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
/*
7 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
7 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:-
7 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
7 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;
7 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;
7 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 <limits.h>
63
#include "system.h"
64
#include "version.h"
65
#include "c_types.h"
66
#include "err_ext.h"
67
#include "ctype_ops.h"
68
#include "etype_ops.h"
69
#include "exp_ops.h"
70
#include "ftype_ops.h"
71
#include "graph_ops.h"
72
#include "hashid_ops.h"
73
#include "id_ops.h"
74
#include "itype_ops.h"
75
#include "nat_ops.h"
76
#include "nspace_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 "buffer.h"
83
#include "char.h"
84
#include "constant.h"
85
#include "convert.h"
86
#include "dump.h"
87
#include "exception.h"
88
#include "file.h"
89
#include "function.h"
90
#include "lex.h"
91
#include "literal.h"
92
#include "macro.h"
93
#include "mangle.h"
94
#include "print.h"
95
#include "statement.h"
96
#include "token.h"
97
#include "ustring.h"
98
#include "xalloc.h"
99
 
100
 
101
/*
102
    DUMP FILE OPTIONS
103
 
104
    These variables give the various dump file options.
105
*/
106
 
7 7u83 107
int do_dump = 0;
108
int do_error = 0;
109
int do_header = 0;
110
int do_keyword = 0;
111
int do_local = 0;
112
int do_macro = 0;
113
int do_scope = 0;
114
int do_string = 0;
115
int do_usage = 0;
2 7u83 116
 
117
 
118
/*
119
    DUMP FILE VARIABLES
120
 
121
    These variables give the dump file and the associated dump buffer.
122
*/
123
 
7 7u83 124
static FILE *dump_file = NULL;
125
static BUFFER dump_buff_rep = NULL_buff;
126
static BUFFER *dump_buff = &dump_buff_rep;
2 7u83 127
 
128
 
129
/*
130
    DUMP BUFFER TO FILE
131
 
132
    This routine adds the contents of the dump buffer to the dump file.
133
*/
134
 
7 7u83 135
static void
136
dump_string(void)
2 7u83 137
{
7 7u83 138
	FILE *f = dump_file;
139
	BUFFER *bf = dump_buff;
140
	string s = bf->start;
141
	size_t n = (size_t)(bf->posn - s);
142
	fprintf_v(f, "&%lu<",(unsigned long)n);
143
	if (n) {
144
		IGNORE fwrite((gen_ptr)s, sizeof(character), n, f);
145
		bf->posn = s;
146
	}
147
	fputc_v('>', f);
148
	return;
2 7u83 149
}
150
 
151
 
152
/*
153
    FORWARD DECLARATIONS
154
 
155
    The dump routines defined in this module are defined recursively
156
    so a couple of forward declarations are required.
157
*/
158
 
7 7u83 159
static void dump_id(IDENTIFIER);
160
static void dump_type(TYPE);
161
static void dump_tok_appl(IDENTIFIER, LIST(TOKEN));
162
static void dump_nat(NAT, int);
2 7u83 163
 
164
 
165
/*
166
    DUMP FLAGS
167
 
168
    The flag dump_implicit can be set to true to indicate that the
169
    following declaration or definition is actually implicit.  The flag
170
    dump_anon_class can be set to inhibit type definitions which name
171
    anonymous classes being output twice.
172
*/
173
 
7 7u83 174
int dump_implicit = 0;
175
int dump_template = 0;
176
int dump_anon_class = 0;
2 7u83 177
 
178
 
179
/*
180
    FIND AN IDENTIFIER KEY
181
 
182
    This routine finds the key corresponding to the identifier id.
183
    This is a sequence of characters giving the type of identifier.
184
*/
185
 
7 7u83 186
static CONST char *
187
dump_key(IDENTIFIER id, int def)
2 7u83 188
{
7 7u83 189
	CONST char *key = NULL;
190
	if (do_dump && !IS_NULL_id(id)) {
191
		switch (TAG_id(id)) {
192
		case id_keyword_tag:
193
		case id_iso_keyword_tag: {
194
			/* Keywords */
195
			key = "K";
196
			break;
2 7u83 197
		}
7 7u83 198
		case id_obj_macro_tag: {
199
			/* Object-like macros */
200
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
201
			if (ds & dspec_builtin) {
202
				key = "MB";
203
			} else {
204
				key = "MO";
205
			}
206
			break;
2 7u83 207
		}
7 7u83 208
		case id_func_macro_tag: {
209
			/* Function-like macros */
210
			key = "MF";
211
			break;
2 7u83 212
		}
7 7u83 213
		case id_builtin_tag: {
214
			/* Built-in functions */
215
			key = "FB";
216
			break;
2 7u83 217
		}
7 7u83 218
		case id_class_name_tag: {
219
			/* Classes, structures and unions */
220
			CLASS_TYPE ct;
221
			CLASS_INFO ci;
222
			TYPE t = DEREF_type(id_class_name_defn(id));
223
			while (IS_type_templ(t)) {
224
				t = DEREF_type(type_templ_defn(t));
225
			}
226
			ct = DEREF_ctype(type_compound_defn(t));
227
			ci = DEREF_cinfo(ctype_info(ct));
228
			if (ci & cinfo_union) {
229
				key = "TU";
230
			} else if (ci & cinfo_struct) {
231
				key = "TS";
232
			} else {
233
				key = "TC";
234
			}
235
			break;
2 7u83 236
		}
7 7u83 237
		case id_enum_name_tag: {
238
			/* Enumerations */
239
			key = "TE";
240
			break;
2 7u83 241
		}
7 7u83 242
		case id_class_alias_tag:
243
		case id_enum_alias_tag:
244
		case id_type_alias_tag: {
245
			/* Type aliases */
246
			if (dump_anon_class) {
247
				dump_anon_class = 0;
248
			} else {
249
				key = "TA";
250
			}
251
			break;
2 7u83 252
		}
7 7u83 253
		case id_nspace_name_tag: {
254
			/* Namespaces */
255
			key = "NN";
256
			break;
2 7u83 257
		}
7 7u83 258
		case id_nspace_alias_tag: {
259
			/* Namespace aliases */
260
			key = "NA";
261
			break;
262
		}
263
		case id_variable_tag: {
264
			/* Variables */
265
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
266
			if (ds & dspec_auto) {
267
				if (do_local) {
268
					key = "VA";
269
				}
270
			} else if (ds & dspec_static) {
271
				key = "VS";
272
			} else {
273
				key = "VE";
274
			}
275
			break;
276
		}
277
		case id_parameter_tag:
278
		case id_weak_param_tag: {
279
			/* Function parameters */
280
			if (def && do_local) {
281
				key = "VP";
282
			}
283
			break;
284
		}
285
		case id_function_tag: {
286
			/* Functions */
287
			static char f[10];
288
			char *fp = f;
289
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
290
			*(fp++) = 'F';
291
			if (ds & dspec_static) {
292
				*(fp++) = 'S';
293
			} else {
294
				*(fp++) = 'E';
295
			}
296
			if (ds & dspec_c) {
297
				*(fp++) = 'C';
298
			}
299
			if (ds & dspec_inline) {
300
				*(fp++) = 'I';
301
			}
302
			*fp = 0;
303
			key = f;
304
			break;
305
		}
306
		case id_mem_func_tag: {
307
			/* Member functions */
308
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
309
			if (!(ds & dspec_trivial)) {
310
				if (ds & dspec_virtual) {
311
					key = "CV";
312
				} else {
313
					key = "CF";
314
				}
315
			}
316
			break;
317
		}
318
		case id_stat_mem_func_tag: {
319
			/* Static member functions */
320
			key = "CS";
321
			break;
322
		}
323
		case id_stat_member_tag: {
324
			/* Static data members */
325
			key = "CD";
326
			break;
327
		}
328
		case id_member_tag: {
329
			/* Data members */
330
			key = "CM";
331
			break;
332
		}
333
		case id_enumerator_tag: {
334
			/* Enumerators */
335
			key = "E";
336
			break;
337
		}
338
		case id_label_tag: {
339
			/* Labels */
340
			key = "L";
341
			break;
342
		}
343
		case id_token_tag: {
344
			/* Tokens */
345
			DECL_SPEC ds = DEREF_dspec(id_storage(id));
346
			if (ds & dspec_auto) {
347
				if (ds & dspec_template) {
348
					key = "XT";
349
				} else {
350
					key = "XP";
351
				}
352
			} else {
353
				TOKEN tok = DEREF_tok(id_token_sort(id));
354
				if (!IS_NULL_tok(tok) && IS_tok_proc(tok)) {
355
					key = "XF";
356
				} else {
357
					key = "XO";
358
				}
359
			}
360
			break;
361
		}
362
		}
2 7u83 363
	}
7 7u83 364
	return (key);
2 7u83 365
}
366
 
367
 
368
/*
369
    DUMP A LEXICAL TOKEN
370
 
371
    This routine adds the lexical token t to the dump file.
372
*/
373
 
7 7u83 374
static void
375
dump_lex(int t)
2 7u83 376
{
7 7u83 377
	FILE *f = dump_file;
378
	string s = token_name(t);
379
	if (s) {
380
		unsigned n = (unsigned)ustrlen(s);
381
		if (n > 100 || ustrchr(s, '>')) {
382
			fprintf_v(f, "&%u", n);
383
		}
384
		fprintf_v(f, "<%s>", strlit(s));
385
	} else {
386
		fputs_v("<>", f);
387
	}
388
	return;
2 7u83 389
}
390
 
391
 
392
/*
393
    DUMP A HASH TABLE ENTRY
394
 
395
    This routine adds the hash table entry nm to the dump file.
396
*/
397
 
7 7u83 398
static void
399
dump_hashid(HASHID nm)
2 7u83 400
{
7 7u83 401
	FILE *f = dump_file;
402
	if (IS_NULL_hashid(nm)) {
403
		fputs_v("<>", f);
404
		return;
2 7u83 405
	}
7 7u83 406
	switch (TAG_hashid(nm)) {
407
	case hashid_name_tag:
408
	case hashid_ename_tag: {
409
		/* Simple identifiers */
410
		string s = DEREF_string(hashid_name_etc_text(nm));
411
		unsigned n = (unsigned)ustrlen(s);
412
		if (n > 100 || ustrchr(s, '>')) {
413
			fprintf_v(f, "&%u", n);
414
		}
415
		fprintf_v(f, "<%s>", strlit(s));
416
		break;
2 7u83 417
	}
7 7u83 418
	case hashid_constr_tag: {
419
		/* Constructor names */
420
		TYPE t = DEREF_type(hashid_constr_type(nm));
421
		fputc_v('C', f);
422
		dump_type(t);
423
		break;
2 7u83 424
	}
7 7u83 425
	case hashid_destr_tag: {
426
		/* Destructor names */
427
		TYPE t = DEREF_type(hashid_destr_type(nm));
428
		fputc_v('D', f);
429
		dump_type(t);
430
		break;
2 7u83 431
	}
7 7u83 432
	case hashid_conv_tag: {
433
		/* Conversion function names */
434
		TYPE t = DEREF_type(hashid_conv_type(nm));
435
		fputc_v('T', f);
436
		dump_type(t);
437
		break;
2 7u83 438
	}
7 7u83 439
	case hashid_op_tag: {
440
		/* Overloaded operator names */
441
		int t = DEREF_int(hashid_op_lex(nm));
442
		fputc_v('O', f);
443
		dump_lex(t);
444
		break;
445
	}
2 7u83 446
	default : {
7 7u83 447
		/* Other names */
448
		fputs_v("<>", f);
449
		break;
2 7u83 450
	}
7 7u83 451
	}
452
	return;
2 7u83 453
}
454
 
455
 
456
/*
457
    DUMP A NAMESPACE
458
 
459
    This routine adds the namespace ns to the dump file.  The current
460
    declaration block is taken into account in blk is true.
461
*/
462
 
7 7u83 463
static void
464
dump_nspace(NAMESPACE ns, int blk)
2 7u83 465
{
7 7u83 466
	if (!IS_NULL_nspace(ns)) {
467
		if (blk) {
468
			LIST(IDENTIFIER)s;
469
			s = LIST_stack(DEREF_stack(nspace_set(ns)));
470
			if (!IS_NULL_list(s)) {
471
				/* Allow for declaration blocks */
472
				IDENTIFIER id = DEREF_id(HEAD_list(s));
473
				dump_id(id);
474
				return;
475
			}
2 7u83 476
		}
7 7u83 477
		if (!IS_nspace_global(ns)) {
478
			ulong n = DEREF_ulong(nspace_dump(ns));
479
			if (n == LINK_NONE) {
480
				IDENTIFIER id = DEREF_id(nspace_name(ns));
481
				if (!IS_NULL_id(id)) {
482
					/* Use namespace name */
483
					dump_id(id);
484
					n = DEREF_ulong(id_dump(id));
485
					COPY_ulong(nspace_dump(ns), n);
486
					return;
487
				}
488
			} else {
489
				/* Already assigned value */
490
				fprintf_v(dump_file, "%lu", n);
491
				return;
492
			}
493
		}
2 7u83 494
	}
7 7u83 495
	fputs_v("*", dump_file);
496
	return;
2 7u83 497
}
498
 
499
 
500
/*
501
    DUMP AN ACCESS SPECIFIER
502
 
503
    This routine adds the access specifier acc to the dump file.
504
*/
505
 
7 7u83 506
static void
507
dump_access(DECL_SPEC acc)
2 7u83 508
{
7 7u83 509
	DECL_SPEC ds = (acc & dspec_access);
510
	if (ds == dspec_private) {
511
		fputc_v('P', dump_file);
512
	} else if (ds == dspec_protected) {
513
		fputc_v('B', dump_file);
514
	}
515
	return;
2 7u83 516
}
517
 
518
 
519
/*
520
    IDENTIFIER DUMP NUMBER
521
 
522
    Each identifier dumped is assigned a number in a sequence given
523
    by this variable.  The zero value stands for the null identifier.
524
*/
525
 
7 7u83 526
ulong dump_id_next = 1;
2 7u83 527
 
528
 
529
/*
530
    DUMP AN IDENTIFIER
531
 
532
    This routine adds the identifier id to the dump file.
533
*/
534
 
7 7u83 535
static void
536
dump_id(IDENTIFIER id)
2 7u83 537
{
7 7u83 538
	if (IS_NULL_id(id)) {
539
		fputs_v("0", dump_file);
2 7u83 540
	} else {
7 7u83 541
		ulong n = DEREF_ulong(id_dump(id));
542
		if (n == LINK_NONE || (n & LINK_EXTERN)) {
543
			FILE *f = dump_file;
544
			HASHID nm = DEREF_hashid(id_name(id));
545
			NAMESPACE ns = DEREF_nspace(id_parent(id));
546
			DECL_SPEC acc = DEREF_dspec(id_storage(id));
547
			if (n == LINK_NONE) {
548
				/* Allocate new number */
549
				n = dump_id_next++;
550
			} else {
551
				/* Use number from spec file */
552
				n &= ~LINK_EXTERN;
553
			}
554
			COPY_ulong(id_dump(id), n);
555
			fprintf_v(f, "%lu = ", n);
556
			dump_hashid(nm);
557
			fputc_v('\t', f);
558
			dump_access(acc);
559
			dump_nspace(ns, 1);
560
		} else {
561
			fprintf_v(dump_file, "%lu", n);
562
		}
2 7u83 563
	}
7 7u83 564
	return;
2 7u83 565
}
566
 
567
 
568
/*
569
    LAST DUMP LOCATION
570
 
571
    When dumping locations the previous location is stored in these
572
    variables and only items which have changed are output.
573
*/
574
 
7 7u83 575
static unsigned long last_ln = 0;
576
static unsigned long last_cn = 0;
577
static string last_file = NULL;
578
static string last_input = NULL;
579
static PTR(POSITION)last_posn = NULL_ptr(POSITION);
2 7u83 580
 
581
 
582
/*
583
    DUMP A LOCATION
584
 
585
    This routine adds the location loc to the dump file.
586
*/
587
 
7 7u83 588
static void
589
dump_loc(LOCATION *loc)
2 7u83 590
{
7 7u83 591
	FILE *f = dump_file;
592
	unsigned long ln = loc->line;
593
	unsigned long cn = loc->column;
594
	PTR(POSITION)posn = loc->posn;
595
	if (EQ_ptr(posn, last_posn)) {
596
		/* Same file information as previously */
597
		if (ln == last_ln) {
598
			if (cn == last_cn) {
599
				fputs_v("*", f);
600
			} else {
601
				fprintf_v(f, "%lu\t*", cn);
602
				last_cn = cn;
603
			}
604
		} else {
605
			fprintf_v(f, "%lu\t%lu\t*", cn, ln );
606
			last_cn = cn;
607
			last_ln = ln;
608
		}
2 7u83 609
	} else {
7 7u83 610
		/* Different file information */
611
		string file = DEREF_string(posn_file(posn));
612
		string input = DEREF_string(posn_input(posn));
613
		unsigned long off = DEREF_ulong(posn_offset(posn));
614
		fprintf_v(f, "%lu\t%lu\t%lu\t", cn, ln, ln - off );
615
		if (ustreq(file, last_file) && ustreq(input, last_input)) {
616
			/* File names unchanged */
617
			fputc_v('*', f);
618
		} else {
619
			unsigned n = (unsigned)ustrlen(file);
620
			fprintf_v(f, "&%u<%s>\t", n, strlit(file));
621
			if (ustreq(file, input)) {
622
				/* Current and actual files match */
623
				fputc_v('*', f);
624
			} else {
625
				/* Different current and actual files */
626
				n = (unsigned)ustrlen(input);
627
				fprintf_v(f, "&%u<%s>", n, strlit(input));
628
			}
629
			last_input = input;
630
			last_file = file;
631
		}
632
		last_posn = posn;
633
		last_cn = cn;
634
		last_ln = ln;
2 7u83 635
	}
7 7u83 636
	return;
2 7u83 637
}
638
 
639
 
640
/*
641
    DUMP AN EXPRESSION
642
 
643
    This routine adds the expression e to the dump file.
644
*/
645
 
7 7u83 646
static void
647
dump_exp(EXP e)
2 7u83 648
{
7 7u83 649
	if (!IS_NULL_exp(e)) {
650
		switch (TAG_exp(e)) {
651
		case exp_int_lit_tag: {
652
			/* Integer literals */
653
			NAT n = DEREF_nat(exp_int_lit_nat(e));
654
			dump_nat(n, 0);
655
			return;
656
		}
657
		case exp_token_tag: {
658
			/* Tokenised expressions */
659
			IDENTIFIER id = DEREF_id(exp_token_tok(e));
660
			LIST(TOKEN)args = DEREF_list(exp_token_args(e));
661
			dump_tok_appl(id, args);
662
			return;
663
		}
664
		}
2 7u83 665
	}
7 7u83 666
	IGNORE print_exp(e, 0, dump_buff, 0);
667
	dump_string();
668
	return;
2 7u83 669
}
670
 
671
 
672
/*
673
    DUMP AN OFFSET
674
 
675
    This routine adds the offset off to the dump file.
676
*/
677
 
7 7u83 678
static void
679
dump_off(OFFSET off)
2 7u83 680
{
7 7u83 681
	IGNORE print_offset(off, dump_buff, 0);
682
	dump_string();
683
	return;
2 7u83 684
}
685
 
686
 
687
/*
688
    DUMP AN INTEGER CONSTANT
689
 
690
    This routine adds the integer constant n to the dump file.
691
*/
692
 
7 7u83 693
static void
694
dump_nat(NAT n, int neg)
2 7u83 695
{
7 7u83 696
	if (!IS_NULL_nat(n)) {
697
		FILE *f = dump_file;
698
		ASSERT(ORDER_nat == 5);
699
		switch (TAG_nat(n)) {
700
		case nat_small_tag: {
701
			/* Small literals */
702
			unsigned v = DEREF_unsigned(nat_small_value(n));
703
			int s = (neg ? '-' : '+');
704
			fputc_v(s, f);
705
			fprintf_v(f, "%u", v);
706
			break;
707
		}
708
		case nat_large_tag: {
709
			/* Large literals */
710
			unsigned long v = get_nat_value(n);
711
			int s = (neg ? '-' : '+');
712
			fputc_v(s, f);
713
			fprintf_v(f, "%lu", v);
714
			break;
715
		}
716
		case nat_neg_tag: {
717
			/* Negated literals */
718
			NAT m = DEREF_nat(nat_neg_arg(n));
719
			dump_nat(m, !neg);
720
			break;
721
		}
722
		case nat_calc_tag: {
723
			/* Calculated literals */
724
			EXP e = DEREF_exp(nat_calc_value(n));
725
			dump_exp(e);
726
			break;
727
		}
728
		case nat_token_tag: {
729
			/* Tokenised literals */
730
			IDENTIFIER id = DEREF_id(nat_token_tok(n));
731
			LIST(TOKEN)args = DEREF_list(nat_token_args(n));
732
			dump_tok_appl(id, args);
733
			break;
734
		}
735
		}
2 7u83 736
	}
7 7u83 737
	return;
2 7u83 738
}
739
 
740
 
741
/*
742
    DUMP A LIST OF TOKEN PARAMETERS
743
 
744
    This routine adds the list of token parameters pids to the dump file.
745
*/
746
 
