OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [libiberty/] [cp-demangle.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Demangler for IA64 / g++ V3 ABI.
2
   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
3
   Written by Alex Samuel <samuel@codesourcery.com>.
4
 
5
   This file is part of GNU CC.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20
*/
21
 
22
/* This file implements demangling of C++ names mangled according to
23
   the IA64 / g++ V3 ABI.  Use the cp_demangle function to
24
   demangle a mangled name, or compile with the preprocessor macro
25
   STANDALONE_DEMANGLER defined to create a demangling filter
26
   executable (functionally similar to c++filt, but includes this
27
   demangler only).  */
28
 
29
#ifdef HAVE_CONFIG_H
30
#include "config.h"
31
#endif
32
 
33
#include <sys/types.h>
34
 
35
#ifdef HAVE_STDLIB_H
36
#include <stdlib.h>
37
#endif
38
 
39
#include <stdio.h>
40
 
41
#ifdef HAVE_STRING_H
42
#include <string.h>
43
#endif
44
 
45
#include "ansidecl.h"
46
#include "libiberty.h"
47
#include "dyn-string.h"
48
#include "demangle.h"
49
 
50
/* If CP_DEMANGLE_DEBUG is defined, a trace of the grammar evaluation,
51
   and other debugging output, will be generated. */
52
#ifdef CP_DEMANGLE_DEBUG
53
#define DEMANGLE_TRACE(PRODUCTION, DM)                                  \
54
  fprintf (stderr, " -> %-24s at position %3d\n",                       \
55
           (PRODUCTION), current_position (DM));
56
#else
57
#define DEMANGLE_TRACE(PRODUCTION, DM)
58
#endif
59
 
60
/* Don't include <ctype.h>, to prevent additional unresolved symbols
61
   from being dragged into the C++ runtime library.  */
62
#define IS_DIGIT(CHAR) ((CHAR) >= '0' && (CHAR) <= '9')
63
#define IS_ALPHA(CHAR)                                                  \
64
  (((CHAR) >= 'a' && (CHAR) <= 'z')                                     \
65
   || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
66
 
67
/* The prefix prepended by GCC to an identifier represnting the
68
   anonymous namespace.  */
69
#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
70
 
71
/* Character(s) to use for namespace separation in demangled output */
72
#define NAMESPACE_SEPARATOR (dm->style == DMGL_JAVA ? "." : "::")
73
 
74
/* If flag_verbose is zero, some simplifications will be made to the
75
   output to make it easier to read and supress details that are
76
   generally not of interest to the average C++ programmer.
77
   Otherwise, the demangled representation will attempt to convey as
78
   much information as the mangled form.  */
79
static int flag_verbose;
80
 
81
/* If flag_strict is non-zero, demangle strictly according to the
82
   specification -- don't demangle special g++ manglings.  */
83
static int flag_strict;
84
 
85
/* String_list_t is an extended form of dyn_string_t which provides a
86
   link field and a caret position for additions to the string.  A
87
   string_list_t may safely be cast to and used as a dyn_string_t.  */
88
 
89
struct string_list_def
90
{
91
  /* The dyn_string; must be first.  */
92
  struct dyn_string string;
93
 
94
  /* The position at which additional text is added to this string
95
     (using the result_add* macros).  This value is an offset from the
96
     end of the string, not the beginning (and should be
97
     non-positive).  */
98
  int caret_position;
99
 
100
  /* The next string in the list.  */
101
  struct string_list_def *next;
102
};
103
 
104
typedef struct string_list_def *string_list_t;
105
 
106
/* Data structure representing a potential substitution.  */
107
 
108
struct substitution_def
109
{
110
  /* The demangled text of the substitution.  */
111
  dyn_string_t text;
112
 
113
  /* Whether this substitution represents a template item.  */
114
  int template_p : 1;
115
};
116
 
117
/* Data structure representing a template argument list.  */
118
 
119
struct template_arg_list_def
120
{
121
  /* The next (lower) template argument list in the stack of currently
122
     active template arguments.  */
123
  struct template_arg_list_def *next;
124
 
125
  /* The first element in the list of template arguments in
126
     left-to-right order.  */
127
  string_list_t first_argument;
128
 
129
  /* The last element in the arguments lists.  */
130
  string_list_t last_argument;
131
};
132
 
133
typedef struct template_arg_list_def *template_arg_list_t;
134
 
135
/* Data structure to maintain the state of the current demangling.  */
136
 
137
struct demangling_def
138
{
139
  /* The full mangled name being mangled.  */
140
  const char *name;
141
 
142
  /* Pointer into name at the current position.  */
143
  const char *next;
144
 
145
  /* Stack for strings containing demangled result generated so far.
146
     Text is emitted to the topmost (first) string.  */
147
  string_list_t result;
148
 
149
  /* The number of presently available substitutions.  */
150
  int num_substitutions;
151
 
152
  /* The allocated size of the substitutions array.  */
153
  int substitutions_allocated;
154
 
155
  /* An array of available substitutions.  The number of elements in
156
     the array is given by num_substitions, and the allocated array
157
     size in substitutions_size.
158
 
159
     The most recent substition is at the end, so
160
 
161
       - `S_'  corresponds to substititutions[num_substitutions - 1]
162
       - `S0_' corresponds to substititutions[num_substitutions - 2]
163
 
164
     etc. */
165
  struct substitution_def *substitutions;
166
 
167
  /* The stack of template argument lists.  */
168
  template_arg_list_t template_arg_lists;
169
 
170
  /* The most recently demangled source-name.  */
171
  dyn_string_t last_source_name;
172
 
173
  /* Language style to use for demangled output. */
174
  int style;
175
 
176
  /* Set to non-zero iff this name is a constructor.  The actual value
177
     indicates what sort of constructor this is; see demangle.h.  */
178
  enum gnu_v3_ctor_kinds is_constructor;
179
 
180
  /* Set to non-zero iff this name is a destructor.  The actual value
181
     indicates what sort of destructor this is; see demangle.h.  */
182
  enum gnu_v3_dtor_kinds is_destructor;
183
 
184
};
185
 
186
typedef struct demangling_def *demangling_t;
187
 
188
/* This type is the standard return code from most functions.  Values
189
   other than STATUS_OK contain descriptive messages.  */
190
typedef const char *status_t;
191
 
192
/* Special values that can be used as a status_t.  */
193
#define STATUS_OK                       NULL
194
#define STATUS_ERROR                    "Error."
195
#define STATUS_UNIMPLEMENTED            "Unimplemented."
196
#define STATUS_INTERNAL_ERROR           "Internal error."
197
 
198
/* This status code indicates a failure in malloc or realloc.  */
199
static const char *const status_allocation_failed = "Allocation failed.";
200
#define STATUS_ALLOCATION_FAILED        status_allocation_failed
201
 
202
/* Non-zero if STATUS indicates that no error has occurred.  */
203
#define STATUS_NO_ERROR(STATUS)         ((STATUS) == STATUS_OK)
204
 
205
/* Evaluate EXPR, which must produce a status_t.  If the status code
206
   indicates an error, return from the current function with that
207
   status code.  */
208
#define RETURN_IF_ERROR(EXPR)                                           \
209
  do                                                                    \
210
    {                                                                   \
211
      status_t s = EXPR;                                                \
212
      if (!STATUS_NO_ERROR (s))                                         \
213
        return s;                                                       \
214
    }                                                                   \
215
  while (0)
216
 
217
static status_t int_to_dyn_string
218
  PARAMS ((int, dyn_string_t));
219
static string_list_t string_list_new
220
  PARAMS ((int));
221
static void string_list_delete
222
  PARAMS ((string_list_t));
223
static status_t result_add_separated_char
224
  PARAMS ((demangling_t, int));
225
static status_t result_push
226
  PARAMS ((demangling_t));
227
static string_list_t result_pop
228
  PARAMS ((demangling_t));
229
static int substitution_start
230
  PARAMS ((demangling_t));
231
static status_t substitution_add
232
  PARAMS ((demangling_t, int, int));
233
static dyn_string_t substitution_get
234
  PARAMS ((demangling_t, int, int *));
235
#ifdef CP_DEMANGLE_DEBUG
236
static void substitutions_print
237
  PARAMS ((demangling_t, FILE *));
238
#endif
239
static template_arg_list_t template_arg_list_new
240
  PARAMS ((void));
241
static void template_arg_list_delete
242
  PARAMS ((template_arg_list_t));
243
static void template_arg_list_add_arg
244
  PARAMS ((template_arg_list_t, string_list_t));
245
static string_list_t template_arg_list_get_arg
246
  PARAMS ((template_arg_list_t, int));
247
static void push_template_arg_list
248
  PARAMS ((demangling_t, template_arg_list_t));
249
static void pop_to_template_arg_list
250
  PARAMS ((demangling_t, template_arg_list_t));
251
#ifdef CP_DEMANGLE_DEBUG
252
static void template_arg_list_print
253
  PARAMS ((template_arg_list_t, FILE *));
254
#endif
255
static template_arg_list_t current_template_arg_list
256
  PARAMS ((demangling_t));
257
static demangling_t demangling_new
258
  PARAMS ((const char *, int));
259
static void demangling_delete
260
  PARAMS ((demangling_t));
261
 
262
/* The last character of DS.  Warning: DS is evaluated twice.  */
263
#define dyn_string_last_char(DS)                                        \
264
  (dyn_string_buf (DS)[dyn_string_length (DS) - 1])
265
 
266
/* Append a space character (` ') to DS if it does not already end
267
   with one.  Evaluates to 1 on success, or 0 on allocation failure.  */
268
#define dyn_string_append_space(DS)                                     \
269
      ((dyn_string_length (DS) > 0                                      \
270
        && dyn_string_last_char (DS) != ' ')                            \
271
       ? dyn_string_append_char ((DS), ' ')                             \
272
       : 1)
273
 
274
/* Returns the index of the current position in the mangled name.  */
275
#define current_position(DM)    ((DM)->next - (DM)->name)
276
 
277
/* Returns the character at the current position of the mangled name.  */
278
#define peek_char(DM)           (*((DM)->next))
279
 
280
/* Returns the character one past the current position of the mangled
281
   name.  */
282
#define peek_char_next(DM)                                              \
283
  (peek_char (DM) == '\0' ? '\0' : (*((DM)->next + 1)))
284
 
285
/* Returns the character at the current position, and advances the
286
   current position to the next character.  */
287
#define next_char(DM)           (*((DM)->next)++)
288
 
289
/* Returns non-zero if the current position is the end of the mangled
290
   name, i.e. one past the last character.  */
291
#define end_of_name_p(DM)       (peek_char (DM) == '\0')
292
 
293
/* Advances the current position by one character.  */
294
#define advance_char(DM)        (++(DM)->next)
295
 
296
/* Returns the string containing the current demangled result.  */
297
#define result_string(DM)       (&(DM)->result->string)
298
 
299
/* Returns the position at which new text is inserted into the
300
   demangled result.  */
301
#define result_caret_pos(DM)                                            \
302
  (result_length (DM) +                                                 \
303
   ((string_list_t) result_string (DM))->caret_position)
304
 
305
/* Adds a dyn_string_t to the demangled result.  */
306
#define result_add_string(DM, STRING)                                   \
307
  (dyn_string_insert (&(DM)->result->string,                            \
308
                      result_caret_pos (DM), (STRING))                  \
309
   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
310
 
311
/* Adds NUL-terminated string CSTR to the demangled result.    */
312
#define result_add(DM, CSTR)                                            \
313
  (dyn_string_insert_cstr (&(DM)->result->string,                       \
314
                           result_caret_pos (DM), (CSTR))               \
315
   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
316
 
317
/* Adds character CHAR to the demangled result.  */
318
#define result_add_char(DM, CHAR)                                       \
319
  (dyn_string_insert_char (&(DM)->result->string,                       \
320
                           result_caret_pos (DM), (CHAR))               \
321
   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
322
 
323
/* Inserts a dyn_string_t to the demangled result at position POS.  */
324
#define result_insert_string(DM, POS, STRING)                           \
325
  (dyn_string_insert (&(DM)->result->string, (POS), (STRING))           \
326
   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
327
 
328
/* Inserts NUL-terminated string CSTR to the demangled result at
329
   position POS.  */
330
#define result_insert(DM, POS, CSTR)                                    \
331
  (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR))        \
332
   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
333
 
334
/* Inserts character CHAR to the demangled result at position POS.  */
335
#define result_insert_char(DM, POS, CHAR)                               \
336
  (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR))        \
337
   ? STATUS_OK : STATUS_ALLOCATION_FAILED)
338
 
339
/* The length of the current demangled result.  */
340
#define result_length(DM)                                               \
341
  dyn_string_length (&(DM)->result->string)
342
 
343
/* Appends a (less-than, greater-than) character to the result in DM
344
   to (open, close) a template argument or parameter list.  Appends a
345
   space first if necessary to prevent spurious elision of angle
346
   brackets with the previous character.  */
347
#define result_open_template_list(DM) result_add_separated_char(DM, '<')
348
#define result_close_template_list(DM) result_add_separated_char(DM, '>')
349
 
350
/* Appends a base 10 representation of VALUE to DS.  STATUS_OK on
351
   success.  On failure, deletes DS and returns an error code.  */
352
 
353
static status_t
354
int_to_dyn_string (value, ds)
355
     int value;
356
     dyn_string_t ds;
357
{
358
  int i;
359
  int mask = 1;
360
 
361
  /* Handle zero up front.  */
362
  if (value == 0)
363
    {
364
      if (!dyn_string_append_char (ds, '0'))
365
        return STATUS_ALLOCATION_FAILED;
366
      return STATUS_OK;
367
    }
368
 
369
  /* For negative numbers, emit a minus sign.  */
370
  if (value < 0)
371
    {
372
      if (!dyn_string_append_char (ds, '-'))
373
        return STATUS_ALLOCATION_FAILED;
374
      value = -value;
375
    }
376
 
377
  /* Find the power of 10 of the first digit.  */
378
  i = value;
379
  while (i > 9)
380
    {
381
      mask *= 10;
382
      i /= 10;
383
    }
384
 
385
  /* Write the digits.  */
386
  while (mask > 0)
387
    {
388
      int digit = value / mask;
389
 
390
      if (!dyn_string_append_char (ds, '0' + digit))
391
        return STATUS_ALLOCATION_FAILED;
392
 
393
      value -= digit * mask;
394
      mask /= 10;
395
    }
396
 
397
  return STATUS_OK;
398
}
399
 
400
/* Creates a new string list node.  The contents of the string are
401
   empty, but the initial buffer allocation is LENGTH.  The string
402
   list node should be deleted with string_list_delete.  Returns NULL
403
   if allocation fails.  */
404
 
405
static string_list_t
406
string_list_new (length)
407
     int length;
408
{
409
  string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));
410
  s->caret_position = 0;
411
  if (s == NULL)
412
    return NULL;
413
  if (!dyn_string_init ((dyn_string_t) s, length))
414
    return NULL;
415
  return s;
416
}
417
 
418
/* Deletes the entire string list starting at NODE.  */
419
 
420
static void
421
string_list_delete (node)
422
     string_list_t node;
423
{
424
  while (node != NULL)
425
    {
426
      string_list_t next = node->next;
427
      dyn_string_delete ((dyn_string_t) node);
428
      node = next;
429
    }
430
}
431
 
432
/* Appends CHARACTER to the demangled result.  If the current trailing
433
   character of the result is CHARACTER, a space is inserted first.  */
434
 
435
static status_t
436
result_add_separated_char (dm, character)
437
     demangling_t dm;
438
     int character;
439
{
440
  char *result = dyn_string_buf (result_string (dm));
441
  int caret_pos = result_caret_pos (dm);
442
 
443
  /* Add a space if the last character is already the character we
444
     want to add.  */
445
  if (caret_pos > 0 && result[caret_pos - 1] == character)
446
    RETURN_IF_ERROR (result_add_char (dm, ' '));
447
  /* Add the character.  */
448
  RETURN_IF_ERROR (result_add_char (dm, character));
449
 
450
  return STATUS_OK;
451
}
452
 
453
/* Allocates and pushes a new string onto the demangled results stack
454
   for DM.  Subsequent demangling with DM will emit to the new string.
455
   Returns STATUS_OK on success, STATUS_ALLOCATION_FAILED on
456
   allocation failure.  */
457
 
458
static status_t
459
result_push (dm)
460
     demangling_t dm;
461
{
462
  string_list_t new_string = string_list_new (0);
463
  if (new_string == NULL)
464
    /* Allocation failed.  */
465
    return STATUS_ALLOCATION_FAILED;
466
 
467
  /* Link the new string to the front of the list of result strings.  */
468
  new_string->next = (string_list_t) dm->result;
469
  dm->result = new_string;
470
  return STATUS_OK;
471
}
472
 
473
/* Removes and returns the topmost element on the demangled results
474
   stack for DM.  The caller assumes ownership for the returned
475
   string.  */
476
 
477
static string_list_t
478
result_pop (dm)
479
     demangling_t dm;
480
{
481
  string_list_t top = dm->result;
482
  dm->result = top->next;
483
  return top;
484
}
485
 
486
/* Returns the current value of the caret for the result string.  The
487
   value is an offet from the end of the result string.  */
488
 
489
static int
490
result_get_caret (dm)
491
     demangling_t dm;
492
{
493
  return ((string_list_t) result_string (dm))->caret_position;
494
}
495
 
496
/* Sets the value of the caret for the result string, counted as an
497
   offet from the end of the result string.  */
498
 
499
static void
500
result_set_caret (dm, position)
501
     demangling_t dm;
502
     int position;
503
{
504
  ((string_list_t) result_string (dm))->caret_position = position;
505
}
506
 
507
/* Shifts the position of the next addition to the result by
508
   POSITION_OFFSET.  A negative value shifts the caret to the left.  */
509
 
510
static void
511
result_shift_caret (dm, position_offset)
512
     demangling_t dm;
513
     int position_offset;
514
{
515
  ((string_list_t) result_string (dm))->caret_position += position_offset;
516
}
517
 
518
/* Returns non-zero if the character that comes right before the place
519
   where text will be added to the result is a space.  In this case,
520
   the caller should supress adding another space.  */
521
 
522
static int
523
result_previous_char_is_space (dm)
524
     demangling_t dm;
525
{
526
  char *result = dyn_string_buf (result_string (dm));
527
  int pos = result_caret_pos (dm);
528
  return pos > 0 && result[pos - 1] == ' ';
529
}
530
 
531
/* Returns the start position of a fragment of the demangled result
532
   that will be a substitution candidate.  Should be called at the
533
   start of productions that can add substitutions.  */
534
 
535
static int
536
substitution_start (dm)
537
     demangling_t dm;
538
{
539
  return result_caret_pos (dm);
540
}
541
 
542
/* Adds the suffix of the current demangled result of DM starting at
543
   START_POSITION as a potential substitution.  If TEMPLATE_P is
544
   non-zero, this potential substitution is a template-id.  */
545
 
546
static status_t
547
substitution_add (dm, start_position, template_p)
548
     demangling_t dm;
549
     int start_position;
550
     int template_p;
551
{
552
  dyn_string_t result = result_string (dm);
553
  dyn_string_t substitution = dyn_string_new (0);
554
  int i;
555
 
556
  if (substitution == NULL)
557
    return STATUS_ALLOCATION_FAILED;
558
 
559
  /* Extract the substring of the current demangling result that
560
     represents the subsitution candidate.  */
561
  if (!dyn_string_substring (substitution,
562
                             result, start_position, result_caret_pos (dm)))
563
    {
564
      dyn_string_delete (substitution);
565
      return STATUS_ALLOCATION_FAILED;
566
    }
567
 
568
  /* If there's no room for the new entry, grow the array.  */
569
  if (dm->substitutions_allocated == dm->num_substitutions)
570
    {
571
      size_t new_array_size;
572
      if (dm->substitutions_allocated > 0)
573
        dm->substitutions_allocated *= 2;
574
      else
575
        dm->substitutions_allocated = 2;
576
      new_array_size =
577
        sizeof (struct substitution_def) * dm->substitutions_allocated;
578
 
579
      dm->substitutions = (struct substitution_def *)
580
        realloc (dm->substitutions, new_array_size);
581
      if (dm->substitutions == NULL)
582
        /* Realloc failed.  */
583
        {
584
          dyn_string_delete (substitution);
585
          return STATUS_ALLOCATION_FAILED;
586
        }
587
    }
588
 
589
  /* Add the substitution to the array.  */
590
  i = dm->num_substitutions++;
591
  dm->substitutions[i].text = substitution;
592
  dm->substitutions[i].template_p = template_p;
593
 
594
#ifdef CP_DEMANGLE_DEBUG
595
  substitutions_print (dm, stderr);
596
#endif
597
 
598
  return STATUS_OK;
599
}
600
 
601
/* Returns the Nth-most-recent substitution.  Sets *TEMPLATE_P to
602
   non-zero if the substitution is a template-id, zero otherwise.
603
   N is numbered from zero.  DM retains ownership of the returned
604
   string.  If N is negative, or equal to or greater than the current
605
   number of substitution candidates, returns NULL.  */
606
 
607
static dyn_string_t
608
substitution_get (dm, n, template_p)
609
     demangling_t dm;
610
     int n;
611
     int *template_p;
612
{
613
  struct substitution_def *sub;
614
 
615
  /* Make sure N is in the valid range.  */
616
  if (n < 0 || n >= dm->num_substitutions)
617
    return NULL;
618
 
619
  sub = &(dm->substitutions[n]);
620
  *template_p = sub->template_p;
621
  return sub->text;
622
}
623
 
624
#ifdef CP_DEMANGLE_DEBUG
625
/* Debugging routine to print the current substitutions to FP.  */
626
 
627
static void
628
substitutions_print (dm, fp)
629
     demangling_t dm;
630
     FILE *fp;
631
{
632
  int seq_id;
633
  int num = dm->num_substitutions;
634
 
635
  fprintf (fp, "SUBSTITUTIONS:\n");
636
  for (seq_id = -1; seq_id < num - 1; ++seq_id)
637
    {
638
      int template_p;
639
      dyn_string_t text = substitution_get (dm, seq_id + 1, &template_p);
640
 
641
      if (seq_id == -1)
642
        fprintf (fp, " S_ ");
643
      else
644
        fprintf (fp, " S%d_", seq_id);
645
      fprintf (fp, " %c: %s\n", template_p ? '*' : ' ', dyn_string_buf (text));
646
    }
647
}
648
 
649
#endif /* CP_DEMANGLE_DEBUG */
650
 
651
/* Creates a new template argument list.  Returns NULL if allocation
652
   fails.  */
653
 
654
static template_arg_list_t
655
template_arg_list_new ()
656
{
657
  template_arg_list_t new_list =
658
    (template_arg_list_t) malloc (sizeof (struct template_arg_list_def));
659
  if (new_list == NULL)
660
    return NULL;
661
  /* Initialize the new list to have no arguments.  */
662
  new_list->first_argument = NULL;
663
  new_list->last_argument = NULL;
664
  /* Return the new list.  */
665
  return new_list;
666
}
667
 
668
/* Deletes a template argument list and the template arguments it
669
   contains.  */
670
 
671
static void
672
template_arg_list_delete (list)
673
     template_arg_list_t list;
674
{
675
  /* If there are any arguments on LIST, delete them.  */
676
  if (list->first_argument != NULL)
677
    string_list_delete (list->first_argument);
678
  /* Delete LIST.  */
679
  free (list);
680
}
681
 
682
/* Adds ARG to the template argument list ARG_LIST.  */
683
 
684
static void
685
template_arg_list_add_arg (arg_list, arg)
686
     template_arg_list_t arg_list;
687
     string_list_t arg;
688
{
689
  if (arg_list->first_argument == NULL)
690
    /* If there were no arguments before, ARG is the first one.  */
691
    arg_list->first_argument = arg;
692
  else
693
    /* Make ARG the last argument on the list.  */
694
    arg_list->last_argument->next = arg;
695
  /* Make ARG the last on the list.  */
696
  arg_list->last_argument = arg;
697
  arg->next = NULL;
698
}
699
 
700
/* Returns the template arugment at position INDEX in template
701
   argument list ARG_LIST.  */
702
 
703
static string_list_t
704
template_arg_list_get_arg (arg_list, index)
705
     template_arg_list_t arg_list;
706
     int index;
707
{
708
  string_list_t arg = arg_list->first_argument;
709
  /* Scan down the list of arguments to find the one at position
710
     INDEX.  */
711
  while (index--)
712
    {
713
      arg = arg->next;
714
      if (arg == NULL)
715
        /* Ran out of arguments before INDEX hit zero.  That's an
716
           error.  */
717
        return NULL;
718
    }
719
  /* Return the argument at position INDEX.  */
720
  return arg;
721
}
722
 
723
/* Pushes ARG_LIST onto the top of the template argument list stack.  */
724
 
725
static void
726
push_template_arg_list (dm, arg_list)
727
     demangling_t dm;
728
     template_arg_list_t arg_list;
729
{
730
  arg_list->next = dm->template_arg_lists;
731
  dm->template_arg_lists = arg_list;
732
#ifdef CP_DEMANGLE_DEBUG
733
  fprintf (stderr, " ** pushing template arg list\n");
734
  template_arg_list_print (arg_list, stderr);
735
#endif 
736
}
737
 
738
/* Pops and deletes elements on the template argument list stack until
739
   arg_list is the topmost element.  If arg_list is NULL, all elements
740
   are popped and deleted.  */
741
 
742
static void
743
pop_to_template_arg_list (dm, arg_list)
744
     demangling_t dm;
745
     template_arg_list_t arg_list;
746
{
747
  while (dm->template_arg_lists != arg_list)
748
    {
749
      template_arg_list_t top = dm->template_arg_lists;
750
      /* Disconnect the topmost element from the list.  */
751
      dm->template_arg_lists = top->next;
752
      /* Delete the popped element.  */
753
      template_arg_list_delete (top);
754
#ifdef CP_DEMANGLE_DEBUG
755
      fprintf (stderr, " ** removing template arg list\n");
756
#endif
757
    }
758
}
759
 
760
#ifdef CP_DEMANGLE_DEBUG
761
 
762
/* Prints the contents of ARG_LIST to FP.  */
763
 
764
static void
765
template_arg_list_print (arg_list, fp)
766
  template_arg_list_t arg_list;
767
  FILE *fp;
768
{
769
  string_list_t arg;
770
  int index = -1;
771
 
772
  fprintf (fp, "TEMPLATE ARGUMENT LIST:\n");
773
  for (arg = arg_list->first_argument; arg != NULL; arg = arg->next)
774
    {
775
      if (index == -1)
776
        fprintf (fp, " T_  : ");
777
      else
778
        fprintf (fp, " T%d_ : ", index);
779
      ++index;
780
      fprintf (fp, "%s\n", dyn_string_buf ((dyn_string_t) arg));
781
    }
782
}
783
 
784
#endif /* CP_DEMANGLE_DEBUG */
785
 
786
/* Returns the topmost element on the stack of template argument
787
   lists.  If there is no list of template arguments, returns NULL.  */
788
 
789
static template_arg_list_t
790
current_template_arg_list (dm)
791
     demangling_t dm;
792
{
793
  return dm->template_arg_lists;
794
}
795
 
796
/* Allocates a demangling_t object for demangling mangled NAME.  A new
797
   result must be pushed before the returned object can be used.
798
   Returns NULL if allocation fails.  */
799
 
800
static demangling_t
801
demangling_new (name, style)
802
     const char *name;
803
     int style;
804
{
805
  demangling_t dm;
806
  dm = (demangling_t) malloc (sizeof (struct demangling_def));
807
  if (dm == NULL)
808
    return NULL;
809
 
810
  dm->name = name;
811
  dm->next = name;
812
  dm->result = NULL;
813
  dm->num_substitutions = 0;
814
  dm->substitutions_allocated = 10;
815
  dm->template_arg_lists = NULL;
816
  dm->last_source_name = dyn_string_new (0);
817
  if (dm->last_source_name == NULL)
818
    return NULL;
819
  dm->substitutions = (struct substitution_def *)
820
    malloc (dm->substitutions_allocated * sizeof (struct substitution_def));
821
  if (dm->substitutions == NULL)
822
    {
823
      dyn_string_delete (dm->last_source_name);
824
      return NULL;
825
    }
826
  dm->style = style;
827
  dm->is_constructor = 0;
828
  dm->is_destructor = 0;
829
 
830
  return dm;
831
}
832
 
833
/* Deallocates a demangling_t object and all memory associated with
834
   it.  */
835
 
836
static void
837
demangling_delete (dm)
838
     demangling_t dm;
839
{
840
  int i;
841
  template_arg_list_t arg_list = dm->template_arg_lists;
842
 
843
  /* Delete the stack of template argument lists.  */
844
  while (arg_list != NULL)
845
    {
846
      template_arg_list_t next = arg_list->next;
847
      template_arg_list_delete (arg_list);
848
      arg_list = next;
849
    }
850
  /* Delete the list of substitutions.  */
851
  for (i = dm->num_substitutions; --i >= 0; )
852
    dyn_string_delete (dm->substitutions[i].text);
853
  free (dm->substitutions);
854
  /* Delete the demangled result.  */
855
  string_list_delete (dm->result);
856
  /* Delete the stored identifier name.  */
857
  dyn_string_delete (dm->last_source_name);
858
  /* Delete the context object itself.  */
859
  free (dm);
860
}
861
 
862
/* These functions demangle an alternative of the corresponding
863
   production in the mangling spec.  The first argument of each is a
864
   demangling context structure for the current demangling
865
   operation.  Most emit demangled text directly to the topmost result
866
   string on the result string stack in the demangling context
867
   structure.  */
868
 
869
static status_t demangle_char
870
  PARAMS ((demangling_t, int));
871
static status_t demangle_mangled_name
872
  PARAMS ((demangling_t));
873
static status_t demangle_encoding
874
  PARAMS ((demangling_t));
875
static status_t demangle_name
876
  PARAMS ((demangling_t, int *));
877
static status_t demangle_nested_name
878
  PARAMS ((demangling_t, int *));
879
static status_t demangle_prefix
880
  PARAMS ((demangling_t, int *));
881
static status_t demangle_unqualified_name
882
  PARAMS ((demangling_t, int *));
883
static status_t demangle_source_name
884
  PARAMS ((demangling_t));
885
static status_t demangle_number
886
  PARAMS ((demangling_t, int *, int, int));
887
static status_t demangle_number_literally
888
  PARAMS ((demangling_t, dyn_string_t, int, int));
889
static status_t demangle_identifier
890
  PARAMS ((demangling_t, int, dyn_string_t));
891
static status_t demangle_operator_name
892
  PARAMS ((demangling_t, int, int *));
893
static status_t demangle_nv_offset
894
  PARAMS ((demangling_t));
895
static status_t demangle_v_offset
896
  PARAMS ((demangling_t));
897
static status_t demangle_call_offset
898
  PARAMS ((demangling_t));
899
static status_t demangle_special_name
900
  PARAMS ((demangling_t));
901
static status_t demangle_ctor_dtor_name
902
  PARAMS ((demangling_t));
903
static status_t demangle_type_ptr
904
  PARAMS ((demangling_t, int *, int));
905
static status_t demangle_type
906
  PARAMS ((demangling_t));
907
static status_t demangle_CV_qualifiers
908
  PARAMS ((demangling_t, dyn_string_t));
909
static status_t demangle_builtin_type
910
  PARAMS ((demangling_t));
911
static status_t demangle_function_type
912
  PARAMS ((demangling_t, int *));
913
static status_t demangle_bare_function_type
914
  PARAMS ((demangling_t, int *));
915
static status_t demangle_class_enum_type
916
  PARAMS ((demangling_t, int *));
917
static status_t demangle_array_type
918
  PARAMS ((demangling_t, int *));
919
static status_t demangle_template_param
920
  PARAMS ((demangling_t));
921
static status_t demangle_template_args
922
  PARAMS ((demangling_t));
923
static status_t demangle_literal
924
  PARAMS ((demangling_t));
925
static status_t demangle_template_arg
926
  PARAMS ((demangling_t));
927
static status_t demangle_expression
928
  PARAMS ((demangling_t));
929
static status_t demangle_scope_expression
930
  PARAMS ((demangling_t));
931
static status_t demangle_expr_primary
932
  PARAMS ((demangling_t));
933
static status_t demangle_substitution
934
  PARAMS ((demangling_t, int *));
935
static status_t demangle_local_name
936
  PARAMS ((demangling_t));
937
static status_t demangle_discriminator
938
  PARAMS ((demangling_t, int));
939
static status_t cp_demangle
940
  PARAMS ((const char *, dyn_string_t, int));
941
#ifdef IN_LIBGCC2
942
static status_t cp_demangle_type
943
  PARAMS ((const char*, dyn_string_t));
944
#endif
945
 
946
/* When passed to demangle_bare_function_type, indicates that the
947
   function's return type is not encoded before its parameter types.  */
948
#define BFT_NO_RETURN_TYPE    NULL
949
 
950
/* Check that the next character is C.  If so, consume it.  If not,
951
   return an error.  */
952
 
953
static status_t
954
demangle_char (dm, c)
955
     demangling_t dm;
956
     int c;
957
{
958
  static char *error_message = NULL;
959
 
960
  if (peek_char (dm) == c)
961
    {
962
      advance_char (dm);
963
      return STATUS_OK;
964
    }
965
  else
966
    {
967
      if (error_message == NULL)
968
        error_message = strdup ("Expected ?");
969
      error_message[9] = c;
970
      return error_message;
971
    }
972
}
973
 
974
/* Demangles and emits a <mangled-name>.
975
 
976
    <mangled-name>      ::= _Z <encoding>  */
977
 
978
static status_t
979
demangle_mangled_name (dm)
980
     demangling_t dm;
981
{
982
  DEMANGLE_TRACE ("mangled-name", dm);
983
  RETURN_IF_ERROR (demangle_char (dm, '_'));
984
  RETURN_IF_ERROR (demangle_char (dm, 'Z'));
985
  RETURN_IF_ERROR (demangle_encoding (dm));
986
  return STATUS_OK;
987
}
988
 
989
/* Demangles and emits an <encoding>.
990
 
991
    <encoding>          ::= <function name> <bare-function-type>
992
                        ::= <data name>
993
                        ::= <special-name>  */
994
 
995
static status_t
996
demangle_encoding (dm)
997
     demangling_t dm;
998
{
999
  int encode_return_type;
1000
  int start_position;
1001
  template_arg_list_t old_arg_list = current_template_arg_list (dm);
1002
  char peek = peek_char (dm);
1003
 
1004
  DEMANGLE_TRACE ("encoding", dm);
1005
 
1006
  /* Remember where the name starts.  If it turns out to be a template
1007
     function, we'll have to insert the return type here.  */
1008
  start_position = result_caret_pos (dm);
1009
 
1010
  if (peek == 'G' || peek == 'T')
1011
    RETURN_IF_ERROR (demangle_special_name (dm));
1012
  else
1013
    {
1014
      /* Now demangle the name.  */
1015
      RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
1016
 
1017
      /* If there's anything left, the name was a function name, with
1018
         maybe its return type, and its parameter types, following.  */
1019
      if (!end_of_name_p (dm)
1020
          && peek_char (dm) != 'E')
1021
        {
1022
          if (encode_return_type)
1023
            /* Template functions have their return type encoded.  The
1024
               return type should be inserted at start_position.  */
1025
            RETURN_IF_ERROR
1026
              (demangle_bare_function_type (dm, &start_position));
1027
          else
1028
            /* Non-template functions don't have their return type
1029
               encoded.  */
1030
            RETURN_IF_ERROR
1031
              (demangle_bare_function_type (dm, BFT_NO_RETURN_TYPE));
1032
        }
1033
    }
1034
 
1035
  /* Pop off template argument lists that were built during the
1036
     mangling of this name, to restore the old template context.  */
1037
  pop_to_template_arg_list (dm, old_arg_list);
1038
 
1039
  return STATUS_OK;
1040
}
1041
 
1042
/* Demangles and emits a <name>.
1043
 
1044
    <name>              ::= <unscoped-name>
1045
                        ::= <unscoped-template-name> <template-args>
1046
                        ::= <nested-name>
1047
                        ::= <local-name>
1048
 
1049
    <unscoped-name>     ::= <unqualified-name>
1050
                        ::= St <unqualified-name>   # ::std::
1051
 
1052
    <unscoped-template-name>
1053
                        ::= <unscoped-name>
1054
                        ::= <substitution>  */
1055
 
1056
static status_t
1057
demangle_name (dm, encode_return_type)
1058
     demangling_t dm;
1059
     int *encode_return_type;
1060
{
1061
  int start = substitution_start (dm);
1062
  char peek = peek_char (dm);
1063
  int is_std_substitution = 0;
1064
 
1065
  /* Generally, the return type is encoded if the function is a
1066
     template-id, and suppressed otherwise.  There are a few cases,
1067
     though, in which the return type is not encoded even for a
1068
     templated function.  In these cases, this flag is set.  */
1069
  int suppress_return_type = 0;
1070
 
1071
  DEMANGLE_TRACE ("name", dm);
1072
 
1073
  switch (peek)
1074
    {
1075
    case 'N':
1076
      /* This is a <nested-name>.  */
1077
      RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
1078
      break;
1079
 
1080
    case 'Z':
1081
      RETURN_IF_ERROR (demangle_local_name (dm));
1082
      *encode_return_type = 0;
1083
      break;
1084
 
1085
    case 'S':
1086
      /* The `St' substitution allows a name nested in std:: to appear
1087
         without being enclosed in a nested name.  */
1088
      if (peek_char_next (dm) == 't')
1089
        {
1090
          (void) next_char (dm);
1091
          (void) next_char (dm);
1092
          RETURN_IF_ERROR (result_add (dm, "std::"));
1093
          RETURN_IF_ERROR
1094
            (demangle_unqualified_name (dm, &suppress_return_type));
1095
          is_std_substitution = 1;
1096
        }
1097
      else
1098
        RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1099
      /* Check if a template argument list immediately follows.
1100
         If so, then we just demangled an <unqualified-template-name>.  */
1101
      if (peek_char (dm) == 'I')
1102
        {
1103
          /* A template name of the form std::<unqualified-name> is a
1104
             substitution candidate.  */
1105
          if (is_std_substitution)
1106
            RETURN_IF_ERROR (substitution_add (dm, start, 0));
1107
          /* Demangle the <template-args> here.  */
1108
          RETURN_IF_ERROR (demangle_template_args (dm));
1109
          *encode_return_type = !suppress_return_type;
1110
        }
1111
      else
1112
        *encode_return_type = 0;
1113
 
1114
      break;
1115
 
1116
    default:
1117
      /* This is an <unscoped-name> or <unscoped-template-name>.  */
1118
      RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
1119
 
1120
      /* If the <unqualified-name> is followed by template args, this
1121
         is an <unscoped-template-name>.  */
1122
      if (peek_char (dm) == 'I')
1123
        {
1124
          /* Add a substitution for the unqualified template name.  */
1125
          RETURN_IF_ERROR (substitution_add (dm, start, 0));
1126
 
1127
          RETURN_IF_ERROR (demangle_template_args (dm));
1128
          *encode_return_type = !suppress_return_type;
1129
        }
1130
      else
1131
        *encode_return_type = 0;
1132
 
1133
      break;
1134
    }
1135
 
1136
  return STATUS_OK;
1137
}
1138
 
1139
/* Demangles and emits a <nested-name>.
1140
 
1141
    <nested-name>     ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E  */
1142
 
1143
static status_t
1144
demangle_nested_name (dm, encode_return_type)
1145
     demangling_t dm;
1146
     int *encode_return_type;
1147
{
1148
  char peek;
1149
 
1150
  DEMANGLE_TRACE ("nested-name", dm);
1151
 
1152
  RETURN_IF_ERROR (demangle_char (dm, 'N'));
1153
 
1154
  peek = peek_char (dm);
1155
  if (peek == 'r' || peek == 'V' || peek == 'K')
1156
    {
1157
      dyn_string_t cv_qualifiers;
1158
      status_t status;
1159
 
1160
      /* Snarf up CV qualifiers.  */
1161
      cv_qualifiers = dyn_string_new (24);
1162
      if (cv_qualifiers == NULL)
1163
        return STATUS_ALLOCATION_FAILED;
1164
      demangle_CV_qualifiers (dm, cv_qualifiers);
1165
 
1166
      /* Emit them, preceded by a space.  */
1167
      status = result_add_char (dm, ' ');
1168
      if (STATUS_NO_ERROR (status))
1169
        status = result_add_string (dm, cv_qualifiers);
1170
      /* The CV qualifiers that occur in a <nested-name> will be
1171
         qualifiers for member functions.  These are placed at the end
1172
         of the function.  Therefore, shift the caret to the left by
1173
         the length of the qualifiers, so other text is inserted
1174
         before them and they stay at the end.  */
1175
      result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);
1176
      /* Clean up.  */
1177
      dyn_string_delete (cv_qualifiers);
1178
      RETURN_IF_ERROR (status);
1179
    }
1180
 
1181
  RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
1182
  /* No need to demangle the final <unqualified-name>; demangle_prefix
1183
     will handle it.  */
1184
  RETURN_IF_ERROR (demangle_char (dm, 'E'));
1185
 
1186
  return STATUS_OK;
1187
}
1188
 
