Beispiel #1
0
time_t
ar_member_date (const char *name)
{
  char *arname;
  char *memname;
  long int val;

  ar_parse_name (name, &arname, &memname);

  /* Make sure we know the modtime of the archive itself because we are
     likely to be called just before commands to remake a member are run,
     and they will change the archive itself.

     But we must be careful not to enter_file the archive itself if it does
     not exist, because pattern_search assumes that files found in the data
     base exist or can be made.  */
  {
    struct file *arfile;
    arfile = lookup_file (arname);
    if (arfile == 0 && file_exists_p (arname))
      arfile = enter_file (strcache_add (arname));

    if (arfile != 0)
      (void) f_mtime (arfile, 0);
  }

  val = ar_scan (arname, ar_member_date_1, memname);

  free (arname);

  return (val <= 0 ? (time_t) -1 : (time_t) val);
}
Beispiel #2
0
void
install_default_suffix_rules (void)
{
  char **s;

  if (no_builtin_rules_flag)
    return;

  for (s = default_suffix_rules; *s != 0; s += 2)
    {
      struct file *f = enter_file (strcache_add (s[0]));
      /* Don't clobber cmds given in a makefile if there were any.  */
      if (f->cmds == 0)
	{
#ifndef CONFIG_WITH_ALLOC_CACHES
	  f->cmds = xmalloc (sizeof (struct commands));
#else
	  f->cmds = alloccache_alloc (&commands_cache);
#endif
	  f->cmds->fileinfo.filenm = 0;
	  f->cmds->commands = s[1];
	  f->cmds->command_lines = 0;
#ifdef CONFIG_WITH_MEMORY_OPTIMIZATIONS
          f->cmds->refs = 1000;
#endif
	}
    }
}
Beispiel #3
0
FILE*enter_file2(const char*name, const char*filename, void*state)
{
    enter_file(name, filename, state);
    FILE*fi = fopen(filename, "rb");
    if(!fi) {
	as3_error("Couldn't find file %s: %s", filename, strerror(errno));
    }
    return fi;
}
Beispiel #4
0
static void
initialize_ucpp(struct lexer_state *ls, FILE *in) {
	int	i;
	/*
	 * This code is an adaption of ucpp's sample.c
	 */

	/* step 1 */
	init_cpp();

	/* step 2 */
	no_special_macros = 0;
	emit_defines = emit_assertions = 0;

	/* step 3 -- with assertions */
	init_tables(1);

	/* step 4 -- no default include path */
	init_include_path(0);

	/* step 5 -- no need to reset the two emit_* variables set in 2 */
	emit_dependencies = 0;

	/* step 6 -- we work with stdin, this is not a real filename */
	set_init_filename("[stdin]", 0);

	/* step 7 -- we make sure that assertions are on, and pragma are
	   handled */
	init_lexer_state(ls);
	init_lexer_mode(ls);
	ls->flags |= HANDLE_ASSERTIONS | HANDLE_PRAGMA | LINE_NUM;

	/* step 8 -- input is from specified FILE stream */
	ls->input = in;

	/* step 9 -- we do not have any macro to define, but we add any
	  argument as an include path */
/*	for (i = 1; i < argc; i ++) add_incpath(argv[i]);*/
	add_incpath("/usr/local/nwcc/include");  /* XXXXXXXXXXXXXXXX */
	add_incpath("/usr/include");  /* XXXXXXXXXXXXXXXX */
	for (i = 0; cpp_args[i] != NULL; ++i ){
		if (strncmp(cpp_args[i], "-I", 2) == 0) {
			add_incpath(cpp_args[i]+2);
		} else if (strncmp(cpp_args[i], "-D", 2) == 0) {
			define_macro(ls, cpp_args[i]+2);
		} else if (strncmp(cpp_args[i], "-U", 2) == 0) {
			undef_macro(ls, cpp_args[i]+2);
		}
	}

	/* step 10 -- we are a lexer and we want CONTEXT tokens */
	enter_file(ls, ls->flags);
}
Beispiel #5
0
/* Similar to record_files in read.c, only much much simpler. */
static void
incdep_commit_recorded_file (const char *filename, struct dep *deps,
                             const struct floc *flocp)
{
  struct file *f;

  /* Perform some validations. */
  if (filename[0] == '.'
      && (   streq(filename, ".POSIX")
          || streq(filename, ".EXPORT_ALL_VARIABLES")
          || streq(filename, ".INTERMEDIATE")
          || streq(filename, ".LOW_RESOLUTION_TIME")
          || streq(filename, ".NOTPARALLEL")
          || streq(filename, ".ONESHELL")
          || streq(filename, ".PHONY")
          || streq(filename, ".PRECIOUS")
          || streq(filename, ".SECONDARY")
          || streq(filename, ".SECONDTARGETEXPANSION")
          || streq(filename, ".SILENT")
          || streq(filename, ".SHELLFLAGS")
          || streq(filename, ".SUFFIXES")
         )
     )
    {
      error (flocp, _("reserved filename '%s' used in dependency file, ignored"), filename);
      return;
    }

  /* Lookup or create an entry in the database. */
  f = enter_file (filename);
  if (f->double_colon)
    {
      error (flocp, _("dependency file '%s' has a double colon entry already, ignoring"), filename);
      return;
    }
  f->is_target = 1;

  /* Append dependencies. */
  deps = enter_prereqs (deps, NULL);
  if (deps)
    {
      struct dep *last = f->deps;
      if (!last)
        f->deps = deps;
      else
        {
          while (last->next)
            last = last->next;
          last->next = deps;
        }
    }
}
Beispiel #6
0
void
set_default_suffixes (void)
{
  suffix_file = enter_file (".SUFFIXES");

  if (no_builtin_rules_flag)
    (void) define_variable ("SUFFIXES", 8, "", o_default, 0);
  else
    {
      char *p = default_suffixes;
      suffix_file->deps = (struct dep *)
	multi_glob (parse_file_seq (&p, '\0', sizeof (struct dep), 1),
		    sizeof (struct dep));
      (void) define_variable ("SUFFIXES", 8, default_suffixes, o_default, 0);
    }
}
Beispiel #7
0
void
set_default_suffixes (void)
{
  suffix_file = enter_file (strcache_add (".SUFFIXES"));

  if (no_builtin_rules_flag)
    define_variable_cname ("SUFFIXES", "", o_default, 0);
  else
    {
      char *p = default_suffixes;
      suffix_file->deps = enter_prereqs(PARSE_FILE_SEQ (&p, struct dep, '\0',
                                                        NULL, 0),
                                        NULL);
      define_variable_cname ("SUFFIXES", default_suffixes, o_default, 0);
    }
}
Beispiel #8
0
int
ar_touch (const char *name)
{
  char *arname, *memname;
  int val;

  ar_parse_name (name, &arname, &memname);

  /* Make sure we know the modtime of the archive itself before we
     touch the member, since this will change the archive modtime.  */
  {
    struct file *arfile;
    arfile = enter_file (strcache_add (arname));
    f_mtime (arfile, 0);
  }

  val = 1;
  switch (ar_member_touch (arname, memname))
    {
    case -1:
      error (NILF, _("touch: Archive `%s' does not exist"), arname);
      break;
    case -2:
      error (NILF, _("touch: `%s' is not a valid archive"), arname);
      break;
    case -3:
      perror_with_name ("touch: ", arname);
      break;
    case 1:
      error (NILF,
             _("touch: Member `%s' does not exist in `%s'"), memname, arname);
      break;
    case 0:
      val = 0;
      break;
    default:
      error (NILF,
             _("touch: Bad return code from ar_member_touch on `%s'"), name);
    }

  free (arname);

  return val;
}
Beispiel #9
0
void
set_default_suffixes (void)
{
  suffix_file = enter_file (strcache_add (".SUFFIXES"));
  suffix_file->builtin = 1;

  if (no_builtin_rules_flag)
    define_variable_cname ("SUFFIXES", "", o_default, 0);
  else
    {
      struct dep *d;
      const char *p = default_suffixes;
      suffix_file->deps = enter_prereqs (PARSE_SIMPLE_SEQ ((char **)&p, struct dep),
                                         NULL);
      for (d = suffix_file->deps; d; d = d->next)
        d->file->builtin = 1;

      define_variable_cname ("SUFFIXES", default_suffixes, o_default, 0);
    }
}
Beispiel #10
0
void
install_default_suffix_rules (void)
{
  register char **s;

  if (no_builtin_rules_flag)
    return;

 for (s = default_suffix_rules; *s != 0; s += 2)
    {
      register struct file *f = enter_file (s[0]);
      /* Don't clobber cmds given in a makefile if there were any.  */
      if (f->cmds == 0)
	{
	  f->cmds = (struct commands *) xmalloc (sizeof (struct commands));
	  f->cmds->fileinfo.filenm = 0;
	  f->cmds->commands = s[1];
	  f->cmds->command_lines = 0;
	}
    }
}
Beispiel #11
0
void
install_default_suffix_rules (void)
{
  const char **s;

  if (no_builtin_rules_flag)
    return;

  for (s = default_suffix_rules; *s != 0; s += 2)
    {
      struct file *f = enter_file (strcache_add (s[0]));
      /* This function should run before any makefile is parsed.  */
      assert (f->cmds == 0);
      f->cmds = xmalloc (sizeof (struct commands));
      f->cmds->fileinfo.filenm = 0;
      f->cmds->commands = xstrdup (s[1]);
      f->cmds->command_lines = 0;
      f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
      f->builtin = 1;
    }
}
Beispiel #12
0
void
install_default_suffix_rules (void)
{
  char **s;

  if (no_builtin_rules_flag)
    return;

  for (s = default_suffix_rules; *s != 0; s += 2)
    {
      struct file *f = enter_file (strcache_add (s[0]));
      /* Don't clobber cmds given in a makefile if there were any.  */
      if (f->cmds == 0)
        {
          f->cmds = xmalloc (sizeof (struct commands));
          f->cmds->fileinfo.filenm = 0;
          f->cmds->commands = s[1];
          f->cmds->command_lines = 0;
          f->cmds->recipe_prefix = RECIPEPREFIX_DEFAULT;
        }
    }
}
Beispiel #13
0
h_core_bool_t write_entry_to_all_files(h_audit_log_t *log,
    char *formatted_entry)
{
  assert(log);
  assert(formatted_entry);
  h_core_bool_t success;
  FILE *file;

  success = h_core_bool_true;

  pthread_mutex_lock(&log->mutex);
  {
    h_container_set_iterate_start(log->files);
    while ((file = h_container_set_iterate_next(log->files))) {
      if (!enter_file(formatted_entry, file)) {
        h_core_trace("enter_file");
        success = h_core_bool_false;
      }
    }
  }
  pthread_mutex_unlock(&log->mutex);

  return success;
}
Beispiel #14
0
FILE_TIMESTAMP
f_mtime (struct file *file, int search)
{
  FILE_TIMESTAMP mtime;

  /* File's mtime is not known; must get it from the system.  */

#ifndef	NO_ARCHIVES
  if (ar_name (file->name))
    {
      /* This file is an archive-member reference.  */

      char *arname, *memname;
      struct file *arfile;
      time_t member_date;

      /* Find the archive's name.  */
      ar_parse_name (file->name, &arname, &memname);

      /* Find the modification time of the archive itself.
	 Also allow for its name to be changed via VPATH search.  */
      arfile = lookup_file (arname);
      if (arfile == 0)
        arfile = enter_file (strcache_add (arname));
      mtime = f_mtime (arfile, search);
      check_renamed (arfile);
      if (search && strcmp (arfile->hname, arname))
	{
	  /* The archive's name has changed.
	     Change the archive-member reference accordingly.  */

          char *name;
	  unsigned int arlen, memlen;

	  arlen = strlen (arfile->hname);
	  memlen = strlen (memname);

	  name = xmalloc (arlen + 1 + memlen + 2);
	  memcpy (name, arfile->hname, arlen);
	  name[arlen] = '(';
	  memcpy (name + arlen + 1, memname, memlen);
	  name[arlen + 1 + memlen] = ')';
	  name[arlen + 1 + memlen + 1] = '\0';

          /* If the archive was found with GPATH, make the change permanent;
             otherwise defer it until later.  */
          if (arfile->name == arfile->hname)
            rename_file (file, name);
          else
            rehash_file (file, name);
          check_renamed (file);
	}

      free (arname);

      file->low_resolution_time = 1;

      if (mtime == NONEXISTENT_MTIME)
	/* The archive doesn't exist, so its members don't exist either.  */
	return NONEXISTENT_MTIME;

      member_date = ar_member_date (file->hname);
      mtime = (member_date == (time_t) -1
               ? NONEXISTENT_MTIME
               : file_timestamp_cons (file->hname, member_date, 0));
    }
  else
#endif
    {
      mtime = name_mtime (file->name);

      if (mtime == NONEXISTENT_MTIME && search && !file->ignore_vpath)
	{
	  /* If name_mtime failed, search VPATH.  */
	  const char *name = vpath_search (file->name, &mtime, NULL, NULL);
	  if (name
	      /* Last resort, is it a library (-lxxx)?  */
	      || (file->name[0] == '-' && file->name[1] == 'l'
		  && (name = library_search (file->name, &mtime)) != 0))
	    {
	      if (mtime != UNKNOWN_MTIME)
		/* vpath_search and library_search store UNKNOWN_MTIME
		   if they didn't need to do a stat call for their work.  */
		file->last_mtime = mtime;

              /* If we found it in VPATH, see if it's in GPATH too; if so,
                 change the name right now; if not, defer until after the
                 dependencies are updated. */
              if (gpath_search (name, strlen(name) - strlen(file->name) - 1))
                {
                  rename_file (file, name);
                  check_renamed (file);
                  return file_mtime (file);
                }

	      rehash_file (file, name);
	      check_renamed (file);
              /* If the result of a vpath search is -o or -W, preserve it.
                 Otherwise, find the mtime of the resulting file.  */
              if (mtime != OLD_MTIME && mtime != NEW_MTIME)
                mtime = name_mtime (name);
	    }
	}
    }

  /* Files can have bogus timestamps that nothing newly made will be
     "newer" than.  Updating their dependents could just result in loops.
     So notify the user of the anomaly with a warning.

     We only need to do this once, for now. */

  if (!clock_skew_detected
      && mtime != NONEXISTENT_MTIME && mtime != NEW_MTIME
      && !file->updated)
    {
      static FILE_TIMESTAMP adjusted_now;

      FILE_TIMESTAMP adjusted_mtime = mtime;

#if defined(WINDOWS32) || defined(__MSDOS__)
      /* Experimentation has shown that FAT filesystems can set file times
         up to 3 seconds into the future!  Play it safe.  */

#define FAT_ADJ_OFFSET  (FILE_TIMESTAMP) 3

      FILE_TIMESTAMP adjustment = FAT_ADJ_OFFSET << FILE_TIMESTAMP_LO_BITS;
      if (ORDINARY_MTIME_MIN + adjustment <= adjusted_mtime)
        adjusted_mtime -= adjustment;
#elif defined(__EMX__)
      /* FAT filesystems round time to the nearest even second!
         Allow for any file (NTFS or FAT) to perhaps suffer from this
         brain damage.  */
      FILE_TIMESTAMP adjustment = (((FILE_TIMESTAMP_S (adjusted_mtime) & 1) == 0
                     && FILE_TIMESTAMP_NS (adjusted_mtime) == 0)
                    ? (FILE_TIMESTAMP) 1 << FILE_TIMESTAMP_LO_BITS
                    : 0);
#endif

      /* If the file's time appears to be in the future, update our
         concept of the present and try once more.  */
      if (adjusted_now < adjusted_mtime)
        {
          int resolution;
          FILE_TIMESTAMP now = file_timestamp_now (&resolution);
          adjusted_now = now + (resolution - 1);
          if (adjusted_now < adjusted_mtime)
            {
#ifdef NO_FLOAT
              error (NILF, _("Warning: File '%s' has modification time in the future"),
                     file->name);
#else
              double from_now =
                (FILE_TIMESTAMP_S (mtime) - FILE_TIMESTAMP_S (now)
                 + ((FILE_TIMESTAMP_NS (mtime) - FILE_TIMESTAMP_NS (now))
                    / 1e9));
              char from_now_string[100];

              if (from_now >= 99 && from_now <= ULONG_MAX)
                sprintf (from_now_string, "%lu", (unsigned long) from_now);
              else
                sprintf (from_now_string, "%.2g", from_now);
              error (NILF, _("Warning: File '%s' has modification time %s s in the future"),
                     file->name, from_now_string);
#endif
              clock_skew_detected = 1;
            }
        }
    }

  /* Store the mtime into all the entries for this file.  */
  if (file->double_colon)
    file = file->double_colon;

  do
    {
      /* If this file is not implicit but it is intermediate then it was
	 made so by the .INTERMEDIATE target.  If this file has never
	 been built by us but was found now, it existed before make
	 started.  So, turn off the intermediate bit so make doesn't
	 delete it, since it didn't create it.  */
      if (mtime != NONEXISTENT_MTIME && file->command_state == cs_not_started
	  && file->command_state == cs_not_started
	  && !file->tried_implicit && file->intermediate)
	file->intermediate = 0;

      file->last_mtime = mtime;
      file = file->prev;
    }
  while (file != 0);

  return mtime;
}
Beispiel #15
0
void
set_file_variables (struct file *file)
{
    struct dep *d;
    const char *at, *percent, *star, *less;

#ifndef	NO_ARCHIVES
    /* If the target is an archive member `lib(member)',
       then $@ is `lib' and $% is `member'.  */

    if (ar_name (file->name))
    {
        unsigned int len;
        const char *cp;
        char *p;

        cp = strchr (file->name, '(');
        p = alloca (cp - file->name + 1);
        memcpy (p, file->name, cp - file->name);
        p[cp - file->name] = '\0';
        at = p;
        len = strlen (cp + 1);
        p = alloca (len);
        memcpy (p, cp + 1, len - 1);
        p[len - 1] = '\0';
        percent = p;
    }
    else
#endif	/* NO_ARCHIVES.  */
    {
        at = file->name;
        percent = "";
    }

    /* $* is the stem from an implicit or static pattern rule.  */
    if (file->stem == 0)
    {
        /* In Unix make, $* is set to the target name with
        any suffix in the .SUFFIXES list stripped off for
         explicit rules.  We store this in the `stem' member.  */
        const char *name;
        unsigned int len;

#ifndef	NO_ARCHIVES
        if (ar_name (file->name))
        {
            name = strchr (file->name, '(') + 1;
            len = strlen (name) - 1;
        }
        else
#endif
        {
            name = file->name;
            len = strlen (name);
        }

        for (d = enter_file (strcache_add (".SUFFIXES"))->deps; d ; d = d->next)
        {
            unsigned int slen = strlen (dep_name (d));
            if (len > slen && strneq (dep_name (d), name + (len - slen), slen))
            {
                file->stem = strcache_add_len (name, len - slen);
                break;
            }
        }
        if (d == 0)
            file->stem = "";
    }
    star = file->stem;

    /* $< is the first not order-only dependency.  */
    less = "";
    for (d = file->deps; d != 0; d = d->next)
        if (!d->ignore_mtime)
        {
            if (!d->need_2nd_expansion)
                less = dep_name (d);
            break;
        }

    if (file->cmds == default_file->cmds)
        /* This file got its commands from .DEFAULT.
           In this case $< is the same as $@.  */
        less = at;

#define	DEFINE_VARIABLE(name, len, value) \
  (void) define_variable_for_file (name,len,value,o_automatic,0,file)

    /* Define the variables.  */

    DEFINE_VARIABLE ("<", 1, less);
    DEFINE_VARIABLE ("*", 1, star);
    DEFINE_VARIABLE ("@", 1, at);
    DEFINE_VARIABLE ("%", 1, percent);

    /* Compute the values for $^, $+, $?, and $|.  */

    {
        static char *plus_value=0, *bar_value=0, *qmark_value=0;
        static unsigned int plus_max=0, bar_max=0, qmark_max=0;

        unsigned int qmark_len, plus_len, bar_len;
        char *cp;
        char *caret_value;
        char *qp;
        char *bp;
        unsigned int len;

        struct hash_table dep_hash;
        void **slot;

        /* Compute first the value for $+, which is supposed to contain
           duplicate dependencies as they were listed in the makefile.  */

        plus_len = 0;
        bar_len = 0;
        for (d = file->deps; d != 0; d = d->next)
        {
            if (!d->need_2nd_expansion)
            {
                if (d->ignore_mtime)
                    bar_len += strlen (dep_name (d)) + 1;
                else
                    plus_len += strlen (dep_name (d)) + 1;
            }
        }

        if (bar_len == 0)
            bar_len++;

        if (plus_len == 0)
            plus_len++;

        if (plus_len > plus_max)
            plus_value = xrealloc (plus_value, plus_max = plus_len);

        cp = plus_value;

        qmark_len = plus_len + 1;	/* Will be this or less.  */
        for (d = file->deps; d != 0; d = d->next)
            if (! d->ignore_mtime && ! d->need_2nd_expansion)
            {
                const char *c = dep_name (d);

#ifndef	NO_ARCHIVES
                if (ar_name (c))
                {
                    c = strchr (c, '(') + 1;
                    len = strlen (c) - 1;
                }
                else
#endif
                    len = strlen (c);

                memcpy (cp, c, len);
                cp += len;
                *cp++ = FILE_LIST_SEPARATOR;
                if (! (d->changed || always_make_flag))
                    qmark_len -= len + 1;	/* Don't space in $? for this one.  */
            }

        /* Kill the last space and define the variable.  */

        cp[cp > plus_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("+", 1, plus_value);

        /* Compute the values for $^, $?, and $|.  */

        cp = caret_value = plus_value; /* Reuse the buffer; it's big enough.  */

        if (qmark_len > qmark_max)
            qmark_value = xrealloc (qmark_value, qmark_max = qmark_len);
        qp = qmark_value;

        if (bar_len > bar_max)
            bar_value = xrealloc (bar_value, bar_max = bar_len);
        bp = bar_value;

        /* Make sure that no dependencies are repeated in $^, $?, and $|.  It
           would be natural to combine the next two loops but we can't do it
           because of a situation where we have two dep entries, the first
           is order-only and the second is normal (see below).  */

        hash_init (&dep_hash, 500, dep_hash_1, dep_hash_2, dep_hash_cmp);

        for (d = file->deps; d != 0; d = d->next)
        {
            if (d->need_2nd_expansion)
                continue;

            slot = hash_find_slot (&dep_hash, d);
            if (HASH_VACANT (*slot))
                hash_insert_at (&dep_hash, d, slot);
            else
            {
                /* Check if the two prerequisites have different ignore_mtime.
                   If so then we need to "upgrade" one that is order-only.  */

                struct dep* hd = (struct dep*) *slot;

                if (d->ignore_mtime != hd->ignore_mtime)
                    d->ignore_mtime = hd->ignore_mtime = 0;
            }
        }

        for (d = file->deps; d != 0; d = d->next)
        {
            const char *c;

            if (d->need_2nd_expansion || hash_find_item (&dep_hash, d) != d)
                continue;

            c = dep_name (d);
#ifndef	NO_ARCHIVES
            if (ar_name (c))
            {
                c = strchr (c, '(') + 1;
                len = strlen (c) - 1;
            }
            else
#endif
                len = strlen (c);

            if (d->ignore_mtime)
            {
                memcpy (bp, c, len);
                bp += len;
                *bp++ = FILE_LIST_SEPARATOR;
            }
            else
            {
                memcpy (cp, c, len);
                cp += len;
                *cp++ = FILE_LIST_SEPARATOR;
                if (d->changed || always_make_flag)
                {
                    memcpy (qp, c, len);
                    qp += len;
                    *qp++ = FILE_LIST_SEPARATOR;
                }
            }
        }

        hash_free (&dep_hash, 0);

        /* Kill the last spaces and define the variables.  */

        cp[cp > caret_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("^", 1, caret_value);

        qp[qp > qmark_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("?", 1, qmark_value);

        bp[bp > bar_value ? -1 : 0] = '\0';
        DEFINE_VARIABLE ("|", 1, bar_value);
    }

#undef	DEFINE_VARIABLE
}
Beispiel #16
0
int main(int argc, char *argv[])
{
	int i, r;
	struct lexer_state ls;

	/* step 1 */
	init_cpp();

	/* step 2 */
	no_special_macros = 0;
	emit_defines = emit_assertions = 0;

	/* step 3 -- with assertions */
	init_tables(1);

	/* step 4 -- no default include path */
	init_include_path(0);

	/* step 5 -- no need to reset the two emit_* variables set in 2 */
	emit_dependencies = 0;

	/* step 6 -- we work with stdin, this is not a real filename */
	set_init_filename("[stdin]", 0);

	/* step 7 -- we make sure that assertions are on, and pragma are
	   handled */
	init_lexer_state(&ls);
	init_lexer_mode(&ls);
	ls.flags |= HANDLE_ASSERTIONS | HANDLE_PRAGMA | LINE_NUM;

	/* step 8 -- input is from stdin */
	ls.input = stdin;

	/* step 9 -- we do not have any macro to define, but we add any
	   argument as an include path */
	for (i = 1; i < argc; i ++) add_incpath(argv[i]);

	/* step 10 -- we are a lexer and we want CONTEXT tokens */
	enter_file(&ls, ls.flags);

	/* read tokens until end-of-input is reached -- errors (non-zero
	   return values different from CPPERR_EOF) are ignored */
	while ((r = lex(&ls)) < CPPERR_EOF) {
		if (r) {
			/* error condition -- no token was retrieved */
			continue;
		}
		/* we print each token: its numerical value, and its
		   string content; if this is a PRAGMA token, the
		   string content is in fact a compressed token list,
		   that we uncompress and print. */
		if (ls.ctok->type == PRAGMA) {
			unsigned char *c = (unsigned char *)(ls.ctok->name);

			printf("line %ld: <#pragma>\n", ls.line);
			for (; *c; c ++) {
				int t = *c;

				if (STRING_TOKEN(t)) {
					printf("  <%2d>  ", t);
					for (c ++; *c != PRAGMA_TOKEN_END;
						c ++) putchar(*c);
					putchar('\n');
				} else {
					printf("  <%2d>  `%s'\n", t,
						operators_name[t]);
				}
			}
		} else if (ls.ctok->type == CONTEXT) {
			printf("new context: file '%s', line %ld\n",
				ls.ctok->name, ls.ctok->line);
		} else if (ls.ctok->type == NEWLINE) {
			printf("[newline]\n");
		} else {
			printf("line %ld: <%2d>  `%s'\n", ls.ctok->line,
				ls.ctok->type,
				STRING_TOKEN(ls.ctok->type) ? ls.ctok->name
				: operators_name[ls.ctok->type]);
		}
	}
	return 0;
}