📄 edg-decode.c
字号:
/******************************************************************************* \ ___ / ** / \ ** Edison Design Group C++/C Front End - | \^/ | - ** \ / ** / | | \ ** Copyright 1996-1999 Edison Design Group Inc. [_] ** *******************************************************************************//*Copyright (c) 1996-1999, Edison Design Group, Inc.Redistribution and use in source and binary forms are permittedprovided that the above copyright notice and this paragraph areduplicated in all source code forms. The name of Edison DesignGroup, Inc. may not be used to endorse or promote products derivedfrom this software without specific prior written permission.THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS ORIMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIEDWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.Any use of this software is at the user's own risk.*//*edg-decode.c -- Name demangler for C++.The demangling is intended to work only on names of external entities.There is some name mangling done for internal entities, or by theC-generating back end, that this program does not try to decode.*/#include <stdio.h>#include <stddef.h>#include <string.h>#include <ctype.h>typedef size_t sizeof_t;typedef int a_boolean;#define FALSE 0#define TRUE 1/*Block used to hold state variables. A block is used so that these routineswill be reentrant.*/typedef struct a_decode_control_block *a_decode_control_block_ptr;typedef struct a_decode_control_block { unsigned long input_id_len; /* Length of the input identifier, not counting the final null. */ char *output_id; /* Pointer to buffer for demangled version of the current identifier. */ sizeof_t output_id_len; /* Length of output_id, not counting the final null. */ sizeof_t output_id_size; /* Allocated size of output_id. */ a_boolean err_in_id; /* TRUE if any error was encountered in the current identifier. */ a_boolean output_overflow_err; /* TRUE if the demangled output overflowed the output buffer. */ unsigned long suppress_id_output; /* If > 0, demangled id output is suppressed. This might be because of an error or just as a way of avoiding output during some processing. */ char *end_of_constant; /* While scanning a constant, this can be set to the character after the end of the constant as an aid to disambiguation. NULL otherwise. */ sizeof_t uncompressed_length; /* If non-zero, the original name was compressed, and this indicates the length of the uncompressed (but still mangled) name. */#ifndef WRS_ORIG /* WRS LOCAL */ a_boolean suppress_function_params; /* TRUE if we do not want to see function parameters; used by GDB to compose a stack trace. */ a_boolean suppress_return_types; /* TRUE if we should avoid printing return types (since they don't participate in overloading). */ a_boolean sourcelike_template_params; /* TRUE if we should display template parameters so they look like a usage in program source code. */#endif} a_decode_control_block;/*Block that contains information used to control the output of templateparameter lists.*/typedef struct a_template_param_block *a_template_param_block_ptr;typedef struct a_template_param_block { unsigned long nesting_level; /* Number of levels of template nesting at this point (1 == top level). */ char *final_specialization; /* Set to point to the mangled encoding for the final specialization encountered while working from outermost template to innermost. NULL if no specialization has been found yet. */ a_boolean set_final_specialization; /* TRUE if final_specialization should be set while scanning. */ a_boolean actual_template_args_until_final_specialization; /* TRUE if template parameter names should not be put out. Reset when the final_specialization position is reached. */ a_boolean output_only_correspondences; /* TRUE if doing a post-pass to output only template parameter/argument correspondences and not anything else. suppress_id_output will have been incremented to suppress everything else, and gets decremented temporarily when correspondences are output. */ a_boolean first_correspondence; /* TRUE until the first template parameter/argument correspondence is put out. */ a_boolean use_old_form_for_template_output; /* TRUE if templates should be output in the old form that always puts actual argument values in template argument lists. */#ifndef WRS_ORIG /* WRS LOCAL */ a_boolean base_name_only; /* TRUE if we are printing a bare basename, without template parameters; this is used for printing the implicit names of Constructors and Destructors. */#endif} a_template_param_block;/*Declarations needed because of forward references:*/static char *demangle_name(char *ptr, unsigned long nchars, a_boolean stop_on_underscores, char *mclass, a_template_param_block_ptr temp_par_info, a_decode_control_block_ptr dctl);static char *demangle_name_with_preceding_length( char *ptr, a_template_param_block_ptr temp_par_info, a_decode_control_block_ptr dctl);static char *demangle_operation(char *ptr, a_decode_control_block_ptr dctl);static char *demangle_operator(char *ptr, int *mangled_length, a_boolean *takes_type);static char *demangle_type(char *ptr, a_decode_control_block_ptr dctl);static char *full_demangle_type_name(char *ptr, a_boolean base_name_only, a_template_param_block_ptr temp_par_info, a_decode_control_block_ptr dctl);static char *demangle_template_arguments( char *ptr, a_boolean partial_spec, a_template_param_block_ptr temp_par_info, a_decode_control_block_ptr dctl);/*Interface to full_demangle_type_name for the simple case.*/#define demangle_type_name(ptr, dctl) \ full_demangle_type_name((ptr), /*base_name_only=*/FALSE, \ /*temp_par_info=*/(a_template_param_block_ptr)NULL, \ (dctl))static char *full_demangle_identifier(char *ptr, unsigned long nchars, a_decode_control_block_ptr dctl);/* Interface to full_demangle_identifier for the simple case. */#define demangle_identifier(ptr, dctl) \ full_demangle_identifier((ptr), (unsigned long)0, (dctl))static void write_id_ch(char ch, a_decode_control_block_ptr dctl)/*Add the indicated character to the demangled version of the current identifier.*/{ if (!dctl->suppress_id_output) { if (!dctl->output_overflow_err) { /* Test for buffer overflow, leaving room for a terminating null. */ if (dctl->output_id_len >= dctl->output_id_size-1) { /* There's no room for the character in the buffer. */ dctl->output_overflow_err = TRUE; /* Make sure the (truncated) output is null-terminated. */ dctl->output_id[dctl->output_id_size-1] = '\0'; } else { /* No overflow; put the character in the buffer. */ dctl->output_id[dctl->output_id_len] = ch; } /* if */ } /* if */ /* Keep track of the number of characters (even if output has overflowed the buffer). */ dctl->output_id_len++; } /* if */} /* write_id_ch */static void write_id_str(char *str, a_decode_control_block_ptr dctl)/*Add the indicated string to the demangled version of the current identifier.*/{ char *p = str; if (!dctl->suppress_id_output) { for (; *p != '\0'; p++) write_id_ch(*p, dctl); } /* if */} /* write_id_str */static void bad_mangled_name(a_decode_control_block_ptr dctl)/*A bad name mangling has been encountered. Record an error.*/{ if (!dctl->err_in_id) { dctl->err_in_id = TRUE; dctl->suppress_id_output++; } /* if */} /* bad_mangled_name */static a_boolean start_of_id_is(char *str, char *id)/*Return TRUE if the identifier (at id) begins with the string str.*/{ a_boolean is_start = FALSE; for (;;) { char chs = *str++; if (chs == '\0') { is_start = TRUE; break; } /* if */ if (chs != *id++) break; } /* for */ return is_start;} /* start_of_id_is */static char *advance_past_underscore(char *p, a_decode_control_block_ptr dctl)/*An underscore is expected at *p. If it's there, advance past it. Ifnot, call bad_mangled_name. In either case, return the updated value of p.*/{ if (*p == '_') { p++; } else { bad_mangled_name(dctl); } /* if */ return p;} /* advance_past_underscore */static char *get_length(char *p, unsigned long *num, a_decode_control_block_ptr dctl)/*Accumulate a number indicating a length, starting at position p, andreturn its value in *num. Return a pointer to the character positionfollowing the number.*/{ unsigned long n = 0; if (!isdigit((unsigned char)*p)) { bad_mangled_name(dctl); goto end_of_routine; } /* if */ do { n = n*10 + (*p - '0'); if (n > dctl->input_id_len) { /* Bad number. */ bad_mangled_name(dctl); n = dctl->input_id_len; goto end_of_routine; } /* if */ p++; } while (isdigit((unsigned char)*p));end_of_routine: *num = n; return p;} /* get_length */static char *get_number(char *p, unsigned long *num, a_decode_control_block_ptr dctl)/*Accumulate a number starting at position p and return its value in *num.Return a pointer to the character position following the number.*/{ unsigned long n = 0; if (!isdigit((unsigned char)*p)) { bad_mangled_name(dctl); goto end_of_routine; } /* if */ do { n = n*10 + (*p - '0'); p++; } while (isdigit((unsigned char)*p));end_of_routine: *num = n; return p;} /* get_number */static char *get_single_digit_number(char *p, unsigned long *num, a_decode_control_block_ptr dctl)/*Accumulate a number starting at position p and return its value in *num.The number is a single digit. Return a pointer to the character positionfollowing the number.*/{ *num = 0; if (!isdigit((unsigned char)*p)) { bad_mangled_name(dctl); goto end_of_routine; } /* if */ *num = (*p - '0'); p++;end_of_routine: return p;} /* get_single_digit_number */static char *get_length_with_optional_underscore( char *p, unsigned long *num, a_decode_control_block_ptr dctl)/*Accumulate a number starting at position p and return its value in *num.If the number has more than one digit, it is followed by an underscore.(Or, in a newer representation, surrounded by underscores.)Return a pointer to the character position following the number.*/{ if (*p == '_') { /* New encoding (not from cfront) -- the length is surrounded by
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -