home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 132_01 / canew.c < prev    next >
Text File  |  1985-08-21  |  21KB  |  856 lines

  1. /*    Starting module of Tiny c compiler by Ron Cain    */
  2. /* Modified Feb. 10,1981 per P.L. Woods article in DDJ #52 */
  3. /*     Functions newfunc and getarg(t)    affected    */
  4. /*
  5.     DEC 25,1981    repaired break function, module ca.c
  6.  
  7.     May 5,1982    Modified declloc(typ) not to update the
  8.     the stack until all allocations have been performed . See
  9.     Doctor Dobb's #67 (May, 1982) in the letters column.
  10.  
  11.     July 10,1982    Re-repaired break function. Use of "==" instead
  12.     of "=" in "ptr = readwhile() " if statement was problem.
  13.  
  14.     July 13,1982    Changed stack offset in getarg(t) for character
  15.     variable from 0 to +1 due to byte swap between 8080 and 6809
  16.     machines.
  17.  
  18. */
  19. /* Other modules are     CDEF.C    Definitions        */
  20. /*            CB.C    Midsection of compiler    */
  21. /*            CD.C    End section of compiler */
  22. #INCLUDE CDEF.H
  23. /* */
  24. /*                            */
  25. /*    Start CC1                    */
  26. /*                            */
  27. /* Compiler begins execution here            */
  28. /*                            */
  29. main()
  30.     {
  31.     glbptr    =startglb;    /* clear global symbols */
  32.     locptr=startloc;    /* clear local symbols    */
  33.     wqptr=wq;        /* clear while queue    */
  34.     macptr=            /* clear the macro pool    */
  35.     litptr=            /* clear the literal pool*/
  36.     sp =            /* stack ptr (relative)    */
  37.     errcnt=            /* no errors (yet)    */
  38.     eof =            /* not end of file    */
  39.     input =            /* no input file    */
  40.     input2 =        /* or include file    */
  41.     output =        /* no open units    */
  42.     ncmp =            /* no open compound stmt*/
  43.     lastst =        /* no last statement    */
  44.     quote[1]=
  45.         0;    /*   all set = to zero        */
  46.     quote[0]='"';        /* fake a quote literal    */
  47.     cmode=1;        /* enable preprocessing    */
  48. /*                            */
  49. /*    Compile body                    */
  50. /*                            */
  51.     ask();            /* get user options    */
  52.     openout();        /* get an output file    */
  53.     openin();        /* and initial input file */
  54.     header();        /* intro code        */
  55.     parse();        /* process all input    */
  56.     dumplits();        /* dump literal pool    */
  57.     dumpglbs();        /* and all static memory*/
  58.     inclrn();        /* Bring in the run time package */
  59.     errorsummary();        /* summarize errors    */
  60.     trailer();        /* follow-up code    */
  61.     closeout();        /* close the output file (if any) */
  62.     return ;        /* exit to system        */
  63. }
  64. /*     Process all input text        */
  65. /* */
  66. /* At this level, only static declarations,defines,includes,    */
  67. /* and function definitions are legal...            */
  68. parse()
  69.     {
  70.     while    (eof==0)        /* do until no more input */
  71.         { 
  72.         if(amatch("char",4)){declglb(cchar);ns();}
  73.         else    if(amatch("int",3)){declglb(cint);ns();}
  74.         else    if(match("#ASM"))doasm();
  75.         else    if(match("#INCLUDE")) doinclude();
  76.         else    if(match("#DEFINE"))addmac();
  77.         else    newfunc();
  78.         blanks();        /*force eof if pending */
  79.         }
  80.     }
  81. /*                    */
  82. /*    Dump the literal pool        */
  83. /*                    */
  84. dumplits()
  85.     {
  86.     int    j,k;
  87.     if (litptr==0) return;        /* if nothing there, exit. */
  88.     printlabel(litlab);col();    /* print literal label    */
  89.     k=0;                /* init an index ...    */
  90.     while (k<litptr)        /* to loop with        */
  91.         {
  92.         defbyte();        /* pseudo-op to define byte */
  93.         j=10;            /* max bytes per line    */
  94.         while(j--)
  95.         {
  96.         outdec((litq[k++]&127));
  97.         if ((j==0) || (k>=litptr))
  98.             {
  99.             nl();        /* need carriage return    */
  100.             break;
  101.             }
  102.         outbyte (',');        /* separate bytes    */
  103.         }
  104.     }
  105. }
  106. /*    Dump all static variables    */
  107. /*                    */
  108. /*                    */
  109. dumpglbs()
  110.     {
  111.     int    j;
  112.     if (glbflag==0) return;        /* no dump if user said no */
  113.     cptr=startglb;
  114.     while(cptr<glbptr) {
  115.         if (cptr[ident]!=function)
  116.             /* do if anything but function */
  117.             { outstr(cptr);col(); /* output name as label..*/
  118.             defstorage();    /* define storage */
  119.             j=((cptr[offset]&255)+((cptr[offset+1]&255)<<8)); /* calculate number of bytes */
  120.             if ((cptr[type]==cint)||(cptr[ident]==pointer))
  121.                 j=j+j;
  122.             outdec(j);    /* neeed that many bytes */
  123.             nl();
  124.             }
  125.         cptr=cptr+symsiz;
  126.         }
  127.     }
  128. /* */
  129. /*    Report errors to user    */
  130. /* */
  131. errorsummary()
  132.     {            /* see if anything left hanging */
  133.     if (ncmp) error ("missing closing bracket");
  134.         /* Open compound statment */
  135.     nl();
  136.     comment();
  137.     outdec(errcnt);        /* total number of errors */
  138.     outstr (" errors in compilation.");
  139.     nl();
  140.     }
  141. /* */
  142. /*    Get options from user    */
  143. /* */
  144. ask()
  145.     { 
  146.     int    k,num[1];
  147.     kill();            /* clear input line */
  148.     outbyte(12);        /* clear the screen */
  149.     nl();nl();nl();        /* print banner        */
  150.     pl(" small c compiler by Ron Cain ");
  151.     nl();
  152.     /* see if the user wants to interleave the c text */
  153.     /* in the form of comments for clarity.           */
  154.     pl("Do you want the c-text to appear?");
  155.     gets(line);        /*retreive answere */
  156.     ctext=0;        /* assume no       */
  157.     if ((ch()=='Y')||(ch()=='y'))
  158.         ctext =1;    /* user said yes   */
  159.     /* see if the user wants to allocate static variables by name in this module */
  160.         pl(" Do you want the globals to be defined? ");
  161.         gets(line);
  162.         glbflag=0;
  163.         if((ch()=='Y'||ch()=='y'))
  164.             glbflag = 1;
  165.     /* get the first allowable number for compiler-generated labels */
  166.     while(1)
  167.         {pl(" Starting number for labels?" );
  168.         gets(line);
  169.         if(ch()==0) {num[0]=0; break;}
  170.         if(k=number(num)) break;
  171.         }
  172.     nxtlab=num[0];
  173.     litlab=getlabel();    /* first label = literal pool */
  174.     kill();            /* erase line              */
  175.     }
  176. /* */
  177. /*    Get output file name        */
  178. /* */
  179. openout()
  180.     {
  181.     char    *ioptr;
  182.     kill();        /* erase line    */
  183.     output = 0;        /* start with none    */
  184.     pl("Output filename?"); /* ask  ....        */
  185.     gets(line);        /* get filename        */
  186.     if(ch()==0)return;    /* none given        */
  187.     ioptr=line;        /* copy of line pointer    */
  188.     if((output=fcreat(line,iobuf0))==EOF)    /* if given, open it up */
  189.         {output =0;        /* cannot open file */
  190.         error(" Open failure ");
  191.         }
  192.     kill();                /* erase line       */
  193.     }
  194. /* */
  195. /*    Get (next) input file    */
  196. /* */
  197. openin()
  198.     {
  199.     char *testptr;
  200.     input=0;        /* none to start with */
  201.     while (input==0)    /* any above 1 allowed */
  202.         {kill();    /* clear any line    */
  203.         if(eof)break;    /* if user said none    */
  204.         pl("Input filename?");
  205.         gets(line);
  206.         testptr=line;
  207.         if(ch()==0){eof=1;break;} /* none given ... */
  208.         if((input=fopen(line,iobuf1))==EOF)
  209.             {input=0;    /* cannot open it */
  210.             pl ("Open failure");
  211.             }
  212.         }
  213.     kill();            /* erase line        */
  214.     }
  215. /* */
  216. /*    Open an include file        */
  217. /* */
  218. doinclude()
  219.     {blanks();        /* skip over to name    */
  220.     if((input2=fopen(line+lptr,iobuf2))==EOF) {
  221.         input2=0;
  222.         error("Open failure on include file");
  223.         }
  224.     kill();            /* clear rest of line    */
  225.                 /* so next read will come from new file (if open)    */
  226.     }
  227. /*    Close the output file    */
  228. closeout()
  229.     {if(output){fflush(iobuf0);fclose(iobuf0);};    /* if open,close it     */
  230.     output=0;            /* and mark it closed    */
  231.     }
  232. /* */
  233. /*    Declare a static variable (ie, define it for use)    */
  234. /*  Makes an entry in the symbol table so subsequent references can call symbol by name */
  235. /* */
  236. declglb(typ)
  237.     int    typ;
  238.     {
  239.     int    k,j;
  240.     char    sname[namesize];
  241.     while(1)
  242.         {while(1)
  243.             {if(endst())return;    /* do line    */
  244.             k=1;            /* assume one element */
  245.             if(match("*"))        /* pointer ?    */
  246.                 j=pointer;    /* yes        */
  247.             else    j=variable;    /* not a pointer*/
  248.             if(symname(sname)==0)    /* name ok ?    */
  249.                 illname();    /* illegal name */
  250.             if(findglb(sname))    /* already there? */
  251.                 multidef(sname);/* multiple def.*/
  252.             if(match("["))        /* array ?    */
  253.                 { k=needsub();    /* get size    */
  254.                 if(k) j=array;    /* 10 = array    */
  255.                 else j=pointer;    /* 0 = pointer    */
  256.                 }
  257.             addglb(sname,j,typ,k);    /* add symbol    */
  258.             break;
  259.             }
  260.         if (match(",")==0) return;    /* more ?    */
  261.         }
  262.     }
  263. /* */
  264. /*    Declare local variables (i.e.,define for use)        */
  265. /* Works just like "declglb" but modifies machine stack and adds sumbol table entry with appropriate */
  266. /* stack offset to find it again                */
  267. /* */
  268. /*
  269.     Modified to not update the stack on declaration until the
  270.    entire argument list has been parsed. See DDJ #67 in letters column.
  271. */
  272. declloc(typ)                /* type is cchar or cint */
  273.     int typ;
  274.     {
  275.     int    k,j,newsp;
  276.     char    sname[namesize];
  277. /*    Init the temp stack pointer */
  278.     newsp = sp;
  279.     while(1)
  280.         {
  281.             if(endst())break;
  282.             if(match("*"))
  283.                 j=pointer;
  284.             else    j=variable;
  285.             if(symname(sname)==0)
  286.                 illname();
  287.             if(findloc(sname))
  288.                 multidef(sname);
  289.             if(match("[")) {
  290.                 k=needsub();
  291.                 if(k)
  292.                     {j=array;
  293.                     if(typ==cint) k=k+k;
  294.                     }
  295.                 else {
  296.                     j=pointer;
  297.                     k=2;
  298.                      }
  299.                 }
  300.             else
  301.                 if((typ==cchar)&&(j!=pointer))
  302.                     k=1;
  303.                 else    k=2;
  304.             /* change machine temp stack    */
  305.             newsp = newsp - k;
  306.             addloc(sname,j,typ,newsp);
  307.             if(match(",")==0) break;
  308.             }
  309.         /* change the machine stack for real */
  310.         sp = modstk(newsp);
  311.     }
  312. /* */
  313. /*    >>>> start of cc2 <<<<<        */
  314. /* Get required array size        */
  315. /* invoked when declared variable is followed by "["    */
  316. /* this routine makes subscript the absolute size of the array */
  317. /* */
  318. needsub()
  319.     {
  320.     int    num[1];
  321.     if (match("]")) return 0;    /* null size    */
  322.     if (number(num)==0)        /* go after a number    */
  323.         { error("must be a constant");    /* if it isn't    */
  324.         num[0]=1;        /* so force one    */
  325.         }
  326.     if(num[0]<0)
  327.         {error("negative size illegal");
  328.         num[0]=(-num[0]);
  329.         }
  330.     needbrack("]");            /* force single dimension */
  331.     return    num[0];            /* and return size    */
  332.     }
  333. /* */
  334. /* Begin a function */
  335. /* Called from "parse", this routine tries to make a function out of what follows */
  336. /* */
  337. newfunc()
  338.     {
  339.     char    n[namesize],*ptr;
  340.     if (symname(n)==0)
  341.         {error("illegal function or declaration");
  342.         kill();        /* invalidate line    */
  343.         return;
  344.         }
  345.     if(ptr=findglb(n))    /* already in symbol table ?    */
  346.         {
  347.         if(ptr[ident]!=function) multidef(n); /* already variable by that name */
  348.     else if(ptr[offset]==function) multidef(n); /* already function by that name   */
  349.     else ptr[offset]=function; /* otherwise, we have what was earlier assumed to be a function */
  350.     }
  351. /* If not in table, define as function now    */
  352. else addglb(n,function,cint,function);
  353. /* look for open paren for arguments    */
  354. if(match("(")==0)error("missing open paren");
  355. outstr(n);col();nl();    /* print function name*/
  356. locptr=startloc;    /* Added per P.L. Woods fix,DDJ #52 */
  357. argstk=0;        /* init arg count    */
  358. while(match(")")==0)    /* then coun the arguments */
  359.     /* any legal name bumps the argument count */
  360.     {if(symname(n))        /* More Woods fixes, DDJ #52 */
  361.         { if(findloc(n)) multidef(n);
  362.           else
  363.             { addloc (n,0,0,argstk);
  364.               argstk=argstk + 2;
  365.             }
  366.         }
  367.     else {error("illegal argument name");junk();}
  368.     blanks();
  369.     /* if not closing paren, should be comma   */
  370.     if(streq(line+lptr,")")==0)
  371.         {if(match(",")==0)
  372.         error("expected a comma");
  373.         }
  374.     if(endst())break;
  375.     }
  376. /* Code to reset locptr to startloc deleted per P.L. Woods fix */
  377. sp=0;                /* preset stack pointer          */
  378. while(argstk) /* user must now declare types of arguments    */
  379.     {if(amatch("char",4)){getarg(cchar);ns();}
  380.     else if(amatch("int",3)){getarg(cint);ns();}
  381.     else {error("wrong number or arguments");break;}
  382.     }
  383. if (statement()!=streturn)    /* doa statement, but if it'S a return,skip cleaning up the stack */
  384.     {modstk(0);
  385.     ret();
  386.     }
  387. sp=0;                /* reset stack pointer again    */
  388. locptr=startloc;        /* deallocate all locals    */
  389. }
  390. /* */
  391. /* Declare argument types    */
  392. /* Called from "newfunc" this routine adds an entry in the local symbol*/
  393. /* table for each named argument    */
  394. /* Totally rewritten by P.L. Woods    */
  395. getarg(t)        /* t= cchar or cint    */
  396.     int t;
  397.     {
  398.     char n[namesize],c,*argptr;
  399.     int j,argtop,legalname,address;
  400.     argtop = argstk;
  401.     while(1)
  402.         {if(argstk==0)return;    /* no more arguments    */
  403.         if(match("*")) j=pointer;
  404.             else j=variable;
  405.         if((legalname = symname(n))==0) illname();
  406.         if(match("["))        /* Is it a pointer ???*/
  407.             /* It is a pointer, so skip all between [...] */
  408.             { while(inbyte() !=']')
  409.                 if(endst()) break;
  410.             j=pointer;        /* add entry as pointer */
  411.             }
  412.         if(legalname)
  413.             {if(argptr=findloc(n))
  414.                 /* add in details of the type and address of the name */
  415.                 {argptr[ident] =j;
  416.                  argptr[type]  =t;
  417.                  address=argtop - ((argptr[offset]&255)+((argptr[offset+1]&255)<<8));
  418. /*
  419.     If variable is a character, the address must be incremented 
  420.     to access the low byte in the stack.
  421. */
  422.             if(j == variable)
  423.               if(t == cchar)
  424.                 address++;
  425.                 argptr[offset]=address;
  426.                 argptr[offset+1]=address >> 8;
  427.                 }
  428.              else
  429.                 error("expecting argument name");
  430.             }
  431.         argstk=argstk - 2;
  432.         if(endst()) return;
  433.         if(match(",")==0) error ("expected comma");
  434.         }
  435.     }
  436. /* */
  437. /*     STATEMENT PARSER    */
  438. /* Called whenever syntax requires a statement.    */
  439. /* Routine performs that statement and returnsa number telling which one*/
  440. statement()
  441.     {if((ch()==0) && (eof)) return;
  442.     else if(amatch("char",4))
  443.         {declloc(cchar);ns();}
  444.     else if(amatch("int",3))
  445.         {
  446.         declloc(cint);
  447.         ns();
  448.         }
  449.     else if(match("{")) compound();
  450.     else if(amatch("if",2))
  451.         {doif();lastst=stif;}
  452.     else if(amatch("while",5))
  453.         {dowhile();lastst=stwhile;}
  454.     else if(amatch("return",6))
  455.         {doreturn();ns();lastst=streturn;}
  456.     else if(amatch("break",5))
  457.         {dobreak();ns();lastst=stbreak;}
  458.     else if(amatch("continue",8))
  459.         {docont();ns();lastst=stcont;}
  460.     else if(match(";"));                /* huh ? */
  461.     else if(match("#ASM"))
  462.         {doasm();lastst=stasm;}
  463.     /* if nothing else, assume it's an expression    */
  464.     else {expression();ns();lastst=stexp;}
  465.     return lastst;
  466.     }
  467. /* */
  468. /*    Semicolon enforcer    */
  469. /* Big Tony weilds a large bludgeon to enforce those tricky little semicolons */
  470. /* */
  471. ns()
  472.     { if(match(";")==0) error("missing semicolon");
  473.     }
  474. /* */
  475. /*    Compound statement    */
  476. /* allow any number or statements to fall between "()"    */
  477. /* */
  478. compound()
  479.     {
  480.     ++ncmp;        /* new level open    */
  481.     while(match("}")==0)
  482.         if(eof) return;
  483.         else statement();
  484.     --ncmp;        /* close current level    */
  485.     }
  486. /* */
  487. /*    "if" statement                */
  488. /* */
  489. doif()
  490.     {
  491.     int    flev,fsp,flab1,flab2;
  492.     flev = locptr;            /* record current local stack     */
  493.     fsp=sp;                /* record current stack pointer */
  494.     flab1=getlabel();    /* get label fro false branch    */
  495.     test(flab1);        /* get expression, and branch if false */
  496.     statement();        /* if true, do a statement    */
  497.     sp=modstk(fsp);        /* then clean up the stack    */
  498.     locptr=flev;        /* and deallocate any locals    */
  499.     if(amatch("else",4)==0)    /* if .... else ?        */
  500.         /* simple if... print false label        */
  501.         {printlabel(flab1);col();nl();
  502.         return;        /*  and exit            */
  503.         }
  504.     /* an "if .... else" statement    */
  505.     jump(flab2=getlabel());    /* jump around false code    */
  506.     printlabel(flab1);col();nl();    /* print false label    */
  507.     statement();            /* and do else clause    */
  508.     sp=modstk(fsp);            /* then clean up stk ptr*/
  509.     locptr=flev;            /* deallocate locals    */
  510.     printlabel(flab2);col();nl();    /* and print true label */
  511.     }
  512. /* */
  513. /*    While statement    */
  514. /* */
  515. dowhile()
  516.     {
  517.     int    wq[4];        /* allocate local que    */
  518.     wq[wqsym]=locptr;    /* recordlocal level    */
  519.     wq[wqsp] = sp;        /* and stak ptr        */
  520.     wq[wqloop]=getlabel();    /* and looping label    */
  521.     wq[wqlab]=getlabel();    /* and exit label    */
  522.     addwhile(wq);        /* add entry to que    */
  523.                 /* for break statement    */
  524.     printlabel(wq[wqloop]);col();nl(); /*loop break */
  525.     test(wq[wqlab]);    /* see if true        */
  526.     statement();        /* if so,do a statement */
  527.     jump(wq[wqloop]);    /* loop to label    */
  528.     printlabel(wq[wqlab]);col();nl(); /* exit label */
  529.     locptr=wq[wqsym];    /* deallocate locals    */
  530.     sp=modstk(wq[wqsp]);    /* clean up stack pointer */
  531.     delwhile();        /* delete queue entry    */
  532.     }
  533. /* */
  534. /*    "return" statement    */
  535. /* */
  536. doreturn()
  537.     {
  538.     /* if not end of statement, get an expression    */
  539.     if(endst()==0) expression();
  540.     modstk(0);        /* clean up stack    */
  541.     ret();            /* exit function    */
  542.     }
  543. /* */
  544. /*    "break" statement    */
  545. /* */
  546. dobreak()
  547.     {
  548.     int    *ptr;
  549.     /* see if any "whiles" are open    */
  550.     if((ptr=readwhile())==0) return;
  551.     modstk((ptr[wqsp]));        /* clean up the stack    */
  552.     jump(ptr[wqlab]);    /* jump to exit label    */
  553.     }
  554. /* */
  555. /*    "continue" statement    */
  556. /* */
  557. docont()
  558.     {
  559.     int    *ptr;
  560.     /* see if any "whiles" are open    */
  561.     if ((ptr=readwhile())==0) return;    /* none open */
  562.     modstk((ptr[wqsp]));        /* else clean up stack pointer */
  563.     jump(ptr[wqloop]);        /* jump to loop label    */
  564.     }
  565. /* */
  566. /*    "ASM" pseudo statement    */
  567. /* enters mode where assembly language statements are passed intact throug parser */
  568. /* */
  569. doasm()
  570.     {
  571.     cmode=0;        /* mark mode as "asm" */
  572.     while(1)
  573.         {inline();    /* get and print line    */
  574.         if (match("#ENDASM")) break;    /* until... */
  575.         if (eof) break;
  576.         outstr(line);
  577.         nl();
  578.         }
  579.     kill();            /* invalidate line    */
  580.     cmode=1;        /* set to parse mode    */
  581.     }
  582. /*    >>>>>>>>> start of cc3 <<<<<<<<    */
  583. /* */
  584. /* Perform a function call        */
  585. /* called from heir11, this routine will either call the named function,*/
  586. /* or if the supplied ptr is zero, will call the contents of HL    */
  587. /* */
  588. callfunction(ptr)
  589.     char    *ptr;        /* symbol table entry (or zero) */
  590.     {
  591.     int    nargs;
  592.     nargs=0;
  593.     blanks();        /* already saw open paren    */
  594.     if(ptr==0)push();    /* calling HL    */
  595.     while(streq(line+lptr,")")==0)
  596.     {if(endst()) break;
  597.     expression();        /* get an argument    */
  598.     if(ptr==0)swapstk();    /* don't push address    */
  599.     push();            /* push argument    */
  600.     nargs=nargs+2;        /* count arguments    */
  601.     if (match(",")==0) break;
  602.     }
  603.     needbrack(")");
  604.     if(ptr)call(ptr);
  605.     else callstk();
  606.     sp=modstk(sp+nargs);    /* clean up arguments    */
  607.     }
  608. /* */
  609. junk()
  610.     {if(an(inbyte()))
  611.         while(an(ch()))gch();
  612.     else while(an(ch())==0)
  613.         {if(ch()==0) break;
  614.         gch();
  615.         }
  616.     blanks();
  617.     }
  618. /* */
  619. endst()
  620.     {blanks();
  621.     return ((streq(line+lptr,";")||(ch()==0)));
  622.     }
  623. /* */
  624. illname()
  625.     {
  626.     error("illegal symbol name");junk();
  627.     }
  628. /* */
  629. multidef(sname)
  630.     char *sname;
  631.     {error("already defined");
  632.     comment();
  633.     outstr(sname);nl();
  634.     }
  635. /* */
  636. /* */
  637. needbrack(str)
  638.     char *str;
  639.     {if (match(str)==0)
  640.         {error("missing bracket");
  641.         comment();outstr(str);nl();
  642.         }
  643.     }
  644. /* */
  645. needlval()
  646. {    error("must be lvalue");
  647. }
  648. findglb(sname)
  649.     char    *sname;
  650.     {char *ptr;
  651.     ptr=startglb;
  652.     while(ptr!=glbptr)
  653.         {if(astreq(sname,ptr,namemax)) return ptr;
  654.         ptr=ptr+symsiz;
  655.         }
  656.     return 0;
  657.     }
  658. findloc(sname)
  659.     char *sname;
  660. {
  661.     char *ptr;
  662.     ptr=startloc;
  663.     while(ptr!=locptr)
  664.         {if(astreq(sname,ptr,namemax))return ptr;
  665.         ptr=ptr+symsiz;
  666.         }
  667.     return 0;
  668. }
  669. /* */
  670. addglb(sname,id,typ,value)
  671.     char *sname,id,typ;
  672.     int  value;
  673.     {
  674.     char *ptr;
  675.     if (cptr=findglb(sname))return cptr;
  676.     if (glbptr >= endglb)
  677.         {error("global symbol table overflow");
  678.         return 0;
  679.         }
  680.     cptr=ptr=glbptr;
  681.     while(an(*ptr++ = *sname++));    /* copy name    */
  682.     cptr[ident]=id;
  683.     cptr[type]=typ;
  684.     cptr[storage]=statik;
  685.     cptr[offset]=value;
  686.     cptr[offset+1]=value>>8;
  687.     glbptr=glbptr+symsiz;
  688.     return cptr;
  689.     }
  690. /* */
  691. addloc(sname,id,typ,value)
  692.     char *sname,id,typ;
  693.     int value;
  694.     {
  695.     char *ptr;
  696.     if(cptr=findloc(sname)) return cptr;
  697.     if(locptr >= endloc)
  698.         {error("local symbol table overflow");
  699.         return 0;
  700.         }
  701.     cptr=ptr=locptr;
  702.     while(an(*ptr++ = *sname++));    /* copy name */
  703.     cptr[ident]=id;
  704.     cptr[type]=typ;
  705.     cptr[storage]=stkloc;
  706.     cptr[offset]=value;
  707.     cptr[offset+1]=value>>8;
  708.     locptr=locptr+symsiz;
  709.     return cptr;
  710.     }
  711. /* */
  712. /*    test if input string is legal symbol name    */
  713. symname(sname)
  714.     char *sname;    
  715.     {
  716.     int k;
  717.     char c;
  718.     blanks();
  719.     if(alpha(ch())==0) return 0;
  720.     k=0;
  721.     while(an(ch())) sname[k++]=gch();
  722.     sname[k]=0;
  723.     return 1;
  724.     }
  725. /*    Return next available internal label number    */
  726. getlabel()
  727.     {return(++nxtlab);}
  728. /*     Print specified number as label    */
  729. printlabel(label)
  730.     int label;
  731. {    outstr("cc");
  732.     outdec(label);
  733. }
  734. /*    Test if given character is alpha    */
  735. alpha(c)
  736.     char c;
  737. {    c=c&127;
  738.     return(((c>='a')&&(c<='z'))||((c>='A')&&(c<='Z'))||(c=='-'));
  739. /* +++++ NOTE: editor would not allow under score above. Used - */
  740. }
  741. /*    Test if given character is numeric    */
  742. numeric(c)
  743.     char c;
  744. {    c=c&127;
  745.     return((c>='0')&&(c<='9'));
  746. }
  747. /* Test if given character is alphanumeric    */
  748. an(c)
  749.     char c;
  750. {
  751.     return((alpha(c))||(numeric(c)));
  752. }
  753. /* Print a carriage return and line feed only to console    */
  754. pl(str)
  755.     char *str;
  756. {    int k;
  757.     k=0;
  758.     putchar(eol);
  759.     putchar(lf);        /* output carriage return and linefeed */
  760.     while(str[k])
  761.         putchar(str[k++]);
  762. }
  763. /* */
  764. addwhile(ptr)
  765.     int ptr[];
  766. {    int k;
  767.     if (wqptr==wqmax)
  768.         {error("too many active whiles");return;}
  769.     k=0;
  770.     while (k<wqsiz)
  771.         {*wqptr++ = ptr[k++];}
  772. }
  773. /* */
  774. delwhile()
  775.     {
  776.     if(readwhile()) wqptr=wqptr-wqsiz;
  777.     }
  778. /* */
  779. readwhile()
  780. {
  781.     if(wqptr==wq) 
  782.         {error("no active whiles"); return 0;}
  783.         else return (wqptr-wqsiz);
  784. }
  785. /* */
  786. ch()
  787. {
  788.     return(line[lptr]&127);
  789. }
  790. nch()
  791. {
  792.     if(ch()==0) return 0;
  793.         else return(line[lptr+1]&127);
  794. }
  795. gch()
  796. {
  797.     if(ch()==0) return 0;
  798.         else return(line[lptr++]&127);
  799. }
  800. kill()
  801. {
  802.     lptr=0;
  803.     line[lptr]=0;
  804. }
  805. inbyte()
  806. {
  807.     while(ch()==0)
  808.         {if (eof) return 0;
  809.         inline();
  810.         preprocess();
  811.         }
  812.     return gch();
  813. }
  814. inchar()
  815. {
  816.     if(ch()==0)inline();
  817.     if(eof) return 0;
  818.     return(gch());
  819. }
  820. inline()
  821. {
  822.     char *ioptr;
  823.     int k,unit;
  824.     while(1)
  825.         {
  826.         if (input==0) openin();
  827.         if(eof) return;
  828.         ioptr=iobuf2;        /* init to include buffer first */
  829.         if((unit=input2)==0) {unit=input;ioptr=iobuf1;}
  830.         kill();
  831.         while(((k=getc(ioptr)) !=26)&&(k != EOF))
  832.             {
  833.             if(k==eol) break;
  834.             if(k!=lf) line[lptr++]=k;
  835.             }
  836.         line[lptr]=0;        /* append null */
  837.         if((k==26)||(k==EOF))
  838.             {fclose(ioptr);
  839.             if(input2)input2=0;
  840.                 else {
  841.                     input=0;
  842.                     eof=1;     /* set end of main file*/
  843.                     }
  844.             }
  845.         if(lptr)
  846.             {if((ctext)&&(cmode))
  847.                 {comment();
  848.                 outstr(line);
  849.                 nl();
  850.                 }
  851.             lptr=0;
  852.             return;
  853.             }
  854.         }
  855.     }
  856. σσσσσσσσσσσσσσσσσσσσ