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 <ctype.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 "flt_ops.h"
69
#include "ftype_ops.h"
70
#include "graph_ops.h"
71
#include "hashid_ops.h"
72
#include "id_ops.h"
73
#include "itype_ops.h"
74
#include "member_ops.h"
75
#include "nat_ops.h"
76
#include "nspace_ops.h"
77
#include "off_ops.h"
78
#include "str_ops.h"
79
#include "tok_ops.h"
80
#include "type_ops.h"
81
#include "error.h"
82
#include "basetype.h"
83
#include "buffer.h"
84
#include "char.h"
85
#include "class.h"
86
#include "constant.h"
87
#include "convert.h"
88
#include "debug.h"
89
#include "exception.h"
90
#include "file.h"
91
#include "function.h"
92
#include "hash.h"
93
#include "label.h"
94
#include "lex.h"
95
#include "literal.h"
96
#include "print.h"
97
#include "redeclare.h"
98
#include "symbols.h"
99
#include "syntax.h"
100
#include "tok.h"
101
#include "token.h"
102
#include "ustring.h"
103
 
104
 
105
/*
106
    PRINT BUFFER
107
 
108
    This buffer is used for the error output.
109
*/
110
 
7 7u83 111
BUFFER print_buff = NULL_buff;
2 7u83 112
 
113
 
114
/*
115
    FUNCTION DECLARATIONS
116
 
117
    A couple of forward function declarations are necessary.
118
*/
119
 
7 7u83 120
static int print_head(TYPE, int, BUFFER *, int);
121
static int print_tail(TYPE, BUFFER *, int);
2 7u83 122
 
123
 
124
/*
125
    PRINT FLAGS
126
 
127
    These flags are used to control the form of the output.
128
*/
129
 
7 7u83 130
static int print_default_args = 0;
131
static int print_member_type = 0;
132
static int print_return_type = 1;
133
static int print_func_params = 0;
134
static int print_except = 0;
135
static int print_func_linkage = 0;
136
static int print_parent_namespace = 1;
137
static int print_bitfield_sep = ':';
138
int print_c_style = LANGUAGE_C;
139
int print_type_alias = 0;
140
int print_uniq_anon = 0;
141
int print_id_desc = 0;
2 7u83 142
 
143
 
144
/*
145
    PRINT A LEXICAL TOKEN NAME
146
 
147
    This routine prints the name of the lexical token t to the buffer bf.
148
    With all the routines in this file the sp argument is true if a space
149
    should be printed before the actual text, and the return value is true
150
    if a space should be printed after it.
151
*/
152
 
7 7u83 153
int
154
print_lex(int t, BUFFER *bf, int sp)
2 7u83 155
{
7 7u83 156
	string s = token_name(t);
157
	if (s == NULL) {
158
		return (sp);
159
	}
160
	if (sp) {
161
		bfputc(bf, ' ');
162
	}
163
	bfputs(bf, s);
164
	return (1);
2 7u83 165
}
166
 
167
 
168
/*
169
    PRINT AN ACCESS SPECIFIER
170
 
171
    This routine prints the access specifier n to the buffer bf.
172
*/
173
 
7 7u83 174
int
175
print_access(DECL_SPEC n, BUFFER *bf, int sp)
2 7u83 176
{
7 7u83 177
	int t;
178
	DECL_SPEC a = (n & dspec_access);
179
	if (a == dspec_private) {
180
		t = lex_private;
181
	} else if (a == dspec_protected) {
182
		t = lex_protected;
183
	} else {
184
		t = lex_public;
185
	}
186
	sp = print_lex(t, bf, sp);
187
	return (sp);
2 7u83 188
}
189
 
190
 
191
/*
192
    BUILT-IN TYPE NAMES
193
 
194
    This table gives the names of the built-in types.
195
*/
196
 
7 7u83 197
CONST char *ntype_name[ORDER_ntype] = {
198
	"<error>",		/* ntype_none */
199
	"char",			/* ntype_char */
200
	"signed char",		/* ntype_schar */
201
	"unsigned char",	/* ntype_uchar */
202
	"short",		/* ntype_sshort */
203
	"unsigned short",	/* ntype_ushort */
204
	"int",			/* ntype_sint */
205
	"unsigned int",		/* ntype_uint */
206
	"long",			/* ntype_slong */
207
	"unsigned long",	/* ntype_ulong */
208
	"long long",		/* ntype_sllong */
209
	"unsigned long long",	/* ntype_ullong */
210
	"float",		/* ntype_float */
211
	"double",		/* ntype_double */
212
	"long double",		/* ntype_ldouble */
213
	"void",			/* ntype_void */
214
	"<bottom>",		/* ntype_bottom */
215
	"bool",			/* ntype_bool */
216
	"ptrdiff_t",		/* ntype_ptrdiff_t */
217
	"size_t",		/* ntype_size_t */
218
	"wchar_t",		/* ntype_wchar_t */
219
	"..."			/* ntype_ellipsis */
220
};
2 7u83 221
 
222
 
223
/*
224
    PRINT A BUILT-IN TYPE
225
 
226
    This routine prints the built-in type n to the buffer bf.
227
*/
228
 
7 7u83 229
int
230
print_ntype(BUILTIN_TYPE n, BUFFER *bf, int sp)
2 7u83 231
{
7 7u83 232
	if (sp) {
233
		bfputc(bf, ' ');
234
	}
235
	bfputs(bf, ustrlit(ntype_name[n]));
236
	return (1);
2 7u83 237
}
238
 
239
 
240
/*
241
    PRINT A BASE TYPE
242
 
243
    This routine prints the base type n to the buffer bf.
244
*/
245
 
7 7u83 246
int
247
print_btype(BASE_TYPE n, BUFFER *bf, int sp)
2 7u83 248
{
7 7u83 249
	BASE_TYPE key = (n & btype_named);
250
	if (key) {
251
		switch (key) {
252
		case btype_class:
253
			sp = print_lex(lex_class, bf, sp);
254
			break;
255
		case btype_struct:
256
			sp = print_lex(lex_struct, bf, sp);
257
			break;
258
		case btype_union:
259
			sp = print_lex(lex_union, bf, sp);
260
			break;
261
		case btype_enum:
262
			sp = print_lex(lex_enum, bf, sp);
263
			break;
264
		case btype_any:
265
			sp = print_lex(lex_tag_Hcap, bf, sp);
266
			break;
267
		}
268
	} else {
269
		if (n & btype_signed) {
270
			sp = print_lex(lex_signed, bf, sp);
271
		}
272
		if (n & btype_unsigned) {
273
			sp = print_lex(lex_unsigned, bf, sp);
274
		}
275
		if (n & btype_short) {
276
			sp = print_lex(lex_short, bf, sp);
277
		}
278
		if (n & btype_long) {
279
			sp = print_lex(lex_long, bf, sp);
280
		}
281
		if (n & btype_long2) {
282
			sp = print_lex(lex_long, bf, sp);
283
		}
284
		if (n & btype_char) {
285
			sp = print_lex(lex_char, bf, sp);
286
		}
287
		if (n & btype_int) {
288
			sp = print_lex(lex_int, bf, sp);
289
		}
290
		if (n & btype_float) {
291
			sp = print_lex(lex_float, bf, sp);
292
		}
293
		if (n & btype_double) {
294
			sp = print_lex(lex_double, bf, sp);
295
		}
296
		if (n & btype_void) {
297
			sp = print_lex(lex_void, bf, sp);
298
		}
299
		if (n & btype_bottom) {
300
			sp = print_lex(lex_bottom, bf, sp);
301
		}
302
		if (n & btype_bool) {
303
			sp = print_lex(lex_bool, bf, sp);
304
		}
305
		if (n & btype_ptrdiff_t) {
306
			sp = print_lex(lex_ptrdiff_Ht, bf, sp);
307
		}
308
		if (n & btype_size_t) {
309
			sp = print_lex(lex_size_Ht, bf, sp);
310
		}
311
		if (n & btype_wchar_t) {
312
			sp = print_lex(lex_wchar_Ht, bf, sp);
313
		}
314
		if (n & btype_ellipsis) {
315
			sp = print_lex(lex_ellipsis, bf, sp);
316
		}
317
		if (n & btype_star) {
318
			sp = print_lex(lex_star, bf, sp);
319
		}
2 7u83 320
	}
7 7u83 321
	return (sp);
2 7u83 322
}
323
 
324
 
325
/*
326
    PRINT A CONST-VOLATILE QUALIFIER
327
 
328
    This routine prints the const-volatile qualifier n to the buffer bf.
329
*/
330
 
7 7u83 331
int
332
print_cv(CV_SPEC n, BUFFER *bf, int sp)
2 7u83 333
{
7 7u83 334
	if (n) {
335
		if (n & cv_const) {
336
			sp = print_lex(lex_const, bf, sp);
337
		}
338
		if (n & cv_volatile) {
339
			sp = print_lex(lex_volatile, bf, sp);
340
		}
341
	}
342
	return (sp);
2 7u83 343
}
344
 
345
 
346
/*
347
    PRINT A DECLARATION SPECIFIER
348
 
349
    This routine prints the declaration specifier n to the buffer bf.  The
350
    C and C++ linkage specifiers are not included.
351
*/
352
 
7 7u83 353
int
354
print_dspec(DECL_SPEC n, BUFFER *bf, int sp)
2 7u83 355
{
7 7u83 356
	if (n & dspec_typedef) {
357
		sp = print_lex(lex_typedef, bf, sp);
358
	}
359
	if (n & dspec_storage) {
360
		if (n & dspec_extern) {
361
			sp = print_lex(lex_extern, bf, sp);
362
		}
363
		if (n & dspec_static) {
364
			sp = print_lex(lex_static, bf, sp);
365
		}
366
		if (n & dspec_register) {
367
			sp = print_lex(lex_register, bf, sp);
368
		}
369
		if (n & dspec_auto) {
370
			sp = print_lex(lex_auto, bf, sp);
371
		}
372
		if (n & dspec_mutable) {
373
			sp = print_lex(lex_mutable, bf, sp);
374
		}
375
	}
376
	if (n & dspec_function) {
377
		if (n & dspec_explicit) {
378
			sp = print_lex(lex_explicit, bf, sp);
379
		}
380
		if (n & dspec_friend) {
381
			sp = print_lex(lex_friend, bf, sp);
382
		}
383
		if (n & dspec_inline) {
384
			sp = print_lex(lex_inline, bf, sp);
385
		}
386
		if (n & dspec_virtual) {
387
			sp = print_lex(lex_virtual, bf, sp);
388
		}
389
	}
390
	return (sp);
2 7u83 391
}
392
 
393
 
394
/*
395
    PRINT A LINKAGE SPECIFIER
396
 
397
    This routine prints the linkage specifier n to the buffer bf.
398
*/
399
 
7 7u83 400
static int
401
print_linkage(CV_SPEC n, BUFFER *bf, int sp)
2 7u83 402
{
7 7u83 403
	CV_SPEC m = (n & cv_language);
404
	if (m) {
405
		if (m != cv_cpp && !print_c_style) {
406
			string s = linkage_string(dspec_none, m);
407
			if (sp) {
408
				bfputc(bf, ' ');
409
			}
410
			bfprintf(bf, "extern \"%s\"", s);
411
			sp = 1;
412
		}
2 7u83 413
	}
7 7u83 414
	return (sp);
2 7u83 415
}
416
 
417
 
418
/*
419
    PRINT A BUFFER LOCATION
420
 
421
    This routine prints the file location p to the buffer bf.  q gives
422
    the main location.  If the file names from p and q match then only
423
    the line number is printed.
424
*/
425
 
7 7u83 426
int
427
print_loc(LOCATION *p, LOCATION *q, BUFFER *bf, int sp)
2 7u83 428
{
7 7u83 429
	string fn;
430
	unsigned long ln;
431
	if (sp) {
432
		bfputc(bf, ' ');
433
	}
434
	if (p == NULL) {
435
		fn = ustrlit("<unknown>");
436
		ln = 0;
2 7u83 437
	} else {
7 7u83 438
		PTR(POSITION)pa = p->posn;
439
		if (IS_NULL_ptr(pa)) {
440
			fn = ustrlit("<unknown>");
441
		} else {
442
			fn = DEREF_string(posn_file(pa));
443
			if (q) {
444
				/* Check previous location */
445
				PTR(POSITION)qa = q->posn;
446
				if (EQ_ptr(qa, pa)) {
447
					fn = NULL;
448
				} else if (!IS_NULL_ptr(qa)) {
449
					string gn = DEREF_string(posn_file(qa));
450
					if (ustreq(gn, fn)) {
451
						fn = NULL;
452
					}
453
				}
454
			}
2 7u83 455
		}
7 7u83 456
		ln = p->line;
2 7u83 457
	}
7 7u83 458
	if (fn) {
459
		bfprintf(bf, "\"%s\"", fn);
460
		if (ln) {
461
			bfprintf(bf, ", line %lu", ln);
462
		}
463
	} else {
464
		bfprintf(bf, "line %lu", ln);
465
	}
466
	return (1);
2 7u83 467
}
468
 
