989 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			989 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /* D E C L A R A T I O N S */
 | |
| 
 | |
| {
 | |
| /* next line DEBUG */ 
 | |
| #include	"debug.h"
 | |
| 
 | |
| #include	<alloc.h>
 | |
| #include	<assert.h>
 | |
| #include	<em_arith.h>
 | |
| #include	<em_label.h>
 | |
| #include	<pc_file.h>
 | |
| 
 | |
| #include	"LLlex.h"
 | |
| #include	"chk_expr.h"
 | |
| #include	"def.h"
 | |
| #include	"idf.h"
 | |
| #include	"main.h"
 | |
| #include	"misc.h"
 | |
| #include	"node.h"
 | |
| #include	"scope.h"
 | |
| #include	"type.h"
 | |
| 
 | |
| #define	offsetof(type, field)	(int) &(((type *)0)->field)
 | |
| #define	PC_BUFSIZ	(sizeof(struct file) - (int)((struct file *)0)->bufadr)
 | |
| 
 | |
| int proclevel = 0;		/* nesting level of procedures */
 | |
| int parlevel = 0;		/* nesting level of parametersections */
 | |
| int expect_label = 0;		/* so the parser knows that we expect a label */
 | |
| static int in_type_defs;	/* in type definition part or not */
 | |
| }
 | |
| 
 | |
| /* ISO section 6.2.1, p. 93 */
 | |
| Block(struct def *df;)
 | |
| {
 | |
| 	arith i;
 | |
| } :
 | |
| 					{ text_label = (label) 0; }
 | |
| 	LabelDeclarationPart
 | |
| 	Module(df, &i)
 | |
| 	CompoundStatement
 | |
| 					{ if( !err_occurred )
 | |
| 						CodeEndBlock(df, i);
 | |
| 					  if( df ) EndBlock(df);
 | |
| 					  FreeNode(BlockScope->sc_lablist);
 | |
| 					}
 | |
| ;
 | |
| 
 | |
| LabelDeclarationPart
 | |
| {
 | |
| 	struct node *nd;
 | |
| } :
 | |
| 	[
 | |
| 		LABEL Label(&nd)
 | |
| 				{ if( nd )	{
 | |
| 					DeclLabel(nd);
 | |
| 					nd->nd_next = CurrentScope->sc_lablist;
 | |
| 					CurrentScope->sc_lablist = nd;
 | |
| 				  }
 | |
| 				}
 | |
| 		[ %persistent
 | |
| 			',' Label(&nd)
 | |
| 				{ if( nd )	{
 | |
| 					DeclLabel(nd);
 | |
| 					nd->nd_next = CurrentScope->sc_lablist;
 | |
| 					CurrentScope->sc_lablist = nd;
 | |
| 				  }
 | |
| 				}
 | |
| 		]*
 | |
| 		';'
 | |
| 	]?
 | |
| ;
 | |
| 
 | |
| Module(struct def *df; arith *i;)
 | |
| {
 | |
| 	label save_label;
 | |
| } :
 | |
| 	ConstantDefinitionPart
 | |
| 					{ in_type_defs = 1; }
 | |
| 	TypeDefinitionPart
 | |
| 					{ in_type_defs = 0;
 | |
| 					  /* resolve forward references */
 | |
| 					  chk_forw_types();
 | |
| 					}
 | |
| 	VariableDeclarationPart
 | |
| 					{ if( !proclevel )	{
 | |
| 						chk_prog_params();
 | |
| 						BssVar();
 | |
| 					  }
 | |
| 					  proclevel++;
 | |
| 					  save_label = text_label;
 | |
| 					}
 | |
| 	ProcedureAndFunctionDeclarationPart
 | |
| 					{ text_label = save_label;
 | |
| 
 | |
| 					  proclevel--;
 | |
| 					  chk_directives();
 | |
| 
 | |
| 					  /* needed with labeldefinitions
 | |
| 					     and for-statement
 | |
| 					  */
 | |
| 					  BlockScope = CurrentScope;
 | |
| 
 | |
| 					  if( !err_occurred )
 | |
| 						*i = CodeBeginBlock( df );
 | |
| 					}
 | |
| ;
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| ConstantDefinitionPart:
 | |
| 	[
 | |
| 		CONST
 | |
| 		[ %persistent
 | |
| 			ConstantDefinition ';'
 | |
| 		]+
 | |
| 	]?
 | |
| ;
 | |
| 
 | |
| TypeDefinitionPart:
 | |
| 	[
 | |
| 		TYPE
 | |
| 		[ %persistent
 | |
| 			TypeDefinition ';'
 | |
| 		]+
 | |
| 	]?
 | |
| ;
 | |
| 
 | |
| VariableDeclarationPart:
 | |
| 	[
 | |
| 		VAR 
 | |
| 		[ %persistent
 | |
| 			VariableDeclaration ';'
 | |
| 		]+
 | |
| 	]?
 | |
| ;
 | |
| 
 | |
| ProcedureAndFunctionDeclarationPart:
 | |
