/* ---------------------------------------------------------------------- */ /* Copyright (C) 1991 by Natrlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ #include #include "defines.h" #include "nasm.h" #include "debug.h" #include "labels.h" #include "exprfast.h" 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 char is_where[], err_defined[]; extern int _in_macro, runnable, _in_instr; extern lword l_hash; label *find_label( s) register char *s; { register label huge *p; register lword hash; register int res; ENTER("find_label"); l_hash = hash = calc_hash( s + 1); p = h_macro[ u_macro = is_where[*s]]; while( p && (p->hash < hash || (p->hash == hash && (res = strcmp( p->name, s)) < 0))) p = p->next; l_macro = p; if( ! found( p, hash) || res) /* if not found or at end of table */ { if( *s == '?' || *s == ':') { l_hash = hash = calc_hash( s + 2); p = h_local[ u_local = is_where[ s[1]]]; while( p && (p->hash < hash || (p->hash == hash && (res = strcmp( p->name, s)) < 0))) p = p->next; l_local = p; } else { p = h_global[ u_global = is_where[*s]]; while( p && (p->hash < hash || (p->hash == hash && (res = strcmp( p->name, s)) < 0))) p = p->next; l_global = p; } if( ! found(p, hash) || res) { LEAVE(); return( 0); } } LEAVE(); return( p); } void undefine( s) char *s; { register label huge *p; int is_local = (*s == '?' || *s == ':'); u_local = u_global = -1; /* if we find a macro label this remains -1 */ if( p = find_label( s)) if( ! p->refs) if( u_local < 0 && u_global < 0) { auslinker( h_macro, t_macro, l_macro, u_macro, p); } else if( is_local) { auslinker( h_local, t_local, l_local, u_local, p); } else { auslinker( h_global, t_global, l_global, u_global, p); } else nerror("Label has pending forward references"); else nwarning("Label is unknown to me"); } /* ---------------------------------------------------------- */ /* This routine is called when a forward label */ /* is encountered: */ /* -- Note that the tables have already been searched -- */ /* e.g.: */ /* sta foo */ /* not: foo lda foo */ /* not: foo: = 56 */ /* not: foo *=$600 */ /* ---------------------------------------------------------- */ label *enter_flabel( s, ex) char *s; register expr huge *ex; { register label *p; int is_local = (*s == '?' || *s == ':'); ENTER("enter forward label"); #if DEBUG fprintf( ESTREAM, "with %s as name, and some s_expr @$%lX\n", s, ex); #endif if( is_local) p = llab_alloc(); else p = lab_alloc(); p->refs = 0; p->name = s; p->hash = l_hash; if( runnable) p->type = L_NORMAL | L_REF; else p->type = L_PC | L_NORMAL | L_REF; refer( p, 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); } void page0decl( s) register char *s; { register label huge *p; register expr huge *ex; int is_local = (*s == '?' || *s == ':'); ENTER("page0decl"); if( runnable) { nwarning(".ZEXT probably not meaningful with -r option"); nmessage("But we're gonna do it anyway!"); } if( ! find_label( s)) /* if not found or at end of table */ if( ! is_local) { p = lab_alloc(); p->refs = 0; p->name = s; p->hash = l_hash; p->type = L_ZERO | L_LINKZERO; ex = exp_alloc(); ex->fix = FIX_NOTHING; refer( p, ex); einlinker( h_global, t_global, l_global, u_global, p); } else nserror("Can't use local labels here", s); else nserror( err_defined, s); LEAVE(); } /* ---------------------------------------------------------- */ /* The variety of label dumping routines, really BEG for a */ /* a one-that-does-it-all-routine */ /* ---------------------------------------------------------- */ void dump_open() { register int i, j, k; int f = 0; register label huge *p; ENTER("dump_open"); for( k = 0; k != 2; k++) for( i = 0; i != SEP; i++) if( p = k ? h_macro[ i] : h_global[ i]) do if( dumpable( p)) { if( ! f) { f = 1; j = 0; printf("Linkable symbols:\n"); } if( ++j == 7) { j = 0; putchar( '\n'); } printf( "%c%-8.8s ", (char) (p->type & L_ZERO ? (p->refs ? ',' : '#') : (p->refs ? ' ' : '*')), p->name); } while( p = p->next); puts( "\n"); LEAVE(); } /* ---------------------------------------------------------- */ /* Remove all labels starting with @ from macro table */ /* ---------------------------------------------------------- */ void clean_mats() { register label huge *p; ENTER("dump_open"); for( p = h_macro[ 1]; p; p = p->next) if( p->refs) nerror("'@' macro label still has open refs", p->name); h_macro[ 1] = 0; LEAVE(); }