Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5-amd64/src/producers/common/output/save.c – Rev 6

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
/*
6 7u83 2
 * Copyright (c) 2002-2006 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "version.h"
63
#include "system.h"
64
#include "c_types.h"
65
#include "ctype_ops.h"
66
#include "etype_ops.h"
67
#include "exp_ops.h"
68
#include "ftype_ops.h"
69
#include "graph_ops.h"
70
#include "hashid_ops.h"
71
#include "id_ops.h"
72
#include "itype_ops.h"
73
#include "loc_ext.h"
74
#include "nat_ops.h"
75
#include "nspace_ops.h"
76
#include "off_ops.h"
77
#include "tok_ops.h"
78
#include "type_ops.h"
79
#include "error.h"
80
#include "catalog.h"
81
#include "basetype.h"
82
#include "bits.h"
83
#include "char.h"
84
#include "chktype.h"
85
#include "dump.h"
86
#include "encode.h"
87
#include "exception.h"
88
#include "file.h"
89
#include "inttype.h"
90
#include "save.h"
91
#include "syntax.h"
92
#include "ustring.h"
93
 
94
 
95
/*
96
    FORWARD DECLARATIONS
97
 
98
    The following forward declarations are required in the spec output
99
    routines.
100
*/
101
 
6 7u83 102
static BITSTREAM *save_exp(BITSTREAM *, EXP, TYPE);
103
static BITSTREAM *save_type(BITSTREAM *, TYPE, IDENTIFIER);
104
static BITSTREAM *save_ctype(BITSTREAM *, CLASS_TYPE, IDENTIFIER);
105
static BITSTREAM *save_type_list(BITSTREAM *, LIST(TYPE));
106
static BITSTREAM *save_tok(BITSTREAM *, TOKEN, int);
2 7u83 107
 
108
 
109
/*
110
    SIMPLE WRITING ROUTINES
111
 
112
    These macros give the simple writing routines for the enumeration
113
    types etc.  Note that ENC_BITS_2 is used when the values occupy more
114
    than 16 bits.
115
*/
116
 
6 7u83 117
#define save_btype(A, B)	ENC_BITS_2((A), BITS_btype,(B))
118
#define save_cinfo(A, B)	ENC_BITS_2((A), BITS_cinfo,(B))
119
#define save_cusage(A, B)	ENC_BITS((A), BITS_cusage,(B))
120
#define save_cv(A, B)		ENC_BITS((A), BITS_cv_qual,(B))
121
#define save_dspec(A, B)	ENC_BITS_2((A), BITS_dspec,(B))
122
#define save_lex(A, B)		ENC_BITS((A), BITS_lex,(B))
123
#define save_mqual(A, B)	ENC_BITS((A), BITS_cv,(B))
124
#define save_ntype(A, B)	ENC_BITS((A), BITS_ntype,(B))
125
#define save_qual(A, B)		ENC_BITS((A), BITS_qual,(B))
2 7u83 126
 
127
 
128
/*
129
    WRITE A LIST OF PREPROCESSING TOKENS
130
 
131
    This routine writes the list of preprocessing tokens p to the
132
    bitstream bs.
133
*/
134
 
6 7u83 135
static BITSTREAM *
136
save_pptoks(BITSTREAM *bs, PPTOKEN *p)
2 7u83 137
{
6 7u83 138
	/* NOT YET IMPLEMENTED */
139
	UNUSED(p);
140
	return (bs);
2 7u83 141
}
142
 
143
 
144
/*
145
    WRITE A LOCATION
146
 
147
    This routine writes the location ploc to the bitstream bs.
148
*/
149
 
6 7u83 150
static BITSTREAM *
151
save_loc(BITSTREAM *bs, PTR(LOCATION)ploc)
2 7u83 152
{
6 7u83 153
	static LOCATION last_loc = NULL_loc;
154
	if (!IS_NULL_ptr(ploc)) {
155
		unsigned long ln = DEREF_ulong(loc_line(ploc));
156
		PTR(POSITION)posn = DEREF_ptr(loc_posn(ploc));
157
		if (EQ_ptr(posn, last_loc.posn) || IS_NULL_ptr(posn)) {
158
			if (ln == last_loc.line) {
159
				/* Same position */
160
				ENC_OFF(bs);
161
			} else {
162
				/* Different line */
163
				ENC_ON(bs);
164
				ENC_INT(bs, ln);
165
				ENC_OFF(bs);
166
				last_loc.line = ln;
167
			}
2 7u83 168
		} else {
6 7u83 169
			int eq =0;
170
			unsigned long off = DEREF_ulong(posn_offset(posn));
171
			string a1 = DEREF_string(posn_file(posn));
172
			string b1 = DEREF_string(posn_input(posn));
173
			if (!IS_NULL_ptr(last_loc.posn)) {
174
				string a2 =
175
				    DEREF_string(posn_file(last_loc.posn));
176
				string b2 =
177
				    DEREF_string(posn_input(last_loc.posn));
178
				if (ustreq(a1, a2) && ustreq(b1, b2)) {
179
					eq = 1;
180
				}
181
			}
182
			ENC_ON(bs);
183
			ENC_INT(bs, ln);
184
			ENC_ON(bs);
185
			ENC_INT(bs, off);
186
			if (eq) {
187
				/* Same file */
188
				ENC_OFF(bs);
189
			} else {
190
				ulong date;
191
				ENC_ON(bs);
192
				bs = enc_ustring(bs, a1);
193
				if (ustreq(a1, b1)) {
194
					/* Same file names */
195
					ENC_OFF(bs);
196
				} else {
197
					/* Different file names */
198
					ENC_ON(bs);
199
					bs = enc_ustring(bs, b1);
200
				}
201
				date = DEREF_ulong(posn_datestamp(posn));
202
				ENC_INT(bs, date);
203
			}
204
			last_loc.line = ln;
205
			last_loc.posn = posn;
2 7u83 206
		}
6 7u83 207
	} else {
208
		ENC_OFF(bs);
2 7u83 209
	}
6 7u83 210
	return (bs);
2 7u83 211
}
212
 
