* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / link / lksym.c
index e04080506c461c2124715583d35fe7f910a40051..d3cacbe3ceb7dc26e51d4406f595aa13e0e91afe 100644 (file)
@@ -1,17 +1,26 @@
-/* lksym.c */
+/* lksym.c
+
+   Copyright (C) 1989-1995 Alan R. Baldwin
+   721 Berkeley St., Kent, Ohio 44240
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 /*
- * (C) Copyright 1989-1995
- * All Rights Reserved
- *
- * Alan R. Baldwin
- * 721 Berkeley St.
- * Kent, Ohio  44240
- *
- * 28-Oct-97 JLH: 
- *          - lkpsym: Use StoreString for sym construction
- *          - change symeq() to do length-independent string compare
- *          - change hash() to do length-independent hash calculation
+ * 28-Oct-97 JLH:
+ *           - lkpsym: Use StoreString for sym construction
+ *           - change symeq() to do length-independent string compare
+ *           - change hash() to do length-independent hash calculation
  */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include "aslink.h"
 
-/*)Module      lksym.c
- *
- *     The module lksym.c contains the functions that operate
- *     on the symbol structures.
- *
- *     lksym.c contains the following functions:
- *             int     hash()
- *             sym *   lkpsym()
- *             VOID *  new()
- *             sym *   newsym()
- *             VOID    symdef()
- *             int     symeq()
- *             VOID    syminit()
- *             VOID    symmod()
- *             Addr_T  symval()
- *
- *     lksym.c contains no local/static variables.
+/*)Module       lksym.c
+ *
+ *      The module lksym.c contains the functions that operate
+ *      on the symbol structures.
+ *
+ *      lksym.c contains the following functions:
+ *              int     hash()
+ *              sym *   lkpsym()
+ *              VOID *  new()
+ *              sym *   newsym()
+ *              VOID    symdef()
+ *              int     symeq()
+ *              VOID    syminit()
+ *              VOID    symmod()
+ *              Addr_T  symval()
+ *
+ *      lksym.c contains no local/static variables.
  */
 
-/*)Function    VOID    syminit()
+/*)Function     VOID    syminit()
  *
- *     The function syminit() is called to clear the hashtable.
+ *      The function syminit() is called to clear the hashtable.
  *
- *     local variables:
- *             int     h               computed hash value
- *             sym **  spp             pointer to an array of
- *                                     sym structure pointers
+ *      local variables:
+ *              int     h               computed hash value
+ *              sym **  spp             pointer to an array of
+ *                                      sym structure pointers
  *
- *     global variables:
- *             sym * symhash[]         array of pointers to NHASH
- *                                     linked symbol lists
+ *      global variables:
+ *              sym * symhash[]         array of pointers to NHASH
+ *                                      linked symbol lists
  *
- *     functions called:
- *             none
+ *      functions called:
+ *              none
  *
- *     side effects:
- *             (1)     The symbol hash tables are cleared
+ *      side effects:
+ *              (1)     The symbol hash tables are cleared
  */
 
 VOID
 syminit(void)
 {
-       struct sym **spp;
+        struct sym **spp;
 
-       spp = &symhash[0];
-       while (spp < &symhash[NHASH])
-               *spp++ = NULL;
+        spp = &symhash[0];
+        while (spp < &symhash[NHASH])
+                *spp++ = NULL;
 }
 
