Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
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 "version.h"
33
#include "c_types.h"
34
#include "ctype_ops.h"
35
#include "exp_ops.h"
36
#include "hashid_ops.h"
37
#include "id_ops.h"
38
#include "member_ops.h"
39
#include "nat_ops.h"
40
#include "nspace_ops.h"
41
#include "tok_ops.h"
42
#include "type_ops.h"
43
#include "error.h"
44
#include "catalog.h"
45
#include "tdf.h"
46
#include "allocate.h"
47
#include "basetype.h"
48
#include "buffer.h"
49
#include "char.h"
50
#include "class.h"
51
#include "constant.h"
52
#include "convert.h"
53
#include "declare.h"
54
#include "exception.h"
55
#include "function.h"
56
#include "hash.h"
57
#include "identifier.h"
58
#include "initialise.h"
59
#include "lex.h"
60
#include "literal.h"
61
#include "mangle.h"
62
#include "namespace.h"
63
#include "print.h"
64
#include "syntax.h"
65
#include "unmangle.h"
66
#include "ustring.h"
67
#include "xalloc.h"
68
 
69
 
70
/*
71
    LANGUAGE DEPENDENT DEFINITIONS
72
 
73
    The unmangling routines are only included in the C++ producer; the
74
    C producer uses a dummy identity mapping.
75
*/
76
 
77
#if LANGUAGE_CPP
78
 
79
 
80
/*
81
    FORWARD DECLARATIONS
82
 
83
    The following forward declarations are required in the name unmangling
84
    routines.
85
*/
86
 
87
static NAT unmangle_nat PROTO_S ( ( string * ) ) ;
88
static TYPE unmangle_type PROTO_S ( ( string *, CV_SPEC, BASE_TYPE, int ) ) ;
89
static IDENTIFIER unmangle_nspace PROTO_S ( ( string *, NAMESPACE, int ) ) ;
90
static LIST ( TOKEN ) unmangle_token_args PROTO_S ( ( string * ) ) ;
91
static TOKEN find_token_arg PROTO_S ( ( string * ) ) ;
92
 
93
 
94
/*
95
    DUMMY RETURN TYPE
96
 
97
    This variable is a dummy used as a return type when none is given in
98
    a mangled form.  Its printed form is empty.
99
*/
100
 
101
static TYPE dummy_ret_type = NULL_type ;
102
 
103
 
104
/*
105
    CURRENT UNMANGLING INFORMATION
106
 
107
    The following variables are used to hold certain information about the
108
    identifier being unmangled.
109
*/
110
 
111
static IDENTIFIER crt_unmangle_class = NULL_id ;
112
static LIST ( TOKEN ) crt_unmangle_args = NULL_list ( TOKEN ) ;
113
 
114
 
115
/*
116
    UNMANGLE AN OPERATOR NAME
117
 
118
    This routine unmangles an operator name from the string pointed to
119
    by ps.
120
*/
121
 
122
static int unmangle_op
123
    PROTO_N ( ( ps ) )
124
    PROTO_T ( string *ps )