213
 
214
/*
215
    WRITE AN IDENTIFIER NAME
216
 
217
    This routine writes the identifier name nm to the bitstream bs.
218
    ns gives the current namespace.
219
*/
220
 
6 7u83 221
static BITSTREAM *
222
save_hashid(BITSTREAM *bs, HASHID nm, NAMESPACE ns)
2 7u83 223
{
6 7u83 224
	if (IS_NULL_hashid(nm)) {
225
		ENC_BITS(bs, BITS_hashid, 0);
226
	} else {
227
		unsigned tag = TAG_hashid(nm);
228
		ENC_BITS(bs, BITS_hashid, tag + 1);
229
		ASSERT(ORDER_hashid == 7);
230
		switch (tag) {
231
		case hashid_name_tag:
232
		case hashid_ename_tag: {
233
			string s = DEREF_string(hashid_name_etc_text(nm));
234
			bs = enc_ustring(bs, s);
235
			break;
236
		}
237
		case hashid_constr_tag: {
238
			UNUSED(ns);
239
			break;
240
		}
241
		case hashid_destr_tag: {
242
			UNUSED(ns);
243
			break;
244
		}
245
		case hashid_conv_tag: {
246
			TYPE t = DEREF_type(hashid_conv_type(nm));
247
			bs = save_type(bs, t, NULL_id);
248
			break;
249
		}
250
		case hashid_op_tag: {
251
			int op = DEREF_int(hashid_op_lex(nm));
252
			save_lex(bs, op);
253
			break;
254
		}
255
		case hashid_anon_tag: {
256
			break;
257
		}
258
		}
2 7u83 259
	}
6 7u83 260
	return (bs);
2 7u83 261
}
262
 
263
 
264
/*
265
    WRITE A LIST OF IDENTIFIER NAMES
266
 
267
    This routine saves a list of identifier names to the bitstream bs.
268
*/
269
 
6 7u83 270
static BITSTREAM *
271
save_hashid_list(BITSTREAM *bs, LIST(HASHID)p, NAMESPACE ns)
2 7u83 272
{
6 7u83 273
	while (!IS_NULL_list(p)) {
274
		HASHID nm = DEREF_hashid(HEAD_list(p));
275
		ENC_ON(bs);
276
		bs = save_hashid(bs, nm, ns);
277
		p = TAIL_list(p);
278
	}
279
	ENC_OFF(bs);
280
	return (bs);
2 7u83 281
}
282
 
283
 
284
/*
285
    WRITE AN IDENTIFIER NUMBER
286
 
287
    This routine writes the identifier number for the identifier id to
288
    the bitstream bs.  The spec and dump output formats share the same
289
    identifier numbers, with zero representing the null identifier.
290
*/
291
 
6 7u83 292
static BITSTREAM *
293
save_use(BITSTREAM *bs, IDENTIFIER id)
2 7u83 294
{
6 7u83 295
	ulong d = 0;
296
	if (!IS_NULL_id(id)) {
297
		d = DEREF_ulong(id_dump(id));
298
		if (d == LINK_NONE) {
299
			d = dump_id_next++;
300
			d |= LINK_EXTERN;
301
			COPY_ulong(id_dump(id), d);
302
		}
303
		d &= ~LINK_EXTERN;
2 7u83 304
	}
6 7u83 305
	ENC_INT(bs, d);
306
	return (bs);
2 7u83 307
}
308
 
309
 
310
/*
311
    WRITE A LIST OF IDENTIFIER NUMBERS
312
 
313
    This routine saves a list of identifier numbers to the bitstream bs.
314
*/
315
 
6 7u83 316
static BITSTREAM *
317
save_use_list(BITSTREAM *bs, LIST(IDENTIFIER)p)
2 7u83 318
{
6 7u83 319
	while (!IS_NULL_list(p)) {
320
		IDENTIFIER id = DEREF_id(HEAD_list(p));
321
		ENC_ON(bs);
322
		bs = save_use(bs, id);
323
		p = TAIL_list(p);
324
	}
325
	ENC_OFF(bs);
326
	return (bs);
2 7u83 327
}
328
 
329
 
330
/*
331
    WRITE A LIST OF IDENTIFIERS
332
 
333
    This routine saves a list of identifiers to the bitstream bs.
334
*/
335
 
6 7u83 336
static BITSTREAM *
337
save_id_list(BITSTREAM *bs, LIST(IDENTIFIER)p, NAMESPACE ns)
2 7u83 338
{
6 7u83 339
	while (!IS_NULL_list(p)) {
340
		IDENTIFIER id = DEREF_id(HEAD_list(p));
341
		ENC_ON(bs);
342
		bs = save_id(bs, id, ns);
343
		p = TAIL_list(p);
344
	}
345
	ENC_OFF(bs);
346
	return (bs);
2 7u83 347
}
348
 
349
 
350
/*
351
    WRITE A LIST OF TOKENS
352
 
353
    This routine writes the list of tokens p to the bitstream bs.  def
354
    is as in save_tok.
355
*/
356
 
6 7u83 357
static BITSTREAM *
358
save_tok_list(BITSTREAM *bs, LIST(TOKEN)p, int def)
2 7u83 359
{
6 7u83 360
	while (!IS_NULL_list(p)) {
361
		TOKEN tok = DEREF_tok(HEAD_list(p));
362
		ENC_ON(bs);
363
		bs = save_tok(bs, tok, def);
364
		p = TAIL_list(p);
365
	}
366
	ENC_OFF(bs);
367
	return (bs);
2 7u83 368
}
369
 
370
 
371
/*
372
    WRITE AN INTEGER CONSTANT
373
 
374
    This routine writes the integer constant n to the bitstream bs.
375
*/
376
 