469
 
470
/*
471
    PRINT A HASH TABLE ENTRY
472
 
473
    This routine prints the identifier name corresponding to the hash
474
    table entry p to the buffer bf.
475
*/
476
 
7 7u83 477
int
478
print_hashid(HASHID p, int sep, int anon, BUFFER *bf, int sp)
2 7u83 479
{
7 7u83 480
	unsigned tag;
481
	if (IS_NULL_hashid(p)) {
482
		return (sp);
2 7u83 483
	}
7 7u83 484
	tag = TAG_hashid(p);
485
	ASSERT(ORDER_hashid == 7);
486
	switch (tag) {
487
	case hashid_name_tag:
488
	case hashid_ename_tag: {
489
		/* Simple name */
490
		string s = DEREF_string(hashid_name_etc_text(p));
491
		if (sp) {
492
			bfputc(bf, ' ');
493
		}
494
		bfputs(bf, s);
495
		sp = 1;
496
		break;
497
	}
498
	case hashid_constr_tag:
499
	case hashid_destr_tag: {
500
		/* Class destructor name */
501
		IDENTIFIER tid = DEREF_id(hashid_constr_etc_tid(p));
502
		if (IS_NULL_id(tid)) {
503
			/* Unnamed constructor or destructor */
504
			TYPE t = DEREF_type(hashid_constr_etc_type(p));
505
			if (sep) {
506
				IGNORE print_type(t, bf, sp);
507
				bfprintf(bf, "::");
508
			} else {
509
				if (sp)bfputc(bf, ' ');
510
			}
511
			if (tag == hashid_destr_tag) {
512
				bfputc(bf, '~');
513
			}
514
			sp = print_type(t, bf, 0);
2 7u83 515
		} else {
7 7u83 516
			/* Named constructor or destructor */
517
			static HASHID lastp = NULL_hashid;
518
			if (sep && !EQ_hashid(p, lastp)) {
519
				lastp = p;
520
				tid = DEREF_id(hashid_id(p));
521
				sp = print_id_short(tid, qual_none, bf, sp);
522
				lastp = NULL_hashid;
523
				break;
524
			}
525
			p = DEREF_hashid(id_name(tid));
526
			if (sp) {
527
				bfputc(bf, ' ');
528
			}
529
			if (sep) {
530
				IGNORE print_hashid(p, 0, 1, bf, 0);
531
				bfprintf(bf, "::");
532
			}
533
			if (tag == hashid_destr_tag) {
534
				bfputc(bf, '~');
535
			}
536
			sp = print_hashid(p, 0, 1, bf, 0);
2 7u83 537
		}
7 7u83 538
		break;
2 7u83 539
	}
7 7u83 540
	case hashid_conv_tag: {
541
		/* Overloaded conversion name */
542
		int prt = print_return_type;
543
		TYPE t = DEREF_type(hashid_conv_type(p));
544
		sp = print_lex(lex_operator, bf, sp);
545
		print_return_type = 1;
546
		sp = print_type(t, bf, sp);
547
		print_return_type = prt;
548
		break;
2 7u83 549
	}
7 7u83 550
	case hashid_op_tag: {
551
		/* Overloaded operator name */
552
		int op = DEREF_int(hashid_op_lex(p));
553
		string s = token_name(op);
554
		sp = print_lex(lex_operator, bf, sp);
555
		if (s) {
556
			int c = (int)*s;
557
			if (isalpha(c)) {
558
				bfputc(bf, ' ');
559
			}
560
			bfputs(bf, s);
561
		}
562
		break;
2 7u83 563
	}
7 7u83 564
	case hashid_anon_tag: {
565
		/* Anonymous identifier */
566
		if (anon) {
567
			unsigned long u = DEREF_ulong(hashid_anon_uniq(p));
568
			if (sp) {
569
				bfputc(bf, ' ');
570
			}
571
			if (print_uniq_anon) {
572
				bfprintf(bf, "<anon%x.%lu>", uniq_string, u);
573
			} else {
574
				bfprintf(bf, "<anon%lu>", u);
575
			}
576
			sp = 1;
2 7u83 577
		}
7 7u83 578
		break;
2 7u83 579
	}
7 7u83 580
	}
581
	return (sp);
2 7u83 582
}
583
 
584
 
585
/*
586
    PRINT AN IDENTIFIER (SHORT FORM)
587
 
588
    This routines prints the short form of the identifier id to the buffer bf.
589
*/
590
 
7 7u83 591
int
592
print_id_short(IDENTIFIER id, QUALIFIER qual, BUFFER *bf, int sp)
2 7u83 593
{
7 7u83 594
	if (!IS_NULL_id(id)) {
595
		int sep = 0;
596
		HASHID p = DEREF_hashid(id_name(id));
2 7u83 597
 
7 7u83 598
		/* Print enclosing namespace name */
599
		NAMESPACE ns = DEREF_nspace(id_parent(id));
600
		if (sp) {
601
			bfputc(bf, ' ');
2 7u83 602
		}
7 7u83 603
		if (print_parent_namespace && !print_c_style) {
604
			if (IS_NULL_nspace(ns)) {
605
				if (qual == qual_full || qual == qual_top) {
606
					bfprintf(bf, "::");
607
				}
608
				sep = 1;
609
			} else {
610
				IGNORE print_nspace(ns, qual, 1, bf, 0);
611
			}
612
		}
2 7u83 613
 
7 7u83 614
		/* Print identifier name */
615
		if (IS_hashid_anon(p)) {
616
			/* Print anonymous identifier names */
617
			IDENTIFIER alt = id;
618
			unsigned tag = TAG_id(id);
619
			if (tag == id_token_tag) {
620
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
621
				if (ds & dspec_auto) {
622
					alt = DEREF_id(id_token_alt(id));
623
					tag = id_parameter_tag;
624
				}
625
			}
626
			if (tag == id_parameter_tag) {
627
				/* Parameter names */
628
				unsigned long n = 0;
629
				MEMBER mem = DEREF_member(nspace_last(ns));
630
				id = DEREF_id(id_alias(id));
631
				alt = DEREF_id(id_alias(alt));
632
				while (!IS_NULL_member(mem)) {
633
					IDENTIFIER mid =
634
					    DEREF_id(member_id(mem));
635
					if (!IS_NULL_id(mid)) {
636
						if (EQ_id(mid, id)) {
637
							n = 0;
638
						}
639
						if (EQ_id(mid, alt)) {
640
							n = 0;
641
						}
642
						n++;
643
					}
644
					mem = DEREF_member(member_next(mem));
645
				}
646
				bfprintf(bf, "<param%lu>", n);
647
			} else {
648
				/* Other identifiers */
649
				LOCATION loc;
650
				string fn, fs;
651
				DEREF_loc(id_loc(id), loc);
652
				fs = DEREF_string(posn_file(loc.posn));
653
				fn = ustrrchr(fs, '/');
654
				fn = (fn ? fn + 1 : fs);
655
				bfprintf(bf, "(\"%s\":%lu)", fn, loc.line );
656
			}
657
		} else {
658
			/* Print other identifier names */
659
			IGNORE print_hashid(p, sep, 0, bf, 0);
2 7u83 660
		}
7 7u83 661
		sp = 1;
2 7u83 662
	}
7 7u83 663
	return (sp);
2 7u83 664
}
665
 
666
 
667
/*
668
    PRINT AN IDENTIFIER (LONG FORM)
669
 
670
    This routines prints the long form of the identifier id to the buffer bf.
671
*/
672
 
7 7u83 673
int
674
print_id_long(IDENTIFIER id, QUALIFIER qual, BUFFER *bf, int sp)
2 7u83 675
{
7 7u83 676
	if (!IS_NULL_id(id)) {
677
		int prt = 1;
678
		int key = 0;
679
		TYPE t = NULL_type;
680
		TYPE f = NULL_type;
681
		TOKEN tok = NULL_tok;
682
		GRAPH gr = NULL_graph;
683
		CONST char *desc = NULL;
684
		int full = print_id_desc;
685
		NAMESPACE pns = NULL_nspace;
686
		LIST(TYPE)p = NULL_list(TYPE);
687
		switch (TAG_id(id)) {
688
		case id_keyword_tag:
689
		case id_iso_keyword_tag: {
690
			/* Keywords */
691
			if (full) {
692
				desc = "keyword";
693
			}
694
			break;
2 7u83 695
		}
7 7u83 696
		case id_builtin_tag: {
697
			/* Built-in operators */
698
			t = DEREF_type(id_builtin_ret(id));
699
			p = DEREF_list(id_builtin_ptypes(id));
700
			if (full) {
701
				desc = "built-in";
702
			}
703
			break;
2 7u83 704
		}
7 7u83 705
		case id_obj_macro_tag:
706
		case id_func_macro_tag: {
707
			/* Macros */
708
			if (full) {
709
				desc = "macro";
710
			}
711
			break;
2 7u83 712
		}
7 7u83 713
		case id_predicate_tag: {
714
			/* Predicates */
715
			if (full) {
716
				desc = "predicate";
717
			}
718
			break;
2 7u83 719
		}
7 7u83 720
		case id_class_name_tag:
721
		case id_enum_name_tag: {
722
			/* Class and enumeration names */
723
			f = DEREF_type(id_class_name_etc_defn(id));
724
			key = (full || print_c_style);
725
			break;
2 7u83 726
		}
7 7u83 727
		case id_class_alias_tag:
728
		case id_enum_alias_tag:
729
		case id_type_alias_tag: {
730
			/* Typedef names */
731
			if (full) {
732
				t = DEREF_type(id_class_name_etc_defn(id));
733
				desc = "typedef";
734
			}
735
			break;
2 7u83 736
		}
7 7u83 737
		case id_nspace_name_tag: {
738
			/* Namespace names */
739
			if (full) {
740
				desc = "namespace";
741
			}
742
			break;
2 7u83 743
		}
7 7u83 744
		case id_nspace_alias_tag: {
745
			/* Namespace aliases */
746
			if (full) {
747
				desc = "namespace";
748
				pns = DEREF_nspace(id_nspace_alias_defn(id));
749
			}
750
			break;
2 7u83 751
		}
7 7u83 752
		case id_variable_tag:
753
		case id_parameter_tag: {
754
			/* Object names */
755
			if (full) {
756
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
757
				if (ds & dspec_auto) {
758
					desc = "auto";
759
				}
760
				t = DEREF_type(id_variable_etc_type(id));
761
			}
762
			break;
2 7u83 763
		}
7 7u83 764
		case id_stat_member_tag: {
765
			/* Static members */
766
			if (full) {
767
				t = DEREF_type(id_stat_member_type(id));
768
				desc = "static";
769
			}
770
			break;
2 7u83 771
		}
7 7u83 772
		case id_weak_param_tag: {
773
			if (full) {
774
				desc = "auto";
775
				t = type_sint;
2 7u83 776
			}
7 7u83 777
			break;
2 7u83 778
		}
7 7u83 779
		case id_function_tag:
780
		case id_mem_func_tag: {
781
			/* Function names */
782
			HASHID nm = DEREF_hashid(id_name(id));
783
			switch (TAG_hashid(nm)) {
784
			case hashid_constr_tag:
785
			case hashid_destr_tag:
786
			case hashid_conv_tag: {
787
				/* Inhibit return type */
788
				prt = 0;
789
				break;
790
			}
791
			}
792
			t = DEREF_type(id_function_etc_type(id));
793
			f = DEREF_type(id_function_etc_form(id));
794
			if (!IS_NULL_type(f) && !IS_type_token(f)) {
795
				f = NULL_type;
796
			}
797
			if (full) {
798
				DECL_SPEC ds = DEREF_dspec(id_storage(id));
799
				if (ds & dspec_implicit) {
800
					desc = "implicit";
801
				}
802
			} else {
803
				if (print_c_style) {
804
					t = NULL_type;
805
				}
806
			}
807
			break;
2 7u83 808
		}
7 7u83 809
		case id_stat_mem_func_tag: {
810
			/* Static function member names */
811
			t = DEREF_type(id_stat_mem_func_type(id));
812
			f = DEREF_type(id_stat_mem_func_form(id));
813
			if (!IS_NULL_type(f) && !IS_type_token(f)) {
814
				f = NULL_type;
815
			}
816
			if (full) {
817
				desc = "static";
818
			} else {
819
				if (print_c_style) {
820
					t = NULL_type;
821
				}
822
			}
823
			break;
824
		}
825
		case id_member_tag: {
826
			/* Member names */
827
			gr = DEREF_graph(id_member_base(id));
828
			if (full) {
829
				t = DEREF_type(id_member_type(id));
830
			}
831
			break;
832
		}
833
		case id_enumerator_tag: {
834
			/* Enumerator names */
835
			if (full) {
836
				desc = "enumerator";
837
			}
838
			break;
839
		}
840
		case id_label_tag: {
841
			/* Label names */
842
			if (full) {
843
				int op = DEREF_int(id_label_op(id));
844
				if (op != lex_identifier) {
845
					/* Print kind of label */
846
					sp = print_lex(op, bf, sp);
847
					if (op == lex_case) {
848
						NAT n = find_case_nat(id);
849
						sp = print_nat(n, 0, bf, sp);
850
					}
851
					return (sp);
852
				}
853
				desc = "label";
854
			}
855
			break;
856
		}
857
		case id_token_tag: {
858
			/* Token names */
859
			if (full) {
860
				tok = DEREF_tok(id_token_sort(id));
861
				desc = "token";
862
			}
863
			break;
864
		}
865
		}
866
		if (desc) {
867
			/* Print description */
868
			if (sp) {
869
				bfputc(bf, ' ');
870
			}
871
			bfprintf(bf, desc);
872
			sp = 1;
873
		}
874
		if (!IS_NULL_tok(tok)) {
875
			/* Print token sort */
876
			sp = print_sort(tok, 0, bf, sp);
877
		}
878
		if (!IS_NULL_type(t)) {
879
			/* Print start of identifier type */
880
			print_return_type = prt;
881
			sp = print_head(t, key, bf, sp);
882
			print_return_type = 1;
883
		}
884
		if (IS_NULL_type(f)) {
885
			if (!IS_NULL_graph(gr)) {
886
				sp = print_graph(gr, 1, bf, sp);
887
				print_parent_namespace = 0;
888
			}
889
			sp = print_id_short(id, qual, bf, sp);
890
			print_parent_namespace = 1;
891
		} else {
892
			sp = print_head(f, key, bf, sp);
893
			sp = print_tail(f, bf, sp);
894
		}
895
		if (!IS_NULL_type(t)) {
896
			/* Print end of identifier type */
897
			print_default_args = 1;
898
			sp = print_tail(t, bf, sp);
899
			print_default_args = 0;
900
		}
901
		if (!IS_NULL_list(p)) {
902
			/* Print parameter types */
903
			sp = print_type_list(p, bf, 1);
904
		}
905
		if (!IS_NULL_nspace(pns)) {
906
			/* Print namespace alias definition */
907
			sp = print_lex(lex_assign, bf, sp);
908
			sp = print_nspace(pns, qual_none, 0, bf, sp);
909
		}
2 7u83 910
	}
7 7u83 911
	return (sp);
2 7u83 912
}
913
 
