~ubuntu-branches/ubuntu/vivid/inform/vivid

« back to all changes in this revision

Viewing changes to inform-6.31.1/src/bpatch.c

  • Committer: Bazaar Package Importer
  • Author(s): Jan Christoph Nordholz
  • Date: 2008-05-26 22:09:44 UTC
  • mfrom: (2.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080526220944-ba7phz0d1k4vo7wx
Tags: 6.31.1+dfsg-1
* Remove a considerable number of files from the package
  due to unacceptable licensing terms.
* Repair library symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ------------------------------------------------------------------------- */
 
2
/*   "bpatch" : Keeps track of, and finally acts on, backpatch markers,      */
 
3
/*              correcting symbol values not known at compilation time       */
 
4
/*                                                                           */
 
5
/*   Part of Inform 6.31                                                     */
 
6
/*   copyright (c) Graham Nelson 1993 - 2006                                 */
 
7
/*                                                                           */
 
8
/* ------------------------------------------------------------------------- */
 
9
 
 
10
#include "header.h"
 
11
 
 
12
memory_block zcode_backpatch_table, zmachine_backpatch_table;
 
13
int32 zcode_backpatch_size, zmachine_backpatch_size;
 
14
 
 
15
/* ------------------------------------------------------------------------- */
 
16
/*   The mending operation                                                   */
 
17
/* ------------------------------------------------------------------------- */
 
18
 
 
19
int backpatch_marker, backpatch_size, backpatch_error_flag;
 
20
 
 
21
static int32 backpatch_value_z(int32 value)
 
22
{   /*  Corrects the quantity "value" according to backpatch_marker  */
 
23
 
 
24
    ASSERT_ZCODE();
 
25
 
 
26
    if (asm_trace_level >= 4)
 
27
        printf("BP %s applied to %04x giving ",
 
28
            describe_mv(backpatch_marker), value);
 
29
 
 
30
    switch(backpatch_marker)
 
31
    {   case STRING_MV:
 
32
            value += strings_offset/scale_factor; break;
 
33
        case ARRAY_MV:
 
34
            value += variables_offset; break;
 
35
        case IROUTINE_MV:
 
36
            value += code_offset/scale_factor; break;
 
37
        case VROUTINE_MV:
 
38
            if ((value<0) || (value>=VENEER_ROUTINES))
 
39
            {   if (no_link_errors > 0) break;
 
40
                if (compiler_error
 
41
                    ("Backpatch veneer routine number out of range"))
 
42
                {   printf("Illegal BP veneer routine number: %d\n", value);
 
43
                    backpatch_error_flag = TRUE;
 
44
                }
 
45
                value = 0;
 
46
                break;
 
47
            }
 
48
            value = veneer_routine_address[value] + code_offset/scale_factor;
 
49
            break;
 
50
        case NO_OBJS_MV:
 
51
            value = no_objects; break;
 
52
        case INCON_MV:
 
53
            if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
 
54
            {   if (no_link_errors > 0) break;
 
55
                if (compiler_error
 
56
                    ("Backpatch system constant number out of range"))
 
57
                {   printf("Illegal BP system constant number: %d\n", value);
 
58
                    backpatch_error_flag = TRUE;
 
59
                }
 
60
                value = 0;
 
61
                break;
 
62
            }
 
63
            value = value_of_system_constant(value); break;
 
64
        case DWORD_MV:
 
65
            value = dictionary_offset + 7 +
 
66
                    final_dict_order[value]*((version_number==3)?7:9);
 
67
            break;
 
68
        case ACTION_MV:
 
69
            break;
 
70
        case INHERIT_MV:
 
71
            value = 256*zmachine_paged_memory[value + prop_values_offset]
 
72
                    + zmachine_paged_memory[value + prop_values_offset + 1];
 
73
            break;
 
74
        case INHERIT_INDIV_MV:
 
75
            value = 256*zmachine_paged_memory[value
 
76
                        + individuals_offset]
 
77
                    + zmachine_paged_memory[value
 
78
                        + individuals_offset + 1];
 
79
            break;
 
80
        case INDIVPT_MV:
 
81
            value += individuals_offset;
 
82
            break;
 
83
        case MAIN_MV:
 
84
            value = symbol_index("Main", -1);
 
85
            if (stypes[value] != ROUTINE_T)
 
86
                error("No 'Main' routine has been defined");
 
87
            sflags[value] |= USED_SFLAG;
 
88
            value = svals[value] + code_offset/scale_factor;
 
89
            break;
 
90
        case SYMBOL_MV:
 
91
            if ((value<0) || (value>=no_symbols))
 
92
            {   if (no_link_errors > 0) break;
 
93
                if (compiler_error("Backpatch symbol number out of range"))
 
94
                {   printf("Illegal BP symbol number: %d\n", value);
 
95
                    backpatch_error_flag = TRUE;
 
96
                }
 
97
                value = 0;
 
98
                break;
 
99
            }
 
100
            if (sflags[value] & UNKNOWN_SFLAG)
 
101
            {   if (!(sflags[value] & UERROR_SFLAG))
 
102
                {   sflags[value] |= UERROR_SFLAG;
 
103
                    error_named_at("No such constant as",
 
104
                        (char *) symbs[value], slines[value]);
 
105
                }
 
106
            }
 
107
            else
 
108
            if (sflags[value] & CHANGE_SFLAG)
 
109
            {   sflags[value] &= (~(CHANGE_SFLAG));
 
110
                backpatch_marker = (svals[value]/0x10000);
 
111
                if ((backpatch_marker < 0)
 
112
                    || (backpatch_marker > LARGEST_BPATCH_MV))
 
113
                {
 
114
                    if (no_link_errors == 0)
 
115
                    {   compiler_error_named(
 
116
                        "Illegal backpatch marker attached to symbol",
 
117
                        (char *) symbs[value]);
 
118
                        backpatch_error_flag = TRUE;
 
119
                    }
 
120
                }
 
121
                else
 
122
                    svals[value] = backpatch_value_z((svals[value]) % 0x10000);
 
123
            }
 
124
 
 
125
            sflags[value] |= USED_SFLAG;
 
126
            {   int t = stypes[value];
 
127
                value = svals[value];
 
128
                switch(t)
 
129
                {   case ROUTINE_T: value += code_offset/scale_factor; break;
 
130
                    case ARRAY_T: value += variables_offset; break;
 
131
                }
 
132
            }
 
133
            break;
 
134
        default:
 
135
            if (no_link_errors > 0) break;
 
136
            if (compiler_error("Illegal backpatch marker"))
 
137
            {   printf("Illegal backpatch marker %d value %04x\n",
 
138
                    backpatch_marker, value);
 
139
                backpatch_error_flag = TRUE;
 
140
            }
 
141
            break;
 
142
    }
 
143
 
 
144
    if (asm_trace_level >= 4) printf(" %04x\n", value);
 
145
 
 
146
    return(value);
 
147
}
 
148
 
 
149
static int32 backpatch_value_g(int32 value)
 
150
{   /*  Corrects the quantity "value" according to backpatch_marker  */
 
151
    int32 valaddr;
 
152
 
 
153
    ASSERT_GLULX();
 
154
 
 
155
    if (asm_trace_level >= 4)
 
156
        printf("BP %s applied to %04x giving ",
 
157
            describe_mv(backpatch_marker), value);
 
158
 
 
159
    switch(backpatch_marker)
 
160
    {
 
161
        case STRING_MV:
 
162
            if (value <= 0 || value > no_strings)
 
163
              compiler_error("Illegal string marker.");
 
164
            value = strings_offset + compressed_offsets[value-1]; break;
 
165
        case IROUTINE_MV:
 
166
            value += code_offset; break;
 
167
        case ARRAY_MV:
 
168
            value += arrays_offset; break;
 
169
        case VARIABLE_MV:
 
170
            value = variables_offset + (4*value); break;
 
171
        case OBJECT_MV:
 
172
            value = object_tree_offset + (OBJECT_BYTE_LENGTH*(value-1)); 
 
173
            break;
 
174
        case VROUTINE_MV:
 
175
            if ((value<0) || (value>=VENEER_ROUTINES))
 
176
            {   if (no_link_errors > 0) break;
 
177
                if (compiler_error
 
178
                    ("Backpatch veneer routine number out of range"))
 
179
                {   printf("Illegal BP veneer routine number: %d\n", value);
 
180
                    backpatch_error_flag = TRUE;
 
181
                }
 
182
                value = 0;
 
183
                break;
 
184
            }
 
185
            value = veneer_routine_address[value] + code_offset;
 
186
            break;
 
187
        case NO_OBJS_MV:
 
188
            value = no_objects; break;
 
189
        case INCON_MV:
 
190
            if ((value<0) || (value>=NO_SYSTEM_CONSTANTS))
 
191
            {   if (no_link_errors > 0) break;
 
192
                if (compiler_error
 
193
                    ("Backpatch system constant number out of range"))
 
194
                {   printf("Illegal BP system constant number: %d\n", value);
 
195
                    backpatch_error_flag = TRUE;
 
196
                }
 
197
                value = 0;
 
198
                break;
 
199
            }
 
200
            value = value_of_system_constant(value); break;
 
201
        case DWORD_MV:
 
202
            value = dictionary_offset + 4 
 
203
              + final_dict_order[value]*(7+DICT_WORD_SIZE);
 
204
            break;
 
205
        case ACTION_MV:
 
206
            break;
 
207
        case INHERIT_MV:
 
208
            valaddr = (prop_values_offset - Write_RAM_At) + value;
 
209
            value = ReadInt32(zmachine_paged_memory + valaddr);
 
210
            break;
 
211
        case INHERIT_INDIV_MV:
 
212
            error("*** No individual property storage in Glulx ***");
 
213
            break;
 
214
        case INDIVPT_MV:
 
215
            value += individuals_offset;
 
216
            break;
 
217
        case MAIN_MV:
 
218
            value = symbol_index("Main", -1);
 
219
            if (stypes[value] != ROUTINE_T)
 
220
                error("No 'Main' routine has been defined");
 
221
            sflags[value] |= USED_SFLAG;
 
222
            value = svals[value] + code_offset;
 
223
            break;
 
224
        case SYMBOL_MV:
 
225
            if ((value<0) || (value>=no_symbols))
 
226
            {   if (no_link_errors > 0) break;
 
227
                if (compiler_error("Backpatch symbol number out of range"))
 
228
                {   printf("Illegal BP symbol number: %d\n", value);
 
229
                    backpatch_error_flag = TRUE;
 
230
                }
 
231
                value = 0;
 
232
                break;
 
233
            }
 
234
            if (sflags[value] & UNKNOWN_SFLAG)
 
235
            {   if (!(sflags[value] & UERROR_SFLAG))
 
236
                {   sflags[value] |= UERROR_SFLAG;
 
237
                    error_named_at("No such constant as",
 
238
                        (char *) symbs[value], slines[value]);
 
239
                }
 
240
            }
 
241
            else
 
242
            if (sflags[value] & CHANGE_SFLAG)
 
243
            {   sflags[value] &= (~(CHANGE_SFLAG));
 
244
                backpatch_marker = smarks[value];
 
245
                if ((backpatch_marker < 0)
 
246
                    || (backpatch_marker > LARGEST_BPATCH_MV))
 
247
                {
 
248
                    if (no_link_errors == 0)
 
249
                    {   compiler_error_named(
 
250
                        "Illegal backpatch marker attached to symbol",
 
251
                        (char *) symbs[value]);
 
252
                        backpatch_error_flag = TRUE;
 
253
                    }
 
254
                }
 
255
                else
 
256
                    svals[value] = backpatch_value_g(svals[value]);
 
257
            }
 
258
 
 
259
            sflags[value] |= USED_SFLAG;
 
260
            {   int t = stypes[value];
 
261
                value = svals[value];
 
262
                switch(t)
 
263
                {
 
264
                    case ROUTINE_T: value += code_offset; break;
 
265
                    case ARRAY_T: value += arrays_offset; break;
 
266
                    case OBJECT_T:
 
267
                    case CLASS_T:
 
268
                      value = object_tree_offset + 
 
269
                        (OBJECT_BYTE_LENGTH*(value-1)); 
 
270
                      break;
 
271
                    case ATTRIBUTE_T:
 
272
                      /* value is unchanged */
 
273
                      break;
 
274
                    case CONSTANT_T:
 
275
                    case INDIVIDUAL_PROPERTY_T:
 
276
                      /* value is unchanged */
 
277
                      break;
 
278
                    default:
 
279
                      error("*** Illegal backpatch marker in forward-declared \
 
280
symbol");
 
281
                      break;
 
282
                }
 
283
            }
 
284
            break;
 
285
        default:
 
286
            if (no_link_errors > 0) break;
 
287
            if (compiler_error("Illegal backpatch marker"))
 
288
            {   printf("Illegal backpatch marker %d value %04x\n",
 
289
                    backpatch_marker, value);
 
290
                backpatch_error_flag = TRUE;
 
291
            }
 
292
            break;
 
293
    }
 
294
 
 
295
    if (asm_trace_level >= 4) printf(" %04x\n", value);
 
296
 
 
297
    return(value);
 
298
}
 
299
 
 
300
extern int32 backpatch_value(int32 value)
 
301
{
 
302
  if (!glulx_mode)
 
303
    return backpatch_value_z(value);
 
304
  else
 
305
    return backpatch_value_g(value);
 
306
}
 
307
 
 
308
static void backpatch_zmachine_z(int mv, int zmachine_area, int32 offset)
 
309
{   if (module_switch)
 
310
    {   if (zmachine_area == PROP_DEFAULTS_ZA) return;
 
311
    }
 
312
    else
 
313
    {   if (mv == OBJECT_MV) return;
 
314
        if (mv == IDENT_MV) return;
 
315
        if (mv == ACTION_MV) return;
 
316
    }
 
317
 
 
318
    /* printf("MV %d ZA %d Off %04x\n", mv, zmachine_area, offset); */
 
319
 
 
320
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
321
        zmachine_backpatch_size++, mv);
 
322
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
323
        zmachine_backpatch_size++, zmachine_area);
 
324
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
325
        zmachine_backpatch_size++, offset/256);
 
326
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
327
        zmachine_backpatch_size++, offset%256);
 
328
}
 
329
 
 
330
static void backpatch_zmachine_g(int mv, int zmachine_area, int32 offset)
 
331
{   if (module_switch)
 
332
    {   if (zmachine_area == PROP_DEFAULTS_ZA) return;
 
333
    }
 
334
    else
 
335
    {   if (mv == IDENT_MV) return;
 
336
        if (mv == ACTION_MV) return;
 
337
    }
 
338
 
 
339
/* The backpatch table format for Glulx:
 
340
   First, the marker byte.
 
341
   Then, the zmachine area being patched.
 
342
   Then the four-byte address.
 
343
*/
 
344
 
 
345
/*    printf("+MV %d ZA %d Off %06x\n", mv, zmachine_area, offset);  */
 
346
 
 
347
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
348
        zmachine_backpatch_size++, mv);
 
349
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
350
        zmachine_backpatch_size++, zmachine_area);
 
351
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
352
        zmachine_backpatch_size++, (offset >> 24) & 0xFF);
 
353
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
354
        zmachine_backpatch_size++, (offset >> 16) & 0xFF);
 
355
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
356
        zmachine_backpatch_size++, (offset >> 8) & 0xFF);
 
357
    write_byte_to_memory_block(&zmachine_backpatch_table,
 
358
        zmachine_backpatch_size++, (offset) & 0xFF);
 