7 7u83 747
static void
748
dump_params(LIST(IDENTIFIER)pids)
2 7u83 749
{
7 7u83 750
	int started = 0;
751
	FILE *f = dump_file;
752
	while (!IS_NULL_list(pids)) {
753
		IDENTIFIER pid = DEREF_id(HEAD_list(pids));
754
		if (!IS_NULL_id(pid)) {
755
			if (IS_id_token(pid)) {
756
				pid = DEREF_id(id_token_alt(pid));
757
			}
758
			if (started) {
759
				fputc_v(MANGLE_comma, f);
760
			}
761
			dump_id(pid);
762
			started = 1;
763
		}
764
		pids = TAIL_list(pids);
2 7u83 765
	}
7 7u83 766
	return;
2 7u83 767
}
768
 
769
 
770
/*
771
    DUMP A TOKEN SORT
772
 
773
    This routine adds the token sort tok to the dump file.
774
*/
775
 
7 7u83 776
static void
777
dump_sort(TOKEN tok)
2 7u83 778
{
7 7u83 779
	FILE *f = dump_file;
780
	ASSERT(ORDER_tok == 10);
781
	switch (TAG_tok(tok)) {
782
	case tok_exp_tag: {
783
		/* Expression tokens */
784
		TYPE t = DEREF_type(tok_exp_type(tok));
785
		int c = DEREF_int(tok_exp_constant(tok));
786
		if (c) {
787
			fputs_v("ZEC", f);
2 7u83 788
		} else {
7 7u83 789
			CV_SPEC cv = DEREF_cv(type_qual(t));
790
			if (cv & cv_lvalue) {
791
				fputs_v("ZEL", f);
792
			} else {
793
				fputs_v("ZER", f);
794
			}
2 7u83 795
		}
7 7u83 796
		dump_type(t);
797
		break;
2 7u83 798
	}
7 7u83 799
	case tok_stmt_tag: {
800
		/* Statement tokens */
801
		fputs_v("ZS", f);
802
		break;
2 7u83 803
	}
7 7u83 804
	case tok_nat_tag: {
805
		/* Integer constant tokens */
806
		fputs_v("ZN", f);
807
		break;
2 7u83 808
	}
7 7u83 809
	case tok_snat_tag: {
810
		/* Integer constant tokens */
811
		fputs_v("ZI", f);
812
		break;
2 7u83 813
	}
7 7u83 814
	case tok_type_tag: {
815
		/* Type tokens */
816
		int c;
817
		BASE_TYPE bt = DEREF_btype(tok_type_kind(tok));
818
		if (bt & btype_float) {
819
			if (bt & btype_int) {
820
				c = 'A';
821
			} else {
822
				c = 'F';
823
			}
824
		} else if (bt & btype_int) {
825
			c = 'I';
826
		} else if (bt & btype_class) {
827
			c = 'S';
828
		} else if (bt & btype_struct) {
829
			c = 'S';
830
		} else if (bt & btype_union) {
831
			c = 'U';
2 7u83 832
		} else {
7 7u83 833
			c = 'O';
2 7u83 834
		}
7 7u83 835
		fputs_v("ZT", f);
836
		fputc_v(c, f);
837
		break;
2 7u83 838
	}
7 7u83 839
	case tok_func_tag: {
840
		/* Function tokens */
841
		TYPE t = DEREF_type(tok_func_type(tok));
842
		fputs_v("ZF", f);
843
		dump_type(t);
844
		break;
2 7u83 845
	}
7 7u83 846
	case tok_member_tag: {
847
		/* Member tokens */
848
		TYPE t = DEREF_type(tok_member_type(tok));
849
		TYPE s = DEREF_type(tok_member_of(tok));
850
		fputs_v("ZM", f);
851
		dump_type(t);
852
		fputc_v(MANGLE_colon, f);
853
		dump_type(s);
854
		break;
2 7u83 855
	}
7 7u83 856
	case tok_class_tag: {
857
		/* Template parameter tokens */
858
		TYPE t = DEREF_type(tok_class_type(tok));
859
		TOKEN sort = DEREF_tok(type_templ_sort(t));
860
		fputs_v("ZT", f);
861
		dump_sort(sort);
862
		break;
2 7u83 863
	}
7 7u83 864
	case tok_proc_tag: {
865
		/* Procedure tokens */
866
		TOKEN res = DEREF_tok(tok_proc_res(tok));
867
		LIST(IDENTIFIER)bids = DEREF_list(tok_proc_bids(tok));
868
		LIST(IDENTIFIER)pids = DEREF_list(tok_proc_pids(tok));
869
		if (EQ_list(bids, pids)) {
870
			fputs_v("ZPS", f);
871
			dump_params(bids);
872
		} else {
873
			fputs_v("ZPG", f);
874
			dump_params(bids);
875
			fputs_v(";", f);
876
			dump_params(pids);
877
		}
878
		fputc_v(MANGLE_colon, f);
879
		dump_sort(res);
880
		break;
2 7u83 881
	}
7 7u83 882
	case tok_templ_tag: {
883
		/* Template tokens */
884
		LIST(IDENTIFIER)pids = DEREF_list(tok_templ_pids(tok));
885
		fputc_v(MANGLE_template, f);
886
		dump_params(pids);
887
		fputc_v(MANGLE_colon, f);
888
		break;
2 7u83 889
	}
7 7u83 890
	}
891
	return;
2 7u83 892
}
893
 
894
 
895
/*
896
    DUMP AN INTEGRAL TYPE
897
 
898
    This routine adds the integral type it to the dump file.  Note that
899
    for this and the other type dumping routines the representation
900
    chosen bears a marked resemblance to the C++ name mangling scheme,
901
    and uses the same MANGLE_* macros.  This is primarily to avoid having
902
    to think up two different forms.
903
*/
904
 
7 7u83 905
static void
906
dump_itype(INT_TYPE it)
2 7u83 907
{
7 7u83 908
	FILE *f = dump_file;
909
	ASSERT(ORDER_itype == 6);
910
	switch (TAG_itype(it)) {
911
	case itype_basic_tag: {
912
		/* Basic integral types */
913
		BUILTIN_TYPE n = DEREF_ntype(itype_basic_no(it));
914
		fputs_v(mangle_ntype[n], f);
915
		break;
2 7u83 916
	}
7 7u83 917
	case itype_bitfield_tag: {
918
		/* Bitfield types */
919
		NAT n = DEREF_nat(itype_bitfield_size(it));
920
		TYPE s = DEREF_type(itype_bitfield_sub(it));
921
		fputc_v(MANGLE_bitfield, f);
922
		dump_nat(n, 0);
923
		fputc_v(MANGLE_colon, f);
924
		dump_type(s);
925
		break;
2 7u83 926
	}
7 7u83 927
	case itype_promote_tag: {
928
		/* Promotion types */
929
		INT_TYPE is = DEREF_itype(itype_promote_arg(it));
930
		fputc_v(MANGLE_promote, f);
931
		dump_itype(is);
932
		break;
2 7u83 933
	}
7 7u83 934
	case itype_arith_tag: {
935
		/* Arithmetic types */
936
		INT_TYPE is = DEREF_itype(itype_arith_arg1(it));
937
		INT_TYPE ir = DEREF_itype(itype_arith_arg2(it));
938
		fputc_v(MANGLE_arith, f);
939
		dump_itype(is);
940
		fputc_v(MANGLE_colon, f);
941
		dump_itype(ir);
942
		break;
2 7u83 943
	}
7 7u83 944
	case itype_literal_tag: {
945
		/* Literal types */
946
		NAT n = DEREF_nat(itype_literal_nat(it));
947
		string s = mangle_literal(it);
948
		fputs_v(strlit(s), f);
949
		dump_nat(n, 0);
950
		break;
2 7u83 951
	}
7 7u83 952
	case itype_token_tag: {
953
		/* Tokenised types */
954
		BUILTIN_TYPE n = DEREF_ntype(itype_unprom(it));
955
		if (n == ntype_none || n == ntype_ellipsis) {
956
			IDENTIFIER id;
957
			LIST(TOKEN)args;
958
			id = DEREF_id(itype_token_tok(it));
959
			args = DEREF_list(itype_token_args(it));
960
			dump_tok_appl(id, args);
961
		} else {
962
			fputc_v(MANGLE_promote, f);
963
			fputs_v(mangle_ntype[n], f);
964
		}
965
		break;
2 7u83 966
	}
7 7u83 967
	}
968
	return;
2 7u83 969
}
970
 
971
 
972
/*
973
    DUMP A FLOATING POINT TYPE
974
 
975
    This routine adds the floating point type ft to the dump file.
976
*/
977
 
7 7u83 978
static void
979
dump_ftype(FLOAT_TYPE ft)
2 7u83 980
{
7 7u83 981
	FILE *f = dump_file;
982
	ASSERT(ORDER_ftype == 4);
983
	switch (TAG_ftype(ft)) {
984
	case ftype_basic_tag: {
985
		/* Basic floating types */
986
		BUILTIN_TYPE n = DEREF_ntype(ftype_basic_no(ft));
987
		fputs_v(mangle_ntype[n], f);
988
		break;
2 7u83 989
	}
7 7u83 990
	case ftype_arg_promote_tag: {
991
		/* Promotion types */
992
		FLOAT_TYPE fs = DEREF_ftype(ftype_arg_promote_arg(ft));
993
		fputc_v(MANGLE_promote, f);
994
		dump_ftype(fs);
995
		break;
2 7u83 996
	}
7 7u83 997
	case ftype_arith_tag: {
998
		/* Arithmetic types */
999
		FLOAT_TYPE fs = DEREF_ftype(ftype_arith_arg1(ft));
1000
		FLOAT_TYPE fr = DEREF_ftype(ftype_arith_arg2(ft));
1001
		fputc_v(MANGLE_arith, f);
1002
		dump_ftype(fs);
1003
		fputc_v(MANGLE_colon, f);
1004
		dump_ftype(fr);
1005
		break;
2 7u83 1006
	}
7 7u83 1007
	case ftype_token_tag: {
1008
		/* Tokenised types */
1009
		IDENTIFIER id = DEREF_id(ftype_token_tok(ft));
1010
		LIST(TOKEN)args = DEREF_list(ftype_token_args(ft));
1011
		dump_tok_appl(id, args);
1012
		break;
2 7u83 1013
	}
7 7u83 1014
	}
1015
	return;
2 7u83 1016
}
1017
 
1018
 
1019
/*
1020
    DUMP A CLASS TYPE
1021
 
1022
    This routine adds the class type ct to the dump file.
1023
*/
1024
 
7 7u83 1025
static void
1026
dump_ctype(CLASS_TYPE ct)
2 7u83 1027
{
7 7u83 1028
	IDENTIFIER cid = DEREF_id(ctype_name(ct));
1029
	dump_id(cid);
1030
	return;
2 7u83 1031
}
1032
 
1033
 
