/* Gengtype persistent state serialization & de-serialization.
Useful for gengtype in plugin mode.
- Copyright (C) 2010 Free Software Foundation, Inc.
+ Copyright (C) 2010-2020 Free Software Foundation, Inc.
This file is part of GCC.
and Basile Starynkevitch <basile@starynkevitch.net>
*/
-#ifdef GENERATOR_FILE
-#include "bconfig.h"
-#else
+#ifdef HOST_GENERATOR_FILE
#include "config.h"
+#define GENERATOR_FILE 1
+#else
+#include "bconfig.h"
#endif
#include "system.h"
#include "errors.h" /* For fatal. */
-#include "double-int.h"
-#include "hashtab.h"
#include "version.h" /* For version_string & pkgversion_string. */
#include "obstack.h"
#include "gengtype.h"
case TYPE_UNION:
case TYPE_LANG_STRUCT:
case TYPE_USER_STRUCT:
+ case TYPE_UNDEFINED:
return CONST_CAST (struct fileloc*, &ty->u.s.line);
- case TYPE_PARAM_STRUCT:
- return CONST_CAST (struct fileloc*, &ty->u.param_struct.line);
case TYPE_SCALAR:
case TYPE_STRING:
case TYPE_POINTER:
static int state_line = 0;
static long state_bol = 0; /* offset of beginning of line */
+/* A class for writing out s-expressions, keeping track of newlines and
+ nested indentation. */
+class s_expr_writer
+{
+public:
+ s_expr_writer ();
+
+ void write_new_line ();
+ void write_any_indent (int leading_spaces);
+
+ void begin_s_expr (const char *tag);
+ void end_s_expr ();
+
+private:
+ int m_indent_amount;
+ int m_had_recent_newline;
+}; // class s_expr_writer
+
+/* A class for writing out "gtype.state". */
+class state_writer : public s_expr_writer
+{
+public:
+ state_writer ();
+
+private:
+ void write_state_fileloc (struct fileloc *floc);
+ void write_state_fields (pair_p fields);
+ void write_state_a_string (const char *s);
+ void write_state_string_option (options_p current);
+ void write_state_type_option (options_p current);
+ void write_state_nested_option (options_p current);
+ void write_state_option (options_p current);
+ void write_state_options (options_p opt);
+ void write_state_lang_bitmap (lang_bitmap bitmap);
+ void write_state_version (const char *version);
+ void write_state_scalar_type (type_p current);
+ void write_state_string_type (type_p current);
+ void write_state_undefined_type (type_p current);
+ void write_state_struct_union_type (type_p current, const char *kindstr);
+ void write_state_struct_type (type_p current);
+ void write_state_user_struct_type (type_p current);
+ void write_state_union_type (type_p current);
+ void write_state_lang_struct_type (type_p current);
+ void write_state_pointer_type (type_p current);
+ void write_state_array_type (type_p current);
+ void write_state_gc_used (enum gc_used_enum gus);
+ void write_state_common_type_content (type_p current);
+ void write_state_type (type_p current);
+ void write_state_pair (pair_p current);
+ int write_state_pair_list (pair_p list);
+ void write_state_typedefs (void);
+ void write_state_structures (void);
+ void write_state_variables (void);
+ void write_state_srcdir (void);
+ void write_state_files_list (void);
+ void write_state_languages (void);
+
+ friend void write_state (const char *state_path);
+
+private:
+ /* Counter of written types. */
+ int m_state_written_type_count;
+}; // class state_writer
+
+
+/* class s_expr_writer's trivial constructor. */
+s_expr_writer::s_expr_writer ()
+ : m_indent_amount (0),
+ m_had_recent_newline (0)
+{
+}
+
+/* Write a newline to the output file, merging adjacent newlines. */
+void
+s_expr_writer::write_new_line (void)
+{
+ /* Don't add a newline if we've just had one. */
+ if (!m_had_recent_newline)
+ {
+ fprintf (state_file, "\n");
+ m_had_recent_newline = 1;
+ }
+}
-/* Counter of written types. */
-static int state_written_type_count = 0;
+/* If we've just had a newline, write the indentation amount, potentially
+ omitting some spaces.
+
+ LEADING_SPACES exists to support code that writes strings with leading
+ spaces (e.g " foo") which might occur within a line, or could be the first
+ thing on a line. By passing leading_spaces == 1, when such a string is the
+ first thing on a line, write_any_indent () swallows the successive
+ leading spaces into the indentation so that the "foo" begins at the expected
+ column. */
+void
+s_expr_writer::write_any_indent (int leading_spaces)
+{
+ int i;
+ int amount = m_indent_amount - leading_spaces;
+ if (m_had_recent_newline)
+ for (i = 0; i < amount; i++)
+ fprintf (state_file, " ");
+ m_had_recent_newline = 0;
+}
+
+/* Write the beginning of a new s-expresion e.g. "(!foo "
+ The writer automatically adds whitespace to show the hierarchical
+ structure of the expressions, so each one starts on a new line,
+ and any within it will be at an increased indentation level. */
+void
+s_expr_writer::begin_s_expr (const char *tag)
+{
+ write_new_line ();
+ write_any_indent (0);
+ fprintf (state_file, "(!%s ", tag);
+ m_indent_amount++;
+}
+
+/* Write out the end of an s-expression: any necssessary indentation,
+ a closing parenthesis, and a new line. */
+void
+s_expr_writer::end_s_expr (void)
+{
+ m_indent_amount--;
+ write_any_indent (0);
+ fprintf (state_file, ")");
+ write_new_line ();
+}
+
+
+/* class state_writer's trivial constructor. */
+state_writer::state_writer ()
+ : s_expr_writer (),
+ m_state_written_type_count (0)
+{
+}
/* Fatal error messages when reading the state. They are extremely
/* Fatal message while reading state. */
-static inline void
+static void
fatal_reading_state (struct state_token_st* tok, const char*msg)
{
if (tok)
else \
fatal ("%s:%d: Invalid state file; " Fmt, \
state_path, state_line, __VA_ARGS__); \
- } while(0)
+ } while (0)
/* Find or allocate an identifier in our name hash table. */
* We want to serialize :
* - typedefs list
* - structures list
- * - param_structs list
* - variables list
*
* So, we have one routine for each kind of data. The main writing
/* Return the length of a linked list made of pairs. */
static int pair_list_length (pair_p list);
-/* Write a pair */
-static void write_state_pair (pair_p);
-
-/* return the number of pairs written. Should match the length given
- by pair_list_length. */
-static int write_state_pair_list (pair_p list);
-
-/* 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
- occurrences. */
-static void write_state_type (type_p);
-
-/* Write a null-terminatel string using our Lispy lexical conventions,
- similar to those of C or MELT. */
-static void write_state_a_string (const char *s);
-
/* Compute the length of a list of pairs, starting from the first
one. */
static int
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
two GCC source trees have different absolute paths. */
-static void
-write_state_fileloc (struct fileloc *floc)
+void
+state_writer::write_state_fileloc (struct fileloc *floc)
{
if (floc != NULL && floc->line > 0)
srcrelpath = get_file_srcdir_relative_path (floc->file);
if (srcrelpath != NULL)
{
- fprintf (state_file, "\n(!srcfileloc ");
+ begin_s_expr ("srcfileloc");
write_state_a_string (srcrelpath);
}
else
{
- fprintf (state_file, "\n(!fileloc ");
+ begin_s_expr ("fileloc");
write_state_a_string (get_input_file_name (floc->file));
}
fprintf (state_file, " %d", floc->line);
- fprintf (state_file, ")\n");
+ end_s_expr ();
}
else
fprintf (state_file, "nil ");
}
/* Write a list of fields. */
-static void
-write_state_fields (pair_p fields)
+void
+state_writer::write_state_fields (pair_p fields)
{
int nbfields = pair_list_length (fields);
int nbpairs = 0;
- fprintf (state_file, "\n(!fields %d ", nbfields);
+ begin_s_expr ("fields");
+ fprintf (state_file, "%d ", nbfields);
nbpairs = write_state_pair_list (fields);
gcc_assert (nbpairs == nbfields);
- fprintf (state_file, ")\n");
+ end_s_expr ();
}
/* Write a null-terminated string in our lexical convention, very
similar to the convention of C. */
-static void
-write_state_a_string (const char *s)
+void
+state_writer::write_state_a_string (const char *s)
{
char c;
+ write_any_indent (1);
+
fputs (" \"", state_file);
for (; *s != 0; s++)
{
}
/* Our option-s have three kinds, each with its writer. */
-static void
-write_state_string_option (options_p current)
+void
+state_writer::write_state_string_option (options_p current)
{
+ write_any_indent (0);
fprintf (state_file, "string ");
if (current->info.string != NULL)
write_state_a_string (current->info.string);
fprintf (state_file, " nil ");
}
-static void
-write_state_type_option (options_p current)
+void
+state_writer::write_state_type_option (options_p current)
{
+ write_any_indent (0);
fprintf (state_file, "type ");
write_state_type (current->info.type);
}
-static void
-write_state_nested_option (options_p current)
+void
+state_writer::write_state_nested_option (options_p current)
{
+ write_any_indent (0);
fprintf (state_file, "nested ");
write_state_type (current->info.nested->type);
if (current->info.nested->convert_from != NULL)
write_state_a_string (current->info.nested->convert_from);
else
- fprintf (state_file, " nil ");
+ {
+ write_any_indent (1);
+ fprintf (state_file, " nil ");
+ }
if (current->info.nested->convert_to != NULL)
write_state_a_string (current->info.nested->convert_to);
else
- fprintf (state_file, " nil ");
+ {
+ write_any_indent (1);
+ fprintf (state_file, " nil ");
+ }
}
-static void
-write_state_option (options_p current)
+void
+state_writer::write_state_option (options_p current)
{
- fprintf (state_file, "\n(!option ");
+ begin_s_expr ("option");
+ write_any_indent (0);
if (current->name != NULL)
fprintf (state_file, "%s ", current->name);
else
fatal ("Option tag unknown");
}
- fprintf (state_file, ")\n");
+ /* Terminate the "option" s-expression. */
+ end_s_expr ();
}
/* Write a list of GTY options. */
-static void
-write_state_options (options_p opt)
+void
+state_writer::write_state_options (options_p opt)
{
options_p current;
if (opt == NULL)
{
- fprintf (state_file, "nil ");
+ write_any_indent (0);
+ fprintf (state_file, "nil ");
return;
}
- fprintf (state_file, "\n(!options ");
+ begin_s_expr ("options");
for (current = opt; current != NULL; current = current->next)
write_state_option (current);
- fprintf (state_file, ")\n");
+ end_s_expr ();
}
/* Write a bitmap representing a set of GCC front-end languages. */
-static void
-write_state_lang_bitmap (lang_bitmap bitmap)
+void
+state_writer::write_state_lang_bitmap (lang_bitmap bitmap)
{
+ write_any_indent (0);
fprintf (state_file, "%d ", (int) bitmap);
}
/* Write version information. */
-static void
-write_state_version (const char *version)
+void
+state_writer::write_state_version (const char *version)
{
- fprintf (state_file, "\n(!version ");
+ begin_s_expr ("version");
write_state_a_string (version);
- fprintf (state_file, ")\n");
+ end_s_expr ();
}
-/* Common routine to write the common content of all types. */
-static void write_state_common_type_content (type_p current);
-
/* Write a scalar type. We have only two of these. */
-static void
-write_state_scalar_type (type_p current)
+void
+state_writer::write_state_scalar_type (type_p current)
{
+ write_any_indent (0);
if (current == &scalar_nonchar)
fprintf (state_file, "scalar_nonchar ");
else if (current == &scalar_char)
}
/* Write the string type. There is only one such thing! */
-static void
-write_state_string_type (type_p current)
+void
+state_writer::write_state_string_type (type_p current)
{
if (current == &string_type)
{
+ write_any_indent (0);
fprintf (state_file, "string ");
write_state_common_type_content (current);
}
fatal ("Unexpected type in write_state_string_type");
}
+/* Write an undefined type. */
+void
+state_writer::write_state_undefined_type (type_p current)
+{
+ DBGPRINTF ("undefined type @ %p #%d '%s'", (void *) current,
+ current->state_number, current->u.s.tag);
+ write_any_indent (0);
+ fprintf (state_file, "undefined ");
+ gcc_assert (current->gc_used == GC_UNUSED);
+ write_state_common_type_content (current);
+ if (current->u.s.tag != NULL)
+ write_state_a_string (current->u.s.tag);
+ else
+ {
+ write_any_indent (0);
+ fprintf (state_file, "nil");
+ }
+
+ write_state_fileloc (type_lineloc (current));
+}
+
/* Common code to write structure like types. */
-static void
-write_state_struct_union_type (type_p current, const char *kindstr)
+void
+state_writer::write_state_struct_union_type (type_p current,
+ const char *kindstr)
{
DBGPRINTF ("%s type @ %p #%d '%s'", kindstr, (void *) current,
current->state_number, current->u.s.tag);
+ write_any_indent (0);
fprintf (state_file, "%s ", kindstr);
write_state_common_type_content (current);
if (current->u.s.tag != NULL)
write_state_a_string (current->u.s.tag);
else
- fprintf (state_file, "nil");
+ {
+ write_any_indent (0);
+ fprintf (state_file, "nil");
+ }
write_state_fileloc (type_lineloc (current));
write_state_fields (current->u.s.fields);
/* Write a GTY struct type. */
-static void
-write_state_struct_type (type_p current)
+void
+state_writer::write_state_struct_type (type_p current)
{
write_state_struct_union_type (current, "struct");
write_state_type (current->u.s.lang_struct);
+ write_state_type (current->u.s.base_class);
}
/* Write a GTY user-defined struct type. */
-static void
-write_state_user_struct_type (type_p current)
+void
+state_writer::write_state_user_struct_type (type_p current)
{
DBGPRINTF ("user_struct type @ %p #%d '%s'", (void *) current,
current->state_number, current->u.s.tag);
+ write_any_indent (0);
fprintf (state_file, "user_struct ");
write_state_common_type_content (current);
if (current->u.s.tag != NULL)
write_state_a_string (current->u.s.tag);
else
- fprintf (state_file, "nil");
+ {
+ write_any_indent (0);
+ fprintf (state_file, "nil");
+ }
write_state_fileloc (type_lineloc (current));
write_state_fields (current->u.s.fields);
}
/* write a GTY union type. */
-static void
-write_state_union_type (type_p current)
+void
+state_writer::write_state_union_type (type_p current)
{
write_state_struct_union_type (current, "union");
write_state_type (current->u.s.lang_struct);
subfield, which points to a linked list of homonumous types.
Change this function with extreme care, see also
read_state_lang_struct_type. */
-static void
-write_state_lang_struct_type (type_p current)
+void
+state_writer::write_state_lang_struct_type (type_p current)
{
int nbhomontype = 0;
type_p hty = NULL;
homoname = hty->u.s.tag;
gcc_assert (strcmp (homoname, hty->u.s.tag) == 0);
}
- fprintf (state_file, "(!homotypes %d\n", nbhomontype);
+ begin_s_expr ("homotypes");
+ fprintf (state_file, "%d", nbhomontype);
for (hty = current->u.s.lang_struct; hty != NULL; hty = hty->next)
write_state_type (hty);
- fprintf (state_file, ")\n");
-}
-
-/* Write a parametrized structure GTY type. */
-static void
-write_state_param_struct_type (type_p current)
-{
- int i;
-
- fprintf (state_file, "param_struct ");
- write_state_common_type_content (current);
- write_state_type (current->u.param_struct.stru);
- for (i = 0; i < NUM_PARAM; i++)
- {
- if (current->u.param_struct.param[i] != NULL)
- write_state_type (current->u.param_struct.param[i]);
- else
- fprintf (state_file, "nil ");
- }
- write_state_fileloc (¤t->u.param_struct.line);
+ end_s_expr ();
}
/* Write a pointer type. */
-static void
-write_state_pointer_type (type_p current)
+void
+state_writer::write_state_pointer_type (type_p current)
{
+ write_any_indent (0);
fprintf (state_file, "pointer ");
write_state_common_type_content (current);
write_state_type (current->u.p);
}
/* Write an array type. */
-static void
-write_state_array_type (type_p current)
+void
+state_writer::write_state_array_type (type_p current)
{
+ write_any_indent (0);
fprintf (state_file, "array ");
write_state_common_type_content (current);
if (current->u.a.len != NULL)
write_state_a_string (current->u.a.len);
else
- fprintf (state_file, " nil");
+ {
+ write_any_indent (1);
+ fprintf (state_file, " nil");
+ }
+ write_any_indent (1);
fprintf (state_file, " ");
write_state_type (current->u.a.p);
}
/* Write the gc_used information. */
-static void
-write_state_gc_used (enum gc_used_enum gus)
+void
+state_writer::write_state_gc_used (enum gc_used_enum gus)
{
+ write_any_indent (1);
switch (gus)
{
case GC_UNUSED:
/* Utility routine to write the common content of all types. Notice
that the next field is *not* written on purpose. */
-static void
-write_state_common_type_content (type_p current)
+void
+state_writer::write_state_common_type_content (type_p current)
{
+ write_any_indent (0);
fprintf (state_file, "%d ", current->state_number);
/* We do not write the next type, because list of types are
explicitly written. However, lang_struct are special in that
/* The important and recursive routine writing GTY types as understood
by gengtype. Types which have a positive state_number have already
been seen and written. */
-static void
-write_state_type (type_p current)
+void
+state_writer::write_state_type (type_p current)
{
+ write_any_indent (0);
if (current == NULL)
{
fprintf (state_file, "nil ");
return;
}
- fprintf (state_file, "\n(!type ");
+ begin_s_expr ("type");
if (current->state_number > 0)
- fprintf (state_file, "already_seen %d", current->state_number);
+ {
+ write_any_indent (0);
+ fprintf (state_file, "already_seen %d", current->state_number);
+ }
else
{
- state_written_type_count++;
- DBGPRINTF ("writing type #%d @%p old number %d", state_written_type_count,
+ m_state_written_type_count++;
+ DBGPRINTF ("writing type #%d @%p old number %d", m_state_written_type_count,
(void *) current, current->state_number);
- current->state_number = state_written_type_count;
+ current->state_number = m_state_written_type_count;
switch (current->kind)
{
+ case TYPE_NONE:
+ gcc_unreachable ();
+ case TYPE_UNDEFINED:
+ write_state_undefined_type (current);
+ break;
case TYPE_STRUCT:
write_state_struct_type (current);
break;
case TYPE_LANG_STRUCT:
write_state_lang_struct_type (current);
break;
- case TYPE_PARAM_STRUCT:
- write_state_param_struct_type (current);
- break;
case TYPE_SCALAR:
write_state_scalar_type (current);
break;
case TYPE_STRING:
write_state_string_type (current);
break;
-
- default:
- fatal ("Unexpected type...");
}
}
- fprintf (state_file, ")\n");
+ /* Terminate the "type" s-expression. */
+ end_s_expr ();
}
/* Write a pair. */
-static void
-write_state_pair (pair_p current)
+void
+state_writer::write_state_pair (pair_p current)
{
if (current == NULL)
{
+ write_any_indent (0);
fprintf (state_file, "nil)");
return;
}
- fprintf (state_file, "\n(!pair ");
+ begin_s_expr ("pair");
if (current->name != NULL)
write_state_a_string (current->name);
write_state_fileloc (&(current->line));
write_state_options (current->opt);
- fprintf (state_file, ")");
+ /* Terminate the "pair" s-expression. */
+ end_s_expr ();
}
/* Write a pair list and return the number of pairs written. */
-static int
-write_state_pair_list (pair_p list)
+int
+state_writer::write_state_pair_list (pair_p list)
{
int nbpair = 0;
pair_p current;
}
-/* When writing imported linked lists, like typedefs, structures,
- param_structs, ... we count their length first and write it. These
- eases the reading, and enables an extra verification on the number
- of actually read items. */
+/* When writing imported linked lists, like typedefs, structures, ... we count
+ their length first and write it. This eases the reading, and enables an
+ extra verification on the number of actually read items. */
/* Write our typedefs. */
-static void
-write_state_typedefs (void)
+void
+state_writer::write_state_typedefs (void)
{
int nbtypedefs = pair_list_length (typedefs);
int nbpairs = 0;
- fprintf (state_file, "\n(!typedefs %d\n", nbtypedefs);
+ begin_s_expr ("typedefs");
+ fprintf (state_file, "%d", nbtypedefs);
nbpairs = write_state_pair_list (typedefs);
gcc_assert (nbpairs == nbtypedefs);
- fprintf (state_file, ")\n");
+ end_s_expr ();
if (verbosity_level >= 2)
printf ("%s wrote %d typedefs\n", progname, nbtypedefs);
}
/* Write our structures. */
-static void
-write_state_structures (void)
+void
+state_writer::write_state_structures (void)
{
int nbstruct = 0;
type_p current;
for (current = structures; current != NULL; current = current->next)
nbstruct++;
- fprintf (state_file, "\n(!structures %d\n", nbstruct);
+ begin_s_expr ("structures");
+ fprintf (state_file, "%d", nbstruct);
for (current = structures; current != NULL; current = current->next)
- write_state_type (current);
+ {
+ write_new_line ();
+ write_state_type (current);
+ }
- fprintf (state_file, ")\n");
+ /* Terminate the "structures" s-expression. */
+ end_s_expr ();
if (verbosity_level >= 2)
printf ("%s wrote %d structures in state\n", progname, nbstruct);
}
-/* Write our param_struct-s. */
-static void
-write_state_param_structs (void)
-{
- int nbparamstruct = 0;
- type_p current;
-
- for (current = param_structs; current != NULL; current = current->next)
- nbparamstruct++;
-
- fprintf (state_file, "\n(!param_structs %d\n", nbparamstruct);
-
- for (current = param_structs; current != NULL; current = current->next)
- write_state_type (current);
-
- fprintf (state_file, ")\n");
-}
-
/* Write our variables. */
-static void
-write_state_variables (void)
+void
+state_writer::write_state_variables (void)
{
int nbvars = pair_list_length (variables);
int nbpairs = 0;
- fprintf (state_file, "\n(!variables %d\n", nbvars);
+ begin_s_expr ("variables");
+ fprintf (state_file, "%d", nbvars);
nbpairs = write_state_pair_list (variables);
gcc_assert (nbpairs == nbvars);
- fprintf (state_file, ")\n");
+ end_s_expr ();
if (verbosity_level >= 2)
printf ("%s wrote %d variables.\n", progname, nbvars);
}
/* Write the source directory. File locations within the source
directory have been written specifically. */
-static void
-write_state_srcdir (void)
+void
+state_writer::write_state_srcdir (void)
{
- fprintf (state_file, "\n(!srcdir ");
+ begin_s_expr ("srcdir");
write_state_a_string (srcdir);
- fprintf (state_file, ")\n");
+ end_s_expr ();
}
/* Count and write the list of our files. */
-static void
-write_state_files_list (void)
+void
+state_writer::write_state_files_list (void)
{
int i = 0;
/* Write the list of files with their lang_bitmap. */
- fprintf (state_file, "\n(!fileslist %d\n", (int) num_gt_files);
+ begin_s_expr ("fileslist");
+ fprintf (state_file, "%d", (int) num_gt_files);
for (i = 0; i < (int) num_gt_files; i++)
{
const char *cursrcrelpath = NULL;
cursrcrelpath = get_file_srcdir_relative_path (curfil);
if (cursrcrelpath)
{
- fprintf (state_file, "(!srcfile %d ", get_lang_bitmap (curfil));
+ begin_s_expr ("srcfile");
+ fprintf (state_file, "%d ", get_lang_bitmap (curfil));
write_state_a_string (cursrcrelpath);
}
else
{
- fprintf (state_file, "(!file %d ", get_lang_bitmap (curfil));
+ begin_s_expr ("file");
+ fprintf (state_file, "%d ", get_lang_bitmap (curfil));
write_state_a_string (get_input_file_name (curfil));
}
- fprintf (state_file, ")\n");
+ /* Terminate the inner s-expression (either "srcfile" or "file"). */
+ end_s_expr ();
}
- fprintf (state_file, ")\n");
+ /* Terminate the "fileslist" s-expression. */
+ end_s_expr ();
}
/* Write the list of GCC front-end languages. */
-static void
-write_state_languages (void)
+void
+state_writer::write_state_languages (void)
{
int i = 0;
- fprintf (state_file, "\n(!languages %d", (int) num_lang_dirs);
+ begin_s_expr ("languages");
+ fprintf (state_file, "%d", (int) num_lang_dirs);
for (i = 0; i < (int) num_lang_dirs; i++)
{
/* Languages names are identifiers, we expect only letters or
valid language name, but cp is valid. */
fprintf (state_file, " %s", lang_dir_names[i]);
}
- fprintf (state_file, ")\n");
+ end_s_expr ();
}
/* Write the trailer. */
fprintf (state_file,
";;; This file should be parsed by the same %s which wrote it.\n",
progname);
+
+ state_writer sw;
+
/* The first non-comment significant line gives the version string. */
- write_state_version (version_string);
- write_state_srcdir ();
- write_state_languages ();
- write_state_files_list ();
- write_state_structures ();
- write_state_typedefs ();
- write_state_param_structs ();
- write_state_variables ();
+ sw.write_state_version (version_string);
+ sw.write_state_srcdir ();
+ sw.write_state_languages ();
+ sw.write_state_files_list ();
+ sw.write_state_structures ();
+ sw.write_state_typedefs ();
+ sw.write_state_variables ();
write_state_trailer ();
statelen = ftell (state_file);
if (ferror (state_file))
if (verbosity_level >= 1)
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, sw.m_state_written_type_count);
}
\f
read_state_common_type_content (*type);
}
-
/* Read the string_type. */
static void
read_state_string_type (type_p *type)
}
+/* Read an undefined type. */
+static void
+read_state_undefined_type (type_p type)
+{
+ struct state_token_st *t0;
+
+ type->kind = TYPE_UNDEFINED;
+ read_state_common_type_content (type);
+ t0 = peek_state_token (0);
+ if (state_token_kind (t0) == STOK_STRING)
+ {
+ if (state_token_is_name (t0, "nil"))
+ {
+ type->u.s.tag = NULL;
+ DBGPRINTF ("read anonymous undefined type @%p #%d",
+ (void *) type, type->state_number);
+ }
+ else
+ {
+ type->u.s.tag = xstrdup (t0->stok_un.stok_string);
+ DBGPRINTF ("read undefined type @%p #%d '%s'",
+ (void *) type, type->state_number, type->u.s.tag);
+ }
+
+ next_state_tokens (1);
+ read_state_fileloc (&(type->u.s.line));
+ }
+ else
+ {
+ fatal_reading_state (t0, "Bad tag in undefined type");
+ }
+}
+
+
/* Read a GTY-ed struct type. */
static void
read_state_struct_type (type_p type)
read_state_options (&(type->u.s.opt));
read_state_lang_bitmap (&(type->u.s.bitmap));
read_state_type (&(type->u.s.lang_struct));
+ read_state_type (&(type->u.s.base_class));
+ if (type->u.s.base_class)
+ add_subclass (type->u.s.base_class, type);
}
else
{
}
-/* Read a param_struct type for GTY parametrized structures. */
-static void
-read_state_param_struct_type (type_p type)
-{
- int i;
- struct state_token_st *t0;
-
- type->kind = TYPE_PARAM_STRUCT;
- read_state_common_type_content (type);
- DBGPRINTF ("read param_struct type @%p #%d",
- (void *) type, type->state_number);
- read_state_type (&(type->u.param_struct.stru));
-
- for (i = 0; i < NUM_PARAM; i++)
- {
- t0 = peek_state_token (0);
- if (state_token_is_name (t0, "nil"))
- {
- type->u.param_struct.param[i] = NULL;
- next_state_tokens (1);
- }
- else
- read_state_type (&(type->u.param_struct.param[i]));
- }
- read_state_fileloc (&(type->u.param_struct.line));
-}
-
-
/* Read the gc used information. */
static void
read_state_gc_used (enum gc_used_enum *pgus)
next_state_tokens (1);
read_state_string_type (current);
}
+ else if (state_token_is_name (t0, "undefined"))
+ {
+ *current = XCNEW (struct type);
+ next_state_tokens (1);
+ read_state_undefined_type (*current);
+ }
else if (state_token_is_name (t0, "struct"))
{
*current = XCNEW (struct type);
next_state_tokens (1);
read_state_lang_struct_type (*current);
}
- else if (state_token_is_name (t0, "param_struct"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_param_struct_type (*current);
- }
else if (state_token_is_name (t0, "pointer"))
{
*current = XCNEW (struct type);
next_state_tokens (1);
read_state_type (&((*current)->type));
read_state_fileloc (&((*current)->line));
- read_state_options (&((*current)->opt));;
+ read_state_options (&((*current)->opt));
t0 = peek_state_token (0);
if (state_token_kind (t0) == STOK_RIGHTPAR)
{
}
-/* Read the param_struct-s. */
-static void
-read_state_param_structs (type_p *param_structs)
-{
- int nbparamstructs = 0;
- int countparamstructs = 0;
- type_p head = NULL;
- type_p previous = NULL;
- type_p tmp;
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
-
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!param_structs")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- nbparamstructs = t2->stok_un.stok_num;
- next_state_tokens (3);
- t0 = t1 = t2 = NULL;
- t0 = peek_state_token (0);
- while (state_token_kind (t0) != STOK_RIGHTPAR)
- {
- tmp = NULL;
- read_state_type (&tmp);
- if (head == NULL)
- {
- head = tmp;
- previous = head;
- }
- else
- {
- previous->next = tmp;
- previous = tmp;
- }
- t0 = peek_state_token (0);
- countparamstructs++;
- }
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Bad param_structs syntax");
- t0 = peek_state_token (0);
- if (countparamstructs != nbparamstructs)
- fatal_reading_state_printf
- (t0,
- "invalid number of param_structs expected %d got %d",
- nbparamstructs, countparamstructs);
- *param_structs = head;
-}
-
-
/* Read the variables. */
static void
read_state_variables (pair_p *variables)
"expecting file in !fileslist of state file");
};
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");
next_state_tokens (1);
}
(NULL_STATE_TOKEN, "input error while reading state [%s]",
xstrerror (errno));
read_state_typedefs (&typedefs);
- read_state_param_structs (¶m_structs);
read_state_variables (&variables);
read_state_trailer ();