📄 stabsread.c
字号:
if (**pp != ';') foo = error_type (pp); else ++*pp; And in case it isn't obvious, the point of all this hair is so the compiler can define new types and new syntaxes, and old versions of the debugger will be able to read the new symbol tables. */struct type *error_type (pp) char **pp;{ complain (&error_type_complaint, 0); while (1) { /* Skip to end of symbol. */ while (**pp != '\0') (*pp)++; /* Check for and handle cretinous dbx symbol name continuation! */ if ((*pp)[-1] == '\\') *pp = next_symbol_text (); else break; } return builtin_type_error;}/* Read a dbx type reference or definition; return the type that is meant. This can be just a number, in which case it references a type already defined and placed in type_vector. Or the number can be followed by an =, in which case it means to define a new type according to the text that follows the =. */struct type *read_type (pp, objfile) register char **pp; struct objfile *objfile;{ register struct type *type = 0; struct type *type1; int typenums[2]; int xtypenums[2]; /* Read type number if present. The type number may be omitted. for instance in a two-dimensional array declared with type "ar1;1;10;ar1;1;10;4". */ if ((**pp >= '0' && **pp <= '9') || **pp == '(') { read_type_number (pp, typenums); /* Type is not being defined here. Either it already exists, or this is a forward reference to it. dbx_alloc_type handles both cases. */ if (**pp != '=') return dbx_alloc_type (typenums, objfile); /* Type is being defined here. */#if 0 /* Callers aren't prepared for a NULL result! FIXME -- metin! */ { struct type *tt; /* if such a type already exists, this is an unnecessary duplication of the stab string, which is common in (RS/6000) xlc generated objects. In that case, simply return NULL and let the caller take care of it. */ tt = *dbx_lookup_type (typenums); if (tt && tt->length && tt->code) return NULL; }#endif *pp += 2; } else { /* 'typenums=' not present, type is anonymous. Read and return the definition, but don't put it in the type vector. */ typenums[0] = typenums[1] = -1; *pp += 1; } switch ((*pp)[-1]) { case 'x': { enum type_code code; /* Used to index through file_symbols. */ struct pending *ppt; int i; /* Name including "struct", etc. */ char *type_name; /* Name without "struct", etc. */ char *type_name_only; { char *prefix; char *from, *to; /* Set the type code according to the following letter. */ switch ((*pp)[0]) { case 's': code = TYPE_CODE_STRUCT; prefix = "struct "; break; case 'u': code = TYPE_CODE_UNION; prefix = "union "; break; case 'e': code = TYPE_CODE_ENUM; prefix = "enum "; break; default: return error_type (pp); } to = type_name = (char *) obstack_alloc (&objfile -> type_obstack, (strlen (prefix) + ((char *) strchr (*pp, ':') - (*pp)) + 1)); /* Copy the prefix. */ from = prefix; while (*to++ = *from++) ; to--; type_name_only = to; /* Copy the name. */ from = *pp + 1; while ((*to++ = *from++) != ':') ; *--to = '\0'; /* Set the pointer ahead of the name which we just read. */ *pp = from; #if 0 /* The following hack is clearly wrong, because it doesn't check whether we are in a baseclass. I tried to reproduce the case that it is trying to fix, but I couldn't get g++ to put out a cross reference to a basetype. Perhaps it doesn't do it anymore. */ /* Note: for C++, the cross reference may be to a base type which has not yet been seen. In this case, we skip to the comma, which will mark the end of the base class name. (The ':' at the end of the base class name will be skipped as well.) But sometimes (ie. when the cross ref is the last thing on the line) there will be no ','. */ from = (char *) strchr (*pp, ','); if (from) *pp = from;#endif /* 0 */ } /* Now check to see whether the type has already been declared. */ /* This is necessary at least in the case where the program says something like struct foo bar[5]; The compiler puts out a cross-reference; we better find set the length of the structure correctly so we can set the length of the array. */ for (ppt = file_symbols; ppt; ppt = ppt->next) for (i = 0; i < ppt->nsyms; i++) { struct symbol *sym = ppt->symbol[i]; if (SYMBOL_CLASS (sym) == LOC_TYPEDEF && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE && (TYPE_CODE (SYMBOL_TYPE (sym)) == code) && !strcmp (SYMBOL_NAME (sym), type_name_only)) { obstack_free (&objfile -> type_obstack, type_name); type = SYMBOL_TYPE (sym); return type; } } /* Didn't find the type to which this refers, so we must be dealing with a forward reference. Allocate a type structure for it, and keep track of it so we can fill in the rest of the fields when we get the full type. */ type = dbx_alloc_type (typenums, objfile); TYPE_CODE (type) = code; TYPE_NAME (type) = type_name; INIT_CPLUS_SPECIFIC(type); TYPE_FLAGS (type) |= TYPE_FLAG_STUB; add_undefined_type (type); return type; }#ifdef IBM6000_HOST case '-': /* RS/6000 built-in type */ (*pp)--; type = builtin_type (pp); /* (in xcoffread.c) */ goto after_digits;#endif case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '(': (*pp)--; read_type_number (pp, xtypenums); type = *dbx_lookup_type (xtypenums); /* fall through */ after_digits: if (type == 0) type = lookup_fundamental_type (objfile, FT_VOID); if (typenums[0] != -1) *dbx_lookup_type (typenums) = type; break; /* In the following types, we must be sure to overwrite any existing type that the typenums refer to, rather than allocating a new one and making the typenums point to the new one. This is because there may already be pointers to the existing type (if it had been forward-referenced), and we must change it to a pointer, function, reference, or whatever, *in-place*. */ case '*': type1 = read_type (pp, objfile); type = make_pointer_type (type1, dbx_lookup_type (typenums)); break; case '&': /* Reference to another type */ type1 = read_type (pp, objfile); type = make_reference_type (type1, dbx_lookup_type (typenums)); break; case 'f': /* Function returning another type */ type1 = read_type (pp, objfile); type = make_function_type (type1, dbx_lookup_type (typenums)); break; case 'k': /* Const qualifier on some type (Sun) */ type = read_type (pp, objfile); /* FIXME! For now, we ignore const and volatile qualifiers. */ break; case 'B': /* Volatile qual on some type (Sun) */ type = read_type (pp, objfile); /* FIXME! For now, we ignore const and volatile qualifiers. */ break;/* FIXME -- we should be doing smash_to_XXX types here. */ case '@': /* Member (class & variable) type */ { struct type *domain = read_type (pp, objfile); struct type *memtype; if (**pp != ',') /* Invalid member type data format. */ return error_type (pp); ++*pp; memtype = read_type (pp, objfile); type = dbx_alloc_type (typenums, objfile); smash_to_member_type (type, domain, memtype); } break; case '#': /* Method (class & fn) type */ if ((*pp)[0] == '#') { /* We'll get the parameter types from the name. */ struct type *return_type; *pp += 1; return_type = read_type (pp, objfile); if (*(*pp)++ != ';') complain (&invalid_member_complaint, (char *) symnum); type = allocate_stub_method (return_type); if (typenums[0] != -1) *dbx_lookup_type (typenums) = type; } else { struct type *domain = read_type (pp, objfile); struct type *return_type; struct type **args; if (*(*pp)++ != ',') error ("invalid member type data format, at symtab pos %d.", symnum); return_type = read_type (pp, objfile); args = read_args (pp, ';', objfile); type = dbx_alloc_type (typenums, objfile); smash_to_method_type (type, domain, return_type, args); } break; case 'r': /* Range type */ type = read_range_type (pp, typenums, objfile); if (typenums[0] != -1) *dbx_lookup_type (typenums) = type; break; case 'b': /* Sun ACC builtin int type */ type = read_sun_builtin_type (pp, typenums, objfile); if (typenums[0] != -1) *dbx_lookup_type (typenums) = type; break; case 'R': /* Sun ACC builtin float type */ type = read_sun_floating_type (pp, typenums, objfile); if (typenums[0] != -1) *dbx_lookup_type (typenums) = type; break; case 'e': /* Enumeration type */ type = dbx_alloc_type (typenums, objfile); type = read_enum_type (pp, type, objfile); *dbx_lookup_type (typenums) = type; break; case 's': /* Struct type */ type = dbx_alloc_type (typenums, objfile); if (!TYPE_NAME (type)) TYPE_NAME (type) = type_synonym_name; type_synonym_name = 0; type = read_struct_type (pp, type, objfile); break; case 'u': /* Union type */ type = dbx_alloc_type (typenums, objfile); if (!TYPE_NAME (type)) TYPE_NAME (type) = type_synonym_name; type_synonym_name = 0; type = read_struct_type (pp, type, objfile); TYPE_CODE (type) = TYPE_CODE_UNION; break; case 'a': /* Array type */ if (**pp != 'r') return error_type (pp); ++*pp; type = dbx_alloc_type (typenums, objfile); type = read_array_type (pp, type, objfile); break; default: --*pp; /* Go back to the symbol in error */ /* Particularly important if it was \0! */ return error_type (pp); } if (type == 0) abort (); return type;}/* This page contains subroutines of read_type. *//* Read the description of a structure (or union type) and return an object describing the type. */static struct type *read_struct_type (pp, type, objfile) char **pp; register struct type *type; struct objfile *objfile;{ /* Total number of methods defined in this class. If the class defines two `f' methods, and one `g' method, then this will have the value 3. */ int total_length = 0; struct nextfield { struct nextfield *next; int visibility; /* 0=public, 1=protected, 2=public */ struct field field; }; struct next_fnfield { struct next_fnfield *next; struct fn_field fn_field; }; struct next_fnfieldlist { struct next_fnfieldlist *next; struct fn_fieldlist fn_fieldlist; }; register struct nextfield *list = 0; struct nextfield *new; register char *p; int nfields = 0; int non_public_fields = 0; register int n; register struct next_fnfieldlist *mainlist = 0; int nfn_fields = 0; TYPE_CODE (type) = TYPE_CODE_STRUCT; INIT_CPLUS_SPECIFIC(type); TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB; /* First comes the total size in bytes. */ TYPE_LENGTH (type) = read_number (pp, 0); /* C++: Now, if the class is a derived class, then the next character will be a '!', followed by the number of base classes derived from. Each element in the list contains visibility information, the offset of this base class in the derived structure, and then the base type. */ if (**pp == '!') { int i, n_baseclasses, offset; struct type *baseclass; int via_public; /* Nonzero if it is a virtual baseclass, i.e., struct A{}; struct B{}; struct C : public B, public virtual A {}; B is a baseclass of C; A is a virtual baseclass for C. This is a C++
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -