home *** CD-ROM | disk | FTP | other *** search
- /* ---------------------------------------------------------------------- */
- /* 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 */
-
-