Added .globl, fix in Xfit call
This commit is contained in:
4
lang/.distr
Normal file
4
lang/.distr
Normal file
@@ -0,0 +1,4 @@
|
||||
basic
|
||||
cem
|
||||
occam
|
||||
pc
|
||||
3
lang/basic/.distr
Normal file
3
lang/basic/.distr
Normal file
@@ -0,0 +1,3 @@
|
||||
lib
|
||||
src
|
||||
test
|
||||
2
lang/basic/lib/.distr
Normal file
2
lang/basic/lib/.distr
Normal file
@@ -0,0 +1,2 @@
|
||||
LIST
|
||||
tail_bc.a
|
||||
@@ -1,5 +1,10 @@
|
||||
/* $Header$ */
|
||||
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
|
||||
long _abl(i) long i;
|
||||
{
|
||||
return( i>=0?i:-i);
|
||||
|
||||
@@ -31,25 +31,31 @@ _str(f,buffer)
|
||||
double f;
|
||||
char *buffer;
|
||||
{
|
||||
char *c;
|
||||
c= buffer;
|
||||
register char *c = buffer;
|
||||
int eformat = 0;
|
||||
if( f>=0){
|
||||
if( f> 1.0e8)
|
||||
if( f> 1.0e8) {
|
||||
eformat = 1;
|
||||
sprintf(buffer," %e",f);
|
||||
}
|
||||
else sprintf(buffer," %f",f);
|
||||
c++;
|
||||
}else {
|
||||
if(-f> 1.0e8)
|
||||
if(-f> 1.0e8) {
|
||||
eformat = 1;
|
||||
sprintf(buffer,"-%e",-f);
|
||||
}
|
||||
else sprintf(buffer,"-%f",-f);
|
||||
}
|
||||
for( ; *c && *c!= ' ';c++) ;
|
||||
c--;
|
||||
while( c>buffer && *c== '0')
|
||||
{
|
||||
*c= 0;c--;
|
||||
if (! eformat) {
|
||||
for( ; *c && *c!= ' ';c++) ;
|
||||
c--;
|
||||
while( c>buffer && *c== '0')
|
||||
{
|
||||
*c= 0;c--;
|
||||
}
|
||||
if( *c=='.') *c=0;
|
||||
}
|
||||
if( *c=='.') *c=0;
|
||||
strcat(buffer," ");
|
||||
}
|
||||
_prfnum(f)
|
||||
|
||||
@@ -21,9 +21,9 @@ double *i1,*i2;
|
||||
}
|
||||
|
||||
_strswap(s1,s2)
|
||||
String *s1,*s2;
|
||||
String **s1,**s2;
|
||||
{
|
||||
String s;
|
||||
String *s;
|
||||
s= *s1;
|
||||
*s1= *s2;
|
||||
*s2 = s;
|
||||
|
||||
20
lang/basic/src.old/.distr
Normal file
20
lang/basic/src.old/.distr
Normal file
@@ -0,0 +1,20 @@
|
||||
Makefile
|
||||
basic.yacc
|
||||
bem.c
|
||||
bem.h
|
||||
compile.c
|
||||
eval.c
|
||||
func.c
|
||||
gencode.c
|
||||
graph.c
|
||||
graph.h
|
||||
initialize.c
|
||||
basic.lex
|
||||
parsepar.c
|
||||
split.c
|
||||
symbols.c
|
||||
symbols.h
|
||||
util.c
|
||||
y.tab.c
|
||||
y.tab.h
|
||||
yywrap.c
|
||||
@@ -5,7 +5,7 @@ h=$d/h
|
||||
l=$d/lib
|
||||
INSTALL=$l/em_bem
|
||||
|
||||
CFLAGS = -I$h
|
||||
CFLAGS = -I$h -O
|
||||
|
||||
FILES= bem.o y.tab.o symbols.o initialize.o compile.o \
|
||||
parsepar.o yywrap.o gencode.o util.o graph.o \
|
||||
|
||||
@@ -44,12 +44,11 @@ Key keywords [] ={
|
||||
"else", ELSESYM, 0, 0,
|
||||
"end", ENDSYM, 0, 0,
|
||||
"eof", FUNCTION, EOFSYM, 0,
|
||||
"eqv", BOOLOP, EQVSYM, 0,
|
||||
"erase", ILLEGAL, 0, 0,
|
||||
"error", ERRORSYM, 0, 0,
|
||||
"err", ERRSYM, 0, 0,
|
||||
"erl", ERLSYM, 0, 0,
|
||||
"else", ELSESYM, 0, 0,
|
||||
"eqv", BOOLOP, EQVSYM, 0,
|
||||
"exp", FUNCTION, EXPSYM, 0,
|
||||
"field", FIELDSYM, 0, 0,
|
||||
"fix", FUNCTION, FIXSYM, 0,
|
||||
@@ -142,6 +141,8 @@ Key keywords [] ={
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
char *index();
|
||||
|
||||
/* Keyword index table */
|
||||
|
||||
int kex[27];
|
||||
@@ -232,7 +233,7 @@ lookup()
|
||||
for(c=cptr; *c && isalnum(*c);c++)
|
||||
if( isupper(*c) )
|
||||
*c= tolower((*c));
|
||||
for(k= keywords+kex[*cptr-'a']; *(k->name)== *cptr;k++)
|
||||
for(k= keywords+kex[*cptr-'a']; k->name != 0 && *(k->name)== *cptr;k++)
|
||||
if( strncmp(cptr,k->name,k->length)==0)
|
||||
{
|
||||
/* check functions first*/
|
||||
@@ -309,23 +310,29 @@ readconstant()
|
||||
number()
|
||||
{
|
||||
long i1;
|
||||
double f,dec;
|
||||
int minflag;
|
||||
double atof();
|
||||
register char *c;
|
||||
int overflow = 0;
|
||||
char cx;
|
||||
|
||||
i1=0;
|
||||
c=cptr;
|
||||
while(isdigit(*c)){
|
||||
i1= i1*10 + *c-'0';
|
||||
if (i1 < 0) overflow = 1;
|
||||
c++;
|
||||
}
|
||||
cptr=c;
|
||||
if( *c != '.'){
|
||||
if( i1> MAXINT || i1<MININT) {
|
||||
/*NOSTRICT*/ dval= i1;
|
||||
if( i1> MAXINT || i1<MININT || overflow) {
|
||||
cx = *c;
|
||||
*c = 0;
|
||||
/*NOSTRICT*/ dval= atof(cptr);
|
||||
cptr=c;
|
||||
*c = cx;
|
||||
return(FLTVALUE);
|
||||
}
|
||||
/*NOSTRICT*/ ival= i1;
|
||||
cptr = c;
|
||||
#ifdef YYDEBUG
|
||||
if(yydebug) printf("number:INTVALUE %d",i1);
|
||||
#endif
|
||||
@@ -333,28 +340,22 @@ number()
|
||||
}
|
||||
/* handle floats */
|
||||
/*NOSTRICT*/
|
||||
f= i1; dec=0.1;
|
||||
c++;
|
||||
while( isdigit(*c)){
|
||||
f= f + dec * (*c - '0');
|
||||
dec /= 10.0;
|
||||
c++;
|
||||
}
|
||||
/* handle exponential part */
|
||||
if( *c =='e' || *c == 'E'){
|
||||
c++;
|
||||
minflag= (*c== '-')? -1: 1;
|
||||
if( *c=='-' || *c=='+') c++;
|
||||
while(isdigit(*c)){
|
||||
f *= 10.0;
|
||||
c++;
|
||||
}
|
||||
if(minflag== -1) f= 1.0/f;
|
||||
}
|
||||
dval= f;
|
||||
cptr=c;
|
||||
cx = *c; *c = 0;
|
||||
dval = atof(cptr);
|
||||
*c = cx; cptr=c;
|
||||
#ifdef YYDEBUG
|
||||
if(yydebug) printf("number:FLTVALUE %f",f);
|
||||
if(yydebug) printf("number:FLTVALUE %f",dval);
|
||||
#endif
|
||||
return(FLTVALUE);
|
||||
}
|
||||
@@ -384,6 +385,9 @@ scanstring()
|
||||
if( firstchar == '"')
|
||||
error("non-terminated string");
|
||||
return(STRVALUE);
|
||||
case '\'':
|
||||
case '\\':
|
||||
putc('\\', emfile);
|
||||
default:
|
||||
fputc(*cptr,emfile);
|
||||
}
|
||||
@@ -445,7 +449,9 @@ yylex()
|
||||
return(yylex());
|
||||
case '&':
|
||||
return(readconstant());
|
||||
case '?': return(PRINTSYM);
|
||||
case '?':
|
||||
cptr++;
|
||||
return(PRINTSYM);
|
||||
case '>':
|
||||
if( *(c+1)=='='){
|
||||
c++;c++;cptr=c; yylval.integer= GESYM;return(RELOP);
|
||||
@@ -466,3 +472,13 @@ yylex()
|
||||
}
|
||||
return(*cptr++);
|
||||
}
|
||||
|
||||
char *
|
||||
index(s, c)
|
||||
register char *s, c;
|
||||
{
|
||||
while (*s)
|
||||
if (*s++ == c)
|
||||
return --s;
|
||||
return (char *)0;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
%token ERRSYM
|
||||
%token ERLSYM
|
||||
%token ERRORSYM
|
||||
%token ELSESYM
|
||||
%token FIELDSYM
|
||||
%token FORSYM
|
||||
%token <integer> FUNCTION
|
||||
@@ -353,8 +352,8 @@ format : USINGSYM STRVALUE ';' { loadstr($2);}
|
||||
| /* empty */ {formatstring=0;}
|
||||
|
||||
printlist: expression { printstmt($1); $$=1;}
|
||||
| ',' { zone(0); $$=0;}
|
||||
| ';' { zone(1); $$=0;}
|
||||
| ',' { zone(1); $$=0;}
|
||||
| ';' { zone(0); $$=0;}
|
||||
| printlist expression { printstmt($2); $$=1;}
|
||||
| printlist ',' { zone(1);$$=0;}
|
||||
| printlist ';' { zone(0);$$=0;}
|
||||
@@ -405,25 +404,31 @@ indexed : identifier '(' {newarrayload($1);}
|
||||
;
|
||||
|
||||
|
||||
expression: negation
|
||||
| negation BOOLOP expression {$$=boolop($1,$3,$2);}
|
||||
expression:
|
||||
negation
|
||||
| expression BOOLOP expression {$$=boolop($1,$3,$2);}
|
||||
;
|
||||
|
||||
negation: NOTSYM compare {$$=boolop($2,0,NOTSYM);}
|
||||
| compare
|
||||
;
|
||||
|
||||
compare : sum
|
||||
| sum RELOP sum {$$=relop($1,$3,$2);}
|
||||
| sum '=' sum {$$=relop($1,$3,'=');}
|
||||
;
|
||||
|
||||
sum : term
|
||||
| term '-' sum {$$=plusmin($1,$3,'-');}
|
||||
| term '+' sum {$$=plusmin($1,$3,'+');}
|
||||
| sum '-' sum {$$=plusmin($1,$3,'-');}
|
||||
| sum '+' sum {$$=plusmin($1,$3,'+');}
|
||||
;
|
||||
term : factor
|
||||
| factor '^' factor {$$=power($1,$3);}
|
||||
| factor '*' term {$$=muldiv($1,$3,'*');}
|
||||
| factor '\\' term {$$=muldiv($1,$3,'\\');}
|
||||
| factor '/' term {$$=muldiv($1,$3,'/');}
|
||||
| factor MODSYM term {$$=muldiv($1,$3,MODSYM);}
|
||||
| term '*' term {$$=muldiv($1,$3,'*');}
|
||||
| term '\\' term {$$=muldiv($1,$3,'\\');}
|
||||
| term '/' term {$$=muldiv($1,$3,'/');}
|
||||
| term MODSYM term {$$=muldiv($1,$3,MODSYM);}
|
||||
;
|
||||
factor : INTVALUE {$$=loadint(ival);}
|
||||
| '(' expression ')' {$$=$2;}
|
||||
| '-' factor { $$=negate($2);}
|
||||
@@ -440,7 +445,8 @@ factor : INTVALUE {$$=loadint(ival);}
|
||||
| funcname { $$=fcnend(0);}
|
||||
| funcname funccall ')' { $$=fcnend($2);}
|
||||
| MIDSYM '$' midparms
|
||||
{ emcode("cal","$_mid");
|
||||
{
|
||||
emcode("cal","$_mid");
|
||||
emcode("asp",EMINTSIZE);
|
||||
emcode("asp",EMINTSIZE);
|
||||
emcode("asp",EMPTRSIZE);
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
@@ -39,7 +43,11 @@ char **argv;
|
||||
/* compile source programs */
|
||||
compileprogram(program);
|
||||
linewarnings();
|
||||
if( errorcnt) exit(-1);
|
||||
if( errorcnt) {
|
||||
unlink(tmpfname);
|
||||
exit(-1);
|
||||
}
|
||||
/* process em object files */
|
||||
simpleprogram();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
@@ -36,7 +40,7 @@ extern char tmpfname[MAXFILENAME]; /* temporary statements file */
|
||||
|
||||
extern FILE *emfile; /* EM output file */
|
||||
extern FILE *datfile; /* data file */
|
||||
extern FILE *tmpfile; /* compiler temporary */
|
||||
extern FILE *Tmpfile; /* compiler temporary */
|
||||
extern FILE *yyin; /* Compiler input */
|
||||
|
||||
extern int endofinput;
|
||||
@@ -51,7 +55,7 @@ extern int threshold;
|
||||
extern int debug;
|
||||
extern int tronoff;
|
||||
|
||||
extern int emlinecount; /* counts lines on tmpfile */
|
||||
extern int emlinecount; /* counts lines on Tmpfile */
|
||||
extern int dataused;
|
||||
extern int typetable[10]; /* parameters to standard functions */
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
@@ -136,9 +140,9 @@ char *opcode;
|
||||
emcode(opcode,instrlabel(l1));
|
||||
emcode("loc",itoa(0));
|
||||
emcode("bra",instrlabel(l2));
|
||||
fprintf(tmpfile,"%d\n",l1); emlinecount++;
|
||||
fprintf(Tmpfile,"%d\n",l1); emlinecount++;
|
||||
emcode("loc",itoa(-1));
|
||||
fprintf(tmpfile,"%d\n",l2); emlinecount++;
|
||||
fprintf(Tmpfile,"%d\n",l2); emlinecount++;
|
||||
}
|
||||
relop( ltype,rtype,operator)
|
||||
int ltype,rtype,operator;
|
||||
@@ -292,10 +296,10 @@ loadptr(s)
|
||||
Symbol *s;
|
||||
{
|
||||
if( POINTERSIZE==WORDSIZE)
|
||||
fprintf(tmpfile," loe l%d\n",s->symalias);
|
||||
fprintf(Tmpfile," loe l%d\n",s->symalias);
|
||||
else
|
||||
if( POINTERSIZE== 2*WORDSIZE)
|
||||
fprintf(tmpfile," lde l%d\n",s->symalias);
|
||||
fprintf(Tmpfile," lde l%d\n",s->symalias);
|
||||
else error("loadptr:unexpected pointersize");
|
||||
}
|
||||
*/
|
||||
@@ -355,10 +359,10 @@ Symbol *s;
|
||||
else{
|
||||
j= -s->symalias;
|
||||
if(debug) printf("load parm %d\n",j);
|
||||
fprintf(tmpfile," lal ");
|
||||
fprintf(Tmpfile," lal ");
|
||||
for(i=fcn->dimensions;i>j;i--)
|
||||
fprintf(tmpfile,"%s+",typesize(fcn->dimlimit[i-1]));
|
||||
fprintf(tmpfile,"0\n");
|
||||
fprintf(Tmpfile,"%s+",typesize(fcn->dimlimit[i-1]));
|
||||
fprintf(Tmpfile,"0\n");
|
||||
emlinecount++;
|
||||
/*
|
||||
emcode("lal",datalabel(fcn->dimalias[-s->symalias]));
|
||||
@@ -424,7 +428,7 @@ int type;
|
||||
conversion(type,INTTYPE);
|
||||
dim--;
|
||||
/* first check index range */
|
||||
fprintf(tmpfile," lae r%d\n",s->dimalias[dim]);
|
||||
fprintf(Tmpfile," lae r%d\n",s->dimalias[dim]);
|
||||
emlinecount++;
|
||||
emcode("rck",EMINTSIZE);
|
||||
emcode("lae",datalabel(s->dimalias[dim]));
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
@@ -36,22 +40,25 @@ int blk1,blk2;
|
||||
{
|
||||
/* exchange assembler blocks */
|
||||
if(debug) printf("exchange %d %d %d\n",blk1,blk2,emlinecount);
|
||||
fprintf(tmpfile," exc %d,%d\n",blk2-blk1,emlinecount-blk2);
|
||||
fprintf(Tmpfile," exc %d,%d\n",blk2-blk1,emlinecount-blk2);
|
||||
emlinecount++;
|
||||
}
|
||||
|
||||
/* routines to manipulate the tmpfile */
|
||||
/* routines to manipulate the Tmpfile */
|
||||
int emlinecount; /* count number of lines generated */
|
||||
/* this value can be used to generate EXC */
|
||||
int tronoff=0;
|
||||
newemblock(nr)
|
||||
int nr;
|
||||
{
|
||||
/* save location on tmpfile */
|
||||
currline->offset= ftell(tmpfile);
|
||||
fprintf(tmpfile,"%d\n",currline->emlabel);
|
||||
fprintf(tmpfile," lin %d\n",nr);
|
||||
emlinecount += 2;
|
||||
/* save location on Tmpfile */
|
||||
currline->offset= ftell(Tmpfile);
|
||||
fprintf(Tmpfile,"%d\n",currline->emlabel);
|
||||
emlinecount++;
|
||||
if (! nolins) {
|
||||
fprintf(Tmpfile," lin %d\n",nr);
|
||||
emlinecount++;
|
||||
}
|
||||
if( tronoff || traceflag) {
|
||||
emcode("loc",itoa(nr));
|
||||
emcode("cal","$_trace");
|
||||
@@ -62,7 +69,7 @@ int nr;
|
||||
emcode(operation,params)
|
||||
char *operation,*params;
|
||||
{
|
||||
fprintf(tmpfile," %s %s\n",operation,params);
|
||||
fprintf(Tmpfile," %s %s\n",operation,params);
|
||||
emlinecount++;
|
||||
}
|
||||
/* Handle data statements */
|
||||
@@ -301,13 +308,13 @@ int elselab;
|
||||
|
||||
nr=genlabel();
|
||||
emcode("bra",instrlabel(nr));
|
||||
fprintf(tmpfile,"%d\n",elselab);
|
||||
fprintf(Tmpfile,"%d\n",elselab);
|
||||
emlinecount++;
|
||||
return(nr);
|
||||
}
|
||||
elsepart(lab)int lab;
|
||||
{
|
||||
fprintf(tmpfile,"%d\n",lab); emlinecount++;
|
||||
fprintf(Tmpfile,"%d\n",lab); emlinecount++;
|
||||
}
|
||||
/* generate code for the for-statement */
|
||||
#define MAXFORDEPTH 20
|
||||
@@ -422,7 +429,7 @@ int type;
|
||||
emcode("sti",typestring(result));
|
||||
emcode("bra",instrlabel(f->fortst));
|
||||
/* increment loop variable */
|
||||
fprintf(tmpfile,"%d\n",f->forinc);
|
||||
fprintf(Tmpfile,"%d\n",f->forinc);
|
||||
emlinecount++;
|
||||
emcode("lae",datalabel(varaddress));
|
||||
loadvar(result);
|
||||
@@ -434,7 +441,7 @@ int type;
|
||||
emcode("lae",datalabel(varaddress));
|
||||
emcode("sti",typestring(result));
|
||||
/* test boundary */
|
||||
fprintf(tmpfile,"%d\n",f->fortst);
|
||||
fprintf(Tmpfile,"%d\n",f->fortst);
|
||||
emlinecount++;
|
||||
emcode("lae",datalabel(varaddress));
|
||||
loadvar(result);
|
||||
@@ -454,7 +461,7 @@ Symbol *s;
|
||||
else{
|
||||
/* address of variable is on top of stack ! */
|
||||
emcode("bra",instrlabel(fortable[forcnt].forinc));
|
||||
fprintf(tmpfile,"%d\n",fortable[forcnt].forout);
|
||||
fprintf(Tmpfile,"%d\n",fortable[forcnt].forout);
|
||||
forcnt--;
|
||||
}
|
||||
}
|
||||
@@ -483,7 +490,7 @@ whilestart()
|
||||
newblock(-1);
|
||||
whilelabels[whilecnt][0]= currline->emlabel;
|
||||
whilelabels[whilecnt][1]= genlabel();
|
||||
fprintf(tmpfile,"%d\n", whilelabels[whilecnt][0]);
|
||||
fprintf(Tmpfile,"%d\n", whilelabels[whilecnt][0]);
|
||||
emlinecount++;
|
||||
}
|
||||
whiletst(exprtype)
|
||||
@@ -491,7 +498,7 @@ int exprtype;
|
||||
{
|
||||
/* test expression type */
|
||||
conversion(exprtype,INTTYPE);
|
||||
fprintf(tmpfile," zeq *%d\n",whilelabels[whilecnt][1]);
|
||||
fprintf(Tmpfile," zeq *%d\n",whilelabels[whilecnt][1]);
|
||||
emlinecount++;
|
||||
}
|
||||
wend()
|
||||
@@ -499,8 +506,8 @@ wend()
|
||||
if( whilecnt<1)
|
||||
error("not part of while statement");
|
||||
else{
|
||||
fprintf(tmpfile," bra *%d\n",whilelabels[whilecnt][0]);
|
||||
fprintf(tmpfile,"%d\n",whilelabels[whilecnt][1]);
|
||||
fprintf(Tmpfile," bra *%d\n",whilelabels[whilecnt][0]);
|
||||
fprintf(Tmpfile,"%d\n",whilelabels[whilecnt][1]);
|
||||
emlinecount++;
|
||||
emlinecount++;
|
||||
whilecnt--;
|
||||
@@ -517,9 +524,9 @@ prologcode()
|
||||
fprintf(emfile,"dummy1\n con 0,0,0,0\n");
|
||||
fprintf(emfile," exa _iomode\n_iomode\n rom \"O\"\n");
|
||||
fprintf(emfile," exa _errsym\n");
|
||||
fprintf(emfile,"_errsym\n bss 2,0,1\n");
|
||||
fprintf(emfile,"_errsym\n bss EM_WSIZE,0,1\n");
|
||||
fprintf(emfile," exa _erlsym\n");
|
||||
fprintf(emfile,"_erlsym\n bss 2,0,1\n");
|
||||
fprintf(emfile,"_erlsym\n bss EM_WSIZE,0,1\n");
|
||||
}
|
||||
|
||||
prolog2()
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
@@ -45,7 +49,7 @@ linewarnings()
|
||||
{
|
||||
if( !srchline(l->linenr))
|
||||
{
|
||||
printf("ERROR: line %d not defined\n",l->linenr);
|
||||
fprintf(stderr,"ERROR: line %d not defined\n",l->linenr);
|
||||
errorcnt++;
|
||||
}
|
||||
l=l->nextlist;
|
||||
@@ -78,8 +82,8 @@ int nr;
|
||||
/*NOSTRICT*/ l= (Linerecord *) salloc(sizeof(*l));
|
||||
l->emlabel= frwrd? frwrd->emlabel: genlabel();
|
||||
l->linenr= nr;
|
||||
/* save offset into tmpfile too */
|
||||
l->offset = (long) ftell(tmpfile);
|
||||
/* save offset into Tmpfile too */
|
||||
l->offset = (long) ftell(Tmpfile);
|
||||
l->codelines= emlinecount;
|
||||
|
||||
/* insert this record */
|
||||
@@ -163,7 +167,7 @@ int lab;
|
||||
emcode("cal","$_gosub"); /* administer legal return */
|
||||
emcode("asp",EMINTSIZE);
|
||||
emcode("bra",instrlabel(nr));
|
||||
fprintf(tmpfile,"%d\n",l->emlabel);
|
||||
fprintf(Tmpfile,"%d\n",l->emlabel);
|
||||
emlinecount++;
|
||||
}
|
||||
genreturns()
|
||||
@@ -185,7 +189,7 @@ returnstmt()
|
||||
{
|
||||
emcode("cal","$_retstmt"); /* ensure legal return*/
|
||||
emcode("lfr",EMINTSIZE);
|
||||
fprintf(tmpfile," lae returns\n");
|
||||
fprintf(Tmpfile," lae returns\n");
|
||||
emlinecount++;
|
||||
emcode("csa",EMINTSIZE);
|
||||
}
|
||||
@@ -219,12 +223,12 @@ int type;
|
||||
/* create descriptor first */
|
||||
descr= genlabel();
|
||||
firstlabel=genlabel();
|
||||
fprintf(tmpfile,"l%d\n",descr); emlinecount++;
|
||||
fprintf(tmpfile," rom *%d,1,%d\n",firstlabel,jumpcnt); emlinecount++;
|
||||
fprintf(Tmpfile,"l%d\n",descr); emlinecount++;
|
||||
fprintf(Tmpfile," rom *%d,1,%d\n",firstlabel,jumpcnt-1); emlinecount++;
|
||||
l= jumphead;
|
||||
while( l)
|
||||
{
|
||||
fprintf(tmpfile," rom *%d\n",l->emlabel); emlinecount++;
|
||||
fprintf(Tmpfile," rom *%d\n",l->emlabel); emlinecount++;
|
||||
l= l->nextlist;
|
||||
}
|
||||
jumphead= jumptail=0; jumpcnt=0;
|
||||
@@ -232,7 +236,7 @@ int type;
|
||||
conversion(type,INTTYPE);
|
||||
emcode("lae",datalabel(descr));
|
||||
emcode("csa",EMINTSIZE);
|
||||
fprintf(tmpfile,"%d\n",firstlabel); emlinecount++;
|
||||
fprintf(Tmpfile,"%d\n",firstlabel); emlinecount++;
|
||||
}
|
||||
ongosubstmt(type)
|
||||
int type;
|
||||
@@ -243,12 +247,12 @@ int type;
|
||||
/* create descriptor first */
|
||||
descr= genlabel();
|
||||
firstlabel=genlabel();
|
||||
fprintf(tmpfile,"l%d\n",descr); emlinecount++;
|
||||
fprintf(tmpfile," rom *%d,1,%d\n",firstlabel,jumpcnt); emlinecount++;
|
||||
fprintf(Tmpfile,"l%d\n",descr); emlinecount++;
|
||||
fprintf(Tmpfile," rom *%d,1,%d\n",firstlabel,jumpcnt-1); emlinecount++;
|
||||
l= jumphead;
|
||||
while( l)
|
||||
{
|
||||
fprintf(tmpfile," rom *%d\n",l->emlabel); emlinecount++;
|
||||
fprintf(Tmpfile," rom *%d\n",l->emlabel); emlinecount++;
|
||||
l= l->nextlist;
|
||||
}
|
||||
jumphead= jumptail=0; jumpcnt=0;
|
||||
@@ -269,7 +273,7 @@ int type;
|
||||
conversion(type,INTTYPE);
|
||||
emcode("lae",datalabel(descr));
|
||||
emcode("csa",EMINTSIZE);
|
||||
fprintf(tmpfile,"%d\n",firstlabel);
|
||||
fprintf(Tmpfile,"%d\n",firstlabel);
|
||||
emlinecount++;
|
||||
}
|
||||
|
||||
@@ -283,11 +287,11 @@ simpleprogram()
|
||||
/* a small EM programs has been found */
|
||||
prologcode();
|
||||
prolog2();
|
||||
(void) fclose(tmpfile);
|
||||
tmpfile= fopen(tmpfname,"r");
|
||||
if( tmpfile==NULL)
|
||||
(void) fclose(Tmpfile);
|
||||
Tmpfile= fopen(tmpfname,"r");
|
||||
if( Tmpfile==NULL)
|
||||
fatal("tmp file disappeared");
|
||||
while( (length=fread(buf,1,512,tmpfile)) != 0)
|
||||
while( (length=fread(buf,1,512,Tmpfile)) != 0)
|
||||
(void) fwrite(buf,1,length,emfile);
|
||||
epilogcode();
|
||||
(void) unlink(tmpfname);
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#
|
||||
|
||||
#ifndef NORCSID
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
#include <em_path.h>
|
||||
|
||||
@@ -8,7 +12,7 @@ static char rcs_id[] = "$Header$" ;
|
||||
/* generate temporary files etc */
|
||||
|
||||
FILE *emfile;
|
||||
FILE *tmpfile;
|
||||
FILE *Tmpfile;
|
||||
FILE *datfile;
|
||||
|
||||
initialize()
|
||||
@@ -35,8 +39,8 @@ initialize()
|
||||
strcat(datfname,".d");
|
||||
yyin= fopen(inpfile,"r");
|
||||
emfile= fopen(outfile,"w");
|
||||
tmpfile= fopen(tmpfname,"w");
|
||||
if( yyin==NULL || emfile== NULL || tmpfile== NULL )
|
||||
Tmpfile= fopen(tmpfname,"w");
|
||||
if( yyin==NULL || emfile== NULL || Tmpfile== NULL )
|
||||
fatal("Improper file permissions");
|
||||
fillkex(); /* initialize symbol table */
|
||||
fprintf(emfile,"#\n");
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
static char rcs_id[] = "$Header$" ;
|
||||
#endif
|
||||
|
||||
int listing; /* -l listing required */
|
||||
int listing; /* -E listing required */
|
||||
int debug; /* -d compiler debugging */
|
||||
int wflag=1; /* -w no warnings */
|
||||
int wflag=0; /* -w no warnings */
|
||||
int hflag=0; /* -h<number> to split EM program */
|
||||
int traceflag=0; /* generate line tracing code */
|
||||
int nolins=0; /* generate no LIN statements */
|
||||
int nolins=0; /* -l: generate no LIN statements */
|
||||
|
||||
parseparams(argc,argv)
|
||||
int argc;
|
||||
@@ -37,8 +41,9 @@ char **argv;
|
||||
threshold= THRESHOLD;
|
||||
break;
|
||||
case 'd': debug++; break;
|
||||
case 'l': nolins++; break; /* no EM lin statements */
|
||||
case 'L': nolins++; break; /* no EM lin statements */
|
||||
case 'E': listing++; break; /* generate full listing */
|
||||
case 'w': wflag++; break;
|
||||
} else {
|
||||
/* new input file */
|
||||
switch ( files++ ) {
|
||||
@@ -49,4 +54,5 @@ char **argv;
|
||||
default:fatal("Too many file arguments") ;
|
||||
}
|
||||
}
|
||||
if (files < 3) fatal("Too few file arguments");
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
@@ -196,8 +200,8 @@ fcnsize()
|
||||
/* generate portable function size */
|
||||
int i;
|
||||
for(i=0;i<fcn->dimensions;i++)
|
||||
fprintf(tmpfile,"%s+",typesize(fcn->dimlimit[i]));
|
||||
fprintf(tmpfile,"0\n"); emlinecount++;
|
||||
fprintf(Tmpfile,"%s+",typesize(fcn->dimlimit[i]));
|
||||
fprintf(Tmpfile,"0\n"); emlinecount++;
|
||||
}
|
||||
endscope(type)
|
||||
int type;
|
||||
@@ -208,7 +212,7 @@ int type;
|
||||
conversion(type,fcn->symtype);
|
||||
emcode("ret", typestring(fcn->symtype));
|
||||
/* generate portable EM code */
|
||||
fprintf(tmpfile," end ");
|
||||
fprintf(Tmpfile," end ");
|
||||
fcnsize();
|
||||
s= firstsym;
|
||||
while(s)
|
||||
@@ -267,9 +271,9 @@ int parmcount;
|
||||
error("not enough parameters");
|
||||
if( parmcount >fcn->dimensions)
|
||||
error("too many parameters");
|
||||
fprintf(tmpfile," cal $_%s\n",fcn->symname);
|
||||
fprintf(Tmpfile," cal $_%s\n",fcn->symname);
|
||||
emlinecount++;
|
||||
fprintf(tmpfile," asp ");
|
||||
fprintf(Tmpfile," asp ");
|
||||
fcnsize();
|
||||
emcode("lfr",typestring(fcn->symtype));
|
||||
type= fcn->symtype;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#ifndef NORCSID
|
||||
# define RCS_SYMB "$Header$"
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
@@ -12,29 +16,36 @@ int errorcnt;
|
||||
warning(str)
|
||||
char *str;
|
||||
{
|
||||
printf("WARNING:%s\n",str);
|
||||
if (! wflag) Xerror("WARNING",str);
|
||||
}
|
||||
error(str)
|
||||
char *str;
|
||||
{
|
||||
extern int listing,yylineno;
|
||||
if( !listing) printf("LINE %d:",yylineno);
|
||||
printf("ERROR:%s\n",str);
|
||||
Xerror("ERROR",str);
|
||||
errorcnt++;
|
||||
}
|
||||
Xerror(type,str)
|
||||
char *str;
|
||||
char *type;
|
||||
{
|
||||
extern int listing,yylineno;
|
||||
if( !listing) fprintf(stderr,"LINE %d:",yylineno);
|
||||
fprintf(stderr,"%s:%s\n",type,str);
|
||||
}
|
||||
fatal(str)
|
||||
char *str;
|
||||
{
|
||||
printf("FATAL:%s\n",str);
|
||||
Xerror("FATAL",str);
|
||||
unlink(tmpfname);
|
||||
exit(-1);
|
||||
}
|
||||
notyetimpl()
|
||||
{
|
||||
printf("WARNING: not yet implemented\n");
|
||||
warning("not yet implemented");
|
||||
}
|
||||
illegalcmd()
|
||||
{
|
||||
printf("WARNING: illegal command\n");
|
||||
warning("illegal command");
|
||||
}
|
||||
char *itoa(i)
|
||||
int i;
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "bem.h"
|
||||
|
||||
#ifndef NORSCID
|
||||
|
||||
100
lang/basic/test/.distr
Normal file
100
lang/basic/test/.distr
Normal file
@@ -0,0 +1,100 @@
|
||||
Makefile
|
||||
Out.std
|
||||
bull.b
|
||||
bull.b.g
|
||||
buzzword.b
|
||||
buzzword.b.g
|
||||
checker.b
|
||||
checker.b.g
|
||||
creator.b
|
||||
grafiek.b
|
||||
grafiek.b.g
|
||||
gunner.b
|
||||
gunner.b.g
|
||||
learn.b
|
||||
learn.b.g
|
||||
opg1.b
|
||||
opg1.b.g
|
||||
opg2.b
|
||||
opg2.b.g
|
||||
opg3.b
|
||||
opg3.b.g
|
||||
opg4.b
|
||||
opg4.b.g
|
||||
opg5.b
|
||||
opg5.b.g
|
||||
opg6.b
|
||||
opg6.b.g
|
||||
runcmp
|
||||
som4.b
|
||||
som4.b.g
|
||||
test01.b
|
||||
test01.b.g
|
||||
test02.b
|
||||
test02.b.g
|
||||
test03.b
|
||||
test03.b.g
|
||||
test04.b
|
||||
test04.b.g
|
||||
test05.b
|
||||
test05.b.g
|
||||
test06.b
|
||||
test06.b.g
|
||||
test07.b
|
||||
test07.b.g
|
||||
test08.b
|
||||
test08.b.g
|
||||
test09.b
|
||||
test09.b.g
|
||||
test10.b
|
||||
test10.b.g
|
||||
test11.b
|
||||
test11.b.g
|
||||
test12.b
|
||||
test12.b.g
|
||||
test13.b
|
||||
test13.b.g
|
||||
test14.b
|
||||
test14.b.g
|
||||
test15.b
|
||||
test15.b.g
|
||||
test16.b
|
||||
test16.b.g
|
||||
test17.b
|
||||
test17.b.g
|
||||
test18.b
|
||||
test18.b.g
|
||||
test19.b
|
||||
test19.b.g
|
||||
test20.b
|
||||
test20.b.g
|
||||
test21.b
|
||||
test21.b.g
|
||||
test22.b
|
||||
test22.b.g
|
||||
test23.b
|
||||
test23.b.g
|
||||
test24.b
|
||||
test24.b.g
|
||||
test25.b
|
||||
test25.b.g
|
||||
test26.b
|
||||
test26.b.g
|
||||
test27.b
|
||||
test27.b.g
|
||||
test28.b
|
||||
test28.b.g
|
||||
test29.b
|
||||
test29.b.g
|
||||
test30.b
|
||||
test30.b.g
|
||||
test31.b
|
||||
test31.b.g
|
||||
test32.b
|
||||
test32.b.g
|
||||
test33.b
|
||||
test33.b.g
|
||||
test34.b
|
||||
test35.b
|
||||
test35.b.g
|
||||
tst
|
||||
@@ -1,8 +1,7 @@
|
||||
for i in bull.b buzzword.b checker.b creator.b grafiek.b gunner.b learn.b opg1.b opg2.b opg3.b opg4.b opg5.b opg6.b som4.b test01.b test02.b test03.b test04.b test05.b test06.b test07.b test08.b test09.b test10.b test11.b test12.b test13.b test14.b test15.b test16.b test17.b test19.b test20.b test21.b test22.b test23.b test24.b test25.b test26.b test27.b test28.b test29.b test30.b test31.b test32.b test33.b test34.b test35.b ; do runcmp $i ; done
|
||||
bull.b ------- execution error(s)-*- Ok
|
||||
buzzword.b ------- execution error(s)-*- Ok
|
||||
checker.b FATAL:improper file creation permission
|
||||
------- compilation error(s)
|
||||
checker.b ------- execution error(s)-*- Ok
|
||||
creator.b Undefined:
|
||||
__inkey
|
||||
------- compilation error(s)
|
||||
@@ -25,7 +24,7 @@ test06.b -*- Ok
|
||||
test07.b ------- execution error(s)-*- Ok
|
||||
test08.b -*- Ok
|
||||
test09.b -*- Ok
|
||||
test10.b ------- execution error(s)-*- Ok
|
||||
test10.b -*- Ok
|
||||
test11.b -*- Ok
|
||||
test12.b -*- Ok
|
||||
test13.b -*- Ok
|
||||
@@ -36,12 +35,12 @@ test17.b ------- execution error(s)-*- Ok
|
||||
test19.b ------- execution error(s)-*- Ok
|
||||
test20.b -*- Ok
|
||||
test21.b -*- Ok
|
||||
test22.b -*- Ok
|
||||
test22.b ------- execution error(s)-*- Ok
|
||||
test23.b ------- execution error(s)-*- Ok
|
||||
test24.b -*- Ok
|
||||
test25.b -*- Ok
|
||||
test26.b -*- Ok
|
||||
test27.b -*- Ok
|
||||
test27.b ------- execution error(s)-*- Ok
|
||||
test28.b ------- execution error(s)-*- Ok
|
||||
test29.b -*- Ok
|
||||
test30.b ------- execution error(s)-*- Ok
|
||||
|
||||
@@ -5,8 +5,8 @@ acceptablewords to work into your material. The words
|
||||
don't actually mean anything, but they sound great.
|
||||
|
||||
the procedure:
|
||||
Think of any three numbers between 0 and 9, enter
|
||||
them after the '?' separated by commas. your
|
||||
buzzword will be printed out. Typing 100 for
|
||||
each of your choices stops this program.
|
||||
Think of any three numbers between 0 and 9, enter
|
||||
them after the '?' separated by commas. your
|
||||
buzzword will be printed out. Typing 100 for
|
||||
each of your choices stops this program.
|
||||
What are your three numbers?LINE 260:ERROR 2: Out of data
|
||||
|
||||
35
lang/basic/test/checker.b.g
Normal file
35
lang/basic/test/checker.b.g
Normal file
@@ -0,0 +1,35 @@
|
||||
This program will play checkers. The computer us X,
|
||||
and you are 0. The computer will go first, -note: squares
|
||||
are printed in the form-(X,Y) and sq. 1.1 is the bottom left!
|
||||
do not attempt a double jump or your piece might just
|
||||
disappear (same for triple!)
|
||||
Wait for the computer to move!!!!!!
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
|
||||
retry
|
||||
LINE 11300:ERROR 1: RETURN without GOSUB
|
||||
@@ -9,7 +9,7 @@ end the enemy will destroy you!
|
||||
|
||||
maximum range of your gun is 46500 yards.
|
||||
|
||||
distance to the target is 43000 yards....
|
||||
distance to the target is 42956 yards....
|
||||
|
||||
|
||||
elevation?LINE 410:ERROR 2: Out of data
|
||||
|
||||
@@ -1 +1 @@
|
||||
percent interest is 0.000173
|
||||
percent interest is 6.918919
|
||||
|
||||
@@ -4,15 +4,15 @@ fahrenheit centrigrade kelvin rankin
|
||||
|
||||
|
||||
|
||||
144 0.00496 273.00496 604
|
||||
36 0.138889 273.138889 496
|
||||
110 0.007123 273.007123 570
|
||||
98 0.008418 273.008418 558
|
||||
63 0.017921 273.017921 523
|
||||
26 -0.092593 272.907407 486
|
||||
14 -0.030864 272.969136 474
|
||||
78 0.012077 273.012077 538
|
||||
66 0.01634 273.01634 526
|
||||
51 0.02924 273.02924 511
|
||||
107 0.007407 273.007407 567
|
||||
2 -0.018519 272.981481 462
|
||||
144 62.222222 335.222222 604
|
||||
36 2.222222 275.222222 496
|
||||
110 43.333333 316.333333 570
|
||||
98 36.666667 309.666667 558
|
||||
63 17.222222 290.222222 523
|
||||
26 -3.333333 269.666667 486
|
||||
14 -10 263 474
|
||||
78 25.555556 298.555556 538
|
||||
66 18.888889 291.888889 526
|
||||
51 10.555556 283.555556 511
|
||||
107 41.666667 314.666667 567
|
||||
2 -16.666667 256.333333 462
|
||||
|
||||
@@ -2,4 +2,5 @@
|
||||
line130
|
||||
line140
|
||||
line150
|
||||
LINE 120:ERROR 1: RETURN without GOSUB
|
||||
4 end
|
||||
Break in 121
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
hello brave new world
|
||||
handicap
|
||||
try to read beyond
|
||||
<EFBFBD>
|
||||
LINE 70:ERROR 2: Out of data
|
||||
|
||||
@@ -9,8 +9,8 @@ chra 0
|
||||
cos 1 0.000796 -0.999999 0.540302
|
||||
sin 0 1 0.001593 -0.841471
|
||||
exp 1 4.806648 23.103867 0.367879
|
||||
hex0 10 ffff
|
||||
oct0 20 177777
|
||||
hex0 10 ffffffff
|
||||
oct0 20 37777777777
|
||||
len 0 3 1
|
||||
tan 0 1255.765592 -0.001593 -1.557408
|
||||
sqr 0 1.252996 1.772005
|
||||
|
||||
@@ -4,5 +4,4 @@
|
||||
160 true
|
||||
170 true
|
||||
yes or no
|
||||
? 0
|
||||
0
|
||||
?LINE 190:ERROR 2: Out of data
|
||||
|
||||
2
lang/basic/test/tst/.distr
Normal file
2
lang/basic/test/tst/.distr
Normal file
@@ -0,0 +1,2 @@
|
||||
data
|
||||
data1
|
||||
3
lang/cem/.distr
Normal file
3
lang/cem/.distr
Normal file
@@ -0,0 +1,3 @@
|
||||
cemcom
|
||||
ctest
|
||||
libcc
|
||||
88
lang/cem/cemcom/.distr
Normal file
88
lang/cem/cemcom/.distr
Normal file
@@ -0,0 +1,88 @@
|
||||
Version.c
|
||||
makefile
|
||||
Resolve
|
||||
nmclash.c
|
||||
LLlex.c
|
||||
LLlex.h
|
||||
LLmessage.c
|
||||
SmallPars
|
||||
BigPars
|
||||
align.h
|
||||
arith.c
|
||||
arith.h
|
||||
asm.c
|
||||
assert.h
|
||||
atw.h
|
||||
blocks.c
|
||||
cem.1
|
||||
cem.c
|
||||
cemcom.1
|
||||
ch7.c
|
||||
ch7bin.c
|
||||
ch7mon.c
|
||||
char.tab
|
||||
class.h
|
||||
code.c
|
||||
code.str
|
||||
conversion.c
|
||||
cstoper.c
|
||||
dataflow.c
|
||||
declar.g
|
||||
declar.str
|
||||
declarator.c
|
||||
decspecs.c
|
||||
decspecs.str
|
||||
def.str
|
||||
domacro.c
|
||||
dumpidf.c
|
||||
error.c
|
||||
estack.str
|
||||
eval.c
|
||||
expr.c
|
||||
expr.str
|
||||
expression.g
|
||||
faulty.h
|
||||
field.c
|
||||
field.str
|
||||
file_info.h
|
||||
idf.c
|
||||
idf.str
|
||||
init.c
|
||||
input.c
|
||||
input.h
|
||||
interface.h
|
||||
ival.g
|
||||
label.c
|
||||
label.h
|
||||
level.h
|
||||
macro.str
|
||||
main.c
|
||||
make.allocd
|
||||
make.hfiles
|
||||
make.next
|
||||
make.tokcase
|
||||
make.tokfile
|
||||
mcomm.c
|
||||
mes.h
|
||||
options
|
||||
options.c
|
||||
program.g
|
||||
replace.c
|
||||
scan.c
|
||||
sizes.h
|
||||
skip.c
|
||||
specials.h
|
||||
stack.c
|
||||
stack.str
|
||||
statement.g
|
||||
stb.c
|
||||
stmt.str
|
||||
struct.c
|
||||
struct.str
|
||||
switch.c
|
||||
switch.str
|
||||
tab.c
|
||||
tokenname.c
|
||||
tokenname.h
|
||||
type.c
|
||||
type.str
|
||||
131
lang/cem/cemcom/BigPars
Normal file
131
lang/cem/cemcom/BigPars
Normal file
@@ -0,0 +1,131 @@
|
||||
!File: pathlength.h
|
||||
#define PATHLENGTH 1024 /* max. length of path to file */
|
||||
|
||||
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define MAXERR_LINE 5 /* maximum number of error messages given
|
||||
on the same input line. */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 64 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: nparams.h
|
||||
#define NPARAMS 32 /* maximum number of parameters of macros */
|
||||
|
||||
|
||||
!File: ifdepth.h
|
||||
#define IFDEPTH 256 /* maximum number of nested if-constructions */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 2 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!File: lapbuf.h
|
||||
#define LAPBUF 4096 /* size of macro actual parameter buffer */
|
||||
|
||||
|
||||
!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
|
||||
#ifndef NOFLOAT
|
||||
#define SZ_FLOAT (arith)4
|
||||
#define SZ_DOUBLE (arith)8
|
||||
#endif NOFLOAT
|
||||
#define SZ_POINTER (arith)4
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT SZ_SHORT
|
||||
#define AL_WORD SZ_WORD
|
||||
#define AL_INT SZ_WORD
|
||||
#define AL_LONG SZ_WORD
|
||||
#ifndef NOFLOAT
|
||||
#define AL_FLOAT SZ_WORD
|
||||
#define AL_DOUBLE SZ_WORD
|
||||
#endif NOFLOAT
|
||||
#define AL_POINTER SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
#define AL_UNION 1
|
||||
|
||||
|
||||
!File: botch_free.h
|
||||
#undef BOTCH_FREE 1 /* when defined, botch freed memory, as a check */
|
||||
|
||||
|
||||
!File: dataflow.h
|
||||
#define DATAFLOW 1 /* produce some compile-time xref */
|
||||
|
||||
|
||||
!File: debug.h
|
||||
#undef DEBUG 1 /* perform various self-tests */
|
||||
|
||||
|
||||
!File: use_tmp.h
|
||||
#define USE_TMP 1 /* collect exa, exp, ina and inp commands
|
||||
and let them precede the rest of
|
||||
the generated compact code */
|
||||
|
||||
|
||||
!File: parbufsize.h
|
||||
#define PARBUFSIZE 1024
|
||||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 8 /* 1st piece of memory for repl. text */
|
||||
#define RTEXTSIZE 8 /* stepsize for enlarging repl.text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nopp.h
|
||||
#undef NOPP 1 /* if NOT defined, use built-int preprocessor */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
#undef NOBITFIELD 1 /* if NOT defined, implement bitfields */
|
||||
|
||||
|
||||
!File: spec_arith.h
|
||||
/* describes internal compiler arithmetics */
|
||||
#undef SPECIAL_ARITHMETICS /* something different from native long */
|
||||
|
||||
|
||||
!File: static.h
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
||||
!File: nofloat.h
|
||||
#undef NOFLOAT 1 /* if NOT defined, floats are implemented */
|
||||
|
||||
|
||||
!File: noRoption.h
|
||||
#undef NOROPTION 1 /* if NOT defined, R option is implemented */
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
#undef NOCROSS 1 /* if NOT defined, cross compiler */
|
||||
|
||||
|
||||
88
lang/cem/cemcom/Files
Normal file
88
lang/cem/cemcom/Files
Normal file
@@ -0,0 +1,88 @@
|
||||
Files
|
||||
cem.1
|
||||
cem.c
|
||||
cemcom.1
|
||||
Parameters
|
||||
Makefile
|
||||
LLlex.c
|
||||
LLlex.h
|
||||
LLmessage.c
|
||||
align.h
|
||||
alloc.c
|
||||
alloc.h
|
||||
arith.c
|
||||
arith.h
|
||||
asm.c
|
||||
assert.h
|
||||
atw.h
|
||||
blocks.c
|
||||
char.tab
|
||||
ch7.c
|
||||
ch7bin.c
|
||||
ch7mon.c
|
||||
class.h
|
||||
code.c
|
||||
code.str
|
||||
conversion.c
|
||||
cstoper.c
|
||||
dataflow.c
|
||||
declar.g
|
||||
declarator.c
|
||||
declar.str
|
||||
decspecs.c
|
||||
decspecs.str
|
||||
def.str
|
||||
domacro.c
|
||||
dumpidf.c
|
||||
error.c
|
||||
eval.c
|
||||
expr.c
|
||||
expr.str
|
||||
expression.g
|
||||
faulty.h
|
||||
field.c
|
||||
field.str
|
||||
file_info.h
|
||||
idf.c
|
||||
idf.str
|
||||
init.c
|
||||
input.c
|
||||
input.h
|
||||
interface.h
|
||||
ival.c
|
||||
label.c
|
||||
label.h
|
||||
level.h
|
||||
macro.str
|
||||
main.c
|
||||
make.allocd
|
||||
make.hfiles
|
||||
make.next
|
||||
make.tokcase
|
||||
make.tokfile
|
||||
mcomm.c
|
||||
mes.h
|
||||
options
|
||||
options.c
|
||||
program.g
|
||||
replace.c
|
||||
scan.c
|
||||
sizes.h
|
||||
skip.c
|
||||
specials.h
|
||||
stack.c
|
||||
stack.str
|
||||
statement.g
|
||||
stb.c
|
||||
storage.c
|
||||
storage.h
|
||||
stmt.str
|
||||
struct.c
|
||||
struct.str
|
||||
switch.c
|
||||
switch.str
|
||||
tab.c
|
||||
tokenname.c
|
||||
tokenname.h
|
||||
type.c
|
||||
type.str
|
||||
577
lang/cem/cemcom/LLlex.c
Normal file
577
lang/cem/cemcom/LLlex.c
Normal file
@@ -0,0 +1,577 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* L E X I C A L A N A L Y Z E R */
|
||||
|
||||
#include <alloc.h>
|
||||
#include "nofloat.h"
|
||||
#include "idfsize.h"
|
||||
#include "numsize.h"
|
||||
#include "debug.h"
|
||||
#include "strsize.h"
|
||||
#include "nopp.h"
|
||||
#include "input.h"
|
||||
#include "arith.h"
|
||||
#include "def.h"
|
||||
#include "idf.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "class.h"
|
||||
#include "assert.h"
|
||||
#include "sizes.h"
|
||||
|
||||
/* Data about the token yielded */
|
||||
struct token dot, ahead, aside;
|
||||
|
||||
#ifndef NOPP
|
||||
int ReplaceMacros = 1; /* replacing macros */
|
||||
int PreProcKeys = 0; /* return preprocessor key */
|
||||
int AccDefined = 0; /* accept "defined(...)" */
|
||||
int UnknownIdIsZero = 0; /* interpret unknown id as integer 0 */
|
||||
int Unstacked = 0; /* an unstack is done */
|
||||
#endif
|
||||
int SkipEscNewline = 0; /* how to interpret backslash-newline */
|
||||
int AccFileSpecifier = 0; /* return filespecifier <...> */
|
||||
int EoiForNewline = 0; /* return EOI upon encountering newline */
|
||||
int File_Inserted = 0; /* a file has just been inserted */
|
||||
|
||||
#define MAX_LL_DEPTH 2
|
||||
|
||||
static struct token LexStack[MAX_LL_DEPTH];
|
||||
static LexSP = 0;
|
||||
|
||||
/* In PushLex() the actions are taken in order to initialise or
|
||||
re-initialise the lexical scanner.
|
||||
E.g. at the invocation of a sub-parser that uses LLlex(), the
|
||||
state of the current parser should be saved.
|
||||
*/
|
||||
PushLex()
|
||||
{
|
||||
ASSERT(LexSP < 2);
|
||||
ASSERT(ASIDE == 0); /* ASIDE = 0; */
|
||||
GetToken(&ahead);
|
||||
ahead.tk_line = LineNumber;
|
||||
ahead.tk_file = FileName;
|
||||
LexStack[LexSP++] = dot;
|
||||
}
|
||||
|
||||
PopLex()
|
||||
{
|
||||
ASSERT(LexSP > 0);
|
||||
dot = LexStack[--LexSP];
|
||||
}
|
||||
|
||||
int
|
||||
LLlex()
|
||||
{
|
||||
/* LLlex() plays the role of Lexical Analyzer for the C parser.
|
||||
The look-ahead and putting aside of tokens are taken into
|
||||
account.
|
||||
*/
|
||||
if (ASIDE) { /* a token is put aside */
|
||||
dot = aside;
|
||||
ASIDE = 0;
|
||||
}
|
||||
else { /* read ahead and return the old one */
|
||||
dot = ahead;
|
||||
/* the following test is performed due to the dual
|
||||
task of LLlex(): it is also called for parsing the
|
||||
restricted constant expression following a #if or
|
||||
#elif. The newline character causes EOF to be
|
||||
returned in this case to stop the LLgen parsing task.
|
||||
*/
|
||||
if (DOT != EOI)
|
||||
GetToken(&ahead);
|
||||
else
|
||||
DOT = EOF;
|
||||
}
|
||||
/* keep track of the place of the token in the file */
|
||||
ahead.tk_file = FileName;
|
||||
ahead.tk_line = LineNumber;
|
||||
return DOT;
|
||||
}
|
||||
|
||||
char *string_token();
|
||||
|
||||
int
|
||||
GetToken(ptok)
|
||||
register struct token *ptok;
|
||||
{
|
||||
/* GetToken() is the actual token recognizer. It calls the
|
||||
control line interpreter if it encounters a "\n#"
|
||||
combination. Macro replacement is also performed if it is
|
||||
needed.
|
||||
*/
|
||||
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
|
||||
register int ch, nch;
|
||||
|
||||
if (File_Inserted) {
|
||||
File_Inserted = 0;
|
||||
goto firstline;
|
||||
}
|
||||
again: /* rescan the input after an error or replacement */
|
||||
#ifndef NOPP
|
||||
if (Unstacked) EnableMacros();
|
||||
#endif
|
||||
LoadChar(ch);
|
||||
go_on: /* rescan, the following character has been read */
|
||||
if ((ch & 0200) && ch != EOI) /* stop on non-ascii character */
|
||||
fatal("non-ascii '\\%03o' read", ch & 0377);
|
||||
switch (class(ch)) { /* detect character class */
|
||||
case STNL: /* newline, vertical space or formfeed */
|
||||
firstline:
|
||||
LineNumber++; /* also at vs and ff */
|
||||
if (EoiForNewline) /* called in control line */
|
||||
/* a newline in a control line indicates the
|
||||
end-of-information of the line.
|
||||
*/
|
||||
return ptok->tk_symb = EOI;
|
||||
while (LoadChar(ch), ch == '#') { /* a control line follows */
|
||||
domacro();
|
||||
if (File_Inserted) {
|
||||
File_Inserted = 0;
|
||||
goto firstline;
|
||||
}
|
||||
}
|
||||
/* We have to loop here, because in
|
||||
`domacro' the nl, vt or ff is read. The
|
||||
character following it may again be a `#'.
|
||||
*/
|
||||
goto go_on;
|
||||
case STSKIP: /* just skip the skip characters */
|
||||
goto again;
|
||||
case STGARB: /* garbage character */
|
||||
#ifndef NOPP
|
||||
if (SkipEscNewline && (ch == '\\')) {
|
||||
/* a '\\' is allowed in #if/#elif expression */
|
||||
LoadChar(ch);
|
||||
if (class(ch) == STNL) { /* vt , ff ? */
|
||||
++LineNumber;
|
||||
goto again;
|
||||
}
|
||||
PushBack();
|
||||
ch = '\\';
|
||||
}
|
||||
#endif NOPP
|
||||
if (040 < ch && ch < 0177)
|
||||
lexerror("garbage char %c", ch);
|
||||
else
|
||||
lexerror("garbage char \\%03o", ch);
|
||||
goto again;
|
||||
case STSIMP: /* a simple character, no part of compound token*/
|
||||
if (ch == '/') { /* probably the start of comment */
|
||||
LoadChar(ch);
|
||||
if (ch == '*') { /* start of comment */
|
||||
skipcomment();
|
||||
goto again;
|
||||
}
|
||||
else {
|
||||
PushBack();
|
||||
ch = '/'; /* restore ch */
|
||||
}
|
||||
}
|
||||
return ptok->tk_symb = ch;
|
||||
case STCOMP: /* maybe the start of a compound token */
|
||||
LoadChar(nch); /* character lookahead */
|
||||
switch (ch) {
|
||||
case '!':
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = NOTEQUAL;
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
case '&':
|
||||
if (nch == '&')
|
||||
return ptok->tk_symb = AND;
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
case '+':
|
||||
if (nch == '+')
|
||||
return ptok->tk_symb = PLUSPLUS;
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
case '-':
|
||||
if (nch == '-')
|
||||
return ptok->tk_symb = MINMIN;
|
||||
if (nch == '>')
|
||||
return ptok->tk_symb = ARROW;
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
case '<':
|
||||
if (AccFileSpecifier) {
|
||||
PushBack(); /* pushback nch */
|
||||
ptok->tk_bts = string_token("file specifier",
|
||||
'>', &(ptok->tk_len));
|
||||
return ptok->tk_symb = FILESPECIFIER;
|
||||
}
|
||||
if (nch == '<')
|
||||
return ptok->tk_symb = LEFT;
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = LESSEQ;
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
case '=':
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = EQUAL;
|
||||
/* The following piece of code tries to recognise
|
||||
old-fashioned assignment operators `=op'
|
||||
*/
|
||||
switch (nch) {
|
||||
case '+':
|
||||
return ptok->tk_symb = PLUSAB;
|
||||
case '-':
|
||||
return ptok->tk_symb = MINAB;
|
||||
case '*':
|
||||
return ptok->tk_symb = TIMESAB;
|
||||
case '/':
|
||||
return ptok->tk_symb = DIVAB;
|
||||
case '%':
|
||||
return ptok->tk_symb = MODAB;
|
||||
case '>':
|
||||
case '<':
|
||||
LoadChar(ch);
|
||||
if (ch != nch) {
|
||||
PushBack();
|
||||
lexerror("illegal combination '=%c'",
|
||||
nch);
|
||||
}
|
||||
return ptok->tk_symb =
|
||||
nch == '<' ? LEFTAB : RIGHTAB;
|
||||
case '&':
|
||||
return ptok->tk_symb = ANDAB;
|
||||
case '^':
|
||||
return ptok->tk_symb = XORAB;
|
||||
case '|':
|
||||
return ptok->tk_symb = ORAB;
|
||||
}
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
case '>':
|
||||
if (nch == '=')
|
||||
return ptok->tk_symb = GREATEREQ;
|
||||
if (nch == '>')
|
||||
return ptok->tk_symb = RIGHT;
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
case '|':
|
||||
if (nch == '|')
|
||||
return ptok->tk_symb = OR;
|
||||
PushBack();
|
||||
return ptok->tk_symb = ch;
|
||||
}
|
||||
case STIDF:
|
||||
{
|
||||
register char *tg = &buf[0];
|
||||
register int pos = -1;
|
||||
register int hash;
|
||||
register struct idf *idef;
|
||||
extern int idfsize; /* ??? */
|
||||
|
||||
hash = STARTHASH();
|
||||
do { /* read the identifier */
|
||||
if (++pos < idfsize) {
|
||||
#ifndef NOPP
|
||||
if (Unstacked) EnableMacros();
|
||||
#endif
|
||||
*tg++ = ch;
|
||||
hash = ENHASH(hash, ch, pos);
|
||||
}
|
||||
LoadChar(ch);
|
||||
} while (in_idf(ch));
|
||||
hash = STOPHASH(hash);
|
||||
if (ch != EOI)
|
||||
PushBack();
|
||||
*tg++ = '\0'; /* mark the end of the identifier */
|
||||
idef = ptok->tk_idf = idf_hashed(buf, tg - buf, hash);
|
||||
#ifndef NOPP
|
||||
if (idef->id_macro && ReplaceMacros && replace(idef))
|
||||
/* macro replacement should be performed */
|
||||
goto again;
|
||||
if (UnknownIdIsZero && idef->id_reserved != SIZEOF) {
|
||||
ptok->tk_ival = (arith)0;
|
||||
ptok->tk_fund = INT;
|
||||
return ptok->tk_symb = INTEGER;
|
||||
}
|
||||
#endif NOPP
|
||||
ptok->tk_symb = (
|
||||
idef->id_reserved ? idef->id_reserved
|
||||
: idef->id_def && idef->id_def->df_sc == TYPEDEF ?
|
||||
TYPE_IDENTIFIER
|
||||
: IDENTIFIER
|
||||
);
|
||||
return IDENTIFIER;
|
||||
}
|
||||
case STCHAR: /* character constant */
|
||||
{
|
||||
register arith val = 0, size = 0;
|
||||
|
||||
LoadChar(ch);
|
||||
if (ch == '\'')
|
||||
lexerror("character constant too short");
|
||||
else
|
||||
while (ch != '\'') {
|
||||
if (ch == '\n') {
|
||||
lexerror("newline in character constant");
|
||||
LineNumber++;
|
||||
break;
|
||||
}
|
||||
if (ch == '\\') {
|
||||
LoadChar(ch);
|
||||
if (ch == '\n')
|
||||
LineNumber++;
|
||||
ch = quoted(ch);
|
||||
}
|
||||
if (ch >= 128) ch -= 256;
|
||||
val = val*256 + ch;
|
||||
size++;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (size > int_size)
|
||||
lexerror("character constant too long");
|
||||
ptok->tk_ival = val;
|
||||
ptok->tk_fund = INT;
|
||||
return ptok->tk_symb = INTEGER;
|
||||
}
|
||||
case STSTR: /* string */
|
||||
ptok->tk_bts = string_token("string", '"', &(ptok->tk_len));
|
||||
return ptok->tk_symb = STRING;
|
||||
case STNUM: /* a numeric constant */
|
||||
{
|
||||
/* It should be noted that 099 means 81(decimal) and
|
||||
099.5 means 99.5 . This severely limits the tricks
|
||||
we can use to scan a numeric value.
|
||||
*/
|
||||
register char *np = &buf[1];
|
||||
register int base = 10;
|
||||
register int vch;
|
||||
register arith val = 0;
|
||||
|
||||
if (ch == '.') { /* an embarrassing ambiguity */
|
||||
#ifndef NOFLOAT
|
||||
LoadChar(vch);
|
||||
PushBack();
|
||||
if (!is_dig(vch)) /* just a `.' */
|
||||
return ptok->tk_symb = ch;
|
||||
*np++ = '0';
|
||||
/* in the rest of the compiler, all floats
|
||||
have to start with a digit.
|
||||
*/
|
||||
#else NOFLOAT
|
||||
return ptok->tk_symb = ch;
|
||||
#endif NOFLOAT
|
||||
}
|
||||
if (ch == '0') {
|
||||
*np++ = ch;
|
||||
LoadChar(ch);
|
||||
if (ch == 'x' || ch == 'X') {
|
||||
base = 16;
|
||||
LoadChar(ch);
|
||||
}
|
||||
else
|
||||
base = 8;
|
||||
}
|
||||
while (vch = val_in_base(ch, base), vch >= 0) {
|
||||
val = val*base + vch;
|
||||
if (np < &buf[NUMSIZE])
|
||||
*np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (ch == 'l' || ch == 'L') {
|
||||
ptok->tk_ival = val;
|
||||
ptok->tk_fund = LONG;
|
||||
return ptok->tk_symb = INTEGER;
|
||||
}
|
||||
#ifndef NOFLOAT
|
||||
if (base == 16 || !(ch == '.' || ch == 'e' || ch == 'E'))
|
||||
#endif NOFLOAT
|
||||
{
|
||||
PushBack();
|
||||
ptok->tk_ival = val;
|
||||
/* The semantic analyser must know if the
|
||||
integral constant is given in octal/hexa-
|
||||
decimal form, in which case its type is
|
||||
UNSIGNED, or in decimal form, in which case
|
||||
its type is signed, indicated by
|
||||
the fund INTEGER.
|
||||
*/
|
||||
ptok->tk_fund =
|
||||
(base == 10 || (base == 8 && val == (arith)0))
|
||||
? INTEGER : UNSIGNED;
|
||||
return ptok->tk_symb = INTEGER;
|
||||
}
|
||||
/* where's the test for the length of the integral ??? */
|
||||
#ifndef NOFLOAT
|
||||
if (ch == '.'){
|
||||
if (np < &buf[NUMSIZE])
|
||||
*np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
while (is_dig(ch)){
|
||||
if (np < &buf[NUMSIZE])
|
||||
*np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (ch == 'e' || ch == 'E') {
|
||||
if (np < &buf[NUMSIZE])
|
||||
*np++ = ch;
|
||||
LoadChar(ch);
|
||||
if (ch == '+' || ch == '-') {
|
||||
if (np < &buf[NUMSIZE])
|
||||
*np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
if (!is_dig(ch)) {
|
||||
lexerror("malformed floating constant");
|
||||
if (np < &buf[NUMSIZE])
|
||||
*np++ = ch;
|
||||
}
|
||||
while (is_dig(ch)) {
|
||||
if (np < &buf[NUMSIZE])
|
||||
*np++ = ch;
|
||||
LoadChar(ch);
|
||||
}
|
||||
}
|
||||
PushBack();
|
||||
*np++ = '\0';
|
||||
buf[0] = '-'; /* good heavens... */
|
||||
if (np == &buf[NUMSIZE+1]) {
|
||||
lexerror("floating constant too long");
|
||||
ptok->tk_fval = Salloc("0.0",(unsigned) 5) + 1;
|
||||
}
|
||||
else
|
||||
ptok->tk_fval = Salloc(buf,(unsigned) (np - buf)) + 1;
|
||||
return ptok->tk_symb = FLOATING;
|
||||
#endif NOFLOAT
|
||||
}
|
||||
case STEOI: /* end of text on source file */
|
||||
return ptok->tk_symb = EOI;
|
||||
default: /* this cannot happen */
|
||||
crash("bad class for char 0%o", ch);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
skipcomment()
|
||||
{
|
||||
/* The last character read has been the '*' of '/_*'. The
|
||||
characters, except NL and EOI, between '/_*' and the first
|
||||
occurring '*_/' are not interpreted.
|
||||
NL only affects the LineNumber. EOI is not legal.
|
||||
|
||||
Important note: it is not possible to stop skipping comment
|
||||
beyond the end-of-file of an included file.
|
||||
EOI is returned by LoadChar only on encountering EOF of the
|
||||
top-level file...
|
||||
*/
|
||||
register int c;
|
||||
|
||||
NoUnstack++;
|
||||
LoadChar(c);
|
||||
do {
|
||||
while (c != '*') {
|
||||
if (class(c) == STNL)
|
||||
++LineNumber;
|
||||
else
|
||||
if (c == EOI) {
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
LoadChar(c);
|
||||
} /* last Character seen was '*' */
|
||||
LoadChar(c);
|
||||
} while (c != '/');
|
||||
NoUnstack--;
|
||||
}
|
||||
|
||||
char *
|
||||
string_token(nm, stop_char, plen)
|
||||
char *nm;
|
||||
int *plen;
|
||||
{
|
||||
register int ch;
|
||||
register int str_size;
|
||||
register char *str = Malloc((unsigned) (str_size = ISTRSIZE));
|
||||
register int pos = 0;
|
||||
|
||||
LoadChar(ch);
|
||||
while (ch != stop_char) {
|
||||
if (ch == '\n') {
|
||||
lexerror("newline in %s", nm);
|
||||
LineNumber++;
|
||||
break;
|
||||
}
|
||||
if (ch == EOI) {
|
||||
lexerror("end-of-file inside %s", nm);
|
||||
break;
|
||||
}
|
||||
if (ch == '\\') {
|
||||
LoadChar(ch);
|
||||
if (ch == '\n') {
|
||||
LineNumber++;
|
||||
LoadChar(ch);
|
||||
continue;
|
||||
}
|
||||
ch = quoted(ch);
|
||||
}
|
||||
str[pos++] = ch;
|
||||
if (pos == str_size)
|
||||
str = Srealloc(str, (unsigned) (str_size += RSTRSIZE));
|
||||
LoadChar(ch);
|
||||
}
|
||||
str[pos++] = '\0'; /* for filenames etc. */
|
||||
*plen = pos;
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
quoted(ch)
|
||||
register int ch;
|
||||
{
|
||||
/* quoted() replaces an escaped character sequence by the
|
||||
character meant.
|
||||
*/
|
||||
/* first char after backslash already in ch */
|
||||
if (!is_oct(ch)) { /* a quoted char */
|
||||
switch (ch) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
else { /* a quoted octal */
|
||||
register int oct = 0, cnt = 0;
|
||||
|
||||
do {
|
||||
oct = oct*8 + (ch-'0');
|
||||
LoadChar(ch);
|
||||
} while (is_oct(ch) && ++cnt < 3);
|
||||
PushBack();
|
||||
ch = oct;
|
||||
}
|
||||
return ch&0377;
|
||||
}
|
||||
|
||||
/* provisional */
|
||||
int
|
||||
val_in_base(ch, base)
|
||||
register int ch;
|
||||
{
|
||||
return
|
||||
is_dig(ch) ? ch - '0'
|
||||
: base != 16 ? -1
|
||||
: is_hex(ch) ? (ch - 'a' + 10) & 017
|
||||
: -1;
|
||||
}
|
||||
72
lang/cem/cemcom/LLlex.h
Normal file
72
lang/cem/cemcom/LLlex.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* D E F I N I T I O N S F O R T H E L E X I C A L A N A L Y Z E R */
|
||||
|
||||
/* A token from the input stream is represented by an integer,
|
||||
called a "symbol", but it may have other information associated
|
||||
to it.
|
||||
*/
|
||||
|
||||
#include "nofloat.h"
|
||||
#include "file_info.h"
|
||||
#include "nopp.h"
|
||||
|
||||
/* the structure of a token: */
|
||||
struct token {
|
||||
int tok_symb; /* the token itself */
|
||||
char *tok_file; /* the file it (probably) comes from */
|
||||
unsigned int tok_line; /* the line it (probably) comes from */
|
||||
union {
|
||||
struct idf *tok_idf; /* for IDENTIFIER & TYPE_IDENTIFIER */
|
||||
struct { /* for STRING */
|
||||
char *tok_bts; /* row of bytes */
|
||||
int tok_len; /* length of row of bytes */
|
||||
} tok_string;
|
||||
struct { /* for INTEGER */
|
||||
int tok_fund; /* INT or LONG */
|
||||
arith tok_ival;
|
||||
} tok_integer;
|
||||
#ifndef NOFLOAT
|
||||
char *tok_fval;
|
||||
#endif NOFLOAT
|
||||
} tok_data;
|
||||
};
|
||||
|
||||
#define tk_symb tok_symb
|
||||
#define tk_file tok_file
|
||||
#define tk_line tok_line
|
||||
#define tk_idf tok_data.tok_idf
|
||||
#define tk_bts tok_data.tok_string.tok_bts
|
||||
#define tk_len tok_data.tok_string.tok_len
|
||||
#define tk_fund tok_data.tok_integer.tok_fund
|
||||
#define tk_ival tok_data.tok_integer.tok_ival
|
||||
#ifndef NOFLOAT
|
||||
#define tk_fval tok_data.tok_fval
|
||||
#endif NOFLOAT
|
||||
|
||||
extern struct token dot, ahead, aside;
|
||||
|
||||
#ifndef NOPP
|
||||
extern int ReplaceMacros; /* "LLlex.c" */
|
||||
extern int PreProcKeys; /* "LLlex.c" */
|
||||
extern int AccDefined; /* "LLlex.c" */
|
||||
extern int Unstacked; /* "LLlex.c" */
|
||||
extern int UnknownIdIsZero; /* "LLlex.c" */
|
||||
#endif NOPP
|
||||
extern int EoiForNewline; /* "LLlex.c" */
|
||||
extern int AccFileSpecifier; /* "LLlex.c" */
|
||||
extern int SkipEscNewline; /* "LLlex.c" */
|
||||
extern int File_Inserted; /* "LLlex.c" */
|
||||
|
||||
extern int NoUnstack; /* buffer.c */
|
||||
|
||||
extern int err_occurred; /* "error.c" */
|
||||
|
||||
#define DOT dot.tk_symb
|
||||
#define AHEAD ahead.tk_symb
|
||||
#define ASIDE aside.tk_symb
|
||||
|
||||
#define EOF (-1)
|
||||
59
lang/cem/cemcom/LLmessage.c
Normal file
59
lang/cem/cemcom/LLmessage.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* PARSER ERROR ADMINISTRATION */
|
||||
|
||||
#include <alloc.h>
|
||||
#include "nofloat.h"
|
||||
#include "idf.h"
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
extern char *symbol2str();
|
||||
|
||||
LLmessage(tk) {
|
||||
err_occurred = 1;
|
||||
if (tk < 0) {
|
||||
error("end of file expected");
|
||||
}
|
||||
else if (tk) {
|
||||
error("%s missing", symbol2str(tk));
|
||||
insert_token(tk);
|
||||
}
|
||||
else
|
||||
error("%s deleted", symbol2str(DOT));
|
||||
}
|
||||
|
||||
insert_token(tk)
|
||||
int tk;
|
||||
{
|
||||
aside = dot;
|
||||
|
||||
DOT = tk;
|
||||
|
||||
switch (tk) {
|
||||
/* The operands need some body */
|
||||
case IDENTIFIER:
|
||||
dot.tk_idf = gen_idf();
|
||||
break;
|
||||
case TYPE_IDENTIFIER:
|
||||
dot.tk_idf = str2idf("int");
|
||||
break;
|
||||
case STRING:
|
||||
dot.tk_bts = Salloc("", 1);
|
||||
dot.tk_len = 1;
|
||||
break;
|
||||
case INTEGER:
|
||||
dot.tk_fund = INT;
|
||||
dot.tk_ival = 1;
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case FLOATING:
|
||||
dot.tk_fval = Salloc("0.0", 4);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
}
|
||||
}
|
||||
796
lang/cem/cemcom/Makefile
Normal file
796
lang/cem/cemcom/Makefile
Normal file
@@ -0,0 +1,796 @@
|
||||
# $Header$
|
||||
# M A K E F I L E F O R A C K C - C O M P I L E R
|
||||
|
||||
# Machine and environ dependent definitions
|
||||
EMHOME = ../../..
|
||||
MKDEP = $(EMHOME)/bin/mkdep
|
||||
PRID = $(EMHOME)/bin/prid
|
||||
CID = $(EMHOME)/bin/cid
|
||||
|
||||
# Libraries and EM interface definitions
|
||||
SYSLIB = $(EMHOME)/modules/lib/libsystem.a
|
||||
EMKLIB = $(EMHOME)/modules/lib/libemk.a
|
||||
EMELIB = $(EMHOME)/modules/lib/libeme.a
|
||||
STRLIB = $(EMHOME)/modules/lib/libstring.a
|
||||
PRTLIB = $(EMHOME)/modules/lib/libprint.a
|
||||
EMMESLIB = $(EMHOME)/modules/lib/libem_mes.a
|
||||
INPLIB = $(EMHOME)/modules/lib/libinput.a
|
||||
ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a
|
||||
MALLOC = $(EMHOME)/modules/lib/malloc.o
|
||||
LIBS = $(INPLIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) \
|
||||
$(ALLOCLIB) $(MALLOC) $(SYSLIB)
|
||||
ELIBS = $(INPLIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) \
|
||||
$(ALLOCLIB) $(MALLOC) $(SYSLIB)
|
||||
LIB_INCLUDES = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg
|
||||
EM_INCLUDES = -I$(EMHOME)/h
|
||||
SYSLLIB = $(EMHOME)/modules/lib/llib-lsystem.ln
|
||||
EMKLLIB = $(EMHOME)/modules/lib/llib-lemk.ln
|
||||
EMELLIB = $(EMHOME)/modules/lib/llib-leme.ln
|
||||
STRLLIB = $(EMHOME)/modules/lib/llib-lstring.ln
|
||||
PRTLLIB = $(EMHOME)/modules/lib/llib-lprint.ln
|
||||
EMMESLLIB = $(EMHOME)/modules/lib/llib-lem_mes.ln
|
||||
INPLLIB = $(EMHOME)/modules/lib/llib-linput.ln
|
||||
ALLOCLLIB = $(EMHOME)/modules/lib/llib-lalloc.ln
|
||||
#LINTLIBS =
|
||||
LINTLIBS = $(EMMESLLIB) $(EMKLLIB) $(PRTLLIB) $(STRLLIB) $(ALLOCLLIB) $(SYSLLIB)
|
||||
CURRDIR = .
|
||||
|
||||
COPTIONS =
|
||||
|
||||
# What parser generator to use and how
|
||||
GEN = $(EMHOME)/bin/LLgen
|
||||
GENOPTIONS = -v
|
||||
|
||||
# Special #defines during compilation
|
||||
CDEFS = $(EM_INCLUDES) $(LIB_INCLUDES)
|
||||
CFLAGS = $(CDEFS) $(COPTIONS) -O
|
||||
LDFLAGS = -i
|
||||
|
||||
# Grammar files and their objects
|
||||
LSRC = tokenfile.g declar.g statement.g expression.g program.g ival.g
|
||||
LCSRC = tokenfile.c declar.c statement.c expression.c program.c Lpars.c ival.c
|
||||
LOBJ = tokenfile.o declar.o statement.o expression.o program.o Lpars.o ival.o
|
||||
|
||||
# Objects of hand-written C files
|
||||
CSRC = main.c idf.c declarator.c decspecs.c struct.c \
|
||||
expr.c ch7.c ch7bin.c cstoper.c arith.c \
|
||||
asm.c code.c dumpidf.c error.c field.c\
|
||||
tokenname.c LLlex.c LLmessage.c \
|
||||
input.c domacro.c replace.c init.c options.c \
|
||||
scan.c skip.c stack.c type.c ch7mon.c label.c eval.c \
|
||||
switch.c conversion.c util.c \
|
||||
blocks.c dataflow.c Version.c
|
||||
COBJ = main.o idf.o declarator.o decspecs.o struct.o \
|
||||
expr.o ch7.o ch7bin.o cstoper.o arith.o \
|
||||
asm.o code.o dumpidf.o error.o field.o\
|
||||
tokenname.o LLlex.o LLmessage.o \
|
||||
input.o domacro.o replace.o init.o options.o \
|
||||
scan.o skip.o stack.o type.o ch7mon.o label.o eval.o \
|
||||
switch.o conversion.o util.o \
|
||||
blocks.o dataflow.o Version.o
|
||||
|
||||
# Objects of other generated C files
|
||||
GCSRC = char.c symbol2str.c next.c
|
||||
GOBJ = char.o symbol2str.o next.o
|
||||
|
||||
STRSRC = code.str declar.str decspecs.str def.str expr.str field.str \
|
||||
estack.str util.str \
|
||||
idf.str macro.str stack.str stmt.str struct.str switch.str type.str
|
||||
# generated source files
|
||||
GHSTRSRC = code.h declar.h decspecs.h def.h expr.h field.h \
|
||||
estack.h util.h \
|
||||
idf.h macro.h stack.h stmt.h struct.h switch.h type.h
|
||||
GSRC = $(GCSRC) $(GHSTRSRC)
|
||||
|
||||
# .h files generated by `make hfiles LLfiles'; PLEASE KEEP THIS UP-TO-DATE!
|
||||
GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \
|
||||
idfsize.h ifdepth.h inputtype.h lapbuf.h \
|
||||
nobitfield.h nofloat.h nopp.h noRoption.h nocross.h \
|
||||
nparams.h numsize.h parbufsize.h pathlength.h Lpars.h \
|
||||
strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h
|
||||
|
||||
HSRC = LLlex.h align.h arith.h assert.h atw.h class.h faulty.h \
|
||||
input.h interface.h label.h level.h mes.h sizes.h specials.h \
|
||||
file_info.h tokenname.h
|
||||
|
||||
HFILES = $(HSRC) $(GHSRC) $(GHSTRSRC)
|
||||
|
||||
# generated files, for 'make clean' only
|
||||
GENERATED = tab tokenfile.g Lpars.h LLfiles LL.output lint.out \
|
||||
print hfiles Cfiles $(GHSRC) $(GSRC) longnames $(LCSRC)
|
||||
|
||||
# include files containing ALLOCDEF specifications
|
||||
OBJ = $(COBJ) $(LOBJ) $(GOBJ)
|
||||
SRC = $(CSRC) $(LCSRC) $(GCSRC)
|
||||
|
||||
#EXCLEXCLEXCLEXCL
|
||||
|
||||
.SUFFIXES: .str .h
|
||||
.str.h:
|
||||
./make.allocd <$*.str >$*.h
|
||||
|
||||
Main: Cfiles
|
||||
sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) $(CURRDIR)/main ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve main ; fi'
|
||||
@rm -f nmclash.o a.out
|
||||
|
||||
Emain: Cfiles
|
||||
sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) $(CURRDIR)/emain ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve emain ; fi'
|
||||
@rm -f nmclash.o a.out
|
||||
|
||||
install: Main
|
||||
rm -f $(EMHOME)/lib/em_cemcom $(EMHOME)/man/em_cemcom.6
|
||||
cp $(CURRDIR)/main $(EMHOME)/lib/em_cemcom
|
||||
cp $(CURRDIR)/cemcom.1 $(EMHOME)/man/em_cemcom.6
|
||||
|
||||
cmp: Main
|
||||
-cmp $(CURRDIR)/main $(EMHOME)/lib/em_cemcom
|
||||
-cmp $(CURRDIR)/cemcom.1 $(EMHOME)/man/em_cemcom.6
|
||||
|
||||
pr:
|
||||
@pr makefile make.* tab.c char.tab Parameters $(HSRC) $(STRSRC) $(LSRC) $(CSRC)
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(GENERATED) main
|
||||
(cd .. ; rm -rf Xsrc)
|
||||
|
||||
lint: Cfiles
|
||||
sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) Xlint ; else sh Resolve Xlint ; fi'
|
||||
@rm -f nmclash.o a.out
|
||||
|
||||
longnames: $(SRC) $(HFILES)
|
||||
sh -c 'if test -f longnames ; then : ; else touch longnames ; fi ; $(PRID) -l7 longnames $? > Xlongnames ; mv Xlongnames longnames'
|
||||
|
||||
# entry points not to be used directly
|
||||
|
||||
Cfiles: hfiles LLfiles $(GENCFILES) $(GSRC) $(GHSRC) makefile
|
||||
echo $(SRC) $(HFILES) > Cfiles
|
||||
|
||||
hfiles: ./make.hfiles Parameters
|
||||
./make.hfiles Parameters
|
||||
@touch hfiles
|
||||
|
||||
LLfiles: $(LSRC)
|
||||
$(GEN) $(GENOPTIONS) $(LSRC)
|
||||
@touch LLfiles
|
||||
|
||||
tokenfile.g: tokenname.c make.tokfile
|
||||
<tokenname.c ./make.tokfile >tokenfile.g
|
||||
|
||||
symbol2str.c: tokenname.c make.tokcase
|
||||
<tokenname.c ./make.tokcase >symbol2str.c
|
||||
|
||||
char.c: tab char.tab
|
||||
tab -fchar.tab >char.c
|
||||
|
||||
tab:
|
||||
$(CC) tab.c -o tab
|
||||
|
||||
next.c: make.next $(STRSRC)
|
||||
./make.next $(STRSRC) >next.c
|
||||
|
||||
code.h: make.allocd
|
||||
declar.h: make.allocd
|
||||
decspecs.h: make.allocd
|
||||
def.h: make.allocd
|
||||
expr.h: make.allocd
|
||||
field.h: make.allocd
|
||||
idf.h: make.allocd
|
||||
macro.h: make.allocd
|
||||
stack.h: make.allocd
|
||||
stmt.h: make.allocd
|
||||
struct.h: make.allocd
|
||||
switch.h: make.allocd
|
||||
type.h: make.allocd
|
||||
estack.h: make.allocd
|
||||
util.h: make.allocd
|
||||
|
||||
depend: Cfiles
|
||||
sed '/^#AUTOAUTO/,$$d' makefile >makefile.new
|
||||
echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >>makefile.new
|
||||
$(MKDEP) $(SRC) | sed 's/\.c:/.o:/' >>makefile.new
|
||||
mv makefile makefile.old
|
||||
mv makefile.new makefile
|
||||
|
||||
#INCLINCLINCLINCL
|
||||
|
||||
$(CURRDIR)/main: $(OBJ) $(CURRDIR)/makefile
|
||||
$(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(LIBS) -o $(CURRDIR)/main
|
||||
size $(CURRDIR)/main
|
||||
|
||||
$(CURRDIR)/emain: $(OBJ) $(CURRDIR)/makefile
|
||||
$(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(ELIBS) -o $(CURRDIR)/emain
|
||||
size $(CURRDIR)/emain
|
||||
|
||||
Xlint:
|
||||
lint $(CDEFS) $(LINTFLAGS) $(SRC)
|
||||
|
||||
#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
|
||||
main.o: LLlex.h
|
||||
main.o: Lpars.h
|
||||
main.o: align.h
|
||||
main.o: arith.h
|
||||
main.o: debug.h
|
||||
main.o: declar.h
|
||||
main.o: file_info.h
|
||||
main.o: idf.h
|
||||
main.o: input.h
|
||||
main.o: inputtype.h
|
||||
main.o: level.h
|
||||
main.o: noRoption.h
|
||||
main.o: nobitfield.h
|
||||
main.o: nocross.h
|
||||
main.o: nofloat.h
|
||||
main.o: nopp.h
|
||||
main.o: sizes.h
|
||||
main.o: spec_arith.h
|
||||
main.o: specials.h
|
||||
main.o: target_sizes.h
|
||||
main.o: tokenname.h
|
||||
main.o: type.h
|
||||
main.o: use_tmp.h
|
||||
idf.o: LLlex.h
|
||||
idf.o: Lpars.h
|
||||
idf.o: align.h
|
||||
idf.o: arith.h
|
||||
idf.o: assert.h
|
||||
idf.o: botch_free.h
|
||||
idf.o: debug.h
|
||||
idf.o: declar.h
|
||||
idf.o: decspecs.h
|
||||
idf.o: def.h
|
||||
idf.o: file_info.h
|
||||
idf.o: idf.h
|
||||
idf.o: idfsize.h
|
||||
idf.o: label.h
|
||||
idf.o: level.h
|
||||
idf.o: noRoption.h
|
||||
idf.o: nobitfield.h
|
||||
idf.o: nocross.h
|
||||
idf.o: nofloat.h
|
||||
idf.o: nopp.h
|
||||
idf.o: sizes.h
|
||||
idf.o: spec_arith.h
|
||||
idf.o: specials.h
|
||||
idf.o: stack.h
|
||||
idf.o: struct.h
|
||||
idf.o: target_sizes.h
|
||||
idf.o: type.h
|
||||
declarator.o: Lpars.h
|
||||
declarator.o: arith.h
|
||||
declarator.o: botch_free.h
|
||||
declarator.o: declar.h
|
||||
declarator.o: expr.h
|
||||
declarator.o: idf.h
|
||||
declarator.o: label.h
|
||||
declarator.o: nobitfield.h
|
||||
declarator.o: nocross.h
|
||||
declarator.o: nofloat.h
|
||||
declarator.o: nopp.h
|
||||
declarator.o: sizes.h
|
||||
declarator.o: spec_arith.h
|
||||
declarator.o: target_sizes.h
|
||||
declarator.o: type.h
|
||||
decspecs.o: Lpars.h
|
||||
decspecs.o: arith.h
|
||||
decspecs.o: decspecs.h
|
||||
decspecs.o: def.h
|
||||
decspecs.o: level.h
|
||||
decspecs.o: noRoption.h
|
||||
decspecs.o: nobitfield.h
|
||||
decspecs.o: nofloat.h
|
||||
decspecs.o: spec_arith.h
|
||||
decspecs.o: type.h
|
||||
struct.o: LLlex.h
|
||||
struct.o: Lpars.h
|
||||
struct.o: align.h
|
||||
struct.o: arith.h
|
||||
struct.o: assert.h
|
||||
struct.o: botch_free.h
|
||||
struct.o: debug.h
|
||||
struct.o: def.h
|
||||
struct.o: field.h
|
||||
struct.o: file_info.h
|
||||
struct.o: idf.h
|
||||
struct.o: level.h
|
||||
struct.o: noRoption.h
|
||||
struct.o: nobitfield.h
|
||||
struct.o: nocross.h
|
||||
struct.o: nofloat.h
|
||||
struct.o: nopp.h
|
||||
struct.o: sizes.h
|
||||
struct.o: spec_arith.h
|
||||
struct.o: stack.h
|
||||
struct.o: struct.h
|
||||
struct.o: target_sizes.h
|
||||
struct.o: type.h
|
||||
expr.o: LLlex.h
|
||||
expr.o: Lpars.h
|
||||
expr.o: arith.h
|
||||
expr.o: botch_free.h
|
||||
expr.o: declar.h
|
||||
expr.o: decspecs.h
|
||||
expr.o: def.h
|
||||
expr.o: expr.h
|
||||
expr.o: file_info.h
|
||||
expr.o: idf.h
|
||||
expr.o: label.h
|
||||
expr.o: level.h
|
||||
expr.o: noRoption.h
|
||||
expr.o: nobitfield.h
|
||||
expr.o: nocross.h
|
||||
expr.o: nofloat.h
|
||||
expr.o: nopp.h
|
||||
expr.o: sizes.h
|
||||
expr.o: spec_arith.h
|
||||
expr.o: target_sizes.h
|
||||
expr.o: type.h
|
||||
ch7.o: Lpars.h
|
||||
ch7.o: arith.h
|
||||
ch7.o: assert.h
|
||||
ch7.o: debug.h
|
||||
ch7.o: def.h
|
||||
ch7.o: expr.h
|
||||
ch7.o: idf.h
|
||||
ch7.o: label.h
|
||||
ch7.o: nobitfield.h
|
||||
ch7.o: nofloat.h
|
||||
ch7.o: nopp.h
|
||||
ch7.o: spec_arith.h
|
||||
ch7.o: struct.h
|
||||
ch7.o: type.h
|
||||
ch7bin.o: Lpars.h
|
||||
ch7bin.o: arith.h
|
||||
ch7bin.o: botch_free.h
|
||||
ch7bin.o: expr.h
|
||||
ch7bin.o: idf.h
|
||||
ch7bin.o: label.h
|
||||
ch7bin.o: noRoption.h
|
||||
ch7bin.o: nobitfield.h
|
||||
ch7bin.o: nofloat.h
|
||||
ch7bin.o: nopp.h
|
||||
ch7bin.o: spec_arith.h
|
||||
ch7bin.o: struct.h
|
||||
ch7bin.o: type.h
|
||||
cstoper.o: Lpars.h
|
||||
cstoper.o: arith.h
|
||||
cstoper.o: assert.h
|
||||
cstoper.o: debug.h
|
||||
cstoper.o: expr.h
|
||||
cstoper.o: idf.h
|
||||
cstoper.o: label.h
|
||||
cstoper.o: nobitfield.h
|
||||
cstoper.o: nocross.h
|
||||
cstoper.o: nofloat.h
|
||||
cstoper.o: nopp.h
|
||||
cstoper.o: sizes.h
|
||||
cstoper.o: spec_arith.h
|
||||
cstoper.o: target_sizes.h
|
||||
cstoper.o: type.h
|
||||
arith.o: Lpars.h
|
||||
arith.o: arith.h
|
||||
arith.o: botch_free.h
|
||||
arith.o: expr.h
|
||||
arith.o: field.h
|
||||
arith.o: idf.h
|
||||
arith.o: label.h
|
||||
arith.o: mes.h
|
||||
arith.o: noRoption.h
|
||||
arith.o: nobitfield.h
|
||||
arith.o: nofloat.h
|
||||
arith.o: nopp.h
|
||||
arith.o: spec_arith.h
|
||||
arith.o: type.h
|
||||
code.o: LLlex.h
|
||||
code.o: Lpars.h
|
||||
code.o: align.h
|
||||
code.o: arith.h
|
||||
code.o: assert.h
|
||||
code.o: atw.h
|
||||
code.o: botch_free.h
|
||||
code.o: code.h
|
||||
code.o: dataflow.h
|
||||
code.o: debug.h
|
||||
code.o: declar.h
|
||||
code.o: decspecs.h
|
||||
code.o: def.h
|
||||
code.o: expr.h
|
||||
code.o: file_info.h
|
||||
code.o: idf.h
|
||||
code.o: label.h
|
||||
code.o: level.h
|
||||
code.o: mes.h
|
||||
code.o: noRoption.h
|
||||
code.o: nobitfield.h
|
||||
code.o: nocross.h
|
||||
code.o: nofloat.h
|
||||
code.o: nopp.h
|
||||
code.o: sizes.h
|
||||
code.o: spec_arith.h
|
||||
code.o: specials.h
|
||||
code.o: stack.h
|
||||
code.o: stmt.h
|
||||
code.o: target_sizes.h
|
||||
code.o: type.h
|
||||
code.o: use_tmp.h
|
||||
dumpidf.o: Lpars.h
|
||||
dumpidf.o: arith.h
|
||||
dumpidf.o: debug.h
|
||||
dumpidf.o: def.h
|
||||
dumpidf.o: expr.h
|
||||
dumpidf.o: field.h
|
||||
dumpidf.o: idf.h
|
||||
dumpidf.o: label.h
|
||||
dumpidf.o: nobitfield.h
|
||||
dumpidf.o: nofloat.h
|
||||
dumpidf.o: nopp.h
|
||||
dumpidf.o: spec_arith.h
|
||||
dumpidf.o: stack.h
|
||||
dumpidf.o: static.h
|
||||
dumpidf.o: struct.h
|
||||
dumpidf.o: type.h
|
||||
error.o: LLlex.h
|
||||
error.o: arith.h
|
||||
error.o: debug.h
|
||||
error.o: errout.h
|
||||
error.o: expr.h
|
||||
error.o: file_info.h
|
||||
error.o: label.h
|
||||
error.o: nofloat.h
|
||||
error.o: nopp.h
|
||||
error.o: spec_arith.h
|
||||
error.o: tokenname.h
|
||||
field.o: Lpars.h
|
||||
field.o: align.h
|
||||
field.o: arith.h
|
||||
field.o: assert.h
|
||||
field.o: code.h
|
||||
field.o: debug.h
|
||||
field.o: expr.h
|
||||
field.o: field.h
|
||||
field.o: idf.h
|
||||
field.o: label.h
|
||||
field.o: nobitfield.h
|
||||
field.o: nocross.h
|
||||
field.o: nofloat.h
|
||||
field.o: nopp.h
|
||||
field.o: sizes.h
|
||||
field.o: spec_arith.h
|
||||
field.o: target_sizes.h
|
||||
field.o: type.h
|
||||
tokenname.o: LLlex.h
|
||||
tokenname.o: Lpars.h
|
||||
tokenname.o: arith.h
|
||||
tokenname.o: file_info.h
|
||||
tokenname.o: idf.h
|
||||
tokenname.o: nofloat.h
|
||||
tokenname.o: nopp.h
|
||||
tokenname.o: spec_arith.h
|
||||
tokenname.o: tokenname.h
|
||||
LLlex.o: LLlex.h
|
||||
LLlex.o: Lpars.h
|
||||
LLlex.o: arith.h
|
||||
LLlex.o: assert.h
|
||||
LLlex.o: class.h
|
||||
LLlex.o: debug.h
|
||||
LLlex.o: def.h
|
||||
LLlex.o: file_info.h
|
||||
LLlex.o: idf.h
|
||||
LLlex.o: idfsize.h
|
||||
LLlex.o: input.h
|
||||
LLlex.o: nocross.h
|
||||
LLlex.o: nofloat.h
|
||||
LLlex.o: nopp.h
|
||||
LLlex.o: numsize.h
|
||||
LLlex.o: sizes.h
|
||||
LLlex.o: spec_arith.h
|
||||
LLlex.o: strsize.h
|
||||
LLlex.o: target_sizes.h
|
||||
LLmessage.o: LLlex.h
|
||||
LLmessage.o: Lpars.h
|
||||
LLmessage.o: arith.h
|
||||
LLmessage.o: file_info.h
|
||||
LLmessage.o: idf.h
|
||||
LLmessage.o: nofloat.h
|
||||
LLmessage.o: nopp.h
|
||||
LLmessage.o: spec_arith.h
|
||||
input.o: file_info.h
|
||||
input.o: input.h
|
||||
input.o: inputtype.h
|
||||
input.o: nopp.h
|
||||
domacro.o: LLlex.h
|
||||
domacro.o: Lpars.h
|
||||
domacro.o: arith.h
|
||||
domacro.o: assert.h
|
||||
domacro.o: botch_free.h
|
||||
domacro.o: class.h
|
||||
domacro.o: debug.h
|
||||
domacro.o: file_info.h
|
||||
domacro.o: idf.h
|
||||
domacro.o: idfsize.h
|
||||
domacro.o: ifdepth.h
|
||||
domacro.o: input.h
|
||||
domacro.o: interface.h
|
||||
domacro.o: macro.h
|
||||
domacro.o: nofloat.h
|
||||
domacro.o: nopp.h
|
||||
domacro.o: nparams.h
|
||||
domacro.o: parbufsize.h
|
||||
domacro.o: spec_arith.h
|
||||
domacro.o: textsize.h
|
||||
replace.o: LLlex.h
|
||||
replace.o: arith.h
|
||||
replace.o: assert.h
|
||||
replace.o: class.h
|
||||
replace.o: debug.h
|
||||
replace.o: file_info.h
|
||||
replace.o: idf.h
|
||||
replace.o: input.h
|
||||
replace.o: interface.h
|
||||
replace.o: macro.h
|
||||
replace.o: nofloat.h
|
||||
replace.o: nopp.h
|
||||
replace.o: pathlength.h
|
||||
replace.o: spec_arith.h
|
||||
replace.o: static.h
|
||||
replace.o: strsize.h
|
||||
init.o: class.h
|
||||
init.o: idf.h
|
||||
init.o: interface.h
|
||||
init.o: macro.h
|
||||
init.o: nopp.h
|
||||
options.o: align.h
|
||||
options.o: arith.h
|
||||
options.o: botch_free.h
|
||||
options.o: class.h
|
||||
options.o: dataflow.h
|
||||
options.o: idf.h
|
||||
options.o: idfsize.h
|
||||
options.o: macro.h
|
||||
options.o: noRoption.h
|
||||
options.o: nobitfield.h
|
||||
options.o: nocross.h
|
||||
options.o: nofloat.h
|
||||
options.o: nopp.h
|
||||
options.o: sizes.h
|
||||
options.o: spec_arith.h
|
||||
options.o: target_sizes.h
|
||||
options.o: use_tmp.h
|
||||
scan.o: class.h
|
||||
scan.o: idf.h
|
||||
scan.o: input.h
|
||||
scan.o: interface.h
|
||||
scan.o: lapbuf.h
|
||||
scan.o: macro.h
|
||||
scan.o: nopp.h
|
||||
scan.o: nparams.h
|
||||
skip.o: LLlex.h
|
||||
skip.o: arith.h
|
||||
skip.o: class.h
|
||||
skip.o: file_info.h
|
||||
skip.o: input.h
|
||||
skip.o: interface.h
|
||||
skip.o: nofloat.h
|
||||
skip.o: nopp.h
|
||||
skip.o: spec_arith.h
|
||||
stack.o: Lpars.h
|
||||
stack.o: arith.h
|
||||
stack.o: botch_free.h
|
||||
stack.o: debug.h
|
||||
stack.o: def.h
|
||||
stack.o: idf.h
|
||||
stack.o: level.h
|
||||
stack.o: mes.h
|
||||
stack.o: noRoption.h
|
||||
stack.o: nobitfield.h
|
||||
stack.o: nofloat.h
|
||||
stack.o: nopp.h
|
||||
stack.o: spec_arith.h
|
||||
stack.o: stack.h
|
||||
stack.o: struct.h
|
||||
stack.o: type.h
|
||||
type.o: Lpars.h
|
||||
type.o: align.h
|
||||
type.o: arith.h
|
||||
type.o: botch_free.h
|
||||
type.o: def.h
|
||||
type.o: idf.h
|
||||
type.o: nobitfield.h
|
||||
type.o: nocross.h
|
||||
type.o: nofloat.h
|
||||
type.o: nopp.h
|
||||
type.o: sizes.h
|
||||
type.o: spec_arith.h
|
||||
type.o: target_sizes.h
|
||||
type.o: type.h
|
||||
ch7mon.o: Lpars.h
|
||||
ch7mon.o: arith.h
|
||||
ch7mon.o: botch_free.h
|
||||
ch7mon.o: def.h
|
||||
ch7mon.o: expr.h
|
||||
ch7mon.o: idf.h
|
||||
ch7mon.o: label.h
|
||||
ch7mon.o: nobitfield.h
|
||||
ch7mon.o: nofloat.h
|
||||
ch7mon.o: nopp.h
|
||||
ch7mon.o: spec_arith.h
|
||||
ch7mon.o: type.h
|
||||
label.o: Lpars.h
|
||||
label.o: arith.h
|
||||
label.o: def.h
|
||||
label.o: idf.h
|
||||
label.o: label.h
|
||||
label.o: level.h
|
||||
label.o: noRoption.h
|
||||
label.o: nobitfield.h
|
||||
label.o: nofloat.h
|
||||
label.o: nopp.h
|
||||
label.o: spec_arith.h
|
||||
label.o: type.h
|
||||
eval.o: Lpars.h
|
||||
eval.o: align.h
|
||||
eval.o: arith.h
|
||||
eval.o: assert.h
|
||||
eval.o: atw.h
|
||||
eval.o: code.h
|
||||
eval.o: dataflow.h
|
||||
eval.o: debug.h
|
||||
eval.o: def.h
|
||||
eval.o: expr.h
|
||||
eval.o: idf.h
|
||||
eval.o: label.h
|
||||
eval.o: level.h
|
||||
eval.o: mes.h
|
||||
eval.o: nobitfield.h
|
||||
eval.o: nocross.h
|
||||
eval.o: nofloat.h
|
||||
eval.o: nopp.h
|
||||
eval.o: sizes.h
|
||||
eval.o: spec_arith.h
|
||||
eval.o: stack.h
|
||||
eval.o: target_sizes.h
|
||||
eval.o: type.h
|
||||
switch.o: Lpars.h
|
||||
switch.o: arith.h
|
||||
switch.o: assert.h
|
||||
switch.o: botch_free.h
|
||||
switch.o: code.h
|
||||
switch.o: debug.h
|
||||
switch.o: density.h
|
||||
switch.o: expr.h
|
||||
switch.o: idf.h
|
||||
switch.o: label.h
|
||||
switch.o: noRoption.h
|
||||
switch.o: nobitfield.h
|
||||
switch.o: nofloat.h
|
||||
switch.o: nopp.h
|
||||
switch.o: spec_arith.h
|
||||
switch.o: switch.h
|
||||
switch.o: type.h
|
||||
conversion.o: Lpars.h
|
||||
conversion.o: arith.h
|
||||
conversion.o: nobitfield.h
|
||||
conversion.o: nocross.h
|
||||
conversion.o: nofloat.h
|
||||
conversion.o: sizes.h
|
||||
conversion.o: spec_arith.h
|
||||
conversion.o: target_sizes.h
|
||||
conversion.o: type.h
|
||||
util.o: align.h
|
||||
util.o: nocross.h
|
||||
util.o: nofloat.h
|
||||
util.o: sizes.h
|
||||
util.o: stack.h
|
||||
util.o: target_sizes.h
|
||||
util.o: use_tmp.h
|
||||
util.o: util.h
|
||||
blocks.o: align.h
|
||||
blocks.o: arith.h
|
||||
blocks.o: atw.h
|
||||
blocks.o: label.h
|
||||
blocks.o: nocross.h
|
||||
blocks.o: nofloat.h
|
||||
blocks.o: sizes.h
|
||||
blocks.o: spec_arith.h
|
||||
blocks.o: stack.h
|
||||
blocks.o: target_sizes.h
|
||||
dataflow.o: dataflow.h
|
||||
tokenfile.o: Lpars.h
|
||||
declar.o: LLlex.h
|
||||
declar.o: Lpars.h
|
||||
declar.o: arith.h
|
||||
declar.o: debug.h
|
||||
declar.o: declar.h
|
||||
declar.o: decspecs.h
|
||||
declar.o: def.h
|
||||
declar.o: expr.h
|
||||
declar.o: field.h
|
||||
declar.o: file_info.h
|
||||
declar.o: idf.h
|
||||
declar.o: label.h
|
||||
declar.o: level.h
|
||||
declar.o: nobitfield.h
|
||||
declar.o: nocross.h
|
||||
declar.o: nofloat.h
|
||||
declar.o: nopp.h
|
||||
declar.o: sizes.h
|
||||
declar.o: spec_arith.h
|
||||
declar.o: struct.h
|
||||
declar.o: target_sizes.h
|
||||
declar.o: type.h
|
||||
statement.o: LLlex.h
|
||||
statement.o: Lpars.h
|
||||
statement.o: arith.h
|
||||
statement.o: botch_free.h
|
||||
statement.o: code.h
|
||||
statement.o: debug.h
|
||||
statement.o: def.h
|
||||
statement.o: expr.h
|
||||
statement.o: file_info.h
|
||||
statement.o: idf.h
|
||||
statement.o: label.h
|
||||
statement.o: nobitfield.h
|
||||
statement.o: nofloat.h
|
||||
statement.o: nopp.h
|
||||
statement.o: spec_arith.h
|
||||
statement.o: stack.h
|
||||
statement.o: type.h
|
||||
expression.o: LLlex.h
|
||||
expression.o: Lpars.h
|
||||
expression.o: arith.h
|
||||
expression.o: expr.h
|
||||
expression.o: file_info.h
|
||||
expression.o: idf.h
|
||||
expression.o: label.h
|
||||
expression.o: noRoption.h
|
||||
expression.o: nobitfield.h
|
||||
expression.o: nofloat.h
|
||||
expression.o: nopp.h
|
||||
expression.o: spec_arith.h
|
||||
expression.o: type.h
|
||||
program.o: LLlex.h
|
||||
program.o: Lpars.h
|
||||
program.o: arith.h
|
||||
program.o: code.h
|
||||
program.o: declar.h
|
||||
program.o: decspecs.h
|
||||
program.o: def.h
|
||||
program.o: expr.h
|
||||
program.o: file_info.h
|
||||
program.o: idf.h
|
||||
program.o: label.h
|
||||
program.o: nobitfield.h
|
||||
program.o: nofloat.h
|
||||
program.o: nopp.h
|
||||
program.o: spec_arith.h
|
||||
program.o: type.h
|
||||
Lpars.o: Lpars.h
|
||||
ival.o: LLlex.h
|
||||
ival.o: Lpars.h
|
||||
ival.o: align.h
|
||||
ival.o: arith.h
|
||||
ival.o: assert.h
|
||||
ival.o: class.h
|
||||
ival.o: debug.h
|
||||
ival.o: def.h
|
||||
ival.o: estack.h
|
||||
ival.o: expr.h
|
||||
ival.o: field.h
|
||||
ival.o: file_info.h
|
||||
ival.o: idf.h
|
||||
ival.o: label.h
|
||||
ival.o: level.h
|
||||
ival.o: noRoption.h
|
||||
ival.o: nobitfield.h
|
||||
ival.o: nocross.h
|
||||
ival.o: nofloat.h
|
||||
ival.o: nopp.h
|
||||
ival.o: sizes.h
|
||||
ival.o: spec_arith.h
|
||||
ival.o: struct.h
|
||||
ival.o: target_sizes.h
|
||||
ival.o: type.h
|
||||
char.o: class.h
|
||||
symbol2str.o: Lpars.h
|
||||
220
lang/cem/cemcom/Makefile.erik
Normal file
220
lang/cem/cemcom/Makefile.erik
Normal file
@@ -0,0 +1,220 @@
|
||||
# $Header$
|
||||
# M A K E F I L E F O R A C K C - C O M P I L E R
|
||||
|
||||
# Machine and environ dependent definitions
|
||||
EMHOME = /usr/em# # ACK tree on this machine
|
||||
DESTINATION = /user1/$$USER/bin# # where to put the stuff
|
||||
MKDEP = $(EMHOME)/bin/mkdep# # dependency generator
|
||||
MAP =
|
||||
#MAP = -DInsertFile=ins_file -DInsertText=ins_text# bug in m68k2 back end
|
||||
SIM = /user1/dick/bin/sim# # Dicks sim program
|
||||
LINT = /usr/new/lint
|
||||
|
||||
# Libraries and EM interface definitions
|
||||
SYSLIB = $(EMHOME)/modules/lib/libsystem.a
|
||||
EMKLIB = $(EMHOME)/modules/lib/libemk.a
|
||||
EMELIB = $(EMHOME)/modules/lib/libeme.a
|
||||
STRLIB = $(EMHOME)/modules/lib/libstring.a
|
||||
PRTLIB = $(EMHOME)/modules/lib/libprint.a
|
||||
EMMESLIB = $(EMHOME)/modules/lib/libem_mes.a
|
||||
INPLIB = $(EMHOME)/modules/lib/libinput.a
|
||||
ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a
|
||||
MALLOC = $(EMHOME)/modules/lib/malloc.o
|
||||
#CH3LIB = $(EMHOME)/modules/lib/libch3.a
|
||||
CH3LIB =
|
||||
LIBS = $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMKLIB) \
|
||||
$(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
|
||||
ELIBS = $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMELIB) \
|
||||
$(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
|
||||
LIB_INCLUDES = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg
|
||||
EM_INCLUDES = -I$(EMHOME)/h
|
||||
SYSLLIB = $(EMHOME)/modules/lib/llib-lsys.ln
|
||||
EMKLLIB = $(EMHOME)/modules/lib/llib-lemk.ln
|
||||
EMELLIB = $(EMHOME)/modules/lib/llib-leme.ln
|
||||
STRLLIB = $(EMHOME)/modules/lib/llib-lstr.ln
|
||||
PRTLLIB = $(EMHOME)/modules/lib/llib-lprint.ln
|
||||
EMMESLLIB = $(EMHOME)/modules/lib/llib-lmes.ln
|
||||
INPLLIB = $(EMHOME)/modules/lib/llib-linput.ln
|
||||
CH3LLIB = $(EMHOME)/modules/lib/llib-lch3.ln
|
||||
ALLOCLLIB = $(EMHOME)/modules/lib/llib-alloc.ln
|
||||
LINTLIBS =
|
||||
#LINTLIBS = $(CH3LLIB) $(INPLLIB) $(EMMESLLIB) $(EMKLLIB) \
|
||||
# $(PRTLLIB) $(STRLLIB) $(SYSLLIB) $(ALLOCLLIB)
|
||||
|
||||
# Where to install the compiler and its driver
|
||||
CEMCOM = $(DESTINATION)/cemcom
|
||||
DRIVER = $(DESTINATION)/cem
|
||||
|
||||
# What C compiler to use and how
|
||||
# CC = $(ACK) -.c
|
||||
# CC = CC
|
||||
# CC = /bin/cc
|
||||
COPTIONS =
|
||||
|
||||
# What parser generator to use and how
|
||||
GEN = $(EMHOME)/bin/LLgen
|
||||
GENOPTIONS = -vv
|
||||
|
||||
# Special #defines during compilation
|
||||
CDEFS = $(MAP) $(EM_INCLUDES) $(LIB_INCLUDES)
|
||||
CFLAGS = $(CDEFS) $(COPTIONS) -O# we cannot pass the COPTIONS to lint!
|
||||
|
||||
# Grammar files and their objects
|
||||
LSRC = tokenfile.g declar.g statement.g expression.g program.g ival.g
|
||||
GLCSRC = tokenfile.c declar.c statement.c expression.c program.c ival.c
|
||||
LOBJ = tokenfile.o declar.o statement.o expression.o program.o Lpars.o ival.o
|
||||
|
||||
# Objects of hand-written C files
|
||||
COBJ = main.o idf.o declarator.o decspecs.o struct.o \
|
||||
expr.o ch7.o ch7bin.o cstoper.o arith.o \
|
||||
asm.o code.o dumpidf.o error.o field.o\
|
||||
tokenname.o LLlex.o LLmessage.o \
|
||||
input.o domacro.o replace.o init.o options.o \
|
||||
scan.o skip.o stack.o type.o ch7mon.o label.o eval.o \
|
||||
switch.o conversion.o \
|
||||
blocks.o dataflow.o Version.o util.o
|
||||
|
||||
# Objects of other generated C files
|
||||
GOBJ = char.o symbol2str.o next.o
|
||||
|
||||
# generated source files
|
||||
GSRC = char.c symbol2str.c next.c \
|
||||
code.h declar.h decspecs.h def.h expr.h field.h estack.h \
|
||||
idf.h macro.h stack.h stmt.h struct.h switch.h type.h util.h
|
||||
|
||||
# .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
|
||||
GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \
|
||||
idfsize.h ifdepth.h inputtype.h inumlength.h lapbuf.h \
|
||||
nobitfield.h nofloat.h nopp.h noRoption.h nocross.h \
|
||||
nparams.h numsize.h parbufsize.h pathlength.h \
|
||||
strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h
|
||||
|
||||
# Other generated files, for 'make clean' only
|
||||
GENERATED = tab tokenfile.g Lpars.h LLfiles LL.output lint.out \
|
||||
print Xref lxref hfiles cfiles $(GLCSRC)
|
||||
|
||||
# include files containing ALLOCDEF specifications
|
||||
NEXTFILES = code.str declar.str decspecs.str def.str expr.str field.str \
|
||||
estack.str util.str \
|
||||
idf.str macro.str stack.str stmt.str struct.str switch.str type.str
|
||||
|
||||
.SUFFIXES: .str .h
|
||||
.str.h:
|
||||
./make.allocd <$*.str >$*.h
|
||||
|
||||
all: cc
|
||||
|
||||
cc:
|
||||
make "EMHOME="$(EMHOME) "CC=$(CC)" hfiles
|
||||
make "EMHOME="$(EMHOME) "CC=$(CC)" LLfiles
|
||||
make "EMHOME="$(EMHOME) "CC=$(CC)" main
|
||||
|
||||
cem: cem.c
|
||||
$(CC) -O cem.c $(SYSLIB) -o cem
|
||||
|
||||
lint.cem: cem.c
|
||||
$(LINT) -bx cem.c
|
||||
|
||||
hfiles: ./make.hfiles Parameters
|
||||
./make.hfiles Parameters
|
||||
@touch hfiles
|
||||
|
||||
LLfiles: $(LSRC)
|
||||
$(GEN) $(GENOPTIONS) $(LSRC)
|
||||
@touch LLfiles
|
||||
|
||||
tokenfile.g: tokenname.c make.tokfile
|
||||
<tokenname.c ./make.tokfile >tokenfile.g
|
||||
|
||||
symbol2str.c: tokenname.c make.tokcase
|
||||
<tokenname.c ./make.tokcase >symbol2str.c
|
||||
|
||||
char.c: tab char.tab
|
||||
tab -fchar.tab >char.c
|
||||
|
||||
next.c: make.next $(NEXTFILES)
|
||||
./make.next $(NEXTFILES) >next.c
|
||||
|
||||
code.h: make.allocd
|
||||
declar.h: make.allocd
|
||||
decspecs.h: make.allocd
|
||||
def.h: make.allocd
|
||||
estack.h: make.allocd
|
||||
expr.h: make.allocd
|
||||
field.h: make.allocd
|
||||
idf.h: make.allocd
|
||||
macro.h: make.allocd
|
||||
stack.h: make.allocd
|
||||
stmt.h: make.allocd
|
||||
struct.h: make.allocd
|
||||
switch.h: make.allocd
|
||||
type.h: make.allocd
|
||||
util.h: make.allocd
|
||||
|
||||
# Objects needed for 'main'
|
||||
OBJ = $(COBJ) $(LOBJ) $(GOBJ)
|
||||
|
||||
main: $(OBJ) Makefile
|
||||
$(CC) $(COPTIONS) $(LFLAGS) $(OBJ) $(LIBS) -o main
|
||||
size main
|
||||
|
||||
emain: $(OBJ) Makefile
|
||||
$(CC) $(COPTIONS) $(LFLAGS) $(OBJ) $(ELIBS) -o emain
|
||||
size emain
|
||||
|
||||
cfiles: hfiles LLfiles $(GSRC)
|
||||
@touch cfiles
|
||||
|
||||
install: main cem
|
||||
cp main $(CEMCOM)
|
||||
cp cem $(DRIVER)
|
||||
|
||||
print: files
|
||||
pr `cat files` > print
|
||||
|
||||
tags: cfiles
|
||||
ctags `sources $(OBJ)`
|
||||
|
||||
shar: files
|
||||
shar `cat files`
|
||||
|
||||
listcfiles:
|
||||
@echo `sources $(OBJ)`
|
||||
|
||||
listobjects:
|
||||
@echo $(OBJ)
|
||||
|
||||
depend: cfiles
|
||||
sed '/^#AUTOAUTO/,$$d' Makefile >Makefile.new
|
||||
echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >>Makefile.new
|
||||
$(MKDEP) `sources $(OBJ)` | sed 's/\.c:/.o:/' >>Makefile.new
|
||||
mv Makefile Makefile.old
|
||||
mv Makefile.new Makefile
|
||||
|
||||
xref:
|
||||
ctags -x `grep "\.[ch]" files`|sed "s/).*/)/">Xref
|
||||
|
||||
lxref:
|
||||
lxref $(OBJ) -lc >lxref
|
||||
|
||||
lint: lint.main lint.cem lint.tab
|
||||
|
||||
lint.main: cfiles
|
||||
$(LINT) -bx $(CDEFS) `sources $(OBJ)` $(LINTLIBS) >lint.out
|
||||
|
||||
cchk:
|
||||
cchk `sources $(COBJ)`
|
||||
|
||||
clean:
|
||||
rm -f `sources $(LOBJ)` $(OBJ) $(GENERATED) $(GSRC) $(GHSRC)
|
||||
|
||||
tab:
|
||||
$(CC) tab.c -o tab
|
||||
|
||||
lint.tab:
|
||||
$(LINT) -abx tab.c
|
||||
|
||||
sim: cfiles
|
||||
$(SIM) $(SIMFLAGS) `sources $(COBJ)` $(GSRC) $(LSRC)
|
||||
|
||||
#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
|
||||
131
lang/cem/cemcom/Parameters
Normal file
131
lang/cem/cemcom/Parameters
Normal file
@@ -0,0 +1,131 @@
|
||||
!File: pathlength.h
|
||||
#define PATHLENGTH 1024 /* max. length of path to file */
|
||||
|
||||
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define MAXERR_LINE 5 /* maximum number of error messages given
|
||||
on the same input line. */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 64 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: nparams.h
|
||||
#define NPARAMS 32 /* maximum number of parameters of macros */
|
||||
|
||||
|
||||
!File: ifdepth.h
|
||||
#define IFDEPTH 256 /* maximum number of nested if-constructions */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 2 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!File: lapbuf.h
|
||||
#define LAPBUF 4096 /* size of macro actual parameter buffer */
|
||||
|
||||
|
||||
!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
|
||||
#ifndef NOFLOAT
|
||||
#define SZ_FLOAT (arith)4
|
||||
#define SZ_DOUBLE (arith)8
|
||||
#endif NOFLOAT
|
||||
#define SZ_POINTER (arith)4
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT SZ_SHORT
|
||||
#define AL_WORD SZ_WORD
|
||||
#define AL_INT SZ_WORD
|
||||
#define AL_LONG SZ_WORD
|
||||
#ifndef NOFLOAT
|
||||
#define AL_FLOAT SZ_WORD
|
||||
#define AL_DOUBLE SZ_WORD
|
||||
#endif NOFLOAT
|
||||
#define AL_POINTER SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
#define AL_UNION 1
|
||||
|
||||
|
||||
!File: botch_free.h
|
||||
#undef BOTCH_FREE 1 /* when defined, botch freed memory, as a check */
|
||||
|
||||
|
||||
!File: dataflow.h
|
||||
#define DATAFLOW 1 /* produce some compile-time xref */
|
||||
|
||||
|
||||
!File: debug.h
|
||||
#undef DEBUG 1 /* perform various self-tests */
|
||||
|
||||
|
||||
!File: use_tmp.h
|
||||
#define USE_TMP 1 /* collect exa, exp, ina and inp commands
|
||||
and let them precede the rest of
|
||||
the generated compact code */
|
||||
|
||||
|
||||
!File: parbufsize.h
|
||||
#define PARBUFSIZE 1024
|
||||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 8 /* 1st piece of memory for repl. text */
|
||||
#define RTEXTSIZE 8 /* stepsize for enlarging repl.text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
#define INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nopp.h
|
||||
#undef NOPP 1 /* if NOT defined, use built-int preprocessor */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
#undef NOBITFIELD 1 /* if NOT defined, implement bitfields */
|
||||
|
||||
|
||||
!File: spec_arith.h
|
||||
/* describes internal compiler arithmetics */
|
||||
#undef SPECIAL_ARITHMETICS /* something different from native long */
|
||||
|
||||
|
||||
!File: static.h
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
||||
!File: nofloat.h
|
||||
#undef NOFLOAT 1 /* if NOT defined, floats are implemented */
|
||||
|
||||
|
||||
!File: noRoption.h
|
||||
#undef NOROPTION 1 /* if NOT defined, R option is implemented */
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
#undef NOCROSS 1 /* if NOT defined, cross compiler */
|
||||
|
||||
|
||||
58
lang/cem/cemcom/Resolve
Executable file
58
lang/cem/cemcom/Resolve
Executable file
@@ -0,0 +1,58 @@
|
||||
: 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|emain)
|
||||
target=$PW/$1
|
||||
;;
|
||||
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
|
||||
for i in `cat $PW/Cfiles`
|
||||
do
|
||||
cat >> makefile <<EOF
|
||||
|
||||
$i: clashes $PW/$i
|
||||
cid -Fclashes < $PW/$i > $i
|
||||
EOF
|
||||
done
|
||||
make EMHOME=$EMHOME `cat $PW/Cfiles`
|
||||
rm -f makefile
|
||||
ed - $PW/makefile <<'EOF'
|
||||
/^#EXCLEXCL/,/^#INCLINCL/d
|
||||
w makefile
|
||||
q
|
||||
EOF
|
||||
make EMHOME=$EMHOME CURRDIR=$PW $target
|
||||
131
lang/cem/cemcom/SmallPars
Normal file
131
lang/cem/cemcom/SmallPars
Normal file
@@ -0,0 +1,131 @@
|
||||
!File: pathlength.h
|
||||
#define PATHLENGTH 1024 /* max. length of path to file */
|
||||
|
||||
|
||||
!File: errout.h
|
||||
#define ERROUT STDERR /* file pointer for writing messages */
|
||||
#define MAXERR_LINE 5 /* maximum number of error messages given
|
||||
on the same input line. */
|
||||
|
||||
|
||||
!File: idfsize.h
|
||||
#define IDFSIZE 64 /* maximum significant length of an identifier */
|
||||
|
||||
|
||||
!File: numsize.h
|
||||
#define NUMSIZE 256 /* maximum length of a numeric constant */
|
||||
|
||||
|
||||
!File: nparams.h
|
||||
#define NPARAMS 32 /* maximum number of parameters of macros */
|
||||
|
||||
|
||||
!File: ifdepth.h
|
||||
#define IFDEPTH 256 /* maximum number of nested if-constructions */
|
||||
|
||||
|
||||
!File: density.h
|
||||
#define DENSITY 2 /* see switch.[ch] for an explanation */
|
||||
|
||||
|
||||
!File: lapbuf.h
|
||||
#define LAPBUF 4096 /* size of macro actual parameter buffer */
|
||||
|
||||
|
||||
!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
|
||||
#ifndef NOFLOAT
|
||||
#define SZ_FLOAT (arith)4
|
||||
#define SZ_DOUBLE (arith)8
|
||||
#endif NOFLOAT
|
||||
#define SZ_POINTER (arith)4
|
||||
|
||||
/* target machine alignment requirements */
|
||||
#define AL_CHAR 1
|
||||
#define AL_SHORT SZ_SHORT
|
||||
#define AL_WORD SZ_WORD
|
||||
#define AL_INT SZ_WORD
|
||||
#define AL_LONG SZ_WORD
|
||||
#ifndef NOFLOAT
|
||||
#define AL_FLOAT SZ_WORD
|
||||
#define AL_DOUBLE SZ_WORD
|
||||
#endif NOFLOAT
|
||||
#define AL_POINTER SZ_WORD
|
||||
#define AL_STRUCT 1
|
||||
#define AL_UNION 1
|
||||
|
||||
|
||||
!File: botch_free.h
|
||||
#undef BOTCH_FREE 1 /* when defined, botch freed memory, as a check */
|
||||
|
||||
|
||||
!File: dataflow.h
|
||||
#undef DATAFLOW 1 /* produce some compile-time xref */
|
||||
|
||||
|
||||
!File: debug.h
|
||||
#undef DEBUG 1 /* perform various self-tests */
|
||||
|
||||
|
||||
!File: use_tmp.h
|
||||
#undef USE_TMP 1 /* collect exa, exp, ina and inp commands
|
||||
and let them precede the rest of
|
||||
the generated compact code */
|
||||
|
||||
|
||||
!File: parbufsize.h
|
||||
#define PARBUFSIZE 1024
|
||||
|
||||
|
||||
!File: textsize.h
|
||||
#define ITEXTSIZE 8 /* 1st piece of memory for repl. text */
|
||||
#define RTEXTSIZE 8 /* stepsize for enlarging repl.text */
|
||||
|
||||
|
||||
!File: inputtype.h
|
||||
#undef INP_READ_IN_ONE 1 /* read input file in one */
|
||||
|
||||
|
||||
!File: nopp.h
|
||||
#define NOPP 1 /* if NOT defined, use built-int preprocessor */
|
||||
|
||||
|
||||
!File: nobitfield.h
|
||||
#undef NOBITFIELD 1 /* if NOT defined, implement bitfields */
|
||||
|
||||
|
||||
!File: spec_arith.h
|
||||
/* describes internal compiler arithmetics */
|
||||
#undef SPECIAL_ARITHMETICS /* something different from native long */
|
||||
|
||||
|
||||
!File: static.h
|
||||
#define GSTATIC /* for large global "static" arrays */
|
||||
|
||||
|
||||
!File: nofloat.h
|
||||
#undef NOFLOAT 1 /* if NOT defined, floats are implemented */
|
||||
|
||||
|
||||
!File: noRoption.h
|
||||
#define NOROPTION 1 /* if NOT defined, R option is implemented */
|
||||
|
||||
|
||||
!File: nocross.h
|
||||
#undef NOCROSS 1 /* if NOT defined, cross compiler */
|
||||
|
||||
|
||||
6
lang/cem/cemcom/Version.c
Normal file
6
lang/cem/cemcom/Version.c
Normal file
@@ -0,0 +1,6 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
static char Version[] = "ACK CEM compiler Version 3.1";
|
||||
34
lang/cem/cemcom/align.h
Normal file
34
lang/cem/cemcom/align.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* A L I G N M E N T D E F I N I T I O N S */
|
||||
|
||||
#include "nofloat.h"
|
||||
#include "nocross.h"
|
||||
#include "target_sizes.h"
|
||||
|
||||
#ifndef NOCROSS
|
||||
extern int
|
||||
short_align, word_align, int_align, long_align,
|
||||
#ifndef NOFLOAT
|
||||
float_align, double_align,
|
||||
#endif NOFLOAT
|
||||
pointer_align,
|
||||
struct_align, union_align;
|
||||
#else NOCROSS
|
||||
#define short_align ((int)AL_SHORT)
|
||||
#define word_align ((int)AL_WORD)
|
||||
#define int_align ((int)AL_INT)
|
||||
#define long_align ((int)AL_LONG)
|
||||
#ifndef NOFLOAT
|
||||
#define float_align ((int)AL_FLOAT)
|
||||
#define double_align ((int)AL_DOUBLE)
|
||||
#endif NOFLOAT
|
||||
#define pointer_align ((int)AL_POINTER)
|
||||
#define struct_align ((int)AL_STRUCT)
|
||||
#define union_align ((int)AL_UNION)
|
||||
#endif NOCROSS
|
||||
|
||||
extern arith align();
|
||||
159
lang/cem/cemcom/alloc.c
Normal file
159
lang/cem/cemcom/alloc.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* $Header$ */
|
||||
/* M E M O R Y A L L O C A T I O N R O U T I N E S */
|
||||
|
||||
/* The allocation of memory in this program, which plays an important
|
||||
role in reading files, replacing macros and building expression
|
||||
trees, is not performed by malloc etc. The reason for having own
|
||||
memory allocation routines (malloc(), realloc() and free()) is
|
||||
plain: the garbage collection performed by the library functions
|
||||
malloc(), realloc() and free() costs a lot of time, while in most
|
||||
cases (on a VAX) the freeing and reallocation of memory is not
|
||||
necessary. The only reallocation done in this program is at
|
||||
building strings in memory. This means that the last
|
||||
(re-)allocated piece of memory can be extended.
|
||||
|
||||
The (basic) memory allocating routines offered by this memory
|
||||
handling package are:
|
||||
|
||||
char *malloc(n) : allocate n bytes
|
||||
char *realloc(ptr, n) : reallocate buffer to n bytes
|
||||
(works only if ptr was last allocated)
|
||||
free(ptr) : if ptr points to last allocated
|
||||
memory, this memory is re-allocatable
|
||||
Salloc(str, sz) : save string in malloc storage
|
||||
*/
|
||||
|
||||
#include <system.h>
|
||||
#include "myalloc.h" /* UF */
|
||||
#include "debug.h" /* UF */
|
||||
|
||||
#include "alloc.h"
|
||||
#include "assert.h"
|
||||
|
||||
#ifdef OWNALLOC
|
||||
char *sys_break();
|
||||
/* the following variables are used for book-keeping */
|
||||
static int nfreebytes = 0; /* # free bytes in sys_break space */
|
||||
static char *freeb; /* pointer to first free byte */
|
||||
static char *lastalloc; /* pointer to last malloced sp */
|
||||
static int lastnbytes; /* nr of bytes in last allocated */
|
||||
/* space */
|
||||
static char *firstfreeb = 0;
|
||||
|
||||
#endif OWNALLOC
|
||||
|
||||
char *
|
||||
Salloc(str, sz)
|
||||
register char str[];
|
||||
register int sz;
|
||||
{
|
||||
/* Salloc() is not a primitive function: it just allocates a
|
||||
piece of storage and copies a given string into it.
|
||||
*/
|
||||
char *res = Malloc(sz);
|
||||
register char *m = res;
|
||||
|
||||
while (sz--)
|
||||
*m++ = *str++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef OWNALLOC
|
||||
|
||||
#define ALIGN(m) (ALIGNSIZE * (((m) - 1) / ALIGNSIZE + 1))
|
||||
|
||||
char *
|
||||
malloc(n)
|
||||
unsigned n;
|
||||
{
|
||||
/* malloc() is a very simple malloc().
|
||||
*/
|
||||
n = ALIGN(n);
|
||||
if (nfreebytes < n) {
|
||||
register nbts = (n <= ALLOCSIZ) ? ALLOCSIZ : n;
|
||||
|
||||
if (!nfreebytes) {
|
||||
if ((freeb = sys_break(nbts)) == ILL_BREAK)
|
||||
fatal("out of memory");
|
||||
}
|
||||
else {
|
||||
if (sys_break(nbts) == ILL_BREAK)
|
||||
fatal("out of memory");
|
||||
}
|
||||
nfreebytes += nbts;
|
||||
}
|
||||
lastalloc = freeb;
|
||||
freeb = lastalloc + n;
|
||||
lastnbytes = n;
|
||||
nfreebytes -= n;
|
||||
return lastalloc;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
char *
|
||||
realloc(ptr, n)
|
||||
char *ptr;
|
||||
unsigned n;
|
||||
{
|
||||
/* realloc() is designed to append more bytes to the latest
|
||||
allocated piece of memory. However reallocation should be
|
||||
performed, even if the mentioned memory is not the latest
|
||||
allocated one, this situation will not occur. To do so,
|
||||
realloc should know how many bytes are allocated the last
|
||||
time for that piece of memory. ????
|
||||
*/
|
||||
register int nbytes = n;
|
||||
|
||||
ASSERT(ptr == lastalloc); /* security */
|
||||
nbytes -= lastnbytes; /* # bytes required */
|
||||
if (nbytes == 0) /* no extra bytes */
|
||||
return lastalloc;
|
||||
|
||||
/* if nbytes < 0: free last allocated bytes;
|
||||
if nbytes > 0: allocate more bytes
|
||||
*/
|
||||
if (nbytes > 0)
|
||||
nbytes = ALIGN(nbytes);
|
||||
if (nfreebytes < nbytes) {
|
||||
register int nbts = (nbytes < ALLOCSIZ) ? ALLOCSIZ : nbytes;
|
||||
if (sys_break(nbts) == ILL_BREAK)
|
||||
fatal("out of memory");
|
||||
nfreebytes += nbts;
|
||||
}
|
||||
freeb += nbytes; /* less bytes */
|
||||
lastnbytes += nbytes; /* change nr of last all. bytes */
|
||||
nfreebytes -= nbytes; /* less or more free bytes */
|
||||
return lastalloc;
|
||||
}
|
||||
|
||||
/* to ensure that the alloc library package will not be loaded: */
|
||||
/*ARGSUSED*/
|
||||
free(p)
|
||||
char *p;
|
||||
{}
|
||||
|
||||
init_mem()
|
||||
{
|
||||
firstfreeb = sys_break(0);
|
||||
/* align the first memory unit to ALIGNSIZE ??? */
|
||||
if ((long) firstfreeb % ALIGNSIZE != 0) {
|
||||
register char *fb = firstfreeb;
|
||||
|
||||
fb = (char *)ALIGN((long)fb);
|
||||
firstfreeb = sys_break(fb - firstfreeb);
|
||||
firstfreeb = fb;
|
||||
ASSERT((long)firstfreeb % ALIGNSIZE == 0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
mem_stat()
|
||||
{
|
||||
extern char options[];
|
||||
|
||||
if (options['m'])
|
||||
print("Total nr of bytes allocated: %d\n",
|
||||
sys_break(0) - firstfreeb);
|
||||
}
|
||||
#endif DEBUG
|
||||
#endif OWNALLOC
|
||||
16
lang/cem/cemcom/alloc.h
Normal file
16
lang/cem/cemcom/alloc.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* $Header$ */
|
||||
/* PROGRAM'S INTERFACE TO MEMORY ALLOCATION ROUTINES */
|
||||
|
||||
/* This file serves as the interface between the program and the
|
||||
memory allocating routines.
|
||||
There are 3 memory allocation routines:
|
||||
char *Malloc(n) to allocate n bytes
|
||||
char *Salloc(str, n) to allocate n bytes
|
||||
and fill them with string str
|
||||
char *Realloc(str, n) reallocate the string at str to n bytes
|
||||
*/
|
||||
|
||||
extern char *Salloc(), *malloc(), *realloc();
|
||||
|
||||
#define Malloc(n) malloc((unsigned)(n))
|
||||
#define Srealloc(ptr,n) realloc(ptr, (unsigned)(n))
|
||||
541
lang/cem/cemcom/arith.c
Normal file
541
lang/cem/cemcom/arith.c
Normal file
@@ -0,0 +1,541 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* A R I T H M E T I C C O N V E R S I O N S */
|
||||
|
||||
/* This file contains the routines for the various conversions that
|
||||
may befall operands in C. It is structurally a mess, but I haven't
|
||||
decided yet whether I can't find the right structure or the
|
||||
semantics of C is a mess.
|
||||
*/
|
||||
|
||||
#include "botch_free.h"
|
||||
#include <alloc.h>
|
||||
#include "nofloat.h"
|
||||
#include "nobitfield.h"
|
||||
#include "idf.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "Lpars.h"
|
||||
#include "field.h"
|
||||
#include "mes.h"
|
||||
#include "noRoption.h"
|
||||
|
||||
extern char *symbol2str();
|
||||
extern char options[];
|
||||
|
||||
int
|
||||
arithbalance(e1p, oper, e2p) /* RM 6.6 */
|
||||
register struct expr **e1p, **e2p;
|
||||
int oper;
|
||||
{
|
||||
/* The expressions *e1p and *e2p are balanced to be operands
|
||||
of the arithmetic operator oper.
|
||||
*/
|
||||
register int t1, t2, u1, u2;
|
||||
|
||||
t1 = any2arith(e1p, oper);
|
||||
t2 = any2arith(e2p, oper);
|
||||
|
||||
/* Now t1 and t2 are either INT or LONG or DOUBLE */
|
||||
#ifndef NOFLOAT
|
||||
if (t1 == DOUBLE && t2 != DOUBLE)
|
||||
t2 = int2float(e2p, double_type);
|
||||
else
|
||||
if (t2 == DOUBLE && t1 != DOUBLE)
|
||||
t1 = int2float(e1p, double_type);
|
||||
else
|
||||
if (t1 == DOUBLE)
|
||||
return DOUBLE;
|
||||
#endif NOFLOAT
|
||||
|
||||
/* Now they are INT or LONG */
|
||||
u1 = (*e1p)->ex_type->tp_unsigned;
|
||||
u2 = (*e2p)->ex_type->tp_unsigned;
|
||||
|
||||
/* if either is long, the other will be */
|
||||
if (t1 == LONG && t2 != LONG)
|
||||
t2 = int2int(e2p, u2 ? ulong_type : long_type);
|
||||
else
|
||||
if (t2 == LONG && t1 != LONG)
|
||||
t1 = int2int(e1p, u1 ? ulong_type : long_type);
|
||||
|
||||
/* if either is unsigned, the other will be */
|
||||
if (u1 && !u2)
|
||||
t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type);
|
||||
else
|
||||
if (!u1 && u2)
|
||||
t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type);
|
||||
|
||||
return t1;
|
||||
}
|
||||
|
||||
relbalance(e1p, oper, e2p)
|
||||
register struct expr **e1p, **e2p;
|
||||
{
|
||||
/* The expressions *e1p and *e2p are balanced to be operands
|
||||
of the relational operator oper.
|
||||
*/
|
||||
if ((*e1p)->ex_type->tp_fund == FUNCTION)
|
||||
function2pointer(*e1p);
|
||||
if ((*e2p)->ex_type->tp_fund == FUNCTION)
|
||||
function2pointer(*e2p);
|
||||
if ((*e1p)->ex_type->tp_fund == POINTER)
|
||||
ch76pointer(e2p, oper, (*e1p)->ex_type);
|
||||
else
|
||||
if ((*e2p)->ex_type->tp_fund == POINTER)
|
||||
ch76pointer(e1p, oper, (*e2p)->ex_type);
|
||||
else
|
||||
if ( (*e1p)->ex_type == (*e2p)->ex_type &&
|
||||
(*e1p)->ex_type->tp_fund == ENUM
|
||||
)
|
||||
{}
|
||||
else
|
||||
arithbalance(e1p, oper, e2p);
|
||||
}
|
||||
|
||||
ch76pointer(expp, oper, tp)
|
||||
struct expr **expp;
|
||||
register struct type *tp;
|
||||
{
|
||||
/* Checks whether *expp may be compared to tp using oper,
|
||||
as described in chapter 7.6 and 7.7.
|
||||
tp is known to be a pointer.
|
||||
*/
|
||||
register struct expr *exp = *expp;
|
||||
|
||||
if (exp->ex_type->tp_fund == POINTER) {
|
||||
if (exp->ex_type != tp)
|
||||
ch7cast(expp, oper, tp);
|
||||
}
|
||||
else
|
||||
if ( is_integral_type(exp->ex_type)
|
||||
#ifndef NOROPTION
|
||||
&&
|
||||
( !options['R'] /* we don't care */ ||
|
||||
(oper == EQUAL || oper == NOTEQUAL || oper == ':')
|
||||
)
|
||||
#endif NOROPTION
|
||||
) /* ch 7.7 */
|
||||
ch7cast(expp, CAST, tp);
|
||||
else {
|
||||
expr_error(exp, "%s on %s and pointer",
|
||||
symbol2str(oper),
|
||||
symbol2str(exp->ex_type->tp_fund)
|
||||
);
|
||||
ch7cast(expp, oper, tp);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
any2arith(expp, oper)
|
||||
register struct expr **expp;
|
||||
register int oper;
|
||||
{
|
||||
/* Turns any expression into int_type, long_type or
|
||||
double_type.
|
||||
*/
|
||||
int fund;
|
||||
|
||||
switch (fund = (*expp)->ex_type->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
int2int(expp,
|
||||
(*expp)->ex_type->tp_unsigned ? uint_type : int_type);
|
||||
break;
|
||||
case INT:
|
||||
case LONG:
|
||||
break;
|
||||
case ENUM:
|
||||
/* test the admissibility of the operator */
|
||||
if ( is_test_op(oper) || oper == '=' || oper == PARCOMMA ||
|
||||
oper == ',' || oper == ':'
|
||||
) {
|
||||
/* allowed by K & R */
|
||||
}
|
||||
else
|
||||
#ifndef NOROPTION
|
||||
if (!options['R']) {
|
||||
/* allowed by us */
|
||||
}
|
||||
else
|
||||
expr_warning(*expp, "%s on enum", symbol2str(oper));
|
||||
#endif NOROPTION
|
||||
int2int(expp, int_type);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
float2float(expp, double_type);
|
||||
break;
|
||||
case DOUBLE:
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
#ifndef NOBITFIELD
|
||||
case FIELD:
|
||||
field2arith(expp);
|
||||
break;
|
||||
#endif NOBITFIELD
|
||||
default:
|
||||
expr_error(*expp, "operator %s on non-numerical operand (%s)",
|
||||
symbol2str(oper), symbol2str(fund));
|
||||
case ERRONEOUS:
|
||||
erroneous2int(expp);
|
||||
break;
|
||||
}
|
||||
|
||||
return (*expp)->ex_type->tp_fund;
|
||||
}
|
||||
|
||||
erroneous2int(expp)
|
||||
struct expr **expp;
|
||||
{
|
||||
/* the (erroneous) expression *expp is replaced by an
|
||||
int expression
|
||||
*/
|
||||
register struct expr *exp = *expp;
|
||||
int flags = exp->ex_flags;
|
||||
|
||||
free_expression(exp);
|
||||
exp = intexpr((arith)0, INT);
|
||||
exp->ex_flags = (flags | EX_ERROR);
|
||||
*expp = exp;
|
||||
}
|
||||
|
||||
struct expr *
|
||||
arith2arith(tp, oper, expr)
|
||||
struct type *tp;
|
||||
int oper;
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* arith2arith constructs a new expression containing a
|
||||
run-time conversion between some arithmetic types.
|
||||
*/
|
||||
register struct expr *new = new_expr();
|
||||
|
||||
new->ex_file = expr->ex_file;
|
||||
new->ex_line = expr->ex_line;
|
||||
new->ex_type = tp;
|
||||
new->ex_class = Type;
|
||||
return new_oper(tp, new, oper, expr);
|
||||
}
|
||||
|
||||
int
|
||||
int2int(expp, tp)
|
||||
struct expr **expp;
|
||||
register struct type *tp;
|
||||
{
|
||||
/* The expression *expp, which is of some integral type, is
|
||||
converted to the integral type tp.
|
||||
*/
|
||||
register struct expr *exp = *expp;
|
||||
|
||||
if (is_cp_cst(exp)) {
|
||||
register struct type *tp1 = exp->ex_type;
|
||||
|
||||
exp->ex_type = tp;
|
||||
if (! tp1->tp_unsigned && tp->tp_unsigned) {
|
||||
/* Avoid "unreal" overflow warnings, such as
|
||||
caused by f.i.:
|
||||
unsigned int x = ~0;
|
||||
unsigned int y = -1;
|
||||
*/
|
||||
extern long full_mask[];
|
||||
long remainder = exp->VL_VALUE &
|
||||
~full_mask[(int)(tp->tp_size)];
|
||||
|
||||
if (remainder == 0 ||
|
||||
remainder == ~full_mask[(int)(tp->tp_size)]) {
|
||||
exp->VL_VALUE &= ~remainder;
|
||||
}
|
||||
}
|
||||
cut_size(exp);
|
||||
}
|
||||
else {
|
||||
exp = arith2arith(tp, INT2INT, exp);
|
||||
}
|
||||
*expp = exp;
|
||||
return exp->ex_type->tp_fund;
|
||||
}
|
||||
|
||||
#ifndef NOFLOAT
|
||||
int
|
||||
int2float(expp, tp)
|
||||
register struct expr **expp;
|
||||
struct type *tp;
|
||||
{
|
||||
/* The expression *expp, which is of some integral type, is
|
||||
converted to the floating type tp.
|
||||
*/
|
||||
|
||||
fp_used = 1;
|
||||
*expp = arith2arith(tp, INT2FLOAT, *expp);
|
||||
return (*expp)->ex_type->tp_fund;
|
||||
}
|
||||
|
||||
float2int(expp, tp)
|
||||
struct expr **expp;
|
||||
struct type *tp;
|
||||
{
|
||||
/* The expression *expp, which is of some floating type, is
|
||||
converted to the integral type tp.
|
||||
*/
|
||||
|
||||
fp_used = 1;
|
||||
*expp = arith2arith(tp, FLOAT2INT, *expp);
|
||||
}
|
||||
|
||||
float2float(expp, tp)
|
||||
register struct expr **expp;
|
||||
struct type *tp;
|
||||
{
|
||||
/* The expression *expp, which is of some floating type, is
|
||||
converted to the floating type tp.
|
||||
There is no need for an explicit conversion operator
|
||||
if the expression is a constant.
|
||||
*/
|
||||
|
||||
fp_used = 1;
|
||||
if (is_fp_cst(*expp))
|
||||
(*expp)->ex_type = tp;
|
||||
else
|
||||
*expp = arith2arith(tp, FLOAT2FLOAT, *expp);
|
||||
}
|
||||
#endif NOFLOAT
|
||||
|
||||
array2pointer(exp)
|
||||
register struct expr *exp;
|
||||
{
|
||||
/* The expression, which must be an array, is converted
|
||||
to a pointer.
|
||||
*/
|
||||
exp->ex_type = construct_type(POINTER, exp->ex_type->tp_up, (arith)0);
|
||||
}
|
||||
|
||||
function2pointer(exp)
|
||||
register struct expr *exp;
|
||||
{
|
||||
/* The expression, which must be a function, is converted
|
||||
to a pointer to the function.
|
||||
*/
|
||||
exp->ex_type = construct_type(POINTER, exp->ex_type, (arith)0);
|
||||
}
|
||||
|
||||
string2pointer(ex)
|
||||
register struct expr *ex;
|
||||
{
|
||||
/* The expression, which must be a string constant, is converted
|
||||
to a pointer to the string-containing area.
|
||||
*/
|
||||
label lbl = data_label();
|
||||
|
||||
code_string(ex->SG_VALUE, ex->SG_LEN, lbl);
|
||||
ex->ex_class = Value;
|
||||
ex->VL_CLASS = Label;
|
||||
ex->VL_LBL = lbl;
|
||||
ex->VL_VALUE = (arith)0;
|
||||
}
|
||||
|
||||
opnd2integral(expp, oper)
|
||||
register struct expr **expp;
|
||||
int oper;
|
||||
{
|
||||
register int fund = (*expp)->ex_type->tp_fund;
|
||||
|
||||
if (fund != INT && fund != LONG) {
|
||||
expr_error(*expp, "%s operand to %s",
|
||||
symbol2str(fund), symbol2str(oper));
|
||||
erroneous2int(expp);
|
||||
/* fund = INT; */
|
||||
}
|
||||
}
|
||||
|
||||
opnd2logical(expp, oper)
|
||||
register struct expr **expp;
|
||||
int oper;
|
||||
{
|
||||
int fund;
|
||||
|
||||
if ((*expp)->ex_type->tp_fund == FUNCTION)
|
||||
function2pointer(*expp);
|
||||
#ifndef NOBITFIELD
|
||||
else
|
||||
if ((*expp)->ex_type->tp_fund == FIELD)
|
||||
field2arith(expp);
|
||||
#endif NOBITFIELD
|
||||
switch (fund = (*expp)->ex_type->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case LONG:
|
||||
case ENUM:
|
||||
case POINTER:
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
#endif NOFLOAT
|
||||
break;
|
||||
default:
|
||||
expr_error(*expp, "%s operand to %s",
|
||||
symbol2str(fund), symbol2str(oper));
|
||||
case ERRONEOUS:
|
||||
erroneous2int(expp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
opnd2test(expp, oper)
|
||||
register struct expr **expp;
|
||||
{
|
||||
opnd2logical(expp, oper);
|
||||
if ((*expp)->ex_class == Oper && is_test_op((*expp)->OP_OPER))
|
||||
{ /* It is already a test */ }
|
||||
else
|
||||
ch7bin(expp, NOTEQUAL, intexpr((arith)0, INT));
|
||||
}
|
||||
|
||||
int
|
||||
is_test_op(oper)
|
||||
{
|
||||
switch (oper) {
|
||||
case '<':
|
||||
case '>':
|
||||
case LESSEQ:
|
||||
case GREATEREQ:
|
||||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
case '!':
|
||||
case AND:
|
||||
case OR: /* && and || also impose a test */
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#ifdef ____
|
||||
int
|
||||
is_arith_op(oper)
|
||||
{
|
||||
switch (oper) {
|
||||
case '*':
|
||||
case '/':
|
||||
case '%':
|
||||
case '+':
|
||||
case '-':
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
case '&':
|
||||
case '^':
|
||||
case '|':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
is_asgn_op(oper)
|
||||
{
|
||||
switch (oper) {
|
||||
case '=':
|
||||
case PLUSAB:
|
||||
case MINAB:
|
||||
case TIMESAB:
|
||||
case DIVAB:
|
||||
case MODAB:
|
||||
case LEFTAB:
|
||||
case RIGHTAB:
|
||||
case ANDAB:
|
||||
case ORAB:
|
||||
case XORAB:
|
||||
case PLUSPLUS:
|
||||
case POSTINCR:
|
||||
case MINMIN:
|
||||
case POSTDECR:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
any2opnd(expp, oper)
|
||||
register struct expr **expp;
|
||||
{
|
||||
if (!*expp)
|
||||
return;
|
||||
switch ((*expp)->ex_type->tp_fund) { /* RM 7.1 */
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case ENUM:
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
#endif NOFLOAT
|
||||
any2arith(expp, oper);
|
||||
break;
|
||||
case ARRAY:
|
||||
array2pointer(*expp);
|
||||
break;
|
||||
case POINTER:
|
||||
if ((*expp)->ex_class == String)
|
||||
string2pointer(*expp);
|
||||
break;
|
||||
#ifndef NOBITFIELD
|
||||
case FIELD:
|
||||
field2arith(expp);
|
||||
break;
|
||||
#endif NOBITFIELD
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NOBITFIELD
|
||||
field2arith(expp)
|
||||
register struct expr **expp;
|
||||
{
|
||||
/* The expression to extract the bitfield value from the
|
||||
memory word is put in the tree.
|
||||
*/
|
||||
register struct type *tp = (*expp)->ex_type->tp_up;
|
||||
register struct field *fd = (*expp)->ex_type->tp_field;
|
||||
register struct type *atype = tp->tp_unsigned ? uword_type : word_type;
|
||||
|
||||
(*expp)->ex_type = atype;
|
||||
|
||||
if (atype->tp_unsigned) { /* don't worry about the sign bit */
|
||||
ch7bin(expp, RIGHT, intexpr((arith)fd->fd_shift, INT));
|
||||
ch7bin(expp, '&', intexpr(fd->fd_mask, INT));
|
||||
}
|
||||
else { /* take care of the sign bit: sign extend if needed */
|
||||
arith bits_in_type = atype->tp_size * 8;
|
||||
|
||||
ch7bin(expp, LEFT,
|
||||
intexpr(bits_in_type - fd->fd_width - fd->fd_shift,
|
||||
INT)
|
||||
);
|
||||
ch7bin(expp, RIGHT, intexpr(bits_in_type - fd->fd_width, INT));
|
||||
}
|
||||
ch7cast(expp, CAST, tp); /* restore its original type */
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
|
||||
#ifndef NOFLOAT
|
||||
/* switch_sign_fp() negates the given floating constant expression
|
||||
The lexical analyser has reserved an extra byte of space in front
|
||||
of the string containing the representation of the floating
|
||||
constant. This byte contains the '-' character and we have to
|
||||
take care of the first byte the fl_value pointer points to.
|
||||
*/
|
||||
switch_sign_fp(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
if (*(expr->FL_VALUE) == '-')
|
||||
++(expr->FL_VALUE);
|
||||
else
|
||||
--(expr->FL_VALUE);
|
||||
}
|
||||
#endif NOFLOAT
|
||||
27
lang/cem/cemcom/arith.h
Normal file
27
lang/cem/cemcom/arith.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* COMPILER ARITHMETIC */
|
||||
|
||||
/* Normally the compiler does its internal arithmetics in longs
|
||||
native to the source machine, which is always good for local
|
||||
compilations, and generally OK too for cross compilations
|
||||
downwards and sidewards. For upwards cross compilation and
|
||||
to save storage on small machines, SPECIAL_ARITHMETICS will
|
||||
be handy.
|
||||
*/
|
||||
|
||||
#include "spec_arith.h"
|
||||
|
||||
#ifndef SPECIAL_ARITHMETICS
|
||||
|
||||
#include <em_arith.h> /* obtain definition of "arith" */
|
||||
|
||||
#else SPECIAL_ARITHMETICS
|
||||
|
||||
/* not implemented yet */
|
||||
#define arith int /* dummy */
|
||||
|
||||
#endif SPECIAL_ARITHMETICS
|
||||
16
lang/cem/cemcom/asm.c
Normal file
16
lang/cem/cemcom/asm.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* A S M */
|
||||
|
||||
/*ARGSUSED*/
|
||||
code_asm(s, l)
|
||||
char *s;
|
||||
int l;
|
||||
{
|
||||
/* 'asm' '(' string ')' ';'
|
||||
*/
|
||||
error("\"asm\" instruction not implemented");
|
||||
}
|
||||
21
lang/cem/cemcom/assert.h
Normal file
21
lang/cem/cemcom/assert.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* A S S E R T I O N M A C R O D E F I N I T I O N */
|
||||
|
||||
/* At some points in the program, it must be sure that some condition
|
||||
holds true, due to further, successful, processing. As long as
|
||||
there is no reasonable method to prove that a program is 100%
|
||||
correct, these assertions are needed in some places.
|
||||
*/
|
||||
#include "debug.h" /* UF */
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Note: this macro uses parameter substitution inside strings */
|
||||
#define ASSERT(exp) (exp || crash("in %s, %u: assertion %s failed", \
|
||||
__FILE__, __LINE__, "exp"))
|
||||
#else
|
||||
#define ASSERT(exp)
|
||||
#endif DEBUG
|
||||
10
lang/cem/cemcom/atw.h
Normal file
10
lang/cem/cemcom/atw.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* Align To Word boundary Definition */
|
||||
|
||||
#include "sizes.h"
|
||||
|
||||
#define ATW(arg) ((((arg) + word_size - 1) / word_size) * word_size)
|
||||
161
lang/cem/cemcom/blocks.c
Normal file
161
lang/cem/cemcom/blocks.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* B L O C K S T O R I N G A N D L O A D I N G */
|
||||
|
||||
#include <em.h>
|
||||
#include <em_reg.h>
|
||||
#include "arith.h"
|
||||
#include "sizes.h"
|
||||
#include "atw.h"
|
||||
#include "align.h"
|
||||
#ifndef STB
|
||||
#include "label.h"
|
||||
#include "stack.h"
|
||||
extern arith NewLocal();
|
||||
#define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, 0)
|
||||
#endif STB
|
||||
|
||||
/* Because EM does not support the loading and storing of
|
||||
objects having other sizes than word fragment and multiple,
|
||||
we need to have a way of transferring these objects, whereby
|
||||
we simulate "loi" and "sti": the address of the source resp.
|
||||
destination is located on top of stack and a call is done
|
||||
to load_block() resp. store_block().
|
||||
===============================================================
|
||||
# Loadblock() works on the stack as follows: ([ ] indicates the
|
||||
# position of the stackpointer)
|
||||
# lower address--->
|
||||
# 1) | &object
|
||||
# 2) | ... ATW(sz) bytes ... | sz | &stack_block | &object
|
||||
# 3) | ... ATW(sz) bytes ...
|
||||
===============================================================
|
||||
Loadblock() pushes ATW(sz) bytes directly onto the stack!
|
||||
|
||||
Store_block() works on the stack as follows:
|
||||
lower address--->
|
||||
1) | ... ATW(sz) bytes ... | &object
|
||||
2) | ... ATW(sz) bytes ... | &object | &stack_block | sz
|
||||
3) <empty>
|
||||
|
||||
If sz is a legal argument for "loi" or "sti", just one EM
|
||||
instruction is generated.
|
||||
In the other cases, the notion of alignment is taken into account:
|
||||
we only push an object of the size accepted by EM onto the stack,
|
||||
while we need a loop to store the stack block into a memory object.
|
||||
*/
|
||||
store_block(sz, al)
|
||||
arith sz;
|
||||
int al;
|
||||
{
|
||||
if (
|
||||
((sz == al) && (word_align % al == 0)) ||
|
||||
(
|
||||
(sz % word_size == 0 || word_size % sz == 0) &&
|
||||
(al % word_align == 0)
|
||||
)
|
||||
) /* Lots of Irritating Stupid Parentheses */
|
||||
C_sti(sz);
|
||||
else {
|
||||
#ifndef STB
|
||||
arith src, dst;
|
||||
|
||||
/* allocate two pointer temporaries */
|
||||
src = LocalPtrVar();
|
||||
dst = LocalPtrVar();
|
||||
|
||||
/* load the addresses */
|
||||
StoreLocal(dst, pointer_size);
|
||||
C_lor((arith)1); /* push current sp */
|
||||
StoreLocal(src, pointer_size);
|
||||
copy_loop(sz, src, dst);
|
||||
C_asp(ATW(sz));
|
||||
FreeLocal(dst);
|
||||
FreeLocal(src);
|
||||
#else STB
|
||||
/* address of destination lies on the stack */
|
||||
|
||||
/* push address of first byte of block on stack onto
|
||||
the stack by computing it from the current stack
|
||||
pointer position
|
||||
*/
|
||||
C_lor((arith)1); /* push current sp */
|
||||
C_adp(pointer_size); /* set & to 1st byte of block */
|
||||
C_loc(sz); /* number of bytes to transfer */
|
||||
C_cal("__stb"); /* call transfer routine */
|
||||
C_asp(pointer_size + pointer_size + int_size + ATW(sz));
|
||||
#endif STB
|
||||
}
|
||||
}
|
||||
|
||||
load_block(sz, al)
|
||||
arith sz;
|
||||
int al;
|
||||
{
|
||||
arith esz = ATW(sz); /* effective size == actual # pushed bytes */
|
||||
|
||||
if (
|
||||
((sz == al) && (word_align % al == 0)) ||
|
||||
(
|
||||
(sz % word_size == 0 || word_size % sz == 0) &&
|
||||
(al % word_align == 0)
|
||||
)
|
||||
) /* Lots of Irritating Stupid Parentheses */
|
||||
C_loi(sz);
|
||||
else {
|
||||
#ifndef STB
|
||||
arith src, dst;
|
||||
|
||||
/* allocate two pointer temporaries */
|
||||
src = LocalPtrVar();
|
||||
dst = LocalPtrVar();
|
||||
|
||||
StoreLocal(src, pointer_size);
|
||||
C_asp(-esz); /* allocate stack block */
|
||||
C_lor((arith)1); /* push & of stack block as dst */
|
||||
StoreLocal(dst, pointer_size);
|
||||
copy_loop(sz, src, dst);
|
||||
FreeLocal(dst);
|
||||
FreeLocal(src);
|
||||
#else STB
|
||||
C_asp(-(esz - pointer_size)); /* allocate stack block */
|
||||
C_lor((arith)1); /* push & of stack block as dst */
|
||||
C_dup(pointer_size); /* fetch source address */
|
||||
C_adp(esz - pointer_size);
|
||||
C_loi(pointer_size);
|
||||
C_loc(sz); /* # bytes to copy */
|
||||
C_cal("__stb"); /* library copy routine */
|
||||
C_asp(int_size + pointer_size + pointer_size);
|
||||
#endif STB
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef STB
|
||||
copy_loop(sz, src, dst)
|
||||
arith sz, src, dst;
|
||||
{
|
||||
/* generate inline byte-copy loop */
|
||||
label l_cont = text_label(), l_stop = text_label();
|
||||
|
||||
C_loc(sz); /* amount of bytes */
|
||||
C_df_ilb(l_cont);
|
||||
C_dup(word_size);
|
||||
C_zle(l_stop);
|
||||
C_dec();
|
||||
LoadLocal(src, pointer_size);
|
||||
C_dup(pointer_size);
|
||||
C_adp((arith)1);
|
||||
StoreLocal(src, pointer_size);
|
||||
C_loi((arith)1);
|
||||
LoadLocal(dst, pointer_size);
|
||||
C_dup(pointer_size);
|
||||
C_adp((arith)1);
|
||||
StoreLocal(dst, pointer_size);
|
||||
C_sti((arith)1);
|
||||
C_bra(l_cont);
|
||||
C_df_ilb(l_stop);
|
||||
C_asp(word_size);
|
||||
}
|
||||
#endif STB
|
||||
230
lang/cem/cemcom/cem.1
Normal file
230
lang/cem/cemcom/cem.1
Normal file
@@ -0,0 +1,230 @@
|
||||
.TH CEM 1L 86/11/12
|
||||
.SH NAME
|
||||
cem \- ACK C compiler
|
||||
.SH SYNOPSIS
|
||||
.B cem
|
||||
[ option ] ... file ...
|
||||
.SH DESCRIPTION
|
||||
.I Cem
|
||||
is a
|
||||
.I cc (1)-like
|
||||
C compiler that uses the C front-end compiler
|
||||
.I cemcom (1)
|
||||
of the Amsterdam Compiler Kit.
|
||||
.I Cem
|
||||
interprets its arguments not starting with a '\-' as
|
||||
source files, to be compiled by the various parts of the compilation process,
|
||||
which are listed below.
|
||||
File arguments whose names end with \fB.\fP\fIcharacter\fP are interpreted as
|
||||
follows:
|
||||
.IP .[ao]
|
||||
object file.
|
||||
.IP .[ci]
|
||||
C source code
|
||||
.IP .e
|
||||
EM assembler source file.
|
||||
.IP .k
|
||||
compact EM file, not yet optimized by the EM peephole optimizer.
|
||||
.IP .m
|
||||
compact EM file, already optimized by the peephole optimizer.
|
||||
.IP .s
|
||||
assembler file.
|
||||
.LP
|
||||
The actions to be taken by
|
||||
.I cem
|
||||
are directed by the type of file argument and the various options that are
|
||||
presented to it.
|
||||
.PP
|
||||
The following set of options, which is a mixture of options interpreted by
|
||||
.I cc (1)
|
||||
and
|
||||
.I ack (?)
|
||||
are interpreted by
|
||||
.I cem .
|
||||
(The options not specified here are passed to the loader.)
|
||||
.IP \fB\-B\fP\fIname\fP
|
||||
Use
|
||||
.I name
|
||||
as front-end compiler instead of the default
|
||||
.I cemcom (1).
|
||||
.br
|
||||
Same as "\fB\-Rcem=\fP\fIname\fP".
|
||||
.IP \fB\-C\fP
|
||||
Run C preprocessor
|
||||
.I /lib/cpp
|
||||
only and prevent it from eliding comments.
|
||||
.IP \fB\-D\fP\fIname\fP\fB=\fP\fIdef\fP
|
||||
Define the
|
||||
.I name
|
||||
to the preprocessor, as if by "#define".
|
||||
.IP \fB\-D\fP\fIname\fP
|
||||
.br
|
||||
Same as "\fB\-D\fP\fIname\fP\fB=1\fP".
|
||||
.IP \fB\-E\fP
|
||||
Run only the macro preprocessor on the named files and send the
|
||||
result to standard output.
|
||||
.IP \fB\-I\fP\fIdir\fP
|
||||
\&"#include" files whose names do not begin with '/' are always
|
||||
sought first in the directory of the \fIfile\fP argument, then in directories
|
||||
in \fB\-I\fP options, then in directories on a standard list (which in fact
|
||||
consists of "/usr/include").
|
||||
.IP \fB\-L\fP\fIdir\fP
|
||||
Use \fIdir\fP as library-containing directory instead of the default.
|
||||
.IP \fB\-N\fP\fIc\fP
|
||||
Only effective if ACK pipeline is used.
|
||||
This option causes some default actions and options to be suppressed, according
|
||||
to
|
||||
.I c :
|
||||
.RS
|
||||
.IP \fBc\fP
|
||||
do not convert from EM a.out to local a.out format (i.e., skip the
|
||||
.B cv
|
||||
pass.)
|
||||
.IP \fBl\fP
|
||||
do not pass the default loader flags to the
|
||||
.B ld
|
||||
pass.
|
||||
.RE
|
||||
.IP \fB\-P\fP
|
||||
Same as \fB\-E\fP, but sending the result of input file \fIfile\fP\fB.[ceis]\fP
|
||||
to \fIfile\fP\fB.i\fP.
|
||||
.IP \fB\-R\fP
|
||||
Passed to \fIcemcom\fP(1) in order to parse the named C programs according
|
||||
to the C language as described in [K&R] (also called \fIRestricted\fP C).
|
||||
.IP \fB\-R\fP\fIprog\fP\fB=\fP\fIname\fP
|
||||
.br
|
||||
Use \fIname\fP as program for phase \fIprog\fP of the compilation instead of
|
||||
the default.
|
||||
\&\fIProg\fP is one of the following names:
|
||||
.RS
|
||||
.IP \fBcpp\fP
|
||||
macro preprocessor
|
||||
.IP \fBcem\fP
|
||||
front\-end compiler
|
||||
.IP \fBopt\fP
|
||||
EM peephole optimizer
|
||||
.IP \fBdecode\fP
|
||||
EM compact to EM assembler translator
|
||||
.IP \fBencode\fP
|
||||
EM assembler to EM compact translator
|
||||
.IP \fBbe\fP
|
||||
EM compact code to target\-machine assembly code compiler
|
||||
.IP \fBcg\fP
|
||||
same as \fBbe\fP
|
||||
.IP \fBas\fP
|
||||
assembler
|
||||
.IP \fBld\fP
|
||||
linker/loader
|
||||
.IP \fBcv\fP
|
||||
a.out format converting program (only if ACK pipeline is used)
|
||||
.RE
|
||||
.IP \fB\-R\fP\fIprog\fP\fB\-\fP\fIoption\fP
|
||||
.br
|
||||
Pass \fB\-\fP\fIoption\fP to the compilation phase indicated by \fIprog\fP.
|
||||
.IP \fB\-S\fP
|
||||
Same as \fB\-c.s\fP.
|
||||
.IP \fB\-U\fP\fIname\fP
|
||||
.br
|
||||
Remove any initial definition of \fIname\fP.
|
||||
.IP \fB\-V\fP\fIcm\fP.\fIn\fP,\ \fB\-V\fIcm\fP.\fIncm\fP.\fIn\fP\ ...
|
||||
.br
|
||||
Set the size and alignment requirements of the C constructs of the named
|
||||
C input files.
|
||||
The letter \fIc\fP indicates the simple type, which is one of
|
||||
\fBs\fP(short), \fBi\fP(int), \fBl\fP(long), \fBf\fP(float), \fBd\fP(double) or
|
||||
\fBp\fP(pointer).
|
||||
The \fIm\fP parameter can be used to specify the length of the type (in bytes)
|
||||
and the \fIn\fP parameter for the alignment of that type.
|
||||
Absence of \fIm\fP or \fIn\fP causes the default value to be retained.
|
||||
To specify that the bitfields should be right adjusted instead of the
|
||||
default left adjustment, specify \fBr\fP as \fIc\fP parameter
|
||||
without parameters.
|
||||
.br
|
||||
This option is passed directly to \fIcemcom\fP(1).
|
||||
.IP \fB\-c\fP
|
||||
Same as \fB\-c.o\fP.
|
||||
.IP \fB\-c.e\fP
|
||||
Produce human-readable EM assembly code on \fIfile\fP\fB.e\fP for the
|
||||
named files \fIfile\fP\fB.[cikm]\fP
|
||||
.IP \fB\-c.k\fP
|
||||
Compile C source \fIfile\fP\fB.[ci]\fP or
|
||||
encode human-readable EM assembly code from \fIfile\fP\fB.e\fP
|
||||
into non-optimized compact EM code and write the result on \fIfile\fP\fB.k\fP
|
||||
.IP \fB\-c.m\fP
|
||||
Compile C source \fIfile\fP\fB.[ci]\fP,
|
||||
translate non-optimized EM code from \fIfile\fP\fB.k\fP or
|
||||
encode EM assembly code from \fIfile\fP\fB.e\fP
|
||||
into optimized compact EM code and write the result on \fIfile\fP\fB.m\fP
|
||||
.IP \fB\-c.o\fP
|
||||
Suppress the loading phase of the compilation, and force an object file to
|
||||
be produced even if only one program is compiled
|
||||
.IP \fB\-c.s\fP
|
||||
Compile the named \fIfile\fP\fB.[ceikm]\fP input files, and leave the
|
||||
assembly language output on corresponding files suffixed ".s".
|
||||
.IP \fB\-k\fP
|
||||
Same as \fB\-c.k\fP.
|
||||
.IP \fB\-l\fP\fIname\fP
|
||||
.br
|
||||
Append the library \fBlib\fP\fIname\fP\fB.a\fP to the list of files that
|
||||
should be loaded and linked into the final output file.
|
||||
The library is searched for in the library directory.
|
||||
.IP \fB\-m\fP
|
||||
Same as \fB\-c.m\fP.
|
||||
.IP \fB\-o\fP\ \fIoutput\fP
|
||||
.br
|
||||
Name the final output file \fIoutput\fP.
|
||||
If this option is used, the default "a.out" will be left undisturbed.
|
||||
.IP \fB\-p\fP
|
||||
Produce EM profiling code (\fBfil\fP and \fBlin\fP instructions to
|
||||
enable an interpreter to keep track of the current location in the
|
||||
source code)
|
||||
.IP \fB\-t\fP
|
||||
Keep the intermediate files, produced during the various phases of the
|
||||
compilation.
|
||||
The produced files are named \fIfile\fP\fB.\fP\fIcharacter\fP where
|
||||
\&\fIcharacter\fP indicates the type of the file as listed before.
|
||||
.IP \fB\-v\fP
|
||||
Verbose.
|
||||
Print the commands before they are executed.
|
||||
.IP \fB\-vn\fP
|
||||
Do not really execute (for debugging purposes only).
|
||||
.IP \fB\-vd\fP
|
||||
Print some additional information (for debugging purposes only).
|
||||
.IP \fB\-\-\fP\fIanything\fP
|
||||
.br
|
||||
Equivalent to \fB\-Rcem\-\-\fP\fIanything\fP.
|
||||
The options
|
||||
.B \-\-C ,
|
||||
.B \-\-E
|
||||
and
|
||||
.B \-\-P
|
||||
all have the same effect as respectively
|
||||
.B \-C ,
|
||||
.B \-E
|
||||
and
|
||||
.B \-P
|
||||
except for the fact that the macro preprocessor is taken to be the
|
||||
built\-in preprocessor of the \fBcem\fP phase.
|
||||
Most "\-\-" options are used by
|
||||
.I cemcom (1)
|
||||
to set some internal debug switches.
|
||||
.LP
|
||||
.SH SEE ALSO
|
||||
cemcom(1), cc(1), ack(?), as(1), ld(1)
|
||||
.br
|
||||
.IP [K&R]
|
||||
B.W. Kernighan and D.M. Ritchie, \fIThe C Programming Language\fP,
|
||||
Prentice-Hall, 1978.
|
||||
.SH DIAGNOSTICS
|
||||
.I Cem
|
||||
reports any failure of its components.
|
||||
.SH BUGS
|
||||
.IP \(bu
|
||||
All intermediate files are placed in the current working directory which
|
||||
causes files with the same name as the intermediate files to be overwritten.
|
||||
.IP \(bu
|
||||
.B Cem
|
||||
only accepts a limited number of arguments to be passed to the components.
|
||||
(e.g., 256).
|
||||
.IP \(bu
|
||||
Please report suggestions and other bugs to erikb@vu44.uucp
|
||||
764
lang/cem/cemcom/cem.c
Normal file
764
lang/cem/cemcom/cem.c
Normal file
@@ -0,0 +1,764 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/*
|
||||
Driver for the CEMCOM compiler: works like /bin/cc and accepts
|
||||
most of the options accepted by /bin/cc and /usr/em/bin/ack.
|
||||
Date written: dec 4, 1985
|
||||
Adapted for 68000 (Aug 19, 1986)
|
||||
Merged the vax and mantra versions (Nov 10, 1986)
|
||||
Author: Erik Baalbergen
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAXARGC 256 /* maximum number of arguments allowed in a list */
|
||||
#define USTR_SIZE 1024 /* maximum length of string variable */
|
||||
|
||||
struct arglist {
|
||||
int al_argc;
|
||||
char *al_argv[MAXARGC];
|
||||
};
|
||||
|
||||
/* some system-dependent variables */
|
||||
char *PP = "/lib/cpp";
|
||||
char *CEM = "/usr/em/lib/em_cemcom";
|
||||
char *ENCODE = "/usr/em/lib/em_encode";
|
||||
char *DECODE = "/usr/em/lib/em_decode";
|
||||
char *OPT = "/usr/em/lib/em_opt";
|
||||
char *SHELL = "/bin/sh";
|
||||
|
||||
#ifndef MANTRA
|
||||
char *CG = "/usr/em/lib/vax4/cg";
|
||||
char *AS = "/bin/as";
|
||||
char *AS_FIX = "/user1/erikb/bin/mcomm";
|
||||
char *LD = "/bin/ld";
|
||||
char *LIBDIR = "/user1/cem/lib";
|
||||
char *V_FLAG = "-Vs2.2w4.4i4.4l4.4f4.4d8.4p4.4";
|
||||
#else MANTRA
|
||||
char *CG = "/usr/em/lib/m68k2/cg";
|
||||
char *AS = "/usr/em/lib/m68k2/as";
|
||||
char *LD = "/usr/em/lib/em_led";
|
||||
char *CV = "/usr/em/lib/m68k2/cv";
|
||||
char *LIBDIR = "/usr/em/lib/m68k2";
|
||||
char *V_FLAG = "-Vs2.2w2.2i2.2l4.2f4.2d8.2p4.2";
|
||||
#endif MANTRA
|
||||
|
||||
struct arglist LD_HEAD = {
|
||||
2,
|
||||
{
|
||||
#ifndef MANTRA
|
||||
"/usr/em/lib/vax4/head_em",
|
||||
"/usr/em/lib/vax4/head_cc"
|
||||
#else MANTRA
|
||||
"/usr/em/lib/m68k2/head_em",
|
||||
"/usr/em/lib/m68k2/head_cc"
|
||||
#endif MANTRA
|
||||
}
|
||||
};
|
||||
|
||||
struct arglist LD_TAIL = {
|
||||
#ifndef MANTRA
|
||||
4,
|
||||
{
|
||||
"/user1/cem/lib/libc.a",
|
||||
"/user1/cem/lib/stb.o",
|
||||
"/usr/em/lib/vax4/tail_mon",
|
||||
"/usr/em/lib/vax4/tail_em"
|
||||
}
|
||||
#else MANTRA
|
||||
7,
|
||||
{
|
||||
"/usr/em/lib/m68k2/tail_cc.1s",
|
||||
"/usr/em/lib/m68k2/tail_cc.2g",
|
||||
"/usr/em/lib/m68k2/tail_cem",
|
||||
"/usr/em/lib/m68k2/tail_fp.a",
|
||||
"/usr/em/lib/m68k2/tail_em.rt",
|
||||
"/usr/em/lib/m68k2/tail_mon",
|
||||
"/usr/em/lib/m68k2/end_em"
|
||||
}
|
||||
#endif MANTRA
|
||||
};
|
||||
|
||||
char *o_FILE = "a.out";
|
||||
#ifdef MANTRA
|
||||
char *cv_FILE = "cv.out";
|
||||
#endif MANTRA
|
||||
|
||||
#define remove(str) (((FLAG(t) == 0) && unlink(str)), (str)[0] = '\0')
|
||||
#define cleanup(str) (str && remove(str))
|
||||
#define mkname(dst, s1, s2) mkstr(dst, (s1), (s2), 0)
|
||||
#define init(al) (al)->al_argc = 1
|
||||
#define library(nm) \
|
||||
mkstr(alloc((unsigned int)strlen(nm) + strlen(LIBDIR) + 7), \
|
||||
LIBDIR, "/lib", nm, ".a", 0)
|
||||
|
||||
struct arglist SRCFILES, LDFILES, GEN_LDFILES, PP_FLAGS, CEM_FLAGS,
|
||||
OPT_FLAGS, DECODE_FLAGS, ENCODE_FLAGS, CG_FLAGS, AS_FLAGS,
|
||||
O_FLAGS, DEBUG_FLAGS, CALL_VEC;
|
||||
|
||||
#ifndef MANTRA
|
||||
struct arglist LD_FLAGS;
|
||||
#else MANTRA
|
||||
struct arglist LD_FLAGS = {
|
||||
5,
|
||||
{
|
||||
"-b0:0x80000",
|
||||
"-a0:2",
|
||||
"-a1:2",
|
||||
"-a2:2",
|
||||
"-a3:2"
|
||||
}
|
||||
};
|
||||
struct arglist CV_FLAGS;
|
||||
int Nc_flag = 0;
|
||||
#endif MANTRA
|
||||
|
||||
/* option naming */
|
||||
#define NAME(chr) chr
|
||||
#define FLAG(chr) NAME(chr)_flag
|
||||
int E_flag, P_flag, S_flag, c_flag, e_flag, k_flag,
|
||||
m_flag, o_flag, t_flag, v_flag;
|
||||
|
||||
/* various passes */
|
||||
struct prog {
|
||||
char *p_name;
|
||||
char **p_task;
|
||||
struct arglist *p_flags;
|
||||
} ProgParts[] = {
|
||||
{ "cpp", &PP, &PP_FLAGS },
|
||||
{ "cem", &CEM, &CEM_FLAGS },
|
||||
{ "opt", &OPT, &OPT_FLAGS },
|
||||
{ "decode", &DECODE, &DECODE_FLAGS },
|
||||
{ "encode", &ENCODE, &ENCODE_FLAGS },
|
||||
{ "be", &CG, &CG_FLAGS },
|
||||
{ "cg", &CG, &CG_FLAGS },
|
||||
{ "as", &AS, &AS_FLAGS },
|
||||
{ "ld", &LD, &LD_FLAGS },
|
||||
#ifdef MANTRA
|
||||
{ "cv", &CV, &CV_FLAGS },
|
||||
#endif MANTRA
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* various forward declarations */
|
||||
int trap();
|
||||
char *mkstr();
|
||||
char *alloc();
|
||||
long sizeof_file();
|
||||
|
||||
/* various globals */
|
||||
char *ProgCall = 0;
|
||||
int debug = 0;
|
||||
int exec = 1;
|
||||
int RET_CODE = 0;
|
||||
|
||||
main(argc, argv)
|
||||
char *argv[];
|
||||
{
|
||||
char *str, **argvec, *file, *ldfile = 0;
|
||||
int count, ext;
|
||||
char Nfile[USTR_SIZE], kfile[USTR_SIZE], sfile[USTR_SIZE],
|
||||
mfile[USTR_SIZE], ofile[USTR_SIZE], BASE[USTR_SIZE];
|
||||
register struct arglist *call = &CALL_VEC;
|
||||
|
||||
set_traps(trap);
|
||||
ProgCall = *argv++;
|
||||
append(&CEM_FLAGS, "-L");
|
||||
while (--argc > 0) {
|
||||
if (*(str = *argv++) != '-') {
|
||||
append(&SRCFILES, str);
|
||||
continue;
|
||||
}
|
||||
switch (str[1]) {
|
||||
case '-':
|
||||
switch (str[2]) {
|
||||
case 'C':
|
||||
case 'E':
|
||||
case 'P':
|
||||
FLAG(E) = 1;
|
||||
append(&PP_FLAGS, str);
|
||||
PP = CEM;
|
||||
FLAG(P) = (str[2] == 'P');
|
||||
break;
|
||||
default:
|
||||
append(&DEBUG_FLAGS, str);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
PP = CEM = &str[2];
|
||||
break;
|
||||
case 'C':
|
||||
case 'E':
|
||||
case 'P':
|
||||
FLAG(E) = 1;
|
||||
append(&PP_FLAGS, str);
|
||||
FLAG(P) = (str[1] == 'P');
|
||||
break;
|
||||
case 'c':
|
||||
if (str[2] == '.') {
|
||||
switch (str[3]) {
|
||||
case 's':
|
||||
FLAG(S) = 1;
|
||||
break;
|
||||
case 'k':
|
||||
FLAG(k) = 1;
|
||||
break;
|
||||
case 'o':
|
||||
FLAG(c) = 1;
|
||||
break;
|
||||
case 'm':
|
||||
FLAG(m) = 1;
|
||||
break;
|
||||
case 'e':
|
||||
FLAG(e) = 1;
|
||||
break;
|
||||
default:
|
||||
bad_option(str);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (str[2] == '\0')
|
||||
FLAG(c) = 1;
|
||||
else
|
||||
bad_option(str);
|
||||
break;
|
||||
case 'D':
|
||||
case 'I':
|
||||
case 'U':
|
||||
append(&PP_FLAGS, str);
|
||||
break;
|
||||
case 'k':
|
||||
FLAG(k) = 1;
|
||||
break;
|
||||
case 'l':
|
||||
if (str[2] == '\0') /* no standard libraries */
|
||||
LD_HEAD.al_argc = LD_TAIL.al_argc = 0;
|
||||
else /* use library from library directory */
|
||||
append(&SRCFILES, library(&str[2]));
|
||||
break;
|
||||
case 'L': /* change default library directory */
|
||||
LIBDIR = &str[2];
|
||||
break;
|
||||
case 'm':
|
||||
FLAG(m) = 1;
|
||||
break;
|
||||
#ifdef MANTRA
|
||||
case 'N':
|
||||
switch (str[2]) {
|
||||
case 'c': /* no a.out conversion */
|
||||
Nc_flag = 1;
|
||||
break;
|
||||
case 'l': /* no default options to led */
|
||||
LD_FLAGS.al_argc = 0;
|
||||
break;
|
||||
default:
|
||||
bad_option(str);
|
||||
}
|
||||
break;
|
||||
#endif MANTRA
|
||||
case 'o':
|
||||
FLAG(o) = 1;
|
||||
if (argc-- < 0)
|
||||
bad_option(str);
|
||||
else
|
||||
o_FILE = *argv++;
|
||||
break;
|
||||
case 'O':
|
||||
append(&O_FLAGS, "-O");
|
||||
break;
|
||||
case 'R':
|
||||
if (str[2] == '\0')
|
||||
append(&CEM_FLAGS, str);
|
||||
else
|
||||
Roption(str);
|
||||
break;
|
||||
case 'S':
|
||||
FLAG(S) = 1;
|
||||
break;
|
||||
case 't':
|
||||
FLAG(t) = 1;
|
||||
break;
|
||||
case 'v': /* set debug switches */
|
||||
FLAG(v) = 1;
|
||||
switch (str[2]) {
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
case 'n': /* no execute */
|
||||
exec = 0;
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
bad_option(str);
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
V_FLAG = str;
|
||||
break;
|
||||
default:
|
||||
append(&LD_FLAGS, str);
|
||||
}
|
||||
}
|
||||
if (debug) report("Note: debug output");
|
||||
if (exec == 0)
|
||||
report("Note: no execution");
|
||||
count = SRCFILES.al_argc;
|
||||
argvec = &(SRCFILES.al_argv[0]);
|
||||
Nfile[0] = '\0';
|
||||
while (count-- > 0) {
|
||||
basename(file = *argvec++, BASE);
|
||||
if (FLAG(E)) {
|
||||
char ifile[USTR_SIZE];
|
||||
|
||||
init(call);
|
||||
append(call, PP);
|
||||
concat(call, &DEBUG_FLAGS);
|
||||
concat(call, &PP_FLAGS);
|
||||
append(call, file);
|
||||
runvec(call, FLAG(P) ? mkname(ifile, BASE, ".i") : 0);
|
||||
continue;
|
||||
}
|
||||
ext = extension(file);
|
||||
/* .c to .k and .N */
|
||||
if (ext == 'c' || ext == 'i') {
|
||||
init(call);
|
||||
append(call, CEM);
|
||||
concat(call, &DEBUG_FLAGS);
|
||||
append(call, V_FLAG);
|
||||
concat(call, &CEM_FLAGS);
|
||||
concat(call, &PP_FLAGS);
|
||||
append(call, file);
|
||||
append(call, mkname(kfile, BASE, ".k"));
|
||||
append(call, mkname(Nfile, BASE, ".N"));
|
||||
if (runvec(call, (char *)0)) {
|
||||
file = kfile;
|
||||
ext = 'k';
|
||||
if (sizeof_file(Nfile) <= 0L)
|
||||
remove(Nfile);
|
||||
}
|
||||
else {
|
||||
remove(kfile);
|
||||
remove(Nfile);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* .e to .k */
|
||||
if (ext == 'e') {
|
||||
init(call);
|
||||
append(call, ENCODE);
|
||||
concat(call, &ENCODE_FLAGS);
|
||||
append(call, file);
|
||||
append(call, mkname(kfile, BASE, ".k"));
|
||||
if (runvec(call, (char *)0) == 0)
|
||||
continue;
|
||||
file = kfile;
|
||||
ext = 'k';
|
||||
}
|
||||
if (FLAG(k))
|
||||
continue;
|
||||
/* decode .k or .m */
|
||||
if (FLAG(e) && (ext == 'k' || ext == 'm')) {
|
||||
char efile[USTR_SIZE];
|
||||
init(call);
|
||||
append(call, DECODE);
|
||||
concat(call, &DECODE_FLAGS);
|
||||
append(call, file);
|
||||
append(call, mkname(efile, BASE, ".e"));
|
||||
runvec(call, (char *)0);
|
||||
cleanup(kfile);
|
||||
continue;
|
||||
}
|
||||
/* .k to .m */
|
||||
if (ext == 'k') {
|
||||
init(call);
|
||||
append(call, OPT);
|
||||
concat(call, &OPT_FLAGS);
|
||||
append(call, file);
|
||||
if (runvec(call, mkname(mfile, BASE, ".m")) == 0)
|
||||
continue;
|
||||
file = mfile;
|
||||
ext = 'm';
|
||||
cleanup(kfile);
|
||||
}
|
||||
if (FLAG(m))
|
||||
continue;
|
||||
/* .m to .s */
|
||||
if (ext == 'm') {
|
||||
init(call);
|
||||
append(call, CG);
|
||||
concat(call, &CG_FLAGS);
|
||||
append(call, file);
|
||||
append(call, mkname(sfile, BASE, ".s"));
|
||||
if (runvec(call, (char *)0) == 0)
|
||||
continue;
|
||||
if (Nfile[0] != '\0') {
|
||||
#ifndef MANTRA
|
||||
init(call);
|
||||
append(call, AS_FIX);
|
||||
append(call, Nfile);
|
||||
append(call, sfile);
|
||||
runvec(call, (char *)0);
|
||||
#endif MANTRA
|
||||
remove(Nfile);
|
||||
}
|
||||
cleanup(mfile);
|
||||
file = sfile;
|
||||
ext = 's';
|
||||
}
|
||||
if (FLAG(S))
|
||||
continue;
|
||||
/* .s to .o */
|
||||
if (ext == 's') {
|
||||
ldfile = FLAG(c) ?
|
||||
ofile :
|
||||
alloc((unsigned)strlen(BASE) + 3);
|
||||
init(call);
|
||||
append(call, AS);
|
||||
concat(call, &AS_FLAGS);
|
||||
#ifdef MANTRA
|
||||
append(call, "-");
|
||||
#endif MANTRA
|
||||
append(call, "-o");
|
||||
append(call, mkname(ldfile, BASE, ".o"));
|
||||
append(call, file);
|
||||
if (runvec(call, (char *)0) == 0)
|
||||
continue;
|
||||
file = ldfile;
|
||||
ext = 'o';
|
||||
cleanup(sfile);
|
||||
}
|
||||
if (FLAG(c))
|
||||
continue;
|
||||
append(&LDFILES, file);
|
||||
if (ldfile) {
|
||||
append(&GEN_LDFILES, ldfile);
|
||||
ldfile = 0;
|
||||
}
|
||||
}
|
||||
/* *.o to a.out */
|
||||
if (RET_CODE == 0 && LDFILES.al_argc > 0) {
|
||||
init(call);
|
||||
append(call, LD);
|
||||
concat(call, &LD_FLAGS);
|
||||
append(call, "-o");
|
||||
#ifndef MANTRA
|
||||
append(call, o_FILE);
|
||||
#else MANTRA
|
||||
append(call, Nc_flag ? o_FILE : cv_FILE);
|
||||
#endif MANTRA
|
||||
concat(call, &LD_HEAD);
|
||||
concat(call, &LDFILES);
|
||||
concat(call, &LD_TAIL);
|
||||
if (runvec(call, (char *)0)) {
|
||||
register i = GEN_LDFILES.al_argc;
|
||||
|
||||
while (i-- > 0)
|
||||
remove(GEN_LDFILES.al_argv[i]);
|
||||
#ifdef MANTRA
|
||||
/* convert to local a.out format */
|
||||
if (Nc_flag == 0) {
|
||||
init(call);
|
||||
append(call, CV);
|
||||
concat(call, &CV_FLAGS);
|
||||
append(call, cv_FILE);
|
||||
append(call, o_FILE);
|
||||
if (runvec(call, (char *)0))
|
||||
remove(cv_FILE);
|
||||
}
|
||||
#endif MANTRA
|
||||
}
|
||||
}
|
||||
exit(RET_CODE);
|
||||
}
|
||||
|
||||
#define BUFSIZE (USTR_SIZE * MAXARGC)
|
||||
char alloc_buf[BUFSIZE];
|
||||
|
||||
char *
|
||||
alloc(u)
|
||||
unsigned u;
|
||||
{
|
||||
static char *bufptr = &alloc_buf[0];
|
||||
register char *p = bufptr;
|
||||
|
||||
if ((bufptr += u) >= &alloc_buf[BUFSIZE])
|
||||
panic("no space");
|
||||
return p;
|
||||
}
|
||||
|
||||
append(al, arg)
|
||||
register struct arglist *al;
|
||||
char *arg;
|
||||
{
|
||||
if (al->al_argc >= MAXARGC)
|
||||
panic("argument list overflow");
|
||||
al->al_argv[(al->al_argc)++] = arg;
|
||||
}
|
||||
|
||||
concat(al1, al2)
|
||||
struct arglist *al1, *al2;
|
||||
{
|
||||
register int i = al2->al_argc;
|
||||
register char **p = &(al1->al_argv[al1->al_argc]);
|
||||
register char **q = &(al2->al_argv[0]);
|
||||
|
||||
if ((al1->al_argc += i) >= MAXARGC)
|
||||
panic("argument list overflow");
|
||||
while (i-- > 0)
|
||||
*p++ = *q++;
|
||||
}
|
||||
|
||||
/* The next function is a dirty old one, taking a variable number of
|
||||
arguments.
|
||||
Take care that the last argument is a null-valued pointer!
|
||||
*/
|
||||
/*VARARGS1*/
|
||||
char *
|
||||
mkstr(dst, arg)
|
||||
char *dst, *arg;
|
||||
{
|
||||
char **vec = (char **) &arg;
|
||||
register char *p;
|
||||
register char *q = dst;
|
||||
|
||||
while (p = *vec++) {
|
||||
while (*q++ = *p++);
|
||||
q--;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
Roption(str)
|
||||
char *str; /* of the form "prog=/-arg" */
|
||||
{
|
||||
char *eq;
|
||||
char *prog, *arg;
|
||||
char bc;
|
||||
char *cindex();
|
||||
|
||||
prog = &str[2];
|
||||
if (eq = cindex(prog, '='))
|
||||
bc = '=';
|
||||
else
|
||||
if (eq = cindex(prog, '-'))
|
||||
bc = '-';
|
||||
else {
|
||||
bad_option(str);
|
||||
return;
|
||||
}
|
||||
*eq++ = '\0';
|
||||
if (arg = eq) {
|
||||
char *opt = 0;
|
||||
struct prog *pp = &ProgParts[0];
|
||||
|
||||
if (bc == '-')
|
||||
opt = mkstr(alloc((unsigned)strlen(arg) + 2),
|
||||
"-", arg, 0);
|
||||
while (pp->p_name) {
|
||||
if (strcmp(prog, pp->p_name) == 0) {
|
||||
if (opt)
|
||||
append(pp->p_flags, opt);
|
||||
else
|
||||
*(pp->p_task) = arg;
|
||||
return;
|
||||
}
|
||||
pp++;
|
||||
}
|
||||
}
|
||||
bad_option(str);
|
||||
}
|
||||
|
||||
basename(str, dst)
|
||||
char *str;
|
||||
register char *dst;
|
||||
{
|
||||
register char *p1 = str;
|
||||
register char *p2 = p1;
|
||||
|
||||
while (*p1)
|
||||
if (*p1++ == '/')
|
||||
p2 = p1;
|
||||
p1--;
|
||||
if (*--p1 == '.') {
|
||||
*p1 = '\0';
|
||||
while (*dst++ = *p2++) {}
|
||||
*p1 = '.';
|
||||
}
|
||||
else
|
||||
while (*dst++ = *p2++) {}
|
||||
}
|
||||
|
||||
int
|
||||
extension(fn)
|
||||
register char *fn;
|
||||
{
|
||||
char c;
|
||||
|
||||
while (*fn++) {}
|
||||
fn--;
|
||||
c = *--fn;
|
||||
return (*--fn == '.') ? c : 0;
|
||||
}
|
||||
|
||||
long
|
||||
sizeof_file(nm)
|
||||
char *nm;
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat(nm, &stbuf) == 0)
|
||||
return stbuf.st_size;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char * sysmsg[] = {
|
||||
0,
|
||||
"Hangup",
|
||||
"Interrupt",
|
||||
"Quit",
|
||||
"Illegal instruction",
|
||||
"Trace/BPT trap",
|
||||
"IOT trap",
|
||||
"EMT trap",
|
||||
"Floating exception",
|
||||
"Killed",
|
||||
"Bus error",
|
||||
"Memory fault",
|
||||
"Bad system call",
|
||||
"Broken pipe",
|
||||
"Alarm call",
|
||||
"Terminated",
|
||||
"Signal 16"
|
||||
};
|
||||
|
||||
runvec(vec, outp)
|
||||
struct arglist *vec;
|
||||
char *outp;
|
||||
{
|
||||
int status, fd;
|
||||
char *task = vec->al_argv[1];
|
||||
|
||||
vec->al_argv[vec->al_argc] = 0;
|
||||
if (FLAG(v))
|
||||
print_vec(vec);
|
||||
if (exec == 0)
|
||||
return 1;
|
||||
if (fork() == 0) { /* start up the process */
|
||||
extern int errno;
|
||||
if (outp) { /* redirect standard output */
|
||||
close(1);
|
||||
if ((fd = creat(outp, 0666)) < 0)
|
||||
panic("cannot create %s", outp);
|
||||
if (fd != 1)
|
||||
panic("illegal redirection");
|
||||
}
|
||||
if (debug) report("exec %s", task);
|
||||
execv(task, &(vec->al_argv[1]));
|
||||
/* not an a.out file, let's try it with the SHELL */
|
||||
if (debug) report("try it with %s", SHELL);
|
||||
if (errno == ENOEXEC) {
|
||||
vec->al_argv[0] = SHELL;
|
||||
execv(SHELL, &(vec->al_argv[0]));
|
||||
}
|
||||
/* failed, so ... */
|
||||
panic("cannot execute %s", task);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
int loworder, highorder, sig;
|
||||
|
||||
wait(&status);
|
||||
loworder = status & 0377;
|
||||
highorder = (status >> 8) & 0377;
|
||||
if (loworder == 0) {
|
||||
if (highorder)
|
||||
report("%s: exit status %d", task, highorder);
|
||||
return highorder ? ((RET_CODE = 1), 0) : 1;
|
||||
}
|
||||
else {
|
||||
sig = loworder & 0177;
|
||||
if (sig == 0177)
|
||||
report("%s: stopped by ptrace", task);
|
||||
else
|
||||
if (sysmsg[sig])
|
||||
report("%s: %s%s", task, sysmsg[sig],
|
||||
(loworder & 0200)
|
||||
? " - core dumped"
|
||||
: "");
|
||||
RET_CODE = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
bad_option(str)
|
||||
char *str;
|
||||
{
|
||||
report("bad option %s", str);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
report(fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
char *fmt;
|
||||
{
|
||||
fprintf(stderr, "%s: ", ProgCall);
|
||||
fprintf(stderr, fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
panic(fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
char *fmt;
|
||||
{
|
||||
fprintf(stderr, "%s: ", ProgCall);
|
||||
fprintf(stderr, fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
set_traps(f)
|
||||
int (*f)();
|
||||
{
|
||||
signal(SIGHUP, f);
|
||||
signal(SIGINT, f);
|
||||
signal(SIGQUIT, f);
|
||||
signal(SIGALRM, f);
|
||||
signal(SIGTERM, f);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
trap(sig)
|
||||
{
|
||||
set_traps(SIG_IGN);
|
||||
panic("Trapped");
|
||||
}
|
||||
|
||||
print_vec(vec)
|
||||
struct arglist *vec;
|
||||
{
|
||||
register i;
|
||||
|
||||
for (i = 1; i < vec->al_argc; i++)
|
||||
printf("%s ", vec->al_argv[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
char *
|
||||
cindex(s, c)
|
||||
char *s, c;
|
||||
{
|
||||
while (*s)
|
||||
if (*s++ == c)
|
||||
return s - 1;
|
||||
return (char *) 0;
|
||||
}
|
||||
79
lang/cem/cemcom/cemcom.1
Normal file
79
lang/cem/cemcom/cemcom.1
Normal file
@@ -0,0 +1,79 @@
|
||||
.TH EM_CEMCOM 6ACK
|
||||
.ad
|
||||
.SH NAME
|
||||
em_cemcom \- C to EM compiler
|
||||
.SH SYNOPSIS
|
||||
\fB~/em/lib/em_cemcom\fP [\fIoptions\fP] \fIsource \fP[\fIdestination \fP[\fInamelist\fP]]
|
||||
.SH DESCRIPTION
|
||||
\fICemcom\fP is a compiler that translates C programs
|
||||
into EM compact code.
|
||||
The input is taken from \fIsource\fP, while the
|
||||
EM code is written on \fIdestination\fP.
|
||||
If either of these two names is "\fB-\fP", standard input or output respectively
|
||||
is taken.
|
||||
The file \fInamelist\fP, if supplied, will contain a list of the names
|
||||
of external, so-called \fBcommon\fP, variables.
|
||||
When the preprocessor is invoked to run stand-alone, \fIdestination\fP
|
||||
needs not be specified.
|
||||
.br
|
||||
\fIOptions\fP is a, possibly empty, sequence of the following combinations:
|
||||
.IP \fB\-D\fIname\fR=\fItext\fR
|
||||
.br
|
||||
define \fIname\fR as a macro with \fItext\fR as its replacement text.
|
||||
.IP \fB\-D\fIname\fR
|
||||
.br
|
||||
the same as \fB\-D\fIname\fR=1.
|
||||
.IP \fB\-I\fIdirname\fR
|
||||
.br
|
||||
insert \fIdirname\fR in the list of include directories.
|
||||
.IP \fB\-M\fP\fIn\fP
|
||||
set maximum identifier length to \fIn\fP.
|
||||
.IP \fB\-n\fR
|
||||
do not generate EM register messages.
|
||||
The user-declared variables are not stored into registers on the target
|
||||
machine.
|
||||
.IP \fB\-L\fR
|
||||
don't generate the EM \fBfil\fR and \fBlin\fR instructions
|
||||
that usually are generated to enable
|
||||
an interpreter to keep track of the current location in the source code.
|
||||
.IP \fB\-p\fR
|
||||
generate code at each procedure entry to call the routine
|
||||
.BR procentry ,
|
||||
and at each return to call the routine
|
||||
.BE procexit .
|
||||
These routines are supplied with one parameter, a pointer to a
|
||||
string containing the name of the procedure.
|
||||
.IP \fB\-R\fR
|
||||
interpret the input as restricted C (according to the language as
|
||||
described in \fIThe C programming language\fR by Kernighan and Ritchie.)
|
||||
.IP \fB\-U\fIname\fR
|
||||
.br
|
||||
get rid of the compiler-predefined macro \fIname\fR.
|
||||
.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
|
||||
\fBs\fR(short), \fBi\fR(int), \fBl\fR(long), \fBf\fR(float), \fBd\fR(double) or
|
||||
\fBp\fR(pointer).
|
||||
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 the default value to be retained.
|
||||
To specify that the bitfields should be right adjusted instead of the
|
||||
default left adjustment, specify \fBr\fR as \fIc\fR parameter.
|
||||
.IP \fB\-w\fR
|
||||
suppress warning messages
|
||||
.IP \fB\-\-\fItext\fR
|
||||
.br
|
||||
where \fItext\fR can be either of the above or
|
||||
a debug flag of the compiler (which is not useful for the common user.)
|
||||
This feature can be used in various shell scripts and surrounding programs
|
||||
to force a certain option to be handed over to \fBcemcom\fR.
|
||||
.LP
|
||||
.SH FILES
|
||||
.IR ~em/lib/em_cemcom :
|
||||
the compiler
|
||||
.SH DIAGNOSTICS
|
||||
All warning and error messages are written on standard error output.
|
||||
.SH REFERENCE
|
||||
Baalbergen, E.H., D. Grune, M. Waage ;"\fIThe CEM compiler\fR",
|
||||
Informatica Manual IM-4
|
||||
393
lang/cem/cemcom/ch7.c
Normal file
393
lang/cem/cemcom/ch7.c
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* S E M A N T I C A N A L Y S I S -- C H A P T E R 7 RM */
|
||||
|
||||
#include "nofloat.h"
|
||||
#include "debug.h"
|
||||
#include "nobitfield.h"
|
||||
#include "idf.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "struct.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "def.h"
|
||||
#include "Lpars.h"
|
||||
#include "assert.h"
|
||||
|
||||
extern char options[];
|
||||
extern char *symbol2str();
|
||||
|
||||
/* Most expression-handling routines have a pointer to a
|
||||
(struct type *) as first parameter. The object under the pointer
|
||||
gets updated in the process.
|
||||
*/
|
||||
|
||||
ch7sel(expp, oper, idf)
|
||||
struct expr **expp;
|
||||
struct idf *idf;
|
||||
{
|
||||
/* The selector idf is applied to *expp; oper may be '.' or
|
||||
ARROW.
|
||||
*/
|
||||
register struct expr *exp;
|
||||
register struct type *tp;
|
||||
register struct sdef *sd;
|
||||
|
||||
any2opnd(expp, oper);
|
||||
exp = *expp;
|
||||
tp = exp->ex_type;
|
||||
if (oper == ARROW) {
|
||||
if (tp->tp_fund == POINTER &&
|
||||
( tp->tp_up->tp_fund == STRUCT ||
|
||||
tp->tp_up->tp_fund == UNION)) /* normal case */
|
||||
tp = tp->tp_up;
|
||||
else { /* constructions like "12->selector" and
|
||||
"char c; c->selector"
|
||||
*/
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
/* Allowed by RM 14.1 */
|
||||
ch7cast(expp, CAST, pa_type);
|
||||
sd = idf2sdef(idf, tp);
|
||||
tp = sd->sd_stype;
|
||||
break;
|
||||
case POINTER:
|
||||
break;
|
||||
default:
|
||||
expr_error(exp, "-> applied to %s",
|
||||
symbol2str(tp->tp_fund));
|
||||
case ERRONEOUS:
|
||||
exp->ex_type = error_type;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} /* oper == ARROW */
|
||||
else { /* oper == '.' */
|
||||
/* filter out illegal expressions "non_lvalue.sel" */
|
||||
if (!exp->ex_lvalue) {
|
||||
expr_error(exp, "dot requires lvalue");
|
||||
return;
|
||||
}
|
||||
}
|
||||
exp = *expp;
|
||||
switch (tp->tp_fund) {
|
||||
case POINTER: /* for int *p; p->next = ... */
|
||||
case STRUCT:
|
||||
case UNION:
|
||||
break;
|
||||
case INT:
|
||||
case LONG:
|
||||
/* warning will be given by idf2sdef() */
|
||||
break;
|
||||
default:
|
||||
if (!is_anon_idf(idf))
|
||||
expr_error(exp, "selector %s applied to %s",
|
||||
idf->id_text, symbol2str(tp->tp_fund));
|
||||
case ERRONEOUS:
|
||||
exp->ex_type = error_type;
|
||||
return;
|
||||
}
|
||||
sd = idf2sdef(idf, tp);
|
||||
if (oper == '.') {
|
||||
/* there are 3 cases in which the selection can be
|
||||
performed compile-time:
|
||||
I: n.sel (n either an identifier or a constant)
|
||||
II: (e.s1).s2 (transformed into (e.(s1+s2)))
|
||||
III: (e->s1).s2 (transformed into (e->(s1+s2)))
|
||||
The code performing these conversions is
|
||||
extremely obscure.
|
||||
*/
|
||||
if (exp->ex_class == Value) {
|
||||
/* It is an object we know the address of; so
|
||||
we can calculate the address of the
|
||||
selected member
|
||||
*/
|
||||
exp->VL_VALUE += sd->sd_offset;
|
||||
exp->ex_type = sd->sd_type;
|
||||
if (exp->ex_type == error_type)
|
||||
exp->ex_flags |= EX_ERROR;
|
||||
}
|
||||
else
|
||||
if (exp->ex_class == Oper) {
|
||||
struct oper *op = &(exp->ex_object.ex_oper);
|
||||
|
||||
if (op->op_oper == '.' || op->op_oper == ARROW) {
|
||||
ASSERT(is_cp_cst(op->op_right));
|
||||
op->op_right->VL_VALUE += sd->sd_offset;
|
||||
exp->ex_type = sd->sd_type;
|
||||
if (exp->ex_type == error_type)
|
||||
exp->ex_flags |= EX_ERROR;
|
||||
}
|
||||
else
|
||||
exp = new_oper(sd->sd_type, exp, '.',
|
||||
intexpr(sd->sd_offset, INT));
|
||||
}
|
||||
}
|
||||
else /* oper == ARROW */
|
||||
exp = new_oper(sd->sd_type,
|
||||
exp, oper, intexpr(sd->sd_offset, INT));
|
||||
exp->ex_lvalue = (sd->sd_type->tp_fund != ARRAY);
|
||||
*expp = exp;
|
||||
}
|
||||
|
||||
ch7incr(expp, oper)
|
||||
struct expr **expp;
|
||||
{
|
||||
/* The monadic prefix/postfix incr/decr operator oper is
|
||||
applied to *expp.
|
||||
*/
|
||||
ch7asgn(expp, oper, intexpr((arith)1, INT));
|
||||
}
|
||||
|
||||
ch7cast(expp, oper, tp)
|
||||
register struct expr **expp;
|
||||
register struct type *tp;
|
||||
{
|
||||
/* The expression *expp is cast to type tp; the cast is
|
||||
caused by the operator oper. If the cast has
|
||||
to be passed on to run time, its left operand will be an
|
||||
expression of class Type.
|
||||
*/
|
||||
register struct type *oldtp;
|
||||
|
||||
if ((*expp)->ex_type->tp_fund == FUNCTION)
|
||||
function2pointer(*expp);
|
||||
if ((*expp)->ex_type->tp_fund == ARRAY)
|
||||
array2pointer(*expp);
|
||||
if ((*expp)->ex_class == String)
|
||||
string2pointer(*expp);
|
||||
oldtp = (*expp)->ex_type;
|
||||
#ifndef NOBITFIELD
|
||||
if (oldtp->tp_fund == FIELD) {
|
||||
field2arith(expp);
|
||||
ch7cast(expp, oper, tp);
|
||||
}
|
||||
else
|
||||
if (tp->tp_fund == FIELD)
|
||||
ch7cast(expp, oper, tp->tp_up);
|
||||
else
|
||||
#endif NOBITFIELD
|
||||
if (oldtp == tp)
|
||||
{} /* life is easy */
|
||||
else
|
||||
if (tp->tp_fund == VOID) /* Easy again */
|
||||
(*expp)->ex_type = void_type;
|
||||
else
|
||||
if (is_arith_type(oldtp) && is_arith_type(tp)) {
|
||||
int oldi = is_integral_type(oldtp);
|
||||
int i = is_integral_type(tp);
|
||||
|
||||
if (oldi && i) {
|
||||
if ( oldtp->tp_fund == ENUM &&
|
||||
tp->tp_fund == ENUM &&
|
||||
oper != CAST
|
||||
)
|
||||
expr_warning(*expp,
|
||||
"%s on enums of different types",
|
||||
symbol2str(oper));
|
||||
int2int(expp, tp);
|
||||
}
|
||||
#ifndef NOFLOAT
|
||||
else
|
||||
if (oldi && !i) {
|
||||
if (oldtp->tp_fund == ENUM && oper != CAST)
|
||||
expr_warning(*expp,
|
||||
"conversion of enum to %s\n",
|
||||
symbol2str(tp->tp_fund));
|
||||
int2float(expp, tp);
|
||||
}
|
||||
else
|
||||
if (!oldi && i)
|
||||
float2int(expp, tp);
|
||||
else /* !oldi && !i */
|
||||
float2float(expp, tp);
|
||||
#else NOFLOAT
|
||||
else
|
||||
crash("(ch7cast) floats not implemented\n");
|
||||
#endif NOFLOAT
|
||||
}
|
||||
else
|
||||
if (oldtp->tp_fund == POINTER && tp->tp_fund == POINTER) {
|
||||
if (oper != CAST)
|
||||
expr_warning(*expp, "incompatible pointers in %s",
|
||||
symbol2str(oper));
|
||||
(*expp)->ex_type = tp; /* free conversion */
|
||||
}
|
||||
else
|
||||
if (oldtp->tp_fund == POINTER && is_integral_type(tp)) {
|
||||
/* from pointer to integral */
|
||||
if (oper != CAST)
|
||||
expr_warning(*expp,
|
||||
"illegal conversion of pointer to %s",
|
||||
symbol2str(tp->tp_fund));
|
||||
if (oldtp->tp_size > tp->tp_size)
|
||||
expr_warning(*expp,
|
||||
"conversion of pointer to %s loses accuracy",
|
||||
symbol2str(tp->tp_fund));
|
||||
if (oldtp->tp_size != tp->tp_size)
|
||||
int2int(expp, tp);
|
||||
else
|
||||
(*expp)->ex_type = tp;
|
||||
}
|
||||
else
|
||||
if (tp->tp_fund == POINTER && is_integral_type(oldtp)) {
|
||||
/* from integral to pointer */
|
||||
switch (oper) {
|
||||
case CAST:
|
||||
break;
|
||||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
case '=':
|
||||
case RETURN:
|
||||
if (is_cp_cst(*expp) && (*expp)->VL_VALUE == (arith)0)
|
||||
break;
|
||||
default:
|
||||
expr_warning(*expp,
|
||||
"illegal conversion of %s to pointer",
|
||||
symbol2str(oldtp->tp_fund));
|
||||
break;
|
||||
}
|
||||
if (oldtp->tp_size > tp->tp_size)
|
||||
expr_warning(*expp,
|
||||
"conversion of %s to pointer loses accuracy",
|
||||
symbol2str(oldtp->tp_fund));
|
||||
if (oldtp->tp_size != tp->tp_size)
|
||||
int2int(expp, tp);
|
||||
else
|
||||
(*expp)->ex_type = tp;
|
||||
}
|
||||
else
|
||||
if (oldtp->tp_fund == ERRONEOUS) /* we just won't look */
|
||||
(*expp)->ex_type = tp; /* brute force */
|
||||
else
|
||||
if (oldtp->tp_size == tp->tp_size && oper == CAST) {
|
||||
expr_warning(*expp, "dubious conversion based on equal size");
|
||||
(*expp)->ex_type = tp; /* brute force */
|
||||
}
|
||||
else {
|
||||
if (oldtp->tp_fund != ERRONEOUS && tp->tp_fund != ERRONEOUS)
|
||||
expr_error(*expp, "cannot convert %s to %s",
|
||||
symbol2str(oldtp->tp_fund),
|
||||
symbol2str(tp->tp_fund)
|
||||
);
|
||||
(*expp)->ex_type = tp; /* brute force */
|
||||
}
|
||||
}
|
||||
|
||||
ch7asgn(expp, oper, expr)
|
||||
struct expr **expp;
|
||||
struct expr *expr;
|
||||
{
|
||||
/* The assignment operators.
|
||||
"f op= e" should be interpreted as
|
||||
"f = (typeof f)((typeof (f op e))f op (typeof (f op e))e)"
|
||||
and not as "f = f op (typeof f)e".
|
||||
Consider, for example, (i == 10) i *= 0.9; (i == 9), where
|
||||
typeof i == int.
|
||||
The resulting expression tree becomes:
|
||||
op=
|
||||
/ \
|
||||
/ \
|
||||
f (typeof (f op e))e
|
||||
EVAL should however take care of evaluating (typeof (f op e))f
|
||||
*/
|
||||
register struct expr *exp = *expp;
|
||||
int fund = exp->ex_type->tp_fund;
|
||||
struct type *tp;
|
||||
|
||||
/* We expect an lvalue */
|
||||
if (!exp->ex_lvalue) {
|
||||
expr_error(exp, "no lvalue in lhs of %s", symbol2str(oper));
|
||||
exp->ex_depth = 99; /* no direct store/load at EVAL() */
|
||||
/* what is 99 ??? DG */
|
||||
}
|
||||
if (oper == '=') {
|
||||
ch7cast(&expr, oper, exp->ex_type);
|
||||
tp = expr->ex_type;
|
||||
}
|
||||
else { /* turn e into e' where typeof(e') = typeof (f op e) */
|
||||
struct expr *extmp = intexpr((arith)0, INT);
|
||||
|
||||
/* this is really $#@&*%$# ! */
|
||||
extmp->ex_lvalue = 1;
|
||||
extmp->ex_type = exp->ex_type;
|
||||
ch7bin(&extmp, oper, expr);
|
||||
/* Note that ch7bin creates a tree of the expression
|
||||
((typeof (f op e))f op (typeof (f op e))e),
|
||||
where f ~ extmp and e ~ expr.
|
||||
We want to use (typeof (f op e))e.
|
||||
Ch7bin does not create a tree if both operands
|
||||
were illegal or constants!
|
||||
*/
|
||||
tp = extmp->ex_type; /* perform the arithmetic in type tp */
|
||||
if (extmp->ex_class == Oper) {
|
||||
expr = extmp->OP_RIGHT;
|
||||
extmp->OP_RIGHT = NILEXPR;
|
||||
free_expression(extmp);
|
||||
}
|
||||
else
|
||||
expr = extmp;
|
||||
}
|
||||
#ifndef NOBITFIELD
|
||||
if (fund == FIELD)
|
||||
exp = new_oper(exp->ex_type->tp_up, exp, oper, expr);
|
||||
else
|
||||
exp = new_oper(exp->ex_type, exp, oper, expr);
|
||||
#else NOBITFIELD
|
||||
exp = new_oper(exp->ex_type, exp, oper, expr);
|
||||
#endif NOBITFIELD
|
||||
exp->OP_TYPE = tp; /* for EVAL() */
|
||||
exp->ex_flags |= EX_SIDEEFFECTS;
|
||||
*expp = exp;
|
||||
}
|
||||
|
||||
/* Some interesting (?) questions answered.
|
||||
*/
|
||||
int
|
||||
is_integral_type(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
switch (tp->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case LONG:
|
||||
case ENUM:
|
||||
return 1;
|
||||
#ifndef NOBITFIELD
|
||||
case FIELD:
|
||||
return is_integral_type(tp->tp_up);
|
||||
#endif NOBITFIELD
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
is_arith_type(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
switch (tp->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case LONG:
|
||||
case ENUM:
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
#endif NOFLOAT
|
||||
return 1;
|
||||
#ifndef NOBITFIELD
|
||||
case FIELD:
|
||||
return is_arith_type(tp->tp_up);
|
||||
#endif NOBITFIELD
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
324
lang/cem/cemcom/ch7bin.c
Normal file
324
lang/cem/cemcom/ch7bin.c
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* SEMANTIC ANALYSIS (CHAPTER 7RM) -- BINARY OPERATORS */
|
||||
|
||||
#include "botch_free.h"
|
||||
#include <alloc.h>
|
||||
#include "nofloat.h"
|
||||
#include "idf.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "struct.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "Lpars.h"
|
||||
#include "noRoption.h"
|
||||
|
||||
extern char options[];
|
||||
extern char *symbol2str();
|
||||
|
||||
/* This chapter asks for the repeated application of code to handle
|
||||
an operation that may be executed at compile time or at run time,
|
||||
depending on the constancy of the operands.
|
||||
*/
|
||||
|
||||
#define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
|
||||
#define non_commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 0)
|
||||
|
||||
ch7bin(expp, oper, expr)
|
||||
register struct expr **expp;
|
||||
struct expr *expr;
|
||||
{
|
||||
/* apply binary operator oper between *expp and expr.
|
||||
NB: don't swap operands if op is one of the op= operators!!!
|
||||
*/
|
||||
any2opnd(expp, oper);
|
||||
any2opnd(&expr, oper);
|
||||
switch (oper) {
|
||||
case '[': /* RM 7.1 */
|
||||
/* RM 14.3 states that indexing follows the commutative laws */
|
||||
switch ((*expp)->ex_type->tp_fund) {
|
||||
case POINTER:
|
||||
case ARRAY:
|
||||
break;
|
||||
case ERRONEOUS:
|
||||
return;
|
||||
default: /* unindexable */
|
||||
switch (expr->ex_type->tp_fund) {
|
||||
case POINTER:
|
||||
case ARRAY:
|
||||
break;
|
||||
case ERRONEOUS:
|
||||
return;
|
||||
default:
|
||||
expr_error(*expp,
|
||||
"indexing an object of type %s",
|
||||
symbol2str((*expp)->ex_type->tp_fund));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ch7bin(expp, '+', expr);
|
||||
ch7mon('*', expp);
|
||||
break;
|
||||
case '(': /* RM 7.1 */
|
||||
if ( (*expp)->ex_type->tp_fund == POINTER &&
|
||||
(*expp)->ex_type->tp_up->tp_fund == FUNCTION
|
||||
) {
|
||||
#ifndef NOROPTION
|
||||
if (options['R'])
|
||||
warning("function pointer called");
|
||||
#endif NOROPTION
|
||||
ch7mon('*', expp);
|
||||
}
|
||||
if ((*expp)->ex_type->tp_fund != FUNCTION) {
|
||||
expr_error(*expp, "call of non-function (%s)",
|
||||
symbol2str((*expp)->ex_type->tp_fund));
|
||||
/* leave the expression; it may still serve */
|
||||
free_expression(expr); /* there go the parameters */
|
||||
}
|
||||
else
|
||||
*expp = new_oper((*expp)->ex_type->tp_up,
|
||||
*expp, '(', expr);
|
||||
(*expp)->ex_flags |= EX_SIDEEFFECTS;
|
||||
break;
|
||||
case PARCOMMA: /* RM 7.1 */
|
||||
if ((*expp)->ex_type->tp_fund == FUNCTION)
|
||||
function2pointer(*expp);
|
||||
*expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
|
||||
break;
|
||||
case '%':
|
||||
case MODAB:
|
||||
case ANDAB:
|
||||
case XORAB:
|
||||
case ORAB:
|
||||
opnd2integral(expp, oper);
|
||||
opnd2integral(&expr, oper);
|
||||
/* Fall through */
|
||||
case '/':
|
||||
case DIVAB:
|
||||
case TIMESAB:
|
||||
arithbalance(expp, oper, &expr);
|
||||
non_commutative_binop(expp, oper, expr);
|
||||
break;
|
||||
case '&':
|
||||
case '^':
|
||||
case '|':
|
||||
opnd2integral(expp, oper);
|
||||
opnd2integral(&expr, oper);
|
||||
/* Fall through */
|
||||
case '*':
|
||||
arithbalance(expp, oper, &expr);
|
||||
commutative_binop(expp, oper, expr);
|
||||
break;
|
||||
case '+':
|
||||
if (expr->ex_type->tp_fund == POINTER) { /* swap operands */
|
||||
struct expr *etmp = expr;
|
||||
expr = *expp;
|
||||
*expp = etmp;
|
||||
}
|
||||
/*FALLTHROUGH*/
|
||||
case PLUSAB:
|
||||
case POSTINCR:
|
||||
case PLUSPLUS:
|
||||
if ((*expp)->ex_type->tp_fund == POINTER) {
|
||||
pointer_arithmetic(expp, oper, &expr);
|
||||
if (expr->ex_type->tp_size != (*expp)->ex_type->tp_size)
|
||||
ch7cast(&expr, CAST, (*expp)->ex_type);
|
||||
pointer_binary(expp, oper, expr);
|
||||
}
|
||||
else {
|
||||
arithbalance(expp, oper, &expr);
|
||||
if (oper == '+')
|
||||
commutative_binop(expp, oper, expr);
|
||||
else
|
||||
non_commutative_binop(expp, oper, expr);
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
case MINAB:
|
||||
case POSTDECR:
|
||||
case MINMIN:
|
||||
if ((*expp)->ex_type->tp_fund == POINTER) {
|
||||
if (expr->ex_type->tp_fund == POINTER)
|
||||
pntminuspnt(expp, oper, expr);
|
||||
else {
|
||||
pointer_arithmetic(expp, oper, &expr);
|
||||
pointer_binary(expp, oper, expr);
|
||||
}
|
||||
}
|
||||
else {
|
||||
arithbalance(expp, oper, &expr);
|
||||
non_commutative_binop(expp, oper, expr);
|
||||
}
|
||||
break;
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
case LEFTAB:
|
||||
case RIGHTAB:
|
||||
opnd2integral(expp, oper);
|
||||
opnd2integral(&expr, oper);
|
||||
arithbalance(expp, oper, &expr); /* ch. 7.5 */
|
||||
ch7cast(&expr, oper, int_type); /* cvt. rightop to int */
|
||||
non_commutative_binop(expp, oper, expr);
|
||||
break;
|
||||
case '<':
|
||||
case '>':
|
||||
case LESSEQ:
|
||||
case GREATEREQ:
|
||||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
relbalance(expp, oper, &expr);
|
||||
non_commutative_binop(expp, oper, expr);
|
||||
(*expp)->ex_type = int_type;
|
||||
break;
|
||||
case AND:
|
||||
case OR:
|
||||
opnd2test(expp, oper);
|
||||
opnd2test(&expr, oper);
|
||||
if (is_cp_cst(*expp)) {
|
||||
register struct expr *ex = *expp;
|
||||
|
||||
/* the following condition is a short-hand for
|
||||
((oper == AND) && o1) || ((oper == OR) && !o1)
|
||||
where o1 == (*expp)->VL_VALUE;
|
||||
and ((oper == AND) || (oper == OR))
|
||||
*/
|
||||
if ((oper == AND) == (ex->VL_VALUE != (arith)0))
|
||||
*expp = expr;
|
||||
else {
|
||||
ex->ex_flags |= expr->ex_flags;
|
||||
free_expression(expr);
|
||||
*expp = intexpr((arith)((oper == AND) ? 0 : 1),
|
||||
INT);
|
||||
}
|
||||
(*expp)->ex_flags |= ex->ex_flags;
|
||||
free_expression(ex);
|
||||
}
|
||||
else
|
||||
if (is_cp_cst(expr)) {
|
||||
/* Note!!!: the following condition is a short-hand for
|
||||
((oper == AND) && o2) || ((oper == OR) && !o2)
|
||||
where o2 == expr->VL_VALUE
|
||||
and ((oper == AND) || (oper == OR))
|
||||
*/
|
||||
if ((oper == AND) == (expr->VL_VALUE != (arith)0)) {
|
||||
(*expp)->ex_flags |= expr->ex_flags;
|
||||
free_expression(expr);
|
||||
}
|
||||
else {
|
||||
if (oper == OR)
|
||||
expr->VL_VALUE = (arith)1;
|
||||
ch7bin(expp, ',', expr);
|
||||
}
|
||||
}
|
||||
else
|
||||
*expp = new_oper(int_type, *expp, oper, expr);
|
||||
(*expp)->ex_flags |= EX_LOGICAL;
|
||||
break;
|
||||
case ':':
|
||||
if ( is_struct_or_union((*expp)->ex_type->tp_fund)
|
||||
|| is_struct_or_union(expr->ex_type->tp_fund)
|
||||
) {
|
||||
if ((*expp)->ex_type != expr->ex_type)
|
||||
expr_error(*expp, "illegal balance");
|
||||
}
|
||||
else
|
||||
relbalance(expp, oper, &expr);
|
||||
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
|
||||
break;
|
||||
case '?':
|
||||
opnd2logical(expp, oper);
|
||||
if (is_cp_cst(*expp))
|
||||
*expp = (*expp)->VL_VALUE ?
|
||||
expr->OP_LEFT : expr->OP_RIGHT;
|
||||
else
|
||||
*expp = new_oper(expr->ex_type, *expp, oper, expr);
|
||||
break;
|
||||
case ',':
|
||||
if (is_cp_cst(*expp))
|
||||
*expp = expr;
|
||||
else
|
||||
*expp = new_oper(expr->ex_type, *expp, oper, expr);
|
||||
(*expp)->ex_flags |= EX_COMMA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pntminuspnt(expp, oper, expr)
|
||||
register struct expr **expp, *expr;
|
||||
{
|
||||
/* Subtracting two pointers is so complicated it merits a
|
||||
routine of its own.
|
||||
*/
|
||||
struct type *up_type = (*expp)->ex_type->tp_up;
|
||||
|
||||
if (up_type != expr->ex_type->tp_up) {
|
||||
expr_error(*expp, "subtracting incompatible pointers");
|
||||
free_expression(expr);
|
||||
erroneous2int(expp);
|
||||
return;
|
||||
}
|
||||
/* we hope the optimizer will eliminate the load-time
|
||||
pointer subtraction
|
||||
*/
|
||||
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
|
||||
ch7cast(expp, CAST, pa_type); /* ptr-ptr: result has pa_type */
|
||||
ch7bin(expp, '/',
|
||||
intexpr(size_of_type(up_type, "object"), pa_type->tp_fund));
|
||||
ch7cast(expp, CAST, int_type); /* result will be an integer expr */
|
||||
}
|
||||
|
||||
mk_binop(expp, oper, expr, commutative)
|
||||
struct expr **expp;
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* Constructs in *expp the operation indicated by the operands.
|
||||
"commutative" indicates wether "oper" is a commutative
|
||||
operator.
|
||||
*/
|
||||
register struct expr *ex = *expp;
|
||||
|
||||
if (is_cp_cst(expr) && is_cp_cst(ex))
|
||||
cstbin(expp, oper, expr);
|
||||
else {
|
||||
*expp = (commutative && expr->ex_depth >= ex->ex_depth) ?
|
||||
new_oper(ex->ex_type, expr, oper, ex) :
|
||||
new_oper(ex->ex_type, ex, oper, expr);
|
||||
}
|
||||
}
|
||||
|
||||
pointer_arithmetic(expp1, oper, expp2)
|
||||
register struct expr **expp1, **expp2;
|
||||
{
|
||||
/* prepares the integral expression expp2 in order to
|
||||
apply it to the pointer expression expp1
|
||||
*/
|
||||
#ifndef NOFLOAT
|
||||
if (any2arith(expp2, oper) == DOUBLE) {
|
||||
expr_error(*expp2,
|
||||
"illegal combination of float and pointer");
|
||||
erroneous2int(expp2);
|
||||
}
|
||||
#endif NOFLOAT
|
||||
ch7bin( expp2, '*',
|
||||
intexpr(size_of_type((*expp1)->ex_type->tp_up, "object"),
|
||||
pa_type->tp_fund)
|
||||
);
|
||||
}
|
||||
|
||||
pointer_binary(expp, oper, expr)
|
||||
register struct expr **expp, *expr;
|
||||
{
|
||||
/* constructs the pointer arithmetic expression out of
|
||||
a pointer expression, a binary operator and an integral
|
||||
expression.
|
||||
*/
|
||||
if (is_ld_cst(expr) && is_ld_cst(*expp))
|
||||
cstbin(expp, oper, expr);
|
||||
else
|
||||
*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
|
||||
}
|
||||
162
lang/cem/cemcom/ch7mon.c
Normal file
162
lang/cem/cemcom/ch7mon.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* SEMANTIC ANALYSIS (CHAPTER 7RM) -- MONADIC OPERATORS */
|
||||
|
||||
#include "botch_free.h"
|
||||
#include <alloc.h>
|
||||
#include "nofloat.h"
|
||||
#include "nobitfield.h"
|
||||
#include "Lpars.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "idf.h"
|
||||
#include "def.h"
|
||||
|
||||
extern char options[];
|
||||
extern long full_mask[/*MAXSIZE*/]; /* cstoper.c */
|
||||
char *symbol2str();
|
||||
|
||||
ch7mon(oper, expp)
|
||||
register struct expr **expp;
|
||||
{
|
||||
/* The monadic prefix operator oper is applied to *expp.
|
||||
*/
|
||||
register struct expr *expr;
|
||||
|
||||
switch (oper) {
|
||||
case '*': /* RM 7.2 */
|
||||
/* no FIELD type allowed */
|
||||
if ((*expp)->ex_type->tp_fund == ARRAY)
|
||||
array2pointer(*expp);
|
||||
if ((*expp)->ex_type->tp_fund != POINTER) {
|
||||
expr_error(*expp,
|
||||
"* applied to non-pointer (%s)",
|
||||
symbol2str((*expp)->ex_type->tp_fund));
|
||||
}
|
||||
else {
|
||||
expr = *expp;
|
||||
if (expr->ex_lvalue == 0)
|
||||
/* dereference in administration only */
|
||||
expr->ex_type = expr->ex_type->tp_up;
|
||||
else /* runtime code */
|
||||
*expp = new_oper(expr->ex_type->tp_up, NILEXPR,
|
||||
'*', expr);
|
||||
(*expp)->ex_lvalue = (
|
||||
(*expp)->ex_type->tp_fund != ARRAY &&
|
||||
(*expp)->ex_type->tp_fund != FUNCTION);
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
if ((*expp)->ex_type->tp_fund == ARRAY) {
|
||||
warning("& before array: ignored");
|
||||
array2pointer(*expp);
|
||||
}
|
||||
else
|
||||
if ((*expp)->ex_type->tp_fund == FUNCTION) {
|
||||
warning("& before function: ignored");
|
||||
function2pointer(*expp);
|
||||
}
|
||||
else
|
||||
#ifndef NOBITFIELD
|
||||
if ((*expp)->ex_type->tp_fund == FIELD)
|
||||
expr_error(*expp, "& applied to field variable");
|
||||
else
|
||||
#endif NOBITFIELD
|
||||
if (!(*expp)->ex_lvalue)
|
||||
expr_error(*expp, "& applied to non-lvalue");
|
||||
else {
|
||||
/* assume that enums are already filtered out */
|
||||
if ( (*expp)->ex_class == Value
|
||||
&& (*expp)->VL_CLASS == Name
|
||||
) {
|
||||
register struct def *def =
|
||||
(*expp)->VL_IDF->id_def;
|
||||
|
||||
/* &<var> indicates that <var>
|
||||
cannot be used as register
|
||||
anymore
|
||||
*/
|
||||
if (def->df_sc == REGISTER) {
|
||||
expr_error(*expp,
|
||||
"& on register variable not allowed");
|
||||
break; /* break case '&' */
|
||||
}
|
||||
}
|
||||
(*expp)->ex_type = pointer_to((*expp)->ex_type);
|
||||
(*expp)->ex_lvalue = 0;
|
||||
}
|
||||
break;
|
||||
case '~':
|
||||
#ifndef NOFLOAT
|
||||
{
|
||||
int fund = (*expp)->ex_type->tp_fund;
|
||||
|
||||
if (fund == FLOAT || fund == DOUBLE) {
|
||||
expr_error(
|
||||
*expp,
|
||||
"~ not allowed on %s operands",
|
||||
symbol2str(fund)
|
||||
);
|
||||
erroneous2int(expp);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
#endif NOFLOAT
|
||||
case '-':
|
||||
any2arith(expp, oper);
|
||||
if (is_cp_cst(*expp)) {
|
||||
arith o1 = (*expp)->VL_VALUE;
|
||||
|
||||
(*expp)->VL_VALUE = (oper == '-') ? -o1 :
|
||||
((*expp)->ex_type->tp_unsigned ?
|
||||
(~o1) & full_mask[(*expp)->ex_type->tp_size] :
|
||||
~o1
|
||||
);
|
||||
}
|
||||
else
|
||||
#ifndef NOFLOAT
|
||||
if (is_fp_cst(*expp))
|
||||
switch_sign_fp(*expp);
|
||||
else
|
||||
#endif NOFLOAT
|
||||
*expp = new_oper((*expp)->ex_type,
|
||||
NILEXPR, oper, *expp);
|
||||
break;
|
||||
case '!':
|
||||
if ((*expp)->ex_type->tp_fund == FUNCTION)
|
||||
function2pointer(*expp);
|
||||
if ((*expp)->ex_type->tp_fund != POINTER)
|
||||
any2arith(expp, oper);
|
||||
opnd2test(expp, '!');
|
||||
if (is_cp_cst(*expp)) {
|
||||
(*expp)->VL_VALUE = !((*expp)->VL_VALUE);
|
||||
(*expp)->ex_type = int_type; /* a cast ???(EB) */
|
||||
}
|
||||
else
|
||||
*expp = new_oper(int_type, NILEXPR, oper, *expp);
|
||||
(*expp)->ex_flags |= EX_LOGICAL;
|
||||
break;
|
||||
case PLUSPLUS:
|
||||
case MINMIN:
|
||||
ch7incr(expp, oper);
|
||||
break;
|
||||
case SIZEOF:
|
||||
if ( (*expp)->ex_class == Value
|
||||
&& (*expp)->VL_CLASS == Name
|
||||
&& (*expp)->VL_IDF->id_def->df_formal_array
|
||||
)
|
||||
warning("sizeof formal array %s is sizeof pointer!",
|
||||
(*expp)->VL_IDF->id_text);
|
||||
expr = intexpr(size_of_type((*expp)->ex_type, "object"), INT);
|
||||
expr->ex_flags |= EX_SIZEOF;
|
||||
free_expression(*expp);
|
||||
*expp = expr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
58
lang/cem/cemcom/char.tab
Normal file
58
lang/cem/cemcom/char.tab
Normal file
@@ -0,0 +1,58 @@
|
||||
%
|
||||
% CHARACTER CLASSES
|
||||
%
|
||||
% some general settings:
|
||||
%S129
|
||||
%F %s,
|
||||
%
|
||||
% START OF TOKEN
|
||||
%
|
||||
%C
|
||||
STGARB:\000-\200
|
||||
STSKIP:\r \t
|
||||
STNL:\n\f\013
|
||||
STCOMP:!&+-<=>|
|
||||
STSIMP:%()*,/:;?[]^{}~
|
||||
STCHAR:'
|
||||
STIDF:a-zA-Z_
|
||||
STNUM:.0-9
|
||||
STSTR:"
|
||||
STEOI:\200
|
||||
%T/* character classes */
|
||||
%T#include "class.h"
|
||||
%Tchar tkclass[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% INIDF
|
||||
%
|
||||
%C
|
||||
1:a-zA-Z_0-9
|
||||
%Tchar inidf[] = {
|
||||
%F %s,
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISDIG
|
||||
%
|
||||
%C
|
||||
1:0-9
|
||||
%Tchar isdig[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISHEX
|
||||
%
|
||||
%C
|
||||
1:a-fA-F
|
||||
%Tchar ishex[] = {
|
||||
%p
|
||||
%T};
|
||||
%
|
||||
% ISOCT
|
||||
%
|
||||
%C
|
||||
1:0-7
|
||||
%Tchar isoct[] = {
|
||||
%p
|
||||
%T};
|
||||
41
lang/cem/cemcom/class.h
Normal file
41
lang/cem/cemcom/class.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* U S E O F C H A R A C T E R C L A S S E S */
|
||||
|
||||
/* 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, although 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 in C */
|
||||
#define STSIMP 3 /* this character can occur as token in C */
|
||||
#define STCOMP 4 /* this one can start a compound token in C */
|
||||
#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) (inidf[ch])
|
||||
#define is_oct(ch) (isoct[ch])
|
||||
#define is_dig(ch) (isdig[ch])
|
||||
#define is_hex(ch) (ishex[ch])
|
||||
|
||||
extern char tkclass[];
|
||||
extern char inidf[], isoct[], isdig[], ishex[];
|
||||
607
lang/cem/cemcom/code.c
Normal file
607
lang/cem/cemcom/code.c
Normal file
@@ -0,0 +1,607 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* C O D E - G E N E R A T I N G R O U T I N E S */
|
||||
|
||||
#include <em.h>
|
||||
#include "botch_free.h"
|
||||
#include <alloc.h>
|
||||
#include "nofloat.h"
|
||||
#include "dataflow.h"
|
||||
#include "use_tmp.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "label.h"
|
||||
#include "code.h"
|
||||
#include "stmt.h"
|
||||
#include "def.h"
|
||||
#include "expr.h"
|
||||
#include "sizes.h"
|
||||
#include "stack.h"
|
||||
#include "level.h"
|
||||
#include "decspecs.h"
|
||||
#include "declar.h"
|
||||
#include "Lpars.h"
|
||||
#include "mes.h"
|
||||
#include "LLlex.h"
|
||||
#include "specials.h"
|
||||
#include "atw.h"
|
||||
#include "assert.h"
|
||||
#include "align.h"
|
||||
#include "noRoption.h"
|
||||
|
||||
label lab_count = 1;
|
||||
label datlab_count = 1;
|
||||
|
||||
#ifndef NOFLOAT
|
||||
int fp_used;
|
||||
#endif NOFLOAT
|
||||
|
||||
#ifdef USE_TMP
|
||||
static int tmp_id;
|
||||
static int pro_id;
|
||||
static char *pro_name;
|
||||
#endif USE_TMP
|
||||
|
||||
extern char options[];
|
||||
char *symbol2str();
|
||||
|
||||
init_code(dst_file)
|
||||
char *dst_file;
|
||||
{
|
||||
/* init_code() initialises the output file on which the
|
||||
compact EM code is written
|
||||
*/
|
||||
C_init(word_size, pointer_size); /* initialise EM module */
|
||||
if (C_open(dst_file) == 0)
|
||||
fatal("cannot write to %s\n", dst_file);
|
||||
C_magic();
|
||||
C_ms_emx(word_size, pointer_size);
|
||||
#ifdef USE_TMP
|
||||
C_insertpart(tmp_id = C_getid());
|
||||
#endif USE_TMP
|
||||
}
|
||||
|
||||
static struct string_cst *str_list = 0;
|
||||
|
||||
code_string(val, len, dlb)
|
||||
char *val;
|
||||
int len;
|
||||
label dlb;
|
||||
{
|
||||
register struct string_cst *sc = new_string_cst();
|
||||
|
||||
C_ina_dlb(dlb);
|
||||
sc->next = str_list;
|
||||
str_list = sc;
|
||||
sc->sc_value = val;
|
||||
sc->sc_len = len;
|
||||
sc->sc_dlb = dlb;
|
||||
}
|
||||
|
||||
def_strings(sc)
|
||||
register struct string_cst *sc;
|
||||
{
|
||||
while (sc) {
|
||||
struct string_cst *sc1 = sc;
|
||||
|
||||
C_df_dlb(sc->sc_dlb);
|
||||
str_cst(sc->sc_value, sc->sc_len);
|
||||
sc = sc->next;
|
||||
free_string_cst(sc1);
|
||||
}
|
||||
}
|
||||
|
||||
end_code()
|
||||
{
|
||||
/* end_code() performs the actions to be taken when closing
|
||||
the output stream.
|
||||
*/
|
||||
#ifndef NOFLOAT
|
||||
if (fp_used) {
|
||||
/* floating point used */
|
||||
C_ms_flt();
|
||||
}
|
||||
#endif NOFLOAT
|
||||
def_strings(str_list);
|
||||
str_list = 0;
|
||||
C_ms_src((int)(LineNumber - 2), FileName);
|
||||
C_close();
|
||||
}
|
||||
|
||||
#ifdef USE_TMP
|
||||
prepend_scopes()
|
||||
{
|
||||
/* prepend_scopes() runs down the list of global idf's
|
||||
and generates those exa's, exp's, ina's and inp's
|
||||
that superior hindsight has provided.
|
||||
*/
|
||||
register struct stack_entry *se = local_level->sl_entry;
|
||||
|
||||
C_beginpart(tmp_id);
|
||||
while (se != 0) {
|
||||
register struct idf *id = se->se_idf;
|
||||
register struct def *df = id->id_def;
|
||||
|
||||
if (df && (df->df_initialized || df->df_used || df->df_alloc))
|
||||
code_scope(id->id_text, df);
|
||||
se = se->next;
|
||||
}
|
||||
C_endpart(tmp_id);
|
||||
}
|
||||
#endif USE_TMP
|
||||
|
||||
code_scope(text, def)
|
||||
char *text;
|
||||
register struct def *def;
|
||||
{
|
||||
/* generates code for one name, text, of the storage class
|
||||
as given by def, if meaningful.
|
||||
*/
|
||||
int fund = def->df_type->tp_fund;
|
||||
|
||||
switch (def->df_sc) {
|
||||
case EXTERN:
|
||||
case GLOBAL:
|
||||
case IMPLICIT:
|
||||
if (fund == FUNCTION)
|
||||
C_exp(text);
|
||||
else
|
||||
C_exa_dnam(text);
|
||||
break;
|
||||
case STATIC:
|
||||
if (fund == FUNCTION)
|
||||
C_inp(text);
|
||||
else
|
||||
C_ina_dnam(text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static label return_label, return2_label;
|
||||
static char return_expr_occurred;
|
||||
static struct type *func_tp;
|
||||
static arith func_size;
|
||||
static label func_res_label;
|
||||
static char *last_fn_given = "";
|
||||
static label file_name_label;
|
||||
|
||||
begin_proc(name, def) /* to be called when entering a procedure */
|
||||
char *name;
|
||||
register struct def *def;
|
||||
{
|
||||
/* begin_proc() is called at the entrance of a new function
|
||||
and performs the necessary code generation:
|
||||
- a scope indicator (if needed) exp/inp
|
||||
- the procedure entry pro $name
|
||||
- reserves some space if the result of the function
|
||||
does not fit in the return area
|
||||
- a fil pseudo instruction
|
||||
*/
|
||||
register struct type *tp = def->df_type;
|
||||
|
||||
#ifndef USE_TMP
|
||||
code_scope(name, def);
|
||||
#endif USE_TMP
|
||||
#ifdef DATAFLOW
|
||||
if (options['d'])
|
||||
DfaStartFunction(name);
|
||||
#endif DATAFLOW
|
||||
|
||||
if (tp->tp_fund != FUNCTION) {
|
||||
error("making function body for non-function");
|
||||
tp = error_type;
|
||||
}
|
||||
else
|
||||
tp = tp->tp_up;
|
||||
func_tp = tp;
|
||||
func_size = ATW(tp->tp_size);
|
||||
#ifndef USE_TMP
|
||||
C_pro_narg(name);
|
||||
#else
|
||||
pro_name = name;
|
||||
C_insertpart(pro_id = C_getid());
|
||||
#endif
|
||||
if (is_struct_or_union(tp->tp_fund)) {
|
||||
C_df_dlb(func_res_label = data_label());
|
||||
C_bss_cst(func_size, (arith)0, 1);
|
||||
}
|
||||
else
|
||||
func_res_label = 0;
|
||||
/* Special arrangements if the function result doesn't fit in
|
||||
the function return area of the EM machine. The size of
|
||||
the function return area is implementation dependent.
|
||||
*/
|
||||
lab_count = (label) 1;
|
||||
return_label = text_label();
|
||||
return2_label = text_label();
|
||||
return_expr_occurred = 0;
|
||||
LocalInit();
|
||||
prc_entry(name);
|
||||
if (! options['L']) { /* profiling */
|
||||
if (strcmp(last_fn_given, FileName) != 0) {
|
||||
/* previous function came from other file */
|
||||
C_df_dlb(file_name_label = data_label());
|
||||
C_con_scon(last_fn_given = FileName,
|
||||
(arith)(strlen(FileName) + 1));
|
||||
}
|
||||
/* enable debug trace of EM source */
|
||||
C_fil_dlb(file_name_label, (arith)0);
|
||||
C_lin((arith)LineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
end_proc(fbytes)
|
||||
arith fbytes;
|
||||
{
|
||||
/* end_proc() deals with the code to be generated at the end of
|
||||
a function, as there is:
|
||||
- the EM ret instruction: "ret 0"
|
||||
- loading of the function result in the function
|
||||
result area if there has been a return <expr>
|
||||
in the function body (see do_return_expr())
|
||||
- indication of the use of floating points
|
||||
- indication of the number of bytes used for
|
||||
formal parameters
|
||||
- use of special identifiers such as "setjmp"
|
||||
- "end" + number of bytes used for local variables
|
||||
*/
|
||||
arith nbytes;
|
||||
char optionsn = options['n'];
|
||||
|
||||
#ifdef DATAFLOW
|
||||
if (options['d'])
|
||||
DfaEndFunction();
|
||||
#endif DATAFLOW
|
||||
C_df_ilb(return2_label);
|
||||
if (return_expr_occurred) C_asp(-func_size);
|
||||
C_df_ilb(return_label);
|
||||
prc_exit();
|
||||
if (return_expr_occurred) {
|
||||
if (func_res_label != 0) {
|
||||
C_lae_dlb(func_res_label, (arith)0);
|
||||
store_block(func_size, func_tp->tp_align);
|
||||
C_lae_dlb(func_res_label, (arith)0);
|
||||
C_ret(pointer_size);
|
||||
}
|
||||
else
|
||||
C_ret(func_size);
|
||||
}
|
||||
else C_ret((arith) 0);
|
||||
|
||||
/* getting the number of "local" bytes is posponed until here,
|
||||
because copying the function result in "func_res_label" may
|
||||
need temporaries! However, local_level is now L_FORMAL2, because
|
||||
L_LOCAL is already unstacked. Therefore, "unstack_level" must
|
||||
also pass "sl_max_block" to the level above L_LOCAL.
|
||||
*/
|
||||
nbytes = ATW(- local_level->sl_max_block);
|
||||
#ifdef USE_TMP
|
||||
C_beginpart(pro_id);
|
||||
C_pro(pro_name, nbytes);
|
||||
#endif
|
||||
C_ms_par(fbytes); /* # bytes for formals */
|
||||
if (sp_occurred[SP_SETJMP]) { /* indicate use of "setjmp" */
|
||||
options['n'] = 1;
|
||||
C_ms_gto();
|
||||
sp_occurred[SP_SETJMP] = 0;
|
||||
}
|
||||
#ifdef USE_TMP
|
||||
C_endpart(pro_id);
|
||||
#endif
|
||||
LocalFinish();
|
||||
C_end(nbytes);
|
||||
options['n'] = optionsn;
|
||||
}
|
||||
|
||||
do_return()
|
||||
{
|
||||
/* do_return handles the case of a return without expression.
|
||||
This version branches to the return label, which is
|
||||
probably smarter than generating a direct return.
|
||||
Return sequences may be expensive.
|
||||
*/
|
||||
C_bra(return2_label);
|
||||
}
|
||||
|
||||
do_return_expr(expr)
|
||||
struct expr *expr;
|
||||
{
|
||||
/* do_return_expr() generates the expression and the jump for
|
||||
a return statement with an expression.
|
||||
*/
|
||||
ch7cast(&expr, RETURN, func_tp);
|
||||
code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_bra(return_label);
|
||||
return_expr_occurred = 1;
|
||||
}
|
||||
|
||||
code_declaration(idf, expr, lvl, sc)
|
||||
register struct idf *idf; /* idf to be declared */
|
||||
struct expr *expr; /* initialisation; NULL if absent */
|
||||
int lvl; /* declaration level */
|
||||
int sc; /* storage class, as in the declaration */
|
||||
{
|
||||
/* code_declaration() does the actual declaration of the
|
||||
variable indicated by "idf" on declaration level "lvl".
|
||||
If the variable is initialised, the expression is given
|
||||
in "expr", but for global and static initialisations it
|
||||
is just non-zero, as the expression is not parsed yet.
|
||||
There are some cases to be considered:
|
||||
- filter out typedefs, they don't correspond to code;
|
||||
- global variables, coded only if initialized;
|
||||
- local static variables;
|
||||
- local automatic variables;
|
||||
Since the expression may be modified in the process,
|
||||
code_declaration() frees it after use, as the caller can
|
||||
no longer do so.
|
||||
|
||||
If there is a storage class indication (EXTERN/STATIC),
|
||||
code_declaration() will generate an exa or ina.
|
||||
The sc is the actual storage class, as given in the
|
||||
declaration. This is to allow:
|
||||
extern int a;
|
||||
int a = 5;
|
||||
while at the same time forbidding
|
||||
extern int a = 5;
|
||||
*/
|
||||
register struct def *def = idf->id_def;
|
||||
register arith size = def->df_type->tp_size;
|
||||
int def_sc = def->df_sc;
|
||||
|
||||
if (def_sc == TYPEDEF) /* no code for typedefs */
|
||||
return;
|
||||
if (sc == EXTERN && expr && !is_anon_idf(idf))
|
||||
error("%s is extern; cannot initialize", idf->id_text);
|
||||
if (lvl == L_GLOBAL) { /* global variable */
|
||||
/* is this an allocating declaration? */
|
||||
if ( (sc == 0 || sc == STATIC)
|
||||
&& def->df_type->tp_fund != FUNCTION
|
||||
&& size >= 0
|
||||
)
|
||||
def->df_alloc = ALLOC_SEEN;
|
||||
if (expr) { /* code only if initialized */
|
||||
#ifndef USE_TMP
|
||||
code_scope(idf->id_text, def);
|
||||
#endif USE_TMP
|
||||
def->df_alloc = ALLOC_DONE;
|
||||
C_df_dnam(idf->id_text);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (lvl >= L_LOCAL) { /* local variable */
|
||||
/* STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or REGISTER */
|
||||
switch (def_sc) {
|
||||
case STATIC:
|
||||
if (def->df_type->tp_fund == FUNCTION) {
|
||||
/* should produce "inp $function" ??? */
|
||||
break;
|
||||
}
|
||||
/* they are handled on the spot and get an
|
||||
integer label in EM.
|
||||
*/
|
||||
C_df_dlb((label)def->df_address);
|
||||
if (expr) { /* there is an initialisation */
|
||||
}
|
||||
else { /* produce blank space */
|
||||
if (size <= 0) {
|
||||
error("size of %s unknown", idf->id_text);
|
||||
size = (arith)0;
|
||||
}
|
||||
C_bss_cst(ATW(size), (arith)0, 1);
|
||||
}
|
||||
break;
|
||||
case EXTERN:
|
||||
case GLOBAL:
|
||||
case IMPLICIT:
|
||||
/* we are sure there is no expression */
|
||||
#ifndef USE_TMP
|
||||
code_scope(idf->id_text, def);
|
||||
#endif USE_TMP
|
||||
break;
|
||||
case AUTO:
|
||||
case REGISTER:
|
||||
if (expr)
|
||||
loc_init(expr, idf);
|
||||
break;
|
||||
default:
|
||||
crash("bad local storage class");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loc_init(expr, id)
|
||||
struct expr *expr;
|
||||
register struct idf *id;
|
||||
{
|
||||
/* loc_init() generates code for the assignment of
|
||||
expression expr to the local variable described by id.
|
||||
It frees the expression afterwards.
|
||||
*/
|
||||
register struct expr *e = expr;
|
||||
register struct type *tp = id->id_def->df_type;
|
||||
|
||||
ASSERT(id->id_def->df_sc != STATIC);
|
||||
switch (tp->tp_fund) {
|
||||
case ARRAY:
|
||||
case STRUCT:
|
||||
case UNION:
|
||||
error("no automatic aggregate initialisation");
|
||||
free_expression(e);
|
||||
return;
|
||||
}
|
||||
if (ISCOMMA(e)) { /* embraced: int i = {12}; */
|
||||
#ifndef NOROPTION
|
||||
if (options['R']) {
|
||||
if (ISCOMMA(e->OP_LEFT)) /* int i = {{1}} */
|
||||
expr_error(e, "extra braces not allowed");
|
||||
else
|
||||
if (e->OP_RIGHT != 0) /* int i = {1 , 2} */
|
||||
expr_error(e, "too many initializers");
|
||||
}
|
||||
#endif NOROPTION
|
||||
while (e) {
|
||||
loc_init(e->OP_LEFT, id);
|
||||
e = e->OP_RIGHT;
|
||||
}
|
||||
}
|
||||
else { /* not embraced */
|
||||
struct value vl;
|
||||
|
||||
ch7cast(&expr, '=', tp); /* may modify expr */
|
||||
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
free_expression(expr);
|
||||
vl.vl_class = Name;
|
||||
vl.vl_data.vl_idf = id;
|
||||
vl.vl_value = (arith)0;
|
||||
store_val(&vl, tp);
|
||||
}
|
||||
}
|
||||
|
||||
bss(idf)
|
||||
register struct idf *idf;
|
||||
{
|
||||
/* bss() allocates bss space for the global idf.
|
||||
*/
|
||||
arith size = idf->id_def->df_type->tp_size;
|
||||
|
||||
#ifndef USE_TMP
|
||||
code_scope(idf->id_text, idf->id_def);
|
||||
#endif USE_TMP
|
||||
/* Since bss() is only called if df_alloc is non-zero, and
|
||||
since df_alloc is only non-zero if size >= 0, we have:
|
||||
*/
|
||||
/* but we already gave a warning at the declaration of the
|
||||
array. Besides, the message given here does not apply to
|
||||
voids
|
||||
|
||||
if (options['R'] && size == 0)
|
||||
warning("actual array of size 0");
|
||||
*/
|
||||
C_df_dnam(idf->id_text);
|
||||
C_bss_cst(ATW(size), (arith)0, 1);
|
||||
}
|
||||
|
||||
formal_cvt(df)
|
||||
register struct def *df;
|
||||
{
|
||||
/* formal_cvt() converts a formal parameter of type char or
|
||||
short from int to that type.
|
||||
*/
|
||||
register struct type *tp = df->df_type;
|
||||
|
||||
if (tp->tp_size != int_size &&
|
||||
(tp->tp_fund == CHAR || tp->tp_fund == SHORT)
|
||||
) {
|
||||
LoadLocal(df->df_address, int_size);
|
||||
/* conversion(int_type, df->df_type); ???
|
||||
No, you can't do this on the stack! (CJ)
|
||||
*/
|
||||
StoreLocal(df->df_address, tp->tp_size);
|
||||
}
|
||||
}
|
||||
|
||||
code_expr(expr, val, code, tlbl, flbl)
|
||||
struct expr *expr;
|
||||
label tlbl, flbl;
|
||||
{
|
||||
/* code_expr() is the parser's interface to the expression code
|
||||
generator. If line number trace is wanted, it generates a
|
||||
lin instruction. EVAL() is called directly.
|
||||
*/
|
||||
if (! options['L']) /* profiling */
|
||||
C_lin((arith)(expr->ex_line));
|
||||
EVAL(expr, val, code, tlbl, flbl);
|
||||
}
|
||||
|
||||
/* The FOR/WHILE/DO/SWITCH stacking mechanism:
|
||||
stack_stmt() has to be called at the entrance of a
|
||||
for, while, do or switch statement to indicate the
|
||||
EM labels where a subsequent break or continue causes
|
||||
the program to jump to.
|
||||
*/
|
||||
static struct stmt_block *stmt_stack; /* top of statement stack */
|
||||
|
||||
/* code_break() generates EM code needed at the occurrence of "break":
|
||||
it generates a branch instruction to the break label of the
|
||||
innermost statement in which break has a meaning.
|
||||
As "break" is legal in any of 'while', 'do', 'for' or 'switch',
|
||||
which are the only ones that are stacked, only the top of
|
||||
the stack is interesting.
|
||||
*/
|
||||
code_break()
|
||||
{
|
||||
register struct stmt_block *stmt_block = stmt_stack;
|
||||
|
||||
if (stmt_block)
|
||||
C_bra(stmt_block->st_break);
|
||||
else
|
||||
error("break not inside for, while, do or switch");
|
||||
}
|
||||
|
||||
/* code_continue() generates EM code needed at the occurrence of
|
||||
"continue":
|
||||
it generates a branch instruction to the continue label of the
|
||||
innermost statement in which continue has a meaning.
|
||||
*/
|
||||
code_continue()
|
||||
{
|
||||
register struct stmt_block *stmt_block = stmt_stack;
|
||||
|
||||
while (stmt_block) {
|
||||
if (stmt_block->st_continue) {
|
||||
C_bra(stmt_block->st_continue);
|
||||
return;
|
||||
}
|
||||
stmt_block = stmt_block->next;
|
||||
}
|
||||
error("continue not inside for, while or do");
|
||||
}
|
||||
|
||||
stack_stmt(break_label, cont_label)
|
||||
label break_label, cont_label;
|
||||
{
|
||||
register struct stmt_block *stmt_block = new_stmt_block();
|
||||
|
||||
stmt_block->next = stmt_stack;
|
||||
stmt_block->st_break = break_label;
|
||||
stmt_block->st_continue = cont_label;
|
||||
stmt_stack = stmt_block;
|
||||
}
|
||||
|
||||
unstack_stmt()
|
||||
{
|
||||
/* unstack_stmt() unstacks the data of a statement
|
||||
which may contain break or continue
|
||||
*/
|
||||
register struct stmt_block *sbp = stmt_stack;
|
||||
stmt_stack = sbp->next;
|
||||
free_stmt_block(sbp);
|
||||
}
|
||||
|
||||
static label prc_name;
|
||||
|
||||
prc_entry(name)
|
||||
char *name;
|
||||
{
|
||||
if (options['p']) {
|
||||
C_df_dlb(prc_name = data_label());
|
||||
C_rom_scon(name, (arith) (strlen(name) + 1));
|
||||
C_lae_dlb(prc_name, (arith) 0);
|
||||
C_cal("procentry");
|
||||
C_asp(pointer_size);
|
||||
}
|
||||
}
|
||||
|
||||
prc_exit()
|
||||
{
|
||||
if (options['p']) {
|
||||
C_lae_dlb(prc_name, (arith) 0);
|
||||
C_cal("procexit");
|
||||
C_asp(pointer_size);
|
||||
}
|
||||
}
|
||||
23
lang/cem/cemcom/code.h
Normal file
23
lang/cem/cemcom/code.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* $Header$ */
|
||||
/* C O D E - G E N E R A T O R D E F I N I T I O N S */
|
||||
|
||||
struct stat_block {
|
||||
struct stat_block *next;
|
||||
label st_break;
|
||||
label st_continue;
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct stat_block */
|
||||
/* ALLOCDEF "stat_block" */
|
||||
extern char *st_alloc();
|
||||
extern struct stat_block *h_stat_block;
|
||||
#define new_stat_block() ((struct stat_block *) \
|
||||
st_alloc((char **)&h_stat_block, sizeof(struct stat_block)))
|
||||
#define free_stat_block(p) st_free(p, h_stat_block, sizeof(struct stat_block))
|
||||
|
||||
|
||||
#define LVAL 0
|
||||
#define RVAL 1
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
20
lang/cem/cemcom/code.str
Normal file
20
lang/cem/cemcom/code.str
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* C O D E - G E N E R A T O R D E F I N I T I O N S */
|
||||
|
||||
struct string_cst { /* storing string constants */
|
||||
struct string_cst *next;
|
||||
char *sc_value;
|
||||
int sc_len;
|
||||
label sc_dlb;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "string_cst" 10 */
|
||||
|
||||
#define LVAL 0
|
||||
#define RVAL 1
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
131
lang/cem/cemcom/conversion.c
Normal file
131
lang/cem/cemcom/conversion.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* C O N V E R S I O N - C O D E G E N E R A T O R */
|
||||
|
||||
#include "nofloat.h"
|
||||
#include <em.h>
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "sizes.h"
|
||||
#include "Lpars.h"
|
||||
|
||||
#define T_SIGNED 1
|
||||
#define T_UNSIGNED 2
|
||||
#ifndef NOFLOAT
|
||||
#define T_FLOATING 3
|
||||
#endif NOFLOAT
|
||||
|
||||
/* conversion() generates the EM code for a conversion between
|
||||
the types char, short, int, long, float, double and pointer.
|
||||
In case of integral type, the notion signed / unsigned is
|
||||
taken into account.
|
||||
The EM code to obtain this conversion looks like:
|
||||
LOC sizeof(from_type)
|
||||
LOC sizeof(to_type)
|
||||
C??
|
||||
*/
|
||||
|
||||
conversion(from_type, to_type)
|
||||
register struct type *from_type, *to_type;
|
||||
{
|
||||
register arith from_size = from_type->tp_size;
|
||||
register arith to_size = to_type->tp_size;
|
||||
int from_fund = fundamental(from_type);
|
||||
int to_fund = fundamental(to_type);
|
||||
|
||||
if (to_size < word_size) to_size = word_size;
|
||||
if (from_size == to_size && from_fund == to_fund)
|
||||
return;
|
||||
switch (from_fund) {
|
||||
case T_SIGNED:
|
||||
switch (to_fund) {
|
||||
case T_SIGNED:
|
||||
C_loc(from_size);
|
||||
C_loc(to_size);
|
||||
C_cii();
|
||||
break;
|
||||
case T_UNSIGNED:
|
||||
#ifndef NOFLOAT
|
||||
case T_FLOATING:
|
||||
#endif NOOFLOAT
|
||||
if (from_size < word_size) {
|
||||
C_loc(from_size);
|
||||
C_loc(word_size);
|
||||
C_cii();
|
||||
from_size = word_size;
|
||||
}
|
||||
C_loc(from_size);
|
||||
C_loc(to_size);
|
||||
if (to_fund == T_UNSIGNED) C_ciu();
|
||||
else C_cif();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case T_UNSIGNED:
|
||||
if (from_size < word_size) from_size = word_size;
|
||||
C_loc(from_size);
|
||||
C_loc(to_size);
|
||||
switch (to_fund) {
|
||||
case T_SIGNED:
|
||||
C_cui();
|
||||
break;
|
||||
case T_UNSIGNED:
|
||||
C_cuu();
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case T_FLOATING:
|
||||
C_cuf();
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
}
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case T_FLOATING:
|
||||
C_loc(from_size);
|
||||
C_loc(to_size);
|
||||
switch (to_fund) {
|
||||
case T_SIGNED:
|
||||
C_cfi();
|
||||
break;
|
||||
case T_UNSIGNED:
|
||||
C_cfu();
|
||||
break;
|
||||
case T_FLOATING:
|
||||
C_cff();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
default:
|
||||
crash("(conversion) illegal type conversion");
|
||||
}
|
||||
}
|
||||
|
||||
/* fundamental() returns in which category a given type falls:
|
||||
signed, unsigned or floating
|
||||
*/
|
||||
int
|
||||
fundamental(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
switch (tp->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case ERRONEOUS:
|
||||
case LONG:
|
||||
case ENUM:
|
||||
return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
return T_FLOATING;
|
||||
#endif NOFLOAT
|
||||
case POINTER: /* pointer : signed / unsigned ??? */
|
||||
return T_SIGNED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
237
lang/cem/cemcom/cstoper.c
Normal file
237
lang/cem/cemcom/cstoper.c
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* 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 */
|
||||
|
||||
#include "target_sizes.h"
|
||||
#include "idf.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "sizes.h"
|
||||
#include "Lpars.h"
|
||||
#include "assert.h"
|
||||
|
||||
long mach_long_sign; /* sign bit of the machine long */
|
||||
int mach_long_size; /* size of long on this machine == sizeof(long) */
|
||||
long full_mask[MAXSIZE];/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
|
||||
arith max_int; /* maximum integer on target machine */
|
||||
arith max_unsigned; /* maximum unsigned on target machine */
|
||||
|
||||
cstbin(expp, oper, expr)
|
||||
register struct expr **expp, *expr;
|
||||
{
|
||||
/* The operation oper is performed on the constant
|
||||
expressions *expp(ld) and expr(ct), and the result restored in
|
||||
*expp.
|
||||
*/
|
||||
register arith o1 = (*expp)->VL_VALUE;
|
||||
register arith o2 = expr->VL_VALUE;
|
||||
int uns = (*expp)->ex_type->tp_unsigned;
|
||||
|
||||
ASSERT(is_ld_cst(*expp) && is_cp_cst(expr));
|
||||
switch (oper) {
|
||||
case '*':
|
||||
o1 *= o2;
|
||||
break;
|
||||
case '/':
|
||||
if (o2 == 0) {
|
||||
expr_error(expr, "division by 0");
|
||||
break;
|
||||
}
|
||||
if (uns) {
|
||||
/* this is more of a problem than you might
|
||||
think on C compilers which do not have
|
||||
unsigned long.
|
||||
*/
|
||||
if (o2 & mach_long_sign) {/* o2 > max_long */
|
||||
o1 = ! (o1 >= 0 || o1 < o2);
|
||||
/* this is the unsigned test
|
||||
o1 < o2 for o2 > max_long
|
||||
*/
|
||||
}
|
||||
else { /* o2 <= max_long */
|
||||
long half, bit, hdiv, hrem, rem;
|
||||
|
||||
half = (o1 >> 1) & ~mach_long_sign;
|
||||
bit = o1 & 01;
|
||||
/* now o1 == 2 * half + bit
|
||||
and half <= max_long
|
||||
and bit <= max_long
|
||||
*/
|
||||
hdiv = half / o2;
|
||||
hrem = half % o2;
|
||||
rem = 2 * hrem + bit;
|
||||
o1 = 2 * hdiv + (rem < 0 || rem >= o2);
|
||||
/* that is the unsigned compare
|
||||
rem >= o2 for o2 <= max_long
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
o1 /= o2;
|
||||
break;
|
||||
case '%':
|
||||
if (o2 == 0) {
|
||||
expr_error(expr, "modulo by 0");
|
||||
break;
|
||||
}
|
||||
if (uns) {
|
||||
if (o2 & mach_long_sign) {/* o2 > max_long */
|
||||
o1 = (o1 >= 0 || o1 < o2) ? o1 : o1 - o2;
|
||||
/* this is the unsigned test
|
||||
o1 < o2 for o2 > max_long
|
||||
*/
|
||||
}
|
||||
else { /* o2 <= max_long */
|
||||
long half, bit, hrem, rem;
|
||||
|
||||
half = (o1 >> 1) & ~mach_long_sign;
|
||||
bit = o1 & 01;
|
||||
/* now o1 == 2 * half + bit
|
||||
and half <= max_long
|
||||
and bit <= max_long
|
||||
*/
|
||||
hrem = half % o2;
|
||||
rem = 2 * hrem + bit;
|
||||
o1 = (rem < 0 || rem >= o2) ? rem - o2 : rem;
|
||||
}
|
||||
}
|
||||
else
|
||||
o1 %= o2;
|
||||
break;
|
||||
case '+':
|
||||
o1 += o2;
|
||||
break;
|
||||
case '-':
|
||||
o1 -= o2;
|
||||
break;
|
||||
case LEFT:
|
||||
o1 <<= o2;
|
||||
break;
|
||||
case RIGHT:
|
||||
if (o2 == 0)
|
||||
break;
|
||||
if (uns) {
|
||||
o1 >>= 1;
|
||||
o1 & = ~mach_long_sign;
|
||||
o1 >>= (o2-1);
|
||||
}
|
||||
else
|
||||
o1 >>= o2;
|
||||
break;
|
||||
case '<':
|
||||
{
|
||||
arith tmp = o1;
|
||||
|
||||
o1 = o2;
|
||||
o2 = tmp;
|
||||
}
|
||||
/* Fall through */
|
||||
case '>':
|
||||
if (uns) {
|
||||
o1 = (o1 & mach_long_sign ?
|
||||
(o2 & mach_long_sign ? o1 > o2 : 1) :
|
||||
(o2 & mach_long_sign ? 0 : o1 > o2)
|
||||
);
|
||||
}
|
||||
else
|
||||
o1 = o1 > o2;
|
||||
break;
|
||||
case LESSEQ:
|
||||
{
|
||||
arith tmp = o1;
|
||||
|
||||
o1 = o2;
|
||||
o2 = tmp;
|
||||
}
|
||||
/* Fall through */
|
||||
case GREATEREQ:
|
||||
if (uns) {
|
||||
o1 = (o1 & mach_long_sign ?
|
||||
(o2 & mach_long_sign ? o1 >= o2 : 1) :
|
||||
(o2 & mach_long_sign ? 0 : o1 >= o2)
|
||||
);
|
||||
}
|
||||
else
|
||||
o1 = o1 >= o2;
|
||||
break;
|
||||
case EQUAL:
|
||||
o1 = o1 == o2;
|
||||
break;
|
||||
case NOTEQUAL:
|
||||
o1 = o1 != o2;
|
||||
break;
|
||||
case '&':
|
||||
o1 &= o2;
|
||||
break;
|
||||
case '|':
|
||||
o1 |= o2;
|
||||
break;
|
||||
case '^':
|
||||
o1 ^= o2;
|
||||
break;
|
||||
}
|
||||
(*expp)->VL_VALUE = o1;
|
||||
cut_size(*expp);
|
||||
(*expp)->ex_flags |= expr->ex_flags;
|
||||
(*expp)->ex_flags &= ~EX_PARENS;
|
||||
free_expression(expr);
|
||||
}
|
||||
|
||||
cut_size(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* The constant value of the expression expr is made to
|
||||
conform to the size of the type of the expression.
|
||||
*/
|
||||
register arith o1 = expr->VL_VALUE;
|
||||
int uns = expr->ex_type->tp_unsigned;
|
||||
int size = (int) expr->ex_type->tp_size;
|
||||
|
||||
ASSERT(expr->ex_class == Value);
|
||||
if (expr->ex_type->tp_fund == POINTER) {
|
||||
/* why warn on "ptr-3" ?
|
||||
This quick hack fixes it
|
||||
*/
|
||||
uns = 0;
|
||||
}
|
||||
if (uns) {
|
||||
if (o1 & ~full_mask[size])
|
||||
expr_warning(expr,
|
||||
"overflow in unsigned constant expression");
|
||||
o1 &= full_mask[size];
|
||||
}
|
||||
else {
|
||||
int nbits = (int) (mach_long_size - size) * 8;
|
||||
long remainder = o1 & ~full_mask[size];
|
||||
|
||||
if (remainder != 0 && remainder != ~full_mask[size])
|
||||
expr_warning(expr, "overflow in constant expression");
|
||||
o1 <<= nbits; /* ??? */
|
||||
o1 >>= nbits;
|
||||
}
|
||||
expr->VL_VALUE = o1;
|
||||
}
|
||||
|
||||
init_cst()
|
||||
{
|
||||
register int i = 0;
|
||||
register arith bt = (arith)0;
|
||||
|
||||
while (!(bt < 0)) {
|
||||
bt = (bt << 8) + 0377, i++;
|
||||
if (i == MAXSIZE)
|
||||
fatal("array full_mask too small for this machine");
|
||||
full_mask[i] = bt;
|
||||
}
|
||||
mach_long_size = i;
|
||||
mach_long_sign = 1L << (mach_long_size * 8 - 1);
|
||||
if (long_size < mach_long_size)
|
||||
fatal("sizeof (long) insufficient on this machine");
|
||||
max_int = full_mask[(int)int_size] & ~(1L << (int_size * 8 - 1));
|
||||
max_unsigned = full_mask[(int)int_size];
|
||||
}
|
||||
37
lang/cem/cemcom/dataflow.c
Normal file
37
lang/cem/cemcom/dataflow.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* DATAFLOW ANALYSIS ON C PROGRAMS */
|
||||
|
||||
/* Compile the C compiler with flag DATAFLOW.
|
||||
Use the compiler option --d.
|
||||
*/
|
||||
|
||||
#include "dataflow.h" /* UF */
|
||||
|
||||
#ifdef DATAFLOW
|
||||
char *CurrentFunction = 0;
|
||||
int NumberOfCalls;
|
||||
|
||||
DfaStartFunction(nm)
|
||||
char *nm;
|
||||
{
|
||||
CurrentFunction = nm;
|
||||
NumberOfCalls = 0;
|
||||
}
|
||||
|
||||
DfaEndFunction()
|
||||
{
|
||||
if (NumberOfCalls == 0)
|
||||
print("DFA: %s: --none--\n", CurrentFunction);
|
||||
}
|
||||
|
||||
DfaCallFunction(s)
|
||||
char *s;
|
||||
{
|
||||
print("DFA: %s: %s\n", CurrentFunction, s);
|
||||
++NumberOfCalls;
|
||||
}
|
||||
#endif DATAFLOW
|
||||
492
lang/cem/cemcom/declar.g
Normal file
492
lang/cem/cemcom/declar.g
Normal file
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* DECLARATION SYNTAX PARSER */
|
||||
|
||||
{
|
||||
#include <alloc.h>
|
||||
#include "nobitfield.h"
|
||||
#include "debug.h"
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "idf.h"
|
||||
#include "type.h"
|
||||
#include "struct.h"
|
||||
#include "field.h"
|
||||
#include "decspecs.h"
|
||||
#include "def.h"
|
||||
#include "declar.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "sizes.h"
|
||||
#include "level.h"
|
||||
|
||||
extern char options[];
|
||||
}
|
||||
|
||||
/* 8 */
|
||||
declaration
|
||||
{struct decspecs Ds;}
|
||||
:
|
||||
{Ds = null_decspecs;}
|
||||
decl_specifiers(&Ds)
|
||||
init_declarator_list(&Ds)?
|
||||
';'
|
||||
;
|
||||
|
||||
/* A `decl_specifiers' describes a sequence of a storage_class_specifier,
|
||||
an unsigned_specifier, a size_specifier and a simple type_specifier,
|
||||
which may occur in arbitrary order and each of which may be absent;
|
||||
at least one of them must be present, however, since the totally
|
||||
empty case has already be dealt with in `external_definition'.
|
||||
This means that something like:
|
||||
unsigned extern int short xx;
|
||||
is perfectly good C.
|
||||
|
||||
On top of that, multiple occurrences of storage_class_specifiers,
|
||||
unsigned_specifiers and size_specifiers are errors, but a second
|
||||
type_specifier should end the decl_specifiers and be treated as
|
||||
the name to be declared (see the thin ice in RM11.1).
|
||||
Such a language is not easily expressed in a grammar; enumeration
|
||||
of the permutations is unattractive. We solve the problem by
|
||||
having a regular grammar for the "soft" items, handling the single
|
||||
occurrence of the type_specifier in the grammar (we have no choice),
|
||||
collecting all data in a `struct decspecs' and turning that data
|
||||
structure into what we want.
|
||||
|
||||
The existence of declarations like
|
||||
short typedef yepp;
|
||||
makes all hope of writing a specific grammar for typedefs illusory.
|
||||
*/
|
||||
|
||||
decl_specifiers /* non-empty */ (register struct decspecs *ds;)
|
||||
/* Reads a non-empty decl_specifiers and fills the struct
|
||||
decspecs *ds.
|
||||
*/
|
||||
:
|
||||
[
|
||||
other_specifier(ds)+
|
||||
[%if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
|
||||
/* the thin ice in R.M. 11.1 */
|
||||
single_type_specifier(ds) other_specifier(ds)*
|
||||
|
|
||||
empty
|
||||
]
|
||||
|
|
||||
single_type_specifier(ds) other_specifier(ds)*
|
||||
]
|
||||
{do_decspecs(ds);}
|
||||
;
|
||||
|
||||
/* 8.1 */
|
||||
other_specifier(register struct decspecs *ds;):
|
||||
[ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
|
||||
{ if (ds->ds_sc_given)
|
||||
error("repeated storage class specifier");
|
||||
ds->ds_sc_given = 1;
|
||||
ds->ds_sc = DOT;
|
||||
}
|
||||
|
|
||||
[ SHORT | LONG ]
|
||||
{ if (ds->ds_size)
|
||||
error("repeated size specifier");
|
||||
ds->ds_size = DOT;
|
||||
}
|
||||
|
|
||||
UNSIGNED
|
||||
{ if (ds->ds_unsigned)
|
||||
error("unsigned specified twice");
|
||||
ds->ds_unsigned = 1;
|
||||
}
|
||||
;
|
||||
|
||||
/* 8.2 */
|
||||
type_specifier(struct type **tpp;)
|
||||
/* Used in struct/union declarations and in casts; only the
|
||||
type is relevant.
|
||||
*/
|
||||
{struct decspecs Ds; Ds = null_decspecs;}
|
||||
:
|
||||
decl_specifiers(&Ds)
|
||||
{
|
||||
if (Ds.ds_sc_given)
|
||||
error("storage class ignored");
|
||||
if (Ds.ds_sc == REGISTER)
|
||||
error("register ignored");
|
||||
}
|
||||
{*tpp = Ds.ds_type;}
|
||||
;
|
||||
|
||||
single_type_specifier(register struct decspecs *ds;):
|
||||
TYPE_IDENTIFIER /* this includes INT, CHAR, etc. */
|
||||
{idf2type(dot.tk_idf, &ds->ds_type);}
|
||||
|
|
||||
IDENTIFIER
|
||||
{error("%s is not a type identifier", dot.tk_idf->id_text);
|
||||
dot.tk_idf->id_def->df_type = error_type;
|
||||
dot.tk_idf->id_def->df_sc = TYPEDEF;
|
||||
ds->ds_type = error_type;
|
||||
}
|
||||
|
|
||||
struct_or_union_specifier(&ds->ds_type)
|
||||
|
|
||||
enum_specifier(&ds->ds_type)
|
||||
;
|
||||
|
||||
/* 8.3 */
|
||||
init_declarator_list(struct decspecs *ds;):
|
||||
init_declarator(ds)
|
||||
[ ',' init_declarator(ds) ]*
|
||||
;
|
||||
|
||||
init_declarator(register struct decspecs *ds;)
|
||||
{
|
||||
struct declarator Dc;
|
||||
}
|
||||
:
|
||||
{
|
||||
Dc = null_declarator;
|
||||
}
|
||||
[
|
||||
declarator(&Dc)
|
||||
{
|
||||
reject_params(&Dc);
|
||||
declare_idf(ds, &Dc, level);
|
||||
}
|
||||
[
|
||||
initializer(Dc.dc_idf, ds->ds_sc)
|
||||
|
|
||||
{ code_declaration(Dc.dc_idf, (struct expr *) 0, level, ds->ds_sc); }
|
||||
]
|
||||
]
|
||||
{remove_declarator(&Dc);}
|
||||
;
|
||||
|
||||
/* 8.6: initializer */
|
||||
initializer(struct idf *idf; int sc;)
|
||||
{
|
||||
struct expr *expr = (struct expr *) 0;
|
||||
int globalflag = level == L_GLOBAL ||
|
||||
(level == L_LOCAL && sc == STATIC);
|
||||
}
|
||||
:
|
||||
{ if (idf->id_def->df_type->tp_fund == FUNCTION) {
|
||||
error("illegal initialization of function");
|
||||
}
|
||||
}
|
||||
[
|
||||
'='
|
||||
|
|
||||
empty
|
||||
{warning("old-fashioned initialization, insert =");}
|
||||
/* This causes trouble at declarator and at
|
||||
external_definition, q.v.
|
||||
*/
|
||||
]
|
||||
{ if (globalflag) {
|
||||
struct expr ex;
|
||||
code_declaration(idf, &ex, level, sc);
|
||||
}
|
||||
}
|
||||
initial_value(globalflag ? &(idf->id_def->df_type) : (struct type **)0,
|
||||
&expr)
|
||||
{ if (! globalflag) {
|
||||
if (idf->id_def->df_type->tp_fund == FUNCTION) {
|
||||
free_expression(expr);
|
||||
expr = 0;
|
||||
}
|
||||
code_declaration(idf, expr, level, sc);
|
||||
#ifdef DEBUG
|
||||
print_expr("initializer-expression", expr);
|
||||
#endif DEBUG
|
||||
}
|
||||
init_idf(idf);
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
Functions yielding pointers to functions must be declared as, e.g.,
|
||||
int (*hehe(par1, par2))() char *par1, *par2; {}
|
||||
Since the function heading is read as a normal declarator,
|
||||
we just include the (formal) parameter list in the declarator
|
||||
description list dc.
|
||||
*/
|
||||
declarator(register struct declarator *dc;)
|
||||
{
|
||||
arith count;
|
||||
struct formal *fm = 0;
|
||||
}
|
||||
:
|
||||
primary_declarator(dc)
|
||||
[%while(1) /* int i (M + 2) / 4;
|
||||
is a function, not an
|
||||
old-fashioned initialization.
|
||||
*/
|
||||
'('
|
||||
formal_list(&fm) ? /* semantic check later... */
|
||||
')'
|
||||
{
|
||||
add_decl_unary(dc, FUNCTION, (arith)0, fm);
|
||||
fm = 0;
|
||||
}
|
||||
|
|
||||
arrayer(&count)
|
||||
{add_decl_unary(dc, ARRAY, count, NO_PARAMS);}
|
||||
]*
|
||||
|
|
||||
'*' declarator(dc)
|
||||
{add_decl_unary(dc, POINTER, (arith)0, NO_PARAMS);}
|
||||
;
|
||||
|
||||
primary_declarator(register struct declarator *dc;) :
|
||||
identifier(&dc->dc_idf)
|
||||
|
|
||||
'(' declarator(dc) ')'
|
||||
;
|
||||
|
||||
arrayer(arith *sizep;)
|
||||
{ struct expr *expr; }
|
||||
:
|
||||
'['
|
||||
[
|
||||
constant_expression(&expr)
|
||||
{
|
||||
check_array_subscript(expr);
|
||||
*sizep = expr->VL_VALUE;
|
||||
free_expression(expr);
|
||||
}
|
||||
|
|
||||
empty
|
||||
{ *sizep = (arith)-1; }
|
||||
]
|
||||
']'
|
||||
;
|
||||
|
||||
formal_list (struct formal **fmp;)
|
||||
:
|
||||
formal(fmp) [ ',' formal(fmp) ]*
|
||||
;
|
||||
|
||||
formal(struct formal **fmp;)
|
||||
{struct idf *idf; }
|
||||
:
|
||||
identifier(&idf)
|
||||
{
|
||||
register struct formal *new = new_formal();
|
||||
|
||||
new->fm_idf = idf;
|
||||
new->next = *fmp;
|
||||
*fmp = new;
|
||||
}
|
||||
;
|
||||
|
||||
/* Change 2 */
|
||||
enum_specifier(register struct type **tpp;)
|
||||
{
|
||||
struct idf *idf;
|
||||
arith l = (arith)0;
|
||||
}
|
||||
:
|
||||
ENUM
|
||||
[
|
||||
{declare_struct(ENUM, (struct idf *) 0, tpp);}
|
||||
enumerator_pack(*tpp, &l)
|
||||
|
|
||||
identifier(&idf)
|
||||
[
|
||||
{declare_struct(ENUM, idf, tpp);}
|
||||
enumerator_pack(*tpp, &l)
|
||||
|
|
||||
{apply_struct(ENUM, idf, tpp);}
|
||||
empty
|
||||
]
|
||||
]
|
||||
;
|
||||
|
||||
enumerator_pack(register struct type *tp; arith *lp;) :
|
||||
'{'
|
||||
enumerator(tp, lp)
|
||||
[%while(AHEAD != '}') /* >>> conflict on ',' */
|
||||
','
|
||||
enumerator(tp, lp)
|
||||
]*
|
||||
','? /* optional trailing comma */
|
||||
'}'
|
||||
{tp->tp_size = int_size;}
|
||||
/* fancy implementations that put small enums in 1 byte
|
||||
or so should start here.
|
||||
*/
|
||||
;
|
||||
|
||||
enumerator(struct type *tp; arith *lp;)
|
||||
{
|
||||
struct idf *idf;
|
||||
struct expr *expr;
|
||||
}
|
||||
:
|
||||
identifier(&idf)
|
||||
[
|
||||
'='
|
||||
constant_expression(&expr)
|
||||
{
|
||||
*lp = expr->VL_VALUE;
|
||||
free_expression(expr);
|
||||
}
|
||||
]?
|
||||
{declare_enum(tp, idf, (*lp)++);}
|
||||
;
|
||||
|
||||
/* 8.5 */
|
||||
struct_or_union_specifier(register struct type **tpp;)
|
||||
{
|
||||
int fund;
|
||||
struct idf *idfX;
|
||||
register struct idf *idf;
|
||||
}
|
||||
:
|
||||
[ STRUCT | UNION ]
|
||||
{fund = DOT;}
|
||||
[
|
||||
{
|
||||
declare_struct(fund, (struct idf *)0, tpp);
|
||||
}
|
||||
struct_declaration_pack(*tpp)
|
||||
|
|
||||
identifier(&idfX) { idf = idfX; }
|
||||
[
|
||||
{
|
||||
declare_struct(fund, idf, tpp);
|
||||
(idf->id_struct->tg_busy)++;
|
||||
}
|
||||
struct_declaration_pack(*tpp)
|
||||
{
|
||||
(idf->id_struct->tg_busy)--;
|
||||
}
|
||||
|
|
||||
{apply_struct(fund, idf, tpp);}
|
||||
empty
|
||||
]
|
||||
]
|
||||
;
|
||||
|
||||
struct_declaration_pack(register struct type *stp;)
|
||||
{
|
||||
struct sdef **sdefp = &stp->tp_sdef;
|
||||
arith size = (arith)0;
|
||||
}
|
||||
:
|
||||
/* The size is only filled in after the whole struct has
|
||||
been read, to prevent recursive definitions.
|
||||
*/
|
||||
'{'
|
||||
struct_declaration(stp, &sdefp, &size)+
|
||||
'}'
|
||||
{stp->tp_size = align(size, stp->tp_align);}
|
||||
;
|
||||
|
||||
struct_declaration(struct type *stp; struct sdef ***sdefpp; arith *szp;)
|
||||
{struct type *tp;}
|
||||
:
|
||||
type_specifier(&tp)
|
||||
struct_declarator_list(tp, stp, sdefpp, szp)
|
||||
[ /* in some standard UNIX compilers the semicolon
|
||||
is optional, would you believe!
|
||||
*/
|
||||
';'
|
||||
|
|
||||
empty
|
||||
{warning("no semicolon after declarator");}
|
||||
]
|
||||
;
|
||||
|
||||
struct_declarator_list(struct type *tp, *stp;
|
||||
struct sdef ***sdefpp; arith *szp;)
|
||||
:
|
||||
struct_declarator(tp, stp, sdefpp, szp)
|
||||
[ ',' struct_declarator(tp, stp, sdefpp, szp) ]*
|
||||
;
|
||||
|
||||
struct_declarator(struct type *tp; struct type *stp;
|
||||
struct sdef ***sdefpp; arith *szp;)
|
||||
{
|
||||
struct declarator Dc;
|
||||
struct field *fd = 0;
|
||||
}
|
||||
:
|
||||
{
|
||||
Dc = null_declarator;
|
||||
}
|
||||
[
|
||||
declarator(&Dc)
|
||||
{reject_params(&Dc);}
|
||||
bit_expression(&fd)?
|
||||
|
|
||||
{Dc.dc_idf = gen_idf();}
|
||||
bit_expression(&fd)
|
||||
]
|
||||
{add_sel(stp, declare_type(tp, &Dc), Dc.dc_idf, sdefpp, szp, fd);}
|
||||
{remove_declarator(&Dc);}
|
||||
;
|
||||
|
||||
bit_expression(struct field **fd;)
|
||||
{ struct expr *expr; }
|
||||
:
|
||||
{
|
||||
*fd = new_field();
|
||||
}
|
||||
':'
|
||||
constant_expression(&expr)
|
||||
{
|
||||
(*fd)->fd_width = expr->VL_VALUE;
|
||||
free_expression(expr);
|
||||
#ifdef NOBITFIELD
|
||||
error("bitfields are not implemented");
|
||||
#endif NOBITFIELD
|
||||
}
|
||||
;
|
||||
|
||||
/* 8.7 */
|
||||
cast(struct type **tpp;) {struct declarator Dc;} :
|
||||
{Dc = null_declarator;}
|
||||
'('
|
||||
type_specifier(tpp)
|
||||
abstract_declarator(&Dc)
|
||||
')'
|
||||
{*tpp = declare_type(*tpp, &Dc);}
|
||||
{remove_declarator(&Dc);}
|
||||
;
|
||||
|
||||
/* This code is an abject copy of that of 'declarator', for lack of
|
||||
a two-level grammar.
|
||||
*/
|
||||
abstract_declarator(register struct declarator *dc;)
|
||||
{arith count;}
|
||||
:
|
||||
primary_abstract_declarator(dc)
|
||||
[
|
||||
'(' ')'
|
||||
{add_decl_unary(dc, FUNCTION, (arith)0, NO_PARAMS);}
|
||||
|
|
||||
arrayer(&count)
|
||||
{add_decl_unary(dc, ARRAY, count, NO_PARAMS);}
|
||||
]*
|
||||
|
|
||||
'*' abstract_declarator(dc)
|
||||
{add_decl_unary(dc, POINTER, (arith)0, NO_PARAMS);}
|
||||
;
|
||||
|
||||
primary_abstract_declarator(struct declarator *dc;) :
|
||||
[%if (AHEAD == ')')
|
||||
empty
|
||||
|
|
||||
'(' abstract_declarator(dc) ')'
|
||||
]
|
||||
;
|
||||
|
||||
empty:
|
||||
;
|
||||
|
||||
/* 8.8 */
|
||||
/* included in the IDENTIFIER/TYPE_IDENTIFIER mechanism */
|
||||
41
lang/cem/cemcom/declar.str
Normal file
41
lang/cem/cemcom/declar.str
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* DEFINITION OF DECLARATOR DESCRIPTORS */
|
||||
|
||||
/* A 'declarator' consists of an idf and a linked list of
|
||||
language-defined unary operations: *, [] and (), called
|
||||
decl_unary's.
|
||||
*/
|
||||
|
||||
struct declarator {
|
||||
struct declarator *next;
|
||||
struct idf *dc_idf;
|
||||
struct decl_unary *dc_decl_unary;
|
||||
struct formal *dc_formal; /* params for function */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "declarator" 50 */
|
||||
|
||||
|
||||
struct formal { /* list of formals */
|
||||
struct formal *next;
|
||||
struct idf *fm_idf;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "formal" 5 */
|
||||
|
||||
#define NO_PARAMS ((struct formal *) 0)
|
||||
|
||||
struct decl_unary {
|
||||
struct decl_unary *next;
|
||||
int du_fund; /* POINTER, ARRAY or FUNCTION */
|
||||
arith du_count; /* for ARRAYs only */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "decl_unary" 10 */
|
||||
|
||||
extern struct type *declare_type();
|
||||
extern struct declarator null_declarator;
|
||||
112
lang/cem/cemcom/declarator.c
Normal file
112
lang/cem/cemcom/declarator.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* D E C L A R A T O R M A N I P U L A T I O N */
|
||||
|
||||
#include "botch_free.h"
|
||||
#include <alloc.h>
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "Lpars.h"
|
||||
#include "declar.h"
|
||||
#include "idf.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "sizes.h"
|
||||
|
||||
struct declarator null_declarator;
|
||||
|
||||
struct type *
|
||||
declare_type(tp, dc)
|
||||
struct type *tp;
|
||||
struct declarator *dc;
|
||||
{
|
||||
/* Applies the decl_unary list starting at dc->dc_decl_unary
|
||||
to the type tp and returns the result.
|
||||
*/
|
||||
register struct decl_unary *du = dc->dc_decl_unary;
|
||||
|
||||
while (du) {
|
||||
tp = construct_type(du->du_fund, tp, du->du_count);
|
||||
du = du->next;
|
||||
}
|
||||
return tp;
|
||||
}
|
||||
|
||||
add_decl_unary(dc, fund, count, fm)
|
||||
register struct declarator *dc;
|
||||
arith count;
|
||||
struct formal *fm;
|
||||
{
|
||||
/* A decl_unary describing a constructor with fundamental
|
||||
type fund and with size count is inserted in front of the
|
||||
declarator dc.
|
||||
*/
|
||||
register struct decl_unary *new = new_decl_unary();
|
||||
|
||||
new->next = dc->dc_decl_unary;
|
||||
new->du_fund = fund;
|
||||
new->du_count = count;
|
||||
if (fm) {
|
||||
if (dc->dc_decl_unary) {
|
||||
/* paramlist only allowed at first decl_unary */
|
||||
error("formal parameter list discarded");
|
||||
}
|
||||
else {
|
||||
/* register the parameters */
|
||||
dc->dc_formal = fm;
|
||||
}
|
||||
}
|
||||
dc->dc_decl_unary = new;
|
||||
}
|
||||
|
||||
remove_declarator(dc)
|
||||
struct declarator *dc;
|
||||
{
|
||||
/* The decl_unary list starting at dc->dc_decl_unary is
|
||||
removed.
|
||||
*/
|
||||
register struct decl_unary *du = dc->dc_decl_unary;
|
||||
|
||||
while (du) {
|
||||
struct decl_unary *old_du = du;
|
||||
|
||||
du = du->next;
|
||||
free_decl_unary(old_du);
|
||||
}
|
||||
}
|
||||
|
||||
reject_params(dc)
|
||||
register struct declarator *dc;
|
||||
{
|
||||
/* The declarator is checked to have no parameters, if it
|
||||
is a function.
|
||||
*/
|
||||
if (dc->dc_formal) {
|
||||
error("non_empty formal parameter pack");
|
||||
free_formals(dc->dc_formal);
|
||||
dc->dc_formal = 0;
|
||||
}
|
||||
}
|
||||
|
||||
check_array_subscript(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
arith size = expr->VL_VALUE;
|
||||
|
||||
if (size < 0) {
|
||||
error("negative number of array elements");
|
||||
expr->VL_VALUE = (arith)1;
|
||||
}
|
||||
else
|
||||
if (size == 0) {
|
||||
warning("empty array declaration");
|
||||
}
|
||||
else
|
||||
if (size & ~max_unsigned) { /* absolutely ridiculous */
|
||||
expr_error(expr, "overflow in array size");
|
||||
expr->VL_VALUE = (arith)1;
|
||||
}
|
||||
}
|
||||
45
lang/cem/cemcom/declarator.h
Normal file
45
lang/cem/cemcom/declarator.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* $Header$ */
|
||||
/* DEFINITION OF DECLARATOR DESCRIPTORS */
|
||||
|
||||
/* A 'declarator' consists of an idf and a linked list of
|
||||
language-defined unary operations: *, [] and (), called
|
||||
decl_unary's.
|
||||
*/
|
||||
|
||||
struct declarator {
|
||||
struct declarator *next;
|
||||
struct idf *dc_idf;
|
||||
struct decl_unary *dc_decl_unary;
|
||||
struct idstack_item *dc_fparams; /* params for function */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct declarator */
|
||||
/* ALLOCDEF "declarator" */
|
||||
extern char *st_alloc();
|
||||
extern struct declarator *h_declarator;
|
||||
#define new_declarator() ((struct declarator *) \
|
||||
st_alloc((char **)&h_declarator, sizeof(struct declarator)))
|
||||
#define free_declarator(p) st_free(p, h_declarator, sizeof(struct declarator))
|
||||
|
||||
|
||||
#define NO_PARAMS ((struct idstack_item *) 0)
|
||||
|
||||
struct decl_unary {
|
||||
struct decl_unary *next;
|
||||
int du_fund; /* POINTER, ARRAY or FUNCTION */
|
||||
arith du_count; /* for ARRAYs only */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct decl_unary */
|
||||
/* ALLOCDEF "decl_unary" */
|
||||
extern char *st_alloc();
|
||||
extern struct decl_unary *h_decl_unary;
|
||||
#define new_decl_unary() ((struct decl_unary *) \
|
||||
st_alloc((char **)&h_decl_unary, sizeof(struct decl_unary)))
|
||||
#define free_decl_unary(p) st_free(p, h_decl_unary, sizeof(struct decl_unary))
|
||||
|
||||
|
||||
extern struct type *declare_type();
|
||||
extern struct declarator null_declarator;
|
||||
108
lang/cem/cemcom/decspecs.c
Normal file
108
lang/cem/cemcom/decspecs.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* D E C L A R A T I O N S P E C I F I E R C H E C K I N G */
|
||||
|
||||
#include "nofloat.h"
|
||||
#include "Lpars.h"
|
||||
#include "decspecs.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "level.h"
|
||||
#include "def.h"
|
||||
#include "noRoption.h"
|
||||
|
||||
extern char options[];
|
||||
extern int level;
|
||||
extern char *symbol2str();
|
||||
|
||||
struct decspecs null_decspecs;
|
||||
|
||||
do_decspecs(ds)
|
||||
register struct decspecs *ds;
|
||||
{
|
||||
/* The provisional decspecs ds as obtained from the program
|
||||
is turned into a legal consistent decspecs.
|
||||
*/
|
||||
register struct type *tp = ds->ds_type;
|
||||
|
||||
if (level == L_FORMAL1)
|
||||
crash("do_decspecs");
|
||||
|
||||
if ( level == L_GLOBAL &&
|
||||
(ds->ds_sc == AUTO || ds->ds_sc == REGISTER)
|
||||
) {
|
||||
warning("no global %s variable allowed",
|
||||
symbol2str(ds->ds_sc));
|
||||
ds->ds_sc = GLOBAL;
|
||||
}
|
||||
|
||||
if (level == L_FORMAL2) {
|
||||
if (ds->ds_sc_given && ds->ds_sc != AUTO &&
|
||||
ds->ds_sc != REGISTER){
|
||||
extern char *symbol2str();
|
||||
error("%s formal illegal", symbol2str(ds->ds_sc));
|
||||
ds->ds_sc = FORMAL;
|
||||
}
|
||||
}
|
||||
/* The tests concerning types require a full knowledge of the
|
||||
type and will have to be postponed to declare_idf.
|
||||
*/
|
||||
|
||||
/* some adjustments as described in RM 8.2 */
|
||||
if (tp == 0)
|
||||
tp = int_type;
|
||||
switch (ds->ds_size) {
|
||||
case SHORT:
|
||||
if (tp == int_type)
|
||||
tp = short_type;
|
||||
else
|
||||
error("short with illegal type");
|
||||
break;
|
||||
case LONG:
|
||||
if (tp == int_type)
|
||||
tp = long_type;
|
||||
else
|
||||
#ifndef NOFLOAT
|
||||
if (tp == float_type)
|
||||
tp = double_type;
|
||||
else
|
||||
#endif NOFLOAT
|
||||
error("long with illegal type");
|
||||
break;
|
||||
}
|
||||
if (ds->ds_unsigned) {
|
||||
switch (tp->tp_fund) {
|
||||
case CHAR:
|
||||
#ifndef NOROPTION
|
||||
if (options['R'])
|
||||
warning("unsigned char not allowed");
|
||||
#endif
|
||||
tp = uchar_type;
|
||||
break;
|
||||
case SHORT:
|
||||
#ifndef NOROPTION
|
||||
if (options['R'])
|
||||
warning("unsigned short not allowed");
|
||||
#endif
|
||||
tp = ushort_type;
|
||||
break;
|
||||
case INT:
|
||||
tp = uint_type;
|
||||
break;
|
||||
case LONG:
|
||||
#ifndef NOROPTION
|
||||
if (options['R'])
|
||||
warning("unsigned long not allowed");
|
||||
#endif
|
||||
tp = ulong_type;
|
||||
break;
|
||||
default:
|
||||
error("unsigned with illegal type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
ds->ds_type = tp;
|
||||
}
|
||||
23
lang/cem/cemcom/decspecs.h
Normal file
23
lang/cem/cemcom/decspecs.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* $Header$ */
|
||||
/* DECLARATION SPECIFIER DEFINITION */
|
||||
|
||||
struct decspecs {
|
||||
struct decspecs *next;
|
||||
struct type *ds_type; /* single type */
|
||||
int ds_sc_given; /* 1 if the st. class is explicitly given */
|
||||
int ds_sc; /* storage class, given or implied */
|
||||
int ds_size; /* LONG, SHORT or 0 */
|
||||
int ds_unsigned; /* 0 or 1 */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct decspecs */
|
||||
/* ALLOCDEF "decspecs" */
|
||||
extern char *st_alloc();
|
||||
extern struct decspecs *h_decspecs;
|
||||
#define new_decspecs() ((struct decspecs *) \
|
||||
st_alloc((char **)&h_decspecs, sizeof(struct decspecs)))
|
||||
#define free_decspecs(p) st_free(p, h_decspecs, sizeof(struct decspecs))
|
||||
|
||||
|
||||
extern struct decspecs null_decspecs;
|
||||
19
lang/cem/cemcom/decspecs.str
Normal file
19
lang/cem/cemcom/decspecs.str
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* DECLARATION SPECIFIER DEFINITION */
|
||||
|
||||
struct decspecs {
|
||||
struct decspecs *next;
|
||||
struct type *ds_type; /* single type */
|
||||
int ds_sc_given; /* 1 if the st. class is explicitly given */
|
||||
int ds_sc; /* storage class, given or implied */
|
||||
int ds_size; /* LONG, SHORT or 0 */
|
||||
int ds_unsigned; /* 0 or 1 */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "decspecs" 50 */
|
||||
|
||||
extern struct decspecs null_decspecs;
|
||||
37
lang/cem/cemcom/def.h
Normal file
37
lang/cem/cemcom/def.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* $Header$ */
|
||||
/* IDENTIFIER DEFINITION DESCRIPTOR */
|
||||
|
||||
struct def { /* for ordinary tags */
|
||||
struct def *next;
|
||||
int df_level;
|
||||
struct type *df_type;
|
||||
int df_sc; /* may be:
|
||||
GLOBAL, STATIC, EXTERN, IMPLICIT,
|
||||
TYPEDEF,
|
||||
FORMAL, AUTO,
|
||||
ENUM, LABEL
|
||||
*/
|
||||
int df_register; /* REG_NONE, REG_DEFAULT or REG_BONUS */
|
||||
char df_initialized; /* an initialization has been generated */
|
||||
char df_alloc; /* 0, ALLOC_SEEN or ALLOC_DONE */
|
||||
char df_used; /* set if idf is used */
|
||||
char df_formal_array; /* to warn if sizeof is taken */
|
||||
arith df_address;
|
||||
};
|
||||
|
||||
#define ALLOC_SEEN 1 /* an allocating declaration has been seen */
|
||||
#define ALLOC_DONE 2 /* the allocating declaration has been done */
|
||||
|
||||
#define REG_NONE 0 /* no register candidate */
|
||||
#define REG_DEFAULT 1 /* register candidate, not declared as such */
|
||||
#define REG_BONUS 10 /* register candidate, declared as such */
|
||||
|
||||
|
||||
/* allocation definitions of struct def */
|
||||
/* ALLOCDEF "def" */
|
||||
extern char *st_alloc();
|
||||
extern struct def *h_def;
|
||||
#define new_def() ((struct def *) \
|
||||
st_alloc((char **)&h_def, sizeof(struct def)))
|
||||
#define free_def(p) st_free(p, h_def, sizeof(struct def))
|
||||
|
||||
31
lang/cem/cemcom/def.str
Normal file
31
lang/cem/cemcom/def.str
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* IDENTIFIER DEFINITION DESCRIPTOR */
|
||||
|
||||
struct def { /* for ordinary tags */
|
||||
struct def *next;
|
||||
int df_level;
|
||||
struct type *df_type;
|
||||
int df_sc; /* may be:
|
||||
GLOBAL, STATIC, EXTERN, IMPLICIT,
|
||||
TYPEDEF,
|
||||
FORMAL, AUTO,
|
||||
ENUM, LABEL
|
||||
*/
|
||||
char df_initialized; /* an initialization has been generated */
|
||||
char df_alloc; /* 0, ALLOC_SEEN or ALLOC_DONE */
|
||||
char df_used; /* set if idf is used */
|
||||
char df_formal_array; /* to warn if sizeof is taken */
|
||||
arith df_address;
|
||||
};
|
||||
|
||||
#define ALLOC_SEEN 1 /* an allocating declaration has been seen */
|
||||
#define ALLOC_DONE 2 /* the allocating declaration has been done */
|
||||
|
||||
#define REG_DEFAULT 0 /* register candidate, not declared as such */
|
||||
#define REG_BONUS 10 /* register candidate, declared as such */
|
||||
|
||||
/* ALLOCDEF "def" 50 */
|
||||
685
lang/cem/cemcom/domacro.c
Normal file
685
lang/cem/cemcom/domacro.c
Normal file
@@ -0,0 +1,685 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* PREPROCESSOR: CONTROLLINE INTERPRETER */
|
||||
|
||||
#include "interface.h"
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "debug.h"
|
||||
#include "idf.h"
|
||||
#include "input.h"
|
||||
#include "nopp.h"
|
||||
|
||||
#ifndef NOPP
|
||||
#include "ifdepth.h"
|
||||
#include "botch_free.h"
|
||||
#include "nparams.h"
|
||||
#include "parbufsize.h"
|
||||
#include "textsize.h"
|
||||
#include "idfsize.h"
|
||||
#include "assert.h"
|
||||
#include <alloc.h>
|
||||
#include "class.h"
|
||||
#include "macro.h"
|
||||
|
||||
IMPORT char **inctable; /* list of include directories */
|
||||
IMPORT char *getwdir();
|
||||
PRIVATE char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
|
||||
/* 1 if a corresponding ELSE has been */
|
||||
/* encountered. */
|
||||
|
||||
PRIVATE struct idf *
|
||||
GetIdentifier()
|
||||
{
|
||||
/* returns a pointer to the descriptor of the identifier that is
|
||||
read from the input stream. A null-pointer is returned if
|
||||
the input does not contain an identifier.
|
||||
The substitution of macros is disabled.
|
||||
*/
|
||||
int tok;
|
||||
struct token tk;
|
||||
|
||||
ReplaceMacros = 0;
|
||||
tok = GetToken(&tk);
|
||||
ReplaceMacros = 1;
|
||||
return tok == IDENTIFIER ? tk.tk_idf : (struct idf *)0;
|
||||
}
|
||||
|
||||
/* domacro() is the control line interpreter. The '#' has already
|
||||
been read by the lexical analyzer by which domacro() is called.
|
||||
The token appearing directly after the '#' is obtained by calling
|
||||
the basic lexical analyzing function GetToken() and is interpreted
|
||||
to perform the action belonging to that token.
|
||||
An error message is produced when the token is not recognized,
|
||||
i.e. it is not one of "define" .. "undef" , integer or newline.
|
||||
*/
|
||||
EXPORT
|
||||
domacro()
|
||||
{
|
||||
struct token tk; /* the token itself */
|
||||
|
||||
EoiForNewline = 1;
|
||||
SkipEscNewline = 1;
|
||||
switch(GetToken(&tk)) { /* select control line action */
|
||||
case IDENTIFIER: /* is it a macro keyword? */
|
||||
switch (tk.tk_idf->id_resmac) {
|
||||
case K_DEFINE: /* "define" */
|
||||
do_define();
|
||||
break;
|
||||
case K_ELIF: /* "elif" */
|
||||
do_elif();
|
||||
break;
|
||||
case K_ELSE: /* "else" */
|
||||
do_else();
|
||||
break;
|
||||
case K_ENDIF: /* "endif" */
|
||||
do_endif();
|
||||
break;
|
||||
case K_IF: /* "if" */
|
||||
do_if();
|
||||
break;
|
||||
case K_IFDEF: /* "ifdef" */
|
||||
do_ifdef(1);
|
||||
break;
|
||||
case K_IFNDEF: /* "ifndef" */
|
||||
do_ifdef(0);
|
||||
break;
|
||||
case K_INCLUDE: /* "include" */
|
||||
do_include();
|
||||
break;
|
||||
case K_LINE: /* "line" */
|
||||
/* set LineNumber and FileName according to
|
||||
the arguments.
|
||||
*/
|
||||
if (GetToken(&tk) != INTEGER) {
|
||||
lexerror("#line without linenumber");
|
||||
SkipRestOfLine();
|
||||
}
|
||||
else
|
||||
do_line((unsigned int)tk.tk_ival);
|
||||
break;
|
||||
case K_UNDEF: /* "undef" */
|
||||
do_undef();
|
||||
break;
|
||||
default:
|
||||
/* invalid word seen after the '#' */
|
||||
lexerror("%s: unknown control", tk.tk_idf->id_text);
|
||||
SkipRestOfLine();
|
||||
}
|
||||
break;
|
||||
case INTEGER: /* # <integer> [<filespecifier>]? */
|
||||
do_line((unsigned int)tk.tk_ival);
|
||||
break;
|
||||
case EOI: /* only `#' on this line: do nothing, ignore */
|
||||
break;
|
||||
default: /* invalid token following '#' */
|
||||
lexerror("illegal # line");
|
||||
SkipRestOfLine();
|
||||
}
|
||||
EoiForNewline = 0;
|
||||
SkipEscNewline = 0;
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
skip_block()
|
||||
{
|
||||
/* skip_block() skips the input from
|
||||
1) a false #if, #ifdef, #ifndef or #elif until the
|
||||
corresponding #elif (resulting in true), #else or
|
||||
#endif is read.
|
||||
2) a #else corresponding to a true #if, #ifdef,
|
||||
#ifndef or #elif until the corresponding #endif is
|
||||
seen.
|
||||
*/
|
||||
register int ch;
|
||||
register int skiplevel = nestlevel; /* current nesting level */
|
||||
struct token tk;
|
||||
|
||||
NoUnstack++;
|
||||
for (;;) {
|
||||
LoadChar(ch); /* read first character after newline */
|
||||
if (ch != '#') {
|
||||
if (ch == EOI) {
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
SkipRestOfLine();
|
||||
continue;
|
||||
}
|
||||
if (GetToken(&tk) != IDENTIFIER) {
|
||||
SkipRestOfLine();
|
||||
continue;
|
||||
}
|
||||
/* an IDENTIFIER: look for #if, #ifdef and #ifndef
|
||||
without interpreting them.
|
||||
Interpret #else, #elif and #endif if they occur
|
||||
on the same level.
|
||||
*/
|
||||
switch(tk.tk_idf->id_resmac) {
|
||||
case K_IF:
|
||||
case K_IFDEF:
|
||||
case K_IFNDEF:
|
||||
push_if();
|
||||
break;
|
||||
case K_ELIF:
|
||||
if (nestlevel == skiplevel) {
|
||||
nestlevel--;
|
||||
push_if();
|
||||
if (ifexpr()) {
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case K_ELSE:
|
||||
++(ifstack[nestlevel]);
|
||||
if (nestlevel == skiplevel) {
|
||||
SkipRestOfLine();
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case K_ENDIF:
|
||||
ASSERT(nestlevel >= 0);
|
||||
if (nestlevel == skiplevel) {
|
||||
SkipRestOfLine();
|
||||
nestlevel--;
|
||||
NoUnstack--;
|
||||
return;
|
||||
}
|
||||
nestlevel--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
ifexpr()
|
||||
{
|
||||
/* ifexpr() returns whether the restricted constant
|
||||
expression following #if or #elif evaluates to true. This
|
||||
is done by calling the LLgen generated subparser for
|
||||
constant expressions. The result of this expression will
|
||||
be given in the extern long variable "ifval".
|
||||
*/
|
||||
IMPORT arith ifval;
|
||||
int errors = err_occurred;
|
||||
|
||||
ifval = (arith)0;
|
||||
AccDefined = 1;
|
||||
UnknownIdIsZero = 1;
|
||||
PushLex(); /* NEW parser */
|
||||
If_expr(); /* invoke constant expression parser */
|
||||
PopLex(); /* OLD parser */
|
||||
AccDefined = 0;
|
||||
UnknownIdIsZero = 0;
|
||||
return (errors == err_occurred) && (ifval != (arith)0);
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_include()
|
||||
{
|
||||
/* do_include() performs the inclusion of a file.
|
||||
*/
|
||||
char *filenm;
|
||||
char *result;
|
||||
int tok;
|
||||
struct token tk;
|
||||
|
||||
AccFileSpecifier = 1;
|
||||
if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
|
||||
filenm = tk.tk_bts;
|
||||
else {
|
||||
lexerror("bad include syntax");
|
||||
filenm = (char *)0;
|
||||
}
|
||||
AccFileSpecifier = 0;
|
||||
SkipRestOfLine();
|
||||
inctable[0] = WorkingDir;
|
||||
if (filenm) {
|
||||
if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
|
||||
fatal("cannot find include file \"%s\"", filenm);
|
||||
}
|
||||
else {
|
||||
WorkingDir = getwdir(result);
|
||||
File_Inserted = 1;
|
||||
FileName = result;
|
||||
LineNumber = 0;
|
||||
nestlevel = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_define()
|
||||
{
|
||||
/* do_define() interprets a #define control line.
|
||||
*/
|
||||
struct idf *id; /* the #defined identifier's descriptor */
|
||||
int nformals = -1; /* keep track of the number of formals */
|
||||
char *formals[NPARAMS]; /* pointers to the names of the formals */
|
||||
char parbuf[PARBUFSIZE]; /* names of formals */
|
||||
char *repl_text; /* start of the replacement text */
|
||||
int length; /* length of the replacement text */
|
||||
register ch;
|
||||
char *get_text();
|
||||
|
||||
/* read the #defined macro's name */
|
||||
if (!(id = GetIdentifier())) {
|
||||
lexerror("#define: illegal macro name");
|
||||
SkipRestOfLine();
|
||||
return;
|
||||
}
|
||||
/* there is a formal parameter list if the identifier is
|
||||
followed immediately by a '('.
|
||||
*/
|
||||
LoadChar(ch);
|
||||
if (ch == '(') {
|
||||
if ((nformals = getparams(formals, parbuf)) == -1) {
|
||||
SkipRestOfLine();
|
||||
return; /* an error occurred */
|
||||
}
|
||||
LoadChar(ch);
|
||||
}
|
||||
/* read the replacement text if there is any */
|
||||
ch = skipspaces(ch); /* find first character of the text */
|
||||
ASSERT(ch != EOI);
|
||||
if (class(ch) == STNL) {
|
||||
/* Treat `#define something' as `#define something ""'
|
||||
*/
|
||||
repl_text = "";
|
||||
length = 0;
|
||||
}
|
||||
else {
|
||||
PushBack();
|
||||
repl_text = get_text((nformals > 0) ? formals : 0, &length);
|
||||
}
|
||||
macro_def(id, repl_text, nformals, length, NOFLAG);
|
||||
LineNumber++;
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
push_if()
|
||||
{
|
||||
if (nestlevel >= IFDEPTH)
|
||||
fatal("too many nested #if/#ifdef/#ifndef");
|
||||
else
|
||||
ifstack[++nestlevel] = 0;
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_elif()
|
||||
{
|
||||
if (nestlevel < 0 || (ifstack[nestlevel])) {
|
||||
lexerror("#elif without corresponding #if");
|
||||
SkipRestOfLine();
|
||||
}
|
||||
else { /* restart at this level as if a #if is detected. */
|
||||
nestlevel--;
|
||||
push_if();
|
||||
skip_block();
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_else()
|
||||
{
|
||||
SkipRestOfLine();
|
||||
if (nestlevel < 0 || (ifstack[nestlevel]))
|
||||
lexerror("#else without corresponding #if");
|
||||
else { /* mark this level as else-d */
|
||||
++(ifstack[nestlevel]);
|
||||
skip_block();
|
||||
}
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_endif()
|
||||
{
|
||||
SkipRestOfLine();
|
||||
if (nestlevel < 0) {
|
||||
lexerror("#endif without corresponding #if");
|
||||
}
|
||||
else nestlevel--;
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_if()
|
||||
{
|
||||
push_if();
|
||||
if (!ifexpr()) /* a false #if/#elif expression */
|
||||
skip_block();
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_ifdef(how)
|
||||
{
|
||||
register struct idf *id;
|
||||
|
||||
/* how == 1 : ifdef; how == 0 : ifndef
|
||||
*/
|
||||
push_if();
|
||||
if (!(id = GetIdentifier()))
|
||||
lexerror("illegal #ifdef construction");
|
||||
|
||||
/* The next test is a shorthand for:
|
||||
(how && !id->id_macro) || (!how && id->id_macro)
|
||||
*/
|
||||
if (how ^ (id && id->id_macro != 0))
|
||||
skip_block();
|
||||
else
|
||||
SkipRestOfLine();
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_undef()
|
||||
{
|
||||
register struct idf *id;
|
||||
|
||||
/* Forget a macro definition. */
|
||||
if (id = GetIdentifier()) {
|
||||
if (id->id_macro) { /* forget the macro */
|
||||
free_macro(id->id_macro);
|
||||
id->id_macro = (struct macro *) 0;
|
||||
} /* else: don't complain */
|
||||
}
|
||||
else
|
||||
lexerror("illegal #undef construction");
|
||||
SkipRestOfLine();
|
||||
}
|
||||
|
||||
PRIVATE int
|
||||
getparams(buf, parbuf)
|
||||
char *buf[];
|
||||
char parbuf[];
|
||||
{
|
||||
/* getparams() reads the formal parameter list of a macro
|
||||
definition.
|
||||
The number of parameters is returned.
|
||||
As a formal parameter list is expected when calling this
|
||||
routine, -1 is returned if an error is detected, for
|
||||
example:
|
||||
#define one(1), where 1 is not an identifier.
|
||||
Note that the '(' has already been eaten.
|
||||
The names of the formal parameters are stored into parbuf.
|
||||
*/
|
||||
register char **pbuf = &buf[0];
|
||||
register int c;
|
||||
register char *ptr = &parbuf[0];
|
||||
register char **pbuf2;
|
||||
|
||||
LoadChar(c);
|
||||
c = skipspaces(c);
|
||||
if (c == ')') { /* no parameters: #define name() */
|
||||
*pbuf = (char *) 0;
|
||||
return 0;
|
||||
}
|
||||
for (;;) { /* eat the formal parameter list */
|
||||
if (class(c) != STIDF) { /* not an identifier */
|
||||
lexerror("#define: bad formal parameter");
|
||||
return -1;
|
||||
}
|
||||
*pbuf = ptr; /* name of the formal */
|
||||
*ptr++ = c;
|
||||
if (ptr >= &parbuf[PARBUFSIZE])
|
||||
fatal("formal parameter buffer overflow");
|
||||
do { /* eat the identifier name */
|
||||
LoadChar(c);
|
||||
*ptr++ = c;
|
||||
if (ptr >= &parbuf[PARBUFSIZE])
|
||||
fatal("formal parameter buffer overflow");
|
||||
} while (in_idf(c));
|
||||
*(ptr - 1) = '\0'; /* mark end of the name */
|
||||
|
||||
/* Check if this formal parameter is already used.
|
||||
Usually, macros do not have many parameters, so ...
|
||||
*/
|
||||
for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
|
||||
if (!strcmp(*pbuf2, *pbuf)) {
|
||||
warning("formal parameter \"%s\" already used",
|
||||
*pbuf);
|
||||
}
|
||||
}
|
||||
|
||||
pbuf++;
|
||||
c = skipspaces(c);
|
||||
if (c == ')') { /* end of the formal parameter list */
|
||||
*pbuf = (char *) 0;
|
||||
return pbuf - buf;
|
||||
}
|
||||
if (c != ',') {
|
||||
lexerror("#define: bad formal parameter list");
|
||||
return -1;
|
||||
}
|
||||
LoadChar(c);
|
||||
c = skipspaces(c);
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
EXPORT
|
||||
macro_def(id, text, nformals, length, flags)
|
||||
register struct idf *id;
|
||||
char *text;
|
||||
{
|
||||
register struct macro *newdef = id->id_macro;
|
||||
|
||||
/* macro_def() puts the contents and information of a macro
|
||||
definition into a structure and stores it into the symbol
|
||||
table entry belonging to the name of the macro.
|
||||
A warning is given if the definition overwrites another.
|
||||
*/
|
||||
if (newdef) { /* is there a redefinition? */
|
||||
if (macroeq(newdef->mc_text, text))
|
||||
return;
|
||||
lexwarning("redefine \"%s\"", id->id_text);
|
||||
}
|
||||
else
|
||||
id->id_macro = newdef = new_macro();
|
||||
newdef->mc_text = text; /* replacement text */
|
||||
newdef->mc_nps = nformals; /* nr of formals */
|
||||
newdef->mc_length = length; /* length of repl. text */
|
||||
newdef->mc_flag = flags; /* special flags */
|
||||
newdef->mc_count = 0;
|
||||
}
|
||||
|
||||
PRIVATE int
|
||||
find_name(nm, index)
|
||||
char *nm, *index[];
|
||||
{
|
||||
/* find_name() returns the index of "nm" in the namelist
|
||||
"index" if it can be found there. 0 is returned if it is
|
||||
not there.
|
||||
*/
|
||||
register char **ip = &index[0];
|
||||
|
||||
while (*ip)
|
||||
if (strcmp(nm, *ip++) == 0)
|
||||
return ip - &index[0];
|
||||
/* arrived here, nm is not in the name list. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRIVATE char *
|
||||
get_text(formals, length)
|
||||
char *formals[];
|
||||
int *length;
|
||||
{
|
||||
/* get_text() copies the replacement text of a macro
|
||||
definition with zero, one or more parameters, thereby
|
||||
substituting each formal parameter by a special character
|
||||
(non-ascii: 0200 & (order-number in the formal parameter
|
||||
list)) in order to substitute this character later by the
|
||||
actual parameter. The replacement text is copied into
|
||||
itself because the copied text will contain fewer or the
|
||||
same amount of characters. The length of the replacement
|
||||
text is returned.
|
||||
|
||||
Implementation:
|
||||
finite automaton : we are only interested in
|
||||
identifiers, because they might be replaced by some actual
|
||||
parameter. Other tokens will not be seen as such.
|
||||
*/
|
||||
register int c;
|
||||
register int text_size;
|
||||
char *text = Malloc(text_size = ITEXTSIZE);
|
||||
register int pos = 0;
|
||||
|
||||
LoadChar(c);
|
||||
|
||||
while ((c != EOI) && (class(c) != STNL)) {
|
||||
if (c == '\\') { /* check for "\\\n" */
|
||||
LoadChar(c);
|
||||
if (c == '\n') {
|
||||
/* More than one line is used for the
|
||||
replacement text.
|
||||
Replace "\\\n" by " ".
|
||||
*/
|
||||
text[pos++] = ' ';
|
||||
++LineNumber;
|
||||
LoadChar(c);
|
||||
}
|
||||
else
|
||||
text[pos++] = '\\';
|
||||
if (pos == text_size)
|
||||
text = Srealloc(text, text_size += RTEXTSIZE);
|
||||
}
|
||||
else
|
||||
if ( c == '/') {
|
||||
LoadChar(c);
|
||||
if (c == '*') {
|
||||
skipcomment();
|
||||
text[pos++] = ' ';
|
||||
LoadChar(c);
|
||||
}
|
||||
else
|
||||
text[pos++] = '/';
|
||||
if (pos == text_size)
|
||||
text = Srealloc(text, text_size += RTEXTSIZE);
|
||||
}
|
||||
else
|
||||
if (formals && class(c) == STIDF) {
|
||||
char id_buf[IDFSIZE + 1];
|
||||
register id_size = 0;
|
||||
register n;
|
||||
|
||||
/* read identifier: it may be a formal parameter */
|
||||
id_buf[id_size++] = c;
|
||||
do {
|
||||
LoadChar(c);
|
||||
if (id_size <= IDFSIZE)
|
||||
id_buf[id_size++] = c;
|
||||
} while (in_idf(c));
|
||||
id_buf[--id_size] = '\0';
|
||||
if (n = find_name(id_buf, formals)) {
|
||||
/* construct the formal parameter mark */
|
||||
text[pos++] = FORMALP | (char) n;
|
||||
if (pos == text_size)
|
||||
text = Srealloc(text,
|
||||
text_size += RTEXTSIZE);
|
||||
}
|
||||
else {
|
||||
register char *ptr = &id_buf[0];
|
||||
|
||||
while (pos + id_size >= text_size)
|
||||
text = Srealloc(text,
|
||||
text_size += RTEXTSIZE);
|
||||
while (text[pos++] = *ptr++) ;
|
||||
pos--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
text[pos++] = c;
|
||||
if (pos == text_size)
|
||||
text = Srealloc(text, text_size += RTEXTSIZE);
|
||||
LoadChar(c);
|
||||
}
|
||||
}
|
||||
text[pos++] = '\0';
|
||||
*length = pos - 1;
|
||||
return text;
|
||||
}
|
||||
|
||||
#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
|
||||
|
||||
/* macroeq() decides whether two macro replacement texts are
|
||||
identical. This version compares the texts, which occur
|
||||
as strings, without taking care of the leading and trailing
|
||||
blanks (spaces and tabs).
|
||||
*/
|
||||
PRIVATE
|
||||
macroeq(s, t)
|
||||
register char *s, *t;
|
||||
{
|
||||
|
||||
/* skip leading spaces */
|
||||
while (BLANK(*s)) s++;
|
||||
while (BLANK(*t)) t++;
|
||||
/* first non-blank encountered in both strings */
|
||||
/* The actual comparison loop: */
|
||||
while (*s && *s == *t)
|
||||
s++, t++;
|
||||
/* two cases are possible when arrived here: */
|
||||
if (*s == '\0') { /* *s == '\0' */
|
||||
while (BLANK(*t)) t++;
|
||||
return *t == '\0';
|
||||
}
|
||||
else { /* *s != *t */
|
||||
while (BLANK(*s)) s++;
|
||||
while (BLANK(*t)) t++;
|
||||
return (*s == '\0') && (*t == '\0');
|
||||
}
|
||||
}
|
||||
#else NOPP
|
||||
EXPORT
|
||||
domacro()
|
||||
{
|
||||
int tok;
|
||||
struct token tk;
|
||||
|
||||
EoiForNewline = 1;
|
||||
SkipEscNewline = 1;
|
||||
if ((tok = GetToken(&tk)) == IDENTIFIER) {
|
||||
if (strcmp(tk.tk_idf->id_text, "line") != 0) {
|
||||
error("illegal # line");
|
||||
SkipRestOfLine();
|
||||
return;
|
||||
}
|
||||
tok = GetToken(&tk);
|
||||
}
|
||||
if (tok != INTEGER) {
|
||||
error("illegal # line");
|
||||
SkipRestOfLine();
|
||||
return;
|
||||
}
|
||||
do_line((unsigned int) tk.tk_ival);
|
||||
EoiForNewline = 0;
|
||||
SkipEscNewline = 0;
|
||||
}
|
||||
#endif NOPP
|
||||
|
||||
PRIVATE
|
||||
SkipRestOfLine()
|
||||
{
|
||||
/* we do a PushBack because we don't want to skip the next line
|
||||
if the last character was a newline
|
||||
*/
|
||||
PushBack();
|
||||
skipline();
|
||||
}
|
||||
|
||||
PRIVATE
|
||||
do_line(l)
|
||||
unsigned int l;
|
||||
{
|
||||
struct token tk;
|
||||
|
||||
LineNumber = l - 1; /* the number of the next input line */
|
||||
if (GetToken(&tk) == STRING) /* is there a filespecifier? */
|
||||
FileName = tk.tk_bts;
|
||||
SkipRestOfLine();
|
||||
}
|
||||
144
lang/cem/cemcom/doprnt.c
Normal file
144
lang/cem/cemcom/doprnt.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/* $Header$ */
|
||||
/* STRING MANIPULATION AND PRINT ROUTINES */
|
||||
|
||||
#include <system.h>
|
||||
#include "ssize.h"
|
||||
|
||||
char *long2str();
|
||||
|
||||
static
|
||||
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;
|
||||
}
|
||||
|
||||
static 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 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
403
lang/cem/cemcom/dumpidf.c
Normal file
403
lang/cem/cemcom/dumpidf.c
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* DUMP ROUTINES */
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nofloat.h"
|
||||
#include "nopp.h"
|
||||
#include "nobitfield.h"
|
||||
#include "arith.h"
|
||||
#include "stack.h"
|
||||
#include "idf.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "struct.h"
|
||||
#include "field.h"
|
||||
#include "Lpars.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "static.h"
|
||||
|
||||
/* Some routines (symbol2str, token2str, type2str) which should have
|
||||
* yielded strings are written to yield a pointer to a transient piece
|
||||
* of memory, containing the string, since this is the only reasonable
|
||||
* thing to do in C. `Transient' means that the result may soon
|
||||
* disappear, which is generally not a problem, since normally it is
|
||||
* consumed immediately. Sometimes we need more than one of them, and
|
||||
* MAXTRANS is the maximum number we will need simultaneously.
|
||||
*/
|
||||
#define MAXTRANS 6
|
||||
|
||||
extern char options[];
|
||||
|
||||
extern char *sprint();
|
||||
|
||||
extern struct idf *idf_hashtable[];
|
||||
extern char *symbol2str(), *type2str(), *next_transient();
|
||||
|
||||
enum sdef_kind {selector, field}; /* parameter for dumpsdefs */
|
||||
|
||||
static int dumplevel;
|
||||
|
||||
static
|
||||
newline() {
|
||||
register int dl = dumplevel;
|
||||
|
||||
print("\n");
|
||||
while (dl >= 2) {
|
||||
print("\t");
|
||||
dl -= 2;
|
||||
}
|
||||
if (dl)
|
||||
print(" ");
|
||||
}
|
||||
|
||||
dumpidftab(msg, opt)
|
||||
char msg[];
|
||||
{
|
||||
/* Dumps the identifier table in readable form (but in
|
||||
arbitrary order).
|
||||
Unless opt & 1, macros are not dumped.
|
||||
Unless opt & 2, reserved identifiers are not dumped.
|
||||
Unless opt & 4, universal identifiers are not dumped.
|
||||
*/
|
||||
int i;
|
||||
|
||||
print(">>> DUMPIDF, %s (start)", msg);
|
||||
dumpstack();
|
||||
for (i = 0; i < HASHSIZE; i++) {
|
||||
register struct idf *notch = idf_hashtable[i];
|
||||
|
||||
while (notch) {
|
||||
dumpidf(notch, opt);
|
||||
notch = notch->next;
|
||||
}
|
||||
}
|
||||
newline();
|
||||
print(">>> DUMPIDF, %s (end)\n", msg);
|
||||
}
|
||||
|
||||
dumpstack()
|
||||
{
|
||||
/* Dumps the identifier stack, starting at the top.
|
||||
*/
|
||||
register struct stack_level *stl = local_level;
|
||||
|
||||
while (stl) {
|
||||
register struct stack_entry *se = stl->sl_entry;
|
||||
|
||||
newline();
|
||||
print("%3d: ", stl->sl_level);
|
||||
while (se) {
|
||||
print("%s ", se->se_idf->id_text);
|
||||
se = se->next;
|
||||
}
|
||||
stl = stl->sl_previous;
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
dumpidf(idf, opt)
|
||||
register struct idf *idf;
|
||||
{
|
||||
/* All information about the identifier idf is divulged in a
|
||||
hopefully readable format.
|
||||
*/
|
||||
int started = 0;
|
||||
|
||||
if (!idf)
|
||||
return;
|
||||
#ifndef NOPP
|
||||
if ((opt&1) && idf->id_macro) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
print("%s:", idf->id_text);
|
||||
}
|
||||
print(" macro");
|
||||
}
|
||||
#endif NOPP
|
||||
if ((opt&2) && idf->id_reserved) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
print("%s:", idf->id_text);
|
||||
}
|
||||
print(" reserved: %d;", idf->id_reserved);
|
||||
}
|
||||
if (idf->id_def && ((opt&4) || idf->id_def->df_level)) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
print("%s:", idf->id_text);
|
||||
}
|
||||
dumpdefs(idf->id_def, opt);
|
||||
}
|
||||
if (idf->id_sdef) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
print("%s:", idf->id_text);
|
||||
}
|
||||
dumpsdefs(idf->id_sdef, selector);
|
||||
}
|
||||
if (idf->id_struct) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
print("%s:", idf->id_text);
|
||||
}
|
||||
dumptags(idf->id_struct);
|
||||
}
|
||||
if (idf->id_enum) {
|
||||
if (!started++) {
|
||||
newline();
|
||||
print("%s:", idf->id_text);
|
||||
}
|
||||
dumptags(idf->id_enum);
|
||||
}
|
||||
}
|
||||
|
||||
dumpdefs(def, opt)
|
||||
register struct def *def;
|
||||
{
|
||||
dumplevel++;
|
||||
while (def && ((opt&4) || def->df_level)) {
|
||||
newline();
|
||||
print("L%d: %s %s%s%s%s%s %lo;",
|
||||
def->df_level,
|
||||
symbol2str(def->df_sc),
|
||||
def->df_initialized ? "init'd " : "",
|
||||
def->df_used ? "used " : "",
|
||||
type2str(def->df_type),
|
||||
def->df_sc == ENUM ? ", =" : " at",
|
||||
def->df_address
|
||||
);
|
||||
def = def->next;
|
||||
}
|
||||
dumplevel--;
|
||||
}
|
||||
|
||||
dumptags(tag)
|
||||
register struct tag *tag;
|
||||
{
|
||||
dumplevel++;
|
||||
while (tag) {
|
||||
register struct type *tp = tag->tg_type;
|
||||
register int fund = tp->tp_fund;
|
||||
|
||||
newline();
|
||||
print("L%d: %s %s",
|
||||
tag->tg_level,
|
||||
fund == STRUCT ? "struct" :
|
||||
fund == UNION ? "union" :
|
||||
fund == ENUM ? "enum" : "<UNKNOWN>",
|
||||
tp->tp_idf->id_text
|
||||
);
|
||||
if (is_struct_or_union(fund)) {
|
||||
print(" {");
|
||||
dumpsdefs(tp->tp_sdef, field);
|
||||
newline();
|
||||
print("}");
|
||||
}
|
||||
print(";");
|
||||
tag = tag->next;
|
||||
}
|
||||
dumplevel--;
|
||||
}
|
||||
|
||||
dumpsdefs(sdef, sdk)
|
||||
register struct sdef *sdef;
|
||||
enum sdef_kind sdk;
|
||||
{
|
||||
/* Since sdef's are members of two chains, there are actually
|
||||
two dumpsdefs's, one following the chain of all selectors
|
||||
belonging to the same idf, starting at idf->id_sdef;
|
||||
and the other following the chain of all selectors belonging
|
||||
to the same struct, starting at stp->tp_sdef.
|
||||
*/
|
||||
|
||||
dumplevel++;
|
||||
while (sdef) {
|
||||
newline();
|
||||
print("L%d: ", sdef->sd_level);
|
||||
#ifndef NOBITFIELD
|
||||
if (sdk == selector)
|
||||
#endif NOBITFIELD
|
||||
print("selector %s at offset %lu in %s;",
|
||||
type2str(sdef->sd_type),
|
||||
sdef->sd_offset, type2str(sdef->sd_stype)
|
||||
);
|
||||
#ifndef NOBITFIELD
|
||||
else print("field %s at offset %lu;",
|
||||
type2str(sdef->sd_type), sdef->sd_offset
|
||||
);
|
||||
#endif NOBITFIELD
|
||||
sdef = (sdk == selector ? sdef->next : sdef->sd_sdef);
|
||||
}
|
||||
dumplevel--;
|
||||
}
|
||||
|
||||
char *
|
||||
type2str(tp)
|
||||
register struct type *tp;
|
||||
{
|
||||
/* Yields a pointer to a one-line description of the type tp.
|
||||
*/
|
||||
char *buf = next_transient();
|
||||
int ops = 1;
|
||||
|
||||
buf[0] = '\0';
|
||||
if (!tp) {
|
||||
sprint(buf, "<NILTYPE>");
|
||||
return buf;
|
||||
}
|
||||
sprint(buf, "(@%lx, #%ld, &%d) ",
|
||||
tp, (long)tp->tp_size, tp->tp_align);
|
||||
while (ops) {
|
||||
switch (tp->tp_fund) {
|
||||
case POINTER:
|
||||
sprint(buf, "%spointer to ", buf);
|
||||
break;
|
||||
case ARRAY:
|
||||
sprint(buf, "%sarray [%ld] of ", buf, tp->tp_size);
|
||||
break;
|
||||
case FUNCTION:
|
||||
sprint(buf, "%sfunction yielding ", buf);
|
||||
break;
|
||||
default:
|
||||
sprint(buf, "%s%s%s", buf,
|
||||
tp->tp_unsigned ? "unsigned " : "",
|
||||
symbol2str(tp->tp_fund)
|
||||
);
|
||||
if (tp->tp_idf)
|
||||
sprint(buf, "%s %s", buf,
|
||||
tp->tp_idf->id_text);
|
||||
#ifndef NOBITFIELD
|
||||
if (tp->tp_field) {
|
||||
struct field *fd = tp->tp_field;
|
||||
|
||||
sprint(buf, "%s [s=%ld,w=%ld] of ", buf,
|
||||
fd->fd_shift, fd->fd_width);
|
||||
}
|
||||
else
|
||||
#endif NOBITFIELD
|
||||
ops = 0;
|
||||
break;
|
||||
}
|
||||
tp = tp->tp_up;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
GSTATIC char trans_buf[MAXTRANS][300];
|
||||
|
||||
char * /* the ultimate transient buffer supplier */
|
||||
next_transient()
|
||||
{
|
||||
static int bnum;
|
||||
|
||||
if (++bnum == MAXTRANS)
|
||||
bnum = 0;
|
||||
return trans_buf[bnum];
|
||||
}
|
||||
|
||||
print_expr(msg, expr)
|
||||
char msg[];
|
||||
struct expr *expr;
|
||||
{
|
||||
/* Provisional routine to print an expression preceded by a
|
||||
message msg.
|
||||
*/
|
||||
if (options['x']) {
|
||||
print("\n%s: ", msg);
|
||||
print("(L=line, T=type, r/lV=r/lvalue, F=flags, D=depth)\n");
|
||||
p1_expr(0, expr);
|
||||
}
|
||||
}
|
||||
|
||||
p1_expr(lvl, expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
extern char *type2str(), *symbol2str();
|
||||
|
||||
p1_indent(lvl);
|
||||
if (!expr) {
|
||||
print("NILEXPR\n");
|
||||
return;
|
||||
}
|
||||
print("expr: L=%u, T=%s, %cV, F=%03o, D=%d, %s: ",
|
||||
expr->ex_line,
|
||||
type2str(expr->ex_type),
|
||||
expr->ex_lvalue ? 'l' : 'r',
|
||||
expr->ex_flags & 0xFF,
|
||||
expr->ex_depth,
|
||||
expr->ex_class == Value ? "Value" :
|
||||
expr->ex_class == String ? "String" :
|
||||
#ifndef NOFLOAT
|
||||
expr->ex_class == Float ? "Float" :
|
||||
#endif NOFLOAT
|
||||
expr->ex_class == Oper ? "Oper" :
|
||||
expr->ex_class == Type ? "Type" : "UNKNOWN CLASS"
|
||||
);
|
||||
switch (expr->ex_class) {
|
||||
struct oper *o;
|
||||
case Value:
|
||||
switch (expr->VL_CLASS) {
|
||||
case Const:
|
||||
print("(Const) ");
|
||||
break;
|
||||
case Name:
|
||||
print("(Name) %s + ", expr->VL_IDF->id_text);
|
||||
break;
|
||||
case Label:
|
||||
print("(Label) .%lu + ", expr->VL_LBL);
|
||||
break;
|
||||
default:
|
||||
print("(Unknown) ");
|
||||
break;
|
||||
}
|
||||
print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n",
|
||||
expr->VL_VALUE);
|
||||
break;
|
||||
case String:
|
||||
{
|
||||
char *bts2str();
|
||||
|
||||
print(
|
||||
"%s\n",
|
||||
bts2str(expr->SG_VALUE, expr->SG_LEN, next_transient())
|
||||
);
|
||||
break;
|
||||
}
|
||||
#ifndef NOFLOAT
|
||||
case Float:
|
||||
print("%s\n", expr->FL_VALUE);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
case Oper:
|
||||
o = &expr->ex_object.ex_oper;
|
||||
print("\n");
|
||||
p1_expr(lvl+1, o->op_left);
|
||||
p1_indent(lvl);
|
||||
print("%s <%s>\n", symbol2str(o->op_oper),
|
||||
type2str(o->op_type)
|
||||
);
|
||||
p1_expr(lvl+1, o->op_right);
|
||||
break;
|
||||
case Type:
|
||||
print("\n");
|
||||
break;
|
||||
default:
|
||||
print("UNKNOWN CLASS\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p1_indent(lvl)
|
||||
register int lvl;
|
||||
{
|
||||
while (lvl--)
|
||||
print(" ");
|
||||
}
|
||||
#endif DEBUG
|
||||
201
lang/cem/cemcom/em.c
Normal file
201
lang/cem/cemcom/em.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/* $Header$ */
|
||||
/* EM CODE OUTPUT ROUTINES */
|
||||
|
||||
#define CMODE 0644
|
||||
#define MAX_ARG_CNT 32
|
||||
|
||||
#include "em.h"
|
||||
#include <system.h>
|
||||
#include "arith.h"
|
||||
#include "label.h"
|
||||
|
||||
/*
|
||||
putbyte(), C_open() and C_close() are the basic routines for
|
||||
respectively write on, open and close the output file.
|
||||
The put_*() functions serve as formatting functions of the
|
||||
various EM language constructs.
|
||||
See "Description of a Machine Architecture for use with
|
||||
Block Structured Languages" par. 11.2 for the meaning of these
|
||||
names.
|
||||
*/
|
||||
|
||||
/* supply a kind of buffered output */
|
||||
#define flush(x) sys_write(ofp, &obuf[0], x)
|
||||
|
||||
static char obuf[BUFSIZ];
|
||||
static char *opp = &obuf[0];
|
||||
File *ofp = 0;
|
||||
|
||||
putbyte(b) /* shouldn't putbyte() be a macro ??? (EB) */
|
||||
int b;
|
||||
{
|
||||
if (opp >= &obuf[BUFSIZ]) { /* flush if buffer overflows */
|
||||
if (flush(BUFSIZ) == 0)
|
||||
sys_stop(S_ABORT);
|
||||
opp = &obuf[0];
|
||||
}
|
||||
*opp++ = (char) b;
|
||||
}
|
||||
|
||||
C_init(wsize, psize)
|
||||
arith wsize, psize;
|
||||
{}
|
||||
|
||||
C_open(nm) /* open file for compact code output */
|
||||
char *nm;
|
||||
{
|
||||
if (nm == 0)
|
||||
ofp = STDOUT; /* standard output */
|
||||
else
|
||||
if (sys_open(nm, OP_WRITE, &ofp) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
C_close()
|
||||
{
|
||||
if (flush(opp - &obuf[0]) == 0)
|
||||
sys_stop(S_ABORT);
|
||||
opp = obuf; /* reset opp */
|
||||
if (ofp != STDOUT)
|
||||
sys_close(ofp);
|
||||
ofp = 0;
|
||||
}
|
||||
|
||||
C_busy()
|
||||
{
|
||||
return ofp != 0; /* true if code is being generated */
|
||||
}
|
||||
|
||||
/*** the compact code generating routines ***/
|
||||
#define fit16i(x) ((x) >= (long)0xFFFF8000 && (x) <= (long)0x00007FFF)
|
||||
#define fit8u(x) ((x) <= 0xFF) /* x is already unsigned */
|
||||
|
||||
put_ilb(l)
|
||||
label l;
|
||||
{
|
||||
if (fit8u(l)) {
|
||||
put8(sp_ilb1);
|
||||
put8((int)l);
|
||||
}
|
||||
else {
|
||||
put8(sp_ilb2);
|
||||
put16(l);
|
||||
}
|
||||
}
|
||||
|
||||
put_dlb(l)
|
||||
label l;
|
||||
{
|
||||
if (fit8u(l)) {
|
||||
put8(sp_dlb1);
|
||||
put8((int)l);
|
||||
}
|
||||
else {
|
||||
put8(sp_dlb2);
|
||||
put16(l);
|
||||
}
|
||||
}
|
||||
|
||||
put_cst(l)
|
||||
arith l;
|
||||
{
|
||||
if (l >= (arith) -sp_zcst0 && l < (arith) (sp_ncst0 - sp_zcst0)) {
|
||||
/* we can convert 'l' to an int because its value
|
||||
can be stored in a byte.
|
||||
*/
|
||||
put8((int) l + (sp_zcst0 + sp_fcst0));
|
||||
}
|
||||
else
|
||||
if (fit16i(l)) { /* the cast from long to int causes no trouble here */
|
||||
put8(sp_cst2);
|
||||
put16((int) l);
|
||||
}
|
||||
else {
|
||||
put8(sp_cst4);
|
||||
put32(l);
|
||||
}
|
||||
}
|
||||
|
||||
put_doff(l, v)
|
||||
label l;
|
||||
arith v;
|
||||
{
|
||||
if (v == 0)
|
||||
put_dlb(l);
|
||||
else {
|
||||
put8(sp_doff);
|
||||
put_dlb(l);
|
||||
put_cst(v);
|
||||
}
|
||||
}
|
||||
|
||||
put_noff(s, v)
|
||||
char *s;
|
||||
arith v;
|
||||
{
|
||||
if (v == 0)
|
||||
put_dnam(s);
|
||||
else {
|
||||
put8(sp_doff);
|
||||
put_dnam(s);
|
||||
put_cst(v);
|
||||
}
|
||||
}
|
||||
|
||||
put_dnam(s)
|
||||
char *s;
|
||||
{
|
||||
put8(sp_dnam);
|
||||
put_str(s);
|
||||
}
|
||||
|
||||
put_pnam(s)
|
||||
char *s;
|
||||
{
|
||||
put8(sp_pnam);
|
||||
put_str(s);
|
||||
}
|
||||
|
||||
#ifdef ____
|
||||
put_fcon(s, sz)
|
||||
char *s;
|
||||
arith sz;
|
||||
{
|
||||
put8(sp_fcon);
|
||||
put_cst(sz);
|
||||
put_str(s);
|
||||
}
|
||||
#endif ____
|
||||
|
||||
put_wcon(sp, v, sz) /* sp_icon, sp_ucon or sp_fcon with int repr */
|
||||
int sp;
|
||||
char *v;
|
||||
arith sz;
|
||||
{
|
||||
/* how 'bout signextension int --> long ??? */
|
||||
put8(sp);
|
||||
put_cst(sz);
|
||||
put_str(v);
|
||||
}
|
||||
|
||||
put_str(s)
|
||||
char *s;
|
||||
{
|
||||
register int len;
|
||||
|
||||
put_cst((arith) (len = strlen(s)));
|
||||
while (--len >= 0)
|
||||
put8(*s++);
|
||||
}
|
||||
|
||||
put_cstr(s)
|
||||
char *s;
|
||||
{
|
||||
register int len = prepare_string(s);
|
||||
|
||||
put8(sp_scon);
|
||||
put_cst((arith) len);
|
||||
while (--len >= 0)
|
||||
put8(*s++);
|
||||
}
|
||||
42
lang/cem/cemcom/em.h
Normal file
42
lang/cem/cemcom/em.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* $Header$ */
|
||||
/* DESCRIPTION OF INTERFACE TO EM CODE GENERATING ROUTINES */
|
||||
|
||||
#include "proc_intf.h" /* use macros or functions */
|
||||
|
||||
/* include the EM description files */
|
||||
#include <em_spec.h>
|
||||
#include <em_pseu.h>
|
||||
#include <em_mes.h>
|
||||
#include <em_mnem.h>
|
||||
#include <em_reg.h>
|
||||
|
||||
/* macros used in the definitions of the interface functions C_* */
|
||||
#define OP(x) put_op(x)
|
||||
#define CST(x) put_cst(x)
|
||||
#define DCST(x) put_cst(x)
|
||||
#define CSTR(x) put_cstr(x)
|
||||
#define PS(x) put_ps(x)
|
||||
#define DLB(x) put_dlb(x)
|
||||
#define ILB(x) put_ilb(x)
|
||||
#define NOFF(x,y) put_noff((x), (y))
|
||||
#define DOFF(x,y) put_doff((x), (y))
|
||||
#define PNAM(x) put_pnam(x)
|
||||
#define DNAM(x) put_dnam(x)
|
||||
#define CEND() put_cend()
|
||||
#define WCON(x,y,z) put_wcon((x), (y), (z))
|
||||
#define FCON(x,y) put_fcon((x), (y))
|
||||
|
||||
/* variants of primitive "putbyte" */
|
||||
#define put8(x) putbyte(x) /* defined in "em.c" */
|
||||
#define put16(x) (put8((int) x), put8((int) (x >> 8)))
|
||||
#define put32(x) (put16((int) x), put16((int) (x >> 16)))
|
||||
#define put_cend() put8(sp_cend)
|
||||
#define put_op(x) put8(x)
|
||||
#define put_ps(x) put8(x)
|
||||
|
||||
/* user interface */
|
||||
#define C_magic() put16(sp_magic) /* EM magic word */
|
||||
|
||||
#ifndef PROC_INTF
|
||||
#include "writeem.h"
|
||||
#endif PROC_INTF
|
||||
136
lang/cem/cemcom/emcode.def
Normal file
136
lang/cem/cemcom/emcode.def
Normal file
@@ -0,0 +1,136 @@
|
||||
% emcode definitions for the CEM compiler -- intermediate code
|
||||
C_adf(p) | arith p; | OP(op_adf), CST(p)
|
||||
C_adi(p) | arith p; | OP(op_adi), CST(p)
|
||||
C_adp(p) | arith p; | OP(op_adp), CST(p)
|
||||
C_ads(p) | arith p; | OP(op_ads), CST(p)
|
||||
C_adu(p) | arith p; | OP(op_adu), CST(p)
|
||||
C_and(p) | arith p; | OP(op_and), CST(p)
|
||||
C_asp(p) | arith p; | OP(op_asp), CST(p)
|
||||
C_bra(l) | label l; | OP(op_bra), CST((arith)l)
|
||||
C_cai() | | OP(op_cai)
|
||||
C_cal(p) | char *p; | OP(op_cal), PNAM(p)
|
||||
C_cff() | | OP(op_cff)
|
||||
C_cfi() | | OP(op_cfi)
|
||||
C_cfu() | | OP(op_cfu)
|
||||
C_cif() | | OP(op_cif)
|
||||
C_cii() | | OP(op_cii)
|
||||
C_ciu() | | OP(op_ciu)
|
||||
C_cmf(p) | arith p; | OP(op_cmf), CST(p)
|
||||
C_cmi(p) | arith p; | OP(op_cmi), CST(p)
|
||||
C_cmp() | | OP(op_cmp)
|
||||
C_cmu(p) | arith p; | OP(op_cmu), CST(p)
|
||||
C_com(p) | arith p; | OP(op_com), CST(p)
|
||||
C_csa(p) | arith p; | OP(op_csa), CST(p)
|
||||
C_csb(p) | arith p; | OP(op_csb), CST(p)
|
||||
C_cuf() | | OP(op_cuf)
|
||||
C_cui() | | OP(op_cui)
|
||||
C_cuu() | | OP(op_cuu)
|
||||
C_dup(p) | arith p; | OP(op_dup), CST(p)
|
||||
C_dvf(p) | arith p; | OP(op_dvf), CST(p)
|
||||
C_dvi(p) | arith p; | OP(op_dvi), CST(p)
|
||||
C_dvu(p) | arith p; | OP(op_dvu), CST(p)
|
||||
C_fil_dlb(l, o) | label l; arith o; | OP(op_fil), DOFF(l, o)
|
||||
C_ior(p) | arith p; | OP(op_ior), CST(p)
|
||||
C_lae_dnam(p, o) | char *p; arith o; | OP(op_lae), NOFF(p, o)
|
||||
C_lae_dlb(l, o) | label l; arith o; | OP(op_lae), DOFF(l, o)
|
||||
C_lal(p) | arith p; | OP(op_lal), CST(p)
|
||||
C_ldc(p) | arith p; | OP(op_ldc), DCST(p)
|
||||
C_lde_dnam(p, o) | char *p; arith o; | OP(op_lde), NOFF(p, o)
|
||||
C_lde_dlb(l, o) | label l; arith o; | OP(op_lde), DOFF(l, o)
|
||||
C_ldl(p) | arith p; | OP(op_ldl), CST(p)
|
||||
C_lfr(p) | arith p; | OP(op_lfr), CST(p)
|
||||
C_lin(p) | arith p; | OP(op_lin), CST(p)
|
||||
C_loc(p) | arith p; | OP(op_loc), CST(p)
|
||||
C_loe_dnam(p, o) | char *p; arith o; | OP(op_loe), NOFF(p, o)
|
||||
C_loe_dlb(l, o) | label l; arith o; | OP(op_loe), DOFF(l, o)
|
||||
C_loi(p) | arith p; | OP(op_loi), CST(p)
|
||||
C_lol(p) | arith p; | OP(op_lol), CST(p)
|
||||
C_lor(p) | arith p; | OP(op_lor), CST(p)
|
||||
C_lpi(p) | char *p; | OP(op_lpi), PNAM(p)
|
||||
C_mlf(p) | arith p; | OP(op_mlf), CST(p)
|
||||
C_mli(p) | arith p; | OP(op_mli), CST(p)
|
||||
C_mlu(p) | arith p; | OP(op_mlu), CST(p)
|
||||
C_ngf(p) | arith p; | OP(op_ngf), CST(p)
|
||||
C_ngi(p) | arith p; | OP(op_ngi), CST(p)
|
||||
C_ret(p) | arith p; | OP(op_ret), CST(p)
|
||||
C_rmi(p) | arith p; | OP(op_rmi), CST(p)
|
||||
C_rmu(p) | arith p; | OP(op_rmu), CST(p)
|
||||
C_sbf(p) | arith p; | OP(op_sbf), CST(p)
|
||||
C_sbi(p) | arith p; | OP(op_sbi), CST(p)
|
||||
C_sbs(p) | arith p; | OP(op_sbs), CST(p)
|
||||
C_sbu(p) | arith p; | OP(op_sbu), CST(p)
|
||||
C_sde_dnam(p, o) | char *p; arith o; | OP(op_sde), NOFF(p, o)
|
||||
C_sde_dlb(l, o) | label l; arith o; | OP(op_sde), DOFF(l, o)
|
||||
C_sdl(p) | arith p; | OP(op_sdl), CST(p)
|
||||
C_sli(p) | arith p; | OP(op_sli), CST(p)
|
||||
C_slu(p) | arith p; | OP(op_slu), CST(p)
|
||||
C_sri(p) | arith p; | OP(op_sri), CST(p)
|
||||
C_sru(p) | arith p; | OP(op_sru), CST(p)
|
||||
C_ste_dnam(p, o) | char *p; arith o; | OP(op_ste), NOFF(p, o)
|
||||
C_ste_dlb(l, o) | label l; arith o; | OP(op_ste), DOFF(l, o)
|
||||
C_sti(p) | arith p; | OP(op_sti), CST(p)
|
||||
C_stl(p) | arith p; | OP(op_stl), CST(p)
|
||||
C_xor(p) | arith p; | OP(op_xor), CST(p)
|
||||
C_zeq(l) | label l; | OP(op_zeq), CST((arith)l)
|
||||
C_zge(l) | label l; | OP(op_zge), CST((arith)l)
|
||||
C_zgt(l) | label l; | OP(op_zgt), CST((arith)l)
|
||||
C_zle(l) | label l; | OP(op_zle), CST((arith)l)
|
||||
C_zlt(l) | label l; | OP(op_zlt), CST((arith)l)
|
||||
C_zne(l) | label l; | OP(op_zne), CST((arith)l)
|
||||
%
|
||||
C_df_dlb(l) | label l; | DLB(l)
|
||||
C_df_dnam(s) | char *s; | DNAM(s)
|
||||
C_df_ilb(l) | label l; | ILB(l)
|
||||
%
|
||||
C_bss_cst(n, w, i) | arith n, w; int i; |
|
||||
PS(ps_bss), DCST(n), CST(w), CST((arith)i)
|
||||
%
|
||||
C_con_icon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_con), WCON(sp_icon, val, siz), CEND()
|
||||
C_con_ucon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_con), WCON(sp_ucon, val, siz), CEND()
|
||||
C_con_fcon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_con), WCON(sp_fcon, val, siz), CEND()
|
||||
C_con_scon(str, siz) | char *str; arith siz; | PS(ps_con), CSTR(str), CEND()
|
||||
C_con_dnam(str, val) | char *str; arith val; |
|
||||
PS(ps_con), NOFF(str, val), CEND()
|
||||
C_con_dlb(l, val) | label l; arith val; |
|
||||
PS(ps_con), DOFF(l, val), CEND()
|
||||
C_con_pnam(str) | char *str; | PS(ps_con), PNAM(str), CEND()
|
||||
%
|
||||
C_rom_cst(l) | arith l; | PS(ps_rom), CST(l), CEND()
|
||||
C_rom_icon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_rom), WCON(sp_icon, val, siz), CEND()
|
||||
C_rom_fcon(val, siz) | char *val; arith siz; |
|
||||
PS(ps_rom), WCON(sp_fcon, val, siz), CEND()
|
||||
C_rom_ilb(l) | label l; | PS(ps_rom), ILB(l), CEND()
|
||||
%
|
||||
C_cst(l) | arith l; | CST(l)
|
||||
C_icon(val, siz) | char *val; arith siz; | WCON(sp_icon, val, siz)
|
||||
C_ucon(val, siz) | char *val; arith siz; | WCON(sp_ucon, val, siz)
|
||||
C_fcon(val, siz) | char *val; arith siz; | WCON(sp_fcon, val, siz)
|
||||
C_scon(str, siz) | char *str; arith siz; | CSTR(str)
|
||||
C_dnam(str, val) | char *str; arith val; | NOFF(str, val)
|
||||
C_dlb(l, val) | label l; arith val; | DOFF(l, val)
|
||||
C_pnam(str) | char *str; | PNAM(str)
|
||||
C_ilb(l) | label l; | ILB(l)
|
||||
%
|
||||
C_pro_narg(p1) | char *p1; | PS(ps_pro), PNAM(p1), CEND()
|
||||
C_end(l) | arith l; | PS(ps_end), CST(l)
|
||||
%
|
||||
C_exa(s) | char *s; | PS(ps_exa), DNAM(s)
|
||||
C_exp(s) | char *s; | PS(ps_exp), PNAM(s)
|
||||
C_ina_pt(l) | label l; | PS(ps_ina), DLB(l)
|
||||
C_ina(s) | char *s; | PS(ps_ina), DNAM(s)
|
||||
C_inp(s) | char *s; | PS(ps_inp), PNAM(s)
|
||||
%
|
||||
C_ms_err() | | PS(ps_mes), CST((arith)ms_err), CEND()
|
||||
C_ms_emx(p1, p2) | arith p1, p2; |
|
||||
PS(ps_mes), CST((arith)ms_emx), CST(p1), CST(p2), CEND()
|
||||
C_ms_reg(a, b, c, d) | arith a, b; int c, d; |
|
||||
PS(ps_mes), CST((arith)ms_reg), CST(a), CST(b), CST((arith)c), CST((arith)d), CEND()
|
||||
C_ms_src(l, s) | arith l; char *s; |
|
||||
PS(ps_mes), CST((arith)ms_src), CST(l), CSTR(s), CEND()
|
||||
C_ms_flt() | | PS(ps_mes), CST((arith)ms_flt), CEND()
|
||||
C_ms_par(l) | arith l; | PS(ps_mes), CST((arith)ms_par), CST(l), CEND()
|
||||
C_ms_gto() | | PS(ps_mes), CST((arith)ms_gto), CEND()
|
||||
214
lang/cem/cemcom/error.c
Normal file
214
lang/cem/cemcom/error.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* 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 */
|
||||
|
||||
#include <system.h>
|
||||
#include <em.h>
|
||||
|
||||
#include "nopp.h"
|
||||
#include "errout.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "tokenname.h"
|
||||
#include "arith.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "LLlex.h"
|
||||
|
||||
/* This file contains the (non-portable) error-message and diagnostic
|
||||
functions. Beware, they are called with a variable number of
|
||||
arguments!
|
||||
*/
|
||||
|
||||
/* error classes */
|
||||
#define ERROR 1
|
||||
#define WARNING 2
|
||||
#define LEXERROR 3
|
||||
#define LEXWARNING 4
|
||||
#define CRASH 5
|
||||
#define FATAL 6
|
||||
|
||||
int err_occurred = 0;
|
||||
|
||||
extern char *symbol2str();
|
||||
extern char options[];
|
||||
|
||||
/* There are three general error-message functions:
|
||||
lexerror() lexical and pre-processor error messages
|
||||
error() syntactic and semantic error messages
|
||||
expr_error() errors in expressions
|
||||
The difference lies in the place where the file name and line
|
||||
number come from.
|
||||
Lexical errors report from the global variables LineNumber and
|
||||
FileName, expression errors get their information from the
|
||||
expression, whereas other errors use the information in the token.
|
||||
*/
|
||||
|
||||
/*VARARGS1*/
|
||||
error(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(ERROR, NILEXPR, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS2*/
|
||||
expr_error(expr, fmt, args)
|
||||
struct expr *expr;
|
||||
char *fmt;
|
||||
{
|
||||
if (expr->ex_flags & EX_ERROR)
|
||||
return; /* to prevent proliferation */
|
||||
_error(ERROR, expr, fmt, &args);
|
||||
expr->ex_flags |= EX_ERROR;
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
warning(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(WARNING, NILEXPR, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS2*/
|
||||
expr_warning(expr, fmt, args)
|
||||
struct expr *expr;
|
||||
char *fmt;
|
||||
{
|
||||
if (expr->ex_flags & EX_ERROR)
|
||||
return; /* to prevent proliferation */
|
||||
_error(WARNING, expr, fmt, &args);
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
lexerror(fmt, args)
|
||||
char *fmt;
|
||||
{
|
||||
_error(LEXERROR, NILEXPR, fmt, &args);
|
||||
}
|
||||
|
||||
#ifndef NOPP
|
||||
/*VARARGS1*/
|
||||
lexwarning(fmt, args) char *fmt; {
|
||||
_error(LEXWARNING, NILEXPR, fmt, &args);
|
||||
}
|
||||
#endif NOPP
|
||||
|
||||
/*VARARGS1*/
|
||||
crash(fmt, args)
|
||||
char *fmt;
|
||||
int args;
|
||||
{
|
||||
_error(CRASH, NILEXPR, fmt, &args);
|
||||
C_close();
|
||||
#ifdef DEBUG
|
||||
sys_stop(S_ABORT);
|
||||
#else DEBUG
|
||||
sys_stop(S_EXIT);
|
||||
#endif DEBUG
|
||||
}
|
||||
|
||||
/*VARARGS1*/
|
||||
fatal(fmt, args)
|
||||
char *fmt;
|
||||
int args;
|
||||
{
|
||||
if (C_busy()) C_close();
|
||||
_error(FATAL, NILEXPR, fmt, &args);
|
||||
sys_stop(S_EXIT);
|
||||
}
|
||||
|
||||
_error(class, expr, fmt, argv)
|
||||
int class;
|
||||
struct expr *expr;
|
||||
char *fmt;
|
||||
int argv[];
|
||||
{
|
||||
/* _error attempts to limit the number of error messages
|
||||
for a given line to MAXERR_LINE.
|
||||
*/
|
||||
static char *last_fn = 0;
|
||||
static unsigned int last_ln = 0;
|
||||
static int e_seen = 0;
|
||||
char *fn = 0;
|
||||
unsigned int ln = 0;
|
||||
char *remark = 0;
|
||||
|
||||
/* Since name and number are gathered from different places
|
||||
depending on the class, we first collect the relevant
|
||||
values and then decide what to print.
|
||||
*/
|
||||
/* preliminaries */
|
||||
switch (class) {
|
||||
case ERROR:
|
||||
case LEXERROR:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
if (C_busy())
|
||||
C_ms_err();
|
||||
err_occurred = 1;
|
||||
break;
|
||||
|
||||
case WARNING:
|
||||
case LEXWARNING:
|
||||
if (options['w'])
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
/* the remark */
|
||||
switch (class) {
|
||||
case WARNING:
|
||||
case LEXWARNING:
|
||||
remark = "(warning)";
|
||||
break;
|
||||
case CRASH:
|
||||
remark = "CRASH\007";
|
||||
break;
|
||||
case FATAL:
|
||||
remark = "fatal error --";
|
||||
break;
|
||||
}
|
||||
|
||||
/* the place */
|
||||
switch (class) {
|
||||
case WARNING:
|
||||
case ERROR:
|
||||
fn = expr ? expr->ex_file : dot.tk_file;
|
||||
ln = expr ? expr->ex_line : dot.tk_line;
|
||||
break;
|
||||
case LEXWARNING:
|
||||
case LEXERROR:
|
||||
case CRASH:
|
||||
case FATAL:
|
||||
fn = FileName;
|
||||
ln = LineNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ln == last_ln && fn && last_fn && strcmp(fn, last_fn) == 0) {
|
||||
/* we've seen this place before */
|
||||
e_seen++;
|
||||
if (e_seen == MAXERR_LINE)
|
||||
fmt = "etc ...";
|
||||
else
|
||||
if (e_seen > MAXERR_LINE)
|
||||
/* and too often, I'd say ! */
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* brand new place */
|
||||
last_fn = fn;
|
||||
last_ln = ln;
|
||||
e_seen = 0;
|
||||
}
|
||||
|
||||
if (fn)
|
||||
fprint(ERROUT, "\"%s\", line %u: ", fn, ln);
|
||||
if (remark)
|
||||
fprint(ERROUT, "%s ", remark);
|
||||
doprnt(ERROUT, fmt, argv); /* contents of error */
|
||||
fprint(ERROUT, "\n");
|
||||
}
|
||||
21
lang/cem/cemcom/estack.str
Normal file
21
lang/cem/cemcom/estack.str
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* EXPRESSION STACK */
|
||||
/* Used for global initializations */
|
||||
struct e_stack {
|
||||
struct e_stack *next;
|
||||
arith s_cnt1, s_cnt2;
|
||||
struct sdef *s_def;
|
||||
struct type **s_tpp;
|
||||
char s_nested;
|
||||
};
|
||||
|
||||
/* ALLOCDEF "e_stack" 5 */
|
||||
|
||||
#define bytes_upto_here s_cnt1
|
||||
#define last_offset s_cnt2
|
||||
#define elem_count s_cnt1
|
||||
#define nelem s_cnt2
|
||||
945
lang/cem/cemcom/eval.c
Normal file
945
lang/cem/cemcom/eval.c
Normal file
@@ -0,0 +1,945 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* EXPRESSION-CODE GENERATOR */
|
||||
|
||||
#include "nofloat.h"
|
||||
#include <em.h>
|
||||
#include <em_reg.h>
|
||||
#include "debug.h"
|
||||
#include "nobitfield.h"
|
||||
#include "dataflow.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "label.h"
|
||||
#include "code.h"
|
||||
#include "assert.h"
|
||||
#include "def.h"
|
||||
#include "expr.h"
|
||||
#include "sizes.h"
|
||||
#include "Lpars.h"
|
||||
#include "level.h"
|
||||
#include "stack.h"
|
||||
#include "align.h"
|
||||
#include "mes.h"
|
||||
#include "atw.h"
|
||||
|
||||
#define CRASH() crash("EVAL: CRASH at line %u", __LINE__)
|
||||
#define toword(n) ((n) < word_size ? word_size : (n))
|
||||
|
||||
char *symbol2str();
|
||||
char *long2str();
|
||||
arith NewLocal(); /* util.c */
|
||||
#define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, 0)
|
||||
|
||||
/* EVAL() is the main expression-tree evaluator, which turns
|
||||
any legal expression tree into EM code. Parameters:
|
||||
|
||||
struct expr *expr
|
||||
pointer to root of the expression tree to be evaluated
|
||||
|
||||
int val
|
||||
indicates whether the resulting expression is to be
|
||||
dereferenced (if val == RVAL and expr->ex_lvalue == 1)
|
||||
or not (val == LVAL). The latter case indicates that
|
||||
the resulting expression is an lvalue expression which
|
||||
should not be dereferenced by EVAL
|
||||
|
||||
int code
|
||||
indicates whether the expression tree must be turned
|
||||
into EM code or not. E.g. the expression statement "12;"
|
||||
delivers the expression "12" to EVAL while this should
|
||||
not result in any EM code
|
||||
|
||||
label false_label, label true_label
|
||||
if the expression is a logical or relational expression
|
||||
and if the loop of the program depends on the resulting
|
||||
value then EVAL generates jumps to the specified program
|
||||
labels, in case they are specified (i.e. are non-zero)
|
||||
*/
|
||||
|
||||
EVAL(expr, val, code, true_label, false_label)
|
||||
register struct expr *expr;
|
||||
int val, code;
|
||||
label true_label, false_label;
|
||||
{
|
||||
register int gencode = (code == TRUE);
|
||||
|
||||
switch (expr->ex_class) {
|
||||
case Value: /* just a simple value */
|
||||
if (gencode)
|
||||
load_val(expr, val);
|
||||
break;
|
||||
case String: /* a string constant */
|
||||
if (gencode) {
|
||||
string2pointer(expr);
|
||||
C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
|
||||
}
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case Float: /* a floating constant */
|
||||
if (gencode) {
|
||||
label datlab = data_label();
|
||||
|
||||
C_df_dlb(datlab);
|
||||
C_rom_fcon(expr->FL_VALUE, expr->ex_type->tp_size);
|
||||
C_lae_dlb(datlab, (arith)0);
|
||||
C_loi(expr->ex_type->tp_size);
|
||||
}
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
case Oper: /* compound expression */
|
||||
{
|
||||
int oper = expr->OP_OPER;
|
||||
register struct expr *left = expr->OP_LEFT;
|
||||
register struct expr *right = expr->OP_RIGHT;
|
||||
register struct type *tp = expr->OP_TYPE;
|
||||
|
||||
if (tp->tp_fund == ERRONEOUS || (expr->ex_flags & EX_ERROR)) {
|
||||
/* stop immediately */
|
||||
break;
|
||||
}
|
||||
if (tp->tp_fund == VOID)
|
||||
gencode = 0;
|
||||
switch (oper) {
|
||||
case '+':
|
||||
/* We have the following possibilities :
|
||||
int + int, pointer + int, pointer + long,
|
||||
long + long, double + double
|
||||
*/
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
if (tp->tp_unsigned)
|
||||
C_adu(tp->tp_size);
|
||||
else
|
||||
C_adi(tp->tp_size);
|
||||
break;
|
||||
case POINTER:
|
||||
C_ads(right->ex_type->tp_size);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case DOUBLE:
|
||||
C_adf(tp->tp_size);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
default:
|
||||
crash("bad type +");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
if (left == 0) { /* unary */
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
case POINTER:
|
||||
C_ngi(tp->tp_size);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case DOUBLE:
|
||||
C_ngf(tp->tp_size);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
default:
|
||||
CRASH();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* else binary; we have the following flavours:
|
||||
int - int, pointer - int, pointer - long,
|
||||
pointer - pointer, long - long, double - double
|
||||
*/
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (!gencode)
|
||||
break;
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
if (tp->tp_unsigned)
|
||||
C_sbu(tp->tp_size);
|
||||
else
|
||||
C_sbi(tp->tp_size);
|
||||
break;
|
||||
case POINTER:
|
||||
if (right->ex_type->tp_fund == POINTER)
|
||||
C_sbs(pointer_size);
|
||||
else {
|
||||
C_ngi(right->ex_type->tp_size);
|
||||
C_ads(right->ex_type->tp_size);
|
||||
}
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case DOUBLE:
|
||||
C_sbf(tp->tp_size);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
default:
|
||||
crash("bad type -");
|
||||
}
|
||||
break;
|
||||
case '*':
|
||||
if (left == 0) /* unary */
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
else { /* binary */
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
case POINTER:
|
||||
if (tp->tp_unsigned)
|
||||
C_mlu(tp->tp_size);
|
||||
else
|
||||
C_mli(tp->tp_size);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case DOUBLE:
|
||||
C_mlf(double_size);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
default:
|
||||
crash("bad type *");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
case POINTER:
|
||||
if (tp->tp_unsigned)
|
||||
C_dvu(tp->tp_size);
|
||||
else
|
||||
C_dvi(tp->tp_size);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case DOUBLE:
|
||||
C_dvf(double_size);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
default:
|
||||
crash("bad type /");
|
||||
}
|
||||
break;
|
||||
case '%':
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG);
|
||||
if (gencode)
|
||||
if (tp->tp_unsigned)
|
||||
C_rmu(tp->tp_size);
|
||||
else
|
||||
C_rmi(tp->tp_size);
|
||||
break;
|
||||
case LEFT:
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
if (tp->tp_unsigned)
|
||||
C_slu(tp->tp_size);
|
||||
else
|
||||
C_sli(tp->tp_size);
|
||||
break;
|
||||
case RIGHT:
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
if (tp->tp_unsigned)
|
||||
C_sru(tp->tp_size);
|
||||
else
|
||||
C_sri(tp->tp_size);
|
||||
break;
|
||||
case '<':
|
||||
case LESSEQ:
|
||||
case '>':
|
||||
case GREATEREQ:
|
||||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
/* The operands have the same type */
|
||||
arith size = left->ex_type->tp_size;
|
||||
|
||||
switch (tp->tp_fund) {
|
||||
case INT:
|
||||
case LONG:
|
||||
if (left->ex_type->tp_unsigned)
|
||||
C_cmu(size);
|
||||
else
|
||||
C_cmi(size);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT: /* thought they were converted??? */
|
||||
case DOUBLE:
|
||||
C_cmf(size);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
case POINTER:
|
||||
C_cmp();
|
||||
break;
|
||||
case ENUM:
|
||||
C_cmi(size);
|
||||
break;
|
||||
default:
|
||||
CRASH();
|
||||
}
|
||||
if (true_label != 0) {
|
||||
compare(oper, true_label);
|
||||
C_bra(false_label);
|
||||
}
|
||||
else {
|
||||
truthvalue(oper);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '&':
|
||||
case '|':
|
||||
case '^':
|
||||
/* both operands should have type int */
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
arith size = tp->tp_size;
|
||||
|
||||
if (size < word_size)
|
||||
size = word_size;
|
||||
switch (oper) {
|
||||
case '&':
|
||||
C_and(size);
|
||||
break;
|
||||
case '|':
|
||||
C_ior(size);
|
||||
break;
|
||||
case '^':
|
||||
C_xor(size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '=': {
|
||||
int newcode = tp->tp_size > 0; /* CJ */
|
||||
#ifndef NOBITFIELD
|
||||
if (left->ex_type->tp_fund == FIELD) {
|
||||
eval_field(expr, gencode);
|
||||
break;
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
C_dup(ATW(tp->tp_size));
|
||||
if (left->ex_class != Value) {
|
||||
EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
|
||||
if (newcode)
|
||||
store_block(tp->tp_size, tp->tp_align);
|
||||
}
|
||||
else if (newcode)
|
||||
store_val(&(left->ex_object.ex_value),
|
||||
left->ex_type);
|
||||
}
|
||||
break;
|
||||
case PLUSAB:
|
||||
case MINAB:
|
||||
case TIMESAB:
|
||||
case DIVAB:
|
||||
case MODAB:
|
||||
case LEFTAB:
|
||||
case RIGHTAB:
|
||||
case ANDAB:
|
||||
case XORAB:
|
||||
case ORAB:
|
||||
case POSTINCR:
|
||||
case POSTDECR:
|
||||
case PLUSPLUS:
|
||||
case MINMIN:
|
||||
{
|
||||
arith tmp;
|
||||
int compl; /* Complexity of left operand */
|
||||
int newcode = left->ex_type->tp_size > 0; /* CJ */
|
||||
#ifndef NOBITFIELD
|
||||
if (left->ex_type->tp_fund == FIELD) {
|
||||
eval_field(expr, gencode);
|
||||
break;
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
if (newcode && left->ex_class == Value) {
|
||||
compl = 0; /* Value */
|
||||
load_val(left, RVAL);
|
||||
}
|
||||
else
|
||||
if (left->ex_depth == 1 &&
|
||||
!(left->ex_flags & EX_SIDEEFFECTS)) {
|
||||
compl = 1;
|
||||
EVAL(left, RVAL, newcode, NO_LABEL, NO_LABEL);
|
||||
}
|
||||
else {
|
||||
compl = 2; /* otherwise */
|
||||
EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
|
||||
if (newcode) {
|
||||
tmp = LocalPtrVar();
|
||||
C_dup(pointer_size);
|
||||
StoreLocal(tmp, pointer_size);
|
||||
C_loi(left->ex_type->tp_size);
|
||||
}
|
||||
}
|
||||
if (newcode) {
|
||||
if (gencode && (oper == POSTINCR ||
|
||||
oper == POSTDECR))
|
||||
C_dup(ATW(left->ex_type->tp_size));
|
||||
conversion(left->ex_type, tp);
|
||||
}
|
||||
EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
|
||||
if (newcode) {
|
||||
int dupval = gencode && oper != POSTINCR &&
|
||||
oper != POSTDECR;
|
||||
assop(tp, oper);
|
||||
conversion(tp, left->ex_type);
|
||||
if (compl == 0) {
|
||||
store_val(&(left->ex_object.ex_value),
|
||||
left->ex_type);
|
||||
if (dupval) load_val(left, RVAL);
|
||||
}
|
||||
else if (compl == 1) {
|
||||
EVAL(left, LVAL,1, NO_LABEL, NO_LABEL);
|
||||
C_sti(left->ex_type->tp_size);
|
||||
if (dupval) {
|
||||
EVAL(left, LVAL, 1, NO_LABEL,
|
||||
NO_LABEL);
|
||||
C_loi(left->ex_type->tp_size);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LoadLocal(tmp, pointer_size);
|
||||
C_sti(left->ex_type->tp_size);
|
||||
if (dupval) {
|
||||
LoadLocal(tmp, pointer_size);
|
||||
C_loi(left->ex_type->tp_size);
|
||||
}
|
||||
FreeLocal(tmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '(':
|
||||
{
|
||||
register struct expr *ex;
|
||||
arith ParSize = (arith)0;
|
||||
|
||||
if ((ex = right) != NILEXPR) {
|
||||
/* function call with parameters*/
|
||||
while ( ex->ex_class == Oper &&
|
||||
ex->OP_OPER == PARCOMMA
|
||||
) {
|
||||
EVAL(ex->OP_RIGHT, RVAL,
|
||||
ex->ex_type->tp_size > 0,
|
||||
NO_LABEL, NO_LABEL);
|
||||
ParSize += ATW(ex->ex_type->tp_size);
|
||||
ex = ex->OP_LEFT;
|
||||
}
|
||||
EVAL(ex, RVAL, ex->ex_type->tp_size > 0,
|
||||
NO_LABEL, NO_LABEL);
|
||||
ParSize += ATW(ex->ex_type->tp_size);
|
||||
}
|
||||
if (left->ex_class == Value && left->VL_CLASS == Name) {
|
||||
/* e.g., main() { (*((int (*)())0))(); } */
|
||||
C_cal(left->VL_IDF->id_text);
|
||||
#ifdef DATAFLOW
|
||||
{ extern char options[];
|
||||
if (options['d'])
|
||||
DfaCallFunction(
|
||||
left->VL_IDF->id_text);
|
||||
}
|
||||
#endif DATAFLOW
|
||||
}
|
||||
else {
|
||||
EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_cai();
|
||||
}
|
||||
/* remove parameters from stack */
|
||||
if (ParSize > (arith)0)
|
||||
C_asp(ParSize);
|
||||
if (gencode) {
|
||||
if (is_struct_or_union(tp->tp_fund)) {
|
||||
C_lfr(pointer_size);
|
||||
load_block(tp->tp_size, word_align);
|
||||
}
|
||||
else
|
||||
C_lfr(ATW(tp->tp_size));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '.':
|
||||
EVAL(left, LVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
ASSERT(is_cp_cst(right));
|
||||
if (gencode)
|
||||
C_adp(right->VL_VALUE);
|
||||
break;
|
||||
case ARROW:
|
||||
EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
ASSERT(is_cp_cst(right));
|
||||
if (gencode)
|
||||
C_adp(right->VL_VALUE);
|
||||
break;
|
||||
case ',':
|
||||
EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL);
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
break;
|
||||
case '~':
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
C_com(tp->tp_size);
|
||||
break;
|
||||
case '?': /* must be followed by ':' */
|
||||
{
|
||||
label l_true = text_label();
|
||||
label l_false = text_label();
|
||||
label l_end = text_label();
|
||||
|
||||
EVAL(left, RVAL, TRUE, l_true, l_false);
|
||||
C_df_ilb(l_true);
|
||||
EVAL(right->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
C_bra(l_end);
|
||||
C_df_ilb(l_false);
|
||||
EVAL(right->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
C_df_ilb(l_end);
|
||||
break;
|
||||
}
|
||||
case OR:
|
||||
case AND: {
|
||||
label l_false, l_true, l_maybe;
|
||||
|
||||
l_maybe = text_label();
|
||||
if (true_label) {
|
||||
l_false = false_label;
|
||||
l_true = true_label;
|
||||
}
|
||||
else {
|
||||
l_false = text_label();
|
||||
l_true = gencode ? text_label(): l_false;
|
||||
}
|
||||
|
||||
EVAL(left, RVAL, TRUE, oper == AND ? l_maybe : l_true,
|
||||
oper == AND ? l_false : l_maybe);
|
||||
C_df_ilb(l_maybe);
|
||||
EVAL(right, RVAL, gencode, l_true, l_false);
|
||||
if (gencode && !true_label) {
|
||||
label l_end = text_label();
|
||||
|
||||
C_df_ilb(l_true);
|
||||
C_loc((arith)1);
|
||||
C_bra(l_end);
|
||||
C_df_ilb(l_false);
|
||||
C_loc((arith)0);
|
||||
C_df_ilb(l_end);
|
||||
}
|
||||
else {
|
||||
if (! true_label) C_df_ilb(l_false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '!':
|
||||
if (true_label == 0) {
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode) {
|
||||
C_teq();
|
||||
}
|
||||
}
|
||||
else
|
||||
EVAL(right, RVAL, gencode, false_label,
|
||||
true_label);
|
||||
break;
|
||||
case INT2INT:
|
||||
#ifndef NOFLOAT
|
||||
case INT2FLOAT:
|
||||
case FLOAT2INT:
|
||||
case FLOAT2FLOAT:
|
||||
#endif NOFLOAT
|
||||
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
|
||||
if (gencode)
|
||||
conversion(right->ex_type, left->ex_type);
|
||||
break;
|
||||
default:
|
||||
crash("(EVAL) bad operator %s\n", symbol2str(oper));
|
||||
}
|
||||
/* If the rvalue of the expression is required but
|
||||
only its lvalue is evaluated, its rvalue is
|
||||
loaded by the following statements:
|
||||
*/
|
||||
if (gencode && val == RVAL && expr->ex_lvalue == 1)
|
||||
load_block(expr->ex_type->tp_size,
|
||||
expr->ex_type->tp_align);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
crash("(EVAL) bad expression class");
|
||||
}
|
||||
}
|
||||
|
||||
/* compare() serves as an auxiliary function of EVAL */
|
||||
compare(relop, lbl)
|
||||
int relop;
|
||||
label lbl;
|
||||
{
|
||||
switch (relop) {
|
||||
case '<':
|
||||
C_zlt(lbl);
|
||||
break;
|
||||
case LESSEQ:
|
||||
C_zle(lbl);
|
||||
break;
|
||||
case '>':
|
||||
C_zgt(lbl);
|
||||
break;
|
||||
case GREATEREQ:
|
||||
C_zge(lbl);
|
||||
break;
|
||||
case EQUAL:
|
||||
C_zeq(lbl);
|
||||
break;
|
||||
case NOTEQUAL:
|
||||
C_zne(lbl);
|
||||
break;
|
||||
default:
|
||||
CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
/* truthvalue() serves as an auxiliary function of EVAL */
|
||||
truthvalue(relop)
|
||||
int relop;
|
||||
{
|
||||
switch (relop) {
|
||||
case '<':
|
||||
C_tlt();
|
||||
break;
|
||||
case LESSEQ:
|
||||
C_tle();
|
||||
break;
|
||||
case '>':
|
||||
C_tgt();
|
||||
break;
|
||||
case GREATEREQ:
|
||||
C_tge();
|
||||
break;
|
||||
case EQUAL:
|
||||
C_teq();
|
||||
break;
|
||||
case NOTEQUAL:
|
||||
C_tne();
|
||||
break;
|
||||
default:
|
||||
CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* assop() generates the opcode of an assignment operators op= */
|
||||
assop(type, oper)
|
||||
register struct type *type;
|
||||
int oper;
|
||||
{
|
||||
register arith size;
|
||||
register uns = type->tp_unsigned;
|
||||
|
||||
if ((size = type->tp_size) < word_size)
|
||||
size = word_size;
|
||||
switch (type->tp_fund) {
|
||||
case CHAR:
|
||||
case SHORT:
|
||||
case INT:
|
||||
case LONG:
|
||||
case ENUM:
|
||||
switch (oper) {
|
||||
case PLUSAB:
|
||||
case PLUSPLUS:
|
||||
case POSTINCR:
|
||||
if (uns)
|
||||
C_adu(size);
|
||||
else
|
||||
C_adi(size);
|
||||
break;
|
||||
case MINAB:
|
||||
case MINMIN:
|
||||
case POSTDECR:
|
||||
if (uns)
|
||||
C_sbu(size);
|
||||
else
|
||||
C_sbi(size);
|
||||
break;
|
||||
case TIMESAB:
|
||||
if (uns)
|
||||
C_mlu(size);
|
||||
else
|
||||
C_mli(size);
|
||||
break;
|
||||
case DIVAB:
|
||||
if (uns)
|
||||
C_dvu(size);
|
||||
else
|
||||
C_dvi(size);
|
||||
break;
|
||||
case MODAB:
|
||||
if (uns)
|
||||
C_rmu(size);
|
||||
else
|
||||
C_rmi(size);
|
||||
break;
|
||||
case LEFTAB:
|
||||
if (uns)
|
||||
C_slu(size);
|
||||
else
|
||||
C_sli(size);
|
||||
break;
|
||||
case RIGHTAB:
|
||||
if (uns)
|
||||
C_sru(size);
|
||||
else
|
||||
C_sri(size);
|
||||
break;
|
||||
case ANDAB:
|
||||
C_and(size);
|
||||
break;
|
||||
case XORAB:
|
||||
C_xor(size);
|
||||
break;
|
||||
case ORAB:
|
||||
C_ior(size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
switch (oper) {
|
||||
case PLUSAB:
|
||||
case PLUSPLUS:
|
||||
case POSTINCR:
|
||||
C_adf(size);
|
||||
break;
|
||||
case MINAB:
|
||||
case MINMIN:
|
||||
case POSTDECR:
|
||||
C_sbf(size);
|
||||
break;
|
||||
case TIMESAB:
|
||||
C_mlf(size);
|
||||
break;
|
||||
case DIVAB:
|
||||
C_dvf(size);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
case POINTER:
|
||||
if (oper == MINAB || oper == MINMIN || oper == POSTDECR)
|
||||
C_ngi(size);
|
||||
C_ads(size);
|
||||
break;
|
||||
case ERRONEOUS:
|
||||
break;
|
||||
default:
|
||||
crash("(assop) bad type %s\n", symbol2str(type->tp_fund));
|
||||
}
|
||||
}
|
||||
|
||||
/* store_val() generates code for a store operation.
|
||||
There are four ways of storing data:
|
||||
- into a global variable
|
||||
- into an automatic local variable
|
||||
- into a local static variable
|
||||
- absolute addressing
|
||||
*/
|
||||
store_val(vl, tp)
|
||||
register struct value *vl;
|
||||
struct type *tp;
|
||||
{
|
||||
arith size = tp->tp_size;
|
||||
int tpalign = tp->tp_align;
|
||||
int al_on_word;
|
||||
register int inword;
|
||||
register int indword;
|
||||
arith val = vl->vl_value;
|
||||
|
||||
if (vl->vl_class == Const) { /* absolute addressing */
|
||||
load_cst(val, pointer_size);
|
||||
store_block(size, tpalign);
|
||||
return;
|
||||
}
|
||||
al_on_word = (tpalign % word_align == 0);
|
||||
if (!(inword = (size == word_size && al_on_word)))
|
||||
indword = (size == dword_size && al_on_word);
|
||||
if (vl->vl_class == Name) {
|
||||
register struct idf *id = vl->vl_data.vl_idf;
|
||||
register struct def *df = id->id_def;
|
||||
|
||||
if (df->df_level == L_GLOBAL) {
|
||||
if (inword)
|
||||
C_ste_dnam(id->id_text, val);
|
||||
else
|
||||
if (indword)
|
||||
C_sde_dnam(id->id_text, val);
|
||||
else {
|
||||
C_lae_dnam(id->id_text, val);
|
||||
store_block(size, tpalign);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(df->df_sc != STATIC);
|
||||
if (inword || indword)
|
||||
StoreLocal(df->df_address + val, size);
|
||||
else {
|
||||
AddrLocal(df->df_address + val);
|
||||
store_block(size, tpalign);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
label dlb = vl->vl_data.vl_lbl;
|
||||
|
||||
ASSERT(vl->vl_class == Label);
|
||||
if (inword)
|
||||
C_ste_dlb(dlb, val);
|
||||
else
|
||||
if (indword)
|
||||
C_sde_dlb(dlb, val);
|
||||
else {
|
||||
C_lae_dlb(dlb, val);
|
||||
store_block(size, tpalign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* load_val() generates code for stacking a certain value (from ex),
|
||||
which can be obtained in one of the following ways:
|
||||
- value from absolute addressed memory
|
||||
- constant value
|
||||
- function result
|
||||
- global variable
|
||||
- static variable
|
||||
- local variable
|
||||
*/
|
||||
load_val(expr, rlval)
|
||||
register struct expr *expr; /* expression containing the value */
|
||||
int rlval; /* generate either LVAL or RVAL */
|
||||
{
|
||||
register struct type *tp = expr->ex_type;
|
||||
int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
|
||||
arith size = tp->tp_size;
|
||||
int tpalign = tp->tp_align;
|
||||
int al_on_word;
|
||||
register int inword, indword;
|
||||
register arith val = expr->VL_VALUE;
|
||||
|
||||
if (expr->VL_CLASS == Const) {
|
||||
if (rvalue) { /* absolute addressing */
|
||||
load_cst(val, pointer_size);
|
||||
load_block(size, tpalign);
|
||||
}
|
||||
else /* integer, unsigned, long, enum etc */
|
||||
load_cst(val, size);
|
||||
return;
|
||||
}
|
||||
if (rvalue) {
|
||||
al_on_word = (tpalign % word_align == 0);
|
||||
if (!(inword = (size == word_size && al_on_word)))
|
||||
indword = (size == dword_size && al_on_word);
|
||||
}
|
||||
if (expr->VL_CLASS == Label) {
|
||||
if (rvalue) {
|
||||
if (inword)
|
||||
C_loe_dlb(expr->VL_LBL, val);
|
||||
else
|
||||
if (indword)
|
||||
C_lde_dlb(expr->VL_LBL, val);
|
||||
else {
|
||||
C_lae_dlb(expr->VL_LBL, val);
|
||||
load_block(size, tpalign);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
C_lae_dlb(expr->VL_LBL, (arith)0);
|
||||
C_adp(val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
register struct idf *id = expr->VL_IDF;
|
||||
register struct def *df;
|
||||
|
||||
ASSERT(expr->VL_CLASS == Name);
|
||||
if ((df = id->id_def)->df_type->tp_fund == FUNCTION)
|
||||
/* the previous statement tried to catch a function
|
||||
identifier, which may be cast to a pointer to a
|
||||
function.
|
||||
ASSERT(!(rvalue)); ???
|
||||
*/
|
||||
C_lpi(id->id_text);
|
||||
else
|
||||
if (df->df_level == L_GLOBAL) {
|
||||
if (rvalue) {
|
||||
if (inword)
|
||||
C_loe_dnam(id->id_text, val);
|
||||
else
|
||||
if (indword)
|
||||
C_lde_dnam(id->id_text, val);
|
||||
else {
|
||||
C_lae_dnam(id->id_text, val);
|
||||
load_block(size, tpalign);
|
||||
}
|
||||
}
|
||||
else {
|
||||
C_lae_dnam(id->id_text, (arith)0);
|
||||
C_adp(val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(df->df_sc != STATIC);
|
||||
if (rvalue) {
|
||||
if (inword || indword)
|
||||
LoadLocal(df->df_address + val, size);
|
||||
else {
|
||||
AddrLocal(df->df_address + val);
|
||||
load_block(size, tpalign);
|
||||
}
|
||||
}
|
||||
else {
|
||||
AddrLocal(df->df_address);
|
||||
C_adp(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
load_cst(val, siz)
|
||||
arith val, siz;
|
||||
{
|
||||
if (siz <= word_size)
|
||||
C_loc(val);
|
||||
else
|
||||
if (siz == dword_size)
|
||||
C_ldc(val);
|
||||
else {
|
||||
label datlab;
|
||||
|
||||
C_df_dlb(datlab = data_label());
|
||||
C_rom_icon(long2str((long)val, 10), siz);
|
||||
C_lae_dlb(datlab, (arith)0);
|
||||
C_loi(siz);
|
||||
}
|
||||
}
|
||||
481
lang/cem/cemcom/expr.c
Normal file
481
lang/cem/cemcom/expr.c
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* EXPRESSION TREE HANDLING */
|
||||
|
||||
#include "nofloat.h"
|
||||
#include "botch_free.h"
|
||||
#include <alloc.h>
|
||||
#include "idf.h"
|
||||
#include "arith.h"
|
||||
#include "def.h"
|
||||
#include "type.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "LLlex.h"
|
||||
#include "Lpars.h"
|
||||
#include "decspecs.h"
|
||||
#include "declar.h"
|
||||
#include "sizes.h"
|
||||
#include "level.h"
|
||||
#include "noRoption.h"
|
||||
|
||||
extern char *symbol2str();
|
||||
extern char options[];
|
||||
|
||||
int
|
||||
rank_of(oper)
|
||||
int oper;
|
||||
{
|
||||
/* The rank of the operator oper is returned.
|
||||
*/
|
||||
switch (oper) {
|
||||
default:
|
||||
return 0; /* INT2INT etc. */
|
||||
case '[':
|
||||
case '(':
|
||||
case '.':
|
||||
case ARROW:
|
||||
case PARCOMMA:
|
||||
return 1;
|
||||
case '!':
|
||||
case PLUSPLUS:
|
||||
case MINMIN:
|
||||
case CAST:
|
||||
case SIZEOF:
|
||||
return 2; /* monadic */
|
||||
case '*':
|
||||
case '/':
|
||||
case '%':
|
||||
return 3;
|
||||
case '+':
|
||||
case '-':
|
||||
return 4;
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
return 5;
|
||||
case '<':
|
||||
case '>':
|
||||
case LESSEQ:
|
||||
case GREATEREQ:
|
||||
return 6;
|
||||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
return 7;
|
||||
case '&':
|
||||
return 8;
|
||||
case '^':
|
||||
return 9;
|
||||
case '|':
|
||||
return 10;
|
||||
case AND:
|
||||
return 11;
|
||||
case OR:
|
||||
return 12;
|
||||
case '?':
|
||||
case ':':
|
||||
return 13;
|
||||
case '=':
|
||||
case PLUSAB:
|
||||
case MINAB:
|
||||
case TIMESAB:
|
||||
case DIVAB:
|
||||
case MODAB:
|
||||
case RIGHTAB:
|
||||
case LEFTAB:
|
||||
case ANDAB:
|
||||
case XORAB:
|
||||
case ORAB:
|
||||
return 14;
|
||||
case ',':
|
||||
return 15;
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
#ifndef NOROPTION
|
||||
int
|
||||
rank_of_expression(ex)
|
||||
register struct expr *ex;
|
||||
{
|
||||
/* Returns the rank of the top node in the expression.
|
||||
*/
|
||||
if (!ex || (ex->ex_flags & EX_PARENS) || ex->ex_class != Oper)
|
||||
return 0;
|
||||
return rank_of(ex->OP_OPER);
|
||||
}
|
||||
|
||||
check_conditional(expr, oper, pos_descr)
|
||||
register struct expr *expr;
|
||||
char *pos_descr;
|
||||
{
|
||||
/* Warn if restricted C is in effect and the expression expr,
|
||||
which occurs at the position pos_descr, is not lighter than
|
||||
the operator oper.
|
||||
*/
|
||||
if (options['R'] && rank_of_expression(expr) >= rank_of(oper))
|
||||
expr_warning(expr, "%s %s is ungrammatical",
|
||||
symbol2str(expr->OP_OPER), pos_descr);
|
||||
}
|
||||
#endif
|
||||
|
||||
dot2expr(expp)
|
||||
struct expr **expp;
|
||||
{
|
||||
/* The token in dot is converted into an expression, a
|
||||
pointer to which is stored in *expp.
|
||||
*/
|
||||
register struct expr *ex = new_expr();
|
||||
|
||||
*expp = ex;
|
||||
ex->ex_file = dot.tk_file;
|
||||
ex->ex_line = dot.tk_line;
|
||||
switch (DOT) {
|
||||
case IDENTIFIER:
|
||||
idf2expr(ex);
|
||||
break;
|
||||
case STRING:
|
||||
string2expr(ex);
|
||||
break;
|
||||
case INTEGER:
|
||||
int2expr(ex);
|
||||
break;
|
||||
#ifndef NOFLOAT
|
||||
case FLOATING:
|
||||
float2expr(ex);
|
||||
break;
|
||||
#endif NOFLOAT
|
||||
default:
|
||||
crash("bad conversion to expression");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
idf2expr(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* Dot contains an identifier which is turned into an
|
||||
expression.
|
||||
Note that this constitutes an applied occurrence of
|
||||
the identifier.
|
||||
*/
|
||||
register struct idf *idf = dot.tk_idf; /* != 0*/
|
||||
register struct def *def = idf->id_def;
|
||||
|
||||
if (def == 0) {
|
||||
if (AHEAD == '(') /* function call, declare name IMPLICITly */
|
||||
add_def(idf, IMPLICIT, funint_type, level); /* RM 13 */
|
||||
else {
|
||||
if (!is_anon_idf(idf))
|
||||
error("%s undefined", idf->id_text);
|
||||
/* declare idf anyway */
|
||||
add_def(idf, 0, error_type, level);
|
||||
}
|
||||
def = idf->id_def;
|
||||
}
|
||||
/* now def != 0 */
|
||||
if (def->df_type->tp_fund == LABEL) {
|
||||
expr_error(expr, "illegal use of label %s", idf->id_text);
|
||||
expr->ex_type = error_type;
|
||||
}
|
||||
else {
|
||||
def->df_used = 1;
|
||||
expr->ex_type = def->df_type;
|
||||
if (expr->ex_type == error_type)
|
||||
expr->ex_flags |= EX_ERROR;
|
||||
}
|
||||
expr->ex_lvalue =
|
||||
( def->df_type->tp_fund == FUNCTION ||
|
||||
def->df_type->tp_fund == ARRAY ||
|
||||
def->df_sc == ENUM
|
||||
) ? 0 : 1;
|
||||
expr->ex_class = Value;
|
||||
if (def->df_sc == ENUM) {
|
||||
expr->VL_CLASS = Const;
|
||||
expr->VL_VALUE = def->df_address;
|
||||
}
|
||||
else
|
||||
if (def->df_sc == STATIC && def->df_level >= L_LOCAL) {
|
||||
expr->VL_CLASS = Label;
|
||||
expr->VL_LBL = def->df_address;
|
||||
expr->VL_VALUE = (arith)0;
|
||||
}
|
||||
else {
|
||||
expr->VL_CLASS = Name;
|
||||
expr->VL_IDF = idf;
|
||||
expr->VL_VALUE = (arith)0;
|
||||
}
|
||||
}
|
||||
|
||||
string2expr(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* Dot contains a string which is turned into an expression.
|
||||
*/
|
||||
expr->ex_type = string_type;
|
||||
expr->ex_lvalue = 0;
|
||||
expr->ex_class = String;
|
||||
expr->SG_VALUE = dot.tk_bts;
|
||||
expr->SG_LEN = dot.tk_len;
|
||||
expr->SG_DATLAB = 0;
|
||||
}
|
||||
|
||||
int2expr(expr)
|
||||
struct expr *expr;
|
||||
{
|
||||
/* Dot contains an integer constant which is turned
|
||||
into an expression.
|
||||
*/
|
||||
fill_int_expr(expr, dot.tk_ival, dot.tk_fund);
|
||||
}
|
||||
|
||||
#ifndef NOFLOAT
|
||||
float2expr(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* Dot contains a floating point constant which is turned
|
||||
into an expression.
|
||||
*/
|
||||
expr->ex_type = double_type;
|
||||
expr->ex_class = Float;
|
||||
expr->FL_VALUE = dot.tk_fval;
|
||||
expr->FL_DATLAB = 0;
|
||||
}
|
||||
#endif NOFLOAT
|
||||
|
||||
struct expr*
|
||||
intexpr(ivalue, fund)
|
||||
arith ivalue;
|
||||
int fund;
|
||||
{
|
||||
/* The value ivalue is turned into an integer expression of
|
||||
the size indicated by fund.
|
||||
*/
|
||||
register struct expr *expr = new_expr();
|
||||
|
||||
expr->ex_file = dot.tk_file;
|
||||
expr->ex_line = dot.tk_line;
|
||||
fill_int_expr(expr, ivalue, fund);
|
||||
return expr;
|
||||
}
|
||||
|
||||
fill_int_expr(ex, ivalue, fund)
|
||||
register struct expr *ex;
|
||||
arith ivalue;
|
||||
int fund;
|
||||
{
|
||||
/* Details derived from ivalue and fund are put into the
|
||||
constant integer expression ex.
|
||||
*/
|
||||
switch (fund) {
|
||||
case INT:
|
||||
ex->ex_type = int_type;
|
||||
break;
|
||||
case LONG:
|
||||
ex->ex_type = long_type;
|
||||
break;
|
||||
case UNSIGNED:
|
||||
/* We cannot make a test like
|
||||
ivalue <= max_unsigned
|
||||
because, if
|
||||
sizeof(long) == int_size
|
||||
holds, max_unsigned may be a negative long in
|
||||
which case the comparison results in an unexpected
|
||||
answer. We assume that the type "unsigned long"
|
||||
is not part of portable C !
|
||||
*/
|
||||
ex->ex_type = (ivalue & ~max_unsigned) ? long_type : uint_type;
|
||||
break;
|
||||
case INTEGER:
|
||||
ex->ex_type = (ivalue <= max_int) ? int_type : long_type;
|
||||
break;
|
||||
default:
|
||||
crash("(intexpr) bad fund %s\n", symbol2str(fund));
|
||||
}
|
||||
ex->ex_class = Value;
|
||||
ex->VL_CLASS = Const;
|
||||
ex->VL_VALUE = ivalue;
|
||||
cut_size(ex);
|
||||
}
|
||||
|
||||
struct expr *
|
||||
new_oper(tp, e1, oper, e2)
|
||||
struct type *tp;
|
||||
register struct expr *e1, *e2;
|
||||
{
|
||||
/* A new expression is constructed which consists of the
|
||||
operator oper which has e1 and e2 as operands; for a
|
||||
monadic operator e1 == NILEXPR.
|
||||
During the construction of the right recursive initialisation
|
||||
tree it is possible for e2 to be NILEXPR.
|
||||
*/
|
||||
register struct expr *expr = new_expr();
|
||||
register struct oper *op;
|
||||
|
||||
if (e2) {
|
||||
register struct expr *e = e2;
|
||||
|
||||
while (e->ex_class == Oper && e->OP_LEFT)
|
||||
e = e->OP_LEFT;
|
||||
expr->ex_file = e->ex_file;
|
||||
expr->ex_line = e->ex_line;
|
||||
}
|
||||
else
|
||||
if (e1) {
|
||||
register struct expr *e = e1;
|
||||
|
||||
while (e->ex_class == Oper && e->OP_RIGHT)
|
||||
e = e->OP_RIGHT;
|
||||
expr->ex_file = e->ex_file;
|
||||
expr->ex_line = e->ex_line;
|
||||
}
|
||||
else {
|
||||
expr->ex_file = dot.tk_file;
|
||||
expr->ex_line = dot.tk_line;
|
||||
}
|
||||
expr->ex_type = tp;
|
||||
expr->ex_class = Oper;
|
||||
/* combine depths and flags of both expressions */
|
||||
if (e2) {
|
||||
int e1_depth = e1 ? e1->ex_depth : 0;
|
||||
int e1_flags = e1 ? e1->ex_flags : 0;
|
||||
|
||||
expr->ex_depth =
|
||||
(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1;
|
||||
expr->ex_flags = (e1_flags | e2->ex_flags) & ~EX_PARENS;
|
||||
}
|
||||
op = &expr->ex_object.ex_oper;
|
||||
op->op_type = tp;
|
||||
op->op_oper = oper;
|
||||
op->op_left = e1;
|
||||
op->op_right = e2;
|
||||
return expr;
|
||||
}
|
||||
|
||||
chk_cst_expr(expp)
|
||||
register struct expr **expp;
|
||||
{
|
||||
/* The expression expr is checked for constancy.
|
||||
|
||||
There are 6 places where constant expressions occur in C:
|
||||
1. after #if
|
||||
2. in a global initialization
|
||||
3. as size in an array declaration
|
||||
4. as value in an enum declaration
|
||||
5. as width in a bit field
|
||||
6. as case value in a switch
|
||||
|
||||
The constant expression in a global initialization is
|
||||
handled separately (by IVAL()).
|
||||
|
||||
There are various disparate restrictions on each of
|
||||
the others in the various C compilers. I have tried some
|
||||
hypotheses to unify them, but all have failed.
|
||||
|
||||
This routine will give a warning for those operators
|
||||
not allowed by K&R, under the R-option only. The anomalies
|
||||
are cast, logical operators and the expression comma.
|
||||
Special problems (of which there is only one, sizeof in
|
||||
Preprocessor #if) have to be dealt with locally
|
||||
|
||||
Note that according to K&R the negation ! is illegal in
|
||||
constant expressions and is indeed rejected by the
|
||||
Ritchie compiler.
|
||||
*/
|
||||
register struct expr *expr = *expp;
|
||||
register int fund = expr->ex_type->tp_fund;
|
||||
register int flags = expr->ex_flags;
|
||||
int err = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
print_expr("constant_expression", expr);
|
||||
#endif DEBUG
|
||||
if ( fund != CHAR && fund != SHORT && fund != INT &&
|
||||
fund != ENUM && fund != LONG
|
||||
)
|
||||
expr_error(expr, "non-numerical constant expression"), err++;
|
||||
else
|
||||
if (!is_ld_cst(expr))
|
||||
expr_error(expr, "expression is not constant"), err++;
|
||||
#ifndef NOROPTION
|
||||
if (options['R']) {
|
||||
if (flags & EX_CAST)
|
||||
expr_warning(expr, "cast in constant expression");
|
||||
if (flags & EX_LOGICAL)
|
||||
expr_warning(expr,
|
||||
"logical operator in constant expression");
|
||||
if (flags & EX_COMMA)
|
||||
expr_warning(expr,
|
||||
"expression comma in constant expression");
|
||||
}
|
||||
#endif NOROPTION
|
||||
if (err)
|
||||
erroneous2int(expp);
|
||||
}
|
||||
|
||||
init_expression(eppp, expr)
|
||||
register struct expr ***eppp, *expr;
|
||||
{
|
||||
/* The expression expr is added to the tree designated
|
||||
indirectly by **eppp.
|
||||
The natural form of a tree representing an
|
||||
initial_value_list is right-recursive, ie. with the
|
||||
left-most comma as main operator. The iterative grammar in
|
||||
expression.g, however, tends to produce a left-recursive
|
||||
tree, ie. one with the right-most comma as its main
|
||||
operator.
|
||||
To produce a right-recursive tree from the iterative
|
||||
grammar, we keep track of the address of the pointer where
|
||||
the next expression must be hooked in.
|
||||
*/
|
||||
**eppp = new_oper(void_type, expr, INITCOMMA, NILEXPR);
|
||||
*eppp = &(**eppp)->OP_RIGHT;
|
||||
}
|
||||
|
||||
int
|
||||
is_ld_cst(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* An expression is a `load-time constant' if it is of the form
|
||||
<idf> +/- <integral> or <integral>.
|
||||
*/
|
||||
return expr->ex_lvalue == 0 && expr->ex_class == Value;
|
||||
}
|
||||
|
||||
int
|
||||
is_cp_cst(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* An expression is a `compile-time constant' if it is a
|
||||
load-time constant, and the idf is not there.
|
||||
*/
|
||||
return is_ld_cst(expr) && expr->VL_CLASS == Const;
|
||||
}
|
||||
|
||||
#ifndef NOFLOAT
|
||||
int
|
||||
is_fp_cst(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* An expression is a `floating-point constant' if it consists
|
||||
of the float only.
|
||||
*/
|
||||
return expr->ex_class == Float;
|
||||
}
|
||||
#endif NOFLOAT
|
||||
|
||||
free_expression(expr)
|
||||
register struct expr *expr;
|
||||
{
|
||||
/* The expression expr is freed recursively.
|
||||
*/
|
||||
if (expr) {
|
||||
if (expr->ex_class == Oper) {
|
||||
free_expression(expr->OP_LEFT);
|
||||
free_expression(expr->OP_RIGHT);
|
||||
}
|
||||
free_expr(expr);
|
||||
}
|
||||
}
|
||||
102
lang/cem/cemcom/expr.h
Normal file
102
lang/cem/cemcom/expr.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* $Header$ */
|
||||
/* EXPRESSION DESCRIPTOR */
|
||||
|
||||
/* What we want to define is the struct expr, but since it contains
|
||||
a union of various goodies, we define them first; so be patient.
|
||||
*/
|
||||
|
||||
struct value {
|
||||
struct idf *vl_idf; /* idf of an external name or 0 */
|
||||
arith vl_value; /* constant, or offset if idf != 0 */
|
||||
};
|
||||
|
||||
struct string {
|
||||
char *sg_value; /* string of characters repr. the constant */
|
||||
label sg_datlab; /* global data-label */
|
||||
};
|
||||
|
||||
struct floating {
|
||||
char *fl_value; /* pointer to string repr. the fp const. */
|
||||
label fl_datlab; /* global data_label */
|
||||
};
|
||||
|
||||
struct oper {
|
||||
struct type *op_type; /* resulting type of the operation */
|
||||
struct expr *op_left;
|
||||
int op_oper; /* the symbol of the operator */
|
||||
struct expr *op_right;
|
||||
};
|
||||
|
||||
/* The following constants indicate the class of the expression: */
|
||||
#define Value 0 /* it is a value known at load time */
|
||||
#define String 1 /* it is a string constant */
|
||||
#define Float 2 /* it is a floating point constant */
|
||||
#define Oper 3 /* it is a run-time expression */
|
||||
#define Type 4 /* only its type is relevant */
|
||||
|
||||
struct expr {
|
||||
struct expr *next;
|
||||
char *ex_file; /* the file it (probably) comes from */
|
||||
unsigned int ex_line; /* the line it (probably) comes from */
|
||||
struct type *ex_type;
|
||||
char ex_lvalue;
|
||||
char ex_flags;
|
||||
int ex_class;
|
||||
int ex_depth;
|
||||
union {
|
||||
struct value ex_value;
|
||||
struct string ex_string;
|
||||
struct floating ex_float;
|
||||
struct oper ex_oper;
|
||||
} ex_object;
|
||||
};
|
||||
|
||||
/* some abbreviated selections */
|
||||
#define VL_VALUE ex_object.ex_value.vl_value
|
||||
#define VL_IDF ex_object.ex_value.vl_idf
|
||||
#define SG_VALUE ex_object.ex_string.sg_value
|
||||
#define SG_DATLAB ex_object.ex_string.sg_datlab
|
||||
#define FL_VALUE ex_object.ex_float.fl_value
|
||||
#define FL_DATLAB ex_object.ex_float.fl_datlab
|
||||
#define OP_TYPE ex_object.ex_oper.op_type
|
||||
#define OP_LEFT ex_object.ex_oper.op_left
|
||||
#define OP_OPER ex_object.ex_oper.op_oper
|
||||
#define OP_RIGHT ex_object.ex_oper.op_right
|
||||
|
||||
#define EXPRTYPE(e) ((e)->ex_type->tp_fund)
|
||||
|
||||
/* An expression is a `load-time constant' if it is of the form
|
||||
<idf> +/- <integral> or <integral>;
|
||||
it is a `compile-time constant' if it is an <integral>.
|
||||
*/
|
||||
#define is_ld_cst(e) ((e)->ex_lvalue == 0 && (e)->ex_class == Value)
|
||||
#define is_cp_cst(e) (is_ld_cst(e) && (e)->VL_IDF == 0)
|
||||
|
||||
/* a floating constant expression ?
|
||||
*/
|
||||
#define is_fp_cst(e) ((e)->ex_class == Float)
|
||||
|
||||
/* some bits for the ex_flag field, to keep track of various
|
||||
interesting properties of an expression.
|
||||
*/
|
||||
#define EX_SIZEOF 001 /* contains sizeof operator */
|
||||
#define EX_CAST 002 /* contains cast */
|
||||
#define EX_LOGICAL 004 /* contains logical operator */
|
||||
#define EX_COMMA 010 /* contains expression comma */
|
||||
#define EX_PARENS 020 /* the top level is parenthesized */
|
||||
|
||||
#define NILEXPR ((struct expr *)0)
|
||||
|
||||
extern struct expr *intexpr(), *new_oper();
|
||||
|
||||
|
||||
/* allocation definitions of struct expr */
|
||||
/* ALLOCDEF "expr" */
|
||||
extern char *st_alloc();
|
||||
extern struct expr *h_expr;
|
||||
#define new_expr() ((struct expr *) \
|
||||
st_alloc((char **)&h_expr, sizeof(struct expr)))
|
||||
#define free_expr(p) st_free(p, h_expr, sizeof(struct expr))
|
||||
|
||||
|
||||
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
|
||||
110
lang/cem/cemcom/expr.str
Normal file
110
lang/cem/cemcom/expr.str
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* EXPRESSION DESCRIPTOR */
|
||||
|
||||
/* What we want to define is the struct expr, but since it contains
|
||||
a union of various goodies, we define them first; so be patient.
|
||||
*/
|
||||
|
||||
#include "nofloat.h"
|
||||
|
||||
/* classes of value */
|
||||
#define Const 1
|
||||
#define Name 2
|
||||
#define Label 3
|
||||
|
||||
struct value {
|
||||
int vl_class; /* Const, Name or Label */
|
||||
arith vl_value; /* constant value or offset */
|
||||
union {
|
||||
struct idf *vl_idf; /* external name */
|
||||
label vl_lbl; /* compiler-generated label */
|
||||
} vl_data;
|
||||
};
|
||||
|
||||
struct string {
|
||||
char *sg_value; /* row of bytes repr. the constant */
|
||||
int sg_len; /* length of the row */
|
||||
label sg_datlab; /* global data-label */
|
||||
};
|
||||
|
||||
#ifndef NOFLOAT
|
||||
struct floating {
|
||||
char *fl_value; /* pointer to string repr. the fp const. */
|
||||
label fl_datlab; /* global data_label */
|
||||
};
|
||||
#endif NOFLOAT
|
||||
|
||||
struct oper {
|
||||
struct type *op_type; /* resulting type of the operation */
|
||||
struct expr *op_left;
|
||||
int op_oper; /* the symbol of the operator */
|
||||
struct expr *op_right;
|
||||
};
|
||||
|
||||
/* The following constants indicate the class of the expression: */
|
||||
#define Value 0 /* it is a value known at load time */
|
||||
#define String 1 /* it is a string constant */
|
||||
#ifndef NOFLOAT
|
||||
#define Float 2 /* it is a floating point constant */
|
||||
#endif NOFLOAT
|
||||
#define Oper 3 /* it is a run-time expression */
|
||||
#define Type 4 /* only its type is relevant */
|
||||
|
||||
struct expr {
|
||||
struct expr *next;
|
||||
char *ex_file; /* the file it (probably) comes from */
|
||||
unsigned int ex_line; /* the line it (probably) comes from */
|
||||
struct type *ex_type;
|
||||
char ex_lvalue;
|
||||
char ex_flags;
|
||||
int ex_class;
|
||||
int ex_depth;
|
||||
union {
|
||||
struct value ex_value;
|
||||
struct string ex_string;
|
||||
#ifndef NOFLOAT
|
||||
struct floating ex_float;
|
||||
#endif NOFLOAT
|
||||
struct oper ex_oper;
|
||||
} ex_object;
|
||||
};
|
||||
|
||||
/* some abbreviated selections */
|
||||
#define VL_CLASS ex_object.ex_value.vl_class
|
||||
#define VL_VALUE ex_object.ex_value.vl_value
|
||||
#define VL_IDF ex_object.ex_value.vl_data.vl_idf
|
||||
#define VL_LBL ex_object.ex_value.vl_data.vl_lbl
|
||||
#define SG_VALUE ex_object.ex_string.sg_value
|
||||
#define SG_LEN ex_object.ex_string.sg_len
|
||||
#define SG_DATLAB ex_object.ex_string.sg_datlab
|
||||
#ifndef NOFLOAT
|
||||
#define FL_VALUE ex_object.ex_float.fl_value
|
||||
#define FL_DATLAB ex_object.ex_float.fl_datlab
|
||||
#endif NOFLOAT
|
||||
#define OP_TYPE ex_object.ex_oper.op_type
|
||||
#define OP_LEFT ex_object.ex_oper.op_left
|
||||
#define OP_OPER ex_object.ex_oper.op_oper
|
||||
#define OP_RIGHT ex_object.ex_oper.op_right
|
||||
|
||||
/* some bits for the ex_flag field, to keep track of various
|
||||
interesting properties of an expression.
|
||||
*/
|
||||
#define EX_SIZEOF 0001 /* contains sizeof operator */
|
||||
#define EX_CAST 0002 /* contains cast */
|
||||
#define EX_LOGICAL 0004 /* contains logical operator */
|
||||
#define EX_COMMA 0010 /* contains expression comma */
|
||||
#define EX_PARENS 0020 /* the top level is parenthesized */
|
||||
#define EX_SIDEEFFECTS 0040 /* expression has side effects */
|
||||
#define EX_ERROR 0200 /* the expression is wrong */
|
||||
|
||||
#define NILEXPR ((struct expr *)0)
|
||||
|
||||
extern struct expr *intexpr(), *new_oper();
|
||||
|
||||
/* ALLOCDEF "expr" 20 */
|
||||
|
||||
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
|
||||
341
lang/cem/cemcom/expression.g
Normal file
341
lang/cem/cemcom/expression.g
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* EXPRESSION SYNTAX PARSER */
|
||||
|
||||
{
|
||||
#include "arith.h"
|
||||
#include "LLlex.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "noRoption.h"
|
||||
|
||||
extern char options[];
|
||||
extern struct expr *intexpr();
|
||||
}
|
||||
|
||||
/* 7.1 */
|
||||
primary(register struct expr **expp;) :
|
||||
IDENTIFIER
|
||||
{dot2expr(expp);}
|
||||
|
|
||||
constant(expp)
|
||||
|
|
||||
STRING
|
||||
{dot2expr(expp);}
|
||||
|
|
||||
'(' expression(expp) ')'
|
||||
{(*expp)->ex_flags |= EX_PARENS;}
|
||||
;
|
||||
|
||||
secundary(register struct expr **expp;) :
|
||||
primary(expp)
|
||||
[
|
||||
index_pack(expp)
|
||||
|
|
||||
parameter_pack(expp)
|
||||
|
|
||||
selection(expp)
|
||||
]*
|
||||
;
|
||||
|
||||
index_pack(struct expr **expp;)
|
||||
{struct expr *e1;}
|
||||
:
|
||||
'[' expression(&e1) ']'
|
||||
{ch7bin(expp, '[', e1);}
|
||||
;
|
||||
|
||||
parameter_pack(struct expr **expp;)
|
||||
{struct expr *e1 = 0;}
|
||||
:
|
||||
'(' parameter_list(&e1)? ')'
|
||||
{ch7bin(expp, '(', e1);}
|
||||
;
|
||||
|
||||
selection(struct expr **expp;)
|
||||
{int oper; struct idf *idf;}
|
||||
:
|
||||
[ '.' | ARROW ]
|
||||
{oper = DOT;}
|
||||
identifier(&idf)
|
||||
{ch7sel(expp, oper, idf);}
|
||||
;
|
||||
|
||||
parameter_list(struct expr **expp;)
|
||||
{struct expr *e1 = 0;}
|
||||
:
|
||||
assignment_expression(expp)
|
||||
{any2opnd(expp, PARCOMMA);}
|
||||
[ ','
|
||||
assignment_expression(&e1)
|
||||
{any2opnd(&e1, PARCOMMA);}
|
||||
{ch7bin(expp, PARCOMMA, e1);}
|
||||
]*
|
||||
;
|
||||
|
||||
/* 7.2 */
|
||||
postfixed(struct expr **expp;)
|
||||
{int oper;}
|
||||
:
|
||||
secundary(expp)
|
||||
[
|
||||
postop(&oper)
|
||||
{ch7incr(expp, oper);}
|
||||
|
|
||||
empty
|
||||
]
|
||||
;
|
||||
|
||||
%first first_of_type_specifier, type_specifier;
|
||||
|
||||
unary(register struct expr **expp;)
|
||||
{struct type *tp; int oper;}
|
||||
:
|
||||
%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
|
||||
cast(&tp) unary(expp)
|
||||
{ ch7cast(expp, CAST, tp);
|
||||
(*expp)->ex_flags |= EX_CAST;
|
||||
}
|
||||
|
|
||||
postfixed(expp)
|
||||
|
|
||||
unop(&oper) unary(expp)
|
||||
{ch7mon(oper, expp);}
|
||||
|
|
||||
size_of(expp)
|
||||
;
|
||||
|
||||
size_of(register struct expr **expp;)
|
||||
{struct type *tp;}
|
||||
:
|
||||
SIZEOF
|
||||
[%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
|
||||
cast(&tp)
|
||||
{
|
||||
*expp = intexpr(size_of_type(tp, "type"), INT);
|
||||
(*expp)->ex_flags |= EX_SIZEOF;
|
||||
}
|
||||
|
|
||||
unary(expp)
|
||||
{ch7mon(SIZEOF, expp);}
|
||||
]
|
||||
;
|
||||
|
||||
/* 7.3-7.12 */
|
||||
/* The set of operators in C is stratified in 15 levels, with level
|
||||
N being treated in RM 7.N. In principle each operator is
|
||||
assigned a rank, ranging from 1 to 15. Such an expression can
|
||||
be parsed by a construct like:
|
||||
binary_expression(int maxrank;)
|
||||
{int oper;}
|
||||
:
|
||||
binary_expression(maxrank - 1)
|
||||
[%if (rank_of(DOT) <= maxrank)
|
||||
binop(&oper)
|
||||
binary_expression(rank_of(oper)-1)
|
||||
]?
|
||||
;
|
||||
except that some call of 'unary' is necessary, depending on the
|
||||
grammar.
|
||||
|
||||
This simple view is marred by three complications:
|
||||
1. Level 15 (comma operator) is not allowed in many
|
||||
contexts and is different.
|
||||
2. Level 13 (conditional operator) is a ternary operator,
|
||||
which does not fit this scheme at all.
|
||||
3. Level 14 (assignment operators) group right-to-left, as
|
||||
opposed to 2-12, which group left-to-right (or are
|
||||
immaterial).
|
||||
4. The operators in level 14 start with operators in levels
|
||||
2-13 (RM 7.14: The two parts of a compound assignment
|
||||
operator are separate tokens.) This causes LL1 problems.
|
||||
This forces us to have four rules:
|
||||
binary_expression for level 2-12
|
||||
conditional_expression for level 13
|
||||
assignment_expression for level 14 and
|
||||
expression for the most general expression
|
||||
*/
|
||||
|
||||
binary_expression(int maxrank; struct expr **expp;)
|
||||
{int oper; struct expr *e1;}
|
||||
:
|
||||
unary(expp)
|
||||
[%while (rank_of(DOT) <= maxrank && AHEAD != '=')
|
||||
/* '?', '=', and ',' are no binops, and the test
|
||||
for AHEAD != '=' keeps the other assignment
|
||||
operators out
|
||||
*/
|
||||
binop(&oper)
|
||||
binary_expression(rank_of(oper)-1, &e1)
|
||||
{
|
||||
ch7bin(expp, oper, e1);
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
/* 7.13 */
|
||||
conditional_expression(struct expr **expp;)
|
||||
/* There is some unfortunate disagreement about what is allowed
|
||||
between the '?' and the ':' of a conditional_expression.
|
||||
Although the Ritchie compiler does not even allow
|
||||
conditional_expressions there, some other compilers (e.g., VAX)
|
||||
accept a full assignment_expression there, and programs
|
||||
(like, e.g., emacs) rely on it. So we have little choice.
|
||||
*/
|
||||
{struct expr *e1 = 0, *e2 = 0;}
|
||||
:
|
||||
/* allow all binary operators */
|
||||
binary_expression(rank_of('?') - 1, expp)
|
||||
[ '?'
|
||||
expression(&e1)
|
||||
{
|
||||
#ifndef NOROPTION
|
||||
check_conditional(e1, '?', "between ? and :");
|
||||
#endif
|
||||
}
|
||||
':'
|
||||
assignment_expression(&e2)
|
||||
{
|
||||
#ifndef NOROPTION
|
||||
check_conditional(e2, '=', "after :");
|
||||
#endif
|
||||
ch7bin(&e1, ':', e2);
|
||||
opnd2test(expp, '?');
|
||||
ch7bin(expp, '?', e1);
|
||||
}
|
||||
]?
|
||||
;
|
||||
|
||||
/* 7.14 */
|
||||
assignment_expression(struct expr **expp;)
|
||||
{
|
||||
int oper;
|
||||
struct expr *e1 = 0;
|
||||
}
|
||||
:
|
||||
conditional_expression(expp)
|
||||
[%prefer /* (rank_of(DOT) <= maxrank) for any asgnop */
|
||||
asgnop(&oper)
|
||||
assignment_expression(&e1)
|
||||
{ch7asgn(expp, oper, e1);}
|
||||
|
|
||||
empty /* LLgen artefact ??? */
|
||||
]
|
||||
;
|
||||
|
||||
/* 7.15 */
|
||||
expression(struct expr **expp;)
|
||||
{struct expr *e1;}
|
||||
:
|
||||
assignment_expression(expp)
|
||||
[ ','
|
||||
assignment_expression(&e1)
|
||||
{
|
||||
ch7bin(expp, ',', e1);
|
||||
}
|
||||
]*
|
||||
;
|
||||
|
||||
unop(int *oper;) :
|
||||
['*' | '&' | '-' | '!' | '~' | PLUSPLUS | MINMIN]
|
||||
{*oper = DOT;}
|
||||
;
|
||||
|
||||
postop(int *oper;):
|
||||
PLUSPLUS {*oper = POSTINCR;}
|
||||
|
|
||||
MINMIN {*oper = POSTDECR;}
|
||||
;
|
||||
|
||||
multop:
|
||||
'*' | '/' | '%'
|
||||
;
|
||||
|
||||
addop:
|
||||
'+' | '-'
|
||||
;
|
||||
|
||||
shiftop:
|
||||
LEFT | RIGHT
|
||||
;
|
||||
|
||||
relop:
|
||||
'<' | '>' | LESSEQ | GREATEREQ
|
||||
;
|
||||
|
||||
eqop:
|
||||
EQUAL | NOTEQUAL
|
||||
;
|
||||
|
||||
arithop:
|
||||
multop | addop | shiftop
|
||||
|
|
||||
'&' | '^' | '|'
|
||||
;
|
||||
|
||||
binop(int *oper;) :
|
||||
[ arithop | relop | eqop | AND | OR ]
|
||||
{*oper = DOT;}
|
||||
;
|
||||
|
||||
asgnop(register int *oper;):
|
||||
'=' {*oper = DOT;}
|
||||
|
|
||||
'+' '=' {*oper = PLUSAB;}
|
||||
|
|
||||
'-' '=' {*oper = MINAB;}
|
||||
|
|
||||
'*' '=' {*oper = TIMESAB;}
|
||||
|
|
||||
'/' '=' {*oper = DIVAB;}
|
||||
|
|
||||
'%' '=' {*oper = MODAB;}
|
||||
|
|
||||
LEFT '=' {*oper = LEFTAB;}
|
||||
|
|
||||
RIGHT '=' {*oper = RIGHTAB;}
|
||||
|
|
||||
'&' '=' {*oper = ANDAB;}
|
||||
|
|
||||
'^' '=' {*oper = XORAB;}
|
||||
|
|
||||
'|' '=' {*oper = ORAB;}
|
||||
|
|
||||
[ PLUSAB | MINAB | TIMESAB | DIVAB | MODAB |
|
||||
LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ]
|
||||
{
|
||||
char *symbol2str();
|
||||
|
||||
warning("old-fashioned assignment operator, use %s",
|
||||
symbol2str(DOT));
|
||||
*oper = DOT;
|
||||
}
|
||||
;
|
||||
|
||||
constant(struct expr **expp;) :
|
||||
[
|
||||
INTEGER
|
||||
|
|
||||
FLOATING
|
||||
] {dot2expr(expp);}
|
||||
;
|
||||
|
||||
/* 15 */
|
||||
constant_expression (struct expr **expp;) :
|
||||
assignment_expression(expp)
|
||||
{chk_cst_expr(expp);}
|
||||
;
|
||||
|
||||
identifier(struct idf **idfp;) :
|
||||
[
|
||||
IDENTIFIER
|
||||
|
|
||||
TYPE_IDENTIFIER
|
||||
]
|
||||
{*idfp = dot.tk_idf;}
|
||||
;
|
||||
9
lang/cem/cemcom/faulty.h
Normal file
9
lang/cem/cemcom/faulty.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* FAULTY DEFINITIONS */
|
||||
|
||||
#define faulty(tp) ((tp)_faulty(__FILE__, __LINE__))
|
||||
#define fault() (_faulty(__FILE__, __LINE__))
|
||||
175
lang/cem/cemcom/field.c
Normal file
175
lang/cem/cemcom/field.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* BITFIELD EXPRESSION EVALUATOR */
|
||||
|
||||
#include "nobitfield.h"
|
||||
|
||||
#ifndef NOBITFIELD
|
||||
#include <em.h>
|
||||
#include <em_reg.h>
|
||||
#include "debug.h"
|
||||
#include "arith.h"
|
||||
#include "type.h"
|
||||
#include "idf.h"
|
||||
#include "label.h"
|
||||
#include "code.h"
|
||||
#include "assert.h"
|
||||
#include "expr.h"
|
||||
#include "sizes.h"
|
||||
#include "align.h"
|
||||
#include "Lpars.h"
|
||||
#include "field.h"
|
||||
|
||||
arith NewLocal(); /* util.c */
|
||||
char *symbol2str(); /* symbol2str.c */
|
||||
|
||||
/* Eval_field() evaluates expressions involving bit fields.
|
||||
The various instructions are not yet optimised in the expression
|
||||
tree and are therefore dealt with in this function.
|
||||
The actions taken at any operation are described clearly by the
|
||||
code for this actions.
|
||||
Notes
|
||||
[1] the bitfields are packed in target machine integers!
|
||||
[2] op is either an assignment operator or an increment/
|
||||
decrement operator
|
||||
[3] atype: the type in which the bitfield arithmetic is done;
|
||||
and in which bitfields are stored!
|
||||
*/
|
||||
eval_field(expr, code)
|
||||
struct expr *expr;
|
||||
int code;
|
||||
{
|
||||
int op = expr->OP_OPER;
|
||||
register struct expr *leftop = expr->OP_LEFT;
|
||||
register struct expr *rightop = expr->OP_RIGHT;
|
||||
register struct field *fd = leftop->ex_type->tp_field;
|
||||
struct type *tp = leftop->ex_type->tp_up;
|
||||
arith tmpvar;
|
||||
struct type *atype = tp->tp_unsigned ? uword_type : word_type;
|
||||
arith asize = atype->tp_size;
|
||||
|
||||
/* First some assertions to be sure that the rest is legal */
|
||||
ASSERT(asize == word_size); /* make sure that C_loc() is legal */
|
||||
ASSERT(leftop->ex_type->tp_fund == FIELD);
|
||||
leftop->ex_type = atype; /* this is cheating but it works... */
|
||||
if (op == '=') {
|
||||
/* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */
|
||||
ASSERT(tp == rightop->ex_type);
|
||||
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
conversion(tp, atype);
|
||||
C_loc(fd->fd_mask);
|
||||
C_and(asize);
|
||||
if (code == TRUE)
|
||||
C_dup(asize);
|
||||
C_loc((arith)fd->fd_shift);
|
||||
if (atype->tp_unsigned)
|
||||
C_slu(asize);
|
||||
else
|
||||
C_sli(asize);
|
||||
C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize))));
|
||||
if (leftop->ex_depth == 0) { /* simple case */
|
||||
load_val(leftop, RVAL);
|
||||
C_and(asize);
|
||||
C_ior(asize);
|
||||
store_val(&(leftop->ex_object.ex_value), atype);
|
||||
}
|
||||
else { /* complex case */
|
||||
tmpvar = NewLocal(pointer_size, pointer_align,
|
||||
reg_pointer, 0);
|
||||
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_dup(pointer_size);
|
||||
StoreLocal(tmpvar, pointer_size);
|
||||
C_loi(asize);
|
||||
C_and(asize);
|
||||
C_ior(asize);
|
||||
LoadLocal(tmpvar, pointer_size);
|
||||
C_sti(asize);
|
||||
FreeLocal(tmpvar);
|
||||
}
|
||||
}
|
||||
else { /* treat ++F as F += 1 and --F as F -= 1 */
|
||||
/* F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
|
||||
(f&~(mask<<shift))
|
||||
*/
|
||||
if (leftop->ex_depth == 0) /* simple case */
|
||||
load_val(leftop, RVAL);
|
||||
else { /* complex case */
|
||||
tmpvar = NewLocal(pointer_size, pointer_align,
|
||||
reg_pointer, 0);
|
||||
EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
C_dup(pointer_size);
|
||||
StoreLocal(tmpvar, pointer_size);
|
||||
C_loi(asize);
|
||||
}
|
||||
if (atype->tp_unsigned) {
|
||||
C_loc((arith)fd->fd_shift);
|
||||
C_sru(asize);
|
||||
C_loc(fd->fd_mask);
|
||||
C_and(asize);
|
||||
}
|
||||
else {
|
||||
arith bits_in_type = asize * 8;
|
||||
C_loc(bits_in_type - (fd->fd_width + fd->fd_shift));
|
||||
C_sli(asize);
|
||||
C_loc(bits_in_type - fd->fd_width);
|
||||
C_sri(asize);
|
||||
}
|
||||
if (code == TRUE && (op == POSTINCR || op == POSTDECR))
|
||||
C_dup(asize);
|
||||
conversion(atype, rightop->ex_type);
|
||||
EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
/* the 'op' operation: */
|
||||
if (op == PLUSPLUS || op == POSTINCR)
|
||||
assop(rightop->ex_type, PLUSAB);
|
||||
else
|
||||
if (op == MINMIN || op == POSTDECR)
|
||||
assop(rightop->ex_type, MINAB);
|
||||
else
|
||||
assop(rightop->ex_type, op);
|
||||
conversion(rightop->ex_type, atype);
|
||||
C_loc(fd->fd_mask);
|
||||
C_and(asize);
|
||||
if (code == TRUE && op != POSTINCR && op != POSTDECR)
|
||||
C_dup(asize);
|
||||
C_loc((arith)fd->fd_shift);
|
||||
if (atype->tp_unsigned)
|
||||
C_slu(asize);
|
||||
else
|
||||
C_sli(asize);
|
||||
C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize))));
|
||||
if (leftop->ex_depth == 0) {
|
||||
load_val(leftop, RVAL);
|
||||
C_and(asize);
|
||||
C_ior(asize);
|
||||
store_val(&(leftop->ex_object.ex_value), atype);
|
||||
}
|
||||
else {
|
||||
LoadLocal(tmpvar, pointer_size);
|
||||
C_loi(asize);
|
||||
C_and(asize);
|
||||
C_ior(asize);
|
||||
LoadLocal(tmpvar, pointer_size);
|
||||
C_sti(asize);
|
||||
FreeLocal(tmpvar);
|
||||
}
|
||||
}
|
||||
if (code == TRUE) {
|
||||
/* Take care that the effective value stored in
|
||||
the bit field (i.e. the value that is got on
|
||||
retrieval) is on top of stack.
|
||||
*/
|
||||
if (atype->tp_unsigned == 0) { /* sign extension */
|
||||
register arith shift = asize * 8 - fd->fd_width;
|
||||
|
||||
C_loc(shift);
|
||||
C_sli(asize);
|
||||
C_loc(shift);
|
||||
C_sri(asize);
|
||||
}
|
||||
conversion(atype, expr->ex_type);
|
||||
}
|
||||
}
|
||||
#endif NOBITFIELD
|
||||
20
lang/cem/cemcom/field.h
Normal file
20
lang/cem/cemcom/field.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* $Header$ */
|
||||
/* FIELD DESCRIPTOR */
|
||||
|
||||
struct field { /* for field specifiers */
|
||||
struct field *next;
|
||||
arith fd_mask;
|
||||
int fd_shift;
|
||||
int fd_width;
|
||||
struct sdef *fd_sdef; /* upward pointer */
|
||||
};
|
||||
|
||||
|
||||
/* allocation definitions of struct field */
|
||||
/* ALLOCDEF "field" */
|
||||
extern char *st_alloc();
|
||||
extern struct field *h_field;
|
||||
#define new_field() ((struct field *) \
|
||||
st_alloc((char **)&h_field, sizeof(struct field)))
|
||||
#define free_field(p) st_free(p, h_field, sizeof(struct field))
|
||||
|
||||
16
lang/cem/cemcom/field.str
Normal file
16
lang/cem/cemcom/field.str
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* FIELD DESCRIPTOR */
|
||||
|
||||
struct field { /* for field specifiers */
|
||||
struct field *next;
|
||||
arith fd_mask;
|
||||
int fd_shift;
|
||||
int fd_width;
|
||||
struct sdef *fd_sdef; /* upward pointer */
|
||||
};
|
||||
|
||||
/* ALLOCDEF "field" 50 */
|
||||
20
lang/cem/cemcom/file_info.h
Normal file
20
lang/cem/cemcom/file_info.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
/* F I L E I N F O R M A T I O N S T R U C T U R E */
|
||||
|
||||
struct file_info {
|
||||
unsigned int fil_lino;
|
||||
int fil_nestlevel;
|
||||
char *fil_name;
|
||||
char *fil_wdir;
|
||||
};
|
||||
|
||||
#define nestlevel finfo.fil_nestlevel
|
||||
#define LineNumber finfo.fil_lino
|
||||
#define FileName finfo.fil_name
|
||||
#define WorkingDir finfo.fil_wdir
|
||||
|
||||
extern struct file_info finfo; /* input.c */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user