* Copyright (c) 1982 Regents of the University of California
static char sccsid
[] = "@(#)asscan2.c 4.7 %G%";
static inttoktype oval
= NL
;
#define INBUFLG NINBUFFERS*ASINBUFSIZ + 2
* We have NINBUFFERS input buffers; the first one is reserved
* for catching the tail of a line split across a buffer
* boundary; the other ones are used for snarfing a buffer
* worth of assembly language source.
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
* ASINBUFSIZ
];
static char *p_stop
= &inbuffer
[NINBUFFERS
* ASINBUFSIZ
];
#define MIDDLE &inbuffer[ASINBUFSIZ]
inbufptr
= MIDDLE
- (p_stop
- p_start
);
movestr(inbufptr
, p_start
, p_stop
- p_start
);
* Now, go read up to NINBUFFERS - 1 full buffers
goal
= (NINBUFFERS
- 1)*ASINBUFSIZ
;
got
= read(stdin
->_file
, MIDDLE
+ nread
, goal
);
* back over the partial line
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 */
reg
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
);
ryylval
= (int)savestr(newfname
, strlen(newfname
) + 1);
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*/
for(rcp
= yytext
, maxstrlg
= NCPS
; maxstrlg
> 0; --maxstrlg
){
yywarning("New line in a string constant");
if ( (inbufptr
= fillinbuffer()) != 0){
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
)) )
while ( (i
< 3) && (INCHARSET(ch
, OCTDIGIT
))){
* account for any lines that were crossed
ptoken(bufptr
, ILINESKIP
);
pint(bufptr
, linescrossed
);
* put the string in yytext into the string pool
* The value in ryylval points to the string;
* the previous 2 bytes is the length of the string
* Cheat: append a trailing null to the string
* and then adjust the string length to ignore
* the trailing null. If any STRING client requires
* the trailing null, the client can just change STRLEN
ryylval
= (int)savestr(yytext
, rcp
- yytext
);
STRLEN(((char *)ryylval
)) -= 1;
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 STRING
: pptr(bufptr
, (int)(char *)ryylval
);
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*/