Added .globl, fix in Xfit call

This commit is contained in:
ceriel
1987-08-26 14:45:27 +00:00
3805 changed files with 199429 additions and 14298 deletions

4
lang/.distr Normal file
View File

@@ -0,0 +1,4 @@
basic
cem
occam
pc

3
lang/basic/.distr Normal file
View File

@@ -0,0 +1,3 @@
lib
src
test

2
lang/basic/lib/.distr Normal file
View File

@@ -0,0 +1,2 @@
LIST
tail_bc.a

View File

@@ -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);

View File

@@ -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)

View File

@@ -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
View 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

View File

@@ -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 \

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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 */

View File

@@ -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

View File

@@ -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]));

View File

@@ -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

View File

@@ -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()

View File

@@ -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);

View File

@@ -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

View File

@@ -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");

View File

@@ -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");
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -1 +1 @@
percent interest is 0.000173
percent interest is 6.918919

View File

@@ -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

View File

@@ -2,4 +2,5 @@
line130
line140
line150
LINE 120:ERROR 1: RETURN without GOSUB
4 end
Break in 121

View File

@@ -1,4 +1,4 @@
hello brave new world
handicap
try to read beyond
<EFBFBD>
LINE 70:ERROR 2: Out of data

View File

@@ -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

View File

@@ -4,5 +4,4 @@
160 true
170 true
yes or no
? 0
0
?LINE 190:ERROR 2: Out of data

View File

@@ -0,0 +1,2 @@
data
data1

3
lang/cem/.distr Normal file
View File

@@ -0,0 +1,3 @@
cemcom
ctest
libcc

88
lang/cem/cemcom/.distr Normal file
View 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
View 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
View 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
View 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
View 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)

View 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
View 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

View 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
View 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
View 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
View 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 */

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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
View 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];
}

View 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
View 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 */

View 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;

View 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;
}
}

View 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
View 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;
}

View 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;

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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");
}

View 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
View 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
View 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
View 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
View 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)

View 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
View 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
View 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
View 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
View 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 */

View 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