540 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			540 lines
		
	
	
	
		
			11 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /*
 | |
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|  * See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
|  */
 | |
| /* $Id$ */
 | |
| /*	DECLARATION SYNTAX PARSER	*/
 | |
| 
 | |
| {
 | |
| #include	"lint.h"
 | |
| #include	"dbsymtab.h"
 | |
| #include	<alloc.h>
 | |
| #include	"nobitfield.h"
 | |
| #include	"debug.h"
 | |
| #include	"arith.h"
 | |
| #include	"LLlex.h"
 | |
| #include	"label.h"
 | |
| #include	"code.h"
 | |
| #include	"idf.h"
 | |
| #include	"type.h"
 | |
| #include	"struct.h"
 | |
| #include	"field.h"
 | |
| #include	"decspecs.h"
 | |
| #include	"def.h"
 | |
| #include	"declar.h"
 | |
| #include	"label.h"
 | |
| #include	"expr.h"
 | |
| #include	"sizes.h"
 | |
| #include	"level.h"
 | |
| #ifdef	LINT
 | |
| #include	"l_lint.h"
 | |
| #endif	/* LINT */
 | |
| 
 | |
| extern char options[];
 | |
| }
 | |
| 
 | |
| /* 8 */
 | |
| declaration
 | |
| 	{struct decspecs Ds;}
 | |
| :
 | |
| 	{Ds = null_decspecs;}
 | |
| 	decl_specifiers(&Ds)
 | |
| 	[%default		/* missing identifier derailed parser */
 | |
| 		init_declarator_list(&Ds)
 | |
| 	|
 | |
| 		empty
 | |
| 	]
 | |
| 	';'
 | |
| ;
 | |
| 
 | |
| /*	A `decl_specifiers' describes a sequence of a storage_class_specifier,
 | |
| 	an unsigned_specifier, a size_specifier and a simple type_specifier,
 | |
| 	which may occur in arbitrary order and each of which may be absent;
 | |
| 	at least one of them must be present, however, since the totally
 | |
| 	empty case has already be dealt with in `external_definition'.
 | |
| 	This means that something like:
 | |
| 		unsigned extern int short xx;
 | |
| 	is perfectly good C.
 | |
| 
 | |
| 	On top of that, multiple occurrences of storage_class_specifiers,
 | |
| 	unsigned_specifiers and size_specifiers are errors, but a second
 | |
| 	type_specifier should end the decl_specifiers and be treated as
 | |
| 	the name to be declared (see the thin ice in RM11.1).
 | |
| 	Such a language is not easily expressed in a grammar; enumeration
 | |
| 	of the permutations is unattractive. We solve the problem by
 | |
| 	having a regular grammar for the "soft" items, handling the single
 | |
| 	occurrence of the type_specifier in the grammar (we have no choice),
 | |
| 	collecting all data in a `struct decspecs' and turning that data
 | |
| 	structure into what we want.
 | |
| 
 | |
| 	The existence of declarations like
 | |
| 		short typedef yepp;
 | |
| 	makes all hope of writing a specific grammar for typedefs illusory.
 | |
| */
 | |
| 
 | |
| decl_specifiers	/* non-empty */ (register struct decspecs *ds;)
 | |
| 	/*	Reads a non-empty decl_specifiers and fills the struct
 | |
| 		decspecs *ds.
 | |
| 	*/
 | |
| :
 | |
| [
 | |
| 	other_specifier(ds)+
 | |
| 	[%if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
 | |
| 		/* the thin ice in R.M. 11.1 */
 | |
| 		single_type_specifier(ds) other_specifier(ds)*
 | |
| 	|
 | |
| 		empty
 | |
| 	]
 | |
| |
 | |
| 	single_type_specifier(ds) other_specifier(ds)*
 | |
| ]
 | |
| 	{do_decspecs(ds);}
 | |
| ;
 | |
| 
 | |
| /* 8.1 */
 | |
| other_specifier(register struct decspecs *ds;):
 | |