| 	[
 | |
| 		[
 | |
| 			ProcedureDeclaration
 | |
| 		|
 | |
| 			FunctionDeclaration
 | |
| 		] ';'
 | |
| 	]*
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.1.6, p. 92 */
 | |
| Label(struct node **pnd;)
 | |
| {
 | |
| 	char lab[5];
 | |
| 	extern char *sprint();
 | |
| } :	{ expect_label = 1; }
 | |
| 	INTEGER		/* not really an integer, in [0..9999] */
 | |
| 	{ if( dot.TOK_INT < 0 || dot.TOK_INT > 9999 )	{
 | |
| 		if( dot.TOK_INT != -1 )		/* This means insertion */
 | |
| 			error("label must lie in closed interval [0..9999]");
 | |
| 		*pnd = NULLNODE;
 | |
| 	  }
 | |
| 	  else	{
 | |
| 		sprint(lab, "%d", dot.TOK_INT);
 | |
| 		*pnd = MkLeaf(Name, &dot);
 | |
| 		(*pnd)->nd_IDF = str2idf(lab, 1);
 | |
| 	  }
 | |
| 	  expect_label = 0;
 | |
| 	}
 | |
| ;
 | |
| 
 | |
| 
 | |
| /* ISO section 6.3, p. 95 */
 | |
| ConstantDefinition
 | |
| {
 | |
| 	register struct idf *id;
 | |
| 	register struct def *df;
 | |
| 	struct node *nd;
 | |
| } :
 | |
| 	IDENT			{ id = dot.TOK_IDF; }
 | |
| 	'=' Constant(&nd)
 | |
