Subversion Repositories tendra.SVN

Rev

Rev 2 | Details | Compare with Previous | 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
/*** library.c --- TDF library ADT.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the TDF library routines used by the TDF linker.
38
 *
39
 *** Change Log:
40
 * $Log: library.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  1995/09/22  08:39:17  smf
45
 * Fixed problems with incomplete structures (to shut "tcc" up).
46
 * Fixed some problems in "name-key.c" (no real problems, but rewritten to
47
 * reduce the warnings that were output by "tcc" and "gcc").
48
 * Fixed bug CR95_354.tld-common-id-problem (library capsules could be loaded
49
 * more than once).
50
 *
51
 * Revision 1.4  1995/07/07  15:32:25  smf
52
 * Updated to support TDF specification 4.0.
53
 *
54
 * Revision 1.3  1994/12/12  11:46:24  smf
55
 * Performing changes for 'CR94_178.sid+tld-update' - bringing in line with
56
 * OSSG C Coding Standards.
57
 *
58
 * Revision 1.2  1994/08/23  09:40:08  smf
59
 * Fixed bug DR114:ids-too-long.
60
 *
61
 * Revision 1.1.1.1  1994/07/25  16:03:31  smf
62
 * Initial import of TDF linker 3.5 non shared files.
63
 *
64
**/
65
 
66
/****************************************************************************/
67
 
68
#include "library.h"
69
#include "capsule.h"
70
#include "debug.h"
71
#include "exception.h"
72
#include "file-name.h"
73
#include "gen-errors.h"
74
#include "tdf.h"
75
#include "tdf-write.h"
76
 
77
#include "solve-cycles.h"
78
 
79
/*--------------------------------------------------------------------------*/
80
 
81
static ExceptionP XX_library_error   = EXCEPTION ("error in TDF library");
82
 
83
/*--------------------------------------------------------------------------*/
84
 
85
static TDFReaderP
86
library_reader PROTO_N ((library))
87
	       PROTO_T (LibraryP library)
88
{
89
    ASSERT (library->type == LT_INPUT);
90
    return (&(library->u.reader));
91
}
92
 
93
static TDFWriterP
94
library_writer PROTO_N ((library))
95
	       PROTO_T (LibraryP library)
96
{
97
    ASSERT (library->type == LT_OUTPUT);
98
    return (&(library->u.writer));
99
}
100
 
101
/*--------------------------------------------------------------------------*/
102
 
103
static void
104
library_check_index_entry PROTO_N ((library, entry, need_dec, no_mult,
105
				    shape_key, key, use, lib_capsule, table))
106
                          PROTO_T (LibraryP    library X
107
				   ShapeEntryP entry X
108
				   BoolT       need_dec X
109
				   BoolT       no_mult X
110
				   NStringP    shape_key X
111
				   NameKeyP    key X
112
				   unsigned    use X
113
				   LibCapsuleP lib_capsule X
114
				   NameTableP  table)
115
{
116
    NameEntryP  name_entry  = name_table_add (table, key, entry);
117
    unsigned    name_use    = name_entry_get_use (name_entry);
118
 
119
    if (use & ~(U_USED | U_DECD | U_DEFD | U_MULT)) {
120
	E_lib_bad_usage (library, shape_key, key, use);
121
	THROW (XX_library_error);
122
	UNREACHED;
123
    } else if (no_mult && (use & U_MULT)) {
124
	E_lib_illegally_mult_defined (library, shape_key, key);
125
	THROW (XX_library_error);
126
	UNREACHED;
127
    } else if (need_dec &&
128
	       (((use & (U_DEFD | U_DECD)) == U_DEFD) ||
129
		((use & (U_MULT | U_DECD)) == U_MULT))) {
130
	E_lib_defined_but_not_declared (library, shape_key, key);
131
	THROW (XX_library_error);
132
	UNREACHED;
133
    }
134
    if ((use & U_DEFD) && (name_use & U_DEFD)) {
135
	LibCapsuleP definition = name_entry_get_lib_definition (name_entry);
136
 
137
	E_lib_multiply_defined (library, shape_key, key, definition);
138
    } else if ((use & U_MULT) && (name_use & U_MULT) &&
139
	       (!(use & U_DEFD)) && (!(name_use & U_DEFD))) {
140
	name_entry_set_lib_definition (name_entry, NIL (LibCapsuleP));
141
    } else if ((use & U_DEFD) ||
142
	       ((use & U_MULT) && (!(name_use & (U_MULT | U_DEFD))))) {
143
	name_entry_set_lib_definition (name_entry, lib_capsule);
144
    }
145
    debug_info_r_index_entry (key, use, name_use, name_entry_key (name_entry),
146
			      lib_capsule_name (lib_capsule));
147
    name_entry_merge_use (name_entry, use);
148
}
149
 
150
static unsigned
151
library_read_version_0_capsules PROTO_N ((library))
152
				PROTO_T (LibraryP library)
153
{
154
    TDFReaderP reader       = library_reader (library);
155
    unsigned   num_capsules = tdf_read_int (reader);
156
    unsigned   i;
157
 
158
    debug_info_r_start_capsules (num_capsules);
159
    library->num_capsules = num_capsules;
160
    library->capsules     = ALLOCATE_VECTOR (LibCapsuleT, num_capsules);
161
    for (i = 0; i < num_capsules; i ++) {
162
	NStringP contents = &(library->capsules [i].contents);
163
	NStringT nstring;
164
	unsigned length;
165
 
166
	tdf_read_string (reader, &nstring);
167
	if (nstring_contains (&nstring, '\0')) {
168
	    E_null_in_file_name (library, &nstring);
169
	    THROW (XX_library_error);
170
	    UNREACHED;
171
	}
172
	library->capsules [i].name    = nstring_to_cstring (&nstring);
173
	library->capsules [i].library = library;
174
	library->capsules [i].loaded  = FALSE;
175
	length = tdf_read_int (reader);
176
	nstring_init_length (contents, length);
177
	tdf_read_bytes (reader, contents);
178
	debug_info_r_capsule (&nstring, length);
179
	nstring_destroy (&nstring);
180
    }
181
    return (num_capsules);
182
}
183
 
184
static void
185
library_read_version_0 PROTO_N ((library, shapes))
186
		       PROTO_T (LibraryP    library X
187
				ShapeTableP shapes)
188
{
189
    TDFReaderP  reader       = library_reader (library);
190
    unsigned    num_capsules = library_read_version_0_capsules (library);
191
    ShapeEntryP token_entry  = shape_table_get_token_entry (shapes);
192
    ShapeEntryP tag_entry    = shape_table_get_tag_entry (shapes);
193
    unsigned    num_shapes   = tdf_read_int (reader);
194
    unsigned    i;
195
 
196
    debug_info_r_start_index (num_shapes);
197
    for (i = 0; i < num_shapes; i ++) {
198
	NStringT    name;
199
	ShapeEntryP entry;
200
	BoolT       need_dec;
201
	BoolT       no_mult;
202
	NameTableP  table;
203
	unsigned    num_names;
204
	unsigned    j;
205
 
206
	tdf_read_string (reader, &name);
207
	entry     = shape_table_add (shapes, &name);
208
	need_dec  = (entry == tag_entry);
209
	no_mult   = (entry == token_entry);
210
	table     = shape_entry_name_table (entry);
211
	num_names = tdf_read_int (reader);
212
	debug_info_r_start_shape_index (&name, num_names);
213
	for (j = 0; j < num_names; j ++) {
214
	    NameKeyT    external_name;
215
	    unsigned    use;
216
	    unsigned    capsule_index;
217
	    LibCapsuleP lib_capsule;
218
 
219
	    tdf_read_name (reader, &external_name);
220
	    use           = tdf_read_int (reader);
221
	    capsule_index = tdf_read_int (reader);
222
	    if (capsule_index >= num_capsules) {
223
		E_capsule_index_too_big (library, &name, &external_name,
224
					 capsule_index, num_capsules);
225
		THROW (XX_library_error);
226
		UNREACHED;
227
	    }
228
	    lib_capsule = &(library->capsules [capsule_index]);
229
	    library_check_index_entry (library, entry, need_dec, no_mult,
230
				       &name, &external_name, use, lib_capsule,
231
				       table);
232
	    name_key_destroy (&external_name);
233
	}
234
	nstring_destroy (&name);
235
    }
236
    tdf_read_eof (reader);
237
}
238
 