914
 
915
/*
916
    PRINT A NAMESPACE
917
 
918
    This routines prints the namespace ns to the buffer bf.  The argument
919
    pre is true if this a prefix to an identifier and false if the namespace
920
    itself is what is required.
921
*/
922
 
7 7u83 923
int
924
print_nspace(NAMESPACE ns, QUALIFIER qual, int pre, BUFFER *bf, int sp)
2 7u83 925
{
7 7u83 926
	if (!IS_NULL_nspace(ns)) {
927
		IDENTIFIER id = DEREF_id(nspace_name(ns));
928
		switch (TAG_nspace(ns)) {
929
		case nspace_named_tag:
930
		case nspace_ctype_tag: {
931
			/* Named and class namespaces */
932
			if (sp) {
933
				bfputc(bf, ' ');
934
			}
935
			if (IS_id_class_name(id)) {
936
				TYPE t = DEREF_type(id_class_name_defn(id));
937
				if (IS_type_compound(t)) {
938
					int key = 0;
939
					CLASS_TYPE ct;
940
					if (!pre) {
941
						key = print_c_style;
942
					}
943
					ct = DEREF_ctype(type_compound_defn(t));
944
					IGNORE print_ctype(ct, qual, key, bf,
945
							   0);
946
				} else {
947
					IGNORE print_id_short(id, qual, bf, 0);
948
				}
949
			} else {
950
				IGNORE print_id_short(id, qual, bf, 0);
951
			}
952
			if (pre) {
953
				bfprintf(bf, "::");
954
			}
955
			sp = 1;
956
			break;
2 7u83 957
		}
7 7u83 958
		case nspace_unnamed_tag: {
959
			/* Unnamed namespaces */
960
			if (sp) {
961
				bfputc(bf, ' ');
962
			}
963
			ns = DEREF_nspace(id_parent(id));
964
			IGNORE print_nspace(ns, qual, 1, bf, 0);
965
			if (print_uniq_anon) {
966
				bfprintf(bf, "<anon%x>", uniq_string);
967
			} else {
968
				bfprintf(bf, "<anon>");
969
			}
970
			if (pre) {
971
				bfprintf(bf, "::");
972
			}
973
			sp = 1;
974
			break;
2 7u83 975
		}
7 7u83 976
		case nspace_global_tag: {
977
			/* The global namespace */
978
			if (!pre || qual == qual_full || qual == qual_top) {
979
				if (sp) {
980
					bfputc(bf, ' ');
981
				}
982
				bfprintf(bf, "::");
983
				sp = 1;
984
			}
985
			break;
2 7u83 986
		}
7 7u83 987
		default : {
988
			/* Other namespaces */
989
			if (!pre) {
990
				sp = print_id_short(id, qual, bf, sp);
991
			}
992
			break;
993
		}
994
		}
2 7u83 995
	}
7 7u83 996
	return (sp);
2 7u83 997
}
998
 
999
 
1000
/*
1001
    PRINT A GRAPH
1002
 
1003
    This routines prints the graph gr to the buffer bf.  The argument sep is
1004
    true to indicate that a terminal '::' should be included.
1005
*/
1006
 
7 7u83 1007
int
1008
print_graph(GRAPH gr, int sep, BUFFER *bf, int sp)
2 7u83 1009
{
7 7u83 1010
	if (!IS_NULL_graph(gr)) {
1011
		CLASS_TYPE ct = DEREF_ctype(graph_head(gr));
1012
		GRAPH gs = DEREF_graph(graph_up(gr));
1013
		if (sp) {
1014
			bfputc(bf, ' ');
1015
			sp = 0;
1016
		}
1017
		if (!IS_NULL_graph(gs)) {
1018
			IGNORE print_graph(gs, 1, bf, 0);
1019
			print_parent_namespace = 0;
1020
		}
1021
		IGNORE print_ctype(ct, qual_none, 0, bf, 0);
1022
		print_parent_namespace = 1;
1023
		if (sep) {
1024
			bfprintf(bf, "::");
1025
		}
2 7u83 1026
	}
7 7u83 1027
	return (sp);
2 7u83 1028
}
1029
 
1030
 
1031
/*
1032
    PRINT A PREPROCESSING TOKEN
1033
 
1034
    This routine prints the preprocessing token p to the buffer bf.  It
1035
    is used not only in the error reporting routines, but also in the
1036
    preprocessing action.
1037
*/
1038
 
7 7u83 1039
int
1040
print_pptok(PPTOKEN *p, BUFFER *bf, int sp)
2 7u83 1041
{
7 7u83 1042
	int q;
1043
	int t = p->tok;
1044
	if (sp) {
1045
		bfputc(bf, ' ');
2 7u83 1046
	}
7 7u83 1047
	switch (t) {
1048
	case lex_identifier:
1049
	case lex_type_Hname:
1050
	case lex_namespace_Hname:
1051
	case lex_statement_Hname:
1052
identifier_label: {
1053
			  /* Identifiers */
1054
			  HASHID nm = p->pp_data.id.hash;
1055
			  string s = DEREF_string(hashid_name_etc_text(nm));
1056
			  bfputs(bf, s);
1057
			  break;
1058
		  }
1059
	case lex_destructor_Hname: {
1060
		/* Destructor names */
1061
		bfputc(bf, '~');
1062
		goto identifier_label;
2 7u83 1063
	}
7 7u83 1064
	case lex_template_Hid:
1065
	case lex_template_Htype: {
1066
		/* Template names */
1067
		IDENTIFIER id = p->pp_data.tok.id;
1068
		IGNORE print_id_short(id, qual_none, bf, 0);
1069
		break;
2 7u83 1070
	}
7 7u83 1071
	case lex_integer_Hlit: {
1072
		/* Integer and floating point literals */
1073
		string s = p->pp_data.text;
1074
		bfputs(bf, s);
1075
		break;
2 7u83 1076
	}
7 7u83 1077
	case lex_char_Hlit: {
1078
		/* Character literals */
1079
		q = '\'';
1080
string_label: {
1081
		      string s = p->pp_data.str.start;
1082
		      string e = p->pp_data.str.end;
1083
		      bfputc(bf, q);
1084
		      while (s != e) {
1085
			      bfputc(bf,(int)*s);
1086
			      s++;
1087
		      }
1088
		      bfputc(bf, q);
1089
	      }
1090
	      break;
2 7u83 1091
	}
7 7u83 1092
	case lex_wchar_Hlit: {
1093
		/* Wide character literals */
1094
		bfputc(bf, 'L');
1095
		q = '\'';
1096
		goto string_label;
2 7u83 1097
	}
7 7u83 1098
	case lex_string_Hlit: {
1099
		/* String literals */
1100
		q = '"';
1101
		goto string_label;
2 7u83 1102
	}
7 7u83 1103
	case lex_wstring_Hlit: {
1104
		/* Wide string literals */
1105
		bfputc(bf, 'L');
1106
		q = '"';
1107
		goto string_label;
2 7u83 1108
	}
7 7u83 1109
	case lex_integer_Hexp:
1110
	case lex_floating_Hexp:
1111
	case lex_char_Hexp:
1112
	case lex_wchar_Hexp:
1113
	case lex_string_Hexp:
1114
	case lex_wstring_Hexp: {
1115
		/* Literal expressions */
1116
		IGNORE print_exp(p->pp_data.exp, 0, bf, 0);
1117
		break;
2 7u83 1118
	}
7 7u83 1119
	case lex_unknown: {
1120
		/* Unknown characters */
1121
		unsigned long u;
1122
		int ch = CHAR_SIMPLE;
1123
		u = get_multi_char(p->pp_data.buff, &ch);
1124
		if (ch == CHAR_SIMPLE) {
1125
			bfputc(bf,(int)u);
1126
		} else {
1127
			print_char(u, ch, 0, bf);
1128
		}
1129
		break;
2 7u83 1130
	}
7 7u83 1131
	case lex_nested_Hname: {
1132
		/* Nested name qualifier */
1133
		NAMESPACE ns = p->pp_data.ns;
1134
		IGNORE print_nspace(ns, qual_nested, 1, bf, 0);
1135
		break;
2 7u83 1136
	}
7 7u83 1137
	case lex_full_Hname: {
1138
		/* Nested name qualifier */
1139
		NAMESPACE ns = p->pp_data.ns;
1140
		IGNORE print_nspace(ns, qual_full, 1, bf, 0);
1141
		break;
2 7u83 1142
	}
7 7u83 1143
	case lex_nested_Hname_Hstar: {
1144
		/* Nested member qualifier */
1145
		IDENTIFIER id = p->pp_data.id.use;
1146
		IGNORE print_id_short(id, qual_nested, bf, 0);
1147
		bfprintf(bf, "::*");
1148
		break;
2 7u83 1149
	}
7 7u83 1150
	case lex_full_Hname_Hstar: {
1151
		/* Nested member qualifier */
1152
		IDENTIFIER id = p->pp_data.id.use;
1153
		IGNORE print_id_short(id, qual_full, bf, 0);
1154
		bfprintf(bf, "::*");
1155
		break;
2 7u83 1156
	}
7 7u83 1157
	case lex_complex_Hexp:
1158
	case lex_complex_Htype: {
1159
		/* Token applications etc. */
1160
		IDENTIFIER id = p->pp_data.tok.id;
1161
		IGNORE print_id_short(id, qual_none, bf, 0);
1162
		break;
2 7u83 1163
	}
7 7u83 1164
	case lex_macro_Harg: {
1165
		/* Macro parameters */
1166
		HASHID nm = p->pp_data.par.hash;
1167
		string s = DEREF_string(hashid_name_etc_text(nm));
1168
		bfputs(bf, s);
1169
		break;
2 7u83 1170
	}
1171
	default : {
7 7u83 1172
		/* Simple token */
1173
		if (t >= 0) {
1174
			string s = token_name(t);
1175
			bfputs(bf, s);
1176
		} else {
1177
			bfprintf(bf, "<ignore>");
1178
		}
1179
		break;
2 7u83 1180
	}
7 7u83 1181
	}
1182
	return (1);
2 7u83 1183
}
1184
 
