Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/*** capsule.c --- TDF capsule ADT.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the TDF capsule routines used by the TDF linker.
38
 *
39
 *** Change Log:
40
 * $Log: capsule.c,v $
41
 * Revision 1.1.1.1  1998/01/17  15:57:18  release
42
 * First version to be checked into rolling release.
43
 *
44
 * Revision 1.5  1997/11/05  14:40:06  smf
45
 * capsule.c:
46
 * 	- Added "dgcompunit" for DDCI work (TDF 4.1).
47
 *
48
 * Revision 1.4  1995/09/22  08:39:10  smf
49
 * Fixed problems with incomplete structures (to shut "tcc" up).
50
 * Fixed some problems in "name-key.c" (no real problems, but rewritten to
51
 * reduce the warnings that were output by "tcc" and "gcc").
52
 * Fixed bug CR95_354.tld-common-id-problem (library capsules could be loaded
53
 * more than once).
54
 *
55
 * Revision 1.3  1995/07/07  15:32:15  smf
56
 * Updated to support TDF specification 4.0.
57
 *
58
 * Revision 1.2  1994/12/12  11:46:13  smf
59
 * Performing changes for 'CR94_178.sid+tld-update' - bringing in line with
60
 * OSSG C Coding Standards.
61
 *
62
 * Revision 1.1.1.1  1994/07/25  16:03:29  smf
63
 * Initial import of TDF linker 3.5 non shared files.
64
 *
65
**/
66
 
67
/****************************************************************************/
68
 
69
#include "capsule.h"
70
#include "debug.h"
71
#include "dstring.h"
72
#include "exception.h"
73
#include "gen-errors.h"
74
#include "istream.h"
75
#include "name-key.h"
76
#include "library.h"
77
#include "syntax.h"
78
#include "tdf.h"
79
#include "unit-entry.h"
80
 
81
#include "solve-cycles.h"
82
 
83
/*--------------------------------------------------------------------------*/
84
 
85
typedef struct UnitSetListEntryT {
86
    struct UnitSetListEntryT   *next;
87
    NStringT			name;
88
} UnitSetListEntryT, *UnitSetListEntryP;
89
 
90
typedef struct UnitSetT {
91
    NStringT			name;
92
    UnitEntryP			entry;
93
} UnitSetT, *UnitSetP;
94
 
95
typedef struct ShapeDataT {
96
    ShapeEntryP			entry;
97
    unsigned			num_ids;
98
    unsigned		       *id_maps;
99
} ShapeDataT, *ShapeDataP;
100
 
101
typedef struct NameDataT {
102
    NameEntryP		       *names_vec;
103
    unsigned			num_names;
104
} NameDataT, *NameDataP;
105
 
106
/*--------------------------------------------------------------------------*/
107
 
108
#define NUM_DEFAULT_UNIT_SETS	(12)
109
 
110
/*--------------------------------------------------------------------------*/
111
 
112
static CStringP capsule_default_unit_set_names [NUM_DEFAULT_UNIT_SETS] = {
113
    "tld",
114
    "tld2",
115
    "versions",
116
    "tokdec",
117
    "tokdef",
118
    "aldef",
119
    "diagtype",
120
    "tagdec",
121
    "diagdef",
122
    "dgcompunit",
123
    "tagdef",
124
    "linkinfo"
125
};
126
static UnitSetT   capsule_default_unit_sets [NUM_DEFAULT_UNIT_SETS];
127
static unsigned   capsule_num_unit_sets;
128
static UnitSetP   capsule_unit_sets     = NIL (UnitSetP);
129
static unsigned   capsule_tld_index     = 0;
130
static unsigned   capsule_tld2_index    = 1;
131
static unsigned   capsule_unit_length;
132
static unsigned   capsule_unit_offset;
133
static ExceptionP XX_capsule_error      = EXCEPTION ("error in TDF capsule");
134
static unsigned   capsule_major_version = 0;
135
static unsigned   capsule_minor_version = 0;
136
 
137
/*--------------------------------------------------------------------------*/
138
 
139
static void
140
capsule_setup_defaults PROTO_Z ()
141
{
142
    if (capsule_unit_sets == NIL (UnitSetP)) {
143
	unsigned i;
144
 
145
	for (i = 0; i < NUM_DEFAULT_UNIT_SETS; i ++) {
146
	    nstring_copy_cstring (&(capsule_default_unit_sets [i].name),
147
				  capsule_default_unit_set_names [i]);
148
	}
149
	capsule_num_unit_sets = NUM_DEFAULT_UNIT_SETS;
150
	capsule_unit_sets     = capsule_default_unit_sets;
151
    }
152
}
153
 
154
static void
155
capsule_setup PROTO_N ((units))
156
	      PROTO_T (UnitTableP  units)
157
{
158
    static BoolT need_setup = TRUE;
159
 
160
    if (need_setup) {
161
	unsigned i;
162
 
163
	capsule_setup_defaults ();
164
	for (i = 0; i < capsule_num_unit_sets; i ++) {
165
	    NStringP   name = &(capsule_unit_sets [i].name);
166
	    UnitEntryP entry;
167
 
168
	    entry = unit_table_add (units, name, i);
169
	    capsule_unit_sets [i].entry = entry;
170
	    debug_info_u_name (name);
171
	}
172
	need_setup = FALSE;
173
    }
174
}
175
 
176
static BoolT
177
capsule_read_unit_set_name PROTO_N ((istream, dstring))
178
			   PROTO_T (IStreamP istream X
179
				    DStringP dstring)
180
{
181
    char c;
182
 
183
    do {
184
	if (!istream_read_char (istream, &c)) {
185
	    return (FALSE);
186
	}
187
    } while (syntax_is_white_space (c));
188
    if (c != '"') {
189
	E_unit_set_expected_quote (istream);
190
	UNREACHED;
191
    }
192
    dstring_init (dstring);
193
    while (istream_read_char (istream, &c)) {
194
	if (c == '"') {
195
	    return (TRUE);
196
	} else if (c == '\\') {
197
	    switch (istream_read_escaped_char (istream, &c)) EXHAUSTIVE {
198
	      case ISTREAM_STAT_READ_CHAR:
199
		dstring_append_char (dstring, c);
200
		break;
201
	      case ISTREAM_STAT_NO_CHAR:
202
		break;
203
	      case ISTREAM_STAT_SYNTAX_ERROR:
204
		E_unit_set_illegal_escape (istream);
205
		UNREACHED;
206
	    }
207
	} else {
208
	    dstring_append_char (dstring, c);
209
	}
210
    }
211
    E_unit_set_eof_in_name (istream);
212
    UNREACHED;
213
}
214
 
