use struct nlist; change field names; vgrind format fixes
[unix-history] / usr / src / old / as.vax / asscan.c
CommitLineData
ce996e48 1/* Copyright (c) 1980 Regents of the University of California */
451260e7 2static char sccsid[] = "@(#)asscan.c 4.3 %G%";
ce996e48 3#include <stdio.h>
ce996e48
BJ
4#include "as.h"
5#include "asscan.h"
6
7/*
8 * NOTE:
9 * This version of the assembler does not use fread and fwrite
10 * for the token buffering. The token buffers are integrals of BUFSIZ
11 * at all times, so we use direct read and write. fread and fwrite
12 * as supplied from BTL in stdio are HORRENDOUSLY inefficient,
13 * as they use putchar for each character, nested two deep in loops.
14 */
15#define writeTEST(pointer, size, nelements, ioptr) \
16 write(ioptr->_file, pointer, nelements * size) != nelements * size
17
18#define readTEST(pointer, size, nelements, ioptr) \
19 read(ioptr->_file, pointer, nelements * size) != nelements * size
20/*
21 * Variables to manage the token buffering.
22 * We scan (lexically analyze) a large number of tokens, and
23 * then parse all of the tokens in the scan buffer.
24 * This reduces procedure call overhead when the parser
25 * demands a token, allows for an efficient reread during
26 * the second pass, and confuses the line number reporting
27 * for errors encountered in the scanner and in the parser.
28 */
29#define TOKDALLOP 8
30struct tokbufdesc *bufstart; /*where the buffer list begins*/
31struct tokbufdesc *buftail; /*last one on the list*/
32struct tokbufdesc *emptybuf; /*the one being filled*/
33/*
34 * If we are using VM, during the second pass we reclaim the used
35 * token buffers for saving the relocation information
36 */
37struct tokbufdesc *tok_free; /* free pool */
38struct tokbufdesc *tok_temp; /* temporary for doing list manipulation */
39/*
40 * Other token buffer managers
41 */
42int bufno; /*which buffer number: 0,1 for tmp file*/
43struct tokbufdesc tokbuf[2]; /*our initial increment of buffers*/
44ptrall tokptr; /*where the current token comes from*/
45ptrall tokub; /*the last token in the current token buffer*/
46
47/*
48 * Variables to manage the string buffering
49 * declared in asscan.h.
50 */
51int strno; /*the current string being filled*/
52struct strdesc strbuf[3]; /*the string buffers; the first for nulls*/
53struct strdesc *strptr; /*current string buffer being filled*/
54
55inittmpfile()
56{
57 if (passno == 1){
58 if (useVM){
59 bufstart = &tokbuf[0];
60 buftail = &tokbuf[1];
61 bufstart->tok_next = buftail;
62 buftail->tok_next = 0;
63 }
64 tokbuf[0].tok_count = -1;
65 tokbuf[1].tok_count = -1;
66 }
67 tok_temp = 0;
68 tok_free = 0;
69 bufno = 0;
70 emptybuf = &tokbuf[bufno];
71 tokptr = 0;
72 tokub = 0;
73}
74
75closetmpfile()
76{
77 if (passno == 1){
78 if (useVM){
79 emptybuf->toks[emptybuf->tok_count++] = PARSEEOF;
80 } else {
81 /*
82 * Clean up the buffers that haven't been
83 * written out yet
84 */
85 if (tokbuf[bufno ^ 1].tok_count >= 0){
86 if (writeTEST((char *)&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tmpfil)){
87 badwrite:
88 yyerror("Unexpected end of file writing the interpass tmp file");
89 exit(2);
90 }
91 }
92 /*
93 * Ensure that we will read an End of file,
94 * if there are more than one file names
95 * in the argument list
96 */
97 tokbuf[bufno].toks[tokbuf[bufno].tok_count++] = PARSEEOF;
98 if (writeTEST((char *)&tokbuf[bufno], sizeof *emptybuf, 1, tmpfil))
99 goto badwrite;
100 }
101 } /*end of being pass 1*/
102}
103
104#define bstrlg(from, length) \
105 *(lgtype *)from = length; \
106 (char *)from += sizeof(lgtype) + length
107
108#define bstrfromto(from,to) \
109 *(lgtype *)from = (char *)to - (char *)from - sizeof(lgtype); \
110 (char *)from += sizeof(lgtype) + (char *)to - (char *)from
111
112#define eatstrlg(from) \
113 (char *)from += sizeof(lgtype) + *(lgtype *)from
114
115#define bskiplg(from, length) \
116 *(lgtype *)from = length; \
117 (char *)from += sizeof(lgtype) + length
118
119#define bskipfromto(from, to) \
120 *(lgtype *)from = (toktype *)to - (toktype *)from - sizeof(lgtype); \
121 (char *)from += sizeof (lgtype) + (toktype *)to - (toktype *)from
122
123#define eatskiplg(from) \
124 (toktype *)from += sizeof(lgtype) + *(lgtype *)from
125
126#ifdef DEBUG
127 ptrall firsttoken;
128#endif DEBUG
129
130extern int yylval; /*global communication with parser*/
451260e7 131static int Lastjxxx; /*this ONLY shuts up cc; see below*/
ce996e48
BJ
132
133toktype yylex()
134{
135 register ptrall bufptr;
136 register toktype val;
137 register struct exp *locxp;
138
139 bufptr = tokptr; /*copy in the global value*/
140 top:
141 if (bufptr < tokub){
142 gtoken(val, bufptr);
143 switch(yylval = val){
144 case PARSEEOF :
145 yylval = val = PARSEEOF;
146 break;
147 case BFINT:
148 case INT:
149 if (xp >= &explist[NEXP])
150 yyerror("Too many expressions; try simplyfing");
151 else
152 locxp = xp++;
451260e7
RH
153 glong(locxp->e_xvalue, bufptr);
154 locxp->e_yvalue = 0;
ce996e48 155 makevalue:
451260e7
RH
156 locxp->e_xtype = XABS;
157 locxp->e_xloc = 0;
158 locxp->e_xname = NULL;
ce996e48
BJ
159 yylval = (int)locxp;
160 break;
161 case FLTNUM:
162 if (xp >= &explist[NEXP])
163 yyerror("Too many expressions; try simplyfing");
164 else
165 locxp = xp++;
166 gdouble( ( (union Double *)locxp)->dvalue, bufptr);
167 goto makevalue;
168 case QUAD:
169 if (xp >= &explist[NEXP])
170 yyerror("Too many expressions; try simplyfing");
171 else
172 locxp = xp++;
451260e7
RH
173 glong(locxp->e_xvalue, bufptr);
174 glong(locxp->e_yvalue, bufptr);
ce996e48
BJ
175 yylval = val = INT;
176 goto makevalue;
177 case NAME:
178 gptr(yylval, bufptr);
179 lastnam = (struct symtab *)yylval;
180 break;
181 case SIZESPEC:
182 case REG:
183 case INSTn:
184 case INST0:
185 gchar(yylval, bufptr);
186 break;
187 case IJXXX:
188 gchar(yylval, bufptr);
451260e7
RH
189 /* We can't cast Lastjxxx into (int *) here.. */
190 gptr(Lastjxxx, bufptr);
191 lastjxxx = (struct symtab *)Lastjxxx;
ce996e48
BJ
192 break;
193 case ILINESKIP:
194 gint(yylval, bufptr);
195 lineno += yylval;
196 goto top;
197 case SKIP:
198 eatskiplg(bufptr);
199 goto top;
200 case VOID:
201 goto top;
202 case STRING:
203 strptr = &strbuf[strno ^= 1];
204 strptr->str_lg = *((lgtype *)bufptr);
205 movestr(&strptr->str[0],
206 (char *)bufptr + sizeof(lgtype),
207 strptr->str_lg);
208 eatstrlg(bufptr);
209 yylval = (int)strptr;
210 break;
211 case ISTAB:
212 case ISTABSTR:
213 case ISTABNONE:
214 case ISTABDOT:
215 case IALIGN:
216 gptr(yylval, bufptr);
217 break;
218 }
219#ifdef DEBUG
220 if (toktrace){
221 char *tok_to_name();
222 printf("P: %d T#: %4d, %s ",
223 passno, bufptr - firsttoken, tok_to_name(val));
224 switch(val){
225 case INT: printf("val %d",
451260e7 226 ((struct exp *)yylval)->e_xvalue);
ce996e48
BJ
227 break;
228 case BFINT: printf("val %d",
451260e7 229 ((struct exp *)yylval)->e_xvalue);
ce996e48
BJ
230 break;
231 case QUAD: printf("val[msd] = 0x%x, val[lsd] = 0x%x.",
451260e7
RH
232 ((struct exp *)yylval)->e_xvalue,
233 ((struct exp *)yylval)->e_yvalue);
ce996e48
BJ
234 break;
235 case FLTNUM: printf("value %20.17f",
236 ((union Double *)yylval)->dvalue);
237 break;
238 case NAME: printf("\"%.8s\"",
451260e7 239 ((struct symtab *)yylval)->s_name);
ce996e48
BJ
240 break;
241 case REG: printf(" r%d",
242 yylval);
243 break;
244 case IJXXX:
245 case INST0:
246 case INSTn: printf("%.8s",
451260e7 247 itab[0xFF &yylval]->s_name);
ce996e48
BJ
248 break;
249 case STRING: printf("length %d ",
250 ((struct strdesc *)yylval)->str_lg);
251 printf("value\"%s\"",
252 ((struct strdesc *)yylval)->str);
253 break;
254 } /*end of the debug switch*/
255 printf("\n");
256 }
257#endif DEBUG
258
259 } else { /* start a new buffer */
260 if (useVM){
261 if (passno == 2){
262 tok_temp = emptybuf->tok_next;
263 emptybuf->tok_next = tok_free;
264 tok_free = emptybuf;
265 emptybuf = tok_temp;
266 } else {
267 emptybuf = emptybuf->tok_next;
268 }
269 bufno += 1;
270 if (emptybuf == 0){
271 struct tokbufdesc *newdallop;
272 int i;
273 if (passno == 2)
274 goto badread;
275 emptybuf = newdallop = (struct tokbufdesc *)
276 Calloc(TOKDALLOP, sizeof (struct tokbufdesc));
277 for (i=0; i < TOKDALLOP; i++){
278 buftail->tok_next = newdallop;
279 buftail = newdallop;
280 newdallop += 1;
281 }
282 buftail->tok_next = 0;
283 } /*end of need to get more buffers*/
284 (toktype *)bufptr = &(emptybuf->toks[0]);
285 if (passno == 1)
286 scan_dot_s(emptybuf);
287 } else { /*don't use VM*/
288 bufno ^= 1;
289 emptybuf = &tokbuf[bufno];
290 ((toktype *)bufptr) = &(emptybuf->toks[0]);
291 if (passno == 1){
292 /*
293 * First check if there are things to write
294 * out at all
295 */
296 if (emptybuf->tok_count >= 0){
297 if (writeTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){
298 badwrite:
299 yyerror("Unexpected end of file writing the interpass tmp file");
300 exit(2);
301 }
302 }
303 scan_dot_s(emptybuf);
304 } else { /*pass 2*/
305 if (readTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){
306 badread:
307 yyerror("Unexpected end of file while reading the interpass tmp file");
308 exit(1);
309 }
310 }
311 } /*end of using a real live file*/
312 (char *)tokub = (char *)bufptr + emptybuf->tok_count;
313#ifdef DEBUG
314 firsttoken = bufptr;
315 if (debug)
316 printf("created buffernumber %d with %d tokens\n",
317 bufno, emptybuf->tok_count);
318#endif DEBUG
319 goto top;
320 } /*end of reading/creating a new buffer*/
321 tokptr = bufptr; /*copy back the global value*/
322 return(val);
323} /*end of yylex*/
324
325
326buildskip(from, to)
327 register ptrall from, to;
328{
329 int diff;
330 register int frombufno;
331 register struct tokbufdesc *middlebuf;
332 /*
333 * check if from and to are in the same buffer
334 * from and to DIFFER BY AT MOST 1 buffer and to is
335 * always ahead of from, with to being in the buffer emptybuf
336 * points to.
337 * The hard part here is accounting for the case where the
338 * skip is to cross a buffer boundary; we must construct
339 * two skips.
340 *
341 * Figure out where the buffer boundary between from and to is
342 * It's easy in VM, as buffers increase to high memory, but
343 * w/o VM, we alternate between two buffers, and want
344 * to look at the exact middle of the contiguous buffer region.
345 */
346 middlebuf = useVM ? emptybuf : &tokbuf[1];
347 if ( ( (toktype *)from > (toktype *)middlebuf)
348 ^ ( (toktype *)to > (toktype *)middlebuf)
349 ){ /*split across a buffer boundary*/
350 ptoken(from, SKIP);
351 /*
352 * Set the skip so it lands someplace beyond
353 * the end of this buffer.
354 * When we pull this skip out in the second pass,
355 * we will temporarily move the current pointer
356 * out beyond the end of the buffer, but immediately
357 * do a compare and fail the compare, and then reset
358 * all the pointers correctly to point into the next buffer.
359 */
360 bskiplg(from, TOKBUFLG + 1);
361 /*
362 * Now, force from to be in the same buffer as to
363 */
364 (toktype *)from = (toktype *)&(emptybuf->toks[0]);
365 }
366 /*
367 * Now, to and from are in the same buffer
368 */
369 if (from > to)
370 yyerror("Internal error: bad skip construction");
371 else {
372 if ( (diff = (toktype *)to - (toktype *)from) >=
373 (sizeof(toktype) + sizeof(lgtype) + 1)) {
374 ptoken(from, SKIP);
375 bskipfromto(from, to);
376 } else {
377 for ( ; diff > 0; --diff)
378 ptoken(from, VOID);
379 }
380 }
381}
382
383movestr(to, from, lg)
384 register char *to, *from;
385 register int lg;
386{
387 if (lg <= 0) return;
388 do
389 *to++ = *from++;
390 while (--lg);
391}
392static int newfflag = 0;
393static char *newfname;
394int scanlineno; /*the scanner's linenumber*/
395
396new_dot_s(namep)
397 char *namep;
398{
399 newfflag = 1;
400 newfname = namep;
401 dotsname = namep;
402 lineno = 1;
403 scanlineno = 1;
404}
405
406/*
407 * Maps characters to their use in assembly language
408 */
409#define EOFCHAR (-1)
410#define NEEDCHAR (-2)
411
412readonly short type[] = {
413 NEEDSBUF, /*fill up the input buffer*/
414 SCANEOF, /*hit the hard end of file*/
415 SP, BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*\0..^G*/
416 BADCHAR,SP, NL, BADCHAR,BADCHAR,SP, BADCHAR,BADCHAR, /*BS..SI*/
417 BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*DLE..ETB*/
418 BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*CAN..US*/
419 SP, ORNOT, DQ, SH, LITOP, REGOP, AND, SQ, /*sp .. '*/
420 LP, RP, MUL, PLUS, CM, MINUS, ALPH, DIV, /*( .. /*/
421 DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /*0 .. 7*/
422 DIG, DIG, COLON, SEMI, LSH, BADCHAR,RSH, BADCHAR, /*8 .. ?*/
423 BADCHAR,ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*@ .. G*/
424 ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*H .. BADCHAR*/
425 ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*P .. V*/
426 ALPH, ALPH, ALPH, LB, BADCHAR,RB, XOR, ALPH,/*W .. _*/
427 SIZEQUOTE,ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*` .. g*/
428 ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*h .. o*/
429 ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*p .. v*/
430 ALPH, ALPH, ALPH, BADCHAR,IOR, BADCHAR,TILDE, BADCHAR,/*x .. del*/
431};
432
433/*
434 * The table of possible uses for each character to test set inclusion.
435 * Different than the above table, which knows about tokens yylex
436 * is to return.
437 */
438#define HEXFLAG 01 /* 'x' or 'X' */
439#define HEXLDIGIT 02 /* 'a' .. 'f' */
6cca131f 440#define HEXUDIGIT 04 /* 'A' .. 'F' */
ce996e48 441#define ALPHA 010 /* 'A' .. 'Z', 'a' .. 'z', '_'*/
6cca131f 442#define DIGIT 020 /* '0' .. '9' */
ce996e48 443#define FLOATEXP 040 /* 'd' 'e' 'D' 'E' */
6cca131f
RH
444#define SIGN 0100 /* '+' .. '-'*/
445#define REGDIGIT 0200 /* '0' .. '5' */
446#define SZSPECBEGIN 0400 /* 'b', 'B', 'l', 'L', 'w', 'W' */
447#define POINT 01000 /* '.' */
448#define SPACE 02000 /* '\t' or ' ' */
449#define BSESCAPE 04000 /* bnrtf */
450#define STRESCAPE 010000 /* '"', '\\', '\n' */
451#define OCTDIGIT 020000 /* '0' .. '7' */
ce996e48
BJ
452#define FLOATFLAG 040000 /* 'd', 'D', 'f', 'F' */
453 /*after leading 0*/
454
455readonly short charsets[] = {
456 0, 0, 0, 0, 0, 0, 0, 0, /*\0..^G*/
457 0, SPACE, STRESCAPE,0, 0, 0, 0, 0, /*BS..SI*/
458 0, 0, 0, 0, 0, 0, 0, 0, /*DLE..ETB*/
459 0, 0, 0, 0, 0, 0, 0, 0, /*CAN..US*/
460/* dollar is an alpha character */
461 SPACE, 0, STRESCAPE,0, ALPHA, 0, 0, 0, /*sp.. '*/
462 0, 0, 0, SIGN, 0, SIGN, POINT+ALPHA,0, /*( .. /*/
463 DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*0..1*/
464 DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*2..3*/
465 DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*4..5*/
466 DIGIT+OCTDIGIT, DIGIT+OCTDIGIT, /*6..7*/
467 DIGIT, DIGIT, 0, 0, 0, 0, 0, 0, /*8..?*/
468 0, /*@*/
469 ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+SZSPECBEGIN, /*A..B*/
470 ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+FLOATEXP+FLOATFLAG, /*C..D*/
471 ALPHA+HEXUDIGIT+FLOATEXP,ALPHA+HEXUDIGIT+FLOATFLAG, /*E..F*/
472 ALPHA, /*G*/
473 ALPHA, ALPHA, ALPHA, ALPHA, /*H..K*/
474 ALPHA+SZSPECBEGIN, ALPHA, ALPHA, ALPHA, /*L..O*/
475 ALPHA, ALPHA, ALPHA, ALPHA, /*P..S*/
476 ALPHA, ALPHA, ALPHA, ALPHA+SZSPECBEGIN, /*T..W*/
477 ALPHA+HEXFLAG, ALPHA, ALPHA, 0,STRESCAPE,0, 0, ALPHA,/*X.._*/
478
479 0,
480 ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+BSESCAPE+SZSPECBEGIN, /*a..b*/
481 ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+FLOATEXP+FLOATFLAG, /*c..d*/
482 ALPHA+HEXLDIGIT+FLOATEXP,ALPHA+HEXLDIGIT+BSESCAPE+FLOATFLAG, /*e..f*/
483 ALPHA, /*g*/
484 ALPHA, ALPHA, ALPHA, ALPHA, /*h..k*/
485 ALPHA+SZSPECBEGIN, ALPHA, ALPHA+BSESCAPE, ALPHA, /*l..o*/
486 ALPHA, ALPHA, ALPHA+BSESCAPE, ALPHA, /*p..s*/
487 ALPHA+BSESCAPE, ALPHA, ALPHA, ALPHA+SZSPECBEGIN,/*t..w*/
488 ALPHA+HEXFLAG, ALPHA, ALPHA, 0,0, 0, 0, 0, /*x..del*/
4890};
490
6cca131f 491#define INCHARSET(val, kind) (charsets[val] & (kind) )
ce996e48
BJ
492static toktype oval = NL;
493
494#define NINBUFFERS 2
495#define INBUFLG NINBUFFERS*BUFSIZ + 2
496 /*
497 * We have two input buffers; the first one is reserved
498 * for catching the tail of a line split across a buffer
499 * boundary; the other one are used for snarfing a buffer
500 * worth of .s source.
501 */
502static char inbuffer[INBUFLG];
503static char *InBufPtr = 0;
504
6cca131f
RH
505#ifdef getchar
506#undef getchar
ce996e48 507#endif
6cca131f 508#define getchar() *inbufptr++
ce996e48 509
6cca131f
RH
510#ifdef ungetc
511#undef ungetc
ce996e48
BJ
512#endif
513#define ungetc(char) *--inbufptr = char
514
515/*
516 * fill the inbuffer from the standard input.
517 * Assert: there are always n COMPLETE! lines in the buffer area.
518 * Assert: there is always a \n terminating the last line
519 * in the buffer area.
520 * Assert: after the \n, there is an EOFCHAR (hard end of file)
521 * or a NEEDCHAR (end of buffer)
522 * Assert: fgets always null pads the string it reads.
523 * Assert: no ungetc's are done at the end of a line or at the
524 * beginning of a line.
525 *
526 * We read a complete buffer of characters in one single read.
527 * We then back scan within this buffer to find the end of the
528 * last complete line, and force the assertions, and save a pointer
529 * to the incomplete line.
530 * The next call to fillinbuffer will move the unread characters
531 * to the end of the first buffer, and then read another two buffers,
532 * completing the cycle.
533 */
534
535static char p_swapped = '\0';
536static char *p_start = &inbuffer[NINBUFFERS * BUFSIZ];
537static char *p_stop = &inbuffer[NINBUFFERS * BUFSIZ];
538char *fillinbuffer()
539{
540 register char *to;
541 register char *from;
542 char *inbufptr;
543 int nread;
544
545 *p_start = p_swapped;
546 inbufptr = &inbuffer[1*BUFSIZ] - (p_stop - p_start);
547
548 for (to = inbufptr, from = p_start; from < p_stop;)
549 *to++ = *from++;
550 /*
551 * Now, go read two full buffers (hopefully)
552 */
553 nread = read(stdin->_file, &inbuffer[1*BUFSIZ], (NINBUFFERS - 1)*BUFSIZ);
554 if (nread == 0)
555 return(0);
556 p_stop = from = &inbuffer[1*BUFSIZ + nread];
557 *from = '\0';
558 while (*--from != '\n') /* back over the partial line */
559 continue;
560 from++; /* first char of partial line */
561 p_start = from;
562 p_swapped = *p_start;
563 *p_start = NEEDCHAR; /* force assertion */
564 return(inbufptr);
565}
566
567scan_dot_s(bufferbox)
568 struct tokbufdesc *bufferbox;
569{
570 register int yylval;/*lexical value*/
571 register toktype val; /*the value returned; the character read*/
572 register int base; /*the base of the number also counter*/
573 register char *cp;
574 register char *inbufptr;
575 register struct symtab *op;
576 register unsigned char tag;
577 int forb;
578
579 register ptrall bufptr; /*where to stuff tokens*/
580 ptrall lgbackpatch; /*where to stuff a string length*/
581 ptrall bufub; /*where not to stuff tokens*/
582 register int maxstrlg; /*how long a string can be*/
583 long intval; /*value of int*/
584 char fltchr[64]; /*buffer for floating values*/
585 union Double fltval; /*floating value returned*/
586 struct Quad quadval; /*quad returned from immediate constant */
587 int linescrossed; /*when doing strings and comments*/
588
589 (toktype *)bufptr = (toktype *) & (bufferbox->toks[0]);
590 (toktype *)bufub = &(bufferbox->toks[AVAILTOKS]);
591
592 inbufptr = InBufPtr;
593 if (inbufptr == 0){
594 inbufptr = fillinbuffer();
595 if (inbufptr == 0){ /*end of file*/
596 endoffile:
597 inbufptr = 0;
598 ptoken(bufptr, PARSEEOF);
599 goto done;
600 }
601 }
602
603 if (newfflag){
604 ptoken(bufptr, IFILE);
605 ptoken(bufptr, STRING);
606 val = strlen(newfname) + 1;
607 movestr( (char *)&( ( (lgtype *)bufptr)[1]), newfname, val);
608 bstrlg(bufptr, val);
609
610 ptoken(bufptr, ILINENO);
611 ptoken(bufptr, INT);
612 pint(bufptr, 1);
613 newfflag = 0;
614 }
615
616 while (bufptr < bufub){
617 loop:
618 switch(yylval = (type+2)[val = getchar()]) {
619 case SCANEOF:
620 inbufptr = 0;
621 goto endoffile;
622
623 case NEEDSBUF:
624 inbufptr = fillinbuffer();
625 if (inbufptr == 0)
626 goto endoffile;
627 goto loop;
628
629 case DIV: /*process C style comments*/
630 if ( (val = getchar()) == '*') { /*comment prelude*/
631 int incomment;
632 linescrossed = 0;
633 incomment = 1;
634 val = getchar(); /*skip over the * */
635 do{
636 while ( (val != '*') &&
637 (val != '\n') &&
638 (val != EOFCHAR) &&
639 (val != NEEDCHAR))
640 val = getchar();
641 if (val == '\n'){
642 scanlineno++;
643 linescrossed++;
644 } else
645 if (val == EOFCHAR)
646 goto endoffile;
647 if (val == NEEDCHAR){
648 inbufptr = fillinbuffer();
649 if (inbufptr == 0)
650 goto endoffile;
651 lineno++;
652 incomment = 1;
653 val = getchar(); /*pull in the new char*/
654 } else { /*its a star */
655 val = getchar();
656 incomment = val != '/';
657 }
658 } while (incomment);
659 val = ILINESKIP;
660 yylval = linescrossed;
661 goto ret;
662 } else { /*just an ordinary DIV*/
663 ungetc(val);
664 val = yylval = DIV;
665 goto ret;
666 }
667 case SH:
668 if (oval == NL){
669 /*
670 * Attempt to recognize a C preprocessor
671 * style comment '^#[ \t]*[0-9]*[ \t]*".*"
672 */
673 val = getchar(); /*bump the #*/
674 while (INCHARSET(val, SPACE))
675 val = getchar();/*bump white */
676 if (INCHARSET(val, DIGIT)){
677 intval = 0;
678 while(INCHARSET(val, DIGIT)){
679 intval = intval *10 + val - '0';
680 val = getchar();
681 }
682 while (INCHARSET(val, SPACE))
683 val = getchar();
684 if (val == '"'){
685 ptoken(bufptr, ILINENO);
686 ptoken(bufptr, INT);
687 pint(bufptr, intval - 1);
688 ptoken(bufptr, IFILE);
689 /*
690 * The '"' has already been
691 * munched
692 *
693 * eatstr will not eat
694 * the trailing \n, so
695 * it is given to the parser
696 * and counted.
697 */
698 goto eatstr;
699 }
700 }
701 }
702 /*
703 * Well, its just an ordinary decadent comment
704 */
705 while ((val != '\n') && (val != EOFCHAR))
706 val = getchar();
707 if (val == EOFCHAR)
708 goto endoffile;
709 val = yylval = oval = NL;
710 scanlineno++;
711 goto ret;
712
713 case NL:
714 scanlineno++;
715 val = yylval;
716 goto ret;
717
718 case SP:
719 oval = SP; /*invalidate ^# meta comments*/
720 goto loop;
721
722 case REGOP: /* % , could be used as modulo, or register*/
723 val = getchar();
724 if (INCHARSET(val, DIGIT)){
725 yylval = val-'0';
726 if (val=='1') {
727 if (INCHARSET( (val = getchar()), REGDIGIT))
728 yylval = 10+val-'0';
729 else
730 ungetc(val);
731 }
732 /*
733 * God only knows what the original author
734 * wanted this undocumented feature to
735 * do.
736 * %5++ is really r7
737 */
738 while(INCHARSET( (val = getchar()), SIGN)) {
739 if (val=='+')
740 yylval++;
741 else
742 yylval--;
743 }
744 ungetc(val);
745 val = REG;
746 } else {
747 ungetc(val);
748 val = REGOP;
749 }
750 goto ret;
751
752 case ALPH:
753 yylval = val;
754 if (INCHARSET(val, SZSPECBEGIN)){
755 if( (val = getchar()) == '`' || val == '^'){
756 yylval |= 0100; /*convert to lower*/
757 if (yylval == 'b') yylval = 1;
758 else if (yylval == 'w') yylval = 2;
759 else if (yylval == 'l') yylval = 4;
760 else yylval = d124;
761 val = SIZESPEC;
762 goto ret;
763 } else {
764 ungetc(val);
765 val = yylval; /*restore first character*/
766 }
767 }
768 cp = yytext;
769 do {
770 if (cp < &yytext[NCPS])
771 *cp++ = val;
772 } while (INCHARSET ( (val = getchar()), ALPHA | DIGIT));
773 *cp = '\0';
774 while (INCHARSET(val, SPACE))
775 val = getchar();
776 ungetc(val);
777 doit:
451260e7 778 tag = (op = *lookup(1))->s_tag;
ce996e48 779 if (tag && tag != LABELID){
451260e7
RH
780 yylval = ( (struct instab *)op)->i_opcode;
781 val = op->s_tag ;
ce996e48
BJ
782 goto ret;
783 } else {
784 /*
785 * Its a name... (Labels are subsets ofname)
786 */
787 yylval = (int)op;
788 val = NAME;
789 goto ret;
790 }
791
792 case DIG:
793 base = 10;
794 cp = fltchr;
795 intval = 0;
796 if (val=='0') {
797 val = getchar();
798 if (val == 'b') {
799 yylval = -1;
800 val = BFINT;
801 goto ret;
802 }
803 if (INCHARSET(val, HEXFLAG)){
804 base = 16;
805 } else
806 if (INCHARSET(val, FLOATFLAG)){
807 double atof();
808 while ( (cp < &fltchr[63]) &&
809 INCHARSET(
810 (val=getchar()),
811 (DIGIT|SIGN|FLOATEXP|POINT)
812 )
813 ) *cp++ = val;
814 if (cp == fltchr) {
815 yylval = 1;
816 val = BFINT;
817 goto ret;
818 }
819 ungetc(val);
820 *cp++ = '\0';
821 fltval.dvalue = atof(fltchr);
822 val = FLTNUM;
823 goto ret;
824 } else {
825 ungetc(val);
826 base = 8;
827 }
828 } else {
829 forb = getchar();
830 if (forb == 'f' || forb == 'b') {
831 yylval = val - '0' + 1;
832 if (forb == 'b')
833 yylval = -yylval;
834 val = BFINT;
835 goto ret;
836 }
837 ungetc(forb); /* put back non zero */
838 goto middle;
839 }
840 while ( (val = getchar()) == '0')
841 continue;
842 ungetc(val);
843 while ( INCHARSET( (val = getchar()), DIGIT) ||
844 (base==16 && (INCHARSET(val, HEXLDIGIT|HEXUDIGIT) )
845 )
846 ){
847 if (base==8)
848 intval <<= 3;
849 else if (base==10)
850 intval *= 10;
851 else {
852 intval <<= 4;
853 if (INCHARSET(val, HEXLDIGIT))
854 val -= 'a' - 10 - '0';
855 else if (INCHARSET(val, HEXUDIGIT))
856 val -= 'A' - 10 - '0';
857 }
858middle:
859 *cp++ = (val -= '0');
860 intval += val;
861 }
862 ungetc(val);
863 *cp = 0;
864 maxstrlg = cp - fltchr;
865 if ( (maxstrlg > 8)
866 && ( ( (base == 8)
867 && ( (maxstrlg>11)
868 || ( (maxstrlg == 11)
869 && (*fltchr > 3)
870 )
871 )
872 )
873 || ( (base == 16)
874 && (maxstrlg > 8)
875 )
876 || ( (base == 10)
877 && (maxstrlg >= 10)
878 )
879 )
880 ) {
881 val = QUAD;
882 get_quad(base, fltchr, cp, &quadval);
883 } else
884 val = INT;
885 goto ret;
886
887 case LSH:
888 case RSH:
889 /*
890 * We allow the C style operators
891 * << and >>, as well as < and >
892 */
893 if ( (base = getchar()) != val)
894 ungetc(base);
895 val = yylval;
896 goto ret;
897
898 case MINUS:
899 if ( (val = getchar()) =='(')
900 yylval=val=MP;
901 else {
902 ungetc(val);
903 val=MINUS;
904 }
905 goto ret;
906
907 case SQ:
908 if ((yylval = getchar()) == '\n')
909 scanlineno++; /*not entirely correct*/
910 intval = yylval;
911 val = INT;
912 goto ret;
913
914 case DQ:
915 eatstr:
916 linescrossed = 0;
917 maxstrlg = (char *)bufub - (char *)bufptr;
918
919 if (maxstrlg < MAXSTRLG) {
920 ungetc('"');
921 *(toktype *)bufptr = VOID ;
922 bufub = bufptr;
923 goto done;
924 }
925 if (maxstrlg > MAXSTRLG)
926 maxstrlg = MAXSTRLG;
927
928 ptoken(bufptr, STRING);
929 lgbackpatch = bufptr; /*this is where the size goes*/
930 bufptr += sizeof(lgtype);
931 /*
932 * bufptr is now set to
933 * be stuffed with characters from
934 * the input
935 */
936
937 while ( (maxstrlg > 0)
938 && !(INCHARSET( (val = getchar()), STRESCAPE))
939 ){
940 stuff:
941 maxstrlg-= 1;
942 pchar(bufptr, val);
943 }
944 if (maxstrlg <= 0){ /*enough characters to fill a string buffer*/
945 ungetc('"'); /*will read it next*/
946 }
947 else if (val == '"'); /*done*/
948 else if (val == '\n'){
949 scanlineno++;
950 linescrossed++;
951 val = getchar();
952 if (val == EOFCHAR){
953 do_eof:
954 pchar(bufptr, '\n');
955 ungetc(EOFCHAR);
956 } else
957 if (val == NEEDCHAR){
958 if ( (inbufptr = fillinbuffer()) == 0)
959 goto do_eof;
960 val = '\n';
961 goto stuff;
962 } else { /* simple case */
963 ungetc(val);
964 val = '\n';
965 goto stuff;
966 }
967 } else {
968 val = getchar(); /*skip the '\\'*/
969 if ( INCHARSET(val, BSESCAPE)){
970 switch (val){
971 case 'b': val = '\b'; goto stuff;
972 case 'f': val = '\f'; goto stuff;
973 case 'n': val = '\n'; goto stuff;
974 case 'r': val = '\r'; goto stuff;
975 case 't': val = '\t'; goto stuff;
976 }
977 }
978 if ( !(INCHARSET(val,OCTDIGIT)) ) goto stuff;
979 base = 0;
980 intval = 0;
981 while ( (base < 3) && (INCHARSET(val, OCTDIGIT))){
982 base++;intval <<= 3;intval += val - '0';
983 val = getchar();
984 }
985 ungetc(val);
986 val = (char)intval;
987 goto stuff;
988 }
989 /*
990 * bufptr now points at the next free slot
991 */
992 bstrfromto(lgbackpatch, bufptr);
993 if (linescrossed){
994 val = ILINESKIP;
995 yylval = linescrossed;
996 goto ret;
997 } else
998 goto builtval;
999
1000 case BADCHAR:
1001 linescrossed = lineno;
1002 lineno = scanlineno;
1003 yyerror("Illegal character mapped: %d, char read:(octal) %o",
1004 yylval, val);
1005 lineno = linescrossed;
1006 val = BADCHAR;
1007 goto ret;
1008
1009 default:
1010 val = yylval;
1011 goto ret;
1012 } /*end of the switch*/
1013 /*
1014 * here with one token, so stuff it
1015 */
1016 ret:
1017 oval = val;
1018 ptoken(bufptr, val);
1019 switch(val){
1020 case ILINESKIP:
1021 pint(bufptr, yylval);
1022 break;
1023 case SIZESPEC:
1024 pchar(bufptr, yylval);
1025 break;
1026 case BFINT: plong(bufptr, yylval);
1027 break;
1028 case INT: plong(bufptr, intval);
1029 break;
1030 case QUAD: plong(bufptr, quadval.quad_low_long);
1031 plong(bufptr, quadval.quad_high_long);
1032 break;
1033 case FLTNUM: pdouble(bufptr, fltval.dvalue);
1034 break;
1035 case NAME: pptr(bufptr, (int)(struct symtab *)yylval);
1036 break;
1037 case REG: pchar(bufptr, yylval);
1038 break;
1039 case INST0:
1040 case INSTn:
1041 pchar(bufptr, yylval);
1042 break;
1043 case IJXXX:
1044 pchar(bufptr, yylval);
1045 pptr(bufptr, (int)(struct symtab *)symalloc());
1046 break;
1047 case ISTAB:
1048 case ISTABSTR:
1049 case ISTABNONE:
1050 case ISTABDOT:
1051 case IALIGN:
1052 pptr(bufptr, (int)(struct symtab *)symalloc());
1053 break;
1054 /*
1055 * default:
1056 */
1057 }
1058 builtval: ;
1059 } /*end of the while to stuff the buffer*/
1060 done:
1061 bufferbox->tok_count = (toktype *)bufptr - &(bufferbox->toks[0]);
1062
1063 /*
1064 * This is a real kludge:
1065 *
1066 * We put the last token in the buffer to be a MINUS
1067 * symbol. This last token will never be picked up
1068 * in the normal way, but can be looked at during
1069 * a peekahead look that the short circuit expression
1070 * evaluator uses to see if an expression is complicated.
1071 *
1072 * Consider the following situation:
1073 *
1074 * .word 45 + 47
1075 * buffer 1 | buffer 0
1076 * the peekahead would want to look across the buffer,
1077 * but will look in the buffer end zone, see the minus, and
1078 * fail.
1079 */
1080 ptoken(bufptr, MINUS);
1081 InBufPtr = inbufptr; /*copy this back*/
1082}
1083
1084struct Quad _quadtemp;
1085get_quad(radix, cp_start, cp_end, quadptr)
1086 int radix;
1087 char *cp_start, *cp_end;
1088 struct Quad *quadptr;
1089{
1090 register char *cp = cp_start; /* r11 */
1091 register struct Quad *qp = quadptr; /* r10 */
1092 register long temp; /* r9 */
1093
1094 asm("clrq (r10)");
1095 for (; cp < cp_end; cp++){
1096 switch (radix) {
1097 case 8:
1098 asm ("ashq $3, (r10), (r10)");
1099 break;
1100 case 16:
1101 asm ("ashq $4, (r10), (r10)");
1102 break;
1103 case 10:
1104 asm ("ashq $1, (r10), __quadtemp");
1105 asm ("ashq $3, (r10), (r10)");
1106 asm ("addl2 __quadtemp, (r10)");
1107 asm ("adwc __quadtemp+4, 4(r10)");
1108 break;
1109 }
1110 asm ("cvtbl (r11), r9");
1111 asm ("addl2 r9, (r10)");
1112 asm ("adwc $0, 4(r10)");
1113 }
1114}