-/*)Function    sym *   newsym()
- *
- *     The function newsym() is called to evaluate the symbol
- *     definition/reference directive from the .rel file(s).
- *     If the symbol is not found in the symbol table a new
- *     symbol structure is created.  Evaluation of the
- *     directive determines if this is a reference or a definition.
- *     Multiple definitions of the same variable will be flagged
- *     as an error if the values are not identical.  A symbol
- *     definition places the symbol value and area extension
- *     into the symbols data structure.  And finally, a pointer
- *     to the symbol structure is placed into the head structure
- *     symbol list.  Refer to the description of the header, symbol,
- *     area, and areax structures in lkdata.c for structure and
- *     linkage details.
- *
- *     local variables:
- *             int     c               character from input text
- *             int     i               evaluation value
- *             char    id[]            symbol name
- *             int     nglob           number of symbols in this header
- *             sym *   tsp             pointer to symbol structure
- *             sym **  s               list of pointers to symbol structures
- *
- *     global variables:
- *             areax   *axp            Pointer to the current
- *                                     areax structure
- *             head    *headp          The pointer to the first
- *                                     head structure of a linked list
- *             int     lkerr           error flag
- *
- *     functions called:
- *             Addr_T  eval()          lkeval.c
- *             VOID    exit()          c_library
- *             int     fprintf()       c_library
- *             char    getSid()        lklex.c
- *             char    get()           lklex.c
- *             char    getnb()         lklex.c
- *             sym *   lkpsym()        lksym.c
- *
- *     side effects:
- *             A symbol structure is created and/or modified.
- *             If structure space allocation fails linker will abort.
- *             Several severe errors (these are internal errors
- *             indicating a corrupted .rel file or corrupted
- *             assembler or linker) will terminated the linker.
+/*)Function     sym *   newsym()
+ *
+ *      The function newsym() is called to evaluate the symbol
+ *      definition/reference directive from the .rel file(s).
+ *      If the symbol is not found in the symbol table a new
+ *      symbol structure is created.  Evaluation of the
+ *      directive determines if this is a reference or a definition.
+ *      Multiple definitions of the same variable will be flagged
+ *      as an error if the values are not identical.  A symbol
+ *      definition places the symbol value and area extension
+ *      into the symbols data structure.  And finally, a pointer
+ *      to the symbol structure is placed into the head structure
+ *      symbol list.  Refer to the description of the header, symbol,
+ *      area, and areax structures in lkdata.c for structure and
+ *      linkage details.
+ *
+ *      local variables:
+ *              int     c               character from input text
+ *              int     i               evaluation value
+ *              char    id[]            symbol name
+ *              int     nglob           number of symbols in this header
+ *              sym *   tsp             pointer to symbol structure
+ *              sym **  s               list of pointers to symbol structures
+ *
+ *      global variables:
+ *              areax   *axp            Pointer to the current
+ *                                      areax structure
+ *              head    *headp          The pointer to the first
+ *                                      head structure of a linked list
+ *              int     lkerr           error flag
+ *
+ *      functions called:
+ *              Addr_T  eval()          lkeval.c
+ *              VOID    exit()          c_library
+ *              int     fprintf()       c_library
+ *              char    getSid()        lklex.c
+ *              char    get()           lklex.c
+ *              char    getnb()         lklex.c
+ *              sym *   lkpsym()        lksym.c
+ *
+ *      side effects:
+ *              A symbol structure is created and/or modified.
+ *              If structure space allocation fails linker will abort.
+ *              Several severe errors (these are internal errors
+ *              indicating a corrupted .rel file or corrupted
+ *              assembler or linker) will terminated the linker.
  */
 
 /*
@@ -131,348 +140,348 @@ newsym(void)
 {
   register unsigned i ;
   register unsigned nglob ;
-       register int c ;
-       struct sym *tsp;
-       struct sym **s;
-       char id[NCPS];
-
-       getSid(id);     // old: getid(id, -1);
-       tsp = lkpsym(id, 1);
-       c = getnb();get();get();
-       if (c == 'R') {
-               tsp->s_type |= S_REF;
-               if (eval()) {
-                       fprintf(stderr, "Non zero S_REF\n");
-                       lkerr++;
-               }
-       } else
-       if (c == 'D') {
-               i = eval();
-               if (tsp->s_type & S_DEF && tsp->s_addr != i) {
-                       fprintf(stderr, "Multiple definition of %s\n", id);
-                       lkerr++;
-               }
-               tsp->s_type |= S_DEF;
-               /*
-                * Set value and area extension link.
-                */
-               tsp->s_addr = i;
-               tsp->s_axp = axp;
-       } else {
-               fprintf(stderr, "Invalid symbol type %c for %s\n", c, id);
-               lkexit(1);
-       }
-       /*
-        * Place pointer in header symbol list
-        */
-       if (headp == NULL) {
-               fprintf(stderr, "No header defined\n");
-               lkexit(1);
-       }
-       nglob = hp->h_nglob;
-       s = hp->s_list;
-       for (i=0; i < nglob ;++i) {
-               if (s[i] == NULL) {
-                       s[i] = tsp;
-                       return(tsp);
-               }
-       }
-       fprintf(stderr, "Header symbol list overflow\n");
-       lkexit(1);
-
-       /* Never reached */
-       return(0);
+        register int c ;
+        struct sym *tsp;
+        struct sym **s;
+        char id[NCPS];
+
+        getSid(id);     // old: getid(id, -1);
+        tsp = lkpsym(id, 1);
+        c = getnb();get();get();
+        if (c == 'R') {
+                tsp->s_type |= S_REF;
+                if (eval()) {
+                        fprintf(stderr, "Non zero S_REF\n");
+                        lkerr++;
+                }
+        } else
+        if (c == 'D') {
+                i = eval();
+                if (tsp->s_type & S_DEF && tsp->s_addr != i) {
+                        fprintf(stderr, "Multiple definition of %s\n", id);
+                        lkerr++;
+                }
+                tsp->s_type |= S_DEF;
+                /*
+                 * Set value and area extension link.
+                 */
+                tsp->s_addr = i;
+                tsp->s_axp = axp;
+        } else {
+                fprintf(stderr, "Invalid symbol type %c for %s\n", c, id);
+                lkexit(1);
+        }
+        /*
+         * Place pointer in header symbol list
+         */
+        if (headp == NULL) {
+                fprintf(stderr, "No header defined\n");
+                lkexit(1);
+        }
+        nglob = hp->h_nglob;
+        s = hp->s_list;
+        for (i=0; i < nglob ;++i) {
+                if (s[i] == NULL) {
+                        s[i] = tsp;
+                        return(tsp);
+                }
+        }
+        fprintf(stderr, "Header symbol list overflow\n");
+        lkexit(1);
+
+        /* Never reached */
+        return(0);
 }
 
