A newer version, safety commit
This commit is contained in:
		
							parent
							
								
									8546fbe868
								
							
						
					
					
						commit
						7f174a46c3
					
				
					 28 changed files with 1034 additions and 222 deletions
				
			
		|  | @ -1,20 +1,23 @@ | |||
| /*	LEXICAL ANALYSER FOR MODULA-2	*/ | ||||
| /* L E X I C A L   A N A L Y S E R   F O R   M O D U L A - 2 */ | ||||
| 
 | ||||
| #include "input.h" | ||||
| #include <alloc.h> | ||||
| #include "f_info.h" | ||||
| #include "Lpars.h" | ||||
| #include "class.h" | ||||
| #include "param.h" | ||||
| #include "idf.h" | ||||
| #include "LLlex.h" | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<alloc.h> | ||||
| #include	<em_arith.h> | ||||
| #include	"input.h" | ||||
| #include	"f_info.h" | ||||
| #include	"Lpars.h" | ||||
| #include	"class.h" | ||||
| #include	"idf.h" | ||||
| #include	"LLlex.h" | ||||
| 
 | ||||
| #define IDFSIZE	256	/* Number of significant characters in an identifier */ | ||||
| #define NUMSIZE	256	/* maximum number of characters in a number */ | ||||
| 
 | ||||
| long str2long(); | ||||
| 
 | ||||
| struct token dot, aside; | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| /*	Skip Modula-2 like comment (* ... *).
 | ||||
| 	Note that comment may be nested. | ||||
| */ | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| /*	Token Descriptor Definition	*/ | ||||
| /* T O K E N   D E S C R I P T O R   D E F I N I T I O N */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
|  | @ -9,8 +9,8 @@ struct token	{ | |||
| 		struct idf *tk_idf;	/* IDENT	*/ | ||||
| 		char *tk_str;		/* STRING	*/ | ||||
| 		struct {		/* INTEGER	*/ | ||||
| 			int tk_type;	/* type	*/ | ||||
| 			long tk_value;	/* value	*/ | ||||
| 			struct type *tk_type;	/* type	*/ | ||||
| 			arith tk_value;	/* value	*/ | ||||
| 		} tk_int; | ||||
| 		char *tk_real;		/* REAL		*/ | ||||
| 	} tk_data; | ||||
|  |  | |||
|  | @ -1,12 +1,15 @@ | |||
| /* S Y N T A X   E R R O R   R E P O R T I N G */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<alloc.h> | ||||
| #include	"f_info.h" | ||||
| #include	<em_arith.h> | ||||
| #include	"idf.h" | ||||
| #include	"LLlex.h" | ||||
| #include	"Lpars.h" | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| extern char *symbol2str(); | ||||
| extern struct idf *gen_anon_idf(); | ||||
| int err_occurred = 0; | ||||
| 
 | ||||
| LLmessage(tk) | ||||
|  | @ -21,28 +24,6 @@ LLmessage(tk) | |||
| 		error("%s deleted", symbol2str(dot.tk_symb)); | ||||
| } | ||||
| 
 | ||||