239
static void
240
library_extract_1 PROTO_N ((capsule, use_basename))
241
		  PROTO_T (LibCapsuleP capsule X
242
			   BoolT       use_basename)
243
{
244
    CStringP   old_name = lib_capsule_name (capsule);
245
    CStringP   name     = old_name;
246
    NStringP   contents = lib_capsule_contents (capsule);
247
    TDFWriterT writer;
248
 
249
    if (use_basename) {
250
	name = file_name_basename (name);
251
    }
252
    file_name_populate (name);
253
    if (tdf_writer_open (&writer, name)) {
254
	E_extracting_capsule (old_name, name);
255
	tdf_write_bytes (&writer, contents);
256
	tdf_writer_close (&writer);
257
    } else {
258
	E_cannot_open_output_file (name);
259
    }
260
    if (use_basename) {
261
	DEALLOCATE (name);
262
    }
263
}
264
 
265
/*--------------------------------------------------------------------------*/
266
 
267
typedef void (*LibTypeProcP)
268
	PROTO_S ((LibraryP, ShapeTableP));
269
 
270
static LibTypeProcP library_type_jump_table [] = {
271
    library_read_version_0
272
};
273
 
274
#define LIBRARY_TYPE_JUMP_TABLE_SIZE \
275
	((unsigned) (sizeof (library_type_jump_table) / sizeof (LibTypeProcP)))
276
 
277
/*--------------------------------------------------------------------------*/
278
 
279
static NStringP
280
library_magic PROTO_Z ()
281
{
282
    static NStringT const_magic;
283
    static BoolT    inited = FALSE;
284
 
285
    if (!inited) {
286
	nstring_copy_cstring (&const_magic, "TDFL");
287
	inited = TRUE;
288
    }
289
    return (&const_magic);
290
}
291
 
292
/*--------------------------------------------------------------------------*/
293
 
294
static void
295
library_read_header PROTO_N ((library))
296
    		    PROTO_T (LibraryP library)
297
{
298
    TDFReaderP reader        = library_reader (library);
299
    NStringP   const_magic   = library_magic ();
300
    unsigned   capsule_major = capsule_get_major_version ();
301
    NStringT   magic;
302
    unsigned   major;
303
    unsigned   minor;
304
 
305
    nstring_init_length (&magic, (unsigned) 4);
306
    tdf_read_bytes (reader, &magic);
307
    if (!nstring_equal (&magic, const_magic)) {
308
	E_library_bad_magic (library, &magic, const_magic);
309
	THROW (XX_library_error);
310
	UNREACHED;
311
    }
312
    nstring_destroy (&magic);
313
    major = tdf_read_int (reader);
314
    minor = tdf_read_int (reader);
315
    debug_info_r_lib_versions (major, minor);
316
    if (major < 4) {
317
	E_library_bad_version (library, major);
318
	THROW (XX_library_error);
319
	UNREACHED;
320
    } else if (capsule_major == 0) {
321
	capsule_set_major_version (major);
322
    } else if (capsule_major != major) {
323
	E_library_version_mismatch (library, capsule_major, major);
324
	THROW (XX_library_error);
325
	UNREACHED;
326
    }
327
    library->major = major;
328
    library->minor = minor;
329
    tdf_read_align (reader);
330
}
331
 
332
/*--------------------------------------------------------------------------*/
333
 
334
static void
335
library_write_header PROTO_N ((library))
336
    		     PROTO_T (LibraryP library)
