parse.c 21.9 KB
Newer Older
Camil Staps's avatar
Camil Staps committed
1
#include <stdlib.h>
2
#include <string.h>
Camil Staps's avatar
Camil Staps committed
3

Camil Staps's avatar
Camil Staps committed
4
#include "abc_instructions.h"
Camil Staps's avatar
Camil Staps committed
5
#include "parse.h"
Camil Staps's avatar
Camil Staps committed
6
#include "util.h"
Camil Staps's avatar
Camil Staps committed
7

8 9 10 11
#ifdef INTERPRETER
# include "interpret.h"
#endif

12
#ifdef LINKER
13
# include "bcgen_instructions.h"
14 15
#endif

Camil Staps's avatar
Camil Staps committed
16 17
#ifdef PRELINKER
# include "bcprelink.h"
18 19
#endif

Camil Staps's avatar
Camil Staps committed
20 21 22 23 24 25 26 27
#ifdef LINK_CLEAN_RUNTIME
void preseed_symbol_matcher(struct parser *state, const char *label, void *location) {
       struct host_symbol *sym=find_host_symbol_by_name(state->program,(char*)label);
       if (sym!=NULL)
               sym->interpreter_location=location;
}
#endif

28 29 30 31 32
void init_parser(struct parser *state
#ifdef LINK_CLEAN_RUNTIME
		, int host_symbols_n, int host_symbols_string_length, char *host_symbols
#endif
		) {
Camil Staps's avatar
Camil Staps committed
33
	state->state = PS_init;
Camil Staps's avatar
Camil Staps committed
34
	state->program = safe_calloc(1, sizeof(struct program));
35 36 37

	state->ptr = 0;

38 39
	state->code_reloc_size = 0;
	state->data_reloc_size = 0;
40 41

	state->strings_size = 0;
42
#if defined(INTERPRETER) && WORD_WIDTH == 32
43 44 45
	state->read_n = 0;
	state->data_n_words = 0;
	state->words_in_strings = 0;
46
	state->strings = NULL;
47 48 49
	state->strings_ptr = 0;
	state->relocation_offset = 0;
#endif
50 51

	state->symbols_ptr = 0;
Camil Staps's avatar
Camil Staps committed
52

53
#ifdef LINK_CLEAN_RUNTIME
54 55 56
	state->program->host_symbols_n = host_symbols_n;
	state->program->host_symbols = safe_malloc(host_symbols_n * sizeof(struct host_symbol));
	state->program->host_symbols_strings = safe_malloc(host_symbols_string_length + host_symbols_n);
57

58
	char *symbol_strings = state->program->host_symbols_strings;
59 60 61
#ifdef MACH_O64
	BC_WORD offset=0;
#endif
62
	for (int i = 0; i < host_symbols_n; i++) {
63
		state->program->host_symbols[i].interpreter_location = (void*) -1;
64
		state->program->host_symbols[i].location = *(void**)host_symbols;
65
		host_symbols += IF_INT_64_OR_32(8,4);
66
		state->program->host_symbols[i].name = symbol_strings;
67 68 69 70
		for (; *host_symbols; host_symbols++)
			*symbol_strings++ = *host_symbols;
		*symbol_strings++ = '\0';
		host_symbols++;
71 72

#ifdef MACH_O64
73
		if (!strcmp(state->program->host_symbols[i].name,"__ARRAY__"))
74 75
			offset=(BC_WORD)&__ARRAY__-(BC_WORD)state->program->host_symbols[i].location;
#endif
76
	}
77 78 79 80
#ifdef MACH_O64
	for (int i=0; i<host_symbols_n; i++)
		state->program->host_symbols[i].location=(void*)((BC_WORD)state->program->host_symbols[i].location+offset);
#endif
81

82
	preseed_symbol_matcher(state, "INT", (void*) &INT);
Camil Staps's avatar
Camil Staps committed
83 84 85 86 87 88
	preseed_symbol_matcher(state, "dINT", (void*) &dINT);
	preseed_symbol_matcher(state, "BOOL", (void*) &BOOL);
	preseed_symbol_matcher(state, "CHAR", (void*) &CHAR);
	preseed_symbol_matcher(state, "REAL", (void*) &REAL);
	preseed_symbol_matcher(state, "__ARRAY__", (void*) &__ARRAY__);
	preseed_symbol_matcher(state, "__STRING__", (void*) &__STRING__);
89 90
#endif

Camil Staps's avatar
Camil Staps committed
91 92 93 94 95
#ifdef LINKER
	state->code_size = 0;
	state->data_size = 0;
	state->code_offset = 0;
	state->data_offset = 0;
96
	state->is_main_module = 0;
Camil Staps's avatar
Camil Staps committed
97
#endif
98

99 100 101 102 103
#ifdef INTERPRETER
	state->program->code_symbols_matching=NULL;
	state->program->data_symbols_matching=NULL;
#endif

104 105 106
#ifdef DEBUG_CURSES
	state->program->nr_instructions = 0;
#endif
107 108
}

