|
|
1.1 root 1: /*
2: * Copyright (c) 1982 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)asscan2.c 5.1 (Berkeley) 4/30/85";
9: #endif not lint
10:
11: #include "asscanl.h"
12:
13: static inttoktype oval = NL;
14: #define ASINBUFSIZ 4096
15: char inbufunget[8];
16: char inbuffer[ASINBUFSIZ];
17: char *Ginbufptr = inbuffer;
18: int Ginbufcnt = 0;
19: int scannerhadeof;
20:
21: fillinbuffer()
22: {
23: int nread;
24: int goal;
25: int got;
26:
27: nread = 0;
28: if (scannerhadeof == 0){
29: goal = sizeof(inbuffer);
30: do {
31: got = read(stdin->_file, inbuffer + nread, goal);
32: if (got == 0)
33: scannerhadeof = 1;
34: if (got <= 0)
35: break;
36: nread += got;
37: goal -= got;
38: } while (goal);
39: } else {
40: scannerhadeof = 0;
41: }
42: /*
43: * getchar assumes that Ginbufcnt and Ginbufptr
44: * are adjusted as if one character has been removed
45: * from the input.
46: */
47: if (nread == 0){
48: inbuffer[0] = EOFCHAR;
49: nread = 1;
50: }
51: Ginbufcnt = nread - 1;
52: Ginbufptr = inbuffer + 1;
53: }
54:
55: scan_dot_s(bufferbox)
56: struct tokbufdesc *bufferbox;
57: {
58: reg char *inbufptr;
59: reg int inbufcnt;
60: reg int ryylval; /* local copy of lexical value */
61: extern int yylval; /* global copy of lexical value */
62: reg int val; /* the value returned */
63: int i; /* simple counter */
64: reg char *rcp;
65: int ch; /* treated as a character */
66: int ch1; /* shadow value */
67: struct symtab *op;
68: ptrall lgbackpatch; /* where to stuff a string length */
69: reg ptrall bufptr; /* where to stuff tokens */
70: ptrall bufub; /* where not to stuff tokens */
71: long intval; /* value of int */
72: int linescrossed; /* when doing strings and comments */
73: struct Opcode opstruct;
74: reg int strlg; /* the length of a string */
75:
76: (bytetoktype *)bufptr = (bytetoktype *) & (bufferbox->toks[0]);
77: (bytetoktype *)bufub = &(bufferbox->toks[AVAILTOKS]);
78:
79: MEMTOREGBUF;
80: if (newfflag){
81: newfflag = 0;
82: ryylval = (int)savestr(newfname, strlen(newfname)+1, STR_BOTH);
83:
84: ptoken(bufptr, IFILE);
85: ptoken(bufptr, STRING);
86: pptr(bufptr, ryylval);
87:
88: ptoken(bufptr, ILINENO);
89: ptoken(bufptr, INT);
90: pint(bufptr, 1);
91: }
92:
93: while (bufptr < bufub){
94: loop:
95: switch(ryylval = (type+1)[ch = getchar()]) {
96: case SCANEOF:
97: endoffile: ;
98: inbufptr = 0;
99: ptoken(bufptr, PARSEEOF);
100: goto done;
101:
102: case DIV: /*process C style comments*/
103: if ( (ch = getchar()) == '*') { /*comment prelude*/
104: int incomment;
105: linescrossed = 0;
106: incomment = 1;
107: ch = getchar(); /*skip over the * */
108: while(incomment){
109: switch(ch){
110: case '*':
111: ch = getchar();
112: incomment = (ch != '/');
113: break;
114: case '\n':
115: scanlineno++;
116: linescrossed++;
117: ch = getchar();
118: break;
119: case EOFCHAR:
120: goto endoffile;
121: default:
122: ch = getchar();
123: break;
124: }
125: }
126: val = ILINESKIP;
127: ryylval = linescrossed;
128: goto ret;
129: } else { /*just an ordinary DIV*/
130: ungetc(ch);
131: val = ryylval = DIV;
132: goto ret;
133: }
134: case SH:
135: if (oval == NL){
136: /*
137: * Attempt to recognize a C preprocessor
138: * style comment '^#[ \t]*[0-9]*[ \t]*".*"
139: */
140: ch = getchar(); /*bump the #*/
141: while (INCHARSET(ch, SPACE))
142: ch = getchar();/*bump white */
143: if (INCHARSET(ch, DIGIT)){
144: intval = 0;
145: while(INCHARSET(ch, DIGIT)){
146: intval = intval*10 + ch - '0';
147: ch = getchar();
148: }
149: while (INCHARSET(ch, SPACE))
150: ch = getchar();
151: if (ch == '"'){
152: ptoken(bufptr, ILINENO);
153: ptoken(bufptr, INT);
154: pint(bufptr, intval - 1);
155: ptoken(bufptr, IFILE);
156: /*
157: * The '"' has already been
158: * munched
159: *
160: * eatstr will not eat
161: * the trailing \n, so
162: * it is given to the parser
163: * and counted.
164: */
165: goto eatstr;
166: }
167: }
168: }
169: /*
170: * Well, its just an ordinary decadent comment
171: */
172: while ((ch != '\n') && (ch != EOFCHAR))
173: ch = getchar();
174: if (ch == EOFCHAR)
175: goto endoffile;
176: val = ryylval = oval = NL;
177: scanlineno++;
178: goto ret;
179:
180: case NL:
181: scanlineno++;
182: val = ryylval;
183: goto ret;
184:
185: case SP:
186: oval = SP; /*invalidate ^# meta comments*/
187: goto loop;
188:
189: case REGOP: /* % , could be used as modulo, or register*/
190: ch = getchar();
191: if (INCHARSET(ch, DIGIT)){
192: ryylval = ch-'0';
193: if (ch=='1') {
194: if (INCHARSET( (ch = getchar()), REGDIGIT))
195: ryylval = 10+ch-'0';
196: else
197: ungetc(ch);
198: }
199: /*
200: * God only knows what the original author
201: * wanted this undocumented feature to
202: * do.
203: * %5++ is really r7
204: */
205: while(INCHARSET( (ch = getchar()), SIGN)) {
206: if (ch=='+')
207: ryylval++;
208: else
209: ryylval--;
210: }
211: ungetc(ch);
212: val = REG;
213: } else {
214: ungetc(ch);
215: val = REGOP;
216: }
217: goto ret;
218:
219: case ALPH:
220: ch1 = ch;
221: if (INCHARSET(ch, SZSPECBEGIN)){
222: if( (ch = getchar()) == '`' || ch == '^'){
223: ch1 |= 0100; /*convert to lower*/
224: switch(ch1){
225: case 'b': ryylval = 1; break;
226: case 'w': ryylval = 2; break;
227: case 'l': ryylval = 4; break;
228: default: ryylval = d124; break;
229: }
230: val = SIZESPEC;
231: goto ret;
232: } else {
233: ungetc(ch);
234: ch = ch1; /*restore first character*/
235: }
236: }
237: rcp = yytext;
238: do {
239: if (rcp < &yytext[NCPName])
240: *rcp++ = ch;
241: } while (INCHARSET ( (ch = getchar()), ALPHA | DIGIT));
242: *rcp = '\0';
243: while (INCHARSET(ch, SPACE))
244: ch = getchar();
245: ungetc(ch);
246:
247: switch((op = *lookup(1))->s_tag){
248: case 0:
249: case LABELID:
250: /*
251: * Its a name... (Labels are subsets of name)
252: */
253: ryylval = (int)op;
254: val = NAME;
255: break;
256: case INST0:
257: case INSTn:
258: case IJXXX:
259: opstruct.Op_popcode = ( (struct instab *)op)->i_popcode;
260: opstruct.Op_eopcode = ( (struct instab *)op)->i_eopcode;
261: val = op->s_tag;
262: break;
263: default:
264: ryylval = ( (struct instab *)op)->i_popcode;
265: val = op->s_tag;
266: break;
267: }
268: goto ret;
269:
270: case DIG:
271: /*
272: * restore local inbufptr and inbufcnt
273: */
274: REGTOMEMBUF;
275: val = number(ch);
276: MEMTOREGBUF;
277: /*
278: * yylval or yybignum has been stuffed as a side
279: * effect to number(); get the global yylval
280: * into our fast local copy in case it was an INT.
281: */
282: ryylval = yylval;
283: goto ret;
284:
285: case LSH:
286: case RSH:
287: /*
288: * We allow the C style operators
289: * << and >>, as well as < and >
290: */
291: if ( (ch1 = getchar()) != ch)
292: ungetc(ch1);
293: val = ryylval;
294: goto ret;
295:
296: case MINUS:
297: if ( (ch = getchar()) =='(')
298: ryylval=val=MP;
299: else {
300: ungetc(ch);
301: val=MINUS;
302: }
303: goto ret;
304:
305: case SQ:
306: if ((ryylval = getchar()) == '\n')
307: scanlineno++; /*not entirely correct*/
308: val = INT;
309: goto ret;
310:
311: case DQ:
312: eatstr:
313: linescrossed = 0;
314: for (strlg = 0; /*VOID*/; strlg++){
315: switch(ch = getchar()){
316: case '"':
317: goto tailDQ;
318: default:
319: stuff:
320: putc(ch, strfile);
321: break;
322: case '\n':
323: yywarning("New line in a string constant");
324: scanlineno++;
325: linescrossed++;
326: ch = getchar();
327: switch(ch){
328: case EOFCHAR:
329: putc('\n', strfile);
330: ungetc(EOFCHAR);
331: goto tailDQ;
332: default:
333: ungetc(ch);
334: ch = '\n';
335: goto stuff;
336: }
337: break;
338:
339: case '\\':
340: ch = getchar(); /*skip the '\\'*/
341: if ( INCHARSET(ch, BSESCAPE)){
342: switch (ch){
343: case 'b': ch = '\b'; goto stuff;
344: case 'f': ch = '\f'; goto stuff;
345: case 'n': ch = '\n'; goto stuff;
346: case 'r': ch = '\r'; goto stuff;
347: case 't': ch = '\t'; goto stuff;
348: }
349: }
350: if ( !(INCHARSET(ch, OCTDIGIT)) )
351: goto stuff;
352: i = 0;
353: intval = 0;
354: while ( (i < 3) && (INCHARSET(ch, OCTDIGIT))){
355: i++;
356: intval <<= 3;
357: intval += ch - '0';
358: ch = getchar();
359: }
360: ungetc(ch);
361: ch = (char)intval;
362: goto stuff;
363: }
364: }
365: tailDQ: ;
366: /*
367: * account for any lines that were crossed
368: */
369: if (linescrossed){
370: ptoken(bufptr, ILINESKIP);
371: pint(bufptr, linescrossed);
372: }
373: /*
374: * Cheat: append a trailing null to the string
375: * and then adjust the string length to ignore
376: * the trailing null. If any STRING client requires
377: * the trailing null, the client can just change STRLEN
378: */
379: putc(0, strfile);
380: ryylval = (int)savestr((char *)0, strlg + 1, STR_FILE);
381: val = STRING;
382: ((struct strdesc *)ryylval)->sd_strlen -= 1;
383: goto ret;
384:
385: case BADCHAR:
386: linescrossed = lineno;
387: lineno = scanlineno;
388: yyerror("Illegal character mapped: %d, char read:(octal) %o",
389: ryylval, ch);
390: lineno = linescrossed;
391: val = BADCHAR;
392: goto ret;
393:
394: default:
395: val = ryylval;
396: goto ret;
397: } /*end of the switch*/
398: /*
399: * here with one token, so stuff it
400: */
401: ret:
402: oval = val;
403: ptoken(bufptr, val);
404: switch(val){
405: case ILINESKIP:
406: pint(bufptr, ryylval);
407: break;
408: case SIZESPEC:
409: pchar(bufptr, ryylval);
410: break;
411: case BFINT: plong(bufptr, ryylval);
412: break;
413: case INT: plong(bufptr, ryylval);
414: break;
415: case BIGNUM: pnumber(bufptr, yybignum);
416: break;
417: case STRING: pptr(bufptr, (int)(char *)ryylval);
418: break;
419: case NAME: pptr(bufptr, (int)(struct symtab *)ryylval);
420: break;
421: case REG: pchar(bufptr, ryylval);
422: break;
423: case INST0:
424: case INSTn:
425: popcode(bufptr, opstruct);
426: break;
427: case IJXXX:
428: popcode(bufptr, opstruct);
429: pptr(bufptr, (int)(struct symtab *)symalloc());
430: break;
431: case ISTAB:
432: case ISTABSTR:
433: case ISTABNONE:
434: case ISTABDOT:
435: case IALIGN:
436: pptr(bufptr, (int)(struct symtab *)symalloc());
437: break;
438: /*
439: * default:
440: */
441: }
442: builtval: ;
443: } /*end of the while to stuff the buffer*/
444: done:
445: bufferbox->tok_count = (bytetoktype *)bufptr - &(bufferbox->toks[0]);
446: /*
447: * This is a real kludge:
448: *
449: * We put the last token in the buffer to be a MINUS
450: * symbol. This last token will never be picked up
451: * in the normal way, but can be looked at during
452: * a peekahead look that the short circuit expression
453: * evaluator uses to see if an expression is complicated.
454: *
455: * Consider the following situation:
456: *
457: * .word 45 + 47
458: * buffer 1 | buffer 0
459: * the peekahead would want to look across the buffer,
460: * but will look in the buffer end zone, see the minus, and
461: * fail.
462: */
463: ptoken(bufptr, MINUS);
464: REGTOMEMBUF;
465: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.