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"
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
	preseed_symbol_matcher(state, "e__system__nind", (void*) &__interpreter_indirection[5]);
90 91
#endif

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

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

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

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

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

125
	switch (state->state) {
Camil Staps's avatar
Camil Staps committed
126
		case PS_init:
127
			state->state = PS_code;
128
#ifdef LINKER
129 130
			if (state->code_size > 0)
#else
131
			if (state->program->code_size > 0)
132
#endif
133 134
				return;
		case PS_code:
135 136 137 138
			state->state = PS_strings;
			if (state->strings_size > 0)
				return;
		case PS_strings:
139
			state->state = PS_data;
140
#ifdef LINKER
141 142
			if (state->data_size > 0)
#else
143
			if (state->program->data_size > 0)
144
#endif
145 146
				return;
		case PS_data:
147
			state->state = PS_symbol_table;
148 149 150 151
#ifdef LINKER
			state->new_label_nodes=safe_malloc(state->program->symbol_table_size*sizeof(struct label_node*));
			state->n_labels=0;
#endif
152 153 154
			if (state->program->symbol_table_size > 0)
				return;
		case PS_symbol_table:
155 156 157 158 159 160 161
#ifdef LINKER
			merge_new_labels_and_rebalance(state->new_label_nodes,state->n_labels);
			free(state->new_label_nodes);

			if (state->is_main_module && state->program->start_symbol_id<state->program->symbol_table_size)
				code_start(state->program->symbol_table[state->program->start_symbol_id].name);
#endif
162 163
			state->state = PS_code_reloc;
			if (state->code_reloc_size > 0)
164
				return;
165 166 167
		case PS_code_reloc:
			state->state = PS_data_reloc;
			if (state->data_reloc_size > 0)
168
				return;
169
		case PS_data_reloc:
170
		case PS_end:
171
#ifdef LINKER
172 173 174
			state->code_offset += state->code_size;
			state->data_offset += state->data_size;
#endif
175 176 177 178 179
			state->state = PS_end;
			return;
	}
}

180 181 182 183
void shift_address(BC_WORD *addr) {
	*addr = ((*addr << 1) & -7) | (*addr & 3);
}

184 185 186 187
/* Return values:
 * 0: success
 * 1: unexpected end of string/file
 * 2: illegal instruction
188 189 190
 * 3: internal state machine error
 * 4: wrong magic number
 * 5: wrong version number */