337
{
338
    TDFWriterP writer      = library_writer (library);
339
    NStringP   const_magic = library_magic ();
340
    unsigned   major       = capsule_get_major_version ();
341
    unsigned   minor       = capsule_get_minor_version ();
342
 
343
    tdf_write_bytes (writer, const_magic);
344
    ASSERT (major >= 4);
345
    tdf_write_int (writer, major);
346
    tdf_write_int (writer, minor);
347
    debug_info_w_lib_versions (major, minor);
348
    tdf_write_align (writer);
349
}
350
 
351
 
352
/*--------------------------------------------------------------------------*/
353
 
354
CStringP
355
lib_capsule_name PROTO_N ((capsule))
356
		 PROTO_T (LibCapsuleP capsule)
357
{
358
    return (capsule->name);
359
}
360
 
361
CStringP
362
lib_capsule_full_name PROTO_N ((capsule))
363
		      PROTO_T (LibCapsuleP capsule)
364
{
365
    CStringP lib_name   = library_name (capsule->library);
366
    unsigned lib_length = cstring_length (lib_name);
367
    CStringP name       = lib_capsule_name (capsule);
368
    unsigned length     = cstring_length (name);
369
    CStringP full_name  = ALLOCATE_VECTOR (char, lib_length + length + 3);
370
    CStringP tmp        = full_name;
371
 
372
    (void) memcpy ((GenericP) tmp, (GenericP) lib_name, (SizeT) lib_length);
373
    tmp += lib_length;
374
    *tmp = '(';
375
    tmp ++;
376
    (void) memcpy ((GenericP) tmp, (GenericP) name, (SizeT) length);
377
    tmp += length;
378
    *tmp = ')';
379
    tmp ++;
380
    *tmp = '\0';
381
    return (full_name);
382
}
383
 
384
NStringP
385
lib_capsule_contents PROTO_N ((capsule))
386
		     PROTO_T (LibCapsuleP capsule)
387
{
388
    return (&(capsule->contents));
389
}
390
 
391
BoolT
392
lib_capsule_is_loaded PROTO_N ((capsule))
393
    		      PROTO_T (LibCapsuleP capsule)
394
{
395
    return (capsule->loaded);
396
}
397
 
398
void
399
lib_capsule_loaded PROTO_N ((capsule))
400
    		   PROTO_T (LibCapsuleP capsule)
401
{
402
    capsule->loaded = TRUE;
403
}
404
 
405
/*--------------------------------------------------------------------------*/
406
 
407
void
408
write_lib_capsule_full_name PROTO_N ((ostream, capsule))
409
			    PROTO_T (OStreamP    ostream X
410
				     LibCapsuleP capsule)
411
{
412
    write_cstring (ostream, library_name (capsule->library));
413
    write_char (ostream, '(');
414
    write_cstring (ostream, lib_capsule_name (capsule));
415
    write_char (ostream, ')');
416
}
417
 
418
/*--------------------------------------------------------------------------*/
419
 
420
LibraryP
421
library_create_stream_input PROTO_N ((name))
422
			    PROTO_T (CStringP name)
423
{
424
    LibraryP library = ALLOCATE (LibraryT);
425
 
426
    library->type = LT_INPUT;
427
    if (!tdf_reader_open (library_reader (library), name)) {
428
	DEALLOCATE (library);
429
	return (NIL (LibraryP));
430
    }
431
    library->name     = name;
432
    library->complete = FALSE;
433
    return (library);
434
}
435
 
436
LibraryP
437
library_create_stream_output PROTO_N ((name))
438
			     PROTO_T (CStringP name)
439
{
440
    LibraryP library = ALLOCATE (LibraryT);
441
 
442
    library->type = LT_OUTPUT;
443
    if (!tdf_writer_open (library_writer (library), name)) {
444
	DEALLOCATE (library);
445
	return (NIL (LibraryP));
446
    }
447
    library->name     = name;
448
    library->complete = FALSE;
449
    return (library);
450
}
451
 
