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