diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CBrowse.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/C/CBrowse.c | 737 |
1 files changed, 737 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CBrowse.c b/compiler_and_linker/FrontEnd/C/CBrowse.c new file mode 100644 index 0000000..12ea4c8 --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CBrowse.c @@ -0,0 +1,737 @@ +#include "compiler/CBrowse.h" +#include "compiler/CDecl.h" +#include "compiler/CError.h" +#include "compiler/CMangler.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CompilerTools.h" +#include "compiler/Unmangle.h" +#include "compiler/objects.h" +#include "compiler/templates.h" +#include "cos.h" +#include "plugin.h" + +Boolean gUseTokenStreamSource; +Boolean gForceSourceLoc; +Boolean gUseNameTable; +static GList gBrowseData; +static GList gClassData; +static GList gMemberFuncList; +static int gNextMemberFuncID; + +enum ELanguage { + langUnknown, + langC, + langCPlus, + langPascal, + langObjectPascal, + langJava, + langAssembler, + langFortran, + langRez +}; + +enum EBrowserItem { + browseFunction, + browseGlobal, + browseClass, + browseMacro, + browseEnum, + browseTypedef, + browseConstant, + browseTemplate, + browsePackage, + browseCompSymbolStart = 0x70, + browseEnd = 0xFF +}; + +enum { + kAbstract = 1, + kStatic = 2, + kFinal = 4, + kMember = 8, + + kInterface = 0x80, + kPublic = 0x100, + + kInline = 0x80, + kPascal = 0x100, + kAsm = 0x200, + kVirtual = 0x400, + kCtor = 0x800, + kDtor = 0x1000, + kNative = 0x2000, + kSynch = 0x4000, + kIntrinsic = 0x8000, + kConst = 0x10000, + + kTransient = 0x80, + kVolatile = 0x100 +}; + +enum EAccess { + accessNone = 0, + accessPrivate = 1, + accessProtected = 2, + accessPublic = 4 +}; + +enum EMember { + memberFunction, + memberData, + memberEnd = 0xFF +}; + +enum ETemplateType { + templateClass, + templateFunction +}; + +static enum EAccess gFromAccessType[] = { + accessPublic, + accessPrivate, + accessProtected, + accessNone +}; + +typedef struct BrowseHeader { + SInt32 browse_header; + SInt32 browse_version; + SInt16 browse_language; + SInt16 uses_name_table; + SInt32 earliest_compatible_version; + SInt32 reserved[15]; +} BrowseHeader; + +// forward decls +static void RecordUndefinedMemberFunctions(void); + +void CBrowse_Setup(CompilerLinkerParamBlk *params) { + BrowseHeader hdr; + + CError_ASSERT(123, params != NULL); + + params->object.browsedata = NULL; + + InitGList(&gBrowseData, 0x10000); + InitGList(&gMemberFuncList, 1024); + + gNextMemberFuncID = 1; + gForceSourceLoc = 0; + gUseNameTable = 0; + + memclrw(&hdr, sizeof(hdr)); + hdr.browse_header = 0xBEABBAEB; + hdr.browse_version = 2; + hdr.earliest_compatible_version = 2; + hdr.browse_language = copts.cplusplus ? langCPlus : langC; + hdr.uses_name_table = gUseNameTable; + + AppendGListData(&gBrowseData, &hdr, sizeof(hdr)); +} + +void CBrowse_Finish(CompilerLinkerParamBlk *params) { + CWMemHandle hnd; + + CError_ASSERT(151, params != NULL); + + if (gBrowseData.size >= sizeof(BrowseHeader)) { + RecordUndefinedMemberFunctions(); + AppendGListByte(&gBrowseData, -1); + + COS_ResizeHandle(gBrowseData.data, gBrowseData.size); + + if (CWSecretAttachHandle(params->context, gBrowseData.data, &hnd) == cwNoErr) { + params->object.browsedata = hnd; + gBrowseData.data = NULL; + } + } +} + +void CBrowse_Cleanup(CompilerLinkerParamBlk *params) { + FreeGList(&gBrowseData); + FreeGList(&gClassData); + FreeGList(&gMemberFuncList); +} + +static void AppendGList(GList *dst, GList *src) { + SInt32 offset = dst->size; + + AppendGListNoData(dst, src->size); + memcpy(*dst->data + offset, *src->data, src->size); +} + +static void RecordName(GList *gl, const char *str, SInt32 id) { + HashNameNode *name; + + CError_ASSERT(190, gl && str && *str); + + if (id < 0 && gUseNameTable) { + for (name = name_hash_nodes[CHash(str)]; name; name = name->next) { + if (!strcmp(str, name->name)) { + id = name->id; + break; + } + } + } + + if (id >= 0 && gUseNameTable) { + AppendGListWord(gl, -1); + AppendGListLong(gl, id); + } else { + int len = strlen(str); + AppendGListWord(gl, len); + if (len) + AppendGListData(gl, str, len + 1); + } +} + +void CBrowse_BeginClass(DeclInfo *di, GList *gl) { + char *buf; + ClassList *base; + SInt32 i; + TypeClass *tclass; + + CError_ASSERT(227, di && di->thetype && gl); + + *gl = gClassData; + + if ( + !di->file || + !di->file->fileID || + !di->file->recordbrowseinfo || + !di->file2 || + !di->file2->fileID || + di->sourceoffset <= 0 + ) + { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + if (IsTempName(TYPE_CLASS(di->thetype)->classname)) { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + InitGList(&gClassData, 0x4000); + AppendGListByte(&gClassData, browseClass); + AppendGListWord(&gClassData, di->file->fileID); + AppendGListWord(&gClassData, di->file2->fileID); + AppendGListLong(&gClassData, di->sourceoffset - 1); + CError_ASSERT(270, gClassData.size == 9); + AppendGListLong(&gClassData, di->sourceoffset - 1); + AppendGListLong(&gClassData, 0); + RecordName(&gClassData, TYPE_CLASS(di->thetype)->classname->name, TYPE_CLASS(di->thetype)->classname->id); + + CMangler_MangleType(di->thetype, 0); + AppendGListByte(&name_mangle_list, 0); + + buf = lalloc(name_mangle_list.size + 1); + strcpy(buf, *name_mangle_list.data); + + while (*buf && *buf >= '0' && *buf <= '9') + buf++; + + if (strcmp(TYPE_CLASS(di->thetype)->classname->name, buf)) + RecordName(&gClassData, buf, -1); + else + AppendGListWord(&gClassData, 0); + + AppendGListLong(&gClassData, 0); + + i = 0; + base = TYPE_CLASS(di->thetype)->bases; + while (base) { + base = base->next; + i++; + } + + AppendGListByte(&gClassData, i); + + for (base = TYPE_CLASS(di->thetype)->bases; base; base = base->next) { + AppendGListByte(&gClassData, gFromAccessType[base->access]); + AppendGListByte(&gClassData, base->is_virtual); + + tclass = base->base; + if ((tclass->flags & CLASS_IS_TEMPL_INST) && !TEMPL_CLASS_INST(tclass)->is_specialized) + tclass = TYPE_CLASS(TEMPL_CLASS_INST(tclass)->templ); + + CMangler_MangleType(TYPE(tclass), 0); + AppendGListByte(&name_mangle_list, 0); + + buf = lalloc(name_mangle_list.size + 1); + strcpy(buf, *name_mangle_list.data); + + while (*buf && *buf >= '0' && *buf <= '9') + buf++; + + i = base->base->classname->id; + while (*buf && *buf >= '0' && *buf <= '9') { + i = -1; + buf++; + } + + RecordName(&gClassData, buf, i); + } +} + +void CBrowse_AddClassMemberVar(ObjMemberVar *ivar, SInt32 startOffset, SInt32 endOffset) { + short len; + + CError_ASSERT(360, ivar); + + if (gClassData.data && startOffset > 0 && endOffset >= startOffset) { + if (tk == ';') + endOffset++; + + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, gFromAccessType[ivar->access]); + AppendGListLong(&gClassData, 0); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(ivar->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, ivar->name->name, len + 1); + } +} + +void CBrowse_AddClassMemberFunction(Object *object, SInt32 startOffset, SInt32 endOffset) { + SInt32 flags; + SInt32 id; + TypeMemberFunc *tfunc; + + CError_ASSERT(380, object); + + if ( + !IsTempName(object->name) && + gClassData.data && + startOffset > 0 && + endOffset >= startOffset + ) + { + flags = 0; + CError_ASSERT(391, object->type && IS_TYPE_FUNC(object->type)); + tfunc = TYPE_METHOD(object->type); + + if (tfunc->flags & FUNC_AUTO_GENERATED) + return; + + if (object->datatype == DVFUNC) + flags |= kVirtual; + if (tfunc->flags & FUNC_PURE) + flags |= kAbstract; + if (tfunc->is_static) + flags |= kStatic; + if (tfunc->flags & FUNC_IS_CTOR) + flags |= kCtor; + if (tfunc->flags & FUNC_IS_DTOR) + flags |= kDtor; + + AppendGListByte(&gClassData, memberFunction); + AppendGListByte(&gClassData, gFromAccessType[object->access]); + AppendGListLong(&gClassData, flags); + + id = tfunc->funcid; + if (id <= 0) { + // TODO: this is not 64-bit safe + if (!(tfunc->flags & FUNC_DEFINED) || id == -1) + AppendGListLong(&gMemberFuncList, (SInt32) object); + tfunc->funcid = id = gNextMemberFuncID++; + } + + AppendGListLong(&gClassData, id); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset); + } +} + +void CBrowse_AddClassMemberData(Object *object, SInt32 startOffset, SInt32 endOffset) { + short len; + + CError_ASSERT(435, object); + + if (gClassData.data && startOffset > 0 && endOffset >= startOffset && object->datatype == DDATA) { + if (tk == ';') + endOffset++; + + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, gFromAccessType[object->access]); + AppendGListLong(&gClassData, kStatic); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(object->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, object->name->name, len + 1); + } +} + +void CBrowse_EndClass(SInt32 offset, GList *gl) { + CError_ASSERT(453, gl); + + if (gClassData.data) { + if (gClassData.size > 0) { + if (tk == ';') + offset++; + memcpy(*gClassData.data + 9, &offset, 4); + AppendGList(&gBrowseData, &gClassData); + AppendGListByte(&gBrowseData, memberEnd); + } + FreeGList(&gClassData); + } + + gClassData = *gl; +} + +void CBrowse_BeginStruct(DeclInfo *di, TypeStruct *tstruct, GList *gl) { + HashNameNode *name; + + CError_ASSERT(480, di && gl); + + *gl = gClassData; + + if ( + !di->file || + !di->file->fileID || + !di->file->recordbrowseinfo || + !di->file2 || + !di->file2->fileID || + di->sourceoffset <= 0 + ) + { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + name = tstruct->name; + if (!name || IsTempName(name)) { + memclrw(&gClassData, sizeof(gClassData)); + return; + } + + InitGList(&gClassData, 0x4000); + AppendGListByte(&gClassData, browseClass); + AppendGListWord(&gClassData, di->file->fileID); + AppendGListWord(&gClassData, di->file2->fileID); + AppendGListLong(&gClassData, di->sourceoffset - 1); + CError_ASSERT(521, gClassData.size == 9); + AppendGListLong(&gClassData, di->sourceoffset - 1); + AppendGListLong(&gClassData, 0); + RecordName(&gClassData, name->name, name->id); + AppendGListWord(&gClassData, 0); + AppendGListLong(&gClassData, 0); + AppendGListByte(&gClassData, 0); +} + +void CBrowse_AddStructMember(StructMember *member, SInt32 startOffset, SInt32 endOffset) { + short len; + + if (tk == ';') + endOffset++; + + if (gClassData.data && member && startOffset > 0 && endOffset >= startOffset) { + AppendGListByte(&gClassData, memberData); + AppendGListByte(&gClassData, accessPublic); + AppendGListLong(&gClassData, 0); + AppendGListLong(&gClassData, startOffset - 1); + AppendGListLong(&gClassData, endOffset - 1); + + len = strlen(member->name->name); + AppendGListWord(&gClassData, len); + AppendGListData(&gClassData, member->name->name, len + 1); + } +} + +void CBrowse_EndStruct(SInt32 offset, GList *gl) { + CError_ASSERT(558, gl); + + if (gClassData.data) { + if (offset > 0 && gClassData.size > 0) { + memcpy(*gClassData.data + 9, &offset, 4); + AppendGList(&gBrowseData, &gClassData); + AppendGListByte(&gBrowseData, memberEnd); + } + FreeGList(&gClassData); + } + + gClassData = *gl; +} + +static void EmitStandardData(int item, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset, const char *str, SInt32 id, const char *str2, SInt32 id2) { + CError_ASSERT(584, str); + + AppendGListByte(&gBrowseData, item); + AppendGListWord(&gBrowseData, fileID1); + AppendGListWord(&gBrowseData, fileID2); + AppendGListLong(&gBrowseData, startOffset - 1); + AppendGListLong(&gBrowseData, endOffset - 1); + AppendGListLong(&gBrowseData, 0); + + RecordName(&gBrowseData, str, id); + if (str2 && str2 != str) + RecordName(&gBrowseData, str2, id2); + else + AppendGListWord(&gBrowseData, 0); +} + +void CBrowse_NewTypedef(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(618, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseTypedef, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +void CBrowse_NewEnum(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(632, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseEnum, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +void CBrowse_NewEnumConstant(NameSpace *nspace, HashNameNode *name, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(646, file1 && file1->recordbrowseinfo); + + if (tk == ',') + endOffset++; + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData(browseConstant, + file1->fileID, file2->fileID, + startOffset, endOffset, + name->name, name->id, + CError_GetQualifiedName(nspace, name), -1); + } +} + +static HashNameNode *CBrowse_GetLinkName(Object *object) { + return CMangler_GetLinkName(object); +} + +static void RecordFunction(Object *object, int fileID1, int fileID2, SInt32 startOffset, SInt32 endOffset) { + TypeFunc *tfunc; + char *tmp; + Boolean flag; + char *str29; + HashNameNode *linkname; + SInt32 flags; + char *namestr; + SInt32 nameid; + char *namestr2; + SInt32 nameid2; + int funcid; + char buf[2048]; + char buf2[256]; + + CError_ASSERT(740, object->type && IS_TYPE_FUNC(object->type)); + + if (IsTempName(object->name)) + return; + + tfunc = TYPE_FUNC(object->type); + if ((tfunc->flags & (FUNC_AUTO_GENERATED | FUNC_INTRINSIC)) && (!fileID2 || startOffset < 0)) + return; + + linkname = object->name; + tmp = linkname->name; + if (!(linkname->name[0] == '_' && linkname->name[1] == '_')) { + namestr = tmp; + nameid = linkname->id; + switch (tmp[0]) { + case '.': + nameid = -1; + namestr += 1; + break; + case '_': + switch (tmp[1]) { + case '#': + case '%': + case '@': + nameid = -1; + namestr += 2; + break; + } + break; + } + } else { + flag = 1; + if (tfunc->flags & (FUNC_IS_CTOR | FUNC_IS_DTOR)) { + tmp = TYPE_METHOD(tfunc)->theclass->classname->name; + while (*tmp >= '0' && *tmp <= '9') + tmp++; + MWUnmangleClassName(tmp, buf, sizeof(buf)); + + str29 = buf; + if ((tmp = strrchr(str29, ':'))) + str29 = tmp + 1; + + if (tfunc->flags & FUNC_IS_DTOR) { + buf2[0] = '~'; + strncpy(&buf2[1], str29, sizeof(buf2) - 1); + namestr = buf2; + } else { + namestr = str29; + } + + flag = 0; + } + + if (flag) { + MWUnmangle(object->name->name, buf, sizeof(buf)); + namestr = buf; + } + + nameid = -1; + } + + while (*namestr >= '0' && *namestr <= '9') { + nameid = -1; + namestr++; + } + + namestr2 = NULL; + nameid2 = -1; + + linkname = CBrowse_GetLinkName(object); + if (object->name != linkname) { + namestr2 = linkname->name; + if (linkname->name[0] == '.') + namestr2++; + else + nameid2 = linkname->id; + } + + EmitStandardData(browseFunction, fileID1, fileID2, startOffset, endOffset, namestr, nameid, namestr2, nameid2); + + flags = 0; + if (object->qual & Q_INLINE) + flags |= kInline; + if (object->qual & Q_PASCAL) + flags |= kPascal; + if (object->qual & Q_ASM) + flags |= kAsm; + if (object->sclass == TK_STATIC) + flags |= kStatic; + if (tfunc->flags & FUNC_METHOD) + flags |= kMember; + AppendGListLong(&gBrowseData, flags); + + funcid = 0; + if (tfunc->flags & FUNC_METHOD) { + funcid = TYPE_METHOD(tfunc)->funcid; + if (funcid <= 0) { + TYPE_METHOD(tfunc)->funcid = funcid = gNextMemberFuncID++; + } + } + AppendGListLong(&gBrowseData, funcid); +} + +void CBrowse_NewFunction(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(890, file1 && file1->recordbrowseinfo); + + if (file2 && file2->fileID && startOffset > 0 && (endOffset + 1) >= startOffset) + RecordFunction(object, file1->fileID, file2->fileID, startOffset, endOffset + 1); +} + +void CBrowse_NewData(Object *object, CPrepFileInfo *file1, CPrepFileInfo *file2, SInt32 startOffset, SInt32 endOffset) { + char *namestr = NULL; + SInt32 flags = 0; + Boolean is_const = is_const_object(object); + + CError_ASSERT(912, file1 && file1->recordbrowseinfo); + CError_ASSERT(913, object); + + if (tk == ';') + endOffset++; + + if (file2 && file2->fileID && startOffset > 0 && endOffset >= startOffset) { + HashNameNode *name = CBrowse_GetLinkName(object); + if (object->name != name) + namestr = name->name; + + EmitStandardData( + is_const ? browseConstant : browseGlobal, + file1->fileID, file2->fileID, + startOffset, endOffset, + object->name->name, object->name->id, + namestr, name->id + ); + + if (!is_const) { + if (object->sclass == TK_STATIC) + flags |= kStatic; + AppendGListLong(&gBrowseData, flags); + } + } +} + +void CBrowse_NewMacro(Macro *macro, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(951, !file || (file->recordbrowseinfo && !macro->is_special)); + + if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) + EmitStandardData( + browseMacro, + file->fileID, file->fileID, + startOffset, endOffset, + macro->name->name, macro->name->id, + NULL, -1 + ); +} + +void CBrowse_NewTemplateClass(TemplClass *tmclass, CPrepFileInfo *file, SInt32 startOffset, SInt32 endOffset) { + CError_ASSERT(965, !file || file->recordbrowseinfo); + + if (file && file->fileID && startOffset > 0 && endOffset >= startOffset) { + EmitStandardData( + browseTemplate, + file->fileID, file->fileID, + startOffset, endOffset, + tmclass->theclass.classname->name, tmclass->theclass.classname->id, + NULL, -1 + ); + AppendGListByte(&gBrowseData, templateClass); + } +} + +void CBrowse_NewTemplateFunc(TemplateFunction *tmfunc) { + CError_ASSERT(979, !tmfunc->srcfile || tmfunc->srcfile->recordbrowseinfo); + + if (tmfunc->srcfile && tmfunc->srcfile->fileID && tmfunc->startoffset > 0 && tmfunc->endoffset >= tmfunc->startoffset) { + EmitStandardData( + browseTemplate, + tmfunc->srcfile->fileID, tmfunc->srcfile->fileID, + tmfunc->startoffset, tmfunc->endoffset, + tmfunc->name->name, tmfunc->name->id, + NULL, -1 + ); + AppendGListByte(&gBrowseData, templateFunction); + } +} + +static void RecordUndefinedMemberFunctions(void) { + int i; + int count; + Object **array; + + COS_LockHandleHi(gMemberFuncList.data); + + count = gMemberFuncList.size / sizeof(Object *); + array = (Object **) *gMemberFuncList.data; + for (i = 0; i < count; i++, array++) { + if (IS_TYPE_FUNC((*array)->type) && !(TYPE_FUNC((*array)->type)->flags & FUNC_DEFINED)) + RecordFunction(*array, 0, 0, -1, -1); + } + + COS_UnlockHandle(gMemberFuncList.data); +} |