home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 146_01 / smallc.c < prev    next >
C/C++ Source or Header  |  1985-03-10  |  75KB  |  2,403 lines

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