edg-decode.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:93k
开发平台:

MultiPlatform

  1. /******************************************************************************
  2. *                                                               ___  /       *
  3. *                                                               /            *
  4. * Edison Design Group C++/C Front End                        - | ^/ | -      *
  5. *                                                                  /         *
  6. *                                                             /  | |         *
  7. * Copyright 1996-1999 Edison Design Group Inc.                   [_]          *
  8. *                                                                             *
  9. ******************************************************************************/
  10. /*
  11. Copyright (c) 1996-1999, Edison Design Group, Inc.
  12. Redistribution and use in source and binary forms are permitted
  13. provided that the above copyright notice and this paragraph are
  14. duplicated in all source code forms.  The name of Edison Design
  15. Group, Inc. may not be used to endorse or promote products derived
  16. from this software without specific prior written permission.
  17. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  18. IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  19. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20. Any use of this software is at the user's own risk.
  21. */
  22. /*
  23. edg-decode.c -- Name demangler for C++.
  24. The demangling is intended to work only on names of external entities.
  25. There is some name mangling done for internal entities, or by the
  26. C-generating back end, that this program does not try to decode.
  27. */
  28. #include <stdio.h>
  29. #include <stddef.h>
  30. #include <string.h>
  31. #include <ctype.h>
  32. typedef size_t sizeof_t;
  33. typedef int a_boolean;
  34. #define FALSE 0
  35. #define TRUE 1
  36. /*
  37. Block used to hold state variables.  A block is used so that these routines
  38. will be reentrant.
  39. */
  40. typedef struct a_decode_control_block *a_decode_control_block_ptr;
  41. typedef struct a_decode_control_block {
  42.   unsigned long
  43. input_id_len;
  44. /* Length of the input identifier, not counting the
  45.    final null. */
  46.   char *output_id;
  47. /* Pointer to buffer for demangled version of
  48.    the current identifier. */
  49.   sizeof_t output_id_len;
  50. /* Length of output_id, not counting the final
  51.    null. */
  52.   sizeof_t output_id_size;
  53. /* Allocated size of output_id. */
  54.   a_boolean err_in_id;
  55. /* TRUE if any error was encountered in the current
  56.    identifier. */
  57.   a_boolean output_overflow_err;
  58. /* TRUE if the demangled output overflowed the
  59.    output buffer. */
  60.   unsigned long suppress_id_output;
  61. /* If > 0, demangled id output is suppressed.  This
  62.    might be because of an error or just as a way
  63.    of avoiding output during some processing. */
  64.   char *end_of_constant;
  65. /* While scanning a constant, this can be set to the
  66.    character after the end of the constant as an
  67.    aid to disambiguation.  NULL otherwise. */
  68.   sizeof_t uncompressed_length;
  69. /* If non-zero, the original name was compressed,
  70.    and this indicates the length of the uncompressed
  71.    (but still mangled) name. */
  72. #ifndef WRS_ORIG /* WRS LOCAL */
  73.   a_boolean suppress_function_params;
  74. /* TRUE if we do not want to see function parameters;
  75.    used by GDB to compose a stack trace. */
  76.   a_boolean suppress_return_types;
  77. /* TRUE if we should avoid printing return types
  78.    (since they don't participate in overloading).  */
  79.   a_boolean sourcelike_template_params;
  80. /* TRUE if we should display template parameters so
  81.    they look like a usage in program source code.  */
  82. #endif
  83. } a_decode_control_block;
  84. /*
  85. Block that contains information used to control the output of template
  86. parameter lists.
  87. */
  88. typedef struct a_template_param_block *a_template_param_block_ptr;
  89. typedef struct a_template_param_block {
  90.   unsigned long nesting_level;
  91. /* Number of levels of template nesting at this
  92.    point (1 == top level). */
  93.   char *final_specialization;
  94. /* Set to point to the mangled encoding for the final
  95.    specialization encountered while working from
  96.    outermost template to innermost.  NULL if
  97.    no specialization has been found yet. */
  98.   a_boolean set_final_specialization;
  99. /* TRUE if final_specialization should be set while
  100.    scanning. */
  101.   a_boolean actual_template_args_until_final_specialization;
  102. /* TRUE if template parameter names should not be
  103.    put out.  Reset when the final_specialization
  104.    position is reached. */
  105.   a_boolean output_only_correspondences;
  106. /* TRUE if doing a post-pass to output only template
  107.    parameter/argument correspondences and not
  108.    anything else.  suppress_id_output will have been
  109.    incremented to suppress everything else, and
  110.    gets decremented temporarily when correspondences
  111.    are output. */
  112.   a_boolean first_correspondence;
  113. /* TRUE until the first template parameter/argument
  114.    correspondence is put out. */
  115.   a_boolean use_old_form_for_template_output;
  116. /* TRUE if templates should be output in the old
  117.    form that always puts actual argument values
  118.    in template argument lists. */
  119. #ifndef WRS_ORIG /* WRS LOCAL */
  120.   a_boolean base_name_only;
  121. /* TRUE if we are printing a bare basename, without
  122.    template parameters; this is used for printing the
  123.    implicit names of Constructors and Destructors. */
  124. #endif
  125. } a_template_param_block;
  126. /*
  127. Declarations needed because of forward references:
  128. */
  129. static char *demangle_name(char                       *ptr,
  130.                            unsigned long              nchars,
  131.                            a_boolean                  stop_on_underscores,
  132.                            char                       *mclass,
  133.                            a_template_param_block_ptr temp_par_info,
  134.                            a_decode_control_block_ptr dctl);
  135. static char *demangle_name_with_preceding_length(
  136.                                 char                       *ptr,
  137.                                 a_template_param_block_ptr temp_par_info,
  138.                                 a_decode_control_block_ptr dctl);
  139. static char *demangle_operation(char                       *ptr,
  140.                                 a_decode_control_block_ptr dctl);
  141. static char *demangle_operator(char      *ptr,
  142.                                int       *mangled_length,
  143.                                a_boolean *takes_type);
  144. static char *demangle_type(char                       *ptr,
  145.                            a_decode_control_block_ptr dctl);
  146. static char *full_demangle_type_name(char                       *ptr,
  147.                                      a_boolean                  base_name_only,
  148.                                      a_template_param_block_ptr temp_par_info,
  149.                                      a_decode_control_block_ptr dctl);
  150. static char *demangle_template_arguments(
  151.                                       char                       *ptr,
  152.                                       a_boolean                  partial_spec,
  153.                                       a_template_param_block_ptr temp_par_info,
  154.                                       a_decode_control_block_ptr dctl);
  155. /*
  156. Interface to full_demangle_type_name for the simple case.
  157. */
  158. #define demangle_type_name(ptr, dctl)                                 
  159.   full_demangle_type_name((ptr), /*base_name_only=*/FALSE,            
  160.                           /*temp_par_info=*/(a_template_param_block_ptr)NULL, 
  161.                           (dctl))
  162. static char *full_demangle_identifier(char                       *ptr,
  163.                                       unsigned long              nchars,
  164.                                       a_decode_control_block_ptr dctl);
  165. /* Interface to full_demangle_identifier for the simple case. */
  166. #define demangle_identifier(ptr, dctl)                                
  167.   full_demangle_identifier((ptr), (unsigned long)0, (dctl))
  168. static void write_id_ch(char                       ch,
  169.                         a_decode_control_block_ptr dctl)
  170. /*
  171. Add the indicated character to the demangled version of the current identifier.
  172. */
  173. {
  174.   if (!dctl->suppress_id_output) {
  175.     if (!dctl->output_overflow_err) {
  176.       /* Test for buffer overflow, leaving room for a terminating null. */
  177.       if (dctl->output_id_len >= dctl->output_id_size-1) {
  178.         /* There's no room for the character in the buffer. */
  179.         dctl->output_overflow_err = TRUE;
  180.         /* Make sure the (truncated) output is null-terminated. */
  181.         dctl->output_id[dctl->output_id_size-1] = '';
  182.       } else {
  183.         /* No overflow; put the character in the buffer. */
  184.         dctl->output_id[dctl->output_id_len] = ch;
  185.       }  /* if */
  186.     }  /* if */
  187.     /* Keep track of the number of characters (even if output has overflowed
  188.        the buffer). */
  189.     dctl->output_id_len++;
  190.   }  /* if */
  191. }  /* write_id_ch */
  192. static void write_id_str(char                      *str,
  193.                         a_decode_control_block_ptr dctl)
  194. /*
  195. Add the indicated string to the demangled version of the current identifier.
  196. */
  197. {
  198.   char *p = str;
  199.   if (!dctl->suppress_id_output) {
  200.     for (; *p != ''; p++) write_id_ch(*p, dctl);
  201.   }  /* if */
  202. }  /* write_id_str */
  203. static void bad_mangled_name(a_decode_control_block_ptr dctl)
  204. /*
  205. A bad name mangling has been encountered.  Record an error.
  206. */
  207. {
  208.   if (!dctl->err_in_id) {
  209.     dctl->err_in_id = TRUE;
  210.     dctl->suppress_id_output++;
  211.   }  /* if */
  212. }  /* bad_mangled_name */
  213. static a_boolean start_of_id_is(char *str, char *id)
  214. /*
  215. Return TRUE if the identifier (at id) begins with the string str.
  216. */
  217. {
  218.   a_boolean is_start = FALSE;
  219.   for (;;) {
  220.     char chs = *str++;
  221.     if (chs == '') {
  222.       is_start = TRUE;
  223.       break;
  224.     }  /* if */
  225.     if (chs != *id++) break;
  226.   }  /* for */
  227.   return is_start;
  228. }  /* start_of_id_is */
  229. static char *advance_past_underscore(char                       *p,
  230.                                      a_decode_control_block_ptr dctl)
  231. /*
  232. An underscore is expected at *p.  If it's there, advance past it.  If
  233. not, call bad_mangled_name.  In either case, return the updated value of p.
  234. */
  235. {
  236.   if (*p == '_') {
  237.     p++;
  238.   } else {
  239.     bad_mangled_name(dctl);
  240.   }  /* if */
  241.   return p;
  242. }  /* advance_past_underscore */
  243. static char *get_length(char                       *p,
  244.                         unsigned long              *num,
  245.                         a_decode_control_block_ptr dctl)
  246. /*
  247. Accumulate a number indicating a length, starting at position p, and
  248. return its value in *num.  Return a pointer to the character position
  249. following the number.
  250. */
  251. {
  252.   unsigned long n = 0;
  253.   if (!isdigit((unsigned char)*p)) {
  254.     bad_mangled_name(dctl);
  255.     goto end_of_routine;
  256.   }  /* if */
  257.   do {
  258.     n = n*10 + (*p - '0');
  259.     if (n > dctl->input_id_len) {
  260.       /* Bad number. */
  261.       bad_mangled_name(dctl);
  262.       n = dctl->input_id_len;
  263.       goto end_of_routine;
  264.     }  /* if */
  265.     p++;
  266.   } while (isdigit((unsigned char)*p));
  267. end_of_routine:
  268.   *num = n;
  269.   return p;
  270. }  /* get_length */
  271. static char *get_number(char                       *p,
  272.                         unsigned long              *num,
  273.                         a_decode_control_block_ptr dctl)
  274. /*
  275. Accumulate a number starting at position p and return its value in *num.
  276. Return a pointer to the character position following the number.
  277. */
  278. {
  279.   unsigned long n = 0;
  280.   if (!isdigit((unsigned char)*p)) {
  281.     bad_mangled_name(dctl);
  282.     goto end_of_routine;
  283.   }  /* if */
  284.   do {
  285.     n = n*10 + (*p - '0');
  286.     p++;
  287.   } while (isdigit((unsigned char)*p));
  288. end_of_routine:
  289.   *num = n;
  290.   return p;
  291. }  /* get_number */
  292. static char *get_single_digit_number(char                       *p,
  293.                                      unsigned long              *num,
  294.                                      a_decode_control_block_ptr dctl)
  295. /*
  296. Accumulate a number starting at position p and return its value in *num.
  297. The number is a single digit.  Return a pointer to the character position
  298. following the number.
  299. */
  300. {
  301.   *num = 0;
  302.   if (!isdigit((unsigned char)*p)) {
  303.     bad_mangled_name(dctl);
  304.     goto end_of_routine;
  305.   }  /* if */
  306.   *num = (*p - '0');
  307.   p++;
  308. end_of_routine:
  309.   return p;
  310. }  /* get_single_digit_number */
  311. static char *get_length_with_optional_underscore(
  312.                                                char                       *p,
  313.                                                unsigned long              *num,
  314.                                                a_decode_control_block_ptr dctl)
  315. /*
  316. Accumulate a number starting at position p and return its value in *num.
  317. If the number has more than one digit, it is followed by an underscore.
  318. (Or, in a newer representation, surrounded by underscores.)
  319. Return a pointer to the character position following the number.
  320. */
  321. {
  322.   if (*p == '_') {
  323.     /* New encoding (not from cfront) -- the length is surrounded by
  324.        underscores whether it's a single digit or several digits,
  325.        e.g., "L_10_1234567890". */
  326.     p++;
  327.     /* Multi-digit number followed by underscore. */
  328.     p = get_length(p, num, dctl);
  329.     p = advance_past_underscore(p, dctl);
  330.   } else if (isdigit((unsigned char)p[0]) && isdigit((unsigned char)p[1]) &&
  331.              (dctl->end_of_constant == NULL || p+2 < dctl->end_of_constant) &&
  332.              p[2] == '_') {
  333.     /* The cfront version -- a multi-digit length is followed by an
  334.        underscore, e.g., "L10_1234567890".  This doesn't work well because
  335.        something like "L11", intended to have a one-digit length, can
  336.        be made ambiguous by following it by a "_" for some other reason.
  337.        (That's resolved in most cases by the check against end_of_constant.)
  338.        So this form is not used in new cases where that can come up, e.g.,
  339.        nontype template arguments for functions.  In any case, interpret
  340.        "multi-digit" as "2-digit" and don't look further for the underscore. */
  341.     /* Multi-digit number followed by underscore. */
  342.     p = get_length(p, num, dctl);
  343.     p = advance_past_underscore(p, dctl);
  344.   } else {
  345.     /* Single-digit number not followed by underscore. */
  346.     p = get_single_digit_number(p, num, dctl);
  347.   }  /* if */
  348.   return p;
  349. }  /* get_length_with_optional_underscore */
  350. static a_boolean is_immediate_type_qualifier(char *p)
  351. /*
  352. Return TRUE if the encoding pointed to is one that indicates type
  353. qualification.
  354. */
  355. {
  356.   a_boolean is_type_qual = FALSE;
  357.   if (*p == 'C' || *p == 'V') {
  358.     /* This is a type qualifier. */
  359.     is_type_qual = TRUE;
  360.   }  /* if */
  361.   return is_type_qual;
  362. }  /* is_immediate_type_qualifier */
  363. static void write_template_parameter_name(unsigned long              depth,
  364.                                           unsigned long              position,
  365.                                           a_boolean                  nontype,
  366.                                           a_decode_control_block_ptr dctl)
  367. /*
  368. Output a representation of a template parameter with depth and position
  369. as indicated.  It's a nontype parameter if nontype is TRUE.
  370. */
  371. {
  372.   char buffer[100];
  373.   char letter = '';
  374.   if (nontype) {
  375.     /* Nontype parameter. */
  376.     /* Use a code letter for the first few levels, then the depth number. */
  377.     if (depth == 1) {
  378.       letter = 'N';
  379.     } else if (depth == 2) {
  380.       letter = 'O';
  381.     } else if (depth == 3) {
  382.       letter = 'P';
  383.     }  /* if */
  384.     if (letter != '') {
  385.       (void)sprintf(buffer, "%c%lu", letter, position);
  386.     } else {
  387.       (void)sprintf(buffer, "N_%lu_%lu", depth, position);
  388.     }  /* if */
  389.   } else {
  390.     /* Normal type parameter. */
  391.     /* Use a code letter for the first few levels, then the depth number. */
  392.     if (depth == 1) {
  393.       letter = 'T';
  394.     } else if (depth == 2) {
  395.       letter = 'U';
  396.     } else if (depth == 3) {
  397.       letter = 'V';
  398.     }  /* if */
  399.     if (letter != '') {
  400.       (void)sprintf(buffer, "%c%lu", letter, position);
  401.     } else {
  402.       (void)sprintf(buffer, "T_%lu_%lu", depth, position);
  403.     }  /* if */
  404.   }  /* if */
  405.   write_id_str(buffer, dctl);
  406. }  /* write_template_parameter_name */
  407. static char *demangle_template_parameter_name(
  408.                                             char                       *ptr,
  409.                                             a_boolean                  nontype,
  410.                                             a_decode_control_block_ptr dctl)
  411. /*
  412. Demangle a template parameter name at the indicated location.  The parameter
  413. is a nontype parameter if nontype is TRUE.  Return a pointer to the character
  414. position following what was demangled.
  415. */
  416. {
  417.   char          *p = ptr;
  418.   unsigned long position, depth = 1;
  419.   /* This comes up with the modern mangling for template functions.
  420.      Form is "ZnZ" or "Zn_mZ", where n is the parameter number and m
  421.      is the depth number (1 if not specified). */
  422.   p++;  /* Advance past the "Z". */
  423.   /* Get the position number. */
  424.   p = get_number(p, &position, dctl);
  425.   if (*p == '_' && p[1] != '_') {
  426.     /* Form including depth ("Zn_mZ"). */
  427.     p++;
  428.     p = get_number(p, &depth, dctl);
  429.   }  /* if */
  430.   /* Output the template parameter name. */
  431.   write_template_parameter_name(depth, position, nontype, dctl);
  432.   if (p[0] == '_' && p[1] == '_' && p[2] == 't' && p[3] == 'm' &&
  433.       p[4] == '_' && p[5] == '_') {
  434.     /* A template template parameter followed by a template
  435.        argument list. */
  436.     p = demangle_template_arguments(p+6, /*partial_spec=*/FALSE,
  437.                                     (a_template_param_block_ptr)NULL, dctl);
  438.   }  /* if */
  439.   /* Check for the final "Z".  This appears in the mangling to avoid
  440.      ambiguities when the template parameter is followed by something whose
  441.      encoding begins with a digit, e.g., a class name. */
  442.   if (*p != 'Z') {
  443.     bad_mangled_name(dctl);
  444.   } else {
  445.     p++;
  446.   }  /* if */
  447.   return p;
  448. }  /* demangle_template_parameter_name */
  449. static char *demangle_constant(char                       *ptr,
  450.                                a_decode_control_block_ptr dctl)
  451. /*
  452. Demangle a constant (e.g., a nontype template class argument) beginning at
  453. ptr, and output the demangled form.  Return a pointer to the character
  454. position following what was demangled.
  455. */
  456. {
  457.   char          *p = ptr, *type = NULL, *index;
  458.   unsigned long nchars;
  459.   /* A constant has a form like
  460.        CiL15   <-- integer constant 5
  461.            ^-- Literal constant representation.
  462.           ^--- Length of literal constant.
  463.          ^---- L indicates literal constant; c indicates address
  464.                of variable, etc.
  465.        ^^----- Type of template argument, with "const" added.
  466.      A template parameter constant or a constant expression does not have
  467.      the initial "C" and type.
  468.   */
  469.   if (*p == 'C') {
  470.     /* Advance past the type. */
  471.     type = p;
  472.     dctl->suppress_id_output++;
  473.     p = demangle_type(p, dctl);
  474.     dctl->suppress_id_output--;
  475.   }  /* if */
  476.   /* The next thing has one of the following forms:
  477.        3abc        Address of "abc".
  478.        L211        Literal constant; length ("2") followed by the characters of
  479.                    the constant ("11").
  480.        LM0_L2n1_1j Pointer-to-member-function constant; the three parts
  481.                    correspond to the triplet of values in the __mptr
  482.                    data structure.
  483.        Z1Z         Template parameter.
  484.        Opl2Z1ZZ2ZO Expression.
  485.   */
  486.   if (isdigit((unsigned char)*p)) {
  487.     /* A name preceded by its length, e.g., "3abc".  Put out "&name". */
  488.     write_id_ch('&', dctl);
  489.     /* Process the length and name. */
  490.     p = demangle_name_with_preceding_length(p,
  491.                                             (a_template_param_block_ptr)NULL,
  492.                                             dctl);
  493.   } else if (*p == 'L') {
  494.     if (p[1] != 'M') {
  495.       /* Normal literal constant.  Form is something like
  496.            L3n12     encoding for -12
  497.              ^^^---- Characters of constant.  Some characters get remapped:
  498.                        n --> -
  499.                        p --> +
  500.                        d --> .
  501.             ^------- Length of constant.
  502.          Output is
  503.            (type)constant
  504.          That is, the literal constant preceded by a cast to the right type.
  505.       */
  506.       /* See if the type is bool. */
  507.       a_boolean is_bool = (type+2 == p && *(type+1) == 'b'), is_nonzero;
  508.       /* If the type is bool, don't put out the cast. */
  509.       if (!is_bool) {
  510.         write_id_ch('(', dctl);
  511.         /* Start at type+1 to avoid the "C" for const. */
  512.         (void)demangle_type(type+1, dctl);
  513.         write_id_ch(')', dctl);
  514.       }  /* if */
  515.       p++;  /* Advance past the "L". */
  516.       /* Get the length of the constant. */
  517.       p = get_length_with_optional_underscore(p, &nchars, dctl);
  518.       /* Process the characters of the literal constant. */
  519.       is_nonzero = FALSE;
  520.       for (; nchars > 0; nchars--, p++) {
  521.         /* Remap characters where necessary. */
  522.         char ch = *p;
  523.         switch (ch) {
  524.           case '':
  525.           case '_':
  526.             /* Ran off end of string. */
  527.             bad_mangled_name(dctl);
  528.             goto end_of_routine;
  529.           case 'p':
  530.             ch = '+';
  531.             break;
  532.           case 'n':
  533.             ch = '-';
  534.             break;
  535.           case 'd':
  536.             ch = '.';
  537.             break;
  538.         }  /* switch */
  539.         if (is_bool) {
  540.           /* For the bool case, just keep track of whether the constant is
  541.              non-zero; true or false will be output later. */
  542.           if (ch != '0') is_nonzero = TRUE;
  543.         } else {
  544.           /* Normal (non-bool) case.  Output the character of the constant. */
  545.           write_id_ch(ch, dctl);
  546.         }  /* if */
  547.       }  /* for */
  548.       if (is_bool) {
  549.         /* For bool, output true or false. */
  550.         write_id_str((char *)(is_nonzero ? "true" : "false"), dctl);
  551.       }  /* if */
  552.     } else {
  553.       /* Pointer-to-member-function.  The form of the constant is
  554.            LM0_L2n1_1j  Non-virtual function
  555.            LM0_L11_0    Virtual function
  556.            LM0_L10_0    Null pointer
  557.          The three parts match the three components of the __mptr structure:
  558.          (delta, index, function or offset).  The index is -1 for a non-virtual
  559.          function, 0 for a null pointer, and greater than 0 for a virtual
  560.          function.  The index is represented like an integer constant (see
  561.          above).  For virtual functions, the last component is always "0"
  562.          even if the offset is not zero. */
  563.       /* Advance past the "LM". */
  564.       p += 2;
  565.       /* Advance over the first component, ignoring it. */
  566.       while (isdigit((unsigned char)*p)) p++;
  567.       p = advance_past_underscore(p, dctl);
  568.       /* The index component should be next. */
  569.       if (*p != 'L') {
  570.         bad_mangled_name(dctl);
  571.         goto end_of_routine;
  572.       }  /* if */
  573.       p++;
  574.       /* Get the index length. */
  575.       /* Note that get_length_with_optional_underscore is not used because
  576.          this is an ambiguous situation: an underscore follows the index
  577.          value, and there's no way to tell if it's the multi-digit
  578.          indicator for the length or the separator between fields. */
  579.       if (*p == '_') {
  580.         /* New-form encoding, no ambiguity. */
  581.         p = get_length_with_optional_underscore(p, &nchars, dctl);
  582.       } else {
  583.         p = get_single_digit_number(p, &nchars, dctl);
  584.       }  /* if */
  585.       /* Remember the start of the index. */
  586.       index = p;
  587.       /* Skip the rest of the index. */
  588.       while (isdigit((unsigned char)*p) || (*p == 'n')) p++;
  589.       p = advance_past_underscore(p, dctl);
  590.       /* If the index number starts with 'n', this is a non-virtual
  591.          function. */
  592.       if (*index == 'n') {
  593.         /* Non-virtual function. */
  594.         /* The third component is a name preceded by its length, e.g.,
  595.            "1f".  Put out "&A::f", where "A" is the class type retrieved
  596.            from the type. */
  597.         write_id_ch('&', dctl);
  598.         /* Start at type+2 to skip the "C" for const and the "M" for
  599.            pointer-to-member. */
  600.         (void)demangle_type_name(type+2, dctl);
  601.         write_id_str("::", dctl);
  602.         /* Demangle the length and name. */
  603.         p = demangle_name_with_preceding_length(p,
  604.                                               (a_template_param_block_ptr)NULL,
  605.                                                 dctl);
  606.       } else {
  607.         /* Not a non-virtual function.  The encoding for the third component
  608.            should be simply "0". */
  609.         if (*p != '0') {
  610.           bad_mangled_name(dctl);
  611.           goto end_of_routine;
  612.         }  /* if */
  613.         p++;
  614.         if (nchars == 1 && *index == '0') {
  615.           /* Null pointer constant.  Output "(type)0", that is, a zero cast
  616.              to the pointer-to-member type. */
  617.           write_id_ch('(', dctl);
  618.           (void)demangle_type(type, dctl);
  619.           write_id_str(")0", dctl);
  620.         } else {
  621.           /* Virtual function.  This case can't really be demangled properly,
  622.              because the mangled name doesn't have enough information.
  623.              Output "&A::virtual-function-n". */
  624.           write_id_ch('&', dctl);
  625.           /* Start at type+2 to skip the "C" for const and the "M" for
  626.              pointer-to-member. */
  627.           (void)demangle_type_name(type+2, dctl);
  628.           write_id_str("::", dctl);
  629.           write_id_str("virtual-function-", dctl);
  630.           /* Write the index number. */
  631.           for (; nchars > 0; nchars--, index++) write_id_ch(*index, dctl);
  632.         }  /* if */
  633.       }  /* if */
  634.     }  /* if */
  635.   } else if (*p == 'Z') {
  636.     /* A template parameter. */
  637.     p = demangle_template_parameter_name(p, /*nontype=*/TRUE, dctl);
  638.   } else if (*p == 'O') {
  639.     /* An operation. */
  640.     p = demangle_operation(p, dctl);
  641.   } else {
  642.     /* The constant starts with something unexpected. */
  643.     bad_mangled_name(dctl);
  644.   }  /* if */
  645. end_of_routine:
  646.   return p;
  647. }  /* demangle_constant */
  648. static char *demangle_operation(char                       *ptr,
  649.                                 a_decode_control_block_ptr dctl)
  650. /*
  651. Demangle an operation in a constant expression (these come up in template
  652. arguments and array sizes, in template function parameter lists) beginning
  653. at ptr, and output the demangled form.  Return a pointer to the character
  654. position following what was demangled.
  655. */
  656. {
  657.   char          *p = ptr, *operator_str;
  658.   int           op_length;
  659.   unsigned long num_operands;
  660.   a_boolean     takes_type;
  661.   /* An operation has the form
  662.        Opl2Z1ZZ2ZO <-- "Z1 + Z2", Z1/Z2 indicating nontype template parameters.
  663.                  ^---- "O" to end the operation encoding.
  664.               ^^^----- Second operand.
  665.            ^^^-------- First operand.
  666.           ^----------- Count of operands.
  667.         ^^------------ Operation, using same encoding as for operator
  668.                        function names.
  669.        ^-------------- "O" for operation.
  670.   */
  671.   p++;  /* Advance past the "O". */
  672.   /* Decode the operator name, e.g., "pl" is "+". */
  673.   operator_str = demangle_operator(p, &op_length, &takes_type);
  674.   if (operator_str == NULL) {
  675.     bad_mangled_name(dctl);
  676.   } else {
  677.     p += op_length;
  678.     /* Put parentheses around the operation. */
  679.     write_id_ch('(', dctl);
  680.     /* For a cast, sizeof, or __ALIGNOF__, get the type. */
  681.     if (takes_type) {
  682.       if (strcmp(operator_str, "cast") == 0) {
  683.         write_id_ch('(', dctl);
  684.         operator_str = "";
  685.       } else {
  686.         write_id_str(operator_str, dctl);
  687.       }  /* if */
  688.       p = demangle_type(p, dctl);
  689.       write_id_ch(')', dctl);
  690.     }  /* if */
  691.     /* Get the count of operands. */
  692.     p = get_single_digit_number(p, &num_operands, dctl);
  693.     /* sizeof and __ALIGNOF__ take zero operands. */
  694.     if (num_operands != 0) {
  695.       if (num_operands == 1) {
  696.         /* Unary operator -- operator comes first. */
  697.         write_id_str(operator_str, dctl);
  698.       }  /* if */
  699.       /* Process the first operand. */
  700.       p = demangle_constant(p, dctl);
  701.       if (num_operands > 1) {
  702.         /* Binary and ternary operators -- operator comes after first
  703.            operand. */
  704.         write_id_str(operator_str, dctl);
  705.         /* Process the second operand. */
  706.         p = demangle_constant(p, dctl);
  707.         if (num_operands > 2) {
  708.           /* Ternary operand -- "?". */
  709.           write_id_ch(':', dctl);
  710.           /* Process the third operand. */
  711.           p = demangle_constant(p, dctl);
  712.         }  /* if */
  713.       }  /* if */
  714.     }  /* if */
  715.     write_id_ch(')', dctl);
  716.     /* Check for the final "O". */
  717.     if (*p != 'O') {
  718.       bad_mangled_name(dctl);
  719.     } else {
  720.       p++;
  721.     }  /* if */
  722.   }  /* if */
  723.   return p;
  724. }  /* demangle_operation */
  725. static void clear_template_param_block(a_template_param_block_ptr tpbp)
  726. /*
  727. Clear the fields of the indicated template parameter block.
  728. */
  729. {
  730.   tpbp->nesting_level = 0;
  731.   tpbp->final_specialization = NULL;
  732.   tpbp->set_final_specialization = FALSE;
  733.   tpbp->actual_template_args_until_final_specialization = FALSE;
  734.   tpbp->output_only_correspondences = FALSE;
  735.   tpbp->first_correspondence = FALSE;
  736.   tpbp->use_old_form_for_template_output = FALSE;
  737.   tpbp->base_name_only = FALSE;
  738. }  /* clear_template_param_block */
  739. static char *demangle_template_arguments(
  740.                                       char                       *ptr,
  741.                                       a_boolean                  partial_spec,
  742.                                       a_template_param_block_ptr temp_par_info,
  743.                                       a_decode_control_block_ptr dctl)
  744. /*
  745. Demangle the template class arguments beginning at ptr and output the
  746. demangled form.  Return a pointer to the character position following what was
  747. demangled.  ptr points to just past the "__tm__", "__ps__", or "__pt__"
  748. string.  partial_spec is TRUE if this is a partial-specialization
  749. parameter list ("__ps__").  When temp_par_info != NULL, it points to a
  750. block that controls output of extra information on template parameters.
  751. */
  752. {
  753.   char          *p = ptr, *arg_base;
  754.   unsigned long nchars, position;
  755.   a_boolean     nontype, skipped, unskipped;
  756.   if (temp_par_info != NULL && !partial_spec) temp_par_info->nesting_level++;
  757.   /* A template argument list looks like
  758.        __tm__3_ii
  759.                ^^---- Argument types.
  760.              ^------- Size of argument types, including the underscore.
  761.              ^------- ptr points here.
  762.      For the first argument list of a partial specialization, "__tm__" is
  763.      replaced by "__ps__".  For old-form mangling of templates, "__tm__"
  764.      is replaced by "__pt__".
  765.   */
  766.   write_id_ch('<', dctl);
  767.   /* Scan the size. */
  768.   p = get_length(p, &nchars, dctl);
  769.   arg_base = p;
  770.   p = advance_past_underscore(p, dctl);
  771.   /* Loop to process the arguments. */
  772.   for (position = 1;; position++) {
  773.     if (dctl->err_in_id) break;  /* Avoid infinite loops on errors. */
  774.     if (*p == '' || *p == '_') {
  775.       /* We ran off the end of the string. */
  776.       bad_mangled_name(dctl);
  777.       break;
  778.     }  /* if */
  779.     /* "X" identifies the beginning of a nontype argument. */
  780.     nontype = (*p == 'X');
  781.     skipped = unskipped = FALSE;
  782.     if (!partial_spec && temp_par_info != NULL &&
  783.         !temp_par_info->use_old_form_for_template_output &&
  784.         !temp_par_info->actual_template_args_until_final_specialization) {
  785.       /* Doing something special: writing out the template parameter name. */
  786.       if (temp_par_info->output_only_correspondences) {
  787.         /* This is the second pass, which writes out parameter/argument
  788.            correspondences, e.g., "T1=int".  Output has been suppressed
  789.            in general, and is turned on briefly here. */
  790.         dctl->suppress_id_output--;
  791.         unskipped = TRUE;
  792.         /* Put out a comma between entries and a left bracket preceding the
  793.            first entry. */
  794.         if (temp_par_info->first_correspondence) {
  795.           write_id_str(" [with ", dctl);
  796.           temp_par_info->first_correspondence = FALSE;
  797.         } else {
  798.           write_id_str(", ", dctl);
  799.         }  /* if */
  800.       }  /* if */
  801.       /* Write the template parameter name. */
  802.       write_template_parameter_name(temp_par_info->nesting_level, position,
  803.                                     nontype, dctl);
  804.       if (temp_par_info->output_only_correspondences) {
  805.         /* This is the second pass, to write out correspondences, so put the
  806.            argument value out after the parameter name. */
  807.         write_id_ch('=', dctl);
  808.       } else {
  809.         /* This is the first pass.  The argument value is skipped.  In
  810.            the second pass, its value will be written out. */
  811.         /* We still have to scan over the argument value, but suppress
  812.            output. */
  813.         dctl->suppress_id_output++;
  814.         skipped = TRUE;
  815.       }  /* if */
  816.     }  /* if */
  817.     /* Write the argument value. */
  818.     if (nontype) {
  819.       /* Nontype argument. */
  820.       char *saved_end_of_constant = dctl->end_of_constant;
  821.       p++;  /* Advance past the "X". */
  822.       /* Note the end position of the constant.  This is used to decide
  823.          that certain lengths are implausible as a way to resolve
  824.          ambiguities. */
  825.       dctl->end_of_constant = arg_base + nchars;
  826.       p = demangle_constant(p, dctl);
  827.       dctl->end_of_constant = saved_end_of_constant;
  828.     } else {
  829.       /* Type argument. */
  830.       p = demangle_type(p, dctl);
  831.     }  /* if */
  832.     if (skipped) dctl->suppress_id_output--;
  833.     if (unskipped) dctl->suppress_id_output++;
  834.     /* Stop after the last argument. */
  835.     if ((p - arg_base) >= nchars) break;
  836.     write_id_str(", ", dctl);
  837.   }  /* for */
  838.   write_id_ch('>', dctl);
  839.   return p;
  840. }  /* demangle_template_arguments */
  841. static char *demangle_operator(char      *ptr,
  842.                                int       *mangled_length,
  843.                                a_boolean *takes_type)
  844. /*
  845. Examine the first few characters at ptr to see if they are an encoding for
  846. an operator (e.g., "pl" for plus).  If so, return a pointer to a string for
  847. the operator (e.g., "+"), set *mangled_length to the number of characters
  848. in the encoding, and *takes_type to TRUE if the operator takes a type
  849. modifier (e.g., cast).  If the first few characters are not an operator
  850. encoding, return NULL.
  851. */
  852. {
  853.   char *s;
  854.   int  len = 2;
  855.   *takes_type = FALSE;
  856.   /* The length-3 codes are tested first to avoid taking their first two
  857.      letters as one of the length-2 codes. */
  858.   if (start_of_id_is("apl", ptr)) {
  859.     s = "+=";
  860.     len = 3;
  861.   } else if (start_of_id_is("ami", ptr)) {
  862.     s = "-=";
  863.     len = 3;
  864.   } else if (start_of_id_is("amu", ptr)) {
  865.     s = "*=";
  866.     len = 3;
  867.   } else if (start_of_id_is("adv", ptr)) {
  868.     s = "/=";
  869.     len = 3;
  870.   } else if (start_of_id_is("amd", ptr)) {
  871.     s = "%=";
  872.     len = 3;
  873.   } else if (start_of_id_is("aer", ptr)) {
  874.     s = "^=";
  875.     len = 3;
  876.   } else if (start_of_id_is("aad", ptr)) {
  877.     s = "&=";
  878.     len = 3;
  879.   } else if (start_of_id_is("aor", ptr)) {
  880.     s = "|=";
  881.     len = 3;
  882.   } else if (start_of_id_is("ars", ptr)) {
  883.     s = ">>=";
  884.     len = 3;
  885.   } else if (start_of_id_is("als", ptr)) {
  886.     s = "<<=";
  887.     len = 3;
  888.   } else if (start_of_id_is("nwa", ptr)) {
  889.     s = "new[]";
  890.     len = 3;
  891.   } else if (start_of_id_is("dla", ptr)) {
  892.     s = "delete[]";
  893.     len = 3;
  894.   } else if (start_of_id_is("nw", ptr)) {
  895.     s = "new";
  896.   } else if (start_of_id_is("dl", ptr)) {
  897.     s = "delete";
  898.   } else if (start_of_id_is("pl", ptr)) {
  899.     s = "+";
  900.   } else if (start_of_id_is("mi", ptr)) {
  901.     s = "-";
  902.   } else if (start_of_id_is("ml", ptr)) {
  903.     s = "*";
  904.   } else if (start_of_id_is("dv", ptr)) {
  905.     s = "/";
  906.   } else if (start_of_id_is("md", ptr)) {
  907.     s = "%";
  908.   } else if (start_of_id_is("er", ptr)) {
  909.     s = "^";
  910.   } else if (start_of_id_is("ad", ptr)) {
  911.     s = "&";
  912.   } else if (start_of_id_is("or", ptr)) {
  913.     s = "|";
  914.   } else if (start_of_id_is("co", ptr)) {
  915.     s = "~";
  916.   } else if (start_of_id_is("nt", ptr)) {
  917.     s = "!";
  918.   } else if (start_of_id_is("as", ptr)) {
  919.     s = "=";
  920.   } else if (start_of_id_is("lt", ptr)) {
  921.     s = "<";
  922.   } else if (start_of_id_is("gt", ptr)) {
  923.     s = ">";
  924.   } else if (start_of_id_is("ls", ptr)) {
  925.     s = "<<";
  926.   } else if (start_of_id_is("rs", ptr)) {
  927.     s = ">>";
  928.   } else if (start_of_id_is("eq", ptr)) {
  929.     s = "==";
  930.   } else if (start_of_id_is("ne", ptr)) {
  931.     s = "!=";
  932.   } else if (start_of_id_is("le", ptr)) {
  933.     s = "<=";
  934.   } else if (start_of_id_is("ge", ptr)) {
  935.     s = ">=";
  936.   } else if (start_of_id_is("aa", ptr)) {
  937.     s = "&&";
  938.   } else if (start_of_id_is("oo", ptr)) {
  939.     s = "||";
  940.   } else if (start_of_id_is("pp", ptr)) {
  941.     s = "++";
  942.   } else if (start_of_id_is("mm", ptr)) {
  943.     s = "--";
  944.   } else if (start_of_id_is("cm", ptr)) {
  945.     s = ",";
  946.   } else if (start_of_id_is("rm", ptr)) {
  947.     s = "->*";
  948.   } else if (start_of_id_is("rf", ptr)) {
  949.     s = "->";
  950.   } else if (start_of_id_is("cl", ptr)) {
  951.     s = "()";
  952.   } else if (start_of_id_is("vc", ptr)) {
  953.     s = "[]";
  954.   } else if (start_of_id_is("qs", ptr)) {
  955.     s = "?";
  956.   } else if (start_of_id_is("cs", ptr)) {
  957.     s = "cast";
  958.     *takes_type = TRUE;
  959.   } else if (start_of_id_is("sz", ptr)) {
  960.     s = "sizeof(";
  961.     *takes_type = TRUE;
  962.   } else if (start_of_id_is("af", ptr)) {
  963.     s = "__ALIGNOF__(";
  964.     *takes_type = TRUE;
  965.   } else if (start_of_id_is("uu", ptr)) {
  966.     s = "__uuidof(";
  967.     *takes_type = TRUE;
  968.   } else {
  969.     s = NULL;
  970.   }  /* if */
  971.   *mangled_length = len;
  972.   return s;
  973. }  /* demangle_operator */
  974. static a_boolean is_operator_function_name(char *ptr,
  975.                                            char **demangled_name,
  976.                                            int  *mangled_length)
  977. /*
  978. Examine the string beginning at ptr to see if it is the mangled name for
  979. an operator function.  If so, return TRUE and set *demangled_name to
  980. the demangled form, and *mangled_length to the length of the mangled form.
  981. */
  982. {
  983.   char      *s, *end_ptr;
  984.   int       len;
  985.   a_boolean takes_type;
  986.   /* Get the operator name.*/
  987.   s = demangle_operator(ptr, &len, &takes_type);
  988.   if (s != NULL) {
  989.     /* Make sure we took the whole name and nothing more. */
  990.     end_ptr = ptr + len;
  991.     if (*end_ptr == '' || (end_ptr[0] == '_' && end_ptr[1] == '_')) {
  992.       /* Okay. */
  993.     } else {
  994.       s = NULL;
  995.     }  /* if */
  996.   }  /* if */
  997.   *demangled_name = s;
  998.   *mangled_length = len;
  999.   return (s != NULL);
  1000. }  /* demangle_operator_function_name */
  1001. static void note_specialization(char                       *ptr,
  1002.                                 a_template_param_block_ptr temp_par_info)
  1003. /*
  1004. Note the fact that a specialization indication has been encountered at ptr
  1005. while scanning a mangled name.  temp_par_info, if non-NULL, points to
  1006. a block of information related to template parameter processing.
  1007. */
  1008. {
  1009.   if (temp_par_info != NULL) {
  1010.     if (temp_par_info->set_final_specialization) {
  1011.       /* Remember the location of the last specialization seen. */
  1012.       temp_par_info->final_specialization = ptr;
  1013.     } else if (temp_par_info->actual_template_args_until_final_specialization&&
  1014.                ptr == temp_par_info->final_specialization) {
  1015.       /* Stop doing the special processing for specializations when the
  1016.          final specialization is reached. */
  1017.       temp_par_info->actual_template_args_until_final_specialization = FALSE;
  1018.     }  /* if */
  1019.   }  /* if */
  1020. }  /* note_specialization */
  1021. static char get_char(char          *ptr,
  1022.                      char          *base_ptr,
  1023.                      unsigned long nchars)
  1024. /*
  1025. Get and return the character pointed to by ptr.  However, if nchars is
  1026. non-zero, the string from which the character is to be extracted starts
  1027. at base_ptr and has length nchars.  An attempt to get a character past
  1028. the end of the string returns a null character.
  1029. */
  1030. {
  1031.   char ch;
  1032.   if (nchars > 0 && ptr >= base_ptr+nchars) {
  1033.     ch = '';
  1034.   } else {
  1035.     ch = *ptr;
  1036.   }  /* if */
  1037.   return ch;
  1038. }  /* get_char */
  1039. static char *demangle_name(char                       *ptr,
  1040.                            unsigned long              nchars,
  1041.                            a_boolean                  stop_on_underscores,
  1042.                            char                       *mclass,
  1043.                            a_template_param_block_ptr temp_par_info,
  1044.                            a_decode_control_block_ptr dctl)
  1045. /*
  1046. Demangle the name at ptr and output the demangled form.  Return a pointer
  1047. to the character position following what was demangled.  A "name" is
  1048. usually just a string of alphanumeric characters.  However, names of
  1049. constructors, destructors, and operator functions require special
  1050. handling, as do template entity names.  nchars indicates the number
  1051. of characters in the name, or is zero if the name is open-ended
  1052. (it's ended by a null or double underscore).  A double underscore
  1053. ends the name if stop_on_underscores is TRUE (though some sequences
  1054. beginning with two underscores, e.g., "__pt", end the name even if
  1055. stop_on_underscores is FALSE).  mclass, when non-NULL, points to
  1056. the mangled form of the class of which this name is a member.
  1057. When it's non-NULL, constructor and destructor names will be put
  1058. out in the proper form (otherwise, they are left in their original
  1059. forms).  When temp_par_info != NULL, it points to a block that
  1060. controls output of extra information on template parameters.
  1061. */
  1062. {
  1063.   char      *p, *end_ptr = NULL;
  1064.   a_boolean is_special_name = FALSE, is_pt, is_partial_spec = FALSE;
  1065.   a_boolean partial_spec_output_suppressed = FALSE;
  1066.   char      *demangled_name;
  1067.   int       mangled_length;
  1068.   /* See if the name is special in some way. */
  1069.   if ((nchars == 0 || nchars >= 4) && ptr[0] == '_' && ptr[1] == '_') {
  1070.     /* Name beginning with two underscores. */
  1071.     p = ptr + 2;
  1072.     if (start_of_id_is("ct", p)) {
  1073.       /* Constructor. */
  1074.       end_ptr = p + 2;
  1075.       if (mclass == NULL) {
  1076.         /* The mangled name for the class is not provided, so handle this as
  1077.            a normal name. */
  1078.       } else {
  1079.         /* Output the class name for the constructor name. */
  1080.         is_special_name = TRUE;
  1081.         (void)full_demangle_type_name(mclass, /*base_name_only=*/TRUE,
  1082.                                       /*temp_par_info=*/
  1083.                                               (a_template_param_block_ptr)NULL,
  1084.                                       dctl);
  1085.       }  /* if */
  1086.     } else if (start_of_id_is("dt", p)) {
  1087.       /* Destructor. */
  1088.       end_ptr = p + 2;
  1089.       if (mclass == NULL) {
  1090.         /* The mangled name for the class is not provided, so handle this as
  1091.            a normal name. */
  1092.       } else {
  1093.         /* Output ~class-name for the destructor name. */
  1094.         is_special_name = TRUE;
  1095.         write_id_ch('~', dctl);
  1096.         (void)full_demangle_type_name(mclass, /*base_name_only=*/TRUE,
  1097.                                       /*temp_par_info=*/
  1098.                                               (a_template_param_block_ptr)NULL,
  1099.                                       dctl);
  1100.       }  /* if */
  1101.     } else if (start_of_id_is("op", p)) {
  1102.       /* Conversion function.  Name looks like __opi__... where the part
  1103.          after "op" encodes the type (e.g., "opi" is "operator int"). */
  1104.       is_special_name = TRUE;
  1105.       write_id_str("operator ", dctl);
  1106.       end_ptr = demangle_type(p+2, dctl);
  1107.     } else if (is_operator_function_name(p, &demangled_name,
  1108.                                          &mangled_length)) {
  1109.       /* Operator function. */
  1110.       is_special_name = TRUE;
  1111.       write_id_str("operator ", dctl);
  1112.       write_id_str(demangled_name, dctl);
  1113.       end_ptr = p + mangled_length;
  1114.     } else if (nchars != 0 && start_of_id_is("N", p)) {
  1115.       /* __Nxxxx: unnamed namespace name.  Put out "<unnamed>" and ignore
  1116.          the characters after "__N". */
  1117.       is_special_name = TRUE;
  1118.       write_id_str("<unnamed>", dctl);
  1119.       end_ptr = p + nchars - 2;
  1120.     } else {
  1121.       /* Something unrecognized. */
  1122.     }  /* if */
  1123.   }  /* if */
  1124.   /* Here, end_ptr non-null means the end of the string has been found
  1125.      already (because the name is special in some way). */
  1126.   if (end_ptr == NULL) {
  1127.     /* Not a special name. Find the end of the string and set end_ptr.
  1128.        Also look for template-related things that terminate the name
  1129.        earlier. */
  1130.     for (p = ptr; ; p++) {
  1131.       char ch = get_char(p, ptr, nchars);
  1132.       /* Stop at the end of the string (real, or as indicated by nchars). */
  1133.       if (ch == '') break;
  1134.       /* Stop on a double underscore, but not one at the start of the string.
  1135.          More than 2 underscores in a row does not terminate the string,
  1136.          so that something like the name for "void f_()" (i.e., "f___Fv")
  1137.          can be demangled successfully. */
  1138.       if (ch == '_' && p != ptr &&
  1139.           get_char(p+1, ptr, nchars) == '_' &&
  1140.           get_char(p+2, ptr, nchars) != '_' &&
  1141.           /* When stop_on_underscores is FALSE, stop only on "__tm", "__ps",
  1142.              "__pt", or "__S".  Double underscores can appear in the middle
  1143.              of some names, e.g., member names used as template arguments. */
  1144.           (stop_on_underscores ||
  1145.            (get_char(p+2, ptr, nchars) == 't' &&
  1146.             get_char(p+3, ptr, nchars) == 'm') ||
  1147.            (get_char(p+2, ptr, nchars) == 'p' &&
  1148.             get_char(p+3, ptr, nchars) == 's') ||
  1149.            (get_char(p+2, ptr, nchars) == 'p' &&
  1150.             get_char(p+3, ptr, nchars) == 't') ||
  1151.            get_char(p+2, ptr, nchars) == 'S')) {
  1152.         break;
  1153.       }  /* if */
  1154.     }  /* for */
  1155.     end_ptr = p;
  1156.   }  /* if */
  1157.   /* Here, end_ptr indicates the character after the end of the initial
  1158.      part of the name. */
  1159.   if (!is_special_name) {
  1160.     /* Output the characters of the base name. */
  1161.     for (p = ptr; p < end_ptr; p++) write_id_ch(*p, dctl);
  1162.   }  /* if */
  1163.   /* If there's a template argument list for a partial specialization
  1164.      (beginning with "__ps__"), process it. */
  1165.   if ((nchars == 0 || (end_ptr-ptr+6) < nchars) &&
  1166.       start_of_id_is("__ps__", end_ptr)) {
  1167.     /* Write the arguments.  This first argument list gives the arguments
  1168.        that appear in the partial specialization declaration:
  1169.          template <class T, class U> struct A { ... };
  1170.          template <class T> struct A<T *, int> { ... };
  1171.                                      ^^^^^^^^this argument list
  1172.        This first argument list will be followed by another argument list
  1173.        that gives the arguments according to the partial specialization.
  1174.        For A<int *, int> according to the example above, the second
  1175.        argument list is <int>.  The second argument list is scanned but
  1176.        not put out, except when argument correspondences are output. */
  1177.     end_ptr = demangle_template_arguments(end_ptr+6, /*partial_spec=*/TRUE,
  1178.                                           temp_par_info, dctl);
  1179.     note_specialization(end_ptr, temp_par_info);
  1180.     is_partial_spec = TRUE;
  1181.   }  /* if */
  1182.   /* If there's a specialization indication ("__S"), ignore it. */
  1183.   if (get_char(end_ptr, ptr, nchars)   == '_' &&
  1184.       get_char(end_ptr+1, ptr, nchars) == '_' &&
  1185.       get_char(end_ptr+2, ptr, nchars) == 'S') {
  1186.     note_specialization(end_ptr, temp_par_info);
  1187.     end_ptr += 3;
  1188.   }  /* if */
  1189.   /* If there's a template argument list (beginning with "__pt__" or "__tm__"),
  1190.      process it. */
  1191.   if ((nchars == 0 || (end_ptr-ptr+6) < nchars) &&
  1192.       ((is_pt = start_of_id_is("__pt__", end_ptr)) ||
  1193.        start_of_id_is("__tm__", end_ptr))) {
  1194.     /* The "__pt__ form indicates an old-style mangled template name. */
  1195.     if (is_pt && temp_par_info != NULL ) {
  1196.       temp_par_info->use_old_form_for_template_output = TRUE;
  1197.     }  /* if */
  1198.     /* For the second argument list of a partial specialization,
  1199.        process the argument list but suppress output. */
  1200.     if (is_partial_spec && temp_par_info != NULL &&
  1201.         !temp_par_info->output_only_correspondences) {
  1202.       dctl->suppress_id_output++;
  1203.       partial_spec_output_suppressed = TRUE;
  1204.     }  /* if */
  1205.     /* Write the arguments. */
  1206. #ifndef WRS_ORIG /* WRS LOCAL */
  1207.     /* But not if we are printing an implicit Ctor/Dtor name! */
  1208.     if (temp_par_info != NULL && temp_par_info->base_name_only)
  1209.       dctl->suppress_id_output++;
  1210. #endif
  1211.     end_ptr = demangle_template_arguments(end_ptr+6, /*partial_spec=*/FALSE,
  1212.                                           temp_par_info, dctl);
  1213. #ifndef WRS_ORIG /* WRS LOCAL */
  1214.     if (temp_par_info != NULL && temp_par_info->base_name_only)
  1215.       dctl->suppress_id_output--;
  1216. #endif
  1217.     if (partial_spec_output_suppressed) dctl->suppress_id_output--;
  1218.     /* If there's a(nother) specialization indication ("__S"), ignore it. */
  1219.     if (get_char(end_ptr, ptr, nchars)   == '_' &&
  1220.         get_char(end_ptr+1, ptr, nchars) == '_' &&
  1221.         get_char(end_ptr+2, ptr, nchars) == 'S') {
  1222.       note_specialization(end_ptr, temp_par_info);
  1223.       end_ptr += 3;
  1224.     }  /* if */
  1225.   }  /* if */
  1226.   /* Check that we took exactly the characters we should have. */
  1227.   if (((nchars != 0) ? (end_ptr-ptr == nchars) : (*end_ptr == '')) ||
  1228.       (stop_on_underscores &&
  1229.        get_char(end_ptr,   ptr, nchars) == '_' &&
  1230.        get_char(end_ptr+1, ptr, nchars) == '_')) {
  1231.     /* Okay. */
  1232.   } else {
  1233.     bad_mangled_name(dctl);
  1234.   }  /* if */
  1235.   return end_ptr;
  1236. }  /* demangle_name */
  1237. static char *demangle_function_local_indication(
  1238.                                              char                       *ptr,
  1239.                                              unsigned long              nchars,
  1240.                                              a_decode_control_block_ptr dctl)
  1241. /*
  1242. Demangle the function name and block number in a function-local indication:
  1243.     __L2__f__Fv
  1244.                ^-- returned pointer points here
  1245.           ^------- mangled function name
  1246.        ^---------- block number within function (ptr points here on entry)
  1247. ptr points to the character after the "__L".  If nchars is non-zero, it
  1248. indicates the length of the string, starting from ptr.  Return a pointer
  1249. to the character following the mangled function name.  Output a function
  1250. indication like "f(void)::".
  1251. */
  1252. {
  1253.   char          *p = ptr;
  1254.   unsigned long block_number;
  1255.   /* Get the block number. */
  1256.   p = get_number(ptr, &block_number, dctl);
  1257.   /* Check for the two underscores following the block number. */
  1258.   if (p[0] != '_' || p[1] != '_') {
  1259.     bad_mangled_name(dctl);
  1260.   } else {
  1261.     p += 2;
  1262.   }  /* if */
  1263.   /* Put out the function name. */
  1264.   if (nchars != 0) nchars -= (p - ptr);
  1265.   p = full_demangle_identifier(p, nchars, dctl);
  1266.   /* Put out the block number if needed.  Block 0 is the top-level block
  1267.      of the function, and need not be identified. */
  1268.   if (block_number != 0) {
  1269.     char buffer[30];
  1270.     write_id_str("[block ", dctl);
  1271.     (void)sprintf(buffer, "%lu", block_number);
  1272.     write_id_str(buffer, dctl);
  1273.     write_id_ch(']', dctl);
  1274.   }  /* if */
  1275.   write_id_str("::", dctl);
  1276.   return p;
  1277. }  /* demangle_function_local_indication */
  1278. static char *demangle_name_with_preceding_length(
  1279.                                    char                       *ptr,
  1280.                                    a_template_param_block_ptr temp_par_info,
  1281.                                    a_decode_control_block_ptr dctl)
  1282. /*
  1283. Demangle a name that is preceded by a length, e.g., "3abc" for the type
  1284. name "abc".  Return a pointer to the character position following what
  1285. was demangled.  When temp_par_info != NULL, it points to a block that
  1286. controls output of extra information on template parameters.
  1287. */
  1288. {
  1289.   char          *p = ptr;
  1290.   char          *p2;
  1291.   unsigned long nchars, nchars2;
  1292.   a_boolean     has_function_local_info = FALSE;
  1293.   /* Get the length. */
  1294.   p = get_length(p, &nchars, dctl);
  1295.   if (nchars >= 8) {
  1296.     /* Look for a function-local indication, e.g., "__Ln__f" for block
  1297.        "n" of function "f". */
  1298.     for (p2 = p+1; p2+6 < p+nchars; p2++) {
  1299.       if (p2[0] == '_' && p2[1] == '_' && p2[2] == 'L') {
  1300.         has_function_local_info = TRUE;
  1301.         nchars2 = nchars;
  1302.         /* Set the length for the scan below to stop just before "__L". */
  1303.         nchars = p2 - p;
  1304.         p2 += 3;  /* Points to block number after "__L". */
  1305.         nchars2 -= (p2 - p);
  1306.         /* Scan and output the block number and function name. */
  1307.         p2 = demangle_function_local_indication(p2, nchars2, dctl);
  1308.         break;
  1309.       }  /* if */
  1310.     }  /* for */
  1311.   }  /* if */
  1312.   /* Demangle the name. */
  1313.   p = demangle_name(p, nchars, /*stop_on_underscores=*/FALSE,
  1314.                     (char *)NULL, temp_par_info, dctl);
  1315.   if (has_function_local_info) p = p2;
  1316.   return p;
  1317. }  /* demangle_name_with_preceding_length */
  1318. static char *demangle_simple_type_name(
  1319.                                    char                       *ptr,
  1320.                                    a_template_param_block_ptr temp_par_info,
  1321.                                    a_decode_control_block_ptr dctl)
  1322. /*
  1323. Demangle a type name (or namespace name) consisting of a length followed
  1324. by the name.  Return a pointer to the character position following what
  1325. was demangled.  The name is not a nested name, but it can have template
  1326. arguments.  When temp_par_info != NULL, it points to a block that
  1327. controls output of extra information on template parameters.
  1328. */
  1329. {
  1330.   char *p = ptr;
  1331.   if (*p == 'Z') {
  1332.     /* A template parameter name. */
  1333.     p = demangle_template_parameter_name(p, /*nontype=*/FALSE, dctl);
  1334.   } else {
  1335.     /* A simple mangled type name consists of digits indicating the length of
  1336.        the name followed by the name itself, e.g., "3abc". */
  1337.     p = demangle_name_with_preceding_length(p, temp_par_info, dctl);
  1338.   }  /* if */
  1339.   return p;
  1340. }  /* demangle_simple_type_name */
  1341. static char *full_demangle_type_name(char                       *ptr,
  1342.                                      a_boolean                  base_name_only,
  1343.                                      a_template_param_block_ptr temp_par_info,
  1344.                                      a_decode_control_block_ptr dctl)
  1345. /*
  1346. Demangle the type name at ptr and output the demangled form.  Return a pointer
  1347. to the character position following what was demangled.  The name can be
  1348. a simple type name or a nested type name, or the name of a namespace.
  1349. If base_name_only is TRUE, do not put out any nested type qualifiers,
  1350. e.g., put out "A::x" as simply "x".  When temp_par_info != NULL, it
  1351. points to a block that controls output of extra information on template
  1352. parameters.  Note that this routine is called for namespaces too
  1353. (the mangling is the same as for class names; you can't actually tell
  1354. the difference in a mangled name).  See demangle_type_name for an
  1355. interface to this routine for the simple case.
  1356. */
  1357. {
  1358.   char          *p = ptr;
  1359.   unsigned long nquals;
  1360.   if (*p == 'Q') {
  1361.     /* A nested type name has the form
  1362.          Q2_5outer5inner   (outer::inner)
  1363.             ^-----^--------Names from outermost to innermost
  1364.           ^----------------Number of levels of qualification.
  1365.        Note that the levels in the qualifier can be class names or namespace
  1366.        names. */
  1367.     p = get_number(p+1, &nquals, dctl);
  1368.     p = advance_past_underscore(p, dctl);
  1369.     /* Handle each level of qualification. */
  1370.     for (; nquals > 0; nquals--) {
  1371.       if (dctl->err_in_id) break;  /* Avoid infinite loops on errors. */
  1372.       /* Do not put out the nested type qualifiers if base_name_only is
  1373.          TRUE. */
  1374.       if (base_name_only && nquals != 1) dctl->suppress_id_output++;
  1375.       p = demangle_simple_type_name(p, temp_par_info, dctl);
  1376.       if (nquals != 1) write_id_str("::", dctl);
  1377.       if (base_name_only && nquals != 1) dctl->suppress_id_output--;
  1378.     }  /* for */
  1379.   } else {
  1380. #ifndef WRS_ORIG /* WRS LOCAL */
  1381.     a_template_param_block ctdt_temp_par_info;
  1382.     if (base_name_only)
  1383.       {
  1384. /* Also need to suppress template parameters when printing these! */
  1385. temp_par_info = &ctdt_temp_par_info;
  1386. clear_template_param_block(temp_par_info);
  1387. temp_par_info->base_name_only = TRUE;
  1388.       }
  1389.     /* N.B. when base_name_only is true, temp_par_info is also NULL.
  1390. We need it to pass down base_name_only, so we create a blank one
  1391. at this level. But note, we don't preserve temp_par_info so if you
  1392. add code that needs the old one, also add code to save/restore it. */
  1393. #endif
  1394.     /* A simple (non-nested) type name. */
  1395.     p = demangle_simple_type_name(p, temp_par_info, dctl);
  1396.   }  /* if */
  1397.   return p;
  1398. }  /* full_demangle_type_name */
  1399. static char *demangle_vtbl_class_name(char                       *ptr,
  1400.                                       a_decode_control_block_ptr dctl)
  1401. /*
  1402. Demangle a class or base class name that is one component of a virtual
  1403. function table name.  Such names are mangled mostly as types, but with
  1404. a few special quirks.
  1405. */
  1406. {
  1407.   char      *p = ptr;
  1408.   a_boolean nested_name_case = FALSE;
  1409.   /* If the name begins with a number, "Q", and another number, assume
  1410.      it's a name with a form like "7Q2_1A1B", which is used to encode
  1411.      A::B as the complete object class name component of a virtual
  1412.      function table name.  This doesn't have any particular sense to
  1413.      it; it's just what cfront does (and EDG's front end does the same
  1414.      at ABI versions >= 2.30 in cfront compatibility mode).  This could
  1415.      fail if the user actually has a class with a name that begins
  1416.      like "Q2_", but there's not much we can do about that. */
  1417.   if (isdigit((unsigned char)*p)) {
  1418.     do { p++; } while (isdigit((unsigned char)*p));
  1419.     if (*p == 'Q') {
  1420.       char *save_p = p;
  1421.       p++;
  1422.       if (isdigit((unsigned char)*p)) {
  1423.         do { p++; } while (isdigit((unsigned char)*p));
  1424.         if (*p == '_') {
  1425.           /* Yes, this is the strange nested name case.  Start the demangling
  1426.              at the "Q". */
  1427.           nested_name_case = TRUE;
  1428.           p = save_p;
  1429.         }  /* if */
  1430.       }  /* if */
  1431.     }  /* if */
  1432.   }  /* if */
  1433.   if (!nested_name_case) p = ptr;
  1434.   /* Now use the normal routine to demangle the class name. */
  1435.   p = demangle_type_name(p, dctl);
  1436.   return p;
  1437. }  /* demangle_vtbl_class_name */
  1438. static char *demangle_type_qualifiers(
  1439.                                      char                       *ptr,
  1440.                                      a_boolean                  trailing_space,
  1441.                                      a_decode_control_block_ptr dctl)
  1442. /*
  1443. Demangle any type qualifiers (const/volatile) at the indicated location.
  1444. Return a pointer to the character position following what was demangled.
  1445. If trailing_space is TRUE, add a space at the end if any qualifiers were
  1446. put out.
  1447. */
  1448. {
  1449.   char      *p = ptr;
  1450.   a_boolean any_quals = FALSE;
  1451.   for (;; p++) {
  1452.     if (*p == 'C') {
  1453.       if (any_quals) write_id_ch(' ', dctl);
  1454.       write_id_str("const", dctl);
  1455.     } else if (*p == 'V') {
  1456.       if (any_quals) write_id_ch(' ', dctl);
  1457.       write_id_str("volatile", dctl);
  1458.     } else {
  1459.       break;
  1460.     }  /* if */
  1461.     any_quals = TRUE;
  1462.   }  /* for */
  1463.   if (any_quals && trailing_space) write_id_ch(' ', dctl);
  1464.   return p;
  1465. }  /* demangle_type_qualifiers */
  1466. static char *demangle_type_specifier(char                       *ptr,
  1467.                                      a_decode_control_block_ptr dctl)
  1468. /*
  1469. Demangle the type at ptr and output the specifier part.  Return a pointer
  1470. to the character position following what was demangled.
  1471. */
  1472. {
  1473.   char *p = ptr, *s;
  1474.   /* Process type qualifiers. */
  1475.   p = demangle_type_qualifiers(p, /*trailing_space=*/TRUE, dctl);
  1476.   if (isdigit((unsigned char)*p) || *p == 'Q' || *p == 'Z') {
  1477.     /* Named type, like class or enum, e.g., "3abc". */
  1478.     p = demangle_type_name(p, dctl);
  1479.   } else {
  1480.     /* Builtin type. */
  1481.     /* Handle signed and unsigned. */
  1482.     if (*p == 'S') {
  1483.       write_id_str("signed ", dctl);
  1484.       p++;
  1485.     } else if (*p == 'U') {
  1486.       write_id_str("unsigned ", dctl);
  1487.       p++;
  1488.     }  /* if */
  1489.     switch (*p++) {
  1490.       case 'v':
  1491.         s = "void";
  1492.         break;
  1493.       case 'c':
  1494.         s = "char";
  1495.         break;
  1496.       case 'w':
  1497.         s = "wchar_t";
  1498.         break;
  1499.       case 'b':
  1500.         s = "bool";
  1501.         break;
  1502.       case 's':
  1503.         s = "short";
  1504.         break;
  1505.       case 'i':
  1506.         s = "int";
  1507.         break;
  1508.       case 'l':
  1509.         s = "long";
  1510.         break;
  1511.       case 'L':
  1512.         s = "long long";
  1513.         break;
  1514.       case 'f':
  1515.         s = "float";
  1516.         break;
  1517.       case 'd':
  1518.         s = "double";
  1519.         break;
  1520.       case 'r':
  1521.         s = "long double";
  1522.         break;
  1523.       case 'm':
  1524.         /* Microsoft intrinsic __intN types (Visual C++ 6.0 and later). */
  1525.         switch (*p++) {
  1526.           case '1':
  1527.             s = "__int8";
  1528.             break;
  1529.           case '2':
  1530.             s = "__int16";
  1531.             break;
  1532.           case '4':
  1533.             s = "__int32";
  1534.             break;
  1535.           case '8':
  1536.             s = "__int64";
  1537.             break;
  1538.           default:
  1539.             bad_mangled_name(dctl);
  1540.             s = "";
  1541.         }  /* switch */
  1542.         break;
  1543.       default:
  1544.         bad_mangled_name(dctl);
  1545.         s = "";
  1546.     }  /* switch */
  1547.     write_id_str(s, dctl);
  1548.   }  /* if */
  1549.   return p;
  1550. }  /* demangle_type_specifier */
  1551. static char *demangle_function_parameters(char                       *ptr,
  1552.                                           a_decode_control_block_ptr dctl)
  1553. /*
  1554. Demangle the parameter list beginning at ptr and output the demangled form.
  1555. Return a pointer to the character position following what was demangled.
  1556. */
  1557. {
  1558.   char      *p = ptr;
  1559.   char      *param_pos[10];
  1560.   unsigned  long curr_param_num, param_num, nreps;
  1561.   a_boolean any_params = FALSE;
  1562.   write_id_ch('(', dctl);
  1563.   if (*p == 'v') {
  1564.     /* Void parameter list. */
  1565.     p++;
  1566.   } else {
  1567.     any_params = TRUE;
  1568.     /* Loop for each parameter. */
  1569.     curr_param_num = 1;
  1570.     for (;;) {
  1571.       if (dctl->err_in_id) break;  /* Avoid infinite loops on errors. */
  1572.       if (*p == 'T' || *p == 'N') {
  1573.         /* Tn means repeat the type of parameter "n". */
  1574.         /* Nmn means "m" repetitions of the type of parameter "n".  "m"
  1575.            is a one-digit number. */
  1576.         /* "n" is also treated as a single-digit number; the front end enforces
  1577.            that (in non-cfront object code compatibility mode).  cfront does
  1578.            not, which leads to some ambiguities when "n" is followed by
  1579.            a class name. */
  1580.         if (*p++ == 'N') {
  1581.           /* Get the number of repetitions. */
  1582.           p = get_single_digit_number(p, &nreps, dctl);
  1583.         } else {
  1584.           nreps = 1;
  1585.         }  /* if */
  1586.         /* Get the parameter number. */
  1587.         p = get_single_digit_number(p, &param_num, dctl);
  1588.         if (param_num < 1 || param_num >= curr_param_num ||
  1589.             param_pos[param_num] == NULL) {
  1590.           /* Parameter number out of range. */
  1591.           bad_mangled_name(dctl);
  1592.           goto end_of_routine;
  1593.         }  /* if */
  1594.         /* Produce "nreps" copies of parameter "param_num". */
  1595.         for (; nreps > 0; nreps--) {
  1596.           if (dctl->err_in_id) break;  /* Avoid infinite loops on errors. */
  1597.           if (curr_param_num < 10) param_pos[curr_param_num] = NULL;
  1598.           (void)demangle_type(param_pos[param_num], dctl);
  1599.           if (nreps != 1) write_id_str(", ", dctl);
  1600.           curr_param_num++;
  1601.         }  /* if */
  1602.       } else {
  1603.         /* A normal parameter. */
  1604.         if (curr_param_num < 10) param_pos[curr_param_num] = p;
  1605.         p = demangle_type(p, dctl);
  1606.         curr_param_num++;
  1607.       }  /* if */
  1608.       /* Stop after the last parameter. */
  1609.       if (*p == '' || *p == 'e' || *p == '_') break;
  1610.       write_id_str(", ", dctl);
  1611.     }  /* for */
  1612.   }  /* if */
  1613.   if (*p == 'e') {
  1614.     /* Ellipsis. */
  1615.     if (any_params) write_id_str(", ", dctl);
  1616.     write_id_str("...", dctl);
  1617.     p++;
  1618.   }  /* if */
  1619.   write_id_ch(')', dctl);
  1620. end_of_routine:
  1621.   return p;
  1622. }  /* demangle_function_parameters */
  1623. static char *skip_extern_C_indication(char *ptr)
  1624. /*
  1625. ptr points to the character after the "F" of a function type.  Skip over
  1626. and ignore an indication of extern "C" following the "F", if one is present.
  1627. Return a pointer to the character following the extern "C" indication.
  1628. There's no syntax for representing the extern "C" in the function type, so
  1629. just ignore it.
  1630. */
  1631. {
  1632.   if (*ptr == 'K') ptr++;
  1633.   return ptr;
  1634. }  /* skip_extern_C_indication */
  1635. static char *demangle_type_first_part(
  1636.                                char                       *ptr,
  1637.                                a_boolean                  under_lhs_declarator,
  1638.                                a_boolean                  need_trailing_space,
  1639.                                a_decode_control_block_ptr dctl)
  1640. /*
  1641. Demangle the type at ptr and output the specifier part and the part of the
  1642. declarator that precedes the name.  Return a pointer to the character
  1643. position following what was demangled.  If under_lhs_declarator is TRUE,
  1644. this type is directly under a type that uses a left-side declarator,
  1645. e.g., a pointer type.  (That's used to control use of parentheses around
  1646. parts of the declarator.)  If need_trailing_space is TRUE, put a space
  1647. at the end of the specifiers part (needed if the declarator part is
  1648. not empty, because it contains a name or a derived type).
  1649. */
  1650. {
  1651.   char *p = ptr, *qualp = p;
  1652.   char kind;
  1653.   /* Remove type qualifiers. */
  1654.   while (is_immediate_type_qualifier(p)) p++;
  1655.   kind = *p;
  1656.   if (kind == 'P' || kind == 'R') {
  1657.     /* Pointer or reference type, e.g., "Pc" is pointer to char. */
  1658.     p = demangle_type_first_part(p+1, /*under_lhs_declarator=*/TRUE,
  1659.                                  /*need_trailing_space=*/TRUE, dctl);
  1660.     /* Output "*" or "&" for pointer or reference. */
  1661.     if (kind == 'R') {
  1662.       write_id_ch('&', dctl);
  1663.     } else {
  1664.       write_id_ch('*', dctl);
  1665.     }  /* if */
  1666.     /* Output the type qualifiers on the pointer, if any. */
  1667.     (void)demangle_type_qualifiers(qualp, /*trailing_space=*/TRUE, dctl);
  1668.   } else if (kind == 'M') {
  1669.     /* Pointer-to-member type, e.g., "M1Ai" is pointer to member of A of
  1670.        type int. */
  1671.     char *classp = p+1;
  1672.     /* Skip over the class name. */
  1673.     dctl->suppress_id_output++;
  1674.     p = demangle_type_name(classp, dctl);
  1675.     dctl->suppress_id_output--;
  1676.     p = demangle_type_first_part(p, /*under_lhs_declarator=*/TRUE,
  1677.                                  /*need_trailing_space=*/TRUE, dctl);
  1678.     /* Output Classname::*. */
  1679.     (void)demangle_type_name(classp, dctl);
  1680.     write_id_str("::*", dctl);
  1681.     /* Output the type qualifiers on the pointer, if any. */
  1682.     (void)demangle_type_qualifiers(qualp, /*trailing_space=*/TRUE, dctl);
  1683.   } else if (kind == 'F') {
  1684.     /* Function type, e.g., "Fii_f" is function(int, int) returning float.
  1685.        The return type is not present for top-level function types (except
  1686.        for template functions). */
  1687.     p = skip_extern_C_indication(p+1);
  1688.     /* Skip over the parameter types without outputting anything. */
  1689.     dctl->suppress_id_output++;
  1690.     p = demangle_function_parameters(p, dctl);
  1691.     dctl->suppress_id_output--;
  1692.     if (*p == '_' && p[1] != '_') {
  1693.       /* The return type is present. */
  1694. #ifndef WRS_ORIG /* WRS LOCAL */
  1695.       if (dctl->suppress_return_types) dctl->suppress_id_output++;
  1696. #endif
  1697.       p = demangle_type_first_part(p+1, /*under_lhs_declarator=*/FALSE,
  1698.                                    /*need_trailing_space=*/TRUE, dctl);
  1699. #ifndef WRS_ORIG /* WRS LOCAL */
  1700.       if (dctl->suppress_return_types) dctl->suppress_id_output--;
  1701. #endif
  1702.     }  /* if */
  1703.     /* This is a right-side declarator, so if it's under a left-side declarator
  1704.        parentheses are needed. */
  1705.     if (under_lhs_declarator) write_id_ch('(', dctl);
  1706.   } else if (kind == 'A') {
  1707.     /* Array type, e.g., "A10_i" is array[10] of int. */
  1708.     p++;
  1709.     if (*p == '_') {
  1710.       /* Length is specified by a constant expression based on template
  1711.          parameters.  Ignore the expression. */
  1712.       p++;
  1713.       dctl->suppress_id_output++;
  1714.       p = demangle_constant(p, dctl);
  1715.       dctl->suppress_id_output--;
  1716.     } else {
  1717.       /* Normal constant number of elements. */
  1718.       /* Skip the array size. */
  1719.       while (isdigit((unsigned char)*p)) p++;
  1720.     }  /* if */
  1721.     p = advance_past_underscore(p, dctl);
  1722.     /* Process the element type. */
  1723.     p = demangle_type_first_part(p, /*under_lhs_declarator=*/FALSE,
  1724.                                  /*need_trailing_space=*/TRUE, dctl);
  1725.     /* This is a right-side declarator, so if it's under a left-side declarator
  1726.        parentheses are needed. */
  1727.     if (under_lhs_declarator) write_id_ch('(', dctl);
  1728.   } else {
  1729.     /* No declarator part to process.  Handle the specifier type. */
  1730.     p = demangle_type_specifier(qualp, dctl);
  1731.     if (need_trailing_space) write_id_ch(' ', dctl);
  1732.   }  /* if */
  1733.   return p;
  1734. }  /* demangle_type_first_part */
  1735. static void demangle_type_second_part(
  1736.                                char                       *ptr,
  1737.                                a_boolean                  under_lhs_declarator,
  1738.                                a_decode_control_block_ptr dctl)
  1739. /*
  1740. Demangle the type at ptr and output the part of the declarator that follows the
  1741. name.  This routine does not return a pointer to the character position
  1742. following what was demangled; it is assumed that the caller will save
  1743. that from the call of demangle_type_first_part, and it saves a lot of
  1744. time if this routine can avoid scanning the specifiers again.
  1745. If under_lhs_declarator is TRUE, this type is directly under a type that
  1746. uses a left-side declarator, e.g., a pointer type.  (That's used to control
  1747. use of parentheses around parts of the declarator.)
  1748. */
  1749. {
  1750.   char *p = ptr, *qualp = p;
  1751.   char kind;
  1752.   /* Remove type qualifiers. */
  1753.   while (is_immediate_type_qualifier(p)) p++;
  1754.   kind = *p;
  1755.   if (kind == 'P' || kind == 'R') {
  1756.     /* Pointer or reference type, e.g., "Pc" is pointer to char. */
  1757.     demangle_type_second_part(p+1, /*under_lhs_declarator=*/TRUE, dctl);
  1758.   } else if (kind == 'M') {
  1759.     /* Pointer-to-member type, e.g., "M1Ai" is pointer to member of A of
  1760.        type int. */
  1761.     /* Advance over the class name. */
  1762.     dctl->suppress_id_output++;
  1763.     p = demangle_type_name(p+1, dctl);
  1764.     dctl->suppress_id_output--;
  1765.     demangle_type_second_part(p, /*under_lhs_declarator=*/TRUE, dctl);
  1766.   } else if (kind == 'F') {
  1767.     /* Function type, e.g., "Fii_f" is function(int, int) returning float.
  1768.        The return type is not present for top-level function types (except
  1769.        for template functions). */
  1770.     /* This is a right-side declarator, so if it's under a left-side declarator
  1771.        parentheses are needed. */
  1772.     if (under_lhs_declarator) write_id_ch(')', dctl);
  1773.     p = skip_extern_C_indication(p+1);
  1774.     /* Put out the parameter types. */
  1775. #ifndef WRS_ORIG /* WRS LOCAL */
  1776.     if (dctl->suppress_function_params) dctl->suppress_id_output++;
  1777. #endif
  1778.     p = demangle_function_parameters(p, dctl);
  1779. #ifndef WRS_ORIG /* WRS LOCAL */
  1780.     if (dctl->suppress_function_params) dctl->suppress_id_output--;
  1781. #endif
  1782.     /* Put out any cv-qualifiers (member functions). */
  1783.     /* Note that such things could come up on nonmember functions in the
  1784.        presence of typedefs.  In such a case what we generate here will not
  1785.        be valid C, but it's a reasonable representation of the mangled
  1786.        type, and there's no way of getting the typedef name in there,
  1787.        so let it be. */
  1788.     if (*qualp != 'F') {
  1789.       write_id_ch(' ', dctl);
  1790.       (void)demangle_type_qualifiers(qualp, /*trailing_space=*/FALSE, dctl);
  1791.     }  /* if */
  1792.     if (*p == '_' && p[1] != '_') {
  1793.       /* Process the return type. */
  1794.       demangle_type_second_part(p+1, /*under_lhs_declarator=*/FALSE, dctl);
  1795.     }  /* if */
  1796.   } else if (kind == 'A') {
  1797.     /* Array type, e.g., "A10_i" is array[10] of int. */
  1798.     /* This is a right-side declarator, so if it's under a left-side declarator
  1799.        parentheses are needed. */
  1800.     if (under_lhs_declarator) write_id_ch(')', dctl);
  1801.     write_id_ch('[', dctl);
  1802.     p++;
  1803.     if (*p == '_') {
  1804.       /* Length is specified by a constant expression based on template
  1805.          parameters. */
  1806.       p++;
  1807.       p = demangle_constant(p, dctl);
  1808.     } else {
  1809.       /* Normal constant number of elements. */
  1810.       if (*p == '0' && p[1] == '_') {
  1811.         /* Size is zero, so do not put out a size (the result is "[]"). */
  1812.         p++;
  1813.       } else {
  1814.         /* Put out the array size. */
  1815.         while (isdigit((unsigned char)*p)) write_id_ch(*p++, dctl);
  1816.       }  /* if */
  1817.     }  /* if */
  1818.     p = advance_past_underscore(p, dctl);
  1819.     write_id_ch(']', dctl);
  1820.     /* Process the element type. */
  1821.     demangle_type_second_part(p, /*under_lhs_declarator=*/FALSE, dctl);
  1822.   } else {
  1823.     /* No declarator part to process.  No need to scan the specifiers type --
  1824.        it was done by demangle_type_first_part. */
  1825.   }  /* if */
  1826. }  /* demangle_type_second_part */
  1827. static char *demangle_type(char                       *ptr,
  1828.                            a_decode_control_block_ptr dctl)
  1829. /*
  1830. Demangle the type at ptr and output the demangled form.  Return a pointer to
  1831. the character position following what was demangled.
  1832. */
  1833. {
  1834.   char *p;
  1835.   /* Generate the specifier part of the type. */
  1836.   p = demangle_type_first_part(ptr, /*under_lhs_declarator=*/FALSE,
  1837.                                /*need_trailing_space=*/FALSE, dctl);
  1838.   /* Generate the declarator part of the type. */
  1839.   demangle_type_second_part(ptr, /*under_lhs_declarator=*/FALSE, dctl);
  1840.   return p;
  1841. }  /* demangle_type */
  1842. static char *full_demangle_identifier(char                       *ptr,
  1843.                                       unsigned long              nchars,
  1844.                                       a_decode_control_block_ptr dctl)
  1845. /*
  1846. Demangle the identifier at ptr and output the demangled form.  Return
  1847. a pointer to the character position following what was demangled.
  1848. If nchars > 0, take no more than that many characters.
  1849. */
  1850. {
  1851.   char          *p = ptr, *pname, *end_ptr, *function_local_end_ptr = NULL;
  1852.   char          *final_specialization, *end_ptr_first_scan;
  1853.   char          ch;
  1854.   a_boolean     member_function = TRUE;
  1855.   a_template_param_block
  1856.                 temp_par_info;
  1857.   clear_template_param_block(&temp_par_info);
  1858. #ifndef WRS_ORIG /* WRS LOCAL */
  1859.   if (dctl->sourcelike_template_params)
  1860.     temp_par_info.use_old_form_for_template_output = TRUE;
  1861. #endif
  1862.   /* Scan through the name (the first part of the mangled name) without
  1863.      generating output, to see what's beyond it.  Special processing is
  1864.      necessary for names of constructors, conversion routines, etc. */
  1865.   /* If the name has a specialization indication in it (which can happen for
  1866.      function names), note that fact. */
  1867.   temp_par_info.set_final_specialization = TRUE;
  1868.   dctl->suppress_id_output++;
  1869.   p = demangle_name(ptr, nchars, /*stop_on_underscores=*/TRUE,
  1870.                     (char *)NULL, &temp_par_info, dctl);
  1871.   dctl->suppress_id_output--;
  1872.   final_specialization = temp_par_info.final_specialization;
  1873.   clear_template_param_block(&temp_par_info);
  1874. #ifndef WRS_ORIG /* WRS LOCAL */
  1875.   if (dctl->sourcelike_template_params)
  1876.     temp_par_info.use_old_form_for_template_output = TRUE;
  1877. #endif
  1878.   temp_par_info.final_specialization = final_specialization;
  1879.   if (get_char(p, ptr, nchars) == '') {
  1880.     /* There is no mangled part of the name.  This happens for strange
  1881.        cases like
  1882.          extern "C" int operator +(A, A);
  1883.        which gets mangled as "__pl".  Just write out the name and stop. */
  1884.     end_ptr = demangle_name(ptr, nchars,
  1885.                             /*stop_on_underscores=*/TRUE,
  1886.                             (char *)NULL,
  1887.                             (a_template_param_block_ptr)NULL, dctl);
  1888.   } else {
  1889.     /* There's more.  There should be a "__" between the name and the
  1890.        additional mangled information. */
  1891.     if (get_char(p, ptr, nchars) != '_' || get_char(p+1, ptr, nchars) != '_') {
  1892.       bad_mangled_name(dctl);
  1893.       end_ptr = p;
  1894.       goto end_of_routine;
  1895.     }  /* if */
  1896.     end_ptr = p + 2;
  1897.     /* Now ptr points to the original-name part of the mangled name, and
  1898.        end_ptr points to the mangled-name part at the end.
  1899.          f__1AFv
  1900.             ^---- end_ptr
  1901.          ^------- ptr
  1902.        The mangled-name part is
  1903.          (a)  A class name for a static data member.
  1904.          (b)  A class name followed by "F" followed by the encoding for the
  1905.               parameter types for a member function.
  1906.          (c)  "F" followed by the encoding for the parameter types for a
  1907.               nonmember function.
  1908.          (d)  "L" plus a local block number, followed by the mangled function
  1909.               name, for a function-local entity.
  1910.        Members of namespaces are encoded similarly. */
  1911.     p = end_ptr;
  1912.     pname = NULL;
  1913.     ch = get_char(end_ptr, ptr, nchars);
  1914.     if (ch == 'L') {
  1915.       unsigned long nchars2 = nchars;
  1916.       /* The name of an entity within a function, mangled on promotion out
  1917.          of the function.  For example, "i__L1__f__Fv" for "i" from block 1
  1918.          of function "f(void)".  Note that this is not the same mangling
  1919.          used by cfront (in the cfront scheme, the __L1 is at the end, and
  1920.          the number is different). */
  1921.       /* Set a length for the name without the function-local indication,
  1922.          for the processing in the rest of this routine. */
  1923.       nchars = (p - 2) - ptr;
  1924.       /* Demangle the function name and block number. */
  1925.       p++;  /* Points to the block number following "__L". */
  1926.       if (nchars2 != 0) nchars2 -= (p - ptr);
  1927.       function_local_end_ptr =
  1928.                           demangle_function_local_indication(p, nchars2, dctl);
  1929.       p = end_ptr = ptr + nchars;
  1930.       member_function = FALSE;
  1931.       /* Go on to demangle the name of the local entity. */
  1932.     } else if (ch != 'F') {
  1933.       /* A class (or namespace) name must be next. */
  1934.       /* Remember the location of the parent entity name. */
  1935.       pname = end_ptr;
  1936.       /* Scan over the class name, producing no output, and remembering the
  1937.          position of the final specialization, if any.  If we already
  1938.          found a specialization on the function name, it's the final one
  1939.          and we shouldn't change it. */
  1940.       dctl->suppress_id_output++;
  1941.       if (temp_par_info.final_specialization == NULL) {
  1942.         temp_par_info.set_final_specialization = TRUE;
  1943.       }  /* if */
  1944.       end_ptr = full_demangle_type_name(pname, /*base_name_only=*/FALSE,
  1945.                                         &temp_par_info, dctl);
  1946.       temp_par_info.set_final_specialization = FALSE;
  1947.       dctl->suppress_id_output--;
  1948.       /* If the name ends here, this is a simple member (e.g., a static
  1949.          data member). */
  1950.       ch = get_char(end_ptr, ptr, nchars);
  1951.       if (ch == '' ||
  1952.           (ch == '_' && get_char(end_ptr+1, ptr, nchars) == '_')) {
  1953.         member_function = FALSE;
  1954.       }  /* if */
  1955.     }  /* if */
  1956.     if (member_function) {
  1957.       /* "S" here means a static member function (ignore). */
  1958.       if (get_char(end_ptr, ptr, nchars) == 'S') end_ptr++;
  1959.       /* Write the specifier part of the type. */
  1960.       end_ptr_first_scan =
  1961.                   demangle_type_first_part(end_ptr,
  1962.                                            /*under_lhs_declarator=*/FALSE,
  1963.                                            /*need_trailing_space=*/TRUE, dctl);
  1964.     }  /* if */
  1965.     temp_par_info.nesting_level = 0;
  1966.     if (pname != NULL) {
  1967.       /* Write the parent class or namespace qualifier. */
  1968.       if (temp_par_info.final_specialization != NULL) {
  1969.         /* Up to the final specialization, put out actual template arguments
  1970.            for specializations. */
  1971.         temp_par_info.actual_template_args_until_final_specialization = TRUE;
  1972.       }  /* if */
  1973.       (void)full_demangle_type_name(pname, /*base_name_only=*/FALSE,
  1974.                                     &temp_par_info, dctl);
  1975.       /* Force template parameter information out on the function even if
  1976.          it is specialized. */
  1977.       temp_par_info.actual_template_args_until_final_specialization = FALSE;
  1978.       write_id_str("::", dctl);
  1979.     }  /* if */
  1980.     /* Write the name of the member. */
  1981.     (void)demangle_name(ptr, nchars, /*stop_on_underscores=*/TRUE,
  1982.                         pname, &temp_par_info, dctl);
  1983.     if (member_function) {
  1984.       /* Write the declarator part of the type. */
  1985.       demangle_type_second_part(end_ptr, /*under_lhs_declarator=*/FALSE,
  1986.                                 dctl);
  1987.       end_ptr = end_ptr_first_scan;
  1988.     }  /* if */
  1989.     if (!temp_par_info.use_old_form_for_template_output &&
  1990.         temp_par_info.nesting_level != 0) {
  1991.       /* Put out correspondences for template parameters, e.g, "T=int". */
  1992.       temp_par_info.nesting_level = 0;
  1993.       temp_par_info.first_correspondence = TRUE;
  1994.       temp_par_info.output_only_correspondences = TRUE;
  1995.       /* Output is suppressed in general, and turned on only where
  1996.          appropriate. */
  1997.       dctl->suppress_id_output++;
  1998.       if (pname != NULL) {
  1999.         /* Write the parent class or namespace qualifier. */
  2000.         if (temp_par_info.final_specialization != NULL) {
  2001.           /* Up to the final specialization, put out actual template arguments
  2002.              for specializations. */
  2003.           temp_par_info.actual_template_args_until_final_specialization = TRUE;
  2004.         }  /* if */
  2005.         (void)full_demangle_type_name(pname, /*base_name_only=*/FALSE,
  2006.                                       &temp_par_info, dctl);
  2007.       }  /* if */
  2008.       /* Force template parameter information out on the function even if
  2009.          it is specialized. */
  2010.       temp_par_info.actual_template_args_until_final_specialization = FALSE;
  2011.       /* Write the name of the member. */
  2012.       (void)demangle_name(ptr, nchars, /*stop_on_underscores=*/TRUE,
  2013.                           pname, &temp_par_info, dctl);
  2014.       dctl->suppress_id_output--;
  2015.       if (!temp_par_info.first_correspondence) {
  2016.         /* End the list of correspondences. */
  2017.         write_id_ch(']', dctl);
  2018.       }  /* if */
  2019.     }  /* if */
  2020.   }  /* if */
  2021. end_of_routine:
  2022.   /* When a function-local indication is scanned, end_ptr has been set
  2023.      to the end of the local entity name, and needs to be set to after the
  2024.      function-local indication at the end of the whole name. */
  2025.   if (function_local_end_ptr != NULL) end_ptr = function_local_end_ptr;
  2026.   return end_ptr;
  2027. }  /* full_demangle_identifier */
  2028. static char *demangle_static_variable_name(char                       *ptr,
  2029.                                            a_decode_control_block_ptr dctl)
  2030. /*
  2031. Demangle the name of a static variable promoted to being external by
  2032. addition of a prefix "__STV__" and a suffix of a module id.  Just put out
  2033. the part in the middle, which is the original name.
  2034. */
  2035. {
  2036.   char *start_ptr;
  2037.   ptr += 7;  /* Move to after "__STV__". */
  2038.   /* Copy the name until "__". */
  2039.   start_ptr = ptr;
  2040.   while (*ptr != '_' || ptr[1] != '_' || ptr == start_ptr) {
  2041.     if (*ptr == '') {
  2042.       bad_mangled_name(dctl);
  2043.       break;
  2044.     }  /* if */
  2045.     write_id_ch(*ptr, dctl);
  2046.     ptr++;
  2047.   }  /* while */
  2048.   /* Advance over the module id part of the name. */
  2049.   while (*ptr != '') ptr++;
  2050.   return ptr;
  2051. }  /* demangle_static_variable_name */
  2052. static char *demangle_static_function_name(char                       *ptr,
  2053.                                            a_decode_control_block_ptr dctl)
  2054. /*
  2055. Demangle the name of a static function promoted to being external by
  2056. addition of a prefix "__STF__" and a suffix of a module id.  Just put out
  2057. the part in the middle, which is the original mangled name.
  2058. */
  2059. {
  2060.   ptr += 7;  /* Move to after "__STF__". */
  2061.   /* Demangle the function name. */
  2062.   ptr = demangle_identifier(ptr, dctl);
  2063.   /* Advance over the module id part of the name. */
  2064.   while (*ptr != '') ptr++;
  2065.   return ptr;
  2066. }  /* demangle_static_function_name */
  2067. static char *demangle_local_name(char                       *ptr,
  2068.                                  a_decode_control_block_ptr dctl)
  2069. /*
  2070. Demangle the local name at ptr and output the demangled form.  Return
  2071. a pointer to the character position following what was demangled.
  2072. This demangles the "__nn_mm_name" form produced by the C-generating
  2073. back end.  This is not something visible unless the C-generating back end
  2074. is used, and it's a local name, which is ordinarily outside the charter
  2075. of these demangling routines, but it's an easy and common case, so...
  2076. Also handles the cfront-style __nnName form.
  2077. */
  2078. {
  2079.   char *p = ptr+2;
  2080.   /* Check for the initial two numbers and underscores.  The caller checked
  2081.      for the two initial underscores and the digit following that. */
  2082.   do { p++; } while (isdigit((unsigned char)*p));
  2083.   if (isalpha((unsigned char)*p)) {
  2084.     /* Cfront-style local name, like "__2name". */
  2085.   } else {
  2086.     if (*p != '_') {
  2087.       bad_mangled_name(dctl);
  2088.       goto end_of_routine;
  2089.     }  /* if */
  2090.     p++;
  2091.     if (!isdigit((unsigned char)*p)) {
  2092.       bad_mangled_name(dctl);
  2093.       goto end_of_routine;
  2094.     }  /* if */
  2095.     do { p++; } while (isdigit((unsigned char)*p));
  2096.     if (*p != '_') {
  2097.       bad_mangled_name(dctl);
  2098.       goto end_of_routine;
  2099.     }  /* if */
  2100.     p++;
  2101.   }  /* if */
  2102.   /* Copy the rest of the string to output. */
  2103.   while (*p != '') {
  2104.     write_id_ch(*p, dctl);
  2105.     p++;
  2106.   }  /* while */
  2107. end_of_routine:
  2108.   return p;
  2109. }  /* demangle_local_name */
  2110. static char *uncompress_mangled_name(char                       *id,
  2111.                                      a_decode_control_block_ptr dctl)
  2112. /*
  2113. Uncompress the compressed mangled name beginning at id.  Return the
  2114. address of the uncompressed name.
  2115. */
  2116. {
  2117.   char          *uncompressed_name = id;
  2118.   unsigned long length;
  2119.   /* Advance past "__CPR". */
  2120.   id += 5;
  2121.   /* Accumulate the length of the uncompressed name. */
  2122.   if (!isdigit((unsigned char)*id)) {
  2123.     bad_mangled_name(dctl);
  2124.     goto end_of_routine;
  2125.   }  /* if */
  2126.   id = get_number(id, &length, dctl);
  2127.   /* Check for the two underscores following the length. */
  2128.   if (id[0] != '_' || id[1] != '_') {
  2129.     bad_mangled_name(dctl);
  2130.     goto end_of_routine;
  2131.   }  /* if */
  2132.   /* Save the uncompressed length so it can be used later in telling the
  2133.      caller how big a buffer is required. */
  2134.   dctl->uncompressed_length = length;
  2135.   id += 2;
  2136.   if (length+1 >= dctl->output_id_size) {
  2137.     /* The buffer supplied by the caller is too small to contain the
  2138.        uncompressed name. */
  2139.     dctl->output_overflow_err = TRUE;
  2140.     goto end_of_routine;
  2141.   } else {
  2142.     char *src, *dst;
  2143.     /* Uncompress to the end of the buffer supplied by the caller, then
  2144.        do the demangling in the space remaining at the beginning. */
  2145.     uncompressed_name = dctl->output_id+dctl->output_id_size-(length+1);
  2146.     dctl->output_id_size -= length+1;
  2147.     /* Set the "input length" -- really the output size -- now.  This
  2148.        is used for error checking on the numbers scanned in the decompression
  2149.        processing (which are positions in the uncompressed string, really,
  2150.        not in the input string). */
  2151.     dctl->input_id_len = length;
  2152.     dst = uncompressed_name;
  2153.     for (src = id; *src != '';) {
  2154.       char ch = *src++;
  2155.       if (ch != 'J') {
  2156.         /* Just copy this character. */
  2157.         *dst++ = ch;
  2158.       } else {
  2159.         if (*src == 'J') {
  2160.           /* "JJ" indicates a simple "J". */
  2161.           /* Simple "J". */
  2162.           *dst++ = 'J';
  2163.         } else {
  2164.           /* "JnnnJ" indicates a repetition of a string that appeared
  2165.              earlier, at position "nnn". */
  2166.           unsigned long pos, prev_len;
  2167.           char          *prev_str, *prev_str2;
  2168.           src = get_length(src, &pos, dctl);
  2169.           if (*src != 'J') {
  2170.             bad_mangled_name(dctl);
  2171.             goto end_of_routine;
  2172.           }  /* if */
  2173.           prev_str = uncompressed_name+pos;
  2174.           if (!isdigit(*prev_str)) {
  2175.             bad_mangled_name(dctl);
  2176.             goto end_of_routine;
  2177.           }  /* if */
  2178.           /* Get the length of the repeated string. */
  2179.           prev_str2 = get_length(prev_str, &prev_len, dctl);
  2180.           /* Copy the repeated string to the uncompressed output. */
  2181.           prev_str2 += prev_len;
  2182.           while (prev_str < prev_str2) *dst++ = *prev_str++;
  2183.         }  /* if */
  2184.         /* Advance past the final "J". */
  2185.         src++;
  2186.       }  /* if */
  2187.     }  /* for */
  2188.     if (dst - uncompressed_name != length) {
  2189.       /* The length didn't come out right. */
  2190.       bad_mangled_name(dctl);
  2191.     }  /* if */
  2192.     /* Add the final null. */
  2193.     *dst++ = '';
  2194.   }  /* if */
  2195. end_of_routine:;
  2196.   return uncompressed_name;
  2197. }  /* uncompress_mangled_name */
  2198. #ifndef WRS_ORIG /* WRS LOCAL */
  2199. /* Forward decl to new enhanced entry point. */
  2200. void decode_identifier_styled(char      *id,
  2201.       int       act_like_gnu,
  2202.       int       suppress_function_params,
  2203.       char      *output_buffer,
  2204.       sizeof_t  output_buffer_size,
  2205.       a_boolean *err,
  2206.       a_boolean *buffer_overflow_err,
  2207.       sizeof_t  *required_buffer_size);
  2208. #endif
  2209. void decode_identifier(char      *id,
  2210.                        char      *output_buffer,
  2211.                        sizeof_t  output_buffer_size,
  2212.                        a_boolean *err,
  2213.                        a_boolean *buffer_overflow_err,
  2214.                        sizeof_t  *required_buffer_size)
  2215. /*
  2216. Demangle the identifier id (which is null-terminated), and put the demangled
  2217. form (null-terminated) into the output_buffer provided by the caller.
  2218. output_buffer_size gives the allocated size of output_buffer.  If there
  2219. is some error in the demangling process, *err will be returned TRUE.
  2220. In addition, if the error is that the output buffer is too small,
  2221. *buffer_overflow_err will (also) be returned TRUE, and *required_buffer_size
  2222. is set to the size of buffer required to do the demangling.  Note that
  2223. if the mangled name is compressed, and the buffer size is smaller than
  2224. the size of the uncompressed mangled name, the size returned will be
  2225. enough to uncompress the name but not enough to produce the demangled form.
  2226. The caller must be prepared in that case to loop a second time (the
  2227. length returned the second time will be correct).
  2228. */
  2229. #ifndef WRS_ORIG /* WRS LOCAL */
  2230. {
  2231.   decode_identifier_styled(id, /* act_like_gnu= */ 0,
  2232.    /* suppress_function_params= */ 0,
  2233.    output_buffer, output_buffer_size,
  2234.    err, buffer_overflow_err, required_buffer_size);
  2235. }
  2236. void decode_identifier_styled(char      *id,
  2237.       int       act_like_gnu,
  2238.       int       suppress_function_params,
  2239.       char      *output_buffer,
  2240.       sizeof_t  output_buffer_size,
  2241.       a_boolean *err,
  2242.       a_boolean *buffer_overflow_err,
  2243.       sizeof_t  *required_buffer_size)
  2244. #endif
  2245. {
  2246.   char                       *end_ptr, *p;
  2247.   a_decode_control_block     control_block;
  2248.   a_decode_control_block_ptr dctl = &control_block;
  2249.   /* Set global variables. */
  2250.   dctl->input_id_len = strlen(id);
  2251.   dctl->output_id = output_buffer;
  2252.   dctl->output_id_len = 0;
  2253.   dctl->output_id_size = output_buffer_size;
  2254.   dctl->err_in_id = FALSE;
  2255.   dctl->output_overflow_err = FALSE;
  2256.   dctl->suppress_id_output = 0;
  2257.   dctl->end_of_constant = NULL;
  2258.   dctl->uncompressed_length = 0;
  2259. #ifndef WRS_ORIG /* WRS LOCAL */
  2260.   dctl->suppress_function_params = suppress_function_params ? TRUE : FALSE;
  2261.   dctl->suppress_return_types = act_like_gnu ? TRUE : FALSE;
  2262.   dctl->sourcelike_template_params = act_like_gnu ? TRUE : FALSE;
  2263. #endif
  2264.   if (start_of_id_is("__CPR", id)) {
  2265.     /* Uncompress a compressed name. */
  2266.     id = uncompress_mangled_name(id, dctl);
  2267.   }  /* if */
  2268.   /* Check for special cases. */
  2269.   if (dctl->output_overflow_err) {
  2270.     /* Previous error (not enough room in the buffer to uncompress). */
  2271.   } else if (start_of_id_is("__vtbl__", id)) {
  2272.     write_id_str("virtual function table for ", dctl);
  2273.     /* Note that if the first name is a base class name and it's not simple,
  2274.        this will produce output containing partially-mangled information.
  2275.        It's hard to do better given the cfront encoding form. */
  2276.     end_ptr = demangle_vtbl_class_name(id+8, dctl);
  2277.     if (start_of_id_is("__A", end_ptr)) {
  2278.       /* "__A" indicates an ambiguous base class. */
  2279.       write_id_str(" (ambiguous)", dctl);
  2280.       end_ptr += 3;
  2281.     }  /* if */
  2282.     if (start_of_id_is("__", end_ptr)) {
  2283.       /* Virtual function table for base class in derived class. */
  2284.       end_ptr += 2;
  2285.       write_id_str(" in ", dctl);
  2286.       end_ptr = demangle_vtbl_class_name(end_ptr, dctl);
  2287.     }  /* if */
  2288.     if (start_of_id_is("__", end_ptr)) {
  2289.       /* Further derived class. */
  2290.       end_ptr += 2;
  2291.       write_id_str(" in ", dctl);
  2292.       end_ptr = demangle_vtbl_class_name(end_ptr, dctl);
  2293.     }  /* if */
  2294.   } else if (start_of_id_is("__CBI__", id)) {
  2295.     write_id_str("can-be-instantiated flag for ", dctl);
  2296.     end_ptr = demangle_identifier(id+7, dctl);
  2297.   } else if (start_of_id_is("__DNI__", id)) {
  2298.     write_id_str("do-not-instantiate flag for ", dctl);
  2299.     end_ptr = demangle_identifier(id+7, dctl);
  2300.   } else if (start_of_id_is("__TIR__", id)) {
  2301.     write_id_str("template-instantiation-request flag for ", dctl);
  2302.     end_ptr = demangle_identifier(id+7, dctl);
  2303.   } else if (start_of_id_is("__LSG__", id)) {
  2304.     write_id_str("initialization guard variable for ", dctl);
  2305.     end_ptr = demangle_identifier(id+7, dctl);
  2306.   } else if (start_of_id_is("__TID_", id)) {
  2307.     write_id_str("type identifier for ", dctl);
  2308.     end_ptr = demangle_type(id+6, dctl);
  2309.   } else if (start_of_id_is("__T_", id)) {
  2310.     write_id_str("typeinfo for ", dctl);
  2311.     end_ptr = demangle_type(id+4, dctl);
  2312.   } else if (start_of_id_is("__VFE__", id)) {
  2313.     write_id_str("surrogate in class ", dctl);
  2314.     p = demangle_type(id+7, dctl);
  2315.     if (p[0] != '_' || p[1] != '_') {
  2316.       bad_mangled_name(dctl);
  2317.       end_ptr = p;
  2318.     } else {
  2319.       write_id_str(" for ", dctl);
  2320.       end_ptr = demangle_identifier(p+2, dctl);
  2321.     }  /* if */
  2322.   } else if (start_of_id_is("__Q", id)) {
  2323.     /* Nested class name. */
  2324.     end_ptr = demangle_type_name(id+2, dctl);
  2325.   } else if (start_of_id_is("__STV__", id)) {
  2326.     /* Static variable made external by addition of prefix "__STV__" and
  2327.        suffix of module id. */
  2328.     end_ptr = demangle_static_variable_name(id, dctl);
  2329.   } else if (start_of_id_is("__STF__", id)) {
  2330.     /* Static function made external by addition of prefix "__STF__" and
  2331.        suffix of module id. */
  2332.     end_ptr = demangle_static_function_name(id, dctl);
  2333.   } else if (start_of_id_is("__", id) && isdigit((unsigned char)id[2])) {
  2334.     /* Local variable mangled by the C-generating back end: __nn_mm_name,
  2335.        where "nn" and "mm" are decimal integers. */
  2336.     end_ptr = demangle_local_name(id, dctl);
  2337.   } else {
  2338.     /* Normal case: function name, static data member name, or
  2339.        name of type or variable promoted out of function. */
  2340.     end_ptr = demangle_identifier(id, dctl);
  2341.   }  /* if */
  2342.   if (dctl->output_overflow_err) {
  2343.     dctl->err_in_id = TRUE;
  2344.   } else {
  2345.     /* Add a terminating null. */
  2346.     dctl->output_id[dctl->output_id_len] = 0;
  2347.   }  /* if */
  2348.   /* Make sure the whole identifier was taken. */
  2349.   if (!dctl->err_in_id && *end_ptr != '') bad_mangled_name(dctl);
  2350.   *err = dctl->err_in_id;
  2351.   *buffer_overflow_err = dctl->output_overflow_err;
  2352.   *required_buffer_size = dctl->output_id_len + 1; /* +1 for final null. */
  2353.   /* If the name is compressed, we need room for the uncompressed
  2354.      form, and a null, in the buffer. */
  2355.   if (dctl->uncompressed_length != 0) {
  2356.     *required_buffer_size += dctl->uncompressed_length+1;
  2357.   }  /* if */
  2358. }  /* decode_identifier */
  2359. /******************************************************************************
  2360. *                                                               ___  /       *
  2361. *                                                               /            *
  2362. * Edison Design Group C++/C Front End                        - | ^/ | -      *
  2363. *                                                                  /         *
  2364. *                                                             /  | |         *
  2365. * Copyright 1996-1999 Edison Design Group Inc.                   [_]          *
  2366. *                                                                             *
  2367. ******************************************************************************/