ian (01/07/83)
# This is a shell file to make up the sources for.... Small C Version 2, J. E. Hendrix # file created at UTCS Thu Jan 6 12:37:45 EST 1983 # Small C Version 2 is copyright 1982 by J. E. Hendrix # "Public domain" software .. may be used freely but not sold as a product. echo Extracting abs.c cat > abs.c << "//SYSIN DD SYSOUT=*" /* ** abs -- returns absolute value of nbr */ abs(nbr) int nbr; {if(nbr<0) return -nbr; else return nbr;} //SYSIN DD SYSOUT=* echo Extracting call.asm cat > call.asm << "//SYSIN DD SYSOUT=*" #asm ;----- call.a: Small-C arithmetic and logical library ; CCDDGC:ENTRY DAD D JMP CCGCHAR ; CCDSGC:ENTRY INX H INX H DAD SP ; ;FETCH A SINGLE BYTE FROM THE ADDRESS IN HL AND ; SIGN EXTEND INTO HL CCGCHAR:ENTRY MOV A,M ;PUT THE ACCUM INTO HL AND SIGN EXTEND THROUGH H. CCARGC:ENTRY CCSXT:ENTRY MOV L,A RLC SBB A MOV H,A RET ; CCDDGI:ENTRY DAD D JMP CCGINT ; CCDSGI:ENTRY INX H INX H DAD SP ; ;FETCH A FULL 16-BIT INTEGER FROM THE ADDRESS IN HL ;INTO HL CCGINT:ENTRY MOV A,M INX H MOV H,M MOV L,A RET ; CCDECC:ENTRY INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR DCX H MOV A,L STAX D RET ; CCINCC:ENTRY INX H INX H DAD SP MOV D,H MOV E,L CALL CCGCHAR INX H MOV A,L STAX D RET ; CCDDPDPC:ENTRY DAD D CCPDPC:ENTRY POP B;;RET ADDR POP D PUSH B ; ;STORE A SINGLE BYTE FROM HL AT THE ADDRESS IN DE CCPCHAR:ENTRY PCHAR:MOV A,L STAX D RET ; CCDECI:ENTRY INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT DCX H JMP CCPINT ; CCINCI:ENTRY INX H INX H DAD SP MOV D,H MOV E,L CALL CCGINT INX H JMP CCPINT ; CCDDPDPI:ENTRY DAD D CCPDPI:ENTRY POP B;;RET ADDR POP D PUSH B ; ;STORE A 16-BIT INTEGER IN HL AT THE ADDRESS IN DE CCPINT:ENTRY PINT:MOV A,L STAX D INX D MOV A,H STAX D RET ;INCLUSIVE "OR" HL AND DE INTO HL CCOR:ENTRY MOV A,L ORA E MOV L,A MOV A,H ORA D MOV H,A RET ;EXCLUSIVE "OR" HL AND DE INTO HL CCXOR:ENTRY MOV A,L XRA E MOV L,A MOV A,H XRA D MOV H,A RET ;"AND" HL AND DE INTO HL CCAND:ENTRY 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:ENTRY CALL CCCMP RZ DCX H RET ;TEST IF DE != HL CCNE:ENTRY CALL CCCMP RNZ DCX H RET ;TEST IF DE > HL (SIGNED) CCGT:ENTRY XCHG CALL CCCMP RC DCX H RET ;TEST IF DE <= HL (SIGNED) CCLE:ENTRY CALL CCCMP RZ RC DCX H RET ;TEST IF DE >= HL (SIGNED) CCGE:ENTRY CALL CCCMP RNC DCX H RET ;TEST IF DE < HL (SIGNED) CCLT:ENTRY 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:ENTRY MOV A,H;;INVERT SIGN 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:ENTRY CALL CCUCMP RNC DCX H RET ; ;TEST IF DE < HL (UNSIGNED) CCULT:ENTRY CALL CCUCMP RC DCX H RET ; ;TEST IF DE > HL (UNSIGNED) CCUGT:ENTRY XCHG CALL CCUCMP RC DCX H RET ; ;TEST IF DE <= HL (UNSIGNED) CCULE:ENTRY CALL CCUCMP RZ RC DCX H RET ; ;COMMON ROUTINE TO PERFORM UNSIGNED COMPARE ;CARRY SET IF DE < HL ;ZERO/NONZERO SET ACCORDINGLY CCUCMP:ENTRY MOV A,D CMP H JNZ CCUCMP1 MOV A,E CMP L CCUCMP1: LXI H,1 RET ; ;SHIFT DE ARITHMETICALLY RIGHT BY HL AND RETURN IN HL CCASR:ENTRY 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:ENTRY XCHG DCR E RM DAD H JMP CCASL+1 ;SUBTRACT HL FROM DE AND RETURN IN HL CCSUB:ENTRY 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:ENTRY CALL CCCOM INX H RET ;FORM THE ONE'S COMPLEMENT OF HL CCCOM:ENTRY 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:ENTRY MULT:MOV B,H MOV C,L LXI H,0 CCMULT1: MOV A,C RRC JNC CCMULT2 DAD D CCMULT2: XRA A MOV A,B RAR MOV B,A MOV A,C RAR 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 CCMULT1 ;DIVIDE DE BY HL AND RETURN QUOTIENT IN HL, REMAINDER IN DE ;(SIGNED DIVIDE) CCDIV:ENTRY 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 MOV 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 MOV 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:ENTRY 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:ENTRY XCHG;;DE = SWITCH VALUE POP H;;HL -> SWITCH TABLE SWLOOP:MOV C,M INX 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 //SYSIN DD SYSOUT=* echo Extracting cc.def cat > cc.def << "//SYSIN DD SYSOUT=*" /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Macro Definitions */ /* ** compile options */ #define PHASE2 /* 2nd and later compiles */ #define SEPARATE /* compile separately */ #define OPTIMIZE /* compile output optimizer */ #define NOCCARGC /* no calls to CCARGC */ /* #define HASH /* use hash search for macros */ #define SMALL_VM /* uses Small-VM interface */ #define CMD_LINE /* command line run options */ #define DYNAMIC /* allocate memory dynamically */ #define POLL /* poll for operator interruptions */ #define PDS /* uses PDS assembler and loader */ #define COL /* terminate labels with a colon */ /* #define TAB 9 /* put out tabs of this value */ #define UPPER /* force symbols to upper case */ #define LINK /* will use with linking loader */ /* ** machine dependent parameters */ #define BPW 2 /* bytes per word */ #define LBPW 1 /* log2(BPW) */ #define SBPC 1 /* stack bytes per character */ #define ERRCODE 7 /* op sys return code */ /* ** symbol table format */ #define IDENT 0 #define TYPE 1 #define CLASS 2 #define OFFSET 3 #define NAME 5 #define OFFSIZE (NAME-OFFSET) #define SYMAVG 10 #define SYMMAX 14 /* ** symbol table parameters */ #define NUMLOCS 25 #define STARTLOC symtab #define ENDLOC (symtab+(NUMLOCS*SYMAVG)) #define NUMGLBS 180 #define STARTGLB ENDLOC #define ENDGLB (ENDLOC+((NUMGLBS-1)*SYMMAX)) #define SYMTBSZ 2770 /* NUMLOCS*SYMAVG + NUMGLBS*SYMMAX */ /* ** System wide name size (for symbols) */ #define NAMESIZE 9 #define NAMEMAX 8 /* ** 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 */ #ifdef PHASE2 #define SWSIZ (2*BPW) #define SWTABSZ (25*SWSIZ) #else #define SWSIZ 4 #define SWTABSZ 100 #endif /* ** "while" statement queue */ #define WQTABSZ 30 #define WQSIZ 3 #define WQMAX (wq+WQTABSZ-WQSIZ) /* ** entry offsets in while queue */ #define WQSP 0 #define WQLOOP 1 #define WQEXIT 2 /* ** literal pool */ #define LITABSZ 700 #define LITMAX (LITABSZ-1) /* ** input line */ #define LINEMAX 80 #define LINESIZE 81 /* ** 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 #define MACQSIZE 950 #endif #define MACMAX (MACQSIZE-1) /* ** statement types */ #define STIF 1 #define STWHILE 2 #define STRETURN 3 #define STBREAK 4 #define STCONT 5 #define STASM 6 #define STEXPR 7 /* #define STDO 8 /* compile "do" logic */ /* #define STFOR 9 /* compile "for" logic */ /* #define STSWITCH 10 /* compile "switch/case/default" logic */ #define STCASE 11 #define STDEF 12 /* #define STGOTO 13 /* compile "goto" logic */ //SYSIN DD SYSOUT=* echo Extracting cc1.c cat > cc1.c << "//SYSIN DD SYSOUT=*" /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Part 1 */ #include stdiol.h,2 #include cc.def,2 /* ** miscellaneous storage */ char #ifdef OPTIMIZE optimize, /* optimize output of staging buffer */ #endif alarm, /* audible alarm on errors? */ monitor, /* monitor function headers? */ pause, /* pause for operator on errors? */ #ifdef DYNAMIC *stage, /* output staging buffer */ *symtab, /* symbol table */ *litq, /* literal pool */ #ifdef HASH *macn, /* macro name buffer */ #endif *macq, /* macro string buffer */ *pline, /* parsing buffer */ *mline, /* macro buffer */ #else stage[STAGESIZE], symtab[SYMTBSZ], litq[LITABSZ], #ifdef HASH macn[MACNSIZE], #endif macq[MACQSIZE], pline[LINESIZE], mline[LINESIZE], swq[SWTABSZ], #endif *line, /* points to pline 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, msname[NAMESIZE], /* macro symbol name array */ ssname[NAMESIZE]; /* static symbol name array */ int #ifdef STGOTO nogo, /* > 0 disables goto statements */ noloc, /* > 0 disables block locals */ #endif op[16], /* function addresses of binary operators */ op2[16], /* same for unsigned operators */ opindex, /* index 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 wq[WQTABSZ], #endif #ifdef CMD_LINE argcs, /* static argc */ *argvs, /* static argv */ #endif *wqptr, /* ptr to next entry */ litptr, /* ptr to next entry */ macptr, /* macro buffer index */ #ifndef HASH mack, /* variable k for findmac routine */ #endif pptr, /* ptr to parsing buffer */ oper, /* address of binary operator function */ ch, /* current character of line being scanned */ nch, /* next character 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 */ 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 assembly code */ listfp, /* file pointer to list device */ lastst, /* last executed statement type */ *iptr; /* work ptr to any int buffer */ #ifdef SEPARATE #ifdef LINK #ifdef PDS #asm CC2.R:LIBRY CC3.R:LIBRY CC4.R:LIBRY #endasm #endif #endif extern int addmac(), addsym(), addwhile(), amatch(), blanks(), bump(), clearstage(), col(), delwhile(), endst(), error(), findglb(), findloc(), 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(); extern int constexpr(), expression(), number(), qstr(), test(), stowlit(); extern int add(), and(), asl(), asr(), defstora(), div(), eq(), entry(), external(), ge(), gt(), header(), jump(), le(), lt(), mod(), modstk(), mult(), ne(), or(), point(), ret(), sub(), sw(), trailer(), uge(), ugt(), ule(), ult(), xor(); #endif #include cc11.c,2 #include cc12.c,2 #include cc13.c,2 #ifndef SEPARATE #include cc21.c,2 #include cc22.c,2 #include cc31.c,2 #include cc32.c,2 #include cc33.c,2 #include cc41.c,2 #include cc42.c,2 #endif //SYSIN DD SYSOUT=* echo Extracting cc11.c cat > cc11.c << "//SYSIN DD SYSOUT=*" /* ** execution begins here */ #ifdef CMD_LINE main(argc, argv) int argc, *argv; { argcs=argc; argvs=argv; #else main() { #endif #ifdef 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 macq=CCALLOC(MACQSIZE); pline=CCALLOC(LINESIZE); mline=CCALLOC(LINESIZE); #else swend=(swnext=swq)+SWTABSZ-SWSIZ; stagelast=stage+STAGELIMIT; #endif 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= quote[1]=0; func1= /* first function */ ccode=1; /* enable preprocessing */ wqptr=wq; /* clear while queue */ quote[0]='"'; /* fake a quote literal */ input=input2=EOF; 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 symtab=CCALLOC(NUMLOCS*SYMAVG); /* global space is allocated with each new entry */ #endif #endif #ifdef HASH cptr=STARTGLB-1; while(++cptr < ENDGLB) *cptr=0; #endif glbptr=STARTGLB; glbflag=1; ctext=0; header(); /* intro code */ setops(); /* set values in op arrays */ parse(); /* process ALL input */ outside(); /* verify outside any function */ trailer(); /* follow-up code */ fclose(output); } /* ** process all input text ** ** At this level, only static declarations, ** defines, includes and function ** definitions are legal... */ parse() { while (eof==0) { if(amatch("extern", 6)) dodeclare(EXTERNAL); else if(dodeclare(STATIC)); else if(match("#asm")) doasm(); else if(match("#include"))doinclude(); else if(match("#define")) addmac(); else newfunc(); blanks(); /* force eof if pending */ } } /* ** dump the literal pool */ dumplits(size) int size; { int j, k; k=0; while (k<litptr) { #ifdef POLL CCPOLL(1); /* allow program interruption */ #endif defstorage(size); j=10; while(j--) { outdec(getint(litq+k, size)); k=k+size; if ((j==0)|(k>=litptr)) { nl(); break; } outbyte(','); } } } /* ** dump zeroes for default initial values */ dumpzero(size, count) int size, count; { int j; while (count > 0) { #ifdef POLL CCPOLL(1); /* allow program interruption */ #endif defstorage(size); j=30; while(j--) { outdec(0); if ((--count <= 0)|(j==0)) { nl(); break; } outbyte(','); } } } /* ** verify compile ends outside any function */ outside() { if (ncmp) error("no closing bracket"); } /* ** get run options */ #ifdef CMD_LINE ask() { int i; i=listfp=nxtlab=0; output=stdout; #ifdef OPTIMIZE optimize= #endif alarm=monitor=pause=NO; line=mline; 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; } #ifdef OPTIMIZE if(upper(line[1])=='O') { optimize=YES; continue; } #endif if(upper(line[1])=='P') { pause=YES; continue; } } #ifndef LINK if(upper(line[1])=='B') { bump(0); bump(2); if(number(&nxtlab)) continue; } #endif sout("usage: cc [file]... [-m] [-a] [-p] [-l#]", stderr); #ifdef OPTIMIZE sout(" [-o]", stderr); #endif #ifndef LINK sout(" [-b#]", stderr); #endif sout("\n", stderr); abort(ERRCODE); } } #else ask() { #ifdef OPTIMIZE optimize= #endif monitor=alarm=pause=listfp=nxtlab=0; line=mline; while(1) { prompt("Output file: ", line, LINESIZE); if(output=fopen(line, "w")) break; else lout("open error"); } #ifndef LINK while(1) { prompt("Beginning label number: ", line, LINESIZE); bump(0); if(number(&nxtlab)) break; } #endif while(1) { prompt("Monitor function headers? ", line, LINESIZE); if(upper(*line)=='Y') monitor=YES; else if(upper(*line)!='N') continue; break; } while(1) { prompt("Sound alarm on errors? ", line, LINESIZE); if(upper(*line)=='Y') alarm=YES; else if(upper(*line)!='N') continue; break; } while(1) { prompt("Pause on errors? ", line, LINESIZE); if(upper(*line)=='Y') pause=YES; else if(upper(*line)!='N') continue; break; } #ifdef OPTIMIZE while(1) { prompt("Optimize for size? ", line, LINESIZE); if(upper(*line)=='Y') optimize=YES; else if(upper(*line)!='N') continue; break; } #endif while(1) { prompt("Listing file descriptor: ", line, LINESIZE); if(numeric(*line)&(line[1]==NULL)) listfp=*line-'0'; else if(*line!=NULL) continue; break; } } #endif /* ** get next input file */ openin() { input=EOF; #ifdef CMD_LINE while(getarg(++filearg, pline, LINESIZE, argcs, argvs)!=EOF) { if(pline[0]=='-') continue; #else while(prompt("Input file: ", pline, LINESIZE)) { #endif if((input=fopen(pline,"r"))==NULL) { lout("open error", stderr); abort(ERRCODE); } files=YES; kill(); return; } if(files++) eof=YES; else input=stdin; kill(); } #ifndef CMD_LINE prompt(msg, ans, anslen) char *msg, *ans; int anslen; { sout(msg, stderr); fgets(ans, anslen, stderr); } #endif setops() { op2[00]= op[00]= or; /* heir5 */ op2[01]= op[01]= xor; /* heir6 */ op2[02]= op[02]= and; /* heir7 */ op2[03]= op[03]= eq; /* heir8 */ op2[04]= op[04]= ne; op2[05]=ule; op[05]= le; /* heir9 */ op2[06]=uge; op[06]= ge; op2[07]=ult; op[07]= lt; op2[08]=ugt; op[08]= gt; op2[09]= op[09]= asr; /* heir10 */ op2[10]= op[10]= asl; op2[11]= op[11]= add; /* heir11 */ op2[12]= op[12]= sub; op2[13]= op[13]=mult; /* heir12 */ op2[14]= op[14]= div; op2[15]= op[15]= mod; } //SYSIN DD SYSOUT=* echo Extracting cc12.c cat > cc12.c << "//SYSIN DD SYSOUT=*" /* ** open an include file */ doinclude() { blanks(); /* skip over to name */ if((input2=fopen(lptr,"r"))==NULL) { input2=EOF; error("open failure on include file"); } kill(); /* clear rest of line */ /* so next read will come 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; } /* ** delcare a static variable */ declglb(type, class) int type, class; { int k, j; while(1) { if(endst()) return; /* do line */ if(match("*")) { j=POINTER; k=0; } else { j=VARIABLE; k=1; } if (symname(ssname, YES)==0) illname(); if(findglb(ssname)) multidef(ssname); if(match("()")) j=FUNCTION; else if (match("[")) { k=needsub(); /* get size */ j=ARRAY; /* !0=array */ } if(class==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 if(declared < 0) error("must declare first in block"); while(1) { while(1) { if(endst()) return; if(match("*")) j=POINTER; else j=VARIABLE; if (symname(ssname, YES)==0) illname(); /* no multidef check, block-locals are together */ k=BPW; if (match("[")) { k=needsub(); if(k) { j=ARRAY; if(typ==CINT)k=k<<LBPW; } else j=POINTER; } else if(match("()")) j=FUNCTION; else if((typ==CCHAR)&(j==VARIABLE)) k=SBPC; declared = declared + k; addsym(ssname, j, typ, csp - declared, &locptr, AUTOMATIC); break; } if (match(",")==0) return; } } /* ** initialize global objects */ initials(size, ident, dim) int size, ident, dim; { int savedim; litptr=0; if(dim==0) dim = -1; savedim=dim; entry(); if(match("=")) { if(match("{")) { while(dim) { init(size, ident, &dim); if(match(",")==0) break; } needtoken("}"); } else init(size, ident, &dim); } if((dim == -1)&(dim==savedim)) { stowlit(0, size=BPW); ident=POINTER; } dumplits(size); dumpzero(size, dim); return ident; } /* ** evaluate one initializer */ init(size, ident, dim) int size, ident, *dim; { int value; if(qstr(&value)) { if((ident==VARIABLE)|(size!=1)) error("must assign to char pointer or array"); *dim = *dim - (litptr - value); if(ident==POINTER) point(); } else if(constexpr(&value)) { if(ident==POINTER) error("cannot assign to pointer"); stowlit(value, size); *dim = *dim - 1; } } /* ** get required array size */ needsub() { int val; if(match("]")) return 0; /* null size */ if (constexpr(&val)==0) val=1; if (val<0) { error("negative size illegal"); val = -val; } needtoken("]"); /* force single dimension */ return val; /* and return size */ } /* ** begin a function ** ** called from "parse" and tries to make a function ** out of the following text ** ** Patched per P.L. Woods (DDJ #52) */ newfunc() { char *ptr; #ifdef STGOTO nogo = /* enable goto statements */ noloc = 0; /* enable block-local declarations */ #endif lastst= /* no statement yet */ litptr=0; /* clear lit pool */ litlab=getlabel(); /* label next lit pool */ locptr=STARTLOC; /* clear local variables */ if(monitor) lout(line, stderr); if (symname(ssname, YES)==0) { error("illegal function or declaration"); kill(); /* invalidate line */ return; } if(func1) { postlabel(beglab); func1=0; } if(ptr=findglb(ssname)) { /* already in symbol table ? */ if(ptr[IDENT]!=FUNCTION) multidef(ssname); else if(ptr[OFFSET]==FUNCTION) multidef(ssname); else ptr[OFFSET]=FUNCTION; /* earlier assumed to be a function */ } else addsym(ssname, FUNCTION, CINT, FUNCTION, &glbptr, STATIC); if(match("(")==0) error("no open paren"); entry(); locptr=STARTLOC; argstk=0; /* init arg count */ while(match(")")==0) { /* then count args */ /* any legal name bumps arg count */ if(symname(ssname, YES)) { if(findloc(ssname)) multidef(ssname); else { addsym(ssname, 0, 0, argstk, &locptr, AUTOMATIC); argstk=argstk+BPW; } } else {error("illegal argument name");junk();} blanks(); /* if not closing paren, should be comma */ if(streq(lptr,")")==0) { if(match(",")==0) error("no comma"); } if(endst()) break; } csp=0; /* preset stack ptr */ argtop=argstk; while(argstk) { /* now let user declare what types of things */ /* those arguments were */ if(amatch("char",4)) {doargs(CCHAR);ns();} else if(amatch("int",3)) {doargs(CINT);ns();} else {error("wrong number of arguments");break;} } if(statement()!=STRETURN) ret(); if(litptr) { printlabel(litlab); col(); dumplits(1); /* dump literals */ } } /* ** declare argument types ** ** called from "newfunc" this routine adds an entry in the ** local symbol table for each named argument ** ** rewritten per P.L. Woods (DDJ #52) */ doargs(t) int t; { int j, legalname; char c, *argptr; while(1) { if(argstk==0) return; /* no arguments */ if(match("*")) j=POINTER; else j=VARIABLE; if((legalname=symname(ssname, YES))==0) illname(); if(match("[")) { /* is it a pointer? */ /* yes, so skip stuff between "[...]" */ while(inbyte()!=']') if(endst()) break; j=POINTER; /* add entry as pointer */ } if(legalname) { if(argptr=findloc(ssname)) { /* add details of type and address */ argptr[IDENT]=j; argptr[TYPE]=t; putint(argtop-getint(argptr+OFFSET, OFFSIZE), argptr+OFFSET, OFFSIZE); } else error("not an argument"); } argstk=argstk-BPW; /* cnt down */ if(endst())return; if(match(",")==0) error("no comma"); } } //SYSIN DD SYSOUT=* echo Extracting cc13.c cat > cc13.c << "//SYSIN DD SYSOUT=*" /* ** 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 csp=modstk(csp - declared, NO); declared = -1; } if(match("{")) compound(); else if(amatch("if",2)) {doif();lastst=STIF;} else if(amatch("while",5)) {dowhile();lastst=STWHILE;} #ifdef STDO else if(amatch("do",2)) {dodo();lastst=STDO;} #endif #ifdef STFOR else if(amatch("for",3)) {dofor();lastst=STFOR;} #endif #ifdef STSWITCH else if(amatch("switch",6)) {doswitch();lastst=STSWITCH;} else if(amatch("case",4)) {docase();lastst=STCASE;} else if(amatch("default",7)) {dodefault();lastst=STDEF;} #endif #ifdef STGOTO else if(amatch("goto", 4)) {dogoto(); lastst=STGOTO;} else if(dolabel()) ; #endif else if(amatch("return",6)) {doreturn();ns();lastst=STRETURN;} else if(amatch("break",5)) {dobreak();ns();lastst=STBREAK;} else if(amatch("continue",8)){docont();ns();lastst=STCONT;} else if(match(";")) errflag=0; else if(match("#asm")) {doasm();lastst=STASM;} 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 }"); 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 locptr=savloc; /* delete local symbols */ declared = -1; /* 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 if(lastst != STRETURN) jump(flab2); #endif 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() { int wq[4]; /* allocate 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"); postlabel(wq[WQLOOP]); test(wq[WQEXIT], YES); jump(top); postlabel(wq[WQEXIT]); delwhile(); ns(); } #endif #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) { doexpr(); /* expr 3 */ needtoken(")"); } jump(lab1); postlabel(lab2); statement(); jump(wq[WQLOOP]); postlabel(wq[WQEXIT]); delwhile(); } #endif #ifdef STSWITCH doswitch() { int wq[4], endlab, swact, swdef, *swnex, *swptr; swact=swactive; swdef=swdefault; swnex=swptr=swnext; addwhile(wq); needtoken("("); doexpr(); /* evaluate switch expression */ needtoken(")"); swdefault=0; swactive=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; } docase() { if(swactive==0) error("not in switch"); if(swnext > 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 #ifdef STGOTO dogoto() { if(nogo > 0) error("not allowed with block-locals"); else 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); return (getint(cptr+OFFSET, OFFSIZE)); } #endif doreturn() { if(endst()==0) { doexpr(); modstk(0, YES); } else modstk(0, NO); ret(); } dobreak() { int *ptr; if ((ptr=readwhile())==0) return; /* no loops open */ modstk((ptr[WQSP]), NO); /* clean up stk ptr */ jump(ptr[WQEXIT]); /* jump to exit label */ } docont() { int *ptr; if ((ptr=readwhile())==0) return; /* no loops open */ 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; } //SYSIN DD SYSOUT=* echo Extracting cc2.c cat > cc2.c << "//SYSIN DD SYSOUT=*" /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Part 2 */ #include stdio.h,2 #include cc.def,2 /* ** external references in part 1 */ extern char #ifdef DYNAMIC *symtab, *stage, #ifdef HASH *macn, #endif *macq, *pline, *mline, #else symtab[SYMTBSZ], stage[STAGESIZE], #ifdef HASH macn[MACNSIZE], #endif macq[MACQSIZE], pline[LINESIZE], mline[LINESIZE], #endif alarm, *glbptr, *line, *lptr, *cptr, *cptr2, *cptr3, *locptr, msname[NAMESIZE], optimize, pause, quote[2], *stagelast, *stagenext; extern int #ifdef DYNAMIC *wq, #else wq[WQTABSZ], #endif #ifndef HASH mack, #endif 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 part 4 */ #ifdef OPTIMIZE extern int peephole(); #endif #include cc21.c,2 #include cc22.c,2 //SYSIN DD SYSOUT=* echo Extracting cc21.c cat > cc21.c << "//SYSIN DD SYSOUT=*" 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 HASH if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME)) return cptr; #else cptr=STARTGLB; while(cptr < glbptr) { if(astreq(sname, cptr+NAME, NAMEMAX)) return cptr; cptr=nextsym(cptr); } #endif 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; } 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 #ifndef DYNAMIC if(glbptr >= ENDGLB) { error("global symbol table overflow"); return 0; } #endif cptr=*lgptrptr; #endif } 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 *cptr2 = cptr2 - cptr3; /* set length */ *lgptrptr = ++cptr2; #ifdef DYNAMIC if(lgptrptr == &glbptr) CCALLOC(cptr2 - cptr); /* gets allocation error if no more memory */ #endif #endif return cptr; } #ifndef HASH nextsym(entry) char *entry; { entry = entry + NAME; while(*entry++ >= ' '); /* find length byte */ return entry; } #endif /* ** get integer of length len from address addr ** (byte sequence set by "putint") */ getint(addr, len) 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)==0) return 0; k=0; while(an(ch)) { #ifdef UPPER if(ucase) sname[k]=upper(gch()); else #endif sname[k]=gch(); if(k<NAMEMAX) ++k; } sname[k]=0; return 1; } #ifdef UPPER /* ** force upper case alphabetics */ upper(c) char c; { if((c >= 'a') & (c <= 'z')) return (c - 32); else return c; } #endif /* ** return next avail internal label number */ getlabel() { return(++nxtlab); } /* ** post a label in the program */ postlabel(label) int 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 ((alpha(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<WQSIZ) *wqptr++ = ptr[k++]; } delwhile() { if(readwhile()) wqptr=wqptr-WQSIZ; } readwhile() { if (wqptr==wq) { error("no active loops"); return 0; } else return (wqptr-WQSIZ); } white() { /* test for stack/program overlap */ /* primary -> symname -> blanks -> white */ #ifdef DYNAMIC CCAVAIL(); /* abort on stack/symbol table overflow */ #endif 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=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 POLL CCPOLL(1); /* allow program interruption */ #endif while(1) { if (input==EOF) openin(); if(eof) return; if((unit=input2)==EOF) unit=input; if(fgets(line, LINEMAX, unit)==NULL) { fclose(unit); if(input2!=EOF) input2=EOF; else input=EOF; } else { bump(0); return; } } } //SYSIN DD SYSOUT=* echo Extracting cc22.c cat > cc22.c << "//SYSIN DD SYSOUT=*" 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 if(findmac(lptr)==0) #endif skiplevel=iflevel; continue; } if(match("#ifndef")) { ++iflevel; if(skiplevel) continue; blanks(); #ifdef HASH if(search(lptr, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) #else if(findmac(lptr)) #endif 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; } if(skiplevel) continue; if(listfp) { if(listfp==output) cout(';', output); lout(line, listfp); } if(ch==0) continue; break; } } keepch(c) char c; { if(pptr<LINEMAX) pline[++pptr]=c; } preprocess() { int k; char c; if(ccode) { line=mline; ifline(); if(eof) return; } else { line=pline; inline(); return; } pptr = -1; while(ch) { if(white()) { keepch(' '); while(white()) gch(); } 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()); } 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<NAMEMAX) msname[k++]=ch; gch(); } msname[k]=0; #ifdef HASH if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) { k=getint(cptr+NAMESIZE, 2); while(c=macq[k++]) keepch(c); } #else if(k=findmac(msname)) while(c=macq[k++]) keepch(c); #endif 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)==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 while(putmac(msname[k++])); #endif while(white()) gch(); while(putmac(gch())); if(macptr>=MACMAX) { error("macro string queue full"); abort(ERRCODE); } } putmac(c) char c; { macq[macptr]=c; if(macptr<MACMAX) ++macptr; return c; } #ifdef HASH /* ** search for symbol match ** on return cptr points to slot found or empty slot */ search(sname, buf, len, end, max, off) char *sname, *buf, *end; int len, max, off; { cptr=cptr2=buf+((hash(sname)%(max-1))*len); while(*cptr != 0) { if(astreq(sname, cptr+off, NAMEMAX)) return 1; if((cptr=cptr+len) >= end) cptr=buf; if(cptr == cptr2) return (cptr=0); } return 0; } hash(sname) char *sname; { int i, c; i=0; while(c=*sname++) i=(i<<1)+c; return i; } #else findmac(sname) char *sname; { mack=0; while(mack<macptr) { if(astreq(sname,macq+mack,NAMEMAX)) { while(macq[mack++]); return mack; } while(macq[mack++]); while(macq[mack++]); } return 0; } #endif setstage(before, start) int *before, *start; { if((*before=stagenext)==0) stagenext=stage; *start=stagenext; } clearstage(before, start) char *before, *start; { *stagenext=0; if(stagenext=before) return; if(start) { #ifdef OPTIMIZE peephole(start); #else sout(start, output); #endif } } outdec(number) int number; { int k,zs; char c; zs = 0; k=10000; if (number<0) { number=(-number); outbyte('-'); } while (k>=1) { c=number/k + '0'; if ((c!='0')|(k==1)|(zs)) { zs=1; outbyte(c); } number=number%k; k=k/10; } } ol(ptr) char ptr[]; { ot(ptr); nl(); } ot(ptr) char ptr[]; { #ifdef TAB tab(); #endif outstr(ptr); } outstr(ptr) char ptr[]; { #ifdef POLL CCPOLL(1); /* allow program interruption */ #endif /* must work with symbol table names terminated by length */ while(*ptr >= ' ') outbyte(*ptr++); } outbyte(c) char c; { if(stagenext) { if(stagenext==stagelast) { error("staging buffer overflow"); return 0; } else *stagenext++ = c; } else cout(c,output); return c; } cout(c, fd) char c; int fd; { if(fputc(c, fd)==EOF) xout(); } 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 error\n", stderr); abort(ERRCODE); } nl() { outbyte('\n'); } tab() { outbyte(TAB); } col() { #ifdef COL outbyte(':'); #endif } error(msg) char msg[]; { if(errflag) return; else errflag=1; lout(line, stderr); errout(msg, stderr); if(alarm) fputc(7, stderr); if(pause) while(fgetc(stderr)!='\n'); if(listfp>0) errout(msg, listfp); } errout(msg, fp) char msg[]; int fp; { int k; k=line+2; while(k++ <= lptr) cout(' ', fp); lout("/\\", fp); sout("**** ", fp); lout(msg, fp); } streq(str1,str2) char str1[],str2[]; { 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; { int k; k=0; while (k<len) { if ((str1[k])!=(str2[k]))break; /* ** must detect end of symbol table names terminated by ** symbol length in binary */ if(str1[k] < ' ') break; if(str2[k] < ' ') break; ++k; } if (an(str1[k]))return 0; if (an(str2[k]))return 0; return k; } match(lit) char *lit; { int k; blanks(); if (k=streq(lptr,lit)) { bump(k); return 1; } return 0; } amatch(lit,len) char *lit;int len; { int k; blanks(); if (k=astreq(lptr,lit,len)) { bump(k); while(an(ch)) inbyte(); return 1; } return 0; } nextop(list) char *list; { char op[4]; opindex=0; blanks(); while(1) { opsize=0; while(*list > ' ') 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) { if(white()) gch(); else return; } if(line==mline) return; preprocess(); if(eof)break; } } //SYSIN DD SYSOUT=* echo Extracting cc3.c cat > cc3.c << "//SYSIN DD SYSOUT=*" /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Part 3 */ #include stdio.h,2 #include cc.def,2 /* ** external references in part 1 */ extern char #ifdef DYNAMIC *stage, *litq, #else stage[STAGESIZE], litq[LITABSZ], #endif *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 */ 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 add(), and(), asl(), asr(), call(), callstk(), com(), dec(), div(), doublereg(), eq(), eq0(), ge(), ge0(), getloc(), getmem(), gt(), gt0(), immed(), immed2(), inc(), indirect(), jump(), le(), le0(), lneg(), loadargc(), lt(), lt0(), mod(), modstk(), move(), mult(), ne(), ne0(), neg(), or(), pop(), push(), putmem(), putstk(), ret(), smartpop(), sub(), swap(), swapstk(), testjump(), uge(), ugt(), ule(), ult(), ult0(), xor(), zerojump(); #include cc31.c,2 #include cc32.c,2 #include cc33.c,2 //SYSIN DD SYSOUT=* echo Extracting cc31.c cat > cc31.c << "//SYSIN DD SYSOUT=*" /* ** lval[0] - symbol table address, else 0 for constant ** lval[1] - type of indirect obj to fetch, else 0 for static ** lval[2] - type of pointer or array, else 0 for all other ** lval[3] - true if constant expression ** lval[4] - value of constant expression ** lval[5] - true if secondary register altered ** lval[6] - function address of highest/last binary operator ** lval[7] - stage address of "oper 0" code, else 0 */ /* ** skim over terms adjoining || and && operators */ skim(opstr, testfunc, dropval, endval, heir, lval) char *opstr; int testfunc, dropval, endval, heir, lval[]; { int k, hits, droplab, endlab; hits=0; while(1) { k=plunge1(heir, lval); if(nextop(opstr)) { bump(opsize); if(hits==0) { hits=1; droplab=getlabel(); } dropout(k, testfunc, droplab, lval); } else if(hits) { dropout(k, testfunc, droplab, lval); const(endval); jump(endlab=getlabel()); postlabel(droplab); const(dropval); postlabel(endlab); lval[1]=lval[2]=lval[3]=lval[7]=0; return 0; } else return k; } } /* ** test for early dropout from || or && evaluations */ dropout(k, testfunc, exit1, lval) int k, testfunc, exit1, lval[]; { if(k) rvalue(lval); else if(lval[3]) const(lval[4]); testfunc(exit1); /* jumps on false */ } /* ** plunge to a lower level */ plunge(opstr, opoff, heir, lval) char *opstr; int opoff, heir, lval[]; { int k, lval2[8]; k=plunge1(heir, lval); if(nextop(opstr)==0) return k; if(k) rvalue(lval); while(1) { if(nextop(opstr)) { bump(opsize); opindex=opindex+opoff; plunge2(op[opindex], op2[opindex], heir, lval, lval2); } else return 0; } } /* ** unary plunge to lower level */ plunge1(heir, lval) int heir, lval[]; { char *before, *start; int k; setstage(&before, &start); k=heir(lval); if(lval[3]) clearstage(before,0); /* load constant later */ return k; } /* ** binary plunge to lower level */ plunge2(oper, oper2, heir, lval, lval2) int oper, oper2, heir, lval[], lval2[]; { 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(plunge1(heir, lval2)) rvalue(lval2); if(lval[4]==0) lval[7]=stagenext; const2(lval[4]<<dbltest(lval2, lval)); } else { /* non-constant on left side */ push(); if(plunge1(heir, lval2)) rvalue(lval2); if(lval2[3]) { /* constant on right side */ if(lval2[4]==0) lval[7]=start; if(oper==add) { /* may test other commutative operators */ csp=csp+2; clearstage(before, 0); const2(lval2[4]<<dbltest(lval, lval2)); /* load secondary */ } else { const(lval2[4]<<dbltest(lval, lval2)); /* load primary */ smartpop(lval2, start); } } else { /* non-constants on both sides */ smartpop(lval2, start); if((oper==add)|(oper==sub)) { if(dbltest(lval,lval2)) doublereg(); if(dbltest(lval2,lval)) { swap(); doublereg(); if(oper==sub) swap(); } } } } if(oper) { if(lval[3]=lval[3]&lval2[3]) { lval[4]=calc(lval[4], oper, lval2[4]); clearstage(before, 0); lval[5]=0; } else { if((lval[2]==0)&(lval2[2]==0)) { oper(); lval[6]=oper; /* identify the operator */ } else { oper2(); lval[6]=oper2; /* identify the operator */ } } if(oper==sub) { if((lval[2]==CINT)&(lval2[2]==CINT)) { swap(); const(1); asr(); /** div by 2 **/ } } if((oper==sub)|(oper==add)) result(lval, lval2); } } calc(left, oper, right) int left, oper, right; { if(oper == or) return (left | right); else if(oper == xor) return (left ^ right); else if(oper == and) return (left & right); else if(oper == eq) return (left == right); else if(oper == ne) return (left != right); else if(oper == le) return (left <= right); else if(oper == ge) return (left >= right); else if(oper == lt) return (left < right); else if(oper == gt) return (left > right); else if(oper == asr) return (left >> right); else if(oper == asl) return (left << right); else if(oper == add) return (left + right); else if(oper == sub) return (left - right); else if(oper ==mult) return (left * right); else if(oper == div) return (left / right); else if(oper == mod) return (left % right); else return 0; } expression(const, val) int *const, *val; { int lval[8]; if(heir1(lval)) rvalue(lval); if(lval[3]) { *const=1; *val=lval[4]; } else *const=0; } heir1(lval) int lval[]; { int k,lval2[8], oper; k=plunge1(heir3, lval); if(lval[3]) const(lval[4]); if(match("|=")) oper=or; else if(match("^=")) oper=xor; else if(match("&=")) oper=and; else if(match("+=")) oper=add; else if(match("-=")) oper=sub; else if(match("*=")) oper=mult; else if(match("/=")) oper=div; else if(match("%=")) oper=mod; else if(match(">>=")) oper=asr; else if(match("<<=")) oper=asl; else if(match("=")) oper=0; else return k; if(k==0) { needlval(); return 0; } if(lval[1]) { if(oper) { push(); rvalue(lval); } plunge2(oper, oper, heir1, lval, lval2); if(oper) pop(); } else { if(oper) { rvalue(lval); plunge2(oper, oper, heir1, lval, lval2); } else { if(heir1(lval2)) rvalue(lval2); lval[5]=lval2[5]; } } store(lval); return 0; } heir3(lval) int lval[]; { return skim("||", eq0, 1, 0, heir4, lval); } heir4(lval) int lval[]; { return skim("&&", ne0, 0, 1, heir5, lval); } heir5(lval) int lval[]; { return plunge("|", 0, heir6, lval); } heir6(lval) int lval[]; { return plunge("^", 1, heir7, lval); } heir7(lval) int lval[]; { return plunge("&", 2, heir8, lval); } heir8(lval) int lval[]; { return plunge("== !=", 3, heir9, lval); } heir9(lval) int lval[]; { return plunge("<= >= < >", 5, heir10, lval); } heir10(lval) int lval[]; { return plunge(">> <<", 9, heir11, lval); } heir11(lval) int lval[]; { return plunge("+ -", 11, heir12, lval); } heir12(lval) int lval[]; { return plunge("* / %", 13, heir13, lval); } //SYSIN DD SYSOUT=* echo Extracting cc32.c cat > cc32.c << "//SYSIN DD SYSOUT=*" 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[4] = ~lval[4]; #endif return 0; } else if (match("!")) { /* ! */ if(heir13(lval)) rvalue(lval); lneg(); #ifdef PHASE2 lval[4] = !lval[4]; #endif 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]=ptr[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("++")) { /* lval++ */ if(k==0) { needlval(); return 0; } step(inc, lval); dec(lval[2]>>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); ptr=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); lval2[3]=0; plunge2(0, 0, heir1, lval2, lval2); /* lval2 deadend */ needtoken("]"); if(lval2[3]) { clearstage(before, 0); if(lval2[4]) { if(ptr[TYPE]==CINT) const2(lval2[4]<<LBPW); else const2(lval2[4]); add(); } } else { if(ptr[TYPE]==CINT) doublereg(); add(); } lval[0]=lval[2]=0; lval[1]=ptr[TYPE]; k=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("(")) { /* (expression) */ k=heir1(lval); needtoken(")"); return k; } putint(0, lval, 8<<LBPW); /* clear lval array */ if(symname(ssname, YES)) { if(ptr=findloc(ssname)) { #ifdef STGOTO if(ptr[IDENT]==LABEL) { experr(); return 0; } #endif getloc(ptr); lval[0]=ptr; lval[1]=ptr[TYPE]; if(ptr[IDENT]==POINTER) { lval[1]=CINT; lval[2]=ptr[TYPE]; } if(ptr[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[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(); /* 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); } //SYSIN DD SYSOUT=* echo Extracting cc33.c cat > cc33.c << "//SYSIN DD SYSOUT=*" /* ** true if val1 -> 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]; } } step(oper, lval) int oper, lval[]; { if(lval[1]) { if(lval[5]) { push(); rvalue(lval); oper(lval[2]>>2); pop(); store(lval); return; } else { move(); lval[5]=1; } } rvalue(lval); oper(lval[2]>>2); store(lval); } 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) 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==eq)| (oper==ule)) zerojump(eq0, label, lval); else if((oper==ne)| (oper==ugt)) zerojump(ne0, label, lval); else if (oper==gt) zerojump(gt0, label, lval); else if (oper==ge) zerojump(ge0, label, lval); else if (oper==uge) clearstage(lval[7],0); else if (oper==lt) zerojump(lt0, label, lval); else if (oper==ult) zerojump(ult0, label, lval); else if (oper==le) 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 generated 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); outbyte('+'); } 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) return 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+size; } /* ** 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; } //SYSIN DD SYSOUT=* echo Extracting cc4.c cat > cc4.c << "//SYSIN DD SYSOUT=*" /* ** Small-C Compiler Version 2.0 ** ** Copyright 1982 J. E. Hendrix ** ** Part 4 */ #include stdio.h,2 #include cc.def,2 /* ** external references in part 1 */ extern char #ifdef HASH *macn, #endif #ifdef OPTIMIZE optimize, #endif *stagenext, ssname[NAMESIZE]; extern int beglab, csp, output; /* ** external references in part 2 */ extern int #ifdef HASH search(), #else findmac(), #endif clearstage(), col(), cout(), getint(), getlabel(), nl(), numeric(), ol(), ot(), printlabel(), lout(), outdec(), outstr(), streq(); /* ** external references in part 3 */ extern int const(); #include cc41.c,2 #include cc42.c,2 //SYSIN DD SYSOUT=* echo Extracting cc41.c cat > cc41.c << "//SYSIN DD SYSOUT=*" /* ** print all assembler info before any code is generated */ header() { beglab=getlabel(); #ifndef LINK if(beglab < 3) #endif { #ifdef SMALL_VM ol("LXI D,$+6"); ol("JMP CC9998"); #endif jump(beglab); } } /* ** print any assembler stuff needed at the end */ trailer() { #ifdef SMALL_VM #ifndef LINK if((beglab == 1)|(beglab > 9000)) #endif { ol("CC9997:JMP CCBOJ"); ol("CC9998:DS 6"); ol("PUSH D"); ol("LXI D,$+6"); ol("JMP CC9997"); ol("ORG CC9998"); ol("JMP $+6"); } #endif ol("END"); } /* ** load # args before function call */ loadargc(val) int val; { #ifdef HASH if(search("NOCCARGC", macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) { #else if(findmac("NOCCARGC")==0) { #endif ot("MVI A,"); outdec(val); nl(); } } /* ** declare entry point */ entry() { outstr(ssname); col(); #ifdef LINK ol("ENTRY"); #else nl(); #endif } /* ** declare external reference */ external(name) char *name; { #ifdef LINK outstr(name); col(); ol("EXTRN"); #endif } /* ** fetch object indirect to primary register */ indirect(lval) int lval[]; { 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(getint(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"); } /* ** 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() { 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 sour="XCHG;;"; /* peephole() uses trailing ";;" */ #endif while(*sour) *dest++ = *sour++; sour=stagenext; while(--sour > dest) { /* adjust stack references */ #ifdef TAB if(streq(sour,"\tDAD SP")) { #else if(streq(sour,"DAD SP")) { #endif --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 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 */ 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 */ zerojump(oper, label, lval) int oper, label, lval[]; { clearstage(lval[7], 0); /* purge conventional code */ oper(label); } /* ** 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) { 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 register */ doublereg() {ol("DAD H");} //SYSIN DD SYSOUT=* echo Extracting cc42.c cat > cc42.c << "//SYSIN DD SYSOUT=*" /* ** add primary and secondary registers (result in primary) */ add() {ol("DAD D");} /* ** subtract primary from secondary register (result in primary) */ sub() {call("CCSUB");} /* ** multiply primary and secondary registers (result in primary) */ mult() {call("CCMULT");} /* ** divide secondary by primary register ** (quotient in primary, remainder in secondary) */ div() {call("CCDIV");} /* ** remainder of secondary/primary ** (remainder in primary, quotient in secondary) */ mod() {div();swap();} /* ** inclusive "or" primary and secondary registers ** (result in primary) */ or() {call("CCOR");} /* ** exclusive "or" the primary and secondary registers ** (result in primary) */ xor() {call("CCXOR");} /* ** "and" primary and secondary registers ** (result in primary) */ and() {call("CCAND");} /* ** logical negation of primary register */ lneg() {call("CCLNEG");} /* ** arithmetic shift right secondary register ** number of bits given in primary register ** (result in primary) */ asr() {call("CCASR");} /* ** arithmetic shift left secondary register ** number of bits given in primary register ** (result in primary) */ asl() {call("CCASL");} /* ** two's complement primary register */ neg() {call("CCNEG");} /* ** one's complement primary register */ com() {call("CCCOM");} /* ** increment primary register by one object of whatever size */ inc(n) int n; { while(1) { ol("INX H"); if(--n < 1) break; } } /* ** decrement primary register by one object of whatever size */ dec(n) int n; { while(1) { ol("DCX H"); if(--n < 1) break; } } /* ** test for equal to */ eq() {call("CCEQ");} /* ** test for equal to zero */ eq0(label) int label; { ol("MOV A,H"); ol("ORA L"); ot("JNZ "); printlabel(label); nl(); } /* ** test for not equal to */ ne() {call("CCNE");} /* ** test for not equal to zero */ ne0(label) int label; { ol("MOV A,H"); ol("ORA L"); ot("JZ "); printlabel(label); nl(); } /* ** test for less than (signed) */ lt() {call("CCLT");} /* ** test for less than to zero */ lt0(label) int label; { ol("XRA A"); ol("ORA H"); ot("JP "); printlabel(label); nl(); } /* ** test for less than or equal to (signed) */ le() {call("CCLE");} /* ** test for less than or equal to zero */ le0(label) int label; { ol("MOV A,H"); ol("ORA L"); ol("JZ $+8"); ol("XRA A"); ol("ORA H"); ot("JP "); printlabel(label); nl(); } /* ** test for greater than (signed) */ gt() {call("CCGT");} /* ** test for greater than to zero */ gt0(label) int label; { ol("XRA A"); ol("ORA H"); ot("JM "); printlabel(label); nl(); ol("ORA L"); ot("JZ "); printlabel(label); nl(); } /* ** test for greater than or equal to (signed) */ ge() {call("CCGE");} /* ** test for gteater than or equal to zero */ ge0(label) int label; { ol("XRA A"); ol("ORA H"); ot("JM "); printlabel(label); nl(); } /* ** test for less than (unsigned) */ ult() {call("CCULT");} /* ** test for less than to zero (unsigned) */ ult0(label) int label; { ot("JMP "); printlabel(label); nl(); } /* ** test for less than or equal to (unsigned) */ ule() {call("CCULE");} /* ** test for greater than (unsigned) */ ugt() {call("CCUGT");} /* ** test for greater than or equal to (unsigned) */ uge() {call("CCUGE");} #ifdef OPTIMIZE peephole(ptr) char *ptr; { while(*ptr) { #ifdef TAB if(streq(ptr, "\tLXI H,0\n\tDAD SP\n\tCALL CCGINT")) { if(streq(ptr+31, "XCHG;;")) {pp2();ptr=ptr+38;} else {pp1();ptr=ptr+30;} } else if(streq(ptr, "\tLXI H,2\n\tDAD SP\n\tCALL CCGINT")) { if(streq(ptr+31, "XCHG;;")) {pp3(pp2);ptr=ptr+38;} else {pp3(pp1);ptr=ptr+30;} } else if(optimize) { if(streq(ptr, "\tDAD SP\n\tCALL CCGINT")) { ol("CALL CCDSGI"); ptr=ptr+21; } else if(streq(ptr, "\tDAD D\n\tCALL CCGINT")) { ol("CALL CCDDGI"); ptr=ptr+20; } else if(streq(ptr, "\tDAD SP\n\tCALL CCGCHAR")) { ol("CALL CCDSGC"); ptr=ptr+22; } else if(streq(ptr, "\tDAD D\n\tCALL CCGCHAR")) { ol("CALL CCDDGC"); ptr=ptr+21; } else if(streq(ptr, "\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGINT\n\tINX H\n\tCALL CCPINT")) { ol("CALL CCINCI"); ptr=ptr+59; } else if(streq(ptr, "\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGINT\n\tDCX H\n\tCALL CCPINT")) { ol("CALL CCDECI"); ptr=ptr+59; } else if(streq(ptr, "\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGCHAR\n\tINX H\n\tMOV A,L\n\tSTAX D")) { ol("CALL CCINCC"); ptr=ptr+64; } else if(streq(ptr, "\tDAD SP\n\tMOV D,H\n\tMOV E,L\n\tCALL CCGCHAR\n\tDCX H\n\tMOV A,L\n\tSTAX D")) { ol("CALL CCDECC"); ptr=ptr+64; } else if(streq(ptr, "\tDAD D\n\tPOP D\n\tCALL CCPINT")) { ol("CALL CCDDPDPI"); ptr=ptr+27; } else if(streq(ptr, "\tDAD D\n\tPOP D\n\tMOV A,L\n\tSTAX D")) { ol("CALL CCDDPDPC"); ptr=ptr+31; } else if(streq(ptr, "\tPOP D\n\tCALL CCPINT")) { ol("CALL CCPDPI"); ptr=ptr+20; } else if(streq(ptr, "\tPOP D\n\tMOV A,L\n\tSTAX D")) { ol("CALL CCPDPC"); ptr=ptr+24; } /* additional optimizing logic goes here */ #else if(streq(ptr,"LXI H,0\nDAD SP\nCALL CCGINT")) { if(streq(ptr+27, "XCHG;;")) {pp2();ptr=ptr+34;} else {pp1();ptr=ptr+27;} } else if(streq(ptr,"LXI H,2\nDAD SP\nCALL CCGINT")) { if(streq(ptr+27, "XCHG;;")) {pp3(pp2);ptr=ptr+34;} else {pp3(pp1);ptr=ptr+27;} } else if(optimize) { if(streq(ptr, "DAD SP\nCALL CCGINT")) { ol("CALL CCDSGI"); ptr=ptr+19; } else if(streq(ptr, "DAD D\nCALL CCGINT")) { ol("CALL CCDDGI"); ptr=ptr+18; } else if(streq(ptr, "DAD SP\nCALL CCGCHAR")) { ol("CALL CCDSGC"); ptr=ptr+20; } else if(streq(ptr, "DAD D\nCALL CCGCHAR")) { ol("CALL CCDDGC"); ptr=ptr+19; } else if(streq(ptr, "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGINT\nINX H\nCALL CCPINT")) { ol("CALL CCINCI"); ptr=ptr+53; } else if(streq(ptr, "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGINT\nDCX H\nCALL CCPINT")) { ol("CALL CCDECI"); ptr=ptr+53; } else if(streq(ptr, "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGCHAR\nINX H\nMOV A,L\nSTAX D")) { ol("CALL CCINCC"); ptr=ptr+57; } else if(streq(ptr, "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGCHAR\nDCX H\nMOV A,L\nSTAX D")) { ol("CALL CCDECC"); ptr=ptr+57; } else if(streq(ptr, "DAD D\nPOP D\nCALL CCPINT")) { ol("CALL CCDDPDPI"); ptr=ptr+24; } else if(streq(ptr, "DAD D\nPOP D\nMOV A,L\nSTAX D")) { ol("CALL CCDDPDPC"); ptr=ptr+27; } else if(streq(ptr, "POP D\nCALL CCPINT")) { ol("CALL CCPDPI"); ptr=ptr+18; } else if(streq(ptr, "POP D\nMOV A,L\nSTAX D")) { ol("CALL CCPDPC"); ptr=ptr+21; } /* additional optimizing logic goes here */ #endif else cout(*ptr++, output); } else cout(*ptr++, output); } } pp1() { ol("POP H"); ol("PUSH H"); } pp2() { ol("POP D"); ol("PUSH D"); } pp3(pp) int pp; { ol("POP B"); pp(); ol("PUSH B"); } #endif //SYSIN DD SYSOUT=* echo Extracting crt.def cat > crt.def << "//SYSIN DD SYSOUT=*" Y -1 0 24,80 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 0,0,0 -1 //SYSIN DD SYSOUT=* echo Extracting dtoi.c cat > dtoi.c << "//SYSIN DD SYSOUT=*" /* ** dtoi -- convert signed decimal string to integer nbr ** returns field length, else ERR on error */ dtoi(decstr, nbr) char *decstr; int *nbr; { int len, s; if((*decstr)=='-') {s=1; ++decstr;} else s=0; if((len=utoi(decstr, nbr))<0) return ERR; if(*nbr<0) return ERR; if(s) {*nbr = -*nbr; return ++len;} else return len; } //SYSIN DD SYSOUT=* echo Extracting itod.c cat > itod.c << "//SYSIN DD SYSOUT=*" /* ** itod -- convert nbr to signed decimal string of width sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itod(nbr, str, sz) int nbr; char str[]; int sz; { char sgn; if(nbr<0) {nbr = -nbr; sgn='-';} else sgn=' '; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { str[--sz]=(nbr%10+'0'); if((nbr=nbr/10)==0) break; } if(sz) str[--sz]=sgn; while(sz>0) str[--sz]=' '; return str; } //SYSIN DD SYSOUT=* echo Extracting itou.c cat > itou.c << "//SYSIN DD SYSOUT=*" /* ** itou -- convert nbr to unsigned decimal string of width sz ** right adjusted, blank filled; returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itou(nbr, str, sz) int nbr; char str[]; int sz; { int lowbit; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { lowbit=nbr&1; nbr=(nbr>>1)&32767; /* divide by 2 */ str[--sz]=((nbr%5)<<1)+lowbit+'0'; if((nbr=nbr/5)==0) break; } while(sz) str[--sz]=' '; return str; } //SYSIN DD SYSOUT=* echo Extracting itox.c cat > itox.c << "//SYSIN DD SYSOUT=*" /* ** itox -- converts nbr to hex string of length sz ** right adjusted and blank filled, returns str ** ** if sz > 0 terminate with null byte ** if sz = 0 find end of string ** if sz < 0 use last byte for data */ itox(nbr, str, sz) int nbr; char str[]; int sz; { int digit, offset; if(sz>0) str[--sz]=NULL; else if(sz<0) sz = -sz; else while(str[sz]!=NULL) ++sz; while(sz) { digit=nbr&15; nbr=(nbr>>4)&4095; if(digit<10) offset=48; else offset=55; str[--sz]=digit+offset; if(nbr==0) break; } while(sz) str[--sz]=' '; return str; } //SYSIN DD SYSOUT=* echo Extracting left.c cat > left.c << "//SYSIN DD SYSOUT=*" /* ** left -- left adjust and null terminate a string */ left(str) char *str; { char *str2; str2=str; while(*str2==' ') ++str2; while(*str++ = *str2++); } //SYSIN DD SYSOUT=* echo Extracting lib.c cat > lib.c << "//SYSIN DD SYSOUT=*" /* ** lib.c -- function library ** ** Copyright 1982 J. E. Hendrix */ #define NOCCARGC /* don't pass arg count to functions */ /* called by these functions */ #include abs.c,2 #include dtoi.c,2 #include itod.c,2 #include itou.c,2 #include itox.c,2 #include left.c,2 #include printf.c,2 #include sign.c,2 #include strcmp.c,2 #include utoi.c,2 #include xtoi.c,2 #include out.c,2 //SYSIN DD SYSOUT=* echo Extracting lib.h cat > lib.h << "//SYSIN DD SYSOUT=*" /* ** lib.h -- invoke a local copy of the function library */ #define PASSARGC /* pass arg count to called functions */ #asm LIB.R:LIBRY ABS:EXTRN DTOI:EXTRN ITOD:EXTRN ITOU:EXTRN ITOX:EXTRN LEFT:EXTRN PRINTF:EXTRN SIGN:EXTRN STRCMP:EXTRN UTOI:EXTRN XTOI:EXTRN #endasm //SYSIN DD SYSOUT=* echo Extracting out.c cat > out.c << "//SYSIN DD SYSOUT=*" cout(c, fd) char c; int fd; { if(fputc(c, fd)==EOF) xout(); } 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 error\n", stderr); abort(ERRCODE); } //SYSIN DD SYSOUT=* echo Extracting printf.c cat > printf.c << "//SYSIN DD SYSOUT=*" /* ** printf(controlstring, arg, arg, ...) -- formatted print ** operates as described by Kernighan & Ritchie ** only d, x, c, s, and u specs are supported. */ printf(argc) int argc; { int i, width, prec, preclen, len, *nxtarg; char *ctl, *cx, c, right, str[7], *sptr, pad; i = CCARGC(); /* fetch arg count from A reg first */ nxtarg = &argc + i - 1; ctl = *nxtarg; while(c=*ctl++) { if(c!='%') {cout(c, stdout); continue;} if(*ctl=='%') {cout(*ctl++, stdout); continue;} cx=ctl; if(*cx=='-') {right=0; ++cx;} else right=1; if(*cx=='0') {pad='0'; ++cx;} else pad=' '; if((i=utoi(cx, &width)) >= 0) cx=cx+i; else continue; if(*cx=='.') { if((preclen=utoi(++cx, &prec)) >= 0) cx=cx+preclen; else continue; } else preclen=0; sptr=str; c=*cx++; i=*(--nxtarg); if(c=='d') itod(i, str, 7); else if(c=='x') itox(i, str, 7); else if(c=='c') {str[0]=i; str[1]=NULL;} else if(c=='s') sptr=i; else if(c=='u') itou(i, str, 7); else continue; ctl=cx; /* accept conversion spec */ if(c!='s') while(*sptr==' ') ++sptr; len=-1; while(sptr[++len]); /* get length */ if((c=='s')&(len>prec)&(preclen>0)) len=prec; if(right) while(((width--)-len)>0) cout(pad, stdout); while(len) {cout(*sptr++, stdout); --len; --width;} while(((width--)-len)>0) cout(pad, stdout); } } //SYSIN DD SYSOUT=* echo Extracting sign.c cat > sign.c << "//SYSIN DD SYSOUT=*" /* ** sign -- return -1, 0, +1 depending on the sign of nbr */ sign(nbr) int nbr; { if(nbr>0) return 1; else if(nbr==0) return 0; else return -1; } //SYSIN DD SYSOUT=* echo Extracting stdio.h cat > stdio.h << "//SYSIN DD SYSOUT=*" /* ** stdio.h -- header for resident STDIO/CALL, and VM interfaces */ #define stdin 0 #define stdout 1 #define stderr 2 #define stdport 3 #define stdlist 4 #define CCEOM 45062 #define ERR -2 #define EOF -1 #define YES 1 #define NO 0 #define NULL 0 #define CR 13 #define LF 10 #asm STDIO:EQU 0E00H;;STDIO BASE CCBOJ: EQU STDIO+0006H CCEXIT: EQU STDIO+0009H CCPOLL: EQU STDIO+000CH CCHALT: EQU STDIO+000FH CCOPEN: EQU STDIO+0012H CCCLOSE:EQU STDIO+0015H CCREAD: EQU STDIO+0018H CCWRITE:EQU STDIO+001BH CCSEEK: EQU STDIO+001EH CCMODE: EQU STDIO+0021H CCFILE: EQU STDIO+0024H CCPURGE:EQU STDIO+0027H CCFLUSH:EQU STDIO+002AH CCALLOC:EQU STDIO+002DH CCFREE: EQU STDIO+0030H CCAVAIL:EQU STDIO+0033H CCDELIM:EQU STDIO+0036H CCDDGC: EQU STDIO+0039H CCDSGC: EQU STDIO+003DH CCGCHAR:EQU STDIO+0040H CCARGC: EQU STDIO+0041H CCSXT: EQU STDIO+0041H CCDDGI: EQU STDIO+0046H CCDSGI: EQU STDIO+004AH CCGINT: EQU STDIO+004DH CCDECC: EQU STDIO+0052H CCINCC: EQU STDIO+005EH CCDDPDPC:EQU STDIO+006AH CCPDPC: EQU STDIO+006BH CCPCHAR:EQU STDIO+006EH CCDECI: EQU STDIO+0071H CCINCI: EQU STDIO+007DH CCDDPDPI:EQU STDIO+0089H CCPDPI: EQU STDIO+008AH CCPINT: EQU STDIO+008DH CCOR: EQU STDIO+0093H CCXOR: EQU STDIO+009AH CCAND: EQU STDIO+00A1H CCEQ: EQU STDIO+00A8H CCNE: EQU STDIO+00AEH CCGT: EQU STDIO+00B4H CCLE: EQU STDIO+00BBH CCGE: EQU STDIO+00C2H CCLT: EQU STDIO+00C8H CCCMP: EQU STDIO+00CEH CCUGE: EQU STDIO+00DFH CCULT: EQU STDIO+00E5H CCUGT: EQU STDIO+00EBH CCULE: EQU STDIO+00F2H CCUCMP: EQU STDIO+00F9H CCASR: EQU STDIO+0104H CCASL: EQU STDIO+0112H CCSUB: EQU STDIO+0119H CCNEG: EQU STDIO+0120H CCCOM: EQU STDIO+0125H CCMULT: EQU STDIO+012CH CCDIV: EQU STDIO+014CH CCLNEG: EQU STDIO+01AAH CCSWITCH:EQU STDIO+01B6H GETC: EQU STDIO+01D0H PUTC: EQU STDIO+01D3H FFLUSH: EQU STDIO+01D6H ABORT: EQU STDIO+01D9H EXIT: EQU STDIO+01DCH UNLINK: EQU STDIO+01DFH FGETC: EQU STDIO+01E2H GETCHAR:EQU STDIO+02D9H FGETS: EQU STDIO+02E2H FPUTC: EQU STDIO+050DH PUTCHAR:EQU STDIO+0579H FPUTS: EQU STDIO+058AH PUTS: EQU STDIO+0699H FOPEN: EQU STDIO+06B5H FCLOSE: EQU STDIO+078BH GETARG: EQU STDIO+07E7H #endasm //SYSIN DD SYSOUT=* echo Extracting stdiol.h cat > stdiol.h << "//SYSIN DD SYSOUT=*" /* ** stdiol.h -- header for local STDIO/CALL, and VM interfaces */ #define stdin 0 #define stdout 1 #define stderr 2 #define stdport 3 #define stdlist 4 #define ERR -2 #define EOF -1 #define YES 1 #define NO 0 #define NULL 0 #define CR 13 #define LF 10 #asm STDIOL.R:LIBRY ; STD I/O ROUTINES GETC: EXTRN GETCHAR:EXTRN FGETC: EXTRN FGETS: EXTRN PUTC: EXTRN PUTCHAR:EXTRN FPUTC: EXTRN FPUTS: EXTRN PUTS: EXTRN FOPEN: EXTRN FCLOSE: EXTRN GETARG: EXTRN ; STD I/O ROUTINES MATCHING VM ROUTINES FFLUSH: EXTRN ABORT: EXTRN EXIT: EXTRN UNLINK: EXTRN ; ARITHMETIC & LOGICAL ROUTINES CCARGC: EXTRN CCSXT: EXTRN CCDSGI: EXTRN CCDDGI: EXTRN CCINCI: EXTRN CCDECI: EXTRN CCGINT: EXTRN CCDDPDPI:EXTRN CCPDPI: EXTRN CCDSGC: EXTRN CCDDGC: EXTRN CCINCC: EXTRN CCDECC: EXTRN CCGCHAR:EXTRN CCDDPDPC:EXTRN CCPDPC: EXTRN CCPCHAR:EXTRN CCPINT: EXTRN CCOR: EXTRN CCXOR: EXTRN CCAND: EXTRN CCEQ: EXTRN CCNE: EXTRN CCGT: EXTRN CCLE: EXTRN CCGE: EXTRN CCLT: EXTRN CCCMP: EXTRN CCUGE: EXTRN CCULT: EXTRN CCUGT: EXTRN CCULE: EXTRN CCUCMP: EXTRN CCASR: EXTRN CCASL: EXTRN CCSUB: EXTRN CCNEG: EXTRN CCCOM: EXTRN CCMULT: EXTRN CCDIV: EXTRN CCLNEG: EXTRN CCSWITCH:EXTRN ; VM ROUTINES VM.R: LIBRY CCBOJ: EXTRN CCEXIT: EXTRN CCPOLL: EXTRN CCHALT: EXTRN CCOPEN: EXTRN CCCLOSE:EXTRN CCDELIM:EXTRN CCREAD: EXTRN CCWRITE:EXTRN CCSEEK: EXTRN CCMODE: EXTRN CCFILE: EXTRN CCPURGE:EXTRN CCFLUSH:EXTRN CCALLOC:EXTRN CCFREE: EXTRN CCAVAIL:EXTRN #endasm //SYSIN DD SYSOUT=* echo Extracting strcmp.c cat > strcmp.c << "//SYSIN DD SYSOUT=*" /* ** strcmp -- return -1, 0, +1 depending on str1 <, =, > str2 */ strcmp(str1, str2) char *str1, *str2; { char c1, c2; while((c1=*str1++)==(c2=*str2++)) if(c1==NULL) return 0; return sign(c1-c2); } //SYSIN DD SYSOUT=* echo Extracting utoi.c cat > utoi.c << "//SYSIN DD SYSOUT=*" /* ** utoi -- convert unsigned decimal string to integer nbr ** returns field size, else ERR on error */ utoi(decstr, nbr) char *decstr; int *nbr; { int d,t; d=0; *nbr=0; while((*decstr>='0')&(*decstr<='9')) { t=*nbr;t=(10*t) + (*decstr++ - '0'); if ((t>=0)&(*nbr<0)) return ERR; d++; *nbr=t; } return d; } //SYSIN DD SYSOUT=* echo Extracting vm.h cat > vm.h << "//SYSIN DD SYSOUT=*" /* ** vm.h -- header for resident VM interface */ #asm VM: EQU 0B000H;;VIRTUAL MACHINE BASE CCBOJ: ENTRY JMP VM+08H CCEXIT: ENTRY JMP VM+0BH CCPOLL: ENTRY JMP VM+0EH CCHALT: ENTRY JMP VM+11H CCOPEN: ENTRY JMP VM+14H CCCLOSE:ENTRY JMP VM+17H CCREAD: ENTRY JMP VM+1AH CCWRITE:ENTRY JMP VM+1DH CCSEEK: ENTRY JMP VM+20H CCMODE: ENTRY JMP VM+23H CCFILE: ENTRY JMP VM+26H CCPURGE:ENTRY JMP VM+29H CCFLUSH:ENTRY JMP VM+2CH CCALLOC:ENTRY JMP VM+2FH CCFREE: ENTRY JMP VM+32H CCAVAIL:ENTRY JMP VM+35H CCDELIM:ENTRY JMP VM+38H #endasm //SYSIN DD SYSOUT=* echo Extracting vml.h cat > vml.h << "//SYSIN DD SYSOUT=*" /* ** vml.h -- header for local VM interface */ #asm VM.R: LIBRY CCBOJ: EXTRN CCEXIT: EXTRN CCPOLL: EXTRN CCHALT: EXTRN CCOPEN: EXTRN CCCLOSE:EXTRN CCDELIM:EXTRN CCREAD: EXTRN CCWRITE:EXTRN CCSEEK: EXTRN CCMODE: EXTRN CCFILE: EXTRN CCPURGE:EXTRN CCFLUSH:EXTRN CCALLOC:EXTRN CCFREE: EXTRN CCAVAIL:EXTRN #endasm //SYSIN DD SYSOUT=* echo Extracting xtoi.c cat > xtoi.c << "//SYSIN DD SYSOUT=*" /* ** xtoi -- convert hex string to integer nbr ** returns field size, else ERR on error */ xtoi(hexstr, nbr) char *hexstr; int *nbr; { int d,t; d=0; *nbr=0; while(1) { if((*hexstr>='0')&(*hexstr<='9')) t=48; else if((*hexstr>='A')&(*hexstr<='F')) t=55; else if((*hexstr>='a')&(*hexstr<='f')) t=87; else break; if(d<4) ++d; else return ERR; *nbr=*nbr<<4; *nbr=*nbr+(*hexstr++)-t; } return d; } //SYSIN DD SYSOUT=*