home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
221_01
/
cc21.c
< prev
next >
Wrap
Text File
|
1979-12-31
|
13KB
|
504 lines
/* >>>>>> start of cc2 <<<<<<<< */
/* */
/* Get required array size */
/* */
/* invoked when declared variable is followed by "[" */
/* this routine makes subscript the absolute */
/* size of the array. */
needsub()
{
int num[1];
if(match("]"))return (0); /* null size */
if (number(num)==0) /* go after a number */
{errrpt("must be constant"); /* it isn't */
num[0]=1; /* so force one */
}
if (num[0]<0)
{errrpt("negative size illegal");
num[0]=(-num[0]);
}
needbrack("]"); /* force single dimension */
return (num[0]); /* and return size */
}
/* */
/* Begin a function */
/* */
/* Called from "parse" this routine tries to make a function */
/* out of what follows. */
newfunc(class) int class; {
/* next lines added by dieter flunkert 23 jan 1986 */
int argtop; /* top of argument stack */
char n[namesize],*ptr;
#ifdef STGOTO
nogo=noloc=0;
#endif
#ifdef PHASE2
if(monitor) {cout('\n',stderr);sout(line,stderr);}
#endif
if (symname(n)==0)
{errrpt("illegal function or declaration");
kill(); /* invalidate line */
return;
}
if(ptr=findglb(n)) /* already in symbol table ? */
{if(ptr[ident]!=function)multidef(n);
/* already variable by that name */
else if(ptr[offset]==function)multidef(n);
/* already function by that name */
else ptr[offset]=function;
/* otherwise we have what was earlier*/
/* assumed to be a function */
}
/* if not in table, define as a function now */
else addglb(n,function,cint,function);
/* we had better see open paren for args... */
if(match("(")==0)errrpt("missing open paren");
/* next lines added by dieter flunkert 23 jan 1986 */
if(first_func) {
defname(n); /* define name of asm module */
first_func = 0;
}
entry(n, class);
if(DEFDEBUG) debug(n);
/* ** Clear local stack pointer rev. 1P */
locptr = startloc; /* ** 2 lines inserted rev. 1P */
argstk=0; /* init arg count */
while(match(")")==0) /* then count args */
/* any legal name bumps arg count */
{if(symname(n)) /* **+ Modification rev. 1P */
{ if (findloc(n)) multidef(n);
else { addloc(n, 0, 0, argstk);
argstk = argstk + 2;
}
} /* **- End of modification rev. 1P */
else{errrpt("illegal argument name");junk();}
blanks();
/* if not closing paren, should be comma */
if(streq(line+lptr,")")==0)
{if(match(",")==0)
errrpt("expected comma");
}
if(endst())break;
}
/* ** Next line deleted rev. 1P */
/* ** locptr=startloc; ** */ /* "clear" local symbol table*/
stkp=0; /* preset stack ptr */
/* next line added by dieter flunkert 23 jan 1986 */
argtop=argstk; /* save top of argument stack */
while(argstk)
/* now let user declare what types of things */
/* those arguments were */
{if(amatch("char",4)){getarg(argtop,cchar);ns();}
else if(amatch("int",3)){getarg(argtop,cint);ns();}
else{errrpt("wrong number args");break;}
}
if(statement()!=streturn) /* do a statement, but if */
/* it's a return, skip */
/* cleaning up the stack */
{modstk(0);
ret();
}
stkp=0; /* reset stack ptr again */
locptr=startloc; /* deallocate all locals */
if(litptr) { /* dump literal pool */
printlabel(litlab);
dumplits(1);
litlab=getlabel();
}
}
/* */
/* Declare argument types */
/* */
/* called from "newfunc" this routine adds an entry in the */
/* local symbol table for each named argument */
/* ** Function completely rewritten rev. 1P */
/* modified by dieter flunkert 23 jan 1986 */
/* argtop is not allowed to change value. This was the case
if a function had a declaration like:
int i; char c; */
getarg(argtop,t) /* t = cchar or cint */
int argtop,t;
{
int j, legalname, address;
char n[namesize], c, *argptr;
/* next line deleted by dieter flunkert 23 jan 1986 */
/* argtop = argstk; */
while(1)
{if(argstk==0)return; /* no more args */
if(match("*"))j=pointer;
else j=variable;
if((legalname = symname(n)) == 0) illname();
if(match("[")) /* pointer ? */
/* it is a pointer, so skip all */
/* stuff between "[]" */
{while(inbyte()!=']')
if(endst())break;
j=pointer;
/* add entry as pointer */
}
if (legalname) {
if (argptr = findloc(n)) {
/* Add in details of the type and address of */
/* the name */
argptr[ident] = j;
argptr[type] = t;
address = argtop - (argptr[offset] + (argptr[offset+1]<<8));
putint(address, argptr+offset, offsize);
}
else errrpt("Expected argument name");
}
argstk=argstk-2; /* cnt down */
if (endst()) return;
if (match(",") == 0) errrpt("expected comma");
}
}
/* ** End of modifications rev. 1P */
/*
** statement parser
**
** called whenever syntax requires a statement
** this routine performs that statement
** and returns a number telling which one
*/
statement() {
int class;
if ((ch==0) && (eof)) return;
if(amatch("static",6)) {
class=statik;
if(++stdecl == 1) /* there are static variables */
jump(stlab=getlabel()); /* skip static declarations */
}
else class=stkloc;
if(amatch("char",4)) {declloc(cchar,class);ns();}
else if(amatch("int",3)) {declloc(cint,class);ns();}
else {
if(stdecl > 0) {
postlabel(stlab);
stdecl = 0;
}
if(declared >= 0) {
#ifdef STGOTO
if(ncmp > 1) nogo=declared; /* disable goto if any */
#endif
stkp=modstk(stkp - declared);
declared = -1;
}
if(match("{")) compound();
else if(amatch("if",2)) {doif();lastst=stif;}
else if(amatch("while",5)) {dowhile();lastst=stwhile;}
#ifdef STDO
else if(amatch("do",2)) {dodo();lastst=STDO;}
#endif
#ifdef STFOR
else if(amatch("for",3)) {dofor();lastst=STFOR;}
#endif
#ifdef STSWITCH
else if(amatch("switch",6)) {doswitch();lastst=STSWITCH;}
else if(amatch("case",4)) {docase();lastst=STCASE;}
else if(amatch("default",7)) {dodefault();lastst=STDEF;}
#endif
#ifdef STGOTO
else if(amatch("goto", 4)) {dogoto(); lastst=STGOTO;}
else if(dolabel()) lastst=STLABEL;
#endif
else if(amatch("return",6)) {doreturn();ns();lastst=streturn;}
else if(amatch("break",5)) {dobreak();ns();lastst=stbreak;}
else if(amatch("continue",8)){docont();ns();lastst=stcont;}
else if(match(";")) ;
else if(match("#asm")) {doasm();lastst=stasm;}
else {doexpression();ns();lastst=stexp;}
}
return lastst;
}
#ifdef STDO
dodo() {
int wq[4], top;
addwhile(wq);
postlabel(top=getlabel());
statement();
needbrack("while");
postlabel(wq[wqloop]);
test(wq[wqlab],YES);
jump(top);
postlabel(wq[wqlab]);
delwhile();
ns();
}
#endif
#ifdef STFOR
dofor() {
int wq[4], lab1, lab2;
addwhile(wq);
lab1=getlabel();
lab2=getlabel();
needbrack("(");
if(match(";")==0) {
doexpression(); /* expr 1 */
ns();
}
postlabel(lab1);
if(match(";")==0) {
test(wq[wqlab],NO); /* expr 2 */
ns();
}
jump(lab2);
postlabel(wq[wqloop]);
if(match(")")==0) {
doexpression(); /* expr 3 */
needbrack(")");
}
jump(lab1);
postlabel(lab2);
statement();
jump(wq[wqloop]);
postlabel(wq[wqlab]);
delwhile();
}
#endif
#ifdef STSWITCH
doswitch() {
int wq[4], endlab, swact, swdef, *swnex, *swptr;
swact=swactive;
swdef=swdefault;
swnex=swptr=swnext;
addwhile(wq);
needbrack("(");
doexpression(); /* evaluate switch expression */
needbrack(")");
swdefault=0;
swactive=1;
jump(endlab=getlabel());
statement(); /* cases, etc. */
jump(wq[wqlab]);
postlabel(endlab);
sw(); /* match cases */
while(swptr < swnext) {
defstorage(cint>>2);
printlabel(*swptr++); /* case label */
outbyte(',');
outdec(*swptr++); /* case value */
nl();
}
defstorage(cint>>2);
outdec(0);
nl();
if(swdefault) jump(swdefault);
postlabel(wq[wqlab]);
delwhile();
swnext=swnex;
swdefault=swdef;
swactive=swact;
}
docase() {
if(swactive==0) errrpt("not in switch");
if(swnext > swend) {
errrpt("too many cases");
return;
}
postlabel(*swnext++ = getlabel());
constexpr(swnext++);
needbrack(":");
}
dodefault() {
if(swactive) {
if(swdefault) errrpt("multiple defaults");
}
else errrpt("not in switch");
needbrack(":");
postlabel(swdefault=getlabel());
}
#endif
#ifdef STGOTO
dogoto() {
char ssname[namesize];
if(nogo > 0) errrpt("not allowed with block-locals");
else noloc = 1;
if(symname(ssname)) jump(addlabel(ssname));
else errrpt("bad label");
ns();
}
dolabel() {
int i;
char ssname[namesize];
char *savelptr;
blanks();
savelptr=lptr;
if(symname(ssname)) {
if(gch()==':') {
postlabel(addlabel(ssname));
return 1;
}
else {
i=savelptr-lptr+1;
while(--i) inchar();
}
}
return 0;
}
addlabel(ssname) char *ssname; {
if(cptr=findloc(ssname)) {
if(cptr[ident]!=LABEL) errrpt("not a label");
}
else cptr=addloc(ssname, LABEL, LABEL, getlabel(), LABEL);
return (getint(cptr+offset, offsize));
}
#endif
/* */
/* Semicolon enforcer */
/* */
/* called whenever syntax requires a semicolon */
ns() {if(match(";")==0)errrpt("missing semicolon");}
/* */
/* Compound statement */
/* */
/* allow any number of statements to fall between "{}" */
compound()
{
int savcsp;
char *savloc, *savstat;
savcsp=stkp;
startcomp=savloc=locptr;
savstat=statptr;
declared = stdecl = statlab = 0;
++ncmp; /* new level open */
while (match("}")==0)
if(eof) {
errrpt("no final }");
break;
}
else statement(); /* do one */
--ncmp; /* close current level */
if(lastst != streturn)
modstk(savcsp); /* delete local variable space */
stkp=savcsp;
#ifdef STGOTO
cptr=savloc; /* retain labels */
while(cptr < locptr) {
cptr2=nextsym(cptr);
if(cptr[ident] == LABEL) {
while(cptr < cptr2) *savloc++ = *cptr++;
}
else cptr=cptr2;
}
#endif
declared = -1;
locptr=savloc;
statptr=savstat;
}
/* */
/* "if" statement */
/* */
doif()
{
int flev,fsp,flab1,flab2;
flev=locptr; /* record current local level */
fsp=stkp; /* record current stk ptr */
flab1=getlabel(); /* get label for false branch */
test(flab1,YES); /* get expression, and branch false */
statement(); /* if true, do a statement */
stkp=modstk(fsp); /* then clean up the stack */
locptr=flev; /* and deallocate any locals */
if (amatch("else",4)==0) /* if...else ? */
/* simple "if"...print false label */
{postlabel(flab1);
return; /* and exit */
}
/* an "if...else" statement. */
flab2=getlabel();
#ifdef STGOTO
if((lastst != streturn)&&(lastst != STGOTO) jump(flab2);
#else
if(lastst != streturn) jump(flab2); /* jump around false code */
#endif
postlabel(flab1); /* print false label */
statement(); /* and do "else" clause */
stkp=modstk(fsp); /* then clean up stk ptr */
locptr=flev; /* and deallocate locals */
postlabel(flab2); /* print true label */
}
/* */
/* "while" statement */
/* */
dowhile()
{
int lwq[4]; /* allocate local queue */
addwhile(lwq); /* add entry to queue */
/* (for "break" statement) */
postlabel(lwq[wqloop]); /* loop label */
test(lwq[wqlab],YES); /* see if true */
statement(); /* if so, do a statement */
jump(lwq[wqloop]); /* loop to label */
postlabel(lwq[wqlab]); /* exit label */
delwhile(); /* delete queue entry */
}
/* */
/* "return" statement */
/* */
doreturn()
{
/* if not end of statement, get an expression */
if(endst()==0)doexpression();
modstk(0); /* clean up stk */
ret(); /* and exit function */
}
/* */
/* "break" statement */
/* */
dobreak()
{
int *ptr;
/* see if any "whiles" are open */
if ((ptr=readwhile())==0) return; /* no */
modstk((ptr[wqsp])); /* else clean up stk ptr */
jump(ptr[wqlab]); /* jump to exit label */
}
/* */
/* "continue" statement */
/* */
docont()
{
int *ptr;
/* see if any "whiles" are open */
if ((ptr=readwhile())==0) return; /* no */
modstk((ptr[wqsp])); /* else clean up stk ptr */
jump(ptr[wqloop]); /* jump to loop label */
}
/* */
/* "asm" pseudo-statement */
/* */
/* enters mode where assembly language statement are */
/* passed intact through parser */
doasm()
{
cmode=0; /* mark mode as "asm" */
while (1)
{inline(); /* get and print lines */
if(eof) break;
if (match("#endasm")){
if (ctext){
comment();
outstr(line);
}
break; /* until... */
}
outstr(line);
nl();
}
kill(); /* invalidate line */
cmode=1; /* then back to parse level */
}