mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
843 lines
28 KiB
Plaintext
843 lines
28 KiB
Plaintext
1File: LEX.C Page 1
|
|
1 /*
|
|
2 Copyright 1982
|
|
3 Alcyon Corporation
|
|
4 8716 Production Ave.
|
|
5 San Diego, Ca. 92121
|
|
6 */
|
|
7
|
|
8 #include "parser.h"
|
|
9 #define SOI '\01'
|
|
10 #define STEL HSIZE/2
|
|
11
|
|
12 /*
|
|
13 * the following are the cases within gettok, all other cases are
|
|
14 * single character unambiguous tokens. Note that we need to take
|
|
15 * special care not to interfere with the single character unambiguous
|
|
16 * operators, this is why there is a gap between WHITSP and EXCLAM.
|
|
17 */
|
|
18 #define BADC 0 /*bad character*/
|
|
19 #define WHITSP 101 /*white space*/
|
|
20 #define EXCLAM 102 /*exlamation point*/
|
|
21 #define DQUOTE 103 /*double quote*/
|
|
22 #define PERCNT 104 /*percent sign*/
|
|
23 #define AMPER 105 /*ampersand*/
|
|
24 #define SQUOTE 106 /*single quote*/
|
|
25 #define STAR 107 /*asterisk or mult sign*/
|
|
26 #define PLUS 108 /*plus sign*/
|
|
27 #define MINUS 109 /*minus sign*/
|
|
28 #define SLASH 110 /*divide sign*/
|
|
29 #define DIGIT 111 /*0..9*/
|
|
30 #define LCAROT 112 /*less than sign*/
|
|
31 #define EQUAL 113 /*equals sign*/
|
|
32 #define RCAROT 114 /*greater than*/
|
|
33 #define ALPHA 115 /*a..z,A..Z and underbar*/
|
|
34 #define CAROT 116 /*^*/
|
|
35 #define BAR 117 /*vertical bar*/
|
|
36
|
|
37 char ctype[] {
|
|
38 BADC, BADC, BADC, BADC, BADC, BADC, BADC, BADC,
|
|
39 BADC, WHITSP, WHITSP, WHITSP, WHITSP, WHITSP, BADC, BADC,
|
|
40 BADC, BADC, BADC, BADC, WHITSP, BADC, BADC, BADC,
|
|
41 BADC, BADC, BADC, BADC, BADC, BADC, BADC, BADC,
|
|
42 WHITSP, EXCLAM, DQUOTE, BADC, BADC, PERCNT, AMPER, SQUOTE,
|
|
43 LPAREN, RPAREN, STAR, PLUS, COMMA, MINUS, PERIOD, SLASH,
|
|
44 DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
|
|
45 DIGIT, DIGIT, COLON, SEMI, LCAROT, EQUAL, RCAROT, QMARK,
|
|
46 BADC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
|
47 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
|
48 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
|
49 ALPHA, ALPHA, ALPHA, LBRACK, BADC, RBRACK, CAROT, ALPHA,
|
|
50 BADC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
|
51 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
|
52 ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,
|
|
53 ALPHA, ALPHA, ALPHA, LCURBR, BAR, RCURBR, COMPL, BADC
|
|
54 };
|
|
55
|
|
56 /*key word table*/
|
|
57 struct resword {
|
|
58 char *r_name;
|
|
59 int r_value;
|
|
1File: LEX.C Page 2
|
|
60 } reswords[] {
|
|
61 "auto", R_AUTO,
|
|
62 "break", R_BREAK,
|
|
63 "case", R_CASE,
|
|
64 "char", R_CHAR,
|
|
65 "continue", R_CONTINUE,
|
|
66 "do", R_DO,
|
|
67 "default", R_DEFAULT,
|
|
68 "double", R_DOUBLE,
|
|
69 "goto", R_GOTO,
|
|
70 "else", R_ELSE,
|
|
71 "extern", R_EXTERNAL,
|
|
72 "float", R_FLOAT,
|
|
73 "for", R_FOR,
|
|
74 "if", R_IF,
|
|
75 "int", R_INT,
|
|
76 "long", R_LONG,
|
|
77 "register", R_REGISTER,
|
|
78 "return", R_RETURN,
|
|
79 "short", R_SHORT,
|
|
80 "sizeof", R_SIZEOF,
|
|
81 "static", R_STATIC,
|
|
82 "struct", R_STRUCT,
|
|
83 "switch", R_SWITCH,
|
|
84 "typedef", R_TYPEDEF,
|
|
85 "union", R_UNION,
|
|
86 "unsigned", R_UNSIGNED,
|
|
87 "while", R_WHILE,
|
|
88 0,
|
|
89 };
|
|
90
|
|
91 #define SELFMOD 0200
|
|
92 #define ASMASK 0177
|
|
93
|
|
94 /*
|
|
95 * this table is used to check for an operator after an equals sign.
|
|
96 * note that =-, =* and =& may all have an ambiguous meaning if not
|
|
97 * followed by a space, this is checked for in gettok.
|
|
98 */
|
|
99 char asmap[] {
|
|
100 EQUALS, /*==*/
|
|
101 EQADD, /*=+*/
|
|
102 EQSUB|SELFMOD, /*=-*/
|
|
103 EQMULT|SELFMOD, /*=**/
|
|
104 EQDIV, /*=/*/
|
|
105 EQOR, /*=|*/
|
|
106 EQAND|SELFMOD, /*=&*/
|
|
107 EQXOR, /*=^*/
|
|
108 EQMOD, /*=%*/
|
|
109 };
|
|
110
|
|
111 char escmap[] "\b\n\r\t";
|
|
112 int pbchar; /*pushed back character*/
|
|
113 struct symbol *symtab[HSIZE]; /*hash table*/
|
|
114 struct symbol *symbols; /*pointer to next avail symbol buf*/
|
|
115 int nsyms; /*number of symbol bufs in memory*/
|
|
116
|
|
117 /*
|
|
118 * getdec - get a decimal number
|
|
1File: LEX.C Page 3
|
|
119 * Uses Horner's method to get decimal number. Note that
|
|
120 * multiplication by 10 is cleverly programmed as two shifts and two
|
|
121 * adds. This is because long multiplies are painful on both the
|
|
122 * PDP-11 and 68000.
|
|
123 */
|
|
124 long getdec() /* returns number*/
|
|
125 {
|
|
126 register long value;
|
|
127 register char c;
|
|
128
|
|
129 for( value = 0; (c=ngetch()) >= '0' && c <= '9'; ) {
|
|
130 value =<< 1; /*value = value*2*/
|
|
131 value =+ value << 2; /*value*2 + value*8 = value*10*/
|
|
132 value =+ (c-'0');
|
|
133 }
|
|
134 putback(c);
|
|
135 return(value);
|
|
136 }
|
|
137
|
|
138 #define BIAS 127L
|
|
139 #define EXPSIZ 4
|
|
140 #define FRACSIZ 20
|
|
141
|
|
142 long toieee();
|
|
143 long toffp();
|
|
144 float power10();
|
|
145
|
|
146 /*
|
|
147 * getfp - get a floating point constant
|
|
148 * we've already gotten the significant digits, now build a
|
|
149 * floating point number with possible decimal digits and an
|
|
150 * exponent, yields an ieee formated floating point number,
|
|
151 * unless the fflag is on, then a ffp constant is generated.
|
|
152 */
|
|
153 long
|
|
154 getfp(significant)
|
|
155 long significant;
|
|
156 {
|
|
157 register char c;
|
|
158 register long places; /* decimal places */
|
|
159 int esign;
|
|
160 float exp, fraction, fp;
|
|
161
|
|
162 places = 0L; esign = 0; fraction = significant; exp = 0.0;
|
|
163 if ((c = ngetch()) == '.') /* get decimal places */
|
|
164 for( ; (c=ngetch()) >= '0' && c <= '9';) {
|
|
165 fraction = fraction * 10.0;
|
|
166 fraction = fraction + (c - '0');
|
|
167 places++;
|
|
168 }
|
|
169
|
|
170 if (c=='e' || c=='E') { /* exponent exists */
|
|
171 esign = (peekis('-')) ? 1 : (peekis('+')) ? 0 : 0;
|
|
172 for( ; (c=ngetch()) >= '0' && c <= '9'; ) {
|
|
173 exp = exp * 10.0;
|
|
174 exp = exp + (c - '0');
|
|
175 }
|
|
176 }
|
|
177
|
|
1File: LEX.C Page 4
|
|
178 putback(c);
|
|
179 if (esign)
|
|
180 exp = -exp;
|
|
181 places = exp - places;
|
|
182 fp = fraction * power10(places);
|
|
183 if (fflag)
|
|
184 return( toffp(fp) );
|
|
185 else
|
|
186 return ( toieee(fp) );
|
|
187 }
|
|
188
|
|
189 float
|
|
190 power10(pwr) /* used by getfp, 10^pwr */
|
|
191 long pwr;
|
|
192 {
|
|
193 float f;
|
|
194
|
|
195 if (pwr < 0L) /* negative power */
|
|
196 for (f = 1.0; pwr < 0L; pwr++)
|
|
197 f = f / 10.0;
|
|
198 else /* positive power */
|
|
199 for (f = 1.0; pwr > 0L; pwr--)
|
|
200 f = f * 10.0;
|
|
201 return(f);
|
|
202 }
|
|
203
|
|
204 long
|
|
205 toffp(f) /* converts current machine float to ffp rep */
|
|
206 float f;
|
|
207 {
|
|
208 register long exp;
|
|
209 register int sign, count;
|
|
210 long l;
|
|
211
|
|
212 if (f == 0.0)
|
|
213 return(0L);
|
|
214 if (f < 0.0) {
|
|
215 sign = 1;
|
|
216 f = -f;
|
|
217 }
|
|
218 else
|
|
219 sign = 0;
|
|
220 exp = 0L;
|
|
221 for( ; f >= 1.0; f = f / 2.0)
|
|
222 exp++;
|
|
223 for( ; f < 0.5; f = f * 2.0)
|
|
224 exp--;
|
|
225 f = f * 16777216.0; /* 2 ^ 24 */
|
|
226 l = f;
|
|
227 l =<< 8;
|
|
228 if (sign)
|
|
229 l =| 0x80;
|
|
230 exp =+ 0x40;
|
|
231 l =| (exp & 0x7f);
|
|
232 return(l);
|
|
233 }
|
|
234
|
|
235 long
|
|
236 toieee(f) /* converts current machine float to ieee rep */
|
|
1File: LEX.C Page 5
|
|
237 float f;
|
|
238 {
|
|
239 register long exp;
|
|
240 register int sign, count;
|
|
241 long l;
|
|
242
|
|
243 if (f == 0.0)
|
|
244 return(0L);
|
|
245 if (f < 0.0) {
|
|
246 sign = 1;
|
|
247 f = -f;
|
|
248 }
|
|
249 else
|
|
250 sign = 0;
|
|
251 exp = 0L;
|
|
252 for( ; f >= 2.0; f = f / 2.0)
|
|
253 exp++;
|
|
254 for( ; f < 1.0; f = f * 2.0)
|
|
255 exp--;
|
|
256 f = f - 1.0;
|
|
257 f = f * 8388608.0; /* 2 ^ 23 */
|
|
258 l = f;
|
|
259 if (sign)
|
|
260 l =| 0x80000000;
|
|
261 exp = (exp + BIAS)<<23;
|
|
262 l =| (exp & 0x7f800000);
|
|
263 return(l);
|
|
264 }
|
|
265
|
|
266 #define toupper(c) ((c) & ~32)
|
|
267 /* gethex - get an hexidecimal number*/
|
|
268 /* Uses Horner's method to get hexidecimal number*/
|
|
269 long gethex() /* returns number*/
|
|
270 {
|
|
271 register long value;
|
|
272 register char c, ch;
|
|
273
|
|
274 value = 0;
|
|
275 while( 1 ) {
|
|
276 if( (c=ngetch()) >= '0' && c <= '9' )
|
|
277 c =- '0';
|
|
278 else if((ch=toupper(c)) >= 'A' && ch <= 'F' ) /* [vlh] */
|
|
279 c = ch - ('A'-10);
|
|
280 else
|
|
281 break;
|
|
282 value = (value<<4) + c;
|
|
283 }
|
|
284 putback(c);
|
|
285 return(value);
|
|
286 }
|
|
287
|
|
288 /* getoct - get an octal number*/
|
|
289 /* Uses Horner's method to get octal number*/
|
|
290 long getoct(flag) /* returns number*/
|
|
291 int flag; /* string flag 1=>in string, else 0*/
|
|
292 {
|
|
293 register long value;
|
|
294 register char c;
|
|
295 register int count;
|
|
1File: LEX.C Page 6
|
|
296
|
|
297 count = 0;
|
|
298 for( value = 0; (c=ngetch()) >= '0' && c <= '7'; ) {
|
|
299 if( flag && ++count > 3 )
|
|
300 break;
|
|
301 value = (value<<3) + (c-'0');
|
|
302 }
|
|
303 putback(c);
|
|
304 return(value);
|
|
305 }
|
|
306
|
|
307 /*
|
|
308 * gettok - get next token from input
|
|
309 * Checks pushed-packed token buffer, supresses / * * / comments,
|
|
310 * folds multiple character special symbols into single word token.
|
|
311 */
|
|
312 gettok() /* returns token type*/
|
|
313 {
|
|
314 register int c, nextc, i;
|
|
315 register char *p;
|
|
316 register long value;
|
|
317 char sym[SSIZE];
|
|
318
|
|
319 if( peektok ) {
|
|
320 i = peektok;
|
|
321 peektok = 0;
|
|
322 return(i);
|
|
323 }
|
|
324 while( (c=ngetch()) != EOF ) {
|
|
325 switch(ctype[c]) {
|
|
326
|
|
327 case BADC: /*bad character*/
|
|
328 error("invalid character");
|
|
329 break;
|
|
330
|
|
331 case SEMI:
|
|
332 cvalue = 0; /* [vlh] not reserved word... */
|
|
333 default:
|
|
334 return( ctype[c] );
|
|
335
|
|
336 case WHITSP: /*skip all white space*/
|
|
337 break;
|
|
338
|
|
339 case EXCLAM: /*!= or !*/
|
|
340 return( peekis('=') ? NEQUALS : NOT );
|
|
341
|
|
342 case DQUOTE: /*quoted string*/
|
|
343 getstr(cstr,STRSIZE,'"');
|
|
344 cvalue = nextlabel++;
|
|
345 return(STRING);
|
|
346
|
|
347 case PERCNT: /*%= or %*/
|
|
348 return( peekis('=') ? EQMOD : MOD );
|
|
349
|
|
350 case AMPER: /*&=, && or &*/
|
|
351 return( peekis('=') ? EQAND : peekis('&') ? LAND : AND );
|
|
352
|
|
353 case SQUOTE: /*character constant*/
|
|
354 getstr(cstr,STRSIZE,'\'');
|
|
1File: LEX.C Page 7
|
|
355 if( cstrsize > CHRSPWORD+1 ) {
|
|
356 error("character constant too long");
|
|
357 cstrsize = CHRSPWORD + 1;
|
|
358 }
|
|
359 cvalue = 0;
|
|
360 for( p = cstr; --cstrsize > 0; ) {
|
|
361 cvalue =<< BITSPCHAR;
|
|
362 cvalue =| (*p++ & 0377);
|
|
363 }
|
|
364 return(CINT);
|
|
365
|
|
366 case STAR: /**= or **/
|
|
367 return( peekis('=') ? EQMULT : MULT );
|
|
368
|
|
369 case PLUS: /*+=, ++ or +*/
|
|
370 return( peekis('=') ? EQADD : peekis('+') ? PREINC : ADD );
|
|
371
|
|
372 case MINUS: /*-=, --, -> or -*/
|
|
373 return( peekis('=') ? EQSUB : peekis('-') ? PREDEC :
|
|
374 peekis('>') ? APTR : SUB );
|
|
375
|
|
376 case SLASH: /*/ *..* /, //..., /= or /*/
|
|
377 if( peekis('*') ) {
|
|
378 while( (c=ngetch()) != EOF )
|
|
379 if( c == '*' && peekis('/') )
|
|
380 break;
|
|
381 if( c == EOF ) {
|
|
382 error("no */ before EOF");
|
|
383 return(EOF);
|
|
384 }
|
|
385 continue;
|
|
386 }
|
|
387 if( peekis('/') ) {
|
|
388 while( (c=ngetch()) != EOF && c != EOLC )
|
|
389 ;
|
|
390 continue;
|
|
391 }
|
|
392 return( peekis('=') ? EQDIV : DIV );
|
|
393
|
|
394 case DIGIT: /*number constant (long or reg)*/
|
|
395 i = 0; /*flags if long constant*/
|
|
396 if( c != '0' ) {
|
|
397 putback(c);
|
|
398 dofp:
|
|
399 value = getdec();
|
|
400 if ((c=ngetch())=='.' || c=='e' || c=='E') { /*[vlh] 3.4 */
|
|
401 putback(c);
|
|
402 clvalue = getfp(value);
|
|
403 return(CFLOAT);
|
|
404 }
|
|
405 putback(c);
|
|
406 if( value > 32767 || value < -32768 )
|
|
407 i++;
|
|
408 }
|
|
409 else if( peekis('x') || peekis('X') ) {
|
|
410 value = gethex();
|
|
411 if( value < 0 || value >= 0x10000L )
|
|
412 i++;
|
|
413 }
|
|
1File: LEX.C Page 8
|
|
414 else {
|
|
415 if (peekis('.')) {
|
|
416 putback('.');
|
|
417 goto dofp;
|
|
418 }
|
|
419 value = getoct(0);
|
|
420 if( value < 0 || value >= 0x10000L )
|
|
421 i++;
|
|
422 }
|
|
423 if( peekis('l') || peekis('L') || i ) {
|
|
424 clvalue = value;
|
|
425 return(CLONG);
|
|
426 }
|
|
427 cvalue = value;
|
|
428 return(CINT);
|
|
429
|
|
430 case LCAROT: /*<=, <<, <<= or <*/
|
|
431 return( peekis('=') ? LESSEQ : peekis('<') ?
|
|
432 (peekis('=') ? EQLSH : LSH) : LESS );
|
|
433
|
|
434 case EQUAL: /*==, =<<, =>>, =+, ..., =*/
|
|
435 if( peekis('<') ) {
|
|
436 if( peekis('<') )
|
|
437 return(EQLSH);
|
|
438 }
|
|
439 else if( peekis('>') ) {
|
|
440 if( peekis('>') )
|
|
441 return(EQRSH);
|
|
442 }
|
|
443 else if( (i=index("=+-*/|&^%",(c=ngetch()))) >= 0 ) {
|
|
444 i = asmap[i];
|
|
445 if( i & SELFMOD ) {
|
|
446 if( (nextc=ngetch()) != ' ' )
|
|
447 if (!wflag) /*[vlh] old fashion initialization*/
|
|
448 error("=%c assumed",c);
|
|
449 putback(nextc);
|
|
450 }
|
|
451 return( i & ASMASK );
|
|
452 }
|
|
453 else
|
|
454 putback(c);
|
|
455 return(ASSIGN);
|
|
456
|
|
457 case RCAROT: /*>=, >>, >>= or >*/
|
|
458 return( peekis('=') ? GREATEQ : peekis('>') ?
|
|
459 (peekis('=') ? EQRSH : RSH) : GREAT );
|
|
460
|
|
461 case ALPHA: /*[A-Za-z][A-Za-z0-9]**/
|
|
462 p = &sym[0];
|
|
463 i = SSIZE;
|
|
464 for(; ctype[c] == ALPHA || ctype[c] == DIGIT; c=ngetch(),i-- )
|
|
465 if( i > 0 )
|
|
466 *p++ = c;
|
|
467 if( i > 0 )
|
|
468 *p = '\0';
|
|
469 putback(c);
|
|
470 csp = lookup(sym);
|
|
471 if( csp->s_attrib & SRESWORD ) {
|
|
472 cvalue = csp->s_offset;
|
|
1File: LEX.C Page 9
|
|
473 return(RESWORD);
|
|
474 }
|
|
475 smember = 0;
|
|
476 return(SYMBOL);
|
|
477
|
|
478 case CAROT: /*^= or ^*/
|
|
479 return( peekis('=') ? EQXOR : XOR );
|
|
480
|
|
481 case BAR: /*|=, || or |*/
|
|
482 return( peekis('=') ? EQOR : peekis('|') ? LOR : OR );
|
|
483
|
|
484 }
|
|
485 }
|
|
486 return(EOF);
|
|
487 }
|
|
488
|
|
489 /*
|
|
490 * peekis - peeks at next character for specific character
|
|
491 * Gets next (possibly pushed back) character, if it matches
|
|
492 * the given character 1 is returned, otherwise the character
|
|
493 * is put back.
|
|
494 */
|
|
495 peekis(tc) /* returns 1 if match, 0 otherwise*/
|
|
496 int tc; /* test character*/
|
|
497 {
|
|
498 register int c;
|
|
499
|
|
500 if( (c=ngetch()) == tc )
|
|
501 return(1);
|
|
502 putback(c);
|
|
503 return(0);
|
|
504 }
|
|
505
|
|
506 /* ngetch - get a possibly pushed back character*/
|
|
507 /* Checks pbchar variable, returns it if non-zero, handles counting*/
|
|
508 /* of new lines and whether you are in an include or not.*/
|
|
509 ngetch() /* returns character read or EOF*/
|
|
510 {
|
|
511 register int c;
|
|
512 register char *ifile;
|
|
513
|
|
514 if( pbchar ) {
|
|
515 c = pbchar;
|
|
516 pbchar = 0;
|
|
517 }
|
|
518 else if( (c=getc(&ibuf)) == EOLC ) {
|
|
519 if( inclflag )
|
|
520 inclflag = 0;
|
|
521 else
|
|
522 lineno++;
|
|
523 }
|
|
524 else if( c == SOI) { /*[vlh]add incl filename & line # */
|
|
525 inclflag++;
|
|
526 ifile = &inclfile;
|
|
527 while ((c=getc(&ibuf)) != SOI)
|
|
528 *ifile++ = c&0377;
|
|
529 *ifile = 0;
|
|
530 inclline = getdec() & 077777;
|
|
531 c = ' ';
|
|
1File: LEX.C Page 10
|
|
532 }
|
|
533 else if( c < 0 )
|
|
534 c = EOF;
|
|
535 return(c);
|
|
536 }
|
|
537
|
|
538 /*
|
|
539 * peekc - peek at the next non-whitespace character after token
|
|
540 * This allows for the problem of having to look at two tokens
|
|
541 * at once. The second token is always a semi-colon or colon,
|
|
542 * so we only look at the single character, rather than going
|
|
543 * thru gettok.
|
|
544 */
|
|
545 peekc(tc) /* returns 1 if match, 0 otherwise*/
|
|
546 int tc; /* character to look for*/
|
|
547 {
|
|
548 register int c;
|
|
549
|
|
550 while( ctype[(c=ngetch())] == WHITSP) ;
|
|
551 if( c == tc )
|
|
552 return(1);
|
|
553 putback(c);
|
|
554 return(0);
|
|
555 }
|
|
556
|
|
557 /* putback - puts back a single character*/
|
|
558 /* Checks pbchar for error condition.*/
|
|
559 putback(c) /* returns - none*/
|
|
560 int c;
|
|
561 {
|
|
562 if( pbchar )
|
|
563 error("too many chars pushed back");
|
|
564 else
|
|
565 pbchar = c;
|
|
566 }
|
|
567
|
|
568 /* getstr - get a quoted (single or double) character string*/
|
|
569 /* Gets specified number of characters, handling escapes.*/
|
|
570 getstr(str,nchars,endc) /* returns - none*/
|
|
571 char *str; /* pointer to string buffer*/
|
|
572 int nchars; /* max number of characters*/
|
|
573 char endc; /* ending string character*/
|
|
574 {
|
|
575 register char *p;
|
|
576 register int i;
|
|
577 register int c;
|
|
578 register int j;
|
|
579
|
|
580 cstrsize = 1;
|
|
581 p = str;
|
|
582 for( i = nchars; (c=ngetch()) != endc; i-- ) {
|
|
583 if( c == EOF || c == EOLC ) {
|
|
584 error("string cannot cross line");
|
|
585 break;
|
|
586 }
|
|
587 if( c == '\\' ) {
|
|
588 if( (c=ngetch()) >= '0' && c <= '7' ) {
|
|
589 putback(c);
|
|
590 if( (c=getoct(1)) < 0 || c > 255 ) {
|
|
1File: LEX.C Page 11
|
|
591 error("bad character constant");
|
|
592 continue;
|
|
593 }
|
|
594 }
|
|
595 else if( (j=index("bnrt",c)) >= 0 )
|
|
596 c = escmap[j];
|
|
597 else if( c == EOLC ) /*escape followed by nl->ignore*/
|
|
598 continue;
|
|
599 }
|
|
600 if( i > 0 ) { /*room left in string?*/
|
|
601 cstrsize++;
|
|
602 *p++ = c;
|
|
603 }
|
|
604 else if( !i ) /*only say error once...*/
|
|
605 error("string too long");
|
|
606 }
|
|
607 if( i <= 0 ) /*string overflow?*/
|
|
608 p--;
|
|
609 *p = '\0';
|
|
610 }
|
|
611
|
|
612 /* syminit - initialize the symbol table, install reswords*/
|
|
613 /* Goes thru the resword table and installs them into the symbol*/
|
|
614 /* table.*/
|
|
615 syminit() /* returns - none*/
|
|
616 {
|
|
617 register struct resword *rp;
|
|
618
|
|
619 for( rp = &reswords[0]; rp->r_name != 0; rp++ )
|
|
620 install(rp->r_name,SRESWORD|SDEFINED,rp->r_value);
|
|
621 }
|
|
622
|
|
623 /* install - install a symbol in the symbol table*/
|
|
624 /* Allocates a symbol entry, copies info into it and links it*/
|
|
625 /* into the hash table chain.*/
|
|
626 char *install(sym,attrib,offset) /* returns pointer to symbol struct*/
|
|
627 char *sym; /* symbol to install*/
|
|
628 int attrib; /* attribues of symbol*/
|
|
629 int offset; /* symbol offset (resword value)*/
|
|
630 {
|
|
631 register struct symbol *sp;
|
|
632 register int i;
|
|
633
|
|
634 while( !(sp=symbols) ) {
|
|
635 if( !(sp=sbrk(SYMSIZE)) )
|
|
636 ferror("symbol table overflow");
|
|
637 for( i = SYMSIZE/(sizeof *symbols); --i >= 0; ) {
|
|
638 sp->s_next = symbols;
|
|
639 symbols = sp++;
|
|
640 }
|
|
641 }
|
|
642 symbols = sp->s_next;
|
|
643 sp->s_attrib = attrib;
|
|
644 sp->s_sc = 0; sp->s_type = 0; sp->s_dp = 0; sp->s_ssp = 0;
|
|
645 sp->s_offset = offset;
|
|
646 sp->s_struc = (instruct) ? strucptr[smember+instruct] : 0;
|
|
647 symcopy(sym,sp->s_symbol); /*copy symbol to symbol struct*/
|
|
648 i = symhash(sym,instruct|smember); /*link into chain list*/
|
|
649 sp->s_next = symtab[i];
|
|
1File: LEX.C Page 12
|
|
650 symtab[i] = sp;
|
|
651 return(sp);
|
|
652 }
|
|
653
|
|
654 /* lookup - looks up a symbol in symbol table*/
|
|
655 /* Hashes symbol, then goes thru chain, if not found, then*/
|
|
656 /* installs the symbol.*/
|
|
657 char *lookup(sym) /* returns pointer to symbol buffer*/
|
|
658 char *sym; /* pointer to symbol*/
|
|
659 {
|
|
660 register struct symbol *sp, *hold;
|
|
661 register char *p;
|
|
662 int exact; /* same name, diff type or offset */
|
|
663
|
|
664 p = sym;
|
|
665 for( sp = symtab[symhash(p,0)]; sp != 0; sp = sp->s_next )
|
|
666 if((sp->s_attrib&(SRESWORD|STYPEDEF)) && symequal(p,sp->s_symbol))
|
|
667 return(sp);
|
|
668 if (!(smember|instruct)) { /*[vlh]*/
|
|
669 for( sp=symtab[symhash(p,0)]; sp!=0; sp=sp->s_next )
|
|
670 if( symequal(p,sp->s_symbol) ) return(sp);
|
|
671 }
|
|
672 else { /* doing a declaration or an expression */
|
|
673 hold = 0; exact = 0;
|
|
674 for( sp=symtab[symhash(p,instruct|smember)]; sp!=0; sp=sp->s_next )
|
|
675 if( symequal(p,sp->s_symbol) )
|
|
676 if (symsame(sp,hold,&exact)) return(sp);
|
|
677 else if (!hold && !exact) hold = sp;
|
|
678 if (hold && !exact) return(hold);
|
|
679 }
|
|
680 return(install(p,0,0));
|
|
681 }
|
|
682
|
|
683 /* freesyms - frees all local symbols at end of function declaration*/
|
|
684 /* Searches thru symbol table, deleting all symbols marked as locals*/
|
|
685 freesyms() /* returns - none*/
|
|
686 {
|
|
687 register int i, tinfo;
|
|
688 register struct symbol *sp, *tp, *nextp, **htp;
|
|
689
|
|
690 for( htp = &symtab[0], i = HSIZE; --i >= 0; htp++ )
|
|
691 for( tp = 0, sp = *htp; sp != 0; sp = nextp ) {
|
|
692 nextp = sp->s_next;
|
|
693 if( !(sp->s_attrib&SDEFINED) ) {
|
|
694 error("undefined label: %.8s",sp->s_symbol);
|
|
695 sp->s_attrib =| SDEFINED;
|
|
696 }
|
|
697 if( sp->s_attrib & (SGLOBAL|SRESWORD) )
|
|
698 tp = sp;
|
|
699 else {
|
|
700 if( tp )
|
|
701 tp->s_next = sp->s_next;
|
|
702 else
|
|
703 *htp = sp->s_next;
|
|
704 sp->s_next = symbols;
|
|
705 symbols = sp;
|
|
706 }
|
|
707 }
|
|
708 }
|
|
1File: LEX.C Page 13
|
|
709
|
|
710 /* chksyms - checks symbol table for undefined symbols, etc.*/
|
|
711 /* Goes thru the symbol table checking for undeclared forward*/
|
|
712 /* referenced structures, and outputs local symbols for debugger.*/
|
|
713 chksyms() /* returns - none*/
|
|
714 {
|
|
715 register struct symbol **htp, *sp;
|
|
716 register int i, sc;
|
|
717
|
|
718 for( htp = &symtab[0], i = HSIZE; --i >= 0; htp++ )
|
|
719 for( sp = *htp; sp != 0; sp = sp->s_next ) {
|
|
720 sc = sp->s_sc;
|
|
721 if(sc!=0 && sp->s_ssp>=0 && (btype(sp->s_type))==FRSTRUCT) {
|
|
722 sp->s_ssp = frstab[sp->s_ssp]->s_ssp; /* 3.4 ssp>0 */
|
|
723 sp->s_type = (sp->s_type&~TYPE) | STRUCT;
|
|
724 }
|
|
725 if( sc == PDECLIST ) {
|
|
726 error("not in parameter list: %.8s",sp->s_symbol);
|
|
727 sp->s_sc = AUTO;
|
|
728 }
|
|
729 if( infunc )
|
|
730 outlocal(sp->s_type,sp->s_sc,sp->s_symbol,sp->s_offset);
|
|
731 }
|
|
732 }
|
|
733
|
|
734 /* symhash - compute hash value for symbol*/
|
|
735 /* Sums the symbols characters and takes that modulus the hash table*/
|
|
736 /* size.*/
|
|
737 symhash(sym,stel) /* returns hash value for symbol*/
|
|
738 char *sym; /* pointer to symbol*/
|
|
739 int stel; /* structure element flag*/
|
|
740 {
|
|
741 register char *p;
|
|
742 register int hashval, i;
|
|
743
|
|
744 hashval = (stel ? STEL : 0 );
|
|
745 for( p = sym, i = SSIZE; *p != '\0' && i > 0; i-- )
|
|
746 hashval =+ *p++;
|
|
747 return( hashval % HSIZE );
|
|
748 }
|
|
749
|
|
750 /* symequal - check for symbol equality*/
|
|
751 /* Does comparison between two symbols.*/
|
|
752 symequal(sym1,sym2) /* returns 1 if equal, 0 otherwise*/
|
|
753 char *sym1; /* pointer to first symbol*/
|
|
754 char *sym2; /* pointer to second symbol*/
|
|
755 {
|
|
756 register char *p, *q;
|
|
757 register int i;
|
|
758
|
|
759 for( p = sym1, q = sym2, i = SSIZE; *p == *q++; )
|
|
760 if( *p++ == '\0' || --i == 0 )
|
|
761 return(1);
|
|
762 return(0);
|
|
763 }
|
|
764
|
|
765 /* symsame - symbol member same as declared */
|
|
766 symsame(sp,hold,exact) /* [vlh] */
|
|
767 struct symbol *sp, *hold;
|
|
1File: LEX.C Page 14
|
|
768 int *exact;
|
|
769 {
|
|
770 if (strucptr[smember+instruct])
|
|
771 if (strucptr[smember+instruct]==sp->s_struc) return(1);
|
|
772 if (hold)
|
|
773 if (sp->s_type != hold->s_type || sp->s_offset != hold->s_offset)
|
|
774 *exact = 1;
|
|
775 return(0);
|
|
776 }
|
|
777
|
|
778 /* symcopy - symbol copy*/
|
|
779 /* Copies one symbol to another.*/
|
|
780 symcopy(sym1,sym2) /* returns - none*/
|
|
781 char *sym1; /* pointer to symbol to copy*/
|
|
782 char *sym2; /* pointer to area to copy to*/
|
|
783 {
|
|
784 register char *p, *q;
|
|
785 register int i;
|
|
786
|
|
787 for( p = sym1, q = sym2, i = SSIZE; --i >= 0; )
|
|
788 *q++ = ( *p ? *p++ : '\0');
|
|
789 }
|
|
790
|
|
791 /* index - find the index of a character in a string*/
|
|
792 /* This is identical to Software Tools index.*/
|
|
793 index(str,chr) /* returns index of c in str or -1*/
|
|
794 char *str; /* pointer to string to search*/
|
|
795 char chr; /* character to search for*/
|
|
796 {
|
|
797 register char *s;
|
|
798 register int i;
|
|
799
|
|
800 for( s = str, i = 0; *s != '\0'; i++ )
|
|
801 if( *s++ == chr )
|
|
802 return(i);
|
|
803 return(-1);
|
|
804 }
|
|
805
|
|
806 /* next - if next token matches given token, skip and return success*/
|
|
807 /* This allows for clean parsing of declarations.*/
|
|
808 next(tok) /* returns 1 if matched, 0 otherwise*/
|
|
809 int tok;
|
|
810 {
|
|
811 register int token;
|
|
812
|
|
813 if( (token=gettok()) == tok )
|
|
814 return(1);
|
|
815 peektok = token;
|
|
816 return(0);
|
|
817 }
|
|
818
|
|
819 /* pbtok - put back the given token*/
|
|
820 /* This merely sets the peektok variable*/
|
|
821 pbtok(tok) /* returns - none*/
|
|
822 int tok;
|
|
823 {
|
|
824 if( peektok )
|
|
825 error("too many tokens pushed back");
|
|
826 peektok = tok;
|
|
1File: LEX.C Page 15
|
|
827 }
|