home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
program
/
compiler
/
nasm20b
/
nasm_src
/
labels.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-19
|
12KB
|
439 lines
/* ---------------------------------------------------------------------- */
/* Copyright (C) 1991 by Natürlich! */
/* This file is copyrighted! */
/* Refer to the documentation for details. */
/* ---------------------------------------------------------------------- */
/* In the faint hope that it will help searching speed, labels will */
/* be alphabetisized (also I do have already code for that...) */
/* ---------------------------------------------------------------------- */
#include <stdio.h>
#include "defines.h"
#include "nasm.h"
#include "debug.h"
#include "labels.h"
#define KEINE_CODE_INNEREIEN
#include "code.h"
#include "fix.h"
#include "exprfast.h"
#include "op.h"
#if ! DORECLAIM
# define expr_tryfree( x)
#endif
extern label huge *h_local[SEP], huge *t_local[SEP], huge *l_local,
huge *h_global[SEP], huge *t_global[SEP], huge *l_global,
huge *h_macro[SEP], huge *t_macro[SEP], huge *l_macro;
extern int u_local, u_global, u_macro;
extern lword l_hash;
extern char err_defined[], warn_0fwd[], warn_equfwd[], buf[];
extern int _in_macro, runnable;
int _in_instr;
extern char *str_alloc();
/* ---------------------------------------------------------- */
/* This routine is called when a label */
/* that is PC-relative is encountered: */
/* foo: lda #56 */
/* bar *= $600 */
/* not: foo = 46 */
/* not: lda foo */
/* ---------------------------------------------------------- */
void enter_pclabel( s)
register char *s;
{
register label huge *p;
int is_local = (*s == '?' || *s == ':');
ENTER("enterlabel");
#if DEBUG
fprintf( ESTREAM, "\t\tWith %s as name @$%4.4X\n", s, __pc);
#endif
u_local = u_global = -1; /* if we find a macro label this remains -1 */
if( ! (p = find_label( s)))
{
if( is_local)
p = llab_alloc();
else
p = lab_alloc();
p->name = s;
p->hash = l_hash;
p->type = __pc < 0x100 ? (L_ZERO | L_PC) : L_PC;
p->val = __pc;
p->refs = 0;
if( is_local)
{
MESS("linking into local");
einlinker( h_local, t_local, l_local, u_local, p);
}
else
if( _in_macro)
{
MESS("linking into macro");
einlinker( h_macro, t_macro, l_macro, u_macro, p);
}
else
{
MESS("linking into global");
einlinker( h_global, t_global, l_global, u_global, p);
}
}
else
{
IMESS("p->refs = $%8.8X", (lword) p->refs, 4);
if( p->refs)
{
if( __pc < 0x100)
nswarning( warn_0fwd, p->name);
p->val = __pc;
p->type |= L_PC;
if( ! _in_macro && u_local < 0 && u_global < 0) /* was assumed */
{ /* macro, but is */
auslinker( h_macro, t_macro, l_macro, u_macro, p); /* global */
(void) find_label( s);
if( is_local)
{
MESS("linking into local");
einlinker( h_local, t_local, l_local, u_local, p);
}
else
{
MESS("linking into global");
einlinker( h_global, t_global, l_global, u_global, p);
}
}
if( p->type & L_EQU)
nswarning( warn_equfwd, p->name);
entrefer( p);
}
else
if( _in_macro)
{
p->val = __pc;
p->type |= L_PC;
}
else
nserror( err_defined, s);
}
LEAVE();
}
/* ---------------------------------------------------------- */
/* This routine is called when a equ label */
/* or .= label is encountered: */
/* e.g.: */
/* bar .= $600 */
/* foo = 462 */
/* bar == 67 */
/* not: lda foo */
/* not: foo: lda #56 */
/* not: foo *=$600 */
/* ---------------------------------------------------------- */
static expr edummy =
{
0,
0, 0, 0,
0, FIX_NOTHING,
0,
0,
0
};
label *enter_elabel( s, ex, type)
char *s;
register expr huge *ex;
register int type;
{
register label huge *p;
int is_local = (*s == '?' || *s == ':');
ENTER("enterlabel/expression");
#if DEBUG
fprintf( ESTREAM, "Name=%s type=$%4.4X + some s_expr @$%lX\n", s, type, ex);
#endif
if( ! (p = find_label( s))) /* if not found or at end of table */
{
if( is_local)
p = llab_alloc();
else
p = lab_alloc();
p->refs = 0;
p->name = s;
p->hash = l_hash;
if( unvalued( ex)) /* top is not value */
{
jump1984:
if( type == L_ZERO && e_pcrel( ex))
nerror("You can't assign a fwd ref to a zeropage label");
#if LOCALDEBUG
fprintf( ESTREAM, "label %s is yet undefined\n", s);
#endif
p->type = type | (e_pcrel( ex) ? L_PC : 0);
fix_lup( ex, p);
(void) refer( p, &edummy); /* casting for prettyness */
}
else
{
p->val = ex->val;
if( type)
{
if( type & L_ZERO && p->val >= 0x100)
nswarning( "zeropage label >= $100", s);
}
else
if( p->val < 0x100 || ex->op & O_ZEROP)
type |= L_ZERO;
if( e_pcrel( ex))
type |= L_PC;
if( (type & (L_PC | L_ZERO)) == (L_PC | L_ZERO))
nserror("Conflict between PC relativism and zeropageism", s);
p->type = type;
expr_tryfree( ex);
}
if( is_local)
{
MESS("linking into local");
einlinker( h_local, t_local, l_local, u_local, p);
}
else
if( _in_macro)
{
MESS("linking into macro");
einlinker( h_macro, t_macro, l_macro, u_macro, p);
}
else
{
MESS("linking into global");
einlinker( h_global, t_global, l_global, u_global, p);
}
LEAVE();
return( p);
}
else
if( type & L_EQU)
{
if( ! (p->type & L_EQU))
nswarning( ".= assignment for a normal label", s);
if( valued( ex))
{
p->val = ex->val;
if( e_pcrel( ex))
p->type |= L_PC;
if( p->refs)
{
if( p->type & L_EQU)
nswarning( warn_equfwd, p->name);
entrefer( p);
}
expr_tryfree( ex);
p->type |= L_EQU;
}
else
if( p->refs)
{
ex->fix = FIX_NOTHING;
nserror( "Label still has open references", p->name);
}
else
goto jump1984;
}
else
if( p->refs)
if( valued( ex))
{
if( ex->val < 0x100)
nswarning( warn_0fwd, s);
p->val = ex->val;
if( (e_pcrel( ex) ? L_PC : 0) ^ (p->type & L_PC))
nserror("Label was assumed to be pc relative", s);
if( p->type & L_EQU)
nswarning( warn_equfwd, s);
entrefer( p);
expr_tryfree( ex);
}
else
goto jump1984;
else
nserror( err_defined, s);
LEAVE();
return( p);
}
void def_label( name, val) /* Pyromania */
char *name;
word val;
{
#if ! VERSION
name = strcpy( str_alloc( strlen( name) + 1), name);
#endif
(void) enter_elabel( name, ival_pl( val), L_SPECIAL);
}
is_ref(s)
char *s;
{
label huge *q;
if( ! (q = find_label( s)))
return( 0);
return( q->type & L_REF);
}
is_def(s)
char *s;
{
label huge *q;
return( (q = find_label( s)) && ! q->refs);
}
void openrefs( table, message)
label huge **table;
char *message;
{
register int i, j, f = 0;
register label huge *p;
ENTER("openrefs");
for( i = 0; i != SEP; i++)
{
p = table[ i];
while( p)
{
if( p->refs)
{
if( ! f)
{
f = 1;
j = 0;
sprintf( buf, "Some %s labels remain undefined", message);
nerror( buf);
putc( '\t', ESTREAM);
}
if( j++ == 4)
{
j = 0;
putc( '\n', ESTREAM);
putc( '\t', ESTREAM);
}
fputs( p->name, ESTREAM);
putc( '\t', ESTREAM);
}
p = p->next;
}
}
if( f)
putc( '\n', ESTREAM);
LEAVE();
}
void err_undefs()
{
register int i, j, k,
f = 0;
register label huge *p;
ENTER("err_undefs");
if( runnable)
{
openrefs( h_global, "global");
openrefs( h_macro, "macro");
}
else
for( k = 0; k != 2; k++)
for( i = 0; i != SEP;)
if( p = k ? h_macro[ i++] : h_global[i++])
do
if( ! (! p->refs || q_pcrel( p) ||
(p->type & (L_SPECIAL | L_LINKZERO)) ))
{
if( ! f)
{
f = 1;
j = 0;
nerror( "Some global non PC-relative labels remain undefined");
putc( '\t', ESTREAM);
}
if( j++ == 4)
{
j = 0;
putc( '\n', ESTREAM);
putc( '\t', ESTREAM);
}
fputs( p->name, ESTREAM);
putc( '\t', ESTREAM);
}
while( p = p->next);
if( f)
putc( '\n', ESTREAM);
LEAVE();
}
void do_local()
{
register int i;
ENTER("do_local");
#if LOCALDEBUG
show_all();
#endif
openrefs( h_local, "local");
llab_free();
for( i = 0; i != SEP; i++)
h_local[ i] = t_local[ i] = 0;
LEAVE();
}
#if LOCALDEBUG || DEBUG
#define oref p->refs ? '*' : ' '
static char format[] =
"%c\"%8.8s\" type=$%2.2X value=$%4.4X hash=$%8.8lX\n";
void show_all()
{
label huge *p;
int i;
fprintf( ESTREAM, "Dumping global table:\n");
for( i = 0; i != SEP; i++)
if( p = h_global[ i])
{
do
fprintf( ESTREAM, format, oref, p->name,
p->type, p->val, p->hash);
while( p = p->next);
putc( '\n', ESTREAM);
}
fprintf( ESTREAM, "\n\nDumping local table:\n");
for( i = 0; i != SEP; i++)
if( p = h_local[ i] )
{
do
fprintf( ESTREAM, format, oref, p->name,
p->type, p->val, p->hash);
while( p = p->next);
putc( '\n', ESTREAM);
}
fprintf( ESTREAM, "\n\nDumping macro label table:\n");
for( i = 0; i != SEP; i++)
if( p = h_macro[ i])
{
do
fprintf( ESTREAM, format, oref, p->name,
p->type, p->val, p->hash);
while( p = p->next);
putc( '\n', ESTREAM);
}
}
#endif