#include <stdio.h>
#include <ctype.h>
#include "compiler.h"
#define iswhite(ch) (ch == ' ' || ch == '\t')
extern void err_abort(char *, ...);
extern void syserr_abort(char *, ...);
extern void warning(char *, ...);
static int first_column;
static void backspace(void);
void reset_input(void);
void panic_mode(int);
int
get_token()
{
long number;
int type = UNDEF;
register int ch;
static char buffer[1024];
register char *ptr;
int dot_flag = FALSE;
while ((ch = next_char()) == '\n' || (isascii(ch) && iswhite(ch)));
if (ch == EOF)
type = EOF;
else {
if (ch == '.') {
dot_flag = TRUE;
while ((ch = next_char()) == ' ' || ch == '\t');
}
if (! isascii(ch) || ! isalnum(ch)) {
warning("Illegal character - '%c'", ch);
panic_mode(',');
}
ptr = buffer;
if (ch != '\n') *(ptr++) = ch;
if (first_column) {
while ((ch = next_char()) != ',' && ch != '\n' && ch != EOF)
*(ptr++) = ch;
if (ch == EOF)
err_abort("Premature EOF");
else if (ch == '\n') {
warning("Newline in middle of terminal name");
panic_mode(',');
}
*ptr = '\0';
curr_token.tk_name = buffer;
type = NAMES;
} else {
ch = next_char();
while (isascii(ch) && isalnum(ch)) {
*(ptr++) = ch;
ch = next_char();
}
*ptr++ = '\0';
switch (ch) {
case ',':
curr_token.tk_name = buffer;
type = BOOLEAN;
break;
case '@':
if (next_char() != ',')
warning("Missing comma");
curr_token.tk_name = buffer;
type = CANCEL;
break;
case '#':
number = 0;
if ((ch = next_char()) == ',')
warning("Missing numeric value");
backspace();
if ((ch = next_char()) == '0') {
if ((ch = next_char()) == 'x' || ch == 'X') {
while (isascii(ch = next_char()) &&
isxdigit(ch)) {
number *= 16;
if (isdigit(ch))
number += ch - '0';
else if (ch >= 'a' && ch <= 'f')
number += 10 + ch - 'a';
else
number += 10 + ch - 'A';
}
} else {
backspace();
while ((ch = next_char()) >= '0' &&
ch <= '7')
number = number * 8 + ch - '0';
}
} else {
backspace();
while (isascii(ch = next_char()) &&
isdigit(ch))
number = number * 10 + ch - '0';
}
if (ch != ',')
warning("Missing comma");
curr_token.tk_name = buffer;
curr_token.tk_valnumber = number;
type = NUMBER;
break;
case '=':
ch = trans_string(ptr);
if (ch != '\0' && ch != ',')
warning("Missing comma");
if (ch == '\0')
warning("NULL string value");
curr_token.tk_name = buffer;
curr_token.tk_valstring = ptr;
type = STRING;
break;
default:
warning("Illegal character - '%c'", ch);
}
}
}
if (dot_flag == TRUE)
DEBUG(8, "Commented out ", "");
if (debug_level >= 8) {
fprintf(stderr, "Token: ");
switch (type) {
case BOOLEAN:
fprintf(stderr, "Boolean; name='%s'\n",
curr_token.tk_name);
break;
case NUMBER:
fprintf(stderr, "Number; name = '%s', value = %d\n",
curr_token.tk_name, curr_token.tk_valnumber);
break;
case STRING:
fprintf(stderr, "String; name = '%s', value = '%s'\n",
curr_token.tk_name, curr_token.tk_valstring);
break;
case CANCEL:
fprintf(stderr, "Cancel; name = '%s'\n",
curr_token.tk_name);
break;
case NAMES:
fprintf(stderr, "Names; value = '%s'\n",
curr_token.tk_name);
break;
case EOF:
fprintf(stderr, "End of file\n");
break;
default:
warning("Bad token type");
}
}
if (dot_flag == TRUE)
type = get_token();
return (type);
}
int curr_column = -1;
char line[1024];
int
next_char()
{
char *rtn_value;
long ftell();
char *p;
if (curr_column < 0 || curr_column > 1023 ||
line[curr_column] == '\0') {
do {
curr_file_pos = ftell(stdin);
if ((rtn_value = fgets(line, 1024, stdin)) == NULL)
return (EOF);
curr_line++;
p = &line[0];
while (*p && iswhite(*p)) {
p++;
}
} while (*p == '#');
curr_column = 0;
while (isascii(line[curr_column]) && iswhite(line[curr_column]))
curr_column++;
}
if (curr_column == 0 && line[0] != '\n')
first_column = TRUE;
else
first_column = FALSE;
return (line[curr_column++]);
}
static void
backspace(void)
{
curr_column--;
if (curr_column < 0)
syserr_abort("Backspaced off beginning of line");
}
void
reset_input(void)
{
curr_column = -1;
}
int
trans_string(char *ptr)
{
register int count = 0;
int number;
register int i;
register int ch;
while ((ch = next_char()) != ',' && ch != EOF && !first_column) {
if (ch == '^') {
ch = next_char();
if (ch == EOF)
err_abort("Premature EOF");
if (!isascii(ch) || ! isprint(ch)) {
warning("Illegal ^ character - '%c'", ch);
}
if (ch == '@')
*(ptr++) = 0200;
else
*(ptr++) = ch & 037;
} else if (ch == '\\') {
ch = next_char();
if (ch == EOF)
err_abort("Premature EOF");
if (ch >= '0' && ch <= '7') {
number = ch - '0';
for (i = 0; i < 2; i++) {
ch = next_char();
if (ch == EOF)
err_abort("Premature EOF");
if (ch < '0' || ch > '7') {
backspace();
break;
}
number = number * 8 + ch - '0';
}
if (number == 0)
number = 0200;
*(ptr++) = (char)number;
} else {
switch (ch) {
case 'E':
case 'e': *(ptr++) = '\033'; break;
case 'l':
case 'n': *(ptr++) = '\n'; break;
case 'r': *(ptr++) = '\r'; break;
case 'b': *(ptr++) = '\010'; break;
case 's': *(ptr++) = ' '; break;
case 'f': *(ptr++) = '\014'; break;
case 't': *(ptr++) = '\t'; break;
case '\\': *(ptr++) = '\\'; break;
case '^': *(ptr++) = '^'; break;
case ',': *(ptr++) = ','; break;
case ':': *(ptr++) = ':'; break;
default:
warning("Illegal character in \\ sequence - '%c'",
ch);
*(ptr++) = ch;
}
}
}
else {
if (ch != '\n') *(ptr++) = ch;
}
count ++;
if (count > 1000)
warning("Very long string found. Missing comma?");
}
if (ch == EOF)
warning("Premature EOF - missing comma?");
else if (first_column) {
backspace();
warning("Missing comma?");
ch = ',';
}
*ptr = '\0';
if (count == 0)
return (0);
return (ch);
}
void
panic_mode(int ch)
{
int c;
for (;;) {
c = next_char();
if (c == ch)
return;
if (c == EOF)
return;
}
}