6 7u83 377
static BITSTREAM *
378
save_nat(BITSTREAM *bs, NAT n)
2 7u83 379
{
6 7u83 380
	unsigned tag;
381
	if (IS_NULL_nat(n)) {
382
		ENC_BITS(bs, BITS_nat, 0);
383
		return (bs);
2 7u83 384
	}
6 7u83 385
	tag = TAG_nat(n);
386
	ENC_BITS(bs, BITS_nat, tag + 1);
387
	ASSERT(ORDER_nat == 5);
388
	switch (tag) {
389
	case nat_small_tag: {
390
		unsigned v = DEREF_unsigned(nat_small_value(n));
391
		ENC_INT(bs, v);
392
		break;
2 7u83 393
	}
6 7u83 394
	case nat_large_tag: {
395
		LIST(unsigned)p = DEREF_list(nat_large_values(n));
396
		while (!IS_NULL_list(p)) {
397
			unsigned v = DEREF_unsigned(HEAD_list(p));
398
			ENC_ON(bs);
399
			ENC_INT(bs, v);
400
			p = TAIL_list(p);
401
		}
402
		ENC_OFF(bs);
403
		break;
2 7u83 404
	}
6 7u83 405
	case nat_calc_tag: {
406
		EXP e = DEREF_exp(nat_calc_value(n));
407
		bs = save_exp(bs, e, type_sint);
408
		break;
2 7u83 409
	}
6 7u83 410
	case nat_neg_tag: {
411
		NAT m = DEREF_nat(nat_neg_arg(n));
412
		bs = save_nat(bs, m);
413
		break;
2 7u83 414
	}
6 7u83 415
	case nat_token_tag: {
416
		IDENTIFIER tok = DEREF_id(nat_token_tok(n));
417
		LIST(TOKEN)args = DEREF_list(nat_token_args(n));
418
		bs = save_use(bs, tok);
419
		bs = save_tok_list(bs, args, 1);
420
		break;
421
	}
422
	}
423
	return (bs);
2 7u83 424
}
425
 
426
 
427
/*
428
    WRITE AN OFFSET
429
 
430
    This routine writes the offset off to the bitstream bs.
431
*/
432
 
6 7u83 433
static BITSTREAM *
434
save_off(BITSTREAM *bs, OFFSET off)
2 7u83 435
{
6 7u83 436
	/* NOT YET IMPLEMENTED */
437
	UNUSED(off);
438
	return (bs);
2 7u83 439
}
440
 
441
 
442
/*
443
    WRITE AN EXPRESSION
444
 
445
    This routine writes the expression e to the bitstream bs.
446
*/
447
 
6 7u83 448
static BITSTREAM *
449
save_exp(BITSTREAM *bs, EXP e, TYPE t)
2 7u83 450
{
6 7u83 451
	unsigned tag;
452
	if (IS_NULL_exp(e)) {
453
		ENC_BITS(bs, BITS_exp, 0);
454
		return (bs);
2 7u83 455
	}
6 7u83 456
	tag = TAG_exp(e);
457
	ENC_BITS(bs, BITS_exp, tag + 1);
458
	switch (tag) {
459
	case exp_int_lit_tag: {
460
		NAT m = DEREF_nat(exp_int_lit_nat(e));
461
		unsigned etag = DEREF_unsigned(exp_int_lit_etag(e));
462
		bs = save_nat(bs, m);
463
		ENC_BITS(bs, BITS_exp, etag);
464
		break;
2 7u83 465
	}
6 7u83 466
	case exp_token_tag: {
467
		IDENTIFIER tok = DEREF_id(exp_token_tok(e));
468
		LIST(TOKEN)args = DEREF_list(exp_token_args(e));
469
		bs = save_use(bs, tok);
470
		bs = save_tok_list(bs, args, 1);
471
		break;
2 7u83 472
	}
6 7u83 473
	default: {
474
		/* NOT YET IMPLEMENTED */
475
		break;
476
	}
477
	}
478
	UNUSED(t);
479
	return (bs);
2 7u83 480
}
481
 
482
 
483
/*
484
    WRITE AN INTEGRAL TYPE
485
 
486
    This routine writes the integral type it to the bitstream bs.
487
*/
488
 
6 7u83 489
static BITSTREAM *
490
save_itype(BITSTREAM *bs, INT_TYPE it)
2 7u83 491
{
6 7u83 492
	unsigned tag;
493
	if (IS_NULL_itype(it)) {
494
		ENC_BITS(bs, BITS_itype, 0);
495
		return (bs);
2 7u83 496
	}
6 7u83 497
	tag = TAG_itype(it);
498
	ENC_BITS(bs, BITS_itype, tag + 1);
499
	ASSERT(ORDER_itype == 6);
500
	switch (tag) {
501
	case itype_basic_tag: {
502
		BUILTIN_TYPE nt = DEREF_ntype(itype_basic_no(it));
503
		save_ntype(bs, nt);
504
		break;
2 7u83 505
	}
6 7u83 506
	case itype_bitfield_tag: {
507
		NAT m = DEREF_nat(itype_bitfield_size(it));
508
		TYPE s = DEREF_type(itype_bitfield_sub(it));
509
		BASE_TYPE bt = DEREF_btype(itype_bitfield_rep(it));
510
		bs = save_type(bs, s, NULL_id);
511
		save_btype(bs, bt);
512
		bs = save_nat(bs, m);
513
		break;
2 7u83 514
	}
6 7u83 515
	case itype_promote_tag: {
516
		INT_TYPE is = DEREF_itype(itype_promote_arg(it));
517
		bs = save_itype(bs, is);
518
		break;
2 7u83 519
	}
6 7u83 520
	case itype_arith_tag: {
521
		INT_TYPE is = DEREF_itype(itype_arith_arg1(it));
522
		INT_TYPE ir = DEREF_itype(itype_arith_arg2(it));
523
		bs = save_itype(bs, is);
524
		bs = save_itype(bs, ir);
525
		break;
2 7u83 526
	}
6 7u83 527
	case itype_literal_tag: {
528
		NAT m = DEREF_nat(itype_literal_nat(it));
529
		int form = DEREF_int(itype_literal_form(it));
530
		int suff = DEREF_int(itype_literal_suff(it));
531
		bs = save_nat(bs, m);
532
		ENC_BITS(bs, 2, form);
533
		ENC_BITS(bs, 3, suff);
534
		break;
2 7u83 535
	}
6 7u83 536
	case itype_token_tag: {
537
		IDENTIFIER tok = DEREF_id(itype_token_tok(it));
538
		LIST(TOKEN)args = DEREF_list(itype_token_args(it));
539
		bs = save_use(bs, tok);
540
		bs = save_tok_list(bs, args, 1);
541
		break;
542
	}
543
	}
544
	return (bs);
2 7u83 545
}
546
 