-/*)Function    sym *   lkpsym(id,f)
- *
- *             char *  id              symbol name string
- *             int     f               f == 0, lookup only
- *                                     f != 0, create if not found
- *
- *     The function lookup() searches the symbol hash tables for
- *     a symbol name match returning a pointer to the sym structure.
- *     If the symbol is not found then a sym structure is created,
- *     initialized, and linked to the appropriate hash table if f != 0.
- *     A pointer to this new sym structure is returned or a NULL
- *     pointer is returned if f == 0.
- *
- *     local variables:
- *             int     h               computed hash value
- *             sym *   sp              pointer to a sym structure
- *
- *     global varaibles:
- *             sym * symhash[]         array of pointers to NHASH
- *                                     linked symbol lists
- *
- *     functions called:
- *             int     hash()          lksym.c
- *             VOID *  new()           lksym.c
- *             int     symeq()         lksym.c
- *
- *     side effects:
- *             If the function new() fails to allocate space
- *             for the new sym structure the linker terminates.
+/*)Function     sym *   lkpsym(id,f)
+ *
+ *              char *  id              symbol name string
+ *              int     f               f == 0, lookup only
+ *                                      f != 0, create if not found
+ *
+ *      The function lookup() searches the symbol hash tables for
+ *      a symbol name match returning a pointer to the sym structure.
+ *      If the symbol is not found then a sym structure is created,
+ *      initialized, and linked to the appropriate hash table if f != 0.
+ *      A pointer to this new sym structure is returned or a NULL
+ *      pointer is returned if f == 0.
+ *
+ *      local variables:
+ *              int     h               computed hash value
+ *              sym *   sp              pointer to a sym structure
+ *
+ *      global varaibles:
+ *              sym * symhash[]         array of pointers to NHASH
+ *                                      linked symbol lists
+ *
+ *      functions called:
+ *              int     hash()          lksym.c
+ *              VOID *  new()           lksym.c
+ *              int     symeq()         lksym.c
+ *
+ *      side effects:
+ *              If the function new() fails to allocate space
+ *              for the new sym structure the linker terminates.
  */
 
 struct sym *
 lkpsym(char *id, int f)
 {
-       register struct sym *sp;
-       register int h;
-
-       h = hash(id);
-       sp = symhash[h];
-       while (sp != NULL) {
-               if (symeq(id, sp->s_id))
-                       return (sp);
-               sp = sp->s_sp;
-       }
-       if (f == 0)
-               return (NULL);
-       sp = (struct sym *) new (sizeof(struct sym));
-       sp->s_sp = symhash[h];
-       symhash[h] = sp;
-       sp->s_id = StoreString( id );   /* JLH */
-       return (sp);
+        register struct sym *sp;
+        register int h;
+
+        h = hash(id);
+        sp = symhash[h];
+        while (sp != NULL) {
+                if (symeq(id, sp->s_id))
+                        return (sp);
+                sp = sp->s_sp;
+        }
+        if (f == 0)
+                return (NULL);
+        sp = (struct sym *) new (sizeof(struct sym));
+        sp->s_sp = symhash[h];
+        symhash[h] = sp;
+        sp->s_id = StoreString( id );   /* JLH */
+        return (sp);
 }
 
