fixup commit for tag 'llgen-1-0'
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
LLlex.c
|
||||
LLlex.h
|
||||
LLmessage.c
|
||||
proto.make
|
||||
proto.main
|
||||
BigPars
|
||||
SmallPars
|
||||
SYSTEM.h
|
||||
casestat.C
|
||||
char.tab
|
||||
chk_expr.c
|
||||
chk_expr.h
|
||||
class.h
|
||||
code.c
|
||||
cstoper.c
|
||||
debug.h
|
||||
declar.g
|
||||
def.H
|
||||
def.c
|
||||
defmodule.c
|
||||
desig.c
|
||||
desig.h
|
||||
em_m2.6
|
||||
enter.c
|
||||
error.c
|
||||
expression.g
|
||||
f_info.h
|
||||
idf.c
|
||||
idf.h
|
||||
input.c
|
||||
input.h
|
||||
lookup.c
|
||||
main.c
|
||||
main.h
|
||||
make.allocd
|
||||
make.hfiles
|
||||
make.next
|
||||
make.tokcase
|
||||
make.tokfile
|
||||
misc.c
|
||||
misc.h
|
||||
modula-2.1
|
||||
node.H
|
||||
node.c
|
||||
options.c
|
||||
options
|
||||
program.g
|
||||
real.H
|
||||
scope.C
|
||||
scope.h
|
||||
stab.c
|
||||
standards.h
|
||||
statement.g
|
||||
tmpvar.C
|
||||
tokenname.c
|
||||
tokenname.h
|
||||
type.H
|
||||
type.c
|
||||
typequiv.c
|
||||
walk.c
|
||||
walk.h
|
||||
warning.h
|
||||
@@ -1,100 +0,0 @@
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define ERR_SHADOW 5 /* a syntax error overshadows error messages
|
||||
until ERR_SHADOW symbols have been
|
||||
accepted without syntax error */
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 128 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: strsize.h
|
||||
#define ISTRSIZE 32 /* minimum number of bytes allocated for
|
||||
storing a string */
|
||||
#define RSTRSIZE 8 /* step size in enlarging the memory for
|
||||
the storage of a string */
|
||||
|
||||
|
||||
!File: target_sizes.h
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR ((arith)1)
|
||||
#define SZ_SHORT ((arith)2)
|
||||
#define SZ_WORD ((arith)4)
|
||||
#define SZ_INT ((arith)4)
|
||||
#define SZ_LONG ((arith)4)
|
||||
#define SZ_FLOAT ((arith)4)
|
||||
#define SZ_DOUBLE ((arith)8)
|
||||
#define SZ_POINTER ((arith)4)
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_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 ((int)SZ_WORD)
|
||||
|
||||
|
||||
!File: debugcst.h
|
||||
/*#define DEBUG 1 /* perform various self-tests */
|
||||
#define NDEBUG 1 /* disable assertions */
|
||||
|
||||
!File: inputtype.h
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 3 /* see casestat.C for an explanation */
|
||||
|
||||
|
||||
!File: squeeze.h
|
||||
/*#define SQUEEZE 1 /* define on "small" machines */
|
||||
|
||||
|
||||
!File: strict3rd.h
|
||||
/*#define STRICT_3RD_ED 1 /* define on "small" machines, and if you want
|
||||
a compiler that only implements "3rd edition"
|
||||
Modula-2
|
||||
*/
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
/*#define NOCROSS 1 /* define when cross-compiler not needed */
|
||||
|
||||
|
||||
!File: nostrict.h
|
||||
/*#define NOSTRICT 1 /* define when STRICT warnings disabled
|
||||
(yet another squeezing method)
|
||||
*/
|
||||
|
||||
|
||||
!File: bigresult.h
|
||||
#define BIG_RESULT_ON_STACK 1 /* define when function results must be
|
||||
put on the stack; in this case, caller
|
||||
reserves space for it. When not defined,
|
||||
callee puts result in global data area and
|
||||
returns a pointer to it
|
||||
*/
|
||||
|
||||
|
||||
!File: dbsymtab.h
|
||||
#define DBSYMTAB 1 /* ability to produce symbol table for debugger */
|
||||
|
||||
|
||||
!File: use_insert.h
|
||||
#define USE_INSERT 1 /* use C_insertpart mechanism */
|
||||
|
||||
|
||||
!File: uns_arith.h
|
||||
/*#define UNSIGNED_ARITH unsigned arith /* when it is supported */
|
||||
|
||||
|
||||
@@ -1,671 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* L E X I C A L A N A L Y S E R F O R M O D U L A - 2 */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
#include "idfsize.h"
|
||||
#include "numsize.h"
|
||||
#include "strsize.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "Lpars.h"
|
||||
#include "class.h"
|
||||
#include "idf.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "warning.h"
|
||||
#include "errout.h"
|
||||
|
||||
extern char *getwdir();
|
||||
|
||||
t_token dot,
|
||||
aside;
|
||||
t_type *toktype;
|
||||
int idfsize = IDFSIZE;
|
||||
int ForeignFlag;
|
||||
#ifdef DEBUG
|
||||
extern int cntlines;
|
||||
#endif
|
||||
|
||||
int token_nmb = 0;
|
||||
int tk_nmb_at_last_syn_err = -ERR_SHADOW;
|
||||
|
||||
extern char options[];
|
||||
extern int flt_status;
|
||||
|
||||
STATIC
|
||||
SkipComment()
|
||||
{
|
||||
/* Skip Modula-2 comments (* ... *).
|
||||
Note that comments may be nested (par. 3.5).
|
||||
*/
|
||||
register int ch, c;
|
||||
register int CommentLevel = 0;
|
||||
|
||||
LoadChar(ch);
|
||||
if (ch == '$') {
|
||||
LoadChar(ch);
|
||||
switch(ch) {
|
||||
case 'F':
|
||||
/* Foreign; This definition module has an
|
||||
implementation in another language.
|
||||
In this case, don't generate prefixes in front
|
||||
of the names. Also, don't generate call to
|
||||
initialization routine.
|
||||
*/
|
||||
ForeignFlag = D_FOREIGN;
|
||||
break;
|
||||
case 'U':
|
||||
inidf['_'] = 1;
|
||||
break;
|
||||
case 'A': /* Extra array bound checks, on or off */
|
||||
case 'R': /* Range checks, on or off */
|
||||
{
|
||||
int on_on_minus = ch == 'R';
|
||||
LoadChar(c);
|
||||
if (c == '-') {
|
||||
options[ch] = on_on_minus;
|
||||
break;
|
||||
}
|
||||
if (c == '+') {
|
||||
options[ch] = !on_on_minus;
|
||||
break;
|
||||
}
|
||||
ch = c;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (;;) {
|
||||
if (!(ch & 0200) && class(ch) == STNL) {
|
||||
LineNumber++;
|
||||
#ifdef DEBUG
|
||||
cntlines++;
|
||||
#endif
|
||||
}
|
||||
else if (ch == '(') {
|
||||
LoadChar(ch);
|
||||
if (ch == '*') CommentLevel++;
|
||||
else continue;
|
||||
}
|
||||
else if (ch == '*') {
|
||||
LoadChar(ch);
|
||||
if (ch == ')') {
|
||||
CommentLevel--;
|
||||
if (CommentLevel < 0) break;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
else if (ch == EOI) {
|
||||
lexerror("unterminated comment");
|
||||
PushBack();
|
||||
break;
|
||||
}
|
||||
LoadChar(ch);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC struct string *
|
||||
GetString(upto)
|
||||
{
|
||||
/* Read a Modula-2 string, delimited by the character "upto".
|
||||
*/
|
||||
register int ch;
|
||||
register struct string *str = (struct string *)
|
||||
Malloc((unsigned) sizeof(struct string));
|
||||
register char *p;
|
||||
register int len;
|
||||
|
||||
len = ISTRSIZE;
|
||||
str->s_str = p = Malloc((unsigned int) ISTRSIZE);
|
||||
while (LoadChar(ch), ch != upto) {
|
||||
if (!(ch & 0200) && class(ch) == STNL) {
|
||||
lexerror("newline in string");
|
||||
LineNumber++;
|
||||
#ifdef DEBUG
|
||||
cntlines++;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
lexerror("end-of-file in string");
|
||||
break;
|
||||
}
|
||||
*p++ = ch;
|
||||
if (p - str->s_str == len) {
|
||||
str->s_str = Realloc(str->s_str,
|
||||
(unsigned int) len + RSTRSIZE);
|
||||
p = str->s_str + len;
|
||||
len += RSTRSIZE;
|
||||
}
|
||||
}
|
||||
str->s_length = p - str->s_str;
|
||||
len = (str->s_length+(int)word_size) & ~((int)word_size-1);
|
||||
while (p - str->s_str < len) {
|
||||
*p++ = '\0';
|
||||
}
|
||||
str->s_str = Realloc(str->s_str, (unsigned) len);
|
||||
if (str->s_length == 0) str->s_length = 1;
|
||||
/* ??? string length at least 1 ??? */
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *s_error = "illegal line directive";
|
||||
|
||||
STATIC int
|
||||
getch()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
while (LoadChar(ch), (ch & 0200) && ch != EOI) {
|
||||
error("non-ascii '\\%03o' read", ch & 0377);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
CheckForLineDirective()
|
||||
{
|
||||
register int ch = getch();
|
||||
register int i = 0;
|
||||
char buf[IDFSIZE];
|
||||
register char *c = buf;
|
||||
|
||||
|
||||
if (ch != '#') {
|
||||
PushBack();
|
||||
return;
|
||||
}
|
||||
do { /*
|
||||
* Skip to next digit
|
||||
* Do not skip newlines
|
||||
*/
|
||||
ch = getch();
|
||||
if (class(ch) == STNL || class(ch) == STEOI) {
|
||||
LineNumber++;
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
} while (class(ch) != STNUM);
|
||||
while (class(ch) == STNUM) {
|
||||
i = i*10 + (ch - '0');
|
||||
ch = getch();
|
||||
}
|
||||
while (ch != '"' && class(ch) != STNL && class(ch) != STEOI)
|
||||
ch = getch();
|
||||
if (ch == '"') {
|
||||
c = buf;
|
||||
do {
|
||||
ch = getch();
|
||||
if (c < &buf[IDFSIZE]) *c++ = ch;
|
||||
if (class(ch) == STNL || class(ch) == STEOI) {
|
||||
LineNumber++;
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
} while (ch != '"');
|
||||
*--c = '\0';
|
||||
do {
|
||||
ch = getch();
|
||||
} while (class(ch) != STNL && class(ch) != STEOI);
|
||||
/*
|
||||
* Remember the file name
|
||||
*/
|
||||
if (class(ch) == STNL && strcmp(FileName,buf)) {
|
||||
FileName = Salloc(buf,(unsigned) strlen(buf) + 1);
|
||||
WorkingDir = getwdir(FileName);
|
||||
}
|
||||
}
|
||||
if (class(ch) == STEOI) {
|
||||
error(s_error);
|
||||
return;
|
||||
}
|
||||
LineNumber = i;
|
||||
}
|
||||
|
||||
STATIC
|
||||
CheckForLet()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
LoadChar(ch);
|
||||
if (ch != EOI) {
|
||||
if (class(ch) == STIDF) {
|
||||
lexerror("token separator required between identifier and number");
|
||||
}
|
||||
PushBack();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
LLlex()
|
||||
{
|
||||
/* LLlex() is the Lexical Analyzer.
|
||||
The putting aside of tokens is taken into account.
|
||||
*/
|
||||
register t_token *tk = ˙
|
||||
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 2];
|
||||
register int ch, nch;
|
||||
|
||||
toktype = error_type;
|
||||
|
||||
if (ASIDE) { /* a token is put aside */
|
||||
*tk = aside;
|
||||
ASIDE = 0;
|
||||
return tk->tk_symb;
|
||||
}
|
||||
|
||||
token_nmb++;
|
||||
again:
|
||||
ch = getch();
|
||||
tk->tk_lineno = LineNumber;
|
||||
|
||||
switch (class(ch)) {
|
||||
|
||||
case STNL:
|
||||
LineNumber++;
|
||||
#ifdef DEBUG
|
||||
cntlines++;
|
||||
#endif
|
||||
CheckForLineDirective();
|
||||
goto again;
|
||||
|
||||
case STSKIP:
|
||||
goto again;
|
||||
|
||||
case STGARB:
|
||||
if ((unsigned) ch - 040 < 0137) {
|
||||
lexerror("garbage char %c", ch);
|
||||
}
|
||||
else lexerror("garbage char \\%03o", ch);
|
||||
goto again;
|
||||
|
||||
case STSIMP:
|
||||
if (ch == '(') {
|
||||
LoadChar(nch);
|
||||
if (nch == '*') {
|
||||
SkipComment();
|
||||
goto again;
|
||||
}
|
||||
PushBack();
|
||||
}
|
||||
if (ch == '&') return tk->tk_symb = AND;
|
||||
if (ch == '~') return tk->tk_symb = NOT;
|
||||
return tk->tk_symb = ch;
|
||||
|
||||
case STCOMP:
|
||||
LoadChar(nch);
|
||||
switch (ch) {
|
||||
|
||||
case '.':
|
||||
if (nch == '.') {
|
||||
return tk->tk_symb = UPTO;
|
||||
}
|
||||
break;
|
||||
|
||||
case ':':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = BECOMES;
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = LESSEQUAL;
|
||||
}
|
||||
if (nch == '>') {
|
||||
return tk->tk_symb = '#';
|
||||
}
|
||||
break;
|
||||
|
||||
case '>':
|
||||
if (nch == '=') {
|
||||
return tk->tk_symb = GREATEREQUAL;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
crash("(LLlex, STCOMP)");
|
||||
}
|
||||
PushBack();
|
||||
return tk->tk_symb = ch;
|
||||
|
||||
case STIDF:
|
||||
{
|
||||
register char *tag = &buf[0];
|
||||
register t_idf *id;
|
||||
|
||||
do {
|
||||
if (tag - buf < idfsize) *tag++ = ch;
|
||||
LoadChar(ch);
|
||||
if (ch == '_' && *(tag-1) == '_') {
|
||||
lexerror("an identifier may not contain two consecutive underscores");
|
||||
}
|
||||
} while(in_idf(ch));
|
||||
|
||||
PushBack();
|
||||
*tag = '\0';
|
||||
if (*(tag - 1) == '_') {
|
||||
lexerror("last character of an identifier may not be an underscore");
|
||||
}
|
||||
|
||||
tk->TOK_IDF = id = str2idf(buf, 1);
|
||||
return tk->tk_symb = id->id_reserved ? id->id_reserved : IDENT;
|
||||
}
|
||||
|
||||
case STSTR: {
|
||||
register struct string *str = GetString(ch);
|
||||
|
||||
if (str->s_length == 1) {
|
||||
tk->TOK_INT = *(str->s_str) & 0377;
|
||||
toktype = char_type;
|
||||
free(str->s_str);
|
||||
free((char *) str);
|
||||
}
|
||||
else {
|
||||
tk->tk_data.tk_str = str;
|
||||
if (! fit((arith)(str->s_length), (int) word_size)) {
|
||||
lexerror("string too long");
|
||||
}
|
||||
toktype = standard_type(T_STRING, 1, (arith)(str->s_length));
|
||||
}
|
||||
return tk->tk_symb = STRING;
|
||||
}
|
||||
|
||||
case STNUM:
|
||||
{
|
||||
/* The problem arising with the "parsing" of a number
|
||||
is that we don't know the base in advance so we
|
||||
have to read the number with the help of a rather
|
||||
complex finite automaton.
|
||||
*/
|
||||
enum statetp {Oct,OptHex,Hex,Dec,OctEndOrHex,End,OptReal,Real};
|
||||
register enum statetp state;
|
||||
register int base = 8;
|
||||
register char *np = &buf[0];
|
||||
|
||||
*np++ = ch;
|
||||
state = is_oct(ch) ? Oct : Dec;
|
||||
LoadChar(ch);
|
||||
for (;;) {
|
||||
switch(state) {
|
||||
case Oct:
|
||||
while (is_oct(ch)) {
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (ch == 'B' || ch == 'C') {
|
||||
state = OctEndOrHex;
|
||||
break;
|
||||
}
|
||||
/* Fall Through */
|
||||
case Dec:
|
||||
base = 10;
|
||||
while (is_dig(ch)) {
|
||||
if (np < &buf[NUMSIZE]) {
|
||||
*np++ = ch;
|
||||
}
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (ch == 'D') state = OptHex;
|
||||
else if (is_hex(ch)) state = Hex;
|
||||
else if (ch == '.') state = OptReal;
|
||||
else {
|
||||
state = End;
|
||||
if (ch == 'H') base = 16;
|
||||
else PushBack();
|
||||
}
|
||||
break;
|
||||
|
||||
case OptHex:
|
||||
LoadChar(ch);
|
||||
if (is_hex(ch)) {
|
||||
if (np < &buf[NUMSIZE]) *np++ = 'D';
|
||||
state = Hex;
|
||||
}
|
||||
else {
|
||||
state = End;
|
||||
ch = 'D';
|
||||
PushBack();
|
||||
}
|
||||
break;
|
||||
|
||||
case Hex:
|
||||
while (is_hex(ch)) {
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
base = 16;
|
||||
state = End;
|
||||
if (ch != 'H') {
|
||||
lexerror("H expected after hex number");
|
||||
PushBack();
|
||||
}
|
||||
break;
|
||||
|
||||
case OctEndOrHex:
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
if (ch == 'H') {
|
||||
base = 16;
|
||||
state = End;
|
||||
break;
|
||||
}
|
||||
if (is_hex(ch)) {
|
||||
state = Hex;
|
||||
break;
|
||||
}
|
||||
PushBack();
|
||||
ch = *--np;
|
||||
*np++ = '\0';
|
||||
/* Fall through */
|
||||
|
||||
case End: {
|
||||
int ovfl = 0;
|
||||
|
||||
*np = '\0';
|
||||
if (np >= &buf[NUMSIZE]) {
|
||||
tk->TOK_INT = 1;
|
||||
lexerror("constant too long");
|
||||
}
|
||||
else {
|
||||
/* The upperbound will be the same as
|
||||
when computed with something like
|
||||
max(unsigned long) / base (when base
|
||||
is even). The problem is that
|
||||
unsigned long or unsigned arith is
|
||||
not accepted by all compilers
|
||||
*/
|
||||
arith ubound = max_int[sizeof(arith)]
|
||||
/ (base >> 1);
|
||||
np = &buf[0];
|
||||
while (*np == '0') np++;
|
||||
tk->TOK_INT = 0;
|
||||
while (*np) {
|
||||
int c;
|
||||
|
||||
if (is_dig(*np)) {
|
||||
c = *np++ - '0';
|
||||
}
|
||||
else {
|
||||
assert(is_hex(*np));
|
||||
c = *np++ - 'A' + 10;
|
||||
}
|
||||
if (tk->TOK_INT < 0 ||
|
||||
tk->TOK_INT > ubound) {
|
||||
ovfl++;
|
||||
}
|
||||
tk->TOK_INT = tk->TOK_INT*base;
|
||||
if (tk->TOK_INT < 0 &&
|
||||
tk->TOK_INT + c >= 0) {
|
||||
ovfl++;
|
||||
}
|
||||
tk->TOK_INT += c;
|
||||
}
|
||||
}
|
||||
toktype = card_type;
|
||||
if (ch == 'C' && base == 8) {
|
||||
toktype = char_type;
|
||||
if (ovfl != 0 || tk->TOK_INT>255 ||
|
||||
tk->TOK_INT < 0) {
|
||||
lexwarning(W_ORDINARY, "character constant out of range");
|
||||
}
|
||||
CheckForLet();
|
||||
return tk->tk_symb = INTEGER;
|
||||
}
|
||||
if (options['l']) {
|
||||
if (base != 10) {
|
||||
LoadChar(ch);
|
||||
if (ch != 'D') {
|
||||
PushBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ch == 'D' && (options['l'] || base == 10)) {
|
||||
if (options['l']) {
|
||||
/* Local extension: LONGCARD exists,
|
||||
so internally also longintorcard_type
|
||||
exists.
|
||||
*/
|
||||
toktype = longcard_type;
|
||||
if (ovfl == 0 && tk->TOK_INT >= 0 &&
|
||||
tk->TOK_INT<=max_int[(int)long_size]) {
|
||||
toktype = longintorcard_type;
|
||||
}
|
||||
else if (! chk_bounds(tk->TOK_INT,
|
||||
full_mask[(int)long_size],
|
||||
T_CARDINAL)) {
|
||||
ovfl = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ovfl != 0 ||
|
||||
tk->TOK_INT > max_int[(int)long_size] ||
|
||||
tk->TOK_INT < 0) {
|
||||
ovfl = 1;
|
||||
}
|
||||
toktype = longint_type;
|
||||
}
|
||||
}
|
||||
else if (ovfl == 0 && tk->TOK_INT >= 0 &&
|
||||
tk->TOK_INT<=max_int[(int)int_size]) {
|
||||
toktype = intorcard_type;
|
||||
}
|
||||
else if (! chk_bounds(tk->TOK_INT,
|
||||
full_mask[(int)int_size],
|
||||
T_CARDINAL)) {
|
||||
ovfl = 1;
|
||||
}
|
||||
if (ovfl)
|
||||
lexwarning(W_ORDINARY, "overflow in constant");
|
||||
CheckForLet();
|
||||
return tk->tk_symb = INTEGER;
|
||||
}
|
||||
|
||||
case OptReal:
|
||||
/* The '.' could be the first of the '..'
|
||||
token. At this point, we need a
|
||||
look-ahead of two characters.
|
||||
*/
|
||||
LoadChar(ch);
|
||||
if (ch == '.') {
|
||||
/* Indeed the '..' token
|
||||
*/
|
||||
PushBack();
|
||||
PushBack();
|
||||
state = End;
|
||||
base = 10;
|
||||
break;
|
||||
}
|
||||
state = Real;
|
||||
break;
|
||||
}
|
||||
if (state == Real) break;
|
||||
}
|
||||
|
||||
/* a real real constant */
|
||||
if (np < &buf[NUMSIZE]) *np++ = '.';
|
||||
|
||||
toktype = real_type;
|
||||
|
||||
while (is_dig(ch)) {
|
||||
/* Fractional part
|
||||
*/
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
|
||||
if (ch == 'D') {
|
||||
toktype = longreal_type;
|
||||
LoadChar(ch);
|
||||
if (ch == '+' || ch == '-' || is_dig(ch)) {
|
||||
ch = 'E';
|
||||
PushBack();
|
||||
}
|
||||
}
|
||||
if (ch == 'E') {
|
||||
/* Scale factor
|
||||
*/
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
if (ch == '+' || ch == '-') {
|
||||
/* Signed scalefactor
|
||||
*/
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (is_dig(ch)) {
|
||||
do {
|
||||
if (np < &buf[NUMSIZE]) *np++ = ch;
|
||||
LoadChar(ch);
|
||||
} while (is_dig(ch));
|
||||
}
|
||||
else {
|
||||
lexerror("bad scale factor");
|
||||
}
|
||||
}
|
||||
|
||||
*np++ = '\0';
|
||||
PushBack();
|
||||
|
||||
tk->tk_data.tk_real = new_real();
|
||||
if (np >= &buf[NUMSIZE]) {
|
||||
tk->TOK_RSTR = Salloc("0.0", 4);
|
||||
lexerror("real constant too long");
|
||||
}
|
||||
else tk->TOK_RSTR = Salloc(buf, (unsigned) (np - buf));
|
||||
CheckForLet();
|
||||
flt_str2flt(tk->TOK_RSTR, &(tk->TOK_RVAL));
|
||||
if (flt_status == FLT_OVFL) {
|
||||
lexwarning(W_ORDINARY, "overflow in floating point constant");
|
||||
}
|
||||
return tk->tk_symb = REAL;
|
||||
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
case STEOI:
|
||||
return tk->tk_symb = -1;
|
||||
|
||||
case STCHAR:
|
||||
default:
|
||||
crash("(LLlex) Impossible character class");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T O K E N D E S C R I P T O R D E F I N I T I O N */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "real.h"
|
||||
|
||||
/* Structure to store a string constant
|
||||
*/
|
||||
struct string {
|
||||
unsigned s_length; /* length of a string */
|
||||
char *s_str; /* the string itself */
|
||||
};
|
||||
|
||||
union tk_attr {
|
||||
struct string *tk_str;
|
||||
arith tk_int;
|
||||
struct real *tk_real;
|
||||
struct {
|
||||
union {
|
||||
arith *tky_set;
|
||||
struct idf *tky_idf;
|
||||
struct def *tky_def;
|
||||
} tk_yy;
|
||||
struct node *tky_next;
|
||||
} tk_y;
|
||||
struct {
|
||||
struct node *tkx_left, *tkx_right;
|
||||
} tk_x;
|
||||
};
|
||||
#define tk_left tk_x.tkx_left
|
||||
#define tk_right tk_x.tkx_right
|
||||
#define tk_next tk_y.tky_next
|
||||
#define tk_idf tk_y.tk_yy.tky_idf
|
||||
#define tk_def tk_y.tk_yy.tky_def
|
||||
#define tk_set tk_y.tk_yy.tky_set
|
||||
|
||||
/* Token structure. Keep it small, as it is part of a parse-tree node
|
||||
*/
|
||||
struct token {
|
||||
short tk_symb; /* token itself */
|
||||
unsigned short tk_lineno; /* linenumber on which it occurred */
|
||||
union tk_attr tk_data;
|
||||
};
|
||||
|
||||
typedef struct token t_token;
|
||||
|
||||
#define TOK_IDF tk_data.tk_idf
|
||||
#define TOK_SSTR tk_data.tk_str
|
||||
#define TOK_STR tk_data.tk_str->s_str
|
||||
#define TOK_SLE tk_data.tk_str->s_length
|
||||
#define TOK_INT tk_data.tk_int
|
||||
#define TOK_REAL tk_data.tk_real
|
||||
#define TOK_RSTR tk_data.tk_real->r_real
|
||||
#define TOK_RVAL tk_data.tk_real->r_val
|
||||
|
||||
extern t_token dot, aside;
|
||||
extern struct type *toktype;
|
||||
|
||||
#define DOT dot.tk_symb
|
||||
#define ASIDE aside.tk_symb
|
||||
|
||||
extern int token_nmb;
|
||||
extern int tk_nmb_at_last_syn_err;
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S Y N T A X E R R O R R E P O R T I N G */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Defines the LLmessage routine. LLgen-generated parsers require the
|
||||
existence of a routine of that name.
|
||||
The routine must do syntax-error reporting and must be able to
|
||||
insert tokens in the token stream.
|
||||
*/
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
extern char *symbol2str();
|
||||
extern t_idf *gen_anon_idf();
|
||||
|
||||
LLmessage(tk)
|
||||
register int tk;
|
||||
{
|
||||
if (tk > 0) {
|
||||
/* if (tk > 0), it represents the token to be inserted.
|
||||
*/
|
||||
register t_token *dotp = ˙
|
||||
|
||||
#ifndef LLNONCORR
|
||||
error("%s missing before %s", symbol2str(tk), symbol2str(dotp->tk_symb));
|
||||
#endif
|
||||
|
||||
aside = *dotp;
|
||||
|
||||
dotp->tk_symb = tk;
|
||||
|
||||
switch (tk) {
|
||||
/* The operands need some body */
|
||||
case IDENT:
|
||||
dotp->TOK_IDF = gen_anon_idf();
|
||||
break;
|
||||
case STRING:
|
||||
dotp->tk_data.tk_str = (struct string *)
|
||||
Malloc(sizeof (struct string));
|
||||
dotp->TOK_SLE = 1;
|
||||
dotp->TOK_STR = Salloc("", 1);
|
||||
break;
|
||||
case INTEGER:
|
||||
dotp->TOK_INT = 1;
|
||||
break;
|
||||
case REAL:
|
||||
dotp->tk_data.tk_real = new_real();
|
||||
dotp->TOK_RSTR = Salloc("0.0", 4);
|
||||
flt_str2flt(dotp->TOK_RSTR, &dotp->TOK_RVAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (tk < 0) {
|
||||
error("end of file expected");
|
||||
}
|
||||
else {
|
||||
#ifndef LLNONCORR
|
||||
error("%s deleted", symbol2str(dot.tk_symb));
|
||||
#else
|
||||
error("%s not expected", symbol2str(dot.tk_symb));
|
||||
#endif
|
||||
}
|
||||
tk_nmb_at_last_syn_err = token_nmb;
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define MAXERR_LINE 100 /* maximum number of error messages given
|
||||
on the same input line. */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 128 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: strsize.h
|
||||
#define ISTRSIZE 32 /* minimum number of bytes allocated for
|
||||
storing a string */
|
||||
#define RSTRSIZE 8 /* step size in enlarging the memory for
|
||||
the storage of a string */
|
||||
|
||||
|
||||
!File: target_sizes.h
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR ((arith)1)
|
||||
#define SZ_SHORT ((arith)2)
|
||||
#define SZ_WORD ((arith)4)
|
||||
#define SZ_INT ((arith)4)
|
||||
#define SZ_LONG ((arith)4)
|
||||
#define SZ_FLOAT ((arith)4)
|
||||
#define SZ_DOUBLE ((arith)8)
|
||||
#define SZ_POINTER ((arith)4)
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_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 ((int)SZ_WORD)
|
||||
|
||||
|
||||
!File: debugcst.h
|
||||
#define DEBUG 1 /* perform various self-tests */
|
||||
|
||||
!File: inputtype.h
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 3 /* see casestat.C for an explanation */
|
||||
|
||||
|
||||
!File: squeeze.h
|
||||
#undef SQUEEZE 1 /* define on "small" machines */
|
||||
|
||||
|
||||
!File: strict3rd.h
|
||||
#undef STRICT_3RD_ED 1 /* define on "small" machines, and if you want
|
||||
a compiler that only implements "3rd edition"
|
||||
Modula-2
|
||||
*/
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
#undef NOCROSS 1 /* define when cross-compiler not needed */
|
||||
|
||||
|
||||
!File: nostrict.h
|
||||
#undef NOSTRICT 1 /* define when STRICT warnings disabled
|
||||
(yet another squeezing method)
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
: create a directory Xsrc with name clashes resolved
|
||||
: and run make in that directory
|
||||
: '$Header$'
|
||||
|
||||
case $# in
|
||||
1)
|
||||
;;
|
||||
*) echo "$0: one argument expected" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
PW=`pwd`
|
||||
case $1 in
|
||||
main) target=$PW/$1
|
||||
;;
|
||||
omain) target=$PW/$1
|
||||
options=-DPEEPHOLE
|
||||
;;
|
||||
cemain) target=$PW/$1
|
||||
options=-DCODE_EXPANDER
|
||||
;;
|
||||
Xlint) target=$1
|
||||
;;
|
||||
*) echo "$0: $1: Illegal argument" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if test -d ../Xsrc
|
||||
then
|
||||
:
|
||||
else mkdir ../Xsrc
|
||||
fi
|
||||
make EMHOME=$EMHOME longnames
|
||||
: remove code generating routines from the clashes list as they are defines.
|
||||
: code generating routine names start with C_
|
||||
sed '/^C_/d' < longnames > tmp$$
|
||||
cclash -c -l7 tmp$$ > ../Xsrc/Xclashes
|
||||
rm -f tmp$$
|
||||
cd ../Xsrc
|
||||
if cmp -s Xclashes clashes
|
||||
then
|
||||
:
|
||||
else
|
||||
mv Xclashes clashes
|
||||
fi
|
||||
rm -f Makefile
|
||||
ed - $PW/Makefile <<'EOF'
|
||||
/^#EXCLEXCL/,/^#INCLINCL/d
|
||||
w Makefile
|
||||
q
|
||||
EOF
|
||||
for i in `cat $PW/Cfiles`
|
||||
do
|
||||
cat >> Makefile <<EOF
|
||||
|
||||
$i: clashes $PW/$i
|
||||
\$(CID) -Fclashes < $PW/$i > $i
|
||||
EOF
|
||||
done
|
||||
make EMHOME=$EMHOME COPTIONS=$options MACH=$MACH CURRDIR=$PW/ $target
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S Y S T E M M O D U L E T E X T */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Text of SYSTEM module, for as far as it can be expressed in Modula-2 */
|
||||
|
||||
#ifndef STRICT_3RD_ED
|
||||
#define SYSTEMTEXT "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"
|
||||
#else
|
||||
#define SYSTEMTEXT "DEFINITION MODULE SYSTEM;\n\
|
||||
PROCEDURE NEWPROCESS(P:PROC; A:ADDRESS; n:CARDINAL; VAR p1:ADDRESS);\n\
|
||||
PROCEDURE TRANSFER(VAR p1,p2:ADDRESS);\n\
|
||||
END SYSTEM.\n"
|
||||
#endif
|
||||
@@ -1,100 +0,0 @@
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define ERR_SHADOW 5 /* a syntax error overshadows error messages
|
||||
until ERR_SHADOW symbols have been
|
||||
accepted without syntax error */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 128 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: strsize.h
|
||||
#define ISTRSIZE 32 /* minimum number of bytes allocated for
|
||||
storing a string */
|
||||
#define RSTRSIZE 8 /* step size in enlarging the memory for
|
||||
the storage of a string */
|
||||
|
||||
|
||||
!File: target_sizes.h
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR ((arith)1)
|
||||
#define SZ_SHORT ((arith)2)
|
||||
#define SZ_WORD ((arith)2)
|
||||
#define SZ_INT ((arith)2)
|
||||
#define SZ_LONG ((arith)4)
|
||||
#define SZ_FLOAT ((arith)4)
|
||||
#define SZ_DOUBLE ((arith)8)
|
||||
#define SZ_POINTER ((arith)2)
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#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 ((int)SZ_WORD)
|
||||
|
||||
|
||||
!File: debugcst.h
|
||||
/*#define DEBUG 1 /* perform various self-tests */
|
||||
#define NDEBUG 1 /* disable assertions */
|
||||
|
||||
!File: inputtype.h
|
||||
/*#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 3 /* see casestat.C for an explanation */
|
||||
|
||||
|
||||
!File: squeeze.h
|
||||
#define SQUEEZE 1 /* define on "small" machines */
|
||||
|
||||
|
||||
!File: strict3rd.h
|
||||
#define STRICT_3RD_ED 1 /* define on "small" machines, and if you want
|
||||
a compiler that only implements "3rd edition"
|
||||
Modula-2
|
||||
*/
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
#define NOCROSS 1 /* define when cross-compiler not needed */
|
||||
|
||||
|
||||
!File: nostrict.h
|
||||
#define NOSTRICT 1 /* define when STRICT warnings disabled
|
||||
(yet another squeezing method)
|
||||
*/
|
||||
|
||||
|
||||
!File: bigresult.h
|
||||
#define BIG_RESULT_ON_STACK 1 /* define when function results must be
|
||||
put on the stack; in this case, caller
|
||||
reserves space for it. When not defined,
|
||||
callee puts result in global data area and
|
||||
returns a pointer to it
|
||||
*/
|
||||
|
||||
!File: dbsymtab.h
|
||||
/*#define DBSYMTAB 1 /* ability to produce symbol table for debugger */
|
||||
|
||||
|
||||
!File: use_insert.h
|
||||
/*#define USE_INSERT 1 /* use C_insertpart mechanism */
|
||||
|
||||
|
||||
!File: uns_arith.h
|
||||
/*#define UNSIGNED_ARITH unsigned arith /* when it is supported */
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
static char Version[] = "ACK Modula-2 compiler Version 0.50";
|
||||
@@ -1,385 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* 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"
|
||||
|
||||
#include <em_label.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_code.h>
|
||||
#include <alloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "Lpars.h"
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "desig.h"
|
||||
#include "walk.h"
|
||||
#include "chk_expr.h"
|
||||
#include "def.h"
|
||||
|
||||
#include "density.h"
|
||||
|
||||
struct switch_hdr {
|
||||
label sh_break; /* label of statement after this one */
|
||||
label sh_default; /* label of ELSE part, or 0 */
|
||||
int sh_nrofentries; /* number of cases */
|
||||
t_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" 5 */
|
||||
|
||||
struct case_entry {
|
||||
struct case_entry *ce_next; /* next in list */
|
||||
label ce_label; /* generated label */
|
||||
arith ce_low, ce_up; /* lower and upper bound of range */
|
||||
};
|
||||
|
||||
/* 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
|
||||
might also be reasonable. On these machines the density of jump tables
|
||||
may be lower.
|
||||
*/
|
||||
|
||||
compact(nr, low, up)
|
||||
arith low, up;
|
||||
{
|
||||
/* Careful! up - low might not fit in an arith. And then,
|
||||
the test "up-low < 0" might also not work to detect this
|
||||
situation! Or is this just a bug in the M68020/M68000?
|
||||
*/
|
||||
arith diff = up - low;
|
||||
|
||||
return (nr != 0 && diff >= 0 && fit(diff, (int) word_size) &&
|
||||
diff / nr <= (DENSITY - 1));
|
||||
}
|
||||
#define nd_lab nd_symb
|
||||
|
||||
int
|
||||
CaseCode(nd, exitlabel, end_reached)
|
||||
t_node *nd;
|
||||
label 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 t_node *pnode = nd;
|
||||
register struct case_entry *ce;
|
||||
register arith val;
|
||||
label CaseDescrLab;
|
||||
int rval;
|
||||
|
||||
assert(pnode->nd_class == Stat && pnode->nd_symb == CASE);
|
||||
|
||||
if (ChkExpression(&(pnode->nd_LEFT))) {
|
||||
MkCoercion(&(pnode->nd_LEFT),BaseType(pnode->nd_LEFT->nd_type));
|
||||
CodePExpr(pnode->nd_LEFT);
|
||||
}
|
||||
sh->sh_type = pnode->nd_LEFT->nd_type;
|
||||
sh->sh_break = ++text_label;
|
||||
|
||||
/* Now, create case label list
|
||||
*/
|
||||
while (pnode = pnode->nd_RIGHT) {
|
||||
if (pnode->nd_class == Link && pnode->nd_symb == '|') {
|
||||
if (pnode->nd_LEFT) {
|
||||
/* non-empty case
|
||||
*/
|
||||
pnode->nd_LEFT->nd_lab = ++text_label;
|
||||
AddCases(sh, /* to descriptor */
|
||||
pnode->nd_LEFT->nd_LEFT,
|
||||
/* of case labels */
|
||||
(label) pnode->nd_LEFT->nd_lab
|
||||
/* and code label */
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Else part
|
||||
*/
|
||||
|
||||
sh->sh_default = ++text_label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sh->sh_nrofentries) {
|
||||
/* There were no cases, so we have to check the case-expression
|
||||
here
|
||||
*/
|
||||
if (! (sh->sh_type->tp_fund & T_DISCRETE)) {
|
||||
node_error(nd, "illegal type in CASE-expression");
|
||||
}
|
||||
}
|
||||
|
||||
/* Now generate code for the switch itself
|
||||
First the part that CSA and CSB descriptions have in common.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
int gen = 1;
|
||||
|
||||
ce = sh->sh_entries;
|
||||
while (! ce->ce_label) ce = ce->ce_next;
|
||||
C_rom_cst((arith) 0);
|
||||
C_rom_cst(sh->sh_upperbd - sh->sh_lowerbd);
|
||||
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
|
||||
assert(ce);
|
||||
if (gen || val == ce->ce_low) {
|
||||
gen = 1;
|
||||
C_rom_ilb(ce->ce_label);
|
||||
if (val == ce->ce_up) {
|
||||
gen = 0;
|
||||
ce = ce->ce_next;
|
||||
while (ce && ! ce->ce_label) ce = ce->ce_next;
|
||||
}
|
||||
}
|
||||
else if (sh->sh_default) C_rom_ilb(sh->sh_default);
|
||||
else C_rom_ucon("0", pointer_size);
|
||||
}
|
||||
C_loc(sh->sh_lowerbd);
|
||||
C_sbu(word_size);
|
||||
c_lae_dlb(CaseDescrLab); /* perform the switch */
|
||||
C_csa(word_size);
|
||||
}
|
||||
else {
|
||||
/* CSB
|
||||
*/
|
||||
C_rom_cst((arith)sh->sh_nrofentries);
|
||||
for (ce = sh->sh_entries; ce; ce = ce->ce_next) {
|
||||
/* generate the entries: value + prog.label
|
||||
*/
|
||||
if (! ce->ce_label) continue;
|
||||
val = ce->ce_low;
|
||||
do {
|
||||
C_rom_cst(val);
|
||||
C_rom_ilb(ce->ce_label);
|
||||
} while (val++ != ce->ce_up);
|
||||
}
|
||||
c_lae_dlb(CaseDescrLab); /* perform the switch */
|
||||
C_csb(word_size);
|
||||
}
|
||||
|
||||
/* Now generate code for the cases
|
||||
*/
|
||||
pnode = nd;
|
||||
rval = 0;
|
||||
while (pnode = pnode->nd_RIGHT) {
|
||||
if (pnode->nd_class == Link && pnode->nd_symb == '|') {
|
||||
if (pnode->nd_LEFT) {
|
||||
rval |= LblWalkNode((label) pnode->nd_LEFT->nd_lab,
|
||||
pnode->nd_LEFT->nd_RIGHT,
|
||||
exitlabel, end_reached);
|
||||
c_bra(sh->sh_break);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Else part
|
||||
*/
|
||||
assert(sh->sh_default != 0);
|
||||
|
||||
rval |= LblWalkNode(sh->sh_default,
|
||||
pnode, exitlabel, end_reached);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
def_ilb(sh->sh_break);
|
||||
FreeSh(sh);
|
||||
return rval;
|
||||
}
|
||||
|
||||
FreeSh(sh)
|
||||
register struct switch_hdr *sh;
|
||||
{
|
||||
/* free the allocated switch structure
|
||||
*/
|
||||
register struct case_entry *ce;
|
||||
|
||||
ce = sh->sh_entries;
|
||||
while (ce) {
|
||||
struct case_entry *tmp = ce->ce_next;
|
||||
|
||||
free_case_entry(ce);
|
||||
ce = tmp;
|
||||
}
|
||||
|
||||
free_switch_hdr(sh);
|
||||
}
|
||||
|
||||
AddCases(sh, node, lbl)
|
||||
struct switch_hdr *sh;
|
||||
register t_node *node;
|
||||
label lbl;
|
||||
{
|
||||
/* Add case labels to the case label list
|
||||
*/
|
||||
|
||||
if (node->nd_class == Link) {
|
||||
if (node->nd_symb == UPTO) {
|
||||
assert(node->nd_LEFT->nd_class == Value);
|
||||
assert(node->nd_RIGHT->nd_class == Value);
|
||||
|
||||
AddOneCase(sh, node->nd_LEFT, node->nd_RIGHT, lbl);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(node->nd_symb == ',');
|
||||
AddCases(sh, node->nd_LEFT, lbl);
|
||||
AddCases(sh, node->nd_RIGHT, lbl);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(node->nd_class == Value);
|
||||
AddOneCase(sh, node, node, lbl);
|
||||
}
|
||||
|
||||
AddOneCase(sh, lnode, rnode, lbl)
|
||||
register struct switch_hdr *sh;
|
||||
t_node *lnode, *rnode;
|
||||
label lbl;
|
||||
{
|
||||
register struct case_entry *ce = new_case_entry();
|
||||
register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
|
||||
int fund = sh->sh_type->tp_fund;
|
||||
arith diff;
|
||||
|
||||
if (! ChkCompat(&lnode, sh->sh_type, "case") ||
|
||||
! ChkCompat(&rnode, sh->sh_type, "case")) {
|
||||
}
|
||||
ce->ce_label = lbl;
|
||||
ce->ce_low = lnode->nd_INT;
|
||||
ce->ce_up = rnode->nd_INT;
|
||||
diff = rnode->nd_INT - lnode->nd_INT;
|
||||
#define MAXRANGE 100
|
||||
if (diff < 0 || diff > MAXRANGE) {
|
||||
/* This is a bit of a hack, but it prevents the compiler
|
||||
from crashing on things like
|
||||
CASE a OF
|
||||
10 .. MAX(CARDINAL): ....
|
||||
|
||||
If the range covers more than MAXRANGE cases, this case
|
||||
is dealt with separately.
|
||||
*/
|
||||
label cont = ++text_label;
|
||||
|
||||
C_dup(int_size);
|
||||
C_loc(lnode->nd_INT);
|
||||
if (fund == T_INTEGER) {
|
||||
C_blt(cont);
|
||||
}
|
||||
else {
|
||||
C_cmu(int_size);
|
||||
C_zlt(cont);
|
||||
}
|
||||
C_dup(int_size);
|
||||
C_loc(rnode->nd_INT);
|
||||
if (fund == T_INTEGER) {
|
||||
C_bgt(cont);
|
||||
}
|
||||
else {
|
||||
C_cmu(int_size);
|
||||
C_zgt(cont);
|
||||
}
|
||||
C_asp(int_size);
|
||||
c_bra(lbl);
|
||||
C_df_ilb(cont);
|
||||
ce->ce_label = 0;
|
||||
}
|
||||
if (sh->sh_entries == 0) {
|
||||
/* first case entry
|
||||
*/
|
||||
sh->sh_entries = ce;
|
||||
if (ce->ce_label) {
|
||||
sh->sh_lowerbd = ce->ce_low;
|
||||
sh->sh_upperbd = ce->ce_up;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* second etc. case entry
|
||||
find the proper place to put ce into the list
|
||||
*/
|
||||
|
||||
while (c1 && chk_bounds(c1->ce_low, ce->ce_low, fund)) {
|
||||
c2 = c1;
|
||||
c1 = c1->ce_next;
|
||||
}
|
||||
/* At this point three cases are possible:
|
||||
1: c1 != 0 && c2 != 0:
|
||||
insert ce somewhere in the middle
|
||||
2: c1 != 0 && c2 == 0:
|
||||
insert ce right after the head
|
||||
3: c1 == 0 && c2 != 0:
|
||||
append ce to last element
|
||||
The case c1 == 0 && c2 == 0 cannot occur, since
|
||||
the list is guaranteed not to be empty.
|
||||
*/
|
||||
if (c2) {
|
||||
if ( chk_bounds(ce->ce_low, c2->ce_up, fund)) {
|
||||
node_error(rnode, "multiple case entry for value %ld", (long)(ce->ce_low));
|
||||
free_case_entry(ce);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (c1) {
|
||||
if ( chk_bounds(c1->ce_low, ce->ce_up, fund)) {
|
||||
node_error(rnode, "multiple case entry for value %ld", (long)(ce->ce_up));
|
||||
free_case_entry(ce);
|
||||
return;
|
||||
}
|
||||
if (c2) {
|
||||
ce->ce_next = c2->ce_next;
|
||||
c2->ce_next = ce;
|
||||
}
|
||||
else {
|
||||
ce->ce_next = sh->sh_entries;
|
||||
sh->sh_entries = ce;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(c2);
|
||||
|
||||
c2->ce_next = ce;
|
||||
}
|
||||
if (ce->ce_label) {
|
||||
if (! chk_bounds(sh->sh_lowerbd, ce->ce_low, fund)) {
|
||||
sh->sh_lowerbd = ce->ce_low;
|
||||
}
|
||||
if (! chk_bounds(ce->ce_up, sh->sh_upperbd, fund)) {
|
||||
sh->sh_upperbd = ce->ce_up;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ce->ce_label) sh->sh_nrofentries += ce->ce_up - ce->ce_low + 1;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
% character tables for mod2 compiler
|
||||
% $Id$
|
||||
%S129
|
||||
%F %s,
|
||||
%
|
||||
% CHARACTER CLASSES
|
||||
%
|
||||
%iSTGARB
|
||||
STSKIP: \t\013\014\015
|
||||
STNL:\012
|
||||
STSIMP:-#&()*+,/;=[]^{|}~
|
||||
STCOMP:.:<>
|
||||
STIDF:a-zA-Z
|
||||
STSTR:"'
|
||||
STNUM:0-9
|
||||
STEOI:\200
|
||||
%T#include "class.h"
|
||||
%Tchar tkclass[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% INIDF
|
||||
%
|
||||
%C
|
||||
1:a-zA-Z0-9
|
||||
%Tchar inidf[] = {
|
||||
%F %s,
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISDIG
|
||||
%
|
||||
%C
|
||||
1:0-9
|
||||
%Tchar isdig[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISHEX
|
||||
%
|
||||
%C
|
||||
1:A-F0-9
|
||||
%Tchar ishex[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISOCT
|
||||
%
|
||||
%C
|
||||
1:0-7
|
||||
%Tchar isoct[] = {
|
||||
%p
|
||||
%T};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* E X P R E S S I O N C H E C K I N G */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
extern int (*ExprChkTable[])(); /* table of expression checking
|
||||
functions, indexed by node class
|
||||
*/
|
||||
extern int (*DesigChkTable[])(); /* table of designator checking
|
||||
functions, indexed by node class
|
||||
*/
|
||||
|
||||
#define ChkExpression(expp) ((*ExprChkTable[(*expp)->nd_class])(expp,D_USED))
|
||||
#define ChkDesig(expp, flags) ((*DesigChkTable[(*expp)->nd_class])(expp,flags))
|
||||
|
||||
/* handle reference counts for sets */
|
||||
#define inc_refcount(s) (*((int *)(s) - 1) += 1)
|
||||
#define dec_refcount(s) (*((int *)(s) - 1) -= 1)
|
||||
#define refcount(s) (*((int *)(s) - 1))
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* U S E O F C H A R A C T E R C L A S S E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* As a starter, chars are divided into classes, according to which
|
||||
token they can be the start of.
|
||||
At present such a class number is supposed to fit in 4 bits.
|
||||
*/
|
||||
|
||||
#define class(ch) (tkclass[ch])
|
||||
|
||||
/* Being the start of a token is, fortunately, a mutual exclusive
|
||||
property, so, as there are less than 16 classes they can be
|
||||
packed in 4 bits.
|
||||
*/
|
||||
|
||||
#define STSKIP 0 /* spaces and so on: skipped characters */
|
||||
#define STNL 1 /* newline character(s): update linenumber etc. */
|
||||
#define STGARB 2 /* garbage ascii character: not allowed */
|
||||
#define STSIMP 3 /* this character can occur as token */
|
||||
#define STCOMP 4 /* this one can start a compound token */
|
||||
#define STIDF 5 /* being the initial character of an identifier */
|
||||
#define STCHAR 6 /* the starter of a character constant */
|
||||
#define STSTR 7 /* the starter of a string */
|
||||
#define STNUM 8 /* the starter of a numeric constant */
|
||||
#define STEOI 9 /* End-Of-Information mark */
|
||||
|
||||
/* But occurring inside a token is not, so we need 1 bit for each
|
||||
class. This is implemented as a collection of tables to speed up
|
||||
the decision whether a character has a special meaning.
|
||||
*/
|
||||
#define in_idf(ch) ((unsigned)ch < 0177 && inidf[ch])
|
||||
#define is_oct(ch) ((unsigned)ch < 0177 && isoct[ch])
|
||||
#define is_dig(ch) ((unsigned)ch < 0177 && isdig[ch])
|
||||
#define is_hex(ch) ((unsigned)ch < 0177 && ishex[ch])
|
||||
|
||||
extern char tkclass[];
|
||||
extern char inidf[], isoct[], isdig[], ishex[];
|
||||
1254
lang/m2/comp/code.c
1254
lang/m2/comp/code.c
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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$ */
|
||||
|
||||
#define arith_sign ((arith) (1L << (sizeof(arith) * 8 - 1)))
|
||||
|
||||
extern unsigned int
|
||||
wrd_bits; /* Number of bits in a word */
|
||||
@@ -1,697 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
#include "target_sizes.h"
|
||||
#include "uns_arith.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
#include <alloc.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "node.h"
|
||||
#include "Lpars.h"
|
||||
#include "standards.h"
|
||||
#include "warning.h"
|
||||
|
||||
extern char *symbol2str();
|
||||
|
||||
#define arith_sign ((arith) (1L << (sizeof(arith) * 8 - 1)))
|
||||
|
||||
#ifndef NOCROSS
|
||||
arith full_mask[MAXSIZE+1];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */
|
||||
arith max_int[MAXSIZE+1]; /* max_int[1] == 0x7F, max_int[2] == 0x7FFF, .. */
|
||||
arith min_int[MAXSIZE+1]; /* min_int[1] == 0xFFFFFF80, min_int[2] = 0xFFFF8000,
|
||||
...
|
||||
*/
|
||||
unsigned int wrd_bits; /* number of bits in a word */
|
||||
#else
|
||||
arith full_mask[] = { 0L, 0xFFL, 0xFFFFL, 0L, 0xFFFFFFFFL };
|
||||
arith max_int[] = { 0L, 0x7FL, 0x7FFFL, 0L, 0x7FFFFFFFL };
|
||||
arith min_int[] = { 0L, -128L, -32768L, 0L, -2147483647L-1 };
|
||||
#endif
|
||||
|
||||
extern char options[];
|
||||
|
||||
overflow(expp)
|
||||
t_node *expp;
|
||||
{
|
||||
if (expp->nd_type != address_type) {
|
||||
node_warning(expp, W_ORDINARY, "overflow in constant expression");
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
commonbin(expp)
|
||||
t_node **expp;
|
||||
{
|
||||
register t_node *exp = *expp;
|
||||
t_type *tp = exp->nd_type;
|
||||
register t_node *right = exp->nd_RIGHT;
|
||||
|
||||
exp->nd_RIGHT = 0;
|
||||
FreeNode(exp);
|
||||
*expp = right;
|
||||
right->nd_type = tp;
|
||||
}
|
||||
|
||||
cstunary(expp)
|
||||
t_node **expp;
|
||||
{
|
||||
/* The unary operation in "expp" is performed on the constant
|
||||
expression below it, and the result restored in expp.
|
||||
*/
|
||||
register t_node *exp = *expp;
|
||||
register t_node *right = exp->nd_RIGHT;
|
||||
register arith o1 = right->nd_INT;
|
||||
|
||||
switch(exp->nd_symb) {
|
||||
/* Should not get here
|
||||
case '+':
|
||||
break;
|
||||
*/
|
||||
|
||||
case '-':
|
||||
if (! options['s'] &&
|
||||
o1 == min_int[(int)(right->nd_type->tp_size)]) {
|
||||
overflow(exp);
|
||||
}
|
||||
o1 = -o1;
|
||||
break;
|
||||
|
||||
case NOT:
|
||||
case '~':
|
||||
o1 = !o1;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstunary)");
|
||||
}
|
||||
|
||||
commonbin(expp);
|
||||
(*expp)->nd_INT = o1;
|
||||
CutSize(*expp);
|
||||
}
|
||||
|
||||
STATIC
|
||||
divide(pdiv, prem)
|
||||
arith *pdiv, *prem;
|
||||
{
|
||||
/* Unsigned divide *pdiv by *prem, and store result in *pdiv,
|
||||
remainder in *prem
|
||||
*/
|
||||
register arith o1 = *pdiv;
|
||||
register arith o2 = *prem;
|
||||
|
||||
#ifndef UNSIGNED_ARITH
|
||||
/* this is more of a problem than you might
|
||||
think on C compilers which do not have
|
||||
unsigned long.
|
||||
*/
|
||||
if (o2 & arith_sign) {/* o2 > max_arith */
|
||||
if (! (o1 >= 0 || o1 < o2)) {
|
||||
/* this is the unsigned test
|
||||
o1 < o2 for o2 > max_arith
|
||||
*/
|
||||
*prem = o2 - o1;
|
||||
*pdiv = 1;
|
||||
}
|
||||
else {
|
||||
*pdiv = 0;
|
||||
}
|
||||
}
|
||||
else { /* o2 <= max_arith */
|
||||
arith half, bit, hdiv, hrem, rem;
|
||||
|
||||
half = (o1 >> 1) & ~arith_sign;
|
||||
bit = o1 & 01;
|
||||
/* now o1 == 2 * half + bit
|
||||
and half <= max_arith
|
||||
and bit <= max_arith
|
||||
*/
|
||||
hdiv = half / o2;
|
||||
hrem = half % o2;
|
||||
rem = 2 * hrem + bit;
|
||||
*pdiv = 2*hdiv;
|
||||
*prem = rem;
|
||||
if (rem < 0 || rem >= o2) {
|
||||
/* that is the unsigned compare
|
||||
rem >= o2 for o2 <= max_arith
|
||||
*/
|
||||
*pdiv += 1;
|
||||
*prem -= o2;
|
||||
}
|
||||
}
|
||||
#else
|
||||
*pdiv = (UNSIGNED_ARITH) o1 / (UNSIGNED_ARITH) o2;
|
||||
*prem = (UNSIGNED_ARITH) o1 % (UNSIGNED_ARITH) o2;
|
||||
#endif
|
||||
}
|
||||
|
||||
cstibin(expp)
|
||||
t_node **expp;
|
||||
{
|
||||
/* The binary operation in "expp" is performed on the constant
|
||||
expressions below it, and the result restored in expp.
|
||||
This version is for INTEGER expressions.
|
||||
*/
|
||||
register t_node *exp = *expp;
|
||||
register arith o1 = exp->nd_LEFT->nd_INT;
|
||||
register arith o2 = exp->nd_RIGHT->nd_INT;
|
||||
register int sz = exp->nd_type->tp_size;
|
||||
|
||||
assert(exp->nd_class == Oper);
|
||||
assert(exp->nd_LEFT->nd_class == Value);
|
||||
assert(exp->nd_RIGHT->nd_class == Value);
|
||||
|
||||
switch (exp->nd_symb) {
|
||||
case '*':
|
||||
if (o1 > 0) {
|
||||
if (o2 > 0) {
|
||||
if (max_int[sz] / o1 < o2) overflow(exp);
|
||||
}
|
||||
else if (min_int[sz] / o1 > o2) overflow(exp);
|
||||
}
|
||||
else if (o1 < 0) {
|
||||
if (o2 < 0) {
|
||||
if (o1 == min_int[sz] || o2 == min_int[sz] ||
|
||||
max_int[sz] / (-o1) < (-o2)) overflow(exp);
|
||||
}
|
||||
else if (o2 > 0) {
|
||||
if (min_int[sz] / o2 > o1) overflow(exp);
|
||||
}
|
||||
}
|
||||
o1 *= o2;
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
case MOD:
|
||||
if (o2 == 0) {
|
||||
node_error(exp, exp->nd_symb == DIV ?
|
||||
"division by 0" :
|
||||
"modulo by 0");
|
||||
return;
|
||||
}
|
||||
if ((o1 < 0) != (o2 < 0)) {
|
||||
if (o1 < 0) o1 = -o1;
|
||||
else o2 = -o2;
|
||||
if (exp->nd_symb == DIV) o1 = -((o1+o2-1)/o2);
|
||||
else o1 = ((o1+o2-1)/o2) * o2 - o1;
|
||||
}
|
||||
else {
|
||||
if (exp->nd_symb == DIV) o1 /= o2;
|
||||
else o1 %= o2;
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
if ( (o1 > 0 && o2 > 0 && max_int[sz] - o1 < o2)
|
||||
|| (o1 < 0 && o2 < 0 && min_int[sz] - o1 > o2)
|
||||
) overflow(exp);
|
||||
o1 += o2;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if ( (o1 >= 0 && o2 < 0 && max_int[sz] + o2 < o1)
|
||||
|| (o1 < 0 && o2 >= 0 && min_int[sz] + o2 > o1)
|
||||
) overflow(exp);
|
||||
o1 -= o2;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
o1 = (o1 < o2);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
o1 = (o1 > o2);
|
||||
break;
|
||||
|
||||
case LESSEQUAL:
|
||||
o1 = (o1 <= o2);
|
||||
break;
|
||||
|
||||
case GREATEREQUAL:
|
||||
o1 = (o1 >= o2);
|
||||
break;
|
||||
|
||||
case '=':
|
||||
o1 = (o1 == o2);
|
||||
break;
|
||||
|
||||
case '#':
|
||||
o1 = (o1 != o2);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstibin)");
|
||||
}
|
||||
|
||||
commonbin(expp);
|
||||
(*expp)->nd_INT = o1;
|
||||
CutSize(*expp);
|
||||
}
|
||||
|
||||
cstfbin(expp)
|
||||
t_node **expp;
|
||||
{
|
||||
/* The binary operation in "expp" is performed on the constant
|
||||
expressions below it, and the result restored in expp.
|
||||
This version is for REAL expressions.
|
||||
*/
|
||||
register t_node *exp = *expp;
|
||||
register struct real *p = exp->nd_LEFT->nd_REAL;
|
||||
register flt_arith *o1 = &p->r_val;
|
||||
register flt_arith *o2 = &exp->nd_RIGHT->nd_RVAL;
|
||||
int compar = 0;
|
||||
int cmpval = 0;
|
||||
|
||||
assert(exp->nd_class == Oper);
|
||||
assert(exp->nd_LEFT->nd_class == Value);
|
||||
assert(exp->nd_RIGHT->nd_class == Value);
|
||||
|
||||
switch (exp->nd_symb) {
|
||||
case '*':
|
||||
flt_mul(o1, o2, o1);
|
||||
break;
|
||||
|
||||
case '/':
|
||||
flt_div(o1, o2, o1);
|
||||
break;
|
||||
|
||||
case '+':
|
||||
flt_add(o1, o2, o1);
|
||||
break;
|
||||
|
||||
case '-':
|
||||
flt_sub(o1, o2, o1);
|
||||
break;
|
||||
|
||||
case '<':
|
||||
case '>':
|
||||
case LESSEQUAL:
|
||||
case GREATEREQUAL:
|
||||
case '=':
|
||||
case '#':
|
||||
compar++;
|
||||
cmpval = flt_cmp(o1, o2);
|
||||
switch(exp->nd_symb) {
|
||||
case '<': cmpval = (cmpval < 0); break;
|
||||
case '>': cmpval = (cmpval > 0); break;
|
||||
case LESSEQUAL: cmpval = (cmpval <= 0); break;
|
||||
case GREATEREQUAL: cmpval = (cmpval >= 0); break;
|
||||
case '=': cmpval = (cmpval == 0); break;
|
||||
case '#': cmpval = (cmpval != 0); break;
|
||||
}
|
||||
if (exp->nd_RIGHT->nd_RSTR) free(exp->nd_RIGHT->nd_RSTR);
|
||||
free_real(exp->nd_RIGHT->nd_REAL);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstfbin)");
|
||||
}
|
||||
|
||||
switch(flt_status) {
|
||||
case FLT_OVFL:
|
||||
node_warning(exp, "floating point overflow on %s",
|
||||
symbol2str(exp->nd_symb));
|
||||
break;
|
||||
case FLT_DIV0:
|
||||
node_error(exp, "division by 0.0");
|
||||
break;
|
||||
}
|
||||
|
||||
if (p->r_real) {
|
||||
free(p->r_real);
|
||||
p->r_real = 0;
|
||||
}
|
||||
if (compar) {
|
||||
free_real(p);
|
||||
}
|
||||
commonbin(expp);
|
||||
exp = *expp;
|
||||
if (compar) {
|
||||
exp->nd_symb = INTEGER;
|
||||
exp->nd_INT = cmpval;
|
||||
}
|
||||
else {
|
||||
exp->nd_REAL = p;
|
||||
}
|
||||
CutSize(exp);
|
||||
}
|
||||
|
||||
cstubin(expp)
|
||||
t_node **expp;
|
||||
{
|
||||
/* The binary operation in "expp" is performed on the constant
|
||||
expressions below it, and the result restored in
|
||||
expp.
|
||||
*/
|
||||
register t_node *exp = *expp;
|
||||
arith o1 = exp->nd_LEFT->nd_INT;
|
||||
arith o2 = exp->nd_RIGHT->nd_INT;
|
||||
register int sz = exp->nd_type->tp_size;
|
||||
arith tmp1, tmp2;
|
||||
|
||||
assert(exp->nd_class == Oper);
|
||||
assert(exp->nd_LEFT->nd_class == Value);
|
||||
assert(exp->nd_RIGHT->nd_class == Value);
|
||||
|
||||
switch (exp->nd_symb) {
|
||||
case '*':
|
||||
if (o1 == 0 || o2 == 0) {
|
||||
o1 = 0;
|
||||
break;
|
||||
}
|
||||
tmp1 = full_mask[sz];
|
||||
tmp2 = o2;
|
||||
divide(&tmp1, &tmp2);
|
||||
if (! chk_bounds(o1, tmp1, T_CARDINAL)) overflow(exp);
|
||||
o1 *= o2;
|
||||
break;
|
||||
|
||||
case DIV:
|
||||
case MOD:
|
||||
if (o2 == 0) {
|
||||
node_error(exp, exp->nd_symb == DIV ?
|
||||
"division by 0" :
|
||||
"modulo by 0");
|
||||
return;
|
||||
}
|
||||
divide(&o1, &o2);
|
||||
if (exp->nd_symb == MOD) o1 = o2;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
if (! chk_bounds(o2, full_mask[sz] - o1, T_CARDINAL)) {
|
||||
overflow(exp);
|
||||
}
|
||||
o1 += o2;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if ( exp->nd_type != address_type
|
||||
&& !chk_bounds(o2, o1, T_CARDINAL)
|
||||
&& ( exp->nd_type->tp_fund != T_INTORCARD
|
||||
|| ( exp->nd_type = int_type
|
||||
, !chk_bounds(min_int[sz], o1 - o2, T_CARDINAL) ) )
|
||||
) {
|
||||
node_warning(exp, W_ORDINARY,
|
||||
"underflow in constant expression");
|
||||
}
|
||||
o1 -= o2;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
o1 = ! chk_bounds(o2, o1, T_CARDINAL);
|
||||
break;
|
||||
|
||||
case '>':
|
||||
o1 = ! chk_bounds(o1, o2, T_CARDINAL);
|
||||
break;
|
||||
|
||||
case LESSEQUAL:
|
||||
o1 = chk_bounds(o1, o2, T_CARDINAL);
|
||||
break;
|
||||
|
||||
case GREATEREQUAL:
|
||||
o1 = chk_bounds(o2, o1, T_CARDINAL);
|
||||
break;
|
||||
|
||||
case '=':
|
||||
o1 = (o1 == o2);
|
||||
break;
|
||||
|
||||
case '#':
|
||||
o1 = (o1 != o2);
|
||||
break;
|
||||
|
||||
case AND:
|
||||
case '&':
|
||||
o1 = (o1 && o2);
|
||||
break;
|
||||
|
||||
case OR:
|
||||
o1 = (o1 || o2);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstubin)");
|
||||
}
|
||||
|
||||
commonbin(expp);
|
||||
exp = *expp;
|
||||
exp->nd_INT = o1;
|
||||
if (exp->nd_type == bool_type) exp->nd_symb = INTEGER;
|
||||
CutSize(exp);
|
||||
}
|
||||
|
||||
cstset(expp)
|
||||
t_node **expp;
|
||||
{
|
||||
extern arith *MkSet();
|
||||
register t_node *exp = *expp;
|
||||
register arith *set1, *set2, *set3;
|
||||
register unsigned int setsize;
|
||||
register int j;
|
||||
|
||||
assert(exp->nd_RIGHT->nd_class == Set);
|
||||
assert(exp->nd_symb == IN || exp->nd_LEFT->nd_class == Set);
|
||||
|
||||
set2 = exp->nd_RIGHT->nd_set;
|
||||
setsize = (unsigned) (exp->nd_RIGHT->nd_type->tp_size) / (unsigned) word_size;
|
||||
|
||||
if (exp->nd_symb == IN) {
|
||||
/* The setsize must fit in an unsigned, as it is
|
||||
allocated with Malloc, so we can do the arithmetic
|
||||
in an unsigned too.
|
||||
*/
|
||||
unsigned i;
|
||||
|
||||
assert(exp->nd_LEFT->nd_class == Value);
|
||||
|
||||
exp->nd_LEFT->nd_INT -= exp->nd_RIGHT->nd_type->set_low;
|
||||
exp = exp->nd_LEFT;
|
||||
i = exp->nd_INT;
|
||||
/* Careful here; use exp->nd_LEFT->nd_INT to see if
|
||||
it falls in the range of the set. Do not use i
|
||||
for this, as i may be truncated.
|
||||
*/
|
||||
i = (exp->nd_INT >= 0 &&
|
||||
exp->nd_INT < setsize * wrd_bits &&
|
||||
(set2[i / wrd_bits] & (1 << (i % wrd_bits))));
|
||||
FreeSet(set2);
|
||||
exp = getnode(Value);
|
||||
exp->nd_symb = INTEGER;
|
||||
exp->nd_lineno = (*expp)->nd_lineno;
|
||||
exp->nd_INT = i;
|
||||
exp->nd_type = bool_type;
|
||||
FreeNode(*expp);
|
||||
*expp = exp;
|
||||
return;
|
||||
}
|
||||
|
||||
set1 = exp->nd_LEFT->nd_set;
|
||||
*expp = getnode(Set);
|
||||
(*expp)->nd_type = exp->nd_type;
|
||||
(*expp)->nd_lineno = exp->nd_lineno;
|
||||
switch(exp->nd_symb) {
|
||||
case '+': /* Set union */
|
||||
case '-': /* Set difference */
|
||||
case '*': /* Set intersection */
|
||||
case '/': /* Symmetric set difference */
|
||||
(*expp)->nd_set = set3 = MkSet(exp->nd_type->set_sz);
|
||||
for (j = 0; j < setsize; j++) {
|
||||
switch(exp->nd_symb) {
|
||||
case '+':
|
||||
*set3++ = *set1++ | *set2++;
|
||||
break;
|
||||
case '-':
|
||||
*set3++ = *set1++ & ~*set2++;
|
||||
break;
|
||||
case '*':
|
||||
*set3++ = *set1++ & *set2++;
|
||||
break;
|
||||
case '/':
|
||||
*set3++ = *set1++ ^ *set2++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GREATEREQUAL:
|
||||
case LESSEQUAL:
|
||||
case '=':
|
||||
case '#':
|
||||
/* Constant set comparisons
|
||||
*/
|
||||
for (j = 0; j < setsize; j++) {
|
||||
switch(exp->nd_symb) {
|
||||
case GREATEREQUAL:
|
||||
if ((*set1 | *set2++) != *set1) break;
|
||||
set1++;
|
||||
continue;
|
||||
case LESSEQUAL:
|
||||
if ((*set2 | *set1++) != *set2) break;
|
||||
set2++;
|
||||
continue;
|
||||
case '=':
|
||||
case '#':
|
||||
if (*set1++ != *set2++) break;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (j < setsize) {
|
||||
j = exp->nd_symb == '#';
|
||||
}
|
||||
else {
|
||||
j = exp->nd_symb != '#';
|
||||
}
|
||||
*expp = getnode(Value);
|
||||
(*expp)->nd_symb = INTEGER;
|
||||
(*expp)->nd_INT = j;
|
||||
(*expp)->nd_type = bool_type;
|
||||
(*expp)->nd_lineno = (*expp)->nd_lineno;
|
||||
break;
|
||||
default:
|
||||
crash("(cstset)");
|
||||
}
|
||||
FreeSet(exp->nd_LEFT->nd_set);
|
||||
FreeSet(exp->nd_RIGHT->nd_set);
|
||||
FreeNode(exp);
|
||||
}
|
||||
|
||||
cstcall(expp, call)
|
||||
t_node **expp;
|
||||
{
|
||||
/* a standard procedure call is found that can be evaluated
|
||||
compile time, so do so.
|
||||
*/
|
||||
register t_node *expr;
|
||||
register t_type *tp;
|
||||
|
||||
assert((*expp)->nd_class == Call);
|
||||
expr = (*expp)->nd_RIGHT->nd_LEFT;
|
||||
tp = expr->nd_type;
|
||||
expr->nd_type = (*expp)->nd_type;
|
||||
|
||||
(*expp)->nd_RIGHT->nd_LEFT = 0;
|
||||
FreeNode(*expp);
|
||||
*expp = expr;
|
||||
expr->nd_symb = INTEGER;
|
||||
expr->nd_class = Value;
|
||||
switch(call) {
|
||||
case S_ABS:
|
||||
if (expr->nd_INT < 0) {
|
||||
if (! options['s'] &&
|
||||
expr->nd_INT <= min_int[(int)(tp->tp_size)]) {
|
||||
overflow(expr);
|
||||
}
|
||||
expr->nd_INT = - expr->nd_INT;
|
||||
}
|
||||
CutSize(expr);
|
||||
break;
|
||||
|
||||
case S_CAP:
|
||||
if (expr->nd_INT >= 'a' && expr->nd_INT <= 'z') {
|
||||
expr->nd_INT += ('A' - 'a');
|
||||
}
|
||||
break;
|
||||
|
||||
case S_HIGH:
|
||||
case S_MAX:
|
||||
if (tp->tp_fund == T_INTEGER) {
|
||||
expr->nd_INT = max_int[(int)(tp->tp_size)];
|
||||
}
|
||||
else if (tp->tp_fund == T_CARDINAL) {
|
||||
expr->nd_INT = full_mask[(int)(tp->tp_size)];
|
||||
}
|
||||
else if (tp->tp_fund == T_SUBRANGE) {
|
||||
expr->nd_INT = tp->sub_ub;
|
||||
}
|
||||
else expr->nd_INT = tp->enm_ncst - 1;
|
||||
break;
|
||||
|
||||
case S_MIN:
|
||||
if (tp->tp_fund == T_INTEGER) {
|
||||
expr->nd_INT = min_int[(int)(tp->tp_size)];
|
||||
}
|
||||
else if (tp->tp_fund == T_SUBRANGE) {
|
||||
expr->nd_INT = tp->sub_lb;
|
||||
}
|
||||
else expr->nd_INT = 0;
|
||||
break;
|
||||
|
||||
case S_ODD:
|
||||
expr->nd_INT &= 1;
|
||||
break;
|
||||
|
||||
case S_TSIZE:
|
||||
case S_SIZE:
|
||||
expr->nd_INT = tp->tp_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(cstcall)");
|
||||
}
|
||||
}
|
||||
|
||||
CutSize(expr)
|
||||
register t_node *expr;
|
||||
{
|
||||
/* The constant value of the expression expr is made to
|
||||
conform to the size of the type of the expression.
|
||||
*/
|
||||
register t_type *tp = BaseType(expr->nd_type);
|
||||
|
||||
assert(expr->nd_class == Value);
|
||||
if (tp->tp_fund == T_REAL) return;
|
||||
if (tp->tp_fund != T_INTEGER) {
|
||||
expr->nd_INT &= full_mask[(int)(tp->tp_size)];
|
||||
}
|
||||
else {
|
||||
int nbits = (int) (sizeof(arith) - tp->tp_size) * 8;
|
||||
|
||||
expr->nd_INT = (expr->nd_INT << nbits) >> nbits;
|
||||
}
|
||||
}
|
||||
|
||||
InitCst()
|
||||
{
|
||||
register int i = 0;
|
||||
#ifndef NOCROSS
|
||||
register arith bt = (arith)0;
|
||||
|
||||
while (!(bt < 0)) {
|
||||
i++;
|
||||
bt = (bt << 8) + 0377;
|
||||
if (i == MAXSIZE+1)
|
||||
fatal("array full_mask too small for this machine");
|
||||
full_mask[i] = bt;
|
||||
max_int[i] = bt & ~(1L << ((8 * i) - 1));
|
||||
min_int[i] = - max_int[i];
|
||||
if (! options['s']) min_int[i]--;
|
||||
}
|
||||
if ((int)long_size > sizeof(arith)) {
|
||||
fatal("sizeof (arith) insufficient on this machine");
|
||||
}
|
||||
|
||||
wrd_bits = 8 * (int) word_size;
|
||||
#else
|
||||
if (options['s']) {
|
||||
for (i = 0; i < sizeof(long); i++) min_int[i] = - max_int[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E B U G G I N G M A C R O */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debugcst.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DO_DEBUG(x, y) ((x) && (y))
|
||||
#define STATIC
|
||||
#else
|
||||
#define DO_DEBUG(x, y)
|
||||
#define STATIC static
|
||||
#endif
|
||||
@@ -1,567 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E C L A R A T I O N S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
{
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <alloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "strict3rd.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "scope.h"
|
||||
#include "node.h"
|
||||
#include "misc.h"
|
||||
#include "main.h"
|
||||
#include "chk_expr.h"
|
||||
#include "warning.h"
|
||||
#include "nostrict.h"
|
||||
|
||||
int proclevel = 0; /* nesting level of procedures */
|
||||
int return_occurred; /* set if a return occurs in a block */
|
||||
|
||||
extern t_node *EmptyStatement;
|
||||
|
||||
#define needs_static_link() (proclevel > 1)
|
||||
}
|
||||
|
||||
/* inline in declaration: need space
|
||||
* ProcedureDeclaration
|
||||
* {
|
||||
* t_def *df;
|
||||
* } :
|
||||
* { ++proclevel; }
|
||||
* ProcedureHeading(&df, D_PROCEDURE)
|
||||
* ';' block(&(df->prc_body))
|
||||
* IDENT
|
||||
* { EndProc(df, dot.TOK_IDF);
|
||||
* --proclevel;
|
||||
* }
|
||||
* ;
|
||||
*/
|
||||
|
||||
ProcedureHeading(t_def **pdf; int type;)
|
||||
{
|
||||
t_type *tp = 0;
|
||||
arith parmaddr = needs_static_link() ? pointer_size : 0;
|
||||
t_param *pr = 0;
|
||||
} :
|
||||
PROCEDURE IDENT
|
||||
{ *pdf = DeclProc(type, dot.TOK_IDF); }
|
||||
[
|
||||
'('
|
||||
[
|
||||
FPSection(&pr, &parmaddr)
|
||||
[
|
||||
';' FPSection(&pr, &parmaddr)
|
||||
]*
|
||||
|
|
||||
]
|
||||
')'
|
||||
[ ':' qualtype(&tp)
|
||||
|
|
||||
]
|
||||
|
|
||||
]
|
||||
{ CheckWithDef(*pdf, proc_type(tp, pr, parmaddr));
|
||||
#ifndef NOSTRICT
|
||||
if (tp && IsConstructed(tp)) {
|
||||
warning(W_STRICT, "procedure \"%s\" has a constructed result type",
|
||||
(*pdf)->df_idf->id_text);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
;
|
||||
|
||||
block(t_node **pnd;) :
|
||||
[ %persistent
|
||||
declaration
|
||||
]*
|
||||
{ return_occurred = 0; }
|
||||
[ %default
|
||||
BEGIN
|
||||
StatementSequence(pnd)
|
||||
|
|
||||
{ *pnd = EmptyStatement; }
|
||||
]
|
||||
END
|
||||
;
|
||||
|
||||
declaration
|
||||
{
|
||||
t_def *df;
|
||||
} :
|
||||
CONST [ ConstantDeclaration ';' ]*
|
||||
|
|
||||
TYPE [ TypeDeclaration ';' ]*
|
||||
|
|
||||
VAR [ VariableDeclaration ';' ]*
|
||||
|
|
||||
{ ++proclevel; }
|
||||
ProcedureHeading(&df, D_PROCEDURE)
|
||||
{
|
||||
}
|
||||
';'
|
||||
block(&(df->prc_body))
|
||||
IDENT
|
||||
{
|
||||
EndProc(df, dot.TOK_IDF);
|
||||
--proclevel;
|
||||
}
|
||||
';'
|
||||
|
|
||||
ModuleDeclaration ';'
|
||||
;
|
||||
|
||||
/* inline in procedureheading: need space
|
||||
* FormalParameters(t_param **ppr; arith *parmaddr; t_type **ptp;):
|
||||
* '('
|
||||
* [
|
||||
* FPSection(ppr, parmaddr)
|
||||
* [
|
||||
* ';' FPSection(ppr, parmaddr)
|
||||
* ]*
|
||||
* |
|
||||
* ]
|
||||
* ')'
|
||||
* [ ':' qualtype(ptp)
|
||||
* |
|
||||
* ]
|
||||
* ;
|
||||
*/
|
||||
|
||||
FPSection(t_param **ppr; arith *parmaddr;)
|
||||
{
|
||||
t_node *FPList;
|
||||
t_type *tp;
|
||||
int VARp;
|
||||
} :
|
||||
var(&VARp) IdentList(&FPList) ':' FormalType(&tp)
|
||||
{ EnterParamList(ppr, FPList, tp, VARp, parmaddr); }
|
||||
;
|
||||
|
||||
FormalType(t_type **ptp;)
|
||||
/* index type of conformant array is "CARDINAL".
|
||||
Recognize a conformant array by size 0.
|
||||
*/
|
||||
{ register t_type *tp;
|
||||
} :
|
||||
ARRAY OF
|
||||
{ tp = construct_type(T_ARRAY, card_type); }
|
||||
qualtype(&(tp->arr_elem))
|
||||
{ ArrayElSize(tp);
|
||||
*ptp = tp;
|
||||
}
|
||||
|
|
||||
qualtype(ptp)
|
||||
;
|
||||
|
||||
TypeDeclaration
|
||||
{
|
||||
t_def *df;
|
||||
t_type *tp;
|
||||
register t_node *nd;
|
||||
}:
|
||||
IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE);
|
||||
nd = dot2leaf(Name);
|
||||
}
|
||||
'=' type(&tp)
|
||||
{ DeclareType(nd, df, tp);
|
||||
FreeNode(nd);
|
||||
}
|
||||
;
|
||||
|
||||
type(register t_type **ptp;):
|
||||
%default SimpleType(ptp)
|
||||
|
|
||||
ArrayType(ptp)
|
||||
|
|
||||
RecordType(ptp)
|
||||
|
|
||||
SetType(ptp)
|
||||
|
|
||||
PointerType(ptp)
|
||||
|
|
||||
ProcedureType(ptp)
|
||||
;
|
||||
|
||||
SimpleType(register t_type **ptp;) :
|
||||
qualtype(ptp)
|
||||
[
|
||||
/* nothing */
|
||||
|
|
||||
SubrangeType(ptp)
|
||||
/* The subrange type is given a base type by the
|
||||
qualident (this is new modula-2).
|
||||
*/
|
||||
]
|
||||
|
|
||||
enumeration(ptp)
|
||||
| { *ptp = 0; /* no qualification */ }
|
||||
SubrangeType(ptp)
|
||||
;
|
||||
|
||||
enumeration(t_type **ptp;)
|
||||
{
|
||||
t_node *EnumList;
|
||||
} :
|
||||
'(' IdentList(&EnumList) ')'
|
||||
{ *ptp = enum_type(EnumList); }
|
||||
;
|
||||
|
||||
IdentList(t_node **p;)
|
||||
{
|
||||
register t_node *q;
|
||||
} :
|
||||
IDENT { *p = q = dot2leaf(Select); }
|
||||
[ %persistent
|
||||
',' IDENT
|
||||
{ q->nd_NEXT = dot2leaf(Select);
|
||||
q = q->nd_NEXT;
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
SubrangeType(t_type **ptp;)
|
||||
{
|
||||
t_node *nd1, *nd2;
|
||||
}:
|
||||
/*
|
||||
This is not exactly the rule in the new report, but see
|
||||
the rule for "SimpleType".
|
||||
*/
|
||||
'[' ConstExpression(&nd1)
|
||||
UPTO ConstExpression(&nd2)
|
||||
']'
|
||||
{ *ptp = subr_type(nd1, nd2, *ptp);
|
||||
FreeNode(nd1);
|
||||
FreeNode(nd2);
|
||||
}
|
||||
;
|
||||
|
||||
ArrayType(t_type **ptp;)
|
||||
{
|
||||
t_type *tp;
|
||||
register t_type *tp1, *tp2;
|
||||
} :
|
||||
ARRAY SimpleType(&tp)
|
||||
{ tp1 = tp2 = construct_type(T_ARRAY, tp); }
|
||||
[
|
||||
',' SimpleType(&tp)
|
||||
{ tp2->arr_elem = construct_type(T_ARRAY, tp);
|
||||
tp2 = tp2->arr_elem;
|
||||
}
|
||||
]* OF type(&tp)
|
||||
{ tp2->arr_elem = tp;
|
||||
ArraySizes(tp1);
|
||||
*ptp = tp1;
|
||||
}
|
||||
;
|
||||
|
||||
RecordType(t_type **ptp;)
|
||||
{
|
||||
register t_scope *scope;
|
||||
arith size = 0;
|
||||
int xalign = struct_align;
|
||||
}
|
||||
:
|
||||
RECORD
|
||||
{ scope = open_and_close_scope(OPENSCOPE); }
|
||||
FieldListSequence(scope, &size, &xalign)
|
||||
{ if (size == 0) {
|
||||
warning(W_ORDINARY, "empty record declaration");
|
||||
size = 1;
|
||||
}
|
||||
*ptp = standard_type(T_RECORD, xalign, align(size, xalign));
|
||||
(*ptp)->rec_scope = scope;
|
||||
Reverse(&(scope->sc_def));
|
||||
}
|
||||
END
|
||||
;
|
||||
|
||||
FieldListSequence(t_scope *scope; arith *cnt; int *palign;):
|
||||
FieldList(scope, cnt, palign)
|
||||
[
|
||||
';' FieldList(scope, cnt, palign)
|
||||
]*
|
||||
;
|
||||
|
||||
FieldList(t_scope *scope; arith *cnt; int *palign;)
|
||||
{
|
||||
t_node *FldList;
|
||||
t_type *tp;
|
||||
t_node *nd;
|
||||
register t_def *df;
|
||||
arith tcnt, max;
|
||||
} :
|
||||
[
|
||||
IdentList(&FldList) ':' type(&tp)
|
||||
{
|
||||
*palign = lcm(*palign, tp->tp_align);
|
||||
EnterFieldList(FldList, tp, scope, cnt);
|
||||
}
|
||||
|
|
||||
CASE
|
||||
/* Also accept old fashioned Modula-2 syntax, but give a warning.
|
||||
Sorry for the complicated code.
|
||||
*/
|
||||
[ qualident(&nd)
|
||||
[ ':' qualtype(&tp)
|
||||
/* This is correct, in both kinds of Modula-2, if
|
||||
the first qualident is a single identifier.
|
||||
*/
|
||||
{ if (nd->nd_class != Name) {
|
||||
error("illegal variant tag");
|
||||
}
|
||||
else {
|
||||
df = define(nd->nd_IDF, scope, D_FIELD);
|
||||
*palign = lcm(*palign, tp->tp_align);
|
||||
if (!(tp->tp_fund & T_DISCRETE)) {
|
||||
error("illegal type in variant");
|
||||
}
|
||||
df->df_type = tp;
|
||||
df->fld_off = align(*cnt, tp->tp_align);
|
||||
*cnt = df->fld_off + tp->tp_size;
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
}
|
||||
FreeNode(nd);
|
||||
}
|
||||
| /* Old fashioned! the first qualident now represents
|
||||
the type
|
||||
*/
|
||||
{
|
||||
#ifndef STRICT_3RD_ED
|
||||
if (! options['3']) warning(W_OLDFASHIONED,
|
||||
"old fashioned Modula-2 syntax; ':' missing");
|
||||
else
|
||||
#endif
|
||||
error("':' missing");
|
||||
tp = qualified_type(&nd);
|
||||
}
|
||||
]
|
||||
| ':' qualtype(&tp)
|
||||
/* Aha, third edition. Well done! */
|
||||
]
|
||||
{ tcnt = *cnt; }
|
||||
OF variant(scope, &tcnt, tp, palign)
|
||||
{ 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; }
|
||||
|
|
||||
]
|
||||
END
|
||||
{ *cnt = max; }
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
variant(t_scope *scope; arith *cnt; t_type *tp; int *palign;)
|
||||
{
|
||||
t_node *nd;
|
||||
} :
|
||||
[
|
||||
CaseLabelList(&tp, &nd)
|
||||
{ /* Ignore the cases for the time being.
|
||||
Maybe a checking version will be supplied
|
||||
later ???
|
||||
*/
|
||||
FreeNode(nd);
|
||||
}
|
||||
':' FieldListSequence(scope, cnt, palign)
|
||||
|
|
||||
]
|
||||
/* Changed rule in new modula-2 */
|
||||
;
|
||||
|
||||
CaseLabelList(t_type **ptp; t_node **pnd;):
|
||||
CaseLabels(ptp, pnd)
|
||||
[
|
||||
{ *pnd = dot2node(Link, *pnd, NULLNODE); }
|
||||
',' CaseLabels(ptp, &((*pnd)->nd_RIGHT))
|
||||
{ pnd = &((*pnd)->nd_RIGHT); }
|
||||
]*
|
||||
;
|
||||
|
||||
CaseLabels(t_type **ptp; register t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
}:
|
||||
ConstExpression(pnd)
|
||||
{
|
||||
if (*ptp != 0) {
|
||||
t_type *tp = intorcard(*ptp,
|
||||
BaseType((*pnd)->nd_type));
|
||||
if (tp) *ptp = tp;
|
||||
ChkCompat(pnd, *ptp, "case label");
|
||||
}
|
||||
nd = *pnd;
|
||||
nd->nd_type = BaseType(nd->nd_type); /* ??? */
|
||||
if (! (nd->nd_type->tp_fund & T_DISCRETE) ||
|
||||
nd->nd_type->tp_size > word_size) {
|
||||
node_error(nd, "illegal type in case label");
|
||||
}
|
||||
}
|
||||
[
|
||||
UPTO { *pnd = nd = dot2node(Link,nd,NULLNODE);
|
||||
nd->nd_type = nd->nd_LEFT->nd_type;
|
||||
}
|
||||
ConstExpression(&(*pnd)->nd_RIGHT)
|
||||
{ if (!ChkCompat(&((*pnd)->nd_RIGHT), nd->nd_type,
|
||||
"case label")) {
|
||||
nd->nd_type = error_type;
|
||||
}
|
||||
else if (! chk_bounds(nd->nd_LEFT->nd_INT,
|
||||
nd->nd_RIGHT->nd_INT,
|
||||
nd->nd_type->tp_fund)) {
|
||||
node_error(nd,
|
||||
"lower bound exceeds upper bound in case label range");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
||||
]
|
||||
{
|
||||
*ptp = nd->nd_type;
|
||||
}
|
||||
;
|
||||
|
||||
SetType(t_type **ptp;)
|
||||
{ t_type *tp;
|
||||
} :
|
||||
SET OF SimpleType(&tp)
|
||||
{ *ptp = set_type(tp); }
|
||||
;
|
||||
|
||||
/* In a pointer type definition, the type pointed at does not
|
||||
have to be declared yet, so be careful about identifying
|
||||
type-identifiers.
|
||||
*/
|
||||
PointerType(register t_type **ptp;)
|
||||
{ register t_type *tp;
|
||||
} :
|
||||
{ tp = construct_type(T_POINTER, NULLTYPE); }
|
||||
POINTER TO
|
||||
[ %if (type_or_forward(tp))
|
||||
type(&(tp->tp_next))
|
||||
|
|
||||
IDENT
|
||||
]
|
||||
{ *ptp = tp; }
|
||||
;
|
||||
|
||||
qualtype(t_type **ptp;)
|
||||
{
|
||||
t_node *nd;
|
||||
} :
|
||||
qualident(&nd)
|
||||
{ *ptp = qualified_type(&nd); }
|
||||
;
|
||||
|
||||
ProcedureType(t_type **ptp;)
|
||||
{
|
||||
t_param *pr = 0;
|
||||
arith parmaddr = 0;
|
||||
t_type *tp = 0;
|
||||
} :
|
||||
PROCEDURE
|
||||
[
|
||||
FormalTypeList(&pr, &parmaddr, &tp)
|
||||
|
|
||||
]
|
||||
{ *ptp = proc_type(tp, pr, parmaddr); }
|
||||
;
|
||||
|
||||
FormalTypeList(t_param **ppr; arith *pparmaddr; t_type **ptp;) :
|
||||
'('
|
||||
[
|
||||
VarFormalType(ppr, pparmaddr)
|
||||
[
|
||||
',' VarFormalType(ppr, pparmaddr)
|
||||
]*
|
||||
|
|
||||
]
|
||||
')'
|
||||
[ ':' qualtype(ptp)
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
VarFormalType(t_param **ppr; arith *pparmaddr;)
|
||||
{
|
||||
t_type *tp;
|
||||
int isvar;
|
||||
} :
|
||||
var(&isvar)
|
||||
FormalType(&tp)
|
||||
{ EnterParamList(ppr,NULLNODE,tp,isvar,pparmaddr); }
|
||||
;
|
||||
|
||||
var(int *VARp;) :
|
||||
[
|
||||
VAR { *VARp = D_VARPAR; }
|
||||
|
|
||||
/* empty */ { *VARp = D_VALPAR; }
|
||||
]
|
||||
;
|
||||
|
||||
ConstantDeclaration
|
||||
{
|
||||
t_idf *id;
|
||||
t_node *nd;
|
||||
register t_def *df;
|
||||
}:
|
||||
IDENT { id = dot.TOK_IDF; }
|
||||
'=' ConstExpression(&nd)
|
||||
{ df = define(id,CurrentScope,D_CONST);
|
||||
df->con_const = nd->nd_token;
|
||||
df->df_type = nd->nd_type;
|
||||
FreeNode(nd);
|
||||
}
|
||||
;
|
||||
|
||||
VariableDeclaration
|
||||
{
|
||||
t_node *VarList;
|
||||
register t_node *nd;
|
||||
t_type *tp;
|
||||
} :
|
||||
IdentAddr(&VarList)
|
||||
{ nd = VarList; }
|
||||
[ %persistent
|
||||
',' IdentAddr(&(nd->nd_RIGHT))
|
||||
{ nd = nd->nd_RIGHT; }
|
||||
]*
|
||||
':' type(&tp)
|
||||
{ EnterVarList(VarList, tp, proclevel > 0); }
|
||||
;
|
||||
|
||||
IdentAddr(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
} :
|
||||
IDENT { nd = dot2leaf(Name);
|
||||
*pnd = dot2node(Link, nd, NULLNODE);
|
||||
}
|
||||
[ '['
|
||||
ConstExpression(&(nd->nd_NEXT))
|
||||
']'
|
||||
|
|
||||
]
|
||||
;
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* I 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 */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
struct module {
|
||||
struct node *mo_priority;/* priority of a module */
|
||||
struct scopelist *mo_vis;/* scope of this module */
|
||||
struct node *mo_body; /* body of this module */
|
||||
#define mod_priority df_value.df_module.mo_priority
|
||||
#define mod_vis df_value.df_module.mo_vis
|
||||
#define mod_body df_value.df_module.mo_body
|
||||
};
|
||||
|
||||
struct variable {
|
||||
arith va_off; /* address or offset of variable */
|
||||
char *va_name; /* name of variable if given */
|
||||
#define var_off df_value.df_variable.va_off
|
||||
#define var_name df_value.df_variable.va_name
|
||||
};
|
||||
|
||||
struct constant {
|
||||
struct token co_const; /* result of a constant expression */
|
||||
#define con_const df_value.df_constant.co_const
|
||||
};
|
||||
|
||||
struct enumval {
|
||||
arith en_val; /* value of this enumeration literal */
|
||||
struct def *en_next; /* next enumeration literal */
|
||||
#define enm_val df_value.df_enum.en_val
|
||||
#define enm_next df_value.df_enum.en_next
|
||||
};
|
||||
|
||||
struct field {
|
||||
arith fd_off;
|
||||
struct variant {
|
||||
struct caselabellist *v_cases;
|
||||
label v_casedescr;
|
||||
struct def *v_varianttag;
|
||||
} *fd_variant;
|
||||
#define fld_off df_value.df_field.fd_off
|
||||
#define fld_variant df_value.df_field.fd_variant
|
||||
};
|
||||
|
||||
struct import {
|
||||
struct def *im_def; /* imported definition */
|
||||
#define imp_def df_value.df_import.im_def
|
||||
};
|
||||
|
||||
struct dforward {
|
||||
struct scopelist *fo_vis;
|
||||
struct node *fo_node;
|
||||
char *fo_name;
|
||||
#define for_node df_value.df_forward.fo_node
|
||||
#define for_vis df_value.df_forward.fo_vis
|
||||
#define prc_vis df_value.df_forward.fo_vis
|
||||
#define prc_body df_value.df_forward.fo_node
|
||||
#define prc_name df_value.df_forward.fo_name
|
||||
};
|
||||
|
||||
struct forwtype {
|
||||
struct node *f_node;
|
||||
struct def *f_def;
|
||||
#define df_forw_node df_value.df_fortype.f_node
|
||||
#define df_forw_def df_value.df_fortype.f_def
|
||||
};
|
||||
|
||||
struct def { /* list of definitions for a name */
|
||||
struct def *df_next; /* next definition in definitions chain */
|
||||
struct def *df_nextinscope;
|
||||
/* link all definitions in a scope */
|
||||
struct idf *df_idf; /* link back to the name */
|
||||
struct scope *df_scope; /* scope in which this definition resides */
|
||||
unsigned short df_kind; /* the kind of this definition: */
|
||||
#define D_MODULE 0x0001 /* a module */
|
||||
#define D_PROCEDURE 0x0002 /* procedure of function */
|
||||
#define D_VARIABLE 0x0004 /* a variable */
|
||||
#define D_FIELD 0x0008 /* a field in a record */
|
||||
#define D_TYPE 0x0010 /* a type */
|
||||
#define D_ENUM 0x0020 /* an enumeration literal */
|
||||
#define D_CONST 0x0040 /* a constant */
|
||||
#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 0x0400 /* not yet defined */
|
||||
#define D_FORWMODULE 0x0800 /* module must be declared later */
|
||||
#define D_FORWTYPE 0x1000 /* forward type */
|
||||
#define D_ERROR 0x4000 /* a compiler generated definition for an
|
||||
undefined variable
|
||||
*/
|
||||
#define D_INUSE 0x8000 /* identification in this scope (like D_IMPORT)
|
||||
*/
|
||||
#define D_END (D_MODULE|D_PROCEDURE) /* special value for stab.c */
|
||||
#define D_PEND (D_MODULE|D_PROCEDURE|D_VARIABLE) /* special value for stab.c */
|
||||
#define D_VALUE (D_PROCEDURE|D_VARIABLE|D_FIELD|D_ENUM|D_CONST|D_PROCHEAD)
|
||||
#define D_ISTYPE (D_HIDDEN|D_TYPE)
|
||||
#define D_IMPORTED (D_IMPORT|D_INUSE)
|
||||
#define is_type(dfx) ((dfx)->df_kind & D_ISTYPE)
|
||||
unsigned short df_flags;
|
||||
#define D_NOREG 0x01 /* set if it may not reside in a register */
|
||||
#define D_USED 0x02 /* set if used */
|
||||
#define D_DEFINED 0x04 /* set if it is assigned a value */
|
||||
#define D_VARPAR 0x08 /* set if it is a VAR parameter */
|
||||
#define D_VALPAR 0x10 /* set if it is a value parameter */
|
||||
#define D_EXPORTED 0x20 /* set if exported */
|
||||
#define D_QEXPORTED 0x40 /* set if qualified exported */
|
||||
#define D_BUSY 0x80 /* set if busy reading this definition module */
|
||||
#define D_FOREIGN 0x100 /* set for foreign language modules */
|
||||
#define D_ADDRGIVEN 0x200 /* set if address given for variable */
|
||||
#define D_FORLOOP 0x400 /* set if busy in for-loop */
|
||||
#define D_IMP_BY_EXP 0x800 /* imported definition by export */
|
||||
struct type *df_type;
|
||||
union {
|
||||
struct module df_module;
|
||||
struct variable df_variable;
|
||||
struct constant df_constant;
|
||||
struct enumval df_enum;
|
||||
struct field df_field;
|
||||
struct import df_import;
|
||||
struct dforward df_forward; /* also used for proc */
|
||||
struct forwtype df_fortype;
|
||||
int df_stdname; /* define for standard name */
|
||||
} df_value;
|
||||
};
|
||||
|
||||
typedef struct def t_def;
|
||||
/* ALLOCDEF "def" 50 */
|
||||
|
||||
extern t_def
|
||||
*define(),
|
||||
*DefineLocalModule(),
|
||||
*MkDef(),
|
||||
*DeclProc(),
|
||||
*lookup(),
|
||||
*lookfor();
|
||||
|
||||
#define NULLDEF ((t_def *) 0)
|
||||
@@ -1,393 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E F I N I T I O N M E C H A N I S M */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "main.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include "node.h"
|
||||
#include "Lpars.h"
|
||||
#include "warning.h"
|
||||
|
||||
extern char *sprint();
|
||||
|
||||
STATIC
|
||||
internal(c)
|
||||
register char *c;
|
||||
{
|
||||
if (options['x']) {
|
||||
C_exp(c);
|
||||
}
|
||||
else C_inp(c);
|
||||
}
|
||||
|
||||
STATIC
|
||||
DefInFront(df)
|
||||
register t_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 t_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;
|
||||
}
|
||||
}
|
||||
|
||||
t_def *
|
||||
MkDef(id, scope, kind)
|
||||
register t_idf *id;
|
||||
register t_scope *scope;
|
||||
{
|
||||
/* Create a new definition structure in scope "scope", with
|
||||
id "id" and kind "kind".
|
||||
*/
|
||||
register t_def *df;
|
||||
|
||||
df = new_def();
|
||||
df->df_idf = id;
|
||||
df->df_scope = scope;
|
||||
df->df_kind = kind;
|
||||
df->df_next = id->id_def;
|
||||
id->id_def = df;
|
||||
if (kind == D_ERROR || kind == D_FORWARD) df->df_type = error_type;
|
||||
if (kind & (D_TYPE|D_PROCEDURE|D_CONST)) {
|
||||
df->df_flags = D_DEFINED;
|
||||
}
|
||||
|
||||
/* enter the definition in the list of definitions in this scope
|
||||
*/
|
||||
df->df_nextinscope = scope->sc_def;
|
||||
scope->sc_def = df;
|
||||
return df;
|
||||
}
|
||||
|
||||
t_def *
|
||||
define(id, scope, kind)
|
||||
register t_idf *id;
|
||||
register t_scope *scope;
|
||||
int kind;
|
||||
{
|
||||
/* Declare an identifier in a scope, but first check if it
|
||||
already has been defined.
|
||||
If so, then check for the cases in which this is legal,
|
||||
and otherwise give an error message.
|
||||
*/
|
||||
register t_def *df;
|
||||
|
||||
DO_DEBUG(options['S'], print("define %s, %x\n", id->id_text, kind));
|
||||
df = lookup(id, scope, D_IMPORT, 0);
|
||||
if ( /* Already in this scope */
|
||||
df
|
||||
) {
|
||||
switch(df->df_kind) {
|
||||
case D_INUSE:
|
||||
if (kind != D_INUSE && kind != D_ERROR) {
|
||||
error("identifier \"%s\" already used; may not be redefined in this scope", df->df_idf->id_text);
|
||||
df->df_kind = D_ERROR;
|
||||
break;
|
||||
}
|
||||
return df;
|
||||
|
||||
case D_HIDDEN:
|
||||
/* An opaque type. We may now have found the
|
||||
definition of this type.
|
||||
*/
|
||||
if (kind == D_TYPE && df->df_scope == CurrentScope &&
|
||||
!DefinitionModule) {
|
||||
df->df_kind = D_TYPE;
|
||||
return df;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_FORWMODULE:
|
||||
/* A forward reference to a module. We may have found
|
||||
another one, or we may have found the definition
|
||||
for this module.
|
||||
*/
|
||||
if (kind & (D_FORWMODULE|D_FORWARD)) {
|
||||
return df;
|
||||
}
|
||||
|
||||
if (kind == D_MODULE) {
|
||||
FreeNode(df->for_node);
|
||||
df->mod_vis = df->for_vis;
|
||||
df->df_kind = kind;
|
||||
DefInFront(df);
|
||||
return df;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_TYPE:
|
||||
if (kind == D_FORWTYPE) return df;
|
||||
break;
|
||||
case D_FORWTYPE:
|
||||
if (kind & (D_FORWTYPE|D_TYPE)) return df;
|
||||
error("identifier \"%s\" must be a type", id->id_text);
|
||||
df->df_kind = D_ERROR;
|
||||
break;
|
||||
case D_FORWARD:
|
||||
/* A forward reference, for which we may now have
|
||||
found a definition.
|
||||
*/
|
||||
if (! (kind & (D_FORWARD | D_FORWMODULE))) {
|
||||
FreeNode(df->for_node);
|
||||
}
|
||||
df->df_kind = D_ERROR; /* avoiding error message */
|
||||
break;
|
||||
}
|
||||
|
||||
if (kind != D_ERROR && df->df_kind != D_ERROR) {
|
||||
/* Avoid spurious error messages
|
||||
*/
|
||||
error("identifier \"%s\" already declared",
|
||||
id->id_text);
|
||||
}
|
||||
if (df->df_scope == scope || df->df_kind == D_ERROR) {
|
||||
df->df_kind = kind;
|
||||
if (kind & (D_TYPE|D_PROCEDURE|D_CONST)) {
|
||||
df->df_flags = D_DEFINED;
|
||||
}
|
||||
|
||||
return df;
|
||||
}
|
||||
}
|
||||
|
||||
return MkDef(id, scope, kind);
|
||||
}
|
||||
|
||||
end_definition_list(pdf)
|
||||
register t_def **pdf;
|
||||
{
|
||||
/* Remove all imports from a definition module. This is
|
||||
neccesary because the implementation module might import
|
||||
them again.
|
||||
Also, mark all other definitions "QUALIFIED EXPORT".
|
||||
*/
|
||||
register t_def *df;
|
||||
|
||||
while (df = *pdf) {
|
||||
if (df->df_kind & D_IMPORTED) {
|
||||
if (! (df->df_flags & D_USED)) {
|
||||
warning(W_ORDINARY, "identifier \"%s\" imported but not used", df->df_idf->id_text);
|
||||
}
|
||||
RemoveFromIdList(df);
|
||||
*pdf = df->df_nextinscope;
|
||||
free_def(df);
|
||||
}
|
||||
else {
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
pdf = &(df->df_nextinscope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoveFromIdList(df)
|
||||
register t_def *df;
|
||||
{
|
||||
/* Remove definition "df" from the definition list
|
||||
*/
|
||||
register t_idf *id = df->df_idf;
|
||||
register t_def *df1;
|
||||
|
||||
if ((df1 = id->id_def) == df) id->id_def = df->df_next;
|
||||
else {
|
||||
while (df1->df_next != df) {
|
||||
assert(df1->df_next != 0);
|
||||
df1 = df1->df_next;
|
||||
}
|
||||
df1->df_next = df->df_next;
|
||||
}
|
||||
}
|
||||
|
||||
t_def *
|
||||
DeclProc(type, id)
|
||||
register t_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 t_def *df;
|
||||
register t_scope *scope;
|
||||
static int nmcount;
|
||||
char buf[256];
|
||||
|
||||
assert(type & (D_PROCEDURE | D_PROCHEAD));
|
||||
|
||||
if (type == D_PROCHEAD) {
|
||||
/* In a definition module
|
||||
*/
|
||||
df = define(id, CurrentScope, type);
|
||||
df->for_node = dot2leaf(Name);
|
||||
df->df_flags |= D_USED | D_DEFINED;
|
||||
if (CurrentScope->sc_definedby->df_flags & D_FOREIGN) {
|
||||
df->prc_name = id->id_text;
|
||||
}
|
||||
else {
|
||||
sprint(buf,"%s_%s",CurrentScope->sc_name,id->id_text);
|
||||
df->prc_name = Salloc(buf, (unsigned) (strlen(buf)+1));
|
||||
}
|
||||
if (CurrVis == Defined->mod_vis) {
|
||||
/* The current module will define this routine.
|
||||
make sure the name is exported.
|
||||
*/
|
||||
C_exp(df->prc_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
df = lookup(id, CurrentScope, D_IMPORTED, 0);
|
||||
if (df && df->df_kind == D_PROCHEAD) {
|
||||
/* C_exp already generated when we saw the definition
|
||||
in the definition module
|
||||
*/
|
||||
DefInFront(df);
|
||||
}
|
||||
else {
|
||||
df = define(id, CurrentScope, type);
|
||||
sprint(buf,"_%d_%s",++nmcount,id->id_text);
|
||||
df->prc_name = Salloc(buf, (unsigned)(strlen(buf)+1));
|
||||
internal(buf);
|
||||
df->df_flags |= D_DEFINED;
|
||||
}
|
||||
open_scope(OPENSCOPE);
|
||||
scope = CurrentScope;
|
||||
scope->sc_name = df->prc_name;
|
||||
scope->sc_definedby = df;
|
||||
}
|
||||
df->prc_vis = CurrVis;
|
||||
|
||||
return df;
|
||||
}
|
||||
|
||||
EndProc(df, id)
|
||||
register t_def *df;
|
||||
t_idf *id;
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
extern int return_occurred;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
t_def *
|
||||
DefineLocalModule(id)
|
||||
t_idf *id;
|
||||
{
|
||||
/* Create a definition for a local module. Also give it
|
||||
a name to be used for code generation.
|
||||
*/
|
||||
register t_def *df = define(id, CurrentScope, D_MODULE);
|
||||
register t_scope *sc;
|
||||
static int modulecount = 0;
|
||||
char buf[256];
|
||||
extern int proclevel;
|
||||
|
||||
sprint(buf, "_%d%s_", ++modulecount, id->id_text);
|
||||
|
||||
if (!df->mod_vis) {
|
||||
/* We never saw the name of this module before. Create a
|
||||
scope for it.
|
||||
*/
|
||||
open_scope(CLOSEDSCOPE);
|
||||
df->mod_vis = CurrVis;
|
||||
}
|
||||
|
||||
CurrVis = df->mod_vis;
|
||||
|
||||
sc = CurrentScope;
|
||||
sc->sc_level = proclevel;
|
||||
sc->sc_definedby = df;
|
||||
sc->sc_name = Salloc(buf, (unsigned) (strlen(buf) + 1));
|
||||
|
||||
/* Create a type for it
|
||||
*/
|
||||
df->df_type = standard_type(T_RECORD, 1, (arith) 0);
|
||||
df->df_type->rec_scope = sc;
|
||||
|
||||
/* Generate code that indicates that the initialization procedure
|
||||
for this module is local.
|
||||
*/
|
||||
internal(buf);
|
||||
return df;
|
||||
}
|
||||
|
||||
CheckWithDef(df, tp)
|
||||
register t_def *df;
|
||||
t_type *tp;
|
||||
{
|
||||
/* Check the header of a procedure declaration against a
|
||||
possible earlier definition in the definition module.
|
||||
*/
|
||||
|
||||
if (df->df_kind == D_PROCHEAD &&
|
||||
df->df_type &&
|
||||
df->df_type != error_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_kind = D_PROCEDURE;
|
||||
}
|
||||
df->df_type = tp;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PrDef(df)
|
||||
register t_def *df;
|
||||
{
|
||||
print("n: %s, k: %d\n", df->df_idf->id_text, df->df_kind);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
@@ -1,22 +0,0 @@
|
||||
/* D E F A U L T S I Z E S A N D A L I G N M E N T S */
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
#define MAXSIZE 8 /* the maximum of the SZ_* constants */
|
||||
/* target machine sizes */
|
||||
#define SZ_CHAR (arith)1
|
||||
#define SZ_WORD (arith)4
|
||||
#define SZ_INT (arith)4
|
||||
#define SZ_LONG (arith)4
|
||||
#define SZ_FLOAT (arith)4
|
||||
#define SZ_DOUBLE (arith)8
|
||||
#define SZ_POINTER (arith)4
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_WORD (int) SZ_WORD
|
||||
#define AL_INT (int) SZ_WORD
|
||||
#define AL_LONG (int) SZ_WORD
|
||||
#define AL_FLOAT (int) SZ_WORD
|
||||
#define AL_DOUBLE (int) SZ_WORD
|
||||
#define AL_POINTER (int) SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E F I N I T I O N M O D U L E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <alloc.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "input.h"
|
||||
#include "scope.h"
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "Lpars.h"
|
||||
#include "f_info.h"
|
||||
#include "main.h"
|
||||
#include "node.h"
|
||||
#include "type.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
long sys_filesize();
|
||||
#endif
|
||||
|
||||
t_idf *DefId;
|
||||
|
||||
char *
|
||||
getwdir(fn)
|
||||
register char *fn;
|
||||
{
|
||||
register char *p;
|
||||
char *strrindex();
|
||||
|
||||
while ((p = strrindex(fn,'/')) && *(p + 1) == '\0') {
|
||||
/* remove trailing /'s */
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
fn = Salloc(fn, (unsigned) (p - &fn[0] + 1));
|
||||
*p = '/';
|
||||
return fn;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
STATIC
|
||||
GetFile(name)
|
||||
char *name;
|
||||
{
|
||||
/* Try to find a file with basename "name" and extension ".def",
|
||||
in the directories mentioned in "DEFPATH".
|
||||
*/
|
||||
char buf[15];
|
||||
char *strncpy(), *strcat();
|
||||
|
||||
strncpy(buf, name, 10);
|
||||
buf[10] = '\0'; /* maximum length */
|
||||
strcat(buf, ".def");
|
||||
DEFPATH[0] = WorkingDir;
|
||||
if (! InsertFile(buf, DEFPATH, &(FileName))) {
|
||||
error("could not find a DEFINITION MODULE for \"%s\"", name);
|
||||
return 0;
|
||||
}
|
||||
WorkingDir = getwdir(FileName);
|
||||
LineNumber = 1;
|
||||
DO_DEBUG(options['F'], debug("File %s : %ld characters", FileName, sys_filesize(FileName)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
t_def *
|
||||
GetDefinitionModule(id, incr)
|
||||
register t_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".
|
||||
*/
|
||||
register t_def *df;
|
||||
static int level;
|
||||
t_scopelist *vis;
|
||||
char *fn = FileName;
|
||||
int ln = LineNumber;
|
||||
t_scope *newsc;
|
||||
|
||||
level += incr;
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
if (!df) {
|
||||
/* Read definition module. Make an exception for SYSTEM.
|
||||
*/
|
||||
extern int ForeignFlag;
|
||||
|
||||
ForeignFlag = 0;
|
||||
DefId = id;
|
||||
open_scope(CLOSEDSCOPE);
|
||||
newsc = CurrentScope;
|
||||
vis = CurrVis;
|
||||
newsc->sc_defmodule = incr;
|
||||
if (!strcmp(id->id_text, "SYSTEM")) {
|
||||
do_SYSTEM();
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
}
|
||||
else {
|
||||
if (!is_anon_idf(id) && GetFile(id->id_text)) {
|
||||
|
||||
char *f = FileName;
|
||||
DefModule();
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
if (level == 1 &&
|
||||
(df && !(df->df_flags & D_FOREIGN))) {
|
||||
/* The module is directly imported by
|
||||
the currently defined module, and
|
||||
is not foreign, so we have to
|
||||
remember its name because we have
|
||||
to call its initialization routine
|
||||
*/
|
||||
static t_node *nd_end;
|
||||
register t_node *n;
|
||||
extern t_node *Modules;
|
||||
|
||||
n = dot2leaf(Def);
|
||||
n->nd_def = newsc->sc_definedby;
|
||||
if (nd_end) nd_end->nd_NEXT = n;
|
||||
else Modules = n;
|
||||
nd_end = n;
|
||||
}
|
||||
free(f);
|
||||
}
|
||||
else {
|
||||
df = lookup(id, GlobalScope, D_IMPORTED, 0);
|
||||
newsc->sc_name = id->id_text;
|
||||
}
|
||||
}
|
||||
close_scope(SC_CHKFORW);
|
||||
if (! df) {
|
||||
df = MkDef(id, GlobalScope, D_ERROR);
|
||||
df->mod_vis = vis;
|
||||
newsc->sc_definedby = df;
|
||||
}
|
||||
}
|
||||
else if (df->df_flags & D_BUSY) {
|
||||
error("definition module \"%s\" depends on itself",
|
||||
id->id_text);
|
||||
}
|
||||
else if (df == Defined && level == 1) {
|
||||
error("cannot import from current module \"%s\"", id->id_text);
|
||||
df->df_kind = D_ERROR;
|
||||
}
|
||||
FileName = fn;
|
||||
LineNumber = ln;
|
||||
assert(df);
|
||||
level -= incr;
|
||||
return df;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E S I G N A T O R D E S C R I P T I O N S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* 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.
|
||||
It contains information on how to find the designator, after generation
|
||||
of the code that is common to both address and value computations.
|
||||
*/
|
||||
|
||||
struct desig {
|
||||
short dsg_kind;
|
||||
#define DSG_INIT 0 /* don't know anything yet */
|
||||
#define DSG_LOADED 1 /* designator loaded on top of the stack */
|
||||
#define DSG_PLOADED 2 /* designator accessible through pointer on
|
||||
stack, possibly with an offset
|
||||
*/
|
||||
#define DSG_FIXED 3 /* designator directly accessible */
|
||||
#define DSG_PFIXED 4 /* designator accessible through directly
|
||||
accessible pointer
|
||||
*/
|
||||
#define DSG_INDEXED 5 /* designator accessible through array
|
||||
operation. Address of array descriptor on
|
||||
top of the stack, index beneath that, and
|
||||
base address beneath that
|
||||
*/
|
||||
arith dsg_offset; /* contains an offset for PLOADED,
|
||||
or for FIXED or PFIXED it contains an
|
||||
offset from dsg_name, if it exists,
|
||||
or from the current Local Base
|
||||
*/
|
||||
char *dsg_name; /* name of global variable, used for
|
||||
FIXED and PFIXED
|
||||
*/
|
||||
struct def *dsg_def; /* def structure associated with this
|
||||
designator, or 0
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct desig t_desig;
|
||||
|
||||
/* The next structure describes the designator in a with-statement.
|
||||
We have a linked list of them, as with-statements may be nested.
|
||||
*/
|
||||
|
||||
struct withdesig {
|
||||
struct withdesig *w_next;
|
||||
int w_flags; /* D_USED|D_DEFINED */
|
||||
struct scope *w_scope; /* scope in which fields of this record
|
||||
reside
|
||||
*/
|
||||
t_desig w_desig; /* a desig structure for this particular
|
||||
designator
|
||||
*/
|
||||
};
|
||||
|
||||
extern struct withdesig *WithDesigs;
|
||||
|
||||
#define NO_LABEL ((label) 0)
|
||||
@@ -1,705 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E S I G N A T O R E V A L U A T I O N */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* 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"
|
||||
structure. It also contains routines to load an address, load a value
|
||||
or perform a store.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <assert.h>
|
||||
#include <alloc.h>
|
||||
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "scope.h"
|
||||
#include "desig.h"
|
||||
#include "node.h"
|
||||
#include "warning.h"
|
||||
#include "walk.h"
|
||||
#include "squeeze.h"
|
||||
|
||||
extern int proclevel;
|
||||
extern arith NewPtr();
|
||||
extern char options[];
|
||||
|
||||
int
|
||||
WordOrDouble(ds, size)
|
||||
t_desig *ds;
|
||||
arith size;
|
||||
{
|
||||
/* Check if designator is suitable for word or double-word
|
||||
operation
|
||||
*/
|
||||
if ((int) (ds->dsg_offset) % word_align == 0) {
|
||||
if (size == word_size) return 1;
|
||||
if (size == dword_size) return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOL(offset, size)
|
||||
arith offset, size;
|
||||
{
|
||||
if (size == word_size) {
|
||||
C_lol(offset);
|
||||
}
|
||||
else if (size == dword_size) {
|
||||
C_ldl(offset);
|
||||
}
|
||||
else {
|
||||
C_lal(offset);
|
||||
C_loi(size);
|
||||
}
|
||||
}
|
||||
|
||||
STL(offset, size)
|
||||
arith offset, size;
|
||||
{
|
||||
if (size == word_size) {
|
||||
C_stl(offset);
|
||||
}
|
||||
else if (size == dword_size) {
|
||||
C_sdl(offset);
|
||||
}
|
||||
else {
|
||||
C_lal(offset);
|
||||
C_sti(size);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
DoLoad(ds, size)
|
||||
register t_desig *ds;
|
||||
arith size;
|
||||
{
|
||||
/* Try to load designator with word or double-word operation.
|
||||
Return 0 if not done
|
||||
*/
|
||||
switch (WordOrDouble(ds, size)) {
|
||||
default:
|
||||
return 0;
|
||||
case 1:
|
||||
if (ds->dsg_name) {
|
||||
C_loe_dnam(ds->dsg_name, ds->dsg_offset);
|
||||
}
|
||||
else C_lol(ds->dsg_offset);
|
||||
break;
|
||||
case 2:
|
||||
if (ds->dsg_name) {
|
||||
C_lde_dnam(ds->dsg_name, ds->dsg_offset);
|
||||
}
|
||||
else C_ldl(ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
DoStore(ds, size)
|
||||
register t_desig *ds;
|
||||
arith size;
|
||||
{
|
||||
/* Try to store designator with word or double-word operation.
|
||||
Return 0 if not done
|
||||
*/
|
||||
switch (WordOrDouble(ds, size)) {
|
||||
default:
|
||||
return 0;
|
||||
case 1:
|
||||
if (ds->dsg_name) {
|
||||
C_ste_dnam(ds->dsg_name, ds->dsg_offset);
|
||||
}
|
||||
else C_stl(ds->dsg_offset);
|
||||
break;
|
||||
case 2:
|
||||
if (ds->dsg_name) {
|
||||
C_sde_dnam(ds->dsg_name, ds->dsg_offset);
|
||||
}
|
||||
else C_sdl(ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return 1 if the type indicated by tp has a size that is a
|
||||
multiple of the word_size and is also word_aligned
|
||||
*/
|
||||
#define word_multiple(tp) \
|
||||
( (int)(tp->tp_size) % (int)word_size == 0 && \
|
||||
tp->tp_align >= word_align)
|
||||
|
||||
/* Return 1 if the type indicated by tp has a size that is a proper
|
||||
dividor of the word_size, and has alignment >= size or
|
||||
alignment >= word_align
|
||||
*/
|
||||
#define word_dividor(tp) \
|
||||
( tp->tp_size < word_size && \
|
||||
(int)word_size % (int)(tp->tp_size) == 0 && \
|
||||
(tp->tp_align >= word_align || \
|
||||
tp->tp_align >= (int)(tp->tp_size)))
|
||||
|
||||
#define USE_LOI_STI 0
|
||||
#define USE_LOS_STS 1
|
||||
#define USE_LOAD_STORE 2
|
||||
#define USE_BLM 3 /* like USE_LOI_STI, but more restricted:
|
||||
multiple of word_size only
|
||||
*/
|
||||
|
||||
STATIC int
|
||||
suitable_move(tp)
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Find out how to load or store the value indicated by "ds".
|
||||
There are four ways:
|
||||
- suitable for BLM/LOI/STI
|
||||
- suitable for LOI/STI
|
||||
- suitable for LOS/STS/BLS
|
||||
- suitable for calls to load/store/blockmove
|
||||
*/
|
||||
|
||||
if (! word_multiple(tp)) {
|
||||
if (word_dividor(tp)) return USE_LOI_STI;
|
||||
return USE_LOAD_STORE;
|
||||
}
|
||||
if (! fit(tp->tp_size, (int) word_size)) return USE_LOS_STS;
|
||||
return USE_BLM;
|
||||
}
|
||||
|
||||
CodeValue(ds, tp)
|
||||
register t_desig *ds;
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Generate code to load the value of the designator described
|
||||
in "ds".
|
||||
*/
|
||||
arith sz;
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_LOADED:
|
||||
break;
|
||||
|
||||
case DSG_FIXED:
|
||||
if (DoLoad(ds, tp->tp_size)) break;
|
||||
/* Fall through */
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
switch (suitable_move(tp)) {
|
||||
case USE_BLM:
|
||||
case USE_LOI_STI:
|
||||
#ifndef SQUEEZE
|
||||
CodeAddress(ds);
|
||||
C_loi(tp->tp_size);
|
||||
break;
|
||||
#endif
|
||||
case USE_LOS_STS:
|
||||
CodeAddress(ds);
|
||||
CodeConst(tp->tp_size, (int)pointer_size);
|
||||
C_los(pointer_size);
|
||||
break;
|
||||
case USE_LOAD_STORE:
|
||||
sz = WA(tp->tp_size);
|
||||
if (ds->dsg_kind != DSG_PFIXED) {
|
||||
arith tmp = NewPtr();
|
||||
|
||||
CodeAddress(ds);
|
||||
STL(tmp, pointer_size);
|
||||
CodeConst(-sz, (int) pointer_size);
|
||||
C_ass(pointer_size);
|
||||
LOL(tmp, pointer_size);
|
||||
FreePtr(tmp);
|
||||
}
|
||||
else {
|
||||
CodeConst(-sz, (int) pointer_size);
|
||||
C_ass(pointer_size);
|
||||
CodeAddress(ds);
|
||||
}
|
||||
CodeConst(tp->tp_size, (int) pointer_size);
|
||||
CAL("load", (int)pointer_size + (int)pointer_size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
C_lar(word_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeValue)");
|
||||
}
|
||||
|
||||
ds->dsg_kind = DSG_LOADED;
|
||||
}
|
||||
|
||||
ChkForFOR(nd)
|
||||
register t_node *nd;
|
||||
{
|
||||
/* Check for an assignment to a FOR-loop control variable
|
||||
*/
|
||||
if (nd->nd_class == Def) {
|
||||
register t_def *df = nd->nd_def;
|
||||
|
||||
if (df->df_flags & D_FORLOOP) {
|
||||
node_warning(nd,
|
||||
W_ORDINARY,
|
||||
"assignment to FOR-loop control variable");
|
||||
df->df_flags &= ~D_FORLOOP;
|
||||
/* only procude warning once */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CodeStore(ds, tp)
|
||||
register t_desig *ds;
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Generate code to store the value on the stack in the designator
|
||||
described in "ds"
|
||||
*/
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_FIXED:
|
||||
if (DoStore(ds, tp->tp_size)) break;
|
||||
/* Fall through */
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
CodeAddress(ds);
|
||||
switch (suitable_move(tp)) {
|
||||
case USE_BLM:
|
||||
case USE_LOI_STI:
|
||||
#ifndef SQUEEZE
|
||||
C_sti(tp->tp_size);
|
||||
break;
|
||||
#endif
|
||||
case USE_LOS_STS:
|
||||
CodeConst(tp->tp_size, (int) pointer_size);
|
||||
C_sts(pointer_size);
|
||||
break;
|
||||
case USE_LOAD_STORE:
|
||||
CodeConst(tp->tp_size, (int) pointer_size);
|
||||
C_cal("store");
|
||||
CodeConst(pointer_size + pointer_size + WA(tp->tp_size),
|
||||
(int) pointer_size);
|
||||
C_ass(pointer_size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
C_sar(word_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeStore)");
|
||||
}
|
||||
|
||||
ds->dsg_kind = DSG_INIT;
|
||||
}
|
||||
|
||||
CodeCopy(lhs, rhs, sz, psize)
|
||||
register t_desig *lhs, *rhs;
|
||||
arith sz, *psize;
|
||||
{
|
||||
/* Do part of a copy, which is assumed to be "reasonable",
|
||||
so that it can be done with LOI/STI or BLM.
|
||||
*/
|
||||
t_desig l, r;
|
||||
|
||||
l = *lhs; r = *rhs;
|
||||
*psize -= sz;
|
||||
lhs->dsg_offset += sz;
|
||||
rhs->dsg_offset += sz;
|
||||
CodeAddress(&r);
|
||||
if (sz <= dword_size) {
|
||||
C_loi(sz);
|
||||
CodeAddress(&l);
|
||||
C_sti(sz);
|
||||
}
|
||||
else {
|
||||
CodeAddress(&l);
|
||||
C_blm(sz);
|
||||
}
|
||||
}
|
||||
|
||||
t_desig null_desig;
|
||||
|
||||
CodeMove(rhs, left, rtp)
|
||||
register t_desig *rhs;
|
||||
register t_node *left;
|
||||
t_type *rtp;
|
||||
{
|
||||
/* Generate code for an assignment. Testing of type
|
||||
compatibility and the like is already done.
|
||||
Go through some (considerable) trouble to see if a BLM can be
|
||||
generated.
|
||||
*/
|
||||
t_desig lhs;
|
||||
register t_type *tp = left->nd_type;
|
||||
int loadedflag = 0;
|
||||
|
||||
lhs = null_desig;
|
||||
ChkForFOR(left);
|
||||
switch(rhs->dsg_kind) {
|
||||
case DSG_LOADED:
|
||||
CodeDesig(left, &lhs);
|
||||
if (rtp->tp_fund == T_STRING) {
|
||||
/* size of a string literal fits in an
|
||||
int of size word_size
|
||||
*/
|
||||
CodeAddress(&lhs);
|
||||
C_loc(rtp->tp_size);
|
||||
C_loc(tp->tp_size);
|
||||
CAL("StringAssign", (int)pointer_size + (int)pointer_size + (int)dword_size);
|
||||
break;
|
||||
}
|
||||
CodeStore(&lhs, tp);
|
||||
break;
|
||||
case DSG_FIXED:
|
||||
CodeDesig(left, &lhs);
|
||||
if (lhs.dsg_kind == DSG_FIXED &&
|
||||
fit(tp->tp_size, (int) word_size) &&
|
||||
(int) (lhs.dsg_offset) % word_align ==
|
||||
(int) (rhs->dsg_offset) % word_align) {
|
||||
register int sz = 1;
|
||||
arith size = tp->tp_size;
|
||||
|
||||
while (size && sz < word_align) {
|
||||
/* First copy up to word-aligned
|
||||
boundaries
|
||||
*/
|
||||
if (!((int)(lhs.dsg_offset)%(sz+sz))) {
|
||||
sz += sz;
|
||||
}
|
||||
else CodeCopy(&lhs, rhs, (arith) sz, &size);
|
||||
}
|
||||
/* Now copy the bulk
|
||||
*/
|
||||
sz = (int) size % (int) word_size;
|
||||
size -= sz;
|
||||
CodeCopy(&lhs, rhs, size, &size);
|
||||
size = sz;
|
||||
sz = word_size;
|
||||
while (size) {
|
||||
/* And then copy remaining parts
|
||||
*/
|
||||
sz >>= 1;
|
||||
if (size >= sz) {
|
||||
CodeCopy(&lhs, rhs, (arith) sz, &size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
CodeAddress(&lhs);
|
||||
loadedflag = 1;
|
||||
/* Fall through */
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
assert(! loadedflag || rhs->dsg_kind == DSG_FIXED);
|
||||
CodeAddress(rhs);
|
||||
if (loadedflag) {
|
||||
C_exg(pointer_size);
|
||||
}
|
||||
else {
|
||||
CodeDesig(left, &lhs);
|
||||
CodeAddress(&lhs);
|
||||
}
|
||||
switch (suitable_move(tp)) {
|
||||
case USE_BLM:
|
||||
#ifndef SQUEEZE
|
||||
C_blm(tp->tp_size);
|
||||
break;
|
||||
#endif
|
||||
case USE_LOS_STS:
|
||||
CodeConst(tp->tp_size, (int) pointer_size);
|
||||
C_bls(pointer_size);
|
||||
break;
|
||||
case USE_LOAD_STORE:
|
||||
case USE_LOI_STI:
|
||||
CodeConst(tp->tp_size, (int) pointer_size);
|
||||
CAL("blockmove", 3 * (int)pointer_size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
crash("CodeMove");
|
||||
}
|
||||
}
|
||||
|
||||
CodeAddress(ds)
|
||||
register t_desig *ds;
|
||||
{
|
||||
/* Generate code to load the address of the designator described
|
||||
in "ds"
|
||||
*/
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_PLOADED:
|
||||
if (ds->dsg_offset) {
|
||||
C_adp(ds->dsg_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case DSG_FIXED:
|
||||
if (ds->dsg_name) {
|
||||
C_lae_dnam(ds->dsg_name, ds->dsg_offset);
|
||||
break;
|
||||
}
|
||||
C_lal(ds->dsg_offset);
|
||||
if (ds->dsg_def) ds->dsg_def->df_flags |= D_NOREG;
|
||||
break;
|
||||
|
||||
case DSG_PFIXED:
|
||||
if (! DoLoad(ds, pointer_size)) {
|
||||
assert(0);
|
||||
}
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
C_aar(word_size);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeAddress)");
|
||||
}
|
||||
|
||||
ds->dsg_offset = 0;
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
}
|
||||
|
||||
CodeFieldDesig(df, ds)
|
||||
register t_def *df;
|
||||
register t_desig *ds;
|
||||
{
|
||||
/* Generate code for a field designator. Only the code common for
|
||||
address as well as value computation is generated, and the
|
||||
resulting information on where to find the designator is placed
|
||||
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
|
||||
of this designator.
|
||||
So, first find the right WITH statement, which is the
|
||||
first one of the proper record type, which is
|
||||
recognized by its scope indication.
|
||||
*/
|
||||
register struct withdesig *wds = WithDesigs;
|
||||
|
||||
assert(wds != 0);
|
||||
|
||||
while (wds->w_scope != df->df_scope) {
|
||||
wds = wds->w_next;
|
||||
assert(wds != 0);
|
||||
}
|
||||
|
||||
/* Found it. Now, act like it was a selection.
|
||||
*/
|
||||
*ds = wds->w_desig;
|
||||
wds->w_flags |= df->df_flags;
|
||||
assert(ds->dsg_kind == DSG_PFIXED);
|
||||
}
|
||||
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_PLOADED:
|
||||
case DSG_FIXED:
|
||||
ds->dsg_offset += df->fld_off;
|
||||
break;
|
||||
|
||||
case DSG_PFIXED:
|
||||
case DSG_INDEXED:
|
||||
CodeAddress(ds);
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = df->fld_off;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeFieldDesig)");
|
||||
}
|
||||
}
|
||||
|
||||
CodeVarDesig(df, ds)
|
||||
register t_def *df;
|
||||
register t_desig *ds;
|
||||
{
|
||||
/* Generate code for a variable represented by a "def" structure.
|
||||
Of course, there are numerous cases: the variable is local,
|
||||
it is a value parameter, it is a var parameter, it is one of
|
||||
those of an enclosing procedure, or it is global.
|
||||
*/
|
||||
register t_scope *sc = df->df_scope;
|
||||
int difflevel;
|
||||
|
||||
/* Selections from a module are handled earlier, when identifying
|
||||
the variable, so ...
|
||||
*/
|
||||
assert(ds->dsg_kind == DSG_INIT);
|
||||
|
||||
if (df->df_flags & D_ADDRGIVEN) {
|
||||
/* the programmer specified an address in the declaration of
|
||||
the variable. Generate code to push the address.
|
||||
*/
|
||||
CodeConst(df->var_off, (int) pointer_size);
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (df->var_name) {
|
||||
/* this variable has been given a name, so it is global.
|
||||
It is directly accessible.
|
||||
*/
|
||||
ds->dsg_name = df->var_name;
|
||||
ds->dsg_offset = 0;
|
||||
ds->dsg_kind = DSG_FIXED;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((difflevel = proclevel - sc->sc_level) != 0) {
|
||||
/* the variable is local to a statically enclosing procedure.
|
||||
*/
|
||||
assert(difflevel > 0);
|
||||
|
||||
df->df_flags |= D_NOREG;
|
||||
if (df->df_flags & (D_VARPAR|D_VALPAR)) {
|
||||
/* value or var parameter
|
||||
*/
|
||||
C_lxa((arith) difflevel);
|
||||
if ((df->df_flags & D_VARPAR) ||
|
||||
IsConformantArray(df->df_type)) {
|
||||
/* var parameter or conformant array.
|
||||
The address is passed.
|
||||
*/
|
||||
C_adp(df->var_off);
|
||||
C_loi(pointer_size);
|
||||
ds->dsg_offset = 0;
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else C_lxl((arith) difflevel);
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = df->var_off;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now, finally, we have a local variable or a local parameter
|
||||
*/
|
||||
if ((df->df_flags & D_VARPAR) ||
|
||||
IsConformantArray(df->df_type)) {
|
||||
/* a var parameter; address directly accessible.
|
||||
*/
|
||||
ds->dsg_kind = DSG_PFIXED;
|
||||
}
|
||||
else ds->dsg_kind = DSG_FIXED;
|
||||
ds->dsg_offset = df->var_off;
|
||||
ds->dsg_def = df;
|
||||
}
|
||||
|
||||
CodeDesig(nd, ds)
|
||||
register t_node *nd;
|
||||
register t_desig *ds;
|
||||
{
|
||||
/* Generate code for a designator. Use divide and conquer
|
||||
principle
|
||||
*/
|
||||
register t_def *df;
|
||||
|
||||
switch(nd->nd_class) { /* Divide */
|
||||
case Def:
|
||||
df = nd->nd_def;
|
||||
if (nd->nd_NEXT) CodeDesig(nd->nd_NEXT, ds);
|
||||
|
||||
switch(df->df_kind) {
|
||||
case D_FIELD:
|
||||
CodeFieldDesig(df, ds);
|
||||
break;
|
||||
|
||||
case D_VARIABLE:
|
||||
CodeVarDesig(df, ds);
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeDesig) Def");
|
||||
}
|
||||
break;
|
||||
|
||||
case Arrsel:
|
||||
assert(nd->nd_symb == '[' || nd->nd_symb == ',');
|
||||
|
||||
CodeDesig(nd->nd_LEFT, ds);
|
||||
CodeAddress(ds);
|
||||
CodePExpr(nd->nd_RIGHT);
|
||||
nd = nd->nd_LEFT;
|
||||
|
||||
/* Now load address of descriptor
|
||||
*/
|
||||
if (IsConformantArray(nd->nd_type)) {
|
||||
arith off;
|
||||
assert(nd->nd_class == Def);
|
||||
|
||||
df = nd->nd_def;
|
||||
off = df->var_off + pointer_size;
|
||||
if (proclevel > df->df_scope->sc_level) {
|
||||
C_lxa((arith) (proclevel - df->df_scope->sc_level));
|
||||
C_adp(off);
|
||||
}
|
||||
else C_lal(off);
|
||||
}
|
||||
else {
|
||||
C_loc(nd->nd_type->arr_low);
|
||||
C_sbu(int_size);
|
||||
c_lae_dlb(nd->nd_type->arr_descr);
|
||||
}
|
||||
if (options['A']) {
|
||||
C_cal("rcka");
|
||||
}
|
||||
ds->dsg_kind = DSG_INDEXED;
|
||||
break;
|
||||
|
||||
case Arrow:
|
||||
assert(nd->nd_symb == '^');
|
||||
|
||||
nd = nd->nd_RIGHT;
|
||||
CodeDesig(nd, ds);
|
||||
switch(ds->dsg_kind) {
|
||||
case DSG_LOADED:
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
break;
|
||||
|
||||
case DSG_INDEXED:
|
||||
case DSG_PLOADED:
|
||||
case DSG_PFIXED:
|
||||
CodeValue(ds, nd->nd_type);
|
||||
ds->dsg_kind = DSG_PLOADED;
|
||||
ds->dsg_offset = 0;
|
||||
break;
|
||||
|
||||
case DSG_FIXED:
|
||||
ds->dsg_kind = DSG_PFIXED;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeDesig) Uoper");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("(CodeDesig) class");
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
.TH EM_M2 6 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
em_m2 \- ACK Modula\-2 compiler
|
||||
.SH SYNOPSIS
|
||||
.B ~em/lib.bin/em_m2
|
||||
.RI [ option ]
|
||||
.I source
|
||||
.I destination
|
||||
.SH DESCRIPTION
|
||||
.I Em_m2
|
||||
is a
|
||||
compiler, part of the Amsterdam Compiler Kit, that translates Modula-2 programs
|
||||
into EM code.
|
||||
The input is taken from
|
||||
.IR source ,
|
||||
while the
|
||||
EM code is written on
|
||||
.IR destination .
|
||||
.br
|
||||
.I Option
|
||||
is a, possibly empty, sequence of the following combinations:
|
||||
.IP \fB\-I\fIdirname\fR
|
||||
.br
|
||||
append \fIdirname\fR to the list of directories where definition modules
|
||||
are looked for.
|
||||
.PP
|
||||
When the compiler needs a definition module, it is first searched for
|
||||
in the current directory, and then in the directories given to it by the
|
||||
\-\fBI\fR flag
|
||||
in the order given.
|
||||
.IP \fB\-M\fP\fIn\fP
|
||||
set maximum identifier length to \fIn\fP.
|
||||
The minimum value for \fIn\fR is 14, because the keyword
|
||||
"IMPLEMENTATION" is that long.
|
||||
.IP \fB\-n\fR
|
||||
do not generate EM register messages.
|
||||
The user-declared variables will not be stored into registers on the target
|
||||
machine.
|
||||
.IP \fB\-L\fR
|
||||
do not generate the EM \fBfil\fR and \fBlin\fR instructions that enable
|
||||
an interpreter to keep track of the current location in the source code.
|
||||
.IP \fB\-V\fIcm\fR.\fIn\fR,\ \fB\-V\fIcm\fR.\fIncm\fR.\fIn\fR\ ...
|
||||
.br
|
||||
set the size and alignment requirements.
|
||||
The letter \fIc\fR indicates the simple type, which is one of
|
||||
\fBw\fR(word size), \fBi\fR(INTEGER), \fBl\fR(LONGINT), \fBf\fR(REAL),
|
||||
\fBd\fR(LONGREAL), or \fBp\fR(POINTER).
|
||||
It may also be the letter \fBS\fR, indicating that an initial
|
||||
record alignment follows.
|
||||
The \fIm\fR parameter can be used to specify the length of the type (in bytes)
|
||||
and the \fIn\fR parameter for the alignment of that type.
|
||||
Absence of \fIm\fR or \fIn\fR causes a default value to be retained.
|
||||
.IP \fB\-w\fR\fIclasses\fR
|
||||
suppress warning messages whose class is a member of \fIclasses\fR.
|
||||
Currently, there are three classes: \fBO\fR, indicating old-flashioned use,
|
||||
\fBW\fR, indicating "ordinary" warnings, and \fBR\fR, indicating
|
||||
restricted Modula-2.
|
||||
If no \fIclasses\fR are given, all warnings are suppressed.
|
||||
By default, warnings in class \fBO\fR and \fBW\fR are given.
|
||||
.IP \fB\-W\fR\fIclasses\fR
|
||||
allow for warning messages whose class is a member of \fIclasses\fR.
|
||||
.IP \fB\-x\fR
|
||||
make all procedure names global, so that \fIadb\fR(1) understands them.
|
||||
.IP \fB\-g\fR
|
||||
produce a DBX-style symbol table.
|
||||
.IP \fB\-l\fR
|
||||
enable local extensions. Currently, there are two local extensions:
|
||||
procedure constants, and the type LONGCARD.
|
||||
.IP \fB\-s\fR
|
||||
make INTEGER ranges symmetric, t.i., MIN(INTEGER) = - MAX(INTEGER).
|
||||
This is useful for interpreters that use the "real" MIN(INTEGER) to
|
||||
indicate "undefined".
|
||||
.IP \fB-R\fR
|
||||
disable all range checks.
|
||||
.IP \fB-A\fR
|
||||
enable extra array bound checks, for machines that do not implement the
|
||||
EM ones.
|
||||
.IP \fB-U\fR
|
||||
allow for underscores within identifiers. Identifiers may not start with
|
||||
an underscore, even if this flag is given.
|
||||
.IP \fB-3\fR
|
||||
only accept Modula-2 programs that strictly conform to [1].
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
\fIack\fR(1), \fImodula-2\fR(1)
|
||||
.IP [1]
|
||||
N. Wirth, \fIProgramming in Modula-2\fP, 3rd edition, Springer Verlag.
|
||||
.SH DIAGNOSTICS
|
||||
All warning and error messages are written on standard error output.
|
||||
.SH REMARKS
|
||||
Debugging and profiling facilities may be present during the development
|
||||
of \fIem_m2\fP.
|
||||
@@ -1,561 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* H I G H L E V E L S Y M B O L E N T R Y */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "dbsymtab.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "scope.h"
|
||||
#include "node.h"
|
||||
#include "main.h"
|
||||
#include "misc.h"
|
||||
#include "f_info.h"
|
||||
|
||||
t_def *
|
||||
Enter(name, kind, type, pnam)
|
||||
char *name;
|
||||
t_type *type;
|
||||
{
|
||||
/* Enter a definition for "name" with kind "kind" and type
|
||||
"type" in the Current Scope. If it is a standard name, also
|
||||
put its number in the definition structure.
|
||||
*/
|
||||
register t_def *df;
|
||||
|
||||
df = define(str2idf(name, 0), CurrentScope, kind);
|
||||
df->df_type = type;
|
||||
if (pnam) df->df_value.df_stdname = pnam;
|
||||
#ifdef DBSYMTAB
|
||||
else if (options['g']) stb_string(df, kind);
|
||||
#endif /* DBSYMTAB */
|
||||
return df;
|
||||
}
|
||||
|
||||
t_def *
|
||||
EnterType(name, type)
|
||||
char *name;
|
||||
t_type *type;
|
||||
{
|
||||
/* Enter a type definition for "name" and type
|
||||
"type" in the Current Scope.
|
||||
*/
|
||||
|
||||
return Enter(name, D_TYPE, type, 0);
|
||||
}
|
||||
|
||||
EnterEnumList(Idlist, type)
|
||||
t_node *Idlist;
|
||||
register t_type *type;
|
||||
{
|
||||
/* Put a list of enumeration literals in the symbol table.
|
||||
They all have type "type".
|
||||
Also assign numbers to them, and link them together.
|
||||
We must link them together because an enumeration type may
|
||||
be exported, in which case its literals must also be exported.
|
||||
Thus, we need an easy way to get to them.
|
||||
*/
|
||||
register t_def *df, *df1 = 0;
|
||||
register t_node *idlist = Idlist;
|
||||
|
||||
type->enm_ncst = 0;
|
||||
for (; idlist; idlist = idlist->nd_NEXT) {
|
||||
df = define(idlist->nd_IDF, CurrentScope, D_ENUM);
|
||||
df->df_type = type;
|
||||
df->enm_val = (type->enm_ncst)++;
|
||||
if (! df1) {
|
||||
type->enm_enums = df;
|
||||
}
|
||||
else df1->enm_next = df;
|
||||
df1 = df;
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterFieldList(Idlist, type, scope, addr)
|
||||
t_node *Idlist;
|
||||
register t_type *type;
|
||||
t_scope *scope;
|
||||
arith *addr;
|
||||
{
|
||||
/* Put a list of fields in the symbol table.
|
||||
They all have type "type", and are put in scope "scope".
|
||||
Mark them as QUALIFIED EXPORT, because that's exactly what
|
||||
fields are, you can get to them by qualifying them.
|
||||
*/
|
||||
register t_def *df;
|
||||
register t_node *idlist = Idlist;
|
||||
|
||||
for (; idlist; idlist = idlist->nd_NEXT) {
|
||||
df = define(idlist->nd_IDF, scope, D_FIELD);
|
||||
df->df_type = type;
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
df->fld_off = align(*addr, type->tp_align);
|
||||
*addr = df->fld_off + type->tp_size;
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterVarList(Idlist, type, local)
|
||||
t_node *Idlist;
|
||||
t_type *type;
|
||||
{
|
||||
/* Enter a list of identifiers representing variables into the
|
||||
name list. "type" represents the type of the variables.
|
||||
"local" is set if the variables are declared local to a
|
||||
procedure.
|
||||
*/
|
||||
register t_def *df;
|
||||
register t_node *idlist = Idlist;
|
||||
register t_scopelist *sc = CurrVis;
|
||||
char buf[256];
|
||||
extern char *sprint();
|
||||
|
||||
if (local) {
|
||||
/* Find the closest enclosing open scope. This
|
||||
is the procedure that we are dealing with
|
||||
*/
|
||||
while (sc->sc_scope->sc_scopeclosed) sc = enclosing(sc);
|
||||
}
|
||||
|
||||
for (; idlist; idlist = idlist->nd_RIGHT) {
|
||||
df = define(idlist->nd_LEFT->nd_IDF, CurrentScope, D_VARIABLE);
|
||||
df->df_type = type;
|
||||
if (idlist->nd_LEFT->nd_NEXT) {
|
||||
/* An address was supplied
|
||||
*/
|
||||
register t_type *tp = idlist->nd_LEFT->nd_NEXT->nd_type;
|
||||
|
||||
df->df_flags |= D_ADDRGIVEN | D_NOREG;
|
||||
if (tp != error_type && !(tp->tp_fund & T_CARDINAL)){
|
||||
node_error(idlist->nd_LEFT->nd_NEXT,
|
||||
"illegal type for address");
|
||||
}
|
||||
df->var_off = idlist->nd_LEFT->nd_NEXT->nd_INT;
|
||||
}
|
||||
else if (local) {
|
||||
/* subtract aligned size of variable to the offset,
|
||||
as the variable list exists only local to a
|
||||
procedure
|
||||
*/
|
||||
sc->sc_scope->sc_off =
|
||||
-WA(align(type->tp_size - sc->sc_scope->sc_off,
|
||||
type->tp_align));
|
||||
df->var_off = sc->sc_scope->sc_off;
|
||||
}
|
||||
else {
|
||||
/* Global name, possibly external
|
||||
*/
|
||||
if (sc->sc_scope->sc_definedby->df_flags & D_FOREIGN) {
|
||||
df->var_name = df->df_idf->id_text;
|
||||
}
|
||||
else {
|
||||
sprint(buf,"%s_%s", sc->sc_scope->sc_name,
|
||||
df->df_idf->id_text);
|
||||
df->var_name = Salloc(buf,
|
||||
(unsigned)(strlen(buf)+1));
|
||||
}
|
||||
df->df_flags |= D_NOREG;
|
||||
|
||||
if (DefinitionModule) {
|
||||
df->df_flags |= D_USED | D_DEFINED;
|
||||
if (sc == Defined->mod_vis) {
|
||||
C_exa_dnam(df->var_name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
C_ina_dnam(df->var_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
EnterParamList(ppr, Idlist, type, VARp, off)
|
||||
t_param **ppr;
|
||||
t_node *Idlist;
|
||||
t_type *type;
|
||||
int VARp;
|
||||
arith *off;
|
||||
{
|
||||
/* Create (part of) a parameterlist of a procedure.
|
||||
"ids" indicates the list of identifiers, "tp" their type, and
|
||||
"VARp" indicates D_VARPAR or D_VALPAR.
|
||||
*/
|
||||
register t_param *pr;
|
||||
register t_def *df;
|
||||
register t_node *idlist = Idlist;
|
||||
t_node *dummy = 0;
|
||||
static t_param *last;
|
||||
|
||||
if (! idlist) {
|
||||
/* Can only happen when a procedure type is defined */
|
||||
dummy = Idlist = idlist = dot2leaf(Name);
|
||||
}
|
||||
for ( ; idlist; idlist = idlist->nd_NEXT) {
|
||||
pr = new_paramlist();
|
||||
pr->par_next = 0;
|
||||
if (!*ppr) *ppr = pr;
|
||||
else last->par_next = pr;
|
||||
last = pr;
|
||||
if (!DefinitionModule && idlist != dummy) {
|
||||
df = define(idlist->nd_IDF, CurrentScope, D_VARIABLE);
|
||||
df->var_off = *off;
|
||||
}
|
||||
else df = new_def();
|
||||
pr->par_def = df;
|
||||
df->df_type = type;
|
||||
df->df_flags |= VARp;
|
||||
|
||||
if (IsConformantArray(type)) {
|
||||
/* we need room for the base address and a descriptor:
|
||||
arr_low and arr_high are set to their offset
|
||||
*/
|
||||
type->arr_low = *off + pointer_size;
|
||||
type->arr_high = *off + pointer_size + word_size;
|
||||
*off += pointer_size + word_size + dword_size;
|
||||
}
|
||||
else if (VARp == D_VARPAR) {
|
||||
*off += pointer_size;
|
||||
}
|
||||
else {
|
||||
*off += WA(type->tp_size);
|
||||
}
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
STATIC t_def *DoImport();
|
||||
|
||||
ImportEffects(idef, scope, flag)
|
||||
register t_def *idef;
|
||||
t_scope *scope;
|
||||
{
|
||||
/* Handle side effects of an import:
|
||||
- a module could have unqualified exports ???
|
||||
- importing an enumeration type also imports literals
|
||||
*/
|
||||
register t_def *df = idef;
|
||||
register t_type *tp;
|
||||
|
||||
while ((df->df_kind & D_IMPORTED) && df->imp_def != df) {
|
||||
/* The second condition could occur on some (erroneous and
|
||||
obscure) input such as:
|
||||
IMPLEMENTATION MODULE Test;
|
||||
FROM X IMPORT XType, XType;
|
||||
END Test.
|
||||
when X does not exist.
|
||||
*/
|
||||
|
||||
df = df->imp_def;
|
||||
}
|
||||
|
||||
tp = BaseType(df->df_type);
|
||||
if (df->df_kind == D_TYPE && tp->tp_fund == T_ENUMERATION) {
|
||||
/* Also import all enumeration literals
|
||||
*/
|
||||
for (df = tp->enm_enums; df; df = df->enm_next) {
|
||||
/* But be careful; we could have a situation where f.i.
|
||||
different subrange types of the enumeration type
|
||||
are imported. If the literal is already imported
|
||||
in some way, don't do it again; we don't want
|
||||
a multiple defined error message here.
|
||||
*/
|
||||
t_def *df1;
|
||||
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
if ((!(df1 = lookup(df->df_idf, scope, D_IMPORT, 0)) ||
|
||||
df1 != df) &&
|
||||
! DoImport(df, scope, flag|D_USED)) assert(0);
|
||||
/* don't complain when not used ... */
|
||||
}
|
||||
idef->df_flags |= D_USED; /* don't complain ... */
|
||||
}
|
||||
else if (df->df_kind == D_MODULE) {
|
||||
if (df->mod_vis == CurrVis) {
|
||||
error("cannot import current module \"%s\"",
|
||||
df->df_idf->id_text);
|
||||
return;
|
||||
}
|
||||
if (df->df_scope == GlobalScope) return;
|
||||
/* Also import all definitions that are exported from this
|
||||
module
|
||||
*/
|
||||
for (df = df->mod_vis->sc_scope->sc_def;
|
||||
df;
|
||||
df = df->df_nextinscope) {
|
||||
if (df->df_flags & D_EXPORTED) {
|
||||
if (!DoImport(df, scope, D_IMP_BY_EXP|D_USED)){
|
||||
assert(0);
|
||||
}
|
||||
/* don't complain when these are not used */
|
||||
}
|
||||
}
|
||||
idef->df_flags |= D_USED; /* don't complain ... */
|
||||
}
|
||||
}
|
||||
|
||||
STATIC t_def *
|
||||
DoImport(df, scope, flag)
|
||||
register t_def *df;
|
||||
t_scope *scope;
|
||||
{
|
||||
/* Definition "df" is imported to scope "scope".
|
||||
*/
|
||||
register t_def *idef = define(df->df_idf, scope, D_IMPORT);
|
||||
|
||||
idef->imp_def = df;
|
||||
idef->df_flags |= flag;
|
||||
ImportEffects(idef, scope, flag);
|
||||
return idef;
|
||||
}
|
||||
|
||||
|
||||
STATIC
|
||||
ForwModule(df, nd)
|
||||
register t_def *df;
|
||||
t_node *nd;
|
||||
{
|
||||
/* An import is done from a not yet defined module "df".
|
||||
We could also end up here for not found DEFINITION MODULES.
|
||||
Create a declaration and a scope for this module.
|
||||
*/
|
||||
register t_scopelist *vis;
|
||||
|
||||
if (df->df_scope != GlobalScope) {
|
||||
df->df_scope = enclosing(CurrVis)->sc_scope;
|
||||
df->df_kind = D_FORWMODULE;
|
||||
}
|
||||
open_scope(CLOSEDSCOPE);
|
||||
vis = CurrVis; /* The new scope, but watch out, it's "sc_encl"
|
||||
field is not set right. It must indicate the
|
||||
enclosing scope, but this must be done AFTER
|
||||
closing this one
|
||||
*/
|
||||
close_scope(0);
|
||||
vis->sc_encl = enclosing(CurrVis);
|
||||
/* Here ! */
|
||||
df->for_vis = vis;
|
||||
df->for_node = nd;
|
||||
}
|
||||
|
||||
STATIC t_def *
|
||||
ForwDef(ids, scope)
|
||||
register t_node *ids;
|
||||
t_scope *scope;
|
||||
{
|
||||
/* Enter a forward definition of "ids" in scope "scope",
|
||||
if it is not already defined.
|
||||
*/
|
||||
register t_def *df;
|
||||
|
||||
if (!(df = lookup(ids->nd_IDF, scope, 0, 0))) {
|
||||
df = define(ids->nd_IDF, scope, D_FORWARD);
|
||||
df->for_node = new_node();
|
||||
*(df->for_node) = *ids;
|
||||
df->for_node->nd_NEXT = 0;
|
||||
}
|
||||
return df;
|
||||
}
|
||||
|
||||
EnterExportList(Idlist, qualified)
|
||||
t_node *Idlist;
|
||||
{
|
||||
/* From the current scope, the list of identifiers "ids" is
|
||||
exported. Note this fact. If the export is not qualified, make
|
||||
all the "ids" visible in the enclosing scope by defining them
|
||||
in this scope as "imported".
|
||||
*/
|
||||
register t_node *idlist = Idlist;
|
||||
register t_def *df, *df1;
|
||||
|
||||
for (;idlist; idlist = idlist->nd_NEXT) {
|
||||
df = lookup(idlist->nd_IDF, CurrentScope, 0, 0);
|
||||
|
||||
if (!df) {
|
||||
/* undefined item in export list
|
||||
*/
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not defined",
|
||||
idlist->nd_IDF->id_text);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (df->df_flags & (D_EXPORTED|D_QEXPORTED)) {
|
||||
node_error(idlist,
|
||||
"multiple occurrences of \"%s\" in export list",
|
||||
idlist->nd_IDF->id_text);
|
||||
continue;
|
||||
}
|
||||
|
||||
df->df_flags |= qualified;
|
||||
if (qualified == D_EXPORTED) {
|
||||
/* Export, but not qualified.
|
||||
Find all imports of the module in which this export
|
||||
occurs, and export the current definition to it
|
||||
*/
|
||||
df1 = CurrentScope->sc_definedby->df_idf->id_def;
|
||||
while (df1) {
|
||||
if ((df1->df_kind & D_IMPORTED) &&
|
||||
df1->imp_def == CurrentScope->sc_definedby) {
|
||||
if (! DoImport(df, df1->df_scope, D_IMP_BY_EXP)) assert(0);
|
||||
}
|
||||
df1 = df1->df_next;
|
||||
}
|
||||
/* Also handle the definition as if the enclosing
|
||||
scope imports it.
|
||||
*/
|
||||
df1 = lookup(idlist->nd_IDF,
|
||||
enclosing(CurrVis)->sc_scope,
|
||||
D_IMPORTED,
|
||||
0);
|
||||
if (df1) {
|
||||
/* It was already defined in the enclosing
|
||||
scope. There are two legal possibilities,
|
||||
which are examined below.
|
||||
*/
|
||||
t_def *df2 = df;
|
||||
|
||||
while (df2->df_kind & D_IMPORTED) {
|
||||
df2 = df2->imp_def;
|
||||
}
|
||||
if (df1->df_kind == D_PROCHEAD &&
|
||||
df2->df_kind == D_PROCEDURE) {
|
||||
df1->df_kind = D_IMPORT;
|
||||
df1->df_flags |= D_IMP_BY_EXP;
|
||||
df1->imp_def = df;
|
||||
continue;
|
||||
}
|
||||
if (df1->df_kind == D_HIDDEN &&
|
||||
df2->df_kind == D_TYPE) {
|
||||
DeclareType(idlist, df1, df2->df_type);
|
||||
df1->df_kind = D_TYPE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (! DoImport(df,enclosing(CurrVis)->sc_scope,D_IMP_BY_EXP)) assert(0);
|
||||
}
|
||||
}
|
||||
FreeNode(Idlist);
|
||||
}
|
||||
|
||||
CheckForImports(df)
|
||||
t_def *df;
|
||||
{
|
||||
/* We have a definition for "df"; check all imports of
|
||||
it for side-effects
|
||||
*/
|
||||
register t_def *df1 = df->df_idf->id_def;
|
||||
|
||||
while (df1) {
|
||||
if (df1->df_kind & D_IMPORTED) {
|
||||
register t_def *df2 = df1->imp_def;
|
||||
|
||||
while (df2->df_kind & D_IMPORTED) df2 = df2->imp_def;
|
||||
if (df2 == df) {
|
||||
ImportEffects(df1, df1->df_scope, 0);
|
||||
}
|
||||
}
|
||||
df1 = df1->df_next;
|
||||
}
|
||||
}
|
||||
|
||||
EnterFromImportList(idlist, FromDef, FromId)
|
||||
register t_node *idlist;
|
||||
register t_def *FromDef;
|
||||
t_node *FromId;
|
||||
{
|
||||
/* Import the list Idlist from the module indicated by Fromdef.
|
||||
*/
|
||||
t_scope *sc;
|
||||
register t_def *df;
|
||||
char *module_name = FromDef->df_idf->id_text;
|
||||
|
||||
switch(FromDef->df_kind) {
|
||||
case D_ERROR:
|
||||
case D_FORWARD:
|
||||
/* The module from which the import was done
|
||||
is not yet declared. I'm not sure if I must
|
||||
accept this, but for the time being I will.
|
||||
We also end up here if some definition module could not
|
||||
be found.
|
||||
???
|
||||
*/
|
||||
ForwModule(FromDef, FromId);
|
||||
/* Fall through */
|
||||
case D_FORWMODULE:
|
||||
EnterImportList(idlist, 1, FromDef->for_vis->sc_scope);
|
||||
return;
|
||||
case D_MODULE:
|
||||
sc = FromDef->mod_vis->sc_scope;
|
||||
if (sc == CurrentScope) {
|
||||
node_error(FromId, "cannot import from current module \"%s\"", module_name);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
node_error(FromId,"identifier \"%s\" does not represent a module",module_name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (; idlist; idlist = idlist->nd_NEXT) {
|
||||
if (! (df = lookup(idlist->nd_IDF, sc, 0, 0))) {
|
||||
if (! is_anon_idf(idlist->nd_IDF)) {
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not declared in module \"%s\"",
|
||||
idlist->nd_IDF->id_text,
|
||||
module_name);
|
||||
}
|
||||
df = define(idlist->nd_IDF,sc,D_ERROR);
|
||||
}
|
||||
else if (! (df->df_flags & (D_EXPORTED|D_QEXPORTED))) {
|
||||
node_error(idlist,
|
||||
"identifier \"%s\" not exported from module \"%s\"",
|
||||
idlist->nd_IDF->id_text,
|
||||
module_name);
|
||||
df->df_flags |= D_QEXPORTED;
|
||||
}
|
||||
if (! DoImport(df, CurrentScope, 0)) assert(0);
|
||||
}
|
||||
|
||||
FreeNode(FromId);
|
||||
}
|
||||
|
||||
EnterImportList(idlist, local, sc)
|
||||
register t_node *idlist;
|
||||
t_scope *sc;
|
||||
{
|
||||
/* Import "idlist" from scope "sc".
|
||||
If the import is not local, definition modules must be read
|
||||
for "idlist".
|
||||
*/
|
||||
extern t_def *GetDefinitionModule();
|
||||
struct f_info f;
|
||||
|
||||
f = file_info;
|
||||
|
||||
for (; idlist; idlist = idlist->nd_NEXT) {
|
||||
if (! DoImport(local ?
|
||||
ForwDef(idlist, sc) :
|
||||
GetDefinitionModule(idlist->nd_IDF, 1),
|
||||
CurrentScope, 0)) assert(0);
|
||||
file_info = f;
|
||||
}
|
||||
}
|
||||
@@ -1,414 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* E R R O R A N D D I A G N O S T I C R O U T I N E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* This file contains the (non-portable) error-message and diagnostic
|
||||
giving functions. Be aware that they are called with a variable
|
||||
number of arguments!
|
||||
*/
|
||||
|
||||
#include "errout.h"
|
||||
#include "debug.h"
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include <system.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
|
||||
#include "strict3rd.h"
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "LLlex.h"
|
||||
#include "main.h"
|
||||
#include "node.h"
|
||||
#include "warning.h"
|
||||
#include "nostrict.h"
|
||||
|
||||
/* error classes */
|
||||
#define ERROR 1
|
||||
#define WARNING 2
|
||||
#define LEXERROR 3
|
||||
#define LEXWARNING 4
|
||||
#define CRASH 5
|
||||
#define FATAL 6
|
||||
#ifdef DEBUG
|
||||
#define VDEBUG 7
|
||||
#endif
|
||||
|
||||
int err_occurred;
|
||||
|
||||
extern char *symbol2str();
|
||||
|
||||
/* There are three general error-message functions:
|
||||
lexerror() lexical and pre-processor error messages
|
||||
error() syntactic and semantic error messages
|
||||
node_error() errors in nodes
|
||||
The difference lies in the place where the file name and line
|
||||
number come from.
|
||||
Lexical errors report from the global variables LineNumber and
|
||||
FileName, node errors get their information from the
|
||||
node, whereas other errors use the information in the token.
|
||||
*/
|
||||
|
||||
#if __STDC__
|
||||
#ifdef DEBUG
|
||||
/*VARARGS*/
|
||||
debug(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(VDEBUG, NULLNODE, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*VARARGS*/
|
||||
error(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(ERROR, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
node_error(t_node *node, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(ERROR, node, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
warning(int class, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(WARNING, NULLNODE, fmt, ap, class);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
node_warning(t_node *node, int class, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(WARNING, node, fmt, ap, class);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
lexerror(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(LEXERROR, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
lexwarning(int class, char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(LEXWARNING, NULLNODE, fmt, ap, class);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
fatal(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(FATAL, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
sys_stop(S_EXIT);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
crash(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
{
|
||||
_error(CRASH, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
#ifdef DEBUG
|
||||
sys_stop(S_ABORT);
|
||||
#else
|
||||
sys_stop(S_EXIT);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#ifdef DEBUG
|
||||
/*VARARGS*/
|
||||
debug(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(VDEBUG, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*VARARGS*/
|
||||
error(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(ERROR, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
node_error(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
t_node *node = va_arg(ap, t_node *);
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(ERROR, node, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
warning(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
int class = va_arg(ap, int);
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(WARNING, NULLNODE, fmt, ap, class);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
node_warning(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
t_node *nd = va_arg(ap, t_node *);
|
||||
int class = va_arg(ap, int);
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(WARNING, nd, fmt, ap, class);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
lexerror(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(LEXERROR, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
lexwarning(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
int class = va_arg(ap, int);
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(LEXWARNING, NULLNODE, fmt, ap, class);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
fatal(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(FATAL, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
sys_stop(S_EXIT);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
crash(va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap);
|
||||
{
|
||||
char *fmt = va_arg(ap, char *);
|
||||
_error(CRASH, NULLNODE, fmt, ap, 0);
|
||||
}
|
||||
va_end(ap);
|
||||
#ifdef DEBUG
|
||||
sys_stop(S_ABORT);
|
||||
#else
|
||||
sys_stop(S_EXIT);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
_error(class, node, fmt, ap, warn_class)
|
||||
int class;
|
||||
t_node *node;
|
||||
char *fmt;
|
||||
register va_list ap;
|
||||
int warn_class;
|
||||
{
|
||||
/* _error attempts to limit the number of error messages
|
||||
for a given line to MAXERR_LINE.
|
||||
*/
|
||||
unsigned int ln = 0;
|
||||
register char *remark = 0;
|
||||
|
||||
/* check visibility of message */
|
||||
if (class == ERROR || class == WARNING) {
|
||||
if (token_nmb < tk_nmb_at_last_syn_err + ERR_SHADOW)
|
||||
/* warning or error message overshadowed */
|
||||
return;
|
||||
}
|
||||
/* Since name and number are gathered from different places
|
||||
depending on the class, we first collect the relevant
|
||||
values and then decide what to print.
|
||||
*/
|
||||
/* preliminaries */
|
||||
switch (class) {
|
||||
case ERROR:
|
||||
case LEXERROR:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
if (C_busy()) C_ms_err();
|
||||
err_occurred = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* the remark */
|
||||
switch (class) {
|
||||
case WARNING:
|
||||
case LEXWARNING:
|
||||
if (! (warn_class & warning_classes)) return;
|
||||
switch(warn_class) {
|
||||
#ifndef STRICT_3RD_ED
|
||||
case W_OLDFASHIONED:
|
||||
remark = "(old-fashioned use)";
|
||||
break;
|
||||
#endif
|
||||
#ifndef NOSTRICT
|
||||
case W_STRICT:
|
||||
remark = "(strict)";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
remark = "(warning)";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CRASH:
|
||||
remark = "CRASH\007";
|
||||
break;
|
||||
case FATAL:
|
||||
remark = "fatal error --";
|
||||
break;
|
||||
#ifdef DEBUG
|
||||
case VDEBUG:
|
||||
remark = "(debug)";
|
||||
break;
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
/* the place */
|
||||
switch (class) {
|
||||
case WARNING:
|
||||
case ERROR:
|
||||
ln = node ? node->nd_lineno : dot.tk_lineno;
|
||||
break;
|
||||
case LEXWARNING:
|
||||
case LEXERROR:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
#ifdef DEBUG
|
||||
case VDEBUG:
|
||||
#endif /* DEBUG */
|
||||
ln = LineNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
if (FileName) fprint(ERROUT, "\"%s\", line %u: ", FileName, ln);
|
||||
|
||||
if (remark) fprint(ERROUT, "%s ", remark);
|
||||
|
||||
doprnt(ERROUT, fmt, ap); /* contents of error */
|
||||
fprint(ERROUT, "\n");
|
||||
}
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* E X P R E S S I O N S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
{
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "idf.h"
|
||||
#include "def.h"
|
||||
#include "node.h"
|
||||
#include "type.h"
|
||||
#include "chk_expr.h"
|
||||
#include "warning.h"
|
||||
|
||||
extern char options[];
|
||||
}
|
||||
|
||||
/* inline, we need room for pdp/11
|
||||
number(t_node **p;) :
|
||||
[
|
||||
%default
|
||||
INTEGER
|
||||
|
|
||||
REAL
|
||||
] { *p = dot2leaf(Value);
|
||||
(*p)->nd_type = toktype;
|
||||
}
|
||||
;
|
||||
*/
|
||||
|
||||
qualident(t_node **p;)
|
||||
{
|
||||
} :
|
||||
IDENT { *p = dot2leaf(Name); }
|
||||
[
|
||||
selector(p)
|
||||
]*
|
||||
;
|
||||
|
||||
selector(register t_node **pnd;)
|
||||
{ t_node *nd;
|
||||
} :
|
||||
'.' { nd = dot2leaf(Select); nd->nd_NEXT = *pnd; *pnd = nd; }
|
||||
IDENT { (*pnd)->nd_IDF = dot.TOK_IDF; }
|
||||
;
|
||||
|
||||
ExpList(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
} :
|
||||
expression(pnd) { *pnd = nd = dot2node(Link,*pnd,NULLNODE);
|
||||
nd->nd_symb = ',';
|
||||
}
|
||||
[
|
||||
',' { nd->nd_RIGHT = dot2leaf(Link);
|
||||
nd = nd->nd_RIGHT;
|
||||
}
|
||||
expression(&(nd->nd_LEFT))
|
||||
]*
|
||||
;
|
||||
|
||||
ConstExpression(register t_node **pnd;)
|
||||
{
|
||||
}:
|
||||
expression(pnd)
|
||||
/*
|
||||
* Changed rule in new Modula-2.
|
||||
* Check that the expression is a constant expression and evaluate!
|
||||
*/
|
||||
{
|
||||
DO_DEBUG(options['C'], print("CONSTANT EXPRESSION\n"));
|
||||
DO_DEBUG(options['C'], PrNode(*pnd, 0));
|
||||
|
||||
if (ChkExpression(pnd) &&
|
||||
(*pnd)->nd_class != Set &&
|
||||
(*pnd)->nd_class != Value &&
|
||||
! (options['l'] && (*pnd)->nd_class == Def && IsProc((*pnd)))) {
|
||||
error("constant expression expected");
|
||||
}
|
||||
|
||||
DO_DEBUG(options['C'], print("RESULTS IN\n"));
|
||||
DO_DEBUG(options['C'], PrNode(*pnd, 0));
|
||||
}
|
||||
;
|
||||
|
||||
expression(register t_node **pnd;)
|
||||
{
|
||||
} :
|
||||
SimpleExpression(pnd)
|
||||
[
|
||||
/* relation */
|
||||
[ '=' | '#' | '<' | LESSEQUAL | '>' | GREATEREQUAL | IN ]
|
||||
{ *pnd = dot2node(Oper, *pnd, NULLNODE); }
|
||||
SimpleExpression(&((*pnd)->nd_RIGHT))
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
/* Inline in expression
|
||||
relation:
|
||||
'=' | '#' | '<' | LESSEQUAL | '>' | GREATEREQUAL | IN
|
||||
;
|
||||
*/
|
||||
|
||||
SimpleExpression(register t_node **pnd;)
|
||||
{
|
||||
register t_node *nd = 0;
|
||||
} :
|
||||
[
|
||||
[ '+' | '-' ]
|
||||
{ nd = dot2leaf(Uoper);
|
||||
/* priority of unary operator ??? */
|
||||
}
|
||||
|
|
||||
]
|
||||
term(pnd)
|
||||
{ if (nd) {
|
||||
nd->nd_RIGHT = *pnd;
|
||||
*pnd = nd;
|
||||
}
|
||||
nd = *pnd;
|
||||
}
|
||||
[
|
||||
/* AddOperator */
|
||||
[ '+' | '-' | OR ]
|
||||
{ nd = dot2node(Oper, nd, NULLNODE); }
|
||||
term(&(nd->nd_RIGHT))
|
||||
]*
|
||||
{ *pnd = nd; }
|
||||
;
|
||||
|
||||
/* Inline in "SimpleExpression"
|
||||
AddOperator:
|
||||
'+' | '-' | OR
|
||||
;
|
||||
*/
|
||||
|
||||
term(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
}:
|
||||
factor(pnd) { nd = *pnd; }
|
||||
[
|
||||
/* MulOperator */
|
||||
[ '*' | '/' | DIV | MOD | AND ]
|
||||
{ nd = dot2node(Oper, nd, NULLNODE); }
|
||||
factor(&(nd->nd_RIGHT))
|
||||
]*
|
||||
{ *pnd = nd; }
|
||||
;
|
||||
|
||||
/* inline in "term"
|
||||
MulOperator:
|
||||
'*' | '/' | DIV | MOD | AND
|
||||
;
|
||||
*/
|
||||
|
||||
factor(register t_node **p;)
|
||||
{
|
||||
register t_node *nd;
|
||||
t_node *nd1;
|
||||
} :
|
||||
qualident(p)
|
||||
[
|
||||
designator_tail(p)
|
||||
[
|
||||
{ *p = dot2node(Call, *p, NULLNODE); }
|
||||
ActualParameters(&((*p)->nd_RIGHT))
|
||||
|
|
||||
]
|
||||
|
|
||||
bare_set(&nd1)
|
||||
{ nd = nd1; nd->nd_LEFT = *p; *p = nd; }
|
||||
]
|
||||
|
|
||||
bare_set(p)
|
||||
| %default
|
||||
[
|
||||
%default
|
||||
INTEGER
|
||||
|
|
||||
REAL
|
||||
|
|
||||
STRING
|
||||
] { *p = dot2leaf(Value);
|
||||
(*p)->nd_type = toktype;
|
||||
}
|
||||
|
|
||||
'(' { nd = dot2leaf(Uoper); }
|
||||
expression(p)
|
||||
{ /* In some cases we must leave the '(' as an unary
|
||||
operator, because otherwise we cannot see that the
|
||||
factor was not a designator
|
||||
*/
|
||||
register int class = (*p)->nd_class;
|
||||
|
||||
if (class == Arrsel ||
|
||||
class == Arrow ||
|
||||
class == Name ||
|
||||
class == Select) {
|
||||
nd->nd_RIGHT = *p;
|
||||
*p = nd;
|
||||
}
|
||||
else FreeNode(nd);
|
||||
}
|
||||
')'
|
||||
|
|
||||
NOT { *p = dot2leaf(Uoper); }
|
||||
factor(&((*p)->nd_RIGHT))
|
||||
;
|
||||
|
||||
bare_set(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
} :
|
||||
'{' { DOT = SET;
|
||||
*pnd = nd = dot2leaf(Xset);
|
||||
nd->nd_type = bitset_type;
|
||||
}
|
||||
[
|
||||
element(nd)
|
||||
[ { nd = nd->nd_RIGHT; }
|
||||
',' element(nd)
|
||||
]*
|
||||
|
|
||||
]
|
||||
'}'
|
||||
;
|
||||
|
||||
ActualParameters(t_node **pnd;):
|
||||
'(' ExpList(pnd)? ')'
|
||||
;
|
||||
|
||||
element(register t_node *nd;) :
|
||||
expression(&(nd->nd_RIGHT))
|
||||
[
|
||||
UPTO
|
||||
{ nd->nd_RIGHT = dot2node(Link, nd->nd_RIGHT, NULLNODE);}
|
||||
expression(&(nd->nd_RIGHT->nd_RIGHT))
|
||||
|
|
||||
]
|
||||
{ nd->nd_RIGHT = dot2node(Link, nd->nd_RIGHT, NULLNODE);
|
||||
nd->nd_RIGHT->nd_symb = ',';
|
||||
}
|
||||
;
|
||||
|
||||
designator(t_node **pnd;)
|
||||
:
|
||||
qualident(pnd)
|
||||
designator_tail(pnd)
|
||||
;
|
||||
|
||||
designator_tail(register t_node **pnd;):
|
||||
visible_designator_tail(pnd)
|
||||
[ %persistent
|
||||
%default
|
||||
selector(pnd)
|
||||
|
|
||||
visible_designator_tail(pnd)
|
||||
]*
|
||||
|
|
||||
;
|
||||
|
||||
visible_designator_tail(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd = *pnd;
|
||||
}:
|
||||
'[' { nd = dot2node(Arrsel, nd, NULLNODE); }
|
||||
expression(&(nd->nd_RIGHT))
|
||||
[
|
||||
','
|
||||
{ nd = dot2node(Arrsel, nd, NULLNODE);
|
||||
}
|
||||
expression(&(nd->nd_RIGHT))
|
||||
]*
|
||||
']'
|
||||
{ *pnd = nd; }
|
||||
|
|
||||
'^' { *pnd = dot2node(Arrow, NULLNODE, nd); }
|
||||
;
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* F I L E D E S C R I P T O R S T R U C T U R E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
struct f_info {
|
||||
unsigned short f_lineno;
|
||||
char *f_filename;
|
||||
char *f_workingdir;
|
||||
};
|
||||
|
||||
extern struct f_info file_info;
|
||||
#define LineNumber file_info.f_lineno
|
||||
#define FileName file_info.f_filename
|
||||
#define WorkingDir file_info.f_workingdir
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* I N S T A N T I A T I O N O F I D F P A C K A G E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "idf.h"
|
||||
#include <idf_pkg.body>
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* U S E R D E C L A R E D P A R T O F I D F */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
struct id_u {
|
||||
int id_res;
|
||||
struct def *id_df;
|
||||
};
|
||||
|
||||
#define IDF_TYPE struct id_u
|
||||
#define id_reserved id_user.id_res
|
||||
#define id_def id_user.id_df
|
||||
|
||||
#include <idf_pkg.spec>
|
||||
|
||||
typedef struct idf t_idf;
|
||||
@@ -1,12 +0,0 @@
|
||||
/* $Header$ */
|
||||
|
||||
#include <alloc.h>
|
||||
|
||||
/* Structure to link idf structures together
|
||||
*/
|
||||
struct id_list {
|
||||
struct id_list *next;
|
||||
struct idf *id_ptr;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "id_list" */
|
||||
@@ -1,20 +0,0 @@
|
||||
static char *RcsId = "$Header$";
|
||||
|
||||
#include "idf.h"
|
||||
#include "idlist.h"
|
||||
|
||||
struct id_list *h_id_list; /* Header of free list */
|
||||
|
||||
/* FreeIdList: take a list of id_list structures and put them
|
||||
on the free list of id_list structures
|
||||
*/
|
||||
FreeIdList(p)
|
||||
struct id_list *p;
|
||||
{
|
||||
register struct id_list *q;
|
||||
|
||||
while (q = p) {
|
||||
p = p->next;
|
||||
free_id_list(q);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* I N S T A N T I A T I O N O F I N P U T P A C K A G E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "f_info.h"
|
||||
struct f_info file_info;
|
||||
#include "input.h"
|
||||
#include <inp_pkg.body>
|
||||
|
||||
|
||||
AtEoIF()
|
||||
{
|
||||
/* Make the unstacking of input streams noticable to the
|
||||
lexical analyzer
|
||||
*/
|
||||
if (WorkingDir[0] != '\0') free(WorkingDir);
|
||||
return 1;
|
||||
}
|
||||
|
||||
AtEoIT()
|
||||
{
|
||||
/* Make the end of the text noticable
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* I N S T A N T I A T I O N O F I N P U T M O D U L E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "inputtype.h"
|
||||
|
||||
#define INP_NPUSHBACK 2
|
||||
#define INP_TYPE struct f_info
|
||||
#define INP_VAR file_info
|
||||
|
||||
#include <inp_pkg.spec>
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* L O O K U P R O U T I N E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include "node.h"
|
||||
#include "type.h"
|
||||
#include "misc.h"
|
||||
|
||||
extern int pass_1;
|
||||
#ifdef DEBUG
|
||||
extern char options[];
|
||||
#endif
|
||||
|
||||
t_def *
|
||||
lookup(id, scope, import, flags)
|
||||
register t_idf *id;
|
||||
t_scope *scope;
|
||||
{
|
||||
/* Look up a definition of an identifier in scope "scope".
|
||||
Make the "def" list self-organizing.
|
||||
Return a pointer to its "def" structure if it exists,
|
||||
otherwise return 0.
|
||||
*/
|
||||
register t_def *df, *df1;
|
||||
|
||||
/* Look in the chain of definitions of this "id" for one with scope
|
||||
"scope".
|
||||
*/
|
||||
for (df = id->id_def, df1 = 0;
|
||||
df && df->df_scope != scope;
|
||||
df1 = df, df = df->df_next) { /* nothing */ }
|
||||
|
||||
if (! df && import && scopeclosed(scope)) {
|
||||
for (df = id->id_def, df1 = 0;
|
||||
df && df->df_scope != PervasiveScope;
|
||||
df1 = df, df = df->df_next) { /* nothing */ }
|
||||
}
|
||||
|
||||
if (df) {
|
||||
/* Found it
|
||||
*/
|
||||
if (df1) {
|
||||
/* Put the definition in front
|
||||
*/
|
||||
df1->df_next = df->df_next;
|
||||
df->df_next = id->id_def;
|
||||
id->id_def = df;
|
||||
}
|
||||
df->df_flags |= flags;
|
||||
while (df->df_kind & import) {
|
||||
assert(df->imp_def != 0);
|
||||
df = df->imp_def;
|
||||
}
|
||||
DO_DEBUG(options['S'], print("lookup %s, %x\n", id->id_text, df->df_kind));
|
||||
}
|
||||
return df;
|
||||
}
|
||||
|
||||
t_def *
|
||||
lookfor(id, vis, message, flags)
|
||||
register t_node *id;
|
||||
register t_scopelist *vis;
|
||||
{
|
||||
/* Look for an identifier in the visibility range started by "vis".
|
||||
If it is not defined create a dummy definition and,
|
||||
if message is set, give an error message
|
||||
*/
|
||||
register t_scopelist *sc;
|
||||
t_scopelist *sc1 = 0;
|
||||
t_def *df;
|
||||
|
||||
for (sc = vis; sc; sc = nextvisible(sc)) {
|
||||
df = lookup(id->nd_IDF, sc->sc_scope, D_IMPORTED, flags);
|
||||
if (df) {
|
||||
if (message && df->df_kind == D_FORWARD) {
|
||||
if (! sc1) sc1 = sc;
|
||||
while (sc && sc->sc_scope != df->df_scope) {
|
||||
sc = enclosing(sc);
|
||||
}
|
||||
if (sc) continue;
|
||||
break;
|
||||
}
|
||||
if (pass_1 && message) {
|
||||
if (sc1) sc = sc1;
|
||||
while (vis->sc_scope->sc_level >
|
||||
sc->sc_scope->sc_level ||
|
||||
(sc1 &&
|
||||
vis->sc_scope->sc_level >=
|
||||
sc->sc_scope->sc_level)) {
|
||||
define( id->nd_IDF,
|
||||
vis->sc_scope,
|
||||
D_INUSE)-> imp_def = df;
|
||||
vis = enclosing(vis);
|
||||
}
|
||||
}
|
||||
return df;
|
||||
}
|
||||
}
|
||||
|
||||
if (message) id_not_declared(id);
|
||||
|
||||
return MkDef(id->nd_IDF, vis->sc_scope, D_ERROR);
|
||||
}
|
||||
@@ -1,288 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* M A I N P R O G R A M */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <system.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <alloc.h>
|
||||
#include <assert.h>
|
||||
#include <stb.h>
|
||||
|
||||
#include "strict3rd.h"
|
||||
#include "dbsymtab.h"
|
||||
#include "input.h"
|
||||
#include "f_info.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "type.h"
|
||||
#include "def.h"
|
||||
#include "scope.h"
|
||||
#include "standards.h"
|
||||
#include "tokenname.h"
|
||||
#include "node.h"
|
||||
#include "warning.h"
|
||||
#include "SYSTEM.h"
|
||||
|
||||
int state; /* either IMPLEMENTATION or PROGRAM */
|
||||
char options[128];
|
||||
int DefinitionModule;
|
||||
char *ProgName;
|
||||
char **DEFPATH;
|
||||
int nDEF = 2, mDEF = 10;
|
||||
int pass_1 = 1;
|
||||
t_def *Defined;
|
||||
extern int err_occurred;
|
||||
extern int fp_used; /* set if floating point used */
|
||||
static t_node _emptystat = { Stat, 0, NULLTYPE, { ';' }};
|
||||
t_node *EmptyStatement = &_emptystat;
|
||||
|
||||
main(argc, argv)
|
||||
register char **argv;
|
||||
{
|
||||
register int Nargc = 1;
|
||||
register char **Nargv = &argv[0];
|
||||
|
||||
ProgName = *argv++;
|
||||
DEFPATH = (char **) Malloc((unsigned)mDEF * sizeof(char *));
|
||||
DEFPATH[1] = 0;
|
||||
|
||||
while (--argc > 0) {
|
||||
if (**argv == '-')
|
||||
DoOption((*argv++) + 1);
|
||||
else
|
||||
Nargv[Nargc++] = *argv++;
|
||||
}
|
||||
Nargv[Nargc] = 0; /* terminate the arg vector */
|
||||
if (Nargc < 2) {
|
||||
fprint(STDERR, "%s: Use a file argument\n", ProgName);
|
||||
sys_stop(S_EXIT);
|
||||
}
|
||||
sys_stop(Compile(Nargv[1], Nargv[2]) ? S_END : S_EXIT);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
Compile(src, dst)
|
||||
char *src, *dst;
|
||||
{
|
||||
extern struct tokenname tkidf[];
|
||||
extern char *getwdir();
|
||||
|
||||
if (! InsertFile(src, (char **) 0, &src)) {
|
||||
fprint(STDERR,"%s: cannot open %s\n", ProgName, src);
|
||||
return 0;
|
||||
}
|
||||
LineNumber = 1;
|
||||
FileName = src;
|
||||
WorkingDir = getwdir(src);
|
||||
C_init(word_size, pointer_size);
|
||||
if (! C_open(dst)) fatal("could not open output file");
|
||||
C_magic();
|
||||
C_ms_emx(word_size, pointer_size);
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) {
|
||||
C_ms_std(FileName, N_SO, 0);
|
||||
}
|
||||
#endif /* DBSYMTAB */
|
||||
init_idf();
|
||||
InitCst();
|
||||
reserve(tkidf);
|
||||
InitScope();
|
||||
InitTypes();
|
||||
AddStandards();
|
||||
#ifdef DEBUG
|
||||
if (options['t']) {
|
||||
LexScan();
|
||||
return 1;
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
open_scope(OPENSCOPE);
|
||||
GlobalVis = CurrVis;
|
||||
close_scope(0);
|
||||
CheckForLineDirective();
|
||||
CompUnit();
|
||||
C_ms_src((int)LineNumber - 1, FileName);
|
||||
if (!err_occurred) {
|
||||
pass_1 = 0;
|
||||
C_exp(Defined->mod_vis->sc_scope->sc_name);
|
||||
WalkModule(Defined);
|
||||
if (fp_used) C_ms_flt();
|
||||
}
|
||||
C_close();
|
||||
#ifdef DEBUG
|
||||
if (options['i']) Info();
|
||||
#endif
|
||||
return ! err_occurred;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
LexScan()
|
||||
{
|
||||
register t_token *tkp = ˙
|
||||
extern char *symbol2str();
|
||||
|
||||
while (LLlex() > 0) {
|
||||
print(">>> %s ", symbol2str(tkp->tk_symb));
|
||||
switch(tkp->tk_symb) {
|
||||
|
||||
case IDENT:
|
||||
print("%s\n", tkp->TOK_IDF->id_text);
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
print("%ld\n", tkp->TOK_INT);
|
||||
break;
|
||||
|
||||
case REAL:
|
||||
print("%s\n", tkp->TOK_RSTR);
|
||||
break;
|
||||
|
||||
case STRING:
|
||||
print("\"%s\"\n", tkp->TOK_STR);
|
||||
break;
|
||||
|
||||
default:
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct stdproc {
|
||||
char *st_nam;
|
||||
int st_con;
|
||||
} stdprocs[] = {
|
||||
{ "ABS", S_ABS },
|
||||
{ "CAP", S_CAP },
|
||||
{ "CHR", S_CHR },
|
||||
{ "FLOAT", S_FLOAT },
|
||||
{ "HIGH", S_HIGH },
|
||||
{ "HALT", S_HALT },
|
||||
{ "EXCL", S_EXCL },
|
||||
{ "DEC", S_DEC },
|
||||
{ "INC", S_INC },
|
||||
{ "VAL", S_VAL },
|
||||
#ifndef STRICT_3RD_ED
|
||||
{ "NEW", S_NEW },
|
||||
{ "DISPOSE", S_DISPOSE },
|
||||
#endif
|
||||
{ "TRUNC", S_TRUNC },
|
||||
{ "SIZE", S_SIZE },
|
||||
{ "ORD", S_ORD },
|
||||
{ "ODD", S_ODD },
|
||||
{ "MAX", S_MAX },
|
||||
{ "MIN", S_MIN },
|
||||
{ "INCL", S_INCL },
|
||||
{ "LONG", S_LONG },
|
||||
{ "SHORT", S_SHORT },
|
||||
{ "TRUNCD", S_TRUNCD },
|
||||
{ "FLOATD", S_FLOATD },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static struct stdproc sysprocs[] = {
|
||||
{ "TSIZE", S_TSIZE },
|
||||
{ "ADR", S_ADR },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
extern t_def *Enter(), *EnterType();
|
||||
|
||||
AddProcs(p)
|
||||
register struct stdproc *p;
|
||||
{
|
||||
for (; p->st_nam != 0; p++) {
|
||||
if (! Enter(p->st_nam, D_PROCEDURE, std_type, p->st_con)) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddStandards()
|
||||
{
|
||||
register t_def *df;
|
||||
static t_token nilconst = { INTEGER, 0};
|
||||
|
||||
AddProcs(stdprocs);
|
||||
EnterType("CHAR", char_type);
|
||||
EnterType("INTEGER", int_type);
|
||||
EnterType("LONGINT", longint_type);
|
||||
EnterType("REAL", real_type);
|
||||
EnterType("LONGREAL", longreal_type);
|
||||
EnterType("CARDINAL", card_type);
|
||||
if (options['l']) {
|
||||
/* local extension: LONGCARD. */
|
||||
EnterType("LONGCARD", longcard_type);
|
||||
}
|
||||
EnterType("(void)", void_type);
|
||||
df = Enter("NIL", D_CONST, address_type, 0);
|
||||
df->con_const = nilconst;
|
||||
|
||||
EnterType("PROC", construct_type(T_PROCEDURE, NULLTYPE));
|
||||
EnterType("BITSET", bitset_type);
|
||||
df = Enter("FALSE", D_ENUM, bool_type, 0);
|
||||
bool_type->enm_enums = df;
|
||||
df->enm_next = Enter("TRUE", D_ENUM, bool_type, 0);
|
||||
df->enm_next->enm_val = 1;
|
||||
assert(df->enm_val == 0 && df->enm_next->enm_next == 0);
|
||||
EnterType("BOOLEAN", bool_type);
|
||||
}
|
||||
|
||||
do_SYSTEM()
|
||||
{
|
||||
/* Simulate the reading of the SYSTEM definition module
|
||||
*/
|
||||
static char systemtext[] = SYSTEMTEXT;
|
||||
|
||||
EnterType("WORD", word_type);
|
||||
EnterType("BYTE", byte_type);
|
||||
EnterType("ADDRESS",address_type);
|
||||
AddProcs(sysprocs);
|
||||
if (!InsertText(systemtext, sizeof(systemtext) - 1)) {
|
||||
fatal("could not insert text");
|
||||
}
|
||||
DefModule();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
int cntlines;
|
||||
|
||||
Info()
|
||||
{
|
||||
extern int cnt_def, cnt_node, cnt_paramlist, cnt_type,
|
||||
cnt_switch_hdr, cnt_case_entry,
|
||||
cnt_scope, cnt_scopelist, cnt_tmpvar;
|
||||
|
||||
print("\
|
||||
%6d def\n%6d node\n%6d paramlist\n%6d type\n%6d switch_hdr\n\
|
||||
%6d case_entry\n%6d scope\n%6d scopelist\n%6d tmpvar\n",
|
||||
cnt_def, cnt_node, cnt_paramlist, cnt_type,
|
||||
cnt_switch_hdr, cnt_case_entry,
|
||||
cnt_scope, cnt_scopelist, cnt_tmpvar);
|
||||
print("\nNumber of lines read: %d\n", cntlines);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
No_Mem()
|
||||
{
|
||||
fatal("out of memory");
|
||||
}
|
||||
|
||||
void
|
||||
C_failed()
|
||||
{
|
||||
fatal("write failed");
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S O M E G L O B A L V A R I A B L E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
extern char options[]; /* indicating which options were given */
|
||||
|
||||
extern int DefinitionModule;
|
||||
/* flag indicating that we are reading a definition
|
||||
module
|
||||
*/
|
||||
|
||||
extern struct def *Defined;
|
||||
/* definition structure of module defined in this
|
||||
compilation
|
||||
*/
|
||||
extern char **DEFPATH; /* search path for DEFINITION MODULE's */
|
||||
extern int mDEF, nDEF;
|
||||
extern int state; /* either IMPLEMENTATION or PROGRAM */
|
||||
@@ -1,26 +0,0 @@
|
||||
sed -e '
|
||||
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;\
|
||||
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), \2))\
|
||||
#endif\
|
||||
#define free_\1(p) st_free(p, \&h_\1, sizeof(struct \1))\
|
||||
:' -e '
|
||||
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), \2, \&cnt_\1))\
|
||||
#else\
|
||||
#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,35 +0,0 @@
|
||||
: Update Files from database
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
|
||||
case $# in
|
||||
1) ;;
|
||||
*) echo use: $0 file >&2
|
||||
exit 1
|
||||
esac
|
||||
|
||||
(
|
||||
IFCOMMAND="if [ -r \$FN ] ;\
|
||||
then if cmp -s \$FN \$TMP;\
|
||||
then rm \$TMP;\
|
||||
else mv \$TMP \$FN;\
|
||||
echo update \$FN;\
|
||||
fi;\
|
||||
else mv \$TMP \$FN;\
|
||||
echo create \$FN;\
|
||||
fi"
|
||||
echo 'TMP=.uf$$'
|
||||
echo 'FN=$TMP'
|
||||
echo 'cat >$TMP <<\!EOF!'
|
||||
sed -n '/^!File:/,${
|
||||
/^$/d
|
||||
/^!File:[ ]*\(.*\)$/s@@!EOF!\
|
||||
'"$IFCOMMAND"'\
|
||||
FN=\1\
|
||||
cat >$TMP <<\\!EOF!@
|
||||
p
|
||||
}' $1
|
||||
echo '!EOF!'
|
||||
echo $IFCOMMAND
|
||||
) |
|
||||
sh
|
||||
@@ -1,7 +0,0 @@
|
||||
echo '#include "debug.h"'
|
||||
sed -n '
|
||||
s:^.*[ ]ALLOCDEF[ ].*"\(.*\)".*$:struct \1 *h_\1 = 0;\
|
||||
#ifdef DEBUG\
|
||||
int cnt_\1 = 0;\
|
||||
#endif:p
|
||||
' $*
|
||||
@@ -1,35 +0,0 @@
|
||||
cat <<'--EOT--'
|
||||
/* Generated by make.tokcase */
|
||||
/* $Id$ */
|
||||
#include "Lpars.h"
|
||||
|
||||
char *
|
||||
symbol2str(tok)
|
||||
int tok;
|
||||
{
|
||||
#define SIZBUF 8
|
||||
/* allow for a few invocations in f.i. an argument list */
|
||||
static char buf[SIZBUF] = { '\'', 0, '\'', 0, '\'', 0, '\'', 0};
|
||||
static int index = 1;
|
||||
|
||||
switch (tok) {
|
||||
--EOT--
|
||||
|
||||
sed '
|
||||
/{[A-Z]/!d
|
||||
s/.*{\(.*\),.*\(".*"\).*$/ case \1 :\
|
||||
return \2;/
|
||||
'
|
||||
|
||||
cat <<'--EOT--'
|
||||
default:
|
||||
if (tok <= 0) return "end of file";
|
||||
if (tok < 040 || tok >= 0177) {
|
||||
return "bad token";
|
||||
}
|
||||
index = (index+4) & (SIZBUF-1);
|
||||
buf[index] = tok;
|
||||
return &buf[index-1];
|
||||
}
|
||||
}
|
||||
--EOT--
|
||||
@@ -1,6 +0,0 @@
|
||||
sed '
|
||||
/{[A-Z]/!d
|
||||
s/.*{//
|
||||
s/,.*//
|
||||
s/.*/%token &;/
|
||||
'
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* M I S C E L L A N E O U S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define is_anon_idf(x) ((x)->id_text[0] == '#')
|
||||
#define id_not_declared(x) (not_declared("identifier", (x), ""))
|
||||
|
||||
extern struct idf
|
||||
*gen_anon_idf();
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* M I S C E L L A N E O U S R O U T I N E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "f_info.h"
|
||||
#include "misc.h"
|
||||
#include "LLlex.h"
|
||||
#include "idf.h"
|
||||
#include "node.h"
|
||||
|
||||
match_id(id1, id2)
|
||||
register t_idf *id1, *id2;
|
||||
{
|
||||
/* Check that identifiers id1 and id2 are equal. If they
|
||||
are not, check that we did'nt generate them in the
|
||||
first place, and if not, give an error message
|
||||
*/
|
||||
if (id1 != id2 && !is_anon_idf(id1) && !is_anon_idf(id2)) {
|
||||
error("name \"%s\" does not match block name \"%s\"",
|
||||
id1->id_text,
|
||||
id2->id_text
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
t_idf *
|
||||
gen_anon_idf()
|
||||
{
|
||||
/* A new idf is created out of nowhere, to serve as an
|
||||
anonymous name.
|
||||
*/
|
||||
static int name_cnt;
|
||||
char *s = Malloc(strlen(FileName)+50);
|
||||
char *sprint();
|
||||
|
||||
sprint(s, "#%d in %s, line %u",
|
||||
++name_cnt, FileName, LineNumber);
|
||||
s = Realloc(s, strlen(s)+1);
|
||||
return str2idf(s, 0);
|
||||
}
|
||||
|
||||
not_declared(what, id, where)
|
||||
char *what, *where;
|
||||
register t_node *id;
|
||||
{
|
||||
/* The identifier "id" is not declared. If it is not generated,
|
||||
give an error message
|
||||
*/
|
||||
if (!is_anon_idf(id->nd_IDF)) {
|
||||
node_error(id,
|
||||
"%s \"%s\" not declared%s",
|
||||
what,
|
||||
id->nd_IDF->id_text,
|
||||
where);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
.TH MODULA\-2 1 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
Modula-2 \- ACK Modula-2 compiler
|
||||
.SH SYNOPSIS
|
||||
\fBack\fR \-m\fImach\fR files
|
||||
.br
|
||||
\fImach\fR files
|
||||
.SH INTRODUCTION
|
||||
This document provides a short introduction to the use of the ACK Modula-2
|
||||
compiler. It also
|
||||
mentions the location of definition modules for "standard" modules.
|
||||
.SH FILENAMES
|
||||
Usually, a Modula-2 program consists of several definition and implementation
|
||||
modules, and one program module.
|
||||
Definition modules must reside in files with names having a ".def" extension.
|
||||
Implementation modules and program modules must reside in files having a
|
||||
".mod" extension.
|
||||
.PP
|
||||
The name of the file in which a definition module is stored must be the same as
|
||||
the module-name, apart from the extension.
|
||||
Also, in most Unix systems filenames are only 14 characters long.
|
||||
So, given an IMPORT declaration for a module called "LongModulName",
|
||||
the compiler will try to open a file called "LongModulN.def".
|
||||
The requirement does not hold for implementation or program modules,
|
||||
but is certainly recommended.
|
||||
.SH CALLING THE COMPILER
|
||||
The easiest way to do this is to let the \fIack\fR(1) program do it.
|
||||
So, to compile a program module "prog.mod", just call
|
||||
.nf
|
||||
\fBack\fR \-m\fImach\fR prog.mod [ objects of implementation modules ]
|
||||
or
|
||||
\fImach\fR prog.mod [ objects of implementation modules ]
|
||||
.fi
|
||||
where \fImach\fR is one of the target machines of ACK.
|
||||
.PP
|
||||
To compile an implementation module, use the \-\fBc\fR flag
|
||||
to produce a ".o" file.
|
||||
Definition modules can not be compiled; the compiler reads them when they are
|
||||
needed.
|
||||
.PP
|
||||
For more details on the \fIack\fR program see \fIack\fR(1).
|
||||
.SH DEFINITION MODULES
|
||||
"Standard" definition modules can be found in
|
||||
the directory \fB~em/lib/m2\fR.
|
||||
.PP
|
||||
When the compiler needs a definition module, it is first searched for
|
||||
in the current directory, then in the directories given to it by the
|
||||
\-\fBI\fR flag
|
||||
in the order given,
|
||||
and then in the directory mentioned above.
|
||||
.SH FLAGS
|
||||
The \fIack\fR(1) program recognizes (among others) the following
|
||||
flags, that are passed to the Modula-2 compiler:
|
||||
.IP \fB\-I\fIdirname\fR
|
||||
.br
|
||||
append \fIdirname\fR to the list of directories where definition modules
|
||||
are looked for.
|
||||
.IP \fB\-I\fP
|
||||
don't look in
|
||||
the directory \fB~em/lib/m2\fR.
|
||||
.IP \fB\-M\fP\fIn\fP
|
||||
set maximum identifier length to \fIn\fR. The minimum value of \fIn\fR
|
||||
is 14, because the keyword "IMPLEMENTATION" is that long.
|
||||
.IP \fB\-n\fR
|
||||
do not generate EM register messages.
|
||||
The user-declared variables will not be stored into registers on the target
|
||||
machine.
|
||||
.IP \fB\-L\fR
|
||||
do not generate the EM \fBfil\fR and \fBlin\fR instructions that enable
|
||||
an interpreter to keep track of the current location in the source code.
|
||||
.IP \fB\-w\fR\fIclasses\fR
|
||||
suppress warning messages whose class is a member of \fIclasses\fR.
|
||||
Currently, there are three classes: \fBO\fR, indicating old-flashioned use,
|
||||
\fBW\fR, indicating "ordinary" warnings, and \fBR\fR, indicating
|
||||
restricted Modula-2.
|
||||
If no \fIclasses\fR are given, all warnings are suppressed.
|
||||
By default, warnings in class \fBO\fR and \fBW\fR are given.
|
||||
.IP \fB\-W\fR\fIclasses\fR
|
||||
allow for warning messages whose class is a member of \fIclasses\fR.
|
||||
.IP \fB\-g\fR
|
||||
produce a DBX-style symbol table.
|
||||
.IP \fB\-x\fR
|
||||
make all procedure names global, so that \fIadb\fR(1) understands them.
|
||||
.IP \fB\-Xs\fR
|
||||
make INTEGER ranges symmetric, t.i., MIN(INTEGER) = - MAX(INTEGER).
|
||||
This is useful for interpreters that use the "real" MIN(INTEGER) to
|
||||
indicate "undefined".
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
\fIack\fR(1), \fIem_m2\fR(6), \fIm2mm(1)\fR
|
||||
.SH FILES
|
||||
.IR ~em/lib/em_m2 :
|
||||
binary of the Modula-2 compiler.
|
||||
.SH DIAGNOSTICS
|
||||
All warning and error messages are written on standard error output.
|
||||
.SH REMARKS
|
||||
Debugging and profiling facilities may be present during the development
|
||||
of \fIem_m2\fP.
|
||||
@@ -1,4 +0,0 @@
|
||||
/* Accepted if many characters of long names are significant */
|
||||
abcdefghijklmnopr() { }
|
||||
abcdefghijklmnopq() { }
|
||||
main() { }
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
struct node {
|
||||
char nd_class; /* kind of node */
|
||||
#define Value 0 /* constant */
|
||||
#define Arrsel 1 /* array selection */
|
||||
#define Oper 2 /* binary operator */
|
||||
#define Uoper 3 /* unary operator */
|
||||
#define Arrow 4 /* ^ construction */
|
||||
#define Call 5 /* cast or procedure - or function call */
|
||||
#define Name 6 /* an identifier */
|
||||
#define Set 7 /* a set constant */
|
||||
#define Xset 8 /* a set */
|
||||
#define Def 9 /* an identified name */
|
||||
#define Stat 10 /* a statement */
|
||||
#define Select 11 /* a '.' selection */
|
||||
#define Link 12
|
||||
/* do NOT change the order or the numbers!!! */
|
||||
char nd_flags; /* options */
|
||||
#define ROPTION 1
|
||||
#define AOPTION 2
|
||||
struct type *nd_type; /* type of this node */
|
||||
struct token nd_token;
|
||||
#define nd_set nd_token.tk_data.tk_set
|
||||
#define nd_def nd_token.tk_data.tk_def
|
||||
#define nd_LEFT nd_token.tk_data.tk_left
|
||||
#define nd_RIGHT nd_token.tk_data.tk_right
|
||||
#define nd_NEXT nd_token.tk_data.tk_next
|
||||
#define nd_symb nd_token.tk_symb
|
||||
#define nd_lineno nd_token.tk_lineno
|
||||
#define nd_IDF nd_token.TOK_IDF
|
||||
#define nd_SSTR nd_token.TOK_SSTR
|
||||
#define nd_STR nd_token.TOK_STR
|
||||
#define nd_SLE nd_token.TOK_SLE
|
||||
#define nd_INT nd_token.TOK_INT
|
||||
#define nd_REAL nd_token.TOK_REAL
|
||||
#define nd_RSTR nd_token.TOK_RSTR
|
||||
#define nd_RVAL nd_token.TOK_RVAL
|
||||
};
|
||||
|
||||
typedef struct node t_node;
|
||||
|
||||
/* ALLOCDEF "node" 50 */
|
||||
|
||||
extern t_node *dot2node(), *dot2leaf(), *getnode();
|
||||
|
||||
#define NULLNODE ((t_node *) 0)
|
||||
|
||||
#define HASSELECTORS 002
|
||||
#define VARIABLE 004
|
||||
#define VALUE 010
|
||||
|
||||
#define IsCast(lnd) ((lnd)->nd_class == Def && is_type((lnd)->nd_def))
|
||||
#define IsProc(lnd) ((lnd)->nd_type->tp_fund == T_PROCEDURE)
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_label.h>
|
||||
#include <em_arith.h>
|
||||
#include <alloc.h>
|
||||
#include <system.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "node.h"
|
||||
#include "main.h"
|
||||
|
||||
static int nsubnodes[] = {
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2
|
||||
};
|
||||
|
||||
t_node *
|
||||
getnode(class)
|
||||
{
|
||||
register t_node *nd = new_node();
|
||||
|
||||
if (options['R']) nd->nd_flags |= ROPTION;
|
||||
if (options['A']) nd->nd_flags |= AOPTION;
|
||||
nd->nd_class = class;
|
||||
return nd;
|
||||
}
|
||||
|
||||
t_node *
|
||||
dot2node(class, left, right)
|
||||
t_node *left, *right;
|
||||
{
|
||||
register t_node *nd = getnode(class);
|
||||
|
||||
nd->nd_symb = dot.tk_symb;
|
||||
nd->nd_lineno = dot.tk_lineno;
|
||||
nd->nd_LEFT = left;
|
||||
nd->nd_RIGHT = right;
|
||||
return nd;
|
||||
}
|
||||
|
||||
t_node *
|
||||
dot2leaf(class)
|
||||
{
|
||||
register t_node *nd = getnode(class);
|
||||
|
||||
nd->nd_token = dot;
|
||||
switch(nsubnodes[class]) {
|
||||
case 1:
|
||||
nd->nd_NEXT = 0;
|
||||
break;
|
||||
case 2:
|
||||
nd->nd_LEFT = 0;
|
||||
nd->nd_RIGHT = 0;
|
||||
break;
|
||||
}
|
||||
return nd;
|
||||
}
|
||||
|
||||
FreeNode(nd)
|
||||
register t_node *nd;
|
||||
{
|
||||
/* Put nodes that are no longer needed back onto the free
|
||||
list
|
||||
*/
|
||||
if (!nd) return;
|
||||
switch(nsubnodes[nd->nd_class]) {
|
||||
case 2:
|
||||
FreeNode(nd->nd_LEFT);
|
||||
FreeNode(nd->nd_RIGHT);
|
||||
break;
|
||||
case 1:
|
||||
FreeNode(nd->nd_NEXT);
|
||||
break;
|
||||
}
|
||||
free_node(nd);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
NodeCrash(expp)
|
||||
t_node *expp;
|
||||
{
|
||||
crash("(NodeCrash) Illegal node");
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
PNodeCrash(expp)
|
||||
t_node **expp;
|
||||
{
|
||||
crash("(PNodeCrash) Illegal node");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
extern char *symbol2str();
|
||||
|
||||
indnt(lvl)
|
||||
{
|
||||
while (lvl--) {
|
||||
print(" ");
|
||||
}
|
||||
}
|
||||
|
||||
printnode(nd, lvl)
|
||||
register t_node *nd;
|
||||
{
|
||||
indnt(lvl);
|
||||
print("Class: %d; Symbol: %s; Flags: %d\n", nd->nd_class, symbol2str(nd->nd_symb), nd->nd_flags);
|
||||
if (nd->nd_type) {
|
||||
indnt(lvl);
|
||||
print("Type: ");
|
||||
DumpType(nd->nd_type);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
PrNode(nd, lvl)
|
||||
register t_node *nd;
|
||||
{
|
||||
if (! nd) {
|
||||
indnt(lvl); print("<nilnode>\n");
|
||||
return;
|
||||
}
|
||||
printnode(nd, lvl);
|
||||
switch(nsubnodes[nd->nd_class]) {
|
||||
case 1:
|
||||
PrNode(nd->nd_LEFT, lvl + 1);
|
||||
PrNode(nd->nd_RIGHT, lvl + 1);
|
||||
break;
|
||||
case 2:
|
||||
PrNode(nd->nd_NEXT, lvl + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
@@ -1,28 +0,0 @@
|
||||
options:
|
||||
|
||||
g: symbol table for debugger
|
||||
l: local extensions enabled
|
||||
n: no register messages
|
||||
s: symmetric range for integers: MIN(INTEGER) = -MAX(INTEGER)
|
||||
w: disable warnings
|
||||
x: make every name global (for ADB)
|
||||
A: extra array bound checks
|
||||
I: look in directory for definition modules
|
||||
L: no FIL/LIN instructions
|
||||
M: maximum identifier length
|
||||
R: runtime checks
|
||||
U: allow underscores in identifiers
|
||||
V: object sizes and alignments
|
||||
W: enable warnings
|
||||
3: strict 3rd edition Modula-2
|
||||
-: to pass debugging options
|
||||
|
||||
Debugging options:
|
||||
|
||||
i: display number of structures allocated and number of lines read
|
||||
t: run lexical analyzer only
|
||||
C: dump of constant expressions
|
||||
F: display size of every file read.
|
||||
S: define/lookup symbol table access dump
|
||||
X: parse-tree dump
|
||||
|
||||
@@ -1,260 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* U S E R O P T I O N - H A N D L I N G */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "idfsize.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <alloc.h>
|
||||
|
||||
#include "strict3rd.h"
|
||||
#include "dbsymtab.h"
|
||||
#include "type.h"
|
||||
#include "main.h"
|
||||
#include "warning.h"
|
||||
#include "nostrict.h"
|
||||
#include "nocross.h"
|
||||
#include "class.h"
|
||||
#include "squeeze.h"
|
||||
|
||||
#define MINIDFSIZE 14
|
||||
|
||||
#if MINIDFSIZE < 14
|
||||
You fouled up! MINIDFSIZE has to be at least 14 or the compiler will not
|
||||
recognize some keywords!
|
||||
#endif
|
||||
|
||||
extern int idfsize;
|
||||
static int ndirs = 1;
|
||||
int warning_classes = W_INITIAL;
|
||||
int gdb_flag;
|
||||
|
||||
DoOption(text)
|
||||
register char *text;
|
||||
{
|
||||
switch(*text++) {
|
||||
|
||||
case '-':
|
||||
options[*text]++; /* debug options etc. */
|
||||
break;
|
||||
|
||||
case 'U': /* allow underscores in identifiers */
|
||||
inidf['_'] = 1;
|
||||
break;
|
||||
case 'L': /* no fil/lin */
|
||||
case 'R': /* no range checks */
|
||||
case 'A': /* extra array bound checks, for machines that do not
|
||||
implement it in AAR/LAR/SAR
|
||||
*/
|
||||
case 'n': /* no register messages */
|
||||
case 'x': /* every name global */
|
||||
case 's': /* symmetric: MIN(INTEGER) = -MAX(INTEGER) */
|
||||
case '3': /* strict 3rd edition Modula-2 */
|
||||
case 'l': /* local additions enabled */
|
||||
options[text[-1]]++;
|
||||
break;
|
||||
|
||||
#ifdef DBSYMTAB
|
||||
case 'g': /* generate symbol table for debugger */
|
||||
options['g']++;
|
||||
if (*text == 'd') {
|
||||
/* Assume -gdb. */
|
||||
gdb_flag = 1;
|
||||
}
|
||||
options['n']++; /* no register vars ??? */
|
||||
break;
|
||||
#endif /* DBSYMTAB */
|
||||
|
||||
case 'w':
|
||||
if (*text) {
|
||||
while (*text) {
|
||||
switch(*text++) {
|
||||
#ifndef STRICT_3RD_ED
|
||||
case 'O':
|
||||
warning_classes &= ~W_OLDFASHIONED;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NOSTRICT
|
||||
case 'R':
|
||||
warning_classes &= ~W_STRICT;
|
||||
break;
|
||||
#endif
|
||||
case 'W':
|
||||
warning_classes &= ~W_ORDINARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else warning_classes = W_ALWAYS;
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
if (*text) {
|
||||
while (*text) {
|
||||
switch(*text++) {
|
||||
#ifndef STRICT_3RD_ED
|
||||
case 'O':
|
||||
warning_classes |= W_OLDFASHIONED;
|
||||
break;
|
||||
#endif
|
||||
#ifndef NOSTRICT
|
||||
case 'R':
|
||||
warning_classes |= W_STRICT;
|
||||
break;
|
||||
#endif
|
||||
case 'W':
|
||||
warning_classes |= W_ORDINARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else warning_classes = W_ALL;
|
||||
break;
|
||||
|
||||
case 'M': { /* maximum identifier length */
|
||||
#ifndef SQUEEZE
|
||||
char *t = text; /* because &text is illegal */
|
||||
|
||||
idfsize = txt2int(&t);
|
||||
if (*t || idfsize <= 0)
|
||||
fatal("malformed -M option");
|
||||
if (idfsize > IDFSIZE) {
|
||||
idfsize = IDFSIZE;
|
||||
warning(W_ORDINARY,"maximum identifier length is %d", IDFSIZE);
|
||||
}
|
||||
if (idfsize < MINIDFSIZE) {
|
||||
warning(W_ORDINARY, "minimum identifier length is %d", MINIDFSIZE);
|
||||
idfsize = MINIDFSIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case 'I' :
|
||||
if (*text) {
|
||||
register int i;
|
||||
register char *new = text;
|
||||
|
||||
if (nDEF > mDEF) {
|
||||
DEFPATH = (char **)
|
||||
Realloc((char *)DEFPATH,(unsigned)(mDEF+=10)*sizeof(char *));
|
||||
}
|
||||
|
||||
for (i = ndirs++; i < nDEF; i++) {
|
||||
char *tmp = DEFPATH[i];
|
||||
|
||||
DEFPATH[i] = new;
|
||||
new = tmp;
|
||||
}
|
||||
++nDEF;
|
||||
}
|
||||
else DEFPATH[ndirs] = 0;
|
||||
break;
|
||||
|
||||
case 'V' : /* set object sizes and alignment requirements */
|
||||
#ifndef NOCROSS
|
||||
{
|
||||
register int size;
|
||||
register int algn;
|
||||
char c;
|
||||
char *t;
|
||||
|
||||
while (c = *text++) {
|
||||
char *strindex();
|
||||
|
||||
t = text;
|
||||
size = txt2int(&t);
|
||||
algn = 0;
|
||||
if (*(text = t) == '.') {
|
||||
t = text + 1;
|
||||
algn = txt2int(&t);
|
||||
text = t;
|
||||
}
|
||||
if (! strindex("wislfdpS", c)) {
|
||||
error("-V: bad type indicator %c\n", c);
|
||||
}
|
||||
if (size != 0) switch (c) {
|
||||
|
||||
case 'w': /* word */
|
||||
word_size = size;
|
||||
dword_size = 2 * size;
|
||||
break;
|
||||
case 'i': /* int */
|
||||
int_size = size;
|
||||
break;
|
||||
case 's': /* short (subranges) */
|
||||
short_size = size;
|
||||
break;
|
||||
case 'l': /* longint */
|
||||
long_size = size;
|
||||
break;
|
||||
case 'f': /* real */
|
||||
float_size = size;
|
||||
break;
|
||||
case 'd': /* longreal */
|
||||
double_size = size;
|
||||
break;
|
||||
case 'p': /* pointer */
|
||||
pointer_size = size;
|
||||
break;
|
||||
}
|
||||
if (algn != 0) switch (c) {
|
||||
|
||||
case 'w': /* word */
|
||||
word_align = algn;
|
||||
break;
|
||||
case 'i': /* int */
|
||||
int_align = algn;
|
||||
break;
|
||||
case 's': /* short (subranges) */
|
||||
short_align = algn;
|
||||
break;
|
||||
case 'l': /* longint */
|
||||
long_align = algn;
|
||||
break;
|
||||
case 'f': /* real */
|
||||
float_align = algn;
|
||||
break;
|
||||
case 'd': /* longreal */
|
||||
double_align = algn;
|
||||
break;
|
||||
case 'p': /* pointer */
|
||||
pointer_align = algn;
|
||||
break;
|
||||
case 'S': /* initial record alignment */
|
||||
struct_align = algn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* NOCROSS */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if (!SQUEEZE) | (!NOCROSS)
|
||||
int
|
||||
txt2int(tp)
|
||||
register char **tp;
|
||||
{
|
||||
/* the integer pointed to by *tp is read, while increasing
|
||||
*tp; the resulting value is yielded.
|
||||
*/
|
||||
register int val = 0;
|
||||
register int ch;
|
||||
|
||||
while (ch = **tp, ch >= '0' && ch <= '9') {
|
||||
val = val * 10 + ch - '0';
|
||||
(*tp)++;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
@@ -1,4 +0,0 @@
|
||||
/* $Header$ */
|
||||
|
||||
#define IDFSIZE 256
|
||||
#define NUMSIZE 256
|
||||
@@ -1,144 +0,0 @@
|
||||
/* P R I N T R O U T I N E S */
|
||||
|
||||
#include <system.h>
|
||||
#include <em_arith.h>
|
||||
|
||||
#define SSIZE 1024 /* string-buffer size for print routines */
|
||||
|
||||
char *long2str();
|
||||
|
||||
doprnt(fp, fmt, argp)
|
||||
File *fp;
|
||||
char *fmt;
|
||||
int argp[];
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(fp, buf, format(buf, fmt, (char *)argp));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
printf(fmt, args)
|
||||
char *fmt;
|
||||
char args;
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(STDOUT, buf, format(buf, fmt, &args));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
fprintf(fp, fmt, args)
|
||||
File *fp;
|
||||
char *fmt;
|
||||
char args;
|
||||
{
|
||||
char buf[SSIZE];
|
||||
|
||||
sys_write(fp, buf, format(buf, fmt, &args));
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
char *
|
||||
sprintf(buf, fmt, args)
|
||||
char *buf, *fmt;
|
||||
char args;
|
||||
{
|
||||
buf[format(buf, fmt, &args)] = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
int
|
||||
format(buf, fmt, argp)
|
||||
char *buf, *fmt;
|
||||
char *argp;
|
||||
{
|
||||
register char *pf = fmt, *pa = argp;
|
||||
register char *pb = buf;
|
||||
|
||||
while (*pf) {
|
||||
if (*pf == '%') {
|
||||
register int width, base, pad, npad;
|
||||
char *arg;
|
||||
char cbuf[2];
|
||||
char *badformat = "<bad format>";
|
||||
|
||||
/* get padder */
|
||||
if (*++pf == '0') {
|
||||
pad = '0';
|
||||
++pf;
|
||||
}
|
||||
else
|
||||
pad = ' ';
|
||||
|
||||
/* get width */
|
||||
width = 0;
|
||||
while (*pf >= '0' && *pf <= '9')
|
||||
width = 10 * width + *pf++ - '0';
|
||||
|
||||
/* get text and move pa */
|
||||
if (*pf == 's') {
|
||||
arg = *(char **)pa;
|
||||
pa += sizeof(char *);
|
||||
}
|
||||
else
|
||||
if (*pf == 'c') {
|
||||
cbuf[0] = * (char *) pa;
|
||||
cbuf[1] = '\0';
|
||||
pa += sizeof(int);
|
||||
arg = &cbuf[0];
|
||||
}
|
||||
else
|
||||
if (*pf == 'l') {
|
||||
/* alignment ??? */
|
||||
if (base = integral(*++pf)) {
|
||||
arg = long2str(*(long *)pa, base);
|
||||
pa += sizeof(long);
|
||||
}
|
||||
else {
|
||||
pf--;
|
||||
arg = badformat;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (base = integral(*pf)) {
|
||||
arg = long2str((long)*(int *)pa, base);
|
||||
pa += sizeof(int);
|
||||
}
|
||||
else
|
||||
if (*pf == '%')
|
||||
arg = "%";
|
||||
else
|
||||
arg = badformat;
|
||||
|
||||
npad = width - strlen(arg);
|
||||
|
||||
while (npad-- > 0)
|
||||
*pb++ = pad;
|
||||
|
||||
while (*pb++ = *arg++);
|
||||
pb--;
|
||||
pf++;
|
||||
}
|
||||
else
|
||||
*pb++ = *pf++;
|
||||
}
|
||||
return pb - buf;
|
||||
}
|
||||
|
||||
integral(c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'b':
|
||||
return -2;
|
||||
case 'd':
|
||||
return 10;
|
||||
case 'o':
|
||||
return -8;
|
||||
case 'u':
|
||||
return -10;
|
||||
case 'x':
|
||||
return -16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,279 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* O V E R A L L S T R U C T U R E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
{
|
||||
#include "debug.h"
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <stb.h>
|
||||
|
||||
#include "dbsymtab.h"
|
||||
#include "strict3rd.h"
|
||||
#include "main.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "scope.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "node.h"
|
||||
#include "f_info.h"
|
||||
#include "warning.h"
|
||||
#include "misc.h"
|
||||
|
||||
extern t_def *GetDefinitionModule();
|
||||
|
||||
}
|
||||
/*
|
||||
The grammar as given by Wirth is already almost LL(1); the
|
||||
main problem is that the full form of a qualified designator
|
||||
may be:
|
||||
[ module_ident '.' ]* IDENT [ '.' field_ident ]*
|
||||
which is quite confusing to an LL(1) parser. Rather than
|
||||
resorting to context-sensitive techniques, I have decided
|
||||
to render this as:
|
||||
IDENT [ '.' IDENT ]*
|
||||
on the grounds that it is quite natural to consider the first
|
||||
IDENT to be the name of the object and regard the others as
|
||||
field identifiers.
|
||||
*/
|
||||
|
||||
%lexical LLlex;
|
||||
|
||||
%start CompUnit, CompilationUnit;
|
||||
%start DefModule, DefinitionModule;
|
||||
|
||||
ModuleDeclaration
|
||||
{
|
||||
register t_def *df;
|
||||
t_node *exportlist;
|
||||
int qualified;
|
||||
} :
|
||||
MODULE IDENT { df = DefineLocalModule(dot.TOK_IDF); }
|
||||
priority(&(df->mod_priority))
|
||||
';'
|
||||
import(1)*
|
||||
export(&qualified, &exportlist)
|
||||
block(&(df->mod_body))
|
||||
IDENT { EnterExportList(exportlist, qualified);
|
||||
close_scope(SC_CHKFORW|SC_CHKPROC|SC_REVERSE);
|
||||
match_id(df->df_idf, dot.TOK_IDF);
|
||||
}
|
||||
;
|
||||
|
||||
priority(register t_node **prio;):
|
||||
[
|
||||
'[' ConstExpression(prio) ']'
|
||||
{ if (! ((*prio)->nd_type->tp_fund & T_CARDINAL)) {
|
||||
node_error(*prio, "illegal priority");
|
||||
}
|
||||
}
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
export(int *QUALflag; t_node **ExportList;):
|
||||
{ *ExportList = 0; *QUALflag = D_EXPORTED; }
|
||||
[
|
||||
EXPORT
|
||||
[
|
||||
QUALIFIED
|
||||
{ *QUALflag = D_QEXPORTED; }
|
||||
|
|
||||
]
|
||||
IdentList(ExportList) ';'
|
||||
|
|
||||
]
|
||||
;
|
||||
|
||||
import(int local;)
|
||||
{
|
||||
t_node *ImportList;
|
||||
register t_node *FromId = 0;
|
||||
register t_def *df;
|
||||
} :
|
||||
/*
|
||||
When parsing a global module, this is the place where we must
|
||||
read already compiled definition modules.
|
||||
If the FROM clause is present, the identifier in it is a module
|
||||
name, otherwise the names in the import list are module names.
|
||||
*/
|
||||
[ FROM
|
||||
IDENT
|
||||
%substart DefinitionModule;
|
||||
{ FromId = dot2leaf(Name);
|
||||
if (local) {
|
||||
df = lookfor(FromId,enclosing(CurrVis),0,D_USED);
|
||||
}
|
||||
else df = GetDefinitionModule(dot.TOK_IDF, 1);
|
||||
}
|
||||
]?
|
||||
IMPORT IdentList(&ImportList) ';'
|
||||
%substart DefinitionModule;
|
||||
{ if (FromId) {
|
||||
EnterFromImportList(ImportList, df, FromId);
|
||||
}
|
||||
else {
|
||||
EnterImportList(ImportList,
|
||||
local,
|
||||
enclosing(CurrVis)->sc_scope);
|
||||
}
|
||||
FreeNode(ImportList);
|
||||
}
|
||||
;
|
||||
|
||||
DefinitionModule
|
||||
{
|
||||
register t_def *df;
|
||||
t_node *exportlist;
|
||||
int dummy;
|
||||
extern t_idf *DefId;
|
||||
extern int ForeignFlag;
|
||||
extern char *sprint();
|
||||
register t_scope *currscope = CurrentScope;
|
||||
char buf[512];
|
||||
} :
|
||||
DEFINITION
|
||||
MODULE IDENT { df = define(dot.TOK_IDF, GlobalScope, D_MODULE);
|
||||
df->df_flags |= D_BUSY | ForeignFlag;
|
||||
currscope->sc_definedby = df;
|
||||
if (DefId &&
|
||||
df->df_idf != DefId &&
|
||||
!is_anon_idf(df->df_idf)) {
|
||||
error("DEFINITION MODULE name is \"%s\", not \"%s\"",
|
||||
df->df_idf->id_text, DefId->id_text);
|
||||
}
|
||||
sprint(buf, "_%s_", df->df_idf->id_text);
|
||||
currscope->sc_name = Salloc(buf, (unsigned) strlen(buf) + 1);
|
||||
df->mod_vis = CurrVis;
|
||||
df->df_type = standard_type(T_RECORD, 1, (arith) 1);
|
||||
df->df_type->rec_scope = currscope;
|
||||
DefinitionModule++;
|
||||
if (!Defined) {
|
||||
Defined = df;
|
||||
}
|
||||
}
|
||||
';'
|
||||
import(0)*
|
||||
export(&dummy, &exportlist)
|
||||
/* New Modula-2 does not have export lists in definition
|
||||
modules. Issue a warning.
|
||||
*/
|
||||
{
|
||||
if (exportlist) {
|
||||
#ifndef STRICT_3RD_ED
|
||||
if (! options['3'])
|
||||
node_warning(exportlist, W_OLDFASHIONED, "export list in definition module ignored");
|
||||
else
|
||||
#endif
|
||||
error("export list not allowed in definition module");
|
||||
FreeNode(exportlist);
|
||||
}
|
||||
}
|
||||
definition* END IDENT
|
||||
{ end_definition_list(&(currscope->sc_def));
|
||||
DefinitionModule--;
|
||||
match_id(dot.TOK_IDF, df->df_idf);
|
||||
df->df_flags &= ~D_BUSY;
|
||||
}
|
||||
'.'
|
||||
;
|
||||
|
||||
definition
|
||||
{
|
||||
register t_def *df;
|
||||
t_def *dummy;
|
||||
} :
|
||||
CONST [ %persistent ConstantDeclaration ';' ]*
|
||||
|
|
||||
TYPE
|
||||
[ %persistent
|
||||
IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE); }
|
||||
[ '=' type(&(df->df_type))
|
||||
{ SolveForwardTypeRefs(df); }
|
||||
| /* empty */
|
||||
/*
|
||||
Here, the exported type has a hidden implementation.
|
||||
The export is said to be opaque.
|
||||
It is restricted to pointer types.
|
||||
*/
|
||||
{ df->df_kind = D_HIDDEN;
|
||||
df->df_type = construct_type(T_HIDDEN, NULLTYPE);
|
||||
}
|
||||
]
|
||||
{
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) stb_string(df, D_TYPE);
|
||||
#endif
|
||||
}
|
||||
';'
|
||||
]*
|
||||
|
|
||||
VAR [ %persistent VariableDeclaration ';' ]*
|
||||
|
|
||||
ProcedureHeading(&dummy, D_PROCHEAD) ';'
|
||||
;
|
||||
|
||||
ProgramModule
|
||||
{
|
||||
register t_def *df;
|
||||
} :
|
||||
MODULE
|
||||
IDENT
|
||||
%substart DefinitionModule;
|
||||
{
|
||||
if (state == IMPLEMENTATION) {
|
||||
int len = strlen(dot.TOK_IDF->id_text);
|
||||
|
||||
if (len > 10) len = 10;
|
||||
if (strncmp(FileName, dot.TOK_IDF->id_text, len)) {
|
||||
warning(W_ORDINARY, "modulename %s does not match filename %s", dot.TOK_IDF->id_text, FileName);
|
||||
}
|
||||
df = GetDefinitionModule(dot.TOK_IDF, 0);
|
||||
CurrVis = df->mod_vis;
|
||||
}
|
||||
else {
|
||||
Defined = df = define(dot.TOK_IDF, GlobalScope, D_MODULE);
|
||||
open_scope(CLOSEDSCOPE);
|
||||
df->mod_vis = CurrVis;
|
||||
CurrentScope->sc_name = "__M2M_";
|
||||
CurrentScope->sc_definedby = df;
|
||||
}
|
||||
}
|
||||
priority(&(df->mod_priority))
|
||||
';' import(0)*
|
||||
block(&(df->mod_body)) IDENT
|
||||
{
|
||||
close_scope(SC_CHKFORW|SC_CHKPROC|SC_REVERSE);
|
||||
match_id(df->df_idf, dot.TOK_IDF);
|
||||
}
|
||||
'.'
|
||||
;
|
||||
|
||||
CompilationUnit:
|
||||
{ error("Compiling a definition module");
|
||||
open_scope(CLOSEDSCOPE);
|
||||
state = DEFINITION;
|
||||
}
|
||||
DefinitionModule
|
||||
{ close_scope(SC_CHKFORW); }
|
||||
| %default
|
||||
[
|
||||
IMPLEMENTATION
|
||||
{ state = IMPLEMENTATION; }
|
||||
|
|
||||
/* empty */
|
||||
{ state = PROGRAM; }
|
||||
]
|
||||
ProgramModule
|
||||
;
|
||||
@@ -1,65 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# C compilation part. Not to be called directly.
|
||||
# Instead, it is to be called by the Makefile.
|
||||
# SRC_DIR, UTIL_HOME, TARGET_HOME, CC, COPTIONS, LINT, LINTOPTIONS, LDOPTIONS,
|
||||
# CC_AND_MKDEP, SUF, LIBSUF should be set here.
|
||||
|
||||
#PARAMS do not remove this line!
|
||||
|
||||
# PRODUCE is either e (readable EM) or k (compact EM)
|
||||
PRODUCE = k
|
||||
|
||||
MDIR = $(TARGET_HOME)/modules
|
||||
LIBDIR = $(MDIR)/lib
|
||||
LINTLIBDIR = $(UTIL_HOME)/modules/lib
|
||||
|
||||
MALLOC = $(LIBDIR)/malloc.$(SUF)
|
||||
|
||||
EMLIB = $(LIBDIR)/libem_mes.$(LIBSUF) \
|
||||
$(LIBDIR)/libem$(PRODUCE).$(LIBSUF) \
|
||||
$(TARGET_HOME)/lib.bin/em_data.$(LIBSUF)
|
||||
|
||||
MODLIB = $(LIBDIR)/libinput.$(LIBSUF) \
|
||||
$(LIBDIR)/libassert.$(LIBSUF) \
|
||||
$(LIBDIR)/liballoc.$(LIBSUF) \
|
||||
$(MALLOC) \
|
||||
$(LIBDIR)/libflt.$(LIBSUF) \
|
||||
$(LIBDIR)/libprint.$(LIBSUF) \
|
||||
$(LIBDIR)/libstring.$(LIBSUF) \
|
||||
$(LIBDIR)/libsystem.$(LIBSUF)
|
||||
|
||||
LIBS = $(EMLIB) $(MODLIB)
|
||||
|
||||
LINTLIBS = $(LINTLIBDIR)/$(LINTPREF)em_mes.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)emk.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)input.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)assert.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)alloc.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)flt.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)print.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)string.$(LINTSUF) \
|
||||
$(LINTLIBDIR)/$(LINTPREF)system.$(LINTSUF)
|
||||
|
||||
PROFILE =
|
||||
INCLUDES = -I. -I$(SRC_DIR) -I$(TARGET_HOME)/modules/h -I$(TARGET_HOME)/h -I$(TARGET_HOME)/modules/pkg
|
||||
CFLAGS = $(PROFILE) $(INCLUDES) $(COPTIONS)
|
||||
LINTFLAGS = $(INCLUDES) $(LINTOPTIONS)
|
||||
LDFLAGS = $(PROFILE) $(LDOPTIONS)
|
||||
|
||||
# C_SRC and OBJ should be set here.
|
||||
#LISTS do not remove this line!
|
||||
|
||||
all: main
|
||||
|
||||
clean:
|
||||
rm -f *.$(SUF) main
|
||||
|
||||
lint:
|
||||
$(LINT) $(LINTFLAGS) $(C_SRC) $(LINTLIBS)
|
||||
|
||||
main: $(OBJ)
|
||||
$(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o main
|
||||
|
||||
# do not remove the next line; it is used for generating dependencies
|
||||
#DEPENDENCIES
|
||||
@@ -1,158 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
# make Modula-2 compiler
|
||||
|
||||
#PARAMS do not remove this line!
|
||||
|
||||
UTIL_BIN = \
|
||||
$(UTIL_HOME)/bin
|
||||
SRC_DIR = \
|
||||
$(SRC_HOME)/lang/m2/comp
|
||||
|
||||
TABGEN= $(UTIL_BIN)/tabgen
|
||||
LLGEN = $(UTIL_BIN)/LLgen
|
||||
LLGENOPTIONS = \
|
||||
-n
|
||||
|
||||
SRC_G = $(SRC_DIR)/program.g $(SRC_DIR)/declar.g \
|
||||
$(SRC_DIR)/expression.g $(SRC_DIR)/statement.g
|
||||
GEN_G = tokenfile.g
|
||||
GFILES= $(GEN_G) $(SRC_G)
|
||||
|
||||
SRC_C = $(SRC_DIR)/LLlex.c $(SRC_DIR)/LLmessage.c $(SRC_DIR)/error.c \
|
||||
$(SRC_DIR)/main.c $(SRC_DIR)/tokenname.c $(SRC_DIR)/idf.c \
|
||||
$(SRC_DIR)/input.c $(SRC_DIR)/type.c $(SRC_DIR)/def.c \
|
||||
$(SRC_DIR)/misc.c $(SRC_DIR)/enter.c $(SRC_DIR)/defmodule.c \
|
||||
$(SRC_DIR)/typequiv.c $(SRC_DIR)/node.c $(SRC_DIR)/cstoper.c \
|
||||
$(SRC_DIR)/chk_expr.c $(SRC_DIR)/options.c $(SRC_DIR)/walk.c \
|
||||
$(SRC_DIR)/desig.c $(SRC_DIR)/code.c $(SRC_DIR)/lookup.c \
|
||||
$(SRC_DIR)/stab.c
|
||||
GEN_C = tokenfile.c program.c declar.c expression.c statement.c \
|
||||
symbol2str.c char.c Lpars.c Lncor.c casestat.c tmpvar.c scope.c next.c
|
||||
CFILES= $(SRC_C) $(GEN_C)
|
||||
|
||||
SRC_H = $(SRC_DIR)/LLlex.h $(SRC_DIR)/chk_expr.h $(SRC_DIR)/class.h \
|
||||
$(SRC_DIR)/debug.h $(SRC_DIR)/desig.h $(SRC_DIR)/f_info.h \
|
||||
$(SRC_DIR)/idf.h $(SRC_DIR)/input.h $(SRC_DIR)/main.h \
|
||||
$(SRC_DIR)/misc.h $(SRC_DIR)/scope.h $(SRC_DIR)/standards.h \
|
||||
$(SRC_DIR)/tokenname.h $(SRC_DIR)/walk.h $(SRC_DIR)/warning.h \
|
||||
$(SRC_DIR)/SYSTEM.h
|
||||
GEN_H = errout.h idfsize.h numsize.h strsize.h target_sizes.h bigresult.h \
|
||||
inputtype.h density.h squeeze.h nocross.h nostrict.h def.h debugcst.h \
|
||||
type.h Lpars.h node.h strict3rd.h real.h use_insert.h dbsymtab.h \
|
||||
uns_arith.h def.h type.h node.h real.h
|
||||
HFILES= $(GEN_H) $(SRC_H)
|
||||
|
||||
NEXTFILES = \
|
||||
$(SRC_DIR)/def.H $(SRC_DIR)/type.H $(SRC_DIR)/node.H $(SRC_DIR)/real.H \
|
||||
$(SRC_DIR)/scope.C $(SRC_DIR)/tmpvar.C $(SRC_DIR)/casestat.C
|
||||
|
||||
all: make.main
|
||||
make -f make.main main
|
||||
|
||||
install: all
|
||||
cp main $(TARGET_HOME)/lib.bin/em_m2
|
||||
if [ $(DO_MACHINE_INDEP) = y ] ; \
|
||||
then mk_manpage $(SRC_DIR)/em_m2.6 $(TARGET_HOME) ; \
|
||||
mk_manpage $(SRC_DIR)/modula-2.1 $(TARGET_HOME) ; \
|
||||
fi
|
||||
|
||||
cmp: all
|
||||
-cmp main $(TARGET_HOME)/lib.bin/em_m2
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
pr:
|
||||
@pr $(SRC_DIR)/proto.make $(SRC_DIR)/proto.main Parameters \
|
||||
$(SRC_DIR)/char.tab $(SRC_G) $(SRC_H) $(NEXTFILES) $(SRC_C)
|
||||
|
||||
lint: make.main
|
||||
make -f make.main lint
|
||||
|
||||
Cfiles: hfiles LLfiles $(GEN_C) $(GEN_H) Makefile
|
||||
echo $(CFILES) | tr ' ' '\012' > Cfiles
|
||||
echo $(HFILES) | tr ' ' '\012' >> Cfiles
|
||||
|
||||
resolved: Cfiles
|
||||
CC="$(CC)" UTIL_HOME="$(UTIL_HOME)" do_resolve `cat Cfiles` > Cfiles.new
|
||||
-if cmp -s Cfiles Cfiles.new ; then rm -f Cfiles.new ; else mv Cfiles.new Cfiles ; fi
|
||||
touch resolved
|
||||
|
||||
# there is no file called "dependencies"; we want dependencies checked
|
||||
# every time. This means that make.main is made every time. Oh well ...
|
||||
# it does not take much time.
|
||||
dependencies: resolved
|
||||
do_deps `grep '.c$$' Cfiles`
|
||||
|
||||
make.main: dependencies make_macros lists $(SRC_DIR)/proto.main
|
||||
rm_deps $(SRC_DIR)/proto.main | sed -e '/^.PARAMS/r make_macros' -e '/^.LISTS/r lists' > make.main
|
||||
cat *.dep >> make.main
|
||||
|
||||
make_macros: Makefile
|
||||
echo 'SRC_DIR=$(SRC_DIR)' > make_macros
|
||||
echo 'UTIL_HOME=$(UTIL_HOME)' >> make_macros
|
||||
echo 'TARGET_HOME=$(TARGET_HOME)' >> make_macros
|
||||
echo 'CC=$(CC)' >> make_macros
|
||||
echo 'COPTIONS=$(COPTIONS)' >> make_macros
|
||||
echo 'LDOPTIONS=$(LDOPTIONS)' >> make_macros
|
||||
echo 'LINT=$(LINT)' >> make_macros
|
||||
echo 'LINTSUF=$(LINTSUF)' >> make_macros
|
||||
echo 'LINTPREF=$(LINTPREF)' >> make_macros
|
||||
echo 'LINTOPTIONS=$(LINTOPTIONS)' >> make_macros
|
||||
echo 'SUF=$(SUF)' >> make_macros
|
||||
echo 'LIBSUF=$(LIBSUF)' >> make_macros
|
||||
echo 'CC_AND_MKDEP=$(CC_AND_MKDEP)' >> make_macros
|
||||
|
||||
lists: Cfiles
|
||||
echo "C_SRC = \\" > lists
|
||||
echo $(CFILES) >> lists
|
||||
echo "OBJ = \\" >> lists
|
||||
echo $(CFILES) | sed -e 's|[^ ]*/||g' -e 's/\.c/.$$(SUF)/g' >> lists
|
||||
|
||||
clean:
|
||||
-make -f make.main clean
|
||||
rm -f $(GEN_C) $(GEN_G) $(GEN_H) hfiles LLfiles Cfiles LL.output
|
||||
rm -f resolved *.dep lists make.main make_macros
|
||||
|
||||
LLfiles: $(GFILES)
|
||||
$(LLGEN) $(LLGENOPTIONS) $(GFILES)
|
||||
@touch LLfiles
|
||||
@if [ -f Lncor.c ] ; then : ; else touch Lncor.c ; fi
|
||||
|
||||
hfiles: Parameters $(SRC_DIR)/make.hfiles
|
||||
$(SRC_DIR)/make.hfiles Parameters
|
||||
touch hfiles
|
||||
|
||||
tokenfile.g: $(SRC_DIR)/tokenname.c $(SRC_DIR)/make.tokfile
|
||||
$(SRC_DIR)/make.tokfile <$(SRC_DIR)/tokenname.c >tokenfile.g
|
||||
|
||||
symbol2str.c: $(SRC_DIR)/tokenname.c $(SRC_DIR)/make.tokcase
|
||||
$(SRC_DIR)/make.tokcase <$(SRC_DIR)/tokenname.c >symbol2str.c
|
||||
|
||||
def.h: $(SRC_DIR)/make.allocd $(SRC_DIR)/def.H
|
||||
$(SRC_DIR)/make.allocd < $(SRC_DIR)/def.H > def.h
|
||||
|
||||
type.h: $(SRC_DIR)/make.allocd $(SRC_DIR)/type.H
|
||||
$(SRC_DIR)/make.allocd < $(SRC_DIR)/type.H > type.h
|
||||
|
||||
real.h: $(SRC_DIR)/make.allocd $(SRC_DIR)/real.H
|
||||
$(SRC_DIR)/make.allocd < $(SRC_DIR)/real.H > real.h
|
||||
|
||||
node.h: $(SRC_DIR)/make.allocd $(SRC_DIR)/node.H
|
||||
$(SRC_DIR)/make.allocd < $(SRC_DIR)/node.H > node.h
|
||||
|
||||
scope.c: $(SRC_DIR)/make.allocd $(SRC_DIR)/scope.C
|
||||
$(SRC_DIR)/make.allocd < $(SRC_DIR)/scope.C > scope.c
|
||||
|
||||
tmpvar.c: $(SRC_DIR)/make.allocd $(SRC_DIR)/tmpvar.C
|
||||
$(SRC_DIR)/make.allocd < $(SRC_DIR)/tmpvar.C > tmpvar.c
|
||||
|
||||
casestat.c: $(SRC_DIR)/make.allocd $(SRC_DIR)/casestat.C
|
||||
$(SRC_DIR)/make.allocd < $(SRC_DIR)/casestat.C > casestat.c
|
||||
|
||||
next.c: $(NEXTFILES) $(SRC_DIR)/make.next
|
||||
$(SRC_DIR)/make.next $(NEXTFILES) > next.c
|
||||
|
||||
char.c: $(SRC_DIR)/char.tab
|
||||
$(TABGEN) -f$(SRC_DIR)/char.tab >char.c
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* R E A L C O N S T A N T D E S C R I P T O R D E F I N I T I O N */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <flt_arith.h>
|
||||
|
||||
struct real {
|
||||
char *r_real;
|
||||
flt_arith r_val;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "real" 20 */
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S C O P E M E C H A N I S M */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include "type.h"
|
||||
#include "def.h"
|
||||
#include "node.h"
|
||||
|
||||
t_scope *PervasiveScope;
|
||||
t_scopelist *CurrVis, *GlobalVis;
|
||||
extern int proclevel;
|
||||
extern char options[];
|
||||
|
||||
/* STATICALLOCDEF "scope" 10 */
|
||||
|
||||
/* STATICALLOCDEF "scopelist" 10 */
|
||||
|
||||
static int sc_count;
|
||||
|
||||
open_scope(scopetype)
|
||||
{
|
||||
/* Open a scope that is either open (automatic imports) or closed.
|
||||
*/
|
||||
register t_scope *sc = new_scope();
|
||||
register t_scopelist *ls = new_scopelist();
|
||||
|
||||
assert(scopetype == OPENSCOPE || scopetype == CLOSEDSCOPE);
|
||||
|
||||
sc->sc_scopeclosed = scopetype == CLOSEDSCOPE;
|
||||
sc->sc_level = proclevel;
|
||||
ls->sc_scope = sc;
|
||||
ls->sc_encl = CurrVis;
|
||||
if (! sc->sc_scopeclosed) {
|
||||
ls->sc_next = ls->sc_encl;
|
||||
}
|
||||
ls->sc_count = sc_count++;
|
||||
CurrVis = ls;
|
||||
}
|
||||
|
||||
t_scope *
|
||||
open_and_close_scope(scopetype)
|
||||
{
|
||||
t_scope *sc;
|
||||
|
||||
open_scope(scopetype);
|
||||
sc = CurrentScope;
|
||||
close_scope(0);
|
||||
return sc;
|
||||
}
|
||||
|
||||
InitScope()
|
||||
{
|
||||
register t_scope *sc = new_scope();
|
||||
register t_scopelist *ls = new_scopelist();
|
||||
|
||||
sc->sc_level = proclevel;
|
||||
PervasiveScope = sc;
|
||||
ls->sc_scope = PervasiveScope;
|
||||
CurrVis = ls;
|
||||
}
|
||||
|
||||
STATIC
|
||||
chk_proc(df)
|
||||
register t_def *df;
|
||||
{
|
||||
/* Called at scope closing. Check all definitions, and if one
|
||||
is a D_PROCHEAD, the procedure was not defined.
|
||||
Also check that hidden types are defined.
|
||||
*/
|
||||
while (df) {
|
||||
if (df->df_kind == D_HIDDEN) {
|
||||
error("hidden type \"%s\" not declared",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
else if (df->df_kind == D_PROCHEAD) {
|
||||
/* A not defined procedure
|
||||
*/
|
||||
error("procedure \"%s\" not defined",
|
||||
df->df_idf->id_text);
|
||||
FreeNode(df->for_node);
|
||||
}
|
||||
df = df->df_nextinscope;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
chk_forw(pdf)
|
||||
t_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.
|
||||
*/
|
||||
register t_def *df;
|
||||
|
||||
while (df = *pdf) {
|
||||
if (df->df_kind == D_FORWTYPE) {
|
||||
pdf = &df->df_nextinscope;
|
||||
ForceForwardTypeDef(df); /* removes df */
|
||||
continue;
|
||||
}
|
||||
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!
|
||||
*/
|
||||
if (scopeclosed(CurrentScope)) {
|
||||
/* Indeed, the scope was a closed
|
||||
scope, so give error message
|
||||
*/
|
||||
node_error(df->for_node, "identifier \"%s\" not declared",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
else {
|
||||
/* This scope was an open scope.
|
||||
Maybe the definitions are in the
|
||||
enclosing scope?
|
||||
*/
|
||||
register t_scopelist *ls =
|
||||
nextvisible(CurrVis);
|
||||
register t_def *df1 = lookup(df->df_idf, ls->sc_scope, 0, 0);
|
||||
|
||||
*pdf = df->df_nextinscope;
|
||||
|
||||
if (! df1) {
|
||||
if (df->df_kind == D_FORWMODULE) {
|
||||
df->for_vis->sc_next = ls;
|
||||
}
|
||||
df->df_nextinscope = ls->sc_scope->sc_def;
|
||||
ls->sc_scope->sc_def = df;
|
||||
df->df_scope = ls->sc_scope;
|
||||
continue;
|
||||
}
|
||||
/* leave it like this ??? */
|
||||
}
|
||||
FreeNode(df->for_node);
|
||||
}
|
||||
pdf = &df->df_nextinscope;
|
||||
}
|
||||
}
|
||||
|
||||
Reverse(pdf)
|
||||
t_def **pdf;
|
||||
{
|
||||
/* Reverse the order in the list of definitions in a scope.
|
||||
This is neccesary because this list is built in reverse.
|
||||
Also, while we're at it, remove uninteresting definitions
|
||||
from this list.
|
||||
*/
|
||||
register t_def *df, *df1;
|
||||
#define INTERESTING (D_MODULE|D_PROCEDURE|D_PROCHEAD|D_VARIABLE|D_IMPORTED|D_TYPE|D_CONST|D_FIELD)
|
||||
|
||||
df = 0;
|
||||
df1 = *pdf;
|
||||
|
||||
while (df1) {
|
||||
if (df1->df_kind & INTERESTING) {
|
||||
t_def *prev = df;
|
||||
|
||||
df = df1;
|
||||
df1 = df1->df_nextinscope;
|
||||
df->df_nextinscope = prev;
|
||||
}
|
||||
else df1 = df1->df_nextinscope;
|
||||
}
|
||||
*pdf = df;
|
||||
}
|
||||
|
||||
close_scope(flag)
|
||||
register int flag;
|
||||
{
|
||||
/* Close a scope. If "flag" is set, check for forward declarations,
|
||||
either POINTER declarations, or EXPORTs, or forward references
|
||||
to MODULES
|
||||
*/
|
||||
register t_scope *sc = CurrentScope;
|
||||
|
||||
assert(sc != 0);
|
||||
|
||||
FreeNode(sc->sc_end);
|
||||
sc->sc_end = dot2leaf(Link);
|
||||
|
||||
if (flag) {
|
||||
DO_DEBUG(options['S'],(print("List of definitions in currently ended scope:\n"), DumpScope(sc->sc_def)));
|
||||
if (flag & SC_CHKPROC) chk_proc(sc->sc_def);
|
||||
if (flag & SC_CHKFORW) chk_forw(&(sc->sc_def));
|
||||
if (flag & SC_REVERSE) Reverse(&(sc->sc_def));
|
||||
}
|
||||
CurrVis = enclosing(CurrVis);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpScope(df)
|
||||
register t_def *df;
|
||||
{
|
||||
while (df) {
|
||||
PrDef(df);
|
||||
df = df->df_nextinscope;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S C O P E M E C H A N I S M */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define OPENSCOPE 0 /* Indicating an open scope */
|
||||
#define CLOSEDSCOPE 1 /* Indicating a closed scope (module) */
|
||||
|
||||
#define SC_CHKFORW 1 /* Check for forward definitions when closing
|
||||
a scope
|
||||
*/
|
||||
#define SC_CHKPROC 2 /* Check for forward procedure definitions
|
||||
when closing a scope
|
||||
*/
|
||||
#define SC_REVERSE 4 /* Reverse list of definitions, to get it
|
||||
back into original order
|
||||
*/
|
||||
|
||||
struct scope {
|
||||
/* struct scope *next; */
|
||||
char *sc_name; /* name of this scope */
|
||||
struct def *sc_def; /* list of definitions in this scope */
|
||||
arith sc_off; /* offsets of variables in this scope */
|
||||
char sc_scopeclosed; /* flag indicating closed or open scope */
|
||||
char sc_defmodule; /* flag set is this scope is from a separate
|
||||
definition module
|
||||
*/
|
||||
int sc_level; /* level of this scope */
|
||||
struct def *sc_definedby; /* The def structure defining this scope */
|
||||
struct node *sc_end; /* node to remember line number of end of scope */
|
||||
};
|
||||
|
||||
struct scopelist {
|
||||
struct scopelist *sc_next;
|
||||
struct scope *sc_scope;
|
||||
struct scopelist *sc_encl;
|
||||
int sc_count;
|
||||
};
|
||||
|
||||
typedef struct scope t_scope;
|
||||
typedef struct scopelist t_scopelist;
|
||||
|
||||
extern t_scope
|
||||
*PervasiveScope;
|
||||
|
||||
extern t_scopelist
|
||||
*CurrVis, *GlobalVis;
|
||||
|
||||
#define CurrentScope (CurrVis->sc_scope)
|
||||
#define GlobalScope (GlobalVis->sc_scope)
|
||||
#define enclosing(x) ((x)->sc_encl)
|
||||
#define scopeclosed(x) ((x)->sc_scopeclosed)
|
||||
#define nextvisible(x) ((x)->sc_next) /* use with scopelists */
|
||||
|
||||
t_scope *open_and_close_scope();
|
||||
@@ -1,447 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* D E B U G G E R S Y M B O L T A B L E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "dbsymtab.h"
|
||||
|
||||
#ifdef DBSYMTAB
|
||||
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <flt_arith.h>
|
||||
#include <stb.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "scope.h"
|
||||
#include "main.h"
|
||||
|
||||
extern int gdb_flag;
|
||||
|
||||
#define INCR_SIZE 64
|
||||
|
||||
extern int proclevel;
|
||||
extern char *sprint();
|
||||
|
||||
static struct db_str {
|
||||
unsigned sz;
|
||||
char *base;
|
||||
char *currpos;
|
||||
} db_str;
|
||||
|
||||
static
|
||||
create_db_str()
|
||||
{
|
||||
if (! db_str.base) {
|
||||
db_str.base = Malloc(INCR_SIZE);
|
||||
db_str.sz = INCR_SIZE;
|
||||
}
|
||||
db_str.currpos = db_str.base;
|
||||
}
|
||||
|
||||
static
|
||||
addc_db_str(c)
|
||||
int c;
|
||||
{
|
||||
int df = db_str.currpos - db_str.base;
|
||||
if (df >= db_str.sz-1) {
|
||||
db_str.sz += INCR_SIZE;
|
||||
db_str.base = Realloc(db_str.base, db_str.sz);
|
||||
db_str.currpos = db_str.base + df;
|
||||
}
|
||||
*db_str.currpos++ = c;
|
||||
*db_str.currpos = '\0';
|
||||
}
|
||||
|
||||
static
|
||||
adds_db_str(s)
|
||||
char *s;
|
||||
{
|
||||
while (*s) addc_db_str(*s++);
|
||||
}
|
||||
|
||||
static
|
||||
stb_type(tp, assign_num)
|
||||
register t_type *tp;
|
||||
{
|
||||
char buf[128];
|
||||
static int stb_count;
|
||||
|
||||
if (tp->tp_dbindex > 0) {
|
||||
adds_db_str(sprint(buf, "%d", tp->tp_dbindex));
|
||||
return;
|
||||
}
|
||||
if (tp->tp_dbindex < 0) {
|
||||
if (tp->tp_next == 0) {
|
||||
adds_db_str(sprint(buf, "%d", -tp->tp_dbindex));
|
||||
return;
|
||||
}
|
||||
tp->tp_dbindex = -tp->tp_dbindex;
|
||||
}
|
||||
if (tp->tp_dbindex == 0 && assign_num) {
|
||||
tp->tp_dbindex = ++stb_count;
|
||||
}
|
||||
if (tp->tp_dbindex > 0) {
|
||||
adds_db_str(sprint(buf, "%d=", tp->tp_dbindex));
|
||||
}
|
||||
if (tp == void_type) {
|
||||
adds_db_str(sprint(buf, "%d", tp->tp_dbindex));
|
||||
return;
|
||||
}
|
||||
switch(tp->tp_fund) {
|
||||
/* simple types ... */
|
||||
case T_INTEGER:
|
||||
adds_db_str(sprint(buf,
|
||||
"r%d;%ld;%ld",
|
||||
tp->tp_dbindex,
|
||||
(long) min_int[(int)tp->tp_size],
|
||||
(long) max_int[(int)tp->tp_size]));
|
||||
break;
|
||||
case T_CARDINAL:
|
||||
adds_db_str(sprint(buf,
|
||||
"r%d;0;-1",
|
||||
tp->tp_dbindex));
|
||||
break;
|
||||
case T_REAL:
|
||||
adds_db_str(sprint(buf,
|
||||
"r%d;%ld;0",
|
||||
tp->tp_dbindex,
|
||||
(long)tp->tp_size));
|
||||
break;
|
||||
case T_CHAR:
|
||||
adds_db_str(sprint(buf,
|
||||
"r%d;0;255",
|
||||
tp->tp_dbindex));
|
||||
break;
|
||||
case T_WORD:
|
||||
if (tp->tp_size == word_size) {
|
||||
adds_db_str(sprint(buf,
|
||||
"r%d;0;-1",
|
||||
tp->tp_dbindex));
|
||||
}
|
||||
else {
|
||||
adds_db_str(sprint(buf,
|
||||
"r%d;0;255",
|
||||
tp->tp_dbindex));
|
||||
}
|
||||
break;
|
||||
|
||||
/* constructed types ... */
|
||||
case T_SUBRANGE:
|
||||
adds_db_str(sprint(buf,
|
||||
"r%d;%ld;%ld",
|
||||
tp->tp_next->tp_dbindex,
|
||||
(long) tp->sub_lb,
|
||||
(long) tp->sub_ub));
|
||||
break;
|
||||
case T_EQUAL:
|
||||
stb_type(tp->tp_next, 0);
|
||||
if (tp->tp_dbindex < 0) tp->tp_dbindex = -tp->tp_dbindex;
|
||||
break;
|
||||
case T_HIDDEN:
|
||||
if (DefinitionModule && CurrVis == Defined->mod_vis) {
|
||||
tp->tp_dbindex = - ++stb_count;
|
||||
adds_db_str(sprint(buf, "%d", -tp->tp_dbindex));
|
||||
}
|
||||
else {
|
||||
/* ??? what to do here??? */
|
||||
addc_db_str('*');
|
||||
stb_type(void_type, 0);
|
||||
/* ??? this certainly is not correct */
|
||||
}
|
||||
break;
|
||||
case T_POINTER:
|
||||
if (tp->tp_next) {
|
||||
addc_db_str('*');
|
||||
stb_type(tp->tp_next, 0);
|
||||
if (tp->tp_dbindex < 0) tp->tp_dbindex = -tp->tp_dbindex;
|
||||
}
|
||||
else {
|
||||
tp->tp_dbindex = - ++stb_count;
|
||||
adds_db_str(sprint(buf, "%d", -tp->tp_dbindex));
|
||||
}
|
||||
break;
|
||||
case T_SET:
|
||||
addc_db_str('S');
|
||||
stb_type(tp->tp_next, 0);
|
||||
adds_db_str(sprint(buf, ";%ld;%ld;", tp->tp_size, tp->set_low));
|
||||
break;
|
||||
case T_ARRAY:
|
||||
addc_db_str('a');
|
||||
if (IsConformantArray(tp)) {
|
||||
addc_db_str('r');
|
||||
stb_type(tp->tp_next, 0);
|
||||
adds_db_str(sprint(buf, ";0;A%ld", tp->arr_high));
|
||||
}
|
||||
else {
|
||||
stb_type(tp->tp_next, 0);
|
||||
}
|
||||
addc_db_str(';');
|
||||
stb_type(tp->arr_elem, 0);
|
||||
break;
|
||||
case T_ENUMERATION:
|
||||
addc_db_str('e');
|
||||
{
|
||||
register struct def *edef = tp->enm_enums;
|
||||
|
||||
while (edef) {
|
||||
adds_db_str(sprint(buf, "%s:%ld,",
|
||||
edef->df_idf->id_text,
|
||||
edef->enm_val));
|
||||
edef = edef->enm_next;
|
||||
}
|
||||
}
|
||||
addc_db_str(';');
|
||||
break;
|
||||
case T_RECORD:
|
||||
adds_db_str(sprint(buf, "s%ld", tp->tp_size));
|
||||
{
|
||||
register struct def *sdef = tp->rec_scope->sc_def;
|
||||
|
||||
while (sdef) {
|
||||
adds_db_str(sdef->df_idf->id_text);
|
||||
addc_db_str(':');
|
||||
stb_type(sdef->df_type, 0);
|
||||
adds_db_str(sprint(buf,
|
||||
",%ld,%ld;",
|
||||
sdef->fld_off*8,
|
||||
sdef->df_type->tp_size*8));
|
||||
sdef = sdef->df_nextinscope;
|
||||
}
|
||||
}
|
||||
addc_db_str(';');
|
||||
break;
|
||||
case T_PROCEDURE:
|
||||
if (gdb_flag) {
|
||||
addc_db_str('f');
|
||||
stb_type(tp->tp_next ? tp->tp_next : void_type, 0);
|
||||
break;
|
||||
}
|
||||
addc_db_str('Q');
|
||||
stb_type(tp->tp_next ? tp->tp_next : void_type, 0);
|
||||
{
|
||||
register struct paramlist *p = tp->prc_params;
|
||||
int paramcount = 0;
|
||||
|
||||
while (p) {
|
||||
paramcount++;
|
||||
p = p->par_next;
|
||||
}
|
||||
adds_db_str(sprint(buf, ",%d;", paramcount));
|
||||
p = tp->prc_params;
|
||||
while (p) {
|
||||
addc_db_str(IsVarParam(p)
|
||||
? 'v'
|
||||
: IsConformantArray(TypeOfParam(p))
|
||||
? 'i'
|
||||
: 'p');
|
||||
stb_type(TypeOfParam(p), 0);
|
||||
addc_db_str(';');
|
||||
p = p->par_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stb_addtp(s, tp)
|
||||
char *s;
|
||||
t_type *tp;
|
||||
{
|
||||
create_db_str();
|
||||
adds_db_str(s);
|
||||
addc_db_str(':');
|
||||
addc_db_str('t');
|
||||
stb_type(tp, 1);
|
||||
addc_db_str(';');
|
||||
C_ms_stb_cst(db_str.base,
|
||||
N_LSYM,
|
||||
tp == void_type || tp->tp_size >= max_int[2]
|
||||
? 0
|
||||
: (int)tp->tp_size,
|
||||
(arith) 0);
|
||||
}
|
||||
|
||||
stb_string(df, kind)
|
||||
register t_def *df;
|
||||
{
|
||||
register t_type *tp = df->df_type;
|
||||
char buf[64];
|
||||
|
||||
create_db_str();
|
||||
adds_db_str(df->df_idf->id_text);
|
||||
addc_db_str(':');
|
||||
switch(kind) {
|
||||
case D_MODULE:
|
||||
if (gdb_flag) {
|
||||
addc_db_str('F');
|
||||
stb_type(void_type, 0);
|
||||
}
|
||||
else {
|
||||
adds_db_str(sprint(buf, "M%d;", df->mod_vis->sc_count));
|
||||
}
|
||||
C_ms_stb_pnam(db_str.base, N_FUN, gdb_flag ? 0 : proclevel, df->mod_vis->sc_scope->sc_name);
|
||||
break;
|
||||
case D_PROCEDURE:
|
||||
if (gdb_flag) {
|
||||
addc_db_str('f');
|
||||
}
|
||||
else adds_db_str(sprint(buf, "Q%d;", df->prc_vis->sc_count));
|
||||
stb_type(tp->tp_next ? tp->tp_next : void_type, 0);
|
||||
if (gdb_flag) {
|
||||
t_scopelist *sc = df->prc_vis;
|
||||
sc = enclosing(sc);
|
||||
while (sc) {
|
||||
t_def *d = sc->sc_scope->sc_definedby;
|
||||
|
||||
if (d && d->df_kind == D_PROCEDURE) {
|
||||
adds_db_str(sprint(buf, ",%s", d->df_idf->id_text));
|
||||
break;
|
||||
}
|
||||
sc = enclosing(sc);
|
||||
}
|
||||
}
|
||||
else addc_db_str(';');
|
||||
C_ms_stb_pnam(db_str.base, N_FUN, gdb_flag ? 0 : proclevel, df->prc_vis->sc_scope->sc_name);
|
||||
break;
|
||||
case D_END:
|
||||
if (gdb_flag) break;
|
||||
adds_db_str(sprint(buf, "E%d;", df->mod_vis->sc_count));
|
||||
C_ms_stb_cst(db_str.base, N_SCOPE, proclevel, (arith) 0);
|
||||
break;
|
||||
case D_PEND:
|
||||
if (gdb_flag) break;
|
||||
adds_db_str(sprint(buf, "E%d;", df->prc_vis->sc_count));
|
||||
C_ms_stb_cst(db_str.base, N_SCOPE, proclevel, (arith) 0);
|
||||
break;
|
||||
case D_VARIABLE:
|
||||
if (DefinitionModule && CurrVis != Defined->mod_vis) break;
|
||||
if (df->df_flags & D_VARPAR) { /* VAR parameter */
|
||||
addc_db_str('v');
|
||||
stb_type(tp, 0);
|
||||
addc_db_str(';');
|
||||
C_ms_stb_cst(db_str.base, N_PSYM, 0, df->var_off);
|
||||
}
|
||||
else if (df->df_flags & D_VALPAR) { /* value parameter */
|
||||
addc_db_str(IsConformantArray(tp)
|
||||
? 'i'
|
||||
: 'p');
|
||||
stb_type(tp, 0);
|
||||
addc_db_str(';');
|
||||
C_ms_stb_cst(db_str.base, N_PSYM, 0, df->var_off);
|
||||
}
|
||||
else if (!proclevel ||
|
||||
(df->df_flags & D_ADDRGIVEN)) { /* global */
|
||||
int knd = N_LCSYM;
|
||||
if (df->df_flags & D_EXPORTED) {
|
||||
knd = N_GSYM;
|
||||
addc_db_str('G');
|
||||
}
|
||||
else {
|
||||
addc_db_str('S');
|
||||
}
|
||||
stb_type(tp, 0);
|
||||
addc_db_str(';');
|
||||
if (df->df_flags & D_ADDRGIVEN) {
|
||||
C_ms_stb_cst(db_str.base, knd, 0, df->var_off);
|
||||
}
|
||||
else {
|
||||
C_ms_stb_dnam(db_str.base, knd, 0, df->var_name, (arith) 0);
|
||||
}
|
||||
}
|
||||
else { /* local variable */
|
||||
stb_type(tp, 1); /* assign type num to avoid
|
||||
difficult to parse string */
|
||||
addc_db_str(';');
|
||||
C_ms_stb_cst(db_str.base, N_LSYM, 0, df->var_off);
|
||||
}
|
||||
break;
|
||||
case D_TYPE:
|
||||
addc_db_str('t');
|
||||
stb_type(tp, 1);
|
||||
addc_db_str(';');
|
||||
C_ms_stb_cst(db_str.base,
|
||||
N_LSYM,
|
||||
tp == void_type || tp->tp_size >= max_int[2]
|
||||
? 0
|
||||
: (int)tp->tp_size,
|
||||
(arith) 0);
|
||||
break;
|
||||
case D_CONST:
|
||||
if (DefinitionModule && CurrVis != Defined->mod_vis) break;
|
||||
addc_db_str('c');
|
||||
addc_db_str('=');
|
||||
tp = BaseType(tp);
|
||||
switch(tp->tp_fund) {
|
||||
case T_INTEGER:
|
||||
case T_INTORCARD:
|
||||
case T_CARDINAL:
|
||||
case T_WORD:
|
||||
case T_POINTER:
|
||||
case T_PROCEDURE:
|
||||
adds_db_str(sprint(buf, "i%ld;", df->con_const.TOK_INT));
|
||||
break;
|
||||
case T_CHAR:
|
||||
adds_db_str(sprint(buf, "c%ld;", df->con_const.TOK_INT));
|
||||
break;
|
||||
case T_REAL:
|
||||
addc_db_str('r');
|
||||
if (! df->con_const.TOK_RSTR) {
|
||||
char buf2[FLT_STRLEN];
|
||||
|
||||
flt_flt2str(&df->con_const.TOK_RVAL, buf2, FLT_STRLEN);
|
||||
adds_db_str(buf2);
|
||||
}
|
||||
else adds_db_str(df->con_const.TOK_RSTR);
|
||||
addc_db_str(';');
|
||||
break;
|
||||
case T_STRING: {
|
||||
register char *p = df->con_const.TOK_STR;
|
||||
|
||||
adds_db_str("s'");
|
||||
while (*p) {
|
||||
if (*p == '\'' || *p == '\\') {
|
||||
addc_db_str('\\');
|
||||
}
|
||||
addc_db_str(*p++);
|
||||
}
|
||||
adds_db_str("';");
|
||||
}
|
||||
break;
|
||||
case T_ENUMERATION:
|
||||
addc_db_str('e');
|
||||
stb_type(tp, 0);
|
||||
adds_db_str(sprint(buf, ",%ld;", df->con_const.TOK_INT));
|
||||
break;
|
||||
case T_SET: {
|
||||
register int i;
|
||||
|
||||
addc_db_str('S');
|
||||
stb_type(tp, 0);
|
||||
for (i = 0; i < tp->tp_size; i++) {
|
||||
adds_db_str(sprint(buf, ",%ld",
|
||||
(df->con_const.tk_data.tk_set[i/(int) word_size] >> (8*(i%(int)word_size)))&0377));
|
||||
}
|
||||
addc_db_str(';');
|
||||
}
|
||||
break;
|
||||
}
|
||||
C_ms_stb_cst(db_str.base,
|
||||
N_LSYM,
|
||||
tp->tp_size < max_int[2] ? (int)tp->tp_size : 0,
|
||||
(arith) 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* DBSYMTAB */
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S T A 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 */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#define S_ABS 1
|
||||
#define S_CAP 2
|
||||
#define S_CHR 3
|
||||
#define S_DEC 4
|
||||
#define S_EXCL 5
|
||||
#define S_FLOAT 6
|
||||
#define S_HALT 7
|
||||
#define S_HIGH 8
|
||||
#define S_INC 9
|
||||
#define S_INCL 10
|
||||
#define S_MAX 11
|
||||
#define S_MIN 12
|
||||
#define S_ODD 13
|
||||
#define S_ORD 14
|
||||
#define S_SIZE 15
|
||||
#define S_TRUNC 16
|
||||
#define S_VAL 17
|
||||
#define S_NEW 18
|
||||
#define S_DISPOSE 19
|
||||
#define S_LONG 20
|
||||
#define S_SHORT 21
|
||||
#define S_TRUNCD 22
|
||||
#define S_FLOATD 23
|
||||
|
||||
/* Standard procedures and functions defined in the SYSTEM module ... */
|
||||
|
||||
#define S_ADR 50
|
||||
#define S_TSIZE 51
|
||||
#define S_NEWPROCESS 52
|
||||
#define S_TRANSFER 53
|
||||
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* S T A T E M E N T S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
{
|
||||
#include <assert.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "scope.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "node.h"
|
||||
|
||||
static int loopcount = 0; /* Count nested loops */
|
||||
extern t_node *EmptyStatement;
|
||||
}
|
||||
|
||||
statement(register t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
extern int return_occurred;
|
||||
} :
|
||||
/*
|
||||
* This part is not in the reference grammar. The reference grammar
|
||||
* states : assignment | ProcedureCall | ...
|
||||
* but this gives LL(1) conflicts
|
||||
*/
|
||||
designator(pnd)
|
||||
[ { nd = dot2node(Stat, *pnd, NULLNODE);
|
||||
nd->nd_symb = '(';
|
||||
nd->nd_lineno = (*pnd)->nd_lineno;
|
||||
}
|
||||
ActualParameters(&(nd->nd_RIGHT))?
|
||||
|
|
||||
[ BECOMES
|
||||
| %erroneous '='
|
||||
{ error("':=' expected instead of '='");
|
||||
DOT = BECOMES;
|
||||
}
|
||||
]
|
||||
{ nd = dot2node(Stat, *pnd, NULLNODE); }
|
||||
expression(&(nd->nd_RIGHT))
|
||||
]
|
||||
{ *pnd = nd; }
|
||||
/*
|
||||
* end of changed part
|
||||
*/
|
||||
|
|
||||
IfStatement(pnd)
|
||||
|
|
||||
CaseStatement(pnd)
|
||||
|
|
||||
WHILE { *pnd = nd = dot2leaf(Stat); }
|
||||
expression(&(nd->nd_LEFT))
|
||||
DO
|
||||
StatementSequence(&(nd->nd_RIGHT))
|
||||
END
|
||||
|
|
||||
REPEAT { *pnd = nd = dot2leaf(Stat); }
|
||||
StatementSequence(&(nd->nd_LEFT))
|
||||
UNTIL
|
||||
expression(&(nd->nd_RIGHT))
|
||||
|
|
||||
{ loopcount++; }
|
||||
LOOP { *pnd = nd = dot2leaf(Stat); }
|
||||
StatementSequence(&((*pnd)->nd_RIGHT))
|
||||
END
|
||||
{ loopcount--; }
|
||||
|
|
||||
ForStatement(pnd)
|
||||
|
|
||||
WITH { *pnd = nd = dot2leaf(Stat); }
|
||||
designator(&(nd->nd_LEFT))
|
||||
DO
|
||||
StatementSequence(&(nd->nd_RIGHT))
|
||||
END
|
||||
|
|
||||
EXIT
|
||||
{ if (!loopcount) error("EXIT not in a LOOP");
|
||||
*pnd = dot2leaf(Stat);
|
||||
}
|
||||
|
|
||||
ReturnStatement(pnd)
|
||||
{ return_occurred = 1; }
|
||||
|
|
||||
/* empty */ { *pnd = EmptyStatement; }
|
||||
;
|
||||
|
||||
/*
|
||||
* The next two rules in-line in "Statement", because of an LL(1) conflict
|
||||
|
||||
assignment:
|
||||
designator BECOMES expression
|
||||
;
|
||||
|
||||
ProcedureCall:
|
||||
designator ActualParameters?
|
||||
;
|
||||
*/
|
||||
|
||||
StatementSequence(register t_node **pnd;)
|
||||
{
|
||||
t_node *nd;
|
||||
register t_node *nd1;
|
||||
} :
|
||||
statement(pnd)
|
||||
[ %persistent
|
||||
';'
|
||||
statement(&nd)
|
||||
{ if (nd != EmptyStatement) {
|
||||
nd1 = dot2node(Link, *pnd, nd);
|
||||
*pnd = nd1;
|
||||
nd1->nd_symb = ';';
|
||||
pnd = &(nd1->nd_RIGHT);
|
||||
}
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
IfStatement(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
} :
|
||||
IF { nd = dot2leaf(Stat);
|
||||
*pnd = nd;
|
||||
}
|
||||
expression(&(nd->nd_LEFT))
|
||||
THEN { nd->nd_RIGHT = dot2leaf(Link);
|
||||
nd = nd->nd_RIGHT;
|
||||
}
|
||||
StatementSequence(&(nd->nd_LEFT))
|
||||
[
|
||||
ELSIF { nd->nd_RIGHT = dot2leaf(Stat);
|
||||
nd = nd->nd_RIGHT;
|
||||
nd->nd_symb = IF;
|
||||
}
|
||||
expression(&(nd->nd_LEFT))
|
||||
THEN { nd->nd_RIGHT = dot2leaf(Link);
|
||||
nd = nd->nd_RIGHT;
|
||||
}
|
||||
StatementSequence(&(nd->nd_LEFT))
|
||||
]*
|
||||
[
|
||||
ELSE
|
||||
StatementSequence(&(nd->nd_RIGHT))
|
||||
|
|
||||
]
|
||||
END
|
||||
;
|
||||
|
||||
CaseStatement(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
t_type *tp = 0;
|
||||
} :
|
||||
CASE { *pnd = nd = dot2leaf(Stat); }
|
||||
expression(&(nd->nd_LEFT))
|
||||
OF
|
||||
case(&(nd->nd_RIGHT), &tp)
|
||||
{ nd = nd->nd_RIGHT; }
|
||||
[
|
||||
'|'
|
||||
case(&(nd->nd_RIGHT), &tp)
|
||||
{ nd = nd->nd_RIGHT; }
|
||||
]*
|
||||
[ ELSE StatementSequence(&(nd->nd_RIGHT))
|
||||
|
|
||||
]
|
||||
END
|
||||
;
|
||||
|
||||
case(t_node **pnd; t_type **ptp;) :
|
||||
[ CaseLabelList(ptp, pnd)
|
||||
':' { *pnd = dot2node(Link, *pnd, NULLNODE); }
|
||||
StatementSequence(&((*pnd)->nd_RIGHT))
|
||||
|
|
||||
]
|
||||
{ *pnd = dot2node(Link, *pnd, NULLNODE);
|
||||
(*pnd)->nd_symb = '|';
|
||||
}
|
||||
;
|
||||
|
||||
/* inline in statement; lack of space
|
||||
WhileStatement(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
}:
|
||||
WHILE { *pnd = nd = dot2leaf(Stat); }
|
||||
expression(&(nd->nd_LEFT))
|
||||
DO
|
||||
StatementSequence(&(nd->nd_RIGHT))
|
||||
END
|
||||
;
|
||||
|
||||
RepeatStatement(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
}:
|
||||
REPEAT { *pnd = nd = dot2leaf(Stat); }
|
||||
StatementSequence(&(nd->nd_LEFT))
|
||||
UNTIL
|
||||
expression(&(nd->nd_RIGHT))
|
||||
;
|
||||
*/
|
||||
|
||||
ForStatement(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd, *nd1;
|
||||
}:
|
||||
FOR { *pnd = nd = dot2leaf(Stat); }
|
||||
IDENT { nd1 = dot2leaf(Name); }
|
||||
BECOMES { nd->nd_LEFT = dot2node(Stat, nd1, dot2leaf(Link));
|
||||
nd1 = nd->nd_LEFT->nd_RIGHT;
|
||||
nd1->nd_symb = TO;
|
||||
}
|
||||
expression(&(nd1->nd_LEFT))
|
||||
TO
|
||||
expression(&(nd1->nd_RIGHT))
|
||||
{ nd->nd_RIGHT = nd1 = dot2leaf(Link);
|
||||
nd1->nd_symb = BY;
|
||||
}
|
||||
[
|
||||
BY
|
||||
ConstExpression(&(nd1->nd_LEFT))
|
||||
{ if (!(nd1->nd_LEFT->nd_type->tp_fund & T_INTORCARD)) {
|
||||
error("illegal type in BY clause");
|
||||
}
|
||||
}
|
||||
|
|
||||
{ nd1->nd_LEFT = dot2leaf(Value);
|
||||
nd1->nd_LEFT->nd_INT = 1;
|
||||
}
|
||||
]
|
||||
DO
|
||||
StatementSequence(&(nd1->nd_RIGHT))
|
||||
END
|
||||
;
|
||||
|
||||
/* inline in Statement; lack of space
|
||||
LoopStatement(t_node **pnd;):
|
||||
LOOP { *pnd = dot2leaf(Stat); }
|
||||
StatementSequence(&((*pnd)->nd_RIGHT))
|
||||
END
|
||||
;
|
||||
|
||||
WithStatement(t_node **pnd;)
|
||||
{
|
||||
register t_node *nd;
|
||||
}:
|
||||
WITH { *pnd = nd = dot2leaf(Stat); }
|
||||
designator(&(nd->nd_LEFT))
|
||||
DO
|
||||
StatementSequence(&(nd->nd_RIGHT))
|
||||
END
|
||||
;
|
||||
*/
|
||||
|
||||
ReturnStatement(t_node **pnd;)
|
||||
{
|
||||
register t_def *df = CurrentScope->sc_definedby;
|
||||
register t_type *tp = df->df_type ? ResultType(df->df_type) : 0;
|
||||
register t_node *nd;
|
||||
} :
|
||||
|
||||
RETURN { *pnd = nd = dot2leaf(Stat); }
|
||||
[
|
||||
expression(&(nd->nd_RIGHT))
|
||||
{ if (scopeclosed(CurrentScope)) {
|
||||
error("a module body cannot return a value");
|
||||
}
|
||||
else if (! tp) {
|
||||
error("procedure \"%s\" is not a function, so cannot return a value", df->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
|
|
||||
{ if (tp) {
|
||||
error("function procedure \"%s\" must return a value", df->df_idf->id_text);
|
||||
}
|
||||
}
|
||||
]
|
||||
;
|
||||
@@ -1,295 +0,0 @@
|
||||
/* @cc tab.c -o $INSTALLDIR/tab@
|
||||
tab - table generator
|
||||
|
||||
Author: Erik Baalbergen (..tjalk!erikb)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static char *RcsId = "$Header$";
|
||||
|
||||
#define MAXTAB 10000
|
||||
#define MAXBUF 10000
|
||||
#define COMCOM '-'
|
||||
#define FILECOM '%'
|
||||
|
||||
int InputForm = 'c';
|
||||
char OutputForm[MAXBUF] = "%s,\n";
|
||||
int TabSize = 257;
|
||||
char *Table[MAXTAB];
|
||||
char *Name;
|
||||
char *ProgCall;
|
||||
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
ProgCall = *argv++;
|
||||
argc--;
|
||||
while (argc-- > 0) {
|
||||
if (**argv == COMCOM) {
|
||||
option(*argv++);
|
||||
}
|
||||
else {
|
||||
process(*argv++, InputForm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
Salloc(s)
|
||||
char *s;
|
||||
{
|
||||
char *malloc();
|
||||
char *ns = malloc(strlen(s) + 1);
|
||||
|
||||
if (ns) {
|
||||
strcpy(ns, s);
|
||||
}
|
||||
return ns;
|
||||
}
|
||||
|
||||
option(str)
|
||||
char *str;
|
||||
{
|
||||
/* note that *str indicates the source of the option:
|
||||
either COMCOM (from command line) or FILECOM (from a file).
|
||||
*/
|
||||
switch (*++str) {
|
||||
|
||||
case ' ': /* command */
|
||||
case '\t':
|
||||
case '\0':
|
||||
break;
|
||||
case 'I':
|
||||
InputForm = *++str;
|
||||
break;
|
||||
case 'f':
|
||||
if (*++str == '\0') {
|
||||
fprintf(stderr, "%s: -f: name expected\n", ProgCall);
|
||||
exit(1);
|
||||
}
|
||||
DoFile(str);
|
||||
break;
|
||||
case 'F':
|
||||
sprintf(OutputForm, "%s\n", ++str);
|
||||
break;
|
||||
case 'T':
|
||||
printf("%s\n", ++str);
|
||||
break;
|
||||
case 'p':
|
||||
PrintTable();
|
||||
break;
|
||||
case 'C':
|
||||
ClearTable();
|
||||
break;
|
||||
case 'S':
|
||||
{
|
||||
register i = stoi(++str);
|
||||
|
||||
if (i <= 0 || i > MAXTAB) {
|
||||
fprintf(stderr, "%s: size would exceed maximum\n",
|
||||
ProgCall);
|
||||
}
|
||||
else {
|
||||
TabSize = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "%s: bad option -%s\n", ProgCall, str);
|
||||
}
|
||||
}
|
||||
|
||||
ClearTable()
|
||||
{
|
||||
register i;
|
||||
|
||||
for (i = 0; i < MAXTAB; i++) {
|
||||
Table[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PrintTable()
|
||||
{
|
||||
register i;
|
||||
|
||||
for (i = 0; i < TabSize; i++) {
|
||||
if (Table[i]) {
|
||||
printf(OutputForm, Table[i]);
|
||||
}
|
||||
else {
|
||||
printf(OutputForm, "0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
process(str, format)
|
||||
char *str;
|
||||
{
|
||||
char *cstr = str;
|
||||
char *Name = cstr; /* overwrite original string! */
|
||||
|
||||
/* strip of the entry name
|
||||
*/
|
||||
while (*str && *str != ':') {
|
||||
if (*str == '\\') {
|
||||
++str;
|
||||
}
|
||||
*cstr++ = *str++;
|
||||
}
|
||||
|
||||
if (*str != ':') {
|
||||
fprintf(stderr, "%s: bad specification: \"%s\", ignored\n",
|
||||
ProgCall, Name);
|
||||
return 0;
|
||||
}
|
||||
*cstr = '\0';
|
||||
str++;
|
||||
|
||||
switch (format) {
|
||||
|
||||
case 'c':
|
||||
return c_proc(str, Name);
|
||||
default:
|
||||
fprintf(stderr, "%s: bad input format\n", ProgCall);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
c_proc(str, Name)
|
||||
char *str;
|
||||
char *Name;
|
||||
{
|
||||
int ch, ch2;
|
||||
int quoted();
|
||||
|
||||
while (*str) {
|
||||
if (*str == '\\') {
|
||||
ch = quoted(&str);
|
||||
}
|
||||
else {
|
||||
ch = *str++;
|
||||
}
|
||||
if (*str == '-') {
|
||||
if (*++str == '\\') {
|
||||
ch2 = quoted(&str);
|
||||
}
|
||||
else {
|
||||
if (ch2 = *str++);
|
||||
else str--;
|
||||
}
|
||||
if (ch > ch2) {
|
||||
fprintf(stderr, "%s: bad range\n", ProgCall);
|
||||
return 0;
|
||||
}
|
||||
if (ch >= 0 && ch2 <= 255)
|
||||
while (ch <= ch2)
|
||||
Table[ch++] = Salloc(Name);
|
||||
}
|
||||
else {
|
||||
if (ch >= 0 && ch <= 255)
|
||||
Table[ch] = Salloc(Name);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
quoted(pstr)
|
||||
char **pstr;
|
||||
{
|
||||
register int ch;
|
||||
register int i;
|
||||
register char *str = *pstr;
|
||||
|
||||
if ((*++str >= '0') && (*str <= '9')) {
|
||||
ch = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
ch = 8 * ch + *str - '0';
|
||||
if (*++str < '0' || *str > '9')
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (*str++) {
|
||||
|
||||
case 'n':
|
||||
ch = '\n';
|
||||
break;
|
||||
case 't':
|
||||
ch = '\t';
|
||||
break;
|
||||
case 'b':
|
||||
ch = '\b';
|
||||
break;
|
||||
case 'r':
|
||||
ch = '\r';
|
||||
break;
|
||||
case 'f':
|
||||
ch = '\f';
|
||||
break;
|
||||
default :
|
||||
ch = *str;
|
||||
}
|
||||
}
|
||||
*pstr = str;
|
||||
return ch & 0377;
|
||||
}
|
||||
|
||||
int
|
||||
stoi(str)
|
||||
char *str;
|
||||
{
|
||||
register i = 0;
|
||||
|
||||
while (*str >= '0' && *str <= '9') {
|
||||
i = i * 10 + *str++ - '0';
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
char *
|
||||
getline(s, n, fp)
|
||||
char *s;
|
||||
FILE *fp;
|
||||
{
|
||||
register c = getc(fp);
|
||||
char *str = s;
|
||||
|
||||
while (n--) {
|
||||
if (c == EOF) {
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
if (c == '\n') {
|
||||
*str++ = '\0';
|
||||
return s;
|
||||
}
|
||||
*str++ = c;
|
||||
c = getc(fp);
|
||||
}
|
||||
s[n - 1] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
DoFile(name)
|
||||
char *name;
|
||||
{
|
||||
char text[BUFSIZE];
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(name, "r")) == NULL) {
|
||||
fprintf(stderr, "%s: cannot read file %s\n", ProgCall, name);
|
||||
exit(1);
|
||||
}
|
||||
while (getline(text, BUFSIZE, fp) != NULL) {
|
||||
if (text[0] == FILECOM) {
|
||||
option(text);
|
||||
}
|
||||
else {
|
||||
process(text, InputForm);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T E M P O R A R Y V A R I A B L E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Code for the allocation and de-allocation of temporary variables,
|
||||
allowing re-use.
|
||||
The routines use "ProcScope" instead of "CurrentScope", because
|
||||
"CurrentScope" also reflects WITH statements, and these scopes do not
|
||||
have local variabes.
|
||||
*/
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
#include <em_reg.h>
|
||||
#include <alloc.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "scope.h"
|
||||
#include "main.h"
|
||||
|
||||
struct tmpvar {
|
||||
struct tmpvar *t_next;
|
||||
arith t_offset; /* offset from LocalBase */
|
||||
};
|
||||
|
||||
/* STATICALLOCDEF "tmpvar" 10 */
|
||||
|
||||
static struct tmpvar *TmpInts, /* for integer temporaries */
|
||||
*TmpPtrs; /* for pointer temporaries */
|
||||
static t_scope *ProcScope; /* scope of procedure in which the
|
||||
temporaries are allocated
|
||||
*/
|
||||
|
||||
TmpOpen(sc) t_scope *sc;
|
||||
{
|
||||
/* Initialize for temporaries in scope "sc".
|
||||
*/
|
||||
ProcScope = sc;
|
||||
}
|
||||
|
||||
arith
|
||||
TmpSpace(sz, al)
|
||||
arith sz;
|
||||
{
|
||||
register t_scope *sc = ProcScope;
|
||||
|
||||
sc->sc_off = - WA(align(sz - sc->sc_off, al));
|
||||
return sc->sc_off;
|
||||
}
|
||||
|
||||
STATIC arith
|
||||
NewTmp(plist, sz, al, regtype)
|
||||
register struct tmpvar **plist;
|
||||
arith sz;
|
||||
{
|
||||
register arith offset;
|
||||
register struct tmpvar *tmp;
|
||||
|
||||
if (!*plist) {
|
||||
offset = TmpSpace(sz, al);
|
||||
if (! options['n']) C_ms_reg(offset, sz, regtype, 0);
|
||||
}
|
||||
else {
|
||||
tmp = *plist;
|
||||
offset = tmp->t_offset;
|
||||
*plist = tmp->t_next;
|
||||
free_tmpvar(tmp);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
arith
|
||||
NewInt()
|
||||
{
|
||||
return NewTmp(&TmpInts, int_size, int_align, reg_any);
|
||||
}
|
||||
|
||||
arith
|
||||
NewPtr()
|
||||
{
|
||||
return NewTmp(&TmpPtrs, pointer_size, pointer_align, reg_pointer);
|
||||
}
|
||||
|
||||
STATIC
|
||||
FreeTmp(plist, off)
|
||||
struct tmpvar **plist;
|
||||
arith off;
|
||||
{
|
||||
register struct tmpvar *tmp = new_tmpvar();
|
||||
|
||||
tmp->t_next = *plist;
|
||||
tmp->t_offset = off;
|
||||
*plist = tmp;
|
||||
}
|
||||
|
||||
FreeInt(off)
|
||||
arith off;
|
||||
{
|
||||
FreeTmp(&TmpInts, off);
|
||||
}
|
||||
|
||||
FreePtr(off)
|
||||
arith off;
|
||||
{
|
||||
FreeTmp(&TmpPtrs, off);
|
||||
}
|
||||
|
||||
TmpClose()
|
||||
{
|
||||
register struct tmpvar *tmp, *tmp1;
|
||||
|
||||
tmp = TmpInts;
|
||||
while (tmp) {
|
||||
tmp1 = tmp;
|
||||
tmp = tmp->t_next;
|
||||
free_tmpvar(tmp1);
|
||||
}
|
||||
tmp = TmpPtrs;
|
||||
while (tmp) {
|
||||
tmp1 = tmp;
|
||||
tmp = tmp->t_next;
|
||||
free_tmpvar(tmp1);
|
||||
}
|
||||
TmpInts = TmpPtrs = 0;
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T O K E N D E F I N I T I O N S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "tokenname.h"
|
||||
#include "Lpars.h"
|
||||
#include "idf.h"
|
||||
|
||||
/* To centralize the declaration of %tokens, their presence in this
|
||||
file is taken as their declaration. The Makefile will produce
|
||||
a grammar file (tokenfile.g) from this file. This scheme ensures
|
||||
that all tokens have a printable name.
|
||||
Also, the "token2str.c" file is produced from this file.
|
||||
*/
|
||||
|
||||
#ifdef ___XXX___
|
||||
struct tokenname tkspec[] = { /* the names of the special tokens */
|
||||
{IDENT, "identifier"},
|
||||
{STRING, "string"},
|
||||
{INTEGER, "number"},
|
||||
{REAL, "real"},
|
||||
{0, ""}
|
||||
};
|
||||
|
||||
struct tokenname tkcomp[] = { /* names of the composite tokens */
|
||||
{LESSEQUAL, "<="},
|
||||
{GREATEREQUAL, ">="},
|
||||
{UPTO, ".."},
|
||||
{BECOMES, ":="},
|
||||
{0, ""}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct tokenname tkidf[] = { /* names of the identifier tokens */
|
||||
{AND, "AND"},
|
||||
{ARRAY, "ARRAY"},
|
||||
{BEGIN, "BEGIN"},
|
||||
{BY, "BY"},
|
||||
{CASE, "CASE"},
|
||||
{CONST, "CONST"},
|
||||
{DEFINITION, "DEFINITION"},
|
||||
{DIV, "DIV"},
|
||||
{DO, "DO"},
|
||||
{ELSE, "ELSE"},
|
||||
{ELSIF, "ELSIF"},
|
||||
{END, "END"},
|
||||
{EXIT, "EXIT"},
|
||||
{EXPORT, "EXPORT"},
|
||||
{FOR, "FOR"},
|
||||
{FROM, "FROM"},
|
||||
{IF, "IF"},
|
||||
{IMPLEMENTATION, "IMPLEMENTATION"},
|
||||
{IMPORT, "IMPORT"},
|
||||
{IN, "IN"},
|
||||
{LOOP, "LOOP"},
|
||||
{MOD, "MOD"},
|
||||
{MODULE, "MODULE"},
|
||||
{NOT, "NOT"},
|
||||
{OF, "OF"},
|
||||
{OR, "OR"},
|
||||
{POINTER, "POINTER"},
|
||||
{PROCEDURE, "PROCEDURE"},
|
||||
{QUALIFIED, "QUALIFIED"},
|
||||
{RECORD, "RECORD"},
|
||||
{REPEAT, "REPEAT"},
|
||||
{RETURN, "RETURN"},
|
||||
{SET, "SET"},
|
||||
{THEN, "THEN"},
|
||||
{TO, "TO"},
|
||||
{TYPE, "TYPE"},
|
||||
{UNTIL, "UNTIL"},
|
||||
{VAR, "VAR"},
|
||||
{WHILE, "WHILE"},
|
||||
{WITH, "WITH"},
|
||||
{0, ""}
|
||||
};
|
||||
|
||||
#ifdef ___XXX___
|
||||
struct tokenname tkinternal[] = { /* internal keywords */
|
||||
{PROGRAM, ""},
|
||||
{COERCION, ""},
|
||||
{CAST, ""},
|
||||
{0, "0"}
|
||||
};
|
||||
|
||||
struct tokenname tkstandard[] = { /* standard identifiers */
|
||||
{0, ""}
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Some routines to handle tokennames */
|
||||
|
||||
reserve(resv)
|
||||
register struct tokenname *resv;
|
||||
{
|
||||
/* The names of the tokens described in resv are entered
|
||||
as reserved words.
|
||||
*/
|
||||
register t_idf *p;
|
||||
|
||||
while (resv->tn_symbol) {
|
||||
p = str2idf(resv->tn_name, 0);
|
||||
if (!p) fatal("out of Memory");
|
||||
p->id_reserved = resv->tn_symbol;
|
||||
resv++;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T O K E N N A M E S T R U C T U R E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
struct tokenname { /* Used for defining the name of a
|
||||
token as identified by its symbol
|
||||
*/
|
||||
int tn_symbol;
|
||||
char *tn_name;
|
||||
};
|
||||
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T Y P E D E S C R I P T O R S T R U C T U R E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "dbsymtab.h"
|
||||
|
||||
struct paramlist { /* structure for parameterlist of a PROCEDURE */
|
||||
struct paramlist *par_next;
|
||||
struct def *par_def; /* "df" of parameter */
|
||||
#define IsVarParam(xpar) ((int) ((xpar)->par_def->df_flags & D_VARPAR))
|
||||
#define TypeOfParam(xpar) ((xpar)->par_def->df_type)
|
||||
};
|
||||
|
||||
typedef struct paramlist t_param;
|
||||
|
||||
/* ALLOCDEF "paramlist" 20 */
|
||||
|
||||
struct enume {
|
||||
struct def *en_enums; /* Definitions of enumeration literals */
|
||||
arith en_ncst; /* Number of constants */
|
||||
label en_rck; /* Label of range check descriptor */
|
||||
#define enm_enums tp_value.tp_enum->en_enums
|
||||
#define enm_ncst tp_value.tp_enum->en_ncst
|
||||
#define enm_rck tp_value.tp_enum->en_rck
|
||||
};
|
||||
|
||||
/* ALLOCDEF "enume" 5 */
|
||||
|
||||
struct subrange {
|
||||
arith su_lb, su_ub; /* lower bound and upper bound */
|
||||
label su_rck; /* label of range check descriptor */
|
||||
#define sub_lb tp_value.tp_subrange->su_lb
|
||||
#define sub_ub tp_value.tp_subrange->su_ub
|
||||
#define sub_rck tp_value.tp_subrange->su_rck
|
||||
};
|
||||
|
||||
/* ALLOCDEF "subrange" 5 */
|
||||
|
||||
struct array {
|
||||
struct type *ar_elem; /* type of elements */
|
||||
label ar_descr; /* label of array descriptor */
|
||||
arith ar_elsize; /* size of elements */
|
||||
arith ar_low; /* lower bound of index */
|
||||
arith ar_high; /* upper bound of index */
|
||||
#define arr_elem tp_value.tp_arr->ar_elem
|
||||
#define arr_descr tp_value.tp_arr->ar_descr
|
||||
#define arr_elsize tp_value.tp_arr->ar_elsize
|
||||
#define arr_low tp_value.tp_arr->ar_low
|
||||
#define arr_high tp_value.tp_arr->ar_high
|
||||
};
|
||||
|
||||
/* ALLOCDEF "array" 5 */
|
||||
|
||||
struct record {
|
||||
struct scope *rc_scope; /* scope of this record */
|
||||
/* members are in the symbol table */
|
||||
#define rec_scope tp_value.tp_record.rc_scope
|
||||
};
|
||||
|
||||
struct proc {
|
||||
struct paramlist *pr_params;
|
||||
arith pr_nbpar; /* number of bytes parameters accessed */
|
||||
#define prc_params tp_value.tp_proc.pr_params
|
||||
#define prc_nbpar tp_value.tp_proc.pr_nbpar
|
||||
};
|
||||
|
||||
struct set {
|
||||
arith st_low; /* lowerbound of subrange type of set */
|
||||
unsigned st_sz; /* size of constant set in compiler */
|
||||
#define set_low tp_value.tp_set.st_low
|
||||
#define set_sz tp_value.tp_set.st_sz
|
||||
};
|
||||
|
||||
struct type {
|
||||
struct type *tp_next; /* used with ARRAY, PROCEDURE, POINTER, SET,
|
||||
SUBRANGE, EQUAL
|
||||
*/
|
||||
short tp_fund; /* fundamental type or constructor */
|
||||
#define T_RECORD 0x0001
|
||||
#define T_ENUMERATION 0x0002
|
||||
#define T_INTEGER 0x0004
|
||||
#define T_CARDINAL 0x0008
|
||||
#define T_EQUAL 0x0010
|
||||
#define T_REAL 0x0020
|
||||
#define T_HIDDEN 0x0040
|
||||
#define T_POINTER 0x0080
|
||||
#define T_CHAR 0x0100
|
||||
#define T_WORD 0x0200
|
||||
#define T_SET 0x0400
|
||||
#define T_SUBRANGE 0x0800
|
||||
#define T_PROCEDURE 0x1000
|
||||
#define T_ARRAY 0x2000
|
||||
#define T_STRING 0x4000
|
||||
#define T_INTORCARD (T_INTEGER|T_CARDINAL)
|
||||
#define T_NOSUB (T_INTORCARD|T_ENUMERATION|T_CHAR)
|
||||
#define T_NUMERIC (T_INTORCARD|T_REAL)
|
||||
#define T_INDEX (T_ENUMERATION|T_CHAR|T_SUBRANGE)
|
||||
#define T_DISCRETE (T_INDEX|T_INTORCARD)
|
||||
#define T_CONSTRUCTED (T_ARRAY|T_SET|T_RECORD)
|
||||
#ifdef DBSYMTAB
|
||||
short tp_dbindex; /* index in debugger symbol table */
|
||||
#endif
|
||||
int tp_align; /* alignment requirement of this type */
|
||||
arith tp_size; /* size of this type */
|
||||
union {
|
||||
struct enume *tp_enum;
|
||||
struct subrange *tp_subrange;
|
||||
struct array *tp_arr;
|
||||
struct record tp_record;
|
||||
struct proc tp_proc;
|
||||
struct set tp_set;
|
||||
} tp_value;
|
||||
};
|
||||
|
||||
typedef struct type t_type;
|
||||
|
||||
/* ALLOCDEF "type" 50 */
|
||||
|
||||
extern t_type
|
||||
*bool_type,
|
||||
*char_type,
|
||||
*int_type,
|
||||
*card_type,
|
||||
*longint_type,
|
||||
*longcard_type,
|
||||
*real_type,
|
||||
*longreal_type,
|
||||
*word_type,
|
||||
*byte_type,
|
||||
*address_type,
|
||||
*intorcard_type,
|
||||
*longintorcard_type,
|
||||
*bitset_type,
|
||||
*void_type,
|
||||
*std_type,
|
||||
*error_type; /* All from type.c */
|
||||
|
||||
#include "nocross.h"
|
||||
#ifdef NOCROSS
|
||||
#include "target_sizes.h"
|
||||
#define word_align (AL_WORD)
|
||||
#define short_align (AL_SHORT)
|
||||
#define int_align (AL_INT)
|
||||
#define long_align (AL_LONG)
|
||||
#define float_align (AL_FLOAT)
|
||||
#define double_align (AL_DOUBLE)
|
||||
#define pointer_align (AL_POINTER)
|
||||
#define struct_align (AL_STRUCT)
|
||||
|
||||
#define word_size (SZ_WORD)
|
||||
#define dword_size (2 * SZ_WORD)
|
||||
#define int_size (SZ_INT)
|
||||
#define short_size (SZ_SHORT)
|
||||
#define long_size (SZ_LONG)
|
||||
#define float_size (SZ_FLOAT)
|
||||
#define double_size (SZ_DOUBLE)
|
||||
#define pointer_size (SZ_POINTER)
|
||||
|
||||
#define wrd_bits (8*(int)word_size)
|
||||
#else /* NOCROSS */
|
||||
|
||||
extern int
|
||||
word_align,
|
||||
short_align,
|
||||
int_align,
|
||||
long_align,
|
||||
float_align,
|
||||
double_align,
|
||||
pointer_align,
|
||||
struct_align; /* All from type.c */
|
||||
|
||||
extern arith
|
||||
word_size,
|
||||
dword_size,
|
||||
short_size,
|
||||
int_size,
|
||||
long_size,
|
||||
float_size,
|
||||
double_size,
|
||||
pointer_size; /* All from type.c */
|
||||
|
||||
extern unsigned int
|
||||
wrd_bits; /* from cstoper.c */
|
||||
#endif /* NOCROSS */
|
||||
|
||||
extern arith
|
||||
ret_area_size;
|
||||
|
||||
extern arith
|
||||
align(); /* type.c */
|
||||
|
||||
extern t_type
|
||||
*construct_type(),
|
||||
*standard_type(),
|
||||
*set_type(),
|
||||
*subr_type(),
|
||||
*proc_type(),
|
||||
*enum_type(),
|
||||
*qualified_type(),
|
||||
*intorcard(),
|
||||
*RemoveEqual(); /* All from type.c */
|
||||
|
||||
#define NULLTYPE ((t_type *) 0)
|
||||
|
||||
#define IsConformantArray(tpx) ((tpx)->tp_fund==T_ARRAY && (tpx)->tp_size==0)
|
||||
#define bounded(tpx) ((tpx)->tp_fund & T_INDEX)
|
||||
#define complex(tpx) ((tpx)->tp_fund & (T_RECORD|T_ARRAY))
|
||||
#define WA(sz) (align(sz, (int) word_size))
|
||||
#ifdef DEBUG
|
||||
#define ResultType(tpx) (assert((tpx)->tp_fund == T_PROCEDURE),\
|
||||
(tpx)->tp_next)
|
||||
#define ParamList(tpx) (assert((tpx)->tp_fund == T_PROCEDURE),\
|
||||
(tpx)->prc_params)
|
||||
#define IndexType(tpx) (assert((tpx)->tp_fund == T_ARRAY),\
|
||||
(tpx)->tp_next)
|
||||
#define ElementType(tpx) (assert((tpx)->tp_fund == T_SET),\
|
||||
(tpx)->tp_next)
|
||||
#define PointedtoType(tpx) (assert((tpx)->tp_fund == T_POINTER),\
|
||||
(tpx)->tp_next)
|
||||
#define SubBaseType(tpx) (assert((tpx)->tp_fund == T_SUBRANGE), \
|
||||
(tpx)->tp_next)
|
||||
#else /* DEBUG */
|
||||
#define ResultType(tpx) ((tpx)->tp_next)
|
||||
#define ParamList(tpx) ((tpx)->prc_params)
|
||||
#define IndexType(tpx) ((tpx)->tp_next)
|
||||
#define ElementType(tpx) ((tpx)->tp_next)
|
||||
#define PointedtoType(tpx) ((tpx)->tp_next)
|
||||
#define SubBaseType(tpx) ((tpx)->tp_next)
|
||||
#endif /* DEBUG */
|
||||
#define BaseType(tpx) ((tpx)->tp_fund == T_SUBRANGE ? (tpx)->tp_next : \
|
||||
(tpx))
|
||||
#define IsConstructed(tpx) ((tpx)->tp_fund & T_CONSTRUCTED)
|
||||
#define TooBigForReturnArea(tpx) ((tpx)->tp_size > ret_area_size)
|
||||
|
||||
extern arith full_mask[];
|
||||
extern arith max_int[];
|
||||
extern arith min_int[];
|
||||
|
||||
#define ufit(n, i) (((n) & ~full_mask[(i)]) == 0)
|
||||
@@ -1,937 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T Y P E D E F I N I T I O N M E C H A N I S M */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <alloc.h>
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <em_code.h>
|
||||
|
||||
#include "nostrict.h"
|
||||
#include "LLlex.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "node.h"
|
||||
#include "scope.h"
|
||||
#include "walk.h"
|
||||
#include "main.h"
|
||||
#include "chk_expr.h"
|
||||
#include "warning.h"
|
||||
#include "uns_arith.h"
|
||||
|
||||
#ifndef NOCROSS
|
||||
#include "target_sizes.h"
|
||||
int
|
||||
word_align = AL_WORD,
|
||||
short_align = AL_SHORT,
|
||||
int_align = AL_INT,
|
||||
long_align = AL_LONG,
|
||||
float_align = AL_FLOAT,
|
||||
double_align = AL_DOUBLE,
|
||||
pointer_align = AL_POINTER,
|
||||
struct_align = AL_STRUCT;
|
||||
|
||||
arith
|
||||
word_size = SZ_WORD,
|
||||
dword_size = 2 * SZ_WORD,
|
||||
int_size = SZ_INT,
|
||||
short_size = SZ_SHORT,
|
||||
long_size = SZ_LONG,
|
||||
float_size = SZ_FLOAT,
|
||||
double_size = SZ_DOUBLE,
|
||||
pointer_size = SZ_POINTER;
|
||||
#endif
|
||||
|
||||
#define arith_sign ((arith) (1L << (sizeof(arith) * 8 - 1)))
|
||||
|
||||
arith ret_area_size;
|
||||
|
||||
t_type
|
||||
*bool_type,
|
||||
*char_type,
|
||||
*int_type,
|
||||
*card_type,
|
||||
*longint_type,
|
||||
*longcard_type,
|
||||
*real_type,
|
||||
*longreal_type,
|
||||
*word_type,
|
||||
*byte_type,
|
||||
*address_type,
|
||||
*intorcard_type,
|
||||
*longintorcard_type,
|
||||
*bitset_type,
|
||||
*void_type,
|
||||
*std_type,
|
||||
*error_type;
|
||||
|
||||
t_type *
|
||||
construct_type(fund, tp)
|
||||
int fund;
|
||||
register t_type *tp;
|
||||
{
|
||||
/* fund must be a type constructor.
|
||||
The pointer to the constructed type is returned.
|
||||
*/
|
||||
register t_type *dtp = new_type();
|
||||
|
||||
switch (dtp->tp_fund = fund) {
|
||||
case T_PROCEDURE:
|
||||
case T_POINTER:
|
||||
case T_HIDDEN:
|
||||
dtp->tp_align = pointer_align;
|
||||
dtp->tp_size = pointer_size;
|
||||
break;
|
||||
|
||||
case T_SET:
|
||||
dtp->tp_align = word_align;
|
||||
break;
|
||||
|
||||
case T_ARRAY:
|
||||
dtp->tp_value.tp_arr = new_array();
|
||||
dtp->tp_align = struct_align;
|
||||
break;
|
||||
|
||||
case T_SUBRANGE:
|
||||
assert(tp != 0);
|
||||
dtp->tp_value.tp_subrange = new_subrange();
|
||||
dtp->tp_align = tp->tp_align;
|
||||
dtp->tp_size = tp->tp_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
crash("funny type constructor");
|
||||
}
|
||||
|
||||
dtp->tp_next = tp;
|
||||
return dtp;
|
||||
}
|
||||
|
||||
arith
|
||||
align(pos, al)
|
||||
arith pos;
|
||||
int al;
|
||||
{
|
||||
int i = pos % al;
|
||||
|
||||
if (i) return pos + (al - i);
|
||||
return pos;
|
||||
}
|
||||
|
||||
t_type *
|
||||
standard_type(fund, algn, size)
|
||||
int fund;
|
||||
int algn;
|
||||
arith size;
|
||||
{
|
||||
register t_type *tp = new_type();
|
||||
|
||||
tp->tp_fund = fund;
|
||||
tp->tp_align = algn;
|
||||
tp->tp_size = size;
|
||||
if (fund == T_ENUMERATION || fund == T_CHAR) {
|
||||
tp->tp_value.tp_enum = new_enume();
|
||||
}
|
||||
|
||||
return tp;
|
||||
}
|
||||
|
||||
InitTypes()
|
||||
{
|
||||
/* Initialize the predefined types
|
||||
*/
|
||||
register t_type *tp;
|
||||
|
||||
/* first, do some checking
|
||||
*/
|
||||
if ((int) int_size != (int) word_size) {
|
||||
fatal("integer size not equal to word size");
|
||||
}
|
||||
|
||||
if ((int) long_size < (int) int_size) {
|
||||
fatal("long integer size smaller than integer size");
|
||||
}
|
||||
|
||||
if ((int) double_size < (int) float_size) {
|
||||
fatal("long real size smaller than real size");
|
||||
}
|
||||
|
||||
ret_area_size = (int) double_size > ((int) pointer_size << 1) ?
|
||||
double_size : (pointer_size << 1);
|
||||
|
||||
/* character type
|
||||
*/
|
||||
char_type = standard_type(T_CHAR, 1, (arith) 1);
|
||||
char_type->enm_ncst = 256;
|
||||
|
||||
/* boolean type
|
||||
*/
|
||||
bool_type = standard_type(T_ENUMERATION, 1, (arith) 1);
|
||||
bool_type->enm_ncst = 2;
|
||||
|
||||
/* integer types, also a "intorcard", for integer constants between
|
||||
0 and MAX(INTEGER)
|
||||
*/
|
||||
int_type = standard_type(T_INTEGER, int_align, int_size);
|
||||
longint_type = standard_type(T_INTEGER, long_align, long_size);
|
||||
longcard_type = standard_type(T_CARDINAL, long_align, long_size);
|
||||
card_type = standard_type(T_CARDINAL, int_align, int_size);
|
||||
intorcard_type = standard_type(T_INTORCARD, int_align, int_size);
|
||||
longintorcard_type = standard_type(T_INTORCARD, long_align, long_size);
|
||||
|
||||
/* floating types
|
||||
*/
|
||||
real_type = standard_type(T_REAL, float_align, float_size);
|
||||
longreal_type = standard_type(T_REAL, double_align, double_size);
|
||||
|
||||
/* SYSTEM types
|
||||
*/
|
||||
word_type = standard_type(T_WORD, word_align, word_size);
|
||||
byte_type = standard_type(T_WORD, 1, (arith) 1);
|
||||
address_type = construct_type(T_POINTER, word_type);
|
||||
|
||||
/* create BITSET type
|
||||
TYPE BITSET = SET OF [0..W-1];
|
||||
The subrange is a subrange of type cardinal, because the lower bound
|
||||
is a non-negative integer (See Rep. 6.3)
|
||||
*/
|
||||
tp = construct_type(T_SUBRANGE, card_type);
|
||||
tp->sub_lb = 0;
|
||||
tp->sub_ub = (int) word_size * 8 - 1;
|
||||
bitset_type = set_type(tp);
|
||||
|
||||
/* a unique type for standard procedures and functions
|
||||
*/
|
||||
std_type = construct_type(T_PROCEDURE, NULLTYPE);
|
||||
|
||||
/* a unique type indicating an error
|
||||
*/
|
||||
error_type = new_type();
|
||||
*error_type = *char_type;
|
||||
void_type = error_type;
|
||||
}
|
||||
|
||||
int
|
||||
fit(sz, nbytes)
|
||||
arith sz;
|
||||
{
|
||||
return ((sz) + ((arith)0x80<<(((nbytes)-1)*8)) & ~full_mask[(nbytes)]) == 0;
|
||||
}
|
||||
|
||||
STATIC
|
||||
u_small(tp, n)
|
||||
register t_type *tp;
|
||||
arith n;
|
||||
{
|
||||
if (ufit(n, 1)) {
|
||||
tp->tp_size = 1;
|
||||
tp->tp_align = 1;
|
||||
}
|
||||
else if (ufit(n, (int)short_size)) {
|
||||
tp->tp_size = short_size;
|
||||
tp->tp_align = short_align;
|
||||
}
|
||||
}
|
||||
|
||||
t_type *
|
||||
enum_type(EnumList)
|
||||
t_node *EnumList;
|
||||
{
|
||||
register t_type *tp =
|
||||
standard_type(T_ENUMERATION, int_align, int_size);
|
||||
|
||||
EnterEnumList(EnumList, tp);
|
||||
if (! fit(tp->enm_ncst, (int) int_size)) {
|
||||
node_error(EnumList, "too many enumeration literals");
|
||||
}
|
||||
u_small(tp, (arith) (tp->enm_ncst-1));
|
||||
return tp;
|
||||
}
|
||||
|
||||
t_type *
|
||||
qualified_type(pnd)
|
||||
t_node **pnd;
|
||||
{
|
||||
register t_def *df;
|
||||
|
||||
if (ChkDesig(pnd, D_USED)) {
|
||||
register t_node *nd = *pnd;
|
||||
if (nd->nd_class != Def) {
|
||||
node_error(nd, "type expected");
|
||||
FreeNode(nd);
|
||||
return error_type;
|
||||
}
|
||||
|
||||
df = nd->nd_def;
|
||||
if (df->df_kind&(D_ISTYPE|D_FORWARD|D_FORWTYPE|D_ERROR)) {
|
||||
if (! df->df_type) {
|
||||
node_error(nd,"type \"%s\" not (yet) declared", df->df_idf->id_text);
|
||||
FreeNode(nd);
|
||||
return error_type;
|
||||
}
|
||||
FreeNode(nd);
|
||||
if (df->df_kind == D_FORWTYPE) {
|
||||
/* Here, df->df_type was already set,
|
||||
so there is an actual definition in the
|
||||
surrounding scope, which is now used.
|
||||
*/
|
||||
ForceForwardTypeDef(df);
|
||||
}
|
||||
return df->df_type;
|
||||
}
|
||||
node_error(nd, "identifier \"%s\" is not a type", df->df_idf->id_text);
|
||||
}
|
||||
FreeNode(*pnd);
|
||||
return error_type;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
chk_bounds(l1, l2, fund)
|
||||
arith l1, l2;
|
||||
{
|
||||
/* compare to arith's, but be careful. They might be unsigned
|
||||
*/
|
||||
if (fund == T_INTEGER) {
|
||||
return l2 >= l1;
|
||||
}
|
||||
#ifdef UNSIGNED_ARITH
|
||||
return (UNSIGNED_ARITH) l2 >= (UNSIGNED_ARITH) l1;
|
||||
#else
|
||||
return (l2 & arith_sign ?
|
||||
(l1 & arith_sign ? l2 >= l1 : 1) :
|
||||
(l1 & arith_sign ? 0 : l2 >= l1)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
in_range(i, tp)
|
||||
arith i;
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Check that the value i fits in the subrange or enumeration
|
||||
type tp. Return 1 if so, 0 otherwise
|
||||
*/
|
||||
|
||||
switch(tp->tp_fund) {
|
||||
case T_ENUMERATION:
|
||||
case T_CHAR:
|
||||
return i >= 0 && i < tp->enm_ncst;
|
||||
|
||||
case T_SUBRANGE:
|
||||
return chk_bounds(i, tp->sub_ub, SubBaseType(tp)->tp_fund) &&
|
||||
chk_bounds(tp->sub_lb, i, SubBaseType(tp)->tp_fund);
|
||||
}
|
||||
assert(0);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
t_type *
|
||||
subr_type(lb, ub, base)
|
||||
register t_node *lb;
|
||||
t_node *ub;
|
||||
t_type *base;
|
||||
{
|
||||
/* Construct a subrange type from the constant expressions
|
||||
indicated by "lb" and "ub", but first perform some
|
||||
checks. "base" is either a user-specified base-type, or NULL.
|
||||
*/
|
||||
register t_type *tp = BaseType(lb->nd_type);
|
||||
register t_type *res;
|
||||
|
||||
if (tp == intorcard_type) {
|
||||
/* Lower bound >= 0; in this case, the base type is CARDINAL,
|
||||
according to the language definition, par. 6.3.
|
||||
But what if the upper-bound is of type INTEGER (f.i.
|
||||
MAX(INTEGER)? The Report does not answer this. Fix this
|
||||
for the time being, by making it an INTEGER subrange.
|
||||
???
|
||||
*/
|
||||
assert(lb->nd_INT >= 0);
|
||||
if (BaseType(ub->nd_type) == int_type ||
|
||||
(base && BaseType(base) == int_type)) tp = int_type;
|
||||
else tp = card_type;
|
||||
}
|
||||
|
||||
if (!ChkCompat(&ub, tp, "subrange bounds")) {
|
||||
return error_type;
|
||||
}
|
||||
|
||||
/* Check base type
|
||||
*/
|
||||
if (! (tp->tp_fund & T_DISCRETE)) {
|
||||
node_error(lb, "illegal base type for subrange");
|
||||
return error_type;
|
||||
}
|
||||
|
||||
/* Now construct resulting type
|
||||
*/
|
||||
res = construct_type(T_SUBRANGE, tp);
|
||||
res->sub_lb = lb->nd_INT;
|
||||
res->sub_ub = ub->nd_INT;
|
||||
|
||||
/* Check bounds
|
||||
*/
|
||||
if (! chk_bounds(lb->nd_INT, ub->nd_INT, tp->tp_fund)) {
|
||||
node_error(lb, "lower bound exceeds upper bound");
|
||||
ub->nd_INT = lb->nd_INT;
|
||||
res->sub_ub = res->sub_lb;
|
||||
}
|
||||
|
||||
if (tp == card_type) {
|
||||
u_small(res, res->sub_ub);
|
||||
}
|
||||
else if (tp == int_type) {
|
||||
if (fit(res->sub_lb, 1) && fit(res->sub_ub, 1)) {
|
||||
res->tp_size = 1;
|
||||
res->tp_align = 1;
|
||||
}
|
||||
else if (fit(res->sub_lb, (int)short_size) &&
|
||||
fit(res->sub_ub, (int)short_size)) {
|
||||
res->tp_size = short_size;
|
||||
res->tp_align = short_align;
|
||||
}
|
||||
}
|
||||
|
||||
if (base) {
|
||||
if (base->tp_fund == T_SUBRANGE) {
|
||||
/* Check that the bounds of "res" fall within the range
|
||||
of "base".
|
||||
*/
|
||||
if (! in_range(res->sub_lb, base) ||
|
||||
! in_range(res->sub_ub, base)) {
|
||||
error("base type has insufficient range");
|
||||
}
|
||||
base = base->tp_next;
|
||||
}
|
||||
if ((base->tp_fund & (T_ENUMERATION|T_CHAR)) ||
|
||||
base == card_type) {
|
||||
if (res->tp_next != base) {
|
||||
error("specified basetype for subrange not compatible with bounds");
|
||||
}
|
||||
}
|
||||
else if (base == int_type) {
|
||||
if (res->tp_next == card_type &&
|
||||
! chk_bounds(res->sub_ub,
|
||||
max_int[(int)int_size],
|
||||
T_CARDINAL)){
|
||||
error("upperbound too large for type INTEGER");
|
||||
}
|
||||
}
|
||||
else error("illegal base for a subrange");
|
||||
res->tp_next = base;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
t_type *
|
||||
proc_type(result_type, parameters, n_bytes_params)
|
||||
t_type *result_type;
|
||||
t_param *parameters;
|
||||
arith n_bytes_params;
|
||||
{
|
||||
register t_type *tp = construct_type(T_PROCEDURE, result_type);
|
||||
|
||||
tp->prc_params = parameters;
|
||||
tp->prc_nbpar = n_bytes_params;
|
||||
if (! fit(n_bytes_params, (int) word_size)) {
|
||||
error("maximum parameter byte count exceeded");
|
||||
}
|
||||
if (result_type && ! fit(WA(result_type->tp_size), (int) word_size)) {
|
||||
error("maximum return value size exceeded");
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
|
||||
genrck(tp)
|
||||
register t_type *tp;
|
||||
{
|
||||
/* generate a range check descriptor for type "tp" when
|
||||
neccessary. Return its label.
|
||||
*/
|
||||
arith lb, ub;
|
||||
register label ol;
|
||||
arith size = tp->tp_size;
|
||||
extern char *long2str();
|
||||
register t_type *btp = BaseType(tp);
|
||||
|
||||
if (size < word_size) size = word_size;
|
||||
getbounds(tp, &lb, &ub);
|
||||
|
||||
if (tp->tp_fund == T_SUBRANGE) {
|
||||
if (!(ol = tp->sub_rck)) {
|
||||
tp->sub_rck = ++data_label;
|
||||
}
|
||||
}
|
||||
else if (!(ol = tp->enm_rck)) {
|
||||
tp->enm_rck = ++data_label;
|
||||
}
|
||||
if (!ol) {
|
||||
C_df_dlb(ol = data_label);
|
||||
C_rom_icon(long2str((long)lb,10), size);
|
||||
C_rom_icon(long2str((long)ub,10), size);
|
||||
}
|
||||
c_lae_dlb(ol);
|
||||
if (size <= word_size) {
|
||||
CAL(btp->tp_fund == T_INTEGER ? "rcki" : "rcku", (int) pointer_size);
|
||||
}
|
||||
else {
|
||||
CAL(btp->tp_fund == T_INTEGER ? "rckil" : "rckul", (int) pointer_size);
|
||||
}
|
||||
}
|
||||
|
||||
getbounds(tp, plo, phi)
|
||||
register t_type *tp;
|
||||
arith *plo, *phi;
|
||||
{
|
||||
/* Get the bounds of a bounded type
|
||||
*/
|
||||
|
||||
assert(bounded(tp));
|
||||
|
||||
if (tp->tp_fund == T_SUBRANGE) {
|
||||
*plo = tp->sub_lb;
|
||||
*phi = tp->sub_ub;
|
||||
}
|
||||
else {
|
||||
*plo = 0;
|
||||
*phi = tp->enm_ncst - 1;
|
||||
}
|
||||
}
|
||||
|
||||
t_type *
|
||||
set_type(tp)
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Construct a set type with base type "tp", but first
|
||||
perform some checks
|
||||
*/
|
||||
arith lb, ub, diff, alloc_size;
|
||||
|
||||
if (! bounded(tp) || tp->tp_size > word_size) {
|
||||
error("illegal base type for set");
|
||||
return error_type;
|
||||
}
|
||||
|
||||
getbounds(tp, &lb, &ub);
|
||||
|
||||
#ifndef NOSTRICT
|
||||
if (lb < 0) {
|
||||
warning(W_STRICT, "base type of set has negative lower bound");
|
||||
}
|
||||
#endif
|
||||
|
||||
diff = ub - lb + 1;
|
||||
if (diff < 0) {
|
||||
error("set type limits exceeded");
|
||||
return error_type;
|
||||
}
|
||||
|
||||
tp = construct_type(T_SET, tp);
|
||||
tp->tp_size = WA((diff + 7) >> 3);
|
||||
alloc_size = (tp->tp_size / word_size + 1) * sizeof(arith);
|
||||
tp->set_sz = alloc_size;
|
||||
if (tp->set_sz != alloc_size) {
|
||||
error("set size too large");
|
||||
return error_type;
|
||||
}
|
||||
tp->set_low = lb;
|
||||
return tp;
|
||||
}
|
||||
|
||||
ArrayElSize(tp)
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Align element size to alignment requirement of element type.
|
||||
Also make sure that its size is either a dividor of the word_size,
|
||||
or a multiple of it.
|
||||
*/
|
||||
register arith algn;
|
||||
register t_type *elem_type = tp->arr_elem;
|
||||
|
||||
if (elem_type->tp_fund == T_ARRAY) ArraySizes(elem_type);
|
||||
algn = align(elem_type->tp_size, elem_type->tp_align);
|
||||
if (word_size % algn != 0) {
|
||||
/* algn is not a dividor of the word size, so make sure it
|
||||
is a multiple
|
||||
*/
|
||||
algn = WA(algn);
|
||||
}
|
||||
if (! fit(algn, (int) word_size)) {
|
||||
error("element size of array too large");
|
||||
}
|
||||
tp->arr_elsize = algn;
|
||||
if (tp->tp_align < elem_type->tp_align) {
|
||||
tp->tp_align = elem_type->tp_align;
|
||||
}
|
||||
}
|
||||
|
||||
ArraySizes(tp)
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Assign sizes to an array type, and check index type
|
||||
*/
|
||||
register t_type *index_type = IndexType(tp);
|
||||
arith diff;
|
||||
|
||||
ArrayElSize(tp);
|
||||
|
||||
/* check index type
|
||||
*/
|
||||
if (index_type->tp_size > word_size || ! bounded(index_type)) {
|
||||
error("illegal index type");
|
||||
tp->tp_size = tp->arr_elsize;
|
||||
return;
|
||||
}
|
||||
|
||||
getbounds(index_type, &(tp->arr_low), &(tp->arr_high));
|
||||
diff = tp->arr_high - tp->arr_low;
|
||||
|
||||
if (diff < 0 || ! fit(diff, (int) int_size)) {
|
||||
error("too many elements in array");
|
||||
}
|
||||
|
||||
tp->tp_size = align((diff + 1) * tp->arr_elsize, tp->tp_align);
|
||||
/* ??? check overflow ??? */
|
||||
if (! ufit(tp->tp_size, (int) pointer_size)) {
|
||||
error("array too large");
|
||||
}
|
||||
|
||||
/* generate descriptor and remember label.
|
||||
*/
|
||||
tp->arr_descr = ++data_label;
|
||||
C_df_dlb(tp->arr_descr);
|
||||
C_rom_cst((arith) 0);
|
||||
C_rom_cst(diff);
|
||||
C_rom_cst(tp->arr_elsize);
|
||||
}
|
||||
|
||||
FreeType(tp)
|
||||
register t_type *tp;
|
||||
{
|
||||
/* Release type structures indicated by "tp".
|
||||
This procedure is only called for types, constructed with
|
||||
T_PROCEDURE.
|
||||
*/
|
||||
register t_param *pr, *pr1;
|
||||
|
||||
assert(tp->tp_fund == T_PROCEDURE);
|
||||
|
||||
pr = ParamList(tp);
|
||||
while (pr) {
|
||||
pr1 = pr;
|
||||
pr = pr->par_next;
|
||||
free_def(pr1->par_def);
|
||||
free_paramlist(pr1);
|
||||
}
|
||||
|
||||
free_type(tp);
|
||||
}
|
||||
|
||||
DeclareType(nd, df, tp)
|
||||
register t_def *df;
|
||||
register t_type *tp;
|
||||
t_node *nd;
|
||||
{
|
||||
/* A type with type-description "tp" is declared and must
|
||||
be bound to definition "df".
|
||||
This routine also handles the case that the type-field of
|
||||
"df" is already bound. In that case, it is either an opaque
|
||||
type, or an error message was given when "df" was created.
|
||||
*/
|
||||
register t_type *df_tp = df->df_type;
|
||||
|
||||
if (df_tp && df_tp->tp_fund == T_HIDDEN) {
|
||||
if (! (tp->tp_fund & (T_POINTER|T_HIDDEN|T_EQUAL))) {
|
||||
node_error(nd,
|
||||
"opaque type \"%s\" is not a pointer type",
|
||||
df->df_idf->id_text);
|
||||
}
|
||||
df_tp->tp_next = tp;
|
||||
df_tp->tp_fund = T_EQUAL;
|
||||
while (tp != df_tp && tp->tp_fund == T_EQUAL) {
|
||||
tp = tp->tp_next;
|
||||
}
|
||||
if (tp == df_tp) {
|
||||
/* Circular definition! */
|
||||
node_error(nd,
|
||||
"opaque type \"%s\" has a circular definition",
|
||||
df->df_idf->id_text);
|
||||
tp->tp_next = error_type;
|
||||
}
|
||||
}
|
||||
else {
|
||||
df->df_type = tp;
|
||||
if (BaseType(tp)->tp_fund == T_ENUMERATION) {
|
||||
CheckForImports(df);
|
||||
}
|
||||
}
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g']) stb_string(df, D_TYPE);
|
||||
#endif
|
||||
|
||||
SolveForwardTypeRefs(df);
|
||||
}
|
||||
|
||||
SolveForwardTypeRefs(df)
|
||||
register t_def *df;
|
||||
{
|
||||
register t_node *nd;
|
||||
|
||||
if (df->df_kind == D_FORWTYPE) {
|
||||
nd = df->df_forw_node;
|
||||
|
||||
df->df_kind = D_TYPE;
|
||||
while (nd) {
|
||||
nd->nd_type->tp_next = df->df_type;
|
||||
#ifdef DBSYMTAB
|
||||
if (options['g'] && nd->nd_type->tp_dbindex < 0) {
|
||||
stb_addtp("(forward_type)", nd->nd_type);
|
||||
}
|
||||
#endif
|
||||
nd = nd->nd_RIGHT;
|
||||
}
|
||||
FreeNode(df->df_forw_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ForceForwardTypeDef(df)
|
||||
register t_def *df;
|
||||
{
|
||||
register t_def *df1 = df, *df2;
|
||||
register t_node *nd = df->df_forw_node;
|
||||
|
||||
while (df && df->df_kind == D_FORWTYPE) {
|
||||
RemoveFromIdList(df);
|
||||
if ((df2 = df->df_scope->sc_def) == df) {
|
||||
df->df_scope->sc_def = df->df_nextinscope;
|
||||
}
|
||||
else {
|
||||
while (df2->df_nextinscope != df) {
|
||||
df2 = df2->df_nextinscope;
|
||||
}
|
||||
df2->df_nextinscope = df->df_nextinscope;
|
||||
}
|
||||
df = df->df_forw_def;
|
||||
}
|
||||
while (nd->nd_class == Link) {
|
||||
nd = nd->nd_RIGHT;
|
||||
}
|
||||
df = lookfor(nd, CurrVis, 1, 0);
|
||||
if (! df->df_kind & (D_ERROR|D_TYPE)) {
|
||||
node_error(nd, "\"%s\" is not a type", df1->df_idf->id_text);
|
||||
}
|
||||
while (df1 && df1->df_kind == D_FORWTYPE) {
|
||||
df2 = df1->df_forw_def;
|
||||
df1->df_type = df->df_type;
|
||||
SolveForwardTypeRefs(df1);
|
||||
free_def(df1);
|
||||
df1 = df2;
|
||||
}
|
||||
}
|
||||
|
||||
t_type *
|
||||
RemoveEqual(tpx)
|
||||
register t_type *tpx;
|
||||
{
|
||||
|
||||
if (tpx) while (tpx->tp_fund == T_EQUAL) tpx = tpx->tp_next;
|
||||
return tpx;
|
||||
}
|
||||
|
||||
int
|
||||
type_or_forward(tp)
|
||||
t_type *tp;
|
||||
{
|
||||
/* POINTER TO IDENTIFIER construction. The IDENTIFIER resides
|
||||
in "dot". This routine handles the different cases.
|
||||
*/
|
||||
register t_node *nd;
|
||||
register t_def *df, *df1;
|
||||
|
||||
if ((df1 = lookup(dot.TOK_IDF, CurrentScope, D_IMPORTED, D_USED))) {
|
||||
/* Either a Module or a Type, but in both cases defined
|
||||
in this scope, so this is the correct identification
|
||||
*/
|
||||
switch(df1->df_kind) {
|
||||
case D_FORWARD:
|
||||
FreeNode(df1->for_node);
|
||||
df1->df_kind = D_FORWTYPE;
|
||||
df1->df_forw_node = 0;
|
||||
/* Fall through */
|
||||
case D_FORWTYPE:
|
||||
nd = dot2node(Link, NULLNODE, df1->df_forw_node);
|
||||
df1->df_forw_node = nd;
|
||||
nd->nd_type = tp;
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
nd = dot2leaf(Name);
|
||||
if ((df1 = lookfor(nd, CurrVis, 0, D_USED))->df_kind == D_MODULE) {
|
||||
/* A Modulename in one of the enclosing scopes.
|
||||
It is not clear from the language definition that
|
||||
it is correct to handle these like this, but
|
||||
existing compilers do it like this, and the
|
||||
alternative is difficult with a lookahead of only
|
||||
one token.
|
||||
This path should actually only be taken if the next token
|
||||
is a '.'.
|
||||
???
|
||||
*/
|
||||
FreeNode(nd);
|
||||
return 1;
|
||||
}
|
||||
/* Enter a forward reference into a list belonging to the
|
||||
current scope. This is used for POINTER declarations, which
|
||||
may have forward references that must howewer be declared in the
|
||||
same scope.
|
||||
*/
|
||||
df = define(nd->nd_IDF, CurrentScope, D_FORWTYPE);
|
||||
assert(df->df_kind == D_FORWTYPE);
|
||||
df->df_flags |= D_USED | D_DEFINED;
|
||||
nd->nd_type = tp;
|
||||
df->df_forw_node = nd;
|
||||
if (df != df1 && (df1->df_kind & (D_TYPE | D_FORWTYPE))) {
|
||||
/* "df1" refers to a possible identification, but
|
||||
we cannot be sure at this point. For the time
|
||||
being, however, we use this one.
|
||||
*/
|
||||
df->df_type = df1->df_type;
|
||||
df->df_forw_def = df1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
gcd(m, n)
|
||||
register int m, n;
|
||||
{
|
||||
/* Greatest Common Divisor
|
||||
*/
|
||||
register int r;
|
||||
|
||||
while (n) {
|
||||
r = m % n;
|
||||
m = n;
|
||||
n = r;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
int
|
||||
lcm(m, n)
|
||||
int m, n;
|
||||
{
|
||||
/* Least Common Multiple
|
||||
*/
|
||||
return m * (n / gcd(m, n));
|
||||
}
|
||||
|
||||
t_type *
|
||||
intorcard(left, right)
|
||||
register t_type *left, *right;
|
||||
{
|
||||
if (left->tp_fund == T_INTORCARD) {
|
||||
t_type *tmp = left;
|
||||
left = right;
|
||||
right = tmp;
|
||||
}
|
||||
if (right->tp_fund == T_INTORCARD) {
|
||||
if (left->tp_fund == T_INTEGER || left->tp_fund == T_CARDINAL) {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
DumpType(tp)
|
||||
register t_type *tp;
|
||||
{
|
||||
if (!tp) return;
|
||||
|
||||
print("align:%d; size:%ld;", tp->tp_align, (long) tp->tp_size);
|
||||
|
||||
print(" fund:");
|
||||
switch(tp->tp_fund) {
|
||||
case T_RECORD:
|
||||
print("RECORD");
|
||||
break;
|
||||
case T_ENUMERATION:
|
||||
print("ENUMERATION; ncst:%d", tp->enm_ncst); break;
|
||||
case T_INTEGER:
|
||||
print("INTEGER"); break;
|
||||
case T_CARDINAL:
|
||||
print("CARDINAL"); break;
|
||||
case T_REAL:
|
||||
print("REAL"); break;
|
||||
case T_HIDDEN:
|
||||
print("HIDDEN"); break;
|
||||
case T_EQUAL:
|
||||
print("EQUAL"); break;
|
||||
case T_POINTER:
|
||||
print("POINTER"); break;
|
||||
case T_CHAR:
|
||||
print("CHAR"); break;
|
||||
case T_WORD:
|
||||
print("WORD"); break;
|
||||
case T_SET:
|
||||
print("SET"); break;
|
||||
case T_SUBRANGE:
|
||||
print("SUBRANGE %ld-%ld", (long) tp->sub_lb, (long) tp->sub_ub);
|
||||
break;
|
||||
case T_PROCEDURE:
|
||||
{
|
||||
register t_param *par = ParamList(tp);
|
||||
|
||||
print("PROCEDURE");
|
||||
if (par) {
|
||||
print("(");
|
||||
while(par) {
|
||||
if (IsVarParam(par)) print("VAR ");
|
||||
DumpType(TypeOfParam(par));
|
||||
par = par->par_next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_ARRAY:
|
||||
print("ARRAY");
|
||||
print("; element:");
|
||||
DumpType(tp->arr_elem);
|
||||
print("; index:");
|
||||
DumpType(tp->tp_next);
|
||||
print(";");
|
||||
return;
|
||||
case T_STRING:
|
||||
print("STRING"); break;
|
||||
case T_INTORCARD:
|
||||
print("INTORCARD"); break;
|
||||
default:
|
||||
crash("DumpType");
|
||||
}
|
||||
if (tp->tp_next && tp->tp_fund != T_POINTER) {
|
||||
/* Avoid printing recursive types!
|
||||
*/
|
||||
print(" next:(");
|
||||
DumpType(tp->tp_next);
|
||||
print(")");
|
||||
}
|
||||
print(";");
|
||||
}
|
||||
#endif
|
||||
@@ -1,314 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* T Y P E E Q U I V A L E N C E */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Routines for testing type equivalence, type compatibility, and
|
||||
assignment compatibility
|
||||
*/
|
||||
#include "debug.h"
|
||||
|
||||
#include <em_arith.h>
|
||||
#include <em_label.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "strict3rd.h"
|
||||
#include "type.h"
|
||||
#include "LLlex.h"
|
||||
#include "idf.h"
|
||||
#include "def.h"
|
||||
#include "node.h"
|
||||
#include "warning.h"
|
||||
#include "main.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
extern char *sprint();
|
||||
|
||||
int
|
||||
TstTypeEquiv(tp1, tp2)
|
||||
t_type *tp1, *tp2;
|
||||
{
|
||||
/* test if two types are equivalent.
|
||||
*/
|
||||
|
||||
return tp1 == tp2
|
||||
||
|
||||
tp1 == error_type
|
||||
||
|
||||
tp2 == error_type;
|
||||
}
|
||||
|
||||
int
|
||||
TstParEquiv(tp1, tp2)
|
||||
register t_type *tp1, *tp2;
|
||||
{
|
||||
/* test if two parameter types are equivalent. This routine
|
||||
is used to check if two different procedure declarations
|
||||
(one in the definition module, one in the implementation
|
||||
module) are equivalent. A complication comes from dynamic
|
||||
arrays.
|
||||
*/
|
||||
|
||||
return
|
||||
TstTypeEquiv(tp1, tp2)
|
||||
||
|
||||
(
|
||||
IsConformantArray(tp1)
|
||||
&&
|
||||
IsConformantArray(tp2)
|
||||
&&
|
||||
TstTypeEquiv(tp1->arr_elem, tp2->arr_elem)
|
||||
);
|
||||
}
|
||||
|
||||
int
|
||||
TstProcEquiv(tp1, tp2)
|
||||
t_type *tp1, *tp2;
|
||||
{
|
||||
/* Test if two procedure types are equivalent. This routine
|
||||
may also be used for the testing of assignment compatibility
|
||||
between procedure variables and procedures.
|
||||
*/
|
||||
register t_param *p1, *p2;
|
||||
|
||||
/* First check if the result types are equivalent
|
||||
*/
|
||||
if (! TstTypeEquiv(ResultType(tp1), ResultType(tp2))) return 0;
|
||||
|
||||
p1 = ParamList(tp1);
|
||||
p2 = ParamList(tp2);
|
||||
|
||||
/* Now check the parameters
|
||||
*/
|
||||
while (p1 && p2) {
|
||||
if (IsVarParam(p1) != IsVarParam(p2) ||
|
||||
!TstParEquiv(TypeOfParam(p1), TypeOfParam(p2))) return 0;
|
||||
p1 = p1->par_next;
|
||||
p2 = p2->par_next;
|
||||
}
|
||||
|
||||
/* Here, at least one of the parameterlists is exhausted.
|
||||
Check that they are both.
|
||||
*/
|
||||
return p1 == p2;
|
||||
}
|
||||
|
||||
int
|
||||
TstCompat(tp1, tp2)
|
||||
register t_type *tp1, *tp2;
|
||||
{
|
||||
/* test if two types are compatible. See section 6.3 of the
|
||||
Modula-2 Report for a definition of "compatible".
|
||||
*/
|
||||
|
||||
if (TstTypeEquiv(tp1, tp2)) return 1;
|
||||
|
||||
tp1 = BaseType(tp1);
|
||||
tp2 = BaseType(tp2);
|
||||
if (tp2->tp_fund != T_INTORCARD &&
|
||||
(tp1->tp_fund == T_INTORCARD || tp1 == address_type)) {
|
||||
t_type *tmp = tp2;
|
||||
|
||||
tp2 = tp1;
|
||||
tp1 = tmp;
|
||||
}
|
||||
|
||||
return tp1 == tp2
|
||||
||
|
||||
( tp2 == intorcard_type
|
||||
&&
|
||||
(tp1 == int_type || tp1 == card_type || tp1 == address_type)
|
||||
)
|
||||
||
|
||||
( tp2 == longintorcard_type
|
||||
&&
|
||||
(tp1 == longint_type || tp1 == longcard_type || tp1 == address_type)
|
||||
)
|
||||
||
|
||||
( tp2 == address_type
|
||||
&&
|
||||
( tp1->tp_fund == T_CARDINAL || tp1->tp_fund == T_POINTER)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
int
|
||||
TstAssCompat(tp1, tp2)
|
||||
register t_type *tp1, *tp2;
|
||||
{
|
||||
/* Test if two types are assignment compatible.
|
||||
See Def 9.1.
|
||||
*/
|
||||
|
||||
if (TstCompat(tp1, tp2)) return 1;
|
||||
|
||||
tp1 = BaseType(tp1);
|
||||
tp2 = BaseType(tp2);
|
||||
|
||||
if (((tp1->tp_fund & T_INTORCARD) || tp1 == address_type) &&
|
||||
((tp2->tp_fund & T_INTORCARD) || tp2 == address_type)) return 1;
|
||||
|
||||
if ((tp1->tp_fund == T_REAL) &&
|
||||
(tp2->tp_fund == T_REAL)) return 1;
|
||||
|
||||
if (tp1->tp_fund == T_PROCEDURE &&
|
||||
tp2->tp_fund == T_PROCEDURE) {
|
||||
return TstProcEquiv(tp1, tp2);
|
||||
}
|
||||
|
||||
if (tp1->tp_fund == T_ARRAY) {
|
||||
/* check for string
|
||||
*/
|
||||
if (IsConformantArray(tp1)) return 0;
|
||||
|
||||
return
|
||||
BaseType(tp1->arr_elem) == char_type
|
||||
&& tp2->tp_fund == T_STRING
|
||||
&& (tp1->arr_high - tp1->arr_low + 1) >= tp2->tp_size
|
||||
;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
incompat(tp1, tp2)
|
||||
register t_type *tp1, *tp2;
|
||||
{
|
||||
|
||||
if (tp1->tp_fund == T_HIDDEN || tp2->tp_fund == T_HIDDEN) {
|
||||
return "properties of opaque type are hidden; illegal use";
|
||||
}
|
||||
return "type incompatibility";
|
||||
}
|
||||
|
||||
int
|
||||
TstParCompat(parno, formaltype, VARflag, nd, edf)
|
||||
register t_type *formaltype;
|
||||
t_node **nd;
|
||||
t_def *edf;
|
||||
{
|
||||
/* Check type compatibility for a parameter in a procedure call.
|
||||
Assignment compatibility may do if the parameter is
|
||||
a value parameter.
|
||||
Otherwise, a conformant array may do, or an ARRAY OF (WORD|BYTE)
|
||||
may do too.
|
||||
Or: a WORD may do.
|
||||
*/
|
||||
register t_type *actualtype = (*nd)->nd_type;
|
||||
char ebuf[256];
|
||||
|
||||
if (edf) {
|
||||
sprint(ebuf, "\"%s\", parameter %d: %%s", edf->df_idf->id_text, parno);
|
||||
}
|
||||
else sprint(ebuf, "parameter %d: %%s", parno);
|
||||
|
||||
if (
|
||||
TstTypeEquiv(formaltype, actualtype)
|
||||
||
|
||||
( !VARflag && ChkAssCompat(nd, formaltype, (char *) 0))
|
||||
||
|
||||
( formaltype == address_type
|
||||
&& actualtype->tp_fund == T_POINTER
|
||||
)
|
||||
||
|
||||
( formaltype == word_type
|
||||
&&
|
||||
( actualtype->tp_size == word_size
|
||||
||
|
||||
( !VARflag
|
||||
&&
|
||||
actualtype->tp_size <= word_size
|
||||
&&
|
||||
! IsConformantArray(actualtype)
|
||||
)
|
||||
)
|
||||
)
|
||||
||
|
||||
( formaltype == byte_type
|
||||
&& actualtype->tp_size == (arith) 1
|
||||
)
|
||||
||
|
||||
( IsConformantArray(formaltype)
|
||||
&&
|
||||
( formaltype->arr_elem == word_type
|
||||
|| formaltype->arr_elem == byte_type
|
||||
||
|
||||
( actualtype->tp_fund == T_ARRAY
|
||||
&& TstTypeEquiv(formaltype->arr_elem,actualtype->arr_elem)
|
||||
)
|
||||
||
|
||||
( actualtype->tp_fund == T_STRING
|
||||
&& TstTypeEquiv(formaltype->arr_elem, char_type)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
return 1;
|
||||
#ifndef STRICT_3RD_ED
|
||||
if (! options['3'] && VARflag && TstCompat(formaltype, actualtype)) {
|
||||
if (formaltype->tp_size == actualtype->tp_size) {
|
||||
node_warning(*nd,
|
||||
W_OLDFASHIONED,
|
||||
ebuf,
|
||||
"identical types required");
|
||||
return 1;
|
||||
}
|
||||
node_error(*nd, ebuf, "equal sized types required");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
node_error(*nd, ebuf, incompat(formaltype, actualtype));
|
||||
return 0;
|
||||
}
|
||||
|
||||
CompatCheck(nd, tp, message, fc)
|
||||
register t_node **nd;
|
||||
t_type *tp;
|
||||
char *message;
|
||||
int (*fc)();
|
||||
{
|
||||
if (! (*fc)(tp, (*nd)->nd_type)) {
|
||||
if (message) {
|
||||
node_error(*nd, "%s in %s",
|
||||
incompat(tp, (*nd)->nd_type),
|
||||
message);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
MkCoercion(nd, tp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ChkAssCompat(nd, tp, message)
|
||||
t_node **nd;
|
||||
t_type *tp;
|
||||
char *message;
|
||||
{
|
||||
/* Check assignment compatibility of node "nd" with type "tp".
|
||||
Give an error message when it fails
|
||||
*/
|
||||
|
||||
if ((*nd)->nd_symb == STRING) {
|
||||
TryToString((*nd), tp);
|
||||
}
|
||||
return CompatCheck(nd, tp, message, TstAssCompat);
|
||||
}
|
||||
|
||||
ChkCompat(nd, tp, message)
|
||||
t_node **nd;
|
||||
t_type *tp;
|
||||
char *message;
|
||||
{
|
||||
/* Check compatibility of node "nd" with type "tp".
|
||||
Give an error message when it fails
|
||||
*/
|
||||
|
||||
return CompatCheck(nd, tp, message, TstCompat);
|
||||
}
|
||||
1152
lang/m2/comp/walk.c
1152
lang/m2/comp/walk.c
File diff suppressed because it is too large
Load Diff
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* P A R S E T R E E W A L K E R */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Definition of WalkNode macro
|
||||
*/
|
||||
|
||||
extern int (*WalkTable[])();
|
||||
|
||||
#define WalkNode(xnd, xlab, rch) (*WalkTable[(xnd)->nd_class])((xnd), (xlab),(rch))
|
||||
|
||||
extern label text_label;
|
||||
extern label data_label;
|
||||
|
||||
#include "squeeze.h"
|
||||
|
||||
#ifndef SQUEEZE
|
||||
#define c_loc(x) C_loc((arith) (x))
|
||||
#define c_lae_dlb(x) C_lae_dlb(x,(arith) 0)
|
||||
#define CAL(nm, sz) (C_cal(nm), C_asp((arith)(sz)))
|
||||
#define c_bra(x) C_bra((label) (x))
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
* Author: Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/* W A R N I N G C L A S S E S */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* Warning classes, at the moment three of them:
|
||||
Strict (R)
|
||||
Ordinary (W)
|
||||
Old-fashioned(O)
|
||||
*/
|
||||
|
||||
/* Bits for a bit mask: */
|
||||
|
||||
#define W_ORDINARY 1
|
||||
#define W_STRICT 2
|
||||
#define W_OLDFASHIONED 4
|
||||
#define W_ALWAYS 010 /* always given */
|
||||
|
||||
#define W_ALL (W_ORDINARY|W_STRICT|W_OLDFASHIONED|W_ALWAYS)
|
||||
|
||||
#define W_INITIAL (W_ORDINARY | W_OLDFASHIONED | W_ALWAYS)
|
||||
|
||||
/* The bit mask itself: */
|
||||
extern int warning_classes;
|
||||
Reference in New Issue
Block a user