125
{
126
    string s = *ps ;
127
    int t = lex_unknown ;
128
    character c = *( s++ ) ;
129
    switch ( c ) {
130
	case 'a' : {
131
	    c = *( s++ ) ;
132
	    switch ( c ) {
133
		case 'a' : {
134
		    c = *( s++ ) ;
135
		    if ( c == 'd' ) {
136
			t = lex_and_Heq_H1 ;
137
		    } else {
138
			s-- ;
139
			t = lex_logical_Hand_H1 ;
140
		    }
141
		    break ;
142
		}
143
		case 'b' : {
144
		    t = lex_abs ;
145
		    break ;
146
		}
147
		case 'd' : {
148
		    c = *( s++ ) ;
149
		    if ( c == 'v' ) {
150
			t = lex_div_Heq ;
151
		    } else {
152
			s-- ;
153
			t = lex_and_H1 ;
154
		    }
155
		    break ;
156
		}
157
		case 'e' : {
158
		    c = *( s++ ) ;
159
		    if ( c == 'r' ) t = lex_xor_Heq_H1 ;
160
		    break ;
161
		}
162
		case 'l' : {
163
		    c = *( s++ ) ;
164
		    if ( c == 's' ) t = lex_lshift_Heq ;
165
		    break ;
166
		}
167
		case 'm' : {
168
		    c = *( s++ ) ;
169
		    switch ( c ) {
170
			case 'd' : t = lex_rem_Heq ; break ;
171
			case 'i' : t = lex_minus_Heq ; break ;
172
			case 'l' : t = lex_star_Heq ; break ;
173
		    }
174
		    break ;
175
		}
176
		case 'o' : {
177
		    c = *( s++ ) ;
178
		    if ( c == 'r' ) t = lex_or_Heq_H1 ;
179
		    break ;
180
		}
181
		case 'p' : {
182
		    c = *( s++ ) ;
183
		    if ( c == 'l' ) t = lex_plus_Heq ;
184
		    break ;
185
		}
186
		case 'r' : {
187
		    c = *( s++ ) ;
188
		    if ( c == 's' ) t = lex_rshift_Heq ;
189
		    break ;
190
		}
191
		case 's' : {
192
		    t = lex_assign ;
193
		    break ;
194
		}
195
	    }
196
	    break ;
197
	}
198
	case 'c' : {
199
	    c = *( s++ ) ;
200
	    switch ( c ) {
201
		case 'c' : t = lex_colon_Hcolon ; break ;
202
		case 'l' : t = lex_func_Hop ; break ;
203
		case 'm' : t = lex_comma ; break ;
204
		case 'n' : t = lex_cond_Hop ; break ;
205
		case 'o' : t = lex_compl_H1 ; break ;
206
		case 's' : t = lex_colon ; break ;
207
		case 't' : t = lex_type_Hname ; break ;
208
	    }
209
	    break ;
210
	}
211
	case 'd' : {
212
	    c = *( s++ ) ;
213
	    switch ( c ) {
214
		case 'f' : t = lex_dot ; break ;
215
		case 'l' : t = lex_delete ; break ;
216
		case 'm' : t = lex_dot_Hstar ; break ;
217
		case 't' : t = lex_destructor_Hname ; break ;
218
		case 'v' : t = lex_div ; break ;
219
	    }
220
	    break ;
221
	}
222
	case 'e' : {
223
	    c = *( s++ ) ;
224
	    switch ( c ) {
225
		case 'q' : t = lex_eq ; break ;
226
		case 'r' : t = lex_xor_H1 ; break ;
227
	    }
228
	    break ;
229
	}
230
	case 'f' : {
231
	    t = lex_float ;
232
	    break ;
233
	}
234
	case 'g' : {
235
	    c = *( s++ ) ;
236
	    switch ( c ) {
237
		case 'e' : t = lex_greater_Heq ; break ;
238
		case 't' : t = lex_greater ; break ;
239
	    }
240
	    break ;
241
	}
242
	case 'l' : {
243
	    c = *( s++ ) ;
244
	    switch ( c ) {
245
		case 'e' : t = lex_less_Heq ; break ;
246
		case 's' : t = lex_lshift ; break ;
247
		case 't' : t = lex_less ; break ;
248
	    }
249
	    break ;
250
	}
251
	case 'm' : {
252
	    c = *( s++ ) ;
253
	    switch ( c ) {
254
		case 'd' : t = lex_rem ; break ;
255
		case 'i' : t = lex_minus ; break ;
256
		case 'l' : t = lex_star ; break ;
257
		case 'm' : t = lex_minus_Hminus ; break ;
258
		case 'n' : t = lex_min ; break ;
259
		case 'x' : t = lex_max ; break ;
260
	    }
261
	    break ;
262
	}
263
	case 'n' : {
264
	    c = *( s++ ) ;
265
	    switch ( c ) {
266
		case 'e' : t = lex_not_Heq_H1 ; break ;
267
		case 't' : t = lex_not_H1 ; break ;
268
		case 'w' : t = lex_new ; break ;
269
	    }
270
	    break ;
271
	}
272
	case 'o' : {
273
	    c = *( s++ ) ;
274
	    switch ( c ) {
275
		case 'o' : t = lex_logical_Hor_H1 ; break ;
276
		case 'p' : t = lex_operator ; break ;
277
		case 'r' : t = lex_or_H1 ; break ;
278
	    }
279
	    break ;
280
	}
281
	case 'p' : {
282
	    c = *( s++ ) ;
283
	    switch ( c ) {
284
		case 'l' : t = lex_plus ; break ;
285
		case 'p' : t = lex_plus_Hplus ; break ;
286
	    }
287
	    break ;
288
	}
289
	case 'r' : {
290
	    c = *( s++ ) ;
291
	    switch ( c ) {
292
		case 'f' : t = lex_arrow ; break ;
293
		case 'm' : t = lex_arrow_Hstar ; break ;
294
		case 's' : t = lex_rshift ; break ;
295
	    }
296
	    break ;
297
	}
298
	case 's' : {
299
	    c = *( s++ ) ;
300
	    if ( c == 'z' ) t = lex_sizeof ;
301
	    break ;
302
	}
303
	case 't' : {
304
	    c = *( s++ ) ;
305
	    switch ( c ) {
306
		case 'b' : t = lex_vtable ; break ;
307
		case 'd' : t = lex_typeid ; break ;
308
		case 'i' : {
309
		    if ( s [0] == '_' && s [1] == '_' ) {
310
			t = lex_typeof ;
311
			s += 2 ;
312
		    }
313
		    break ;
314
		}
315
	    }
316
	    break ;
317
	}
318
	case 'v' : {
319
	    c = *( s++ ) ;
320
	    switch ( c ) {
321
		case 'c' : t = lex_array_Hop ; break ;
322
		case 'd' : t = lex_delete_Harray ; break ;
323
		case 'n' : t = lex_new_Harray ; break ;
324
		case '_' : t = lex_static ; break ;
325
		case 't' : {
326
		    if ( s [0] == '_' && s [1] == '_' ) {
327
			t = lex_virtual ;
328
			s += 2 ;
329
		    }
330
		    break ;
331
		}
332
	    }
333
	    break ;
334
	}
335
	case '0' : case '1' : case '2' : case '3' : case '4' :
336
	case '5' : case '6' : case '7' : case '8' : case '9' : {
337
	    t = lex_auto ;
338
	    break ;
339
	}
340
    }
341
    if ( t != lex_unknown ) *ps = s ;
342
    return ( t ) ;
343
}
344
 
345
 
346
/*
347
    UNMANGLE A NUMBER
348
 
349
    This routine unmangles a series of digits from the string pointed
350
    to by ps.  If e is true then the digits should be terminated by an
351
    underscore.
352
*/
353
 
354
static unsigned unmangle_no
355
    PROTO_N ( ( ps, e ) )
356
    PROTO_T ( string *ps X int e )
357
{
358
    character c ;
359
    unsigned n = 0 ;
360
    string s = *ps ;
361
    while ( c = *( s++ ), ( c >= char_zero && c <= char_nine ) ) {
362
	unsigned d = ( unsigned ) ( c - char_zero ) ;
363
	n = 10 * n + d ;
364
    }
365
    if ( c != MANGLE_sep || e == 0 ) s-- ;
366
    *ps = s ;
367
    return ( n ) ;
368
}
369
 
370
 
371
/*
372
    UNMANGLE A SMALL NUMBER
373
 
374
    This routine unmangles a small number from the string pointed to
375
    by ps.  This consists either of a single digit or a series of digits
376
    delimited by underscores.
377
*/
378
 
379
static unsigned unmangle_digit
380
    PROTO_N ( ( ps ) )
381
    PROTO_T ( string *ps )
382
{
383
    unsigned n ;
384
    string s = *ps ;
385
    character c = *( s++ ) ;
386
    if ( c >= char_zero && c <= char_nine ) {
387
	n = ( unsigned ) ( c - char_zero ) ;
388
    } else if ( c == MANGLE_sep ) {
389
	n = unmangle_no ( &s, 1 ) ;
390
    } else {
391
	n = 0 ;
392
	s-- ;
393
    }
394
    *ps = s ;
395
    return ( n ) ;
396
}
397
 
398
 
399
/*
400
    UNMANGLE AN EXPRESSION
401
 
402
    This routine unmangles an expression of type t from the string pointed
403
    to by ps.
404
*/
405
 
406
static EXP unmangle_exp
407
    PROTO_N ( ( ps, t ) )
408
    PROTO_T ( string *ps X TYPE t )
409
{
410
    EXP e = NULL_exp ;
411
    string s = *ps ;
412
    character c = *s ;
413
    if ( ( c >= char_zero && c <= char_nine ) || c == MANGLE_neg ) {
414
	/* Read an integer constant */
415
	NAT n = unmangle_nat ( &s ) ;
416
	if ( !IS_NULL_nat ( n ) ) {
417
	    MAKE_exp_int_lit ( t, n, exp_int_lit_tag, e ) ;
418
	}
419
 
420
    } else if ( c == MANGLE_op ) {
421
	int op ;
422
	s++ ;
423
	op = unmangle_op ( &s ) ;
424
	if ( op == lex_float ) {
425
	    /* Floating point literals */
426
	    string u = xustrcpy ( s ) ;
427
	    string v = u ;
428
	    while ( c = *( s++ ), c != 0 ) {
429
		if ( c == MANGLE_sep ) {
430
		    *v = 0 ;
431
		    s++ ;
432
		    break ;
433
		}
434
		if ( ( c >= char_zero && c <= char_nine ) || c == 'e' ) {
435
		    /* EMPTY */
436
		} else if ( c == 'd' ) {
437
		    *v = '.' ;
438
		} else if ( c == MANGLE_neg ) {
439
		    *v = '-' ;
440
		} else {
441
		    *v = 0 ;
442
		    break ;
443
		}
444
		v++ ;
445
	    }
446
	    s-- ;
447
	    e = make_literal_exp ( u, &op, 0 ) ;
448
	} else {
449
	    int n = 0 ;
450
	    c = *s ;
451
	    if ( c >= char_zero && c <= char_nine ) {
452
		n = ( int ) ( c - char_zero ) ;
453
		s++ ;
454
	    }
455
	    if ( op == lex_sizeof ) {
456
		TYPE r = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
457
		e = make_sizeof_exp ( r, NULL_exp, 0, op ) ;
458
	    } else {
459
		LIST ( EXP ) p = NULL_list ( EXP ) ;
460
		while ( n ) {
461
		    EXP a = unmangle_exp ( &s, t ) ;
462
		    CONS_exp ( a, p, p ) ;
463
		    n-- ;
464
		}
465
		p = REVERSE_list ( p ) ;
466
		MAKE_exp_opn ( t, op, p, e ) ;
467
	    }
468
	}
469
 
470
    } else if ( c == MANGLE_sep ) {
471
	IDENTIFIER id ;
472
	s++ ;
473
	id = unmangle_nspace ( &s, global_namespace, 1 ) ;
474
	if ( !IS_NULL_id ( id ) ) {
475
	    MAKE_exp_identifier ( t, id, qual_nested, e ) ;
476
	}
477
 
478
    } else if ( c == MANGLE_templ_param ) {
479
	/* Template parameter expressions */
480
	TOKEN tok ;
481
	s++ ;
482
	tok = find_token_arg ( &s ) ;
483
	if ( !IS_NULL_tok ( tok ) && IS_tok_exp ( tok ) ) {
484
	    e = DEREF_exp ( tok_exp_value ( tok ) ) ;
485
	}
486
    }
487
    *ps = s ;
488
    return ( e ) ;
489
}
490
 
491
 
492
/*
493
    UNMANGLE AN INTEGER CONSTANT
494
 
495
    This routine unmangles an integer constant from the string pointed to
496
    by ps.
497
*/
498
 
499
static NAT unmangle_nat
500
    PROTO_N ( ( ps ) )
501
    PROTO_T ( string *ps )
502
{
503
    NAT n = NULL_nat ;
504
    string s = *ps ;
505
    character c = *s ;
506
    if ( c >= char_zero && c <= char_nine ) {
507
	/* Read a sequence of digits */
508
	s++ ;
509
	do {
510
	    unsigned d = ( unsigned ) ( c - char_zero ) ;
511
	    n = make_nat_literal ( n, ( unsigned ) 10, d ) ;
512
	} while ( c = *( s++ ), ( c >= char_zero && c <= char_nine ) ) ;
513
	if ( c != MANGLE_sep ) s-- ;
514
    } else if ( c == MANGLE_sep ) {
515
	/* Empty sequence of digits */
516
	s++ ;
517
    } else if ( c == MANGLE_neg ) {
518
	/* Negate an integer */
519
	s++ ;
520
	n = unmangle_nat ( &s ) ;
521
	n = negate_nat ( n ) ;
522
    } else {
523
	/* Read an expression */
524
	EXP e = unmangle_exp ( &s, type_sint ) ;
525
	if ( !IS_NULL_exp ( e ) ) {
526
	    MAKE_nat_calc ( e, n ) ;
527
	}
528
    }
529
    *ps = s ;
530
    return ( n ) ;
531
}
532
 
533
 
534
/*
535
    UNMANGLE A NAMESPACE QUALIFIER
536
 
537
    This routine unmangles a namespace qualifier from the string pointed
538
    to by ps.  Note that all such namespaces are declared as classes even
539
    if they are not in reality.
540
*/
541
 
542
static IDENTIFIER unmangle_nspace
543
    PROTO_N ( ( ps, ns, var ) )
544
    PROTO_T ( string *ps X NAMESPACE ns X int var )
545
{
546
    string s = *ps ;
547
    character c = *s ;
548
    IDENTIFIER id = NULL_id ;
549
    if ( c >= char_zero && c <= char_nine ) {
550
	unsigned n = unmangle_no ( &s, 0 ) ;
551
	if ( n ) {
552
	    HASHID nm ;
553
	    int ext = 0 ;
554
	    TYPE t = NULL_type ;
555
	    string p = xustr ( ( gen_size ) ( n + 1 ) ) ;
556
	    string q = p ;
557
	    while ( n ) {
558
		c = *s ;
559
		if ( c ) {
560
		    if ( c == MANGLE_sep && s [1] == MANGLE_sep ) {
561
			/* Allow for unicode characters */
562
			if ( s [2] == MANGLE_unicode4 ) {
563
			    *( q++ ) = char_backslash ;
564
			    c = char_u ;
565
			    ext = 1 ;
566
			    s += 2 ;
567
			} else if ( s [2] == MANGLE_unicode8 ) {
568
			    *( q++ ) = char_backslash ;
569
			    c = char_U ;
570
			    ext = 1 ;
571
			    s += 2 ;
572
			}
573
		    }
574
		    *( q++ ) = c ;
575
		    s++ ;
576
		} else {
577
		    *( q++ ) = char_question ;
578
		}
579
		n-- ;
580
	    }
581
	    *q = 0 ;
582
	    nm = lookup_name ( p, hash ( p ), ext, lex_identifier ) ;
583
	    if ( var ) {
584
		t = type_sint ;
585
		MAKE_id_variable ( nm, dspec_extern, ns, crt_loc, t, id ) ;
586
	    } else {
587
		id = make_class ( ns, nm, btype_lang, dspec_extern, t, t ) ;
588
	    }
589
	}
590
 
591
    } else if ( c == MANGLE_qual ) {
592
	unsigned n ;
593
	s++ ;
594
	n = unmangle_digit ( &s ) ;
595
	while ( n ) {
596
	    NAMESPACE pns ;
597
	    id = unmangle_nspace ( &s, ns, 0 ) ;
598
	    pns = find_namespace ( id ) ;
599
	    if ( !IS_NULL_nspace ( pns ) ) ns = pns ;
600
	    n-- ;
601
	}
602
 
603
    } else if ( c == MANGLE_template ) {
604
	s++ ;
605
	id = unmangle_nspace ( &s, ns, 0 ) ;
606
	if ( !IS_NULL_id ( id ) ) {
607
	    LIST ( TOKEN ) args = unmangle_token_args ( &s ) ;
608
	    TYPE t = make_dummy_class ( id, args, btype_lang ) ;
609
	    CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
610
	    id = DEREF_id ( ctype_name ( ct ) ) ;
611
	}
612
 
613
    } else if ( c == MANGLE_templ_param ) {
614
	TOKEN tok ;
615
	s++ ;
616
	tok = find_token_arg ( &s ) ;
617
	if ( !IS_NULL_tok ( tok ) && IS_tok_type ( tok ) ) {
618
	    TYPE t = DEREF_type ( tok_type_value ( tok ) ) ;
619
	    if ( !IS_NULL_type ( t ) && IS_type_compound ( t ) ) {
620
		CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( t ) ) ;
621
		id = DEREF_id ( ctype_name ( ct ) ) ;
622
	    }
623
	}
624
    }
625
    *ps = s ;
626
    return ( id ) ;
627
}
628
 
629
 
630
/*
631
    UNMANGLE A TOKEN ARGUMENT
632
 
633
    This routine unmangles a token or template argument from the string
634
    pointed to by ps.
635
*/
636
 
637
static TOKEN unmangle_token_arg
638
    PROTO_N ( ( ps ) )
639
    PROTO_T ( string *ps )
640
{
641
    TOKEN tok = NULL_tok ;
642
    string s = *ps ;
643
    character c = *s ;
644
    switch ( c ) {
645
	case MANGLE_nat : {
646
	    /* Integer constant tokens */
647
	    NAT n ;
648
	    s++ ;
649
	    n = unmangle_nat ( &s ) ;
650
	    if ( !IS_NULL_nat ( n ) ) {
651
		MAKE_tok_nat ( n, tok ) ;
652
	    }
653
	    break ;
654
	}
655
	case MANGLE_stmt : {
656
	    /* Statement tokens */
657
	    EXP e ;
658
	    s++ ;
659
	    e = unmangle_exp ( &s, type_void ) ;
660
	    if ( !IS_NULL_exp ( e ) ) {
661
		MAKE_tok_stmt ( e, tok ) ;
662
	    }
663
	    break ;
664
	}
665
	case MANGLE_type : {
666
	    /* Type tokens */
667
	    TYPE t ;
668
	    s++ ;
669
	    t = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
670
	    MAKE_tok_type ( btype_none, t, tok ) ;
671
	    break ;
672
	}
673
	default : {
674
	    /* Expression tokens */
675
	    TYPE t = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
676
	    EXP e = unmangle_exp ( &s, t ) ;
677
	    if ( !IS_NULL_exp ( e ) ) {
678
		MAKE_tok_exp ( t, 0, e, tok ) ;
679
	    }
680
	    break ;
681
	}
682
    }
683
    *ps = s ;
684
    return ( tok ) ;
685
}
686
 
687
 
688
/*
689
    UNMANGLE A LIST OF TOKEN ARGUMENTS
690
 
691
    This routine unmangles a list of token or template arguments from the
692
    string pointed to by ps.
693
*/
694
 
695
static LIST ( TOKEN ) unmangle_token_args
696
    PROTO_N ( ( ps ) )
697
    PROTO_T ( string *ps )
698
{
699
    string s = *ps ;
700
    unsigned n = unmangle_digit ( &s ) ;
701
    LIST ( TOKEN ) args = NULL_list ( TOKEN ) ;
702
    while ( n ) {
703
	TOKEN tok = unmangle_token_arg ( &s ) ;
704
	if ( !IS_NULL_tok ( tok ) ) {
705
	    CONS_tok ( tok, args, args ) ;
706
	}
707
	if ( *s == 0 ) break ;
708
	n-- ;
709
    }
710
    args = REVERSE_list ( args ) ;
711
    *ps = s ;
712
    return ( args ) ;
713
}
714
 
715
 
716
/*
717
    FIND A TOKEN ARGUMENT VALUE
718
 
719
    This routine returns the an argument from the current argument list.
720
    The arguments are numbered from zero.
721
*/
722
 
723
static TOKEN find_token_arg
724
    PROTO_N ( ( ps ) )
725
    PROTO_T ( string *ps )
726
{
727
    unsigned n = unmangle_digit ( ps ) ;
728
    LIST ( TOKEN ) args = crt_unmangle_args ;
729
    while ( !IS_NULL_list ( args ) ) {
730
	if ( n == 0 ) {
731
	    /* Token argument found */
732
	    TOKEN arg = DEREF_tok ( HEAD_list ( args ) ) ;
733
	    return ( arg ) ;
734
	}
735
	n-- ;
736
	args = TAIL_list ( args ) ;
737
    }
738
    return ( NULL_tok ) ;
739
}
740
 
741
 
742
/*
743
    FIND A FUNCTION PARAMETER TYPE
744
 
745
    This routine returns the mth parameter type from the members mem.
746
    The parameters are numbered from one, with n giving the total number
747
    of parameters.
748
*/
749
 
750
static TYPE unmangle_param
751
    PROTO_N ( ( m, n, mem ) )
752
    PROTO_T ( unsigned m X unsigned n X MEMBER mem )
753
{
754
    while ( !IS_NULL_member ( mem ) ) {
755
	IDENTIFIER id = DEREF_id ( member_id ( mem ) ) ;
756
	if ( !IS_NULL_id ( id ) && IS_id_parameter ( id ) ) {
757
	    if ( m == n ) {
758
		/* Parameter type found */
759
		TYPE t = DEREF_type ( id_parameter_type ( id ) ) ;
760
		return ( t ) ;
761
	    }
762
	    m++ ;
763
	}
764
	mem = DEREF_member ( member_next ( mem ) ) ;
765
    }
766
    return ( type_error ) ;
767
}
768
 
769
 
770
/*
771
    UNMANGLE A FUNCTION TYPE
772
 
773
    This routine unmangles a function type from the string pointed to
774
    by ps.
775
*/
776
 
777
static TYPE unmangle_func
778
    PROTO_N ( ( ps, cv, ret ) )
779
    PROTO_T ( string *ps X CV_SPEC cv X int ret )
780
{
781
    TYPE t ;
782
    string s = *ps ;
783
    character c = *s ;
784
    if ( c == MANGLE_const ) {
785
	/* Const member function type */
786
	s++ ;
787
	cv |= cv_const ;
788
	t = unmangle_func ( &s, cv, ret ) ;
789
 
790
    } else if ( c == MANGLE_volatile ) {
791
	/* Volatile member function type */
792
	s++ ;
793
	cv |= cv_volatile ;
794
	t = unmangle_func ( &s, cv, ret ) ;
795
 
796
    } else if ( c == MANGLE_c_lang ) {
797
	/* C linkage function type */
798
	s++ ;
799
	cv |= cv_c ;
800
	t = unmangle_func ( &s, cv, ret ) ;
801
 
802
    } else {
803
	/* Read list of parameter types */
804
	TYPE t1 ;
805
	MEMBER mem ;
806
	NAMESPACE ns ;
807
	unsigned npars = 0 ;
808
	int ell = FUNC_NONE ;
809
	begin_param ( NULL_id ) ;
810
	ns = crt_namespace ;
811
	for ( ; ; ) {
812
	    /* Read parameter types */
813
	    unsigned m ;
814
	    unsigned n = 1 ;
815
	    c = *s ;
816
	    if ( c == 0 ) {
817
		break ;
818
	    } else if ( c == MANGLE_ellipsis ) {
819
		/* Ellipsis */
820
		s++ ;
821
		ell = FUNC_ELLIPSIS ;
822
		break ;
823
	    } else if ( c == MANGLE_repeat ) {
824
		/* Repeated parameter */
825
		s++ ;
826
		m = unmangle_digit ( &s ) ;
827
		mem = DEREF_member ( nspace_last ( ns ) ) ;
828
		t1 = unmangle_param ( m, npars, mem ) ;
829
	    } else if ( c == MANGLE_multi ) {
830
		/* Multiply repeated parameter */
831
		s++ ;
832
		n = unmangle_digit ( &s ) ;
833
		m = unmangle_no ( &s, 1 ) ;
834
		mem = DEREF_member ( nspace_last ( ns ) ) ;
835
		t1 = unmangle_param ( m, npars, mem ) ;
836
	    } else {
837
		/* Simple parameter type */
838
		t1 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
839
		if ( IS_type_error ( t1 ) ) break ;
840
	    }
841
	    while ( n ) {
842
		/* Declare parameters */
843
		DECL_SPEC ds = dspec_none ;
844
		HASHID nm = lookup_anon () ;
845
		IDENTIFIER pid = DEREF_id ( hashid_id ( nm ) ) ;
846
		pid = make_param_decl ( ds, t1, pid, CONTEXT_PARAMETER ) ;
847
		init_param ( pid, NULL_exp ) ;
848
		npars++ ;
849
		n-- ;
850
	    }
851
	}
852
	t = make_func_type ( dummy_ret_type, ell, cv, empty_type_set ) ;
853
	end_param () ;
854
	if ( ret ) {
855
	    /* Read return type */
856
	    c = *( s++ ) ;
857
	    if ( c == MANGLE_sep ) {
858
		t1 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
859
	    } else {
860
		t1 = type_error ;
861
		s-- ;
862
	    }
863
	    COPY_type ( type_func_ret ( t ), NULL_type ) ;
864
	    t = inject_pre_type ( t, t1, 0 ) ;
865
	}
866
    }
867
    *ps = s ;
868
    return ( t ) ;
869
}
870
 
871
 
872
/*
873
    UNMANGLE A TYPE
874
 
875
    This routine unmangles a type from the string pointed to by ps.
876
*/
877
 
878
static TYPE unmangle_type
879
    PROTO_N ( ( ps, cv, bt, ret ) )
880
    PROTO_T ( string *ps X CV_SPEC cv X BASE_TYPE bt X int ret )
881
{
882
    TYPE t ;
883
    string s = *ps ;
884
    character c = *( s++ ) ;
885
    switch ( c ) {
886
 
887
	case MANGLE_char : t = make_base_type ( bt | btype_char ) ; break ;
888
	case MANGLE_short : t = make_base_type ( bt | btype_short ) ; break ;
889
	case MANGLE_int : t = make_base_type ( bt | btype_int ) ; break ;
890
	case MANGLE_long : t = make_base_type ( bt | btype_long ) ; break ;
891
	case MANGLE_llong : t = make_base_type ( bt | btype_llong ) ; break ;
892
 
893
	case MANGLE_float : t = type_float ; break ;
894
	case MANGLE_double : t = type_double ; break ;
895
	case MANGLE_ldouble : t = type_ldouble ; break ;
896
	case MANGLE_void : t = type_void ; break ;
897
	case MANGLE_bottom : t = type_bottom ; break ;
898
	case MANGLE_bool : t = type_bool ; break ;
899
	case MANGLE_ptrdiff_t : t = type_ptrdiff_t ; break ;
900
	case MANGLE_size_t : t = type_size_t ; break ;
901
	case MANGLE_wchar_t : t = type_wchar_t ; break ;
902
 
903
	case MANGLE_signed : {
904
	    /* Signed types */
905
	    bt |= btype_signed ;
906
	    t = unmangle_type ( &s, cv_none, bt, ret ) ;
907
	    break ;
908
	}
909
 
910
	case MANGLE_unsigned : {
911
	    /* Unsigned types */
912
	    bt |= btype_unsigned ;
913
	    t = unmangle_type ( &s, cv_none, bt, ret ) ;
914
	    break ;
915
	}
916
 
917
	case MANGLE_const : {
918
	    /* Const types */
919
	    cv |= cv_const ;
920
	    t = unmangle_type ( &s, cv, bt, ret ) ;
921
	    cv = cv_none ;
922
	    break ;
923
	}
924
 
925
	case MANGLE_volatile : {
926
	    /* Volatile types */
927
	    cv |= cv_volatile ;
928
	    t = unmangle_type ( &s, cv, bt, ret ) ;
929
	    cv = cv_none ;
930
	    break ;
931
	}
932
 
933
	case MANGLE_ptr : {
934
	    /* Pointer types */
935
	    TYPE t1 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
936
	    MAKE_type_ptr ( cv, NULL_type, t ) ;
937
	    t = inject_pre_type ( t, t1, 0 ) ;
938
	    cv = cv_none ;
939
	    break ;
940
	}
941
 
942
	case MANGLE_ref : {
943
	    /* Reference types */
944
	    TYPE t1 = unmangle_type ( &s, cv, btype_none, 1 ) ;
945
	    MAKE_type_ref ( cv_none, NULL_type, t ) ;
946
	    t = inject_pre_type ( t, t1, 0 ) ;
947
	    cv = cv_none ;
948
	    break ;
949
	}
950
 
951
	case MANGLE_ptr_mem : {
952
	    /* Pointer to member types */
953
	    TYPE t1 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
954
	    TYPE t2 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
955
	    if ( IS_type_compound ( t1 ) ) {
956
		CLASS_TYPE c1 = DEREF_ctype ( type_compound_defn ( t1 ) ) ;
957
		MAKE_type_ptr_mem ( cv, c1, NULL_type, t ) ;
958
	    } else {
959
		report ( crt_loc, ERR_dcl_mptr_class ( t1 ) ) ;
960
		MAKE_type_ptr ( cv, NULL_type, t ) ;
961
	    }
962
	    t = inject_pre_type ( t, t2, 0 ) ;
963
	    cv = cv_none ;
964
	    break ;
965
	}
966
 
967
	case MANGLE_func : {
968
	    /* Function types */
969
	    t = unmangle_func ( &s, cv, ret ) ;
970
	    cv = cv_none ;
971
	    break ;
972
	}
973
 
974
	case MANGLE_array : {
975
	    /* Array types */
976
	    NAT n = unmangle_nat ( &s ) ;
977
	    TYPE t1 = unmangle_type ( &s, cv, btype_none, 1 ) ;
978
	    n = check_array_dim ( n ) ;
979
	    MAKE_type_array ( cv_none, NULL_type, n, t ) ;
980
	    t = inject_pre_type ( t, t1, 0 ) ;
981
	    cv = cv_none ;
982
	    break ;
983
	}
984
 
985
	case MANGLE_bitfield : {
986
	    /* Bitfield types */
987
	    TYPE t1 ;
988
	    NAT n = unmangle_nat ( &s ) ;
989
	    BASE_TYPE b1 = btype_named ;
990
	    if ( *s == MANGLE_signed ) b1 |= btype_signed ;
991
	    t1 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
992
	    b1 = get_bitfield_rep ( t1, b1 ) ;
993
	    t = check_bitfield_type ( cv, t1, b1, n, 0 ) ;
994
	    cv = cv_none ;
995
	    break ;
996
	}
997
 
998
	case MANGLE_template : {
999
	    /* Template class types */
1000
	    IDENTIFIER id = unmangle_nspace ( &s, global_namespace, 0 ) ;
1001
	    if ( IS_NULL_id ( id ) ) {
1002
		t = type_error ;
1003
	    } else {
1004
		LIST ( TOKEN ) args = unmangle_token_args ( &s ) ;
1005
		MAKE_type_token ( cv, id, args, t ) ;
1006
		cv = cv_none ;
1007
	    }
1008
	    break ;
1009
	}
1010
 
1011
	case MANGLE_templ_param : {
1012
	    /* Template parameter types */
1013
	    TOKEN tok = find_token_arg ( &s ) ;
1014
	    if ( !IS_NULL_tok ( tok ) && IS_tok_type ( tok ) ) {
1015
		t = DEREF_type ( tok_type_value ( tok ) ) ;
1016
	    } else {
1017
		t = type_error ;
1018
	    }
1019
	    break ;
1020
	}
1021
 
1022
	case MANGLE_promote : {
1023
	    /* Promotion types */
1024
	    TYPE t1 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
1025
	    t = promote_type ( t1 ) ;
1026
	    break ;
1027
	}
1028
 
1029
	case MANGLE_arith : {
1030
	    /* Arithmetic types */
1031
	    TYPE t1 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
1032
	    TYPE t2 = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
1033
	    t = arith_type ( t1, t2, NULL_exp, NULL_exp ) ;
1034
	    break ;
1035
	}
1036
 
1037
	case MANGLE_literal : {
1038
	    /* Literal types */
1039
	    NAT n ;
1040
	    int fit = 0 ;
1041
	    int form = BASE_DECIMAL ;
1042
	    int suff = SUFFIX_NONE ;
1043
	    c = *s ;
1044
	    if ( c == MANGLE_octal ) {
1045
		form = BASE_OCTAL ;
1046
		c = *( ++s ) ;
1047
	    } else if ( c == MANGLE_hex ) {
1048
		form = BASE_HEXADECIMAL ;
1049
		c = *( ++s ) ;
1050
	    }
1051
	    if ( c == MANGLE_unsigned ) {
1052
		suff |= SUFFIX_U ;
1053
		c = *( ++s ) ;
1054
	    }
1055
	    if ( c == MANGLE_long ) {
1056
		suff |= SUFFIX_L ;
1057
		c = *( ++s ) ;
1058
	    }
1059
	    if ( c == MANGLE_llong ) {
1060
		suff |= SUFFIX_LL ;
1061
		s++ ;
1062
	    }
1063
	    n = unmangle_nat ( &s ) ;
1064
	    if ( IS_NULL_nat ( n ) ) n = small_nat [0] ;
1065
	    t = find_literal_type ( n, form, suff, NULL_string, &fit ) ;
1066
	    break ;
1067
	}
1068
 
1069
	case MANGLE_self : {
1070
	    /* Parent class type */
1071
	    IDENTIFIER self = crt_unmangle_class ;
1072
	    if ( IS_NULL_id ( self ) ) {
1073
		t = type_error ;
1074
	    } else {
1075
		t = DEREF_type ( id_class_name_etc_defn ( self ) ) ;
1076
	    }
1077
	    break ;
1078
	}
1079
 
1080
	case char_zero : case char_one : case char_two :
1081
	case char_three : case char_four : case char_five :
1082
	case char_six : case char_seven : case char_eight :
1083
	case char_nine : case MANGLE_qual : {
1084
	    /* Named types */
1085
	    IDENTIFIER id ;
1086
	    s-- ;
1087
	    id = unmangle_nspace ( &s, global_namespace, 0 ) ;
1088
	    if ( IS_NULL_id ( id ) ) {
1089
		t = type_error ;
1090
	    } else {
1091
		t = DEREF_type ( id_class_name_etc_defn ( id ) ) ;
1092
	    }
1093
	    break ;
1094
	}
1095
 
1096
	default : {
1097
	    /* Invalid mangled types */
1098
	    if ( bt == btype_none && cv == cv_none ) {
1099
		t = type_error ;
1100
	    } else {
1101
		t = make_base_type ( bt | btype_int ) ;
1102
	    }
1103
	    s-- ;
1104
	    break ;
1105
	}
1106
    }
1107
    if ( cv ) t = qualify_type ( t, cv, 0 ) ;
1108
    *ps = s ;
1109
    return ( t ) ;
1110
}
1111
 