| 			{ if( df = define(id,CurrentScope,D_CONST) )	{
 | |
| 			  	df->con_const = nd;
 | |
| 				df->df_type = nd->nd_type;
 | |
| 				df->df_flags |= D_SET;
 | |
| 			  }
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.1, p. 96 */
 | |
| TypeDefinition
 | |
| {
 | |
| 	register struct idf *id;
 | |
| 	register struct def *df;
 | |
| 	struct type *tp;
 | |
| } :
 | |
| 	IDENT			{ id = dot.TOK_IDF; }
 | |
| 	'=' TypeDenoter(&tp)
 | |
| 			{ if( df = define(id, CurrentScope, D_TYPE) ) {
 | |
| 			  	df->df_type = tp;
 | |
| 				df->df_flags |= D_SET;
 | |
| 			  }
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| TypeDenoter(register struct type **ptp;):
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 */
 | |
| 	TypeIdentifierOrSubrangeType(ptp)
 | |
| |
 | |
| 	PointerType(ptp)
 | |
| |
 | |
| 	StructuredType(ptp)
 | |
| |
 | |
| 	EnumeratedType(ptp)
 | |
| ;
 | |
| 
 | |
| TypeIdentifierOrSubrangeType(register struct type **ptp;)
 | |
| {
 | |
| 	struct node *nd1, *nd2;
 | |
| } :
 | |
| 	/* This is a new rule because the grammar specified by the standard
 | |
| 	 * is not exactly LL(1) (see TypeDenoter).
 | |
| 	 */
 | |
| [
 | |
| 	%prefer
 | |
| 	IDENT			{ nd1 = MkLeaf(Name, &dot); }
 | |
| 	[
 | |
| 		/* empty */
 | |
| 		/* at this point IDENT must be a TypeIdentifier !! */
 | |
| 				{ chk_type_id(ptp, nd1);
 | |
| 			  	  FreeNode(nd1);
 | |
| 				}
 | |
| 	|
 | |
| 		/* at this point IDENT must be a Constant !! */
 | |
| 				{ (void) ChkConstant(nd1); }
 | |
| 		UPTO Constant(&nd2)
 | |
| 				{ *ptp = subr_type(nd1, nd2);
 | |
| 				  FreeNode(nd1);
 | |
| 				  FreeNode(nd2);
 | |
| 				}
 | |
| 	]
 | |
| |
 | |
| 	Constant(&nd1) UPTO Constant(&nd2)
 | |
| 				{ *ptp = subr_type(nd1, nd2);
 | |
| 				  FreeNode(nd1);
 | |
| 				  FreeNode(nd2);
 | |
| 				}
 | |
| ]
 | |
| ;
 | |
| 
 | |
| TypeIdentifier(register struct type **ptp;):
 | |
| 	IDENT			{ register struct node *nd = MkLeaf(Name, &dot);
 | |
| 				  chk_type_id(ptp, nd);
 | |
| 				  FreeNode(nd);
 | |
| 				}
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.5.1, p. 105 */
 | |
| VariableDeclaration
 | |
| {
 | |
| 	struct node *VarList;
 | |
| 	struct type *tp;
 | |
| } :
 | |
| 	IdentifierList(&VarList) ':' TypeDenoter(&tp)
 | |
| 				{ EnterVarList(VarList, tp, proclevel > 0); }
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.6.1, p. 108 */
 | |
| ProcedureDeclaration
 | |
| {
 | |
| 	struct node *nd;
 | |
| 	struct type *tp;
 | |
| 	register struct scopelist *scl;
 | |
| 	register struct def *df;
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 *
 | |
| 	 * ProcedureHeading without a FormalParameterList can be a
 | |
| 	 * ProcedureIdentification, i.e. the IDENT used in the Heading is
 | |
| 	 * also used in a "forward" declaration.
 | |
| 	 */
 | |
| 				{ open_scope(); }
 | |
| 	ProcedureHeading(&nd, &tp) ';'
 | |
| 				{ scl = CurrVis; close_scope(); }
 | |
| 	[
 | |
| 		Directive
 | |
| 				{ DoDirective(dot.TOK_IDF, nd, tp, scl, 0); }
 | |
| 	|
 | |
| 				{ df = DeclProc(nd, tp, scl); }
 | |
| 		Block(df)
 | |
| 				{ /* open_scope() is simulated in DeclProc() */
 | |
| 				  close_scope();
 | |
| 				}
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| ProcedureHeading(register struct node **pnd; register struct type **ptp;)
 | |
| {
 | |
| 	struct node *fpl;
 | |
| } :
 | |
| 	PROCEDURE
 | |
| 	IDENT			{
 | |
| 				  *pnd = MkLeaf(Name, &dot);
 | |
| 				}
 | |
| 	[
 | |
| 		FormalParameterList(&fpl)
 | |
| 				{ arith nb_pars = 0;
 | |
| 				  struct paramlist *pr = 0;
 | |
| 
 | |
| 				  if( !parlevel )
 | |
| 					/* procedure declaration */
 | |
| 					nb_pars = EnterParamList(fpl, &pr);
 | |
| 				  else
 | |
| 					/* procedure parameter */
 | |
| 					nb_pars = EnterParTypes(fpl, &pr);
 | |
| 				
 | |
| 				  *ptp = proc_type(pr, nb_pars);
 | |
| 				  FreeNode(fpl);
 | |
| 				}
 | |
| 	|
 | |
| 		/* empty */
 | |
| 				{ *ptp =
 | |
| 				    proc_type((struct paramlist *)0,
 | |
| 						(proclevel > 1) ? pointer_size : (arith) 0);
 | |
| 				}
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| Directive:
 | |
| 	/* see also Functiondeclaration (6.6.2, p. 110)
 | |
| 	 * Not actually an identifier but 'letter {letter | digit}'
 | |
| 	 */
 | |
| 	IDENT
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.6.1, p. 108 */
 | |
| FunctionDeclaration
 | |
| {
 | |
| 	struct node *nd;
 | |
| 	struct type *tp;
 | |
| 	register struct scopelist *scl;
 | |
| 	register struct def *df;
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 */
 | |
| 				{ open_scope(); }
 | |
| 	FunctionHeading(&nd, &tp) ';'
 | |
| 				{ scl = CurrVis; close_scope(); }
 | |
| 	[
 | |
| 		Directive
 | |
| 				{ if( !tp )	{
 | |
| 					node_error(nd,
 | |
| 					 "function \"%s\": illegal declaration",
 | |
| 							nd->nd_IDF->id_text);
 | |
| 				  }
 | |
| 				  else DoDirective(dot.TOK_IDF, nd, tp, scl, 1);
 | |
| 				}
 | |
| 	|
 | |
| 				{ if( df = DeclFunc(nd, tp, scl) ) {
 | |
| 					df->prc_res =
 | |
| 					     - ResultType(df->df_type)->tp_size;
 | |
| 					df->prc_bool =
 | |
| 						CurrentScope->sc_off =
 | |
| 							df->prc_res - int_size;
 | |
| 				    }
 | |
| 				}
 | |
| 			Block(df)
 | |
| 				{ if( df ) {
 | |
| 					EndFunc(df);
 | |
| 				  }
 | |
| 
 | |
| 				  /* open_scope() is simulated in DeclFunc() */
 | |
| 				  close_scope();
 | |
| 				}
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| FunctionHeading(register struct node **pnd; register struct type **ptp;)
 | |
| {
 | |
| 	/*	This is the Function AND FunctionIdentification part.
 | |
| 		If it is a identification, *ptp is set to NULLTYPE.
 | |
| 	*/
 | |
| 	struct node *fpl = NULLNODE;
 | |
| 	struct type *tp;
 | |
| 	struct paramlist *pr = 0;
 | |
| 	arith nb_pars = (proclevel > 1) ? pointer_size : 0;
 | |
| } :
 | |
| 	FUNCTION
 | |
| 	IDENT			{ *pnd = MkLeaf(Name, &dot);
 | |
| 				  *ptp = NULLTYPE;
 | |
| 				}
 | |
| [
 | |
| 	[
 | |
| 		FormalParameterList(&fpl)
 | |
| 				{ if( !parlevel )
 | |
| 					/* function declaration */
 | |
| 					nb_pars = EnterParamList(fpl, &pr);
 | |
| 				  else
 | |
| 					/* function parameter */
 | |
| 					nb_pars = EnterParTypes(fpl, &pr);
 | |
| 				}
 | |
| 	|
 | |
| 		/* empty */
 | |
| 	]
 | |
| 	':' TypeIdentifier(&tp)
 | |
| 				{ if( IsConstructed(tp) )	{
 | |
| 				        node_error(*pnd,
 | |
| 				         "function has an illegal result type");
 | |
| 					tp = error_type;
 | |
| 				  }
 | |
| 				  *ptp = func_type(pr, nb_pars, tp);
 | |
| 				  FreeNode(fpl);
 | |
| 				}
 | |
| ]?
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.2.1, p. 96 */
 | |
| OrdinalType(register struct type **ptp;):
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference states that a SubrangeType can start with an IDENT and
 | |
| 	 * so can an OrdinalTypeIdentifier, and this is not LL(1).
 | |
| 	 */
 | |
| 	TypeIdentifierOrSubrangeType(ptp)
 | |
| |
 | |
| 	EnumeratedType(ptp)
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.2.3, p. 97 */
 | |
| EnumeratedType(register struct type **ptp;)
 | |
| {
 | |
| 	struct node *EnumList;
 | |
| 	arith i = (arith) 1;
 | |
| } :
 | |
| 	'(' IdentifierList(&EnumList) ')'
 | |
| 		{ register struct type *tp =
 | |
| 		  	standard_type(T_ENUMERATION, word_align, word_size);
 | |
| 
 | |
| 		  *ptp = tp;
 | |
| 		  EnterEnumList(EnumList, tp);
 | |
| 		  if( tp->enm_ncst == 0 )
 | |
| 			*ptp = error_type;
 | |
| 		  else do	{
 | |
| 			if( ufit(tp->enm_ncst-1, i) )	{
 | |
| 				tp->tp_psize = i;
 | |
| 				tp->tp_palign = i;
 | |
| 				break;
 | |
| 		  	}
 | |
| 			i <<= 1;
 | |
| 		  } while( i < word_size );
 | |
| 		}
 | |
| ;
 | |
| 
 | |
| IdentifierList(register struct node **nd;)
 | |
| {
 | |
| 	register struct node *tnd;
 | |
| } :
 | |
| 	IDENT		{ *nd = tnd = MkLeaf(Name, &dot); }
 | |
| 	[ %persistent
 | |
| 		',' IDENT
 | |
| 			{ tnd->nd_next = MkLeaf(Name, &dot);
 | |
| 			  tnd = tnd->nd_next;
 | |
| 			}
 | |
| 	]*
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.3.2, p. 98 */
 | |
| StructuredType(register struct type **ptp;)
 | |
| {
 | |
| 	unsigned short packed = 0;
 | |
| } :
 | |
| 	[
 | |
| 		PACKED { packed = T_PACKED; }
 | |
| 	]?
 | |
| 	UnpackedStructuredType(ptp, packed)
 | |
| ;
 | |
| 
 | |
| UnpackedStructuredType(register struct type **ptp; unsigned short packed;):
 | |
| 	ArrayType(ptp, packed)
 | |
| |
 | |
| 	RecordType(ptp, packed)
 | |
| |
 | |
| 	SetType(ptp, packed)
 | |
| |
 | |
| 	FileType(ptp)
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.3.2, p. 98 */
 | |
| ArrayType(register struct type **ptp; unsigned short packed;)
 | |
| {
 | |
| 	struct type *tp;
 | |
| 	register struct type *tp2;
 | |
| } :
 | |
| 	ARRAY
 | |
| 	'['
 | |
| 		Indextype(&tp)
 | |
| 			{ *ptp = tp2 = construct_type(T_ARRAY, tp);
 | |
| 			  tp2->tp_flags |= packed;
 | |
| 			}
 | |
| 		[ %persistent
 | |
| 			',' Indextype(&tp)
 | |
| 			{ tp2->arr_elem = construct_type(T_ARRAY, tp);
 | |
| 			  tp2 = tp2->arr_elem;
 | |
| 			  tp2->tp_flags |= packed;
 | |
| 			}
 | |
| 		]*
 | |
| 	']'
 | |
| 	OF ComponentType(&tp)
 | |
| 			{ tp2->arr_elem = tp;
 | |
| 			  ArraySizes(*ptp);
 | |
| 			  if( tp->tp_flags & T_HASFILE )
 | |
| 			  	(*ptp)->tp_flags |= T_HASFILE;
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| Indextype(register struct type **ptp;):
 | |
| 	OrdinalType(ptp)
 | |
| ;
 | |
| 
 | |
| ComponentType(register struct type **ptp;):
 | |
| 	TypeDenoter(ptp)
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.3.3, p. 99 */
 | |
| RecordType(register struct type **ptp; unsigned short packed;)
 | |
| {
 | |
| 	register struct scope *scope;
 | |
| 	register struct def *df;
 | |
| 	struct selector *sel = 0;
 | |
| 	arith size = 0;
 | |
| 	int xalign = struct_align;
 | |
| } :
 | |
| 	RECORD
 | |
| 		{ open_scope();		/* scope for fields of record */
 | |
| 		  scope = CurrentScope;
 | |
| 		  close_scope();
 | |
| 		}
 | |
| 	FieldList(scope, &size, &xalign, packed, &sel)
 | |
| 		{ if( size == 0 )	{
 | |
| 			warning("empty record declaration");
 | |
| 			size = 1;
 | |
| 		  }
 | |
| 		  *ptp = standard_type(T_RECORD, xalign, size);
 | |
| 		  (*ptp)->rec_scope = scope;
 | |
| 		  (*ptp)->rec_sel = sel;
 | |
| 		  (*ptp)->tp_flags |= packed;
 | |
| 
 | |
| 		  /* copy the file component flag */
 | |
| 		  df = scope->sc_def;
 | |
| 		  while( df && !(df->df_type->tp_flags & T_HASFILE) )
 | |
| 			df = df->df_nextinscope;
 | |
| 
 | |
| 		  if( df )
 | |
| 			(*ptp)->tp_flags |= T_HASFILE;
 | |
| 		}
 | |
| 	END
 | |
| ;
 | |
| 
 | |
| FieldList(struct scope *scope; arith *cnt; int *palign; unsigned short packed;
 | |
| 							struct selector **sel;):
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 * Those irritating, annoying (Siklossy !!) semicolons.
 | |
| 	 */
 | |
| 
 | |
| 	/* empty */
 | |
| |
 | |
| 	FixedPart(scope, cnt, palign, packed, sel)
 | |
| |
 | |
| 	VariantPart(scope, cnt, palign, packed, sel)
 | |
| ;
 | |
| 
 | |
| FixedPart(struct scope *scope; arith *cnt; int *palign; unsigned short packed;
 | |
| 							struct selector **sel;):
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 * Again those frustrating semicolons !!
 | |
| 	 */
 | |
| 	RecordSection(scope, cnt, palign, packed)
 | |
| 	FixedPartTail(scope, cnt, palign, packed, sel)
 | |
| ;
 | |
| 
 | |
| FixedPartTail(struct scope *scope; arith *cnt; int *palign;
 | |
| 				unsigned short packed; struct selector **sel;):
 | |
| 	/* This is a new rule because the grammar specified by the standard
 | |
| 	 * is not exactly LL(1).
 | |
| 	 * We see the light at the end of the tunnel !
 | |
| 	 */
 | |
| 
 | |
| 	/* empty */
 | |
| |
 | |
| 	%default
 | |
| 	';'
 | |
| 	[
 | |
| 		/* empty */
 | |
| 	|
 | |
| 		VariantPart(scope, cnt, palign, packed, sel)
 | |
| 	|
 | |
| 		RecordSection(scope, cnt, palign, packed)
 | |
| 		FixedPartTail(scope, cnt, palign, packed, sel)
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| RecordSection(struct scope *scope; arith *cnt; int *palign;
 | |
| 							unsigned short packed;)
 | |
| {
 | |
| 	struct node *FldList;
 | |
| 	struct type *tp;
 | |
| } :
 | |
| 
 | |
| 	IdentifierList(&FldList) ':' TypeDenoter(&tp)
 | |
| 			{ *palign =
 | |
| 			      lcm(*palign, packed ? tp->tp_palign : word_align);
 | |
| 			  EnterFieldList(FldList, tp, scope, cnt, packed);
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| VariantPart(struct scope *scope; arith *cnt; int *palign;
 | |
| 				unsigned short packed; struct selector **sel;)
 | |
| {
 | |
| 	struct type *tp;
 | |
| 	struct def *df = 0;
 | |
| 	struct idf *id = 0;
 | |
| 	arith tcnt, max;
 | |
| 	register arith ncst = 0;/* the number of values of the tagtype */
 | |
| 	register struct selector **sp;
 | |
| 	extern char *Malloc();
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 * We're almost there !!
 | |
| 	 */
 | |
| 
 | |
| 		{ *sel = (struct selector *) Malloc(sizeof(struct selector));
 | |
| 		  (*sel)->sel_ptrs = 0;
 | |
| 		}
 | |
| 	CASE
 | |
| 	VariantSelector(&tp, &id)
 | |
| 		{ if (id)
 | |
| 		  	df = define(id, scope, D_FIELD);
 | |
| /* ISO 6.4.3.3 (p. 100)
 | |
|  * The standard permits the integertype as tagtype, but demands that the set
 | |
|  * of values denoted by the case-constants is equal to the set of values
 | |
|  * specified by the tagtype. So we've decided not to allow integer as tagtype,
 | |
|  * because it's not practical to enumerate ALL integers as case-constants. 
 | |
|  * Though it wouldn't make a great difference to allow it as tagtype.
 | |
|  */
 | |
| 	  	  if( !(tp->tp_fund & T_INDEX) )	{
 | |
| 			error("illegal type in variant");
 | |
| 			tp = error_type;
 | |
| 		  }
 | |
| 		  else	{
 | |
| 			arith lb, ub;
 | |
| 
 | |
| 			getbounds(tp, &lb, &ub);
 | |
| 			ncst = ub - lb + 1;
 | |
| 
 | |
| 			/* initialize selector */
 | |
| 			(*sel)->sel_ptrs = (struct selector **)
 | |
| 			   Malloc((unsigned)ncst * sizeof(struct selector *));
 | |
| 			(*sel)->sel_ncst = ncst;
 | |
| 			(*sel)->sel_lb = lb;
 | |
| 
 | |
| 			/* initialize tagvalue-table */
 | |
| 			sp = (*sel)->sel_ptrs;
 | |
| 			while( ncst-- ) *sp++ = *sel;
 | |
| 		  }
 | |
| 		  (*sel)->sel_type = tp;
 | |
| 		  if( df )	{
 | |
| 	  		df->df_type = tp;
 | |
| 	  		df->fld_flags |=
 | |
| 				  packed ? (F_PACKED | F_SELECTOR) : F_SELECTOR;
 | |
| 	  		df->fld_off = align(*cnt,
 | |
| 					 packed ? tp->tp_palign : tp->tp_align);
 | |
| 	  		*cnt = df->fld_off +
 | |
| 					 (packed ? tp->tp_psize : tp->tp_size);
 | |
| 		  }
 | |
| 		  tcnt = *cnt;
 | |
| 		}
 | |
| 	OF
 | |
| 	Variant(scope, &tcnt, palign, packed, *sel)
 | |
| 			{ max = tcnt; }
 | |
| 	VariantTail(scope, &tcnt, &max, cnt, palign, packed, *sel)
 | |
| 			{ *cnt = max;
 | |
| 			  if( sp = (*sel)->sel_ptrs )	{
 | |
| 				int errflag = 0;
 | |
| 
 | |
| 				ncst = (*sel)->sel_ncst;
 | |
| 				while( ncst-- )
 | |
| 					if( *sp == *sel )	{
 | |
| 						*sp++ = 0;
 | |
| 						errflag = 1;
 | |
| 					}
 | |
| 					else *sp++;
 | |
| 				if( errflag )
 | |
| 		error("record variant part: each tagvalue must have a variant");
 | |
| 			  }
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| VariantTail(register struct scope *scope; arith *tcnt, *max, *cnt;
 | |
| 		int *palign; unsigned short packed; struct selector *sel;):
 | |
| 	/* This is a new rule because the grammar specified by the standard
 | |
| 	 * is not exactly LL(1).
 | |
| 	 * At last, the garden of Eden !!
 | |
| 	 */
 | |
| 
 | |
| 	/* empty */
 | |
| |
 | |
| %default
 | |
| 	';'
 | |
| 	[
 | |
| 		/* empty */
 | |
| 	|
 | |
| 					{ *tcnt = *cnt; }
 | |
| 		Variant(scope, tcnt, palign, packed, sel)
 | |
| 					{ if( *tcnt > *max ) *max = *tcnt; }
 | |
| 		VariantTail(scope, tcnt, max, cnt, palign, packed, sel)
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| VariantSelector(register struct type **ptp; register struct idf **pid;)
 | |
| {
 | |
| 	register struct node *nd;
 | |
| } :
 | |
| 	/* This is a changed rule, because the grammar as specified in the
 | |
| 	 * reference is not LL(1), and this gives conflicts.
 | |
| 	 */
 | |
| 
 | |
| 	IDENT				{ nd = MkLeaf(Name, &dot); }
 | |
| 	[
 | |
| 		/* Old fashioned ! at this point the IDENT represents
 | |
| 		 * the TagType
 | |
| 		 */
 | |
| 				{ warning("old-fashioned syntax ':' missing");
 | |
| 				  chk_type_id(ptp, nd);
 | |
| 				  FreeNode(nd);
 | |
| 				}
 | |
| 	|
 | |
| 		/* IDENT is now the TagField */
 | |
| 		':'
 | |
| 		TypeIdentifier(ptp)
 | |
| 					{ *pid = nd->nd_IDF;
 | |
| 					  FreeNode(nd);
 | |
| 					}
 | |
| 	]
 | |
| ;
 | |
| 
 | |
| Variant(struct scope *scope; arith *cnt; int *palign; unsigned short packed;
 | |
| 							struct selector *sel;)
 | |
| {
 | |
| 	struct node *nd;
 | |
| 	struct selector *sel1 = 0;
 | |
| } :
 | |
| 	CaseConstantList(&nd)
 | |
| 	':'
 | |
| 	'(' FieldList(scope, cnt, palign, packed, &sel1) ')'
 | |
| 					{ TstCaseConstants(nd, sel, sel1);
 | |
| 					  FreeNode(nd);
 | |
| 					}
 | |
| ;
 | |
| 
 | |
| CaseConstantList(struct node **nd;)
 | |
| {
 | |
| 	struct node *nd1;
 | |
| } :
 | |
| 	Constant(&nd1)			{ *nd = nd1; }
 | |
| 	[ %persistent
 | |
| 		',' Constant(&(nd1->nd_next))
 | |
| 					{ nd1 = nd1->nd_next; }
 | |
| 	]*
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.3.4, p. 101 */
 | |
| SetType(register struct type **ptp; unsigned short packed;):
 | |
| 	SET OF OrdinalType(ptp)
 | |
| 		{ *ptp = set_type(*ptp, packed); }
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.3.5, p. 101 */
 | |
| FileType(register struct type **ptp;):
 | |
| 	FILE OF
 | |
| 			{ *ptp = construct_type(T_FILE, NULLTYPE);
 | |
| 			  (*ptp)->tp_flags |= T_HASFILE;
 | |
| 			}
 | |
| 	ComponentType(&(*ptp)->next)
 | |
| 			{ if( (*ptp)->next->tp_flags & T_HASFILE ) {
 | |
| 			      error("file type has an illegal component type");
 | |
| 			      (*ptp)->next = error_type;
 | |
| 			  }
 | |
| 			  else {
 | |
| 				if( (*ptp)->next->tp_size > PC_BUFSIZ )
 | |
| 					(*ptp)->tp_size = (*ptp)->tp_psize =
 | |
| 					    (*ptp)->next->tp_size +
 | |
| 					    sizeof(struct file) - PC_BUFSIZ;
 | |
| 			  }
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.4.4, p. 103 */
 | |
| PointerType(register struct type **ptp;)
 | |
| {
 | |
| 	register struct node *nd;
 | |
| 	register struct def *df;
 | |
| } :
 | |
| 	'^'
 | |
| 			{ *ptp = construct_type(T_POINTER, NULLTYPE); }
 | |
| 	IDENT
 | |
| 			{ nd = MkLeaf(Name, &dot);
 | |
| 			  df = lookup(nd->nd_IDF, CurrentScope, D_INUSE);
 | |
| 			  /* if( !df && CurrentScope == GlobalScope)
 | |
| 			      df = lookup(nd->nd_IDF, PervasiveScope, D_INUSE);
 | |
| 			  */
 | |
| 			  if( in_type_defs &&
 | |
| 			      (!df || (df->df_kind & (D_ERROR | D_FORWTYPE)))
 | |
| 			    )
 | |
| 				/* forward declarations only in typedefintion
 | |
| 				   part
 | |
| 				*/
 | |
| 				Forward(nd, *ptp);
 | |
| 			  else	{
 | |
| 				chk_type_id(&(*ptp)->next, nd);
 | |
| 			  	FreeNode(nd);
 | |
| 			  }
 | |
| 			}
 | |
| ;
 | |
| 
 | |
| /* ISO section 6.6.3.1, p. 112 */
 | |
| FormalParameterList(struct node **pnd;)
 | |
| {
 | |
| 	struct node *nd;
 | |
| } :
 | |
| 	'('
 | |
| 					{ *pnd = nd = MkLeaf(Link, &dot); }
 | |
| 		FormalParameterSection(nd)
 | |
| 		[ %persistent
 | |
| 					{ nd->nd_right = MkLeaf(Link, &dot);
 | |
| 					  nd = nd->nd_right;
 | |
| 					}
 | |
| 		';' FormalParameterSection(nd)
 | |
| 		]*
 | |
| 	')'
 | |
| ;
 | |
| 
 | |
| FormalParameterSection(struct node *nd;):
 | |
| /* This is a changed rule, because the grammar as specified
 | |
|  * in the reference is not LL(1), and this gives conflicts.
 | |
|  */
 | |
| 					{ /* kind of parameter */
 | |
| 					  nd->nd_INT = 0;
 | |
| 					}
 | |
| [
 | |
| 	[
 | |
| 		/* ValueParameterSpecification */
 | |
| 		/* empty */
 | |
| 					{ nd->nd_INT = (D_VALPAR | D_SET); }
 | |
| 	|
 | |
| 		/* VariableParameterSpecification */
 | |
| 		VAR
 | |
| 					{ nd->nd_INT = (D_VARPAR | D_USED); }
 | |
| 	]
 | |
| 	IdentifierList(&(nd->nd_left)) ':'
 | |
| 	[
 | |
| 		/* ISO section 6.6.3.7.1, p. 115 */
 | |
| 		/* ConformantArrayParameterSpecification */
 | |
| 		ConformantArraySchema(&(nd->nd_type))
 | |
| 	|
 | |
| 		TypeIdentifier(&(nd->nd_type))
 | |
| 	]
 | |
| 			{ if( nd->nd_type->tp_flags & T_HASFILE  &&
 | |
| 			      (nd->nd_INT  & D_VALPAR) ) {
 | |
| 			    error("value parameter can't have a filecomponent");
 | |
| 			    nd->nd_type = error_type;
 | |
| 			  }
 | |
| 			}
 | |
| |
 | |
| 	ProceduralParameterSpecification(&(nd->nd_left), &(nd->nd_type))
 | |
| 					{ nd->nd_INT = (D_VALPAR | D_SET); }
 | |
| |
 | |
| 	FunctionalParameterSpecification(&(nd->nd_left), &(nd->nd_type))
 | |
| 					{ nd->nd_INT = (D_VALPAR | D_SET); }
 | |
| ]
 | |
| ;
 | |
| 
 | |
| ProceduralParameterSpecification(register struct node **pnd;
 | |
| 						register struct type **ptp;):
 | |
| 				{ parlevel++; }
 | |
| 	ProcedureHeading(pnd, ptp)
 | |
| 				{ parlevel--; }
 | |
| ;
 | |
| 
 | |
| FunctionalParameterSpecification(register struct node **pnd;
 | |
| 						register struct type **ptp;):
 | |
| 				{ parlevel++; }
 | |
| 	FunctionHeading(pnd, ptp)
 | |
| 				{ parlevel--;
 | |
| 				  if( !*ptp )	{
 | |
| 				      node_error(*pnd,
 | |
| 				      "illegal function parameter declaration");
 | |
| 				      *ptp = error_type;
 | |
| 				  }
 | |
| 				}
 | |
| ;
 | |
| 
 | |
| ConformantArraySchema(register struct type **ptp;):
 | |
| 	PackedConformantArraySchema(ptp)
 | |
| |
 | |
| 	%default
 | |
| 	UnpackedConformantArraySchema(ptp)
 | |
| ;
 | |
| 
 | |
| PackedConformantArraySchema(register struct type **ptp;)
 | |
| {
 | |
| 	struct type *tp;
 | |
| } :
 | |
| 	PACKED ARRAY
 | |
| 				{ tp = construct_type(T_ARRAY, NULLTYPE);
 | |
| 				  tp->tp_flags |= T_PACKED;
 | |
| 				}
 | |
| 	'['
 | |
| 		Index_TypeSpecification(ptp, tp)
 | |
| 				{ tp->next = *ptp; }
 | |
| 	']'
 | |
| 	OF TypeIdentifier(ptp)
 | |
| 				{ if( (*ptp)->tp_flags & T_HASFILE )
 | |
| 					tp->tp_flags |= T_HASFILE;
 | |
| 				  tp->arr_elem = *ptp;
 | |
| 				  *ptp = tp;
 | |
| 				}
 | |
| ;
 | |
| 
 | |
| UnpackedConformantArraySchema(register struct type **ptp;)
 | |
| {
 | |
| 	struct type *tp, *tp2;
 | |
| } :
 | |
| 	ARRAY
 | |
| 				{ *ptp = tp = construct_type(T_ARRAY,NULLTYPE);}
 | |
| 	'['
 | |
| 		Index_TypeSpecification(&tp2, tp)
 | |
| 				{ tp->next = tp2; }
 | |
| 		[
 | |
| 				{ tp->arr_elem =
 | |
| 					construct_type(T_ARRAY, NULLTYPE);
 | |
| 				  tp = tp->arr_elem;
 | |
| 				}
 | |
| 		';' Index_TypeSpecification(&tp2, tp)
 | |
| 				{ tp->next = tp2; }
 | |
| 		]*
 | |
| 	']'
 | |
| 	OF
 | |
| 	[
 | |
| 		TypeIdentifier(&tp2)
 | |
| 	|
 | |
| 		ConformantArraySchema(&tp2)
 | |
| 	]
 | |
| 				{ if( tp2->tp_flags & T_HASFILE )
 | |
| 					(*ptp)->tp_flags |= T_HASFILE;
 | |
| 				  tp->arr_elem = tp2;
 | |
| 				}
 | |
| ;
 | |
| 
 | |
| Index_TypeSpecification(register struct type **ptp, *tp;)
 | |
| {
 | |
| 	register struct def *df1, *df2;
 | |
| } :
 | |
| 	IDENT
 | |
| 			{ if( df1 =
 | |
| 			    define(dot.TOK_IDF, CurrentScope, D_LBOUND)) {
 | |
| 				df1->bnd_type = tp;	/* type conf. array */
 | |
| 				df1->df_flags |= D_SET;
 | |
| 			  }
 | |
| 			}
 | |
| 	UPTO
 | |
| 	IDENT
 | |
| 			{ if( df2 =
 | |
| 			    define(dot.TOK_IDF, CurrentScope, D_UBOUND)) {
 | |
| 				df2->bnd_type = tp;	/* type conf. array */
 | |
| 				df2->df_flags |= D_SET;
 | |
| 			  }
 | |
| 			}
 | |
| 	':' TypeIdentifier(ptp)
 | |
| 			{ if( !bounded(*ptp) &&
 | |
| 			      (*ptp)->tp_fund != T_INTEGER )	{
 | |
| 				error("Indextypespecification: illegal type");
 | |
| 				*ptp = error_type;
 | |
| 			  }
 | |
| 			  df1->df_type = df2->df_type = *ptp;
 | |
| 			}
 | |
| ;
 |