A newer version, safety commit

This commit is contained in:
ceriel 1986-03-26 15:11:02 +00:00
parent 8546fbe868
commit 7f174a46c3
28 changed files with 1034 additions and 222 deletions

View file

@ -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 */
static char *RcsId = "$Header$";
#include "input.h"
#include <alloc.h> #include <alloc.h>
#include <em_arith.h>
#include "input.h"
#include "f_info.h" #include "f_info.h"
#include "Lpars.h" #include "Lpars.h"
#include "class.h" #include "class.h"
#include "param.h"
#include "idf.h" #include "idf.h"
#include "LLlex.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(); long str2long();
struct token dot, aside; struct token dot, aside;
static char *RcsId = "$Header$";
/* Skip Modula-2 like comment (* ... *). /* Skip Modula-2 like comment (* ... *).
Note that comment may be nested. Note that comment may be nested.
*/ */

View file

@ -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$ */ /* $Header$ */
@ -9,8 +9,8 @@ struct token {
struct idf *tk_idf; /* IDENT */ struct idf *tk_idf; /* IDENT */
char *tk_str; /* STRING */ char *tk_str; /* STRING */
struct { /* INTEGER */ struct { /* INTEGER */
int tk_type; /* type */ struct type *tk_type; /* type */
long tk_value; /* value */ arith tk_value; /* value */
} tk_int; } tk_int;
char *tk_real; /* REAL */ char *tk_real; /* REAL */
} tk_data; } tk_data;

View file

