Diff for /binutils/ld.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2018/04/24 16:07:00 version 1.1.1.3, 2018/04/24 16:07:02
Line 103  software. Line 103  software.
 /* Written by Richard Stallman with some help from Eric Albert.  /* Written by Richard Stallman with some help from Eric Albert.
    Set and indirect features added by Randy Smith.  */     Set and indirect features added by Randy Smith.  */
   
 #include <a.out.h>  
 #include <stab.h>  
 #include <ar.h>  #include <ar.h>
 #include <stdio.h>  #include <stdio.h>
 #include <sys/types.h>  #include <sys/types.h>
 #include <strings.h>  
 #include <sys/stat.h>  #include <sys/stat.h>
 #include "symseg.h"  
 #include <sys/file.h>  #include <sys/file.h>
   #include <fcntl.h>
   
   #ifdef COFF_ENCAPSULATE
   #include "a.out.encap.h"
   #else
   #include <a.out.h>
   #endif
   
   /* If compiled with GNU C, use the built-in alloca */
   #ifdef __GNUC__
   #define alloca __builtin_alloca
   #endif
   
   /* Always use the GNU version of debugging symbol type codes, if possible.  */
   
   #include "stab.h"
   #define CORE_ADDR unsigned long /* For symseg.h */
   #include "symseg.h"
   
   #ifdef USG
   #include <string.h>
   #else
   #include <strings.h>
   #endif
   
   /* Determine whether we should attempt to handle (minimally)
      N_BINCL and N_EINCL.  */
   
   #if defined (__GNU_STAB__) || defined (N_BINCL)
   #define HAVE_SUN_STABS
   #endif
   
 #define min(a,b) ((a) < (b) ? (a) : (b))  #define min(a,b) ((a) < (b) ? (a) : (b))
   
Line 121  software. Line 148  software.
 /* Size of a page; obtained from the operating system.  */  /* Size of a page; obtained from the operating system.  */
   
 int page_size;  int page_size;
   
   /* Name this program was invoked by.  */
   
   char *progname;
   
 /* System dependencies */  /* System dependencies */
   
Line 147  int page_size; Line 178  int page_size;
 #ifdef vax  #ifdef vax
 #define N_TXTADDR(X) 0  #define N_TXTADDR(X) 0
 #endif  #endif
   #ifdef is68k
   #define N_TXTADDR(x)  (sizeof (struct exec))
   #endif
 #endif  #endif
   
 #ifndef N_DATADDR  #ifndef N_DATADDR
Line 155  int page_size; Line 189  int page_size;
         (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \          (((x).a_magic==OMAGIC)? (N_TXTADDR(x)+(x).a_text) \
         : (page_size+((N_TXTADDR(x)+(x).a_text-1) & ~(page_size-1))))          : (page_size+((N_TXTADDR(x)+(x).a_text-1) & ~(page_size-1))))
 #endif  #endif
   #ifdef is68k
   #define SEGMENT_SIZE 0x20000
   #define N_DATADDR(x) \
       (((x).a_magic==Omagic)? (N_TXTADDR(x)+(x).a_text) \
        : (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))))
   #endif
 #endif  #endif
   
 #ifdef hpux  #ifdef hpux
Line 163  int page_size; Line 203  int page_size;
   
 /* Define how to initialize system-dependent header fields.  */  /* Define how to initialize system-dependent header fields.  */
 #ifdef sun  #ifdef sun
   #ifdef sparc
   #define INITIALIZE_HEADER \
     {outheader.a_machtype = M_SPARC; outheader.a_toolversion = 1;}
   #endif
   #if defined(mc68010) || defined(m68010) || (TARGET == SUN2)
   #define INITIALIZE_HEADER outheader.a_machtype = M_68010
   #endif
   #ifndef INITIALIZE_HEADER
 #define INITIALIZE_HEADER outheader.a_machtype = M_68020  #define INITIALIZE_HEADER outheader.a_machtype = M_68020
 #endif  #endif
   #endif
   #ifdef is68k
   #ifdef M_68020
   /* ISI rel 4.0D doesn't use it, and rel 3.05 doesn't have an
      a_machtype field and so won't recognize the magic number.  To keep
      binary compatibility for now, just ignore it */
   #define INITIALIZE_HEADER outheader.a_machtype = 0;
   #endif
   #endif
 #ifdef hpux  #ifdef hpux
 #define INITIALIZE_HEADER outheader.a_machtype = HP9000S200_ID  #define INITIALIZE_HEADER outheader.a_machtype = HP9000S200_ID
 #endif  #endif
   #ifdef i386
   #define INITIALIZE_HEADER outheader.a_machtype = M_386
   #endif
   
   #ifdef is68k
   /* This enables code to take care of an ugly hack in the ISI OS.
      If a symbol beings with _$, then the object file is included only
      if the rest of the symbol name has been referenced. */
   #define DOLLAR_KLUDGE
   #endif
   
   /*
    * Alloca include.
    */
   #if defined(sun) && defined(sparc)
   #include "alloca.h"
   #endif
   
   #ifndef L_SET
   #define L_SET 0
   #endif
   
   /*
    * Ok.  Following are the relocation information macros.  If your
    * system should not be able to use the default set (below), you must
    * define the following:
   
    *   relocation_info: This must be typedef'd (or #define'd to the type
    * of structure that is stored in the relocation info section of your
    * a.out files.  Often this is defined in the a.out.h for your system.
    *
    *   RELOC_ADDRESS (rval): Offset into the current section of the
    * <whatever> to be relocated.  *Must be an lvalue*.
    *
    *   RELOC_EXTERN_P (rval):  Is this relocation entry based on an
    * external symbol (1), or was it fully resolved upon entering the
    * loader (0) in which case some combination of the value in memory
    * (if RELOC_MEMORY_ADD_P) and the extra (if RELOC_ADD_EXTRA) contains
    * what the value of the relocation actually was.  *Must be an lvalue*.
    *
    *   RELOC_TYPE (rval): If this entry was fully resolved upon
    * entering the loader, what type should it be relocated as?
    *
    *   RELOC_SYMBOL (rval): If this entry was not fully resolved upon
    * entering the loader, what is the index of it's symbol in the symbol
    * table?  *Must be a lvalue*.
    *
    *   RELOC_MEMORY_ADD_P (rval): This should return true if the final
    * relocation value output here should be added to memory, or if the
    * section of memory described should simply be set to the relocation
    * value.
    *
    *   RELOC_ADD_EXTRA (rval): (Optional) This macro, if defined, gives
    * an extra value to be added to the relocation value based on the
    * individual relocation entry.
    *
    *   RELOC_PCREL_P (rval): True if the relocation value described is
    * pc relative.
    *
    *   RELOC_VALUE_RIGHTSHIFT (rval): Number of bits right to shift the
    * final relocation value before putting it where it belongs.
    *
    *   RELOC_TARGET_SIZE (rval): log to the base 2 of the number of
    * bytes of size this relocation entry describes; 1 byte == 0; 2 bytes
    * == 1; 4 bytes == 2, and etc.  This is somewhat redundant (we could
    * do everything in terms of the bit operators below), but having this
    * macro could end up producing better code on machines without fancy
    * bit twiddling.  Also, it's easier to understand/code big/little
    * endian distinctions with this macro.
    *
    *   RELOC_TARGET_BITPOS (rval): The starting bit position within the
    * object described in RELOC_TARGET_SIZE in which the relocation value
    * will go.
    *
    *   RELOC_TARGET_BITSIZE (rval): How many bits are to be replaced
    * with the bits of the relocation value.  It may be assumed by the
    * code that the relocation value will fit into this many bits.  This
    * may be larger than RELOC_TARGET_SIZE if such be useful.
    *
    *
    *              Things I haven't implemented
    *              ----------------------------
    *
    *    Values for RELOC_TARGET_SIZE other than 0, 1, or 2.
    *
    *    Pc relative relocation for External references.
    *
    *
    */
   
   #if defined(sun) && defined(sparc)
   /* Sparc (Sun 4) macros */
   #undef relocation_info
   #define relocation_info                 reloc_info_sparc
   #define RELOC_ADDRESS(r)                ((r)->r_address)                 
   #define RELOC_EXTERN_P(r)               ((r)->r_extern)      
   #define RELOC_TYPE(r)                   ((r)->r_index)  
   #define RELOC_SYMBOL(r)                 ((r)->r_index)   
   #define RELOC_MEMORY_ADD_P(r)           0                          
   #define RELOC_ADD_EXTRA(r)              ((r)->r_addend)       
   #define RELOC_PCREL_P(r)             \
           ((r)->r_type >= RELOC_DISP8 && (r)->r_type <= RELOC_WDISP22)
   #define RELOC_VALUE_RIGHTSHIFT(r)       (reloc_target_rightshift[(r)->r_type])
   #define RELOC_TARGET_SIZE(r)            (reloc_target_size[(r)->r_type])
   #define RELOC_TARGET_BITPOS(r)          0
   #define RELOC_TARGET_BITSIZE(r)         (reloc_target_bitsize[(r)->r_type])
   
   /* Note that these are very dependent on the order of the enums in
      enum reloc_type (in a.out.h); if they change the following must be
      changed */
   /* Also note that the last few may be incorrect; I have no information */
   static int reloc_target_rightshift[] = {
     0, 0, 0, 0, 0, 0, 2, 2, 10, 0, 0, 0, 0, 0, 0,
   };
   static int reloc_target_size[] = {
     0, 1, 2, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
   };
   static int reloc_target_bitsize[] = {
     8, 16, 32, 8, 16, 32, 30, 22, 22, 22, 13, 10, 32, 32, 16,
   };
   #endif
   
   /* Default macros */
   #ifndef RELOC_ADDRESS
   #define RELOC_ADDRESS(r)                ((r)->r_address)
   #define RELOC_EXTERN_P(r)               ((r)->r_extern)
   #define RELOC_TYPE(r)           ((r)->r_symbolnum)
   #define RELOC_SYMBOL(r)         ((r)->r_symbolnum)
   #define RELOC_MEMORY_ADD_P(r)   1
   /* #define RELOC_ADD_EXTRA(r)           0       /* Don't need to define */
   #define RELOC_PCREL_P(r)                ((r)->r_pcrel)
   #define RELOC_VALUE_RIGHTSHIFT(r)       0
   #define RELOC_TARGET_SIZE(r)            ((r)->r_length)
   #define RELOC_TARGET_BITPOS(r)  0
   #define RELOC_TARGET_BITSIZE(r) 32
   #endif
   
 /* Special global symbol types understood by GNU LD.  */  /* Special global symbol types understood by GNU LD.  */
   
Line 217  int page_size; Line 410  int page_size;
 #ifndef N_SETV  #ifndef N_SETV
 #define N_SETV  0x1C            /* Pointer to set vector in text area.  */  #define N_SETV  0x1C            /* Pointer to set vector in text area.  */
 #endif                          /* This is output from LD.  */  #endif                          /* This is output from LD.  */
   
   #ifndef N_WARNING
   #define N_WARNING 0x1E          /* Warning message to print if file included */
   #endif                          /* This is input to ld */
   
   #ifndef __GNU_STAB__
   
   /* Line number for the data section.  This is to be used to describe
      the source location of a variable declaration.  */
   #ifndef N_DSLINE
   #define N_DSLINE (N_SLINE+N_DATA-N_TEXT)
   #endif
   
   /* Line number for the bss section.  This is to be used to describe
      the source location of a variable declaration.  */
   #ifndef N_BSLINE
   #define N_BSLINE (N_SLINE+N_BSS-N_TEXT)
   #endif
   
   #endif /* not __GNU_STAB__ */
   
 /* Symbol table */  /* Symbol table */
   
Line 234  typedef Line 447  typedef
       char *name;        char *name;
       /* Value of this symbol as a global symbol.  */        /* Value of this symbol as a global symbol.  */
       long value;        long value;
       /* Chain of external 'nlist's in files for this symbol, both defs and refs.  */        /* Chain of external 'nlist's in files for this symbol, both defs
            and refs.  */
       struct nlist *refs;        struct nlist *refs;
         /* Any warning message that might be associated with this symbol
            from an N_WARNING symbol encountered. */
         char *warning;
       /* Nonzero means definitions of this symbol as common have been seen,        /* Nonzero means definitions of this symbol as common have been seen,
          and the value here is the largest size specified by any of them.  */           and the value here is the largest size specified by any of them.  */
       int max_common_size;        int max_common_size;
       /* For relocatable_output, records the index of this global sym in the        /* For relocatable_output, records the index of this global sym in the
          symbol table to be written, with the first global sym given index 0.  */           symbol table to be written, with the first global sym given index 0.*/
       int def_count;        int def_count;
       /* Nonzero means a definition of this global symbol is known to exist.        /* Nonzero means a definition of this global symbol is known to exist.
          Library members should not be loaded on its account.  */           Library members should not be loaded on its account.  */
Line 251  typedef Line 468  typedef
          definition.  */           definition.  */
       char referenced;        char referenced;
       /* A count of the number of undefined references printed for a        /* A count of the number of undefined references printed for a
          specific symbol.  See list_unresolved_references for more           specific symbol.  If a symbol is unresolved at the end of
          info */           digest_symbols (and the loading run is supposed to produce
            relocatable output) do_file_warnings keeps track of how many
            unresolved reference error messages have been printed for
            each symbol here.  When the number hits MAX_UREFS_PRINTED,
            messages stop. */
       unsigned char undef_refs;        unsigned char undef_refs;
       /* Nonzero means print a message at all refs or defs of this symbol */        /* Nonzero means print a message at all refs or defs of this symbol */
       char trace;        char trace;
Line 302  int set_vector_count; Line 523  int set_vector_count;
    to the value of some other symbol. */     to the value of some other symbol. */
 int global_indirect_count;  int global_indirect_count;
   
   /* Count the number of warning symbols encountered. */
   int warning_count;
   
 /* Total number of symbols to be written in the output file.  /* Total number of symbols to be written in the output file.
    Computed by digest_symbols from the variables above.  */     Computed by digest_symbols from the variables above.  */
 int nsyms;  int nsyms;
Line 352  struct file_entry { Line 576  struct file_entry {
      The string table is not kept in core all the time,       The string table is not kept in core all the time,
      but when it is in core, its address is here.  */       but when it is in core, its address is here.  */
   char *strings;    char *strings;
     /* Pointer to any warning specified in this file by an N_WARNING
        type symbol */
     char *warning;
   
   /* Next two used only if `relocatable_output' or if needed for */    /* Next two used only if `relocatable_output' or if needed for */
   /* output of undefined reference line numbers. */    /* output of undefined reference line numbers. */
Line 371  struct file_entry { Line 598  struct file_entry {
   int bss_start_address;    int bss_start_address;
   /* Offset in bytes in the output file symbol table    /* Offset in bytes in the output file symbol table
      of the first local symbol for this file.  Set by `write_file_symbols'.  */       of the first local symbol for this file.  Set by `write_file_symbols'.  */
   int local_syms_offset;                                       int local_syms_offset;
   
   /* For library members only */    /* For library members only */
   
Line 432  int outdesc; Line 659  int outdesc;
   
 struct exec outheader;  struct exec outheader;
   
   #ifdef COFF_ENCAPSULATE
   struct coffheader coffheader;
   int need_coff_header;
   #endif
   
 /* The following are computed by `digest_symbols'.  */  /* The following are computed by `digest_symbols'.  */
   
 int text_size;          /* total size of text of all input files.  */  int text_size;          /* total size of text of all input files.  */
Line 525  int force_common_definition; Line 757  int force_common_definition;
   
 /* Standard directories to search for files specified by -l.  */  /* Standard directories to search for files specified by -l.  */
 char *standard_search_dirs[] =  char *standard_search_dirs[] =
   #ifdef STANDARD_SEARCH_DIRS
     {STANDARD_SEARCH_DIRS};
   #else
 #ifdef NON_NATIVE  #ifdef NON_NATIVE
   {"/usr/local/lib/gnu"};    {"/usr/local/lib/gnu"};
 #else  #else
   {"/lib", "/usr/lib", "/usr/local/lib"};    {"/lib", "/usr/lib", "/usr/local/lib"};
 #endif  #endif
   #endif
   
 /* Actual vector of directories to search;  /* Actual vector of directories to search;
    this contains those specified with -L plus the standard ones.  */     this contains those specified with -L plus the standard ones.  */
Line 546  int make_executable; Line 782  int make_executable;
    errors */     errors */
 int force_executable;  int force_executable;
   
   /* Keep a list of any symbols referenced from the command line (so
      that error messages for these guys can be generated). This list is
      zero terminated. */
   struct glosym **cmdline_references;
   int cl_refs_allocated;
   
 void bcopy (), bzero ();  void bcopy (), bzero ();
 int malloc (), realloc (), alloca ();  int malloc (), realloc ();
   #ifndef alloca
   int alloca ();
   #endif
 int free ();  int free ();
   
 int xmalloc ();  int xmalloc ();
Line 585  main (argc, argv) Line 830  main (argc, argv)
      int argc;       int argc;
 {  {
   page_size = getpagesize ();    page_size = getpagesize ();
     progname = argv[0];
   
   /* Clear the cumulative info on the output file.  */    /* Clear the cumulative info on the output file.  */
   
Line 622  main (argc, argv) Line 868  main (argc, argv)
   set_symbol_count = 0;    set_symbol_count = 0;
   set_vector_count = 0;    set_vector_count = 0;
   global_indirect_count = 0;    global_indirect_count = 0;
     warning_count = 0;
   
     /* Keep a list of symbols referenced from the command line */
     cl_refs_allocated = 10;
     cmdline_references =
       (struct glosym **) xmalloc (cl_refs_allocated
                                   * sizeof(struct glosym *));
   
   /* Completely decode ARGV.  */    /* Completely decode ARGV.  */
   
Line 641  main (argc, argv) Line 894  main (argc, argv)
   INITIALIZE_HEADER;    INITIALIZE_HEADER;
 #endif  #endif
   
   text_size = sizeof (struct exec) - N_TXTOFF (outheader);    text_size = sizeof (struct exec);
   #ifdef COFF_ENCAPSULATE
     if (relocatable_output == 0)
       {
         need_coff_header = 1;
         /* set A_ENCAP now, since it will change the values of N_TXTOFF, etc */
         outheader.a_flags |= A_ENCAP;
         text_size += sizeof (struct coffheader);
       }
   #endif
   
     text_size -= N_TXTOFF (outheader);
   
   if (text_size < 0)    if (text_size < 0)
     text_size = 0;      text_size = 0;
   entry_offset = text_size;    entry_offset = text_size;
Line 661  main (argc, argv) Line 926  main (argc, argv)
   
   digest_symbols ();    digest_symbols ();
   
   /* Print error messages for any missing symbols.  */    /* Print error messages for any missing symbols, for any warning
        symbols, and possibly multiple definitions */
   
   if (!relocatable_output)    do_warnings (stderr);
     list_undefined_symbols (stderr);  
   
   /* Print a map, if requested.  */    /* Print a map, if requested.  */
   
Line 675  main (argc, argv) Line 940  main (argc, argv)
   if (make_executable || force_executable)    if (make_executable || force_executable)
     write_output ();      write_output ();
   
   return 0;    return ! make_executable;
 }  }
   
 void decode_option ();  void decode_option ();
Line 826  decode_command (argc, argv) Line 1091  decode_command (argc, argv)
   }    }
 }  }
   
   
   void
   add_cmdline_ref (sp)
        struct glosym *sp;
   {
     struct glosym **ptr;
   
     for (ptr = cmdline_references;
          ptr < cmdline_references + cl_refs_allocated && *ptr;
          ptr++)
       ;
   
     if (ptr == cmdline_references + cl_refs_allocated)
       {
         int diff = ptr - cmdline_references;
         
         cl_refs_allocated *= 2;
         cmdline_references = (struct glosym **)
           xrealloc (cmdline_references,
                    cl_refs_allocated * sizeof (struct glosym *));
         ptr = cmdline_references + diff;
       }
     
     *ptr++ = sp;
     *ptr = (struct glosym *) 0;
   }
       
 int parse ();  int parse ();
   
 /* Record an option and arrange to act on it later.  /* Record an option and arrange to act on it later.
Line 878  decode_option (swt, arg) Line 1170  decode_option (swt, arg)
       if (!entry_symbol->defined && !entry_symbol->referenced)        if (!entry_symbol->defined && !entry_symbol->referenced)
         undefined_global_sym_count++;          undefined_global_sym_count++;
       entry_symbol->referenced = 1;        entry_symbol->referenced = 1;
         add_cmdline_ref (entry_symbol);
       return;        return;
   
     case 'l':      case 'l':
Line 889  decode_option (swt, arg) Line 1182  decode_option (swt, arg)
         = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));          = (char **) xrealloc (search_dirs, n_search_dirs * sizeof (char *));
       search_dirs[n_search_dirs - 1] = arg;        search_dirs[n_search_dirs - 1] = arg;
       return;        return;
         
     case 'M':      case 'M':
       write_map = 1;        write_map = 1;
       return;        return;
Line 932  decode_option (swt, arg) Line 1225  decode_option (swt, arg)
     case 'u':      case 'u':
       {        {
         register symbol *sp = getsym (arg);          register symbol *sp = getsym (arg);
         if (!sp->defined && !sp->referenced) undefined_global_sym_count++;          if (!sp->defined && !sp->referenced)
             undefined_global_sym_count++;
         sp->referenced = 1;          sp->referenced = 1;
           add_cmdline_ref (sp);
       }        }
       return;        return;
   
Line 968  void print_file_name (); Line 1263  void print_file_name ();
 /* Call FUNCTION on each input file entry.  /* Call FUNCTION on each input file entry.
    Do not call for entries for libraries;     Do not call for entries for libraries;
    instead, call once for each library member that is being loaded.     instead, call once for each library member that is being loaded.
      
    FUNCTION receives two arguments: the entry, and ARG.  */     FUNCTION receives two arguments: the entry, and ARG.  */
   
 void  void