| struct idf * | ||||
| gen_anon_idf() | ||||
| { | ||||
| 	/*	A new idf is created out of nowhere, to serve as an
 | ||||
| 		anonymous name. | ||||
| 	*/ | ||||
| 	static int name_cnt; | ||||
| 	char buff[100]; | ||||
| 	char *sprintf(); | ||||
| 
 | ||||
| 	sprintf(buff, "#%d in %s, line %u", | ||||
| 			++name_cnt, FileName, LineNumber); | ||||
| 	return str2idf(buff, 1); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| is_anon_idf(idf) | ||||
| 	struct idf *idf; | ||||
| { | ||||
| 	return idf->id_text[0] == '#'; | ||||
| } | ||||
| 
 | ||||
| insert_token(tk) | ||||
| 	int tk; | ||||
| { | ||||
|  |  | |||
|  | @ -13,7 +13,8 @@ CFLAGS =	-DDEBUG -p $(INCLUDES) | |||
| LFLAGS =	-p | ||||
| LOBJ =	tokenfile.o program.o declar.o expression.o statement.o | ||||
| COBJ =	LLlex.o LLmessage.o char.o error.o main.o \
 | ||||
| 	symbol2str.o tokenname.o idf.o input.o idlist.o | ||||
| 	symbol2str.o tokenname.o idf.o input.o type.o def.o \
 | ||||
| 	scope.o misc.o print.o | ||||
| OBJ =	$(COBJ) $(LOBJ) Lpars.o | ||||
| GENFILES=	tokenfile.c \
 | ||||
| 	program.c declar.c expression.c statement.c \
 | ||||
|  | @ -40,7 +41,10 @@ tokenfile.g:	tokenname.c make.tokfile | |||
| symbol2str.c:	tokenname.c make.tokcase | ||||
| 	make.tokcase <tokenname.c >symbol2str.c | ||||
| 
 | ||||
| idlist.h:	idlist.H make.allocd | ||||
| misc.h:		misc.H make.allocd | ||||
| def.h:		def.H make.allocd | ||||
| type.h:		type.H make.allocd | ||||
| scope.c:	scope.C make.allocd | ||||
| 
 | ||||
| char.c: char.tab tab | ||||
| 	./tab -fchar.tab >char.c | ||||
|  | @ -61,19 +65,22 @@ depend: | |||
| 	make.allocd < $< > $@ | ||||
| 
 | ||||
| #AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
 | ||||
| LLlex.o: LLlex.h Lpars.h class.h f_info.h idf.h param.h | ||||
| LLmessage.o: LLlex.h Lpars.h f_info.h idf.h | ||||
| LLlex.o: LLlex.h Lpars.h class.h f_info.h idf.h input.h | ||||
| LLmessage.o: LLlex.h Lpars.h idf.h | ||||
| char.o: class.h | ||||
| error.o: LLlex.h f_info.h | ||||
| main.o: LLlex.h Lpars.h f_info.h idf.h | ||||
| error.o: LLlex.h f_info.h input.h | ||||
| main.o: LLlex.h Lpars.h debug.h f_info.h idf.h input.h main.h | ||||
| symbol2str.o: Lpars.h | ||||
| tokenname.o: Lpars.h idf.h tokenname.h | ||||
| idf.o: idf.h | ||||
| input.o: f_info.h input.h | ||||
| idlist.o: idf.h idlist.h | ||||
| type.o: Lpars.h def.h def_sizes.h idf.h type.h | ||||
| def.o: Lpars.h def.h idf.h main.h scope.h | ||||
| scope.o: scope.h | ||||
| misc.o: LLlex.h f_info.h idf.h misc.h | ||||
| tokenfile.o: Lpars.h | ||||
| program.o: Lpars.h idf.h idlist.h | ||||
| declar.o: LLlex.h Lpars.h idf.h idlist.h | ||||
| program.o: LLlex.h Lpars.h idf.h main.h misc.h | ||||
| declar.o: LLlex.h Lpars.h def.h idf.h misc.h scope.h type.h | ||||
| expression.o: Lpars.h | ||||
| statement.o: Lpars.h | ||||
| Lpars.o: Lpars.h | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| /*		U S E   O F   C H A R A C T E R   C L A S S E S		*/ | ||||
| /* U S E   O F   C H A R A C T E R   C L A S S E S */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,17 +1,43 @@ | |||
| { | ||||
| #include "idf.h" | ||||
| #include "idlist.h" | ||||
| #include "LLlex.h" | ||||
| /* D E C L A R A T I O N S */ | ||||
| 
 | ||||
| { | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<em_arith.h> | ||||
| #include	<em_label.h> | ||||
| #include	"idf.h" | ||||
| #include	"misc.h" | ||||
| #include	"LLlex.h" | ||||
| #include	"def.h" | ||||
| #include	"type.h" | ||||
| #include	"scope.h" | ||||
| } | ||||
| 
 | ||||
| ProcedureDeclaration: | ||||
| 	ProcedureHeading ';' block IDENT | ||||
| ProcedureDeclaration | ||||
| { | ||||
| 	register struct def *df; | ||||
| } : | ||||
| 	/* ProcedureHeading(&df) */ | ||||
| 	PROCEDURE IDENT | ||||
| 			{ df = define(dot.TOK_IDF, CurrentScope, D_PROCEDURE); | ||||
| 			  open_scope(OPENSCOPE, 0); | ||||
| 			} | ||||
| 	FormalParameters? | ||||
| 	';' block IDENT | ||||
| 			{ match_id(dot.TOK_IDF, df->df_idf); | ||||
| 			  close_scope(); | ||||
| 			} | ||||
| ; | ||||
| 
 | ||||
| ProcedureHeading: | ||||
| 	PROCEDURE IDENT FormalParameters? | ||||
| ProcedureHeading | ||||
| { | ||||
| 	register struct def *df; | ||||
| } : | ||||
| 	/*	Only used for definition modules | ||||
| 	*/ | ||||
| 	PROCEDURE IDENT | ||||
| 			{ df = define(dot.TOK_IDF, CurrentScope, D_PROCHEAD); } | ||||
| 	FormalParameters? | ||||
| ; | ||||
| 
 | ||||
| block: | ||||
|  | @ -32,22 +58,34 @@ declaration: | |||
| 
 | ||||
| FormalParameters: | ||||
| 	'(' [ FPSection [ ';' FPSection ]* ]? ')' | ||||
| 	[ ':' qualident ]? | ||||
| 	[ ':' qualident | ||||
| 	]? | ||||
| ; | ||||
| 
 | ||||
| FPSection | ||||
| { | ||||
| 	struct id_list *FPList; | ||||
| 	int VARflag = 0; | ||||
| } : | ||||
| 	VAR? IdentList(&FPList) ':' FormalType | ||||
| 	[ | ||||
| 		VAR	{ VARflag = 1; } | ||||
| 	]? | ||||
| 	IdentList(&FPList) ':' FormalType | ||||
| 			{ | ||||
| 			  FreeIdList(FPList); | ||||
| 			} | ||||
| ; | ||||
| 
 | ||||
| FormalType: | ||||
| 	[ ARRAY OF ]? qualident | ||||
| ; | ||||
| 
 | ||||
| TypeDeclaration: | ||||
| 	IDENT '=' type | ||||
| TypeDeclaration | ||||
| { | ||||
| 	register struct def *df; | ||||
| }: | ||||
| 	IDENT		{ df = define(dot.TOK_IDF, CurrentScope, D_TYPE); } | ||||
| 	'=' type | ||||
| ; | ||||
| 
 | ||||
| type: | ||||
|  | @ -169,8 +207,12 @@ FormalTypeList: | |||
| 	[ ':' qualident ]? | ||||
| ; | ||||
| 
 | ||||
| ConstantDeclaration: | ||||
| 	IDENT '=' ConstExpression | ||||
| ConstantDeclaration | ||||
| { | ||||
| 	register struct def *df; | ||||
| }: | ||||
| 	IDENT		{ df = define(dot.TOK_IDF, CurrentScope, D_CONST); } | ||||
| 	'=' ConstExpression | ||||
| ; | ||||
| 
 | ||||
| VariableDeclaration | ||||
|  |  | |||
							
								
								
									
										75
									
								
								lang/m2/comp/def.H
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								lang/m2/comp/def.H
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| /* I D E N T I F I E R   D E S C R I P T O R   S T R U C T U R E */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| struct module { | ||||
| 	int mo_priority;	/* Priority of a module */ | ||||
| }; | ||||
| 
 | ||||
| struct variable { | ||||
| 	char va_fixedaddress;	/* Flag, set if an address was given */ | ||||
| 	arith va_off;		/* Address or offset of variable */ | ||||
| }; | ||||
| 
 | ||||
| struct constant { | ||||
| 	struct expr *co_const;	/* A constant expression */ | ||||
| }; | ||||
| 
 | ||||
| struct enumval { | ||||
| 	unsigned int en_val;	/* Value of this enumeration literal */ | ||||
| 	struct def *en_next;	/* Next enumeration literal */ | ||||
| }; | ||||
| 
 | ||||
| struct field { | ||||
| 	arith fld_off; | ||||
| 	struct variant { | ||||
| 		struct caselabellist *fld_cases; | ||||
| 		label fld_casedescr; | ||||
| 		struct def *fld_varianttag; | ||||
| 	} *fld_variant; | ||||
| }; | ||||
| 
 | ||||
| struct import { | ||||
| 	int im_scopenr;		/* Scope number from which imported */ | ||||
| }; | ||||
| 
 | ||||
| struct def	{		/* list of definitions for a name */ | ||||
| 	struct def *next; | ||||
| 	struct idf *df_idf;	/* link back to the name */ | ||||
| 	int df_scope;		/* Scope in which this definition resides */ | ||||
| 	char df_kind;		/* The kind of this definition: */ | ||||
| #define D_MODULE	0x00 | ||||
| #define D_PROCEDURE	0x01 | ||||
| #define D_VARIABLE	0x02 | ||||
| #define D_FIELD		0x03 | ||||
| #define D_TYPE		0x04 | ||||
| #define D_ENUM		0x05 | ||||
| #define D_CONST		0x06 | ||||
| #define D_IMPORT	0x07 | ||||
| #define D_PROCHEAD	0x08	/* A procedure heading in a definition module */ | ||||
| #define D_HIDDEN	0x09	/* A hidden type */ | ||||
| #define D_HTYPE		0x0A	/* Definition of a hidden type seen */ | ||||
| #define D_ISEXPORTED	0xFF	/* Not yet defined */ | ||||
| 	char df_flags; | ||||
| #define D_ADDRESS	0x01	/* Set if address was taken */ | ||||
| #define D_USED		0x02	/* Set if used */ | ||||
| #define D_DEFINED	0x04	/* Set if it is assigned a value */ | ||||
| #define D_VARPAR	0x08	/* Set if it is a VAR parameter */ | ||||
| #define D_EXPORTED	0x40	/* Set if exported */ | ||||
| #define D_QEXPORTED	0x80	/* Set if qualified exported */ | ||||
| 	struct type *df_type; | ||||
| 	union { | ||||
| 		struct module df_module; | ||||
| 		struct variable df_variable; | ||||
| 		struct constant df_constant; | ||||
| 		struct enumval df_enum; | ||||
| 		struct field df_field; | ||||
| 		struct import df_import; | ||||
| 	} df_value; | ||||
| }; | ||||
| 
 | ||||
| /* ALLOCDEF "def" */ | ||||
| 
 | ||||
| struct def | ||||
| 	*define(), | ||||
| 	*lookup(); | ||||
							
								
								
									
										83
									
								
								lang/m2/comp/def.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								lang/m2/comp/def.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | |||
| /* D E F I N I T I O N   M E C H A N I S M */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<alloc.h> | ||||
| #include	<em_arith.h> | ||||
| #include	<em_label.h> | ||||
| #include	"Lpars.h" | ||||
| #include	"def.h" | ||||
| #include	"idf.h" | ||||
| #include	"main.h" | ||||
| #include	"scope.h" | ||||
| 
 | ||||
| struct def *h_def;		/* Pointer to free list of def structures */ | ||||
| 
 | ||||
| struct def * | ||||
| define(id, scope, kind) | ||||
| 	register struct idf *id; | ||||
| 	struct scope *scope; | ||||
| { | ||||
| 	/*	Declare an identifier in a scope, but first check if it
 | ||||
| 		already has been defined. If so, error message. | ||||
| 	*/ | ||||
| 	register struct def *df = lookup(id, scope); | ||||
| 
 | ||||
| 	if (df) { | ||||
| 		switch(df->df_kind) { | ||||
| 		case D_PROCHEAD: | ||||
| 			if (kind == D_PROCEDURE) { | ||||
| 				df->df_kind = D_PROCEDURE; | ||||
| 				return df; | ||||
| 			} | ||||
| 			break;	 | ||||
| 		case D_HIDDEN: | ||||
| 			if (kind == D_TYPE && state == IMPLEMENTATION) { | ||||
| 				df->df_kind = D_HTYPE; | ||||
| 				return df; | ||||
| 			} | ||||
| 			break; | ||||
| 		case D_ISEXPORTED: | ||||
| 			df->df_kind = kind; | ||||
| 			return df; | ||||
| 			break; | ||||
| 		} | ||||
| 		error("Identifier %s already declared", id->id_text); | ||||
| 		return df; | ||||
| 	} | ||||
| 	df = new_def(); | ||||
| 	df->df_idf = id; | ||||
| 	df->df_scope = scope->sc_scope; | ||||
| 	df->df_kind = kind; | ||||
| 	df->next = id->id_def; | ||||
| 	id->id_def = df; | ||||
| 	return df; | ||||
| } | ||||
| 
 | ||||
| struct def * | ||||
| lookup(id, scope) | ||||
| 	register struct idf *id; | ||||
| 	struct scope *scope; | ||||
| { | ||||
| 	/*	Look up a definition of an identifier in scope "scope".
 | ||||
| 		Make the "def" list self-organizing. | ||||
| 		Return a pointer to its "def" structure if it exists, | ||||
| 		otherwise return 0. | ||||
| 	*/ | ||||
| 	register struct def *df, *df1; | ||||
| 
 | ||||
| 	df1 = 0; | ||||
| 	df = id->id_def; | ||||
| 	while (df) { | ||||
| 		if (df->df_scope == scope->sc_scope) { | ||||
| 			if (df1) { | ||||
| 				df1->next = df->next; | ||||
| 				df->next = id->id_def; | ||||
| 				id->id_def = df; | ||||
| 			} | ||||
| 			return df; | ||||
| 		} | ||||
| 		df = df->next; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										22
									
								
								lang/m2/comp/def_sizes.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								lang/m2/comp/def_sizes.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| /* D E F A U L T   S I Z E S   A N D   A L I G N M E N T S */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| #define MAXSIZE		8	/* the maximum of the SZ_* constants	*/ | ||||
| /* target machine sizes	*/ | ||||
| #define	SZ_CHAR		(arith)1 | ||||
| #define SZ_WORD		(arith)4 | ||||
| #define	SZ_INT		(arith)4 | ||||
| #define	SZ_LONG		(arith)4 | ||||
| #define	SZ_FLOAT	(arith)4 | ||||
| #define	SZ_DOUBLE	(arith)8 | ||||
| #define	SZ_POINTER	(arith)4 | ||||
| /* target machine alignment requirements	*/ | ||||
| #define	AL_CHAR		1 | ||||
| #define AL_WORD		(int) SZ_WORD | ||||
| #define	AL_INT		(int) SZ_WORD | ||||
| #define	AL_LONG		(int) SZ_WORD | ||||
| #define	AL_FLOAT	(int) SZ_WORD | ||||
| #define	AL_DOUBLE	(int) SZ_WORD | ||||
| #define	AL_POINTER	(int) SZ_WORD | ||||
| #define AL_STRUCT	1 | ||||
|  | @ -1,105 +1,101 @@ | |||
| /*	E R R O R   A N D  D I A G N O S T I C   R O U T I N E S	*/ | ||||
| /* E R R O R   A N D   D I A G N O S T I C   R O U T I N E S */ | ||||
| 
 | ||||
| /*	This file contains the (non-portable) error-message and diagnostic
 | ||||
| 	giving functions.  Be aware that they are called with a variable | ||||
| 	number of arguments! | ||||
| */ | ||||
| 
 | ||||
| #include	<stdio.h> | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<system.h> | ||||
| #include	<em_arith.h> | ||||
| #include	"input.h" | ||||
| #include	"f_info.h" | ||||
| #include	"LLlex.h" | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #define	ERROUT	stderr | ||||
| #define MAXERR_LINE	5	/* Number of error messages on one line ... */ | ||||
| #define	ERROUT		STDERR | ||||
| 
 | ||||
| /* error classes */ | ||||
| #define	ERROR		1 | ||||
| #define	WARNING		2 | ||||
| #define	LEXERROR	3 | ||||
| #define	LEXWARNING	4 | ||||
| #define	CRASH		5 | ||||
| #define	FATAL		6 | ||||
| #define	NONFATAL	7 | ||||
| #ifdef	DEBUG | ||||
| #define	VDEBUG		8 | ||||
| #endif	DEBUG | ||||
| #ifdef DEBUG | ||||
| #define VDEBUG		7 | ||||
| #endif | ||||
| 
 | ||||
| #define NILEXPR	((struct expr *) 0) | ||||
| 
 | ||||
| int err_occurred; | ||||
| /*
 | ||||
| 	extern int ofd;		/* compact.c	* /
 | ||||
| 	#define	compiling (ofd >= 0) | ||||
| */ | ||||
| 
 | ||||
| extern char *symbol2str(); | ||||
| extern char options[]; | ||||
| 
 | ||||
| /*	There are two general error message giving functions:
 | ||||
| 	error() : syntactic and semantic error messages | ||||
| 	lexerror() : lexical and pre-processor error messages | ||||
| 	The difference lies in the fact that the first function deals with | ||||
| 	tokens already read in by the lexical analyzer so the name of the | ||||
| 	file it comes from and the linenumber must be retrieved from the | ||||
| 	token instead of looking at the global variables LineNumber and | ||||
| 	FileName. | ||||
| /*	There are three general error-message functions:
 | ||||
| 		lexerror()	lexical and pre-processor error messages | ||||
| 		error()		syntactic and semantic error messages | ||||
| 		expr_error()	errors in expressions | ||||
| 	The difference lies in the place where the file name and line | ||||
| 	number come from. | ||||
| 	Lexical errors report from the global variables LineNumber and | ||||
| 	FileName, expression errors get their information from the | ||||
| 	expression, whereas other errors use the information in the token. | ||||
| */ | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| /*VARARGS2*/ | ||||
| debug(level, fmt, args) | ||||
| 	char *fmt; | ||||
| { | ||||
| 	if (level <= options['D']) _error(VDEBUG, NILEXPR, fmt, &args); | ||||
| } | ||||
| #endif DEBUG | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| error(fmt, args) | ||||
| 	char *fmt; | ||||
| { | ||||
| 	/*
 | ||||
| 		if (compiling) | ||||
| 			C_ms_err(); | ||||
| 	*/ | ||||
| 	++err_occurred; | ||||
| 	_error(ERROR, fmt, &args); | ||||
| 	_error(ERROR, NILEXPR, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| #ifdef DEBUG | ||||
| debug(fmt, args) | ||||
| /*VARARGS2*/ | ||||
| expr_error(expr, fmt, args) | ||||
| 	struct expr *expr; | ||||
| 	char *fmt; | ||||
| { | ||||
| 	if (options['D']) | ||||
| 		_error(VDEBUG, fmt, &args); | ||||
| 	_error(ERROR, expr, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| warning(fmt, args) | ||||
| 	char *fmt; | ||||
| { | ||||
| 	_error(WARNING, NILEXPR, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS2*/ | ||||
| expr_warning(expr, fmt, args) | ||||
| 	struct expr *expr; | ||||
| 	char *fmt; | ||||
| { | ||||
| 	_error(WARNING, expr, fmt, &args); | ||||
| } | ||||
| #endif DEBUG | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| lexerror(fmt, args) | ||||
| 	char *fmt; | ||||
| { | ||||
| 	/*
 | ||||
| 		if (compiling) | ||||
| 			C_ms_err(); | ||||
| 	*/ | ||||
| 	++err_occurred; | ||||
| 	_error(LEXERROR, fmt, &args); | ||||
| 	_error(LEXERROR, NILEXPR, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| lexwarning(fmt, args) char *fmt;	{ | ||||
| 	if (options['w']) return; | ||||
| 	_error(LEXWARNING, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| crash(fmt, args) | ||||
| lexwarning(fmt, args)  | ||||
| 	char *fmt; | ||||
| 	int args; | ||||
| { | ||||
| 	/*
 | ||||
| 		if (compiling) | ||||
| 			C_ms_err(); | ||||
| 	*/ | ||||
| 	_error(CRASH, fmt, &args); | ||||
| 	fflush(ERROUT); | ||||
| 	fflush(stderr); | ||||
| 	fflush(stdout); | ||||
| 	/*
 | ||||
| 		cclose(); | ||||
| 	*/ | ||||
| 	abort();	/* produce core by "Illegal Instruction" */ | ||||
| 			/* this should be changed into exit(1)	 */ | ||||
| 	_error(LEXWARNING, NILEXPR, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
|  | @ -107,64 +103,103 @@ fatal(fmt, args) | |||
| 	char *fmt; | ||||
| 	int args; | ||||
| { | ||||
| 	/*
 | ||||
| 		if (compiling) | ||||
| 			C_ms_err(); | ||||
| 	*/ | ||||
| 	_error(FATAL, fmt, &args); | ||||
| 	exit(-1); | ||||
| 
 | ||||
| 	_error(FATAL, NILEXPR, fmt, &args); | ||||
| 	sys_stop(S_EXIT); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| nonfatal(fmt, args) | ||||
| 	char *fmt; | ||||
| 	int args; | ||||
| { | ||||
| 	_error(NONFATAL, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| warning(fmt, args) | ||||
| 	char *fmt; | ||||
| { | ||||
| 	if (options['w']) return; | ||||
| 	_error(WARNING, fmt, &args); | ||||
| } | ||||
| 
 | ||||
| _error(class, fmt, argv) | ||||
| _error(class, expr, fmt, argv) | ||||
| 	int class; | ||||
| 	struct expr *expr; | ||||
| 	char *fmt; | ||||
| 	int argv[]; | ||||
| { | ||||
| 	/*	_error attempts to limit the number of error messages
 | ||||
| 		for a given line to MAXERR_LINE. | ||||
| 	*/ | ||||
| 	static unsigned int last_ln = 0; | ||||
| 	static int e_seen = 0; | ||||
| 	unsigned int ln = 0; | ||||
| 	char *remark = 0; | ||||
| 	 | ||||
| 	/*	Since name and number are gathered from different places
 | ||||
| 		depending on the class, we first collect the relevant | ||||
| 		values and then decide what to print. | ||||
| 	*/ | ||||
| 	/* preliminaries */ | ||||
| 	switch (class)	{ | ||||
| 
 | ||||
| 	case ERROR: | ||||
| 	case LEXERROR: | ||||
| 		fprintf(ERROUT, "%s, line %ld: ", FileName, LineNumber); | ||||
| 	case CRASH: | ||||
| 	case FATAL: | ||||
| 		/*
 | ||||
| 		if (C_busy()) | ||||
| 			C_ms_err(); | ||||
| 		*/ | ||||
| 		err_occurred = 1; | ||||
| 		break; | ||||
| 	 | ||||
| 	case WARNING: | ||||
| 	case LEXWARNING: | ||||
| 		fprintf(ERROUT, "%s, line %ld: (warning) ", | ||||
| 			FileName, LineNumber); | ||||
| 		if (options['w']) | ||||
| 			return; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	/* the remark */ | ||||
| 	switch (class)	{	 | ||||
| 	case WARNING: | ||||
| 	case LEXWARNING: | ||||
| 		remark = "(warning)"; | ||||
| 		break; | ||||
| 	case CRASH: | ||||
| 		fprintf(ERROUT, "CRASH\007 %s, line %ld: \n", | ||||
| 			FileName, LineNumber); | ||||
| 		remark = "CRASH\007"; | ||||
| 		break; | ||||
| 	case FATAL: | ||||
| 		fprintf(ERROUT, "%s, line %ld: fatal error -- ", | ||||
| 			FileName, LineNumber); | ||||
| 		remark = "fatal error --"; | ||||
| 		break; | ||||
| 	case NONFATAL: | ||||
| 		fprintf(ERROUT, "warning: ");	/* no line number ??? */ | ||||
| 		break; | ||||
| #ifdef DEBUG | ||||
| 	case VDEBUG: | ||||
| 		fprintf(ERROUT, "-D "); | ||||
| 		break; | ||||
| #endif DEBUG | ||||
| 	} | ||||
| 	_doprnt(fmt, argv, ERROUT); | ||||
| 	 | ||||
| 	/* the place */ | ||||
| 	switch (class)	{	 | ||||
| 	case WARNING: | ||||
| 	case ERROR: | ||||
| 		ln = /* expr ? expr->ex_line : */ dot.tk_lineno; | ||||
| 		break; | ||||
| 	case LEXWARNING: | ||||
| 	case LEXERROR: | ||||
| 	case CRASH: | ||||
| 	case FATAL: | ||||
| 		ln = LineNumber; | ||||
| 		break; | ||||
| 	} | ||||
| 	 | ||||
| #ifdef DEBUG | ||||
| 	if (class != VDEBUG) { | ||||
| #endif | ||||
| 	if (ln == last_ln)	{ | ||||
| 		/* we've seen this place before */ | ||||
| 		e_seen++; | ||||
| 		if (e_seen == MAXERR_LINE) | ||||
| 			fmt = "etc ..."; | ||||
| 		else | ||||
| 		if (e_seen > MAXERR_LINE) | ||||
| 			/* and too often, I'd say ! */ | ||||
| 			return; | ||||
| 	} | ||||
| 	else	{ | ||||
| 		/* brand new place */ | ||||
| 		last_ln = ln; | ||||
| 		e_seen = 0; | ||||
| 	} | ||||
| 	 | ||||
| 	if (FileName) | ||||
| 		fprintf(ERROUT, "\"%s\", line %u: ", FileName, ln); | ||||
| 	if (remark) | ||||
| 		fprintf(ERROUT, "%s ", remark); | ||||
| #ifdef DEBUG | ||||
| 	} | ||||
| #endif | ||||
| 	doprnt(ERROUT, fmt, argv);		/* contents of error */ | ||||
| 	fprintf(ERROUT, "\n"); | ||||
| } | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| /* F I L E   D E S C R I P T O R   S T R U C T U R E */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| struct f_info { | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| /* I N S T A N T I A T I O N   O F   I D F   P A C K A G E */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| #include	"idf.h" | ||||
|  |  | |||
|  | @ -1,5 +1,14 @@ | |||
| /* U S E R   D E C L A R E D   P A R T   O F   I D F */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| #define IDF_TYPE int | ||||
| #define id_reserved id_user | ||||
| struct id_u { | ||||
| 	int id_res; | ||||
| 	struct def *id_df; | ||||
| }; | ||||
| 
 | ||||
| #define IDF_TYPE	struct id_u | ||||
| #define id_reserved	id_user.id_res | ||||
| #define id_def		id_user.id_df | ||||
| 
 | ||||
| #include	<idf_pkg.spec> | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| /* I N S T A N T I A T I O N   O F   I N P U T   P A C K A G E */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| #include	"f_info.h" | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| /* I N S T A N T I A T I O N   O F   I N P U T   M O D U L E */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| #define INP_NPUSHBACK 2 | ||||
|  |  | |||
|  | @ -1,18 +1,20 @@ | |||
| /* mod2 -- compiler , althans: een aanzet daartoe */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #undef BUFSIZ			/* Really neccesary??? */ | ||||
| #include <system.h> | ||||
| #include "input.h" | ||||
| #include "f_info.h" | ||||
| #include "idf.h" | ||||
| #include "LLlex.h" | ||||
| #include "Lpars.h" | ||||
| /* M A I N   P R O G R A M */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<system.h> | ||||
| #include	<em_arith.h> | ||||
| #include	"input.h" | ||||
| #include	"f_info.h" | ||||
| #include	"idf.h" | ||||
| #include	"LLlex.h" | ||||
| #include	"Lpars.h" | ||||
| #include	"main.h" | ||||
| #include	"debug.h" | ||||
| 
 | ||||
| char options[128]; | ||||
| char *ProgName; | ||||
| int state; | ||||
| extern int err_occurred; | ||||
| 
 | ||||
| main(argc, argv) | ||||
|  | @ -23,9 +25,6 @@ main(argc, argv) | |||
| 
 | ||||
| 	ProgName = *argv++; | ||||
| 
 | ||||
| # ifdef DEBUG | ||||
| 	setbuf(stdout, (char *) 0); | ||||
| # endif | ||||
| 	while (--argc > 0) { | ||||
| 		if (**argv == '-') | ||||
| 			Option(*argv++); | ||||
|  | @ -34,13 +33,13 @@ main(argc, argv) | |||
| 	} | ||||
| 	Nargv[Nargc] = 0;	/* terminate the arg vector	*/ | ||||
| 	if (Nargc != 2) { | ||||
| 		fprintf(stderr, "%s: Use one file argument\n", ProgName); | ||||
| 		fprintf(STDERR, "%s: Use one file argument\n", ProgName); | ||||
| 		return 1; | ||||
| 	} | ||||
| #ifdef DEBUG | ||||
| 	printf("Mod2 compiler -- Debug version\n"); | ||||
| 	debug("-D: Debugging on"); | ||||
| #endif DEBUG | ||||
| 	DO_DEBUG(debug(1,"Debugging level: %d", options['D'])); | ||||
| 	return !Compile(Nargv[1]); | ||||
| } | ||||
| 
 | ||||
|  | @ -53,13 +52,15 @@ Compile(src) | |||
| 	printf("%s\n", src); | ||||
| #endif DEBUG | ||||
| 	if (! InsertFile(src, (char **) 0)) { | ||||
| 		fprintf(stderr,"%s: cannot open %s\n", ProgName, src); | ||||
| 		fprintf(STDERR,"%s: cannot open %s\n", ProgName, src); | ||||
| 		return 0; | ||||
| 	} | ||||
| 	LineNumber = 1; | ||||
| 	FileName = src; | ||||
| 	init_idf(); | ||||
| 	reserve(tkidf); | ||||
| 	init_scope(); | ||||
| 	init_types(); | ||||
| #ifdef DEBUG | ||||
| 	if (options['L']) | ||||
| 		LexScan(); | ||||
|  | @ -80,7 +81,7 @@ LexScan() | |||
| { | ||||
| 	register int symb; | ||||
| 
 | ||||
| 	while ((symb = LLlex()) != EOF) { | ||||
| 	while ((symb = LLlex()) != EOI) { | ||||
| 		printf(">>> %s ", symbol2str(symb)); | ||||
| 		switch(symb) { | ||||
| 
 | ||||
|  | @ -107,15 +108,12 @@ LexScan() | |||
| } | ||||
| 
 | ||||
| TimeScan() { | ||||
| 	while (LLlex() != EOF) /* nothing */; | ||||
| 	while (LLlex() != -1) /* nothing */; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| Option(str) | ||||
| 	char *str; | ||||
| { | ||||
| #ifdef DEBUG | ||||
| 	debug("option %c", str[1]); | ||||
| #endif DEBUG | ||||
| 	options[str[1]]++;	/* switch option on	*/ | ||||
| } | ||||
|  |  | |||
							
								
								
									
										8
									
								
								lang/m2/comp/main.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								lang/m2/comp/main.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| /* S O M E   G L O B A L   V A R I A B L E S */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| extern int | ||||
| 	state;		/* Indicates what we are compiling: A DEFINITION,
 | ||||
| 			   an IMPLEMENTATION, or a PROGRAM module | ||||
| 			*/ | ||||
							
								
								
									
										12
									
								
								lang/m2/comp/misc.H
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lang/m2/comp/misc.H
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| /* M I S C E L L A N E O U S */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| /*	Structure to link idf structures together
 | ||||
| */ | ||||
| struct id_list { | ||||
| 	struct id_list *next; | ||||
| 	struct idf *id_ptr; | ||||
| }; | ||||
| 
 | ||||
| /* ALLOCDEF "id_list" */ | ||||
							
								
								
									
										63
									
								
								lang/m2/comp/misc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								lang/m2/comp/misc.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,63 @@ | |||
| /* M I S C E L L A N E O U S    R O U T I N E S */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<alloc.h> | ||||
| #include	<em_arith.h> | ||||
| #include	"f_info.h" | ||||
| #include	"misc.h" | ||||
| #include	"LLlex.h" | ||||
| #include	"idf.h" | ||||
| 
 | ||||
| match_id(id1, id2) | ||||
| 	struct idf *id1, *id2; | ||||
| { | ||||
| 	/*	Check that identifiers id1 and id2 are equal. If they
 | ||||
| 		are not, check that we did'nt generate them in the | ||||
| 		first place, and if not, give an error message | ||||
| 	*/ | ||||
| 	if (id1 != id2 && !is_anon_idf(id1) && !is_anon_idf(id2)) { | ||||
| 		error("Identifier \"%s\" does not match identifier \"%s\"", | ||||
| 		      id1->id_text, | ||||
| 		      id2->id_text | ||||
| 		); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct id_list *h_id_list;	/* Header of free list of id_list structures */ | ||||
| 
 | ||||
| /*	FreeIdList: take a list of id_list structures and put them
 | ||||
| 	on the free list of id_list structures | ||||
| */ | ||||
| FreeIdList(p) | ||||
| 	struct id_list *p; | ||||
| { | ||||
| 	register struct id_list *q; | ||||
| 
 | ||||
| 	while (q = p) { | ||||
| 		p = p->next; | ||||
| 		free_id_list(q); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| struct idf * | ||||
| gen_anon_idf() | ||||
| { | ||||
| 	/*	A new idf is created out of nowhere, to serve as an
 | ||||
| 		anonymous name. | ||||
| 	*/ | ||||
| 	static int name_cnt; | ||||
| 	char buff[100]; | ||||
| 	char *sprintf(); | ||||
| 
 | ||||
| 	sprintf(buff, "#%d in %s, line %u", | ||||
| 			++name_cnt, FileName, LineNumber); | ||||
| 	return str2idf(buff, 1); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| is_anon_idf(idf) | ||||
| 	struct idf *idf; | ||||
| { | ||||
| 	return idf->id_text[0] == '#'; | ||||
| } | ||||
							
								
								
									
										144
									
								
								lang/m2/comp/print.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								lang/m2/comp/print.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,144 @@ | |||
| /* P R I N T    R O U T I N E S */ | ||||
| 
 | ||||
| #include	<system.h> | ||||
| #include	<em_arith.h> | ||||
| 
 | ||||
| #define SSIZE	1024	/* string-buffer size for print routines	*/ | ||||
| 
 | ||||
| char *long2str(); | ||||
| 
 | ||||
| doprnt(fp, fmt, argp) | ||||
| 	File *fp; | ||||
| 	char *fmt; | ||||
| 	int argp[]; | ||||
| { | ||||
| 	char buf[SSIZE]; | ||||
| 
 | ||||
| 	sys_write(fp, buf, format(buf, fmt, (char *)argp)); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| printf(fmt, args) | ||||
| 	char *fmt; | ||||
| 	char args; | ||||
| { | ||||
| 	char buf[SSIZE]; | ||||
| 
 | ||||
| 	sys_write(STDOUT, buf, format(buf, fmt, &args)); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| fprintf(fp, fmt, args) | ||||
| 	File *fp; | ||||
| 	char *fmt; | ||||
| 	char args; | ||||
| { | ||||
| 	char buf[SSIZE]; | ||||
| 
 | ||||
| 	sys_write(fp, buf, format(buf, fmt, &args)); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| char * | ||||
| sprintf(buf, fmt, args) | ||||
| 	char *buf, *fmt; | ||||
| 	char args; | ||||
| { | ||||
| 	buf[format(buf, fmt, &args)] = '\0'; | ||||
| 	return buf; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| format(buf, fmt, argp) | ||||
| 	char *buf, *fmt; | ||||
| 	char *argp; | ||||
| { | ||||
| 	register char *pf = fmt, *pa = argp; | ||||
| 	register char *pb = buf; | ||||
| 
 | ||||
| 	while (*pf) { | ||||
| 		if (*pf == '%') { | ||||
| 			register int width, base, pad, npad; | ||||
| 			char *arg; | ||||
| 			char cbuf[2]; | ||||
| 			char *badformat = "<bad format>"; | ||||
| 			 | ||||
| 			/* get padder */ | ||||
| 			if (*++pf == '0') { | ||||
| 				pad = '0'; | ||||
| 				++pf; | ||||
| 			} | ||||
| 			else | ||||
| 				pad = ' '; | ||||
| 			 | ||||
| 			/* get width */ | ||||
| 			width = 0; | ||||
| 			while (*pf >= '0' && *pf <= '9') | ||||
| 				width = 10 * width + *pf++ - '0'; | ||||
| 			 | ||||
| 			/* get text and move pa */ | ||||
| 			if (*pf == 's') { | ||||
| 				arg = *(char **)pa; | ||||
| 				pa += sizeof(char *); | ||||
| 			} | ||||
| 			else | ||||
| 			if (*pf == 'c') { | ||||
| 				cbuf[0] = * (char *) pa; | ||||
| 				cbuf[1] = '\0'; | ||||
| 				pa += sizeof(int); | ||||
| 				arg = &cbuf[0]; | ||||
| 			} | ||||
| 			else | ||||
| 			if (*pf == 'l') { | ||||
| 				/* alignment ??? */ | ||||
| 				if (base = integral(*++pf)) { | ||||
| 					arg = long2str(*(long *)pa, base); | ||||
| 					pa += sizeof(long); | ||||
| 				} | ||||
| 				else { | ||||
| 					pf--; | ||||
| 					arg = badformat; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			if (base = integral(*pf)) { | ||||
| 				arg = long2str((long)*(int *)pa, base); | ||||
| 				pa += sizeof(int); | ||||
| 			} | ||||
| 			else | ||||
| 			if (*pf == '%') | ||||
| 				arg = "%"; | ||||
| 			else | ||||
| 				arg = badformat; | ||||
| 
 | ||||
| 			npad = width - strlen(arg); | ||||
| 
 | ||||
| 			while (npad-- > 0) | ||||
| 				*pb++ = pad; | ||||
| 			 | ||||
| 			while (*pb++ = *arg++); | ||||
| 			pb--; | ||||
| 			pf++; | ||||
| 		} | ||||
| 		else | ||||
| 			*pb++ = *pf++; | ||||
| 	} | ||||
| 	return pb - buf; | ||||
| } | ||||
| 
 | ||||
| integral(c) | ||||
| { | ||||
| 	switch (c) { | ||||
| 	case 'b': | ||||
| 		return -2; | ||||
| 	case 'd': | ||||
| 		return 10; | ||||
| 	case 'o': | ||||
| 		return -8; | ||||
| 	case 'u': | ||||
| 		return -10; | ||||
| 	case 'x': | ||||
| 		return -16; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | @ -1,8 +1,15 @@ | |||
| /* | ||||
| 	Program: Modula-2 grammar in LL(1) form | ||||
| 	Version: Mon Feb 24 14:29:39 MET 1986 | ||||
| */ | ||||
| /* O V E R A L L   S T R U C T U R E */ | ||||
| 
 | ||||
| { | ||||
| static  char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<alloc.h> | ||||
| #include	<em_arith.h> | ||||
| #include	"idf.h" | ||||
| #include	"misc.h" | ||||
| #include	"main.h" | ||||
| #include	"LLlex.h" | ||||
| } | ||||
| /* | ||||
| 	The grammar as given by Wirth is already almost LL(1); the | ||||
| 	main problem is that the full form of a qualified designator | ||||
|  | @ -17,19 +24,12 @@ | |||
| 	field identifiers. | ||||
| */ | ||||
| 
 | ||||
| { | ||||
| #include "idf.h" | ||||
| #include "idlist.h" | ||||
| 
 | ||||
| static  char *RcsId = "$Header$"; | ||||
| } | ||||
| 
 | ||||
| %lexical LLlex; | ||||
| 
 | ||||
| %start	CompUnit, CompilationUnit; | ||||
| 
 | ||||
| ModuleDeclaration: | ||||
| 	MODULE IDENT priority? ';' import* export? block IDENT | ||||
| 	MODULE IDENT priority? ';' import(1)* export? block IDENT | ||||
| ; | ||||
| 
 | ||||
| priority: | ||||
|  | @ -41,14 +41,18 @@ export | |||
| 	struct id_list *ExportList; | ||||
| } : | ||||
| 	EXPORT QUALIFIED? IdentList(&ExportList) ';' | ||||
| 			{ | ||||
| 			  FreeIdList(ExportList); | ||||
| 			} | ||||
| ; | ||||
| 
 | ||||
| import | ||||
| import(int local;) | ||||
| { | ||||
| 	struct id_list *ImportList; | ||||
| 	struct idf *id = 0; | ||||
| } : | ||||
| 	[ FROM | ||||
| 	  IDENT | ||||
| 	  IDENT		{ id = dot.TOK_IDF; } | ||||
| 	]? | ||||
| 	IMPORT IdentList(&ImportList) ';' | ||||
| 	/* | ||||
|  | @ -57,19 +61,19 @@ import | |||
| 	   If the FROM clause is present, the identifier in it is a module | ||||
| 	   name, otherwise the names in the import list are module names. | ||||
| 	*/ | ||||
| 			{ | ||||
| 			  FreeIdList(ImportList); | ||||
| 			} | ||||
| ; | ||||
| 
 | ||||
| DefinitionModule: | ||||
| 	DEFINITION | ||||
| 	{ | ||||
| #ifdef DEBUG | ||||
| 		debug("Definition module"); | ||||
| #endif DEBUG | ||||
| 	} | ||||
| 	MODULE IDENT ';' import*  | ||||
| 	/* export? | ||||
| 	DEFINITION	{ state = DEFINITION; } | ||||
| 	MODULE IDENT | ||||
| 	';' | ||||
| 	import(0)*  | ||||
| 	/*	export? | ||||
| 
 | ||||
| 	   New Modula-2 does not have export lists in definition modules. | ||||
| 	   	New Modula-2 does not have export lists in definition modules. | ||||
| 	*/ | ||||
| 	definition* END IDENT '.' | ||||
| ; | ||||
|  | @ -96,19 +100,17 @@ definition: | |||
| ; | ||||
| 
 | ||||
| ProgramModule: | ||||
| 	MODULE | ||||
| 	{ | ||||
| #ifdef DEBUG | ||||
| 		debug("Program module"); | ||||
| #endif DEBUG | ||||
| 	} | ||||
| 	IDENT priority? ';' import* block IDENT '.' | ||||
| 	MODULE		{ if (state != IMPLEMENTATION) state = PROGRAM; } | ||||
| 	IDENT priority? ';' import(0)* block IDENT '.' | ||||
| ; | ||||
| 
 | ||||
| Module: | ||||
| 	DefinitionModule | ||||
| | | ||||
| 	IMPLEMENTATION? ProgramModule | ||||
| 	[ | ||||
| 		IMPLEMENTATION	{ state = IMPLEMENTATION; } | ||||
| 	]? | ||||
| 	ProgramModule | ||||
| ; | ||||
| 
 | ||||
| CompilationUnit: | ||||
|  |  | |||
							
								
								
									
										62
									
								
								lang/m2/comp/scope.C
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								lang/m2/comp/scope.C
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| /* S C O P E   M E C H A N I S M */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<assert.h> | ||||
| #include	<alloc.h> | ||||
| #include	"scope.h" | ||||
| 
 | ||||
| static int maxscope;		/* maximum assigned scope number */ | ||||
| 
 | ||||
| struct scope *CurrentScope; | ||||
| 
 | ||||
| /* STATICALLOCDEF "scope" */ | ||||
| 
 | ||||
| /*	Open a scope that is either open (automatic imports) or closed.
 | ||||
| 	A closed scope is handled by adding an extra entry to the list | ||||
| 	with scope number 0. This has two purposes: it makes scope 0 | ||||
| 	visible, and it marks the end of a visibility list. | ||||
| 	Scope 0 is the pervasive scope, the one that is always visible. | ||||
| 	A disadvantage of this method is that we cannot open scope 0 | ||||
| 	explicitly. | ||||
| */ | ||||
| open_scope(scopetype, scopenr) | ||||
| { | ||||
| 	register struct scope *sc = new_scope(); | ||||
| 	register struct scope *sc1; | ||||
| 
 | ||||
| 	sc->sc_scope = scopenr == 0 ? ++maxscope : scopenr; | ||||
| 	assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE); | ||||
| 	sc1 = CurrentScope; | ||||
| 	if (scopetype == CLOSEDSCOPE) { | ||||
| 		sc1 = new_scope(); | ||||
| 		sc1->sc_scope = 0;			/* Pervasive scope nr */ | ||||
| 		sc1->next = CurrentScope; | ||||
| 	} | ||||
| 	sc->next = sc1; | ||||
| 	CurrentScope = sc; | ||||
| } | ||||
| 
 | ||||
| close_scope() | ||||
| { | ||||
| 	register struct scope *sc = CurrentScope; | ||||
| 
 | ||||
| 	assert(sc != 0); | ||||
| 	if (sc->next && (sc->next->sc_scope == 0)) { | ||||
| 		struct scope *sc1 = sc; | ||||
| 
 | ||||
| 		sc = sc->next; | ||||
| 		free_scope(sc1); | ||||
| 	} | ||||
| 	CurrentScope = sc->next; | ||||
| 	free_scope(sc); | ||||
| } | ||||
| 
 | ||||
| init_scope() | ||||
| { | ||||
| 	register struct scope *sc = new_scope(); | ||||
| 
 | ||||
| 	sc->sc_scope = 0; | ||||
| 	sc->next = 0; | ||||
| 	CurrentScope = sc; | ||||
| } | ||||
							
								
								
									
										19
									
								
								lang/m2/comp/scope.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								lang/m2/comp/scope.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| /* S C O P E   M E C H A N I S M */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| #define OPENSCOPE	0	/* Indicating an open scope */ | ||||
| #define CLOSEDSCOPE	1	/* Indicating a closed scope (module) */ | ||||
| 
 | ||||
| struct scope { | ||||
| 	struct scope *next; | ||||
| 	int sc_scope;		/* The scope number. Scope number 0 indicates
 | ||||
| 				   both the pervasive scope and the end of a | ||||
| 				   visibility range | ||||
| 				*/ | ||||
| }; | ||||
| 
 | ||||
| extern struct scope | ||||
| 	*CurrentScope; | ||||
| 
 | ||||
| #define nextvisible(x)	((x)->sc_scope ? (x)->next : (struct scope *) 0) | ||||
|  | @ -1,3 +1,5 @@ | |||
| /* S T A T E M E N T S */ | ||||
| 
 | ||||
| { | ||||
| static char *RcsId = "$Header$"; | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,10 @@ | |||
| #include "tokenname.h" | ||||
| #include "Lpars.h" | ||||
| #include "idf.h" | ||||
| /* T O K E N   D E F I N I T I O N S */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	"tokenname.h" | ||||
| #include	"Lpars.h" | ||||
| #include	"idf.h" | ||||
| 
 | ||||
| /*	To centralize the declaration of %tokens, their presence in this
 | ||||
| 	file is taken as their declaration. The Makefile will produce | ||||
|  | @ -9,8 +13,6 @@ | |||
| 	Also, the "token2str.c" file is produced from this file. | ||||
| */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| struct tokenname tkspec[] =	{	/* the names of the special tokens */ | ||||
| 	{IDENT, "identifier"}, | ||||
| 	{STRING, "string"}, | ||||
|  | @ -73,10 +75,18 @@ struct tokenname tkidf[] =	{	/* names of the identifier tokens */ | |||
| }; | ||||
| 
 | ||||
| struct tokenname tkinternal[] = {	/* internal keywords	*/ | ||||
| 	{PROGRAM, ""}, | ||||
| 	{0, "0"} | ||||
| }; | ||||
| 
 | ||||
| struct tokenname tkstandard[] =	{	/* standard identifiers */ | ||||
| 	{CHAR, "CHAR"}, | ||||
| 	{BOOLEAN, "BOOLEAN"}, | ||||
| 	{LONGINT, "LONGINT"}, | ||||
| 	{CARDINAL, "CARDINAL"}, | ||||
| 	{LONGREAL, "LONGREAL"}, | ||||
| 	{SUBRANGE, ""}, | ||||
| 	{ERRONEOUS, ""}, | ||||
| 	{0, ""} | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,4 +1,7 @@ | |||
| /* T O K E N N A M E   S T R U C T U R E */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| struct tokenname	{	/*	Used for defining the name of a
 | ||||
| 					token as identified by its symbol | ||||
| 				*/ | ||||
|  |  | |||
							
								
								
									
										90
									
								
								lang/m2/comp/type.H
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								lang/m2/comp/type.H
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,90 @@ | |||
| /* T Y P E   D E S C R I P T O R   S T R U C T U R E */ | ||||
| 
 | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| struct paramlist {		/* structure for parameterlist of a PROCEDURE */ | ||||
| 	struct paramlist *next; | ||||
| 	struct type *par_type;	/* Parameter type */ | ||||
| 	int par_var;		/* flag, set if VAR parameter */ | ||||
| }; | ||||
| 
 | ||||
| /* ALLOCDEF "paramlist" */ | ||||
| 
 | ||||
| struct enume { | ||||
| 	struct def *en_enums;	/* Definitions of enumeration literals */ | ||||
| 	unsigned int en_ncst;	/* Number of constants */ | ||||
| 	label en_rck;		/* Label of range check descriptor */ | ||||
| }; | ||||
| 
 | ||||
| struct subrange { | ||||
| 	arith su_lb, su_ub;	/* Lower bound and upper bound */ | ||||
| 	label su_rck;		/* Label of range check descriptor */ | ||||
| }; | ||||
| 
 | ||||
| struct array { | ||||
| 	struct type *ar_index;	/* Type of index */ | ||||
| 	arith ar_lb, ar_ub;	/* Lower bound and upper bound */ | ||||
| 	label ar_descr;		/* Label of array descriptor */ | ||||
| }; | ||||
| 
 | ||||
| struct record { | ||||
| 	int rc_scopenr;		/* Scope number of this record */ | ||||
| 				/* Members are in the symbol table */ | ||||
| }; | ||||
| 
 | ||||
| struct proc { | ||||
| 	struct paramlist *pr_params; | ||||
| }; | ||||
| 
 | ||||
| struct type	{ | ||||
| 	struct type *next;	/* used with ARRAY, PROCEDURE, POINTER, SET,
 | ||||
| 				   SUBRANGE | ||||
| 				*/ | ||||
| 	int tp_fund;		/* fundamental type  or constructor */ | ||||
| 	int tp_align;		/* alignment requirement of this type */ | ||||
| 	arith tp_size;		/* size of this type */ | ||||
| /*	struct idf *tp_idf;	/* name of this type */ | ||||
| 	union { | ||||
| 	    struct enume tp_enum; | ||||
| 	    struct subrange tp_subrange; | ||||
| 	    struct array tp_arr; | ||||
| 	    struct record tp_record; | ||||
| 	    struct proc tp_proc; | ||||
| 	} tp_value; | ||||
| }; | ||||
| 
 | ||||
| /* ALLOCDEF "type" */ | ||||
| 
 | ||||
| extern struct type | ||||
| 	*char_type, | ||||
| 	*int_type, | ||||
| 	*card_type, | ||||
| 	*longint_type, | ||||
| 	*real_type, | ||||
| 	*longreal_type, | ||||
| 	*error_type; | ||||
| 
 | ||||
| extern int | ||||
| 	wrd_align, | ||||
| 	int_align, | ||||
| 	lint_align, | ||||
| 	real_align, | ||||
| 	lreal_align, | ||||
| 	ptr_align, | ||||
| 	record_align; | ||||
| 
 | ||||
| extern arith | ||||
| 	wrd_size, | ||||
| 	int_size, | ||||
| 	lint_size, | ||||
| 	real_size, | ||||
| 	lreal_size, | ||||
| 	ptr_size; | ||||
| 
 | ||||
| extern arith | ||||
| 	align(); | ||||
| 
 | ||||
| struct type | ||||
| 	*create_type(), | ||||
| 	*construct_type(), | ||||
| 	*standard_type(); | ||||
							
								
								
									
										134
									
								
								lang/m2/comp/type.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								lang/m2/comp/type.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,134 @@ | |||
| /*	T Y P E   D E F I N I T I O N   M E C H A N I S M	 */ | ||||
| 
 | ||||
| static char *RcsId = "$Header$"; | ||||
| 
 | ||||
| #include	<assert.h> | ||||
| #include	<alloc.h> | ||||
| #include	<em_arith.h> | ||||
| #include	<em_label.h> | ||||
| #include	"def_sizes.h" | ||||
| #include	"Lpars.h" | ||||
| #include	"def.h" | ||||
| #include	"type.h" | ||||
| #include	"idf.h" | ||||
| 
 | ||||
| /*	To be created dynamically in main() from defaults or from command
 | ||||
| 	line parameters. | ||||
| */ | ||||
| int | ||||
| 	wrd_align = AL_WORD, | ||||
| 	int_align = AL_INT, | ||||
| 	lint_align = AL_LONG, | ||||
| 	real_align = AL_FLOAT, | ||||
| 	lreal_align = AL_DOUBLE, | ||||
| 	ptr_align = AL_POINTER, | ||||
| 	record_align = AL_STRUCT; | ||||
| 
 | ||||
| arith | ||||
| 	wrd_size = SZ_WORD, | ||||
| 	int_size = SZ_INT, | ||||
| 	lint_size = SZ_LONG, | ||||
| 	real_size = SZ_FLOAT, | ||||
| 	lreal_size = SZ_DOUBLE, | ||||
| 	ptr_size = SZ_POINTER; | ||||
| 
 | ||||
| struct type | ||||
| 	*bool_type, | ||||
| 	*char_type, | ||||
| 	*int_type, | ||||
| 	*card_type, | ||||
| 	*longint_type, | ||||
| 	*real_type, | ||||
| 	*longreal_type, | ||||
| 	*error_type; | ||||
| 
 | ||||
| struct paramlist *h_paramlist; | ||||
| 
 | ||||
| struct type *h_type; | ||||
| 
 | ||||
| struct type * | ||||
| create_type(fund) | ||||
| 	register int fund; | ||||
| { | ||||
| 	/*	A brand new struct type is created, and its tp_fund set
 | ||||
| 		to fund. | ||||
| 	*/ | ||||
| 	register struct type *ntp = new_type(); | ||||
| 
 | ||||
| 	clear((char *)ntp, sizeof(struct type)); | ||||
| 	ntp->tp_fund = fund; | ||||
| 	ntp->tp_size = (arith)-1; | ||||
| 
 | ||||
| 	return ntp; | ||||
| } | ||||
| 
 | ||||
| struct type * | ||||
| construct_type(fund, tp, count) | ||||
| 	struct type *tp; | ||||
| 	arith count; | ||||
| { | ||||
| 	/*	fund must be a type constructor.
 | ||||
| 		The pointer to the constructed type is returned. | ||||
| 	*/ | ||||
| 	struct type *dtp = create_type(fund); | ||||
| 
 | ||||
| 	switch (fund)	{ | ||||
| 	case PROCEDURE: | ||||
| 	case POINTER: | ||||
| 		dtp->tp_align = ptr_align; | ||||
| 		dtp->tp_size = ptr_size; | ||||
| 		dtp->next = tp; | ||||
| 		break; | ||||
| 	case SET: | ||||
| 		dtp->tp_align = wrd_align; | ||||
| 		dtp->tp_size = align((count + 7) / 8, wrd_align); | ||||
| 		dtp->next = tp; | ||||
| 		break; | ||||
| 	case ARRAY: | ||||
| 		dtp->tp_align = tp->tp_align; | ||||
| 		if (tp->tp_size < 0) dtp->tp_size = -1; | ||||
| 		else dtp->tp_size = count * tp->tp_size; | ||||
| 		dtp->next = tp; | ||||
| 		break; | ||||
| 	case SUBRANGE: | ||||
| 		dtp->tp_align = tp->tp_align; | ||||
| 		dtp->tp_size = tp->tp_size; | ||||
| 		dtp->next = tp; | ||||
| 		break; | ||||
| 	default: | ||||
| 		assert(0); | ||||
| 	} | ||||
| 	return dtp; | ||||
| } | ||||
| 
 | ||||
| arith | ||||
| align(pos, al) | ||||
| 	arith pos; | ||||
| 	int al; | ||||
| { | ||||
| 	return ((pos + al - 1) / al) * al; | ||||
| } | ||||
| 
 | ||||
| struct type * | ||||
| standard_type(fund, align, size) | ||||
| 	int align; arith size; | ||||
| { | ||||
| 	register struct type *tp = create_type(fund); | ||||
| 
 | ||||
| 	tp->tp_align = align; | ||||
| 	tp->tp_size = size; | ||||
| 
 | ||||
| 	return tp; | ||||
| } | ||||
| 
 | ||||
| init_types() | ||||
| { | ||||
| 	char_type = standard_type(CHAR, 1, (arith) 1); | ||||
| 	bool_type = standard_type(BOOLEAN, 1, (arith) 1); | ||||
| 	int_type = standard_type(INTEGER, int_align, int_size); | ||||
| 	longint_type = standard_type(LONGINT, lint_align, lint_size); | ||||
| 	card_type = standard_type(CARDINAL, int_align, int_size); | ||||
| 	real_type = standard_type(REAL, real_align, real_size); | ||||
| 	longreal_type = standard_type(LONGREAL, lreal_align, lreal_size); | ||||
| 	error_type = standard_type(ERRONEOUS, 1, (arith) 1); | ||||
| } | ||||
		Loading…
	
	Add table
		
		Reference in a new issue