359
}
 
360
 
 
361
extern void backpatch_zmachine(int mv, int zmachine_area, int32 offset)
 
362
{
 
363
  if (!glulx_mode)
 
364
    backpatch_zmachine_z(mv, zmachine_area, offset);
 
365
  else
 
366
    backpatch_zmachine_g(mv, zmachine_area, offset);
 
367
}
 
368
 
 
369
extern void backpatch_zmachine_image_z(void)
 
370
{   int bm = 0, zmachine_area; int32 offset, value, addr;
 
371
    ASSERT_ZCODE();
 
372
    backpatch_error_flag = FALSE;
 
373
    while (bm < zmachine_backpatch_size)
 
374
    {   backpatch_marker
 
375
            = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
 
376
        zmachine_area
 
377
            = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
 
378
        offset
 
379
          = 256*read_byte_from_memory_block(&zmachine_backpatch_table,bm+2)
 
380
            + read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
 
381
        bm += 4;
 
382
 
 
383
        switch(zmachine_area)
 
384
        {   case PROP_DEFAULTS_ZA:   addr = prop_defaults_offset; break;
 
385
            case PROP_ZA:            addr = prop_values_offset; break;
 
386
            case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
 
387
            case DYNAMIC_ARRAY_ZA:   addr = variables_offset; break;
 
388
            default:
 
389
                if (no_link_errors == 0)
 
390
                    if (compiler_error("Illegal area to backpatch"))
 
391
                        backpatch_error_flag = TRUE;
 
392
        }
 
393
        addr += offset;
 
394
 
 
395
        value = 256*zmachine_paged_memory[addr]
 
396
                + zmachine_paged_memory[addr+1];
 
397
        value = backpatch_value_z(value);
 
398
        zmachine_paged_memory[addr] = value/256;
 
399
        zmachine_paged_memory[addr+1] = value%256;
 
400
 
 
401
        if (backpatch_error_flag)
 
402
        {   backpatch_error_flag = FALSE;
 
403
            if (no_link_errors == 0)
 
404
                printf("*** MV %d ZA %d Off %04x ***\n",
 
405
                    backpatch_marker, zmachine_area, offset);
 
406
        }
 
407
    }
 
408
}
 
