/* locals.c -- STAR Local Symbols

This file is part of STAR, the Saturn Macro Assembler.

   STAR is not distributed by the Free Software Foundation. Do not ask
them for a copy or how to obtain new releases. Instead, send e-mail to
the address below. STAR is merely covered by the GNU General Public
License.

Please send your comments, ideas, and bug reports to
Jan Brittenson <bson@ai.mit.edu>

*/


/* Copyright (C) 1990, 1991 Jan Brittenson

   STAR is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 1, or (at your option) any
later version.

   STAR is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.

   You should have received a copy of the GNU General Public License
along with STAR; see the file COPYING. If not, to obtain a copy, write
to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
USA, or send e-mail to bson@ai.mit.edu. */

/* Local symbols are stored in a sparse array. Each symbol is a
 * short-sized index into the array, its upper half is the counter,
 * and low half is the symbol identifier. For each appearance of a
 * global symbol declaration (name:) a global context counter is
 * incremented, and at any point, a local symbol is identified by a
 * long integer whose upper-end short is equal to the context counter,
 * and its lower-end short is equal to the symbol identity.
 *
 * For instance, the symbol $256: will appear at the indices
 *
 *	00000100, 00010100, 00020100 etc depending on the context
 *	counter's current value.
 *
 * The semantics are those of DEC Macro-11 local symbols.
 *
 */

#include <stdio.h>
#include "star.h"
#include "sparse.h"

int
  local_pass,			/* Curret pass */
  ncontext;			/* Context counter */

static SPR_ROOT
  *local_symbols;		/* Local symbol table */


/* Initialize local symbol table data */
void local_init()
{
  extern char *malloc();
  extern void free();

  local_symbols = spr_open(malloc, free, "STAR Local Symbol Table",
			   sizeof(unsigned long)*2, 4);
}


/* Set up for new pass */
void local_new_pass(pass)
  int pass;
{
  local_pass = pass;

  ncontext = 0;
}


/* Set up for new context */
void local_new_context()
{
  ncontext++;
}


/* Join ID and context into index key */
static
#ifdef __GNUC__
  const inline
#endif
  unsigned long local_key(id, ctx)
    unsigned long id;
    int ctx;
{
  return((unsigned long) ((unsigned long) ctx << (sizeof(short)*8)) |
	 (id & SHORT_MASK));
}


/* Bind local symbol. Ignore multiple definitions. */
void local_bind(symid, value)
  unsigned long symid, value;
{
  spr_bind(local_symbols,
	   local_key(symid, ncontext),
	   (char *) ((value & 0xfffff) |
		     0x100000)); /* Kludge to avoid NULL value */
}


/* Return local symbol as value */
struct val local_value(symid)
  unsigned long symid;
{
  char *cp;
  struct val v;
  extern struct val val_zero;

  cp = spr_get(local_symbols, local_key(symid, ncontext));

  if(!cp)
    {
      sgnerr("Undefined local symbol `$%lu'", symid);
      return(val_zero);
    }

  v.vint = (long) cp & 0xfffff;
  v.type = VT_INT;
  return(v);
}