215
static void
216
capsule_check_unit_sets PROTO_N ((istream))
217
			PROTO_T (IStreamP istream)
218
{
219
    static BoolT    inited    = FALSE;
220
    static NStringT tld;
221
    static NStringT tld2;
222
    BoolT           tld_found = FALSE;
223
    unsigned        i;
224
 
225
    if (!inited) {
226
	nstring_copy_cstring (&tld, "tld");
227
	nstring_copy_cstring (&tld2, "tld2");
228
	inited = TRUE;
229
    }
230
    capsule_tld_index  = UINT_MAX;
231
    capsule_tld2_index = UINT_MAX;
232
    for (i = 0; i < capsule_num_unit_sets; i ++) {
233
	NStringP name = &(capsule_unit_sets [i].name);
234
	unsigned j;
235
 
236
	for (j = 0; j < i; j ++) {
237
	    if (nstring_equal (name, &(capsule_unit_sets [j].name))) {
238
		E_unit_set_duplicate_name (istream_name (istream), name);
239
		UNREACHED;
240
	    }
241
	}
242
	if (nstring_equal (name, &tld)) {
243
	    capsule_tld_index = i;
244
	    tld_found         = TRUE;
245
	} else if (nstring_equal (name, &tld2)) {
246
	    capsule_tld2_index = i;
247
	}
248
    }
249
    if (!tld_found) {
250
	E_unit_set_no_tld_name (istream_name (istream));
251
	UNREACHED;
252
    }
253
}
254
 
255
static void
256
capsule_read_unit_set_file_1 PROTO_N ((istream))
257
			     PROTO_T (IStreamP istream)
258
{
259
    UnitSetListEntryP  head          = NIL (UnitSetListEntryP);
260
    UnitSetListEntryP *tail          = &head;
261
    unsigned           num_unit_sets = 0;
262
    UnitSetListEntryP  entry;
263
    UnitSetP           unit_sets;
264
    unsigned           i;
265
 
266
    for (;;) {
267
	DStringT dstring;
268
 
269
	if (!capsule_read_unit_set_name (istream, &dstring)) {
270
	    goto done;
271
	}
272
	entry       = ALLOCATE (UnitSetListEntryT);
273
	entry->next = NIL (UnitSetListEntryP);
274
	dstring_to_nstring (&dstring, &(entry->name));
275
	*tail       = entry;
276
	tail        = &(entry->next);
277
	dstring_destroy (&dstring);
278
	num_unit_sets ++;
279
    }
280
  done:
281
    unit_sets = ALLOCATE_VECTOR (UnitSetT, num_unit_sets);
282
    i         = 0;
283
    entry     = head;
284
    while (entry) {
285
	UnitSetListEntryP tmp = entry->next;
286
 
287
	nstring_assign (&(unit_sets [i].name), &(entry->name));
288
	DEALLOCATE (entry);
289
	entry = tmp;
290
	i ++;
291
    }
292
    capsule_num_unit_sets = num_unit_sets;
293
    capsule_unit_sets     = unit_sets;
294
    capsule_check_unit_sets (istream);
295
}
296
 
297
/*--------------------------------------------------------------------------*/
298
 
299
static TDFReaderP
300
capsule_reader PROTO_N ((capsule))
301
	       PROTO_T (CapsuleP capsule)
302
{
303
    ASSERT (capsule->type == CT_INPUT);
304
    return (&(capsule->u.reader));
305
}
306
 
307
static TDFWriterP
308
capsule_writer PROTO_N ((capsule))
309
	       PROTO_T (CapsuleP capsule)
310
{
311
    ASSERT (capsule->type == CT_OUTPUT);
312
    return (&(capsule->u.writer));
313
}
314
 
315
static NStringP
316
capsule_magic PROTO_Z ()
317
{
318
    static NStringT const_magic;
319
    static BoolT    inited = FALSE;
320
 
321
    if (!inited) {
322
	nstring_copy_cstring (&const_magic, "TDFC");
323
	inited = TRUE;
324
    }
325
    return (&const_magic);
326
}
327
 
328
/*--------------------------------------------------------------------------*/
329
 
330
static void
331
capsule_read_header PROTO_N ((capsule))
332
    		    PROTO_T (CapsuleP capsule)
333
{
334
    TDFReaderP reader      = capsule_reader (capsule);
335
    NStringP   const_magic = capsule_magic ();
336
    NStringT   magic;
337
    unsigned   major;
338
    unsigned   minor;
339
 
340
    nstring_init_length (&magic, (unsigned) 4);
341
    tdf_read_bytes (reader, &magic);
342
    if (!nstring_equal (&magic, const_magic)) {
343
	E_capsule_bad_magic (capsule, &magic, const_magic);
344
	THROW (XX_capsule_error);
345
	UNREACHED;
346
    }
347
    nstring_destroy (&magic);
348
    major = tdf_read_int (reader);
349
    minor = tdf_read_int (reader);
350
    debug_info_r_versions (major, minor);
351
    if (major < 4) {
352
	E_capsule_bad_version (capsule, major);
353
	THROW (XX_capsule_error);
354
	UNREACHED;
355
    } else if (capsule_major_version == 0) {
356
	capsule_major_version = major;
357
	capsule_minor_version = minor;
358
    } else if (capsule_major_version != major) {
359
	E_capsule_version_mismatch (capsule, capsule_major_version, major);
360
	THROW (XX_capsule_error);
361
	UNREACHED;
362
    } else if (capsule_minor_version < minor) {
363
	capsule_minor_version = minor;
364
    }
365
    tdf_read_align (reader);
366
}
367
 
368
static UnitEntryP *
369
capsule_read_unit_set_names PROTO_N ((capsule, units, num_unit_sets_ref))
370
			    PROTO_T (CapsuleP   capsule X
371
				     UnitTableP units X
372
				     unsigned  *num_unit_sets_ref)
