
/* 
 * $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: sym.c 1.1 90/01/19 $@(#)sym.c	1.1 89/12/01"
#include <stdio.h>
#include "xsld.h"

extern char *gettxt();

void
load_def(sym, mo, init)
  char *sym;
  bool init;
  MODULE mo;
{
  SYMBOL sym_pos = sym_locate(sym);

  if (!is_null_symbol(sym_pos)){
    /*
     * Symbol is already in the table
     */
    if (sym_used(sym_pos)){
      /*
       * Symbol is already used
       */
      if (sym_def(sym_pos)){
        /*
         * Symbol is already defined
         */
        if (mo_used(mo)){
          /*
           * The current module is used
           * Symbol is already used and defined
           */
          add_entry(sym_pos, mo, TRUE, init);
          sym_count_new(sym_pos, sym_count(sym_pos) + 1);
          multi_def = TRUE;
        } else {
          /*
           * The current module is not used.
           * This definition could be a multiple definition if the current
           * module was used
           */
          add_entry(sym_pos, mo, TRUE, init);
        }
      } else {
        /*
         * The symbol in the table is used but undefined
         */
        if (!mo_used(mo)){
          /*
           * The current module defines a symbol that is undefined and
           * being used. It must become used
           */
          use_module(mo);
        }
        add_entry(sym_pos, mo, TRUE, init);
        sym_def_new(sym_pos, TRUE);
        sym_count_new(sym_pos, 1);
        sym_mo_new(sym_pos, mo);
        sym_init_new(sym_pos, init);
        check_init(sym_pos);
        if (init)
          sym_add_init(sym_pos, mo);
        del_undef(sym_pos);
      }
    } else {
      /*
       * Symbol is unused
       */
      if (sym_def(sym_pos)){
        /*
         * Symbol is defined
         */
        if (mo_used(mo)){
          /*
           * Module is used
           */
          add_entry(sym_pos, mo, TRUE, init);
          sym_def_new(sym_pos, TRUE);
          sym_count_new(sym_pos, 1);
          sym_init_new(sym_pos, init);
          sym_mo_new(sym_pos, mo);
          if (init)
            sym_add_init(sym_pos, mo);
        } else {
          /*
           * Module is unused
           */
          add_entry(sym_pos, mo, TRUE, init);
        }
      } else {
        /*
         * Symbol is undefined
         */
        if (mo_used(mo)){
          /*
           * Module is used
           */
          add_entry(sym_pos, mo, TRUE, init);
          sym_def_new(sym_pos, TRUE);
          sym_count_new(sym_pos, 1);
          sym_init_new(sym_pos, init);
          sym_mo_new(sym_pos, mo);
          if (init)
            sym_add_init(sym_pos, mo);
        } else {
          /*
           * Module is unused
           */
          add_entry(sym_pos, mo, TRUE, init);
          sym_def_new(sym_pos, TRUE);
        }
      }
    }
  } else {
    /*
     * Symbol is not yet in the table
     */
    sym_pos = sym_insert(sym);
    sym_def_new(sym_pos, TRUE);
    sym_count_new(sym_pos, 1);
    sym_mo_new(sym_pos, mo);
    sym_init_new(sym_pos, init);
    add_entry(sym_pos, mo, TRUE, init);
    sym_used_new(sym_pos, mo_used(mo));
  }
}

