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