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

label huge  *h_macro[SEP],  huge *t_macro[SEP],  huge *l_macro,
      huge  *h_local[SEP],  huge *t_local[SEP],  huge *l_local,
      huge  *h_global[SEP], huge *t_global[SEP], huge *l_global;
int         u_local, u_macro, u_global;
lword       l_hash;

char  err_defined[] = "label already defined",
      warn_0fwd[]   = "assumed 2-byte fwd address was i.e. zeropage",
      warn_equfwd[] = ".= label was fwd referenced";

#undef  X
#if LINKER
#define X 0
#else
#define X 30
#endif

/* This is a conversion table to extract a more or less significant */
/* 5 bit hash value out of a 7 bit ascii char. this will be stored  *
/* into ->hash as .aaaaabbbbbccccc .dddddeeeefffff                  */

char  hash_tab[] =
{
    0, 1, 2, 3,   4, 5, 6, 7,   8, 9,10,11,  12,13,14,15, /* $ 0 */
   16,17,18,19,  20,21,22,23,  24,25,26,27,  28,29,30,31, /* $10 */
   27,28,29,30,  31,17,22,10,  23,26,31,30,  29,28,27,26, /* $20 */
   25,24,23,22,  21,20,19,18,  17,16,15,14,  13,12,11,10, /* $30 */

    9, 1, 2, 3,   4, 5, 6, 7,   8, 9,10,11,  12,13,14,15, /* $40 */
   16,17,18,19,  20,21,22,23,  24,25,26, 8,   7, 6, 5, 4, /* $50 */
    3, 2, 1, 2,   3, 4, 5, 6,   7, 8, 9,10,  11,12,13,14, /* $60 */
   15,16,17,18,  18,20,21,22,  23,24,25,26,  27,28,29,30, /* $70 */
};

/* if you change the is_where order for some reason, you'd need  */
/* to look at VfL variables (probably) and at  "clean_mats"      */    

char  is_where[] =
{
    0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, /* $ 0 */
    0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, /* $10 */
    0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 2, 0, /* $20 */
    0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, /* $30 */

    1, 3, 4, 5,   6, 7, 8, 9,  10,11,12,13,  14,15,16,17, /* $40 */
   18,19,20,21,  22,23,24,25,  26,27,28, 0,   0, 0, 0,29, /* $50 */
    0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0, /* $60 */
    0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   X, 0, 0, 0  /* $70 */
};
#undef X

/* ---------------------------------------------------------- */
/*                Mallocer for the labelstructure             */
/*                                                            */
/*   (Keeping the fingers crossed that this is faster than a) */
/*                       (simple malloc)                      */
/*                Mallocer for the local labels               */
/* Hold on. I don't get it. Why TWO mallocers for labels?     */
/* The point is that global label space is never freed until  */
/* assembly is completed, whereas local label space is freed  */
/* whenever a .LOCAL appears. Since we like to reclaim memory */
/* We need a different mallocer (+ freeer)                    */
/* ---------------------------------------------------------- */
make_mallocer( label, LABMAX, lab_alloc)

dup_mallocer( label, LLABMAX, llab_alloc, l)


void llab_free()
{
   register label_m huge   *p = llabel_h,
                    huge   *q;               /* q for multitaskin' (har) */

   ENTER("llab_free");
   if( p)
      for(;;)
      {
         if( ! p->before)
         {
            p->free  = LLABMAX;
            p->tab   = (label *) ((char huge *) p + sizeof( label_m));
            llabel_h = p;
            LEAVE();
            return;
         }
         q = p;
         p = p->before;
         nfree( (void *) q);
      }
   LEAVE();
}