1034
/*
1035
    DUMP AN ENUMERATION TYPE
1036
 
1037
    This routine adds the enumeration type et to the dump file.
1038
*/
1039
 
7 7u83 1040
static void
1041
dump_etype(ENUM_TYPE et)
2 7u83 1042
{
7 7u83 1043
	IDENTIFIER eid = DEREF_id(etype_name(et));
1044
	dump_id(eid);
1045
	return;
2 7u83 1046
}
1047
 
1048
 
1049
/*
1050
    DUMP A CONST-VOLATILE QUALIFIER
1051
 
1052
    This routine adds the const-volatile qualifier cv to the dump file.
1053
*/
1054
 
7 7u83 1055
static void
1056
dump_cv(CV_SPEC cv)
2 7u83 1057
{
7 7u83 1058
	if (cv & cv_const) {
1059
		fputc_v(MANGLE_const, dump_file);
1060
	}
1061
	if (cv & cv_volatile) {
1062
		fputc_v(MANGLE_volatile, dump_file);
1063
	}
1064
	return;
2 7u83 1065
}
1066
 
1067
 
1068
/*
1069
    DUMP A LIST OF TYPES
1070
 
1071
    This routine adds the list of types p to the dump file.
1072
*/
1073
 
7 7u83 1074
static void
1075
dump_type_list(LIST(TYPE)p, int ell, int started)
2 7u83 1076
{
7 7u83 1077
	while (!IS_NULL_list(p)) {
1078
		TYPE t = DEREF_type(HEAD_list(p));
1079
		if (!IS_NULL_type(t)) {
1080
			if (started) {
1081
				fputc_v(MANGLE_comma, dump_file);
1082
			}
1083
			if (ell & FUNC_PARAMS) {
1084
				t = unpromote_type(t);
1085
			}
1086
			dump_type(t);
1087
			started = 1;
1088
		}
1089
		p = TAIL_list(p);
2 7u83 1090
	}
7 7u83 1091
	return;
2 7u83 1092
}
1093
 
1094
 
1095
/*
1096
    DUMP A TYPE
1097
 
1098
    This routine adds the type t to the dump file.
1099
*/
1100
 
7 7u83 1101
static void
1102
dump_type(TYPE t)
2 7u83 1103
{
7 7u83 1104
	CV_SPEC qual = DEREF_cv(type_qual(t));
1105
	IDENTIFIER tid = DEREF_id(type_name(t));
1106
	dump_cv(qual);
1107
	if (!IS_NULL_id(tid)) {
1108
		switch (TAG_id(tid)) {
1109
		case id_class_alias_tag:
1110
		case id_enum_alias_tag:
1111
		case id_type_alias_tag: {
1112
			dump_id(tid);
1113
			return;
1114
		}
1115
		}
2 7u83 1116
	}
7 7u83 1117
	ASSERT(ORDER_type == 18);
1118
	switch (TAG_type(t)) {
2 7u83 1119
 
7 7u83 1120
	case type_pre_tag: {
1121
		/* Pre-types */
1122
		if (!IS_NULL_id(tid)) {
1123
			dump_id(tid);
2 7u83 1124
		} else {
7 7u83 1125
			BASE_TYPE bt = DEREF_btype(type_pre_rep(t));
1126
			if (bt == btype_ellipsis) {
1127
				fputs_v("Q<...>", dump_file);
1128
			} else {
1129
				fputc_v(MANGLE_error, dump_file);
1130
			}
2 7u83 1131
		}
7 7u83 1132
		break;
2 7u83 1133
	}
1134
 
7 7u83 1135
	case type_integer_tag: {
1136
		/* Integral types */
1137
		INT_TYPE it = DEREF_itype(type_integer_rep(t));
1138
		dump_itype(it);
1139
		break;
2 7u83 1140
	}
1141
 
7 7u83 1142
	case type_floating_tag: {
1143
		/* Floating point types */
1144
		FLOAT_TYPE ft = DEREF_ftype(type_floating_rep(t));
1145
		dump_ftype(ft);
1146
		break;
2 7u83 1147
	}
1148
 
7 7u83 1149
	case type_top_tag: {
1150
		/* Top type */
1151
		fputc_v(MANGLE_void, dump_file);
1152
		break;
2 7u83 1153
	}
1154
 
7 7u83 1155
	case type_bottom_tag: {
1156
		/* Bottom type */
1157
		fputc_v(MANGLE_bottom, dump_file);
1158
		break;
2 7u83 1159
	}
1160
 
7 7u83 1161
	case type_ptr_tag: {
1162
		/* Pointer types */
1163
		TYPE s = DEREF_type(type_ptr_sub(t));
1164
		fputc_v(MANGLE_ptr, dump_file);
1165
		dump_type(s);
1166
		break;
2 7u83 1167
	}
1168
 
7 7u83 1169
	case type_ref_tag: {
1170
		/* Reference types */
1171
		TYPE s = DEREF_type(type_ref_sub(t));
1172
		fputc_v(MANGLE_ref, dump_file);
1173
		dump_type(s);
1174
		break;
2 7u83 1175
	}
1176
 
7 7u83 1177
	case type_ptr_mem_tag: {
1178
		/* Pointer to member types */
1179
		CLASS_TYPE ct = DEREF_ctype(type_ptr_mem_of(t));
1180
		TYPE s = DEREF_type(type_ptr_mem_sub(t));
1181
		fputc_v(MANGLE_ptr_mem, dump_file);
1182
		dump_ctype(ct);
1183
		fputc_v(MANGLE_colon, dump_file);
1184
		dump_type(s);
1185
		break;
2 7u83 1186
	}
1187
 
7 7u83 1188
	case type_func_tag: {
1189
		/* Function types */
1190
		FILE *f = dump_file;
1191
		TYPE r = DEREF_type(type_func_ret(t));
1192
		LIST(TYPE)p = DEREF_list(type_func_ptypes(t));
1193
		LIST(TYPE)e = DEREF_list(type_func_except(t));
1194
		int ell = DEREF_int(type_func_ellipsis(t));
1195
		CV_SPEC mqual = DEREF_cv(type_func_mqual(t));
1196
		if (ell & FUNC_WEAK) {
1197
			fputc_v(MANGLE_weak, f);
1198
		} else {
1199
			fputc_v(MANGLE_func, f);
1200
		}
1201
		dump_type(r);
1202
		dump_type_list(p, ell, 1);
1203
		if (ell & FUNC_VAR_PARAMS) {
1204
			fputc_v(MANGLE_dot, f);
1205
		} else {
1206
			fputc_v(MANGLE_colon, f);
1207
		}
1208
		if (!EQ_list(e, univ_type_set)) {
1209
			/* Output exception specifiers */
1210
			fputc_v('(', f);
1211
			dump_type_list(e, FUNC_NONE, 0);
1212
			fputc_v(')', f);
1213
		}
1214
		dump_cv(mqual);
1215
		if (ell & FUNC_NO_PARAMS) {
1216
			fputc_v(MANGLE_dot, f);
1217
		} else {
1218
			fputc_v(MANGLE_colon, f);
1219
		}
1220
		break;
2 7u83 1221
	}
1222
 
7 7u83 1223
	case type_array_tag: {
1224
		/* Array types */
1225
		TYPE s = DEREF_type(type_array_sub(t));
1226
		NAT n = DEREF_nat(type_array_size(t));
1227
		fputc_v(MANGLE_array, dump_file);
1228
		if (!IS_NULL_nat(n)) {
1229
			dump_nat(n, 0);
1230
		}
1231
		fputc_v(MANGLE_colon, dump_file);
1232
		dump_type(s);
1233
		break;
2 7u83 1234
	}
1235
 
7 7u83 1236
	case type_bitfield_tag: {
1237
		/* Bitfield types */
1238
		INT_TYPE it = DEREF_itype(type_bitfield_defn(t));
1239
		dump_itype(it);
1240
		break;
2 7u83 1241
	}
1242
 
7 7u83 1243
	case type_compound_tag: {
1244
		/* Class types */
1245
		CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
1246
		dump_ctype(ct);
1247
		break;
2 7u83 1248
	}
1249
 
7 7u83 1250
	case type_enumerate_tag: {
1251
		/* Enumeration types */
1252
		ENUM_TYPE et = DEREF_etype(type_enumerate_defn(t));
1253
		dump_etype(et);
1254
		break;
2 7u83 1255
	}
1256
 
7 7u83 1257
	case type_token_tag: {
1258
		/* Tokenised types */
1259
		IDENTIFIER id = DEREF_id(type_token_tok(t));
1260
		LIST(TOKEN)args = DEREF_list(type_token_args(t));
1261
		dump_tok_appl(id, args);
1262
		break;
2 7u83 1263
	}
1264
 
7 7u83 1265
	case type_templ_tag: {
1266
		/* Template types */
1267
		TYPE s = DEREF_type(type_templ_defn(t));
1268
		TOKEN sort = DEREF_tok(type_templ_sort(t));
1269
		dump_sort(sort);
1270
		dump_type(s);
1271
		break;
2 7u83 1272
	}
1273
 
7 7u83 1274
	case type_instance_tag: {
1275
		/* Template instance types */
1276
		IDENTIFIER id = DEREF_id(type_name(t));
1277
		dump_id(id);
1278
		break;
2 7u83 1279
	}
1280
 
1281
	default : {
7 7u83 1282
		/* Other types */
1283
		fputc_v(MANGLE_error, dump_file);
1284
		break;
2 7u83 1285
	}
7 7u83 1286
	}
1287
	return;
2 7u83 1288
}
1289
 
1290
 
1291
/*
1292
    DUMP A GRAPH
1293
 
1294
    This routine adds the graph gr and all its subgraphs to the dump file.
1295
*/
1296
 
7 7u83 1297
static void
1298
dump_graph(GRAPH gr)
2 7u83 1299
{
7 7u83 1300
	FILE *f = dump_file;
1301
	unsigned n = DEREF_unsigned(graph_no(gr));
1302
	DECL_SPEC ds = DEREF_dspec(graph_access(gr));
1303
	if (ds & dspec_main) {
1304
		/* First instance of base */
1305
		DECL_SPEC acc = (ds & dspec_access);
1306
		CLASS_TYPE ct = DEREF_ctype(graph_head(gr));
1307
		LIST(GRAPH)br = DEREF_list(graph_tails(gr));
1308
		fprintf_v(f, "%u=", n);
2 7u83 1309
 
7 7u83 1310
		/* Dump access */
1311
		if (ds & dspec_virtual) {
1312
			fputc_v('V', f);
1313
		}
1314
		if (acc != dspec_public) {
1315
			gr = DEREF_graph(graph_equal(gr));
1316
			while (!IS_NULL_graph(gr)) {
1317
				ds = DEREF_dspec(graph_access(gr));
1318
				ds &= dspec_access;
1319
				if (ds < acc) {
1320
					acc = ds;
1321
				}
1322
				if (acc == dspec_public) {
1323
					break;
1324
				}
1325
				gr = DEREF_graph(graph_equal(gr));
1326
			}
1327
		}
1328
		dump_access(acc);
2 7u83 1329
 
7 7u83 1330
		/* Dump base classes */
1331
		dump_ctype(ct);
1332
		if (!IS_NULL_list(br)) {
1333
			fputs_v(" ( ", f);
1334
			while (!IS_NULL_list(br)) {
1335
				GRAPH gs = DEREF_graph(HEAD_list(br));
1336
				dump_graph(gs);
1337
				fputc_v(' ', f);
1338
				br = TAIL_list(br);
1339
			}
1340
			fputc_v(')', f);
1341
		}
1342
 
1343
	} else {
1344
		/* Subsequent instances of base */
1345
		fprintf_v(f, "%u:", n);
2 7u83 1346
	}
7 7u83 1347
	return;
2 7u83 1348
}
1349
 
