This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: gengtype improvements for plugins. What is missing???



See http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02058.html &
http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02060.html &
http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02063.html &
http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02065.html & 
http://gcc.gnu.org/ml/gcc-patches/2010-08/msg02068.html
for the previous pieces of the patch.

In my understanding, the files generated by gengtype patched as above do
not change from current trunk's behavior. Even better, the same files
are generated with the current trunk (r.163612-), with the current trunk
plus only the first patch piece applied, with the current trunk plus the
two first patch pieces applied, etc.



Ian Taylor, Diego Novillo, Paolo Bonzini and others, is that slicing in
several pieces enough for you? I hope yes!

We (Jeremie Salvucci & me Basile) strongly believe that the just
referenced patch pieces can be reviewed & should go into the trunk
before end of stage 1 of 4.6 i.e. current trunk.

____________



This current message is *NOT* a formal patch submission (in contrast to
the previous 5 messages whose URL are given before.). So there is no
ChangeLog & formal *.diff file

The future (& hopefully last) patch of the file will indeed provide
routine write_state & read_state (and all the many routines they need).
We have a prototype, as file gengtype-state.c, attached for convenience.

The idea is to have this state written in a textual file by running
   gengtype -S $(srcdir) -I gtyp-input.list -w gtype.state
The above command would indeed parse all the files currently parsed, but
does not generate any files. They should be generated by reading the
state file with
  gengtype -r gtype.state
but we still have a bug (all C files are generated as before, but there
is an issue with C++ frontend related file).

In plugin mode, one would run
  gengtype -r gtype.state -P gt-plugin.h plugin1.c plugin2.c


The idea is that gengtype (with a main function suitably patched) would
be able to persist its state (i.e. to serialize it when writing, and
de-serialize when reading).

However, there still is a bug in that gengtype-state.c file. For C
language, the state file is correct & behave well. We still have a small
issue for other languages. I will investigate that tomorrow.

I have several questions.

I am not able to break the gengtype-state.c into independent & testable
pieces. Is it acceptable to send an entire new file in a patch? I don't
see how to avoid that.

What should be the ChangeLog entry for an entire new file. Is just a
simple line 
   * gengtype-state.c: Added file.
enough or should I detail every added function/variable inside?


Who are the best (notably the less stressed) reviewers able to comment
and Ok our patches?

Regards.



-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***
/* Gengtype persistent state serialization & de-serialization.
   Useful for gengtype in plugin mode.

   Copyright (C) 2010  Free Software Foundation, Inc.

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify it under
   the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3, or (at your option) any later
   version.

   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.  

   Contributed by Jeremie Salvucci <jeremie.salvucci@free.fr>
   and Basile Starynkevitch <basile@starynkevitch.net>
*/

#include "bconfig.h"
#include "system.h"
#include "getopt.h"
#include "errors.h"             /* for fatal */
#include "double-int.h"
#include "hashtab.h"
#include "version.h"            /* for version_string & pkgversion_string */
#include "obstack.h"
#include "xregex.h"
#include "gengtype.h"


enum state_token_en
{
  STOK_NONE,
  STOK_INTEGER,
  STOK_STRING,
  STOK_LEFTPAR,
  STOK_RIGHTPAR,
  STOK_NAME,
  STOK_EOF,
  STOK__LAST
};


/* the state file has simplistic lispy lexical tokens. */

struct state_ident_st
{
  void *stid_data;
  char stid_name[1];            /* actually bigger & null terminated */
};

static htab_t state_ident_tab;

struct state_token_st
{
  enum state_token_en stok_kind;        /* the lexical kind
                                           discriminates the stok_un
                                           union  */
  int stok_line;                /* the line number */
  int stok_col;                /* the column number */
  const char *stok_file;        /* the file path */
  struct state_token_st *stok_next;     /* the next token, when peeked */
  union
  {
    int stok_int;               /* when STOK_INTEGER */
    char stok_string[1];        /* when STOK_STRING, actual size is
				   bigger and null terminated */
    struct state_ident_st *stok_ident;  /* when STOK_IDENT */
    void *stok_ptr;             /* null otherwise */
  }
  stok_un;
};



char *read_state_filename = NULL;
char *write_state_filename = NULL;

struct state_token_st *state_token = NULL;
static FILE *state_file;
static const char *state_path = NULL;
static int state_line = 0;
static long state_bol = 0;	/* offset of beginning of line */

#define NULL_TOKEN (struct state_token_st*)0
/* Fatal message while reading state.  */
#define fatal_reading_state(Tok,Msg)  do {		\
    struct state_token_st* badtok = Tok;		\
    if (badtok)						\
      fatal("%s:%d:%d: Invalid state file; " Msg,	\
	    badtok->stok_file,				\
	    badtok->stok_line,				\
	    badtok->stok_col);				\
    else						\
      fatal("%s:%d: Invalid state file; " Msg,		\
	    state_path, state_line);			\
  } while(0)

#define fatal_reading_state_printf(Tok,Fmt,...) do {	\
    struct state_token_st* badtok = Tok;		\
    if (badtok)						\
      fatal("%s:%d:%d: Invalid state file; " Fmt,	\
	    badtok->stok_file,				\
	    badtok->stok_line,				\
	    badtok->stok_col, __VA_ARGS__);		\
    else						\
      fatal("%s:%d: Invalid state file; " Fmt,		\
	    state_path, state_line, __VA_ARGS__);	\
  } while(0)

static struct state_ident_st *
state_ident_by_name (const char *name, enum insert_option optins)
{
  PTR *slot = NULL;
  int namlen = 0;
  struct state_ident_st *stid = NULL;

  if (!name || !name[0])
    return NULL;

  slot = htab_find_slot (state_ident_tab, name, optins);
  if (!slot)
    return NULL;

  namlen = strlen (name);
  stid =
    (struct state_ident_st *) xmalloc (sizeof (struct state_ident_st) +
                                       namlen);
  memset (stid, 0, sizeof (struct state_ident_st) + namlen);
  strcpy (stid->stid_name, name);
  *slot = stid;

  return stid;
}

