#include <stdlib.h>
#include <string.h>
#include "as.h"
#include "hash.h"
#include "obstack.h"
#include "struc-symbol.h"
#include "symbols.h"
#include "frags.h"
#include "expr.h"
#include "sections.h"
#include "read.h"
#include "xmalloc.h"
#include "messages.h"
#include "fixes.h"
#include "input-scrub.h"
struct hash_control *sy_hash = NULL;
struct obstack notes = { 0 };
symbolS *symbol_rootP = NULL;
symbolS *symbol_lastP = NULL;
symbolS abs_symbol = { {{0}} };
typedef short unsigned int local_label_countT;
static local_label_countT local_label_counter[10];
static
char symbol_name_build[12];
static void make_stab_for_symbol(
symbolS *symbolP);
void
symbol_begin(
void)
{
symbol_lastP = NULL;
symbol_rootP = NULL;
sy_hash = hash_new();
memset((char *)(&abs_symbol), '\0', sizeof(abs_symbol));
abs_symbol.sy_type = N_ABS;
memset((char *)(local_label_counter), '\0', sizeof(local_label_counter) );
}
char *
local_label_name(
int n,
int augend)
{
register char * p;
register char * q;
char symbol_name_temporary[10];
know( n >= 0 );
know( augend == 0 || augend == 1 );
p = symbol_name_build;
* p ++ = 'L';
* p ++ = n + '0';
* p ++ = 1;
n = local_label_counter [ n ] + augend;
q = symbol_name_temporary;
for (*q++=0; n; q++)
{
know(n>0);
*q = n % 10 + '0';
n /= 10;
}
while (( * p ++ = * -- q ))
{
}
return (symbol_name_build);
}
void
local_colon(
int n)
{
local_label_counter [n] ++;
colon (local_label_name (n, 0));
}
symbolS *
symbol_new(
char *name,
unsigned char type,
char other,
short desc,
valueT value,
struct frag *frag)
{
register symbolS * symbolP;
register char * preserved_copy_of_name;
register unsigned int name_length;
char * p;
name_length = strlen(name) + 1;
obstack_grow(¬es,name,name_length);
p=obstack_finish(¬es);
preserved_copy_of_name = p;
p=obstack_alloc(¬es,sizeof(struct symbol));
symbolP = (symbolS *) p;
symbolP -> sy_name = preserved_copy_of_name;
symbolP -> sy_type = type;
symbolP -> sy_other = other;
symbolP -> sy_desc = desc;
symbolP -> sy_value = value;
symbolP -> sy_frag = frag;
symbolP -> sy_next = NULL;
symbolP -> sy_forward = NULL;
symbolP -> expression = NULL;
#ifdef SUSPECT
symbolP -> sy_name_offset = ~ 0;
symbolP -> sy_number = ~ 0;
#endif
if (symbol_lastP)
{
symbol_lastP -> sy_next = symbolP;
}
else
{
symbol_rootP = symbolP;
}
symbol_lastP = symbolP;
return (symbolP);
}
static volatile unsigned int temp;
void
colon(
char *sym_name)
{
register struct symbol * symbolP;
if (frchain_now == NULL)
{
know(flagseen['n']);
as_fatal("with -n a section directive must be seen before assembly "
"can begin");
}
if ((symbolP = symbol_table_lookup( sym_name )))
{
if ((symbolP -> sy_type & N_TYPE) == N_UNDF)
{
temp = symbolP->sy_desc;
if( symbolP -> sy_other == 0
&& (temp & (~REFERENCE_TYPE)) == 0
&& symbolP -> sy_value == 0)
{
symbolP -> sy_frag = frag_now;
symbolP -> sy_value = obstack_next_free(& frags) - frag_now -> fr_literal;
know( N_UNDF == 0 );
symbolP -> sy_type |= N_SECT;
symbolP -> sy_other = frchain_now->frch_nsect;
symbolP -> sy_desc &= ~REFERENCE_TYPE;
#ifdef NeXT_MOD
if(flagseen['g'])
make_stab_for_symbol(symbolP);
#endif
}
else
{
as_fatal( "Symbol \"%s\" is already defined as \"%s\"/%d.%d.%ld.",
sym_name,
seg_name [(int) N_TYPE_seg [symbolP -> sy_type & N_TYPE]],
symbolP -> sy_other, symbolP -> sy_desc,
symbolP -> sy_value);
}
}
else
{
as_fatal("Symbol %s already defined.",sym_name);
}
}
else
{
symbolP = symbol_new (sym_name,
N_SECT,
frchain_now->frch_nsect,
0,
(valueT)(obstack_next_free(&frags)-frag_now->fr_literal),
frag_now);
symbol_table_insert (symbolP);
#ifdef NeXT_MOD
if(flagseen['g'])
make_stab_for_symbol(symbolP);
#endif
}
}
void
symbol_table_insert(
struct symbol *symbolP)
{
register char * error_string;
know( symbolP );
know( symbolP -> sy_name );
if ( * (error_string = hash_jam (sy_hash, symbolP -> sy_name, (char *)symbolP)))
{
as_fatal( "Inserting \"%s\" into symbol table failed: %s",
symbolP -> sy_name, error_string);
}
}
symbolS *
symbol_find_or_make(
char *name)
{
register symbolS * symbolP;
symbolP = symbol_table_lookup (name);
if (symbolP == NULL)
{
symbolP = symbol_new (name, N_UNDF, 0, 0, 0, & zero_address_frag);
symbol_table_insert (symbolP);
}
return (symbolP);
}
symbolS *
symbol_find(
char *name)
{
return ( (symbolS *) hash_find( sy_hash, name ));
}
symbolS *
symbol_table_lookup(
char *name)
{
register symbolS * symbolP;
symbolP = (symbolS *) hash_find( sy_hash, name );
if(symbolP != NULL)
symbolP->sy_desc &= ~REFERENCE_FLAG_UNDEFINED_LAZY;
return(symbolP);
}
#ifdef NeXT_MOD
static
void
make_stab_for_symbol(
symbolS *symbolP)
{
symbolS *stab;
int stabnamelen;
char *stabname;
if(symbolP->sy_name[0] == 'L')
return;
if((symbolP->sy_type & N_TYPE) != N_SECT)
return;
if(symbolP->sy_other != text_nsect)
return;
stabnamelen = strlen(symbolP->sy_name) + sizeof(":f3");
stabname = xmalloc(stabnamelen);
strcpy(stabname, symbolP->sy_name);
if(symbolP->sy_type & N_EXT)
strcat(stabname, ":F3");
else
strcat(stabname, ":f3");
stab = symbol_new(
stabname,
36,
text_nsect,
logical_input_line,
symbolP->sy_value,
symbolP->sy_frag);
free(stabname);
}
#endif
isymbolS *
indirect_symbol_new(
char *name,
struct frag *frag,
unsigned long offset)
{
isymbolS *isymbolP;
char *preserved_copy_of_name;
unsigned long name_length;
char *p;
struct frag *fr_next;
symbolS *symbolP;
#ifdef CHECK_INDIRECTS
unsigned long stride, fr_fix;
#endif
if(frchain_now->frch_isym_last != NULL &&
frchain_now->frch_isym_last->isy_frag->fr_fix == 0){
if(frchain_now->frch_isym_last->isy_frag->fr_next != NULL){
fr_next = frchain_now->frch_isym_last->isy_frag->fr_next;
while(fr_next->fr_fix == 0 &&
fr_next->fr_type == rs_fill &&
fr_next->fr_next != NULL)
fr_next = fr_next->fr_next;
frchain_now->frch_isym_last->isy_frag = fr_next;
}
}
name_length = strlen(name) + 1;
obstack_grow(¬es, name, name_length);
p = obstack_finish(¬es);
preserved_copy_of_name = p;
p = obstack_alloc(¬es, sizeof(struct indirect_symbol));
isymbolP = (isymbolS *)p;
isymbolP->isy_name = preserved_copy_of_name;
isymbolP->isy_offset = offset;
isymbolP->isy_frag = frag;
isymbolP->isy_next = NULL;
isymbolP->isy_symbol = NULL;
if(frchain_now->frch_isym_root == NULL){
#ifdef CHECK_INDIRECTS
if(offset != 0)
as_warn("missing or bad indirect symbol for section (%s,%s)",
frchain_now->frch_section.segname,
frchain_now->frch_section.sectname);
#endif
frchain_now->frch_isym_root = isymbolP;
frchain_now->frch_isym_last = isymbolP;
}
else{
#ifdef CHECK_INDIRECTS
if((frchain_now->frch_section.flags & SECTION_TYPE) ==
S_SYMBOL_STUBS)
stride = frchain_now->frch_section.reserved2;
else
stride = sizeof(unsigned long);
if(frag == frchain_now->frch_isym_last->isy_frag){
if(offset - frchain_now->frch_isym_last->isy_offset != stride)
as_warn("missing or bad indirect symbol for section "
"(%s,%s)", frchain_now->frch_section.segname,
frchain_now->frch_section.sectname);
}
else{
if(frchain_now->frch_isym_last->isy_frag->fr_fix < stride){
fr_fix = 0;
fr_next = frchain_now->frch_isym_last->isy_frag;
while(fr_fix + fr_next->fr_fix < stride &&
fr_next->fr_type == rs_fill &&
fr_next->fr_next != NULL){
fr_fix += fr_next->fr_fix;
fr_next = fr_next->fr_next;
}
if(frag != fr_next->fr_next ||
fr_fix + fr_next->fr_fix != stride ||
offset != 0)
as_warn("missing or bad indirect symbol for section "
"(%s,%s)", frchain_now->frch_section.segname,
frchain_now->frch_section.sectname);
}
else{
fr_next = frchain_now->frch_isym_last->isy_frag->fr_next;
while(fr_next->fr_fix == 0 &&
fr_next->fr_type == rs_fill &&
fr_next->fr_next != NULL)
fr_next = fr_next->fr_next;
if(frag != fr_next || offset != 0)
as_warn("missing or bad indirect symbol for section "
"(%s,%s)", frchain_now->frch_section.segname,
frchain_now->frch_section.sectname);
}
}
#endif
frchain_now->frch_isym_last->isy_next = isymbolP;
frchain_now->frch_isym_last = isymbolP;
}
if((frchain_now->frch_section.flags & SECTION_TYPE) ==
S_NON_LAZY_SYMBOL_POINTERS){
symbolP = (symbolS *)hash_find(sy_hash, name);
if(symbolP != NULL)
symbolP->sy_desc &= ~REFERENCE_FLAG_UNDEFINED_LAZY;
}
return(isymbolP);
}