home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 170_01 / cpcn.c < prev    next >
Text File  |  1979-12-31  |  49KB  |  2,503 lines

  1. /* ### cpcn-1 */
  2. /************************************************/
  3. /*                        */
  4. /*        small-c:PC compiler        */
  5. /*                        */
  6. /*          by Ron Cain            */
  7. /*    modified by CAPROCK SYSTEMS for IBM PC    */
  8. /*                        */
  9. /************************************************/
  10.  
  11.  
  12. #define BANNER  "* * *  Small-C:PC  V1.1  * * *"
  13.  
  14.  
  15. #define VERSION "PC-DOS Version N: June, 1982"
  16.  
  17.  
  18. #define AUTHOR "By Ron Cain, Modified by CAPROCK SYSTEMS for IBM PC"
  19.  
  20.  
  21. /*    Define system dependent parameters    */
  22.  
  23.  
  24. /*    Stand-alone definitions            */
  25.  
  26.  
  27. #define NULL 0
  28. #define eol 13
  29.  
  30.  
  31. /*    UNIX definitions (if not stand-alone)    */
  32.  
  33.  
  34. /* #include <stdio.h>    */
  35. /* #define eol 10    */
  36.  
  37.  
  38. /*    Define the symbol table parameters    */
  39.  
  40.  
  41. #define    symsiz    14
  42. #define    symtbsz    5040
  43. #define numglbs 300
  44. #define    startglb symtab
  45. #define    endglb    startglb+numglbs*symsiz
  46. #define    startloc endglb+symsiz
  47. #define    endloc    symtab+symtbsz-symsiz
  48.  
  49.  
  50. /*    Define symbol table entry format    */
  51.  
  52.  
  53. #define    name    0
  54. #define    ident    9
  55. #define    type    10
  56. #define    storage    11
  57. #define    offset    12
  58.  
  59.  
  60. /*    System wide name size (for symbols)    */
  61.  
  62.  
  63. #define    namesize 9
  64. #define namemax  8
  65.  
  66.  
  67. /*    Define data for external symbols    */
  68.  
  69. #define extblsz 2000
  70. #define startextrn exttab
  71. #define endextrn exttab+extblsz-namesize-1
  72.  
  73. /* Possible types of exttab entries */
  74. /* Stored in the byte following zero terminating the name */
  75.  
  76. #define rtsfunc 1
  77. #define userfunc 2
  78. #define statref 3
  79.  
  80.  
  81. /*    Define possible entries for "ident"    */
  82.  
  83.  
  84. #define    variable 1
  85. #define    array    2
  86. #define    pointer    3
  87. #define    function 4
  88.  
  89.  
  90. /*    Define possible entries for "type"    */
  91.  
  92.  
  93. #define    cchar    1
  94. #define    cint    2
  95.  
  96.  
  97. /*    Define possible entries for "storage"    */
  98.  
  99.  
  100. #define    statik    1
  101. #define    stkloc    2
  102.  
  103.  
  104. /*    Define the "while" statement queue    */
  105.  
  106.  
  107. #define    wqtabsz    100
  108. #define    wqsiz    4
  109. #define    wqmax    wq+wqtabsz-wqsiz
  110.  
  111.  
  112. /*    Define entry offsets in while queue    */
  113.  
  114.  
  115. #define    wqsym    0
  116. #define    wqsp    1
  117. #define    wqloop    2
  118. #define    wqlab    3
  119.  
  120.  
  121. /*    Define the literal pool            */
  122.  
  123.  
  124. #define    litabsz    3000
  125. #define    litmax    litabsz-1
  126.  
  127.  
  128. /*    Define the input line            */
  129.  
  130.  
  131. #define    linesize 80
  132. #define    linemax    linesize-1
  133. #define    mpmax    linemax
  134.  
  135.  
  136. /*    Define the macro (define) pool        */
  137.  
  138.  
  139. #define    macqsize 1000
  140. #define    macmax    macqsize-1
  141.  
  142.  
  143. /*    Define statement types (tokens)        */
  144.  
  145.  
  146. #define    stif    1
  147. #define    stwhile    2
  148. #define    streturn 3
  149. #define    stbreak    4
  150. #define    stcont    5
  151. #define    stasm    6
  152. #define    stexp    7
  153.  
  154.  
  155. /* Define how to carve up a name too long for the assembler */
  156.  
  157.  
  158. #define asmpref    7
  159. #define asmsuff    7
  160.  
  161.  
  162. /*    Now reserve some storage words        */
  163.  
  164.  
  165. char    exttab[extblsz];    /* external symbols */
  166. char    *extptr;        /* pointer to next available entry */
  167.  
  168.  
  169. char    symtab[symtbsz];    /* symbol table */
  170. char    *glbptr,*locptr;        /* ptrs to next entries */
  171.  
  172.  
  173. int    wq[wqtabsz];        /* while queue */
  174. int    *wqptr;            /* ptr to next entry */
  175.  
  176.  
  177. char    litq[litabsz];        /* literal pool */
  178. int    litptr;            /* ptr to next entry */
  179.  
  180.  
  181. char    macq[macqsize];        /* macro string buffer */
  182. int    macptr;            /* and its index */
  183.  
  184.  
  185. char    line[linesize];        /* parsing buffer */
  186. char    mline[linesize];    /* temp macro buffer */
  187. int    lptr,mptr;        /* ptrs into each */
  188.  
  189.  
  190. /*    Misc storage    */
  191.  
  192.  
  193. int    nxtlab,        /* next avail label # */
  194.     litlab,        /* label # assigned to literal pool */
  195.     cextern,    /* collecting external names flag */
  196.     Zsp,        /* compiler relative stk ptr */
  197.     argstk,        /* function arg sp */
  198.     ncmp,        /* # open compound statements */
  199.     errcnt,        /* # errors in compilation */
  200.     errstop,    /* stop on error            gtf 7/17/80 */
  201.     eof,        /* set non-zero on final input eof */
  202.     input,        /* iob # for input file */
  203.     output,        /* iob # for output file (if any) */
  204.     input2,        /* iob # for "include" file */
  205.     ctext,        /* non-zero to intermix c-source */
  206.     cmode,        /* non-zero while parsing c-code */
  207.             /* zero when passing assembly code */
  208.     lastst,        /* last executed statement type */
  209.     saveout,    /* holds output ptr when diverted to console       */
  210.             /*                    gtf 7/16/80 */
  211.     fnstart,    /* line# of start of current fn.    gtf 7/2/80 */
  212.     lineno,        /* line# in current file        gtf 7/2/80 */
  213.     infunc,        /* "inside function" flag        gtf 7/2/80 */
  214.     savestart,    /* copy of fnstart "    "        gtf 7/16/80 */
  215.     saveline,    /* copy of lineno  "    "        gtf 7/16/80 */
  216.     saveinfn;    /* copy of infunc  "    "        gtf 7/16/80 */
  217.  
  218.  
  219. char   *currfn,        /* ptr to symtab entry for current fn.    gtf 7/17/80 */
  220.        *savecurr;    /* copy of currfn for #include        gtf 7/17/80 */
  221. char    quote[2];    /* literal string for '"' */
  222. char    *cptr;        /* work ptr to any char buffer */
  223. int    *iptr;        /* work ptr to any int buffer */
  224. /*    >>>>> start cc1 <<<<<<        */
  225.  
  226.  
  227. /*                    */
  228. /*    Compiler begins execution here    */
  229. /*                    */
  230. main()
  231. {
  232.     hello();    /* greet user */
  233.     see();        /* determine options */
  234.     litlab=1;
  235.     openin();    /* first file to process */
  236.     while (input!=0)    /* process user files till he quits */
  237.         {
  238.         extptr=startextrn;    /* clear external symbols */
  239.         glbptr=startglb;    /* clear global symbols */
  240.         locptr=startloc;    /* clear local symbols */
  241.         wqptr=wq;        /* clear while queue */
  242.         macptr=        /* clear the macro pool */
  243.         litptr=        /* clear literal pool */
  244.           Zsp =        /* stack ptr (relative) */
  245.         errcnt=        /* no errors */
  246.         eof=        /* not end-of-file yet */
  247.         input2=        /* no include file */
  248.         saveout=    /* no diverted output */
  249.         ncmp=        /* no open compound states */
  250.         lastst=        /* no last statement yet */
  251.         cextern=    /* no externs yet */
  252.         fnstart=    /* current "function" started at line 0 gtf 7/2/80 */
  253.         lineno=        /* no lines read from file        gtf 7/2/80 */
  254.         infunc=        /* not in function now            gtf 7/2/80 */
  255.         quote[1]=
  256.         0;        /*  ...all set to zero.... */
  257.         quote[0]='"';        /* fake a quote literal */
  258.         currfn=NULL;    /* no function yet            gtf 7/2/80 */
  259.         cmode=nxtlab=1;    /* enable preprocessing and reset label numbers */
  260.         openout();
  261.         header();
  262.         parse();
  263.         if (ncmp) error("missing closing bracket");
  264.         extdump();
  265.         dumpublics();
  266.         trailer();
  267.         closeout();
  268.         errorsummary();
  269.         openin();
  270.         }
  271. }
  272. /* ### cpcn-2 */
  273. /*                    */
  274. /*    Abort compilation        */
  275. /*        gtf 7/17/80        */
  276. abort()
  277. {
  278.     if(input2)
  279.         endinclude();
  280.     if(input)
  281.         fclose(input);
  282.     closeout();
  283.     toconsole();
  284.     pl("Compilation aborted.");  nl();
  285.     exit();
  286. /* end abort */}
  287.  
  288.  
  289. /*                    */
  290. /*    Process all input text        */
  291. /*                    */
  292. /* At this level, only static declarations, */
  293. /*    defines, includes, and function */
  294. /*    definitions are legal...    */
  295. parse()
  296.     {
  297.     while (eof==0)        /* do until no more input */
  298.         {
  299.         if(amatch("extern",6)) {
  300.             cextern=1;
  301.             if(amatch("char",4)) {declglb(cchar);ns();}
  302.             else if(amatch("int",3)) {declglb(cint);ns();}
  303.             else {declglb(cint);ns();}
  304.             cextern=0;
  305.             }
  306.         else if(amatch("char",4)){declglb(cchar);ns();}
  307.         else if(amatch("int",3)){declglb(cint);ns();}
  308.         else if(match("#asm"))doasm();
  309.         else if(match("#include"))doinclude();
  310.         else if(match("#define"))addmac();
  311.         else newfunc();
  312.         blanks();    /* force eof if pending */
  313.         }
  314.     }
  315. /* ### cpcn-3 */
  316. dumpublics()
  317.     {
  318.     outstr("DUMMY SEGMENT BYTE STACK 'dummy'");nl();
  319.     outstr("DUMMY ENDS");nl();
  320.     outstr("STACK SEGMENT BYTE PUBLIC 'stack'");nl();
  321.     dumplits();
  322.     dumpglbs();
  323.     outstr("STACK ENDS");nl();
  324.     }
  325.  
  326. extdump()
  327.     {
  328.     char *ptrext;
  329.     ptrext=startextrn;
  330.     while(ptrext<extptr)
  331.         {
  332.         if((cptr=findglb(ptrext))!=0)
  333.             {if(cptr[ident]==function)
  334.                 if(cptr[offset]!=function) outextrn(ptrext);
  335.             }
  336.         else outextrn(ptrext);
  337.         ptrext=ptrext+strlen(ptrext)+2;
  338.         }
  339.     outstr("CSEG ENDS");nl();
  340.     }
  341. /* ### cpcn-4 */
  342. outextrn(ptr)
  343.     char *ptr;
  344.     {
  345.     char *functype;
  346.     functype=ptr+strlen(ptr)+1;
  347.     if(*functype==statref) return;
  348.     ot("EXTRN ");
  349.     if(*functype==rtsfunc) outasm(ptr);
  350.     else outname(ptr);
  351.     col();outstr("NEAR");nl();
  352.     }
  353.  
  354.  
  355. /*                    */
  356. /*    Dump the literal pool        */
  357. /*                    */
  358. dumplits()
  359.     {int j,k;
  360.     if (litptr==0) return;    /* if nothing there, exit...*/
  361.     printlabel(litlab); /* print literal label */
  362.     k=0;            /* init an index... */
  363.     while (k<litptr)    /*     to loop with */
  364.         {defbyte();    /* pseudo-op to define byte */
  365.         j=10;        /* max bytes per line */
  366.         while(j--)
  367.             {outdec((litq[k++]&127));
  368.             if ((j==0) | (k>=litptr))
  369.                 {nl();        /* need <cr> */
  370.                 break;
  371.                 }
  372.             outbyte(',');    /* separate bytes */
  373.             }
  374.         }
  375.     }
  376. /*                    */
  377. /*    Dump all static variables    */
  378. /*                    */
  379. dumpglbs()
  380. {
  381.     int j;
  382.     cptr=startglb;
  383.     while(cptr<glbptr)
  384.         {if(cptr[ident]!=function)
  385.             /* do if anything but function */
  386.             {
  387.             if(findext(cptr+name))
  388.                 {
  389.                 ot("EXTRN ");
  390.                 outname(cptr);col();
  391.                 if((cptr[type]==cint) |
  392.                     (cptr[ident]==pointer)) outstr("WORD");
  393.                 else outstr("BYTE");
  394.                 nl();
  395.                 }
  396.             else {
  397.                 ot("PUBLIC ");outname(cptr);nl();
  398.                 outname(cptr);
  399.                 /* output name as label... */
  400.                 j=((cptr[offset]&255)+
  401.                     ((cptr[offset+1]&255)<<8));
  402.                     /* calc # bytes */
  403.                 if((cptr[type]==cint)|
  404.                     (cptr[ident]==pointer)) defword();
  405.                 else defbyte();
  406.                 outdec(j);
  407.                 outstr(" DUP(?)");
  408.                 nl();
  409.                 }
  410.             }
  411.         cptr=cptr+symsiz;
  412.         }
  413. }
  414. /*                    */
  415. /*    Report errors for user        */
  416. /*                    */
  417. errorsummary()
  418.     {
  419.     nl();
  420.     outstr("There were ");
  421.     outdec(errcnt);    /* total # errors */
  422.     outstr(" errors in compilation.");
  423.     nl();
  424.     }
  425. /* ### cpcn-5 */
  426. /*    Greet User    */
  427.  
  428.  
  429. hello()
  430.     {
  431.     clrscreen();     /* clear screen function */
  432.     nl();nl();        /* print banner */
  433.     pl(BANNER);
  434.     nl();
  435.     pl(AUTHOR);
  436.     nl();nl();
  437.     pl("Distributed by: CAPROCK SYSTEMS, INC.");
  438.     pl("                P.O. Box 13814");
  439.     pl("                Arlington, Texas 76013");
  440.     nl();
  441.     pl(VERSION);
  442.     nl();
  443.     nl();
  444. } /* end of hello */
  445.  
  446.  
  447. see()
  448.     {
  449.     kill();
  450.     /* see if user wants to be sure to see all errors */
  451.     pl("Should I pause after an error (y,N)?");
  452.     gets(line);
  453.     errstop=0;
  454.     if((ch()=='Y')|(ch()=='y'))
  455.         errstop=1;
  456.  
  457.     kill();
  458.     pl("Do you want the small-c:PC-text to appear (y,N)?");
  459.     gets(line);
  460.     ctext=0;
  461.     if((ch()=='Y')|(ch()=='y')) ctext=1;
  462.         }
  463. /*                    */
  464. /*    Get output filename        */
  465. /*                    */
  466. openout()
  467.     {
  468.     output=0;        /* start with none */
  469.     while(output==0)
  470.         {
  471.         kill();
  472.         pl("Output filename? "); /* ask...*/
  473.         gets(line);    /* get a filename */
  474.         if(ch()==0)break;    /* none given... */
  475.         if((output=fopen(line,"w"))==NULL) /* if given, open */
  476.             {output=0;    /* can't open */
  477.             error("Open failure!");
  478.             }
  479.         }
  480.     kill();            /* erase line */
  481. }
  482. /*                    */
  483. /*    Get (next) input file        */
  484. /*                    */
  485. openin()
  486. {
  487.     input=0;        /* none to start with */
  488.     while(input==0){    /* any above 1 allowed */
  489.         kill();        /* clear line */
  490.         pl("Input filename? ");
  491.         gets(line);    /* get a name */
  492.         if(ch()==0) break;
  493.         if((input=fopen(line,"r"))!=NULL)
  494.             newfile();            /* gtf 7/16/80 */
  495.         else {    input=0;    /* can't open it */
  496.             pl("Open failure");
  497.             }
  498.         }
  499.     kill();        /* erase line */
  500.     }
  501.  
  502.  
  503. /*                    */
  504. /*    Reset line count, etc.        */
  505. /*            gtf 7/16/80    */
  506. newfile()
  507. {
  508.     lineno  = 0;    /* no lines read */
  509.     fnstart = 0;    /* no fn. start yet. */
  510.     currfn  = NULL;    /* because no fn. yet */
  511.     infunc  = 0;    /* therefore not in fn. */
  512. /* end newfile */}
  513. /* ### cpcn-6 */
  514.  
  515.  
  516. /*                    */
  517. /*    Open an include file        */
  518. /*                    */
  519. doinclude()
  520. {
  521.     blanks();    /* skip over to name */
  522.  
  523.  
  524.     toconsole();                    /* gtf 7/16/80 */
  525.     outstr("#include "); outstr(line+lptr); nl();
  526.     tofile();
  527.  
  528.  
  529.     if(input2)                    /* gtf 7/16/80 */
  530.         error("Cannot nest include files");
  531.     else if((input2=fopen(line+lptr,"r"))==NULL)
  532.         {input2=0;
  533.         error("Open failure on include file");
  534.         }
  535.     else {    saveline = lineno;
  536.         savecurr = currfn;
  537.         saveinfn = infunc;
  538.         savestart= fnstart;
  539.         newfile();
  540.         }
  541.     kill();        /* clear rest of line */
  542.             /* so next read will come from */
  543.             /* new file (if open */
  544. }
  545.  
  546.  
  547. /*                    */
  548. /*    Close an include file        */
  549. /*            gtf 7/16/80    */
  550. endinclude()
  551. {
  552.     toconsole();
  553.     outstr("#end include"); nl();
  554.     tofile();
  555.  
  556.  
  557.     input2  = 0;
  558.     lineno  = saveline;
  559.     currfn  = savecurr;
  560.     infunc  = saveinfn;
  561.     fnstart = savestart;
  562. /* end endinclude */}
  563.  
  564.  
  565. /*                    */
  566. /*    Close the output file        */
  567. /*                    */
  568. closeout()
  569. {
  570.     tofile();    /* if diverted, return to file */
  571.     if(output)fclose(output); /* if open, close it */
  572.     output=0;        /* mark as closed */
  573. }
  574. /* ### cpcn-7 */
  575. /*                    */
  576. /*    Declare a static variable    */
  577. /*      (i.e. define for use)        */
  578. /*                    */
  579. /* makes an entry in the symbol table so subsequent */
  580. /*  references can call symbol by name    */
  581. declglb(typ)        /* typ is cchar or cint */
  582.     int typ;
  583. {    int k,j;char sname[namesize];
  584.     while(1)
  585.         {while(1)
  586.             {if(endst())return;    /* do line */
  587.             k=1;        /* assume 1 element */
  588.             if(match("*"))    /* pointer ? */
  589.                 j=pointer;    /* yes */
  590.                 else j=variable; /* no */
  591.              if (symname(sname)==0) /* name ok? */
  592.                 illname(); /* no... */
  593.             if(findglb(sname)) /* already there? */
  594.                 multidef(sname);
  595.             if (match("["))        /* array? */
  596.                 {k=needsub();    /* get size */
  597.                 if(k)j=array;    /* !0=array */
  598.                 else j=pointer; /* 0=ptr */
  599.                 }
  600.             addglb(sname,j,typ,k); /* add symbol */
  601.             if(cextern) addext(sname,statref);
  602.             break;
  603.             }
  604.         if (match(",")==0) return; /* more? */
  605.         }
  606.     }
  607. /*                    */
  608. /*    Declare local variables        */
  609. /*    (i.e. define for use)        */
  610. /*                    */
  611. /* works just like "declglb" but modifies machine stack */
  612. /*    and adds symbol table entry with appropriate */
  613. /*    stack offset to find it again            */
  614. declloc(typ)        /* typ is cchar or cint */
  615.     int typ;
  616.     {
  617.     int k,j;char sname[namesize];
  618.     while(1)
  619.         {while(1)
  620.             {if(endst())return;
  621.             if(match("*"))
  622.                 j=pointer;
  623.                 else j=variable;
  624.             if (symname(sname)==0)
  625.                 illname();
  626.             if(findloc(sname))
  627.                 multidef(sname);
  628.             if (match("["))
  629.                 {k=needsub();
  630.                 if(k)
  631.                     {j=array;
  632.                     if(typ==cint)k=k+k;
  633.                     }
  634.                 else
  635.                     {j=pointer;
  636.                     k=2;
  637.                     }
  638.                 }
  639.             else
  640.                 if((typ==cchar)
  641.                     &(j!=pointer))
  642.                     k=1;else k=2;
  643.             /* change machine stack */
  644.             Zsp=modstk(Zsp-k);
  645.             addloc(sname,j,typ,Zsp);
  646.             break;
  647.             }
  648.         if (match(",")==0) return;
  649.         }
  650.     }
  651. /* ### cpcn-8 */
  652. /*    >>>>>> start of cc2 <<<<<<<<    */
  653.  
  654.  
  655. /*                    */
  656. /*    Get required array size        */
  657. /*                    */
  658. /* invoked when declared variable is followed by "[" */
  659. /*    this routine makes subscript the absolute */
  660. /*    size of the array. */
  661. needsub()
  662.     {
  663.     int num[1];
  664.     if(match("]"))return 0;    /* null size */
  665.     if (number(num)==0)    /* go after a number */
  666.         {error("must be constant");    /* it isn't */
  667.         num[0]=1;        /* so force one */
  668.         }
  669.     if (num[0]<0)
  670.         {error("negative size illegal");
  671.         num[0]=(-num[0]);
  672.         }
  673.     needbrack("]");        /* force single dimension */
  674.     return num[0];        /* and return size */
  675.     }
  676. /*                    */
  677. /* ### cpcn-9 */
  678. /*    Begin a function        */
  679. /*                    */
  680. /* Called from "parse" this routine tries to make a function */
  681. /*    out of what follows.    */
  682. newfunc()
  683.     {
  684.     char n[namesize]; /* ptr => currfn,  gtf 7/16/80 */
  685.     if (symname(n)==0)
  686.         {
  687.         if(eof==0) error("illegal function or declaration");
  688.         kill();    /* invalidate line */
  689.         return;
  690.         }
  691.     fnstart=lineno;        /* remember where fn began    gtf 7/2/80 */
  692.     infunc=1;        /* note, in function now.    gtf 7/16/80 */
  693.     if(currfn=findglb(n))    /* already in symbol table ? */
  694.         {if(currfn[ident]!=function)multidef(n);
  695.             /* already variable by that name */
  696.         else if(currfn[offset]==function)multidef(n);
  697.             /* already function by that name */
  698.         else currfn[offset]=function;
  699.             /* otherwise we have what was earlier*/
  700.             /*  assumed to be a function */
  701.         }
  702.     /* if not in table, define as a function now */
  703.     else currfn=addglb(n,function,cint,function);
  704.  
  705.  
  706.     toconsole();                    /* gtf 7/16/80 */
  707.     outstr("====== "); outstr(currfn+name); outstr("()"); nl();
  708.     tofile();
  709.  
  710.  
  711.     /* we had better see open paren for args... */
  712.     if(match("(")==0)error("missing open paren");
  713.     ot("PUBLIC ");outname(n);nl();
  714.     outname(n);col();nl();    /* print function name */
  715.     argstk=0;        /* init arg count */
  716.     while(match(")")==0)    /* then count args */
  717.         /* any legal name bumps arg count */
  718.         {if(symname(n))argstk=argstk+2;
  719.         else{error("illegal argument name");junk();}
  720.         blanks();
  721.         /* if not closing paren, should be comma */
  722.         if(streq(line+lptr,")")==0)
  723.             {if(match(",")==0)
  724.             error("expected comma");
  725.             }
  726.         if(endst())break;
  727.         }
  728.     locptr=startloc;    /* "clear" local symbol table*/
  729.     Zsp=0;            /* preset stack ptr */
  730.     while(argstk)
  731.         /* now let user declare what types of things */
  732.         /*    those arguments were */
  733.         {if(amatch("char",4)){getarg(cchar);ns();}
  734.         else if(amatch("int",3)){getarg(cint);ns();}
  735.         else{error("wrong number args");break;}
  736.         }
  737.     if(statement()!=streturn) /* do a statement, but if */
  738.                 /* it's a return, skip */
  739.                 /* cleaning up the stack */
  740.         {modstk(0);
  741.         zret();
  742.         }
  743.     Zsp=0;            /* reset stack ptr again */
  744.     locptr=startloc;    /* deallocate all locals */
  745.     infunc=0;        /* not in fn. any more        gtf 7/2/80 */
  746.     }
  747. /* ### cpcn-10 */
  748. /*                    */
  749. /*    Declare argument types        */
  750. /*                    */
  751. /* called from "newfunc" this routine adds an entry in the */
  752. /*    local symbol table for each named argument */
  753. getarg(t)        /* t = cchar or cint */
  754.     int t;
  755.     {
  756.     char n[namesize],c;int j;
  757.     while(1)
  758.         {if(argstk==0)return;    /* no more args */
  759.         if(match("*"))j=pointer;
  760.             else j=variable;
  761.         if(symname(n)==0) illname();
  762.         if(findloc(n))multidef(n);
  763.         if(match("["))    /* pointer ? */
  764.         /* it is a pointer, so skip all */
  765.         /* stuff between "[]" */
  766.             {while(inbyte()!=']')
  767.                 if(endst())break;
  768.             j=pointer;
  769.             /* add entry as pointer */
  770.             }
  771.         addloc(n,j,t,argstk);
  772.         argstk=argstk-2;    /* cnt down */
  773.         if(endst())return;
  774.         if(match(",")==0)error("expected comma");
  775.         }
  776.     }
  777. /* ### cpcn-11 */
  778. /*    Statement parser        */
  779. /*                    */
  780. /* called whenever syntax requires    */
  781. /*    a statement.              */
  782. /*  this routine performs that statement */
  783. /*  and returns a number telling which one */
  784. statement()
  785. {
  786. /* comment out ctrl-C check since ctrl-break will work on PC */
  787. /*    if(cpm(11,0) & 1) */    /* check for ctrl-C        gtf 7/17/80 */
  788.     /*    if(getchar()==3) */
  789.         /*    abort(); */
  790.  
  791.  
  792.     if ((ch()==0) & (eof)) return;
  793.     else if(amatch("char",4))
  794.         {declloc(cchar);ns();}
  795.     else if(amatch("int",3))
  796.         {declloc(cint);ns();}
  797.     else if(match("{"))compound();
  798.     else if(amatch("if",2))
  799.         {doif();lastst=stif;}
  800.     else if(amatch("while",5))
  801.         {dowhile();lastst=stwhile;}
  802.     else if(amatch("return",6))
  803.         {doreturn();ns();lastst=streturn;}
  804.     else if(amatch("break",5))
  805.         {dobreak();ns();lastst=stbreak;}
  806.     else if(amatch("continue",8))
  807.         {docont();ns();lastst=stcont;}
  808.     else if(match(";"));
  809.     else if(match("#asm"))
  810.         {doasm();lastst=stasm;}
  811.     /* if nothing else, assume it's an expression */
  812.     else{expression();ns();lastst=stexp;}
  813.     return lastst;
  814. }
  815. /*                    */
  816. /* ### cpcn-12 */
  817. /*    Semicolon enforcer        */
  818. /*                    */
  819. /* called whenever syntax requires a semicolon */
  820. ns()    {if(match(";")==0)error("missing semicolon");}
  821. /*                    */
  822. /*    Compound statement        */
  823. /*                    */
  824. /* allow any number of statements to fall between "{}" */
  825. compound()
  826.     {
  827.     ++ncmp;        /* new level open */
  828.     while (match("}")==0) statement(); /* do one */
  829.     --ncmp;        /* close current level */
  830.     }
  831. /*                    */
  832. /*        "if" statement        */
  833. /*                    */
  834. doif()
  835.     {
  836.     int flev,fsp,flab1,flab2;
  837.     flev=locptr;    /* record current local level */
  838.     fsp=Zsp;        /* record current stk ptr */
  839.     flab1=getlabel(); /* get label for false branch */
  840.     test(flab1);    /* get expression, and branch false */
  841.     statement();    /* if true, do a statement */
  842.     Zsp=modstk(fsp);    /* then clean up the stack */
  843.     locptr=flev;    /* and deallocate any locals */
  844.     if (amatch("else",4)==0)    /* if...else ? */
  845.         /* simple "if"...print false label */
  846.         {printlabel(flab1);col();nl();
  847.         return;        /* and exit */
  848.         }
  849.     /* an "if...else" statement. */
  850.     jump(flab2=getlabel());    /* jump around false code */
  851.     printlabel(flab1);col();nl();    /* print false label */
  852.     statement();        /* and do "else" clause */
  853.     Zsp=modstk(fsp);        /* then clean up stk ptr */
  854.     locptr=flev;        /* and deallocate locals */
  855.     printlabel(flab2);col();nl();    /* print true label */
  856.     }
  857. /*                    */
  858. /*    "while" statement        */
  859. /*                    */
  860. dowhile()
  861.     {
  862.     int wq[4];        /* allocate local queue */
  863.     wq[wqsym]=locptr;    /* record local level */
  864.     wq[wqsp]=Zsp;        /* and stk ptr */
  865.     wq[wqloop]=getlabel();    /* and looping label */
  866.     wq[wqlab]=getlabel();    /* and exit label */
  867.     addwhile(wq);        /* add entry to queue */
  868.                 /* (for "break" statement) */
  869.     printlabel(wq[wqloop]);col();nl(); /* loop label */
  870.     test(wq[wqlab]);    /* see if true */
  871.     statement();        /* if so, do a statement */
  872.     Zsp = modstk(wq[wqsp]);    /* zap local vars: 9/25/80 gtf */
  873.     jump(wq[wqloop]);    /* loop to label */
  874.     printlabel(wq[wqlab]);col();nl(); /* exit label */
  875.     locptr=wq[wqsym];    /* deallocate locals */
  876.     delwhile();        /* delete queue entry */
  877.     }
  878. /*                    */
  879. /* ### cpcn-13 */
  880. /*                    */
  881. /*    "return" statement        */
  882. /*                    */
  883. doreturn()
  884.     {
  885.     /* if not end of statement, get an expression */
  886.     if(endst()==0)expression();
  887.     modstk(0);    /* clean up stk */
  888.     zret();        /* and exit function */
  889.     }
  890. /*                    */
  891. /*    "break" statement        */
  892. /*                    */
  893. dobreak()
  894.     {
  895.     int *ptr;
  896.     /* see if any "whiles" are open */
  897.     if ((ptr=readwhile())==0) return;    /* no */
  898.     modstk((ptr[wqsp]));    /* else clean up stk ptr */
  899.     jump(ptr[wqlab]);    /* jump to exit label */
  900.     }
  901. /*                    */
  902. /*    "continue" statement        */
  903. /*                    */
  904. docont()
  905.     {
  906.     int *ptr;
  907.     /* see if any "whiles" are open */
  908.     if ((ptr=readwhile())==0) return;    /* no */
  909.     modstk((ptr[wqsp]));    /* else clean up stk ptr */
  910.     jump(ptr[wqloop]);    /* jump to loop label */
  911.     }
  912. /*                    */
  913. /*    "asm" pseudo-statement        */
  914. /*                    */
  915. /* enters mode where assembly language statement are */
  916. /*    passed intact through parser    */
  917. doasm()
  918.     {
  919.     cmode=0;        /* mark mode as "asm" */
  920.     while (1)
  921.         {inline();    /* get and print lines */
  922.         if (match("#endasm")) break;    /* until... */
  923.         if(eof)break;
  924.         outstr(line);
  925.         nl();
  926.         }
  927.     kill();        /* invalidate line */
  928.     cmode=1;        /* then back to parse level */
  929.     }
  930. /* ### cpcn-14 */
  931. /*    >>>>> start of cc3 <<<<<<<<<    */
  932.  
  933.  
  934. /*                    */
  935. /*    Perform a function call        */
  936. /*                    */
  937. /* called from heir11, this routine will either call */
  938. /*    the named function, or if the supplied ptr is */
  939. /*    zero, will call the contents of BX        */
  940. callfunction(ptr)
  941.     char *ptr;    /* symbol table entry (or 0) */
  942. {    int nargs;
  943.     nargs=0;
  944.     blanks();    /* already saw open paren */
  945.     if(ptr==0)zpush();    /* calling BX */
  946.     while(streq(line+lptr,")")==0)
  947.         {if(endst())break;
  948.         expression();    /* get an argument */
  949.         if(ptr==0)swapstk(); /* don't push addr */
  950.         zpush();    /* push argument */
  951.         nargs=nargs+2;    /* count args*2 */
  952.         if (match(",")==0) break;
  953.         }
  954.     needbrack(")");
  955.     if(ptr)zcall(ptr);
  956.     else callstk();
  957.     Zsp=modstk(Zsp+nargs);    /* clean up arguments */
  958. }
  959. junk()
  960. {    if(an(inbyte()))
  961.         while(an(ch()))gch();
  962.     else while(an(ch())==0)
  963.         {if(ch()==0)break;
  964.         gch();
  965.         }
  966.     blanks();
  967. }
  968. endst()
  969. {    blanks();
  970.     return ((streq(line+lptr,";")|(ch()==0)));
  971. }
  972. illname()
  973. {    error("illegal symbol name");junk();}
  974. multidef(sname)
  975.     char *sname;
  976. {    error("already defined");
  977.     comment();
  978.     outstr(sname);nl();
  979. }
  980. needbrack(str)
  981.     char *str;
  982. {    if (match(str)==0)
  983.         {error("missing bracket");
  984.         comment();outstr(str);nl();
  985.         }
  986. }
  987. needlval()
  988. {    error("must be lvalue");
  989. }
  990. /* ### cpcn-15 */
  991. findglb(sname)
  992.     char *sname;
  993. {    char *ptr;
  994.     ptr=startglb;
  995.     while(ptr!=glbptr)
  996.         {if(astreq(sname,ptr,namemax))return ptr;
  997.         ptr=ptr+symsiz;
  998.         }
  999.     return 0;
  1000. }
  1001. findloc(sname)
  1002.     char *sname;
  1003. {    char *ptr;
  1004.     ptr=startloc;
  1005.     while(ptr!=locptr)
  1006.         {if(astreq(sname,ptr,namemax))return ptr;
  1007.         ptr=ptr+symsiz;
  1008.         }
  1009.     return 0;
  1010. }
  1011. addglb(sname,id,typ,value)
  1012.     char *sname,id,typ;
  1013.     int value;
  1014. {    char *ptr;
  1015.     if(cptr=findglb(sname))return cptr;
  1016.     if(glbptr>=endglb)
  1017.         {error("global symbol table overflow");
  1018.         return 0;
  1019.         }
  1020.     cptr=ptr=glbptr;
  1021.     while(an(*ptr++ = *sname++));    /* copy name */
  1022.     cptr[ident]=id;
  1023.     cptr[type]=typ;
  1024.     cptr[storage]=statik;
  1025.     cptr[offset]=value;
  1026.     cptr[offset+1]=value>>8;
  1027.     glbptr=glbptr+symsiz;
  1028.     return cptr;
  1029. }
  1030. addloc(sname,id,typ,value)
  1031.     char *sname,id,typ;
  1032.     int value;
  1033. {    char *ptr;
  1034.     if(cptr=findloc(sname))return cptr;
  1035.     if(locptr>=endloc)
  1036.         {error("local symbol table overflow");
  1037.         return 0;
  1038.         }
  1039.     cptr=ptr=locptr;
  1040.     while(an(*ptr++ = *sname++));    /* copy name */
  1041.     cptr[ident]=id;
  1042.     cptr[type]=typ;
  1043.     cptr[storage]=stkloc;
  1044.     cptr[offset]=value;
  1045.     cptr[offset+1]=value>>8;
  1046.     locptr=locptr+symsiz;
  1047.     return cptr;
  1048. }
  1049. /* ### cpcn-16 */
  1050. addext(sname,id)
  1051.     char *sname,id;
  1052.     {
  1053.     char *ptr;
  1054.     if(cptr=findext(sname)) return cptr;
  1055.     if(extptr>=endextrn)
  1056.         {error("external symbol table overflow"); return 0;}
  1057.     cptr=ptr=extptr;
  1058.     while(an(*ptr++=*sname++)); /* copy name */
  1059.     /* type stored in byte following zero terminating name */
  1060.     *ptr++=id;
  1061.     extptr=ptr;
  1062.     return cptr;
  1063.     }
  1064. findext(sname)
  1065.     char *sname;
  1066.     {char *ptr;
  1067.     ptr=startextrn;
  1068.     while(ptr<extptr)
  1069.         {if(astreq(sname,ptr,namemax)) return ptr;
  1070.          ptr=ptr+strlen(ptr)+2;
  1071.         }
  1072.     return 0;
  1073.     }
  1074.  
  1075.  
  1076. /* Test if next input string is legal symbol name */
  1077. symname(sname)
  1078.     char *sname;
  1079. {    int k;char c;
  1080.     blanks();
  1081.     if(alpha(ch())==0)return 0;
  1082.     k=0;
  1083.     while(an(ch()))sname[k++]=gch();
  1084.     sname[k]=0;
  1085.     return 1;
  1086.     }
  1087. /* ### cpcn-17 */
  1088. /* Return next avail internal label number */
  1089. getlabel()
  1090. {    return(++nxtlab);
  1091. }
  1092. /* Print specified number as label */
  1093. printlabel(label)
  1094.     int label;
  1095. {    outasm("cc");
  1096.     outdec(label);
  1097. }
  1098. /* Test if given character is alpha */
  1099. alpha(c)
  1100.     char c;
  1101. {    c=c&127;
  1102.     return(((c>='a')&(c<='z'))|
  1103.         ((c>='A')&(c<='Z'))|
  1104.         (c=='_'));
  1105. }
  1106. /* Test if given character is numeric */
  1107. numeric(c)
  1108.     char c;
  1109. {    c=c&127;
  1110.     return((c>='0')&(c<='9'));
  1111. }
  1112. /* Test if given character is alphanumeric */
  1113. an(c)
  1114.     char c;
  1115. {    return((alpha(c))|(numeric(c)));
  1116. }
  1117. /* Print a carriage return and a string only to console */
  1118. pl(str)
  1119.     char *str;
  1120. {    int k;
  1121.     k=0;
  1122.     putchar(eol);
  1123.     while(str[k])putchar(str[k++]);
  1124. }
  1125. addwhile(ptr)
  1126.     int ptr[];
  1127.  {
  1128.     int k;
  1129.     if (wqptr==wqmax)
  1130.         {error("too many active whiles");return;}
  1131.     k=0;
  1132.     while (k<wqsiz)
  1133.         {*wqptr++ = ptr[k++];}
  1134. }
  1135. delwhile()
  1136.     {if(readwhile()) wqptr=wqptr-wqsiz;
  1137.     }
  1138. readwhile()
  1139.  {
  1140.     if (wqptr==wq){error("no active whiles");return 0;}
  1141.     else return (wqptr-wqsiz);
  1142.  }
  1143. ch()
  1144. {    return(line[lptr]&127);
  1145. }
  1146. nch()
  1147. {    if(ch()==0)return 0;
  1148.         else return(line[lptr+1]&127);
  1149. }
  1150. gch()
  1151. {    if(ch()==0)return 0;
  1152.         else return(line[lptr++]&127);
  1153. }
  1154. kill()
  1155. {    lptr=0;
  1156.     line[lptr]=0;
  1157. }
  1158. /* ### cpcn-18 */
  1159. inbyte()
  1160. {
  1161.     while(ch()==0)
  1162.         {if (eof) return 0;
  1163.         inline();
  1164.         preprocess();
  1165.         }
  1166.     return gch();
  1167. }
  1168. inchar()
  1169. {
  1170.     if(ch()==0)inline();
  1171.     if(eof)return 0;
  1172.     return(gch());
  1173. }
  1174. inline()
  1175. {
  1176.     int k,unit;
  1177.     while(1)
  1178.         {if (input==0)  {eof=1;return;}
  1179.         if((unit=input2)==0)unit=input;
  1180.         kill();
  1181.         while((k=getc(unit))>0)
  1182.             {if((k==eol)|(lptr>=linemax))break;
  1183.             line[lptr++]=k;
  1184.             }
  1185.         line[lptr]=0;    /* append null */
  1186.         lineno++;    /* read one more line        gtf 7/2/80 */
  1187.         if(k<=0)
  1188.             {fclose(unit);
  1189.             if(input2)endinclude();        /* gtf 7/16/80 */
  1190.                 else input=0;
  1191.             }
  1192.         if(lptr)
  1193.             {if((ctext)&(cmode))
  1194.                 {comment();
  1195.                 outstr(line);
  1196.                 nl();
  1197.                 }
  1198.             lptr=0;
  1199.             return;
  1200.             }
  1201.         }
  1202. }
  1203. /* ### cpcn-19 */
  1204. /*    >>>>>> start of cc4 <<<<<<<    */
  1205.  
  1206.  
  1207. preprocess()
  1208. {    int k;
  1209.     char c,sname[namesize];
  1210.     if(cmode==0)return;
  1211.     mptr=lptr=0;
  1212.     while(ch())
  1213.         {if((ch()==' ')|(ch()==9))
  1214.             predel();
  1215.         else if(ch()=='"')
  1216.             prequote();
  1217.         else if(ch()==39)
  1218.             preapos();
  1219.         else if((ch()=='/')&(nch()=='*'))
  1220.             precomm();
  1221.         else if(alpha(ch()))    /* from an(): 9/22/80 gtf */
  1222.             {k=0;
  1223.             while(an(ch()))
  1224.                 {if(k<namemax)sname[k++]=ch();
  1225.                 gch();
  1226.                 }
  1227.             sname[k]=0;
  1228.             if(k=findmac(sname))
  1229.                 while(c=macq[k++])
  1230.                     keepch(c);
  1231.             else
  1232.                 {k=0;
  1233.                 while(c=sname[k++])
  1234.                     keepch(c);
  1235.                 }
  1236.             }
  1237.         else keepch(gch());
  1238.         }
  1239.     keepch(0);
  1240.     if(mptr>=mpmax)error("line too long");
  1241.     lptr=mptr=0;
  1242.     while(line[lptr++]=mline[mptr++]);
  1243.     lptr=0;
  1244.     }
  1245. /* ### cpcn-20 */
  1246. keepch(c)
  1247.     char c;
  1248. {    mline[mptr]=c;
  1249.     if(mptr<mpmax)mptr++;
  1250.     return c;
  1251. }
  1252. predel()
  1253.             {keepch(' ');
  1254.             while((ch()==' ')|
  1255.                 (ch()==9))
  1256.                 gch();
  1257.             }
  1258. prequote()
  1259.             {keepch(ch());
  1260.             gch();
  1261.             while(ch()!='"')
  1262.                 {if(ch()==0)
  1263.                   {error("missing quote");
  1264.                   break;
  1265.                   }
  1266.                 keepch(gch());
  1267.                 }
  1268.             gch();
  1269.             keepch('"');
  1270.             }
  1271. preapos()
  1272.             {keepch(39);
  1273.             gch();
  1274.             while(ch()!=39)
  1275.                 {if(ch()==0)
  1276.                   {error("missing apostrophe");
  1277.                   break;
  1278.                   }
  1279.                 keepch(gch());
  1280.                 }
  1281.             gch();
  1282.             keepch(39);
  1283.             }
  1284. precomm()
  1285.             {inchar();inchar();
  1286.             while(((ch()=='*')&
  1287.                 (nch()=='/'))==0)
  1288.                 {if(ch()==0)inline();
  1289.                     else inchar();
  1290.                 if(eof)break;
  1291.                 }
  1292.             inchar();inchar();
  1293.             }
  1294. /* ### cpcn-21 */
  1295. addmac()
  1296. {    char sname[namesize];
  1297.     int k;
  1298.     if(symname(sname)==0)
  1299.         {illname();
  1300.         kill();
  1301.         return;
  1302.         }
  1303.     k=0;
  1304.     while(putmac(sname[k++]));
  1305.     while(ch()==' ' | ch()==9) gch();
  1306.     while(putmac(gch()));
  1307.     if(macptr>=macmax)error("macro table full");
  1308.     }
  1309. putmac(c)
  1310.     char c;
  1311. {    macq[macptr]=c;
  1312.     if(macptr<macmax)macptr++;
  1313.     return c;
  1314. }
  1315. findmac(sname)
  1316.     char *sname;
  1317. {    int k;
  1318.     k=0;
  1319.     while(k<macptr)
  1320.         {if(astreq(sname,macq+k,namemax))
  1321.             {while(macq[k++]);
  1322.             return k;
  1323.             }
  1324.         while(macq[k++]);
  1325.         while(macq[k++]);
  1326.         }
  1327.     return 0;
  1328. }
  1329. /* ### cpcn-22 */
  1330. /* direct output to console        gtf 7/16/80 */
  1331. toconsole()
  1332. {
  1333.     saveout = output;
  1334.     output = 0;
  1335. /* end toconsole */}
  1336.  
  1337.  
  1338. /* direct output back to file        gtf 7/16/80 */
  1339. tofile()
  1340. {
  1341.     if(saveout)
  1342.         output = saveout;
  1343.     saveout = 0;
  1344. /* end tofile */}
  1345.  
  1346.  
  1347. outbyte(c)
  1348.     char c;
  1349. {
  1350.     if(c==0)return 0;
  1351.     if(output)
  1352.         {if((putc(c,output))<=0)
  1353.             {closeout();
  1354.             error("Output file error");
  1355.             abort();            /* gtf 7/17/80 */
  1356.             }
  1357.         }
  1358.     else putchar(c);
  1359.     return c;
  1360. }
  1361. outstr(ptr)
  1362.     char ptr[];
  1363.  {
  1364.     int k;
  1365.     k=0;
  1366.     while(outbyte(ptr[k++]));
  1367.  }
  1368.  
  1369.  
  1370. /* write text destined for the assembler to read */
  1371. /* (i.e. stuff not in comments)            */
  1372. /*  gtf  6/26/80 */
  1373. outasm(ptr)
  1374. char *ptr;
  1375. {
  1376.     while(outbyte(raise(*ptr++)));
  1377. /* end outasm */}
  1378.  
  1379.  
  1380. nl()
  1381.     {outbyte(eol);}
  1382. tab()
  1383.     {outbyte(9);}
  1384. col()
  1385.     {outbyte(58);}
  1386. /* ### cpcn-23 */
  1387. error(ptr)
  1388. char ptr[];
  1389. {    int k;
  1390.     char junk[81];
  1391.  
  1392.  
  1393.     toconsole();
  1394.     bell();
  1395.     outstr("Line "); outdec(lineno); outstr(", ");
  1396.     if(infunc==0)
  1397.         outbyte('(');
  1398.     if(currfn==NULL)
  1399.         outstr("start of file");
  1400.     else    outstr(currfn+name);
  1401.     if(infunc==0)
  1402.         outbyte(')');
  1403.     outstr(" + ");
  1404.     outdec(lineno-fnstart);
  1405.     outstr(": ");  outstr(ptr);  nl();
  1406.  
  1407.  
  1408.     outstr(line); nl();
  1409.  
  1410.  
  1411.     k=0;    /* skip to error position */
  1412.     while(k<lptr){
  1413.         if(line[k++]==9)
  1414.             tab();
  1415.         else    outbyte(' ');
  1416.         }
  1417.     outbyte('^');  nl();
  1418.     ++errcnt;
  1419.  
  1420.  
  1421.     if(errstop){
  1422.         pl("Continue (Y,n,g) ? ");
  1423.         gets(junk);        
  1424.         k=junk[0];
  1425.         if((k=='N') | (k=='n'))
  1426.             abort();
  1427.         if((k=='G') | (k=='g'))
  1428.             errstop=0;
  1429.         }
  1430.     tofile();
  1431. /* end error */}
  1432.  
  1433.  
  1434. ol(ptr)
  1435.     char ptr[];
  1436. {
  1437.     ot(ptr);
  1438.     nl();
  1439. }
  1440. ot(ptr)
  1441.     char ptr[];
  1442. {
  1443.     tab();
  1444.     outasm(ptr);
  1445. }
  1446. /* ### cpcn-24 */
  1447. streq(str1,str2)
  1448.     char str1[],str2[];
  1449.  {
  1450.     int k;
  1451.     k=0;
  1452.     while (str2[k])
  1453.         {if ((str1[k])!=(str2[k])) return 0;
  1454.         k++;
  1455.         }
  1456.     return k;
  1457.  }
  1458. astreq(str1,str2,len)
  1459.     char str1[],str2[];int len;
  1460.  {
  1461.     int k;
  1462.     k=0;
  1463.     while (k<len)
  1464.         {if ((str1[k])!=(str2[k]))break;
  1465.         if(str1[k]==0)break;
  1466.         if(str2[k]==0)break;
  1467.         k++;
  1468.         }
  1469.     if (an(str1[k]))return 0;
  1470.     if (an(str2[k]))return 0;
  1471.     return k;
  1472.  }
  1473. match(lit)
  1474.     char *lit;
  1475. {
  1476.     int k;
  1477.     blanks();
  1478.     if (k=streq(line+lptr,lit))
  1479.         {lptr=lptr+k;
  1480.         return 1;
  1481.         }
  1482.      return 0;
  1483. }
  1484. amatch(lit,len)
  1485.     char *lit;int len;
  1486.  {
  1487.     int k;
  1488.     blanks();
  1489.     if (k=astreq(line+lptr,lit,len))
  1490.         {lptr=lptr+k;
  1491.         while(an(ch())) inbyte();
  1492.         return 1;
  1493.         }
  1494.     return 0;
  1495.  }
  1496. /* ### cpcn-25 */
  1497. blanks()
  1498.     {while(1)
  1499.         {while(ch()==0)
  1500.             {inline();
  1501.             preprocess();
  1502.             if(eof)break;
  1503.             }
  1504.         if(ch()==' ')gch();
  1505.         else if(ch()==9)gch();
  1506.         else return;
  1507.         }
  1508.     }
  1509. outdec(number)
  1510.     int number;
  1511.  {
  1512.     int k,zs;
  1513.     char c;
  1514.     zs = 0;
  1515.     k=10000;
  1516.     if (number<0)
  1517.         {number=(-number);
  1518.         outbyte('-');
  1519.         }
  1520.     while (k>=1)
  1521.         {
  1522.         c=number/k + '0';
  1523.         if ((c!='0')|(k==1)|(zs))
  1524.             {zs=1;outbyte(c);}
  1525.         number=number%k;
  1526.         k=k/10;
  1527.         }
  1528.  }
  1529. /* return the length of a string */
  1530. /* gtf 4/8/80 */
  1531. strlen(s)
  1532. char *s;
  1533. {    char *t;
  1534.  
  1535.  
  1536.     t = s;
  1537.     while(*s) s++;
  1538.     return(s-t);
  1539. /* end strlen */}
  1540.  
  1541.  
  1542. /* convert lower case to upper */
  1543. /* gtf 6/26/80 */
  1544. raise(c)
  1545. char c;
  1546. {
  1547.     if((c>='a') & (c<='z'))
  1548.         c = c - 'a' + 'A';
  1549.     return(c);
  1550. /* end raise */}
  1551. /* ### cpcn-26 */
  1552. /*    >>>>>>> start of cc5 <<<<<<<    */
  1553.  
  1554.  
  1555. /* modified 9/25/80: putstk() */
  1556.  
  1557.  
  1558. expression()
  1559. {
  1560.     int lval[2];
  1561.     if(heir1(lval))rvalue(lval);
  1562. }
  1563. heir1(lval)
  1564.     int lval[];
  1565. {
  1566.     int k,lval2[2];
  1567.     k=heir2(lval);
  1568.     if (match("="))
  1569.         {if(k==0){needlval();return 0;}
  1570.         if (lval[1])zpush();
  1571.         if(heir1(lval2))rvalue(lval2);
  1572.         store(lval);
  1573.         return 0;
  1574.         }
  1575.     else return k;
  1576. }
  1577. heir2(lval)
  1578.     int lval[];
  1579. {    int k,lval2[2];
  1580.     k=heir3(lval);
  1581.     blanks();
  1582.     if(ch()!='|')return k;
  1583.     if(k)rvalue(lval);
  1584.     while(1)
  1585.         {if (match("|"))
  1586.             {zpush();
  1587.             if(heir3(lval2)) rvalue(lval2);
  1588.             zpop();
  1589.             zor();
  1590.             }
  1591.         else return 0;
  1592.         }
  1593. }
  1594. /* ### cpcn-27 */
  1595. heir3(lval)
  1596.     int lval[];
  1597. {    int k,lval2[2];
  1598.     k=heir4(lval);
  1599.     blanks();
  1600.     if(ch()!='^')return k;
  1601.     if(k)rvalue(lval);
  1602.     while(1)
  1603.         {if (match("^"))
  1604.             {zpush();
  1605.             if(heir4(lval2))rvalue(lval2);
  1606.             zpop();
  1607.             zxor();
  1608.             }
  1609.         else return 0;
  1610.         }
  1611. }
  1612. heir4(lval)
  1613.     int lval[];
  1614. {    int k,lval2[2];
  1615.     k=heir5(lval);
  1616.     blanks();
  1617.     if(ch()!='&')return k;
  1618.     if(k)rvalue(lval);
  1619.     while(1)
  1620.         {if (match("&"))
  1621.             {zpush();
  1622.             if(heir5(lval2))rvalue(lval2);
  1623.             zpop();
  1624.             zand();
  1625.             }
  1626.         else return 0;
  1627.         }
  1628. }
  1629. heir5(lval)
  1630.     int lval[];
  1631. {
  1632.     int k,lval2[2];
  1633.     k=heir6(lval);
  1634.     blanks();
  1635.     if((streq(line+lptr,"==")==0)&
  1636.         (streq(line+lptr,"!=")==0))return k;
  1637.     if(k)rvalue(lval);
  1638.     while(1)
  1639.         {if (match("=="))
  1640.             {zpush();
  1641.             if(heir6(lval2))rvalue(lval2);
  1642.             zpop();
  1643.             zeq();
  1644.             }
  1645.         else if (match("!="))
  1646.             {zpush();
  1647.             if(heir6(lval2))rvalue(lval2);
  1648.             zpop();
  1649.             zne();
  1650.             }
  1651.         else return 0;
  1652.         }
  1653. }
  1654. /* ### cpcn-28 */
  1655. heir6(lval)
  1656.     int lval[];
  1657. {
  1658.     int k;
  1659.     k=heir7(lval);
  1660.     blanks();
  1661.     if((streq(line+lptr,"<")==0)&
  1662.         (streq(line+lptr,">")==0)&
  1663.         (streq(line+lptr,"<=")==0)&
  1664.         (streq(line+lptr,">=")==0))return k;
  1665.         if(streq(line+lptr,">>"))return k;
  1666.         if(streq(line+lptr,"<<"))return k;
  1667.     if(k)rvalue(lval);
  1668.     while(1)
  1669.         {if (match("<="))
  1670.             {if(heir6wrk(1,lval)) continue;
  1671.             zle();
  1672.             }
  1673.         else if (match(">="))
  1674.             {if(heir6wrk(2,lval)) continue;
  1675.             zge();
  1676.             }
  1677.         else if((streq(line+lptr,"<"))&
  1678.             (streq(line+lptr,"<<")==0))
  1679.             {inbyte();
  1680.             if(heir6wrk(3,lval)) continue;
  1681.             zlt();
  1682.             }
  1683.         else if((streq(line+lptr,">"))&
  1684.             (streq(line+lptr,">>")==0))
  1685.             {inbyte();
  1686.             if(heir6wrk(4,lval)) continue;
  1687.             zgt();
  1688.             }
  1689.         else return 0;
  1690.         }
  1691. }
  1692. /* ### cpcn-29 */
  1693. heir6wrk(k,lval)
  1694.     int k,lval[];
  1695. {
  1696.     int lval2[2];
  1697.     zpush();
  1698.     if(heir7(lval2))rvalue(lval2);
  1699.     zpop();
  1700.     if(cptr=lval[0])
  1701.         if(cptr[ident]==pointer)
  1702.             {heir6op(k);
  1703.             return 1;
  1704.             }
  1705.     if(cptr=lval2[0])
  1706.         if(cptr[ident]==pointer)
  1707.             {heir6op(k);
  1708.             return 1;
  1709.             }
  1710.     return 0;
  1711. }
  1712. heir6op(k)
  1713.     int k;
  1714. {
  1715.     if(k==1) ule();
  1716.     else if(k==2) uge();
  1717.          else if(k==3) ult();
  1718.           else ugt();
  1719. }
  1720. /* ### cpcn-30 */
  1721. /*    >>>>>> start of cc6 <<<<<<    */
  1722.  
  1723.  
  1724. heir7(lval)
  1725.     int lval[];
  1726. {
  1727.     int k,lval2[2];
  1728.     k=heir8(lval);
  1729.     blanks();
  1730.     if((streq(line+lptr,">>")==0)&
  1731.         (streq(line+lptr,"<<")==0))return k;
  1732.     if(k)rvalue(lval);
  1733.     while(1)
  1734.         {if (match(">>"))
  1735.             {zpush();
  1736.             if(heir8(lval2))rvalue(lval2);
  1737.             zpop();
  1738.             asr();
  1739.             }
  1740.         else if (match("<<"))
  1741.             {zpush();
  1742.             if(heir8(lval2))rvalue(lval2);
  1743.             zpop();
  1744.             asl();
  1745.             }
  1746.         else return 0;
  1747.         }
  1748. }
  1749. /* ### cpcn-31 */
  1750. heir8(lval)
  1751.     int lval[];
  1752. {
  1753.     int k,lval2[2];
  1754.     k=heir9(lval);
  1755.     blanks();
  1756.     if((ch()!='+')&(ch()!='-'))return k;
  1757.     if(k)rvalue(lval);
  1758.     while(1)
  1759.         {if (match("+"))
  1760.             {zpush();
  1761.             if(heir9(lval2))rvalue(lval2);
  1762.             if(cptr=lval[0])
  1763.                 if((cptr[ident]==pointer)&
  1764.                 (cptr[type]==cint))
  1765.                 doublereg();
  1766.             zpop();
  1767.             zadd();
  1768.             }
  1769.         else if (match("-"))
  1770.             {zpush();
  1771.             if(heir9(lval2))rvalue(lval2);
  1772.             if(cptr=lval[0])
  1773.                 if((cptr[ident]==pointer)&
  1774.                 (cptr[type]==cint))
  1775.                 doublereg();
  1776.             zpop();
  1777.             zsub();
  1778.             }
  1779.         else return 0;
  1780.         }
  1781. }
  1782. /* ### cpcn-32 */
  1783. heir9(lval)
  1784.     int lval[];
  1785. {
  1786.     int k,lval2[2];
  1787.     k=heir10(lval);
  1788.     blanks();
  1789.     if((ch()!='*')&(ch()!='/')&
  1790.         (ch()!='%'))return k;
  1791.     if(k)rvalue(lval);
  1792.     while(1)
  1793.         {if (match("*"))
  1794.             {zpush();
  1795.             if(heir9(lval2))rvalue(lval2);
  1796.             zpop();
  1797.             mult();
  1798.             }
  1799.         else if (match("/"))
  1800.             {zpush();
  1801.             if(heir10(lval2))rvalue(lval2);
  1802.             zpop();
  1803.             div();
  1804.             }
  1805.         else if (match("%"))
  1806.             {zpush();
  1807.             if(heir10(lval2))rvalue(lval2);
  1808.             zpop();
  1809.             zmod();
  1810.             }
  1811.         else return 0;
  1812.         }
  1813. }
  1814. /* ### cpcn-33 */
  1815. heir10(lval)
  1816.     int lval[];
  1817. {
  1818.     int k;
  1819.     if(match("++"))
  1820.         {if((k=heir10(lval))==0)
  1821.             {needlval();
  1822.             return 0;
  1823.             }
  1824.         heir10inc(lval);
  1825.         return 0;
  1826.         }
  1827.     else if(match("--"))
  1828.         {if((k=heir10(lval))==0)
  1829.             {needlval();
  1830.             return 0;
  1831.             }
  1832.         heir10dec(lval);
  1833.         return 0;
  1834.         }
  1835.     else if (match("-"))
  1836.         {k=heir10(lval);
  1837.         if (k) rvalue(lval);
  1838.         neg();
  1839.         return 0;
  1840.         }
  1841.     else if(match("*"))
  1842.         {heir10as(lval);
  1843.         return 1;
  1844.         }
  1845.     else if(match("&"))
  1846.         {k=heir10(lval);
  1847.         if(k==0)
  1848.             {error("illegal address");
  1849.             return 0;
  1850.             }
  1851.         else if(lval[1])return 0;
  1852.         else
  1853.             {heir10at(lval);
  1854.             return 0;
  1855.             }
  1856.         }
  1857.     else 
  1858.         {k=heir11(lval);
  1859.         if(match("++"))
  1860.             {if(k==0)
  1861.                 {needlval();
  1862.                 return 0;
  1863.                 }
  1864.             heir10id(lval);
  1865.             return 0;
  1866.             }
  1867.         else if(match("--"))
  1868.             {if(k==0)
  1869.                 {needlval();
  1870.                 return 0;
  1871.                 }
  1872.             heir10di(lval);
  1873.             return 0;
  1874.             }
  1875.         else return k;
  1876.         }
  1877.     }
  1878. /* ### cpcn-34 */
  1879. heir10inc(lval)
  1880.     int lval[];
  1881. {
  1882.     char *ptr;
  1883.     if(lval[1])zpush();
  1884.     rvalue(lval);
  1885.     inc();
  1886.     ptr=lval[0];
  1887.     if((ptr[ident]==pointer)&
  1888.         (ptr[type]==cint))
  1889.             inc();
  1890.     store(lval);
  1891. }
  1892. heir10dec(lval)
  1893.     int lval[];
  1894. {
  1895.     char *ptr;
  1896.  
  1897.  
  1898.     if(lval[1])zpush();
  1899.     rvalue(lval);
  1900.     dec();
  1901.     ptr=lval[0];
  1902.     if((ptr[ident]==pointer)&
  1903.         (ptr[type]==cint))
  1904.             dec();
  1905.     store(lval);
  1906. }
  1907. heir10as(lval)
  1908.     int lval[];
  1909. {
  1910.     int k;
  1911.     char *ptr;
  1912.  
  1913.  
  1914.     k=heir10(lval);
  1915.     if(k)rvalue(lval);
  1916.     lval[1]=cint;
  1917.     if(ptr=lval[0])lval[1]=ptr[type];
  1918.     lval[0]=0;
  1919. }
  1920. /* ### cpcn-35 */
  1921. heir10at(lval)
  1922.     int lval[];
  1923. {
  1924.     char *ptr;
  1925.  
  1926.  
  1927.     immed();
  1928.     outstr("OFFSET ");
  1929.     outname(ptr=lval[0]);
  1930.     nl();
  1931.     lval[1]=ptr[type];
  1932. }
  1933. heir10id(lval)
  1934.     int lval[];
  1935. {
  1936.     char *ptr;
  1937.  
  1938.  
  1939.     if(lval[1])zpush();
  1940.     rvalue(lval);
  1941.     inc();
  1942.     ptr=lval[0];
  1943.     if((ptr[ident]==pointer)&
  1944.         (ptr[type]==cint))
  1945.             inc();
  1946.     store(lval);
  1947.     dec();
  1948.     if((ptr[ident]==pointer)&
  1949.         (ptr[type]==cint))
  1950.         dec();
  1951. }
  1952. heir10di(lval)
  1953.     int lval[];
  1954. {
  1955.     char *ptr;
  1956.  
  1957.  
  1958.     if(lval[1])zpush();
  1959.     rvalue(lval);
  1960.     dec();
  1961.     ptr=lval[0];
  1962.     if((ptr[ident]==pointer)&
  1963.         (ptr[type]==cint))
  1964.             dec();
  1965.     store(lval);
  1966.     inc();
  1967.     if((ptr[ident]==pointer)&
  1968.         (ptr[type]==cint))
  1969.         inc();
  1970. }
  1971. /* ### cpcn-36 */
  1972. /*    >>>>>> start of cc7 <<<<<<    */
  1973.  
  1974.  
  1975. heir11(lval)
  1976.     int *lval;
  1977. {    int k;char *ptr;
  1978.     k=primary(lval);
  1979.     ptr=lval[0];
  1980.     blanks();
  1981.     if((ch()=='[')|(ch()=='('))
  1982.     while(1)
  1983.         {if(match("["))
  1984.             {if(ptr==0)
  1985.                 {error("can't subscript");
  1986.                 junk();
  1987.                 needbrack("]");
  1988.                 return 0;
  1989.                 }
  1990.             else if(ptr[ident]==pointer)rvalue(lval);
  1991.             else if(ptr[ident]!=array)
  1992.                 {error("can't subscript");
  1993.                 k=0;
  1994.                 }
  1995.             zpush();
  1996.             expression();
  1997.             needbrack("]");
  1998.             if(ptr[type]==cint)doublereg();
  1999.             zpop();
  2000.             zadd();
  2001.             lval[1]=ptr[type];
  2002.             k=1;
  2003.             }
  2004.         else if(match("("))
  2005.             {if(ptr==0)
  2006.                 {callfunction(0);
  2007.                 }
  2008.             else if(ptr[ident]!=function)
  2009.                 {rvalue(lval);
  2010.                 callfunction(0);
  2011.                 }
  2012.             else callfunction(ptr);
  2013.             k=lval[0]=0;
  2014.             }
  2015.         else return k;
  2016.         }
  2017.     if(ptr==0)return k;
  2018.     if(ptr[ident]==function)
  2019.         {immed();
  2020.         outstr("OFFSET ");
  2021.         outname(ptr);
  2022.         nl();
  2023.         return 0;
  2024.         }
  2025.     return k;
  2026. }
  2027. /* ### cpcn-37 */
  2028. primary(lval)
  2029.     int *lval;
  2030. {    char *ptr,sname[namesize];int num[1];
  2031.     int k;
  2032.     if(match("("))
  2033.         {k=heir1(lval);
  2034.         needbrack(")");
  2035.         return k;
  2036.         }
  2037.     if(symname(sname))
  2038.         {if(ptr=findloc(sname))
  2039.             {getloc(ptr);
  2040.             lval[0]=ptr;
  2041.             lval[1]=ptr[type];
  2042.             if(ptr[ident]==pointer)lval[1]=cint;
  2043.             if(ptr[ident]==array)return 0;
  2044.                 else return 1;
  2045.             }
  2046.         if(ptr=findglb(sname))
  2047.             if(ptr[ident]!=function)
  2048.             {lval[0]=ptr;
  2049.             lval[1]=0;
  2050.             if(ptr[ident]!=array)return 1;
  2051.             immed();
  2052.             outstr("OFFSET ");
  2053.             outname(ptr);nl();
  2054.             lval[1]=ptr[type];
  2055.             return 0;
  2056.             }
  2057.         ptr=addglb(sname,function,cint,0);
  2058.         lval[0]=ptr;
  2059.         lval[1]=0;
  2060.         return 0;
  2061.         }
  2062.     if(constant(num))
  2063.         return(lval[0]=lval[1]=0);
  2064.     else
  2065.         {error("invalid expression");
  2066.         immed();outdec(0);nl();
  2067.         junk();
  2068.         return 0;
  2069.         }
  2070.     }
  2071. /* ### cpcn-38 */
  2072. store(lval)
  2073.     int *lval;
  2074. {    if (lval[1]==0)putmem(lval[0]);
  2075.     else putstk(lval[1]);
  2076. }
  2077. rvalue(lval)
  2078.     int *lval;
  2079. {    if((lval[0] != 0) & (lval[1] == 0))
  2080.         getmem(lval[0]);
  2081.         else indirect(lval[1]);
  2082. }
  2083. test(label)
  2084.     int label;
  2085. {
  2086.     needbrack("(");
  2087.     expression();
  2088.     needbrack(")");
  2089.     testjump(label);
  2090. }
  2091. constant(val)
  2092.     int val[];
  2093. {    if (number(val))
  2094.         immed();
  2095.     else if (pstr(val))
  2096.         immed();
  2097.     else if (qstr(val))
  2098.         {immed();outstr("OFFSET ");printlabel(litlab);outbyte('+');}
  2099.     else return 0;    
  2100.     outdec(val[0]);
  2101.     nl();
  2102.     return 1;
  2103. }
  2104. /* ### cpcn-39 */
  2105. number(val)
  2106.     int val[];
  2107. {    int k,minus;char c;
  2108.     k=minus=1;
  2109.     while(k)
  2110.         {k=0;
  2111.         if (match("+")) k=1;
  2112.         if (match("-")) {minus=(-minus);k=1;}
  2113.         }
  2114.     if(numeric(ch())==0)return 0;
  2115.     while (numeric(ch()))
  2116.         {c=inbyte();
  2117.         k=k*10+(c-'0');
  2118.         }
  2119.     if (minus<0) k=(-k);
  2120.     val[0]=k;
  2121.     return 1;
  2122. }
  2123. pstr(val)
  2124.     int val[];
  2125. {    int k;char c;
  2126.     k=0;
  2127.     if (match("'")==0) return 0;
  2128.     while((c=gch())!=39)
  2129.         k=(k&255)*256 + (c&127);
  2130.     val[0]=k;
  2131.     return 1;
  2132. }
  2133. qstr(val)
  2134.     int val[];
  2135. {    char c;
  2136.     if (match(quote)==0) return 0;
  2137.     val[0]=litptr;
  2138.     while (ch()!='"')
  2139.         {if(ch()==0)break;
  2140.         if(litptr>=litmax)
  2141.             {error("string space exhausted");
  2142.             while(match(quote)==0)
  2143.                 if(gch()==0)break;
  2144.             return 1;
  2145.             }
  2146.         litq[litptr++]=gch();
  2147.         }
  2148.     gch();
  2149.     litq[litptr++]=0;
  2150.     return 1;
  2151. }
  2152. /* ### cpcn-40 */
  2153. /*    >>>>>> start of cc8 <<<<<<<    */
  2154.  
  2155.  
  2156. /* Begin a comment line for the assembler */
  2157. comment()
  2158. {    outbyte(';');
  2159. }
  2160.  
  2161.  
  2162. /* Put out assembler info before any code is generated */
  2163. header()
  2164. {    comment();
  2165.     outstr(BANNER);
  2166.     nl();
  2167.     comment();
  2168.     outstr(VERSION);
  2169.     nl();
  2170.     comment();
  2171.     outstr(AUTHOR);
  2172.     nl();
  2173.     comment();
  2174.     nl();
  2175.     outstr("CSEG SEGMENT BYTE PUBLIC 'code'");nl();
  2176.     ol("ASSUME CS:CSEG,SS:STACK");
  2177. }
  2178. /* Print any assembler stuff needed after all code */
  2179. trailer()
  2180. {
  2181.     nl();            /* 6 May 80 rj errorsummary() now goes to console */
  2182.     comment();
  2183.     outstr(" --- End of Compilation ---");
  2184.     nl();
  2185.     ol("END");
  2186. }
  2187. /* ### cpcn-41 */
  2188. /* Print out a name such that it won't annoy the assembler */
  2189. /*    (by matching anything reserved, like opcodes.) */
  2190. /*    gtf 4/7/80 */
  2191. outname(sname)
  2192. char *sname;
  2193. {    int len, i,j;
  2194.  
  2195.  
  2196.     outasm("qz");
  2197.     len = strlen(sname);
  2198.     if(len>(asmpref+asmsuff)){
  2199.         i = asmpref;
  2200.         len = len-asmpref-asmsuff;
  2201.         while(i-- > 0)
  2202.             outbyte(raise(*sname++));
  2203.         while(len-- > 0)
  2204.             sname++;
  2205.         while(*sname)
  2206.             outbyte(raise(*sname++));
  2207.         }
  2208.     else    outasm(sname);
  2209. /* end outname */}
  2210. /* Fetch a static memory cell into the primary register */
  2211. getmem(sym)
  2212.     char *sym;
  2213. {    if((sym[ident]!=pointer)&(sym[type]==cchar))
  2214.         { ot("MOV AL,SS:");
  2215.         outname(sym+name);
  2216.         nl();
  2217.         ol("CBW");
  2218.         ol("MOV BX,AX");
  2219.         }
  2220.     else
  2221.         {ot("MOV BX,SS:");
  2222.         outname(sym+name);
  2223.         nl();
  2224.         }
  2225.     }
  2226. /* Fetch the address of the specified symbol */
  2227. /*    into the primary register */
  2228. getloc(sym)
  2229.     char *sym;
  2230. {    immed();
  2231.     outdec(((sym[offset]&255)+
  2232.         ((sym[offset+1]&255)<<8))-
  2233.         Zsp);
  2234.     nl();
  2235.     ol("ADD BX,SP");
  2236.     }
  2237. /* Store the primary register into the specified */
  2238. /*    static memory cell */
  2239. putmem(sym)
  2240.     char *sym;
  2241. {
  2242.     ot("MOV SS:");outname(sym+name);
  2243.     outstr(",");
  2244.     if((sym[ident]!=pointer)&(sym[type]==cchar)) outstr("BL");
  2245.     else outstr("BX");
  2246.     nl();
  2247.     }
  2248. /* Store the specified object type in the primary register */
  2249. /*    at the address on the top of the stack */
  2250. putstk(typeobj)
  2251.     char typeobj;
  2252. {    zpop();
  2253.     if(typeobj==cint)
  2254.         callrts("ccpint");
  2255.     else {
  2256.         ol("MOV BP,DX");
  2257.         ol("MOV [BP],BL");
  2258.         }
  2259.     }
  2260. /* ### cpcn-42 */
  2261. /* Fetch the specified object type indirect through the */
  2262. /*    primary register into the primary register */
  2263. indirect(typeobj)
  2264.     char typeobj;
  2265. {    if(typeobj==cchar)callrts("ccgchar");
  2266.         else callrts("ccgint");
  2267. }
  2268. /* Swap the primary and secondary registers */
  2269. swap()
  2270. {
  2271.     ol("XCHG DX,BX");
  2272. }
  2273. /* Print partial instruction to get an immediate value */
  2274. /*    into the primary register */
  2275. immed()
  2276. {
  2277.     ot("MOV BX,");
  2278. }
  2279. /* Push the primary register onto the stack */
  2280. zpush()
  2281. {
  2282.     ol("PUSH BX");
  2283.     Zsp=Zsp-2;
  2284. }
  2285. /* Pop the top of the stack into the secondary register */
  2286. zpop()
  2287. {
  2288.     ol("POP DX");
  2289.     Zsp=Zsp+2;
  2290. }
  2291. /* Swap the primary register and the top of the stack */
  2292. swapstk()
  2293. {
  2294.     ol("MOV BP,SP");
  2295.     ol("XCHG BX,[BP]");
  2296. }
  2297. /* Call the specified subroutine name */
  2298. zcall(sname)
  2299.     char *sname;
  2300. {    ot("CALL ");
  2301.     outname(sname);
  2302.     nl();
  2303.     addext(sname,userfunc);
  2304. }
  2305. /* Call a run-time library routine */
  2306. callrts(sname)
  2307. char *sname;
  2308. {
  2309.     ot("CALL ");
  2310.     outasm(sname);
  2311.     nl();
  2312.     addext(sname,rtsfunc);
  2313. /*end callrts*/}
  2314.  
  2315.  
  2316. /* Return from subroutine */
  2317. zret()
  2318. {    ol("RET");
  2319. }
  2320. /* ### cpcn-43 */
  2321. /* Perform subroutine call to value on top of stack */
  2322. callstk()
  2323. {    immed();
  2324.     outasm("$+11");
  2325.     nl();
  2326.     swapstk();
  2327.     ol("JMP BX");
  2328.     Zsp=Zsp-2;
  2329.     }
  2330. /* Jump to specified internal label number */
  2331. jump(label)
  2332.     int label;
  2333. {    ot("JMP ");
  2334.     printlabel(label);
  2335.     nl();
  2336.     }
  2337. /* Test the primary register and jump if false to label */
  2338. testjump(label)
  2339.     int label;
  2340. {    
  2341.     ol("OR BX,BX");
  2342.     ol("JNZ $+5");
  2343.     jump(label);
  2344. }
  2345. /* Print pseudo-op to define a byte */
  2346. defbyte()
  2347. {    ot("DB ");
  2348. }
  2349. /*Print pseudo-op to define storage */
  2350. defstorage()
  2351. {    ot("DS ");
  2352. }
  2353. /* Print pseudo-op to define a word */
  2354. defword()
  2355. {    ot("DW ");
  2356. }
  2357. /* Modify the stack pointer to the new value indicated */
  2358. modstk(newsp)
  2359.     int newsp;
  2360.  {    int k;
  2361.     k=newsp-Zsp;
  2362.     if(k==0)return newsp;
  2363.     if(k>=0)
  2364.         {if(k<7)
  2365.             {if(k&1)
  2366.                 {
  2367.                 ol("INC SP");
  2368.                 k--;
  2369.                 }
  2370.             while(k)
  2371.                 {ol("POP CX");
  2372.                 k=k-2;
  2373.                 }
  2374.             return newsp;
  2375.             }
  2376.         }
  2377.     if(k<0)
  2378.         {if(k>-7)
  2379.             {if(k&1)
  2380.                 { ol("DEC SP");
  2381.                 k++;
  2382.                 }
  2383.             while(k)
  2384.                 {ol("PUSH CX");
  2385.                 k=k+2;
  2386.                 }
  2387.             return newsp;
  2388.             }
  2389.         }
  2390.     swap();
  2391.     immed();outdec(k);nl();
  2392.     ol("ADD SP,BX");
  2393.     swap();
  2394.     return newsp;
  2395. }
  2396. /* ### cpcn-44 */
  2397. /* Double the primary register */
  2398. doublereg()
  2399. {    ol("ADD BX,BX");
  2400. }
  2401. /* Add the primary and secondary registers */
  2402. /*    (results in primary) */
  2403. zadd()
  2404. {    ol("ADD BX,DX");
  2405. }
  2406. /* Subtract the primary register from the secondary */
  2407. /*    (results in primary) */
  2408. zsub()
  2409. {
  2410.     ol("SUB BX,DX");
  2411.     ol("NEG BX");
  2412. }
  2413. /* Multiply the primary and secondary registers */
  2414. /*    (results in primary */
  2415. mult()
  2416. {    callrts("ccmult");
  2417. }
  2418. /* Divide the secondary register by the primary */
  2419. /*    (quotient in primary, remainder in secondary) */
  2420. div()
  2421. {    callrts("ccdiv");
  2422. }
  2423. /* Compute remainder (mod) of secondary register divided */
  2424. /*    by the primary */
  2425. /*    (remainder in primary, quotient in secondary) */
  2426. zmod()
  2427. {    div();
  2428.     swap();
  2429.     }
  2430. /* Inclusive 'or' the primary and the secondary registers */
  2431. /*    (results in primary) */
  2432. zor()
  2433.     {ol("OR BX,DX");}
  2434. /* Exclusive 'or' the primary and seconday registers */
  2435. /*    (results in primary) */
  2436. zxor()
  2437.     {ol("XOR BX,DX");}
  2438. /* 'And' the primary and secondary registers */
  2439. /*    (results in primary) */
  2440. zand()
  2441.     {ol("AND BX,DX");}
  2442. /* Arithmetic shift right the secondary register number of */
  2443. /*     times in primary (results in primary) */
  2444. asr()
  2445.     {ol("MOV CL,BL");ol("MOV BX,DX");ol("SAR BX,CL");}
  2446. /* Arithmetic left shift the secondary register number of */
  2447. /*    times in primary (results in primary) */
  2448. asl()
  2449.     {ol("MOV CL,BL");ol("MOV BX,DX");ol("SAL BX,CL");}
  2450. /* Form two's complement of primary register */
  2451. neg()
  2452.     {ol("NEG BX");}
  2453. /* Form one's complement of primary register */
  2454. com()
  2455.     {ol("NOT BX");}
  2456. /* Increment the primary register by one */
  2457. inc()
  2458.     {ol("INC BX");}
  2459. /* Decrement the primary register by one */
  2460. dec()
  2461.     {ol("DEC BX");}
  2462.  
  2463.  
  2464. /* Following are the conditional operators */
  2465. /* They compare the secondary register against the primary */
  2466. /* and put a literal 1 in the primary if the condition is */
  2467. /* true, otherwise they clear the primary register */
  2468.  
  2469.  
  2470. /* Test for equal */
  2471. zeq()
  2472.     {callrts("cceq");}
  2473. /* Test for not equal */
  2474. zne()
  2475.     {callrts("ccne");}
  2476. /* Test for less than (signed) */
  2477. zlt()
  2478.     {callrts("cclt");}
  2479. /* Test for less than or equal to (signed) */
  2480. zle()
  2481.     {callrts("ccle");}
  2482. /* Test for greater than (signed) */
  2483. zgt()
  2484.     {callrts("ccgt");}
  2485. /* Test for greater than or equal to (signed) */
  2486. zge()
  2487.     {callrts("ccge");}
  2488. /* Test for less than (unsigned) */
  2489. ult()
  2490.     {callrts("ccult");}
  2491. /* Test for less than or equal to (unsigned) */
  2492. ule()
  2493.     {callrts("ccule");}
  2494. /* Test for greater than (unsigned) */
  2495. ugt()
  2496.     {callrts("ccugt");}
  2497. /* Test for greater than or equal to (unsigned) */
  2498. uge()
  2499.     {callrts("ccuge");}
  2500.  
  2501.  
  2502. /*    <<<<<  End of small-c:PC compiler  >>>>>    */
  2503.