home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
compiler
/
nasm20b
/
nasm_src
/
macro.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-19
|
14KB
|
493 lines
/* ---------------------------------------------------------------------- */
/* Copyright (C) 1991 by Natürlich! */
/* This file is copyrighted! */
/* Refer to the documentation for details. */
/* ---------------------------------------------------------------------- */
#define DEBUG 0
#define LOCALDEBUG DEBUG
#include <stdio.h>
#include "defines.h"
#include "nasm.h"
#include "y_tab.h"
#include "labels.h"
#include "debug.h"
#include <setjmp.h>
#include "buffer.h"
#if VERSION
#include "inputfst.h"
#include "exprfast.h"
#endif
#include OSBIND
#include NMALLOC_H
#include "code.h"
#define MB_SIZE (sizeof( buffer) + sizeof( macro))
#define NIL ((char *) 0)
#if __NSTDC__ && TURBO
static void mac_done( buffer huge *),
lxsyntax( char *);
static int mac_get( void),
*more_space( void);
extern int (*gettoken)(void);
#else
static void mac_done(),
lxsyntax();
static int mac_get( void);
extern int (*gettoken)();
#endif
static macro huge *header[SEP], huge *tailer[SEP], huge *rover;
extern char is_where[], ovf_loss[];
int freshflag = 1,
_call_macro;
extern char c;
extern jmp_buf syn_panic;
#if DEBUG
#if LOCALDEBUG
int syndebug;
#else
extern int syndebug;
#endif
#endif
extern int _in_if, show_expansion, show_mload;
extern lword yylval, l_hash;
extern buffer huge *bp, huge *hp;
int used, _in_macro;
/* ---------------------------------------------------------- */
/* This is a rather wasteful, but nevertheless _fast_ way of */
/* Sucking in macros. Only once, when the boundary has been */
/* crossed, there is a need to copy over stuff. */
/* ---------------------------------------------------------- */
typedef struct mac_m_
{
int huge *s;
struct mac_m_ huge *before;
} mac_m;
static mac_m huge *c_h;
word tok_remain;
static int huge *start; /* points to the beginning of macro */
static int *more_space()
{
register mac_m huge *p;
register lword rem;
#if STATISTICS
extern word _m_macro;
extern lword _s_macro;
_m_macro++;
_s_macro = MACSPACE + sizeof( mac_m);
#endif
ENTER("more_space");
p = (mac_m huge *) nmalloc( MACSPACE + sizeof( mac_m));
p->s = (int *) ((char huge *) p + sizeof( mac_m));
if( ! (p->before = (mac_m huge *) c_h)) /* First time ?? */
{
c_h = p;
tok_remain = MACTOKMAX;
LEAVE();
return( start = p->s);
}
#if ! VERSION
if( (size_t) ((char huge *) c_h->s + MACSPACE - (char huge *) start) !=
(lword) ((char huge *) c_h->s + MACSPACE - (char huge *) start))
nierror("Conversion did indeed lose some bytes in MACRO.C:more_space");
#endif
if( start == c_h->s)
nferror("ONE macro can't possibly be THAT long!");
bcopy( start, p->s,
rem = (lword) ((char huge *) c_h->s + MACSPACE - (char huge *) start));
tok_remain = (word) ((MACSPACE - rem) / (sizeof( int) + sizeof( lword)));
c_h = p;
LEAVE();
return( (int *) ((char huge *) (start = p->s) + rem));
}
/* ---------------------------------------------------------- */
/* Functions to suck in a macro and store it. */
/* HIDE your register variables, if a LONGJMP is about to */
/* happen. Therefore no and remain are static outside. */
/* ---------------------------------------------------------- */
static unsigned no = 0; /* bc/o LONGJMPs */
void load_macro( name)
char *name;
{
register int tok;
register int huge *s = start;
ENTER("load_macro");
no = 0;
freshflag = 1; /* new yylex caller */
if( find_macro( name))
{
nerror("This old assembler can't handle macro redefinitions, so you better choose another name");
while( (tok = yylex()) && tok != T_ENDM);
if( ! tok)
nferror("Reached end of file while skipping to .ENDM");
return;
}
if( (tok = yylex()) != T_EOL)
{
nwarning("Garbage after .macro <name> definition!");
while( (tok = yylex()) != T_EOL);
}
inc_line();
if( show_mload)
printf("Loading macro definition \"%s\"\n", name);
for(;;)
{
switch( tok = yylex())
{
case 0 :
MESS("Case 0");
nferror("Reached end of file before an .ENDM");
case T_MACRO :
MESS("Case T_MACRO");
nerror("U can't define a macro in a macro, ignoring until .ENDM");
while( (tok = yylex()) && tok != T_ENDM);
if( ! tok)
nferror("...unfortunately that doesn't exist");
break;
case T_ENDM :
MESS("Case T_ENDM");
{
register buffer huge *p;
register macro huge *q;
p = (buffer huge *) nmalloc( (long) MB_SIZE);
q = (macro huge *) ((char huge *) p + sizeof( buffer));
p->buflist = p->p = (byte *) start;
p->name = name;
p->remain = p->oremain = no;
p->type = BUF_ALLOC | BUF_TOKEN | BUF_MACRO;
p->multi.fill= (void (*)(buffer *)) dummy; /* **-PORT #1-**/
p->done = mac_done;
p->get = (int (*)()) mac_get; /* **-PORT #1-**/
MESS("Filling q");
q->name = p->name = name;
q->hash = l_hash;
q->buf = p;
q->inuse = p->line = 0;
MESS("Linking in...");
einlinker( header, tailer, rover, used, q);
start = (int huge *) s;
freshflag = 1; /* a new yylex caller will appear */
LEAVE();
return;
}
case T_INCLUDE :
MESS("T_INCLUDE");
if( ! (tok = yylex()))
nferror("Unexpected EOF in the middle of a macro definition");
if( tok != T_FILE)
nerror("Valid file specifier expected after .INCLUDE");
include( (char *) yylval, ".s65");
if( (tok = yylex()) != T_EOL)
{
nwarning("Garbage after .include <file> definition!");
while( (tok = yylex()) != T_EOL);
}
break;
default :
while( ! tok_remain--)
s = more_space();
if( (*s++ = tok) == T_EOL)
bp->line++;
*(lword huge *)s = yylval;
s += sizeof( lword) / sizeof( int);
no++;
}
}
}
#if DEBUG
#define fdreturn( val) \
{ \
int foo = (val); \
\
prtname( foo); \
LEAVE(); \
return( foo); \
}
#else
#define fdreturn return
#endif
static int mac_get()
{
static int tok;
register buffer huge *P = bp;
ENTER("mac_get");
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 */
{
int foo;
#if DEBUG
SETBACK(syndebug);
#endif
MESS("\007\t\tsyntax panic occurred");
while( P->remain--) /* Something left ? */
{
foo = *(int huge *)P->p;
P->p += sizeof( int) + sizeof( lword);
if( foo)
break;
}
}
}
if( P->remain--) /* Something left ? */
{
#if ! PHILOSOPHICAL_PROBLEM
tok = *((int huge *) P->p)++;
yylval = *((lword huge *) P->p)++;
#else
tok = *(int huge *) P->p;
P->p = (void huge *) ((int *) P->p + 1);
yylval = *(lword huge *) P->p;
P->p = (void huge *) ((lword huge *) P->p + 1);
#endif
if( tok < HIGHEST || _in_if) /* not a parameter ?? */
fdreturn( tok); /* then return that */
{
register lexpr huge *l;
if( tok >= T_MLPARA)
{
register label huge *q;
MESS("Using the label indirection");
if( ! (q = find_label( (char huge *) yylval)) || q->refs)
lxsyntax("Foward references of macro indices. Tsk Tsk");
yylval = (lword) q->val;
}
if( yylval > P->parms.list->expr->val)
lxsyntax("Missing macro parameter error");
l = lex_get( P->parms.list, (word) yylval);
if( _call_macro)
{
yylval = (lword) l;
return( T_PARA);
}
if( (tok & 1) == (T_MSPARA & 1)) /* OPTIMIZE */
{
yylval = (lword) l->string;
IMESS("Supplying $%lx as string value", yylval, 4);
fdreturn( T_STRING);
}
l = (lexpr huge *) l->expr;
yylval = (lword) copyexpr( (expr *) l);
/* ((expr *)yylval)->fix = 0; */ /* That true ? */
IMESS("Supplying $%lx for an expression", yylval, 4);
fdreturn( T_EXPR);
}
}
#if DEBUG
dump_buffer( bp);
#endif
MESS("Killing buffer");
kill_buffer( hp); /* Install new buffer */
#if DEBUG
dump_buffer( bp);
#endif
fdreturn( T_EOL);
}
macro *find_macro( s)
register char *s;
{
register macro huge *p;
register lword hash;
register int res;
ENTER("find_macro");
IMESS("Looking for \"%s\"", (lword) s, 4);
l_hash = hash = calc_hash( s + 1);
p = header[ used = is_where[*s]];
while( p && (p->hash < hash ||
(p->hash == hash && (res = strcmp( p->name, s)) < 0)))
p = p->next;
rover = p;
if( ! found( p, hash) || res) /* if not found or at end of table */
{
LEAVE();
return( 0);
}
LEAVE();
return( p);
}
void do_macro( name, lex)
char *name;
lexpr huge *lex;
{
register macro huge *q;
register buffer huge *p;
int flag = __p - __program >= MAXMODULE;
ENTER("do_macro");
IMESS("Executing macro \"%s\"", (lword) name, 4);
if( q = find_macro( name))
{
lex->string = make_string( name); /* ARGH! make that better */
if( ! q->buf->oremain)
{
LEAVE();
return;
}
if( q->inuse)
{
MESS("q seems to be in use");
if( q->inuse == 1)
nwarning("Macro recursion (allowed but maybe unwanted)");
if( flag)
nferror("Probably a macro recursion caused the code buffer\
overflow");
p = (buffer huge *) nmalloc( (long) sizeof( buffer));
bcopy((char *) q->buf, (char *) p, (long) sizeof( buffer));
p->buflist = p->p = q->buf->buflist;
p->remain = p->oremain;
p->name = q->name;
p->type = BUF_MACRO | BUF_TOKEN | BUF_FREE | BUF_ALLOC;
}
else
p = q->buf;
if( flag)
nferror( ovf_loss);
q->inuse++;
IMESS("p->remain = %ld", p->remain, 4);
if( (p->before = bp))
{
bp->next = p;
/* if( ! (bp->type & BUF_TOKEN))
bp->_aux2 = c;
*/
}
p->multi.dad = q;
p->parms.list = lex;
p->line = 0;
p->next = 0;
p->get = (int (*)()) (gettoken = mac_get); /* **-PORT #1-**/
p->done = mac_done;
bp = p;
MESS("MACRO has been linked into buffer list");
#if DEBUG
dump_buffer( bp);
#endif
freshflag = 1;
_in_macro++;
if( show_expansion)
{
int i = 1;
tabout();
printf( "line %4.4d, expanding macro: \"%s\"\n",
p->before->line, name);
tab();
printf( "\t#parameters : %d\n", lex->expr->val);
while( lex = lex->next)
{
tab();
printf("\t%%%d : %c $%04X %%$%d : \"%s\"\n",
i,
valued( lex->expr) ? ' ' : 'F',
lex->expr->val,
i,
lex->string + 2);
i++;
}
}
}
else
nserror( "Macro is undefined", name);
LEAVE();
}
void call_macro( s)
char *s;
{
nwarning("unimplemented directive");
/*
if( bp->type & BUF_MACRO)
do_macro( s, slex_ch( lex_pl( NIL, bp->parms.list->expr),
bp->parms.list->next));
else
nerror("You can use .CALL only in macro definitions");
*/
}
void rept_macro( ex, name, lex)
expr huge *ex;
char *name;
lexpr huge *lex;
{
if( unvalued( ex))
nerror("No foward references for repeat factor allowed");
else
{
word i;
for( i = ex->val; i; i--)
do_macro( name, lex);
}
}
static void mac_done( p)
register buffer huge *p;
{
ENTER("mac_done");
p->line = 0;
p->p = p->buflist;
p->remain = p->oremain;
p->multi.dad->inuse--; /* incomplete */
_in_macro--; /* (later: ;) */
if( show_expansion)
{
tabin();
printf( "Done with macro: \"%s\"\n", p->name);
}
LEAVE();
}
static void lxsyntax( err)
char *err;
{
nerror( err);
longjmp( syn_panic, 1);
}
/* ; Huh? What? Why?? Tell me more... I don't see the problem */