1350
/*
1351
    DUMP A TOKEN APPLICATION
1352
 
1353
    This routine adds the token application id ( args ) to the dump file.
1354
*/
1355
 
7 7u83 1356
static void
1357
dump_tok_appl(IDENTIFIER id, LIST(TOKEN)args)
2 7u83 1358
{
7 7u83 1359
	if (IS_id_token(id)) {
1360
		IDENTIFIER alt = DEREF_id(id_token_alt(id));
1361
		if (!IS_NULL_id(alt)) {
1362
			id = alt;
2 7u83 1363
		}
1364
	}
7 7u83 1365
	if (IS_NULL_list(args)) {
1366
		dump_id(id);
1367
	} else {
1368
		FILE *f = dump_file;
1369
		fputc_v('T', f);
1370
		dump_id(id);
1371
		while (!IS_NULL_list(args)) {
1372
			TOKEN arg = DEREF_tok(HEAD_list(args));
1373
			fputc_v(MANGLE_comma, f);
1374
			if (!IS_NULL_tok(arg)) {
1375
				ASSERT(ORDER_tok == 10);
1376
				switch (TAG_tok(arg)) {
1377
				case tok_exp_tag: {
1378
					EXP e = DEREF_exp(tok_exp_value(arg));
1379
					fputc_v('E', f);
1380
					if (!IS_NULL_exp(e)) {
1381
						dump_exp(e);
1382
					}
1383
					break;
1384
				}
1385
				case tok_stmt_tag: {
1386
					EXP e = DEREF_exp(tok_stmt_value(arg));
1387
					fputc_v('S', f);
1388
					if (!IS_NULL_exp(e)) {
1389
						dump_exp(e);
1390
					}
1391
					break;
1392
				}
1393
				case tok_nat_tag: {
1394
					NAT n = DEREF_nat(tok_nat_value(arg));
1395
					fputc_v('N', f);
1396
					if (!IS_NULL_nat(n)) {
1397
						dump_nat(n, 0);
1398
					}
1399
					break;
1400
				}
1401
				case tok_snat_tag: {
1402
					NAT n = DEREF_nat(tok_snat_value(arg));
1403
					fputc_v('I', f);
1404
					if (!IS_NULL_nat(n)) {
1405
						dump_nat(n, 0);
1406
					}
1407
					break;
1408
				}
1409
				case tok_type_tag: {
1410
					TYPE t =
1411
					    DEREF_type(tok_type_value(arg));
1412
					fputc_v('T', f);
1413
					if (!IS_NULL_type(t)) {
1414
						dump_type(t);
1415
					}
1416
					break;
1417
				}
1418
				case tok_func_tag: {
1419
					IDENTIFIER fid =
1420
					    DEREF_id(tok_func_defn(arg));
1421
					fputc_v('F', f);
1422
					if (!IS_NULL_id(fid)) {
1423
						dump_id(fid);
1424
					}
1425
					break;
1426
				}
1427
				case tok_member_tag: {
1428
					OFFSET off =
1429
					    DEREF_off(tok_member_value(arg));
1430
					fputc_v('M', f);
1431
					if (!IS_NULL_off(off)) {
1432
						dump_off(off);
1433
					}
1434
					break;
1435
				}
1436
				case tok_class_tag: {
1437
					IDENTIFIER tid =
1438
					    DEREF_id(tok_class_value(arg));
1439
					fputc_v('C', f);
1440
					if (!IS_NULL_id(tid)) {
1441
						dump_id(tid);
1442
					}
1443
					break;
1444
				}
1445
				}
1446
			}
1447
			args = TAIL_list(args);
1448
		}
1449
		fputc_v(MANGLE_colon, f);
1450
	}
1451
	return;
2 7u83 1452
}
1453
 
1454
 
1455
/*
1456
    DUMP A BASE CLASS GRAPH
1457
 
1458
    This routine adds the base class graph associated with the class type
1459
    ct to the dump file.
1460
*/
1461
 
7 7u83 1462
void
1463
dump_base(CLASS_TYPE ct)
2 7u83 1464
{
7 7u83 1465
	unsigned n = DEREF_unsigned(ctype_no_bases(ct));
1466
	if (n > 1) {
1467
		FILE *f = dump_file;
1468
		if (f) {
1469
			CONST char *key;
1470
			GRAPH gr = DEREF_graph(ctype_base(ct));
1471
			CLASS_INFO ci = DEREF_cinfo(ctype_info(ct));
1472
			if (ci & cinfo_union) {
1473
				key = "TU";
1474
			} else if (ci & cinfo_struct) {
1475
				key = "TS";
1476
			} else {
1477
				key = "TC";
1478
			}
1479
			fprintf_v(f, "B%s\t%u\t", key, n);
1480
			dump_graph(gr);
1481
			fputc_v('\n', f);
1482
		}
2 7u83 1483
	}
7 7u83 1484
	return;
2 7u83 1485
}
1486
 
1487
 
1488
/*
1489
    DUMP AN OVERRIDING VIRTUAL FUNCTION
1490
 
1491
    This routine dumps the fact that the virtual function id overrides
1492
    the virtual function fid.
1493
*/
1494
 
7 7u83 1495
void
1496
dump_override(IDENTIFIER id, IDENTIFIER fid)
2 7u83 1497
{
7 7u83 1498
	FILE *f = dump_file;
1499
	if (f) {
1500
		fputs_v("O\t", f);
1501
		dump_id(id);
1502
		fputc_v('\t', f);
1503
		dump_id(fid);
1504
		fputc_v('\n', f);
1505
	}
1506
	return;
2 7u83 1507
}
1508
 
1509
 
1510
/*
1511
    DUMP A USING DECLARATION
1512
 
1513
    This routine dumps the fact that a using declaration has been used to
1514
    set up the alias id for cid.
1515
*/
1516
 
7 7u83 1517
void
1518
dump_alias(IDENTIFIER id, IDENTIFIER cid, LOCATION *loc)
2 7u83 1519
{
7 7u83 1520
	ulong n = DEREF_ulong(id_dump(cid));
1521
	COPY_ulong(id_dump(id), n);
1522
	/* NOT YET IMPLEMENTED */
1523
	UNUSED(loc);
1524
	return;
2 7u83 1525
}
1526
 
1527
 
1528
/*
1529
    DUMP A USING DIRECTIVE
1530
 
1531
    This routine dumps the fact that the namespace ns has been the subject
1532
    of a using directive in the namespace cns.
1533
*/
1534
 
7 7u83 1535
void
1536
dump_using(NAMESPACE ns, NAMESPACE cns, LOCATION *loc)
2 7u83 1537
{
7 7u83 1538
	/* NOT YET IMPLEMENTED */
1539
	UNUSED(ns);
1540
	UNUSED(cns);
1541
	UNUSED(loc);
1542
	return;
2 7u83 1543
}
1544
 
1545
 
1546
/*
1547
    TABLE OF ERROR NUMBERS
1548
 
1549
    This array contains a table of flags indicating whether each error
1550
    has been output or not.
1551
*/
1552
 
7 7u83 1553
static char *err_output = NULL;
2 7u83 1554
 
1555
 
1556
/*
1557
    DUMP AN ERROR
1558
 
1559
    This routine adds the error e of severity sev to the dump file.  It
1560
    returns false if the dump has already been closed or e is an internal
1561
    compiler error.
1562
*/
1563
 