1185
 
1186
/*
1187
    INTEGER LITERAL PRINTING
1188
 
1189
    This prints an integer literal to the buffer bf.  The only difficult case
1190
    is when a large literal will not fit into an unsigned long.  The digits
1191
    need to be printed in reverse order, and it is again quickest to reverse
1192
    the order of the list twice.
1193
*/
1194
 
7 7u83 1195
int
1196
print_nat(NAT n, int paren, BUFFER *bf, int sp)
2 7u83 1197
{
7 7u83 1198
	if (!IS_NULL_nat(n)) {
1199
		ASSERT(ORDER_nat == 5);
1200
		switch (TAG_nat(n)) {
1201
		case nat_small_tag: {
1202
			/* Small values */
1203
			unsigned v = DEREF_unsigned(nat_small_value(n));
1204
			if (sp) {
1205
				bfputc(bf, ' ');
1206
			}
1207
			bfprintf(bf, "%u", v);
1208
			sp = 1;
1209
			break;
2 7u83 1210
		}
7 7u83 1211
		case nat_large_tag: {
1212
			/* Large values */
1213
			LIST(unsigned)p;
1214
			p = DEREF_list(nat_large_values(n));
1215
			if (sp) {
1216
				bfputc(bf, ' ');
1217
			}
1218
			if (LENGTH_list(p) <= 2) {
1219
				/* Two digit literals will fit into a unsigned
1220
				 * long */
1221
				unsigned long v = get_nat_value(n);
1222
				bfprintf(bf, "%lu", v);
1223
			} else {
1224
				/* Print large literals by scanning through
1225
				 * digits */
1226
				char buff[50];
1227
				CONST char *fmt = "0x%x";
1228
				LIST(unsigned)q;
1229
				p = REVERSE_list(p);
1230
				q = p;
1231
				while (!IS_NULL_list(q)) {
1232
					unsigned v =
1233
					    DEREF_unsigned(HEAD_list(q));
1234
					sprintf_v(buff, fmt, v);
1235
					bfputs(bf, ustrlit(buff));
1236
					fmt = "%04x";
1237
					q = TAIL_list(q);
1238
				}
1239
				IGNORE REVERSE_list(p);
1240
			}
1241
			sp = 1;
1242
			break;
2 7u83 1243
		}
7 7u83 1244
		case nat_calc_tag: {
1245
			/* Calculated values */
1246
			EXP e = DEREF_exp(nat_calc_value(n));
1247
			while (!IS_NULL_exp(e) && IS_exp_cast(e)) {
1248
				e = DEREF_exp(exp_cast_arg(e));
1249
			}
1250
			sp = print_exp(e, paren, bf, sp);
1251
			break;
1252
		}
1253
		case nat_neg_tag: {
1254
			/* Negative values */
1255
			NAT m = DEREF_nat(nat_neg_arg(n));
1256
			if (sp) {
1257
				bfputc(bf, ' ');
1258
			}
1259
			bfputc(bf, '-');
1260
			IGNORE print_nat(m, 1, bf, 0);
1261
			break;
1262
		}
1263
		case nat_token_tag: {
1264
			IDENTIFIER id = DEREF_id(nat_token_tok(n));
1265
			LIST(TOKEN)args = DEREF_list(nat_token_args(n));
1266
			sp = print_token(id, qual_none, args, bf, sp);
1267
			break;
1268
		}
1269
		}
2 7u83 1270
	}
7 7u83 1271
	return (sp);
2 7u83 1272
}
1273
 
1274
 
1275
/*
1276
    FLOATING-POINT LITERAL PRINTING
1277
 
1278
    This routine prints a floating-point literal to the buffer bf.
1279
*/
1280
 
7 7u83 1281
int
1282
print_flt(FLOAT n, BUFFER *bf, int sp)
2 7u83 1283
{
7 7u83 1284
	if (!IS_NULL_flt(n)) {
1285
		string i = DEREF_string(flt_simple_int_part(n));
1286
		string d = DEREF_string(flt_simple_frac_part(n));
1287
		NAT e = DEREF_nat(flt_simple_exponent(n));
1288
		if (sp) {
1289
			bfputc(bf, ' ');
1290
		}
1291
		bfprintf(bf, "%s.%s", i, d);
1292
		if (!is_zero_nat(e)) {
1293
			bfputc(bf, 'e');
1294
			IGNORE print_nat(e, 0, bf, 0);
1295
		}
1296
		sp = 1;
2 7u83 1297
	}
7 7u83 1298
	return (sp);
2 7u83 1299
}
1300
 
1301
 
1302
/*
1303
    CHARACTER PRINTING
1304
 
1305
    This routine prints the character c to the buffer bf as a string
1306
    character of type ch enclosed by the quote character q.
1307
*/
1308
 
7 7u83 1309
void
1310
print_char(unsigned long c, int ch, int q, BUFFER *bf)
2 7u83 1311
{
7 7u83 1312
	char buff[20];
1313
	if (ch == CHAR_SIMPLE) {
1314
		switch (c) {
1315
		case char_alert:
1316
			bfprintf(bf, "\\a");
1317
			break;
1318
		case char_backspace:
1319
			bfprintf(bf, "\\b");
1320
			break;
1321
		case char_form_feed:
1322
			bfprintf(bf, "\\f");
1323
			break;
1324
		case char_newline:
1325
			bfprintf(bf, "\\n");
1326
			break;
1327
		case char_return:
1328
			bfprintf(bf, "\\r");
1329
			break;
1330
		case char_tab:
1331
			bfprintf(bf, "\\t");
1332
			break;
1333
		case char_vert_tab:
1334
			bfprintf(bf, "\\v");
1335
			break;
2 7u83 1336
 
7 7u83 1337
		case char_backslash:
1338
		case char_question: {
1339
			if (q) {
1340
				bfputc(bf, '\\');
1341
			}
1342
			bfputc(bf,(int)c);
1343
			break;
1344
		}
2 7u83 1345
 
7 7u83 1346
		case char_quote:
1347
		case char_single_quote: {
1348
			int a = (int)c;
1349
			if (a == q) {
1350
				bfputc(bf, '\\');
1351
			}
1352
			bfputc(bf, a);
1353
			break;
1354
		}
2 7u83 1355
 
7 7u83 1356
		default : {
1357
			int a = (int)c;
1358
			if (isprint(a)) {
1359
				bfputc(bf, a);
1360
			} else {
1361
				sprintf_v(buff, "\\%03lo", c );
1362
				bfputs(bf, ustrlit(buff));
1363
			}
1364
			break;
2 7u83 1365
		}
7 7u83 1366
		}
1367
	} else {
1368
		CONST char *fmt;
1369
		switch (ch) {
1370
		case CHAR_OCTAL:
1371
			fmt = "\\%03lo";
1372
			break;
1373
		case CHAR_UNI4:
1374
			fmt = "\\u%04lx";
1375
			break;
1376
		case CHAR_UNI8:
1377
			fmt = "\\U%08lx";
1378
			break;
1379
		default:
1380
			fmt = "\\x%lx";
1381
			break;
1382
		}
1383
		sprintf_v(buff, fmt, c);
1384
		bfputs(bf, ustrlit(buff));
2 7u83 1385
	}
7 7u83 1386
	return;
2 7u83 1387
}
1388
 
1389
 
1390
/*
1391
    STRING LITERAL PRINTING
1392
 
1393
    This routine prints a string or character literal to the buffer bf.
1394
*/
1395
 
7 7u83 1396
int
1397
print_str(STRING s, BUFFER *bf, int sp)
2 7u83 1398
{
7 7u83 1399
	string text;
1400
	int q = '"';
1401
	unsigned kind;
1402
	unsigned long i, len;
2 7u83 1403
 
7 7u83 1404
	if (IS_NULL_str(s)) {
1405
		return (sp);
1406
	}
2 7u83 1407
 
7 7u83 1408
	/* Print the opening quote */
1409
	if (sp) {
1410
		bfputc(bf, ' ');
1411
	}
1412
	kind = DEREF_unsigned(str_simple_kind(s));
1413
	if (kind & STRING_CHAR) {
1414
		q = '\'';
1415
	}
1416
	if (kind & STRING_WIDE) {
1417
		bfputc(bf, 'L');
1418
	}
2 7u83 1419
 
7 7u83 1420
	/* Print the string text */
1421
	text = DEREF_string(str_simple_text(s));
1422
	len = DEREF_ulong(str_simple_len(s));
1423
	bfputc(bf, q);
1424
	if (kind & STRING_MULTI) {
1425
		/* Multi-byte strings */
1426
		for (i = 0; i < len; i++) {
1427
			int ch = CHAR_SIMPLE;
1428
			unsigned long c = get_multi_char(text, &ch);
1429
			print_char(c, ch, q, bf);
1430
			text += MULTI_WIDTH;
1431
		}
1432
	} else {
1433
		/* Simple strings */
1434
		for (i = 0; i < len; i++) {
1435
			unsigned long c = (unsigned long)text[i];
1436
			print_char(c, CHAR_SIMPLE, q, bf);
1437
		}
2 7u83 1438
	}
7 7u83 1439
	bfputc(bf, q);
1440
	return (1);
2 7u83 1441
}
1442
 
1443
 
1444
/*
1445
    EXPRESSION PRINTING
1446
 
1447
    This routine prints an expression to the buffer bf.
1448
*/
1449
 
7 7u83 1450
int
1451
print_exp(EXP e, int paren, BUFFER *bf, int sp)
2 7u83 1452
{
7 7u83 1453
	if (!IS_NULL_exp(e)) {
1454
		switch (TAG_exp(e)) {
1455
		case exp_identifier_tag:
1456
		case exp_member_tag:
1457
		case exp_ambiguous_tag:
1458
		case exp_undeclared_tag: {
1459
			IDENTIFIER id = DEREF_id(exp_identifier_etc_id(e));
1460
			QUALIFIER q = DEREF_qual(exp_identifier_etc_qual(e));
1461
			q &= qual_explicit;
1462
			sp = print_id_short(id, q, bf, sp);
1463
			break;
1464
		}
1465
		case exp_int_lit_tag: {
1466
			NAT n = DEREF_nat(exp_int_lit_nat(e));
1467
			sp = print_nat(n, paren, bf, sp);
1468
			break;
1469
		}
1470
		case exp_float_lit_tag: {
1471
			FLOAT flt = DEREF_flt(exp_float_lit_flt(e));
1472
			sp = print_flt(flt, bf, sp);
1473
			break;
1474
		}
1475
		case exp_char_lit_tag: {
1476
			STRING s = DEREF_str(exp_char_lit_str(e));
1477
			sp = print_str(s, bf, sp);
1478
			break;
1479
		}
1480
		case exp_string_lit_tag: {
1481
			STRING s = DEREF_str(exp_string_lit_str(e));
1482
			sp = print_str(s, bf, sp);
1483
			break;
1484
		}
1485
		case exp_null_tag:
1486
		case exp_zero_tag:
1487
		case exp_value_tag: {
1488
			if (sp) {
1489
				bfputc(bf, ' ');
1490
			}
1491
			bfputc(bf, '0');
1492
			break;
1493
		}
1494
		case exp_contents_tag: {
1495
			EXP a = DEREF_exp(exp_contents_ptr(e));
1496
			sp = print_exp(a, 0, bf, sp);
1497
			break;
1498
		}
1499
		case exp_token_tag: {
1500
			IDENTIFIER id = DEREF_id(exp_token_tok(e));
1501
			LIST(TOKEN)args = DEREF_list(exp_token_args(e));
1502
			sp = print_token(id, qual_none, args, bf, sp);
1503
			break;
1504
		}
1505
		default: {
1506
			static unsigned long exp_no = 0;
2 7u83 1507
#ifdef RUNTIME
7 7u83 1508
			if (debugging) {
1509
				/* Debug expression printing routine */
1510
				sp = print_exp_aux(e, paren, bf, sp);
1511
				break;
1512
			}
1513
#endif
1514
			if (sp) {
1515
				bfputc(bf, ' ');
1516
			}
1517
			bfprintf(bf, "<exp%lu>", ++exp_no);
1518
			sp = 1;
1519
			break;
2 7u83 1520
		}
7 7u83 1521
		}
2 7u83 1522
	}
7 7u83 1523
	return (sp);
2 7u83 1524
}
1525
 