109
void free_parser(struct parser *state) {
110
#if defined(INTERPRETER) && WORD_WIDTH == 32
111 112
	if (state->strings != NULL)
		free(state->strings);
113
#endif
114 115
}

116
void next_state(struct parser *state) {
117
	state->ptr = 0;
118
#if defined(INTERPRETER) && WORD_WIDTH == 32
119 120 121
	state->strings_ptr = 0;
	state->relocation_offset = 0;
#endif
122
	state->symbols_ptr = 0;
123

124
	switch (state->state) {
Camil Staps's avatar
Camil Staps committed
125
		case PS_init:
126
			state->state = PS_code;
127
#ifdef LINKER
128 129
			if (state->code_size > 0)
#else
130
			if (state->program->code_size > 0)
131
#endif
132 133
				return;
		case PS_code:
134 135 136 137
			state->state = PS_strings;
			if (state->strings_size > 0)
				return;
		case PS_strings:
138
			state->state = PS_data;
139
#ifdef LINKER
140 141
			if (state->data_size > 0)
#else
142
			if (state->program->data_size > 0)
143
#endif
144 145
				return;
		case PS_data:
146 147 148 149
			state->state = PS_symbol_table;
			if (state->program->symbol_table_size > 0)
				return;
		case PS_symbol_table:
150 151
			state->state = PS_code_reloc;
			if (state->code_reloc_size > 0)
152
				return;
153 154 155
		case PS_code_reloc:
			state->state = PS_data_reloc;
			if (state->data_reloc_size > 0)
156
				return;
157
		case PS_data_reloc:
158
		case PS_end:
159
#ifdef LINKER
160 161 162
			state->code_offset += state->code_size;
			state->data_offset += state->data_size;
#endif
163 164 165 166 167
			state->state = PS_end;
			return;
	}
}

168 169 170 171
void shift_address(BC_WORD *addr) {
	*addr = ((*addr << 1) & -7) | (*addr & 3);
}

172 173 174 175
/* Return values:
 * 0: success
 * 1: unexpected end of string/file
 * 2: illegal instruction
176 177 178
 * 3: internal state machine error
 * 4: wrong magic number
 * 5: wrong version number */
179
int parse_program(struct parser *state, struct char_provider *cp) {
180
	char elem8;
181 182 183
	int16_t elem16;
	int32_t elem32;
	int64_t elem64;
184

185 186 187
#ifdef LINK_CLEAN_RUNTIME
	build_host_nodes();
#endif
188 189
#ifdef COMPUTED_GOTOS
	/* See rationale in interpret.h */
Camil Staps's avatar
Camil Staps committed
190 191 192 193 194
	interpret(NULL,
#ifdef LINK_CLEAN_RUNTIME
			0,
#endif
			NULL, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL);
195

196
	for (int i=0; i<32; i++)
197
		Fjmp_ap[i]=(BC_WORD)instruction_labels[Fjmp_ap[i]];
198

199
	__interpreter_cycle_in_spine[1] = (void*) instruction_labels[(BC_WORD)__interpreter_cycle_in_spine[1]];
Camil Staps's avatar
Camil Staps committed
200 201 202 203 204 205 206
	__interpreter_indirection[0] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[0]];
	__interpreter_indirection[1] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[1]];
	__interpreter_indirection[2] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[2]];
	__interpreter_indirection[3] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[3]];
	__interpreter_indirection[5] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[5]];
	__interpreter_indirection[7] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[7]];
	__interpreter_indirection[8] = (void*) instruction_labels[(BC_WORD)__interpreter_indirection[8]];