373
{
374
    TDFReaderP  reader        = capsule_reader (capsule);
375
    unsigned    num_unit_sets = tdf_read_int (reader);
376
    UnitEntryP *units_vec     = ALLOCATE_VECTOR (UnitEntryP, num_unit_sets);
377
    UnitEntryP  tld_entry     = capsule_unit_sets [capsule_tld_index].entry;
378
    UnitEntryP  tld2_entry    = ((capsule_tld2_index == UINT_MAX) ?
379
				 NIL (UnitEntryP) :
380
				 capsule_unit_sets [capsule_tld2_index].entry);
381
    BoolT       has_tld_unit  = FALSE;
382
    unsigned    i;
383
 
384
    debug_info_r_start_unit_decs (num_unit_sets);
385
    for (i = 0; i < num_unit_sets; i ++) {
386
	NStringT   nstring;
387
	UnitEntryP entry;
388
 
389
	tdf_read_string (reader, &nstring);
390
	if ((entry = unit_table_get (units, &nstring)) != NIL (UnitEntryP)) {
391
	    unsigned order = unit_entry_order (entry);
392
	    unsigned j;
393
 
394
	    for (j = 0; j < i; j ++) {
395
		if (entry == units_vec [j]) {
396
		    E_duplicate_unit_set_name (capsule, &nstring);
397
		    THROW (XX_capsule_error);
398
		    UNREACHED;
399
		} else if (order < unit_entry_order (units_vec [j])) {
400
		    E_out_of_order_unit_set_name (capsule, &nstring);
401
		    THROW (XX_capsule_error);
402
		    UNREACHED;
403
		}
404
	    }
405
	    if (entry == tld2_entry) {
406
		E_tld2_unit_set_type_obsolete (capsule);
407
	    }
408
	    if ((entry == tld_entry) || (entry == tld2_entry)) {
409
		if (has_tld_unit) {
410
		    E_extra_tld_unit_set (capsule);
411
		    THROW (XX_capsule_error);
412
		    UNREACHED;
413
		}
414
		has_tld_unit = TRUE;
415
	    }
416
	    units_vec [i] = entry;
417
	} else {
418
	    E_unknown_unit_set_name (capsule, &nstring);
419
	    THROW (XX_capsule_error);
420
	    UNREACHED;
421
	}
422
	debug_info_r_unit_dec (&nstring);
423
	nstring_destroy (&nstring);
424
    }
425
    if (!has_tld_unit) {
426
	E_missing_tld_unit_set (tdf_reader_name (reader));
427
    }
428
    *num_unit_sets_ref = num_unit_sets;
429
    return (units_vec);
430
}
431
 
432
static ShapeDataP
433
capsule_read_shapes PROTO_N ((capsule, shapes, num_shapes_ref))
434
		    PROTO_T (CapsuleP    capsule X
435
			     ShapeTableP shapes X
436
			     unsigned   *num_shapes_ref)
437
{
438
    TDFReaderP reader     = capsule_reader (capsule);
439
    unsigned   num_shapes = tdf_read_int (reader);
440
    ShapeDataP shapes_vec = ALLOCATE_VECTOR (ShapeDataT, num_shapes);
441
    unsigned   i;
442
 
443
    debug_info_r_start_shapes (num_shapes);
444
    for (i = 0; i < num_shapes; i ++) {
445
	NStringT    nstring;
446
	unsigned    num_ids;
447
	ShapeEntryP entry;
448
	unsigned    j;
449
 
450
	tdf_read_string (reader, &nstring);
451
	num_ids = tdf_read_int (reader);
452
	entry   = shape_table_add (shapes, &nstring);
453
	for (j = 0; j < i; j ++) {
454
	    if (entry == shapes_vec [j].entry) {
455
		E_duplicate_shape_name (capsule, &nstring);
456
		THROW (XX_capsule_error);
457
		UNREACHED;
458
	    }
459
	}
460
	debug_info_r_shape (&nstring, num_ids);
461
	nstring_destroy (&nstring);
462
	shapes_vec [i].entry   = entry;
463
	shapes_vec [i].num_ids = num_ids;
464
	shapes_vec [i].id_maps = ALLOCATE_VECTOR (unsigned, num_ids);
465
	for (j = 0; j < num_ids; j ++) {
466
	    shapes_vec [i].id_maps [j] = UINT_MAX;
467
	}
468
    }
469
    *num_shapes_ref = num_shapes;
470
    return (shapes_vec);
471
}
472
 
473
static NameEntryP *
474
capsule_read_external_names_1 PROTO_N ((capsule, shape, num_ref))
475
			      PROTO_T (CapsuleP   capsule X
476
				       ShapeDataP shape X
477
				       unsigned  *num_ref)
478
{
479
    TDFReaderP  reader         = capsule_reader (capsule);
480
    unsigned    num_this_shape = tdf_read_int (reader);
481
    ShapeEntryP entry          = shape->entry;
482
    NStringP    key            = shape_entry_key (entry);
483
    NameTableP  table          = shape_entry_name_table (entry);
484
    unsigned    num_ids        = shape->num_ids;
485
    unsigned   *id_maps        = shape->id_maps;
486
    NameEntryP *names_vec      = ALLOCATE_VECTOR (NameEntryP, num_this_shape);
487
    unsigned    i;
488
 
489
    debug_info_r_start_shape_names (key, num_this_shape);
490
    for (i = 0; i < num_this_shape; i ++) {
491
	unsigned   id = tdf_read_int (reader);
492
	NameKeyT   name;
493
	NameEntryP name_entry;
494
 
495
	tdf_read_name (reader, &name);
496
	if (id >= num_ids) {
497
	    E_name_id_out_of_range (capsule, key, &name, id, num_ids);
498
	    THROW (XX_capsule_error);
499
	    UNREACHED;
500
	}
501
	name_entry = name_table_add (table, &name, entry);
502
	if (id_maps [id] != UINT_MAX) {
503
	    E_name_id_used_multiple_times (capsule, key, &name, id);
504
	    THROW (XX_capsule_error);
505
	    UNREACHED;
506
	}
507
	names_vec [i] = name_entry;
508
	id_maps [id]  = name_entry_id (name_entry);
509
	debug_info_r_name (&name, id, id_maps [id],
510
			   name_entry_key (name_entry));
511
	name_key_destroy (&name);
512
    }
513
    *num_ref = num_this_shape;
514
    return (names_vec);
515
}
516
 
