123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* L E X I C A L A N A L Y Z E R */
- #include <string.h>
- #include "idfsize.h"
- #include "numsize.h"
- #include "strsize.h"
- #include <alloc.h>
- #include "input.h"
- #include "idf.h"
- #include "LLlex.h"
- #include "Lpars.h"
- #include "class.h"
- #include "bits.h"
- /* Data about the token yielded */
- struct token dot;
- int ReplaceMacros = 1; /* replacing macros */
- int AccFileSpecifier = 0; /* return filespecifier <...> */
- int AccDefined = 0; /* accept "defined(...)" */
- int UnknownIdIsZero = 0; /* interpret unknown id as integer 0 */
- char *string_token(char *nm, int stop_char);
- void skipcomment();
- void PushLex()
- {
- DOT = 0;
- }
- void PopLex()
- {}
- int LLlex()
- {
- return (DOT != EOF) ? GetToken(&dot) : EOF;
- }
- #define BUFSIZ 1024
- int GetToken(struct token *ptok)
- {
- char buf[BUFSIZ];
- register int c, nch;
- again: /* rescan the input after an error or replacement */
- LoadChar(c);
- if ((c & 0200) && c != EOI)
- fatal("non-ascii '\\%03o' read", c & 0377);
- switch (class(c)) { /* detect character class */
- case STNL:
- LineNumber++;
- return ptok->tk_symb = EOF;
- case STSKIP:
- goto again;
- case STGARB: /* garbage character */
- if (c == '\\') {
- /* a '\\' is allowed in #if/#elif expression */
- LoadChar(c);
- if (class(c) == STNL) { /* vt , ff ? */
- ++LineNumber;
- goto again;
- }
- PushBack();
- c = '\\';
- }
- if (040 < c && c < 0177)
- error("garbage char %c", c);
- else
- error("garbage char \\%03o", c);
- goto again;
- case STSIMP: /* a simple character, no part of compound token*/
- if (c == '/') { /* probably the start of comment */
- LoadChar(c);
- if (c == '*') { /* start of comment */
- skipcomment();
- goto again;
- }
- else {
- PushBack();
- c = '/'; /* restore c */
- }
- }
- return ptok->tk_symb = c;
- case STCOMP: /* maybe the start of a compound token */
- LoadChar(nch); /* character lookahead */
- switch (c) {
- case '!':
- if (nch == '=')
- return ptok->tk_symb = NOTEQUAL;
- PushBack();
- return ptok->tk_symb = c;
- case '&':
- if (nch == '&')
- return ptok->tk_symb = AND;
- PushBack();
- return ptok->tk_symb = c;
- case '<':
- if (AccFileSpecifier) {
- PushBack(); /* pushback nch */
- ptok->tk_str =
- string_token("file specifier", '>');
- return ptok->tk_symb = FILESPECIFIER;
- }
- if (nch == '<')
- return ptok->tk_symb = LEFT;
- if (nch == '=')
- return ptok->tk_symb = LESSEQ;
- PushBack();
- return ptok->tk_symb = c;
- case '=':
- if (nch != '=') {
- PushBack();
- error("missing =");
- }
- return ptok->tk_symb = EQUAL;
- case '>':
- if (nch == '=')
- return ptok->tk_symb = GREATEREQ;
- if (nch == '>')
- return ptok->tk_symb = RIGHT;
- PushBack();
- return ptok->tk_symb = c;
- case '|':
- if (nch == '|')
- return ptok->tk_symb = OR;
- PushBack();
- return ptok->tk_symb = c;
- }
- case STIDF:
- {
- extern int idfsize; /* ??? */
- register char *tg = &buf[0];
- register char *maxpos = &buf[idfsize];
- register struct idf *idef;
- #define tstmac(bx) if (!(bits[c] & bx)) goto nomac
- #define cpy if (Unstacked) EnableMacros(); *tg++ = c
- #define load LoadChar(c); if (!in_idf(c)) goto endidf
- #ifdef DOBITS
- cpy; tstmac(bit0); load;
- cpy; tstmac(bit1); load;
- cpy; tstmac(bit2); load;
- cpy; tstmac(bit3); load;
- cpy; tstmac(bit4); load;
- cpy; tstmac(bit5); load;
- cpy; tstmac(bit6); load;
- cpy; tstmac(bit7); load;
- #endif
- for(;;) {
- if (tg < maxpos) {
- cpy;
- }
- load;
- }
- endidf:
- PushBack();
- *tg = '\0'; /* mark the end of the identifier */
- if (ReplaceMacros) {
- idef = findidf(buf);
- if ((idef && idef->id_macro && replace(idef))) {
- goto again;
- }
- }
- nomac:
- LoadChar(c);
- while (in_idf(c)) {
- if (tg < maxpos) *tg++ = c;
- LoadChar(c);
- }
- PushBack();
- *tg++ = '\0'; /* mark the end of the identifier */
- if (UnknownIdIsZero) {
- ptok->tk_val = 0;
- return ptok->tk_symb = INTEGER;
- }
- ptok->tk_str = Malloc(tg - buf);
- strcpy(ptok->tk_str, buf);
- return ptok->tk_symb = IDENTIFIER;
- }
- case STCHAR: /* character constant */
- {
- register arith val = 0;
- register int size = 0;
- LoadChar(c);
- if (c == '\'')
- error("character constant too short");
- else
- while (c != '\'') {
- if (c == '\n') {
- error("newline in character constant");
- PushBack();
- break;
- }
- if (c == '\\') {
- LoadChar(c);
- if (c == '\n') {
- LineNumber++;
- }
- c = quoted(c);
- }
- if (c >= 128) c -= 256;
- val = val*256 + c;
- size++;
- LoadChar(c);
- }
- if (size > sizeof(arith))
- error("character constant too long");
- ptok->tk_val = val;
- return ptok->tk_symb = INTEGER;
- }
- case STNUM:
- {
- register char *np = &buf[1];
- register int base = 10;
- register int vch;
- register arith val = 0;
- if (c == '0') {
- *np++ = c;
- LoadChar(c);
- if (c == 'x' || c == 'X') {
- base = 16;
- LoadChar(c);
- }
- else
- base = 8;
- }
- while (vch = val_in_base(c, base), vch >= 0) {
- val = val*base + vch;
- if (np < &buf[NUMSIZE])
- *np++ = c;
- LoadChar(c);
- }
- if (c == 'l' || c == 'L')
- LoadChar(c);
- PushBack();
- ptok->tk_val = val;
- return ptok->tk_symb = INTEGER;
- }
- case STSTR:
- ptok->tk_str = string_token("string", '"');
- return ptok->tk_symb = STRING;
- case STEOI: /* end of text on source file */
- return ptok->tk_symb = EOF;
- default:
- crash("Impossible character class");
- }
- /*NOTREACHED*/
- return 0;
- }
- void skipcomment()
- {
- register int c;
- NoUnstack++;
- LoadChar(c);
- do {
- while (c != '*') {
- if (class(c) == STNL)
- ++LineNumber;
- else
- if (c == EOI) {
- NoUnstack--;
- return;
- }
- LoadChar(c);
- }
- /* Last Character seen was '*' */
- LoadChar(c);
- } while (c != '/');
- NoUnstack--;
- }
- char *string_token(char *nm, int stop_char)
- {
- register int c;
- register unsigned int str_size;
- register char *str = Malloc(str_size = ISTRSIZE);
- register int pos = 0;
-
- LoadChar(c);
- while (c != stop_char) {
- if (c == '\n') {
- error("newline in %s", nm);
- PushBack();
- break;
- }
- if (c == EOI) {
- error("end-of-file inside %s", nm);
- break;
- }
- if (c == '\\') {
- LoadChar(c);
- if (c == '\n') {
- LineNumber++;
- LoadChar(c);
- continue;
- }
- c = quoted(c);
- }
- str[pos++] = c;
- if (pos == str_size)
- str = Realloc(str, str_size <<= 1);
- LoadChar(c);
- }
- str[pos++] = '\0'; /* for filenames etc. */
- str = Realloc(str, pos);
- return str;
- }
- int quoted(int c)
- {
- /* quoted() replaces an escaped character sequence by the
- character meant.
- */
- /* first char after backslash already in c */
- if (!is_oct(c)) { /* a quoted char */
- switch (c) {
- case 'n':
- c = '\n';
- break;
- case 't':
- c = '\t';
- break;
- case 'b':
- c = '\b';
- break;
- case 'r':
- c = '\r';
- break;
- case 'f':
- c = '\f';
- break;
- }
- }
- else { /* a quoted octal */
- register int oct = 0, cnt = 0;
- do {
- oct = oct*8 + (c-'0');
- LoadChar(c);
- } while (is_oct(c) && ++cnt < 3);
- PushBack();
- c = oct;
- }
- return c&0377;
- }
- /* provisional */
- int val_in_base(int c, int base)
- {
- return
- is_dig(c) ? c - '0' :
- base != 16 ? -1 :
- is_hex(c) ? (c - 'a' + 10) & 017 :
- -1;
- }
|