home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
compiler
/
nasm20b
/
nasm_src
/
lexer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-19
|
34KB
|
1,273 lines
/* ---------------------------------------------------------------------- */
/* Copyright (C) 1991 by Natürlich! */
/* This file is copyrighted! */
/* Refer to the documentation for details. */
/* ---------------------------------------------------------------------- */
#define DEBUG 0
#define TOKDEBUG 0 /* following set 4 Atari 8MHz */
#define FINPUT_IO 1 /* yields 15% speed increase */
#define QINPUT_IO 1 /* yields 20% speed increase */
#define USEINLINE 0
#define QSTRING 0 /* 1 == doesn't do much */
#define QWHITE 1
#define QCOMMENT 1
#define QIDENT 1
#define QIDENT2 0 /* 1 == worsens performance ! */
#define QLABEL 0 /* 1 == doesn't do anything */
#define QMACRO 0 /* 1 == same or worse */
#define QDIRECT 0 /* 1 == doesn't do anything */
/* --------------------------------------------------------- */
/* SHIT!! FLEX can't digest characters >= 128 */
/* Now I have to write my own lexer... */
/* --------------------------------------------------------- */
#include "defines.h"
#include "nasm.h"
#include "y_tab.h"
#include <stdio.h>
#if OS == TOS
#include <osbind.h>
#endif
#include <setjmp.h>
#include "debug.h"
#include "code.h"
#include NMALLOC_H
#if VERSION && FINPUT_IO
extern buffer huge *bp;
# include "inputfst.h"
#endif
#define LINESTART 0
#define INSTRUCTION 1
#define AFTERINSTR 2
#define AFTERELSE 3
#define AFTEROPTION 4
#define AFTERFLOAT 5
#define AFTERINCLUDE 6
#define COMMENT 7
#define E_GARBAGE garbage /* historic */
#define E_LABELFORM labelform
#define E_HEXLEN hexlen
#define E_INTSIZE intsize
static char
igarbage[] = "Garbage in the instruction field",
garbage[] = "Totally uncomprehendable garbage",
labelform[] = "Label starts off with wrong character",
hexlen[] = "Hex value exceeds 16 Bit (not that good on a 64K machine)",
intsize[] = "Integer value >= 65536, how would that fit into 2 bytes ?",
mpara_incomplete[] =
"Incomplete macro parameter (form %[$]<[0-9]+|(<label>))";
/* --------------------------------------------------------- */
/* The ultra-clever (har har) way of deciding whether we are */
/* facing something usable as an identifier character. */
/* There is a method to this madness: */
/* Bit7 . Bit6 . Bit5 . Bit4 . Bit3 . Bit2 . Bit1 . Bit0 */
/* -----+------+------+------+------+------+------+----- */
/* Lower| | | Foo | A-Z |Float | Hex | No */
/* -----+------+------+------+------+------+------+----- */
/* $80 $40 $20 $10 $08 $04 $02 $01 */
/* */
/* A question remains, are we losing with this table ?? */
/* --------------------------------------------------------- */
#define is_ident( c) (is_what[ (c)])
#define is_lower( c) ((signed char) is_what[ (c)] < 0)
#define is_hex( c) (is_what[ (c)] & M_HEX)
#define is_digit( c) (is_what[ (c)] == DIGIT)
#define is_letter( c) (is_what[ (c)] & M_LETTER)
#define is_float( c) (is_what[ (c)] & M_FLOAT)
#define tis_ident( c) (p_table[ (c)])
#define tis_lower( c) ((signed char) p_table[ (c)] < 0)
#define tis_hex( c) (p_table[ (c)] & M_HEX)
#define tis_digit( c) (p_table[ (c)] == DIGIT)
#define tis_letter( c) (p_table[ (c)] & M_LETTER)
#define tis_float( c) (p_table[ (c)] & M_FLOAT)
#define M_LOWER 0x80
#define M_FOO 0x10
#define M_LETTER 0x08
#define M_FLOAT 0x04
#define M_HEX 0x02
#define M_DIGIT 0x01
#define DIGIT (M_DIGIT | M_HEX | M_FLOAT)
#define L (M_LETTER | M_LOWER) /* lower */
#define A M_LETTER /* upper */
#define H (M_LETTER | M_HEX) /* up&hex */
#define E (M_LETTER | M_HEX | M_FLOAT)
#define P M_FLOAT
#define X M_FOO
#define N DIGIT
byte is_what[] = /* xlat: is' watt !?!? */
{
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $00 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $10 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,P,0, /* $20 */
N,N,N,N, N,N,N,N, N,N,X,0, 0,0,0,X, /* $30 */
X,H,H,H, H,E,H,A, A,A,A,A, A,A,A,A, /* $40 */
A,A,A,A, A,A,A,A, A,A,A,0, 0,0,0,X, /* $50 */
0,L,L,L, L,L,L,L, L,L,L,L, L,L,L,L, /* $60 */
L,L,L,L, L,L,L,L, L,L,L,0, 0,0,0,0, /* $70 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $80 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $90 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $A0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $B0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $C0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $D0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $E0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 /* $F0 */
};
#undef F
#undef N
#undef L
#undef A
#undef H
#undef E
#undef P
#undef X
#define is_white( c) (white[ (c)])
#define skip_white(c) while( white[ c]) c = uinput()
#define tis_white( c) (p_table[ (c)])
#define tskip_white(c) while( p_table[ c]) c = uinput()
static char white[] = /* ain't no saying whether this actually */
{ /* helps improve the speed */
0,0,0,0, 0,0,0,0, 0,1,0,0, 0,1,0,0, /* $00 */
0,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,0, /* $10 */ /* $1A for MSDOS */
1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $20 */ /* whatever that */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $30 */ /* might be */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $40 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $50 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $60 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $70 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $80 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $90 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $A0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $B0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $C0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $D0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $E0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 /* $F0 */
};
#define A 0x01 /* 'X' */
#define B 0x02 /* 'Y' */
#define C 0x03 /* '#' */
#define D 0x04 /* '(' */
#define E 0x05 /* ')' */
#define F 0x06 /* ',' */
#define G 0x07 /* '=' */
#define H 0x08 /* '+' */
#define I 0x09 /* '-' */
#define J 0x0A /* '!' */
#define K 0x0B /* '&' */
#define L 0x0C /* '*' */
#define M 0x0D /* '/' */
#define N 0x0E /* '\\' */
#define O 0x0F /* '^' */
#define P 0x10 /* '[' */
#define Q 0x11 /* ']' */
#define IREGS 0x02
static byte af1_toks[] =
{
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $00 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $10 */
0,J,0,C, 0,0,K,0, D,E,L,H, F,I,0,M, /* $20 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,G,0,0, /* $30 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $40 */
0,0,0,0, 0,0,0,0, A,B,0,P, N,Q,O,0, /* $50 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $60 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $70 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $80 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $90 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $A0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $B0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $C0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $D0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $E0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 /* $F0 */
};
static byte af2_toks[] =
{
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $00 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $10 */
0,J,0,0, 0,0,K,0, D,E,L,H, F,I,0,M, /* $20 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,G,0,0, /* $30 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $40 */
0,0,0,0, 0,0,0,0, 0,0,0,P, N,Q,O,0, /* $50 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $60 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $70 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $80 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $90 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $A0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $B0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $C0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $D0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* $E0 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 /* $F0 */
};
#undef A
#undef B
#undef C
#undef D
#undef E
#undef F
#undef G
#undef H
#undef I
#undef J
#undef K
#undef L
#undef M
#undef N
#undef O
#undef P
#undef Q
#if DEBUG /* Bugs ? Yeah SURE we gottem.. All sizes and shapes! */
#define dreturn( val) \
{ \
int foo = (val); \
prtname( foo); \
LEAVE(); \
return( foo); \
}
#define xreturn( val) \
{ \
int foo = (val); \
\
LEAVE(); \
return( foo); \
}
#define fdreturn( val) \
{ \
int foo = (val); \
\
c = uinput(); \
prtname( foo); \
LEAVE(); \
return( foo); \
}
#else
#define dreturn return
#define xreturn return
#define fdreturn( val) \
{ \
c = uinput(); \
return( val); \
}
#endif
#define comparators() \
if( c_ == '<') \
if( (c_ = uinput()) == '>') \
{ \
c = c_; \
fdreturn( T_NEQ); \
} \
else \
if( (c = c_) == '=') \
{ \
fdreturn( T_LEQ); \
} \
else \
dreturn( '<'); \
\
if( c_ == '>') \
{ \
if( (c = uinput()) == '=') \
{ \
fdreturn( T_GEQ); \
} \
dreturn( '>'); \
}
extern lword yylval;
extern freshflag;
static char miss_char[] = "Missing character after \' (quote)",
yytext[1024];
int state = LINESTART,
wasstrlen,
#if __NSTDC__
(*gettoken)( void);
#else
(*gettoken)();
#endif
byte c;
#if VERSION
static byte tmp;
#endif
jmp_buf syn_panic;
#if DEBUG
int syndebug;
#endif
int nilexer()
{
yylval = 0;
return(0);
}
int yylex()
{
ENTER("yylex");
#if TOKDEBUG
{
int i = (*gettoken)();
prtname( i);
xreturn( i);
}
#else
# if OS == TOS && WITHNOISY
{
extern int noisytok, _in_macro;
if( noisytok)
{
static unsigned char fx[] =
{
2, 0, 3, 0, 9, 8, 7, 0xFD, 0xFF, 10,
7, 0xFF, 0xFF, 0
};
int tok = (*gettoken)();
fx[1] = tok & 0x3F;
fx[3] = _in_macro;
Dosound( fx);
xreturn( tok);
}
}
# endif
xreturn((*gettoken)());
#endif
}
int lexer()
{
register byte c_ = c,
*p_table = (byte *) white;
ENTER( "lexer");
if( freshflag) /* Have we set syn_panic already ?? */
{
freshflag = 0; /* No clr flag */
#if DEBUG
SAVESTATE( &syndebug);
#endif
if( setjmp( syn_panic)) /* Do the setjmp ONCE */
{
#if DEBUG
SETBACK( syndebug);
#endif
MESS("\007\t\tsyntax panic occurred");
while( c_ != '\n') /* If a longjmp() happens: ignore line */
c_ = uinput();
state = LINESTART; /* reset state */
}
}
if( tis_white( c_)) /* TOS files have white before LF */
{
#if VERSION && FINPUT_IO && QINPUT_IO && QWHITE
register byte huge *pt = bp->p;
register byte *tab = _uptable;
register lword rem = bp->remain;
while( tis_white( c_ = quinput( rem, pt, tab)));
if( bp)
{
bp->remain = rem;
bp->p = pt;
}
#else
while( tis_white( c_ = uinput()));
#endif
if( state == LINESTART)
state = INSTRUCTION;
}
if( c_ == ';' || state == COMMENT)
{
#if VERSION && FINPUT_IO && QINPUT_IO && QCOMMENT
register byte huge *pt = bp->p;
register byte *tab = _uptable;
register lword rem = bp->remain;
while( (c_ = quinput( rem, pt, tab)) != '\n');
if( bp)
{
bp->remain = rem;
bp->p = pt;
}
#else
while( (c_ = uinput()) != '\n');
#endif
}
if( c_ == '\n')
{
state = LINESTART;
c = c_;
fdreturn( T_EOL);
}
#if USEINLINE
switch( state)
{
case LINESTART :
IMESS("[LINESTART] c == %d", (lword) c_, 2);
state = INSTRUCTION;
if( is_ident( c = c_))
{
xreturn( label_suckin());
}
else
junk_suckin( E_GARBAGE);
case INSTRUCTION :
IMESS("[INSTRUCTION c=='%c']", (lword) c_, 1);
if( c_ == '.')
{
c = c_;
state = AFTERELSE;
xreturn( directive_suckin());
}
if( is_ident( c = c_))
{
state = AFTERINSTR;
xreturn( macro_suckin()); /* macros and instructions too */
}
state = AFTERELSE;
if( c_ == '=')
fdreturn( c_);
if( c_ == '*')
{
while( tis_white( c_ = uinput()));
if( c_ == '=')
fdreturn( T_ORG);
c_ = '*';
}
yytext[0] = c = c_;
yytext[1] = 0;
lsyntax( igarbage);
case AFTERINSTR :
MESS("[AFTERINSTR]");
switch( c_)
{
case '$' : xreturn( hex_suckin());
case '.' : xreturn( directive_suckin());
case '%' : xreturn( para_suckin());
case '\'':
{
if( tis_white( c = input()))
lsyntax(miss_char);
yylval = (lword) c;
fdreturn( T_CHAR);
}
}
if( is_digit( c = c_))
xreturn( int_suckin());
{
register int a;
if( a = af1_toks[ c_])
{
if( is_ident( c = uinput()) && a <= IREGS)
xreturn( ident2_suckin( c_));
dreturn( c_);
}
}
if( is_ident( c_))
xreturn( ident_suckin());
comparators();
junk_suckin( garbage);
case AFTERELSE :
MESS("[AFTERELSE]");
switch( c_)
{
case '%' : xreturn( para_suckin());
case '"' : xreturn( string_suckin());
case '$' : xreturn( hex_suckin());
case '.' : xreturn( directive_suckin());
case '\'': if( tiswhite( c = input()))
lsyntax(miss_char);
yylval = (lword) c;
fdreturn( T_CHAR);
}
if( is_digit( c = c_))
xreturn( int_suckin());
if( af2_toks[ c_])
fdreturn( c_);
if( is_ident(c_))
xreturn( ident_suckin());
comparators();
junk_suckin( garbage);
case AFTEROPTION :
MESS("[AFTEROPTION]");
if( c_ == ',')
fdreturn( c_);
c = c_;
xreturn( option_suckin());
case AFTERINCLUDE :
MESS("[AFTERINCLUDE]");
if( c_ == '#')
fdreturn( c_);
c = c_;
xreturn( file_suckin());
case AFTERFLOAT :
MESS("[AFTERFLOAT]");
if( c_ == ',')
fdreturn( c_);
c = c_;
xreturn( float_suckin());
}
nierror("problems with the lexer state");
}
#else
switch( state)
{
case LINESTART :
IMESS("[LINESTART] c == %d", (lword) c, 2);
state = INSTRUCTION;
if( is_ident(c = c_))
{
xreturn( label_suckin());
}
else
junk_suckin( E_GARBAGE);
case INSTRUCTION :
IMESS("[INSTRUCTION c=='%c']", (lword) c_, 1);
if( (c = c_) == '.')
{
state = AFTERELSE;
xreturn( directive_suckin());
}
if( is_ident( c))
{
state = AFTERINSTR;
xreturn( macro_suckin()); /* macros and instructions too */
}
MESS("**HIT THIS***");
state = AFTERELSE;
if( c_ == '=')
fdreturn( c_);
if( c_ == '*')
{
while( tis_white( c_ = uinput()));
if( c_ == '=')
fdreturn( T_ORG);
c_ = '*';
}
yytext[0] = c = c_;
yytext[1] = 0;
lsyntax( igarbage);
case AFTERINSTR :
{
register int a;
MESS("[AFTERINSTR]");
if( a = af1_toks[ c_])
{
if( is_ident( c = uinput()) && a <= IREGS)
xreturn( ident2_suckin( c_));
dreturn( c_);
}
comparators();
c = c_;
xreturn( get_itoken());
}
case AFTERELSE :
{
MESS("[AFTERELSE]");
if( af2_toks[ c_])
fdreturn( c_);
comparators();
c = c_;
xreturn( get_etoken());
}
case AFTEROPTION:
MESS("[AFTEROPTION]");
if( c_ == ',')
fdreturn( c_);
c = c_;
xreturn( option_suckin());
case AFTERFLOAT:
MESS("[AFTERFLOAT]");
if( c_ == ',')
fdreturn( c_);
c = c_;
xreturn( float_suckin());
case AFTERINCLUDE:
MESS("[AFTERINCLUDE]");
if( c_ == '#')
fdreturn( c_);
c = c_;
xreturn( file_suckin());
}
nierror("problems with the lexer state");
#if __NSTDC__ && VERY_PRETTY
return(0);
#endif
}
/* ------------------------------------------------------------- */
/* Stands for: Get after instruction token. */
/* ------------------------------------------------------------- */
get_itoken()
{
ENTER("get_itoken");
switch( c)
{
case '$' : xreturn( hex_suckin());
case '.' : xreturn( directive_suckin());
case '%' : xreturn( para_suckin());
case '\'': if( is_white( c = input()))
lsyntax(miss_char);
yylval = (lword) c;
fdreturn( T_CHAR);
}
if( is_digit(c))
xreturn( int_suckin());
if( is_ident( c))
xreturn( ident_suckin());
junk_suckin( garbage);
#if __NSTDC__ && VERY_PRETTY
return(0);
#endif
}
/* ------------------------------------------------------------- */
/* Stands for: Get after macro call token. */
/* ------------------------------------------------------------- */
get_etoken()
{
ENTER("get_etoken");
IMESS("c = '%c'", (lword) c, 1);
switch( c)
{
case '%' : xreturn( para_suckin());
case '"' : xreturn( string_suckin());
case '$' : xreturn( hex_suckin());
case '.' : xreturn( directive_suckin());
case '\'': if( is_white( c = input()))
lsyntax(miss_char);
yylval = (lword) c;
fdreturn( T_CHAR);
}
if( is_digit(c))
xreturn( int_suckin());
if( is_ident(c))
xreturn( ident_suckin());
junk_suckin( garbage);
#if __NSTDC__ && VERY_PRETTY
return(0);
#endif
}
#endif
/* ------------------------------------------------------------- */
/* Stands for: Get after macro call token. */
/* ------------------------------------------------------------- */
para_suckin()
{
ENTER("para_suckin");
switch( c = uinput())
{
case '(' :
MESS("way1a");
while( is_white( c = uinput()));
if( is_ident( c))
{
MESS("way1b");
ident_suckin();
skip_white( c);
if( c == ')')
fdreturn( T_MLPARA)
}
break;
case '$' :
MESS("way2a");
if( is_digit( c = uinput()))
{
int_suckin();
dreturn( T_MSPARA);
}
if( c == '(')
{
MESS("way2b");
while( is_white( c = uinput()));
if( is_ident( c))
{
MESS("way2c");
ident_suckin();
skip_white( c);
if( c == ')')
fdreturn( T_MLSPARA)
}
}
break;
default :
IMESS("way3 c = '%c'", (lword) c, 1);
if( is_digit( c))
{
int_suckin();
dreturn( T_MPARA);
}
}
lsyntax( mpara_incomplete);
}
ident_suckin()
{
register byte *p = (byte *) yytext,
c_ = c,
*p_table = is_what;
register int i = 1;
ENTER("ident_suckin");
#if VERSION && FINPUT_IO && QINPUT_IO && QIDENT
{
register byte huge *pt = bp->p;
register byte *tab = _uptable;
register lword rem = bp->remain;
do
{
*p++ = c_;
i++;
}
while( tis_ident( c_ = quinput( rem, pt, tab)));
if( bp)
{
bp->remain = rem;
bp->p = pt;
}
}
#else
do
{
*p++ = c_; /* convert to upper & save */
i++;
}
while( tis_ident( c_ = uinput()));
#endif
*p = 0;
c = c_;
if( state == AFTERINSTR)
if( ! yytext[1] && yytext[0] == 'A')
xreturn( T_ACCU);
yy_txt2val( i);
dreturn( T_IDENT);
}
ident2_suckin( extra)
char extra;
{
register byte *p = (byte *) yytext,
c_ = c,
*p_table = is_what;
register int i = 2;
ENTER("ident2_suckin");
*p++ = extra;
#if VERSION && FINPUT_IO && QINPUT_IO && QIDENT2
{
register byte huge *pt = bp->p;
register byte *tab = _uptable;
register lword rem = bp->remain;
do
{
*p++ = c_;
i++;
}
while( tis_ident( c_ = quinput( rem, pt, tab)));
if( bp)
{
bp->remain = rem;
bp->p = pt;
}
}
#else
do
{
*p++ = c_; /* convert to upper & save */
i++;
}
while( tis_ident(c_ = uinput()));
#endif
*p = 0;
c = c_;
if( state == AFTERINSTR)
if( ! yytext[1] && yytext[0] == 'A')
xreturn( T_ACCU);
yy_txt2val( i);
dreturn( T_IDENT);
}
label_suckin()
{
register char *p = yytext,
c_ = c,
*p_table = (char *) is_what;
register int i = 1;
ENTER("label_suckin");
if( c_ == '.' || tis_digit( c_))
{
c = c_;
lsyntax( E_LABELFORM);
}
#if VERSION && FINPUT_IO && QINPUT_IO && QLABEL
{
register byte huge *pt = bp->p;
register byte *tab = _uptable;
register lword rem = bp->remain;
while( tis_ident( c_))
{
*p++ = c_;
i++;
c_ = quinput( rem, pt, tab);
}
if( bp)
{
bp->remain = rem;
bp->p = pt;
}
}
#else
while( tis_ident(c_)) /* Suck in macro call or */
{ /* instruction */
*p++ = c_; /* convert to upper & save */
i++;
c_ = uinput(); /* get fresh input */
}
#endif
if( p[-1] == ':' && i > 2) /* kill trailing : for labels */
{
--i;
--p;
}
*p = 0;
c = c_;
yy_txt2val( i);
dreturn( T_LABEL);
}
void junk_suckin( error)
char *error;
{
register byte *p = (byte *) yytext;
ENTER("junk_suckin");
while( c > ' ' && c != ';' && c != ',') /* Errors.. so we don't care */
{ /* about speed anyway. */
*p++ = c;
c = uinput();
}
*p = 0;
ALEAVE();
lsyntax( error);
}
string_suckin()
{
register byte *p = (byte *) yytext + 2;
register unsigned i = 0;
ENTER("string_suckin");
#if VERSION && FINPUT_IO && QINPUT_IO && QSTRING
{
register byte huge *pt = bp->p;
register lword rem = bp->remain;
while( (*p++ = qinput( rem, pt)) != '\"')
i++;
if( bp)
{
bp->remain = rem;
bp->p = pt;
}
}
#else
while( (*p++ = input()) != '\"')
i++;
#endif
p[-1] = 0;
dbyte( yytext, wasstrlen = i);
i += 3; /* 2 for i, 1 for strlen */
yy_txt2val( i);
fdreturn( T_STRING);
}
char *make_string( s)
register char *s;
{
register char *q;
register int i;
char *t;
ENTER("make_string");
{
register char *src = s;
for( src = s, i = 0; *src++; i++);
}
q = t = str_alloc( i + 3);
dbyte( q, i);
q += 2;
while( i > 4)
{
*q++ = *s++;
*q++ = *s++;
*q++ = *s++;
*q++ = *s++;
i -= 4;
}
do
*q++ = *s++;
while( --i);
LEAVE();
return( t);
}
file_suckin()
{
register byte *p = (byte *) yytext,
c_ = (c >= 'A' && c <= 'Z') ? c + 32 : c;
register int i = 1;
ENTER("file_suckin");
do
{
*p++ = c_;
i++;
if ( (c_ = input()) == '/' || c_ == '>')
c_ = '\\';
}
while( is_ident( c_) || c_ == '\\');
*p = 0;
c = c_;
yy_txt2val( i);
dreturn( T_FILE);
}
float_suckin()
{
char *p = yytext;
int eflag = 1,
pflag = 1,
jflag = 0,
kflag = 1;
ENTER("float_suckin");
while( (is_float(c) || ((c == '+' || c == '-') && (jflag || kflag)))
&& (c != '.' || (pflag && eflag))
&& (c != 'E' || eflag))
{
if( (c == '+') || (c == '-'))
kflag = 0;
if( c == '.')
pflag = 0;
jflag = 0;
if( c == 'E')
{
pflag = eflag = 0;
jflag = 1;
}
*p++ = c;
c = uinput();
}
*p = 0;
dropfloat( yytext);
dreturn( T_XFLOAT);
}
/* ---------------------------------------------------------- */
/* To make this more generic, it would be good to */
/* parametrize (sp?) this macro a bit more */
/* ---------------------------------------------------------- */
#define nextdigit( _recurs) \
if( tis_digit( c_ = uinput())) \
{ \
tmp = val + val; \
val = (tmp << 2) + tmp; \
val += c_ - '0'; \
_recurs \
}
#define finaldigit() \
if( tis_digit( c_ = uinput())) \
{ \
if( val >= 6553 && (val > 6553 || c_ >= '6')) /* This looks */ \
{ /* worse than */ \
c = c_; /* it is */ \
synerr: \
lsyntax( E_INTSIZE); \
} \
tmp = val + val; \
val = (tmp << 2) + tmp; \
yylval = (lword) (val + c_ - '0'); \
if( tis_digit( c = uinput())) \
goto synerr; \
IMESS("Int number is %ld", yylval, 4); \
xreturn( T_NUMBER); \
}
/* ---------------------------------------------------------- */
/* Suck in a int value. Most probably fuinputting the number */
/* into yytext and converting it later with nextdigit would */
/* be faster. remains to be tested. */
/* ---------------------------------------------------------- */
int_suckin()
{
register word val = c - '0', tmp;
register byte c_,
*p_table = is_what;
ENTER("int_suckin");
nextdigit( nextdigit( nextdigit( finaldigit()))); /* can you dig it ? */
c = c_;
yylval = (lword) val;
IMESS("Int number is %ld", yylval, 4);
xreturn( T_NUMBER);
}
/* ---------------------------------------------------------- */
/* Suck in a hex value, we assume that, the '$' has been */
/* removed before. */
/* ---------------------------------------------------------- */
hex_suckin()
{
register byte *p = (byte *) yytext,
c_,
*p_table = is_what;
register unsigned val = 0,
i = 4;
ENTER("hex_suckin");
do
if( tis_hex(c_ = uinput()))
{
*p++ = c_;
val <<= 4;
val += (c_ >= 'A') ? c_ - 'A' + 10 : c_ - '0';
}
else
{
c = c_;
if( i == 4)
lsyntax("That hex number looks mighty strange");
yylval = (lword) val;
IMESS("calced hexnumber = %x", (lword) val, 2);
dreturn( T_NUMBER);
}
while( i--);
c = c_;
lsyntax(E_HEXLEN);
}
#include "md_suck.c"
/* ---------------------------------------------------------- */
/* If a lsyntax error occurs, we'll give a nice message and */
/* then go back to the business at hand. Tokenizing. */
/* This is not supposed to find EOF errors, that's for the */
/* I/O routines. */
/* ---------------------------------------------------------- */
void lsyntax( err)
char *err;
{
if( yytext[0])
nserror( err, yytext);
else
nterror( err, (int) c);
longjmp( syn_panic, 1);
}
/* ---------------------------------------------------------- */
/* Mallocer for identifier and other strings */
/* */
/* (Keeping the fingers crossed that this is faster than a) */
/* (simple malloc) */
/* ---------------------------------------------------------- */
typedef struct _str_m
{
lword free;
char huge *space;
struct _str_m huge *before;
} str_m;
static str_m huge *st_h;
char *str_alloc( size)
int size;
{
register str_m huge *p;
register char huge *q;
#if STATISTICS
extern word _a_char, _m_char;
extern lword _z_char, _s_char;
#endif
ENTER("str_alloc");
#if STATISTICS
_a_char++;
_z_char += size;
#endif
#if DEBUG
IMESS("Requested size $%lX", (lword) (size_t) size, 4);
if( st_h)
{
IMESS("st_h == $%lX", (lword) st_h, 4);
IMESS("st_h->free : $%lX", (lword) st_h->free, 4);
IMESS("st_h->space: $%lX", (lword) st_h->space, 4);
}
#endif
if( (p = st_h) && p->free >= (lword) size)
{
letsdoit:
p->free -= (lword) size;
q = p->space;
p->space += (lword) size;
IMESS("sending $%lX as address", (lword) q, 4);
IMESS("st_h->space: $%lX", (lword) st_h->space, 4);
LEAVE();
return( q);
}
#if STATISTICS
_m_char++;
_s_char = sizeof(str_m) + STRMAX;
#endif
MESS("New big block to allocate");
p = (str_m huge *) nmalloc( (long) sizeof(str_m) + STRMAX);
p->free = (lword) STRMAX;
p->space = (char huge *) p + sizeof( str_m);
p->before = st_h;
st_h = p;
if( size > STRMAX)
nierror("An unusally large string forces NASM65 to crash");
goto letsdoit;
}
void yy_txt2val( i)
register int i;
{
register char *src = yytext,
*q;
#if VERSION
register str_m huge *p = st_h;
ENTER("yy_txt2val");
if( p->free >= (lword) i)
{
p->free -= (lword) i;
q = p->space;
p->space += (lword) i;
}
else
q = str_alloc( i);
#else
ENTER("yy_txt2val");
q = str_alloc( i);
#endif
yylval = (lword) q;
while( i > 4)
{
*q++ = *src++;
*q++ = *src++;
*q++ = *src++;
*q++ = *src++;
i -= 4;
}
do
*q++ = *src++;
while( --i);
IMESS("st_h->space: $%lX", (lword) st_h->space, 4);
LEAVE();
}
/* ------------------------------------------------------------
Words to keep in mind:
"Little green man
about four foot
maybe he want
to kick some butt!" (Vai)
------------------------------------------------------------ */