
/* 
 * $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
 */

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/
#ident "$Header: syms.c 1.1 90/01/19 $@(#)syms.c	1.1 89/12/01"
#include <stdio.h>
#include "xsld.h"
#include <malloc.h>

extern char *gettxt();

static SYM *symbols;
static SYMBOL sym_free = 0;
static SYMBOL sym_max = 0;

SYMTAB	null_symtab = NULL_SYMTAB;
SYMBOL null_symbol = NULL_SYMBOL;

#define INC_SYM		1024
#define INC_SYMTAB	20

void
add_entry(sym_pos, mo, def, init)
  SYMBOL sym_pos;
  MODULE mo;
  bool def, init;
{
  int new = symbols[sym_pos].sy_free++;
  SYMTAB new_sym, old_sym;
    
  if (new == symbols[sym_pos].sy_max){
    if (symbols[sym_pos].sy_max == 0){
      symbols[sym_pos].sy_max = INC_SYMTAB;
      if ((symbols[sym_pos].sy_sy = (SYMTAB *)malloc(sizeof(SYMTAB) * INC_SYMTAB))
             == 0){
        fprintf(stderr, gettxt("xsld:45", "Out of memory (syms.c (1))\n"));
        fatal();
      }
    } else {
      symbols[sym_pos].sy_max += INC_SYMTAB;
      if ((symbols[sym_pos].sy_sy = (SYMTAB *)realloc(
              (char *)symbols[sym_pos].sy_sy, sizeof(SYMTAB) * 
                                               symbols[sym_pos].sy_max)) == 0){
        fprintf(stderr, gettxt("xsld:36","Out of memory (syms.c (2))\n"));
	fatal();
      }
    }
  }
  symbols[sym_pos].sy_sy[new].symtab_def = def;
  symbols[sym_pos].sy_sy[new].symtab_init = init;
  symbols[sym_pos].sy_sy[new].symtab_mo = mo;
  symbols[sym_pos].sy_sy[new].symtab_sym = -1;
  symbols[sym_pos].sy_sy[new].symtab_entry = -1;
/*  new_sym = symbols[sym_pos].sy_sy[new];*/
  
  if (def){
    if (is_null_symtab(mo_def_last(mo))){
      new_sym.symtab_sym = sym_pos;
      new_sym.symtab_entry = new;
      mo_def_new(mo, new_sym);
    } else {
      old_sym = mo_def_last(mo);
      new_sym = symbols[old_sym.symtab_sym].sy_sy[old_sym.symtab_entry];
      new_sym.symtab_sym = sym_pos;
      new_sym.symtab_entry = new;
      symbols[old_sym.symtab_sym].sy_sy[old_sym.symtab_entry] = new_sym;
    }
    mo_def_last_new(mo, new_sym);
  } else {
    if (is_null_symtab(mo_undef_last(mo))){
      new_sym.symtab_sym = sym_pos;
      new_sym.symtab_entry = new;
      mo_undef_new(mo, new_sym);
    } else {
      old_sym = mo_undef_last(mo);
      new_sym = symbols[old_sym.symtab_sym].sy_sy[old_sym.symtab_entry];
      new_sym.symtab_sym = sym_pos;
      new_sym.symtab_entry = new;
      symbols[old_sym.symtab_sym].sy_sy[old_sym.symtab_entry] = new_sym;
    }
    mo_undef_last_new(mo, new_sym);
  }
}
         
SYMTAB
symtab_next(sym)
  SYMTAB sym;
{
  return symbols[sym.symtab_sym].sy_sy[sym.symtab_entry];
}

SYMBOL
symtab_sym(sym)
  SYMTAB sym;
{
  return sym.symtab_sym;
}

bool
symtab_init(sym)
  SYMTAB sym;
{
  return symbols[sym.symtab_sym].sy_sy[sym.symtab_entry].symtab_init;
}

