/* -*- indented-text -*- */
/* Process source files and output type information.
Copyright (C) 2002, 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, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
%{
#include "bconfig.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "gengtype.h"
#define YYERROR_VERBOSE
%}
%union {
type_p t;
pair_p p;
options_p o;
const char *s;
}
%token <t>ENT_TYPEDEF_STRUCT
%token <t>ENT_STRUCT
%token ENT_EXTERNSTATIC
%token ENT_YACCUNION
%token GTY_TOKEN
%token UNION
%token STRUCT
%token ENUM
%token ALIAS
%token NESTED_PTR
%token <s>PARAM_IS
%token NUM
%token PERCENTPERCENT "%%"
%token <t>SCALAR
%token <s>ID
%token <s>STRING
%token <s>ARRAY
%token <s>PERCENT_ID
%token <s>CHAR
%type <p> struct_fields yacc_ids yacc_typematch
%type <t> type lasttype
%type <o> optionsopt options option optionseq optionseqopt
%type <s> type_option stringseq
%%
start: /* empty */
| typedef_struct start
| externstatic start
| yacc_union start
;
typedef_struct: ENT_TYPEDEF_STRUCT options '{' struct_fields '}' ID
{
new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
$4, $2);
do_typedef ($6, $1, &lexer_line);
lexer_toplevel_done = 1;
}
';'
{}
| ENT_STRUCT options '{' struct_fields '}'
{
new_structure ($1->u.s.tag, UNION_P ($1), &lexer_line,
$4, $2);
lexer_toplevel_done = 1;
}
';'
{}
;
externstatic: ENT_EXTERNSTATIC options lasttype ID semiequal
{
note_variable ($4, adjust_field_type ($3, $2), $2,
&lexer_line);
}
| ENT_EXTERNSTATIC options lasttype ID ARRAY semiequal
{
note_variable ($4, create_array ($3, $5),
$2, &lexer_line);
}
| ENT_EXTERNSTATIC options lasttype ID ARRAY ARRAY semiequal
{
note_variable ($4, create_array (create_array ($3, $6),
$5),
$2, &lexer_line);
}
;
lasttype: type
{
lexer_toplevel_done = 1;
$$ = $1;
}
;
semiequal: ';'
| '='
;
yacc_union: ENT_YACCUNION options struct_fields '}' yacc_typematch
PERCENTPERCENT
{
note_yacc_type ($2, $3, $5, &lexer_line);
}
;
yacc_typematch: /* empty */
{ $$ = NULL; }
| yacc_typematch PERCENT_ID yacc_ids
{
pair_p p;
for (p = $3; p->next != NULL; p = p->next)
{
p->name = NULL;
p->type = NULL;
}
p->name = NULL;
p->type = NULL;
p->next = $1;
$$ = $3;
}
| yacc_typematch PERCENT_ID '<' ID '>' yacc_ids
{
pair_p p;
type_p newtype = NULL;
if (strcmp ($2, "type") == 0)
newtype = (type_p) 1;
for (p = $6; p->next != NULL; p = p->next)
{
p->name = $4;
p->type = newtype;
}
p->name = $4;
p->next = $1;
p->type = newtype;
$$ = $6;
}
;
yacc_ids: /* empty */
{ $$ = NULL; }
| yacc_ids ID
{
pair_p p = XCNEW (struct pair);
p->next = $1;
p->line = lexer_line;
p->opt = XNEW (struct options);
p->opt->name = "tag";
p->opt->next = NULL;
p->opt->info = (char *)$2;
$$ = p;
}
| yacc_ids CHAR
{
pair_p p = XCNEW (struct pair);
p->next = $1;
p->line = lexer_line;
p->opt = XNEW (struct options);
p->opt->name = "tag";
p->opt->next = NULL;
p->opt->info = xasprintf ("'%s'", $2);
$$ = p;
}
;
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;
}
| 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;
}
| 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 ':' bitfieldlen ';' struct_fields
{ $$ = $5; }
;
bitfieldopt: /* empty */
| ':' bitfieldlen
;
bitfieldlen: NUM | ID
{ }
;
type: SCALAR
{ $$ = $1; }
| ID
{ $$ = resolve_typedef ($1, &lexer_line); }
| type '*'
{ $$ = create_pointer ($1); }
| STRUCT ID '{' struct_fields '}'
{ $$ = new_structure ($2, 0, &lexer_line, $4, NULL); }
| STRUCT ID
{ $$ = find_structure ($2, 0); }
| UNION ID '{' struct_fields '}'
{ $$ = new_structure ($2, 1, &lexer_line, $4, NULL); }
| UNION ID
{ $$ = find_structure ($2, 1); }
| ENUM ID
{ $$ = create_scalar_type ($2, strlen ($2)); }
| ENUM ID '{' enum_items '}'
{ $$ = create_scalar_type ($2, strlen ($2)); }
;
enum_items: /* empty */
| ID '=' NUM ',' enum_items
{ }
| ID ',' enum_items
{ }
| ID enum_items
{ }
;
optionsopt: { $$ = NULL; }
| options { $$ = $1; }
;
options: GTY_TOKEN '(' '(' optionseqopt ')' ')'
{ $$ = $4; }
;
type_option : ALIAS
{ $$ = "ptr_alias"; }
| PARAM_IS
{ $$ = $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 ')'
{
struct nested_ptr_data d;
d.type = adjust_field_type ($3, NULL);
d.convert_to = $5;
d.convert_from = $7;
$$ = create_option (NULL, "nested_ptr",
xmemdup (&d, sizeof (d), sizeof (d)));
}
;
optionseq: option
{
$1->next = NULL;
$$ = $1;
}
| optionseq ',' option
{
$3->next = $1;
$$ = $3;
}
;
optionseqopt: { $$ = NULL; }
| optionseq { $$ = $1; }
;
stringseq: STRING
{ $$ = $1; }
| stringseq STRING
{
size_t l1 = strlen ($1);
size_t l2 = strlen ($2);
char *s = XRESIZEVEC (char, $1, l1 + l2 + 1);
memcpy (s + l1, $2, l2 + 1);
XDELETE ($2);
$$ = s;
}
;
%%