home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / language / sozobon2 / tok.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-23  |  11.4 KB  |  714 lines

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