SYMBOL
sym_insert(sym)
  char *sym;
{
  if (sym_free == sym_max){
    if (sym_max == 0){
      sym_max = INC_SYM;
      /*
       * Keep first entry empty for compare routine
       */
      sym_free = 1;
      if ((symbols = (SYM *)malloc(sizeof(SYM) * INC_SYM)) == 0){
        fprintf(stderr, gettxt("xsld:37","Out of memory (syms.c (3))\n"));
        fatal();
      }
    } else {
      sym_max += INC_SYM;
      if ((symbols = 
           (SYM *)realloc((char *)symbols, sizeof(SYM) * sym_max)) == 0){
        fprintf(stderr, gettxt("xsld:38","Out of memory (syms.c (4))\n"));
        fatal();
      }
    }
  }
  symbols[sym_free].sy_name = sym_store(sym, sym_free);
  symbols[sym_free].sy_mo = NULL_MODULE;
  symbols[sym_free].sy_free = 0;
  symbols[sym_free].sy_max = 0;
  symbols[sym_free].sy_used = FALSE;
  symbols[sym_free].sy_def = FALSE;
  symbols[sym_free].sy_init = FALSE;
  symbols[sym_free].sy_count = 0;
  symbols[sym_free].sy_undef_back = null_symtab;
  symbols[sym_free].sy_undef_forw = null_symtab;
  return sym_free++;
}

sym_close()
{
}

char *
sym_name(s)
  SYMBOL s;
{
  return symbols[s].sy_name;
}

bool
sym_used(s)
  SYMBOL s;
{
  return symbols[s].sy_used;
}

void
sym_used_new(s, used)
  SYMBOL s;
  bool used;
{
  symbols[s].sy_used = used;
}

bool
sym_def(s)
  SYMBOL s;
{
  return symbols[s].sy_def;
}

void
sym_def_new(s, def)
  SYMBOL s;
  bool def;
{
  symbols[s].sy_def = def;
}

bool
sym_init(s)
  SYMBOL s;
{
  return symbols[s].sy_init;
}

void
sym_init_new(s, init)
  SYMBOL s;
  bool init;
{
  symbols[s].sy_init = init;
}

int
sym_count(s)
  SYMBOL s;
{
  return symbols[s].sy_count;
}

void
sym_count_new(s, count)
  SYMBOL s;
  int count;
{
  symbols[s].sy_count = count;
}

static SYMTAB undef_start, undef_end;
static int undef_cnt;

void
add_undef(s, mo)
  SYMBOL s;
  MODULE mo;
{
  if (undef_cnt++ == 0)
    undef_start = undef_end = null_symtab;

  symbols[s].sy_undef_forw = null_symtab;
  symbols[s].sy_undef_back = undef_end;
  if (is_null_symtab(undef_start)){
    undef_start.symtab_sym = s;
    undef_start.symtab_mo = mo;
  } else {
    symbols[undef_end.symtab_sym].sy_undef_forw.symtab_sym = s;
    symbols[undef_end.symtab_sym].sy_undef_forw.symtab_mo = mo;
  }

  undef_end.symtab_sym = s;
}

void
del_undef(s)
  SYMBOL s;
{
  SYMBOL s_aux;
  
  undef_cnt--;
  if (undef_start.symtab_sym == s){
    undef_start = symbols[s].sy_undef_forw;
  } else {
    s_aux = symbols[s].sy_undef_back.symtab_sym;
    symbols[s_aux].sy_undef_forw = symbols[s].sy_undef_forw;
  }
  if (undef_end.symtab_sym == s){
    undef_end = symbols[s].sy_undef_back;
  } else {
    s_aux = symbols[s].sy_undef_forw.symtab_sym;
    symbols[s_aux].sy_undef_back = symbols[s].sy_undef_back;
  }
}

int
undef_count()
{
  return undef_cnt;
}

bool
is_null_symtab(s)
  SYMTAB s;
{
  return (s.symtab_sym == NULL_SYMBOL);
}

bool
is_null_symbol(s)
  SYMBOL s;
{
  return (s == NULL_SYMBOL);
}

MODULE
symtab_mo(s)
  SYMTAB s;
{
  return s.symtab_mo;
}

bool
symtab_def(s)
  SYMTAB s;
{
  return s.symtab_def;
}

void
disp_multi_def()
{
  SYMBOL s;
  register int i;

  fprintf(stdout, gettxt("xsld:39","Multiply defined symbols:\n"));
  for (s = 1 ; s < sym_free ; s++){
    if (sym_used(s) && sym_def(s) && sym_count(s) > 1){
      bool first;
      first = TRUE;
      fprintf(stdout, "%s:", sym_name(s));
      for (i = 0 ; i < symbols[s].sy_free ; i++){
        if (mo_used(symtab_mo(symbols[s].sy_sy[i])) && 
          symtab_def(symbols[s].sy_sy[i])){
          if (first)
            first = FALSE;
          else
            fprintf(stdout, ", ");
          mo_print(symtab_mo(symbols[s].sy_sy[i]));
        }
      }
      fprintf(stdout, "\n");
    }
  }
}

