/* ** execution begins here */ /* * there are four different versions of the beginning of the * main procedure, depending on the compiler used and whether * command line processing is used. */ #ifdef CMD_LINE #ifdef N_CMD_LN #ifdef FULLC main(argc, argv) int argc; char *argv[]; { #else /* FULLC */ main(argc, argv) int argc, argv[]; { #endif /* FULLC */ int ii; if (argc > MAXARGS) { lout("too many command arguments", stderr); abort(ERRCODE); } argcs=argc; ii = 0; while(argc--) argvs[ii++] = *argv++; /* make static copy of args */ #else /* N_CMD_LN */ /* * original command line processing. * NOTE: the function 'getarg' is not in the library * supplied with this distribution. */ main(argc, argv) int argc, *argv; { argcs=argc; argvs=argv; #endif /* N_CMD_LN */ #else /* CMD_LINE */ main() { #endif /* CMD_LINE */ sout("Small-C Ver. ", stderr); sout(VERSION, stderr); sout(" ", stderr); lout(DATE, stderr); #ifdef DYNAMIC swnext=alloc(SWTABSZ); swend=swnext+((SWTABSZ-SWSIZ)>>1); stage=alloc(STAGESIZE); stagelast=stage+STAGELIMIT; wq=alloc(WQTABSZ*BPW); litq=alloc(LITABSZ); #ifdef HASH macn=alloc(MACNSIZE); cptr=macn-1; while(++cptr < MACNEND) *cptr=0; #endif /* HASH */ macq=alloc(MACQSIZE); pline=alloc(LINESIZE); mline=alloc(LINESIZE); #else /* DYNAMIC */ swnext=swq; swend=swnext+SWTABSZ-SWSIZ; stagelast=stage+STAGELIMIT; #endif /* DYNAMIC */ swactive= /* not in switch */ stagenext= /* direct output mode */ iflevel= /* #if... nesting level = 0 */ skiplevel= /* #if... not encountered */ macptr= /* clear the macro pool */ csp = /* stack ptr (relative) */ errflag= /* not skipping errors till ";" */ eof= /* not eof yet */ ncmp= /* not in compound statement */ files= filearg= 0; quote[1]='\0'; func1= /* first function */ ccode=1; /* enable preprocessing */ wqptr=wq; /* clear while queue */ quote[0]='"'; /* fake a quote literal */ input=input2= EOF; /* * this is where the nitty-gritty begins */ ask(); /* get user options */ openin(); /* and initial input file */ preprocess(); /* fetch first line */ #ifdef DYNAMIC #ifdef HASH symtab=alloc(NUMLOCS*SYMAVG + NUMGLBS*SYMMAX); #else /* HASH */ symtab=alloc(NUMLOCS*SYMAVG); /* global space is allocated with each new entry */ #endif /* HASH */ #endif /* DYNAMIC */ #ifdef HASH cptr=STARTGLB-1; while(++cptr < ENDGLB) *cptr=0; #endif /* HASH */ glbptr=STARTGLB; glbflag=1; ctext=0; header(); /* intro code */ setops(); /* set values in op arrays */ parse(); /* process ALL input */ outside(); /* verify outside any function */ trailer(); /* follow-up code */ fclose(output); } /* ** process all input text ** ** At this level, only static declarations, ** defines, includes and function ** definitions are legal... */ parse() { while (eof==0) { if(amatch("extern", 6)) dodeclare(EXTERNAL); else if(dodeclare(STATIC)); 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(size) int size; { int j, k; k=0; while (k=litptr)) { nl(); break; } outbyte(','); } } } /* ** dump zeroes for default initial values */ dumpzero(size, count) int size, count; { int j; while (count > 0) { #ifdef POLL CCPOLL(1); /* allow program interruption */ #endif defstorage(size); j=30; while(j--) { outdec(0); if ((--count <= 0)|(j==0)) { nl(); break; } outbyte(','); } } } /* ** verify compile ends outside any function */ outside() { if (ncmp) error("no closing bracket"); } /* ** get run options */ #ifdef CMD_LINE ask() { int i; i=listfp=nxtlab=0; #ifdef C80 output=fout; /* V6 convention */ #else /* C80 */ output=stdout; /* V7 convention */ #endif /* C80 */ #ifdef OPTIMIZE optimize= #endif /* OPTIMIZE */ alarm=monitor=pause=m80flg=NO; line=mline; #ifdef N_CMD_LN while(++i < argcs) { line = argvs[i]; if (line[0] == '-') { switch (upper(line[1])) { case 'L': if (numeric(line[2]) & (line[3] <= ' ')) { listfp = line[2] - '0'; break; } else goto errcase; case 'A': alarm = YES; break; case 'M': monitor = YES; break; case 'C': m80flg = YES; break; case 'P': pause = YES; break; #ifdef OPTIMIZE case 'O': optimize = YES; break; #endif /* OPTIMIZE */ #ifndef LINK case 'B': { bump(0); bump(2); if(number(&nxtlab)) break; } /* fall through to error case */ #endif /* LINK */ errcase: default: sout("usage: cc [file]... [-c] [-m] [-a] [-p] [-l#]", stderr); #ifdef OPTIMIZE sout(" [-o]", stderr); #endif /* OPTIMIZE */ #ifndef LINK sout(" [-b#]", stderr); #endif /* LINK */ sout("\n", stderr); abort(ERRCODE); } } } #else /* N_CMD_LN */ /* ** use original input processing abortion */ while(getarg(++i, line, LINESIZE, argcs, argvs)!=EOF) { if(line[0]!='-') continue; if((upper(line[1])=='L')&(numeric(line[2]))&(line[3]<=' ')) { listfp=line[2]-'0'; continue; } if(line[2]<=' ') { if(upper(line[1])=='A') { alarm=YES; continue; } if(upper(line[1])=='M') { monitor=YES; continue; } if(upper(line[1]=='C') { m80flg=YES; continue; } #ifdef OPTIMIZE if(upper(line[1])=='O') { optimize=YES; continue; } #endif /* OPTIMIZE */ if(upper(line[1])=='P') { pause=YES; continue; } } #ifndef LINK if(upper(line[1])=='B') { bump(0); bump(2); if(number(&nxtlab)) continue; } #endif /* LINK */ sout("usage: cc [file]... [-c] [-m] [-a] [-p] [-l#]", stderr); #ifdef OPTIMIZE sout(" [-o]", stderr); #endif /* OPTIMIZE */ #ifndef LINK sout(" [-b#]", stderr); #endif /* LINK */ sout("\n", stderr); abort(ERRCODE); } #endif /* N_CMD_LN */ } #else /* CMD_LINE */ ask() { #ifdef OPTIMIZE optimize= #endif /* OPTIMIZE */ monitor=alarm=pause=m80flg=listfp=nxtlab=0; line=mline; while(1) { prompt("Output file: ", line, LINESIZE); if(output=fopen(line, "w")) break; else { sout("open error: ", stderr); lout(line, stderr); } } #ifndef LINK while(1) { prompt("Beginning label number: ", line, LINESIZE); bump(0); if(number(&nxtlab)) break; } #endif /* LINK */ while(1) { prompt("Monitor function headers? ", line, LINESIZE); if(upper(*line)=='Y') monitor=YES; else if(upper(*line)!='N') continue; break; } while(1) { prompt("Sound alarm on errors? ", line, LINESIZE); if(upper(*line)=='Y') alarm=YES; else if(upper(*line)!='N') continue; break; } while(1) { prompt("Pause on errors? ", line, LINESIZE); if(upper(*line)=='Y') pause=YES; else if(upper(*line)!='N') continue; break; } while(1) { prompt("Generate M80 code? ", line, LINESIZE); if(upper(*line)=='Y') m80flg=YES; else if(upper(*line)!='N') continue; break; } #ifdef OPTIMIZE while(1) { prompt("Optimize for size? ", line, LINESIZE); if(upper(*line)=='Y') optimize=YES; else if(upper(*line)!='N') continue; break; } #endif /* OPTIMIZE */ while(1) { prompt("Listing file descriptor: ", line, LINESIZE); if(numeric(*line)&(line[1]==NULL)) listfp = *line-'0'; else if(*line!=NULL) continue; break; } } #endif /* CMD_LINE */ /* ** get next input file */ openin() { input = EOF; line = pline; #ifdef CMD_LINE #ifdef N_CMD_LN while(++filearg < argcs) { line = argvs[filearg]; #else /* N_CMD_LN */ while(getarg(++filearg, line, LINESIZE, argcs, argvs)!=EOF) { #endif /* N_CMD_LN */ if(line[0]=='-') continue; #else /* CMD_LINE */ while(prompt("Input file: ", line, LINESIZE)) { #endif /* CMD_LINE */ if((input=fopen(line,"r"))==NULL) { sout("open error: ", stderr); lout(line, stderr); abort(ERRCODE); } files=YES; kill(); return; } if(files++) eof=YES; #ifdef C80 else input=fin; /* V6 convention */ #else else input=stdin; /* V7 convention */ #endif kill(); } #ifndef CMD_LINE prompt(msg, ans, anslen) char *msg, *ans; int anslen; { sout(msg, stderr); xgets(ans, anslen, stderr); } #endif /* CMD_LINE */ setops() { op2[00]= op[00]= zzor; /* heir5 */ op2[01]= op[01]= zzxor; /* heir6 */ op2[02]= op[02]= zzand; /* heir7 */ op2[03]= op[03]= zzeq; /* heir8 */ op2[04]= op[04]= zzne; op2[05]=ule; op[05]= zzle; /* heir9 */ op2[06]=uge; op[06]= zzge; op2[07]=ult; op[07]= zzlt; op2[08]=ugt; op[08]= zzgt; op2[09]= op[09]= zzasr; /* heir10 */ op2[10]= op[10]= zzasl; op2[11]= op[11]= zzadd; /* heir11 */ op2[12]= op[12]= zzsub; op2[13]= op[13]=zzmult; /* heir12 */ op2[14]= op[14]= zzdiv; op2[15]= op[15]= zzmod; }