207 208

# ifdef LINK_CLEAN_RUNTIME
209 210
	for (int i = 0; i < 32; i++)
		HOST_NODES[i][1] = instruction_labels[Cjsr_eval_host_node+i];
211
# endif
212 213
#endif

214 215
	while (state->state != PS_end) {
		switch (state->state) {
Camil Staps's avatar
Camil Staps committed
216
			case PS_init:
217
			{
218
				uint32_t header_length,code_size;
219 220 221 222 223 224 225 226 227

				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				if (elem32 != ABC_MAGIC_NUMBER)
					return 4;

				if (provide_chars(&header_length, sizeof(header_length), 1, cp) < 0)
					return 1;

228 229
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
230 231 232 233 234 235 236
				header_length-=4;
				if (elem32 != ABC_VERSION)
					return 5;

				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				header_length-=4;
237
#ifdef LINKER
238
				state->code_size = code_size = elem32;
239
#else
240
				state->program->code_size = code_size = elem32;
241
#endif
Camil Staps's avatar
Camil Staps committed
242

243 244
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
245
				header_length-=4;
246
#ifdef LINKER
247
				add_words_in_strings(elem32);
Camil Staps's avatar
Camil Staps committed
248
#elif defined(INTERPRETER) && WORD_WIDTH==32
249 250
				state->words_in_strings = elem32;
#endif
Camil Staps's avatar
Camil Staps committed
251

252 253
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
254
				header_length-=4;
255
				state->strings_size = elem32;
Camil Staps's avatar
Camil Staps committed
256
#if defined(INTERPRETER) && WORD_WIDTH == 32
257 258 259 260
				/* Allocate one more to prevent reading out of bounds in PS_data */
				state->strings = safe_malloc(sizeof(uint32_t*) * (elem32+1));
				state->strings[elem32] = 0;
#endif
Camil Staps's avatar
Camil Staps committed
261

262 263
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
264
				header_length-=4;
265
#ifdef LINKER
266 267
				state->data_size = elem32;
#else
Camil Staps's avatar
Camil Staps committed
268
# if defined(INTERPRETER) && WORD_WIDTH==32
269 270 271
				state->data_n_words = elem32;
				/* Allocate extra space because strings take more words on 32-bit */
				state->program->data_size = elem32 + state->words_in_strings;
272
# else
273
				state->program->data_size = elem32;
274
# endif
Camil Staps's avatar
Camil Staps committed
275 276
				/* The prelinker writes data size between code and data segment, so reserve this space.
				 * TODO: better would be to use a different file format in the prelinker. */
277 278
				state->program->code = safe_malloc(sizeof(BC_WORD) * (code_size+state->program->data_size+1));
				state->program->data = state->program->code + code_size + 1;
279
#endif
Camil Staps's avatar
Camil Staps committed
280

281 282
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
283
				header_length-=4;
284 285 286 287
				state->program->symbol_table_size = elem32;
				state->program->symbol_table = safe_malloc(elem32 * sizeof(struct symbol));
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
288
				header_length-=4;
289
				state->program->symbols = safe_malloc(elem32 + state->program->symbol_table_size);
Camil Staps's avatar
Camil Staps committed
290

291 292
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
293
				header_length-=4;
294
				state->code_reloc_size = elem32;
Camil Staps's avatar
Camil Staps committed
295

296 297
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
298
				header_length-=4;
299
				state->data_reloc_size = elem32;
Camil Staps's avatar
Camil Staps committed
300

301 302
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
303
				header_length-=4;
304 305
				state->program->start_symbol_id = elem32;

306 307 308 309 310 311 312 313
				while (header_length >= sizeof(elem32)) {
					if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
						return 1;
					header_length -= sizeof(elem32);
				}
				if (header_length > 0 && provide_chars(&elem32, header_length, 1, cp) < 0)
					return 1;

314
				next_state(state);
315
				break;
316
			}
Camil Staps's avatar
Camil Staps committed
317
			case PS_code: {
318 319
				if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
					return 1;
320
#if 0
Camil Staps's avatar
Camil Staps committed
321
				EPRINTF(":%d\t%d\t%s %s\n", state->ptr, elem16, instruction_name(elem16), instruction_type(elem16));
322
#endif
323
#ifdef LINKER
324 325 326
				state->ptr++;
				store_code_elem(2, elem16);
#else
327 328 329
# ifdef COMPUTED_GOTOS
				state->program->code[state->ptr++] = (BC_WORD) instruction_labels[elem16];
# else
Camil Staps's avatar
Camil Staps committed
330
				state->program->code[state->ptr++] = elem16;
331
# endif
332 333 334
#endif
#ifdef DEBUG_CURSES
				state->program->nr_instructions++;
335
#endif
336
				const char *type = instruction_type(elem16);
Camil Staps's avatar
Camil Staps committed
337
				for (; *type; type++) {
338
#ifdef LINKER
339 340
					state->ptr++;
#endif
341
					switch (*type) {
342
						case 'I': /* Instruction */
343 344
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
345
#ifdef LINKER
346 347
							store_code_elem(2, elem16);
#else
348 349 350
# ifdef COMPUTED_GOTOS
							state->program->code[state->ptr++] = (BC_WORD) instruction_labels[elem16];
# else
351
							state->program->code[state->ptr++] = elem16;
352
# endif
353
#endif
354
							break;
355
						case 'n': /* Stack index */
356 357
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
358
#ifdef LINKER
359 360
							store_code_elem(2, elem16);
#else
361
							state->program->code[state->ptr++] = elem16;
362
#endif
363 364
							break;
						case 'N': /* Stack index, optimised to byte width */
365 366
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
367
#ifdef LINKER
368 369
							store_code_elem(2, elem16);
#else
370
							state->program->code[state->ptr++] = ((BC_WORD_S) elem16) * IF_INT_64_OR_32(8, 4);
371
#endif
372
							break;
373
						case 'a': /* Arity */
374 375
							if (provide_chars(&elem16, sizeof(elem16), 1, cp) < 0)
								return 1;
376
#ifdef LINKER
377 378
							store_code_elem(2, elem16);
#else
379
							/* Shift so that offset -1 contains the arity; this is used in the garbage collector */
380
							state->program->code[state->ptr++] = (BC_WORD) elem16 << IF_INT_64_OR_32(32, 0);
381
#endif
382
							break;
383
						case 'l': /* Label */
384
						case 'C': /* CAF label */
385 386
						case 'S': /* String label */
						case 's': /* String label */
387 388
							if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
								return 1;
389
#ifdef LINKER
390 391 392 393
							store_code_elem(4, elem32);
#else
							state->program->code[state->ptr++] = elem32;
#endif
394
							break;
395
						case 'r': /* Real */
396 397
							if (provide_chars(&elem64, sizeof(elem64), 1, cp) < 0)
								return 1;
398
#ifdef LINKER
399
							store_code_elem(8, elem64);
400
#else
401 402 403
# if (WORD_WIDTH == 64)
							state->program->code[state->ptr++] = elem64;
# else
404 405
							float f = *(double*)&elem64;
							state->program->code[state->ptr++] = *(BC_WORD*)&f;
406
# endif
407
#endif
408
							break;
409
						case 'c': /* Char */
410
							if (provide_chars(&elem8, sizeof(elem8), 1, cp) < 0)
411
								return 1;
412
#ifdef LINKER
413
							store_code_elem(1, elem8);
414
#else
415
							state->program->code[state->ptr++] = elem8;
416
#endif
417
							break;
418
						case 'i':
419 420
							if (provide_chars(&elem64, sizeof(elem64), 1, cp) < 0)
								return 1;
421
#ifdef LINKER
422 423
							store_code_elem(8, elem64);
#else
424
							state->program->code[state->ptr++] = elem64;
425
#endif
426 427 428 429
							break;
						case '?':
							EPRINTF(":%d\t%d\t%s %s\n", state->ptr, elem16, instruction_name(elem16), instruction_type(elem16));
							EPRINTF("\tUnknown instruction; add to abc_instructions.c\n");
430 431
							EXIT((void*)-1,-1);
							return 2;
432 433
						default:
							EPRINTF("\tUnknown type character '%c' in type of %s\n",*type,instruction_name(elem16));
434 435
							EXIT((void*)-1,1);
							return 2;
436
					}
Camil Staps's avatar
Camil Staps committed
437
				}
438

439
#ifdef LINKER
440 441
				if (state->ptr >= state->code_size) {
#else
442
				if (state->ptr >= state->program->code_size) {
443
#endif
444 445 446
					state->ptr = 0;
					next_state(state);
				}
Camil Staps's avatar
Camil Staps committed
447
				break; }
448
			case PS_strings:
449 450
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
451
#ifdef LINKER
Camil Staps's avatar
Camil Staps committed
452
				add_string_information(elem32 + state->data_offset);
Camil Staps's avatar
Camil Staps committed
453
#elif defined(INTERPRETER) && WORD_WIDTH==32
454
				state->strings[state->ptr] = elem32;
455
#endif
456
				if (++state->ptr >= state->strings_size)
457 458 459
					next_state(state);
				break;
			case PS_data:
460 461
				if (provide_chars(&elem64, sizeof(elem64), 1, cp) < 0)
					return 1;
462
#ifdef LINKER
463 464 465
				store_data_l(elem64);
				state->ptr++;
#else
466
				state->program->data[state->ptr++] = elem64;
467
#endif
Camil Staps's avatar
Camil Staps committed
468
#if defined(INTERPRETER) && WORD_WIDTH==32
469 470 471 472 473 474
				/* On 64-bit, strings can be read as-is. On 32-bit, we need to
				 * read 64 bits and store them in two words. */
				if (state->strings[state->strings_ptr] == state->read_n) {
					int length = elem64;
					uint64_t bytes;
					while (length >= 8) {
475 476
						if (provide_chars(&bytes, sizeof(bytes), 1, cp) < 0)
							return 1;
477 478 479 480 481 482
						state->program->data[state->ptr++] = bytes & 0xffffffff;
						state->program->data[state->ptr++] = bytes >> 32;
						length -= 8;
						state->read_n++;
					}
					if (length > 0) {
483 484
						if (provide_chars(&bytes, sizeof(bytes), 1, cp) < 0)
							return 1;
485 486 487 488 489 490 491 492 493
						state->program->data[state->ptr++] = bytes & 0xffffffff;
						if (length > 4)
							state->program->data[state->ptr++] = bytes >> 32;
						state->read_n++;
					}
					state->strings_ptr++;
				}

				if (++state->read_n >= state->data_n_words)
494
#elif defined(LINKER)
495
				if (state->ptr >= state->data_size)
496 497 498
#else
				if (state->ptr >= state->program->data_size)
#endif
499
					next_state(state);
500
				break;
501 502 503 504
			case PS_symbol_table:
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				state->program->symbol_table[state->ptr].offset = elem32;
505
#ifdef LINKER
506 507 508
				if (elem32 != -1)
					state->program->symbol_table[state->ptr].offset += (elem32 & 1 ? state->data_offset : state->code_offset) * 4;
#endif
509 510 511 512 513 514
				state->program->symbol_table[state->ptr].name = state->program->symbols + state->symbols_ptr;
				do {
					if (provide_chars(&elem8, sizeof(elem8), 1, cp) < 0)
						return 1;
					state->program->symbols[state->symbols_ptr++] = elem8;
				} while (elem8);
Camil Staps's avatar
Camil Staps committed
515
#if defined(INTERPRETER) || defined(PRELINKER)
516
# ifdef INTERPRETER
Camil Staps's avatar
Camil Staps committed
517
#  define INTERPRETER_OR_PRELINKER(i,u) i
518
# else
Camil Staps's avatar
Camil Staps committed
519
#  define INTERPRETER_OR_PRELINKER(i,u) (u*8)
520
# endif
521
				if (!strcmp(state->program->symbol_table[state->ptr].name, "__ARRAY__")) {
Camil Staps's avatar
Camil Staps committed
522
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__ARRAY__,1);
523
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "__STRING__")) {
Camil Staps's avatar
Camil Staps committed
524
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__STRING__,6);
525 526
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "INT") ||
						!strcmp(state->program->symbol_table[state->ptr].name, "dINT")) {
Camil Staps's avatar
Camil Staps committed
527
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&INT,26);
528
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "BOOL")) {
Camil Staps's avatar
Camil Staps committed
529
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&BOOL,11);
530
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "CHAR")) {
Camil Staps's avatar
Camil Staps committed
531
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&CHAR,16);
532
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "REAL")) {
Camil Staps's avatar
Camil Staps committed
533
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&REAL,21);
534
				} else if (state->program->symbol_table[state->ptr].offset == -1) {
535
# ifdef DEBUG_CLEAN_LINKS
Camil Staps's avatar
Camil Staps committed
536
					EPRINTF("Warning: symbol '%s' is not defined.\n",state->program->symbol_table[state->ptr].name);
537
# endif
538
				} else
