summaryrefslogtreecommitdiff
path: root/ld/table.c
blob: 5260741c36be3697e1206f7d7d92aaa380ec94ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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);
}