/* Our token lexer is heavily inspired by MELT's lexer! */
static struct state_token_st *
read_a_state_token (void)
{
  int c = 0;
  long curoff = 0;
  struct state_token_st *tk = NULL;
again:
  c = getc (state_file);

  if (c < 0)
    return NULL;
  if (c == '\n')
    {
      state_line++;
      state_bol = curoff = ftell (state_file);
      goto again;
    };
  if (ISSPACE (c))
    goto again;
  if (c == ';')
    {                           /* comment */
      do
        {
          c = getc (state_file);
        }
      while (c > 0 && c != '\n');
      if (c == '\n') {
        state_line++;
	state_bol = curoff = ftell (state_file);
      }
      goto again;
    };
  if (ISDIGIT (c) || c == '-' || c == '+')
    {                           /* number */
      int n = 0;
      ungetc (c, state_file);
      curoff = ftell (state_file);
      if (fscanf (state_file, "%d", &n) <= 0)
        fatal_reading_state (NULL_TOKEN, "Lexical error in number");
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_INTEGER;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      tk->stok_un.stok_int = n;

      return tk;
    }
  else if (c == '(')
    {
      curoff = ftell (state_file);
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_LEFTPAR;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_next = NULL;

      return tk;
    }
  else if (c == ')')
    {
      curoff = ftell (state_file);
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_RIGHTPAR;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_next = NULL;

      return tk;
    }
  else if (ISALPHA (c) || c == '_' || c == '$' || c == '!' || c == '#')
    {                           /* identifier */
      struct obstack id_obstack;
      struct state_ident_st *sid = NULL;
      char* ids = NULL;
      obstack_init (&id_obstack);
      curoff = ftell (state_file);
      while (ISALNUM (c) || c == '_' || c == '$' || c == '!' || c == '#')
        {
	  obstack_1grow (&id_obstack, c);
          c = getc (state_file);
          if (c < 0)
            break;
        };
      if (c >= 0)
        ungetc (c, state_file);
      obstack_1grow (&id_obstack, (char) 0);
      ids = XOBFINISH (&id_obstack, char *);
      sid = state_ident_by_name (ids, INSERT);
      obstack_free (&id_obstack, ids);
      ids = NULL;
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_NAME;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      tk->stok_un.stok_ident = sid;

      return tk;
    }
  else if (c == '"')
    {
      char *cstr = NULL;
      int cslen = 0;
      struct obstack bstring_obstack;
      obstack_init (&bstring_obstack);
      curoff = ftell (state_file);
      while ((c = getc (state_file)) != '"' && c >= 0)
        {
          if (ISPRINT (c) && c != '\\')
            obstack_1grow (&bstring_obstack, (char) c);
          else if (ISSPACE (c) && c != '\n')
            obstack_1grow (&bstring_obstack, (char) c);
          else if (c == '\\')
            {
              c = getc (state_file);
              switch (c)
                {
                case 'a':
                  obstack_1grow (&bstring_obstack, '\a');
                  c = getc (state_file);
                  break;
                case 'b':
                  obstack_1grow (&bstring_obstack, '\b');
                  c = getc (state_file);
                  break;
                case 't':
                  obstack_1grow (&bstring_obstack, '\t');
                  c = getc (state_file);
                  break;
                case 'n':
                  obstack_1grow (&bstring_obstack, '\n');
                  c = getc (state_file);
                  break;
                case 'v':
                  obstack_1grow (&bstring_obstack, '\v');
                  c = getc (state_file);
                  break;
                case 'f':
                  obstack_1grow (&bstring_obstack, '\f');
                  c = getc (state_file);
                  break;
                case 'r':
                  obstack_1grow (&bstring_obstack, '\r');
                  c = getc (state_file);
                  break;
                case '"':
                  obstack_1grow (&bstring_obstack, '\"');
                  c = getc (state_file);
                  break;
                case '\\':
                  obstack_1grow (&bstring_obstack, '\\');
                  c = getc (state_file);
                  break;
                case ' ':
                  obstack_1grow (&bstring_obstack, ' ');
                  c = getc (state_file);
                  break;
                case 'x':
                  {
                    unsigned int cx = 0;
                    if (fscanf (state_file, "%02x", &cx) > 0 && cx > 0)
                      obstack_1grow (&bstring_obstack, cx);
                    else
                      fatal_reading_state (NULL_TOKEN,
                                           "Lexical error in string escape");
                    c = getc (state_file);
                    break;
                  }
                default:
                  fatal_reading_state (NULL_TOKEN,
                                       "Lexical error in string escape");
                }
            }
          else
            fatal_reading_state (NULL_TOKEN, "Lexical error...");
        };
      if (c != '"')
        fatal_reading_state (NULL_TOKEN, "Unterminated string");
      obstack_1grow (&bstring_obstack, (char) 0);
      cstr = XOBFINISH (&bstring_obstack, char *);
      cslen = strlen (cstr);
      tk = (struct state_token_st *)
        xcalloc (sizeof (struct state_token_st) + cslen, 1);
      tk->stok_kind = STOK_STRING;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      strcpy (tk->stok_un.stok_string, cstr);
      obstack_free (&bstring_obstack, cstr);

      return tk;
    }
  fatal_reading_state_printf (NULL_TOKEN, "Lexical error at offset %ld",
                              ftell (state_file));
}

static struct state_token_st *
peek_state_token (int depth)
{
  int remdepth = depth;
  struct state_token_st **ptoken = &state_token;
  struct state_token_st *tok = NULL;

  while (remdepth >= 0)
    {
      if (*ptoken == NULL)
        {
          *ptoken = tok = read_a_state_token ();
          if (tok == NULL)
            return NULL;
        }
      tok = *ptoken;
      ptoken = &((*ptoken)->stok_next);
      remdepth--;
    }

  return tok;
}

static void
next_state_tokens (int depth)
{
  struct state_token_st *n;

  while (depth > 0)
    {
      if (state_token != NULL)
        {
          n = state_token->stok_next;
          free (state_token);
          state_token = n;
        }
      else
        fatal_reading_state (NULL_TOKEN, "Tokens stack empty");

      depth--;
    }
}

static enum state_token_en
state_token_kind (struct state_token_st *p)
{
  if (p == NULL)
    return STOK_NONE;
  else
    return p->stok_kind;
}

