Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2. ** Small-C Compiler -- Part 2 -- Front End and Miscellaneous.
  3. ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
  4. ** Copyright 1998 H T Walheim
  5. ** All rights reserved.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include "cc.h"
  10.  
  11. extern char
  12.  *symtab, *macn, *macq, *pline, *mline,  optimize,
  13.   alarm, *glbptr, *line, *lptr, *cptr, *cptr2,  *cptr3,
  14.  *locptr, msname[NAMESIZE],  pause,  quote[2];
  15.  
  16. extern int
  17.   *wq,  ccode,  ch,  csp,  eof,  errflag,  iflevel,
  18.   input,  input2,  listfp,  macptr,  nch,
  19.   nxtlab,  op[16],  opindex,  opsize,  output,  pptr,
  20.   skiplevel,  *wqptr;
  21.  
  22. /********************** input functions **********************/
  23.  
  24. preprocess() {
  25.   int k;
  26.   char c;
  27.   if(ccode) {
  28.     line = mline;
  29.     ifline();
  30.     if(eof) return;
  31.     }
  32.   else {
  33.     inline();
  34.     return;
  35.     }
  36.   pptr = -1;
  37.   while(ch != NEWLINE && ch) {
  38.     if(white()) {
  39.       keepch(' ');
  40.       while(white()) gch();
  41.       }
  42.     else if(ch == '"') {
  43.       keepch(ch);
  44.       gch();
  45.       while(ch != '"' || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
  46.         if(ch == NULL) {
  47.           error("no quote");
  48.           break;
  49.           }
  50.         keepch(gch());
  51.         }
  52.       gch();
  53.       keepch('"');
  54.       }
  55.     else if(ch == 39) {
  56.       keepch(39);
  57.       gch();
  58.       while(ch != 39 || (*(lptr-1) == 92 && *(lptr-2) != 92)) {
  59.         if(ch == NULL) {
  60.           error("no apostrophe");
  61.           break;
  62.           }
  63.         keepch(gch());
  64.         }
  65.       gch();
  66.       keepch(39);
  67.       }
  68.     else if(ch == '/' && nch == '*')
  69.       {
  70.         bump(2);
  71.         while((ch == '*' && nch == '/') == 0)
  72.           {
  73.             if(ch)
  74.               bump(1);
  75.             else
  76.               {
  77.                 ifline();
  78.                 if(eof)
  79.                   break;
  80.               }
  81.           }
  82.         bump(2);
  83.       }
  84.     else  if(ch == '/' && nch == '/')
  85.       {
  86.         bump(2);
  87.         while(ch != NEWLINE)
  88.           {
  89.             if(ch)
  90.               bump(1);
  91.             else
  92.               {
  93.                 if(eof)
  94.                   break;
  95.               }
  96.           }
  97.         bump(1);
  98.       }
  99.     else if(an(ch)) {
  100.       k = 0;
  101.       while(an(ch) && k < NAMEMAX) {
  102.         msname[k++] = ch;
  103.         gch();
  104.         }
  105.       msname[k] = NULL;
  106.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0)) {
  107.         k = getint(cptr+NAMESIZE, 2/*INTSIZE*/);
  108.         while(c = macq[k++]) keepch(c);
  109.         while(an(ch)) gch();
  110.         }
  111.       else {
  112.         k = 0;
  113.         while(c = msname[k++]) keepch(c);
  114.         }
  115.       }
  116.     else keepch(gch());
  117.     }
  118.   if(pptr >= LINEMAX) error("line too long");
  119.   keepch(NULL);
  120.   line = pline;
  121.   bump(0);
  122.   }
  123.  
  124. keepch(c)  char c; {
  125.   if(pptr < LINEMAX) pline[++pptr] = c;
  126.   }
  127.  
  128. ifline() {
  129.   while(1) {
  130.     inline();
  131.     if(eof) return;
  132.     if(match("#ifdef")) {
  133.       ++iflevel;
  134.       if(skiplevel) continue;
  135.       symname(msname);
  136.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0) == 0)
  137.         skiplevel = iflevel;
  138.       continue;
  139.       }
  140.     if(match("#ifndef")) {
  141.       ++iflevel;
  142.       if(skiplevel) continue;
  143.       symname(msname);
  144.       if(search(msname, macn, NAMESIZE+2, MACNEND, MACNBR, 0))
  145.         skiplevel = iflevel;
  146.       continue;
  147.       }
  148.     if(match("#else")) {
  149.       if(iflevel) {
  150.         if(skiplevel == iflevel) skiplevel = 0;
  151.         else if(skiplevel == 0)  skiplevel = iflevel;
  152.         }
  153.       else noiferr();
  154.       continue;
  155.       }
  156.     if(match("#endif")) {
  157.       if(iflevel) {
  158.         if(skiplevel == iflevel) skiplevel = 0;
  159.         --iflevel;
  160.         }
  161.       else noiferr();
  162.       continue;
  163.       }
  164.     if(skiplevel) continue;
  165.     if(ch == 0) continue;
  166.     break;
  167.     }
  168.   }
  169.  
  170. inline() {           /* numerous revisions */
  171.   int k, unit;
  172.  
  173.   if(input == EOF) openfile();
  174.   if(eof) return;
  175.   if((unit = input2) == EOF) unit = input;
  176.   if(fgets(line, LINEMAX, unit) == NULL) {
  177.     fclose(unit);
  178.     if(input2 != EOF)
  179.          input2 = EOF;
  180.     else input  = EOF;
  181.     *line = NULL;
  182.     }
  183.   else if(listfp)
  184.     {
  185.     if(listfp == output) fputc(';', output);
  186.     fputs(line, listfp);
  187.     }
  188. #ifdef _MSC_VER
  189.   else
  190.     {
  191.       fputc(';', output);
  192.       fputs(line, output);
  193.     }
  194. #endif    
  195.   bump(0);
  196.   }
  197.  
  198. inbyte()  {
  199.   while(ch == 0) {
  200.     if(eof) return 0;
  201.     preprocess();
  202.     }
  203.   return gch();
  204.   }
  205.  
  206. /********************* scanning functions ********************/
  207.  
  208. /*
  209. ** test if next input string is legal symbol name
  210. */
  211. symname(sname) char *sname; {
  212.   int k;char c;
  213.   blanks();
  214.   if(alpha(ch) == 0) return (*sname = 0);
  215.   k = 0;
  216.   while(an(ch)) {
  217.     sname[k] = gch();
  218.     if(k < NAMEMAX) ++k;
  219.     }
  220.   sname[k] = 0;
  221.   return 1;
  222.   }
  223.  
  224. need(str)  char *str; {
  225.   if(match(str) == 0) error("missing token");
  226.   }
  227.  
  228. ns()  {
  229.   if(match(";") == 0) error("no semicolon");
  230.   else errflag = 0;
  231.   }
  232.  
  233. match(lit)  char *lit; {
  234.   int k;
  235.   blanks();
  236.   if(k = streq(lptr, lit)) {
  237.     bump(k);
  238.     return 1;
  239.     }
  240.   return 0;
  241.   }
  242.  
  243. streq(str1, str2)  char str1[], str2[]; {
  244.   int k;
  245.   k = 0;
  246.   while (str2[k]) {
  247.     if(str1[k] != str2[k]) return 0;
  248.     ++k;
  249.     }
  250.   return k;
  251.  }
  252.  
  253. amatch(lit, len)  char *lit; int len; {
  254.   int k;
  255.   blanks();
  256.   if(k = astreq(lptr, lit, len)) {
  257.     bump(k);
  258.     return 1;
  259.     }
  260.   return 0;
  261.  }
  262.  
  263. astreq(str1, str2, len)  char str1[], str2[]; int len; {
  264.   int k;
  265.   k = 0;
  266.   while (k < len) {
  267.     if(str1[k] != str2[k]) break;
  268.     /*
  269.     ** must detect end of symbol table names terminated by
  270.     ** symbol length in binary
  271.     */
  272.     if(str2[k] < ' ') break;
  273.     if(str1[k] < ' ') break;
  274.     ++k;
  275.     }
  276.   if(an(str1[k]) || an(str2[k])) return 0;
  277.   return k;
  278.   }
  279.  
  280. nextop(list) char *list; {
  281.   char op[4];
  282.   opindex = 0;
  283.   blanks();
  284.   while(1) {
  285.     opsize = 0;
  286.     while(*list > ' ') op[opsize++] = *list++;
  287.     op[opsize] = 0;
  288.     if(opsize = streq(lptr, op))
  289.       if(*(lptr+opsize) != '=' &&
  290.          *(lptr+opsize) != *(lptr+opsize-1))
  291.          return 1;
  292.     if(*list) {
  293.       ++list;
  294.       ++opindex;
  295.       }
  296.     else return 0;
  297.     }
  298.   }
  299.  
  300. blanks() {
  301.   while(1) {
  302.     while(ch) {
  303.       if(white()) gch();
  304.       else return;
  305.       }
  306.     if(line == mline) return;
  307.     preprocess();
  308.     if(eof) break;
  309.     }
  310.   }
  311.  
  312. white() {
  313.   return (*lptr <= ' ' && *lptr);
  314.   }
  315.  
  316. gch() {
  317.   int c;
  318.   if(c = ch) bump(1);
  319.   return c;
  320.   }
  321.  
  322. bump(n) int n; {
  323.   if(n) lptr += n;
  324.   else  lptr  = line;
  325.   if(ch = nch = *lptr) nch = *(lptr+1);
  326.   }
  327.  
  328. kill() {
  329.   *line = 0;
  330.   bump(0);
  331.   }
  332.  
  333. skip() {
  334.   if(an(inbyte()))
  335.        while(an(ch)) gch();
  336.   else while(an(ch) == 0) {
  337.     if(ch == 0) break;
  338.     gch();
  339.     }
  340.   blanks();
  341.   }
  342.  
  343. endst() {
  344.   blanks();
  345.   return (streq(lptr, ";") || ch == 0);
  346.   }
  347.  
  348. /*********** symbol table management functions ***********/
  349.  
  350. addsym(sname, id, type, size, value, lgpp, class)
  351. char *sname, id, type;
  352. int size, value, *lgpp, class;
  353.   {
  354.     if(lgpp == &glbptr)
  355.       {
  356.         if(cptr2 = findglb(sname))
  357.           return cptr2;
  358.         if(cptr == 0)
  359.           {
  360.             error("global symbol table overflow");
  361.             return 0;
  362.           }
  363.       }
  364.     else
  365.       {
  366.         if(locptr > (ENDLOC-SYMMAX))
  367.           {
  368.             error("local symbol table overflow");
  369.             exit(ERRCODE);
  370.           }
  371.         cptr = *lgpp;
  372.       }
  373.     cptr[IDENT] = id;
  374.     cptr[TYPE]  = type;
  375.     cptr[CLASS] = class;
  376.     putint(size, cptr + SIZE, INTSIZE);
  377.     putint(value, cptr + OFFSET, INTSIZE);
  378.     cptr3 = cptr2 = cptr + NAME;
  379.     while(an(*sname))
  380.       *cptr2++ = *sname++;
  381.  
  382.     if(lgpp == &locptr)
  383.       {
  384.         *cptr2 = cptr2 - cptr3;         /* set length */
  385.         *lgpp = ++cptr2;
  386.       }
  387.     return cptr;
  388.   }
  389.  
  390. /*
  391. ** search for symbol match
  392. ** on return cptr points to slot found or empty slot
  393. */
  394. search(sname, buf, len, end, max, off)
  395.   char *sname, *buf, *end;  int len, max, off; {
  396.   cptr  =
  397.   cptr2 = buf+((hash(sname)%(max-1))*len);
  398.   while(*cptr != NULL) {
  399.     if(astreq(sname, cptr+off, NAMEMAX)) return 1;
  400.     if((cptr = cptr+len) >= end) cptr = buf;
  401.     if(cptr == cptr2) return (cptr = 0);
  402.     }
  403.   return 0;
  404.   }
  405.  
  406. hash(sname) char *sname; {
  407.   int i, c;
  408.   i = 0;
  409.   while(c = *sname++) i = (i << 1) + c;
  410.   return i;
  411.   }
  412.  
  413. findglb(sname)  char *sname; {
  414.   if(search(sname, STARTGLB, SYMMAX, ENDGLB, NUMGLBS, NAME))
  415.     return cptr;
  416.   return 0;
  417.   }
  418.  
  419. findloc(sname)  char *sname;  {
  420.   cptr = locptr - 1;  /* search backward for block locals */
  421.   while(cptr > STARTLOC) {
  422.     cptr = cptr - *cptr;
  423.     if(astreq(sname, cptr, NAMEMAX)) return (cptr - NAME);
  424.     cptr = cptr - NAME - 1;
  425.     }
  426.   return 0;
  427.   }
  428.  
  429. nextsym(entry) char *entry; {
  430.   entry = entry + NAME;
  431.   while(*entry++ >= ' ');    /* find length byte */
  432.   return entry;
  433.   }
  434.  
  435. /******** while queue management functions *********/  
  436.  
  437. addwhile(ptr)  int ptr[]; {
  438.   int k;
  439.   ptr[WQSP]   = csp;         /* and stk ptr */
  440.   ptr[WQLOOP] = getlabel();  /* and looping label */
  441.   ptr[WQEXIT] = getlabel();  /* and exit label */
  442.   if(wqptr == WQMAX) {
  443.     error("control statement nesting limit");
  444.     exit(ERRCODE);
  445.     }
  446.   k = 0;
  447.   while (k < WQSIZ) *wqptr++ = ptr[k++];
  448.   }
  449.  
  450. readwhile(ptr) int *ptr; {
  451.   if(ptr <= wq) {
  452.     error("out of context");
  453.     return 0;
  454.     }
  455.   else return (ptr - WQSIZ);
  456.  }
  457.  
  458. delwhile() {
  459.   if(wqptr > wq) wqptr -= WQSIZ;
  460.   }
  461.  
  462. /****************** utility functions ********************/  
  463.  
  464. /*
  465. ** test if c is alphabetic
  466. */
  467. alpha(c)  char c; {
  468.   return (isalpha(c) || c == '_');
  469.   }
  470.  
  471. /*
  472. ** test if given character is alphanumeric
  473. */
  474. an(c)  char c; {
  475.   return (alpha(c) || isdigit(c));
  476.   }
  477.  
  478. /*
  479. ** return next avail internal label number
  480. */
  481. getlabel() {
  482.   return(++nxtlab);
  483.   }
  484.  
  485. /*
  486. ** get integer of length len from address addr
  487. ** (byte sequence set by "putint")
  488. */
  489. getint(addr, len) char *addr; int len; {
  490.   int i;
  491.   i = *(addr + --len);  /* high order byte sign extended */
  492.   while(len--) i = (i << 8) | *(addr + len) & 255;
  493.   return i;
  494.   }
  495.  
  496. /*
  497. ** put integer i of length len into address addr
  498. ** (low byte first)
  499. */
  500. putint(i, addr, len) char *addr; int i, len; {
  501.   while(len--) {
  502.     *addr++ = i;
  503.     i = i >> 8;
  504.     }
  505.   }
  506.  
  507. lout(line, fd) char *line; int fd; {
  508.   fputs(line, fd);
  509.   fputc(NEWLINE, fd);
  510.   }
  511.  
  512. /******************* error functions *********************/  
  513.  
  514. illname() {
  515.   error("illegal symbol");
  516.   skip();
  517.   }
  518.  
  519. multidef(sname)  char *sname; {
  520.   error("already defined");
  521.   }
  522.  
  523. needlval() {
  524.   error("must be lvalue");
  525.   }
  526.  
  527. noiferr() {
  528.   error("no matching #if...");
  529.   errflag = 0;
  530.   }
  531.  
  532. error(msg)
  533. char msg[];
  534.   {
  535.     if(errflag)
  536.       return;
  537.     else
  538.       errflag = 1;
  539.    
  540.     lout(line, stderr);
  541.     errout(msg, stderr);
  542.     if(alarm)
  543.       fputc(7, stderr);
  544.     if(pause)
  545.       while(fgetc(stderr) != NEWLINE);
  546.     if(listfp > 0)
  547.       errout(msg, listfp);
  548.   }
  549.  
  550. errout(msg, fp) char msg[]; int fp; {
  551.   int k;
  552.   k = line+2;
  553.   while(k++ <= lptr) fputc(' ', fp);
  554.   lout("/\\", fp);
  555.   fputs("**** ", fp); lout(msg, fp);
  556.   }
  557.  
  558.