547
 
548
/*
549
    WRITE A FLOATING POINT TYPE
550
 
551
    This routine writes the floating point type ft to the bitstream bs.
552
*/
553
 
6 7u83 554
static BITSTREAM *
555
save_ftype(BITSTREAM *bs, FLOAT_TYPE ft)
2 7u83 556
{
6 7u83 557
	unsigned tag;
558
	if (IS_NULL_ftype(ft)) {
559
		ENC_BITS(bs, BITS_ftype, 0);
560
		return (bs);
2 7u83 561
	}
6 7u83 562
	tag = TAG_ftype(ft);
563
	ENC_BITS(bs, BITS_ftype, tag + 1);
564
	switch (tag) {
565
	case ftype_basic_tag: {
566
		BUILTIN_TYPE no = DEREF_ntype(ftype_basic_no(ft));
567
		save_ntype(bs, no);
568
		break;
2 7u83 569
	}
6 7u83 570
	case ftype_arg_promote_tag: {
571
		FLOAT_TYPE fs = DEREF_ftype(ftype_arg_promote_arg(ft));
572
		bs = save_ftype(bs, fs);
573
		break;
2 7u83 574
	}
6 7u83 575
	case ftype_arith_tag: {
576
		FLOAT_TYPE fs = DEREF_ftype(ftype_arith_arg1(ft));
577
		FLOAT_TYPE fr = DEREF_ftype(ftype_arith_arg2(ft));
578
		bs = save_ftype(bs, fs);
579
		bs = save_ftype(bs, fr);
580
		break;
2 7u83 581
	}
6 7u83 582
	case ftype_token_tag: {
583
		IDENTIFIER tok = DEREF_id(ftype_token_tok(ft));
584
		LIST(TOKEN)args = DEREF_list(ftype_token_args(ft));
585
		bs = save_use(bs, tok);
586
		bs = save_tok_list(bs, args, 1);
587
		break;
588
	}
589
	}
590
	return (bs);
2 7u83 591
}
592
 
593
 
594
/*
595
    WRITE A BASE CLASS GRAPH
596
 
597
    This routine writes the base class graph gr to the bitstream bs.
598
    The graph gt gives the top of the graph which is not output.
599
*/
600
 
6 7u83 601
static BITSTREAM *
602
save_graph(BITSTREAM *bs, GRAPH gr, GRAPH gt)
2 7u83 603
{
6 7u83 604
	LIST(GRAPH)br = DEREF_list(graph_tails(gr));
605
	if (!EQ_graph(gr, gt)) {
606
		CLASS_TYPE ct = DEREF_ctype(graph_head(gr));
607
		DECL_SPEC acc = DEREF_dspec(graph_access(gr));
608
		bs = save_ctype(bs, ct, NULL_id);
609
		save_dspec(bs, acc);
610
	}
611
	while (!IS_NULL_list(br)) {
612
		GRAPH gs = DEREF_graph(HEAD_list(br));
613
		ENC_ON(bs);
614
		bs = save_graph(bs, gs, gt);
615
		br = TAIL_list(br);
616
	}
617
	ENC_OFF(bs);
618
	return (bs);
2 7u83 619
}
620
 
621
 
622
/*
623
    WRITE A CLASS TYPE
624
 
625
    This routine writes the class type ct to the bitstream bs.  If def
626
    is not null then the full definition is written, otherwise just a use
627
    is written.
628
*/
629
 
6 7u83 630
static BITSTREAM *
631
save_ctype(BITSTREAM *bs, CLASS_TYPE ct, IDENTIFIER def)
2 7u83 632
{
6 7u83 633
	if (!IS_NULL_id(def)) {
634
		CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
635
		CLASS_USAGE cu = DEREF_cusage(ctype_usage(ct));
636
		GRAPH gr = DEREF_graph(ctype_base(ct));
637
		TYPE form = DEREF_type(ctype_form(ct));
638
		save_cinfo(bs, ci);
639
		save_cusage(bs, cu);
640
		bs = save_graph(bs, gr, gr);
641
		if (!IS_NULL_type(form)) {
642
			ENC_ON(bs);
643
			bs = save_type(bs, form, NULL_id);
644
		} else {
645
			ENC_OFF(bs);
646
		}
2 7u83 647
	} else {
6 7u83 648
		IDENTIFIER cid = DEREF_id(ctype_name(ct));
649
		bs = save_use(bs, cid);
2 7u83 650
	}
6 7u83 651
	return (bs);
2 7u83 652
}
653
 
654
 
655
/*
656
    WRITE AN ENUMERATION TYPE
657
 
658
    This routine writes the enumeration type et to the bitstream bs.  If
659
    def is not null then the full definition is written, otherwise just a
660
    use is written.
661
*/
662
 
6 7u83 663
static BITSTREAM *
664
save_etype(BITSTREAM *bs, ENUM_TYPE et, IDENTIFIER def)
2 7u83 665
{
6 7u83 666
	if (!IS_NULL_id(def)) {
667
		CLASS_INFO ei = DEREF_cinfo(etype_info(et));
668
		TYPE t = DEREF_type(etype_rep(et));
669
		TYPE form = DEREF_type(etype_form(et));
670
		save_cinfo(bs, ei);
671
		bs = save_type(bs, t, NULL_id);
672
		if (!IS_NULL_type(form)) {
673
			ENC_ON(bs);
674
			bs = save_type(bs, form, NULL_id);
675
		} else {
676
			ENC_OFF(bs);
677
		}
2 7u83 678
	} else {
6 7u83 679
		IDENTIFIER eid = DEREF_id(etype_name(et));
680
		bs = save_use(bs, eid);
2 7u83 681
	}
6 7u83 682
	return (bs);
2 7u83 683
}
684
 