1189
/* Demangles and emits a <prefix>.
1190
 
1191
    <prefix>            ::= <prefix> <unqualified-name>
1192
                        ::= <template-prefix> <template-args>
1193
                        ::= # empty
1194
                        ::= <substitution>
1195
 
1196
    <template-prefix>   ::= <prefix>
1197
                        ::= <substitution>  */
1198
 
1199
static status_t
1200
demangle_prefix (dm, encode_return_type)
1201
     demangling_t dm;
1202
     int *encode_return_type;
1203
{
1204
  int start = substitution_start (dm);
1205
  int nested = 0;
1206
 
1207
  /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
1208
     After <template-args>, it is set to non-zero; after everything
1209
     else it is set to zero.  */
1210
 
1211
  /* Generally, the return type is encoded if the function is a
1212
     template-id, and suppressed otherwise.  There are a few cases,
1213
     though, in which the return type is not encoded even for a
1214
     templated function.  In these cases, this flag is set.  */
1215
  int suppress_return_type = 0;
1216
 
1217
  DEMANGLE_TRACE ("prefix", dm);
1218
 
1219
  while (1)
1220
    {
1221
      char peek;
1222
 
1223
      if (end_of_name_p (dm))
1224
        return "Unexpected end of name in <compound-name>.";
1225
 
1226
      peek = peek_char (dm);
1227
 
1228
      /* We'll initialize suppress_return_type to false, and set it to true
1229
         if we end up demangling a constructor name.  However, make
1230
         sure we're not actually about to demangle template arguments
1231
         -- if so, this is the <template-args> following a
1232
         <template-prefix>, so we'll want the previous flag value
1233
         around.  */
1234
      if (peek != 'I')
1235
        suppress_return_type = 0;
1236
 
1237
      if (IS_DIGIT ((unsigned char) peek)
1238
          || (peek >= 'a' && peek <= 'z')
1239
          || peek == 'C' || peek == 'D'
1240
          || peek == 'S')
1241
        {
1242
          /* We have another level of scope qualification.  */
1243
          if (nested)
1244
            RETURN_IF_ERROR (result_add (dm, NAMESPACE_SEPARATOR));
1245
          else
1246
            nested = 1;
1247
 
1248
          if (peek == 'S')
1249
            /* The substitution determines whether this is a
1250
               template-id.  */
1251
            RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
1252
          else
1253
            {
1254
              /* It's just a name.  */
1255
              RETURN_IF_ERROR
1256
                (demangle_unqualified_name (dm, &suppress_return_type));
1257
              *encode_return_type = 0;
1258
            }
1259
        }
1260
      else if (peek == 'Z')
1261
        RETURN_IF_ERROR (demangle_local_name (dm));
1262
      else if (peek == 'I')
1263
        {
1264
          RETURN_IF_ERROR (demangle_template_args (dm));
1265
 
1266
          /* Now we want to indicate to the caller that we've
1267
             demangled template arguments, thus the prefix was a
1268
             <template-prefix>.  That's so that the caller knows to
1269
             demangle the function's return type, if this turns out to
1270
             be a function name.  But, if it's a member template
1271
             constructor or a templated conversion operator, report it
1272
             as untemplated.  Those never get encoded return types.  */
1273
          *encode_return_type = !suppress_return_type;
1274
        }
1275
      else if (peek == 'E')
1276
        /* All done.  */
1277
        return STATUS_OK;
1278
      else
1279
        return "Unexpected character in <compound-name>.";
1280
 
1281
      if (peek != 'S'
1282
          && peek_char (dm) != 'E')
1283
        /* Add a new substitution for the prefix thus far.  */
1284
        RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
1285
    }
1286
}
1287
 