539
				if (state->program->symbol_table[state->ptr].offset & 1) /* data symbol */ {
540
					state->program->symbol_table[state->ptr].offset &= -2;
541
# if (WORD_WIDTH == 64)
542
					state->program->symbol_table[state->ptr].offset *= 2;
543
# else
544 545 546 547 548 549 550 551 552 553 554
					/* code[elem32] is an offset to the abstract data segment.
					 * This offset is incorrect, because strings are longer on
					 * 32-bit. Thus, we add the required offset. This is not
					 * that efficient, but it's okay since it is only for
					 * 32-bit and only during parsing. */
					state->program->symbol_table[state->ptr].offset &= -2;
					int temp_relocation_offset = 0;
					for (int i = 0; state->program->symbol_table[state->ptr].offset / 4 > state->strings[i] && i < state->strings_size; i++)
						temp_relocation_offset += (state->program->data[state->strings[i] + temp_relocation_offset] + 3) / 8;
					state->program->symbol_table[state->ptr].offset += temp_relocation_offset * 4;
# endif
555
# ifdef INTERPRETER
556
					state->program->symbol_table[state->ptr].offset += (BC_WORD) state->program->data;
Camil Staps's avatar
Camil Staps committed
557 558
# elif defined(PRELINKER)
					state->program->symbol_table[state->ptr].offset += ((BC_WORD)state->program->code_size+3)*8+sizeof(prelinker_preamble);
559
# endif
560 561 562 563 564 565 566
# ifdef LINK_CLEAN_RUNTIME
					if (state->program->symbol_table[state->ptr].name[0]) {
						int v = ((BC_WORD*)state->program->symbol_table[state->ptr].offset)[-2];
						if (v == 0) {
							/* Descriptor has a code address that is not _hnf; ignore */
						} else if (v == -1) {
							/* Descriptor has a _hnf code address */
567
							struct host_symbol *host_sym = find_host_symbol_by_name(state->program, state->program->symbol_table[state->ptr].name);
568
							if (host_sym == NULL) {
569
#  ifdef DEBUG_CLEAN_LINKS
Camil Staps's avatar
Camil Staps committed
570
								EPRINTF("Warning: symbol '%s' not present in host\n",state->program->symbol_table[state->ptr].name);
571
#  endif
572 573 574 575
							} else {
								((BC_WORD*)state->program->symbol_table[state->ptr].offset)[-2] = (BC_WORD) host_sym->location;
								host_sym->interpreter_location = (BC_WORD*) state->program->symbol_table[state->ptr].offset;
							}
576 577
						} else {
							/* This shouldn't happen */
Camil Staps's avatar
Camil Staps committed
578
							EPRINTF("Parse error: %s should have -1/0 for descriptor resolve address\n",state->program->symbol_table[state->ptr].name);
579 580
							EXIT((void*)-1,1);
							return 2;
581
						}
582
					}
583 584 585 586
# endif
# ifdef DEBUG_CURSES
					if (!strcmp(state->program->symbol_table[state->ptr].name, "ARRAY"))
						ARRAY = (void*) state->program->symbol_table[state->ptr].offset;
587
# endif
588 589 590 591
				} else /* code symbol */ {
# if (WORD_WIDTH == 64)
					state->program->symbol_table[state->ptr].offset *= 2;
# endif
592
# ifdef INTERPRETER
593
					state->program->symbol_table[state->ptr].offset += (BC_WORD) state->program->code;
Camil Staps's avatar
Camil Staps committed
594 595
# elif defined(PRELINKER)
					state->program->symbol_table[state->ptr].offset += 2*8+sizeof(prelinker_preamble);
596
# endif
597 598 599 600 601 602 603 604 605
# ifdef LINK_CLEAN_RUNTIME
					if (state->program->symbol_table[state->ptr].name[0]) {
						/* Descriptor has a _hnf code address */
						struct host_symbol *host_sym = find_host_symbol_by_name(state->program, state->program->symbol_table[state->ptr].name);
						if (host_sym != NULL) {
							host_sym->interpreter_location = (BC_WORD*) state->program->symbol_table[state->ptr].offset;
						}
					}
# endif
606
				}