static bool
state_token_is_name (struct state_token_st *p, const char *name)
{
  if (p == NULL)
    return false;

  if (p->stok_kind != STOK_NAME)
    return false;

  return !strcmp (p->stok_un.stok_ident->stid_name, name);
}


/* Following routines are useful for serializing datas.
 *
 * We want to serialize :
 *          - typedefs list
 *          - structures list
 *          - param_structs list
 *          - variables list
 *
 * So, we have one routine for each kind of data. The main writing
 * routine is write_state. Most writing routines have a corresponding
 * reading routine.
 */

static htab_t state_seen_types;

static void write_state_pair (pair_p);
static void write_state_pair_list (pair_p list);
static void write_state_type (type_p);
static void write_state_a_string (const char *s);

static void
write_state_fileloc (struct fileloc *line)
{
  fprintf (state_file, "\n(!fileloc ");

  if (line != NULL && line->line > 0)
    {
      gcc_assert (line->ifile != NULL);
      write_state_a_string (input_file_name (line->ifile));
      fprintf (state_file, " %d", line->line);
    }
  else
    {
      fprintf (state_file, "nil ");
    }

  fprintf (state_file, ")\n");
}

static void
write_state_fields (pair_p fields)
{
  fprintf (state_file, "\n(!fields ");

  write_state_pair_list (fields);

  fprintf (state_file, ")\n");
}

static void
write_state_a_string (const char *s)
{
  char c;

  fputs (" \"", state_file);
  for (; *s != 0; s++)
    {
      c = *s;
      switch (c)
        {
        case '\a':
          fputs ("\\a", state_file);
          break;
        case '\b':
          fputs ("\\b", state_file);
          break;
        case '\t':
          fputs ("\\t", state_file);
          break;
        case '\n':
          fputs ("\\n", state_file);
          break;
        case '\v':
          fputs ("\\v", state_file);
          break;
        case '\f':
          fputs ("\\f", state_file);
          break;
        case '\r':
          fputs ("\\r", state_file);
          break;
        case '\"':
          fputs ("\\\"", state_file);
          break;
        case '\\':
          fputs ("\\\\", state_file);
          break;
        default:
          if (ISPRINT (c))
            putc (c, state_file);
          else
            fprintf (state_file, "\\x%02x", (unsigned) c);
        }
    }
  fputs ("\"", state_file);
}

static void
write_state_string_option (options_p current)
{
  fprintf (state_file, "string ");
  if (current->info.string != NULL)
    write_state_a_string (current->info.string);
  else
    fprintf (state_file, " nil ");
}

static void
write_state_type_option (options_p current)
{
  fprintf (state_file, "type ");
  write_state_type (current->info.type);
}

static void
write_state_nested_option (options_p current)
{
  fprintf (state_file, "nested ");
  write_state_type (current->info.nested->type);
  if (current->info.nested->convert_from != NULL)
    write_state_a_string (current->info.nested->convert_from);
  else
    fprintf (state_file, " nil ");

  if (current->info.nested->convert_to != NULL)
    write_state_a_string (current->info.nested->convert_to);
  else
    fprintf (state_file, " nil ");
}

static void
write_state_option (options_p current)
{
  fprintf (state_file, "\n(!option ");

  if (current->name != NULL)
    fprintf (state_file, "%s ", current->name);
  else
    fprintf (state_file, "nil ");

  switch (current->kind)
    {
    case INFO_STRING:
      write_state_string_option (current);
      break;
    case INFO_TYPE:
      write_state_type_option (current);
      break;
    case INFO_NESTED:
      write_state_nested_option (current);
      break;
    default:
      fatal ("Option tag unknown");
    }

  fprintf (state_file, ")\n");
}



static void
write_state_options (options_p opt)
{
  options_p current;

  if (opt == NULL)
    {
      fprintf (state_file, "nil ");
      return;
    }

  fprintf (state_file, "\n(!options ");

  for (current = opt; current != NULL; current = current->next)
    {
      write_state_option (current);
    }

  fprintf (state_file, ")\n");
}

static void
write_state_lang_bitmap (lang_bitmap bitmap)
{
  fprintf (state_file, "%d ", bitmap);
}

static void
write_state_version (const char *version)
{
  fprintf (state_file, "\n(!version ");
  write_state_a_string (version);
  fprintf (state_file, ")\n");
}

void write_state_common_type_content (type_p current);

static void
write_state_scalar_type (type_p current)
{
  if (current == &scalar_non_char)
    fprintf (state_file, "scalar_non_char ");

  else if (current == &scalar_char)
    fprintf (state_file, "scalar_char ");

  else
    fatal ("Unexpected type in write_state_scalar_type");

  write_state_common_type_content (current);
}

static void
write_state_string_type (type_p current)
{
  if (current == &string_type)
    {
      fprintf (state_file, "string ");
      write_state_common_type_content (current);
    }
  else
    fatal ("Unexpected type in write_state_string_type");
}

#warning write_state_lang_struct_list inutile
#if 0
static void
write_state_lang_struct_list (type_p lis)
{
  if (!lis)
    fprintf (state_file, "nil");
  else
    {
      type_p cur = NULL;
      fprintf (state_file, "(!lang_struct_list ");
      for (cur = lis; cur; cur = cur->next)
        {
          fprintf (state_file, "\n");
          write_state_type (cur);
	  /* we only need to proceed to the next if we have a
	     lang_struct; otherwise it is an ordinary type.. */
	  if (!cur || cur->kind != TYPE_LANG_STRUCT)
	    break;
        }
      fprintf (state_file, ")\n");
    }
}
#endif


static void
write_state_struct_union_type (type_p current, const char *t)
{
  fprintf (state_file, "%s ", t);
  write_state_common_type_content (current);
  if (current->u.s.tag != NULL)
    write_state_a_string (current->u.s.tag);
  else
    fprintf (state_file, "nil");

  write_state_fileloc (type_lineloc (current));
  write_state_fields (current->u.s.fields);
  write_state_options (current->u.s.opt);
  write_state_lang_bitmap (current->u.s.bitmap);
  write_state_type (current->u.s.lang_struct);
}