1288
/* Demangles and emits an <unqualified-name>.  If this
1289
   <unqualified-name> is for a special function type that should never
1290
   have its return type encoded (particularly, a constructor or
1291
   conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
1292
   it is set to zero.
1293
 
1294
    <unqualified-name>  ::= <operator-name>
1295
                        ::= <special-name>
1296
                        ::= <source-name>  */
1297
 
1298
static status_t
1299
demangle_unqualified_name (dm, suppress_return_type)
1300
     demangling_t dm;
1301
     int *suppress_return_type;
1302
{
1303
  char peek = peek_char (dm);
1304
 
1305
  DEMANGLE_TRACE ("unqualified-name", dm);
1306
 
1307
  /* By default, don't force suppression of the return type (though
1308
     non-template functions still don't get a return type encoded).  */
1309
  *suppress_return_type = 0;
1310
 
1311
  if (IS_DIGIT ((unsigned char) peek))
1312
    RETURN_IF_ERROR (demangle_source_name (dm));
1313
  else if (peek >= 'a' && peek <= 'z')
1314
    {
1315
      int num_args;
1316
 
1317
      /* Conversion operators never have a return type encoded.  */
1318
      if (peek == 'c' && peek_char_next (dm) == 'v')
1319
        *suppress_return_type = 1;
1320
 
1321
      RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
1322
    }
1323
  else if (peek == 'C' || peek == 'D')
1324
    {
1325
      /* Constructors never have a return type encoded.  */
1326
      if (peek == 'C')
1327
        *suppress_return_type = 1;
1328
 
1329
      RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
1330
    }
1331
  else
1332
    return "Unexpected character in <unqualified-name>.";
1333
 
1334
  return STATUS_OK;
1335
}
1336
 
1337
/* Demangles and emits <source-name>.
1338
 
1339
    <source-name> ::= <length number> <identifier>  */
1340
 
1341
static status_t
1342
demangle_source_name (dm)
1343
     demangling_t dm;
1344
{
1345
  int length;
1346
 
1347
  DEMANGLE_TRACE ("source-name", dm);
1348
 
1349
  /* Decode the length of the identifier.  */
1350
  RETURN_IF_ERROR (demangle_number (dm, &length, 10, 0));
1351
  if (length == 0)
1352
    return "Zero length in <source-name>.";
1353
 
1354
  /* Now the identifier itself.  It's placed into last_source_name,
1355
     where it can be used to build a constructor or destructor name.  */
1356
  RETURN_IF_ERROR (demangle_identifier (dm, length,
1357
                                        dm->last_source_name));
1358
 
1359
  /* Emit it.  */
1360
  RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
1361
 
1362
  return STATUS_OK;
1363
}
1364
 
1365
/* Demangles a number, either a <number> or a <positive-number> at the
1366
   current position, consuming all consecutive digit characters.  Sets
1367
   *VALUE to the resulting numberand returns STATUS_OK.  The number is
1368
   interpreted as BASE, which must be either 10 or 36.  If IS_SIGNED
1369
   is non-zero, negative numbers -- prefixed with `n' -- are accepted.
1370
 
1371
    <number> ::= [n] <positive-number>
1372
 
1373
    <positive-number> ::= <decimal integer>  */
1374
 
1375
static status_t
1376
demangle_number (dm, value, base, is_signed)
1377
     demangling_t dm;
1378
     int *value;
1379
     int base;
1380
     int is_signed;
1381
{
1382
  dyn_string_t number = dyn_string_new (10);
1383
 
1384
  DEMANGLE_TRACE ("number", dm);
1385
 
1386
  if (number == NULL)
1387
    return STATUS_ALLOCATION_FAILED;
1388
 
1389
  demangle_number_literally (dm, number, base, is_signed);
1390
  *value = strtol (dyn_string_buf (number), NULL, base);
1391
  dyn_string_delete (number);
1392
 
1393
  return STATUS_OK;
1394
}
1395
 
1396
/* Demangles a number at the current position.  The digits (and minus
1397
   sign, if present) that make up the number are appended to STR.
1398
   Only base-BASE digits are accepted; BASE must be either 10 or 36.
1399
   If IS_SIGNED, negative numbers -- prefixed with `n' -- are
1400
   accepted.  Does not consume a trailing underscore or other
1401
   terminating character.  */
1402
 
1403
static status_t
1404
demangle_number_literally (dm, str, base, is_signed)
1405
     demangling_t dm;
1406
     dyn_string_t str;
1407
     int base;
1408
     int is_signed;
1409
{
1410
  DEMANGLE_TRACE ("number*", dm);
1411
 
1412
  if (base != 10 && base != 36)
1413
    return STATUS_INTERNAL_ERROR;
1414
 
1415
  /* An `n' denotes a negative number.  */
1416
  if (is_signed && peek_char (dm) == 'n')
1417
    {
1418
      /* Skip past the n.  */
1419
      advance_char (dm);
1420
      /* The normal way to write a negative number is with a minus
1421
         sign.  */
1422
      if (!dyn_string_append_char (str, '-'))
1423
        return STATUS_ALLOCATION_FAILED;
1424
    }
1425
 
1426
  /* Loop until we hit a non-digit.  */
1427
  while (1)
1428
    {
1429
      char peek = peek_char (dm);
1430
      if (IS_DIGIT ((unsigned char) peek)
1431
          || (base == 36 && peek >= 'A' && peek <= 'Z'))
1432
        {
1433
          /* Accumulate digits.  */
1434
          if (!dyn_string_append_char (str, next_char (dm)))
1435
            return STATUS_ALLOCATION_FAILED;
1436
        }
1437
      else
1438
        /* Not a digit?  All done.  */
1439
        break;
1440
    }
1441
 
1442
  return STATUS_OK;
1443
}
1444
 
1445
/* Demangles an identifier at the current position of LENGTH
1446
   characters and places it in IDENTIFIER.  */
1447
 
1448
static status_t
1449
demangle_identifier (dm, length, identifier)
1450
     demangling_t dm;
1451
     int length;
1452
     dyn_string_t identifier;
1453
{
1454
  DEMANGLE_TRACE ("identifier", dm);
1455
 
1456
  dyn_string_clear (identifier);
1457
  if (!dyn_string_resize (identifier, length))
1458
    return STATUS_ALLOCATION_FAILED;
1459
 
1460
  while (length-- > 0)
1461
    {
1462
      if (end_of_name_p (dm))
1463
        return "Unexpected end of name in <identifier>.";
1464
      if (!dyn_string_append_char (identifier, next_char (dm)))
1465
        return STATUS_ALLOCATION_FAILED;
1466
    }
1467
 
1468
  /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
1469
     followed by the source file name and some random characters.
1470
     Unless we're in strict mode, decipher these names appropriately.  */
1471
  if (!flag_strict)
1472
    {
1473
      char *name = dyn_string_buf (identifier);
1474
      int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
1475
 
1476
      /* Compare the first, fixed part.  */
1477
      if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
1478
        {
1479
          name += prefix_length;
1480
          /* The next character might be a period, an underscore, or
1481
             dollar sign, depending on the target architecture's
1482
             assembler's capabilities.  After that comes an `N'.  */
1483
          if ((*name == '.' || *name == '_' || *name == '$')
1484
              && *(name + 1) == 'N')
1485
            /* This looks like the anonymous namespace identifier.
1486
               Replace it with something comprehensible.  */
1487
            dyn_string_copy_cstr (identifier, "(anonymous namespace)");
1488
        }
1489
    }
1490
 
1491
  return STATUS_OK;
1492
}
1493
 
1494
/* Demangles and emits an <operator-name>.  If SHORT_NAME is non-zero,
1495
   the short form is emitted; otherwise the full source form
1496
   (`operator +' etc.) is emitted.  *NUM_ARGS is set to the number of
1497
   operands that the operator takes.
1498
 
1499
    <operator-name>
1500
                  ::= nw        # new
1501
                  ::= na        # new[]
1502
                  ::= dl        # delete
1503
                  ::= da        # delete[]
1504
                  ::= ps        # + (unary)
1505
                  ::= ng        # - (unary)
1506
                  ::= ad        # & (unary)
1507
                  ::= de        # * (unary)
1508
                  ::= co        # ~
1509
                  ::= pl        # +
1510
                  ::= mi        # -
1511
                  ::= ml        # *
1512
                  ::= dv        # /
1513
                  ::= rm        # %
1514
                  ::= an        # &
1515
                  ::= or        # |
1516
                  ::= eo        # ^
1517
                  ::= aS        # =
1518
                  ::= pL        # +=
1519
                  ::= mI        # -=
1520
                  ::= mL        # *=
1521
                  ::= dV        # /=
1522
                  ::= rM        # %=
1523
                  ::= aN        # &=
1524
                  ::= oR        # |=
1525
                  ::= eO        # ^=
1526
                  ::= ls        # <<
1527
                  ::= rs        # >>
1528
                  ::= lS        # <<=
1529
                  ::= rS        # >>=
1530
                  ::= eq        # ==
1531
                  ::= ne        # !=
1532
                  ::= lt        # <
1533
                  ::= gt        # >
1534
                  ::= le        # <=
1535
                  ::= ge        # >=
1536
                  ::= nt        # !
1537
                  ::= aa        # &&
1538
                  ::= oo        # ||
1539
                  ::= pp        # ++
1540
                  ::= mm        # --
1541
                  ::= cm        # ,
1542
                  ::= pm        # ->*
1543
                  ::= pt        # ->
1544
                  ::= cl        # ()
1545
                  ::= ix        # []
1546
                  ::= qu        # ?
1547
                  ::= sz        # sizeof
1548
                  ::= cv <type> # cast
1549
                  ::= v [0-9] <source-name>  # vendor extended operator  */
1550
 
1551
static status_t
1552
demangle_operator_name (dm, short_name, num_args)
1553
     demangling_t dm;
1554
     int short_name;
1555
     int *num_args;