7 7u83 1564
int
1565
dump_error(ERROR e, LOCATION *loc, int sev, int cnt)
2 7u83 1566
{
7 7u83 1567
	if (IS_err_simple(e)) {
1568
		/* Simple error message */
1569
		FILE *f = dump_file;
1570
		int n = DEREF_int(err_simple_number(e));
1571
		ERR_DATA *msg = ERR_CATALOG + n;
1572
		CONST char *sig = msg->signature;
1573
		ERR_PROPS props = msg->props;
2 7u83 1574
 
7 7u83 1575
		/* Dump start of error */
1576
		if (f == NULL) {
1577
			return (0);
1578
		}
1579
		if (props & ERR_PROP_compiler) {
1580
			return (0);
1581
		}
1582
		if (loc) {
1583
			/* First error component */
1584
			CONST char *err;
1585
			switch (sev) {
1586
			case ERROR_FATAL:
1587
				err = "EF";
1588
				break;
1589
			case ERROR_INTERNAL:
1590
				err = "EI";
1591
				break;
1592
			case ERROR_WARNING:
1593
				err = "EW";
1594
				break;
1595
			default:
1596
				err = "ES";
1597
				break;
1598
			}
1599
			fprintf_v(f, "%s\t", err);
1600
			dump_loc(loc);
1601
			fputc_v('\t', f);
1602
		} else {
1603
			/* Subsequent error component */
1604
			fputs_v("EC\t", f);
1605
		}
2 7u83 1606
 
7 7u83 1607
		/* Dump error number */
1608
		if (err_output[n]) {
1609
			fprintf_v(f, "%d", n);
1610
		} else {
1611
			CONST char *name = msg->name;
1612
			fprintf_v(f, "%d = <%s.%s>", n, ERR_NAME, name);
1613
			err_output[n] = 1;
1614
		}
2 7u83 1615
 
7 7u83 1616
		/* Dump error arguments */
1617
		if (sig == NULL) {
1618
			fprintf_v(f, "\t0\t%d\n", cnt );
1619
		} else {
1620
			unsigned a;
1621
			unsigned na = (unsigned)strlen(sig);
1622
			fprintf_v(f, "\t%u\t%d\n", na, cnt );
1623
			for (a = 0; a < na; a++) {
1624
				switch (sig[a]) {
1625
				case ERR_KEY_ACCESS: {
1626
					ACCESS acc;
1627
					acc =
1628
					    DEREF_dspec(err_arg(e, a, ACCESS));
1629
					IGNORE print_access(acc, dump_buff, 0);
1630
					fputs_v("EAS\t", f);
1631
					dump_string();
1632
					break;
1633
				}
1634
				case ERR_KEY_BASE_TYPE: {
1635
					BASE_TYPE bt;
1636
					bt = DEREF_btype(err_arg(e, a, BASE_TYPE));
1637
					IGNORE print_btype(bt, dump_buff, 0);
1638
					fputs_v("EAS\t", f);
1639
					dump_string();
1640
					break;
1641
				}
1642
				case ERR_KEY_CLASS_TYPE: {
1643
					CLASS_TYPE ct;
1644
					ct = DEREF_ctype(err_arg(e, a, CLASS_TYPE));
1645
					fputs_v("EAT\t", f);
1646
					dump_ctype(ct);
1647
					break;
1648
				}
1649
				case ERR_KEY_CV_SPEC: {
1650
					CV_SPEC cv =
1651
					    DEREF_cv(err_arg(e, a, CV_SPEC));
1652
					IGNORE print_cv(cv, dump_buff, 0);
1653
					fputs_v("EAS\t", f);
1654
					dump_string();
1655
					break;
1656
				}
1657
				case ERR_KEY_DECL_SPEC: {
1658
					DECL_SPEC ds;
1659
					ds = DEREF_dspec(err_arg(e, a, DECL_SPEC));
1660
					IGNORE print_dspec(ds, dump_buff, 0);
1661
					fputs_v("EAS\t", f);
1662
					dump_string();
1663
					break;
1664
				}
1665
				case ERR_KEY_FLOAT: {
1666
					FLOAT flt =
1667
					    DEREF_flt(err_arg(e, a, FLOAT));
1668
					IGNORE print_flt(flt, dump_buff, 0);
1669
					fputs_v("EAS\t", f);
1670
					dump_string();
1671
					break;
1672
				}
1673
				case ERR_KEY_HASHID: {
1674
					HASHID nm;
1675
					nm = DEREF_hashid(err_arg(e, a, HASHID));
1676
					fputs_v("EAH\t", f);
1677
					dump_hashid(nm);
1678
					break;
1679
				}
1680
				case ERR_KEY_IDENTIFIER:
1681
				case ERR_KEY_LONG_ID: {
1682
					IDENTIFIER id;
1683
					id = DEREF_id(err_arg(e, a, IDENTIFIER));
1684
					fputs_v("EAI\t", f);
1685
					dump_id(id);
1686
					break;
1687
				}
1688
				case ERR_KEY_LEX: {
1689
					LEX t = DEREF_int(err_arg(e, a, LEX));
1690
					fputs_v("EAS\t", f);
1691
					dump_lex(t);
1692
					break;
1693
				}
1694
				case ERR_KEY_NAMESPACE: {
1695
					NAMESPACE ns;
1696
					ns = DEREF_nspace(err_arg(e, a, NAMESPACE));
1697
					fputs_v("EAC\t", f);
1698
					dump_nspace(ns, 0);
1699
					break;
1700
				}
1701
				case ERR_KEY_NAT: {
1702
					NAT nat = DEREF_nat(err_arg(e, a, NAT));
1703
					fputs_v("EAN\t", f);
1704
					dump_nat(nat, 0);
1705
					break;
1706
				}
1707
				case ERR_KEY_PPTOKEN_P: {
1708
					PPTOKEN_P tok;
1709
					tok = DEREF_pptok(err_arg(e, a, PPTOKEN_P));
1710
					IGNORE print_pptok(tok, dump_buff, 0);
1711
					fputs_v("EAS\t", f);
1712
					dump_string();
1713
					break;
1714
				}
1715
				case ERR_KEY_PTR_LOC: {
1716
					PTR_LOC ploc;
1717
					LOCATION aloc;
1718
					ploc =
1719
					    DEREF_ptr(err_arg(e, a, PTR_LOC));
1720
					DEREF_loc(ploc, aloc);
1721
					fputs_v("EAL\t", f);
1722
					dump_loc(&aloc);
1723
					break;
1724
				}
1725
				case ERR_KEY_QUALIFIER: {
1726
					CONST char *s;
1727
					QUALIFIER qual;
1728
					qual = DEREF_qual(err_arg(e, a, QUALIFIER));
1729
					if (qual == qual_full ||
1730
					    qual == qual_top) {
1731
						s = "::";
1732
					} else {
1733
						s = "";
1734
					}
1735
					fprintf_v(f, "EAS\t<%s>", s);
1736
					break;
1737
				}
1738
				case ERR_KEY_STRING: {
1739
					STRING str =
1740
					    DEREF_str(err_arg(e, a, STRING));
1741
					IGNORE print_str(str, dump_buff, 0);
1742
					fputs_v("EAS\t", f);
1743
					dump_string();
1744
					break;
1745
				}
1746
				case ERR_KEY_TYPE: {
1747
					TYPE t =
1748
					    DEREF_type(err_arg(e, a, TYPE));
1749
					fputs_v("EAT\t", f);
1750
					dump_type(t);
1751
					break;
1752
				}
1753
				case ERR_KEY_cint: {
1754
					cint i = DEREF_int(err_arg(e, a, cint));
1755
					fprintf_v(f, "EAV\t%d", i);
1756
					break;
1757
				}
1758
				case ERR_KEY_plural: {
1759
					plural i;
1760
					i = DEREF_unsigned(err_arg(e, a, plural));
1761
					if (i == 1) {
1762
						fputs_v("EAS\t<>", f);
1763
					} else {
1764
						fputs_v("EAS\t<s>", f);
1765
					}
1766
					break;
1767
				}
1768
				case ERR_KEY_cstring:
1769
				case ERR_KEY_string: {
1770
					string s;
1771
					s = DEREF_string(err_arg(e, a, string));
1772
					if (s) {
1773
						unsigned d =
1774
						    (unsigned)ustrlen(s);
1775
						fprintf_v(f, "EAS\t&%u<%s>", d,
1776
							  strlit(s));
1777
					} else {
1778
						fputs_v("EAS\t<>", f);
1779
					}
1780
					break;
1781
				}
1782
				case ERR_KEY_ulong:
1783
				case ERR_KEY_ucint: {
1784
					ulong u =
1785
					    DEREF_ulong(err_arg(e, a, ulong));
1786
					fprintf_v(f, "EAV\t%lu", u);
1787
					break;
1788
				}
1789
				case ERR_KEY_unsigned: {
1790
					unsigned u;
1791
					u = DEREF_unsigned(err_arg(e, a,
1792
								   unsigned));
1793
					fprintf_v(f, "EAV\t%u", u);
1794
					break;
1795
				}
1796
				default: {
1797
					fputs_v("EAS\t<>", f);
1798
					break;
1799
				}
1800
				}
1801
				fputc_v('\n', f);
2 7u83 1802
			}
1803
		}
7 7u83 1804
 
1805
	} else {
1806
		/* Composite error message */
1807
		ERROR e1 = DEREF_err(err_compound_head(e));
1808
		ERROR e2 = DEREF_err(err_compound_tail(e));
1809
		if (!dump_error(e1, loc, sev, 1)) {
1810
			return (0);
1811
		}
1812
		if (!dump_error(e2, NIL(LOCATION), sev, cnt)) {
1813
			return (0);
1814
		}
2 7u83 1815
	}
7 7u83 1816
	return (1);
2 7u83 1817
}
1818
 
1819
 
1820
/*
1821
    DUMP A VARIABLE DESTRUCTOR CALL
1822
 
1823
    This routine adds the call of the destructor for the variable id to
1824
    the dump file.
1825
*/
1826
 
7 7u83 1827
void
1828
dump_destr(IDENTIFIER id, LOCATION *loc)
2 7u83 1829
{
7 7u83 1830
	EXP d = DEREF_exp(id_variable_etc_term(id));
1831
	if (!IS_NULL_exp(d)) {
1832
		unsigned tag = TAG_exp(d);
1833
		while (tag == exp_paren_tag) {
1834
			d = DEREF_exp(exp_paren_arg(d));
1835
			if (IS_NULL_exp(d)) {
1836
				return;
1837
			}
1838
			tag = TAG_exp(d);
1839
		}
1840
		while (tag == exp_nof_tag) {
1841
			d = DEREF_exp(exp_nof_pad(d));
1842
			tag = TAG_exp(d);
1843
		}
1844
		while (tag == exp_destr_tag) {
1845
			d = DEREF_exp(exp_destr_call(d));
1846
			tag = TAG_exp(d);
1847
		}
1848
		if (tag == exp_func_id_tag) {
1849
			IDENTIFIER fn = DEREF_id(exp_func_id_id(d));
1850
			dump_use(id, loc, 0);
1851
			dump_call(fn, loc, 0);
1852
		}
2 7u83 1853
	}
7 7u83 1854
	return;
2 7u83 1855
}
1856
 
1857
 
1858
/*
1859
    DUMP AN IDENTIFIER DECLARATION
1860
 
1861
    This routine adds the declaration of the identifier id to the dump
1862
    file.  The parameter def is 1 for a definition, 2 for a tentative
1863
    definition, and 0 for a declaration.
1864
*/
1865
 