static void
write_state_struct_type (type_p current)
{
  write_state_struct_union_type (current, "struct");
}

static void
write_state_union_type (type_p current)
{
  write_state_struct_union_type (current, "union");
}

static void
write_state_lang_struct_type (type_p current)
{
  write_state_struct_union_type (current, "lang_struct");
}

static void
write_state_param_struct_type (type_p current)
{
  int i;

  fprintf (state_file, "param_struct ");
  write_state_common_type_content (current);
  write_state_type (current->u.param_struct.stru);
  for (i = 0; i < NUM_PARAM; i++)
    {
      if (current->u.param_struct.param[i] != NULL)
        write_state_type (current->u.param_struct.param[i]);
      else
        fprintf (state_file, "nil ");
    }
  write_state_fileloc (&current->u.param_struct.ptyline);
}

static void
write_state_pointer_type (type_p current)
{
  fprintf (state_file, "pointer ");
  write_state_common_type_content (current);
  write_state_type (current->u.p);
}

static void
write_state_array_type (type_p current)
{
  fprintf (state_file, "array ");
  write_state_common_type_content (current);
  if (current->u.a.len != NULL)
    write_state_a_string (current->u.a.len);
  else
    fprintf (state_file, " nil");

  fprintf (state_file, " ");
  write_state_type (current->u.a.p);
}

void
write_state_common_type_content (type_p current)
{
  fprintf (state_file, "%d ", current->state_number);
  /* we do not write the next type.  */
  write_state_type (current->pointer_to);
  /* We do not write gc_used.  It is re-computed after reading the state!  */
}


static void
write_state_type (type_p current)
{
  static int type_count = 0;

  if (current == NULL)
    {
      fprintf (state_file, "nil ");
      return;
    }

  fprintf (state_file, "\n(!type ");

  if (current->state_number > 0)
    {
      fprintf (state_file, "already_seen %d", current->state_number);
    }
  else if (current->state_number == 0)
    {
      type_count++;
      current->state_number = type_count;
      switch (current->kind)
        {
        case TYPE_STRUCT:
          write_state_struct_type (current);
          break;
        case TYPE_UNION:
          write_state_union_type (current);
          break;
        case TYPE_POINTER:
          write_state_pointer_type (current);
          break;
        case TYPE_ARRAY:
          write_state_array_type (current);
          break;
        case TYPE_LANG_STRUCT:
          write_state_lang_struct_type (current);
          break;
        case TYPE_PARAM_STRUCT:
          write_state_param_struct_type (current);
          break;
        case TYPE_SCALAR:
          write_state_scalar_type (current);
          break;
        case TYPE_STRING:
          write_state_string_type (current);
          break;

        default:
          fatal ("Unexpected type...");
        }
    }

  fprintf (state_file, ")\n");
}

static void
write_state_pair (pair_p current)
{
  if (current == NULL)
    {
      fprintf (state_file, "nil)");
      return;
    }

  fprintf (state_file, "\n(!pair ");

  if (current->name != NULL)
    {
      write_state_a_string (current->name);
    }
  else
    {
      write_state_a_string ("nil");
    }
  write_state_type (current->type);
  write_state_fileloc (&(current->line));
  write_state_options (current->opt);

  fprintf (state_file, ")");
}

static void
write_state_pair_list (pair_p list)
{
  pair_p current;

  fprintf (state_file, "\n(!pairs ");

  for (current = list; current != NULL; current = current->next)
    {
      write_state_pair (current);
    }

  fprintf (state_file, ")\n");
}

static void
write_state_typedefs (void)
{
  fprintf (state_file, "\n(!typedefs\n");

  write_state_pair_list (typedefs);

  fprintf (state_file, ")\n");
}

static void
write_state_structures (void)
{
  type_p current;

  fprintf (state_file, "\n(!structures\n");

  for (current = structures; current != NULL; current = current->next)
    {
      write_state_type (current);
    }

  fprintf (state_file, ")\n");
}

static void
write_state_param_structs (void)
{
  type_p current;

  fprintf (state_file, "\n(!param_structs\n");

  for (current = param_structs; current != NULL; current = current->next)
    {
      write_state_type (current);
    }

  fprintf (state_file, ")\n");
}

static void
write_state_variables (void)
{
  fprintf (state_file, "\n(!variables\n");

  write_state_pair_list (variables);

  fprintf (state_file, ")\n");
}

static void
write_state_srcdir (void)
{
  fprintf (state_file, "\n(!srcdir ");
  write_state_a_string (srcdir);
  fprintf (state_file, ")\n");
}

static void
write_state_files_list (void)
{
  int i = 0;
  /* write the list of files with its lang_bitmap */
  fprintf (state_file, "\n(!fileslist %d\n", (int) num_gt_files);
  for (i = 0; i < (int) num_gt_files; i++)
    {
      fprintf (state_file, "(!file %d ", get_lang_bitmap (gt_files[i]));
      write_state_a_string (input_file_name (gt_files[i]));
      fprintf (state_file, ")\n");
    }
  fprintf (state_file, ")\n");
}

static void
write_state_languages (void)
{
  int i = 0;
  fprintf (state_file, "\n(!languages %d", (int) num_lang_dirs);
  for (i = 0; i < (int) num_lang_dirs; i++)
    {
      /* languages names are identifiers */
      fprintf (state_file, " %s", lang_dir_names[i]);
    }
  fprintf (state_file, ")\n");
}

static void
write_state_trailer (void)
{
  fprintf (state_file, "\n(!endfile)\n");
}

