/* Copyright (c) 1979 Regents of the University of California */
struct tokbufdesc
*bufstart
; /*where the buffer list begins*/
struct tokbufdesc
*buftail
; /*last one on the list*/
struct tokbufdesc
*emptybuf
; /*the one being filled*/
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*/
bufstart
->tok_next
= buftail
;
tokbuf
[0].tok_count
= -1;
tokbuf
[1].tok_count
= -1;
emptybuf
= &tokbuf
[bufno
];
emptybuf
->toks
[emptybuf
->tok_count
++] = PARSEEOF
;
* Clean up the buffers that haven't been
if (tokbuf
[bufno
^ 1].tok_count
>= 0){
if (fwrite(&tokbuf
[bufno
^ 1], sizeof *emptybuf
, 1, tmpfil
) != 1){
yyerror("Unexpected end of file writing the interpass tmp file");
* Ensure that we will read an End of file,
* if there are more than one file names
tokbuf
[bufno
].toks
[tokbuf
[bufno
].tok_count
++] = PARSEEOF
;
if (fwrite(&tokbuf
[bufno
], sizeof *emptybuf
, 1, tmpfil
)
} /*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
(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
extern int yylval
; /*global communication with parser*/
register struct exp
*locxp
;
bufptr
= tokptr
; /*copy in the global value*/
glong(locxp
->xvalue
, bufptr
);
case FLTNUM
: /*case patched on 3-Jan-80*/
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
* at the field xvalue when
* it encounters an in line
lastnam
= (struct symtab
*)yylval
;
strptr
= &strbuf
[strno
^= 1];
strptr
->str_lg
= *((lgtype
*)bufptr
);
(char *)bufptr
+ sizeof(lgtype
),
case INT
: printf("Class integer val %d\n",
((struct exp
*)yylval
)->xvalue
);
case FLTNUM
: printf("Class floating point num value %4.3f\n",
((struct exp
*)yylval
) -> doubval
.dvalue
);
case NAME
: printf("Class name, \"%.8s\"\n",
((struct symtab
*)yylval
)->name
);
case REG
: printf("Class register, number %d\n",
case INSTn
: printf("Class INSTn, %.8s\n",
itab
[0xFF &yylval
]->name
);
case IJXXX
: printf("Class IJXXX, %.8s\n",
itab
[0xFF &yylval
]->name
);
case INST0
: printf("Class INST0, %.8s\n",
itab
[0xFF &yylval
]->name
);
case STRING
: printf("Class string, length %d\n",
((struct strdesc
*)yylval
)->str_lg
);
default: printf("Pass: %d Tok: %d Other class: %d, 0%o, '%c'\n",
} /*end of the debug switch*/
emptybuf
= emptybuf
->tok_next
;
struct tokbufdesc
*newdallop
;
(struct tokbufdesc
*)sbrk(
TOKDALLOP
*sizeof (struct tokbufdesc
));
if (emptybuf
== (struct tokbufdesc
*)-1)
for (i
=0; i
< TOKDALLOP
; i
++){
buftail
->tok_next
= newdallop
;
} /*end of need to get more buffers*/
(toktype
*)bufptr
= &(emptybuf
->toks
[0]);
} else { /*don't use VM*/
emptybuf
= &tokbuf
[bufno
];
((toktype
*)bufptr
) = &(emptybuf
->toks
[0]);
* First check if there are things to write
if (emptybuf
->tok_count
>= 0){
if (fwrite(emptybuf
, sizeof *emptybuf
, 1, tmpfil
) != 1){
yyerror("Unexpected end of file writing the interpass tmp file");
if (fread(emptybuf
, sizeof *emptybuf
, 1, tmpfil
) != 1){
yyerror("Unexpected end of file while reading the interpass tmp file");
} /*end of using a real live file*/
(char *)tokub
= (char *)bufptr
+ emptybuf
->tok_count
;
printf("created buffernumber %d with %d tokens\n",
bufno
, emptybuf
->tok_count
);
} /*end of reading/creating a new buffer*/
tokptr
= bufptr
; /*copy back the global value*/
register ptrall from
, to
;
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
* The hard part here is accounting for the case where the
* skip is to cross a buffer boundary; we must construct
* 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*/
* 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
yyerror("Internal error: bad skip construction");
if ( (diff
= (toktype
*)to
- (toktype
*)from
) >=
(sizeof(toktype
) + sizeof(lgtype
) + 1)) {
for ( ; diff
> 0; --diff
)
register char *to
, *from
;
int scanlineno
; /*the scanner's linenumber*/
* Maps characters to their use in assembly language
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
#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' */
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*/
SPACE
, 0, STRESCAPE
,0, 0, 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..?*/
ALPHA
+HEXUDIGIT
,ALPHA
+HEXUDIGIT
+SZSPECBEGIN
, /*A..B*/
ALPHA
+HEXUDIGIT
,ALPHA
+HEXUDIGIT
+FLOATEXP
+FLOATFLAG
, /*C..D*/
ALPHA
+HEXUDIGIT
+FLOATEXP
,ALPHA
+HEXUDIGIT
+FLOATFLAG
, /*E..F*/
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.._*/
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
, 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*/
#define INCHARSET(val, kind) (charsets[val] & (kind) )
static toktype oval
= NL
;
#define INBUFLG 2 + 2*BUFSIZ + 128
static char inbuffer
[INBUFLG
];
static char *InBufPtr
= 0;
#define getchar() *inbufptr++
#define ungetc(char, fileptr) *--inbufptr = char
register char *cp
, *inbufptr
;
inbufptr
= &inbuffer
[2]; /*allow enough room for two ungetcs*/
nread
= fread(inbufptr
, 1, 2*BUFSIZ
, stdin
);
cp
= fgets(inbufptr
+2*BUFSIZ
, 128, stdin
); /*get next whole line*/
while(*cp
++); /*find the trailing null*/
*--cp
= NEEDCHAR
; /*clobber with a NEED character*/
*(inbufptr
+ 2*BUFSIZ
) = EOFCHAR
;
if (nread
== 0) /*hard end of file*/
inbuffer
[2+nread
] = EOFCHAR
;
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 struct symtab
*op
;
register unsigned char tag
;
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*/
double fltval
; /*floating value returned*/
int linescrossed
; /*when doing strings and comments*/
inbufptr
= fillinbuffer();
if (inbufptr
== 0){ /*end of file*/
ptoken(bufptr
, PARSEEOF
);
(toktype
*)bufptr
= (toktype
*) & (bufferbox
->toks
[0]);
(toktype
*)bufub
= &(bufferbox
->toks
[AVAILTOKS
]);
printf(">>>>>>>>>>>>>(scanner) Starting to insert tokens into a new file: %s\n",
val
= strlen(newfname
) + 1;
movestr( (char *)&( ( (lgtype
*)bufptr
)[1]), newfname
, val
);
switch(yylval
= (type
+2)[val
= getchar()]) {
inbufptr
= fillinbuffer();
case DIV
: /*process C style comments*/
if ( (val
= getchar()) == '*') { /*comment prelude*/
val
= getchar(); /*skip over the * */
inbufptr
= fillinbuffer();
val
= getchar(); /*pull in the new char*/
} else { /*just an ordinary DIV*/
* 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
)){
while(INCHARSET(val
, DIGIT
)){
intval
= intval
*10 + val
- '0';
while (INCHARSET(val
, SPACE
))
pint(bufptr
, intval
- 1);
* The '"' has already been
* it is given to the parser
* Well, its just an ordinary decadent comment
while ((val
!= '\n') && (val
!= EOFCHAR
))
val
= yylval
= oval
= NL
;
oval
= SP
; /*invalidate ^# meta comments*/
case REGOP
: /* % , could be used as modulo, or register*/
if (INCHARSET(val
, DIGIT
)){
if (INCHARSET( (val
= getchar()), REGDIGIT
))
* God only knows what the original author
* wanted this undocumented feature to
while(INCHARSET( (val
= getchar()), SIGN
)) {
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;
val
= yylval
; /*restore first character*/
} while (INCHARSET ( (val
= getchar()), ALPHA
| DIGIT
));
while (INCHARSET(val
, SPACE
))
tag
= (op
= *lookup(1))->tag
;
if (tag
&& tag
!= LABELID
){
yylval
= ( (struct instab
*)op
)->opcode
;
* Its a name... (Labels are subsets ofname)
if (INCHARSET(val
, HEXFLAG
)){
if (INCHARSET(val
, FLOATFLAG
)){
while ( (p
< &fltchr
[63]) &&
(DIGIT
|SIGN
|FLOATEXP
|POINT
)
while ( INCHARSET( (val
= getchar()), DIGIT
) ||
(base
==16 && (INCHARSET(val
, HEXLDIGIT
|HEXUDIGIT
) )
if (INCHARSET(val
, HEXLDIGIT
))
else if (INCHARSET(val
, HEXUDIGIT
))
* We allow the C style operators
* << and >>, as well as < and >
if ( (base
= getchar()) != val
)
if ( (val
= getchar()) =='(')
if ((yylval
= getchar()) == '\n')
scanlineno
++; /*not entirely correct*/
maxstrlg
= (char *)bufub
- (char *)bufptr
;
if (maxstrlg
< MAXSTRLG
) {
*(toktype
*)bufptr
= VOID
;
lgbackpatch
= bufptr
; /*this is where the size goes*/
bufptr
+= sizeof(lgtype
);
* be stuffed with characters from
&& !(INCHARSET( (val
= getchar()), STRESCAPE
))
if (maxstrlg
<= 0){ /*enough characters to fill a string buffer*/
ungetc('"', stdin
); /*will read it next*/
else if (val
== '"'); /*done*/
val
= getchar(); /*skip the '\\'*/
if ( INCHARSET(val
, BSESCAPE
)){
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
;
while ( (base
< 3) && (INCHARSET(val
, OCTDIGIT
))){
base
++;intval
<<= 3;intval
+= val
- '0';
* bufptr now points at the next free slot
bstrfromto(lgbackpatch
, bufptr
);
yyerror("Illegal character mapped: %d, char read:(octal) %o",
* here with one token, so stuff it
case INT
: plong(bufptr
, intval
);
case FLTNUM
: pdouble(bufptr
, fltval
);
case NAME
: pptr(bufptr
, (int)(struct symtab
*)yylval
);
case REG
: pchar(bufptr
, yylval
);
pptr(bufptr
, (int)(struct symtab
*)symalloc());
pptr(bufptr
, (int)(struct symtab
*)symalloc());
} /*end of the while to stuff the buffer*/
bufferbox
->tok_count
= (toktype
*)bufptr
- &(bufferbox
->toks
[0]);
* 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:
* the peekahead would want to look across the buffer,
* but will look in the buffer end zone, see the minus, and
InBufPtr
= inbufptr
; /*copy this back*/