newer version
This commit is contained in:
parent
f3bf7cd5bc
commit
3030eb8cae
50 changed files with 839 additions and 924 deletions
|
@ -1,9 +1,5 @@
|
|||
/* 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 */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "idfsize.h"
|
||||
#include "numsize.h"
|
||||
|
@ -40,9 +36,10 @@ SkipComment()
|
|||
Note that comments may be nested (par. 3.5).
|
||||
*/
|
||||
register int ch;
|
||||
register int CommentLevel = 0;
|
||||
|
||||
LoadChar(ch);
|
||||
for (;;) {
|
||||
LoadChar(ch);
|
||||
if (class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
#ifdef DEBUG
|
||||
|
@ -51,12 +48,22 @@ SkipComment()
|
|||
}
|
||||
else if (ch == '(') {
|
||||
LoadChar(ch);
|
||||
if (ch == '*') SkipComment();
|
||||
if (ch == '*') CommentLevel++;
|
||||
else continue;
|
||||
}
|
||||
else if (ch == '*') {
|
||||
LoadChar(ch);
|
||||
if (ch == ')') break;
|
||||
if (ch == ')') {
|
||||
CommentLevel--;
|
||||
if (CommentLevel < 0) break;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
else if (ch == EOI) {
|
||||
lexerror("unterminated comment");
|
||||
break;
|
||||
}
|
||||
LoadChar(ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +76,8 @@ GetString(upto)
|
|||
register struct string *str = (struct string *) Malloc(sizeof(struct string));
|
||||
register char *p;
|
||||
|
||||
str->s_str = p = Malloc((unsigned int) (str->s_length = ISTRSIZE));
|
||||
str->s_length = ISTRSIZE;
|
||||
str->s_str = p = Malloc((unsigned int) ISTRSIZE);
|
||||
while (LoadChar(ch), ch != upto) {
|
||||
if (class(ch) == STNL) {
|
||||
lexerror("newline in string");
|
||||
|
@ -394,6 +402,7 @@ lexwarning("Character constant out of range");
|
|||
case STCHAR:
|
||||
default:
|
||||
crash("(LLlex) Impossible character class");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* 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$ */
|
||||
|
||||
/* Structure to store a string constant
|
||||
*/
|
||||
struct string {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* S Y N T A X E R R O R R E P O R T I N G */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
/* 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
|
||||
|
@ -39,24 +35,28 @@ LLmessage(tk)
|
|||
insert_token(tk)
|
||||
int tk;
|
||||
{
|
||||
aside = dot;
|
||||
register struct token *dotp = ˙
|
||||
|
||||
dot.tk_symb = tk;
|
||||
aside = *dotp;
|
||||
|
||||
dotp->tk_symb = tk;
|
||||
|
||||
switch (tk) {
|
||||
/* The operands need some body */
|
||||
case IDENT:
|
||||
dot.TOK_IDF = gen_anon_idf();
|
||||
dotp->TOK_IDF = gen_anon_idf();
|
||||
break;
|
||||
case STRING:
|
||||
dot.TOK_SLE = 1;
|
||||
dot.TOK_STR = Salloc("", 1);
|
||||
dotp->tk_data.tk_str = (struct string *)
|
||||
Malloc(sizeof (struct string));
|
||||
dotp->TOK_SLE = 1;
|
||||
dotp->TOK_STR = Salloc("", 1);
|
||||
break;
|
||||
case INTEGER:
|
||||
dot.TOK_INT = 1;
|
||||
dotp->TOK_INT = 1;
|
||||
break;
|
||||
case REAL:
|
||||
dot.TOK_REL = Salloc("0.0", 4);
|
||||
dotp->TOK_REL = Salloc("0.0", 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
# make modula-2 "compiler"
|
||||
# $Header$
|
||||
EMDIR = /usr/ceriel/em
|
||||
MHDIR = $(EMDIR)/modules/h
|
||||
PKGDIR = $(EMDIR)/modules/pkg
|
||||
|
@ -8,19 +7,26 @@ LLGEN = $(EMDIR)/bin/LLgen
|
|||
|
||||
INCLUDES = -I$(MHDIR) -I$(EMDIR)/h -I$(PKGDIR)
|
||||
|
||||
LSRC = tokenfile.g program.g declar.g expression.g statement.g
|
||||
GFILES = tokenfile.g program.g declar.g expression.g statement.g
|
||||
CC = cc
|
||||
LLGENOPTIONS =
|
||||
PROFILE =
|
||||
CFLAGS = $(PROFILE) $(INCLUDES) -DSTATIC=
|
||||
LINTFLAGS = -DSTATIC= -DNORCSID
|
||||
LFLAGS = $(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 char.c error.c main.c \
|
||||
symbol2str.c tokenname.c idf.c input.c type.c def.c \
|
||||
scope.c misc.c enter.c defmodule.c typequiv.c node.c \
|
||||
cstoper.c chk_expr.c options.c walk.c casestat.c desig.c \
|
||||
code.c tmpvar.c lookup.c Version.c
|
||||
COBJ = LLlex.o LLmessage.o char.o error.o main.o \
|
||||
symbol2str.o tokenname.o idf.o input.o type.o def.o \
|
||||
scope.o misc.o enter.o defmodule.o typequiv.o node.o \
|
||||
cstoper.o chk_expr.o options.o walk.o casestat.o desig.o \
|
||||
code.o tmpvar.o lookup.o
|
||||
code.o tmpvar.o lookup.o Version.o
|
||||
SRC = $(CSRC) $(LSRC) Lpars.c
|
||||
OBJ = $(COBJ) $(LOBJ) Lpars.o
|
||||
|
||||
# Keep the next entries up to date!
|
||||
|
@ -44,11 +50,11 @@ all: Cfiles
|
|||
@rm -f nmclash.o a.out
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(GENFILES) LLfiles hfiles Cfiles tab cclash.o cid.o cclash cid
|
||||
rm -f $(OBJ) $(GENFILES) LLfiles hfiles Cfiles tab cclash.o cid.o cclash cid clashes
|
||||
(cd .. ; rm -rf Xsrc)
|
||||
|
||||
lint: Cfiles
|
||||
sh -c `if $(CC) nmclash.c > /dev/null 2>&1 ; then make Xlint ; else sh Resolve Xlint ; fi'
|
||||
sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make Xlint ; else sh Resolve Xlint ; fi'
|
||||
@rm -f nmclash.o a.out
|
||||
|
||||
mkdep: mkdep.o
|
||||
|
@ -57,20 +63,22 @@ mkdep: mkdep.o
|
|||
cclash: cclash.o
|
||||
$(CC) $(LFLAGS) -o cclash cclash.o
|
||||
|
||||
clashes: $(SRC) $(HFILES)
|
||||
sh -c 'if test -f clashes ; then ./cclash -l7 clashes $? > Xclashes ; mv Xclashes clashes ; else ./cclash -l7 $? > clashes ; fi'
|
||||
|
||||
cid: cid.o
|
||||
$(CC) $(LFLAGS) -o cid cid.o
|
||||
|
||||
# entry points not to be used directly
|
||||
|
||||
Xlint:
|
||||
lint $(INCLUDES) $(LINTFLAGS) `./sources $(OBJ)`
|
||||
lint $(INCLUDES) $(LINTFLAGS) $(SRC)
|
||||
|
||||
Cfiles: hfiles LLfiles $(GENHFILES) $(GENCFILES)
|
||||
./sources $(OBJ) > Cfiles
|
||||
sh -c 'for i in $(HFILES) ; do echo $$i ; done >> Cfiles'
|
||||
Cfiles: hfiles LLfiles $(GENCFILES) $(GENHFILES)
|
||||
echo $(SRC) $(HFILES) > Cfiles
|
||||
|
||||
LLfiles: $(LSRC)
|
||||
$(LLGEN) $(LLGENOPTIONS) $(LSRC)
|
||||
LLfiles: $(GFILES)
|
||||
$(LLGEN) $(LLGENOPTIONS) $(GFILES)
|
||||
@touch LLfiles
|
||||
|
||||
hfiles: Parameters make.hfiles
|
||||
|
@ -78,7 +86,7 @@ hfiles: Parameters make.hfiles
|
|||
touch hfiles
|
||||
|
||||
main: $(OBJ) ../src/Makefile
|
||||
$(CC) $(LFLAGS) $(OBJ) $(LIBDIR)/libem_mes.a $(LIBDIR)/libemk.a $(LIBDIR)/input.a $(LIBDIR)/assert.a $(LIBDIR)/alloc.a $(LIBDIR)/malloc.o $(LIBDIR)/libprint.a $(LIBDIR)/libstr.a $(LIBDIR)/libsystem.a -o ../src/main
|
||||
$(CC) $(LFLAGS) $(OBJ) $(LIBDIR)/libem_mes.a $(LIBDIR)/libemk.a $(LIBDIR)/input.a $(LIBDIR)/assert.a $(LIBDIR)/alloc.a $(LIBDIR)/dickmalloc.o $(LIBDIR)/libprint.a $(LIBDIR)/libstr.a $(LIBDIR)/libsystem.a -o ../src/main
|
||||
size ../src/main
|
||||
|
||||
tokenfile.g: tokenname.c make.tokfile
|
||||
|
@ -114,7 +122,7 @@ char.c: ../src/char.tab ../src/tab
|
|||
depend: mkdep
|
||||
sed '/^#AUTOAUTO/,$$d' Makefile > Makefile.new
|
||||
echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >> Makefile.new
|
||||
./mkdep `./sources $(OBJ)` |\
|
||||
./mkdep $(SRC) |\
|
||||
sed 's/\.c:/\.o:/' >> Makefile.new
|
||||
mv Makefile Makefile.old
|
||||
mv Makefile.new Makefile
|
||||
|
@ -128,13 +136,13 @@ main.o: LLlex.h Lpars.h debug.h def.h f_info.h idf.h input.h inputtype.h ndir.h
|
|||
symbol2str.o: Lpars.h
|
||||
tokenname.o: Lpars.h idf.h tokenname.h
|
||||
idf.o: idf.h
|
||||
input.o: f_info.h input.h inputtype.h
|
||||
input.o: def.h f_info.h idf.h input.h inputtype.h scope.h
|
||||
type.o: LLlex.h const.h debug.h def.h idf.h maxset.h node.h scope.h target_sizes.h type.h walk.h
|
||||
def.o: LLlex.h Lpars.h debug.h def.h idf.h main.h node.h scope.h type.h
|
||||
scope.o: LLlex.h debug.h def.h idf.h node.h scope.h type.h
|
||||
misc.o: LLlex.h f_info.h idf.h misc.h node.h
|
||||
enter.o: LLlex.h debug.h def.h idf.h main.h node.h scope.h type.h
|
||||
defmodule.o: LLlex.h debug.h def.h f_info.h idf.h input.h inputtype.h main.h scope.h
|
||||
defmodule.o: LLlex.h Lpars.h debug.h def.h f_info.h idf.h input.h inputtype.h main.h node.h scope.h
|
||||
typequiv.o: LLlex.h debug.h def.h node.h type.h
|
||||
node.o: LLlex.h debug.h def.h node.h type.h
|
||||
cstoper.o: LLlex.h Lpars.h debug.h idf.h node.h standards.h target_sizes.h type.h
|
||||
|
@ -145,7 +153,7 @@ casestat.o: LLlex.h Lpars.h debug.h density.h desig.h node.h type.h walk.h
|
|||
desig.o: LLlex.h debug.h def.h desig.h node.h scope.h type.h
|
||||
code.o: LLlex.h Lpars.h debug.h def.h desig.h node.h scope.h standards.h type.h walk.h
|
||||
tmpvar.o: debug.h def.h main.h scope.h type.h
|
||||
lookup.o: LLlex.h debug.h def.h idf.h node.h scope.h
|
||||
lookup.o: LLlex.h debug.h def.h idf.h node.h scope.h type.h
|
||||
tokenfile.o: Lpars.h
|
||||
program.o: LLlex.h Lpars.h debug.h def.h f_info.h idf.h main.h node.h scope.h type.h
|
||||
declar.o: LLlex.h Lpars.h chk_expr.h debug.h def.h idf.h main.h misc.h node.h scope.h type.h
|
||||
|
|
|
@ -34,13 +34,13 @@
|
|||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT SZ_SHORT
|
||||
#define AL_WORD SZ_WORD
|
||||
#define AL_INT SZ_WORD
|
||||
#define AL_LONG SZ_WORD
|
||||
#define AL_FLOAT SZ_WORD
|
||||
#define AL_DOUBLE SZ_WORD
|
||||
#define AL_POINTER SZ_WORD
|
||||
#define AL_SHORT (int)SZ_SHORT
|
||||
#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
|
||||
#define AL_UNION 1
|
||||
|
||||
|
@ -55,7 +55,7 @@ extern char options[];
|
|||
#endif DEBUG
|
||||
|
||||
!File: inputtype.h
|
||||
#undef INP_READ_IN_ONE 1 /* read input file in one */
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: maxset.h
|
||||
|
|
|
@ -19,10 +19,10 @@ then
|
|||
:
|
||||
else mkdir ../Xsrc
|
||||
fi
|
||||
make cclash
|
||||
make cid
|
||||
./cclash -c -l7 `cat Cfiles` > clashes
|
||||
sed '/^C_/d' < clashes > ../Xsrc/Xclashes
|
||||
make cclash clashes cid
|
||||
sed '/^C_/d' < clashes > tmp$$
|
||||
./cclash -c -l7 tmp$$ > ../Xsrc/Xclashes
|
||||
rm -f tmp$$
|
||||
cd ../Xsrc
|
||||
if cmp -s Xclashes clashes
|
||||
then
|
||||
|
|
1
lang/m2/comp/Version.c
Normal file
1
lang/m2/comp/Version.c
Normal file
|
@ -0,0 +1 @@
|
|||
char Version[] = "Version 0.5";
|
|
@ -1,8 +1,11 @@
|
|||
/* C A S E S T A T E M E N T C O D E G E N E R A T I O N */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
/* Generation of case statements is done by first creating a
|
||||
description structure for the statement, build a list of the
|
||||
case-labels, then generating a case description in the code,
|
||||
and generating either CSA or CSB, and then generating code for the
|
||||
cases themselves.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -22,30 +25,32 @@ static char *RcsId = "$Header$";
|
|||
#include "density.h"
|
||||
|
||||
struct switch_hdr {
|
||||
struct switch_hdr *next;
|
||||
label sh_break;
|
||||
label sh_default;
|
||||
int sh_nrofentries;
|
||||
struct type *sh_type;
|
||||
arith sh_lowerbd;
|
||||
arith sh_upperbd;
|
||||
struct case_entry *sh_entries;
|
||||
struct switch_hdr *next; /* in the free list */
|
||||
label sh_break; /* label of statement after this one */
|
||||
label sh_default; /* label of ELSE part, or 0 */
|
||||
int sh_nrofentries; /* number of cases */
|
||||
struct type *sh_type; /* type of case expression */
|
||||
arith sh_lowerbd; /* lowest case label */
|
||||
arith sh_upperbd; /* highest case label */
|
||||
struct case_entry *sh_entries; /* the cases with their generated
|
||||
labels
|
||||
*/
|
||||
};
|
||||
|
||||
/* STATICALLOCDEF "switch_hdr" */
|
||||
/* STATICALLOCDEF "switch_hdr" 5 */
|
||||
|
||||
struct case_entry {
|
||||
struct case_entry *next;
|
||||
label ce_label;
|
||||
arith ce_value;
|
||||
struct case_entry *next; /* next in list */
|
||||
label ce_label; /* generated label */
|
||||
arith ce_value; /* value of case label */
|
||||
};
|
||||
|
||||
/* STATICALLOCDEF "case_entry" */
|
||||
/* STATICALLOCDEF "case_entry" 20 */
|
||||
|
||||
/* The constant DENSITY determines when CSA and when CSB instructions
|
||||
are generated. Reasonable values are: 2, 3, 4.
|
||||
On machines that have lots of address space and memory, higher values
|
||||
are also reasonable. On these machines the density of jump tables
|
||||
might also be reasonable. On these machines the density of jump tables
|
||||
may be lower.
|
||||
*/
|
||||
#define compact(nr, low, up) (nr != 0 && (up - low) / nr <= DENSITY)
|
||||
|
@ -56,30 +61,36 @@ CaseCode(nd, exitlabel)
|
|||
{
|
||||
/* Check the expression, stack a new case header and
|
||||
fill in the necessary fields.
|
||||
"exitlabel" is the exit-label of the closest enclosing
|
||||
LOOP-statement, or 0.
|
||||
*/
|
||||
register struct switch_hdr *sh = new_switch_hdr();
|
||||
register struct node *pnode = nd;
|
||||
register struct case_entry *ce;
|
||||
register arith val;
|
||||
label tablabel;
|
||||
label CaseDescrLab;
|
||||
|
||||
assert(pnode->nd_class == Stat && pnode->nd_symb == CASE);
|
||||
|
||||
clear((char *) sh, sizeof(*sh));
|
||||
WalkExpr(pnode->nd_left);
|
||||
WalkExpr(pnode->nd_left); /* evaluate case expression */
|
||||
sh->sh_type = pnode->nd_left->nd_type;
|
||||
sh->sh_break = ++text_label;
|
||||
|
||||
/* Now, create case label list
|
||||
*/
|
||||
while (pnode && pnode->nd_right) {
|
||||
while (pnode->nd_right) {
|
||||
pnode = pnode->nd_right;
|
||||
if (pnode->nd_class == Link && pnode->nd_symb == '|') {
|
||||
if (pnode->nd_left) {
|
||||
/* non-empty case
|
||||
*/
|
||||
pnode->nd_lab = ++text_label;
|
||||
if (! AddCases(sh,
|
||||
if (! AddCases(sh, /* to descriptor */
|
||||
pnode->nd_left->nd_left,
|
||||
pnode->nd_lab)) {
|
||||
/* of case labels */
|
||||
pnode->nd_lab
|
||||
/* and code label */
|
||||
)) {
|
||||
FreeSh(sh);
|
||||
return;
|
||||
}
|
||||
|
@ -90,19 +101,20 @@ CaseCode(nd, exitlabel)
|
|||
*/
|
||||
|
||||
sh->sh_default = ++text_label;
|
||||
pnode = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now generate code for the switch itself
|
||||
First the part that CSA and CSB descriptions have in common.
|
||||
*/
|
||||
tablabel = ++data_label; /* the rom must have a label */
|
||||
C_df_dlb(tablabel);
|
||||
CaseDescrLab = ++data_label; /* the rom must have a label */
|
||||
C_df_dlb(CaseDescrLab);
|
||||
if (sh->sh_default) C_rom_ilb(sh->sh_default);
|
||||
else C_rom_ucon("0", pointer_size);
|
||||
if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
|
||||
/* CSA */
|
||||
|
||||
/* CSA
|
||||
*/
|
||||
C_rom_cst(sh->sh_lowerbd);
|
||||
C_rom_cst(sh->sh_upperbd - sh->sh_lowerbd);
|
||||
ce = sh->sh_entries;
|
||||
|
@ -115,24 +127,27 @@ CaseCode(nd, exitlabel)
|
|||
else if (sh->sh_default) C_rom_ilb(sh->sh_default);
|
||||
else C_rom_ucon("0", pointer_size);
|
||||
}
|
||||
C_lae_dlb(tablabel, (arith)0); /* perform the switch */
|
||||
C_lae_dlb(CaseDescrLab, (arith)0); /* perform the switch */
|
||||
C_csa(word_size);
|
||||
}
|
||||
else { /* CSB */
|
||||
else {
|
||||
/* CSB
|
||||
*/
|
||||
C_rom_cst((arith)sh->sh_nrofentries);
|
||||
for (ce = sh->sh_entries; ce; ce = ce->next) {
|
||||
/* generate the entries: value + prog.label */
|
||||
/* generate the entries: value + prog.label
|
||||
*/
|
||||
C_rom_cst(ce->ce_value);
|
||||
C_rom_ilb(ce->ce_label);
|
||||
}
|
||||
C_lae_dlb(tablabel, (arith)0); /* perform the switch */
|
||||
C_lae_dlb(CaseDescrLab, (arith)0); /* perform the switch */
|
||||
C_csb(word_size);
|
||||
}
|
||||
|
||||
/* Now generate code for the cases
|
||||
*/
|
||||
pnode = nd;
|
||||
while (pnode && pnode->nd_right) {
|
||||
while (pnode->nd_right) {
|
||||
pnode = pnode->nd_right;
|
||||
if (pnode->nd_class == Link && pnode->nd_symb == '|') {
|
||||
if (pnode->nd_left) {
|
||||
|
@ -148,7 +163,7 @@ CaseCode(nd, exitlabel)
|
|||
|
||||
C_df_ilb(sh->sh_default);
|
||||
WalkNode(pnode, exitlabel);
|
||||
pnode = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,7 +172,7 @@ CaseCode(nd, exitlabel)
|
|||
}
|
||||
|
||||
FreeSh(sh)
|
||||
struct switch_hdr *sh;
|
||||
register struct switch_hdr *sh;
|
||||
{
|
||||
/* free the allocated switch structure
|
||||
*/
|
||||
|
@ -176,7 +191,7 @@ FreeSh(sh)
|
|||
|
||||
AddCases(sh, node, lbl)
|
||||
struct switch_hdr *sh;
|
||||
struct node *node;
|
||||
register struct node *node;
|
||||
label lbl;
|
||||
{
|
||||
/* Add case labels to the case label list
|
||||
|
@ -208,7 +223,7 @@ AddCases(sh, node, lbl)
|
|||
|
||||
AddOneCase(sh, node, lbl)
|
||||
register struct switch_hdr *sh;
|
||||
struct node *node;
|
||||
register struct node *node;
|
||||
label lbl;
|
||||
{
|
||||
register struct case_entry *ce = new_case_entry();
|
||||
|
@ -222,15 +237,17 @@ AddOneCase(sh, node, lbl)
|
|||
return 0;
|
||||
}
|
||||
if (sh->sh_entries == 0) {
|
||||
/* first case entry */
|
||||
/* first case entry
|
||||
*/
|
||||
ce->next = (struct case_entry *) 0;
|
||||
sh->sh_entries = ce;
|
||||
sh->sh_lowerbd = sh->sh_upperbd = ce->ce_value;
|
||||
sh->sh_nrofentries = 1;
|
||||
}
|
||||
else {
|
||||
/* second etc. case entry */
|
||||
/* find the proper place to put ce into the list */
|
||||
/* second etc. case entry
|
||||
find the proper place to put ce into the list
|
||||
*/
|
||||
|
||||
if (ce->ce_value < sh->sh_lowerbd) {
|
||||
sh->sh_lowerbd = ce->ce_value;
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* E X P R E S S I O N C H E C K I N G */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
/* Check expressions, and try to evaluate them as far as possible.
|
||||
*/
|
||||
|
||||
|
@ -31,6 +27,9 @@ int
|
|||
ChkVariable(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* Check that "expp" indicates an item that can be
|
||||
assigned to.
|
||||
*/
|
||||
|
||||
if (! ChkDesignator(expp)) return 0;
|
||||
|
||||
|
@ -47,6 +46,9 @@ STATIC int
|
|||
ChkArrow(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* Check an application of the '^' operator.
|
||||
The operand must be a variable of a pointer type.
|
||||
*/
|
||||
register struct type *tp;
|
||||
|
||||
assert(expp->nd_class == Arrow);
|
||||
|
@ -59,8 +61,7 @@ ChkArrow(expp)
|
|||
tp = expp->nd_right->nd_type;
|
||||
|
||||
if (tp->tp_fund != T_POINTER) {
|
||||
node_error(expp, "illegal operand for unary operator \"%s\"",
|
||||
symbol2str(expp->nd_symb));
|
||||
node_error(expp, "illegal operand for unary operator \"^\"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -72,6 +73,12 @@ STATIC int
|
|||
ChkArr(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* Check an array selection.
|
||||
The left hand side must be a variable of an array type,
|
||||
and the right hand side must be an expression that is
|
||||
assignment compatible with the array-index.
|
||||
*/
|
||||
|
||||
register struct type *tpl, *tpr;
|
||||
|
||||
assert(expp->nd_class == Arrsel);
|
||||
|
@ -91,7 +98,7 @@ ChkArr(expp)
|
|||
tpr = expp->nd_right->nd_type;
|
||||
|
||||
if (tpl->tp_fund != T_ARRAY) {
|
||||
node_error(expp, "array index not belonging to an ARRAY");
|
||||
node_error(expp, "not indexing an ARRAY type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -110,6 +117,7 @@ ChkArr(expp)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
STATIC int
|
||||
ChkValue(expp)
|
||||
struct node *expp;
|
||||
|
@ -125,11 +133,15 @@ ChkValue(expp)
|
|||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC int
|
||||
ChkLinkOrName(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* Check either an ID or a construction of the form
|
||||
ID.ID [ .ID ]*
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
expp->nd_type = error_type;
|
||||
|
@ -140,6 +152,9 @@ ChkLinkOrName(expp)
|
|||
expp->nd_type = RemoveEqual(expp->nd_def->df_type);
|
||||
}
|
||||
else if (expp->nd_class == Link) {
|
||||
/* A selection from a record or a module.
|
||||
Modules also have a record type.
|
||||
*/
|
||||
register struct node *left = expp->nd_left;
|
||||
|
||||
assert(expp->nd_symb == '.');
|
||||
|
@ -188,16 +203,17 @@ df->df_idf->id_text);
|
|||
if (df->df_kind == D_ERROR) return 0;
|
||||
|
||||
if (df->df_kind & (D_ENUM | D_CONST)) {
|
||||
/* Replace an enum-literal or a CONST identifier by its value.
|
||||
*/
|
||||
if (df->df_kind == D_ENUM) {
|
||||
expp->nd_class = Value;
|
||||
expp->nd_INT = df->enm_val;
|
||||
expp->nd_symb = INTEGER;
|
||||
}
|
||||
else {
|
||||
unsigned int ln;
|
||||
unsigned int ln = expp->nd_lineno;
|
||||
|
||||
assert(df->df_kind == D_CONST);
|
||||
ln = expp->nd_lineno;
|
||||
*expp = *(df->con_const);
|
||||
expp->nd_lineno = ln;
|
||||
}
|
||||
|
@ -210,25 +226,28 @@ STATIC int
|
|||
ChkExLinkOrName(expp)
|
||||
register struct node *expp;
|
||||
{
|
||||
/* Check either an ID or an ID.ID [.ID]* occurring in an
|
||||
expression.
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
if (! ChkLinkOrName(expp)) return 0;
|
||||
if (expp->nd_class != Def) return 1;
|
||||
df = expp->nd_def;
|
||||
|
||||
if (!(df->df_kind & (D_ENUM|D_CONST|D_PROCEDURE|D_FIELD|D_VARIABLE|D_PROCHEAD))) {
|
||||
if (!(df->df_kind & D_VALUE)) {
|
||||
node_error(expp, "value expected");
|
||||
}
|
||||
|
||||
if (df->df_kind == D_PROCEDURE) {
|
||||
/* Check that this procedure is one that we
|
||||
may take the address from.
|
||||
/* Check that this procedure is one that we may take the
|
||||
address from.
|
||||
*/
|
||||
if (df->df_type == std_type || df->df_scope->sc_level > 0) {
|
||||
/* Address of standard or nested procedure
|
||||
taken.
|
||||
*/
|
||||
node_error(expp, "it is illegal to take the address of a standard or local procedure");
|
||||
node_error(expp, "standard or local procedures may not be assigned");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -236,20 +255,6 @@ node_error(expp, "it is illegal to take the address of a standard or local proce
|
|||
return 1;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
RemoveSet(set)
|
||||
arith **set;
|
||||
{
|
||||
/* This routine is only used for error exits of ChkElement.
|
||||
It frees the set indicated by "set", and returns 0.
|
||||
*/
|
||||
if (*set) {
|
||||
free((char *) *set);
|
||||
*set = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
ChkElement(expp, tp, set)
|
||||
register struct node *expp;
|
||||
|
@ -279,7 +284,7 @@ ChkElement(expp, tp, set)
|
|||
|
||||
if (left->nd_INT > right->nd_INT) {
|
||||
node_error(expp, "lower bound exceeds upper bound in range");
|
||||
return RemoveSet(set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*set) {
|
||||
|
@ -298,28 +303,24 @@ node_error(expp, "lower bound exceeds upper bound in range");
|
|||
|
||||
/* Here, a single element is checked
|
||||
*/
|
||||
if (!ChkExpression(expp)) {
|
||||
return RemoveSet(set);
|
||||
}
|
||||
if (!ChkExpression(expp)) return 0;
|
||||
|
||||
if (!TstCompat(tp, expp->nd_type)) {
|
||||
node_error(expp, "set element has incompatible type");
|
||||
return RemoveSet(set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (expp->nd_class == Value) {
|
||||
/* a constant element
|
||||
*/
|
||||
i = expp->nd_INT;
|
||||
arith low, high;
|
||||
|
||||
if ((tp->tp_fund != T_ENUMERATION &&
|
||||
(i < tp->sub_lb || i > tp->sub_ub))
|
||||
||
|
||||
(tp->tp_fund == T_ENUMERATION &&
|
||||
(i < 0 || i > tp->enm_ncst))
|
||||
) {
|
||||
i = expp->nd_INT;
|
||||
getbounds(tp, &low, &high);
|
||||
|
||||
if (i < low || i > high) {
|
||||
node_error(expp, "set element out of range");
|
||||
return RemoveSet(set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*set) (*set)[i/wrd_bits] |= (1 << (i%wrd_bits));
|
||||
|
@ -353,9 +354,11 @@ ChkSet(expp)
|
|||
assert(nd->nd_class == Def);
|
||||
df = nd->nd_def;
|
||||
|
||||
if (!(df->df_kind & (D_TYPE|D_ERROR)) ||
|
||||
if (!is_type(df) ||
|
||||
(df->df_type->tp_fund != T_SET)) {
|
||||
node_error(expp, "specifier does not represent a set type");
|
||||
if (df->df_kind != D_ERROR) {
|
||||
node_error(expp, "type specifier does not represent a set type");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
tp = df->df_type;
|
||||
|
@ -394,7 +397,8 @@ node_error(expp, "specifier does not represent a set type");
|
|||
/* Yes, it was a constant set, and we managed to compute it!
|
||||
Notice that at the moment there is no such thing as
|
||||
partial evaluation. Either we evaluate the set, or we
|
||||
don't (at all). Improvement not neccesary. (???)
|
||||
don't (at all). Improvement not neccesary (???)
|
||||
??? sets have a contant part and a variable part ???
|
||||
*/
|
||||
expp->nd_class = Set;
|
||||
expp->nd_set = set;
|
||||
|
@ -417,7 +421,6 @@ getarg(argp, bases, designator)
|
|||
that it must be a designator and may not be a register
|
||||
variable.
|
||||
*/
|
||||
struct type *tp;
|
||||
register struct node *arg = (*argp)->nd_right;
|
||||
register struct node *left;
|
||||
|
||||
|
@ -437,8 +440,7 @@ getarg(argp, bases, designator)
|
|||
}
|
||||
|
||||
if (bases) {
|
||||
tp = BaseType(left->nd_type);
|
||||
if (!(tp->tp_fund & bases)) {
|
||||
if (!(BaseType(left->nd_type)->tp_fund & bases)) {
|
||||
node_error(arg, "unexpected type");
|
||||
return 0;
|
||||
}
|
||||
|
@ -452,7 +454,12 @@ STATIC struct node *
|
|||
getname(argp, kinds)
|
||||
struct node **argp;
|
||||
{
|
||||
/* Get the next argument from argument list "argp".
|
||||
The argument must indicate a definition, and the
|
||||
definition kind must be one of "kinds".
|
||||
*/
|
||||
register struct node *arg = *argp;
|
||||
register struct node *left;
|
||||
|
||||
if (!arg->nd_right) {
|
||||
node_error(arg, "too few arguments supplied");
|
||||
|
@ -460,25 +467,26 @@ getname(argp, kinds)
|
|||
}
|
||||
|
||||
arg = arg->nd_right;
|
||||
if (! ChkDesignator(arg->nd_left)) return 0;
|
||||
left = arg->nd_left;
|
||||
if (! ChkDesignator(left)) return 0;
|
||||
|
||||
if (arg->nd_left->nd_class != Def && arg->nd_left->nd_class != LinkDef) {
|
||||
if (left->nd_class != Def && left->nd_class != LinkDef) {
|
||||
node_error(arg, "identifier expected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(arg->nd_left->nd_def->df_kind & kinds)) {
|
||||
if (!(left->nd_def->df_kind & kinds)) {
|
||||
node_error(arg, "unexpected type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
*argp = arg;
|
||||
return arg->nd_left;
|
||||
return left;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
ChkProcCall(expp)
|
||||
register struct node *expp;
|
||||
struct node *expp;
|
||||
{
|
||||
/* Check a procedure call
|
||||
*/
|
||||
|
@ -487,11 +495,12 @@ ChkProcCall(expp)
|
|||
register struct paramlist *param;
|
||||
|
||||
left = expp->nd_left;
|
||||
arg = expp;
|
||||
expp->nd_type = RemoveEqual(ResultType(left->nd_type));
|
||||
|
||||
/* Check parameter list
|
||||
*/
|
||||
for (param = ParamList(left->nd_type); param; param = param->next) {
|
||||
if (!(left = getarg(&arg, 0, IsVarParam(param)))) return 0;
|
||||
if (!(left = getarg(&expp, 0, IsVarParam(param)))) return 0;
|
||||
if (left->nd_symb == STRING) {
|
||||
TryToString(left, TypeOfParam(param));
|
||||
}
|
||||
|
@ -504,8 +513,8 @@ node_error(left, "type incompatibility in parameter");
|
|||
}
|
||||
}
|
||||
|
||||
if (arg->nd_right) {
|
||||
node_error(arg->nd_right, "too many parameters supplied");
|
||||
if (expp->nd_right) {
|
||||
node_error(expp->nd_right, "too many parameters supplied");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -517,7 +526,7 @@ ChkCall(expp)
|
|||
register struct node *expp;
|
||||
{
|
||||
/* Check something that looks like a procedure or function call.
|
||||
Of course this does not have to be a call at all.
|
||||
Of course this does not have to be a call at all,
|
||||
it may also be a cast or a standard procedure call.
|
||||
*/
|
||||
register struct node *left;
|
||||
|
@ -531,14 +540,14 @@ ChkCall(expp)
|
|||
if (! ChkDesignator(left)) return 0;
|
||||
|
||||
if (IsCast(left)) {
|
||||
/* It was a type cast. This is of course not portable.
|
||||
/* It was a type cast.
|
||||
*/
|
||||
return ChkCast(expp, left);
|
||||
}
|
||||
|
||||
if (IsProcCall(left)) {
|
||||
/* A procedure call. it may also be a call to a
|
||||
standard procedure
|
||||
/* A procedure call.
|
||||
It may also be a call to a standard procedure
|
||||
*/
|
||||
if (left->nd_type == std_type) {
|
||||
/* A standard procedure
|
||||
|
@ -559,6 +568,10 @@ STATIC struct type *
|
|||
ResultOfOperation(operator, tp)
|
||||
struct type *tp;
|
||||
{
|
||||
/* Return the result type of the binary operation "operator",
|
||||
with operand type "tp".
|
||||
*/
|
||||
|
||||
switch(operator) {
|
||||
case '=':
|
||||
case '#':
|
||||
|
@ -582,6 +595,10 @@ Boolean(operator)
|
|||
STATIC int
|
||||
AllowedTypes(operator)
|
||||
{
|
||||
/* Return a bit mask indicating the allowed operand types
|
||||
for binary operator "operator".
|
||||
*/
|
||||
|
||||
switch(operator) {
|
||||
case '+':
|
||||
case '-':
|
||||
|
@ -615,13 +632,17 @@ STATIC int
|
|||
ChkAddress(tpl, tpr)
|
||||
register struct type *tpl, *tpr;
|
||||
{
|
||||
/* Check that either "tpl" or "tpr" are both of type
|
||||
address_type, or that one of them is, but the other is
|
||||
of type cardinal.
|
||||
*/
|
||||
|
||||
if (tpl == address_type) {
|
||||
return tpr == address_type || tpr->tp_fund != T_POINTER;
|
||||
return tpr == address_type || (tpr->tp_fund & T_CARDINAL);
|
||||
}
|
||||
|
||||
if (tpr == address_type) {
|
||||
return tpl->tp_fund != T_POINTER;
|
||||
return (tpl->tp_fund & T_CARDINAL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -656,21 +677,26 @@ ChkBinOper(expp)
|
|||
}
|
||||
}
|
||||
|
||||
expp->nd_type = ResultOfOperation(expp->nd_symb, tpl);
|
||||
expp->nd_type = ResultOfOperation(expp->nd_symb, tpr);
|
||||
|
||||
/* Check that the application of the operator is allowed on the type
|
||||
of the operands.
|
||||
There are three tricky parts:
|
||||
- Boolean operators are only allowed on boolean operands, but
|
||||
the "allowed-mask" of "AllowedTypes" can only indicate
|
||||
an enumeration type.
|
||||
- All operations that are allowed on CARDINALS are also allowed
|
||||
on ADDRESS.
|
||||
- The IN-operator has as right-hand-size operand a set.
|
||||
*/
|
||||
if (expp->nd_symb == IN) {
|
||||
/* Handle this one specially */
|
||||
if (tpr->tp_fund != T_SET) {
|
||||
node_error(expp, "RHS of IN operator not a SET type");
|
||||
return 0;
|
||||
}
|
||||
if (!TstAssCompat(tpl, ElementType(tpr))) {
|
||||
/* Assignment compatible ???
|
||||
I don't know! Should we be allowed to check
|
||||
if a CARDINAL is a member of a BITSET???
|
||||
*/
|
||||
|
||||
node_error(expp, "IN operator: type of LHS not compatible with element type of RHS");
|
||||
node_error(expp, "incompatible types for operator \"IN\"");
|
||||
return 0;
|
||||
}
|
||||
if (left->nd_class == Value && right->nd_class == Set) {
|
||||
|
@ -679,6 +705,25 @@ node_error(expp, "IN operator: type of LHS not compatible with element type of R
|
|||
return 1;
|
||||
}
|
||||
|
||||
allowed = AllowedTypes(expp->nd_symb);
|
||||
|
||||
if (!(tpr->tp_fund & allowed) || !(tpl->tp_fund & allowed)) {
|
||||
if (!((T_CARDINAL & allowed) &&
|
||||
ChkAddress(tpl, tpr))) {
|
||||
node_error(expp,"operator \"%s\": illegal operand type(s)", symbol2str(expp->nd_symb));
|
||||
return 0;
|
||||
}
|
||||
if (expp->nd_type->tp_fund & T_CARDINAL) {
|
||||
expp->nd_type = address_type;
|
||||
}
|
||||
}
|
||||
|
||||
if (Boolean(expp->nd_symb) && tpl != bool_type) {
|
||||
node_error(expp,"operator \"%s\": illegal operand type(s)", symbol2str(expp->nd_symb));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Operands must be compatible (distilled from Def 8.2)
|
||||
*/
|
||||
if (!TstCompat(tpl, tpr)) {
|
||||
|
@ -687,32 +732,6 @@ node_error(expp, "IN operator: type of LHS not compatible with element type of R
|
|||
return 0;
|
||||
}
|
||||
|
||||
allowed = AllowedTypes(expp->nd_symb);
|
||||
|
||||
/* Check that the application of the operator is allowed on the type
|
||||
of the operands.
|
||||
There are two tricky parts:
|
||||
- Boolean operators are only allowed on boolean operands, but
|
||||
the "allowed-mask" of "AllowedTypes" can only indicate
|
||||
an enumeration type.
|
||||
- All operations that are allowed on CARDINALS are also allowed
|
||||
on ADDRESS.
|
||||
*/
|
||||
if (Boolean(expp->nd_symb) && tpl != bool_type) {
|
||||
node_error(expp,"operator \"%s\": illegal operand type(s)", symbol2str(expp->nd_symb));
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (!(tpl->tp_fund & allowed)) {
|
||||
if (!(tpl->tp_fund == T_POINTER &&
|
||||
(T_CARDINAL & allowed) &&
|
||||
ChkAddress(tpl, tpr))) {
|
||||
node_error(expp,"operator \"%s\": illegal operand type(s)", symbol2str(expp->nd_symb));
|
||||
return 0;
|
||||
}
|
||||
if (expp->nd_type == card_type) expp->nd_type = address_type;
|
||||
}
|
||||
|
||||
if (tpl->tp_fund == T_SET) {
|
||||
if (left->nd_class == Set && right->nd_class == Set) {
|
||||
cstset(expp);
|
||||
|
@ -737,9 +756,8 @@ ChkUnOper(expp)
|
|||
|
||||
if (! ChkExpression(right)) return 0;
|
||||
|
||||
tpr = BaseType(right->nd_type);
|
||||
expp->nd_type = tpr = BaseType(right->nd_type);
|
||||
if (tpr == address_type) tpr = card_type;
|
||||
expp->nd_type = tpr;
|
||||
|
||||
switch(expp->nd_symb) {
|
||||
case '+':
|
||||
|
@ -799,6 +817,9 @@ STATIC struct node *
|
|||
getvariable(argp)
|
||||
struct node **argp;
|
||||
{
|
||||
/* Get the next argument from argument list "argp".
|
||||
It must obey the rules of "ChkVariable".
|
||||
*/
|
||||
register struct node *arg = *argp;
|
||||
|
||||
arg = arg->nd_right;
|
||||
|
@ -807,10 +828,11 @@ getvariable(argp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (! ChkVariable(arg->nd_left)) return 0;
|
||||
|
||||
*argp = arg;
|
||||
return arg->nd_left;
|
||||
arg = arg->nd_left;
|
||||
if (! ChkVariable(arg)) return 0;
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -1104,7 +1126,11 @@ done_before(expp)
|
|||
extern int NodeCrash();
|
||||
|
||||
int (*ExprChkTable[])() = {
|
||||
#ifdef DEBUG
|
||||
ChkValue,
|
||||
#else
|
||||
done_before,
|
||||
#endif
|
||||
ChkArr,
|
||||
ChkBinOper,
|
||||
ChkUnOper,
|
||||
|
@ -1120,7 +1146,11 @@ int (*ExprChkTable[])() = {
|
|||
};
|
||||
|
||||
int (*DesigChkTable[])() = {
|
||||
#ifdef DEBUG
|
||||
ChkValue,
|
||||
#else
|
||||
done_before,
|
||||
#endif
|
||||
ChkArr,
|
||||
no_desig,
|
||||
no_desig,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* E X P R E S S I O N C H E C K I N G */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
extern int (*ExprChkTable[])(); /* table of expression checking
|
||||
functions, indexed by node class
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* 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.
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* C O D E G E N E R A T I O N R O U T I N E S */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
/* Code generation for expressions and coercions
|
||||
*/
|
||||
|
||||
|
@ -34,7 +30,6 @@ CodeConst(cst, size)
|
|||
{
|
||||
/* Generate code to push constant "cst" with size "size"
|
||||
*/
|
||||
label dlab;
|
||||
|
||||
if (size <= word_size) {
|
||||
C_loc(cst);
|
||||
|
@ -43,23 +38,28 @@ CodeConst(cst, size)
|
|||
C_ldc(cst);
|
||||
}
|
||||
else {
|
||||
C_df_dlb(dlab = ++data_label);
|
||||
crash("(CodeConst)");
|
||||
/*
|
||||
label dlab = ++data_label;
|
||||
|
||||
C_df_dlb(dlab);
|
||||
C_rom_icon(long2str((long) cst), size);
|
||||
C_lae_dlb(dlab, (arith) 0);
|
||||
C_loi(size);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
CodeString(nd)
|
||||
register struct node *nd;
|
||||
{
|
||||
label lab;
|
||||
|
||||
if (nd->nd_type->tp_fund != T_STRING) {
|
||||
C_loc(nd->nd_INT);
|
||||
}
|
||||
else {
|
||||
C_df_dlb(lab = ++data_label);
|
||||
label lab = ++data_label;
|
||||
|
||||
C_df_dlb(lab);
|
||||
C_rom_scon(nd->nd_STR, WA(nd->nd_SLE + 1));
|
||||
C_lae_dlb(lab, (arith) 0);
|
||||
}
|
||||
|
@ -85,16 +85,6 @@ CodePadString(nd, sz)
|
|||
C_loi(sizearg);
|
||||
}
|
||||
|
||||
CodeReal(nd)
|
||||
register struct node *nd;
|
||||
{
|
||||
label lab = ++data_label;
|
||||
|
||||
C_df_dlb(lab);
|
||||
C_rom_fcon(nd->nd_REL, nd->nd_type->tp_size);
|
||||
C_lae_dlb(lab, (arith) 0);
|
||||
C_loi(nd->nd_type->tp_size);
|
||||
}
|
||||
|
||||
CodeExpr(nd, ds, true_label, false_label)
|
||||
register struct node *nd;
|
||||
|
@ -136,8 +126,14 @@ CodeExpr(nd, ds, true_label, false_label)
|
|||
|
||||
case Value:
|
||||
switch(nd->nd_symb) {
|
||||
case REAL:
|
||||
CodeReal(nd);
|
||||
case REAL: {
|
||||
label lab = ++data_label;
|
||||
|
||||
C_df_dlb(lab);
|
||||
C_rom_fcon(nd->nd_REL, nd->nd_type->tp_size);
|
||||
C_lae_dlb(lab, (arith) 0);
|
||||
C_loi(nd->nd_type->tp_size);
|
||||
}
|
||||
break;
|
||||
case STRING:
|
||||
CodeString(nd);
|
||||
|
@ -157,8 +153,8 @@ CodeExpr(nd, ds, true_label, false_label)
|
|||
break;
|
||||
|
||||
case Set: {
|
||||
arith *st;
|
||||
int i;
|
||||
register arith *st = nd->nd_set;
|
||||
register int i;
|
||||
|
||||
st = nd->nd_set;
|
||||
ds->dsg_kind = DSG_LOADED;
|
||||
|
@ -182,6 +178,8 @@ CodeExpr(nd, ds, true_label, false_label)
|
|||
}
|
||||
|
||||
if (true_label != 0) {
|
||||
/* Only for boolean expressions
|
||||
*/
|
||||
CodeValue(ds, tp->tp_size);
|
||||
*ds = InitDesig;
|
||||
C_zne(true_label);
|
||||
|
@ -293,6 +291,7 @@ CodeCall(nd)
|
|||
and result is already done.
|
||||
*/
|
||||
register struct node *left = nd->nd_left;
|
||||
register struct node *right = nd->nd_right;
|
||||
register struct type *result_tp;
|
||||
|
||||
if (left->nd_type == std_type) {
|
||||
|
@ -303,16 +302,16 @@ CodeCall(nd)
|
|||
if (IsCast(left)) {
|
||||
/* it was just a cast. Simply ignore it
|
||||
*/
|
||||
CodePExpr(nd->nd_right->nd_left);
|
||||
*nd = *(nd->nd_right->nd_left);
|
||||
CodePExpr(right->nd_left);
|
||||
*nd = *(right->nd_left);
|
||||
nd->nd_type = left->nd_def->df_type;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(IsProcCall(left));
|
||||
|
||||
if (nd->nd_right) {
|
||||
CodeParameters(ParamList(left->nd_type), nd->nd_right);
|
||||
if (right) {
|
||||
CodeParameters(ParamList(left->nd_type), right);
|
||||
}
|
||||
|
||||
switch(left->nd_class) {
|
||||
|
@ -387,11 +386,9 @@ CodeParameters(param, arg)
|
|||
C_loc((left_type->tp_size+word_size-1) / word_size - 1);
|
||||
}
|
||||
else {
|
||||
tp = IndexType(left_type);
|
||||
if (tp->tp_fund == T_SUBRANGE) {
|
||||
C_loc(tp->sub_ub - tp->sub_lb);
|
||||
}
|
||||
else C_loc((arith) (tp->enm_ncst - 1));
|
||||
arith lb, ub;
|
||||
getbounds(IndexType(left_type), &lb, &ub);
|
||||
C_loc(ub - lb);
|
||||
}
|
||||
C_loc((arith) 0);
|
||||
if (left->nd_symb == STRING) {
|
||||
|
@ -417,7 +414,7 @@ CodeStd(nd)
|
|||
register struct node *arg = nd->nd_right;
|
||||
register struct node *left = 0;
|
||||
register struct type *tp = 0;
|
||||
int std;
|
||||
int std = nd->nd_left->nd_def->df_value.df_stdname;
|
||||
|
||||
if (arg) {
|
||||
left = arg->nd_left;
|
||||
|
@ -425,7 +422,7 @@ CodeStd(nd)
|
|||
arg = arg->nd_right;
|
||||
}
|
||||
|
||||
switch(std = nd->nd_left->nd_def->df_value.df_stdname) {
|
||||
switch(std) {
|
||||
case S_ABS:
|
||||
CodePExpr(left);
|
||||
if (tp->tp_fund == T_INTEGER) {
|
||||
|
@ -446,7 +443,7 @@ CodeStd(nd)
|
|||
|
||||
case S_CAP:
|
||||
CodePExpr(left);
|
||||
C_loc((arith) 0137);
|
||||
C_loc((arith) 0137); /* ASCII assumed */
|
||||
C_and(word_size);
|
||||
break;
|
||||
|
||||
|
@ -498,34 +495,25 @@ CodeStd(nd)
|
|||
break;
|
||||
|
||||
case S_DEC:
|
||||
case S_INC:
|
||||
case S_INC: {
|
||||
register arith size = tp->tp_size;
|
||||
|
||||
if (size < word_size) size = word_size;
|
||||
CodePExpr(left);
|
||||
if (arg) CodePExpr(arg->nd_left);
|
||||
else C_loc((arith) 1);
|
||||
if (tp->tp_size <= word_size) {
|
||||
if (std == S_DEC) {
|
||||
if (tp->tp_fund == T_INTEGER) C_sbi(word_size);
|
||||
else C_sbu(word_size);
|
||||
}
|
||||
else {
|
||||
if (tp->tp_fund == T_INTEGER) C_adi(word_size);
|
||||
else C_adu(word_size);
|
||||
}
|
||||
RangeCheck(tp, int_type);
|
||||
if (std == S_DEC) {
|
||||
if (tp->tp_fund == T_INTEGER) C_sbi(size);
|
||||
else C_sbu(size);
|
||||
}
|
||||
else {
|
||||
CodeCoercion(int_type, tp);
|
||||
if (std == S_DEC) {
|
||||
if (tp->tp_fund==T_INTEGER) C_sbi(tp->tp_size);
|
||||
else C_sbu(tp->tp_size);
|
||||
}
|
||||
else {
|
||||
if (tp->tp_fund==T_INTEGER) C_adi(tp->tp_size);
|
||||
else C_adu(tp->tp_size);
|
||||
}
|
||||
if (tp->tp_fund == T_INTEGER) C_adi(size);
|
||||
else C_adu(size);
|
||||
}
|
||||
if (size == word_size) RangeCheck(tp, int_type);
|
||||
CodeDStore(left);
|
||||
break;
|
||||
}
|
||||
|
||||
case S_HALT:
|
||||
C_cal("_halt");
|
||||
|
@ -552,29 +540,30 @@ CodeStd(nd)
|
|||
}
|
||||
|
||||
CodeAssign(nd, dss, dst)
|
||||
struct node *nd;
|
||||
register struct node *nd;
|
||||
struct desig *dst, *dss;
|
||||
{
|
||||
/* Generate code for an assignment. Testing of type
|
||||
compatibility and the like is already done.
|
||||
*/
|
||||
register struct type *tp = nd->nd_right->nd_type;
|
||||
arith size = nd->nd_left->nd_type->tp_size;
|
||||
|
||||
if (dss->dsg_kind == DSG_LOADED) {
|
||||
if (tp->tp_fund == T_STRING) {
|
||||
CodeAddress(dst);
|
||||
C_loc(tp->tp_size);
|
||||
C_loc(nd->nd_left->nd_type->tp_size);
|
||||
C_loc(size);
|
||||
C_cal("_StringAssign");
|
||||
C_asp((int_size << 1) + (pointer_size << 1));
|
||||
return;
|
||||
}
|
||||
CodeStore(dst, nd->nd_left->nd_type->tp_size);
|
||||
CodeStore(dst, size);
|
||||
return;
|
||||
}
|
||||
CodeAddress(dss);
|
||||
CodeAddress(dst);
|
||||
C_blm(nd->nd_left->nd_type->tp_size);
|
||||
C_blm(size);
|
||||
}
|
||||
|
||||
RangeCheck(tpl, tpr)
|
||||
|
@ -593,7 +582,10 @@ RangeCheck(tpl, tpr)
|
|||
}
|
||||
else {
|
||||
/* both types are restricted. check the bounds
|
||||
to see wether we need a range check
|
||||
to see wether we need a range check.
|
||||
We don't need one if the range of values of the
|
||||
right hand side is a subset of the range of values
|
||||
of the left hand side.
|
||||
*/
|
||||
getbounds(tpl, &llo, &lhi);
|
||||
getbounds(tpr, &rlo, &rhi);
|
||||
|
@ -806,6 +798,7 @@ CodeOper(expr, true_label, false_label)
|
|||
C_bra(false_label);
|
||||
}
|
||||
break;
|
||||
case OR:
|
||||
case AND:
|
||||
case '&': {
|
||||
label l_true, l_false, l_maybe = ++text_label, l_end;
|
||||
|
@ -822,7 +815,10 @@ CodeOper(expr, true_label, false_label)
|
|||
}
|
||||
|
||||
Des = InitDesig;
|
||||
CodeExpr(leftop, &Des, l_maybe, l_false);
|
||||
if (expr->nd_symb == OR) {
|
||||
CodeExpr(leftop, &Des, l_true, l_maybe);
|
||||
}
|
||||
else CodeExpr(leftop, &Des, l_maybe, l_false);
|
||||
C_df_ilb(l_maybe);
|
||||
Des = InitDesig;
|
||||
CodeExpr(rightop, &Des, l_true, l_false);
|
||||
|
@ -836,34 +832,6 @@ CodeOper(expr, true_label, false_label)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case OR: {
|
||||
label l_true, l_false, l_maybe = ++text_label, l_end;
|
||||
struct desig Des;
|
||||
|
||||
if (true_label == 0) {
|
||||
l_true = ++text_label;
|
||||
l_false = ++text_label;
|
||||
l_end = ++text_label;
|
||||
}
|
||||
else {
|
||||
l_true = true_label;
|
||||
l_false = false_label;
|
||||
}
|
||||
Des = InitDesig;
|
||||
CodeExpr(leftop, &Des, l_true, l_maybe);
|
||||
C_df_ilb(l_maybe);
|
||||
Des = InitDesig;
|
||||
CodeExpr(rightop, &Des, l_true, l_false);
|
||||
if (true_label == 0) {
|
||||
C_df_ilb(l_false);
|
||||
C_loc((arith)0);
|
||||
C_bra(l_end);
|
||||
C_df_ilb(l_true);
|
||||
C_loc((arith)1);
|
||||
C_df_ilb(l_end);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
crash("(CodeOper) Bad operator %s\n",symbol2str(expr->nd_symb));
|
||||
}
|
||||
|
@ -958,9 +926,9 @@ CodeUoper(nd)
|
|||
CodeSet(nd)
|
||||
register struct node *nd;
|
||||
{
|
||||
struct type *tp = nd->nd_type;
|
||||
register struct type *tp = nd->nd_type;
|
||||
|
||||
C_zer(nd->nd_type->tp_size); /* empty set */
|
||||
C_zer(tp->tp_size); /* empty set */
|
||||
nd = nd->nd_right;
|
||||
while (nd) {
|
||||
assert(nd->nd_class == Link && nd->nd_symb == ',');
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* C O N S T A N T S F O R E X P R E S S I O N H A N D L I N G */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
extern long
|
||||
mach_long_sign; /* sign bit of the machine long */
|
||||
extern int
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* C O N S T A N T E X P R E S S I O N H A N D L I N G */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "target_sizes.h"
|
||||
|
||||
|
@ -35,8 +31,10 @@ cstunary(expp)
|
|||
register arith o1 = expp->nd_right->nd_INT;
|
||||
|
||||
switch(expp->nd_symb) {
|
||||
/* Should not get here
|
||||
case '+':
|
||||
break;
|
||||
*/
|
||||
|
||||
case '-':
|
||||
o1 = -o1;
|
||||
|
@ -71,7 +69,7 @@ cstbin(expp)
|
|||
*/
|
||||
register arith o1 = expp->nd_left->nd_INT;
|
||||
register arith o2 = expp->nd_right->nd_INT;
|
||||
int uns = expp->nd_type != int_type;
|
||||
register int uns = expp->nd_type != int_type;
|
||||
|
||||
assert(expp->nd_class == Oper);
|
||||
assert(expp->nd_left->nd_class == Value);
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/* D E C L A R A T I O N S */
|
||||
|
||||
{
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
|
@ -23,69 +19,38 @@ static char *RcsId = "$Header$";
|
|||
#include "chk_expr.h"
|
||||
|
||||
int proclevel = 0; /* nesting level of procedures */
|
||||
int return_occurred; /* set if a return occurred in a
|
||||
procedure or function
|
||||
*/
|
||||
int return_occurred; /* set if a return occurs in a block */
|
||||
}
|
||||
|
||||
ProcedureDeclaration
|
||||
{
|
||||
register struct def *df;
|
||||
struct def *df1; /* only exists because &df is illegal */
|
||||
struct def *df;
|
||||
} :
|
||||
{ ++proclevel;
|
||||
return_occurred = 0;
|
||||
}
|
||||
ProcedureHeading(&df1, D_PROCEDURE)
|
||||
{ CurrentScope->sc_definedby = df = df1;
|
||||
df->prc_vis = CurrVis;
|
||||
}
|
||||
';' block(&(df->prc_body)) IDENT
|
||||
{ match_id(dot.TOK_IDF, df->df_idf);
|
||||
close_scope(SC_CHKFORW|SC_REVERSE);
|
||||
if (! return_occurred && ResultType(df->df_type)) {
|
||||
error("function procedure %s does not return a value", df->df_idf->id_text);
|
||||
}
|
||||
{ ++proclevel; }
|
||||
ProcedureHeading(&df, D_PROCEDURE)
|
||||
';' block(&(df->prc_body))
|
||||
IDENT
|
||||
{ EndProc(df, dot.TOK_IDF);
|
||||
--proclevel;
|
||||
}
|
||||
;
|
||||
|
||||
ProcedureHeading(struct def **pdf; int type;)
|
||||
{
|
||||
struct paramlist *params = 0;
|
||||
register struct type *tp;
|
||||
struct type *tp1 = 0;
|
||||
register struct def *df;
|
||||
arith NBytesParams; /* parameter offset counter */
|
||||
struct type *tp = 0;
|
||||
#define needs_static_link() (proclevel > 1)
|
||||
arith parmaddr = needs_static_link() ? pointer_size : 0;
|
||||
struct paramlist *pr = 0;
|
||||
} :
|
||||
PROCEDURE IDENT
|
||||
{ df = DeclProc(type);
|
||||
if (proclevel > 1) { /* need room for static link */
|
||||
NBytesParams = pointer_size;
|
||||
}
|
||||
else NBytesParams = 0;
|
||||
}
|
||||
FormalParameters(¶ms, &tp1, &NBytesParams)?
|
||||
{ tp = construct_type(T_PROCEDURE, tp1);
|
||||
tp->prc_params = params;
|
||||
tp->prc_nbpar = NBytesParams;
|
||||
if (df->df_type) {
|
||||
/* We already saw a definition of this type
|
||||
in the definition module.
|
||||
*/
|
||||
if (!TstProcEquiv(tp, df->df_type)) {
|
||||
error("inconsistent procedure declaration for \"%s\"", df->df_idf->id_text);
|
||||
}
|
||||
FreeType(df->df_type);
|
||||
}
|
||||
df->df_type = tp;
|
||||
*pdf = df;
|
||||
}
|
||||
{ *pdf = DeclProc(type, dot.TOK_IDF); }
|
||||
FormalParameters(&pr, &parmaddr, &tp)?
|
||||
{ CheckWithDef(*pdf, proc_type(tp, pr, parmaddr)); }
|
||||
;
|
||||
|
||||
block(struct node **pnd;) :
|
||||
declaration*
|
||||
[
|
||||
[ { return_occurred = 0; }
|
||||
BEGIN
|
||||
StatementSequence(pnd)
|
||||
|
|
||||
|
@ -106,15 +71,12 @@ declaration:
|
|||
ModuleDeclaration ';'
|
||||
;
|
||||
|
||||
FormalParameters(struct paramlist **pr;
|
||||
struct type **ptp;
|
||||
arith *parmaddr;)
|
||||
:
|
||||
FormalParameters(struct paramlist *ppr; arith *parmaddr; struct type **ptp;):
|
||||
'('
|
||||
[
|
||||
FPSection(pr, parmaddr)
|
||||
FPSection(ppr, parmaddr)
|
||||
[
|
||||
';' FPSection(pr, parmaddr)
|
||||
';' FPSection(ppr, parmaddr)
|
||||
]*
|
||||
]?
|
||||
')'
|
||||
|
@ -134,12 +96,12 @@ FPSection(struct paramlist **ppr; arith *parmaddr;)
|
|||
|
||||
FormalType(struct type **ptp;)
|
||||
{
|
||||
register struct type *tp;
|
||||
extern arith ArrayElSize();
|
||||
} :
|
||||
ARRAY OF qualtype(ptp)
|
||||
{ tp = construct_type(T_ARRAY, NULLTYPE);
|
||||
tp->arr_elem = *ptp; *ptp = tp;
|
||||
{ register struct type *tp = construct_type(T_ARRAY, NULLTYPE);
|
||||
tp->arr_elem = *ptp;
|
||||
*ptp = tp;
|
||||
tp->arr_elsize = ArrayElSize(tp->arr_elem);
|
||||
tp->tp_align = lcm(word_align, pointer_align);
|
||||
}
|
||||
|
@ -194,12 +156,12 @@ SimpleType(struct type **ptp;)
|
|||
enumeration(struct type **ptp;)
|
||||
{
|
||||
struct node *EnumList;
|
||||
register struct type *tp;
|
||||
} :
|
||||
'(' IdentList(&EnumList) ')'
|
||||
{ *ptp = tp = standard_type(T_ENUMERATION, 1, (arith) 1);
|
||||
EnterEnumList(EnumList, tp);
|
||||
if (tp->enm_ncst > 256) { /* ??? is this reasonable ??? */
|
||||
{
|
||||
*ptp = standard_type(T_ENUMERATION, 1, (arith) 1);
|
||||
EnterEnumList(EnumList, *ptp);
|
||||
if ((*ptp)->enm_ncst > 256) { /* ??? is this reasonable ??? */
|
||||
error("Too many enumeration literals");
|
||||
}
|
||||
}
|
||||
|
@ -230,7 +192,10 @@ SubrangeType(struct type **ptp;)
|
|||
'[' ConstExpression(&nd1)
|
||||
UPTO ConstExpression(&nd2)
|
||||
']'
|
||||
{ *ptp = subr_type(nd1, nd2); }
|
||||
{ *ptp = subr_type(nd1, nd2);
|
||||
free_node(nd1);
|
||||
free_node(nd2);
|
||||
}
|
||||
;
|
||||
|
||||
ArrayType(struct type **ptp;)
|
||||
|
@ -254,18 +219,18 @@ ArrayType(struct type **ptp;)
|
|||
RecordType(struct type **ptp;)
|
||||
{
|
||||
register struct scope *scope;
|
||||
arith count;
|
||||
arith size;
|
||||
int xalign = struct_align;
|
||||
}
|
||||
:
|
||||
RECORD
|
||||
{ open_scope(OPENSCOPE);
|
||||
{ open_scope(OPENSCOPE); /* scope for fields of record */
|
||||
scope = CurrentScope;
|
||||
close_scope(0);
|
||||
count = 0;
|
||||
size = 0;
|
||||
}
|
||||
FieldListSequence(scope, &count, &xalign)
|
||||
{ *ptp = standard_type(T_RECORD, xalign, WA(count));
|
||||
FieldListSequence(scope, &size, &xalign)
|
||||
{ *ptp = standard_type(T_RECORD, xalign, WA(size));
|
||||
(*ptp)->rec_scope = scope;
|
||||
}
|
||||
END
|
||||
|
@ -281,10 +246,10 @@ FieldListSequence(struct scope *scope; arith *cnt; int *palign;):
|
|||
FieldList(struct scope *scope; arith *cnt; int *palign;)
|
||||
{
|
||||
struct node *FldList;
|
||||
register struct idf *id = gen_anon_idf();
|
||||
register struct def *df;
|
||||
register struct idf *id = 0;
|
||||
struct type *tp;
|
||||
struct node *nd;
|
||||
struct node *nd1;
|
||||
register struct node *nd;
|
||||
arith tcnt, max;
|
||||
} :
|
||||
[
|
||||
|
@ -294,77 +259,81 @@ FieldList(struct scope *scope; arith *cnt; int *palign;)
|
|||
}
|
||||
|
|
||||
CASE
|
||||
/* Also accept old fashioned Modula-2 syntax, but give a warning
|
||||
/* Also accept old fashioned Modula-2 syntax, but give a warning.
|
||||
Sorry for the complicated code.
|
||||
*/
|
||||
[ qualident(0, (struct def **) 0, (char *) 0, &nd)
|
||||
[ ':' qualtype(&tp)
|
||||
[ qualident(0, (struct def **) 0, (char *) 0, &nd1)
|
||||
{ nd = nd1; }
|
||||
[ ':' qualtype(&tp)
|
||||
/* This is correct, in both kinds of Modula-2, if
|
||||
the first qualident is a single identifier.
|
||||
the first qualident is a single identifier.
|
||||
*/
|
||||
{ if (nd->nd_class != Name) {
|
||||
error("illegal variant tag");
|
||||
}
|
||||
else id = nd->nd_IDF;
|
||||
}
|
||||
|
|
||||
/* Old fashioned! the first qualident now represents
|
||||
{ if (nd->nd_class != Name) {
|
||||
error("illegal variant tag");
|
||||
}
|
||||
else id = nd->nd_IDF;
|
||||
FreeNode(nd);
|
||||
}
|
||||
| /* Old fashioned! the first qualident now represents
|
||||
the type
|
||||
*/
|
||||
{ warning("Old fashioned Modula-2 syntax!");
|
||||
if (ChkDesignator(nd) &&
|
||||
(nd->nd_class != Def ||
|
||||
!(nd->nd_def->df_kind&(D_ERROR|D_ISTYPE)) ||
|
||||
!nd->nd_def->df_type)) {
|
||||
node_error(nd, "type expected");
|
||||
tp = error_type;
|
||||
}
|
||||
else tp = nd->nd_def->df_type;
|
||||
FreeNode(nd);
|
||||
}
|
||||
]
|
||||
|
|
||||
/* Aha, third edition. Well done! */
|
||||
':' qualtype(&tp)
|
||||
{ warning("Old fashioned Modula-2 syntax; ':' missing");
|
||||
if (ChkDesignator(nd) &&
|
||||
(nd->nd_class != Def ||
|
||||
!(nd->nd_def->df_kind&(D_ERROR|D_ISTYPE)) ||
|
||||
!nd->nd_def->df_type)) {
|
||||
node_error(nd, "type expected");
|
||||
tp = error_type;
|
||||
}
|
||||
else tp = nd->nd_def->df_type;
|
||||
FreeNode(nd);
|
||||
}
|
||||
]
|
||||
| ':' qualtype(&tp)
|
||||
/* Aha, third edition. Well done! */
|
||||
]
|
||||
{ if (!(tp->tp_fund & T_DISCRETE)) {
|
||||
{ if (id) {
|
||||
register struct def *df = define(id,
|
||||
scope,
|
||||
D_FIELD);
|
||||
if (!(tp->tp_fund & T_DISCRETE)) {
|
||||
error("Illegal type in variant");
|
||||
}
|
||||
df = define(id, scope, D_FIELD);
|
||||
df->df_type = tp;
|
||||
df->fld_off = align(*cnt, tp->tp_align);
|
||||
*cnt = tcnt = df->fld_off + tp->tp_size;
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
}
|
||||
}
|
||||
df->df_type = tp;
|
||||
df->fld_off = align(*cnt, tp->tp_align);
|
||||
*cnt = tcnt = df->fld_off + tp->tp_size;
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
}
|
||||
}
|
||||
OF variant(scope, &tcnt, tp, palign)
|
||||
{ max = tcnt; tcnt = *cnt; }
|
||||
{ max = tcnt; tcnt = *cnt; }
|
||||
[
|
||||
'|' variant(scope, &tcnt, tp, palign)
|
||||
{ if (tcnt > max) max = tcnt; tcnt = *cnt; }
|
||||
'|' variant(scope, &tcnt, tp, palign)
|
||||
{ if (tcnt > max) max = tcnt; tcnt = *cnt; }
|
||||
]*
|
||||
[ ELSE FieldListSequence(scope, &tcnt, palign)
|
||||
{ if (tcnt > max) max = tcnt; }
|
||||
{ if (tcnt > max) max = tcnt; }
|
||||
]?
|
||||
END
|
||||
{ *cnt = max; }
|
||||
{ *cnt = max; }
|
||||
]?
|
||||
;
|
||||
|
||||
variant(struct scope *scope; arith *cnt; struct type *tp; int *palign;)
|
||||
{
|
||||
struct type *tp1 = tp;
|
||||
struct node *nd;
|
||||
} :
|
||||
[
|
||||
CaseLabelList(&tp1, &nd)
|
||||
{ /* Ignore the cases for the time being.
|
||||
Maybe a checking version will be supplied
|
||||
later ???
|
||||
*/
|
||||
FreeNode(nd);
|
||||
}
|
||||
CaseLabelList(&tp, &nd)
|
||||
{ /* Ignore the cases for the time being.
|
||||
Maybe a checking version will be supplied
|
||||
later ??? (Improbable)
|
||||
*/
|
||||
FreeNode(nd);
|
||||
}
|
||||
':' FieldListSequence(scope, cnt, palign)
|
||||
]?
|
||||
/* Changed rule in new modula-2 */
|
||||
/* Changed rule in new modula-2 */
|
||||
;
|
||||
|
||||
CaseLabelList(struct type **ptp; struct node **pnd;):
|
||||
|
@ -376,27 +345,29 @@ CaseLabelList(struct type **ptp; struct node **pnd;):
|
|||
]*
|
||||
;
|
||||
|
||||
CaseLabels(struct type **ptp; struct node **pnd;)
|
||||
CaseLabels(struct type **ptp; register struct node **pnd;)
|
||||
{
|
||||
struct node *nd1, *nd2 = 0;
|
||||
register struct node *nd1;
|
||||
}:
|
||||
ConstExpression(&nd1) { *pnd = nd1; }
|
||||
ConstExpression(pnd)
|
||||
{ nd1 = *pnd; }
|
||||
[
|
||||
UPTO { *pnd = MkNode(Link,nd1,NULLNODE,&dot); }
|
||||
ConstExpression(&nd2)
|
||||
{ if (!TstCompat(nd1->nd_type, nd2->nd_type)) {
|
||||
node_error(nd2,"type incompatibility in case label");
|
||||
nd1->nd_type = error_type;
|
||||
}
|
||||
(*pnd)->nd_right = nd2;
|
||||
}
|
||||
UPTO { *pnd = MkNode(Link,nd1,NULLNODE,&dot); }
|
||||
ConstExpression(&(*pnd)->nd_right)
|
||||
{ if (!TstCompat(nd1->nd_type,
|
||||
(*pnd)->nd_right->nd_type)) {
|
||||
node_error((*pnd)->nd_right,
|
||||
"type incompatibility in case label");
|
||||
nd1->nd_type = error_type;
|
||||
}
|
||||
}
|
||||
]?
|
||||
{ if (*ptp != 0 &&
|
||||
!TstCompat(*ptp, nd1->nd_type)) {
|
||||
node_error(nd1,"type incompatibility in case label");
|
||||
}
|
||||
*ptp = nd1->nd_type;
|
||||
}
|
||||
{ if (*ptp != 0 && !TstCompat(*ptp, nd1->nd_type)) {
|
||||
node_error(nd1,
|
||||
"type incompatibility in case label");
|
||||
}
|
||||
*ptp = nd1->nd_type;
|
||||
}
|
||||
;
|
||||
|
||||
SetType(struct type **ptp;) :
|
||||
|
@ -410,7 +381,7 @@ SetType(struct type **ptp;) :
|
|||
*/
|
||||
PointerType(struct type **ptp;)
|
||||
{
|
||||
register struct node *nd;
|
||||
register struct node *nd = 0;
|
||||
} :
|
||||
POINTER TO
|
||||
{ *ptp = construct_type(T_POINTER, NULLTYPE); }
|
||||
|
@ -418,49 +389,51 @@ PointerType(struct type **ptp;)
|
|||
/* Either a Module or a Type, but in both cases defined
|
||||
in this scope, so this is the correct identification
|
||||
*/
|
||||
qualtype(&((*ptp)->next))
|
||||
| %if ( nd = new_node(), nd->nd_token = dot,
|
||||
qualtype(&((*ptp)->next))
|
||||
| %if ( nd = new_node(),
|
||||
nd->nd_token = dot,
|
||||
lookfor(nd, CurrVis, 0)->df_kind == D_MODULE)
|
||||
{ if (dot.tk_symb == IDENT) free_node(nd); }
|
||||
type(&((*ptp)->next))
|
||||
type(&((*ptp)->next))
|
||||
{ if (nd) free_node(nd); }
|
||||
|
|
||||
IDENT { Forward(nd, (*ptp)); }
|
||||
IDENT { Forward(nd, (*ptp)); }
|
||||
]
|
||||
;
|
||||
|
||||
qualtype(struct type **ptp;)
|
||||
{
|
||||
struct def *df;
|
||||
struct def *df = 0;
|
||||
} :
|
||||
qualident(D_ISTYPE, &df, "type", (struct node **) 0)
|
||||
{ if (!(*ptp = df->df_type)) {
|
||||
error("type \"%s\" not declared", df->df_idf->id_text);
|
||||
*ptp = error_type;
|
||||
}
|
||||
}
|
||||
{ if (df && !(*ptp = df->df_type)) {
|
||||
error("type \"%s\" not declared",
|
||||
df->df_idf->id_text);
|
||||
*ptp = error_type;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
ProcedureType(struct type **ptp;)
|
||||
{
|
||||
struct paramlist *pr = 0;
|
||||
register struct type *tp;
|
||||
arith nbytes = 0;
|
||||
} :
|
||||
arith parmaddr = 0;
|
||||
}
|
||||
:
|
||||
{ *ptp = 0; }
|
||||
PROCEDURE FormalTypeList(&pr, ptp, &nbytes)?
|
||||
{ *ptp = tp = construct_type(T_PROCEDURE, *ptp);
|
||||
tp->prc_params = pr;
|
||||
tp->prc_nbpar = nbytes;
|
||||
}
|
||||
PROCEDURE
|
||||
[
|
||||
FormalTypeList(&pr, &parmaddr, ptp)
|
||||
]?
|
||||
{ *ptp = proc_type(*ptp, pr, parmaddr); }
|
||||
;
|
||||
|
||||
FormalTypeList(struct paramlist **ppr; struct type **ptp; arith *parmaddr;)
|
||||
FormalTypeList(struct paramlist **ppr; arith *parmaddr; struct type **ptp;)
|
||||
{
|
||||
int VARp;
|
||||
struct type *tp;
|
||||
int VARp;
|
||||
} :
|
||||
'(' { *ppr = 0; }
|
||||
'('
|
||||
[
|
||||
var(&VARp) FormalType(&tp)
|
||||
{ EnterParamList(ppr,NULLNODE,tp,VARp,parmaddr); }
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* 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 {
|
||||
arith mo_priority; /* priority of a module */
|
||||
struct scopelist *mo_vis;/* scope of this module */
|
||||
|
@ -82,12 +80,12 @@ struct def { /* list of definitions for a name */
|
|||
#define D_IMPORT 0x0080 /* an imported definition */
|
||||
#define D_PROCHEAD 0x0100 /* a procedure heading in a definition module */
|
||||
#define D_HIDDEN 0x0200 /* a hidden type */
|
||||
#define D_FORWARD 0x0800 /* not yet defined */
|
||||
#define D_UNDEF_IMPORT 0x1000 /* imported from an undefined name */
|
||||
#define D_FORWMODULE 0x2000 /* module must be declared later */
|
||||
#define D_ERROR 0x4000 /* a compiler generated definition for an
|
||||
#define D_FORWARD 0x0400 /* not yet defined */
|
||||
#define D_FORWMODULE 0x0800 /* module must be declared later */
|
||||
#define D_ERROR 0x1000 /* a compiler generated definition for an
|
||||
undefined variable
|
||||
*/
|
||||
#define D_VALUE (D_PROCEDURE|D_VARIABLE|D_FIELD|D_ENUM|D_CONST|D_PROCHEAD)
|
||||
#define D_ISTYPE (D_HIDDEN|D_TYPE)
|
||||
#define is_type(dfx) ((dfx)->df_kind & D_ISTYPE)
|
||||
char df_flags;
|
||||
|
@ -115,14 +113,13 @@ struct def { /* list of definitions for a name */
|
|||
|
||||
#define SetUsed(df) ((df)->df_flags |= D_USED)
|
||||
|
||||
/* ALLOCDEF "def" */
|
||||
/* ALLOCDEF "def" 50 */
|
||||
|
||||
extern struct def
|
||||
*define(),
|
||||
*DefineLocalModule(),
|
||||
*MkDef(),
|
||||
*DeclProc(),
|
||||
*ill_df;
|
||||
*DeclProc();
|
||||
|
||||
extern struct def
|
||||
*lookup(),
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* D E F I N I T I O N M E C H A N I S M */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
|
@ -25,11 +21,42 @@ struct def *h_def; /* pointer to free list of def structures */
|
|||
int cnt_def; /* count number of allocated ones */
|
||||
#endif
|
||||
|
||||
struct def *ill_df;
|
||||
STATIC
|
||||
DefInFront(df)
|
||||
register struct def *df;
|
||||
{
|
||||
/* Put definition "df" in front of the list of definitions
|
||||
in its scope.
|
||||
This is neccessary because in some cases the order in this
|
||||
list is important.
|
||||
*/
|
||||
register struct def *df1 = df->df_scope->sc_def;
|
||||
|
||||
if (df1 != df) {
|
||||
/* Definition "df" is not in front of the list
|
||||
*/
|
||||
while (df1) {
|
||||
/* Find definition "df"
|
||||
*/
|
||||
if (df1->df_nextinscope == df) {
|
||||
/* It already was in the list. Remove it
|
||||
*/
|
||||
df1->df_nextinscope = df->df_nextinscope;
|
||||
break;
|
||||
}
|
||||
df1 = df1->df_nextinscope;
|
||||
}
|
||||
|
||||
/* Now put it in front
|
||||
*/
|
||||
df->df_nextinscope = df->df_scope->sc_def;
|
||||
df->df_scope->sc_def = df;
|
||||
}
|
||||
}
|
||||
|
||||
struct def *
|
||||
MkDef(id, scope, kind)
|
||||
struct idf *id;
|
||||
register struct idf *id;
|
||||
register struct scope *scope;
|
||||
{
|
||||
/* Create a new definition structure in scope "scope", with
|
||||
|
@ -38,7 +65,6 @@ MkDef(id, scope, kind)
|
|||
register struct def *df;
|
||||
|
||||
df = new_def();
|
||||
clear((char *) df, sizeof (*df));
|
||||
df->df_idf = id;
|
||||
df->df_scope = scope;
|
||||
df->df_kind = kind;
|
||||
|
@ -52,24 +78,16 @@ MkDef(id, scope, kind)
|
|||
return df;
|
||||
}
|
||||
|
||||
InitDef()
|
||||
{
|
||||
/* Initialize this module. Easy, the only thing to be initialized
|
||||
is "ill_df".
|
||||
*/
|
||||
struct idf *gen_anon_idf();
|
||||
|
||||
ill_df = MkDef(gen_anon_idf(), CurrentScope, D_ERROR);
|
||||
ill_df->df_type = error_type;
|
||||
}
|
||||
|
||||
struct def *
|
||||
define(id, scope, kind)
|
||||
register struct idf *id;
|
||||
register struct scope *scope;
|
||||
int kind;
|
||||
{
|
||||
/* Declare an identifier in a scope, but first check if it
|
||||
already has been defined. If so, error message.
|
||||
already has been defined.
|
||||
If so, then check for the cases in which this is legal,
|
||||
and otherwise give an error message.
|
||||
*/
|
||||
register struct def *df;
|
||||
|
||||
|
@ -133,7 +151,8 @@ define(id, scope, kind)
|
|||
if (kind != D_ERROR) {
|
||||
/* Avoid spurious error messages
|
||||
*/
|
||||
error("identifier \"%s\" already declared", id->id_text);
|
||||
error("identifier \"%s\" already declared",
|
||||
id->id_text);
|
||||
}
|
||||
|
||||
return df;
|
||||
|
@ -143,7 +162,7 @@ error("identifier \"%s\" already declared", id->id_text);
|
|||
}
|
||||
|
||||
RemoveImports(pdf)
|
||||
struct def **pdf;
|
||||
register struct def **pdf;
|
||||
{
|
||||
/* Remove all imports from a definition module. This is
|
||||
neccesary because the implementation module might import
|
||||
|
@ -165,16 +184,15 @@ RemoveImports(pdf)
|
|||
}
|
||||
|
||||
RemoveFromIdList(df)
|
||||
struct def *df;
|
||||
register struct def *df;
|
||||
{
|
||||
/* Remove definition "df" from the definition list
|
||||
*/
|
||||
register struct idf *id = df->df_idf;
|
||||
register struct def *df1;
|
||||
|
||||
if (id->id_def == df) id->id_def = df->next;
|
||||
if ((df1 = id->id_def) == df) id->id_def = df->next;
|
||||
else {
|
||||
df1 = id->id_def;
|
||||
while (df1->next != df) {
|
||||
assert(df1->next != 0);
|
||||
df1 = df1->next;
|
||||
|
@ -184,13 +202,15 @@ RemoveFromIdList(df)
|
|||
}
|
||||
|
||||
struct def *
|
||||
DeclProc(type)
|
||||
DeclProc(type, id)
|
||||
register struct idf *id;
|
||||
{
|
||||
/* A procedure is declared, either in a definition or a program
|
||||
module. Create a def structure for it (if neccessary).
|
||||
Also create a name for it.
|
||||
*/
|
||||
register struct def *df;
|
||||
register struct scope *scope;
|
||||
extern char *sprint();
|
||||
static int nmcount;
|
||||
char buf[256];
|
||||
|
@ -200,85 +220,61 @@ DeclProc(type)
|
|||
if (type == D_PROCHEAD) {
|
||||
/* In a definition module
|
||||
*/
|
||||
df = define(dot.TOK_IDF, CurrentScope, type);
|
||||
df = define(id, CurrentScope, type);
|
||||
df->for_node = MkLeaf(Name, &dot);
|
||||
sprint(buf,"%s_%s",CurrentScope->sc_name,df->df_idf->id_text);
|
||||
sprint(buf,"%s_%s",CurrentScope->sc_name,id->id_text);
|
||||
df->for_name = Salloc(buf, (unsigned) (strlen(buf)+1));
|
||||
if (CurrVis == Defined->mod_vis) C_exp(df->for_name);
|
||||
if (CurrVis == Defined->mod_vis) {
|
||||
/* The current module will define this routine.
|
||||
make sure the name is exported.
|
||||
*/
|
||||
C_exp(df->for_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
df = lookup(dot.TOK_IDF, CurrentScope);
|
||||
char *name;
|
||||
|
||||
df = lookup(id, CurrentScope);
|
||||
if (df && df->df_kind == D_PROCHEAD) {
|
||||
/* C_exp already generated when we saw the definition
|
||||
in the definition module
|
||||
*/
|
||||
df->df_kind = D_PROCEDURE;
|
||||
open_scope(OPENSCOPE);
|
||||
CurrentScope->sc_name = df->for_name;
|
||||
df->prc_vis = CurrVis;
|
||||
name = df->for_name;
|
||||
DefInFront(df);
|
||||
}
|
||||
else {
|
||||
df = define(dot.TOK_IDF, CurrentScope, type);
|
||||
open_scope(OPENSCOPE);
|
||||
df->prc_vis = CurrVis;
|
||||
sprint(buf,"_%d_%s",++nmcount,df->df_idf->id_text);
|
||||
CurrentScope->sc_name =
|
||||
Salloc(buf, (unsigned)(strlen(buf)+1));
|
||||
df = define(id, CurrentScope, type);
|
||||
sprint(buf,"_%d_%s",++nmcount,id->id_text);
|
||||
name = Salloc(buf, (unsigned)(strlen(buf)+1));
|
||||
C_inp(buf);
|
||||
}
|
||||
open_scope(OPENSCOPE);
|
||||
scope = CurrentScope;
|
||||
scope->sc_name = name;
|
||||
scope->sc_definedby = df;
|
||||
df->prc_vis = CurrVis;
|
||||
}
|
||||
|
||||
return df;
|
||||
}
|
||||
|
||||
AddModule(id)
|
||||
EndProc(df, id)
|
||||
register struct def *df;
|
||||
struct idf *id;
|
||||
{
|
||||
/* Add the name of a module to the Module list. This list is
|
||||
maintained to create the initialization routine of the
|
||||
program/implementation module currently defined.
|
||||
/* The end of a procedure declaration.
|
||||
Check that the closing identifier matches the name of the
|
||||
procedure, close the scope, and check that a function
|
||||
procedure has at least one RETURN statement.
|
||||
*/
|
||||
static struct node *nd_end; /* to remember end of list */
|
||||
register struct node *n;
|
||||
extern struct node *Modules;
|
||||
extern int return_occurred;
|
||||
|
||||
n = MkLeaf(Name, &dot);
|
||||
n->nd_IDF = id;
|
||||
n->nd_symb = IDENT;
|
||||
if (nd_end) nd_end->next = n;
|
||||
else Modules = n;
|
||||
nd_end = n;
|
||||
}
|
||||
|
||||
DefInFront(df)
|
||||
register struct def *df;
|
||||
{
|
||||
/* Put definition "df" in front of the list of definitions
|
||||
in its scope.
|
||||
This is neccessary because in some cases the order in this
|
||||
list is important.
|
||||
*/
|
||||
register struct def *df1 = df->df_scope->sc_def;
|
||||
|
||||
if (df1 != df) {
|
||||
/* Definition "df" is not in front of the list
|
||||
*/
|
||||
while (df1 && df1->df_nextinscope != df) {
|
||||
/* Find definition "df"
|
||||
*/
|
||||
df1 = df1->df_nextinscope;
|
||||
}
|
||||
if (df1) {
|
||||
/* It already was in the list. Remove it
|
||||
*/
|
||||
df1->df_nextinscope = df->df_nextinscope;
|
||||
}
|
||||
|
||||
/* Now put it in front
|
||||
*/
|
||||
df->df_nextinscope = df->df_scope->sc_def;
|
||||
df->df_scope->sc_def = df;
|
||||
match_id(id, df->df_idf);
|
||||
close_scope(SC_CHKFORW|SC_REVERSE);
|
||||
if (! return_occurred && ResultType(df->df_type)) {
|
||||
error("function procedure %s does not return a value",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,6 +322,27 @@ DefineLocalModule(id)
|
|||
return df;
|
||||
}
|
||||
|
||||
CheckWithDef(df, tp)
|
||||
register struct def *df;
|
||||
struct type *tp;
|
||||
{
|
||||
/* Check the header of a procedure declaration against a
|
||||
possible earlier definition in the definition module.
|
||||
*/
|
||||
|
||||
if (df->df_type) {
|
||||
/* We already saw a definition of this type
|
||||
in the definition module.
|
||||
*/
|
||||
if (!TstProcEquiv(tp, df->df_type)) {
|
||||
error("inconsistent procedure declaration for \"%s\"",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
FreeType(df->df_type);
|
||||
}
|
||||
df->df_type = tp;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PrDef(df)
|
||||
register struct def *df;
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* D E F I N I T I O N M O D U L E S */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -15,23 +11,27 @@ static char *RcsId = "$Header$";
|
|||
#include "scope.h"
|
||||
#include "def.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "f_info.h"
|
||||
#include "main.h"
|
||||
#include "node.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
long sys_filesize();
|
||||
#endif
|
||||
|
||||
struct idf * CurrentId;
|
||||
|
||||
GetFile(name)
|
||||
char *name;
|
||||
{
|
||||
/* Try to find a file with basename "name" and extension ".def",
|
||||
in the directories mentioned in "DEFPATH".
|
||||
*/
|
||||
char buf[256];
|
||||
char buf[15];
|
||||
char *strcpy(), *strcat();
|
||||
|
||||
strcpy(buf, name);
|
||||
strncpy(buf, name, 10);
|
||||
buf[10] = '\0'; /* maximum length */
|
||||
strcat(buf, ".def");
|
||||
if (! InsertFile(buf, DEFPATH, &(FileName))) {
|
||||
|
@ -42,17 +42,18 @@ GetFile(name)
|
|||
}
|
||||
|
||||
struct def *
|
||||
GetDefinitionModule(id)
|
||||
struct idf *id;
|
||||
GetDefinitionModule(id, incr)
|
||||
register struct idf *id;
|
||||
{
|
||||
/* Return a pointer to the "def" structure of the definition
|
||||
module indicated by "id".
|
||||
We may have to read the definition module itself.
|
||||
Also increment level by "incr".
|
||||
*/
|
||||
struct def *df;
|
||||
static int level;
|
||||
|
||||
level++;
|
||||
level += incr;
|
||||
df = lookup(id, GlobalScope);
|
||||
if (!df) {
|
||||
/* Read definition module. Make an exception for SYSTEM.
|
||||
|
@ -62,6 +63,8 @@ GetDefinitionModule(id)
|
|||
}
|
||||
else {
|
||||
GetFile(id->id_text);
|
||||
CurrentId = id;
|
||||
open_scope(CLOSEDSCOPE);
|
||||
DefModule();
|
||||
if (level == 1) {
|
||||
/* The module is directly imported by the
|
||||
|
@ -69,12 +72,23 @@ GetDefinitionModule(id)
|
|||
remember its name because we have to call
|
||||
its initialization routine
|
||||
*/
|
||||
AddModule(id);
|
||||
static struct node *nd_end; /* end of list */
|
||||
register struct node *n;
|
||||
extern struct node *Modules;
|
||||
|
||||
n = MkLeaf(Name, &dot);
|
||||
n->nd_IDF = id;
|
||||
n->nd_symb = IDENT;
|
||||
if (nd_end) nd_end->next = n;
|
||||
else Modules = n;
|
||||
nd_end = n;
|
||||
}
|
||||
close_scope(SC_CHKFORW);
|
||||
}
|
||||
df = lookup(id, GlobalScope);
|
||||
}
|
||||
CurrentId = 0;
|
||||
assert(df && df->df_kind == D_MODULE);
|
||||
level--;
|
||||
level -= incr;
|
||||
return df;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* D E S I G N A T O R E V A L U A T I O N */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
/* Code generation for designators.
|
||||
This file contains some routines that generate code common to address
|
||||
as well as value computations, and leave a description in a "desig"
|
||||
|
@ -166,7 +162,6 @@ CodeFieldDesig(df, ds)
|
|||
in "ds". "df" indicates the definition of the field.
|
||||
*/
|
||||
|
||||
|
||||
if (ds->dsg_kind == DSG_INIT) {
|
||||
/* In a WITH statement. We must find the designator in the
|
||||
WITH statement, and act as if the field is a selection
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* D E S I G N A T O R D E S C R I P T I O N S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/* Generating code for designators is not particularly easy, especially if
|
||||
you don't know wether you want the address or the value.
|
||||
The next structure is used to generate code for designators.
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* H I G H L E V E L S Y M B O L E N T R Y */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
|
@ -119,7 +115,8 @@ EnterVarList(Idlist, type, local)
|
|||
df->var_addrgiven = 1;
|
||||
df->df_flags |= D_NOREG;
|
||||
if (idlist->nd_left->nd_type != card_type) {
|
||||
node_error(idlist->nd_left,"Illegal type for address");
|
||||
node_error(idlist->nd_left,
|
||||
"Illegal type for address");
|
||||
}
|
||||
df->var_off = idlist->nd_left->nd_INT;
|
||||
}
|
||||
|
@ -155,8 +152,8 @@ node_error(idlist->nd_left,"Illegal type for address");
|
|||
}
|
||||
|
||||
EnterParamList(ppr, Idlist, type, VARp, off)
|
||||
struct node *Idlist;
|
||||
struct paramlist **ppr;
|
||||
struct node *Idlist;
|
||||
struct type *type;
|
||||
int VARp;
|
||||
arith *off;
|
||||
|
@ -178,18 +175,14 @@ EnterParamList(ppr, Idlist, type, VARp, off)
|
|||
for ( ; idlist; idlist = idlist->next) {
|
||||
pr = new_paramlist();
|
||||
pr->next = 0;
|
||||
if (!*ppr) {
|
||||
*ppr = pr;
|
||||
}
|
||||
if (!*ppr) *ppr = pr;
|
||||
else last->next = pr;
|
||||
last = pr;
|
||||
if (!DefinitionModule && idlist != dummy) {
|
||||
df = define(idlist->nd_IDF, CurrentScope, D_VARIABLE);
|
||||
df->var_off = *off;
|
||||
}
|
||||
else {
|
||||
df = new_def();
|
||||
}
|
||||
else df = new_def();
|
||||
pr->par_def = df;
|
||||
df->df_type = type;
|
||||
df->df_flags = VARp;
|
||||
|
@ -259,11 +252,11 @@ ForwModule(df, idn)
|
|||
enclosing scope, but this must be done AFTER
|
||||
closing this one
|
||||
*/
|
||||
df->for_vis = vis;
|
||||
df->for_node = MkLeaf(Name, &(idn->nd_token));
|
||||
close_scope(0);
|
||||
vis->sc_encl = enclosing(CurrVis);
|
||||
/* Here ! */
|
||||
df->for_vis = vis;
|
||||
df->for_node = MkLeaf(Name, &(idn->nd_token));
|
||||
return vis;
|
||||
}
|
||||
|
||||
|
@ -294,7 +287,6 @@ EnterExportList(Idlist, qualified)
|
|||
*/
|
||||
register struct node *idlist = Idlist;
|
||||
register struct def *df, *df1;
|
||||
register struct def *impmod;
|
||||
|
||||
for (;idlist; idlist = idlist->next) {
|
||||
df = lookup(idlist->nd_IDF, CurrentScope);
|
||||
|
@ -302,13 +294,16 @@ EnterExportList(Idlist, qualified)
|
|||
if (!df) {
|
||||
/* undefined item in export list
|
||||
*/
|
||||
node_error(idlist, "identifier \"%s\" not defined", idlist->nd_IDF->id_text);
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not defined",
|
||||
idlist->nd_IDF->id_text);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (df->df_flags & (D_EXPORTED|D_QEXPORTED)) {
|
||||
node_error(idlist, "identifier \"%s\" occurs more than once in export list",
|
||||
idlist->nd_IDF->id_text);
|
||||
node_error(idlist,
|
||||
"multiple occurrences of \"%s\" in export list",
|
||||
idlist->nd_IDF->id_text);
|
||||
}
|
||||
|
||||
df->df_flags |= qualified;
|
||||
|
@ -317,13 +312,13 @@ idlist->nd_IDF->id_text);
|
|||
Find all imports of the module in which this export
|
||||
occurs, and export the current definition to it
|
||||
*/
|
||||
impmod = CurrentScope->sc_definedby->df_idf->id_def;
|
||||
while (impmod) {
|
||||
if (impmod->df_kind == D_IMPORT &&
|
||||
impmod->imp_def == CurrentScope->sc_definedby) {
|
||||
DoImport(df, impmod->df_scope);
|
||||
df1 = CurrentScope->sc_definedby->df_idf->id_def;
|
||||
while (df1) {
|
||||
if (df1->df_kind == D_IMPORT &&
|
||||
df1->imp_def == CurrentScope->sc_definedby) {
|
||||
DoImport(df, df1->df_scope);
|
||||
}
|
||||
impmod = impmod->next;
|
||||
df1 = df1->next;
|
||||
}
|
||||
|
||||
/* Also handle the definition as if the enclosing
|
||||
|
@ -345,7 +340,9 @@ idlist->nd_IDF->id_text);
|
|||
if (df1->df_kind == D_HIDDEN &&
|
||||
df->df_kind == D_TYPE) {
|
||||
if (df->df_type->tp_fund != T_POINTER) {
|
||||
node_error(idlist, "opaque type \"%s\" is not a pointer type", df->df_idf->id_text);
|
||||
node_error(idlist,
|
||||
"opaque type \"%s\" is not a pointer type",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
assert(df1->df_type->next == NULLTYPE);
|
||||
df1->df_kind = D_TYPE;
|
||||
|
@ -388,23 +385,23 @@ EnterFromImportList(Idlist, FromDef)
|
|||
vis = FromDef->mod_vis;
|
||||
break;
|
||||
default:
|
||||
error("identifier \"%s\" does not represent a module",
|
||||
FromDef->df_idf->id_text);
|
||||
error("identifier \"%s\" does not represent a module",
|
||||
FromDef->df_idf->id_text);
|
||||
break;
|
||||
}
|
||||
|
||||
for (; idlist; idlist = idlist->next) {
|
||||
if (forwflag) {
|
||||
df = ForwDef(idlist, vis->sc_scope);
|
||||
}
|
||||
else if (!(df = lookup(idlist->nd_IDF, vis->sc_scope))) {
|
||||
node_error(idlist, "identifier \"%s\" not declared in qualifying module",
|
||||
idlist->nd_IDF->id_text);
|
||||
if (forwflag) df = ForwDef(idlist, vis->sc_scope);
|
||||
else if (! (df = lookup(idlist->nd_IDF, vis->sc_scope))) {
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not declared in qualifying module",
|
||||
idlist->nd_IDF->id_text);
|
||||
df = define(idlist->nd_IDF,vis->sc_scope,D_ERROR);
|
||||
}
|
||||
else if (!(df->df_flags&(D_EXPORTED|D_QEXPORTED))) {
|
||||
node_error(idlist,"identifier \"%s\" not exported from qualifying module",
|
||||
idlist->nd_IDF->id_text);
|
||||
else if (! (df->df_flags & (D_EXPORTED|D_QEXPORTED))) {
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not exported from qualifying module",
|
||||
idlist->nd_IDF->id_text);
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
}
|
||||
DoImport(df, CurrentScope);
|
||||
|
@ -422,14 +419,14 @@ EnterImportList(Idlist, local)
|
|||
This case is indicated by the value 0 of the "local" flag.
|
||||
*/
|
||||
register struct node *idlist = Idlist;
|
||||
register struct def *df;
|
||||
struct scopelist *vis = enclosing(CurrVis);
|
||||
struct scope *sc = enclosing(CurrVis)->sc_scope;
|
||||
extern struct def *GetDefinitionModule();
|
||||
|
||||
for (; idlist; idlist = idlist->next) {
|
||||
if (local) df = ForwDef(idlist, vis->sc_scope);
|
||||
else df = GetDefinitionModule(idlist->nd_IDF);
|
||||
DoImport(df, CurrentScope);
|
||||
DoImport(local ?
|
||||
ForwDef(idlist, sc) :
|
||||
GetDefinitionModule(idlist->nd_IDF) ,
|
||||
CurrentScope);
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
number of arguments!
|
||||
*/
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "errout.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/* E X P R E S S I O N S */
|
||||
|
||||
{
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
|
@ -38,22 +34,19 @@ qualident(int types;
|
|||
struct node **p;
|
||||
)
|
||||
{
|
||||
register struct def *df;
|
||||
struct node *nd;
|
||||
} :
|
||||
IDENT { nd = MkLeaf(Name, &dot); }
|
||||
[
|
||||
selector(&nd)
|
||||
]*
|
||||
{ if (types) {
|
||||
df = ill_df;
|
||||
|
||||
if (ChkDesignator(nd)) {
|
||||
if (nd->nd_class != Def) {
|
||||
{ if (types && ChkDesignator(nd)) {
|
||||
if (nd->nd_class != Def) {
|
||||
node_error(nd, "%s expected", str);
|
||||
}
|
||||
else {
|
||||
df = nd->nd_def;
|
||||
}
|
||||
else {
|
||||
register struct def *df = nd->nd_def;
|
||||
|
||||
if ( !((types|D_ERROR) & df->df_kind)) {
|
||||
if (df->df_kind == D_FORWARD) {
|
||||
node_error(nd,"%s \"%s\" not declared", str, df->df_idf->id_text);
|
||||
|
@ -62,9 +55,8 @@ node_error(nd,"%s \"%s\" not declared", str, df->df_idf->id_text);
|
|||
node_error(nd,"identifier \"%s\" is not a %s", df->df_idf->id_text, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pdf) *pdf = df;
|
||||
}
|
||||
*pdf = df;
|
||||
}
|
||||
if (!p) FreeNode(nd);
|
||||
else *p = nd;
|
||||
|
@ -170,10 +162,9 @@ MulOperator:
|
|||
|
||||
factor(register struct node **p;)
|
||||
{
|
||||
struct def *df;
|
||||
struct node *nd;
|
||||
} :
|
||||
qualident(0, &df, (char *) 0, p)
|
||||
qualident(0, (struct def **) 0, (char *) 0, p)
|
||||
[
|
||||
designator_tail(p)?
|
||||
[
|
||||
|
@ -236,10 +227,8 @@ element(struct node *nd;)
|
|||
;
|
||||
|
||||
designator(struct node **pnd;)
|
||||
{
|
||||
struct def *df;
|
||||
} :
|
||||
qualident(0, &df, (char *) 0, pnd)
|
||||
:
|
||||
qualident(0, (struct def **) 0, (char *) 0, pnd)
|
||||
designator_tail(pnd)?
|
||||
;
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* F I L E D E S C R I P T O R S T R U C T U R E */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
struct f_info {
|
||||
unsigned short f_lineno;
|
||||
char *f_filename;
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
/* 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>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* U S E R D E C L A R E D P A R T O F I D F */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
struct id_u {
|
||||
int id_res;
|
||||
struct def *id_df;
|
||||
|
|
|
@ -1,17 +1,25 @@
|
|||
/* 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 <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include "def.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include <inp_pkg.body>
|
||||
|
||||
extern struct idf *CurrentId;
|
||||
|
||||
AtEoIF()
|
||||
{
|
||||
/* Make the unstacking of input streams noticable to the
|
||||
lexical analyzer
|
||||
*/
|
||||
if (CurrentId && ! lookup(CurrentId, GlobalScope)) {
|
||||
fatal("No definition module read for \"%s\"", CurrentId->id_text);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +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$ */
|
||||
|
||||
#include "inputtype.h"
|
||||
|
||||
#define INP_NPUSHBACK 2
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* L O O K U P R O U T I N E S */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* M A I N P R O G R A M */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "ndir.h"
|
||||
|
||||
|
@ -26,7 +22,6 @@ static char *RcsId = "$Header$";
|
|||
int state; /* either IMPLEMENTATION or PROGRAM */
|
||||
char options[128];
|
||||
int DefinitionModule;
|
||||
int SYSTEMModule;
|
||||
char *ProgName;
|
||||
char *DEFPATH[NDIRS+1];
|
||||
struct def *Defined;
|
||||
|
@ -73,7 +68,6 @@ Compile(src, dst)
|
|||
reserve(tkidf);
|
||||
InitScope();
|
||||
InitTypes();
|
||||
InitDef();
|
||||
AddStandards();
|
||||
#ifdef DEBUG
|
||||
if (options['l']) {
|
||||
|
@ -186,27 +180,29 @@ AddStandards()
|
|||
df->enm_next = 0;
|
||||
}
|
||||
|
||||
do_SYSTEM()
|
||||
{
|
||||
/* Simulate the reading of the SYSTEM definition module
|
||||
*/
|
||||
char *SYSTEM = "\
|
||||
/* How do you like that! Modula-2 in a C-program.
|
||||
*/
|
||||
char SYSTEM[] = "\
|
||||
DEFINITION MODULE SYSTEM;\n\
|
||||
TYPE PROCESS = ADDRESS;\n\
|
||||
PROCEDURE NEWPROCESS(P:PROC; A:ADDRESS; n:CARDINAL; VAR p1:ADDRESS);\n\
|
||||
PROCEDURE TRANSFER(VAR p1,p2:ADDRESS);\n\
|
||||
END SYSTEM.\n";
|
||||
|
||||
do_SYSTEM()
|
||||
{
|
||||
/* Simulate the reading of the SYSTEM definition module
|
||||
*/
|
||||
open_scope(CLOSEDSCOPE);
|
||||
(void) Enter("WORD", D_TYPE, word_type, 0);
|
||||
(void) Enter("ADDRESS", D_TYPE, address_type, 0);
|
||||
(void) Enter("ADR", D_PROCEDURE, std_type, S_ADR);
|
||||
(void) Enter("TSIZE", D_PROCEDURE, std_type, S_TSIZE);
|
||||
if (!InsertText(SYSTEM, strlen(SYSTEM))) {
|
||||
if (!InsertText(SYSTEM, sizeof(SYSTEM) - 1)) {
|
||||
fatal("Could not insert text");
|
||||
}
|
||||
SYSTEMModule = 1;
|
||||
DefModule();
|
||||
SYSTEMModule = 0;
|
||||
close_scope(SC_CHKFORW);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* 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 int DefinitionModule;
|
||||
|
@ -9,9 +7,6 @@ extern int DefinitionModule;
|
|||
module
|
||||
*/
|
||||
|
||||
extern int SYSTEMModule;/* flag indicating that we are handling the SYSTEM
|
||||
module
|
||||
*/
|
||||
extern struct def *Defined;
|
||||
/* definition structure of module defined in this
|
||||
compilation
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
sed -e '
|
||||
s:^.*[ ]ALLOCDEF[ ].*"\(.*\)".*$:\
|
||||
s:^.*[ ]ALLOCDEF[ ].*"\(.*\)"[ ]*\([0-9][0-9]*\).*$:\
|
||||
/* allocation definitions of struct \1 */\
|
||||
extern char *st_alloc();\
|
||||
extern struct \1 *h_\1;\
|
||||
#ifdef DEBUG\
|
||||
extern int cnt_\1;\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \&cnt_\1))\
|
||||
extern char *std_alloc();\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \2, \&cnt_\1))\
|
||||
#else\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1)))\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1), \2))\
|
||||
#endif\
|
||||
#define free_\1(p) st_free(p, h_\1, sizeof(struct \1))\
|
||||
:' -e '
|
||||
s:^.*[ ]STATICALLOCDEF[ ].*"\(.*\)".*$:\
|
||||
s:^.*[ ]STATICALLOCDEF[ ].*"\(.*\)"[ ]*\([0-9][0-9]*\).*$:\
|
||||
/* allocation definitions of struct \1 */\
|
||||
extern char *st_alloc();\
|
||||
struct \1 *h_\1;\
|
||||
#ifdef DEBUG\
|
||||
int cnt_\1;\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \&cnt_\1))\
|
||||
#define new_\1() ((struct \1 *) std_alloc((char **)\&h_\1, sizeof(struct \1), \2, \&cnt_\1))\
|
||||
#else\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1)))\
|
||||
#define new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1), \2))\
|
||||
#endif\
|
||||
#define free_\1(p) st_free(p, h_\1, sizeof(struct \1))\
|
||||
:'
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* M I S C E L L A N E O U S R O U T I N E S */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* M I S C E L L A N E O U S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#define is_anon_idf(x) ((x)->id_text[0] == '#')
|
||||
|
||||
extern struct idf
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* N O D E O F A N A B S T R A C T P A R S E T R E E */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
struct node {
|
||||
struct node *next;
|
||||
#define nd_left next
|
||||
|
@ -35,7 +33,7 @@ struct node {
|
|||
#define nd_REL nd_token.TOK_REL
|
||||
};
|
||||
|
||||
/* ALLOCDEF "node" */
|
||||
/* ALLOCDEF "node" 50 */
|
||||
|
||||
extern struct node *MkNode(), *MkLeaf();
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* N O D E O F A N A B S T R A C T P A R S E T R E E */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_label.h>
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* U S E R O P T I O N - H A N D L I N G */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "idfsize.h"
|
||||
#include "ndir.h"
|
||||
|
||||
|
@ -17,7 +13,7 @@ extern int idfsize;
|
|||
static int ndirs;
|
||||
|
||||
DoOption(text)
|
||||
char *text;
|
||||
register char *text;
|
||||
{
|
||||
switch(*text++) {
|
||||
|
||||
|
@ -33,12 +29,15 @@ DoOption(text)
|
|||
*/
|
||||
|
||||
|
||||
case 'M': /* maximum identifier length */
|
||||
idfsize = txt2int(&text);
|
||||
if (*text || idfsize <= 0)
|
||||
case 'M': { /* maximum identifier length */
|
||||
char *t = text; /* because &text is illegal */
|
||||
|
||||
idfsize = txt2int(&t);
|
||||
if (*t || idfsize <= 0)
|
||||
fatal("malformed -M option");
|
||||
if (idfsize > IDFSIZE)
|
||||
fatal("maximum identifier length is %d", IDFSIZE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I' :
|
||||
|
@ -53,13 +52,16 @@ DoOption(text)
|
|||
arith size;
|
||||
int align;
|
||||
char c;
|
||||
char *t;
|
||||
|
||||
while (c = *text++) {
|
||||
size = txt2int(&text);
|
||||
t = text;
|
||||
size = txt2int(&t);
|
||||
align = 0;
|
||||
if (*text == '.') {
|
||||
text++;
|
||||
align = txt2int(&text);
|
||||
if (*(text = t) == '.') {
|
||||
t = text + 1;
|
||||
align = txt2int(&t);
|
||||
text = t;
|
||||
}
|
||||
switch (c) {
|
||||
|
||||
|
@ -104,7 +106,7 @@ DoOption(text)
|
|||
|
||||
int
|
||||
txt2int(tp)
|
||||
char **tp;
|
||||
register char **tp;
|
||||
{
|
||||
/* the integer pointed to by *tp is read, while increasing
|
||||
*tp; the resulting value is yielded.
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/* O V E R A L L S T R U C T U R E */
|
||||
|
||||
{
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
|
@ -42,14 +38,11 @@ static char *RcsId = "$Header$";
|
|||
|
||||
ModuleDeclaration
|
||||
{
|
||||
struct idf *id; /* save module identifier */
|
||||
register struct def *df;
|
||||
struct node *exportlist = 0;
|
||||
int qualified;
|
||||
} :
|
||||
MODULE IDENT { id = dot.TOK_IDF;
|
||||
df = DefineLocalModule(id);
|
||||
}
|
||||
MODULE IDENT { df = DefineLocalModule(dot.TOK_IDF); }
|
||||
priority(&(df->mod_priority))?
|
||||
';'
|
||||
import(1)*
|
||||
|
@ -59,7 +52,7 @@ ModuleDeclaration
|
|||
EnterExportList(exportlist, qualified);
|
||||
}
|
||||
close_scope(SC_CHKFORW|SC_CHKPROC|SC_REVERSE);
|
||||
match_id(id, dot.TOK_IDF);
|
||||
match_id(df->df_idf, dot.TOK_IDF);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -104,7 +97,7 @@ import(int local;)
|
|||
df = lookfor(nd,enclosing(CurrVis),0);
|
||||
FreeNode(nd);
|
||||
}
|
||||
else df = GetDefinitionModule(dot.TOK_IDF);
|
||||
else df = GetDefinitionModule(dot.TOK_IDF, 1);
|
||||
}
|
||||
|
|
||||
{ fromid = 0; }
|
||||
|
@ -124,16 +117,13 @@ import(int local;)
|
|||
DefinitionModule
|
||||
{
|
||||
register struct def *df;
|
||||
struct idf *id; /* save module identifier */
|
||||
struct node *exportlist;
|
||||
int dummy;
|
||||
} :
|
||||
DEFINITION
|
||||
MODULE IDENT { id = dot.TOK_IDF;
|
||||
df = define(id, GlobalScope, D_MODULE);
|
||||
MODULE IDENT { df = define(dot.TOK_IDF, GlobalScope, D_MODULE);
|
||||
if (!Defined) Defined = df;
|
||||
if (!SYSTEMModule) open_scope(CLOSEDSCOPE);
|
||||
CurrentScope->sc_name = id->id_text;
|
||||
CurrentScope->sc_name = df->df_idf->id_text;
|
||||
df->mod_vis = CurrVis;
|
||||
df->df_type = standard_type(T_RECORD, 0, (arith) 0);
|
||||
df->df_type->rec_scope = df->mod_vis->sc_scope;
|
||||
|
@ -154,15 +144,14 @@ node_warning(exportlist, "export list in definition module ignored");
|
|||
/* empty */
|
||||
]
|
||||
definition* END IDENT
|
||||
{ df = CurrentScope->sc_def;
|
||||
while (df) {
|
||||
{ register struct def *df1 = CurrentScope->sc_def;
|
||||
while (df1) {
|
||||
/* Make all definitions "QUALIFIED EXPORT" */
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
df = df->df_nextinscope;
|
||||
df1->df_flags |= D_QEXPORTED;
|
||||
df1 = df1->df_nextinscope;
|
||||
}
|
||||
close_scope(SC_CHKFORW);
|
||||
DefinitionModule--;
|
||||
match_id(id, dot.TOK_IDF);
|
||||
match_id(df->df_idf, dot.TOK_IDF);
|
||||
}
|
||||
'.'
|
||||
;
|
||||
|
@ -206,19 +195,17 @@ Semicolon:
|
|||
|
||||
ProgramModule
|
||||
{
|
||||
struct idf *id;
|
||||
struct def *GetDefinitionModule();
|
||||
register struct def *df;
|
||||
} :
|
||||
MODULE
|
||||
IDENT { id = dot.TOK_IDF;
|
||||
if (state == IMPLEMENTATION) {
|
||||
df = GetDefinitionModule(id);
|
||||
IDENT { if (state == IMPLEMENTATION) {
|
||||
df = GetDefinitionModule(dot.TOK_IDF, 0);
|
||||
CurrVis = df->mod_vis;
|
||||
RemoveImports(&(CurrentScope->sc_def));
|
||||
}
|
||||
else {
|
||||
Defined = df = define(id, CurrentScope, D_MODULE);
|
||||
Defined = df = define(dot.TOK_IDF, CurrentScope, D_MODULE);
|
||||
open_scope(CLOSEDSCOPE);
|
||||
df->mod_vis = CurrVis;
|
||||
CurrentScope->sc_name = "_M2M";
|
||||
|
@ -229,13 +216,15 @@ ProgramModule
|
|||
';' import(0)*
|
||||
block(&(df->mod_body)) IDENT
|
||||
{ close_scope(SC_CHKFORW|SC_CHKPROC|SC_REVERSE);
|
||||
match_id(id, dot.TOK_IDF);
|
||||
match_id(df->df_idf, dot.TOK_IDF);
|
||||
}
|
||||
'.'
|
||||
;
|
||||
|
||||
Module:
|
||||
{ open_scope(CLOSEDSCOPE); }
|
||||
DefinitionModule
|
||||
{ close_scope(SC_CHKFORW); }
|
||||
|
|
||||
[
|
||||
IMPLEMENTATION { state = IMPLEMENTATION; }
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* S C O P E M E C H A N I S M */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
@ -23,9 +19,9 @@ struct scopelist *CurrVis;
|
|||
extern int proclevel;
|
||||
static struct scopelist *PervVis;
|
||||
|
||||
/* STATICALLOCDEF "scope" */
|
||||
/* STATICALLOCDEF "scope" 10 */
|
||||
|
||||
/* STATICALLOCDEF "scopelist" */
|
||||
/* STATICALLOCDEF "scopelist" 10 */
|
||||
|
||||
open_scope(scopetype)
|
||||
{
|
||||
|
@ -36,15 +32,14 @@ open_scope(scopetype)
|
|||
|
||||
assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE);
|
||||
|
||||
clear((char *) sc, sizeof (struct scope));
|
||||
sc->sc_scopeclosed = scopetype == CLOSEDSCOPE;
|
||||
sc->sc_level = proclevel;
|
||||
if (scopetype == OPENSCOPE) {
|
||||
ls->next = CurrVis;
|
||||
}
|
||||
else ls->next = PervVis;
|
||||
ls->sc_scope = sc;
|
||||
ls->sc_encl = CurrVis;
|
||||
if (scopetype == OPENSCOPE) {
|
||||
ls->next = ls->sc_encl;
|
||||
}
|
||||
else ls->next = PervVis;
|
||||
CurrVis = ls;
|
||||
}
|
||||
|
||||
|
@ -71,7 +66,7 @@ struct forwards {
|
|||
struct type *fo_ptyp;
|
||||
};
|
||||
|
||||
/* STATICALLOCDEF "forwards" */
|
||||
/* STATICALLOCDEF "forwards" 5 */
|
||||
|
||||
Forward(tk, ptp)
|
||||
struct node *tk;
|
||||
|
@ -83,11 +78,12 @@ Forward(tk, ptp)
|
|||
same scope.
|
||||
*/
|
||||
register struct forwards *f = new_forwards();
|
||||
register struct scope *sc = CurrentScope;
|
||||
|
||||
f->fo_tok = tk;
|
||||
f->fo_ptyp = ptp;
|
||||
f->next = CurrentScope->sc_forw;
|
||||
CurrentScope->sc_forw = f;
|
||||
f->next = sc->sc_forw;
|
||||
sc->sc_forw = f;
|
||||
}
|
||||
|
||||
STATIC
|
||||
|
@ -95,13 +91,14 @@ chk_proc(df)
|
|||
register struct def *df;
|
||||
{
|
||||
/* Called at scope closing. Check all definitions, and if one
|
||||
is a D_PROCHEAD, the procedure was not defined
|
||||
is a D_PROCHEAD, the procedure was not defined.
|
||||
*/
|
||||
while (df) {
|
||||
if (df->df_kind == D_PROCHEAD) {
|
||||
/* A not defined procedure
|
||||
*/
|
||||
error("procedure \"%s\" not defined", df->df_idf->id_text);
|
||||
error("procedure \"%s\" not defined",
|
||||
df->df_idf->id_text);
|
||||
FreeNode(df->for_node);
|
||||
}
|
||||
df = df->df_nextinscope;
|
||||
|
@ -110,46 +107,48 @@ error("procedure \"%s\" not defined", df->df_idf->id_text);
|
|||
|
||||
STATIC
|
||||
chk_forw(pdf)
|
||||
register struct def **pdf;
|
||||
struct def **pdf;
|
||||
{
|
||||
/* Called at scope close. Look for all forward definitions and
|
||||
if the scope was a closed scope, give an error message for
|
||||
them, and otherwise move them to the enclosing scope.
|
||||
*/
|
||||
while (*pdf) {
|
||||
if ((*pdf)->df_kind & (D_FORWARD|D_FORWMODULE)) {
|
||||
register struct def *df;
|
||||
|
||||
while (df = *pdf) {
|
||||
if (df->df_kind & (D_FORWARD|D_FORWMODULE)) {
|
||||
/* These definitions must be found in
|
||||
the enclosing closed scope, which of course
|
||||
may be the scope that is now closed!
|
||||
*/
|
||||
struct def *df1 = (*pdf)->df_nextinscope;
|
||||
|
||||
if (scopeclosed(CurrentScope)) {
|
||||
/* Indeed, the scope was a closed
|
||||
scope, so give error message
|
||||
*/
|
||||
node_error((*pdf)->for_node, "identifier \"%s\" has not been declared",
|
||||
(*pdf)->df_idf->id_text);
|
||||
FreeNode((*pdf)->for_node);
|
||||
pdf = &(*pdf)->df_nextinscope;
|
||||
node_error(df->for_node, "identifier \"%s\" has not been declared",
|
||||
df->df_idf->id_text);
|
||||
FreeNode(df->for_node);
|
||||
}
|
||||
else { /* This scope was an open scope.
|
||||
else {
|
||||
/* This scope was an open scope.
|
||||
Maybe the definitions are in the
|
||||
enclosing scope?
|
||||
*/
|
||||
struct scopelist *ls;
|
||||
|
||||
ls = nextvisible(CurrVis);
|
||||
if ((*pdf)->df_kind == D_FORWMODULE) {
|
||||
(*pdf)->for_vis->next = ls;
|
||||
register struct scopelist *ls =
|
||||
nextvisible(CurrVis);
|
||||
struct def *df1 = df->df_nextinscope;
|
||||
|
||||
if (df->df_kind == D_FORWMODULE) {
|
||||
df->for_vis->next = ls;
|
||||
}
|
||||
(*pdf)->df_nextinscope = ls->sc_scope->sc_def;
|
||||
ls->sc_scope->sc_def = *pdf;
|
||||
(*pdf)->df_scope = ls->sc_scope;
|
||||
df->df_nextinscope = ls->sc_scope->sc_def;
|
||||
ls->sc_scope->sc_def = df;
|
||||
df->df_scope = ls->sc_scope;
|
||||
*pdf = df1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else pdf = &(*pdf)->df_nextinscope;
|
||||
pdf = &df->df_nextinscope;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,20 +162,17 @@ rem_forwards(fo)
|
|||
|
||||
if (fo->next) rem_forwards(fo->next);
|
||||
df = lookfor(fo->fo_tok, CurrVis, 0);
|
||||
if (df->df_kind == D_ERROR) {
|
||||
node_error(fo->fo_tok, "identifier \"%s\" not declared",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
else if (df->df_kind != D_TYPE) {
|
||||
node_error(fo->fo_tok, "identifier \"%s\" not a type",
|
||||
df->df_idf->id_text);
|
||||
if (! is_type(df)) {
|
||||
node_error(fo->fo_tok,
|
||||
"identifier \"%s\" does not represent a type",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
fo->fo_ptyp->next = df->df_type;
|
||||
free_forwards(fo);
|
||||
}
|
||||
|
||||
Reverse(pdf)
|
||||
register struct def **pdf;
|
||||
struct def **pdf;
|
||||
{
|
||||
/* Reverse the order in the list of definitions in a scope.
|
||||
This is neccesary because this list is built in reverse.
|
||||
|
@ -188,23 +184,18 @@ Reverse(pdf)
|
|||
|
||||
df = 0;
|
||||
df1 = *pdf;
|
||||
while (df1) {
|
||||
if (df1->df_kind & INTERESTING) break;
|
||||
df1 = df1->df_nextinscope;
|
||||
}
|
||||
|
||||
if (!(*pdf = df1)) return;
|
||||
|
||||
while (df1) {
|
||||
*pdf = df1;
|
||||
df1 = df1->df_nextinscope;
|
||||
while (df1) {
|
||||
if (df1->df_kind & INTERESTING) break;
|
||||
if (df1->df_kind & INTERESTING) {
|
||||
struct def *prev = df;
|
||||
|
||||
df = df1;
|
||||
df1 = df1->df_nextinscope;
|
||||
df->df_nextinscope = prev;
|
||||
}
|
||||
(*pdf)->df_nextinscope = df;
|
||||
df = *pdf;
|
||||
else df1 = df1->df_nextinscope;
|
||||
}
|
||||
*pdf = df;
|
||||
}
|
||||
|
||||
close_scope(flag)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* 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) */
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* S T A N D A R D P R O C E D U R E S A N D F U N C T I O N S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#define S_ABS 1
|
||||
#define S_CAP 2
|
||||
#define S_CHR 3
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
/* S T A T E M E N T S */
|
||||
|
||||
{
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
@ -22,6 +18,7 @@ static int loopcount = 0; /* Count nested loops */
|
|||
statement(register struct node **pnd;)
|
||||
{
|
||||
register struct node *nd;
|
||||
extern int return_occurred;
|
||||
} :
|
||||
/*
|
||||
* This part is not in the reference grammar. The reference grammar
|
||||
|
@ -64,6 +61,7 @@ statement(register struct node **pnd;)
|
|||
}
|
||||
|
|
||||
ReturnStatement(pnd)
|
||||
{ return_occurred = 1; }
|
||||
|
|
||||
/* empty */ { *pnd = 0; }
|
||||
;
|
||||
|
@ -88,9 +86,12 @@ StatementSequence(register struct node **pnd;)
|
|||
[ %persistent
|
||||
';' statement(&nd)
|
||||
{ if (nd) {
|
||||
*pnd = MkNode(Link, *pnd, nd, &dot);
|
||||
(*pnd)->nd_symb = ';';
|
||||
pnd = &((*pnd)->nd_right);
|
||||
register struct node *nd1 =
|
||||
MkNode(Link, *pnd, nd, &dot);
|
||||
|
||||
*pnd = nd1;
|
||||
nd1->nd_symb = ';';
|
||||
pnd = &(nd1->nd_right);
|
||||
}
|
||||
}
|
||||
]*
|
||||
|
@ -178,31 +179,29 @@ RepeatStatement(struct node **pnd;)
|
|||
|
||||
ForStatement(struct node **pnd;)
|
||||
{
|
||||
register struct node *nd;
|
||||
register struct node *nd, *nd1;
|
||||
struct node *dummy;
|
||||
}:
|
||||
FOR { *pnd = nd = MkLeaf(Stat, &dot); }
|
||||
IDENT { nd->nd_IDF = dot.TOK_IDF; }
|
||||
BECOMES { nd->nd_left = MkLeaf(Stat, &dot);
|
||||
nd = nd->nd_left;
|
||||
}
|
||||
expression(&(nd->nd_left))
|
||||
BECOMES { nd->nd_left = nd1 = MkLeaf(Stat, &dot); }
|
||||
expression(&(nd1->nd_left))
|
||||
TO
|
||||
expression(&(nd->nd_right))
|
||||
expression(&(nd1->nd_right))
|
||||
[
|
||||
BY
|
||||
ConstExpression(&dummy)
|
||||
{ if (!(dummy->nd_type->tp_fund & T_INTORCARD)) {
|
||||
error("illegal type in BY clause");
|
||||
}
|
||||
nd->nd_INT = dummy->nd_INT;
|
||||
nd1->nd_INT = dummy->nd_INT;
|
||||
FreeNode(dummy);
|
||||
}
|
||||
|
|
||||
{ nd->nd_INT = 1; }
|
||||
{ nd1->nd_INT = 1; }
|
||||
]
|
||||
DO
|
||||
StatementSequence(&((*pnd)->nd_right))
|
||||
StatementSequence(&(nd->nd_right))
|
||||
END
|
||||
;
|
||||
|
||||
|
@ -227,12 +226,9 @@ ReturnStatement(struct node **pnd;)
|
|||
{
|
||||
register struct def *df = CurrentScope->sc_definedby;
|
||||
register struct node *nd;
|
||||
extern int return_occurred;
|
||||
} :
|
||||
|
||||
RETURN { *pnd = nd = MkLeaf(Stat, &dot);
|
||||
return_occurred = 1;
|
||||
}
|
||||
RETURN { *pnd = nd = MkLeaf(Stat, &dot); }
|
||||
[
|
||||
expression(&(nd->nd_right))
|
||||
{ if (scopeclosed(CurrentScope)) {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* T E M P O R A R Y V A R I A B L E S */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
/* Code for the allocation and de-allocation of temporary variables,
|
||||
allowing re-use.
|
||||
The routines use "ProcScope" instead of "CurrentScope", because
|
||||
|
@ -29,7 +25,7 @@ struct tmpvar {
|
|||
arith t_offset; /* offset from LocalBase */
|
||||
};
|
||||
|
||||
/* STATICALLOCDEF "tmpvar" */
|
||||
/* STATICALLOCDEF "tmpvar" 10 */
|
||||
|
||||
static struct tmpvar *TmpInts, /* for integer temporaries */
|
||||
*TmpPtrs; /* for pointer temporaries */
|
||||
|
@ -47,7 +43,7 @@ TmpOpen(sc) struct scope *sc;
|
|||
arith
|
||||
NewInt()
|
||||
{
|
||||
arith offset;
|
||||
register arith offset;
|
||||
register struct tmpvar *tmp;
|
||||
|
||||
if (!TmpInts) {
|
||||
|
@ -67,7 +63,7 @@ NewInt()
|
|||
arith
|
||||
NewPtr()
|
||||
{
|
||||
arith offset;
|
||||
register arith offset;
|
||||
register struct tmpvar *tmp;
|
||||
|
||||
if (!TmpPtrs) {
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* T O K E N D E F I N I T I O N S */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "tokenname.h"
|
||||
#include "Lpars.h"
|
||||
#include "idf.h"
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* 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
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* 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 def *par_def; /* "df" of parameter */
|
||||
|
@ -9,7 +7,7 @@ struct paramlist { /* structure for parameterlist of a PROCEDURE */
|
|||
#define TypeOfParam(xpar) ((xpar)->par_def->df_type)
|
||||
};
|
||||
|
||||
/* ALLOCDEF "paramlist" */
|
||||
/* ALLOCDEF "paramlist" 20 */
|
||||
|
||||
struct enume {
|
||||
struct def *en_enums; /* Definitions of enumeration literals */
|
||||
|
@ -86,7 +84,7 @@ struct type {
|
|||
} tp_value;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "type" */
|
||||
/* ALLOCDEF "type" 50 */
|
||||
|
||||
extern struct type
|
||||
*bool_type,
|
||||
|
@ -125,11 +123,11 @@ extern arith
|
|||
align(); /* type.c */
|
||||
|
||||
struct type
|
||||
*create_type(),
|
||||
*construct_type(),
|
||||
*standard_type(),
|
||||
*set_type(),
|
||||
*subr_type(),
|
||||
*proc_type(),
|
||||
*RemoveEqual(); /* All from type.c */
|
||||
|
||||
#define NULLTYPE ((struct type *) 0)
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* T Y P E D E F I N I T I O N M E C H A N I S M */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
#include "target_sizes.h"
|
||||
#include "debug.h"
|
||||
#include "maxset.h"
|
||||
|
@ -66,21 +62,6 @@ struct type *h_type;
|
|||
int cnt_type;
|
||||
#endif
|
||||
|
||||
struct type *
|
||||
create_type(fund)
|
||||
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;
|
||||
|
||||
return ntp;
|
||||
}
|
||||
|
||||
struct type *
|
||||
construct_type(fund, tp)
|
||||
int fund;
|
||||
|
@ -89,9 +70,9 @@ construct_type(fund, tp)
|
|||
/* fund must be a type constructor.
|
||||
The pointer to the constructed type is returned.
|
||||
*/
|
||||
register struct type *dtp = create_type(fund);
|
||||
register struct type *dtp = new_type();
|
||||
|
||||
switch (fund) {
|
||||
switch (dtp->tp_fund = fund) {
|
||||
case T_PROCEDURE:
|
||||
case T_POINTER:
|
||||
case T_HIDDEN:
|
||||
|
@ -135,8 +116,9 @@ standard_type(fund, align, size)
|
|||
int align;
|
||||
arith size;
|
||||
{
|
||||
register struct type *tp = create_type(fund);
|
||||
register struct type *tp = new_type();
|
||||
|
||||
tp->tp_fund = fund;
|
||||
tp->tp_align = align;
|
||||
tp->tp_size = size;
|
||||
|
||||
|
@ -167,10 +149,6 @@ InitTypes()
|
|||
fatal("long real size smaller than real size");
|
||||
}
|
||||
|
||||
if (!pointer_size || pointer_size % word_size != 0) {
|
||||
fatal("illegal pointer size");
|
||||
}
|
||||
|
||||
/* character type
|
||||
*/
|
||||
char_type = standard_type(T_CHAR, 1, (arith) 1);
|
||||
|
@ -303,6 +281,19 @@ subr_type(lb, ub)
|
|||
return res;
|
||||
}
|
||||
|
||||
struct type *
|
||||
proc_type(result_type, parameters, n_bytes_params)
|
||||
struct type *result_type;
|
||||
struct paramlist *parameters;
|
||||
arith n_bytes_params;
|
||||
{
|
||||
register struct type *tp = construct_type(T_PROCEDURE, result_type);
|
||||
|
||||
tp->prc_params = parameters;
|
||||
tp->prc_nbpar = n_bytes_params;
|
||||
return tp;
|
||||
}
|
||||
|
||||
genrck(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
|
@ -310,20 +301,22 @@ genrck(tp)
|
|||
neccessary. Return its label.
|
||||
*/
|
||||
arith lb, ub;
|
||||
label ol, l;
|
||||
register label ol;
|
||||
int newlabel = 0;
|
||||
|
||||
getbounds(tp, &lb, &ub);
|
||||
|
||||
if (tp->tp_fund == T_SUBRANGE) {
|
||||
if (!(ol = tp->sub_rck)) {
|
||||
tp->sub_rck = l = ++data_label;
|
||||
tp->sub_rck = ol = ++data_label;
|
||||
newlabel = 1;
|
||||
}
|
||||
}
|
||||
else if (!(ol = tp->enm_rck)) {
|
||||
tp->enm_rck = l = ++data_label;
|
||||
tp->enm_rck = ol = ++data_label;
|
||||
newlabel = 1;
|
||||
}
|
||||
if (!ol) {
|
||||
ol = l;
|
||||
if (newlabel) {
|
||||
C_df_dlb(ol);
|
||||
C_rom_cst(lb);
|
||||
C_rom_cst(ub);
|
||||
|
@ -385,7 +378,7 @@ ArrayElSize(tp)
|
|||
Also make sure that its size is either a dividor of the word_size,
|
||||
or a multiple of it.
|
||||
*/
|
||||
arith algn;
|
||||
register arith algn;
|
||||
|
||||
if (tp->tp_fund == T_ARRAY) ArraySizes(tp);
|
||||
algn = align(tp->tp_size, tp->tp_align);
|
||||
|
@ -446,6 +439,7 @@ FreeType(tp)
|
|||
while (pr) {
|
||||
pr1 = pr;
|
||||
pr = pr->next;
|
||||
free_def(pr1->par_def);
|
||||
free_paramlist(pr1);
|
||||
}
|
||||
|
||||
|
@ -520,21 +514,14 @@ DumpType(tp)
|
|||
{
|
||||
if (!tp) return;
|
||||
|
||||
print(" a:%d; s:%ld;", tp->tp_align, (long) tp->tp_size);
|
||||
if (tp->next && tp->tp_fund != T_POINTER) {
|
||||
/* Avoid printing recursive types!
|
||||
*/
|
||||
print(" n:(");
|
||||
DumpType(tp->next);
|
||||
print(")");
|
||||
}
|
||||
print("align:%d; size:%ld;", tp->tp_align, (long) tp->tp_size);
|
||||
|
||||
print(" f:");
|
||||
print(" fund:");
|
||||
switch(tp->tp_fund) {
|
||||
case T_RECORD:
|
||||
print("RECORD"); break;
|
||||
case T_ENUMERATION:
|
||||
print("ENUMERATION; n:%d", tp->enm_ncst); break;
|
||||
print("ENUMERATION; ncst:%d", tp->enm_ncst); break;
|
||||
case T_INTEGER:
|
||||
print("INTEGER"); break;
|
||||
case T_CARDINAL:
|
||||
|
@ -562,7 +549,7 @@ DumpType(tp)
|
|||
|
||||
print("PROCEDURE");
|
||||
if (par) {
|
||||
print("; p:");
|
||||
print("(");
|
||||
while(par) {
|
||||
if (IsVarParam(par)) print("VAR ");
|
||||
DumpType(TypeOfParam(par));
|
||||
|
@ -573,11 +560,12 @@ DumpType(tp)
|
|||
}
|
||||
case T_ARRAY:
|
||||
print("ARRAY");
|
||||
print("; el:");
|
||||
print("; element:");
|
||||
DumpType(tp->arr_elem);
|
||||
print("; index:");
|
||||
DumpType(tp->next);
|
||||
break;
|
||||
print(";");
|
||||
return;
|
||||
case T_STRING:
|
||||
print("STRING"); break;
|
||||
case T_INTORCARD:
|
||||
|
@ -585,6 +573,13 @@ DumpType(tp)
|
|||
default:
|
||||
crash("DumpType");
|
||||
}
|
||||
if (tp->next && tp->tp_fund != T_POINTER) {
|
||||
/* Avoid printing recursive types!
|
||||
*/
|
||||
print(" next:(");
|
||||
DumpType(tp->next);
|
||||
print(")");
|
||||
}
|
||||
print(";");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* T Y P E E Q U I V A L E N C E */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
/* Routines for testing type equivalence, type compatibility, and
|
||||
assignment compatibility
|
||||
*/
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
/* P A R S E T R E E W A L K E R */
|
||||
|
||||
#ifndef NORCSID
|
||||
static char *RcsId = "$Header$";
|
||||
#endif
|
||||
|
||||
/* Routines to walk through parts of the parse tree, and generate
|
||||
code for these parts.
|
||||
*/
|
||||
|
@ -103,11 +99,6 @@ WalkModule(module)
|
|||
C_loe_dlb(l1, (arith) 0);
|
||||
C_zne(RETURN_LABEL);
|
||||
C_ine_dlb(l1, (arith) 0);
|
||||
/* Prevent this module from calling its own
|
||||
initialization routine
|
||||
*/
|
||||
assert(nd->nd_IDF == module->df_idf);
|
||||
nd = nd->next;
|
||||
}
|
||||
|
||||
for (; nd; nd = nd->next) {
|
||||
|
@ -415,17 +406,16 @@ WalkStat(nd, exit_label)
|
|||
break;
|
||||
|
||||
case IF:
|
||||
{ label l1, l2, l3;
|
||||
{ label l1 = ++text_label, l3 = ++text_label;
|
||||
|
||||
l1 = ++text_label;
|
||||
l2 = ++text_label;
|
||||
l3 = ++text_label;
|
||||
ExpectBool(left, l3, l1);
|
||||
assert(right->nd_symb == THEN);
|
||||
C_df_ilb(l3);
|
||||
WalkNode(right->nd_left, exit_label);
|
||||
|
||||
if (right->nd_right) { /* ELSE part */
|
||||
label l2 = ++text_label;
|
||||
|
||||
C_bra(l2);
|
||||
C_df_ilb(l1);
|
||||
WalkNode(right->nd_right, exit_label);
|
||||
|
@ -440,73 +430,72 @@ WalkStat(nd, exit_label)
|
|||
break;
|
||||
|
||||
case WHILE:
|
||||
{ label l1, l2, l3;
|
||||
{ label loop = ++text_label,
|
||||
exit = ++text_label,
|
||||
dummy = ++text_label;
|
||||
|
||||
l1 = ++text_label;
|
||||
l2 = ++text_label;
|
||||
l3 = ++text_label;
|
||||
C_df_ilb(l1);
|
||||
ExpectBool(left, l3, l2);
|
||||
C_df_ilb(l3);
|
||||
C_df_ilb(loop);
|
||||
ExpectBool(left, dummy, exit);
|
||||
C_df_ilb(dummy);
|
||||
WalkNode(right, exit_label);
|
||||
C_bra(l1);
|
||||
C_df_ilb(l2);
|
||||
C_bra(loop);
|
||||
C_df_ilb(exit);
|
||||
break;
|
||||
}
|
||||
|
||||
case REPEAT:
|
||||
{ label l1, l2;
|
||||
{ label loop = ++text_label, exit = ++text_label;
|
||||
|
||||
l1 = ++text_label;
|
||||
l2 = ++text_label;
|
||||
C_df_ilb(l1);
|
||||
C_df_ilb(loop);
|
||||
WalkNode(left, exit_label);
|
||||
ExpectBool(right, l2, l1);
|
||||
C_df_ilb(l2);
|
||||
ExpectBool(right, exit, loop);
|
||||
C_df_ilb(exit);
|
||||
break;
|
||||
}
|
||||
|
||||
case LOOP:
|
||||
{ label l1, l2;
|
||||
{ label loop = ++text_label, exit = ++text_label;
|
||||
|
||||
l1 = ++text_label;
|
||||
l2 = ++text_label;
|
||||
C_df_ilb(l1);
|
||||
WalkNode(right, l2);
|
||||
C_bra(l1);
|
||||
C_df_ilb(l2);
|
||||
C_df_ilb(loop);
|
||||
WalkNode(right, exit);
|
||||
C_bra(loop);
|
||||
C_df_ilb(exit);
|
||||
break;
|
||||
}
|
||||
|
||||
case FOR:
|
||||
{
|
||||
arith tmp = 0;
|
||||
struct node *fnd;
|
||||
register struct node *fnd;
|
||||
label l1 = ++text_label;
|
||||
label l2 = ++text_label;
|
||||
|
||||
if (! DoForInit(nd, left)) break;
|
||||
fnd = left->nd_right;
|
||||
if (fnd->nd_class != Value) {
|
||||
/* Upperbound not constant.
|
||||
The expression may only be evaluated once,
|
||||
so generate a temporary for it
|
||||
*/
|
||||
CodePExpr(fnd);
|
||||
tmp = NewInt();
|
||||
C_stl(tmp);
|
||||
}
|
||||
C_bra(l1);
|
||||
C_df_ilb(l2);
|
||||
C_df_ilb(l1);
|
||||
C_dup(int_size);
|
||||
if (tmp) C_lol(tmp); else C_loc(fnd->nd_INT);
|
||||
if (left->nd_INT > 0) {
|
||||
C_bgt(l2);
|
||||
}
|
||||
else C_blt(l2);
|
||||
RangeCheck(nd->nd_type, int_type);
|
||||
CodeDStore(nd);
|
||||
WalkNode(right, exit_label);
|
||||
CodePExpr(nd);
|
||||
C_loc(left->nd_INT);
|
||||
C_adi(int_size);
|
||||
C_df_ilb(l1);
|
||||
C_dup(int_size);
|
||||
if (tmp) C_lol(tmp); else C_loc(fnd->nd_INT);
|
||||
if (left->nd_INT > 0) {
|
||||
C_ble(l2);
|
||||
}
|
||||
else C_bge(l2);
|
||||
C_bra(l1);
|
||||
C_df_ilb(l2);
|
||||
C_asp(int_size);
|
||||
if (tmp) FreeInt(tmp);
|
||||
}
|
||||
|
@ -517,7 +506,6 @@ WalkStat(nd, exit_label)
|
|||
struct scopelist link;
|
||||
struct withdesig wds;
|
||||
struct desig ds;
|
||||
arith tmp = 0;
|
||||
|
||||
if (! WalkDesignator(left, &ds)) break;
|
||||
if (left->nd_type->tp_fund != T_RECORD) {
|
||||
|
@ -532,7 +520,7 @@ WalkStat(nd, exit_label)
|
|||
ds.dsg_kind = DSG_FIXED;
|
||||
/* Create a designator structure for the temporary.
|
||||
*/
|
||||
ds.dsg_offset = tmp = NewPtr();
|
||||
ds.dsg_offset = NewPtr();
|
||||
ds.dsg_name = 0;
|
||||
CodeStore(&ds, pointer_size);
|
||||
ds.dsg_kind = DSG_PFIXED;
|
||||
|
@ -544,7 +532,7 @@ WalkStat(nd, exit_label)
|
|||
WalkNode(right, exit_label);
|
||||
CurrVis = link.next;
|
||||
WithDesigs = wds.w_next;
|
||||
FreePtr(tmp);
|
||||
FreePtr(ds.dsg_offset);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -648,12 +636,13 @@ DoForInit(nd, left)
|
|||
nd->nd_symb = IDENT;
|
||||
|
||||
if (! ChkVariable(nd) ||
|
||||
! ChkExpression(left->nd_left) ||
|
||||
! WalkExpr(left->nd_left) ||
|
||||
! ChkExpression(left->nd_right)) return 0;
|
||||
|
||||
df = nd->nd_def;
|
||||
if (df->df_kind == D_FIELD) {
|
||||
node_error(nd, "FOR-loop variable may not be a field of a record");
|
||||
node_error(nd,
|
||||
"FOR-loop variable may not be a field of a record");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -665,14 +654,15 @@ DoForInit(nd, left)
|
|||
if (df->df_scope != CurrentScope) {
|
||||
register struct scopelist *sc = CurrVis;
|
||||
|
||||
while (sc && sc->sc_scope != df->df_scope) {
|
||||
for (;;) {
|
||||
if (!sc) {
|
||||
node_error(nd,
|
||||
"FOR-loop variable may not be imported");
|
||||
return 0;
|
||||
}
|
||||
if (sc->sc_scope == df->df_scope) break;
|
||||
sc = nextvisible(sc);
|
||||
}
|
||||
|
||||
if (!sc) {
|
||||
node_error(nd, "FOR-loop variable may not be imported");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (df->df_type->tp_size > word_size ||
|
||||
|
@ -691,8 +681,6 @@ DoForInit(nd, left)
|
|||
node_warning(nd, "old-fashioned! compatibility required in FOR statement");
|
||||
}
|
||||
|
||||
CodePExpr(left->nd_left);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -703,11 +691,12 @@ DoAssign(nd, left, right)
|
|||
/* May we do it in this order (expression first) ???
|
||||
The reference manual sais nothing about it, but the book does:
|
||||
it sais that the left hand side is evaluated first.
|
||||
DAMN THE BOOK!
|
||||
*/
|
||||
struct desig dsl, dsr;
|
||||
|
||||
if (! ChkExpression(right)) return;
|
||||
if (! ChkVariable(left)) return;
|
||||
if (! ChkExpression(right) || ! ChkVariable(left)) return;
|
||||
|
||||
if (right->nd_symb == STRING) TryToString(right, left->nd_type);
|
||||
dsr = InitDesig;
|
||||
CodeExpr(right, &dsr, NO_LABEL, NO_LABEL);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/* P A R S E T R E E W A L K E R */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/* Definition of WalkNode macro
|
||||
*/
|
||||
|
||||
|
|
Loading…
Reference in a new issue