SYMTAB
undef_next(s)
  SYMTAB s;
{
  return symbols[s.symtab_sym].sy_undef_forw;
}

void
disp_undefined()
{
  SYMTAB sym;
  SYMBOL s;
  register int i;
  bool first;
  
  /*
   * Check for a 'strings_extracted' module used with a dummy message file
   */
  sym = undef_start;
  first = TRUE;
  while(!is_null_symtab(sym)){
    MODULE mo;
    s = symtab_sym(sym);
    if (strcmp(sym_name(s), str_init) == 0 || 
        strcmp(sym_name(s), str_replace) == 0){
      for (i = 0 ; i < symbols[s].sy_free ; i++){
        if (mo_used(mo = symtab_mo(symbols[s].sy_sy[i])) && 
            !symtab_def(symbols[s].sy_sy[i]) && !mo_badundef(mo)){
          if (first){
            fprintf(stdout, gettxt("xsld:40","ERROR: Lost messages from modules:\n"));
            first = FALSE;
            bad_undef = TRUE;
          } else 
            fprintf(stdout, ", ");
          mo_print(symtab_mo(symbols[s].sy_sy[i]));
          mo_badundef_new(mo, TRUE);
        }
      }
    }
    sym = undef_next(sym);
    if (!first){
      fprintf(stdout, "\n");
      fflush(stdout);
    }
  }
  if (bad_undef)
    return;
  fprintf(stdout, gettxt("xsld:41","Undefined symbols:\n"));
  sym = undef_start;
  while (!is_null_symtab(sym)){
    s = symtab_sym(sym);
    first = TRUE;
    fprintf(stdout, "%s:", sym_name(s));
    
    for (i = 0 ; i < symbols[s].sy_free ; i++){
      if (mo_used(symtab_mo(symbols[s].sy_sy[i])) && 
          !symtab_def(symbols[s].sy_sy[i])){
        if (first)
          first = FALSE;
        else
          fprintf(stdout, ", ");
        mo_print(symtab_mo(symbols[s].sy_sy[i]));
      }
    }
    fprintf(stdout, "\n");
    fflush(stdout);
    sym = undef_next(sym);
  }
}

void
sym_add_init(s, mo)
  SYMBOL s;
  MODULE mo;
{
  register int i;

  for (i = 0 ; i < symbols[s].sy_free ; i++){
    if (!symtab_def(symbols[s].sy_sy[i]) && 
           mo_used(symtab_mo(symbols[s].sy_sy[i]))){
      if (!symbols[s].sy_sy[i].symtab_init)
        should_init(symtab_mo(symbols[s].sy_sy[i]));
      mo_add_init(mo, symtab_mo(symbols[s].sy_sy[i]), s);
    }
  }
}

void
sym_mo_new(s, mo)
  SYMBOL s;
  MODULE mo;
{
  symbols[s].sy_mo = mo;
}

MODULE sym_mo(s)
  SYMBOL s;
{
  return symbols[s].sy_mo;
}

/*
 * Find out the non-loaded module that defines a symbol
 */
MODULE
mo_defines(s)
  SYMBOL s;
{
  register int i;
  
  for (i = 0 ; i < symbols[s].sy_free ; i++){
    if (symbols[s].sy_sy[i].symtab_def)
      return symbols[s].sy_sy[i].symtab_mo;
  }
  return NULL_SYMBOL;
}

void
desc_init(fd)
  FILE *fd;
{
  register SYMBOL i;

  for (i = 1 ; i < sym_free ; i++){
   if (sym_used(i) && sym_init(i)){
      register  int j;

      fprintf(fd, "%-16s", sym_name(i));
      for (j = 0 ; j < symbols[i].sy_free ; j++){
	MODULE mo;
	mo = symbols[i].sy_sy[j].symtab_mo;
	if (mo_used(mo))
	  fprintf(fd, " %s", mo_name(mo));
      }
      fprintf(fd, "\n");
    }
  }
}
  
check_init(sym_pos)
  SYMBOL sym_pos;
{
  register int i;
 
  for (i = 0 ; i < symbols[sym_pos].sy_free ; i++){
    if (mo_used(symtab_mo(symbols[sym_pos].sy_sy[i])) &&
        !symtab_def(symbols[sym_pos].sy_sy[i])){
      if (symbols[sym_pos].sy_sy[i].symtab_init != sym_init(sym_pos))
        should_init(symtab_mo(symbols[sym_pos].sy_sy[i]));
    }
  }
}