Line 977  each_file (function, arg) Line 1272  each_file (function, arg)
      register int arg;       register int arg;
 {  {
   register int i;    register int i;
     
   for (i = 0; i < number_of_files; i++)    for (i = 0; i < number_of_files; i++)
     {      {
       register struct file_entry *entry = &file_table[i];        register struct file_entry *entry = &file_table[i];
Line 996  each_file (function, arg) Line 1291  each_file (function, arg)
    value.  Return this value.     value.  Return this value.
    Do not call for entries for libraries;     Do not call for entries for libraries;
    instead, call once for each library member that is being loaded.     instead, call once for each library member that is being loaded.
      
    FUNCTION receives two arguments: the entry, and ARG.  It must be a     FUNCTION receives two arguments: the entry, and ARG.  It must be a
    function returning unsigned long (though this can probably be fudged). */     function returning unsigned long (though this can probably be fudged). */
   
Line 1007  check_each_file (function, arg) Line 1302  check_each_file (function, arg)
 {  {
   register int i;    register int i;
   register unsigned long return_val;    register unsigned long return_val;
     
   for (i = 0; i < number_of_files; i++)    for (i = 0; i < number_of_files; i++)
     {      {
       register struct file_entry *entry = &file_table[i];        register struct file_entry *entry = &file_table[i];
Line 1174  read_header (desc, entry) Line 1469  read_header (desc, entry)
      register struct file_entry *entry;       register struct file_entry *entry;
 {  {
   register int len;    register int len;
   struct exec *loc = &entry->header;    struct exec *loc = (struct exec *) &entry->header;
   
   lseek (desc, entry->starting_offset, 0);    lseek (desc, entry->starting_offset, 0);
   len = read (desc, loc, sizeof (struct exec));    len = read (desc, loc, sizeof (struct exec));
Line 1319  void Line 1614  void
 enter_file_symbols (entry)  enter_file_symbols (entry)
      struct file_entry *entry;       struct file_entry *entry;
 {  {
    register struct nlist *p, *end = entry->symbols + entry->header.a_syms / sizeof (struct nlist);     register struct nlist
        *p,
        *end = entry->symbols + entry->header.a_syms / sizeof (struct nlist);
    int lowest_set_vector = -1;     int lowest_set_vector = -1;
   
   if (trace_files) prline_file_name (entry, stderr);    if (trace_files) prline_file_name (entry, stderr);
Line 1339  enter_file_symbols (entry) Line 1636  enter_file_symbols (entry)
         if (!relocatable_output)          if (!relocatable_output)
           enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);            enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
       }        }
       else if (p->n_type == N_WARNING)
         {
           char *name = p->n_un.n_strx + entry->strings;
           
           entry->warning = (char *) xmalloc (strlen(name) + 1);
           strcpy (entry->warning, name);
           warning_count++;
         }
     else if (p->n_type & N_EXT)      else if (p->n_type & N_EXT)
       enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);        enter_global_ref (p, p->n_un.n_strx + entry->strings, entry);
     else if (p->n_un.n_strx && !(p->n_type & (N_STAB | N_EXT)))      else if (p->n_un.n_strx && !(p->n_type & (N_STAB | N_EXT)))
Line 1349  enter_file_symbols (entry) Line 1654  enter_file_symbols (entry)
       }        }
     else debugger_sym_count++;      else debugger_sym_count++;
   
 #if 0     #if 0
   entry->set_vector_offset = lowest_set_vector;    entry->set_vector_offset = lowest_set_vector;
 #endif  #endif
   
Line 1389  enter_global_ref (nlist_p, name, entry) Line 1694  enter_global_ref (nlist_p, name, entry)
   if (type != (N_UNDF | N_EXT) || nlist_p->n_value)    if (type != (N_UNDF | N_EXT) || nlist_p->n_value)
     {      {
       sp->defined = 1;        sp->defined = 1;
       if (oldref && !olddef) undefined_global_sym_count--;        if (oldref && !olddef)
           undefined_global_sym_count--;
       /* If this is a common definition, keep track of largest        /* If this is a common definition, keep track of largest
          common definition seen for this symbol.  */           common definition seen for this symbol.  */
       if (type == (N_UNDF | N_EXT)        if (type == (N_UNDF | N_EXT)
Line 1408  enter_global_ref (nlist_p, name, entry) Line 1714  enter_global_ref (nlist_p, name, entry)
         }          }
     }      }
   else    else
     if (!oldref) undefined_global_sym_count++;      if (!oldref)
   #ifndef DOLLAR_KLUDGE
         undefined_global_sym_count++;
   #else
         {
           if (entry->superfile && type == (N_UNDF | N_EXT) && name[1] == '$')
             {
               /* This is an (ISI?) $-conditional; skip it */
               sp->referenced = 0;
               if (sp->trace)
                 {
                   fprintf (stderr, "symbol %s is a $-conditional ignored in ", sp->name);
                   print_file_name (entry, stderr);
                   fprintf (stderr, "\n");
                 }
               return;
             }
           else
             undefined_global_sym_count++;
         }
   #endif
   
   if (sp == end_symbol && entry->just_syms_flag && !T_flag_specified)    if (sp == end_symbol && entry->just_syms_flag && !T_flag_specified)
     text_start = nlist_p->n_value;      text_start = nlist_p->n_value;
Line 1443  enter_global_ref (nlist_p, name, entry) Line 1769  enter_global_ref (nlist_p, name, entry)
         case N_SETT:          case N_SETT:
           reftype = "is a text set element";            reftype = "is a text set element";
           break;            break;
             
         case N_SETD:          case N_SETD:
           reftype = "is a data set element";            reftype = "is a data set element";
           break;            break;
             
         case N_SETB:          case N_SETB:
           reftype = "is a BSS set element";            reftype = "is a BSS set element";
           break;            break;
             
         case N_SETA:          case N_SETA:
           reftype = "is an absolute set element";            reftype = "is an absolute set element";
           break;            break;
Line 1459  enter_global_ref (nlist_p, name, entry) Line 1785  enter_global_ref (nlist_p, name, entry)
         case N_SETV:          case N_SETV:
           reftype = "defined in text section as vector";            reftype = "defined in text section as vector";
           break;            break;
             
         case N_INDR:          case N_INDR:
           reftype = (char *) alloca (23            reftype = (char *) alloca (23
                                      + strlen ((nlist_p + 1)->n_un.n_strx                                       + strlen ((nlist_p + 1)->n_un.n_strx
Line 1564  decode_library_subfile (desc, library_en Line 1890  decode_library_subfile (desc, library_en
   
   for (namelen = 0;    for (namelen = 0;
        namelen < sizeof hdr1.ar_name         namelen < sizeof hdr1.ar_name
        && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' ';         && hdr1.ar_name[namelen] != 0 && hdr1.ar_name[namelen] != ' '
          && hdr1.ar_name[namelen] != '/';
        namelen++);         namelen++);
   
   name = (char *) xmalloc (namelen+1);    name = (char *) xmalloc (namelen+1);
Line 1783  subfile_wanted_p (entry) Line 2110  subfile_wanted_p (entry)
   register struct nlist *p;    register struct nlist *p;
   register struct nlist *end    register struct nlist *end
     = entry->symbols + entry->header.a_syms / sizeof (struct nlist);      = entry->symbols + entry->header.a_syms / sizeof (struct nlist);
   #ifdef DOLLAR_KLUDGE
     register int dollar_cond = 0;
   #endif
   
   for (p = entry->symbols; p < end; p++)    for (p = entry->symbols; p < end; p++)
     {      {
       register int type = p->n_type;        register int type = p->n_type;
         register char *name = p->n_un.n_strx + entry->strings;
   
       if (type & N_EXT && (type != (N_UNDF | N_EXT) || p->n_value))        if (type & N_EXT && (type != (N_UNDF | N_EXT) || p->n_value
   #ifdef DOLLAR_KLUDGE
                              || name[1] == '$'
   #endif
                              ))
         {          {
           register char *name = p->n_un.n_strx + entry->strings;  
           register symbol *sp = getsym_soft (name);            register symbol *sp = getsym_soft (name);
   
   #ifdef DOLLAR_KLUDGE
             if (name[1] == '$')
               {
                 sp = getsym_soft (&name[2]);
                 dollar_cond = 1;
                 if (!sp) continue;
                 if (sp->referenced)
                   {
                     if (write_map)
                       {
                         print_file_name (entry, stdout);
                         fprintf (stdout, " needed due to $-conditional %s\n", name);
                       }
                     return 1;
                   }
                 continue;
               }
   #endif
   
           /* If this symbol has not been hashed, we can't be looking for it. */            /* If this symbol has not been hashed, we can't be looking for it. */
   
           if (!sp) continue;            if (!sp) continue;
Line 1800  subfile_wanted_p (entry) Line 2153  subfile_wanted_p (entry)
           if (sp->referenced && !sp->defined)            if (sp->referenced && !sp->defined)
             {              {
               /* This is a symbol we are looking for.  */                /* This is a symbol we are looking for.  */
   #ifdef DOLLAR_KLUDGE
                 if (dollar_cond) continue;
   #endif
               if (type == (N_UNDF | N_EXT))                if (type == (N_UNDF | N_EXT))
                 {                  {
                   /* Symbol being defined as common.                    /* Symbol being defined as common.
Line 1855  digest_symbols () Line 2211  digest_symbols ()
     {      {
       set_sect_size =        set_sect_size =
         (set_symbol_count + set_vector_count) * sizeof (unsigned long);          (set_symbol_count + set_vector_count) * sizeof (unsigned long);
       set_sect_start = text_start + text_size;         set_sect_start = text_start + text_size;
       text_size += set_sect_size;        text_size += set_sect_size;
       set_vectors = (unsigned long *) xmalloc (set_sect_size);        set_vectors = (unsigned long *) xmalloc (set_sect_size);
       setv_fill_count = 0;        setv_fill_count = 0;
Line 1897  digest_symbols () Line 2253  digest_symbols ()
       register symbol *sp;        register symbol *sp;
       for (sp = symtab[i]; sp; sp = sp->link)        for (sp = symtab[i]; sp; sp = sp->link)
         {          {
             /* For each symbol */
           register struct nlist *p, *next;            register struct nlist *p, *next;
           int defs = 0, com = sp->max_common_size, erred = 0;            int defs = 0, com = sp->max_common_size, erred = 0;
           struct nlist *first_definition;            struct nlist *first_definition;
Line 1921  digest_symbols () Line 2278  digest_symbols ()
                   else if ((sp->defined & ~N_EXT) != N_SETV)                    else if ((sp->defined & ~N_EXT) != N_SETV)
                     {                      {
                       make_executable = 0;                        make_executable = 0;
                       error ("text symbol %s redifined as set vector.  Files:",                        error ("text symbol `%s' redefined as set vector.  Files:",
                              sp->name);                               sp->name);
                       print_files_defining_symbol (first_definition, p);                        print_files_defining_symbol (first_definition, p);
                     }                      }
Line 1934  digest_symbols () Line 2291  digest_symbols ()
                     if (!erred++)                      if (!erred++)
                       {                        {
                         make_executable = 0;                          make_executable = 0;
                         error ("multiple definitions of symbol %s. Files:",                          error ("multiple definitions of symbol `%s'.  Files:",
                                sp->name);                                 sp->name);
                         print_files_defining_symbol (first_definition, p);                          print_files_defining_symbol (first_definition, p);
                       }                        }
Line 1951  digest_symbols () Line 2308  digest_symbols ()
               if (!relocatable_output || force_common_definition)                if (!relocatable_output || force_common_definition)
                 {                  {
                   com = (com + sizeof (int) - 1) & (- sizeof (int));                    com = (com + sizeof (int) - 1) & (- sizeof (int));
       
                   sp->value = data_start + data_size + bss_size;                    sp->value = data_start + data_size + bss_size;
                   sp->defined = N_BSS | N_EXT;                    sp->defined = N_BSS | N_EXT;
                   bss_size += com;                    bss_size += com;
Line 1970  digest_symbols () Line 2327  digest_symbols ()
             {              {
               unsigned long length_word_index =                unsigned long length_word_index =
                 (sp->value - set_sect_start) / sizeof (unsigned long);                  (sp->value - set_sect_start) / sizeof (unsigned long);
                 
               set_vectors[length_word_index] = setv_fill_count - 1 - length_word_index;                set_vectors[length_word_index] = setv_fill_count - 1 - length_word_index;
             }                       }
           if (sp->defined)            if (sp->defined)
             defined_global_sym_count++;              defined_global_sym_count++;
         }          }
Line 2055  relocate_file_addresses (entry) Line 2412  relocate_file_addresses (entry)
         /* If this belongs to a section, update it by the section's start address */          /* If this belongs to a section, update it by the section's start address */
         register int type = p->n_type & N_TYPE;          register int type = p->n_type & N_TYPE;
   
         switch (type) {          switch (type)
         case N_TEXT:            {
         case N_SETV:            case N_TEXT:
         case N_SETT:            case N_SETV:
           p->n_value += entry->text_start_address;            case N_SETT:
           break;              p->n_value += entry->text_start_address;
         case N_DATA:              break;
         case N_SETD:            case N_DATA:
           /* A symbol whose value is in the data section            case N_SETD:
              is present in the input file as if the data section              /* A symbol whose value is in the data section
              started at an address equal to the length of the file's text.  */                 is present in the input file as if the data section
           p->n_value += entry->data_start_address - entry->header.a_text;                 started at an address equal to the length of the file's text.  */
           break;              p->n_value += entry->data_start_address - entry->header.a_text;
         case N_BSS:              break;
         case N_SETB:            case N_BSS:
           /* likewise for symbols with value in BSS.  */            case N_SETB:
           p->n_value += entry->bss_start_address              /* likewise for symbols with value in BSS.  */
                          - entry->header.a_text - entry->header.a_data;              p->n_value += entry->bss_start_address
           break;                - entry->header.a_text - entry->header.a_data;
         }              break;
             }
       }        }
   }    }
 }  }
Line 2143  list_file_locals (entry, outfile) Line 2501  list_file_locals (entry, outfile)
   fprintf (outfile, ":\n\n");    fprintf (outfile, ":\n\n");
   
   for (p = entry->symbols; p < end; p++)    for (p = entry->symbols; p < end; p++)
     /* If this is a definition,       /* If this is a definition,
        update it if necessary by this file's start address.  */         update it if necessary by this file's start address.  */
     if (!(p->n_type & (N_STAB | N_EXT)))      if (!(p->n_type & (N_STAB | N_EXT)))
       fprintf (outfile, "  %s: 0x%x\n",        fprintf (outfile, "  %s: 0x%x\n",
                entry->strings + p->n_un.n_strx, p->n_value);                 entry->strings + p->n_un.n_strx, p->n_value);
 }  }
   
 /* Print on OUTFILE a list of all of the references to undefined  
    global symbols.  Assume that there will not be any if  /* Static vars for do_warnings and subroutines of it */
    undefined_global_sym_count is null.  If it isn't we have an error,  int list_unresolved_refs;       /* List unresolved refs */
    so clear `make_executable'. */  int list_warning_symbols;       /* List warning syms */
 void  int list_multple_defs;          /* List multiple definitions */
 list_undefined_symbols (outfile)  
      FILE *outfile;  
 {  
   if (undefined_global_sym_count) {  
     each_full_file (list_unresolved_references, outfile);  
     fprintf (outfile, "\n");  
     make_executable = 0;  
   }  
 }  
   
 /*  /*
  * Structure for communication between list_unresolved refs and it's   * Structure for communication between do_file_warnings and it's
  * helper routines.  Will in practice be an array of three of these:   * helper routines.  Will in practice be an array of three of these:
  * 0) Current line, 1) Next line, 2) Source file info.   * 0) Current line, 1) Next line, 2) Source file info.
  */   */
 struct line_debug_entry {  struct line_debug_entry
   {
   int line;    int line;
   char *filename;    char *filename;
   struct nlist *sym;    struct nlist *sym;
Line 2183  int next_debug_entry (); Line 2533  int next_debug_entry ();
 int address_to_line ();  int address_to_line ();
 int relocation_entries_relation ();  int relocation_entries_relation ();
   
 /* Print on OUTFILE a list of all references to undefined global  /* Print on OUTFILE a list of all warnings generated by references
    symbols in the file ENTRY.  List source file and line number if     and/or definitions in the file ENTRY.  List source file and line
    possible, just the .o file if not. */     number if possible, just the .o file if not. */
   
 void  void
 list_unresolved_references (entry, outfile)  do_file_warnings (entry, outfile)
      struct file_entry *entry;       struct file_entry *entry;
      FILE *outfile;       FILE *outfile;
 {  {
   struct relocation_info *txt_reloc, *data_reloc;    struct relocation_info *txt_reloc, *data_reloc;
   struct line_debug_entry *state_pointer;    struct line_debug_entry *state_pointer;
   register struct line_debug_entry *current, *next, *source;    register struct line_debug_entry *current, *next, *source;
     char *errfmt;                         /* Assigned to generally */
                                           /* static values; should not */
                                           /* be written into */
     char *errmsg;                         /* Assigned to malloc'd values */
                                           /* and copied into; should be */
                                           /* freed when done */
     int invalidate_line_number;
   
   /* Read in the files strings if they aren't available */    /* Read in the files strings if they aren't available */
   if (!entry->strings) {    if (!entry->strings)
     int desc;      {
             int desc;
     entry->strings = (char *) alloca (entry->string_size);  
     desc = file_open (entry);        entry->strings = (char *) alloca (entry->string_size);
     read_entry_strings (desc, entry);        desc = file_open (entry);
   }        read_entry_strings (desc, entry);
       }
   
   state_pointer = init_debug_scan (0, entry);    state_pointer = init_debug_scan (0, entry);
   current = state_pointer;    current = state_pointer;
   next = state_pointer + 1;    next = state_pointer + 1;
   source = state_pointer + 2;    source = state_pointer + 2;
     
   read_file_relocation (entry);    read_file_relocation (entry);
   
   /* We need to sort the relocation info here.  Sheesh, so much effort    /* We need to sort the relocation info here.  Sheesh, so much effort
Line 2227  list_unresolved_references (entry, outfi Line 2585  list_unresolved_references (entry, outfi
     {      {
       register struct nlist *s;        register struct nlist *s;
       register symbol *g;        register symbol *g;
         
       if (!txt_reloc->r_extern) continue;        /* If the relocation isn't resolved through a symbol, continue */
       s = &(entry->symbols[txt_reloc->r_symbolnum]);        if (!RELOC_EXTERN_P(txt_reloc))
           continue;
   
         s = &(entry->symbols[RELOC_SYMBOL(txt_reloc)]);
   
         /* Local symbols shouldn't ever be used by relocation info, so
            the next should be safe.
            This is, of course, wrong.  References to local BSS symbols can be
            the targets of relocation info, and they can (must) be
            resolved through symbols.  However, these must be defined properly,
            (the compiler would have caught it otherwise), so we can
            ignore these cases.  */
         if (!(s->n_type & N_EXT))
           continue;
   
       g = (symbol *) s->n_un.n_name;        g = (symbol *) s->n_un.n_name;
       if (s->n_type & N_EXT && !g->defined)  
         if (!g->defined)                       /* Reference */
         {          {
           if (g->undef_refs < MAX_UREFS_PRINTED)            if (!list_unresolved_refs ||               /* Don't list any */
                 g->undef_refs >= MAX_UREFS_PRINTED)    /* Listed too many */
               continue;
   
             /* Undefined symbol which we should mention */
   
             if (++(g->undef_refs) == MAX_UREFS_PRINTED)
             {              {
               address_to_line (txt_reloc->r_address + entry->text_start_address,                errfmt = "More undefined symbol %s refs follow";
                                state_pointer);                invalidate_line_number = 1;
               g->undef_refs++;              }
               if (g->undef_refs == MAX_UREFS_PRINTED)            else
                 {              {
                   if (current->line >=0)                errfmt = "Undefined symbol %s referenced from text";
                     fprintf (outfile, "%s:0:More undefined symbol %s refs follow\n",                invalidate_line_number = 0;
                              current->filename, g->name);  
                   else  
                     fprintf (outfile, "%s: More undefined symbol %s refs follow\n",  
                              current->filename, g->name);  
                 }  
               else  
                 {  
                   if (current->line >= 0)  
                     fprintf (outfile, "%s:%d: Undefined symbol %s referenced from text\n",  
                              current->filename, current->line, g->name);  
                   else  
                     fprintf (outfile, "%s: Undefined symbol %s referenced from text\n",  
                              current->filename, g->name);  
                 }  
             }              }
         }          }
     }        else                                           /* Defined */
           {
             /* Potential symbol warning here */
             if (!g->warning) continue;
   
             errfmt = g->warning;
             invalidate_line_number = 0;
           }
               
         errmsg = (char *) xmalloc (strlen (errfmt) + strlen (g->name) + 1);
         sprintf(errmsg, errfmt, g->name);
         address_to_line ( (RELOC_ADDRESS (txt_reloc)
                            + entry->text_start_address),
                          state_pointer);
   
         if (current->line >=0)
           fprintf (outfile, "%s:%d: %s\n", current->filename,
                    invalidate_line_number ? 0 : current->line, errmsg);
         else
           fprintf (outfile, "%s: %s\n", current->filename, errmsg);
   
         free (errmsg);
       }
   
   free (state_pointer);    free (state_pointer);
   state_pointer = init_debug_scan (1, entry);    state_pointer = init_debug_scan (1, entry);
   current = state_pointer;    current = state_pointer;
Line 2282  list_unresolved_references (entry, outfi Line 2669  list_unresolved_references (entry, outfi
     {      {
       register struct nlist *s;        register struct nlist *s;
       register symbol *g;        register symbol *g;
         
       if (!data_reloc->r_extern) continue;        /* If the relocation isn't resolved through a symbol, continue */
       s = &(entry->symbols[data_reloc->r_symbolnum]);        if (!RELOC_EXTERN_P(data_reloc))
           continue;
   
         s = &(entry->symbols[RELOC_SYMBOL(data_reloc)]);
       g = (symbol *) s->n_un.n_name;        g = (symbol *) s->n_un.n_name;
       if (s->n_type & N_EXT && !g->defined)  
         if (!g->defined)                       /* Reference */
         {          {
           address_to_line (data_reloc->r_address + entry->data_start_address,            if (!list_unresolved_refs ||               /* Don't list any */
                            state_pointer);                g->undef_refs >= MAX_UREFS_PRINTED)    /* Listed too many */
           if (current->line >= 0)              continue;
             fprintf (outfile, "%s:%d: Undefined symbol %s referenced from data\n",  
                      current->filename, current->line, g->name);            /* Undefined symbol which we should mention */
   
             if (++(g->undef_refs) == MAX_UREFS_PRINTED)
               {
                 errfmt = "More undefined symbol %s refs follow";
                 invalidate_line_number = 1;
               }
           else            else
             fprintf (outfile, "%s: Undefined symbol %s referenced from data\n",              {
                      current->filename, g->name);                errfmt = "Undefined symbol %s referenced from data";
                 invalidate_line_number = 0;
               }
           }
         else                                           /* Defined */
           {
             /* Potential symbol warning here */
             if (!g->warning) continue;
   
             errfmt = g->warning;
             invalidate_line_number = 0;
         }          }
         
         errmsg = (char *) xmalloc (strlen (errfmt) + strlen (g->name) + 1);
         sprintf(errmsg, errfmt, g->name);
         address_to_line ( (RELOC_ADDRESS (data_reloc)
                            + entry->text_start_address),
                          state_pointer);
   
         if (current->line >=0)
           fprintf (outfile, "%s:%d: %s\n", current->filename,
                    invalidate_line_number ? 0 : current->line, errmsg);
         else
           fprintf (outfile, "%s: %s\n", current->filename, errmsg);
   
         free (errmsg);
     }      }
 }  }
 /*  /*
  * Helper routines for list_unresolved references.   * Helper routines for do_file_warnings.
  */   */
   
 /*  /*
Line 2312  int Line 2733  int
 relocation_entries_relation (rel1, rel2)  relocation_entries_relation (rel1, rel2)
      struct relocation_info *rel1, *rel2;       struct relocation_info *rel1, *rel2;
 {  {
   return rel1->r_address - rel2->r_address;    return RELOC_ADDRESS(rel1) - RELOC_ADDRESS(rel2);
 }  }
   
 /*  /*
Line 2335  next_debug_entry (use_data_symbols, stat Line 2756  next_debug_entry (use_data_symbols, stat
   
   current->sym = next->sym;    current->sym = next->sym;
   current->line = next->line;    current->line = next->line;
   current->filename = next->filename;               current->filename = next->filename;
   
   while (++(next->sym) < (entry->symbols    while (++(next->sym) < (entry->symbols
                           + entry->header.a_syms/sizeof (struct nlist)))                            + entry->header.a_syms/sizeof (struct nlist)))
     {      {
       switch (next->sym->n_type)                        switch (next->sym->n_type)
         {                                                         {
         case N_SLINE:          case N_SLINE:
           if (use_data_symbols) continue;            if (use_data_symbols) continue;
           next->line = next->sym->n_desc;            next->line = next->sym->n_desc;
           return 1;            return 1;
         case N_DSLNE:          case N_DSLINE:
           if (!use_data_symbols) continue;            if (!use_data_symbols) continue;
           next->line = next->sym->n_desc;            next->line = next->sym->n_desc;
           return 1;            return 1;
         case N_EINCL:                             #ifdef HAVE_SUN_STABS
           next->filename = source->filename;                      case N_EINCL:
           continue;                                         next->filename = source->filename;
         case N_SO:                                          continue;
   #endif
           case N_SO:
           source->filename = next->sym->n_un.n_strx + entry->strings;            source->filename = next->sym->n_un.n_strx + entry->strings;
           source->line++;            source->line++;
         case N_BINCL:                             #ifdef HAVE_SUN_STABS
         case N_SOL:                                       case N_BINCL:
           next->filename =                        #endif
           case N_SOL:
             next->filename =
             next->sym->n_un.n_strx + entry->strings;              next->sym->n_un.n_strx + entry->strings;
         default:                                                  default:
           continue;                                         continue;
         }                                                         }
     }                                                 }
   next->sym = (struct nlist *) 0;    next->sym = (struct nlist *) 0;
   return 0;    return 0;
 }  }
     
 int  int
 address_to_line (address, state_pointer)  address_to_line (address, state_pointer)
      unsigned long address;       unsigned long address;
Line 2376  address_to_line (address, state_pointer) Line 2801  address_to_line (address, state_pointer)
   struct line_debug_entry    struct line_debug_entry
     *current = state_pointer,      *current = state_pointer,
     *next = state_pointer + 1;      *next = state_pointer + 1;
     
   int use_data_symbols;    int use_data_symbols;
   
   if (next->sym)    if (next->sym)
     use_data_symbols = (next->sym->n_type & N_TYPE) == N_DATA;      use_data_symbols = (next->sym->n_type & N_TYPE) == N_DATA;
     
   while (next->sym    while (next->sym
          && next->sym->n_value < address           && next->sym->n_value < address
          && next_debug_entry (use_data_symbols, state_pointer))           && next_debug_entry (use_data_symbols, state_pointer))
Line 2408  init_debug_scan (use_data_symbols, entry Line 2833  init_debug_scan (use_data_symbols, entry
        tmp < (entry->symbols         tmp < (entry->symbols
               + entry->header.a_syms/sizeof (struct nlist));                + entry->header.a_syms/sizeof (struct nlist));
        tmp++)         tmp++)
     if (tmp->n_type == N_SO) break;      if (tmp->n_type == (int) N_SO) break;
   
   if (tmp >= (entry->symbols    if (tmp >= (entry->symbols
               + entry->header.a_syms/sizeof (struct nlist))) {                + entry->header.a_syms/sizeof (struct nlist)))
     /* I believe this translates to "We loose" */      {
     current->filename = next->filename = entry->filename;        /* I believe this translates to "We lose" */
     current->line = next->line = -1;        current->filename = next->filename = entry->filename;
     current->sym = next->sym = (struct nlist *) 0;        current->line = next->line = -1;
     return state_pointer;        current->sym = next->sym = (struct nlist *) 0;
   }        return state_pointer;
       }
   
   next->line = source->line = 0;    next->line = source->line = 0;
   next->filename = source->filename = (tmp->n_un.n_strx    next->filename = source->filename
                       + entry->strings);      = (tmp->n_un.n_strx + entry->strings);
   source->sym = (struct nlist *) entry;    source->sym = (struct nlist *) entry;
   next->sym = tmp;    next->sym = tmp;
   
Line 2442  init_debug_scan (use_data_symbols, entry Line 2868  init_debug_scan (use_data_symbols, entry
         }          }
       return state_pointer;        return state_pointer;
     }      }
           
     
   next_debug_entry (use_data_symbols, state_pointer); /* To setup current */    next_debug_entry (use_data_symbols, state_pointer); /* To setup current */
   
   return state_pointer;    return state_pointer;
 }  }
   
   void 
   mark_flagged_symbols (entry, outfile)
        struct file_entry *entry;
        FILE *outfile;
   {
     struct nlist *p;
       
     if (!entry->warning) return;
   
     for (p = entry->symbols;
          p < entry->symbols + (entry->header.a_syms / sizeof(struct nlist));
          p++)
       {
         unsigned char type = p->n_type;
         struct glosym *sym;
         
        /* Ignore locals and references */
         if (!(type & N_EXT) || type == N_EXT) continue;
   
         sym = (struct glosym *) p->n_un.n_name;
         if (sym->referenced)
           ((struct glosym *) p->n_un.n_name)->warning = entry->warning;
       }
   }
   
   do_warnings (outfile)
        FILE *outfile;
   {
     struct glosym **clrefs;
   
     list_unresolved_refs = !relocatable_output && undefined_global_sym_count;
     list_warning_symbols = warning_count;
     list_multple_defs = 0;                /* Not currently done here */
   
     if (!(list_unresolved_refs ||
           list_warning_symbols ||
           list_multple_defs      ))
       /* No need to run this routine */
       return;
   
     if (list_warning_symbols)
       each_full_file (mark_flagged_symbols, outfile);
   
     each_full_file (do_file_warnings, outfile);
   
     if (!relocatable_output)
       for (clrefs = cmdline_references;
            clrefs < cmdline_references + cl_refs_allocated && *clrefs;
            clrefs++)
         if ((*clrefs)->referenced && !(*clrefs)->defined)
           fprintf(stderr, "Error: Unresolved reference to symbol %s\n",
                   (*clrefs)->name);
   
     fprintf (outfile, "\n");
   
     if (list_unresolved_refs || list_multple_defs)
       make_executable = 0;
   }
   
 /* Print the files which have the definitions for a given symbol.  /* Print the files which have the definitions for a given symbol.
    FIRST_DEF is the first nlist entry which defines the symbol, and     FIRST_DEF is the first nlist entry which defines the symbol, and
    REST_OF_REFS is a chain of nlist entries which may or may not be     REST_OF_REFS is a chain of nlist entries which may or may not be
    definitions for this symbol, but which are all references for the     definitions for this symbol, but which are all references for the
    symbol.      symbol.
   
    We do the job in this clumsy fashion because of the state our data     We do the job in this clumsy fashion because of the state our data
    structures are in in the middle of digest_symbols (from which this     structures are in in the middle of digest_symbols (from which this
Line 2465  print_files_defining_symbol (first_def,  Line 2950  print_files_defining_symbol (first_def, 
 {  {
   struct file_entry *holder;    struct file_entry *holder;
   struct nlist *n_ptr;    struct nlist *n_ptr;
     
   if (holder =    if (holder =
       (struct file_entry *) check_each_file (contains_symbol, first_def))        (struct file_entry *) check_each_file (contains_symbol, first_def))
     {      {
Line 2489  print_files_defining_symbol (first_def,  Line 2974  print_files_defining_symbol (first_def, 
         fatal ("internal: file not found containing nlist entry");          fatal ("internal: file not found containing nlist entry");
 }  }
   
 /* Write the output file */   /* Write the output file */
   
 void  void
 write_output ()  write_output ()
Line 2535  void Line 3020  void
 write_header ()  write_header ()
 {  {
   outheader.a_magic = magic;    outheader.a_magic = magic;
 #ifdef INITIALIZE_HEADER  
   INITIALIZE_HEADER;  
 #endif  
   outheader.a_text = text_size;    outheader.a_text = text_size;
   outheader.a_data = data_size;    outheader.a_data = data_size;
   outheader.a_bss = bss_size;    outheader.a_bss = bss_size;
   outheader.a_entry = (entry_symbol ? entry_symbol->value    outheader.a_entry = (entry_symbol ? entry_symbol->value
                        : text_start + entry_offset);                         : text_start + entry_offset);
   #ifdef COFF_ENCAPSULATE
     if (need_coff_header)
       {
         /* We are encapsulating BSD format within COFF format.  */
         struct coffscn *tp, *dp, *bp;
   
         tp = &coffheader.scns[0];
         dp = &coffheader.scns[1];
         bp = &coffheader.scns[2];
   
         strcpy (tp->s_name, ".text");
         tp->s_paddr = text_start;
         tp->s_vaddr = text_start;
         tp->s_size = text_size;
         tp->s_scnptr = sizeof (struct coffheader) + sizeof (struct exec);
         tp->s_relptr = 0;
         tp->s_lnnoptr = 0;
         tp->s_nreloc = 0;
         tp->s_nlnno = 0;
         tp->s_flags = 0x20;
         strcpy (dp->s_name, ".data");
         dp->s_paddr = data_start;
         dp->s_vaddr = data_start;
         dp->s_size = data_size;
         dp->s_scnptr = tp->s_scnptr + tp->s_size;
         dp->s_relptr = 0;
         dp->s_lnnoptr = 0;
         dp->s_nreloc = 0;
         dp->s_nlnno = 0;
         dp->s_flags = 0x40;
         strcpy (bp->s_name, ".bss");
         bp->s_paddr = dp->s_vaddr + dp->s_size;
         bp->s_vaddr = bp->s_paddr;
         bp->s_size = bss_size;
         bp->s_scnptr = 0;
         bp->s_relptr = 0;
         bp->s_lnnoptr = 0;
         bp->s_nreloc = 0;
         bp->s_nlnno = 0;
         bp->s_flags = 0x80;
   
         coffheader.f_magic = COFF_MAGIC;
         coffheader.f_nscns = 3;
         coffheader.f_timdat = 0;
         coffheader.f_symptr = 0;
         coffheader.f_nsyms = 0;
         coffheader.f_opthdr = 28;
         coffheader.f_flags = 0x103;
         /* aouthdr */
         coffheader.magic = ZMAGIC;
         coffheader.vstamp = 0;
         coffheader.tsize = tp->s_size;
         coffheader.dsize = dp->s_size;
         coffheader.bsize = bp->s_size;
         coffheader.entry = outheader.a_entry;
         coffheader.text_start = tp->s_vaddr;
         coffheader.data_start = dp->s_vaddr;
       }
   #endif
   
   #ifdef INITIALIZE_HEADER
     INITIALIZE_HEADER;
   #endif
   
   if (strip_symbols == STRIP_ALL)    if (strip_symbols == STRIP_ALL)
     nsyms = 0;      nsyms = 0;
Line 2575  write_header () Line 3120  write_header ()
       outheader.a_drsize = 0;        outheader.a_drsize = 0;
     }      }
   
   #ifdef COFF_ENCAPSULATE
     if (need_coff_header)
       mywrite (&coffheader, sizeof coffheader, 1, outdesc);
   #endif
   mywrite (&outheader, sizeof (struct exec), 1, outdesc);    mywrite (&outheader, sizeof (struct exec), 1, outdesc);
   
   /* Output whatever padding is required in the executable file    /* Output whatever padding is required in the executable file
      between the header and the start of the text.  */       between the header and the start of the text.  */
   
   #ifndef COFF_ENCAPSULATE
   padfile (N_TXTOFF (outheader) - sizeof outheader, outdesc);    padfile (N_TXTOFF (outheader) - sizeof outheader, outdesc);
   #endif
 }  }
   
 /* Relocate the text segment of each input file  /* Relocate the text segment of each input file
Line 2596  write_text () Line 3147  write_text ()
   file_close ();    file_close ();
   
   /* Write out the set element vectors */    /* Write out the set element vectors */
     
   if (set_vector_count)    if (set_vector_count)
     mywrite (set_vectors, set_symbol_count + set_vector_count, sizeof (unsigned long), outdesc);      mywrite (set_vectors, set_symbol_count + set_vector_count, sizeof (unsigned long), outdesc);
   
Line 2630  read_file_relocation (entry) Line 3181  read_file_relocation (entry)
   register struct relocation_info *reloc;    register struct relocation_info *reloc;
   int desc;    int desc;
   int read_return;    int read_return;
     
   desc = -1;    desc = -1;
   if (!entry->textrel)    if (!entry->textrel)
     {      {
Line 2647  read_file_relocation (entry) Line 3198  read_file_relocation (entry)
       entry->textrel = reloc;        entry->textrel = reloc;
     }      }
   
   if (!entry->datarel)     if (!entry->datarel)
     {      {
       reloc = (struct relocation_info *) xmalloc (entry->header.a_drsize);        reloc = (struct relocation_info *) xmalloc (entry->header.a_drsize);
       if (desc == -1) desc = file_open (entry);        if (desc == -1) desc = file_open (entry);
Line 2656  read_file_relocation (entry) Line 3207  read_file_relocation (entry)
              + entry->header.a_data + entry->header.a_trsize,               + entry->header.a_data + entry->header.a_trsize,
              L_SET);               L_SET);
       if (entry->header.a_drsize != read (desc, reloc, entry->header.a_drsize))        if (entry->header.a_drsize != read (desc, reloc, entry->header.a_drsize))
         fatal_with_file ("premature eof in text relocatino of ", entry);          fatal_with_file ("premature eof in text relocation of ", entry);
       entry->datarel = reloc;        entry->datarel = reloc;
     }      }
 }  }
         
 /* Read the text segment contents of ENTRY, relocate them,  /* Read the text segment contents of ENTRY, relocate them,
    and write the result to the output file.     and write the result to the output file.
    If `-r', save the text relocation for later reuse.  */     If `-r', save the text relocation for later reuse.  */
Line 2683  copy_text (entry) Line 3234  copy_text (entry)
   bytes = (char *) alloca (entry->header.a_text);    bytes = (char *) alloca (entry->header.a_text);
   
   /* Deal with relocation information however is appropriate */    /* Deal with relocation information however is appropriate */
     
   if (entry->textrel)  reloc = entry->textrel;    if (entry->textrel)  reloc = entry->textrel;
   else if (relocatable_output)    else if (relocatable_output)
     {      {
Line 2752  copy_data (entry) Line 3303  copy_data (entry)
   desc = file_open (entry);    desc = file_open (entry);
   
   bytes = (char *) alloca (entry->header.a_data);    bytes = (char *) alloca (entry->header.a_data);
     
   if (entry->datarel) reloc = entry->datarel;    if (entry->datarel) reloc = entry->datarel;
   else if (relocatable_output)  /* Will need this again */    else if (relocatable_output)  /* Will need this again */
     {      {
Line 2768  copy_data (entry) Line 3319  copy_data (entry)
       if (entry->header.a_drsize != read (desc, reloc, entry->header.a_drsize))        if (entry->header.a_drsize != read (desc, reloc, entry->header.a_drsize))
         fatal_with_file ("premature eof in data relocation of ", entry);          fatal_with_file ("premature eof in data relocation of ", entry);
     }      }
     
   lseek (desc, text_offset (entry) + entry->header.a_text, 0);    lseek (desc, text_offset (entry) + entry->header.a_text, 0);
   if (entry->header.a_data != read (desc, bytes, entry->header.a_data))    if (entry->header.a_data != read (desc, bytes, entry->header.a_data))
     fatal_with_file ("premature eof in data section of ", entry);      fatal_with_file ("premature eof in data section of ", entry);
Line 2786  copy_data (entry) Line 3337  copy_data (entry)
      in the output file and its address in the input file.       in the output file and its address in the input file.
    RELOC_INFO is the address of the relocation info, in core.     RELOC_INFO is the address of the relocation info, in core.
    RELOC_SIZE is its length in bytes.  */     RELOC_SIZE is its length in bytes.  */
   /* This version is about to be severley hacked by Randy.  Hope it
      works afterwards. */
 void  void
 perform_relocation (data, pc_relocation, data_size, reloc_info, reloc_size, entry)  perform_relocation (data, pc_relocation, data_size, reloc_info, reloc_size, entry)
      char *data;       char *data;
Line 2807  perform_relocation (data, pc_relocation, Line 3359  perform_relocation (data, pc_relocation,
   for (; p < end; p++)    for (; p < end; p++)
     {      {
       register int relocation = 0;        register int relocation = 0;
       register int addr = p->r_address;        register int addr = RELOC_ADDRESS(p);
       register int symbolnum = p->r_symbolnum;        register unsigned int mask = 0;
       register int length = p->r_length;  
   
       if (addr >= data_size)        if (addr >= data_size)
         fatal_with_file ("relocation address out of range in ", entry);          fatal_with_file ("relocation address out of range in ", entry);
       if (p->r_extern)  
         if (RELOC_EXTERN_P(p))
         {          {
           int symindex = symbolnum * sizeof (struct nlist);            int symindex = RELOC_SYMBOL (p) * sizeof (struct nlist);
           symbol *sp = ((symbol *)            symbol *sp = ((symbol *)
                         (((struct nlist *)                          (((struct nlist *)
                           (((char *)entry->symbols) + symindex))                            (((char *)entry->symbols) + symindex))
                          ->n_un.n_name));                           ->n_un.n_name));
   
   #ifdef N_INDR
           /* Resolve indirection */            /* Resolve indirection */
           if ((sp->defined & ~N_EXT) == N_INDR)            if ((sp->defined & ~N_EXT) == N_INDR)
             sp = (symbol *) sp->value;              sp = (symbol *) sp->value;
   #endif
   
           if (symindex >= entry->header.a_syms)            if (symindex >= entry->header.a_syms)
             fatal_with_file ("relocation symbolnum out of range in ", entry);              fatal_with_file ("relocation symbolnum out of range in ", entry);
Line 2834  perform_relocation (data, pc_relocation, Line 3388  perform_relocation (data, pc_relocation,
           else            else
             relocation = sp->value;              relocation = sp->value;
         }          }
       else switch (symbolnum)        else switch (RELOC_TYPE(p))
         {          {
         case N_TEXT:          case N_TEXT:
         case N_TEXT | N_EXT:          case N_TEXT | N_EXT:
Line 2865  perform_relocation (data, pc_relocation, Line 3419  perform_relocation (data, pc_relocation,
           fatal_with_file ("nonexternal relocation code invalid in ", entry);            fatal_with_file ("nonexternal relocation code invalid in ", entry);
         }          }
   
       if (p->r_pcrel)        if (RELOC_PCREL_P(p))
         relocation -= pc_relocation;          relocation -= pc_relocation;
   
       switch (length)  #ifdef RELOC_ADD_EXTRA
         relocation += RELOC_ADD_EXTRA(p);
   #endif
   
         relocation >>= RELOC_VALUE_RIGHTSHIFT(p);
   
         /* Unshifted mask for relocation */
         mask = 1 << RELOC_TARGET_BITSIZE(p) - 1;
         mask |= mask - 1;
         relocation &= mask;
   
         /* Shift everything up to where it's going to be used */
         relocation <<= RELOC_TARGET_BITPOS(p);
         mask <<= RELOC_TARGET_BITPOS(p);
   
         switch (RELOC_TARGET_SIZE(p))
         {          {
         case 0:          case 0:
           *(char *) (data + addr) += relocation;            if (RELOC_MEMORY_ADD_P(p))
               relocation += mask & *(char *) (data + addr);
             *(char *) (data + addr) &= ~mask;
             *(char *) (data + addr) |= relocation;
           break;            break;
             
         case 1:          case 1:
           *(short *) (data + addr) += relocation;            if (RELOC_MEMORY_ADD_P(p))
               relocation += mask & *(short *) (data + addr);
             *(short *) (data + addr) &= ~mask;
             *(short *) (data + addr) |= relocation;
           break;            break;
             
         case 2:          case 2:
           *(int *) (data + addr) += relocation;            if (RELOC_MEMORY_ADD_P(p))
               relocation += mask & *(long *) (data + addr);
             *(long *) (data + addr) &= ~mask;
             *(long *) (data + addr) |= relocation;
           break;            break;
             
         default:          default:
           fatal_with_file ("invalid relocation field length in ", entry);            fatal_with_file ("Unimplemented relocation field length in ", entry);
         }          }
     }      }
 }  }
Line 2941  coptxtrel (entry) Line 3519  coptxtrel (entry)
   end = (struct relocation_info *) (entry->header.a_trsize + (char *) p);    end = (struct relocation_info *) (entry->header.a_trsize + (char *) p);
   while (p < end)    while (p < end)
     {      {
       p->r_address += reloc;        RELOC_ADDRESS(p) += reloc;
       if (p->r_extern)        if (RELOC_EXTERN_P(p))
         {          {
           register int symindex = p->r_symbolnum * sizeof (struct nlist);            register int symindex = RELOC_SYMBOL(p) * sizeof (struct nlist);
           symbol *symptr = ((symbol *)            symbol *symptr = ((symbol *)
                             (((struct nlist *)                              (((struct nlist *)
                               (((char *)entry->symbols) + symindex))                                (((char *)entry->symbols) + symindex))
Line 2953  coptxtrel (entry) Line 3531  coptxtrel (entry)
           if (symindex >= entry->header.a_syms)            if (symindex >= entry->header.a_syms)
             fatal_with_file ("relocation symbolnum out of range in ", entry);              fatal_with_file ("relocation symbolnum out of range in ", entry);
   
 #if 0  
           /* No longer necessary; not creating N_SETV symbols until we */  
           /* *aren't* doing relocatable output */  
           /* If we are using relocation with a symbol of type set  
              vector, mark it to be assigned to rather than accessed  
              relative.  This means that as the symbol goes through  
              many changes of value (which it can), we don't have to  
              worry about our calculations getting messed up by old values.  */  
   
           if ((symptr->defined & ~N_EXT) == N_SETV) p->r_assign = 1;  
 #endif  
   
           /* If the symbol is now defined, change the external relocation            /* If the symbol is now defined, change the external relocation
              to an internal one.  */               to an internal one.  */
   
           if (symptr->defined            if (symptr->defined)
 #if 0  
               && !(p->r_assign)  
 #endif  
               )  
             {              {
               p->r_extern = 0;                RELOC_EXTERN_P(p) = 0;
               p->r_symbolnum = (symptr->defined & N_TYPE);                RELOC_SYMBOL(p) = (symptr->defined & N_TYPE);
             }              }
           else            else
               p->r_symbolnum = (symptr->def_count + nsyms                RELOC_SYMBOL(p) = (symptr->def_count + nsyms
                                 - defined_global_sym_count                                   - defined_global_sym_count
                                 - undefined_global_sym_count);                                   - undefined_global_sym_count);
         }          }
       p++;        p++;
     }      }
Line 3001  copdatrel (entry) Line 3563  copdatrel (entry)
   end = (struct relocation_info *) (entry->header.a_drsize + (char *) p);    end = (struct relocation_info *) (entry->header.a_drsize + (char *) p);
   while (p < end)    while (p < end)
     {      {
       p->r_address += reloc;        RELOC_ADDRESS(p) += reloc;
       if (p->r_extern)        if (RELOC_EXTERN_P(p))
         {          {
           register int symindex = p->r_symbolnum * sizeof (struct nlist);            register int symindex = RELOC_SYMBOL(p) * sizeof (struct nlist);
           symbol *symptr = ((symbol *)            symbol *symptr = ((symbol *)
                             (((struct nlist *)                              (((struct nlist *)
                               (((char *)entry->symbols) + symindex))                                (((char *)entry->symbols) + symindex))
Line 3016  copdatrel (entry) Line 3578  copdatrel (entry)
           if (force_common_definition            if (force_common_definition
               || symtype == N_DATA || symtype == N_TEXT || symtype == N_ABS)                || symtype == N_DATA || symtype == N_TEXT || symtype == N_ABS)
             {              {
               p->r_extern = 0;                RELOC_EXTERN_P(p) = 0;
               p->r_symbolnum = symtype;                RELOC_SYMBOL(p) = symtype;
             }              }
           else            else
             p->r_symbolnum              RELOC_SYMBOL(p)
               = (((symbol *)                = (((symbol *)
                   (((struct nlist *)                    (((struct nlist *)
                     (((char *)entry->symbols) + symindex))                      (((char *)entry->symbols) + symindex))
Line 3209  write_syms () Line 3771  write_syms ()
                 nl.n_type = N_UNDF | N_EXT;                  nl.n_type = N_UNDF | N_EXT;
                 nl.n_value = 0;                  nl.n_value = 0;
               }                }
             else               else
               fatal ("internal error: %s defined in mysterious way", sp->name);                fatal ("internal error: %s defined in mysterious way", sp->name);
   
             /* Allocate string table space for the symbol name.  */              /* Allocate string table space for the symbol name.  */
Line 3323  write_file_syms (entry, syms_written_add Line 3885  write_file_syms (entry, syms_written_add
         write = relocatable_output;          write = relocatable_output;
       else if (!(type & (N_STAB | N_EXT)))        else if (!(type & (N_STAB | N_EXT)))
         /* ordinary local symbol */          /* ordinary local symbol */
         write = (discard_locals != DISCARD_ALL)          write = ((discard_locals != DISCARD_ALL)
                 && !(discard_locals == DISCARD_L &&                   && !(discard_locals == DISCARD_L &&
                      (p->n_un.n_strx + entry->strings)[0] == 'L');                        (p->n_un.n_strx + entry->strings)[0] == 'L')
                    && type != N_WARNING);
       else if (!(type & N_EXT))        else if (!(type & N_EXT))
         /* debugger symbol */          /* debugger symbol */
         write = (strip_symbols == STRIP_NONE);          write = (strip_symbols == STRIP_NONE);
Line 3358  write_file_syms (entry, syms_written_add Line 3921  write_file_syms (entry, syms_written_add
   
   /* All the symbols are now in BUF; write them.  */    /* All the symbols are now in BUF; write them.  */
   
   lseek (outdesc, symbol_table_offset + symbol_table_len, 0);     lseek (outdesc, symbol_table_offset + symbol_table_len, 0);
   mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);    mywrite (buf, sizeof (struct nlist), bufp - buf, outdesc);
   symbol_table_len += sizeof (struct nlist) * (bufp - buf);    symbol_table_len += sizeof (struct nlist) * (bufp - buf);
   
Line 3519  getsym (key) Line 4082  getsym (key)
   bp->trace = 0;    bp->trace = 0;
   bp->value = 0;    bp->value = 0;
   bp->max_common_size = 0;    bp->max_common_size = 0;
     bp->warning = 0;
   
   /* Add the entry to the bucket.  */    /* Add the entry to the bucket.  */
   
Line 3623  void Line 4187  void
 error (string, arg1, arg2, arg3)  error (string, arg1, arg2, arg3)
      char *string, *arg1, *arg2, *arg3;       char *string, *arg1, *arg2, *arg3;
 {  {
     fprintf (stderr, "%s: ", progname);
   fprintf (stderr, string, arg1, arg2, arg3);    fprintf (stderr, string, arg1, arg2, arg3);
   fprintf (stderr, "\n");    fprintf (stderr, "\n");
 }  }
Line 3724  xrealloc (ptr, size) Line 4289  xrealloc (ptr, size)
     fatal ("virtual memory exhausted", 0);      fatal ("virtual memory exhausted", 0);
   return result;    return result;
 }  }
   
   #ifdef USG
   
   void
   bzero (p, n)
        char *p;
   {
     memset (p, 0, n);
   }
   
   void
   bcopy (from, to, n)
        char *from, *to;
   {
     memcpy (to, from, n);
   }
   
   getpagesize ()
   {
     return (4096);
   }
   
   #endif

Removed from v.1.1.1.2  
changed lines
  Added in v.1.1.1.3


unix.superglobalmegacorp.com