MWCC/compiler_and_linker/unsorted/CBrowse.c

738 lines
20 KiB
C

#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->x60 <= 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->x60 - 1);
CError_ASSERT(270, gClassData.size == 9);
AppendGListLong(&gClassData, di->x60 - 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_FLAGS_800) && !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;
TypeMethod *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_FLAGS_100)
return;
if (object->datatype == DVFUNC)
flags |= kVirtual;
if (tfunc->flags & FUNC_FLAGS_8)
flags |= kAbstract;
if (tfunc->x26)
flags |= kStatic;
if (tfunc->flags & FUNC_FLAGS_1000)
flags |= kCtor;
if (tfunc->flags & FUNC_FLAGS_2000)
flags |= kDtor;
AppendGListByte(&gClassData, memberFunction);
AppendGListByte(&gClassData, gFromAccessType[object->access]);
AppendGListLong(&gClassData, flags);
id = tfunc->x22;
if (id <= 0) {
// TODO: this is not 64-bit safe
if (!(tfunc->flags & FUNC_FLAGS_2) || id == -1)
AppendGListLong(&gMemberFuncList, (SInt32) object);
tfunc->x22 = 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->x60 <= 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->x60 - 1);
CError_ASSERT(521, gClassData.size == 9);
AppendGListLong(&gClassData, di->x60 - 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_FLAGS_100 | FUNC_FLAGS_200)) && (!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_FLAGS_1000 | FUNC_FLAGS_2000)) {
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_FLAGS_2000) {
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_FLAGS_METHOD)
flags |= kMember;
AppendGListLong(&gBrowseData, flags);
funcid = 0;
if (tfunc->flags & FUNC_FLAGS_METHOD) {
funcid = TYPE_METHOD(tfunc)->x22;
if (funcid <= 0) {
TYPE_METHOD(tfunc)->x22 = 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_FLAGS_2))
RecordFunction(*array, 0, 0, -1, -1);
}
COS_UnlockHandle(gMemberFuncList.data);
}