put etherlink support in, but #ifdef notdef
[unix-history] / usr / src / old / as.vax / asscan2.c
CommitLineData
3bd55f52
RH
1/*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4#ifndef lint
ad67d5e5 5static char sccsid[] = "@(#)asscan2.c 4.7 %G%";
3bd55f52
RH
6#endif not lint
7
8#include "asscanl.h"
9static inttoktype oval = NL;
10
ad67d5e5 11#define ASINBUFSIZ 4096
3bd55f52 12#define NINBUFFERS 2
ad67d5e5 13#define INBUFLG NINBUFFERS*ASINBUFSIZ + 2
3bd55f52 14 /*
ad67d5e5 15 * We have NINBUFFERS input buffers; the first one is reserved
3bd55f52 16 * for catching the tail of a line split across a buffer
ad67d5e5
RH
17 * boundary; the other ones are used for snarfing a buffer
18 * worth of assembly language source.
3bd55f52
RH
19 */
20static char inbuffer[INBUFLG];
21static char *InBufPtr = 0;
22
23/*
24 * fill the inbuffer from the standard input.
25 * Assert: there are always n COMPLETE! lines in the buffer area.
26 * Assert: there is always a \n terminating the last line
27 * in the buffer area.
28 * Assert: after the \n, there is an EOFCHAR (hard end of file)
29 * or a NEEDCHAR (end of buffer)
30 * Assert: fgets always null pads the string it reads.
31 * Assert: no ungetc's are done at the end of a line or at the
32 * beginning of a line.
33 *
34 * We read a complete buffer of characters in one single read.
35 * We then back scan within this buffer to find the end of the
36 * last complete line, and force the assertions, and save a pointer
37 * to the incomplete line.
38 * The next call to fillinbuffer will move the unread characters
39 * to the end of the first buffer, and then read another two buffers,
40 * completing the cycle.
41 */
42
43static char p_swapped = '\0';
ad67d5e5
RH
44static char *p_start = &inbuffer[NINBUFFERS * ASINBUFSIZ];
45static char *p_stop = &inbuffer[NINBUFFERS * ASINBUFSIZ];
46
47#define MIDDLE &inbuffer[ASINBUFSIZ]
8a7e35d9 48
3bd55f52
RH
49char *fillinbuffer()
50{
3bd55f52
RH
51 register char *from;
52 char *inbufptr;
53 int nread;
8a7e35d9
RH
54 static int hadeof;
55 int goal;
56 int got;
3bd55f52
RH
57
58 *p_start = p_swapped;
ad67d5e5
RH
59 inbufptr = MIDDLE - (p_stop - p_start);
60 movestr(inbufptr, p_start, p_stop - p_start);
3bd55f52 61 /*
ad67d5e5 62 * Now, go read up to NINBUFFERS - 1 full buffers
3bd55f52 63 */
8a7e35d9
RH
64 if (hadeof){
65 hadeof = 0;
66 return (0);
67 }
ad67d5e5 68 goal = (NINBUFFERS - 1)*ASINBUFSIZ;
8a7e35d9
RH
69 nread = 0;
70 do {
ad67d5e5 71 got = read(stdin->_file, MIDDLE + nread, goal);
8a7e35d9
RH
72 if (got == 0)
73 hadeof = 1;
74 if (got <= 0)
75 break;
76 nread += got;
77 goal -= got;
78 } while (goal);
79
3bd55f52
RH
80 if (nread == 0)
81 return(0);
ad67d5e5
RH
82 from = MIDDLE + nread;
83 p_stop = from;
3bd55f52 84 *from = '\0';
8a7e35d9
RH
85 while (*--from != '\n'){
86 /*
87 * back over the partial line
88 */
ad67d5e5 89 if (from == MIDDLE) {
8a7e35d9
RH
90 from = p_stop;
91 *p_stop++ = '\n';
92 break;
93 } else {
94 continue;
95 }
96 }
97
3bd55f52
RH
98 from++; /* first char of partial line */
99 p_start = from;
100 p_swapped = *p_start;
101 *p_start = NEEDCHAR; /* force assertion */
102 return(inbufptr);
103}
104
105scan_dot_s(bufferbox)
106 struct tokbufdesc *bufferbox;
107{
108 reg int ryylval; /* local copy of lexical value */
109 extern int yylval; /* global copy of lexical value */
110 reg int val; /* the value returned */
111 int i; /* simple counter */
112 reg char *rcp;
113 char *cp; /* can have address taken */
114 reg int ch; /* treated as a character */
115 int ch1; /* shadow value */
116 reg char *inbufptr;
117 struct symtab *op;
118
119 reg ptrall bufptr; /* where to stuff tokens */
120 ptrall lgbackpatch; /* where to stuff a string length */
121 ptrall bufub; /* where not to stuff tokens */
ad67d5e5 122 reg int maxstrlg; /* how long a string can be */
3bd55f52
RH
123 long intval; /* value of int */
124 int linescrossed; /* when doing strings and comments */
125 struct Opcode opstruct;
126
127 (bytetoktype *)bufptr = (bytetoktype *) & (bufferbox->toks[0]);
128 (bytetoktype *)bufub = &(bufferbox->toks[AVAILTOKS]);
129
130 inbufptr = InBufPtr;
131 if (inbufptr == 0){
132 inbufptr = fillinbuffer();
133 if (inbufptr == 0){ /*end of file*/
134 endoffile:
135 inbufptr = 0;
136 ptoken(bufptr, PARSEEOF);
137 goto done;
138 }
139 }
140
141 if (newfflag){
ad67d5e5
RH
142 newfflag = 0;
143 ryylval = (int)savestr(newfname, strlen(newfname) + 1);
144
3bd55f52
RH
145 ptoken(bufptr, IFILE);
146 ptoken(bufptr, STRING);
ad67d5e5 147 pptr(bufptr, ryylval);
3bd55f52
RH
148
149 ptoken(bufptr, ILINENO);
150 ptoken(bufptr, INT);
151 pint(bufptr, 1);
3bd55f52
RH
152 }
153
154 while (bufptr < bufub){
155 loop:
156 switch(ryylval = (type+2)[ch = getchar()]) {
157 case SCANEOF:
158 inbufptr = 0;
159 goto endoffile;
160
161 case NEEDSBUF:
162 inbufptr = fillinbuffer();
163 if (inbufptr == 0)
164 goto endoffile;
165 goto loop;
166
167 case DIV: /*process C style comments*/
168 if ( (ch = getchar()) == '*') { /*comment prelude*/
169 int incomment;
170 linescrossed = 0;
171 incomment = 1;
172 ch = getchar(); /*skip over the * */
173 while(incomment){
174 switch(ch){
175 case '*':
176 ch = getchar();
177 incomment = (ch != '/');
178 break;
179 case '\n':
180 scanlineno++;
181 linescrossed++;
182 ch = getchar();
183 break;
184 case EOFCHAR:
185 goto endoffile;
186 case NEEDCHAR:
187 inbufptr = fillinbuffer();
188 if (inbufptr == 0)
189 goto endoffile;
190 lineno++;
191 ch = getchar();
192 break;
193 default:
194 ch = getchar();
195 break;
196 }
197 }
198 val = ILINESKIP;
199 ryylval = linescrossed;
200 goto ret;
201 } else { /*just an ordinary DIV*/
202 ungetc(ch);
203 val = ryylval = DIV;
204 goto ret;
205 }
206 case SH:
207 if (oval == NL){
208 /*
209 * Attempt to recognize a C preprocessor
210 * style comment '^#[ \t]*[0-9]*[ \t]*".*"
211 */
212 ch = getchar(); /*bump the #*/
213 while (INCHARSET(ch, SPACE))
214 ch = getchar();/*bump white */
215 if (INCHARSET(ch, DIGIT)){
216 intval = 0;
217 while(INCHARSET(ch, DIGIT)){
218 intval = intval*10 + ch - '0';
219 ch = getchar();
220 }
221 while (INCHARSET(ch, SPACE))
222 ch = getchar();
223 if (ch == '"'){
224 ptoken(bufptr, ILINENO);
225 ptoken(bufptr, INT);
226 pint(bufptr, intval - 1);
227 ptoken(bufptr, IFILE);
228 /*
229 * The '"' has already been
230 * munched
231 *
232 * eatstr will not eat
233 * the trailing \n, so
234 * it is given to the parser
235 * and counted.
236 */
237 goto eatstr;
238 }
239 }
240 }
241 /*
242 * Well, its just an ordinary decadent comment
243 */
244 while ((ch != '\n') && (ch != EOFCHAR))
245 ch = getchar();
246 if (ch == EOFCHAR)
247 goto endoffile;
248 val = ryylval = oval = NL;
249 scanlineno++;
250 goto ret;
251
252 case NL:
253 scanlineno++;
254 val = ryylval;
255 goto ret;
256
257 case SP:
258 oval = SP; /*invalidate ^# meta comments*/
259 goto loop;
260
261 case REGOP: /* % , could be used as modulo, or register*/
262 ch = getchar();
263 if (INCHARSET(ch, DIGIT)){
264 ryylval = ch-'0';
265 if (ch=='1') {
266 if (INCHARSET( (ch = getchar()), REGDIGIT))
267 ryylval = 10+ch-'0';
268 else
269 ungetc(ch);
270 }
271 /*
272 * God only knows what the original author
273 * wanted this undocumented feature to
274 * do.
275 * %5++ is really r7
276 */
277 while(INCHARSET( (ch = getchar()), SIGN)) {
278 if (ch=='+')
279 ryylval++;
280 else
281 ryylval--;
282 }
283 ungetc(ch);
284 val = REG;
285 } else {
286 ungetc(ch);
287 val = REGOP;
288 }
289 goto ret;
290
291 case ALPH:
292 ch1 = ch;
293 if (INCHARSET(ch, SZSPECBEGIN)){
294 if( (ch = getchar()) == '`' || ch == '^'){
295 ch1 |= 0100; /*convert to lower*/
296 switch(ch1){
297 case 'b': ryylval = 1; break;
298 case 'w': ryylval = 2; break;
299 case 'l': ryylval = 4; break;
300 default: ryylval = d124; break;
301 }
302 val = SIZESPEC;
303 goto ret;
304 } else {
305 ungetc(ch);
306 ch = ch1; /*restore first character*/
307 }
308 }
309 rcp = yytext;
310 do {
311 if (rcp < &yytext[NCPS])
312 *rcp++ = ch;
313 } while (INCHARSET ( (ch = getchar()), ALPHA | DIGIT));
314 *rcp = '\0';
315 while (INCHARSET(ch, SPACE))
316 ch = getchar();
317 ungetc(ch);
318
319 switch((op = *lookup(1))->s_tag){
320 case 0:
321 case LABELID:
322 /*
323 * Its a name... (Labels are subsets ofname)
324 */
325 ryylval = (int)op;
326 val = NAME;
327 break;
328 case INST0:
329 case INSTn:
330 case IJXXX:
331 opstruct.Op_popcode = ( (struct instab *)op)->i_popcode;
332 opstruct.Op_eopcode = ( (struct instab *)op)->i_eopcode;
333 val = op->s_tag;
334 break;
335 default:
336 ryylval = ( (struct instab *)op)->i_popcode;
337 val = op->s_tag;
338 break;
339 }
340 goto ret;
341
342 case DIG:
343 /*
344 * Implement call by reference on a reg variable
345 */
346 cp = inbufptr;
347 val = number(ch, &cp);
348 /*
349 * yylval or yybignum has been stuffed as a side
350 * effect to number(); get the global yylval
351 * into our fast local copy in case it was an INT.
352 */
353 ryylval = yylval;
354 inbufptr = cp;
355 goto ret;
356
357 case LSH:
358 case RSH:
359 /*
360 * We allow the C style operators
361 * << and >>, as well as < and >
362 */
363 if ( (ch1 = getchar()) != ch)
364 ungetc(ch1);
365 val = ryylval;
366 goto ret;
367
368 case MINUS:
369 if ( (ch = getchar()) =='(')
370 ryylval=val=MP;
371 else {
372 ungetc(ch);
373 val=MINUS;
374 }
375 goto ret;
376
377 case SQ:
378 if ((ryylval = getchar()) == '\n')
379 scanlineno++; /*not entirely correct*/
380 val = INT;
381 goto ret;
382
383 case DQ:
384 eatstr:
385 linescrossed = 0;
ad67d5e5
RH
386 for(rcp = yytext, maxstrlg = NCPS; maxstrlg > 0; --maxstrlg){
387 switch(ch = getchar()){
388 case '"':
389 goto tailDQ;
390 default:
391 stuff:
392 pchar(rcp, ch);
393 break;
394 case '\n':
395 yywarning("New line in a string constant");
3bd55f52
RH
396 scanlineno++;
397 linescrossed++;
398 ch = getchar();
ad67d5e5
RH
399 switch(ch){
400 case NEEDCHAR:
401 if ( (inbufptr = fillinbuffer()) != 0){
402 ch = '\n';
403 goto stuff;
404 }
405 /*FALLTHROUGH*/
406 case EOFCHAR:
407 pchar(rcp, '\n');
3bd55f52 408 ungetc(EOFCHAR);
ad67d5e5
RH
409 goto tailDQ;
410 default:
3bd55f52
RH
411 ungetc(ch);
412 ch = '\n';
413 goto stuff;
414 }
ad67d5e5
RH
415 break;
416
417 case '\\':
3bd55f52
RH
418 ch = getchar(); /*skip the '\\'*/
419 if ( INCHARSET(ch, BSESCAPE)){
420 switch (ch){
421 case 'b': ch = '\b'; goto stuff;
422 case 'f': ch = '\f'; goto stuff;
423 case 'n': ch = '\n'; goto stuff;
424 case 'r': ch = '\r'; goto stuff;
425 case 't': ch = '\t'; goto stuff;
426 }
427 }
ad67d5e5
RH
428 if ( !(INCHARSET(ch, OCTDIGIT)) )
429 goto stuff;
3bd55f52
RH
430 i = 0;
431 intval = 0;
432 while ( (i < 3) && (INCHARSET(ch, OCTDIGIT))){
ad67d5e5
RH
433 i++;
434 intval <<= 3;
435 intval += ch - '0';
3bd55f52
RH
436 ch = getchar();
437 }
438 ungetc(ch);
8a7e35d9 439 ch = (char)intval;
3bd55f52 440 goto stuff;
ad67d5e5 441 }
3bd55f52 442 }
ad67d5e5 443 tailDQ: ;
3bd55f52 444 /*
ad67d5e5 445 * account for any lines that were crossed
3bd55f52 446 */
3bd55f52 447 if (linescrossed){
ad67d5e5
RH
448 ptoken(bufptr, ILINESKIP);
449 pint(bufptr, linescrossed);
450 }
451 /*
452 * put the string in yytext into the string pool
453 *
454 * The value in ryylval points to the string;
455 * the previous 2 bytes is the length of the string
456 *
457 * Cheat: append a trailing null to the string
458 * and then adjust the string length to ignore
459 * the trailing null. If any STRING client requires
460 * the trailing null, the client can just change STRLEN
461 */
462 val = STRING;
463 *rcp++ = 0;
464 ryylval = (int)savestr(yytext, rcp - yytext);
465 STRLEN(((char *)ryylval)) -= 1;
466 goto ret;
3bd55f52
RH
467
468 case BADCHAR:
469 linescrossed = lineno;
470 lineno = scanlineno;
471 yyerror("Illegal character mapped: %d, char read:(octal) %o",
472 ryylval, ch);
473 lineno = linescrossed;
474 val = BADCHAR;
475 goto ret;
476
477 default:
478 val = ryylval;
479 goto ret;
480 } /*end of the switch*/
481 /*
482 * here with one token, so stuff it
483 */
484 ret:
485 oval = val;
486 ptoken(bufptr, val);
487 switch(val){
488 case ILINESKIP:
489 pint(bufptr, ryylval);
490 break;
491 case SIZESPEC:
492 pchar(bufptr, ryylval);
493 break;
494 case BFINT: plong(bufptr, ryylval);
495 break;
496 case INT: plong(bufptr, ryylval);
497 break;
498 case BIGNUM: pnumber(bufptr, yybignum);
499 break;
ad67d5e5
RH
500 case STRING: pptr(bufptr, (int)(char *)ryylval);
501 break;
3bd55f52
RH
502 case NAME: pptr(bufptr, (int)(struct symtab *)ryylval);
503 break;
504 case REG: pchar(bufptr, ryylval);
505 break;
506 case INST0:
507 case INSTn:
508 popcode(bufptr, opstruct);
509 break;
510 case IJXXX:
511 popcode(bufptr, opstruct);
512 pptr(bufptr, (int)(struct symtab *)symalloc());
513 break;
514 case ISTAB:
515 case ISTABSTR:
516 case ISTABNONE:
517 case ISTABDOT:
518 case IALIGN:
519 pptr(bufptr, (int)(struct symtab *)symalloc());
520 break;
521 /*
522 * default:
523 */
524 }
525 builtval: ;
526 } /*end of the while to stuff the buffer*/
527 done:
528 bufferbox->tok_count = (bytetoktype *)bufptr - &(bufferbox->toks[0]);
529
530 /*
531 * This is a real kludge:
532 *
533 * We put the last token in the buffer to be a MINUS
534 * symbol. This last token will never be picked up
535 * in the normal way, but can be looked at during
536 * a peekahead look that the short circuit expression
537 * evaluator uses to see if an expression is complicated.
538 *
539 * Consider the following situation:
540 *
541 * .word 45 + 47
542 * buffer 1 | buffer 0
543 * the peekahead would want to look across the buffer,
544 * but will look in the buffer end zone, see the minus, and
545 * fail.
546 */
547 ptoken(bufptr, MINUS);
548 InBufPtr = inbufptr; /*copy this back*/
549}