607
#elif defined(LINKER)
608 609
				if (state->program->symbol_table[state->ptr].name[0] != '\0') {
					struct label *label = enter_label(state->program->symbol_table[state->ptr].name);
610 611
					if (state->program->symbol_table[state->ptr].offset != -1)
						label->label_offset = state->program->symbol_table[state->ptr].offset;
612 613
					make_label_global(label);
				}
614 615 616

				if (state->is_main_module && state->program->start_symbol_id==state->ptr)
					code_start(state->program->symbol_table[state->ptr].name);
617
#endif
618 619 620
				if (++state->ptr >= state->program->symbol_table_size)
					next_state(state);
				break;
621 622 623 624 625 626 627 628
			case PS_code_reloc:
				{
					uint32_t code_i,sym_i;
					if (provide_chars(&code_i, sizeof(code_i), 1, cp) < 0)
						return 1;

					if (provide_chars(&sym_i, sizeof(sym_i), 1, cp) < 0)
						return 1;
629
					struct symbol *sym = &state->program->symbol_table[sym_i];
630

631
#ifdef LINKER
632 633 634 635 636
					struct label *label;
					if (sym->name[0] == '\0')
						label = new_label(sym->offset);
					else
						label = enter_label(sym->name);
637
					add_code_relocation(label, code_i + state->code_offset);
638 639
#else
# if (WORD_WIDTH == 64)
640
					shift_address(&state->program->code[code_i]);
641
# endif
642
					state->program->code[code_i] += sym->offset;
643
#endif
644
				}