-/*)Function    Addr_T  symval(tsp)
+/*)Function     Addr_T  symval(tsp)
  *
- *             sym *   tsp             pointer to a symbol structure
+ *              sym *   tsp             pointer to a symbol structure
  *
- *     The function symval() returns the value of the
- *     relocated symbol by adding the variable definition
- *     value to the areax base address.
+ *      The function symval() returns the value of the
+ *      relocated symbol by adding the variable definition
+ *      value to the areax base address.
  *
- *     local variables:
- *             Addr_T  val             relocated address value
+ *      local variables:
+ *              Addr_T  val             relocated address value
  *
- *     global variables:
- *             none
+ *      global variables:
+ *              none
  *
- *     functions called:
- *             none
+ *      functions called:
+ *              none
  *
- *     side effects:
- *             none
+ *      side effects:
+ *              none
  */
 
 Addr_T
 symval(register struct sym *tsp)
 {
-       register Addr_T val;
+        register Addr_T val;
 
-       val = tsp->s_addr;
-       if (tsp->s_axp) {
-               val += tsp->s_axp->a_addr;
-       }
-       return(val);
+        val = tsp->s_addr;
+        if (tsp->s_axp) {
+                val += tsp->s_axp->a_addr;
+        }
+        return(val);
 }
 
-/*)Function    VOID    symdef(fp)
+/*)Function     VOID    symdef(fp)
  *
- *             FILE *  fp              file handle for output
+ *              FILE *  fp              file handle for output
  *
- *     The function symdef() scans the hashed symbol table
- *     searching for variables referenced but not defined.
- *     Undefined variables are linked to the default
- *     area "_CODE" and reported as referenced by the
- *     appropriate module.
+ *      The function symdef() scans the hashed symbol table
+ *      searching for variables referenced but not defined.
+ *      Undefined variables are linked to the default
+ *      area "_CODE" and reported as referenced by the
+ *      appropriate module.
  *
- *     local variables:
- *             int     i               hash table index loop variable
- *             sym *   sp              pointer to linked symbol structure
+ *      local variables:
+ *              int     i               hash table index loop variable
+ *              sym *   sp              pointer to linked symbol structure
  *
- *     global variables:
- *             area    *areap          The pointer to the first
- *                                     area structure of a linked list
- *             sym *symhash[NHASH]     array of pointers to NHASH
- *                                     linked symbol lists
+ *      global variables:
+ *              area    *areap          The pointer to the first
+ *                                      area structure of a linked list
+ *              sym *symhash[NHASH]     array of pointers to NHASH
+ *                                      linked symbol lists
  *
- *     functions called:
- *             symmod()                lksym.c
+ *      functions called:
+ *              symmod()                lksym.c
  *
- *     side effects:
- *             Undefined variables have their areas set to "_CODE".
+ *      side effects:
+ *              Undefined variables have their areas set to "_CODE".
  */
 
 VOID
 symdef(FILE *fp)
 {
-       register struct sym *sp;
-       register int i;
-
-       for (i=0; i<NHASH; ++i) {
-               sp = symhash[i];
-               while (sp) {
-                       if (sp->s_axp == NULL)
-                               sp->s_axp = areap->a_axp;
-                       if ((sp->s_type & S_DEF) == 0)
-                               symmod(fp, sp);
-                       sp = sp->s_sp;
-               }
-       }
+        register struct sym *sp;
+        register int i;
+
+        for (i=0; i<NHASH; ++i) {
+                sp = symhash[i];
+                while (sp) {
+                        if (sp->s_axp == NULL)
+                                sp->s_axp = areap->a_axp;
+                        if ((sp->s_type & S_DEF) == 0)
+                                symmod(fp, sp);
+                        sp = sp->s_sp;
+                }
+        }
 }
 
