/* $Id: grammar.y,v 1.7 2020/03/30 23:55:49 tom Exp $
*
* yacc grammar for C function prototype generator
* This was derived from the grammar in Appendix A of
* "The C Programming Language" by Kernighan and Ritchie.
*/
%expect 1
%{
#ifdef YYBISON
#include <stdlib.h>
#define YYSTYPE_IS_DECLARED
#define yyerror yaccError
#endif
#if defined(YYBISON) || !defined(YYBYACC)
static void yyerror(const char *s);
#endif
%}
%token <text> '(' '*' '&'
/* identifiers that are not reserved words */
T_IDENTIFIER T_TYPEDEF_NAME T_DEFINE_NAME
/* storage class */
T_AUTO T_EXTERN T_REGISTER T_STATIC T_TYPEDEF
/* This keyword included for compatibility with C++. */
T_INLINE
/* This keyword included for compatibility with GCC */
T_EXTENSION
/* type specifiers */
T_CHAR T_DOUBLE T_FLOAT T_INT T_VOID
T_LONG T_SHORT T_SIGNED T_UNSIGNED
T_ENUM T_STRUCT T_UNION
/* C9X new types */
T_Bool T_Complex T_Imaginary
/* type qualifiers */
T_TYPE_QUALIFIER
/* paired square brackets and everything between them: [ ... ] */
T_BRACKETS
%token
/* left brace */
T_LBRACE
/* all input to the matching right brace */
T_MATCHRBRACE
/* three periods */
T_ELLIPSIS
/* constant expression or paired braces following an equal sign */
T_INITIALIZER
/* string literal */
T_STRING_LITERAL
/* asm */
T_ASM
/* ( "string literal" ) following asm keyword */
T_ASMARG
/* va_dcl from <varargs.h> */
T_VA_DCL
%type <decl_spec> decl_specifiers decl_specifier
%type <decl_spec> storage_class type_specifier type_qualifier
%type <decl_spec> struct_or_union_specifier enum_specifier
%type <decl_list> init_declarator_list
%type <declarator> init_declarator declarator direct_declarator
%type <declarator> abs_declarator direct_abs_declarator
%type <param_list> parameter_type_list parameter_list
%type <parameter> parameter_declaration
%type <param_list> opt_identifier_list identifier_list
%type <text> struct_or_union pointer opt_type_qualifiers type_qualifier_list
any_id identifier_or_ref
%type <text> enumeration
%{
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define OPT_LINTLIBRARY 1
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
/* #include "cproto.h" */
#define MAX_TEXT_SIZE 1024
#define TEXT_LEN (MAX_TEXT_SIZE / 2 - 3)
/* Prototype styles */
#if OPT_LINTLIBRARY
#define PROTO_ANSI_LLIB -2 /* form ANSI lint-library source */
#define PROTO_LINTLIBRARY -1 /* form lint-library source */
#endif
#define PROTO_NONE 0 /* do not output any prototypes */
#define PROTO_TRADITIONAL 1 /* comment out parameters */
#define PROTO_ABSTRACT 2 /* comment out parameter names */
#define PROTO_ANSI 3 /* ANSI C prototype */
typedef int PrototypeStyle;
typedef char boolean;
extern boolean types_out;
extern PrototypeStyle proto_style;
#define ansiLintLibrary() (proto_style == PROTO_ANSI_LLIB)
#define knrLintLibrary() (proto_style == PROTO_LINTLIBRARY)
#define lintLibrary() (knrLintLibrary() || ansiLintLibrary())
#if OPT_LINTLIBRARY
#define FUNC_UNKNOWN -1 /* unspecified */
#else
#define FUNC_UNKNOWN 0 /* unspecified (same as FUNC_NONE) */
#endif
#define FUNC_NONE 0 /* not a function definition */
#define FUNC_TRADITIONAL 1 /* traditional style */
#define FUNC_ANSI 2 /* ANSI style */
#define FUNC_BOTH 3 /* both styles */
typedef int FuncDefStyle;
/* Source file text */
typedef struct text {
char text[MAX_TEXT_SIZE]; /* source text */
long begin; /* offset in temporary file */
} Text;
/* Declaration specifier flags */
#define DS_NONE 0 /* default */
#define DS_EXTERN 1 /* contains "extern" specifier */
#define DS_STATIC 2 /* contains "static" specifier */
#define DS_CHAR 4 /* contains "char" type specifier */
#define DS_SHORT 8 /* contains "short" type specifier */
#define DS_FLOAT 16 /* contains "float" type specifier */
#define DS_INLINE 32 /* contains "inline" specifier */
#define DS_JUNK 64 /* we're not interested in this declaration */
/* This structure stores information about a declaration specifier. */
typedef struct decl_spec {
unsigned short flags; /* flags defined above */
char *text; /* source text */
long begin; /* offset in temporary file */
} DeclSpec;
/* This is a list of function parameters. */
typedef struct _ParameterList {
struct parameter *first; /* pointer to first parameter in list */
struct parameter *last; /* pointer to last parameter in list */
long begin_comment; /* begin offset of comment */
long end_comment; /* end offset of comment */
char *comment; /* comment at start of parameter list */
} ParameterList;
/* This structure stores information about a declarator. */
typedef struct _Declarator {
char *name; /* name of variable or function */
char *text; /* source text */
long begin; /* offset in temporary file */
long begin_comment; /* begin offset of comment */
long end_comment; /* end offset of comment */
FuncDefStyle func_def; /* style of function definition */
ParameterList params; /* function parameters */
boolean pointer; /* TRUE if it declares a pointer */
struct _Declarator *head; /* head function declarator */
struct _Declarator *func_stack; /* stack of function declarators */
struct _Declarator *next; /* next declarator in list */
} Declarator;
/* This structure stores information about a function parameter. */
typedef struct parameter {
struct parameter *next; /* next parameter in list */
DeclSpec decl_spec;
Declarator *declarator;
char *comment; /* comment following the parameter */
} Parameter;
/* This is a list of declarators. */
typedef struct declarator_list {
Declarator *first; /* pointer to first declarator in list */
Declarator *last; /* pointer to last declarator in list */
} DeclaratorList;
/* #include "symbol.h" */
typedef struct symbol {
struct symbol *next; /* next symbol in list */
char *name; /* name of symbol */
char *value; /* value of symbol (for defines) */
short flags; /* symbol attributes */
} Symbol;
/* parser stack entry type */
typedef union {
Text text;
DeclSpec decl_spec;
Parameter *parameter;
ParameterList param_list;
Declarator *declarator;
DeclaratorList decl_list;
} YYSTYPE;
/* The hash table length should be a prime number. */
#define SYM_MAX_HASH 251
typedef struct symbol_table {
Symbol *bucket[SYM_MAX_HASH]; /* hash buckets */
} SymbolTable;
extern SymbolTable *new_symbol_table /* Create symbol table */
(void);
extern void free_symbol_table /* Destroy symbol table */
(SymbolTable *s);
extern Symbol *find_symbol /* Lookup symbol name */
(SymbolTable *s, const char *n);
extern Symbol *new_symbol /* Define new symbol */
(SymbolTable *s, const char *n, const char *v, int f);
/* #include "semantic.h" */
extern void new_decl_spec (DeclSpec *, const char *, long, int);
extern void free_decl_spec (DeclSpec *);
extern void join_decl_specs (DeclSpec *, DeclSpec *, DeclSpec *);
extern void check_untagged (DeclSpec *);
extern Declarator *new_declarator (const char *, const char *, long);
extern void free_declarator (Declarator *);
extern void new_decl_list (DeclaratorList *, Declarator *);
extern void free_decl_list (DeclaratorList *);
extern void add_decl_list (DeclaratorList *, DeclaratorList *, Declarator *);
extern Parameter *new_parameter (DeclSpec *, Declarator *);
extern void free_parameter (Parameter *);
extern void new_param_list (ParameterList *, Parameter *);
extern void free_param_list (ParameterList *);
extern void add_param_list (ParameterList *, ParameterList *, Parameter *);
extern void new_ident_list (ParameterList *);
extern void add_ident_list (ParameterList *, ParameterList *, const char *);
extern void set_param_types (ParameterList *, DeclSpec *, DeclaratorList *);
extern void gen_declarations (DeclSpec *, DeclaratorList *);
extern void gen_prototype (DeclSpec *, Declarator *);
extern void gen_func_declarator (Declarator *);
extern void gen_func_definition (DeclSpec *, Declarator *);
extern void init_parser (void);
extern void process_file (FILE *infile, char *name);
extern char *cur_text (void);
extern char *cur_file_name (void);
extern char *implied_typedef (void);
extern void include_file (char *name, int convert);
extern char *supply_parm (int count);
extern char *xstrdup (const char *);
extern int already_declared (char *name);
extern int is_actual_func (Declarator *d);
extern int lint_ellipsis (Parameter *p);
extern int want_typedef (void);
extern void begin_tracking (void);
extern void begin_typedef (void);
extern void copy_typedef (char *s);
extern void ellipsis_varargs (Declarator *d);
extern void end_typedef (void);
extern void flush_varargs (void);
extern void fmt_library (int code);
extern void imply_typedef (const char *s);
extern void indent (FILE *outf);
extern void put_blankline (FILE *outf);
extern void put_body (FILE *outf, DeclSpec *decl_spec, Declarator *declarator);
extern void put_char (FILE *outf, int c);
extern void put_error (void);
extern void put_newline (FILE *outf);
extern void put_padded (FILE *outf, const char *s);
extern void put_string (FILE *outf, const char *s);
extern void track_in (void);
extern boolean file_comments;
extern FuncDefStyle func_style;
extern char base_file[];
extern int yylex (void);
/* declaration specifier attributes for the typedef statement currently being
* scanned
*/
static int cur_decl_spec_flags;
/* pointer to parameter list for the current function definition */
static ParameterList *func_params;
/* A parser semantic action sets this pointer to the current declarator in
* a function parameter declaration in order to catch any comments following
* the parameter declaration on the same line. If the lexer scans a comment
* and <cur_declarator> is not NULL, then the comment is attached to the
* declarator. To ignore subsequent comments, the lexer sets this to NULL
* after scanning a comment or end of line.
*/
static Declarator *cur_declarator;
/* temporary string buffer */
static char buf[MAX_TEXT_SIZE];
/* table of typedef names */
static SymbolTable *typedef_names;
/* table of define names */
static SymbolTable *define_names;
/* table of type qualifiers */
static SymbolTable *type_qualifiers;
/* information about the current input file */
typedef struct {
char *base_name; /* base input file name */
char *file_name; /* current file name */
FILE *file; /* input file */
unsigned line_num; /* current line number in input file */
FILE *tmp_file; /* temporary file */
long begin_comment; /* tmp file offset after last written ) or ; */
long end_comment; /* tmp file offset after last comment */
boolean convert; /* if TRUE, convert function definitions */
boolean changed; /* TRUE if conversion done in this file */
} IncludeStack;
static IncludeStack *cur_file; /* current input file */
/* #include "yyerror.c" */
static int haveAnsiParam (void);
/* Flags to enable us to find if a procedure returns a value.
*/
static int return_val; /* nonzero on BRACES iff return-expression found */
static const char *
dft_decl_spec (void)
{
return (lintLibrary() && !return_val) ? "void" : "int";
}
static int
haveAnsiParam (void)
{
Parameter *p;
if (func_params != 0) {
for (p = func_params->first; p != 0; p = p->next) {
if (p->declarator->func_def == FUNC_ANSI) {
return TRUE;
}
}
}
return FALSE;
}
%}
%%
program
: /* empty */
| translation_unit
;
translation_unit
: external_declaration
| translation_unit external_declaration
;
external_declaration
: declaration
| function_definition
| ';'
| linkage_specification
| T_ASM T_ASMARG ';'
| error T_MATCHRBRACE
{
yyerrok;
}
| error ';'
{
yyerrok;
}
;
braces
: T_LBRACE T_MATCHRBRACE
;
linkage_specification
: T_EXTERN T_STRING_LITERAL braces
{
/* Provide an empty action here so bison will not complain about
* incompatible types in the default action it normally would
* have generated.
*/
}
| T_EXTERN T_STRING_LITERAL declaration
{
/* empty */
}
;
declaration
: decl_specifiers ';'
{
#if OPT_LINTLIBRARY
if (types_out && want_typedef()) {
gen_declarations(&$1, (DeclaratorList *)0);
flush_varargs();
}
#endif
free_decl_spec(&$1);
end_typedef();
}
| decl_specifiers init_declarator_list ';'
{
if (func_params != NULL) {
set_param_types(func_params, &$1, &$2);
} else {
gen_declarations(&$1, &$2);
#if OPT_LINTLIBRARY
flush_varargs();
#endif
free_decl_list(&$2);
}
free_decl_spec(&$1);
end_typedef();
}
| any_typedef decl_specifiers
{
cur_decl_spec_flags = $2.flags;
free_decl_spec(&$2);
}
opt_declarator_list ';'
{
end_typedef();
}
;
any_typedef
: T_EXTENSION T_TYPEDEF
{
begin_typedef();
}
| T_TYPEDEF
{
begin_typedef();
}
;
opt_declarator_list
: /* empty */
| declarator_list
;
declarator_list
: declarator
{
int flags = cur_decl_spec_flags;
/* If the typedef is a pointer type, then reset the short type
* flags so it does not get promoted.
*/
if (strcmp($1->text, $1->name) != 0)
flags &= ~(DS_CHAR | DS_SHORT | DS_FLOAT);
new_symbol(typedef_names, $1->name, NULL, flags);
free_declarator($1);
}
| declarator_list ',' declarator
{
int flags = cur_decl_spec_flags;
if (strcmp($3->text, $3->name) != 0)
flags &= ~(DS_CHAR | DS_SHORT | DS_FLOAT);
new_symbol(typedef_names, $3->name, NULL, flags);
free_declarator($3);
}
;
function_definition
: decl_specifiers declarator
{
check_untagged(&$1);
if ($2->func_def == FUNC_NONE) {
yyerror("syntax error");
YYERROR;
}
func_params = &($2->head->params);
func_params->begin_comment = cur_file->begin_comment;
func_params->end_comment = cur_file->end_comment;
}
opt_declaration_list T_LBRACE
{
/* If we're converting to K&R and we've got a nominally K&R
* function which has a parameter which is ANSI (i.e., a prototyped
* function pointer), then we must override the deciphered value of
* 'func_def' so that the parameter will be converted.
*/
if (func_style == FUNC_TRADITIONAL
&& haveAnsiParam()
&& $2->head->func_def == func_style) {
$2->head->func_def = FUNC_BOTH;
}
func_params = NULL;
if (cur_file->convert)
gen_func_definition(&$1, $2);
gen_prototype(&$1, $2);
#if OPT_LINTLIBRARY
flush_varargs();
#endif
free_decl_spec(&$1);
free_declarator($2);
}
T_MATCHRBRACE
| declarator
{
if ($1->func_def == FUNC_NONE) {
yyerror("syntax error");
YYERROR;
}
func_params = &($1->head->params);
func_params->begin_comment = cur_file->begin_comment;
func_params->end_comment = cur_file->end_comment;
}
opt_declaration_list T_LBRACE T_MATCHRBRACE
{
DeclSpec decl_spec;
func_params = NULL;
new_decl_spec(&decl_spec, dft_decl_spec(), $1->begin, DS_NONE);
if (cur_file->convert)
gen_func_definition(&decl_spec, $1);
gen_prototype(&decl_spec, $1);
#if OPT_LINTLIBRARY
flush_varargs();
#endif
free_decl_spec(&decl_spec);
free_declarator($1);
}
;
opt_declaration_list
: /* empty */
| T_VA_DCL
| declaration_list
;
declaration_list
: declaration
| declaration_list declaration
;
decl_specifiers
: decl_specifier
| decl_specifiers decl_specifier
{
join_decl_specs(&$$, &$1, &$2);
free($1.text);
free($2.text);
}
;
decl_specifier
: storage_class
| type_specifier
| type_qualifier
;
storage_class
: T_AUTO
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_EXTERN
{
new_decl_spec(&$$, $1.text, $1.begin, DS_EXTERN);
}
| T_REGISTER
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_STATIC
{
new_decl_spec(&$$, $1.text, $1.begin, DS_STATIC);
}
| T_INLINE
{
new_decl_spec(&$$, $1.text, $1.begin, DS_INLINE);
}
| T_EXTENSION
{
new_decl_spec(&$$, $1.text, $1.begin, DS_JUNK);
}
;
type_specifier
: T_CHAR
{
new_decl_spec(&$$, $1.text, $1.begin, DS_CHAR);
}
| T_DOUBLE
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_FLOAT
{
new_decl_spec(&$$, $1.text, $1.begin, DS_FLOAT);
}
| T_INT
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_LONG
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_SHORT
{
new_decl_spec(&$$, $1.text, $1.begin, DS_SHORT);
}
| T_SIGNED
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_UNSIGNED
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_VOID
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_Bool
{
new_decl_spec(&$$, $1.text, $1.begin, DS_CHAR);
}
| T_Complex
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_Imaginary
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_TYPEDEF_NAME
{
Symbol *s;
s = find_symbol(typedef_names, $1.text);
if (s != NULL)
new_decl_spec(&$$, $1.text, $1.begin, s->flags);
}
| struct_or_union_specifier
| enum_specifier
;
type_qualifier
: T_TYPE_QUALIFIER
{
new_decl_spec(&$$, $1.text, $1.begin, DS_NONE);
}
| T_DEFINE_NAME
{
/* This rule allows the <pointer> nonterminal to scan #define
* names as if they were type modifiers.
*/
Symbol *s;
s = find_symbol(define_names, $1.text);
if (s != NULL)
new_decl_spec(&$$, $1.text, $1.begin, s->flags);
}
;
struct_or_union_specifier
: struct_or_union any_id braces
{
char *s;
if ((s = implied_typedef()) == 0)
(void)sprintf(s = buf, "%.*s %.*s", TEXT_LEN, $1.text, TEXT_LEN, $2.text);
new_decl_spec(&$$, s, $1.begin, DS_NONE);
}
| struct_or_union braces
{
char *s;
if ((s = implied_typedef()) == 0)
(void)sprintf(s = buf, "%.*s {}", TEXT_LEN, $1.text);
new_decl_spec(&$$, s, $1.begin, DS_NONE);
}
| struct_or_union any_id
{
(void)sprintf(buf, "%.*s %.*s", TEXT_LEN, $1.text, TEXT_LEN, $2.text);
new_decl_spec(&$$, buf, $1.begin, DS_NONE);
}
;
struct_or_union
: T_STRUCT
{
imply_typedef($$.text);
}
| T_UNION
{
imply_typedef($$.text);
}
;
init_declarator_list
: init_declarator
{
new_decl_list(&$$, $1);
}
| init_declarator_list ',' init_declarator
{
add_decl_list(&$$, &$1, $3);
}
;
init_declarator
: declarator
{
if ($1->func_def != FUNC_NONE && func_params == NULL &&
func_style == FUNC_TRADITIONAL && cur_file->convert) {
gen_func_declarator($1);
fputs(cur_text(), cur_file->tmp_file);
}
cur_declarator = $$;
}
| declarator '='
{
if ($1->func_def != FUNC_NONE && func_params == NULL &&
func_style == FUNC_TRADITIONAL && cur_file->convert) {
gen_func_declarator($1);
fputs(" =", cur_file->tmp_file);
}
}
T_INITIALIZER
;
enum_specifier
: enumeration any_id braces
{
char *s;
if ((s = implied_typedef()) == 0)
(void)sprintf(s = buf, "enum %.*s", TEXT_LEN, $2.text);
new_decl_spec(&$$, s, $1.begin, DS_NONE);
}
| enumeration braces
{
char *s;
if ((s = implied_typedef()) == 0)
(void)sprintf(s = buf, "%.*s {}", TEXT_LEN, $1.text);
new_decl_spec(&$$, s, $1.begin, DS_NONE);
}
| enumeration any_id
{
(void)sprintf(buf, "enum %.*s", TEXT_LEN, $2.text);
new_decl_spec(&$$, buf, $1.begin, DS_NONE);
}
;
enumeration
: T_ENUM
{
imply_typedef("enum");
$$ = $1;
}
;
any_id
: T_IDENTIFIER
| T_TYPEDEF_NAME
;
declarator
: pointer direct_declarator
{
$$ = $2;
(void)sprintf(buf, "%.*s%.*s", TEXT_LEN, $1.text, TEXT_LEN, $$->text);
free($$->text);
$$->text = xstrdup(buf);
$$->begin = $1.begin;
$$->pointer = TRUE;
}
| direct_declarator
;
direct_declarator
: identifier_or_ref
{
$$ = new_declarator($1.text, $1.text, $1.begin);
}
| '(' declarator ')'
{
$$ = $2;
(void)sprintf(buf, "(%.*s)", TEXT_LEN, $$->text);
free($$->text);
$$->text = xstrdup(buf);
$$->begin = $1.begin;
}
| direct_declarator T_BRACKETS
{
$$ = $1;
(void)sprintf(buf, "%.*s%.*s", TEXT_LEN, $$->text, TEXT_LEN, $2.text);
free($$->text);
$$->text = xstrdup(buf);
}
| direct_declarator '(' parameter_type_list ')'
{
$$ = new_declarator("%s()", $1->name, $1->begin);
$$->params = $3;
$$->func_stack = $1;
$$->head = ($1->func_stack == NULL) ? $$ : $1->head;
$$->func_def = FUNC_ANSI;
}
| direct_declarator '(' opt_identifier_list ')'
{
$$ = new_declarator("%s()", $1->name, $1->begin);
$$->params = $3;
$$->func_stack = $1;
$$->head = ($1->func_stack == NULL) ? $$ : $1->head;
$$->func_def = FUNC_TRADITIONAL;
}
;
pointer
: '*' opt_type_qualifiers
{
(void)sprintf($$.text, "*%.*s", TEXT_LEN, $2.text);
$$.begin = $1.begin;
}
| '*' opt_type_qualifiers pointer
{
(void)sprintf($$.text, "*%.*s%.*s", TEXT_LEN, $2.text, TEXT_LEN, $3.text);
$$.begin = $1.begin;
}
;
opt_type_qualifiers
: /* empty */
{
strcpy($$.text, "");
$$.begin = 0L;
}
| type_qualifier_list
;
type_qualifier_list
: type_qualifier
{
(void)sprintf($$.text, "%s ", $1.text);
$$.begin = $1.begin;
free($1.text);
}
| type_qualifier_list type_qualifier
{
(void)sprintf($$.text, "%.*s%.*s ", TEXT_LEN, $1.text, TEXT_LEN, $2.text);
$$.begin = $1.begin;
free($2.text);
}
;
parameter_type_list
: parameter_list
| parameter_list ',' T_ELLIPSIS
{
add_ident_list(&$$, &$1, "...");
}
;
parameter_list
: parameter_declaration
{
new_param_list(&$$, $1);
}
| parameter_list ',' parameter_declaration
{
add_param_list(&$$, &$1, $3);
}
;
parameter_declaration
: decl_specifiers declarator
{
check_untagged(&$1);
$$ = new_parameter(&$1, $2);
}
| decl_specifiers abs_declarator
{
check_untagged(&$1);
$$ = new_parameter(&$1, $2);
}
| decl_specifiers
{
check_untagged(&$1);
$$ = new_parameter(&$1, (Declarator *)0);
}
;
opt_identifier_list
: /* empty */
{
new_ident_list(&$$);
}
| identifier_list
;
identifier_list
: any_id
{
new_ident_list(&$$);
add_ident_list(&$$, &$$, $1.text);
}
| identifier_list ',' any_id
{
add_ident_list(&$$, &$1, $3.text);
}
;
identifier_or_ref
: any_id
{
$$ = $1;
}
| '&' any_id
{
#if OPT_LINTLIBRARY
if (lintLibrary()) { /* Lint doesn't grok C++ ref variables */
$$ = $2;
} else
#endif
(void)sprintf($$.text, "&%.*s", TEXT_LEN, $2.text);
$$.begin = $1.begin;
}
;
abs_declarator
: pointer
{
$$ = new_declarator($1.text, "", $1.begin);
}
| pointer direct_abs_declarator
{
$$ = $2;
(void)sprintf(buf, "%.*s%.*s", TEXT_LEN, $1.text, TEXT_LEN, $$->text);
free($$->text);
$$->text = xstrdup(buf);
$$->begin = $1.begin;
}
| direct_abs_declarator
;
direct_abs_declarator
: '(' abs_declarator ')'
{
$$ = $2;
(void)sprintf(buf, "(%.*s)", TEXT_LEN, $$->text);
free($$->text);
$$->text = xstrdup(buf);
$$->begin = $1.begin;
}
| direct_abs_declarator T_BRACKETS
{
$$ = $1;
(void)sprintf(buf, "%.*s%.*s", TEXT_LEN, $$->text, TEXT_LEN, $2.text);
free($$->text);
$$->text = xstrdup(buf);
}
| T_BRACKETS
{
$$ = new_declarator($1.text, "", $1.begin);
}
| direct_abs_declarator '(' parameter_type_list ')'
{
$$ = new_declarator("%s()", "", $1->begin);
$$->params = $3;
$$->func_stack = $1;
$$->head = ($1->func_stack == NULL) ? $$ : $1->head;
$$->func_def = FUNC_ANSI;
}
| direct_abs_declarator '(' ')'
{
$$ = new_declarator("%s()", "", $1->begin);
$$->func_stack = $1;
$$->head = ($1->func_stack == NULL) ? $$ : $1->head;
$$->func_def = FUNC_ANSI;
}
| '(' parameter_type_list ')'
{
Declarator *d;
d = new_declarator("", "", $1.begin);
$$ = new_declarator("%s()", "", $1.begin);
$$->params = $2;
$$->func_stack = d;
$$->head = $$;
$$->func_def = FUNC_ANSI;
}
| '(' ')'
{
Declarator *d;
d = new_declarator("", "", $1.begin);
$$ = new_declarator("%s()", "", $1.begin);
$$->func_stack = d;
$$->head = $$;
$$->func_def = FUNC_ANSI;
}
;
%%
/* lex.yy.c */
#define BEGIN yy_start = 1 + 2 *
#define CPP1 1
#define INIT1 2
#define INIT2 3
#define CURLY 4
#define LEXYACC 5
#define ASM 6
#define CPP_INLINE 7
extern char *yytext;
extern FILE *yyin, *yyout;
static int curly; /* number of curly brace nesting levels */
static int ly_count; /* number of occurrences of %% */
static int inc_depth; /* include nesting level */
static SymbolTable *included_files; /* files already included */
static int yy_start = 0; /* start state number */
#define grammar_error(s) yaccError(s)
static void
yaccError (const char *msg)
{
func_params = NULL;
put_error(); /* tell what line we're on, and what file */
fprintf(stderr, "%s at token '%s'\n", msg, yytext);
}
/* Initialize the table of type qualifier keywords recognized by the lexical
* analyzer.
*/
void
init_parser (void)
{
static const char *keywords[] = {
"const",
"restrict",
"volatile",
"interrupt",
#ifdef vms
"noshare",
"readonly",
#endif
#if defined(MSDOS) || defined(OS2)
"__cdecl",
"__export",
"__far",
"__fastcall",
"__fortran",
"__huge",
"__inline",
"__interrupt",
"__loadds",
"__near",
"__pascal",
"__saveregs",
"__segment",
"__stdcall",
"__syscall",
"_cdecl",
"_cs",
"_ds",
"_es",
"_export",
"_far",
"_fastcall",
"_fortran",
"_huge",
"_interrupt",
"_loadds",
"_near",
"_pascal",
"_saveregs",
"_seg",
"_segment",
"_ss",
"cdecl",
"far",
"huge",
"near",
"pascal",
#ifdef OS2
"__far16",
#endif
#endif
#ifdef __GNUC__
/* gcc aliases */
"__builtin_va_arg",
"__builtin_va_list",
"__const",
"__const__",
"__inline",
"__inline__",
"__restrict",
"__restrict__",
"__volatile",
"__volatile__",
#endif
};
unsigned i;
/* Initialize type qualifier table. */
type_qualifiers = new_symbol_table();
for (i = 0; i < sizeof(keywords)/sizeof(keywords[0]); ++i) {
new_symbol(type_qualifiers, keywords[i], NULL, DS_NONE);
}
}
/* Process the C source file. Write function prototypes to the standard
* output. Convert function definitions and write the converted source
* code to a temporary file.
*/
void
process_file (FILE *infile, char *name)
{
char *s;
if (strlen(name) > 2) {
s = name + strlen(name) - 2;
if (*s == '.') {
++s;
if (*s == 'l' || *s == 'y')
BEGIN LEXYACC;
#if defined(MSDOS) || defined(OS2)
if (*s == 'L' || *s == 'Y')
BEGIN LEXYACC;
#endif
}
}
included_files = new_symbol_table();
typedef_names = new_symbol_table();
define_names = new_symbol_table();
inc_depth = -1;
curly = 0;
ly_count = 0;
func_params = NULL;
yyin = infile;
include_file(strcpy(base_file, name), func_style != FUNC_NONE);
if (file_comments) {
#if OPT_LINTLIBRARY
if (lintLibrary()) {
put_blankline(stdout);
begin_tracking();
}
#endif
put_string(stdout, "/* ");
put_string(stdout, cur_file_name());
put_string(stdout, " */\n");
}
yyparse();
free_symbol_table(define_names);
free_symbol_table(typedef_names);
free_symbol_table(included_files);
}
#ifdef NO_LEAKS
void
free_parser(void)
{
free_symbol_table (type_qualifiers);
#ifdef FLEX_SCANNER
if (yy_current_buffer != 0)
yy_delete_buffer(yy_current_buffer);
#endif
}
#endif