home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d141 / smallc.lha / SmallC / CC12.C < prev    next >
C/C++ Source or Header  |  1988-05-15  |  27KB  |  713 lines

  1. /*      >>>>> start cc1 <<<<<<          */
  2.  
  3. /* 3/3/88 */
  4.  
  5. /*                                      */
  6. /*      Compiler begins execution here  */
  7. /*                                      */
  8. main()
  9. {
  10.         mainmode=
  11.         litlab=1;
  12.         hello();        /* greet user */
  13.         see();          /* determine options */
  14.         openin();       /* first file to process */
  15.         while (input!=0)        /* process user files till he quits */
  16.                 {
  17.                 extptr=startextrn;      /* clear external symbols */
  18.                 glbptr=startglb;        /* clear global symbols */
  19.                 locptr=startloc;        /* clear local symbols */
  20.                 wqptr=wq;               /* clear while queue */
  21.                 macptr=         /* clear the macro pool */
  22.                 litptr=         /* clear literal pool */
  23.                 Zsp =           /* stack ptr (relative) */
  24.                 errcnt=         /* no errors */
  25.                 eof=            /* not end-of-file yet */
  26.                 input2=         /* no include file */
  27.                 saveout=        /* no diverted output */
  28.                 ncmp=           /* no open compound states */
  29.                 lastst=         /* no last statement yet */
  30.                 cextern=        /* no externs yet */
  31.                 fnstart=        /* current "function" started at line 0 gtf 7/2/80 */
  32.                 lineno=         /* no lines read from file              gtf 7/2/80 */
  33.                 infunc=         /* not in function now                  gtf 7/2/80 */
  34.                 quote[1]=
  35.                 0;              /*  ...all set to zero.... */
  36.                 quote[0]='"';           /* fake a quote literal */
  37.                 currfn=NULL;    /* no function yet                      gtf 7/2/80 */
  38.                 cmode=nxtlab=1; /* enable preprocessing and reset label numbers */
  39.                 openout();
  40.                 header();
  41.                 parse();
  42.                 if (ncmp) error("missing closing bracket");
  43.                 extdump();
  44.                 dumpglbs();
  45.                 dumplits();
  46.                 trailer();
  47.                 closeout();
  48.                 errorsummary();
  49.                 mainmode=0;
  50.                 openin();
  51.                 }
  52. }
  53.  
  54. /*                                      */
  55. /*      Abort compilation               */
  56. /*              gtf 7/17/80             */
  57. abort()
  58. {
  59.         if(input2)
  60.                 endinclude();
  61.         if(input)
  62.                 fclose(input);
  63.         closeout();
  64.         toconsole();
  65.         pl("Compilation aborted.");  nl();
  66.         exit();
  67. }
  68.  
  69. /*                                      */
  70. /*      Process all input text          */
  71. /*                                      */
  72. /* At this level, only static declarations, */
  73. /*      defines, includes, and function */
  74. /*      definitions are legal...        */
  75. parse()
  76.         {
  77.         while (eof==0)          /* do until no more input */
  78.                 {
  79.                 if(amatch("extern",6)) {
  80.                         cextern=1;
  81.                         if(amatch("char",4)) {declglb(cchar);ns();}
  82.                         else if(amatch("int",3)) {declglb(cint);ns();}
  83.                         else {declglb(cint);ns();}
  84.                         cextern=0;
  85.                         }
  86.                 else if(amatch("char",4)){declglb(cchar);ns();}
  87.                 else if(amatch("int",3)){declglb(cint);ns();}
  88.                 else if(match("#asm"))doasm();
  89.                 else if(match("#include"))doinclude();
  90.                 else if(match("#define"))addmac();
  91.                 else newfunc();
  92.                 blanks();       /* force eof if pending */
  93.                 }
  94.         }
  95.  
  96. extdump()
  97.         {
  98.         char *ptrext;
  99.         ptrext=startextrn;
  100.         while(ptrext<extptr)
  101.                 {
  102.                 if((cptr=findglb(ptrext))!=0)
  103.                         {if(cptr[ident]==function)
  104.                                 if(cptr[offset]!=function) outextrn(ptrext);
  105.                         }
  106.                 else outextrn(ptrext);
  107.                 ptrext=ptrext+strlen(ptrext)+2;
  108.                 }
  109.         }
  110.  
  111. outextrn(ptr)
  112.         char *ptr;
  113.         {
  114.         char *functype;
  115.         functype=ptr+strlen(ptr)+1;
  116.         if(*functype==statref) return;
  117.         ot("XREF ");
  118.         if(*functype==rtsfunc) outasm(ptr);
  119.         else outname(ptr);
  120.         nl();
  121.         }
  122.  
  123. /*                                      */
  124. /*      Dump the literal pool           */
  125. /*                                      */
  126. dumplits()
  127.         {int j,k;
  128.         if (litptr==0) return;  /* if nothing there, exit...*/
  129.         ol("SECTION TWO,DATA");
  130.         printlabel(litlab); /* print literal label */
  131.         k=0;                    /* init an index... */
  132.         while (k<litptr)        /*      to loop with */
  133.                 {defbyte();     /* pseudo-op to define byte */
  134.                 j=10;           /* max bytes per line */
  135.                 while(j--)
  136.                         {outdec((litq[k++]&127));
  137.                         if ((j==0) | (k>=litptr))
  138.                                 {nl();          /* need <cr> */
  139.                                 break;
  140.                                 }
  141.                         outbyte(',');   /* separate bytes */
  142.                         }
  143.                 }
  144.         }
  145.  
  146. /*                                      */
  147. /*      Dump all static variables       */
  148. /*                                      */
  149. dumpglbs()
  150.         {
  151.         int j;
  152.         if(mainmode)
  153.                 ol("SECTION THREE,BSS");
  154.         cptr=startglb;
  155.         while (cptr<glbptr)
  156.                 {
  157.                 if(cptr[ident]!=function)
  158.                         /* do if anything but function */
  159.                         {
  160.                         if(findext(cptr+name))
  161.                                 {
  162.                                 ot("XREF ");
  163.                                 outname(cptr);
  164.                                 nl();
  165.                                 }
  166.                         else
  167.                                 {
  168.                                 if(mainmode)
  169.                                         ot("XDEF ");
  170.                                 else ot("XREF ");
  171.                                 outname(cptr);
  172.                                 nl();
  173.                                 if(mainmode)
  174.                                         {
  175.                                         outname(cptr);  /* output name as label... */
  176.                                         if(cptr[ident]==pointer)
  177.                                                 defstorptr();
  178.                                         else if(cptr[type]==cint)
  179.                                                 defstorint();
  180.                                         else defstorchr();
  181.                                         j=((cptr[offset]&255)
  182.                                                 + ((cptr[offset+1]&255)<<8));
  183.                                         outdec(j);
  184.                                         nl();
  185.                                         }
  186.                                 }
  187.                         }
  188.                 cptr=cptr+symsiz;
  189.                 }
  190.         }
  191.  
  192. /*                                      */
  193. /*      Report errors for user          */
  194. /*                                      */
  195. errorsummary()
  196.         {
  197.         nl();
  198.         outstr("There were ");
  199.         outdec(errcnt); /* total # errors */
  200.         outstr(" errors in compilation.");
  201.         nl();
  202.         }
  203.  
  204. /*      Greet User      */
  205. hello()
  206.         {
  207.         clrscreen();    /* clear screen function */
  208.         nl();nl();              /* print banner */
  209.         pl(BANNER);
  210.         nl();
  211.         pl(AUTHOR);
  212.         nl();nl();
  213.         pl(VERSION);
  214.         nl();
  215.         nl();
  216. } /* end of hello */
  217.  
  218. see()
  219.         {
  220.         kill();
  221.         /* see if user wants to be sure to see all errors */
  222.         pl("Should I pause after an error (y,N)? ");
  223.         gets(line);
  224.         errstop=0;
  225.         if((ch()=='Y')|(ch()=='y'))
  226.                 errstop=1;
  227.         kill();
  228.         pl("Do you want the Small-C text to appear (y,N)? ");
  229.         gets(line);
  230.         ctext=0;
  231.         if((ch()=='Y')|(ch()=='y')) ctext=1;
  232.         if(mainmode)
  233.                 {
  234.                 kill();
  235.                 pl("Compiling 'main()' (Y,n)? ");
  236.                 gets(line);
  237.                 if((ch()=='N')|(ch()=='n')) mainmode=0;
  238.                 }
  239.         }
  240.  
  241. /*                                      */
  242. /*      Get output filename             */
  243. /*                                      */
  244. openout()
  245.         {
  246.         output=0;               /* start with none */
  247.         while(output==0)
  248.                 {
  249.                 kill();
  250.                 pl("Output filename? "); /* ask...*/
  251.                 gets(line);     /* get a filename */
  252.                 if(ch()==0)break;       /* none given... */
  253.                 if((output=fopen(line,"w"))==NULL) /* if given, open */
  254.                         {output=0;      /* can't open */
  255.                         error("Open failure!");
  256.                         }
  257.                 }
  258.         kill();                 /* erase line */
  259.         }
  260.  
  261. /*                                      */
  262. /*      Get (next) input file           */
  263. /*                                      */
  264. openin()
  265. {
  266.         input=0;                /* none to start with */
  267.         while(input==0){        /* any above 1 allowed */
  268.                 kill();         /* clear line */
  269.                 pl("Input filename? ");
  270.                 gets(line);     /* get a name */
  271.                 if(ch()==0) break;
  272.                 if((input=fopen(line,"r"))!=NULL)
  273.                         newfile();                      /* gtf 7/16/80 */
  274.                 else {  input=0;        /* can't open it */
  275.                         pl("Open failure");
  276.                         }
  277.                 }
  278.         kill();         /* erase line */
  279.         }
  280.  
  281. /*                                      */
  282. /*      Reset line count, etc.          */
  283. /*                      gtf 7/16/80     */
  284. newfile()
  285.         {
  286.         lineno  = 0;    /* no lines read */
  287.         fnstart = 0;    /* no fn. start yet. */
  288.         currfn  = NULL; /* because no fn. yet */
  289.         infunc  = 0;    /* therefore not in fn. */
  290.         }
  291.  
  292. /*                                      */
  293. /*      Open an include file            */
  294. /*                                      */
  295. doinclude()
  296.         {
  297.         blanks();       /* skip over to name */
  298.         toconsole();                                    /* gtf 7/16/80 */
  299.         outstr("#include "); outstr(line+lptr); nl();
  300.         tofile();
  301.         if(input2)                                      /* gtf 7/16/80 */
  302.                 error("Cannot nest include files");
  303.         else if((input2=fopen(line+lptr,"r"))==NULL)
  304.                 {input2=0;
  305.                 error("Open failure on include file");
  306.                 }
  307.         else {  saveline = lineno;
  308.                 savecurr = currfn;
  309.                 saveinfn = infunc;
  310.                 savestart= fnstart;
  311.                 newfile();
  312.                 }
  313.         kill();         /* clear rest of line */
  314.                         /* so next read will come from */
  315.                         /* new file (if open */
  316.         }
  317.  
  318. /*                                      */
  319. /*      Close an include file           */
  320. /*                      gtf 7/16/80     */
  321. endinclude()
  322.         {
  323.         toconsole();
  324.         outstr("#end include"); nl();
  325.         tofile();
  326.         input2  = 0;
  327.         lineno  = saveline;
  328.         currfn  = savecurr;
  329.         infunc  = saveinfn;
  330.         fnstart = savestart;
  331.         }
  332.  
  333. /*                                      */
  334. /*      Close the output file           */
  335. /*                                      */
  336. closeout()
  337.         {
  338.         tofile();       /* if diverted, return to file */
  339.         if(output)fclose(output); /* if open, close it */
  340.         output=0;               /* mark as closed */
  341.         }
  342.  
  343. /*                                      */
  344. /*      Declare a static variable       */
  345. /*        (i.e. define for use)         */
  346. /*                                      */
  347. /* makes an entry in the symbol table so subsequent */
  348. /*  references can call symbol by name  */
  349. declglb(typ)            /* typ is cchar or cint */
  350.         int typ;
  351.         {
  352.         int k, j;
  353.         char sname[namesize];
  354.         while(1)
  355.                 {
  356.                 while(1)
  357.                         {
  358.                         if(endst())
  359.                                 return; /* do line */
  360.                         k=1;            /* assume 1 element */
  361.                         if(match("*"))  /* pointer ? */
  362.                                 j=pointer;      /* yes */
  363.                         else j=variable; /* no */
  364.                         if (symname(sname)==0) /* name ok? */
  365.                                 illname(); /* no... */
  366.                         if(findglb(sname)) /* already there? */
  367.                                 multidef(sname);
  368.                         if (match("["))         /* array? */
  369.                                 {k=needsub();   /* get size */
  370.                                 if(k)j=array;   /* !0=array */
  371.                                 else j=pointer; /* 0=ptr */
  372.                                 }
  373.                         addglb(sname,j,typ,k); /* add symbol */
  374.                         if(cextern) addext(sname,statref);
  375.                         break;
  376.                         }
  377.                 if (match(",")==0) return; /* more? */
  378.                 }
  379.         }
  380.  
  381. /*                                      */
  382. /*      Declare local variables         */
  383. /*      (i.e. define for use)           */
  384. /*                                      */
  385. /* works just like "declglb" but modifies machine stack */
  386. /*      and adds symbol table entry with appropriate */
  387. /*      stack offset to find it again                   */
  388. declloc(typ)            /* typ is cchar or cint */
  389.         int typ;
  390.         {
  391.         int idclass, size;
  392.         char sname[namesize];
  393.         while(1)
  394.                 {
  395.                 while(1)
  396.                         {
  397.                         if(endst())
  398.                                 return;
  399.                         if(match("*"))
  400.                                 idclass=pointer;
  401.                         else idclass=variable;
  402.                         if(symname(sname)==0)
  403.                                 illname();
  404.                         if(findloc(sname))
  405.                                 multidef(sname);
  406.                         if(match("["))
  407.                                 {
  408.                                 size=needsub();
  409.                                 if(size)
  410.                                         {
  411.                                         idclass=array;
  412.                                         if(typ==cint)
  413.                                                 size=size<<2;   /* multiply by 4 */
  414.                                         else if(size&1)
  415.                                                 size++;
  416.                                         }
  417.                                 else
  418.                                         {idclass=pointer;
  419.                                         size=4;
  420.                                         }
  421.                                 }
  422.                         else
  423.                                 if((typ==cchar) & (idclass!=pointer))
  424.                                         size=2; /* 68000 stack address can't be odd */
  425.                                 else size=4;
  426.                         /* change machine stack */
  427.                         Zsp=modstk(Zsp-size);
  428.                         addloc(sname,idclass,typ,Zsp);
  429.                         break;
  430.                         }
  431.                 if (match(",")==0) return;
  432.                 }
  433.         }
  434.  
  435. /*      >>>>>> start of cc2 <<<<<<<<    */
  436.  
  437. /*                                      */
  438. /*      Get required array size         */
  439. /*                                      */
  440. /* invoked when declared variable is followed by "[" */
  441. /*      this routine makes subscript the absolute */
  442. /*      size of the array. */
  443. needsub()
  444.         {
  445.         int num[1];
  446.         if(match("]"))return 0; /* null size */
  447.         if (number(num)==0)     /* go after a number */
  448.                 {error("must be constant");     /* it isn't */
  449.                 num[0]=1;               /* so force one */
  450.                 }
  451.         if (num[0]<0)
  452.                 {error("negative size illegal");
  453.                 num[0]=(-num[0]);
  454.                 }
  455.         needbrack("]");         /* force single dimension */
  456.         return num[0];          /* and return size */
  457.         }
  458.  
  459. /*                                      */
  460. /*      Begin a function                */
  461. /*                                      */
  462. /* Called from "parse" this routine tries to make a function */
  463. /*      out of what follows.    */
  464. newfunc()
  465.         {
  466.         char n[namesize]; /* ptr => currfn,  gtf 7/16/80 */
  467.         if (symname(n)==0)
  468.                 {
  469.                 if(eof==0) error("illegal function or declaration");
  470.                 kill(); /* invalidate line */
  471.                 return;
  472.                 }
  473.         fnstart=lineno;         /* remember where fn began      gtf 7/2/80 */
  474.         infunc=1;               /* note, in function now.       gtf 7/16/80 */
  475.         if(currfn=findglb(n))   /* already in symbol table ? */
  476.                 {if(currfn[ident]!=function)multidef(n);
  477.                         /* already variable by that name */
  478.                 else if(currfn[offset]==function)multidef(n);
  479.                         /* already function by that name */
  480.                 else currfn[offset]=function;
  481.                         /* otherwise we have what was earlier*/
  482.                         /*  assumed to be a function */
  483.                 }
  484.         /* if not in table, define as a function now */
  485.         else currfn=addglb(n,function,cint,function);
  486.         toconsole();                                    /* gtf 7/16/80 */
  487.         outstr("====== "); outstr(currfn+name); outstr("()"); nl();
  488.         tofile();
  489.         /* we had better see open paren for args... */
  490.         if(match("(")==0)error("missing open paren");
  491.         ot("XDEF ");outname(n);nl();
  492.         outname(n);col();nl();  /* print function name */
  493.         argstk=0;               /* init arg count */
  494.         while(match(")")==0)    /* then count args */
  495.                 /* any legal name bumps arg count */
  496.                 {if(symname(n))argstk=argstk+4;
  497.                 else{error("illegal argument name");junk();}
  498.                 blanks();
  499.                 /* if not closing paren, should be comma */
  500.                 if(streq(line+lptr,")")==0)
  501.                         {if(match(",")==0)
  502.                         error("expected comma");
  503.                         }
  504.                 if(endst())break;
  505.                 }
  506.         locptr=startloc;        /* "clear" local symbol table*/
  507.         Zsp=0;                  /* preset stack ptr */
  508.         while(argstk)
  509.                 /* now let user declare what types of things */
  510.                 /*      those arguments were */
  511.                 {if(amatch("char",4)){getarg(cchar);ns();}
  512.                 else if(amatch("int",3)){getarg(cint);ns();}
  513.                 else{error("wrong number args");break;}
  514.                 }
  515.         if(statement()!=streturn) /* do a statement, but if */
  516.                                 /* it's a return, skip */
  517.                                 /* cleaning up the stack */
  518.                 {modstk(0);
  519.                 zret();
  520.                 }
  521.         Zsp=0;                  /* reset stack ptr again */
  522.         locptr=startloc;        /* deallocate all locals */
  523.         infunc=0;               /* not in fn. any more          gtf 7/2/80 */
  524.         }
  525.  
  526. /*                                      */
  527. /*      Declare argument types          */
  528. /*                                      */
  529. /* called from "newfunc" this routine adds an entry in the */
  530. /*      local symbol table for each named argument */
  531. getarg(idtype)          /* idtype = cchar or cint */
  532.         int idtype;
  533.         {
  534.         char idname[namesize];
  535.         int idclass;
  536.         while(1)
  537.                 {if(argstk==0)return;   /* no more args */
  538.                 if(match("*"))idclass=pointer;
  539.                         else idclass=argument;
  540.                 if(symname(idname)==0) illname();
  541.                 if(findloc(idname))multidef(idname);
  542.                 if(match("["))  /* pointer ? */
  543.                 /* it is a pointer, so skip all */
  544.                 /* stuff between "[]" */
  545.                         {while(inbyte()!=']')
  546.                                 if(endst())break;
  547.                         idclass=pointer;
  548.                         /* add entry as pointer */
  549.                         }
  550.                 addloc(idname,idclass,idtype,argstk);
  551.                 argstk=argstk-4;        /* cnt down */
  552.                 if(endst())return;
  553.                 if(match(",")==0)error("expected comma");
  554.                 }
  555.         }
  556.  
  557. /*      Statement parser                */
  558. /*                                      */
  559. /* called whenever syntax requires      */
  560. /*      a statement.                     */
  561. /*  this routine performs that statement */
  562. /*  and returns a number telling which one */
  563. statement()
  564. {
  565. /* comment out ctrl-C check since ctrl-break will work on PC */
  566. /*      if(cpm(11,0) & 1) */    /* check for ctrl-C             gtf 7/17/80 */
  567.         /*      if(getchar()==3) */
  568.                 /*      abort(); */
  569.         if ((ch()==0) & (eof)) return;
  570.         else if(amatch("char",4))
  571.                 {declloc(cchar);ns();}
  572.         else if(amatch("int",3))
  573.                 {declloc(cint);ns();}
  574.         else if(match("{"))compound();
  575.         else if(amatch("if",2))
  576.                 {doif();lastst=stif;}
  577.         else if(amatch("while",5))
  578.                 {dowhile();lastst=stwhile;}
  579.         else if(amatch("return",6))
  580.                 {doreturn();ns();lastst=streturn;}
  581.         else if(amatch("break",5))
  582.                 {dobreak();ns();lastst=stbreak;}
  583.         else if(amatch("continue",8))
  584.                 {docont();ns();lastst=stcont;}
  585.         else if(match(";"));
  586.         else if(match("#asm"))
  587.                 {doasm();lastst=stasm;}
  588.         /* if nothing else, assume it's an expression */
  589.         else{expression();ns();lastst=stexp;}
  590.         return lastst;
  591. }
  592.  
  593. /*                                      */
  594. /*      Semicolon enforcer              */
  595. /*                                      */
  596. /* called whenever syntax requires a semicolon */
  597. ns()    {if(match(";")==0)error("missing semicolon");}
  598.  
  599. /*                                      */
  600. /*      Compound statement              */
  601. /*                                      */
  602. /* allow any number of statements to fall between "{}" */
  603. compound()
  604.         {
  605.         ++ncmp;         /* new level open */
  606.         while (match("}")==0) statement(); /* do one */
  607.         --ncmp;         /* close current level */
  608.         }
  609.  
  610. /*                                      */
  611. /*              "if" statement          */
  612. /*                                      */
  613. doif()
  614.         {
  615.         int flev,fsp,flab1,flab2;
  616.         flev=locptr;    /* record current local level */
  617.         fsp=Zsp;                /* record current stk ptr */
  618.         flab1=getlabel(); /* get label for false branch */
  619.         test(flab1);    /* get expression, and branch false */
  620.         statement();    /* if true, do a statement */
  621.         Zsp=modstk(fsp);        /* then clean up the stack */
  622.         locptr=flev;    /* and deallocate any locals */
  623.         if (amatch("else",4)==0)        /* if...else ? */
  624.                 /* simple "if"...print false label */
  625.                 {printlabel(flab1);col();nl();
  626.                 return;         /* and exit */
  627.                 }
  628.         /* an "if...else" statement. */
  629.         jump(flab2=getlabel()); /* jump around false code */
  630.         printlabel(flab1);col();nl();   /* print false label */
  631.         statement();            /* and do "else" clause */
  632.         Zsp=modstk(fsp);                /* then clean up stk ptr */
  633.         locptr=flev;            /* and deallocate locals */
  634.         printlabel(flab2);col();nl();   /* print true label */
  635.         }
  636.  
  637. /*                                      */
  638. /*      "while" statement               */
  639. /*                                      */
  640. dowhile()
  641.         {
  642.         int wq[4];              /* allocate local queue */
  643.         wq[wqsym]=locptr;       /* record local level */
  644.         wq[wqsp]=Zsp;           /* and stk ptr */
  645.         wq[wqloop]=getlabel();  /* and looping label */
  646.         wq[wqlab]=getlabel();   /* and exit label */
  647.         addwhile(wq);           /* add entry to queue */
  648.                                 /* (for "break" statement) */
  649.         printlabel(wq[wqloop]);col();nl(); /* loop label */
  650.         test(wq[wqlab]);        /* see if true */
  651.         statement();            /* if so, do a statement */
  652.         Zsp = modstk(wq[wqsp]); /* zap local vars: 9/25/80 gtf */
  653.         jump(wq[wqloop]);       /* loop to label */
  654.         printlabel(wq[wqlab]);col();nl(); /* exit label */
  655.         locptr=wq[wqsym];       /* deallocate locals */
  656.         delwhile();             /* delete queue entry */
  657.         }
  658.  
  659. /*                                      */
  660. /*                                      */
  661. /*      "return" statement              */
  662. /*                                      */
  663. doreturn()
  664.         {
  665.         /* if not end of statement, get an expression */
  666.         if(endst()==0)expression();
  667.         modstk(0);      /* clean up stk */
  668.         zret();         /* and exit function */
  669.         }
  670.  
  671. /*                                      */
  672. /*      "break" statement               */
  673. /*                                      */
  674. dobreak()
  675.         {
  676.         int *ptr;
  677.         /* see if any "whiles" are open */
  678.         if ((ptr=readwhile())==0) return;       /* no */
  679.         modstk((ptr[wqsp]));    /* else clean up stk ptr */
  680.         jump(ptr[wqlab]);       /* jump to exit label */
  681.         }
  682.  
  683. /*                                      */
  684. /*      "continue" statement            */
  685. /*                                      */
  686. docont()
  687.         {
  688.         int *ptr;
  689.         /* see if any "whiles" are open */
  690.         if ((ptr=readwhile())==0) return;       /* no */
  691.         modstk((ptr[wqsp]));    /* else clean up stk ptr */
  692.         jump(ptr[wqloop]);      /* jump to loop label */
  693.         }
  694.  
  695. /*                                      */
  696. /*      "asm" pseudo-statement          */
  697. /*                                      */
  698. /* enters mode where assembly language statement are */
  699. /*      passed intact through parser    */
  700. doasm()
  701.         {
  702.         cmode=0;                /* mark mode as "asm" */
  703.         while (1)
  704.                 {inline();      /* get and print lines */
  705.                 if (match("#endasm")) break;    /* until... */
  706.                 if(eof)break;
  707.                 outstr(line);
  708.                 nl();
  709.                 }
  710.         kill();         /* invalidate line */
  711.         cmode=1;                /* then back to parse level */
  712.         }
  713.