/* ---------------------------------------------------------------------- */
/*                   Copyright (C) 1991 by Natrlich!                     */
/*                      This file is copyrighted!                         */
/*                Refer to the documentation for details.                 */
/* ---------------------------------------------------------------------- */
#define LINKER 1
#include <stdio.h>
#include "defines.h"
#include "nasm.h"
#include "debug.h"
#include "labels.h"

extern label huge *h_global[SEP], huge *t_global[SEP], huge *l_global;
extern int        u_global;
extern lword      l_hash;

extern char    err_defined[], warn_0fwd[], warn_equfwd[], is_where[];
extern char    *str_alloc();

/* ---------------------------------------------------------- */
/*                  Find a label by it's name                 */
/* ---------------------------------------------------------- */
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_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);
}

/* ---------------------------------------------------------- */
/*         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_llabel( s, val, type)
char              *s;
register word     val;
word              type;
{
   register label huge  *p;

   ENTER("enter forward label");
#if DEBUG
   fprintf( ESTREAM, "with %s as name, and some value $%X\n", s, val);
#endif
   (p = lab_alloc())->name = s;
   p->refs = 0;
   p->hash = l_hash;
   p->val  = val;
   p->type = type;
   einlinker( h_global, t_global, l_global, u_global, p);
   LEAVE();
   return( p);
}


void  define( name, value)
char  *name;
word  value;
{
#if ! VERSION
   name = strcpy( str_alloc( strlen( name) + 1), name);
#endif   
   if( ! find_label( name))
      (void) enter_llabel( name, value, L_NORMAL);
   else
      nserror("Label has been already defined", name);
}


lerr_undefs( flag)
{
   register label huge  *p;
   register int         i, j, f;

   ENTER("lerr_undefs");
   for( i = f = 0; i < SEP;)
      if( p = h_global[i++])
         do
            if( p->refs)
            {
               if( ! f)
               {
                  if( flag)
                     return( 1);
                  f = 1;
                  j = 0;
                  putc( '\n', ESTREAM);
                  nerror( "Some labels remain undefined");
               }
               if( ++j == 8)
               {
                  j = 0;
                  putc( '\n', ESTREAM);
               }
               fprintf( ESTREAM, "%-8.8s ", p->name);
            }
         while( p = p->next);
   if( f && ! flag && j)
      putc( '\n', ESTREAM);
   LEAVE();
   return( 0);
}