685
 
686
/*
687
    WRITE A TYPE
688
 
689
    This routine writes the type t to the bitstream bs.  def is passed to
690
    save_ctype and save_etype.
691
*/
692
 
6 7u83 693
static BITSTREAM *
694
save_type(BITSTREAM *bs, TYPE t, IDENTIFIER def)
2 7u83 695
{
6 7u83 696
	CV_SPEC cv;
697
	unsigned tag;
698
	BUILTIN_TYPE nt = is_builtin_type(t, 1);
699
	if (nt != ntype_none) {
700
		/* Built-in types */
701
		ENC_ON(bs);
702
		cv = DEREF_cv(type_qual(t));
703
		save_cv(bs, cv);
704
		save_ntype(bs, nt);
705
		return (bs);
706
	}
707
	ENC_OFF(bs);
708
	if (IS_NULL_type(t)) {
709
		/* Null types */
710
		ENC_BITS(bs, BITS_type, 0);
711
		return (bs);
712
	}
2 7u83 713
 
6 7u83 714
	/* Save type independent fields */
715
	tag = TAG_type(t);
716
	ENC_BITS(bs, BITS_type, tag + 1);
717
	cv = DEREF_cv(type_qual(t));
718
	save_cv(bs, cv);
2 7u83 719
 
6 7u83 720
	/* Save type dependent fields */
721
	ASSERT(ORDER_type == 18);
722
	switch (TAG_type(t)) {
723
	case type_pre_tag: {
724
		IDENTIFIER tid = DEREF_id(type_name(t));
725
		QUALIFIER qual = DEREF_qual(type_pre_nqual(t));
726
		BASE_TYPE bt = DEREF_btype(type_pre_rep(t));
727
		bs = save_use(bs, tid);
728
		save_qual(bs, qual);
729
		save_btype(bs, bt);
730
		break;
2 7u83 731
	}
6 7u83 732
	case type_integer_tag: {
733
		INT_TYPE it = DEREF_itype(type_integer_rep(t));
734
		INT_TYPE is = DEREF_itype(type_integer_sem(t));
735
		INT_TYPE ir = it;
736
		bs = save_itype(bs, it);
737
		if (IS_itype_promote(ir)) {
738
			/* Find default semantic type for it */
739
			ir = DEREF_itype(itype_promote_arg(ir));
740
		}
741
		if (EQ_itype(ir, is) || eq_itype(ir, is)) {
742
			/* Default semantics */
743
			ENC_OFF(bs);
744
		} else {
745
			/* Non-standard semantic type */
746
			ENC_ON(bs);
747
			bs = save_itype(bs, is);
748
		}
749
		break;
2 7u83 750
	}
6 7u83 751
	case type_floating_tag: {
752
		FLOAT_TYPE ft = DEREF_ftype(type_floating_rep(t));
753
		bs = save_ftype(bs, ft);
754
		break;
2 7u83 755
	}
6 7u83 756
	case type_top_tag:
757
	case type_bottom_tag: {
758
		/* Already handled */
759
		break;
2 7u83 760
	}
6 7u83 761
	case type_ptr_tag:
762
	case type_ref_tag: {
763
		TYPE s = DEREF_type(type_ptr_etc_sub(t));
764
		bs = save_type(bs, s, NULL_id);
765
		break;
2 7u83 766
	}
6 7u83 767
	case type_ptr_mem_tag: {
768
		CLASS_TYPE cs = DEREF_ctype(type_ptr_mem_of(t));
769
		TYPE s = DEREF_type(type_ptr_mem_sub(t));
770
		bs = save_ctype(bs, cs, NULL_id);
771
		bs = save_type(bs, s, NULL_id);
772
		break;
2 7u83 773
	}
6 7u83 774
	case type_func_tag: {
775
		TYPE r = DEREF_type(type_func_ret(t));
776
		LIST(IDENTIFIER)pids = DEREF_list(type_func_pids(t));
777
		int ell = DEREF_int(type_func_ellipsis(t));
778
		LIST(TYPE)p = DEREF_list(type_func_ptypes(t));
779
		LIST(TYPE)m = DEREF_list(type_func_mtypes(t));
780
		LIST(TYPE)ex = DEREF_list(type_func_except(t));
781
		CV_SPEC mqual = DEREF_cv(type_func_mqual(t));
782
		bs = save_type(bs, r, NULL_id);
783
		bs = save_id_list(bs, pids, NULL_nspace);
784
		ENC_BITS(bs, BITS_ellipsis, ell);
785
		save_mqual(bs, mqual);
786
		if (EQ_list(p, m)) {
787
			ENC_OFF(bs);
788
		} else {
789
			CLASS_TYPE cs;
790
			TYPE s = DEREF_type(HEAD_list(m));
791
			s = DEREF_type(type_ref_sub(s));
792
			cs = DEREF_ctype(type_compound_defn(s));
793
			ENC_ON(bs);
794
			bs = save_ctype(bs, cs, NULL_id);
795
		}
796
		if (EQ_list(ex, univ_type_set)) {
797
			ENC_OFF(bs);
798
		} else {
799
			ENC_ON(bs);
800
			bs = save_type_list(bs, ex);
801
		}
802
		break;
2 7u83 803
	}
6 7u83 804
	case type_array_tag: {
805
		TYPE s = DEREF_type(type_array_sub(t));
806
		NAT m = DEREF_nat(type_array_size(t));
807
		bs = save_type(bs, s, NULL_id);
808
		bs = save_nat(bs, m);
809
		break;
2 7u83 810
	}
6 7u83 811
	case type_bitfield_tag: {
812
		INT_TYPE it = DEREF_itype(type_bitfield_defn(t));
813
		bs = save_itype(bs, it);
814
		break;
2 7u83 815
	}
6 7u83 816
	case type_compound_tag: {
817
		CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
818
		bs = save_ctype(bs, ct, def);
819
		break;
2 7u83 820
	}
6 7u83 821
	case type_enumerate_tag: {
822
		ENUM_TYPE et = DEREF_etype(type_enumerate_defn(t));
823
		bs = save_etype(bs, et, def);
824
		break;
2 7u83 825
	}
6 7u83 826
	case type_token_tag: {
827
		IDENTIFIER tok = DEREF_id(type_token_tok(t));
828
		LIST(TOKEN)args = DEREF_list(type_token_args(t));
829
		bs = save_use(bs, tok);
830
		bs = save_tok_list(bs, args, 1);
831
		break;
2 7u83 832
	}
6 7u83 833
	case type_templ_tag: {
834
		TOKEN tok = DEREF_tok(type_templ_sort(t));
835
		TYPE s = DEREF_type(type_templ_defn(t));
836
		int fix = DEREF_int(type_templ_fix(t));
837
		bs = save_tok(bs, tok, 0);
838
		bs = save_type(bs, s, def);
839
		ENC_BOOL(bs, fix);
840
		break;
2 7u83 841
	}
6 7u83 842
	case type_instance_tag: {
843
		IDENTIFIER tid = DEREF_id(type_name(t));
844
		IDENTIFIER id = DEREF_id(type_instance_id(t));
845
		DECL_SPEC acc = DEREF_dspec(type_instance_access(t));
846
		bs = save_use(bs, tid);
847
		bs = save_use(bs, id);
848
		save_dspec(bs, acc);
849
		break;
2 7u83 850
	}
6 7u83 851
	case type_dummy_tag: {
852
		int tok = DEREF_int(type_dummy_tok(t));
853
		ENC_INT(bs, tok);
854
		break;
2 7u83 855
	}
6 7u83 856
	case type_error_tag: {
857
		break;
2 7u83 858
	}
6 7u83 859
	}
860
	return (bs);
2 7u83 861
}
862
 
