#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "t1stdio.h"
#include "util.h"
#include "digit.h"
#include "token.h"
#include "tokst.h"
#include "hdigit.h"
char *tokenStartP;
char *tokenMaxP;
int tokenLength;
boolean tokenTooLong;
int tokenType;
psvalue tokenValue;
static FILE *inputFileP;
static char *tokenCharP;
#define Exp10(e) \
((e) == 0\
? (double)(1.0)\
: (-64 <= (e) && (e) <= 63\
? Exp10T[(e)+64]\
: P10(e)\
)\
)
static double Exp10T[128] = {
1e-64, 1e-63, 1e-62, 1e-61, 1e-60, 1e-59, 1e-58, 1e-57,
1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49,
1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41,
1e-40, 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33,
1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25,
1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, 1e-18, 1e-17,
1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9,
1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23,
1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31,
1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47,
1e48, 1e49, 1e50, 1e51, 1e52, 1e53, 1e54, 1e55,
1e56, 1e57, 1e58, 1e59, 1e60, 1e61, 1e62, 1e63
};
static double
P10(long exponent)
{
double value, power;
if (exponent < 0) {
power = 0.1;
value = (exponent & 1 ? power : 1.0);
exponent++;
exponent = -(exponent >> 1);
}
else {
power = 10.0;
value = (exponent & 1 ? power : 1.0);
exponent = exponent >> 1;
}
while(exponent > 0) {
power *= power;
if (exponent & 1)
value *= power;
exponent >>= 1;
}
return(value);
}
#define next_ch() (_XT1getc(inputFileP))
#define back_ch(ch) (T1Ungetc(ch, inputFileP))
#define back_ch_not_white(ch) \
(\
isWHITE_SPACE(ch)\
? ((ch == '\r')\
? (((ch = next_ch()) == '\n')\
? EOF\
: back_ch(ch)\
)\
: EOF\
)\
: back_ch(ch)\
)
#define save_unsafe_ch(ch) (*tokenCharP++ = ch)
#define save_ch(ch) \
((tokenCharP < tokenMaxP)\
? save_unsafe_ch(ch)\
: (tokenTooLong = TRUE)\
)
#define save_ch_no_inc(ch) \
if (tokenCharP < tokenMaxP) *tokenCharP = ch
#define DONE (256)
static int
next_char(int ch)
{
return(next_ch());
}
static int
add_char(int ch)
{
save_ch(ch);
return(next_ch());
}
static int
skip_space(int ch)
{
do {
ch = next_ch();
} while(isWHITE_SPACE(ch));
return(ch);
}
static int
skip_comment(int ch)
{
do {
ch = next_ch();
} while(isCOMMENT(ch));
return(ch);
}
static int m_sign;
static long m_value;
static long m_scale;
static int e_sign;
static long e_value;
static long r_base;
static long r_value;
static long r_scale;
static int
add_sign(int ch)
{
m_sign = ch;
save_unsafe_ch(ch);
return(next_ch());
}
static int
add_1st_digits(int ch)
{
m_sign = '+';
return(add_digits(ch));
}
static int
add_digits(int ch)
{
long value, p_value, scale;
int digit;
value = ch - '0';
save_unsafe_ch(ch);
ch = next_ch();
while(isDECIMAL_DIGIT(ch) && value < (MAX_INTEGER/10)) {
value = (value << 3) + (value << 1) + (ch - '0');
save_unsafe_ch(ch);
ch = next_ch();
}
if (isNUMBER_ENDER(ch)) {
back_ch_not_white(ch);
tokenValue.integer = (m_sign == '-' ? -value : value);
tokenType = TOKEN_INTEGER;
return(DONE);
}
p_value = value;
value = (m_sign == '-' ? -value : value);
scale = 0;
if (isDECIMAL_DIGIT(ch)) {
if (p_value == (MAX_INTEGER/10)) {
digit = ch - '0';
if (value > 0) {
if (digit <= MAX_INTEGER%10)
value = (value << 3) + (value << 1) + digit;
else
++scale;
}
else {
if (digit <= -(MIN_INTEGER+10)%10)
value = (value << 3) + (value << 1) - digit;
else
++scale;
}
}
else
++scale;
save_unsafe_ch(ch);
ch = next_ch();
while(isDECIMAL_DIGIT(ch)) {
++scale;
save_ch(ch);
ch = next_ch();
}
}
m_value = value;
m_scale = scale;
e_sign = '+';
e_value = 0;
return(ch);
}
static int
add_1st_decpt(int ch)
{
m_sign = '+';
return(add_decpt(ch));
}
static int
add_decpt(int ch)
{
m_value = 0;
m_scale = 0;
save_unsafe_ch(ch);
return(next_ch());
}
static int
add_fraction(int ch)
{
long value, scale;
int digit;
value = m_value;
scale = m_scale;
if (value == 0) {
while(ch == '0') {
--scale;
save_ch(ch);
ch = next_ch();
}
if (isDECIMAL_DIGIT(ch)) {
--scale;
value = ch - '0';
value = (m_sign == '-' ? -value : value);
save_ch(ch);
ch = next_ch();
}
else
scale = 0;
}
if (isDECIMAL_DIGIT(ch)) {
if (value > 0) {
while(isDECIMAL_DIGIT(ch) && value < (MAX_INTEGER/10)) {
--scale;
value = (value << 3) + (value << 1) + (ch - '0');
save_ch(ch);
ch = next_ch();
}
if (isDECIMAL_DIGIT(ch) && value == (MAX_INTEGER/10)) {
digit = ch - '0';
if (digit <= MAX_INTEGER%10) {
--scale;
value = (value << 3) + (value << 1) + digit;
save_ch(ch);
ch = next_ch();
}
}
}
else {
while(isDECIMAL_DIGIT(ch) && value > -(-(MIN_INTEGER+10)/10+1)) {
--scale;
value = (value << 3) + (value << 1) - (ch - '0');
save_ch(ch);
ch = next_ch();
}
if (isDECIMAL_DIGIT(ch)
&& value == -(-(MIN_INTEGER+10)/10+1)) {
digit = ch - '0';
if (digit <= -(MIN_INTEGER+10)%10) {
--scale;
value = (value << 3) + (value << 1) - digit;
save_ch(ch);
ch = next_ch();
}
}
}
while(isDECIMAL_DIGIT(ch)) {
save_ch(ch);
ch = next_ch();
}
}
m_value = value;
m_scale = scale;
e_sign = '+';
e_value = 0;
return(ch);
}
static int
add_e_sign(int ch)
{
e_sign = ch;
save_ch(ch);
return(next_ch());
}
static int
add_exponent(int ch)
{
long value, p_value;
long scale = 0;
int digit;
value = ch - '0';
save_ch(ch);
ch = next_ch();
while(isDECIMAL_DIGIT(ch) && value < (MAX_INTEGER/10)) {
value = (value << 3) + (value << 1) + (ch - '0');
save_ch(ch);
ch = next_ch();
}
p_value = value;
value = (e_sign == '-' ? -value : value);
if (isDECIMAL_DIGIT(ch)) {
if (p_value == (MAX_INTEGER/10)) {
digit = ch - '0';
if (value > 0) {
if (digit <= MAX_INTEGER%10)
value = (value << 3) + (value << 1) + digit;
else
++scale;
}
else {
if (digit <= -(MIN_INTEGER+10)%10)
value = (value << 3) + (value << 1) - digit;
else
++scale;
}
}
else
++scale;
save_ch(ch);
ch = next_ch();
while(isDECIMAL_DIGIT(ch)) {
++scale;
save_ch(ch);
ch = next_ch();
}
}
e_value = value;
return(ch);
}
static int
add_radix(int ch)
{
if (2 <= m_value && m_value <= 36 && m_scale == 0) {
r_base = m_value;
save_ch(ch);
return(next_ch());
}
else {
return(AAH_NAME(ch));
}
}
static int
add_r_digits(int ch)
{
unsigned long value;
long radix, scale;
int digit;
radix = r_base;
value = 0;
scale = 0;
while(ch == '0') {
save_ch(ch);
ch = next_ch();
}
if ((digit=digit_value[ch]) < radix) {
value = digit;
save_ch(ch);
ch = next_ch();
while((digit=digit_value[ch]) < radix
&& value < (MAX_ULONG / radix)) {
value = value * radix + digit;
save_ch(ch);
ch = next_ch();
};
if ((digit=digit_value[ch]) < radix) {
if (value == (MAX_ULONG/radix) && digit <= MAX_ULONG%radix)
value = value * radix + digit;
else
++scale;
save_ch(ch);
ch = next_ch();
while(digit_value[ch] < radix) {
++scale;
save_ch(ch);
ch = next_ch();
}
}
}
r_value = (long) value;
r_scale = scale;
return(ch);
}
static int
RADIX_NUMBER(int ch)
{
back_ch_not_white(ch);
if (r_scale == 0) {
tokenValue.integer = r_value;
tokenType = TOKEN_INTEGER;
}
else {
tokenType = TOKEN_NAME;
}
return(DONE);
}
static int
INTEGER(int ch)
{
back_ch_not_white(ch);
if (m_scale == 0) {
tokenValue.integer = m_value;
tokenType = TOKEN_INTEGER;
}
else {
tokenValue.real = (double)(m_value) * Exp10(m_scale);
tokenType = TOKEN_REAL;
}
return(DONE);
}
static int
REAL(int ch)
{
double temp;
back_ch_not_white(ch);
if ((m_scale >= 0 && e_value <= 0)
|| (m_scale <= 0 && e_value >= 0)) {
tokenValue.real = (double)(m_value) * Exp10(m_scale + e_value);
}
else {
temp = (double)(m_value) * Exp10(m_scale);
tokenValue.real = temp * Exp10(e_value);
}
tokenType = TOKEN_REAL;
return(DONE);
}
static int
HEX_STRING(int ch)
{
int value;
while(TRUE) {
ch = next_ch();
if (!isHEX_DIGIT(ch)) {
while(isWHITE_SPACE(ch))
ch = next_ch();
if (!isHEX_DIGIT(ch)) {
break;
}
}
value = digit_value[ch] << 4;
ch = next_ch();
if (!isHEX_DIGIT(ch)) {
while(isWHITE_SPACE(ch))
ch = next_ch();
if (!isHEX_DIGIT(ch)) {
save_ch(value);
break;
}
}
save_ch(value + digit_value[ch]);
}
if (ch == '>')
tokenType = TOKEN_HEX_STRING;
else {
save_ch(ch);
tokenType = TOKEN_INVALID;
}
return(DONE);
}
static void
save_digraph(int ch)
{
int value;
switch (ch) {
case 'b':
ch = '\b';
break;
case 'f':
ch = '\f';
break;
case 'n':
ch = '\n';
break;
case 'r':
ch = '\r';
break;
case 't':
ch = '\t';
break;
case '\n':
return;
case '\r':
ch = next_ch();
if (ch == '\n') return;
back_ch(ch);
return;
case EOF:
return;
default:
if (isOCTAL_DIGIT(ch)) {
value = digit_value[ch];
ch = next_ch();
if (isOCTAL_DIGIT(ch)) {
value = (value << 3) + digit_value[ch];
ch = next_ch();
if (isOCTAL_DIGIT(ch))
value = (value << 3) + digit_value[ch];
else
back_ch(ch);
}
else
back_ch(ch);
ch = value;
}
}
save_ch(ch);
}
static int
STRING(int ch)
{
int nest_level = 1;
tokenType = TOKEN_STRING;
do {
ch = next_ch();
while(!isSTRING_SPECIAL(ch)) {
save_ch(ch);
ch = next_ch();
};
switch (ch) {
case '(':
++nest_level;
save_ch(ch);
break;
case ')':
if (--nest_level > 0)
save_ch(ch);
break;
case '\\':
save_digraph(next_ch());
break;
case '\r':
ch = next_ch();
if (ch != '\n') {
back_ch(ch);
}
save_ch('\n');
break;
case EOF:
tokenType = TOKEN_INVALID;
nest_level = 0;
break;
}
} while(nest_level > 0);
save_ch_no_inc(0);
return(DONE);
}
static int
AAH_NAME(int ch)
{
do {
save_ch(ch);
ch = next_ch();
} while(isNAME(ch));
back_ch_not_white(ch);
tokenType = TOKEN_NAME;
return(DONE);
}
static int
NAME(int ch)
{
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
while(isNAME(ch)) {
save_ch(ch);
ch = next_ch();
}
}
}
}
}
}
}
back_ch_not_white(ch);
tokenType = TOKEN_NAME;
return(DONE);
}
static int
LITERAL_NAME(int ch)
{
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
while(isNAME(ch)) {
save_ch(ch);
ch = next_ch();
}
}
}
}
}
}
}
back_ch_not_white(ch);
tokenType = TOKEN_LITERAL_NAME;
return(DONE);
}
static int
IMMED_NAME(int ch)
{
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
if (isNAME(ch)) {
save_unsafe_ch(ch);
ch = next_ch();
while(isNAME(ch)) {
save_ch(ch);
ch = next_ch();
}
}
}
}
}
}
}
back_ch_not_white(ch);
tokenType = TOKEN_IMMED_NAME;
return(DONE);
}
static int
OOPS_NAME(int ch)
{
back_ch_not_white(ch);
tokenType = TOKEN_NAME;
return(DONE);
}
static int
RIGHT_ANGLE(int ch)
{
tokenType = TOKEN_RIGHT_ANGLE;
return(DONE);
}
static int
RIGHT_PAREN(int ch)
{
tokenType = TOKEN_RIGHT_PAREN;
return(DONE);
}
static int
LEFT_BRACE(int ch)
{
tokenType = TOKEN_LEFT_BRACE;
return(DONE);
}
static int
RIGHT_BRACE(int ch)
{
tokenType = TOKEN_RIGHT_BRACE;
return(DONE);
}
static int
LEFT_BRACKET(int ch)
{
save_unsafe_ch(ch);
tokenType = TOKEN_LEFT_BRACKET;
return(DONE);
}
static int
RIGHT_BRACKET(int ch)
{
save_unsafe_ch(ch);
tokenType = TOKEN_RIGHT_BRACKET;
return(DONE);
}
static int
BREAK_SIGNAL(int ch)
{
tokenType = TOKEN_BREAK;
return(DONE);
}
static int
NO_TOKEN(int ch)
{
tokenType = TOKEN_EOF;
return(DONE);
}
void
scan_token(psobj *inputP)
{
int ch;
unsigned char *stateP = s0;
unsigned char entry;
int (*actionP)(int);
inputFileP = inputP->data.fileP;
if (inputFileP == NULL) {
tokenType = TOKEN_EOF;
return;
}
tokenStartP = vm_next_byte();
tokenMaxP = tokenStartP + MIN(vm_free_bytes(), MAX_STRING_LEN);
if ((tokenMaxP-tokenStartP) < (MAX_NAME_LEN)) {
tokenLength = 0;
tokenTooLong = TRUE;
tokenType = TOKEN_NONE;
tokenValue.integer = 0;
return;
}
tokenCharP = tokenStartP;
tokenTooLong = FALSE;
ch = next_ch();
do {
entry = stateP[ch];
stateP = classActionTable[entry].nextStateP;
actionP = classActionTable[entry].actionRoutineP;
ch = (*actionP)(ch);
} while(ch != DONE);
tokenLength = tokenCharP - tokenStartP;
}