home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / sozobon / scsrc20 / hcc / tok.c < prev    next >
C/C++ Source or Header  |  1991-02-22  |  12KB  |  716 lines

  1. /* Copyright (c) 1988,1991 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    tok.c
  12.  *
  13.  *    Basic level token routines
  14.  *
  15.  *    At this level, we return the following things:
  16.  *        id's - strings of alpha-alnum
  17.  *        integer constants
  18.  *        float constants
  19.  *        string constants
  20.  *        multi-char tokens
  21.  *
  22.  *    We DONT know about:
  23.  *        keywords
  24.  *        #defined id's
  25.  *        any other meaning of a name
  26.  *
  27.  *    Interface:
  28.  *        call nxttok() to get next token
  29.  *        look at 'curtok' for current token
  30.  *        note that curtok.name points to a static area
  31.  *          for ID or SCON
  32.  *
  33.  *        if EOF is seen, we call endfile() before
  34.  *          giving up
  35.  *
  36.  *    Special flags:  (tk_flags)
  37.  *        These special flags are needed for the pre-processor.
  38.  *        All but TK_SEENL are 1-shot.
  39.  *
  40.  *        TK_SEENL - want to see \n
  41.  *        TK_WS - want to see white space (for #define)
  42.  *        TK_NOESC - dont do '\' escapes in strings
  43.  *        TK_LTSTR - '<' is a string starter
  44.  *        TK_ONLY1 - skip to token after \n  (for #if--)
  45.  */
  46.  
  47. #include <stdio.h>
  48. #include "param.h"
  49. #include "tok.h"
  50.  
  51. #if dLibs
  52. #include <ctype.h>
  53. #endif
  54.  
  55. struct tok curtok;
  56. char curstr[MAXSTR+1];
  57.  
  58. #define TK_SEENL    1    /* want to see NL token */
  59. #define TK_SEEWS    2    /* want to see WS token */
  60. #define TK_ONLY1    4    /* only want 1st token on line */
  61. #define TK_LTSTR    8    /* '<' starts a string */
  62. #define TK_NOESC    16    /* dont do '\' escapes in string */
  63.  
  64. int tk_flags, sawnl;
  65.  
  66. extern FILE *input;
  67. extern int lineno;
  68.  
  69. #define NOCHAR    0x100
  70.  
  71. #ifdef DEBUG
  72. extern int oflags[];
  73. #define debug oflags['b'-'a']
  74. #endif
  75.  
  76. extern double f_zero, f_ten, f_tenth, f_e10, f_em10;
  77.  
  78. nxttok()
  79. {
  80.     register struct tok *t;
  81.     char *getname();
  82.     long getnum();
  83.     register int c;
  84.     double getfrac();
  85.  
  86.     t = &curtok;
  87.     t->name = curstr;
  88.     t->name[0] = 0;
  89.     t->prec = 0;
  90.     t->flags = 0;
  91. more:
  92.     c = mygetchar();
  93.     if (c == EOF) {
  94.         tk_flags = 0;
  95.         return 0;
  96.     }
  97.     if (c == '\n') {
  98.         tk_flags &= ~TK_ONLY1;
  99.         if ((tk_flags & TK_SEENL) == 0)
  100.             goto more;
  101.         t->tnum = NL;
  102.         t->name = "\n";
  103.         goto out;
  104.     }
  105.     if (tk_flags & TK_ONLY1)
  106.         goto more;
  107.     if (c <= ' ') {
  108.         if ((tk_flags & TK_SEEWS) == 0)
  109.             goto more;
  110.         t->tnum = WS;
  111.         t->name = " ";
  112.         goto out;
  113.     }
  114.     if (c >= '0' && c <= '9') {
  115.         t->tnum = ICON;
  116.         t->ival = getnum(c);
  117.         if (lookfrac(t->ival) || lookexp(t->ival,f_zero))
  118.             goto out;
  119.     moresuf:
  120.         c = mygetchar();
  121.         if (tolower(c) == 'l') {
  122.             t->flags |= SEE_L;
  123.             goto moresuf;
  124.         } else if (tolower(c) == 'u') {
  125.             t->flags |= SEE_U;
  126.             goto moresuf;
  127.         } else {
  128.             myungetc(c);
  129.         }
  130.         sprintf(curstr, "%ld",
  131.             t->ival);
  132.         goto out;
  133.     }
  134.     if (isalpha(c) || c == '_') {
  135.         t->tnum = ID;
  136.         t->name = getname(c);
  137.         goto out;
  138.     }
  139.     if (c == '.') {
  140.         c = mygetchar();
  141.         if (c >= '0' && c <= '9') {
  142.             gotfrac(0L, getfrac(c));
  143.             goto out;
  144.         } else {
  145.             myungetc(c);
  146.             matchop('.');
  147.             goto out;
  148.         }
  149.     }
  150.     if(matchop(c) == 0)
  151.         goto more;
  152. out:
  153.     if (debug) printf("<%s>", t->name);
  154.     tk_flags &= TK_SEENL;    /* all but SEENL are 1-shot */
  155.     return 1;
  156. }
  157.  
  158. long
  159. getnum(c)
  160. register int c;
  161. {
  162.     register long val = 0;
  163.     int base, i;
  164.  
  165.     if (c == '0') {
  166.         base = 8;
  167.     } else {
  168.         base = 10;
  169.         val = c - '0';
  170.     }
  171. more:
  172.     c = mygetchar();
  173.     if (c == EOF)
  174.         return val;
  175.     if (tolower(c) == 'x' && val == 0) {
  176.         base = 16;
  177.         goto more;
  178.     }
  179.     if (c >= '0' && c <= '9') {
  180.         val = base*val + (c - '0');
  181.         goto more;
  182.     }
  183.     if (base == 16 && (i = ishexa(c))) {
  184.         val = 16*val + i;
  185.         goto more;
  186.     }
  187.     myungetc(c);
  188.     return val;
  189. }
  190.  
  191. double
  192. getfrac(c)
  193. register c;
  194. {
  195.     register double val;
  196.     register double dig = f_tenth;
  197.  
  198.     val = dig * (c - '0');
  199. more:
  200.     c = mygetchar();
  201.     if (c >= '0' && c <= '9') {
  202.         dig = f_tenth * dig;
  203.         val += dig * (c - '0');
  204.         goto more;
  205.     }
  206.     myungetc(c);
  207.     return val;
  208. }
  209.  
  210. lookfrac(intpart)
  211. long intpart;
  212. {
  213.     int c;
  214.     double frac;
  215.  
  216.     c = mygetchar();
  217.     if (c != '.') {
  218.         myungetc(c);
  219.         return 0;
  220.     }
  221.     c = mygetchar();
  222.     if (c >= '0' && c <= '9') {
  223.         frac = getfrac(c);
  224.     } else {
  225.         myungetc(c);
  226.         frac = f_zero;
  227.     }
  228.     gotfrac(intpart, frac);
  229.     return 1;
  230. }
  231.  
  232. gotfrac(intpart, frac)
  233. long intpart;
  234. double frac;
  235. {
  236.     if (lookexp(intpart, frac) == 0)
  237.         makeflt(intpart, frac, 0);
  238. }
  239.  
  240. lookexp(intpart, frac)
  241. long intpart;
  242. double frac;
  243. {
  244.     int c;
  245.     int minus;
  246.     int exp;
  247.  
  248.     minus = 0;
  249.     c = mygetchar();
  250.     if (tolower(c) != 'e') {
  251.         myungetc(c);
  252.         return 0;
  253.     }
  254.     c = mygetchar();
  255.     if (c == '-') {
  256.         minus = 1;
  257.         c = mygetchar();
  258.     } else if (c == '+')
  259.         c = mygetchar();
  260.     if (c >= '0' && c <= '9') {
  261.         exp = getnum(c);
  262.     } else {
  263.         exp = 0;
  264.         myungetc(c);
  265.     }
  266.     if (minus)
  267.         exp = -exp;
  268.     makeflt(intpart, frac, exp);
  269.     return 1;
  270. }
  271.  
  272. makeflt(intpart, frac, exp)
  273. long intpart;
  274. double frac;
  275. {
  276.     register double val;
  277.     double mod, mod10;
  278.     register struct tok *t;
  279.  
  280.     val = intpart + frac;
  281.     if (exp > 0) {
  282.         mod = f_ten;
  283.         mod10 = f_e10;
  284.     } else if (exp < 0) {
  285.         mod = f_tenth;
  286.         mod10 = f_em10;
  287.         exp = -exp;
  288.     }
  289.     while (exp >= 10) {
  290.         val *= mod10;
  291.         exp -= 10;
  292.     }
  293.     while (exp--)
  294.         val *= mod;        /* slow and dirty */
  295.     t = &curtok;
  296.     t->tnum = FCON;
  297.     t->fval = val;
  298.     sprintf(t->name, FLTFORM, val);
  299. }
  300.  
  301. char *
  302. getname(c)
  303. register int c;
  304. {
  305.     register int nhave;
  306.  
  307.     nhave = 0;
  308.     do {
  309.         if (nhave < MAXSTR)
  310.             curstr[nhave++] = c;
  311.         c = mygetchar();
  312.     } while (isalnum(c) || c == '_');
  313.     myungetc(c);
  314.     curstr[nhave] = 0;
  315.     return curstr;
  316. }
  317.  
  318. static char *holdstr;
  319.  
  320. chr_push(s)
  321. char *s;
  322. {
  323.     holdstr = s;
  324. }
  325.  
  326. static int holdchar, xholdchar;
  327.  
  328. mygetchar()
  329. {
  330.     register int c;
  331.     int c2;
  332.  
  333.     if (holdchar) {
  334.         c = holdchar;
  335.         holdchar = 0;
  336.         goto out;
  337.     }
  338.     if (holdstr) {        /* used for -D args */
  339.         c = *holdstr++;
  340.         if (c == 0) {
  341.             holdstr = NULL;
  342.             return '\n';
  343.         }
  344.         return c;
  345.     }
  346.  
  347. retry:
  348.     c = xgetc();
  349.     if (c == EOF) {
  350.         if (endfile())
  351.             goto retry;
  352.     } else if (c == '\\') {        /* ansi handling of backslash nl */
  353.         c2 = xgetc();
  354.         if (c2 == '\n') {
  355.             lineno++;
  356.             goto retry;
  357.         } else
  358.             xholdchar = c2;
  359.     }
  360. out:
  361.     if (c == '\n') {
  362.         sawnl++;    /* for pre.c */
  363.         lineno++;
  364.     }
  365.     return c;
  366. }
  367.  
  368. xgetc()
  369. {
  370.     register int c;
  371.  
  372.     if (xholdchar) {
  373.         c = xholdchar;
  374.         xholdchar = 0;
  375.         return c;
  376.     }
  377. #if CC68|dLibs
  378.     if (input == stdin)    /* bypass stupid input */
  379.         c = hackgetc();
  380.     else
  381. #endif
  382.         c = getc(input);
  383.     if (c != EOF)
  384.         c &= 0x7f;
  385.     return c;
  386. }
  387.  
  388. myungetc(c)
  389. char c;
  390. {
  391.     if (c != EOF)
  392.         holdchar = c;
  393.     if (c == '\n')
  394.         lineno--;
  395. }
  396.  
  397. struct op {
  398.     char *name;
  399.     char *asname;
  400.     int flags;
  401.     char prec;
  402.     char value;
  403. } ops[] = {
  404.     {"{"},
  405.     {"}"},
  406.     {"["},
  407.     {"]"},
  408.     {"("},
  409.     {")"},
  410.     {"#"},
  411.     {"\\"},
  412.     {";"},
  413.     {","},
  414.     {":"},
  415.     {"."},
  416.  
  417.     {"\"", 0, SPECIAL},
  418.     {"'", 0, SPECIAL},
  419.  
  420.     {"==", 0, C_NOT_A, 5},
  421.     {"=", 0, 0},
  422.  
  423.     {"++", 0, CAN_U},
  424.     {"+", "+=", CAN_AS|C_AND_A, 2},
  425.  
  426.     {"--", 0, CAN_U},
  427.     {"->", 0, 0, 0, ARROW},
  428.     {"-", "-=", CAN_U|CAN_AS, 2},
  429.  
  430.     {"*", "*=", CAN_U|CAN_AS|C_AND_A, 1},
  431.     {"%", "%=", CAN_AS, 1},
  432.  
  433.     {"/*", 0, SPECIAL},
  434.     {"/", "/=", CAN_AS, 1},
  435.  
  436.     {"&&", 0, 0, 9},
  437.     {"&", "&=", CAN_U|CAN_AS|C_AND_A, 6},
  438.  
  439.     {"||", 0, 0, 10},
  440.     {"|", "|=", CAN_AS|C_AND_A, 8},
  441.  
  442.     {"!=", 0, C_NOT_A, 5, NOTEQ},
  443.     {"!", 0, CAN_U},
  444.  
  445.     {"~", 0, CAN_U},
  446.  
  447.     {"^", "^=", CAN_AS|C_AND_A, 7},
  448.  
  449.     {"<<", "<<=", CAN_AS, 3},
  450.     {"<=", 0, C_NOT_A, 4, LTEQ},
  451.     {"<", 0, SPECIAL|C_NOT_A, 4},
  452.  
  453.     {">>", ">>=", CAN_AS, 3},
  454.     {">=", 0, C_NOT_A, 4, GTEQ},
  455.     {">", 0, C_NOT_A, 4},
  456.  
  457.     {"?", 0, 0},
  458.  
  459.     {0, 0, 0}
  460. };
  461.  
  462. #define FIRST_C    '!'
  463. #define LAST_C    0177
  464. struct op *opstart[LAST_C-FIRST_C+1];
  465.  
  466. mo_init()
  467. {
  468.     register struct op *p;
  469.     register c;
  470.  
  471.     for (p=ops; p->name; p++) {
  472.         c = p->name[0];
  473.         if (opstart[c-FIRST_C] == 0)
  474.             opstart[c-FIRST_C] = p;
  475.     }
  476. }
  477.  
  478. matchop(c)
  479. {
  480.     register struct tok *t;
  481.     register struct op *p;
  482.     int nxt;
  483.     int value;
  484.     static first = 0;
  485.  
  486.     t = &curtok;
  487.     nxt = mygetchar();
  488.     value = c;
  489.     if (first == 0) {
  490.         mo_init();
  491.         first = 1;
  492.     }
  493.     p = opstart[c-FIRST_C];
  494.     if (p)
  495.     for (; p->name; p++)
  496.         if (p->name[0] == c)
  497.             if (p->name[1] == 0 || p->name[1] == nxt) {
  498.                 if (p->name[1] == 0)
  499.                     myungetc(nxt);
  500.                 else {
  501.                     value = p->value ? p->value :
  502.                         DOUBLE value;
  503.                 }
  504.                 if (p->flags & SPECIAL)
  505.                     if (c != '<' || 
  506.                       tk_flags & TK_LTSTR)
  507.                         return dospec(p);
  508.                 t->flags = p->flags;
  509.                 if (p->flags & CAN_AS) {
  510.                     nxt = mygetchar();
  511.                     if (nxt != '=') {
  512.                         myungetc(nxt);
  513.                     } else {
  514.                         value = ASSIGN value;
  515.                         t->flags = 0;
  516.                     }
  517.                 }
  518.                 t->name = isassign(value)?p->asname:p->name;
  519.                 t->tnum = value;
  520.                 t->prec = isassign(value)? 0 : p->prec;
  521.                 return 1;
  522.             }
  523.     myungetc(nxt);
  524.     t->name = "???";
  525.     t->tnum = BADTOK;
  526.     return 0;
  527. }
  528.  
  529. dospec(p)
  530. struct op *p;
  531. {
  532.     register struct tok *t;
  533.     register int c;
  534.     int nhave;
  535.     int endc;
  536.  
  537.     t = &curtok;
  538.     switch (p->name[0]) {
  539.     case '/':        /* slash-star */
  540. look:
  541.         do {
  542.             c = mygetchar();
  543.         } while (c != '*');
  544.         c = mygetchar();
  545.         if (c == '/')
  546.             return 0;
  547.         myungetc(c);
  548.         goto look;
  549.     case '\'':
  550.         t->tnum = ICON;
  551.         t->ival = getschar('\''); /* allow only 1 for now*/
  552.         while (getschar('\'') != NOCHAR)
  553.             ;
  554.         sprintf(curstr, "%d", (int)t->ival);
  555.         return 1;
  556.     case '<':
  557.         endc = '>';
  558.         t->tnum = SCON2;
  559.         goto strs;
  560.     case '"':
  561.         endc = '"';
  562.         t->tnum = SCON;
  563.     strs:
  564.         t->name = curstr;
  565.         nhave = 0;
  566.         c = getschar(endc);
  567.         while (c != NOCHAR) {
  568.             if (c >= 0 && c <= 1 && nhave < MAXSTR) {
  569.                  /* allow null */
  570.                 curstr[nhave++] = 1;
  571.                 c++;
  572.             }
  573.             if (nhave < MAXSTR)
  574.                 curstr[nhave++] = c;
  575.             c = getschar(endc);
  576.         }
  577.         curstr[nhave] = 0;
  578.         return 1;
  579.     }
  580. }
  581.  
  582. getoct(c)
  583. {
  584.     char n, i;
  585.  
  586.     n = c - '0';
  587.     for (i=1; i < 3; i++) {
  588.         c = mygetchar();
  589.         if (c < '0' || c > '7') {
  590.             myungetc(c);
  591.             return (int)n;
  592.         }
  593.         n = 8*n + (c - '0');
  594.     }
  595.     return (int)n;
  596. }
  597.     
  598. getschar(del)
  599. char del;
  600. {
  601.     register int c;
  602.  
  603. more:
  604.     c = mygetchar();
  605.     if (c == del)
  606.         return NOCHAR;
  607.     if (c == '\n') {
  608.         error("nl in string");
  609.         myungetc(c);
  610.         return NOCHAR;
  611.     }
  612.     if (c == '\\' && (tk_flags & TK_NOESC) == 0) {
  613.         c = mygetchar();
  614.         if (c == del)
  615.             return c;
  616.         if (c >= '0' && c <= '7')
  617.             return getoct(c);
  618.         switch (c) {
  619. /*
  620.         case '\n':
  621.             goto more;
  622. */
  623.         case 'b':
  624.             c = '\b';
  625.             break;
  626.         case 'n':
  627.             c = '\n';
  628.             break;
  629.         case 't':
  630.             c = '\t';
  631.             break;
  632.         case 'r':
  633.             c = '\r';
  634.             break;
  635.         case 'f':
  636.             c = '\f';
  637.             break;
  638.         }
  639.     }
  640.     return c;
  641. }
  642.  
  643. #if !dLibs
  644.  
  645. isalpha(c)
  646. register char c;
  647. {
  648.     if ((c>='a' && c<='z') ||
  649.         (c>='A' && c<='Z'))
  650.         return 1;
  651.     return 0;
  652. }
  653.  
  654. isalnum(c)
  655. register char c;
  656. {
  657.     return (isalpha(c) || (c>='0' && c<='9'));
  658. }
  659.  
  660. tolower(c)
  661. register char c;
  662. {
  663.     if (c>='A' && c<='Z')
  664.         c += 'a'-'A';
  665.     return c;
  666. }
  667.  
  668. #endif
  669.  
  670. ishexa(c)
  671. register char c;
  672. {
  673.     if (c>='a' && c<='f')
  674.         return (c-'a'+10);
  675.     if (c>='A' && c<='F')
  676.         return (c-'A'+10);
  677.     return 0;
  678. }
  679.  
  680. #if CC68
  681. hackgetc()
  682. {
  683.     register int c;
  684.  
  685.     c = bios(2,2);
  686.     switch (c) {
  687.     case 4:
  688.         return EOF;
  689.     case '\r':
  690.     case '\n':
  691.         bios(3,2,'\r');
  692.         bios(3,2,'\n');
  693.         return '\n';
  694.     }
  695.     bios(3,2,c);
  696.     return c;
  697. }
  698. #endif
  699.  
  700. #if dLibs
  701. hackgetc()
  702. {
  703.     register int c;
  704.  
  705.     c = getchar();
  706.     switch (c) {
  707.     case 4:
  708.         return EOF;
  709.     case '\n':
  710.         putchar('\n');
  711.         break;
  712.     }
  713.     return c;
  714. }
  715. #endif
  716.