1556
{
1557
  struct operator_code
1558
  {
1559
    /* The mangled code for this operator.  */
1560
    const char *code;
1561
    /* The source name of this operator.  */
1562
    const char *name;
1563
    /* The number of arguments this operator takes.  */
1564
    int num_args;
1565
  };
1566
 
1567
  static const struct operator_code operators[] =
1568
  {
1569
    { "aN", "&="       , 2 },
1570
    { "aS", "="        , 2 },
1571
    { "aa", "&&"       , 2 },
1572
    { "ad", "&"        , 1 },
1573
    { "an", "&"        , 2 },
1574
    { "cl", "()"       , 0 },
1575
    { "cm", ","        , 2 },
1576
    { "co", "~"        , 1 },
1577
    { "dV", "/="       , 2 },
1578
    { "da", " delete[]", 1 },
1579
    { "de", "*"        , 1 },
1580
    { "dl", " delete"  , 1 },
1581
    { "dv", "/"        , 2 },
1582
    { "eO", "^="       , 2 },
1583
    { "eo", "^"        , 2 },
1584
    { "eq", "=="       , 2 },
1585
    { "ge", ">="       , 2 },
1586
    { "gt", ">"        , 2 },
1587
    { "ix", "[]"       , 2 },
1588
    { "lS", "<<="      , 2 },
1589
    { "le", "<="       , 2 },
1590
    { "ls", "<<"       , 2 },
1591
    { "lt", "<"        , 2 },
1592
    { "mI", "-="       , 2 },
1593
    { "mL", "*="       , 2 },
1594
    { "mi", "-"        , 2 },
1595
    { "ml", "*"        , 2 },
1596
    { "mm", "--"       , 1 },
1597
    { "na", " new[]"   , 1 },
1598
    { "ne", "!="       , 2 },
1599
    { "ng", "-"        , 1 },
1600
    { "nt", "!"        , 1 },
1601
    { "nw", " new"     , 1 },
1602
    { "oR", "|="       , 2 },
1603
    { "oo", "||"       , 2 },
1604
    { "or", "|"        , 2 },
1605
    { "pL", "+="       , 2 },
1606
    { "pl", "+"        , 2 },
1607
    { "pm", "->*"      , 2 },
1608
    { "pp", "++"       , 1 },
1609
    { "ps", "+"        , 1 },
1610
    { "pt", "->"       , 2 },
1611
    { "qu", "?"        , 3 },
1612
    { "rM", "%="       , 2 },
1613
    { "rS", ">>="      , 2 },
1614
    { "rm", "%"        , 2 },
1615
    { "rs", ">>"       , 2 },
1616
    { "sz", " sizeof"  , 1 }
1617
  };
1618
 
1619
  const int num_operators =
1620
    sizeof (operators) / sizeof (struct operator_code);
1621
 
1622
  int c0 = next_char (dm);
1623
  int c1 = next_char (dm);
1624
  const struct operator_code* p1 = operators;
1625
  const struct operator_code* p2 = operators + num_operators;
1626
 
1627
  DEMANGLE_TRACE ("operator-name", dm);
1628
 
1629
  /* Is this a vendor-extended operator?  */
1630
  if (c0 == 'v' && IS_DIGIT (c1))
1631
    {
1632
      RETURN_IF_ERROR (result_add (dm, "operator "));
1633
      RETURN_IF_ERROR (demangle_source_name (dm));
1634
      *num_args = 0;
1635
      return STATUS_OK;
1636
    }
1637
 
1638
  /* Is this a conversion operator?  */
1639
  if (c0 == 'c' && c1 == 'v')
1640
    {
1641
      RETURN_IF_ERROR (result_add (dm, "operator "));
1642
      /* Demangle the converted-to type.  */
1643
      RETURN_IF_ERROR (demangle_type (dm));
1644
      *num_args = 0;
1645
      return STATUS_OK;
1646
    }
1647
 
1648
  /* Perform a binary search for the operator code.  */
1649
  while (1)
1650
    {
1651
      const struct operator_code* p = p1 + (p2 - p1) / 2;
1652
      char match0 = p->code[0];
1653
      char match1 = p->code[1];
1654
 
1655
      if (c0 == match0 && c1 == match1)
1656
        /* Found it.  */
1657
        {
1658
          if (!short_name)
1659
            RETURN_IF_ERROR (result_add (dm, "operator"));
1660
          RETURN_IF_ERROR (result_add (dm, p->name));
1661
          *num_args = p->num_args;
1662
 
1663
          return STATUS_OK;
1664
        }
1665
 
1666
      if (p == p1)
1667
        /* Couldn't find it.  */
1668
        return "Unknown code in <operator-name>.";
1669
 
1670
      /* Try again.  */
1671
      if (c0 < match0 || (c0 == match0 && c1 < match1))
1672
        p2 = p;
1673
      else
1674
        p1 = p;
1675
    }
1676
}
1677
 
1678
/* Demangles and omits an <nv-offset>.
1679
 
1680
    <nv-offset> ::= <offset number>   # non-virtual base override  */
1681
 
1682
static status_t
1683
demangle_nv_offset (dm)
1684
     demangling_t dm;
1685
{
1686
  dyn_string_t number;
1687
  status_t status = STATUS_OK;
1688
 
1689
  DEMANGLE_TRACE ("h-offset", dm);
1690
 
1691
  /* Demangle the offset.  */
1692
  number = dyn_string_new (4);
1693
  if (number == NULL)
1694
    return STATUS_ALLOCATION_FAILED;
1695
  demangle_number_literally (dm, number, 10, 1);
1696
 
1697
  /* Don't display the offset unless in verbose mode.  */
1698
  if (flag_verbose)
1699
    {
1700
      status = result_add (dm, " [nv:");
1701
      if (STATUS_NO_ERROR (status))
1702
        status = result_add_string (dm, number);
1703
      if (STATUS_NO_ERROR (status))
1704
        status = result_add_char (dm, ']');
1705
    }
1706
 
1707
  /* Clean up.  */
1708
  dyn_string_delete (number);
1709
  RETURN_IF_ERROR (status);
1710
  return STATUS_OK;
1711
}
1712
 
1713
/* Demangles and emits a <v-offset>.
1714
 
1715
    <v-offset>  ::= <offset number> _ <virtual offset number>
1716
                        # virtual base override, with vcall offset  */
1717
 
1718
static status_t
1719
demangle_v_offset (dm)
1720
     demangling_t dm;
1721
{
1722
  dyn_string_t number;
1723
  status_t status = STATUS_OK;
1724
 
1725
  DEMANGLE_TRACE ("v-offset", dm);
1726
 
1727
  /* Demangle the offset.  */
1728
  number = dyn_string_new (4);
1729
  if (number == NULL)
1730
    return STATUS_ALLOCATION_FAILED;
1731
  demangle_number_literally (dm, number, 10, 1);
1732
 
1733
  /* Don't display the offset unless in verbose mode.  */
1734
  if (flag_verbose)
1735
    {
1736
      status = result_add (dm, " [v:");
1737
      if (STATUS_NO_ERROR (status))
1738
        status = result_add_string (dm, number);
1739
      if (STATUS_NO_ERROR (status))
1740
        result_add_char (dm, ',');
1741
    }
1742
  dyn_string_delete (number);
1743
  RETURN_IF_ERROR (status);
1744
 
1745
  /* Demangle the separator.  */
1746
  RETURN_IF_ERROR (demangle_char (dm, '_'));
1747
 
1748
  /* Demangle the vcall offset.  */
1749
  number = dyn_string_new (4);
1750
  if (number == NULL)
1751
    return STATUS_ALLOCATION_FAILED;
1752
  demangle_number_literally (dm, number, 10, 1);
1753
 
1754
  /* Don't display the vcall offset unless in verbose mode.  */
1755
  if (flag_verbose)
1756
    {
1757
      status = result_add_string (dm, number);
1758
      if (STATUS_NO_ERROR (status))
1759
        status = result_add_char (dm, ']');
1760
    }
1761
  dyn_string_delete (number);
1762
  RETURN_IF_ERROR (status);
1763
 
1764
  return STATUS_OK;
1765
}
1766
 
1767
/* Demangles and emits a <call-offset>.
1768
 
1769
    <call-offset> ::= h <nv-offset> _
1770
                  ::= v <v-offset> _  */
1771
 
1772
static status_t
1773
demangle_call_offset (dm)
1774
     demangling_t dm;
1775
{
1776
  DEMANGLE_TRACE ("call-offset", dm);
1777
 
1778
  switch (peek_char (dm))
1779
    {
1780
    case 'h':
1781
      advance_char (dm);
1782
      /* Demangle the offset.  */
1783
      RETURN_IF_ERROR (demangle_nv_offset (dm));
1784
      /* Demangle the separator.  */
1785
      RETURN_IF_ERROR (demangle_char (dm, '_'));
1786
      break;
1787
 
1788
    case 'v':
1789
      advance_char (dm);
1790
      /* Demangle the offset.  */
1791
      RETURN_IF_ERROR (demangle_v_offset (dm));
1792
      /* Demangle the separator.  */
1793
      RETURN_IF_ERROR (demangle_char (dm, '_'));
1794
      break;
1795
 
1796
    default:
1797
      return "Unrecognized <call-offset>.";
1798
    }
1799
 
1800
  return STATUS_OK;
1801
}
1802
 
1803
/* Demangles and emits a <special-name>.
1804
 
1805
    <special-name> ::= GV <object name>   # Guard variable
1806
                   ::= TV <type>          # virtual table
1807
                   ::= TT <type>          # VTT
1808
                   ::= TI <type>          # typeinfo structure
1809
                   ::= TS <type>          # typeinfo name
1810
 
1811
   Other relevant productions include thunks:
1812
 
1813
    <special-name> ::= T <call-offset> <base encoding>
1814
                         # base is the nominal target function of thunk
1815
 
1816
    <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
1817
                         # base is the nominal target function of thunk
1818
                         # first call-offset is 'this' adjustment
1819
                         # second call-offset is result adjustment
1820
 
1821
   where
1822
 
1823
    <call-offset>  ::= h <nv-offset> _
1824
                   ::= v <v-offset> _
1825
 
1826
   Also demangles the special g++ manglings,
1827
 
1828
    <special-name> ::= TC <type> <offset number> _ <base type>
1829
                                          # construction vtable
1830
                   ::= TF <type>          # typeinfo function (old ABI only)
1831
                   ::= TJ <type>          # java Class structure  */
1832
 
1833
static status_t
1834
demangle_special_name (dm)
1835
     demangling_t dm;
1836
{
1837
  dyn_string_t number;
1838
  int unused;
1839
  char peek = peek_char (dm);
1840
 
1841
  DEMANGLE_TRACE ("special-name", dm);
1842
 
1843
  if (peek == 'G')
1844
    {
1845
      /* A guard variable name.  Consume the G.  */
1846
      advance_char (dm);
1847
      RETURN_IF_ERROR (demangle_char (dm, 'V'));
1848
      RETURN_IF_ERROR (result_add (dm, "guard variable for "));
1849
      RETURN_IF_ERROR (demangle_name (dm, &unused));
1850
    }
1851
  else if (peek == 'T')
1852
    {
1853
      status_t status = STATUS_OK;
1854
 
1855
      /* Other C++ implementation miscellania.  Consume the T.  */
1856
      advance_char (dm);
1857
 
1858
      switch (peek_char (dm))
1859
        {
1860
        case 'V':
1861
          /* Virtual table.  */
1862
          advance_char (dm);
1863
          RETURN_IF_ERROR (result_add (dm, "vtable for "));
1864
          RETURN_IF_ERROR (demangle_type (dm));
1865
          break;
1866
 
1867
        case 'T':
1868
          /* VTT structure.  */
1869
          advance_char (dm);
1870
          RETURN_IF_ERROR (result_add (dm, "VTT for "));
1871
          RETURN_IF_ERROR (demangle_type (dm));
1872
          break;
1873
 
1874
        case 'I':
1875
          /* Typeinfo structure.  */
1876
          advance_char (dm);
1877
          RETURN_IF_ERROR (result_add (dm, "typeinfo for "));
1878
          RETURN_IF_ERROR (demangle_type (dm));
1879
          break;
1880
 
1881
        case 'F':
1882
          /* Typeinfo function.  Used only in old ABI with new mangling.  */
1883
          advance_char (dm);
1884
          RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));
1885
          RETURN_IF_ERROR (demangle_type (dm));
1886
          break;
1887
 
1888
        case 'S':
1889
          /* Character string containing type name, used in typeinfo. */
1890
          advance_char (dm);
1891
          RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));
1892
          RETURN_IF_ERROR (demangle_type (dm));
1893
          break;
1894
 
1895
        case 'J':
1896
          /* The java Class variable corresponding to a C++ class.  */
1897
          advance_char (dm);
1898
          RETURN_IF_ERROR (result_add (dm, "java Class for "));
1899
          RETURN_IF_ERROR (demangle_type (dm));
1900
          break;
1901
 
1902
        case 'h':
1903
          /* Non-virtual thunk.  */
1904
          advance_char (dm);
1905
          RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));
1906
          RETURN_IF_ERROR (demangle_nv_offset (dm));
1907
          /* Demangle the separator.  */
1908
          RETURN_IF_ERROR (demangle_char (dm, '_'));
1909
          /* Demangle and emit the target name and function type.  */
1910
          RETURN_IF_ERROR (result_add (dm, " to "));
1911
          RETURN_IF_ERROR (demangle_encoding (dm));
1912
          break;
1913
 
1914
        case 'v':
1915
          /* Virtual thunk.  */
1916
          advance_char (dm);
1917
          RETURN_IF_ERROR (result_add (dm, "virtual thunk"));
1918
          RETURN_IF_ERROR (demangle_v_offset (dm));
1919
          /* Demangle the separator.  */
1920
          RETURN_IF_ERROR (demangle_char (dm, '_'));
1921
          /* Demangle and emit the target function.  */
1922
          RETURN_IF_ERROR (result_add (dm, " to "));
1923
          RETURN_IF_ERROR (demangle_encoding (dm));
1924
          break;
1925
 
1926
        case 'c':
1927
          /* Covariant return thunk.  */
1928
          advance_char (dm);
1929
          RETURN_IF_ERROR (result_add (dm, "covariant return thunk"));
1930
          RETURN_IF_ERROR (demangle_call_offset (dm));
1931
          RETURN_IF_ERROR (demangle_call_offset (dm));
1932
          /* Demangle and emit the target function.  */
1933
          RETURN_IF_ERROR (result_add (dm, " to "));
1934
          RETURN_IF_ERROR (demangle_encoding (dm));
1935
          break;
1936
 
1937
        case 'C':
1938
          /* TC is a special g++ mangling for a construction vtable. */
1939
          if (!flag_strict)
1940
            {
1941
              dyn_string_t derived_type;
1942
 
1943
              advance_char (dm);
1944
              RETURN_IF_ERROR (result_add (dm, "construction vtable for "));
1945
 
1946
              /* Demangle the derived type off to the side.  */
1947
              RETURN_IF_ERROR (result_push (dm));
1948
              RETURN_IF_ERROR (demangle_type (dm));
1949
              derived_type = (dyn_string_t) result_pop (dm);
1950
 
1951
              /* Demangle the offset.  */
1952
              number = dyn_string_new (4);
1953
              if (number == NULL)
1954
                {
1955
                  dyn_string_delete (derived_type);
1956
                  return STATUS_ALLOCATION_FAILED;
1957
                }
1958
              demangle_number_literally (dm, number, 10, 1);
1959
              /* Demangle the underscore separator.  */
1960
              status = demangle_char (dm, '_');
1961
 
1962
              /* Demangle the base type.  */
1963
              if (STATUS_NO_ERROR (status))
1964
                status = demangle_type (dm);
1965
 
1966
              /* Emit the derived type.  */
1967
              if (STATUS_NO_ERROR (status))
1968
                status = result_add (dm, "-in-");
1969
              if (STATUS_NO_ERROR (status))
1970
                status = result_add_string (dm, derived_type);
1971
              dyn_string_delete (derived_type);
1972
 
1973
              /* Don't display the offset unless in verbose mode.  */
1974
              if (flag_verbose)
1975
                {
1976
                  status = result_add_char (dm, ' ');
1977
                  if (STATUS_NO_ERROR (status))
1978
                    result_add_string (dm, number);
1979
                }
1980
              dyn_string_delete (number);
1981
              RETURN_IF_ERROR (status);
1982
              break;
1983
            }
1984
          /* If flag_strict, fall through.  */
1985
 
1986
        default:
1987
          return "Unrecognized <special-name>.";
1988
        }
1989
    }
1990
  else
1991
    return STATUS_ERROR;
1992
 
1993
  return STATUS_OK;
1994
}
1995
 
1996
/* Demangles and emits a <ctor-dtor-name>.
1997
 
1998
    <ctor-dtor-name>
1999
                   ::= C1  # complete object (in-charge) ctor
2000
                   ::= C2  # base object (not-in-charge) ctor
2001
                   ::= C3  # complete object (in-charge) allocating ctor
2002
                   ::= D0  # deleting (in-charge) dtor
2003
                   ::= D1  # complete object (in-charge) dtor
2004
                   ::= D2  # base object (not-in-charge) dtor  */
2005
 
2006
static status_t
2007
demangle_ctor_dtor_name (dm)
2008
     demangling_t dm;
2009
{
2010
  static const char *const ctor_flavors[] =
2011
  {
2012
    "in-charge",
2013
    "not-in-charge",
2014
    "allocating"
2015
  };
2016
  static const char *const dtor_flavors[] =
2017
  {
2018
    "in-charge deleting",
2019
    "in-charge",
2020
    "not-in-charge"
2021
  };
2022
 
2023
  int flavor;
2024
  char peek = peek_char (dm);
2025
 
2026
  DEMANGLE_TRACE ("ctor-dtor-name", dm);
2027
 
2028
  if (peek == 'C')
2029
    {
2030
      /* A constructor name.  Consume the C.  */
2031
      advance_char (dm);
2032
      flavor = next_char (dm);
2033
      if (flavor < '1' || flavor > '3')
2034
        return "Unrecognized constructor.";
2035
      RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
2036
      switch (flavor)
2037
        {
2038
        case '1': dm->is_constructor = gnu_v3_complete_object_ctor;
2039
          break;
2040
        case '2': dm->is_constructor = gnu_v3_base_object_ctor;
2041
          break;
2042
        case '3': dm->is_constructor = gnu_v3_complete_object_allocating_ctor;
2043
          break;
2044
        }
2045
      /* Print the flavor of the constructor if in verbose mode.  */
2046
      if (flag_verbose)
2047
        {
2048
          RETURN_IF_ERROR (result_add (dm, "["));
2049
          RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor - '1']));
2050
          RETURN_IF_ERROR (result_add_char (dm, ']'));
2051
        }
2052
    }
2053
  else if (peek == 'D')
2054
    {
2055
      /* A destructor name.  Consume the D.  */
2056
      advance_char (dm);
2057
      flavor = next_char (dm);
2058
      if (flavor < '0' || flavor > '2')
2059
        return "Unrecognized destructor.";
2060
      RETURN_IF_ERROR (result_add_char (dm, '~'));
2061
      RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
2062
      switch (flavor)
2063
        {
2064
        case '0': dm->is_destructor = gnu_v3_deleting_dtor;
2065
          break;
2066
        case '1': dm->is_destructor = gnu_v3_complete_object_dtor;
2067
          break;
2068
        case '2': dm->is_destructor = gnu_v3_base_object_dtor;
2069
          break;
2070
        }
2071
      /* Print the flavor of the destructor if in verbose mode.  */
2072
      if (flag_verbose)
2073
        {
2074
          RETURN_IF_ERROR (result_add (dm, " ["));
2075
          RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor - '0']));
2076
          RETURN_IF_ERROR (result_add_char (dm, ']'));
2077
        }
2078
    }
2079
  else
2080
    return STATUS_ERROR;
2081
 
2082
  return STATUS_OK;
2083
}
2084
 