void
write_state (const char *state_path)
{
  long statelen = 0;
  time_t now = 0;
  char *temp_state_path = NULL;
  char tempsuffix[40];
  time (&now);

  /* We write a unique temporary file which is renamed when complete
   * only.  So even if gengtype is interrupted, the written state file
   * won't be partially written, since the temporary file is not yet
   * renamed in that case.... */
  memset (tempsuffix, 0, sizeof (tempsuffix));
  snprintf (tempsuffix, sizeof (tempsuffix) - 1, "-%ld-%d.tmp", (long) now,
            (int) getpid ());
  temp_state_path = concat (state_path, tempsuffix, NULL);
  state_file = fopen (temp_state_path, "w");
  if (state_file == NULL)
    fatal ("Failed to open file %s for writing state: %s",
           temp_state_path, strerror (errno));

  fprintf (state_file,
           ";;; DON'T EDIT THIS FILE, since generated by GCC's gengtype\n");
  fprintf (state_file, ";; file %s generated on %s\n", state_path,
           ctime (&now));

  write_state_version (version_string);
  write_state_srcdir ();
  write_state_languages ();
  write_state_files_list ();
  write_state_structures ();
  write_state_typedefs ();
  write_state_param_structs ();
  write_state_variables ();
  write_state_trailer ();
  statelen = ftell (state_file);
  fclose (state_file);

  if (rename (temp_state_path, state_path))
    fatal ("failed to rename %s to state file %s [%s]", temp_state_path,
           state_path, strerror (errno));
  free (temp_state_path);

  printf ("gengtype wrote state file %s of %ld bytes\n", state_path,
          statelen);

}

/*****************************************************************
 * End of writing routines!  The corresponding reading routines follow.
 *****************************************************************/


/* Forward declarations, since some read_state_* functions are
   recursive! */
static void read_state_fileloc (struct fileloc *line);
static void read_state_options (options_p * opt);
static void read_state_type (type_p * current);
static void read_state_pair (pair_p * pair);
static void read_state_pair_list (pair_p * list);
static void read_state_fields (pair_p * fields);
static void read_state_common_type_content (type_p current);





static void
record_type (type_p type)
{
  PTR *slot;

  slot = htab_find_slot (state_seen_types, type, INSERT);
  gcc_assert (slot);

  *slot = type;
}

static void
read_state_already_seen_type (type_p * type)
{
  struct state_token_st *t0;

  t0 = peek_state_token (0);

  if (state_token_kind (t0) == STOK_INTEGER)
    {
      PTR *slot = NULL;
      struct type loctype = { TYPE_SCALAR, 0, 0, 0, GC_UNUSED, {0} };

      loctype.state_number = t0->stok_un.stok_int;
      slot = htab_find_slot (state_seen_types, &loctype, NO_INSERT);
      if (slot == NULL)
        {
          fatal_reading_state (t0, "Unknown type");
        }

      next_state_tokens (1);
      *type = (type_p) * slot;
    }
  else
    {
      fatal_reading_state (t0, "Bad seen type");
    }
}

static void
read_state_scalar_non_char_type (type_p * type)
{
  *type = &scalar_non_char;
  read_state_common_type_content (*type);
}

static void
read_state_scalar_char_type (type_p * type)
{
  *type = &scalar_char;
  read_state_common_type_content (*type);
}

static void
read_state_string_type (type_p * type)
{
  *type = &string_type;
  read_state_common_type_content (*type);
}

static void
read_state_lang_bitmap (lang_bitmap * bitmap)
{
  struct state_token_st *t;

  t = peek_state_token (0);
  if (state_token_kind (t) == STOK_INTEGER)
    {
      *bitmap = t->stok_un.stok_int;
      next_state_tokens (1);
    }
  else
    {
      fatal_reading_state (t, "Bad syntax for bitmap");
    }
}

static void
read_state_struct_type (type_p type)
{
  struct state_token_st *t0;

  type->kind = TYPE_STRUCT;
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
    {
      if (state_token_is_name (t0, "nil"))
        {
          type->u.s.tag = NULL;
        }
      else
        {
          type->u.s.tag = xstrdup (t0->stok_un.stok_string);
        }
      next_state_tokens (1);
      read_state_fileloc (&(type->u.s.styline));
      read_state_fields (&(type->u.s.fields));
      read_state_options (&(type->u.s.opt));
      read_state_lang_bitmap (&(type->u.s.bitmap));
      read_state_type (&(type->u.s.lang_struct));
    }
  else
    {
      fatal_reading_state (t0, "Bad tag in struct type");
    }
}

static void
read_state_union_type (type_p type)
{
  struct state_token_st *t0;

  type->kind = TYPE_UNION;
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
    {
      if (state_token_is_name (t0, "nil"))
        type->u.s.tag = NULL;
      else
        type->u.s.tag = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
      read_state_fileloc (&(type->u.s.styline));
      read_state_fields (&(type->u.s.fields));
      read_state_options (&(type->u.s.opt));
      read_state_lang_bitmap (&(type->u.s.bitmap));
      read_state_type (&(type->u.s.lang_struct));
    }
  else
    fatal_reading_state (t0, "Bad tag in union type");
}

static void
read_state_pointer_type (type_p type)
{
  type->kind = TYPE_POINTER;
  read_state_common_type_content (type);
  read_state_type (&(type->u.p));
}

static void
read_state_array_type (type_p type)
{
  struct state_token_st *t0;

  type->kind = TYPE_ARRAY;
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
    {
      type->u.a.len = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
      read_state_type (&(type->u.a.p));
    }

  else if (state_token_is_name (t0, "nil"))
    {
      type->u.a.len = NULL;
      next_state_tokens (1);
    }

  else
    fatal_reading_state (t0, "Bad array name type");
}

#warning read_state_lang_struct_list inutile
#if 0
static void
read_state_lang_struct_list (type_p * plis)
{
  struct state_token_st *t0;
  struct state_token_st *t1;
  t0 = peek_state_token (0);
  t1 = peek_state_token (1);
  gcc_assert (plis != NULL && *plis == NULL);
  if (state_token_is_name (t0, "nil"))
    {
      t0 = t1 = NULL;
      next_state_tokens (1);
      *plis = NULL;
    }
  else if (state_token_kind (t0) == STOK_LEFTPAR
           && state_token_is_name (t1, "!lang_struct_list"))
    {
      t0 = t1 = NULL;
      next_state_tokens (2);
      while ((t0 = peek_state_token (0)) != NULL
             && state_token_kind (t0) != STOK_RIGHTPAR)
        {
#warning t1 pour deboguer
	  t1 = peek_state_token (1);
          read_state_type (plis);
          gcc_assert (*plis != NULL && (*plis)->next == NULL);
          plis = &(*plis)->next;
        }
      t0 = peek_state_token (0);
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        fatal_reading_state (t0, "expecting ) for !lang_struct_list");
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "Bad !lang_struct_list");
}
#endif


