This is token.c in view mode; [Download] [Up]
/* File : Token.c Author : Richard A. O'Keefe Modified by : Deeporn H. Beardsley & Saumya Debray Updated : Summer 1988 Purpose : Tokenizer for SB-Prolog. */ #ifdef vms #include stdio #else #include <stdio.h> #endif /* stuff defined to interface with SB-Prolog */ #include "builtin.h" #include <errno.h> /* We used to use an 8-bit character set under VMS, but 7-bit ASCII * elsewhere. Now that DIS 8859/1 exists (a draft international * standard for an 8-bit extension of ASCII) we use that, and we are * in luck: it is almost identical to the VMS character set. */ #define AlphabetSize 256 #define SBPMAXINT 268435455 extern char *strcpy(/* CHAR_PTR, CHAR_PTR */); #define StrCpy(dst, src) (void)strcpy(dst, src) #define Printf (void)printf #define Sprintf (void)sprintf #define Fprintf (void)fprintf #define InRange(X,L,U) ((unsigned)((X)-(L)) <= (unsigned)((U)-(L))) #define IsLayout(X) InRange(InType(X), SPACE, EOLN) /* VERY IMPORTANT NOTE: I assume that the stdio library returns the value * EOF when character input hits the end of the file, and that this value * is actually the integer -1. You will note the DigVal(), InType(), and * OuType() macros below, and there is a ChType() macro used in crack(). * They all depend on this assumption. */ #define DIGIT 0 /* 0 .. 9 */ #define BREAK 1 /* _ */ #define UPPER 2 /* A .. Z */ #define LOWER 3 /* a .. z */ #define SIGN 4 /* -/+*<=>#@$\^&~`:.? */ #define NOBLE 5 /* !; (don't form compounds) */ #define PUNCT 6 /* (),[]|{}% */ #define ATMQT 7 /* ' (atom quote) */ #define LISQT 8 /* " (list quote) */ #define STRQT 9 /* $ (string quote) */ #define CHRQT 10 /* ` (character quote, maybe) */ #define TILDE 11 /* ~ (like character quote but buggy) */ #define SPACE 12 /* layout and control chars */ #define EOLN 13 /* line terminators ^J ^L */ #define REALO 14 /* floating point number */ #define EOFCH 15 /* end of file */ #define ALPHA DIGIT /* any of digit, break, upper, lower */ #define BEGIN BREAK /* atom left-paren pair */ #define ENDCL EOLN /* end of clause token */ #define RREAL 16 /* radix number(real) - overflowed */ #define RDIGIT 17 /* radix number(int) */ #define InType(c) (intab.chtype+1)[c] #define DigVal(c) (digval+1)[c] BYTE outqt[EOFCH+1]; struct CHARS { int eolcom; /* End-of-line comment, default % */ int endeol; /* early terminator of eolcoms, default none */ int begcom; /* In-line comment start, default / */ int astcom; /* In-line comment second, default * */ int endcom; /* In-line comment finish, default / */ int radix; /* Radix character, default ' */ int dpoint; /* Decimal point, default . */ int escape; /* String escape character, default \ */ int termin; /* Terminates a clause */ CHAR chtype[AlphabetSize+1]; }; struct CHARS intab = /* Special character table */ { '%', /* eolcom: end of line comments */ -1, /* endeol: early end for eolcoms */ '/', /* begcom: in-line comments */ '*', /* astcom: in-line comments */ '/', /* endcom: in-line comments */ '\'', /* radix : radix separator */ '.', /* dpoint: decimal point */ -1, /* escape: string escape character */ '.', /* termin: ends clause, sign or solo */ { EOFCH, /* really the -1th element of the table: */ /* ^@ ^A ^B ^C ^D ^E ^F ^G */ SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, /* ^H ^I ^J ^K ^L ^M ^N ^O */ SPACE, SPACE, EOLN, SPACE, EOLN, SPACE, SPACE, SPACE, /* ^P ^Q ^R ^S ^T ^U ^V ^W */ SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */ SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, /* sp ! " # $ % & ' */ SPACE, NOBLE, LISQT, SIGN, LOWER, PUNCT, SIGN, ATMQT, /* ( ) * + , - . / */ PUNCT, PUNCT, SIGN, SIGN, PUNCT, SIGN, SIGN, SIGN, /* 0 1 2 3 4 5 6 7 */ DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, /* 8 9 : ; < = > ? */ DIGIT, DIGIT, SIGN, PUNCT, SIGN, SIGN, SIGN, SIGN, /* @ A B C D E F G */ SIGN, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, /* H I J K L M N O */ UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, /* P Q R S T U V W */ UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, /* X Y Z [ \ ] ^ _ */ UPPER, UPPER, UPPER, PUNCT, SIGN, PUNCT, SIGN, BREAK, /* ` a b c d e f g */ SIGN, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, /* h i j k l m n o */ LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, /* p q r s t u v w */ LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, /* x y z { | } ~ ^? */ LOWER, LOWER, LOWER, PUNCT, PUNCT, PUNCT, SIGN, SPACE, /* 128 129 130 131 132 133 134 135 */ SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, /* 136 137 138 139 140 141 142 143 */ SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, /* 144 145 146 147 148 149 150 151 */ SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, /* 152 153 154 155 156 157 158 159 */ SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, /* NBSP !-inv cents pounds ching yen brobar section */ SPACE, SIGN, SIGN, SIGN, SIGN, SIGN, SIGN, SIGN, /* "accent copyr -a ord << nothook SHY (reg) ovbar */ SIGN, SIGN, LOWER, SIGN, SIGN, SIGN, SIGN, SIGN, /* degrees +/- super 2 super 3 - micron pilcrow - */ SIGN, SIGN, LOWER, LOWER, SIGN, SIGN, SIGN, SIGN, /* , super 1 -o ord >> 1/4 1/2 3/4 ?-inv */ SIGN, LOWER, LOWER, SIGN, SIGN, SIGN, SIGN, SIGN, /* `A 'A ^A ~A "A oA AE ,C */ UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, /* `E 'E ^E "E `I 'I ^I "I */ UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, /* ETH ~N `O 'O ^O ~O "O x times */ #ifdef vms UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, #else UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, SIGN, #endif /* /O `U 'U ^U "U 'Y THORN ,B */ UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, UPPER, LOWER, /* `a 'a ^a ~a "a oa ae ,c */ LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, /* `e 'e ^e "e `i 'i ^i "i */ LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, /* eth ~n `o 'o ^o ~o "o -:- */ #ifdef vms LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, #else LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, SIGN, #endif /* /o `u 'u ^u "u 'y thorn "y */ #ifdef vms LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, SPACE #else LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER, LOWER #endif } }; CHAR digval[AlphabetSize+1] = { 99, /* really the -1th element of the table */ /* ^@ ^A ^B ^C ^D ^E ^F ^G */ 99, 99, 99, 99, 99, 99, 99, 99, /* ^H ^I ^J ^K ^L ^M ^N ^O */ 99, 99, 99, 99, 99, 99, 99, 99, /* ^P ^Q ^R ^S ^T ^U ^V ^W */ 99, 99, 99, 99, 99, 99, 99, 99, /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */ 99, 99, 99, 99, 99, 99, 99, 99, /* sp ! " # $ % & ' */ 99, 99, 99, 99, 99, 99, 99, 99, /* ( ) * + , - . / */ 99, 99, 99, 99, 99, 99, 99, 99, /* 0 1 2 3 4 5 6 7 */ 0, 1, 2, 3, 4, 5, 6, 7, /* 8 9 : ; < = > ? */ 8, 9, 99, 99, 99, 99, 99, 99, /* @ A B C D E F G */ 99, 10, 11, 12, 13, 14, 15, 99, /* H I J K L M N O */ 99, 99, 99, 99, 99, 99, 99, 99, /* P Q R S T U V W */ 99, 99, 99, 99, 99, 99, 99, 99, /* X Y Z [ \ ] ^ _ */ 99, 99, 99, 99, 99, 99, 99, 0, /*NB*/ /* ` a b c d e f g */ 99, 10, 11, 12, 13, 14, 15, 99, /* h i j k l m n o */ 99, 99, 99, 99, 99, 99, 99, 99, /* p q r s t u v w */ 99, 99, 99, 99, 99, 99, 99, 99, /* x y z { | } ~ ^? */ 99, 99, 99, 99, 99, 99, 99, 99, /* 128 129 130 131 132 133 134 135 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 136 137 138 139 140 141 142 143 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 144 145 146 147 148 149 150 151 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 152 153 154 155 156 157 158 159 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 160 161 162 163 164 165 166 167 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 168 169 170(-a) 171 172 173 174 175 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 176 177 178(2) 179(3) 180 181 182 183 */ 99, 99, 2, 3, 99, 99, 99, 99, /* 184 185(1) 186(-o) 187 188 189 190 191 */ 99, 1, 99, 99, 99, 99, 99, 99, /* 192 193 194 195 196 197 198 199 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 200 201 202 203 204 205 206 207 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 208 209 210 211 212 213 214 215 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 216 217 218 219 220 221 222 223 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 224 225 226 227 228 229 230 231 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 232 233 234 235 236 237 238 239 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 240 241 242 243 244 245 246 247 */ 99, 99, 99, 99, 99, 99, 99, 99, /* 248 249 250 251 252 253 254 255 */ 99, 999, 99, 99, 99, 99, 99, 99 }; /* values returned to calling program */ #define SPECIAL 0 /* puncuation , ( ) [ ] ... */ #define VARO 1 /* type is a variable */ #define FUNC 2 /* type is atom( */ #define NUMBERO 3 /* type is a number */ #define ATOMO 4 /* type is an atom */ #define ENDCLS 5 /* END of clause but not file */ #define USCORE 6 /* underscore '_' */ #define SEMI 7 /* ; */ #define BADEND 8 /* END of file, not end of clause */ #define STRING 9 /* type is a char string */ int cNUMERO = 0, cATOMO = 0, cFUNC = 0, cVARO = 0, cUSCORE = 0, cSTRING = 0, cSPECIAL = 0, cSEMI = 0, cENDCLS = 0, cENDPRG = 0; extern LONG_PTR insert(); static BYTE perm = PERM; extern FILE *curr_in, *curr_out; /* current input, output streams */ void SyntaxError(message) CHAR_PTR message; { Fprintf(stderr, "Syntax error: %s\n", message); exit(1); } /* GetToken() reads a single token from the input stream and returns * its type, which is one of * DIGIT -- a number * BEGIN -- an atom( pair * LOWER -- an atom * UPPER -- a variable * PUNCT -- a single punctuation mark * LISQT -- a quoted list of character codes * STRQT -- a quoted string * ENDCL -- end of clause (normally '.\n'). * EOFCH -- signifies end-of-file. * RREAL -- a real, from some radix notation, in double_v. * RDIGIT -- an integer, from some radix notation, in rad_int. * In all cases except the last, the text of the token is in AtomStr. * There are two questions: between which pairs of adjacent tokens is * a space (a) necessary, (b) desirable? There is an additional * dummy token type used by the output routines, namely * NOBLE -- extra space is definitely not needed. * I leave it as an exercise for the reader to answer question (a). * Since this program is to produce output I find palatable (even if * it isn't exactly what I'd write myself), extra spaces are ok. In * fact, the main use of this program is as an editor command, so it * is normal to do a bit of manual post-processing. Question (b) is * the one to worry about then. My answer is that a space is never * written * - after PUNCT ( [ { | * - before PUNCT ) ] } | , <ENDCL> * is written after comma only sometimes, and is otherwise always * written. The variable lastput thus takes these values: * ALPHA -- put a space except before PUNCT * SIGN -- as alpha, but different so ENDCL knows to put a space. * NOBLE -- don't put a space * ENDCL -- just ended a clause * EOFCH -- at beginning of file */ int lastc = ' '; /* previous character */ #define MaxStrLen 1000 BYTE AtomStr[MaxStrLen+20]; LONG list_p; int rtnint; double double_v; LONG rad_int; CHAR tok2long[] = "token too long"; CHAR eofinrem[] = "end of file in comment"; CHAR badexpt[] = "bad exponent"; CHAR badradix[] = "radix > 36"; /* read_character(FILE* card, BYTE q) * reads one character from a quoted atom, list, string, or character. * Doubled quotes are read as single characters, otherwise a * quote is returned as -1 and lastc is set to the next character. * If the input syntax has character escapes, they are processed. * Note that many more character escape sequences are accepted than * are generated. There is a divergence from C: \xhh sequences are * two hexadecimal digits long, not three. * Note that the \c and \<space> sequences combine to make a pretty * way of continuing strings. Do it like this: * "This is a string, which \c * \ has to be continued over \c * \ several lines.\n". */ int read_character(card, q) register FILE *card; register int q; { register int c; c = getc(card); BACK: if (c < 0) { DOERR: if (q < 0) SyntaxError("end of file in character constant"); else { CHAR message[80]; Sprintf(message, "end of file in %cquoted%c constant", q, q); SyntaxError(message); } } if (c == q) { c = getc(card); if (c == q) return c; lastc = c; return -1; } else if (c != intab.escape) return c; /* If we get here, we have read the "\" of an escape sequence */ c = getc(card); switch (c) { case EOF: clearerr(curr_in); goto DOERR; case 'n': case 'N': /* newline */ return 10; case 't': case 'T': /* tab */ return 9; case 'r': case 'R': /* reeturn */ return 13; case 'v': case 'V': /* vertical tab */ return 11; case 'b': case 'B': /* backspace */ return 8; case 'f': case 'F': /* formfeed */ return 12; case 'e': case 'E': /* escape */ return 27; case 'd': case 'D': /* delete */ return 127; case 's': case 'S': /* space */ return 32; case 'a': case 'A': /* alarm */ return 7; case '^': /* control */ c = getc(card); if (c < 0) goto DOERR; return (c == '?' ? 127 : c&31); case 'c': case 'C': /* continuation */ while (IsLayout(c = getc(card))) ; goto BACK; case 'x': case 'X': /* hexadecimal */ { int i, n; for (n = 0, i = 2; --i >= 0; n = (n<<4) + DigVal(c)) if (DigVal(c = getc(card)) >= 16) { if (c < 0) goto DOERR; (void)ungetc(c, card); break; } return (n & 255); } case 'o': case 'O': /* octal */ c = getc(card); if (DigVal(c) >= 8) { if (c < 0) goto DOERR; (void)ungetc(c, card); return 0; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int i, n; for (n = c-'0', i = 2; --i >= 0; n = (n<<3) + DigVal(c)) if (DigVal(c = getc(card)) >= 8) { if (c < 0) goto DOERR; (void)ungetc(c, card); break; } return (n & 255); } default: if (!IsLayout(c)) return c; c = getc(card); goto BACK; } } /* com0plain(card, endeol) * These comments have the form * <eolcom> <char>* <newline> {PUNCT} * or <eolcom><eolcom> <char>* <newline> {SIGN } * depending on the classification of <eolcom>. Note that we could * handle ADA comments with no trouble at all. There was a Pop-2 * dialect which had end-of-line comments using "!" where the comment * could also be terminated by "!". You could obtain the effect of * including a "!" in the comment by doubling it, but what you had * then was of course two comments. The endeol parameter of this * function allows the handling of comments like that which can be * terminated either by a new-line character or an <endeol>, whichever * comes first. For ordinary purposes, endeol = -1 will do fine. * When this is called, the initial <eolcom>s have been consumed. * We return the first character after the comment. * If the end of the source file is encountered, we do not treat it * as an error, but quietly close the comment and return EOF as the * "FOLLOWing" character. */ int com0plain(card, endeol) register FILE *card; /* source file */ register int endeol; /* The closing character "!" */ { register int c; while ((c = getc(card)) >= 0 && c != '\n' && c != endeol) ; if (c >= 0) c = getc(card); return c; } /* The states in the next two functions are * 0 - after an uninteresting character * 1 - after an "astcom" * 2 - after a "begcom" * Assuming begcom = "(", astom = "#", endcom = ")", * com2plain will accept "(#)" as a complete comment. This can * be changed by initialising the state to 0 rather than 1. * The same is true of com2nest, which accepts "(#(#)#) as a * complete comment. Changing it would be rather harder. * Fixing the bug where the closing <astcom> is copied if it is * not an asterisk may entail rejecting "(#)". */ /* com2plain(card, astcom, endcom) * handles PL/I-style comments, that is, comments which begin with * a pair of characters <begcom><astcom> and end with a pair of * chracters <astcom><endcom>, where nesting is not allowed. For * example, if we take begcom='(', astcom='*', endcom=')' as in * Pascal, the comment "(* not a (* plain *)^ comment *) ends at * the "^". * For this kind of comment, it is perfectly sensible for any of * the characters to be equal. For example, if all three of the * bracket characters are "#", then "## stuff ##" is a comment. * When this is called, the initial <begcom><astcom> has been consumed. */ void com2plain(card, astcom, endcom) register FILE *card; /* source file */ int astcom; /* The asterisk character "*" */ int endcom; /* The closing character "/" */ { register int c; register int state; for (state = 0; (c = getc(card)) >= 0; ) { if (c == endcom && state) break; state = c == astcom; } if (c < 0) SyntaxError(eofinrem); } int GetToken() { register FILE *card = curr_in; register BYTE_PTR s = AtomStr; register int c, d; register int n = MaxStrLen; LONG oldv = 0, newv = 0; LONG_PTR newpair, list_head, stack_top; c = lastc; START: switch (InType(c)) { case DIGIT: /* The FOLLOWing kinds of numbers exist: * (1) unsigned decimal integers: d+ * (2) unsigned based integers: d+Ro+[R] * (3) unsigned floats: d* [. d*] [e +/-] d+ * (4) characters: 0Rc[R] * We allow underscores in numbers too, ignoring them. */ do { if (c != '_') *s++ = c; c = getc(card); } while (InType(c) <= BREAK); if (c == intab.radix) { *s = 0; for (d = 0, s = AtomStr; c = *s++; ) { d = d*10-'0'+c; if (d > 36) SyntaxError(badradix); } if (d == 0) { /* 0'c['] is a character code */ d = read_character(card, -1); Sprintf(AtomStr, "%d", d); d = getc(card); lastc = d == intab.radix ? getc(card) : d; return DIGIT; } while (c = getc(card), DigVal(c) < 99) if (c != '_') { oldv = newv; newv = newv*d + DigVal(c); if (newv < oldv || newv > SBPMAXINT) { Fprintf(stderr, "*** overflow in radix notation ***\n"); double_v = oldv*1.0*d + DigVal(c); while (c = getc(card), DigVal(c) < 99) if (c != '_') double_v = double_v*d + DigVal(c); if (c == intab.radix) c = getc(card); lastc = c; return RREAL; } } /* Sprintf(AtomStr, "%ld", newv); */ rad_int = newv; if (c == intab.radix) c = getc(card); lastc = c; return RDIGIT; } else if (c == intab.dpoint) { d = getc(card); if (InType(d) == DIGIT) { DECIMAL: *s++ = '.'; do { if (d != '_') *s++ = d; d = getc(card); } while (InType(d) <= BREAK); if ((d | 32) == 'e') { *s++ = 'E'; d = getc(card); if (d == '-') { *s++ = d; d = getc(card); } else if (d == '+') d = getc(card); if (InType(d) > BREAK) SyntaxError(badexpt); do { if (d != '_') *s++ = d; d = getc(card); } while (InType(d) <= BREAK); } c = d; *s = 0; lastc = c; return REALO; } else /* c has not changed */ ungetc(d, card); } *s = 0; lastc = c; return DIGIT; case BREAK: case UPPER: do { if (--n < 0) SyntaxError(tok2long); *s++ = c; c = getc(card); } while (InType(c) <= LOWER); *s = 0; lastc = c; rtnint = (int)(s - AtomStr); return UPPER; case LOWER: do { if (--n < 0) SyntaxError(tok2long); *s++ = c; c = getc(card); } while (InType(c) <= LOWER); *s = 0; SYMBOL: if (c == '(') { lastc = getc(card); rtnint = (int)(s - AtomStr); return BEGIN; } else { lastc = c; rtnint = (int)(s - AtomStr); return LOWER; } case SIGN: *s = c; d = getc(card); if (c == intab.begcom && d == intab.astcom) { ASTCOM: com2plain(card, d, intab.endcom); c = getc(card); goto START; } else if (c == intab.dpoint && InType(d) == DIGIT) { *s++ = '0'; goto DECIMAL; } while (InType(d) == SIGN) { if (--n == 0) SyntaxError(tok2long); *++s = d; d = getc(card); } *++s = 0; if (InType(d) >= SPACE && c == intab.termin && AtomStr[1] == 0) { lastc = d; return ENDCL; /* i.e. '.' FOLLOWed by layout */ } c = d; goto SYMBOL; case NOBLE: if (c == intab.termin) { *s = 0; lastc = ' '; return ENDCL; } else if (c == intab.eolcom) { c = com0plain(card, intab.endeol); goto START; } *s++ = c; *s = 0; lastc = c = getc(card); goto SYMBOL; case PUNCT: if (c == intab.termin) { *s = 0; lastc = ' '; return ENDCL; } else if (c == intab.eolcom) { c = com0plain(card, intab.endeol); goto START; } d = getc(card); if (c == intab.begcom && d == intab.astcom) goto ASTCOM; /* If we arrive here, c is an ordinary punctuation mark */ if (c == '(') /* need to distingusih between atom( and atom ( */ *s++ = ' '; lastc = d; *s++ = c; *s = 0; rtnint = (int)(s - AtomStr); return PUNCT; case CHRQT: /* `c[`] is read as an integer. * Eventually we should treat characters as a distinct * token type, so they can be generated on output. * If the character quote, atom quote, list quote, * or string quote is the radix character, we should * generate 0'x notation, otherwise `x`. */ d = read_character(card, -1); Sprintf(AtomStr, "%d", d); d = getc(card); lastc = d == c ? getc(card) : d; return DIGIT; case ATMQT: case STRQT: while ((d = read_character(card, c)) >= 0) { if (--n < 0) SyntaxError(tok2long); *s++ = d; } *s = 0; rtnint = (int) (s - AtomStr); c = lastc; goto SYMBOL; case LISQT: /* check for potential heap overflow */ /* (this will guarantee space for lists of up to 50 elements) */ stack_top = (breg < ereg) ? breg : ereg - ENV_SIZE(cpreg); if (stack_top < hreg + 100) { garbage_collection("GetToken"); if (stack_top < hreg + 100) /* still too full */ quit("Heap overflow\n"); } list_head = newpair = hreg; while ((d = read_character(card, c)) >= 0) { hreg += 2; *newpair++ = MAKEINT(d); *newpair++ = (LONG)hreg | LIST_TAG; } if (list_head == hreg) /* null string */ list_p = nil_sym; else { *(--newpair) = nil_sym; list_p = (LONG)list_head | LIST_TAG; } return LISQT; case EOLN: case SPACE: c = getc(card); goto START; case EOFCH: clearerr(curr_in); return EOFCH; } Fprintf(stderr, "Internal error: InType(%d)==%d\n", c, InType(c)); abort(); /* There is no way we can get here */ /*NOTREACHED*/ } void b_NEXT_TOKEN() { register LONG op; register LONG_PTR top; register FILE *card = curr_in; int i, atoi(), oldnum, newnum; int len; double atof(); LONG makefloat(), ptr; i = GetToken(); switch (i) { case LOWER: op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(ATOMO); ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG; op = reg[2]; DEREF(op); FOLLOW(op) = ptr; cATOMO++; break; case BEGIN: op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(FUNC); ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG; op = reg[2]; DEREF(op); FOLLOW(op) = ptr; cFUNC++; break; case UPPER: if (AtomStr[0] == '_' && AtomStr[1] == 0) { op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(USCORE); cUSCORE++; } else { op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(VARO); cVARO++; } if (rtnint > 256) { AtomStr[256] = 0; rtnint = 256; Fprintf(stderr, "*** Name of constant too long: %s\n", AtomStr); } ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG; op = reg[2]; DEREF(op); FOLLOW(op) = ptr; break; case REALO: op = reg[2]; DEREF(op); FOLLOW(op) = makefloat(atof(AtomStr)); op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(NUMBERO); cNUMERO++; break; case RREAL: op = reg[2]; DEREF(op); FOLLOW(op) = makefloat(double_v); op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(NUMBERO); cNUMERO++; break; case RDIGIT: cNUMERO++; op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(NUMBERO); op = reg[2]; DEREF(op); FOLLOW(op) = MAKEINT(rad_int); break; case DIGIT: cNUMERO++; op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(NUMBERO); op = reg[2]; DEREF(op); for (len = oldnum = newnum = 0; AtomStr[len] != 0; len++) { oldnum = newnum; newnum = newnum * 10 + DigVal(AtomStr[len]); if (newnum < oldnum || newnum > SBPMAXINT) { Fprintf(stderr, "*** overflow >> %s\n", AtomStr); len = strlen(AtomStr); AtomStr[len++] = '.'; AtomStr[len++] = '0'; AtomStr[len] = 0; FOLLOW(op) = makefloat(atof(AtomStr)); return; } } FOLLOW(op) = MAKEINT(newnum); break; case LISQT: op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(STRING); op = reg[2]; DEREF(op); FOLLOW(op) = list_p; cSTRING++; break; case PUNCT: /* there are nine punctuation marks, */ /* ( , ) [ | ] { ; } */ /* % is listed as one, but isn't really. */ if (AtomStr[0] == ';') { op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(SEMI); cSEMI++; } else { op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(SPECIAL); cSPECIAL++; ptr = (LONG)insert(AtomStr, rtnint, 0, &perm) | CS_TAG; op = reg[2]; DEREF(op); FOLLOW(op) = ptr; } break; case ENDCL: op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(ENDCLS); cENDCLS++; break; case EOFCH: op = reg[1]; DEREF(op); FOLLOW(op) = MAKEINT(BADEND); break; default: Fprintf(stderr, "Internal error %d %s\n", i, AtomStr); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.