-/* Copyright (c) 1980 Regents of the University of California */
-static char sccsid[] = "@(#)asscan.c 4.6 %G%";
-#include <stdio.h>
-#include "as.h"
-#include "asscan.h"
-
-/*
- * 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*/
-
-/*
- * 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()
-{
- if (passno == 1){
- if (useVM){
- bufstart = &tokbuf[0];
- buftail = &tokbuf[1];
- bufstart->tok_next = buftail;
- buftail->tok_next = 0;
- }
- tokbuf[0].tok_count = -1;
- tokbuf[1].tok_count = -1;
- }
- tok_temp = 0;
- tok_free = 0;
- bufno = 0;
- emptybuf = &tokbuf[bufno];
- tokptr = 0;
- tokub = 0;
-}
-
-closetmpfile()
-{
- if (passno == 1){
- if (useVM){
- emptybuf->toks[emptybuf->tok_count++] = PARSEEOF;
- } else {
- /*
- * Clean up the buffers that haven't been
- * written out yet
- */
- if (tokbuf[bufno ^ 1].tok_count >= 0){
- if (writeTEST((char *)&tokbuf[bufno ^ 1], sizeof *emptybuf, 1, tmpfil)){
- badwrite:
- yyerror("Unexpected end of file writing the interpass tmp file");
- exit(2);
- }
- }
- /*
- * Ensure that we will read an End of file,
- * if there are more than one file names
- * in the argument list
- */
- tokbuf[bufno].toks[tokbuf[bufno].tok_count++] = PARSEEOF;
- if (writeTEST((char *)&tokbuf[bufno], sizeof *emptybuf, 1, tmpfil))
- goto badwrite;
- }
- } /*end of being pass 1*/
-}
-
-#define bstrlg(from, length) \
- *(lgtype *)from = length; \
- (char *)from += sizeof(lgtype) + length
-
-#define bstrfromto(from,to) \
- *(lgtype *)from = (char *)to - (char *)from - sizeof(lgtype); \
- (char *)from += sizeof(lgtype) + (char *)to - (char *)from
-
-#define eatstrlg(from) \
- (char *)from += sizeof(lgtype) + *(lgtype *)from
-
-#define bskiplg(from, length) \
- *(lgtype *)from = length; \
- (char *)from += sizeof(lgtype) + length
-
-#define bskipfromto(from, to) \
- *(lgtype *)from = (toktype *)to - (toktype *)from - sizeof(lgtype); \
- (char *)from += sizeof (lgtype) + (toktype *)to - (toktype *)from
-
-#define eatskiplg(from) \
- (toktype *)from += sizeof(lgtype) + *(lgtype *)from
-
-#ifdef DEBUG
- ptrall firsttoken;
-#endif DEBUG
-
-extern int yylval; /*global communication with parser*/
-static int Lastjxxx; /*this ONLY shuts up cc; see below*/
-
-toktype yylex()
-{
- register ptrall bufptr;
- register toktype val;
- register struct exp *locxp;
-
- bufptr = tokptr; /*copy in the global value*/
- top:
- if (bufptr < tokub){
- gtoken(val, bufptr);
- switch(yylval = val){
- 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){
- char *tok_to_name();
- printf("P: %d T#: %4d, %s ",
- passno, bufptr - firsttoken, tok_to_name(val));
- switch(val){
- 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
-
- } 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;
- }
- 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 DEBUG
- goto top;
- } /*end of reading/creating a new buffer*/
- tokptr = bufptr; /*copy back the global value*/
- return(val);
-} /*end of yylex*/
-
-
-buildskip(from, to)
- register ptrall from, to;
-{
- int diff;
- register int frombufno;
- register struct tokbufdesc *middlebuf;
- /*
- * check if from and to are in the same buffer
- * from and to DIFFER BY AT MOST 1 buffer and to is
- * always ahead of from, with to being in the buffer emptybuf
- * points to.
- * The hard part here is accounting for the case where the
- * skip is to cross a buffer boundary; we must construct
- * two skips.
- *
- * Figure out where the buffer boundary between from and to is
- * It's easy in VM, as buffers increase to high memory, but
- * w/o VM, we alternate between two buffers, and want
- * to look at the exact middle of the contiguous buffer region.
- */
- middlebuf = useVM ? emptybuf : &tokbuf[1];
- if ( ( (toktype *)from > (toktype *)middlebuf)
- ^ ( (toktype *)to > (toktype *)middlebuf)
- ){ /*split across a buffer boundary*/
- ptoken(from, SKIP);
- /*
- * Set the skip so it lands someplace beyond
- * the end of this buffer.
- * When we pull this skip out in the second pass,
- * we will temporarily move the current pointer
- * out beyond the end of the buffer, but immediately
- * do a compare and fail the compare, and then reset
- * all the pointers correctly to point into the next buffer.
- */
- bskiplg(from, TOKBUFLG + 1);
- /*
- * Now, force from to be in the same buffer as to
- */
- (toktype *)from = (toktype *)&(emptybuf->toks[0]);
- }
- /*
- * Now, to and from are in the same buffer
- */
- if (from > to)
- yyerror("Internal error: bad skip construction");
- else {
- if ( (diff = (toktype *)to - (toktype *)from) >=
- (sizeof(toktype) + sizeof(lgtype) + 1)) {
- ptoken(from, SKIP);
- bskipfromto(from, to);
- } else {
- for ( ; diff > 0; --diff)
- ptoken(from, VOID);
- }
- }
-}
-
-movestr(to, from, lg)
- register char *to, *from;
- register int lg;
-{
- if (lg <= 0) return;
- do
- *to++ = *from++;
- while (--lg);
-}
-static int newfflag = 0;
-static char *newfname;
-int scanlineno; /*the scanner's linenumber*/
-
-new_dot_s(namep)
- char *namep;
-{
- newfflag = 1;
- newfname = namep;
- dotsname = namep;
- lineno = 1;
- scanlineno = 1;
-}
-
-/*
- * Maps characters to their use in assembly language
- */
-#define EOFCHAR (-1)
-#define NEEDCHAR (-2)
-
-readonly short type[] = {
- NEEDSBUF, /*fill up the input buffer*/
- SCANEOF, /*hit the hard end of file*/
- SP, BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*\0..^G*/
- BADCHAR,SP, NL, BADCHAR,BADCHAR,SP, BADCHAR,BADCHAR, /*BS..SI*/
- BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*DLE..ETB*/
- BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR,BADCHAR, /*CAN..US*/
- SP, ORNOT, DQ, SH, LITOP, REGOP, AND, SQ, /*sp .. '*/
- LP, RP, MUL, PLUS, CM, MINUS, ALPH, DIV, /*( .. /*/
- DIG, DIG, DIG, DIG, DIG, DIG, DIG, DIG, /*0 .. 7*/
- DIG, DIG, COLON, SEMI, LSH, BADCHAR,RSH, BADCHAR, /*8 .. ?*/
- BADCHAR,ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*@ .. G*/
- ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*H .. BADCHAR*/
- ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*P .. V*/
- ALPH, ALPH, ALPH, LB, BADCHAR,RB, XOR, ALPH,/*W .. _*/
- SIZEQUOTE,ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*` .. g*/
- ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*h .. o*/
- ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH, ALPH,/*p .. v*/
- ALPH, ALPH, ALPH, BADCHAR,IOR, BADCHAR,TILDE, BADCHAR,/*x .. del*/
-};
-
-/*
- * The table of possible uses for each character to test set inclusion.
- * Different than the above table, which knows about tokens yylex
- * is to return.
- */
-#define HEXFLAG 01 /* 'x' or 'X' */
-#define HEXLDIGIT 02 /* 'a' .. 'f' */
-#define HEXUDIGIT 04 /* 'A' .. 'F' */
-#define ALPHA 010 /* 'A' .. 'Z', 'a' .. 'z', '_'*/
-#define DIGIT 020 /* '0' .. '9' */
-#define FLOATEXP 040 /* 'd' 'e' 'D' 'E' */
-#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*/
-
-readonly short charsets[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, /*\0..^G*/
- 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*/
-/* 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*/
- DIGIT+REGDIGIT+OCTDIGIT, DIGIT+REGDIGIT+OCTDIGIT, /*4..5*/
- DIGIT+OCTDIGIT, DIGIT+OCTDIGIT, /*6..7*/
- DIGIT, DIGIT, 0, 0, 0, 0, 0, 0, /*8..?*/
- 0, /*@*/
- ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+SZSPECBEGIN, /*A..B*/
- ALPHA+HEXUDIGIT,ALPHA+HEXUDIGIT+FLOATEXP+FLOATFLAG, /*C..D*/
- ALPHA+HEXUDIGIT+FLOATEXP,ALPHA+HEXUDIGIT+FLOATFLAG, /*E..F*/
- ALPHA, /*G*/
- ALPHA, ALPHA, ALPHA, ALPHA, /*H..K*/
- ALPHA+SZSPECBEGIN, ALPHA, ALPHA, ALPHA, /*L..O*/
- ALPHA, ALPHA, ALPHA, ALPHA, /*P..S*/
- ALPHA, ALPHA, ALPHA, ALPHA+SZSPECBEGIN, /*T..W*/
- ALPHA+HEXFLAG, ALPHA, ALPHA, 0,STRESCAPE,0, 0, ALPHA,/*X.._*/
-
- 0,
- ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+BSESCAPE+SZSPECBEGIN, /*a..b*/
- ALPHA+HEXLDIGIT,ALPHA+HEXLDIGIT+FLOATEXP+FLOATFLAG, /*c..d*/
- ALPHA+HEXLDIGIT+FLOATEXP,ALPHA+HEXLDIGIT+BSESCAPE+FLOATFLAG, /*e..f*/
- ALPHA, /*g*/
- ALPHA, ALPHA, ALPHA, ALPHA, /*h..k*/
- ALPHA+SZSPECBEGIN, ALPHA, ALPHA+BSESCAPE, ALPHA, /*l..o*/
- ALPHA, ALPHA, ALPHA+BSESCAPE, ALPHA, /*p..s*/
- ALPHA+BSESCAPE, ALPHA, ALPHA, ALPHA+SZSPECBEGIN,/*t..w*/
- ALPHA+HEXFLAG, ALPHA, ALPHA, 0,0, 0, 0, 0, /*x..del*/
-0};
-
-#define INCHARSET(val, kind) (charsets[val] & (kind) )
-static toktype oval = NL;
-
-#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
-#endif
-#define getchar() *inbufptr++
-
-#ifdef ungetc
-#undef ungetc
-#endif
-#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 *to;
- register char *from;
- char *inbufptr;
- int nread;
-
- *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)
- struct tokbufdesc *bufferbox;
-{
- register int yylval;/*lexical value*/
- register toktype val; /*the value returned; the character read*/
- register int base; /*the base of the number also counter*/
- register char *cp;
- 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*/
- ptrall bufub; /*where not to stuff tokens*/
- register int maxstrlg; /*how long a string can be*/
- long intval; /*value of int*/
- char fltchr[64]; /*buffer for floating values*/
- 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();
- if (inbufptr == 0){ /*end of file*/
- endoffile:
- inbufptr = 0;
- ptoken(bufptr, PARSEEOF);
- goto done;
- }
- }
-
- if (newfflag){
- ptoken(bufptr, IFILE);
- ptoken(bufptr, STRING);
- val = strlen(newfname) + 1;
- movestr( (char *)&( ( (lgtype *)bufptr)[1]), newfname, val);
- bstrlg(bufptr, val);
-
- ptoken(bufptr, ILINENO);
- ptoken(bufptr, INT);
- pint(bufptr, 1);
- newfflag = 0;
- }
-
- while (bufptr < bufub){
- loop:
- switch(yylval = (type+2)[val = getchar()]) {
- case SCANEOF:
- inbufptr = 0;
- goto endoffile;
-
- 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 */
- 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();
- 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);
- }
- /*
- * God only knows what the original author
- * wanted this undocumented feature to
- * do.
- * %5++ is really r7
- */
- 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;
- } else {
- /*
- * Its a name... (Labels are subsets ofname)
- */
- yylval = (int)op;
- val = NAME;
- goto ret;
- }
-
- case DIG:
- base = 10;
- cp = fltchr;
- intval = 0;
- if (val=='0') {
- val = getchar();
- if (val == 'b') {
- yylval = -1;
- val = BFINT;
- goto ret;
- }
- if (val == 'f') {
- /*
- * Well, it appears to be a local label
- * reference, but check to see if
- * the next character makes it a floating
- * point constant.
- */
- forb = getchar();
- ungetc(forb);
- if (!(INCHARSET(forb,(DIGIT|SIGN|FLOATEXP|POINT)))){
- yylval = 1;
- val = BFINT;
- goto ret;
- }
- }
- 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;
- }
- ungetc(val);
- *cp++ = '\0';
- fltval.dvalue = atof(fltchr);
- val = FLTNUM;
- goto ret;
- } else {
- ungetc(val);
- base = 8;
- }
- } else {
- forb = getchar();
- if (forb == 'f' || forb == 'b') {
- yylval = val - '0' + 1;
- if (forb == 'b')
- yylval = -yylval;
- val = BFINT;
- goto ret;
- }
- 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 {
- intval <<= 4;
- if (INCHARSET(val, HEXLDIGIT))
- val -= 'a' - 10 - '0';
- else if (INCHARSET(val, HEXUDIGIT))
- val -= 'A' - 10 - '0';
- }
-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 LSH:
- case RSH:
- /*
- * We allow the C style operators
- * << and >>, as well as < and >
- */
- if ( (base = getchar()) != val)
- ungetc(base);
- val = yylval;
- goto ret;
-
- 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);
- }
- 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 { /* simple case */
- ungetc(val);
- 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);
- val = (char)intval;
- 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;
- goto ret;
- } /*end of the switch*/
- /*
- * here with one token, so stuff it
- */
- ret:
- oval = val;
- ptoken(bufptr, val);
- switch(val){
- case ILINESKIP:
- pint(bufptr, yylval);
- break;
- case SIZESPEC:
- pchar(bufptr, yylval);
- break;
- case BFINT: plong(bufptr, yylval);
- break;
- case INT: plong(bufptr, intval);
- break;
- 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;
- case REG: pchar(bufptr, yylval);
- break;
- case INST0:
- case INSTn:
- pchar(bufptr, yylval);
- break;
- case IJXXX:
- pchar(bufptr, yylval);
- pptr(bufptr, (int)(struct symtab *)symalloc());
- break;
- case ISTAB:
- case ISTABSTR:
- case ISTABNONE:
- case ISTABDOT:
- case IALIGN:
- pptr(bufptr, (int)(struct symtab *)symalloc());
- break;
- /*
- * default:
- */
- }
- builtval: ;
- } /*end of the while to stuff the buffer*/
- done:
- bufferbox->tok_count = (toktype *)bufptr - &(bufferbox->toks[0]);
-
- /*
- * This is a real kludge:
- *
- * We put the last token in the buffer to be a MINUS
- * symbol. This last token will never be picked up
- * in the normal way, but can be looked at during
- * a peekahead look that the short circuit expression
- * evaluator uses to see if an expression is complicated.
- *
- * Consider the following situation:
- *
- * .word 45 + 47
- * buffer 1 | buffer 0
- * the peekahead would want to look across the buffer,
- * but will look in the buffer end zone, see the minus, and
- * fail.
- */
- 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)");
- }
-}