2085
/* Handle pointer, reference, and pointer-to-member cases for
2086
   demangle_type.  All consecutive `P's, `R's, and 'M's are joined to
2087
   build a pointer/reference type.  We snarf all these, plus the
2088
   following <type>, all at once since we need to know whether we have
2089
   a pointer to data or pointer to function to construct the right
2090
   output syntax.  C++'s pointer syntax is hairy.
2091
 
2092
   This function adds substitution candidates for every nested
2093
   pointer/reference type it processes, including the outermost, final
2094
   type, assuming the substitution starts at SUBSTITUTION_START in the
2095
   demangling result.  For example, if this function demangles
2096
   `PP3Foo', it will add a substitution for `Foo', `Foo*', and
2097
   `Foo**', in that order.
2098
 
2099
   *INSERT_POS is a quantity used internally, when this function calls
2100
   itself recursively, to figure out where to insert pointer
2101
   punctuation on the way up.  On entry to this function, INSERT_POS
2102
   should point to a temporary value, but that value need not be
2103
   initialized.
2104
 
2105
     <type> ::= P <type>
2106
            ::= R <type>
2107
            ::= <pointer-to-member-type>
2108
 
2109
     <pointer-to-member-type> ::= M </class/ type> </member/ type>  */
2110
 
2111
static status_t
2112
demangle_type_ptr (dm, insert_pos, substitution_start)
2113
     demangling_t dm;
2114
     int *insert_pos;
2115
     int substitution_start;
2116
{
2117
  status_t status;
2118
  int is_substitution_candidate = 1;
2119
 
2120
  DEMANGLE_TRACE ("type*", dm);
2121
 
2122
  /* Scan forward, collecting pointers and references into symbols,
2123
     until we hit something else.  Then emit the type.  */
2124
  switch (peek_char (dm))
2125
    {
2126
    case 'P':
2127
      /* A pointer.  Snarf the `P'.  */
2128
      advance_char (dm);
2129
      /* Demangle the underlying type.  */
2130
      RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2131
                                          substitution_start));
2132
      /* Insert an asterisk where we're told to; it doesn't
2133
         necessarily go at the end.  If we're doing Java style output,
2134
         there is no pointer symbol.  */
2135
      if (dm->style != DMGL_JAVA)
2136
        RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
2137
      /* The next (outermost) pointer or reference character should go
2138
         after this one.  */
2139
      ++(*insert_pos);
2140
      break;
2141
 
2142
    case 'R':
2143
      /* A reference.  Snarf the `R'.  */
2144
      advance_char (dm);
2145
      /* Demangle the underlying type.  */
2146
      RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
2147
                                          substitution_start));
2148
      /* Insert an ampersand where we're told to; it doesn't
2149
         necessarily go at the end.  */
2150
      RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
2151
      /* The next (outermost) pointer or reference character should go
2152
         after this one.  */
2153
      ++(*insert_pos);
2154
      break;
2155
 
2156
    case 'M':
2157
    {
2158
      /* A pointer-to-member.  */
2159
      dyn_string_t class_type;
2160
 
2161
      /* Eat the 'M'.  */
2162
      advance_char (dm);
2163
 
2164
      /* Capture the type of which this is a pointer-to-member.  */
2165
      RETURN_IF_ERROR (result_push (dm));
2166
      RETURN_IF_ERROR (demangle_type (dm));
2167
      class_type = (dyn_string_t) result_pop (dm);
2168
 
2169
      if (peek_char (dm) == 'F')
2170
        /* A pointer-to-member function.  We want output along the
2171
           lines of `void (C::*) (int, int)'.  Demangle the function
2172
           type, which would in this case give `void () (int, int)'
2173
           and set *insert_pos to the spot between the first
2174
           parentheses.  */
2175
        status = demangle_type_ptr (dm, insert_pos, substitution_start);
2176
      else if (peek_char (dm) == 'A')
2177
        /* A pointer-to-member array variable.  We want output that
2178
           looks like `int (Klass::*) [10]'.  Demangle the array type
2179
           as `int () [10]', and set *insert_pos to the spot between
2180
           the parentheses.  */
2181
        status = demangle_array_type (dm, insert_pos);
2182
      else
2183
        {
2184
          /* A pointer-to-member variable.  Demangle the type of the
2185
             pointed-to member.  */
2186
          status = demangle_type (dm);
2187
          /* Make it pretty.  */
2188
          if (STATUS_NO_ERROR (status)
2189
              && !result_previous_char_is_space (dm))
2190
            status = result_add_char (dm, ' ');
2191
          /* The pointer-to-member notation (e.g. `C::*') follows the
2192
             member's type.  */
2193
          *insert_pos = result_caret_pos (dm);
2194
        }
2195
 
2196
      /* Build the pointer-to-member notation.  */
2197
      if (STATUS_NO_ERROR (status))
2198
        status = result_insert (dm, *insert_pos, "::*");
2199
      if (STATUS_NO_ERROR (status))
2200
        status = result_insert_string (dm, *insert_pos, class_type);
2201
      /* There may be additional levels of (pointer or reference)
2202
         indirection in this type.  If so, the `*' and `&' should be
2203
         added after the pointer-to-member notation (e.g. `C::*&' for
2204
         a reference to a pointer-to-member of class C).  */
2205
      *insert_pos += dyn_string_length (class_type) + 3;
2206
 
2207
      /* Clean up. */
2208
      dyn_string_delete (class_type);
2209
 
2210
      RETURN_IF_ERROR (status);
2211
    }
2212
    break;
2213
 
2214
    case 'F':
2215
      /* Ooh, tricky, a pointer-to-function.  When we demangle the
2216
         function type, the return type should go at the very
2217
         beginning.  */
2218
      *insert_pos = result_caret_pos (dm);
2219
      /* The parentheses indicate this is a function pointer or
2220
         reference type.  */
2221
      RETURN_IF_ERROR (result_add (dm, "()"));
2222
      /* Now demangle the function type.  The return type will be
2223
         inserted before the `()', and the argument list will go after
2224
         it.  */
2225
      RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
2226
      /* We should now have something along the lines of
2227
         `void () (int, int)'.  The pointer or reference characters
2228
         have to inside the first set of parentheses.  *insert_pos has
2229
         already been updated to point past the end of the return
2230
         type.  Move it one character over so it points inside the
2231
         `()'.  */
2232
      ++(*insert_pos);
2233
      break;
2234
 
2235
    case 'A':
2236
      /* An array pointer or reference.  demangle_array_type will figure
2237
         out where the asterisks and ampersands go.  */
2238
      RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));
2239
      break;
2240
 
2241
    default:
2242
      /* No more pointer or reference tokens; this is therefore a
2243
         pointer to data.  Finish up by demangling the underlying
2244
         type.  */
2245
      RETURN_IF_ERROR (demangle_type (dm));
2246
      /* The pointer or reference characters follow the underlying
2247
         type, as in `int*&'.  */
2248
      *insert_pos = result_caret_pos (dm);
2249
      /* Because of the production <type> ::= <substitution>,
2250
         demangle_type will already have added the underlying type as
2251
         a substitution candidate.  Don't do it again.  */
2252
      is_substitution_candidate = 0;
2253
      break;
2254
    }
2255
 
2256
  if (is_substitution_candidate)
2257
    RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
2258
 
2259
  return STATUS_OK;
2260
}
2261
 
2262
/* Demangles and emits a <type>.
2263
 
2264
    <type> ::= <builtin-type>
2265
           ::= <function-type>
2266
           ::= <class-enum-type>
2267
           ::= <array-type>
2268
           ::= <pointer-to-member-type>
2269
           ::= <template-param>
2270
           ::= <template-template-param> <template-args>
2271
           ::= <CV-qualifiers> <type>
2272
           ::= P <type>   # pointer-to
2273
           ::= R <type>   # reference-to
2274
           ::= C <type>   # complex pair (C 2000)
2275
           ::= G <type>   # imaginary (C 2000)
2276
           ::= U <source-name> <type>     # vendor extended type qualifier
2277
           ::= <substitution>  */
2278
 
2279
static status_t
2280
demangle_type (dm)
2281
     demangling_t dm;
2282
{
2283
  int start = substitution_start (dm);
2284
  char peek = peek_char (dm);
2285
  char peek_next;
2286
  int encode_return_type = 0;
2287
  template_arg_list_t old_arg_list = current_template_arg_list (dm);
2288
  int insert_pos;
2289
 
2290
  /* A <type> can be a <substitution>; therefore, this <type> is a
2291
     substitution candidate unless a special condition holds (see
2292
     below).  */
2293
  int is_substitution_candidate = 1;
2294
 
2295
  DEMANGLE_TRACE ("type", dm);
2296
 
2297
  /* A <class-enum-type> can start with a digit (a <source-name>), an
2298
     N (a <nested-name>), or a Z (a <local-name>).  */
2299
  if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
2300
    RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
2301
  /* Lower-case letters begin <builtin-type>s, except for `r', which
2302
     denotes restrict.  */
2303
  else if (peek >= 'a' && peek <= 'z' && peek != 'r')
2304
    {
2305
      RETURN_IF_ERROR (demangle_builtin_type (dm));
2306
      /* Built-in types are not substitution candidates.  */
2307
      is_substitution_candidate = 0;
2308
    }
2309
  else
2310
    switch (peek)
2311
      {
2312
      case 'r':
2313
      case 'V':
2314
      case 'K':
2315
        /* CV-qualifiers (including restrict).  We have to demangle
2316
           them off to the side, since C++ syntax puts them in a funny
2317
           place for qualified pointer and reference types.  */
2318
        {
2319
          status_t status;
2320
          dyn_string_t cv_qualifiers = dyn_string_new (24);
2321
          int old_caret_position = result_get_caret (dm);
2322
 
2323
          if (cv_qualifiers == NULL)
2324
            return STATUS_ALLOCATION_FAILED;
2325
 
2326
          /* Decode all adjacent CV qualifiers.  */
2327
          demangle_CV_qualifiers (dm, cv_qualifiers);
2328
          /* Emit them, and shift the caret left so that the
2329
             underlying type will be emitted before the qualifiers.  */
2330
          status = result_add_string (dm, cv_qualifiers);
2331
          result_shift_caret (dm, -dyn_string_length (cv_qualifiers));
2332
          /* Clean up.  */
2333
          dyn_string_delete (cv_qualifiers);
2334
          RETURN_IF_ERROR (status);
2335
          /* Also prepend a blank, if needed.  */
2336
          RETURN_IF_ERROR (result_add_char (dm, ' '));
2337
          result_shift_caret (dm, -1);
2338
 
2339
          /* Demangle the underlying type.  It will be emitted before
2340
             the CV qualifiers, since we moved the caret.  */
2341
          RETURN_IF_ERROR (demangle_type (dm));
2342
 
2343
          /* Put the caret back where it was previously.  */
2344
          result_set_caret (dm, old_caret_position);
2345
        }
2346
        break;
2347
 
2348
      case 'F':
2349
        return "Non-pointer or -reference function type.";
2350
 
2351
      case 'A':
2352
        RETURN_IF_ERROR (demangle_array_type (dm, NULL));
2353
        break;
2354
 
2355
      case 'T':
2356
        /* It's either a <template-param> or a
2357
           <template-template-param>.  In either case, demangle the
2358
           `T' token first.  */
2359
        RETURN_IF_ERROR (demangle_template_param (dm));
2360
 
2361
        /* Check for a template argument list; if one is found, it's a
2362
             <template-template-param> ::= <template-param>
2363
                                       ::= <substitution>  */
2364
        if (peek_char (dm) == 'I')
2365
          {
2366
            /* Add a substitution candidate.  The template parameter
2367
               `T' token is a substitution candidate by itself,
2368
               without the template argument list.  */
2369
            RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2370
 
2371
            /* Now demangle the template argument list.  */
2372
            RETURN_IF_ERROR (demangle_template_args (dm));
2373
            /* The entire type, including the template template
2374
               parameter and its argument list, will be added as a
2375
               substitution candidate below.  */
2376
          }
2377
 
2378
        break;
2379
 
2380
      case 'S':
2381
        /* First check if this is a special substitution.  If it is,
2382
           this is a <class-enum-type>.  Special substitutions have a
2383
           letter following the `S'; other substitutions have a digit
2384
           or underscore.  */
2385
        peek_next = peek_char_next (dm);
2386
        if (IS_DIGIT (peek_next) || peek_next == '_')
2387
          {
2388
            RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
2389
 
2390
            /* The substituted name may have been a template name.
2391
               Check if template arguments follow, and if so, demangle
2392
               them.  */
2393
            if (peek_char (dm) == 'I')
2394
              RETURN_IF_ERROR (demangle_template_args (dm));
2395
            else
2396
              /* A substitution token is not itself a substitution
2397
                 candidate.  (However, if the substituted template is
2398
                 instantiated, the resulting type is.)  */
2399
              is_substitution_candidate = 0;
2400
          }
2401
        else
2402
          {
2403
            /* Now some trickiness.  We have a special substitution
2404
               here.  Often, the special substitution provides the
2405
               name of a template that's subsequently instantiated,
2406
               for instance `SaIcE' => std::allocator<char>.  In these
2407
               cases we need to add a substitution candidate for the
2408
               entire <class-enum-type> and thus don't want to clear
2409
               the is_substitution_candidate flag.
2410
 
2411
               However, it's possible that what we have here is a
2412
               substitution token representing an entire type, such as
2413
               `Ss' => std::string.  In this case, we mustn't add a
2414
               new substitution candidate for this substitution token.
2415
               To detect this case, remember where the start of the
2416
               substitution token is.  */
2417
            const char *next = dm->next;
2418
            /* Now demangle the <class-enum-type>.  */
2419
            RETURN_IF_ERROR
2420
              (demangle_class_enum_type (dm, &encode_return_type));
2421
            /* If all that was just demangled is the two-character
2422
               special substitution token, supress the addition of a
2423
               new candidate for it.  */
2424
            if (dm->next == next + 2)
2425
              is_substitution_candidate = 0;
2426
          }
2427
 
2428
        break;
2429
 
2430
      case 'P':
2431
      case 'R':
2432
      case 'M':
2433
        RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
2434
        /* demangle_type_ptr adds all applicable substitution
2435
           candidates.  */
2436
        is_substitution_candidate = 0;
2437
        break;
2438
 
2439
      case 'C':
2440
        /* A C99 complex type.  */
2441
        RETURN_IF_ERROR (result_add (dm, "complex "));
2442
        advance_char (dm);
2443
        RETURN_IF_ERROR (demangle_type (dm));
2444
        break;
2445
 
2446
      case 'G':
2447
        /* A C99 imaginary type.  */
2448
        RETURN_IF_ERROR (result_add (dm, "imaginary "));
2449
        advance_char (dm);
2450
        RETURN_IF_ERROR (demangle_type (dm));
2451
        break;
2452
 
2453
      case 'U':
2454
        /* Vendor-extended type qualifier.  */
2455
        advance_char (dm);
2456
        RETURN_IF_ERROR (demangle_source_name (dm));
2457
        RETURN_IF_ERROR (result_add_char (dm, ' '));
2458
        RETURN_IF_ERROR (demangle_type (dm));
2459
        break;
2460
 
2461
      default:
2462
        return "Unexpected character in <type>.";
2463
      }
2464
 
2465
  if (is_substitution_candidate)
2466
    /* Add a new substitution for the type. If this type was a
2467
       <template-param>, pass its index since from the point of
2468
       substitutions; a <template-param> token is a substitution
2469
       candidate distinct from the type that is substituted for it.  */
2470
    RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
2471
 
2472
  /* Pop off template argument lists added during mangling of this
2473
     type.  */
2474
  pop_to_template_arg_list (dm, old_arg_list);
2475
 
2476
  return STATUS_OK;
2477
}
2478
 
2479
/* C++ source names of builtin types, indexed by the mangled code
2480
   letter's position in the alphabet ('a' -> 0, 'b' -> 1, etc).  */
2481
static const char *const builtin_type_names[26] =
2482
{
2483
  "signed char",              /* a */
2484
  "bool",                     /* b */
2485
  "char",                     /* c */
2486
  "double",                   /* d */
2487
  "long double",              /* e */
2488
  "float",                    /* f */
2489
  "__float128",               /* g */
2490
  "unsigned char",            /* h */
2491
  "int",                      /* i */
2492
  "unsigned",                 /* j */
2493
  NULL,                       /* k */
2494
  "long",                     /* l */
2495
  "unsigned long",            /* m */
2496
  "__int128",                 /* n */
2497
  "unsigned __int128",        /* o */
2498
  NULL,                       /* p */
2499
  NULL,                       /* q */
2500
  NULL,                       /* r */
2501
  "short",                    /* s */
2502
  "unsigned short",           /* t */
2503
  NULL,                       /* u */
2504
  "void",                     /* v */
2505
  "wchar_t",                  /* w */
2506
  "long long",                /* x */
2507
  "unsigned long long",       /* y */
2508
  "..."                       /* z */
2509
};
2510
 
2511
/* Java source names of builtin types.  Types that arn't valid in Java
2512
   are also included here - we don't fail if someone attempts to demangle a
2513
   C++ symbol in Java style. */
2514
static const char *const java_builtin_type_names[26] =
2515
{
2516
  "signed char",                /* a */
2517
  "boolean", /* C++ "bool" */   /* b */
2518
  "byte", /* C++ "char" */      /* c */
2519
  "double",                     /* d */
2520
  "long double",                /* e */
2521
  "float",                      /* f */
2522
  "__float128",                 /* g */
2523
  "unsigned char",              /* h */
2524
  "int",                        /* i */
2525
  "unsigned",                   /* j */
2526
  NULL,                         /* k */
2527
  "long",                       /* l */
2528
  "unsigned long",              /* m */
2529
  "__int128",                   /* n */
2530
  "unsigned __int128",          /* o */
2531
  NULL,                         /* p */
2532
  NULL,                         /* q */
2533
  NULL,                         /* r */
2534
  "short",                      /* s */
2535
  "unsigned short",             /* t */
2536
  NULL,                         /* u */
2537
  "void",                       /* v */
2538
  "char", /* C++ "wchar_t" */   /* w */
2539
  "long", /* C++ "long long" */ /* x */
2540
  "unsigned long long",         /* y */
2541
  "..."                         /* z */
2542
};
2543
 
2544
/* Demangles and emits a <builtin-type>.
2545
 
2546
    <builtin-type> ::= v  # void
2547
                   ::= w  # wchar_t
2548
                   ::= b  # bool
2549
                   ::= c  # char
2550
                   ::= a  # signed char
2551
                   ::= h  # unsigned char
2552
                   ::= s  # short
2553
                   ::= t  # unsigned short
2554
                   ::= i  # int
2555
                   ::= j  # unsigned int
2556
                   ::= l  # long
2557
                   ::= m  # unsigned long
2558
                   ::= x  # long long, __int64
2559
                   ::= y  # unsigned long long, __int64
2560
                   ::= n  # __int128
2561
                   ::= o  # unsigned __int128
2562
                   ::= f  # float
2563
                   ::= d  # double
2564
                   ::= e  # long double, __float80
2565
                   ::= g  # __float128
2566
                   ::= z  # ellipsis
2567
                   ::= u <source-name>    # vendor extended type  */
