aboutsummaryrefslogtreecommitdiff
path: root/gcc/gengtype.c
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2007-03-26 21:04:59 +0000
committerZack Weinberg <zack@gcc.gnu.org>2007-03-26 21:04:59 +0000
commit065ae6117579cc9a089c238207b42f5a1470423a (patch)
tree0a7175b4448ec3facb884c40c5169621bbe9bbe8 /gcc/gengtype.c
parent17defa6a13ef4f317e22dcb3827b4e8ea1b37541 (diff)
downloadgcc-065ae6117579cc9a089c238207b42f5a1470423a.zip
gcc-065ae6117579cc9a089c238207b42f5a1470423a.tar.gz
gcc-065ae6117579cc9a089c238207b42f5a1470423a.tar.bz2
gengtype.h: Remove all type definitions to gengtype.c...
* gengtype.h: Remove all type definitions to gengtype.c; leave only definitions of options_p, type_p, and pair_p as opaque pointers. Update prototypes. * gengtype.c: Many type definitions moved here from gengtype.h. Consolidate type definitions at the top of the file. (xvasprintf): Delete. (xasprintf): Make static. (create_nested_pointer_option): Add 'next' parameter. (create_field_all, create_field_at): New functions. (create_field): Now a thin wrapper around create_field_all. (create_optional_field): Rename create_optional_field_ and add line argument. Original name is now a macro which supplies __LINE__. (oprintf): Use vsnprintf directly. (close_output_files): Use fatal rather than perror/exit. (note_def_vec, note_def_vec_alloc): Use create_field_at. (main): Set progname. Don't use exit. * gengtype-yacc.y (struct_fields): Use create_field_at. (option, optionseqopt): Delete. (optionseq): Consolidate productions from option here so we can use the first argument to create_option. From-SVN: r123233
Diffstat (limited to 'gcc/gengtype.c')
-rw-r--r--gcc/gengtype.c326
1 files changed, 223 insertions, 103 deletions
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 86d72d8f..604d94c 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -22,9 +22,153 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "bconfig.h"
#include "system.h"
#include "gengtype.h"
-#include "gtyp-gen.h"
#include "errors.h" /* for fatal */
+/* Data types, macros, etc. used only in this file. */
+
+/* Kinds of types we can understand. */
+enum typekind {
+ TYPE_SCALAR,
+ TYPE_STRING,
+ TYPE_STRUCT,
+ TYPE_UNION,
+ TYPE_POINTER,
+ TYPE_ARRAY,
+ TYPE_LANG_STRUCT,
+ TYPE_PARAM_STRUCT
+};
+
+typedef unsigned lang_bitmap;
+
+/* A way to pass data through to the output end. */
+struct options
+{
+ struct options *next;
+ const char *name;
+ const char *info;
+};
+
+/* Option data for the 'nested_ptr' option. */
+struct nested_ptr_data
+{
+ type_p type;
+ const char *convert_to;
+ const char *convert_from;
+};
+
+/* A name and a type. */
+struct pair
+{
+ pair_p next;
+ const char *name;
+ type_p type;
+ struct fileloc line;
+ options_p opt;
+};
+
+#define NUM_PARAM 10
+
+/* A description of a type. */
+enum gc_used_enum
+ {
+ GC_UNUSED = 0,
+ GC_USED,
+ GC_MAYBE_POINTED_TO,
+ GC_POINTED_TO
+ };
+
+struct type
+{
+ enum typekind kind;
+ type_p next;
+ type_p pointer_to;
+ enum gc_used_enum gc_used;
+ union {
+ type_p p;
+ struct {
+ const char *tag;
+ struct fileloc line;
+ pair_p fields;
+ options_p opt;
+ lang_bitmap bitmap;
+ type_p lang_struct;
+ } s;
+ bool scalar_is_char;
+ struct {
+ type_p p;
+ const char *len;
+ } a;
+ struct {
+ type_p stru;
+ type_p param[NUM_PARAM];
+ struct fileloc line;
+ } param_struct;
+ } u;
+};
+
+#define UNION_P(x) \
+ ((x)->kind == TYPE_UNION || \
+ ((x)->kind == TYPE_LANG_STRUCT \
+ && (x)->u.s.lang_struct->kind == TYPE_UNION))
+#define UNION_OR_STRUCT_P(x) \
+ ((x)->kind == TYPE_UNION \
+ || (x)->kind == TYPE_STRUCT \
+ || (x)->kind == TYPE_LANG_STRUCT)
+
+/* Structure representing an output file. */
+struct outf
+{
+ struct outf *next;
+ const char *name;
+ size_t buflength;
+ size_t bufused;
+ char *buf;
+};
+typedef struct outf * outf_p;
+
+/* An output file, suitable for definitions, that can see declarations
+ made in INPUT_FILE and is linked into every language that uses
+ INPUT_FILE. */
+extern outf_p get_output_file_with_visibility
+ (const char *input_file);
+const char *get_output_file_name (const char *);
+
+#include "gtyp-gen.h"
+
+/* A bitmap that specifies which of BASE_FILES should be used to
+ output a definition that is different for each language and must be
+ defined once in each language that uses INPUT_FILE. */
+static lang_bitmap get_base_file_bitmap (const char *input_file);
+
+/* Print, like fprintf, to O. */
+static void oprintf (outf_p o, const char *S, ...)
+ ATTRIBUTE_PRINTF_2;
+
+/* The list of output files. */
+static outf_p output_files;
+
+/* The output header file that is included into pretty much every
+ source file. */
+static outf_p header_file;
+
+/* Number of files specified in gtfiles. */
+#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
+
+/* Number of files in the language files array. */
+#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
+
+/* Length of srcdir name. */
+static int srcdir_len = 0;
+
+/* A list of output files suitable for definitions. There is one
+ BASE_FILES entry for each language. */
+#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
+static outf_p base_files[NUM_BASE_FILES];
+
+static outf_p create_file (const char *, const char *);
+static const char * get_file_basename (const char *);
+
+
/* Nonzero iff an error has occurred. */
static int hit_error = 0;
@@ -50,29 +194,20 @@ error_at_line (struct fileloc *pos, const char *msg, ...)
va_end (ap);
}
-/* vasprintf, but produces fatal message on out-of-memory. */
-int
-xvasprintf (char **result, const char *format, va_list args)
-{
- int ret = vasprintf (result, format, args);
- if (*result == NULL || ret < 0)
- {
- fputs ("gengtype: out of memory", stderr);
- xexit (1);
- }
- return ret;
-}
-
-/* Wrapper for xvasprintf. */
-char *
+/* asprintf, but produces fatal message on out-of-memory. */
+static char * ATTRIBUTE_PRINTF_1
xasprintf (const char *format, ...)
{
+ int n;
char *result;
va_list ap;
va_start (ap, format);
- xvasprintf (&result, format, ap);
+ n = vasprintf (&result, format, ap);
+ if (result == NULL || n < 0)
+ fatal ("out of memory");
va_end (ap);
+
return result;
}
@@ -332,14 +467,15 @@ create_option (options_p next, const char *name, const void *info)
/* Return an options structure for a "nested_ptr" option. */
options_p
-create_nested_ptr_option (type_p t, const char *to, const char *from)
+create_nested_ptr_option (options_p next, type_p t,
+ const char *to, const char *from)
{
struct nested_ptr_data *d = XNEW (struct nested_ptr_data);
d->type = adjust_field_type (t, 0);
d->convert_to = to;
d->convert_from = from;
- return create_option (NULL, "nested_ptr", d);
+ return create_option (next, "nested_ptr", d);
}
/* Add a variable named S of type T with options O defined at POS,
@@ -358,11 +494,10 @@ note_variable (const char *s, type_p t, options_p o, struct fileloc *pos)
variables = n;
}
-/* Create a fake field with the given type and name. NEXT is the next
- field in the chain. */
-
+/* Most-general structure field creator. */
static pair_p
-create_field (pair_p next, type_p type, const char *name)
+create_field_all (pair_p next, type_p type, const char *name, options_p opt,
+ const char *file, int line)
{
pair_p field;
@@ -370,21 +505,37 @@ create_field (pair_p next, type_p type, const char *name)
field->next = next;
field->type = type;
field->name = name;
- field->opt = NULL;
- field->line.file = __FILE__;
- field->line.line = __LINE__;
+ field->opt = opt;
+ field->line.file = file;
+ field->line.line = line;
return field;
}
+/* Create a field that came from the source code we are scanning,
+ i.e. we have a 'struct fileloc', and possibly options; also,
+ adjust_field_type should be called. */
+pair_p
+create_field_at (pair_p next, type_p type, const char *name, options_p opt,
+ struct fileloc *pos)
+{
+ return create_field_all (next, adjust_field_type (type, opt),
+ name, opt, pos->file, pos->line);
+}
+
+/* Create a fake field with the given type and name. NEXT is the next
+ field in the chain. */
+#define create_field(next,type,name) \
+ create_field_all(next,type,name, 0, __FILE__, __LINE__)
+
/* Like create_field, but the field is only valid when condition COND
is true. */
static pair_p
-create_optional_field (pair_p next, type_p type, const char *name,
- const char *cond)
+create_optional_field_ (pair_p next, type_p type, const char *name,
+ const char *cond, int line)
{
static int id = 1;
- pair_p union_fields, field;
+ pair_p union_fields;
type_p union_type;
/* Create a fake union type with a single nameless field of type TYPE.
@@ -398,10 +549,12 @@ create_optional_field (pair_p next, type_p type, const char *name,
/* Create the field and give it the new fake union type. Add a "desc"
tag that specifies the condition under which the field is valid. */
- field = create_field (next, union_type, name);
- field->opt = create_option (field->opt, "desc", cond);
- return field;
+ return create_field_all (next, union_type, name,
+ create_option (0, "desc", cond),
+ __FILE__, line);
}
+#define create_optional_field(next,type,name,cond) \
+ create_optional_field_(next,type,name,cond,__LINE__)
/* We don't care how long a CONST_DOUBLE is. */
#define CONST_DOUBLE_FORMAT "ww"
@@ -953,27 +1106,7 @@ set_gc_used (pair_p variables)
(but some output files have many input files), and there is one .h file
for the whole build. */
-/* The list of output files. */
-static outf_p output_files;
-
-/* The output header file that is included into pretty much every
- source file. */
-static outf_p header_file;
-
-/* Number of files specified in gtfiles. */
-#define NUM_GT_FILES (ARRAY_SIZE (all_files) - 1)
-
-/* Number of files in the language files array. */
-#define NUM_LANG_FILES (ARRAY_SIZE (lang_files) - 1)
-
-/* Length of srcdir name. */
-static int srcdir_len = 0;
-
-#define NUM_BASE_FILES (ARRAY_SIZE (lang_dir_names) - 1)
-outf_p base_files[NUM_BASE_FILES];
-
-static outf_p create_file (const char *, const char *);
-static const char * get_file_basename (const char *);
+/* Output file handling. */
/* Create and return an outf_p for a new file for NAME, to be called
ONAME. */
@@ -1021,15 +1154,20 @@ create_file (const char *name, const char *oname)
void
oprintf (outf_p o, const char *format, ...)
{
- char *s;
size_t slength;
- va_list ap;
- va_start (ap, format);
- slength = xvasprintf (&s, format, ap);
+ /* Try first with the assumption that there is enough space. */
+ {
+ va_list ap;
+ va_start (ap, format);
+ slength = vsnprintf (o->buf + o->bufused, o->buflength - o->bufused,
+ format, ap);
+ va_end (ap);
+ }
- if (o->bufused + slength > o->buflength)
+ if (o->bufused + slength >= o->buflength)
{
+ /* There wasn't enough space. */
size_t new_len = o->buflength;
if (new_len == 0)
new_len = 1024;
@@ -1038,11 +1176,21 @@ oprintf (outf_p o, const char *format, ...)
} while (o->bufused + slength >= new_len);
o->buf = XRESIZEVEC (char, o->buf, new_len);
o->buflength = new_len;
+
+ /* We now know that there is enough space. */
+ {
+ size_t slen2;
+ va_list ap;
+ va_start (ap, format);
+ slen2 = vsnprintf (o->buf + o->bufused, o->buflength - o->bufused,
+ format, ap);
+ va_end (ap);
+
+ gcc_assert (slen2 == slength);
+ gcc_assert (o->bufused + slen2 < o->buflength);
+ }
}
- memcpy (o->buf + o->bufused, s, slength);
o->bufused += slength;
- free (s);
- va_end (ap);
}
/* Open the global header file and the language-specific header files. */
@@ -1298,20 +1446,11 @@ close_output_files (void)
newfile = fopen (of->name, "w");
if (newfile == NULL)
- {
- perror ("opening output file");
- exit (1);
- }
+ fatal ("opening output file %s: %s", of->name, strerror (errno));
if (fwrite (of->buf, 1, of->bufused, newfile) != of->bufused)
- {
- perror ("writing output file");
- exit (1);
- }
+ fatal ("writing output file %s: %s", of->name, strerror (errno));
if (fclose (newfile) != 0)
- {
- perror ("closing output file");
- exit (1);
- }
+ fatal ("closing output file %s: %s", of->name, strerror (errno));
}
}
@@ -3029,9 +3168,10 @@ write_roots (pair_p variables)
void
note_def_vec (const char *typename, bool is_scalar, struct fileloc *pos)
{
- pair_p f, fields;
+ pair_p fields;
type_p t;
options_p o;
+ type_p len_ty = create_scalar_type ("unsigned");
const char *name = concat ("VEC_", typename, "_base", (char *)0);
if (is_scalar)
@@ -3046,29 +3186,9 @@ note_def_vec (const char *typename, bool is_scalar, struct fileloc *pos)
}
/* We assemble the field list in reverse order. */
- f = XNEW (struct pair);
- f->type = adjust_field_type (create_array (t, "1"), o);
- f->name = "vec";
- f->opt = o;
- f->line = *pos;
- f->next = 0;
- fields = f;
-
- f = XNEW (struct pair);
- f->type = adjust_field_type (create_scalar_type ("unsigned"), 0);
- f->name = "alloc";
- f->opt = 0;
- f->line = *pos;
- f->next = fields;
- fields = f;
-
- f = XNEW (struct pair);
- f->type = adjust_field_type (create_scalar_type ("unsigned"), 0);
- f->name = "num";
- f->opt = 0;
- f->line = *pos;
- f->next = fields;
- fields = f;
+ fields = create_field_at (0, create_array (t, "1"), "vec", o, pos);
+ fields = create_field_at (fields, len_ty, "alloc", 0, pos);
+ fields = create_field_at (fields, len_ty, "num", 0, pos);
do_typedef (name, new_structure (name, 0, pos, fields, 0), pos);
}
@@ -3086,11 +3206,8 @@ note_def_vec_alloc (const char *type, const char *astrat, struct fileloc *pos)
const char *astratname = concat ("VEC_", type, "_", astrat, (char *)0);
const char *basename = concat ("VEC_", type, "_base", (char *)0);
- pair_p field = XNEW (struct pair);
- field->name = "base";
- field->type = adjust_field_type (resolve_typedef (basename, pos), 0);
- field->line = *pos;
- field->next = 0;
+ pair_p field = create_field_at (0, resolve_typedef (basename, pos),
+ "base", 0, pos);
do_typedef (astratname, new_structure (astratname, 0, pos, field, 0), pos);
}
@@ -3109,6 +3226,9 @@ main (int ARG_UNUSED (argc), char ** ARG_UNUSED (argv))
scalar_char.u.scalar_is_char = true;
scalar_nonchar.u.scalar_is_char = false;
+ /* fatal uses this */
+ progname = "gengtype";
+
gen_rtx_next ();
do_scalar_typedef ("CUMULATIVE_ARGS", &pos);
@@ -3150,7 +3270,7 @@ main (int ARG_UNUSED (argc), char ** ARG_UNUSED (argv))
}
if (hit_error != 0)
- exit (1);
+ return 1;
set_gc_used (variables);