home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- *
- * tok.c
- *
- * Basic level token routines
- *
- * At this level, we return the following things:
- * id's - strings of alpha-alnum
- * integer constants
- * float constants
- * string constants
- * multi-char tokens
- *
- * We DONT know about:
- * keywords
- * #defined id's
- * any other meaning of a name
- *
- * Interface:
- * call nxttok() to get next token
- * look at 'curtok' for current token
- * note that curtok.name points to a static area
- * for ID or SCON
- *
- * if EOF is seen, we call endfile() before
- * giving up
- *
- * Special flags: (tk_flags)
- * These special flags are needed for the pre-processor.
- * All but TK_SEENL are 1-shot.
- *
- * TK_SEENL - want to see \n
- * TK_WS - want to see white space (for #define)
- * TK_NOESC - dont do '\' escapes in strings
- * TK_LTSTR - '<' is a string starter
- * TK_ONLY1 - skip to token after \n (for #if--)
- */
-
- #include <stdio.h>
- #include "param.h"
- #include "tok.h"
-
- #if dLibs
- #include <ctype.h>
- #endif
-
- struct tok curtok;
- char curstr[MAXSTR+1];
-
- #define TK_SEENL 1 /* want to see NL token */
- #define TK_SEEWS 2 /* want to see WS token */
- #define TK_ONLY1 4 /* only want 1st token on line */
- #define TK_LTSTR 8 /* '<' starts a string */
- #define TK_NOESC 16 /* dont do '\' escapes in string */
-
- int tk_flags, sawnl;
-
- extern FILE *input;
- extern int lineno;
-
- #define NOCHAR 0x100
-
- #ifdef DEBUG
- extern int oflags[];
- #define debug oflags['b'-'a']
- #endif
-
- nxttok()
- {
- register struct tok *t;
- char *getname();
- long getnum();
- register int c;
- double getfrac();
-
- t = &curtok;
- t->name = curstr;
- t->name[0] = 0;
- t->prec = 0;
- t->flags = 0;
- more:
- c = mygetchar();
- if (c == EOF) {
- tk_flags = 0;
- return 0;
- }
- if (c == '\n') {
- tk_flags &= ~TK_ONLY1;
- if ((tk_flags & TK_SEENL) == 0)
- goto more;
- t->tnum = NL;
- t->name = "\n";
- goto out;
- }
- if (tk_flags & TK_ONLY1)
- goto more;
- if (c <= ' ') {
- if ((tk_flags & TK_SEEWS) == 0)
- goto more;
- t->tnum = WS;
- t->name = " ";
- goto out;
- }
- if (c >= '0' && c <= '9') {
- t->tnum = ICON;
- t->ival = getnum(c);
- if (lookfrac(t->ival) || lookexp(t->ival,0.0))
- goto out;
- moresuf:
- c = mygetchar();
- if (tolower(c) == 'l') {
- t->flags |= SEE_L;
- goto moresuf;
- } else if (tolower(c) == 'u') {
- t->flags |= SEE_U;
- goto moresuf;
- } else {
- myungetc(c);
- }
- sprintf(curstr, "%ld",
- t->ival);
- goto out;
- }
- if (isalpha(c) || c == '_') {
- t->tnum = ID;
- t->name = getname(c);
- goto out;
- }
- if (c == '.') {
- c = mygetchar();
- if (c >= '0' && c <= '9') {
- gotfrac(0L, getfrac(c));
- goto out;
- } else {
- myungetc(c);
- matchop('.');
- goto out;
- }
- }
- if(matchop(c) == 0)
- goto more;
- out:
- if (debug) printf("<%s>", t->name);
- tk_flags &= TK_SEENL; /* all but SEENL are 1-shot */
- return 1;
- }
-
- long
- getnum(c)
- register int c;
- {
- register long val = 0;
- int base, i;
-
- if (c == '0') {
- base = 8;
- } else {
- base = 10;
- val = c - '0';
- }
- more:
- c = mygetchar();
- if (c == EOF)
- return val;
- if (tolower(c) == 'x' && val == 0) {
- base = 16;
- goto more;
- }
- if (c >= '0' && c <= '9') {
- val = base*val + (c - '0');
- goto more;
- }
- if (base == 16 && (i = ishexa(c))) {
- val = 16*val + i;
- goto more;
- }
- myungetc(c);
- return val;
- }
-
- double
- getfrac(c)
- register c;
- {
- register double val;
- register double dig = 0.1;
-
- val = dig * (c - '0');
- more:
- c = mygetchar();
- if (c >= '0' && c <= '9') {
- dig = .1 * dig;
- val += dig * (c - '0');
- goto more;
- }
- myungetc(c);
- return val;
- }
-
- lookfrac(intpart)
- long intpart;
- {
- int c;
- double frac;
-
- c = mygetchar();
- if (c != '.') {
- myungetc(c);
- return 0;
- }
- c = mygetchar();
- if (c >= '0' && c <= '9') {
- frac = getfrac(c);
- } else {
- myungetc(c);
- frac = 0.0;
- }
- gotfrac(intpart, frac);
- return 1;
- }
-
- gotfrac(intpart, frac)
- long intpart;
- double frac;
- {
- if (lookexp(intpart, frac) == 0)
- makeflt(intpart, frac, 0);
- }
-
- lookexp(intpart, frac)
- long intpart;
- double frac;
- {
- int c;
- int minus;
- int exp;
-
- minus = 0;
- c = mygetchar();
- if (tolower(c) != 'e') {
- myungetc(c);
- return 0;
- }
- c = mygetchar();
- if (c == '-') {
- minus = 1;
- c = mygetchar();
- } else if (c == '+')
- c = mygetchar();
- if (c >= '0' && c <= '9') {
- exp = getnum(c);
- } else {
- exp = 0;
- myungetc(c);
- }
- if (minus)
- exp = -exp;
- makeflt(intpart, frac, exp);
- return 1;
- }
-
- makeflt(intpart, frac, exp)
- long intpart;
- double frac;
- {
- register double val;
- double mod, mod10;
- register struct tok *t;
-
- val = intpart + frac;
- if (exp > 0) {
- mod = 1e1;
- mod10 = 1e10;
- } else if (exp < 0) {
- mod = 1e-1;
- mod10 = 1e-10;
- exp = -exp;
- }
- while (exp >= 10) {
- val *= mod10;
- exp -= 10;
- }
- while (exp--)
- val *= mod; /* slow and dirty */
- t = &curtok;
- t->tnum = FCON;
- t->fval = val;
- sprintf(t->name, FLTFORM, val);
- }
-
- char *
- getname(c)
- register int c;
- {
- register int nhave;
-
- nhave = 0;
- do {
- if (nhave < MAXSTR)
- curstr[nhave++] = c;
- c = mygetchar();
- } while (isalnum(c) || c == '_');
- myungetc(c);
- curstr[nhave] = 0;
- return curstr;
- }
-
- static char *holdstr;
-
- chr_push(s)
- char *s;
- {
- holdstr = s;
- }
-
- static int holdchar, xholdchar;
-
- mygetchar()
- {
- register int c;
- int c2;
-
- if (holdchar) {
- c = holdchar;
- holdchar = 0;
- goto out;
- }
- if (holdstr) { /* used for -D args */
- c = *holdstr++;
- if (c == 0) {
- holdstr = NULL;
- return '\n';
- }
- return c;
- }
-
- retry:
- c = xgetc();
- if (c == EOF) {
- if (endfile())
- goto retry;
- } else if (c == '\\') { /* ansi handling of backslash nl */
- c2 = xgetc();
- if (c2 == '\n') {
- lineno++;
- goto retry;
- } else
- xholdchar = c2;
- }
- out:
- if (c == '\n') {
- sawnl++; /* for pre.c */
- lineno++;
- }
- return c;
- }
-
- xgetc()
- {
- register int c;
-
- if (xholdchar) {
- c = xholdchar;
- xholdchar = 0;
- return c;
- }
- #if CC68|dLibs
- if (input == stdin) /* bypass stupid input */
- c = hackgetc();
- else
- #endif
- c = getc(input);
- if (c != EOF)
- c &= 0x7f;
- return c;
- }
-
- myungetc(c)
- char c;
- {
- if (c != EOF)
- holdchar = c;
- if (c == '\n')
- lineno--;
- }
-
- struct op {
- char *name;
- char *asname;
- int flags;
- char prec;
- char value;
- } ops[] = {
- {"{"},
- {"}"},
- {"["},
- {"]"},
- {"("},
- {")"},
- {"#"},
- {"\\"},
- {";"},
- {","},
- {":"},
- {"."},
-
- {"\"", 0, SPECIAL},
- {"'", 0, SPECIAL},
-
- {"==", 0, C_NOT_A, 5},
- {"=", 0, 0},
-
- {"++", 0, CAN_U},
- {"+", "+=", CAN_AS|C_AND_A, 2},
-
- {"--", 0, CAN_U},
- {"->", 0, 0, 0, ARROW},
- {"-", "-=", CAN_U|CAN_AS, 2},
-
- {"*", "*=", CAN_U|CAN_AS|C_AND_A, 1},
- {"%", "%=", CAN_AS, 1},
-
- {"/*", 0, SPECIAL},
- {"/", "/=", CAN_AS, 1},
-
- {"&&", 0, 0, 9},
- {"&", "&=", CAN_U|CAN_AS|C_AND_A, 6},
-
- {"||", 0, 0, 10},
- {"|", "|=", CAN_AS|C_AND_A, 8},
-
- {"!=", 0, C_NOT_A, 5, NOTEQ},
- {"!", 0, CAN_U},
-
- {"~", 0, CAN_U},
-
- {"^", "^=", CAN_AS|C_AND_A, 7},
-
- {"<<", "<<=", CAN_AS, 3},
- {"<=", 0, C_NOT_A, 4, LTEQ},
- {"<", 0, SPECIAL|C_NOT_A, 4},
-
- {">>", ">>=", CAN_AS, 3},
- {">=", 0, C_NOT_A, 4, GTEQ},
- {">", 0, C_NOT_A, 4},
-
- {"?", 0, 0},
-
- {0, 0, 0}
- };
-
- #define FIRST_C '!'
- #define LAST_C 0177
- struct op *opstart[LAST_C-FIRST_C+1];
-
- mo_init()
- {
- register struct op *p;
- register c;
-
- for (p=ops; p->name; p++) {
- c = p->name[0];
- if (opstart[c-FIRST_C] == 0)
- opstart[c-FIRST_C] = p;
- }
- }
-
- matchop(c)
- {
- register struct tok *t;
- register struct op *p;
- int nxt;
- int value;
- static first = 0;
-
- t = &curtok;
- nxt = mygetchar();
- value = c;
- if (first == 0) {
- mo_init();
- first = 1;
- }
- p = opstart[c-FIRST_C];
- if (p)
- for (; p->name; p++)
- if (p->name[0] == c)
- if (p->name[1] == 0 || p->name[1] == nxt) {
- if (p->name[1] == 0)
- myungetc(nxt);
- else {
- value = p->value ? p->value :
- DOUBLE value;
- }
- if (p->flags & SPECIAL)
- if (c != '<' ||
- tk_flags & TK_LTSTR)
- return dospec(p);
- t->flags = p->flags;
- if (p->flags & CAN_AS) {
- nxt = mygetchar();
- if (nxt != '=') {
- myungetc(nxt);
- } else {
- value = ASSIGN value;
- t->flags = 0;
- }
- }
- t->name = isassign(value)?p->asname:p->name;
- t->tnum = value;
- t->prec = isassign(value)? 0 : p->prec;
- return 1;
- }
- myungetc(nxt);
- t->name = "???";
- t->tnum = BADTOK;
- return 0;
- }
-
- dospec(p)
- struct op *p;
- {
- register struct tok *t;
- register int c;
- int nhave;
- int endc;
-
- t = &curtok;
- switch (p->name[0]) {
- case '/': /* slash-star */
- look:
- do {
- c = mygetchar();
- } while (c != '*');
- c = mygetchar();
- if (c == '/')
- return 0;
- myungetc(c);
- goto look;
- case '\'':
- t->tnum = ICON;
- t->ival = getschar('\''); /* allow only 1 for now*/
- while (getschar('\'') != NOCHAR)
- ;
- sprintf(curstr, "%d", (int)t->ival);
- return 1;
- case '<':
- endc = '>';
- t->tnum = SCON2;
- goto strs;
- case '"':
- endc = '"';
- t->tnum = SCON;
- strs:
- t->name = curstr;
- nhave = 0;
- c = getschar(endc);
- while (c != NOCHAR) {
- if (c >= 0 && c <= 1 && nhave < MAXSTR) {
- /* allow null */
- curstr[nhave++] = 1;
- c++;
- }
- if (nhave < MAXSTR)
- curstr[nhave++] = c;
- c = getschar(endc);
- }
- curstr[nhave] = 0;
- return 1;
- }
- }
-
- getoct(c)
- {
- char n, i;
-
- n = c - '0';
- for (i=1; i < 3; i++) {
- c = mygetchar();
- if (c < '0' || c > '7') {
- myungetc(c);
- return (int)n;
- }
- n = 8*n + (c - '0');
- }
- return (int)n;
- }
-
- getschar(del)
- char del;
- {
- register int c;
-
- more:
- c = mygetchar();
- if (c == del)
- return NOCHAR;
- if (c == '\n') {
- error("nl in string");
- myungetc(c);
- return NOCHAR;
- }
- if (c == '\\' && (tk_flags & TK_NOESC) == 0) {
- c = mygetchar();
- if (c == del)
- return c;
- if (c >= '0' && c <= '7')
- return getoct(c);
- switch (c) {
- /*
- case '\n':
- goto more;
- */
- case 'b':
- c = '\b';
- break;
- case 'n':
- c = '\n';
- break;
- case 't':
- c = '\t';
- break;
- case 'r':
- c = '\r';
- break;
- case 'f':
- c = '\f';
- break;
- }
- }
- return c;
- }
-
- #if !dLibs
-
- isalpha(c)
- register char c;
- {
- if ((c>='a' && c<='z') ||
- (c>='A' && c<='Z'))
- return 1;
- return 0;
- }
-
- isalnum(c)
- register char c;
- {
- return (isalpha(c) || (c>='0' && c<='9'));
- }
-
- tolower(c)
- register char c;
- {
- if (c>='A' && c<='Z')
- c += 'a'-'A';
- return c;
- }
-
- #endif
-
- ishexa(c)
- register char c;
- {
- if (c>='a' && c<='f')
- return (c-'a'+10);
- if (c>='A' && c<='F')
- return (c-'A'+10);
- return 0;
- }
-
- #if CC68
- hackgetc()
- {
- register int c;
-
- c = bios(2,2);
- switch (c) {
- case 4:
- return EOF;
- case '\r':
- case '\n':
- bios(3,2,'\r');
- bios(3,2,'\n');
- return '\n';
- }
- bios(3,2,c);
- return c;
- }
- #endif
-
- #if dLibs
- hackgetc()
- {
- register int c;
-
- c = getchar();
- switch (c) {
- case 4:
- return EOF;
- case '\n':
- putchar('\n');
- break;
- }
- return c;
- }
- #endif
-