2568
 
2569
static status_t
2570
demangle_builtin_type (dm)
2571
     demangling_t dm;
2572
{
2573
 
2574
  char code = peek_char (dm);
2575
 
2576
  DEMANGLE_TRACE ("builtin-type", dm);
2577
 
2578
  if (code == 'u')
2579
    {
2580
      advance_char (dm);
2581
      RETURN_IF_ERROR (demangle_source_name (dm));
2582
      return STATUS_OK;
2583
    }
2584
  else if (code >= 'a' && code <= 'z')
2585
    {
2586
      const char *type_name;
2587
      /* Java uses different names for some built-in types. */
2588
      if (dm->style == DMGL_JAVA)
2589
        type_name = java_builtin_type_names[code - 'a'];
2590
      else
2591
        type_name = builtin_type_names[code - 'a'];
2592
      if (type_name == NULL)
2593
        return "Unrecognized <builtin-type> code.";
2594
 
2595
      RETURN_IF_ERROR (result_add (dm, type_name));
2596
      advance_char (dm);
2597
      return STATUS_OK;
2598
    }
2599
  else
2600
    return "Non-alphabetic <builtin-type> code.";
2601
}
2602
 
2603
/* Demangles all consecutive CV-qualifiers (const, volatile, and
2604
   restrict) at the current position.  The qualifiers are appended to
2605
   QUALIFIERS.  Returns STATUS_OK.  */
2606
 
2607
static status_t
2608
demangle_CV_qualifiers (dm, qualifiers)
2609
     demangling_t dm;
2610
     dyn_string_t qualifiers;
2611
{
2612
  DEMANGLE_TRACE ("CV-qualifiers", dm);
2613
 
2614
  while (1)
2615
    {
2616
      switch (peek_char (dm))
2617
        {
2618
        case 'r':
2619
          if (!dyn_string_append_space (qualifiers))
2620
            return STATUS_ALLOCATION_FAILED;
2621
          if (!dyn_string_append_cstr (qualifiers, "restrict"))
2622
            return STATUS_ALLOCATION_FAILED;
2623
          break;
2624
 
2625
        case 'V':
2626
          if (!dyn_string_append_space (qualifiers))
2627
            return STATUS_ALLOCATION_FAILED;
2628
          if (!dyn_string_append_cstr (qualifiers, "volatile"))
2629
            return STATUS_ALLOCATION_FAILED;
2630
          break;
2631
 
2632
        case 'K':
2633
          if (!dyn_string_append_space (qualifiers))
2634
            return STATUS_ALLOCATION_FAILED;
2635
          if (!dyn_string_append_cstr (qualifiers, "const"))
2636
            return STATUS_ALLOCATION_FAILED;
2637
          break;
2638
 
2639
        default:
2640
          return STATUS_OK;
2641
        }
2642
 
2643
      advance_char (dm);
2644
    }
2645
}
2646
 
2647
/* Demangles and emits a <function-type>.  *FUNCTION_NAME_POS is the
2648
   position in the result string of the start of the function
2649
   identifier, at which the function's return type will be inserted;
2650
   *FUNCTION_NAME_POS is updated to position past the end of the
2651
   function's return type.
2652
 
2653
    <function-type> ::= F [Y] <bare-function-type> E  */
2654
 
2655
static status_t
2656
demangle_function_type (dm, function_name_pos)
2657
     demangling_t dm;
2658
     int *function_name_pos;
2659
{
2660
  DEMANGLE_TRACE ("function-type", dm);
2661
  RETURN_IF_ERROR (demangle_char (dm, 'F'));
2662
  if (peek_char (dm) == 'Y')
2663
    {
2664
      /* Indicate this function has C linkage if in verbose mode.  */
2665
      if (flag_verbose)
2666
        RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));
2667
      advance_char (dm);
2668
    }
2669
  RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
2670
  RETURN_IF_ERROR (demangle_char (dm, 'E'));
2671
  return STATUS_OK;
2672
}
2673
 
2674
/* Demangles and emits a <bare-function-type>.  RETURN_TYPE_POS is the
2675
   position in the result string at which the function return type
2676
   should be inserted.  If RETURN_TYPE_POS is BFT_NO_RETURN_TYPE, the
2677
   function's return type is assumed not to be encoded.
2678
 
2679
    <bare-function-type> ::= <signature type>+  */
2680
 
2681
static status_t
2682
demangle_bare_function_type (dm, return_type_pos)
2683
     demangling_t dm;
2684
     int *return_type_pos;
2685
{
2686
  /* Sequence is the index of the current function parameter, counting
2687
     from zero.  The value -1 denotes the return type.  */
2688
  int sequence =
2689
    (return_type_pos == BFT_NO_RETURN_TYPE ? 0 : -1);
2690
 
2691
  DEMANGLE_TRACE ("bare-function-type", dm);
2692
 
2693
  RETURN_IF_ERROR (result_add_char (dm, '('));
2694
  while (!end_of_name_p (dm) && peek_char (dm) != 'E')
2695
    {
2696
      if (sequence == -1)
2697
        /* We're decoding the function's return type.  */
2698
        {
2699
          dyn_string_t return_type;
2700
          status_t status = STATUS_OK;
2701
 
2702
          /* Decode the return type off to the side.  */
2703
          RETURN_IF_ERROR (result_push (dm));
2704
          RETURN_IF_ERROR (demangle_type (dm));
2705
          return_type = (dyn_string_t) result_pop (dm);
2706
 
2707
          /* Add a space to the end of the type.  Insert the return
2708
             type where we've been asked to. */
2709
          if (!dyn_string_append_space (return_type))
2710
            status = STATUS_ALLOCATION_FAILED;
2711
          if (STATUS_NO_ERROR (status))
2712
            {
2713
              if (!dyn_string_insert (result_string (dm), *return_type_pos,
2714
                                      return_type))
2715
                status = STATUS_ALLOCATION_FAILED;
2716
              else
2717
                *return_type_pos += dyn_string_length (return_type);
2718
            }
2719
 
2720
          dyn_string_delete (return_type);
2721
          RETURN_IF_ERROR (status);
2722
        }
2723
      else
2724
        {
2725
          /* Skip `void' parameter types.  One should only occur as
2726
             the only type in a parameter list; in that case, we want
2727
             to print `foo ()' instead of `foo (void)'.  */
2728
          if (peek_char (dm) == 'v')
2729
            /* Consume the v.  */
2730
            advance_char (dm);
2731
          else
2732
            {
2733
              /* Separate parameter types by commas.  */
2734
              if (sequence > 0)
2735
                RETURN_IF_ERROR (result_add (dm, ", "));
2736
              /* Demangle the type.  */
2737
              RETURN_IF_ERROR (demangle_type (dm));
2738
            }
2739
        }
2740
 
2741
      ++sequence;
2742
    }
2743
  RETURN_IF_ERROR (result_add_char (dm, ')'));
2744
 
2745
  /* We should have demangled at least one parameter type (which would
2746
     be void, for a function that takes no parameters), plus the
2747
     return type, if we were supposed to demangle that.  */
2748
  if (sequence == -1)
2749
    return "Missing function return type.";
2750
  else if (sequence == 0)
2751
    return "Missing function parameter.";
2752
 
2753
  return STATUS_OK;
2754
}
2755
 
2756
/* Demangles and emits a <class-enum-type>.  *ENCODE_RETURN_TYPE is set to
2757
   non-zero if the type is a template-id, zero otherwise.
2758
 
2759
    <class-enum-type> ::= <name>  */
2760
 
2761
static status_t
2762
demangle_class_enum_type (dm, encode_return_type)
2763
     demangling_t dm;
2764
     int *encode_return_type;
2765
{
2766
  DEMANGLE_TRACE ("class-enum-type", dm);
2767
 
2768
  RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
2769
  return STATUS_OK;
2770
}
2771
 
2772
/* Demangles and emits an <array-type>.
2773
 
2774
   If PTR_INSERT_POS is not NULL, the array type is formatted as a
2775
   pointer or reference to an array, except that asterisk and
2776
   ampersand punctuation is omitted (since it's not know at this
2777
   point).  *PTR_INSERT_POS is set to the position in the demangled
2778
   name at which this punctuation should be inserted.  For example,
2779
   `A10_i' is demangled to `int () [10]' and *PTR_INSERT_POS points
2780
   between the parentheses.
2781
 
2782
   If PTR_INSERT_POS is NULL, the array type is assumed not to be
2783
   pointer- or reference-qualified.  Then, for example, `A10_i' is
2784
   demangled simply as `int[10]'.
2785
 
2786
    <array-type> ::= A [<dimension number>] _ <element type>
2787
                 ::= A <dimension expression> _ <element type>  */
2788
 
2789
static status_t
2790
demangle_array_type (dm, ptr_insert_pos)
2791
     demangling_t dm;
2792
     int *ptr_insert_pos;
2793
{
2794
  status_t status = STATUS_OK;
2795
  dyn_string_t array_size = NULL;
2796
  char peek;
2797
 
2798
  DEMANGLE_TRACE ("array-type", dm);
2799
 
2800
  RETURN_IF_ERROR (demangle_char (dm, 'A'));
2801
 
2802
  /* Demangle the array size into array_size.  */
2803
  peek = peek_char (dm);
2804
  if (peek == '_')
2805
    /* Array bound is omitted.  This is a C99-style VLA.  */
2806
    ;
2807
  else if (IS_DIGIT (peek_char (dm)))
2808
    {
2809
      /* It looks like a constant array bound.  */
2810
      array_size = dyn_string_new (10);
2811
      if (array_size == NULL)
2812
        return STATUS_ALLOCATION_FAILED;
2813
      status = demangle_number_literally (dm, array_size, 10, 0);
2814
    }
2815
  else
2816
    {
2817
      /* Anything is must be an expression for a nont-constant array
2818
         bound.  This happens if the array type occurs in a template
2819
         and the array bound references a template parameter.  */
2820
      RETURN_IF_ERROR (result_push (dm));
2821
      RETURN_IF_ERROR (demangle_expression (dm));
2822
      array_size = (dyn_string_t) result_pop (dm);
2823
    }
2824
  /* array_size may have been allocated by now, so we can't use
2825
     RETURN_IF_ERROR until it's been deallocated.  */
2826
 
2827
  /* Demangle the base type of the array.  */
2828
  if (STATUS_NO_ERROR (status))
2829
    status = demangle_char (dm, '_');
2830
  if (STATUS_NO_ERROR (status))
2831
    status = demangle_type (dm);
2832
 
2833
  if (ptr_insert_pos != NULL)
2834
    {
2835
      /* This array is actually part of an pointer- or
2836
         reference-to-array type.  Format appropriately, except we
2837
         don't know which and how much punctuation to use.  */
2838
      if (STATUS_NO_ERROR (status))
2839
        status = result_add (dm, " () ");
2840
      /* Let the caller know where to insert the punctuation.  */
2841
      *ptr_insert_pos = result_caret_pos (dm) - 2;
2842
    }
2843
 
2844
  /* Emit the array dimension syntax.  */
2845
  if (STATUS_NO_ERROR (status))
2846
    status = result_add_char (dm, '[');
2847
  if (STATUS_NO_ERROR (status) && array_size != NULL)
2848
    status = result_add_string (dm, array_size);
2849
  if (STATUS_NO_ERROR (status))
2850
    status = result_add_char (dm, ']');
2851
  if (array_size != NULL)
2852
    dyn_string_delete (array_size);
2853
 
2854
  RETURN_IF_ERROR (status);
2855
 
2856
  return STATUS_OK;
2857
}
2858
 
2859
/* Demangles and emits a <template-param>.
2860
 
2861
    <template-param> ::= T_       # first template parameter
2862
                     ::= T <parameter-2 number> _  */
2863
 
2864
static status_t
2865
demangle_template_param (dm)
2866
     demangling_t dm;
2867
{
2868
  int parm_number;
2869
  template_arg_list_t current_arg_list = current_template_arg_list (dm);
2870
  string_list_t arg;
2871
 
2872
  DEMANGLE_TRACE ("template-param", dm);
2873
 
2874
  /* Make sure there is a template argmust list in which to look up
2875
     this parameter reference.  */
2876
  if (current_arg_list == NULL)
2877
    return "Template parameter outside of template.";
2878
 
2879
  RETURN_IF_ERROR (demangle_char (dm, 'T'));
2880
  if (peek_char (dm) == '_')
2881
    parm_number = 0;
2882
  else
2883
    {
2884
      RETURN_IF_ERROR (demangle_number (dm, &parm_number, 10, 0));
2885
      ++parm_number;
2886
    }
2887
  RETURN_IF_ERROR (demangle_char (dm, '_'));
2888
 
2889
  arg = template_arg_list_get_arg (current_arg_list, parm_number);
2890
  if (arg == NULL)
2891
    /* parm_number exceeded the number of arguments in the current
2892
       template argument list.  */
2893
    return "Template parameter number out of bounds.";
2894
  RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
2895
 
2896
  return STATUS_OK;
2897
}
2898
 
2899
/* Demangles and emits a <template-args>.
2900
 
2901
    <template-args> ::= I <template-arg>+ E  */
2902
 
2903
static status_t
2904
demangle_template_args (dm)
2905
     demangling_t dm;
2906
{
2907
  int first = 1;
2908
  dyn_string_t old_last_source_name;
2909
  template_arg_list_t arg_list = template_arg_list_new ();
2910
 
2911
  if (arg_list == NULL)
2912
    return STATUS_ALLOCATION_FAILED;
2913
 
2914
  /* Preserve the most recently demangled source name.  */
2915
  old_last_source_name = dm->last_source_name;
2916
  dm->last_source_name = dyn_string_new (0);
2917
 
2918
  DEMANGLE_TRACE ("template-args", dm);
2919
 
2920
  if (dm->last_source_name == NULL)
2921
    return STATUS_ALLOCATION_FAILED;
2922
 
2923
  RETURN_IF_ERROR (demangle_char (dm, 'I'));
2924
  RETURN_IF_ERROR (result_open_template_list (dm));
2925
  do
2926
    {
2927
      string_list_t arg;
2928
 
2929
      if (first)
2930
        first = 0;
2931
      else
2932
        RETURN_IF_ERROR (result_add (dm, ", "));
2933
 
2934
      /* Capture the template arg.  */
2935
      RETURN_IF_ERROR (result_push (dm));
2936
      RETURN_IF_ERROR (demangle_template_arg (dm));
2937
      arg = result_pop (dm);
2938
 
2939
      /* Emit it in the demangled name.  */
2940
      RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
2941
 
2942
      /* Save it for use in expanding <template-param>s.  */
2943
      template_arg_list_add_arg (arg_list, arg);
2944
    }
2945
  while (peek_char (dm) != 'E');
2946
  /* Append the '>'.  */
2947
  RETURN_IF_ERROR (result_close_template_list (dm));
2948
 
2949
  /* Consume the 'E'.  */
2950
  advance_char (dm);
2951
 
2952
  /* Restore the most recent demangled source name.  */
2953
  dyn_string_delete (dm->last_source_name);
2954
  dm->last_source_name = old_last_source_name;
2955
 
2956
  /* Push the list onto the top of the stack of template argument
2957
     lists, so that arguments from it are used from now on when
2958
     expanding <template-param>s.  */
2959
  push_template_arg_list (dm, arg_list);
2960
 
2961
  return STATUS_OK;
2962
}
2963
 
2964
/* This function, which does not correspond to a production in the
2965
   mangling spec, handles the `literal' production for both
2966
   <template-arg> and <expr-primary>.  It does not expect or consume
2967
   the initial `L' or final `E'.  The demangling is given by:
2968
 
2969
     <literal> ::= <type> </value/ number>
2970
 
2971
   and the emitted output is `(type)number'.  */
2972
 
2973
static status_t
2974
demangle_literal (dm)
2975
     demangling_t dm;
2976
{
2977
  char peek = peek_char (dm);
2978
  dyn_string_t value_string;
2979
  status_t status;
2980
 
2981
  DEMANGLE_TRACE ("literal", dm);
2982
 
2983
  if (!flag_verbose && peek >= 'a' && peek <= 'z')
2984
    {
2985
      /* If not in verbose mode and this is a builtin type, see if we
2986
         can produce simpler numerical output.  In particular, for
2987
         integer types shorter than `long', just write the number
2988
         without type information; for bools, write `true' or `false'.
2989
         Other refinements could be made here too.  */
2990
 
2991
      /* This constant string is used to map from <builtin-type> codes
2992
         (26 letters of the alphabet) to codes that determine how the
2993
         value will be displayed.  The codes are:
2994
           b: display as bool
2995
           i: display as int
2996
           l: display as long
2997
         A space means the value will be represented using cast
2998
         notation. */
2999
      static const char *const code_map = "ibi    iii ll     ii  i  ";
3000
 
3001
      char code = code_map[peek - 'a'];
3002
      /* FIXME: Implement demangling of floats and doubles.  */
3003
      if (code == 'u')
3004
        return STATUS_UNIMPLEMENTED;
3005
      if (code == 'b')
3006
        {
3007
          /* It's a boolean.  */
3008
          char value;
3009
 
3010
          /* Consume the b.  */
3011
          advance_char (dm);
3012
          /* Look at the next character.  It should be 0 or 1,
3013
             corresponding to false or true, respectively.  */
3014
          value = peek_char (dm);
3015
          if (value == '0')
3016
            RETURN_IF_ERROR (result_add (dm, "false"));
3017
          else if (value == '1')
3018
            RETURN_IF_ERROR (result_add (dm, "true"));
3019
          else
3020
            return "Unrecognized bool constant.";
3021
          /* Consume the 0 or 1.  */
3022
          advance_char (dm);
3023
          return STATUS_OK;
3024
        }
3025
      else if (code == 'i' || code == 'l')
3026
        {
3027
          /* It's an integer or long.  */
3028
 
3029
          /* Consume the type character.  */
3030
          advance_char (dm);
3031
 
3032
          /* Demangle the number and write it out.  */
3033
          value_string = dyn_string_new (0);
3034
          status = demangle_number_literally (dm, value_string, 10, 1);
3035
          if (STATUS_NO_ERROR (status))
3036
            status = result_add_string (dm, value_string);
3037
          /* For long integers, append an l.  */
3038
          if (code == 'l' && STATUS_NO_ERROR (status))
3039
            status = result_add_char (dm, code);
3040
          dyn_string_delete (value_string);
3041
 
3042
          RETURN_IF_ERROR (status);
3043
          return STATUS_OK;
3044
        }
3045
      /* ...else code == ' ', so fall through to represent this
3046
         literal's type explicitly using cast syntax.  */
3047
    }
3048
 
3049
  RETURN_IF_ERROR (result_add_char (dm, '('));
3050
  RETURN_IF_ERROR (demangle_type (dm));
3051
  RETURN_IF_ERROR (result_add_char (dm, ')'));
3052
 
3053
  value_string = dyn_string_new (0);
3054
  if (value_string == NULL)
3055
    return STATUS_ALLOCATION_FAILED;
3056
 
3057
  status = demangle_number_literally (dm, value_string, 10, 1);
3058
  if (STATUS_NO_ERROR (status))
3059
    status = result_add_string (dm, value_string);
3060
  dyn_string_delete (value_string);
3061
  RETURN_IF_ERROR (status);
3062
 
3063
  return STATUS_OK;
3064
}
3065
 
