Initial revision
This commit is contained in:
parent
a830d68fae
commit
e30234fce8
445
lang/m2/m2mm/LLlex.c
Normal file
445
lang/m2/m2mm/LLlex.c
Normal file
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <alloc.h>
|
||||
#include "idfsize.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "Lpars.h"
|
||||
#include "class.h"
|
||||
|
||||
struct token dot,
|
||||
aside;
|
||||
int idfsize = IDFSIZE;
|
||||
int ForeignFlag;
|
||||
|
||||
static int eofseen;
|
||||
extern char options[];
|
||||
|
||||
STATIC
|
||||
SkipComment()
|
||||
{
|
||||
/* Skip Modula-2 comments (* ... *).
|
||||
Note that comments may be nested (par. 3.5).
|
||||
*/
|
||||
register int ch;
|
||||
register int CommentLevel = 0;
|
||||
|
||||
LoadChar(ch);
|
||||
if (ch == '$') {
|
||||
LoadChar(ch);
|
||||
switch(ch) {
|
||||
case 'F':
|
||||
/* Foreign; This definition module has an
|
||||
implementation in another language.
|
||||
In this case, check that the object file is present
|
||||
and don't generate a rule for it.
|
||||
*/
|
||||
ForeignFlag = 1;
|
||||
break;
|
||||
default:
|
||||
PushBack();
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
}
|
||||
else if (ch == '(') {
|
||||
LoadChar(ch);
|
||||
if (ch == '*') CommentLevel++;
|
||||
else continue;
|
||||
}
|
||||
else if (ch == '*') {
|
||||
LoadChar(ch);
|
||||
if (ch == ')') {
|
||||
CommentLevel--;
|
||||
if (CommentLevel < 0) break;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
else if (ch == EOI) {
|
||||
lexerror("unterminated comment");
|
||||
break;
|
||||
}
|
||||
LoadChar(ch);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
GetString(upto)
|
||||
{
|
||||
/* Read a Modula-2 string, delimited by the character "upto".
|
||||
*/
|
||||
register int ch;
|
||||
register char *p;
|
||||
|
||||
while (LoadChar(ch), ch != upto) {
|
||||
if (class(ch) == STNL) {
|
||||
lexerror("newline in string");
|
||||
LineNumber++;
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
lexerror("end-of-file in string");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *s_error = "illegal line directive";
|
||||
|
||||
STATIC int
|
||||
getch()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
for (;;) {
|
||||
LoadChar(ch);
|
||||
if ((ch & 0200) && ch != EOI) {
|
||||
error("non-ascii '\\%03o' read", ch & 0377);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
eofseen = 1;
|
||||
return '\n';
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
CheckForLineDirective()
|
||||
{
|
||||
register int ch = getch();
|
||||
register int i = 0;
|
||||
char buf[IDFSIZE + 2];
|
||||
register char *c = buf;
|
||||
|
||||
|
||||
if (ch != '#') {
|
||||
PushBack();
|
||||
return;
|
||||
}
|
||||
do { /*
|
||||
* Skip to next digit
|
||||
* Do not skip newlines
|
||||
*/
|
||||
ch = getch();
|
||||
if (class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
} while (class(ch) != STNUM);
|
||||
while (class(ch) == STNUM) {
|
||||
i = i*10 + (ch - '0');
|
||||
ch = getch();
|
||||
}
|
||||
while (ch != '"' && class(ch) != STNL) ch = getch();
|
||||
if (ch == '"') {
|
||||
c = buf;
|
||||
do {
|
||||
*c++ = ch = getch();
|
||||
if (class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
} while (ch != '"');
|
||||
*--c = '\0';
|
||||
do {
|
||||
ch = getch();
|
||||
} while (class(ch) != STNL);
|
||||
/*
|
||||
* Remember the file name
|
||||
*/
|
||||
if (!eofseen && strcmp(FileName,buf)) {
|
||||
FileName = Salloc(buf,(unsigned) strlen(buf) + 1);
|
||||
}
|
||||
}
|
||||
if (eofseen) {
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
LineNumber = i;
|
||||
}
|
||||
|
||||
char idfbuf[IDFSIZE + 2];
|
||||
|
||||
int
|
||||
LLlex()
|
||||
{
|
||||
/* LLlex() is the Lexical Analyzer.
|
||||
The putting aside of tokens is taken into account.
|
||||
*/
|
||||
register struct token *tk = ˙
|
||||
register int ch, nch;
|
||||
|
||||
if (ASIDE) { /* a token is put aside */
|
||||
*tk = aside;
|
||||
ASIDE = 0;
|
||||
return tk->tk_symb;
|
||||
}
|
||||
|
||||
again1:
|
||||
if (eofseen) {
|
||||
eofseen = 0;
|
||||
ch = EOI;
|
||||
}
|
||||
else {
|
||||
again:
|
||||
LoadChar(ch);
|
||||
if ((ch & 0200) && ch != EOI) {
|
||||
error("non-ascii '\\%03o' read", ch & 0377);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
tk->tk_lineno = LineNumber;
|
||||
|
||||
switch (class(ch)) {
|
||||
|
||||
case STNL:
|
||||
LineNumber++;
|
||||
CheckForLineDirective();
|
||||
goto again1;
|
||||
|
||||
case STSKIP:
|
||||
goto again;
|
||||
|
||||
case STGARB:
|
||||
if ((unsigned) ch - 040 < 0137) {
|
||||
lexerror("garbage char %c", ch);
|
||||
}
|
||||
else lexerror("garbage char \\%03o", ch);
|
||||
goto again;
|
||||
|
||||
case STSIMP:
|
||||
if (ch == '(') {
|
||||
LoadChar(nch);
|
||||
if (nch == '*') {
|
||||
SkipComment();
|
||||
goto again;
|
||||
}
|
||||
else if (nch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
}
|
||||
if (ch == '&') return tk->tk_symb = AND;
|
||||
if (ch == '~') return tk->tk_symb = NOT;
|
||||
return tk->tk_symb = ch;
|
||||
|
||||
case STCOMP:
|
||||
LoadChar(nch);
|
||||
switch (ch) {
|
||||
|
||||
case '.':
|
||||
if (nch == '.') {
|
||||
return tk->tk_symb = UPTO;
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = BECOMES;
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = LESSEQUAL;
|
||||
}
|
||||
if (nch == '>') {
|
||||
return tk->tk_symb = '#';
|
||||
}
|
||||
break;
|
||||
|
||||
case '>':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = GREATEREQUAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
crash("(LLlex, STCOMP)");
|
||||
}
|
||||
if (nch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
return tk->tk_symb = ch;
|
||||
|
||||
case STIDF:
|
||||
{
|
||||
register char *tag = &idfbuf[0];
|
||||
register struct idf *id;
|
||||
|
||||
do {
|
||||
if (tag - idfbuf < idfsize) *tag++ = ch;
|
||||
LoadChar(ch);
|
||||
} while(in_idf(ch));
|
||||
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
*tag++ = '\0';
|
||||
|
||||
tk->TOK_IDF = id = findidf(idfbuf);
|
||||
return tk->tk_symb = id && id->id_reserved ? id->id_reserved : IDENT;
|
||||
}
|
||||
|
||||
case STSTR:
|
||||
GetString(ch);
|
||||
return tk->tk_symb = STRING;
|
||||
|
||||
case STNUM:
|
||||
{
|
||||
/* The problem arising with the "parsing" of a number
|
||||
is that we don't know the base in advance so we
|
||||
have to read the number with the help of a rather
|
||||
complex finite automaton.
|
||||
*/
|
||||
enum statetp {Oct,OptHex,Hex,Dec,OctEndOrHex,End,OptReal,Real};
|
||||
register enum statetp state;
|
||||
state = is_oct(ch) ? Oct : Dec;
|
||||
LoadChar(ch);
|
||||
for (;;) {
|
||||
switch(state) {
|
||||
case Oct:
|
||||
while (is_oct(ch)) {
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (ch == 'B' || ch == 'C') {
|
||||
state = OctEndOrHex;
|
||||
break;
|
||||
}
|
||||
/* Fall Through */
|
||||
case Dec:
|
||||
while (is_dig(ch)) {
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (ch == 'D') state = OptHex;
|
||||
else if (is_hex(ch)) state = Hex;
|
||||
else if (ch == '.') state = OptReal;
|
||||
else {
|
||||
state = End;
|
||||
if (ch == 'H') ;
|
||||
else if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
}
|
||||
break;
|
||||
|
||||
case OptHex:
|
||||
LoadChar(ch);
|
||||
if (is_hex(ch)) {
|
||||
state = Hex;
|
||||
}
|
||||
else state = End;
|
||||
break;
|
||||
|
||||
case Hex:
|
||||
while (is_hex(ch)) {
|
||||
LoadChar(ch);
|
||||
}
|
||||
state = End;
|
||||
if (ch != 'H') {
|
||||
lexerror("H expected after hex number");
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
}
|
||||
break;
|
||||
|
||||
case OctEndOrHex:
|
||||
LoadChar(ch);
|
||||
if (ch == 'H') {
|
||||
state = End;
|
||||
break;
|
||||
}
|
||||
if (is_hex(ch)) {
|
||||
state = Hex;
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
/* Fall through */
|
||||
|
||||
case End:
|
||||
return tk->tk_symb = INTEGER;
|
||||
|
||||
case OptReal:
|
||||
/* The '.' could be the first of the '..'
|
||||
token. At this point, we need a
|
||||
look-ahead of two characters.
|
||||
*/
|
||||
LoadChar(ch);
|
||||
if (ch == '.') {
|
||||
/* Indeed the '..' token
|
||||
*/
|
||||
PushBack();
|
||||
PushBack();
|
||||
state = End;
|
||||
break;
|
||||
}
|
||||
state = Real;
|
||||
break;
|
||||
}
|
||||
if (state == Real) break;
|
||||
}
|
||||
|
||||
while (is_dig(ch)) {
|
||||
/* Fractional part
|
||||
*/
|
||||
LoadChar(ch);
|
||||
}
|
||||
|
||||
if (ch == 'E' || ch == 'D') {
|
||||
/* Scale factor
|
||||
*/
|
||||
if (ch == 'D') {
|
||||
LoadChar(ch);
|
||||
if (!(ch == '+' || ch == '-' || is_dig(ch)))
|
||||
goto noscale;
|
||||
}
|
||||
LoadChar(ch);
|
||||
if (ch == '+' || ch == '-') {
|
||||
/* Signed scalefactor
|
||||
*/
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (is_dig(ch)) {
|
||||
do {
|
||||
LoadChar(ch);
|
||||
} while (is_dig(ch));
|
||||
}
|
||||
else {
|
||||
lexerror("bad scale factor");
|
||||
}
|
||||
}
|
||||
|
||||
noscale:
|
||||
if (ch == EOI) eofseen = 1;
|
||||
else PushBack();
|
||||
|
||||
return tk->tk_symb = REAL;
|
||||
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
case STEOI:
|
||||
return tk->tk_symb = -1;
|
||||
|
||||
case STCHAR:
|
||||
default:
|
||||
crash("(LLlex) Impossible character class");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
28
lang/m2/m2mm/LLlex.h
Normal file
28
lang/m2/m2mm/LLlex.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* stripped down version of the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/* Token structure. Keep it small, as it is part of a parse-tree node
|
||||
*/
|
||||
struct token {
|
||||
short tk_symb; /* token itself */
|
||||
unsigned short tk_lineno; /* linenumber on which it occurred */
|
||||
struct idf *tk_idf; /* IDENT */
|
||||
};
|
||||
|
||||
#define TOK_IDF tk_idf
|
||||
|
||||
extern struct token dot, aside;
|
||||
extern int ForeignFlag;
|
||||
|
||||
#define DOT dot.tk_symb
|
||||
#define ASIDE aside.tk_symb
|
52
lang/m2/m2mm/LLmessage.c
Normal file
52
lang/m2/m2mm/LLmessage.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S Y N T A X E R R O R R E P O R T I N G */
|
||||
|
||||
/* stripped down version from the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/* Defines the LLmessage routine. LLgen-generated parsers require the
|
||||
existence of a routine of that name.
|
||||
The routine must do syntax-error reporting and must be able to
|
||||
insert tokens in the token stream.
|
||||
*/
|
||||
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
extern char *symbol2str();
|
||||
extern struct idf *gen_anon_idf();
|
||||
|
||||
LLmessage(tk)
|
||||
register int tk;
|
||||
{
|
||||
if (tk > 0) {
|
||||
/* if (tk > 0), it represents the token to be inserted.
|
||||
*/
|
||||
register struct token *dotp = ˙
|
||||
|
||||
error("%s missing", symbol2str(tk));
|
||||
|
||||
aside = *dotp;
|
||||
|
||||
dotp->tk_symb = tk;
|
||||
|
||||
switch (tk) {
|
||||
/* The operands need some body */
|
||||
case IDENT:
|
||||
dotp->TOK_IDF = gen_anon_idf();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (tk < 0) {
|
||||
error("garbage at end of program");
|
||||
}
|
||||
else error("%s deleted", symbol2str(dot.tk_symb));
|
||||
}
|
147
lang/m2/m2mm/Makefile
Normal file
147
lang/m2/m2mm/Makefile
Normal file
|
@ -0,0 +1,147 @@
|
|||
#
|
||||
EMHOME = ../../..
|
||||
MHDIR = $(EMHOME)/modules/h
|
||||
PKGDIR = $(EMHOME)/modules/pkg
|
||||
LIBDIR = $(EMHOME)/modules/lib
|
||||
LLGEN = $(EMHOME)/bin/LLgen
|
||||
MKDEP = $(EMHOME)/bin/mkdep
|
||||
|
||||
INCLUDES = -I$(MHDIR) -I$(PKGDIR) -I$(EMHOME)/h
|
||||
|
||||
GF = program.g declar.g expression.g statement.g
|
||||
GENGFILES= tokenfile.g
|
||||
GFILES =$(GENGFILES) $(GF)
|
||||
LLGENOPTIONS = -v
|
||||
PROFILE =
|
||||
CFLAGS = $(PROFILE) $(INCLUDES) -DSTATIC=
|
||||
LINTFLAGS = -DSTATIC= -DNORCSID
|
||||
MALLOC = $(LIBDIR)/malloc.o
|
||||
LDFLAGS = -i $(PROFILE)
|
||||
LSRC = tokenfile.c program.c declar.c expression.c statement.c
|
||||
LOBJ = tokenfile.o program.o declar.o expression.o statement.o
|
||||
CSRC = LLlex.c LLmessage.c error.c main.c lib.c \
|
||||
tokenname.c idf.c input.c misc.c options.c
|
||||
COBJ = LLlex.o LLmessage.o error.o main.o lib.o \
|
||||
tokenname.o idf.o input.o misc.o options.o char.o symbol2str.o
|
||||
GENC= $(LSRC) symbol2str.c char.c Lpars.c
|
||||
SRC = $(CSRC) $(GENC)
|
||||
OBJ = $(COBJ) $(LOBJ) Lpars.o
|
||||
GENH = Lpars.h
|
||||
HSRC = main.h LLlex.h class.h f_info.h idf.h input.h tokenname.h
|
||||
HFILES =$(GENH) $(HSRC)
|
||||
#
|
||||
GENFILES = $(GENGFILES) $(GENC) $(GENH)
|
||||
|
||||
all: Cfiles
|
||||
make "EMHOME="$(EMHOME) m2mm
|
||||
|
||||
install: all
|
||||
cp m2mm $(EMHOME)/bin
|
||||
|
||||
cmp: all
|
||||
cmp m2mm $(EMHOME)/bin/m2mm
|
||||
|
||||
opr:
|
||||
make "EMHOME="$(EMHOME) pr | opr
|
||||
|
||||
pr:
|
||||
@pr Makefile $(GF) $(HFILES) $(CSRC)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(GENFILES) LLfiles Cfiles tab LL.output
|
||||
|
||||
lint: Cfiles
|
||||
lint $(INCLUDES) $(LINTFLAGS) $(SRC) \
|
||||
$(LIBDIR)/llib-linput.ln \
|
||||
$(LIBDIR)/llib-lalloc.ln \
|
||||
$(LIBDIR)/llib-lprint.ln \
|
||||
$(LIBDIR)/llib-lstring.ln \
|
||||
$(LIBDIR)/llib-lsystem.ln
|
||||
|
||||
# entry points not to be used directly
|
||||
Cfiles: LLfiles $(GENC) $(GENH) Makefile
|
||||
|
||||
LLfiles: $(GFILES)
|
||||
$(LLGEN) $(LLGENOPTIONS) $(GFILES)
|
||||
@touch LLfiles
|
||||
|
||||
tokenfile.g: tokenname.c make.tokfile
|
||||
make.tokfile <tokenname.c >tokenfile.g
|
||||
|
||||
symbol2str.c: tokenname.c make.tokcase
|
||||
make.tokcase <tokenname.c >symbol2str.c
|
||||
|
||||
char.c: char.tab tab
|
||||
tab -fchar.tab >char.c
|
||||
|
||||
tab:
|
||||
$(CC) tab.c -o tab
|
||||
|
||||
depend: Cfiles
|
||||
sed '/^#AUTOAUTO/,$$d' Makefile > Makefile.new
|
||||
echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >> Makefile.new
|
||||
$(MKDEP) $(SRC) |\
|
||||
sed 's/\.c:/\.o:/' >> Makefile.new
|
||||
mv Makefile Makefile.old
|
||||
mv Makefile.new Makefile
|
||||
|
||||
m2mm: $(OBJ)
|
||||
$(CC) $(LDFLAGS) $(OBJ) $(LIBDIR)/libinput.a $(LIBDIR)/liballoc.a $(MALLOC) $(LIBDIR)/libprint.a $(LIBDIR)/libstring.a $(LIBDIR)/libsystem.a -o m2mm
|
||||
size m2mm
|
||||
|
||||
#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
|
||||
LLlex.o: LLlex.h
|
||||
LLlex.o: Lpars.h
|
||||
LLlex.o: class.h
|
||||
LLlex.o: f_info.h
|
||||
LLlex.o: file_list.h
|
||||
LLlex.o: idf.h
|
||||
LLlex.o: idfsize.h
|
||||
LLlex.o: input.h
|
||||
LLlex.o: inputtype.h
|
||||
LLmessage.o: LLlex.h
|
||||
LLmessage.o: Lpars.h
|
||||
LLmessage.o: file_list.h
|
||||
LLmessage.o: idf.h
|
||||
error.o: LLlex.h
|
||||
error.o: f_info.h
|
||||
error.o: input.h
|
||||
error.o: inputtype.h
|
||||
main.o: LLlex.h
|
||||
main.o: Lpars.h
|
||||
main.o: f_info.h
|
||||
main.o: file_list.h
|
||||
main.o: idf.h
|
||||
main.o: input.h
|
||||
main.o: inputtype.h
|
||||
main.o: tokenname.h
|
||||
tokenname.o: Lpars.h
|
||||
tokenname.o: file_list.h
|
||||
tokenname.o: idf.h
|
||||
tokenname.o: tokenname.h
|
||||
idf.o: file_list.h
|
||||
idf.o: idf.h
|
||||
input.o: f_info.h
|
||||
input.o: input.h
|
||||
input.o: inputtype.h
|
||||
misc.o: LLlex.h
|
||||
misc.o: f_info.h
|
||||
misc.o: file_list.h
|
||||
misc.o: idf.h
|
||||
options.o: main.h
|
||||
tokenfile.o: Lpars.h
|
||||
program.o: LLlex.h
|
||||
program.o: Lpars.h
|
||||
program.o: f_info.h
|
||||
program.o: file_list.h
|
||||
program.o: idf.h
|
||||
program.o: main.h
|
||||
declar.o: Lpars.h
|
||||
expression.o: Lpars.h
|
||||
statement.o: LLlex.h
|
||||
statement.o: Lpars.h
|
||||
statement.o: file_list.h
|
||||
statement.o: idf.h
|
||||
symbol2str.o: Lpars.h
|
||||
char.o: class.h
|
||||
Lpars.o: Lpars.h
|
54
lang/m2/m2mm/char.tab
Normal file
54
lang/m2/m2mm/char.tab
Normal file
|
@ -0,0 +1,54 @@
|
|||
% character tables for mod2 compiler
|
||||
% $Header$
|
||||
%S129
|
||||
%F %s,
|
||||
%
|
||||
% CHARACTER CLASSES
|
||||
%
|
||||
%C
|
||||
STGARB:\000-\200
|
||||
STSKIP: \r\t
|
||||
STNL:\012\013\014
|
||||
STSIMP:#&()*+,-/;=[]^{|}~
|
||||
STCOMP:.:<>
|
||||
STIDF:a-zA-Z
|
||||
STSTR:"'
|
||||
STNUM:0-9
|
||||
STEOI:\200
|
||||
%T#include "class.h"
|
||||
%Tchar tkclass[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% INIDF
|
||||
%
|
||||
%C
|
||||
1:a-zA-Z0-9
|
||||
%Tchar inidf[] = {
|
||||
%F %s,
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISDIG
|
||||
%
|
||||
%C
|
||||
1:0-9
|
||||
%Tchar isdig[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISHEX
|
||||
%
|
||||
%C
|
||||
1:a-fA-F
|
||||
%Tchar ishex[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISOCT
|
||||
%
|
||||
%C
|
||||
1:0-7
|
||||
%Tchar isoct[] = {
|
||||
%p
|
||||
%T};
|
45
lang/m2/m2mm/class.h
Normal file
45
lang/m2/m2mm/class.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* U S E O F C H A R A C T E R C L A S S E S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/* As a starter, chars are divided into classes, according to which
|
||||
token they can be the start of.
|
||||
At present such a class number is supposed to fit in 4 bits.
|
||||
*/
|
||||
|
||||
#define class(ch) (tkclass[ch])
|
||||
|
||||
/* Being the start of a token is, fortunately, a mutual exclusive
|
||||
property, so, as there are less than 16 classes they can be
|
||||
packed in 4 bits.
|
||||
*/
|
||||
|
||||
#define STSKIP 0 /* spaces and so on: skipped characters */
|
||||
#define STNL 1 /* newline character(s): update linenumber etc. */
|
||||
#define STGARB 2 /* garbage ascii character: not allowed */
|
||||
#define STSIMP 3 /* this character can occur as token */
|
||||
#define STCOMP 4 /* this one can start a compound token */
|
||||
#define STIDF 5 /* being the initial character of an identifier */
|
||||
#define STCHAR 6 /* the starter of a character constant */
|
||||
#define STSTR 7 /* the starter of a string */
|
||||
#define STNUM 8 /* the starter of a numeric constant */
|
||||
#define STEOI 9 /* End-Of-Information mark */
|
||||
|
||||
/* But occurring inside a token is not, so we need 1 bit for each
|
||||
class. This is implemented as a collection of tables to speed up
|
||||
the decision whether a character has a special meaning.
|
||||
*/
|
||||
#define in_idf(ch) ((unsigned)ch < 0177 && inidf[ch])
|
||||
#define is_oct(ch) ((unsigned)ch < 0177 && isoct[ch])
|
||||
#define is_dig(ch) ((unsigned)ch < 0177 && isdig[ch])
|
||||
#define is_hex(ch) ((unsigned)ch < 0177 && ishex[ch])
|
||||
|
||||
extern char tkclass[];
|
||||
extern char inidf[], isoct[], isdig[], ishex[];
|
266
lang/m2/m2mm/declar.g
Normal file
266
lang/m2/m2mm/declar.g
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E C L A R A T I O N S */
|
||||
|
||||
/* stripped down version of the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
ProcedureHeading :
|
||||
PROCEDURE IDENT
|
||||
[
|
||||
'('
|
||||
[
|
||||
FPSection
|
||||
[
|
||||
';' FPSection
|
||||
]*
|
||||
]?
|
||||
')'
|
||||
[ ':' qualtype
|
||||
]?
|
||||
]?
|
||||
;
|
||||
|
||||
block :
|
||||
[ %persistent
|
||||
declaration
|
||||
]*
|
||||
[ %default
|
||||
BEGIN
|
||||
StatementSequence
|
||||
|
|
||||
]
|
||||
END
|
||||
;
|
||||
|
||||
declaration :
|
||||
CONST [ ConstantDeclaration ';' ]*
|
||||
|
|
||||
TYPE [ TypeDeclaration ';' ]*
|
||||
|
|
||||
VAR [ VariableDeclaration ';' ]*
|
||||
|
|
||||
ProcedureHeading ';'
|
||||
block
|
||||
IDENT
|
||||
';'
|
||||
|
|
||||
ModuleDeclaration ';'
|
||||
;
|
||||
|
||||
FPSection :
|
||||
var IdentList ':' FormalType
|
||||
;
|
||||
|
||||
FormalType :
|
||||
ARRAY OF qualtype
|
||||
|
|
||||
qualtype
|
||||
;
|
||||
|
||||
TypeDeclaration :
|
||||
IDENT
|
||||
'=' type
|
||||
;
|
||||
|
||||
type :
|
||||
%default SimpleType
|
||||
|
|
||||
ArrayType
|
||||
|
|
||||
RecordType
|
||||
|
|
||||
SetType
|
||||
|
|
||||
PointerType
|
||||
|
|
||||
ProcedureType
|
||||
;
|
||||
|
||||
SimpleType :
|
||||
qualtype
|
||||
[
|
||||
/* nothing */
|
||||
|
|
||||
SubrangeType
|
||||
/* The subrange type is given a base type by the
|
||||
qualident (this is new modula-2).
|
||||
*/
|
||||
]
|
||||
|
|
||||
enumeration
|
||||
|
|
||||
SubrangeType
|
||||
;
|
||||
|
||||
enumeration :
|
||||
'(' IdentList ')'
|
||||
;
|
||||
|
||||
IdentList :
|
||||
IDENT
|
||||
[ %persistent
|
||||
',' IDENT
|
||||
]*
|
||||
;
|
||||
|
||||
SubrangeType :
|
||||
/*
|
||||
This is not exactly the rule in the new report, but see
|
||||
the rule for "SimpleType".
|
||||
*/
|
||||
'[' ConstExpression
|
||||
UPTO ConstExpression
|
||||
']'
|
||||
;
|
||||
|
||||
ArrayType :
|
||||
ARRAY SimpleType
|
||||
[
|
||||
',' SimpleType
|
||||
]* OF type
|
||||
;
|
||||
|
||||
RecordType :
|
||||
RECORD
|
||||
FieldListSequence
|
||||
END
|
||||
;
|
||||
|
||||
FieldListSequence :
|
||||
FieldList
|
||||
[
|
||||
';' FieldList
|
||||
]*
|
||||
;
|
||||
|
||||
FieldList :
|
||||
[
|
||||
IdentList ':' type
|
||||
|
|
||||
CASE
|
||||
/* Also accept old fashioned Modula-2 syntax, but give a warning.
|
||||
Sorry for the complicated code.
|
||||
*/
|
||||
[ qualident
|
||||
[ ':' qualtype
|
||||
/* This is correct, in both kinds of Modula-2, if
|
||||
the first qualident is a single identifier.
|
||||
*/
|
||||
| /* Old fashioned! the first qualident now represents
|
||||
the type
|
||||
*/
|
||||
]
|
||||
| ':' qualtype
|
||||
/* Aha, third edition. Well done! */
|
||||
]
|
||||
OF variant
|
||||
[
|
||||
'|' variant
|
||||
]*
|
||||
[ ELSE FieldListSequence
|
||||
]?
|
||||
END
|
||||
]?
|
||||
;
|
||||
|
||||
variant :
|
||||
[
|
||||
CaseLabelList
|
||||
':' FieldListSequence
|
||||
]?
|
||||
/* Changed rule in new modula-2 */
|
||||
;
|
||||
|
||||
CaseLabelList :
|
||||
CaseLabels
|
||||
[
|
||||
',' CaseLabels
|
||||
]*
|
||||
;
|
||||
|
||||
CaseLabels :
|
||||
ConstExpression
|
||||
[
|
||||
UPTO
|
||||
ConstExpression
|
||||
]?
|
||||
;
|
||||
|
||||
SetType :
|
||||
SET OF SimpleType
|
||||
;
|
||||
|
||||
/* In a pointer type definition, the type pointed at does not
|
||||
have to be declared yet, so be careful about identifying
|
||||
type-identifiers
|
||||
*/
|
||||
PointerType :
|
||||
POINTER TO type
|
||||
;
|
||||
|
||||
qualtype :
|
||||
qualident
|
||||
;
|
||||
|
||||
ProcedureType :
|
||||
PROCEDURE
|
||||
[
|
||||
FormalTypeList
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
FormalTypeList :
|
||||
'('
|
||||
[
|
||||
VarFormalType
|
||||
[
|
||||
',' VarFormalType
|
||||
]*
|
||||
]?
|
||||
')'
|
||||
[ ':' qualtype
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
VarFormalType :
|
||||
var
|
||||
FormalType
|
||||
;
|
||||
|
||||
var :
|
||||
[
|
||||
VAR
|
||||
|
|
||||
/* empty */
|
||||
]
|
||||
;
|
||||
|
||||
ConstantDeclaration :
|
||||
IDENT
|
||||
'=' ConstExpression
|
||||
;
|
||||
|
||||
VariableDeclaration :
|
||||
IdentAddr
|
||||
[ %persistent
|
||||
',' IdentAddr
|
||||
]*
|
||||
':' type
|
||||
;
|
||||
|
||||
IdentAddr :
|
||||
IDENT
|
||||
[ '['
|
||||
ConstExpression
|
||||
']'
|
||||
]?
|
||||
;
|
146
lang/m2/m2mm/error.c
Normal file
146
lang/m2/m2mm/error.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* stripped down version from the one in the Modula-2 compiler */
|
||||
/* $Header$ */
|
||||
|
||||
/* 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 <system.h>
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "LLlex.h"
|
||||
|
||||
/* error classes */
|
||||
#define ERROR 1
|
||||
#define LEXERROR 3
|
||||
#define CRASH 5
|
||||
#define FATAL 6
|
||||
|
||||
int err_occurred;
|
||||
|
||||
extern char *symbol2str();
|
||||
|
||||
/* There are three general error-message functions:
|
||||
lexerror() lexical and pre-processor error messages
|
||||
error() syntactic and semantic error messages
|
||||
node_error() errors in nodes
|
||||
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, node errors get their information from the
|
||||
node, whereas other errors use the information in the token.
|
||||
*/
|
||||
|
||||
/*VARARGS1*/
|
||||
error(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(ERROR, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
Gerror(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
char *fn = FileName;
|
||||
|
||||
FileName = 0;
|
||||
_error(ERROR, fmt, &args);
|
||||
FileName = fn;
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
lexerror(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(LEXERROR, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
fatal(fmt, args)
|
||||
char *fmt;
|
||||
int args;
|
||||
{
|
||||
|
||||
_error(FATAL, fmt, &args);
|
||||
sys_stop(S_EXIT);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
crash(fmt, args)
|
||||
char *fmt;
|
||||
int args;
|
||||
{
|
||||
|
||||
_error(CRASH, fmt, &args);
|
||||
#ifdef DEBUG
|
||||
sys_stop(S_ABORT);
|
||||
#else
|
||||
sys_stop(S_EXIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
_error(class, fmt, argv)
|
||||
int class;
|
||||
char *fmt;
|
||||
int argv[];
|
||||
{
|
||||
/* _error attempts to limit the number of error messages
|
||||
for a given line to MAXERR_LINE.
|
||||
*/
|
||||
unsigned int ln = 0;
|
||||
register 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:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
err_occurred = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* the remark */
|
||||
switch (class) {
|
||||
case CRASH:
|
||||
remark = "CRASH\007";
|
||||
break;
|
||||
case FATAL:
|
||||
remark = "fatal error --";
|
||||
break;
|
||||
}
|
||||
|
||||
/* the place */
|
||||
switch (class) {
|
||||
case ERROR:
|
||||
ln = dot.tk_lineno;
|
||||
break;
|
||||
case LEXERROR:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
ln = LineNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FileName) fprint(STDERR, "\"%s\", line %u: ", FileName, ln);
|
||||
|
||||
if (remark) fprint(STDERR, "%s ", remark);
|
||||
|
||||
doprnt(STDERR, fmt, argv); /* contents of error */
|
||||
fprint(STDERR, "\n");
|
||||
}
|
146
lang/m2/m2mm/expression.g
Normal file
146
lang/m2/m2mm/expression.g
Normal file
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* E X P R E S S I O N S */
|
||||
|
||||
/* stripped down version of the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
qualident :
|
||||
IDENT
|
||||
[
|
||||
selector
|
||||
]*
|
||||
;
|
||||
|
||||
selector :
|
||||
'.' IDENT
|
||||
;
|
||||
|
||||
ExpList :
|
||||
expression
|
||||
[
|
||||
','
|
||||
expression
|
||||
]*
|
||||
;
|
||||
|
||||
ConstExpression :
|
||||
expression
|
||||
/*
|
||||
* Changed rule in new Modula-2.
|
||||
*/
|
||||
;
|
||||
|
||||
expression :
|
||||
SimpleExpression
|
||||
[
|
||||
/* relation */
|
||||
[ '=' | '#' | '<' | LESSEQUAL | '>' | GREATEREQUAL | IN ]
|
||||
SimpleExpression
|
||||
]?
|
||||
;
|
||||
|
||||
SimpleExpression :
|
||||
[
|
||||
[ '+' | '-' ]
|
||||
]?
|
||||
term
|
||||
[
|
||||
/* AddOperator */
|
||||
[ '+' | '-' | OR ]
|
||||
term
|
||||
]*
|
||||
;
|
||||
|
||||
term :
|
||||
factor
|
||||
[
|
||||
/* MulOperator */
|
||||
[ '*' | '/' | DIV | MOD | AND ]
|
||||
factor
|
||||
]*
|
||||
;
|
||||
|
||||
factor :
|
||||
qualident
|
||||
[
|
||||
designator_tail?
|
||||
[
|
||||
ActualParameters
|
||||
]?
|
||||
|
|
||||
bare_set
|
||||
]
|
||||
|
|
||||
bare_set
|
||||
| %default
|
||||
[
|
||||
%default
|
||||
INTEGER
|
||||
|
|
||||
REAL
|
||||
|
|
||||
STRING
|
||||
]
|
||||
|
|
||||
'(' expression ')'
|
||||
|
|
||||
NOT factor
|
||||
;
|
||||
|
||||
bare_set :
|
||||
'{'
|
||||
[
|
||||
element
|
||||
[
|
||||
',' element
|
||||
]*
|
||||
]?
|
||||
'}'
|
||||
;
|
||||
|
||||
ActualParameters :
|
||||
'(' ExpList? ')'
|
||||
;
|
||||
|
||||
element :
|
||||
expression
|
||||
[
|
||||
UPTO
|
||||
expression
|
||||
]?
|
||||
;
|
||||
|
||||
designator :
|
||||
qualident
|
||||
designator_tail?
|
||||
;
|
||||
|
||||
designator_tail :
|
||||
visible_designator_tail
|
||||
[ %persistent
|
||||
%default
|
||||
selector
|
||||
|
|
||||
visible_designator_tail
|
||||
]*
|
||||
;
|
||||
|
||||
visible_designator_tail :
|
||||
[
|
||||
'['
|
||||
expression
|
||||
[
|
||||
',' expression
|
||||
]*
|
||||
']'
|
||||
|
|
||||
'^'
|
||||
]
|
||||
;
|
21
lang/m2/m2mm/f_info.h
Normal file
21
lang/m2/m2mm/f_info.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 {
|
||||
unsigned short f_lineno;
|
||||
char *f_filename;
|
||||
char *f_workingdir;
|
||||
};
|
||||
|
||||
extern struct f_info file_info;
|
||||
#define LineNumber file_info.f_lineno
|
||||
#define FileName file_info.f_filename
|
||||
#define WorkingDir file_info.f_workingdir
|
6
lang/m2/m2mm/file_list.h
Normal file
6
lang/m2/m2mm/file_list.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
struct file_list {
|
||||
char *a_filename;
|
||||
char *a_dir;
|
||||
struct idf *a_idf;
|
||||
struct file_list *a_next;
|
||||
};
|
13
lang/m2/m2mm/idf.c
Normal file
13
lang/m2/m2mm/idf.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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"
|
||||
#include <idf_pkg.body>
|
40
lang/m2/m2mm/idf.h
Normal file
40
lang/m2/m2mm/idf.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* U S E R D E C L A R E D P A R T O F I D F */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "file_list.h"
|
||||
|
||||
struct lnk {
|
||||
struct lnk *lnk_next;
|
||||
struct idf *lnk_imp;
|
||||
};
|
||||
|
||||
struct id_u {
|
||||
int id_res;
|
||||
int id_tp; /* PROGRAM OR IMPLEMENTATION OR DEFINITION */
|
||||
struct lnk *id_defimp; /* imported by definition module */
|
||||
struct lnk *id_modimp; /* imported by implementation module */
|
||||
char *id_d; /* directory */
|
||||
struct file_list *id_mdep; /* module depends on: */
|
||||
struct file_list *id_ddep; /* definition module depends on: */
|
||||
char *id_df; /* name of definition module */
|
||||
};
|
||||
|
||||
#define IDF_TYPE struct id_u
|
||||
#define id_reserved id_user.id_res
|
||||
#define id_type id_user.id_tp
|
||||
#define id_defimports id_user.id_defimp
|
||||
#define id_modimports id_user.id_modimp
|
||||
#define id_dir id_user.id_d
|
||||
#define id_mdependson id_user.id_mdep
|
||||
#define id_ddependson id_user.id_ddep
|
||||
#define id_def id_user.id_df
|
||||
|
||||
#include <idf_pkg.spec>
|
1
lang/m2/m2mm/idfsize.h
Normal file
1
lang/m2/m2mm/idfsize.h
Normal file
|
@ -0,0 +1 @@
|
|||
#define IDFSIZE 128 /* maximum significant length of an identifier */
|
31
lang/m2/m2mm/input.c
Normal file
31
lang/m2/m2mm/input.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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"
|
||||
struct f_info file_info;
|
||||
#include "input.h"
|
||||
#include <inp_pkg.body>
|
||||
|
||||
|
||||
AtEoIF()
|
||||
{
|
||||
/* Make the unstacking of input streams noticable to the
|
||||
lexical analyzer
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
AtEoIT()
|
||||
{
|
||||
/* Make the end of the text noticable
|
||||
*/
|
||||
return 1;
|
||||
}
|
18
lang/m2/m2mm/input.h
Normal file
18
lang/m2/m2mm/input.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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$ */
|
||||
|
||||
#include "inputtype.h"
|
||||
|
||||
#define INP_NPUSHBACK 2
|
||||
#define INP_TYPE struct f_info
|
||||
#define INP_VAR file_info
|
||||
|
||||
#include <inp_pkg.spec>
|
1
lang/m2/m2mm/inputtype.h
Normal file
1
lang/m2/m2mm/inputtype.h
Normal file
|
@ -0,0 +1 @@
|
|||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
32
lang/m2/m2mm/lib.c
Normal file
32
lang/m2/m2mm/lib.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* L I B R A R Y */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <em_path.h>
|
||||
|
||||
static char lib_dir[128] = EM_DIR;
|
||||
|
||||
is_library_dir(d)
|
||||
char *d;
|
||||
{
|
||||
/* Check if directory d is a directory containing
|
||||
"system" definition modules. Return 1 if it is, 0 otherwise.
|
||||
*/
|
||||
|
||||
return strcmp(lib_dir, d) == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
init_lib()
|
||||
{
|
||||
extern char *strcat();
|
||||
|
||||
strcat(lib_dir, "/lib/m2");
|
||||
AddInclDir(lib_dir);
|
||||
}
|
44
lang/m2/m2mm/m2mm.1
Normal file
44
lang/m2/m2mm/m2mm.1
Normal file
|
@ -0,0 +1,44 @@
|
|||
.TH M2MM 1ACK
|
||||
.ad
|
||||
.SH NAME
|
||||
m2mm \- Modula-2 makefile generator
|
||||
.SH SYNOPSIS
|
||||
\fBm2mm\fP [ \fB-I\fPdir \fB-M\fPflags \fB-C\fPcompiler \fB-S\fPsuffix ] file ...
|
||||
.SH DESCRIPTION
|
||||
.I M2mm
|
||||
is a makefile generator and fast syntax checker for Modula-2 programs.
|
||||
The makefile is produced on standard output.
|
||||
.I M2mm
|
||||
will generate rules to produce an object file
|
||||
for every module used in the argument files.
|
||||
In addition, it will generate a rule to make a program, for each of the
|
||||
program modules given as argument.
|
||||
Using
|
||||
.IR make (1)
|
||||
without an argument will make all these programs.
|
||||
.PP
|
||||
In the makefile, the variables \fBMOD\fP, \fBM2FLAGS\fP, \fBIFLAGS\fP, and
|
||||
\fBSUFFIX\fP will be defined.
|
||||
The generated rules have the following form:
|
||||
.DS
|
||||
\fIname\fP.$(SUFFIX): ...
|
||||
$(MOD) -c $(M2FLAGS) $(IFLAGS) \fIname\fP.mod
|
||||
.DE
|
||||
.I M2mm
|
||||
recognizes the following options:
|
||||
.IP \fB-I\fP\fIdir\fP
|
||||
Add \fIdir\fP to the list of directories where definition modules are
|
||||
looked for. Also add the flag to \fBIFLAGS\fP.
|
||||
The default value for \fBIFLAGS\fP is empty.
|
||||
.IP \fB-M\fP\fIflags\fP
|
||||
Set \fBM2FLAGS\fP to \fIflags\fP.
|
||||
.IP \fB-C\fP\fIcompiler\fP
|
||||
Set \fBMOD\fP to \fIcompiler\fP.
|
||||
The default value for \fBMOD\fP is "ack" (for the time being).
|
||||
.IP \fB-S\fPsuffix
|
||||
Set \fBSUFFIX\fP to \fIsuffix\fP.
|
||||
The default suffix is "o".
|
||||
.SH SEE ALSO
|
||||
.IR make "(1), " modula-2 (1)
|
||||
.SH DIAGNOSTICS
|
||||
Are intended to be self-explanatory.
|
412
lang/m2/m2mm/main.c
Normal file
412
lang/m2/m2mm/main.c
Normal file
|
@ -0,0 +1,412 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* M A I N P R O G R A M */
|
||||
|
||||
/* stripped down version from the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <alloc.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "tokenname.h"
|
||||
|
||||
int state; /* either IMPLEMENTATION or PROGRAM */
|
||||
char options[128];
|
||||
int DefinitionModule;
|
||||
char *ProgName;
|
||||
char **DEFPATH;
|
||||
int nDEF, mDEF;
|
||||
struct file_list *CurrentArg;
|
||||
extern int err_occurred;
|
||||
extern int Roption;
|
||||
extern char *strrindex();
|
||||
extern char *strcpy(), *strcat();
|
||||
|
||||
char *
|
||||
getwdir(fn)
|
||||
register char *fn;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
p = strrindex(fn, '/');
|
||||
while (p && *(p + 1) == '\0') { /* remove trailing /'s */
|
||||
*p = '\0';
|
||||
p = strrindex(fn, '/');
|
||||
}
|
||||
|
||||
if (p) {
|
||||
register char **d = DEFPATH;
|
||||
|
||||
*p = '\0';
|
||||
while (*d && strcmp(*d, fn) != 0) d++;
|
||||
if (*d) {
|
||||
*p = '/';
|
||||
return *d;
|
||||
}
|
||||
fn = Salloc(fn, (unsigned) (p - &fn[0] + 1));
|
||||
*p = '/';
|
||||
return fn;
|
||||
}
|
||||
return ".";
|
||||
}
|
||||
|
||||
static struct file_list *arglist;
|
||||
|
||||
char *mflags = "";
|
||||
char *compiler = "ack";
|
||||
char *suff = "o";
|
||||
|
||||
main(argc, argv)
|
||||
register char **argv;
|
||||
{
|
||||
extern struct tokenname tkidf[];
|
||||
extern char *getwdir();
|
||||
int i;
|
||||
|
||||
ProgName = *argv++;
|
||||
DEFPATH = (char **) Malloc(10 * sizeof(char *));
|
||||
mDEF = 10;
|
||||
nDEF = 1;
|
||||
|
||||
while (--argc > 0) {
|
||||
if (**argv == '-')
|
||||
DoOption((*argv++) + 1);
|
||||
else {
|
||||
Add(&arglist, *argv, getwdir(*argv), 1);
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
|
||||
init_idf();
|
||||
reserve(tkidf);
|
||||
print("IFLAGS =");
|
||||
for (i = 1; i < nDEF; i++) {
|
||||
print(" -I%s", DEFPATH[i]);
|
||||
}
|
||||
print("\nM2FLAGS = %s\nMOD = %s\nSUFFIX = %s\n", mflags, compiler, suff);
|
||||
init_lib();
|
||||
ProcessArgs();
|
||||
find_dependencies();
|
||||
print_dep();
|
||||
programs();
|
||||
exit(err_occurred);
|
||||
}
|
||||
|
||||
struct file_list *
|
||||
new_file_list()
|
||||
{
|
||||
static struct file_list *p;
|
||||
static int cnt;
|
||||
extern char *calloc();
|
||||
|
||||
if (cnt--) return p++;
|
||||
p = (struct file_list *)calloc(50, sizeof(struct file_list));
|
||||
cnt = 49;
|
||||
return p++;
|
||||
}
|
||||
|
||||
Add(parglist, f, d, copy)
|
||||
char *f, *d;
|
||||
struct file_list **parglist;
|
||||
{
|
||||
register struct file_list *a = *parglist, *b = 0;
|
||||
|
||||
while (a && strcmp(a->a_filename, f) != 0) {
|
||||
b = a;
|
||||
a = a->a_next;
|
||||
}
|
||||
if (a) return 0;
|
||||
a = new_file_list();
|
||||
if (copy) {
|
||||
a->a_filename = Salloc(f, (unsigned) (strlen(f)+1));
|
||||
}
|
||||
else {
|
||||
a->a_filename = f;
|
||||
}
|
||||
a->a_dir = d;
|
||||
if (! b) *parglist = a;
|
||||
else b->a_next = a;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ProcessArgs()
|
||||
{
|
||||
register struct file_list *a = arglist;
|
||||
char *fn;
|
||||
|
||||
while (a) {
|
||||
register char *p = strrindex(a->a_filename, '.');
|
||||
|
||||
CurrentArg = a;
|
||||
DEFPATH[0] = a->a_dir;
|
||||
if ( p && strcmp(p, ".def") == 0) {
|
||||
ForeignFlag = 0;
|
||||
if (! InsertFile(a->a_filename, DEFPATH, &fn)) {
|
||||
Gerror("Could not find %s", a->a_filename);
|
||||
a = a->a_next;
|
||||
continue;
|
||||
}
|
||||
FileName = fn;
|
||||
a->a_dir = WorkingDir = getwdir(FileName);
|
||||
DefModule();
|
||||
}
|
||||
else if (p && strcmp(p, ".mod") == 0) {
|
||||
if (! InsertFile(a->a_filename, DEFPATH, &fn)) {
|
||||
Gerror("Could not find %s", a->a_filename);
|
||||
*p = 0; /* prevent from being used
|
||||
later
|
||||
*/
|
||||
a->a_filename = Salloc(a->a_filename,
|
||||
strlen(a->a_filename) +
|
||||
11);
|
||||
strcat(a->a_filename, ".$(SUFFIX)");
|
||||
a = a->a_next;
|
||||
continue;
|
||||
}
|
||||
FileName = fn;
|
||||
a->a_dir = WorkingDir = getwdir(FileName);
|
||||
CompUnit();
|
||||
}
|
||||
else fatal("No Modula-2 file: %s", a->a_filename);
|
||||
a = a->a_next;
|
||||
}
|
||||
}
|
||||
|
||||
No_Mem()
|
||||
{
|
||||
fatal("out of memory");
|
||||
}
|
||||
|
||||
C_failed()
|
||||
{
|
||||
fatal("write failed");
|
||||
}
|
||||
|
||||
AddToList(name, ext)
|
||||
char *name, *ext;
|
||||
{
|
||||
/* Try to find a file with basename "name" and extension ".def",
|
||||
in the directories mentioned in "DEFPATH".
|
||||
*/
|
||||
char buf[15];
|
||||
char *strncpy();
|
||||
|
||||
if (strcmp(name, "SYSTEM") != 0 && ! is_library_dir(WorkingDir)) {
|
||||
strncpy(buf, name, 10);
|
||||
buf[10] = '\0'; /* maximum length */
|
||||
strcat(buf, ext);
|
||||
Add(&arglist, buf, WorkingDir, 1);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
find_dependencies()
|
||||
{
|
||||
register struct file_list *arg = arglist;
|
||||
|
||||
print("\nall:\t");
|
||||
while (arg) {
|
||||
char *dotspot = strrindex(arg->a_filename, '.');
|
||||
|
||||
if (dotspot && strcmp(dotspot, ".mod") == 0) {
|
||||
register struct idf *id = arg->a_idf;
|
||||
|
||||
if (id) {
|
||||
if (id->id_type == PROGRAM) {
|
||||
print("%s ", id->id_text);
|
||||
}
|
||||
file_dep(id);
|
||||
}
|
||||
}
|
||||
arg = arg->a_next;
|
||||
}
|
||||
print("\n\n");
|
||||
}
|
||||
|
||||
file_dep(id)
|
||||
register struct idf *id;
|
||||
{
|
||||
register struct lnk *m;
|
||||
|
||||
if (id->id_ddependson || id->id_mdependson) return;
|
||||
if (id->id_def) Add(&(id->id_mdependson), id->id_def, id->id_dir, 0);
|
||||
for (m = id->id_defimports; m; m = m->lnk_next) {
|
||||
register struct idf *iid = m->lnk_imp;
|
||||
|
||||
Add(&(id->id_mdependson), iid->id_def, iid->id_dir, 0);
|
||||
if (Add(&(id->id_ddependson), iid->id_def, iid->id_dir, 0)) {
|
||||
register struct file_list *p;
|
||||
|
||||
file_dep(iid);
|
||||
for (p = iid->id_ddependson; p; p = p->a_next) {
|
||||
Add(&(id->id_ddependson), p->a_filename,
|
||||
p->a_dir, 0);
|
||||
Add(&(id->id_mdependson), p->a_filename,
|
||||
p->a_dir, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (m = id->id_modimports; m; m = m->lnk_next) {
|
||||
register struct idf *iid = m->lnk_imp;
|
||||
|
||||
if (Add(&(id->id_mdependson), iid->id_def, iid->id_dir, 0)) {
|
||||
register struct file_list *p;
|
||||
|
||||
file_dep(iid);
|
||||
for (p = iid->id_ddependson; p; p = p->a_next) {
|
||||
Add(&(id->id_mdependson), p->a_filename,
|
||||
p->a_dir, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
object(arg)
|
||||
register struct file_list *arg;
|
||||
{
|
||||
static char buf[512];
|
||||
char *dotp = strrindex(arg->a_filename, '.');
|
||||
|
||||
buf[0] = 0;
|
||||
/*
|
||||
if (strcmp(arg->a_dir, ".") != 0) {
|
||||
strcpy(buf, arg->a_dir);
|
||||
strcat(buf, "/");
|
||||
}
|
||||
*/
|
||||
*dotp = 0;
|
||||
strcat(buf, arg->a_filename);
|
||||
*dotp = '.';
|
||||
strcat(buf, ".$(SUFFIX)");
|
||||
return buf;
|
||||
}
|
||||
|
||||
pr_arg(a)
|
||||
register struct file_list *a;
|
||||
{
|
||||
if (strcmp(a->a_dir, ".") == 0) {
|
||||
print(a->a_filename);
|
||||
}
|
||||
else print("%s/%s", a->a_dir, a->a_filename);
|
||||
}
|
||||
|
||||
print_dep()
|
||||
{
|
||||
register struct file_list *arg = arglist;
|
||||
|
||||
while (arg) {
|
||||
char *dotspot = strrindex(arg->a_filename, '.');
|
||||
|
||||
if (dotspot && strcmp(dotspot, ".mod") == 0) {
|
||||
register struct idf *id = arg->a_idf;
|
||||
|
||||
if (id) {
|
||||
char *obj = object(arg);
|
||||
register struct file_list *a;
|
||||
|
||||
print("%s: \\\n\t", obj);
|
||||
pr_arg(arg);
|
||||
for (a = id->id_mdependson; a; a = a->a_next) {
|
||||
print(" \\\n\t");
|
||||
pr_arg(a);
|
||||
}
|
||||
print("\n\t$(MOD) -c $(M2FLAGS) $(IFLAGS) ");
|
||||
pr_arg(arg);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
arg = arg->a_next;
|
||||
}
|
||||
}
|
||||
|
||||
prog_dep(id)
|
||||
register struct idf *id;
|
||||
{
|
||||
register struct lnk *m;
|
||||
register struct file_list *p;
|
||||
|
||||
id->id_mdependson = 0;
|
||||
id->id_def = 0;
|
||||
if (strlen(id->id_text) >= 10) id->id_text[10] = 0;
|
||||
Add(&(id->id_mdependson), id->id_text, id->id_dir, 0);
|
||||
for (m = id->id_modimports; m; m = m->lnk_next) {
|
||||
register struct idf *iid = m->lnk_imp;
|
||||
|
||||
if (Add(&(id->id_mdependson), iid->id_text, iid->id_dir, 0)) {
|
||||
if (iid->id_def) prog_dep(iid);
|
||||
for (p = iid->id_mdependson; p; p = p->a_next) {
|
||||
Add(&(id->id_mdependson), p->a_filename,
|
||||
p->a_dir, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module_in_arglist(n)
|
||||
char *n;
|
||||
{
|
||||
register struct file_list *a;
|
||||
|
||||
for (a = arglist; a; a = a->a_next) {
|
||||
char *dotp = strrindex(a->a_filename, '.');
|
||||
|
||||
if (dotp && strcmp(dotp, ".mod") == 0) {
|
||||
*dotp = 0;
|
||||
if (strcmp(a->a_filename, n) == 0) {
|
||||
*dotp = '.';
|
||||
return 1;
|
||||
}
|
||||
*dotp = '.';
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_prog_dep(id)
|
||||
register struct idf *id;
|
||||
{
|
||||
register struct file_list *p;
|
||||
|
||||
print("\nOBS_%s = ", id->id_text);
|
||||
for (p = id->id_mdependson; p; p = p->a_next) {
|
||||
if (module_in_arglist(p->a_filename)) {
|
||||
print("\\\n\t%s.$(SUFFIX)", p->a_filename);
|
||||
}
|
||||
else if (! is_library_dir(p->a_dir)) {
|
||||
print("\\\n\t%s/%s.$(SUFFIX)", p->a_dir, p->a_filename);
|
||||
}
|
||||
}
|
||||
print("\n\n");
|
||||
print("%s:\t$(OBS_%s)\n", id->id_text, id->id_text);
|
||||
print("\t$(MOD) -.mod -o %s $(M2FLAGS) $(OBS_%s)\n", id->id_text, id->id_text);
|
||||
}
|
||||
|
||||
programs()
|
||||
{
|
||||
register struct file_list *a;
|
||||
|
||||
for (a = arglist; a; a = a->a_next) {
|
||||
char *dotspot = strrindex(a->a_filename, '.');
|
||||
|
||||
if (dotspot && strcmp(dotspot, ".mod") == 0) {
|
||||
register struct idf *id = a->a_idf;
|
||||
|
||||
if (id && id->id_type == PROGRAM) {
|
||||
prog_dep(id);
|
||||
pr_prog_dep(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
lang/m2/m2mm/main.h
Normal file
17
lang/m2/m2mm/main.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S O M E G L O B A L V A R I A B L E S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
extern char options[]; /* indicating which options were given */
|
||||
|
||||
extern char **DEFPATH; /* search path for DEFINITION MODULE's */
|
||||
extern int mDEF, nDEF;
|
||||
extern int state; /* either IMPLEMENTATION or PROGRAM */
|
||||
extern struct file_list *CurrentArg;
|
34
lang/m2/m2mm/make.tokcase
Executable file
34
lang/m2/m2mm/make.tokcase
Executable file
|
@ -0,0 +1,34 @@
|
|||
cat <<'--EOT--'
|
||||
#include "Lpars.h"
|
||||
|
||||
char *
|
||||
symbol2str(tok)
|
||||
int tok;
|
||||
{
|
||||
static char buf[2] = { '\0', '\0' };
|
||||
|
||||
if (040 <= tok && tok < 0177) {
|
||||
buf[0] = tok;
|
||||
buf[1] = '\0';
|
||||
return buf;
|
||||
}
|
||||
switch (tok) {
|
||||
--EOT--
|
||||
sed '
|
||||
/{[A-Z]/!d
|
||||
s/.*{\(.*\),.*\(".*"\).*$/ case \1 :\
|
||||
return \2;/
|
||||
'
|
||||
cat <<'--EOT--'
|
||||
case '\n':
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\r':
|
||||
case '\t':
|
||||
buf[0] = tok;
|
||||
return buf;
|
||||
default:
|
||||
return "bad token";
|
||||
}
|
||||
}
|
||||
--EOT--
|
6
lang/m2/m2mm/make.tokfile
Executable file
6
lang/m2/m2mm/make.tokfile
Executable file
|
@ -0,0 +1,6 @@
|
|||
sed '
|
||||
/{[A-Z]/!d
|
||||
s/.*{//
|
||||
s/,.*//
|
||||
s/.*/%token &;/
|
||||
'
|
31
lang/m2/m2mm/misc.c
Normal file
31
lang/m2/m2mm/misc.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* M I S C E L L A N E O U S R O U T I N E S */
|
||||
|
||||
/* stripped version from the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include "f_info.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
|
||||
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 *sprint();
|
||||
|
||||
sprint(buff, "#%d in %s, line %u",
|
||||
++name_cnt, FileName, LineNumber);
|
||||
return str2idf(buff, 1);
|
||||
}
|
80
lang/m2/m2mm/options.c
Normal file
80
lang/m2/m2mm/options.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* U S E R O P T I O N - H A N D L I N G */
|
||||
|
||||
/* stripped down version from the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#include <alloc.h>
|
||||
#include "main.h"
|
||||
|
||||
static int ndirs = 1;
|
||||
|
||||
DoOption(text)
|
||||
register char *text;
|
||||
{
|
||||
extern char *mflags;
|
||||
extern char *suff;
|
||||
extern char *compiler;
|
||||
|
||||
switch(*text++) {
|
||||
|
||||
case 'I' :
|
||||
AddInclDir(text);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
mflags = text;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
compiler = text;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
suff = text;
|
||||
break;
|
||||
|
||||
default:
|
||||
Gerror("Unrecognized option: -%s", text-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AddInclDir(text)
|
||||
char *text;
|
||||
{
|
||||
register int i;
|
||||
register char *new = text;
|
||||
|
||||
if (! *text) {
|
||||
DEFPATH[ndirs] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (++nDEF > mDEF) {
|
||||
char **n = (char **)
|
||||
Malloc((unsigned)((10+mDEF)*sizeof(char *)));
|
||||
|
||||
for (i = 0; i < mDEF; i++) {
|
||||
n[i] = DEFPATH[i];
|
||||
}
|
||||
free((char *) DEFPATH);
|
||||
DEFPATH = n;
|
||||
mDEF += 10;
|
||||
}
|
||||
|
||||
i = ndirs++;
|
||||
while (new) {
|
||||
register char *tmp = DEFPATH[i];
|
||||
|
||||
DEFPATH[i++] = new;
|
||||
new = tmp;
|
||||
}
|
||||
}
|
237
lang/m2/m2mm/program.g
Normal file
237
lang/m2/m2mm/program.g
Normal file
|
@ -0,0 +1,237 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* O V E R A L L S T R U C T U R E */
|
||||
|
||||
/* stripped down version of the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/*
|
||||
The grammar as given by Wirth is already almost LL(1); the
|
||||
main problem is that the full form of a qualified designator
|
||||
may be:
|
||||
[ module_ident '.' ]* IDENT [ '.' field_ident ]*
|
||||
which is quite confusing to an LL(1) parser. Rather than
|
||||
resorting to context-sensitive techniques, I have decided
|
||||
to render this as:
|
||||
IDENT [ '.' IDENT ]*
|
||||
on the grounds that it is quite natural to consider the first
|
||||
IDENT to be the name of the object and regard the others as
|
||||
field identifiers.
|
||||
*/
|
||||
|
||||
{
|
||||
#include "main.h"
|
||||
#include "idf.h"
|
||||
#include "f_info.h"
|
||||
#include "LLlex.h"
|
||||
|
||||
struct lnk *
|
||||
new_lnk()
|
||||
{
|
||||
static struct lnk *p;
|
||||
static int cnt;
|
||||
extern char *calloc();
|
||||
|
||||
if (cnt--) return p++;
|
||||
p = (struct lnk *)calloc(50, sizeof(struct lnk));
|
||||
cnt = 49;
|
||||
return p++;
|
||||
}
|
||||
}
|
||||
|
||||
%lexical LLlex;
|
||||
|
||||
%start CompUnit, CompilationUnit;
|
||||
%start DefModule, DefinitionModule;
|
||||
|
||||
ModuleDeclaration :
|
||||
MODULE IDENT
|
||||
priority
|
||||
';'
|
||||
import((struct lnk **) 0)*
|
||||
export?
|
||||
block
|
||||
IDENT
|
||||
;
|
||||
|
||||
priority:
|
||||
[
|
||||
'[' ConstExpression ']'
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
export :
|
||||
EXPORT
|
||||
[
|
||||
QUALIFIED
|
||||
|
|
||||
]
|
||||
IdentList ';'
|
||||
;
|
||||
|
||||
import(register struct lnk **p;)
|
||||
{
|
||||
register struct idf *fromid = 0;
|
||||
struct idf *id;
|
||||
}
|
||||
:
|
||||
{ if (p) while (*p) p = &((*p)->lnk_next); }
|
||||
[ FROM
|
||||
identifier(&id) { fromid = id;
|
||||
if (p) {
|
||||
if (AddToList(fromid->id_text, ".def")) {
|
||||
*p = new_lnk();
|
||||
(*p)->lnk_imp = fromid;
|
||||
}
|
||||
}
|
||||
}
|
||||
]?
|
||||
IMPORT
|
||||
identifier(&id) { if (! fromid && p) {
|
||||
if (AddToList(id->id_text, ".def")) {
|
||||
*p = new_lnk();
|
||||
(*p)->lnk_imp = id;
|
||||
p = &((*p)->lnk_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
[
|
||||
',' identifier(&id)
|
||||
{ if (! fromid && p) {
|
||||
if (AddToList(id->id_text, ".def")) {
|
||||
*p = new_lnk();
|
||||
(*p)->lnk_imp = id;
|
||||
p = &((*p)->lnk_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
]*
|
||||
';'
|
||||
/*
|
||||
When parsing a global module, this is the place where we must
|
||||
read already compiled definition modules.
|
||||
If the FROM clause is present, the identifier in it is a module
|
||||
name, otherwise the names in the import list are module names.
|
||||
*/
|
||||
;
|
||||
|
||||
DefinitionModule
|
||||
{
|
||||
struct idf *id;
|
||||
extern char *strrindex();
|
||||
}
|
||||
:
|
||||
DEFINITION
|
||||
MODULE identifier(&id)
|
||||
{ if (! ForeignFlag) {
|
||||
AddToList(id->id_text, ".mod");
|
||||
}
|
||||
if (! id->id_type) {
|
||||
id->id_type = DEFINITION;
|
||||
}
|
||||
else if (id->id_type != IMPLEMENTATION) {
|
||||
error("multiple declaration for module %s",
|
||||
id->id_text);
|
||||
}
|
||||
if (! id->id_dir) {
|
||||
id->id_dir = WorkingDir;
|
||||
}
|
||||
else if (strcmp(id->id_dir, WorkingDir)) {
|
||||
Gerror("definition and implementation of module %s reside in different directories", id->id_text);
|
||||
}
|
||||
id->id_def = strrindex(FileName, '/');
|
||||
if (! id->id_def) id->id_def = FileName;
|
||||
else (id->id_def)++;
|
||||
CurrentArg->a_idf = id;
|
||||
}
|
||||
';'
|
||||
import(&(id->id_defimports))*
|
||||
[
|
||||
export
|
||||
|
|
||||
/* empty */
|
||||
]
|
||||
definition* END IDENT
|
||||
'.'
|
||||
;
|
||||
|
||||
definition :
|
||||
CONST [ %persistent ConstantDeclaration ';' ]*
|
||||
|
|
||||
TYPE
|
||||
[ %persistent
|
||||
IDENT
|
||||
[ '=' type
|
||||
| /* empty */
|
||||
/*
|
||||
Here, the exported type has a hidden implementation.
|
||||
The export is said to be opaque.
|
||||
It is restricted to pointer types.
|
||||
*/
|
||||
]
|
||||
';'
|
||||
]*
|
||||
|
|
||||
VAR [ %persistent VariableDeclaration ';' ]*
|
||||
|
|
||||
ProcedureHeading
|
||||
';'
|
||||
;
|
||||
|
||||
ProgramModule
|
||||
{
|
||||
struct idf *id;
|
||||
}
|
||||
:
|
||||
MODULE
|
||||
identifier(&id) { if (! id->id_type) {
|
||||
id->id_type = state;
|
||||
}
|
||||
else if (id->id_type != DEFINITION ||
|
||||
state != IMPLEMENTATION) {
|
||||
error("multiple declaration for module %s",
|
||||
id->id_text);
|
||||
}
|
||||
if (! id->id_dir) {
|
||||
id->id_dir = WorkingDir;
|
||||
}
|
||||
else if (strcmp(id->id_dir, WorkingDir)) {
|
||||
Gerror("definition and implementation of module %s reside in different directories", id->id_text);
|
||||
}
|
||||
CurrentArg->a_idf = id;
|
||||
}
|
||||
priority
|
||||
';' import(&(id->id_modimports))*
|
||||
block IDENT
|
||||
'.'
|
||||
;
|
||||
|
||||
Module:
|
||||
DEFINITION
|
||||
{ fatal("Definition module in .mod file"); }
|
||||
| %default
|
||||
[
|
||||
IMPLEMENTATION { state = IMPLEMENTATION; }
|
||||
|
|
||||
/* empty */ { state = PROGRAM; }
|
||||
]
|
||||
ProgramModule
|
||||
;
|
||||
|
||||
CompilationUnit:
|
||||
Module
|
||||
;
|
||||
|
||||
identifier(struct idf **id;):
|
||||
IDENT
|
||||
{ extern char idfbuf[];
|
||||
*id = str2idf(idfbuf);
|
||||
}
|
||||
;
|
136
lang/m2/m2mm/statement.g
Normal file
136
lang/m2/m2mm/statement.g
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S T A T E M E N T S */
|
||||
|
||||
/* stripped down version from the one in the Modula-2 compiler */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
{
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
|
||||
static int loopcount;
|
||||
}
|
||||
|
||||
statement :
|
||||
[
|
||||
/*
|
||||
* This part is not in the reference grammar. The reference grammar
|
||||
* states : assignment | ProcedureCall | ...
|
||||
* but this gives LL(1) conflicts
|
||||
*/
|
||||
designator
|
||||
[
|
||||
ActualParameters?
|
||||
|
|
||||
[ BECOMES
|
||||
| '=' { error("':=' expected instead of '='");
|
||||
DOT = BECOMES;
|
||||
}
|
||||
]
|
||||
expression
|
||||
]
|
||||
/*
|
||||
* end of changed part
|
||||
*/
|
||||
|
|
||||
IfStatement
|
||||
|
|
||||
CaseStatement
|
||||
|
|
||||
WHILE
|
||||
expression
|
||||
DO
|
||||
StatementSequence
|
||||
END
|
||||
|
|
||||
REPEAT
|
||||
StatementSequence
|
||||
UNTIL
|
||||
expression
|
||||
|
|
||||
{ loopcount++; }
|
||||
LOOP
|
||||
StatementSequence
|
||||
END
|
||||
{ loopcount--; }
|
||||
|
|
||||
ForStatement
|
||||
|
|
||||
WithStatement
|
||||
|
|
||||
EXIT
|
||||
{ if (!loopcount) error("EXIT not in a LOOP"); }
|
||||
|
|
||||
ReturnStatement
|
||||
|
|
||||
/* empty */
|
||||
]
|
||||
;
|
||||
|
||||
StatementSequence :
|
||||
statement
|
||||
[ %persistent
|
||||
';'
|
||||
statement
|
||||
]*
|
||||
;
|
||||
|
||||
IfStatement :
|
||||
IF expression
|
||||
THEN StatementSequence
|
||||
[
|
||||
ELSIF expression
|
||||
THEN StatementSequence
|
||||
]*
|
||||
[
|
||||
ELSE StatementSequence
|
||||
]?
|
||||
END
|
||||
;
|
||||
|
||||
CaseStatement :
|
||||
CASE expression
|
||||
OF case
|
||||
[
|
||||
'|' case
|
||||
]*
|
||||
[ ELSE StatementSequence
|
||||
]?
|
||||
END
|
||||
;
|
||||
|
||||
case :
|
||||
[ CaseLabelList ':'
|
||||
StatementSequence
|
||||
]?
|
||||
;
|
||||
|
||||
ForStatement :
|
||||
FOR IDENT BECOMES expression TO expression
|
||||
[
|
||||
BY ConstExpression
|
||||
|
|
||||
]
|
||||
DO StatementSequence
|
||||
END
|
||||
;
|
||||
|
||||
WithStatement :
|
||||
WITH designator DO StatementSequence
|
||||
END
|
||||
;
|
||||
|
||||
ReturnStatement :
|
||||
RETURN
|
||||
[
|
||||
expression
|
||||
|
|
||||
]
|
||||
;
|
295
lang/m2/m2mm/tab.c
Normal file
295
lang/m2/m2mm/tab.c
Normal file
|
@ -0,0 +1,295 @@
|
|||
/* @cc tab.c -o $INSTALLDIR/tab@
|
||||
tab - table generator
|
||||
|
||||
Author: Erik Baalbergen (..tjalk!erikb)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static char *RcsId = "$Header$";
|
||||
|
||||
#define MAXTAB 10000
|
||||
#define MAXBUF 10000
|
||||
#define COMCOM '-'
|
||||
#define FILECOM '%'
|
||||
|
||||
int InputForm = 'c';
|
||||
char OutputForm[MAXBUF] = "%s,\n";
|
||||
int TabSize = 257;
|
||||
char *Table[MAXTAB];
|
||||
char *Name;
|
||||
char *ProgCall;
|
||||
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
ProgCall = *argv++;
|
||||
argc--;
|
||||
while (argc-- > 0) {
|
||||
if (**argv == COMCOM) {
|
||||
option(*argv++);
|
||||
}
|
||||
else {
|
||||
process(*argv++, InputForm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
Salloc(s)
|
||||
char *s;
|
||||
{
|
||||
char *malloc();
|
||||
char *ns = malloc(strlen(s) + 1);
|
||||
|
||||
if (ns) {
|
||||
strcpy(ns, s);
|
||||
}
|
||||
return ns;
|
||||
}
|
||||
|
||||
option(str)
|
||||
char *str;
|
||||
{
|
||||
/* note that *str indicates the source of the option:
|
||||
either COMCOM (from command line) or FILECOM (from a file).
|
||||
*/
|
||||
switch (*++str) {
|
||||
|
||||
case ' ': /* command */
|
||||
case '\t':
|
||||
case '\0':
|
||||
break;
|
||||
case 'I':
|
||||
InputForm = *++str;
|
||||
break;
|
||||
case 'f':
|
||||
if (*++str == '\0') {
|
||||
fprintf(stderr, "%s: -f: name expected\n", ProgCall);
|
||||
exit(1);
|
||||
}
|
||||
DoFile(str);
|
||||
break;
|
||||
case 'F':
|
||||
sprintf(OutputForm, "%s\n", ++str);
|
||||
break;
|
||||
case 'T':
|
||||
printf("%s\n", ++str);
|
||||
break;
|
||||
case 'p':
|
||||
PrintTable();
|
||||
break;
|
||||
case 'C':
|
||||
ClearTable();
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
register i = stoi(++str);
|
||||
|
||||
if (i <= 0 || i > MAXTAB) {
|
||||
fprintf(stderr, "%s: size would exceed maximum\n",
|
||||
ProgCall);
|
||||
}
|
||||
else {
|
||||
TabSize = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "%s: bad option -%s\n", ProgCall, str);
|
||||
}
|
||||
}
|
||||
|
||||
ClearTable()
|
||||
{
|
||||
register i;
|
||||
|
||||
for (i = 0; i < MAXTAB; i++) {
|
||||
Table[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PrintTable()
|
||||
{
|
||||
register i;
|
||||
|
||||
for (i = 0; i < TabSize; i++) {
|
||||
if (Table[i]) {
|
||||
printf(OutputForm, Table[i]);
|
||||
}
|
||||
else {
|
||||
printf(OutputForm, "0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process(str, format)
|
||||
char *str;
|
||||
{
|
||||
char *cstr = str;
|
||||
char *Name = cstr; /* overwrite original string! */
|
||||
|
||||
/* strip of the entry name
|
||||
*/
|
||||
while (*str && *str != ':') {
|
||||
if (*str == '\\') {
|
||||
++str;
|
||||
}
|
||||
*cstr++ = *str++;
|
||||
}
|
||||
|
||||
if (*str != ':') {
|
||||
fprintf(stderr, "%s: bad specification: \"%s\", ignored\n",
|
||||
ProgCall, Name);
|
||||
return 0;
|
||||
}
|
||||
*cstr = '\0';
|
||||
str++;
|
||||
|
||||
switch (format) {
|
||||
|
||||
case 'c':
|
||||
return c_proc(str, Name);
|
||||
default:
|
||||
fprintf(stderr, "%s: bad input format\n", ProgCall);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
c_proc(str, Name)
|
||||
char *str;
|
||||
char *Name;
|
||||
{
|
||||
int ch, ch2;
|
||||
int quoted();
|
||||
|
||||
while (*str) {
|
||||
if (*str == '\\') {
|
||||
ch = quoted(&str);
|
||||
}
|
||||
else {
|
||||
ch = *str++;
|
||||
}
|
||||
if (*str == '-') {
|
||||
if (*++str == '\\') {
|
||||
ch2 = quoted(&str);
|
||||
}
|
||||
else {
|
||||
if (ch2 = *str++);
|
||||
else str--;
|
||||
}
|
||||
if (ch > ch2) {
|
||||
fprintf(stderr, "%s: bad range\n", ProgCall);
|
||||
return 0;
|
||||
}
|
||||
if (ch >= 0 && ch2 <= 255)
|
||||
while (ch <= ch2)
|
||||
Table[ch++] = Salloc(Name);
|
||||
}
|
||||
else {
|
||||
if (ch >= 0 && ch <= 255)
|
||||
Table[ch] = Salloc(Name);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
quoted(pstr)
|
||||
char **pstr;
|
||||
{
|
||||
register int ch;
|
||||
register int i;
|
||||
register char *str = *pstr;
|
||||
|
||||
if ((*++str >= '0') && (*str <= '9')) {
|
||||
ch = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
ch = 8 * ch + *str - '0';
|
||||
if (*++str < '0' || *str > '9')
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (*str++) {
|
||||
|
||||
case 'n':
|
||||
ch = '\n';
|
||||
break;
|
||||
case 't':
|
||||
ch = '\t';
|
||||
break;
|
||||
case 'b':
|
||||
ch = '\b';
|
||||
break;
|
||||
case 'r':
|
||||
ch = '\r';
|
||||
break;
|
||||
case 'f':
|
||||
ch = '\f';
|
||||
break;
|
||||
default :
|
||||
ch = *str;
|
||||
}
|
||||
}
|
||||
*pstr = str;
|
||||
return ch & 0377;
|
||||
}
|
||||
|
||||
int
|
||||
stoi(str)
|
||||
char *str;
|
||||
{
|
||||
register i = 0;
|
||||
|
||||
while (*str >= '0' && *str <= '9') {
|
||||
i = i * 10 + *str++ - '0';
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
char *
|
||||
getline(s, n, fp)
|
||||
char *s;
|
||||
FILE *fp;
|
||||
{
|
||||
register c = getc(fp);
|
||||
char *str = s;
|
||||
|
||||
while (n--) {
|
||||
if (c == EOF) {
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
if (c == '\n') {
|
||||
*str++ = '\0';
|
||||
return s;
|
||||
}
|
||||
*str++ = c;
|
||||
c = getc(fp);
|
||||
}
|
||||
s[n - 1] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
DoFile(name)
|
||||
char *name;
|
||||
{
|
||||
char text[BUFSIZE];
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(name, "r")) == NULL) {
|
||||
fprintf(stderr, "%s: cannot read file %s\n", ProgCall, name);
|
||||
exit(1);
|
||||
}
|
||||
while (getline(text, BUFSIZE, fp) != NULL) {
|
||||
if (text[0] == FILECOM) {
|
||||
option(text);
|
||||
}
|
||||
else {
|
||||
process(text, InputForm);
|
||||
}
|
||||
}
|
||||
}
|
113
lang/m2/m2mm/tokenname.c
Normal file
113
lang/m2/m2mm/tokenname.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T O K E N D E F I N I T I O N S */
|
||||
|
||||
/* $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
|
||||
a grammar file (tokenfile.g) from this file. This scheme ensures
|
||||
that all tokens have a printable name.
|
||||
Also, the "token2str.c" file is produced from this file.
|
||||
*/
|
||||
|
||||
#ifdef ___XXX___
|
||||
struct tokenname tkspec[] = { /* the names of the special tokens */
|
||||
{IDENT, "identifier"},
|
||||
{STRING, "string"},
|
||||
{INTEGER, "number"},
|
||||
{REAL, "real"},
|
||||
{0, ""}
|
||||
};
|
||||
|
||||
struct tokenname tkcomp[] = { /* names of the composite tokens */
|
||||
{LESSEQUAL, "<="},
|
||||
{GREATEREQUAL, ">="},
|
||||
{UPTO, ".."},
|
||||
{BECOMES, ":="},
|
||||
{0, ""}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct tokenname tkidf[] = { /* names of the identifier tokens */
|
||||
{AND, "AND"},
|
||||
{ARRAY, "ARRAY"},
|
||||
{BEGIN, "BEGIN"},
|
||||
{BY, "BY"},
|
||||
{CASE, "CASE"},
|
||||
{CONST, "CONST"},
|
||||
{DEFINITION, "DEFINITION"},
|
||||
{DIV, "DIV"},
|
||||
{DO, "DO"},
|
||||
{ELSE, "ELSE"},
|
||||
{ELSIF, "ELSIF"},
|
||||
{END, "END"},
|
||||
{EXIT, "EXIT"},
|
||||
{EXPORT, "EXPORT"},
|
||||
{FOR, "FOR"},
|
||||
{FROM, "FROM"},
|
||||
{IF, "IF"},
|
||||
{IMPLEMENTATION, "IMPLEMENTATION"},
|
||||
{IMPORT, "IMPORT"},
|
||||
{IN, "IN"},
|
||||
{LOOP, "LOOP"},
|
||||
{MOD, "MOD"},
|
||||
{MODULE, "MODULE"},
|
||||
{NOT, "NOT"},
|
||||
{OF, "OF"},
|
||||
{OR, "OR"},
|
||||
{POINTER, "POINTER"},
|
||||
{PROCEDURE, "PROCEDURE"},
|
||||
{QUALIFIED, "QUALIFIED"},
|
||||
{RECORD, "RECORD"},
|
||||
{REPEAT, "REPEAT"},
|
||||
{RETURN, "RETURN"},
|
||||
{SET, "SET"},
|
||||
{THEN, "THEN"},
|
||||
{TO, "TO"},
|
||||
{TYPE, "TYPE"},
|
||||
{UNTIL, "UNTIL"},
|
||||
{VAR, "VAR"},
|
||||
{WHILE, "WHILE"},
|
||||
{WITH, "WITH"},
|
||||
{0, ""}
|
||||
};
|
||||
|
||||
#ifdef ___XXX___
|
||||
struct tokenname tkinternal[] = { /* internal keywords */
|
||||
{PROGRAM, ""},
|
||||
{COERCION, ""},
|
||||
{0, "0"}
|
||||
};
|
||||
|
||||
struct tokenname tkstandard[] = { /* standard identifiers */
|
||||
{0, ""}
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Some routines to handle tokennames */
|
||||
|
||||
reserve(resv)
|
||||
register struct tokenname *resv;
|
||||
{
|
||||
/* The names of the tokens described in resv are entered
|
||||
as reserved words.
|
||||
*/
|
||||
register struct idf *p;
|
||||
|
||||
while (resv->tn_symbol) {
|
||||
p = str2idf(resv->tn_name, 0);
|
||||
if (!p) fatal("out of Memory");
|
||||
p->id_reserved = resv->tn_symbol;
|
||||
resv++;
|
||||
}
|
||||
}
|
17
lang/m2/m2mm/tokenname.h
Normal file
17
lang/m2/m2mm/tokenname.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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
|
||||
*/
|
||||
int tn_symbol;
|
||||
char *tn_name;
|
||||
};
|
Loading…
Reference in a new issue