IMD 1.18: 22/01/1996 5:53:32 micro cornucopia kaypro user group disk 8 small c version 2 source     CC11 C R CC21 C 1CC12 C ?CC42 C E !"#$%&CC DEF '()*CC41 BAK1+,-./01CC13 C ;23456789CC22 C F:;<=>?@ABCC4 C CCC31 C BDEFGHIJKLCC32 C +MNOPQRCC33 C $STUVWCC1 C -XYZ[\]CC3 C ^_CC2 C `aCRCKLISTCRCb /* ** 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; IOLIB MACcdefghijklmnopqrIOLIB MACJstuvwxyz{|CALL MAC.}~CRC COMCC41 C 1D COMSMC COMSMC COMSMC COM 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); #i  fdef DYNAMIC swnext=CCALLOC(SWTABSZ); swend=swnext+((SWTABSZ-SWSIZ)>>1); stage=CCALLOC(STAGESIZE); stagelast=stage+STAGELIMIT; wq=CCALLOC(WQTABSZ*BPW); litq=CCALLOC(LITABSZ); #ifdef HASH macn=CCALLOC(MACNSIZE); cptr=macn-1; while(++cptr < MACNEND) *cptr=0; #endif /* HASH */ macq=CCALLOC(MACQSIZE); pline=CCALLOC(LINESIZE); mline=CCALLOC(LINESIZE); #else /* DYNAMIC */ swnext=swq; swend=swnext+SWTABSZ-SWSIZ; stagelast=stage+STAGELIMIT; #endif /* DYNAMIC */ } } /* ** 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; { */ symtab=CCALLOC(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 */  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': if (numeric(line[2]) & (line[3] <= ' ')) { bump(0); 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; 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 C8fclose(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 */  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); }  /* 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 SMALL_VM fopen(" ",NULL);/* pre-alloc FCB for include file */ #endif #ifdef DYNAMIC #ifdef HASH symtab=CCALLOC(NUMLOCS*SYMAVG + NUMGLBS*SYMMAX); #else /* HASH 0 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 /* 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(l } #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) { #end } #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; } 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; } ine[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 if /* 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  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;  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); } 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]=    junk() { if(an(inbyte())) while(an(ch)) gch(); else while(an(ch)==0) { if(ch==0) break; gch(); } blanks(); } endst() { blanks(); return ((streq(lptr,";")|(ch==0))); } illname() { error("illegal symbol"); junk(); } multidef(sname) char *sname; { error("already defined"); } needtoken(str) char *str; { if (match(str)==0) error("missing token"); } needlval() { error("must be lvalue"); } findglb(sname) char *sname; { #ifdef en) char *addr; int len; { int i; i = *(addr + --len); /* high order byte sign extended */ while(len--) i = (i << 8) | *(addr+len)&255; return i; } /* ** put integer i of length len into address addr ** (low byte first) */ putint(i, addr, len) char *addr; int i, len; { while(len--) { *addr++ = i; i = i>>8; } } /* ** test if next input string is legal symbol name */ symname(sname, ucase) char *sname; int ucase; { int k;char c; blanks(); if(alpha(ch)=SH */ } else { if(locptr > (ENDLOC-SYMMAX)) { error("local symbol table overflow"); abort(ERRCODE); } cptr = *lgptrptr; } cptr[IDENT]=id; cptr[TYPE]=typ; cptr[CLASS]=class; putint(value, cptr+OFFSET, OFFSIZE); cptr3 = cptr2 = cptr + NAME; while(an(*sname)) *cptr2++ = *sname++; #ifdef HASH if(lgptrptr == &locptr) { *cptr2 = cptr2 - cptr3; /* set length */ *lgptrptr = ++cptr2; } #else /* HASH */ *cptr2 = cptr2 - cha(c))|(numeric(c))); } addwhile(ptr) int ptr[]; { int k; ptr[WQSP]=csp; /* and stk ptr */ ptr[WQLOOP]=getlabel(); /* and looping label */ ptr[WQEXIT]=getlabel(); /* and exit label */ if (wqptr==WQMAX) { error("too many active loops"); abort(ERRCODE); } k=0; while (k wq) wqptr=wqptr-WQSIZ; } readwhile(ptr) int *ptr; { /* ** patched per DDJ *HASH if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME)) return cptr; #else /* HASH */ cptr=STARTGLB; while(cptr < glbptr) { if(astreq(sname, cptr+NAME, NAMEMAX)) return cptr; cptr=nextsym(cptr); } #endif /* HASH */ return 0; } findloc(sname) char *sname; { cptr = locptr - 1; /* search backward for block locals */ while(cptr > STARTLOC) { cptr = cptr - *cptr; if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME); cptr = cptr - NAME - 1=0) return 0; k=0; while(an(ch)) { #ifdef UPPER if(ucase) sname[k]=upper(gch()); else #endif /* UPPER */ sname[k]=gch(); if(k= 'a') & (c <= 'z')) return (c - 32); else return c; } /* ** return next avail internal label number */ getlabel() { return(++nxtlab); } /* ** post a label in the program */ postlabel(label) inptr3; /* set length */ *lgptrptr = ++cptr2; #ifdef DYNAMIC if(lgptrptr == &glbptr) CCALLOC(cptr2 - cptr); /* gets allocation error if no more memory */ #endif /* DYNAMIC */ #endif /* HASH */ return cptr; } #ifndef HASH nextsym(entry) char *entry; { entry = entry + NAME; while(*entry++ >= ' '); /* find length byte */ return entry; } #endif /* HASH */ /* ** get integer of length len from address addr ** (byte sequence set by "putint") */ getint(addr, l/ if (ptr <= wq) { error("out of context"); return 0; } else return (ptr-WQSIZ); } white() { /* test for stack/program overlap */ /* primary -> symname -> blanks -> white */ #ifdef DYNAMIC CCAVAIL(); /* abort on stack/symbol table overflow */ #endif /* DYNAMIC */ if(*lptr==' ') return 1; if(*lptr==9) return 1; return 0; } gch() { int c; if(c=ch) bump(1); return c; } bump(n) int n; { if(n) lptr=lptr+n; else lptr=line; if(ch =; } return 0; } addsym(sname, id, typ, value, lgptrptr, class) char *sname, id, typ; int value, *lgptrptr, class; { if(lgptrptr == &glbptr) { if(cptr2=findglb(sname)) return cptr2; #ifdef HASH if(cptr==0) { error("global symbol table overflow"); return 0; } #else /* HASH */ #ifndef DYNAMIC if(glbptr >= ENDGLB) { error("global symbol table overflow"); return 0; } #endif /* DYNAMIC */ cptr = *lgptrptr; #endif /* HAt label; { printlabel(label); col(); nl(); } /* ** print specified number as a label */ printlabel(label) int label; { outstr("CC"); outdec(label); } /* ** test if given character is alphabetic */ alpha(c) char c; { return (((c>='a')&(c<='z'))|((c>='A')&(c<='Z'))|(c=='_')); } /* ** test if given character is numeric */ numeric(c) char c; { return((c>='0')&(c<='9')); } /* ** test if given character is alphanumeric */ an(c) char c; { return ((alp   nch = *lptr) nch = *(lptr+1); } kill() { *line=0; bump(0); } inbyte() { while(ch==0) { if (eof) return 0; preprocess(); } return gch(); } inline() { int k,unit; #ifdef FULLC char *xgets(); #endif /* FULLC */ #ifdef POLL CCPOLL(1); /* allow program interruption */ #endif /* POLL */ while(1) { if (input == EOF) openin(); if(eof) return; if((unit=input2) == EOF) unit=input; if(xgets(line, LINEMAX, unit)==NULL) { fcltr == '<')) { i = 0; fname = buff; while (i<14) { c = *++lptr; if ((c == '"') | (c == '>')) i = 14; /* force exit from loop */ else *fname++ = c; } *fname = '\0'; fname = buff; } else fname = lptr; /* no '"' or '<' (original convention) */ if((input2=fopen(fname,"r"))==NULL) { input2= EOF; error("open failure on include file"); } kill(); /* clear rest of line */ /* so next read will EXTERNAL) external(ssname); else j=initials(type>>2, j, k); addsym(ssname, j, type, k, &glbptr, class); if (match(",")==0) return; /* more? */ } } /* ** declare local variables */ declloc(typ) int typ; { int k,j; #ifdef STGOTO if(noloc) error("not allowed with goto"); #endif /* STGOTO */ if(declared < 0) error("must declare first in block"); while(1) { while(1) { if(endst()) return; if(match("*")) j=POINTER; else j=VARIABLE; iose(unit); if(input2 != EOF) input2 = EOF; else input = EOF; } else { bump(0); return; } } } /* * special version of 'fgets' that deletes trailing '\n' */ #ifdef FULLC char * xgets(string, len, fd) char *string; int len, fd; { #else /* FULLC */ xgets(string, len, fd) char *string; int len, fd; { #endif /* FULLC */ char c, *strptr; strptr = string; while ((((c = getc(fd)) & 127) != '\n') && (--len)) { if (c == EOF) return Ncome from */ /* new file (if open) */ } /* ** test for global declarations */ dodeclare(class) int class; { if(amatch("char",4)) { declglb(CCHAR, class); ns(); return 1; } else if((amatch("int",3))|(class==EXTERNAL)) { declglb(CINT, class); ns(); return 1; } return 0; } /* ** declare a static variable */ declglb(type, class) int type, class; { int k, j; while(1) { if(endst()) return; /* do line */ if(match("*")) { /* ** open an include file */ doinclude() { char c, *fname, buff[15]; int i; /* * test for nested includes added 4/7/83 br. * (this may be buried somewhere else, but I don't see it) */ if(input2 != EOF) { error("nested include files not allowed"); kill(); /* ignore rest of line */ return; } blanks(); /* skip over to name */ /* * added code to handle include filename in quotes or brackets * 4/5/83 br */ if ((*lptr == '"') | (*lpf (symname(ssname, YES)==0) illname(); /* no multidef check, block-locals are together */ k=BPW; if (match("[")) { k=needsub(); if(k) { /* * check for `*var[nn]' 4/7/83 br */ if (j==POINTER) error("declaration type not allowed"); j=ARRAY; if(typ==CINT)k=k< 9000)) #endif /* LINK */ { ol("CC9997:JMP CCBOJ"); ol("CC9998:DS 6"); IZE 101 /* ** command line */ #define MAXARGS 32 /* maximum number of option arguments */ /* ** output staging buffer size */ #define STAGESIZE 800 #define STAGELIMIT (STAGESIZE-1) /* ** macro (define) pool */ #ifdef HASH #define MACNBR 90 #define MACNSIZE 990 /* 90*(NAMESIZE+2) */ #define MACNEND (macn+MACNSIZE) #define MACQSIZE 450 /* 90*5 */ #else /* HASH */ #define MACQSIZE 950 #endif /* HASH */ #define MACMAX (MACQSIZE-1) /* ** statement types */ #"CCGCHAR"); else call("CCGINT"); } /* ** fetch a static memory cell into primary register */ getmem(lval) int lval[]; { char *sym; sym=lval[0]; if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) { ot("LDA "); outstr(sym+NAME); nl(); call("CCSXT"); } else { ot("LHLD "); outstr(sym+NAME); nl(); } } /* ** fetch addr of the specified symbol into primary register */ getloc(sym) char *sym; { const(getint(sym+OFFSET, OFFSIZE /* ** possible entries for "IDENT" */ #define LABEL 0 #define VARIABLE 1 #define ARRAY 2 #define POINTER 3 #define FUNCTION 4 /* ** possible entries for "TYPE" ** low order 2 bits make type unique within length ** high order bits give length of object */ /* LABEL 0 */ #define CCHAR (1<<2) #define CINT (BPW<<2) /* ** possible entries for "CLASS" */ /* LABEL 0 */ #define STATIC 1 #define AUTOMATIC 2 #define EXTERNAL 3 /* ** "switch" table  ol("PUSH D"); ol("LXI D,$+6"); ol("JMP CC9997"); ol("ORG CC9998"); ol("JMP $+6"); } #endif /* SMALL_VM */ ol("END"); } /* ** load # args before function call */ loadargc(val) int val; { #ifdef HASH if(search("NOCCARGC", macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) { #else /* HASH */ if(findmac("NOCCARGC")==0) { #endif /* HASH */ ot("MVI A,"); outdec(val); nl(); } } /* ** declare entry point */ entry() { outstr(ssname);   )-csp); ol("DAD SP"); } /* ** store primary register into static cell */ putmem(lval) int lval[]; { char *sym; sym=lval[0]; if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) { ol("MOV A,L"); ot("STA "); } else ot("SHLD "); outstr(sym+NAME); nl(); } /* ** put on the stack the type object in primary register */ putstk(lval) int lval[]; { if(lval[1]==CCHAR) { ol("MOV A,L"); ol("STAX D"); } else call("CCPINT"); } /* ** move primary re jump(label) int label; { ot("JMP "); printlabel(label); nl(); } /* ** test primary register and jump if false */ testjump(label) int label; { ol("MOV A,H"); ol("ORA L"); ot("JZ "); printlabel(label); nl(); } /* ** test primary register against zero and jump if false */ #ifdef FULLC zerojump(oper, label, lval) int (*oper)(), label, lval[]; { clearstage(lval[7], 0); /* purge conventional code */ (*oper)(label); } #else /* FULLC */ zerojump(oper, label, > dest) { /* adjust stack references */ #ifdef TAB if(streq(sour,"\tDAD SP")) { #else /* TAB */ if(streq(sour," DAD SP")) { #endif /* TAB */ --sour; i=BPW; while(numeric(*(--sour))) { if((*sour = *sour-i) < '0') { *sour = *sour+10; i=1; } else i=0; } } } csp=csp+BPW; } /* ** pop stack to the secondary register */ pop() { ol("POP D"); csp=csp+BPW; } /* ** swap primary register */ doublereg() {ol("DAD H");} ); ol("SPHL"); if(save) swap(); return newsp; } /* ** double primary registgister to secondary */ move() { ol("MOV D,H"); ol("MOV E,L"); } /* ** swap primary and secondary registers */ swap() { ol("XCHG;;"); /* peephole() uses trailing ";;" */ } /* ** partial instruction to get immediate value ** into the primary register */ immed() { ot("LXI H,"); } /* ** partial instruction to get immediate operand ** into secondary register */ immed2() { ot("LXI D,"); } /* ** push primary register onto stack */ push() { ol("PUSH H");  lval) int oper, label, lval[]; { clearstage(lval[7], 0); /* purge conventional code */ oper(label); } #endif /* FULLC */ /* ** define storage according to size */ defstorage(size) int size; { if(size==1) ot("DB "); else ot("DW "); } /* ** point to following object(s) */ point() { ol("DW $+2"); } /* ** modify stack pointer to value given */ modstk(newsp, save) int newsp, save; { int k; k=newsp-csp; if(k==0)return newsp; if(k>=0) { if(k<7) er and stack */ swapstk() { ol("XTHL"); } /* ** process switch statement */ sw() { call("CCSWITCH"); } /* ** call specified subroutine name */ call(sname) char *sname; { ot("CALL "); outstr(sname); nl(); } /* ** return from subroutine */ ret() { ol("RET"); } /* ** perform subroutine call to value on stack */ callstk() { immed(); outstr("$+5"); nl(); swapstk(); ol("PCHL"); csp=csp+BPW; } /* ** jump to internal label number */  csp=csp-BPW; } /* ** unpush or pop as required */ smartpop(lval, start) int lval[]; char *start; { if(lval[5]) pop(); /* secondary was used */ else unpush(start); } /* ** replace a push with a swap */ unpush(dest) char *dest; { int i; char *sour; #ifdef TAB sour="\tXCHG;;"; /* peephole() uses trailing ";;" */ #else /* TAB */ sour=" XCHG;;"; /* peephole() uses trailing ";;" */ #endif /* TAB */ while(*sour) *dest++ = *sour++; sour=stagenext; while(--sour{ if(k&1) { ol("INX SP"); k--; } while(k) { ol("POP B"); k=k-BPW; } return newsp; } } if(k<0) { if(k>-7) { if(k&1) { ol("DCX SP"); k++; } while(k) { ol("PUSH B"); k=k+BPW; } return newsp; } } if(save) swap(); const(k); ol("DAD SP"); ol("SPHL"); if(save) swap(); return newsp; } /* ** double primary regist   /* ** statement parser ** ** called whenever syntax requires a statement ** this routine performs that statement ** and returns a number telling which one */ statement() { if ((ch==0) & (eof)) return; else if(amatch("char",4)) {declloc(CCHAR);ns();} else if(amatch("int",3)) {declloc(CINT);ns();} else { if(declared >= 0) { #ifdef STGOTO if(ncmp > 1) nogo=declared; /* disable goto if any */ #endif /* STGOTO */ csp=modstk(csp - declared, NO); declared =/* may not declare variables */ } doif() { int flab1,flab2; flab1=getlabel(); /* get label for false branch */ test(flab1, YES); /* get expression, and branch false */ statement(); /* if true, do a statement */ if (amatch("else",4)==0) { /* if...else ? */ /* simple "if"...print false label */ postlabel(flab1); return; /* and exit */ } flab2=getlabel(); #ifdef STGOTO if((lastst != STRETURN)&(lastst != STGOTO)) jump(flab2); #else /* STGOTO TASM;} else {doexpr();ns();lastst=STEXPR;} } return lastst; } /* ** semicolon enforcer ** ** called whenever syntax requires a semicolon */ ns() { if(match(";")==0) error("no semicolon"); else errflag=0; } compound() { int savcsp; char *savloc; savcsp=csp; savloc=locptr; declared=0; /* may now declare local variables */ ++ncmp; /* new level open */ while (match("}")==0) if(eof) { error("no final }"); abel(wq[WQLOOP]); test(wq[WQEXIT], YES); jump(top); postlabel(wq[WQEXIT]); delwhile(); ns(); } #endif /* STDO */ #ifdef STFOR dofor() { int wq[4], lab1, lab2; addwhile(wq); lab1=getlabel(); lab2=getlabel(); needtoken("("); if(match(";")==0) { doexpr(); /* expr 1 */ ns(); } postlabel(lab1); if(match(";")==0) { test(wq[WQEXIT], NO); /* expr 2 */ ns(); } jump(lab2); postlabel(wq[WQLOOP]); if(match(")")==0) { d -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 /* STDO */ #ifdef STFOR else if(amatch("for",3)) {dofor();lastst=STFOR;} #endif /* STFOR */ #ifdef STSWITCH else if(amatch("switch",6)) {doswitch();lastst=STSWITCH;} else if(amatch("case",4)) {docase();lastst=STCASE;} el*/ if(lastst != STRETURN) jump(flab2); #endif /* STGOTO */ postlabel(flab1); /* print false label */ statement(); /* and do "else" clause */ postlabel(flab2); /* print true label */ } doexpr() { int const, val; char *before, *start; while(1) { setstage(&before, &start); expression(&const, &val); clearstage(before, start); if(ch != ',') break; bump(1); } } dowhile() { /* ** patched per DDJ */ int wq[4]; /* alloca break; } else statement(); /* do one */ --ncmp; /* close current level */ csp=modstk(savcsp, NO); /* delete local variable space */ #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 /* STGOTO */ locptr=savloc; /* delete local symbols */ declared = -1; oexpr(); /* expr 3 */ needtoken(")"); } jump(lab1); postlabel(lab2); statement(); jump(wq[WQLOOP]); postlabel(wq[WQEXIT]); delwhile(); } #endif /* STFOR */ #ifdef STSWITCH doswitch() { int wq[4], endlab, swact, swdef, *swnex, *swptr; swact=swactive; swdef=swdefault; swnex=swptr=swnext; addwhile(wq); *(wqptr + WQLOOP - WQSIZ) = 0; needtoken("("); doexpr(); /* evaluate switch expression */ needtoken(")"); swdefault=0; swactivse if(amatch("default",7)) {dodefault();lastst=STDEF;} #endif /* STSWITCH */ #ifdef STGOTO else if(amatch("goto", 4)) {dogoto(); lastst=STGOTO;} else if(dolabel()) ; #endif /* STGOTO */ 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(";")) errflag=0; else if(match("#asm")) {doasm();lastst=Ste local queue */ addwhile(wq); /* add entry to queue for "break" */ postlabel(wq[WQLOOP]); /* loop label */ test(wq[WQEXIT], YES); /* see if true */ statement(); /* if so, do a statement */ jump(wq[WQLOOP]); /* loop to label */ postlabel(wq[WQEXIT]); /* exit label */ delwhile(); /* delete queue entry */ } #ifdef STDO dodo() { int wq[4], top; addwhile(wq); postlabel(top=getlabel()); statement(); needtoken("while"); postl  e=1; jump(endlab=getlabel()); statement(); /* cases, etc. */ jump(wq[WQEXIT]); 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[WQEXIT]); delwhile(); swnext=swnex; swdefault=swdef; swactive=swact; } n (getint(cptr+OFFSET, OFFSIZE)); } #endif /* STGOTO */ doreturn() { if(endst()==0) { doexpr(); modstk(0, YES); } else modstk(0, NO); ret(); } dobreak() { int *ptr; if ((ptr=readwhile(wqptr))==0) return; /* no loops open */ modstk((ptr[WQSP]), NO); /* clean up stk ptr */ jump(ptr[WQEXIT]); /* jump to exit label */ } docont() { int *ptr; ptr = wqptr; while (1) { if ((ptr=readwhile(ptr))==0) return; /* no loops ope if(skiplevel) continue; if(listfp) { if(listfp==output) cout(';', output); lout(line, listfp); } if(ch==0) continue; break; } } keepch(c) char c; { if(pptr swend) { error("too many cases"); return; } postlabel(*swnext++ = getlabel()); constexpr(swnext++); needtoken(":"); } dodefault() { if(swactive) { if(swdefault) error("multiple defaults"); } else error("not in switch"); needtoken(":"); postlabel(swdefault=getlabel()); } #endif /* STSWITCH */ #ifdef STGOTO dogoto() { if(nogo > 0) error("not allowed with block-locals"); else ifline() { while(1) { inline(); if(eof) return; if(match("#ifdef")) { ++iflevel; if(skiplevel) continue; blanks(); #ifdef HASH if(search(lptr, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) #else /* HASH */ if(findmac(lptr)==0) #endif /* HASH */ skiplevel=iflevel; continue; } if(match("#ifndef")) { ++iflevel; if(skiplevel) continue; blanks(); #ifdef HASH if(search(lptr, macn, NAMESIZE+2, MACNEn */ if (ptr[WQLOOP]) break; } modstk((ptr[WQSP]), NO); /* clean up stk ptr */ jump(ptr[WQLOOP]); /* jump to loop label */ } doasm() { ccode=0; /* mark mode as "asm" */ while (1) { inline(); if (match("#endasm")) break; if(eof)break; lout(line, output); } kill(); ccode=1; } ; } else if(ch=='"') { keepch(ch); gch(); while((ch!='"')|((*(lptr-1)==92)&(*(lptr-2)!=92))) { if(ch==0) { error("no quote"); break; } keepch(gch()); } gch(); keepch('"'); } else if(ch==39) { keepch(39); gch(); while((ch!=39)|((*(lptr-1)==92)&(*(lptr-2)!=92))) { if(ch==0) { error("no apostrophe"); break; } keepch(gch()) noloc = 1; if(symname(ssname, YES)) jump(addlabel()); else error("bad label"); ns(); } dolabel() { char *savelptr; blanks(); savelptr=lptr; if(symname(ssname, YES)) { if(gch()==':') { postlabel(addlabel()); return 1; } else bump(savelptr-lptr); } return 0; } addlabel() { if(cptr=findloc(ssname)) { if(cptr[IDENT]!=LABEL) error("not a label"); } else cptr=addsym(ssname, LABEL, LABEL, getlabel(), &locptr, LABEL); returND, MACNBR, 0)) #else /* HASH */ if(findmac(lptr)) #endif /* HASH */ skiplevel=iflevel; continue; } if(match("#else")) { if(iflevel) { if(skiplevel==iflevel) skiplevel=0; else if(skiplevel==0) skiplevel=iflevel; } else noiferr(); continue; } if(match("#endif")) { if(iflevel) { if(skiplevel==iflevel) skiplevel=0; --iflevel; } else noiferr(); continue; }   ; } gch(); keepch(39); } else if((ch=='/')&(nch=='*')) { bump(2); while(((ch=='*')&(nch=='/'))==0) { if(ch) bump(1); else { ifline(); if(eof) break; } } bump(2); } else if(an(ch)) { k=0; while(an(ch)) { if(k=1) { c=number/k + '0'; if ((c!='0')|(k==1)|(zs)) { zs=1; outbyte(c);  } } putmac(c) char c; { macq[macptr]=c; if(macptr= end) cptr=buf; if(cptr == cptr2) return (cptr=0); }  error\n", stderr); abort(ERRCODE); } #ifdef C80 abort(err) int err; { exit(); /* exit to CP/M */ } #endif /* C80 */ #ifdef C80 fputs(string, fd) char *string; int fd; { char c; while ((c = *string++) != NULL) { if (putc(c, fd) == EOF) return EOF; } return 0; } #endif /* C80 */ nl() { outbyte('\n'); } tab() { outbyte(TAB); } col() { #ifdef COL outbyte(':'); #else /* COL */ outbyte(' '); #endif /* COL */ } error(msg) char ms k=getint(cptr+NAMESIZE, 2); while(c=macq[k++]) keepch(c); } #else /* HASH */ if(k=findmac(msname)) while(c=macq[k++]) keepch(c); #endif /* HASH */ else { k=0; while(c=msname[k++]) keepch(c); } } else keepch(gch()); } if(pptr>=LINEMAX) error("line too long"); keepch(0); line=pline; bump(0); } noiferr() { error("no matching #if..."); errflag=0; } addmac() { int k; if(symname(msname, NO) } number=number%k; k=k/10; } } ol(ptr) char ptr[]; { ot(ptr); nl(); } ot(ptr) char ptr[]; { #ifdef TAB tab(); #else /* TAB */ outbyte(' '); #endif /* TAB */ outstr(ptr); } outstr(ptr) char ptr[]; { #ifdef POLL CCPOLL(1); /* allow program interruption */ #endif /* POLL */ /* must work with symbol table names terminated by length */ while(*ptr >= ' ') outbyte(*ptr++); } outbyte(c) char c; { if(stagenext) { if(stagenex return 0; } hash(sname) char *sname; { int i, c; i=0; while(c = *sname++) i=(i<<1)+c; return i; } #else /* HASH */ findmac(sname) char *sname; { mack=0; while(mack0) errout(msg, listfp); } errout(msg, fp) char msg[]; int fp; ==0) { illname(); kill(); return; } k=0; #ifdef HASH if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) { if(cptr2=cptr) while(*cptr2++ = msname[k++]); else { error("macro name table full"); return; } } putint(macptr, cptr+NAMESIZE, 2); #else /* HASH */ while(putmac(msname[k++])); #endif /* HASH */ while(white()) gch(); while(putmac(gch())); if(macptr>=MACMAX) { error("macro string queue full"); abort(ERRCODE);t==stagelast) { error("staging buffer overflow"); return 0; } else *stagenext++ = c; } else cout(c,output); return c; } cout(c, fd) char c; int fd; { #ifdef C80 if(putc(c, fd)==EOF) xout(); #else /* C80 */ if(fputc(c, fd)==EOF) xout(); #endif /* C80 */ } sout(string, fd) char *string; int fd; { if(fputs(string, fd)==EOF) xout(); } lout(line, fd) char *line; int fd; { sout(line, fd); cout('\n', fd); } xout() { fputs("output  { int k; k=line+2; while(k++ <= lptr) cout(' ', fp); lout("/\\", fp); sout("**** ", fp); lout(msg, fp); } streq(str1,str2) char str1[],str2[]; { /* check for string equality over whole string */ int k; k=0; while (str2[k]) { if ((str1[k])!=(str2[k])) return 0; ++k; } return k; } astreq(str1,str2,len) char str1[],str2[];int len; { /* check for string equality over first 'len' characters */ int k; k=0; while (k ' ') op[opsize++] = *list++; op[opsize]=0; if(opsize=streq(lptr, op)) if((*(lptr+opsize) != '=')& (*(lptr+opsize) != *(lptr+opsize-1))) return 1; if(*list) { ++list; ++opindex; } else return 0; } } blanks() { while(1) { while(ch) { testfunc, dropval, endval, heir, lval) char *opstr; #ifdef FULLC int (*testfunc)(), dropval, endval, (*heir)(), lval[]; { #else /* FULLC */ int testfunc, dropval, endval, heir, lval[]; { #endif /* FULLC */ int k, hits, droplab, endlab; hits=0; while(1) { k=plung1(heir, lval); if(nextop(opstr)) { bump(opsize); if(hits==0) { hits=1; droplab=getlabel(); } dropout(k, testfunc, droplab, lval); } else if(hits) {    if(k) rvalue(lval); while(1) { if(nextop(opstr)) { bump(opsize); opindex=opindex+opoff; plung2(op[opindex], op2[opindex], heir, lval, lval2); } else return 0; } } /* ** unary plunge to lower level ** renamed "plung1" (original was "plunge1") to have ** first 6 chars unique for M80 assembler. */ #ifdef FULLC plung1(heir, lval) int (*heir)(), lval[]; { #else /* FULLC */ plung1(heir, lval) int heir, lval[]; { #endif /* FULLC */ char *before, *r)(); #else /* FULLC */ oper(); #endif /* FULLC */ lval[6]= oper; /* identify the operator */ } else { #ifdef FULLC (*oper2)(); #else /* FULLC */ oper2(); #endif /* FULLC */ lval[6]= oper2; /* identify the operator */ } } if(oper==zzsub) { if((lval[2]==CINT)&(lval2[2]==CINT)) { swap(); const(1); zzasr(); /** div by 2 **/ } } if((oper==zzsub)|(oper==zzadd))heir, lval2)) rvalue(lval2); if(lval2[3]) { /* constant on right side */ if(lval2[4]==0) lval[7]=start; if(oper==zzadd) { /* may test other commutative operators */ csp=csp+2; clearstage(before, 0); const2(lval2[4]<>=")) oper= zzasr; else if(match("<<=")) oper= zzasl; else if(match("=")) oper= 0; else return k; if(k==0) { needlval(); return 0; } if(lval[1]) { if(oper) { push(); rvalue(lval); } plung2(oper, oper, heir1, lval, lval2); if(op oper2, heir, lval[], lval2[]; { #endif /* FULLC */ char *before, *start; setstage(&before, &start); lval[5]=1; /* flag secondary register used */ lval[7]=0; /* flag as not "... oper 0" syntax */ if(lval[3]) { /* constant on left side not yet loaded */ if(plung1(heir, lval2)) rvalue(lval2); if(lval[4]==0) lval[7]=stagenext; const2(lval[4]<= right); else if(oper == zzlt) return (left < right); else if(oper == zzgt) return (left > right); else if(oper == zzasr) return (left >> right); else if(oper == zzasl) return (left << right); else if(oper == zzadd) return (left + right); else if(oper == zzsub) return (left - right); else if(oper ==zzmult) return (left * right); else if(oper == zzdiv) return (left / right); else if(oper == zzmod) return (left % right); else retu  er) pop(); } else { if(oper) { rvalue(lval); plung2(oper, oper, heir1, lval, lval2); } else { if(heir1(lval2)) rvalue(lval2); lval[5]=lval2[5]; } } store(lval); return 0; } heir3(lval) int lval[]; { int heir4(); return skim("||", eq0, 1, 0, heir4, lval); } heir4(lval) int lval[]; { int heir5(); return skim("&&", ne0, 0, 1, heir5, lval); } heir5(lval) int lval[]; { int heir6(); return plunge("|", 0, [4] = ~lval[4]; #endif /* PHASE2 */ return 0; } else if (match("!")) { /* ! */ if(heir13(lval)) rvalue(lval); lneg(); #ifdef PHASE2 lval[4] = !lval[4]; #endif /* PHASE2 */ return 0; } else if (match("-")) { /* unary - */ if(heir13(lval)) rvalue(lval); neg(); lval[4] = -lval[4]; return 0; } else if(match("*")) { /* unary * */ if(heir13(lval)) rvalue(lval); if(ptr=lval[0])lval[1]=ptrr=lval[0]; blanks(); if((ch=='[')|(ch=='(')) { lval[5]=1; /* secondary register will be used */ while(1) { if(match("[")) { /* [subscript] */ if(ptr==0) { error("can't subscript"); junk(); needtoken("]"); return 0; } else if(ptr[IDENT]==POINTER)rvalue(lval); else if(ptr[IDENT]!=ARRAY) { error("can't subscript"); k=0; } setstage(&before, &start);heir6, lval); } heir6(lval) int lval[]; { int heir7(); return plunge("^", 1, heir7, lval); } heir7(lval) int lval[]; { int heir8(); return plunge("&", 2, heir8, lval); } heir8(lval) int lval[]; { int heir9(); return plunge("== !=", 3, heir9, lval); } heir9(lval) int lval[]; { int heir10(); return plunge("<= >= < >", 5, heir10, lval); } heir10(lval) int lval[]; { int heir11(); return plunge(">> <<", 9, heir11, lval); } heir11(lval) in[TYPE]; else lval[1]=CINT; lval[2]=0; /* flag as not pointer or array */ lval[3]=0; /* flag as not constant */ return 1; } else if(match("&")) { /* unary & */ if(heir13(lval)==0) { error("illegal address"); return 0; } ptr=lval[0]; lval[2]=ptr[TYPE]; if(lval[1]) return 0; /* global & non-array */ address(ptr); lval[1]=ptr[TYPE]; return 0; } else { k=heir14(lval); if(match("++")) {  heir13(lval) int lval[]; { int k; char *ptr; if(match("++")) { /* ++lval */ if(heir13(lval)==0) { needlval(); return 0; } step(inc, lval); return 0; } else if(match("--")) { /* --lval */ if(heir13(lval)==0) { needlval(); return 0; } step(dec, lval); return 0; } else if (match("~")) { /* ~ */ if(heir13(lval)) rvalue(lval); com(); #ifdef PHASE2 lval lval2[3]=0; plung2(0, 0, heir1, lval2, lval2); /* lval2 deadend */ needtoken("]"); if(lval2[3]) { clearstage(before, 0); if(lval2[4]) { if(ptr[TYPE]==CINT) const2(lval2[4]<>2); return 0; } else if(match("--")) { /* lval-- */ if(k==0) { needlval(); return 0; } step(dec, lval); inc(lval[2]>>2); return 0; } else return k; } } heir14(lval) int *lval; { int k, const, val, lval2[8]; char *ptr, *before, *start; k=primary(lval); pt  =1; } else if(match("(")) { /* function(...) */ if(ptr==0) callfunction(0); else if(ptr[IDENT]!=FUNCTION) { rvalue(lval); callfunction(0); } else callfunction(ptr); k=lval[0]=lval[3]=0; } else return k; } } if(ptr==0) return k; if(ptr[IDENT]==FUNCTION) { address(ptr); return 0; } return k; } primary(lval) int *lval; { char *ptr; int k; if(match("([1]=0; return 0; } if(constant(lval)==0) experr(); return 0; } experr() { error("invalid expression"); const(0); junk(); } callfunction(ptr) char *ptr; { /* symbol table entry or 0 */ int nargs, const, val; nargs=0; blanks(); /* already saw open paren */ if(ptr==0) push(); /* calling HL */ while(streq(lptr,")")==0) { if(endst()) break; expression(&const, &val); if(ptr==0) swapstk(); /* don't push addr */ push(); ; } store(lval) int lval[]; { if(lval[1]) putstk(lval); else putmem(lval); } rvalue(lval) int lval[]; { if ((lval[0]!=0)&(lval[1]==0)) getmem(lval); else indirect(lval); } test(label, parens) int label, parens; { int lval[8]; char *before, *start; if(parens) needtoken("("); while(1) { setstage(&before, &start); if(heir1(lval)) rvalue(lval); if(match(",")) clearstage(before, start); else break; } if(parens")) { /* (expression) */ k=heir1(lval); needtoken(")"); return k; } putint(0, lval, 8< int pointer or int array and val2 not ptr or array */ dbltest(val1,val2) int val1[], val2[]; { if(val1[2]!=CINT) return 0; if(val2[2]) return 0; return 1; } /* ** determine type of binary operation */ result(lval, lval2) int lval[], lval2[]; { if((lval[2]!=0)&(lval2[2]!=0)) { lval[2]=0; } else if(lval2[2]) { lval[0]=lval2[0]; lval[1]=lval2[1]; lval[2]=lval2[2]; } } #ifdef FULLC step(oper, lval) int (*oper)(), lval[]; {  /* push argument */ nargs=nargs+BPW; /* count args*BPW */ if (match(",")==0) break; } needtoken(")"); if(streq(ptr+NAME, "CCARGC")==0) loadargc(nargs>>LBPW); if(ptr) call(ptr+NAME); else callstk(); csp=modstk(csp+nargs, YES); } ) needtoken(")"); if(lval[3]) { /* constant expression */ clearstage(before, 0); if(lval[4]) return; jump(label); return; } if(lval[7]) { /* stage address of "oper 0" code */ oper=lval[6];/* operator function address */ if((oper==zzeq)| (oper==ule)) zerojump(eq0, label, lval); else if((oper==zzne)| (oper==ugt)) zerojump(ne0, label, lval); else if (oper==zzgt) zerojump(gt0, label, lval); else if (oper==zzge) zerojump(ge0tr[IDENT]==ARRAY) { lval[2]=ptr[TYPE]; return 0; } else return 1; } if(ptr=findglb(ssname)) if(ptr[IDENT]!=FUNCTION) { lval[0]=ptr; lval[1]=0; if(ptr[IDENT]!=ARRAY) { if(ptr[IDENT]==POINTER) lval[2]=ptr[TYPE]; return 1; } address(ptr); lval[1]=lval[2]=ptr[TYPE]; return 0; } ptr=addsym(ssname, FUNCTION, CINT, 0, &glbptr, STATIC); lval[0]=ptr; lval#else /* FULLC */ step(oper, lval) int oper, lval[]; { #endif /* FULLC */ if(lval[1]) { if(lval[5]) { push(); rvalue(lval); #ifdef FULLC (*oper)(lval[2]>>2); #else /* FULLC */ oper(lval[2]>>2); #endif /* FULLC */ pop(); store(lval); return; } else { move(); lval[5]=1; } } rvalue(lval); #ifdef FULLC (*oper)(lval[2]>>2); #else /* FULLC */ oper(lval[2]>>2); #endif /* FULLC */ store(lval)  , label, lval); else if (oper==uge) clearstage(lval[7],0); else if (oper==zzlt) zerojump(lt0, label, lval); else if (oper==ult) zerojump(ult0, label, lval); else if (oper==zzle) zerojump(le0, label, lval); else testjump(label); } else testjump(label); clearstage(before, start); } constexpr(val) int *val; { int const; char *before, *start; setstage(&before, &start); expression(&const, val); clearstage(before, 0); /* scratch generatedurn 0; while(ch!=39) k=(k&255)*256 + (litchar()&255); ++lptr; val[0]=k; return 1; } qstr(val) int val[]; { char c; if (match(quote)==0) return 0; val[0]=litptr; while (ch!='"') { if(ch==0) break; stowlit(litchar(), 1); } gch(); litq[litptr++]=0; return 1; } stowlit(value, size) int value, size; { if((litptr+size) >= LITMAX) { error("literal queue overflow"); abort(ERRCODE); } putint(value, litq+litptr, size); litptr=litptr+siline or mline */ *lptr, /* ptr to either */ *glbptr, /* ptrs to next entries */ *locptr, /* ptr to next local symbol */ *stagenext,/* next addr in stage */ *stagelast,/* last addr in stage */ quote[2], /* literal string for '"' */ *cptr, /* work ptrs to any char buffer */ *cptr2, *cptr3, #ifdef CMD_LINE #ifdef FULLC *argvs[MAXARGS], /* static copy of argv */ #endif /* FULLC */ #endif /* CMD_LINE */ msname[NAMESIZE], /* macro symbol name array */ ssname[NAME code */ if(const==0) error("must be constant expression"); return const; } const(val) int val; { immed(); outdec(val); nl(); } const2(val) int val; { immed2(); outdec(val); nl(); } constant(lval) int lval[]; { lval=lval+3; *lval=1; /* assume it will be a constant */ if (number(++lval)) immed(); else if (pstr(lval)) immed(); else if (qstr(lval)) { *(lval-1)=0; /* nope, it's a string address */ immed(); printlabel(litlab); ou /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Part 1 */ #include "stdiol.h" #include "cc.def" /* ** miscellaneous storage */ char #ifdef OPTIMIZE optimize, /* optimize output of staging buffer */ #endif /* OPTIMIZE */ alarm, /* audible alarm on errors? */ monitor, /* monitor function headers? */ pause, /* pause for operator on errors? */ m80flg, /* compile for M80 assembler? */ #ifdef DYNAMIC *stage, /* output staging buffze; } /* ** return current literal char & bump lptr */ litchar() { int i, oct; if((ch!=92)|(nch==0)) return gch(); gch(); if(ch=='n') {gch(); return 13;} /* CR */ if(ch=='t') {gch(); return 9;} /* HT */ if(ch=='b') {gch(); return 8;} /* BS */ if(ch=='f') {gch(); return 12;} /* FF */ i=3; oct=0; while(((i--)>0)&(ch>='0')&(ch<='7')) oct=(oct<<3)+gch()-'0'; if(i==2) return gch(); else return oct; } SIZE]; /* static symbol name array */ int #ifdef STGOTO nogo, /* > 0 disables goto statements */ noloc, /* > 0 disables block locals */ #endif /* STGOTO */ /* ** the following two definitions are arrays of pointers to functions ** and should look like this: ** (*op)()[16], ** (*op2)()[16], ** but small-c cheats and declares an array of ints */ op[16], /* function addresses of binary operators */ op2[16], /* same for unsigned operators */ opindex, /* indetbyte('+'); } else return 0; outdec(*lval); nl(); return 1; } number(val) int val[]; { int k, minus; k=minus=0; while(1) { if(match("+")) ; else if(match("-")) minus=1; else break; } if(numeric(ch)==0)return 0; while (numeric(ch)) k=k*10+(inbyte()-'0'); if (minus) k=(-k); val[0]=k; return 1; } address(ptr) char *ptr; { immed(); outstr(ptr+NAME); nl(); } pstr(val) int val[]; { int k; k=0; if (match("'")==0) reter */ *symtab, /* symbol table */ *litq, /* literal pool */ #ifdef HASH *macn, /* macro name buffer */ #endif /* HASH */ *macq, /* macro string buffer */ *pline, /* parsing buffer */ *mline, /* macro buffer */ #else /* DYNAMIC */ stage[STAGESIZE], symtab[SYMTBSZ], litq[LITABSZ], #ifdef HASH macn[MACNSIZE], #endif /* HASH */ macq[MACQSIZE], pline[LINESIZE], mline[LINESIZE], swq[SWTABSZ], #endif /* DYNAMIC */ *line, /* points to p  x to matched operator */ opsize, /* size of operator in bytes */ swactive, /* true inside a switch */ swdefault,/* default label #, else 0 */ *swnext, /* address of next entry */ *swend, /* address of last table entry */ #ifdef DYNAMIC *wq, /* while queue */ #else /* DYNAMIC */ wq[WQTABSZ], #endif /* DYNAMIC */ #ifdef CMD_LINE argcs, /* static argc */ #ifdef N_CMD_LN #ifndef FULLC argvs[MAXARGS], /* static argv (new_cmd_line && !full_c) */ #endif /* FU, gch(), getint(), getlabel(), illname(), inbyte(), inline(), junk(), kill(), lout(), match(), multidef(), needtoken(), nextsym(), nl(), numeric(), outbyte(), outdec(), postlabel(), preprocess(), printlabel(), putint(), readwhile(), setstage(), sout(), streq(), symname(), upper(), xgets(); extern int constexpr(), expression(), number(), qstr(), test(), stowlit(); extern int /* ** arithmetic routines prefaced with "zz" to keep M80 ** assembler f errflag, /* non-zero after 1st error in statement */ eof, /* set non-zero on final input eof */ input, /* fd # for input file */ input2, /* fd # for "include" file */ output, /* fd # for output file */ files, /* non-zero if file list specified on cmd line */ filearg, /* cur file arg index */ glbflag, /* non-zero if internal globals */ ctext, /* non-zero to intermix c-source */ ccode, /* non-zero while parsing c-code */ /* zero when passing  /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Part 3 */ #include "stdiol.h" #include "cc.def" /* ** external references in part 1 */ extern char #ifdef DYNAMIC *stage, *litq, #else /* DYNAMIC */ stage[STAGESIZE], litq[LITABSZ], #endif /* DYNAMIC */ *glbptr, *lptr, ssname[NAMESIZE], quote[2], *stagenext; extern int ch, csp, litlab, litptr, nch, op[16], op2[16], oper, opindex, opsize; /* ** external references in part 2 LLC */ #else /* N_CMD_LN */ *argvs, /* static argv (original version) */ #endif /* N_CMD_LN */ #endif /* CMD_LINE */ *wqptr, /* ptr to next entry */ litptr, /* ptr to next entry */ macptr, /* macro buffer index */ #ifndef HASH mack, /* variable k for findmac routine */ #endif /* HASH */ pptr, /* ptr to parsing buffer */ oper, /* address of binary operator function */ ch, /* current character of line being scanned */ nch, /* next charrom generating error msgs when this is compiled */ zzadd(), zzand(), zzasl(), zzasr(), defstora(), zzdiv(), zzeq(), entry(), external(), zzge(), zzgt(), header(), jump(), zzle(), zzlt(), zzmod(), modstk(), zzmult(), zzne(), zzor(), point(), ret(), zzsub(), sw(), trailer(), uge(), ugt(), ule(), ult(), zzxor(); #endif /* SEPARATE */ #include "cc11.c" #include "cc12.c" #include "cc13.c" #ifndef SEPARATE #include "cc21.c" #include "cc22.c" #include "cc31.c"assembly code */ listfp, /* file pointer to list device */ lastst, /* last executed statement type */ *iptr; /* work ptr to any int buffer */ #ifdef C80 extern int fin, fout; #endif /* C80 */ #ifdef SEPARATE #ifdef LINK #ifdef PDS #asm CC2.R:LIBRY CC3.R:LIBRY CC4.R:LIBRY #endasm #endif /* PDS */ #endif /* LINK */ extern int addmac(), addsym(), addwhile(), amatch(), blanks(), bump(), clearstage(), col(), delwhile(), endst(), error(), findglb(), findloc() */ extern int addsym(), blanks(), bump(), clearstage(), endst(), error(), findglb(), findloc(), gch(), getlabel(), inbyte(), junk(), match(), needlval(), needtoken(), nextop(), nl(), numeric(), outbyte(), outdec(), outstr(), postlabel(), printlabel(), putint(), setstage(), streq(), symname(); /* ** external references in part 4 */ extern int /* ** arithmetic routines prefaced with "zz" to keep M80 ** assembler from generating error msgs when this is coacter of line being scanned */ declared, /* # of local bytes declared, else -1 when done */ iflevel, /* #if... nest level */ skiplevel,/* level at which #if... skipping started */ func1, /* true for first function */ nxtlab, /* next avail label # */ litlab, /* label # assigned to literal pool */ beglab, /* beginning label -- first function */ csp, /* compiler relative stk ptr */ argstk, /* function arg sp */ argtop, ncmp, /* # open compound statements */ #include "cc32.c" #include "cc33.c" #include "cc41.c" #include "cc42.c" #endif /* SEPARATE */ cc22.c" #include "cc31.c"  mpiled */ zzadd(), zzand(), zzasl(), zzasr(), call(), callstk(), com(), dec(), zzdiv(), doublereg(), zzeq(), eq0(), zzge(), ge0(), getloc(), getmem(), zzgt(), gt0(), immed(), immed2(), inc(), indirect(), jump(), zzle(), le0(), lneg(), loadargc(), zzlt(), lt0(), zzmod(), modstk(), move(), zzmult(), zzne(), ne0(), neg(), zzor(), pop(), push(), putmem(), putstk(), ret(), smartpop(), zzsub(), swap(), swapstk(), testjump(), uge(), ugt(), ule(rm, *glbptr, *line, *lptr, *cptr, *cptr2, *cptr3, *locptr, msname[NAMESIZE], optimize, pause, quote[2], *stagelast, *stagenext; extern int #ifdef DYNAMIC *wq, #else /* DYNAMIC */ wq[WQTABSZ], #endif /* DYNAMIC */ #ifndef HASH mack, #endif /* HASH */ ccode, ch, csp, eof, errflag, iflevel, input, input2, listfp, macptr, nch, nxtlab, op[16], opindex, opsize, output, pptr, skiplevel, *wqptr; extern int openin(); /* ** external references in ;#asm ; ;------------------------------------------------------------------ ; Small-C Run-time Library ; ; ; V3b As of June 9, 1980 12pm (rj) ; corrected cp to chp in @gets ; changed lower case to hex constants in @fopen and fcb ; V4 As of June 26, 1980 12:15pm (gtf) ; Changed all @'s and ?'s to "QZ" for ASM compatibility ; V4b As of July 7, 1980 3:00 pm (gtf) ; Changed putc() to test code returned by cput() ; V4c As of July 9, 1980 9:15 pm (gtf) ; Fixed bug in CPMIO whi), ult(), ult0(), zzxor(), zerojump(); #include "cc31.c" #include "cc32.c" #include "cc33.c"  --> FILE: CC11 .C CRC = 63 95 --> FILE: CC21 .C CRC = F0 C1 --> FILE: CC12 .C CRC = 52 4D --> FILE: CC42 .C CRC = 64 B5 --> FILE: CC .DEF CRC = 50 99 --> FILE: CC41 .BAK CRC = 3E 85 --> FILE: CC13 .C CRC = 28 D7 --> FILE: CC22 .C CRC = 62 5E --> FILE: CC4 .C CRC = 28 02 --> FILE: CC31 .C CRC = F2 68 --> FILE: CC32 .C CRC = C4 0C --> FILE: CC33 .C CRC = E1 76 --> FILE: CC1 .C CRC = 9F A9 --> FILE: CC3  part 4 */ #ifdef OPTIMIZE extern int peephole(); #endif /* OPTIMIZE */ #include "cc21.c" #include "cc22.c" ch returned wrong error status. ; Added PUTS() function ; Un-hardwired I/O buffer count. ; Made GETCHAR() print LF after reading CR. ; Made GETCHAR() return -1 on EOF (=CTRL-Z) ; Added EOL and LF equates, instead of magic numbers ; V4d As of July 16, 1980 9:00 pm (gtf) ; Added EXIT() function ; V5 As of April 12, 1983 12:30 am (br) ; Modified to reuse package for Small-C, ver 2. ; Removed "QZ" in front of names. ; Added runtime initialization and command line /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Part 2 */ #include "stdiol.h" #include "cc.def" /* ** external references in part 1 */ extern char #ifdef DYNAMIC *symtab, *stage, #ifdef HASH *macn, #endif /* HASH */ *macq, *pline, *mline, #else /* DYNAMIC */ symtab[SYMTBSZ], stage[STAGESIZE], #ifdef HASH macn[MACNSIZE], #endif /* HASH */ macq[MACQSIZE], pline[LINESIZE], mline[LINESIZE], #endif /* DYNAMIC */ ala .C CRC = B8 76 --> FILE: CC2 .C CRC = 63 3E --> FILE: IOLIB .MAC CRC = 4C 98 --> FILE: CALL .MAC CRC = E4 A4 --> FILE: CRC .COM CRC = B2 07 --> FILE: CC41 .C CRC = E1 89 --> FILE: D .COM CRC = 66 48 --> FILE: SMC .COM CRC = EC 9D   ; processing from RUNTIM.MAC [by Bill Danielson, 3/83]. ; Added I/O redirection for stdin and stdout. ; Added FPUTS(), FGETS(), DOLDDR(), DOLDIR(), ; UNLINK() and ABORT() functions. ; V5a As of April 14, 1983 12:55 pm (br) ; Masked parity bit in compares for EOL, LF & ^Z. ; V5b As of July 19, 1983 9:50 pm (br) ; Fixed bug in FCLOSE(). ; V5c As of July 27, 1983 9:55 pm (br) ; Fixed bug in initialization of RSTDIN and RSTDOUT. ; Fixed bug in PUTS(). ; V5d As of J ;Default for stderr STDLIST EQU 4 ;Default for stdlist ; DFLTDSK: DS 1 ;drive to use if no drive is named UNIT: DS 2 ;I/O structure address to act on IP: DS 2 ;int *ip; CHP: DS 2 ;char *chp; DP: DS 2 ;char *dp; FILE: DS 2 ;file name MODE: DS 2 ;char *mode;(read or write) ZCH: DS 2 ;char ch; ZT: DS 2 ;int t; FN: DS 2 ;int fn; i/o function (for cpmio) ; SVCHP: DS 2 ;char *svchp; saved character pointer RSTDIN: DS 2 ;int rstdin; unit of redirected stdin RSTDOUT: DS 2 ;int rstdout; unit of rediting BUFSIZ EQU 128 ;how long the sector buffer is NBUFS EQU 4 ;number of I/O buffers (change buffer declarations, too) ; CP/M system call codes CLOSE EQU 16 ;close a file CPMSTR EQU 9 ;print '$' delimited string on console CREATE EQU 22 ;make a file DMA EQU 26 ;set DMA (I/O address) DELETE EQU 19 ;delete a file GETCH EQU 1 ;read character from console GETSTR EQU 10 ;read string from console LSTOUT EQU 5 ;write character to list device OPEN EQU 15 ;open a file PUTCH EQU 2 ;write character to c string with 'pgmname' in it LXI D,PGM ; Pointer to 'pgmname' string CALL SVARG ; Save next argument ; Ok, now for the real stuff. Set DE pair to point to ; CPM command line and start searching for arguments LXI D,CPMARG ; Pointer to CPM arg line LDAX D ; Load # character in line MOV B,A ; Save it in B NXTSP: INX D ; Point to next character DCR B ; Decrement character count JM ENDCMD ; End of cmd line LDAX D ; Load next character in line CPI ' ' ; Space? JZ NXTSP ; Yes...continuly 29, 1983 7:47am (br) ; Fixed GETC()/CGET() so it skips check for CR when ; calling GETCHAR(). ;------------------------------------------------------------------ ; ; *** may need following statement when using ASM *** ; ORG 100H ; *** ; JMP START ; ; *** delete following extern when using ASM *** EXTRN MAIN, CCDSGI, CCSXT ; *** ; ; ======================================== ; I/O subroutines for CP/M ; By Glen Fisher ; The Code Works(tm) ; [modified by Bill Randle] ; ======rected stdout ; ; First thing, we save CPM's stack pointer and current disk and ; init stdin and stdout. ; Second thing, we run through the CPM input line and ; modify it so that we can pass the C program the ; command line in the argc, argv form that it expects ; HL = pointer to next argv entry ; DE = pointer to next character in command line ; B = number of characters left in line ; C = argument count (argc) START: LXI H,0 ; Get CPM's stack pointer DAD SP SHLD STACK ; Save it for lateonsole QUERY EQU 25 ;get logged-in drive id READ EQU 20 ;read a sector SELECT EQU 14 ;log-in a drive WRITE EQU 21 ;write a sector ; LF EQU 10 ;line feed EOL EQU 13 ;end-of-line character (=carriage return) CTRLZ EQU 26 ;end-of-file mark for text files TBUFF EQU 80H ;address of default I/O address BDOS EQU 5 ;Entry point to CP/M BDOS CPMARG EQU 80H ;CP/M command line MAXARG EQU 32 ;Maximum number of args in input line STDIN EQU 0 ;Default for stdin STDOUT EQU 1 ;Default for stdout STDERR EQU 2ue searching CPI '>' ; Redirect output? JZ RDOUT ; Yes...open the file for output CPI '<' ; Redirect input? JZ RDINP ; Yes...open the file for input CALL SVARG ; Nope, save starting point of this arg ; Loop looking for either end of line of a space NXTCH: INX D ; Point to next character DCR B ; Decrement character count JM ENDWRD ; End of cmd line, but need to end arg LDAX D ; Load next character in line CPI ' ' ; Space? JNZ NXTCH ; Nope...keep looking MVI A,0 ; Yes, replace it w================================== ; NULL EQU 0 ;pointer to nothing FCBSIZE EQU 36 ;size, in bytes, of an FCB NEXTP EQU 0 ;offset to next-character pointer in I/O structure UNUSED EQU 2 ;offset to unused-positions-count in I/O structure BUFFER EQU 4 ;offset to disk sector buffer in I/O structure FLAG EQU 33 ;file-type flag byte (in unused part of FCB) FREEFLG EQU 128 ;This I/O structure is available for the taking EOFFLG EQU 2 ;The end of this file has been hit WRTFLG EQU 1 ;This file open for wrir MVI C,QUERY ; get logged-in disk CALL BDOS INR A ; make it so it will work in fcb STA DFLTDSK LDA BDOS+2 ; Get base of BDOS MOV H,A ; Save page in HL MVI L,0 SPHL ; Set stack pointer LXI H,STDIN SHLD RSTDIN ; Init rstdin LXI H,STDOUT SHLD RSTDOUT ; Init rstdout MVI C,0 ; Init argc LXI H,ARGV ; Pointer to first entry of argv array ; Unfortunately, CPM does not tell us what the first word of ; the command line was (the name of pgm), so we fake ; it by pointing it to a ascii  ith a zero byte STAX D JMP NXTSP ; Look for start of next arg ENDWRD: MVI A,0 STAX D ENDCMD: MVI B,0 ; Zero B (BC now is 16 bit argc) PUSH B ; First arg to main procedure LXI H,ARGV ; Point to argv array PUSH H ; Second argument to main procedure MVI A,2 ; Load up the argument count CALL MAIN ; Transfer to the C world.... JMP EXIT ; Return to CPM SVARG: MOV M,E ; Save pointer to start of string INX H MOV M,D INX H INR C ; Increment argc RET ARGV: DS MAXARG*2 PGM: DB 'PGMNAMEe DB 0EDH, 0B0H ; Do LDIR instruction PUSH H ; Restore stack PUSH D PUSH B DCX SP DCX SP RET ; End of memory function ; Returns top memory location in HL TOPOFMEM:: LDA BDOS+2 ; Get base of BDOS MOV H,A ; Save page in HL MVI L,0 RET ; Return the first free location FIRSTFREE:: LHLD $MEMRY RET $MEMRY::DW 0 ; This assembly routine allows CPM calls from Small C. ; ; cpm(cpmfunction#, inputparameter) ; ; Since this function returns whatever is returned in regiset next argument DEBLNK: INX D ; Skip leading spaces DCR B RM ; End of line reached LDAX D CPI ' ' JZ DEBLNK RET CPYNAM: LXI H,NAMBUF ; Copy filename to temp buffer PUSH B ; Save reg C MVI C,16 ; Maximum filename length CPY1: MOV M,A INX D INX H DCR B JM ENDNAM DCR C JZ RDERR LDAX D CPI ' ' JNZ CPY1 ENDNAM: MVI M,0 POP H MOV C,L ; Restore reg C RET RDERR: LXI D,RDEMSG ; Error message MVI C,CPMSTR CALL BDOS ; Make sure it gets put on the terminal JMP POP B LXI H,2 CALL CCDSGI PUSH H ; Someday this should write out the correct error code ; CALL OUTDEC## ; Inside C compiler POP B JMP EXIT ABTMSG: DB 0DH, 0DH, "Aborted, reason = ",0 ; ; grabio() ; ; find an input buffer, and return its address. ; if there isn't one, return a NULL. ; GRABIO: ;6 May 80 rj MVI B,NBUFS LXI H,IOBUFS+FLAG LXI D,FCBSIZE+BUFFER+BUFSIZ MVI A,FREEFLG GRAB2: CMP M ;flag byte == freeflg? JZ GRAB3 ;if so, found a free buffer DAD D ;on to n',0 RDINP: CALL DEBLNK ; Skip leading spaces JM RDERR ; End of line reached PUSH H CALL CPYNAM ; Copy filename to temp buffer PUSH D ; Save registers PUSH B LXI H,NAMBUF ; Begining of filename PUSH H LXI H,RDOPN ; Mode PUSH H CALL FOPEN ; Open the file POP D POP D MOV A,H ORA L ; Check return status JZ RDERR SHLD RSTDIN ; Save unit for redirected input POP B ; Restore registers POP D POP H MVI A,0FFH CMP B ; End of command line? JZ ENDCMD JMP NXTSP ; Get nextter ; it cannot be used to call ReturnVersionNumber, ReturnLoginVector, ; WriteProtectDisk, or GetAddr. CPM:: POP H ; Pop rtn address POP D ; Pop input parameter in DE register pair POP B ; Pop function code into C register PUSH B ; Restore stack PUSH D PUSH H CALL BDOS ; Call CPM MOV L,A ; Sign extend A into HL register pair RLC SBB A MOV H,A RET ; exit() ; ; Stop execution of the program, ; restore the logged-in drive, ; and re-boot CP/M ; EXIT:: LHLD RSTDOUT MOV A,H EXIT RDOPN: DB 'r',0 WROPN: DB 'w',0 NAMBUF: DS 16 RDEMSG: DB 'iolib: Unable to open < or > file$' ; lddr(source, dest, n) DOLDDR:: INX SP ; Skip over return address INX SP POP B ; Load n POP D ; Load destination POP H ; Load source DB 0EDH, 0B8H ; Do LDDR instruction PUSH H ; Restore stack PUSH D PUSH B DCX SP DCX SP RET ; doldir(source, dest, n) DOLDIR:: INX SP ; Skip over return address INX SP POP B ; Load n POP D ; Load destination POP H ; Load sourcext buffer DCR B JNZ GRAB2 ;if there is one... LXI H,NULL ;there ain't RET ;give up GRAB3: MVI M,0 ;mark buffer as taken LXI D,-FLAG ;back up to buffer start DAD D RET ;and hand it back ; ; freeio(unit) ; ; mark a buffer as free. ; FREEIO: ;Mod 6 May 80 rj POP B ;save rtn addr POP H ;get buffer addr PUSH H ;put the stack back together PUSH B LXI D,FLAG ;find flag byte DAD D MVI M,FREEFLG ;mark buffer as 'free' LXI H,NULL ;return something  argument RDOUT: CALL DEBLNK ; Skip leading spaces JM RDERR ; End of line reached PUSH H CALL CPYNAM ; Copy filename to temp buffer PUSH D ; Save registers PUSH B LXI H,NAMBUF ; Begining of filename PUSH H LXI H,WROPN ; Mode PUSH H CALL FOPEN ; Open the file POP D POP D MOV A,H ORA L ; Check return status JZ RDERR SHLD RSTDOUT ; Save unit for redirected input POP B ; Restore registers POP D POP H MVI A,0FFH CMP B ; End of command line? JZ ENDCMD JMP NXTSP ; G ORA A ; See if stdout has been redirected JZ EXIT1 PUSH H CALL FCLOSE ; If so, close the file POP B EXIT1: LDA DFLTDSK ; Grab orig. logged-in disk MOV E,A DCR E ; (cvt. back to 0-n) MVI C,SELECT ; and log it in again CALL BDOS LHLD STACK ; Load stack pointer SPHL JMP 0 ; return to CP/M STACK: DW 0 ; ; abort(reason) ; ABORT:: POP B POP D PUSH D PUSH B PUSH D ; error code LXI H,ABTMSG ; Load abort message PUSH H LXI H,STDERR PUSH H CALL FPUTS POP B    RET IOBUFS: DS FCBSIZE-3 DB FREEFLG,0,0 DS BUFFER+BUFSIZ DS FCBSIZE-3 DB FREEFLG,0,0 DS BUFFER+BUFSIZ DS FCBSIZE-3 DB FREEFLG,0,0 DS BUFFER+BUFSIZ DS FCBSIZE-3 ;mod 4 May 80 rj DB FREEFLG,0,0 DS BUFFER+BUFSIZ ; ; fopen(name,mode) ; FOPEN:: POP B ;get args POP H ;mode SHLD MODE POP D XCHG SHLD FILE PUSH H PUSH D PUSH B CALL GRABIO ; unit = grabio(); SHLD UNIT MOV A,H ; if(unit==NULL) ORA L ; return(NULL); RZ LXI D,FCBSIZE ; ip = unit+FCBOP H LHLD UNIT ; ip = unit + FCBSIZE; LXI D,FCBSIZE DAD D SHLD IP LHLD IP ; cp = ip[NEXTP]; LXI D,NEXTP DAD D MOV E,M INX H MOV D,M XCHG SHLD CHP LHLD IP ; dp = &ip[BUFFER]+BUFSIZ; LXI D,BUFFER+BUFSIZ DAD D SHLD DP FCLWH1: ; while(cp'a'-'A') /* lower case? */ 9 Jun 80 rj JC FCBIF2 SUI 61H-41H ; A -= 'a'-'A'; 9 Jun 80 rj JMP FCBIF2 ; } FCBIF1: LDA DFLTDSK ; else A = default_drive; FCBIF2: STAX B ; *fp++ = A; INX B MVI H,' ' ; fp = fcbfill(fp,name,' ',8); MVI L,8 CALL FCBFILL MVI L,3 ; fp = fcbfill(fp,name,' ',3); CALL FCBFILL MVI H,0 ; fp = fcbpad(fp,0,4); MVI L,4 CALL FCBPAD LXI H,16 ; fp[16] = 0; DAD B MVI M,0 RET ; retSIZE; DAD D SHLD IP LHLD IP ; ip[NEXTP] = &ip[BUFFER]; LXI D,BUFFER DAD D XCHG LHLD IP LXI B,NEXTP DAD B MOV M,E INX H MOV M,D LHLD UNIT ; fcb(unit,name); PUSH H LHLD FILE PUSH H CALL FCB POP H POP H LHLD UNIT ; cpmdisk(*unit); MOV L,M MVI H,0 PUSH H CALL CPMDISK POP H LHLD MODE ; if(*mode=='r' || *mode=='R'){ MOV A,M CPI 72H ; 'r' ? 9 Jun 80 rj JZ FOPIF0 CPI 52H ; 'R' ? 9 Jun 80 rj JNZ FOPIF1 FOPIF0: MVI C,OPEN ; if(cpm(OPEN,un(WRITE,unit)<0) PUSH H LHLD UNIT PUSH H CALL CPMIO POP D POP D MOV A,H ORA A JP FCLIF4 LXI H,0 ; t = 0; SHLD ZT FCLIF4: ; } FCLIF3: ; } FCLIF1: MVI C,CLOSE ; if(cpm(CLOSE,unit)<0) LHLD UNIT XCHG CALL BDOS ORA A JP FCLIF5 LXI H,0 ; t = 0; SHLD ZT FCLIF5: LHLD UNIT ; freeio(unit); PUSH H CALL FREEIO POP H LHLD ZT ; return(NULL+t); RET ; ; unlink(name) ; UNLINK:: POP B POP D PUSH D PUSH B PUSH D ; name ; /* open file IO POP H LXI H,NULL ; return(NULL); RET ; } FOPIF4: LHLD UNIT ; return(unit); RET ; ; fclose(unit) ; FCLOSE:: POP B POP H SHLD UNIT PUSH H PUSH B MOV A,H ; if (unit<256) ORA A ; /* assume stdin, stdout, etc. */ MVI L,0 RZ ; return NULL; LXI H,1 ; t = 1; SHLD ZT LHLD UNIT ; if(unit[FLAG] & WRITE_FL){ LXI D,FLAG DAD D MOV A,M ANI WRTFLG JZ FCLIF1 LXI H,CTRLZ ; putc(CTRL_Z,unit); PUSH H LHLD UNIT PUSH H CALL PUTC POP H Purn; ; ; fcbfill(dest,name,pad,size) ; B D H L ; FCBFILL: MOV A,L ; while(L>0 && (A= *D)~='.' && A~=0){ ORA A JZ FILL2 LDAX D CPI '.' JZ FILL2 CPI 0 JZ FILL2 CPI 61H ; if(A>='a' && A<='z') JC FILL1 CPI 7AH+1 ; 'z' 9 Jun 80 rj JNC FILL1 SUI 61H-41H ; A = A - 'a' + 'A'; FILL1: STAX B ; *B++ = A; INX B INX D ; D++; DCR L ; L--; JMP FCBFILL ; } FILL2: LDAX D ; while(*D~='.' && *D~=0) CPI '.' JZ FILL3 CPI 0 JZ FILL3 INX D ; D++;it)<0){ LHLD UNIT XCHG CALL BDOS ORA A JP FOPIF2 LHLD UNIT ; freeio(unit); PUSH H CALL FREEIO POP H LXI H,NULL ; return(NULL); RET ; } FOPIF2: LHLD IP ; ip[UNUSED] = 0; LXI D,UNUSED DAD D LXI D,0 MOV M,E INX H MOV M,D ; } JMP FOPIF4 FOPIF1: ; else if(*mode=='w' || *mode=='W'){ LHLD MODE MOV A,M CPI 77H ; 'w' 9 Jun 80 rj JZ FOPIFA CPI 57H ; 'W' 9 Jun 80 rj JNZ FOPIF5 FOPIFA: MVI C,DELETE ; cpm(DELETE,unit); LHLD UNIT to unlink in LXI H,RDOPN ; Mode ; order to get fcb for it. */ PUSH H CALL FOPEN ; unit = fopen(name,'r'); POP D POP D SHLD UNIT MVI C,DELETE ; cpm(DELETE,unit); CALL BDOS LHLD UNIT ; freeio(unit); PUSH H CALL FREEIO POP D RET ; return; ; ; fcb(fp,name) ; FCB: POP H ;get args POP D ;name POP B ;fp PUSH B PUSH D PUSH H INX D ; if(name[1]==':'){ LDAX D DCX D CPI ':' JNZ FCBIF1 LDAX D ; A = *name - '@'; SUI 40H ; '@' 9 Jun 80 rj    JMP FILL2 FILL3: CPI '.' ; if(*D=='.') JNZ FILL4 INX D ; D++; FILL4: ; fall into... ; ; fcbpad(dest,pad,size) ; B H L ; FCBPAD: MOV A,L ; while(L>0){ ORA A JZ PAD2 MOV A,H ; *B++ = H; STAX B INX B DCR L ; L--; JMP FCBPAD ; } PAD2: RET ; return; ; ; getc(unit) ; FGETC:: GETC:: POP B POP H ; get args PUSH H PUSH B ; c=cget(unit); PUSH H CALL CGET POP D MOV A,L ; if(c=='\r') ANI 7FH ; /* mask parity in compare */ CPI EOare */ CPI CTRLZ ; if(t==CTRLZ) JNZ GET1CHAR LXI H,-1 ; t = -1; GET1CHAR: CPI EOL ; if(t==EOL) JNZ GET2CHAR PUSH H ; putchar('\n'); MVI C,PUTCH MVI E,LF CALL BDOS POP H GET2CHAR: ; return(t); RET ; } ; ; gets(buff) ; GETS:: POP B POP H PUSH H PUSH B PUSH H ; buff LHLD RSTDIN ; if(rstdin >= 256) { MOV A,H ORA A JZ GETS1 XCHG LXI H,80 PUSH H ; len PUSH D ; unit CALL FGETS ; return(fgets(buff, 80, rstdin)); POP B POP B POP B RET GESIZ MOV M,E INX H MOV M,D LHLD IP ; cp = &ip[BUFFER]; LXI D,BUFFER DAD D SHLD CHP ; } ; } GTCIF2: LHLD IP ; ip[UNUSED]--; LXI D,UNUSED DAD D MOV E,M INX H MOV D,M DCX D MOV M,D DCX H MOV M,E LHLD CHP ; ip[NEXTP] = cp+1; INX H XCHG LHLD IP LXI B,NEXTP DAD B MOV M,E INX H MOV M,D LHLD CHP ; if(*cp==CTRL_Z){ MOV A,M ANI 7FH ; /* mask parity in compare */ CPI CTRLZ JNZ GTCIF4 LHLD UNIT ; unit[FLAG] |= EOF_FL; LXI D,FLAGe cp PUSH B ; unit CALL GETC ; c = getc(unit); POP B MOV A,H ; if(c==EOF) /* c>255 */ ORA A JZ FGETS3 POP D ; cp LHLD SVCHP ; if (cp!=save_cp) XCHG ; /* read something */ MOV A,H CMP D JNZ FGETS4 ; goto fgets4; MOV A,L CMP E JNZ FGETS4 ; else LXI H,0 ; /* no characters */ POP D ; fix stack RET ; return (NULL); FGETS3: MOV A,L ; else { POP H MOV M,A ; *cp++ = c; INX H ANI 7FH ; /* mask parity in compare */ CPI LF ; L JNZ GETCRET PUSH H ; cget(unit); PUSH D ; /* to skip LF */ CALL CGET POP H POP H GETCRET: RET ; ; cget(unit) ; CGET: POP D POP H PUSH H PUSH D MOV A,H ORA A ; if(unit < 256) { JNZ CGET1 ; /* assume stdin */ CALL GETCHAR ; getchar(); POP D ; /* return to caller of getc() POP D ; to bypass CR check */ RET ; return; } CGET1: SHLD UNIT LXI D,FLAG ; if(unit[FLAG] & EOF_FL) DAD D MOV A,M ANI EOFFLG JZ GTCIF1 LXI H,-1 ; return(-1); RET TS1: POP H ; } else { SHLD CHP DCX H ; save = buff[-1]; save2 = buff[-2]; MOV D,M ; buff[-1] = 0; buff[-2] = 79; MVI M,0 DCX H MOV E,M MVI M,79 ;6 May 80 rj PUSH H PUSH D XCHG ; cpm(GETSTR,buff-2); MVI C,GETSTR CALL BDOS LHLD CHP ; buff[buff[-1]] = 0; (9 Jun 80. Was cp) DCX H MOV E,M INX H MVI D,0 DAD D MVI M,0 POP D ; buff[-1] = save; buff[-2] = save2; POP H MOV M,E INX H MOV M,D INX H MVI C,PUTCH ; putchar('\n'); MVI E,LF CALL BDOS DAD D MOV A,M ORI EOFFLG MOV M,A LXI H,-1 ; return(-1); RET ; } GTCIF4: MOV A,M MOV L,A ; return(*cp & 0377); MVI H,0 RET ; ; getchar() ; GETCHAR:: LHLD RSTDIN ; if(rdstdin >= 256) { MOV A,H ; /* stdin has been redirected */ ORA A JZ GETCHR1 PUSH H CALL GETC ; getc(rdstdin); POP B ; return; RET GETCHR1: ; } else { /* read from console */ MVI C,GETCH ; t = cpm(GETCH,0) & 0377; CALL BDOS MOV L,A MVI H,0 ANI 7FH ; /* mask parity in compif(c=='\n') JNZ FGETS2 FGETS4: MVI M,0 ; *cp='\0'; POP D ; fix stack LHLD SVCHP ; return save_cp; RET ; } } } } ; ; putc(c,unit) ; FPUTC:: PUTC:: POP B ;rtn addr POP D ;unit POP H ;c PUSH H PUSH D PUSH B MOV A,D ORA A ; if(unit < 256) { JNZ PUTC4 ; /* assume stdout, stderr */ MOV A,E ; /* or stdlist. */ CPI STDOUT ; if(unit == stdout) { JNZ PUTC1 PUSH H CALL PUTCHAR ; putchar(c); POP H RET ; return;} PUTC1: CPI STDERR ; elseif(unit == stderr)  GTCIF1: LHLD UNIT ; ip = unit + FCBSIZE; LXI D,FCBSIZE DAD D SHLD IP LXI D,NEXTP ; cp = ip[NEXTP]; DAD D MOV E,M INX H MOV D,M XCHG SHLD CHP LHLD IP ; if(ip[UNUSED]==0){ LXI D,UNUSED DAD D MOV A,M INX H ORA M JNZ GTCIF2 LXI H,READ ; if(cpmio(READ,unit)~=0) PUSH H LHLD UNIT PUSH H CALL CPMIO POP D POP D MOV A,H ORA L JZ GTCIF3 LXI H,-1 ; return(-1); RET GTCIF3: LHLD IP ; else { ip[UNUSED] = BUFSIZ; LXI D,UNUSED DAD D LXI D,BUF LHLD CHP ; return(buff); RET ; } ; ; fgets(cp,len,unit) ; FGETS:: INX SP ; skip rtn addr INX SP POP B ; unit POP D ; length POP H ; cp PUSH H PUSH D PUSH B DCX SP DCX SP MOV A,B ; if(unit < 256) { ORA A ; /* assume stdin */ JNZ FGETS1 PUSH H CALL GETS ; gets(cp) POP B ; return (cp); RET ; } else { FGETS1: SHLD SVCHP ; save_cp = cp; PUSH D ; keep stack right FGETS2: POP D DCX D ; while (--len) { PUSH D MOV A,D ORA E JZ FGETS4 PUSH H ; sav  { JNZ PUTC2 CALL PUTCON ; putconsole(c); RET ; return;} PUTC2: CPI STDLIST ; elseif(unit == stdlist) { JNZ PUTC3 PUSH H CALL PUTLST ; putlist(c); POP H RET ; return;} PUTC3: JMP PTCER1 ; else goto putcerr; } PUTC4: PUSH H ; if(cput(c,unit)<0) PUSH D ; goto putcerr; CALL CPUT POP D MOV A,H ORA A JM PUTCERR MOV A,L ; if(c=='\r') CPI EOL JNZ PUTCRET LXI H,LF ; cput('\n',unit); PUSH H PUSH D CALL CPUT POP D POP D MOV A,H ORA A JM PUTCE; PUTS:: POP B ; get args POP H PUSH H PUSH B PUSH H ; cp LHLD RSTDOUT MOV A,H ; if(rstdout >= 256) { ORA A JZ PUTS1 PUSH H CALL FPUTS ; return (fputs(cp, rstdout)); POP B POP B RET PUTS1: POP H ; } else { MOV A,M ; while(*cp) ORA A JZ PUTSRET MOV E,M ; putchar(*cp++); INX H PUSH H MVI C,PUTCH CALL BDOS JMP PUTS1 PUTSRET: ; return; RET ; } ; ; fputs(cp,unit) ; FPUTS:: POP B POP D ; unit POP H ; cp PUSH H PUSH D PUSH B FPUTS1M,D LHLD IP ; cp = &ip[BUFFER]; LXI D,BUFFER DAD D SHLD CHP ; } ; } PTCIF1: LHLD IP LXI D,UNUSED ; ip[UNUSED]--; DAD D MOV E,M INX H MOV D,M DCX D MOV M,D DCX H MOV M,E LHLD CHP ; ip[NEXTP] = cp+1; INX H XCHG LHLD IP LXI B,NEXTP DAD B MOV M,E INX H MOV M,D LDA ZCH ; return((*cp = c) & 0377); LHLD CHP MOV M,A MVI H,0 MOV L,A RET ; ; putchar(c) ; PUTCHAR:: POP B POP H PUSH H PUSH B PUSH H LHLD RSTDOUT ; if(rdstdou~=0) ORA H JZ DISKIF1 XCHG ; cpm(SELECT,d-1); DCX D MVI C,SELECT CALL BDOS DISKIF1: RET ; ;----------- End of Small-c library ----------- ; ;#endasm END RR PUTCRET: POP H ; return(c); RET PUTCERR: ;putcerr: POP B ; return(-1); PTCER1: LXI H,-1 RET ; ; putlist(c) ; PUTLST: POP B POP D PUSH D PUSH B SHLD ZCH MVI C,LSTOUT ; cpm(LSTOUT,c); CALL BDOS LDA ZCH CPI EOL ; if(c==EOL) JNZ PUTLS1 MVI E,LF ; cpm(LSTOUT,LF); MVI C,LSTOUT CALL BDOS PUTLS1: LHLD ZCH ; return(c & 0377) MVI H,0 RET ; ; cput(c,unit) ; CPUT: POP B POP D POP H PUSH H PUSH D PUSH B SHLD ZCH XCHG SHLD UNIT LXI D,F: MOV A,M ; while((c=*cp++) != NULL) { INX H ORA A JZ FPUTS3 PUSH H MOV C,A MVI B,0 PUSH B PUSH D CALL PUTC ; if(putc(c,unit)==EOF) POP D POP B MOV A,H ORA A JZ FPUTS2 POP B RET ; return(EOF); FPUTS2: POP H JMP FPUTS1 ; } FPUTS3: LXI H,0 RET ; return(NULL); ; ; cpmio(fn,unit) ; CPMIO: POP B POP D POP H SHLD FN XCHG SHLD UNIT PUSH D PUSH H PUSH B LHLD UNIT ; cpmdisk(*unit); MOV L,M MVI H,0 PUSH H CALL CPMDISK POP H LHLD UNIT t >= 256) { MOV A,H ; /* stdout has been redirected */ ORA A JZ PUTCHR1 PUSH H CALL PUTC ; putc(c, rdstdout); POP B POP B ; return; RET PUTCHR1: ; } else { POP H PUTCON: SHLD ZCH ; /* send to console */ XCHG ; cpm(PUTCH,c); MVI C,PUTCH CALL BDOS LDA ZCH ; if(c==EOL) ANI 7FH ; /* mask parity in compare */ CPI EOL JNZ PUTCHIF1 MVI E,LF ; cpm(PUTCH,LF); MVI C,PUTCH CALL BDOS PUTCHIF1: LHLD ZCH ; return(c & 0377); MVI H,0 RET ; } ; ; puts(cp) CBSIZE ; ip = unit + FCBSIZE; DAD D SHLD IP LXI D,NEXTP ; cp = ip[NEXTP]; DAD D MOV E,M INX H MOV D,M XCHG SHLD CHP LHLD IP ; if(ip[UNUSED]==0){ LXI D,UNUSED DAD D MOV A,M INX H ORA M JNZ PTCIF1 LXI H,WRITE ; if(cpmio(WRITE,unit)~=0) PUSH H LHLD UNIT PUSH H CALL CPMIO POP D POP D MOV A,H ORA L JZ PTCIF2 LXI H,-1 ; return(-1); RET PTCIF2: LHLD IP ; else { ip[UNUSED] = BUFSIZ; LXI D,UNUSED DAD D LXI D,BUFSIZ MOV M,E INX H MOV  ; ip = unit+FCBSIZE; LXI D,FCBSIZE ; cpm(DMA,&ip[BUFFER]); DAD D LXI D,BUFFER DAD D XCHG MVI C,DMA CALL BDOS LHLD FN ; t = cpm(fn,unit); MOV C,L LHLD UNIT XCHG CALL BDOS CALL CCSXT SHLD ZT MVI C,DMA ; cpm(DMA,TBUFF); LXI D,TBUFF CALL BDOS LHLD ZT ; if(t~=0) return(-1); MOV A,H ; else return(0); ORA L JNZ CPMIF1 LXI H,0 JMP CPMIF2 CPMIF1: LXI H,-1 CPMIF2: RET ; ; cpmdisk(disk) ; CPMDISK: POP D POP H PUSH H PUSH D MOV A,L ; if(d   ;#asm ; ;----- call.a: Small-C ver. 2 arithmetic and logical library ; (Modified for M80, 4-4-83, Bill Randle) ; CCDDGC:: DAD D JMP CCGCHAR ; CCDSGC:: INX H INX H DAD SP ; ;FETCH A SINGLE BYTE FROM THE ADDRESS IN HL AND ;SIGN EXTEND INTO HL ; CCGCHAR:: MOV A,M ; ;PUT THE ACCUM INTO HL AND SIGN EXTEND THROUGH H. ; CCARGC:: CCSXT:: MOV L,A RLC SBB A MOV H,A RET ; CCDDGI:: DAD D JMP CCGINT ; CCDSGI:: INX H INX H DAD SP ; ;FETCH A FULL 16-BIIGN OF HL XRI 80H MOV H,A MOV A,D ;;INVERT SIGN OF DE XRI 80H CMP H ;;COMPARE MSBS JNZ CCCMP1 ;;DONE IF NEQ MOV A,E ;;COMPARE LSBS CMP L CCCMP1: LXI H,1 ;;PRESET TRUE COND RET ; ;TEST IF DE >= HL (UNSIGNED) ; CCUGE:: CALL CCUCMP RNC DCX H RET ; ;TEST IF DE < HL (UNSIGNED) ; CCULT:: CALL CCUCMP RC DCX H RET ; ;TEST IF DE > HL (UNSIGNED) ; CCUGT:: XCHG CALL CCUCMP RC DCX H RET ; ;TEST IF DE <= HL (UNSIGNED) ; CCULE:: CALL CCUCMP L ; CCXOR:: MOV A,L XRA E MOV L,A MOV A,H XRA D MOV H,A RET ; ;"AND" HL AND DE INTO HL ; CCAND:: MOV A,L ANA E MOV L,A MOV A,H ANA D MOV H,A RET ; ;IN ALL THE FOLLOWING COMPARE ROUTINES, HL IS SET TO 1 IF THE ;CONDITION IS TRUE, OTHERWISE IT IS SET TO 0 (ZERO). ; ;TEST IF HL = DE ; CCEQ:: CALL CCCMP RZ DCX H RET ; ;TEST IF DE != HL ; CCNE:: CALL CCCMP RNZ DCX H RET ; ;TEST IF DE > HL (SIGNED) ; CCGT:: XCHG CALL CCCMP RC  MOV C,A ORA B RZ XRA A MOV A,E RAL MOV E,A MOV A,D RAL MOV D,A ORA E RZ JMP CCMLT1 ; ;DIVIDE DE BY HL AND RETURN QUOTIENT IN HL, REMAINDER IN DE ;(SIGNED DIVIDE) ; CCDIV:: DIV: MOV B,H MOV C,L MOV A,D XRA B PUSH PSW MOV A,D ORA A CM CCDENEG MOV A,B ORA A CM CCBCNEG MVI A,16 PUSH PSW XCHG LXI D,0 CCDIV1: DAD H CALL CCRDEL JZ CCDIV2 CALL CCCMPBCDE JM CCDIV2 MOV A,L ORI 1 MOV L,A MOV A,E SUB C MOV E,A MOV A,D SBB B MOVT INTEGER FROM THE ADDRESS IN HL ;INTO HL ; CCGINT:: MOV A,M INX H MOV H,M MOV L,A RET ; CCDECC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX D RET ; CCINCC:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX D RET ; CCDDPC:: DAD D CCPDPC:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A SINGLE BYTE FROM HL AT THE ADDRESS IN DE ; CCPCHAR:: PCHAR: MOV A,L STAX D RET ; CCDECI:: INX H I RZ RC DCX H RET ; ;COMMON ROUTINE TO PERFORM UNSIGNED COMPARE ;CARRY SET IF DE < HL ;ZERO/NONZERO SET ACCORDINGLY ; CCUCMP:: MOV A,D CMP H JNZ CCUCP1 MOV A,E CMP L CCUCP1: LXI H,1 RET ; ;SHIFT DE ARITHMETICALLY RIGHT BY HL AND RETURN IN HL ; CCASR:: XCHG DCR E RM MOV A,H RAL MOV A,H RAR MOV H,A MOV A,L RAR MOV L,A JMP CCASR+1 ; ;SHIFT DE ARITHMETICALLY LEFT BY HL AND RETURN IN HL ; CCASL:: XCHG DCR E RM DAD H JMP CCASL+1 ; ;S DCX H RET ; ;TEST IF DE <= HL (SIGNED) ; CCLE:: CALL CCCMP RZ RC DCX H RET ; ;TEST IF DE >= HL (SIGNED) ; CCGE:: CALL CCCMP RNC DCX H RET ; ;TEST IF DE < HL (SIGNED) ; CCLT:: CALL CCCMP RC DCX H RET ; ;COMMON ROUTINE TO PERFORM A SIGNED COMPARE ; OF DE AND HL ;THIS ROUTINE PERFORMS DE - HL AND SETS THE CONDITIONS: ; CARRY REFLECTS SIGN OF DIFFERENCE (SET MEANS DE < HL) ; ZERO/NON-ZERO SET ACCORDING TO EQUALITY. ; CCCMP:: MOV A,H ;;INVERT S D,A CCDIV2: POP PSW DCR A JZ CCDIV3 PUSH PSW JMP CCDIV1 CCDIV3: POP PSW RP CALL CCDENEG XCHG CALL CCDENEG XCHG RET ; ;NEGATE THE INTEGER IN DE ;(INTERNAL ROUTINE) ; CCDENEG: MOV A,D CMA MOV D,A MOV A,E CMA MOV E,A INX D RET ; ;NEGATE THE INTEGER IN BC ;(INTERNAL ROUTINE) ; CCBCNEG: MOV A,B CMA MOV B,A MOV A,C CMA MOV C,A INX B RET ; ;ROTATE DE LEFT ONE BIT ;(INTERNAL ROUTINE) ; CCRDEL: MOV A,E RAL MOV E,A MOV A,D RAL MONX H DAD SP MOV D,H MOV E,L CALL CCGINT DCX H JMP CCPINT ; CCINCI:: INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT INX H JMP CCPINT ; CCDDPI:: DAD D CCPDPI:: POP B ;;RET ADDR POP D PUSH B ; ;STORE A 16-BIT INTEGER IN HL AT THE ADDRESS IN DE ; CCPINT:: PINT: MOV A,L STAX D INX D MOV A,H STAX D RET ; ;INCLUSIVE "OR" HL AND DE INTO HL ; CCOR:: MOV A,L ORA E MOV L,A MOV A,H ORA D MOV H,A RET ; ;EXCLUSIVE "OR" HL AND DE INTO HUBTRACT HL FROM DE AND RETURN IN HL ; CCSUB:: MOV A,E SUB L MOV L,A MOV A,D SBB H MOV H,A RET ; ;FORM THE TWO'S COMPLEMENT OF HL ; CCNEG:: CALL CCCOM INX H RET ; ;FORM THE ONE'S COMPLEMENT OF HL ; CCCOM:: MOV A,H CMA MOV H,A MOV A,L CMA MOV L,A RET ; ;MULTIPLY DE BY HL AND RETURN IN HL ;(SIGNED MULTIPLY) ; CCMULT:: MULT: MOV B,H MOV C,L LXI H,0 CCMLT1: MOV A,C RRC JNC CCMLT2 DAD D CCMLT2: XRA A MOV A,B RAR MOV B,A MOV A,C RAR  V D,A ORA E RET ; ;COMPARE BC TO DE ;(INTERNAL ROUTINE) ; CCCMPBCDE: MOV A,E SUB C MOV A,D SBB B RET ; ; LOGICAL NEGATION ; CCLNEG:: MOV A,H ORA L JNZ $+6 MVI L,1 RET LXI H,0 RET ; ; EXECUTE "SWITCH" STATEMENT ; ; HL = SWITCH VALUE ; (SP) -> SWITCH TABLE ; DW ADDR1, VALUE1 ; DW ADDR2, VALUE2 ; ... ; DW 0 ; [JMP default] ; continuation ; CCSWITCH:: XCHG ;;DE = SWITCH VALUE POP H ;;HL -> SWITCH TABLE SWLOOP: MOV C,M INX *#"ɯ2i2}! "!"]]2 s : ~# ++FILE NOT FOUND++$: F*}’">͇†]<  CANNOT CLOSE CRCFILE$CRCKLISTCRCSK FULL: CRCFILE$  w# !]͐ DONE$!e S!]Q !eZ @ --> FILE: XXXXXXXX.XXX CRC = oS) \<‘@ ++OPEN FAILED++ !" !" * | ʹ) \!~2 #" Ý: ) > T : ) @ ++FILE READ Eth file - ! ~T #M M 2 2 2 2 ! >2 3o: : @ ***No CRC Files found***$> ʉ ʉw#: <2 P6: .6@ Can not parse string ! ~ʽT #ñM ! > 6 #6^#6! ~T #! 4M #x] #e w~ T #>2 @ - s M@ File not found ! 4 >2 o: G: „: G: „@ *Match* 2 ! 4@ <-- is, was --> : ) > T : ) M 2 ! 4<2 ~# @ Not a space between CRC values<2 G-CATALOG??? /* ** print all assembler info before any code is generated */ header() { beglab=getlabel(); #ifndef LINK if(beglab < 3) #endif /* LINK */ { #ifdef SMALL_VM ol("LXI D,$+6"); ol("JMP CC9998"); #endif /* SMALL_VM */ #ifdef LINK jump(beglab); #endif } } /* ** print any assembler stuff needed at the end */ trailer() { #ifdef SMALL_VM #ifndef LINK if((beglab == 1)|(beglab > 9000)) #endif /* LINK */ { ol("CC9997:JMP CCBOJ"); H MOV B,M ;;BC -> CASE ADDR, ELSE 0 INX H MOV A,B ORA C JZ SWEND ;;DEFAULT OR CONTINUATION CODE MOV A,M INX H CMP E MOV A,M INX H JNZ SWLOOP CMP D JNZ SWLOOP MOV H,B ;;CASE MATCHED MOV L,C SWEND: PCHL ; ;#endasm END RROR++ <* |): o% |g}o" 2  ; 0T ~T #~A > T > _h : F{͇2h2|: ʲ !\   :\2 ! \  \ ! \  \! \  \<7=Ɓo&   ]  2h2|2   ~$#~# x  : F} *}= ">͇1 ].”#””͡”››tK››͸›* =: =͔="  ʳ ª~#.  ¿~  #~  .+~#0:0~#!A.O.Gy~#0M0 K MMɷ:m2 FSÄCRCKLIST$$$››tK›, › **}|!"*{z*~]*"Ü  DISK FULL: CRCFILE$!"*~ ol("CC9998:DS 6"); ol("PUSH D"); ol("LXI D,$+6"); ol("JMP CC9997"); ol("ORG CC9998"); ol("JMP $+6"); } #endif /* SMALL_VM */ ol("END"); } /* ** load # args before function call */ loadargc(val) int val; { #ifdef HASH if(search("NOCCARGC", macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) { #else /* HASH */ if(findmac("NOCCARGC")==0) { #endif /* HASH */ ot("MVI A,"); outdec(val); nl(); } } /* ** declare entry point */ entry() { #CRC.COM 5.0 6/18/82CRCKFILE???!9" 1 M @ CRC Ver 5.0 CTL-S pauses, CTL-C aborts :] O@ ++Searching for CRCKLIST file++@ Now searching for "CRCKFILE" file++ !  1 .) F!  ͡]͸! ͔0CRCKLIST???CRCKFILE???!9" M à*,*.}|ډ!".*,{z{** u*.".G*.",!".***,}>*.#".ɯ22)! ",". <  NO FILECRC FILE$!   >. @ Checking wi match - : ̓ : J M @ Quantity of lines failed parse test - : ̓ : ~ M @ Quantity of file(s) not found - : ̓ * d͔  ͔ 0T  Җ Wyʩ 0T 0ztiil   outstr(ssname); col(); #ifdef LINK if (m80flg) { col(); nl(); } else ol("ENTRY"); #else /* LINK */ nl(); #endif /* LINK */ } /* ** declare external reference */ external(name) char *name; { #ifdef LINK if (m80flg) { ot("EXTRN "); outstr(name); nl(); } else { outstr(name); col(); ol("EXTRN"); } #endif /* LINK */ } /* ** fetch object indirect to primary register */ indirect(lval) int lval[]; { if(next; while(--sour > dest) { /* adjust stack references */ #ifdef TAB if(streq(sour,"\tDAD SP")) { #else /* TAB */ if(streq(sour," DAD SP")) { #endif /* TAB */ --sour; i=BPW; while(numeric(*(--sour))) { if((*sour = *sour-i) < '0') { *sour = *sour+10; i=1; } else i=0; } } } csp=csp+BPW; } /* ** pop stack to the secondary register */ pop() { ol("POP D"); csp=csp+BPW; } /* ** ** move primary register to secondary */ move() { ol("MOV D,H"); ol("MOV E,L"); } /* ** swap primary and secondary registers */ swap() { ol("XCHG;;"); /* peephole() uses trailing ";;" */ } /* ** partial instruction to get immediate value ** into the primary register */ immed() { ot("LXI H,"); } /* ** partial instruction to get immediate operand ** into secondary register */ immed2() { ot("LXI D,"); } /* ** push primary register onto stack */ push() zerojump(oper, label, lval) int oper, label, lval[]; { clearstage(lval[7], 0); /* purge conventional code */ oper(label); } #endif /* FULLC */ /* ** define storage according to size */ defstorage(size) int size; { if(size==1) ot("DB "); else ot("DW "); } /* ** point to following object(s) */ point() { ol("DW $+2"); } /* ** modify stack pointer to value given */ modstk(newsp, save) int newsp, save; { int k; k=newsp-csp; if(k==0)return newsp; if(lval[1]==CCHAR) call("CCGCHAR"); else call("CCGINT"); } /* ** fetch a static memory cell into primary register */ getmem(lval) int lval[]; { char *sym; sym=lval[0]; if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) { ot("LDA "); outstr(sym+NAME); nl(); call("CCSXT"); } else { ot("LHLD "); outstr(sym+NAME); nl(); } } /* ** fetch addr of the specified symbol into primary register */ getloc(sym) char *sym; { const(getin* swap primary register and stack */ swapstk() { ol("XTHL"); } /* ** process switch statement */ sw() { call("CCSWITCH"); } /* ** call specified subroutine name */ call(sname) char *sname; { ot("CALL "); outstr(sname); nl(); } /* ** return from subroutine */ ret() { ol("RET"); } /* ** perform subroutine call to value on stack */ callstk() { immed(); outstr("$+5"); nl(); swapstk(); ol("PCHL"); csp=csp+BPW; } /* ** jump to inter{ ol("PUSH H"); csp=csp-BPW; } /* ** unpush or pop as required */ smartpop(lval, start) int lval[]; char *start; { if(lval[5]) pop(); /* secondary was used */ else unpush(start); } /* ** replace a push with a swap */ unpush(dest) char *dest; { int i; char *sour; #ifdef TAB sour="\tXCHG;;"; /* peephole() uses trailing ";;" */ #else /* TAB */ sour=" XCHG;;"; /* peephole() uses trailing ";;" */ #endif /* TAB */ while(*sour) *dest++ = *sour++; sour=stagek>=0) { if(k<7) { if(k&1) { ol("INX SP"); k--; } while(k) { ol("POP B"); k=k-BPW; } return newsp; } } if(k<0) { if(k>-7) { if(k&1) { ol("DCX SP"); k++; } while(k) { ol("PUSH B"); k=k+BPW; } return newsp; } } if(save) swap(); const(k); ol("DAD SP"); ol("SPHL"); if(save) swap(); return newsp; } /* ** t(sym+OFFSET, OFFSIZE)-csp); ol("DAD SP"); } /* ** store primary register into static cell */ putmem(lval) int lval[]; { char *sym; sym=lval[0]; if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) { ol("MOV A,L"); ot("STA "); } else ot("SHLD "); outstr(sym+NAME); nl(); } /* ** put on the stack the type object in primary register */ putstk(lval) int lval[]; { if(lval[1]==CCHAR) { ol("MOV A,L"); ol("STAX D"); } else call("CCPINT"); } /nal label number */ jump(label) int label; { ot("JMP "); printlabel(label); nl(); } /* ** test primary register and jump if false */ testjump(label) int label; { ol("MOV A,H"); ol("ORA L"); ot("JZ "); printlabel(label); nl(); } /* ** test primary register against zero and jump if false */ #ifdef FULLC zerojump(oper, label, lval) int (*oper)(), label, lval[]; { clearstage(lval[7], 0); /* purge conventional code */ (*oper)(label); } #else /* FULLC */   double primary register */ doublereg() {ol("DAD H");} ^#V"; *;  ͪ  *; q#pÝn* " ! p+q* )*= ^#V"; ! 6> ! i* &*; >OK : <2 E:/ *; ^#V*% DMf kK : *; Nf E*; ~ڻWK þE *; ~SK E = ! 6:! ':/ : = !: = : <2 * " !" >! .  * *&͵ "( * *&͵ > j*( #"( *DM*( V"( !" (   K!" }2 : <2 O:* * * "    >! = * DM** +" *( * " Ø* #" *&C 4Ø:!4:!5(  ! I3= : [= t:\a:\=_: :] t ?]\ : ҃! 6?Î : 2   ]Q  ?\\ : DM, Q ! "= *3 ##)*= "; */ &# "! *3 #"#  !! "% >!1 . 2' \: 2 : ʩ: ƀo&"* ~ʛ*# +"# ** DMY қ** DM  *; q#p* " . ** #DM*; -e**  *; w* #" )*= *; s#r*; "; : 2 !S 6!"V * "n >!S d*S &T ) ^#V"K O!l ^#V"M :S =2S M K  a*K "G *!9"<2:g.!"!"!͍G~ R><͍{ j>R>!>G"s#r# PGMNAME5[?!j!f|[">~R5[?!j!h|[">~R 5!jw#V [ E6Mz rwT:6 0'{2,6iolib: Unable to open < or > file$33;;33;;:g.* og*|:_*!!*( * " 3*1 #" " " *5 " > # R : B * +" ! +s#r( ! 6: " * ~2 * #" * +" > ʶ : 2 Ғ * +" : <2 O>ҳ ! 6* #" * ~2 p ̓: AOK = * Ͱ= * ͷ= * Ͱ= *# ͷ= * Ͱ= . g S -A >>!  ~?l W >#^ : /!:' —  ʑ #‹  W ʢ #™ i`N#FogDM!>))덑o|g =¼ DM!>)) = ^#V) ^#V|g}o M "I *K  )*= ^#V"O I G  *G )*= N#F*O ? J*G #"G (*I )*= ^#V*O DM? m*I +"I JI G  *G )*= ^#V"Q *I )*= *G )*= N#Fq#p*I )*= *Q s#r*G #"G *I +"I K I  G M   !M G  :S <2S O!T *G s#r*S &l ) *M s#r*I "M ^I K  X:S <2S O!T *K s#r*S &l ) *I s#r*G "K û!" "    #* #" )*= * #" )*= N#Fq#p   * )*= * ) *= ^#VN#F? H * #" )*= ^#V";  *; ^#V" * )*=  !̈́ Aborted, reason = !p>:-!6!6!ɽ("$+D(w2}-*&+:$+(؀(ʀ(N,>s .["&+y(0(̀(! +Oa(!F1(#>2 +:H1(:I1(y6!.C)~Ā((O:1y: +y) Oä(ñ((( }&~6×2-Y!Yw:a{_ O((A{0a0 [8ɿ0:0#|+ }!#1#1)~'!1=o$!1A)~#fo)yw#xw+)Y)##Ň!1F€'= 'ͣ)/*ͩ)'ͣ)5*ͩ)>G'xG Hit Space: KK : k Used: /k Not used: k *% DMf : remain on 1 !9" ! J> # ->! . *ͪe> # < * v K  K  K !B r+s+p+qA ?  p*A *? :]$Ž l]Q !]6 !E 6!C 6 :C *C &l ~2D U¼:E 2 :D S:E 2:D F:E 2:D V:E 2:D P:E 2 :D N2E ! _{ozgO{ozgi`N#Fogo&og_{_z#W OK = Y -S {-_ ! s+p+q*  ͼ 2 <2 : ! ڗ  K ! 4Á ! 6: =! ڻ * & NK ! 4œ >3  03} Z; { ) #    8)?*+;*"+)*+K*|}N))RDMɯO>Gl&*A}g R0OxG *xx )͒)B)́)+ɯw]T ́)> ''#' +#~7( '82828282""#"|$" * *  s#r**͌*n&h *~rDRm*]*A!* s#r*~w{W¸***A!* s#r*!>w*A!*"|.!"*!~N!*͜ *$" * ͜ | !""*n&h *$*M*{"*|d !g !}x G"^#V" * " * * z*6{6* 6#" !* |N!"*a!"*A*!f"*A:©@ ڬ ì:& ..&.! 6}.a{ -..} |-&} %&|5"!~F!*$" ^#V" * ~#•!* |~!* s#r* " * ^#Vr+s* #*  s#r* ~*!~w!~o&*| o&!  *| !PJ " +V6+^6O * +^#6s#r# * 33;;x_ "zʕ |ʊ *|• }• !}w# c 6*z {³ ͓ ¼ ͨ   | } !  | !":  *&""$" ^#V" * ~#k !* |T !* s#r* " * ^#Vr+s* #*  s#r:* w&o*|ʧ ͜ ":  *&*| ~ ^# ~# O  !*!!S"!! "!!"9""7""+""/""-""%"" """"""!"!!!!}!"?"""!!""!!!"}!"3""1"%K'ͭJ!"!!";"!"="v(#͡%w*5"too many command argumentsSmall-C Ver. 2.03 (7/28/83)*/"|Z$![$!bT|$! +T$! +|$T$!b$-T|+$@T$!g$-T|>$͢)T$!p$-T|Q$NT$͉1͛U#extern#asm#include#define!9!LJ* "|%!9͇|!9! LJ!9T]͇+LJ#|%!s!9͇ͪCͩO!9!9͇LJ!* "LJ!]!!=!!H~LJLJ!]!!=!!}LJLJ!]!!=!!}LJLJ!]!!=!!}LJLJ!]!!=!!}LJLJ!]!!=!!}LJLJ!9*3"!|)!*QͶG!9͛U*!z!"*!z!<͇|ʎ*!9!LJ!9!9LJ!|r*!9*!#"!z}!9z!"!9z!>͇|W*!9!LJo*!9T]͇#LJ+!9z}*!9͇!}!9!9LJÙ*!9*!LJ!9͇!*"3"|*!"3"!*QͶG!9nested include files not allowedropen failure on incl͇|%Q%!,Pé$Å$!9͇%ʟ%!9͇|!9!LJ!9T]͇+LJ#|ʜ%!ͩO!9T]͇+LJ!!͇|ʑ%QÜ%!,PH%!%*+"|ʱ%!%Qno closing bracket!9!"""A"LJ!"5"!}2 }2 }2~ }2} }2| !J "!!9T]͇#LJ*!|'!!)͇"!*!z!-|'*!zE&*!zE*!z! ۇ|ʉ&*!z!0S"A"'Ì&þ&!}2} '!}2~ '!}2 '!}2 '!}2| '!'!pQ!C'!pQ!I'!pQ!'E&L&A&M!9͇! |p"!#!͕Q!!9͇"!!9!LJ!9T]͇+LJ#|"!!!9T]͇#LJ+)!9T]͇##LJ++͇LJÅ"!#!pQ!#!pQ!#!pQ!#!͕Q! "ude file!t+!bT|3+!!9͇}+r8!!y+!bT!9͇!͇|p+!!9͇}+r8!!charintͫ@|ʊ+!,-T|ʰ+!9!LJ!9!LJ+!9!LJ!9!LJ!0!!aD|+@!0!>A|+!0!@!,-T| ,!9!LJD,!,-T|D,!91LJ!|9,!,Q!9!LJ!9͇!|b,!0!nwÐ,!9! 9͇!>!9͇!9͇.LJ!0!! 9͇!9͇!!!9͇A! 9!,-T|,+*()[declaration type not allowed,*;!&C&P&Oþ&%usage: cc [file]... [-c] [-m] [-a] [-p] [-l#] [-o] !"1"!"!*9"#"9"*!|'!!*9")͇"!*!z!-|ʎ'W'*!!'"1"|'!'!pQ*!!͕Q!!"7"ͶGW'*7"#"7"+|'!"/"'!"1"ͶGropen error: !]!!=!!}LJLJ!]!!=!! ~LJLJ!]!!=!!~LJLJ!]!!=!!~LJLJ!]!!=!!LJLJ!]! !LJ!=! !LJ!]! !LJ!=! !xLJ!]!!LJ!=!!\LJ!]!!LJ!=!!LJ!]!!=!!9~  | -!.Q*"-!.Qͫ@|(-!.-T|C-!9!LJN-!9!LJ!0!!aD|c-@!9!LJ!.-T|-!91LJ|-!|ʥ-!.Q!9!LJ!9͇!|-!9!9͇!LLJ-!9!LJ3.!.-T|.!9!LJ3.!9͇!!ۇ|3.!9!LJ*"""!0!! 9͇*%"*"S!!!A! 9s.-!.-T|ƒ.-not allowed with gotomust declare first in block*[declaration type not allowed(),!" "!9͇|.!9!LJ!!bT|7! "C"8ͨ>|78!U8!bT|ʠ7a?r8!"C"8!\8!bT|7͍?r8!"C"8!b8!bT|7?r8!"C"8!k8-T|7!"-"8!m8-T|8@!"C"8:r8!"C"*C"charint{ifwhiledoforswitchcasedefaultgotoreturnbreakcontinue;#asm!8-T|Š8!8QÐ8!"-";no semicolon!9*%"LJ!9*!LJ!""*+"#"+"!x9-T|8*/"|8!z9Q8858*+"+"+"!T 3!4Qf@͛U*!!4R|73! 4-T|73!"4Qͫ@|B3E3Ü2!"%"*'"")"*'"|ʧ3!+4!bT|y3!N4r8ä3!04!bT|ʙ3!N4r8ä3!44Qç3Q35!|ʹ3a{* "|3*!"jEQ!x$illegal function or declaration(no open paren)illegal argument name),no commacharintwrong number of arguments!9*'"|a4!9!5-T||4!9!LJÇ4!9!LJ!9!0!!aDLJ|¥4@!5-T|4G!]|4ͫ@|44ò4!9͇!|4!5Q!9!LJ!9͇|k++͇ͩOQýQ>!*>Q!8>ARE"!ZEmultiple defaultsnot in switch:*9!Q>Q>!>QW>!";!!0!!aD|t>>͛{|>!>Qr8not allowed with block-localsbad label͛U!9*!LJ!0!!aD|>[G!:|>>ZE!*!SyG!!0!͉A9!9͇LJ@w!/-T|ʋ/!/-T|p/!9͇|e/!9͇!9͇!90!0-T|b/e/+/!0AË/!9͇!9͇!90!9͇!!9͇ۇ|/!! 9!LJpu!9!LJ!9͇x$!9͇!9͇ %!9͇={,}!9 u|ʄ0!9͇!! 9͇!͇|B0!0Q!9͇!9͇͇* "!9͇SSLJ!9͇!|ʁ0D|0!9͗r|0!9͇!|ʭ0!1Q! 9͇pu!9͇!9͇͇!SLJmust assign to char pointer or array|"%""!!*!!*!|j9*!!qC"#!*!!z|a9*!!*#!|^9!9T]͇#LJ+*!!#"!!+z}09g9*#!"!! 9"!!""}no final }!9RELJ!!p5! :!bT|9ZE!9RELJ*C"!*C"! ۇ|9͛{ZE5ZEelse!9!9!9YO!9!9^}O*"!,|R:]:!yG:!9!9!9F!9͇ZE!9͇!!p5!9͇͛{!9͇ZEF!9!9!9F!9RELJZE5!4;A!9͇ZE!95!9!0!͉ALJ|c5!9͇}! 9͇}*)"!ͪCS!Dk5!5Q*'"!S"'"ͫ@|ʆ5!9!5-T|›5!5QS4!9*[declaration type not allowednot an argument,no comma*"!*/"ۇ|5!!8!bT|6!,r88!&8!bT|76!,r88*"q6*+"!|T6*""9!*%"*"S!T|"%"!""!*8-T|ʄ6͠88!,8!bT|ʢ6ͅ9!"C"8!/8!bT|6c:!"C"8!58!bT|6:!"C"8!88!bT|6:;! "C"8!<8"!!|?*!!z|?!U?QC?!0!!!RE!!!A! 9"!!*!!!ͪCnot a labelͫ@||?:!!T|É?!!T|a{!9*"FLJ|¦?͇!T|͇͛{!9*"LJ!9FLJ|?͇|???͇!T|͇͛{!"?"G![@-T|6@Q@*/"|A@Q@*!*5"͕Q#@ͶG!"?"#endasmf@GE|ʉ@*"E|ʆ@[Gs@ç@*"E|§@*"|¡@ç@[GÉ@͛U͛U*!!@R*"!͇;!@Qf@illegal symbol!@Qalready definedcannot assign to pointer!o1-T|-1!!9͗r|F1!9!LJ寴b1!q1Q!9ZLJ!1A]negative size illegal]!";!"9!!" ""C"RE"!"!"!:~ {|1*!!͕Q!0!!aD|1!3QͶG*"|1*#"ZE!""!9!0!>ALJ|V2z!|'2!0!@S2z!|G2!0!@S2!}x2!0!!!!!!!A! 9!3-T|2!3Q@w!"!!"'"!4-T|E3!0!!aD|3!0!͉A|2!0!@2!0!!!*'"!!!A! 9*'""'"͇!!p͛{!9͇ZEFr8! 9while!9!9F!9RELJ!9RELJ!<A!<-T|{;:r8ZE!<-T|©;!9͇!!pr8͛{!9͇ZE!<-T|;:!<A͛{ZE5!9͇͛{!9͇ZEF! 9(;;))!9!9*!LJ!9*!LJ!9!9*!LJLJ! 9F*"!S!LJ!g=A:!i=A!"!!"!!9RELJ͛{5! 9͇͛{!9͇ZE4{*!|=!|!9T]͇##LJ++͇jE!,P!9T]͇##LJ!  -T|A!AQmissing token!/AQmust be lvalue!"!!*!!*!|ʅA*!!!\S|wA*!!*!!qC"!!HA!*!!S"!!*!!!%|A*!!*!!zS"!!*!!!\S|A*!!!S*!!!S!S"!!ÖA!!9͇!!|RB! 9͇>A"#!|B*#!*!! |BB!8CQ!!9͇͇"!!ÊB*!!!S%|}B!UCQ!!9͇͇"!!*!!! 9z}*!!!9z}*!!}!9͇*!!!D*!!"#!"%!! 9͇zE|C*#!#"#!+!9T][GJÉM*"!"|ʐK*"͇J[G*"!"*!!Sz!\*!!Sz!\ۇ͇|ʂK*"|wK!MQÂK[G͇J#K[G!"͇JÉM*"!'|L!'͇J[G*"!'*!!Sz!\*!!Sz!\ۇ͇| L*"|K!MQ L[G͇JêK[G!'͇JÉM*"!/*"!*ۇ|ʊL!yG*"!**"!/ۇ|L*"|nL!yG|L#I*/"||LL=L!yGÉM*"E|ʁM!9!LJ*"E|L!9͇!|L!'!!9T]͇#LJ+*"}[GâL!'!!9͇!}!9!'!NG!GQ!!Sout of context*!z! |AG!*!z! |WG!!!9*"LJ|tG!yG|ʑG*!"!×G*!"!*!z""""|ʵG*!z""*!!}!yG*"|G*/"|G!ͭJG[G*1"!|GK'*/"|H!9*3"LJ!|'H!9*1"LJ*!!d!9͇{H|jH*3"!|aH!"3"gH!"1"uH!yGG;!9! 9͇LJ!9!9͇ }!ۇ! |H!9T]͇+LJ|H!H!|I!9z!|H!3! 9T]͇#LJ+!9!*!#"!+!9z}+Q!9z*5"KQ!9zstaging buffer overflow!9z!9͇͜ !|oQͼQ!9͇!9͇ !|ʔQͼQ!9͇!9͇pQ! !9͇KQ!Q! !output error ! P! P!:P*-"|R!"-"*!!͕Q!zR:} {|=R!!͜ : {|_R! ! |_RHR*A"yRyR*A"zR!9*!LJ!9T]͇#LJ+*!,|ʹR! !9͇KQËR!R!9͇͕Q!R!9͇pQ!9͇!9͇͕Q/\**** !9͇#LJ+z}B*#!*#!*%!S}!9͇*#!#"#!LJ*!!global symbol table overflowlocal symbol table overflow!9!9͇LJ!9T]͇#LJ+z! |ʥCÅC!9!9͇!9T]͇+LJzLJ!9T]͇+LJ#|D!9!L! 9͇!9͇z!ۇ͇LJC!9T]͇+LJ#|`D!9T]͇#LJ+!9͇}!9!9͇!>LJD;͛U*"E|yD!3!9!LJ*"E|D!9͇|ʼD!9͇!9͇[GE}D!9͇!9͇[G}!9͇!|D!9T]͇#LJÄD!9͇!LJ|@M!9!/!9T]͇#LJ+z}|=M!9z͇J M~M!9!LJ!9!'!!9T]͇#LJ+z}|~M!9z͇JKMÉM[G͇JJ*"!d|ʣM!MQ!͇J!"!!yG3no quoteno apostropheline too long!MQ!"-"no matching #if...!'!!aD|N@ͶG!9!LJ!'!!9T]͇#LJ+zͤN|MN)N+G|[N[GMN[GͤN|kN[N* "!|ʊN!NQ!macro string queue full!/* "!9z}* "!|N* "#" "!9z!" "* "* "|UO!/* "!\Sz!ۇ}ÌH! 9͇!}33G*/"|/I!kJ-T|gI*"#""*"|NI#I͛U*!N|dI*"""#I!rJ-T|ʟI*"#""*"|ʆI#I͛U*!N|ʜI*"""#I!zJ-T|I*"|I*"*"|I!""I*"|I*"""IM#I!J-T|J*"|J*"*"| J!""*"+""JM#I*"|(J#I*A"|YJ*A"*5"|LJ!;*5"KQ*!*A"͕Q*"|dJ#IjJ#I#ifdef#ifndef#else#endif*"!d|ʬJ!*"#""!9z};*?"|J!J "!#I*/"|J3J!"!G3!""*"|ʌM+G| K! ͇J+G|K!LJ!9͇z|WS!9͇z!9͇z|GS!!9T]͇#LJS!9!LJ!9͇|S!9͇z!9͇z|ʤSS!9͇z! |SS!9͇z! |SS!9T]͇#LJhS!9͇zE| T!!9͇zE|(T!͛U!9*!!9͇RLJ|\TyG!!͛U!9*!! 9͇! 9͇\SLJ|ʭTyG*"E|ʨTGÕT!!!"}!͛U!"!!9͇z! |U!9*!#"!+!9T]͇#LJ+z}T9͇!}!33!9z!a!9z!zۇ|IE!9z! S!9z*"#""jEQQ!|E͵PͩOCC!9z!a!9z!zۇ!9z!A!9z!Zۇ͇!9z!_͇!9z!0!9z!9ۇ!9zE!9zE͇!9͇*%"LJ!9͇RELJ!9͇RELJ*"!!<!S|zF!FQ!!9!LJ!|F*"##""++!9͇!9T]͇#LJ+)͇LJÅFtoo many active loops*"!!%|F*"!S""!!,||"O!/* "#" "+z|OO* "!/* "#" "+z|:O"O!/* "#" "+z|RO:ON!!9͇*!LJ|rO! "!*!LJ*!!}!9͇"!|ʖO|ʨO;!9!LJ!9!'LJ!9͇O!9!9͇ZLJ!-P!9͇!|ʗP!9! 9͇!9͇͆0}!9z!0!9͇!͇!9͇͇|aP!9!LJ!9zP!9! 9͇!9͇͆LJ!9!9͇! ͆LJO3ͨPQQ͵Pz! |P!9T]͇#LJ+zPõP*!|Q*!*!|Q!3QQ"  !9*!!}*!!9R"!|iU*!*!z!=*!*!z*!*!!Szۇ|iU!!9͇z|ʏU!9T]͇#LJ*}!#"}!ÕU!þT*"|ʵU+G|ʱU[GòUÛU*!!J |UͭJ*/"|UUÛUU!9!9!LJ!9!9͇!9͇hXLJ!9͇ͳT|qV*!yG!9͇|DV!9!LJ!9RELJ!9͇!9͇!9͇!9͇EW!9ͣ~!!Wg-T|*g|f&A!!~!!9͇!LJLJLJLJ!!9!9͇!9U!9!9͇|]Wo}W͇|}W͇s!9͇!9͇!W!9!9!9͇!9͇hXLJ!9͇ͳT|W!9͇!9!9͇|W!9͇o!9͇ͳT|TX*!yG*}!!9͇"}!!=!*}!)͇!]!*}!)͇!9͇!9͇!9X! 9_X!!9W!9!9!9YO!9! 9͇! 9͇!XLJ!9͇͇|ʾX!9͇!}O!9!9YO!9͇ !LJ!9͇!LJ!9͇|\a|%aʹy!9͇o!9͇!__!9͇! 9X! 9|Ya {a|ʜa!9͇o!9͇!__!9͇! 9X! 9a!9__|ʳa!9o!9͇ !9 ͇LJ!9͇͸o!!9!9|=^=&=+=-=*=/=%=>>=<<==!:b!~!!!9!=b!9͇U! 9||!kb!%!!!9!nb!9͇U! 9&&!b!!9!b! 9͇͕W!9|!b!!9!b! 9͇͕W!9^!b!!9!b! 9͇͕W!9&! c!!9!c! 9͇ԇ!9͇!~|,]!9͇ۇ!9͇!~|O]!9͇!9͇!|r]!9͇!9͇!|ʕ]!9͇!9͇!x|ʸ]!9͇!9͇!\|]!9͇!9͇!|]!9͇!9͇!9~|!^!9͇>!9͇!H~|D^!9͇L!9͇!}|e^!9͇!9͇!}|ʈ^!9͇S!9͇!}|ʫ^!9͇f!9͇!}|^!9͇͆!9͇!}|^!9͇͆!!9!99͇o!9͇͇!>u~!++--~!-*&illegal address++--!9!9! 9͇̈́jLJ!9! 9͇͇LJ͛U*"![*"!(͇|j!9͇ !LJ!\j-T|gi!9͇|g!^jQf@!njA!!9!9͇z!|h!9͇o?h!9͇z!|?h!pjQ!9!LJ!9!9YO!9!LJ!!!__! 9!9X! 9!jA!9͇|h!}O!9͇|h!9͇z!|h!9͇!Lsh!9͇s͹}i!͇͇|ʊY! 9͇!9͇hX|5Y!9͇o!9͇͇|ZY!9͇*!LJ!9͇͇!9͇! 9͇.nLs[ʹy! 9͇!9͇hX|ʳY!9͇o!9͇͇|ʇZ!9͇͇|Y!9͇LJ!9͇!}|EZ*%""%"!}O!9͇͇! 9͇! 9͇.nLsÄZ!9͇͇! 9͇! 9͇.nLs!9͇y[!9͇y!9͇!}!9͇!}͇|[!9͇!9͇.n|Zͪ}!9͇! 9͇.n|[̈́yͪ}!9W!9== !=!8c!!9!Bc! 9͇͕W!9<= >= < >!hc! !9!nc! 9͇͕W!9>> <<!c! !9!c! 9͇͕W!9+ -!c! !9!c! 9͇͕W!9* / %!4g-T|d!9͇c|c&A!!u~!9͇o!!7g-T|Bd!9͇c|+d&A!!~!9͇o!!:g-T|ʖd!9͇c|ld!9͇of~!9͇!9͇͇_LJ!!g-T|>e!9͇#  9͇z!|iͪ}͹}!9͇! 9͇!LJLJ!9͇!9͇zLJ!9!LJi!j-T|i!9͇|‹i!(mi!9͇z!|ʸi!9͇o!(mi!9͇(m!9! 9͇!"9͇!LJLJLJi!9͇!9úg!9͇|j!9͇!9!9͇z!|Hj!9͇͂t!!9!9͇!9!9[can't subscript]can't subscript](!l-T|ʵj!9!9͇__LJ!lA!!9͇!D!0!!aD|l!9!0!͉ALJ|ʾkz|kession͔yͩOQͤyͩOQ!9!9͇LJ!LJ!9T]͇##LJs|cs͔yðs͖t|ws͔yðs u|ʬs!S!LJ͔y*!"jE!+Pðs!͇ͩOQ!!9!9!LJLJ!~t-T|st!t-T|t!9!LJt ts*"E|t!*"E|Qt!9!9͇! fG!0SLJt|gt!9ZLJ!9͇LJ!+-͔y͵PQ!9!LJ!u-T|´t!*"!'|t!9!ۇ!fu!ۇLJôt*!#"!!9͇9͇͇LJ͇|ʀo ͇|noʹyo!9͇!9͇͇!>!`o {͸ocy !LJo!9͇!9͇͇!>!o͸o͇|oyo͠x͇!!9͇͇!ۇ|pw pͲw!9!9͇|:p!rA!9!9YO!9__|`p!9o!r-T|p}OÂpÅp:p!9͇|ʙp!rA!9͇|p!}O!9͇|p!9!9͇͛{!9!9͇|pr!9 ͇""*"PQMOV A,LSTA SHLD ͇!|Dy!My͛P!Uy͛PLy!\yF{MOV A,LSTAX DCCPINT!ty͛P!|y͛PMOV D,HMOV E,L!y͛PXCHG;;!yͨPLXI H,!yͨPLXI D,!y͛P*%"!S"%"PUSH H!9͇ ͇|y {yy!9!zLJz|1z!9T]͇#LJ+!9T]͇#LJ+z}z!9*!LJ!9T]͇+LJ!9͇%|z!{R|z!9T]͇+LJ!9!LJ!9T]͇+LJzE|zz!9͇S}!0|zz }!9!LJz!9!LJÂzALJ|ʏlz!|ʏl!9͇LJ!9͇!LJz!|Rlz!|Ll!9͇!9͇zLJ!͂t!9͇!9͇!9͇zLJLJ!!9!0!!!!!!!A! 9LJ!9͇LJ!9͇!LJ!!9͇'s|lm!()!';!!-T|u!3!9͇* "LJ*"!"|Tu*"|DuTuu!pu*u[G!s* "#" "+!}!33* "!|ʕu!uQ!!9͇!s* "!9͇D* "" "literal queue overflow*"!\*"!͇|u[G[G*"!n|v[G! *"!t|1v[G! *"!b|Iv[G!*"!f|av[G! !9!LJ!9!LJ!9T]͇+LJ#!*"!0ۇ*"!7ۇ|v!9!L[G!0SLJwv!|v[GvRE"#"*#"͛{!~*"!͇|5q!~!9͇!9{mr*"!*"!͇|mq!%!9͇!9{mr*"!|ʖq!!9͇!9{mr*"!x|ʿq!!9͇!9{mr*"!|q!9͇!}Omr*"!\|r!j!9͇!9{mr*"!|8r!ʀ!9͇!9{mr*"!|ar!!9͇!9{mr!9͇͵{|r!9͇͵{}O!9(,)!9!9YO!9! 9͇^!}O!9͇|r!rQ!9͇must be constant exprHG;; DAD SP! {͛P*%""%"POP D!/{͛PXTHL!={F{CCSWITCH![{ͨP͵PQCALL !j{͛PRET͔y!{͵PQ&{!{͛P*%""%"$+5PCHL!{ͨPjEQJMP !{͛P!{͛P!{ͨPjEQMOV A,HORA LJZ ͇!}O!9͇!9͇!|!|3|!<|ͨP;|!@|ͨPDB DW !M|͛PDW $+2!9!9͇*%"SLJ|||!9͇寴|!||!ۇ|ʳ|!}͛P!9T]͇+LJ#||!}͛P!9!SLJó|!9͇寴D}!|D}!ۇ|!mQ!sf@invalid expression!9!LJ͛U!9͇|Hmʹy*!!!nR|­mͫ@|emím!9!9^!9͇|ƒm&{ʹy!9!9͇LJ!#n-T|ªmímHm!%nA!9͇!'nR|m!9͇!>w!9͇|n!9͇F{nn{*%"!9͇!T|"%"),)CCARGC!9͇͇!|Ln!͇|`n!!!9͇͇!!9͇͇!ۇ|ʭn!9͇!LJo͇|o!9͇!9͇͇LJ!9͇!9͇͇LJ!9͇!! w͛PEND!0wN|/w!9wͨPͩOQNOCCARGCMVI A,!0!͵PQ: {|_wQQgw!hw͛PENTRY: {|ʐw!wͨP͵PQäw͵PQ!w͛PEXTRN EXTRN͇!|w!wF{w!wF{CCGCHARCCGINT!9!9͇͇LJz!z!ۇ|Ix!axͨP͵PQ!fxF{_x!lxͨP͵PQLDA CCSXTLHLD !ͪC*%"Ss!x͛PDAD SP!9!9͇͇LJz!z!ۇ|x!y͛P!yͨPx!yͨP͵$  }!}͛P!9T]͇#LJ+|;}!}͛P!9LJ}!9͇!9͇|S}̈́ys!}͛P!}͛P!9͇|y}̈́y!9͇INX SPPOP BDCX SPPUSH BDAD SPSPHL!}͛PDAD H!}͛PDAD D!}F{CCSUB!}F{CCMULT!}F{CCDIV}̈́y!~F{CCOR!~F{CCXOR!#~F{CCAND!2~F{CCLNEG!B~F{CCASR!Q~F{CCASL!`~F{CCNEG!o~F{CCCOM!~͛P!9T]͇+LJ!|ʙ~Ü~u~INX H!~͛P!9T]͇+LJ!|~~ã~DCX H!~F{CCEQ!͛P! ͛P!ͨPjE DCALL CCPDPC! ͛P!&͛PPOP HPUSH H!>͛P!D͛PPOP DPUSH D!f͛P!]!l͛PPOP BPUSH Bz##9~ogÇ##9~#fo##9T]z+}##9T]z#}}##9T]͇+LJ##9T]͇#LJ}|}o|g}o|g}o|g++++++|gz{!3+3+3+3+z:{!||g}o?)M{ozg_#|/g}/oDM!yqxGyOȯ{_zWkDMzzLjxψ>)׈ʳ߈}o{_zW=ʼÜLjLjz/W{/_x/Gy/O{_zW{z|.!N#F#x ~#~#P!9!9͇;LJa!R|L!!͛P!9!9͇@LJa!-R|~!m͛P!9!9͇@LJa!yR|ʰ!͛P!9!9͇LJa!R|!͛P!9!9͇LJa!ˆR|!߆͛P!9!9͇LJa!R|F!͛P!9!9͇LJa!9T]͇#LJ+z*5"KQ!9T]͇#LJ+z*5"KQ LXI H,0 DAD SP CALL CCGINT XCHG;; LXI H,2 DAD SP CALL CCGINT XCHG;; DAD SP CALL CCGINTCALL CCDSGI DAD D CALL CCGQMOV A,HORA LJNZ ! F{CCNE!J͛P!R͛P!XͨPjEQMOV A,HORA LJZ !eF{CCLT!͛P!͛P!ͨPjEQXRA AORA HJP !F{CCLE!͛P!͛P!͛P!͛P!͛P! ͨPjEQMOV A,HORA LJZ $+8XRA AORA HJP !F{CCGT!^͛P!d͛P!jͨPjEQ!n͛P!tͨPjEQXRA AORA HJM ORA LJZ !F{CCGE!͛P!͛P!ͨPjEQXRA AORA HJM !ĀF{CCULT!߀ͨPjEQJMP !F{CCULE!F{CCUG`izLjxψ>)׈ʳ߈}o{_zW=ʼÜLjLjz/W{/_x/Gy/O{_zW{z|.!N#F#x ~#~#INTCALL CCDDGI DAD SP CALL CCGCHARCALL CCDSGC DAD D CALL CCGCHARCALL CCDDGC DAD SP MOV D,H MOV E,L CALL CCGINT INX H CALL CCPINTCALL CCINCI DAD SP MOV D,H MOV E,L CALL CCGINT DCX H CALL CCPINTCALL CCDECI DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX DCALL CCINCC DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX DCALL CCDECC DAD D POP D CALL CCPINTCALL CCDDPI DAD D POP D MOV A,L STAX DCALL CCDDPC POP D CALL CCPINTCALL CCPDPI POP D MOV A,L STAXT! F{CCUGEz|ʂ!R|{!R|a-!9!9͇&LJx!9!9͇LJ!R|!DŽR|ā!-K!9!9͇&LJ!K!9!9͇LJ:| {|d!τR| !͛P!9!9͇LJa!R|R!͛P!9!9͇LJa!R|ʄ!&͛P!9!9͇LJa!2R|ʶ!G͛P!9!9͇LJa!SR|!͛P!9!9͇;LJa!R|!Յ%  &  '