517
static NameDataP
518
capsule_read_external_names PROTO_N ((capsule, num_shapes, shapes_vec))
519
			    PROTO_T (CapsuleP   capsule X
520
				     unsigned   num_shapes X
521
				     ShapeDataP shapes_vec)
522
{
523
    TDFReaderP reader = capsule_reader (capsule);
524
    NameDataT *names_vec_vec;
525
    unsigned   num_names;
526
    unsigned   i;
527
 
528
    if ((num_names = tdf_read_int (reader)) != num_shapes) {
529
	E_shape_and_name_count_mismatch (capsule, num_shapes, num_names);
530
	THROW (XX_capsule_error);
531
	UNREACHED;
532
    }
533
    debug_info_r_start_names (num_names);
534
    names_vec_vec = ALLOCATE_VECTOR (NameDataT, num_names);
535
    for (i = 0; i < num_names; i ++) {
536
	ShapeDataP  shape = &(shapes_vec [i]);
537
	NameEntryP *names_vec;
538
	unsigned    num_this_shape;
539
 
540
	names_vec = capsule_read_external_names_1 (capsule, shape,
541
						   &num_this_shape);
542
	names_vec_vec [i].names_vec = names_vec;
543
	names_vec_vec [i].num_names = num_this_shape;
544
    }
545
    return (names_vec_vec);
546
}
547
 
548
/*--------------------------------------------------------------------------*/
549
 
550
static unsigned
551
capsule_get_token_index PROTO_N ((shapes, num_shapes, shapes_vec))
552
			PROTO_T (ShapeTableP shapes X
553
				 unsigned    num_shapes X
554
				 ShapeDataP  shapes_vec)
555
{
556
    ShapeEntryP token_entry = shape_table_get_token_entry (shapes);
557
    unsigned    i;
558
 
559
    for (i = 0; i < num_shapes; i ++) {
560
	if (shapes_vec [i].entry == token_entry) {
561
	    return (i);
562
	}
563
    }
564
    return (UINT_MAX);
565
}
566
 
567
static unsigned
568
capsule_get_tag_index PROTO_N ((shapes, num_shapes, shapes_vec))
569
		      PROTO_T (ShapeTableP shapes X
570
			       unsigned    num_shapes X
571
			       ShapeDataP  shapes_vec)
572
{
573
    ShapeEntryP tag_entry = shape_table_get_tag_entry (shapes);
574
    unsigned    i;
575
 
576
    for (i = 0; i < num_shapes; i ++) {
577
	if (shapes_vec [i].entry == tag_entry) {
578
	    return (i);
579
	}
580
    }
581
    return (UINT_MAX);
582
}
583
 
584
static void
585
capsule_read_usage PROTO_N ((capsule, entry, need_dec, no_mult, shape_key))
586
		   PROTO_T (CapsuleP  capsule X
587
			    NameDataP entry X
588
			    BoolT     need_dec X
589
			    BoolT     no_mult X
590
			    NStringP  shape_key)
591
{
592
    TDFReaderP  reader    = capsule_reader (capsule);
593
    unsigned    num_names = entry->num_names;
594
    NameEntryP *names_vec = entry->names_vec;
595
    unsigned    i;
596
 
597
    debug_info_r_start_usages (shape_key, num_names);
598
    for (i = 0; i < num_names; i ++) {
599
	unsigned   use        = tdf_read_int (reader);
600
	NameEntryP name_entry = names_vec [i];
601
	unsigned   name_use   = name_entry_get_use (name_entry);
602
	NameKeyP   key        = name_entry_key (name_entry);
603
 
604
	if (use & ~(U_USED | U_DECD | U_DEFD | U_MULT)) {
605
	    E_bad_usage (capsule, shape_key, key, use);
606
	    THROW (XX_capsule_error);
607
	    UNREACHED;
608
	} else if (no_mult && (use & U_MULT)) {
609
	    E_illegally_multiply_defined (capsule, shape_key, key);
610
	    THROW (XX_capsule_error);
611
	    UNREACHED;
612
	} else if (need_dec &&
613
		   (((use & (U_DEFD | U_DECD)) == U_DEFD) ||
614
		    ((use & (U_MULT | U_DECD)) == U_MULT))) {
615
	    E_defined_but_not_declared (capsule, shape_key, key);
616
	    THROW (XX_capsule_error);
617
	    UNREACHED;
618
	}
619
	if ((use & U_DEFD) && (name_use & U_DEFD)) {
620
	    CapsuleP definition = name_entry_get_definition (name_entry);
621
	    CStringP prev_name  = capsule_name (definition);
622
 
623
	    E_multiply_defined (capsule, shape_key, key, prev_name);
624
	} else if ((use & U_MULT) && (name_use & U_MULT) &&
625
		   (!(use & U_DEFD)) && (!(name_use & U_DEFD))) {
626
	    name_entry_set_definition (name_entry, NIL (CapsuleP));
627
	} else if ((use & U_DEFD) ||
628
		   ((use & U_MULT) && (!(name_use & (U_MULT | U_DEFD))))) {
629
	    name_entry_set_definition (name_entry, capsule);
630
	}
631
	debug_info_r_usage (use, name_use, key);
632
	name_entry_merge_use (name_entry, use);
633
    }
634
}
635
 
636
static void
637
capsule_read_tld_type_0_unit PROTO_N ((capsule, shapes, num_shapes, shapes_vec,
638
				       names_vec_vec))
639
			     PROTO_T (CapsuleP    capsule X
640
				      ShapeTableP shapes X
641
				      unsigned    num_shapes X
642
				      ShapeDataP  shapes_vec X
643
				      NameDataP   names_vec_vec)
