* Copyright (c) 1982 Regents of the University of California
static char sccsid
[] = "@(#)asscan2.c 4.6 %G%";
static inttoktype oval
= NL
;
#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
static char inbuffer
[INBUFLG
];
static char *InBufPtr
= 0;
* 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
* 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
* 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,
static char p_swapped
= '\0';
static char *p_start
= &inbuffer
[NINBUFFERS
* BUFSIZ
];
static char *p_stop
= &inbuffer
[NINBUFFERS
* BUFSIZ
];
inbufptr
= &inbuffer
[1*BUFSIZ
] - (p_stop
- p_start
);
for (to
= inbufptr
, from
= p_start
; from
< p_stop
;)
* Now, go read two full buffers (hopefully)
goal
= (NINBUFFERS
- 1)*BUFSIZ
;
got
= read(stdin
->_file
, &inbuffer
[1*BUFSIZ
+ nread
], goal
);
p_stop
= from
= &inbuffer
[1*BUFSIZ
+ nread
];
* back over the partial line
if (from
== &inbuffer
[1*BUFSIZ
]) {
from
++; /* first char of partial line */
*p_start
= NEEDCHAR
; /* force assertion */
struct tokbufdesc
*bufferbox
;
reg
int ryylval
; /* local copy of lexical value */
extern int yylval
; /* global copy of lexical value */
reg
int val
; /* the value returned */
int i
; /* simple counter */
char *cp
; /* can have address taken */
reg
int ch
; /* treated as a character */
int ch1
; /* shadow value */
reg ptrall bufptr
; /* where to stuff tokens */
ptrall lgbackpatch
; /* where to stuff a string length */
ptrall bufub
; /* where not to stuff tokens */
int maxstrlg
; /* how long a string can be */
long intval
; /* value of int */
int linescrossed
; /* when doing strings and comments */
(bytetoktype
*)bufptr
= (bytetoktype
*) & (bufferbox
->toks
[0]);
(bytetoktype
*)bufub
= &(bufferbox
->toks
[AVAILTOKS
]);
inbufptr
= fillinbuffer();
if (inbufptr
== 0){ /*end of file*/
ptoken(bufptr
, PARSEEOF
);
val
= strlen(newfname
) + 1;
movestr( (char *)&( ( (lgtype
*)bufptr
)[1]), newfname
, val
);
switch(ryylval
= (type
+2)[ch
= getchar()]) {
inbufptr
= fillinbuffer();
case DIV
: /*process C style comments*/
if ( (ch
= getchar()) == '*') { /*comment prelude*/
ch
= getchar(); /*skip over the * */
inbufptr
= fillinbuffer();
} else { /*just an ordinary DIV*/
* Attempt to recognize a C preprocessor
* style comment '^#[ \t]*[0-9]*[ \t]*".*"
ch
= getchar(); /*bump the #*/
while (INCHARSET(ch
, SPACE
))
ch
= getchar();/*bump white */
if (INCHARSET(ch
, DIGIT
)){
while(INCHARSET(ch
, DIGIT
)){
intval
= intval
*10 + ch
- '0';
while (INCHARSET(ch
, SPACE
))
pint(bufptr
, intval
- 1);
* The '"' has already been
* it is given to the parser
* Well, its just an ordinary decadent comment
while ((ch
!= '\n') && (ch
!= EOFCHAR
))
val
= ryylval
= oval
= NL
;
oval
= SP
; /*invalidate ^# meta comments*/
case REGOP
: /* % , could be used as modulo, or register*/
if (INCHARSET(ch
, DIGIT
)){
if (INCHARSET( (ch
= getchar()), REGDIGIT
))
* God only knows what the original author
* wanted this undocumented feature to
while(INCHARSET( (ch
= getchar()), SIGN
)) {
if (INCHARSET(ch
, SZSPECBEGIN
)){
if( (ch
= getchar()) == '`' || ch
== '^'){
ch1
|= 0100; /*convert to lower*/
case 'b': ryylval
= 1; break;
case 'w': ryylval
= 2; break;
case 'l': ryylval
= 4; break;
default: ryylval
= d124
; break;
ch
= ch1
; /*restore first character*/
} while (INCHARSET ( (ch
= getchar()), ALPHA
| DIGIT
));
while (INCHARSET(ch
, SPACE
))
switch((op
= *lookup(1))->s_tag
){
* Its a name... (Labels are subsets ofname)
opstruct
.Op_popcode
= ( (struct instab
*)op
)->i_popcode
;
opstruct
.Op_eopcode
= ( (struct instab
*)op
)->i_eopcode
;
ryylval
= ( (struct instab
*)op
)->i_popcode
;
* Implement call by reference on a reg variable
* yylval or yybignum has been stuffed as a side
* effect to number(); get the global yylval
* into our fast local copy in case it was an INT.
* We allow the C style operators
* << and >>, as well as < and >
if ( (ch1
= getchar()) != ch
)
if ( (ch
= getchar()) =='(')
if ((ryylval
= getchar()) == '\n')
scanlineno
++; /*not entirely correct*/
maxstrlg
= (char *)bufub
- (char *)bufptr
;
if (maxstrlg
< MAXSTRLG
) {
*(bytetoktype
*)bufptr
= VOID
;
lgbackpatch
= bufptr
; /*this is where the size goes*/
bufptr
+= sizeof(lgtype
);
* be stuffed with characters from
&& !(INCHARSET( (ch
= getchar()), STRESCAPE
))
if (maxstrlg
<= 0){ /*enough characters to fill a string buffer*/
ungetc('"'); /*will read it next*/
yywarning("New line embedded in a string constant.");
if ( (inbufptr
= fillinbuffer()) == 0)
} else { /* simple case */
ch
= getchar(); /*skip the '\\'*/
if ( INCHARSET(ch
, BSESCAPE
)){
case 'b': ch
= '\b'; goto stuff
;
case 'f': ch
= '\f'; goto stuff
;
case 'n': ch
= '\n'; goto stuff
;
case 'r': ch
= '\r'; goto stuff
;
case 't': ch
= '\t'; goto stuff
;
if ( !(INCHARSET(ch
,OCTDIGIT
)) ) goto stuff
;
while ( (i
< 3) && (INCHARSET(ch
, OCTDIGIT
))){
i
++;intval
<<= 3;intval
+= ch
- '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 BFINT
: plong(bufptr
, ryylval
);
case INT
: plong(bufptr
, ryylval
);
case BIGNUM
: pnumber(bufptr
, yybignum
);
case NAME
: pptr(bufptr
, (int)(struct symtab
*)ryylval
);
case REG
: pchar(bufptr
, ryylval
);
popcode(bufptr
, opstruct
);
popcode(bufptr
, opstruct
);
pptr(bufptr
, (int)(struct symtab
*)symalloc());
pptr(bufptr
, (int)(struct symtab
*)symalloc());
} /*end of the while to stuff the buffer*/
bufferbox
->tok_count
= (bytetoktype
*)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*/