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
This commit is contained in:
Zack Weinberg 2007-03-26 21:04:59 +00:00 committed by Zack Weinberg
parent 17defa6a13
commit 065ae61175
4 changed files with 274 additions and 276 deletions

View File

@ -1,5 +1,27 @@
2007-03-26 Zack Weinberg <zackw@panix.com>
* 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.
* gengtype-lex.l: Distinguish unions from structures in the
token type. Don't call find_structure; return the tag as a string.
* gengtype-yacc.y: Add new token types ENT_TYPEDEF_UNION and ENT_UNION.

View File

@ -57,7 +57,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
%type <p> struct_fields
%type <t> type lasttype
%type <o> optionsopt options option optionseq optionseqopt
%type <o> optionsopt options optionseq
%type <s> type_option stringseq
%%
@ -128,33 +128,17 @@ semiequal: ';'
struct_fields: { $$ = NULL; }
| type optionsopt ID bitfieldopt ';' struct_fields
{
pair_p p = XNEW (struct pair);
p->type = adjust_field_type ($1, $2);
p->opt = $2;
p->name = $3;
p->next = $6;
p->line = lexer_line;
$$ = p;
$$ = create_field_at ($6, $1, $3, $2, &lexer_line);
}
| type optionsopt ID ARRAY ';' struct_fields
{
pair_p p = XNEW (struct pair);
p->type = adjust_field_type (create_array ($1, $4), $2);
p->opt = $2;
p->name = $3;
p->next = $6;
p->line = lexer_line;
$$ = p;
$$ = create_field_at ($6, create_array ($1, $4),
$3, $2, &lexer_line);
}
| type optionsopt ID ARRAY ARRAY ';' struct_fields
{
pair_p p = XNEW (struct pair);
p->type = create_array (create_array ($1, $5), $4);
p->opt = $2;
p->name = $3;
p->next = $7;
p->line = lexer_line;
$$ = p;
type_p arr = create_array (create_array ($1, $5), $4);
$$ = create_field_at ($7, arr, $3, $2, &lexer_line);
}
| type ':' bitfieldlen ';' struct_fields
{ $$ = $5; }
@ -204,7 +188,7 @@ optionsopt: { $$ = NULL; }
| options { $$ = $1; }
;
options: GTY_TOKEN '(' '(' optionseqopt ')' ')'
options: GTY_TOKEN '(' '(' optionseq ')' ')'
{ $$ = $4; }
;
@ -214,31 +198,19 @@ type_option : ALIAS
{ $$ = $1; }
;
option: ID
{ $$ = create_option (NULL, $1, (void *)""); }
| ID '(' stringseq ')'
{ $$ = create_option (NULL, $1, (void *)$3); }
| type_option '(' type ')'
{ $$ = create_option (NULL, $1, adjust_field_type ($3, NULL)); }
| NESTED_PTR '(' type ',' stringseq ',' stringseq ')'
{ $$ = create_nested_ptr_option ($3, $5, $7); }
;
optionseq: { $$ = NULL; }
| optionseq commaopt ID
{ $$ = create_option ($1, $3, (void *)""); }
| optionseq commaopt ID '(' stringseq ')'
{ $$ = create_option ($1, $3, (void *)$5); }
| optionseq commaopt type_option '(' type ')'
{ $$ = create_option ($1, $3, adjust_field_type ($5, 0)); }
| optionseq commaopt NESTED_PTR '(' type ',' stringseq ',' stringseq ')'
{ $$ = create_nested_ptr_option ($1, $5, $7, $9); }
optionseq: option
{
$1->next = NULL;
$$ = $1;
}
| optionseq ',' option
{
$3->next = $1;
$$ = $3;
}
;
optionseqopt: { $$ = NULL; }
| optionseq { $$ = $1; }
;
commaopt: /* nothing */
| ','
;
stringseq: STRING
{ $$ = $1; }

View File

@ -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);

View File

@ -18,6 +18,9 @@ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
#ifndef GCC_GENGTYPE_H
#define GCC_GENGTYPE_H
/* A file position, mostly for error messages.
The FILE element may be compared using pointer equality. */
struct fileloc {
@ -25,92 +28,10 @@ struct fileloc {
int line;
};
/* 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
};
/* Data types handed around within, but opaque to, the lexer and parser. */
typedef struct pair *pair_p;
typedef struct type *type_p;
typedef unsigned lang_bitmap;
/* Option data for the 'nested_ptr' option. */
struct nested_ptr_data {
type_p type;
const char *convert_to;
const char *convert_from;
};
/* A way to pass data through to the output end. */
typedef struct options {
struct options *next;
const char *name;
const char *info;
} *options_p;
/* 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)
typedef struct options *options_p;
/* Variables used to communicate between the lexer and the parser. */
extern int lexer_toplevel_done;
@ -120,13 +41,6 @@ extern struct fileloc lexer_line;
extern void error_at_line
(struct fileloc *pos, const char *msg, ...) ATTRIBUTE_PRINTF_2;
/* Combines xmalloc() and vasprintf(). */
extern int xvasprintf (char **, const char *, va_list)
ATTRIBUTE_PRINTF (2, 0);
/* Like the above, but more convenient for quick coding. */
extern char * xasprintf (const char *, ...)
ATTRIBUTE_PRINTF_1;
/* Constructor routines for types. */
extern void do_typedef (const char *s, type_p t, struct fileloc *pos);
extern void do_scalar_typedef (const char *s, struct fileloc *pos);
@ -139,8 +53,10 @@ extern type_p create_scalar_type (const char *name);
extern type_p create_pointer (type_p t);
extern type_p create_array (type_p t, const char *len);
extern options_p create_option (options_p, const char *name, const void *info);
extern options_p create_nested_ptr_option (type_p t, const char *from,
const char *to);
extern options_p create_nested_ptr_option (options_p, type_p t,
const char *from, const char *to);
extern pair_p create_field_at (pair_p next, type_p type, const char *name,
options_p opt, struct fileloc *pos);
extern type_p adjust_field_type (type_p, options_p);
extern void note_variable (const char *s, type_p t, options_p o,
struct fileloc *pos);
@ -155,36 +71,4 @@ extern void yyerror (const char *);
extern int yyparse (void);
extern void parse_file (const char *name);
/* Output file handling. */
/* 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 *);
/* A list of output files suitable for definitions. There is one
BASE_FILES entry for each language. */
extern outf_p base_files[];
/* 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. */
extern lang_bitmap get_base_file_bitmap (const char *input_file);
/* Print, like fprintf, to O. */
extern void oprintf (outf_p o, const char *S, ...)
ATTRIBUTE_PRINTF_2;
#endif