| 	[ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
 | |
| 	{	if (ds->ds_sc_given)
 | |
| 			error("repeated storage class specifier");
 | |
| 		ds->ds_sc_given = 1;
 | |
| 		ds->ds_sc = DOT;
 | |
| 	}
 | |
| |
 | |
| 	[ SHORT | LONG ]
 | |
| 	{	if (ds->ds_size)
 | |
| 			error("repeated size specifier");
 | |
| 		ds->ds_size = DOT;
 | |
| 	}
 | |
| |
 | |
| 	UNSIGNED
 | |
| 	{	if (ds->ds_unsigned)
 | |
| 			error("unsigned specified twice");
 | |
| 		ds->ds_unsigned = 1;
 | |
| 	}
 | |
| ;
 | |
| 
 | |
| /* 8.2 */
 | |
| type_specifier(struct type **tpp;)
 | |
| 	/*	Used in struct/union declarations and in casts; only the
 | |
| 		type is relevant.
 | |
| 	*/
 | |
| 	{struct decspecs Ds; Ds = null_decspecs;}
 | |
| :
 | |
| 	decl_specifiers(&Ds)
 | |
| 	{
 | |
| 		if (Ds.ds_sc_given)
 | |
| 			error("storage class ignored");
 | |
| 		if (Ds.ds_sc == REGISTER)
 | |
| 			error("register ignored");
 | |
| 	}
 | |
| 	{*tpp = Ds.ds_type;}
 | |
| ;
 | |
| 
 | |
| single_type_specifier(register struct decspecs *ds;):
 | |
| 	%default TYPE_IDENTIFIER	/* this includes INT, CHAR, etc. */
 | |
| 	{idf2type(dot.tk_idf, &ds->ds_type);}
 | |
| |
 | |
| 	%erroneous
 | |
| 	IDENTIFIER
 | |
| 	{
 | |
| 		error("%s is not a type identifier", dot.tk_idf->id_text);
 | |
| 		ds->ds_type = error_type;
 | |
| 		if (dot.tk_idf->id_def) {
 | |
| 			dot.tk_idf->id_def->df_type = error_type;
 | |
| 			dot.tk_idf->id_def->df_sc = TYPEDEF;
 | |
| 		}
 | |
| 	}
 | |
| |
 | |
| 	%illegal
 | |
| 	IDENTIFIER
 | |
| |
 | |
| 	struct_or_union_specifier(&ds->ds_type)
 | |
| |
 | |
| 	enum_specifier(&ds->ds_type)
 | |
| ;
 | |
| 
 | |
| /* 8.3 */
 | |
| init_declarator_list(struct decspecs *ds;):
 | |
| 	init_declarator(ds)
 | |
| 	[ ',' init_declarator(ds) ]*
 | |
| ;
 | |
| 
 | |
| init_declarator(register struct decspecs *ds;)
 | |
| 	{
 | |
| 		struct declarator Dc;
 | |
| 	}
 | |
| :
 | |
| 	{
 | |
| 		Dc = null_declarator;
 | |
| 	}
 | |
| [
 | |
| 	declarator(&Dc)
 | |
| 	{
 | |
| 		reject_params(&Dc);
 | |
| 		declare_idf(ds, &Dc, level);
 | |
| #ifdef	LINT
 | |
| 		lint_declare_idf(Dc.dc_idf, ds->ds_sc);
 | |
| #endif	/* LINT */
 | |
| 	}
 | |
| 	[
 | |
| 		initializer(Dc.dc_idf, ds->ds_sc)
 | |
| 	|
 | |
| 		{ code_declaration(Dc.dc_idf, (struct expr *) 0, level, ds->ds_sc); }
 | |
| 	]
 | |
| ]
 | |
| 	{
 | |
| #ifdef	LINT
 | |
| 		add_auto(Dc.dc_idf);
 | |
| #endif	/* LINT */
 | |
| 		remove_declarator(&Dc);
 | |
| 	}
 | |
| ;
 | |
| 
 | |
| /* 8.6: initializer */
 | |
| initializer(struct idf *idf; int sc;)
 | |
| 	{
 | |
| 		struct expr *expr = (struct expr *) 0;
 | |
| 		int globalflag = level == L_GLOBAL ||
 | |
| 				 (level >= L_LOCAL && sc == STATIC);
 | |
| 	}
 | |
| :
 | |
| 	{	if (idf->id_def->df_type->tp_fund == FUNCTION)	{
 | |
| 			error("illegal initialization of function");
 | |
| 			idf->id_def->df_type->tp_fund = ERRONEOUS;
 | |
| 		}
 | |
| 		if (level == L_FORMAL2)
 | |
| 			warning("illegal initialization of formal parameter (ignored)");
 | |
| 	}
 | |
| 	'='				/* used to be optional because of V6 */
 | |
| 	{
 | |
| #ifdef	LINT
 | |
| 		lint_statement();
 | |
| #endif	/* LINT */
 | |
| 		if (globalflag) {
 | |
| 			struct expr ex;
 | |
| 			code_declaration(idf, &ex, level, sc);
 | |
| 		}
 | |
| 	}
 | |
| 	initial_value(globalflag ? &(idf->id_def->df_type) : (struct type **)0,
 | |
| 			&expr)
 | |
| 	{	if (! globalflag) {
 | |
| 			if (idf->id_def->df_type->tp_fund == FUNCTION)	{
 | |
| 				free_expression(expr);
 | |
| 				expr = 0;
 | |
| 			}
 | |
| #ifdef	DEBUG
 | |
| 			print_expr("initializer-expression", expr);
 | |
| #endif	/* DEBUG */
 | |
| #ifdef	LINT
 | |
| 			change_state(idf, SET);
 | |
| #endif	/* LINT */
 | |
| #ifdef	DBSYMTAB
 | |
| 			if (options['g'] && level >= L_LOCAL && expr) {
 | |
| 				db_line(expr->ex_file, (unsigned) expr->ex_line)
 | |
| ;
 | |
| 			}
 | |
| #endif	/* DBSYMTAB */
 | |
| 			code_declaration(idf, expr, level, sc);
 | |
| 		}
 | |
| #ifdef	DBSYMTAB
 | |
| 		if (options['g'] && globalflag) {
 | |
| 			stb_string(idf->id_def, sc, idf->id_text);
 | |
| 		}
 | |
| #endif	/* DBSYMTAB */
 | |
| 		init_idf(idf);
 | |
| 	}
 | |
| ;
 | |
| 
 | |
| /*
 | |
| 	Functions yielding pointers to functions must be declared as, e.g.,
 | |
| 		int (*hehe(par1, par2))() char *par1, *par2;	{}
 | |
| 	Since the function heading is read as a normal declarator,
 | |
| 	we just include the (formal) parameter list in the declarator
 | |
| 	description list dc.
 | |
| */
 | |
| declarator(register struct declarator *dc;)
 | |
| 	{
 | |
| 		arith count;
 | |
| 		struct formal *fm = 0;
 | |
| 	}
 | |
| :
 | |
| 	primary_declarator(dc)
 | |
| 	[
 | |
| 		'('
 | |
| 		formal_list(&fm) ?	/* semantic check later...	*/
 | |
| 		')'
 | |
| 		{
 | |
| 			add_decl_unary(dc, FUNCTION, (arith)0, fm);
 | |
| 			fm = 0;
 | |
| 		}
 | |
| 	|
 | |
| 		arrayer(&count)
 | |
| 		{add_decl_unary(dc, ARRAY, count, NO_PARAMS);}
 | |
| 	]*
 | |
| |
 | |
| 	'*' declarator(dc)
 | |
| 	{add_decl_unary(dc, POINTER, (arith)0, NO_PARAMS);}
 | |
| ;
 | |
| 
 | |
| primary_declarator(register struct declarator *dc;) :
 | |
| 	identifier(&dc->dc_idf)
 | |
| |
 | |
| 	'(' declarator(dc) ')'
 | |
| ;
 | |
| 
 | |
| arrayer(arith *sizep;)
 | |
| 	{ struct expr *expr; }
 | |
| :
 | |
| 	'['
 | |
| 		[
 | |
| 			constant_expression(&expr)
 | |
| 			{
 | |
| 				check_array_subscript(expr);
 | |
| 				*sizep = expr->VL_VALUE;
 | |
| 				free_expression(expr);
 | |
| 			}
 | |
| 		|
 | |
| 			empty
 | |
| 			{ *sizep = (arith)-1; }
 | |
| 		]
 | |
| 	']'
 | |
| ;
 | |
| 
 | |
| formal_list (struct formal **fmp;)
 | |
| :
 | |
| 	formal(fmp) [ %persistent ',' formal(fmp) ]*
 | |
| ;
 | |
| 
 | |
| formal(struct formal **fmp;)
 | |
| 	{struct idf *idf;	}
 | |
| :
 | |
| 	identifier(&idf)
 | |
| 	{
 | |
| 		register struct formal *new = new_formal();
 | |
| 
 | |
| 		new->fm_idf = idf;
 | |
| 		new->next = *fmp;
 | |
| 		*fmp = new;
 | |
| 	}
 | |
| ;
 | |
| 
 | |
| /* Change 2 */
 | |
| enum_specifier(register struct type **tpp;)
 | |
| 	{
 | |
| 		struct idf *idf;
 | |
| 		arith l = (arith)0;
 | |
| 	}
 | |
| :
 | |
| 	ENUM
 | |
| 	[
 | |
| 		{declare_struct(ENUM, (struct idf *) 0, tpp);}
 | |
| 		enumerator_pack(*tpp, &l)
 | |
| 	|
 | |
| 		identifier(&idf)
 | |
| 		[
 | |
| 			{declare_struct(ENUM, idf, tpp);}
 | |
| 			enumerator_pack(*tpp, &l)
 | |
| 			{
 | |
| #ifdef DBSYMTAB
 | |
| 				if (options['g']) {
 | |
| 					stb_tag(idf->id_enum, idf->id_text);
 | |
| 				}
 | |
| #endif /*DBSYMTAB */
 | |
| 			}
 | |
| 		|
 | |
| 			{apply_struct(ENUM, idf, tpp);}
 | |
| 			empty
 | |
| 		]
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| enumerator_pack(register struct type *tp; arith *lp;) :
 | |
| 	'{'
 | |
| 	enumerator(tp, lp)
 | |
| 	[%while(AHEAD != '}')		/* >>> conflict on ',' */
 | |
| 		','
 | |
| 		enumerator(tp, lp)
 | |
| 	]*
 | |
| 	','?				/* optional trailing comma */
 | |
| 	'}'
 | |
| 	{tp->tp_size = int_size;}
 | |
| 	/*	fancy implementations that put small enums in 1 byte
 | |
| 		or so should start here.
 | |
| 	*/
 | |
| ;
 | |
| 
 | |
| enumerator(struct type *tp; arith *lp;)
 | |
| 	{
 | |
| 		struct idf *idf;
 | |
| 		struct expr *expr;
 | |
| 	}
 | |
| :
 | |
| 	identifier(&idf)
 | |
| 	[
 | |
| 		'='
 | |
| 		constant_expression(&expr)
 | |
| 		{
 | |
| 			*lp = expr->VL_VALUE;
 | |
| 			free_expression(expr);
 | |
| 		}
 | |
| 	]?
 | |
| 	{declare_enum(tp, idf, (*lp)++);}
 | |
| ;
 | |
| 
 | |
| /* 8.5 */
 | |
| struct_or_union_specifier(register struct type **tpp;)
 | |
| 	{
 | |
| 		int fund;
 | |
| 		struct idf *idfX;
 | |
| 		register struct idf *idf;
 | |
| 	}
 | |
| :
 | |
| 	[ STRUCT | UNION ]
 | |
| 	{fund = DOT;}
 | |
| 	[
 | |
| 		{
 | |
| 			declare_struct(fund, (struct idf *)0, tpp);
 | |
| 		}
 | |
| 		struct_declaration_pack(*tpp)
 | |
| 	|
 | |
| 		identifier(&idfX)	{ idf = idfX; }
 | |
| 		[
 | |
| 			{
 | |
| 				declare_struct(fund, idf, tpp);
 | |
| 				(idf->id_struct->tg_busy)++;
 | |
| 			}
 | |
| 			struct_declaration_pack(*tpp)
 | |
| 			{
 | |
| 				(idf->id_struct->tg_busy)--;
 | |
| #ifdef DBSYMTAB
 | |
| 				if (options['g']) {
 | |
| 					stb_tag(idf->id_struct, idf->id_text);
 | |
| 				}
 | |
| #endif /*DBSYMTAB */
 | |
| 			}
 | |
| 		|
 | |
| 			{apply_struct(fund, idf, tpp);}
 | |
| 			empty
 | |
| 		]
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| struct_declaration_pack(register struct type *stp;)
 | |
| 	{
 | |
| 		struct sdef **sdefp = &stp->tp_sdef;
 | |
| 		arith size = (arith)0;
 | |
| 	}
 | |
| :
 | |
| 	/*	The size is only filled in after the whole struct has
 | |
| 		been read, to prevent recursive definitions.
 | |
| 	*/
 | |
| 	'{'
 | |
| 	struct_declaration(stp, &sdefp, &size)+
 | |
| 	'}'
 | |
| 	{stp->tp_size = align(size, stp->tp_align);}
 | |
| ;
 | |
| 
 | |
| struct_declaration(struct type *stp; struct sdef ***sdefpp; arith *szp;)
 | |
| 	{struct type *tp;}
 | |
| :
 | |
| 	type_specifier(&tp)
 | |
| 	struct_declarator_list(tp, stp, sdefpp, szp)
 | |
| 	[	/*	in some standard UNIX compilers the semicolon
 | |
| 			is optional, would you believe!
 | |
| 		*/
 | |
| 		';'
 | |
| 	|
 | |
| 		empty
 | |
| 		{warning("no semicolon after declarator");}
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| struct_declarator_list(struct type *tp; struct type *stp;
 | |
| 			struct sdef ***sdefpp; arith *szp;)
 | |
| :
 | |
| 	struct_declarator(tp, stp, sdefpp, szp)
 | |
| 	[ ',' struct_declarator(tp, stp, sdefpp, szp) ]*
 | |
| ;
 | |
| 
 | |
| struct_declarator(struct type *tp; struct type *stp;
 | |
| 			struct sdef ***sdefpp; arith *szp;)
 | |
| 	{
 | |
| 		struct declarator Dc;
 | |
| 		struct field *fd = 0;
 | |
| 	}
 | |
| :
 | |
| 	{
 | |
| 		Dc = null_declarator;
 | |
| 	}
 | |
| [
 | |
| 	declarator(&Dc)
 | |
| 	{reject_params(&Dc);}
 | |
| 	bit_expression(&fd)?
 | |
| |
 | |
| 	{Dc.dc_idf = gen_idf();}
 | |
| 	bit_expression(&fd)
 | |
| ]
 | |
| 	{add_sel(stp, declare_type(tp, &Dc), Dc.dc_idf, sdefpp, szp, fd);}
 | |
| 	{remove_declarator(&Dc);}
 | |
| ;
 | |
| 
 | |
| bit_expression(struct field **fd;)
 | |
| 	{ struct expr *expr; }
 | |
| :
 | |
| 	{
 | |
| 		*fd = new_field();
 | |
| 	}
 | |
| 	':'
 | |
| 	constant_expression(&expr)
 | |
| 	{
 | |
| 		(*fd)->fd_width = expr->VL_VALUE;
 | |
| 		free_expression(expr);
 | |
| #ifdef NOBITFIELD
 | |
| 		error("bitfields are not implemented");
 | |
| #endif /* NOBITFIELD */
 | |
| 	}
 | |
| ;
 | |
| 
 | |
| /* 8.7 */
 | |
| cast(struct type **tpp;)	{struct declarator Dc;} :
 | |
| 	{Dc = null_declarator;}
 | |
| 	'('
 | |
| 	type_specifier(tpp)
 | |
| 	abstract_declarator(&Dc)
 | |
| 	')'
 | |
| 	{*tpp = declare_type(*tpp, &Dc);}
 | |
| 	{remove_declarator(&Dc);}
 | |
| ;
 | |
| 
 | |
| /*	This code is an abject copy of that of 'declarator', for lack of
 | |
| 	a two-level grammar.
 | |
| */
 | |
| abstract_declarator(register struct declarator *dc;)
 | |
| 	{arith count;}
 | |
| :
 | |
| 	primary_abstract_declarator(dc)
 | |
| 	[
 | |
| 		'(' ')'
 | |
| 		{add_decl_unary(dc, FUNCTION, (arith)0, NO_PARAMS);}
 | |
| 	|
 | |
| 		arrayer(&count)
 | |
| 		{add_decl_unary(dc, ARRAY, count, NO_PARAMS);}
 | |
| 	]*
 | |
| |
 | |
| 	'*' abstract_declarator(dc)
 | |
| 	{add_decl_unary(dc, POINTER, (arith)0, NO_PARAMS);}
 | |
| ;
 | |
| 
 | |
| primary_abstract_declarator(struct declarator *dc;) :
 | |
| [%if (AHEAD == ')')
 | |
| 	empty
 | |
| |
 | |
| 	'(' abstract_declarator(dc) ')'
 | |
| ]
 | |
| ;
 | |
| 
 | |
| empty:
 | |
| ;
 | |
| 
 | |
| /* 8.8 */
 | |
| /* included in the IDENTIFIER/TYPE_IDENTIFIER mechanism */
 |