7 7u83 1866
void
1867
dump_declare(IDENTIFIER id, LOCATION *loc, int def)
2 7u83 1868
{
7 7u83 1869
	FILE *f = dump_file;
1870
	CONST char *key = dump_key(id, def);
1871
	if (key && f) {
1872
		/* Dump identifier key */
1873
		char d = 'M';
1874
		int destr = 0;
1875
		DECL_SPEC ds = DEREF_dspec(id_storage(id));
1876
		if (dump_implicit || dump_template) {
1877
			fputc_v('I', f);
1878
		}
1879
		switch (def) {
1880
		case 1:
1881
			d = 'D';
1882
			break;
1883
		case 2:
1884
			d = 'T';
1885
			break;
1886
		}
2 7u83 1887
 
7 7u83 1888
		/* Dump location and identifier information */
1889
		fprintf_v(f, "%c%s\t", d, key);
1890
		dump_loc(loc);
1891
		fputc_v('\t', f);
1892
		dump_id(id);
1893
		fputc_v('\t', f);
2 7u83 1894
 
7 7u83 1895
		/* Dump identifier specific information */
1896
		switch (TAG_id(id)) {
1897
		case id_obj_macro_tag: {
1898
			/* Object-like macros */
1899
			fputs_v("ZUO", f);
1900
			break;
2 7u83 1901
		}
7 7u83 1902
		case id_func_macro_tag: {
1903
			/* Function-like macros */
1904
			unsigned n;
1905
			n = DEREF_unsigned(id_func_macro_no_params(id));
1906
			fprintf_v(f, "ZUF%u", n);
1907
			break;
2 7u83 1908
		}
7 7u83 1909
		case id_builtin_tag: {
1910
			/* Built-in operators */
1911
			TYPE r = DEREF_type(id_builtin_ret(id));
1912
			LIST(TYPE)p = DEREF_list(id_builtin_ptypes(id));
1913
			fputc_v(MANGLE_func, f);
1914
			dump_type(r);
1915
			dump_type_list(p, FUNC_NONE, 1);
1916
			fputc_v(MANGLE_colon, f);
1917
			fputc_v(MANGLE_colon, f);
1918
			break;
1919
		}
1920
		case id_class_name_tag:
1921
		case id_enum_name_tag:
1922
		case id_class_alias_tag:
1923
		case id_enum_alias_tag:
1924
		case id_type_alias_tag: {
1925
			/* Type aliases */
1926
			TYPE t = DEREF_type(id_class_name_etc_defn(id));
1927
			if (ds & dspec_token) {
1928
				/* Tokenised types */
1929
				IDENTIFIER tid = find_token(id);
1930
				if (IS_id_token(tid)) {
1931
					TOKEN tok =
1932
					    DEREF_tok(id_token_sort(tid));
1933
					dump_sort(tok);
1934
					break;
1935
				}
1936
			}
1937
			dump_type(t);
1938
			break;
1939
		}
1940
		case id_nspace_name_tag: {
1941
			/* Namespace names */
1942
			fputc_v('*', f);
1943
			break;
1944
		}
1945
		case id_nspace_alias_tag: {
1946
			/* Namespace aliases */
1947
			NAMESPACE ns = DEREF_nspace(id_nspace_alias_defn(id));
1948
			dump_nspace(ns, 0);
1949
			break;
1950
		}
1951
		case id_variable_tag:
1952
		case id_parameter_tag:
1953
		case id_stat_member_tag: {
1954
			/* Variables */
1955
			TYPE t = DEREF_type(id_variable_etc_type(id));
1956
			dump_type(t);
1957
			if (!(ds & dspec_auto))destr = def;
1958
			break;
1959
		}
1960
		case id_weak_param_tag: {
1961
			/* Non-prototype function parameters */
1962
			dump_type(type_sint);
1963
			break;
1964
		}
1965
		case id_function_tag:
1966
		case id_mem_func_tag:
1967
		case id_stat_mem_func_tag: {
1968
			/* Functions */
1969
			TYPE t = DEREF_type(id_function_etc_type(id));
1970
			IDENTIFIER over = DEREF_id(id_function_etc_over(id));
1971
			dump_type(t);
1972
			if (!IS_NULL_id(over)) {
1973
				fputc_v('\t', f);
1974
				dump_id(over);
1975
			}
1976
			break;
1977
		}
1978
		case id_member_tag: {
1979
			/* Data members */
1980
			TYPE t = DEREF_type(id_member_type(id));
1981
			dump_type(t);
1982
			break;
1983
		}
1984
		case id_enumerator_tag: {
1985
			/* Enumerators */
1986
			TYPE t = DEREF_type(id_enumerator_etype(id));
1987
			dump_type(t);
1988
			break;
1989
		}
1990
		case id_token_tag: {
1991
			/* Tokens */
1992
			TOKEN tok = DEREF_tok(id_token_sort(id));
1993
			dump_sort(tok);
1994
			break;
1995
		}
1996
		default : {
1997
			/* Other identifiers */
1998
			fputc_v('*', f);
1999
			break;
2000
		}
2001
		}
2002
		fputc_v('\n', f);
2003
 
2004
		/* Deal with destructors */
2005
		if (destr && do_usage) {
2006
			dump_destr(id, loc);
2007
		}
2 7u83 2008
	}
7 7u83 2009
	dump_implicit = 0;
2010
	return;
2 7u83 2011
}
2012
 
2013
 
2014
/*
2015
    DUMP AN IDENTIFIER UNDEFINITION
2016
 
2017
    This routine adds the undefinition (indicating the end of a scope)
2018
    of the identifier id to the dump file.
2019
*/
2020
 
7 7u83 2021
void
2022
dump_undefine(IDENTIFIER id, LOCATION *loc, int def)
2 7u83 2023
{
7 7u83 2024
	FILE *f = dump_file;
2025
	CONST char *key = dump_key(id, def);
2026
	if (key && f) {
2027
		if (def) {
2028
			fprintf_v(f, "U%s\t", key);
2029
		} else {
2030
			fprintf_v(f, "Q%s\t", key);
2031
		}
2032
		dump_loc(loc);
2033
		fputc_v('\t', f);
2034
		dump_id(id);
2035
		fputc_v('\n', f);
2 7u83 2036
	}
7 7u83 2037
	return;
2 7u83 2038
}
2039
 
2040
 
2041
/*
2042
    DUMP AN IDENTIFIER USE
2043
 
2044
    This routine adds the use of the identifier id to the dump file.
2045
    expl is true for an explicit use.
2046
*/
2047
 
7 7u83 2048
void
2049
dump_use(IDENTIFIER id, LOCATION *loc, int expl)
2 7u83 2050
{
7 7u83 2051
	FILE *f = dump_file;
2052
	CONST char *key = dump_key(id, 1);
2053
	if (key && f) {
2054
		if (!expl) {
2055
			fputc_v('I', f);
2056
		}
2057
		fprintf_v(f, "L%s\t", key);
2058
		dump_loc(loc);
2059
		fputc_v('\t', f);
2060
		dump_id(id);
2061
		fputc_v('\n', f);
2062
	}
2063
	return;
2 7u83 2064
}
2065
 
2066
 
2067
/*
2068
    DUMP AN IDENTIFIER CALL
2069
 
2070
    This routine adds the call of the identifier id to the dump file.
2071
    expl is true for an explicit call.
2072
*/
2073
 
7 7u83 2074
void
2075
dump_call(IDENTIFIER id, LOCATION *loc, int expl)
2 7u83 2076
{
7 7u83 2077
	FILE *f = dump_file;
2078
	CONST char *key = dump_key(id, 1);
2079
	if (key && f) {
2080
		if (!expl) {
2081
			fputc_v('I', f);
2082
		}
2083
		fprintf_v(f, "C%s\t", key);
2084
		dump_loc(loc);
2085
		fputc_v('\t', f);
2086
		dump_id(id);
2087
		fputc_v('\n', f);
2088
	}
2089
	return;
2 7u83 2090
}
2091
 
2092
 
2093
/*
2094
    DUMP A TEMPLATE INSTANCE
2095
 
2096
    This routine adds the association of the identifier id and the
2097
    template instance form to the dump file.
2098
*/
2099
 
7 7u83 2100
void
2101
dump_instance(IDENTIFIER id, TYPE form, TYPE spec)
2 7u83 2102
{
7 7u83 2103
	FILE *f = dump_file;
2104
	CONST char *key = dump_key(id, 1);
2105
	if (key && f) {
2106
		fprintf_v(f, "Z%s\t", key);
2107
		dump_id(id);
2108
		fputc_v('\t', f);
2109
		dump_type(form);
2110
		if (!EQ_type(form, spec)) {
2111
			fputc_v('\t', f);
2112
			dump_type(spec);
2113
			fputc_v('\n', f);
2114
		} else {
2115
			fputs_v("\t*\n", f);
2116
		}
2 7u83 2117
	}
7 7u83 2118
	return;
2 7u83 2119
}
2120
 
2121
 
2122
/*
2123
    DUMP A TOKEN NAME
2124
 
2125
    This routine adds the association of the identifier id and the external
2126
    token name tok to the dump file.
2127
*/
2128
 
7 7u83 2129
void
2130
dump_token(IDENTIFIER id, IDENTIFIER tok)
2 7u83 2131
{
7 7u83 2132
	FILE *f = dump_file;
2133
	CONST char *key = dump_key(id, 1);
2134
	if (key && f) {
2135
		HASHID nm = DEREF_hashid(id_name(tok));
2136
		if (IS_hashid_name_etc(nm)) {
2137
			string s = DEREF_string(hashid_name_etc_text(nm));
2138
			unsigned n = (unsigned)ustrlen(s);
2139
			fprintf_v(f, "X%s\t", key);
2140
			dump_id(id);
2141
			fprintf_v(f, "\t&%u<%s>\n", n, strlit(s));
2142
		}
2 7u83 2143
	}
7 7u83 2144
	return;
2 7u83 2145
}
2146
 
2147
 
2148
/*
2149
    DUMP A TOKEN PARAMETER
2150
 
2151
    This routine adds the declaration of the token or template parameter
2152
    id to the dump file.
2153
*/
2154
 
7 7u83 2155
void
2156
dump_token_param(IDENTIFIER id)
2 7u83 2157
{
7 7u83 2158
	dump_declare(id, &crt_loc, 0);
2159
	if (IS_id_token(id)) {
2160
		IDENTIFIER alt = DEREF_id(id_token_alt(id));
2161
		ulong n = DEREF_ulong(id_dump(id));
2162
		COPY_ulong(id_dump(alt), n);
2163
	}
2164
	return;
2 7u83 2165
}
2166
 
2167
 
2168
/*
2169
    DUMP A BUILT-IN OPERATOR
2170
 
2171
    This routine adds the declaration of the built-in operator id to the
2172
    dump file.
2173
*/
2174
 
7 7u83 2175
void
2176
dump_builtin(IDENTIFIER id)
2 7u83 2177
{
7 7u83 2178
	if (IS_id_builtin(id)) {
2179
		dump_implicit = 1;
2180
		dump_declare(id, &crt_loc, 0);
2181
	}
2182
	return;
2 7u83 2183
}
2184
 
2185
 
2186
/*
2187
    DUMP A PROMOTION TYPE
2188
 
2189
    This routine adds the fact that the promotion of the integral type
2190
    it is ip to the dump file.
2191
*/
2192
 
7 7u83 2193
void
2194
dump_promote(INT_TYPE it, INT_TYPE ip)
2 7u83 2195
{
7 7u83 2196
	FILE *f = dump_file;
2197
	if (f) {
2198
		fputs_v("P\t", f);
2199
		dump_itype(it);
2200
		fputc_v(MANGLE_colon, f);
2201
		dump_itype(ip);
2202
		fputc_v('\n', f);
2203
	}
2204
	return;
2 7u83 2205
}
2206
 
2207
 
2208
/*
2209
    DUMP THE START OF A SCOPE
2210
 
2211
    This routine adds the start of the scope ns (which may have an associated
2212
    name, id) to the dump file.  pns gives the enclosing scope, if known.
2213
*/
2214
 
