#include <stdio.h>#include <ctype.h>#include <bfd.h>#include "bucomm.h"#include <libiberty.h>#include "demangle.h"#include "debug.h"#include "budbg.h"#include "aout/aout64.h"#include "aout/stab_gnu.h"Include dependency graph for stabs.c:

Classes | |
| struct | stab_handle |
| struct | stab_pending_var |
| struct | stab_types |
| struct | stab_tag |
| struct | bincl_file |
| struct | stab_demangle_typestring |
| struct | stab_demangle_info |
Defines | |
| #define | BYTES_IN_WORD 4 |
| #define | XCOFF_TYPE_COUNT 34 |
| #define | STAB_TYPES_SLOTS (16) |
| #define | LLLOW "01000000000000000000000;" |
| #define | LLHIGH "0777777777777777777777;" |
| #define | ULLHIGH "01777777777777777777777;" |
Functions | |
| char *savestring | PARAMS ((const char *, int)) |
| bfd_vma parse_number | PARAMS ((const char **, bfd_boolean *)) |
| void bad_stab | PARAMS ((const char *)) |
| void warn_stab | PARAMS ((const char *, const char *)) |
| bfd_boolean parse_stab_string | PARAMS ((PTR, struct stab_handle *, int, int, bfd_vma, const char *)) |
| debug_type parse_stab_type | PARAMS ((PTR, struct stab_handle *, const char *, const char **, debug_type **)) |
| bfd_boolean parse_stab_type_number | PARAMS ((const char **, int *)) |
| debug_type parse_stab_range_type | PARAMS ((PTR, struct stab_handle *, const char *, const char **, const int *)) |
| debug_type parse_stab_sun_builtin_type | PARAMS ((PTR, const char **)) |
| debug_type parse_stab_struct_type | PARAMS ((PTR, struct stab_handle *, const char *, const char **, bfd_boolean, const int *)) |
| bfd_boolean parse_stab_baseclasses | PARAMS ((PTR, struct stab_handle *, const char **, debug_baseclass **)) |
| bfd_boolean parse_stab_struct_fields | PARAMS ((PTR, struct stab_handle *, const char **, debug_field **, bfd_boolean *)) |
| bfd_boolean parse_stab_cpp_abbrev | PARAMS ((PTR, struct stab_handle *, const char **, debug_field *)) |
| bfd_boolean parse_stab_one_struct_field | PARAMS ((PTR, struct stab_handle *, const char **, const char *, debug_field *, bfd_boolean *)) |
| bfd_boolean parse_stab_members | PARAMS ((PTR, struct stab_handle *, const char *, const char **, const int *, debug_method **)) |
| debug_type parse_stab_argtypes | PARAMS ((PTR, struct stab_handle *, debug_type, const char *, const char *, debug_type, const char *, bfd_boolean, bfd_boolean, const char **)) |
| bfd_boolean parse_stab_tilde_field | PARAMS ((PTR, struct stab_handle *, const char **, const int *, debug_type *, bfd_boolean *)) |
| debug_type parse_stab_array_type | PARAMS ((PTR, struct stab_handle *, const char **, bfd_boolean)) |
| void push_bincl | PARAMS ((struct stab_handle *, const char *, bfd_vma)) |
| const char *pop_bincl | PARAMS ((struct stab_handle *)) |
| bfd_boolean stab_record_variable | PARAMS ((PTR, struct stab_handle *, const char *, debug_type, enum debug_var_kind, bfd_vma)) |
| bfd_boolean stab_emit_pending_vars | PARAMS ((PTR, struct stab_handle *)) |
| debug_type *stab_find_slot | PARAMS ((struct stab_handle *, const int *)) |
| debug_type stab_find_type | PARAMS ((PTR, struct stab_handle *, const int *)) |
| bfd_boolean stab_record_type | PARAMS ((PTR, struct stab_handle *, const int *, debug_type)) |
| debug_type stab_xcoff_builtin_type | PARAMS ((PTR, struct stab_handle *, int)) |
| debug_type stab_find_tagged_type | PARAMS ((PTR, struct stab_handle *, const char *, int, enum debug_type_kind)) |
| debug_type *stab_demangle_argtypes | PARAMS ((PTR, struct stab_handle *, const char *, bfd_boolean *)) |
| char * | savestring (char *start, int len) const |
| bfd_vma | parse_number (char **pp, bfd_boolean *poverflow) const |
| void | bad_stab (char *p) const |
| void | warn_stab (char *p, const char *err) const |
| PTR | start_stab (PTR dhandle, bfd *abfd, bfd_boolean sections, asymbol **syms, long symcount) |
| bfd_boolean | finish_stab (PTR dhandle, PTR handle) |
| bfd_boolean | parse_stab (PTR dhandle, PTR handle, int type, int desc, bfd_vma value, const char *string) |
| bfd_boolean | parse_stab_string (PTR dhandle, struct stab_handle *info, int stabtype, int desc, bfd_vma value, const char *string) |
| debug_type | parse_stab_type (PTR dhandle, struct stab_handle *info, const char *typename, const char **pp, debug_type **slotp) |
| bfd_boolean | parse_stab_type_number (char **pp, int *typenums) const |
| debug_type | parse_stab_range_type (PTR dhandle, struct stab_handle *info, const char *typename, const char **pp, const int *typenums) |
| debug_type | parse_stab_sun_builtin_type (PTR dhandle, const char **pp) |
| debug_type | parse_stab_sun_floating_type (PTR dhandle, const char **pp) |
| debug_type | parse_stab_enum_type (PTR dhandle, const char **pp) |
| debug_type | parse_stab_struct_type (PTR dhandle, struct stab_handle *info, const char *tagname, const char **pp, bfd_boolean structp, const int *typenums) |
| bfd_boolean | parse_stab_baseclasses (PTR dhandle, struct stab_handle *info, const char **pp, debug_baseclass **retp) |
| bfd_boolean | parse_stab_struct_fields (PTR dhandle, struct stab_handle *info, const char **pp, debug_field **retp, bfd_boolean *staticsp) |
| bfd_boolean | parse_stab_cpp_abbrev (PTR dhandle, struct stab_handle *info, const char **pp, debug_field *retp) |
| bfd_boolean | parse_stab_one_struct_field (PTR dhandle, struct stab_handle *info, const char **pp, const char *p, debug_field *retp, bfd_boolean *staticsp) |
| bfd_boolean | parse_stab_members (PTR dhandle, struct stab_handle *info, const char *tagname, const char **pp, const int *typenums, debug_method **retp) |
| debug_type | parse_stab_argtypes (PTR dhandle, struct stab_handle *info, debug_type class_type, const char *fieldname, const char *tagname, debug_type return_type, const char *argtypes, bfd_boolean constp, bfd_boolean volatilep, const char **pphysname) |
| bfd_boolean | parse_stab_tilde_field (PTR dhandle, struct stab_handle *info, const char **pp, const int *typenums, debug_type *retvptrbase, bfd_boolean *retownvptr) |
| debug_type | parse_stab_array_type (PTR dhandle, struct stab_handle *info, const char **pp, bfd_boolean stringp) |
| void | push_bincl (struct stab_handle *info, const char *name, bfd_vma hash) |
| const char * | pop_bincl (struct stab_handle *info) |
| bfd_boolean | find_excl (struct stab_handle *info, const char *name, bfd_vma hash) |
| bfd_boolean | stab_record_variable (PTR dhandle, struct stab_handle *info, const char *name, debug_type type, enum debug_var_kind kind, bfd_vma val) |
| bfd_boolean | stab_emit_pending_vars (PTR dhandle, struct stab_handle *info) |
| debug_type * | stab_find_slot (struct stab_handle *info, const int *typenums) |
| debug_type | stab_find_type (PTR dhandle, struct stab_handle *info, const int *typenums) |
| bfd_boolean | stab_record_type (PTR dhandle, struct stab_handle *info, const int *typenums, debug_type type) |
| debug_type | stab_xcoff_builtin_type (PTR dhandle, struct stab_handle *info, int typenum) |
| debug_type | stab_find_tagged_type (PTR dhandle, struct stab_handle *info, const char *p, int len, enum debug_type_kind kind) |
| unsigned int stab_demangle_count | PARAMS ((const char **)) |
| bfd_boolean stab_demangle_get_count | PARAMS ((const char **, unsigned int *)) |
| bfd_boolean stab_demangle_prefix | PARAMS ((struct stab_demangle_info *, const char **)) |
| bfd_boolean stab_demangle_function_name | PARAMS ((struct stab_demangle_info *, const char **, const char *)) |
| bfd_boolean stab_demangle_qualified | PARAMS ((struct stab_demangle_info *, const char **, debug_type *)) |
| bfd_boolean stab_demangle_class | PARAMS ((struct stab_demangle_info *, const char **, const char **)) |
| bfd_boolean stab_demangle_args | PARAMS ((struct stab_demangle_info *, const char **, debug_type **, bfd_boolean *)) |
| bfd_boolean stab_demangle_arg | PARAMS ((struct stab_demangle_info *, const char **, debug_type **, unsigned int *, unsigned int *)) |
| bfd_boolean stab_demangle_remember_type | PARAMS ((struct stab_demangle_info *, const char *, int)) |
| void | stab_bad_demangle (char *s) const |
| unsigned int | stab_demangle_count (char **pp) const |
| bfd_boolean | stab_demangle_get_count (char **pp, unsigned int *pi) const |
| debug_type * | stab_demangle_argtypes (PTR dhandle, struct stab_handle *info, const char *physname, bfd_boolean *pvarargs) |
| bfd_boolean | stab_demangle_prefix (struct stab_demangle_info *minfo, const char **pp) |
| bfd_boolean | stab_demangle_function_name (struct stab_demangle_info *minfo, const char **pp, const char *scan) |
| bfd_boolean | stab_demangle_signature (struct stab_demangle_info *minfo, const char **pp) |
| bfd_boolean | stab_demangle_qualified (struct stab_demangle_info *minfo, const char **pp, debug_type *ptype) |
| bfd_boolean | stab_demangle_template (struct stab_demangle_info *minfo, const char **pp) |
| bfd_boolean | stab_demangle_class (struct stab_demangle_info *minfo, const char **pp, const char **pstart) |
| bfd_boolean | stab_demangle_args (struct stab_demangle_info *minfo, const char **pp, debug_type **pargs, bfd_boolean *pvarargs) |
| bfd_boolean | stab_demangle_arg (struct stab_demangle_info *minfo, const char **pp, debug_type **pargs, unsigned int *pcount, unsigned int *palloc) |
| bfd_boolean | stab_demangle_type (struct stab_demangle_info *minfo, const char **pp, debug_type *ptype) |
| bfd_boolean | stab_demangle_fund_type (struct stab_demangle_info *minfo, const char **pp, debug_type *ptype) |
| bfd_boolean | stab_demangle_remember_type (struct stab_demangle_info *minfo, const char *p, int len) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
00341 {
00342 fprintf (stderr, "Bad stab: %s\n", p);
00343 }
|
|
||||||||||||||||
|
03221 {
03222 struct bincl_file *l;
03223
03224 ++info->files;
03225 info->file_types = ((struct stab_types **)
03226 xrealloc ((PTR) info->file_types,
03227 (info->files
03228 * sizeof *info->file_types)));
03229
03230 for (l = info->bincl_list; l != NULL; l = l->next)
03231 if (l->hash == hash && strcmp (l->name, name) == 0)
03232 break;
03233 if (l == NULL)
03234 {
03235 warn_stab (name, "Undefined N_EXCL");
03236 info->file_types[info->files - 1] = NULL;
03237 return true;
03238 }
03239
03240 info->file_types[info->files - 1] = l->file_types;
03241
03242 return true;
03243 }
|
|
||||||||||||
|
00388 {
00389 struct stab_handle *info = (struct stab_handle *) handle;
00390 struct stab_tag *st;
00391
00392 if (info->within_function)
00393 {
00394 if (! stab_emit_pending_vars (dhandle, info)
00395 || ! debug_end_function (dhandle, info->function_end))
00396 return false;
00397 info->within_function = false;
00398 info->function_end = (bfd_vma) -1;
00399 }
00400
00401 for (st = info->tags; st != NULL; st = st->next)
00402 {
00403 enum debug_type_kind kind;
00404
00405 kind = st->kind;
00406 if (kind == DEBUG_KIND_ILLEGAL)
00407 kind = DEBUG_KIND_STRUCT;
00408 st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
00409 if (st->slot == DEBUG_TYPE_NULL)
00410 return false;
00411 }
00412
00413 return true;
00414 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||||
|
00234 {
00235 unsigned long ul;
00236 const char *orig;
00237
00238 if (poverflow != NULL)
00239 *poverflow = false;
00240
00241 orig = *pp;
00242
00243 errno = 0;
00244 ul = strtoul (*pp, (char **) pp, 0);
00245 if (ul + 1 != 0 || errno == 0)
00246 return (bfd_vma) ul;
00247
00248 /* Note that even though strtoul overflowed, it should have set *pp
00249 to the end of the number, which is where we want it. */
00250
00251 if (sizeof (bfd_vma) > sizeof (unsigned long))
00252 {
00253 const char *p;
00254 boolean neg;
00255 int base;
00256 bfd_vma over, lastdig;
00257 boolean overflow;
00258 bfd_vma v;
00259
00260 /* Our own version of strtoul, for a bfd_vma. */
00261
00262 p = orig;
00263
00264 neg = false;
00265 if (*p == '+')
00266 ++p;
00267 else if (*p == '-')
00268 {
00269 neg = true;
00270 ++p;
00271 }
00272
00273 base = 10;
00274 if (*p == '0')
00275 {
00276 if (p[1] == 'x' || p[1] == 'X')
00277 {
00278 base = 16;
00279 p += 2;
00280 }
00281 else
00282 {
00283 base = 8;
00284 ++p;
00285 }
00286 }
00287
00288 over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
00289 lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
00290
00291 overflow = false;
00292 v = 0;
00293 while (1)
00294 {
00295 int d;
00296
00297 d = *p++;
00298 if (isdigit ((unsigned char) d))
00299 d -= '0';
00300 else if (isupper ((unsigned char) d))
00301 d -= 'A';
00302 else if (islower ((unsigned char) d))
00303 d -= 'a';
00304 else
00305 break;
00306
00307 if (d >= base)
00308 break;
00309
00310 if (v > over || (v == over && (bfd_vma) d > lastdig))
00311 {
00312 overflow = true;
00313 break;
00314 }
00315 }
00316
00317 if (! overflow)
00318 {
00319 if (neg)
00320 v = - v;
00321 return v;
00322 }
00323 }
00324
00325 /* If we get here, the number is too large to represent in a
00326 bfd_vma. */
00327
00328 if (poverflow != NULL)
00329 *poverflow = true;
00330 else
00331 warn_stab (orig, "numeric overflow");
00332
00333 return 0;
00334 }
|
|
||||||||||||||||||||||||||||
|
00426 {
00427 struct stab_handle *info = (struct stab_handle *) handle;
00428
00429 /* gcc will emit two N_SO strings per compilation unit, one for the
00430 directory name and one for the file name. We just collect N_SO
00431 strings as we see them, and start the new compilation unit when
00432 we see a non N_SO symbol. */
00433 if (info->so_string != NULL
00434 && (type != N_SO || *string == '\0' || value != info->so_value))
00435 {
00436 if (! debug_set_filename (dhandle, info->so_string))
00437 return false;
00438 info->main_filename = info->so_string;
00439
00440 info->gcc_compiled = 0;
00441 info->n_opt_found = false;
00442
00443 /* Generally, for stabs in the symbol table, the N_LBRAC and
00444 N_RBRAC symbols are relative to the N_SO symbol value. */
00445 if (! info->sections)
00446 info->file_start_offset = info->so_value;
00447
00448 /* We need to reset the mapping from type numbers to types. We
00449 can't free the old mapping, because of the use of
00450 debug_make_indirect_type. */
00451 info->files = 1;
00452 info->file_types = ((struct stab_types **)
00453 xmalloc (sizeof *info->file_types));
00454 info->file_types[0] = NULL;
00455
00456 info->so_string = NULL;
00457
00458 /* Now process whatever type we just got. */
00459 }
00460
00461 switch (type)
00462 {
00463 case N_FN:
00464 case N_FN_SEQ:
00465 break;
00466
00467 case N_LBRAC:
00468 /* Ignore extra outermost context from SunPRO cc and acc. */
00469 if (info->n_opt_found && desc == 1)
00470 break;
00471
00472 if (! info->within_function)
00473 {
00474 fprintf (stderr, "N_LBRAC not within function\n");
00475 return false;
00476 }
00477
00478 /* Start an inner lexical block. */
00479 if (! debug_start_block (dhandle,
00480 (value
00481 + info->file_start_offset
00482 + info->function_start_offset)))
00483 return false;
00484
00485 /* Emit any pending variable definitions. */
00486 if (! stab_emit_pending_vars (dhandle, info))
00487 return false;
00488
00489 ++info->block_depth;
00490 break;
00491
00492 case N_RBRAC:
00493 /* Ignore extra outermost context from SunPRO cc and acc. */
00494 if (info->n_opt_found && desc == 1)
00495 break;
00496
00497 /* We shouldn't have any pending variable definitions here, but,
00498 if we do, we probably need to emit them before closing the
00499 block. */
00500 if (! stab_emit_pending_vars (dhandle, info))
00501 return false;
00502
00503 /* End an inner lexical block. */
00504 if (! debug_end_block (dhandle,
00505 (value
00506 + info->file_start_offset
00507 + info->function_start_offset)))
00508 return false;
00509
00510 --info->block_depth;
00511 if (info->block_depth < 0)
00512 {
00513 fprintf (stderr, "Too many N_RBRACs\n");
00514 return false;
00515 }
00516 break;
00517
00518 case N_SO:
00519 /* This always ends a function. */
00520 if (info->within_function)
00521 {
00522 bfd_vma endval;
00523
00524 endval = value;
00525 if (*string != '\0'
00526 && info->function_end != (bfd_vma) -1
00527 && info->function_end < endval)
00528 endval = info->function_end;
00529 if (! stab_emit_pending_vars (dhandle, info)
00530 || ! debug_end_function (dhandle, endval))
00531 return false;
00532 info->within_function = false;
00533 info->function_end = (bfd_vma) -1;
00534 }
00535
00536 /* An empty string is emitted by gcc at the end of a compilation
00537 unit. */
00538 if (*string == '\0')
00539 return true;
00540
00541 /* Just accumulate strings until we see a non N_SO symbol. If
00542 the string starts with '/', we discard the previously
00543 accumulated strings. */
00544 if (info->so_string == NULL)
00545 info->so_string = xstrdup (string);
00546 else
00547 {
00548 char *f;
00549
00550 f = info->so_string;
00551 if (*string == '/')
00552 info->so_string = xstrdup (string);
00553 else
00554 info->so_string = concat (info->so_string, string,
00555 (const char *) NULL);
00556 free (f);
00557 }
00558
00559 info->so_value = value;
00560
00561 break;
00562
00563 case N_SOL:
00564 /* Start an include file. */
00565 if (! debug_start_source (dhandle, string))
00566 return false;
00567 break;
00568
00569 case N_BINCL:
00570 /* Start an include file which may be replaced. */
00571 push_bincl (info, string, value);
00572 if (! debug_start_source (dhandle, string))
00573 return false;
00574 break;
00575
00576 case N_EINCL:
00577 /* End an N_BINCL include. */
00578 if (! debug_start_source (dhandle, pop_bincl (info)))
00579 return false;
00580 break;
00581
00582 case N_EXCL:
00583 /* This is a duplicate of a header file named by N_BINCL which
00584 was eliminated by the linker. */
00585 if (! find_excl (info, string, value))
00586 return false;
00587 break;
00588
00589 case N_SLINE:
00590 if (! debug_record_line (dhandle, desc,
00591 value + info->function_start_offset))
00592 return false;
00593 break;
00594
00595 case N_BCOMM:
00596 if (! debug_start_common_block (dhandle, string))
00597 return false;
00598 break;
00599
00600 case N_ECOMM:
00601 if (! debug_end_common_block (dhandle, string))
00602 return false;
00603 break;
00604
00605 case N_FUN:
00606 if (*string == '\0')
00607 {
00608 if (info->within_function)
00609 {
00610 /* This always marks the end of a function; we don't
00611 need to worry about info->function_end. */
00612 if (info->sections)
00613 value += info->function_start_offset;
00614 if (! stab_emit_pending_vars (dhandle, info)
00615 || ! debug_end_function (dhandle, value))
00616 return false;
00617 info->within_function = false;
00618 info->function_end = (bfd_vma) -1;
00619 }
00620 break;
00621 }
00622
00623 /* A const static symbol in the .text section will have an N_FUN
00624 entry. We need to use these to mark the end of the function,
00625 in case we are looking at gcc output before it was changed to
00626 always emit an empty N_FUN. We can't call debug_end_function
00627 here, because it might be a local static symbol. */
00628 if (info->within_function
00629 && (info->function_end == (bfd_vma) -1
00630 || value < info->function_end))
00631 info->function_end = value;
00632
00633 /* Fall through. */
00634 /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
00635 symbols, and if it does not start with :S, gdb relocates the
00636 value to the start of the section. gcc always seems to use
00637 :S, so we don't worry about this. */
00638 /* Fall through. */
00639 default:
00640 {
00641 const char *colon;
00642
00643 colon = strchr (string, ':');
00644 if (colon != NULL
00645 && (colon[1] == 'f' || colon[1] == 'F'))
00646 {
00647 if (info->within_function)
00648 {
00649 bfd_vma endval;
00650
00651 endval = value;
00652 if (info->function_end != (bfd_vma) -1
00653 && info->function_end < endval)
00654 endval = info->function_end;
00655 if (! stab_emit_pending_vars (dhandle, info)
00656 || ! debug_end_function (dhandle, endval))
00657 return false;
00658 info->function_end = (bfd_vma) -1;
00659 }
00660 /* For stabs in sections, line numbers and block addresses
00661 are offsets from the start of the function. */
00662 if (info->sections)
00663 info->function_start_offset = value;
00664 info->within_function = true;
00665 }
00666
00667 if (! parse_stab_string (dhandle, info, type, desc, value, string))
00668 return false;
00669 }
00670 break;
00671
00672 case N_OPT:
00673 if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
00674 info->gcc_compiled = 2;
00675 else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
00676 info->gcc_compiled = 1;
00677 else
00678 info->n_opt_found = true;
00679 break;
00680
00681 case N_OBJ:
00682 case N_ENDM:
00683 case N_MAIN:
00684 break;
00685 }
00686
00687 return true;
00688 }
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
02857 {
02858 boolean is_full_physname_constructor;
02859 boolean is_constructor;
02860 boolean is_destructor;
02861 debug_type *args;
02862 boolean varargs;
02863
02864 /* Constructors are sometimes handled specially. */
02865 is_full_physname_constructor = ((argtypes[0] == '_'
02866 && argtypes[1] == '_'
02867 && (isdigit ((unsigned char) argtypes[2])
02868 || argtypes[2] == 'Q'
02869 || argtypes[2] == 't'))
02870 || strncmp (argtypes, "__ct", 4) == 0);
02871
02872 is_constructor = (is_full_physname_constructor
02873 || (tagname != NULL
02874 && strcmp (fieldname, tagname) == 0));
02875 is_destructor = ((argtypes[0] == '_'
02876 && (argtypes[1] == '$' || argtypes[1] == '.')
02877 && argtypes[2] == '_')
02878 || strncmp (argtypes, "__dt", 4) == 0);
02879
02880 if (is_destructor || is_full_physname_constructor)
02881 *pphysname = argtypes;
02882 else
02883 {
02884 unsigned int len;
02885 const char *const_prefix;
02886 const char *volatile_prefix;
02887 char buf[20];
02888 unsigned int mangled_name_len;
02889 char *physname;
02890
02891 len = tagname == NULL ? 0 : strlen (tagname);
02892 const_prefix = constp ? "C" : "";
02893 volatile_prefix = volatilep ? "V" : "";
02894
02895 if (len == 0)
02896 sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
02897 else if (tagname != NULL && strchr (tagname, '<') != NULL)
02898 {
02899 /* Template methods are fully mangled. */
02900 sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
02901 tagname = NULL;
02902 len = 0;
02903 }
02904 else
02905 sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
02906
02907 mangled_name_len = ((is_constructor ? 0 : strlen (fieldname))
02908 + strlen (buf)
02909 + len
02910 + strlen (argtypes)
02911 + 1);
02912
02913 if (fieldname[0] == 'o'
02914 && fieldname[1] == 'p'
02915 && (fieldname[2] == '$' || fieldname[2] == '.'))
02916 {
02917 const char *opname;
02918
02919 opname = cplus_mangle_opname (fieldn |