1112
 
1113
/*
1114
    UNMANGLE AN IDENTIFIER NAME
1115
 
1116
    This routine unmangles the identifier s into the buffer bf.
1117
*/
1118
 
1119
static string unmangle_name
1120
    PROTO_N ( ( s, bf ) )
1121
    PROTO_T ( string s X BUFFER *bf )
1122
{
1123
    int func = 0 ;
1124
    int op = lex_identifier ;
1125
    IDENTIFIER id = NULL_id ;
1126
    HASHID nm = NULL_hashid ;
1127
 
1128
    /* Check names beginning with '__' */
1129
    if ( s [0] == '_' && s [1] == '_' ) {
1130
	string s0 = s + 2 ;
1131
	op = unmangle_op ( &s0 ) ;
1132
	if ( op == lex_unknown ) {
1133
#if ( TDF_major < 4 )
1134
	    if ( ustrseq ( s, "__MAIN__" ) s = ustrlit ( "main" ) ;
1135
#endif
1136
	    bfputs ( bf, s ) ;
1137
	    return ( NULL ) ;
1138
	}
1139
	s = s0 ;
1140
    }
1141
 
1142
    /* Read identifier name */
1143
    switch ( op ) {
1144
 
1145
	case lex_identifier : {
1146
	    /* Identifier name */
1147
	    character c ;
1148
	    int ext = 0 ;
1149
	    unsigned long h ;
1150
	    BUFFER *tf = clear_buffer ( &token_buff, NIL ( FILE ) ) ;
1151
	    while ( c = *s, c != 0 ) {
1152
		if ( c == MANGLE_sep && s [1] == MANGLE_sep ) {
1153
		    c = s [2] ;
1154
		    if ( c == MANGLE_unicode4 ) {
1155
			bfputc ( tf, char_backslash ) ;
1156
			c = char_u ;
1157
			ext = 1 ;
1158
			s += 2 ;
1159
		    } else if ( c == MANGLE_unicode8 ) {
1160
			bfputc ( tf, char_backslash ) ;
1161
			c = char_U ;
1162
			ext = 1 ;
1163
			s += 2 ;
1164
		    } else {
1165
			break ;
1166
		    }
1167
		}
1168
		bfputc ( tf, ( int ) c ) ;
1169
		s++ ;
1170
	    }
1171
	    bfputc ( tf, 0 ) ;
1172
	    h = hash ( tf->start ) ;
1173
	    nm = lookup_name ( tf->start, h, ext, lex_unknown ) ;
1174
	    id = DEREF_id ( hashid_id ( nm ) ) ;
1175
	    break ;
1176
	}
1177
 
1178
	case lex_type_Hname :
1179
	case lex_destructor_Hname : {
1180
	    /* Constructor and destructor names */
1181
	    func = 1 ;
1182
	    break ;
1183
	}
1184
 
1185
	case lex_operator : {
1186
	    /* Conversion function name */
1187
	    TYPE t = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
1188
	    nm = lookup_conv ( t ) ;
1189
	    id = DEREF_id ( hashid_id ( nm ) ) ;
1190
	    func = 1 ;
1191
	    break ;
1192
	}
1193
 
1194
	case lex_auto : {
1195
	    /* Anonymous identifier */
1196
	    bfprintf ( bf, "<anon>" ) ;
1197
	    return ( NULL ) ;
1198
	}
1199
 
1200
	case lex_static : {
1201
	    /* Local static variable */
1202
	    bfprintf ( bf, "<static>" ) ;
1203
	    return ( NULL ) ;
1204
	}
1205
 
1206
	case lex_typeof : {
1207
	    /* Run-time type information */
1208
	    TYPE t = unmangle_type ( &s, cv_none, btype_none, 1 ) ;
1209
	    bfprintf ( bf, "typeid ( " ) ;
1210
	    IGNORE print_type ( t, bf, 0 ) ;
1211
	    bfprintf ( bf, " )" ) ;
1212
	    return ( s ) ;
1213
	}
1214
 
1215
	case lex_virtual : {
1216
	    /* Virtual function table */
1217
	    int sep = 0 ;
1218
	    bfprintf ( bf, "vtable ( " ) ;
1219
	    for ( ; ; ) {
1220
		id = unmangle_nspace ( &s, global_namespace, 0 ) ;
1221
		if ( IS_NULL_id ( id ) ) break ;
1222
		if ( sep ) bfprintf ( bf, "::" ) ;
1223
		IGNORE print_id_long ( id, qual_none, bf, 0 ) ;
1224
		sep = 1 ;
1225
	    }
1226
	    if ( !sep ) bfprintf ( bf, "<error>" ) ;
1227
	    bfprintf ( bf, " )" ) ;
1228
	    return ( s ) ;
1229
	}
1230
 
1231
	default : {
1232
	    /* Operator name */
1233
	    nm = lookup_op ( op ) ;
1234
	    if ( !IS_NULL_hashid ( nm ) ) {
1235
		id = DEREF_id ( hashid_id ( nm ) ) ;
1236
		func = 1 ;
1237
	    }
1238
	    break ;
1239
	}
1240
    }
1241
 
1242
    /* Unmangle identifier namespace and type */
1243
    if ( s [0] == MANGLE_sep && s [1] == MANGLE_sep ) {
1244
	TYPE t ;
1245
	string s0 = s + 2 ;
1246
	NAMESPACE pns = global_namespace ;
1247
	IDENTIFIER pid = unmangle_nspace ( &s0, pns, 0 ) ;
1248
	character c = *s0 ;
1249
	if ( c == MANGLE_func_templ ) {
1250
	    /* Allow for template functions */
1251
	    s0++ ;
1252
	    crt_unmangle_args = unmangle_token_args ( &s0 ) ;
1253
	    if ( *s0 == MANGLE_sep ) s0++ ;
1254
	}
1255
 
1256
	/* Unmangle identifier type */
1257
	if ( func ) {
1258
	    crt_unmangle_class = pid ;
1259
	    t = unmangle_func ( &s0, cv_none, 0 ) ;
1260
	} else {
1261
	    if ( c == 0 && !IS_NULL_id ( pid ) ) {
1262
		t = DEREF_type ( id_class_name_etc_defn ( pid ) ) ;
1263
		pid = NULL_id ;
1264
	    } else {
1265
		crt_unmangle_class = pid ;
1266
		t = unmangle_type ( &s0, cv_none, btype_none, 0 ) ;
1267
	    }
1268
	}
1269
	if ( IS_NULL_id ( pid ) ) {
1270
	    member_func_type ( NULL_ctype, id_function_tag, t ) ;
1271
	}
1272
 
1273
	/* Look up constructor and destructor names */
1274
	if ( !IS_NULL_id ( pid ) ) {
1275
	    TYPE p = DEREF_type ( id_class_name_etc_defn ( pid ) ) ;
1276
	    if ( IS_type_compound ( p ) ) {
1277
		CLASS_TYPE ct = DEREF_ctype ( type_compound_defn ( p ) ) ;
1278
		pns = DEREF_nspace ( ctype_member ( ct ) ) ;
1279
		if ( op == lex_type_Hname ) {
1280
		    id = DEREF_id ( ctype_constr ( ct ) ) ;
1281
		    nm = DEREF_hashid ( id_name ( id ) ) ;
1282
		} else if ( op == lex_destructor_Hname ) {
1283
		    id = DEREF_id ( ctype_destr ( ct ) ) ;
1284
		    nm = DEREF_hashid ( id_name ( id ) ) ;
1285
		}
1286
	    }
1287
	}
1288
	if ( IS_NULL_hashid ( nm ) ) nm = KEYWORD ( lex_zzzz ) ;
1289
 
1290
	/* Create result identifier */
1291
	MAKE_id_function ( nm, dspec_extern, pns, crt_loc, t, NULL_id, id ) ;
1292
	if ( c == MANGLE_func_templ ) {
1293
	    /* Set up template function arguments */
1294
	    TYPE form ;
1295
	    DECL_SPEC ds = ( dspec_extern | dspec_instance ) ;
1296
	    MAKE_type_token ( cv_none, id, crt_unmangle_args, form ) ;
1297
	    MAKE_id_function ( nm, ds, pns, crt_loc, t, NULL_id, id ) ;
1298
	    COPY_type ( id_function_form ( id ), form ) ;
1299
	}
1300
	crt_unmangle_args = NULL_list ( TOKEN ) ;
1301
	crt_unmangle_class = NULL_id ;
1302
	s = s0 ;
1303
    }
1304
 
1305
    /* Print identifier to buffer */
1306
    if ( IS_NULL_id ( id ) ) {
1307
	bfprintf ( bf, "<error>" ) ;
1308
	s = NULL ;
1309
    } else {
1310
	print_id_desc++ ;
1311
	IGNORE print_id_long ( id, qual_none, bf, 0 ) ;
1312
	print_id_desc-- ;
1313
    }
1314
    return ( s ) ;
1315
}
1316
 
1317
 
1318
/*
1319
    INITIALISE UNMANGLING ROUTINES
1320
 
1321
    This routine initialises the unmangling routines.
1322
*/
1323
 
1324
static void init_unmangle
1325
    PROTO_Z ()
1326
{
1327
    static int done = 0 ;
1328
    if ( !done ) {
1329
	MAKE_type_pre ( cv_none, btype_none, qual_none, dummy_ret_type ) ;
1330
	done = 1 ;
1331
    }
1332
    return ;
1333
}
1334
 
1335
 
1336
/*
1337
    END OF LANGUAGE DEPENDENT ROUTINES
1338
 
1339
    The remaining routine is the only one included in the C producer.
1340
*/
1341
 
1342
#endif
1343
 
1344
 
1345
/*
1346
    UNMANGLE A LIST OF IDENTIFIER NAMES
1347
 
1348
    This routine unmangles the list of identifier names p to the file f.
1349
*/
1350
 
1351
void unmangle_list
1352
    PROTO_N ( ( p, f, pre ) )
1353
    PROTO_T ( LIST ( string ) p X FILE *f X int pre )
1354
{
1355
#if LANGUAGE_CPP
1356
    init_unmangle () ;
1357
#endif
1358
    while ( !IS_NULL_list ( p ) ) {
1359
	string s = DEREF_string ( HEAD_list ( p ) ) ;
1360
	if ( s ) {
1361
	    BUFFER *bf = clear_buffer ( &mangle_buff, f ) ;
1362
	    if ( pre ) {
1363
		/* Print mapping information */
1364
		bfprintf ( bf, "%s -> ", s ) ;
1365
	    }
1366
#if LANGUAGE_CPP
1367
	    s = unmangle_name ( s, bf ) ;
1368
	    if ( s && *s ) bfprintf ( bf, " ?" ) ;
1369
#else
1370
	    bfputs ( bf, s ) ;
1371
#endif
1372
	    bfputc ( bf, '\n' ) ;
1373
	    output_buffer ( bf, 1 ) ;
1374
	}
1375
	p = TAIL_list ( p ) ;
1376
    }
1377
    fflush_v ( f ) ;
1378
    return ;
1379
}