Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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