645 646 647 648

				if (++state->ptr >= state->code_reloc_size)
					next_state(state);
				break;
649 650 651 652 653 654 655 656
			case PS_data_reloc:
				{
					uint32_t data_i,sym_i;
					if (provide_chars(&data_i, sizeof(data_i), 1, cp) < 0)
						return 1;

					if (provide_chars(&sym_i, sizeof(sym_i), 1, cp) < 0)
						return 1;
657
					struct symbol *sym = &state->program->symbol_table[sym_i];
658

659
#ifdef LINKER
660 661 662 663 664
					struct label *label;
					if (sym->name[0] == '\0')
						label = new_label(sym->offset);
					else
						label = enter_label(sym->name);
665
					add_data_relocation(label, data_i + state->data_offset);
666 667
#else
# if (WORD_WIDTH == 64)
668
					shift_address(&state->program->data[data_i]);
669
# endif
670

Camil Staps's avatar
Camil Staps committed
671
# if defined(INTERPRETER) && WORD_WIDTH==32
672 673 674 675 676 677 678
					/* data_i is an offset to the abstract data segment. We need to
					 * fix it up for the extra length of strings on 32-bit. */
					while (data_i >= state->strings[state->strings_ptr]) {
						state->relocation_offset += (state->program->data[state->strings[state->strings_ptr] + state->relocation_offset] + 3) / 8;
						state->strings_ptr++;
					}
					data_i += state->relocation_offset;
679
# endif
680

681
					state->program->data[data_i] += sym->offset;
682
#endif
683
				}
684 685 686 687

				if (++state->ptr >= state->data_reloc_size)
					next_state(state);
				break;
688 689 690
			default:
				return 3;
		}
Camil Staps's avatar
Camil Staps committed
691
	}
692 693 694 695

#ifdef LINK_CLEAN_RUNTIME
	sort_host_symbols_by_location(state->program);
#endif
696
	return 0;
Camil Staps's avatar
Camil Staps committed
697
}