2007-11-17 Borut Razem <borut.razem AT siol.net>
[fw/sdcc] / as / asxxsrc / assym.c
diff --git a/as/asxxsrc/assym.c b/as/asxxsrc/assym.c
new file mode 100644 (file)
index 0000000..13d175a
--- /dev/null
@@ -0,0 +1,505 @@
+/* assym.c */
+
+/*
+ * (C) Copyright 1989-1995
+ * All Rights Reserved
+ *
+ * Alan R. Baldwin
+ * 721 Berkeley St.
+ * Kent, Ohio  44240
+ *
+ * 10-Nov-07 borutr:
+ *           - use strsto instead StoreString and include it in assym.c
+ *             for compatibility with the original asxxxx
+ *           - applied changes from 28-Oct-97 JLH:
+ *             - lookup: Use StoreString for sym construction
+ *             - change symeq() to do length-independent string compare
+ *             - change hash() to do length-independent hash calculation
+ *           - applied changes from 29-Oct-97 JLH:
+ *             - make mnemonics case insensitive ALWAYS
+ *             - make hash() case-insensitive always
+ *             - replace symeq() call in mlookup with strcmpi
+ */
+
+#include <stdio.h>
+#include <setjmp.h>
+#include <string.h>
+#include <stdlib.h>
+#include "asm.h"
+
+/*)Module       assym.c
+ *
+ *      The module assym.c contains the functions that operate
+ *      on the mnemonic/directive and symbol structures.
+ *
+ *      assym.c contains the following functions:
+ *              VOID    allglob()
+ *              area *  alookup()
+ *              int     hash()
+ *              sym *   lookup()
+ *              mne *   mlookup()
+ *              VOID *  new()
+ *              int     symeq()
+ *              VOID    syminit()
+ *              VOID    symglob()
+ *
+ *      assym.c contains no local/static variables.
+ */
+
+/*)Function     VOID    syminit()
+ *
+ *      The function syminit() is called early in the game
+ *      to set up the hashtables.  First all buckets in a
+ *      table are cleared.  Then a pass is made through
+ *      the respective symbol lists, linking them into
+ *      their hash buckets.  Finally the base area pointer
+ *      is set to 'dca'.
+ *
+ *      local variables:
+ *              int     h               computed hash value
+ *              mne *   mp              pointer to a mne structure
+ *              mne **  mpp             pointer to an array of
+ *                                      mne structure pointers
+ *              sym *   sp              pointer to a sym structure
+ *              sym **  spp             pointer to an array of
+ *                                      sym structure pointers
+ *
+ *      global variables:
+ *              area    area[]          single elememt area array
+ *              area    dca             defined as area[0]
+ *              mne * mnehash[]         array of pointers to NHASH
+ *                                      linked mnemonic/directive lists
+ *              sym * symhash[]         array of pointers to NHASH
+ *                                      linked symbol lists
+ *
+ *      functions called:
+ *              none
+ *
+ *      side effects:
+ *              (1)     The symbol hash tables are initialized,
+ *                      the only defined symbol is '.'.
+ *              (2)     The mnemonic/directive hash tables are
+ *                      initialized with the assembler directives
+ *                      and mnemonics found in the machine dependent
+ *                      file ___pst.c.
+ *              (3)     The area pointer is initialized to dca (area[0]).
+ */
+
+VOID
+syminit(void)
+{
+        register struct mne  *mp;
+        struct mne **mpp;
+        register struct sym  *sp;
+        struct sym **spp;
+        register int h;
+
+        mpp = &mnehash[0];
+        while (mpp < &mnehash[NHASH])
+                *mpp++ = NULL;
+        mp = &mne[0];
+        for (;;) {
+                h = hash(mp->m_id);
+                mp->m_mp = mnehash[h];
+                mnehash[h] = mp;
+                if (mp->m_flag&S_END)
+                        break;
+                ++mp;
+        }
+
+        spp = &symhash[0];
+        while (spp < &symhash[NHASH])
+                *spp++ = NULL;
+        sp = &sym[0];
+        for (;;) {
+                h = hash(sp->s_id);
+                sp->s_sp = symhash[h];
+                symhash[h] = sp;
+                if (sp->s_flag&S_END)
+                        break;
+                ++sp;
+        }
+
+        areap = &dca;
+}
+
+/*)Function     area *  alookup(id)
+ *
+ *              char *  id              area name string
+ *
+ *      The function alookup() searches the area list for a
+ *      match with id.  If the area is defined then a pointer
+ *      to this area is returned else a NULL is returned.
+ *
+ *      local variables:
+ *              area *  ap              pointer to area structure
+ *
+ *      global variables:
+ *              area *  areap           pointer to an area structure
+ *
+ *      functions called:
+ *              int     symeq()         assym.c
+ *
+ *      side effects:
+ *              none
+ */
+
+struct area *
+alookup(char *id)
+{
+        register struct area *ap;
+
+        ap = areap;
+        while (ap) {
+                if (symeq(id, ap->a_id)) {
+                        return (ap);
+                }
+                ap = ap->a_ap;
+        }
+        return(NULL);
+}
+
+/*)Function     mne *   mlookup(id)
+ *
+ *              char *  id              mnemonic/directive name string
+ *
+ *      The function mlookup() searches the mnemonic/directive
+ *      hash tables for a match returning a pointer to the
+ *      mne structure else it returns a NULL.
+ *
+ *      local variables:
+ *              mne *   mp              pointer to mne structure
+ *              int     h               calculated hash value
+ *
+ *      global variables:
+ *              mne * mnehash[]         array of pointers to NHASH
+ *                                      linked mnemonic/directive lists
+ *
+ *      functions called:
+ *              none
+ *
+ *      side effects:
+ *              none
+ */
+
+struct mne *
+mlookup(char *id)
+{
+        register struct mne *mp;
+        register int h;
+
+        h = hash(id);
+        mp = mnehash[h];
+        while (mp) {
+                if (as_strcmpi(id, mp->m_id) == 0)      /* JLH: case insensitive */
+                        return (mp);
+                mp = mp->m_mp;
+        }
+        return (NULL);
+}
+
+/*)Function     sym *   lookup(id)
+ *
+ *              char *  id              symbol name string
+ *
+ *      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.
+ *      A pointer to this new sym structure is returned.
+ *
+ *      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()          assym.c
+ *              VOID *  new()           assym.c
+ *              int     symeq()         assym.c
+ *
+ *      side effects:
+ *              If the function new() fails to allocate space
+ *              for the new sym structure the assembly terminates.
+ */
+
+struct sym *
+lookup(char *id)
+{
+        register struct sym *sp;
+        register int h;
+
+        h = hash(id);
+        sp = symhash[h];
+        while (sp) {
+                if (symeq(id, sp->s_id))
+                        return (sp);
+                sp = sp->s_sp;
+        }
+        sp = (struct sym *) new (sizeof(struct sym));
+        sp->s_sp = symhash[h];
+        symhash[h] = sp;
+        sp->s_tsym = NULL;
+        sp->s_id = strsto(id);
+        sp->s_type = S_NEW;
+        sp->s_flag = 0;
+        sp->s_area = NULL;
+        sp->s_ref = 0;
+        sp->s_addr = 0;
+        return (sp);
+}
+
+/*)Function     VOID    symglob()
+ *
+ *      The function symglob() will mark all symbols of
+ *      type S_NEW as global.  Called at the beginning of pass 1
+ *      if the assembly option -g was specified.
+ *
+ *      local variables:
+ *              sym *   sp              pointer to a sym structure
+ *              int     i               loop index
+ *
+ *      global variables:
+ *              sym * symhash[]         array of pointers to NHASH
+ *                                      linked symbol lists
+ *
+ *      functions called:
+ *              none
+ *
+ *      side effects:
+ *              Symbol types changed.
+ */
+
+VOID
+symglob(void)
+{
+        register struct sym *sp;
+        register int i;
+
+        for (i=0; i<NHASH; ++i) {
+                sp = symhash[i];
+                while (sp != NULL) {
+                        if (sp->s_type == S_NEW)
+                                sp->s_flag |= S_GBL;
+                        sp = sp->s_sp;
+                }
+        }
+}
+
+/*)Function     VOID    allglob()
+ *
+ *      The function allglob() will mark all symbols of
+ *      type S_USER as global.  Called at the beginning of pass 1
+ *      if the assembly option -a was specified.
+ *
+ *      local variables:
+ *              sym *   sp              pointer to a sym structure
+ *              int     i               loop index
+ *
+ *      global variables:
+ *              sym * symhash[]         array of pointers to NHASH
+ *                                      linked symbol lists
+ *
+ *      functions called:
+ *              none
+ *
+ *      side effects:
+ *              Symbol types changed.
+ */
+
+VOID
+allglob(void)
+{
+        register struct sym *sp;
+        register int i;
+
+        for (i=0; i<NHASH; ++i) {
+                sp = symhash[i];
+                while (sp != NULL) {
+                        if (sp != &dot && sp->s_type == S_USER)
+                                sp->s_flag |= S_GBL;
+                        sp = sp->s_sp;
+                }
+        }
+}
+
+/*)Function     int     symeq(p1, p2)
+ *
+ *              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.
+ *
+ *      local variables:
+ *              int     h               loop counter
+ *
+ *      global variables:
+ *              char    ccase[]         an array of characters which
+ *                                      perform the case translation function
+ *
+ *      functions called:
+ *              none
+ *
+ *      side effects:
+ *              none
+ *
+ */
+
+int
+symeq(char *p1, char *p2)
+{
+#if     CASE_SENSITIVE
+                return (strcmp( p1, p2 ) == 0);
+#else
+                return (as_strcmpi( p1, p2 ) == 0);
+#endif
+}
+
+/*)Function     int     hash(p)
+ *
+ *              char *  p               pointer to string to hash
+ *
+ *      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
+ *
+ *      global variables:
+ *              char    ccase[]         an array of characters which
+ *                                      perform the case translation function
+ *
+ *      functions called:
+ *              none
+ *
+ *      side effects:
+ *              none
+ */
+
+int
+hash(char *p)
+{
+        register int h;
+
+        h = 0;
+        while (*p) {
+                /* JLH: case insensitive hash:  Doesn't much affect
+                 * hashing, and allows same function for mnemonics and symbols
+                 */
+                h += ccase[(int)*p++];
+        }
+        return (h&HMASK);
+}
+
+/*)Function     char *  strsto(str)
+ *
+ *              char *  str             pointer to string to save
+ *
+ *      Allocate space for "str", copy str into new space.
+ *      Return a pointer to the allocated string.
+ *
+ *      This function based on code by
+ *              John L. Hartman
+ *              jhartman at compuserve dot com
+ *
+ *      local variables:
+ *              int     l               string length + 1
+ *              int     bytes           bytes remaining in buffer area
+ *              char *  p               pointer to head of copied string
+ *              char *  pnext           next location in buffer area
+ *
+ *      global variables:
+ *              none
+ *
+ *      functions called:
+ *              VOID *  new()           assym.c
+ *              char *  strncpy()       c_library
+ *
+ *      side effects:
+ *              Space allocated for string, string copied
+ *              to space.  Out of Space terminates assembler.
+ */
+
+/*
+ * To avoid wasting memory headers on small allocations, we
+ * allocate a big chunk and parcel it out as required.
+ * These static variables remember our hunk
+ */
+
+#define STR_SPC 1024
+static  char *  pnext = NULL;
+static  int     bytes = 0;
+
+char *
+strsto(char *str)
+{
+        int  l;
+        char *p;
+
+        /*
+         * What we need, including a null.
+         */
+        l = strlen(str) + 1;
+
+        if (l > bytes) {
+                /*
+                 * No space.  Allocate a new hunk.
+                 * We lose the pointer to any old hunk.
+                 * We don't care, as the names are never deleted.
+                */
+                pnext = (char *) new (STR_SPC);
+                bytes = STR_SPC;
+        }
+
+        /*
+         * Copy the name and terminating null.
+         */
+        p = pnext;
+        strncpy(p, str, l);
+
+        pnext += l;
+        bytes -= l;
+
+        return(p);
+}
+
+/*)Function     VOID *  new(n)
+ *
+ *              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
+ *      assembly is terminated.
+ *
+ *      local variables:
+ *              VOID *  p               a general pointer
+ *
+ *      global variables:
+ *              none
+ *
+ *      functions called:
+ *              VOID    asexit()        asmain.c
+ *              int     fprintf()       c_library
+ *              VOID *  malloc()        c_library
+ *
+ *      side effects:
+ *              Memory is allocated, if allocation fails
+ *              the assembly is terminated.
+ */
+
+VOID *
+new(unsigned int n)
+{
+        register VOID *p;
+
+        if ((p = (VOID *) malloc(n)) == NULL) {
+                fprintf(stderr, "Out of space!\n");
+                asexit(1);
+        }
+        return (p);
+}