home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / MBUG / MBUG100.ARC / CC.ARC < prev    next >
Text File  |  1979-12-31  |  68KB  |  3,167 lines

  1. >>> STDIO.H 296
  2. /*
  3. ** STDIO.H -- Standard Small-C Definitions
  4. */
  5. #define stdin    0
  6. #define stdout   1
  7. #define stderr   2
  8. #define ERR   (-2)
  9. #define EOF   (-1)
  10. #define YES      1
  11. #define NO       0
  12. #define NULL     0
  13. #define CR      13
  14. #define LF      10
  15. #define BELL     7
  16. #define SPACE  ' '
  17. #define NEWLINE LF
  18. >>> NOTICE.H 99
  19. #define VERSION "Version 2.1 (Rev. 67)\n"
  20. #define CRIGHT1 "Copyright 1982, 1983 J. E. Hendrix\n\n"
  21. >>> CC.DEF 2770
  22. /*
  23. ** Small-C Compiler Symbol Definitions
  24. */
  25.  
  26. /*
  27. ** compile options
  28. */
  29. #define NOCCARGC    /* no argument counts */
  30. #define SEPARATE    /* compile separately */
  31. #define OPTIMIZE    /* compile output optimizer */
  32. #define DYNAMIC     /* allocate memory dynamically */
  33. #define COL        /* terminate labels with a colon */
  34. /* #define UPPER    /* force symbols to upper case */
  35. #define LINK        /* will use with linking loader */
  36.  
  37. /*
  38. ** machine dependent parameters
  39. */
  40. #define BPW     2    /* bytes per word */
  41. #define LBPW    1    /* log2(BPW) */
  42. #define SBPC    1    /* stack bytes per character */
  43. #define ERRCODE 7    /* op sys return code */
  44.  
  45. /*
  46. ** symbol table format
  47. */
  48. #define IDENT    0
  49. #define TYPE     1
  50. #define CLASS    2
  51. #define OFFSET   3
  52. #define NAME     5
  53. #define OFFSIZE (NAME-OFFSET)
  54. #define SYMAVG  10
  55. #define SYMMAX  14
  56.  
  57. /*
  58. ** symbol table parameters
  59. */
  60. #define NUMLOCS   25
  61. #define STARTLOC  symtab
  62. #define ENDLOC   (symtab+(NUMLOCS*SYMAVG))
  63. #define NUMGLBS   200
  64. #define STARTGLB  ENDLOC
  65. #define ENDGLB   (ENDLOC+((NUMGLBS-1)*SYMMAX))
  66. #define SYMTBSZ   3050  /* NUMLOCS*SYMAVG + NUMGLBS*SYMMAX */
  67.  
  68. /*
  69. ** System wide name size (for symbols)
  70. */
  71. #define NAMESIZE 9
  72. #define NAMEMAX  8
  73.  
  74. /*
  75. ** possible entries for "IDENT"
  76. */
  77. #define LABEL    0
  78. #define VARIABLE 1
  79. #define ARRAY    2
  80. #define POINTER  3
  81. #define FUNCTION 4
  82.  
  83. /*
  84. ** possible entries for "TYPE"
  85. **    low order 2 bits make type unique within length
  86. **    high order bits give length of object
  87. */
  88. /*      LABEL   0 */
  89. #define CCHAR   (1<<2)
  90. #define CINT    (BPW<<2)
  91.  
  92. /*
  93. ** possible entries for "CLASS"
  94. */
  95. /*      LABEL     0 */
  96. #define STATIC    1
  97. #define AUTOMATIC 2
  98. #define EXTERNAL  3
  99. #define AUTOEXT   4
  100.  
  101. /*
  102. ** "switch" table
  103. */
  104. #define SWSIZ   (2*BPW)
  105. #define SWTABSZ (60*SWSIZ)
  106.  
  107. /*
  108. ** "while" statement queue
  109. */
  110. #define WQTABSZ  30
  111. #define WQSIZ     3
  112. #define WQMAX   (wq+WQTABSZ-WQSIZ)
  113.  
  114. /*
  115. ** entry offsets in while queue
  116. */
  117. #define WQSP    0
  118. #define WQLOOP  1
  119. #define WQEXIT  2
  120.  
  121. /*
  122. ** literal pool
  123. */
  124. #define LITABSZ 800
  125. #define LITMAX  (LITABSZ-1)
  126.  
  127. /*
  128. ** input line
  129. */
  130. #define LINEMAX  127
  131. #define LINESIZE 128
  132.  
  133. /*
  134. ** output staging buffer size
  135. */
  136. #define STAGESIZE   800
  137. #define STAGELIMIT  (STAGESIZE-1)
  138.  
  139. /*
  140. ** macro (define) pool
  141. */
  142. #define MACNBR   130
  143. #define MACNSIZE (MACNBR*(NAMESIZE+2))
  144. #define MACNEND  (macn+MACNSIZE)
  145. #define MACQSIZE (MACNBR*7)
  146. #define MACMAX   (MACQSIZE-1)
  147.  
  148. /*
  149. ** statement types
  150. */
  151. #define STIF      1
  152. #define STWHILE   2
  153. #define STRETURN  3
  154. #define STBREAK   4
  155. #define STCONT    5
  156. #define STASM     6
  157. #define STEXPR    7
  158. #define STDO      8    /* compile "do" logic */
  159. #define STFOR     9    /* compile "for" logic */
  160. #define STSWITCH 10    /* compile "switch/case/default" logic */
  161. #define STCASE   11
  162. #define STDEF    12
  163. #define STGOTO   13    /* compile "goto" logic */
  164. #define STLABEL  14
  165. >>> CC1.C 3299
  166. /*
  167. ** Small-C Compiler Part 1
  168. */
  169. #include <stdio.h>
  170. #include "notice.h"
  171. #include "cc.def"
  172.  
  173. /*
  174. ** miscellaneous storage
  175. */
  176. char
  177. #ifdef OPTIMIZE
  178.   optimize,    /* optimize output of staging buffer */
  179. #endif
  180.   alarm,    /* audible alarm on errors? */
  181.   monitor,    /* monitor function headers? */
  182.   pause,    /* pause for operator on errors? */
  183. #ifdef DYNAMIC
  184.  *stage,    /* output staging buffer */
  185.  *symtab,    /* symbol table */
  186.  *litq,        /* literal pool */
  187.  *macn,        /* macro name buffer */
  188.  *macq,        /* macro string buffer */
  189.  *pline,    /* parsing buffer */
  190.  *mline,    /* macro buffer */
  191. #else
  192.   stage[STAGESIZE],
  193.   symtab[SYMTBSZ],
  194.   litq[LITABSZ],
  195.   macn[MACNSIZE],
  196.   macq[MACQSIZE],
  197.   pline[LINESIZE],
  198.   mline[LINESIZE],
  199.   swq[SWTABSZ],
  200. #endif
  201.  *line,        /* points to pline or mline */
  202.  *lptr,        /* ptr to either */
  203.  *glbptr,    /* ptrs to next entries */
  204.  *locptr,    /* ptr to next local symbol */
  205.  *stagenext,    /* next addr in stage */
  206.  *stagelast,    /* last addr in stage */
  207.   quote[2],    /* literal string for '"' */
  208.  *cptr,        /* work ptrs to any char buffer */
  209.  *cptr2,
  210.  *cptr3,
  211.   msname[NAMESIZE],    /* macro symbol name array */
  212.   ssname[NAMESIZE];    /* static symbol name array */
  213. int
  214. #ifdef STGOTO
  215.   nogo,        /* > 0 disables goto statements */
  216.   noloc,    /* > 0 disables block locals */
  217. #endif
  218.   op[16],    /* function addresses of binary operators */
  219.   op2[16],    /* same for unsigned operators */
  220.   opindex,    /* index to matched operator */
  221.   opsize,    /* size of operator in bytes */
  222.   swactive,    /* true inside a switch */
  223.   swdefault,    /* default label #, else 0 */
  224.  *swnext,    /* address of next entry */
  225.  *swend,    /* address of last table entry */
  226. #ifdef DYNAMIC
  227.  *wq,        /* while queue */
  228. #else
  229.   wq[WQTABSZ],
  230. #endif
  231.   argcs,    /* static argc */
  232.  *argvs,    /* static argv */
  233.  *wqptr,    /* ptr to next entry */
  234.   litptr,    /* ptr to next entry */
  235.   macptr,    /* macro buffer index */
  236.   pptr,        /* ptr to parsing buffer */
  237.   oper,        /* address of binary operator function */
  238.   ch,        /* current character of line being scanned */
  239.   nch,        /* next character of line being scanned */
  240.   declared,    /* # of local bytes declared, else -1 when done */
  241.   iflevel,    /* #if... nest level */
  242.   skiplevel,    /* level at which #if... skipping started */
  243.   func1,    /* true for first function */
  244.   nxtlab,    /* next avail label # */
  245.   litlab,    /* label # assigned to literal pool */
  246.   beglab,    /* beginning label -- first function */
  247.   csp,        /* compiler relative stk ptr */
  248.   argstk,    /* function arg sp */
  249.   argtop,
  250.   ncmp,        /* # open compound statements */
  251.   errflag,    /* non-zero after 1st error in statement */
  252.   eof,        /* set non-zero on final input eof */
  253.   input,    /* fd # for input file */
  254.   input2,    /* fd # for "include" file */
  255.   output,    /* fd # for output file */
  256.   files,    /* non-zero if file list specified on cmd line */
  257.   filearg,    /* cur file arg index */
  258.   glbflag,    /* non-zero if internal globals */
  259.   ctext,    /* non-zero to intermix c-source */
  260.   ccode,    /* non-zero while parsing c-code */
  261.         /* zero when passing assembly code */
  262.   listfp,    /* file pointer to list device */
  263.   lastst,    /* last executed statement type */
  264.  *iptr;        /* work ptr to any int buffer */
  265.  
  266. #include "cc11.c"
  267. #include "cc12.c"
  268. #include "cc13.c"
  269.  
  270. #ifndef SEPARATE
  271. #include "cc21.c"
  272. #include "cc22.c"
  273. #include "cc31.c"
  274. #include "cc32.c"
  275. #include "cc33.c"
  276. #include "cc41.c"
  277. #include "cc42.c"
  278. #endif
  279. >>> CC11.C 5409
  280. /*
  281. ** execution begins here
  282. */
  283. main(argc, argv) int argc, *argv; {
  284.   argcs=argc;
  285.   argvs=argv;
  286.   fputs("Small-C Compiler, ", stderr); fputs(VERSION, stderr);
  287.   fputs(CRIGHT1, stderr);
  288. #ifdef DYNAMIC
  289.   swnext=calloc(SWTABSZ, 1);
  290.   swend=swnext+((SWTABSZ-SWSIZ)>>1);
  291.   stage=calloc(STAGESIZE, 1);
  292.   stagelast=stage+STAGELIMIT;
  293.   wq=calloc(WQTABSZ, BPW);
  294.   litq=calloc(LITABSZ, 1);
  295.   macn=calloc(MACNSIZE, 1);
  296.   macq=calloc(MACQSIZE, 1);
  297.   pline=calloc(LINESIZE, 1);
  298.   mline=calloc(LINESIZE, 1);
  299. #else
  300.   swend=(swnext=swq)+SWTABSZ-SWSIZ;
  301.   stagelast=stage+STAGELIMIT;
  302. #endif
  303.   swactive=        /* not in switch */
  304.   stagenext=        /* direct output mode */
  305.   iflevel=        /* #if... nesting level = 0 */
  306.   skiplevel=        /* #if... not encountered */
  307.   macptr=        /* clear the macro pool */
  308.   csp=            /* stack ptr (relative) */
  309.   errflag=        /* not skipping errors till ";" */
  310.   eof=            /* not eof yet */
  311.   ncmp=            /* not in compound statement */
  312.   files=
  313.   filearg=
  314.   quote[1]=0;
  315.   func1=        /* first function */
  316.   ccode=1;        /* enable preprocessing */
  317.   wqptr=wq;        /* clear while queue */
  318.   quote[0]='"';        /* fake a quote literal */
  319.   input=input2=EOF;
  320.   ask();        /* get user options */
  321.   openfile();        /* and initial input file */
  322.   preprocess();        /* fetch first line */
  323. #ifdef DYNAMIC
  324.   symtab=calloc((NUMLOCS*SYMAVG + NUMGLBS*SYMMAX), 1);
  325. #endif
  326.   locptr=STARTLOC;
  327.   glbptr=STARTGLB;
  328.   glbflag=1;
  329.   ctext=0;
  330.   header();        /* intro code */
  331.   setops();        /* set values in op arrays */
  332.   parse();        /* process ALL input */
  333.   outside();        /* verify outside any function */
  334.   trailer();        /* follow-up code */
  335.   fclose(output);
  336.   }
  337.  
  338. /*
  339. ** process all input text
  340. **
  341. ** At this level, only static declarations,
  342. **      defines, includes and function
  343. **      definitions are legal...
  344. */
  345. parse() {
  346.   while (eof==0) {
  347.     if(amatch("extern", 6))   dodeclare(EXTERNAL);
  348.     else if(dodeclare(STATIC));
  349.     else if(match("#asm"))    doasm();
  350.     else if(match("#include"))doinclude();
  351.     else if(match("#define")) addmac();
  352.     else                      newfunc();
  353.     blanks();        /* force eof if pending */
  354.     }
  355.   }
  356.  
  357. /*
  358. ** dump the literal pool
  359. */
  360. dumplits(size) int size; {
  361.   int j, k;
  362.   k=0;
  363.   while (k<litptr) {
  364.     poll(1);        /* allow program interruption */
  365.     defstorage(size);
  366.     j=10;
  367.     while(j--) {
  368.       outdec(getint(litq+k, size));
  369.       k=k+size;
  370.       if ((j==0)|(k>=litptr)) {nl(); break;}
  371.       outbyte(',');
  372.       }
  373.     }
  374.   }
  375.  
  376. /*
  377. ** dump zeroes for default initial values
  378. */
  379. dumpzero(size, count) int size, count; {
  380.   int j;
  381.   while (count > 0) {
  382.     poll(1);        /* allow program interruption */
  383.     defstorage(size);
  384.     j=30;
  385.     while(j--) {
  386.       outdec(0);
  387.       if ((--count <= 0)|(j==0)) {nl(); break;}
  388.       outbyte(',');
  389.       }
  390.     }
  391.   }
  392.  
  393. /*
  394. ** verify compile ends outside any function
  395. */
  396. outside()  {
  397.   if (ncmp) error("no closing bracket");
  398.   }
  399.  
  400. /*
  401. ** get run options
  402. */
  403. ask() {
  404.   int i;
  405.   i=listfp=nxtlab=0;
  406.   output=stdout;
  407. #ifdef OPTIMIZE
  408.   optimize=
  409. #endif
  410.   alarm=monitor=pause=NO;
  411.   line=mline;
  412.   while(getarg(++i, line, LINESIZE, argcs, argvs)!=EOF) {
  413.     if(line[0]!='-') continue;
  414.     if((toupper(line[1])=='L')&(isdigit(line[2]))&(line[3]<=' ')) {
  415.       listfp=line[2]-'0';
  416.       continue;
  417.       }
  418.     if(line[2]<=' ') {
  419.       if(toupper(line[1])=='A') {
  420.         alarm=YES;
  421.         continue;
  422.         }
  423.       if(toupper(line[1])=='M') {
  424.         monitor=YES;
  425.         continue;
  426.         }
  427. #ifdef OPTIMIZE
  428.       if(toupper(line[1])=='O') {
  429.         optimize=YES;
  430.         continue;
  431.         }
  432. #endif
  433.       if(toupper(line[1])=='P') {
  434.         pause=YES;
  435.         continue;
  436.         }
  437.       }
  438. #ifndef LINK
  439.     if(toupper(line[1])=='B') {
  440.       bump(0); bump(2);
  441.       if(number(&nxtlab)) continue;
  442.       }
  443. #endif
  444.     sout("usage: cc [file]... [-m] [-a] [-p] [-l#]", stderr);
  445. #ifdef OPTIMIZE
  446.     sout(" [-o]", stderr);
  447. #endif
  448. #ifndef LINK
  449.     sout(" [-b#]", stderr);
  450. #endif
  451.     sout(NEWLINE, stderr);
  452.     abort(ERRCODE);
  453.     }
  454.   }
  455.  
  456. /*
  457. ** input and output file opens
  458. */
  459. openfile() {        /* entire function revised */
  460.   char outfn[15];
  461.   int i, j, ext;
  462.   input=EOF;
  463.   while(getarg(++filearg, pline, LINESIZE, argcs, argvs)!=EOF) {
  464.     if(pline[0]=='-') continue;
  465.     ext = NO;
  466.     i = -1;
  467.     j = 0;
  468.     while(pline[++i]) {
  469.       if(pline[i] == '.') {ext = YES; break;}
  470.       if(j < 10) outfn[j++] = pline[i];
  471.       }
  472.     if(!ext) {
  473.       strcpy(pline + i, ".C");
  474.       }
  475.     input = mustopen(pline, "r");
  476.     if(!files && isatty(stdout)) {
  477.       strcpy(outfn + j, ".MAC");
  478.       output = mustopen(outfn, "w");
  479.       }
  480.     files=YES;
  481.     kill();
  482.     return;
  483.     }
  484.   if(files++) eof=YES;
  485.   else input=stdin;
  486.   kill();
  487.   }
  488.  
  489. /*
  490. ** open a file with error checking
  491. */
  492. mustopen(fn, mode) char *fn, *mode; {
  493.   int fd;
  494.   if(fd = fopen(fn, mode)) return fd;
  495.   sout("open error on ", stderr);
  496.   lout(fn, stderr);
  497.   abort(ERRCODE);
  498.   }
  499.  
  500. setops() {
  501.   op2[ 0]=     op[ 0]=  ffor;        /* heir5 */
  502.   op2[ 1]=     op[ 1]= ffxor;        /* heir6 */
  503.   op2[ 2]=     op[ 2]= ffand;        /* heir7 */
  504.   op2[ 3]=     op[ 3]=  ffeq;        /* heir8 */
  505.   op2[ 4]=     op[ 4]=  ffne;
  506.   op2[ 5]=ule; op[ 5]=  ffle;        /* heir9 */
  507.   op2[ 6]=uge; op[ 6]=  ffge;
  508.   op2[ 7]=ult; op[ 7]=  fflt;
  509.   op2[ 8]=ugt; op[ 8]=  ffgt;
  510.   op2[ 9]=     op[ 9]= ffasr;        /* heir10 */
  511.   op2[10]=     op[10]= ffasl;
  512.   op2[11]=     op[11]= ffadd;        /* heir11 */
  513.   op2[12]=     op[12]= ffsub;
  514.   op2[13]=     op[13]=ffmult;        /* heir12 */
  515.   op2[14]=     op[14]= ffdiv;
  516.   op2[15]=     op[15]= ffmod;
  517.   }
  518.  
  519. >>> CC12.C 6788
  520. /*
  521. ** open an include file
  522. */
  523. doinclude()  {
  524.   char *cp;
  525.   blanks();            /* skip over to name */
  526.   switch (*lptr) {
  527.     case '"': case '<': cp = ++lptr;
  528.     while(*cp) {
  529.       switch(*cp) {case '"': case '>': *cp=NULL;}
  530.       ++cp;
  531.       }
  532.     }
  533.   if((input2=fopen(lptr,"r"))==NULL) {
  534.     input2=EOF;
  535.     error("open failure on include file");
  536.     }
  537.   kill();            /* clear rest of line */
  538.                 /* so next read will come from */
  539.                 /* new file (if open) */
  540.   }
  541.  
  542. /*
  543. ** test for global declarations
  544. */
  545. dodeclare(class) int class; {
  546.   if(amatch("char",4)) {
  547.     declglb(CCHAR, class);
  548.     ns();
  549.     return 1;
  550.     }
  551.   else if((amatch("int",3))|(class==EXTERNAL)) {
  552.     declglb(CINT, class);
  553.     ns();
  554.     return 1;
  555.     }
  556.   return 0;
  557.   }
  558.  
  559. /*
  560. ** delcare a static variable
  561. */
  562. declglb(type, class)  int type, class; {
  563.   int k, j;
  564.   while(1) {
  565.     if(endst()) return;            /* do line */
  566.     if(match("(*")|match("*")) {
  567.       j=POINTER;
  568.       k=0;
  569.       }
  570.     else {
  571.       j=VARIABLE;
  572.       k=1;
  573.       }
  574.     if (symname(ssname, YES)==0) illname();
  575.     if(findglb(ssname)) multidef(ssname);
  576.     if(match(")")) ;
  577.     if(match("()")) j=FUNCTION;
  578.     else if (match("[")) {
  579.       paerror(j);
  580.       k=needsub();            /* get size */
  581.       j=ARRAY;                /* !0=array */
  582.       }
  583.     if(class==EXTERNAL) external(ssname);
  584.     else if(j!=FUNCTION) j=initials(type>>2, j, k);
  585.     addsym(ssname, j, type, k, &glbptr, class);
  586.     if (match(",")==0) return;        /* more? */
  587.     }
  588.   }
  589.  
  590. /*
  591. ** declare local variables
  592. */
  593. declloc(typ)  int typ;  {
  594.   int k,j;
  595.   if(swactive) error("not allowed in switch");
  596. #ifdef STGOTO
  597.   if(noloc) error("not allowed with goto");
  598. #endif
  599.   if(declared < 0) error("must declare first in block");
  600.   while(1) {
  601.     while(1) {
  602.       if(endst()) return;
  603.       if(match("*")) j=POINTER;
  604.       else           j=VARIABLE;
  605.       if (symname(ssname, YES)==0) illname();
  606.       /* no multidef check, block-locals are together */
  607.       k=BPW;
  608.       if (match("[")) {
  609.         paerror(j);
  610.         if(k=needsub()) {
  611.           j=ARRAY;
  612.           if(typ==CINT)k=k<<LBPW;
  613.           }
  614.         else {j=POINTER; k=BPW;}
  615.         }
  616.       else if((typ==CCHAR)&(j==VARIABLE)) k=SBPC;
  617.       declared = declared + k;
  618.       addsym(ssname, j, typ, csp - declared, &locptr, AUTOMATIC);
  619.       break;
  620.       }
  621.     if (match(",")==0) return;
  622.     }
  623.   }
  624.  
  625. /*
  626. ** test for pointer array (unsupported)
  627. */
  628. paerror(j) int j; {
  629.   if(j==POINTER) error("no pointer arrays");
  630.   }
  631.  
  632. /*
  633. ** initialize global objects
  634. */
  635. initials(size, ident, dim) int size, ident, dim; {
  636.   int savedim;
  637.   litptr=0;
  638.   if(dim==0) dim = -1;
  639.   savedim=dim;
  640.   entry();
  641.   if(match("=")) {
  642.     if(match("{")) {
  643.       while(dim) {
  644.         init(size, ident, &dim);
  645.         if(match(",")==0) break;
  646.         }
  647.       needtoken("}");
  648.       }
  649.     else init(size, ident, &dim);
  650.     }
  651.   if((dim == -1)&(dim==savedim)) {
  652.      stowlit(0, size=BPW);
  653.     ident=POINTER;
  654.     }
  655.   dumplits(size);
  656.   dumpzero(size, dim);
  657.   return ident;
  658.   }
  659.  
  660. /*
  661. ** evaluate one initializer
  662. */
  663. init(size, ident, dim) int size, ident, *dim; {
  664.   int value;
  665.   if(qstr(&value)) {
  666.     if((ident==VARIABLE)|(size!=1))
  667.       error("must assign to char pointer or array");
  668.     *dim = *dim - (litptr - value);
  669.     if(ident==POINTER) point();
  670.     }
  671.   else if(constexpr(&value)) {
  672.     if(ident==POINTER) error("cannot assign to pointer");
  673.     stowlit(value, size);
  674.     *dim = *dim - 1;
  675.     }
  676.   }
  677.  
  678. /*
  679. ** get required array size
  680. */
  681. needsub()  {
  682.   int val;
  683.   if(match("]")) return 0;    /* null size */
  684.   if (constexpr(&val)==0) val=1;
  685.   if (val<0) {
  686.     error("negative size illegal");
  687.     val = -val;
  688.     }
  689.   needtoken("]");        /* force single dimension */
  690.   return val;            /* and return size */
  691.   }
  692.  
  693. /*
  694. ** begin a function
  695. **
  696. ** called from "parse" and tries to make a function
  697. ** out of the following text
  698. **
  699. */
  700. newfunc()  {
  701.   char *ptr;
  702. #ifdef STGOTO
  703.   nogo  =            /* enable goto statements */
  704.   noloc = 0;            /* enable block-local declarations */
  705. #endif
  706.   lastst=            /* no statement yet */
  707.   litptr=0;            /* clear lit pool */
  708.   litlab=getlabel();        /* label next lit pool */
  709.   locptr=STARTLOC;        /* clear local variables */
  710.   if(monitor) lout(line, stderr);
  711.   if (symname(ssname, YES)==0) {
  712.     error("illegal function or declaration");
  713.     kill();            /* invalidate line */
  714.     return;
  715.     }
  716.   if(func1) {
  717.     postlabel(beglab);
  718.     func1=0;
  719.     }
  720.   if(ptr=findglb(ssname)) {    /* already in symbol table ? */
  721.     if(ptr[IDENT]!=FUNCTION)       multidef(ssname);
  722.     else if(ptr[OFFSET]==FUNCTION) multidef(ssname);
  723.     else {
  724.       /* earlier assumed to be a function */
  725.       ptr[OFFSET]=FUNCTION;
  726.       ptr[CLASS]=STATIC;
  727.       }
  728.     }
  729.   else
  730.     addsym(ssname, FUNCTION, CINT, FUNCTION, &glbptr, STATIC);
  731.   if(match("(")==0) error("no open paren");
  732.   entry();
  733.   locptr=STARTLOC;
  734.   argstk=0;            /* init arg count */
  735.   while(match(")")==0) {    /* then count args */
  736.     /* any legal name bumps arg count */
  737.     if(symname(ssname, YES)) {
  738.       if(findloc(ssname)) multidef(ssname);
  739.       else {
  740.         addsym(ssname, 0, 0, argstk, &locptr, AUTOMATIC);
  741.         argstk=argstk+BPW;
  742.         }
  743.       }
  744.     else {error("illegal argument name");junk();}
  745.     blanks();
  746.     /* if not closing paren, should be comma */
  747.     if(streq(lptr,")")==0) {
  748.       if(match(",")==0) error("no comma");
  749.       }
  750.     if(endst()) break;
  751.     }
  752.   csp=0;            /* preset stack ptr */
  753.   argtop=argstk;
  754.   while(argstk) {
  755.     /* now let user declare what types of things */
  756.     /*      those arguments were */
  757.     if(amatch("char",4))     {doargs(CCHAR);ns();}
  758.     else if(amatch("int",3)) {doargs(CINT);ns();}
  759.     else {error("wrong number of arguments");break;}
  760.     }
  761.   statement();
  762. #ifdef STGOTO
  763.   if(lastst != STRETURN && lastst != STGOTO) ffret();
  764. #else
  765.   if(lastst != STRETURN) ffret();
  766. #endif
  767.   if(litptr) {
  768.     printlabel(litlab);
  769.     col();
  770.     dumplits(1);        /* dump literals */
  771.     }
  772.   }
  773.  
  774. /*
  775. ** declare argument types
  776. **
  777. ** called from "newfunc" this routine adds an entry in the
  778. ** local symbol table for each named argument
  779. */
  780. doargs(t) int t; {
  781.   int j, legalname;
  782.   char c, *argptr;
  783.   while(1) {
  784.     if(argstk==0) return;    /* no arguments */
  785.     if(match("(*")|match("*")) j=POINTER;  else j=VARIABLE;
  786.     if((legalname=symname(ssname, YES))==0) illname();
  787.     if(match(")")) ;
  788.     if(match("()")) ;
  789.     if(match("[")) {
  790.       paerror(j);
  791.       while(inbyte()!=']') if(endst()) break;    /* skip "[...]" */
  792.       j=POINTER;        /* add entry as pointer */
  793.       }
  794.     if(legalname) {
  795.       if(argptr=findloc(ssname)) {
  796.         /* add details of type and address */
  797.         argptr[IDENT]=j;
  798.         argptr[TYPE]=t;
  799.         putint(argtop-getint(argptr+OFFSET, OFFSIZE), argptr+OFFSET, OFFSIZE);
  800.         }
  801.       else error("not an argument");
  802.       }
  803.     argstk=argstk-BPW;        /* cnt down */
  804.     if(endst())return;
  805.     if(match(",")==0) error("no comma");
  806.     }
  807.   }
  808.  
  809. >>> CC13.C 6825
  810. /*
  811. ** statement parser
  812. **
  813. ** called whenever syntax requires a statement
  814. **  this routine performs that statement
  815. **  and returns a number telling which one
  816. */
  817. statement() {
  818.   if ((ch==0) & (eof)) return;
  819.   else if(amatch("char",4))  {declloc(CCHAR);ns();}
  820.   else if(amatch("int",3))   {declloc(CINT);ns();}
  821.   else {
  822.     if(declared >= 0) {
  823. #ifdef STGOTO
  824.       if(ncmp > 1) nogo=declared;    /* disable goto if any */
  825. #endif
  826.       csp=modstk(csp - declared, NO);
  827.       declared = -1;
  828.       }
  829.     if(match("{"))                compound();
  830.     else if(amatch("if",2))       {doif();        lastst=STIF;}
  831.     else if(amatch("while",5))    {dowhile();        lastst=STWHILE;}
  832. #ifdef STDO
  833.     else if(amatch("do",2))       {dodo();        lastst=STDO;}
  834. #endif
  835. #ifdef STFOR
  836.     else if(amatch("for",3))      {dofor();        lastst=STFOR;}
  837. #endif
  838. #ifdef STSWITCH
  839.     else if(amatch("switch",6))      {doswitch();        lastst=STSWITCH;}
  840.     else if(amatch("case",4))      {docase();        lastst=STCASE;}
  841.     else if(amatch("default",7))  {dodefault();        lastst=STDEF;}
  842. #endif
  843. #ifdef STGOTO
  844.     else if(amatch("goto", 4))      {dogoto();        lastst=STGOTO;}
  845.     else if(dolabel())                    lastst=STLABEL;
  846. #endif
  847.     else if(amatch("return",6))      {doreturn();ns();    lastst=STRETURN;}
  848.     else if(amatch("break",5))      {dobreak();ns();    lastst=STBREAK;}
  849.     else if(amatch("continue",8)) {docont();ns();    lastst=STCONT;}
  850.     else if(match(";"))          errflag=0;
  851.     else if(match("#asm"))      {doasm();        lastst=STASM;}
  852.     else              {doexpr();ns();    lastst=STEXPR;}
  853.     }
  854.   return lastst;
  855.   }
  856.  
  857. /*
  858. ** semicolon enforcer
  859. **
  860. ** called whenever syntax requires a semicolon
  861. */
  862. ns()  {
  863.   if(match(";")==0) error("no semicolon");
  864.   else errflag=0;
  865.   }
  866.  
  867. compound()  {
  868.   int savcsp;
  869.   char *savloc;
  870.   savcsp=csp;
  871.   savloc=locptr;
  872.   declared=0;            /* may now declare local variables */
  873.   ++ncmp;            /* new level open */
  874.   while (match("}")==0)
  875.     if(eof) {
  876.       error("no final }");
  877.       break;
  878.       }
  879.     else statement();        /* do one */
  880.   --ncmp;            /* close current level */
  881. /*55*/
  882. #ifdef STGOTO
  883.   if(lastst != STRETURN && lastst != STGOTO)
  884. #else
  885.   if(lastst != STRETURN)
  886. #endif
  887.     modstk(savcsp, NO);        /* delete local variable space */
  888.   csp=savcsp;
  889. /*55*/
  890. #ifdef STGOTO
  891.   cptr=savloc;            /* retain labels */
  892.   while(cptr < locptr) {
  893.     cptr2=nextsym(cptr);
  894.     if(cptr[IDENT] == LABEL) {
  895.       while(cptr < cptr2) *savloc++ = *cptr++;
  896.       }
  897.     else cptr=cptr2;
  898.     }
  899. #endif
  900.   locptr=savloc;        /* delete local symbols */
  901.   declared = -1;        /* may not declare variables */
  902.   }
  903.  
  904. doif()  {
  905.   int flab1,flab2;
  906.   flab1=getlabel();        /* get label for false branch */
  907.   test(flab1, YES);        /* get expression, and branch false */
  908.   statement();            /* if true, do a statement */
  909.   if (amatch("else",4)==0) {    /* if...else ? */
  910.     /* simple "if"...print false label */
  911.     postlabel(flab1);
  912.     return;            /* and exit */
  913.     }
  914.   flab2=getlabel();
  915. #ifdef STGOTO
  916.   if((lastst != STRETURN)&(lastst != STGOTO)) jump(flab2);
  917. #else
  918.   if(lastst != STRETURN) jump(flab2);
  919. #endif
  920.   postlabel(flab1);        /* print false label */
  921.   statement();            /* and do "else" clause */
  922.   postlabel(flab2);        /* print true label */
  923.   }
  924.  
  925. doexpr() {
  926.   int const, val;
  927.   char *before, *start;
  928.   while(1) {
  929.     setstage(&before, &start);
  930.     expression(&const, &val);
  931.     clearstage(before, start);
  932.     if(ch != ',') break;
  933.     bump(1);
  934.     }
  935.   }
  936.  
  937. dowhile()  {
  938.   int wq[4];            /* allocate local queue */
  939.   addwhile(wq);            /* add entry to queue for "break" */
  940.   postlabel(wq[WQLOOP]);    /* loop label */
  941.   test(wq[WQEXIT], YES);    /* see if true */
  942.   statement();            /* if so, do a statement */
  943.   jump(wq[WQLOOP]);        /* loop to label */
  944.   postlabel(wq[WQEXIT]);    /* exit label */
  945.   delwhile();            /* delete queue entry */
  946.   }
  947.  
  948. #ifdef STDO
  949. dodo() {
  950.   int wq[4], top;
  951.   addwhile(wq);
  952.   postlabel(top=getlabel());
  953.   statement();
  954.   needtoken("while");
  955.   postlabel(wq[WQLOOP]);
  956.   test(wq[WQEXIT], YES);
  957.   jump(top);
  958.   postlabel(wq[WQEXIT]);
  959.   delwhile();
  960.   ns();
  961.   }
  962. #endif
  963.  
  964. #ifdef STFOR
  965. dofor() {
  966.   int wq[4], lab1, lab2;
  967.   addwhile(wq);
  968.   lab1=getlabel();
  969.   lab2=getlabel();
  970.   needtoken("(");
  971.   if(match(";")==0) {
  972.     doexpr();            /* expr 1 */
  973.     ns();
  974.     }
  975.   postlabel(lab1);
  976.   if(match(";")==0) {
  977.     test(wq[WQEXIT], NO);    /* expr 2 */
  978.     ns();
  979.     }
  980.   jump(lab2);
  981.   postlabel(wq[WQLOOP]);
  982.   if(match(")")==0) {
  983.     doexpr();            /* expr 3 */
  984.     needtoken(")");
  985.     }
  986.   jump(lab1);
  987.   postlabel(lab2);
  988.   statement();
  989.   jump(wq[WQLOOP]);
  990.   postlabel(wq[WQEXIT]);
  991.   delwhile();
  992.   }
  993. #endif
  994.  
  995. #ifdef STSWITCH
  996. doswitch() {
  997.   int wq[4], endlab, swact, swdef, *swnex, *swptr;
  998.   swact=swactive;
  999.   swdef=swdefault;
  1000.   swnex=swptr=swnext;
  1001.   addwhile(wq);
  1002.   *(wqptr + WQLOOP - WQSIZ) = 0;
  1003.   needtoken("(");
  1004.   doexpr();            /* evaluate switch expression */
  1005.   needtoken(")");
  1006.   swdefault=0;
  1007.   swactive=1;
  1008.   jump(endlab=getlabel());
  1009.   statement();            /* cases, etc. */
  1010.   jump(wq[WQEXIT]);
  1011.   postlabel(endlab);
  1012.   sw();                /* match cases */
  1013.   while(swptr < swnext) {
  1014.     defstorage(CINT>>2);
  1015.     printlabel(*swptr++);    /* case label */
  1016.     outbyte(',');
  1017.     outdec(*swptr++);        /* case value */
  1018.     nl();
  1019.     }
  1020.   defstorage(CINT>>2);
  1021.   outdec(0);
  1022.   nl();
  1023.   if(swdefault) jump(swdefault);
  1024.   postlabel(wq[WQEXIT]);
  1025.   delwhile();
  1026.   swnext=swnex;
  1027.   swdefault=swdef;
  1028.   swactive=swact;
  1029.   }
  1030.  
  1031. docase() {
  1032.   if(swactive==0) error("not in switch");
  1033.   if(swnext > swend) {
  1034.     error("too many cases");
  1035.     return;
  1036.     }
  1037.   postlabel(*swnext++ = getlabel());
  1038.   constexpr(swnext++);
  1039.   needtoken(":");
  1040.   }
  1041.  
  1042. dodefault() {
  1043.   if(swactive) {
  1044.     if(swdefault) error("multiple defaults");
  1045.     }
  1046.   else error("not in switch");
  1047.   needtoken(":");
  1048.   postlabel(swdefault=getlabel());
  1049.   }
  1050. #endif
  1051.  
  1052. #ifdef STGOTO
  1053. dogoto() {
  1054.   if(nogo > 0) error("not allowed with block-locals");
  1055.   else noloc = 1;
  1056.   if(symname(ssname, YES)) jump(addlabel());
  1057.   else error("bad label");
  1058.   ns();
  1059.   }
  1060.  
  1061. dolabel() {
  1062.   char *savelptr;
  1063.   blanks();
  1064.   savelptr=lptr;
  1065.   if(symname(ssname, YES)) {
  1066.     if(gch()==':') {
  1067.       postlabel(addlabel());
  1068.       return 1;
  1069.       }
  1070.     else bump(savelptr-lptr);
  1071.     }
  1072.   return 0;
  1073.   }
  1074.  
  1075. addlabel()  {
  1076.   if(cptr=findloc(ssname)) {
  1077.     if(cptr[IDENT]!=LABEL) error("not a label");
  1078.     }
  1079.   else cptr=addsym(ssname, LABEL, LABEL, getlabel(), &locptr, LABEL);
  1080.   return (getint(cptr+OFFSET, OFFSIZE));
  1081.   }
  1082. #endif
  1083.  
  1084. doreturn()  {
  1085.   if(endst()==0) {
  1086.     doexpr();
  1087.     modstk(0, YES);
  1088.     }
  1089.   else modstk(0, NO);
  1090.   ffret();
  1091.   }
  1092.  
  1093. dobreak()  {
  1094.   int *ptr;
  1095.   if ((ptr=readwhile(wqptr))==0) return;
  1096.   modstk((ptr[WQSP]), NO);
  1097.   jump(ptr[WQEXIT]);
  1098.   }
  1099.  
  1100. docont()  {
  1101.   int *ptr;
  1102.   ptr = wqptr;
  1103.   while (1) {
  1104.     if ((ptr=readwhile(ptr))==0) return;
  1105.     if (ptr[WQLOOP]) break;
  1106.     }
  1107.   modstk((ptr[WQSP]), NO);
  1108.   jump(ptr[WQLOOP]);
  1109.   }
  1110.  
  1111. doasm()  {
  1112.   ccode=0;            /* mark mode as "asm" */
  1113.   while (1) {
  1114.     inline();
  1115.     if (match("#endasm")) break;
  1116.     if(eof)break;
  1117.     sout(line, output);
  1118.     }
  1119.   kill();
  1120.   ccode=1;
  1121.   }
  1122.  
  1123. >>> CC2.C 703
  1124. /*
  1125. ** Small-C Compiler Part 2
  1126. */
  1127. #include <stdio.h>
  1128. #include "cc.def"
  1129.  
  1130. extern char
  1131. #ifdef DYNAMIC
  1132.  *symtab,
  1133.  *stage,
  1134.  *macn,
  1135.  *macq,
  1136.  *pline,
  1137.  *mline,
  1138. #else
  1139.   symtab[SYMTBSZ],
  1140.   stage[STAGESIZE],
  1141.   macn[MACNSIZE],
  1142.   macq[MACQSIZE],
  1143.   pline[LINESIZE],
  1144.   mline[LINESIZE],
  1145. #endif
  1146. #ifdef OPTIMIZE
  1147.   optimize,
  1148. #endif
  1149.   alarm, *glbptr, *line, *lptr, *cptr, *cptr2,  *cptr3,
  1150.  *locptr, msname[NAMESIZE],  pause,  quote[2],
  1151.  *stagelast, *stagenext;
  1152. extern int
  1153. #ifdef DYNAMIC
  1154.   *wq,
  1155. #else
  1156.   wq[WQTABSZ],
  1157. #endif
  1158.   ccode,  ch,  csp,  eof,  errflag,  iflevel,
  1159.   input,  input2,  listfp,  macptr,  nch,
  1160.   nxtlab,  op[16],  opindex,  opsize,  output,  pptr,
  1161.   skiplevel,  *wqptr;
  1162.  
  1163. #include "cc21.c"
  1164. #include "cc22.c"
  1165.  
  1166. >>> CC21.C 4371
  1167. junk() {
  1168.   if(an(inbyte())) while(an(ch)) gch();
  1169.   else while(an(ch)==0) {
  1170.     if(ch==0) break;
  1171.     gch();
  1172.     }
  1173.   blanks();
  1174.   }
  1175.  
  1176. endst() {
  1177.   blanks();
  1178.   return ((streq(lptr,";")|(ch==0)));
  1179.   }
  1180.  
  1181. illname() {
  1182.   error("illegal symbol");
  1183.   junk();
  1184.   }
  1185.   
  1186. multidef(sname)  char *sname; {
  1187.   error("already defined");
  1188.   }
  1189.  
  1190. needtoken(str)  char *str; {
  1191.   if (match(str)==0) error("missing token");
  1192.   }
  1193.  
  1194. needlval() {
  1195.   error("must be lvalue");
  1196.   }
  1197.  
  1198. findglb(sname)  char *sname; {
  1199.   if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME))
  1200.     return cptr;
  1201.   return 0;
  1202.   }
  1203.  
  1204. findloc(sname)  char *sname;  {
  1205.   cptr = locptr - 1;        /* search backward for block locals */
  1206.   while(cptr > STARTLOC) {
  1207.     cptr = cptr - *cptr;
  1208.     if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
  1209.     cptr = cptr - NAME - 1;
  1210.     }
  1211.   return 0;
  1212.   }
  1213.  
  1214. addsym(sname, id, typ, value, lgptrptr, class)
  1215.   char *sname, id, typ;  int value, *lgptrptr, class; {
  1216.   if(lgptrptr == &glbptr) {
  1217.     if(cptr2=findglb(sname)) return cptr2;
  1218.     if(cptr==0) {
  1219.       error("global symbol table overflow");
  1220.       return 0;
  1221.       }
  1222.     }
  1223.   else {
  1224.     if(locptr > (ENDLOC-SYMMAX)) {
  1225.       error("local symbol table overflow");
  1226.       abort(ERRCODE);
  1227.       }
  1228.     cptr = *lgptrptr;
  1229.     }
  1230.   cptr[IDENT]=id;
  1231.   cptr[TYPE]=typ;
  1232.   cptr[CLASS]=class;
  1233.   putint(value, cptr+OFFSET, OFFSIZE);
  1234.   cptr3 = cptr2 = cptr + NAME;
  1235.   while(an(*sname)) *cptr2++ = *sname++;
  1236.   if(lgptrptr == &locptr) {
  1237.     *cptr2 = cptr2 - cptr3;    /* set length */
  1238.     *lgptrptr = ++cptr2;
  1239.     }
  1240.   return cptr;
  1241.   }
  1242.  
  1243. nextsym(entry) char *entry; {
  1244.   entry = entry + NAME;
  1245.   while(*entry++ >= ' ');    /* find length byte */
  1246.   return entry;
  1247.   }
  1248.  
  1249. /*
  1250. ** get integer of length len from address addr
  1251. ** (byte sequence set by "putint")
  1252. */
  1253. getint(addr, len) char *addr; int len; {
  1254.   int i;
  1255.   i = *(addr + --len);        /* high order byte sign extended */
  1256.   while(len--) i = (i << 8) | *(addr+len)&255;
  1257.   return i;
  1258.   }
  1259.  
  1260. /*
  1261. ** put integer i of length len into address addr
  1262. ** (low byte first)
  1263. */
  1264. putint(i, addr, len) char *addr; int i, len; {
  1265.   while(len--) {
  1266.     *addr++ = i;
  1267.     i = i>>8;
  1268.     }
  1269.   }
  1270.  
  1271. /*
  1272. ** test if next input string is legal symbol name
  1273. */
  1274. symname(sname, ucase) char *sname; int ucase; {
  1275.   int k;char c;
  1276.   blanks();
  1277.   if(alpha(ch)==0) return (*sname=0);
  1278.   k=0;
  1279.   while(an(ch)) {
  1280. #ifdef UPPER
  1281.     if(ucase)
  1282.       sname[k]=toupper(gch());
  1283.     else
  1284. #endif
  1285.       sname[k]=gch();
  1286.     if(k<NAMEMAX) ++k;
  1287.     }
  1288.   sname[k]=0;
  1289.   return 1;
  1290.   }
  1291.  
  1292. /*
  1293. ** return next avail internal label number
  1294. */
  1295. getlabel() {
  1296.   return(++nxtlab);
  1297.   }
  1298.  
  1299. /*
  1300. ** post a label in the program
  1301. */
  1302. postlabel(label) int label; {
  1303.   printlabel(label);
  1304.   col();
  1305.   nl();
  1306.   }
  1307.  
  1308. /*
  1309. ** print specified number as a label
  1310. */
  1311. printlabel(label)  int label; {
  1312.   outstr("CC");
  1313.   outdec(label);
  1314.   }
  1315.  
  1316. /*
  1317. ** test if c is alphabetic
  1318. */
  1319. alpha(c)  char c; {
  1320.   return (isalpha(c) || c=='_');
  1321.   }
  1322.  
  1323. /*
  1324. ** test if given character is alphanumeric
  1325. */
  1326. an(c)  char c; {
  1327.   return (alpha(c) || isdigit(c));
  1328.   }
  1329.  
  1330. addwhile(ptr)  int ptr[]; {
  1331.   int k;
  1332.   ptr[WQSP]=csp;        /* and stk ptr */
  1333.   ptr[WQLOOP]=getlabel();    /* and looping label */
  1334.   ptr[WQEXIT]=getlabel();    /* and exit label */
  1335.   if (wqptr==WQMAX) {
  1336.     error("too many active loops");
  1337.     abort(ERRCODE);
  1338.     }
  1339.   k=0;
  1340.   while (k<WQSIZ) *wqptr++ = ptr[k++];
  1341.   }
  1342.  
  1343. delwhile() {
  1344.   if (wqptr > wq) wqptr=wqptr-WQSIZ;
  1345.   }
  1346.  
  1347. readwhile(ptr) int *ptr; {
  1348.   if (ptr <= wq) {
  1349.     error("out of context");
  1350.     return 0;
  1351.     }
  1352.   else return (ptr-WQSIZ);
  1353.  }
  1354.  
  1355. white() {
  1356. #ifdef DYNAMIC
  1357.   /* test for stack/prog overlap at deepest nesting */
  1358.   /* primary -> symname -> blanks -> white */
  1359.   avail(YES);        /* abort on stack overflow */
  1360. #endif
  1361.   return (*lptr<= ' ' && *lptr!=NULL);
  1362.   }
  1363.  
  1364. gch() {
  1365.   int c;
  1366.   if(c=ch) bump(1);
  1367.   return c;
  1368.   }
  1369.  
  1370. bump(n) int n; {
  1371.   if(n) lptr=lptr+n;
  1372.   else  lptr=line;
  1373.   if(ch=nch = *lptr) nch = *(lptr+1);
  1374.   }
  1375.  
  1376. kill() {
  1377.   *line=0;
  1378.   bump(0);
  1379.   }
  1380.  
  1381. inbyte()  {
  1382.   while(ch==0) {
  1383.     if (eof) return 0;
  1384.     preprocess();
  1385.     }
  1386.   return gch();
  1387.   }
  1388.  
  1389. inline() {            /* numerous revisions */
  1390.   int k,unit;
  1391.   poll(1);            /* allow operator interruption */
  1392.   if (input==EOF) openfile();
  1393.   if(eof) return;
  1394.   if((unit=input2)==EOF) unit=input;
  1395.   if(fgets(line, LINEMAX, unit)==NULL) {
  1396.     fclose(unit);
  1397.     if(input2!=EOF) input2=EOF;
  1398.     else input=EOF;
  1399.     *line=NULL;
  1400.     }
  1401.   else if(listfp) {
  1402.     if(listfp==output) cout(';', output);
  1403.     sout(line, listfp);
  1404.     }
  1405.   bump(0);
  1406.   }
  1407.  
  1408. >>> CC22.C 6866
  1409. ifline() {
  1410.   while(1) {
  1411.     inline();
  1412.     if(eof) return;
  1413.     if(match("#ifdef")) {
  1414.       ++iflevel;
  1415.       if(skiplevel) continue;
  1416.       symname(msname, NO);
  1417.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0)
  1418.         skiplevel=iflevel;
  1419.       continue;
  1420.       }
  1421.     if(match("#ifndef")) {
  1422.       ++iflevel;
  1423.       if(skiplevel) continue;
  1424.       symname(msname, NO);
  1425.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
  1426.         skiplevel=iflevel;
  1427.       continue;
  1428.       }
  1429.     if(match("#else")) {
  1430.       if(iflevel) {
  1431.         if(skiplevel==iflevel) skiplevel=0;
  1432.         else if(skiplevel==0)  skiplevel=iflevel;
  1433.         }
  1434.       else noiferr();
  1435.       continue;
  1436.       }
  1437.     if(match("#endif")) {
  1438.       if(iflevel) {
  1439.         if(skiplevel==iflevel) skiplevel=0;
  1440.         --iflevel;
  1441.         }
  1442.       else noiferr();
  1443.       continue;
  1444.       }
  1445.     if(skiplevel) continue;
  1446.     if(ch==0) continue;
  1447.     break;
  1448.     }
  1449.   }
  1450.  
  1451. keepch(c)  char c; {
  1452.   if(pptr<LINEMAX) pline[++pptr]=c;
  1453.   }
  1454.  
  1455. preprocess() {
  1456.   int k;
  1457.   char c;
  1458.   if(ccode) {
  1459.     line=mline;
  1460.     ifline();
  1461.     if(eof) return;
  1462.     }
  1463.   else {
  1464.     line=pline;
  1465.     inline();
  1466.     return;
  1467.     }
  1468.   pptr = -1;
  1469.   while(ch != NEWLINE && ch) {
  1470.     if(white()) {
  1471.       keepch(' ');
  1472.       while(white()) gch();
  1473.       }
  1474.     else if(ch=='"') {
  1475.       keepch(ch);
  1476.       gch();
  1477.       while((ch!='"')|((*(lptr-1)==92)&(*(lptr-2)!=92))) {
  1478.         if(ch==0) {
  1479.           error("no quote");
  1480.           break;
  1481.           }
  1482.         keepch(gch());
  1483.         }
  1484.       gch();
  1485.       keepch('"');
  1486.       }
  1487.     else if(ch==39) {
  1488.       keepch(39);
  1489.       gch();
  1490.       while((ch!=39)|((*(lptr-1)==92)&(*(lptr-2)!=92))) {
  1491.         if(ch==0) {
  1492.           error("no apostrophe");
  1493.           break;
  1494.           }
  1495.         keepch(gch());
  1496.         }
  1497.       gch();
  1498.       keepch(39);
  1499.       }
  1500.     else if((ch=='/')&(nch=='*')) {
  1501.       bump(2);
  1502.       while(((ch=='*')&(nch=='/'))==0) {
  1503.         if(ch) bump(1);
  1504.         else {
  1505.           ifline();
  1506.           if(eof) break;
  1507.           }
  1508.         }
  1509.       bump(2);
  1510.       }
  1511.     else if(an(ch)) {
  1512.       k=0;
  1513.       while((an(ch)) & (k<NAMEMAX)) {
  1514.         msname[k++]=ch;
  1515.         gch();
  1516.         }
  1517.       msname[k]=0;
  1518.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
  1519.         k=getint(cptr+NAMESIZE, 2);
  1520.         while(c=macq[k++]) keepch(c);
  1521.         while(an(ch)) gch();
  1522.         }
  1523.       else {
  1524.         k=0;
  1525.         while(c=msname[k++]) keepch(c);
  1526.         }
  1527.       }
  1528.     else keepch(gch());
  1529.     }
  1530.   if(pptr>=LINEMAX) error("line too long");
  1531.   keepch(0);
  1532.   line=pline;
  1533.   bump(0);
  1534.   }
  1535.  
  1536. noiferr() {
  1537.   error("no matching #if...");
  1538.   errflag=0;
  1539.   }
  1540.  
  1541. addmac() {
  1542.   int k;
  1543.   if(symname(msname, NO)==0) {
  1544.     illname();
  1545.     kill();
  1546.     return;
  1547.     }
  1548.   k=0;
  1549.   if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) {
  1550.     if(cptr2=cptr) while(*cptr2++ = msname[k++]);
  1551.     else {
  1552.       error("macro name table full");
  1553.       return;
  1554.       }
  1555.     }
  1556.   putint(macptr, cptr+NAMESIZE, 2);
  1557.   while(white()) gch();
  1558.   while(putmac(gch()));
  1559.   if(macptr>=MACMAX) {
  1560.     error("macro string queue full"); abort(ERRCODE);
  1561.     }
  1562.   }
  1563.  
  1564. putmac(c)  char c; {
  1565.   macq[macptr]=c;
  1566.   if(macptr<MACMAX) ++macptr;
  1567.   return c;
  1568.   }
  1569.  
  1570. /*
  1571. ** search for symbol match
  1572. ** on return cptr points to slot found or empty slot
  1573. */
  1574. search(sname, buf, len, end, max, off)
  1575.   char *sname, *buf, *end;  int len, max, off; {
  1576.   cptr=cptr2=buf+((hash(sname)%(max-1))*len);
  1577.   while(*cptr != 0) {
  1578.     if(astreq(sname, cptr+off, NAMEMAX)) return 1;
  1579.     if((cptr=cptr+len) >= end) cptr=buf;
  1580.     if(cptr == cptr2) return (cptr=0);
  1581.     }
  1582.   return 0;
  1583.   }
  1584.  
  1585. hash(sname) char *sname; {
  1586.   int i, c;
  1587.   i=0;
  1588.   while(c = *sname++) i=(i<<1)+c;
  1589.   return i;
  1590.   }
  1591.  
  1592. setstage(before, start) int *before, *start; {
  1593.   if((*before=stagenext)==0) stagenext=stage;
  1594.   *start=stagenext;
  1595.   }
  1596.  
  1597. clearstage(before, start) char *before, *start; {
  1598.   *stagenext=0;
  1599.   if(stagenext=before) return;
  1600.   if(start) {
  1601. #ifdef OPTIMIZE
  1602.     peephole(start);
  1603. #else
  1604.     sout(start, output);
  1605. #endif
  1606.     }
  1607.   }
  1608.  
  1609. outdec(number)  int number; {
  1610.   int k,zs;
  1611.   char c, *q, *r;
  1612.   zs = 0;
  1613.   k=10000;
  1614.   if (number<0) {
  1615.     number=(-number);
  1616.     outbyte('-');
  1617.     }
  1618.   while (k>=1) {
  1619.     q=0; r=number;
  1620.     while(r >= k) {++q; r -= k;}
  1621.     c = q + '0';
  1622.     if ((c!='0')|(k==1)|(zs)) {
  1623.       zs=1;
  1624.       outbyte(c);
  1625.       }
  1626.     number=r;
  1627.     k=k/10;
  1628.     }
  1629.   }
  1630.  
  1631. ol(ptr)  char ptr[];  {
  1632.   ot(ptr);
  1633.   nl();
  1634.   }
  1635.  
  1636. ot(ptr) char ptr[]; {
  1637.   outstr(ptr);
  1638.   }
  1639.  
  1640. outstr(ptr) char ptr[]; {
  1641.   poll(1); /* allow program interruption */
  1642.   /* must work with symbol table names terminated by length */
  1643.   while(*ptr >= ' ') outbyte(*ptr++);
  1644.   }
  1645.  
  1646. outbyte(c) char c; {
  1647.   if(stagenext) {
  1648.     if(stagenext==stagelast) {
  1649.       error("staging buffer overflow");
  1650.       return 0;
  1651.       }
  1652.     else *stagenext++ = c;
  1653.     }
  1654.   else cout(c,output);
  1655.   return c;
  1656.   }
  1657.  
  1658. cout(c, fd) char c; int fd; {
  1659.   if(fputc(c, fd)==EOF) xout();
  1660.   }
  1661.  
  1662. sout(string, fd) char *string; int fd; {
  1663.   if(fputs(string, fd)==EOF) xout();
  1664.   }
  1665.  
  1666. lout(line, fd) char *line; int fd; {
  1667.   sout(line, fd);
  1668.   cout(NEWLINE, fd);
  1669.   }
  1670.  
  1671. xout() {
  1672.   fputs("output error", stderr);
  1673.   abort(ERRCODE);
  1674.   }
  1675.  
  1676. nl() {
  1677.   outbyte(NEWLINE);
  1678.   }
  1679.  
  1680. col() {
  1681. #ifdef COL
  1682.   outbyte(':');
  1683. #endif
  1684.   }
  1685.  
  1686. error(msg) char msg[]; {
  1687.   if(errflag) return; else errflag=1;
  1688.   lout(line, stderr);
  1689.   errout(msg, stderr);
  1690.   if(alarm) fputc(7, stderr);
  1691.   if(pause) while(fgetc(stderr)!=NEWLINE);
  1692.   if(listfp>0) errout(msg, listfp);
  1693.   }
  1694.  
  1695. errout(msg, fp) char msg[]; int fp; {
  1696.   int k; k=line+2;
  1697.   while(k++ <= lptr) cout(' ', fp);
  1698.   lout("/\\", fp);
  1699.   sout("**** ", fp); lout(msg, fp);
  1700.   }
  1701.  
  1702. streq(str1,str2)  char str1[],str2[]; {
  1703.   int k;
  1704.   k=0;
  1705.   while (str2[k]) {
  1706.     if ((str1[k])!=(str2[k])) return 0;
  1707.     ++k;
  1708.     }
  1709.   return k;
  1710.  }
  1711.  
  1712. astreq(str1,str2,len)  char str1[],str2[];int len; {
  1713.   int k;
  1714.   k=0;
  1715.   while (k<len) {
  1716.     if ((str1[k])!=(str2[k]))break;
  1717.     /*
  1718.     ** must detect end of symbol table names terminated by
  1719.     ** symbol length in binary
  1720.     */
  1721.     if(str1[k] < ' ') break;
  1722.     if(str2[k] < ' ') break;
  1723.     ++k;
  1724.     }
  1725.   if (an(str1[k]))return 0;
  1726.   if (an(str2[k]))return 0;
  1727.   return k;
  1728.  }
  1729.  
  1730. match(lit)  char *lit; {
  1731.   int k;
  1732.   blanks();
  1733.   if (k=streq(lptr,lit)) {
  1734.     bump(k);
  1735.     return 1;
  1736.     }
  1737.   return 0;
  1738.   }
  1739.  
  1740. amatch(lit,len)  char *lit;int len; {
  1741.   int k;
  1742.   blanks();
  1743.   if (k=astreq(lptr,lit,len)) {
  1744.     bump(k);
  1745.     while(an(ch)) inbyte();
  1746.     return 1;
  1747.     }
  1748.   return 0;
  1749.  }
  1750.  
  1751. nextop(list) char *list; {
  1752.   char op[4];
  1753.   opindex=0;
  1754.   blanks();
  1755.   while(1) {
  1756.     opsize=0;
  1757.     while(*list > ' ') op[opsize++] = *list++;
  1758.     op[opsize]=0;
  1759.     if(opsize=streq(lptr, op))
  1760.       if((*(lptr+opsize) != '=')&
  1761.          (*(lptr+opsize) != *(lptr+opsize-1)))
  1762.          return 1;
  1763.     if(*list) {
  1764.       ++list;
  1765.       ++opindex;
  1766.       }
  1767.     else return 0;
  1768.     }
  1769.   }
  1770.  
  1771. blanks() {
  1772.   while(1) {
  1773.     while(ch) {
  1774.       if(white()) gch();
  1775.       else return;
  1776.       }
  1777.     if(line==mline) return;
  1778.     preprocess();
  1779.     if(eof)break;
  1780.     }
  1781.   }
  1782.  
  1783. >>> CC3.C 373
  1784. /*
  1785. ** Small-C Compiler Part 3
  1786. */
  1787. #include <stdio.h>
  1788. #include "cc.def"
  1789.  
  1790. extern char
  1791. #ifdef DYNAMIC
  1792.  *stage,
  1793.  *litq,
  1794. #else
  1795.   stage[STAGESIZE],
  1796.   litq[LITABSZ],
  1797. #endif
  1798.  *glbptr, *lptr,  ssname[NAMESIZE],  quote[2], *stagenext;
  1799. extern int
  1800.   ch,  csp,  litlab,  litptr,  nch,  op[16],  op2[16],
  1801.   oper,  opindex,  opsize;
  1802.  
  1803. #include "cc31.c"
  1804. #include "cc32.c"
  1805. #include "cc33.c"
  1806.  
  1807. >>> CC31.C 6680
  1808. /*
  1809. ** lval[0] - symbol table address, else 0 for constant
  1810. ** lval[1] - type of indirect obj to fetch, else 0 for static
  1811. ** lval[2] - type of pointer or array, else 0 for all other
  1812. ** lval[3] - true if constant expression
  1813. ** lval[4] - value of constant expression (+ auxiliary uses)
  1814. ** lval[5] - true if secondary register altered
  1815. ** lval[6] - function address of highest/last binary operator
  1816. ** lval[7] - stage address of "oper 0" code, else 0
  1817. */
  1818.  
  1819. /*
  1820. ** skim over terms adjoining || and && operators
  1821. */
  1822. skim(opstr, testfunc, dropval, endval, hier, lval)
  1823.   char *opstr;
  1824.   int (*testfunc)(), dropval, endval, (*hier)(), lval[]; {
  1825.   int k, hits, droplab, endlab;
  1826.   hits=0;
  1827.   while(1) {
  1828.     k=plnge1(hier, lval);
  1829.     if(nextop(opstr)) {
  1830.       bump(opsize);
  1831.       if(hits==0) {
  1832.         hits=1;
  1833.         droplab=getlabel();
  1834.         }
  1835.       dropout(k, testfunc, droplab, lval);
  1836.       }
  1837.     else if(hits) {
  1838.       dropout(k, testfunc, droplab, lval);
  1839.       const(endval);
  1840.       jump(endlab=getlabel());
  1841.       postlabel(droplab);
  1842.       const(dropval);
  1843.       postlabel(endlab);
  1844.       lval[1]=lval[2]=lval[3]=lval[4]=lval[7]=0;
  1845.       return 0;
  1846.       }
  1847.     else return k;
  1848.     }
  1849.   }
  1850.  
  1851. /*
  1852. ** test for early dropout from || or && evaluations
  1853. */
  1854. dropout(k, testfunc, exit1, lval)
  1855.   int k, (*testfunc)(), exit1, lval[]; {
  1856.   if(k) rvalue(lval);
  1857.   else if(lval[3]) const(lval[4]);
  1858.   (*testfunc)(exit1);        /* jumps on false */
  1859.   }
  1860.  
  1861. /*
  1862. ** plunge to a lower level
  1863. */
  1864. plnge(opstr, opoff, hier, lval)
  1865.   char *opstr;
  1866.   int opoff, (*hier)(), lval[]; {
  1867.   int k, lval2[8];
  1868.   k=plnge1(hier, lval);
  1869.   if(nextop(opstr)==0) return k;
  1870.   if(k) rvalue(lval);
  1871.   while(1) {
  1872.     if(nextop(opstr)) {
  1873.       bump(opsize);
  1874.       opindex=opindex+opoff;
  1875.       plnge2(op[opindex], op2[opindex], hier, lval, lval2);
  1876.       }
  1877.     else return 0;
  1878.     }
  1879.   }
  1880.  
  1881. /*
  1882. ** unary plunge to lower level
  1883. */
  1884. plnge1(hier, lval) int (*hier)(), lval[]; {
  1885.   char *before, *start;
  1886.   int k;
  1887.   setstage(&before, &start);
  1888.   k=(*hier)(lval);
  1889.   if(lval[3]) clearstage(before,0);    /* load constant later */
  1890.   return k;
  1891.   }
  1892.  
  1893. /*
  1894. ** binary plunge to lower level
  1895. */
  1896. plnge2(oper, oper2, hier, lval, lval2)
  1897.   int (*oper)(),(*oper2)(),(*hier)(),lval[],lval2[]; {
  1898.   char *before, *start;
  1899.   setstage(&before, &start);
  1900.   lval[5]=1;        /* flag secondary register used */
  1901.   lval[7]=0;        /* flag as not "... oper 0" syntax */
  1902.   if(lval[3]) {        /* constant on left side not yet loaded */
  1903.     if(plnge1(hier, lval2)) rvalue(lval2);
  1904.     if(lval[4]==0) lval[7]=stagenext;
  1905.     const2(lval[4]<<dbltest(oper, lval2, lval));
  1906.     }
  1907.   else {        /* non-constant on left side */
  1908.     push();
  1909.     if(plnge1(hier, lval2)) rvalue(lval2);
  1910.     if(lval2[3]) {    /* constant on right side */
  1911.       if(lval2[4]==0) lval[7]=start;
  1912.       if(oper==ffadd) {    /* may test other commutative operators */
  1913.         csp=csp+2;
  1914.         clearstage(before, 0);
  1915.         const2(lval2[4]<<dbltest(oper, lval, lval2));
  1916.             /* load secondary */
  1917.         }
  1918.       else {
  1919.         const(lval2[4]<<dbltest(oper, lval, lval2));
  1920.             /* load primary */
  1921.         smartpop(lval2, start);
  1922.         }
  1923.       }
  1924.     else {        /* non-constants on both sides */
  1925.       smartpop(lval2, start);
  1926.       if(dbltest(oper, lval,lval2)) doublereg();
  1927.       if(dbltest(oper, lval2,lval)) {
  1928.         swap();
  1929.         doublereg();
  1930.         if(oper==ffsub) swap();
  1931.         }
  1932.       }
  1933.     }
  1934.   if(oper) {
  1935.     if(lval[3]=lval[3]&lval2[3]) {
  1936.       lval[4]=calc(lval[4], oper, lval2[4]);
  1937.       clearstage(before, 0);  
  1938.       lval[5]=0;
  1939.       }
  1940.     else {
  1941.       if((lval[2]==0)&(lval2[2]==0)) {
  1942.         (*oper)();
  1943.         lval[6]=oper;            /* identify the operator */
  1944.         }
  1945.       else {
  1946.         (*oper2)();
  1947.         lval[6]=oper2;            /* identify the operator */
  1948.         }
  1949.       }
  1950.     if(oper==ffsub) {
  1951.       if((lval[2]==CINT)&(lval2[2]==CINT)) {
  1952.         swap();
  1953.         const(1);
  1954.         ffasr();            /** div by 2 **/
  1955.         }
  1956.       }
  1957.     if((oper==ffsub)|(oper==ffadd)) result(lval, lval2);
  1958.     }
  1959.   }
  1960.  
  1961. calc(left, oper, right) int left, (*oper)(), right; {
  1962.        if(oper ==  ffor) return (left  |  right);
  1963.   else if(oper == ffxor) return (left  ^  right);
  1964.   else if(oper == ffand) return (left  &  right);
  1965.   else if(oper ==  ffeq) return (left  == right);
  1966.   else if(oper ==  ffne) return (left  != right);
  1967.   else if(oper ==  ffle) return (left  <= right);
  1968.   else if(oper ==  ffge) return (left  >= right);
  1969.   else if(oper ==  fflt) return (left  <  right);
  1970.   else if(oper ==  ffgt) return (left  >  right);
  1971.   else if(oper == ffasr) return (left  >> right);
  1972.   else if(oper == ffasl) return (left  << right);
  1973.   else if(oper == ffadd) return (left  +  right);
  1974.   else if(oper == ffsub) return (left  -  right);
  1975.   else if(oper ==ffmult) return (left  *  right);
  1976.   else if(oper == ffdiv) return (left  /  right);
  1977.   else if(oper == ffmod) return (left  %  right);
  1978.   else return 0;
  1979.   }
  1980.  
  1981. expression(const, val) int *const, *val;  {
  1982.   int lval[8];
  1983.   if(hier1(lval)) rvalue(lval);
  1984.   if(lval[3]) {
  1985.     *const=1;
  1986.     *val=lval[4];
  1987.     }
  1988.   else *const=0;
  1989.   }
  1990.  
  1991. hier1(lval)  int lval[];  {
  1992.   int k,lval2[8], lval3[2], oper;
  1993.   k=plnge1(hier3, lval);
  1994.   if(lval[3]) const(lval[4]);
  1995.        if(match("|="))  oper=ffor;
  1996.   else if(match("^="))  oper=ffxor;
  1997.   else if(match("&="))  oper=ffand;
  1998.   else if(match("+="))  oper=ffadd;
  1999.   else if(match("-="))  oper=ffsub;
  2000.   else if(match("*="))  oper=ffmult;
  2001.   else if(match("/="))  oper=ffdiv;
  2002.   else if(match("%="))  oper=ffmod;
  2003.   else if(match(">>=")) oper=ffasr;
  2004.   else if(match("<<=")) oper=ffasl;
  2005.   else if(match("="))   oper=0;
  2006.   else return k;
  2007.   if(k==0) {
  2008.     needlval();
  2009.     return 0;
  2010.     }
  2011.   lval3[0] = lval[0];
  2012.   lval3[1] = lval[1];
  2013.   if(lval[1]) {
  2014.     if(oper) {
  2015.       push();
  2016.       rvalue(lval);
  2017.       }
  2018.     plnge2(oper, oper, hier1, lval, lval2);
  2019.     if(oper) pop();
  2020.     }
  2021.   else {
  2022.     if(oper) {
  2023.       rvalue(lval);
  2024.       plnge2(oper, oper, hier1, lval, lval2);
  2025.       }
  2026.     else {
  2027.       if(hier1(lval2)) rvalue(lval2);
  2028.       lval[5]=lval2[5];
  2029.       }
  2030.     }
  2031.   store(lval3);
  2032.   return 0;
  2033.   }
  2034.  
  2035. hier3(lval)  int lval[]; {
  2036.   return skim("||", eq0, 1, 0, hier4, lval);
  2037.   }
  2038.  
  2039. hier4(lval)  int lval[]; {
  2040.   return skim("&&", ne0, 0, 1, hier5, lval);
  2041.   }
  2042.  
  2043. hier5(lval)  int lval[]; {
  2044.   return plnge("|", 0, hier6, lval);
  2045.   }
  2046.  
  2047. hier6(lval)  int lval[]; {
  2048.   return plnge("^", 1, hier7, lval);
  2049.   }
  2050.  
  2051. hier7(lval)  int lval[]; {
  2052.   return plnge("&", 2, hier8, lval);
  2053.   }
  2054.  
  2055. hier8(lval)  int lval[];  {
  2056.   return plnge("== !=", 3, hier9, lval);
  2057.   }
  2058.  
  2059. hier9(lval)  int lval[];  {
  2060.   return plnge("<= >= < >", 5, hier10, lval);
  2061.   }
  2062.  
  2063. hier10(lval)  int lval[];  {
  2064.   return plnge(">> <<", 9, hier11, lval);
  2065.   }
  2066.  
  2067. hier11(lval)  int lval[];  {
  2068.   return plnge("+ -", 11, hier12, lval);
  2069.   }
  2070.  
  2071. hier12(lval)  int lval[];  {
  2072.   return plnge("* / %", 13, hier13, lval);
  2073.   }
  2074.  
  2075. >>> CC32.C 5065
  2076. hier13(lval)  int lval[];  {
  2077.   int k;
  2078.   char *ptr;
  2079.   if(match("++")) {            /* ++lval */
  2080.     if(hier13(lval)==0) {
  2081.       needlval();
  2082.       return 0;
  2083.       }
  2084.     step(inc, lval);
  2085.     return 0;
  2086.     }
  2087.   else if(match("--")) {        /* --lval */
  2088.     if(hier13(lval)==0) {
  2089.       needlval();
  2090.       return 0;
  2091.       }
  2092.     step(dec, lval);
  2093.     return 0;
  2094.     }
  2095.   else if (match("~")) {        /* ~ */
  2096.     if(hier13(lval)) rvalue(lval);
  2097.     com();
  2098.     lval[4] = ~lval[4];
  2099.     return (lval[7]=0);
  2100.     }
  2101.   else if (match("!")) {        /* ! */
  2102.     if(hier13(lval)) rvalue(lval);
  2103.     lneg();
  2104.     lval[4] = !lval[4];
  2105.     return (lval[7]=0);
  2106.     }
  2107.   else if (match("-")) {        /* unary - */
  2108.     if(hier13(lval)) rvalue(lval);
  2109.     neg();
  2110.     lval[4] = -lval[4];
  2111.     return (lval[7]=0);
  2112.     }
  2113.   else if(match("*")) {            /* unary * */
  2114.     if(hier13(lval)) rvalue(lval);
  2115.     if(ptr=lval[0])lval[1]=ptr[TYPE];
  2116.     else lval[1]=CINT;
  2117.     lval[2]=0;        /* flag as not pointer or array */
  2118.     lval[3]=0;        /* flag as not constant */
  2119.     lval[4]=1;        /* omit rvalue() on func call */
  2120.     lval[7]=0;
  2121.     return 1;
  2122.     }
  2123.   else if(match("&")) {            /* unary & */
  2124.     if(hier13(lval)==0) {
  2125.       error("illegal address");
  2126.       return 0;
  2127.       }
  2128.     ptr=lval[0];
  2129.     lval[2]=ptr[TYPE];
  2130.     if(lval[1]) return 0;
  2131.                     /* global & non-array */
  2132.     address(ptr);
  2133.     lval[1]=ptr[TYPE];
  2134.     return 0;
  2135.     }
  2136.   else {
  2137.     k=hier14(lval);
  2138.     if(match("++")) {            /* lval++ */
  2139.       if(k==0) {
  2140.         needlval();
  2141.         return 0;
  2142.         }
  2143.       step(inc, lval);
  2144.       dec(lval[2]>>2);
  2145.       return 0;
  2146.       }
  2147.     else if(match("--")) {        /* lval-- */
  2148.       if(k==0) {
  2149.         needlval();
  2150.         return 0;
  2151.         }
  2152.       step(dec, lval);
  2153.       inc(lval[2]>>2);
  2154.       return 0;
  2155.       }
  2156.     else return k;
  2157.     }
  2158.   }
  2159.  
  2160. hier14(lval)  int *lval; {
  2161.   int k, const, val, lval2[8];
  2162.   char *ptr, *before, *start;
  2163.   k=primary(lval);
  2164.   ptr=lval[0];
  2165.   blanks();
  2166.   if((ch=='[')|(ch=='(')) {
  2167.     lval[5]=1;            /* secondary register will be used */
  2168.     while(1) {
  2169.       if(match("[")) {            /* [subscript] */
  2170.         if(ptr==0) {
  2171.           error("can't subscript");
  2172.           junk();
  2173.           needtoken("]");
  2174.           return 0;
  2175.           }
  2176.         else if(ptr[IDENT]==POINTER)rvalue(lval);
  2177.         else if(ptr[IDENT]!=ARRAY) {
  2178.           error("can't subscript");
  2179.           k=0;
  2180.           }
  2181.         setstage(&before, &start);
  2182.         lval2[3]=0;
  2183.         plnge2(0, 0, hier1, lval2, lval2); /* lval2 deadend */
  2184.         needtoken("]");
  2185.         if(lval2[3]) {
  2186.           clearstage(before, 0);
  2187.           if(lval2[4]) {
  2188.             if(ptr[TYPE]==CINT) const2(lval2[4]<<LBPW);
  2189.             else                const2(lval2[4]);
  2190.             ffadd();
  2191.             }
  2192.           }
  2193.         else {
  2194.           if(ptr[TYPE]==CINT) doublereg();
  2195.           ffadd();
  2196.           }
  2197.         lval[2]=0;
  2198.         lval[1]=ptr[TYPE];
  2199.         k=1;
  2200.         }
  2201.       else if(match("(")) {        /* function(...) */
  2202.         if(ptr==0) callfunction(0);
  2203.         else if(ptr[IDENT]!=FUNCTION) {
  2204.           if(k && !lval[4]) rvalue(lval);
  2205.           callfunction(0);
  2206.           }
  2207.         else callfunction(ptr);
  2208.         k=lval[0]=lval[3]=lval[4]=0;
  2209.         }
  2210.       else return k;
  2211.       }
  2212.     }
  2213.   if(ptr==0) return k;
  2214.   if(ptr[IDENT]==FUNCTION) {
  2215.     address(ptr);
  2216.     lval[0]=0;
  2217.     return 0;
  2218.     }
  2219.   return k;
  2220.   }
  2221.  
  2222. primary(lval)  int *lval; {
  2223.   char *ptr, sname[NAMESIZE];
  2224.   int k;
  2225.   if(match("(")) {            /* (expression,...) */
  2226.     do k=hier1(lval); while(match(","));
  2227.     needtoken(")");
  2228.     return k;
  2229.     }
  2230.   putint(0, lval, 8<<LBPW);        /* clear lval array */
  2231.   if(symname(sname, YES)) {
  2232.     if(ptr=findloc(sname)) {
  2233. #ifdef STGOTO
  2234.       if(ptr[IDENT]==LABEL) {
  2235.         experr();
  2236.         return 0;
  2237.         }
  2238. #endif
  2239.       getloc(ptr);
  2240.       lval[0]=ptr;
  2241.       lval[1]=ptr[TYPE];
  2242.       if(ptr[IDENT]==POINTER) {
  2243.         lval[1]=CINT;
  2244.         lval[2]=ptr[TYPE];
  2245.         }
  2246.       if(ptr[IDENT]==ARRAY) {
  2247.         lval[2]=ptr[TYPE];
  2248.         return 0;
  2249.         }
  2250.       else return 1;
  2251.       }
  2252.     if(ptr=findglb(sname))
  2253.       if(ptr[IDENT]!=FUNCTION) {
  2254.         lval[0]=ptr;
  2255.         lval[1]=0;
  2256.         if(ptr[IDENT]!=ARRAY) {
  2257.           if(ptr[IDENT]==POINTER) lval[2]=ptr[TYPE];
  2258.           return 1;
  2259.           }
  2260.         address(ptr);
  2261.         lval[1]=lval[2]=ptr[TYPE];
  2262.         return 0;
  2263.         }
  2264.     ptr=addsym(sname,FUNCTION,CINT,0,&glbptr,AUTOEXT);
  2265.     lval[0]=ptr;
  2266.     lval[1]=0;
  2267.     return 0;
  2268.     }
  2269.   if(constant(lval)==0) experr();
  2270.   return 0;
  2271.   }
  2272.  
  2273. experr() {
  2274.   error("invalid expression");
  2275.   const(0);
  2276.   junk();
  2277.   }
  2278.  
  2279. callfunction(ptr)  char *ptr; {        /* symbol table entry or 0 */
  2280.   int nargs, const, val;
  2281.   nargs=0;
  2282.   blanks();                /* already saw open paren */
  2283.   while(streq(lptr,")")==0) {
  2284.     if(endst()) break;
  2285.     if(ptr) {
  2286.       expression(&const, &val);
  2287.       push();
  2288.       }
  2289.     else {
  2290.       push();
  2291.       expression(&const, &val);
  2292.       swapstk();
  2293.       }
  2294.     nargs=nargs+BPW;            /* count args*BPW */
  2295.     if (match(",")==0) break;
  2296.     }
  2297.   needtoken(")");
  2298.   if(streq(ptr+NAME, "CCARGC")==0) loadargc(nargs>>LBPW);
  2299.   if(ptr) ffcall(ptr+NAME);
  2300.   else callstk();
  2301.   csp=modstk(csp+nargs, YES);
  2302.   }
  2303.  
  2304. >>> CC33.C 4152
  2305. /*
  2306. ** true if val1 -> int pointer or int array and val2 not ptr or array
  2307. */
  2308. dbltest(oper, val1, val2) int (*oper)(), val1[], val2[]; {
  2309.   if((oper!=ffadd) && (oper!=ffsub)) return 0;
  2310.   if(val1[2]!=CINT) return 0;
  2311.   if(val2[2]) return 0;
  2312.   return 1;
  2313.   }
  2314.  
  2315. /*
  2316. ** determine type of binary operation
  2317. */
  2318. result(lval, lval2) int lval[], lval2[]; {
  2319.   if((lval[2]!=0)&(lval2[2]!=0)) {
  2320.     lval[2]=0;
  2321.     }
  2322.   else if(lval2[2]) {
  2323.     lval[0]=lval2[0];
  2324.     lval[1]=lval2[1];
  2325.     lval[2]=lval2[2];
  2326.     }
  2327.   }
  2328.  
  2329. step(oper, lval) int (*oper)(), lval[]; {
  2330.   if(lval[1]) {
  2331.     if(lval[5]) {
  2332.       push();
  2333.       rvalue(lval);
  2334.       (*oper)(lval[2]>>2);
  2335.       pop();
  2336.       store(lval);
  2337.       return;
  2338.       }
  2339.     else {
  2340.       move();
  2341.       lval[5]=1;
  2342.       }
  2343.     }
  2344.   rvalue(lval);
  2345.   (*oper)(lval[2]>>2);
  2346.   store(lval);
  2347.   }
  2348.  
  2349. store(lval)  int lval[]; {
  2350.   if(lval[1]) putstk(lval);
  2351.   else        putmem(lval);
  2352.   }
  2353.  
  2354. rvalue(lval) int lval[]; {
  2355.   if ((lval[0]!=0)&(lval[1]==0)) getmem(lval);
  2356.   else                         indirect(lval);
  2357.   }
  2358.  
  2359. test(label, parens)  int label, parens;  {
  2360.   int lval[8];
  2361.   char *before, *start;
  2362.   if(parens) needtoken("(");
  2363.   while(1) {
  2364.     setstage(&before, &start);
  2365.     if(hier1(lval)) rvalue(lval);
  2366.     if(match(",")) clearstage(before, start);
  2367.     else break;
  2368.     }
  2369.   if(parens) needtoken(")");
  2370.   if(lval[3]) {            /* constant expression */
  2371.     clearstage(before, 0);
  2372.     if(lval[4]) return;
  2373.     jump(label);
  2374.     return;
  2375.     }
  2376.   if(lval[7]) {            /* stage address of "oper 0" code */
  2377.     oper=lval[6];        /* operator function address */
  2378.          if((oper==ffeq)|
  2379.             (oper==ule)) zerojump(eq0, label, lval);
  2380.     else if((oper==ffne)|
  2381.             (oper==ugt)) zerojump(ne0, label, lval);
  2382.     else if (oper==ffgt) zerojump(gt0, label, lval);
  2383.     else if (oper==ffge) zerojump(ge0, label, lval);
  2384.     else if (oper==uge)  clearstage(lval[7],0);
  2385.     else if (oper==fflt) zerojump(lt0, label, lval);
  2386.     else if (oper==ult)  zerojump(ult0, label, lval);
  2387.     else if (oper==ffle) zerojump(le0, label, lval);
  2388.     else                 testjump(label);
  2389.     }
  2390.   else testjump(label);
  2391.   clearstage(before, start);
  2392.   }
  2393.  
  2394. constexpr(val) int *val; {
  2395.   int const;
  2396.   char *before, *start;
  2397.   setstage(&before, &start);
  2398.   expression(&const, val);
  2399.   clearstage(before, 0);    /* scratch generated code */
  2400.   if(const==0) error("must be constant expression");
  2401.   return const;
  2402.   }
  2403.  
  2404. const(val) int val; {
  2405.   immed();
  2406.   outdec(val);
  2407.   nl();
  2408.   }
  2409.  
  2410. const2(val) int val; {
  2411.   immed2();
  2412.   outdec(val);
  2413.   nl();
  2414.   }
  2415.  
  2416. constant(lval)  int lval[]; {
  2417.   lval=lval+3;
  2418.   *lval=1;            /* assume it will be a constant */
  2419.   if (number(++lval)) immed();
  2420.   else if (pstr(lval)) immed();
  2421.   else if (qstr(lval)) {
  2422.     *(lval-1)=0;        /* nope, it's a string address */
  2423.     immed();
  2424.     printlabel(litlab);
  2425.     outbyte('+');
  2426.     }
  2427.   else return 0;
  2428.   outdec(*lval);
  2429.   nl();
  2430.   return 1;
  2431.   }
  2432.  
  2433. number(val)  int val[]; {
  2434.   int k, minus;
  2435.   k=minus=0;
  2436.   while(1) {
  2437.     if(match("+")) ;
  2438.     else if(match("-")) minus=1;
  2439.     else break;
  2440.     }
  2441.   if(isdigit(ch)==0)return 0;
  2442.   while (isdigit(ch)) k=k*10+(inbyte()-'0');
  2443.   if (minus) k=(-k);
  2444.   val[0]=k;
  2445.   return 1;
  2446.   }
  2447.  
  2448. address(ptr) char *ptr; {
  2449.   immed();
  2450.   outstr(ptr+NAME);
  2451.   nl();
  2452.   }
  2453.  
  2454. pstr(val)  int val[]; {
  2455.   int k;
  2456.   k=0;
  2457.   if (match("'")==0) return 0;
  2458.   while(ch!=39)    k=(k&255)*256 + (litchar()&255);
  2459.   gch();
  2460.   val[0]=k;
  2461.   return 1;
  2462.   }
  2463.  
  2464. qstr(val)  int val[]; {
  2465.   char c;
  2466.   if (match(quote)==0) return 0;
  2467.   val[0]=litptr;
  2468.   while (ch!='"') {
  2469.     if(ch==0) break;
  2470.     stowlit(litchar(), 1);
  2471.     }
  2472.   gch();
  2473.   litq[litptr++]=0;
  2474.   return 1;
  2475.   }
  2476.  
  2477. stowlit(value, size) int value, size; {
  2478.   if((litptr+size) >= LITMAX) {
  2479.     error("literal queue overflow"); abort(ERRCODE);
  2480.     }
  2481.   putint(value, litq+litptr, size);
  2482.   litptr=litptr+size;
  2483.   }
  2484.  
  2485. /*
  2486. ** return current literal char & bump lptr
  2487. */
  2488. litchar() {
  2489.   int i, oct;
  2490.   if((ch!=92)|(nch==0)) return gch();
  2491.   gch();
  2492.   if(ch=='n') {gch(); return NEWLINE;}
  2493.   if(ch=='t') {gch(); return  9;} /* HT */
  2494.   if(ch=='b') {gch(); return  8;} /* BS */
  2495.   if(ch=='f') {gch(); return 12;} /* FF */
  2496.   i=3; oct=0;
  2497.   while(((i--)>0)&(ch>='0')&(ch<='7')) oct=(oct<<3)+gch()-'0';
  2498.   if(i==2) return gch(); else return oct;
  2499.   }
  2500.  
  2501. >>> CC4.C 244
  2502. /*
  2503. ** Small-C Compiler Part 4
  2504. */
  2505. #include <stdio.h>
  2506. #include "cc.def"
  2507.  
  2508. extern char
  2509.  *macn,
  2510.  *cptr, *symtab,
  2511. #ifdef OPTIMIZE
  2512.  optimize,
  2513. #endif
  2514.  *stagenext, ssname[NAMESIZE];
  2515. extern int
  2516.  beglab,  csp, output;
  2517.  
  2518. #include "cc41.c"
  2519. #include "cc42.c"
  2520. >>> CC41.C 5196
  2521. /*
  2522. ** print all assembler info before any code is generated
  2523. */
  2524. header()  {
  2525.   beglab=getlabel();
  2526.   }
  2527.  
  2528. /*
  2529. ** print any assembler stuff needed at the end
  2530. */
  2531. trailer()  {  
  2532. #ifndef LINK
  2533.   if((beglab == 1)|(beglab > 9000)) {
  2534.     /* implementation dependent trailer code goes here */
  2535.     }
  2536. #else
  2537.   char *ptr;
  2538.   cptr=STARTGLB;
  2539.   while(cptr<ENDGLB) {
  2540.     if(cptr[IDENT]==FUNCTION && cptr[CLASS]==AUTOEXT)
  2541.       external(cptr+NAME);
  2542.     cptr+=SYMMAX;
  2543.     }
  2544. #ifdef UPPER
  2545.   if((ptr=findglb("MAIN")) && (ptr[OFFSET]==FUNCTION))
  2546. #else
  2547.   if((ptr=findglb("main")) && (ptr[OFFSET]==FUNCTION))
  2548. #endif
  2549.     external("Ulink");    /* link to library functions */
  2550. #endif
  2551.   ol("END");
  2552.   }
  2553.  
  2554. /*
  2555. ** load # args before function call
  2556. */
  2557. loadargc(val) int val; {
  2558.   if(search("NOCCARGC", macn, NAMESIZE+2, MACNEND, MACNBR, 0)==0) {
  2559.     if(val) {
  2560.       ot("MVI A,");
  2561.       outdec(val);
  2562.       nl();
  2563.       }
  2564.     else ol("XRA A");
  2565.     }
  2566.   }
  2567.  
  2568. /*
  2569. ** declare entry point
  2570. */
  2571. entry() {
  2572.   outstr(ssname);
  2573.   col();
  2574. #ifdef LINK
  2575.   col();
  2576. #endif
  2577.   nl();
  2578.   }
  2579.  
  2580. /*
  2581. ** declare external reference
  2582. */
  2583. external(name) char *name; {
  2584. #ifdef LINK
  2585.   ot("EXT ");
  2586.   ol(name);
  2587. #endif
  2588.   }
  2589.  
  2590. /*
  2591. ** fetch object indirect to primary register
  2592. */
  2593. indirect(lval) int lval[]; {
  2594.   if(lval[1]==CCHAR) ffcall("CCGCHAR##");
  2595.   else               ffcall("CCGINT##");
  2596.   }
  2597.  
  2598. /*
  2599. ** fetch a static memory cell into primary register
  2600. */
  2601. getmem(lval)  int lval[]; {
  2602.   char *sym;
  2603.   sym=lval[0];
  2604.   if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) {
  2605.     ot("LDA ");
  2606.     outstr(sym+NAME);
  2607.     nl();
  2608.     ffcall("CCSXT##");
  2609.     }
  2610.   else {
  2611.     ot("LHLD ");
  2612.     outstr(sym+NAME);
  2613.     nl();
  2614.     }
  2615.   }
  2616.  
  2617. /*
  2618. ** fetch addr of the specified symbol into primary register
  2619. */
  2620. getloc(sym)  char *sym; {
  2621.   const(getint(sym+OFFSET, OFFSIZE)-csp);
  2622.   ol("DAD SP");
  2623.   }
  2624.  
  2625. /*
  2626. ** store primary register into static cell
  2627. */
  2628. putmem(lval)  int lval[]; {
  2629.   char *sym;
  2630.   sym=lval[0];
  2631.   if((sym[IDENT]!=POINTER)&(sym[TYPE]==CCHAR)) {
  2632.     ol("MOV A,L");
  2633.     ot("STA ");
  2634.     }
  2635.   else ot("SHLD ");
  2636.   outstr(sym+NAME);
  2637.   nl();
  2638.   }
  2639.  
  2640. /*
  2641. ** put on the stack the type object in primary register
  2642. */
  2643. putstk(lval) int lval[]; {
  2644.   if(lval[1]==CCHAR) {
  2645.     ol("MOV A,L");
  2646.     ol("STAX D");
  2647.     }
  2648.   else ffcall("CCPINT##");
  2649.   }
  2650.  
  2651. /*
  2652. ** move primary register to secondary
  2653. */
  2654. move() {
  2655.   ol("MOV D,H");
  2656.   ol("MOV E,L");
  2657.   }
  2658.  
  2659. /*
  2660. ** swap primary and secondary registers
  2661. */
  2662. swap() {
  2663.   ol("XCHG;;");        /* peephole() uses trailing ";;" */
  2664.   }
  2665.  
  2666. /*
  2667. ** partial instruction to get immediate value
  2668. ** into the primary register
  2669. */
  2670. immed() {
  2671.   ot("LXI H,");
  2672.   }
  2673.  
  2674. /*
  2675. ** partial instruction to get immediate operand
  2676. ** into secondary register
  2677. */
  2678. immed2() {
  2679.   ot("LXI D,");
  2680.   }
  2681.  
  2682. /*
  2683. ** push primary register onto stack
  2684. */
  2685. push() {
  2686.   ol("PUSH H");
  2687.   csp=csp-BPW;
  2688.   }
  2689.  
  2690. /*
  2691. ** unpush or pop as required
  2692. */
  2693. smartpop(lval, start) int lval[]; char *start; {
  2694.   if(lval[5])  pop();        /* secondary was used */
  2695.   else unpush(start);
  2696.   }
  2697.  
  2698. /*
  2699. ** replace a push with a swap
  2700. */
  2701. unpush(dest) char *dest; {
  2702.   int i;
  2703.   char *sour;
  2704.   sour="XCHG;;";        /* peephole() uses trailing ";;" */
  2705.   while(*sour) *dest++ = *sour++;
  2706.   sour=stagenext;
  2707.   while(--sour > dest) {    /* adjust stack references */
  2708.     if(streq(sour,"DAD SP")) {
  2709.       --sour;
  2710.       i=BPW;
  2711.       while(isdigit(*(--sour))) {
  2712.         if((*sour = *sour-i) < '0') {
  2713.           *sour = *sour+10;
  2714.           i=1;
  2715.           }
  2716.         else i=0;
  2717.         }
  2718.       }
  2719.     }
  2720.   csp=csp+BPW;
  2721.   }
  2722.  
  2723. /*
  2724. ** pop stack to the secondary register
  2725. */
  2726. pop() {
  2727.   ol("POP D");
  2728.   csp=csp+BPW;
  2729.   }
  2730.  
  2731. /*
  2732. ** swap primary register and stack
  2733. */
  2734. swapstk() {
  2735.   ol("XTHL");
  2736.   }
  2737.  
  2738. /*
  2739. ** process switch statement
  2740. */
  2741. sw() {
  2742.   ffcall("CCSWITCH##");
  2743.   }
  2744.  
  2745. /*
  2746. ** call specified subroutine name
  2747. */
  2748. ffcall(sname)  char *sname; {
  2749.   ot("CALL ");
  2750.   outstr(sname);
  2751.   nl();
  2752.   }
  2753.  
  2754. /*
  2755. ** return from subroutine
  2756. */
  2757. ffret() {
  2758.   ol("RET");
  2759.   }
  2760.  
  2761. /*
  2762. ** perform subroutine call to value on stack
  2763. */
  2764. callstk() {
  2765.   ffcall("CCDCAL##");
  2766.   }
  2767.  
  2768. /*
  2769. ** jump to internal label number
  2770. */
  2771. jump(label)  int label; {
  2772.   ot("JMP ");
  2773.   printlabel(label);
  2774.   nl();
  2775.   }
  2776.  
  2777. /*
  2778. ** test primary register and jump if false
  2779. */
  2780. testjump(label)  int label; {
  2781.   ol("MOV A,H");
  2782.   ol("ORA L");
  2783.   ot("JZ ");
  2784.   printlabel(label);
  2785.   nl();
  2786.   }
  2787.  
  2788. /*
  2789. ** test primary register against zero and jump if false
  2790. */
  2791. zerojump(oper, label, lval) int (*oper)(), label, lval[]; {
  2792.   clearstage(lval[7], 0);    /* purge conventional code */
  2793.   (*oper)(label);
  2794.   }
  2795.  
  2796. /*
  2797. ** define storage according to size
  2798. */
  2799. defstorage(size) int size; {
  2800.   if(size==1) ot("DB ");
  2801.   else        ot("DW ");
  2802.   }
  2803.  
  2804. /*
  2805. ** point to following object(s)
  2806. */
  2807. point() {
  2808.   ol("DW $+2");
  2809.   }
  2810.  
  2811. /*
  2812. ** modify stack pointer to value given
  2813. */
  2814. modstk(newsp, save)  int newsp, save; {
  2815.   int k;
  2816.   k=newsp-csp;
  2817.   if(k==0)return newsp;
  2818.   if(k>=0) {
  2819.     if(k<7) {
  2820.       if(k&1) {
  2821.         ol("INX SP");
  2822.         k--;
  2823.         }
  2824.       while(k) {
  2825.         ol("POP B");
  2826.         k=k-BPW;
  2827.         }
  2828.       return newsp;
  2829.       }
  2830.     }
  2831.   if(k<0) {
  2832.     if(k>-7) {
  2833.       if(k&1) {
  2834.         ol("DCX SP");
  2835.         k++;
  2836.         }
  2837.       while(k) {
  2838.         ol("PUSH B");
  2839.         k=k+BPW;
  2840.         }
  2841.       return newsp;
  2842.       }
  2843.     }
  2844.   if(save) swap();
  2845.   const(k);
  2846.   ol("DAD SP");
  2847.   ol("SPHL");
  2848.   if(save) swap();
  2849.   return newsp;
  2850.   }
  2851.  
  2852. /*
  2853. ** double primary register
  2854. */
  2855. doublereg() {ol("DAD H");}
  2856.  
  2857. >>> CC42.C 5615
  2858. /*
  2859. ** add primary and secondary registers (result in primary)
  2860. */
  2861. ffadd() {ol("DAD D");}
  2862.  
  2863. /*
  2864. ** subtract primary from secondary register (result in primary)
  2865. */
  2866. ffsub() {ffcall("CCSUB##");}
  2867.  
  2868. /*
  2869. ** multiply primary and secondary registers (result in primary)
  2870. */
  2871. ffmult() {ffcall("CCMULT##");}
  2872.  
  2873. /*
  2874. ** divide secondary by primary register
  2875. ** (quotient in primary, remainder in secondary)
  2876. */
  2877. ffdiv() {ffcall("CCDIV##");}
  2878.  
  2879. /*
  2880. ** remainder of secondary/primary
  2881. ** (remainder in primary, quotient in secondary)
  2882. */
  2883. ffmod() {ffdiv();swap();}
  2884.  
  2885. /*
  2886. ** inclusive "or" primary and secondary registers
  2887. ** (result in primary)
  2888. */
  2889. ffor() {ffcall("CCOR##");}
  2890.  
  2891. /*
  2892. ** exclusive "or" the primary and secondary registers
  2893. ** (result in primary)
  2894. */
  2895. ffxor() {ffcall("CCXOR##");}
  2896.  
  2897. /*
  2898. ** "and" primary and secondary registers
  2899. ** (result in primary)
  2900. */
  2901. ffand() {ffcall("CCAND##");}
  2902.  
  2903. /*
  2904. ** logical negation of primary register
  2905. */
  2906. lneg() {ffcall("CCLNEG##");}
  2907.  
  2908. /*
  2909. ** arithmetic shift right secondary register
  2910. ** number of bits given in primary register
  2911. ** (result in primary)
  2912. */
  2913. ffasr() {ffcall("CCASR##");}
  2914.  
  2915. /*
  2916. ** arithmetic shift left secondary register
  2917. ** number of bits given in primary register
  2918. ** (result in primary)
  2919. */
  2920. ffasl() {ffcall("CCASL##");}
  2921.  
  2922. /*
  2923. ** two's complement primary register
  2924. */
  2925. neg() {ffcall("CCNEG##");}
  2926.  
  2927. /*
  2928. ** one's complement primary register
  2929. */
  2930. com() {ffcall("CCCOM##");}
  2931.  
  2932. /*
  2933. ** increment primary register by one object of whatever size
  2934. */
  2935. inc(n) int n; {
  2936.   while(1) {
  2937.     ol("INX H");
  2938.     if(--n < 1) break;
  2939.     }
  2940.   }
  2941.  
  2942. /*
  2943. ** decrement primary register by one object of whatever size
  2944. */
  2945. dec(n) int n; {
  2946.   while(1) {
  2947.     ol("DCX H");
  2948.     if(--n < 1) break;
  2949.     }
  2950.   }
  2951.  
  2952. /*
  2953. ** test for equal to
  2954. */
  2955. ffeq()  {ffcall("CCEQ##");}
  2956.  
  2957. /*
  2958. ** test for equal to zero
  2959. */
  2960. eq0(label) int label; {
  2961.   ol("MOV A,H");
  2962.   ol("ORA L");
  2963.   ot("JNZ ");
  2964.   printlabel(label);
  2965.   nl();
  2966.   }
  2967.  
  2968. /*
  2969. ** test for not equal to
  2970. */
  2971. ffne()  {ffcall("CCNE##");}
  2972.  
  2973. /*
  2974. ** test for not equal to zero
  2975. */
  2976. ne0(label) int label; {
  2977.   ol("MOV A,H");
  2978.   ol("ORA L");
  2979.   ot("JZ ");
  2980.   printlabel(label);
  2981.   nl();
  2982.   }
  2983.  
  2984. /*
  2985. ** test for less than (signed)
  2986. */
  2987. fflt()  {ffcall("CCLT##");}
  2988.  
  2989. /*
  2990. ** test for less than to zero
  2991. */
  2992. lt0(label) int label; {
  2993.   ol("XRA A");
  2994.   ol("ORA H");
  2995.   ot("JP ");
  2996.   printlabel(label);
  2997.   nl();
  2998.   }
  2999.  
  3000. /*
  3001. ** test for less than or equal to (signed)
  3002. */
  3003. ffle()  {ffcall("CCLE##");}
  3004.  
  3005. /*
  3006. ** test for less than or equal to zero
  3007. */
  3008. le0(label) int label; {
  3009.   ol("MOV A,H");
  3010.   ol("ORA L");
  3011.   ol("JZ $+8");
  3012.   ol("XRA A");
  3013.   ol("ORA H");
  3014.   ot("JP ");
  3015.   printlabel(label);
  3016.   nl();
  3017.   }
  3018.  
  3019. /*
  3020. ** test for greater than (signed)
  3021. */
  3022. ffgt()  {ffcall("CCGT##");}
  3023.  
  3024. /*
  3025. ** test for greater than to zero
  3026. */
  3027. gt0(label) int label; {
  3028.   ol("XRA A");
  3029.   ol("ORA H");
  3030.   ot("JM ");
  3031.   printlabel(label);
  3032.   nl();
  3033.   ol("ORA L");
  3034.   ot("JZ ");
  3035.   printlabel(label);
  3036.   nl();
  3037.   }
  3038.  
  3039. /*
  3040. ** test for greater than or equal to (signed)
  3041. */
  3042. ffge()  {ffcall("CCGE##");}
  3043.  
  3044. /*
  3045. ** test for gteater than or equal to zero
  3046. */
  3047. ge0(label) int label; {
  3048.   ol("XRA A");
  3049.   ol("ORA H");
  3050.   ot("JM ");
  3051.   printlabel(label);
  3052.   nl();
  3053.   }
  3054.  
  3055. /*
  3056. ** test for less than (unsigned)
  3057. */
  3058. ult()  {ffcall("CCULT##");}
  3059.  
  3060. /*
  3061. ** test for less than to zero (unsigned)
  3062. */
  3063. ult0(label) int label; {
  3064.   ot("JMP ");
  3065.   printlabel(label);
  3066.   nl();
  3067.   }
  3068.  
  3069. /*
  3070. ** test for less than or equal to (unsigned)
  3071. */
  3072. ule()  {ffcall("CCULE##");}
  3073.  
  3074. /*
  3075. ** test for greater than (unsigned)
  3076. */
  3077. ugt()  {ffcall("CCUGT##");}
  3078.  
  3079. /*
  3080. ** test for greater than or equal to (unsigned)
  3081. */
  3082. uge()  {ffcall("CCUGE##");}
  3083.  
  3084. #ifdef OPTIMIZE
  3085. peephole(ptr) char *ptr; {
  3086.   while(*ptr) {
  3087.     if(streq(ptr,"LXI H,0\nDAD SP\nCALL CCGINT##")) {
  3088.       if(streq(ptr+29, "XCHG;;")) {pp2();ptr=ptr+36;}
  3089.       else                        {pp1();ptr=ptr+29;}
  3090.       }
  3091.     else if(streq(ptr,"LXI H,2\nDAD SP\nCALL CCGINT##")) {
  3092.       if(streq(ptr+29, "XCHG;;")) {pp3(pp2);ptr=ptr+36;}
  3093.       else                        {pp3(pp1);ptr=ptr+29;}
  3094.       }
  3095.     else if(optimize) {
  3096.       if(streq(ptr, "DAD SP\nCALL CCGINT##")) {
  3097.         ol("CALL CCDSGI##");
  3098.         ptr=ptr+21;
  3099.         }
  3100.       else if(streq(ptr, "DAD D\nCALL CCGINT##")) {
  3101.         ol("CALL CCDDGI##");
  3102.         ptr=ptr+20;
  3103.         }
  3104.       else if(streq(ptr, "DAD SP\nCALL CCGCHAR##")) {
  3105.         ol("CALL CCDSGC##");
  3106.         ptr=ptr+22;
  3107.           }
  3108.       else if(streq(ptr, "DAD D\nCALL CCGCHAR##")) {
  3109.         ol("CALL CCDDGC##");
  3110.         ptr=ptr+21;
  3111.         }
  3112.       else if(streq(ptr,
  3113.         "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGINT##\nINX H\nCALL CCPINT##")) {
  3114.         ol("CALL CCINCI##");
  3115.         ptr=ptr+57;
  3116.         }
  3117.       else if(streq(ptr,
  3118.         "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGINT##\nDCX H\nCALL CCPINT##")) {
  3119.         ol("CALL CCDECI##");
  3120.         ptr=ptr+57;
  3121.         }
  3122.       else if(streq(ptr,
  3123.         "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGCHAR##\nINX H\nMOV A,L\nSTAX D")) {
  3124.         ol("CALL CCINCC##");
  3125.         ptr=ptr+59;
  3126.         }
  3127.       else if(streq(ptr,
  3128.         "DAD SP\nMOV D,H\nMOV E,L\nCALL CCGCHAR##\nDCX H\nMOV A,L\nSTAX D")) {
  3129.         ol("CALL CCDECC##");
  3130.         ptr=ptr+59;
  3131.         }
  3132.       else if(streq(ptr, "DAD D\nPOP D\nCALL CCPINT##")) {
  3133.         ol("CALL CDPDPI##");
  3134.         ptr=ptr+26;
  3135.         }
  3136.       else if(streq(ptr, "DAD D\nPOP D\nMOV A,L\nSTAX D")) {
  3137.         ol("CALL CDPDPC##");
  3138.         ptr=ptr+27;
  3139.         }
  3140.       else if(streq(ptr, "POP D\nCALL CCPINT##")) {
  3141.         ol("CALL CCPDPI##");
  3142.         ptr=ptr+20;
  3143.         }
  3144.       /* additional optimizing logic goes here */
  3145.       else cout(*ptr++, output);
  3146.       }
  3147.     else cout(*ptr++, output);
  3148.     }
  3149.   }
  3150.  
  3151. pp1() {
  3152.   ol("POP H");
  3153.   ol("PUSH H");
  3154.   }
  3155.  
  3156. pp2() {
  3157.   ol("POP D");
  3158.   ol("PUSH D");
  3159.   }
  3160.  
  3161. pp3(pp) int (*pp)(); {
  3162.   ol("POP B");
  3163.   (*pp)();
  3164.   ol("PUSH B");
  3165.   }
  3166. #endif
  3167.