gcc/gcc/gengtype-lex.l

520 lines
13 KiB
Plaintext
Raw Normal View History

/* -*- indented-text -*- */
/* Process source files and output type information.
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
%{
#include "bconfig.h"
#include "coretypes.h"
#include "system.h"
#define malloc xmalloc
#define realloc xrealloc
#include "gengtype.h"
#include "gengtype-yacc.h"
#define YY_INPUT(BUF,RESULT,SIZE) ((RESULT) = macro_input (BUF,SIZE))
static unsigned macro_input (char *buffer, unsigned);
static void push_macro_expansion (const char *, unsigned,
const char *, unsigned);
static void update_lineno (const char *l, size_t len);
struct fileloc lexer_line;
int lexer_toplevel_done;
static void
update_lineno (const char *l, size_t len)
{
while (len-- > 0)
if (*l++ == '\n')
lexer_line.line++;
}
%}
ID [[:alpha:]_][[:alnum:]_]*
WS [[:space:]]+
IWORD short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD
ITYPE {IWORD}({WS}{IWORD})*
%x in_struct in_struct_comment in_comment in_yacc_escape
%option warn noyywrap nounput nodefault perf-report
%option 8bit never-interactive
%%
[^[:alnum:]_]typedef{WS}(struct|union){WS}{ID}{WS}?[*[:space:]]{WS}?{ID}{WS}?";" {
char *tagstart;
size_t taglen;
char *namestart;
size_t namelen;
int is_pointer = 0;
struct type *t;
int union_p;
tagstart = yytext + strlen (" typedef ");
while (ISSPACE (*tagstart))
tagstart++;
union_p = tagstart[0] == 'u';
tagstart += strlen ("union ");
while (ISSPACE (*tagstart))
tagstart++;
for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
;
for (namestart = tagstart + taglen;
! ISIDNUM (*namestart);
namestart++)
if (*namestart == '*')
is_pointer = 1;
for (namelen = 1; ISIDNUM (namestart[namelen]); namelen++)
;
t = find_structure ((const char *) xmemdup (tagstart, taglen, taglen+1),
union_p);
if (is_pointer)
t = create_pointer (t);
namestart = (char *) xmemdup (namestart, namelen, namelen+1);
#ifdef USE_MAPPED_LOCATION
/* temporary kludge - gentype doesn't handle cpp conditionals */
if (strcmp (namestart, "location_t") != 0
&& strcmp (namestart, "expanded_location") != 0)
#endif
do_typedef (namestart, t, &lexer_line);
update_lineno (yytext, yyleng);
}
[^[:alnum:]_]typedef{WS}{ITYPE}{WS}{ID}{WS}?";" {
char *namestart;
size_t namelen;
struct type *t;
char *typestart;
size_t typelen;
for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
;
for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
;
namestart -= namelen - 1;
for (typestart = yytext + strlen (" typedef ");
ISSPACE(*typestart);
typestart++)
;
for (typelen = namestart - typestart;
ISSPACE (typestart[typelen-1]);
typelen--)
;
t = create_scalar_type (typestart, typelen);
do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
&lexer_line);
update_lineno (yytext, yyleng);
}
[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}PARAMS {
char *namestart;
size_t namelen;
struct type *t;
for (namestart = yytext + yyleng - 7; ISSPACE (*namestart); namestart--)
;
for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
;
namestart -= namelen - 1;
t = create_scalar_type ("function type", sizeof ("function type")-1);
do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
&lexer_line);
update_lineno (yytext, yyleng);
}
[^[:alnum:]_]typedef{WS}{ID}{WS}{ID}{WS}"(" {
char *namestart;
size_t namelen;
struct type *t;
for (namestart = yytext + yyleng - 2; ISSPACE (*namestart); namestart--)
;
for (namelen = 1; !ISSPACE (namestart[-namelen]); namelen++)
;
namestart -= namelen - 1;
t = create_scalar_type ("function type", sizeof ("function type")-1);
do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
&lexer_line);
update_lineno (yytext, yyleng);
}
[^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?PARAMS {
char *namestart;
size_t namelen;
struct type *t;
for (namestart = yytext + yyleng - 7; !ISIDNUM (*namestart); namestart--)
;
for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
;
namestart -= namelen - 1;
t = create_scalar_type ("function type", sizeof ("function type")-1);
do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
&lexer_line);
update_lineno (yytext, yyleng);
}
[^[:alnum:]_]typedef{WS}{ID}{WS}?"*"?{WS}?"("{WS}?"*"{WS}?{ID}{WS}?")"{WS}?"(" {
char *namestart;
size_t namelen;
struct type *t;
for (namestart = yytext + yyleng - 2; !ISIDNUM (*namestart); namestart--)
;
for (namelen = 1; ISIDNUM (namestart[-namelen]); namelen++)
;
namestart -= namelen - 1;
t = create_scalar_type ("function type", sizeof ("function type")-1);
do_typedef ((const char *) xmemdup (namestart, namelen, namelen+1), t,
&lexer_line);
update_lineno (yytext, yyleng);
}
[^[:alnum:]_](typedef{WS})?(struct|union){WS}{ID}{WS}/"GTY" {
char *tagstart;
size_t taglen;
int typedef_p;
int union_p;
typedef_p = yytext[1] == 't';
if (typedef_p)
for (tagstart = yytext + strlen (" typedef ");
ISSPACE(*tagstart);
tagstart++)
;
else
tagstart = yytext + 1;
union_p = tagstart[0] == 'u';
tagstart += strlen ("union ");
while (ISSPACE (*tagstart))
tagstart++;
for (taglen = 1; ISIDNUM (tagstart[taglen]); taglen++)
;
yylval.t = find_structure ((const char *) xmemdup (tagstart, taglen,
taglen + 1),
union_p);
BEGIN(in_struct);
update_lineno (yytext, yyleng);
return typedef_p ? ENT_TYPEDEF_STRUCT : ENT_STRUCT;
}
[^[:alnum:]_](extern|static){WS}/"GTY" {
BEGIN(in_struct);
update_lineno (yytext, yyleng);
return ENT_EXTERNSTATIC;
}
^"%union"{WS}"{"{WS}/"GTY" {
BEGIN(in_struct);
update_lineno (yytext, yyleng);
return ENT_YACCUNION;
}
^"DEF_VEC_"[[:alnum:]_]*{WS}?"("{WS}?{ID}{WS}?")" {
char *macro, *arg;
unsigned macro_len, arg_len;
char *ptr = yytext;
type_p t;
/* Locate the macro and argument strings. */
macro = ptr;
while (*ptr != '(' && !ISSPACE (*ptr))
ptr++;
macro_len = ptr - macro;
while (*ptr == '(' || ISSPACE (*ptr))
ptr++;
arg = ptr;
while (*ptr != ')' && !ISSPACE (*ptr))
ptr++;
arg_len = ptr - arg;
/* Push the macro for later expansion. */
push_macro_expansion (macro, macro_len, arg, arg_len);
/* Create the struct and typedef. */
ptr = (char *) xmemdup ("VEC_", 4, 4 + arg_len + 1);
memcpy (&ptr[4], arg, arg_len);
ptr[4 + arg_len] = 0;
t = find_structure (ptr, 0);
do_typedef (ptr, t, &lexer_line);
}
<in_struct>{
"/*" { BEGIN(in_struct_comment); }
^"%{" { BEGIN(in_yacc_escape); }
^"@@".* /* Used for c-parse.in C/ObjC demarcation. */
{WS} { update_lineno (yytext, yyleng); }
"const"/[^[:alnum:]_] /* don't care */
"GTY"/[^[:alnum:]_] { return GTY_TOKEN; }
"union"/[^[:alnum:]_] { return UNION; }
"struct"/[^[:alnum:]_] { return STRUCT; }
"enum"/[^[:alnum:]_] { return ENUM; }
"ptr_alias"/[^[:alnum:]_] { return ALIAS; }
"nested_ptr"/[^[:alnum:]_] { return NESTED_PTR; }
[0-9]+ { return NUM; }
"param"[0-9]*"_is"/[^[:alnum:]_] {
yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
Index: gcc/ChangeLog 2002-09-12 Geoffrey Keating <geoffk@apple.com> * ggc-common.c (ggc_mark_rtx_children_1): Update for changed name mangling. The following changes are merged from pch-branch: * doc/gty.texi (GTY Options): Document %a. * gengtype.c (do_scalar_typedef): New function. (process_gc_options): Handle `length' option. (set_gc_used_type): A pointer to an array of structures doesn't qualify as a pointer to a structure. (output_escaped_param): Add `%a' escape. (write_gc_structure_fields): Allow 'desc' on array of unions. (main): Define `uint8', `jword' and `JCF_u2' as scalars; use do_scalar_typedef. * gengtype.c (enum rtx_code): Make global. (rtx_format): Make global. (rtx_next): New. (gen_rtx_next): New. (write_rtx_next): New. (adjust_field_rtx_def): Skip fields marked by chain_next. (open_base_files): Delete redundant prototype. (write_enum_defn): New. (output_mangled_typename): Correct abort call. (write_gc_marker_routine_for_structure): Handle chain_next and chain_prev options. (finish_root_table): Don't output redundant \n. (main): Call gen_rtx_next, write_rtx_next, write_enum_defn. * c-tree.h (union lang_tree_node): Add chain_next option. * gengtype.h (NUM_PARAM): New definition. (struct type): For TYPE_PARAM_STRUCT, allow multiple parameters. * gengtype.c (find_param_structure): New. (adjust_field_type): Handle param<n>_is option. (process_gc_options): Detect use_params option. Update callers. (set_gc_used_type): Add 'param' parameter, update callers. Handle 'use_params' option. (open_base_files): Add splay-tree.h to list of files included. (output_mangled_typename): New. (write_gc_structure_fields): Update 'param' parameter to support multiple parameters. Change name mangling. Allow parameterized fields to have an apparent scalar type. Handle param<n>_is options, use_param option. (write_gc_marker_routine_for_structure): Update for change to name mangling. Better guess the output file for parameterized types. (write_gc_types): Update for change to name mangling. (write_gc_root): Update for change to name mangling. Handle (ignore) param<n>_is options. * doc/gty.texi (GTY Options): Add description of param<n>_is options, use_params option. * ggc.h (ggc_mark_rtx): Update for changed name mangling. * gengtype-lex.l: Produce token for param<n>_is. * gengtype-yacc.y: Parse param<n>_is. * gengtype.c (adjust_field_tree_exp): Don't name a variable 'rindex'. * rtl.c: Update comment describing rtx_format. * rtl.h (union rtunion): Separate definition and typedef. (struct rtx_def): Use gengtype to mark. * Makefile.in (gengtype.o): Also depend on rtl.def. * ggc.h (ggc_mark_rtx_children): Delete prototype. (ggc_mark_rtx): Change to alias of gengtype-generated routine. * ggc-common.c (ggc_mark_rtx_children): Delete. (ggc_mark_rtx_children_1): Delete. (gt_ggc_m_rtx_def): Delete. * gengtype.c (adjust_field_rtx_def): New. (adjust_field_type): Call adjust_field_rtx_def. (write_gc_structure_fields): Add 'default' case to switch if none is specified; remove unused code. * tree.h (struct tree_exp): Update for change to meaning of special. * gengtype.c (adjust_field_tree_exp): New function. (adjust_field_type): Handle `tree_exp' special here. (write_gc_structure_fields): Don't handle `tree_exp' special here. Handle new `dot' option. * gengtype.h: Make `info' a pointer-to-const. * gengtype-yacc.y (yacc_ids): Use xasprintf. * gengtype.c (write_gc_structure_fields): Remove implementation of `always' option, add `default' option. * doc/gty.texi (GTY Options): Remove documentation of `always', add `default'. Index: gcc/cp/ChangeLog 2002-09-12 Geoffrey Keating <geoffk@apple.com> * cp-tree.h (union lang_tree_node): Add chain_next option. Index: gcc/f/ChangeLog 2002-09-12 Geoffrey Keating <geoffk@apple.com> * com.c (union lang_tree_node): Add chain_next option. Index: gcc/java/ChangeLog 2002-09-12 Geoffrey Keating <geoffk@apple.com> * java-tree.h (union lang_tree_node): Add chain_next option. From-SVN: r57206
2002-09-16 20:33:23 +02:00
return PARAM_IS;
}
{IWORD}({WS}{IWORD})*/[^[:alnum:]_] |
"ENUM_BITFIELD"{WS}?"("{WS}?{ID}{WS}?")" {
size_t len;
for (len = yyleng; ISSPACE (yytext[len-1]); len--)
;
yylval.t = create_scalar_type (yytext, len);
update_lineno (yytext, yyleng);
return SCALAR;
}
"VEC"{WS}?"("{WS}?{ID}{WS}?")" {
char *macro, *arg;
unsigned macro_len, arg_len;
char *ptr = yytext;
macro = ptr;
while (*ptr != '(' && !ISSPACE (*ptr))
ptr++;
macro_len = ptr - macro;
while (*ptr == '(' || ISSPACE (*ptr))
ptr++;
arg = ptr;
while (*ptr != ')' && !ISSPACE (*ptr))
ptr++;
arg_len = ptr - arg;
ptr = (char *) xmemdup (macro, macro_len, macro_len + arg_len + 2);
ptr[macro_len] = '_';
memcpy (&ptr[macro_len+1], arg, arg_len);
yylval.s = ptr;
return ID;
}
{ID}/[^[:alnum:]_] {
yylval.s = (const char *) xmemdup (yytext, yyleng, yyleng+1);
return ID;
}
\"([^"\\]|\\.)*\" {
yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
return STRING;
}
"["[^\[\]]*"]" {
yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng-1);
return ARRAY;
}
^"%"{ID} {
yylval.s = (const char *) xmemdup (yytext+1, yyleng-1, yyleng);
return PERCENT_ID;
}
"'"("\\".|[^\\])"'" {
yylval.s = (const char *) xmemdup (yytext+1, yyleng-2, yyleng);
return CHAR;
}
[(){},*:<>] { return yytext[0]; }
[;=] {
if (lexer_toplevel_done)
{
BEGIN(INITIAL);
lexer_toplevel_done = 0;
}
return yytext[0];
}
^"%%" {
BEGIN(INITIAL);
return PERCENTPERCENT;
}
. {
error_at_line (&lexer_line, "unexpected character `%s'", yytext);
}
}
"/*" { BEGIN(in_comment); }
\n { lexer_line.line++; }
{ID} |
"'"("\\".|[^\\])"'" |
[^"/\n] /* do nothing */
\"([^"\\]|\\.|\\\n)*\" { update_lineno (yytext, yyleng); }
"/"/[^*] /* do nothing */
<in_comment,in_struct_comment>{
\n { lexer_line.line++; }
[^*\n]{16} |
[^*\n] /* do nothing */
"*"/[^/] /* do nothing */
}
<in_comment>"*/" { BEGIN(INITIAL); }
<in_struct_comment>"*/" { BEGIN(in_struct); }
<in_yacc_escape>{
\n { lexer_line.line++; }
[^%]{16} |
[^%] /* do nothing */
"%"/[^}] /* do nothing */
"%}" { BEGIN(in_struct); }
"%" {
error_at_line (&lexer_line,
"unterminated %%{; unexpected EOF");
}
}
["/] |
<in_struct_comment,in_comment>"*" {
error_at_line (&lexer_line,
"unterminated comment or string; unexpected EOF");
}
^"#define"{WS}"GTY(" /* do nothing */
{WS}"GTY"{WS}?"(" {
error_at_line (&lexer_line, "stray GTY marker");
}
%%
/* Deal with the expansion caused by the DEF_VEC_x macros. */
typedef struct macro
{
const char *name;
const char *expansion;
struct macro *next;
} macro_t;
static const macro_t macro_defs[] =
{
#define IN_GENGTYPE 1
#include "vec.h"
{NULL, NULL, NULL}
};
/* Chain of macro expansions to do at end of scanning. */
static macro_t *macro_expns;
/* Push macro NAME (NAME_LEN) with argument ARG (ARG_LEN) onto the
expansion queue. We ensure NAME is known at this point. */
static void
push_macro_expansion (const char *name, unsigned name_len,
const char *arg, unsigned arg_len)
{
unsigned ix;
for (ix = 0; macro_defs[ix].name; ix++)
if (strlen (macro_defs[ix].name) == name_len
&& !memcmp (name, macro_defs[ix].name, name_len))
{
macro_t *expansion = XNEW (macro_t);
expansion->next = macro_expns;
expansion->name = (char *) xmemdup (arg, arg_len, arg_len+1);
expansion->expansion = macro_defs[ix].expansion;
macro_expns = expansion;
return;
}
error_at_line (&lexer_line, "unrecognized macro `%.*s(%.*s)'",
name_len, name, arg_len, arg);
}
/* Attempt to read some input. Use fread until we're at the end of
file. At end of file expand the next queued macro. We presume the
buffer is large enough for the entire expansion. */
static unsigned
macro_input (char *buffer, unsigned size)
{
unsigned result;
result = fread (buffer, 1, size, yyin);
if (result)
/*NOP*/;
else if (ferror (yyin))
YY_FATAL_ERROR ("read of source file failed");
else if (macro_expns)
{
const char *expn;
unsigned len;
for (expn = macro_expns->expansion; *expn; expn++)
{
if (*expn == '#')
{
if (buffer[result-1] == ' ' && buffer[result-2] == '_')
result--;
len = strlen (macro_expns->name);
memcpy (&buffer[result], macro_expns->name, len);
result += len;
}
else
{
buffer[result++] = *expn;
if (*expn == ';' || *expn == '{')
buffer[result++] = '\n';
}
}
if (result > size)
YY_FATAL_ERROR ("buffer too small to expand macro");
macro_expns = macro_expns->next;
}
return result;
}
void
yyerror (const char *s)
{
error_at_line (&lexer_line, s);
}
void
parse_file (const char *fname)
{
yyin = fopen (fname, "r");
lexer_line.file = fname;
lexer_line.line = 1;
if (yyin == NULL)
{
perror (fname);
exit (1);
}
if (yyparse() != 0)
exit (1);
fclose (yyin);
}