452
CStringP
453
library_name PROTO_N ((library))
454
	     PROTO_T (LibraryP library)
455
{
456
    return (library->name);
457
}
458
 
459
unsigned
460
library_num_capsules PROTO_N ((library))
461
		     PROTO_T (LibraryP library)
462
{
463
    return (library->num_capsules);
464
}
465
 
466
LibCapsuleP
467
library_get_capsule PROTO_N ((library, capsule_index))
468
		    PROTO_T (LibraryP library X
469
			     unsigned capsule_index)
470
{
471
    ASSERT (capsule_index < library->num_capsules);
472
    return (&(library->capsules [capsule_index]));
473
}
474
 
475
unsigned
476
library_byte PROTO_N ((library))
477
	     PROTO_T (LibraryP library)
478
{
479
    return (tdf_reader_byte (library_reader (library)));
480
}
481
 
482
void
483
library_content PROTO_N ((library, want_index, want_size, want_version))
484
		PROTO_T (LibraryP library X
485
			 BoolT    want_index X
486
			 BoolT    want_size X
487
		         BoolT    want_version)
488
{
489
    ShapeTableP shapes = shape_table_create ();
490
 
491
    library_read (library, shapes);
492
    if (library->complete) {
493
	unsigned i;
494
 
495
	if (want_version) {
496
	    write_char     (ostream_output, '[');
497
	    write_unsigned (ostream_output, library->major);
498
	    write_cstring  (ostream_output, ", ");
499
	    write_unsigned (ostream_output, library->minor);
500
	    write_char     (ostream_output, ']');
501
	    write_newline  (ostream_output);
502
	}
503
	for (i = 0; i < library->num_capsules; i ++) {
504
	    LibCapsuleP capsule = &(library->capsules [i]);
505
 
506
	    write_cstring (ostream_output, lib_capsule_name (capsule));
507
	    if (want_size) {
508
		NStringP body = lib_capsule_contents (capsule);
509
 
510
		write_cstring (ostream_output, " (");
511
		write_unsigned (ostream_output, nstring_length (body));
512
		write_char (ostream_output, ')');
513
	    }
514
	    write_newline (ostream_output);
515
	}
516
	if (want_index) {
517
	    shape_table_iter (shapes, shape_entry_show_content,
518
			      NIL (GenericP));
519
	}
520
    }
521
}
522
 
523
void
524
library_extract_all PROTO_N ((library, use_basename))
525
		    PROTO_T (LibraryP library X
526
			     BoolT    use_basename)
527
{
528
    ShapeTableP shapes = shape_table_create ();
529
 
530
    library_read (library, shapes);
531
    if (library->complete) {
532
	unsigned i;
533
 
534
	for (i = 0; i < library->num_capsules; i ++) {
535
	    LibCapsuleP capsule = &(library->capsules [i]);
536
 
537
	    library_extract_1 (capsule, use_basename);
538
	}
539
    }
540
}
541
 
542
void
543
library_extract PROTO_N ((library, use_basename, match_basename, num_files,
544
			  files))
545
		PROTO_T (LibraryP  library X
546
			 BoolT     use_basename X
547
			 BoolT     match_basename X
548
			 unsigned  num_files X
549
			 CStringP *files)
550
{
551
    ShapeTableP shapes = shape_table_create ();
552
 
553
    library_read (library, shapes);
554
    if (library->complete) {
555
	unsigned i;
556
 
557
	for (i = 0; i < num_files; i ++) {
558
	    BoolT    matched = FALSE;
559
	    unsigned j;
560
 
561
	    for (j = 0; j < library->num_capsules; j ++) {
562
		LibCapsuleP capsule   = &(library->capsules [j]);
563
		CStringP    file_name = (files [i]);
564
		CStringP    lib_name  = lib_capsule_name (capsule);
565
		CStringP    base_name = NIL (CStringP);
566
 
567
		if (match_basename) {
568
		    base_name = file_name_basename (lib_name);
569
		}
570
		if ((cstring_equal (file_name, lib_name)) ||
571
		    (match_basename && cstring_equal (file_name, base_name))) {
572
		    library_extract_1 (capsule, use_basename);
573
		    matched = TRUE;
574
		}
575
		if (match_basename) {
576
		    DEALLOCATE (base_name);
577
		}
578
	    }
579
	    if (!matched) {
580
		E_capsule_not_found (files [i], library_name (library));
581
	    }
582
	}
583
    }
584
}
585
 
