OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-dev/] [fsf-gcc-snapshot-1-mar-12/] [or1k-gcc/] [gcc/] [gengtype-state.c] - Diff between revs 684 and 783

Only display areas with differences | Details | Blame | View Log

Rev 684 Rev 783
/* Gengtype persistent state serialization & de-serialization.
/* Gengtype persistent state serialization & de-serialization.
   Useful for gengtype in plugin mode.
   Useful for gengtype in plugin mode.
 
 
   Copyright (C) 2010  Free Software Foundation, Inc.
   Copyright (C) 2010  Free Software Foundation, Inc.
 
 
   This file is part of GCC.
   This file is part of GCC.
 
 
   GCC is free software; you can redistribute it and/or modify it under
   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
   the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3, or (at your option) any later
   Software Foundation; either version 3, or (at your option) any later
   version.
   version.
 
 
   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for more details.
   for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING3.  If not see
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.
   <http://www.gnu.org/licenses/>.
 
 
   Contributed by Jeremie Salvucci <jeremie.salvucci@free.fr>
   Contributed by Jeremie Salvucci <jeremie.salvucci@free.fr>
   and Basile Starynkevitch <basile@starynkevitch.net>
   and Basile Starynkevitch <basile@starynkevitch.net>
*/
*/
 
 
#ifdef GENERATOR_FILE
#ifdef GENERATOR_FILE
#include "bconfig.h"
#include "bconfig.h"
#else
#else
#include "config.h"
#include "config.h"
#endif
#endif
#include "system.h"
#include "system.h"
#include "errors.h"     /* For fatal.  */
#include "errors.h"     /* For fatal.  */
#include "double-int.h"
#include "double-int.h"
#include "hashtab.h"
#include "hashtab.h"
#include "version.h"    /* For version_string & pkgversion_string.  */
#include "version.h"    /* For version_string & pkgversion_string.  */
#include "obstack.h"
#include "obstack.h"
#include "gengtype.h"
#include "gengtype.h"
 
 
 
 
 
 
/* Gives the file location of a type, if any.  */
/* Gives the file location of a type, if any.  */
static inline struct fileloc*
static inline struct fileloc*
type_lineloc (const_type_p ty)
type_lineloc (const_type_p ty)
{
{
  if (!ty)
  if (!ty)
    return NULL;
    return NULL;
  switch (ty->kind)
  switch (ty->kind)
    {
    {
    case TYPE_NONE:
    case TYPE_NONE:
      gcc_unreachable ();
      gcc_unreachable ();
    case TYPE_STRUCT:
    case TYPE_STRUCT:
    case TYPE_UNION:
    case TYPE_UNION:
    case TYPE_LANG_STRUCT:
    case TYPE_LANG_STRUCT:
      return CONST_CAST (struct fileloc*, &ty->u.s.line);
      return CONST_CAST (struct fileloc*, &ty->u.s.line);
    case TYPE_PARAM_STRUCT:
    case TYPE_PARAM_STRUCT:
      return CONST_CAST (struct fileloc*, &ty->u.param_struct.line);
      return CONST_CAST (struct fileloc*, &ty->u.param_struct.line);
    case TYPE_SCALAR:
    case TYPE_SCALAR:
    case TYPE_STRING:
    case TYPE_STRING:
    case TYPE_POINTER:
    case TYPE_POINTER:
    case TYPE_ARRAY:
    case TYPE_ARRAY:
      return NULL;
      return NULL;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* The state file has simplistic lispy lexical tokens.  Its lexer gives
/* The state file has simplistic lispy lexical tokens.  Its lexer gives
   a linked list of struct state_token_st, thru the peek_state_token
   a linked list of struct state_token_st, thru the peek_state_token
   function.  Lexical tokens are consumed with next_state_tokens.  */
   function.  Lexical tokens are consumed with next_state_tokens.  */
 
 
 
 
/* The lexical kind of each lispy token.  */
/* The lexical kind of each lispy token.  */
enum state_token_en
enum state_token_en
{
{
  STOK_NONE,                    /* Never used.  */
  STOK_NONE,                    /* Never used.  */
  STOK_INTEGER,                 /* Integer token.  */
  STOK_INTEGER,                 /* Integer token.  */
  STOK_STRING,                  /* String token.  */
  STOK_STRING,                  /* String token.  */
  STOK_LEFTPAR,                 /* Left opening parenthesis.  */
  STOK_LEFTPAR,                 /* Left opening parenthesis.  */
  STOK_RIGHTPAR,                /* Right closing parenthesis.  */
  STOK_RIGHTPAR,                /* Right closing parenthesis.  */
  STOK_NAME                     /* hash-consed name or identifier.  */
  STOK_NAME                     /* hash-consed name or identifier.  */
};
};
 
 
 
 
/* Structure and hash-table used to share identifiers or names.  */
/* Structure and hash-table used to share identifiers or names.  */
struct state_ident_st
struct state_ident_st
{
{
  /* TODO: We could improve the parser by reserving identifiers for
  /* TODO: We could improve the parser by reserving identifiers for
     state keywords and adding a keyword number for them.  That would
     state keywords and adding a keyword number for them.  That would
     mean adding another field in this state_ident_st struct.  */
     mean adding another field in this state_ident_st struct.  */
  char stid_name[1];            /* actually bigger & null terminated */
  char stid_name[1];            /* actually bigger & null terminated */
};
};
static htab_t state_ident_tab;
static htab_t state_ident_tab;
 
 
 
 
/* The state_token_st structure is for lexical tokens in the read
/* The state_token_st structure is for lexical tokens in the read
   state file.  The stok_kind field discriminates the union.  Tokens
   state file.  The stok_kind field discriminates the union.  Tokens
   are allocated by peek_state_token which calls read_a_state_token
   are allocated by peek_state_token which calls read_a_state_token
   which allocate them.  Tokens are freed by calls to
   which allocate them.  Tokens are freed by calls to
   next_state_tokens.  Token are organized in a FIFO look-ahead queue
   next_state_tokens.  Token are organized in a FIFO look-ahead queue
   filled by peek_state_token.  */
   filled by peek_state_token.  */
struct state_token_st
struct state_token_st
{
{
  enum state_token_en stok_kind;        /* the lexical kind
  enum state_token_en stok_kind;        /* the lexical kind
                                           discriminates the stok_un
                                           discriminates the stok_un
                                           union  */
                                           union  */
  int stok_line;                        /* the line number */
  int stok_line;                        /* the line number */
  int stok_col;                         /* the column number */
  int stok_col;                         /* the column number */
  const char *stok_file;                /* the file path */
  const char *stok_file;                /* the file path */
  struct state_token_st *stok_next;     /* the next token in the
  struct state_token_st *stok_next;     /* the next token in the
                                           queue, when peeked */
                                           queue, when peeked */
  union                                 /* discriminated by stok_kind! */
  union                                 /* discriminated by stok_kind! */
  {
  {
    int stok_num;                       /* when STOK_INTEGER */
    int stok_num;                       /* when STOK_INTEGER */
    char stok_string[1];                /* when STOK_STRING, actual size is
    char stok_string[1];                /* when STOK_STRING, actual size is
                                           bigger and null terminated */
                                           bigger and null terminated */
    struct state_ident_st *stok_ident;  /* when STOK_IDENT */
    struct state_ident_st *stok_ident;  /* when STOK_IDENT */
    void *stok_ptr;                     /* null otherwise */
    void *stok_ptr;                     /* null otherwise */
  }
  }
  stok_un;
  stok_un;
};
};
 
 
 
 
 
 
 
 
#define NULL_STATE_TOKEN (struct state_token_st*)0
#define NULL_STATE_TOKEN (struct state_token_st*)0
 
 
/* the state_token pointer contains the leftmost current token.  The
/* the state_token pointer contains the leftmost current token.  The
   tokens are organized in a linked queue, using stok_next, for token
   tokens are organized in a linked queue, using stok_next, for token
   look-ahead.  */
   look-ahead.  */
struct state_token_st *state_token = NULL_STATE_TOKEN;
struct state_token_st *state_token = NULL_STATE_TOKEN;
 
 
/* Used by the reading lexer.  */
/* Used by the reading lexer.  */
static FILE *state_file;
static FILE *state_file;
static const char *state_path = NULL;
static const char *state_path = NULL;
static int state_line = 0;
static int state_line = 0;
static long state_bol = 0;       /* offset of beginning of line */
static long state_bol = 0;       /* offset of beginning of line */
 
 
 
 
/* Counter of written types.  */
/* Counter of written types.  */
static int state_written_type_count = 0;
static int state_written_type_count = 0;
 
 
 
 
/* Fatal error messages when reading the state.  They are extremely
/* Fatal error messages when reading the state.  They are extremely
   unlikely, and only appear when this gengtype-state.c file is buggy,
   unlikely, and only appear when this gengtype-state.c file is buggy,
   or when reading a gengtype state which was not generated by the
   or when reading a gengtype state which was not generated by the
   same version of gengtype or GCC.  */
   same version of gengtype or GCC.  */
 
 
 
 
/* Fatal message while reading state.  */
/* Fatal message while reading state.  */
static inline void
static inline void
fatal_reading_state (struct state_token_st* tok, const char*msg)
fatal_reading_state (struct state_token_st* tok, const char*msg)
{
{
  if (tok)
  if (tok)
    fatal ("%s:%d:%d: Invalid state file; %s",
    fatal ("%s:%d:%d: Invalid state file; %s",
           tok->stok_file, tok->stok_line, tok->stok_col,
           tok->stok_file, tok->stok_line, tok->stok_col,
           msg);
           msg);
  else
  else
    fatal ("%s:%d: Invalid state file; %s",
    fatal ("%s:%d: Invalid state file; %s",
           state_path, state_line, msg);
           state_path, state_line, msg);
}
}
 
 
 
 
/* Fatal printf-like message while reading state.  This can't be a
/* Fatal printf-like message while reading state.  This can't be a
   function, because there is no way to pass a va_arg to a variant of
   function, because there is no way to pass a va_arg to a variant of
   fatal.  */
   fatal.  */
#define fatal_reading_state_printf(Tok,Fmt,...) do {    \
#define fatal_reading_state_printf(Tok,Fmt,...) do {    \
    struct state_token_st* badtok = Tok;                \
    struct state_token_st* badtok = Tok;                \
    if (badtok)                                         \
    if (badtok)                                         \
      fatal ("%s:%d:%d: Invalid state file; " Fmt,      \
      fatal ("%s:%d:%d: Invalid state file; " Fmt,      \
              badtok->stok_file,                        \
              badtok->stok_file,                        \
              badtok->stok_line,                        \
              badtok->stok_line,                        \
              badtok->stok_col, __VA_ARGS__);           \
              badtok->stok_col, __VA_ARGS__);           \
    else                                                \
    else                                                \
      fatal ("%s:%d: Invalid state file; " Fmt,         \
      fatal ("%s:%d: Invalid state file; " Fmt,         \
             state_path, state_line, __VA_ARGS__);      \
             state_path, state_line, __VA_ARGS__);      \
  } while(0)
  } while(0)
 
 
 
 
/* Find or allocate an identifier in our name hash table.  */
/* Find or allocate an identifier in our name hash table.  */
static struct state_ident_st *
static struct state_ident_st *
state_ident_by_name (const char *name, enum insert_option optins)
state_ident_by_name (const char *name, enum insert_option optins)
{
{
  PTR *slot = NULL;
  PTR *slot = NULL;
  int namlen = 0;
  int namlen = 0;
  struct state_ident_st *stid = NULL;
  struct state_ident_st *stid = NULL;
 
 
  if (!name || !name[0])
  if (!name || !name[0])
    return NULL;
    return NULL;
 
 
  slot = htab_find_slot (state_ident_tab, name, optins);
  slot = htab_find_slot (state_ident_tab, name, optins);
  if (!slot)
  if (!slot)
    return NULL;
    return NULL;
 
 
  namlen = strlen (name);
  namlen = strlen (name);
  stid =
  stid =
    (struct state_ident_st *) xmalloc (sizeof (struct state_ident_st) +
    (struct state_ident_st *) xmalloc (sizeof (struct state_ident_st) +
                                       namlen);
                                       namlen);
  memset (stid, 0, sizeof (struct state_ident_st) + namlen);
  memset (stid, 0, sizeof (struct state_ident_st) + namlen);
  strcpy (stid->stid_name, name);
  strcpy (stid->stid_name, name);
  *slot = stid;
  *slot = stid;
 
 
  return stid;
  return stid;
}
}
 
 
/* Our token lexer is heavily inspired by MELT's lexer, and share some
/* Our token lexer is heavily inspired by MELT's lexer, and share some
   code with the file gcc/melt-runtime.c of the GCC MELT branch!  We
   code with the file gcc/melt-runtime.c of the GCC MELT branch!  We
   really want the gengtype state to be easily parsable by MELT.  This
   really want the gengtype state to be easily parsable by MELT.  This
   is a usual lispy lexing routine, dealing with spaces and comments,
   is a usual lispy lexing routine, dealing with spaces and comments,
   numbers, parenthesis, names, strings.  */
   numbers, parenthesis, names, strings.  */
static struct state_token_st *
static struct state_token_st *
read_a_state_token (void)
read_a_state_token (void)
{
{
  int c = 0;
  int c = 0;
  long curoff = 0;
  long curoff = 0;
  struct state_token_st *tk = NULL;
  struct state_token_st *tk = NULL;
 
 
 again: /* Read again, e.g. after a comment or spaces.  */
 again: /* Read again, e.g. after a comment or spaces.  */
  c = getc (state_file);
  c = getc (state_file);
  if (c == EOF)
  if (c == EOF)
    return NULL;
    return NULL;
 
 
  /* Handle spaces, count lines.  */
  /* Handle spaces, count lines.  */
  if (c == '\n')
  if (c == '\n')
    {
    {
      state_line++;
      state_line++;
      state_bol = curoff = ftell (state_file);
      state_bol = curoff = ftell (state_file);
      goto again;
      goto again;
    };
    };
  if (ISSPACE (c))
  if (ISSPACE (c))
    goto again;
    goto again;
  /* Skip comments starting with semi-colon.  */
  /* Skip comments starting with semi-colon.  */
  if (c == ';')
  if (c == ';')
    {
    {
      do
      do
        {
        {
          c = getc (state_file);
          c = getc (state_file);
        }
        }
      while (c > 0 && c != '\n');
      while (c > 0 && c != '\n');
      if (c == '\n')
      if (c == '\n')
        {
        {
          state_line++;
          state_line++;
          state_bol = curoff = ftell (state_file);
          state_bol = curoff = ftell (state_file);
        }
        }
      goto again;
      goto again;
    };
    };
  /* Read signed numbers.  */
  /* Read signed numbers.  */
  if (ISDIGIT (c) || c == '-' || c == '+')
  if (ISDIGIT (c) || c == '-' || c == '+')
    {                           /* number */
    {                           /* number */
      int n = 0;
      int n = 0;
      ungetc (c, state_file);
      ungetc (c, state_file);
      curoff = ftell (state_file);
      curoff = ftell (state_file);
      if (fscanf (state_file, "%d", &n) <= 0)
      if (fscanf (state_file, "%d", &n) <= 0)
        fatal_reading_state (NULL_STATE_TOKEN, "Lexical error in number");
        fatal_reading_state (NULL_STATE_TOKEN, "Lexical error in number");
      tk = XCNEW (struct state_token_st);
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_INTEGER;
      tk->stok_kind = STOK_INTEGER;
      tk->stok_line = state_line;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      tk->stok_next = NULL;
      tk->stok_un.stok_num = n;
      tk->stok_un.stok_num = n;
 
 
      return tk;
      return tk;
    }
    }
  /* Read an opening left parenthesis.  */
  /* Read an opening left parenthesis.  */
  else if (c == '(')
  else if (c == '(')
    {
    {
      curoff = ftell (state_file);
      curoff = ftell (state_file);
      tk = XCNEW (struct state_token_st);
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_LEFTPAR;
      tk->stok_kind = STOK_LEFTPAR;
      tk->stok_line = state_line;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      tk->stok_next = NULL;
 
 
      return tk;
      return tk;
    }
    }
  /* Read an closing right parenthesis.  */
  /* Read an closing right parenthesis.  */
  else if (c == ')')
  else if (c == ')')
    {
    {
      curoff = ftell (state_file);
      curoff = ftell (state_file);
      tk = XCNEW (struct state_token_st);
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_RIGHTPAR;
      tk->stok_kind = STOK_RIGHTPAR;
      tk->stok_line = state_line;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      tk->stok_next = NULL;
 
 
      return tk;
      return tk;
    }
    }
  /* Read identifiers, using an obstack.  */
  /* Read identifiers, using an obstack.  */
  else if (ISALPHA (c) || c == '_' || c == '$' || c == '!' || c == '#')
  else if (ISALPHA (c) || c == '_' || c == '$' || c == '!' || c == '#')
    {
    {
      struct obstack id_obstack;
      struct obstack id_obstack;
      struct state_ident_st *sid = NULL;
      struct state_ident_st *sid = NULL;
      char *ids = NULL;
      char *ids = NULL;
      obstack_init (&id_obstack);
      obstack_init (&id_obstack);
      curoff = ftell (state_file);
      curoff = ftell (state_file);
      while (ISALNUM (c) || c == '_' || c == '$' || c == '!' || c == '#')
      while (ISALNUM (c) || c == '_' || c == '$' || c == '!' || c == '#')
        {
        {
          obstack_1grow (&id_obstack, c);
          obstack_1grow (&id_obstack, c);
          c = getc (state_file);
          c = getc (state_file);
          if (c < 0)
          if (c < 0)
            break;
            break;
        };
        };
      if (c >= 0)
      if (c >= 0)
        ungetc (c, state_file);
        ungetc (c, state_file);
      obstack_1grow (&id_obstack, (char) 0);
      obstack_1grow (&id_obstack, (char) 0);
      ids = XOBFINISH (&id_obstack, char *);
      ids = XOBFINISH (&id_obstack, char *);
      sid = state_ident_by_name (ids, INSERT);
      sid = state_ident_by_name (ids, INSERT);
      obstack_free (&id_obstack, NULL);
      obstack_free (&id_obstack, NULL);
      ids = NULL;
      ids = NULL;
      tk = XCNEW (struct state_token_st);
      tk = XCNEW (struct state_token_st);
      tk->stok_kind = STOK_NAME;
      tk->stok_kind = STOK_NAME;
      tk->stok_line = state_line;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      tk->stok_next = NULL;
      tk->stok_un.stok_ident = sid;
      tk->stok_un.stok_ident = sid;
 
 
      return tk;
      return tk;
    }
    }
  /* Read a string, dealing with escape sequences a la C! */
  /* Read a string, dealing with escape sequences a la C! */
  else if (c == '"')
  else if (c == '"')
    {
    {
      char *cstr = NULL;
      char *cstr = NULL;
      int cslen = 0;
      int cslen = 0;
      struct obstack bstring_obstack;
      struct obstack bstring_obstack;
      obstack_init (&bstring_obstack);
      obstack_init (&bstring_obstack);
      curoff = ftell (state_file);
      curoff = ftell (state_file);
      while ((c = getc (state_file)) != '"' && c >= 0)
      while ((c = getc (state_file)) != '"' && c >= 0)
        {
        {
          if (ISPRINT (c) && c != '\\')
          if (ISPRINT (c) && c != '\\')
            obstack_1grow (&bstring_obstack, (char) c);
            obstack_1grow (&bstring_obstack, (char) c);
          else if (ISSPACE (c) && c != '\n')
          else if (ISSPACE (c) && c != '\n')
            obstack_1grow (&bstring_obstack, (char) c);
            obstack_1grow (&bstring_obstack, (char) c);
          else if (c == '\\')
          else if (c == '\\')
            {
            {
              c = getc (state_file);
              c = getc (state_file);
              switch (c)
              switch (c)
                {
                {
                case 'a':
                case 'a':
                  obstack_1grow (&bstring_obstack, '\a');
                  obstack_1grow (&bstring_obstack, '\a');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case 'b':
                case 'b':
                  obstack_1grow (&bstring_obstack, '\b');
                  obstack_1grow (&bstring_obstack, '\b');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case 't':
                case 't':
                  obstack_1grow (&bstring_obstack, '\t');
                  obstack_1grow (&bstring_obstack, '\t');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case 'n':
                case 'n':
                  obstack_1grow (&bstring_obstack, '\n');
                  obstack_1grow (&bstring_obstack, '\n');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case 'v':
                case 'v':
                  obstack_1grow (&bstring_obstack, '\v');
                  obstack_1grow (&bstring_obstack, '\v');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case 'f':
                case 'f':
                  obstack_1grow (&bstring_obstack, '\f');
                  obstack_1grow (&bstring_obstack, '\f');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case 'r':
                case 'r':
                  obstack_1grow (&bstring_obstack, '\r');
                  obstack_1grow (&bstring_obstack, '\r');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case '"':
                case '"':
                  obstack_1grow (&bstring_obstack, '\"');
                  obstack_1grow (&bstring_obstack, '\"');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case '\\':
                case '\\':
                  obstack_1grow (&bstring_obstack, '\\');
                  obstack_1grow (&bstring_obstack, '\\');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case ' ':
                case ' ':
                  obstack_1grow (&bstring_obstack, ' ');
                  obstack_1grow (&bstring_obstack, ' ');
                  c = getc (state_file);
                  c = getc (state_file);
                  break;
                  break;
                case 'x':
                case 'x':
                  {
                  {
                    unsigned int cx = 0;
                    unsigned int cx = 0;
                    if (fscanf (state_file, "%02x", &cx) > 0 && cx > 0)
                    if (fscanf (state_file, "%02x", &cx) > 0 && cx > 0)
                      obstack_1grow (&bstring_obstack, cx);
                      obstack_1grow (&bstring_obstack, cx);
                    else
                    else
                      fatal_reading_state
                      fatal_reading_state
                        (NULL_STATE_TOKEN,
                        (NULL_STATE_TOKEN,
                         "Lexical error in string hex escape");
                         "Lexical error in string hex escape");
                    c = getc (state_file);
                    c = getc (state_file);
                    break;
                    break;
                  }
                  }
                default:
                default:
                  fatal_reading_state
                  fatal_reading_state
                    (NULL_STATE_TOKEN,
                    (NULL_STATE_TOKEN,
                     "Lexical error - unknown string escape");
                     "Lexical error - unknown string escape");
                }
                }
            }
            }
          else
          else
            fatal_reading_state (NULL_STATE_TOKEN, "Lexical error...");
            fatal_reading_state (NULL_STATE_TOKEN, "Lexical error...");
        };
        };
      if (c != '"')
      if (c != '"')
        fatal_reading_state (NULL_STATE_TOKEN, "Unterminated string");
        fatal_reading_state (NULL_STATE_TOKEN, "Unterminated string");
      obstack_1grow (&bstring_obstack, '\0');
      obstack_1grow (&bstring_obstack, '\0');
      cstr = XOBFINISH (&bstring_obstack, char *);
      cstr = XOBFINISH (&bstring_obstack, char *);
      cslen = strlen (cstr);
      cslen = strlen (cstr);
      tk = (struct state_token_st *)
      tk = (struct state_token_st *)
        xcalloc (sizeof (struct state_token_st) + cslen, 1);
        xcalloc (sizeof (struct state_token_st) + cslen, 1);
      tk->stok_kind = STOK_STRING;
      tk->stok_kind = STOK_STRING;
      tk->stok_line = state_line;
      tk->stok_line = state_line;
      tk->stok_col = curoff - state_bol;
      tk->stok_col = curoff - state_bol;
      tk->stok_file = state_path;
      tk->stok_file = state_path;
      tk->stok_next = NULL;
      tk->stok_next = NULL;
      strcpy (tk->stok_un.stok_string, cstr);
      strcpy (tk->stok_un.stok_string, cstr);
      obstack_free (&bstring_obstack, NULL);
      obstack_free (&bstring_obstack, NULL);
 
 
      return tk;
      return tk;
    }
    }
  /* Got an unexpected character.  */
  /* Got an unexpected character.  */
  fatal_reading_state_printf
  fatal_reading_state_printf
    (NULL_STATE_TOKEN,
    (NULL_STATE_TOKEN,
     "Lexical error at offset %ld - bad character \\%03o = '%c'",
     "Lexical error at offset %ld - bad character \\%03o = '%c'",
     ftell (state_file), c, c);
     ftell (state_file), c, c);
}
}
 
 
/* Used for lexical look-ahead.  Retrieves the lexical token of rank
/* Used for lexical look-ahead.  Retrieves the lexical token of rank
   DEPTH, starting with 0 when reading the state file.  Gives null on
   DEPTH, starting with 0 when reading the state file.  Gives null on
   end of file.  */
   end of file.  */
static struct state_token_st *
static struct state_token_st *
peek_state_token (int depth)
peek_state_token (int depth)
{
{
  int remdepth = depth;
  int remdepth = depth;
  struct state_token_st **ptoken = &state_token;
  struct state_token_st **ptoken = &state_token;
  struct state_token_st *tok = NULL;
  struct state_token_st *tok = NULL;
 
 
  while (remdepth >= 0)
  while (remdepth >= 0)
    {
    {
      if (*ptoken == NULL)
      if (*ptoken == NULL)
        {
        {
          *ptoken = tok = read_a_state_token ();
          *ptoken = tok = read_a_state_token ();
          if (tok == NULL)
          if (tok == NULL)
            return NULL;
            return NULL;
        }
        }
      tok = *ptoken;
      tok = *ptoken;
      ptoken = &((*ptoken)->stok_next);
      ptoken = &((*ptoken)->stok_next);
      remdepth--;
      remdepth--;
    }
    }
 
 
  return tok;
  return tok;
}
}
 
 
/* Consume the next DEPTH tokens and free them.  */
/* Consume the next DEPTH tokens and free them.  */
static void
static void
next_state_tokens (int depth)
next_state_tokens (int depth)
{
{
  struct state_token_st *n;
  struct state_token_st *n;
 
 
  while (depth > 0)
  while (depth > 0)
    {
    {
      if (state_token != NULL)
      if (state_token != NULL)
        {
        {
          n = state_token->stok_next;
          n = state_token->stok_next;
          free (state_token);
          free (state_token);
          state_token = n;
          state_token = n;
        }
        }
      else
      else
        fatal_reading_state (NULL_STATE_TOKEN, "Tokens stack empty");
        fatal_reading_state (NULL_STATE_TOKEN, "Tokens stack empty");
 
 
      depth--;
      depth--;
    }
    }
}
}
 
 
/* Safely retrieve the lexical kind of a token.  */
/* Safely retrieve the lexical kind of a token.  */
static inline enum state_token_en
static inline enum state_token_en
state_token_kind (struct state_token_st *p)
state_token_kind (struct state_token_st *p)
{
{
  if (p == NULL)
  if (p == NULL)
    return STOK_NONE;
    return STOK_NONE;
  else
  else
    return p->stok_kind;
    return p->stok_kind;
}
}
 
 
/* Test if a token is a given name i.e. an identifier.  */
/* Test if a token is a given name i.e. an identifier.  */
static inline bool
static inline bool
state_token_is_name (struct state_token_st *p, const char *name)
state_token_is_name (struct state_token_st *p, const char *name)
{
{
  if (p == NULL)
  if (p == NULL)
    return false;
    return false;
 
 
  if (p->stok_kind != STOK_NAME)
  if (p->stok_kind != STOK_NAME)
    return false;
    return false;
 
 
  return !strcmp (p->stok_un.stok_ident->stid_name, name);
  return !strcmp (p->stok_un.stok_ident->stid_name, name);
}
}
 
 
 
 
/* Following routines are useful for serializing datas.
/* Following routines are useful for serializing datas.
 *
 *
 * We want to serialize :
 * We want to serialize :
 *          - typedefs list
 *          - typedefs list
 *          - structures list
 *          - structures list
 *          - param_structs list
 *          - param_structs list
 *          - variables list
 *          - variables list
 *
 *
 * So, we have one routine for each kind of data.  The main writing
 * So, we have one routine for each kind of data.  The main writing
 * routine is write_state.  The main reading routine is
 * routine is write_state.  The main reading routine is
 * read_state.  Most writing routines write_state_FOO have a
 * read_state.  Most writing routines write_state_FOO have a
 * corresponding reading routine read_state_FOO.  Reading is done in a
 * corresponding reading routine read_state_FOO.  Reading is done in a
 * recursive descending way, and any read error is fatal.
 * recursive descending way, and any read error is fatal.
 */
 */
 
 
/* When reading the state, we need to remember the previously seen
/* When reading the state, we need to remember the previously seen
   types by their state_number, since GTY-ed types are usually
   types by their state_number, since GTY-ed types are usually
   shared.  */
   shared.  */
static htab_t state_seen_types;
static htab_t state_seen_types;
 
 
/* Return the length of a linked list made of pairs.  */
/* Return the length of a linked list made of pairs.  */
static int pair_list_length (pair_p list);
static int pair_list_length (pair_p list);
 
 
/* Write a pair */
/* Write a pair */
static void write_state_pair (pair_p);
static void write_state_pair (pair_p);
 
 
/* return the number of pairs written.  Should match the length given
/* return the number of pairs written.  Should match the length given
   by pair_list_length.  */
   by pair_list_length.  */
static int write_state_pair_list (pair_p list);
static int write_state_pair_list (pair_p list);
 
 
/* Write a type.  When a type is written, its state_number is updated,
/* Write a type.  When a type is written, its state_number is updated,
   to ensure that a "reference" to a seen type is written on next
   to ensure that a "reference" to a seen type is written on next
   occurrences.  */
   occurrences.  */
static void write_state_type (type_p);
static void write_state_type (type_p);
 
 
/* Write a null-terminatel string using our Lispy lexical conventions,
/* Write a null-terminatel string using our Lispy lexical conventions,
   similar to those of C or MELT.  */
   similar to those of C or MELT.  */
static void write_state_a_string (const char *s);
static void write_state_a_string (const char *s);
 
 
/* Compute the length of a list of pairs, starting from the first
/* Compute the length of a list of pairs, starting from the first
   one.  */
   one.  */
static int
static int
pair_list_length (pair_p list)
pair_list_length (pair_p list)
{
{
  int nbpair = 0;
  int nbpair = 0;
  pair_p l = NULL;
  pair_p l = NULL;
  for (l = list; l; l = l->next)
  for (l = list; l; l = l->next)
    nbpair++;
    nbpair++;
  return nbpair;
  return nbpair;
}
}
 
 
/* Write a file location.  Files relative to $(srcdir) are quite
/* Write a file location.  Files relative to $(srcdir) are quite
   frequent and are handled specially.  This ensures that two gengtype
   frequent and are handled specially.  This ensures that two gengtype
   state file-s produced by gengtype on the same GCC source tree are
   state file-s produced by gengtype on the same GCC source tree are
   very similar and can be reasonably compared with diff, even if the
   very similar and can be reasonably compared with diff, even if the
   two GCC source trees have different absolute paths.  */
   two GCC source trees have different absolute paths.  */
static void
static void
write_state_fileloc (struct fileloc *floc)
write_state_fileloc (struct fileloc *floc)
{
{
 
 
  if (floc != NULL && floc->line > 0)
  if (floc != NULL && floc->line > 0)
    {
    {
      const char *srcrelpath = NULL;
      const char *srcrelpath = NULL;
      gcc_assert (floc->file != NULL);
      gcc_assert (floc->file != NULL);
      /* Most of the files are inside $(srcdir) so it is worth to
      /* Most of the files are inside $(srcdir) so it is worth to
         handle them specially.  */
         handle them specially.  */
      srcrelpath = get_file_srcdir_relative_path (floc->file);
      srcrelpath = get_file_srcdir_relative_path (floc->file);
      if (srcrelpath != NULL)
      if (srcrelpath != NULL)
        {
        {
          fprintf (state_file, "\n(!srcfileloc ");
          fprintf (state_file, "\n(!srcfileloc ");
          write_state_a_string (srcrelpath);
          write_state_a_string (srcrelpath);
        }
        }
      else
      else
        {
        {
          fprintf (state_file, "\n(!fileloc ");
          fprintf (state_file, "\n(!fileloc ");
          write_state_a_string (get_input_file_name (floc->file));
          write_state_a_string (get_input_file_name (floc->file));
        }
        }
      fprintf (state_file, " %d", floc->line);
      fprintf (state_file, " %d", floc->line);
      fprintf (state_file, ")\n");
      fprintf (state_file, ")\n");
    }
    }
  else
  else
    fprintf (state_file, "nil ");
    fprintf (state_file, "nil ");
}
}
 
 
/* Write a list of fields.  */
/* Write a list of fields.  */
static void
static void
write_state_fields (pair_p fields)
write_state_fields (pair_p fields)
{
{
  int nbfields = pair_list_length (fields);
  int nbfields = pair_list_length (fields);
  int nbpairs = 0;
  int nbpairs = 0;
  fprintf (state_file, "\n(!fields %d ", nbfields);
  fprintf (state_file, "\n(!fields %d ", nbfields);
  nbpairs = write_state_pair_list (fields);
  nbpairs = write_state_pair_list (fields);
  gcc_assert (nbpairs == nbfields);
  gcc_assert (nbpairs == nbfields);
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
/* Write a null-terminated string in our lexical convention, very
/* Write a null-terminated string in our lexical convention, very
   similar to the convention of C.  */
   similar to the convention of C.  */
static void
static void
write_state_a_string (const char *s)
write_state_a_string (const char *s)
{
{
  char c;
  char c;
 
 
  fputs (" \"", state_file);
  fputs (" \"", state_file);
  for (; *s != 0; s++)
  for (; *s != 0; s++)
    {
    {
      c = *s;
      c = *s;
      switch (c)
      switch (c)
        {
        {
        case '\a':
        case '\a':
          fputs ("\\a", state_file);
          fputs ("\\a", state_file);
          break;
          break;
        case '\b':
        case '\b':
          fputs ("\\b", state_file);
          fputs ("\\b", state_file);
          break;
          break;
        case '\t':
        case '\t':
          fputs ("\\t", state_file);
          fputs ("\\t", state_file);
          break;
          break;
        case '\n':
        case '\n':
          fputs ("\\n", state_file);
          fputs ("\\n", state_file);
          break;
          break;
        case '\v':
        case '\v':
          fputs ("\\v", state_file);
          fputs ("\\v", state_file);
          break;
          break;
        case '\f':
        case '\f':
          fputs ("\\f", state_file);
          fputs ("\\f", state_file);
          break;
          break;
        case '\r':
        case '\r':
          fputs ("\\r", state_file);
          fputs ("\\r", state_file);
          break;
          break;
        case '\"':
        case '\"':
          fputs ("\\\"", state_file);
          fputs ("\\\"", state_file);
          break;
          break;
        case '\\':
        case '\\':
          fputs ("\\\\", state_file);
          fputs ("\\\\", state_file);
          break;
          break;
        default:
        default:
          if (ISPRINT (c))
          if (ISPRINT (c))
            putc (c, state_file);
            putc (c, state_file);
          else
          else
            fprintf (state_file, "\\x%02x", (unsigned) c);
            fprintf (state_file, "\\x%02x", (unsigned) c);
        }
        }
    }
    }
  fputs ("\"", state_file);
  fputs ("\"", state_file);
}
}
 
 
/* Our option-s have three kinds, each with its writer.  */
/* Our option-s have three kinds, each with its writer.  */
static void
static void
write_state_string_option (options_p current)
write_state_string_option (options_p current)
{
{
  fprintf (state_file, "string ");
  fprintf (state_file, "string ");
  if (current->info.string != NULL)
  if (current->info.string != NULL)
    write_state_a_string (current->info.string);
    write_state_a_string (current->info.string);
  else
  else
    fprintf (state_file, " nil ");
    fprintf (state_file, " nil ");
}
}
 
 
static void
static void
write_state_type_option (options_p current)
write_state_type_option (options_p current)
{
{
  fprintf (state_file, "type ");
  fprintf (state_file, "type ");
  write_state_type (current->info.type);
  write_state_type (current->info.type);
}
}
 
 
static void
static void
write_state_nested_option (options_p current)
write_state_nested_option (options_p current)
{
{
  fprintf (state_file, "nested ");
  fprintf (state_file, "nested ");
  write_state_type (current->info.nested->type);
  write_state_type (current->info.nested->type);
  if (current->info.nested->convert_from != NULL)
  if (current->info.nested->convert_from != NULL)
    write_state_a_string (current->info.nested->convert_from);
    write_state_a_string (current->info.nested->convert_from);
  else
  else
    fprintf (state_file, " nil ");
    fprintf (state_file, " nil ");
 
 
  if (current->info.nested->convert_to != NULL)
  if (current->info.nested->convert_to != NULL)
    write_state_a_string (current->info.nested->convert_to);
    write_state_a_string (current->info.nested->convert_to);
  else
  else
    fprintf (state_file, " nil ");
    fprintf (state_file, " nil ");
}
}
 
 
static void
static void
write_state_option (options_p current)
write_state_option (options_p current)
{
{
  fprintf (state_file, "\n(!option ");
  fprintf (state_file, "\n(!option ");
 
 
  if (current->name != NULL)
  if (current->name != NULL)
    fprintf (state_file, "%s ", current->name);
    fprintf (state_file, "%s ", current->name);
  else
  else
    fprintf (state_file, "nil ");
    fprintf (state_file, "nil ");
 
 
  switch (current->kind)
  switch (current->kind)
    {
    {
    case OPTION_STRING:
    case OPTION_STRING:
      write_state_string_option (current);
      write_state_string_option (current);
      break;
      break;
    case OPTION_TYPE:
    case OPTION_TYPE:
      write_state_type_option (current);
      write_state_type_option (current);
      break;
      break;
    case OPTION_NESTED:
    case OPTION_NESTED:
      write_state_nested_option (current);
      write_state_nested_option (current);
      break;
      break;
    default:
    default:
      fatal ("Option tag unknown");
      fatal ("Option tag unknown");
    }
    }
 
 
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
 
 
 
 
/* Write a list of GTY options.  */
/* Write a list of GTY options.  */
static void
static void
write_state_options (options_p opt)
write_state_options (options_p opt)
{
{
  options_p current;
  options_p current;
 
 
  if (opt == NULL)
  if (opt == NULL)
    {
    {
      fprintf (state_file, "nil ");
      fprintf (state_file, "nil ");
      return;
      return;
    }
    }
 
 
  fprintf (state_file, "\n(!options ");
  fprintf (state_file, "\n(!options ");
  for (current = opt; current != NULL; current = current->next)
  for (current = opt; current != NULL; current = current->next)
      write_state_option (current);
      write_state_option (current);
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
 
 
/* Write a bitmap representing a set of GCC front-end languages.  */
/* Write a bitmap representing a set of GCC front-end languages.  */
static void
static void
write_state_lang_bitmap (lang_bitmap bitmap)
write_state_lang_bitmap (lang_bitmap bitmap)
{
{
  fprintf (state_file, "%d ", (int) bitmap);
  fprintf (state_file, "%d ", (int) bitmap);
}
}
 
 
/* Write version information.  */
/* Write version information.  */
static void
static void
write_state_version (const char *version)
write_state_version (const char *version)
{
{
  fprintf (state_file, "\n(!version ");
  fprintf (state_file, "\n(!version ");
  write_state_a_string (version);
  write_state_a_string (version);
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
/* Common routine to write the common content of all types.  */
/* Common routine to write the common content of all types.  */
static void write_state_common_type_content (type_p current);
static void write_state_common_type_content (type_p current);
 
 
/* Write a scalar type.  We have only two of these.  */
/* Write a scalar type.  We have only two of these.  */
static void
static void
write_state_scalar_type (type_p current)
write_state_scalar_type (type_p current)
{
{
  if (current == &scalar_nonchar)
  if (current == &scalar_nonchar)
    fprintf (state_file, "scalar_nonchar ");
    fprintf (state_file, "scalar_nonchar ");
  else if (current == &scalar_char)
  else if (current == &scalar_char)
    fprintf (state_file, "scalar_char ");
    fprintf (state_file, "scalar_char ");
  else
  else
    fatal ("Unexpected type in write_state_scalar_type");
    fatal ("Unexpected type in write_state_scalar_type");
 
 
  write_state_common_type_content (current);
  write_state_common_type_content (current);
}
}
 
 
/* Write the string type.  There is only one such thing! */
/* Write the string type.  There is only one such thing! */
static void
static void
write_state_string_type (type_p current)
write_state_string_type (type_p current)
{
{
  if (current == &string_type)
  if (current == &string_type)
    {
    {
      fprintf (state_file, "string ");
      fprintf (state_file, "string ");
      write_state_common_type_content (current);
      write_state_common_type_content (current);
    }
    }
  else
  else
    fatal ("Unexpected type in write_state_string_type");
    fatal ("Unexpected type in write_state_string_type");
}
}
 
 
 
 
/* Common code to write structure like types.  */
/* Common code to write structure like types.  */
static void
static void
write_state_struct_union_type (type_p current, const char *kindstr)
write_state_struct_union_type (type_p current, const char *kindstr)
{
{
  DBGPRINTF ("%s type @ %p #%d '%s'", kindstr, (void *) current,
  DBGPRINTF ("%s type @ %p #%d '%s'", kindstr, (void *) current,
             current->state_number, current->u.s.tag);
             current->state_number, current->u.s.tag);
  fprintf (state_file, "%s ", kindstr);
  fprintf (state_file, "%s ", kindstr);
  write_state_common_type_content (current);
  write_state_common_type_content (current);
  if (current->u.s.tag != NULL)
  if (current->u.s.tag != NULL)
    write_state_a_string (current->u.s.tag);
    write_state_a_string (current->u.s.tag);
  else
  else
    fprintf (state_file, "nil");
    fprintf (state_file, "nil");
 
 
  write_state_fileloc (type_lineloc (current));
  write_state_fileloc (type_lineloc (current));
  write_state_fields (current->u.s.fields);
  write_state_fields (current->u.s.fields);
  write_state_options (current->u.s.opt);
  write_state_options (current->u.s.opt);
  write_state_lang_bitmap (current->u.s.bitmap);
  write_state_lang_bitmap (current->u.s.bitmap);
}
}
 
 
 
 
/* Write a GTY struct type.  */
/* Write a GTY struct type.  */
static void
static void
write_state_struct_type (type_p current)
write_state_struct_type (type_p current)
{
{
  write_state_struct_union_type (current, "struct");
  write_state_struct_union_type (current, "struct");
  write_state_type (current->u.s.lang_struct);
  write_state_type (current->u.s.lang_struct);
}
}
 
 
/* write a GTY union type.  */
/* write a GTY union type.  */
static void
static void
write_state_union_type (type_p current)
write_state_union_type (type_p current)
{
{
  write_state_struct_union_type (current, "union");
  write_state_struct_union_type (current, "union");
  write_state_type (current->u.s.lang_struct);
  write_state_type (current->u.s.lang_struct);
}
}
 
 
/* Write a lang_struct type.  This is tricky and was painful to debug,
/* Write a lang_struct type.  This is tricky and was painful to debug,
   we deal with the next field specifically within their lang_struct
   we deal with the next field specifically within their lang_struct
   subfield, which points to a linked list of homonumous types.
   subfield, which points to a linked list of homonumous types.
   Change this function with extreme care, see also
   Change this function with extreme care, see also
   read_state_lang_struct_type.  */
   read_state_lang_struct_type.  */
static void
static void
write_state_lang_struct_type (type_p current)
write_state_lang_struct_type (type_p current)
{
{
  int nbhomontype = 0;
  int nbhomontype = 0;
  type_p hty = NULL;
  type_p hty = NULL;
  const char *homoname = 0;
  const char *homoname = 0;
  write_state_struct_union_type (current, "lang_struct");
  write_state_struct_union_type (current, "lang_struct");
  /* lang_struct-ures are particularily tricky, since their
  /* lang_struct-ures are particularily tricky, since their
     u.s.lang_struct field gives a list of homonymous struct-s or
     u.s.lang_struct field gives a list of homonymous struct-s or
     union-s! */
     union-s! */
  DBGPRINTF ("lang_struct @ %p #%d", (void *) current, current->state_number);
  DBGPRINTF ("lang_struct @ %p #%d", (void *) current, current->state_number);
  for (hty = current->u.s.lang_struct; hty != NULL; hty = hty->next)
  for (hty = current->u.s.lang_struct; hty != NULL; hty = hty->next)
    {
    {
      nbhomontype++;
      nbhomontype++;
      DBGPRINTF ("homonymous #%d hty @ %p #%d '%s'", nbhomontype,
      DBGPRINTF ("homonymous #%d hty @ %p #%d '%s'", nbhomontype,
                 (void *) hty, hty->state_number, hty->u.s.tag);
                 (void *) hty, hty->state_number, hty->u.s.tag);
      /* Every member of the homonymous list should have the same tag.  */
      /* Every member of the homonymous list should have the same tag.  */
      gcc_assert (UNION_OR_STRUCT_P (hty));
      gcc_assert (UNION_OR_STRUCT_P (hty));
      gcc_assert (hty->u.s.lang_struct == current);
      gcc_assert (hty->u.s.lang_struct == current);
      if (!homoname)
      if (!homoname)
        homoname = hty->u.s.tag;
        homoname = hty->u.s.tag;
      gcc_assert (strcmp (homoname, hty->u.s.tag) == 0);
      gcc_assert (strcmp (homoname, hty->u.s.tag) == 0);
    }
    }
  fprintf (state_file, "(!homotypes %d\n", nbhomontype);
  fprintf (state_file, "(!homotypes %d\n", nbhomontype);
  for (hty = current->u.s.lang_struct; hty != NULL; hty = hty->next)
  for (hty = current->u.s.lang_struct; hty != NULL; hty = hty->next)
    write_state_type (hty);
    write_state_type (hty);
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
/* Write a parametrized structure GTY type.  */
/* Write a parametrized structure GTY type.  */
static void
static void
write_state_param_struct_type (type_p current)
write_state_param_struct_type (type_p current)
{
{
  int i;
  int i;
 
 
  fprintf (state_file, "param_struct ");
  fprintf (state_file, "param_struct ");
  write_state_common_type_content (current);
  write_state_common_type_content (current);
  write_state_type (current->u.param_struct.stru);
  write_state_type (current->u.param_struct.stru);
  for (i = 0; i < NUM_PARAM; i++)
  for (i = 0; i < NUM_PARAM; i++)
    {
    {
      if (current->u.param_struct.param[i] != NULL)
      if (current->u.param_struct.param[i] != NULL)
        write_state_type (current->u.param_struct.param[i]);
        write_state_type (current->u.param_struct.param[i]);
      else
      else
        fprintf (state_file, "nil ");
        fprintf (state_file, "nil ");
    }
    }
  write_state_fileloc (&current->u.param_struct.line);
  write_state_fileloc (&current->u.param_struct.line);
}
}
 
 
/* Write a pointer type.  */
/* Write a pointer type.  */
static void
static void
write_state_pointer_type (type_p current)
write_state_pointer_type (type_p current)
{
{
  fprintf (state_file, "pointer ");
  fprintf (state_file, "pointer ");
  write_state_common_type_content (current);
  write_state_common_type_content (current);
  write_state_type (current->u.p);
  write_state_type (current->u.p);
}
}
 
 
/* Write an array type.  */
/* Write an array type.  */
static void
static void
write_state_array_type (type_p current)
write_state_array_type (type_p current)
{
{
  fprintf (state_file, "array ");
  fprintf (state_file, "array ");
  write_state_common_type_content (current);
  write_state_common_type_content (current);
  if (current->u.a.len != NULL)
  if (current->u.a.len != NULL)
    write_state_a_string (current->u.a.len);
    write_state_a_string (current->u.a.len);
  else
  else
    fprintf (state_file, " nil");
    fprintf (state_file, " nil");
 
 
  fprintf (state_file, " ");
  fprintf (state_file, " ");
  write_state_type (current->u.a.p);
  write_state_type (current->u.a.p);
}
}
 
 
/* Write the gc_used information.  */
/* Write the gc_used information.  */
static void
static void
write_state_gc_used (enum gc_used_enum gus)
write_state_gc_used (enum gc_used_enum gus)
{
{
  switch (gus)
  switch (gus)
    {
    {
    case GC_UNUSED:
    case GC_UNUSED:
      fprintf (state_file, " gc_unused");
      fprintf (state_file, " gc_unused");
      break;
      break;
    case GC_USED:
    case GC_USED:
      fprintf (state_file, " gc_used");
      fprintf (state_file, " gc_used");
      break;
      break;
    case GC_MAYBE_POINTED_TO:
    case GC_MAYBE_POINTED_TO:
      fprintf (state_file, " gc_maybe_pointed_to");
      fprintf (state_file, " gc_maybe_pointed_to");
      break;
      break;
    case GC_POINTED_TO:
    case GC_POINTED_TO:
      fprintf (state_file, " gc_pointed_to");
      fprintf (state_file, " gc_pointed_to");
      break;
      break;
    default:
    default:
      gcc_unreachable ();
      gcc_unreachable ();
    }
    }
}
}
 
 
/* Utility routine to write the common content of all types.  Notice
/* Utility routine to write the common content of all types.  Notice
   that the next field is *not* written on purpose.  */
   that the next field is *not* written on purpose.  */
static void
static void
write_state_common_type_content (type_p current)
write_state_common_type_content (type_p current)
{
{
  fprintf (state_file, "%d ", current->state_number);
  fprintf (state_file, "%d ", current->state_number);
  /* We do not write the next type, because list of types are
  /* We do not write the next type, because list of types are
     explicitly written.  However, lang_struct are special in that
     explicitly written.  However, lang_struct are special in that
     respect.  See function write_state_lang_struct_type for more.  */
     respect.  See function write_state_lang_struct_type for more.  */
  write_state_type (current->pointer_to);
  write_state_type (current->pointer_to);
  write_state_gc_used (current->gc_used);
  write_state_gc_used (current->gc_used);
}
}
 
 
 
 
/* The important and recursive routine writing GTY types as understood
/* The important and recursive routine writing GTY types as understood
   by gengtype.  Types which have a positive state_number have already
   by gengtype.  Types which have a positive state_number have already
   been seen and written.  */
   been seen and written.  */
static void
static void
write_state_type (type_p current)
write_state_type (type_p current)
{
{
  if (current == NULL)
  if (current == NULL)
    {
    {
      fprintf (state_file, "nil ");
      fprintf (state_file, "nil ");
      return;
      return;
    }
    }
 
 
  fprintf (state_file, "\n(!type ");
  fprintf (state_file, "\n(!type ");
 
 
  if (current->state_number > 0)
  if (current->state_number > 0)
    fprintf (state_file, "already_seen %d", current->state_number);
    fprintf (state_file, "already_seen %d", current->state_number);
  else
  else
    {
    {
      state_written_type_count++;
      state_written_type_count++;
      DBGPRINTF ("writing type #%d @%p old number %d", state_written_type_count,
      DBGPRINTF ("writing type #%d @%p old number %d", state_written_type_count,
                 (void *) current, current->state_number);
                 (void *) current, current->state_number);
      current->state_number = state_written_type_count;
      current->state_number = state_written_type_count;
      switch (current->kind)
      switch (current->kind)
        {
        {
        case TYPE_STRUCT:
        case TYPE_STRUCT:
          write_state_struct_type (current);
          write_state_struct_type (current);
          break;
          break;
        case TYPE_UNION:
        case TYPE_UNION:
          write_state_union_type (current);
          write_state_union_type (current);
          break;
          break;
        case TYPE_POINTER:
        case TYPE_POINTER:
          write_state_pointer_type (current);
          write_state_pointer_type (current);
          break;
          break;
        case TYPE_ARRAY:
        case TYPE_ARRAY:
          write_state_array_type (current);
          write_state_array_type (current);
          break;
          break;
        case TYPE_LANG_STRUCT:
        case TYPE_LANG_STRUCT:
          write_state_lang_struct_type (current);
          write_state_lang_struct_type (current);
          break;
          break;
        case TYPE_PARAM_STRUCT:
        case TYPE_PARAM_STRUCT:
          write_state_param_struct_type (current);
          write_state_param_struct_type (current);
          break;
          break;
        case TYPE_SCALAR:
        case TYPE_SCALAR:
          write_state_scalar_type (current);
          write_state_scalar_type (current);
          break;
          break;
        case TYPE_STRING:
        case TYPE_STRING:
          write_state_string_type (current);
          write_state_string_type (current);
          break;
          break;
 
 
        default:
        default:
          fatal ("Unexpected type...");
          fatal ("Unexpected type...");
        }
        }
    }
    }
 
 
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
 
 
/* Write a pair.  */
/* Write a pair.  */
static void
static void
write_state_pair (pair_p current)
write_state_pair (pair_p current)
{
{
  if (current == NULL)
  if (current == NULL)
    {
    {
      fprintf (state_file, "nil)");
      fprintf (state_file, "nil)");
      return;
      return;
    }
    }
 
 
  fprintf (state_file, "\n(!pair ");
  fprintf (state_file, "\n(!pair ");
 
 
  if (current->name != NULL)
  if (current->name != NULL)
    write_state_a_string (current->name);
    write_state_a_string (current->name);
  else
  else
    write_state_a_string ("nil");
    write_state_a_string ("nil");
 
 
  write_state_type (current->type);
  write_state_type (current->type);
  write_state_fileloc (&(current->line));
  write_state_fileloc (&(current->line));
  write_state_options (current->opt);
  write_state_options (current->opt);
 
 
  fprintf (state_file, ")");
  fprintf (state_file, ")");
}
}
 
 
/* Write a pair list and return the number of pairs written.  */
/* Write a pair list and return the number of pairs written.  */
static int
static int
write_state_pair_list (pair_p list)
write_state_pair_list (pair_p list)
{
{
  int nbpair = 0;
  int nbpair = 0;
  pair_p current;
  pair_p current;
 
 
  for (current = list; current != NULL; current = current->next)
  for (current = list; current != NULL; current = current->next)
    {
    {
      write_state_pair (current);
      write_state_pair (current);
      nbpair++;
      nbpair++;
    }
    }
  return nbpair;
  return nbpair;
 
 
}
}
 
 
/* When writing imported linked lists, like typedefs, structures,
/* When writing imported linked lists, like typedefs, structures,
   param_structs, ... we count their length first and write it.  These
   param_structs, ... we count their length first and write it.  These
   eases the reading, and enables an extra verification on the number
   eases the reading, and enables an extra verification on the number
   of actually read items.  */
   of actually read items.  */
 
 
/* Write our typedefs.  */
/* Write our typedefs.  */
static void
static void
write_state_typedefs (void)
write_state_typedefs (void)
{
{
  int nbtypedefs = pair_list_length (typedefs);
  int nbtypedefs = pair_list_length (typedefs);
  int nbpairs = 0;
  int nbpairs = 0;
  fprintf (state_file, "\n(!typedefs %d\n", nbtypedefs);
  fprintf (state_file, "\n(!typedefs %d\n", nbtypedefs);
  nbpairs = write_state_pair_list (typedefs);
  nbpairs = write_state_pair_list (typedefs);
  gcc_assert (nbpairs == nbtypedefs);
  gcc_assert (nbpairs == nbtypedefs);
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
  if (verbosity_level >= 2)
  if (verbosity_level >= 2)
    printf ("%s wrote %d typedefs\n", progname, nbtypedefs);
    printf ("%s wrote %d typedefs\n", progname, nbtypedefs);
}
}
 
 
/* Write our structures.  */
/* Write our structures.  */
static void
static void
write_state_structures (void)
write_state_structures (void)
{
{
  int nbstruct = 0;
  int nbstruct = 0;
  type_p current;
  type_p current;
 
 
  for (current = structures; current != NULL; current = current->next)
  for (current = structures; current != NULL; current = current->next)
    nbstruct++;
    nbstruct++;
 
 
  fprintf (state_file, "\n(!structures %d\n", nbstruct);
  fprintf (state_file, "\n(!structures %d\n", nbstruct);
 
 
  for (current = structures; current != NULL; current = current->next)
  for (current = structures; current != NULL; current = current->next)
    write_state_type (current);
    write_state_type (current);
 
 
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
  if (verbosity_level >= 2)
  if (verbosity_level >= 2)
    printf ("%s wrote %d structures in state\n", progname, nbstruct);
    printf ("%s wrote %d structures in state\n", progname, nbstruct);
}
}
 
 
/* Write our param_struct-s.  */
/* Write our param_struct-s.  */
static void
static void
write_state_param_structs (void)
write_state_param_structs (void)
{
{
  int nbparamstruct = 0;
  int nbparamstruct = 0;
  type_p current;
  type_p current;
 
 
  for (current = param_structs; current != NULL; current = current->next)
  for (current = param_structs; current != NULL; current = current->next)
    nbparamstruct++;
    nbparamstruct++;
 
 
  fprintf (state_file, "\n(!param_structs %d\n", nbparamstruct);
  fprintf (state_file, "\n(!param_structs %d\n", nbparamstruct);
 
 
  for (current = param_structs; current != NULL; current = current->next)
  for (current = param_structs; current != NULL; current = current->next)
    write_state_type (current);
    write_state_type (current);
 
 
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
/* Write our variables.  */
/* Write our variables.  */
static void
static void
write_state_variables (void)
write_state_variables (void)
{
{
  int nbvars = pair_list_length (variables);
  int nbvars = pair_list_length (variables);
  int nbpairs = 0;
  int nbpairs = 0;
  fprintf (state_file, "\n(!variables %d\n", nbvars);
  fprintf (state_file, "\n(!variables %d\n", nbvars);
  nbpairs = write_state_pair_list (variables);
  nbpairs = write_state_pair_list (variables);
  gcc_assert (nbpairs == nbvars);
  gcc_assert (nbpairs == nbvars);
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
  if (verbosity_level >= 2)
  if (verbosity_level >= 2)
    printf ("%s wrote %d variables.\n", progname, nbvars);
    printf ("%s wrote %d variables.\n", progname, nbvars);
}
}
 
 
/* Write the source directory.  File locations within the source
/* Write the source directory.  File locations within the source
   directory have been written specifically.  */
   directory have been written specifically.  */
static void
static void
write_state_srcdir (void)
write_state_srcdir (void)
{
{
  fprintf (state_file, "\n(!srcdir ");
  fprintf (state_file, "\n(!srcdir ");
  write_state_a_string (srcdir);
  write_state_a_string (srcdir);
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
/* Count and write the list of our files.  */
/* Count and write the list of our files.  */
static void
static void
write_state_files_list (void)
write_state_files_list (void)
{
{
  int i = 0;
  int i = 0;
  /* Write the list of files with their lang_bitmap.  */
  /* Write the list of files with their lang_bitmap.  */
  fprintf (state_file, "\n(!fileslist %d\n", (int) num_gt_files);
  fprintf (state_file, "\n(!fileslist %d\n", (int) num_gt_files);
  for (i = 0; i < (int) num_gt_files; i++)
  for (i = 0; i < (int) num_gt_files; i++)
    {
    {
      const char *cursrcrelpath = NULL;
      const char *cursrcrelpath = NULL;
      const input_file *curfil = gt_files[i];
      const input_file *curfil = gt_files[i];
      /* Most of the files are inside $(srcdir) so it is worth to
      /* Most of the files are inside $(srcdir) so it is worth to
         handle them specially.  */
         handle them specially.  */
      cursrcrelpath = get_file_srcdir_relative_path (curfil);
      cursrcrelpath = get_file_srcdir_relative_path (curfil);
      if (cursrcrelpath)
      if (cursrcrelpath)
        {
        {
          fprintf (state_file, "(!srcfile %d ", get_lang_bitmap (curfil));
          fprintf (state_file, "(!srcfile %d ", get_lang_bitmap (curfil));
          write_state_a_string (cursrcrelpath);
          write_state_a_string (cursrcrelpath);
        }
        }
      else
      else
        {
        {
          fprintf (state_file, "(!file %d ", get_lang_bitmap (curfil));
          fprintf (state_file, "(!file %d ", get_lang_bitmap (curfil));
          write_state_a_string (get_input_file_name (curfil));
          write_state_a_string (get_input_file_name (curfil));
        }
        }
      fprintf (state_file, ")\n");
      fprintf (state_file, ")\n");
    }
    }
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
/* Write the list of GCC front-end languages.  */
/* Write the list of GCC front-end languages.  */
static void
static void
write_state_languages (void)
write_state_languages (void)
{
{
  int i = 0;
  int i = 0;
  fprintf (state_file, "\n(!languages %d", (int) num_lang_dirs);
  fprintf (state_file, "\n(!languages %d", (int) num_lang_dirs);
  for (i = 0; i < (int) num_lang_dirs; i++)
  for (i = 0; i < (int) num_lang_dirs; i++)
    {
    {
      /* Languages names are identifiers, we expect only letters or
      /* Languages names are identifiers, we expect only letters or
         underscores or digits in them.  In particular, C++ is not a
         underscores or digits in them.  In particular, C++ is not a
         valid language name, but cp is valid.  */
         valid language name, but cp is valid.  */
      fprintf (state_file, " %s", lang_dir_names[i]);
      fprintf (state_file, " %s", lang_dir_names[i]);
    }
    }
  fprintf (state_file, ")\n");
  fprintf (state_file, ")\n");
}
}
 
 
/* Write the trailer.  */
/* Write the trailer.  */
static void
static void
write_state_trailer (void)
write_state_trailer (void)
{
{
  /* This test should probably catch IO errors like disk full...  */
  /* This test should probably catch IO errors like disk full...  */
  if (fputs ("\n(!endfile)\n", state_file) == EOF)
  if (fputs ("\n(!endfile)\n", state_file) == EOF)
    fatal ("failed to write state trailer [%s]", xstrerror (errno));
    fatal ("failed to write state trailer [%s]", xstrerror (errno));
}
}
 
 
/* The write_state routine is the only writing routine called by main
/* The write_state routine is the only writing routine called by main
   in gengtype.c.  To avoid messing the state if gengtype is
   in gengtype.c.  To avoid messing the state if gengtype is
   interrupted or aborted, we write a temporary file and rename it
   interrupted or aborted, we write a temporary file and rename it
   after having written it in totality.  */
   after having written it in totality.  */
void
void
write_state (const char *state_path)
write_state (const char *state_path)
{
{
  long statelen = 0;
  long statelen = 0;
  time_t now = 0;
  time_t now = 0;
  char *temp_state_path = NULL;
  char *temp_state_path = NULL;
  char tempsuffix[40];
  char tempsuffix[40];
  time (&now);
  time (&now);
 
 
  /* We write a unique temporary file which is renamed when complete
  /* We write a unique temporary file which is renamed when complete
   * only.  So even if gengtype is interrupted, the written state file
   * only.  So even if gengtype is interrupted, the written state file
   * won't be partially written, since the temporary file is not yet
   * won't be partially written, since the temporary file is not yet
   * renamed in that case.  */
   * renamed in that case.  */
  memset (tempsuffix, 0, sizeof (tempsuffix));
  memset (tempsuffix, 0, sizeof (tempsuffix));
  snprintf (tempsuffix, sizeof (tempsuffix) - 1, "-%ld-%d.tmp", (long) now,
  snprintf (tempsuffix, sizeof (tempsuffix) - 1, "-%ld-%d.tmp", (long) now,
            (int) getpid ());
            (int) getpid ());
  temp_state_path = concat (state_path, tempsuffix, NULL);
  temp_state_path = concat (state_path, tempsuffix, NULL);
  state_file = fopen (temp_state_path, "w");
  state_file = fopen (temp_state_path, "w");
  if (state_file == NULL)
  if (state_file == NULL)
    fatal ("Failed to open file %s for writing state: %s",
    fatal ("Failed to open file %s for writing state: %s",
           temp_state_path, xstrerror (errno));
           temp_state_path, xstrerror (errno));
  if (verbosity_level >= 3)
  if (verbosity_level >= 3)
    printf ("%s writing state file %s temporarily in %s\n",
    printf ("%s writing state file %s temporarily in %s\n",
            progname, state_path, temp_state_path);
            progname, state_path, temp_state_path);
  /* This is the first line of the state.  Perhaps the file utility
  /* This is the first line of the state.  Perhaps the file utility
     could know about that, so don't change it often.  */
     could know about that, so don't change it often.  */
  fprintf (state_file, ";;;;@@@@ GCC gengtype state\n");
  fprintf (state_file, ";;;;@@@@ GCC gengtype state\n");
  /* Output a few comments for humans. */
  /* Output a few comments for humans. */
  fprintf (state_file,
  fprintf (state_file,
           ";;; DON'T EDIT THIS FILE, since generated by GCC's gengtype\n");
           ";;; DON'T EDIT THIS FILE, since generated by GCC's gengtype\n");
  fprintf (state_file,
  fprintf (state_file,
           ";;; The format of this file is tied to a particular version of GCC.\n");
           ";;; The format of this file is tied to a particular version of GCC.\n");
  fprintf (state_file,
  fprintf (state_file,
           ";;; Don't parse this file wihout knowing GCC gengtype internals.\n");
           ";;; Don't parse this file wihout knowing GCC gengtype internals.\n");
  fprintf (state_file,
  fprintf (state_file,
           ";;; This file should be parsed by the same %s which wrote it.\n",
           ";;; This file should be parsed by the same %s which wrote it.\n",
           progname);
           progname);
  /* The first non-comment significant line gives the version string.  */
  /* The first non-comment significant line gives the version string.  */
  write_state_version (version_string);
  write_state_version (version_string);
  write_state_srcdir ();
  write_state_srcdir ();
  write_state_languages ();
  write_state_languages ();
  write_state_files_list ();
  write_state_files_list ();
  write_state_structures ();
  write_state_structures ();
  write_state_typedefs ();
  write_state_typedefs ();
  write_state_param_structs ();
  write_state_param_structs ();
  write_state_variables ();
  write_state_variables ();
  write_state_trailer ();
  write_state_trailer ();
  statelen = ftell (state_file);
  statelen = ftell (state_file);
  if (ferror (state_file))
  if (ferror (state_file))
    fatal ("output error when writing state file %s [%s]",
    fatal ("output error when writing state file %s [%s]",
           temp_state_path, xstrerror (errno));
           temp_state_path, xstrerror (errno));
  if (fclose (state_file))
  if (fclose (state_file))
    fatal ("failed to close state file %s [%s]",
    fatal ("failed to close state file %s [%s]",
           temp_state_path, xstrerror (errno));
           temp_state_path, xstrerror (errno));
  if (rename (temp_state_path, state_path))
  if (rename (temp_state_path, state_path))
    fatal ("failed to rename %s to state file %s [%s]", temp_state_path,
    fatal ("failed to rename %s to state file %s [%s]", temp_state_path,
           state_path, xstrerror (errno));
           state_path, xstrerror (errno));
  free (temp_state_path);
  free (temp_state_path);
 
 
  if (verbosity_level >= 1)
  if (verbosity_level >= 1)
    printf ("%s wrote state file %s of %ld bytes with %d GTY-ed types\n",
    printf ("%s wrote state file %s of %ld bytes with %d GTY-ed types\n",
            progname, state_path, statelen, state_written_type_count);
            progname, state_path, statelen, state_written_type_count);
 
 
}
}


/** End of writing routines!  The corresponding reading routines follow.  **/
/** End of writing routines!  The corresponding reading routines follow.  **/
 
 
 
 
 
 
/* Forward declarations, since some read_state_* functions are
/* Forward declarations, since some read_state_* functions are
   recursive! */
   recursive! */
static void read_state_fileloc (struct fileloc *line);
static void read_state_fileloc (struct fileloc *line);
static void read_state_options (options_p *opt);
static void read_state_options (options_p *opt);
static void read_state_type (type_p *current);
static void read_state_type (type_p *current);
static void read_state_pair (pair_p *pair);
static void read_state_pair (pair_p *pair);
/* Return the number of pairs actually read.  */
/* Return the number of pairs actually read.  */
static int read_state_pair_list (pair_p *list);
static int read_state_pair_list (pair_p *list);
static void read_state_fields (pair_p *fields);
static void read_state_fields (pair_p *fields);
static void read_state_common_type_content (type_p current);
static void read_state_common_type_content (type_p current);
 
 
 
 
 
 
 
 
/* Record into the state_seen_types hash-table a type which we are
/* Record into the state_seen_types hash-table a type which we are
   reading, to enable recursive or circular references to it.  */
   reading, to enable recursive or circular references to it.  */
static void
static void
record_type (type_p type)
record_type (type_p type)
{
{
  PTR *slot;
  PTR *slot;
 
 
  slot = htab_find_slot (state_seen_types, type, INSERT);
  slot = htab_find_slot (state_seen_types, type, INSERT);
  gcc_assert (slot);
  gcc_assert (slot);
 
 
  *slot = type;
  *slot = type;
}
}
 
 
/* Read an already seen type.  */
/* Read an already seen type.  */
static void
static void
read_state_already_seen_type (type_p *type)
read_state_already_seen_type (type_p *type)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
 
 
  if (state_token_kind (t0) == STOK_INTEGER)
  if (state_token_kind (t0) == STOK_INTEGER)
    {
    {
      PTR *slot = NULL;
      PTR *slot = NULL;
      struct type loctype = { TYPE_SCALAR, 0, 0, 0, GC_UNUSED, {0} };
      struct type loctype = { TYPE_SCALAR, 0, 0, 0, GC_UNUSED, {0} };
 
 
      loctype.state_number = t0->stok_un.stok_num;
      loctype.state_number = t0->stok_un.stok_num;
      slot = htab_find_slot (state_seen_types, &loctype, NO_INSERT);
      slot = htab_find_slot (state_seen_types, &loctype, NO_INSERT);
      if (slot == NULL)
      if (slot == NULL)
        {
        {
          fatal_reading_state (t0, "Unknown type");
          fatal_reading_state (t0, "Unknown type");
        }
        }
 
 
      next_state_tokens (1);
      next_state_tokens (1);
      *type = (type_p) *slot;
      *type = (type_p) *slot;
    }
    }
  else
  else
    {
    {
      fatal_reading_state (t0, "Bad seen type");
      fatal_reading_state (t0, "Bad seen type");
    }
    }
}
}
 
 
 
 
/* Read the scalar_nonchar type.  */
/* Read the scalar_nonchar type.  */
static void
static void
read_state_scalar_nonchar_type (type_p *type)
read_state_scalar_nonchar_type (type_p *type)
{
{
  *type = &scalar_nonchar;
  *type = &scalar_nonchar;
  read_state_common_type_content (*type);
  read_state_common_type_content (*type);
}
}
 
 
 
 
/* Read the scalar_char type.  */
/* Read the scalar_char type.  */
static void
static void
read_state_scalar_char_type (type_p *type)
read_state_scalar_char_type (type_p *type)
{
{
  *type = &scalar_char;
  *type = &scalar_char;
  read_state_common_type_content (*type);
  read_state_common_type_content (*type);
}
}
 
 
 
 
/* Read the string_type.  */
/* Read the string_type.  */
static void
static void
read_state_string_type (type_p *type)
read_state_string_type (type_p *type)
{
{
  *type = &string_type;
  *type = &string_type;
  read_state_common_type_content (*type);
  read_state_common_type_content (*type);
}
}
 
 
 
 
/* Read a lang_bitmap representing a set of GCC front-end languages.  */
/* Read a lang_bitmap representing a set of GCC front-end languages.  */
static void
static void
read_state_lang_bitmap (lang_bitmap *bitmap)
read_state_lang_bitmap (lang_bitmap *bitmap)
{
{
  struct state_token_st *t;
  struct state_token_st *t;
 
 
  t = peek_state_token (0);
  t = peek_state_token (0);
  if (state_token_kind (t) == STOK_INTEGER)
  if (state_token_kind (t) == STOK_INTEGER)
    {
    {
      *bitmap = t->stok_un.stok_num;
      *bitmap = t->stok_un.stok_num;
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    {
    {
      fatal_reading_state (t, "Bad syntax for bitmap");
      fatal_reading_state (t, "Bad syntax for bitmap");
    }
    }
}
}
 
 
 
 
/* Read a GTY-ed struct type.  */
/* Read a GTY-ed struct type.  */
static void
static void
read_state_struct_type (type_p type)
read_state_struct_type (type_p type)
{
{
  struct state_token_st *t0;
  struct state_token_st *t0;
 
 
  type->kind = TYPE_STRUCT;
  type->kind = TYPE_STRUCT;
  read_state_common_type_content (type);
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
  if (state_token_kind (t0) == STOK_STRING)
    {
    {
      if (state_token_is_name (t0, "nil"))
      if (state_token_is_name (t0, "nil"))
        {
        {
          type->u.s.tag = NULL;
          type->u.s.tag = NULL;
          DBGPRINTF ("read anonymous struct type @%p #%d",
          DBGPRINTF ("read anonymous struct type @%p #%d",
                     (void *) type, type->state_number);
                     (void *) type, type->state_number);
        }
        }
      else
      else
        {
        {
          type->u.s.tag = xstrdup (t0->stok_un.stok_string);
          type->u.s.tag = xstrdup (t0->stok_un.stok_string);
          DBGPRINTF ("read struct type @%p #%d '%s'",
          DBGPRINTF ("read struct type @%p #%d '%s'",
                     (void *) type, type->state_number, type->u.s.tag);
                     (void *) type, type->state_number, type->u.s.tag);
        }
        }
 
 
      next_state_tokens (1);
      next_state_tokens (1);
      read_state_fileloc (&(type->u.s.line));
      read_state_fileloc (&(type->u.s.line));
      read_state_fields (&(type->u.s.fields));
      read_state_fields (&(type->u.s.fields));
      read_state_options (&(type->u.s.opt));
      read_state_options (&(type->u.s.opt));
      read_state_lang_bitmap (&(type->u.s.bitmap));
      read_state_lang_bitmap (&(type->u.s.bitmap));
      read_state_type (&(type->u.s.lang_struct));
      read_state_type (&(type->u.s.lang_struct));
    }
    }
  else
  else
    {
    {
      fatal_reading_state (t0, "Bad tag in struct type");
      fatal_reading_state (t0, "Bad tag in struct type");
    }
    }
}
}
 
 
 
 
/* Read a GTY-ed union type.  */
/* Read a GTY-ed union type.  */
static void
static void
read_state_union_type (type_p type)
read_state_union_type (type_p type)
{
{
  struct state_token_st *t0;
  struct state_token_st *t0;
 
 
  type->kind = TYPE_UNION;
  type->kind = TYPE_UNION;
  read_state_common_type_content (type);
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
  if (state_token_kind (t0) == STOK_STRING)
    {
    {
      if (state_token_is_name (t0, "nil"))
      if (state_token_is_name (t0, "nil"))
        {
        {
          type->u.s.tag = NULL;
          type->u.s.tag = NULL;
          DBGPRINTF ("read anonymous union type @%p #%d",
          DBGPRINTF ("read anonymous union type @%p #%d",
                     (void *) type, type->state_number);
                     (void *) type, type->state_number);
        }
        }
      else
      else
        {
        {
          type->u.s.tag = xstrdup (t0->stok_un.stok_string);
          type->u.s.tag = xstrdup (t0->stok_un.stok_string);
          DBGPRINTF ("read union type @%p #%d '%s'",
          DBGPRINTF ("read union type @%p #%d '%s'",
                     (void *) type, type->state_number, type->u.s.tag);
                     (void *) type, type->state_number, type->u.s.tag);
        }
        }
      next_state_tokens (1);
      next_state_tokens (1);
      read_state_fileloc (&(type->u.s.line));
      read_state_fileloc (&(type->u.s.line));
      read_state_fields (&(type->u.s.fields));
      read_state_fields (&(type->u.s.fields));
      read_state_options (&(type->u.s.opt));
      read_state_options (&(type->u.s.opt));
      read_state_lang_bitmap (&(type->u.s.bitmap));
      read_state_lang_bitmap (&(type->u.s.bitmap));
      read_state_type (&(type->u.s.lang_struct));
      read_state_type (&(type->u.s.lang_struct));
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad tag in union type");
    fatal_reading_state (t0, "Bad tag in union type");
}
}
 
 
 
 
/* Read a GTY-ed pointer type.  */
/* Read a GTY-ed pointer type.  */
static void
static void
read_state_pointer_type (type_p type)
read_state_pointer_type (type_p type)
{
{
  type->kind = TYPE_POINTER;
  type->kind = TYPE_POINTER;
  read_state_common_type_content (type);
  read_state_common_type_content (type);
  DBGPRINTF ("read pointer type @%p #%d", (void *) type, type->state_number);
  DBGPRINTF ("read pointer type @%p #%d", (void *) type, type->state_number);
  read_state_type (&(type->u.p));
  read_state_type (&(type->u.p));
}
}
 
 
 
 
/* Read a GTY-ed array type.  */
/* Read a GTY-ed array type.  */
static void
static void
read_state_array_type (type_p type)
read_state_array_type (type_p type)
{
{
  struct state_token_st *t0;
  struct state_token_st *t0;
 
 
  type->kind = TYPE_ARRAY;
  type->kind = TYPE_ARRAY;
  read_state_common_type_content (type);
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
  if (state_token_kind (t0) == STOK_STRING)
    {
    {
      type->u.a.len = xstrdup (t0->stok_un.stok_string);
      type->u.a.len = xstrdup (t0->stok_un.stok_string);
      DBGPRINTF ("read array type @%p #%d length '%s'",
      DBGPRINTF ("read array type @%p #%d length '%s'",
                 (void *) type, type->state_number, type->u.a.len);
                 (void *) type, type->state_number, type->u.a.len);
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
 
 
  else if (state_token_is_name (t0, "nil"))
  else if (state_token_is_name (t0, "nil"))
    {
    {
      type->u.a.len = NULL;
      type->u.a.len = NULL;
      DBGPRINTF ("read array type @%p #%d without length",
      DBGPRINTF ("read array type @%p #%d without length",
                 (void *) type, type->state_number);
                 (void *) type, type->state_number);
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
 
 
  else
  else
    fatal_reading_state (t0, "Bad array name type");
    fatal_reading_state (t0, "Bad array name type");
  read_state_type (&(type->u.a.p));
  read_state_type (&(type->u.a.p));
}
}
 
 
 
 
 
 
/* Read a lang_struct type for GTY-ed struct-s which depends upon GCC
/* Read a lang_struct type for GTY-ed struct-s which depends upon GCC
   front-end languages.  This is a tricky function and it was painful
   front-end languages.  This is a tricky function and it was painful
   to debug.  Change it with extreme care.  See also
   to debug.  Change it with extreme care.  See also
   write_state_lang_struct_type.  */
   write_state_lang_struct_type.  */
static void
static void
read_state_lang_struct_type (type_p type)
read_state_lang_struct_type (type_p type)
{
{
  struct state_token_st *t0 = NULL;
  struct state_token_st *t0 = NULL;
  struct state_token_st *t1 = NULL;
  struct state_token_st *t1 = NULL;
  struct state_token_st *t2 = NULL;
  struct state_token_st *t2 = NULL;
 
 
  type->kind = TYPE_LANG_STRUCT;
  type->kind = TYPE_LANG_STRUCT;
  read_state_common_type_content (type);
  read_state_common_type_content (type);
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
  if (state_token_kind (t0) == STOK_STRING)
    {
    {
      if (state_token_is_name (t0, "nil"))
      if (state_token_is_name (t0, "nil"))
        {
        {
          DBGPRINTF ("read anonymous lang_struct type @%p #%d",
          DBGPRINTF ("read anonymous lang_struct type @%p #%d",
                     (void *) type, type->state_number);
                     (void *) type, type->state_number);
          type->u.s.tag = NULL;
          type->u.s.tag = NULL;
        }
        }
      else
      else
        {
        {
          type->u.s.tag = xstrdup (t0->stok_un.stok_string);
          type->u.s.tag = xstrdup (t0->stok_un.stok_string);
          DBGPRINTF ("read lang_struct type @%p #%d '%s'",
          DBGPRINTF ("read lang_struct type @%p #%d '%s'",
                     (void *) type, type->state_number, type->u.s.tag);
                     (void *) type, type->state_number, type->u.s.tag);
        }
        }
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad tag in lang struct type");
    fatal_reading_state (t0, "Bad tag in lang struct type");
  read_state_fileloc (&(type->u.s.line));
  read_state_fileloc (&(type->u.s.line));
  read_state_fields (&(type->u.s.fields));
  read_state_fields (&(type->u.s.fields));
  read_state_options (&(type->u.s.opt));
  read_state_options (&(type->u.s.opt));
  read_state_lang_bitmap (&(type->u.s.bitmap));
  read_state_lang_bitmap (&(type->u.s.bitmap));
  /* Within lang_struct-ures, the lang_struct field is a linked list
  /* Within lang_struct-ures, the lang_struct field is a linked list
     of homonymous types! */
     of homonymous types! */
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  t1 = peek_state_token (1);
  t1 = peek_state_token (1);
  t2 = peek_state_token (2);
  t2 = peek_state_token (2);
  /* Parse (!homotypes <number-types> <type-1> .... <type-n>) */
  /* Parse (!homotypes <number-types> <type-1> .... <type-n>) */
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!homotypes")
      && state_token_is_name (t1, "!homotypes")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      type_p *prevty = &type->u.s.lang_struct;
      type_p *prevty = &type->u.s.lang_struct;
      int nbhomotype = t2->stok_un.stok_num;
      int nbhomotype = t2->stok_un.stok_num;
      int i = 0;
      int i = 0;
      t0 = t1 = t2 = NULL;
      t0 = t1 = t2 = NULL;
      next_state_tokens (3);
      next_state_tokens (3);
      for (i = 0; i < nbhomotype; i++)
      for (i = 0; i < nbhomotype; i++)
        {
        {
          read_state_type (prevty);
          read_state_type (prevty);
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
          if (*prevty)
          if (*prevty)
            prevty = &(*prevty)->next;
            prevty = &(*prevty)->next;
          else
          else
              fatal_reading_state (t0,
              fatal_reading_state (t0,
                                   "expecting type in homotype list for lang_struct");
                                   "expecting type in homotype list for lang_struct");
        };
        };
      if (state_token_kind (t0) != STOK_RIGHTPAR)
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        fatal_reading_state (t0,
        fatal_reading_state (t0,
                             "expecting ) in homotype list for lang_struct");
                             "expecting ) in homotype list for lang_struct");
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "expecting !homotypes for lang_struct");
    fatal_reading_state (t0, "expecting !homotypes for lang_struct");
}
}
 
 
 
 
/* Read a param_struct type for GTY parametrized structures.  */
/* Read a param_struct type for GTY parametrized structures.  */
static void
static void
read_state_param_struct_type (type_p type)
read_state_param_struct_type (type_p type)
{
{
  int i;
  int i;
  struct state_token_st *t0;
  struct state_token_st *t0;
 
 
  type->kind = TYPE_PARAM_STRUCT;
  type->kind = TYPE_PARAM_STRUCT;
  read_state_common_type_content (type);
  read_state_common_type_content (type);
  DBGPRINTF ("read param_struct type @%p #%d",
  DBGPRINTF ("read param_struct type @%p #%d",
             (void *) type, type->state_number);
             (void *) type, type->state_number);
  read_state_type (&(type->u.param_struct.stru));
  read_state_type (&(type->u.param_struct.stru));
 
 
  for (i = 0; i < NUM_PARAM; i++)
  for (i = 0; i < NUM_PARAM; i++)
    {
    {
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (state_token_is_name (t0, "nil"))
      if (state_token_is_name (t0, "nil"))
        {
        {
          type->u.param_struct.param[i] = NULL;
          type->u.param_struct.param[i] = NULL;
          next_state_tokens (1);
          next_state_tokens (1);
        }
        }
      else
      else
        read_state_type (&(type->u.param_struct.param[i]));
        read_state_type (&(type->u.param_struct.param[i]));
    }
    }
  read_state_fileloc (&(type->u.param_struct.line));
  read_state_fileloc (&(type->u.param_struct.line));
}
}
 
 
 
 
/* Read the gc used information.  */
/* Read the gc used information.  */
static void
static void
read_state_gc_used (enum gc_used_enum *pgus)
read_state_gc_used (enum gc_used_enum *pgus)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  if (state_token_is_name (t0, "gc_unused"))
  if (state_token_is_name (t0, "gc_unused"))
    *pgus = GC_UNUSED;
    *pgus = GC_UNUSED;
  else if (state_token_is_name (t0, "gc_used"))
  else if (state_token_is_name (t0, "gc_used"))
    *pgus = GC_USED;
    *pgus = GC_USED;
  else if (state_token_is_name (t0, "gc_maybe_pointed_to"))
  else if (state_token_is_name (t0, "gc_maybe_pointed_to"))
    *pgus = GC_MAYBE_POINTED_TO;
    *pgus = GC_MAYBE_POINTED_TO;
  else if (state_token_is_name (t0, "gc_pointed_to"))
  else if (state_token_is_name (t0, "gc_pointed_to"))
    *pgus = GC_POINTED_TO;
    *pgus = GC_POINTED_TO;
  else
  else
    fatal_reading_state (t0, "invalid gc_used information");
    fatal_reading_state (t0, "invalid gc_used information");
  next_state_tokens (1);
  next_state_tokens (1);
}
}
 
 
 
 
/* Utility function to read the common content of types.  */
/* Utility function to read the common content of types.  */
static void
static void
read_state_common_type_content (type_p current)
read_state_common_type_content (type_p current)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
 
 
  if (state_token_kind (t0) == STOK_INTEGER)
  if (state_token_kind (t0) == STOK_INTEGER)
    {
    {
      current->state_number = t0->stok_un.stok_num;
      current->state_number = t0->stok_un.stok_num;
      next_state_tokens (1);
      next_state_tokens (1);
      record_type (current);
      record_type (current);
    }
    }
  else
  else
      fatal_reading_state_printf (t0,
      fatal_reading_state_printf (t0,
                                  "Expected integer for state_number line %d",
                                  "Expected integer for state_number line %d",
                                  state_line);
                                  state_line);
  /* We don't read the next field of the type.  */
  /* We don't read the next field of the type.  */
  read_state_type (&current->pointer_to);
  read_state_type (&current->pointer_to);
  read_state_gc_used (&current->gc_used);
  read_state_gc_used (&current->gc_used);
}
}
 
 
 
 
/* Read a GTY-ed type.  */
/* Read a GTY-ed type.  */
void
void
read_state_type (type_p *current)
read_state_type (type_p *current)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR &&
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!type"))
      state_token_is_name (t1, "!type"))
    {
    {
      next_state_tokens (2);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (state_token_is_name (t0, "already_seen"))
      if (state_token_is_name (t0, "already_seen"))
        {
        {
          next_state_tokens (1);
          next_state_tokens (1);
          read_state_already_seen_type (current);
          read_state_already_seen_type (current);
        }
        }
      else
      else
        {
        {
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
 
 
          if (state_token_is_name (t0, "scalar_nonchar"))
          if (state_token_is_name (t0, "scalar_nonchar"))
            {
            {
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_scalar_nonchar_type (current);
              read_state_scalar_nonchar_type (current);
            }
            }
          else if (state_token_is_name (t0, "scalar_char"))
          else if (state_token_is_name (t0, "scalar_char"))
            {
            {
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_scalar_char_type (current);
              read_state_scalar_char_type (current);
            }
            }
          else if (state_token_is_name (t0, "string"))
          else if (state_token_is_name (t0, "string"))
            {
            {
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_string_type (current);
              read_state_string_type (current);
            }
            }
          else if (state_token_is_name (t0, "struct"))
          else if (state_token_is_name (t0, "struct"))
            {
            {
              *current = XCNEW (struct type);
              *current = XCNEW (struct type);
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_struct_type (*current);
              read_state_struct_type (*current);
            }
            }
          else if (state_token_is_name (t0, "union"))
          else if (state_token_is_name (t0, "union"))
            {
            {
              *current = XCNEW (struct type);
              *current = XCNEW (struct type);
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_union_type (*current);
              read_state_union_type (*current);
            }
            }
          else if (state_token_is_name (t0, "lang_struct"))
          else if (state_token_is_name (t0, "lang_struct"))
            {
            {
              *current = XCNEW (struct type);
              *current = XCNEW (struct type);
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_lang_struct_type (*current);
              read_state_lang_struct_type (*current);
            }
            }
          else if (state_token_is_name (t0, "param_struct"))
          else if (state_token_is_name (t0, "param_struct"))
            {
            {
              *current = XCNEW (struct type);
              *current = XCNEW (struct type);
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_param_struct_type (*current);
              read_state_param_struct_type (*current);
            }
            }
          else if (state_token_is_name (t0, "pointer"))
          else if (state_token_is_name (t0, "pointer"))
            {
            {
              *current = XCNEW (struct type);
              *current = XCNEW (struct type);
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_pointer_type (*current);
              read_state_pointer_type (*current);
            }
            }
          else if (state_token_is_name (t0, "array"))
          else if (state_token_is_name (t0, "array"))
            {
            {
              *current = XCNEW (struct type);
              *current = XCNEW (struct type);
              next_state_tokens (1);
              next_state_tokens (1);
              read_state_array_type (*current);
              read_state_array_type (*current);
            }
            }
          else
          else
            fatal_reading_state (t0, "bad type in (!type");
            fatal_reading_state (t0, "bad type in (!type");
        }
        }
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) != STOK_RIGHTPAR)
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        fatal_reading_state (t0, "missing ) in type");
        fatal_reading_state (t0, "missing ) in type");
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else if (state_token_is_name (t0, "nil"))
  else if (state_token_is_name (t0, "nil"))
    {
    {
      next_state_tokens (1);
      next_state_tokens (1);
      *current = NULL;
      *current = NULL;
    }
    }
  else
  else
    fatal_reading_state (t0, "bad type syntax");
    fatal_reading_state (t0, "bad type syntax");
}
}
 
 
 
 
/* Read a file location.  Files within the source directory are dealt
/* Read a file location.  Files within the source directory are dealt
   with specifically.  */
   with specifically.  */
void
void
read_state_fileloc (struct fileloc *floc)
read_state_fileloc (struct fileloc *floc)
{
{
  bool issrcfile = false;
  bool issrcfile = false;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
 
 
  gcc_assert (floc != NULL);
  gcc_assert (floc != NULL);
  gcc_assert (srcdir != NULL);
  gcc_assert (srcdir != NULL);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR &&
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      (state_token_is_name (t1, "!fileloc")
      (state_token_is_name (t1, "!fileloc")
       || (issrcfile = state_token_is_name (t1, "!srcfileloc"))))
       || (issrcfile = state_token_is_name (t1, "!srcfileloc"))))
    {
    {
      next_state_tokens (2);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      t1 = peek_state_token (1);
      t1 = peek_state_token (1);
      if (state_token_kind (t0) == STOK_STRING &&
      if (state_token_kind (t0) == STOK_STRING &&
          state_token_kind (t1) == STOK_INTEGER)
          state_token_kind (t1) == STOK_INTEGER)
        {
        {
          char *path = t0->stok_un.stok_string;
          char *path = t0->stok_un.stok_string;
          if (issrcfile)
          if (issrcfile)
            {
            {
              static const char dirsepstr[2] = { DIR_SEPARATOR, (char) 0 };
              static const char dirsepstr[2] = { DIR_SEPARATOR, (char) 0 };
              char *fullpath = concat (srcdir, dirsepstr, path, NULL);
              char *fullpath = concat (srcdir, dirsepstr, path, NULL);
              floc->file = input_file_by_name (fullpath);
              floc->file = input_file_by_name (fullpath);
              free (fullpath);
              free (fullpath);
            }
            }
          else
          else
            floc->file = input_file_by_name (path);
            floc->file = input_file_by_name (path);
          floc->line = t1->stok_un.stok_num;
          floc->line = t1->stok_un.stok_num;
          next_state_tokens (2);
          next_state_tokens (2);
        }
        }
      else
      else
        fatal_reading_state (t0,
        fatal_reading_state (t0,
                             "Bad fileloc syntax, expected path string and line");
                             "Bad fileloc syntax, expected path string and line");
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) != STOK_RIGHTPAR)
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        fatal_reading_state (t0, "Bad fileloc syntax, expected )");
        fatal_reading_state (t0, "Bad fileloc syntax, expected )");
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else if (state_token_is_name (t0, "nil"))
  else if (state_token_is_name (t0, "nil"))
    {
    {
      next_state_tokens (1);
      next_state_tokens (1);
      floc->file = NULL;
      floc->file = NULL;
      floc->line = 0;
      floc->line = 0;
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad fileloc syntax");
    fatal_reading_state (t0, "Bad fileloc syntax");
}
}
 
 
 
 
/* Read the fields of a GTY-ed type.  */
/* Read the fields of a GTY-ed type.  */
void
void
read_state_fields (pair_p *fields)
read_state_fields (pair_p *fields)
{
{
  pair_p tmp = NULL;
  pair_p tmp = NULL;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!fields")
      && state_token_is_name (t1, "!fields")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      int nbfields = t2->stok_un.stok_num;
      int nbfields = t2->stok_un.stok_num;
      int nbpairs = 0;
      int nbpairs = 0;
      next_state_tokens (3);
      next_state_tokens (3);
      nbpairs = read_state_pair_list (&tmp);
      nbpairs = read_state_pair_list (&tmp);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (nbpairs != nbfields)
      if (nbpairs != nbfields)
        fatal_reading_state_printf
        fatal_reading_state_printf
          (t0,
          (t0,
           "Mismatched fields number, expected %d got %d", nbpairs, nbfields);
           "Mismatched fields number, expected %d got %d", nbpairs, nbfields);
      if (state_token_kind (t0) == STOK_RIGHTPAR)
      if (state_token_kind (t0) == STOK_RIGHTPAR)
        next_state_tokens (1);
        next_state_tokens (1);
      else
      else
        fatal_reading_state (t0, "Bad fields expecting )");
        fatal_reading_state (t0, "Bad fields expecting )");
    }
    }
 
 
  *fields = tmp;
  *fields = tmp;
}
}
 
 
 
 
/* Read a string option.  */
/* Read a string option.  */
static void
static void
read_state_string_option (options_p opt)
read_state_string_option (options_p opt)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  opt->kind = OPTION_STRING;
  opt->kind = OPTION_STRING;
  if (state_token_kind (t0) == STOK_STRING)
  if (state_token_kind (t0) == STOK_STRING)
    {
    {
      opt->info.string = xstrdup (t0->stok_un.stok_string);
      opt->info.string = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else if (state_token_is_name (t0, "nil"))
  else if (state_token_is_name (t0, "nil"))
    {
    {
      opt->info.string = NULL;
      opt->info.string = NULL;
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "Missing name in string option");
    fatal_reading_state (t0, "Missing name in string option");
}
}
 
 
 
 
/* Read a type option.  */
/* Read a type option.  */
static void
static void
read_state_type_option (options_p opt)
read_state_type_option (options_p opt)
{
{
  opt->kind = OPTION_TYPE;
  opt->kind = OPTION_TYPE;
  read_state_type (&(opt->info.type));
  read_state_type (&(opt->info.type));
}
}
 
 
 
 
/* Read a nested option.  */
/* Read a nested option.  */
static void
static void
read_state_nested_option (options_p opt)
read_state_nested_option (options_p opt)
{
{
  struct state_token_st *t0;
  struct state_token_st *t0;
 
 
  opt->info.nested = XCNEW (struct nested_ptr_data);
  opt->info.nested = XCNEW (struct nested_ptr_data);
  opt->kind = OPTION_NESTED;
  opt->kind = OPTION_NESTED;
  read_state_type (&(opt->info.nested->type));
  read_state_type (&(opt->info.nested->type));
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
  if (state_token_kind (t0) == STOK_STRING)
    {
    {
      opt->info.nested->convert_from = xstrdup (t0->stok_un.stok_string);
      opt->info.nested->convert_from = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else if (state_token_is_name (t0, "nil"))
  else if (state_token_is_name (t0, "nil"))
    {
    {
      opt->info.nested->convert_from = NULL;
      opt->info.nested->convert_from = NULL;
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad nested convert_from option");
    fatal_reading_state (t0, "Bad nested convert_from option");
 
 
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  if (state_token_kind (t0) == STOK_STRING)
  if (state_token_kind (t0) == STOK_STRING)
    {
    {
      opt->info.nested->convert_to = xstrdup (t0->stok_un.stok_string);
      opt->info.nested->convert_to = xstrdup (t0->stok_un.stok_string);
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else if (state_token_is_name (t0, "nil"))
  else if (state_token_is_name (t0, "nil"))
    {
    {
      opt->info.nested->convert_to = NULL;
      opt->info.nested->convert_to = NULL;
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad nested convert_from option");
    fatal_reading_state (t0, "Bad nested convert_from option");
}
}
 
 
 
 
/* Read an GTY option.  */
/* Read an GTY option.  */
static void
static void
read_state_option (options_p *opt)
read_state_option (options_p *opt)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR &&
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!option"))
      state_token_is_name (t1, "!option"))
    {
    {
      next_state_tokens (2);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_NAME)
      if (state_token_kind (t0) == STOK_NAME)
        {
        {
          *opt = XCNEW (struct options);
          *opt = XCNEW (struct options);
          if (state_token_is_name (t0, "nil"))
          if (state_token_is_name (t0, "nil"))
            (*opt)->name = NULL;
            (*opt)->name = NULL;
          else
          else
            (*opt)->name = t0->stok_un.stok_ident->stid_name;
            (*opt)->name = t0->stok_un.stok_ident->stid_name;
          next_state_tokens (1);
          next_state_tokens (1);
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
          if (state_token_kind (t0) == STOK_NAME)
          if (state_token_kind (t0) == STOK_NAME)
            {
            {
              if (state_token_is_name (t0, "string"))
              if (state_token_is_name (t0, "string"))
                {
                {
                  next_state_tokens (1);
                  next_state_tokens (1);
                  read_state_string_option (*opt);
                  read_state_string_option (*opt);
                }
                }
              else if (state_token_is_name (t0, "type"))
              else if (state_token_is_name (t0, "type"))
                {
                {
                  next_state_tokens (1);
                  next_state_tokens (1);
                  read_state_type_option (*opt);
                  read_state_type_option (*opt);
                }
                }
              else if (state_token_is_name (t0, "nested"))
              else if (state_token_is_name (t0, "nested"))
                {
                {
                  next_state_tokens (1);
                  next_state_tokens (1);
                  read_state_nested_option (*opt);
                  read_state_nested_option (*opt);
                }
                }
              else
              else
                fatal_reading_state (t0, "Bad option type");
                fatal_reading_state (t0, "Bad option type");
              t0 = peek_state_token (0);
              t0 = peek_state_token (0);
              if (state_token_kind (t0) != STOK_RIGHTPAR)
              if (state_token_kind (t0) != STOK_RIGHTPAR)
                fatal_reading_state (t0, "Bad syntax in option, expecting )");
                fatal_reading_state (t0, "Bad syntax in option, expecting )");
 
 
              next_state_tokens (1);
              next_state_tokens (1);
            }
            }
          else
          else
            fatal_reading_state (t0, "Missing option type");
            fatal_reading_state (t0, "Missing option type");
        }
        }
      else
      else
        fatal_reading_state (t0, "Bad name for option");
        fatal_reading_state (t0, "Bad name for option");
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad option, waiting for )");
    fatal_reading_state (t0, "Bad option, waiting for )");
}
}
 
 
/* Read a list of options.  */
/* Read a list of options.  */
void
void
read_state_options (options_p *opt)
read_state_options (options_p *opt)
{
{
  options_p head = NULL;
  options_p head = NULL;
  options_p previous = NULL;
  options_p previous = NULL;
  options_p current_option = NULL;
  options_p current_option = NULL;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR &&
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!options"))
      state_token_is_name (t1, "!options"))
    {
    {
      next_state_tokens (2);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      while (state_token_kind (t0) != STOK_RIGHTPAR)
      while (state_token_kind (t0) != STOK_RIGHTPAR)
        {
        {
          read_state_option (&current_option);
          read_state_option (&current_option);
          if (head == NULL)
          if (head == NULL)
            {
            {
              head = current_option;
              head = current_option;
              previous = head;
              previous = head;
            }
            }
          else
          else
            {
            {
              previous->next = current_option;
              previous->next = current_option;
              previous = current_option;
              previous = current_option;
            }
            }
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
        }
        }
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else if (state_token_is_name (t0, "nil"))
  else if (state_token_is_name (t0, "nil"))
    {
    {
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad options syntax");
    fatal_reading_state (t0, "Bad options syntax");
 
 
  *opt = head;
  *opt = head;
}
}
 
 
 
 
/* Read a version, and check against the version of the gengtype.  */
/* Read a version, and check against the version of the gengtype.  */
static void
static void
read_state_version (const char *version_string)
read_state_version (const char *version_string)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR &&
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!version"))
      state_token_is_name (t1, "!version"))
    {
    {
      next_state_tokens (2);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      t1 = peek_state_token (1);
      t1 = peek_state_token (1);
      if (state_token_kind (t0) == STOK_STRING &&
      if (state_token_kind (t0) == STOK_STRING &&
          state_token_kind (t1) == STOK_RIGHTPAR)
          state_token_kind (t1) == STOK_RIGHTPAR)
        {
        {
          /* Check that the read version string is the same as current
          /* Check that the read version string is the same as current
             version.  */
             version.  */
          if (strcmp (version_string, t0->stok_un.stok_string))
          if (strcmp (version_string, t0->stok_un.stok_string))
            fatal_reading_state_printf (t0,
            fatal_reading_state_printf (t0,
                                        "version string mismatch; expecting %s but got %s",
                                        "version string mismatch; expecting %s but got %s",
                                        version_string,
                                        version_string,
                                        t0->stok_un.stok_string);
                                        t0->stok_un.stok_string);
          next_state_tokens (2);
          next_state_tokens (2);
        }
        }
      else
      else
        fatal_reading_state (t0, "Missing version or right parenthesis");
        fatal_reading_state (t0, "Missing version or right parenthesis");
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad version syntax");
    fatal_reading_state (t0, "Bad version syntax");
}
}
 
 
 
 
/* Read a pair.  */
/* Read a pair.  */
void
void
read_state_pair (pair_p *current)
read_state_pair (pair_p *current)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  if (state_token_kind (t0) == STOK_LEFTPAR &&
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!pair"))
      state_token_is_name (t1, "!pair"))
    {
    {
      *current = XCNEW (struct pair);
      *current = XCNEW (struct pair);
      next_state_tokens (2);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) == STOK_STRING)
      if (state_token_kind (t0) == STOK_STRING)
        {
        {
          if (strcmp (t0->stok_un.stok_string, "nil") == 0)
          if (strcmp (t0->stok_un.stok_string, "nil") == 0)
            {
            {
              (*current)->name = NULL;
              (*current)->name = NULL;
            }
            }
          else
          else
            {
            {
              (*current)->name = xstrdup (t0->stok_un.stok_string);
              (*current)->name = xstrdup (t0->stok_un.stok_string);
            }
            }
          next_state_tokens (1);
          next_state_tokens (1);
          read_state_type (&((*current)->type));
          read_state_type (&((*current)->type));
          read_state_fileloc (&((*current)->line));
          read_state_fileloc (&((*current)->line));
          read_state_options (&((*current)->opt));;
          read_state_options (&((*current)->opt));;
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
          if (state_token_kind (t0) == STOK_RIGHTPAR)
          if (state_token_kind (t0) == STOK_RIGHTPAR)
            {
            {
              next_state_tokens (1);
              next_state_tokens (1);
            }
            }
          else
          else
            {
            {
              fatal_reading_state (t0, "Bad syntax for pair, )");
              fatal_reading_state (t0, "Bad syntax for pair, )");
            }
            }
        }
        }
      else
      else
        {
        {
          fatal_reading_state (t0, "Bad name for pair");
          fatal_reading_state (t0, "Bad name for pair");
        }
        }
    }
    }
  else if (state_token_kind (t0) == STOK_NAME &&
  else if (state_token_kind (t0) == STOK_NAME &&
           state_token_is_name (t0, "nil"))
           state_token_is_name (t0, "nil"))
    {
    {
      next_state_tokens (1);
      next_state_tokens (1);
      *current = NULL;
      *current = NULL;
    }
    }
  else
  else
    fatal_reading_state_printf (t0, "Bad syntax for pair, (!pair %d",
    fatal_reading_state_printf (t0, "Bad syntax for pair, (!pair %d",
                                state_token->stok_kind);
                                state_token->stok_kind);
}
}
 
 
 
 
/* Return the number of pairs actually read.  */
/* Return the number of pairs actually read.  */
int
int
read_state_pair_list (pair_p *list)
read_state_pair_list (pair_p *list)
{
{
  int nbpair = 0;
  int nbpair = 0;
  pair_p head = NULL;
  pair_p head = NULL;
  pair_p previous = NULL;
  pair_p previous = NULL;
  pair_p tmp = NULL;
  pair_p tmp = NULL;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  while (t0 && state_token_kind (t0) != STOK_RIGHTPAR)
  while (t0 && state_token_kind (t0) != STOK_RIGHTPAR)
    {
    {
      read_state_pair (&tmp);
      read_state_pair (&tmp);
      if (head == NULL)
      if (head == NULL)
        {
        {
          head = tmp;
          head = tmp;
          previous = head;
          previous = head;
        }
        }
      else
      else
        {
        {
          previous->next = tmp;
          previous->next = tmp;
          previous = tmp;
          previous = tmp;
        }
        }
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      nbpair++;
      nbpair++;
    }
    }
 
 
  /* don't consume the ); the caller will eat it.  */
  /* don't consume the ); the caller will eat it.  */
  *list = head;
  *list = head;
  return nbpair;
  return nbpair;
}
}
 
 
/* Read the typedefs.  */
/* Read the typedefs.  */
static void
static void
read_state_typedefs (pair_p *typedefs)
read_state_typedefs (pair_p *typedefs)
{
{
  int nbtypedefs = 0;
  int nbtypedefs = 0;
  pair_p list = NULL;
  pair_p list = NULL;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!typedefs")
      && state_token_is_name (t1, "!typedefs")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      int nbpairs = 0;
      int nbpairs = 0;
      nbtypedefs = t2->stok_un.stok_num;
      nbtypedefs = t2->stok_un.stok_num;
      next_state_tokens (3);
      next_state_tokens (3);
      nbpairs = read_state_pair_list (&list);
      nbpairs = read_state_pair_list (&list);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (nbpairs != nbtypedefs)
      if (nbpairs != nbtypedefs)
        fatal_reading_state_printf
        fatal_reading_state_printf
          (t0,
          (t0,
           "invalid number of typedefs, expected %d but got %d",
           "invalid number of typedefs, expected %d but got %d",
           nbtypedefs, nbpairs);
           nbtypedefs, nbpairs);
      if (state_token_kind (t0) == STOK_RIGHTPAR)
      if (state_token_kind (t0) == STOK_RIGHTPAR)
        next_state_tokens (1);
        next_state_tokens (1);
      else
      else
        fatal_reading_state (t0, "Bad typedefs syntax )");
        fatal_reading_state (t0, "Bad typedefs syntax )");
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad typedefs syntax (!typedefs");
    fatal_reading_state (t0, "Bad typedefs syntax (!typedefs");
 
 
  if (verbosity_level >= 2)
  if (verbosity_level >= 2)
    printf ("%s read %d typedefs from state\n", progname, nbtypedefs);
    printf ("%s read %d typedefs from state\n", progname, nbtypedefs);
  *typedefs = list;
  *typedefs = list;
}
}
 
 
 
 
/* Read the structures.  */
/* Read the structures.  */
static void
static void
read_state_structures (type_p *structures)
read_state_structures (type_p *structures)
{
{
  type_p head = NULL;
  type_p head = NULL;
  type_p previous = NULL;
  type_p previous = NULL;
  type_p tmp;
  type_p tmp;
  int nbstruct = 0, countstruct = 0;
  int nbstruct = 0, countstruct = 0;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!structures")
      && state_token_is_name (t1, "!structures")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      nbstruct = t2->stok_un.stok_num;
      nbstruct = t2->stok_un.stok_num;
      next_state_tokens (3);
      next_state_tokens (3);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      while (t0 && state_token_kind (t0) != STOK_RIGHTPAR)
      while (t0 && state_token_kind (t0) != STOK_RIGHTPAR)
        {
        {
          tmp = NULL;
          tmp = NULL;
          read_state_type (&tmp);
          read_state_type (&tmp);
          countstruct++;
          countstruct++;
          if (head == NULL)
          if (head == NULL)
            {
            {
              head = tmp;
              head = tmp;
              previous = head;
              previous = head;
            }
            }
          else
          else
            {
            {
              previous->next = tmp;
              previous->next = tmp;
              previous = tmp;
              previous = tmp;
            }
            }
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
        }
        }
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad structures syntax");
    fatal_reading_state (t0, "Bad structures syntax");
  if (countstruct != nbstruct)
  if (countstruct != nbstruct)
    fatal_reading_state_printf (NULL_STATE_TOKEN,
    fatal_reading_state_printf (NULL_STATE_TOKEN,
                                "expected %d structures but got %d",
                                "expected %d structures but got %d",
                                nbstruct, countstruct);
                                nbstruct, countstruct);
  if (verbosity_level >= 2)
  if (verbosity_level >= 2)
    printf ("%s read %d structures from state\n", progname, nbstruct);
    printf ("%s read %d structures from state\n", progname, nbstruct);
  *structures = head;
  *structures = head;
}
}
 
 
 
 
/* Read the param_struct-s.  */
/* Read the param_struct-s.  */
static void
static void
read_state_param_structs (type_p *param_structs)
read_state_param_structs (type_p *param_structs)
{
{
  int nbparamstructs = 0;
  int nbparamstructs = 0;
  int countparamstructs = 0;
  int countparamstructs = 0;
  type_p head = NULL;
  type_p head = NULL;
  type_p previous = NULL;
  type_p previous = NULL;
  type_p tmp;
  type_p tmp;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!param_structs")
      && state_token_is_name (t1, "!param_structs")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      nbparamstructs = t2->stok_un.stok_num;
      nbparamstructs = t2->stok_un.stok_num;
      next_state_tokens (3);
      next_state_tokens (3);
      t0 = t1 = t2 = NULL;
      t0 = t1 = t2 = NULL;
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      while (state_token_kind (t0) != STOK_RIGHTPAR)
      while (state_token_kind (t0) != STOK_RIGHTPAR)
        {
        {
          tmp = NULL;
          tmp = NULL;
          read_state_type (&tmp);
          read_state_type (&tmp);
          if (head == NULL)
          if (head == NULL)
            {
            {
              head = tmp;
              head = tmp;
              previous = head;
              previous = head;
            }
            }
          else
          else
            {
            {
              previous->next = tmp;
              previous->next = tmp;
              previous = tmp;
              previous = tmp;
            }
            }
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
          countparamstructs++;
          countparamstructs++;
        }
        }
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad param_structs syntax");
    fatal_reading_state (t0, "Bad param_structs syntax");
  t0 = peek_state_token (0);
  t0 = peek_state_token (0);
  if (countparamstructs != nbparamstructs)
  if (countparamstructs != nbparamstructs)
    fatal_reading_state_printf
    fatal_reading_state_printf
      (t0,
      (t0,
       "invalid number of param_structs expected %d got %d",
       "invalid number of param_structs expected %d got %d",
       nbparamstructs, countparamstructs);
       nbparamstructs, countparamstructs);
  *param_structs = head;
  *param_structs = head;
}
}
 
 
 
 
/* Read the variables.  */
/* Read the variables.  */
static void
static void
read_state_variables (pair_p *variables)
read_state_variables (pair_p *variables)
{
{
  pair_p list = NULL;
  pair_p list = NULL;
  int nbvars = 0;
  int nbvars = 0;
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!variables")
      && state_token_is_name (t1, "!variables")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      int nbpairs = 0;
      int nbpairs = 0;
      nbvars = t2->stok_un.stok_num;
      nbvars = t2->stok_un.stok_num;
      next_state_tokens (3);
      next_state_tokens (3);
      nbpairs = read_state_pair_list (&list);
      nbpairs = read_state_pair_list (&list);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (nbpairs != nbvars)
      if (nbpairs != nbvars)
        fatal_reading_state_printf
        fatal_reading_state_printf
          (t0, "Invalid number of variables, expected %d but got %d",
          (t0, "Invalid number of variables, expected %d but got %d",
           nbvars, nbpairs);
           nbvars, nbpairs);
      if (state_token_kind (t0) == STOK_RIGHTPAR)
      if (state_token_kind (t0) == STOK_RIGHTPAR)
        next_state_tokens (1);
        next_state_tokens (1);
      else
      else
        fatal_reading_state (t0, "Waiting for ) in variables");
        fatal_reading_state (t0, "Waiting for ) in variables");
    }
    }
  else
  else
    fatal_reading_state (t0, "Bad variables syntax");
    fatal_reading_state (t0, "Bad variables syntax");
  *variables = list;
  *variables = list;
  if (verbosity_level >= 2)
  if (verbosity_level >= 2)
    printf ("%s read %d variables from state\n", progname, nbvars);
    printf ("%s read %d variables from state\n", progname, nbvars);
}
}
 
 
 
 
/* Read the source directory.  */
/* Read the source directory.  */
static void
static void
read_state_srcdir (void)
read_state_srcdir (void)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  if (state_token_kind (t0) == STOK_LEFTPAR &&
  if (state_token_kind (t0) == STOK_LEFTPAR &&
      state_token_is_name (t1, "!srcdir"))
      state_token_is_name (t1, "!srcdir"))
    {
    {
      next_state_tokens (2);
      next_state_tokens (2);
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      t1 = peek_state_token (1);
      t1 = peek_state_token (1);
      if (state_token_kind (t0) == STOK_STRING &&
      if (state_token_kind (t0) == STOK_STRING &&
          state_token_kind (t1) == STOK_RIGHTPAR)
          state_token_kind (t1) == STOK_RIGHTPAR)
        {
        {
          srcdir = xstrdup (t0->stok_un.stok_string);
          srcdir = xstrdup (t0->stok_un.stok_string);
          srcdir_len = strlen (srcdir);
          srcdir_len = strlen (srcdir);
          next_state_tokens (2);
          next_state_tokens (2);
          return;
          return;
        }
        }
    }
    }
 
 
  fatal_reading_state (t0, "Bad srcdir in state_file");
  fatal_reading_state (t0, "Bad srcdir in state_file");
}
}
 
 
 
 
/* Read the sequence of GCC front-end languages.  */
/* Read the sequence of GCC front-end languages.  */
static void
static void
read_state_languages (void)
read_state_languages (void)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!languages")
      && state_token_is_name (t1, "!languages")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      int i = 0;
      int i = 0;
      num_lang_dirs = t2->stok_un.stok_num;
      num_lang_dirs = t2->stok_un.stok_num;
      lang_dir_names = XCNEWVEC (const char *, num_lang_dirs);
      lang_dir_names = XCNEWVEC (const char *, num_lang_dirs);
      next_state_tokens (3);
      next_state_tokens (3);
      t0 = t1 = t2 = NULL;
      t0 = t1 = t2 = NULL;
      for (i = 0; i < (int) num_lang_dirs; i++)
      for (i = 0; i < (int) num_lang_dirs; i++)
        {
        {
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
          if (state_token_kind (t0) != STOK_NAME)
          if (state_token_kind (t0) != STOK_NAME)
            fatal_reading_state (t0, "expecting language name in state file");
            fatal_reading_state (t0, "expecting language name in state file");
          lang_dir_names[i] = t0->stok_un.stok_ident->stid_name;
          lang_dir_names[i] = t0->stok_un.stok_ident->stid_name;
          next_state_tokens (1);
          next_state_tokens (1);
        }
        }
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (state_token_kind (t0) != STOK_RIGHTPAR)
      if (state_token_kind (t0) != STOK_RIGHTPAR)
        fatal_reading_state (t0, "missing ) in languages list of state file");
        fatal_reading_state (t0, "missing ) in languages list of state file");
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "expecting languages list in state file");
    fatal_reading_state (t0, "expecting languages list in state file");
 
 
}
}
 
 
/* Read the sequence of files.  */
/* Read the sequence of files.  */
static void
static void
read_state_files_list (void)
read_state_files_list (void)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!fileslist")
      && state_token_is_name (t1, "!fileslist")
      && state_token_kind (t2) == STOK_INTEGER)
      && state_token_kind (t2) == STOK_INTEGER)
    {
    {
      int i = 0;
      int i = 0;
      num_gt_files = t2->stok_un.stok_num;
      num_gt_files = t2->stok_un.stok_num;
      next_state_tokens (3);
      next_state_tokens (3);
      t0 = t1 = t2 = NULL;
      t0 = t1 = t2 = NULL;
      gt_files = XCNEWVEC (const input_file *, num_gt_files);
      gt_files = XCNEWVEC (const input_file *, num_gt_files);
      for (i = 0; i < (int) num_gt_files; i++)
      for (i = 0; i < (int) num_gt_files; i++)
        {
        {
          bool issrcfile = FALSE;
          bool issrcfile = FALSE;
          t0 = t1 = t2 = NULL;
          t0 = t1 = t2 = NULL;
          t0 = peek_state_token (0);
          t0 = peek_state_token (0);
          t1 = peek_state_token (1);
          t1 = peek_state_token (1);
          t2 = peek_state_token (2);
          t2 = peek_state_token (2);
          if (state_token_kind (t0) == STOK_LEFTPAR
          if (state_token_kind (t0) == STOK_LEFTPAR
              && (state_token_is_name (t1, "!file")
              && (state_token_is_name (t1, "!file")
                  || (issrcfile = state_token_is_name (t1, "!srcfile")))
                  || (issrcfile = state_token_is_name (t1, "!srcfile")))
              && state_token_kind (t2) == STOK_INTEGER)
              && state_token_kind (t2) == STOK_INTEGER)
            {
            {
              lang_bitmap bmap = t2->stok_un.stok_num;
              lang_bitmap bmap = t2->stok_un.stok_num;
              next_state_tokens (3);
              next_state_tokens (3);
              t0 = t1 = t2 = NULL;
              t0 = t1 = t2 = NULL;
              t0 = peek_state_token (0);
              t0 = peek_state_token (0);
              t1 = peek_state_token (1);
              t1 = peek_state_token (1);
              if (state_token_kind (t0) == STOK_STRING
              if (state_token_kind (t0) == STOK_STRING
                  && state_token_kind (t1) == STOK_RIGHTPAR)
                  && state_token_kind (t1) == STOK_RIGHTPAR)
                {
                {
                  const char *fnam = t0->stok_un.stok_string;
                  const char *fnam = t0->stok_un.stok_string;
                  /* Allocate & fill a gt_file entry with space for the lang_bitmap before! */
                  /* Allocate & fill a gt_file entry with space for the lang_bitmap before! */
                  input_file *curgt = NULL;
                  input_file *curgt = NULL;
                  if (issrcfile)
                  if (issrcfile)
                    {
                    {
                      static const char dirsepstr[2] =
                      static const char dirsepstr[2] =
                        { DIR_SEPARATOR, (char) 0 };
                        { DIR_SEPARATOR, (char) 0 };
                      char *fullpath = concat (srcdir, dirsepstr, fnam, NULL);
                      char *fullpath = concat (srcdir, dirsepstr, fnam, NULL);
                      curgt = input_file_by_name (fullpath);
                      curgt = input_file_by_name (fullpath);
                      free (fullpath);
                      free (fullpath);
                    }
                    }
                  else
                  else
                    curgt = input_file_by_name (fnam);
                    curgt = input_file_by_name (fnam);
                  set_lang_bitmap (curgt, bmap);
                  set_lang_bitmap (curgt, bmap);
                  gt_files[i] = curgt;
                  gt_files[i] = curgt;
                  next_state_tokens (2);
                  next_state_tokens (2);
                }
                }
              else
              else
                fatal_reading_state (t0,
                fatal_reading_state (t0,
                                     "bad file in !fileslist of state file");
                                     "bad file in !fileslist of state file");
            }
            }
          else
          else
            fatal_reading_state (t0,
            fatal_reading_state (t0,
                                 "expecting file in !fileslist of state file");
                                 "expecting file in !fileslist of state file");
        };
        };
      t0 = peek_state_token (0);
      t0 = peek_state_token (0);
      if (!state_token_kind (t0) == STOK_RIGHTPAR)
      if (!state_token_kind (t0) == STOK_RIGHTPAR)
        fatal_reading_state (t0, "missing ) for !fileslist in state file");
        fatal_reading_state (t0, "missing ) for !fileslist in state file");
      next_state_tokens (1);
      next_state_tokens (1);
    }
    }
  else
  else
    fatal_reading_state (t0, "missing !fileslist in state file");
    fatal_reading_state (t0, "missing !fileslist in state file");
}
}
 
 
 
 
/* Read the trailer.  */
/* Read the trailer.  */
static void
static void
read_state_trailer (void)
read_state_trailer (void)
{
{
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t0 = peek_state_token (0);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t1 = peek_state_token (1);
  struct state_token_st *t2 = peek_state_token (2);
  struct state_token_st *t2 = peek_state_token (2);
 
 
  if (state_token_kind (t0) == STOK_LEFTPAR
  if (state_token_kind (t0) == STOK_LEFTPAR
      && state_token_is_name (t1, "!endfile")
      && state_token_is_name (t1, "!endfile")
      && state_token_kind (t2) == STOK_RIGHTPAR)
      && state_token_kind (t2) == STOK_RIGHTPAR)
    next_state_tokens (3);
    next_state_tokens (3);
  else
  else
    fatal_reading_state (t0, "missing !endfile in state file");
    fatal_reading_state (t0, "missing !endfile in state file");
}
}
 
 
 
 
/* Utility functions for the state_seen_types hash table.  */
/* Utility functions for the state_seen_types hash table.  */
static unsigned
static unsigned
hash_type_number (const void *ty)
hash_type_number (const void *ty)
{
{
  const struct type *type = (const struct type *) ty;
  const struct type *type = (const struct type *) ty;
 
 
  return type->state_number;
  return type->state_number;
}
}
 
 
static int
static int
equals_type_number (const void *ty1, const void *ty2)
equals_type_number (const void *ty1, const void *ty2)
{
{
  const struct type *type1 = (const struct type *) ty1;
  const struct type *type1 = (const struct type *) ty1;
  const struct type *type2 = (const struct type *) ty2;
  const struct type *type2 = (const struct type *) ty2;
 
 
  return type1->state_number == type2->state_number;
  return type1->state_number == type2->state_number;
}
}
 
 
static int
static int
string_eq (const void *a, const void *b)
string_eq (const void *a, const void *b)
{
{
  const char *a0 = (const char *)a;
  const char *a0 = (const char *)a;
  const char *b0 = (const char *)b;
  const char *b0 = (const char *)b;
 
 
  return (strcmp (a0, b0) == 0);
  return (strcmp (a0, b0) == 0);
}
}
 
 
 
 
/* The function reading the state, called by main from gengtype.c.  */
/* The function reading the state, called by main from gengtype.c.  */
void
void
read_state (const char *path)
read_state (const char *path)
{
{
  state_file = fopen (path, "r");
  state_file = fopen (path, "r");
  if (state_file == NULL)
  if (state_file == NULL)
    fatal ("Failed to open state file %s for reading [%s]", path,
    fatal ("Failed to open state file %s for reading [%s]", path,
           xstrerror (errno));
           xstrerror (errno));
  state_path = path;
  state_path = path;
  state_line = 1;
  state_line = 1;
 
 
  if (verbosity_level >= 1)
  if (verbosity_level >= 1)
    {
    {
      printf ("%s reading state file %s;", progname, state_path);
      printf ("%s reading state file %s;", progname, state_path);
      if (verbosity_level >= 2)
      if (verbosity_level >= 2)
        putchar ('\n');
        putchar ('\n');
      fflush (stdout);
      fflush (stdout);
    }
    }
 
 
  state_seen_types =
  state_seen_types =
    htab_create (2017, hash_type_number, equals_type_number, NULL);
    htab_create (2017, hash_type_number, equals_type_number, NULL);
  state_ident_tab =
  state_ident_tab =
    htab_create (4027, htab_hash_string, string_eq, NULL);
    htab_create (4027, htab_hash_string, string_eq, NULL);
  read_state_version (version_string);
  read_state_version (version_string);
  read_state_srcdir ();
  read_state_srcdir ();
  read_state_languages ();
  read_state_languages ();
  read_state_files_list ();
  read_state_files_list ();
  read_state_structures (&structures);
  read_state_structures (&structures);
  if (ferror (state_file))
  if (ferror (state_file))
    fatal_reading_state_printf
    fatal_reading_state_printf
      (NULL_STATE_TOKEN, "input error while reading state [%s]",
      (NULL_STATE_TOKEN, "input error while reading state [%s]",
       xstrerror (errno));
       xstrerror (errno));
  read_state_typedefs (&typedefs);
  read_state_typedefs (&typedefs);
  read_state_param_structs (&param_structs);
  read_state_param_structs (&param_structs);
  read_state_variables (&variables);
  read_state_variables (&variables);
  read_state_trailer ();
  read_state_trailer ();
 
 
  if (verbosity_level >= 1)
  if (verbosity_level >= 1)
    {
    {
      printf ("%s read %ld bytes.\n", progname, ftell (state_file));
      printf ("%s read %ld bytes.\n", progname, ftell (state_file));
      fflush (stdout);
      fflush (stdout);
    };
    };
 
 
  if (fclose (state_file))
  if (fclose (state_file))
    fatal ("failed to close read state file %s [%s]",
    fatal ("failed to close read state file %s [%s]",
           path, xstrerror (errno));
           path, xstrerror (errno));
  state_file = NULL;
  state_file = NULL;
  state_path = NULL;
  state_path = NULL;
}
}
 
 
/* End of file gengtype-state.c.  */
/* End of file gengtype-state.c.  */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.