1526
 
1527
/*
1528
    TOKEN VALUE PRINTING
1529
 
1530
    This routine prints the value of the token tok to the buffer bf.
1531
*/
1532
 
7 7u83 1533
int
1534
print_tok_value(TOKEN tok, BUFFER *bf, int sp)
2 7u83 1535
{
7 7u83 1536
	if (!IS_NULL_tok(tok)) {
1537
		ASSERT(ORDER_tok == 10);
1538
		switch (TAG_tok(tok)) {
1539
		case tok_exp_tag: {
1540
			EXP e = DEREF_exp(tok_exp_value(tok));
1541
			sp = print_exp(e, 0, bf, sp);
1542
			break;
1543
		}
1544
		case tok_stmt_tag: {
1545
			EXP e = DEREF_exp(tok_stmt_value(tok));
1546
			sp = print_exp(e, 0, bf, sp);
1547
			break;
1548
		}
1549
		case tok_nat_tag:
1550
		case tok_snat_tag: {
1551
			NAT n = DEREF_nat(tok_nat_etc_value(tok));
1552
			sp = print_nat(n, 0, bf, sp);
1553
			break;
1554
		}
1555
		case tok_type_tag: {
1556
			TYPE t = DEREF_type(tok_type_value(tok));
1557
			sp = print_type(t, bf, sp);
1558
			break;
1559
		}
1560
		case tok_member_tag: {
1561
			OFFSET off = DEREF_off(tok_member_value(tok));
1562
			sp = print_offset(off, bf, sp);
1563
			break;
1564
		}
1565
		case tok_class_tag: {
1566
			IDENTIFIER cid = DEREF_id(tok_class_value(tok));
1567
			sp = print_id_short(cid, qual_none, bf, sp);
1568
			break;
1569
		}
1570
		default : {
1571
			if (sp)bfputc(bf, ' ');
1572
			bfprintf(bf, "<arg>");
1573
			sp = 1;
1574
			break;
1575
		}
1576
		}
2 7u83 1577
	}
7 7u83 1578
	return (sp);
2 7u83 1579
}
1580
 
1581
 
1582
/*
1583
    TOKEN APPLICATION PRINTING
1584
 
1585
    This routine prints the token application 'id ( args )' or the template
1586
    application 'id < args >' to the buffer bf.
1587
*/
1588
 
7 7u83 1589
int
1590
print_token(IDENTIFIER id, QUALIFIER qual, LIST(TOKEN)args, BUFFER *bf, int sp)
2 7u83 1591
{
7 7u83 1592
	int open_bracket = 0;
1593
	int close_bracket = 0;
1594
	if (IS_id_token(id)) {
1595
		/* Token application */
1596
		TOKEN tok = DEREF_tok(id_token_sort(id));
1597
		unsigned tag = TAG_tok(tok);
1598
		IDENTIFIER alt = DEREF_id(id_token_alt(id));
1599
		if (!IS_NULL_id(alt)) {
1600
			id = alt;
1601
		}
1602
		if (tag == tok_proc_tag || !IS_NULL_list(args)) {
1603
			open_bracket = '(';
1604
			close_bracket = ')';
1605
		} else if (tag == tok_class_tag) {
1606
			open_bracket = '<';
1607
			close_bracket = '>';
1608
		}
1609
	} else {
1610
		/* Template application */
1611
		open_bracket = '<';
1612
		close_bracket = '>';
2 7u83 1613
	}
7 7u83 1614
	sp = print_id_short(id, qual, bf, sp);
1615
	if (open_bracket) {
1616
		int first = 1;
1617
		bfputc(bf, ' ');
1618
		bfputc(bf, open_bracket);
1619
		while (!IS_NULL_list(args)) {
1620
			TOKEN ptok = DEREF_tok(HEAD_list(args));
1621
			if (!IS_NULL_tok(ptok)) {
1622
				if (!first) {
1623
					bfputc(bf, ',');
1624
				}
1625
				IGNORE print_tok_value(ptok, bf, 1);
1626
				first = 0;
1627
			}
1628
			args = TAIL_list(args);
1629
		}
1630
		if (!first) {
1631
			bfputc(bf, ' ');
1632
		}
1633
		bfputc(bf, close_bracket);
1634
		sp = 1;
2 7u83 1635
	}
7 7u83 1636
	return (sp);
2 7u83 1637
}
1638
 
1639
 
1640
/*
1641
    TOKEN SORT PRINTING
1642
 
1643
    This routine prints the token sort tok to the buffer bf.
1644
*/
1645
 
7 7u83 1646
int
1647
print_sort(TOKEN tok, int arg, BUFFER *bf, int sp)
2 7u83 1648
{
7 7u83 1649
	unsigned tag;
1650
	if (IS_NULL_tok(tok)) {
1651
		return (sp);
1652
	}
1653
	tag = TAG_tok(tok);
1654
	ASSERT(ORDER_tok == 10);
1655
	switch (tag) {
1656
	case tok_exp_tag: {
1657
		/* Expression tokens */
1658
		sp = print_lex(lex_exp_Hcap, bf, sp);
1659
		if (!arg) {
1660
			TYPE t = DEREF_type(tok_exp_type(tok));
1661
			CV_SPEC cv = DEREF_cv(type_qual(t));
1662
			if (cv & cv_lvalue) {
1663
				IGNORE print_lex(lex_lvalue, bf, sp);
1664
			} else {
1665
				int c = DEREF_int(tok_exp_constant(tok));
1666
				if (c) {
1667
					IGNORE print_lex(lex_const, bf, sp);
1668
				}
1669
			}
1670
			bfprintf(bf, " :");
1671
			IGNORE print_type(t, bf, 1);
1672
			bfprintf(bf, " :");
1673
			sp = 1;
1674
		}
1675
		break;
1676
	}
2 7u83 1677
 
7 7u83 1678
	case tok_nat_tag: {
1679
		/* Integer constant tokens */
1680
		if (arg) {
1681
			sp = print_lex(lex_exp_Hcap, bf, sp);
2 7u83 1682
		} else {
7 7u83 1683
			sp = print_lex(lex_nat_Hcap, bf, sp);
2 7u83 1684
		}
7 7u83 1685
		break;
2 7u83 1686
	}
1687
 
7 7u83 1688
	case tok_snat_tag: {
1689
		/* Integer constant tokens */
1690
		if (arg) {
1691
			sp = print_lex(lex_exp_Hcap, bf, sp);
1692
		} else {
1693
			sp = print_lex(lex_int_Hcap, bf, sp);
1694
		}
1695
		break;
2 7u83 1696
	}
1697
 
7 7u83 1698
	case tok_stmt_tag: {
1699
		/* Statement tokens */
1700
		sp = print_lex(lex_stmt_Hcap, bf, sp);
1701
		break;
2 7u83 1702
	}
1703
 
7 7u83 1704
	case tok_type_tag: {
1705
		/* Type tokens */
1706
		if (arg) {
1707
			sp = print_lex(lex_type_Hcap, bf, sp);
1708
		} else {
1709
			BASE_TYPE bt = DEREF_btype(tok_type_kind(tok));
1710
			int key = type_token_key(bt);
1711
			if (key == lex_signed || key == lex_unsigned) {
1712
				sp = print_lex(lex_variety_Hcap, bf, sp);
1713
			}
1714
			sp = print_lex(key, bf, sp);
1715
		}
1716
		break;
2 7u83 1717
	}
1718
 
7 7u83 1719
	case tok_func_tag: {
1720
		/* Function tokens */
1721
		if (arg) {
1722
			sp = print_lex(lex_proc_Hcap, bf, sp);
1723
		} else {
1724
			TYPE t = DEREF_type(tok_func_type(tok));
1725
			IGNORE print_lex(lex_func_Hcap, bf, sp);
1726
			IGNORE print_type(t, bf, 1);
1727
			bfprintf(bf, " :");
1728
			sp = 1;
2 7u83 1729
		}
7 7u83 1730
		break;
2 7u83 1731
	}
1732
 
7 7u83 1733
	case tok_member_tag: {
1734
		/* Member tokens */
1735
		TYPE s = DEREF_type(tok_member_of(tok));
1736
		IGNORE print_lex(lex_member_Hcap, bf, sp);
1737
		if (!arg) {
1738
			TYPE t = DEREF_type(tok_member_type(tok));
1739
			print_bitfield_sep = '%';
1740
			IGNORE print_type(t, bf, 1);
1741
			print_bitfield_sep = ':';
1742
			bfprintf(bf, " :");
1743
		}
1744
		IGNORE print_type(s, bf, 1);
1745
		bfprintf(bf, " :");
1746
		sp = 1;
1747
		break;
2 7u83 1748
	}
1749
 
7 7u83 1750
	case tok_class_tag: {
1751
		/* Template class tokens */
1752
		TYPE t = DEREF_type(tok_class_type(tok));
1753
		while (!IS_NULL_type(t) && IS_type_templ(t)) {
1754
			TOKEN sort = DEREF_tok(type_templ_sort(t));
1755
			sp = print_sort(sort, 0, bf, sp);
1756
			t = DEREF_type(type_templ_defn(t));
1757
		}
1758
		sp = print_lex(lex_class, bf, sp);
1759
		break;
2 7u83 1760
	}
1761
 
7 7u83 1762
	case tok_proc_tag: {
1763
		/* Procedure tokens */
1764
		TOKEN res;
1765
		int simple = 0;
1766
		LIST(IDENTIFIER)p, q;
1767
		sp = print_lex(lex_proc_Hcap, bf, sp);
1768
		if (arg) {
1769
			break;
2 7u83 1770
		}
7 7u83 1771
		res = DEREF_tok(tok_proc_res(tok));
1772
		p = DEREF_list(tok_proc_pids(tok));
1773
		q = DEREF_list(tok_proc_bids(tok));
1774
		if (EQ_list(p, q)) {
1775
			simple = 1;
1776
		}
1777
		if (simple) {
1778
			bfprintf(bf, " (");
1779
		} else {
1780
			bfprintf(bf, " {");
1781
		}
1782
		sp = 0;
1783
		while (!IS_NULL_list(q)) {
1784
			IDENTIFIER id = DEREF_id(HEAD_list(q));
1785
			if (!IS_NULL_id(id)) {
1786
				TOKEN par = DEREF_tok(id_token_sort(id));
1787
				if (sp) {
1788
					bfputc(bf, ',');
1789
				}
1790
				IGNORE print_sort(par, 0, bf, 1);
1791
				if (!simple) {
1792
					HASHID nm = DEREF_hashid(id_name(id));
1793
					IGNORE print_hashid(nm, 0, 0, bf, 1);
1794
				}
1795
				sp = 1;
2 7u83 1796
			}
7 7u83 1797
			q = TAIL_list(q);
2 7u83 1798
		}
7 7u83 1799
		if (simple) {
1800
			if (sp) {
1801
				bfputc(bf, ' ');
1802
			}
1803
			bfputc(bf, ')');
1804
		} else {
1805
			bfprintf(bf, " |");
1806
			sp = 0;
1807
			while (!IS_NULL_list(p)) {
1808
				IDENTIFIER id = DEREF_id(HEAD_list(p));
1809
				if (!IS_NULL_id(id)) {
1810
					if (sp) {
1811
						bfputc(bf, ',');
1812
					}
1813
					if (IS_id_token(id)) {
1814
						/* Simple token parameter */
1815
						HASHID nm =
1816
						    DEREF_hashid(id_name(id));
1817
						TOKEN par = DEREF_tok(id_token_sort(id));
1818
						IGNORE print_sort(par, 1, bf,
1819
								  1);
1820
						IGNORE print_hashid(nm, 0, 0,
1821
								    bf, 1);
1822
					} else {
1823
						/* Complex type parameter */
1824
						TYPE r;
1825
						r = DEREF_type(id_class_name_etc_defn(id));
1826
						IGNORE print_lex(lex_type_Hcap,
1827
								 bf, 1);
1828
						IGNORE print_type(r, bf, 1);
1829
					}
1830
					sp = 1;
1831
				}
1832
				p = TAIL_list(p);
1833
			}
1834
			bfprintf(bf, " }");
1835
		}
1836
		sp = print_sort(res, 0, bf, 1);
1837
		break;
2 7u83 1838
	}
1839
 
7 7u83 1840
	case tok_templ_tag: {
1841
		/* Template tokens */
1842
		LIST(TOKEN)q;
1843
		LIST(IDENTIFIER)p;
1844
		DECL_SPEC ex = DEREF_dspec(tok_templ_usage(tok));
1845
		NAMESPACE ns = DEREF_nspace(tok_templ_pars(tok));
1846
		if (ex & dspec_extern) {
1847
			/* Exported templates */
1848
			sp = print_lex(lex_export, bf, sp);
2 7u83 1849
		}
7 7u83 1850
		IGNORE print_lex(lex_template, bf, sp);
1851
		if (IS_NULL_nspace(ns)) {
1852
			sp = 1;
1853
			break;
2 7u83 1854
		}
7 7u83 1855
		p = DEREF_list(tok_templ_pids(tok));
1856
		q = DEREF_list(tok_templ_dargs(tok));
1857
		bfprintf(bf, " <");
1858
		sp = 0;
1859
		while (!IS_NULL_list(p)) {
1860
			TOKEN val = NULL_tok;
1861
			IDENTIFIER id = DEREF_id(HEAD_list(p));
1862
			HASHID nm = DEREF_hashid(id_name(id));
1863
			if (!IS_NULL_list(q)) {
1864
				val = DEREF_tok(HEAD_list(q));
1865
				q = TAIL_list(q);
1866
			}
1867
			tok = DEREF_tok(id_token_sort(id));
1868
			tag = TAG_tok(tok);
1869
			if (tag == tok_exp_tag) {
1870
				TYPE t = DEREF_type(tok_exp_type(tok));
1871
				int sp2 = print_head(t, 0, bf, 1);
1872
				sp2 = print_hashid(nm, 0, 0, bf, sp2);
1873
				IGNORE print_tail(t, bf, sp2);
1874
			} else if (tag == tok_type_tag) {
1875
				IGNORE print_lex(lex_class, bf, 1);
1876
				IGNORE print_hashid(nm, 0, 0, bf, 1);
1877
			} else {
1878
				IGNORE print_sort(tok, 0, bf, 1);
1879
				IGNORE print_hashid(nm, 0, 0, bf, 1);
1880
			}
1881
			if (!IS_NULL_tok(val)) {
1882
				bfprintf(bf, " =");
1883
				IGNORE print_tok_value(val, bf, 1);
1884
			}
1885
			p = TAIL_list(p);
1886
			if (!IS_NULL_list(p)) {
1887
				bfputc(bf, ',');
1888
			}
1889
			sp = 1;
2 7u83 1890
		}
7 7u83 1891
		if (sp) {
1892
			bfputc(bf, ' ');
1893
		}
1894
		bfputc(bf, '>');
1895
		sp = 1;
1896
		break;
2 7u83 1897
	}
7 7u83 1898
	}
1899
	return (sp);
2 7u83 1900
}
1901
 
