00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifdef HAVE_CONFIG_H
00043 #include "config.h"
00044 #endif
00045
00046 #include <sys/types.h>
00047
00048 #ifdef HAVE_STDLIB_H
00049 #include <stdlib.h>
00050 #endif
00051
00052 #include <stdio.h>
00053
00054 #ifdef HAVE_STRING_H
00055 #include <string.h>
00056 #endif
00057
00058 #include <ctype.h>
00059
00060 #include "ansidecl.h"
00061 #include "libiberty.h"
00062 #include "dyn-string.h"
00063 #include "demangle.h"
00064
00065
00066
00067 #ifdef CP_DEMANGLE_DEBUG
00068 #define DEMANGLE_TRACE(PRODUCTION, DM) \
00069 fprintf (stderr, " -> %-24s at position %3d\n", \
00070 (PRODUCTION), current_position (DM));
00071 #else
00072 #define DEMANGLE_TRACE(PRODUCTION, DM)
00073 #endif
00074
00075
00076
00077 #define IS_DIGIT(CHAR) ((CHAR) >= '0' && (CHAR) <= '9')
00078 #define IS_ALPHA(CHAR) \
00079 (((CHAR) >= 'a' && (CHAR) <= 'z') \
00080 || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
00081
00082
00083
00084 #define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
00085
00086
00087 #define NAMESPACE_SEPARATOR (dm->style == DMGL_JAVA ? "." : "::")
00088
00089
00090
00091
00092
00093
00094 static int flag_verbose;
00095
00096
00097
00098 static int flag_strict;
00099
00100
00101
00102
00103
00104 struct string_list_def
00105 {
00106
00107 struct dyn_string string;
00108
00109
00110
00111
00112
00113 int caret_position;
00114
00115
00116 struct string_list_def *next;
00117 };
00118
00119 typedef struct string_list_def *string_list_t;
00120
00121
00122
00123 struct substitution_def
00124 {
00125
00126 dyn_string_t text;
00127
00128
00129 int template_p : 1;
00130 };
00131
00132
00133
00134 struct template_arg_list_def
00135 {
00136
00137
00138 struct template_arg_list_def *next;
00139
00140
00141
00142 string_list_t first_argument;
00143
00144
00145 string_list_t last_argument;
00146 };
00147
00148 typedef struct template_arg_list_def *template_arg_list_t;
00149
00150
00151
00152 struct demangling_def
00153 {
00154
00155 const char *name;
00156
00157
00158 const char *next;
00159
00160
00161
00162 string_list_t result;
00163
00164
00165 int num_substitutions;
00166
00167
00168 int substitutions_allocated;
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 struct substitution_def *substitutions;
00181
00182
00183 template_arg_list_t template_arg_lists;
00184
00185
00186 dyn_string_t last_source_name;
00187
00188
00189 int style;
00190
00191
00192
00193 enum gnu_v3_ctor_kinds is_constructor;
00194
00195
00196
00197 enum gnu_v3_dtor_kinds is_destructor;
00198
00199 };
00200
00201 typedef struct demangling_def *demangling_t;
00202
00203
00204
00205 typedef const char *status_t;
00206
00207
00208 #define STATUS_OK NULL
00209 #define STATUS_ERROR "Error."
00210 #define STATUS_UNIMPLEMENTED "Unimplemented."
00211 #define STATUS_INTERNAL_ERROR "Internal error."
00212
00213
00214 static const char *const status_allocation_failed = "Allocation failed.";
00215 #define STATUS_ALLOCATION_FAILED status_allocation_failed
00216
00217
00218 #define STATUS_NO_ERROR(STATUS) ((STATUS) == STATUS_OK)
00219
00220
00221
00222
00223 #define RETURN_IF_ERROR(EXPR) \
00224 do \
00225 { \
00226 status_t s = EXPR; \
00227 if (!STATUS_NO_ERROR (s)) \
00228 return s; \
00229 } \
00230 while (0)
00231
00232 static status_t int_to_dyn_string
00233 PARAMS ((int, dyn_string_t));
00234 static string_list_t string_list_new
00235 PARAMS ((int));
00236 static void string_list_delete
00237 PARAMS ((string_list_t));
00238 static status_t result_add_separated_char
00239 PARAMS ((demangling_t, int));
00240 static status_t result_push
00241 PARAMS ((demangling_t));
00242 static string_list_t result_pop
00243 PARAMS ((demangling_t));
00244 static int substitution_start
00245 PARAMS ((demangling_t));
00246 static status_t substitution_add
00247 PARAMS ((demangling_t, int, int));
00248 static dyn_string_t substitution_get
00249 PARAMS ((demangling_t, int, int *));
00250 #ifdef CP_DEMANGLE_DEBUG
00251 static void substitutions_print
00252 PARAMS ((demangling_t, FILE *));
00253 #endif
00254 static template_arg_list_t template_arg_list_new
00255 PARAMS ((void));
00256 static void template_arg_list_delete
00257 PARAMS ((template_arg_list_t));
00258 static void template_arg_list_add_arg
00259 PARAMS ((template_arg_list_t, string_list_t));
00260 static string_list_t template_arg_list_get_arg
00261 PARAMS ((template_arg_list_t, int));
00262 static void push_template_arg_list
00263 PARAMS ((demangling_t, template_arg_list_t));
00264 static void pop_to_template_arg_list
00265 PARAMS ((demangling_t, template_arg_list_t));
00266 #ifdef CP_DEMANGLE_DEBUG
00267 static void template_arg_list_print
00268 PARAMS ((template_arg_list_t, FILE *));
00269 #endif
00270 static template_arg_list_t current_template_arg_list
00271 PARAMS ((demangling_t));
00272 static demangling_t demangling_new
00273 PARAMS ((const char *, int));
00274 static void demangling_delete
00275 PARAMS ((demangling_t));
00276
00277
00278 #define dyn_string_last_char(DS) \
00279 (dyn_string_buf (DS)[dyn_string_length (DS) - 1])
00280
00281
00282
00283 #define dyn_string_append_space(DS) \
00284 ((dyn_string_length (DS) > 0 \
00285 && dyn_string_last_char (DS) != ' ') \
00286 ? dyn_string_append_char ((DS), ' ') \
00287 : 1)
00288
00289
00290 #define current_position(DM) ((DM)->next - (DM)->name)
00291
00292
00293 #define peek_char(DM) (*((DM)->next))
00294
00295
00296
00297 #define peek_char_next(DM) \
00298 (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))
00299
00300
00301
00302 #define next_char(DM) (*((DM)->next)++)
00303
00304
00305
00306 #define end_of_name_p(DM) (peek_char (DM) == '\0')
00307
00308
00309 #define advance_char(DM) (++(DM)->next)
00310
00311
00312 #define result_string(DM) (&(DM)->result->string)
00313
00314
00315
00316 #define result_caret_pos(DM) \
00317 (result_length (DM) + \
00318 ((string_list_t) result_string (DM))->caret_position)
00319
00320
00321 #define result_add_string(DM, STRING) \
00322 (dyn_string_insert (&(DM)->result->string, \
00323 result_caret_pos (DM), (STRING)) \
00324 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
00325
00326
00327 #define result_add(DM, CSTR) \
00328 (dyn_string_insert_cstr (&(DM)->result->string, \
00329 result_caret_pos (DM), (CSTR)) \
00330 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
00331
00332
00333 #define result_add_char(DM, CHAR) \
00334 (dyn_string_insert_char (&(DM)->result->string, \
00335 result_caret_pos (DM), (CHAR)) \
00336 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
00337
00338
00339 #define result_insert_string(DM, POS, STRING) \
00340 (dyn_string_insert (&(DM)->result->string, (POS), (STRING)) \
00341 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
00342
00343
00344
00345 #define result_insert(DM, POS, CSTR) \
00346 (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR)) \
00347 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
00348
00349
00350 #define result_insert_char(DM, POS, CHAR) \
00351 (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR)) \
00352 ? STATUS_OK : STATUS_ALLOCATION_FAILED)
00353
00354
00355 #define result_length(DM) \
00356 dyn_string_length (&(DM)->result->string)
00357
00358
00359
00360
00361
00362 #define result_open_template_list(DM) result_add_separated_char(DM, '<')
00363 #define result_close_template_list(DM) result_add_separated_char(DM, '>')
00364
00365
00366
00367
00368 static status_t
00369 int_to_dyn_string (value, ds)
00370 int value;
00371 dyn_string_t ds;
00372 {
00373 int i;
00374 int mask = 1;
00375
00376
00377 if (value == 0)
00378 {
00379 if (!dyn_string_append_char (ds, '0'))
00380 return STATUS_ALLOCATION_FAILED;
00381 return STATUS_OK;
00382 }
00383
00384
00385 if (value < 0)
00386 {
00387 if (!dyn_string_append_char (ds, '-'))
00388 return STATUS_ALLOCATION_FAILED;
00389 value = -value;
00390 }
00391
00392
00393 i = value;
00394 while (i > 9)
00395 {
00396 mask *= 10;
00397 i /= 10;
00398 }
00399
00400
00401 while (mask > 0)
00402 {
00403 int digit = value / mask;
00404
00405 if (!dyn_string_append_char (ds, '0' + digit))
00406 return STATUS_ALLOCATION_FAILED;
00407
00408 value -= digit * mask;
00409 mask /= 10;
00410 }
00411
00412 return STATUS_OK;
00413 }
00414
00415
00416
00417
00418
00419
00420 static string_list_t
00421 string_list_new (length)
00422 int length;
00423 {
00424 string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));
00425 s->caret_position = 0;
00426 if (s == NULL)
00427 return NULL;
00428 if (!dyn_string_init ((dyn_string_t) s, length))
00429 return NULL;
00430 return s;
00431 }
00432
00433
00434
00435 static void
00436 string_list_delete (node)
00437 string_list_t node;
00438 {
00439 while (node != NULL)
00440 {
00441 string_list_t next = node->next;
00442 dyn_string_delete ((dyn_string_t) node);
00443 node = next;
00444 }
00445 }
00446
00447
00448
00449
00450 static status_t
00451 result_add_separated_char (dm, character)
00452 demangling_t dm;
00453 int character;
00454 {
00455 char *result = dyn_string_buf (result_string (dm));
00456 int caret_pos = result_caret_pos (dm);
00457
00458
00459
00460 if (caret_pos > 0 && result[caret_pos - 1] == character)
00461 RETURN_IF_ERROR (result_add_char (dm, ' '));
00462
00463 RETURN_IF_ERROR (result_add_char (dm, character));
00464
00465 return STATUS_OK;
00466 }
00467
00468
00469
00470
00471
00472
00473 static status_t
00474 result_push (dm)
00475 demangling_t dm;
00476 {
00477 string_list_t new_string = string_list_new (0);
00478 if (new_string == NULL)
00479
00480 return STATUS_ALLOCATION_FAILED;
00481
00482
00483 new_string->next = (string_list_t) dm->result;
00484 dm->result = new_string;
00485 return STATUS_OK;
00486 }
00487
00488
00489
00490
00491
00492 static string_list_t
00493 result_pop (dm)
00494 demangling_t dm;
00495 {
00496 string_list_t top = dm->result;
00497 dm->result = top->next;
00498 return top;
00499 }
00500
00501
00502
00503
00504 static int
00505 result_get_caret (dm)
00506 demangling_t dm;
00507 {
00508 return ((string_list_t) result_string (dm))->caret_position;
00509 }
00510
00511
00512
00513
00514 static void
00515 result_set_caret (dm, position)
00516 demangling_t dm;
00517 int position;
00518 {
00519 ((string_list_t) result_string (dm))->caret_position = position;
00520 }
00521
00522
00523
00524
00525 static void
00526 result_shift_caret (dm, position_offset)
00527 demangling_t dm;
00528 int position_offset;
00529 {
00530 ((string_list_t) result_string (dm))->caret_position += position_offset;
00531 }
00532
00533
00534
00535
00536
00537 static int
00538 result_previous_char_is_space (dm)
00539 demangling_t dm;
00540 {
00541 char *result = dyn_string_buf (result_string (dm));
00542 int pos = result_caret_pos (dm);
00543 return pos > 0 && result[pos - 1] == ' ';
00544 }
00545
00546
00547
00548
00549
00550 static int
00551 substitution_start (dm)
00552 demangling_t dm;
00553 {
00554 return result_caret_pos (dm);
00555 }
00556
00557
00558
00559
00560
00561 static status_t
00562 substitution_add (dm, start_position, template_p)
00563 demangling_t dm;
00564 int start_position;
00565 int template_p;
00566 {
00567 dyn_string_t result = result_string (dm);
00568 dyn_string_t substitution = dyn_string_new (0);
00569 int i;
00570
00571 if (substitution == NULL)
00572 return STATUS_ALLOCATION_FAILED;
00573
00574
00575
00576 if (!dyn_string_substring (substitution,
00577 result, start_position, result_caret_pos (dm)))
00578 {
00579 dyn_string_delete (substitution);
00580 return STATUS_ALLOCATION_FAILED;
00581 }
00582
00583
00584 if (dm->substitutions_allocated == dm->num_substitutions)
00585 {
00586 size_t new_array_size;
00587 if (dm->substitutions_allocated > 0)
00588 dm->substitutions_allocated *= 2;
00589 else
00590 dm->substitutions_allocated = 2;
00591 new_array_size =
00592 sizeof (struct substitution_def) * dm->substitutions_allocated;
00593
00594 dm->substitutions = (struct substitution_def *)
00595 realloc (dm->substitutions, new_array_size);
00596 if (dm->substitutions == NULL)
00597
00598 {
00599 dyn_string_delete (substitution);
00600 return STATUS_ALLOCATION_FAILED;
00601 }
00602 }
00603
00604
00605 i = dm->num_substitutions++;
00606 dm->substitutions[i].text = substitution;
00607 dm->substitutions[i].template_p = template_p;
00608
00609 #ifdef CP_DEMANGLE_DEBUG
00610 substitutions_print (dm, stderr);
00611 #endif
00612
00613 return STATUS_OK;
00614 }
00615
00616
00617
00618
00619
00620
00621
00622 static dyn_string_t
00623 substitution_get (dm, n, template_p)
00624 demangling_t dm;
00625 int n;
00626 int *template_p;
00627 {
00628 struct substitution_def *sub;
00629
00630
00631 if (n < 0 || n >= dm->num_substitutions)
00632 return NULL;
00633
00634 sub = &(dm->substitutions[n]);
00635 *template_p = sub->template_p;
00636 return sub->text;
00637 }
00638
00639 #ifdef CP_DEMANGLE_DEBUG
00640
00641
00642 static void
00643 substitutions_print (dm, fp)
00644 demangling_t dm;
00645 FILE *fp;
00646 {
00647 int seq_id;
00648 int num = dm->num_substitutions;
00649
00650 fprintf (fp, "SUBSTITUTIONS:\n");
00651 for (seq_id = -1; seq_id < num - 1; ++seq_id)
00652 {
00653 int template_p;
00654 dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p);
00655
00656 if (seq_id == -1)
00657 fprintf (fp, " S_ ");
00658 else
00659 fprintf (fp, " S%d_", seq_id);
00660 fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text));
00661 }
00662 }
00663
00664 #endif
00665
00666
00667
00668
00669 static template_arg_list_t
00670 template_arg_list_new ()
00671 {
00672 template_arg_list_t new_list =
00673 (template_arg_list_t) malloc (sizeof (struct template_arg_list_def));
00674 if (new_list == NULL)
00675 return NULL;
00676
00677 new_list->first_argument = NULL;
00678 new_list->last_argument = NULL;
00679
00680 return new_list;
00681 }
00682
00683
00684
00685
00686 static void
00687 template_arg_list_delete (list)
00688 template_arg_list_t list;
00689 {
00690
00691 if (list->first_argument != NULL)
00692 string_list_delete (list->first_argument);
00693
00694 free (list);
00695 }
00696
00697
00698
00699 static void
00700 template_arg_list_add_arg (arg_list, arg)
00701 template_arg_list_t arg_list;
00702 string_list_t arg;
00703 {
00704 if (arg_list->first_argument == NULL)
00705
00706 arg_list->first_argument = arg;
00707 else
00708
00709 arg_list->last_argument->next = arg;
00710
00711 arg_list->last_argument = arg;
00712 arg->next = NULL;
00713 }
00714
00715
00716
00717
00718 static string_list_t
00719 template_arg_list_get_arg (arg_list, index)
00720 template_arg_list_t arg_list;
00721 int index;
00722 {
00723 string_list_t arg = arg_list->first_argument;
00724
00725
00726 while (index--)
00727 {
00728 arg = arg->next;
00729 if (arg == NULL)
00730
00731
00732 return NULL;
00733 }
00734
00735 return arg;
00736 }
00737
00738
00739
00740 static void
00741 push_template_arg_list (dm, arg_list)
00742 demangling_t dm;
00743 template_arg_list_t arg_list;
00744 {
00745 arg_list->next = dm->template_arg_lists;
00746 dm->template_arg_lists = arg_list;
00747 #ifdef CP_DEMANGLE_DEBUG
00748 fprintf (stderr, " ** pushing template arg list\n");
00749 template_arg_list_print (arg_list, stderr);
00750 #endif
00751 }
00752
00753
00754
00755
00756
00757 static void
00758 pop_to_template_arg_list (dm, arg_list)
00759 demangling_t dm;
00760 template_arg_list_t arg_list;
00761 {
00762 while (dm->template_arg_lists != arg_list)
00763 {
00764 template_arg_list_t top = dm->template_arg_lists;
00765
00766 dm->template_arg_lists = top->next;
00767
00768 template_arg_list_delete (top);
00769 #ifdef CP_DEMANGLE_DEBUG
00770 fprintf (stderr, " ** removing template arg list\n");
00771 #endif
00772 }
00773 }
00774
00775 #ifdef CP_DEMANGLE_DEBUG
00776
00777
00778
00779 static void
00780 template_arg_list_print (arg_list, fp)
00781 template_arg_list_t arg_list;
00782 FILE *fp;
00783 {
00784 string_list_t arg;
00785 int index = -1;
00786
00787 fprintf (fp, "TEMPLATE ARGUMENT LIST:\n");
00788 for (arg = arg_list->first_argument; arg != NULL; arg = arg->next)
00789 {
00790 if (index == -1)
00791 fprintf (fp, " T_ : ");
00792 else
00793 fprintf (fp, " T%d_ : ", index);
00794 ++index;
00795 fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg));
00796 }
00797 }
00798
00799 #endif
00800
00801
00802
00803
00804 static template_arg_list_t
00805 current_template_arg_list (dm)
00806 demangling_t dm;
00807 {
00808 return dm->template_arg_lists;
00809 }
00810
00811
00812
00813
00814
00815 static demangling_t
00816 demangling_new (name, style)
00817 const char *name;
00818 int style;
00819 {
00820 demangling_t dm;
00821 dm = (demangling_t) malloc (sizeof (struct demangling_def));
00822 if (dm == NULL)
00823 return NULL;
00824
00825 dm->name = name;
00826 dm->next = name;
00827 dm->result = NULL;
00828 dm->num_substitutions = 0;
00829 dm->substitutions_allocated = 10;
00830 dm->template_arg_lists = NULL;
00831 dm->last_source_name = dyn_string_new (0);
00832 if (dm->last_source_name == NULL)
00833 return NULL;
00834 dm->substitutions = (struct substitution_def *)
00835 malloc (dm->substitutions_allocated * sizeof (struct substitution_def));
00836 if (dm->substitutions == NULL)
00837 {
00838 dyn_string_delete (dm->last_source_name);
00839 return NULL;
00840 }
00841 dm->style = style;
00842 dm->is_constructor = (enum gnu_v3_ctor_kinds) 0;
00843 dm->is_destructor = (enum gnu_v3_dtor_kinds) 0;
00844
00845 return dm;
00846 }
00847
00848
00849
00850
00851 static void
00852 demangling_delete (dm)
00853 demangling_t dm;
00854 {
00855 int i;
00856 template_arg_list_t arg_list = dm->template_arg_lists;
00857
00858
00859 while (arg_list != NULL)
00860 {
00861 template_arg_list_t next = arg_list->next;
00862 template_arg_list_delete (arg_list);
00863 arg_list = next;
00864 }
00865
00866 for (i = dm->num_substitutions; --i >= 0; )
00867 dyn_string_delete (dm->substitutions[i].text);
00868 free (dm->substitutions);
00869
00870 string_list_delete (dm->result);
00871
00872 dyn_string_delete (dm->last_source_name);
00873
00874 free (dm);
00875 }
00876
00877
00878
00879
00880
00881
00882
00883
00884 static status_t demangle_char
00885 PARAMS ((demangling_t, int));
00886 static status_t demangle_mangled_name
00887 PARAMS ((demangling_t));
00888 static status_t demangle_encoding
00889 PARAMS ((demangling_t));
00890 static status_t demangle_name
00891 PARAMS ((demangling_t, int *));
00892 static status_t demangle_nested_name
00893 PARAMS ((demangling_t, int *));
00894 static status_t demangle_prefix
00895 PARAMS ((demangling_t, int *));
00896 static status_t demangle_unqualified_name
00897 PARAMS ((demangling_t, int *));
00898 static status_t demangle_source_name
00899 PARAMS ((demangling_t));
00900 static status_t demangle_number
00901 PARAMS ((demangling_t, int *, int, int));
00902 static status_t demangle_number_literally
00903 PARAMS ((demangling_t, dyn_string_t, int, int));
00904 static status_t demangle_identifier
00905 PARAMS ((demangling_t, int, dyn_string_t));
00906 static status_t demangle_operator_name
00907 PARAMS ((demangling_t, int, int *, int *));
00908 static status_t demangle_nv_offset
00909 PARAMS ((demangling_t));
00910 static status_t demangle_v_offset
00911 PARAMS ((demangling_t));
00912 static status_t demangle_call_offset
00913 PARAMS ((demangling_t));
00914 static status_t demangle_special_name
00915 PARAMS ((demangling_t));
00916 static status_t demangle_ctor_dtor_name
00917 PARAMS ((demangling_t));
00918 static status_t demangle_type_ptr
00919 PARAMS ((demangling_t, int *, int));
00920 static status_t demangle_type
00921 PARAMS ((demangling_t));
00922 static status_t demangle_CV_qualifiers
00923 PARAMS ((demangling_t, dyn_string_t));
00924 static status_t demangle_builtin_type
00925 PARAMS ((demangling_t));
00926 static status_t demangle_function_type
00927 PARAMS ((demangling_t, int *));
00928 static status_t demangle_bare_function_type
00929 PARAMS ((demangling_t, int *));
00930 static status_t demangle_class_enum_type
00931 PARAMS ((demangling_t, int *));
00932 static status_t demangle_array_type
00933 PARAMS ((demangling_t, int *));
00934 static status_t demangle_template_param
00935 PARAMS ((demangling_t));
00936 static status_t demangle_template_args
00937 PARAMS ((demangling_t));
00938 static status_t demangle_literal
00939 PARAMS ((demangling_t));
00940 static status_t demangle_template_arg
00941 PARAMS ((demangling_t));
00942 static status_t demangle_expression
00943 PARAMS ((demangling_t));
00944 static status_t demangle_scope_expression
00945 PARAMS ((demangling_t));
00946 static status_t demangle_expr_primary
00947 PARAMS ((demangling_t));
00948 static status_t demangle_substitution
00949 PARAMS ((demangling_t, int *));
00950 static status_t demangle_local_name
00951 PARAMS ((demangling_t));
00952 static status_t demangle_discriminator
00953 PARAMS ((demangling_t, int));
00954 static status_t cp_demangle
00955 PARAMS ((const char *, dyn_string_t, int));
00956 static status_t cp_demangle_type
00957 PARAMS ((const char*, dyn_string_t));
00958
00959
00960
00961 #define BFT_NO_RETURN_TYPE NULL
00962
00963
00964
00965
00966 static status_t
00967 demangle_char (dm, c)
00968 demangling_t dm;
00969 int c;
00970 {
00971 static char *error_message = NULL;
00972
00973 if (peek_char (dm) == c)
00974 {
00975 advance_char (dm);
00976 return STATUS_OK;
00977 }
00978 else
00979 {
00980 if (error_message == NULL)
00981 error_message = (char *) strdup ("Expected ?");
00982 error_message[9] = c;
00983 return error_message;
00984 }
00985 }
00986
00987
00988
00989
00990
00991 static status_t
00992 demangle_mangled_name (dm)
00993 demangling_t dm;
00994 {
00995 DEMANGLE_TRACE ("mangled-name", dm);
00996 RETURN_IF_ERROR (demangle_char (dm, '_'));
00997 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
00998 RETURN_IF_ERROR (demangle_encoding (dm));
00999 return STATUS_OK;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008 static status_t
01009 demangle_encoding (dm)
01010 demangling_t dm;
01011 {
01012 int encode_return_type;
01013 int start_position;
01014 template_arg_list_t old_arg_list = current_template_arg_list (dm);
01015 char peek = peek_char (dm);
01016
01017 DEMANGLE_TRACE ("encoding", dm);
01018
01019
01020
01021 start_position = result_caret_pos (dm);
01022
01023 if (peek == 'G' || peek == 'T')
01024 RETURN_IF_ERROR (demangle_special_name (dm));
01025 else
01026 {
01027
01028 RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
01029
01030
01031
01032 if (!end_of_name_p (dm)
01033 && peek_char (dm) != 'E')
01034 {
01035 if (encode_return_type)
01036
01037
01038 RETURN_IF_ERROR
01039 (demangle_bare_function_type (dm, &start_position));
01040 else
01041
01042
01043 RETURN_IF_ERROR
01044 (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE));
01045 }
01046 }
01047
01048
01049
01050 pop_to_template_arg_list (dm, old_arg_list);
01051
01052 return STATUS_OK;
01053 }
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 static status_t
01070 demangle_name (dm, encode_return_type)
01071 demangling_t dm;
01072 int *encode_return_type;
01073 {
01074 int start = substitution_start (dm);
01075 char peek = peek_char (dm);
01076 int is_std_substitution = 0;
01077
01078
01079
01080
01081
01082 int suppress_return_type = 0;
01083
01084 DEMANGLE_TRACE ("name", dm);
01085
01086 switch (peek)
01087 {
01088 case 'N':
01089
01090 RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
01091 break;
01092
01093 case 'Z':
01094 RETURN_IF_ERROR (demangle_local_name (dm));
01095 *encode_return_type = 0;
01096 break;
01097
01098 case 'S':
01099
01100
01101 if (peek_char_next (dm) == 't')
01102 {
01103 (void) next_char (dm);
01104 (void) next_char (dm);
01105 RETURN_IF_ERROR (result_add (dm, "std::"));
01106 RETURN_IF_ERROR
01107 (demangle_unqualified_name (dm, &suppress_return_type));
01108 is_std_substitution = 1;
01109 }
01110 else
01111 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
01112
01113
01114 if (peek_char (dm) == 'I')
01115 {
01116
01117
01118 if (is_std_substitution)
01119 RETURN_IF_ERROR (substitution_add (dm, start, 0));
01120
01121 RETURN_IF_ERROR (demangle_template_args (dm));
01122 *encode_return_type = !suppress_return_type;
01123 }
01124 else
01125 *encode_return_type = 0;
01126
01127 break;
01128
01129 default:
01130
01131 RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
01132
01133
01134
01135 if (peek_char (dm) == 'I')
01136 {
01137
01138 RETURN_IF_ERROR (substitution_add (dm, start, 0));
01139
01140 RETURN_IF_ERROR (demangle_template_args (dm));
01141 *encode_return_type = !suppress_return_type;
01142 }
01143 else
01144 *encode_return_type = 0;
01145
01146 break;
01147 }
01148
01149 return STATUS_OK;
01150 }
01151
01152
01153
01154
01155
01156 static status_t
01157 demangle_nested_name (dm, encode_return_type)
01158 demangling_t dm;
01159 int *encode_return_type;
01160 {
01161 char peek;
01162
01163 DEMANGLE_TRACE ("nested-name", dm);
01164
01165 RETURN_IF_ERROR (demangle_char (dm, 'N'));
01166
01167 peek = peek_char (dm);
01168 if (peek == 'r' || peek == 'V' || peek == 'K')
01169 {
01170 dyn_string_t cv_qualifiers;
01171 status_t status;
01172
01173
01174 cv_qualifiers = dyn_string_new (24);
01175 if (cv_qualifiers == NULL)
01176 return STATUS_ALLOCATION_FAILED;
01177 demangle_CV_qualifiers (dm, cv_qualifiers);
01178
01179
01180 status = result_add_char (dm, ' ');
01181 if (STATUS_NO_ERROR (status))
01182 status = result_add_string (dm, cv_qualifiers);
01183
01184
01185
01186
01187
01188 result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);
01189
01190 dyn_string_delete (cv_qualifiers);
01191 RETURN_IF_ERROR (status);
01192 }
01193
01194 RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
01195
01196
01197 RETURN_IF_ERROR (demangle_char (dm, 'E'));
01198
01199 return STATUS_OK;
01200 }
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 static status_t
01213 demangle_prefix (dm, encode_return_type)
01214 demangling_t dm;
01215 int *encode_return_type;
01216 {
01217 int start = substitution_start (dm);
01218 int nested = 0;
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228 int suppress_return_type = 0;
01229
01230 DEMANGLE_TRACE ("prefix", dm);
01231
01232 while (1)
01233 {
01234 char peek;
01235
01236 if (end_of_name_p (dm))
01237 return "Unexpected end of name in <compound-name>.";
01238
01239 peek = peek_char (dm);
01240
01241
01242
01243
01244
01245
01246
01247 if (peek != 'I')
01248 suppress_return_type = 0;
01249
01250 if (IS_DIGIT ((unsigned char) peek)
01251 || (peek >= 'a' && peek <= 'z')
01252 || peek == 'C' || peek == 'D'
01253 || peek == 'S')
01254 {
01255
01256 if (nested)
01257 RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));
01258 else
01259 nested = 1;
01260
01261 if (peek == 'S')
01262
01263
01264 RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
01265 else
01266 {
01267
01268 RETURN_IF_ERROR
01269 (demangle_unqualified_name (dm, &suppress_return_type));
01270 *encode_return_type = 0;
01271 }
01272 }
01273 else if (peek == 'Z')
01274 RETURN_IF_ERROR (demangle_local_name (dm));
01275 else if (peek == 'I')
01276 {
01277 RETURN_IF_ERROR (demangle_template_args (dm));
01278
01279
01280
01281
01282
01283
01284
01285
01286 *encode_return_type = !suppress_return_type;
01287 }
01288 else if (peek == 'E')
01289
01290 return STATUS_OK;
01291 else
01292 return "Unexpected character in <compound-name>.";
01293
01294 if (peek != 'S'
01295 && peek_char (dm) != 'E')
01296
01297 RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
01298 }
01299 }
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 static status_t
01312 demangle_unqualified_name (dm, suppress_return_type)
01313 demangling_t dm;
01314 int *suppress_return_type;
01315 {
01316 char peek = peek_char (dm);
01317
01318 DEMANGLE_TRACE ("unqualified-name", dm);
01319
01320
01321
01322 *suppress_return_type = 0;
01323
01324 if (IS_DIGIT ((unsigned char) peek))
01325 RETURN_IF_ERROR (demangle_source_name (dm));
01326 else if (peek >= 'a' && peek <= 'z')
01327 {
01328 int num_args;
01329
01330
01331 if (peek == 'c' && peek_char_next (dm) == 'v')
01332 *suppress_return_type = 1;
01333
01334 RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args, NULL));
01335 }
01336 else if (peek == 'C' || peek == 'D')
01337 {
01338
01339 if (peek == 'C')
01340 *suppress_return_type = 1;
01341
01342 RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
01343 }
01344 else
01345 return "Unexpected character in <unqualified-name>.";
01346
01347 return STATUS_OK;
01348 }
01349
01350
01351
01352
01353
01354 static status_t
01355 demangle_source_name (dm)
01356 demangling_t dm;
01357 {
01358 int length;
01359
01360 DEMANGLE_TRACE ("source-name", dm);
01361
01362
01363 RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
01364 if (length == 0)
01365 return "Zero length in <source-name>.";
01366
01367
01368
01369 RETURN_IF_ERROR (demangle_identifier (dm, length,
01370 dm->last_source_name));
01371
01372
01373 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
01374
01375 return STATUS_OK;
01376 }
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388 static status_t
01389 demangle_number (dm, value, base, is_signed)
01390 demangling_t dm;
01391 int *value;
01392 int base;
01393 int is_signed;
01394 {
01395 dyn_string_t number = dyn_string_new (10);
01396
01397 DEMANGLE_TRACE ("number", dm);
01398
01399 if (number == NULL)
01400 return STATUS_ALLOCATION_FAILED;
01401
01402 demangle_number_literally (dm, number, base, is_signed);
01403 *value = strtol (dyn_string_buf (number), NULL, base);
01404 dyn_string_delete (number);
01405
01406 return STATUS_OK;
01407 }
01408
01409
01410
01411
01412
01413
01414
01415
01416 static status_t
01417 demangle_number_literally (dm, str, base, is_signed)
01418 demangling_t dm;
01419 dyn_string_t str;
01420 int base;
01421 int is_signed;
01422 {
01423 DEMANGLE_TRACE ("number*", dm);
01424
01425 if (base != 10 && base != 36)
01426 return STATUS_INTERNAL_ERROR;
01427
01428
01429 if (is_signed && peek_char (dm) == 'n')
01430 {
01431
01432 advance_char (dm);
01433
01434
01435 if (!dyn_string_append_char (str, '-'))
01436 return STATUS_ALLOCATION_FAILED;
01437 }
01438
01439
01440 while (1)
01441 {
01442 char peek = peek_char (dm);
01443 if (IS_DIGIT ((unsigned char) peek)
01444 || (base == 36 && peek >= 'A' && peek <= 'Z'))
01445 {
01446
01447 if (!dyn_string_append_char (str, next_char (dm)))
01448 return STATUS_ALLOCATION_FAILED;
01449 }
01450 else
01451
01452 break;
01453 }
01454
01455 return STATUS_OK;
01456 }
01457
01458
01459
01460
01461 static status_t
01462 demangle_identifier (dm, length, identifier)
01463 demangling_t dm;
01464 int length;
01465 dyn_string_t identifier;
01466 {
01467 DEMANGLE_TRACE ("identifier", dm);
01468
01469 dyn_string_clear (identifier);
01470 if (!dyn_string_resize (identifier, length))
01471 return STATUS_ALLOCATION_FAILED;
01472
01473 while (length-- > 0)
01474 {
01475 int ch;
01476 if (end_of_name_p (dm))
01477 return "Unexpected end of name in <identifier>.";
01478 ch = next_char (dm);
01479
01480
01481
01482
01483 if (ch == '_'
01484 && peek_char (dm) == '_'
01485 && peek_char_next (dm) == 'U')
01486 {
01487 char buf[10];
01488 int pos = 0;
01489 advance_char (dm); advance_char (dm); length -= 2;
01490 while (length-- > 0)
01491 {
01492 ch = next_char (dm);
01493 if (!isxdigit (ch))
01494 break;
01495 buf[pos++] = ch;
01496 }
01497 if (ch != '_' || length < 0)
01498 return STATUS_ERROR;
01499 if (pos == 0)
01500 {
01501
01502 if (!dyn_string_append_cstr (identifier, "__U"))
01503 return STATUS_ALLOCATION_FAILED;
01504 continue;
01505 }
01506 else
01507 {
01508 buf[pos] = '\0';
01509 ch = strtol (buf, 0, 16);
01510 }
01511 }
01512
01513 if (!dyn_string_append_char (identifier, ch))
01514 return STATUS_ALLOCATION_FAILED;
01515 }
01516
01517
01518
01519
01520 if (!flag_strict)
01521 {
01522 char *name = dyn_string_buf (identifier);
01523 int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
01524
01525
01526 if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
01527 {
01528 name += prefix_length;
01529
01530
01531
01532 if ((*name == '.' || *name == '_' || *name == '$')
01533 && *(name + 1) == 'N')
01534
01535
01536 dyn_string_copy_cstr (identifier, "(anonymous namespace)");
01537 }
01538 }
01539
01540 return STATUS_OK;
01541 }
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603 static status_t
01604 demangle_operator_name (dm, short_name, num_args, type_arg)
01605 demangling_t dm;
01606 int short_name;
01607 int *num_args;
01608 int *type_arg;
01609 {
01610 struct operator_code
01611 {
01612
01613 const char *const code;
01614
01615 const char *const name;
01616
01617 const int num_args;
01618 };
01619
01620 static const struct operator_code operators[] =
01621 {
01622 { "aN", "&=" , 2 },
01623 { "aS", "=" , 2 },
01624 { "aa", "&&" , 2 },
01625 { "ad", "&" , 1 },
01626 { "an", "&" , 2 },
01627 { "cl", "()" , 0 },
01628 { "cm", "," , 2 },
01629 { "co", "~" , 1 },
01630 { "dV", "/=" , 2 },
01631 { "da", " delete[]", 1 },
01632 { "de", "*" , 1 },
01633 { "dl", " delete" , 1 },
01634 { "dv", "/" , 2 },
01635 { "eO", "^=" , 2 },
01636 { "eo", "^" , 2 },
01637 { "eq", "==" , 2 },
01638 { "ge", ">=" , 2 },
01639 { "gt", ">" , 2 },
01640 { "ix", "[]" , 2 },
01641 { "lS", "<<=" , 2 },
01642 { "le", "<=" , 2 },
01643 { "ls", "<<" , 2 },
01644 { "lt", "<" , 2 },
01645 { "mI", "-=" , 2 },
01646 { "mL", "*=" , 2 },
01647 { "mi", "-" , 2 },
01648 { "ml", "*" , 2 },
01649 { "mm", "--" , 1 },
01650 { "na", " new[]" , 1 },
01651 { "ne", "!=" , 2 },
01652 { "ng", "-" , 1 },
01653 { "nt", "!" , 1 },
01654 { "nw", " new" , 1 },
01655 { "oR", "|=" , 2 },
01656 { "oo", "||" , 2 },
01657 { "or", "|" , 2 },
01658 { "pL", "+=" , 2 },
01659 { "pl", "+" , 2 },
01660 { "pm", "->*" , 2 },
01661 { "pp", "++" , 1 },
01662 { "ps", "+" , 1 },
01663 { "pt", "->" , 2 },
01664 { "qu", "?" , 3 },
01665 { "rM", "%=" , 2 },
01666 { "rS", ">>=" , 2 },
01667 { "rm", "%" , 2 },
01668 { "rs", ">>" , 2 },
01669 { "sz", " sizeof" , 1 }
01670 };
01671
01672 const int num_operators =
01673 sizeof (operators) / sizeof (struct operator_code);
01674
01675 int c0 = next_char (dm);
01676 int c1 = next_char (dm);
01677 const struct operator_code* p1 = operators;
01678 const struct operator_code* p2 = operators + num_operators;
01679
01680 DEMANGLE_TRACE ("operator-name", dm);
01681
01682
01683 if (type_arg)
01684 *type_arg = 0;
01685
01686
01687 if (c0 == 'v' && IS_DIGIT (c1))
01688 {
01689 RETURN_IF_ERROR (result_add (dm, "operator "));
01690 RETURN_IF_ERROR (demangle_source_name (dm));
01691 *num_args = 0;
01692 return STATUS_OK;
01693 }
01694
01695
01696 if (c0 == 'c' && c1 == 'v')
01697 {
01698 RETURN_IF_ERROR (result_add (dm, "operator "));
01699
01700 RETURN_IF_ERROR (demangle_type (dm));
01701 *num_args = 0;
01702 return STATUS_OK;
01703 }
01704
01705
01706 if (c0 == 's' && c1 == 't')
01707 {
01708 RETURN_IF_ERROR (result_add (dm, " sizeof"));
01709 *num_args = 1;
01710 if (type_arg)
01711 *type_arg = 1;
01712 return STATUS_OK;
01713 }
01714
01715
01716 while (1)
01717 {
01718 const struct operator_code* p = p1 + (p2 - p1) / 2;
01719 char match0 = p->code[0];
01720 char match1 = p->code[1];
01721
01722 if (c0 == match0 && c1 == match1)
01723
01724 {
01725 if (!short_name)
01726 RETURN_IF_ERROR (result_add (dm, "operator"));
01727 RETURN_IF_ERROR (result_add (dm, p->name));
01728 *num_args = p->num_args;
01729
01730 return STATUS_OK;
01731 }
01732
01733 if (p == p1)
01734
01735 return "Unknown code in <operator-name>.";
01736
01737
01738 if (c0 < match0 || (c0 == match0 && c1 < match1))
01739 p2 = p;
01740 else
01741 p1 = p;
01742 }
01743 }
01744
01745
01746
01747
01748
01749 static status_t
01750 demangle_nv_offset (dm)
01751 demangling_t dm;
01752 {
01753 dyn_string_t number;
01754 status_t status = STATUS_OK;
01755
01756 DEMANGLE_TRACE ("h-offset", dm);
01757
01758
01759 number = dyn_string_new (4);
01760 if (number == NULL)
01761 return STATUS_ALLOCATION_FAILED;
01762 demangle_number_literally (dm, number, 10, 1);
01763
01764
01765 if (flag_verbose)
01766 {
01767 status = result_add (dm, " [nv:");
01768 if (STATUS_NO_ERROR (status))
01769 status = result_add_string (dm, number);
01770 if (STATUS_NO_ERROR (status))
01771 status = result_add_char (dm, ']');
01772 }
01773
01774
01775 dyn_string_delete (number);
01776 RETURN_IF_ERROR (status);
01777 return STATUS_OK;
01778 }
01779
01780
01781
01782
01783
01784
01785 static status_t
01786 demangle_v_offset (dm)
01787 demangling_t dm;
01788 {
01789 dyn_string_t number;
01790 status_t status = STATUS_OK;
01791
01792 DEMANGLE_TRACE ("v-offset", dm);
01793
01794
01795 number = dyn_string_new (4);
01796 if (number == NULL)
01797 return STATUS_ALLOCATION_FAILED;
01798 demangle_number_literally (dm, number, 10, 1);
01799
01800
01801 if (flag_verbose)
01802 {
01803 status = result_add (dm, " [v:");
01804 if (STATUS_NO_ERROR (status))
01805 status = result_add_string (dm, number);
01806 if (STATUS_NO_ERROR (status))
01807 result_add_char (dm, ',');
01808 }
01809 dyn_string_delete (number);
01810 RETURN_IF_ERROR (status);
01811
01812
01813 RETURN_IF_ERROR (demangle_char (dm, '_'));
01814
01815
01816 number = dyn_string_new (4);
01817 if (number == NULL)
01818 return STATUS_ALLOCATION_FAILED;
01819 demangle_number_literally (dm, number, 10, 1);
01820
01821
01822 if (flag_verbose)
01823 {
01824 status = result_add_string (dm, number);
01825 if (STATUS_NO_ERROR (status))
01826 status = result_add_char (dm, ']');
01827 }
01828 dyn_string_delete (number);
01829 RETURN_IF_ERROR (status);
01830
01831 return STATUS_OK;
01832 }
01833
01834
01835
01836
01837
01838
01839 static status_t
01840 demangle_call_offset (dm)
01841 demangling_t dm;
01842 {
01843 DEMANGLE_TRACE ("call-offset", dm);
01844
01845 switch (peek_char (dm))
01846 {
01847 case 'h':
01848 advance_char (dm);
01849
01850 RETURN_IF_ERROR (demangle_nv_offset (dm));
01851
01852 RETURN_IF_ERROR (demangle_char (dm, '_'));
01853 break;
01854
01855 case 'v':
01856 advance_char (dm);
01857
01858 RETURN_IF_ERROR (demangle_v_offset (dm));
01859
01860 RETURN_IF_ERROR (demangle_char (dm, '_'));
01861 break;
01862
01863 default:
01864 return "Unrecognized <call-offset>.";
01865 }
01866
01867 return STATUS_OK;
01868 }
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900 static status_t
01901 demangle_special_name (dm)
01902 demangling_t dm;
01903 {
01904 dyn_string_t number;
01905 int unused;
01906 char peek = peek_char (dm);
01907
01908 DEMANGLE_TRACE ("special-name", dm);
01909
01910 if (peek == 'G')
01911 {
01912
01913 advance_char (dm);
01914 switch (peek_char (dm))
01915 {
01916 case 'V':
01917
01918 advance_char (dm);
01919 RETURN_IF_ERROR (result_add (dm, "guard variable for "));
01920 RETURN_IF_ERROR (demangle_name (dm, &unused));
01921 break;
01922
01923 case 'R':
01924
01925 advance_char (dm);
01926 RETURN_IF_ERROR (result_add (dm, "reference temporary for "));
01927 RETURN_IF_ERROR (demangle_name (dm, &unused));
01928 break;
01929
01930 default:
01931 return "Unrecognized <special-name>.";
01932 }
01933 }
01934 else if (peek == 'T')
01935 {
01936 status_t status = STATUS_OK;
01937
01938
01939 advance_char (dm);
01940
01941 switch (peek_char (dm))
01942 {
01943 case 'V':
01944
01945 advance_char (dm);
01946 RETURN_IF_ERROR (result_add (dm, "vtable for "));
01947 RETURN_IF_ERROR (demangle_type (dm));
01948 break;
01949
01950 case 'T':
01951
01952 advance_char (dm);
01953 RETURN_IF_ERROR (result_add (dm, "VTT for "));
01954 RETURN_IF_ERROR (demangle_type (dm));
01955 break;
01956
01957 case 'I':
01958
01959 advance_char (dm);
01960 RETURN_IF_ERROR (result_add (dm, "typeinfo for "));
01961 RETURN_IF_ERROR (demangle_type (dm));
01962 break;
01963
01964 case 'F':
01965
01966 advance_char (dm);
01967 RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));
01968 RETURN_IF_ERROR (demangle_type (dm));
01969 break;
01970
01971 case 'S':
01972
01973 advance_char (dm);
01974 RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));
01975 RETURN_IF_ERROR (demangle_type (dm));
01976 break;
01977
01978 case 'J':
01979
01980 advance_char (dm);
01981 RETURN_IF_ERROR (result_add (dm, "java Class for "));
01982 RETURN_IF_ERROR (demangle_type (dm));
01983 break;
01984
01985 case 'h':
01986
01987 advance_char (dm);
01988 RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));
01989 RETURN_IF_ERROR (demangle_nv_offset (dm));
01990
01991 RETURN_IF_ERROR (demangle_char (dm, '_'));
01992
01993 RETURN_IF_ERROR (result_add (dm, " to "));
01994 RETURN_IF_ERROR (demangle_encoding (dm));
01995 break;
01996
01997 case 'v':
01998
01999 advance_char (dm);
02000 RETURN_IF_ERROR (result_add (dm, "virtual thunk"));
02001 RETURN_IF_ERROR (demangle_v_offset (dm));
02002
02003 RETURN_IF_ERROR (demangle_char (dm, '_'));
02004
02005 RETURN_IF_ERROR (result_add (dm, " to "));
02006 RETURN_IF_ERROR (demangle_encoding (dm));
02007 break;
02008
02009 case 'c':
02010
02011 advance_char (dm);
02012 RETURN_IF_ERROR (result_add (dm, "covariant return thunk"));
02013 RETURN_IF_ERROR (demangle_call_offset (dm));
02014 RETURN_IF_ERROR (demangle_call_offset (dm));
02015
02016 RETURN_IF_ERROR (result_add (dm, " to "));
02017 RETURN_IF_ERROR (demangle_encoding (dm));
02018 break;
02019
02020 case 'C':
02021
02022 if (!flag_strict)
02023 {
02024 dyn_string_t derived_type;
02025
02026 advance_char (dm);
02027 RETURN_IF_ERROR (result_add (dm, "construction vtable for "));
02028
02029
02030 RETURN_IF_ERROR (result_push (dm));
02031 RETURN_IF_ERROR (demangle_type (dm));
02032 derived_type = (dyn_string_t) result_pop (dm);
02033
02034
02035 number = dyn_string_new (4);
02036 if (number == NULL)
02037 {
02038 dyn_string_delete (derived_type);
02039 return STATUS_ALLOCATION_FAILED;
02040 }
02041 demangle_number_literally (dm, number, 10, 1);
02042
02043 status = demangle_char (dm, '_');
02044
02045
02046 if (STATUS_NO_ERROR (status))
02047 status = demangle_type (dm);
02048
02049
02050 if (STATUS_NO_ERROR (status))
02051 status = result_add (dm, "-in-");
02052 if (STATUS_NO_ERROR (status))
02053 status = result_add_string (dm, derived_type);
02054 dyn_string_delete (derived_type);
02055
02056
02057 if (flag_verbose)
02058 {
02059 status = result_add_char (dm, ' ');
02060 if (STATUS_NO_ERROR (status))
02061 result_add_string (dm, number);
02062 }
02063 dyn_string_delete (number);
02064 RETURN_IF_ERROR (status);
02065 break;
02066 }
02067
02068
02069 default:
02070 return "Unrecognized <special-name>.";
02071 }
02072 }
02073 else
02074 return STATUS_ERROR;
02075
02076 return STATUS_OK;
02077 }
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089 static status_t
02090 demangle_ctor_dtor_name (dm)
02091 demangling_t dm;
02092 {
02093 static const char *const ctor_flavors[] =
02094 {
02095 "in-charge",
02096 "not-in-charge",
02097 "allocating"
02098 };
02099 static const char *const dtor_flavors[] =
02100 {
02101 "in-charge deleting",
02102 "in-charge",
02103 "not-in-charge"
02104 };
02105
02106 int flavor;
02107 char peek = peek_char (dm);
02108
02109 DEMANGLE_TRACE ("ctor-dtor-name", dm);
02110
02111 if (peek == 'C')
02112 {
02113
02114 advance_char (dm);
02115 flavor = next_char (dm);
02116 if (flavor < '1' || flavor > '3')
02117 return "Unrecognized constructor.";
02118 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
02119 switch (flavor)
02120 {
02121 case '1': dm->is_constructor = gnu_v3_complete_object_ctor;
02122 break;
02123 case '2': dm->is_constructor = gnu_v3_base_object_ctor;
02124 break;
02125 case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;
02126 break;
02127 }
02128
02129 if (flag_verbose)
02130 {
02131 RETURN_IF_ERROR (result_add (dm, "["));
02132 RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));
02133 RETURN_IF_ERROR (result_add_char (dm, ']'));
02134 }
02135 }
02136 else if (peek == 'D')
02137 {
02138
02139 advance_char (dm);
02140 flavor = next_char (dm);
02141 if (flavor < '0' || flavor > '2')
02142 return "Unrecognized destructor.";
02143 RETURN_IF_ERROR (result_add_char (dm, '~'));
02144 RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
02145 switch (flavor)
02146 {
02147 case '0': dm->is_destructor = gnu_v3_deleting_dtor;
02148 break;
02149 case '1': dm->is_destructor = gnu_v3_complete_object_dtor;
02150 break;
02151 case '2': dm->is_destructor = gnu_v3_base_object_dtor;
02152 break;
02153 }
02154
02155 if (flag_verbose)
02156 {
02157 RETURN_IF_ERROR (result_add (dm, " ["));
02158 RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));
02159 RETURN_IF_ERROR (result_add_char (dm, ']'));
02160 }
02161 }
02162 else
02163 return STATUS_ERROR;
02164
02165 return STATUS_OK;
02166 }
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194 static status_t
02195 demangle_type_ptr (dm, insert_pos, substitution_start)
02196 demangling_t dm;
02197 int *insert_pos;
02198 int substitution_start;
02199 {
02200 status_t status;
02201 int is_substitution_candidate = 1;
02202
02203 DEMANGLE_TRACE ("type*", dm);
02204
02205
02206
02207 switch (peek_char (dm))
02208 {
02209 case 'P':
02210
02211 advance_char (dm);
02212
02213 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
02214 substitution_start));
02215
02216
02217
02218 if (dm->style != DMGL_JAVA)
02219 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
02220
02221
02222 ++(*insert_pos);
02223 break;
02224
02225 case 'R':
02226
02227 advance_char (dm);
02228
02229 RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
02230 substitution_start));
02231
02232
02233 RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
02234
02235
02236 ++(*insert_pos);
02237 break;
02238
02239 case 'M':
02240 {
02241
02242 dyn_string_t class_type;
02243
02244
02245 advance_char (dm);
02246
02247
02248 RETURN_IF_ERROR (result_push (dm));
02249 RETURN_IF_ERROR (demangle_type (dm));
02250 class_type = (dyn_string_t) result_pop (dm);
02251
02252 if (peek_char (dm) == 'F')
02253
02254
02255
02256
02257
02258 status = demangle_type_ptr (dm, insert_pos, substitution_start);
02259 else if (peek_char (dm) == 'A')
02260
02261
02262
02263
02264 status = demangle_array_type (dm, insert_pos);
02265 else
02266 {
02267
02268
02269 status = demangle_type (dm);
02270
02271 if (STATUS_NO_ERROR (status)
02272 && !result_previous_char_is_space (dm))
02273 status = result_add_char (dm, ' ');
02274
02275
02276 *insert_pos = result_caret_pos (dm);
02277 }
02278
02279
02280 if (STATUS_NO_ERROR (status))
02281 status = result_insert (dm, *insert_pos, "::*");
02282 if (STATUS_NO_ERROR (status))
02283 status = result_insert_string (dm, *insert_pos, class_type);
02284
02285
02286
02287
02288 *insert_pos += dyn_string_length (class_type) + 3;
02289
02290
02291 dyn_string_delete (class_type);
02292
02293 RETURN_IF_ERROR (status);
02294 }
02295 break;
02296
02297 case 'F':
02298
02299
02300
02301 *insert_pos = result_caret_pos (dm);
02302
02303
02304 RETURN_IF_ERROR (result_add (dm, "()"));
02305
02306
02307
02308 RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
02309
02310
02311
02312
02313
02314
02315 ++(*insert_pos);
02316 break;
02317
02318 case 'A':
02319
02320
02321 RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));
02322 break;
02323
02324 default:
02325
02326
02327
02328 RETURN_IF_ERROR (demangle_type (dm));
02329
02330
02331 *insert_pos = result_caret_pos (dm);
02332
02333
02334
02335 is_substitution_candidate = 0;
02336 break;
02337 }
02338
02339 if (is_substitution_candidate)
02340 RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
02341
02342 return STATUS_OK;
02343 }
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362 static status_t
02363 demangle_type (dm)
02364 demangling_t dm;
02365 {
02366 int start = substitution_start (dm);
02367 char peek = peek_char (dm);
02368 char peek_next;
02369 int encode_return_type = 0;
02370 template_arg_list_t old_arg_list = current_template_arg_list (dm);
02371 int insert_pos;
02372
02373
02374
02375
02376 int is_substitution_candidate = 1;
02377
02378 DEMANGLE_TRACE ("type", dm);
02379
02380
02381
02382 if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
02383 RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
02384
02385
02386 else if (peek >= 'a' && peek <= 'z' && peek != 'r')
02387 {
02388 RETURN_IF_ERROR (demangle_builtin_type (dm));
02389
02390 is_substitution_candidate = 0;
02391 }
02392 else
02393 switch (peek)
02394 {
02395 case 'r':
02396 case 'V':
02397 case 'K':
02398
02399
02400
02401 {
02402 status_t status;
02403 dyn_string_t cv_qualifiers = dyn_string_new (24);
02404 int old_caret_position = result_get_caret (dm);
02405
02406 if (cv_qualifiers == NULL)
02407 return STATUS_ALLOCATION_FAILED;
02408
02409
02410 demangle_CV_qualifiers (dm, cv_qualifiers);
02411
02412
02413 status = result_add_string (dm, cv_qualifiers);
02414 result_shift_caret (dm, -dyn_string_length (cv_qualifiers));
02415
02416 dyn_string_delete (cv_qualifiers);
02417 RETURN_IF_ERROR (status);
02418
02419 RETURN_IF_ERROR (result_add_char (dm, ' '));
02420 result_shift_caret (dm, -1);
02421
02422
02423
02424 RETURN_IF_ERROR (demangle_type (dm));
02425
02426
02427 result_set_caret (dm, old_caret_position);
02428 }
02429 break;
02430
02431 case 'F':
02432 return "Non-pointer or -reference function type.";
02433
02434 case 'A':
02435 RETURN_IF_ERROR (demangle_array_type (dm, NULL));
02436 break;
02437
02438 case 'T':
02439
02440
02441
02442 RETURN_IF_ERROR (demangle_template_param (dm));
02443
02444
02445
02446
02447 if (peek_char (dm) == 'I')
02448 {
02449
02450
02451
02452 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
02453
02454
02455 RETURN_IF_ERROR (demangle_template_args (dm));
02456
02457
02458
02459 }
02460
02461 break;
02462
02463 case 'S':
02464
02465
02466
02467
02468 peek_next = peek_char_next (dm);
02469 if (IS_DIGIT (peek_next) || peek_next == '_')
02470 {
02471 RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
02472
02473
02474
02475
02476 if (peek_char (dm) == 'I')
02477 RETURN_IF_ERROR (demangle_template_args (dm));
02478 else
02479
02480
02481
02482 is_substitution_candidate = 0;
02483 }
02484 else
02485 {
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500 const char *next = dm->next;
02501
02502 RETURN_IF_ERROR
02503 (demangle_class_enum_type (dm, &encode_return_type));
02504
02505
02506
02507 if (dm->next == next + 2)
02508 is_substitution_candidate = 0;
02509 }
02510
02511 break;
02512
02513 case 'P':
02514 case 'R':
02515 case 'M':
02516 RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
02517
02518
02519 is_substitution_candidate = 0;
02520 break;
02521
02522 case 'C':
02523
02524 RETURN_IF_ERROR (result_add (dm, "complex "));
02525 advance_char (dm);
02526 RETURN_IF_ERROR (demangle_type (dm));
02527 break;
02528
02529 case 'G':
02530
02531 RETURN_IF_ERROR (result_add (dm, "imaginary "));
02532 advance_char (dm);
02533 RETURN_IF_ERROR (demangle_type (dm));
02534 break;
02535
02536 case 'U':
02537
02538 advance_char (dm);
02539 RETURN_IF_ERROR (demangle_source_name (dm));
02540 RETURN_IF_ERROR (result_add_char (dm, ' '));
02541 RETURN_IF_ERROR (demangle_type (dm));
02542 break;
02543
02544 default:
02545 return "Unexpected character in <type>.";
02546 }
02547
02548 if (is_substitution_candidate)
02549
02550
02551
02552
02553 RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
02554
02555
02556
02557 pop_to_template_arg_list (dm, old_arg_list);
02558
02559 return STATUS_OK;
02560 }
02561
02562
02563
02564 static const char *const builtin_type_names[26] =
02565 {
02566 "signed char",
02567 "bool",
02568 "char",
02569 "double",
02570 "long double",
02571 "float",
02572 "__float128",
02573 "unsigned char",
02574 "int",
02575 "unsigned",
02576 NULL,
02577 "long",
02578 "unsigned long",
02579 "__int128",
02580 "unsigned __int128",
02581 NULL,
02582 NULL,
02583 NULL,
02584 "short",
02585 "unsigned short",
02586 NULL,
02587 "void",
02588 "wchar_t",
02589 "long long",
02590 "unsigned long long",
02591 "..."
02592 };
02593
02594
02595
02596
02597 static const char *const java_builtin_type_names[26] =
02598 {
02599 "signed char",
02600 "boolean",
02601 "byte",
02602 "double",
02603 "long double",
02604 "float",
02605 "__float128",
02606 "unsigned char",
02607 "int",
02608 "unsigned",
02609 NULL,
02610 "long",
02611 "unsigned long",
02612 "__int128",
02613 "unsigned __int128",
02614 NULL,
02615 NULL,
02616 NULL,
02617 "short",
02618 "unsigned short",
02619 NULL,
02620 "void",
02621 "char",
02622 "long",
02623 "unsigned long long",
02624 "..."
02625 };
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652 static status_t
02653 demangle_builtin_type (dm)
02654 demangling_t dm;
02655 {
02656
02657 char code = peek_char (dm);
02658
02659 DEMANGLE_TRACE ("builtin-type", dm);
02660
02661 if (code == 'u')
02662 {
02663 advance_char (dm);
02664 RETURN_IF_ERROR (demangle_source_name (dm));
02665 return STATUS_OK;
02666 }
02667 else if (code >= 'a' && code <= 'z')
02668 {
02669 const char *type_name;
02670
02671 if (dm->style == DMGL_JAVA)
02672 type_name = java_builtin_type_names[code - 'a'];
02673 else
02674 type_name = builtin_type_names[code - 'a'];
02675 if (type_name == NULL)
02676 return "Unrecognized <builtin-type> code.";
02677
02678 RETURN_IF_ERROR (result_add (dm, type_name));
02679 advance_char (dm);
02680 return STATUS_OK;
02681 }
02682 else
02683 return "Non-alphabetic <builtin-type> code.";
02684 }
02685
02686
02687
02688
02689
02690 static status_t
02691 demangle_CV_qualifiers (dm, qualifiers)
02692 demangling_t dm;
02693 dyn_string_t qualifiers;
02694 {
02695 DEMANGLE_TRACE ("CV-qualifiers", dm);
02696
02697 while (1)
02698 {
02699 switch (peek_char (dm))
02700 {
02701 case 'r':
02702 if (!dyn_string_append_space (qualifiers))
02703 return STATUS_ALLOCATION_FAILED;
02704 if (!dyn_string_append_cstr (qualifiers, "restrict"))
02705 return STATUS_ALLOCATION_FAILED;
02706 break;
02707
02708 case 'V':
02709 if (!dyn_string_append_space (qualifiers))
02710 return STATUS_ALLOCATION_FAILED;
02711 if (!dyn_string_append_cstr (qualifiers, "volatile"))
02712 return STATUS_ALLOCATION_FAILED;
02713 break;
02714
02715 case 'K':
02716 if (!dyn_string_append_space (qualifiers))
02717 return STATUS_ALLOCATION_FAILED;
02718 if (!dyn_string_append_cstr (qualifiers, "const"))
02719 return STATUS_ALLOCATION_FAILED;
02720 break;
02721
02722 default:
02723 return STATUS_OK;
02724 }
02725
02726 advance_char (dm);
02727 }
02728 }
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738 static status_t
02739 demangle_function_type (dm, function_name_pos)
02740 demangling_t dm;
02741 int *function_name_pos;
02742 {
02743 DEMANGLE_TRACE ("function-type", dm);
02744 RETURN_IF_ERROR (demangle_char (dm, 'F'));
02745 if (peek_char (dm) == 'Y')
02746 {
02747
02748 if (flag_verbose)
02749 RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));
02750 advance_char (dm);
02751 }
02752 RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
02753 RETURN_IF_ERROR (demangle_char (dm, 'E'));
02754 return STATUS_OK;
02755 }
02756
02757
02758
02759
02760
02761
02762
02763
02764 static status_t
02765 demangle_bare_function_type (dm, return_type_pos)
02766 demangling_t dm;
02767 int *return_type_pos;
02768 {
02769
02770
02771 int sequence =
02772 (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
02773
02774 DEMANGLE_TRACE ("bare-function-type", dm);
02775
02776 RETURN_IF_ERROR (result_add_char (dm, '('));
02777 while (!end_of_name_p (dm) && peek_char (dm) != 'E')
02778 {
02779 if (sequence == -1)
02780
02781 {
02782 dyn_string_t return_type;
02783 status_t status = STATUS_OK;
02784
02785
02786 RETURN_IF_ERROR (result_push (dm));
02787 RETURN_IF_ERROR (demangle_type (dm));
02788 return_type = (dyn_string_t) result_pop (dm);
02789
02790
02791
02792 if (!dyn_string_append_space (return_type))
02793 status = STATUS_ALLOCATION_FAILED;
02794 if (STATUS_NO_ERROR (status))
02795 {
02796 if (!dyn_string_insert (result_string (dm), *return_type_pos,
02797 return_type))
02798 status = STATUS_ALLOCATION_FAILED;
02799 else
02800 *return_type_pos += dyn_string_length (return_type);
02801 }
02802
02803 dyn_string_delete (return_type);
02804 RETURN_IF_ERROR (status);
02805 }
02806 else
02807 {
02808
02809
02810
02811 if (peek_char (dm) == 'v')
02812
02813 advance_char (dm);
02814 else
02815 {
02816
02817 if (sequence > 0)
02818 RETURN_IF_ERROR (result_add (dm, ", "));
02819
02820 RETURN_IF_ERROR (demangle_type (dm));
02821 }
02822 }
02823
02824 ++sequence;
02825 }
02826 RETURN_IF_ERROR (result_add_char (dm, ')'));
02827
02828
02829
02830
02831 if (sequence == -1)
02832 return "Missing function return type.";
02833 else if (sequence == 0)
02834 return "Missing function parameter.";
02835
02836 return STATUS_OK;
02837 }
02838
02839
02840
02841
02842
02843
02844 static status_t
02845 demangle_class_enum_type (dm, encode_return_type)
02846 demangling_t dm;
02847 int *encode_return_type;
02848 {
02849 DEMANGLE_TRACE ("class-enum-type", dm);
02850
02851 RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
02852 return STATUS_OK;
02853 }
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872 static status_t
02873 demangle_array_type (dm, ptr_insert_pos)
02874 demangling_t dm;
02875 int *ptr_insert_pos;
02876 {
02877 status_t status = STATUS_OK;
02878 dyn_string_t array_size = NULL;
02879 char peek;
02880
02881 DEMANGLE_TRACE ("array-type", dm);
02882
02883 RETURN_IF_ERROR (demangle_char (dm, 'A'));
02884
02885
02886 peek = peek_char (dm);
02887 if (peek == '_')
02888
02889 ;
02890 else if (IS_DIGIT (peek_char (dm)))
02891 {
02892
02893 array_size = dyn_string_new (10);
02894 if (array_size == NULL)
02895 return STATUS_ALLOCATION_FAILED;
02896 status = demangle_number_literally (dm, array_size, 10, 0);
02897 }
02898 else
02899 {
02900
02901
02902
02903 RETURN_IF_ERROR (result_push (dm));
02904 RETURN_IF_ERROR (demangle_expression (dm));
02905 array_size = (dyn_string_t) result_pop (dm);
02906 }
02907
02908
02909
02910
02911 if (STATUS_NO_ERROR (status))
02912 status = demangle_char (dm, '_');
02913 if (STATUS_NO_ERROR (status))
02914 status = demangle_type (dm);
02915
02916 if (ptr_insert_pos != NULL)
02917 {
02918
02919
02920
02921 if (STATUS_NO_ERROR (status))
02922 status = result_add (dm, " () ");
02923
02924 *ptr_insert_pos = result_caret_pos (dm) - 2;
02925 }
02926
02927
02928 if (STATUS_NO_ERROR (status))
02929 status = result_add_char (dm, '[');
02930 if (STATUS_NO_ERROR (status) && array_size != NULL)
02931 status = result_add_string (dm, array_size);
02932 if (STATUS_NO_ERROR (status))
02933 status = result_add_char (dm, ']');
02934 if (array_size != NULL)
02935 dyn_string_delete (array_size);
02936
02937 RETURN_IF_ERROR (status);
02938
02939 return STATUS_OK;
02940 }
02941
02942
02943
02944
02945
02946
02947 static status_t
02948 demangle_template_param (dm)
02949 demangling_t dm;
02950 {
02951 int parm_number;
02952 template_arg_list_t current_arg_list = current_template_arg_list (dm);
02953 string_list_t arg;
02954
02955 DEMANGLE_TRACE ("template-param", dm);
02956
02957
02958
02959 if (current_arg_list == NULL)
02960 return "Template parameter outside of template.";
02961
02962 RETURN_IF_ERROR (demangle_char (dm, 'T'));
02963 if (peek_char (dm) == '_')
02964 parm_number = 0;
02965 else
02966 {
02967 RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
02968 ++parm_number;
02969 }
02970 RETURN_IF_ERROR (demangle_char (dm, '_'));
02971
02972 arg = template_arg_list_get_arg (current_arg_list, parm_number);
02973 if (arg == NULL)
02974
02975
02976 return "Template parameter number out of bounds.";
02977 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
02978
02979 return STATUS_OK;
02980 }
02981
02982
02983
02984
02985
02986 static status_t
02987 demangle_template_args (dm)
02988 demangling_t dm;
02989 {
02990 int first = 1;
02991 dyn_string_t old_last_source_name;
02992 template_arg_list_t arg_list = template_arg_list_new ();
02993
02994 if (arg_list == NULL)
02995 return STATUS_ALLOCATION_FAILED;
02996
02997
02998 old_last_source_name = dm->last_source_name;
02999 dm->last_source_name = dyn_string_new (0);
03000
03001 DEMANGLE_TRACE ("template-args", dm);
03002
03003 if (dm->last_source_name == NULL)
03004 return STATUS_ALLOCATION_FAILED;
03005
03006 RETURN_IF_ERROR (demangle_char (dm, 'I'));
03007 RETURN_IF_ERROR (result_open_template_list (dm));
03008 do
03009 {
03010 string_list_t arg;
03011
03012 if (first)
03013 first = 0;
03014 else
03015 RETURN_IF_ERROR (result_add (dm, ", "));
03016
03017
03018 RETURN_IF_ERROR (result_push (dm));
03019 RETURN_IF_ERROR (demangle_template_arg (dm));
03020 arg = result_pop (dm);
03021
03022
03023 RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
03024
03025
03026 template_arg_list_add_arg (arg_list, arg);
03027 }
03028 while (peek_char (dm) != 'E');
03029
03030 RETURN_IF_ERROR (result_close_template_list (dm));
03031
03032
03033 advance_char (dm);
03034
03035
03036 dyn_string_delete (dm->last_source_name);
03037 dm->last_source_name = old_last_source_name;
03038
03039
03040
03041
03042 push_template_arg_list (dm, arg_list);
03043
03044 return STATUS_OK;
03045 }
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056 static status_t
03057 demangle_literal (dm)
03058 demangling_t dm;
03059 {
03060 char peek = peek_char (dm);
03061 dyn_string_t value_string;
03062 status_t status;
03063
03064 DEMANGLE_TRACE ("literal", dm);
03065
03066 if (!flag_verbose && peek >= 'a' && peek <= 'z')
03067 {
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082 static const char *const code_map = "ibi iii ll ii i ";
03083
03084 char code = code_map[peek - 'a'];
03085
03086 if (code == 'u')
03087 return STATUS_UNIMPLEMENTED;
03088 if (code == 'b')
03089 {
03090
03091 char value;
03092
03093
03094 advance_char (dm);
03095
03096
03097 value = peek_char (dm);
03098 if (value == '0')
03099 RETURN_IF_ERROR (result_add (dm, "false"));
03100 else if (value == '1')
03101 RETURN_IF_ERROR (result_add (dm, "true"));
03102 else
03103 return "Unrecognized bool constant.";
03104
03105 advance_char (dm);
03106 return STATUS_OK;
03107 }
03108 else if (code == 'i' || code == 'l')
03109 {
03110
03111
03112
03113 advance_char (dm);
03114
03115
03116 value_string = dyn_string_new (0);
03117 status = demangle_number_literally (dm, value_string, 10, 1);
03118 if (STATUS_NO_ERROR (status))
03119 status = result_add_string (dm, value_string);
03120
03121 if (code == 'l' && STATUS_NO_ERROR (status))
03122 status = result_add_char (dm, code);
03123 dyn_string_delete (value_string);
03124
03125 RETURN_IF_ERROR (status);
03126 return STATUS_OK;
03127 }
03128
03129
03130 }
03131
03132 RETURN_IF_ERROR (result_add_char (dm, '('));
03133 RETURN_IF_ERROR (demangle_type (dm));
03134 RETURN_IF_ERROR (result_add_char (dm, ')'));
03135
03136 value_string = dyn_string_new (0);
03137 if (value_string == NULL)
03138 return STATUS_ALLOCATION_FAILED;
03139
03140 status = demangle_number_literally (dm, value_string, 10, 1);
03141 if (STATUS_NO_ERROR (status))
03142 status = result_add_string (dm, value_string);
03143 dyn_string_delete (value_string);
03144 RETURN_IF_ERROR (status);
03145
03146 return STATUS_OK;
03147 }
03148
03149
03150
03151
03152
03153
03154
03155
03156 static status_t
03157 demangle_template_arg (dm)
03158 demangling_t dm;
03159 {
03160 DEMANGLE_TRACE ("template-arg", dm);
03161
03162 switch (peek_char (dm))
03163 {
03164 case 'L':
03165 advance_char (dm);
03166
03167 if (peek_char (dm) == 'Z')
03168 {
03169
03170 advance_char (dm);
03171
03172 RETURN_IF_ERROR (demangle_encoding (dm));
03173 }
03174 else
03175 RETURN_IF_ERROR (demangle_literal (dm));
03176 RETURN_IF_ERROR (demangle_char (dm, 'E'));
03177 break;
03178
03179 case 'X':
03180
03181 advance_char (dm);
03182 RETURN_IF_ERROR (demangle_expression (dm));
03183 RETURN_IF_ERROR (demangle_char (dm, 'E'));
03184 break;
03185
03186 default:
03187 RETURN_IF_ERROR (demangle_type (dm));
03188 break;
03189 }
03190
03191 return STATUS_OK;
03192 }
03193
03194
03195
03196
03197
03198
03199
03200
03201 static status_t
03202 demangle_expression (dm)
03203 demangling_t dm;
03204 {
03205 char peek = peek_char (dm);
03206
03207 DEMANGLE_TRACE ("expression", dm);
03208
03209 if (peek == 'L' || peek == 'T')
03210 RETURN_IF_ERROR (demangle_expr_primary (dm));
03211 else if (peek == 's' && peek_char_next (dm) == 'r')
03212 RETURN_IF_ERROR (demangle_scope_expression (dm));
03213 else
03214
03215 {
03216 int num_args;
03217 int type_arg;
03218 status_t status = STATUS_OK;
03219 dyn_string_t operator_name;
03220
03221
03222
03223
03224 RETURN_IF_ERROR (result_push (dm));
03225 RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args,
03226 &type_arg));
03227 operator_name = (dyn_string_t) result_pop (dm);
03228
03229
03230 if (num_args > 1)
03231 {
03232 status = result_add_char (dm, '(');
03233 if (STATUS_NO_ERROR (status))
03234 status = demangle_expression (dm);
03235 if (STATUS_NO_ERROR (status))
03236 status = result_add_char (dm, ')');
03237 }
03238
03239
03240 if (STATUS_NO_ERROR (status))
03241 status = result_add_string (dm, operator_name);
03242 dyn_string_delete (operator_name);
03243 RETURN_IF_ERROR (status);
03244
03245
03246 RETURN_IF_ERROR (result_add_char (dm, '('));
03247 if (type_arg)
03248 RETURN_IF_ERROR (demangle_type (dm));
03249 else
03250 RETURN_IF_ERROR (demangle_expression (dm));
03251 RETURN_IF_ERROR (result_add_char (dm, ')'));
03252
03253
03254 if (num_args == 3)
03255 {
03256 RETURN_IF_ERROR (result_add (dm, ":("));
03257 RETURN_IF_ERROR (demangle_expression (dm));
03258 RETURN_IF_ERROR (result_add_char (dm, ')'));
03259 }
03260 }
03261
03262 return STATUS_OK;
03263 }
03264
03265
03266
03267
03268
03269
03270 static status_t
03271 demangle_scope_expression (dm)
03272 demangling_t dm;
03273 {
03274 RETURN_IF_ERROR (demangle_char (dm, 's'));
03275 RETURN_IF_ERROR (demangle_char (dm, 'r'));
03276 RETURN_IF_ERROR (demangle_type (dm));
03277 RETURN_IF_ERROR (result_add (dm, "::"));
03278 RETURN_IF_ERROR (demangle_encoding (dm));
03279 return STATUS_OK;
03280 }
03281
03282
03283
03284
03285
03286
03287
03288 static status_t
03289 demangle_expr_primary (dm)
03290 demangling_t dm;
03291 {
03292 char peek = peek_char (dm);
03293
03294 DEMANGLE_TRACE ("expr-primary", dm);
03295
03296 if (peek == 'T')
03297 RETURN_IF_ERROR (demangle_template_param (dm));
03298 else if (peek == 'L')
03299 {
03300
03301 advance_char (dm);
03302 peek = peek_char (dm);
03303
03304 if (peek == '_')
03305 RETURN_IF_ERROR (demangle_mangled_name (dm));
03306 else
03307 RETURN_IF_ERROR (demangle_literal (dm));
03308
03309 RETURN_IF_ERROR (demangle_char (dm, 'E'));
03310 }
03311 else
03312 return STATUS_ERROR;
03313
03314 return STATUS_OK;
03315 }
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337 static status_t
03338 demangle_substitution (dm, template_p)
03339 demangling_t dm;
03340 int *template_p;
03341 {
03342 int seq_id;
03343 int peek;
03344 dyn_string_t text;
03345
03346 DEMANGLE_TRACE ("substitution", dm);
03347
03348 RETURN_IF_ERROR (demangle_char (dm, 'S'));
03349
03350
03351
03352 peek = peek_char (dm);
03353 if (peek == '_')
03354 seq_id = -1;
03355
03356
03357
03358 else if (IS_DIGIT ((unsigned char) peek)
03359 || (peek >= 'A' && peek <= 'Z'))
03360 RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
03361 else
03362 {
03363 const char *new_last_source_name = NULL;
03364
03365 switch (peek)
03366 {
03367 case 't':
03368 RETURN_IF_ERROR (result_add (dm, "std"));
03369 break;
03370
03371 case 'a':
03372 RETURN_IF_ERROR (result_add (dm, "std::allocator"));
03373 new_last_source_name = "allocator";
03374 *template_p = 1;
03375 break;
03376
03377 case 'b':
03378 RETURN_IF_ERROR (result_add (dm, "std::basic_string"));
03379 new_last_source_name = "basic_string";
03380 *template_p = 1;
03381 break;
03382
03383 case 's':
03384 if (!flag_verbose)
03385 {
03386 RETURN_IF_ERROR (result_add (dm, "std::string"));
03387 new_last_source_name = "string";
03388 }
03389 else
03390 {
03391 RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
03392 new_last_source_name = "basic_string";
03393 }
03394 *template_p = 0;
03395 break;
03396
03397 case 'i':
03398 if (!flag_verbose)
03399 {
03400 RETURN_IF_ERROR (result_add (dm, "std::istream"));
03401 new_last_source_name = "istream";
03402 }
03403 else
03404 {
03405 RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traits<char> >"));
03406 new_last_source_name = "basic_istream";
03407 }
03408 *template_p = 0;
03409 break;
03410
03411 case 'o':
03412 if (!flag_verbose)
03413 {
03414 RETURN_IF_ERROR (result_add (dm, "std::ostream"));
03415 new_last_source_name = "ostream";
03416 }
03417 else
03418 {
03419 RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));
03420 new_last_source_name = "basic_ostream";
03421 }
03422 *template_p = 0;
03423 break;
03424
03425 case 'd':
03426 if (!flag_verbose)
03427 {
03428 RETURN_IF_ERROR (result_add (dm, "std::iostream"));
03429 new_last_source_name = "iostream";
03430 }
03431 else
03432 {
03433 RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));
03434 new_last_source_name = "basic_iostream";
03435 }
03436 *template_p = 0;
03437 break;
03438
03439 default:
03440 return "Unrecognized <substitution>.";
03441 }
03442
03443
03444 advance_char (dm);
03445
03446 if (new_last_source_name != NULL)
03447 {
03448 if (!dyn_string_copy_cstr (dm->last_source_name,
03449 new_last_source_name))
03450 return STATUS_ALLOCATION_FAILED;
03451 }
03452
03453 return STATUS_OK;
03454 }
03455
03456
03457
03458
03459 text = substitution_get (dm, seq_id + 1, template_p);
03460 if (text == NULL)
03461 return "Substitution number out of range.";
03462
03463
03464 RETURN_IF_ERROR (result_add_string (dm, text));
03465
03466 RETURN_IF_ERROR (demangle_char (dm, '_'));
03467 return STATUS_OK;
03468 }
03469
03470
03471
03472
03473
03474
03475 static status_t
03476 demangle_local_name (dm)
03477 demangling_t dm;
03478 {
03479 DEMANGLE_TRACE ("local-name", dm);
03480
03481 RETURN_IF_ERROR (demangle_char (dm, 'Z'));
03482 RETURN_IF_ERROR (demangle_encoding (dm));
03483 RETURN_IF_ERROR (demangle_char (dm, 'E'));
03484 RETURN_IF_ERROR (result_add (dm, "::"));
03485
03486 if (peek_char (dm) == 's')
03487 {
03488
03489 RETURN_IF_ERROR (result_add (dm, "string literal"));
03490
03491 advance_char (dm);
03492 RETURN_IF_ERROR (demangle_discriminator (dm, 0));
03493 }
03494 else
03495 {
03496 int unused;
03497
03498 RETURN_IF_ERROR (demangle_name (dm, &unused));
03499 RETURN_IF_ERROR (demangle_discriminator (dm, 1));
03500 }
03501
03502 return STATUS_OK;
03503 }
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513 static status_t
03514 demangle_discriminator (dm, suppress_first)
03515 demangling_t dm;
03516 int suppress_first;
03517 {
03518
03519
03520
03521 if (peek_char (dm) == '_')
03522 {
03523
03524 advance_char (dm);
03525 if (flag_verbose)
03526 RETURN_IF_ERROR (result_add (dm, " [#"));
03527
03528 if (IS_DIGIT ((unsigned char) peek_char (dm)))
03529 {
03530 int discriminator;
03531
03532 RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
03533 if (flag_verbose)
03534
03535
03536
03537 RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,
03538 (dyn_string_t) dm->result));
03539 }
03540 else
03541 return STATUS_ERROR;
03542 if (flag_verbose)
03543 RETURN_IF_ERROR (result_add_char (dm, ']'));
03544 }
03545 else if (!suppress_first)
03546 {
03547 if (flag_verbose)
03548 RETURN_IF_ERROR (result_add (dm, " [#0]"));
03549 }
03550
03551 return STATUS_OK;
03552 }
03553
03554
03555
03556
03557
03558 static status_t
03559 cp_demangle (name, result, style)
03560 const char *name;
03561 dyn_string_t result;
03562 int style;
03563 {
03564 status_t status;
03565 int length = strlen (name);
03566
03567 if (length > 2 && name[0] == '_' && name[1] == 'Z')
03568 {
03569 demangling_t dm = demangling_new (name, style);
03570 if (dm == NULL)
03571 return STATUS_ALLOCATION_FAILED;
03572
03573 status = result_push (dm);
03574 if (status != STATUS_OK)
03575 {
03576 demangling_delete (dm);
03577 return status;
03578 }
03579
03580 status = demangle_mangled_name (dm);
03581 if (STATUS_NO_ERROR (status))
03582 {
03583 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
03584 if (!dyn_string_copy (result, demangled))
03585 return STATUS_ALLOCATION_FAILED;
03586 dyn_string_delete (demangled);
03587 }
03588
03589 demangling_delete (dm);
03590 }
03591 else
03592 {
03593
03594
03595
03596 if (!dyn_string_copy_cstr (result, name))
03597 return STATUS_ALLOCATION_FAILED;
03598 status = STATUS_OK;
03599 }
03600
03601 return status;
03602 }
03603
03604
03605
03606
03607
03608 static status_t
03609 cp_demangle_type (type_name, result)
03610 const char* type_name;
03611 dyn_string_t result;
03612 {
03613 status_t status;
03614 demangling_t dm = demangling_new (type_name, DMGL_GNU_V3);
03615
03616 if (dm == NULL)
03617 return STATUS_ALLOCATION_FAILED;
03618
03619
03620 status = result_push (dm);
03621 if (status != STATUS_OK)
03622 {
03623 demangling_delete (dm);
03624 return status;
03625 }
03626
03627 status = demangle_type (dm);
03628
03629 if (STATUS_NO_ERROR (status))
03630 {
03631
03632
03633 dyn_string_t demangled = (dyn_string_t) result_pop (dm);
03634 if (!dyn_string_copy (result, demangled))
03635 return STATUS_ALLOCATION_FAILED;
03636 dyn_string_delete (demangled);
03637 }
03638
03639
03640 demangling_delete (dm);
03641
03642 return status;
03643 }
03644
03645 #if defined(IN_LIBGCC2) || defined(IN_GLIBCPP_V3)
03646 extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674 char *
03675 __cxa_demangle (mangled_name, output_buffer, length, status)
03676 const char *mangled_name;
03677 char *output_buffer;
03678 size_t *length;
03679 int *status;
03680 {
03681 struct dyn_string demangled_name;
03682 status_t result;
03683
03684 if (status == NULL)
03685 return NULL;
03686
03687 if (mangled_name == NULL) {
03688 *status = -3;
03689 return NULL;
03690 }
03691
03692
03693 if (output_buffer == NULL) {
03694
03695 if (!dyn_string_init (&demangled_name, 0))
03696 {
03697 *status = -1;
03698 return NULL;
03699 }
03700 }
03701 else {
03702
03703 if (length == NULL) {
03704 *status = -3;
03705 return NULL;
03706 }
03707
03708 demangled_name.allocated = *length;
03709 demangled_name.length = 0;
03710 demangled_name.s = output_buffer;
03711 }
03712
03713 if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
03714
03715
03716 result = cp_demangle (mangled_name, &demangled_name, 0);
03717 else
03718
03719 result = cp_demangle_type (mangled_name, &demangled_name);
03720
03721 if (result == STATUS_OK)
03722
03723 {
03724
03725
03726
03727 if (length != NULL)
03728 *length = demangled_name.allocated;
03729
03730 *status = 0;
03731 return dyn_string_buf (&demangled_name);
03732 }
03733 else if (result == STATUS_ALLOCATION_FAILED)
03734
03735
03736 {
03737 *status = -1;
03738 return NULL;
03739 }
03740 else
03741
03742
03743 {
03744
03745
03746 if (output_buffer == NULL)
03747 free (dyn_string_buf (&demangled_name));
03748 *status = -2;
03749 return NULL;
03750 }
03751 }
03752
03753 #else
03754
03755
03756
03757
03758
03759
03760
03761 char *
03762 cplus_demangle_v3 (mangled, options)
03763 const char* mangled;
03764 int options;
03765 {
03766 dyn_string_t demangled;
03767 status_t status;
03768 int type = !!(options & DMGL_TYPES);
03769
03770 if (mangled[0] == '_' && mangled[1] == 'Z')
03771
03772 type = 0;
03773 else
03774 {
03775
03776 if (!type)
03777 return NULL;
03778 }
03779
03780 flag_verbose = !!(options & DMGL_VERBOSE);
03781
03782
03783 demangled = dyn_string_new (0);
03784
03785 if (!type)
03786
03787 status = cp_demangle (mangled, demangled, 0);
03788 else
03789
03790 status = cp_demangle_type (mangled, demangled);
03791
03792 if (STATUS_NO_ERROR (status))
03793
03794 {
03795
03796
03797 char *return_value = dyn_string_release (demangled);
03798
03799 return return_value;
03800 }
03801 else if (status == STATUS_ALLOCATION_FAILED)
03802 {
03803 fprintf (stderr, "Memory allocation failed.\n");
03804 abort ();
03805 }
03806 else
03807
03808 {
03809 dyn_string_delete (demangled);
03810 return NULL;
03811 }
03812 }
03813
03814
03815
03816
03817
03818
03819
03820
03821 char *
03822 java_demangle_v3 (mangled)
03823 const char* mangled;
03824 {
03825 dyn_string_t demangled;
03826 char *next;
03827 char *end;
03828 int len;
03829 status_t status;
03830 int nesting = 0;
03831 char *cplus_demangled;
03832 char *return_value;
03833
03834
03835 demangled = dyn_string_new (0);
03836
03837
03838 status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);
03839
03840 if (STATUS_NO_ERROR (status))
03841
03842 {
03843
03844 cplus_demangled = dyn_string_release (demangled);
03845 }
03846 else if (status == STATUS_ALLOCATION_FAILED)
03847 {
03848 fprintf (stderr, "Memory allocation failed.\n");
03849 abort ();
03850 }
03851 else
03852
03853 {
03854 dyn_string_delete (demangled);
03855 return NULL;
03856 }
03857
03858 len = strlen (cplus_demangled);
03859 next = cplus_demangled;
03860 end = next + len;
03861 demangled = NULL;
03862
03863
03864 while (next < end)
03865 {
03866 char *open_str = strstr (next, "JArray<");
03867 char *close_str = NULL;
03868 if (nesting > 0)
03869 close_str = strchr (next, '>');
03870
03871 if (open_str != NULL && (close_str == NULL || close_str > open_str))
03872 {
03873 ++nesting;
03874
03875 if (!demangled)
03876 demangled = dyn_string_new(len);
03877
03878
03879 if (open_str > next)
03880 {
03881 open_str[0] = 0;
03882 dyn_string_append_cstr (demangled, next);
03883 }
03884 next = open_str + 7;
03885 }
03886 else if (close_str != NULL)
03887 {
03888 --nesting;
03889
03890
03891
03892 if (close_str > next && next[0] != ' ')
03893 {
03894 close_str[0] = 0;
03895 dyn_string_append_cstr (demangled, next);
03896 }
03897 dyn_string_append_cstr (demangled, "[]");
03898 next = close_str + 1;
03899 }
03900 else
03901 {
03902
03903
03904 if (next == cplus_demangled)
03905 return cplus_demangled;
03906
03907 dyn_string_append_cstr (demangled, next);
03908 next = end;
03909 }
03910 }
03911
03912 free (cplus_demangled);
03913
03914 if (demangled)
03915 return_value = dyn_string_release (demangled);
03916 else
03917 return_value = NULL;
03918
03919 return return_value;
03920 }
03921
03922 #endif
03923
03924
03925 #ifndef IN_GLIBCPP_V3
03926
03927
03928
03929 static demangling_t
03930 demangle_v3_with_details (name)
03931 const char *name;
03932 {
03933 demangling_t dm;
03934 status_t status;
03935
03936 if (strncmp (name, "_Z", 2))
03937 return 0;
03938
03939 dm = demangling_new (name, DMGL_GNU_V3);
03940 if (dm == NULL)
03941 {
03942 fprintf (stderr, "Memory allocation failed.\n");
03943 abort ();
03944 }
03945
03946 status = result_push (dm);
03947 if (! STATUS_NO_ERROR (status))
03948 {
03949 demangling_delete (dm);
03950 fprintf (stderr, "%s\n", status);
03951 abort ();
03952 }
03953
03954 status = demangle_mangled_name (dm);
03955 if (STATUS_NO_ERROR (status))
03956 return dm;
03957
03958 demangling_delete (dm);
03959 return 0;
03960 }
03961
03962
03963
03964
03965
03966
03967
03968 enum gnu_v3_ctor_kinds
03969 is_gnu_v3_mangled_ctor (name)
03970 const char *name;
03971 {
03972 demangling_t dm = demangle_v3_with_details (name);
03973
03974 if (dm)
03975 {
03976 enum gnu_v3_ctor_kinds result = dm->is_constructor;
03977 demangling_delete (dm);
03978 return result;
03979 }
03980 else
03981 return (enum gnu_v3_ctor_kinds) 0;
03982 }
03983
03984
03985
03986
03987
03988
03989
03990 enum gnu_v3_dtor_kinds
03991 is_gnu_v3_mangled_dtor (name)
03992 const char *name;
03993 {
03994 demangling_t dm = demangle_v3_with_details (name);
03995
03996 if (dm)
03997 {
03998 enum gnu_v3_dtor_kinds result = dm->is_destructor;
03999 demangling_delete (dm);
04000 return result;
04001 }
04002 else
04003 return (enum gnu_v3_dtor_kinds) 0;
04004 }
04005 #endif
04006
04007
04008 #ifdef STANDALONE_DEMANGLER
04009
04010 #include "getopt.h"
04011
04012 static void print_usage
04013 PARAMS ((FILE* fp, int exit_value));
04014
04015
04016 #define is_mangled_char(CHAR) \
04017 (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
04018 || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
04019
04020
04021 const char* program_name;
04022
04023
04024
04025 static void
04026 print_usage (fp, exit_value)
04027 FILE* fp;
04028 int exit_value;
04029 {
04030 fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
04031 fprintf (fp, "Options:\n");
04032 fprintf (fp, " -h,--help Display this message.\n");
04033 fprintf (fp, " -s,--strict Demangle standard names only.\n");
04034 fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
04035 fprintf (fp, "If names are provided, they are demangled. Otherwise filters standard input.\n");
04036
04037 exit (exit_value);
04038 }
04039
04040
04041 static const struct option long_options[] =
04042 {
04043 { "help", no_argument, NULL, 'h' },
04044 { "strict", no_argument, NULL, 's' },
04045 { "verbose", no_argument, NULL, 'v' },
04046 { NULL, no_argument, NULL, 0 },
04047 };
04048
04049
04050
04051
04052
04053
04054 int
04055 main (argc, argv)
04056 int argc;
04057 char *argv[];
04058 {
04059 status_t status;
04060 int i;
04061 int opt_char;
04062
04063
04064 program_name = argv[0];
04065
04066
04067 do
04068 {
04069 opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
04070 switch (opt_char)
04071 {
04072 case '?':
04073 print_usage (stderr, 1);
04074 break;
04075
04076 case 'h':
04077 print_usage (stdout, 0);
04078 break;
04079
04080 case 's':
04081 flag_strict = 1;
04082 break;
04083
04084 case 'v':
04085 flag_verbose = 1;
04086 break;
04087 }
04088 }
04089 while (opt_char != -1);
04090
04091 if (optind == argc)
04092
04093 {
04094 dyn_string_t mangled = dyn_string_new (3);
04095 dyn_string_t demangled = dyn_string_new (0);
04096 status_t status;
04097
04098
04099 while (!feof (stdin))
04100 {
04101 char c = getchar ();
04102
04103
04104 if (feof (stdin))
04105 break;
04106 if (c != '_')
04107 {
04108
04109
04110 putchar (c);
04111 continue;
04112 }
04113 c = getchar ();
04114
04115
04116 if (feof (stdin))
04117 break;
04118 if (c != 'Z')
04119 {
04120
04121
04122 putchar ('_');
04123 putchar (c);
04124 continue;
04125 }
04126
04127
04128 dyn_string_append_char (mangled, '_');
04129 dyn_string_append_char (mangled, 'Z');
04130
04131
04132
04133 c = getchar ();
04134 while (!feof (stdin) && is_mangled_char (c))
04135 {
04136 dyn_string_append_char (mangled, c);
04137 if (feof (stdin))
04138 break;
04139 c = getchar ();
04140 }
04141
04142
04143 status = cp_demangle (dyn_string_buf (mangled), demangled, 0);
04144
04145
04146
04147 if (STATUS_NO_ERROR (status))
04148 fputs (dyn_string_buf (demangled), stdout);
04149
04150 else if (status == STATUS_ALLOCATION_FAILED)
04151 {
04152 fprintf (stderr, "Memory allocation failed.\n");
04153 abort ();
04154 }
04155
04156
04157 else
04158 fputs (dyn_string_buf (mangled), stdout);
04159
04160
04161
04162 if (!feof (stdin))
04163 putchar (c);
04164
04165
04166
04167 dyn_string_clear (mangled);
04168 }
04169
04170 dyn_string_delete (mangled);
04171 dyn_string_delete (demangled);
04172 }
04173 else
04174
04175 {
04176 dyn_string_t result = dyn_string_new (0);
04177
04178
04179 for (i = optind; i < argc; ++i)
04180 {
04181
04182 status = cp_demangle (argv[i], result, 0);
04183
04184
04185 if (STATUS_NO_ERROR (status))
04186 printf ("%s\n", dyn_string_buf (result));
04187
04188 else if (status == STATUS_ALLOCATION_FAILED)
04189 {
04190 fprintf (stderr, "Memory allocation failed.\n");
04191 abort ();
04192 }
04193
04194 else
04195 fprintf (stderr, "%s\n", status);
04196 }
04197 dyn_string_delete (result);
04198 }
04199
04200 return 0;
04201 }
04202
04203 #endif