586
void
587
library_read PROTO_N ((library, shapes))
588
	     PROTO_T (LibraryP    library X
589
		      ShapeTableP shapes)
590
{
591
    HANDLE {
592
	TDFReaderP reader = library_reader (library);
593
	unsigned   library_type;
594
 
595
	debug_info_r_start_library (library_name (library));
596
	library_read_header (library);
597
	library_type = tdf_read_int (reader);
598
	if (library_type >= LIBRARY_TYPE_JUMP_TABLE_SIZE) {
599
	    E_lib_unknown_type (library, library_type);
600
	    THROW (XX_library_error);
601
	    UNREACHED;
602
	}
603
	debug_info_r_library_version (library_type);
604
	(*(library_type_jump_table [library_type])) (library, shapes);
605
	debug_info_r_end_library ();
606
	library->complete = TRUE;
607
    } WITH {
608
	ExceptionP exception = EXCEPTION_EXCEPTION ();
609
 
610
	debug_info_r_abort_library ();
611
	if ((exception != XX_tdf_read_error) &&
612
	    (exception != XX_library_error)) {
613
	    RETHROW ();
614
	}
615
    } END_HANDLE
616
}
617
 
618
void
619
library_write PROTO_N ((library, shapes, num_capsules, capsules))
620
	      PROTO_T (LibraryP    library X
621
		       ShapeTableP shapes X
622
		       unsigned    num_capsules X
623
		       CapsuleP   *capsules)
624
{
625
    TDFWriterP writer     = library_writer (library);
626
    unsigned   num_shapes = 0;
627
    unsigned   i;
628
 
629
    debug_info_w_start_library (library_name (library));
630
    library_write_header (library);
631
    debug_info_w_library_version ((unsigned) 0);
632
    tdf_write_int (writer, (unsigned) 0);
633
    debug_info_w_start_capsules (num_capsules);
634
    tdf_write_int (writer, num_capsules);
635
    for (i = 0; i < num_capsules; i ++) {
636
	CapsuleP capsule  = capsules [i];
637
	CStringP name     = capsule_name (capsule);
638
	NStringP contents = capsule_contents (capsule);
639
	unsigned length   = nstring_length (contents);
640
	NStringT nstring;
641
 
642
	debug_info_w_capsule (name, length);
643
	nstring_copy_cstring (&nstring, name);
644
	tdf_write_string (writer, &nstring);
645
	nstring_destroy (&nstring);
646
	tdf_write_int (writer, length);
647
	tdf_write_bytes (writer, contents);
648
    }
649
    shape_table_iter (shapes, shape_entry_do_lib_count,
650
		      (GenericP) &num_shapes);
651
    debug_info_w_start_index (num_shapes);
652
    tdf_write_int (writer, num_shapes);
653
    shape_table_iter (shapes, shape_entry_do_lib_write, (GenericP) writer);
654
    debug_info_w_end_library ();
655
}
656
 
657
void
658
library_close PROTO_N ((library))
659
	      PROTO_T (LibraryP library)
660
{
661
    switch (library->type) EXHAUSTIVE {
662
      case CT_INPUT:
663
	tdf_reader_close (library_reader (library));
664
	break;
665
      case CT_OUTPUT:
666
	tdf_writer_close (library_writer (library));
667
	break;
668
    }
669
}
670
 
671
/*
672
 * Local variables(smf):
673
 * eval: (include::add-path-entry "../os-interface" "../library")
674
 * eval: (include::add-path-entry "../generated")
675
 * end:
676
**/