/* Copyright (c) 1982 Regents of the University of California */
static char sccsid
[] = "@(#)scanner.c 1.9 (Berkeley) %G%";
public String initfile
= ".dbxinit";
typedef enum { WHITE
, ALPHA
, NUM
, OTHER
} Charclass
;
private Charclass
class[256 + 1];
private Charclass
*lexclass
= class + 1;
#define isdigit(c) (lexclass[c] == NUM)
#define isalnum(c) (lexclass[c] == ALPHA or lexclass[c] == NUM)
#define ishexdigit(c) ( \
isdigit(c) or (c >= 'a' and c <= 'f') or (c >= 'A' and c <= 'F') \
private Char linebuf
[MAXLINESIZE
];
private Char
*curchar
, *prevchar
;
} inclinfo
[MAXINCLDEPTH
];
private unsigned int curinclindex
;
private Token
getident();
private Token
getstring();
private Boolean
eofinput();
private Char
charlookup();
private enterlexclass(class, s
)
for (p
= s
; *p
!= '\0'; p
++) {
for (i
= 0; i
< 257; i
++) {
enterlexclass(WHITE
, " \t");
enterlexclass(ALPHA
, "abcdefghijklmnopqrstuvwxyz");
enterlexclass(ALPHA
, "ABCDEFGHIJKLMNOPQRSTUVWXYZ_$");
enterlexclass(NUM
, "0123456789");
* Input is line buffered.
* There are two "modes" of operation: one as in a compiler,
* and one for reading shell-like syntax.
private Boolean shellmode
;
printf("(%s) ", cmdname
);
line
= fgets(linebuf
, MAXLINESIZE
, in
);
} while (line
== nil
and not eofinput());
while (lexclass
[*p
] == WHITE
) {
while (lexclass
[*p
] == WHITE
) {
if (lexclass
[c
] == ALPHA
) {
} else if (lexclass
[c
] == NUM
) {
} else if (isdigit(*curchar
)) {
if (not shellmode
and *curchar
== '<') {
if (not shellmode
and *curchar
== '>') {
} else if (*curchar
== '>') {
if (shellmode
and index("!&*()[]", c
) == nil
) {
fprintf(stderr
, "yylex returns ");
if (streq(s
, "syntax error")) {
while (lexclass
[*p
] == WHITE
and p
> &linebuf
[0]) {
fprintf(stderr
, "%s", linebuf
);
fprintf(stderr
, "%*c", start
, ' ');
fprintf(stderr
, "^ unrecognized command");
fprintf(stderr
, "^ syntax error");
* Scan an identifier and check to see if it's a keyword.
} while (index(" \t\n!&<>*[]()'\"", *p
) == nil
);
yylval
.y_name
= identname(buf
, false);
t
= findkeyword(yylval
.y_name
);
} while (ishexdigit(*p
));
if (*p
== 'e' or *p
== 'E') {
if (*p
== '+' or *p
== '-' or isdigit(*p
)) {
yylval
.y_real
= atof(buf
);
yylval
.y_int
= atol(buf
);
yylval
.y_int
= octal(buf
);
* Convert a string of octal digits to an integer.
for (p
= s
; *p
!= '\0'; p
++) {
* Convert a string of hexadecimal digits to an integer.
for (p
= s
; *p
!= '\0'; p
++) {
if (*p
>= 'a' and *p
<= 'f') {
} else if (*p
>= 'A' and *p
<= 'F') {
private Token
getstring()
while (not endofstring
) {
if (*p
== '\n' or *p
== '\0') {
error("non-terminated string");
} else if (*p
== '"' or *p
== '\'') {
yylval
.y_string
= strdup(buf
);
* Process a character constant.
* Watch out for backslashes.
} while (*p
!= '\\' and *p
!= '\'' and *p
!= '\n' and *p
!= '\0');
* Do a lookup for a ASCII character name.
private String ascii
[] = {
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
"BS", "HT", "NL", "VT", "NP", "CR", "SO", "SI",
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
private char charlookup(s
)
for (i
= 0; ascii
[i
] != NULL
; i
++) {
if (streq(s
, ascii
[i
])) {
error("unknown ascii name \"%s\"", s
);
* Input file management routines.
public setinput(filename
)
f
= fopen(filename
, "r");
error("can't open %s", filename
);
if (curinclindex
>= MAXINCLDEPTH
) {
error("unreasonable input nesting on \"%s\"", filename
);
inclinfo
[curinclindex
].savefile
= in
;
inclinfo
[curinclindex
].savefn
= errfilename
;
inclinfo
[curinclindex
].savelineno
= errlineno
;
private Boolean
eofinput()
in
= inclinfo
[curinclindex
].savefile
;
errfilename
= inclinfo
[curinclindex
].savefn
;
errlineno
= inclinfo
[curinclindex
].savelineno
;
* Pop the current input. Return whether successful.
public Boolean
popinput()
b
= (Boolean
) (not eofinput());
* Return whether we are currently reading from standard input.
return (Boolean
) (in
== stdin
);
* Send the current line to the shell.
while (*p
!= '\0' and (*p
== '\n' or lexclass
[*p
] == WHITE
)) {
if (*p
== '\0' and isterm(in
)) {
* Read the rest of the current line in "shell mode".
* Print out a token for debugging.
fprintf(f
, "char '\\n'");
fprintf(f
, "char '%c'", t
);
fprintf(f
, "\"%s\"", keywdstring(t
));