-/*)Function    VOID    symmod(fp,tsp)
- *
- *             FILE *  fp              output file handle
- *             sym *   tsp             pointer to a symbol structure
- *
- *     The function symmod() scans the header structures
- *     searching for a reference to the symbol structure
- *     pointer to by tsp.  The function then generates an error
- *     message whichs names the module having referenced the
- *     undefined variable.
- *
- *     local variables:
- *             int     i               loop counter
- *             sym **  p               pointer to a list of pointers
- *                                     to symbol structures
- *
- *     global variables:
- *             head    *headp          The pointer to the first
- *                                     head structure of a linked list
- *             head    *hp             Pointer to the current
- *                                     head structure
- *             int     lkerr           error flag
- *
- *     functions called:
- *             int     fprintf()       c_library
- *
- *     side effects:
- *             Error output generated.
+/*)Function     VOID    symmod(fp,tsp)
+ *
+ *              FILE *  fp              output file handle
+ *              sym *   tsp             pointer to a symbol structure
+ *
+ *      The function symmod() scans the header structures
+ *      searching for a reference to the symbol structure
+ *      pointer to by tsp.  The function then generates an error
+ *      message whichs names the module having referenced the
+ *      undefined variable.
+ *
+ *      local variables:
+ *              int     i               loop counter
+ *              sym **  p               pointer to a list of pointers
+ *                                      to symbol structures
+ *
+ *      global variables:
+ *              head    *headp          The pointer to the first
+ *                                      head structure of a linked list
+ *              head    *hp             Pointer to the current
+ *                                      head structure
+ *              int     lkerr           error flag
+ *
+ *      functions called:
+ *              int     fprintf()       c_library
+ *
+ *      side effects:
+ *              Error output generated.
  */
 
 VOID
 symmod(FILE *fp, struct sym *tsp)
 {
-       register int i;
-       struct sym **p;
-
-       if ((hp = headp) != NULL) {
-               while(hp) {
-                       p = hp->s_list;
-                       for (i=0; i<hp->h_nglob; ++i) {
-                               if (p[i] == tsp) {
-                                       fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id);
-                                       fprintf(fp, "referenced by module '%s'\n", hp->m_id);
-                                       lkerr++;
-                               }
-                       }
-                       hp = hp->h_hp;
-               }
-       }
+        register int i;
+        struct sym **p;
+
+        if ((hp = headp) != NULL) {
+                while(hp) {
+                        p = hp->s_list;
+                        for (i=0; i<hp->h_nglob; ++i) {
+                                if (p[i] == tsp) {
+                                        fprintf(fp, "\n?ASlink-Warning-Undefined Global '%s' ", tsp->s_id);
+                                        fprintf(fp, "referenced by module '%s'\n", hp->m_id);
+                                        lkerr++;
+                                }
+                        }
+                        hp = hp->h_hp;
+                }
+        }
 }
 
