X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/2b84abb596f52ab2068d52108adc96838ad4340a..31cef89cb428866f787983e68246030321893df4:/usr/src/cmd/as/asscan.c diff --git a/usr/src/cmd/as/asscan.c b/usr/src/cmd/as/asscan.c index ee3fd8cea2..6ba09c6ac1 100644 --- a/usr/src/cmd/as/asscan.c +++ b/usr/src/cmd/as/asscan.c @@ -1,20 +1,56 @@ -/* Copyright (c) 1979 Regents of the University of California */ +/* Copyright (c) 1980 Regents of the University of California */ +static char sccsid[] = "@(#)asscan.c 4.6 9/8/80"; #include #include "as.h" #include "asscan.h" -extern int d124; -extern struct exp *xp; - -struct tokbufdesc *bufstart; /*where the buffer list begins*/ -struct tokbufdesc *buftail; /*last one on the list*/ -struct tokbufdesc *emptybuf; /*the one being filled*/ +/* + * NOTE: + * This version of the assembler does not use fread and fwrite + * for the token buffering. The token buffers are integrals of BUFSIZ + * at all times, so we use direct read and write. fread and fwrite + * as supplied from BTL in stdio are HORRENDOUSLY inefficient, + * as they use putchar for each character, nested two deep in loops. + */ +#define writeTEST(pointer, size, nelements, ioptr) \ + write(ioptr->_file, pointer, nelements * size) != nelements * size +#define readTEST(pointer, size, nelements, ioptr) \ + read(ioptr->_file, pointer, nelements * size) != nelements * size +/* + * Variables to manage the token buffering. + * We scan (lexically analyze) a large number of tokens, and + * then parse all of the tokens in the scan buffer. + * This reduces procedure call overhead when the parser + * demands a token, allows for an efficient reread during + * the second pass, and confuses the line number reporting + * for errors encountered in the scanner and in the parser. + */ #define TOKDALLOP 8 +struct tokbufdesc *bufstart; /*where the buffer list begins*/ +struct tokbufdesc *buftail; /*last one on the list*/ +struct tokbufdesc *emptybuf; /*the one being filled*/ +/* + * If we are using VM, during the second pass we reclaim the used + * token buffers for saving the relocation information + */ +struct tokbufdesc *tok_free; /* free pool */ +struct tokbufdesc *tok_temp; /* temporary for doing list manipulation */ +/* + * Other token buffer managers + */ +int bufno; /*which buffer number: 0,1 for tmp file*/ +struct tokbufdesc tokbuf[2]; /*our initial increment of buffers*/ +ptrall tokptr; /*where the current token comes from*/ +ptrall tokub; /*the last token in the current token buffer*/ -int useVM; /*keep `tmp' file in virtual memory*/ -int bufno; /*which buffer number: 0,1 for tmp file*/ -struct tokbufdesc tokbuf[2]; /*our initial increment of buffers*/ +/* + * Variables to manage the string buffering + * declared in asscan.h. + */ +int strno; /*the current string being filled*/ +struct strdesc strbuf[3]; /*the string buffers; the first for nulls*/ +struct strdesc *strptr; /*current string buffer being filled*/ inittmpfile() { @@ -28,6 +64,8 @@ inittmpfile() tokbuf[0].tok_count = -1; tokbuf[1].tok_count = -1; } + tok_temp = 0; + tok_free = 0; bufno = 0; emptybuf = &tokbuf[bufno]; tokptr = 0; @@ -45,7 +83,7 @@ closetmpfile() * written out yet */ if (tokbuf[bufno ^ 1].tok_count >= 0){ - if (fwrite(&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tmpfil) != 1){ + if (writeTEST((char *)&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tmpfil)){ badwrite: yyerror("Unexpected end of file writing the interpass tmp file"); exit(2); @@ -57,8 +95,8 @@ closetmpfile() * in the argument list */ tokbuf[bufno].toks[tokbuf[bufno].tok_count++] = PARSEEOF; - if (fwrite(&tokbuf[bufno], sizeof *emptybuf, 1, tmpfil) - != 1) goto badwrite; + if (writeTEST((char *)&tokbuf[bufno], sizeof *emptybuf, 1, tmpfil)) + goto badwrite; } } /*end of being pass 1*/ } @@ -87,9 +125,10 @@ closetmpfile() #ifdef DEBUG ptrall firsttoken; -#endif +#endif DEBUG extern int yylval; /*global communication with parser*/ +static int Lastjxxx; /*this ONLY shuts up cc; see below*/ toktype yylex() { @@ -102,171 +141,182 @@ toktype yylex() if (bufptr < tokub){ gtoken(val, bufptr); switch(yylval = val){ - case PARSEEOF : - yylval = val = PARSEEOF; - break; - case INT: - locxp = xp++; - glong(locxp->xvalue, bufptr); - makevalue: - locxp->xtype = XABS; - locxp->xloc = 0; - locxp->xname = NULL; - yylval = (int)locxp; - break; - case FLTNUM: /*case patched on 3-Jan-80*/ - locxp = xp++; - gdouble(locxp->doubval.dvalue, bufptr); - /* - * We make sure that locxp->xvalue - * is not in the range suitable for - * a short literal. The field - * xvalue is only used for - * integers, not doubles, but when - * we test for short literals - * in ascode.c, we look - * at the field xvalue when - * it encounters an in line - * floating number. Ergo, - * give it a bad value. - */ - locxp->xvalue = -1; - goto makevalue; - case NAME: - gptr(yylval, bufptr); - lastnam = (struct symtab *)yylval; - break; - case SIZESPEC: - case REG: - case INSTn: - case INST0: - gchar(yylval, bufptr); - break; - case IJXXX: - gchar(yylval, bufptr); - gptr(lastjxxx, bufptr); - break; - case ILINESKIP: - gint(yylval, bufptr); - lineno += yylval; - goto top; - case SKIP: - eatskiplg(bufptr); - goto top; - case VOID: - goto top; - case STRING: - strptr = &strbuf[strno ^= 1]; - strptr->str_lg = *((lgtype *)bufptr); - movestr(&strptr->str[0], - (char *)bufptr + sizeof(lgtype), - strptr->str_lg); - eatstrlg(bufptr); - yylval = (int)strptr; - break; - case ISTAB: - case ISTABSTR: - case ISTABNONE: - case ISTABDOT: - case IALIGN: - gptr(yylval, bufptr); - break; - } /*end of the switch*/ - + case PARSEEOF : + yylval = val = PARSEEOF; + break; + case BFINT: + case INT: + if (xp >= &explist[NEXP]) + yyerror("Too many expressions; try simplyfing"); + else + locxp = xp++; + glong(locxp->e_xvalue, bufptr); + locxp->e_yvalue = 0; + makevalue: + locxp->e_xtype = XABS; + locxp->e_xloc = 0; + locxp->e_xname = NULL; + yylval = (int)locxp; + break; + case FLTNUM: + if (xp >= &explist[NEXP]) + yyerror("Too many expressions; try simplyfing"); + else + locxp = xp++; + gdouble( ( (union Double *)locxp)->dvalue, bufptr); + goto makevalue; + case QUAD: + if (xp >= &explist[NEXP]) + yyerror("Too many expressions; try simplyfing"); + else + locxp = xp++; + glong(locxp->e_xvalue, bufptr); + glong(locxp->e_yvalue, bufptr); + yylval = val = INT; + goto makevalue; + case NAME: + gptr(yylval, bufptr); + lastnam = (struct symtab *)yylval; + break; + case SIZESPEC: + case REG: + case INSTn: + case INST0: + gchar(yylval, bufptr); + break; + case IJXXX: + gchar(yylval, bufptr); + /* We can't cast Lastjxxx into (int *) here.. */ + gptr(Lastjxxx, bufptr); + lastjxxx = (struct symtab *)Lastjxxx; + break; + case ILINESKIP: + gint(yylval, bufptr); + lineno += yylval; + goto top; + case SKIP: + eatskiplg(bufptr); + goto top; + case VOID: + goto top; + case STRING: + strptr = &strbuf[strno ^= 1]; + strptr->str_lg = *((lgtype *)bufptr); + movestr(&strptr->str[0], + (char *)bufptr + sizeof(lgtype), + strptr->str_lg); + eatstrlg(bufptr); + yylval = (int)strptr; + break; + case ISTAB: + case ISTABSTR: + case ISTABNONE: + case ISTABDOT: + case IALIGN: + gptr(yylval, bufptr); + break; + } #ifdef DEBUG - - if (toktrace) + if (toktrace){ + char *tok_to_name(); + printf("P: %d T#: %4d, %s ", + passno, bufptr - firsttoken, tok_to_name(val)); switch(val){ - case INT: printf("Class integer val %d\n", - ((struct exp *)yylval)->xvalue); - break; - case FLTNUM: printf("Class floating point num value %4.3f\n", - ((struct exp *)yylval) -> doubval.dvalue); - break; - case NAME: printf("Class name, \"%.8s\"\n", - ((struct symtab *)yylval)->name); - break; - case REG: printf("Class register, number %d\n", - yylval); - break; - case INSTn: printf("Class INSTn, %.8s\n", - itab[0xFF &yylval]->name); - break; - case IJXXX: printf("Class IJXXX, %.8s\n", - itab[0xFF &yylval]->name); - break; - case INST0: printf("Class INST0, %.8s\n", - itab[0xFF &yylval]->name); - break; - case STRING: printf("Class string, length %d\n", - ((struct strdesc *)yylval)->str_lg); - break; - default: printf("Pass: %d Tok: %d Other class: %d, 0%o, '%c'\n", - passno, - bufptr - firsttoken, - val,val, val); - break; - } /*end of the debug switch*/ -#endif + case INT: printf("val %d", + ((struct exp *)yylval)->e_xvalue); + break; + case BFINT: printf("val %d", + ((struct exp *)yylval)->e_xvalue); + break; + case QUAD: printf("val[msd] = 0x%x, val[lsd] = 0x%x.", + ((struct exp *)yylval)->e_xvalue, + ((struct exp *)yylval)->e_yvalue); + break; + case FLTNUM: printf("value %20.17f", + ((union Double *)yylval)->dvalue); + break; + case NAME: printf("\"%.8s\"", + ((struct symtab *)yylval)->s_name); + break; + case REG: printf(" r%d", + yylval); + break; + case IJXXX: + case INST0: + case INSTn: printf("%.8s", + itab[0xFF &yylval]->s_name); + break; + case STRING: printf("length %d ", + ((struct strdesc *)yylval)->str_lg); + printf("value\"%s\"", + ((struct strdesc *)yylval)->str); + break; + } /*end of the debug switch*/ + printf("\n"); + } +#endif DEBUG - } /*end of this buffer*/ - else { - if (useVM){ - bufno += 1; + } else { /* start a new buffer */ + if (useVM){ + if (passno == 2){ + tok_temp = emptybuf->tok_next; + emptybuf->tok_next = tok_free; + tok_free = emptybuf; + emptybuf = tok_temp; + } else { emptybuf = emptybuf->tok_next; - if (emptybuf == 0){ - struct tokbufdesc *newdallop; - int i; - if (passno == 2) - goto badread; - emptybuf = newdallop = - (struct tokbufdesc *)sbrk( - TOKDALLOP*sizeof (struct tokbufdesc)); - if (emptybuf == (struct tokbufdesc *)-1) - goto badwrite; - for (i=0; i < TOKDALLOP; i++){ - buftail->tok_next = newdallop; - buftail = newdallop; - newdallop += 1; - } - buftail->tok_next = 0; - } /*end of need to get more buffers*/ - (toktype *)bufptr = &(emptybuf->toks[0]); - if (passno == 1) - scan_dot_s(emptybuf); - } else { /*don't use VM*/ - bufno ^= 1; - emptybuf = &tokbuf[bufno]; - ((toktype *)bufptr) = &(emptybuf->toks[0]); - if (passno == 1){ - /* - * First check if there are things to write - * out at all - */ - if (emptybuf->tok_count >= 0){ - if (fwrite(emptybuf, sizeof *emptybuf, 1, tmpfil) != 1){ - badwrite: - yyerror("Unexpected end of file writing the interpass tmp file"); - exit(2); - } - } - scan_dot_s(emptybuf); - } else { /*pass 2*/ - if (fread(emptybuf, sizeof *emptybuf, 1, tmpfil) != 1){ - badread: - yyerror("Unexpected end of file while reading the interpass tmp file"); - exit(1); - } - } /*end of pass2*/ - } /*end of using a real live file*/ - (char *)tokub = (char *)bufptr + emptybuf->tok_count; + } + bufno += 1; + if (emptybuf == 0){ + struct tokbufdesc *newdallop; + int i; + if (passno == 2) + goto badread; + emptybuf = newdallop = (struct tokbufdesc *) + Calloc(TOKDALLOP, sizeof (struct tokbufdesc)); + for (i=0; i < TOKDALLOP; i++){ + buftail->tok_next = newdallop; + buftail = newdallop; + newdallop += 1; + } + buftail->tok_next = 0; + } /*end of need to get more buffers*/ + (toktype *)bufptr = &(emptybuf->toks[0]); + if (passno == 1) + scan_dot_s(emptybuf); + } else { /*don't use VM*/ + bufno ^= 1; + emptybuf = &tokbuf[bufno]; + ((toktype *)bufptr) = &(emptybuf->toks[0]); + if (passno == 1){ + /* + * First check if there are things to write + * out at all + */ + if (emptybuf->tok_count >= 0){ + if (writeTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){ + badwrite: + yyerror("Unexpected end of file writing the interpass tmp file"); + exit(2); + } + } + scan_dot_s(emptybuf); + } else { /*pass 2*/ + if (readTEST((char *)emptybuf, sizeof *emptybuf, 1, tmpfil)){ + badread: + yyerror("Unexpected end of file while reading the interpass tmp file"); + exit(1); + } + } + } /*end of using a real live file*/ + (char *)tokub = (char *)bufptr + emptybuf->tok_count; #ifdef DEBUG - firsttoken = bufptr; - if (debug) - printf("created buffernumber %d with %d tokens\n", - bufno, emptybuf->tok_count); -#endif - goto top; + firsttoken = bufptr; + if (debug) + printf("created buffernumber %d with %d tokens\n", + bufno, emptybuf->tok_count); +#endif DEBUG + goto top; } /*end of reading/creating a new buffer*/ tokptr = bufptr; /*copy back the global value*/ return(val); @@ -387,19 +437,18 @@ readonly short type[] = { */ #define HEXFLAG 01 /* 'x' or 'X' */ #define HEXLDIGIT 02 /* 'a' .. 'f' */ -#define HEXUDIGIT 04 /* 'A' .. 'F' */ +#define HEXUDIGIT 04 /* 'A' .. 'F' */ #define ALPHA 010 /* 'A' .. 'Z', 'a' .. 'z', '_'*/ -#define DIGIT 020 /* '0' .. '9' */ +#define DIGIT 020 /* '0' .. '9' */ #define FLOATEXP 040 /* 'd' 'e' 'D' 'E' */ - /*exponent field*/ -#define SIGN 0100 /* '+' .. '-'*/ -#define REGDIGIT 0200 /* '0' .. '5' */ -#define SZSPECBEGIN 0400 /* 'b', 'B', 'l', 'L', 'w', 'W' */ -#define POINT 01000 /* '.' */ -#define SPACE 02000 /* '\t' or ' ' */ -#define BSESCAPE 04000 /* bnrtf */ -#define STRESCAPE 010000 /* '"', '\\', '\n' */ -#define OCTDIGIT 020000 /* '0' .. '7' */ +#define SIGN 0100 /* '+' .. '-'*/ +#define REGDIGIT 0200 /* '0' .. '5' */ +#define SZSPECBEGIN 0400 /* 'b', 'B', 'l', 'L', 'w', 'W' */ +#define POINT 01000 /* '.' */ +#define SPACE 02000 /* '\t' or ' ' */ +#define BSESCAPE 04000 /* bnrtf */ +#define STRESCAPE 010000 /* '"', '\\', '\n' */ +#define OCTDIGIT 020000 /* '0' .. '7' */ #define FLOATFLAG 040000 /* 'd', 'D', 'f', 'F' */ /*after leading 0*/ @@ -408,7 +457,8 @@ readonly short charsets[] = { 0, SPACE, STRESCAPE,0, 0, 0, 0, 0, /*BS..SI*/ 0, 0, 0, 0, 0, 0, 0, 0, /*DLE..ETB*/ 0, 0, 0, 0, 0, 0, 0, 0, /*CAN..US*/ - SPACE, 0, STRESCAPE,0, 0, 0, 0, 0, /*sp.. '*/ +/* dollar is an alpha character */ + SPACE, 0, STRESCAPE,0, ALPHA, 0, 0, 0, /*sp.. '*/ 0, 0, 0, SIGN, 0, SIGN, POINT+ALPHA,0, /*( .. /*/ DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*0..1*/ DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*2..3*/ @@ -438,46 +488,80 @@ readonly short charsets[] = { ALPHA+HEXFLAG, ALPHA, ALPHA, 0,0, 0, 0, 0, /*x..del*/ 0}; -#define INCHARSET(val, kind) (charsets[val] & (kind) ) +#define INCHARSET(val, kind) (charsets[val] & (kind) ) static toktype oval = NL; -#define INBUFLG 2 + 2*BUFSIZ + 128 +#define NINBUFFERS 2 +#define INBUFLG NINBUFFERS*BUFSIZ + 2 + /* + * We have two input buffers; the first one is reserved + * for catching the tail of a line split across a buffer + * boundary; the other one are used for snarfing a buffer + * worth of .s source. + */ static char inbuffer[INBUFLG]; static char *InBufPtr = 0; -#ifdef getchar -#undef getchar +#ifdef getchar +#undef getchar #endif -#define getchar() *inbufptr++ +#define getchar() *inbufptr++ -#ifdef ungetc -#undef ungetc +#ifdef ungetc +#undef ungetc #endif -#define ungetc(char, fileptr) *--inbufptr = char +#define ungetc(char) *--inbufptr = char +/* + * fill the inbuffer from the standard input. + * Assert: there are always n COMPLETE! lines in the buffer area. + * Assert: there is always a \n terminating the last line + * in the buffer area. + * Assert: after the \n, there is an EOFCHAR (hard end of file) + * or a NEEDCHAR (end of buffer) + * Assert: fgets always null pads the string it reads. + * Assert: no ungetc's are done at the end of a line or at the + * beginning of a line. + * + * We read a complete buffer of characters in one single read. + * We then back scan within this buffer to find the end of the + * last complete line, and force the assertions, and save a pointer + * to the incomplete line. + * The next call to fillinbuffer will move the unread characters + * to the end of the first buffer, and then read another two buffers, + * completing the cycle. + */ + +static char p_swapped = '\0'; +static char *p_start = &inbuffer[NINBUFFERS * BUFSIZ]; +static char *p_stop = &inbuffer[NINBUFFERS * BUFSIZ]; char *fillinbuffer() { - register char *cp, *inbufptr; + register char *to; + register char *from; + char *inbufptr; int nread; - inbufptr = &inbuffer[2]; /*allow enough room for two ungetcs*/ - nread = fread(inbufptr, 1, 2*BUFSIZ, stdin); - if (nread == 2*BUFSIZ){ - cp = fgets(inbufptr+2*BUFSIZ, 128, stdin); /*get next whole line*/ - if (cp != 0){ - while(*cp++); /*find the trailing null*/ - *--cp = NEEDCHAR; /*clobber with a NEED character*/ - return(inbufptr); - } else { - *(inbufptr + 2*BUFSIZ) = EOFCHAR; - return(inbufptr); - } - } else { - if (nread == 0) /*hard end of file*/ - return(0); - inbuffer[2+nread] = EOFCHAR; - return(inbufptr); - } + *p_start = p_swapped; + inbufptr = &inbuffer[1*BUFSIZ] - (p_stop - p_start); + + for (to = inbufptr, from = p_start; from < p_stop;) + *to++ = *from++; + /* + * Now, go read two full buffers (hopefully) + */ + nread = read(stdin->_file, &inbuffer[1*BUFSIZ], (NINBUFFERS - 1)*BUFSIZ); + if (nread == 0) + return(0); + p_stop = from = &inbuffer[1*BUFSIZ + nread]; + *from = '\0'; + while (*--from != '\n') /* back over the partial line */ + continue; + from++; /* first char of partial line */ + p_start = from; + p_swapped = *p_start; + *p_start = NEEDCHAR; /* force assertion */ + return(inbufptr); } scan_dot_s(bufferbox) @@ -490,6 +574,7 @@ scan_dot_s(bufferbox) register char *inbufptr; register struct symtab *op; register unsigned char tag; + int forb; register ptrall bufptr; /*where to stuff tokens*/ ptrall lgbackpatch; /*where to stuff a string length*/ @@ -497,9 +582,13 @@ scan_dot_s(bufferbox) register int maxstrlg; /*how long a string can be*/ long intval; /*value of int*/ char fltchr[64]; /*buffer for floating values*/ - double fltval; /*floating value returned*/ + union Double fltval; /*floating value returned*/ + struct Quad quadval; /*quad returned from immediate constant */ int linescrossed; /*when doing strings and comments*/ + (toktype *)bufptr = (toktype *) & (bufferbox->toks[0]); + (toktype *)bufub = &(bufferbox->toks[AVAILTOKS]); + inbufptr = InBufPtr; if (inbufptr == 0){ inbufptr = fillinbuffer(); @@ -511,15 +600,7 @@ scan_dot_s(bufferbox) } } - (toktype *)bufptr = (toktype *) & (bufferbox->toks[0]); - (toktype *)bufub = &(bufferbox->toks[AVAILTOKS]); - if (newfflag){ -#ifdef DEBUG - if (debug) - printf(">>>>>>>>>>>>>(scanner) Starting to insert tokens into a new file: %s\n", - newfname); -#endif ptoken(bufptr, IFILE); ptoken(bufptr, STRING); val = strlen(newfname) + 1; @@ -534,339 +615,417 @@ scan_dot_s(bufferbox) while (bufptr < bufub){ loop: - switch(yylval = (type+2)[val = getchar()]) { - case SCANEOF: - inbufptr = 0; + switch(yylval = (type+2)[val = getchar()]) { + case SCANEOF: + inbufptr = 0; + goto endoffile; + + case NEEDSBUF: + inbufptr = fillinbuffer(); + if (inbufptr == 0) goto endoffile; + goto loop; - case NEEDSBUF: - inbufptr = fillinbuffer(); - if (inbufptr == 0) - goto endoffile; - goto loop; - - case DIV: /*process C style comments*/ - if ( (val = getchar()) == '*') { /*comment prelude*/ - int incomment; - linescrossed = 0; - incomment = 1; - val = getchar(); /*skip over the * */ - do{ - while ( (val != '*') && - (val != '\n') && - (val != EOFCHAR) && - (val != NEEDCHAR)) - val = getchar(); - if (val == '\n'){ - scanlineno++; - linescrossed++; - } else - if (val == EOFCHAR) - goto endoffile; - if (val == NEEDCHAR){ - inbufptr = fillinbuffer(); - if (inbufptr == 0) - goto endoffile; - lineno++; - incomment = 1; - val = getchar(); /*pull in the new char*/ - } else { /*its a star */ + case DIV: /*process C style comments*/ + if ( (val = getchar()) == '*') { /*comment prelude*/ + int incomment; + linescrossed = 0; + incomment = 1; + val = getchar(); /*skip over the * */ + do{ + while ( (val != '*') && + (val != '\n') && + (val != EOFCHAR) && + (val != NEEDCHAR)) val = getchar(); - incomment = val != '/'; - } - } while (incomment); - val = ILINESKIP; - yylval = linescrossed; - goto ret; - } else { /*just an ordinary DIV*/ - ungetc(val, stdin); - val = yylval = DIV; - goto ret; - } - case SH: - if (oval == NL){ - /* - * Attempt to recognize a C preprocessor - * style comment '^#[ \t]*[0-9]*[ \t]*".*" - */ - val = getchar(); /*bump the #*/ + if (val == '\n'){ + scanlineno++; + linescrossed++; + } else + if (val == EOFCHAR) + goto endoffile; + if (val == NEEDCHAR){ + inbufptr = fillinbuffer(); + if (inbufptr == 0) + goto endoffile; + lineno++; + incomment = 1; + val = getchar(); /*pull in the new char*/ + } else { /*its a star */ + val = getchar(); + incomment = val != '/'; + } + } while (incomment); + val = ILINESKIP; + yylval = linescrossed; + goto ret; + } else { /*just an ordinary DIV*/ + ungetc(val); + val = yylval = DIV; + goto ret; + } + case SH: + if (oval == NL){ + /* + * Attempt to recognize a C preprocessor + * style comment '^#[ \t]*[0-9]*[ \t]*".*" + */ + val = getchar(); /*bump the #*/ + while (INCHARSET(val, SPACE)) + val = getchar();/*bump white */ + if (INCHARSET(val, DIGIT)){ + intval = 0; + while(INCHARSET(val, DIGIT)){ + intval = intval *10 + val - '0'; + val = getchar(); + } while (INCHARSET(val, SPACE)) - val = getchar();/*bump white */ - if (INCHARSET(val, DIGIT)){ - intval = 0; - while(INCHARSET(val, DIGIT)){ - intval = intval *10 + val - '0'; - val = getchar(); - } - while (INCHARSET(val, SPACE)) - val = getchar(); - if (val == '"'){ - ptoken(bufptr, ILINENO); - ptoken(bufptr, INT); - pint(bufptr, intval - 1); - ptoken(bufptr, IFILE); - /* - * The '"' has already been - * munched - * - * eatstr will not eat - * the trailing \n, so - * it is given to the parser - * and counted. - */ - goto eatstr; - } + val = getchar(); + if (val == '"'){ + ptoken(bufptr, ILINENO); + ptoken(bufptr, INT); + pint(bufptr, intval - 1); + ptoken(bufptr, IFILE); + /* + * The '"' has already been + * munched + * + * eatstr will not eat + * the trailing \n, so + * it is given to the parser + * and counted. + */ + goto eatstr; } } + } + /* + * Well, its just an ordinary decadent comment + */ + while ((val != '\n') && (val != EOFCHAR)) + val = getchar(); + if (val == EOFCHAR) + goto endoffile; + val = yylval = oval = NL; + scanlineno++; + goto ret; + + case NL: + scanlineno++; + val = yylval; + goto ret; + + case SP: + oval = SP; /*invalidate ^# meta comments*/ + goto loop; + + case REGOP: /* % , could be used as modulo, or register*/ + val = getchar(); + if (INCHARSET(val, DIGIT)){ + yylval = val-'0'; + if (val=='1') { + if (INCHARSET( (val = getchar()), REGDIGIT)) + yylval = 10+val-'0'; + else + ungetc(val); + } /* - * Well, its just an ordinary decadent comment + * God only knows what the original author + * wanted this undocumented feature to + * do. + * %5++ is really r7 */ - while ((val != '\n') && (val != EOFCHAR)) - val = getchar(); - if (val == EOFCHAR) - goto endoffile; - val = yylval = oval = NL; - scanlineno++; + while(INCHARSET( (val = getchar()), SIGN)) { + if (val=='+') + yylval++; + else + yylval--; + } + ungetc(val); + val = REG; + } else { + ungetc(val); + val = REGOP; + } + goto ret; + + case ALPH: + yylval = val; + if (INCHARSET(val, SZSPECBEGIN)){ + if( (val = getchar()) == '`' || val == '^'){ + yylval |= 0100; /*convert to lower*/ + if (yylval == 'b') yylval = 1; + else if (yylval == 'w') yylval = 2; + else if (yylval == 'l') yylval = 4; + else yylval = d124; + val = SIZESPEC; + goto ret; + } else { + ungetc(val); + val = yylval; /*restore first character*/ + } + } + cp = yytext; + do { + if (cp < &yytext[NCPS]) + *cp++ = val; + } while (INCHARSET ( (val = getchar()), ALPHA | DIGIT)); + *cp = '\0'; + while (INCHARSET(val, SPACE)) + val = getchar(); + ungetc(val); + doit: + tag = (op = *lookup(1))->s_tag; + if (tag && tag != LABELID){ + yylval = ( (struct instab *)op)->i_opcode; + val = op->s_tag ; goto ret; - - case NL: - scanlineno++; - val = yylval; + } else { + /* + * Its a name... (Labels are subsets ofname) + */ + yylval = (int)op; + val = NAME; goto ret; + } - case SP: - oval = SP; /*invalidate ^# meta comments*/ - goto loop; - - case REGOP: /* % , could be used as modulo, or register*/ + case DIG: + base = 10; + cp = fltchr; + intval = 0; + if (val=='0') { val = getchar(); - if (INCHARSET(val, DIGIT)){ - yylval = val-'0'; - if (val=='1') { - if (INCHARSET( (val = getchar()), REGDIGIT)) - yylval = 10+val-'0'; - else - ungetc(val, stdin); - } + if (val == 'b') { + yylval = -1; + val = BFINT; + goto ret; + } + if (val == 'f') { /* - * God only knows what the original author - * wanted this undocumented feature to - * do. - * %5++ is really r7 + * Well, it appears to be a local label + * reference, but check to see if + * the next character makes it a floating + * point constant. */ - while(INCHARSET( (val = getchar()), SIGN)) { - if (val=='+') - yylval++; - else - yylval--; + forb = getchar(); + ungetc(forb); + if (!(INCHARSET(forb,(DIGIT|SIGN|FLOATEXP|POINT)))){ + yylval = 1; + val = BFINT; + goto ret; } - ungetc(val, stdin); - val = REG; - } else { - ungetc(val, stdin); - val = REGOP; } - goto ret; - - case ALPH: - yylval = val; - if (INCHARSET(val, SZSPECBEGIN)){ - if( (val = getchar()) == '`' || val == '^'){ - yylval |= 0100; /*convert to lower*/ - if (yylval == 'b') yylval = 1; - else if (yylval == 'w') yylval = 2; - else if (yylval == 'l') yylval = 4; - else yylval = d124; - val = SIZESPEC; + if (INCHARSET(val, HEXFLAG)){ + base = 16; + } else + if (INCHARSET(val, FLOATFLAG)){ + double atof(); + while ( (cp < &fltchr[63]) && + INCHARSET( + (val=getchar()), + (DIGIT|SIGN|FLOATEXP|POINT) + ) + ) *cp++ = val; + if (cp == fltchr) { + yylval = 1; + val = BFINT; goto ret; - } else { - ungetc(val, stdin); - val = yylval; /*restore first character*/ } - } - cp = yytext; - do { - if (cp < &yytext[NCPS]) - *cp++ = val; - } while (INCHARSET ( (val = getchar()), ALPHA | DIGIT)); - *cp = '\0'; - while (INCHARSET(val, SPACE)) - val = getchar(); - ungetc(val, stdin); - tag = (op = *lookup(1))->tag; - if (tag && tag != LABELID){ - yylval = ( (struct instab *)op)->opcode; - val = op->tag ; + ungetc(val); + *cp++ = '\0'; + fltval.dvalue = atof(fltchr); + val = FLTNUM; goto ret; } else { - /* - * Its a name... (Labels are subsets ofname) - */ - yylval = (int)op; - val = NAME; - goto ret; + ungetc(val); + base = 8; } - - case DIG: - intval = val-'0'; - if (val=='0') { - val = getchar(); - if (INCHARSET(val, HEXFLAG)){ - base = 16; - } else - if (INCHARSET(val, FLOATFLAG)){ - char *p = fltchr; - double atof(); - - while ( (p < &fltchr[63]) && - INCHARSET( - (val=getchar()), - (DIGIT|SIGN|FLOATEXP|POINT) - ) - ) *p++ = val; - ungetc(val, stdin); - *p++ = '\0'; - fltval = atof(fltchr); - val = FLTNUM; - goto ret; - } else { - ungetc(val, stdin); - base = 8; - } - } else - base = 10; - while ( INCHARSET( (val = getchar()), DIGIT) || - (base==16 && (INCHARSET(val, HEXLDIGIT|HEXUDIGIT) ) - ) - ){ - if (base==8) - intval <<= 3; - else if (base==10) - intval *= 10; - else { - intval <<= 4; - if (INCHARSET(val, HEXLDIGIT)) - val -= 'a' - 10 - '0'; - else if (INCHARSET(val, HEXUDIGIT)) - val -= 'A' - 10 - '0'; - } - intval += val-'0'; + } else { + forb = getchar(); + if (forb == 'f' || forb == 'b') { + yylval = val - '0' + 1; + if (forb == 'b') + yylval = -yylval; + val = BFINT; + goto ret; } - ungetc(val, stdin); - val = INT; - goto ret; - - case LSH: - case RSH: - /* - * We allow the C style operators - * << and >>, as well as < and > - */ - if ( (base = getchar()) != val) - ungetc(base, stdin); - val = yylval; - goto ret; - - case MINUS: - if ( (val = getchar()) =='(') - yylval=val=MP; + ungetc(forb); /* put back non zero */ + goto middle; + } + while ( (val = getchar()) == '0') + continue; + ungetc(val); + while ( INCHARSET( (val = getchar()), DIGIT) || + (base==16 && (INCHARSET(val, HEXLDIGIT|HEXUDIGIT) ) + ) + ){ + if (base==8) + intval <<= 3; + else if (base==10) + intval *= 10; else { - ungetc(val,stdin); - val=MINUS; + intval <<= 4; + if (INCHARSET(val, HEXLDIGIT)) + val -= 'a' - 10 - '0'; + else if (INCHARSET(val, HEXUDIGIT)) + val -= 'A' - 10 - '0'; } - goto ret; - - case SQ: - if ((yylval = getchar()) == '\n') - scanlineno++; /*not entirely correct*/ - intval = yylval; +middle: + *cp++ = (val -= '0'); + intval += val; + } + ungetc(val); + *cp = 0; + maxstrlg = cp - fltchr; + if ( (maxstrlg > 8) + && ( ( (base == 8) + && ( (maxstrlg>11) + || ( (maxstrlg == 11) + && (*fltchr > 3) + ) + ) + ) + || ( (base == 16) + && (maxstrlg > 8) + ) + || ( (base == 10) + && (maxstrlg >= 10) + ) + ) + ) { + val = QUAD; + get_quad(base, fltchr, cp, &quadval); + } else val = INT; - goto ret; - - case DQ: - eatstr: - linescrossed = 0; - maxstrlg = (char *)bufub - (char *)bufptr; + goto ret; - if (maxstrlg < MAXSTRLG) { - ungetc('"', stdin); - *(toktype *)bufptr = VOID ; - bufub = bufptr; - goto done; - } - if (maxstrlg > MAXSTRLG) - maxstrlg = MAXSTRLG; - - ptoken(bufptr, STRING); - lgbackpatch = bufptr; /*this is where the size goes*/ - bufptr += sizeof(lgtype); - /* - * bufptr is now set to - * be stuffed with characters from - * the input - */ + case LSH: + case RSH: + /* + * We allow the C style operators + * << and >>, as well as < and > + */ + if ( (base = getchar()) != val) + ungetc(base); + val = yylval; + goto ret; - while ( (maxstrlg > 0) - && !(INCHARSET( (val = getchar()), STRESCAPE)) - ){ - stuff: - maxstrlg-= 1; - pchar(bufptr, val); - } - if (maxstrlg <= 0){ /*enough characters to fill a string buffer*/ - ungetc('"', stdin); /*will read it next*/ + case MINUS: + if ( (val = getchar()) =='(') + yylval=val=MP; + else { + ungetc(val); + val=MINUS; + } + goto ret; + + case SQ: + if ((yylval = getchar()) == '\n') + scanlineno++; /*not entirely correct*/ + intval = yylval; + val = INT; + goto ret; + + case DQ: + eatstr: + linescrossed = 0; + maxstrlg = (char *)bufub - (char *)bufptr; + + if (maxstrlg < MAXSTRLG) { + ungetc('"'); + *(toktype *)bufptr = VOID ; + bufub = bufptr; + goto done; + } + if (maxstrlg > MAXSTRLG) + maxstrlg = MAXSTRLG; + + ptoken(bufptr, STRING); + lgbackpatch = bufptr; /*this is where the size goes*/ + bufptr += sizeof(lgtype); + /* + * bufptr is now set to + * be stuffed with characters from + * the input + */ + + while ( (maxstrlg > 0) + && !(INCHARSET( (val = getchar()), STRESCAPE)) + ){ + stuff: + maxstrlg-= 1; + pchar(bufptr, val); } - else if (val == '"'); /*done*/ - else if (val == '\n'){ - scanlineno++; - linescrossed++; + if (maxstrlg <= 0){ /*enough characters to fill a string buffer*/ + ungetc('"'); /*will read it next*/ + } + else if (val == '"'); /*done*/ + else if (val == '\n'){ + yywarning("New line embedded in a string constant."); + scanlineno++; + linescrossed++; + val = getchar(); + if (val == EOFCHAR){ + do_eof: + pchar(bufptr, '\n'); + ungetc(EOFCHAR); + } else + if (val == NEEDCHAR){ + if ( (inbufptr = fillinbuffer()) == 0) + goto do_eof; + val = '\n'; goto stuff; - } else { - val = getchar(); /*skip the '\\'*/ - if ( INCHARSET(val, BSESCAPE)){ - switch (val){ - case 'b': val = '\b'; goto stuff; - case 'f': val = '\f'; goto stuff; - case 'n': val = '\n'; goto stuff; - case 'r': val = '\r'; goto stuff; - case 't': val = '\t'; goto stuff; - } - } - if ( !(INCHARSET(val,OCTDIGIT)) ) goto stuff; - base = 0; - intval = 0; - while ( (base < 3) && (INCHARSET(val, OCTDIGIT))){ - base++;intval <<= 3;intval += val - '0'; - val = getchar(); - } - ungetc(val, stdin); - val = (char)intval; + } else { /* simple case */ + ungetc(val); + val = '\n'; goto stuff; } - /* - * bufptr now points at the next free slot - */ - bstrfromto(lgbackpatch, bufptr); - if (linescrossed){ - val = ILINESKIP; - yylval = linescrossed; - goto ret; - } else - goto builtval; - - case BADCHAR: - linescrossed = lineno; - lineno = scanlineno; - yyerror("Illegal character mapped: %d, char read:(octal) %o", - yylval, val); - lineno = linescrossed; - val = BADCHAR; - goto ret; - - default: - val = yylval; + } else { + val = getchar(); /*skip the '\\'*/ + if ( INCHARSET(val, BSESCAPE)){ + switch (val){ + case 'b': val = '\b'; goto stuff; + case 'f': val = '\f'; goto stuff; + case 'n': val = '\n'; goto stuff; + case 'r': val = '\r'; goto stuff; + case 't': val = '\t'; goto stuff; + } + } + if ( !(INCHARSET(val,OCTDIGIT)) ) goto stuff; + base = 0; + intval = 0; + while ( (base < 3) && (INCHARSET(val, OCTDIGIT))){ + base++;intval <<= 3;intval += val - '0'; + val = getchar(); + } + ungetc(val); + val = (char)intval; + goto stuff; + } + /* + * bufptr now points at the next free slot + */ + bstrfromto(lgbackpatch, bufptr); + if (linescrossed){ + val = ILINESKIP; + yylval = linescrossed; goto ret; - } /*end of the switch*/ + } else + goto builtval; + + case BADCHAR: + linescrossed = lineno; + lineno = scanlineno; + yyerror("Illegal character mapped: %d, char read:(octal) %o", + yylval, val); + lineno = linescrossed; + val = BADCHAR; + goto ret; + + default: + val = yylval; + goto ret; + } /*end of the switch*/ /* * here with one token, so stuff it */ @@ -880,9 +1039,14 @@ scan_dot_s(bufferbox) case SIZESPEC: pchar(bufptr, yylval); break; + case BFINT: plong(bufptr, yylval); + break; case INT: plong(bufptr, intval); break; - case FLTNUM: pdouble(bufptr, fltval); + case QUAD: plong(bufptr, quadval.quad_low_long); + plong(bufptr, quadval.quad_high_long); + break; + case FLTNUM: pdouble(bufptr, fltval.dvalue); break; case NAME: pptr(bufptr, (int)(struct symtab *)yylval); break; @@ -932,3 +1096,35 @@ scan_dot_s(bufferbox) ptoken(bufptr, MINUS); InBufPtr = inbufptr; /*copy this back*/ } + +struct Quad _quadtemp; +get_quad(radix, cp_start, cp_end, quadptr) + int radix; + char *cp_start, *cp_end; + struct Quad *quadptr; +{ + register char *cp = cp_start; /* r11 */ + register struct Quad *qp = quadptr; /* r10 */ + register long temp; /* r9 */ + + asm("clrq (r10)"); + for (; cp < cp_end; cp++){ + switch (radix) { + case 8: + asm ("ashq $3, (r10), (r10)"); + break; + case 16: + asm ("ashq $4, (r10), (r10)"); + break; + case 10: + asm ("ashq $1, (r10), __quadtemp"); + asm ("ashq $3, (r10), (r10)"); + asm ("addl2 __quadtemp, (r10)"); + asm ("adwc __quadtemp+4, 4(r10)"); + break; + } + asm ("cvtbl (r11), r9"); + asm ("addl2 r9, (r10)"); + asm ("adwc $0, 4(r10)"); + } +}