863
 
864
/*
865
    WRITE A LIST OF TYPES
866
 
867
    This routine saves a list of types to the bitstream bs.
868
*/
869
 
6 7u83 870
static BITSTREAM *
871
save_type_list(BITSTREAM *bs, LIST(TYPE)p)
2 7u83 872
{
6 7u83 873
	while (!IS_NULL_list(p)) {
874
		TYPE t = DEREF_type(HEAD_list(p));
875
		ENC_ON(bs);
876
		bs = save_type(bs, t, NULL_id);
877
		p = TAIL_list(p);
878
	}
879
	ENC_OFF(bs);
880
	return (bs);
2 7u83 881
}
882
 
883
 
884
/*
885
    WRITE A TOKEN
886
 
887
    This routine writes the token tok to the bitstream bs.  If def is
888
    true then the token value is included.
889
*/
890
 
6 7u83 891
static BITSTREAM *
892
save_tok(BITSTREAM *bs, TOKEN tok, int def)
2 7u83 893
{
6 7u83 894
	unsigned tag;
895
	if (IS_NULL_tok(tok)) {
896
		ENC_BITS(bs, BITS_tok, 0);
897
		return (bs);
2 7u83 898
	}
6 7u83 899
	tag = TAG_tok(tok);
900
	ENC_BITS(bs, BITS_tok, tag + 1);
901
	ASSERT(ORDER_tok == 10);
902
	switch (tag) {
903
	case tok_exp_tag: {
904
		TYPE t = DEREF_type(tok_exp_type(tok));
905
		int c = DEREF_int(tok_exp_constant(tok));
906
		bs = save_type(bs, t, NULL_id);
907
		ENC_BOOL(bs, c);
908
		if (def) {
909
			EXP e = DEREF_exp(tok_exp_value(tok));
910
			bs = save_exp(bs, e, t);
911
		}
912
		break;
2 7u83 913
	}
6 7u83 914
	case tok_stmt_tag: {
915
		if (def) {
916
			EXP e = DEREF_exp(tok_stmt_value(tok));
917
			bs = save_exp(bs, e, type_void);
918
		}
919
		break;
2 7u83 920
	}
6 7u83 921
	case tok_nat_tag:
922
	case tok_snat_tag: {
923
		if (def) {
924
			NAT m = DEREF_nat(tok_nat_etc_value(tok));
925
			bs = save_nat(bs, m);
926
		}
927
		break;
2 7u83 928
	}
6 7u83 929
	case tok_type_tag: {
930
		BASE_TYPE kind = DEREF_btype(tok_type_kind(tok));
931
		TYPE s = DEREF_type(tok_type_alt(tok));
932
		save_btype(bs, kind);
933
		bs = save_type(bs, s, NULL_id);
934
		if (def) {
935
			TYPE t = DEREF_type(tok_type_value(tok));
936
			bs = save_type(bs, t, NULL_id);
937
		}
938
		break;
2 7u83 939
	}
6 7u83 940
	case tok_func_tag: {
941
		TYPE t = DEREF_type(tok_func_type(tok));
942
		TOKEN proc = DEREF_tok(tok_func_proc(tok));
943
		bs = save_type(bs, t, NULL_id);
944
		bs = save_tok(bs, proc, 0);
945
		if (def) {
946
			IDENTIFIER id = DEREF_id(tok_func_defn(tok));
947
			bs = save_use(bs, id);
948
		}
949
		break;
2 7u83 950
	}
6 7u83 951
	case tok_member_tag: {
952
		TYPE s = DEREF_type(tok_member_of(tok));
953
		TYPE t = DEREF_type(tok_member_type(tok));
954
		bs = save_type(bs, s, NULL_id);
955
		bs = save_type(bs, t, NULL_id);
956
		if (def) {
957
			OFFSET off = DEREF_off(tok_member_value(tok));
958
			bs = save_off(bs, off);
959
		}
960
		break;
2 7u83 961
	}
6 7u83 962
	case tok_class_tag: {
963
		TYPE t = DEREF_type(tok_class_type(tok));
964
		TYPE s = DEREF_type(tok_class_alt(tok));
965
		bs = save_type(bs, t, NULL_id);
966
		bs = save_type(bs, s, NULL_id);
967
		if (def) {
968
			IDENTIFIER id = DEREF_id(tok_class_value(tok));
969
			bs = save_use(bs, id);
970
		}
971
		break;
2 7u83 972
	}
6 7u83 973
	case tok_proc_tag: {
974
		LIST(IDENTIFIER)bids;
975
		LIST(IDENTIFIER)pids;
976
		int key = DEREF_int(tok_proc_key(tok));
977
		TOKEN res = DEREF_tok(tok_proc_res(tok));
978
		bids = DEREF_list(tok_proc_bids(tok));
979
		pids = DEREF_list(tok_proc_pids(tok));
980
		bs = save_id_list(bs, bids, NULL_nspace);
981
		if (EQ_list(pids, bids)) {
982
			ENC_ON(bs);
983
		} else {
984
			ENC_OFF(bs);
985
			bs = save_use_list(bs, pids);
986
		}
987
		bs = save_tok(bs, res, def);
988
		if (key == lex_identifier) {
989
			ENC_OFF(bs);
990
		} else {
991
			ENC_ON(bs);
992
			save_lex(bs, key);
993
		}
994
		break;
2 7u83 995
	}
6 7u83 996
	case tok_templ_tag: {
997
		DECL_SPEC ex = DEREF_dspec(tok_templ_usage(tok));
998
		NAMESPACE pns = DEREF_nspace(tok_templ_pars(tok));
999
		save_dspec(bs, ex);
1000
		if (!IS_NULL_nspace(pns)) {
1001
			LIST(TOKEN)dargs;
1002
			LIST(IDENTIFIER)pids;
1003
			pids = DEREF_list(tok_templ_pids(tok));
1004
			dargs = DEREF_list(tok_templ_dargs(tok));
1005
			ENC_ON(bs);
1006
			bs = save_id_list(bs, pids, NULL_nspace);
1007
			bs = save_tok_list(bs, dargs, 1);
1008
		} else {
1009
			ENC_OFF(bs);
1010
		}
1011
		break;
1012
	}
1013
	}
1014
	return (bs);
2 7u83 1015
}
1016
 