3066
/* Demangles and emits a <template-arg>.
3067
 
3068
    <template-arg> ::= <type>                     # type
3069
                   ::= L <type> <value number> E  # literal
3070
                   ::= LZ <encoding> E            # external name
3071
                   ::= X <expression> E           # expression  */
3072
 
3073
static status_t
3074
demangle_template_arg (dm)
3075
     demangling_t dm;
3076
{
3077
  DEMANGLE_TRACE ("template-arg", dm);
3078
 
3079
  switch (peek_char (dm))
3080
    {
3081
    case 'L':
3082
      advance_char (dm);
3083
 
3084
      if (peek_char (dm) == 'Z')
3085
        {
3086
          /* External name.  */
3087
          advance_char (dm);
3088
          /* FIXME: Standard is contradictory here.  */
3089
          RETURN_IF_ERROR (demangle_encoding (dm));
3090
        }
3091
      else
3092
        RETURN_IF_ERROR (demangle_literal (dm));
3093
      RETURN_IF_ERROR (demangle_char (dm, 'E'));
3094
      break;
3095
 
3096
    case 'X':
3097
      /* Expression.  */
3098
      advance_char (dm);
3099
      RETURN_IF_ERROR (demangle_expression (dm));
3100
      RETURN_IF_ERROR (demangle_char (dm, 'E'));
3101
      break;
3102
 
3103
    default:
3104
      RETURN_IF_ERROR (demangle_type (dm));
3105
      break;
3106
    }
3107
 
3108
  return STATUS_OK;
3109
}
3110
 
3111
/* Demangles and emits an <expression>.
3112
 
3113
    <expression> ::= <unary operator-name> <expression>
3114
                 ::= <binary operator-name> <expression> <expression>
3115
                 ::= <expr-primary>
3116
                 ::= <scope-expression>  */
3117
 
3118
static status_t
3119
demangle_expression (dm)
3120
     demangling_t dm;
3121
{
3122
  char peek = peek_char (dm);
3123
 
3124
  DEMANGLE_TRACE ("expression", dm);
3125
 
3126
  if (peek == 'L' || peek == 'T')
3127
    RETURN_IF_ERROR (demangle_expr_primary (dm));
3128
  else if (peek == 's' && peek_char_next (dm) == 'r')
3129
    RETURN_IF_ERROR (demangle_scope_expression (dm));
3130
  else
3131
    /* An operator expression.  */
3132
    {
3133
      int num_args;
3134
      status_t status = STATUS_OK;
3135
      dyn_string_t operator_name;
3136
 
3137
      /* We have an operator name.  Since we want to output binary
3138
         operations in infix notation, capture the operator name
3139
         first.  */
3140
      RETURN_IF_ERROR (result_push (dm));
3141
      RETURN_IF_ERROR (demangle_operator_name (dm, 1, &num_args));
3142
      operator_name = (dyn_string_t) result_pop (dm);
3143
 
3144
      /* If it's binary, do an operand first.  */
3145
      if (num_args > 1)
3146
        {
3147
          status = result_add_char (dm, '(');
3148
          if (STATUS_NO_ERROR (status))
3149
            status = demangle_expression (dm);
3150
          if (STATUS_NO_ERROR (status))
3151
            status = result_add_char (dm, ')');
3152
        }
3153
 
3154
      /* Emit the operator.  */
3155
      if (STATUS_NO_ERROR (status))
3156
        status = result_add_string (dm, operator_name);
3157
      dyn_string_delete (operator_name);
3158
      RETURN_IF_ERROR (status);
3159
 
3160
      /* Emit its second (if binary) or only (if unary) operand.  */
3161
      RETURN_IF_ERROR (result_add_char (dm, '('));
3162
      RETURN_IF_ERROR (demangle_expression (dm));
3163
      RETURN_IF_ERROR (result_add_char (dm, ')'));
3164
 
3165
      /* The ternary operator takes a third operand.  */
3166
      if (num_args == 3)
3167
        {
3168
          RETURN_IF_ERROR (result_add (dm, ":("));
3169
          RETURN_IF_ERROR (demangle_expression (dm));
3170
          RETURN_IF_ERROR (result_add_char (dm, ')'));
3171
        }
3172
    }
3173
 
3174
  return STATUS_OK;
3175
}
3176
 
3177
/* Demangles and emits a <scope-expression>.
3178
 
3179
    <scope-expression> ::= sr <qualifying type> <source-name>
3180
                       ::= sr <qualifying type> <encoding>  */
3181
 
3182
static status_t
3183
demangle_scope_expression (dm)
3184
     demangling_t dm;
3185
{
3186
  RETURN_IF_ERROR (demangle_char (dm, 's'));
3187
  RETURN_IF_ERROR (demangle_char (dm, 'r'));
3188
  RETURN_IF_ERROR (demangle_type (dm));
3189
  RETURN_IF_ERROR (result_add (dm, "::"));
3190
  RETURN_IF_ERROR (demangle_encoding (dm));
3191
  return STATUS_OK;
3192
}
3193
 
3194
/* Demangles and emits an <expr-primary>.
3195
 
3196
    <expr-primary> ::= <template-param>
3197
                   ::= L <type> <value number> E  # literal
3198
                   ::= L <mangled-name> E         # external name  */
3199
 
3200
static status_t
3201
demangle_expr_primary (dm)
3202
     demangling_t dm;
3203
{
3204
  char peek = peek_char (dm);
3205
 
3206
  DEMANGLE_TRACE ("expr-primary", dm);
3207
 
3208
  if (peek == 'T')
3209
    RETURN_IF_ERROR (demangle_template_param (dm));
3210
  else if (peek == 'L')
3211
    {
3212
      /* Consume the `L'.  */
3213
      advance_char (dm);
3214
      peek = peek_char (dm);
3215
 
3216
      if (peek == '_')
3217
        RETURN_IF_ERROR (demangle_mangled_name (dm));
3218
      else
3219
        RETURN_IF_ERROR (demangle_literal (dm));
3220
 
3221
      RETURN_IF_ERROR (demangle_char (dm, 'E'));
3222
    }
3223
  else
3224
    return STATUS_ERROR;
3225
 
3226
  return STATUS_OK;
3227
}
3228
 
3229
/* Demangles and emits a <substitution>.  Sets *TEMPLATE_P to non-zero
3230
   if the substitution is the name of a template, zero otherwise.
3231
 
3232
     <substitution> ::= S <seq-id> _
3233
                    ::= S_
3234
 
3235
                    ::= St   # ::std::
3236
                    ::= Sa   # ::std::allocator
3237
                    ::= Sb   # ::std::basic_string
3238
                    ::= Ss   # ::std::basic_string<char,
3239
                                                   ::std::char_traits<char>,
3240
                                                   ::std::allocator<char> >
3241
                    ::= Si   # ::std::basic_istream<char,
3242
                                                    std::char_traits<char> >
3243
                    ::= So   # ::std::basic_ostream<char,
3244
                                                    std::char_traits<char> >
3245
                    ::= Sd   # ::std::basic_iostream<char,
3246
                                                    std::char_traits<char> >
3247
*/
3248
 
3249
static status_t
3250
demangle_substitution (dm, template_p)
3251
     demangling_t dm;
3252
     int *template_p;
3253
{
3254
  int seq_id;
3255
  int peek;
3256
  dyn_string_t text;
3257
 
3258
  DEMANGLE_TRACE ("substitution", dm);
3259
 
3260
  RETURN_IF_ERROR (demangle_char (dm, 'S'));
3261
 
3262
  /* Scan the substitution sequence index.  A missing number denotes
3263
     the first index.  */
3264
  peek = peek_char (dm);
3265
  if (peek == '_')
3266
    seq_id = -1;
3267
  /* If the following character is 0-9 or a capital letter, interpret
3268
     the sequence up to the next underscore as a base-36 substitution
3269
     index.  */
3270
  else if (IS_DIGIT ((unsigned char) peek)
3271
           || (peek >= 'A' && peek <= 'Z'))
3272
    RETURN_IF_ERROR (demangle_number (dm, &seq_id, 36, 0));
3273
  else
3274
    {
3275
      const char *new_last_source_name = NULL;
3276
 
3277
      switch (peek)
3278
        {
3279
        case 't':
3280
          RETURN_IF_ERROR (result_add (dm, "std"));
3281
          break;
3282
 
3283
        case 'a':
3284
          RETURN_IF_ERROR (result_add (dm, "std::allocator"));
3285
          new_last_source_name = "allocator";
3286
          *template_p = 1;
3287
          break;
3288
 
3289
        case 'b':
3290
          RETURN_IF_ERROR (result_add (dm, "std::basic_string"));
3291
          new_last_source_name = "basic_string";
3292
          *template_p = 1;
3293
          break;
3294
 
3295
        case 's':
3296
          if (!flag_verbose)
3297
            {
3298
              RETURN_IF_ERROR (result_add (dm, "std::string"));
3299
              new_last_source_name = "string";
3300
            }
3301
          else
3302
            {
3303
              RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
3304
              new_last_source_name = "basic_string";
3305
            }
3306
          *template_p = 0;
3307
          break;
3308
 
3309
        case 'i':
3310
          if (!flag_verbose)
3311
            {
3312
              RETURN_IF_ERROR (result_add (dm, "std::istream"));
3313
              new_last_source_name = "istream";
3314
            }
3315
          else
3316
            {
3317
              RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traints<char> >"));
3318
              new_last_source_name = "basic_istream";
3319
            }
3320
          *template_p = 0;
3321
          break;
3322
 
3323
        case 'o':
3324
          if (!flag_verbose)
3325
            {
3326
              RETURN_IF_ERROR (result_add (dm, "std::ostream"));
3327
              new_last_source_name = "ostream";
3328
            }
3329
          else
3330
            {
3331
              RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));
3332
              new_last_source_name = "basic_ostream";
3333
            }
3334
          *template_p = 0;
3335
          break;
3336
 
3337
        case 'd':
3338
          if (!flag_verbose)
3339
            {
3340
              RETURN_IF_ERROR (result_add (dm, "std::iostream"));
3341
              new_last_source_name = "iostream";
3342
            }
3343
          else
3344
            {
3345
              RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));
3346
              new_last_source_name = "basic_iostream";
3347
            }
3348
          *template_p = 0;
3349
          break;
3350
 
3351
        default:
3352
          return "Unrecognized <substitution>.";
3353
        }
3354
 
3355
      /* Consume the character we just processed.  */
3356
      advance_char (dm);
3357
 
3358
      if (new_last_source_name != NULL)
3359
        {
3360
          if (!dyn_string_copy_cstr (dm->last_source_name,
3361
                                     new_last_source_name))
3362
            return STATUS_ALLOCATION_FAILED;
3363
        }
3364
 
3365
      return STATUS_OK;
3366
    }
3367
 
3368
  /* Look up the substitution text.  Since `S_' is the most recent
3369
     substitution, `S0_' is the second-most-recent, etc., shift the
3370
     numbering by one.  */
3371
  text = substitution_get (dm, seq_id + 1, template_p);
3372
  if (text == NULL)
3373
    return "Substitution number out of range.";
3374
 
3375
  /* Emit the substitution text.  */
3376
  RETURN_IF_ERROR (result_add_string (dm, text));
3377
 
3378
  RETURN_IF_ERROR (demangle_char (dm, '_'));
3379
  return STATUS_OK;
3380
}
3381
 
3382
/* Demangles and emits a <local-name>.
3383
 
3384
    <local-name> := Z <function encoding> E <entity name> [<discriminator>]
3385
                 := Z <function encoding> E s [<discriminator>]  */
3386
 
3387
static status_t
3388
demangle_local_name (dm)
3389
     demangling_t dm;
3390
{
3391
  DEMANGLE_TRACE ("local-name", dm);
3392
 
3393
  RETURN_IF_ERROR (demangle_char (dm, 'Z'));
3394
  RETURN_IF_ERROR (demangle_encoding (dm));
3395
  RETURN_IF_ERROR (demangle_char (dm, 'E'));
3396
  RETURN_IF_ERROR (result_add (dm, "::"));
3397
 
3398
  if (peek_char (dm) == 's')
3399
    {
3400
      /* Local character string literal.  */
3401
      RETURN_IF_ERROR (result_add (dm, "string literal"));
3402
      /* Consume the s.  */
3403
      advance_char (dm);
3404
      RETURN_IF_ERROR (demangle_discriminator (dm, 0));
3405
    }
3406
  else
3407
    {
3408
      int unused;
3409
      /* Local name for some other entity.  Demangle its name.  */
3410
      RETURN_IF_ERROR (demangle_name (dm, &unused));
3411
      RETURN_IF_ERROR (demangle_discriminator (dm, 1));
3412
     }
3413
 
3414
   return STATUS_OK;
3415
 }
3416
 
3417
 /* Optimonally demangles and emits a <discriminator>.  If there is no
3418
    <discriminator> at the current position in the mangled string, the
3419
    descriminator is assumed to be zero.  Emit the discriminator number
3420
    in parentheses, unless SUPPRESS_FIRST is non-zero and the
3421
    discriminator is zero.
3422
 
3423
     <discriminator> ::= _ <number>  */
3424
 
3425
static status_t
3426
demangle_discriminator (dm, suppress_first)
3427
     demangling_t dm;
3428
     int suppress_first;
3429
{
3430
  /* Output for <discriminator>s to the demangled name is completely
3431
     suppressed if not in verbose mode.  */
3432
 
3433
  if (peek_char (dm) == '_')
3434
    {
3435
      /* Consume the underscore.  */
3436
      advance_char (dm);
3437
      if (flag_verbose)
3438
        RETURN_IF_ERROR (result_add (dm, " [#"));
3439
      /* Check if there's a number following the underscore.  */
3440
      if (IS_DIGIT ((unsigned char) peek_char (dm)))
3441
        {
3442
          int discriminator;
3443
          /* Demangle the number.  */
3444
          RETURN_IF_ERROR (demangle_number (dm, &discriminator, 10, 0));
3445
          if (flag_verbose)
3446
            /* Write the discriminator.  The mangled number is two
3447
               less than the discriminator ordinal, counting from
3448
               zero.  */
3449
            RETURN_IF_ERROR (int_to_dyn_string (discriminator + 1,
3450
                                                (dyn_string_t) dm->result));
3451
        }
3452
      else
3453
        return STATUS_ERROR;
3454
      if (flag_verbose)
3455
        RETURN_IF_ERROR (result_add_char (dm, ']'));
3456
    }
3457
  else if (!suppress_first)
3458
    {
3459
      if (flag_verbose)
3460
        RETURN_IF_ERROR (result_add (dm, " [#0]"));
3461
    }
3462
 
3463
  return STATUS_OK;
3464
}
3465
 
3466
/* Demangle NAME into RESULT, which must be an initialized
3467
   dyn_string_t.  On success, returns STATUS_OK.  On failure, returns
3468
   an error message, and the contents of RESULT are unchanged.  */
3469
 
3470
static status_t
3471
cp_demangle (name, result, style)
3472
     const char *name;
3473
     dyn_string_t result;
3474
     int style;
3475
{
3476
  status_t status;
3477
  int length = strlen (name);
3478
 
3479
  if (length > 2 && name[0] == '_' && name[1] == 'Z')
3480
    {
3481
      demangling_t dm = demangling_new (name, style);
3482
      if (dm == NULL)
3483
        return STATUS_ALLOCATION_FAILED;
3484
 
3485
      status = result_push (dm);
3486
      if (status != STATUS_OK)
3487
        {
3488
          demangling_delete (dm);
3489
          return status;
3490
        }
3491
 
3492
      status = demangle_mangled_name (dm);
3493
      if (STATUS_NO_ERROR (status))
3494
        {
3495
          dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3496
          if (!dyn_string_copy (result, demangled))
3497
            return STATUS_ALLOCATION_FAILED;
3498
          dyn_string_delete (demangled);
3499
        }
3500
 
3501
      demangling_delete (dm);
3502
    }
3503
  else
3504
    {
3505
      /* It's evidently not a mangled C++ name.  It could be the name
3506
         of something with C linkage, though, so just copy NAME into
3507
         RESULT.  */
3508
      if (!dyn_string_copy_cstr (result, name))
3509
        return STATUS_ALLOCATION_FAILED;
3510
      status = STATUS_OK;
3511
    }
3512
 
3513
  return status;
3514
}
3515
 
3516
/* Demangle TYPE_NAME into RESULT, which must be an initialized
3517
   dyn_string_t.  On success, returns STATUS_OK.  On failiure, returns
3518
   an error message, and the contents of RESULT are unchanged.  */
3519
 
3520
#ifdef IN_LIBGCC2
3521
static status_t
3522
cp_demangle_type (type_name, result)
3523
     const char* type_name;
3524
     dyn_string_t result;
3525
{
3526
  status_t status;
3527
  demangling_t dm = demangling_new (type_name);
3528
 
3529
  if (dm == NULL)
3530
    return STATUS_ALLOCATION_FAILED;
3531
 
3532
  /* Demangle the type name.  The demangled name is stored in dm.  */
3533
  status = result_push (dm);
3534
  if (status != STATUS_OK)
3535
    {
3536
      demangling_delete (dm);
3537
      return status;
3538
    }
3539
 
3540
  status = demangle_type (dm);
3541
 
3542
  if (STATUS_NO_ERROR (status))
3543
    {
3544
      /* The demangling succeeded.  Pop the result out of dm and copy
3545
         it into RESULT.  */
3546
      dyn_string_t demangled = (dyn_string_t) result_pop (dm);
3547
      if (!dyn_string_copy (result, demangled))
3548
        return STATUS_ALLOCATION_FAILED;
3549
      dyn_string_delete (demangled);
3550
    }
3551
 
3552
  /* Clean up.  */
3553
  demangling_delete (dm);
3554
 
3555
  return status;
3556
}
3557
 
3558
extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
3559
 