7 7u83 2215
void
2216
dump_begin_scope(IDENTIFIER id, NAMESPACE ns, NAMESPACE pns, LOCATION *loc)
2 7u83 2217
{
7 7u83 2218
	FILE *f = dump_file;
2219
	if (!IS_NULL_nspace(ns) && f) {
2220
		ulong n;
2221
		HASHID nm;
2222
		if (!IS_NULL_id(id)) {
2223
			/* Named scope */
2224
			fputs_v("SSH\t", f);
2225
			n = DEREF_ulong(id_dump(id));
2226
			if (n != LINK_NONE) {
2227
				/* Already used */
2228
				dump_loc(loc);
2229
				fprintf_v(f, "\t%lu\n", n);
2230
				return;
2231
			}
2232
			n = dump_id_next++;
2233
			COPY_ulong(id_dump(id), n);
2234
			nm = DEREF_hashid(id_name(id));
2235
		} else {
2236
			/* Unnamed scope */
2237
			fputs_v("SSB\t", f);
2238
			n = dump_id_next++;
2239
			nm = NULL_hashid;
2240
		}
2241
		dump_loc(loc);
2242
		fprintf_v(f, "\t%lu = ", n);
2243
		dump_hashid(nm);
2244
		fputc_v('\t', f);
2245
		dump_nspace(pns, 1);
2246
		fputc_v('\n', f);
2247
		COPY_ulong(nspace_dump(ns), n);
2 7u83 2248
	}
7 7u83 2249
	return;
2 7u83 2250
}
2251
 
2252
 
2253
/*
2254
    DUMP THE END OF A SCOPE
2255
 
2256
    This routine adds the end of the scope ns (which may have an associated
2257
    name, id) to the dump file.
2258
*/
2259
 
7 7u83 2260
void
2261
dump_end_scope(IDENTIFIER id, NAMESPACE ns, LOCATION *loc)
2 7u83 2262
{
7 7u83 2263
	FILE *f = dump_file;
2264
	if (!IS_NULL_nspace(ns) && f) {
2265
		ulong n = DEREF_ulong(nspace_dump(ns));
2266
		if (!IS_NULL_id(id)) {
2267
			fputs_v("SEH\t", f);
2268
		} else {
2269
			fputs_v("SEB\t", f);
2270
		}
2271
		dump_loc(loc);
2272
		fprintf_v(f, "\t%lu\n", n);
2 7u83 2273
	}
7 7u83 2274
	return;
2 7u83 2275
}
2276
 
2277
 
2278
/*
2279
    DUMP A STRING LITERAL
2280
 
2281
    This routine adds the string literal of type kind given by the start
2282
    and end points s and e to the dump file.
2283
*/
2284
 
7 7u83 2285
void
2286
dump_string_lit(string s, string e, unsigned kind)
2 7u83 2287
{
7 7u83 2288
	FILE *f = dump_file;
2289
	if (f) {
2290
		unsigned long n = (unsigned long)(e - s);
2291
		fputc_v('A', f);
2292
		if (kind & STRING_CHAR) {
2293
			fputc_v('C', f);
2294
		}
2295
		if (kind & STRING_WIDE) {
2296
			fputc_v('L', f);
2297
		}
2298
		fputc_v('\t', f);
2299
		dump_loc(&crt_loc);
2300
		fprintf_v(f, "\t&%lu<", n);
2301
		while (s != e) {
2302
			int c = (int)*(s++);
2303
			fputc_v(c, f);
2304
		}
2305
		fputs_v(">\n", f);
2 7u83 2306
	}
7 7u83 2307
	return;
2 7u83 2308
}
2309
 
2310
 
2311
/*
2312
    DUMP THE START OF A FILE
2313
 
2314
    This routine adds the start of the file loc to the dump file.  dir
2315
    gives the directory in which the file was found.
2316
*/
2317
 
7 7u83 2318
void
2319
dump_start(LOCATION *loc, INCL_DIR *dir)
2 7u83 2320
{
7 7u83 2321
	FILE *f = dump_file;
2322
	if (f) {
2323
		fputs_v("FS\t", f);
2324
		dump_loc(loc);
2325
		if (dir) {
2326
			fprintf_v(f, "\t%lu\n", dir->no);
2327
		} else {
2328
			fputs_v("\t*\n", f);
2329
		}
2 7u83 2330
	}
7 7u83 2331
	return;
2 7u83 2332
}
2333
 
2334
 
2335
/*
2336
    DUMP THE END OF A FILE
2337
 
2338
    This routine adds the end of the file loc to the dump file.
2339
*/
2340
 
7 7u83 2341
void
2342
dump_end(LOCATION *loc)
2 7u83 2343
{
7 7u83 2344
	FILE *f = dump_file;
2345
	if (f) {
2346
		fputs_v("FE\t", f);
2347
		dump_loc(loc);
2348
		fputc_v('\n', f);
2349
	}
2350
	return;
2 7u83 2351
}
2352
 
2353
 
2354
/*
2355
    DUMP A FILE INCLUSION
2356
 
2357
    This routine adds a file inclusion to the dump file.  loc gives the
2358
    location of the '#include' directive, the following file start gives
2359
    the file included.  st is as in start_include, plus 4 for the
2360
    resumption of a file after a file has been included.  q is either '"',
2361
    '>' or ']' depending on the type of inclusion.
2362
*/
2363
 
7 7u83 2364
void
2365
dump_include(LOCATION *loc, string nm, int st, int q)
2 7u83 2366
{
7 7u83 2367
	FILE *f = dump_file;
2368
	if (f) {
2369
		CONST char *incl;
2370
		switch (st) {
2371
		case 2:
2372
			incl = "FIS";
2373
			break;
2374
		case 3:
2375
			incl = "FIE";
2376
			break;
2377
		case 4:
2378
			incl = "FIR";
2379
			nm = NULL;
2380
			break;
2381
		default: {
2382
			if (q == char_quote) {
2383
				incl = "FIQ";
2384
			} else if (q == char_close_square) {
2385
				incl = "FIN";
2386
			} else {
2387
				incl = "FIA";
2388
			}
2389
			break;
2 7u83 2390
		}
7 7u83 2391
		}
2392
		fprintf_v(f, "%s\t", incl);
2393
		dump_loc(loc);
2394
		if (nm) {
2395
			/* Output included name */
2396
			unsigned n = (unsigned)ustrlen(nm);
2397
			fprintf_v(f, "\t&%u<%s>", n, strlit(nm));
2398
		}
2399
		fputc_v('\n', f);
2 7u83 2400
	}
7 7u83 2401
	return;
2 7u83 2402
}
2403
 
2404
 
2405
/*
2406
    OPEN DUMP FILE
2407
 
2408
    This routine opens the dump file nm with dump options given by opt.
2409
    This corresponds to the command-line option '-dopt=nm'.
2410
*/
2411
 
7 7u83 2412
void
2413
init_dump(string nm, string opt)
2 7u83 2414
{
7 7u83 2415
	if (nm) {
2416
		/* Open dump file */
2417
		FILE *f;
2418
		char *p;
2419
		character c;
2420
		unsigned i, n;
2421
		int do_all = 0;
2422
		output_name[OUTPUT_DUMP] = nm;
2423
		if (!open_output(OUTPUT_DUMP, text_mode)) {
2424
			fail(ERR_fail_dump(nm));
2425
			term_error(0);
2426
			return;
2427
		}
2428
		f = output_file[OUTPUT_DUMP];
2429
		fprintf_v(f, "# Dump file for %s %s\n", progname, progvers);
2430
		fprintf_v(f, "V\t%lu\t%lu\t", DUMP_major, DUMP_minor );
2431
		fprintf_v(f, "<%s>\n", LANGUAGE_NAME);
2432
		dump_file = f;
2 7u83 2433
 
7 7u83 2434
		/* Set dump options */
2435
		do_dump = 1;
2436
		while (c = *(opt++), (c && c != '=')) {
2437
			switch (c) {
2438
			case 'a':
2439
				do_all = 1;
2440
				break;
2441
			case 'c':
2442
				do_string = 1;
2443
				break;
2444
			case 'e':
2445
				do_error = 1;
2446
				break;
2447
			case 'h':
2448
				do_header = 1;
2449
				break;
2450
			case 'k':
2451
				do_keyword = 1;
2452
				break;
2453
			case 'l':
2454
				do_local = 1;
2455
				break;
2456
			case 'm':
2457
				do_macro = 1;
2458
				break;
2459
			case 'p':
2460
				break;
2461
			case 's':
2462
				do_scope = 1;
2463
				break;
2464
			case 'u':
2465
				do_usage = 1;
2466
				break;
2467
			default: {
2468
				/* Unknown dump options */
2469
				CONST char *err = "Unknown dump option, '%c'";
2470
				error(ERROR_WARNING, err,(int)c);
2471
				break;
2472
			}
2473
			}
2 7u83 2474
		}
7 7u83 2475
		if (do_all) {
2476
			/* Enable all dump options */
2477
			do_error = 1;
2478
			do_header = 1;
2479
			do_local = 1;
2480
			do_macro = 1;
2481
			do_usage = 1;
2482
		}
2 7u83 2483
 
7 7u83 2484
		/* Allocate table of error numbers */
2485
		n = catalog_size;
2486
		p = xmalloc_nof(char, n);
2487
		for (i = 0; i < n; i++) {
2488
			p[i] = 0;
2489
		}
2490
		err_output = p;
2491
		last_input = ustrlit("");
2492
		last_file = ustrlit("");
2 7u83 2493
 
7 7u83 2494
		/* Output file inclusion directories */
2495
		if (do_header) {
2496
			ulong r = 0;
2497
			INCL_DIR *d = dir_path;
2498
			while (d != NULL) {
2499
				string s = d->path;
2500
				if (s) {
2501
					unsigned m = (unsigned)ustrlen(s);
2502
					fprintf_v(f, "FD\t%lu = &%u<%s>", r, m,
2503
						  strlit(s));
2504
					s = d->name;
2505
					if (s) {
2506
						m = (unsigned)ustrlen(s);
2507
						fprintf_v(f, "\t&%u<%s>", m,
2508
							  strlit(s));
2509
					}
2510
					fputc_v('\n', f);
2511
				}
2512
				d->no = r++;
2513
				d = d->next;
2514
			}
2 7u83 2515
		}
7 7u83 2516
		if (do_usage || do_scope) {
2517
			record_location = 1;
2518
		}
2519
		if (do_error) {
2520
			max_errors = ULONG_MAX;
2521
		}
2 7u83 2522
	}
7 7u83 2523
	return;
2 7u83 2524
}
2525
 
2526
 
2527
/*
2528
    CLOSE DUMP FILE
2529
 
2530
    This routine closes the dump file.
2531
*/
2532
 
7 7u83 2533
void
2534
term_dump(void)
2 7u83 2535
{
7 7u83 2536
	if (do_dump) {
2537
		FILE *f = dump_file;
2538
		if (f) {
2539
			dump_file = NULL;
2540
			fputs_v("# End of dump file\n", f);
2541
			close_output(OUTPUT_DUMP);
2542
		}
2543
		do_dump = 0;
2 7u83 2544
	}
7 7u83 2545
	return;
2 7u83 2546
}