static void
read_state_lang_struct_type (type_p type)
{
  struct state_token_st *t0;

  type->kind = TYPE_LANG_STRUCT;
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
    {
      if (state_token_is_name (t0, "nil"))
        type->u.s.tag = NULL;
      else
        type->u.s.tag = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "Bad tag in lang struct type");
  read_state_fileloc (&(type->u.s.styline));
  read_state_fields (&(type->u.s.fields));
  read_state_options (&(type->u.s.opt));
  read_state_lang_bitmap (&(type->u.s.bitmap));
  read_state_type (&(type->u.s.lang_struct));
}

static void
read_state_param_struct_type (type_p type)
{
  int i;
  struct state_token_st *t0;

  type->kind = TYPE_PARAM_STRUCT;
  read_state_common_type_content (type);
  read_state_type (&(type->u.param_struct.stru));

  for (i = 0; i < NUM_PARAM; i++)
    {
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_NAME)
        {
          if (state_token_is_name (t0, "nil"))
            {
              type->u.param_struct.param[i] = NULL;
              next_state_tokens (1);
            }
          else
            {
              fatal_reading_state (t0, "Bad param struct for null case");
            }
        }
      else
        {
          read_state_type (&(type->u.param_struct.param[i]));
        }
    }
  read_state_fileloc (&(type->u.param_struct.ptyline));
}

static void
read_state_common_type_content (type_p current)
{
  struct state_token_st *t0;

  t0 = peek_state_token (0);

  if (state_token_kind (t0) == STOK_INTEGER)
    {
      current->state_number = t0->stok_un.stok_int;
      next_state_tokens (1);
      record_type (current);
    }
  else
    {
      fatal_reading_state_printf (t0,
                                  "Expected integer for state_number line %d",
                                  state_line);
    }
  /* we don't read the next type */
  read_state_type (&(current->pointer_to));
}

void
read_state_type (type_p * current)
{
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!type"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      if (state_token_is_name (t0, "already_seen"))
        {
          next_state_tokens (1);
          read_state_already_seen_type (current);
        }
      else
        {
          t0 = peek_state_token (0);

          if (state_token_is_name (t0, "scalar_non_char"))
            {
              next_state_tokens (1);
              read_state_scalar_non_char_type (current);
            }
          else if (state_token_is_name (t0, "scalar_char"))
            {
              next_state_tokens (1);
              read_state_scalar_char_type (current);
            }
          else if (state_token_is_name (t0, "string"))
            {
              next_state_tokens (1);
              /* the common content is read specially */
              read_state_string_type (current);
            }
          else if (state_token_is_name (t0, "struct"))
            {
              *current = XCNEW (struct type);
              next_state_tokens (1);
              read_state_struct_type (*current);
            }
          else if (state_token_is_name (t0, "union"))
            {
              *current = XCNEW (struct type);
              next_state_tokens (1);
              read_state_union_type (*current);
            }
          else if (state_token_is_name (t0, "lang_struct"))
            {
              *current = XCNEW (struct type);
              next_state_tokens (1);
              read_state_lang_struct_type (*current);
            }
          else if (state_token_is_name (t0, "param_struct"))
            {
              *current = XCNEW (struct type);
              next_state_tokens (1);
              read_state_param_struct_type (*current);
            }
          else if (state_token_is_name (t0, "pointer"))
            {
              *current = XCNEW (struct type);
              next_state_tokens (1);
              read_state_pointer_type (*current);
            }
          else if (state_token_is_name (t0, "array"))
            {
              *current = XCNEW (struct type);
              next_state_tokens (1);
              read_state_array_type (*current);
            }
          else
            {
              fatal_reading_state (t0, "bad type in (!type");
            }
        }
      t0 = peek_state_token (0);
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        {
          fatal_reading_state (t0, "missing ) in type");
        }
      next_state_tokens (1);
    }
  else if (state_token_is_name (t0, "nil"))
    {
      next_state_tokens (1);
      *current = NULL;
    }
  else
      fatal_reading_state (t0, "bad type syntax");
}

void
read_state_fileloc (struct fileloc *line)
{
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!fileloc"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t1 = peek_state_token (1);
      if (state_token_kind (t0) == STOK_NAME &&
          state_token_is_name (t0, "nil"))
        {
          next_state_tokens (1);
          line->ifile = NULL;
          line->line = 0;
        }
      else if (state_token_kind (t0) == STOK_STRING &&
               state_token_kind (t1) == STOK_INTEGER)
        {
          char *fpath = t0->stok_un.stok_string;
          line->ifile = input_file_by_name (fpath);
          line->line = t1->stok_un.stok_int;
          next_state_tokens (2);
        }
      else
        {
          fatal_reading_state (t0, "Bad fileloc syntax");
        }
      t0 = peek_state_token (0);
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        {
          fatal_reading_state (t0, "Bad fileloc syntax, waiting for )");
        }
      next_state_tokens (1);
    }
  else
    {
      fatal_reading_state (t0, "Bad fileloc syntax");
    }
}

void
read_state_fields (pair_p * fields)
{
  pair_p tmp = NULL;
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!fields"))
    {
      next_state_tokens (2);
      read_state_pair_list (&tmp);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_RIGHTPAR)
        {
          next_state_tokens (1);
        }
      else
        {
          fatal_reading_state (t0, "Bad fields waiting )");
        }
    }

  *fields = tmp;
}

static void
read_state_string_option (options_p opt)
{
  struct state_token_st *t0;

  t0 = peek_state_token (0);
  opt->kind = INFO_STRING;
  if (state_token_kind (t0) == STOK_STRING)
    {
      opt->info.string = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
    }
  else if (state_token_is_name (t0, "nil"))
    {
      opt->info.string = NULL;
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "Missing name in string option");
}

static void
read_state_type_option (options_p opt)
{
  opt->kind = INFO_TYPE;
  read_state_type (&(opt->info.type));
}