1902
 
1903
/*
1904
    INTEGRAL TYPE PRINTING
1905
 
1906
    This routine prints an integral type to the buffer bf.  Note that the
1907
    standard full forms, such as 'signed short int', are translated into
1908
    shorter forms, such as 'short'.
1909
*/
1910
 
7 7u83 1911
int
1912
print_itype(INT_TYPE t, BUFFER *bf, int sp)
2 7u83 1913
{
7 7u83 1914
	if (!IS_NULL_itype(t)) {
1915
		ASSERT(ORDER_itype == 6);
1916
		switch (TAG_itype(t)) {
1917
		case itype_basic_tag: {
1918
			BUILTIN_TYPE n = DEREF_ntype(itype_basic_no(t));
1919
			sp = print_ntype(n, bf, sp);
1920
			break;
2 7u83 1921
		}
7 7u83 1922
		case itype_bitfield_tag: {
1923
			BASE_TYPE bt = DEREF_btype(itype_bitfield_rep(t));
1924
			if (bt & btype_named) {
1925
				TYPE s = DEREF_type(itype_bitfield_sub(t));
1926
				sp = print_type(s, bf, sp);
1927
			} else {
1928
				sp = print_btype(bt, bf, sp);
1929
			}
1930
			break;
2 7u83 1931
		}
7 7u83 1932
		case itype_promote_tag: {
1933
			INT_TYPE s = DEREF_itype(itype_promote_arg(t));
1934
			if (sp) {
1935
				bfputc(bf, ' ');
1936
			}
1937
			bfprintf(bf, "%s ( ", special_name(TOK_promote));
1938
			IGNORE print_itype(s, bf, 0);
1939
			bfprintf(bf, " )");
1940
			sp = 1;
1941
			break;
1942
		}
1943
		case itype_arith_tag: {
1944
			INT_TYPE s1 = DEREF_itype(itype_arith_arg1(t));
1945
			INT_TYPE s2 = DEREF_itype(itype_arith_arg2(t));
1946
			if (sp) {
1947
				bfputc(bf, ' ');
1948
			}
1949
			bfprintf(bf, "%s ( ", special_name(TOK_arith_type));
1950
			IGNORE print_itype(s1, bf, 0);
1951
			bfprintf(bf, ", ");
1952
			IGNORE print_itype(s2, bf, 0);
1953
			bfprintf(bf, " )");
1954
			sp = 1;
1955
			break;
1956
		}
1957
		case itype_literal_tag: {
1958
			NAT n = DEREF_nat(itype_literal_nat(t));
1959
			int tok = DEREF_int(itype_literal_spec(t));
1960
			if (sp) {
1961
				bfputc(bf, ' ');
1962
			}
1963
			bfprintf(bf, "%s ( ", special_name(tok));
1964
			IGNORE print_nat(n, 0, bf, 0);
1965
			bfprintf(bf, " )");
1966
			sp = 1;
1967
			break;
1968
		}
1969
		case itype_token_tag: {
1970
			BUILTIN_TYPE n = DEREF_ntype(itype_unprom(t));
1971
			if (n == ntype_none || n == ntype_ellipsis) {
1972
				IDENTIFIER id;
1973
				LIST(TOKEN)args;
1974
				id = DEREF_id(itype_token_tok(t));
1975
				args = DEREF_list(itype_token_args(t));
1976
				sp = print_token(id, qual_none, args, bf, sp);
1977
			} else {
1978
				if (sp)bfputc(bf, ' ');
1979
				bfprintf(bf, "%s ( ",
1980
					 special_name(TOK_promote));
1981
				IGNORE print_ntype(n, bf, 0);
1982
				bfprintf(bf, " )");
1983
				sp = 1;
1984
			}
1985
			break;
1986
		}
1987
		}
2 7u83 1988
	}
7 7u83 1989
	return (sp);
2 7u83 1990
}
1991
 
1992
 
1993
/*
1994
    FLOATING-POINT TYPE PRINTING
1995
 
1996
    This routine prints a floating-point type to the buffer bf.
1997
*/
1998
 
7 7u83 1999
int
2000
print_ftype(FLOAT_TYPE t, BUFFER *bf, int sp)
2 7u83 2001
{
7 7u83 2002
	if (!IS_NULL_ftype(t)) {
2003
		ASSERT(ORDER_ftype == 4);
2004
		switch (TAG_ftype(t)) {
2005
		case ftype_basic_tag: {
2006
			BUILTIN_TYPE n = DEREF_ntype(ftype_basic_no(t));
2007
			sp = print_ntype(n, bf, sp);
2008
			break;
2009
		}
2010
		case ftype_arg_promote_tag: {
2011
			FLOAT_TYPE s = DEREF_ftype(ftype_arg_promote_arg(t));
2012
			if (sp) {
2013
				bfputc(bf, ' ');
2014
			}
2015
			bfprintf(bf, "%s ( ", special_name(TOK_promote));
2016
			IGNORE print_ftype(s, bf, 0);
2017
			bfprintf(bf, " )");
2018
			sp = 1;
2019
			break;
2020
		}
2021
		case ftype_arith_tag: {
2022
			FLOAT_TYPE s1 = DEREF_ftype(ftype_arith_arg1(t));
2023
			FLOAT_TYPE s2 = DEREF_ftype(ftype_arith_arg2(t));
2024
			if (sp) {
2025
				bfputc(bf, ' ');
2026
			}
2027
			bfprintf(bf, "%s ( ", special_name(TOK_arith_type));
2028
			IGNORE print_ftype(s1, bf, 0);
2029
			bfprintf(bf, ", ");
2030
			IGNORE print_ftype(s2, bf, 0);
2031
			bfprintf(bf, " )");
2032
			sp = 1;
2033
			break;
2034
		}
2035
		case ftype_token_tag: {
2036
			IDENTIFIER id = DEREF_id(ftype_token_tok(t));
2037
			LIST(TOKEN)args = DEREF_list(ftype_token_args(t));
2038
			sp = print_token(id, qual_none, args, bf, sp);
2039
			break;
2040
		}
2041
		}
2 7u83 2042
	}
7 7u83 2043
	return (sp);
2 7u83 2044
}
2045
 
2046
 
2047
/*
2048
    CLASS TYPE PRINTING
2049
 
2050
    This routines prints the class type ct to the buffer bf.
2051
*/
2052
 
7 7u83 2053
int
2054
print_ctype(CLASS_TYPE ct, QUALIFIER qual, int key, BUFFER *bf, int sp)
2 7u83 2055
{
7 7u83 2056
	if (!IS_NULL_ctype(ct)) {
2057
		TYPE t = DEREF_type(ctype_form(ct));
2058
		IDENTIFIER id = DEREF_id(ctype_name(ct));
2059
		if (key && IS_id_class_name(id)) {
2060
			BASE_TYPE bt = find_class_key(ct);
2061
			sp = print_btype(bt, bf, sp);
2062
		}
2063
		if (!IS_NULL_type(t) && IS_type_token(t)) {
2064
			IDENTIFIER tid = DEREF_id(type_token_tok(t));
2065
			LIST(TOKEN)args = DEREF_list(type_token_args(t));
2066
			sp = print_token(tid, qual, args, bf, sp);
2067
		} else {
2068
			sp = print_id_short(id, qual, bf, sp);
2069
		}
2 7u83 2070
	}
7 7u83 2071
	return (sp);
2 7u83 2072
}
2073
 
2074
 
2075
/*
2076
    ENUMERATION TYPE PRINTING
2077
 
2078
    This routines prints the enumeration type et to the buffer bf.
2079
*/
2080
 
7 7u83 2081
int
2082
print_etype(ENUM_TYPE et, int key, BUFFER *bf, int sp)
2 7u83 2083
{
7 7u83 2084
	if (!IS_NULL_etype(et)) {
2085
		IDENTIFIER id = DEREF_id(etype_name(et));
2086
		if (key && IS_id_enum_name(id)) {
2087
			sp = print_lex(lex_enum, bf, sp);
2088
		}
2089
		sp = print_id_short(id, qual_none, bf, sp);
2 7u83 2090
	}
7 7u83 2091
	return (sp);
2 7u83 2092
}
2093
 
2094
 
2095
/*
2096
    CHECK FOR TAILED TYPES
2097
 
2098
    This routine tested whether the type t is a tailed type, that is an
2099
    array, bitfield, or function type.
2100
*/
2101
 
7 7u83 2102
static int
2103
is_tailed_type(TYPE t)
2 7u83 2104
{
7 7u83 2105
	if (!IS_NULL_type(t)) {
2106
		IDENTIFIER tid = DEREF_id(type_name(t));
2107
		if (IS_NULL_id(tid) || !print_type_alias) {
2108
			switch (TAG_type(t)) {
2109
			case type_func_tag:
2110
			case type_array_tag:
2111
			case type_bitfield_tag: {
2112
				return (1);
2113
			}
2114
			case type_templ_tag: {
2115
				TYPE s = DEREF_type(type_templ_defn(t));
2116
				return (is_tailed_type(s));
2117
			}
2118
			}
2 7u83 2119
		}
2120
	}
7 7u83 2121
	return (0);
2 7u83 2122
}
2123
 