@ -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 <alloc.h>
#include "f_info.h" #include <em_arith.h>
#include "idf.h" #include "idf.h"
#include "LLlex.h" #include "LLlex.h"
#include "Lpars.h" #include "Lpars.h"
static char *RcsId = "$Header$";
extern char *symbol2str(); extern char *symbol2str();
extern struct idf *gen_anon_idf();
int err_occurred = 0; int err_occurred = 0;
LLmessage(tk) LLmessage(tk)
@ -21,28 +24,6 @@ LLmessage(tk)
error("%s deleted", symbol2str(dot.tk_symb)); 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) insert_token(tk)
int tk; int tk;
{ {

View file

@ -13,7 +13,8 @@ CFLAGS = -DDEBUG -p $(INCLUDES)
LFLAGS = -p LFLAGS = -p
LOBJ = tokenfile.o program.o declar.o expression.o statement.o LOBJ = tokenfile.o program.o declar.o expression.o statement.o
COBJ = LLlex.o LLmessage.o char.o error.o main.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 OBJ = $(COBJ) $(LOBJ) Lpars.o
GENFILES= tokenfile.c \ GENFILES= tokenfile.c \
program.c declar.c expression.c statement.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 symbol2str.c: tokenname.c make.tokcase
make.tokcase <tokenname.c >symbol2str.c 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 char.c: char.tab tab
./tab -fchar.tab >char.c ./tab -fchar.tab >char.c
@ -61,19 +65,22 @@ depend:
make.allocd < $< > $@ make.allocd < $< > $@
#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO #AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
LLlex.o: LLlex.h Lpars.h class.h f_info.h idf.h param.h LLlex.o: LLlex.h Lpars.h class.h f_info.h idf.h input.h
LLmessage.o: LLlex.h Lpars.h f_info.h idf.h LLmessage.o: LLlex.h Lpars.h idf.h
char.o: class.h char.o: class.h
error.o: LLlex.h f_info.h error.o: LLlex.h f_info.h input.h
main.o: LLlex.h Lpars.h f_info.h idf.h main.o: LLlex.h Lpars.h debug.h f_info.h idf.h input.h main.h
symbol2str.o: Lpars.h symbol2str.o: Lpars.h
tokenname.o: Lpars.h idf.h tokenname.h tokenname.o: Lpars.h idf.h tokenname.h
idf.o: idf.h idf.o: idf.h
input.o: f_info.h input.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 tokenfile.o: Lpars.h
program.o: Lpars.h idf.h idlist.h program.o: LLlex.h Lpars.h idf.h main.h misc.h
declar.o: LLlex.h Lpars.h idf.h idlist.h declar.o: LLlex.h Lpars.h def.h idf.h misc.h scope.h type.h
expression.o: Lpars.h expression.o: Lpars.h
statement.o: Lpars.h statement.o: Lpars.h
Lpars.o: Lpars.h Lpars.o: Lpars.h

View file

@ -1,17 +1,43 @@
{ /* D E C L A R A T I O N S */
#include "idf.h"
#include "idlist.h"
#include "LLlex.h"
{
static char *RcsId = "$Header$"; 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: ProcedureDeclaration
ProcedureHeading ';' block IDENT {
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: ProcedureHeading
PROCEDURE IDENT FormalParameters? {
register struct def *df;
} :
/* Only used for definition modules
*/
PROCEDURE IDENT
{ df = define(dot.TOK_IDF, CurrentScope, D_PROCHEAD); }
FormalParameters?
; ;
block: block:
@ -32,22 +58,34 @@ declaration:
FormalParameters: FormalParameters:
'(' [ FPSection [ ';' FPSection ]* ]? ')' '(' [ FPSection [ ';' FPSection ]* ]? ')'
[ ':' qualident ]? [ ':' qualident
]?
; ;
FPSection FPSection
{ {
struct id_list *FPList; struct id_list *FPList;
int VARflag = 0;
} : } :
VAR? IdentList(&FPList) ':' FormalType [
VAR { VARflag = 1; }
]?
IdentList(&FPList) ':' FormalType
{
FreeIdList(FPList);
}
; ;
FormalType: FormalType:
[ ARRAY OF ]? qualident [ ARRAY OF ]? qualident
; ;
TypeDeclaration: TypeDeclaration
IDENT '=' type {
register struct def *df;
}:
IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE); }
'=' type
; ;
type: type:
@ -169,8 +207,12 @@ FormalTypeList:
[ ':' qualident ]? [ ':' qualident ]?
; ;
ConstantDeclaration: ConstantDeclaration
IDENT '=' ConstExpression {
register struct def *df;
}:
IDENT { df = define(dot.TOK_IDF, CurrentScope, D_CONST); }
'=' ConstExpression
; ;
VariableDeclaration VariableDeclaration

75
lang/m2/comp/def.H Normal file
View 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
View 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
View 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

View file

@ -5,101 +5,97 @@
number of arguments! number of arguments!
*/ */
#include <stdio.h> static char *RcsId = "$Header$";
#include <system.h>
#include <em_arith.h>
#include "input.h" #include "input.h"
#include "f_info.h" #include "f_info.h"
#include "LLlex.h" #include "LLlex.h"
static char *RcsId = "$Header$"; #define MAXERR_LINE 5 /* Number of error messages on one line ... */
#define ERROUT STDERR
#define ERROUT stderr
/* error classes */
#define ERROR 1 #define ERROR 1
#define WARNING 2 #define WARNING 2
#define LEXERROR 3 #define LEXERROR 3
#define LEXWARNING 4 #define LEXWARNING 4
#define CRASH 5 #define CRASH 5
#define FATAL 6 #define FATAL 6
#define NONFATAL 7
#ifdef DEBUG #ifdef DEBUG
#define VDEBUG 8 #define VDEBUG 7
#endif DEBUG #endif
#define NILEXPR ((struct expr *) 0)
int err_occurred; int err_occurred;
/*
extern int ofd; /* compact.c * /
#define compiling (ofd >= 0)
*/
extern char *symbol2str();
extern char options[]; extern char options[];
/* There are two general error message giving functions: /* There are three general error-message functions:
error() : syntactic and semantic error messages lexerror() lexical and pre-processor error messages
lexerror() : lexical and pre-processor error messages error() syntactic and semantic error messages
The difference lies in the fact that the first function deals with expr_error() errors in expressions
tokens already read in by the lexical analyzer so the name of the The difference lies in the place where the file name and line
file it comes from and the linenumber must be retrieved from the number come from.
token instead of looking at the global variables LineNumber and Lexical errors report from the global variables LineNumber and
FileName. 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*/ /*VARARGS1*/
error(fmt, args) error(fmt, args)
char *fmt; char *fmt;
{ {
/* _error(ERROR, NILEXPR, fmt, &args);
if (compiling)
C_ms_err();
*/
++err_occurred;
_error(ERROR, fmt, &args);
} }
#ifdef DEBUG /*VARARGS2*/
debug(fmt, args) expr_error(expr, fmt, args)
struct expr *expr;
char *fmt; char *fmt;
{ {
if (options['D']) _error(ERROR, expr, fmt, &args);
_error(VDEBUG, 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*/ /*VARARGS1*/
lexerror(fmt, args) lexerror(fmt, args)
char *fmt; char *fmt;
{ {
/* _error(LEXERROR, NILEXPR, fmt, &args);
if (compiling)
C_ms_err();
*/
++err_occurred;
_error(LEXERROR, fmt, &args);
} }
/*VARARGS1*/ /*VARARGS1*/
lexwarning(fmt, args) char *fmt; { lexwarning(fmt, args)
if (options['w']) return;
_error(LEXWARNING, fmt, &args);
}
/*VARARGS1*/
crash(fmt, args)
char *fmt; char *fmt;
int args;
{ {
/* _error(LEXWARNING, NILEXPR, fmt, &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) */
} }
/*VARARGS1*/ /*VARARGS1*/
@ -107,64 +103,103 @@ fatal(fmt, args)
char *fmt; char *fmt;
int args; int args;
{ {
/*
if (compiling) _error(FATAL, NILEXPR, fmt, &args);
C_ms_err(); sys_stop(S_EXIT);
*/
_error(FATAL, fmt, &args);
exit(-1);
} }
/*VARARGS1*/ _error(class, expr, fmt, argv)
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)
int class; int class;
struct expr *expr;
char *fmt; char *fmt;
int argv[]; 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) { switch (class) {
case ERROR: case ERROR:
case LEXERROR: case LEXERROR:
fprintf(ERROUT, "%s, line %ld: ", FileName, LineNumber); case CRASH:
case FATAL:
/*
if (C_busy())
C_ms_err();
*/
err_occurred = 1;
break; break;
case WARNING: case WARNING:
case LEXWARNING: case LEXWARNING:
fprintf(ERROUT, "%s, line %ld: (warning) ", if (options['w'])
FileName, LineNumber); return;
break;
}
/* the remark */
switch (class) {
case WARNING:
case LEXWARNING:
remark = "(warning)";
break; break;
case CRASH: case CRASH:
fprintf(ERROUT, "CRASH\007 %s, line %ld: \n", remark = "CRASH\007";
FileName, LineNumber);
break; break;
case FATAL: case FATAL:
fprintf(ERROUT, "%s, line %ld: fatal error -- ", remark = "fatal error --";
FileName, LineNumber);
break; 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"); fprintf(ERROUT, "\n");
} }

View file

@ -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$ */ /* $Header$ */
struct f_info { struct f_info {

View file

@ -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$ */ /* $Header$ */
#include "idf.h" #include "idf.h"

View file

@ -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$ */ /* $Header$ */
#define IDF_TYPE int struct id_u {
#define id_reserved id_user 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> #include <idf_pkg.spec>

View file

@ -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$ */ /* $Header$ */
#include "f_info.h" #include "f_info.h"

View file

@ -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$ */ /* $Header$ */
#define INP_NPUSHBACK 2 #define INP_NPUSHBACK 2

View file

@ -1,18 +1,20 @@
/* mod2 -- compiler , althans: een aanzet daartoe */ /* M A I N P R O G R A M */
static char *RcsId = "$Header$";
#include <stdio.h>
#undef BUFSIZ /* Really neccesary??? */
#include <system.h> #include <system.h>
#include <em_arith.h>
#include "input.h" #include "input.h"
#include "f_info.h" #include "f_info.h"
#include "idf.h" #include "idf.h"
#include "LLlex.h" #include "LLlex.h"
#include "Lpars.h" #include "Lpars.h"
#include "main.h"
static char *RcsId = "$Header$"; #include "debug.h"
char options[128]; char options[128];
char *ProgName; char *ProgName;
int state;
extern int err_occurred; extern int err_occurred;
main(argc, argv) main(argc, argv)
@ -23,9 +25,6 @@ main(argc, argv)
ProgName = *argv++; ProgName = *argv++;
# ifdef DEBUG
setbuf(stdout, (char *) 0);
# endif
while (--argc > 0) { while (--argc > 0) {
if (**argv == '-') if (**argv == '-')
Option(*argv++); Option(*argv++);
@ -34,13 +33,13 @@ main(argc, argv)
} }
Nargv[Nargc] = 0; /* terminate the arg vector */ Nargv[Nargc] = 0; /* terminate the arg vector */
if (Nargc != 2) { if (Nargc != 2) {
fprintf(stderr, "%s: Use one file argument\n", ProgName); fprintf(STDERR, "%s: Use one file argument\n", ProgName);
return 1; return 1;
} }
#ifdef DEBUG #ifdef DEBUG
printf("Mod2 compiler -- Debug version\n"); printf("Mod2 compiler -- Debug version\n");
debug("-D: Debugging on");
#endif DEBUG #endif DEBUG
DO_DEBUG(debug(1,"Debugging level: %d", options['D']));
return !Compile(Nargv[1]); return !Compile(Nargv[1]);
} }
@ -53,13 +52,15 @@ Compile(src)
printf("%s\n", src); printf("%s\n", src);
#endif DEBUG #endif DEBUG
if (! InsertFile(src, (char **) 0)) { 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; return 0;
} }
LineNumber = 1; LineNumber = 1;
FileName = src; FileName = src;
init_idf(); init_idf();
reserve(tkidf); reserve(tkidf);
init_scope();
init_types();
#ifdef DEBUG #ifdef DEBUG
if (options['L']) if (options['L'])
LexScan(); LexScan();
@ -80,7 +81,7 @@ LexScan()
{ {
register int symb; register int symb;
while ((symb = LLlex()) != EOF) { while ((symb = LLlex()) != EOI) {
printf(">>> %s ", symbol2str(symb)); printf(">>> %s ", symbol2str(symb));
switch(symb) { switch(symb) {
@ -107,15 +108,12 @@ LexScan()
} }
TimeScan() { TimeScan() {
while (LLlex() != EOF) /* nothing */; while (LLlex() != -1) /* nothing */;
} }
#endif #endif
Option(str) Option(str)
char *str; char *str;
{ {
#ifdef DEBUG
debug("option %c", str[1]);
#endif DEBUG
options[str[1]]++; /* switch option on */ options[str[1]]++; /* switch option on */
} }

8
lang/m2/comp/main.h Normal file
View 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
View 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
View 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
View 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;
}

View file

@ -1,8 +1,15 @@
/* /* O V E R A L L S T R U C T U R E */
Program: Modula-2 grammar in LL(1) form
Version: Mon Feb 24 14:29:39 MET 1986
*/
{
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 The grammar as given by Wirth is already almost LL(1); the
main problem is that the full form of a qualified designator main problem is that the full form of a qualified designator
@ -17,19 +24,12 @@
field identifiers. field identifiers.
*/ */
{
#include "idf.h"
#include "idlist.h"
static char *RcsId = "$Header$";
}
%lexical LLlex; %lexical LLlex;
%start CompUnit, CompilationUnit; %start CompUnit, CompilationUnit;
ModuleDeclaration: ModuleDeclaration:
MODULE IDENT priority? ';' import* export? block IDENT MODULE IDENT priority? ';' import(1)* export? block IDENT
; ;
priority: priority:
@ -41,14 +41,18 @@ export
struct id_list *ExportList; struct id_list *ExportList;
} : } :
EXPORT QUALIFIED? IdentList(&ExportList) ';' EXPORT QUALIFIED? IdentList(&ExportList) ';'
{
FreeIdList(ExportList);
}
; ;
import import(int local;)
{ {
struct id_list *ImportList; struct id_list *ImportList;
struct idf *id = 0;
} : } :
[ FROM [ FROM
IDENT IDENT { id = dot.TOK_IDF; }
]? ]?
IMPORT IdentList(&ImportList) ';' IMPORT IdentList(&ImportList) ';'
/* /*
@ -57,16 +61,16 @@ import
If the FROM clause is present, the identifier in it is a module If the FROM clause is present, the identifier in it is a module
name, otherwise the names in the import list are module names. name, otherwise the names in the import list are module names.
*/ */
{
FreeIdList(ImportList);
}
; ;
DefinitionModule: DefinitionModule:
DEFINITION DEFINITION { state = DEFINITION; }
{ MODULE IDENT
#ifdef DEBUG ';'
debug("Definition module"); import(0)*
#endif DEBUG
}
MODULE IDENT ';' import*
/* export? /* export?
New Modula-2 does not have export lists in definition modules. New Modula-2 does not have export lists in definition modules.
@ -96,19 +100,17 @@ definition:
; ;
ProgramModule: ProgramModule:
MODULE MODULE { if (state != IMPLEMENTATION) state = PROGRAM; }
{ IDENT priority? ';' import(0)* block IDENT '.'
#ifdef DEBUG
debug("Program module");
#endif DEBUG
}
IDENT priority? ';' import* block IDENT '.'
; ;
Module: Module:
DefinitionModule DefinitionModule
| |
IMPLEMENTATION? ProgramModule [
IMPLEMENTATION { state = IMPLEMENTATION; }
]?
ProgramModule
; ;
CompilationUnit: CompilationUnit:

62
lang/m2/comp/scope.C Normal file
View 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
View 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)

View file

@ -1,3 +1,5 @@
/* S T A T E M E N T S */
{ {
static char *RcsId = "$Header$"; static char *RcsId = "$Header$";
} }

View file

@ -1,3 +1,7 @@
/* T O K E N D E F I N I T I O N S */
static char *RcsId = "$Header$";
#include "tokenname.h" #include "tokenname.h"
#include "Lpars.h" #include "Lpars.h"
#include "idf.h" #include "idf.h"
@ -9,8 +13,6 @@
Also, the "token2str.c" file is produced from this file. Also, the "token2str.c" file is produced from this file.
*/ */
static char *RcsId = "$Header$";
struct tokenname tkspec[] = { /* the names of the special tokens */ struct tokenname tkspec[] = { /* the names of the special tokens */
{IDENT, "identifier"}, {IDENT, "identifier"},
{STRING, "string"}, {STRING, "string"},
@ -73,10 +75,18 @@ struct tokenname tkidf[] = { /* names of the identifier tokens */
}; };
struct tokenname tkinternal[] = { /* internal keywords */ struct tokenname tkinternal[] = { /* internal keywords */
{PROGRAM, ""},
{0, "0"} {0, "0"}
}; };
struct tokenname tkstandard[] = { /* standard identifiers */ struct tokenname tkstandard[] = { /* standard identifiers */
{CHAR, "CHAR"},
{BOOLEAN, "BOOLEAN"},
{LONGINT, "LONGINT"},
{CARDINAL, "CARDINAL"},
{LONGREAL, "LONGREAL"},
{SUBRANGE, ""},
{ERRONEOUS, ""},
{0, ""} {0, ""}
}; };

View file

@ -1,4 +1,7 @@
/* T O K E N N A M E S T R U C T U R E */
/* $Header$ */ /* $Header$ */
struct tokenname { /* Used for defining the name of a struct tokenname { /* Used for defining the name of a
token as identified by its symbol token as identified by its symbol
*/ */

90
lang/m2/comp/type.H Normal file
View 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
View 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);
}