1017
 
1018
/*
1019
    STANDARD BITSTREAM
1020
 
1021
    This bitstream is used to write the spec output file.
1022
*/
1023
 
6 7u83 1024
BITSTREAM *spec_unit = NULL;
1025
static int written_spec = 0;
1026
int output_spec = 0;
2 7u83 1027
 
1028
 
1029
/*
1030
    WRITE AN IDENTIFIER SPEC
1031
 
1032
    This routine writes the spec of the identifier id from the namespace ns
1033
    to the bitstream bs.
1034
*/
1035
 
6 7u83 1036
BITSTREAM *
1037
save_id(BITSTREAM *bs, IDENTIFIER id, NAMESPACE ns)
2 7u83 1038
{
6 7u83 1039
	if (bs && output_spec) {
1040
		bs = save_use(bs, id);
1041
		if (!IS_NULL_id(id)) {
1042
			/* Save identifier independent fields */
1043
			unsigned tag = TAG_id(id);
1044
			HASHID nm = DEREF_hashid(id_name(id));
1045
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
1046
			IDENTIFIER lid = DEREF_id(id_alias(id));
1047
			ENC_BITS(bs, BITS_id, tag + 1);
1048
			bs = save_hashid(bs, nm, ns);
1049
			save_dspec(bs, ds);
1050
			bs = save_loc(bs, id_loc(id));
1051
			if (EQ_id(id, lid)) {
1052
				ENC_OFF(bs);
1053
			} else {
1054
				ENC_ON(bs);
1055
				bs = save_use(bs, lid);
1056
			}
2 7u83 1057
 
6 7u83 1058
			/* Save identifier dependent fields */
1059
			ASSERT(ORDER_id == 29);
1060
			switch (tag) {
1061
			case id_dummy_tag: {
1062
				break;
1063
			}
1064
			case id_keyword_tag:
1065
			case id_iso_keyword_tag:
1066
			case id_reserved_tag: {
1067
				int key = (int)DEREF_ulong(id_no(id));
1068
				save_lex(bs, key);
1069
				break;
1070
			}
1071
			case id_builtin_tag: {
1072
				LIST(TYPE)p;
1073
				TYPE r = DEREF_type(id_builtin_ret(id));
1074
				p = DEREF_list(id_builtin_ptypes(id));
1075
				bs = save_type(bs, r, NULL_id);
1076
				bs = save_type_list(bs, p);
1077
				break;
1078
			}
1079
			case id_obj_macro_tag: {
1080
				PPTOKEN *def;
1081
				def = DEREF_pptok(id_obj_macro_defn(id));
1082
				bs = save_pptoks(bs, def);
1083
				break;
1084
			}
1085
			case id_func_macro_tag: {
1086
				PPTOKEN *def;
1087
				LIST(HASHID)pars;
1088
				def = DEREF_pptok(id_func_macro_defn(id));
1089
				pars = DEREF_list(id_func_macro_params(id));
1090
				bs = save_hashid_list(bs, pars, NULL_nspace);
1091
				bs = save_pptoks(bs, def);
1092
				break;
1093
			}
1094
			case id_predicate_tag: {
1095
				/* NOT YET IMPLEMENTED */
1096
				break;
1097
			}
1098
			case id_class_name_tag:
1099
			case id_enum_name_tag: {
1100
				TYPE t = DEREF_type(id_class_name_etc_defn(id));
1101
				if (!(ds & dspec_implicit)) {
1102
					bs = save_type(bs, t, id);
1103
				}
1104
				break;
1105
			}
1106
			case id_class_alias_tag:
1107
			case id_enum_alias_tag:
1108
			case id_type_alias_tag: {
1109
				TYPE t = DEREF_type(id_class_name_etc_defn(id));
1110
				bs = save_type(bs, t, NULL_id);
1111
				break;
1112
			}
1113
			case id_nspace_name_tag: {
1114
				break;
1115
			}
1116
			case id_nspace_alias_tag: {
1117
				NAMESPACE pns;
1118
				IDENTIFIER pid;
1119
				pns = DEREF_nspace(id_nspace_alias_defn(id));
1120
				pid = DEREF_id(nspace_name(pns));
1121
				bs = save_use(bs, pid);
1122
				break;
1123
			}
1124
			case id_variable_tag:
1125
			case id_parameter_tag:
1126
			case id_stat_member_tag: {
1127
				TYPE t = DEREF_type(id_variable_etc_type(id));
1128
				bs = save_type(bs, t, NULL_id);
1129
				/* NOT YET IMPLEMENTED */
1130
				break;
1131
			}
1132
			case id_function_tag:
1133
			case id_mem_func_tag:
1134
			case id_stat_mem_func_tag: {
1135
				TYPE t = DEREF_type(id_function_etc_type(id));
1136
				TYPE form = DEREF_type(id_function_etc_form(id));
1137
				bs = save_type(bs, t, NULL_id);
1138
				if (!IS_NULL_type(form)) {
1139
					ENC_ON(bs);
1140
					bs = save_type(bs, form, NULL_id);
1141
				} else {
1142
					ENC_OFF(bs);
1143
				}
1144
				/* NOT YET IMPLEMENTED */
1145
				break;
1146
			}
1147
			case id_member_tag: {
1148
				TYPE t = DEREF_type(id_member_type(id));
1149
				bs = save_type(bs, t, NULL_id);
1150
				/* NOT YET IMPLEMENTED */
1151
				break;
1152
			}
1153
			case id_enumerator_tag: {
1154
				EXP e;
1155
				TYPE t;
1156
				t = DEREF_type(id_enumerator_etype(id));
1157
				e = DEREF_exp(id_enumerator_value(id));
1158
				bs = save_type(bs, t, NULL_id);
1159
				bs = save_exp(bs, e, t);
1160
				break;
1161
			}
1162
			case id_label_tag:
1163
			case id_weak_param_tag: {
1164
				/* NOT YET IMPLEMENTED */
1165
				break;
1166
			}
1167
			case id_token_tag: {
1168
				TOKEN tok = DEREF_tok(id_token_sort(id));
1169
				bs = save_tok(bs, tok, 0);
1170
				break;
1171
			}
1172
			case id_ambig_tag: {
1173
				LIST(IDENTIFIER)ids;
1174
				int over = DEREF_int(id_ambig_over(id));
1175
				ids = DEREF_list(id_ambig_ids(id));
1176
				bs = save_use_list(bs, ids);
1177
				ENC_BOOL(bs, over);
1178
				break;
1179
			}
1180
			case id_undef_tag: {
1181
				TYPE form = DEREF_type(id_undef_form(id));
1182
				if (!IS_NULL_type(form)) {
1183
					ENC_ON(bs);
1184
					bs = save_type(bs, form, NULL_id);
1185
				} else {
1186
					ENC_OFF(bs);
1187
				}
1188
				break;
1189
			}
1190
			case id_pending_tag: {
1191
				/* This shouldn't happen */
1192
				break;
1193
			}
1194
			}
2 7u83 1195
		}
1196
	}
6 7u83 1197
	return (bs);
2 7u83 1198
}
1199
 
