Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

247 lines
4.2 KiB
C

#include "stdio.h"
/*
* Changed to use the Standard I/O library 9/13/82 FZ
*/
#include "acom.h"
/*
* Version 3.3, 8/20/82. Made colon a real token and got rid of the TKLAB
* token type, to accomodate 8086 version.
*
* Version 3.2, 7/5/82. Performance enhancements.
*/
static char ident[] = "@(#)a.token.c 3.3";
/*
* stresc - Processes a string escape. This routine is called after the
* escape character (normally '\') has been seen. It scans off the remainder
* of the escape and returns its value.
*/
stresc() {
int ct,
val;
scanc();
if('0'<=ch && ch<='7') { /* an octal escape */
val = 0; ct = 3;
do {
val = (val<<3)+ch-'0';
scanc();
} while(--ct>0 && '0'<=ch && ch<='7');
unscanc();
return(val);
}
switch(ch) { /* a single-character escape */
case 'b':
case 'B':
return('\b');
case 'f':
case 'F':
return('\f');
case 'n':
case 'N':
return('\n');
case 'r':
case 'R':
return('\r');
case 't':
case 'T':
return('\t');
default:
return(ch);
}
}
/*
* token - Scans the next token and returns its type. Also sets up the
* token's type and value information in the global cells toktyp, tokval,
* and tokstr.
*/
token() {
int c;
struct chent *chp;
char radix;
char *strp;
strp = tokstr;
scanc();
#ifdef DEBUG
printf("%c(%o)",ch,ch);
#endif
if(white(ch)) { /* white space */
do {
scanc();
} while(white(ch));
if(ch!=';' && ch!='\n') {
unscanc();
return(toktyp = TKSPC);
}
}
if(ch == ';') { /* comment */
do {
scanc();
} while(ch != '\n');
return(toktyp = TKEOL);
}
if('a'<=ch&&ch<='z' || 'A'<=ch&&ch<='Z' || ch=='$' || ch=='_'
|| ch=='.') { /* symbol */
do {
if(strp < tokstr+SYMSIZ) *strp++ = ch;
scanc();
} while('a'<=ch&&ch<='z' || 'A'<=ch&&ch<='Z' ||
'0'<=ch&&ch<='9' || ch=='$' || ch=='_' || ch=='.');
*strp = '\0';
unscanc();
return(toktyp = TKSYM);
}
if('0'<=ch && ch<='9') { /* constant */
do {
*strp++ = ch;
scanc();
if('A'<=ch && ch<='Z') ch += 'a'-'A';
} while('0'<=ch&&ch<='9' || 'a'<=ch&&ch<='z');
unscanc();
*strp = '\0';
c = *--strp;
if('0'<=c && c<='9') radix = 10;
else {
switch(c) {
case 'b':
radix = 2;
break;
case 'd':
radix = 10;
break;
case 'h':
radix = 16;
break;
case 'o':
case 'q':
radix = 8;
break;
default:
return(toktyp = TKERR);
}
*strp = '\0';
}
tokval = 0; strp = tokstr;
while(c = *strp++) {
if('0'<=c && c<='9') c -= '0';
else c += 10-'a';
if(c >= radix) return(toktyp = TKERR);
tokval = tokval*radix+c;
}
return(toktyp = TKCON);
}
if(ch == '\'') { /* character constant */
scanc();
if(ch == '\n') {
unscanc();
return(toktyp = TKERR);
}
tokval = (ch==escchr)?stresc():ch;
scanc();
if(ch != '\'') {
unscanc();
return(toktyp = TKERR);
}
return(toktyp = TKCON);
}
if(ch == '"') { /* quoted string */
scanc();
while(ch != '"') {
if(ch == '\n') {
unscanc();
return(toktyp = TKERR);
}
if(strp < tokstr+STRSIZ) {
*strp++ = (ch==escchr)?stresc():ch;
}
scanc();
}
*strp = '\0';
tokval = strp-tokstr;
return(toktyp = TKSTR);
}
if(ch == '<') {
scanc();
if(ch == '<') {
tokval = TVSHL;
return(toktyp = TKMULOP);
}
if(ch == '=') {
tokval = TVLE;
return(toktyp = TKRELOP);
}
unscanc();
tokval = TVLT;
return(toktyp = TKRELOP);
}
if(ch == '>') {
scanc();
if(ch == '>') {
tokval = TVSHR;
return(toktyp = TKMULOP);
}
if(ch == '=') {
tokval = TVGE;
return(toktyp = TKRELOP);
}
unscanc();
tokval = TVGT;
return(toktyp = TKRELOP);
}
if(ch == '!') {
scanc();
if(ch == '=') {
tokval = TVNE;
return(toktyp = TKRELOP);
}
unscanc();
return(toktyp = TKERR);
}
/* single character token */
for(chp=chtab ; chp->ch_chr ; chp++) {
if(ch == chp->ch_chr) break;
}
tokval = chp->ch_val;
return(toktyp = chp->ch_typ);
}
/*
* xscanc - Takes care of the cases of character scanning which would be
* difficult for the macro scanc() to handle. Namely, these are end of line
* processing and continuation processing.
*/
xscanc() {
top:
if(ch == '\0') {
getline();
ch = *scanpt++;
goto top;
}
if(ch==escchr && *scanpt=='\n') { /* continuation */
scanpt++;
putline();
ch = *scanpt++;
goto top;
}
return(ch);
}