summaryrefslogtreecommitdiff
path: root/ld/table.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/table.c')
-rw-r--r--ld/table.c205
1 files changed, 205 insertions, 0 deletions
diff --git a/ld/table.c b/ld/table.c
new file mode 100644
index 0000000..5260741
--- /dev/null
+++ b/ld/table.c
@@ -0,0 +1,205 @@
+/* table.c - table-handler module for linker */
+
+/* Copyright (C) 1994 Bruce Evans */
+
+#include "const.h"
+#include "align.h"
+#include "obj.h"
+#include "type.h"
+#include "globvar.h"
+
+#ifdef STDC_HEADERS_MISSING
+void *malloc P((unsigned size));
+#else
+#undef NULL
+#include <stdlib.h>
+#endif
+
+#define GOLDEN 157 /* GOLDEN/HASHTABSIZE approx golden ratio */
+#define HASHTABSIZE 256
+
+PRIVATE struct symstruct *hashtab[HASHTABSIZE]; /* hash table */
+PRIVATE char *tableptr; /* next free spot in catchall table */
+PRIVATE char *tableend; /* ptr to spot after last in table */
+
+FORWARD struct symstruct **gethashptr P((char *name));
+
+/* initialise symbol table */
+
+PUBLIC void syminit()
+{
+ unsigned i;
+
+ for (i = sizeof(int) <= 2 ? 0xE000 : (unsigned) 0x38000;
+ i != 0; i -= 512)
+ if ((tableptr = malloc(i)) != NULL)
+ break;
+ if (tableptr == NULL)
+ outofmemory();
+ tableend = tableptr + i;
+ for (i = 0; i < HASHTABSIZE; i++)
+ hashtab[i] = NULL;
+}
+
+/* add named symbol to end of table - initialise only name and next fields */
+/* caller must not duplicate names of externals for findsym() to work */
+
+PUBLIC struct symstruct *addsym(name)
+char *name;
+{
+ struct symstruct **hashptr;
+ struct symstruct *oldsymptr;
+ struct symstruct *symptr;
+
+ hashptr = gethashptr(name);
+ symptr = *hashptr;
+ while (symptr != NULL)
+ {
+ oldsymptr = symptr;
+ symptr = symptr->next;
+ }
+ align(tableptr);
+ symptr = (struct symstruct *) tableptr;
+ if ((tableptr = symptr->name + (strlen(name) + 1)) > tableend)
+ outofmemory();
+ symptr->modptr = NULL;
+ symptr->next = NULL;
+ if (name != symptr->name)
+ strcpy(symptr->name, name); /* should't happen */
+ if (*hashptr == NULL)
+ *hashptr = symptr;
+ else
+ oldsymptr->next = symptr;
+ return symptr;
+}
+
+/* lookup named symbol */
+
+PUBLIC struct symstruct *findsym(name)
+char *name;
+{
+ struct symstruct *symptr;
+
+ symptr = *gethashptr(name);
+ while (symptr != NULL && (!(symptr->flags & (E_MASK | I_MASK)) ||
+ strcmp(symptr->name, name) != 0))
+ symptr = symptr->next;
+ return symptr;
+}
+
+/* convert name to a hash table ptr */
+
+PRIVATE struct symstruct **gethashptr(name)
+register char *name;
+{
+ register unsigned hashval;
+
+ hashval = 0;
+ while (*name)
+ hashval = hashval * 2 + *name++;
+ return hashtab + ((hashval * GOLDEN) & (HASHTABSIZE - 1));
+
+/*
+
+#asm
+
+GOLDEN EQU 157
+HASHTABSIZE EQU 256
+
+ CLRB can build value here since HASHTABSIZE <= 256
+ LDA ,X
+ BEQ HASHVAL.EXIT
+HASHVAL.LOOP
+ ADDB ,X+
+ LSLB
+ LDA ,X
+ BNE HASHVAL.LOOP
+ RORB
+ LDA #GOLDEN
+ MUL
+HASHVAL.EXIT
+HASHVAL.EXIT
+ LDX #_hashtab
+ ABX discard A - same as taking mod HASHTABSIZE
+ ABX
+#endasm
+
+*/
+
+}
+
+/* move symbol descriptor entries to top of table (no error checking) */
+
+PUBLIC char *moveup(nbytes)
+unsigned nbytes;
+{
+ register char *source;
+ register char *target;
+
+ source = tableptr;
+ target = tableend;
+ while (nbytes--)
+ *--target = *--source;
+ tableptr = source;
+ return tableend = target;
+}
+
+/* our version of malloc */
+
+PUBLIC char *ourmalloc(nbytes)
+unsigned nbytes;
+{
+ char *allocptr;
+
+ align(tableptr);
+ allocptr = tableptr;
+ if ((tableptr += nbytes) > tableend)
+ outofmemory();
+ return allocptr;
+}
+
+/* our version of free (release from bottom of table) */
+
+PUBLIC void ourfree(cptr)
+char *cptr;
+{
+ tableptr = cptr;
+}
+
+/* read string from file into table at offset suitable for next symbol */
+
+PUBLIC char *readstring()
+{
+ int c;
+ char *s;
+ char *start;
+
+ align(tableptr);
+ start = s = ((struct symstruct *) tableptr)->name;
+ while (TRUE)
+ {
+ if (s >= tableend)
+ outofmemory();
+ if ((c = readchar()) < 0)
+ prematureeof();
+ if ((*s++ = c) == 0)
+ return start;
+ }
+ /* NOTREACHED */
+}
+
+/* release from top of table */
+
+PUBLIC void release(cptr)
+char *cptr;
+{
+ tableend = cptr;
+}
+
+/* allocate space for string */
+
+PUBLIC char *stralloc(s)
+char *s;
+{
+ return strcpy(ourmalloc((unsigned) strlen(s) + 1), s);
+}