644
{
645
    unsigned i;
646
 
647
    i = capsule_get_token_index (shapes, num_shapes, shapes_vec);
648
    if (i != UINT_MAX) {
649
	NStringP key = shape_entry_key (shapes_vec [i].entry);
650
 
651
	capsule_read_usage (capsule, &(names_vec_vec [i]), FALSE, TRUE, key);
652
    }
653
    i = capsule_get_tag_index (shapes, num_shapes, shapes_vec);
654
    if (i != UINT_MAX) {
655
	NStringP key = shape_entry_key (shapes_vec [i].entry);
656
 
657
	capsule_read_usage (capsule, &(names_vec_vec [i]), TRUE, FALSE, key);
658
    }
659
}
660
 
661
static void
662
capsule_read_tld_type_1_unit PROTO_N ((capsule, shapes, num_shapes, shapes_vec,
663
				       names_vec_vec))
664
			     PROTO_T (CapsuleP    capsule X
665
				      ShapeTableP shapes X
666
				      unsigned    num_shapes X
667
				      ShapeDataP  shapes_vec X
668
				      NameDataP   names_vec_vec)
669
{
670
    unsigned i;
671
    unsigned token = capsule_get_token_index (shapes, num_shapes, shapes_vec);
672
    unsigned tag   = capsule_get_tag_index (shapes, num_shapes, shapes_vec);
673
 
674
    for (i = 0; i < num_shapes; i ++) {
675
	NStringP key = shape_entry_key (shapes_vec [i].entry);
676
 
677
	capsule_read_usage (capsule, &(names_vec_vec [i]), i == tag,
678
			    i == token, key);
679
    }
680
}
681
 
682
/*--------------------------------------------------------------------------*/
683
 
684
typedef void (*UnitTypeProcP)
685
	PROTO_S ((CapsuleP, ShapeTableP, unsigned, ShapeDataP, NameDataP));
686
 
687
static UnitTypeProcP capsule_type_jump_table [] = {
688
    capsule_read_tld_type_0_unit,
689
    capsule_read_tld_type_1_unit
690
};
691
 
692
#define CAPSULE_TYPE_JUMP_TABLE_SIZE \
693
	((unsigned) (sizeof (capsule_type_jump_table) / \
694
		     sizeof (UnitTypeProcP)))
695
 
696
/*--------------------------------------------------------------------------*/
697
 
698
static void
699
capsule_read_tld_unit_header PROTO_N ((capsule, unit_set))
700
			     PROTO_T (CapsuleP capsule X
701
				      NStringP unit_set)
702
{
703
    TDFReaderP reader = capsule_reader (capsule);
704
 
705
    if (tdf_read_int (reader) != 1) {
706
	E_too_many_tld_units (capsule);
707
	THROW (XX_capsule_error);
708
	UNREACHED;
709
    }
710
    debug_info_r_start_units (unit_set, (unsigned) 1);
711
    debug_info_r_start_unit (unit_set, (unsigned) 1, (unsigned) 1);
712
    if (tdf_read_int (reader) != 0) {
713
	E_too_many_tld_unit_counts (capsule);
714
	THROW (XX_capsule_error);
715
	UNREACHED;
716
    }
717
    debug_info_r_start_counts ((unsigned) 0);
718
    if (tdf_read_int (reader) != 0) {
719
	E_too_many_tld_unit_mappings (capsule);
720
	THROW (XX_capsule_error);
721
	UNREACHED;
722
    }
723
    debug_info_r_start_maps ((unsigned) 0);
724
    capsule_unit_length = tdf_read_int (reader);
725
    debug_info_r_unit_body (capsule_unit_length);
726
    tdf_read_align (reader);
727
    capsule_unit_offset = tdf_reader_byte (reader);
728
}
729
 
730
static void
731
capsule_read_tld_unit_trailer PROTO_N ((capsule))
732
			      PROTO_T (CapsuleP capsule)
733
{
734
    TDFReaderP reader  = capsule_reader (capsule);
735
    unsigned   offset  = tdf_reader_byte (reader);
736
    unsigned   correct = (capsule_unit_offset + capsule_unit_length);
737
 
738
    tdf_read_align (reader);
739
    if (correct != offset) {
740
	E_tld_unit_wrong_size (capsule, correct, offset);
741
	THROW (XX_capsule_error);
742
	UNREACHED;
743
    }
744
}
745
 
746
static void
747
capsule_read_tld2_units PROTO_N ((capsule, shapes, num_shapes, shapes_vec,
748
				  names_vec_vec))
749
			PROTO_T (CapsuleP    capsule X
750
				 ShapeTableP shapes X
751
				 unsigned    num_shapes X
752
				 ShapeDataP  shapes_vec X
753
				 NameDataP   names_vec_vec)
754
{
755
    UnitEntryP tld2_entry = capsule_unit_sets [capsule_tld2_index].entry;
756
    NStringP   key        = unit_entry_key (tld2_entry);
757
 
758
    ASSERT (capsule_tld2_index != UINT_MAX);
759
    capsule_read_tld_unit_header (capsule, key);
760
    debug_info_r_tld_version ((unsigned) 0);
761
    capsule_read_tld_type_0_unit (capsule, shapes, num_shapes, shapes_vec,
762
				  names_vec_vec);
763
    capsule_read_tld_unit_trailer (capsule);
764
}
765
 
766
static void
767
capsule_read_tld_units PROTO_N ((capsule, shapes, num_shapes, shapes_vec,
768
				 names_vec_vec))
769
		       PROTO_T (CapsuleP    capsule X
770
				ShapeTableP shapes X
771
				unsigned    num_shapes X
772
				ShapeDataP  shapes_vec X
773
				NameDataP   names_vec_vec)
774
{
775
    TDFReaderP reader    = capsule_reader (capsule);
776
    UnitEntryP tld_entry = capsule_unit_sets [capsule_tld_index].entry;
777
    NStringP   key       = unit_entry_key (tld_entry);
778
    unsigned   unit_type;
779
 
780
    capsule_read_tld_unit_header (capsule, key);
781
    unit_type = tdf_read_int (reader);
782
    if (unit_type >= CAPSULE_TYPE_JUMP_TABLE_SIZE) {
783
	E_unknown_tld_unit_type (capsule, unit_type);
784
	THROW (XX_capsule_error);
785
	UNREACHED;
786
    }
787
    debug_info_r_tld_version (unit_type);
788
    (*(capsule_type_jump_table [unit_type])) (capsule, shapes, num_shapes,
789
					      shapes_vec, names_vec_vec);
790
    capsule_read_tld_unit_trailer (capsule);
791
}
792
 