-/*)Function    int     symeq(p1, p2)
+/*)Function     int     symeq(p1, p2)
  *
- *             char *  p1              name string
- *             char *  p2              name string
+ *              char *  p1              name string
+ *              char *  p2              name string
  *
- *     The function symeq() compares the two name strings for a match.
- *     The return value is 1 for a match and 0 for no match.
+ *      The function symeq() compares the two name strings for a match.
+ *      The return value is 1 for a match and 0 for no match.
  *
- *     local variables:
- *             int     h               loop counter
+ *      local variables:
+ *              int     h               loop counter
  *
- *     global variables:
- *             char    ccase[]         an array of characters which
- *                                     perform the case translation function
+ *      global variables:
+ *              char    ccase[]         an array of characters which
+ *                                      perform the case translation function
  *
- *     functions called:
- *             none
+ *      functions called:
+ *              none
  *
- *     side effects:
- *             none
+ *      side effects:
+ *              none
  *
  */
 
 int
 symeq(register char *p1, register char *p2)
 {
-#if    CASE_SENSITIVE
-               return (strncmp( p1, p2, NCPS ) == 0);
+#if     CASE_SENSITIVE
+                return (strncmp( p1, p2, NCPS ) == 0);
 #else
-               return (as_strncmpi( p1, p2, NCPS ) == 0);
+                return (as_strncmpi( p1, p2, NCPS ) == 0);
 #endif
 }
 
-/*)Function    int     hash(p)
+/*)Function     int     hash(p)
  *
- *             char *  p               pointer to string to hash
+ *              char *  p               pointer to string to hash
  *
- *     The function hash() computes a hash code using the sum
- *     of all characters mod table size algorithm.
+ *      The function hash() computes a hash code using the sum
+ *      of all characters mod table size algorithm.
  *
- *     local variables:
- *             int     h               accumulated character sum
- *             int     n               loop counter
+ *      local variables:
+ *              int     h               accumulated character sum
+ *              int     n               loop counter
  *
- *     global variables:
- *             char    ccase[]         an array of characters which
- *                                     perform the case translation function
+ *      global variables:
+ *              char    ccase[]         an array of characters which
+ *                                      perform the case translation function
  *
- *     functions called:
- *             none
+ *      functions called:
+ *              none
  *
- *     side effects:
- *             none
+ *      side effects:
+ *              none
  *
  */
+
 int
 hash(register char *p)
 {
-       register int h, n;
+        register int h, n;
 
-       h = 0;
-       n = NCPS;
-       while (*p && n--) {
+        h = 0;
+        n = NCPS;
+        while (*p && n--) {
 
-#if    CASE_SENSITIVE
-               h += *p++;
+#if     CASE_SENSITIVE
+                h += *p++;
 #else
-               h += ccase[(unsigned char)(*p++)];
+                h += ccase[(unsigned char)(*p++)];
 #endif
 
-       }
-       return (h&HMASK);
+        }
+        return (h&HMASK);
 }
 
-/*)Function    VOID *  new(n)
+/*)Function     VOID *  new(n)
  *
- *             unsigned int    n       allocation size in bytes
+ *              unsigned int    n       allocation size in bytes
  *
- *     The function new() allocates n bytes of space and returns
- *     a pointer to this memory.  If no space is available the
- *     linker is terminated.
+ *      The function new() allocates n bytes of space and returns
+ *      a pointer to this memory.  If no space is available the
+ *      linker is terminated.
  *
- *     local variables:
- *             char *  p               a general pointer
- *             char *  q               a general pointer
+ *      local variables:
+ *              char *  p               a general pointer
+ *              char *  q               a general pointer
  *
- *     global variables:
- *             none
+ *      global variables:
+ *              none
  *
- *     functions called:
- *             int     fprintf()       c_library
- *             VOID *  malloc()        c_library
+ *      functions called:
+ *              int     fprintf()       c_library
+ *              VOID *  malloc()        c_library
  *
- *     side effects:
- *             Memory is allocated, if allocation fails
- *             the linker is terminated.
+ *      side effects:
+ *              Memory is allocated, if allocation fails
+ *              the linker is terminated.
  */
 
 VOID *
 new(unsigned int n)
 {
-       register char *p;
+        register char *p;
 
-       if ((p = (char *) calloc(n, 1)) == NULL) {
-               fprintf(stderr, "Out of space!\n");
-               lkexit(1);
-       }
-       return (p);
+        if ((p = (char *) calloc(n, 1)) == NULL) {
+                fprintf(stderr, "Out of space!\n");
+                lkexit(1);
+        }
+        return (p);
 }