parse.c 22.8 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
#ifdef DESCS_RELATIVE_TO_ARRAY
60 61
	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 DESCS_RELATIVE_TO_ARRAY
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
#ifdef DESCS_RELATIVE_TO_ARRAY
78 79 80
	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
	preseed_symbol_matcher(state, "BOOL", (void*) &BOOL);
	preseed_symbol_matcher(state, "CHAR", (void*) &CHAR);
	preseed_symbol_matcher(state, "REAL", (void*) &REAL);
86
	preseed_symbol_matcher(state, "DREAL", (void*) &DREAL);
Camil Staps's avatar
Camil Staps committed
87 88
	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
258 259
				state->program->code = safe_malloc(sizeof(BC_WORD) * (code_size+state->program->data_size));
				state->program->data = state->program->code + code_size;
260
#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 266 267 268
				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;
269
				header_length-=4;
270
				state->program->symbols = safe_malloc(elem32 + state->program->symbol_table_size);
Camil Staps's avatar
Camil Staps committed
271

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

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

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

287 288 289 290 291 292 293 294
				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;

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

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

						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;
Camil Staps's avatar
Camil Staps committed
632 633
					} else if (state->program->symbol_table[state->ptr].offset!=-1){
						label->label_offset=state->program->symbol_table[state->ptr].offset;
634
					}
Camil Staps's avatar
Camil Staps committed
635 636

					make_label_global(label);
637 638
				}
#endif
639 640 641
				if (++state->ptr >= state->program->symbol_table_size)
					next_state(state);
				break;
642 643 644 645 646 647 648 649
			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;
650
					struct symbol *sym = &state->program->symbol_table[sym_i];
651

652
#ifdef LINKER
653
					struct label *label;
654 655 656
					if (sym->name[0] == '\0')
						label = new_label_at_offset(sym->offset);
					else
657
						label = enter_label(sym->name);
658
					add_code_relocation(label, code_i + state->code_offset);
659 660
#else
# if (WORD_WIDTH == 64)
661
					shift_address(&state->program->code[code_i]);
662
# endif
663
					state->program->code[code_i] += sym->offset;
664
#endif
665
				}
666 667 668 669

				if (++state->ptr >= state->code_reloc_size)
					next_state(state);
				break;
670 671 672 673 674 675 676 677
			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;
678
					struct symbol *sym = &state->program->symbol_table[sym_i];
679

680
#ifdef LINKER
681
					struct label *label;
682 683 684
					if (sym->name[0] == '\0')
						label = new_label_at_offset(sym->offset);
					else
685
						label = enter_label(sym->name);
686
					add_data_relocation(label, data_i + state->data_offset);
687 688
#else
# if (WORD_WIDTH == 64)
689
					shift_address(&state->program->data[data_i]);
690
# endif
691

Camil Staps's avatar
Camil Staps committed
692
# if defined(INTERPRETER) && WORD_WIDTH==32
693 694 695 696 697 698 699
					/* 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;
700
# endif
701

702
					state->program->data[data_i] += sym->offset;
703
#endif
704
				}
705 706 707 708

				if (++state->ptr >= state->data_reloc_size)
					next_state(state);
				break;
709 710 711
			default:
				return 3;
		}
Camil Staps's avatar
Camil Staps committed
712
	}
713 714 715 716

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