409
 
 
410
extern void backpatch_zmachine_image_g(void)
 
411
{   int bm = 0, zmachine_area; int32 offset, value, addr;
 
412
    ASSERT_GLULX();
 
413
    backpatch_error_flag = FALSE;
 
414
    while (bm < zmachine_backpatch_size)
 
415
    {   backpatch_marker
 
416
            = read_byte_from_memory_block(&zmachine_backpatch_table, bm);
 
417
        zmachine_area
 
418
            = read_byte_from_memory_block(&zmachine_backpatch_table, bm+1);
 
419
        offset = read_byte_from_memory_block(&zmachine_backpatch_table, bm+2);
 
420
        offset = (offset << 8) |
 
421
          read_byte_from_memory_block(&zmachine_backpatch_table, bm+3);
 
422
        offset = (offset << 8) |
 
423
          read_byte_from_memory_block(&zmachine_backpatch_table, bm+4);
 
424
        offset = (offset << 8) |
 
425
          read_byte_from_memory_block(&zmachine_backpatch_table, bm+5);
 
426
            bm += 6;
 
427
 
 
428
        /* printf("-MV %d ZA %d Off %06x\n", backpatch_marker, zmachine_area, offset);  */
 
429
 
 
430
            switch(zmachine_area) {   
 
431
        case PROP_DEFAULTS_ZA:   addr = prop_defaults_offset+4; break;
 
432
        case PROP_ZA:            addr = prop_values_offset; break;
 
433
        case INDIVIDUAL_PROP_ZA: addr = individuals_offset; break;
 
434
        case ARRAY_ZA:           addr = arrays_offset; break;
 
435
        case GLOBALVAR_ZA:       addr = variables_offset; break;
 
436
        default:
 
437
          if (no_link_errors == 0)
 
438
            if (compiler_error("Illegal area to backpatch"))
 
439
              backpatch_error_flag = TRUE;
 
440
        }
 
441
        addr = addr + offset - Write_RAM_At; 
 
442
 
 
443
        value = (zmachine_paged_memory[addr] << 24)
 
444
                | (zmachine_paged_memory[addr+1] << 16)
 
445
                | (zmachine_paged_memory[addr+2] << 8)
 
446
                | (zmachine_paged_memory[addr+3]);
 
447
        value = backpatch_value(value);
 
448
        zmachine_paged_memory[addr] = (value >> 24) & 0xFF;
 
449
        zmachine_paged_memory[addr+1] = (value >> 16) & 0xFF;
 
450
        zmachine_paged_memory[addr+2] = (value >> 8) & 0xFF;
 
451
        zmachine_paged_memory[addr+3] = (value) & 0xFF;
 
452
 
 
453
        if (backpatch_error_flag)
 
454
        {   backpatch_error_flag = FALSE;
 
455
            if (no_link_errors == 0)
 
456
                printf("*** MV %d ZA %d Off %04x ***\n",
 
457
                    backpatch_marker, zmachine_area, offset);
 
458
        }
 
459
    }
 
460
}
 
461
 
 
462
/* ========================================================================= */
 
463
/*   Data structure management routines                                      */
 
464
/* ------------------------------------------------------------------------- */
 
465
 
 
466
extern void init_bpatch_vars(void)
 
467
{   initialise_memory_block(&zcode_backpatch_table);
 
468
    initialise_memory_block(&zmachine_backpatch_table);
 
469
}
 
470
 
 
471
extern void bpatch_begin_pass(void)
 
472
{   zcode_backpatch_size = 0;
 
473
    zmachine_backpatch_size = 0;
 
474
}
 
475
 
 
476
extern void bpatch_allocate_arrays(void)
 
477
{
 
478
}
 
479
 
 
480
extern void bpatch_free_arrays(void)
 
481
{   deallocate_memory_block(&zcode_backpatch_table);
 
482
    deallocate_memory_block(&zmachine_backpatch_table);
 
483
}
 
484
 
 
485
/* ========================================================================= */