793
static MapEntryP *
794
capsule_read_unit_counts PROTO_N ((capsule, num_shapes, shapes_vec, num_counts,
795
				   unit_entry, unit, unit_num))
796
			 PROTO_T (CapsuleP   capsule X
797
				  unsigned   num_shapes X
798
				  ShapeDataP shapes_vec X
799
				  unsigned   num_counts X
800
				  UnitEntryP unit_entry X
801
				  UnitP      unit X
802
				  unsigned   unit_num)
803
{
804
    if ((num_counts != 0) && (num_counts != num_shapes)) {
805
	E_unit_count_num_mismatch (capsule, num_counts, num_shapes, unit_num,
806
				   unit_entry_key (unit_entry));
807
	THROW (XX_capsule_error);
808
	UNREACHED;
809
    }
810
    debug_info_r_start_counts (num_counts);
811
    if (num_counts != 0) {
812
	TDFReaderP reader  = capsule_reader (capsule);
813
	MapTableP  table   = unit_map_table (unit);
814
	MapEntryP *entries = ALLOCATE_VECTOR (MapEntryP, num_counts);
815
	unsigned   i;
816
 
817
	for (i = 0; i < num_counts; i ++) {
818
	    unsigned  count = tdf_read_int (reader);
819
	    NStringP  key   = shape_entry_key (shapes_vec [i].entry);
820
	    MapEntryP entry = map_table_add (table, key, count);
821
 
822
	    debug_info_r_count (count, key);
823
	    entries [i] = entry;
824
	}
825
	return (entries);
826
    } else {
827
	return (NIL (MapEntryP *));
828
    }
829
}
830
 
831
static void
832
capsule_read_unit_maps PROTO_N ((capsule, num_counts, shapes_vec, unit_entry,
833
				 unit_num, entries))
834
		       PROTO_T (CapsuleP   capsule X
835
				unsigned   num_counts X
836
				ShapeDataP shapes_vec X
837
				UnitEntryP unit_entry X
838
				unsigned   unit_num X
839
				MapEntryP *entries)
840
{
841
    TDFReaderP reader          = capsule_reader (capsule);
842
    unsigned   num_link_shapes = tdf_read_int (reader);
843
    unsigned   i;
844
 
845
    if (num_link_shapes != num_counts) {
846
	E_unit_mapping_num_mismatch (capsule, num_link_shapes, num_counts,
847
				     unit_num, unit_entry_key (unit_entry));
848
	THROW (XX_capsule_error);
849
	UNREACHED;
850
    }
851
    debug_info_r_start_maps (num_link_shapes);
852
    for (i = 0; i < num_link_shapes; i ++) {
853
	unsigned    num_links   = tdf_read_int (reader);
854
	ShapeEntryP shape_entry = (shapes_vec [i].entry);
855
	NStringP    key         = shape_entry_key (shape_entry);
856
	unsigned    j;
857
 
858
	map_entry_set_num_links (entries [i], num_links);
859
	debug_info_r_start_shape_maps (key, num_links);
860
	for (j = 0; j < num_links; j ++) {
861
	    unsigned  internal = tdf_read_int (reader);
862
	    unsigned  external = tdf_read_int (reader);
863
	    unsigned  num_ids  = shapes_vec [i].num_ids;
864
	    unsigned *id_maps  = shapes_vec [i].id_maps;
865
 
866
	    if (external >= num_ids) {
867
		E_id_out_of_range (capsule, external, num_ids, key, unit_num,
868
				   unit_entry_key (unit_entry));
869
		THROW (XX_capsule_error);
870
		UNREACHED;
871
	    }
872
	    if (id_maps [external] == UINT_MAX) {
873
		unsigned id = shape_entry_next_id (shape_entry);
874
 
875
		id_maps [external] = id;
876
	    }
877
	    debug_info_r_map (internal, external, id_maps [external]);
878
	    external = id_maps [external];
879
	    map_entry_set_link (entries [i], j, internal, external);
880
	}
881
    }
882
}
883
 
884
static void
885
capsule_read_unit PROTO_N ((capsule, num_shapes, shapes_vec, unit_entry,
886
			    unit_num))
887
		  PROTO_T (CapsuleP   capsule X
888
			   unsigned   num_shapes X
889
			   ShapeDataP shapes_vec X
890
			   UnitEntryP unit_entry X
891
			   unsigned   unit_num)
892
{
893
    TDFReaderP reader     = capsule_reader (capsule);
894
    unsigned   num_counts = tdf_read_int (reader);
895
    UnitP      unit       = unit_entry_add_unit (unit_entry, num_counts);
896
    MapEntryP *entries;
897
    unsigned   size;
898
    NStringT   nstring;
899
 
900
    entries = capsule_read_unit_counts (capsule, num_shapes, shapes_vec,
901
					num_counts, unit_entry, unit,
902
					unit_num);
903
    capsule_read_unit_maps (capsule, num_counts, shapes_vec, unit_entry,
904
			    unit_num, entries);
905
    size = tdf_read_int (reader);
906
    debug_info_r_unit_body (size);
907
    nstring_init_length (&nstring, size);
908
    tdf_read_bytes (reader, &nstring);
909
    unit_set_contents (unit, &nstring);
910
    DEALLOCATE (entries);
911
}
912
 
913
static void
914
capsule_read_units PROTO_N ((capsule, num_shapes, shapes_vec, unit_entry))
915
		   PROTO_T (CapsuleP   capsule X
916
			    unsigned   num_shapes X
917
			    ShapeDataP shapes_vec X
918
			    UnitEntryP unit_entry)
919
{
920
    TDFReaderP reader    = capsule_reader (capsule);
921
    unsigned   num_units = tdf_read_int (reader);
922
    unsigned   i;
923
 
924
    debug_info_r_start_units (unit_entry_key (unit_entry), num_units);
925
    for (i = 0; i < num_units; i ++) {
926
	debug_info_r_start_unit (unit_entry_key (unit_entry), i + 1,
927
				 num_units);
928
	capsule_read_unit (capsule, num_shapes, shapes_vec, unit_entry, i);
929
    }
930
}
931
 