void
load_undef(sym, mo, init)
  char *sym;
  MODULE mo;
  bool init;
{
  SYMBOL sym_pos = sym_locate(sym);
  
  if (!is_null_symbol(sym_pos)){
    /*
     * Symbol is already in the table
     */
    if (sym_used(sym_pos)){
      /*
       * Symbol is used
       */
      if(sym_init(sym_pos)){
      	/*
      	 * Symbol is init
      	 */
      	if (!init){
      	  /*
      	   * Symbol should be initialized
      	   */
      	  should_init(mo);
      	}
      } else {
        if (init){
          /*
           * Symbol should not be initialized
           */
          should_init(mo);
        }
      }
      add_entry(sym_pos, mo, FALSE, init);
      if (sym_def(sym_pos) && sym_init(sym_pos))
        mo_add_init(sym_mo(sym_pos), mo, sym_pos);
    } else {
      /*
       * Symbol is unused
       */
      if (sym_def(sym_pos)){
        /*
         * Symbol is defined
         */
        add_entry(sym_pos, mo, FALSE, init);
        if (mo_used(mo)){
          /*
           * Current module is used
           * The current symbol is defined in a module that is not used
           */
          add_to_be_used(sym_pos);
        }
      } else {
        /*
         * Symbol is undefined
         */
         
        if (mo_used(mo)){
          /*
           * The current module is used
           * The symbol becomes used
           */
          add_entry(sym_pos, mo, FALSE, init);
          sym_used_new(sym_pos, TRUE);
          add_undef(sym_pos, mo);
        } else {
          /*
           * Module is unused
           */
          add_entry(sym_pos, mo, FALSE, init);
        }
      }
    }
  } else {
    /*
     * Symbol is not in the table
     */
    sym_pos = sym_insert(sym);
    add_entry(sym_pos, mo, FALSE, init);
    sym_used_new(sym_pos, mo_used(mo));
    sym_def_new(sym_pos, FALSE);
    sym_init_new(sym_pos, init);
    if (sym_used(sym_pos))
      add_undef(sym_pos, mo);
  }
}

/*
 * Change module from unused to used
 */
void
use_module(mo)
  MODULE mo;
{
  SYMBOL sym_pos;
  SYMTAB ptr;

  ptr = mo_def(mo);
  while (!is_null_symtab(ptr)){
    sym_pos = symtab_sym(ptr);
    if (sym_used(sym_pos)){
      if (sym_def(sym_pos)){

        /*
         * Multiple definition
         */
        sym_count_new(sym_pos, sym_count(sym_pos) + 1);
        multi_def = TRUE;
      } else {
        /*
         * Symbol is defined now
         */
        sym_def_new(sym_pos, TRUE);
        sym_count_new(sym_pos, 1);
        sym_mo_new(sym_pos, mo);
        sym_init_new(sym_pos, symtab_init(ptr));
        if (sym_init(sym_pos))
          sym_add_init(sym_pos, mo);
      }
    } else {
      /*
       * Symbol is unused
       */
      if (sym_def(sym_pos)){
        /*
         * Symbol becomes defined and used
         */
        sym_used_new(sym_pos, TRUE);
        sym_count_new(sym_pos, 1);
        sym_mo_new(sym_pos, mo);
        sym_init_new(sym_pos, symtab_init(ptr));
        check_init(sym_pos);
        if (sym_init(sym_pos))
          sym_add_init(sym_pos, mo);
      } else {
        fprintf(stderr, gettxt("xsld:33","Internal error in sym.c\n"));
        fatal();
      }
    }
    ptr = symtab_next(ptr);
  }
  ptr = mo_undef(mo);
  
  while (!is_null_symtab(ptr)){
    sym_pos = symtab_sym(ptr);
    if (!sym_used(sym_pos)){
      if (sym_def(sym_pos)){
        add_to_be_used(sym_pos);
      } else {
        sym_used_new(sym_pos, TRUE);
        add_undef(sym_pos, mo);
      }
    } else {
      if (sym_def(sym_pos)){
        if (sym_init(sym_pos)){
          if (!symtab_init(ptr))
            should_init(mo);
          else
            mo_add_init(sym_mo(sym_pos), mo, sym_pos);
        } else {
          if (symtab_init(ptr))
            should_init(mo);
        }
      }
    }
    ptr = symtab_next(ptr);
  }
  mo_used_new(mo, TRUE);
}

should_init(mo)
  MODULE mo;
{
  char loc_buf[20];
  char *strrchr();
  char *ptr;
  LIB lib;
  
  strcpy(loc_buf, mo_name(mo));
  if (mo_badinit(mo))
    /*
     * Already asked to recompile the module
     */
    return;
    
  ptr = strrchr(loc_buf, '.');
  if (ptr != 0)
    *ptr = '\0';
  if ((lib = mo_lib(mo)) != NULL_LIB)
    fprintf(stdout, gettxt("xsld:34","ERROR: %s.c (%s) must be recompiled\n"), loc_buf, 
            lib_name(lib));
  else
    fprintf(stdout, gettxt("xsld:35","ERROR: %s.c must be recompiled\n"), loc_buf);
  mo_badinit_new(mo, TRUE);
  bad_init = TRUE;
}