static void
read_state_nested_option (options_p opt)
{
  struct state_token_st *t0;

  opt->info.nested = XCNEW (struct nested_ptr_data);
  opt->kind = INFO_NESTED;
  read_state_type (&(opt->info.nested->type));
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
    {
      opt->info.nested->convert_from = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
    }
  else if (state_token_is_name (t0, "nil"))
    {
      opt->info.nested->convert_from = NULL;
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "Bad nested convert_from option");

  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
    {
      opt->info.nested->convert_to = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
    }
  else if (state_token_is_name (t0, "nil"))
    {
      opt->info.nested->convert_to = NULL;
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "Bad nested convert_from option");
}

static void
read_state_option (options_p * opt)
{
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!option"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_NAME)
        {
          *opt = XCNEW (struct options);
          if (state_token_is_name (t0, "nil"))
            (*opt)->name = NULL;
          else
            (*opt)->name = t0->stok_un.stok_ident->stid_name;
          next_state_tokens (1);
          t0 = peek_state_token (0);
          if (state_token_kind (t0) == STOK_NAME)
            {
              if (state_token_is_name (t0, "string"))
                {
                  next_state_tokens (1);
                  read_state_string_option (*opt);
                }
              else if (state_token_is_name (t0, "type"))
                {
                  next_state_tokens (1);
                  read_state_type_option (*opt);
                }
              else if (state_token_is_name (t0, "nested"))
                {
                  next_state_tokens (1);
                  read_state_nested_option (*opt);
                }
              else
                fatal_reading_state (t0, "Bad option type");
              t0 = peek_state_token (0);
              if (state_token_kind (t0) != STOK_RIGHTPAR)
                fatal_reading_state (t0, "Bad syntax in option, expecting )");

              next_state_tokens (1);
            }
          else
            fatal_reading_state (t0, "Missing option type");
        }
      else
        fatal_reading_state (t0, "Bad name for option");
    }
  else
    fatal_reading_state (t0, "Bad option, waiting for )");
}

void
read_state_options (options_p * opt)
{
  options_p head = NULL;
  options_p previous;
  options_p current_option;
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!options"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      while (state_token_kind (t0) != STOK_RIGHTPAR)
        {
          read_state_option (&current_option);
          if (head == NULL)
            {
              head = current_option;
              previous = head;
            }
          else
            {
              previous->next = current_option;
              previous = current_option;
            }
          t0 = peek_state_token (0);
        }
      next_state_tokens (1);
    }
  else if (state_token_is_name (t0, "nil"))
    {
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "Bad options syntax");

  *opt = head;
}

static void
read_state_version (const char *version_string)
{
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!version"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t1 = peek_state_token (1);
      if (state_token_kind (t0) == STOK_STRING &&
          state_token_kind (t1) == STOK_RIGHTPAR)
        {
          version_string = xstrdup (t0->stok_un.stok_string);
          next_state_tokens (2);
        }
      else
        {
          fatal_reading_state (t0, "Missing version or right parenthesis");
        }
    }
  else
    {
      fatal_reading_state (t0, "Bad version syntax");
    }
}

void
read_state_pair (pair_p * current)
{
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!pair"))
    {
      *current = XCNEW (struct pair);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_STRING)
        {
          if (strcmp (t0->stok_un.stok_string, "nil") == 0)
            {
              (*current)->name = NULL;
            }
          else
            {
              (*current)->name = xstrdup (t0->stok_un.stok_string);
            }
          next_state_tokens (1);
          read_state_type (&((*current)->type));
          read_state_fileloc (&((*current)->line));
          read_state_options (&((*current)->opt));;
          t0 = peek_state_token (0);
          if (state_token_kind (t0) == STOK_RIGHTPAR)
            {
              next_state_tokens (1);
            }
          else
            {
              fatal_reading_state (t0, "Bad syntax for pair, )");
            }
        }
      else
        {
          fatal_reading_state (t0, "Bad name for pair");
        }
    }
  else if (state_token_kind (t0) == STOK_NAME &&
           state_token_is_name (t0, "nil"))
    {
      next_state_tokens (1);
      *current = NULL;
    }
  else
    {
      fatal_reading_state_printf (t0, "Bad syntax for pair, (!pair %d",
                                  state_token->stok_kind);
    }
}

void
read_state_pair_list (pair_p * list)
{
  pair_p head = NULL;
  pair_p previous;
  pair_p tmp;
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!pairs"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      while (state_token_kind (t0) != STOK_RIGHTPAR)
        {
          read_state_pair (&tmp);
          if (head == NULL)
            {
              head = tmp;
              previous = head;
            }
          else
            {
              previous->next = tmp;
              previous = tmp;
            }
          t0 = peek_state_token (0);
        }

      next_state_tokens (1);
      *list = head;
    }
}

static void
read_state_typedefs (pair_p * typedefs)
{
  pair_p list = NULL;
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!typedefs"))
    {
      next_state_tokens (2);
      read_state_pair_list (&list);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_RIGHTPAR)
        {
          next_state_tokens (1);
        }
      else
        {
          fatal_reading_state (t0, "Bad typedefs syntax )");
        }
    }
  else
    {
      fatal_reading_state (t0, "Bad typedefs syntax (!typedefs");
    }

  *typedefs = list;
}

static void
read_state_structures (type_p * structures)
{
  type_p head = NULL;
  type_p previous;
  type_p tmp;
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!structures"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      while (state_token_kind (t0) != STOK_RIGHTPAR)
        {
          read_state_type (&tmp);
          if (head == NULL)
            {
              head = tmp;
              previous = head;
            }
          else
            {
              previous->next = tmp;
              previous = tmp;
            }
          t0 = peek_state_token (0);
        }
      next_state_tokens (1);
    }
  else
    {
      fatal_reading_state (t0, "Bad structures syntax");
    }

  *structures = head;
}

static void
read_state_param_structs (type_p * param_structs)
{
  type_p head = NULL;
  type_p previous;
  type_p tmp;
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!param_structs"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      while (state_token_kind (t0) != STOK_RIGHTPAR)
        {
          read_state_type (&tmp);
          if (head == NULL)
            {
              head = tmp;
              previous = head;
            }
          else
            {
              previous->next = tmp;
              previous = tmp;
            }
          t0 = peek_state_token (0);
        }
      next_state_tokens (1);
    }
  else
    {
      fatal_reading_state (t0, "Bad param_structs syntax");
    }

  *param_structs = head;
}