932
static void
933
capsule_read_unit_sets PROTO_N ((capsule, num_unit_sets, units_vec, shapes,
934
				 num_shapes, shapes_vec, names_vec_vec))
935
		       PROTO_T (CapsuleP    capsule X
936
				unsigned    num_unit_sets X
937
				UnitEntryP *units_vec X
938
				ShapeTableP shapes X
939
				unsigned    num_shapes X
940
				ShapeDataP  shapes_vec X
941
				NameDataP   names_vec_vec)
942
{
943
    TDFReaderP reader       = capsule_reader (capsule);
944
    UnitEntryP tld_entry    = capsule_unit_sets [capsule_tld_index].entry;
945
    UnitEntryP tld2_entry   = ((capsule_tld2_index == UINT_MAX) ?
946
			       NIL (UnitEntryP) :
947
			       capsule_unit_sets [capsule_tld2_index].entry);
948
    unsigned   num_units;
949
    unsigned   i;
950
 
951
    if ((num_units = tdf_read_int (reader)) != num_unit_sets) {
952
	E_unit_set_count_mismatch (capsule, num_unit_sets, num_units);
953
	THROW (XX_capsule_error);
954
	UNREACHED;
955
    }
956
    debug_info_r_start_unit_sets (num_units);
957
    for (i = 0; i < num_units; i ++) {
958
	if (units_vec [i] == tld_entry) {
959
	    capsule_read_tld_units (capsule, shapes, num_shapes, shapes_vec,
960
				    names_vec_vec);
961
	} else if (units_vec [i] == tld2_entry) {
962
	    capsule_read_tld2_units (capsule, shapes, num_shapes, shapes_vec,
963
				     names_vec_vec);
964
	} else {
965
	    capsule_read_units (capsule, num_shapes, shapes_vec,
966
				units_vec [i]);
967
	}
968
    }
969
}
970
 
971
/*--------------------------------------------------------------------------*/
972
 
973
static void
974
capsule_write_header PROTO_N ((capsule))
975
    		     PROTO_T (CapsuleP capsule)
976
{
977
    TDFWriterP writer      = capsule_writer (capsule);
978
    NStringP   const_magic = capsule_magic ();
979
 
980
    tdf_write_bytes (writer, const_magic);
981
    ASSERT (capsule_major_version >= 4);
982
    tdf_write_int (writer, capsule_major_version);
983
    tdf_write_int (writer, capsule_minor_version);
984
    debug_info_w_versions (capsule_major_version, capsule_minor_version);
985
    tdf_write_align (writer);
986
}
987
 
988
/*--------------------------------------------------------------------------*/
989
 
990
void
991
capsule_read_unit_set_file PROTO_N ((name))
992
			   PROTO_T (CStringP name)
993
{
994
    IStreamT istream;
995
 
996
    ASSERT (capsule_unit_sets == NIL (UnitSetP));
997
    if (!istream_open (&istream, name)) {
998
	E_cannot_open_unit_set_file (name);
999
	UNREACHED;
1000
    }
1001
    capsule_read_unit_set_file_1 (&istream);
1002
    istream_close (&istream);
1003
}
1004
 
1005
CapsuleP
1006
capsule_create_stream_input PROTO_N ((name))
1007
			    PROTO_T (CStringP name)
1008
{
1009
    CapsuleP capsule = ALLOCATE (CapsuleT);
1010
 
1011
    capsule->type = CT_INPUT;
1012
    if (!tdf_reader_open (capsule_reader (capsule), name)) {
1013
	DEALLOCATE (capsule);
1014
	return (NIL (CapsuleP));
1015
    }
1016
    capsule->name     = name;
1017
    capsule->complete = FALSE;
1018
    return (capsule);
1019
}
1020
 
1021
CapsuleP
1022
capsule_create_string_input PROTO_N ((name, contents))
1023
			    PROTO_T (CStringP name X
1024
				     NStringP contents)
1025
{
1026
    CapsuleP capsule = ALLOCATE (CapsuleT);
1027
 
1028
    capsule->type     = CT_INPUT;
1029
    tdf_reader_open_string (capsule_reader (capsule), name, contents);
1030
    capsule->name     = name;
1031
    capsule->complete = FALSE;
1032
    return (capsule);
1033
}
1034
 
1035
CapsuleP
1036
capsule_create_stream_output PROTO_N ((name))
1037
			     PROTO_T (CStringP name)
1038
{
1039
    CapsuleP capsule = ALLOCATE (CapsuleT);
1040
 
1041
    capsule->type = CT_OUTPUT;
1042
    if (!tdf_writer_open (capsule_writer (capsule), name)) {
1043
	DEALLOCATE (capsule);
1044
	return (NIL (CapsuleP));
1045
    }
1046
    capsule->name = name;
1047
    return (capsule);
1048
}
1049
 
1050
CStringP
1051
capsule_name PROTO_N ((capsule))
1052
	     PROTO_T (CapsuleP capsule)
1053
{
1054
    return (capsule->name);
1055
}
1056
 
1057
unsigned
1058
capsule_byte PROTO_N ((capsule))
1059
	     PROTO_T (CapsuleP capsule)
1060
{
1061
    return (tdf_reader_byte (capsule_reader (capsule)));
1062
}
1063
 
1064
void
1065
capsule_read PROTO_N ((capsule, units, shapes))
1066
	     PROTO_T (CapsuleP    capsule X
1067
		      UnitTableP  units X
1068
		      ShapeTableP shapes)
