Exemple #1
0
static bool
run_wgetrc (const char *file)
{
  FILE *fp;
  char *line;
  int ln;
  int errcnt = 0;

  fp = fopen (file, "rb");
  if (!fp)
    {
      fprintf (stderr, _("%s: Cannot read %s (%s).\n"), exec_name,
               file, strerror (errno));
      return true;                      /* not a fatal error */
    }
  enable_tilde_expansion = true;
  ln = 1;
  while ((line = read_whole_line (fp)) != NULL)
    {
      char *com = NULL, *val = NULL;
      int comind;

      /* Parse the line.  */
      switch (parse_line (line, &com, &val, &comind))
        {
        case line_ok:
          /* If everything is OK, set the value.  */
          if (!setval_internal (comind, com, val))
            {
              fprintf (stderr, _("%s: Error in %s at line %d.\n"),
                       exec_name, file, ln);
              ++errcnt;
            }
          break;
        case line_syntax_error:
          fprintf (stderr, _("%s: Syntax error in %s at line %d.\n"),
                   exec_name, file, ln);
          ++errcnt;
          break;
        case line_unknown_command:
          fprintf (stderr, _("%s: Unknown command `%s' in %s at line %d.\n"),
                   exec_name, com, file, ln);
          ++errcnt;
          break;
        case line_empty:
          break;
        default:
          abort ();
        }
      xfree_null (com);
      xfree_null (val);
      xfree (line);
      ++ln;
    }
  enable_tilde_expansion = false;
  fclose (fp);

  return errcnt == 0;
}
Exemple #2
0
/* Convert the Un*x-ish style directory listing stored in FILE to a
   linked list of fileinfo (system-independent) entries.  The contents
   of FILE are considered to be produced by the standard Unix `ls -la'
   output (whatever that might be).  BSD (no group) and SYSV (with
   group) listings are handled.

   The time stamps are stored in a separate variable, time_t
   compatible (I hope).  The timezones are ignored.  */
