|
|
1.1 root 1: /* Copyright (c) 1980 Regents of the University of California */
2: static char sccsid[] = "@(#)asscan.c 4.6 9/8/80";
3: #include <stdio.h>
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
30: struct tokbufdesc *bufstart; /*where the buffer list begins*/
31: struct tokbufdesc *buftail; /*last one on the list*/
32: struct 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: */
37: struct tokbufdesc *tok_free; /* free pool */
38: struct tokbufdesc *tok_temp; /* temporary for doing list manipulation */
39: /*
40: * Other token buffer managers
41: */
42: int bufno; /*which buffer number: 0,1 for tmp file*/
43: struct tokbufdesc tokbuf[2]; /*our initial increment of buffers*/
44: ptrall tokptr; /*where the current token comes from*/
45: ptrall tokub; /*the last token in the current token buffer*/
46:
47: /*
48: * Variables to manage the string buffering
49: * declared in asscan.h.
50: */
51: int strno; /*the current string being filled*/
52: struct strdesc strbuf[3]; /*the string buffers; the first for nulls*/
53: struct strdesc *strptr; /*current string buffer being filled*/
54:
55: inittmpfile()
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:
75: closetmpfile()
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:
130: extern int yylval; /*global communication with parser*/
131: static int Lastjxxx; /*this ONLY shuts up cc; see below*/
132:
133: toktype 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++;
153: glong(locxp->e_xvalue, bufptr);
154: locxp->e_yvalue = 0;
155: makevalue:
156: locxp->e_xtype = XABS;
157: locxp->e_xloc = 0;
158: locxp->e_xname = NULL;
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++;
173: glong(locxp->e_xvalue, bufptr);
174: glong(locxp->e_yvalue, bufptr);
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);
189: /* We can't cast Lastjxxx into (int *) here.. */
190: gptr(Lastjxxx, bufptr);
191: lastjxxx = (struct symtab *)Lastjxxx;
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",
226: ((struct exp *)yylval)->e_xvalue);
227: break;
228: case BFINT: printf("val %d",
229: ((struct exp *)yylval)->e_xvalue);
230: break;
231: case QUAD: printf("val[msd] = 0x%x, val[lsd] = 0x%x.",
232: ((struct exp *)yylval)->e_xvalue,
233: ((struct exp *)yylval)->e_yvalue);
234: break;
235: case FLTNUM: printf("value %20.17f",
236: ((union Double *)yylval)->dvalue);
237: break;
238: case NAME: printf("\"%.8s\"",
239: ((struct symtab *)yylval)->s_name);
240: break;
241: case REG: printf(" r%d",
242: yylval);
243: break;
244: case IJXXX:
245: case INST0:
246: case INSTn: printf("%.8s",
247: itab[0xFF &yylval]->s_name);
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:
326: buildskip(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:
383: movestr(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: }
392: static int newfflag = 0;
393: static char *newfname;
394: int scanlineno; /*the scanner's linenumber*/
395:
396: new_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:
412: readonly 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' */
440: #define HEXUDIGIT 04 /* 'A' .. 'F' */
441: #define ALPHA 010 /* 'A' .. 'Z', 'a' .. 'z', '_'*/
442: #define DIGIT 020 /* '0' .. '9' */
443: #define FLOATEXP 040 /* 'd' 'e' 'D' 'E' */
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' */
452: #define FLOATFLAG 040000 /* 'd', 'D', 'f', 'F' */
453: /*after leading 0*/
454:
455: readonly 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*/
489: 0};
490:
491: #define INCHARSET(val, kind) (charsets[val] & (kind) )
492: static 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: */
502: static char inbuffer[INBUFLG];
503: static char *InBufPtr = 0;
504:
505: #ifdef getchar
506: #undef getchar
507: #endif
508: #define getchar() *inbufptr++
509:
510: #ifdef ungetc
511: #undef ungetc
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:
535: static char p_swapped = '\0';
536: static char *p_start = &inbuffer[NINBUFFERS * BUFSIZ];
537: static char *p_stop = &inbuffer[NINBUFFERS * BUFSIZ];
538: char *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:
567: scan_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:
778: tag = (op = *lookup(1))->s_tag;
779: if (tag && tag != LABELID){
780: yylval = ( (struct instab *)op)->i_opcode;
781: val = op->s_tag ;
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 (val == 'f') {
804: /*
805: * Well, it appears to be a local label
806: * reference, but check to see if
807: * the next character makes it a floating
808: * point constant.
809: */
810: forb = getchar();
811: ungetc(forb);
812: if (!(INCHARSET(forb,(DIGIT|SIGN|FLOATEXP|POINT)))){
813: yylval = 1;
814: val = BFINT;
815: goto ret;
816: }
817: }
818: if (INCHARSET(val, HEXFLAG)){
819: base = 16;
820: } else
821: if (INCHARSET(val, FLOATFLAG)){
822: double atof();
823: while ( (cp < &fltchr[63]) &&
824: INCHARSET(
825: (val=getchar()),
826: (DIGIT|SIGN|FLOATEXP|POINT)
827: )
828: ) *cp++ = val;
829: if (cp == fltchr) {
830: yylval = 1;
831: val = BFINT;
832: goto ret;
833: }
834: ungetc(val);
835: *cp++ = '\0';
836: fltval.dvalue = atof(fltchr);
837: val = FLTNUM;
838: goto ret;
839: } else {
840: ungetc(val);
841: base = 8;
842: }
843: } else {
844: forb = getchar();
845: if (forb == 'f' || forb == 'b') {
846: yylval = val - '0' + 1;
847: if (forb == 'b')
848: yylval = -yylval;
849: val = BFINT;
850: goto ret;
851: }
852: ungetc(forb); /* put back non zero */
853: goto middle;
854: }
855: while ( (val = getchar()) == '0')
856: continue;
857: ungetc(val);
858: while ( INCHARSET( (val = getchar()), DIGIT) ||
859: (base==16 && (INCHARSET(val, HEXLDIGIT|HEXUDIGIT) )
860: )
861: ){
862: if (base==8)
863: intval <<= 3;
864: else if (base==10)
865: intval *= 10;
866: else {
867: intval <<= 4;
868: if (INCHARSET(val, HEXLDIGIT))
869: val -= 'a' - 10 - '0';
870: else if (INCHARSET(val, HEXUDIGIT))
871: val -= 'A' - 10 - '0';
872: }
873: middle:
874: *cp++ = (val -= '0');
875: intval += val;
876: }
877: ungetc(val);
878: *cp = 0;
879: maxstrlg = cp - fltchr;
880: if ( (maxstrlg > 8)
881: && ( ( (base == 8)
882: && ( (maxstrlg>11)
883: || ( (maxstrlg == 11)
884: && (*fltchr > 3)
885: )
886: )
887: )
888: || ( (base == 16)
889: && (maxstrlg > 8)
890: )
891: || ( (base == 10)
892: && (maxstrlg >= 10)
893: )
894: )
895: ) {
896: val = QUAD;
897: get_quad(base, fltchr, cp, &quadval);
898: } else
899: val = INT;
900: goto ret;
901:
902: case LSH:
903: case RSH:
904: /*
905: * We allow the C style operators
906: * << and >>, as well as < and >
907: */
908: if ( (base = getchar()) != val)
909: ungetc(base);
910: val = yylval;
911: goto ret;
912:
913: case MINUS:
914: if ( (val = getchar()) =='(')
915: yylval=val=MP;
916: else {
917: ungetc(val);
918: val=MINUS;
919: }
920: goto ret;
921:
922: case SQ:
923: if ((yylval = getchar()) == '\n')
924: scanlineno++; /*not entirely correct*/
925: intval = yylval;
926: val = INT;
927: goto ret;
928:
929: case DQ:
930: eatstr:
931: linescrossed = 0;
932: maxstrlg = (char *)bufub - (char *)bufptr;
933:
934: if (maxstrlg < MAXSTRLG) {
935: ungetc('"');
936: *(toktype *)bufptr = VOID ;
937: bufub = bufptr;
938: goto done;
939: }
940: if (maxstrlg > MAXSTRLG)
941: maxstrlg = MAXSTRLG;
942:
943: ptoken(bufptr, STRING);
944: lgbackpatch = bufptr; /*this is where the size goes*/
945: bufptr += sizeof(lgtype);
946: /*
947: * bufptr is now set to
948: * be stuffed with characters from
949: * the input
950: */
951:
952: while ( (maxstrlg > 0)
953: && !(INCHARSET( (val = getchar()), STRESCAPE))
954: ){
955: stuff:
956: maxstrlg-= 1;
957: pchar(bufptr, val);
958: }
959: if (maxstrlg <= 0){ /*enough characters to fill a string buffer*/
960: ungetc('"'); /*will read it next*/
961: }
962: else if (val == '"'); /*done*/
963: else if (val == '\n'){
964: yywarning("New line embedded in a string constant.");
965: scanlineno++;
966: linescrossed++;
967: val = getchar();
968: if (val == EOFCHAR){
969: do_eof:
970: pchar(bufptr, '\n');
971: ungetc(EOFCHAR);
972: } else
973: if (val == NEEDCHAR){
974: if ( (inbufptr = fillinbuffer()) == 0)
975: goto do_eof;
976: val = '\n';
977: goto stuff;
978: } else { /* simple case */
979: ungetc(val);
980: val = '\n';
981: goto stuff;
982: }
983: } else {
984: val = getchar(); /*skip the '\\'*/
985: if ( INCHARSET(val, BSESCAPE)){
986: switch (val){
987: case 'b': val = '\b'; goto stuff;
988: case 'f': val = '\f'; goto stuff;
989: case 'n': val = '\n'; goto stuff;
990: case 'r': val = '\r'; goto stuff;
991: case 't': val = '\t'; goto stuff;
992: }
993: }
994: if ( !(INCHARSET(val,OCTDIGIT)) ) goto stuff;
995: base = 0;
996: intval = 0;
997: while ( (base < 3) && (INCHARSET(val, OCTDIGIT))){
998: base++;intval <<= 3;intval += val - '0';
999: val = getchar();
1000: }
1001: ungetc(val);
1002: val = (char)intval;
1003: goto stuff;
1004: }
1005: /*
1006: * bufptr now points at the next free slot
1007: */
1008: bstrfromto(lgbackpatch, bufptr);
1009: if (linescrossed){
1010: val = ILINESKIP;
1011: yylval = linescrossed;
1012: goto ret;
1013: } else
1014: goto builtval;
1015:
1016: case BADCHAR:
1017: linescrossed = lineno;
1018: lineno = scanlineno;
1019: yyerror("Illegal character mapped: %d, char read:(octal) %o",
1020: yylval, val);
1021: lineno = linescrossed;
1022: val = BADCHAR;
1023: goto ret;
1024:
1025: default:
1026: val = yylval;
1027: goto ret;
1028: } /*end of the switch*/
1029: /*
1030: * here with one token, so stuff it
1031: */
1032: ret:
1033: oval = val;
1034: ptoken(bufptr, val);
1035: switch(val){
1036: case ILINESKIP:
1037: pint(bufptr, yylval);
1038: break;
1039: case SIZESPEC:
1040: pchar(bufptr, yylval);
1041: break;
1042: case BFINT: plong(bufptr, yylval);
1043: break;
1044: case INT: plong(bufptr, intval);
1045: break;
1046: case QUAD: plong(bufptr, quadval.quad_low_long);
1047: plong(bufptr, quadval.quad_high_long);
1048: break;
1049: case FLTNUM: pdouble(bufptr, fltval.dvalue);
1050: break;
1051: case NAME: pptr(bufptr, (int)(struct symtab *)yylval);
1052: break;
1053: case REG: pchar(bufptr, yylval);
1054: break;
1055: case INST0:
1056: case INSTn:
1057: pchar(bufptr, yylval);
1058: break;
1059: case IJXXX:
1060: pchar(bufptr, yylval);
1061: pptr(bufptr, (int)(struct symtab *)symalloc());
1062: break;
1063: case ISTAB:
1064: case ISTABSTR:
1065: case ISTABNONE:
1066: case ISTABDOT:
1067: case IALIGN:
1068: pptr(bufptr, (int)(struct symtab *)symalloc());
1069: break;
1070: /*
1071: * default:
1072: */
1073: }
1074: builtval: ;
1075: } /*end of the while to stuff the buffer*/
1076: done:
1077: bufferbox->tok_count = (toktype *)bufptr - &(bufferbox->toks[0]);
1078:
1079: /*
1080: * This is a real kludge:
1081: *
1082: * We put the last token in the buffer to be a MINUS
1083: * symbol. This last token will never be picked up
1084: * in the normal way, but can be looked at during
1085: * a peekahead look that the short circuit expression
1086: * evaluator uses to see if an expression is complicated.
1087: *
1088: * Consider the following situation:
1089: *
1090: * .word 45 + 47
1091: * buffer 1 | buffer 0
1092: * the peekahead would want to look across the buffer,
1093: * but will look in the buffer end zone, see the minus, and
1094: * fail.
1095: */
1096: ptoken(bufptr, MINUS);
1097: InBufPtr = inbufptr; /*copy this back*/
1098: }
1099:
1100: struct Quad _quadtemp;
1101: get_quad(radix, cp_start, cp_end, quadptr)
1102: int radix;
1103: char *cp_start, *cp_end;
1104: struct Quad *quadptr;
1105: {
1106: register char *cp = cp_start; /* r11 */
1107: register struct Quad *qp = quadptr; /* r10 */
1108: register long temp; /* r9 */
1109:
1110: asm("clrq (r10)");
1111: for (; cp < cp_end; cp++){
1112: switch (radix) {
1113: case 8:
1114: asm ("ashq $3, (r10), (r10)");
1115: break;
1116: case 16:
1117: asm ("ashq $4, (r10), (r10)");
1118: break;
1119: case 10:
1120: asm ("ashq $1, (r10), __quadtemp");
1121: asm ("ashq $3, (r10), (r10)");
1122: asm ("addl2 __quadtemp, (r10)");
1123: asm ("adwc __quadtemp+4, 4(r10)");
1124: break;
1125: }
1126: asm ("cvtbl (r11), r9");
1127: asm ("addl2 r9, (r10)");
1128: asm ("adwc $0, 4(r10)");
1129: }
1130: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.