-/* 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 <stdio.h>
#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()
{
tokbuf[0].tok_count = -1;
tokbuf[1].tok_count = -1;
}
+ tok_temp = 0;
+ tok_free = 0;
bufno = 0;
emptybuf = &tokbuf[bufno];
tokptr = 0;
* 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);
* 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*/
}
#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()
{
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);
*/
#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*/
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*/
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)
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*/
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();
}
}
- (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;
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
*/
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;
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)");
+ }
+}