static struct fileinfo *
ftp_parse_unix_ls (const char *file, int ignore_perms)
{
  FILE *fp;
  static const char *months[] = {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  };
  int next, len, i, error, ignore;
  int year, month, day;         /* for time analysis */
  int hour, min, sec;
  struct tm timestruct, *tnow;
  time_t timenow;

  char *line, *tok, *ptok;      /* tokenizer */
  struct fileinfo *dir, *l, cur; /* list creation */

  fp = fopen (file, "rb");
  if (!fp)
    {
      logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
      return NULL;
    }
  dir = l = NULL;

  /* Line loop to end of file: */
  while ((line = read_whole_line (fp)) != NULL)
    {
      len = clean_line (line);
      /* Skip if total...  */
      if (!strncasecmp (line, "total", 5))
        {
          xfree (line);
          continue;
        }
      /* Get the first token (permissions).  */
      tok = strtok (line, " ");
      if (!tok)
        {
          xfree (line);
          continue;
        }

      cur.name = NULL;
      cur.linkto = NULL;

      /* Decide whether we deal with a file or a directory.  */
      switch (*tok)
        {
        case '-':
          cur.type = FT_PLAINFILE;
          DEBUGP (("PLAINFILE; "));
          break;
        case 'd':
          cur.type = FT_DIRECTORY;
          DEBUGP (("DIRECTORY; "));
          break;
        case 'l':
          cur.type = FT_SYMLINK;
          DEBUGP (("SYMLINK; "));
          break;
        default:
          cur.type = FT_UNKNOWN;
          DEBUGP (("UNKNOWN; "));
          break;
        }

      if (ignore_perms)
        {
          switch (cur.type)
            {
            case FT_PLAINFILE:
              cur.perms = 0644;
              break;
            case FT_DIRECTORY:
              cur.perms = 0755;
              break;
            default:
              /*cur.perms = 1023;*/     /* #### What is this?  --hniksic */
              cur.perms = 0644;
            }
          DEBUGP (("implicit perms %0o; ", cur.perms));
        }
       else
         {
           cur.perms = symperms (tok + 1);
           DEBUGP (("perms %0o; ", cur.perms));
         }

      error = ignore = 0;       /* Erroneous and ignoring entries are
                                   treated equally for now.  */
      year = hour = min = sec = 0; /* Silence the compiler.  */
      month = day = 0;
      next = -1;
      /* While there are tokens on the line, parse them.  Next is the
         number of tokens left until the filename.

         Use the month-name token as the "anchor" (the place where the
         position wrt the file name is "known").  When a month name is
         encountered, `next' is set to 5.  Also, the preceding
         characters are parsed to get the file size.

         This tactic is quite dubious when it comes to
         internationalization issues (non-English month names), but it
         works for now.  */
      tok = line;
      while (ptok = tok,
             (tok = strtok (NULL, " ")) != NULL)
        {
          --next;
          if (next < 0)         /* a month name was not encountered */
            {
              for (i = 0; i < 12; i++)
                if (!strcmp (tok, months[i]))
                  break;
              /* If we got a month, it means the token before it is the
                 size, and the filename is three tokens away.  */
              if (i != 12)
                {
                  wgint size;

                  /* Parse the previous token with str_to_wgint.  */
                  if (ptok == line)
                    {
                      /* Something has gone wrong during parsing. */
                      error = 1;
                      break;
                    }
                  errno = 0;
                  size = str_to_wgint (ptok, NULL, 10);
                  if (size == WGINT_MAX && errno == ERANGE)
                    /* Out of range -- ignore the size.  #### Should
                       we refuse to start the download.  */
                    cur.size = 0;
                  else
                    cur.size = size;
                  DEBUGP (("size: %s; ", number_to_static_string(cur.size)));

                  month = i;
                  next = 5;
                  DEBUGP (("month: %s; ", months[month]));
                }
            }
          else if (next == 4)   /* days */
            {
              if (tok[1])       /* two-digit... */
                day = 10 * (*tok - '0') + tok[1] - '0';
              else              /* ...or one-digit */
                day = *tok - '0';
              DEBUGP (("day: %d; ", day));
            }
          else if (next == 3)
            {
              /* This ought to be either the time, or the year.  Let's
                 be flexible!

                 If we have a number x, it's a year.  If we have x:y,
                 it's hours and minutes.  If we have x:y:z, z are
                 seconds.  */
              year = 0;
              min = hour = sec = 0;
              /* We must deal with digits.  */
              if (c_isdigit (*tok))
                {
                  /* Suppose it's year.  */
                  for (; c_isdigit (*tok); tok++)
                    year = (*tok - '0') + 10 * year;
                  if (*tok == ':')
                    {
                      /* This means these were hours!  */
                      hour = year;
                      year = 0;
                      ++tok;
                      /* Get the minutes...  */
                      for (; c_isdigit (*tok); tok++)
                        min = (*tok - '0') + 10 * min;
                      if (*tok == ':')
                        {
                          /* ...and the seconds.  */
                          ++tok;
                          for (; c_isdigit (*tok); tok++)
                            sec = (*tok - '0') + 10 * sec;
                        }
                    }
                }
              if (year)
                DEBUGP (("year: %d (no tm); ", year));
              else
                DEBUGP (("time: %02d:%02d:%02d (no yr); ", hour, min, sec));
            }
          else if (next == 2)    /* The file name */
            {
              int fnlen;
              char *p;

              /* Since the file name may contain a SPC, it is possible
                 for strtok to handle it wrong.  */
              fnlen = strlen (tok);
              if (fnlen < len - (tok - line))
                {
                  /* So we have a SPC in the file name.  Restore the
                     original.  */
                  tok[fnlen] = ' ';
                  /* If the file is a symbolic link, it should have a
                     ` -> ' somewhere.  */
                  if (cur.type == FT_SYMLINK)
                    {
                      p = strstr (tok, " -> ");
                      if (!p)
                        {
                          error = 1;
                          break;
                        }
                      cur.linkto = xstrdup (p + 4);
                      DEBUGP (("link to: %s\n", cur.linkto));
                      /* And separate it from the file name.  */
                      *p = '\0';
                    }
                }
              /* If we have the filename, add it to the list of files or
                 directories.  */
              /* "." and ".." are an exception!  */
              if (!strcmp (tok, ".") || !strcmp (tok, ".."))
                {
                  DEBUGP (("\nIgnoring `.' and `..'; "));
                  ignore = 1;
                  break;
                }
              /* Some FTP sites choose to have ls -F as their default
                 LIST output, which marks the symlinks with a trailing
                 `@', directory names with a trailing `/' and
                 executables with a trailing `*'.  This is no problem
                 unless encountering a symbolic link ending with `@',
                 or an executable ending with `*' on a server without
                 default -F output.  I believe these cases are very
                 rare.  */
              fnlen = strlen (tok); /* re-calculate `fnlen' */
              cur.name = xmalloc (fnlen + 1);
              memcpy (cur.name, tok, fnlen + 1);
              if (fnlen)
                {
                  if (cur.type == FT_DIRECTORY && cur.name[fnlen - 1] == '/')
                    {
                      cur.name[fnlen - 1] = '\0';
                      DEBUGP (("trailing `/' on dir.\n"));
                    }
                  else if (cur.type == FT_SYMLINK && cur.name[fnlen - 1] == '@')
                    {
                      cur.name[fnlen - 1] = '\0';
                      DEBUGP (("trailing `@' on link.\n"));
                    }
                  else if (cur.type == FT_PLAINFILE
                           && (cur.perms & 0111)
                           && cur.name[fnlen - 1] == '*')
                    {
                      cur.name[fnlen - 1] = '\0';
                      DEBUGP (("trailing `*' on exec.\n"));
                    }
                } /* if (fnlen) */
              else
                error = 1;
              break;
            }
          else
            abort ();
        } /* while */

      if (!cur.name || (cur.type == FT_SYMLINK && !cur.linkto))
        error = 1;

      DEBUGP (("%s\n", cur.name ? cur.name : ""));

      if (error || ignore)
        {
          DEBUGP (("Skipping.\n"));
          xfree_null (cur.name);
          xfree_null (cur.linkto);
          xfree (line);
          continue;
        }

      if (!dir)
        {
          l = dir = xnew (struct fileinfo);
          memcpy (l, &cur, sizeof (cur));
          l->prev = l->next = NULL;
        }
      else
        {
Exemple #3
0
/* Convert the Un*x-ish style directory listing stored in FILE to a
   linked list of fileinfo (system-independent) entries.  The contents
   of FILE are considered to be produced by the standard Unix `ls -la'
   output (whatever that might be).  BSD (no group) and SYSV (with
   group) listings are handled.

   The time stamps are stored in a separate variable, time_t
   compatible (I hope).  The timezones are ignored.  */
static struct fileinfo *
ftp_parse_unix_ls (const char *file)
{
  FILE *fp;
  static const char *months[] = {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  };
  int next, len, i, error, ignore;
  int year, month, day;		/* for time analysis */
  int hour, min, sec;
  struct tm timestruct, *tnow;
  time_t timenow;

  char *line, *tok;		/* tokenizer */
  struct fileinfo *dir, *l, cur; /* list creation */

  fp = fopen (file, "rb");
  if (!fp)
    {
      logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno));
      return NULL;
    }
  dir = l = NULL;

  /* Line loop to end of file: */
  while ((line = read_whole_line (fp)))
    {
      DEBUGP (("%s\n", line));
      len = strlen (line);
      /* Destroy <CR> if there is one.  */
      if (len && line[len - 1] == '\r')
	line[--len] = '\0';

      /* Skip if total...  */
      if (!strncasecmp (line, "total", 5))
	{
	  free (line);
	  continue;
	}
      /* Get the first token (permissions).  */
      tok = strtok (line, " ");
      if (!tok)
	{
	  free (line);
	  continue;
	}

      cur.name = NULL;
      cur.linkto = NULL;

      /* Decide whether we deal with a file or a directory.  */
      switch (*tok)
	{
	case '-':
	  cur.type = FT_PLAINFILE;
	  DEBUGP (("PLAINFILE; "));
	  break;
	case 'd':
	  cur.type = FT_DIRECTORY;
	  DEBUGP (("DIRECTORY; "));
	  break;
	case 'l':
	  cur.type = FT_SYMLINK;
	  DEBUGP (("SYMLINK; "));
	  break;
	default:
	  cur.type = FT_UNKNOWN;
	  DEBUGP (("UNKOWN; "));
	  break;
	}

      cur.perms = symperms (tok + 1);
      DEBUGP (("perms %0o; ", cur.perms));

      error = ignore = 0;       /* Errnoeous and ignoring entries are
				   treated equally for now.  */
      year = hour = min = sec = 0; /* Silence the compiler.  */
      month = day = 0;
      next = -1;
      /* While there are tokens on the line, parse them.  Next is the
	 number of tokens left until the filename.

	 Use the month-name token as the "anchor" (the place where the
	 position wrt the file name is "known").  When a month name is
	 encountered, `next' is set to 5.  Also, the preceding
	 characters are parsed to get the file size.

	 This tactic is quite dubious when it comes to
	 internationalization issues (non-English month names), but it
	 works for now.  */
      while ((tok = strtok (NULL, " ")))
	{
	  --next;
	  if (next < 0)		/* a month name was not encountered */
	    {
	      for (i = 0; i < 12; i++)
		if (!strcmp (tok, months[i]))
		  break;
	      /* If we got a month, it means the token before it is the
		 size, and the filename is three tokens away.  */
	      if (i != 12)
		{
		  char *t = tok - 2;
		  long mul = 1;

		  for (cur.size = 0; t > line && ISDIGIT (*t); mul *= 10, t--)
		    cur.size += mul * (*t - '0');
		  if (t == line)
		    {
		      /* Something is seriously wrong.  */
		      error = 1;
		      break;
		    }
		  month = i;
		  next = 5;
		  DEBUGP (("month: %s; ", months[month]));
		}
	    }
	  else if (next == 4)	/* days */
	    {
	      if (tok[1])	/* two-digit... */
		day = 10 * (*tok - '0') + tok[1] - '0';
	      else		/* ...or one-digit */
		day = *tok - '0';
	      DEBUGP (("day: %d; ", day));
	    }
	  else if (next == 3)
	    {
	      /* This ought to be either the time, or the year.  Let's
		 be flexible!

		 If we have a number x, it's a year.  If we have x:y,
		 it's hours and minutes.  If we have x:y:z, z are
		 seconds.  */
	      year = 0;
	      min = hour = sec = 0;
	      /* We must deal with digits.  */
	      if (ISDIGIT (*tok))
		{
		  /* Suppose it's year.  */
		  for (; ISDIGIT (*tok); tok++)
		    year = (*tok - '0') + 10 * year;
		  if (*tok == ':')
		    {
		      /* This means these were hours!  */
		      hour = year;
		      year = 0;
		      ++tok;
		      /* Get the minutes...  */
		      for (; ISDIGIT (*tok); tok++)
			min = (*tok - '0') + 10 * min;
		      if (*tok == ':')
			{
			  /* ...and the seconds.  */
			  ++tok;
			  for (; ISDIGIT (*tok); tok++)
			    sec = (*tok - '0') + 10 * sec;
			}
		    }
		}
	      if (year)
		DEBUGP (("year: %d (no tm); ", year));
	      else
		DEBUGP (("time: %02d:%02d:%02d (no yr); ", hour, min, sec));
	    }
	  else if (next == 2)    /* The file name */
	    {
	      int fnlen;
	      char *p;

	      /* Since the file name may contain a SPC, it is possible
		 for strtok to handle it wrong.  */
	      fnlen = strlen (tok);
	      if (fnlen < len - (tok - line))
		{
		  /* So we have a SPC in the file name.  Restore the
		     original.  */
		  tok[fnlen] = ' ';
		  /* If the file is a symbolic link, it should have a
		     ` -> ' somewhere.  */
		  if (cur.type == FT_SYMLINK)
		    {
		      p = strstr (tok, " -> ");
		      if (!p)
			{
			  error = 1;
			  break;
			}
		      cur.linkto = xstrdup (p + 4);
		      DEBUGP (("link to: %s\n", cur.linkto));
		      /* And separate it from the file name.  */
		      *p = '\0';
		    }
		}
	      /* If we have the filename, add it to the list of files or
		 directories.  */
	      /* "." and ".." are an exception!  */
	      if (!strcmp (tok, ".") || !strcmp (tok, ".."))
		{
		  DEBUGP (("\nIgnoring `.' and `..'; "));
		  ignore = 1;
		  break;
		}
	      /* Some FTP sites choose to have ls -F as their default
		 LIST output, which marks the symlinks with a trailing
		 `@', directory names with a trailing `/' and
		 executables with a trailing `*'.  This is no problem
		 unless encountering a symbolic link ending with `@',
		 or an executable ending with `*' on a server without
		 default -F output.  I believe these cases are very
		 rare.  */
	      fnlen = strlen (tok); /* re-calculate `fnlen' */
	      cur.name = (char *)xmalloc (fnlen + 1);
	      memcpy (cur.name, tok, fnlen + 1);
	      if (fnlen)
		{
		  if (cur.type == FT_DIRECTORY && cur.name[fnlen - 1] == '/')
		    {
		      cur.name[fnlen - 1] = '\0';
		      DEBUGP (("trailing `/' on dir.\n"));
		    }
		  else if (cur.type == FT_SYMLINK && cur.name[fnlen - 1] == '@')
		    {
		      cur.name[fnlen - 1] = '\0';
		      DEBUGP (("trailing `@' on link.\n"));
		    }
		  else if (cur.type == FT_PLAINFILE
			   && (cur.perms & 0111)
			   && cur.name[fnlen - 1] == '*')
		    {
		      cur.name[fnlen - 1] = '\0';
		      DEBUGP (("trailing `*' on exec.\n"));
		    }
		} /* if (fnlen) */
	      else
		error = 1;
	      break;
	    }
	  else
	    abort ();
	} /* while */

      if (!cur.name || (cur.type == FT_SYMLINK && !cur.linkto))
	error = 1;

      DEBUGP (("\n"));

      if (error || ignore)
	{
	  DEBUGP (("Skipping.\n"));
	  FREE_MAYBE (cur.name);
	  FREE_MAYBE (cur.linkto);
	  free (line);
	  continue;
	}

      if (!dir)
	{
	  l = dir = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
	  memcpy (l, &cur, sizeof (cur));
	  l->prev = l->next = NULL;
	}
      else
	{
	  cur.prev = l;
	  l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo));
	  l = l->next;
	  memcpy (l, &cur, sizeof (cur));
	  l->next = NULL;
	}
      /* Get the current time.  */
      timenow = time (NULL);
      tnow = localtime (&timenow);
      /* Build the time-stamp (the idea by [email protected]).  */
      timestruct.tm_sec   = sec;
      timestruct.tm_min   = min;
      timestruct.tm_hour  = hour;
      timestruct.tm_mday  = day;
      timestruct.tm_mon   = month;
      if (year == 0)
	{
	  /* Some listings will not specify the year if it is "obvious"
	     that the file was from the previous year.  E.g. if today
	     is 97-01-12, and you see a file of Dec 15th, its year is
	     1996, not 1997.  Thanks to Vladimir Volovich for
	     mentioning this!  */
	  if (month > tnow->tm_mon)
	    timestruct.tm_year = tnow->tm_year - 1;
	  else
	    timestruct.tm_year = tnow->tm_year;
	}
      else
	timestruct.tm_year = year;
      if (timestruct.tm_year >= 1900)
	timestruct.tm_year -= 1900;
      timestruct.tm_wday  = 0;
      timestruct.tm_yday  = 0;
      timestruct.tm_isdst = -1;
      l->tstamp = mktime (&timestruct); /* store the time-stamp */

      free (line);
    }

  fclose (fp);
  return dir;
}
Exemple #4
0
void
load_cookies (const char *file)
{
  char *line;
  FILE *fp = fopen (file, "r");
  if (!fp)
    {
      logprintf (LOG_NOTQUIET, "Cannot open cookies file `%s': %s\n",
		 file, strerror (errno));
      return;
    }
  cookies_now = time (NULL);

  for (; ((line = read_whole_line (fp)) != NULL); xfree (line))
    {
      struct cookie *cookie;
      char *p = line;

      int port;

      char *domain_b  = NULL, *domain_e  = NULL;
      char *ignore_b  = NULL, *ignore_e  = NULL;
      char *path_b    = NULL, *path_e    = NULL;
      char *secure_b  = NULL, *secure_e  = NULL;
      char *expires_b = NULL, *expires_e = NULL;
      char *name_b    = NULL, *name_e    = NULL;
      char *value_b   = NULL, *value_e   = NULL;

      SKIP_WS (p);

      if (!*p || *p == '#')
	/* empty line */
	continue;

      SET_WORD_BOUNDARIES (p, domain_b,  domain_e);
      SET_WORD_BOUNDARIES (p, ignore_b,  ignore_e);
      SET_WORD_BOUNDARIES (p, path_b,    path_e);
      SET_WORD_BOUNDARIES (p, secure_b,  secure_e);
      SET_WORD_BOUNDARIES (p, expires_b, expires_e);
      SET_WORD_BOUNDARIES (p, name_b,    name_e);

      /* Don't use SET_WORD_BOUNDARIES for value because it may
	 contain whitespace.  Instead, set value_e to the end of line,
	 modulo trailing space (this will skip the line separator.) */
      SKIP_WS (p);
      value_b = p;
      value_e = p + strlen (p);
      while (value_e > value_b && ISSPACE (*(value_e - 1)))
	--value_e;
      if (value_b == value_e)
	/* Hmm, should we check for empty value?  I guess that's
	   legal, so I leave it.  */
	;

      cookie = cookie_new ();

      cookie->attr    = strdupdelim (name_b, name_e);
      cookie->value   = strdupdelim (value_b, value_e);
      cookie->path    = strdupdelim (path_b, path_e);

      if (BOUNDED_EQUAL (secure_b, secure_e, "TRUE"))
	cookie->secure = 1;

      /* DOMAIN needs special treatment because we might need to
	 extract the port.  */
      port = domain_port (domain_b, domain_e, (const char **)&domain_e);
      if (port)
	cookie->port = port;
      else
	cookie->port = cookie->secure ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT;

      cookie->domain  = strdupdelim (domain_b, domain_e);

      /* safe default in case EXPIRES field is garbled. */
      cookie->expiry_time = cookies_now - 1;

      /* I don't like changing the line, but it's completely safe.
	 (line is malloced.)  */
      *expires_e = '\0';
      sscanf (expires_b, "%lu", &cookie->expiry_time);
      if (cookie->expiry_time < cookies_now)
	/* ignore stale cookie. */
	goto abort;
      cookie->permanent = 1;

      store_cookie (cookie);

    next:
      continue;

    abort:
      delete_cookie (cookie);
    }
  fclose (fp);
}
Exemple #5
0
void fortran_split_lines(FILE* input, FILE* output, int width)
{
    ERROR_CONDITION(width <= 0, "Invalid width = %d\n", width);

	int length;
	char* line;

	while ((line = read_whole_line(input)) != NULL)
	{
		// We must remove trailing spaces before "\n" (if any)
		// since we cannot continuate to an empty line
		trim_right_line(line);

		// Comments that will reach here are those created within the compiler 
		// (e.g. TPL) because scanner always trims them
        char prefix[33] = { 0 };
        char is_construct = check_for_construct(line, prefix, 32);
		char is_comment = check_for_comment(line);

		length = strlen(line);
		// Many times we will fall here by means of length <= width
		if ((length <= width))
		{
			fputs(line, output);
		}
        else if (is_construct)
        {
            // Do not complicate ourselves, rely on a double continuation
            int column = 1;
            double_continuate_construct(output, prefix, line, width, &column);
            fprintf(output, "\n");
        }
        else if (is_comment)
        {
			fputs(line, output);
        }
		else
		{
			int column, next_column;
			char* position;
			char* next_position;

            mf03_prepare_string_for_scanning(line);

			// Initialize stuff
			column = 1;
			position = line;

			// Scan
			int token = mf03lex();
			while (token != EOS)
			{
				// Find the token as there can be spaces
				// next_position has the first character of the token
				next_position = strstr(position, mf03lval.token_atrib.token_text);

				if (next_position == NULL)
				{
					fatal_error("Serious problem when splitting line. '%s' not found:\n\n %s", mf03lval.token_atrib.token_text, position);
				}

				// Next column has the column where the token will start
				next_column = column + (next_position - position);


				// Check if we have reached the last column or if spaces plus
				// token will not fit in this line
				if (column == width
						|| (next_column + (int)strlen(mf03lval.token_atrib.token_text) >= width))
				{
					DEBUG_CODE() DEBUG_MESSAGE("Cutting at '%s'", mf03lval.token_atrib.token_text);
					// Nothing fits here already
                    fprintf(output, "&\n");
                    column = 1;
				}

				// Write the blanks
				char* c;
				for (c = position; c < next_position; c++)
				{
					DEBUG_CODE() DEBUG_MESSAGE("%d - Blank - '%c'", column, *c);
					fprintf(output, "%c", *c);
					column++;
				}

				if ((column + (int)strlen(mf03lval.token_atrib.token_text)) >= width)
				{
					// We are very unlucky, the whole token still does not fit
					// in this line !
					double_continuate(output, mf03lval.token_atrib.token_text, width, &column);
				}
				else
				{
					// Write the token
					DEBUG_CODE() DEBUG_MESSAGE("%d - Token '%s'", column, mf03lval.token_atrib.token_text);
					fprintf(output, "%s", mf03lval.token_atrib.token_text);
					column += strlen(mf03lval.token_atrib.token_text);
				}

				// Update state to be coherent before entering the next iteration
				// column has been updated before
				position = next_position + strlen(mf03lval.token_atrib.token_text);
				token = mf03lex();
			}

			// The EOS
			fprintf(output, "\n");
		}
		
		DELETE(line);
	}
}