-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcplus-dem.c
5032 lines (4410 loc) · 124 KB
/
cplus-dem.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Demangler for GNU C++
Copyright (C) 1989-2017 Free Software Foundation, Inc.
Written by James Clark ([email protected])
Rewritten by Fred Fish ([email protected]) for ARM and Lucid demangling
Modified by Satish Pai ([email protected]) for HP demangling
This file is part of the libiberty library.
Libiberty is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
In addition to the permissions in the GNU Library General Public
License, the Free Software Foundation gives you unlimited permission
to link the compiled version of this file into combinations with other
programs, and to distribute those combinations without any restriction
coming from the use of this file. (The Library Public License
restrictions do apply in other respects; for example, they cover
modification of the file, and distribution when not linked into a
combined executable.)
Libiberty is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with libiberty; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
Boston, MA 02110-1301, USA. */
/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
This file imports xmalloc and xrealloc, which are like malloc and
realloc except that they generate a fatal error if there is no
available memory. */
/* This file lives in both GCC and libiberty. When making changes, please
try not to break either. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "safe-ctype.h"
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#else
void * malloc ();
void * realloc ();
#endif
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#ifndef INT_MAX
# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */
#endif
#include <demangle.h>
#undef CURRENT_DEMANGLING_STYLE
#define CURRENT_DEMANGLING_STYLE work->options
#include "libiberty.h"
#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
/* A value at least one greater than the maximum number of characters
that will be output when using the `%d' format with `printf'. */
#define INTBUF_SIZE 32
extern void fancy_abort (void) ATTRIBUTE_NORETURN;
/* In order to allow a single demangler executable to demangle strings
using various common values of CPLUS_MARKER, as well as any specific
one set at compile time, we maintain a string containing all the
commonly used ones, and check to see if the marker we are looking for
is in that string. CPLUS_MARKER is usually '$' on systems where the
assembler can deal with that. Where the assembler can't, it's usually
'.' (but on many systems '.' is used for other things). We put the
current defined CPLUS_MARKER first (which defaults to '$'), followed
by the next most common value, followed by an explicit '$' in case
the value of CPLUS_MARKER is not '$'.
We could avoid this if we could just get g++ to tell us what the actual
cplus marker character is as part of the debug information, perhaps by
ensuring that it is the character that terminates the gcc<n>_compiled
marker symbol (FIXME). */
#if !defined (CPLUS_MARKER)
#define CPLUS_MARKER '$'
#endif
enum demangling_styles current_demangling_style = auto_demangling;
static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
static char char_str[2] = { '\000', '\000' };
void
set_cplus_marker_for_demangling (int ch)
{
cplus_markers[0] = ch;
}
typedef struct string /* Beware: these aren't required to be */
{ /* '\0' terminated. */
char *b; /* pointer to start of string */
char *p; /* pointer after last character */
char *e; /* pointer after end of allocated space */
} string;
/* Stuff that is shared between sub-routines.
Using a shared structure allows cplus_demangle to be reentrant. */
struct work_stuff
{
int options;
char **typevec;
char **ktypevec;
char **btypevec;
int numk;
int numb;
int ksize;
int bsize;
int ntypes;
int typevec_size;
int constructor;
int destructor;
int static_type; /* A static member function */
int temp_start; /* index in demangled to start of template args */
int type_quals; /* The type qualifiers. */
int dllimported; /* Symbol imported from a PE DLL */
char **tmpl_argvec; /* Template function arguments. */
int ntmpl_args; /* The number of template function arguments. */
int forgetting_types; /* Nonzero if we are not remembering the types
we see. */
string* previous_argument; /* The last function argument demangled. */
int nrepeats; /* The number of times to repeat the previous
argument. */
int *proctypevec; /* Indices of currently processed remembered typevecs. */
int proctypevec_size;
int nproctypes;
};
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
static const struct optable
{
const char *const in;
const char *const out;
const int flags;
} optable[] = {
{"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
{"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */
{"new", " new", 0}, /* old (1.91, and 1.x) */
{"delete", " delete", 0}, /* old (1.91, and 1.x) */
{"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */
{"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */
{"as", "=", DMGL_ANSI}, /* ansi */
{"ne", "!=", DMGL_ANSI}, /* old, ansi */
{"eq", "==", DMGL_ANSI}, /* old, ansi */
{"ge", ">=", DMGL_ANSI}, /* old, ansi */
{"gt", ">", DMGL_ANSI}, /* old, ansi */
{"le", "<=", DMGL_ANSI}, /* old, ansi */
{"lt", "<", DMGL_ANSI}, /* old, ansi */
{"plus", "+", 0}, /* old */
{"pl", "+", DMGL_ANSI}, /* ansi */
{"apl", "+=", DMGL_ANSI}, /* ansi */
{"minus", "-", 0}, /* old */
{"mi", "-", DMGL_ANSI}, /* ansi */
{"ami", "-=", DMGL_ANSI}, /* ansi */
{"mult", "*", 0}, /* old */
{"ml", "*", DMGL_ANSI}, /* ansi */
{"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
{"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
{"convert", "+", 0}, /* old (unary +) */
{"negate", "-", 0}, /* old (unary -) */
{"trunc_mod", "%", 0}, /* old */
{"md", "%", DMGL_ANSI}, /* ansi */
{"amd", "%=", DMGL_ANSI}, /* ansi */
{"trunc_div", "/", 0}, /* old */
{"dv", "/", DMGL_ANSI}, /* ansi */
{"adv", "/=", DMGL_ANSI}, /* ansi */
{"truth_andif", "&&", 0}, /* old */
{"aa", "&&", DMGL_ANSI}, /* ansi */
{"truth_orif", "||", 0}, /* old */
{"oo", "||", DMGL_ANSI}, /* ansi */
{"truth_not", "!", 0}, /* old */
{"nt", "!", DMGL_ANSI}, /* ansi */
{"postincrement","++", 0}, /* old */
{"pp", "++", DMGL_ANSI}, /* ansi */
{"postdecrement","--", 0}, /* old */
{"mm", "--", DMGL_ANSI}, /* ansi */
{"bit_ior", "|", 0}, /* old */
{"or", "|", DMGL_ANSI}, /* ansi */
{"aor", "|=", DMGL_ANSI}, /* ansi */
{"bit_xor", "^", 0}, /* old */
{"er", "^", DMGL_ANSI}, /* ansi */
{"aer", "^=", DMGL_ANSI}, /* ansi */
{"bit_and", "&", 0}, /* old */
{"ad", "&", DMGL_ANSI}, /* ansi */
{"aad", "&=", DMGL_ANSI}, /* ansi */
{"bit_not", "~", 0}, /* old */
{"co", "~", DMGL_ANSI}, /* ansi */
{"call", "()", 0}, /* old */
{"cl", "()", DMGL_ANSI}, /* ansi */
{"alshift", "<<", 0}, /* old */
{"ls", "<<", DMGL_ANSI}, /* ansi */
{"als", "<<=", DMGL_ANSI}, /* ansi */
{"arshift", ">>", 0}, /* old */
{"rs", ">>", DMGL_ANSI}, /* ansi */
{"ars", ">>=", DMGL_ANSI}, /* ansi */
{"component", "->", 0}, /* old */
{"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
{"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
{"indirect", "*", 0}, /* old */
{"method_call", "->()", 0}, /* old */
{"addr", "&", 0}, /* old (unary &) */
{"array", "[]", 0}, /* old */
{"vc", "[]", DMGL_ANSI}, /* ansi */
{"compound", ", ", 0}, /* old */
{"cm", ", ", DMGL_ANSI}, /* ansi */
{"cond", "?:", 0}, /* old */
{"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
{"max", ">?", 0}, /* old */
{"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
{"min", "<?", 0}, /* old */
{"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
{"nop", "", 0}, /* old (for operator=) */
{"rm", "->*", DMGL_ANSI}, /* ansi */
{"sz", "sizeof ", DMGL_ANSI} /* pseudo-ansi */
};
/* These values are used to indicate the various type varieties.
They are all non-zero so that they can be used as `success'
values. */
typedef enum type_kind_t
{
tk_none,
tk_pointer,
tk_reference,
tk_rvalue_reference,
tk_integral,
tk_bool,
tk_char,
tk_real
} type_kind_t;
const struct demangler_engine libiberty_demanglers[] =
{
{
NO_DEMANGLING_STYLE_STRING,
no_demangling,
"Demangling disabled"
}
,
{
AUTO_DEMANGLING_STYLE_STRING,
auto_demangling,
"Automatic selection based on executable"
}
,
{
GNU_DEMANGLING_STYLE_STRING,
gnu_demangling,
"GNU (g++) style demangling"
}
,
{
LUCID_DEMANGLING_STYLE_STRING,
lucid_demangling,
"Lucid (lcc) style demangling"
}
,
{
ARM_DEMANGLING_STYLE_STRING,
arm_demangling,
"ARM style demangling"
}
,
{
HP_DEMANGLING_STYLE_STRING,
hp_demangling,
"HP (aCC) style demangling"
}
,
{
EDG_DEMANGLING_STYLE_STRING,
edg_demangling,
"EDG style demangling"
}
,
{
GNU_V3_DEMANGLING_STYLE_STRING,
gnu_v3_demangling,
"GNU (g++) V3 ABI-style demangling"
}
,
{
JAVA_DEMANGLING_STYLE_STRING,
java_demangling,
"Java style demangling"
}
,
{
GNAT_DEMANGLING_STYLE_STRING,
gnat_demangling,
"GNAT style demangling"
}
,
{
DLANG_DEMANGLING_STYLE_STRING,
dlang_demangling,
"DLANG style demangling"
}
,
{
RUST_DEMANGLING_STYLE_STRING,
rust_demangling,
"Rust style demangling"
}
,
{
NULL, unknown_demangling, NULL
}
};
#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
string_append(str, " ");}
#define LEN_STRING(str) ( (STRING_EMPTY(str))?0:((str)->p - (str)->b))
/* The scope separator appropriate for the language being demangled. */
#define SCOPE_STRING(work) ((work->options & DMGL_JAVA) ? "." : "::")
#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
/* Prototypes for local functions */
static void delete_work_stuff (struct work_stuff *);
static void delete_non_B_K_work_stuff (struct work_stuff *);
static char *mop_up (struct work_stuff *, string *, int);
static void squangle_mop_up (struct work_stuff *);
static void work_stuff_copy_to_from (struct work_stuff *, struct work_stuff *);
#if 0
static int
demangle_method_args (struct work_stuff *, const char **, string *);
#endif
static char *
internal_cplus_demangle (struct work_stuff *, const char *);
static int
demangle_template_template_parm (struct work_stuff *work,
const char **, string *);
static int
demangle_template (struct work_stuff *work, const char **, string *,
string *, int, int);
static int
arm_pt (struct work_stuff *, const char *, int, const char **,
const char **);
static int
demangle_class_name (struct work_stuff *, const char **, string *);
static int
demangle_qualified (struct work_stuff *, const char **, string *,
int, int);
static int demangle_class (struct work_stuff *, const char **, string *);
static int demangle_fund_type (struct work_stuff *, const char **, string *);
static int demangle_signature (struct work_stuff *, const char **, string *);
static int demangle_prefix (struct work_stuff *, const char **, string *);
static int gnu_special (struct work_stuff *, const char **, string *);
static int arm_special (const char **, string *);
static void string_need (string *, int);
static void string_delete (string *);
static void
string_init (string *);
static void string_clear (string *);
#if 0
static int string_empty (string *);
#endif
static void string_append (string *, const char *);
static void string_appends (string *, string *);
static void string_appendn (string *, const char *, int);
static void string_prepend (string *, const char *);
static void string_prependn (string *, const char *, int);
static void string_append_template_idx (string *, int);
static int get_count (const char **, int *);
static int consume_count (const char **);
static int consume_count_with_underscores (const char**);
static int demangle_args (struct work_stuff *, const char **, string *);
static int demangle_nested_args (struct work_stuff*, const char**, string*);
static int do_type (struct work_stuff *, const char **, string *);
static int do_arg (struct work_stuff *, const char **, string *);
static int
demangle_function_name (struct work_stuff *, const char **, string *,
const char *);
static int
iterate_demangle_function (struct work_stuff *,
const char **, string *, const char *);
static void remember_type (struct work_stuff *, const char *, int);
static void push_processed_type (struct work_stuff *, int);
static void pop_processed_type (struct work_stuff *);
static void remember_Btype (struct work_stuff *, const char *, int, int);
static int register_Btype (struct work_stuff *);
static void remember_Ktype (struct work_stuff *, const char *, int);
static void forget_types (struct work_stuff *);
static void forget_B_and_K_types (struct work_stuff *);
static void string_prepends (string *, string *);
static int
demangle_template_value_parm (struct work_stuff*, const char**,
string*, type_kind_t);
static int
do_hpacc_template_const_value (struct work_stuff *, const char **, string *);
static int
do_hpacc_template_literal (struct work_stuff *, const char **, string *);
static int snarf_numeric_literal (const char **, string *);
/* There is a TYPE_QUAL value for each type qualifier. They can be
combined by bitwise-or to form the complete set of qualifiers for a
type. */
#define TYPE_UNQUALIFIED 0x0
#define TYPE_QUAL_CONST 0x1
#define TYPE_QUAL_VOLATILE 0x2
#define TYPE_QUAL_RESTRICT 0x4
static int code_for_qualifier (int);
static const char* qualifier_string (int);
static const char* demangle_qualifier (int);
static int demangle_expression (struct work_stuff *, const char **, string *,
type_kind_t);
static int
demangle_integral_value (struct work_stuff *, const char **, string *);
static int
demangle_real_value (struct work_stuff *, const char **, string *);
static void
demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
static void
recursively_demangle (struct work_stuff *, const char **, string *, int);
/* Translate count to integer, consuming tokens in the process.
Conversion terminates on the first non-digit character.
Trying to consume something that isn't a count results in no
consumption of input and a return of -1.
Overflow consumes the rest of the digits, and returns -1. */
static int
consume_count (const char **type)
{
int count = 0;
if (! ISDIGIT ((unsigned char)**type))
return -1;
while (ISDIGIT ((unsigned char)**type))
{
const int digit = **type - '0';
/* Check for overflow. */
if (count > ((INT_MAX - digit) / 10))
{
while (ISDIGIT ((unsigned char) **type))
(*type)++;
return -1;
}
count *= 10;
count += digit;
(*type)++;
}
if (count < 0)
count = -1;
return (count);
}
/* Like consume_count, but for counts that are preceded and followed
by '_' if they are greater than 10. Also, -1 is returned for
failure, since 0 can be a valid value. */
static int
consume_count_with_underscores (const char **mangled)
{
int idx;
if (**mangled == '_')
{
(*mangled)++;
if (!ISDIGIT ((unsigned char)**mangled))
return -1;
idx = consume_count (mangled);
if (**mangled != '_')
/* The trailing underscore was missing. */
return -1;
(*mangled)++;
}
else
{
if (**mangled < '0' || **mangled > '9')
return -1;
idx = **mangled - '0';
(*mangled)++;
}
return idx;
}
/* C is the code for a type-qualifier. Return the TYPE_QUAL
corresponding to this qualifier. */
static int
code_for_qualifier (int c)
{
switch (c)
{
case 'C':
return TYPE_QUAL_CONST;
case 'V':
return TYPE_QUAL_VOLATILE;
case 'u':
return TYPE_QUAL_RESTRICT;
default:
break;
}
/* C was an invalid qualifier. */
abort ();
}
/* Return the string corresponding to the qualifiers given by
TYPE_QUALS. */
static const char*
qualifier_string (int type_quals)
{
switch (type_quals)
{
case TYPE_UNQUALIFIED:
return "";
case TYPE_QUAL_CONST:
return "const";
case TYPE_QUAL_VOLATILE:
return "volatile";
case TYPE_QUAL_RESTRICT:
return "__restrict";
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
return "const volatile";
case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
return "const __restrict";
case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
return "volatile __restrict";
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
return "const volatile __restrict";
default:
break;
}
/* TYPE_QUALS was an invalid qualifier set. */
abort ();
}
/* C is the code for a type-qualifier. Return the string
corresponding to this qualifier. This function should only be
called with a valid qualifier code. */
static const char*
demangle_qualifier (int c)
{
return qualifier_string (code_for_qualifier (c));
}
int
cplus_demangle_opname (const char *opname, char *result, int options)
{
int len, len1, ret;
string type;
struct work_stuff work[1];
const char *tem;
len = strlen(opname);
result[0] = '\0';
ret = 0;
memset ((char *) work, 0, sizeof (work));
work->options = options;
if (opname[0] == '_' && opname[1] == '_'
&& opname[2] == 'o' && opname[3] == 'p')
{
/* ANSI. */
/* type conversion operator. */
tem = opname + 4;
if (do_type (work, &tem, &type))
{
strcat (result, "operator ");
strncat (result, type.b, type.p - type.b);
string_delete (&type);
ret = 1;
}
}
else if (opname[0] == '_' && opname[1] == '_'
&& ISLOWER((unsigned char)opname[2])
&& ISLOWER((unsigned char)opname[3]))
{
if (opname[4] == '\0')
{
/* Operator. */
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 2
&& memcmp (optable[i].in, opname + 2, 2) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
ret = 1;
break;
}
}
}
else
{
if (opname[2] == 'a' && opname[5] == '\0')
{
/* Assignment. */
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 3
&& memcmp (optable[i].in, opname + 2, 3) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
ret = 1;
break;
}
}
}
}
}
else if (len >= 3
&& opname[0] == 'o'
&& opname[1] == 'p'
&& strchr (cplus_markers, opname[2]) != NULL)
{
/* see if it's an assignment expression */
if (len >= 10 /* op$assign_ */
&& memcmp (opname + 3, "assign_", 7) == 0)
{
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
len1 = len - 10;
if ((int) strlen (optable[i].in) == len1
&& memcmp (optable[i].in, opname + 10, len1) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
strcat (result, "=");
ret = 1;
break;
}
}
}
else
{
size_t i;
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
len1 = len - 3;
if ((int) strlen (optable[i].in) == len1
&& memcmp (optable[i].in, opname + 3, len1) == 0)
{
strcat (result, "operator");
strcat (result, optable[i].out);
ret = 1;
break;
}
}
}
}
else if (len >= 5 && memcmp (opname, "type", 4) == 0
&& strchr (cplus_markers, opname[4]) != NULL)
{
/* type conversion operator */
tem = opname + 5;
if (do_type (work, &tem, &type))
{
strcat (result, "operator ");
strncat (result, type.b, type.p - type.b);
string_delete (&type);
ret = 1;
}
}
squangle_mop_up (work);
return ret;
}
/* Takes operator name as e.g. "++" and returns mangled
operator name (e.g. "postincrement_expr"), or NULL if not found.
If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
const char *
cplus_mangle_opname (const char *opname, int options)
{
size_t i;
int len;
len = strlen (opname);
for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if ((int) strlen (optable[i].out) == len
&& (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
&& memcmp (optable[i].out, opname, len) == 0)
return optable[i].in;
}
return (0);
}
/* Add a routine to set the demangling style to be sure it is valid and
allow for any demangler initialization that maybe necessary. */
enum demangling_styles
cplus_demangle_set_style (enum demangling_styles style)
{
const struct demangler_engine *demangler = libiberty_demanglers;
for (; demangler->demangling_style != unknown_demangling; ++demangler)
if (style == demangler->demangling_style)
{
current_demangling_style = style;
return current_demangling_style;
}
return unknown_demangling;
}
/* Do string name to style translation */
enum demangling_styles
cplus_demangle_name_to_style (const char *name)
{
const struct demangler_engine *demangler = libiberty_demanglers;
for (; demangler->demangling_style != unknown_demangling; ++demangler)
if (strcmp (name, demangler->demangling_style_name) == 0)
return demangler->demangling_style;
return unknown_demangling;
}
/* char *cplus_demangle (const char *mangled, int options)
If MANGLED is a mangled function name produced by GNU C++, then
a pointer to a @code{malloc}ed string giving a C++ representation
of the name will be returned; otherwise NULL will be returned.
It is the caller's responsibility to free the string which
is returned.
The OPTIONS arg may contain one or more of the following bits:
DMGL_ANSI ANSI qualifiers such as `const' and `void' are
included.
DMGL_PARAMS Function parameters are included.
For example,
cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
cplus_demangle ("foo__1Ai", 0) => "A::foo"
cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
cplus_demangle ("foo__1Afe", 0) => "A::foo"
Note that any leading underscores, or other such characters prepended by
the compilation system, are presumed to have already been stripped from
MANGLED. */
char *
cplus_demangle (const char *mangled, int options)
{
char *ret;
struct work_stuff work[1];
if (current_demangling_style == no_demangling)
return xstrdup (mangled);
memset ((char *) work, 0, sizeof (work));
work->options = options;
if ((work->options & DMGL_STYLE_MASK) == 0)
work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
/* The V3 ABI demangling is implemented elsewhere. */
if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
{
ret = cplus_demangle_v3 (mangled, work->options);
if (GNU_V3_DEMANGLING)
return ret;
if (ret)
{
/* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
The subtitutions are always smaller, so do in place changes. */
if (rust_is_mangled (ret))
rust_demangle_sym (ret);
else if (RUST_DEMANGLING)
{
free (ret);
ret = NULL;
}
}
if (ret || RUST_DEMANGLING)
return ret;
}
if (JAVA_DEMANGLING)
{
ret = java_demangle_v3 (mangled);
if (ret)
return ret;
}
if (GNAT_DEMANGLING)
return ada_demangle (mangled, options);
if (DLANG_DEMANGLING)
{
ret = dlang_demangle (mangled, options);
if (ret)
return ret;
}
ret = internal_cplus_demangle (work, mangled);
squangle_mop_up (work);
return (ret);
}
char *
rust_demangle (const char *mangled, int options)
{
/* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */
char *ret = cplus_demangle_v3 (mangled, options);
/* The Rust subtitutions are always smaller, so do in place changes. */
if (ret != NULL)
{
if (rust_is_mangled (ret))
rust_demangle_sym (ret);
else
{
free (ret);
ret = NULL;
}
}
return ret;
}
/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
char *
ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
{
int len0;
const char* p;
char *d;
char *demangled = NULL;
/* Discard leading _ada_, which is used for library level subprograms. */
if (strncmp (mangled, "_ada_", 5) == 0)
mangled += 5;
/* All ada unit names are lower-case. */
if (!ISLOWER (mangled[0]))
goto unknown;
/* Most of the demangling will trivially remove chars. Operator names
may add one char but because they are always preceeded by '__' which is
replaced by '.', they eventually never expand the size.
A few special names such as '___elabs' add a few chars (at most 7), but
they occur only once. */
len0 = strlen (mangled) + 7 + 1;
demangled = XNEWVEC (char, len0);
d = demangled;
p = mangled;
while (1)
{
/* An entity names is expected. */
if (ISLOWER (*p))
{
/* An identifier, which is always lower case. */
do
*d++ = *p++;
while (ISLOWER(*p) || ISDIGIT (*p)
|| (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
}
else if (p[0] == 'O')
{
/* An operator name. */
static const char * const operators[][2] =
{{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"},
{"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"},
{"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="},
{"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"},
{"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"},
{"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
{"Oexpon", "**"}, {NULL, NULL}};
int k;
for (k = 0; operators[k][0] != NULL; k++)
{
size_t slen = strlen (operators[k][0]);
if (strncmp (p, operators[k][0], slen) == 0)
{