1200
 
1201
/*
1202
    WRITE THE END OF A NAMESPACE
1203
 
1204
    This routine marks the end of the namespace ns by writing the null
1205
    identifier to the bitstream bs.
1206
*/
1207
 
6 7u83 1208
BITSTREAM *
1209
save_end(BITSTREAM *bs, NAMESPACE ns)
2 7u83 1210
{
6 7u83 1211
	bs = save_id(bs, NULL_id, ns);
1212
	return (bs);
2 7u83 1213
}
1214
 
1215
 
1216
/*
1217
    WRITE A SPEC FILE
1218
 
1219
    This routine begins the writing of a spec file to the second output
1220
    file.
1221
*/
1222
 
6 7u83 1223
void
1224
begin_spec(void)
2 7u83 1225
{
6 7u83 1226
	string nm = output_name[OUTPUT_SPEC];
1227
	if (nm && !written_spec) {
1228
		/* Open output file */
1229
		FILE *f;
1230
		BITSTREAM *bs;
1231
		written_spec = 1;
1232
		if (!open_output(OUTPUT_SPEC, binary_mode)) {
1233
			fail(ERR_fail_spec(nm));
1234
			spec_unit = NULL;
1235
			term_error(0);
1236
			return;
1237
		}
1238
		f = output_file[OUTPUT_SPEC];
1239
		bs = start_bitstream(f, NULL_gen_ptr);
1240
 
1241
		/* Write file identifier */
1242
		ENC_BITS(bs, BYTE_SIZE, ascii_T);
1243
		ENC_BITS(bs, BYTE_SIZE, ascii_D);
1244
		ENC_BITS(bs, BYTE_SIZE, ascii_F);
1245
		ENC_BITS(bs, BYTE_SIZE, ascii_K);
1246
		ENC_INT(bs, SPEC_major);
1247
		ENC_INT(bs, SPEC_minor);
1248
		ENC_INT(bs, LANGUAGE_CPP);
1249
		ENC_ALIGN(bs);
1250
		spec_unit = bs;
2 7u83 1251
	}
6 7u83 1252
	return;
2 7u83 1253
}
1254
 
1255
 
1256
/*
1257
    END A SPEC FILE
1258
 
1259
    This routine completes the output of a spec file.
1260
*/
1261
 
6 7u83 1262
void
1263
end_spec(void)
2 7u83 1264
{
6 7u83 1265
	BITSTREAM *bs = spec_unit;
1266
	if (bs) {
1267
		if (!output_spec)ENC_INT(bs, 0);
1268
		end_bitstream(bs, 1);
1269
		close_output(OUTPUT_SPEC);
1270
		spec_unit = NULL;
1271
	}
1272
	return;
2 7u83 1273
}