191
int parse_program(struct parser *state, struct char_provider *cp) {
192
	char elem8;
193 194 195
	int16_t elem16;
	int32_t elem32;
	int64_t elem64;
196

197 198
	while (state->state != PS_end) {
		switch (state->state) {
Camil Staps's avatar
Camil Staps committed
199
			case PS_init:
200
			{
201
				uint32_t header_length,code_size;
202 203 204 205 206 207 208 209 210

				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;

211 212
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
213 214 215 216 217 218 219
				header_length-=4;
				if (elem32 != ABC_VERSION)
					return 5;

				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				header_length-=4;
220
#ifdef LINKER
221
				state->code_size = code_size = elem32;
222
#else
223
				state->program->code_size = code_size = elem32;
224
#endif
Camil Staps's avatar
Camil Staps committed
225

226 227
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
228
				header_length-=4;
229
#ifdef LINKER
230
				add_words_in_strings(elem32);
Camil Staps's avatar
Camil Staps committed
231
#elif defined(INTERPRETER) && WORD_WIDTH==32
232 233
				state->words_in_strings = elem32;
#endif
Camil Staps's avatar
Camil Staps committed
234

235 236
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
237
				header_length-=4;
238
				state->strings_size = elem32;
Camil Staps's avatar
Camil Staps committed
239
#if defined(INTERPRETER) && WORD_WIDTH == 32
240 241 242 243
				/* 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
244

245 246
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
247
				header_length-=4;
248
#ifdef LINKER
249 250
				state->data_size = elem32;
#else
Camil Staps's avatar
Camil Staps committed
251
# if defined(INTERPRETER) && WORD_WIDTH==32
252 253 254
				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;
255
# else
256
				state->program->data_size = elem32;
257
# endif
Camil Staps's avatar
Camil Staps committed
258 259
				/* 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. */
260 261
				state->program->code = safe_malloc(sizeof(BC_WORD) * (code_size+state->program->data_size+1));
				state->program->data = state->program->code + code_size + 1;
262
#endif
Camil Staps's avatar
Camil Staps committed
263

264 265
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
266
				header_length-=4;
267 268 269 270
				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;
271
				header_length-=4;
272
				state->program->symbols = safe_malloc(elem32 + state->program->symbol_table_size);
Camil Staps's avatar
Camil Staps committed
273

274 275
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
276
				header_length-=4;
277
				state->code_reloc_size = elem32;
Camil Staps's avatar
Camil Staps committed
278

279 280
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
281
				header_length-=4;
282
				state->data_reloc_size = elem32;
Camil Staps's avatar
Camil Staps committed
283

284 285
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
286
				header_length-=4;
287 288
				state->program->start_symbol_id = elem32;

289 290 291 292 293 294 295 296
				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;

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

422
#ifdef LINKER
423 424
				if (state->ptr >= state->code_size) {
#else
425
				if (state->ptr >= state->program->code_size) {
426
#endif
427 428 429
					state->ptr = 0;
					next_state(state);
				}
Camil Staps's avatar
Camil Staps committed
430
				break; }
431
			case PS_strings:
432 433
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
434
#ifdef LINKER
435
				add_string_information(elem32 + state->data_offset);
Camil Staps's avatar
Camil Staps committed
436
#elif defined(INTERPRETER) && WORD_WIDTH==32
437
				state->strings[state->ptr] = elem32;
438
#endif
439
				if (++state->ptr >= state->strings_size)
440 441 442
					next_state(state);
				break;
			case PS_data:
443 444
				if (provide_chars(&elem64, sizeof(elem64), 1, cp) < 0)
					return 1;
445
#ifdef LINKER
446 447 448
				store_data_l(elem64);
				state->ptr++;
#else
449
				state->program->data[state->ptr++] = elem64;
450
#endif
Camil Staps's avatar
Camil Staps committed
451
#if defined(INTERPRETER) && WORD_WIDTH==32
452 453 454 455 456 457
				/* 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) {
458 459
						if (provide_chars(&bytes, sizeof(bytes), 1, cp) < 0)
							return 1;
460 461 462 463 464 465
						state->program->data[state->ptr++] = bytes & 0xffffffff;
						state->program->data[state->ptr++] = bytes >> 32;
						length -= 8;
						state->read_n++;
					}
					if (length > 0) {
466 467
						if (provide_chars(&bytes, sizeof(bytes), 1, cp) < 0)
							return 1;
468 469 470 471 472 473 474 475 476
						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)
477
#elif defined(LINKER)
478
				if (state->ptr >= state->data_size)
479 480 481
#else
				if (state->ptr >= state->program->data_size)
#endif
482
					next_state(state);
483
				break;
484 485 486 487
			case PS_symbol_table:
				if (provide_chars(&elem32, sizeof(elem32), 1, cp) < 0)
					return 1;
				state->program->symbol_table[state->ptr].offset = elem32;
488
#ifdef LINKER
489 490 491
				if (elem32 != -1)
					state->program->symbol_table[state->ptr].offset += (elem32 & 1 ? state->data_offset : state->code_offset) * 4;
#endif
492 493 494 495 496 497
				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
498
#if defined(INTERPRETER) || defined(PRELINKER)
499
# ifdef INTERPRETER
Camil Staps's avatar
Camil Staps committed
500
#  define INTERPRETER_OR_PRELINKER(i,u) i
501
# else
Camil Staps's avatar
Camil Staps committed
502
#  define INTERPRETER_OR_PRELINKER(i,u) (u*8)
503
# endif
504
				if (!strcmp(state->program->symbol_table[state->ptr].name, "__ARRAY__")) {
Camil Staps's avatar
Camil Staps committed
505
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__ARRAY__,1);
506
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "__STRING__")) {
Camil Staps's avatar
Camil Staps committed
507
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__STRING__,6);
508 509
				} 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
510
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&INT,26);
511
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "BOOL")) {
Camil Staps's avatar
Camil Staps committed
512
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&BOOL,11);
513
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "CHAR")) {
Camil Staps's avatar
Camil Staps committed
514
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&CHAR,16);
515
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "REAL")) {
Camil Staps's avatar
Camil Staps committed
516
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&REAL,21);
517 518
				} else if (!strcmp(state->program->symbol_table[state->ptr].name, "e__system__nind")) {
					state->program->symbol_table[state->ptr].offset = (BC_WORD) INTERPRETER_OR_PRELINKER(&__interpreter_indirection[5], 137);
519
				} else if (state->program->symbol_table[state->ptr].offset == -1) {
520
# ifdef DEBUG_CLEAN_LINKS
521
					EPRINTF("Warning: symbol '%s' is not defined.\n",state->program->symbol_table[state->ptr].name);
522
# endif
523
				} else
524
				if (state->program->symbol_table[state->ptr].offset & 1) /* data symbol */ {
525
					state->program->symbol_table[state->ptr].offset &= -2;
526
# if (WORD_WIDTH == 64)
527
					state->program->symbol_table[state->ptr].offset *= 2;
528
# else
529 530 531 532 533 534 535 536 537 538 539
					/* 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
540
# ifdef INTERPRETER
541
					state->program->symbol_table[state->ptr].offset += (BC_WORD) state->program->data;
Camil Staps's avatar
Camil Staps committed
542 543
# elif defined(PRELINKER)
					state->program->symbol_table[state->ptr].offset += ((BC_WORD)state->program->code_size+3)*8+sizeof(prelinker_preamble);
544
# endif
545 546 547 548 549 550 551
# 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 */
552
							struct host_symbol *host_sym = find_host_symbol_by_name(state->program, state->program->symbol_table[state->ptr].name);
553
							if (host_sym == NULL) {
554
#  ifdef DEBUG_CLEAN_LINKS
555
								EPRINTF("Warning: symbol '%s' not present in host\n",state->program->symbol_table[state->ptr].name);
556
#  endif
557 558 559 560
							} 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;
							}
561 562
						} else {
							/* This shouldn't happen */
563
							EPRINTF("Parse error: %s should have -1/0 for descriptor resolve address\n",state->program->symbol_table[state->ptr].name);
564 565
							EXIT((void*)-1,1);
							return 2;
566
						}
567
					}
568 569 570 571
# endif
# ifdef DEBUG_CURSES
					if (!strcmp(state->program->symbol_table[state->ptr].name, "ARRAY"))
						ARRAY = (void*) state->program->symbol_table[state->ptr].offset;
572
# endif
573 574 575 576
				} else /* code symbol */ {
# if (WORD_WIDTH == 64)
					state->program->symbol_table[state->ptr].offset *= 2;
# endif
577
# ifdef INTERPRETER
578
					state->program->symbol_table[state->ptr].offset += (BC_WORD) state->program->code;
Camil Staps's avatar
Camil Staps committed
579 580
# elif defined(PRELINKER)
					state->program->symbol_table[state->ptr].offset += 2*8+sizeof(prelinker_preamble);
581
# endif
582 583 584 585 586 587 588 589 590
# 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
591
				}
592
#elif defined(LINKER)
593
				if (state->program->symbol_table[state->ptr].name[0] != '\0') {
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
					struct label *label=find_label(state->program->symbol_table[state->ptr].name);

					if (label==NULL) {
						label=safe_malloc(sizeof(struct label));
						label->label_name=safe_malloc(strlen(state->program->symbol_table[state->ptr].name)+1);
						strcpy(label->label_name,state->program->symbol_table[state->ptr].name);
						label->label_id=-1;
						label->label_offset=state->program->symbol_table[state->ptr].offset;
						label->label_module_n=-2;

						struct label_node *node=safe_malloc(sizeof(struct label_node));
						node->label_node_left=NULL;
						node->label_node_right=NULL;
						node->label_node_label_p=label;

						state->new_label_nodes[state->n_labels++]=node;
					} else {
						if (state->program->symbol_table[state->ptr].offset!=-1)
							label->label_offset=state->program->symbol_table[state->ptr].offset;
						make_label_global(label);
					}
615 616
				}
#endif
617 618 619
				if (++state->ptr >= state->program->symbol_table_size)
					next_state(state);
				break;
620 621 622 623 624 625 626 627
			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;
628
					struct symbol *sym = &state->program->symbol_table[sym_i];
629

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

				if (++state->ptr >= state->code_reloc_size)
					next_state(state);
				break;
648 649 650 651 652 653 654 655
			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;
656
					struct symbol *sym = &state->program->symbol_table[sym_i];
657

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

Camil Staps's avatar
Camil Staps committed
670
# if defined(INTERPRETER) && WORD_WIDTH==32
671 672 673 674 675 676 677
					/* 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;
678
# endif
679

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

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

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