/* >>>>> start cc1 <<<<<< */ /* 3/3/88 */ /* */ /* Compiler begins execution here */ /* */ main() { mainmode= litlab=1; hello(); /* greet user */ see(); /* determine options */ openin(); /* first file to process */ while (input!=0) /* process user files till he quits */ { extptr=startextrn; /* clear external symbols */ glbptr=startglb; /* clear global symbols */ locptr=startloc; /* clear local symbols */ wqptr=wq; /* clear while queue */ macptr= /* clear the macro pool */ litptr= /* clear literal pool */ Zsp = /* stack ptr (relative) */ errcnt= /* no errors */ eof= /* not end-of-file yet */ input2= /* no include file */ saveout= /* no diverted output */ ncmp= /* no open compound states */ lastst= /* no last statement yet */ cextern= /* no externs yet */ fnstart= /* current "function" started at line 0 gtf 7/2/80 */ lineno= /* no lines read from file gtf 7/2/80 */ infunc= /* not in function now gtf 7/2/80 */ quote[1]= 0; /* ...all set to zero.... */ quote[0]='"'; /* fake a quote literal */ currfn=NULL; /* no function yet gtf 7/2/80 */ cmode=nxtlab=1; /* enable preprocessing and reset label numbers */ openout(); header(); parse(); if (ncmp) error("missing closing bracket"); extdump(); dumpglbs(); dumplits(); trailer(); closeout(); errorsummary(); mainmode=0; openin(); } } /* */ /* Abort compilation */ /* gtf 7/17/80 */ abort() { if(input2) endinclude(); if(input) fclose(input); closeout(); toconsole(); pl("Compilation aborted."); nl(); exit(); } /* */ /* Process all input text */ /* */ /* At this level, only static declarations, */ /* defines, includes, and function */ /* definitions are legal... */ parse() { while (eof==0) /* do until no more input */ { if(amatch("extern",6)) { cextern=1; if(amatch("char",4)) {declglb(cchar);ns();} else if(amatch("int",3)) {declglb(cint);ns();} else {declglb(cint);ns();} cextern=0; } else if(amatch("char",4)){declglb(cchar);ns();} else if(amatch("int",3)){declglb(cint);ns();} else if(match("#asm"))doasm(); else if(match("#include"))doinclude(); else if(match("#define"))addmac(); else newfunc(); blanks(); /* force eof if pending */ } } extdump() { char *ptrext; ptrext=startextrn; while(ptrext=litptr)) {nl(); /* need */ break; } outbyte(','); /* separate bytes */ } } } /* */ /* Dump all static variables */ /* */ dumpglbs() { int j; if(mainmode) ol("SECTION THREE,BSS"); cptr=startglb; while (cptr>>>>> 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 */ {error("must be constant"); /* it isn't */ num[0]=1; /* so force one */ } if (num[0]<0) {error("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() { char n[namesize]; /* ptr => currfn, gtf 7/16/80 */ if (symname(n)==0) { if(eof==0) error("illegal function or declaration"); kill(); /* invalidate line */ return; } fnstart=lineno; /* remember where fn began gtf 7/2/80 */ infunc=1; /* note, in function now. gtf 7/16/80 */ if(currfn=findglb(n)) /* already in symbol table ? */ {if(currfn[ident]!=function)multidef(n); /* already variable by that name */ else if(currfn[offset]==function)multidef(n); /* already function by that name */ else currfn[offset]=function; /* otherwise we have what was earlier*/ /* assumed to be a function */ } /* if not in table, define as a function now */ else currfn=addglb(n,function,cint,function); toconsole(); /* gtf 7/16/80 */ outstr("====== "); outstr(currfn+name); outstr("()"); nl(); tofile(); /* we had better see open paren for args... */ if(match("(")==0)error("missing open paren"); ot("XDEF ");outname(n);nl(); outname(n);col();nl(); /* print function name */ argstk=0; /* init arg count */ while(match(")")==0) /* then count args */ /* any legal name bumps arg count */ {if(symname(n))argstk=argstk+4; else{error("illegal argument name");junk();} blanks(); /* if not closing paren, should be comma */ if(streq(line+lptr,")")==0) {if(match(",")==0) error("expected comma"); } if(endst())break; } locptr=startloc; /* "clear" local symbol table*/ Zsp=0; /* preset stack ptr */ while(argstk) /* now let user declare what types of things */ /* those arguments were */ {if(amatch("char",4)){getarg(cchar);ns();} else if(amatch("int",3)){getarg(cint);ns();} else{error("wrong number args");break;} } if(statement()!=streturn) /* do a statement, but if */ /* it's a return, skip */ /* cleaning up the stack */ {modstk(0); zret(); } Zsp=0; /* reset stack ptr again */ locptr=startloc; /* deallocate all locals */ infunc=0; /* not in fn. any more gtf 7/2/80 */ } /* */ /* Declare argument types */ /* */ /* called from "newfunc" this routine adds an entry in the */ /* local symbol table for each named argument */ getarg(idtype) /* idtype = cchar or cint */ int idtype; { char idname[namesize]; int idclass; while(1) {if(argstk==0)return; /* no more args */ if(match("*"))idclass=pointer; else idclass=argument; if(symname(idname)==0) illname(); if(findloc(idname))multidef(idname); if(match("[")) /* pointer ? */ /* it is a pointer, so skip all */ /* stuff between "[]" */ {while(inbyte()!=']') if(endst())break; idclass=pointer; /* add entry as pointer */ } addloc(idname,idclass,idtype,argstk); argstk=argstk-4; /* cnt down */ if(endst())return; if(match(",")==0)error("expected comma"); } } /* Statement parser */ /* */ /* called whenever syntax requires */ /* a statement. */ /* this routine performs that statement */ /* and returns a number telling which one */ statement() { /* comment out ctrl-C check since ctrl-break will work on PC */ /* if(cpm(11,0) & 1) */ /* check for ctrl-C gtf 7/17/80 */ /* if(getchar()==3) */ /* abort(); */ if ((ch()==0) & (eof)) return; else if(amatch("char",4)) {declloc(cchar);ns();} else if(amatch("int",3)) {declloc(cint);ns();} else if(match("{"))compound(); else if(amatch("if",2)) {doif();lastst=stif;} else if(amatch("while",5)) {dowhile();lastst=stwhile;} 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;} /* if nothing else, assume it's an expression */ else{expression();ns();lastst=stexp;} return lastst; } /* */ /* Semicolon enforcer */ /* */ /* called whenever syntax requires a semicolon */ ns() {if(match(";")==0)error("missing semicolon");} /* */ /* Compound statement */ /* */ /* allow any number of statements to fall between "{}" */ compound() { ++ncmp; /* new level open */ while (match("}")==0) statement(); /* do one */ --ncmp; /* close current level */ } /* */ /* "if" statement */ /* */ doif() { int flev,fsp,flab1,flab2; flev=locptr; /* record current local level */ fsp=Zsp; /* record current stk ptr */ flab1=getlabel(); /* get label for false branch */ test(flab1); /* get expression, and branch false */ statement(); /* if true, do a statement */ Zsp=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 */ {printlabel(flab1);col();nl(); return; /* and exit */ } /* an "if...else" statement. */ jump(flab2=getlabel()); /* jump around false code */ printlabel(flab1);col();nl(); /* print false label */ statement(); /* and do "else" clause */ Zsp=modstk(fsp); /* then clean up stk ptr */ locptr=flev; /* and deallocate locals */ printlabel(flab2);col();nl(); /* print true label */ } /* */ /* "while" statement */ /* */ dowhile() { int wq[4]; /* allocate local queue */ wq[wqsym]=locptr; /* record local level */ wq[wqsp]=Zsp; /* and stk ptr */ wq[wqloop]=getlabel(); /* and looping label */ wq[wqlab]=getlabel(); /* and exit label */ addwhile(wq); /* add entry to queue */ /* (for "break" statement) */ printlabel(wq[wqloop]);col();nl(); /* loop label */ test(wq[wqlab]); /* see if true */ statement(); /* if so, do a statement */ Zsp = modstk(wq[wqsp]); /* zap local vars: 9/25/80 gtf */ jump(wq[wqloop]); /* loop to label */ printlabel(wq[wqlab]);col();nl(); /* exit label */ locptr=wq[wqsym]; /* deallocate locals */ delwhile(); /* delete queue entry */ } /* */ /* */ /* "return" statement */ /* */ doreturn() { /* if not end of statement, get an expression */ if(endst()==0)expression(); modstk(0); /* clean up stk */ zret(); /* 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 (match("#endasm")) break; /* until... */ if(eof)break; outstr(line); nl(); } kill(); /* invalidate line */ cmode=1; /* then back to parse level */ }