#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: gsp_sym.c,v 1.10 2025/11/24 08:04:28 nia Exp $");
#endif
#include <stdio.h>
#include <string.h>
#include <util.h>
#include "gsp_ass.h"
#define NHASH 64
symbol symbol_hash[NHASH];
void define_sym(char *, unsigned, unsigned, int);
symbol
lookup(char *id, bool makeit)
{
symbol ptr, p, *pp;
int h;
char *ip;
h = 0;
for( ip = id; *ip != 0; )
h = (h << 1) + *ip++;
h &= NHASH-1;
for( pp = &symbol_hash[h]; (p = *pp) != NULL; pp = &p->next )
if( (h = strcmp(id, p->name)) == 0 )
return p;
else if( h < 0 )
break;
if( !makeit )
return NULL;
ptr = emalloc(sizeof(struct symbol) + strlen(id));
ptr->ndefn = 0;
ptr->flags = 0;
ptr->value = 0;
ptr->lineno = NOT_YET;
strcpy(ptr->name, id);
*pp = ptr;
ptr->next = p;
ptr->nlab = NULL;
return ptr;
}
void
define_sym(char *id, unsigned val, unsigned lno, int flags)
{
symbol ptr;
ptr = lookup(id, TRUE);
if( (ptr->flags & SET_LABEL) == 0 ){
if( ptr->ndefn >= 2 ){
perr("Multiply defined label %s", id);
if( (flags & SET_LABEL) != 0 )
return;
} else if( pass2 && ptr->value != val )
perr("Phase error on label %s (%#x -> %#x)",
id, ptr->value, val);
}
ptr->flags = flags;
ptr->ndefn += 1;
ptr->value = val;
ptr->lineno = lno;
}
void
set_label(char *id)
{
if( id != NULL ){
define_sym(id, pc, lineno, DEFINED);
if( pass2 )
do_list_pc();
}
}
void
do_asg(char *name, expr value, int flags)
{
int32_t val;
unsigned lno;
if( eval_expr(value, &val, &lno) )
flags |= DEFINED;
if( lno < lineno )
lno = lineno;
define_sym(name, val, lno, flags);
if( pass2 )
do_show_val(val);
}
void
set_numeric_label(int lnum)
{
symbol bp, fp;
struct numlab *nl;
char id[32];
sprintf(id, "%dB", lnum);
bp = lookup(id, TRUE);
bp->flags = NUMERIC_LABEL | DEFINED;
bp->value = pc;
bp->lineno = lineno;
id[strlen(id) - 1] = 'F';
fp = lookup(id, TRUE);
if( !pass2 ){
new(nl);
nl->value = pc;
nl->lineno = lineno;
nl->next = NULL;
if( bp->nlab == NULL )
fp->nlab = nl;
else
bp->nlab->next = nl;
bp->nlab = nl;
fp->flags = NUMERIC_LABEL;
} else {
if( pc != fp->value )
perr("Phase error on numeric label %d (%#x -> %#x)",
lnum, fp->value, pc);
nl = fp->nlab;
nl = nl->next;
if( nl == NULL ){
fp->flags &= ~DEFINED;
fp->lineno = NOT_YET;
fp->value = 0;
} else {
fp->lineno = nl->lineno;
fp->value = nl->value;
fp->nlab = nl;
}
do_list_pc();
}
}
void
reset_numeric_labels()
{
symbol p;
struct numlab *nl;
int h;
for( h = 0; h < NHASH; ++h ) {
for( p = symbol_hash[h]; p != NULL; p = p->next ) {
if( (p->flags & NUMERIC_LABEL) != 0 ) {
if( (p->flags & DEFINED) != 0 ) {
p->flags &= ~DEFINED;
} else {
p->flags |= DEFINED;
nl = p->nlab;
p->value = nl->value;
p->lineno = nl->lineno;
}
}
}
}
}