/************************************************/ /* */ /* small-c compiler */ /* */ /* Version 2.0 (mod 2) */ /* */ /* by Ron Cain */ /* */ /* modified by Charles L. Athey, III */ /* Ed Hirgelt */ /* */ /* last revision: 1 Jan 81 */ /* */ /************************************************/ #include cc.def/1 /* */ /* Compiler begins execution here */ /* */ #asm debug equ 0 Disable debugging logic if debug org 100h dw symtab symbol table address dw wq while queue dw litq literal queue dw macq macro queue dw line processing line endf #endasm /* Now reserve some storage words */ char symtab[symtbsz]; /* symbol table */ char *glbptr,*locptr; /* ptrs to next entries */ int wq[wqtabsz]; /* while queue */ int *wqptr; /* ptr to next entry */ char litq[litabsz]; /* literal pool */ int litptr; /* ptr to next entry */ char macq[macqsize]; /* macro string buffer */ int macptr; /* and its index */ char line[linesize]; /* parsing buffer */ char mline[linesize]; /* temp macro buffer */ int lptr,mptr; /* ptrs into each */ /* Misc storage */ int nxtlab, /* next avail label # */ litlab, /* label # assigned to literal pool */ xsp, /* compiler relative stk ptr */ argstk, /* function arg sp */ ncmp, /* # open compound statements */ errcnt, /* # errors in compilation */ eof, /* set non-zero on final input eof */ input, /* iob # for input file */ output, /* iob # for output file (if any) */ input2, /* iob # for "include" file */ glbflag, /* non-zero if internal globals */ ctext, /* non-zero to intermix c-source */ cmode, /* non-zero while parsing c-code */ /* zero when passing assembly code */ lastst; /* last executed statement type */ char quote[2]; /* literal string for '"' */ char *cptr; /* work ptr to any char buffer */ int *iptr; /* work ptr to any int buffer */ char prefix[MAXPREFIX]; /* label prefix */ main(argc,argv) int argc; int argv[]; { if(argc <= 1) { pl("Usage: cc input [-c] [-lcc] [-nnn] [>output]"); exit(); } glbptr=startglb; /* clear global symbols */ locptr=startloc; /* clear local symbols */ wqptr=wq; /* clear while queue */ macptr= /* clear the macro pool */ litptr= /* clear literal pool */ xsp= /* stack ptr (relative) */ errcnt= /* no errors */ eof= /* not eof yet */ input= /* no input file */ input2= /* or include file */ output= /* no open units */ ncmp= /* no open compound states */ glbflag= /* to include initialization code */ lastst= 0; /* no last statement yet */ quote[1]= 0; quote[0]='"'; /* fake a quote literal */ prefix[0] = prefix[1] = 'c'; prefix[2] = 0; cmode=1; /* enable preprocessing */ /* compiler body */ ask(argc,argv); /* get user options */ openout(argc,argv); /* get an output file */ openin(argc,argv); /* and initial input file */ kill(); /* Initialize input line */ header(); /* intro code */ parse(); /* process ALL input */ dumplits(); /* then dump literal pool */ dumpglbs(); /* and all static memory */ errorsummary(); /* summarize errors */ trailer(); /* follow-up code */ closeout(); /* close the output (if any) */ errorsummary(); /* summarize to terminal */ outstr("Last label used "); outdec(nxtlab); nl(); nl(); return; /* then exit to system */ } /* */ /* 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("char",4)){declglb(cchar,statik); ns();} else if(amatch("int",3)){declglb(cint,statik); ns();} else if(amatch("extern",6)){declext();ns();} else if(match("#asm"))doasm(); else if(match("#include"))doinclude(); else if(match("#define"))addmac(); else newfunc(); blanks(); /* force eof if pending */ } } /* */ /* Dump the literal pool */ /* */ dumplits() {int j,k; if (litptr==0) return; /* if nothing there, exit...*/ printlabel(litlab);col(); /* print literal label */ nl(); /* add for PTDOS ASSeMbler */ k=0; /* init an index... */ while (k=litptr)) {nl(); /* need */ break; } outbyte(','); /* separate bytes */ } } } /* ==================================== */ /* Dump all static variables */ /* ==================================== */ dumpglbs() { int j; for(cptr = startglb; cptr < glbptr; cptr = cptr + symsiz) { if(cptr[storage] == xtern) { outstr(";external "); outstr(cptr); nl(); } else if(cptr[ident] != function) { if(cptr[storage] == hidden) { iptr = &cptr[inname]; /* Internal label */ printlabel(*iptr); } else outstr(cptr); col(); nl(); defstorage(); iptr = &cptr[offset]; j = *iptr; if(cptr[type] == cint || cptr[ident] == pointer) j = j + j; outdec(j); nl(); } } /* for each symbol table entry */ } /* dumpglbs */ /* ==================================== */ /* Report errors for user */ /* ==================================== */ errorsummary() { /* see if anything left hanging... */ if (ncmp) error("missing closing bracket"); /* open compound statement ... */ nl(); comment(); outdec(errcnt); /* total # errors */ outstr(" errors in compilation."); nl(); } /* ==================================== */ /* Get options from user */ /* ==================================== */ ask(argc,argv) int argc; int argv[]; { int i,j; char *s; ctext = 0; /* do not include C source */ nxtlab = 0; /* labels start at 0 */ for(i = 1; i < argc; ++i) { s = argv[i]; if(*s != '-') /* not an option */ continue; ++s; if(*s =='c' || *s == 'C') ctext = 1; else if(*s == 'l' || *s == 'L') { ++s; j = 0; while(*s) if( j >= MAXPREFIX-1) break; else prefix[j++] = *(s++); prefix[j] = 0; } else if(numeric(*s)) { nxtlab = *s - '0'; while(numeric(*(++s))) nxtlab = nxtlab*10 + *s - '0'; } } /* end for each argument */ litlab = getlabel(); } /* ask */ /* */ /* Get output filename */ /* */ openout(argc, argvc) int argc; int argv[]; { int i; char *s; output = 0; /* default to terminal */ for( i= 1; i < argc; ++i) { s = argv[i]; if(*s != '>') continue; ++s; if((output = fopen(s,"w")) <= 0 ) { output = 0; pl("Unable to create output file"); exit(); } return; } /* for each argument */ } /* openout */ /* */ /* Get (next) input file */ /* */ openin(argc,argv) int argc; int argv[]; { int i; char *s; input = 0; for( i=1; i < argc; ++i) { s = argv[i]; if(*s =='-') continue; else if(*s == '>') continue; if((input = fopen(s,"r")) <= 0 ) { pl("Unable to open input file"); exit(); } } /* for each argument */ } /* openin */ /* */ /* Open an include file */ /* */ doinclude() { blanks(); /* skip over to name */ if((input2=fopen(line+lptr,"r"))==NULL) {input2=0; error("Open failure on include file"); } kill(); /* clear rest of line */ /* so next read will come from */ /* new file (if open */ } /* */ /* Close the output file */ /* */ closeout() { if(output)fclose(output); /* if open, close it */ output=0; /* mark as closed */ } /* */ /* Declare a static variable */ /* (i.e. define for use) */ /* */ /* makes an entry in the symbol table so subsequent */ /* references can call symbol by name */ declglb(typ,stg) /* typ is cchar or cint */ int typ; char stg; { int k,j;char sname[namesize]; forever { forever { if(endst())return; /* do line */ k=1; /* assume 1 element */ if(match("*")) /* pointer ? */ j=pointer; /* yes */ else j=variable; /* no */ if (symname(sname)==0) /* name ok? */ illname(); /* no... */ if(findglb(sname)) /* already there? */ multidef(sname); if (match("[")) { /* array? */ k=needsub(); /* get size */ j=array; } else if(match("(")) { /* function */ needbrack(")"); j = function; stg = xtern; } addglb(sname,j,typ,k,stg); /* add sym */ break; } if (match(",")==0) return; /* more? */ } } /* */ /* Declare local variables */ /* (i.e. define for use) */ /* */ /* works just like "declglb" but modifies machine stack */ /* and adds symbol table entry with appropriate */ /* stack offset to find it again */ declloc(typ,stg) /* typ is cchar or cint */ int typ; char stg; { int k,j;char sname[namesize]; forever { forever { if(endst())return; if(match("*")) j=pointer; else j=variable; if (symname(sname)==0) illname(); if(findloc(sname)) multidef(sname); if (match("[")) { k=needsub(); j=array; if(typ==cint)k=k+k; } else if( match("(")) { needbrack(")"); j = function; stg = xtern; } else if((typ==cchar) &(j!=pointer)) k=1;else k=2; if(stg == stkloc) { /* change machine stack */ xsp=modstk(xsp-k); addloc(sname,j,typ,xsp, stg); } else /* not stack resident */ addloc(sname, j, typ, k, stg); break; } if (match(",")==0) return; } } declext() /* Declare externals */ { if(amatch("char",4)) { declglb(cchar,xtern); } else if( amatch("int", 3)) { declglb(cint, xtern); } blanks(); } /* declext */ decllex() /* Externals local to a routine */ { if(amatch("char",4)) declloc(cchar, xtern); else if(amatch("int",4)) declloc(cint, xtern); blanks(); } /* decllex */