home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 309_01 / cc2.c < prev    next >
Text File  |  1990-03-20  |  14KB  |  537 lines

  1. /*
  2. HEADER:        Small-C source part 2;
  3. FILENAME:    CC2.C;
  4. AUTHORS:    Dieter H. Flunkert;
  5. COMPILERS:Turbo C V2.0 Medium Memory Model;
  6. SYSTEM: MSDOS, modified by Brian Brown, Nov 1989
  7. */
  8. #include <stdio.h>
  9. #include "ccdef.c"
  10.  
  11. /* define external functions */
  12. extern int addglb(), addloc(), addwhile(), amatch(), blanks(), ch(),
  13.   comment(), constexpr(), cout(), debug(), declloc(), defname(),
  14.   defstorage(), delwhile(), doexpression(), dumplits(), endst(), entry(),
  15.   errrpt(), findglb(), findloc(), gch(), getlabel(), getint(), illname(),
  16.   inbyte(), inchar(), inline(), junk(), jump(), kill(), match(), modstk(),
  17.   multidef(), needbrack(), nextsym(), nl(), number(), outbyte(), outdec(),
  18.   outstr(), postlabel(), prelabel(), printlabel(), putint(),
  19.   readwhile(), ret(), sout(), streq(), sw(), symname(), tab(), test();
  20.  
  21. /*  external variables */
  22. extern int argstk, ctext, cmode, DEFDEBUG, declared, declstat, eof,
  23.   first_func,lastst, litlab, litptr, lptr, monitor,
  24.   nogo, noloc, ncmp, *startcomp, statlab, stdecl, stkp,
  25.   stlab, swactive, swdefault, *swnext, *swend, asmtype;
  26.  
  27. extern char *cptr, *cptr2, line[linesize], *locptr, *glbptr, *statptr,symtab[symtbsz];
  28.  
  29. /* Get required array size, invoked when declared variable is followed
  30.    by "[",  this routine makes subscript the absolute size of the array. */
  31. needsub()
  32. {
  33.  int num[1];
  34.  if(match("]"))return (0); /* null size */
  35.  if (number(num)==0) /* go after a number */
  36.   {errrpt("must be constant"); /* it isn't */
  37.   num[0]=1;  /* so force one */
  38.   }
  39.  if (num[0]<0)
  40.   {errrpt("negative size illegal");
  41.   num[0]=(-num[0]);
  42.   }
  43.  needbrack("]");  /* force single dimension */
  44.  return (num[0]);  /* and return size */
  45.  }
  46.  
  47. /* Begin a function  */
  48. /* Called from "parse" this routine tries to make a function out of what follows. */
  49. newfunc(class)
  50. int class;
  51. {  /* next lines added by dieter flunkert 23 jan 1986 */
  52.   int argtop;  /* top of argument stack */
  53.   char n[namesize],*ptr;
  54. #ifdef STGOTO
  55.   nogo=noloc=0;
  56. #endif
  57.   if(monitor)
  58.   {
  59.     cout('\n',stderr);
  60.     sout(line,stderr);
  61.   }
  62.   if (symname(n)==0)
  63.   {
  64.     errrpt("illegal function or declaration");
  65.     kill(); /* invalidate line */
  66.     return;
  67.   }
  68.  if(ptr=findglb(n)) /* already in symbol table ? */
  69.   {
  70.     if(ptr[ident]!=function)  multidef(n);
  71.     /* already variable by that name */
  72.     else if(ptr[offset]==function)multidef(n);
  73.     /* already function by that name */
  74.    else ptr[offset]=function;
  75.     /* otherwise we have what was earlier*/
  76.     /*  assumed to be a function */
  77.   }
  78.  /* if not in table, define as a function now */
  79.  else addglb(n,function,cint,function);
  80.  /* we had better see open paren for args... */
  81.  if(match("(")==0)errrpt("missing open paren");
  82. /* next lines added by dieter flunkert 23 jan 1986 */
  83.  if(first_func) {
  84.    defname(n);  /* define name of asm module */
  85.    first_func = 0;
  86.  }
  87.  entry(n, class);
  88.  if(DEFDEBUG) debug(n);
  89.      /* ** Clear local stack pointer rev. 1P */
  90.  locptr = startloc; /* ** 2 lines inserted  rev. 1P */
  91.  argstk=0;  /* init arg count */
  92.  while(match(")")==0) /* then count args */
  93.   /* any legal name bumps arg count */
  94.   {if(symname(n)) /* **+ Modification  rev. 1P */
  95.    { if (findloc(n)) multidef(n);
  96.    else { addloc(n, 0, 0, argstk);
  97.     argstk = argstk + 2;
  98.    }
  99.   }  /* **- End of modification rev. 1P */
  100.   else{errrpt("illegal argument name");junk();}
  101.   blanks();
  102.   /* if not closing paren, should be comma */
  103.   if(streq(line+lptr,")")==0)
  104.    {if(match(",")==0)
  105.    errrpt("expected comma");
  106.    }
  107.   if(endst())break;
  108.   }
  109. /* ** Next line deleted      rev. 1P */
  110. /* ** locptr=startloc; ** */ /* "clear" local symbol table*/
  111.  stkp=0;   /* preset stack ptr */
  112. /* next line added by dieter flunkert 23 jan 1986 */
  113.  argtop=argstk; /* save top of argument stack */
  114.  while(argstk)
  115.   /* now let user declare what types of things */
  116.   /* those arguments were */
  117.   {if(amatch("char",4)){getarg(argtop,cchar);ns();}
  118.   else if(amatch("int",3)){getarg(argtop,cint);ns();}
  119.   else{errrpt("wrong number args");break;}
  120.   }
  121.  if(statement()!=streturn) /* do a statement, but if */
  122.     /* it's a return, skip */
  123.     /* cleaning up the stack */
  124.   {modstk(0);
  125.   ret();
  126.   }
  127.  stkp=0;   /* reset stack ptr again */
  128.  locptr=startloc; /* deallocate all locals */
  129.  if(litptr) {     /* dump literal pool */
  130.     prelabel(litlab);
  131.     dumplits(1);
  132.     litlab=getlabel();
  133.   }
  134. }
  135.  
  136. /* Declare argument types, called from "newfunc" this routine adds an entry
  137.    in the local symbol table for each named argument. argtop is not allowed
  138.    to change value. This was the case if a function had a declaration like:
  139.    int i; char c; */
  140.  
  141. getarg(argtop,t)  /* t = cchar or cint */
  142. int argtop,t;
  143. {
  144.  int j, legalname, address;
  145.  char n[namesize], c, *argptr;
  146.  while(1)
  147.   {if(argstk==0)return; /* no more args */
  148.   if(match("*"))j=pointer;
  149.    else j=variable;
  150.   if((legalname = symname(n)) == 0) illname();
  151.   if(match("[")) /* pointer ? */
  152.   {
  153.      while(inbyte()!=']')     /* it is a pointer, so skip all stuff between "[]" */
  154.      if(endst())break;
  155.     j=pointer;  /* add entry as pointer */
  156.   }
  157.   if (legalname) {
  158.    if (argptr = findloc(n)) {
  159.    /*  Add in details of the type and address of the name  */
  160.    argptr[ident] = j;
  161.    argptr[type] = t;
  162.    address = argtop - (argptr[offset] + (argptr[offset+1]<<8));
  163.    putint(address, argptr+offset, offsize);
  164.    }
  165.   else errrpt("Expected argument name");
  166.   }
  167.   argstk=argstk-2; /* cnt down */
  168.   if (endst()) return;
  169.   if (match(",") == 0) errrpt("expected comma");
  170.   }
  171. }
  172.  
  173. /* statement parser, called whenever syntax requires a statement this
  174.    routine performs that statement and returns a number telling which one */
  175. statement()
  176. {
  177.   int class;
  178.   if ((ch==0) && (eof)) return;
  179.   if(amatch("static",6)) {
  180.    class=statik;
  181.    if(++stdecl == 1)  /* there are static variables */
  182.        jump(stlab=getlabel()); /* skip static declarations */
  183.   }
  184.   else class=stkloc;
  185.   if(amatch("char",4))  {declloc(cchar,class);ns();}
  186.   else if(amatch("int",3))   {declloc(cint,class);ns();}
  187.   else {
  188.     if(stdecl > 0) {
  189.       postlabel(stlab);
  190.       stdecl = 0;
  191.     }
  192.     if(declared >= 0) {
  193. #ifdef STGOTO
  194.       if(ncmp > 1) nogo=declared; /* disable goto if any */
  195. #endif
  196.       stkp=modstk(stkp - declared);
  197.       declared = -1;
  198.       }
  199.     if(match("{"))               compound();
  200.     else if(amatch("if",2))      {doif();lastst=stif;}
  201.     else if(amatch("while",5))   {dowhile();lastst=stwhile;}
  202.     else if(amatch("do",2))      {dodo();lastst=STDO;}
  203.     else if(amatch("for",3))     {dofor();lastst=STFOR;}
  204.     else if(amatch("switch",6))  {doswitch();lastst=STSWITCH;}
  205.     else if(amatch("case",4))    {docase();lastst=STCASE;}
  206.     else if(amatch("default",7)) {dodefault();lastst=STDEF;}
  207. #ifdef STGOTO
  208.     else if(amatch("goto", 4))   {dogoto(); lastst=STGOTO;}
  209.     else if(dolabel())           lastst=STLABEL;
  210. #endif
  211.     else if(amatch("return",6))  {doreturn();ns();lastst=streturn;}
  212.     else if(amatch("break",5))   {dobreak();ns();lastst=stbreak;}
  213.     else if(amatch("continue",8)){docont();ns();lastst=stcont;}
  214.     else if(match(";"))          ;
  215.     else if(match("#asm"))       {doasm();lastst=stasm;}
  216.     else if(match("#data"))      {dodata(); lastst=stdata;}
  217.     else if(match("#const"))     {doconst(); lastst=stconst;}
  218.     else if(match("#code"))      {docode(); lastst=stcode;}
  219.     else                         {doexpression();ns();lastst=stexp;}
  220.     }
  221.   return lastst;
  222.   }
  223.  
  224. dodo() {
  225.   int wq[4], top;
  226.   addwhile(wq);
  227.   prelabel(top=getlabel());
  228.   statement();
  229.   needbrack("while");
  230.   prelabel(wq[wqloop]);
  231.   test(wq[wqlab],YES);
  232.   jump(top);
  233.   prelabel(wq[wqlab]);
  234.   delwhile();
  235.   ns();
  236. }
  237.  
  238. dofor() {
  239.   int wq[4], lab1, lab2;
  240.   addwhile(wq);
  241.   lab1=getlabel();
  242.   lab2=getlabel();
  243.   needbrack("(");
  244.   if(match(";")==0) {
  245.     doexpression();            /* expr 1 */
  246.     ns();
  247.     }
  248.   prelabel(lab1);
  249.   if(match(";")==0) {
  250.     test(wq[wqlab],NO); /* expr 2 */
  251.     ns();
  252.     }
  253.   jump(lab2);
  254.   prelabel(wq[wqloop]);
  255.   if(match(")")==0) {
  256.     doexpression();            /* expr 3 */
  257.     needbrack(")");
  258.     }
  259.   jump(lab1);
  260.   prelabel(lab2);
  261.   statement();
  262.   jump(wq[wqloop]);
  263.   prelabel(wq[wqlab]);
  264.   delwhile();
  265. }
  266.  
  267. doswitch()
  268. {
  269.   int wq[4], endlab, swact, swdef, *swnex, *swptr;
  270.   swact=swactive;
  271.   swdef=swdefault;
  272.   swnex=swptr=swnext;
  273.   addwhile(wq);
  274.   needbrack("(");
  275.   doexpression();      /* evaluate switch expression */
  276.   needbrack(")");
  277.   swdefault=0;
  278.   swactive=1;
  279.   jump(endlab=getlabel());
  280.   statement();   /* cases, etc. */
  281.   jump(wq[wqlab]);
  282.   prelabel(endlab);
  283.   sw();          /* match cases */
  284.   while(swptr < swnext) {
  285.     defstorage(cint>>2);
  286.     printlabel(*swptr++);  /* case label */
  287.     outbyte(',');
  288.     outdec(*swptr++);      /* case value */
  289.     nl();
  290.     }
  291.   defstorage(cint>>2);
  292.   outdec(0);
  293.   nl();
  294.   if(swdefault) jump(swdefault);
  295.   prelabel(wq[wqlab]);
  296.   delwhile();
  297.   swnext=swnex;
  298.   swdefault=swdef;
  299.   swactive=swact;
  300. }
  301.  
  302. docase() {
  303.   if(swactive==0) errrpt("not in switch");
  304.   if(swnext > swend) {
  305.     errrpt("too many cases");
  306.     return;
  307.   }
  308.   prelabel(*swnext++ = getlabel());
  309.   constexpr(swnext++);
  310.   needbrack(":");
  311. }
  312.  
  313. dodefault() {
  314.   if(swactive) {
  315.     if(swdefault) errrpt("multiple defaults");
  316.     }
  317.   else errrpt("not in switch");
  318.   needbrack(":");
  319.   prelabel(swdefault=getlabel());
  320. }
  321.  
  322. #ifdef STGOTO
  323. dogoto() {
  324.   char ssname[namesize];
  325.   if(nogo > 0) errrpt("not allowed with block-locals");
  326.   else noloc = 1;
  327.   if(symname(ssname)) jump(addlabel(ssname));
  328.   else errrpt("bad label");
  329.   ns();
  330. }
  331.  
  332. dolabel() {
  333.   int i;
  334.   char ssname[namesize];
  335.   char *savelptr;
  336.   blanks();
  337.   savelptr=lptr;
  338.   if(symname(ssname)) {
  339.     if(gch()==':') {
  340.       prelabel(addlabel(ssname));
  341.       return 1;
  342.     }
  343.     else {
  344.      i=savelptr-lptr+1;
  345.      while(--i) inchar();
  346.      }
  347.     }
  348.   return 0;
  349. }
  350.  
  351. addlabel(ssname) char *ssname; {
  352.   if(cptr=findloc(ssname)) {
  353.     if(cptr[ident]!=LABEL) errrpt("not a label");
  354.     }
  355.   else cptr=addloc(ssname, LABEL, LABEL, getlabel(), LABEL);
  356.   return (getint(cptr+offset, offsize));
  357.   }
  358. #endif
  359.  
  360. /* Semicolon enforcer, called whenever syntax requires a semicolon */
  361. ns()
  362. {
  363.   if(match(";")==0)errrpt("missing semicolon");
  364. }
  365.  
  366. /* Compound statement, allow any number of statements to fall between "{}" */
  367. compound()
  368. {
  369.  int savcsp;
  370.  char *savloc, *savstat;
  371.  savcsp=stkp;
  372.  startcomp=savloc=locptr;
  373.  savstat=statptr;
  374.  declared = stdecl = statlab = 0;
  375.  ++ncmp;  /* new level open */
  376.  while (match("}")==0)
  377.   if(eof) {
  378.     errrpt("no final }");
  379.     break;
  380.   }
  381.   else statement(); /* do one */
  382.  --ncmp;  /* close current level */
  383.  if(lastst != streturn)
  384.    modstk(savcsp);  /* delete local variable space */
  385.  stkp=savcsp;
  386. #ifdef STGOTO
  387.   cptr=savloc;            /* retain labels */
  388.   while(cptr < locptr) {
  389.     cptr2=nextsym(cptr);
  390.     if(cptr[ident] == LABEL) {
  391.       while(cptr < cptr2) *savloc++ = *cptr++;
  392.       }
  393.     else cptr=cptr2;
  394.     }
  395. #endif
  396.   declared = -1;
  397.   locptr=savloc;
  398.   statptr=savstat;
  399. }
  400.  
  401. /*  "if" statement  */
  402. doif()
  403.  {
  404.  int flev,fsp,flab1,flab2;
  405.  flev=locptr; /* record current local level */
  406.  fsp=stkp;  /* record current stk ptr */
  407.  flab1=getlabel(); /* get label for false branch */
  408.  test(flab1,YES); /* get expression, and branch false */
  409.  statement(); /* if true, do a statement */
  410.  stkp=modstk(fsp); /* then clean up the stack */
  411.  locptr=flev; /* and deallocate any locals */
  412.  if (amatch("else",4)==0) /* if...else ? */
  413.   /* simple "if"...print false label */
  414.   {
  415.      prelabel(flab1);
  416.      return;  /* and exit */
  417.   }
  418.  /* an "if...else" statement. */
  419.  flab2=getlabel();
  420. #ifdef STGOTO
  421.  if((lastst != streturn)&&(lastst != STGOTO)) jump(flab2);
  422. #else
  423.  if(lastst != streturn) jump(flab2); /* jump around false code */
  424. #endif
  425.  prelabel(flab1);
  426.  /* print false label */
  427.  statement();  /* and do "else" clause */
  428.  stkp=modstk(fsp);  /* then clean up stk ptr */
  429.  locptr=flev;  /* and deallocate locals */
  430.  prelabel(flab2);
  431.  /* print true label */
  432. }
  433.  
  434. /* "while" statement  */
  435. dowhile()
  436. {
  437.  int lwq[4];  /* allocate local queue */
  438.  addwhile(lwq);  /* add entry to queue */
  439.     /* (for "break" statement) */
  440.  prelabel(lwq[wqloop]); /* loop label */
  441.  test(lwq[wqlab],YES); /* see if true */
  442.  statement();  /* if so, do a statement */
  443.  jump(lwq[wqloop]); /* loop to label */
  444.  prelabel(lwq[wqlab]); /* exit label */
  445.  delwhile();  /* delete queue entry */
  446. }
  447.  
  448. /* "return" statement  */
  449. doreturn()
  450. {
  451.   /* if not end of statement, get an expression */
  452.   if(endst()==0)doexpression();
  453.   modstk(0); /* clean up stk */
  454.   ret();  /* and exit function */
  455. }
  456.  
  457. /* "break" statement  */
  458. dobreak()
  459. {
  460.  int *ptr;
  461.  /* see if any "whiles" are open */
  462.  if ((ptr=readwhile())==0) return; /* no */
  463.  modstk((ptr[wqsp])); /* else clean up stk ptr */
  464.  jump(ptr[wqlab]); /* jump to exit label */
  465. }
  466.  
  467. /* "continue" statement  */
  468. docont()
  469. {
  470.  int *ptr;
  471.  /* see if any "whiles" are open */
  472.  if ((ptr=readwhile())==0) return; /* no */
  473.  modstk((ptr[wqsp])); /* else clean up stk ptr */
  474.  jump(ptr[wqloop]); /* jump to loop label */
  475. }
  476.  
  477. /* "asm" pseudo-statement, enters mode where assembly language statement are
  478.    passed intact through parser */
  479. doasm()
  480. {
  481.  cmode=0;  /* mark mode as "asm" */
  482.  while (1)
  483.   {inline(); /* get and print lines */
  484.   if(eof) break;
  485.   if (match("#endasm")){
  486.    if (ctext){
  487.     comment();
  488.     outstr(line); nl();
  489.    }
  490.    break; /* until... */
  491.   }
  492.   outstr(line);
  493.   nl();
  494.   }
  495.  kill();  /* invalidate line */
  496.  cmode=1;  /* then back to parse level */
  497. }
  498.  
  499. /* following added by Brian Brown to support ASxxx Assembler */
  500. dodata()
  501. {
  502.  nl();
  503.  if( asmtype == AS6809 ) {
  504.    ot(".area  RAMDATA  (REL,CON)"); nl();
  505.  }
  506.  else if( asmtype == AS9 ){
  507.   outstr("* .area  RAMDATA  (REL,CON)"); nl();
  508.  }
  509.  kill();  /* invalidate line */
  510. }
  511.  
  512. doconst()
  513. {
  514.  nl();
  515.  if( asmtype == AS6809 ) {
  516.     ot(".area  CONST  (REL,CON)"); nl();
  517.  }
  518.  else if( asmtype == AS9 ) {
  519.     outstr("*  .area  CONST  (REL,CON)"); nl();
  520.  }
  521.  kill();  /* invalidate line */
  522. }
  523.  
  524. docode()
  525. {
  526.  nl();
  527.  if( asmtype == AS6809 ) {
  528.    ot(".area  ROMCODE  (REL,CON)"); nl();
  529.  }
  530.  else if( asmtype == AS9 )
  531.  {
  532.    outstr("*  .area  ROMCODE  (REL,CON)"); nl();
  533.  }
  534.  kill();  /* invalidate line */
  535. }
  536.  
  537.