1069
{
1070
    ASSERT (capsule->type == CT_INPUT);
1071
    capsule_setup (units);
1072
    HANDLE {
1073
	UnitEntryP *units_vec;
1074
	unsigned    num_unit_sets;
1075
	ShapeDataP  shapes_vec;
1076
	unsigned    num_shapes;
1077
	NameDataP   names_vec_vec;
1078
	unsigned    i;
1079
 
1080
	debug_info_r_start_capsule (capsule_name (capsule));
1081
	capsule_read_header (capsule);
1082
	units_vec     = capsule_read_unit_set_names (capsule, units,
1083
						     &num_unit_sets);
1084
	shapes_vec    = capsule_read_shapes (capsule, shapes, &num_shapes);
1085
	names_vec_vec = capsule_read_external_names (capsule, num_shapes,
1086
						     shapes_vec);
1087
	capsule_read_unit_sets (capsule, num_unit_sets, units_vec, shapes,
1088
				num_shapes, shapes_vec, names_vec_vec);
1089
	tdf_read_eof (capsule_reader (capsule));
1090
	debug_info_r_end_capsule ();
1091
	DEALLOCATE (units_vec);
1092
	for (i = 0; i < num_shapes; i ++) {
1093
	    DEALLOCATE (shapes_vec [i].id_maps);
1094
	    DEALLOCATE (names_vec_vec [i].names_vec);
1095
	}
1096
	DEALLOCATE (shapes_vec);
1097
	DEALLOCATE (names_vec_vec);
1098
	capsule->complete = TRUE;
1099
    } WITH {
1100
	ExceptionP exception = EXCEPTION_EXCEPTION ();
1101
 
1102
	debug_info_r_abort_capsule ();
1103
	if ((exception != XX_capsule_error) &&
1104
	    (exception != XX_tdf_read_error)) {
1105
	    RETHROW ();
1106
	}
1107
    } END_HANDLE
1108
}
1109
 
1110
void
1111
capsule_store_contents PROTO_N ((capsule))
1112
		       PROTO_T (CapsuleP capsule)
1113
{
1114
    if (capsule->complete) {
1115
	TDFReaderP reader = capsule_reader (capsule);
1116
	unsigned   length = tdf_reader_byte (reader);
1117
 
1118
	nstring_init_length (&(capsule->contents), length);
1119
	tdf_reader_rewind (reader);
1120
	tdf_read_bytes (reader, &(capsule->contents));
1121
	tdf_read_eof (reader);
1122
    }
1123
}
1124
 
1125
NStringP
1126
capsule_contents PROTO_N ((capsule))
1127
		 PROTO_T (CapsuleP capsule)
1128
{
1129
    return (&(capsule->contents));
1130
}
1131
 
1132
void
1133
capsule_set_index PROTO_N ((capsule, i))
1134
		  PROTO_T (CapsuleP capsule X
1135
			   unsigned i)
1136
{
1137
    capsule->capsule_index = i;
1138
}
1139
 
1140
unsigned
1141
capsule_get_index PROTO_N ((capsule))
1142
		  PROTO_T (CapsuleP capsule)
1143
{
1144
    return (capsule->capsule_index);
1145
}
1146
 
1147
void
1148
capsule_write PROTO_N ((capsule, units, shapes))
1149
	      PROTO_T (CapsuleP    capsule X
1150
		       UnitTableP  units X
1151
		       ShapeTableP shapes)
1152
{
1153
    TDFWriterP      writer     = capsule_writer (capsule);
1154
    UnitEntryP      tld_entry  = capsule_unit_sets [capsule_tld_index].entry;
1155
    unsigned        num_shapes = 0;
1156
    UnitSetClosureT unit_set_closure;
1157
    unsigned        i;
1158
 
1159
    debug_info_w_start_capsule (capsule_name (capsule));
1160
    capsule_write_header (capsule);
1161
    unit_set_closure.num_unit_sets = 1;
1162
    unit_set_closure.shapes        = shapes;
1163
    unit_table_iter (units, unit_entry_do_count, (GenericP) &unit_set_closure);
1164
    debug_info_w_start_unit_decs (unit_set_closure.num_unit_sets);
1165
    tdf_write_int (writer, unit_set_closure.num_unit_sets);
1166
    for (i = 0; i < capsule_num_unit_sets; i ++) {
1167
	UnitEntryP entry = capsule_unit_sets [i].entry;
1168
 
1169
	unit_entry_write_unit_set (entry, tld_entry, writer);
1170
    }
1171
    shape_table_iter (shapes, shape_entry_do_count, (GenericP) &num_shapes);
1172
    debug_info_w_start_shapes (num_shapes);
1173
    tdf_write_int (writer, num_shapes);
1174
    shape_table_iter (shapes, shape_entry_write_shape, (GenericP) writer);
1175
    debug_info_w_start_names (num_shapes);
1176
    tdf_write_int (writer, num_shapes);
1177
    shape_table_iter (shapes, shape_entry_write_externs, (GenericP) writer);
1178
    debug_info_w_start_unit_sets (unit_set_closure.num_unit_sets);
1179
    tdf_write_int (writer, unit_set_closure.num_unit_sets);
1180
    for (i = 0; i < capsule_num_unit_sets; i ++) {
1181
	UnitEntryP entry = capsule_unit_sets [i].entry;
1182
 
1183
	if (entry == tld_entry) {
1184
	    unit_entry_write_tld_unit (entry, shapes, writer);
1185
	} else {
1186
	    unit_entry_write_units (entry, shapes, num_shapes, writer);
1187
	}
1188
    }
1189
    debug_info_w_end_capsule ();
1190
}
1191
 
1192
void
1193
capsule_close PROTO_N ((capsule))
1194
	      PROTO_T (CapsuleP capsule)
1195
{
1196
    switch (capsule->type) EXHAUSTIVE {
1197
      case CT_INPUT:
1198
	tdf_reader_close (capsule_reader (capsule));
1199
	break;
1200
      case CT_OUTPUT:
1201
	tdf_writer_close (capsule_writer (capsule));
1202
	break;
1203
    }
1204
}
1205
 
1206
unsigned
1207
capsule_get_major_version PROTO_Z ()
1208
{
1209
    return (capsule_major_version);
1210
}
1211
 
1212
void
1213
capsule_set_major_version PROTO_N ((major))
1214
    			  PROTO_T (unsigned major)
1215
{
1216
    capsule_major_version = major;
1217
}
1218
 
1219
unsigned
1220
capsule_get_minor_version PROTO_Z ()
1221
{
1222
    return (capsule_minor_version);
1223
}
1224
 
1225
/*
1226
 * Local variables(smf):
1227
 * eval: (include::add-path-entry "../os-interface" "../library")
1228
 * eval: (include::add-path-entry "../generated")
1229
 * end:
1230
**/