-
Notifications
You must be signed in to change notification settings - Fork 1
/
tables.cpp
391 lines (335 loc) · 11.8 KB
/
tables.cpp
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
#define _CRT_SECURE_NO_WARNINGS
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cassert>
#include "main.h"
/////////////////////////////////////////////////////////////////////////////
SaveStatusEntry SaveStatusArea[SaveStatusAreaSize];
int SaveStatusCount = 0;
SymbolTableEntry* SymbolTable = nullptr;
SymbolTableEntry* ASECTentry = nullptr;
int SymbolTableCount = 0; // STCNT -- SYMBOL TBL ENTRIES COUNTER
RELEntry* RelocationTable = nullptr;
int RelocationTableCount = 0;
RELEntry* LdaTable = nullptr;
LibraryModuleEntry LibraryModuleList[LibraryModuleListSize];
int LibraryModuleCount = 0; // Count of records in LibraryModuleList, see LMLPTR
ModuleSectionEntry ModuleSectionTable[ModuleSectionTableSize];
int ModuleSectionCount = 0;
/////////////////////////////////////////////////////////////////////////////
void symbol_table_enter(int* pindex, uint32_t lkname, uint16_t lkwd)
{
assert(pindex != nullptr);
assert(SymbolTable != nullptr);
// Find empty entry
if (SymbolTableCount >= SymbolTableSize)
fatal_error("ERR1: Symbol table overflow.\n");
int index = *pindex;
SymbolTableEntry* entry;
for (;;)
{
entry = SymbolTable + index;
if (entry->name == 0)
break;
index++;
if (index >= SymbolTableSize)
index = 0;
}
//printf(" Saving entry: index %4d name '%s' segment %d\n", index, unrad50(lkname), Globals.SEGNUM);
if (lkname == 0)
lkname = (Globals.SEGNUM + 1) << 2; // USE SEGMENT # FOR BLANK SECTION NAME
// Save the entry
SymbolTableCount++;
entry->name = lkname;
entry->flagseg = lkwd;
*pindex = index;
}
// MAKE A DUPLICATE SYMBOL NON-DUPLICATE, see LINK3\DELETE
void symbol_table_delete(int index)
{
assert(index > 0);
assert(index < SymbolTableSize);
assert(SymbolTable != nullptr);
//TODO
NOTIMPLEMENTED
}
// ADD A REFERENCED SYMBOL TO THE UNDEFINED LIST, see LINK3\ADDUDF
void symbol_table_add_undefined_head(int index)
{
assert(index > 0 && index < SymbolTableSize);
assert(SymbolTable != nullptr);
if (Globals.UNDLST != 0)
{
SymbolTableEntry* oldentry = SymbolTable + Globals.UNDLST;
oldentry->value = (uint16_t)index; // set back reference
}
else
{
Globals.UNDEND = index;
}
SymbolTableEntry* entry = SymbolTable + index;
entry->status |= SY_UDF; // MAKE CUR SYM UNDEFINED
entry->flagseg = (entry->flagseg & ~SY_SEG) | Globals.SEGNUM; // SET SEGMENT # WHERE INITIAL REF
entry->status |= (uint16_t)Globals.UNDLST;
Globals.UNDLST = index;
Globals.FLGWD |= AD_LML; // IND TO ADD TO LML LATER
}
void symbol_table_add_undefined_tail(int index)
{
assert(index > 0 && index < SymbolTableSize);
assert(SymbolTable != nullptr);
SymbolTableEntry* entry = SymbolTable + index;
entry->status |= SY_UDF; // MAKE CUR SYM UNDEFINED
entry->flagseg = (entry->flagseg & ~SY_SEG) | Globals.SEGNUM; // SET SEGMENT # WHERE INITIAL REF
if (Globals.UNDLST == 0)
{
entry->value = 0;
Globals.UNDLST = index;
Globals.UNDEND = index;
}
else
{
uint16_t oldindex = Globals.UNDEND;
SymbolTableEntry* oldentry = SymbolTable + Globals.UNDEND;
oldentry->status |= (uint16_t)index;
entry->value = oldindex; // set back reference
Globals.UNDEND = index;
}
Globals.FLGWD |= AD_LML; // IND TO ADD TO LML LATER
}
void symbol_table_add_undefined(int index)
{
symbol_table_add_undefined_tail(index);
}
// REMOVE A ENTRY FROM THE UNDEFINED LIST, see LINK3\REMOVE
void symbol_table_remove_undefined(int index)
{
assert(index > 0 && index < SymbolTableSize);
assert(SymbolTable != nullptr);
SymbolTableEntry* entry = SymbolTable + index;
uint16_t previndex = entry->value;
uint16_t nextindex = entry->nextindex();
if (previndex == 0)
Globals.UNDLST = nextindex;
else
{
SymbolTableEntry* preventry = SymbolTable + previndex;
preventry->status = (preventry->status & 0170000) | (entry->status & 07777);
}
if (nextindex != 0)
{
SymbolTableEntry* nextentry = SymbolTable + nextindex;
nextentry->value = previndex;
}
else
{
Globals.UNDEND = previndex;
}
entry->value = 0;
entry->status &= 0170000;
}
// ANY UNDEFINED SYMBOLS IN LIST ? See LINK3\ANYUND
bool is_any_undefined()
{
return (Globals.UNDLST != 0);
}
// SYMBOL TABLE SEARCH ROUTINE
// In: lkname = symbol name to lookup
// In: lnwd = FLAGS & SEGMENT # MATCH WORD
// In: lkmsk = MASK OF BITS DO NOT CARE ABOUT FOR A MATCH
// In: dupmsk
// Out: return = true if found
// Out: result = index of the found entity, or index of entity to work with
bool symbol_table_search_routine(uint32_t lkname, uint16_t lkwd, uint16_t lkmsk, uint16_t dupmsk, int* result)
{
assert(result != nullptr);
assert(SymbolTable != nullptr);
// Calculate hash
uint16_t hash = 0;
if (lkname != 0)
hash = LOWORD(lkname) + HIWORD(lkname);
else
{
// 0 = BLANK NAME
hash = (Globals.SEGNUM + 1) << 2; // USE SEGMENT # FOR BLANK SECTION NAME
lkname = hash;
}
// Normalize hash to table size
uint16_t stdiv = 0120000; // NORMALIZED STSIZE USED FOR DIVISION
while (hash >= SymbolTableSize)
{
if (hash > stdiv)
hash -= stdiv;
else
stdiv = stdiv >> 1;
}
bool found = false;
int index = hash; // Now we have starting index
int count = SymbolTableCount;
for (;;)
{
SymbolTableEntry* entry = SymbolTable + index;
if (entry->name == 0)
{
*result = index;
break; // EMPTY CELL
}
if (entry->name == lkname)
{
// AT THIS POINT HAVE FOUND A MATCHING SYMBOL NAME, NOW MUST CHECK FOR MATCHING ATTRIBUTES.
uint16_t flagsmasked = (entry->flagseg & ~lkmsk);
if (flagsmasked == lkwd)
{
if (dupmsk == 0 || (entry->status & SY_DUP) == 0)
{
*result = index;
found = true;
break;
}
//TODO: Process dups
NOTIMPLEMENTED
}
}
count--;
if (count == 0)
{
*result = index;
break; // not found
}
index++;
if (index >= SymbolTableSize)
index = 0;
}
return found;
}
// 'DLOOKE' DOES A LOOKUP & IF NOT FOUND THEN ENTERS THE NEW SYMBOL INTO
// THE SYMBOL TABLE. DOES NOT REQUIRE A SEGMENT NUMBER MATCH
// WHETHER THE SYMBOL IS A DUPLICATE OR NOT.
// Out: return = true if found, false if new entry
bool symbol_table_dlooke(uint32_t lkname, uint16_t lkwd, uint16_t lkmsk, int* pindex)
{
assert(pindex != nullptr);
bool found = symbol_table_search_routine(lkname, lkwd, lkmsk, 0, pindex);
if (found)
return true;
symbol_table_enter(pindex, lkname, lkwd);
return false;
}
// 'LOOKUP' ONLY SEARCHES THE SYMBOL TABLE FOR A SYMBOL MATCH. IF SYMBOL
// IS A DUPLICATE, THIS ROUTINE REQUIRES A SEGMENT NUMBER MATCH.
bool symbol_table_lookup(uint32_t lkname, uint16_t lkwd, uint16_t lkmsk, int* pindex)
{
assert(pindex != nullptr);
return symbol_table_search_routine(lkname, lkwd, lkmsk, SY_DUP, pindex);
}
// 'LOOKE' DOES A LOOKUP & IF NOT FOUND THEN ENTERS THE NEW SYMBOL INTO
// THE SYMBOL TABLE. IF SYMBOL IS A DUPLICATE, THIS ROUTINE
// REQUIRES A SEGMENT NUMBER MATCH.
// Out: return = true if found, false if new entry
bool symbol_table_looke(uint32_t lkname, uint16_t lkwd, uint16_t lkmsk, int* pindex)
{
assert(pindex != nullptr);
bool found = symbol_table_search_routine(lkname, lkwd, lkmsk, SY_DUP, pindex);
if (found)
return true;
symbol_table_enter(pindex, lkname, lkwd);
return false;
}
// 'SEARCH' THIS ROUTINE DOES A LOOKUP ONLY AND DOES NOT CARE WHETHER THE
// SYMBOL IS A DUPLICATE OR NOT. THIS ROUTINE IS USED REPEATEDLY
// AFTER A SINGLE CALL TO 'DLOOKE'.
bool symbol_table_search(uint32_t lkname, uint16_t lkwd, uint16_t lkmsk, int* pindex)
{
assert(pindex != nullptr);
return symbol_table_search_routine(lkname, lkwd, lkmsk, 0, pindex);
}
// Print Library Module List, for DEBUG only
void print_lml_table()
{
printf(" LibraryModuleList count = %d.\n", LibraryModuleCount);
for (int i = 0; i < LibraryModuleCount; i++)
{
const LibraryModuleEntry* lmlentry = LibraryModuleList + i;
printf(" #%04d file %02d block %03ho offset %03ho pass %d\n", (uint16_t)i, lmlentry->libfileno, lmlentry->relblockno, lmlentry->byteoffset, (int)lmlentry->passno/*, lmlentry->segmentno*/);
}
}
// Print the Symbol Table, for DEBUG only
void print_symbol_table()
{
printf(" SymbolTable count = %d.\n", SymbolTableCount);
for (int i = 0; i < SymbolTableSize; i++)
{
const SymbolTableEntry* entry = SymbolTable + i;
if (entry->name == 0)
continue;
printf(" %06ho '%s' %06ho %06ho %06ho ", (uint16_t)i, entry->unrad50name(), entry->flagseg, entry->value, entry->status);
if (entry->flagseg & SY_SEC) printf("SECT ");
if (entry->status & SY_UDF) printf("UNDEF ");
if (entry->status & SY_IND) printf("IND ");
if ((entry->flagseg & SY_SEC) == 0 && (entry->status & SY_WK)) printf("WEAK ");
if ((entry->flagseg & SY_SEC) && (entry->status & SY_SAV)) printf("SAV ");
if (entry->nextindex() == 0) printf("(eol) "); // show end-of-list node
printf("\n");
}
printf(" BEGBLK '%s' %06ho\n", unrad50(Globals.BEGBLK.symbol), Globals.BEGBLK.value);
// Enumerate entries starting with ASECT, make sure there's no loops or UNDEF entries
SymbolTableEntry* preventry = ASECTentry;
int count = 1;
for (;;)
{
int nextindex = preventry->nextindex();
if (nextindex == 0) // end of chain
break;
SymbolTableEntry* nextentry = SymbolTable + nextindex;
preventry = nextentry;
count++;
if (count > SymbolTableSize)
break;
}
if (count > SymbolTableSize)
printf(" ASECT-started list has loops.\n");
else
printf(" ASECT-started list has %d. entries.\n", count);
if (Globals.UNDLST == 0)
printf(" UNDLST = %06ho\n", (uint16_t)Globals.UNDLST);
else // Enumerate entries starting with UNDLST, make sure there's no loops or non-UNDEF entries
{
int index = Globals.UNDLST;
count = 0;
while (index != 0)
{
SymbolTableEntry* entry = SymbolTable + index;
index = entry->nextindex();
count++;
if (count > SymbolTableSize)
break;
}
if (count > SymbolTableSize)
printf(" UNDLST = %06ho; the list has loops.\n", (uint16_t)Globals.UNDLST);
else
printf(" UNDLST = %06ho; the list has %d. entries.\n", (uint16_t)Globals.UNDLST, count);
}
}
// Clear Module Section Table (MST)
void mst_table_clear()
{
memset(ModuleSectionTable, 0, ModuleSectionTableSize * sizeof(ModuleSectionEntry));
ModuleSectionCount = 0;
}
// Print Module Section Table (MST), for DEBUG only
void print_mst_table()
{
printf(" ModuleSectionTable count = %d.\n", ModuleSectionCount);
for (int m = 0; m < ModuleSectionCount; m++)
{
const ModuleSectionEntry* mstentry = ModuleSectionTable + m;
const SymbolTableEntry* entry = SymbolTable + mstentry->stindex;
printf(" #%04d index %06ho '%s' size %06ho flagseg %06ho value %06ho\n",
(uint16_t)m, mstentry->stindex,
mstentry->stindex == 0 ? "" : entry->unrad50name(),
mstentry->size,
entry->flagseg, entry->value);
}
}
/////////////////////////////////////////////////////////////////////////////