static void
read_state_variables (pair_p * variables)
{
  pair_p list = NULL;
  struct state_token_st *t0;
  struct state_token_st *t1;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);

  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!variables"))
    {
      next_state_tokens (2);
      read_state_pair_list (&list);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_RIGHTPAR)
        {
          next_state_tokens (1);
        }
      else
        {
          fatal_reading_state (t0, "Waiting for ) in variables");
        }
    }
  else
    {
      fatal_reading_state (t0, "Bad variables syntax");
    }

  *variables = list;
}

static void
read_state_srcdir (void)
{
  struct state_token_st *t0 = NULL;
  struct state_token_st *t1 = NULL;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!srcdir"))
    {
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t1 = peek_state_token (1);
      if (state_token_kind (t0) == STOK_STRING &&
          state_token_kind (t1) == STOK_RIGHTPAR)
        {
          srcdir = xstrdup (t0->stok_un.stok_string);
          srcdir_len = strlen (srcdir);
          next_state_tokens (2);
          return;
        }
    }

  fatal_reading_state (t0, "Bad srcdir in state_file");
}

static void
read_state_languages (void)
{
  struct state_token_st *t0 = NULL;
  struct state_token_st *t1 = NULL;
  struct state_token_st *t2 = NULL;
  t0 = peek_state_token (0);
  t1 = peek_state_token (1);
  t2 = peek_state_token (2);
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!languages")
      && state_token_kind (t2) == STOK_INTEGER)
    {
      int i = 0;
      num_lang_dirs = t2->stok_un.stok_int;
      lang_dir_names = XCNEWVEC (const char *, num_lang_dirs);
      next_state_tokens (3);
      t0 = t1 = t2 = NULL;
      for (i = 0; i < (int) num_lang_dirs; i++)
        {
          t0 = peek_state_token (0);
          if (state_token_kind (t0) != STOK_NAME)
            fatal_reading_state (t0, "expecting language name in state file");
          lang_dir_names[i] = t0->stok_un.stok_ident->stid_name;
          next_state_tokens (1);
        }
      t0 = peek_state_token (0);
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        fatal_reading_state (t0, "missing ) in languages list of state file");
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "expecting languages list in state file");

}

static void
read_state_files_list (void)
{
  struct state_token_st *t0 = NULL;
  struct state_token_st *t1 = NULL;
  struct state_token_st *t2 = NULL;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);
  t2 = peek_state_token (2);

  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!fileslist")
      && state_token_kind (t2) == STOK_INTEGER)
    {
      int i = 0;
      num_gt_files = t2->stok_un.stok_int;
      next_state_tokens (3);
      t0 = t1 = t2 = NULL;
      gt_files = XCNEWVEC (input_file *, num_gt_files);
      for (i = 0; i < (int) num_gt_files; i++)
        {
          t0 = t1 = t2 = NULL;
          t0 = peek_state_token (0);
          t1 = peek_state_token (1);
          t2 = peek_state_token (2);
          if (state_token_kind (t0) == STOK_LEFTPAR
              && state_token_is_name (t1, "!file")
              && state_token_kind (t2) == STOK_INTEGER)
            {
              lang_bitmap bmap = t2->stok_un.stok_int;
              next_state_tokens (3);
              t0 = t1 = t2 = NULL;
              t0 = peek_state_token (0);
              t1 = peek_state_token (1);
              if (state_token_kind (t0) == STOK_STRING
                  && state_token_kind (t1) == STOK_RIGHTPAR)
                {
                  const char *fnam = t0->stok_un.stok_string;
                  /* Allocate & fill a gt_file entry with space for the lang_bitmap before! */
                  input_file *curgt = input_file_by_name (fnam);
                  set_lang_bitmap (curgt, bmap);
                  gt_files[i] = curgt;
                  next_state_tokens (2);
                }
              else
                fatal_reading_state (t0,
                                     "bad !file in !fileslist of state file");
            }
          else
            fatal_reading_state (t0,
                                 "expecting !file in !fileslist of state file");
        };
      t0 = peek_state_token (0);
      if (!state_token_kind (t0) == STOK_RIGHTPAR)
        fatal_reading_state (t0, "missing ) for !fileslist in state file");
      next_state_tokens (1);
    }
  else
    fatal_reading_state (t0, "missing !fileslist in state file");
}


static void
read_state_trailer (void)
{
  struct state_token_st *t0 = NULL;
  struct state_token_st *t1 = NULL;
  struct state_token_st *t2 = NULL;

  t0 = peek_state_token (0);
  t1 = peek_state_token (1);
  t2 = peek_state_token (2);

  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!endfile")
      && state_token_kind (t2) == STOK_RIGHTPAR)
    next_state_tokens (3);
  else
    fatal_reading_state (t0, "missing !endfile in state file");
}


static unsigned
hash_type_number (const void *ty)
{
  const struct type *type = (const struct type *) ty;

  return type->state_number;
}

static int
equals_type_number (const void *ty1, const void *ty2)
{
  const struct type *type1 = (const struct type *) ty1;
  const struct type *type2 = (const struct type *) ty2;

  return type1->state_number == type2->state_number;
}


void
read_state (const char *path)
{
  state_file = fopen (path, "r");
  if (state_file == NULL)
    fatal ("Failed to open state file %s for reading [%s]", path,
           strerror (errno));
  state_path = path;
  state_line = 1;
  
  state_seen_types =
    htab_create (400, hash_type_number, equals_type_number, NULL);
  state_ident_tab =
    htab_create (800, htab_hash_string, (htab_eq) strcmp, NULL);
  read_state_version (version_string);
  read_state_srcdir ();
  read_state_languages ();
  read_state_files_list ();
  read_state_structures (&structures);
  read_state_typedefs (&typedefs);
  read_state_param_structs (&param_structs);
  read_state_variables (&variables);
  read_state_trailer ();

  fclose (state_file);
  state_file = NULL;
  state_path = NULL;
}

/* End of file gengtype-state.c.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]