2124
 
2125
/*
2126
    TYPE HEAD PRINTING
2127
 
2128
    This routine prints the head of a type (i.e. the main part and any
2129
    pointer or reference components) to the buffer bf.
2130
*/
2131
 
7 7u83 2132
static int
2133
print_head(TYPE t, int key, BUFFER *bf, int sp)
2 7u83 2134
{
7 7u83 2135
	if (IS_NULL_type(t)) {
2136
		static unsigned long type_no = 0;
2137
		if (sp) {
2138
			bfputc(bf, ' ');
2 7u83 2139
		}
7 7u83 2140
		bfprintf(bf, "<type%lu>", ++type_no);
2141
		sp = 1;
2142
	} else {
2143
		CV_SPEC qual = DEREF_cv(type_qual(t));
2144
		IDENTIFIER tid = DEREF_id(type_name(t));
2145
		qual &= cv_qual;
2146
		if (!IS_NULL_id(tid) && print_type_alias) {
2147
			switch (TAG_id(tid)) {
2148
			case id_class_alias_tag:
2149
			case id_enum_alias_tag:
2150
			case id_type_alias_tag: {
2151
				/* Print type aliases */
2152
				if (!IS_type_pre(t)) {
2153
					sp = print_cv(qual, bf, sp);
2154
					sp = print_id_short(tid, qual_none, bf,
2155
							    sp);
2156
					return (sp);
2157
				}
2158
				break;
2159
			}
2160
			}
2 7u83 2161
		}
7 7u83 2162
		ASSERT(ORDER_type == 18);
2163
		switch (TAG_type(t)) {
2164
		case type_pre_tag: {
2165
			/* Pre-types */
2166
			BASE_TYPE bt = DEREF_btype(type_pre_rep(t));
2167
			BASE_TYPE kt = (bt & btype_named);
2168
			sp = print_cv(qual, bf, sp);
2169
			if (kt) {
2170
				if (kt == btype_alias) {
2171
					sp = print_id_short(tid, qual_none, bf,
2172
							    sp);
2173
				} else {
2174
					HASHID nm = DEREF_hashid(id_name(tid));
2175
					sp = print_btype(kt, bf, sp);
2176
					sp = print_hashid(nm, 0, 0, bf, sp);
2177
				}
2178
			} else {
2179
				sp = print_btype(bt, bf, sp);
2180
			}
2181
			break;
2 7u83 2182
		}
7 7u83 2183
		case type_integer_tag: {
2184
			/* Integral types */
2185
			INT_TYPE it = DEREF_itype(type_integer_rep(t));
2186
			sp = print_cv(qual, bf, sp);
2187
			sp = print_itype(it, bf, sp);
2188
			break;
2 7u83 2189
		}
7 7u83 2190
		case type_floating_tag: {
2191
			/* Floating-point types */
2192
			FLOAT_TYPE ft = DEREF_ftype(type_floating_rep(t));
2193
			sp = print_cv(qual, bf, sp);
2194
			sp = print_ftype(ft, bf, sp);
2195
			break;
2 7u83 2196
		}
7 7u83 2197
		case type_top_tag: {
2198
			/* Top type */
2199
			sp = print_cv(qual, bf, sp);
2200
			sp = print_ntype(ntype_void, bf, sp);
2201
			break;
2 7u83 2202
		}
7 7u83 2203
		case type_bottom_tag: {
2204
			/* Bottom type */
2205
			sp = print_cv(qual, bf, sp);
2206
			sp = print_ntype(ntype_bottom, bf, sp);
2207
			break;
2 7u83 2208
		}
7 7u83 2209
		case type_ptr_tag: {
2210
			/* Pointer type */
2211
			TYPE s = DEREF_type(type_ptr_sub(t));
2212
			sp = print_head(s, key, bf, sp);
2213
			if (is_tailed_type(s)) {
2214
				bfprintf(bf, " ( *");
2215
			} else {
2216
				if (sp) {
2217
					bfputc(bf, ' ');
2218
				}
2219
				bfputc(bf, '*');
2220
			}
2221
			sp = (qual ? print_cv(qual, bf, 1) : 0);
2222
			break;
2223
		}
2224
		case type_ref_tag: {
2225
			/* Reference type */
2226
			TYPE s = DEREF_type(type_ref_sub(t));
2227
			sp = print_head(s, key, bf, sp);
2228
			if (is_tailed_type(s)) {
2229
				bfprintf(bf, " ( &");
2230
			} else {
2231
				if (sp) {
2232
					bfputc(bf, ' ');
2233
				}
2234
				bfputc(bf, '&');
2235
			}
2236
			sp = (qual ? print_cv(qual, bf, 1) : 0);
2237
			break;
2238
		}
2239
		case type_ptr_mem_tag: {
2240
			/* Pointer to member type */
2241
			TYPE s = DEREF_type(type_ptr_mem_sub(t));
2242
			CLASS_TYPE ct = DEREF_ctype(type_ptr_mem_of(t));
2243
			sp = print_head(s, key, bf, sp);
2244
			if (is_tailed_type(s)) {
2245
				bfprintf(bf, " ( ");
2246
				sp = 0;
2247
			}
2248
			IGNORE print_ctype(ct, qual_none, 0, bf, sp);
2249
			bfprintf(bf, "::*");
2250
			sp = (qual ? print_cv(qual, bf, 1) : 0);
2251
			break;
2252
		}
2253
		case type_func_tag: {
2254
			/* Function type */
2255
			qual = DEREF_cv(type_func_mqual(t));
2256
			if (qual && print_func_linkage) {
2257
				sp = print_linkage(qual, bf, sp);
2258
			}
2259
			if (print_return_type) {
2260
				TYPE r = DEREF_type(type_func_ret(t));
2261
				if (!IS_NULL_type(r)) {
2262
					sp = print_head(r, 0, bf, sp);
2263
				}
2264
			}
2265
			break;
2266
		}
2267
		case type_array_tag: {
2268
			/* Array type */
2269
			TYPE s = DEREF_type(type_array_sub(t));
2270
			sp = print_head(s, key, bf, sp);
2271
			break;
2272
		}
2273
		case type_bitfield_tag: {
2274
			/* Bitfield type */
2275
			INT_TYPE it = DEREF_itype(type_bitfield_defn(t));
2276
			sp = print_cv(qual, bf, sp);
2277
			sp = print_itype(it, bf, sp);
2278
			break;
2279
		}
2280
		case type_compound_tag: {
2281
			/* Class type */
2282
			CLASS_TYPE ct = DEREF_ctype(type_compound_defn(t));
2283
			sp = print_cv(qual, bf, sp);
2284
			sp = print_ctype(ct, qual_none, key, bf, sp);
2285
			break;
2286
		}
2287
		case type_enumerate_tag: {
2288
			/* Enumeration type */
2289
			ENUM_TYPE et = DEREF_etype(type_enumerate_defn(t));
2290
			sp = print_cv(qual, bf, sp);
2291
			sp = print_etype(et, key, bf, sp);
2292
			break;
2293
		}
2294
		case type_token_tag: {
2295
			/* Tokenised type */
2296
			IDENTIFIER id = DEREF_id(type_token_tok(t));
2297
			LIST(TOKEN)args = DEREF_list(type_token_args(t));
2298
			sp = print_cv(qual, bf, sp);
2299
			sp = print_token(id, qual_none, args, bf, sp);
2300
			break;
2301
		}
2302
		case type_templ_tag: {
2303
			/* Template type */
2304
			TYPE s = DEREF_type(type_templ_defn(t));
2305
			TOKEN tok = DEREF_tok(type_templ_sort(t));
2306
			sp = print_sort(tok, 0, bf, sp);
2307
			sp = print_cv(qual, bf, sp);
2308
			sp = print_head(s, 1, bf, sp);
2309
			break;
2310
		}
2311
		case type_instance_tag: {
2312
			/* Instance type */
2313
			IDENTIFIER id = DEREF_id(type_name(t));
2314
			sp = print_id_short(id, qual_none, bf, sp);
2315
			break;
2316
		}
2317
		default : {
2318
			/* Error type */
2319
			sp = print_cv(qual, bf, sp);
2320
			if (sp) {
2321
				bfputc(bf, ' ');
2322
			}
2323
			bfprintf(bf, "<error_type>");
2324
			sp = 1;
2325
			break;
2326
		}
2327
		}
2 7u83 2328
	}
7 7u83 2329
	return (sp);
2 7u83 2330
}
2331
 
2332
 
2333
/*
2334
    TYPE TAIL PRINTING
2335
 
2336
    This routine prints the tail of a type (i.e. any array, bitfield or
2337
    function components) to the buffer bf.
2338
*/
2339
 
7 7u83 2340
static int
2341
print_tail(TYPE t, BUFFER *bf, int sp)
2 7u83 2342
{
7 7u83 2343
	if (!IS_NULL_type(t)) {
2344
		IDENTIFIER tid = DEREF_id(type_name(t));
2345
		if (!IS_NULL_id(tid) && print_type_alias) {
2346
			return (sp);
2 7u83 2347
		}
7 7u83 2348
		switch (TAG_type(t)) {
2349
		case type_ptr_tag:
2350
		case type_ref_tag: {
2351
			/* Pointer and reference types */
2352
			TYPE s = DEREF_type(type_ptr_etc_sub(t));
2353
			if (is_tailed_type(s)) {
2354
				bfprintf(bf, " )");
2355
			}
2356
			sp = print_tail(s, bf, sp);
2357
			break;
2 7u83 2358
		}
7 7u83 2359
		case type_ptr_mem_tag: {
2360
			/* Pointer to member type */
2361
			TYPE s = DEREF_type(type_ptr_mem_sub(t));
2362
			if (is_tailed_type(s)) {
2363
				bfprintf(bf, " )");
2 7u83 2364
			}
7 7u83 2365
			sp = print_tail(s, bf, sp);
2366
			break;
2367
		}
2368
		case type_func_tag: {
2369
			/* Function type */
2370
			int prt = print_return_type;
2371
			int ell = DEREF_int(type_func_ellipsis(t));
2372
			CV_SPEC qual = DEREF_cv(type_func_mqual(t));
2373
			LIST(TYPE)p = DEREF_list(type_func_ptypes(t));
2374
			LIST(IDENTIFIER)q = DEREF_list(type_func_pids(t));
2375
			LIST(TYPE)ex = DEREF_list(type_func_except(t));
2376
			sp = 0;
2377
			if (print_member_type) {
2378
				/* Print member parameter types */
2379
				p = DEREF_list(type_func_mtypes(t));
2 7u83 2380
			}
7 7u83 2381
			if (ell & FUNC_WEAK) {
2382
				/* Weak function prototype */
2383
				bfprintf(bf, " WEAK");
2384
			}
2385
			bfprintf(bf, " (");
2386
			if (IS_NULL_list(p) && !(ell & FUNC_ELLIPSIS)) {
2387
				/* There are no parameters */
2388
				if (!(ell & FUNC_NO_PARAMS) && print_c_style) {
2389
					bfprintf(bf, " void");
2390
					sp = 1;
2391
				}
2392
			} else {
2393
				/* Print parameters */
2394
				int pars = print_func_params;
2395
				int dargs = print_default_args;
2396
				if (LENGTH_list(p) != LENGTH_list(q)) {
2397
					dargs = 0;
2398
				}
2399
				print_return_type = 1;
2400
				while (!IS_NULL_list(p)) {
2401
					TYPE s = DEREF_type(HEAD_list(p));
2402
					if (ell & FUNC_PARAMS) {
2403
						s = unpromote_type(s);
2404
					}
2405
					IGNORE print_type(s, bf, 1);
2406
					if (dargs) {
2407
						/* Print default argument */
2408
						IDENTIFIER id =
2409
						    DEREF_id(HEAD_list(q));
2410
						EXP e = DEREF_exp(id_parameter_init(id));
2411
						if (pars) {
2412
							HASHID nm = DEREF_hashid(id_name(id));
2413
							IGNORE print_hashid(nm, 0, 0, bf, 1);
2414
						}
2415
						if (!IS_NULL_exp(e)) {
2416
							bfprintf(bf, " = ");
2417
							IGNORE print_exp(e, 0, bf, 0);
2418
						}
2419
						q = TAIL_list(q);
2420
					}
2421
					p = TAIL_list(p);
2422
					if (!IS_NULL_list(p)) {
2423
						bfputc(bf, ',');
2424
					} else if (ell & FUNC_ELLIPSIS) {
2425
						bfputc(bf, ',');
2426
					}
2427
					sp = 1;
2428
				}
2429
				if (ell & FUNC_ELLIPSIS) {
2430
					bfprintf(bf, " ...");
2431
					sp = 1;
2432
				}
2433
				print_return_type = prt;
2434
			}
2435
			if (sp) {
2436
				bfputc(bf, ' ');
2437
			}
2438
			bfputc(bf, ')');
2439
			sp = print_cv(qual, bf, 1);
2440
			if (prt) {
2441
				TYPE r = DEREF_type(type_func_ret(t));
2442
				if (!IS_NULL_type(r)) {
2443
					sp = print_tail(r, bf, sp);
2444
				}
2445
			}
2446
			if (!EQ_list(ex, univ_type_set) && print_except) {
2447
				/* Print exception specifier */
2448
				sp = print_lex(lex_throw, bf, sp);
2449
				sp = print_type_list(ex, bf, sp);
2450
			}
2451
			break;
2 7u83 2452
		}
7 7u83 2453
		case type_array_tag: {
2454
			/* Array type */
2455
			TYPE s = DEREF_type(type_array_sub(t));
2456
			NAT n = DEREF_nat(type_array_size(t));
2457
			bfprintf(bf, " [");
2458
			IGNORE print_nat(n, 0, bf, 0);
2459
			bfprintf(bf, "]");
2460
			sp = print_tail(s, bf, 1);
2461
			break;
2 7u83 2462
		}
7 7u83 2463
		case type_bitfield_tag: {
2464
			/* Bitfield type */
2465
			INT_TYPE it = DEREF_itype(type_bitfield_defn(t));
2466
			NAT n = DEREF_nat(itype_bitfield_size(it));
2467
			bfputc(bf, ' ');
2468
			bfputc(bf, print_bitfield_sep);
2469
			IGNORE print_nat(n, 0, bf, 1);
2470
			break;
2 7u83 2471
		}
7 7u83 2472
		case type_templ_tag: {
2473
			/* Template type */
2474
			TYPE s = DEREF_type(type_templ_defn(t));
2475
			sp = print_tail(s, bf, sp);
2476
			break;
2477
		}
2478
		}
2 7u83 2479
	}
7 7u83 2480
	return (sp);
2 7u83 2481
}
2482
 
2483
 
2484
/*
2485
    PRINT A TYPE
2486
 
2487
    This routine prints the type t to the buffer bf.  Note that this is in
2488
    two passes - the first prints the head of the type, comprising the
2489
    base type and any pointer or reference qualifiers, while the second
2490
    prints the tail of the type, comprising any array or function qualifiers.
2491
*/
2492
 
7 7u83 2493
int
2494
print_type(TYPE t, BUFFER *bf, int sp)
2 7u83 2495
{
7 7u83 2496
	sp = print_head(t, print_c_style, bf, sp);
2497
	sp = print_tail(t, bf, sp);
2498
	return (sp);
2 7u83 2499
}
2500
 
2501
 
2502
/*
2503
    PRINT A LIST OF TYPES
2504
 
2505
    This routine prints the list of types p, enclosed in brackets, to the
2506
    buffer bf.
2507
*/
2508
 
7 7u83 2509
int
2510
print_type_list(LIST(TYPE)p, BUFFER *bf, int sp)
2 7u83 2511
{
7 7u83 2512
	if (sp)bfputc(bf, ' ');
2513
	bfputc(bf, '(');
2514
	if (!IS_NULL_list(p)) {
2515
		for (;;) {
2516
			TYPE t = DEREF_type(HEAD_list(p));
2517
			IGNORE print_type(t, bf, 1);
2518
			p = TAIL_list(p);
2519
			if (IS_NULL_list(p)) {
2520
				break;
2521
			}
2522
			bfputc(bf, ',');
2523
		}
2524
		bfputc(bf, ' ');
2 7u83 2525
	}
7 7u83 2526
	bfputc(bf, ')');
2527
	return (1);
2 7u83 2528
}
2529
 
2530
 
2531
/*
2532
    OFFSET PRINTING
2533
 
2534
    This routine prints an offset to the buffer bf.
2535
*/
2536
 
7 7u83 2537
int
2538
print_offset(OFFSET off, BUFFER *bf, int sp)
2 7u83 2539
{
7 7u83 2540
	if (!IS_NULL_off(off)) {
2541
		switch (TAG_off(off)) {
2542
		case off_base_tag: {
2543
			GRAPH gr = DEREF_graph(off_base_graph(off));
2544
			sp = print_graph(gr, 0, bf, sp);
2545
			break;
2546
		}
2547
		case off_deriv_tag: {
2548
			GRAPH gr = DEREF_graph(off_deriv_graph(off));
2549
			sp = print_graph(gr, 0, bf, sp);
2550
			break;
2551
		}
2552
		case off_member_tag: {
2553
			IDENTIFIER id = DEREF_id(off_member_id(off));
2554
			sp = print_id_short(id, qual_none, bf, sp);
2555
			break;
2556
		}
2557
		case off_token_tag: {
2558
			IDENTIFIER id = DEREF_id(off_token_tok(off));
2559
			LIST(TOKEN)args = DEREF_list(off_token_args(off));
2560
			sp = print_token(id, qual_none, args, bf, sp);
2561
			break;
2562
		}
2563
		default: {
2564
			static unsigned long off_no = 0;
2 7u83 2565
#ifdef RUNTIME
7 7u83 2566
			if (debugging) {
2567
				/* Debug offset printing routine */
2568
				sp = print_offset_aux(off, bf, sp);
2569
				break;
2570
			}
2571
#endif
2572
			if (sp) {
2573
				bfputc(bf, ' ');
2574
			}
2575
			bfprintf(bf, "<off%lu>", ++off_no);
2576
			sp = 1;
2577
			break;
2 7u83 2578
		}
7 7u83 2579
		}
2 7u83 2580
	}
7 7u83 2581
	return (sp);
2 7u83 2582
}
2583
 
2584
 
2585
/*
2586
    FIND A LINE WITHIN THE CURRENT FILE BUFFER
2587
 
2588
    This routine checks whether the start of line n lies within the
2589
    current file buffer.  If so it returns a pointer to the start of
2590
    the line.  m gives the line number of the current position.
2591
*/
2592
 
7 7u83 2593
static string
2594
find_buffer_line(unsigned long n, unsigned long m)
2 7u83 2595
{
7 7u83 2596
	string p = input_posn - 1;
2597
	if (n <= m) {
2598
		/* Scan backwards */
2599
		while (p >= input_start) {
2600
			character c = *(p--);
2601
			if (c == char_newline) {
2602
				if (n == m) {
2603
					return (p + 2);
2604
				}
2605
				m--;
2606
			}
2607
		}
2608
		if (m == 1) {
2609
			/* Allow falling off start */
2610
			return (input_start);
2611
		}
2612
	} else {
2613
		while (p < input_end) {
2614
			character c = *(p++);
2615
			if (c == char_newline) {
2616
				if (n == m) {
2617
					return (p);
2618
				}
2619
				m++;
2620
			}
2621
		}
2622
		if (p == input_eof) {
2623
			/* Allow falling off end */
2624
			return (p);
2625
		}
2 7u83 2626
	}
7 7u83 2627
	return (NULL);
2 7u83 2628
}
2629
 
2630
 
2631
/*
2632
    FIND A LOCATION WITHIN THE CURRENT FILE BUFFER
2633
 
2634
    This routine checks whether the n lines following line ln of file fn
2635
    lie within the input buffer.  If so it returns the position of the
2636
    first line within the buffer.
2637
*/
2638
 
7 7u83 2639
static string
2640
find_buffer_loc(string fn, unsigned long ln, unsigned long n)
2 7u83 2641
{
7 7u83 2642
	if (input_start && !bad_crt_loc) {
2643
		PTR(POSITION)pm = crt_loc.posn;
2644
		if (!IS_NULL_ptr(pm)) {
2645
			string fm = DEREF_string(posn_input(pm));
2646
			if (ustreq(fn, fm)) {
2647
				unsigned long om = DEREF_ulong(posn_offset(pm));
2648
				unsigned long lm = crt_loc.line - om;
2649
				string p = find_buffer_line(ln, lm);
2650
				if (p) {
2651
					string q = find_buffer_line(ln + n, lm);
2652
					if (q) {
2653
						return (p);
2654
					}
2655
				}
2656
			}
2 7u83 2657
		}
2658
	}
7 7u83 2659
	return (NULL);
2 7u83 2660
}
2661
 
2662
 
2663
/*
2664
    PRINT SOURCE LINES
2665
 
2666
    This routine prints a number of lines from the input buffer centred
2667
    on the location loc to the file f.  If loc does not correspond to a
2668
    position within the current buffer then no text is output.
2669
*/
2670
 
7 7u83 2671
void
2672
print_source(LOCATION *loc, int lines, int full, CONST char *pre, FILE *f)
2 7u83 2673
{
7 7u83 2674
	PTR(POSITION)pn = loc->posn;
2675
	if (lines > 0 && !IS_NULL_ptr(pn)) {
2676
		string p;
2677
		int nl = 0;
2678
		FILE *g = NULL;
2679
		CONST char *mark = "!!!!";
2680
		unsigned long n = (unsigned long)lines;
2681
		unsigned long b = n / 2;
2682
		string fn = DEREF_string(posn_input(pn));
2683
		unsigned long on = DEREF_ulong(posn_offset(pn));
2684
		unsigned long ln = loc->line - on;
2685
		unsigned long cn = loc->column;
2686
		unsigned long lc = ln;
2687
		unsigned long cc = 0;
2688
		if (ln <= b) {
2689
			ln = 1;
2690
		} else {
2691
			ln -= b;
2692
		}
2 7u83 2693
 
7 7u83 2694
		/* Find start of source */
2695
		p = find_buffer_loc(fn, ln, n);
2696
		if (p == NULL) {
2697
			g = fopen(strlit(fn), "r");
2698
			if (g) {
2699
				/* Skip to correct line in file */
2700
				unsigned long lm = 1;
2701
				while (lm != ln) {
2702
					int c = fgetc(g);
2703
					if (c == EOF) {
2704
						fclose_v(g);
2705
						g = NULL;
2706
						break;
2707
					}
2708
					if (c == '\n')lm++;
2709
				}
2710
			}
2 7u83 2711
		}
2712
 
7 7u83 2713
		/* Print source */
2714
		if (full) {
2715
			if (pre) {
2716
				fputs_v(pre, f);
2717
			}
2718
			fn = DEREF_string(posn_file(pn));
2719
			fprintf_v(f, "FILE: %s\n", strlit(fn));
2 7u83 2720
		}
7 7u83 2721
		while (n) {
2722
			int c;
2723
			if (nl == 0) {
2724
				if (pre) {
2725
					fputs_v(pre, f);
2726
				}
2727
				if (full) {
2728
					fprintf_v(f, "%lu:\t", ln + on);
2729
				}
2730
				nl = 1;
2731
			}
2732
			if (ln == lc && cn == cc) {
2733
				fputs_v(mark, f);
2734
				mark = NULL;
2735
			}
2736
			if (p) {
2737
				/* Read from buffer */
2738
				if (p >= input_end) {
2739
					break;
2740
				}
2741
				c = (int)*(p++);
2742
			} else if (g) {
2743
				/* Read from file */
2744
				c = fgetc(g);
2745
				if (c == EOF) {
2746
					break;
2747
				}
2748
			} else {
2749
				break;
2750
			}
2751
			if (c == char_newline) {
2752
				/* Newline characters */
2753
				if (ln == lc && mark) {
2754
					fputs_v(mark, f);
2755
					mark = NULL;
2756
				}
2757
				if (--n == 0) {
2758
					break;
2759
				}
2760
				nl = 0;
2761
				ln++;
2762
				cc = 0;
2763
			} else {
2764
				cc++;
2765
			}
2766
			fputc_v((int)c, f);
2767
		}
2768
		if (mark) {
2769
			fputs_v(mark, f);
2770
			nl = 1;
2771
		}
2772
		if (nl) {
2773
			fputc_v('\n', f);
2774
		}
2775
		if (g) {
2776
			fclose_v(g);
2777
		}
2 7u83 2778
	}
7 7u83 2779
	return;
2 7u83 2780
}