3560
/* ia64 ABI-mandated entry point in the C++ runtime library for performing
3561
   demangling.  MANGLED_NAME is a NUL-terminated character string
3562
   containing the name to be demangled.
3563
 
3564
   OUTPUT_BUFFER is a region of memory, allocated with malloc, of
3565
   *LENGTH bytes, into which the demangled name is stored.  If
3566
   OUTPUT_BUFFER is not long enough, it is expanded using realloc.
3567
   OUTPUT_BUFFER may instead be NULL; in that case, the demangled name
3568
   is placed in a region of memory allocated with malloc.
3569
 
3570
   If LENGTH is non-NULL, the length of the buffer conaining the
3571
   demangled name, is placed in *LENGTH.
3572
 
3573
   The return value is a pointer to the start of the NUL-terminated
3574
   demangled name, or NULL if the demangling fails.  The caller is
3575
   responsible for deallocating this memory using free.
3576
 
3577
   *STATUS is set to one of the following values:
3578
      0: The demangling operation succeeded.
3579
     -1: A memory allocation failiure occurred.
3580
     -2: MANGLED_NAME is not a valid name under the C++ ABI mangling rules.
3581
     -3: One of the arguments is invalid.
3582
 
3583
   The demagling is performed using the C++ ABI mangling rules, with
3584
   GNU extensions.  */
3585
 
3586
char *
3587
__cxa_demangle (mangled_name, output_buffer, length, status)
3588
     const char *mangled_name;
3589
     char *output_buffer;
3590
     size_t *length;
3591
     int *status;
3592
{
3593
  struct dyn_string demangled_name;
3594
  status_t result;
3595
 
3596
  if (status == NULL)
3597
    return NULL;
3598
 
3599
  if (mangled_name == NULL) {
3600
    *status = -3;
3601
    return NULL;
3602
  }
3603
 
3604
  /* Did the caller provide a buffer for the demangled name?  */
3605
  if (output_buffer == NULL) {
3606
    /* No; dyn_string will malloc a buffer for us.  */
3607
    if (!dyn_string_init (&demangled_name, 0))
3608
      {
3609
        *status = -1;
3610
        return NULL;
3611
      }
3612
  }
3613
  else {
3614
    /* Yes.  Check that the length was provided.  */
3615
    if (length == NULL) {
3616
      *status = -3;
3617
      return NULL;
3618
    }
3619
    /* Install the buffer into a dyn_string.  */
3620
    demangled_name.allocated = *length;
3621
    demangled_name.length = 0;
3622
    demangled_name.s = output_buffer;
3623
  }
3624
 
3625
  if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
3626
    /* MANGLED_NAME apprears to be a function or variable name.
3627
       Demangle it accordingly.  */
3628
    result = cp_demangle (mangled_name, &demangled_name, 0);
3629
  else
3630
    /* Try to demangled MANGLED_NAME as the name of a type.  */
3631
    result = cp_demangle_type (mangled_name, &demangled_name);
3632
 
3633
  if (result == STATUS_OK)
3634
    /* The demangling succeeded.  */
3635
    {
3636
      /* If LENGTH isn't NULL, store the allocated buffer length
3637
         there; the buffer may have been realloced by dyn_string
3638
         functions.  */
3639
      if (length != NULL)
3640
        *length = demangled_name.allocated;
3641
      /* The operation was a success.  */
3642
      *status = 0;
3643
      return dyn_string_buf (&demangled_name);
3644
    }
3645
  else if (result == STATUS_ALLOCATION_FAILED)
3646
    /* A call to malloc or realloc failed during the demangling
3647
       operation.  */
3648
    {
3649
      *status = -1;
3650
      return NULL;
3651
    }
3652
  else
3653
    /* The demangling failed for another reason, most probably because
3654
       MANGLED_NAME isn't a valid mangled name.  */
3655
    {
3656
      /* If the buffer containing the demangled name wasn't provided
3657
         by the caller, free it.  */
3658
      if (output_buffer == NULL)
3659
        free (dyn_string_buf (&demangled_name));
3660
      *status = -2;
3661
      return NULL;
3662
    }
3663
}
3664
 
3665
#else /* !IN_LIBGCC2 */
3666
 
3667
/* Variant entry point for integration with the existing cplus-dem
3668
   demangler.  Attempts to demangle MANGLED.  If the demangling
3669
   succeeds, returns a buffer, allocated with malloc, containing the
3670
   demangled name.  The caller must deallocate the buffer using free.
3671
   If the demangling failes, returns NULL.  */
3672
 
3673
char *
3674
cplus_demangle_v3 (mangled)
3675
     const char* mangled;
3676
{
3677
  dyn_string_t demangled;
3678
  status_t status;
3679
 
3680
  /* If this isn't a mangled name, don't pretend to demangle it.  */
3681
  if (strncmp (mangled, "_Z", 2) != 0)
3682
    return NULL;
3683
 
3684
  /* Create a dyn_string to hold the demangled name.  */
3685
  demangled = dyn_string_new (0);
3686
  /* Attempt the demangling.  */
3687
  status = cp_demangle ((char *) mangled, demangled, 0);
3688
 
3689
  if (STATUS_NO_ERROR (status))
3690
    /* Demangling succeeded.  */
3691
    {
3692
      /* Grab the demangled result from the dyn_string.  It was
3693
         allocated with malloc, so we can return it directly.  */
3694
      char *return_value = dyn_string_release (demangled);
3695
      /* Hand back the demangled name.  */
3696
      return return_value;
3697
    }
3698
  else if (status == STATUS_ALLOCATION_FAILED)
3699
    {
3700
      fprintf (stderr, "Memory allocation failed.\n");
3701
      abort ();
3702
    }
3703
  else
3704
    /* Demangling failed.  */
3705
    {
3706
      dyn_string_delete (demangled);
3707
      return NULL;
3708
    }
3709
}
3710
 
3711
/* Demangle a Java symbol.  Java uses a subset of the V3 ABI C++ mangling
3712
   conventions, but the output formatting is a little different.
3713
   This instructs the C++ demangler not to emit pointer characters ("*"), and
3714
   to use Java's namespace separator symbol ("." instead of "::").  It then
3715
   does an additional pass over the demangled output to replace instances
3716
   of JArray<TYPE> with TYPE[].  */
3717
 
3718
char *
3719
java_demangle_v3 (mangled)
3720
     const char* mangled;
3721
{
3722
  dyn_string_t demangled;
3723
  char *next;
3724
  char *end;
3725
  int len;
3726
  status_t status;
3727
  int nesting = 0;
3728
  char *cplus_demangled;
3729
  char *return_value;
3730
 
3731
  /* Create a dyn_string to hold the demangled name.  */
3732
  demangled = dyn_string_new (0);
3733
 
3734
  /* Attempt the demangling.  */
3735
  status = cp_demangle ((char *) mangled, demangled, DMGL_JAVA);
3736
 
3737
  if (STATUS_NO_ERROR (status))
3738
    /* Demangling succeeded.  */
3739
    {
3740
      /* Grab the demangled result from the dyn_string. */
3741
      cplus_demangled = dyn_string_release (demangled);
3742
    }
3743
  else if (status == STATUS_ALLOCATION_FAILED)
3744
    {
3745
      fprintf (stderr, "Memory allocation failed.\n");
3746
      abort ();
3747
    }
3748
  else
3749
    /* Demangling failed.  */
3750
    {
3751
      dyn_string_delete (demangled);
3752
      return NULL;
3753
    }
3754
 
3755
  len = strlen (cplus_demangled);
3756
  next = cplus_demangled;
3757
  end = next + len;
3758
  demangled = NULL;
3759
 
3760
  /* Replace occurances of JArray<TYPE> with TYPE[]. */
3761
  while (next < end)
3762
    {
3763
      char *open_str = strstr (next, "JArray<");
3764
      char *close_str = NULL;
3765
      if (nesting > 0)
3766
        close_str = strchr (next, '>');
3767
 
3768
      if (open_str != NULL && (close_str == NULL || close_str > open_str))
3769
        {
3770
          ++nesting;
3771
 
3772
          if (!demangled)
3773
            demangled = dyn_string_new(len);
3774
 
3775
          /* Copy prepending symbols, if any. */
3776
          if (open_str > next)
3777
            {
3778
              open_str[0] = 0;
3779
              dyn_string_append_cstr (demangled, next);
3780
            }
3781
          next = open_str + 7;
3782
        }
3783
      else if (close_str != NULL)
3784
        {
3785
          --nesting;
3786
 
3787
          /* Copy prepending type symbol, if any. Squash any spurious
3788
             whitespace. */
3789
          if (close_str > next && next[0] != ' ')
3790
            {
3791
              close_str[0] = 0;
3792
              dyn_string_append_cstr (demangled, next);
3793
            }
3794
          dyn_string_append_cstr (demangled, "[]");
3795
          next = close_str + 1;
3796
        }
3797
      else
3798
        {
3799
          /* There are no more arrays. Copy the rest of the symbol, or
3800
             simply return the original symbol if no changes were made. */
3801
          if (next == cplus_demangled)
3802
            return cplus_demangled;
3803
 
3804
          dyn_string_append_cstr (demangled, next);
3805
          next = end;
3806
        }
3807
    }
3808
 
3809
  free (cplus_demangled);
3810
 
3811
  return_value = dyn_string_release (demangled);
3812
  return return_value;
3813
}
3814
 
3815
#endif /* IN_LIBGCC2 */
3816
 
3817
 
3818
/* Demangle NAME in the G++ V3 ABI demangling style, and return either
3819
   zero, indicating that some error occurred, or a demangling_t
3820
   holding the results.  */
3821
static demangling_t
3822
demangle_v3_with_details (name)
3823
     const char *name;
3824
{
3825
  demangling_t dm;
3826
  status_t status;
3827
 
3828
  if (strncmp (name, "_Z", 2))
3829
    return 0;
3830
 
3831
  dm = demangling_new (name, DMGL_GNU_V3);
3832
  if (dm == NULL)
3833
    {
3834
      fprintf (stderr, "Memory allocation failed.\n");
3835
      abort ();
3836
    }
3837
 
3838
  status = result_push (dm);
3839
  if (! STATUS_NO_ERROR (status))
3840
    {
3841
      demangling_delete (dm);
3842
      fprintf (stderr, "%s\n", status);
3843
      abort ();
3844
    }
3845
 
3846
  status = demangle_mangled_name (dm);
3847
  if (STATUS_NO_ERROR (status))
3848
    return dm;
3849
 
3850
  demangling_delete (dm);
3851
  return 0;
3852
}
3853
 
3854
 
3855
/* Return non-zero iff NAME is the mangled form of a constructor name
3856
   in the G++ V3 ABI demangling style.  Specifically, return:
3857
   - '1' if NAME is a complete object constructor,
3858
   - '2' if NAME is a base object constructor, or
3859
   - '3' if NAME is a complete object allocating constructor.  */
3860
enum gnu_v3_ctor_kinds
3861
is_gnu_v3_mangled_ctor (name)
3862
     const char *name;
3863
{
3864
  demangling_t dm = demangle_v3_with_details (name);
3865
 
3866
  if (dm)
3867
    {
3868
      enum gnu_v3_ctor_kinds result = dm->is_constructor;
3869
      demangling_delete (dm);
3870
      return result;
3871
    }
3872
  else
3873
    return 0;
3874
}
3875
 
3876
 
3877
/* Return non-zero iff NAME is the mangled form of a destructor name
3878
   in the G++ V3 ABI demangling style.  Specifically, return:
3879
   - '0' if NAME is a deleting destructor,
3880
   - '1' if NAME is a complete object destructor, or
3881
   - '2' if NAME is a base object destructor.  */
3882
enum gnu_v3_dtor_kinds
3883
is_gnu_v3_mangled_dtor (name)
3884
     const char *name;
3885
{
3886
  demangling_t dm = demangle_v3_with_details (name);
3887
 
3888
  if (dm)
3889
    {
3890
      enum gnu_v3_dtor_kinds result = dm->is_destructor;
3891
      demangling_delete (dm);
3892
      return result;
3893
    }
3894
  else
3895
    return 0;
3896
}
3897
 
3898
 
3899
#ifdef STANDALONE_DEMANGLER
3900
 
3901
#include "getopt.h"
3902
 
3903
static void print_usage
3904
  PARAMS ((FILE* fp, int exit_value));
3905
 
3906
/* Non-zero if CHAR is a character than can occur in a mangled name.  */
3907
#define is_mangled_char(CHAR)                                           \
3908
  (IS_ALPHA (CHAR) || IS_DIGIT (CHAR)                                   \
3909
   || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
3910
 
3911
/* The name of this program, as invoked.  */
3912
const char* program_name;
3913
 
3914
/* Prints usage summary to FP and then exits with EXIT_VALUE.  */
3915
 
3916
static void
3917
print_usage (fp, exit_value)
3918
     FILE* fp;
3919
     int exit_value;
3920
{
3921
  fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
3922
  fprintf (fp, "Options:\n");
3923
  fprintf (fp, "  -h,--help       Display this message.\n");
3924
  fprintf (fp, "  -s,--strict     Demangle standard names only.\n");
3925
  fprintf (fp, "  -v,--verbose    Produce verbose demanglings.\n");
3926
  fprintf (fp, "If names are provided, they are demangled.  Otherwise filters standard input.\n");
3927
 
3928
  exit (exit_value);
3929
}
3930
 
3931
/* Option specification for getopt_long.  */
3932
static struct option long_options[] =
3933
{
3934
  { "help",    no_argument, NULL, 'h' },
3935
  { "strict",  no_argument, NULL, 's' },
3936
  { "verbose", no_argument, NULL, 'v' },
3937
  { NULL,      no_argument, NULL, 0   },
3938
};
3939
 
3940
/* Main entry for a demangling filter executable.  It will demangle
3941
   its command line arguments, if any.  If none are provided, it will
3942
   filter stdin to stdout, replacing any recognized mangled C++ names
3943
   with their demangled equivalents.  */
3944
 
3945
int
3946
main (argc, argv)
3947
     int argc;
3948
     char *argv[];
3949
{
3950
  status_t status;
3951
  int i;
3952
  int opt_char;
3953
 
3954
  /* Use the program name of this program, as invoked.  */
3955
  program_name = argv[0];
3956
 
3957
  /* Parse options.  */
3958
  do
3959
    {
3960
      opt_char = getopt_long (argc, argv, "hsv", long_options, NULL);
3961
      switch (opt_char)
3962
        {
3963
        case '?':  /* Unrecognized option.  */
3964
          print_usage (stderr, 1);
3965
          break;
3966
 
3967
        case 'h':
3968
          print_usage (stdout, 0);
3969
          break;
3970
 
3971
        case 's':
3972
          flag_strict = 1;
3973
          break;
3974
 
3975
        case 'v':
3976
          flag_verbose = 1;
3977
          break;
3978
        }
3979
    }
3980
  while (opt_char != -1);
3981
 
3982
  if (optind == argc)
3983
    /* No command line arguments were provided.  Filter stdin.  */
3984
    {
3985
      dyn_string_t mangled = dyn_string_new (3);
3986
      dyn_string_t demangled = dyn_string_new (0);
3987
      status_t status;
3988
 
3989
      /* Read all of input.  */
3990
      while (!feof (stdin))
3991
        {
3992
          char c = getchar ();
3993
 
3994
          /* The first character of a mangled name is an underscore.  */
3995
          if (feof (stdin))
3996
            break;
3997
          if (c != '_')
3998
            {
3999
              /* It's not a mangled name.  Print the character and go
4000
                 on.  */
4001
              putchar (c);
4002
              continue;
4003
            }
4004
          c = getchar ();
4005
 
4006
          /* The second character of a mangled name is a capital `Z'.  */
4007
          if (feof (stdin))
4008
            break;
4009
          if (c != 'Z')
4010
            {
4011
              /* It's not a mangled name.  Print the previous
4012
                 underscore, the `Z', and go on.  */
4013
              putchar ('_');
4014
              putchar (c);
4015
              continue;
4016
            }
4017
 
4018
          /* Start keeping track of the candidate mangled name.  */
4019
          dyn_string_append_char (mangled, '_');
4020
          dyn_string_append_char (mangled, 'Z');
4021
 
4022
          /* Pile characters into mangled until we hit one that can't
4023
             occur in a mangled name.  */
4024
          c = getchar ();
4025
          while (!feof (stdin) && is_mangled_char (c))
4026
            {
4027
              dyn_string_append_char (mangled, c);
4028
              if (feof (stdin))
4029
                break;
4030
              c = getchar ();
4031
            }
4032
 
4033
          /* Attempt to demangle the name.  */
4034
          status = cp_demangle (dyn_string_buf (mangled), demangled, 0);
4035
 
4036
          /* If the demangling succeeded, great!  Print out the
4037
             demangled version.  */
4038
          if (STATUS_NO_ERROR (status))
4039
            fputs (dyn_string_buf (demangled), stdout);
4040
          /* Abort on allocation failures.  */
4041
          else if (status == STATUS_ALLOCATION_FAILED)
4042
            {
4043
              fprintf (stderr, "Memory allocation failed.\n");
4044
              abort ();
4045
            }
4046
          /* Otherwise, it might not have been a mangled name.  Just
4047
             print out the original text.  */
4048
          else
4049
            fputs (dyn_string_buf (mangled), stdout);
4050
 
4051
          /* If we haven't hit EOF yet, we've read one character that
4052
             can't occur in a mangled name, so print it out.  */
4053
          if (!feof (stdin))
4054
            putchar (c);
4055
 
4056
          /* Clear the candidate mangled name, to start afresh next
4057
             time we hit a `_Z'.  */
4058
          dyn_string_clear (mangled);
4059
        }
4060
 
4061
      dyn_string_delete (mangled);
4062
      dyn_string_delete (demangled);
4063
    }
4064
  else
4065
    /* Demangle command line arguments.  */
4066
    {
4067
      dyn_string_t result = dyn_string_new (0);
4068
 
4069
      /* Loop over command line arguments.  */
4070
      for (i = optind; i < argc; ++i)
4071
        {
4072
          /* Attempt to demangle.  */
4073
          status = cp_demangle (argv[i], result, 0);
4074
 
4075
          /* If it worked, print the demangled name.  */
4076
          if (STATUS_NO_ERROR (status))
4077
            printf ("%s\n", dyn_string_buf (result));
4078
          /* Abort on allocaiton failures.  */
4079
          else if (status == STATUS_ALLOCATION_FAILED)
4080
            {
4081
              fprintf (stderr, "Memory allocation failed.\n");
4082
              abort ();
4083
            }
4084
          /* If not, print the error message to stderr instead.  */
4085
          else
4086
            fprintf (stderr, "%s\n", status);
4087
        }
4088
      dyn_string_delete (result);
4089
    }
4090
 
4091
  return 0;
4092
}
4093
 
4094
#endif /* STANDALONE_DEMANGLER */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.