diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/C/CPrec.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/C/CPrec.c | 3482 |
1 files changed, 3482 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/C/CPrec.c b/compiler_and_linker/FrontEnd/C/CPrec.c new file mode 100644 index 0000000..e61b96e --- /dev/null +++ b/compiler_and_linker/FrontEnd/C/CPrec.c @@ -0,0 +1,3482 @@ +#include "compiler/CPrec.h" +#include "compiler/CError.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CInline.h" +#include "compiler/CMachine.h" +#include "compiler/CObjC.h" +#include "compiler/CParser.h" +#include "compiler/CPrep.h" +#include "compiler/CScope.h" +#include "compiler/CSOM.h" +#include "compiler/CTemplateNew.h" +#include "compiler/CompilerTools.h" +#include "compiler/Exceptions.h" +#include "compiler/enode.h" +#include "compiler/objc.h" +#include "compiler/objects.h" +#include "compiler/scopes.h" +#include "compiler/som.h" +#include "compiler/templates.h" +#include "compiler/types.h" +#include "cos.h" +#include "compiler/CCompiler.h" +#include "compiler/InlineAsm.h" + +#define RESOLVE_BUFFER(offset) ((void *) (((char *) cprec_buffer) + ((uintptr_t) (offset)))) +#define RESOLVE_RAW_BUFFER(offset) ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset)))) +#define RESOLVE_SAFE(offset) (!(offset) ? NULL : ((void *) (((char *) cprec_rawbuffer) + ((uintptr_t) (offset))))) + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct StaticData { + struct StaticData *next; + Object *object; + void *buffer; + OLinkList *links; + SInt32 size; +} StaticData; + +typedef struct Header { + UInt32 magic; + UInt16 version; + UInt16 x6; + char target; + Boolean check_header_flags; + Boolean cplusplus; + UInt32 xC; + UInt32 x10; + UInt32 x14; + UInt32 x18; + UInt32 x1C; + UInt32 x20; + UInt32 x24; + UInt32 x28; + UInt32 x2C; + UInt32 x30; + UInt32 compressedPatchCount; + UInt32 compressedPatchSize; + UInt32 compressedPatchOffset; + UInt32 builtinPatchSize; + UInt32 builtinPatchOffset; + UInt32 tokenStreamPatchSize; + UInt32 tokenStreamPatchOffset; + UInt32 root_names; + NameSpaceList *usings; + TemplClass *ctempl_templates; + CSOMStub *csom_stubs; + StaticData *cprec_staticdata; + UInt32 uniqueID; + CallbackAction *callbackactions; + Type *cobjc_type_class; + Type *cobjc_type_id; + Type *cobjc_type_sel; + ObjCSelector **cobjc_selhashtable; + BClassList *cobjc_classdefs; + ObjCProtocol *cobjc_protocols; + UInt32 cobjc_selrefcount; + UInt32 cobjc_classrefcount; + UInt32 cobjc_stringcount; + InitExpr *init_expressions; + CI_Action *cinline_tactionlist; + TemplateFunction *ctempl_templatefuncs; + UInt32 x9C; + UInt32 xA0; + UInt32 xA4; + UInt32 xA8; + UInt32 xAC; + UInt32 xB0; + UInt32 xB4; + UInt32 xB8; + UInt32 xBC; + UInt32 xC0; + UInt32 xC4; + UInt32 xC8; + UInt32 xCC; + UInt32 xD0; + UInt32 xD4; + UInt32 xD8; + UInt32 xDC; + UInt32 xE0; + UInt32 xE4; + HashNameNode *nametable[0x800]; + Macro *macrotable[0x800]; + NameSpaceName *root_nametable[0x400]; +} Header; + +typedef struct Patch { + struct Patch *next; + SInt32 offset; +} Patch; + +typedef struct AddrPatch { + struct AddrPatch *next; + void *addr; + void *value; +} AddrPatch; + +typedef struct BuiltIn { + void *target; + SInt32 idx; + Patch *patches; +} BuiltIn; + +static Boolean cprec_exportargnames; +static Boolean cprec_dowrite; +static OSErr cprec_ioerror; +static void *cprec_rawbuffer; +static void *cprec_buffer; +static SInt32 cprec_zero_offset; +static SInt32 cprec_offset; +static int cprec_builtins; +static void **cprec_builtin_array; + +typedef struct TokenPatch { + struct TokenPatch *next; + TStreamElement *tokens; + SInt32 count; +} TokenPatch; +static TokenPatch *cprec_tokenpatches; +static StaticData *cprec_staticdata; + +typedef struct PointerHash { + struct PointerHash *next; + TypePointer *tptr; + TypePointer *prec_tptr; +} PointerHash; +static PointerHash **cprec_pointerhash; + +static BuiltIn *cprec_builtin; +static Patch *cprec_patch_list; +static AddrPatch **cprec_addrhash; +static Header *cprec_header; +static GList cprec_glist; +static short cprec_refnum; +char *precomp_target_str; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +// Assorted forward declarations +static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace); +static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj); +static Object *CPrec_GetObjectPatch(Object *obj); +static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj); +static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar); +static Type *CPrec_GetTypePatch(Type *type); +static ENode *CPrec_GetExpressionPatch(ENode *expr); +static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth); +static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst); +static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg); +static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol); +static OSErr CPrec_FlushBufferCheck(void); + +void SetupPrecompiler(Boolean isPrecompiling) { + cprec_refnum = 0; + cprec_glist.data = NULL; + cprec_header = NULL; + cprec_staticdata = NULL; + cprec_ioerror = noErr; +} + +void CleanupPrecompiler(void) { + if (cprec_refnum) { + COS_FileClose(cprec_refnum); + cprec_refnum = 0; + } + + if (cprec_glist.data) + FreeGList(&cprec_glist); +} + +static OLinkList *CPrec_OLinkListCopy(OLinkList *list) { + OLinkList *copy; + + if (!list) + return NULL; + + copy = galloc(sizeof(OLinkList)); + *copy = *list; + copy->next = CPrec_OLinkListCopy(copy->next); + return copy; +} + +void PreComp_StaticData(Object *obj, const void *data, OLinkList *links, SInt32 size) { + StaticData *entry; + + if (obj->sclass != TK_STATIC && !(obj->qual & (Q_20000 | Q_WEAK))) + CError_Error(CErrorStr180); + + entry = galloc(sizeof(StaticData)); + entry->object = obj; + entry->size = size; + + entry->next = cprec_staticdata; + cprec_staticdata = entry; + + if (data) { + entry->buffer = galloc(obj->type->size); + memcpy(entry->buffer, data, obj->type->size); + } else { + entry->buffer = NULL; + } + + entry->links = CPrec_OLinkListCopy(links); +} + +static void CPrec_InitAddressHashTable(void) { + cprec_addrhash = lalloc(0x4000 * sizeof(AddrPatch *)); + memclrw(cprec_addrhash, 0x4000 * sizeof(AddrPatch *)); +} + +static void CPrec_InitPointerHashTable(void) { + cprec_pointerhash = lalloc(0x400 * sizeof(PointerHash *)); + memclrw(cprec_pointerhash, 0x400 * sizeof(PointerHash *)); +} + +static int CPrec_AddressHashVal(void *addr) { + UInt32 v = (UInt32) addr; + return ( + v + + ((unsigned char *) &v)[0] + + ((unsigned char *) &v)[1] + + ((unsigned char *) &v)[2] + + ((unsigned char *) &v)[3] + ) & 0x3FFF; +} + +static AddrPatch *CPrec_FindAddrPatch(void *addr) { + AddrPatch *scan; + + for (scan = cprec_addrhash[CPrec_AddressHashVal(addr)]; scan; scan = scan->next) { + if (scan->addr == addr) + return scan; + } + + return NULL; +} + +static AddrPatch *CPrec_NewAddrPatch(void *addr, void *value) { + AddrPatch **loc; + AddrPatch *patch; + + loc = cprec_addrhash + CPrec_AddressHashVal(addr); + patch = lalloc(sizeof(AddrPatch)); + patch->addr = addr; + patch->value = value; + patch->next = *loc; + *loc = patch; + return patch; +} + +static void CPrec_SetupBuiltInArray(void) { + int count1, count2; + Boolean flag; + void **array; + +#define REG_BUILTIN(a) \ + if (!flag) { array[count2++] = (a); } else { count1++; } + + for (count2 = count1 = 0, flag = 1; ;) { + REG_BUILTIN(cscope_root); + REG_BUILTIN(&stvoid); + REG_BUILTIN(&stbool); + REG_BUILTIN(&stchar); + REG_BUILTIN(&stsignedchar); + REG_BUILTIN(&stunsignedchar); + REG_BUILTIN(&stwchar); + REG_BUILTIN(&stsignedshort); + REG_BUILTIN(&stunsignedshort); + REG_BUILTIN(&stsignedint); + REG_BUILTIN(&stunsignedint); + REG_BUILTIN(&stsignedlong); + REG_BUILTIN(&stunsignedlong); + REG_BUILTIN(&stsignedlonglong); + REG_BUILTIN(&stunsignedlonglong); + REG_BUILTIN(&stfloat); + REG_BUILTIN(&stshortdouble); + REG_BUILTIN(&stdouble); + REG_BUILTIN(&stlongdouble); + REG_BUILTIN(&elipsis); + REG_BUILTIN(&oldstyle); + REG_BUILTIN(&stillegal); + REG_BUILTIN(&sttemplexpr); + REG_BUILTIN(&stvoid); + REG_BUILTIN(&void_ptr); + REG_BUILTIN(&rt_func); + REG_BUILTIN(&catchinfostruct); + REG_BUILTIN(newh_func); + REG_BUILTIN(delh_func); + REG_BUILTIN(copy_func); + REG_BUILTIN(clear_func); + REG_BUILTIN(Rgtid_func); + REG_BUILTIN(Rdync_func); + REG_BUILTIN(rt_ptmf_cast); + REG_BUILTIN(rt_ptmf_cmpr); + REG_BUILTIN(rt_ptmf_test); + REG_BUILTIN(rt_ptmf_call); + REG_BUILTIN(rt_ptmf_scall); + REG_BUILTIN(rt_ptmf_null); + REG_BUILTIN(rt_som_glue1); + REG_BUILTIN(rt_som_glue2); + REG_BUILTIN(rt_som_glue3); + REG_BUILTIN(rt_som_check); + REG_BUILTIN(rt_som_new); + REG_BUILTIN(rt_som_newcheck); + REG_BUILTIN(rt_ptmf_call4); + REG_BUILTIN(rt_ptmf_scall4); + REG_BUILTIN(carr_func); + REG_BUILTIN(cnar_func); + REG_BUILTIN(darr_func); + REG_BUILTIN(dnar_func); + REG_BUILTIN(dnar3_func); + REG_BUILTIN(Xgreg_func); + REG_BUILTIN(Xthrw_func); + REG_BUILTIN(Xicth_func); + REG_BUILTIN(Xecth_func); + REG_BUILTIN(Xunex_func); + REG_BUILTIN(&stvectorunsignedchar); + REG_BUILTIN(&stvectorsignedchar); + REG_BUILTIN(&stvectorboolchar); + REG_BUILTIN(&stvectorunsignedshort); + REG_BUILTIN(&stvectorsignedshort); + REG_BUILTIN(&stvectorboolshort); + REG_BUILTIN(&stvectorunsignedlong); + REG_BUILTIN(&stvectorsignedlong); + REG_BUILTIN(&stvectorboollong); + REG_BUILTIN(&stvectorfloat); + REG_BUILTIN(&stvectorpixel); + + if (flag) { + array = lalloc(sizeof(void *) * count1); + cprec_builtin_array = array; + cprec_builtins = count1; + flag = 0; + } else { + return; + } + } +} + +static void CPrec_SetupBuiltIn(void) { + int x; + + CPrec_SetupBuiltInArray(); + cprec_builtin = lalloc(sizeof(BuiltIn) * cprec_builtins); + memclrw(cprec_builtin, sizeof(BuiltIn) * cprec_builtins); + + for (x = 0; x < cprec_builtins; x++) { + cprec_builtin[x].target = cprec_builtin_array[x]; + cprec_builtin[x].idx = ~x; + CPrec_NewAddrPatch(cprec_builtin[x].target, (void *) cprec_builtin[x].idx); + } +} + +static void CPrec_NewPointerPatch(void *src, void *ptr) { + if (cprec_dowrite) { + Patch *patch = lalloc(sizeof(Patch)); + patch->offset = (SInt32) src; + CError_ASSERT(507, (patch->offset & 0x80000001) == 0); + + if ((SInt32) ptr < 0) { + ptr = (void *) ~((SInt32) ptr); + CError_ASSERT(513, (SInt32) ptr < cprec_builtins); + + patch->next = cprec_builtin[(SInt32) ptr].patches; + cprec_builtin[(SInt32) ptr].patches = patch; + ptr = NULL; + } else { + patch->next = cprec_patch_list; + cprec_patch_list = patch; + } + + src = (void *)((char *) src - cprec_zero_offset); + CError_ASSERT(525, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); + *((void **) (*cprec_glist.data + (SInt32) src)) = ptr; + } +} + +static void CPrec_ExistingPointerPatch(void *src, void *ptr) { + if (cprec_dowrite) { + AddrPatch *addrPatch; + Patch *patch; + + CError_ASSERT(543, addrPatch = CPrec_FindAddrPatch(ptr)); + + patch = lalloc(sizeof(Patch)); + patch->offset = (SInt32) src; + patch->next = cprec_patch_list; + cprec_patch_list = patch; + + CError_ASSERT(548, (patch->offset & 0x80000001) == 0); + + src = (void *)((char *) src - cprec_zero_offset); + CError_ASSERT(552, (SInt32) src >= 0 && (SInt32) src <= cprec_glist.size); + *((void **) (*cprec_glist.data + (SInt32) src)) = addrPatch->value; + } +} + +static void CPrec_NamePatch(void *src, HashNameNode *name) { + name->id = 1; + CPrec_ExistingPointerPatch(src, name); +} + +static void *CPrec_AppendAlign(void) { + if (cprec_dowrite) { + while (cprec_offset & 3) { + AppendGListByte(&cprec_glist, 0); + ++cprec_offset; + } + } + + return (void *) cprec_offset; +} + +static UInt32 CPrec_AppendByte(UInt8 v) { + if (cprec_dowrite) + AppendGListByte(&cprec_glist, v); + return cprec_offset++; +} + +static UInt32 CPrec_AppendWord16(UInt16 v) { + UInt32 offset; + if (cprec_dowrite) + AppendGListWord(&cprec_glist, v); + offset = cprec_offset; + cprec_offset += 2; + return offset; +} + +static UInt32 CPrec_AppendWord32(UInt32 v) { + UInt32 offset; + if (cprec_dowrite) + AppendGListLong(&cprec_glist, v); + offset = cprec_offset; + cprec_offset += 4; + return offset; +} + +static UInt32 CPrec_AppendPointer(void *v) { + UInt32 offset; + if (cprec_dowrite) + AppendGListLong(&cprec_glist, (SInt32) v); + offset = cprec_offset; + cprec_offset += 4; + return offset; +} + +static UInt32 CPrec_AppendPointerPatch(void *v) { + AddrPatch *addrPatch; + + if (v) { + CError_ASSERT(644, addrPatch = CPrec_FindAddrPatch(v)); + + if (cprec_dowrite) { + Patch *patch = lalloc(sizeof(Patch)); + patch->offset = cprec_offset; + patch->next = cprec_patch_list; + cprec_patch_list = patch; + CError_ASSERT(651, (patch->offset & 0x80000001) == 0); + } + + return CPrec_AppendPointer(addrPatch->value); + } else { + return CPrec_AppendPointer(NULL); + } +} + +static void CPrec_AppendNamePatch(HashNameNode *name) { + if (name) { + CPrec_AppendPointerPatch(name); + name->id = 1; + } +} + +static void CPrec_AppendString(const char *str) { + int len = strlen(str) + 1; + if (cprec_dowrite) + AppendGListData(&cprec_glist, str, len); + cprec_offset += len; +} + +static void CPrec_AppendData(const void *data, int len) { + if (cprec_dowrite) + AppendGListData(&cprec_glist, data, len); + cprec_offset += len; +} + +static void CPrec_RawMemPatch(void *source, const void *data, int len) { + void *ptr = CPrec_AppendAlign(); + CPrec_AppendData(data, len); + CPrec_NewPointerPatch(source, ptr); +} + +static void CPrec_DumpNameTable(void) { + HashNameNode *name; + int i; + HashNameNode *p; + HashNameNode *next; + + if (cprec_dowrite) { + i = 0; + do { + name = name_hash_nodes[i]; + while (name && name->id == 0) + name = name->next; + + if (name) { + p = CPrec_AppendAlign(); + cprec_header->nametable[i] = p; + + while (1) { + CPrec_NewAddrPatch(name, p); + CPrec_AppendPointer(NULL); + CPrec_AppendWord32(0); + CPrec_AppendWord16(name->hashval); + CPrec_AppendString(name->name); + + name = name->next; + while (name && name->id == 0) + name = name->next; + + if (!name) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->next, next); + p = next; + } + } + } while (++i < 0x800); + } else { + i = 0; + do { + if ((name = name_hash_nodes[i])) { + p = CPrec_AppendAlign(); + while (1) { + CPrec_NewAddrPatch(name, p); + CPrec_AppendPointer(NULL); + CPrec_AppendWord32(0); + CPrec_AppendWord16(name->hashval); + CPrec_AppendString(name->name); + + name = name->next; + if (!name) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->next, next); + p = next; + } + } + } while (++i < 0x800); + } +} + +static void CPrec_DumpMacroTable(void) { + Macro *macro; + int i; + int j; + Macro *p; + Macro *next; + + i = 0; + do { + for (macro = macrohashtable[i]; macro; macro = macro->next) { + if (macro->c) { + CPrec_NewAddrPatch(macro->c, (void *) cprec_offset); + CPrec_AppendString(macro->c); + } + } + } while (++i < 0x800); + + i = 0; + do { + macro = macrohashtable[i]; + + if (macro) { + p = CPrec_AppendAlign(); + if (cprec_dowrite) + cprec_header->macrotable[i] = p; + + while (1) { + CPrec_AppendPointer(NULL); + CPrec_AppendNamePatch(macro->name); + CPrec_AppendPointerPatch(macro->c); + CPrec_AppendWord16(macro->xC); + CPrec_AppendByte(macro->is_special); + CPrec_AppendByte(macro->xF); + + for (j = 1; j < (macro->xC & 0x7FFF); j++) + CPrec_AppendNamePatch(macro->names[j - 1]); + + macro = macro->next; + if (!macro) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->next, next); + p = next; + } + } + } while (++i < 0x800); +} + +static BClassList *CPrec_GetClassAccessPatch(BClassList *path) { + AddrPatch *addrPatch; + BClassList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(path))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(path, first); + + while (1) { + CPrec_AppendData(path, sizeof(BClassList)); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(path->type)); + if (!path->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + path = path->next; + } + + return first; +} + +static int CPrec_PointerHash(TypePointer *type) { + Type *target; + int work; + FuncArg *arg; + + work = type->qual; + target = type->target; + +restart: + switch (target->type) { + case TYPECLASS: + if (TYPE_CLASS(target)->classname) + work += TYPE_CLASS(target)->classname->hashval; + break; + case TYPEENUM: + if (TYPE_ENUM(target)->enumname) + work += TYPE_ENUM(target)->enumname->hashval; + target = TYPE_ENUM(target)->enumtype; + work += 3; + case TYPEINT: + case TYPEFLOAT: + work += TYPE_INTEGRAL(target)->integral; + break; + case TYPEPOINTER: + work += TYPE_POINTER(target)->qual; + target = TYPE_POINTER(target)->target; + goto restart; + case TYPEARRAY: + work += target->size; + target = TYPE_POINTER(target)->target; + goto restart; + case TYPEFUNC: + work += TYPE_FUNC(target)->functype->type; + work += TYPE_FUNC(target)->functype->size; + for (arg = TYPE_FUNC(target)->args; arg; arg = arg->next) { + if (arg->type) { + work += arg->type->type; + work += arg->type->size; + } + } + break; + } + + work += target->type + target->size; + return (work + (work >> 24) + (work >> 16) + (work >> 8)) & 0x3FF; +} + +static TypePointer *CPrec_GetTypePointerPatch(TypePointer *tptr) { + TypePointer *p; + int hash; + PointerHash *phash; + TypePointer *scan1; + TypePointer *scan2; + + if (tptr->qual & Q_IS_OBJC_ID) { + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tptr, p); + CPrec_AppendData(tptr, sizeof(TypeObjCID)); + if (TYPE_OBJC_ID(tptr)->protocols) + CPrec_NewPointerPatch(&TYPE_OBJC_ID(p)->protocols, CPrec_GetObjCProtocolListPatch(TYPE_OBJC_ID(tptr)->protocols)); + } else { + if (!copts.faster_pch_gen && cprec_dowrite && tptr->size > 0) { + hash = CPrec_PointerHash(tptr); + for (phash = cprec_pointerhash[hash]; phash; phash = phash->next) { + scan1 = tptr; + scan2 = phash->tptr; + check_again: + if (scan1->type == scan2->type && scan1->size == scan2->size && scan1->qual == scan2->qual) { + scan1 = TYPE_POINTER(TPTR_TARGET(scan1)); + scan2 = TYPE_POINTER(TPTR_TARGET(scan2)); + if (scan1->type == TYPEPOINTER && scan1->type == TYPEARRAY) + goto check_again; + if (scan1 == scan2) + return phash->prec_tptr; + } + } + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tptr, p); + + phash = lalloc(sizeof(PointerHash)); + phash->tptr = tptr; + phash->prec_tptr = p; + phash->next = cprec_pointerhash[hash]; + cprec_pointerhash[hash] = phash; + } else { + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tptr, p); + } + + CPrec_AppendData(tptr, sizeof(TypePointer)); + } + + CPrec_NewPointerPatch(&p->target, CPrec_GetTypePatch(tptr->target)); + return p; +} + +static TypeEnum *CPrec_GetTypeEnumPatch(TypeEnum *type) { + TypeEnum *p = CPrec_AppendAlign(); + + CPrec_NewAddrPatch(type, p); + CPrec_AppendData(type, sizeof(TypeEnum)); + + if (type->nspace) + CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(type->nspace)); + if (type->enumlist) + CPrec_NewPointerPatch(&p->enumlist, CPrec_GetObjEnumConstPatch(type->enumlist)); + + CPrec_NewPointerPatch(&p->enumtype, CPrec_GetTypePatch(type->enumtype)); + if (type->enumname) + CPrec_NamePatch(&p->enumname, type->enumname); + + return p; +} + +static TypeBitfield *CPrec_GetTypeBitfieldPatch(TypeBitfield *type) { + TypeBitfield *p = CPrec_AppendAlign(); + + CPrec_NewAddrPatch(type, p); + CPrec_AppendData(type, sizeof(TypeBitfield)); + CPrec_NewPointerPatch(&p->bitfieldtype, CPrec_GetTypePatch(type->bitfieldtype)); + + return p; +} + +static TypeStruct *CPrec_GetTypeStructPatch(TypeStruct *tstruct) { + StructMember *member; + TypeStruct *p; + StructMember *current, *next; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tstruct, p); + CPrec_AppendData(tstruct, sizeof(TypeStruct)); + + if (tstruct->name) + CPrec_NamePatch(&p->name, tstruct->name); + + if ((member = tstruct->members)) { + current = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->members, current); + + while (1) { + CPrec_AppendData(member, sizeof(StructMember)); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(member->type)); + CPrec_NamePatch(¤t->name, member->name); + + if (!member->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + + member = member->next; + } + } + + return p; +} + +static ExceptSpecList *CPrec_GetExceptSpecPatch(ExceptSpecList *exspec) { + ExceptSpecList *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (exspec) { + CPrec_AppendData(exspec, sizeof(ExceptSpecList)); + if (exspec->type) + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(exspec->type)); + + if (!exspec->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + exspec = exspec->next; + } + + return first; +} + +static FuncArg *CPrec_GetArgListPatch(FuncArg *lst, Boolean includeNames) { + FuncArg *first, *current, *next; + AddrPatch *addrPatch; + + if ((addrPatch = CPrec_FindAddrPatch(lst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + while (1) { + if (!includeNames) + lst->name = NULL; + CPrec_AppendData(lst, sizeof(FuncArg)); + if (includeNames && lst->name) + CPrec_NamePatch(¤t->name, lst->name); + + if (lst->dexpr) + CPrec_NewPointerPatch(¤t->dexpr, CPrec_GetExpressionPatch(lst->dexpr)); + if (lst->type) + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(lst->type)); + else + CError_FATAL(1167); + + if (!lst->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + CPrec_NewAddrPatch(lst, next); + } + + return first; +} + +static TypeFunc *CPrec_GetTypeFuncPatch(TypeFunc *type) { + TypeFunc *p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(type, p); + + CPrec_AppendData(type, (type->flags & FUNC_METHOD) ? sizeof(TypeMemberFunc) : sizeof(TypeFunc)); + + CPrec_NewPointerPatch(&p->functype, CPrec_GetTypePatch(type->functype)); + if (type->args) + CPrec_NewPointerPatch(&p->args, CPrec_GetArgListPatch(type->args, (type->flags & FUNC_IS_TEMPL_ANY) != 0)); + if (type->exspecs) + CPrec_NewPointerPatch(&p->exspecs, CPrec_GetExceptSpecPatch(type->exspecs)); + if (type->flags & FUNC_METHOD) + CPrec_NewPointerPatch(&TYPE_METHOD(p)->theclass, CPrec_GetTypePatch((Type *) TYPE_METHOD(type)->theclass)); + + return p; +} + +static TypeMemberPointer *CPrec_GetTypeMemberPointerPatch(TypeMemberPointer *type) { + TypeMemberPointer *p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(type, p); + + CPrec_AppendData(type, sizeof(TypeMemberPointer)); + + CPrec_NewPointerPatch(&p->ty1, CPrec_GetTypePatch(type->ty1)); + CPrec_NewPointerPatch(&p->ty2, CPrec_GetTypePatch(type->ty2)); + + return p; +} + +static TypeTemplDep *CPrec_GetTypeTemplDepPatch(TypeTemplDep *type) { + TypeTemplDep *p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(type, p); + + CPrec_AppendData(type, sizeof(TypeTemplDep)); + + switch (type->dtype) { + case TEMPLDEP_ARGUMENT: + break; + case TEMPLDEP_QUALNAME: + CPrec_NewPointerPatch(&p->u.qual.type, CPrec_GetTypeTemplDepPatch(type->u.qual.type)); + CPrec_NamePatch(&p->u.qual.name, type->u.qual.name); + break; + case TEMPLDEP_TEMPLATE: + CPrec_NewPointerPatch(&p->u.templ.templ, CPrec_GetTypePatch((Type *) type->u.templ.templ)); + CPrec_NewPointerPatch(&p->u.templ.args, CPrec_GetTemplateArgPatch(type->u.templ.args)); + break; + case TEMPLDEP_ARRAY: + CPrec_NewPointerPatch(&p->u.array.type, CPrec_GetTypePatch(type->u.array.type)); + CPrec_NewPointerPatch(&p->u.array.index, CPrec_GetExpressionPatch(type->u.array.index)); + break; + case TEMPLDEP_QUALTEMPL: + CPrec_NewPointerPatch(&p->u.qualtempl.type, CPrec_GetTypeTemplDepPatch(type->u.qualtempl.type)); + CPrec_NewPointerPatch(&p->u.qualtempl.args, CPrec_GetTemplateArgPatch(type->u.qualtempl.args)); + break; + case TEMPLDEP_BITFIELD: + CPrec_NewPointerPatch(&p->u.bitfield.type, CPrec_GetTypePatch(type->u.bitfield.type)); + CPrec_NewPointerPatch(&p->u.bitfield.size, CPrec_GetExpressionPatch(type->u.bitfield.size)); + break; + default: + CError_FATAL(1295); + } + + return p; +} + +static ClassList *CPrec_GetClassListPatch(ClassList *cl) { + AddrPatch *addrPatch; + ClassList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(cl))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(cl, first); + + do { + CPrec_AppendData(cl, sizeof(ClassList)); + CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) cl->base)); + + if (!cl->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(cl->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + cl = cl->next; + } + } while (1); + + return first; +} + +static VClassList *CPrec_GetVClassListPatch(VClassList *vcl) { + VClassList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(vcl, sizeof(VClassList)); + CPrec_NewPointerPatch(¤t->base, CPrec_GetTypePatch((Type *) vcl->base)); + + if (!vcl->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + vcl = vcl->next; + } while (1); + + return first; +} + +static ClassFriend *CPrec_GetClassFriendPatch(ClassFriend *cf) { + ClassFriend *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(cf, sizeof(ClassFriend)); + if (cf->isclass) + CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetTypePatch((Type *) cf->u.theclass)); + else + CPrec_NewPointerPatch(¤t->u.theclass, CPrec_GetObjectPatch(cf->u.obj)); + + if (!cf->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + cf = cf->next; + } while (1); + + return first; +} + +static BClassList *CPrec_GetBClassListPatch(BClassList *bcl) { + BClassList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(bcl, sizeof(BClassList)); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch((Type *) bcl->type)); + + if (!bcl->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + bcl = bcl->next; + } while (1); + + return first; +} + +static VTable *CPrec_GetVTablePatch(VTable *vtbl) { + VTable *p = CPrec_AppendAlign(); + CPrec_AppendData(vtbl, sizeof(VTable)); + + if (vtbl->object) + CPrec_NewPointerPatch(&p->object, CPrec_GetObjectPatch(vtbl->object)); + if (vtbl->owner) + CPrec_NewPointerPatch(&p->owner, CPrec_GetTypePatch((Type *) vtbl->owner)); + + return p; +} + +static SOMReleaseOrder *CPrec_GetSOMReleaseOrderPatch(SOMReleaseOrder *sro) { + SOMReleaseOrder *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(sro, sizeof(SOMReleaseOrder)); + CPrec_NamePatch(¤t->name, sro->name); + if (!sro->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + sro = sro->next; + } while (1); + + return first; +} + +static SOMInfo *CPrec_GetSOMInfoPatch(SOMInfo *som) { + SOMInfo *p = CPrec_AppendAlign(); + CPrec_AppendData(som, sizeof(SOMInfo)); + + if (som->metaclass) + CPrec_NewPointerPatch(&p->metaclass, CPrec_GetTypePatch((Type *) som->metaclass)); + if (som->classdataobject) + CPrec_NewPointerPatch(&p->classdataobject, CPrec_GetObjectPatch(som->classdataobject)); + if (som->order) + CPrec_NewPointerPatch(&p->order, CPrec_GetSOMReleaseOrderPatch(som->order)); + + return p; +} + +static ObjCMethodArg *CPrec_GetObjCMethodArgPatch(ObjCMethodArg *arg) { + ObjCMethodArg *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(arg, sizeof(ObjCMethod)); + if (arg->selector) + CPrec_NamePatch(¤t->selector, arg->selector); + if (arg->name) + CPrec_NamePatch(¤t->name, arg->name); + if (arg->type) + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(arg->type)); + + if (!arg->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + arg = arg->next; + } while (1); + + return first; +} + +static ObjCMethodList *CPrec_GetObjCMethodListPatch(ObjCMethodList *lst) { + AddrPatch *addrPatch; + ObjCMethodList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(lst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(lst, first); + + do { + CPrec_AppendData(lst, sizeof(ObjCMethodList)); + if (lst->method) + CPrec_NewPointerPatch(¤t->method, CPrec_GetObjCMethodPatch(lst->method)); + + if (!lst->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(lst->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + CPrec_NewAddrPatch(lst, next); + } + } while (1); + + return first; +} + +static ObjCSelector *CPrec_GetObjCSelectorPatch(ObjCSelector *sel) { + AddrPatch *addrPatch; + ObjCSelector *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(sel))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(sel, first); + + do { + CPrec_AppendData(sel, sizeof(ObjCSelector)); + if (sel->selobject) + CPrec_NewPointerPatch(¤t->selobject, CPrec_GetObjectPatch(sel->selobject)); + CPrec_NamePatch(¤t->name, sel->name); + if (sel->methods) + CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodListPatch(sel->methods)); + + if (!sel->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(sel->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + sel = sel->next; + CPrec_NewAddrPatch(sel, next); + } + } while (1); + + return first; +} + +static ObjCMethod *CPrec_GetObjCMethodPatch(ObjCMethod *meth) { + // does not match - affected by weirdness where the arg goes into r31 instead of r28 + AddrPatch *addrPatch; + ObjCMethod *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(meth))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(meth, first); + + do { + CPrec_AppendData(meth, sizeof(ObjCMethod)); + if (meth->object) + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(meth->object)); + if (meth->functype) + CPrec_NewPointerPatch(¤t->functype, CPrec_GetTypePatch((Type *) meth->functype)); + if (meth->selector) + CPrec_NewPointerPatch(¤t->selector, CPrec_GetObjCSelectorPatch(meth->selector)); + if (meth->return_type) + CPrec_NewPointerPatch(¤t->return_type, CPrec_GetTypePatch(meth->return_type)); + if (meth->selector_args) + CPrec_NewPointerPatch(¤t->selector_args, CPrec_GetObjCMethodArgPatch(meth->selector_args)); + + if (!meth->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(meth->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + meth = meth->next; + CPrec_NewAddrPatch(meth, next); + } + } while (1); + + return first; +} + +static ObjCProtocol *CPrec_GetObjCProtocolPatch(ObjCProtocol *prot) { + AddrPatch *addrPatch; + ObjCProtocol *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(prot))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(prot, first); + + do { + CPrec_AppendData(prot, sizeof(ObjCProtocol)); + CPrec_NamePatch(¤t->name, prot->name); + if (prot->protocols) + CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(prot->protocols)); + if (prot->methods) + CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(prot->methods)); + if (prot->object) + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(prot->object)); + + if (!prot->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(prot->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + prot = prot->next; + CPrec_NewAddrPatch(prot, next); + } + } while (1); + + return first; +} + +static ObjCProtocolList *CPrec_GetObjCProtocolListPatch(ObjCProtocolList *lst) { + AddrPatch *addrPatch; + ObjCProtocolList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(lst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(lst, first); + + do { + CPrec_AppendData(lst, sizeof(ObjCProtocolList)); + CPrec_NewPointerPatch(¤t->protocol, CPrec_GetObjCProtocolPatch(lst->protocol)); + + if (!lst->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + } while (1); + + return first; +} + +static ObjCCategory *CPrec_GetObjCCategoryPatch(ObjCCategory *cat) { + AddrPatch *addrPatch; + ObjCCategory *current, *first, *next; + + if ((addrPatch = CPrec_FindAddrPatch(cat))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(cat, first); + + do { + CPrec_AppendData(cat, sizeof(ObjCCategory)); + CPrec_NamePatch(¤t->name, cat->name); + if (cat->protocols) + CPrec_NewPointerPatch(¤t->protocols, CPrec_GetObjCProtocolListPatch(cat->protocols)); + if (cat->methods) + CPrec_NewPointerPatch(¤t->methods, CPrec_GetObjCMethodPatch(cat->methods)); + + if (!cat->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(cat->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + cat = cat->next; + CPrec_NewAddrPatch(cat, next); + } + } while (1); + + return first; +} + +static ObjCInfo *CPrec_GetObjCInfoPatch(ObjCInfo *info) { + ObjCInfo *p = CPrec_AppendAlign(); + CPrec_AppendData(info, sizeof(ObjCInfo)); + + if (info->classobject) + CPrec_NewPointerPatch(&p->classobject, CPrec_GetObjectPatch(info->classobject)); + if (info->metaobject) + CPrec_NewPointerPatch(&p->metaobject, CPrec_GetObjectPatch(info->metaobject)); + if (info->classrefobj) + CPrec_NewPointerPatch(&p->classrefobj, CPrec_GetObjectPatch(info->classrefobj)); + if (info->methods) + CPrec_NewPointerPatch(&p->methods, CPrec_GetObjCMethodPatch(info->methods)); + if (info->protocols) + CPrec_NewPointerPatch(&p->protocols, CPrec_GetObjCProtocolListPatch(info->protocols)); + if (info->categories) + CPrec_NewPointerPatch(&p->categories, CPrec_GetObjCCategoryPatch(info->categories)); + + return p; +} + +static TemplArg *CPrec_GetTemplateArgPatch(TemplArg *arg) { + TemplArg *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(arg, sizeof(TemplArg)); + switch (arg->pid.type) { + case TPT_TYPE: + if (arg->data.typeparam.type) + CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(arg->data.typeparam.type)); + break; + case TPT_NONTYPE: + if (arg->data.paramdecl.expr) + CPrec_NewPointerPatch(¤t->data.paramdecl.expr, CPrec_GetExpressionPatch(arg->data.paramdecl.expr)); + break; + case TPT_TEMPLATE: + if (arg->data.ttargtype) + CPrec_NewPointerPatch(¤t->data.ttargtype, CPrec_GetTypePatch(arg->data.ttargtype)); + break; + default: + CError_FATAL(1879); + } + + if (!arg->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + arg = arg->next; + } while (1); + + return first; +} + +static TemplParam *CPrec_GetTemplateParamPatch(TemplParam *param) { + // register swap issues + TemplParam *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(param, sizeof(TemplParam)); + if (param->name) + CPrec_NamePatch(¤t->name, param->name); + + switch (param->pid.type) { + case TPT_TYPE: + if (param->data.typeparam.type) + CPrec_NewPointerPatch(¤t->data.typeparam.type, CPrec_GetTypePatch(param->data.typeparam.type)); + break; + case TPT_NONTYPE: + CPrec_NewPointerPatch(¤t->data.paramdecl.type, CPrec_GetTypePatch(param->data.paramdecl.type)); + if (param->data.paramdecl.defaultarg) + CPrec_NewPointerPatch(¤t->data.paramdecl.defaultarg, CPrec_GetExpressionPatch(param->data.paramdecl.defaultarg)); + break; + case TPT_TEMPLATE: + if (param->data.templparam.plist) + CPrec_NewPointerPatch(¤t->data.templparam.plist, CPrec_GetTemplateParamPatch(param->data.templparam.plist)); + CError_ASSERT(1953, !param->data.templparam.defaultarg); + break; + default: + CError_FATAL(1958); + } + + if (!param->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + param = param->next; + } while (1); + + return first; +} + +static TStreamElement *CPrec_GetTStreamPatch(TStreamElement *tokens, SInt32 count) { + TStreamElement elem; + TStreamElement *first, *current, *scan; + SInt32 x; + + scan = tokens; + x = 0; + while (x < count) { + elem = *scan; + memclrw(scan, sizeof(TStreamElement)); + + scan->tokentype = elem.tokentype; + switch (elem.tokentype) { + case TK_IDENTIFIER: + scan->data.tkidentifier = elem.data.tkidentifier; + break; + case TK_INTCONST: + scan->subtype = elem.subtype; + scan->data.tkintconst = elem.data.tkintconst; + break; + case TK_FLOATCONST: + scan->subtype = elem.subtype; + scan->data.tkfloatconst = elem.data.tkfloatconst; + break; + case TK_STRING: + case TK_STRING_WIDE: + scan->subtype = elem.subtype; + scan->data.tkstring = elem.data.tkstring; + break; + } + x++; + scan++; + } + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(tokens, count * sizeof(TStreamElement)); + + if (cprec_dowrite) { + TokenPatch *tp = lalloc(sizeof(TokenPatch)); + tp->tokens = current; + tp->count = count; + tp->next = cprec_tokenpatches; + cprec_tokenpatches = tp; + } + + x = 0; + while (x < count) { + switch (tokens->tokentype) { + case TK_IDENTIFIER: + CPrec_NamePatch(¤t->data.tkidentifier, tokens->data.tkidentifier); + break; + case TK_INTCONST: + case TK_FLOATCONST: + break; + case TK_STRING: + case TK_STRING_WIDE: + CPrec_RawMemPatch(¤t->data.tkstring.data, tokens->data.tkstring.data, tokens->data.tkstring.size); + break; + case TK_EOL: + break; + default: + if (tokens->tokentype < 0) + CError_FATAL(2063); + } + x++; + tokens++; + current++; + } + + return first; +} + +static TemplFuncInstance *CPrec_GetTemplFuncInstancePatch(TemplFuncInstance *inst) { + AddrPatch *addrPatch; + TemplFuncInstance *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(inst))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(inst, first); + + do { + CPrec_AppendData(inst, sizeof(TemplFuncInstance)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(inst->object)); + CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(inst->args)); + + if (!inst->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(inst->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + inst = inst->next; + CPrec_NewAddrPatch(inst, next); + } + } while (1); + + return first; +} + +static TemplateMember *CPrec_GetTemplateMemberPatch(TemplateMember *memb) { + TemplateMember *current, *first, *next; + first = current = CPrec_AppendAlign(); + + do { + memclrw(&memb->fileoffset, sizeof(FileOffsetInfo)); + memb->srcfile = NULL; + memb->startoffset = 0; + memb->endoffset = 0; + + CPrec_AppendData(memb, sizeof(TemplateMember)); + if (memb->params) + CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(memb->params)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(memb->object)); + if (memb->stream.firsttoken) + CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(memb->stream.firsttoken, memb->stream.tokens)); + + if (!memb->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + memb = memb->next; + } while (1); + + return first; +} + +static TemplPartialSpec *CPrec_GetTemplPartialSpecPatch(TemplPartialSpec *pspec) { + TemplPartialSpec *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(pspec, sizeof(TemplPartialSpec)); + if (pspec->templ) + CPrec_NewPointerPatch(¤t->templ, CPrec_GetTypePatch((Type *) pspec->templ)); + if (pspec->args) + CPrec_NewPointerPatch(¤t->args, CPrec_GetTemplateArgPatch(pspec->args)); + + if (!pspec->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + pspec = pspec->next; + } while (1); + + return first; +} + +static TemplateFriend *CPrec_GetTemplateFriendPatch(TemplateFriend *frnd) { + TemplateFriend *p; + + memclrw(&frnd->fileoffset, sizeof(FileOffsetInfo)); + p = CPrec_AppendAlign(); + CPrec_AppendData(frnd, sizeof(TemplateFriend)); + + if (frnd->decl.thetype) + CPrec_NewPointerPatch(&p->decl.thetype, CPrec_GetTypePatch(frnd->decl.thetype)); + if (frnd->decl.nspace) + CPrec_NewPointerPatch(&p->decl.nspace, CPrec_GetNameSpacePatch(frnd->decl.nspace)); + if (frnd->decl.name) + CPrec_NamePatch(&p->decl.name, frnd->decl.name); + if (frnd->decl.expltargs) + CPrec_NewPointerPatch(&p->decl.expltargs, CPrec_GetTemplateArgPatch(frnd->decl.expltargs)); + if (frnd->stream.firsttoken) + CPrec_NewPointerPatch(&p->stream.firsttoken, CPrec_GetTStreamPatch(frnd->stream.firsttoken, frnd->stream.tokens)); + + return p; +} + +static TemplateAction *CPrec_GetTemplateActionPatch(TemplateAction *act) { + // register swap issue + TemplateAction *current, *first, *next; + first = current = CPrec_AppendAlign(); + + do { + memclrw(&act->source_ref, sizeof(TStreamElement)); + CPrec_AppendData(act, sizeof(TemplateAction)); + + switch (act->type) { + case TAT_NESTEDCLASS: + CPrec_NewPointerPatch(¤t->u.tclasstype, CPrec_GetTypePatch((Type *) act->u.tclasstype)); + break; + case TAT_ENUMTYPE: + CPrec_NewPointerPatch(¤t->u.enumtype, CPrec_GetTypePatch((Type *) act->u.enumtype)); + break; + case TAT_FRIEND: + CPrec_NewPointerPatch(¤t->u.tfriend, CPrec_GetTemplateFriendPatch(act->u.tfriend)); + break; + case TAT_ENUMERATOR: + CPrec_NewPointerPatch(¤t->u.enumerator.objenumconst, CPrec_GetObjEnumConstPatch(act->u.enumerator.objenumconst)); + if (act->u.enumerator.initexpr) + CPrec_NewPointerPatch(¤t->u.enumerator.initexpr, CPrec_GetExpressionPatch(act->u.enumerator.initexpr)); + break; + case TAT_BASE: + CPrec_NewPointerPatch(¤t->u.base.type, CPrec_GetTypePatch(act->u.base.type)); + if (act->u.base.insert_after) + CPrec_NewPointerPatch(¤t->u.base.insert_after, CPrec_GetClassListPatch(act->u.base.insert_after)); + break; + case TAT_OBJECTINIT: + CPrec_NewPointerPatch(¤t->u.objectinit.object, CPrec_GetObjectPatch(act->u.objectinit.object)); + CPrec_NewPointerPatch(¤t->u.objectinit.initexpr, CPrec_GetExpressionPatch(act->u.objectinit.initexpr)); + break; + case TAT_USINGDECL: + CPrec_NewPointerPatch(¤t->u.usingdecl.type, CPrec_GetTypeTemplDepPatch(act->u.usingdecl.type)); + break; + case TAT_OBJECTDEF: + CPrec_NewPointerPatch(¤t->u.refobj, CPrec_GetObjBasePatch(act->u.refobj)); + break; + default: + CError_FATAL(2410); + } + + if (!act->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + act = act->next; + } while (1); + + return first; +} + +static TemplateFunction *CPrec_GetTemplateFunctionPatch(TemplateFunction *tf) { + // the same cursed register swaps + AddrPatch *addrPatch; + TemplateFunction *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(tf))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(tf, first); + + do { + memclrw(&tf->deftoken, sizeof(TStreamElement)); + tf->srcfile = NULL; + tf->startoffset = 0; + tf->endoffset = 0; + + CPrec_AppendData(tf, sizeof(TemplateFunction)); + if (tf->unk4) + CPrec_NewPointerPatch(¤t->unk4, CPrec_GetTemplateFunctionPatch(tf->unk4)); + CPrec_NamePatch(¤t->name, tf->name); + if (tf->params) + CPrec_NewPointerPatch(¤t->params, CPrec_GetTemplateParamPatch(tf->params)); + if (tf->stream.firsttoken) + CPrec_NewPointerPatch(¤t->stream.firsttoken, CPrec_GetTStreamPatch(tf->stream.firsttoken, tf->stream.tokens)); + CPrec_NewPointerPatch(¤t->tfunc, CPrec_GetObjectPatch(tf->tfunc)); + if (tf->instances) + CPrec_NewPointerPatch(¤t->instances, CPrec_GetTemplFuncInstancePatch(tf->instances)); + + if (!tf->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(tf->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + tf = tf->next; + CPrec_NewAddrPatch(tf, next); + } + } while (1); + + return first; +} + +static TypeClass *CPrec_GetTypeClassPatch(TypeClass *tclass) { + TypeClass *first, *current, *next; + Boolean hasNextTempl, hasNextTemplInst; + first = current = CPrec_AppendAlign(); + + do_over: + hasNextTempl = hasNextTemplInst = 0; + CPrec_NewAddrPatch(tclass, current); + + if (tclass->flags & CLASS_IS_TEMPL) { + // template class + CPrec_AppendData(tclass, sizeof(TemplClass)); + if (TEMPL_CLASS(tclass)->next) + hasNextTempl = 1; + if (TEMPL_CLASS(tclass)->templ_parent) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->templ_parent)); + if (TEMPL_CLASS(tclass)->inst_parent) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->inst_parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->inst_parent)); + if (TEMPL_CLASS(tclass)->templ__params) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->templ__params, CPrec_GetTemplateParamPatch(TEMPL_CLASS(tclass)->templ__params)); + if (TEMPL_CLASS(tclass)->members) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->members, CPrec_GetTemplateMemberPatch(TEMPL_CLASS(tclass)->members)); + if (TEMPL_CLASS(tclass)->instances) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->instances, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->instances)); + if (TEMPL_CLASS(tclass)->pspec_owner) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspec_owner, CPrec_GetTypePatch((Type *) TEMPL_CLASS(tclass)->pspec_owner)); + if (TEMPL_CLASS(tclass)->pspecs) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->pspecs, CPrec_GetTemplPartialSpecPatch(TEMPL_CLASS(tclass)->pspecs)); + if (TEMPL_CLASS(tclass)->actions) + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->actions, CPrec_GetTemplateActionPatch(TEMPL_CLASS(tclass)->actions)); + } else if (tclass->flags & CLASS_IS_TEMPL_INST) { + // template class instance + CPrec_AppendData(tclass, sizeof(TemplClassInst)); + if (TEMPL_CLASS_INST(tclass)->next) + hasNextTemplInst = 1; + if (TEMPL_CLASS_INST(tclass)->parent) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->parent, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->parent)); + if (TEMPL_CLASS_INST(tclass)->templ) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->templ, CPrec_GetTypePatch((Type *) TEMPL_CLASS_INST(tclass)->templ)); + if (TEMPL_CLASS_INST(tclass)->inst_args) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->inst_args, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->inst_args)); + if (TEMPL_CLASS_INST(tclass)->oargs) + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->oargs, CPrec_GetTemplateArgPatch(TEMPL_CLASS_INST(tclass)->oargs)); + } else { + // base + CPrec_AppendData(tclass, sizeof(TypeClass)); + } + + if (tclass->nspace) + CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(tclass->nspace)); + if (tclass->classname) + CPrec_NamePatch(¤t->classname, tclass->classname); + if (tclass->bases) + CPrec_NewPointerPatch(¤t->bases, CPrec_GetClassListPatch(tclass->bases)); + if (tclass->vbases) + CPrec_NewPointerPatch(¤t->vbases, CPrec_GetVClassListPatch(tclass->vbases)); + if (tclass->ivars) + CPrec_NewPointerPatch(¤t->ivars, CPrec_GetObjMemberVarPatch(tclass->ivars)); + if (tclass->friends) + CPrec_NewPointerPatch(¤t->friends, CPrec_GetClassFriendPatch(tclass->friends)); + if (tclass->vtable) + CPrec_NewPointerPatch(¤t->vtable, CPrec_GetVTablePatch(tclass->vtable)); + if (tclass->sominfo) + CPrec_NewPointerPatch(¤t->sominfo, CPrec_GetSOMInfoPatch(tclass->sominfo)); + if (tclass->objcinfo) + CPrec_NewPointerPatch(¤t->objcinfo, CPrec_GetObjCInfoPatch(tclass->objcinfo)); + + if (hasNextTempl) { + AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS(tclass)->next); + if (!addrPatch) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, next); + current = next; + tclass = (TypeClass *) TEMPL_CLASS(tclass)->next; + goto do_over; + } else { + CPrec_NewPointerPatch(&TEMPL_CLASS(current)->next, addrPatch->value); + } + } + + if (hasNextTemplInst) { + AddrPatch *addrPatch = CPrec_FindAddrPatch(TEMPL_CLASS_INST(tclass)->next); + if (!addrPatch) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, next); + current = next; + tclass = (TypeClass *) TEMPL_CLASS_INST(tclass)->next; + goto do_over; + } else { + CPrec_NewPointerPatch(&TEMPL_CLASS_INST(current)->next, addrPatch->value); + } + } + + return first; +} + +static Type *CPrec_GetTypePatch(Type *type) { + AddrPatch *addrPatch = CPrec_FindAddrPatch(type); + if (addrPatch) + return addrPatch->value; + + switch (type->type) { + case TYPEPOINTER: + case TYPEARRAY: + return (Type *) CPrec_GetTypePointerPatch(TYPE_POINTER(type)); + case TYPEENUM: + return (Type *) CPrec_GetTypeEnumPatch(TYPE_ENUM(type)); + case TYPEBITFIELD: + return (Type *) CPrec_GetTypeBitfieldPatch(TYPE_BITFIELD(type)); + case TYPESTRUCT: + return (Type *) CPrec_GetTypeStructPatch(TYPE_STRUCT(type)); + case TYPEFUNC: + return (Type *) CPrec_GetTypeFuncPatch(TYPE_FUNC(type)); + case TYPEMEMBERPOINTER: + return (Type *) CPrec_GetTypeMemberPointerPatch(TYPE_MEMBER_POINTER(type)); + case TYPETEMPLATE: + return (Type *) CPrec_GetTypeTemplDepPatch(TYPE_TEMPLATE(type)); + case TYPECLASS: + return (Type *) CPrec_GetTypeClassPatch(TYPE_CLASS(type)); + case TYPEVOID: + case TYPEINT: + case TYPEFLOAT: + case TYPELABEL: + case TYPEOBJCID: + case TYPETEMPLDEPEXPR: + default: + CError_FATAL(2796); + return NULL; + } +} + +static ExceptionAction *CPrec_GetExceptionPatch(ExceptionAction *exc) { + ExceptionAction *first, *current, *next; + + first = current = CPrec_AppendAlign(); +repeat: + CPrec_AppendData(exc, sizeof(ExceptionAction)); + switch (exc->type) { + case EAT_DESTROYLOCAL: + CPrec_NewPointerPatch(¤t->data.destroy_local.dtor, CPrec_GetObjectPatch(exc->data.destroy_local.dtor)); + break; + case EAT_DESTROYLOCALCOND: + CPrec_NewPointerPatch(¤t->data.destroy_local_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_cond.dtor)); + break; + case EAT_DESTROYLOCALOFFSET: + CPrec_NewPointerPatch(¤t->data.destroy_local_offset.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_offset.dtor)); + break; + case EAT_DESTROYLOCALPOINTER: + CPrec_NewPointerPatch(¤t->data.destroy_local_pointer.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_pointer.dtor)); + break; + case EAT_DESTROYLOCALARRAY: + CPrec_NewPointerPatch(¤t->data.destroy_local_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_local_array.dtor)); + break; + case EAT_DESTROYPARTIALARRAY: + break; + case EAT_DESTROYMEMBER: + case EAT_DESTROYBASE: + CPrec_NewPointerPatch(¤t->data.destroy_member.dtor, CPrec_GetObjectPatch(exc->data.destroy_member.dtor)); + break; + case EAT_DESTROYMEMBERCOND: + CPrec_NewPointerPatch(¤t->data.destroy_member_cond.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_cond.dtor)); + break; + case EAT_DESTROYMEMBERARRAY: + CPrec_NewPointerPatch(¤t->data.destroy_member_array.dtor, CPrec_GetObjectPatch(exc->data.destroy_member_array.dtor)); + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + CPrec_NewPointerPatch(¤t->data.delete_pointer.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer.deletefunc)); + break; + case EAT_DELETEPOINTERCOND: + CPrec_NewPointerPatch(¤t->data.delete_pointer_cond.deletefunc, CPrec_GetObjectPatch(exc->data.delete_pointer_cond.deletefunc)); + break; + case EAT_CATCHBLOCK: + if (exc->data.catch_block.catch_typeid) { + CPrec_NewPointerPatch(¤t->data.catch_block.catch_typeid, CPrec_GetObjectPatch(exc->data.catch_block.catch_typeid)); + CPrec_NewPointerPatch(¤t->data.catch_block.catch_type, CPrec_GetTypePatch(exc->data.catch_block.catch_type)); + } + break; + case EAT_ACTIVECATCHBLOCK: + break; + case EAT_SPECIFICATION: + if (exc->data.specification.unexp_id) { + int x; + char *ptrs; + ptrs = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->data.specification.unexp_id, ptrs); + CPrec_AppendData(exc->data.specification.unexp_id, sizeof(Object *) * exc->data.specification.unexp_ids); + for (x = 0; x < exc->data.specification.unexp_ids; x++) { + CPrec_NewPointerPatch(ptrs + x * sizeof(Object *), CPrec_GetObjectPatch(exc->data.specification.unexp_id[x])); + } + } + break; + case EAT_TERMINATE: + break; + default: + CError_FATAL(2905); + } + + if (exc->prev) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->prev, next); + current = next; + exc = exc->prev; + goto repeat; + } + return first; +} + +static ENodeList *CPrec_GetExpressionListPatch(ENodeList *lst) { + ENodeList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(lst, sizeof(ENodeList)); + CPrec_NewPointerPatch(¤t->node, CPrec_GetExpressionPatch(lst->node)); + + if (!lst->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + lst = lst->next; + } while (1); + + return first; +} + +static EMemberInfo *CPrec_GetEMemberInfoPatch(EMemberInfo *emember) { + EMemberInfo *p; + + CError_FATAL(2953); + + p = CPrec_AppendAlign(); + CPrec_AppendData(emember, sizeof(EMemberInfo)); + + if (emember->path) + CPrec_NewPointerPatch(&p->path, CPrec_GetClassAccessPatch(emember->path)); + if (emember->expr) + CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(emember->expr)); + CError_ASSERT(2968, !emember->templargs); + CPrec_NewPointerPatch(&p->list, CPrec_GetNameSpaceObjectListPatch(emember->list)); + + return p; +} + +static ENode *CPrec_GetExpressionPatch(ENode *expr) { + ENode *p; + + if (ENODE_IS(expr, ETEMPLDEP) && expr->data.templdep.subtype == TDE_SOURCEREF) + expr->data.templdep.u.sourceref.token = NULL; + + p = CPrec_AppendAlign(); + CPrec_AppendData(expr, sizeof(ENode)); + + CPrec_NewPointerPatch(&p->rtype, CPrec_GetTypePatch(expr->rtype)); + + switch (expr->type) { + ENODE_CASE_MONADIC: + CPrec_NewPointerPatch(&p->data.monadic, CPrec_GetExpressionPatch(expr->data.monadic)); + break; + ENODE_CASE_DIADIC_ALL: + CPrec_NewPointerPatch(&p->data.diadic.left, CPrec_GetExpressionPatch(expr->data.diadic.left)); + CPrec_NewPointerPatch(&p->data.diadic.right, CPrec_GetExpressionPatch(expr->data.diadic.right)); + break; + case ECOND: + CPrec_NewPointerPatch(&p->data.cond.cond, CPrec_GetExpressionPatch(expr->data.cond.cond)); + CPrec_NewPointerPatch(&p->data.cond.expr1, CPrec_GetExpressionPatch(expr->data.cond.expr1)); + CPrec_NewPointerPatch(&p->data.cond.expr2, CPrec_GetExpressionPatch(expr->data.cond.expr2)); + break; + case ESTRINGCONST: + CPrec_RawMemPatch(&p->data.string.data, expr->data.string.data, expr->data.string.size); + break; + case EOBJREF: + CPrec_NewPointerPatch(&p->data.objref, CPrec_GetObjectPatch(expr->data.objref)); + break; + case EOBJLIST: + CPrec_NewPointerPatch(&p->data.objlist.list, CPrec_GetNameSpaceObjectListPatch(expr->data.objlist.list)); + CError_ASSERT(3043, !expr->data.objlist.templargs); + if (expr->data.objlist.name) + CPrec_NamePatch(&p->data.objlist.name, expr->data.objlist.name); + break; + case EMFPOINTER: + CPrec_NewPointerPatch(&p->data.mfpointer.accessnode, CPrec_GetExpressionPatch(expr->data.mfpointer.accessnode)); + CPrec_NewPointerPatch(&p->data.mfpointer.mfpointer, CPrec_GetExpressionPatch(expr->data.mfpointer.mfpointer)); + break; + case ENULLCHECK: + CPrec_NewPointerPatch(&p->data.nullcheck.nullcheckexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.nullcheckexpr)); + CPrec_NewPointerPatch(&p->data.nullcheck.condexpr, CPrec_GetExpressionPatch(expr->data.nullcheck.condexpr)); + break; + case ETEMP: + CPrec_NewPointerPatch(&p->data.temp.type, CPrec_GetTypePatch(expr->data.temp.type)); + break; + case EFUNCCALL: + case EFUNCCALLP: + CPrec_NewPointerPatch(&p->data.funccall.funcref, CPrec_GetExpressionPatch(expr->data.funccall.funcref)); + CPrec_NewPointerPatch(&p->data.funccall.functype, CPrec_GetTypePatch(TYPE(expr->data.funccall.functype))); + if (expr->data.funccall.args) + CPrec_NewPointerPatch(&p->data.funccall.args, CPrec_GetExpressionListPatch(expr->data.funccall.args)); + break; + case EMEMBER: + CPrec_NewPointerPatch(&p->data.emember, CPrec_GetEMemberInfoPatch(expr->data.emember)); + break; + case ETEMPLDEP: + switch (expr->data.templdep.subtype) { + case TDE_PARAM: + break; + case TDE_SIZEOF: + case TDE_ALIGNOF: + CPrec_NewPointerPatch(&p->data.templdep.u.typeexpr.type, CPrec_GetTypePatch(expr->data.templdep.u.typeexpr.type)); + break; + case TDE_CAST: + if (expr->data.templdep.u.cast.args) + CPrec_NewPointerPatch(&p->data.templdep.u.cast.args, CPrec_GetExpressionListPatch(expr->data.templdep.u.cast.args)); + CPrec_NewPointerPatch(&p->data.templdep.u.cast.type, CPrec_GetTypePatch(expr->data.templdep.u.cast.type)); + break; + case TDE_QUALNAME: + CPrec_NamePatch(&p->data.templdep.u.qual.name, expr->data.templdep.u.qual.name); + CPrec_NewPointerPatch(&p->data.templdep.u.qual.type, CPrec_GetTypePatch(TYPE(expr->data.templdep.u.qual.type))); + break; + case TDE_OBJ: + CPrec_NewPointerPatch(&p->data.templdep.u.obj, CPrec_GetObjectPatch(expr->data.templdep.u.obj)); + break; + case TDE_SOURCEREF: + CPrec_NewPointerPatch(&p->data.templdep.u.sourceref.expr, CPrec_GetExpressionPatch(expr->data.templdep.u.sourceref.expr)); + break; + case TDE_ADDRESS_OF: + CPrec_NewPointerPatch(&p->data.templdep.u.monadic, CPrec_GetExpressionPatch(expr->data.templdep.u.monadic)); + break; + default: + CError_FATAL(3136); + } + break; + case EINTCONST: + case EFLOATCONST: + case EPRECOMP: + case EARGOBJ: + case ELOCOBJ: + case ELABEL: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + default: + CError_FATAL(3142); + } + + return p; +} + +static CI_Switch *CPrec_GetSwitchInfoPatch(CI_Switch *si) { + CI_Switch *p = CPrec_AppendAlign(); + CPrec_AppendData(si, sizeof(CI_Switch) + sizeof(CI_SwitchCase) * (si->numcases - 1)); + + CPrec_NewPointerPatch(&p->expr, CPrec_GetExpressionPatch(si->expr)); + CPrec_NewPointerPatch(&p->unkSwitch8, CPrec_GetTypePatch(si->unkSwitch8)); + return p; +} + +static InlineAsm *CPrec_GetInlineAsmPatch(InlineAsm *ia, SInt32 size) { + InlineAsm *p; + SInt32 index; + SInt32 offset; + Object *object; + + p = CPrec_AppendAlign(); + CPrec_AppendData(ia, size); + + index = 0; + while (1) { + object = InlineAsm_GetObjectOffset(ia, index, &offset); + if (!object) + break; + + object = CPrec_GetObjectPatch(object); + CPrec_NewPointerPatch((char *) p + offset, object); + index++; + } + + return p; +} + +static CI_Statement *CPrec_GetStatementPatch(CI_Statement *stmt, short count) { + short i; + CI_Statement *first, *current; + + for (i = 0; i < count; i++) { + stmt[i].sourcefilepath = NULL; + stmt[i].sourceoffset = -1; + } + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(stmt, sizeof(CI_Statement) * count); + + for (i = 0; i < count; i++) { + if (stmt->dobjstack) + CPrec_NewPointerPatch(¤t->dobjstack, CPrec_GetExceptionPatch(stmt->dobjstack)); + + switch (stmt->type) { + case ST_EXPRESSION: + case ST_RETURN: + case ST_BEGINCATCH: + case ST_ENDCATCH: + case ST_ENDCATCHDTOR: + if (stmt->u.expr) + CPrec_NewPointerPatch(¤t->u.expr, CPrec_GetExpressionPatch(stmt->u.expr)); + break; + case ST_IFGOTO: + case ST_IFNGOTO: + CPrec_NewPointerPatch(¤t->u.ifgoto.expr, CPrec_GetExpressionPatch(stmt->u.ifgoto.expr)); + break; + case ST_SWITCH: + CPrec_NewPointerPatch(¤t->u.switchdata, CPrec_GetSwitchInfoPatch(stmt->u.switchdata)); + break; + case ST_ASM: + CPrec_NewPointerPatch(¤t->u.asmdata.data, CPrec_GetInlineAsmPatch(stmt->u.asmdata.data, stmt->u.asmdata.size)); + break; + case ST_NOP: + case ST_LABEL: + case ST_GOTO: + break; + default: + CError_FATAL(3261); + } + + current++; + stmt++; + } + + return first; +} + +static CI_Var *CPrec_GetLocObjectPatch(CI_Var *obj, short count) { + CI_Var *first, *current; + short i; + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(obj, sizeof(CI_Var) * count); + + for (i = 0; i < count; i++) { + CPrec_NamePatch(¤t->name, obj->name); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(obj->type)); + current++; + obj++; + } + + return first; +} + +static CI_FuncData *CPrec_GetInlineFuncPatch(CI_FuncData *ifunc) { + CI_FuncData *p; + + memclrw(&ifunc->fileoffset, sizeof(FileOffsetInfo)); + ifunc->symdecloffset = 0; + ifunc->functionbodyoffset = 0; + ifunc->functionbodypath = NULL; + ifunc->symdeclend = 0; + + p = CPrec_AppendAlign(); + CPrec_AppendData(ifunc, sizeof(CI_FuncData)); + + if (ifunc->numarguments) + CPrec_NewPointerPatch(&p->arguments, CPrec_GetLocObjectPatch(ifunc->arguments, ifunc->numarguments)); + if (ifunc->numlocals) + CPrec_NewPointerPatch(&p->locals, CPrec_GetLocObjectPatch(ifunc->locals, ifunc->numlocals)); + if (ifunc->numstatements) + CPrec_NewPointerPatch(&p->statements, CPrec_GetStatementPatch(ifunc->statements, ifunc->numstatements)); + + return p; +} + +static ObjEnumConst *CPrec_GetObjEnumConstPatch(ObjEnumConst *obj) { + AddrPatch *addrPatch; + ObjEnumConst *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, first); + + do { + CPrec_AppendData(obj, sizeof(ObjEnumConst)); + if (cprec_dowrite) { + CError_ASSERT(3349, obj->access != 255); + obj->access = 255; + } + CPrec_NamePatch(¤t->name, obj->name); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch( obj->type)); + + if (!obj->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(obj->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + obj = obj->next; + CPrec_NewAddrPatch(obj, next); + } + } while (1); + + return first; +} + +static ObjType *CPrec_GetObjTypePatch(ObjType *obj) { + AddrPatch *addrPatch; + ObjType *p; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + CPrec_AppendData(obj, sizeof(ObjType)); + CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); + return p; +} + +static ObjTypeTag *CPrec_GetObjTypeTagPatch(ObjTypeTag *obj) { + AddrPatch *addrPatch; + ObjTypeTag *p; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + CPrec_AppendData(obj, sizeof(ObjTypeTag)); + CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); + return p; +} + +static ObjNameSpace *CPrec_GetObjNameSpacePatch(ObjNameSpace *obj) { + AddrPatch *addrPatch; + ObjNameSpace *p; + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + CPrec_AppendData(obj, sizeof(ObjNameSpace)); + CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); + return p; +} + +static ObjMemberVar *CPrec_GetObjMemberVarPatch(ObjMemberVar *ivar) { + AddrPatch *addrPatch; + ObjMemberVar *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(ivar))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(ivar, first); + + while (1) { + if (ivar->has_path) { + CPrec_AppendData(ivar, sizeof(ObjMemberVarPath)); + if (OBJ_MEMBER_VAR_PATH(ivar)->path) + CPrec_NewPointerPatch( + &OBJ_MEMBER_VAR_PATH(current)->path, + CPrec_GetClassAccessPatch(OBJ_MEMBER_VAR_PATH(ivar)->path)); + } else { + CPrec_AppendData(ivar, sizeof(ObjMemberVar)); + } + + if (ivar->name) + CPrec_NamePatch(¤t->name, ivar->name); + CPrec_NewPointerPatch(¤t->type, CPrec_GetTypePatch(ivar->type)); + + if (!ivar->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(ivar->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + + current = next; + ivar = ivar->next; + CPrec_NewAddrPatch(ivar, current); + } + + return first; +} + +static DefArgCtorInfo *CPrec_GetDefArgCtorInfoPatch(DefArgCtorInfo *dac) { + DefArgCtorInfo *p = CPrec_AppendAlign(); + CPrec_AppendData(dac, sizeof(DefArgCtorInfo)); + CPrec_NewPointerPatch(&p->default_func, CPrec_GetObjectPatch(dac->default_func)); + CPrec_NewPointerPatch(&p->default_arg, CPrec_GetExpressionPatch(dac->default_arg)); + return p; +} + +static InlineXRef *CPrec_GetInlineXRefPatch(InlineXRef *ix) { + InlineXRef *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(ix, sizeof(InlineXRef) + sizeof(XRefOffset) * (ix->numxrefs - 1)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ix->object)); + + if (!ix->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + ix = ix->next; + } while (1); + + return first; +} + +static Object *CPrec_GetObjectPatch(Object *obj) { + AddrPatch *addrPatch; + Object *p; + + if (CWUserBreak(cparams.context) != cwNoErr) + CError_UserBreak(); + + if ((addrPatch = CPrec_FindAddrPatch(obj))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(obj, p); + + obj->toc = NULL; + + if ((obj->qual & Q_IS_TEMPLATED) && obj->datatype != DALIAS) { + CPrec_AppendData(obj, sizeof(ObjectTemplated)); + CPrec_NewPointerPatch(&OBJECT_TEMPL(p)->parent, CPrec_GetObjectPatch(OBJECT_TEMPL(obj)->parent)); + } else { + CPrec_AppendData(obj, sizeof(Object)); + } + + if (obj->nspace) + CPrec_NewPointerPatch(&p->nspace, CPrec_GetNameSpacePatch(obj->nspace)); + if (obj->name) + CPrec_NamePatch(&p->name, obj->name); + CPrec_NewPointerPatch(&p->type, CPrec_GetTypePatch(obj->type)); + + switch (obj->datatype) { + case DABSOLUTE: + break; + + case DLOCAL: + CError_FATAL(3580); + break; + + case DFUNC: + case DVFUNC: + if (IS_TEMPL_FUNC(obj->type)) + CPrec_NewPointerPatch(&p->u.func.u.templ, CPrec_GetTemplateFunctionPatch(obj->u.func.u.templ)); + else if ((obj->qual & Q_INLINE) && obj->u.func.u.ifuncdata) + CPrec_NewPointerPatch(&p->u.func.u.ifuncdata, CPrec_GetInlineFuncPatch(obj->u.func.u.ifuncdata)); + + if (obj->u.func.defargdata) + CPrec_NewPointerPatch(&p->u.func.defargdata, CPrec_GetDefArgCtorInfoPatch(obj->u.func.defargdata)); + if (obj->u.func.linkname) + CPrec_NamePatch(&p->u.func.linkname, obj->u.func.linkname); + if (obj->u.func.inst) + CPrec_NewPointerPatch(&p->u.func.inst, CPrec_GetTemplFuncInstancePatch(obj->u.func.inst)); + break; + + case DDATA: + CError_ASSERT(3622, !obj->u.data.info); + if (obj->qual & Q_INLINE_DATA) { + switch (obj->type->type) { + case TYPEINT: + case TYPEENUM: + case TYPEPOINTER: + break; + case TYPEFLOAT: + CPrec_RawMemPatch(&p->u.data.u.floatconst, obj->u.data.u.floatconst, sizeof(Float)); + break; + default: + CError_FATAL(3638); + } + } + if (obj->u.data.linkname) + CPrec_NamePatch(&p->u.data.linkname, obj->u.data.linkname); + break; + + case DINLINEFUNC: + CPrec_RawMemPatch(&p->u.ifunc.data, obj->u.ifunc.data, obj->u.ifunc.size); + if (obj->u.ifunc.xrefs) + CPrec_NewPointerPatch(&p->u.ifunc.xrefs, CPrec_GetInlineXRefPatch(obj->u.ifunc.xrefs)); + break; + + case DALIAS: + CPrec_NewPointerPatch(&p->u.alias.object, CPrec_GetObjectPatch(obj->u.alias.object)); + if (obj->u.alias.member) + CPrec_NewPointerPatch(&p->u.alias.member, CPrec_GetClassAccessPatch(obj->u.alias.member)); + break; + + default: + CError_FATAL(3677); + } + + if (cprec_dowrite) + obj->datatype = -1; + + return p; +} + +static ObjBase *CPrec_GetObjBasePatch(ObjBase *obj) { + switch (obj->otype) { + default: + CError_FATAL(3694); + case OT_ENUMCONST: + return (ObjBase *) CPrec_GetObjEnumConstPatch((ObjEnumConst *) obj); + case OT_TYPE: + return (ObjBase *) CPrec_GetObjTypePatch((ObjType *) obj); + case OT_TYPETAG: + return (ObjBase *) CPrec_GetObjTypeTagPatch((ObjTypeTag *) obj); + case OT_NAMESPACE: + return (ObjBase *) CPrec_GetObjNameSpacePatch((ObjNameSpace *) obj); + case OT_MEMBERVAR: + return (ObjBase *) CPrec_GetObjMemberVarPatch((ObjMemberVar *) obj); + case OT_OBJECT: + return (ObjBase *) CPrec_GetObjectPatch((Object *) obj); + } +} + +static ObjectList *CPrec_GetObjectListPatch(ObjectList *ol) { + AddrPatch *addrPatch; + ObjectList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(ol))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(ol, first); +restart: + CPrec_AppendData(ol, sizeof(ObjectList)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(ol->object)); + if (ol->next) { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + ol = ol->next; + goto restart; + } + + return first; +} + +static NameSpaceObjectList *CPrec_GetNameSpaceObjectListPatch(NameSpaceObjectList *nsol) { + AddrPatch *addrPatch; + NameSpaceObjectList *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(nsol))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(nsol, first); + + do { + CPrec_AppendData(nsol, sizeof(NameSpaceObjectList)); + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjBasePatch(nsol->object)); + + if (!nsol->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(nsol->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + nsol = nsol->next; + CPrec_NewAddrPatch(nsol, next); + } + } while (1); + + return first; +} + +static NameSpaceName *CPrec_GetNameSpaceNamePatch(NameSpaceName *nsn, Boolean flag) { + AddrPatch *addrPatch; + NameSpaceName *first, *current, *next; + + if ((addrPatch = CPrec_FindAddrPatch(nsn))) + return addrPatch->value; + + first = current = CPrec_AppendAlign(); + CPrec_NewAddrPatch(nsn, first); + + do { + CPrec_AppendData(nsn, sizeof(NameSpaceName)); + CPrec_NamePatch(¤t->name, nsn->name); + CPrec_NewPointerPatch(¤t->first.object, CPrec_GetObjBasePatch(nsn->first.object)); + if (nsn->first.next) + CPrec_NewPointerPatch(¤t->first.next, CPrec_GetNameSpaceObjectListPatch(nsn->first.next)); + + if (!nsn->next) + break; + + if ((addrPatch = CPrec_FindAddrPatch(nsn->next))) { + CPrec_NewPointerPatch(¤t->next, addrPatch->value); + break; + } else { + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + nsn = nsn->next; + CPrec_NewAddrPatch(nsn, next); + } + } while (!flag || !cprec_dowrite || CPrec_FlushBufferCheck() == noErr); + + return first; +} + +static NameSpaceList *CPrec_GetNameSpaceListPatch(NameSpaceList *nsl) { + NameSpaceList *first, *current, *next; + first = current = CPrec_AppendAlign(); + + do { + CPrec_AppendData(nsl, sizeof(NameSpaceList)); + CPrec_NewPointerPatch(¤t->nspace, CPrec_GetNameSpacePatch(nsl->nspace)); + + if (!nsl->next) + break; + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + nsl = nsl->next; + } while (1); + + return first; +} + +static NameSpace *CPrec_GetNameSpacePatch(NameSpace *nspace) { + NameSpace *p; + AddrPatch *addrPatch; + + if ((addrPatch = CPrec_FindAddrPatch(nspace))) + return addrPatch->value; + + p = CPrec_AppendAlign(); + CPrec_NewAddrPatch(nspace, p); + CPrec_AppendData(nspace, sizeof(NameSpace)); + + if (nspace->parent) + CPrec_NewPointerPatch(&p->parent, CPrec_GetNameSpacePatch(nspace->parent)); + if (nspace->name) + CPrec_NamePatch(&p->name, nspace->name); + if (nspace->usings) + CPrec_NewPointerPatch(&p->usings, CPrec_GetNameSpaceListPatch(nspace->usings)); + if (nspace->theclass) + CPrec_NewPointerPatch(&p->theclass, CPrec_GetTypePatch((Type *) nspace->theclass)); + + if (nspace->is_hash) { + char *hash; + int i; + hash = CPrec_AppendAlign(); + CPrec_NewPointerPatch(&p->data.hash, hash); + CPrec_AppendData(nspace->data.hash, sizeof(NameSpaceName *) * 1024); + for (i = 0; i < 1024; i++) { + if (nspace->data.hash[i]) + CPrec_NewPointerPatch(hash + (i * sizeof(NameSpaceName *)), CPrec_GetNameSpaceNamePatch(nspace->data.hash[i], 0)); + } + } else if (nspace->data.list) { + CPrec_NewPointerPatch(&p->data.list, CPrec_GetNameSpaceNamePatch(nspace->data.list, 0)); + } + + return p; +} + +static void CPrec_DumpRootNameSpace(void) { + NameSpaceList *nslist; + NameSpaceName *nsname; + int i; + + CError_ASSERT(3905, cscope_root->is_hash); + + if (cscope_root->usings) { + nslist = CPrec_GetNameSpaceListPatch(cscope_root->usings); + if (cprec_dowrite) + cprec_header->usings = nslist; + } + + if (cprec_dowrite) + cprec_header->root_names = cscope_root->names; + + i = 0; + do { + if (cscope_root->data.hash[i]) { + nsname = CPrec_GetNameSpaceNamePatch(cscope_root->data.hash[i], 1); + if (cprec_dowrite) { + if (cprec_ioerror != noErr) + break; + cprec_header->root_nametable[i] = nsname; + } + } + } while (++i < 0x400); +} + +static CSOMStub *CPrec_GetSOMPatch(CSOMStub *stub) { + CSOMStub *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(stub, sizeof(CSOMStub)); + + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(stub->object)); + CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(stub->tclass))); + + if (!stub->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + stub = stub->next; + } + + return first; +} + +static OLinkList *CPrec_GetOLinkPatch(OLinkList *olink) { + OLinkList *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(olink, sizeof(OLinkList)); + + CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(olink->obj)); + + if (!olink->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + olink = olink->next; + } + + return first; +} + +static StaticData *CPrec_GetStaticDataPatch(StaticData *sd) { + StaticData *current, *first, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(sd, sizeof(StaticData)); + + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(sd->object)); + if (sd->buffer) + CPrec_RawMemPatch(¤t->buffer, sd->buffer, sd->object->type->size); + if (sd->links) + CPrec_NewPointerPatch(¤t->links, CPrec_GetOLinkPatch(sd->links)); + + if (!sd->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + sd = sd->next; + } + + return first; +} + +static CallbackAction *CPrec_GetCallbackPatch(CallbackAction *ca) { + CallbackAction *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(ca, sizeof(CallbackAction)); + + CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(ca->obj)); + CPrec_NewPointerPatch(¤t->tclass, CPrec_GetTypePatch(TYPE(ca->tclass))); + + if (!ca->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + ca = ca->next; + } + + return first; +} + +static ObjCSelector **CPrec_GetSelHashTablePatch(ObjCSelector **table) { + ObjCSelector **first, **current; + int i; + + first = current = CPrec_AppendAlign(); + CPrec_AppendData(table, sizeof(ObjCSelector *) * 0x400); + + for (i = 0; i < 0x400; i++) { + if (*table) + CPrec_NewPointerPatch(current, CPrec_GetObjCSelectorPatch(*table)); + table++; + current++; + } + + return first; +} + +static InitExpr *CPrec_GetIExpressionPatch(InitExpr *initexpr) { + InitExpr *first, *current, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + CPrec_AppendData(initexpr, sizeof(InitExpr)); + + CPrec_NewPointerPatch(¤t->object, CPrec_GetObjectPatch(initexpr->object)); + CPrec_NewPointerPatch(¤t->expr, CPrec_GetExpressionPatch(initexpr->expr)); + + if (!initexpr->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + initexpr = initexpr->next; + } + + return first; +} + +static CI_Action *CPrec_GetInlineActionPatch(CI_Action *act) { + CI_Action *current, *first, *next; + + first = current = CPrec_AppendAlign(); + while (1) { + if (act->actiontype == CI_ActionInlineFunc) + memclrw(&act->u.inlinefunc.fileoffset, sizeof(FileOffsetInfo)); + + CPrec_AppendData(act, sizeof(CI_Action)); + + CPrec_NewPointerPatch(¤t->obj, CPrec_GetObjectPatch(act->obj)); + + switch (act->actiontype) { + case CI_ActionInlineFunc: + if (act->u.inlinefunc.stream.firsttoken) + CPrec_NewPointerPatch( + ¤t->u.inlinefunc.stream.firsttoken, + CPrec_GetTStreamPatch(act->u.inlinefunc.stream.firsttoken, act->u.inlinefunc.stream.tokens)); + if (act->u.inlinefunc.tclass) + CPrec_NewPointerPatch(¤t->u.inlinefunc.tclass, CPrec_GetTypePatch(TYPE(act->u.inlinefunc.tclass))); + break; + + case CI_ActionMemberFunc: + CPrec_NewPointerPatch(¤t->u.memberfunc.templ, CPrec_GetTypePatch(TYPE(act->u.memberfunc.templ))); + CPrec_NewPointerPatch(¤t->u.memberfunc.inst, CPrec_GetTypePatch(TYPE(act->u.memberfunc.inst))); + CPrec_NewPointerPatch(¤t->u.memberfunc.tmemb, CPrec_GetTemplateMemberPatch(act->u.memberfunc.tmemb)); + break; + + case CI_ActionTemplateFunc: + CPrec_NewPointerPatch(¤t->u.templatefunc.func, CPrec_GetTemplateFunctionPatch(act->u.templatefunc.func)); + CPrec_NewPointerPatch(¤t->u.templatefunc.inst, CPrec_GetTemplFuncInstancePatch(act->u.templatefunc.inst)); + break; + + case CI_ActionDefaultFunc: + break; + + default: + CError_FATAL(4177); + } + + if (!act->next) + break; + + next = CPrec_AppendAlign(); + CPrec_NewPointerPatch(¤t->next, next); + current = next; + act = act->next; + } + + return first; +} + +static void CPrec_GenerateBuiltinPatches(void) { + int x; + int y; + Patch *scan; + + for (x = 0; x < cprec_builtins; x++) { + y = 0; + for (scan = cprec_builtin[x].patches; scan; scan = scan->next) + ++y; + + if (y) { + CPrec_AppendWord32(y); + CPrec_AppendWord32(x); + for (scan = cprec_builtin[x].patches; scan; scan = scan->next) + CPrec_AppendWord32(scan->offset); + } + } + + CPrec_AppendWord32(0); +} + +static void CPrec_GenerateTokenStreamPatches(void) { + TokenPatch *scan; + + for (scan = cprec_tokenpatches; scan; scan = scan->next) { + CPrec_AppendWord32((UInt32) scan->tokens); + CPrec_AppendWord32((UInt32) scan->count); + } + CPrec_AppendWord32(0); +} + +static OSErr CPrec_CompressWrite(const char *data, SInt32 size) { + char buf[2048 + 256]; + OSErr err; + int bufpos = 0; + int blockstart; + int c; + const char *p = data; + const char *end = data + size; + + for (;;) { + if (p < end) { + if (!*p) { + c = 224; + while (!*p && p < end && c < 256) { + c++; + p++; + } + buf[bufpos++] = c - 1; + } else { + blockstart = bufpos++; + c = 0; + while (p < end && c < 224) { + if (!p[0] && !p[1]) { + break; + } else { + buf[bufpos++] = *(p++); + c++; + } + } + buf[blockstart] = c - 1; + } + } + + if (p >= end || bufpos > 2048) { + if ((err = COS_FileWrite(cprec_refnum, buf, bufpos))) + return err; + + if (p >= end) + break; + else + bufpos = 0; + } + } + + return noErr; +} + +static OSErr CPrec_FlushRawBuffer(void) { + OSErr err; + + if (cprec_dowrite) { + CPrec_AppendAlign(); + cprec_zero_offset += cprec_glist.size; + COS_LockHandle(cprec_glist.data); + err = CPrec_CompressWrite(*cprec_glist.data, cprec_glist.size); + COS_UnlockHandle(cprec_glist.data); + cprec_glist.size = 0; + + return err; + } else { + return noErr; + } +} + +static OSErr CPrec_FlushBufferCheck(void) { + static SInt32 flushmax; + OSErr err; + + if (cprec_glist.size > flushmax) + flushmax = cprec_glist.size; + + if (cprec_glist.size > 10000) { + err = CPrec_FlushRawBuffer(); + if (err) { + cprec_ioerror = err; + return err; + } + } + + return noErr; +} + +static int CPrec_CompressPatches(void) { + Patch *scan; + int count; + SInt32 last; + + cprec_glist.size = 0; + + scan = cprec_patch_list; + last = 0; + count = 0; + while (scan) { + CError_ASSERT(4339, (scan->offset & 0x80000001) == 0); + + if ((scan->offset - last) >= -128 && (scan->offset - last) <= 126) + CPrec_AppendByte(((scan->offset - last) >> 1) | 0x80); + else + CPrec_AppendWord32(scan->offset); + + last = scan->offset; + scan = scan->next; + count++; + } + + return count; +} + +static OSErr CPrec_DumpColorSymbolTable(Boolean doWrite) { + OSErr err; + + freelheap(); + + CPrec_InitAddressHashTable(); + CPrec_InitPointerHashTable(); + + cprec_patch_list = NULL; + cprec_tokenpatches = NULL; + cprec_offset = 0; + cprec_zero_offset = 0; + cprec_dowrite = doWrite; + cprec_ioerror = noErr; + + CPrec_SetupBuiltIn(); + CPrec_AppendWord32(0); + + CPrec_DumpNameTable(); + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + + CPrec_DumpMacroTable(); + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + + CPrec_DumpRootNameSpace(); + if (doWrite) { + if (cprec_ioerror != noErr) + return cprec_ioerror; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (ctempl_templates) { + TemplClass *p = TEMPL_CLASS(CPrec_GetTypePatch(TYPE(ctempl_templates))); + if (doWrite) + cprec_header->ctempl_templates = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (ctempl_templatefuncs) { + TemplateFunction *p = CPrec_GetTemplateFunctionPatch(ctempl_templatefuncs); + if (doWrite) + cprec_header->ctempl_templatefuncs = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (csom_stubs) { + CSOMStub *p = CPrec_GetSOMPatch(csom_stubs); + if (doWrite) + cprec_header->csom_stubs = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cprec_staticdata) { + StaticData *p = CPrec_GetStaticDataPatch(cprec_staticdata); + if (doWrite) + cprec_header->cprec_staticdata = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (callbackactions) { + CallbackAction *p = CPrec_GetCallbackPatch(callbackactions); + if (doWrite) + cprec_header->callbackactions = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_type_class) { + Type *p = CPrec_GetTypePatch(cobjc_type_class); + if (doWrite) + cprec_header->cobjc_type_class = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_type_id) { + Type *p = CPrec_GetTypePatch(cobjc_type_id); + if (doWrite) + cprec_header->cobjc_type_id = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_type_sel) { + Type *p = CPrec_GetTypePatch(cobjc_type_sel); + if (doWrite) + cprec_header->cobjc_type_sel = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_selhashtable) { + ObjCSelector **p = CPrec_GetSelHashTablePatch(cobjc_selhashtable); + if (doWrite) + cprec_header->cobjc_selhashtable = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_classdefs) { + BClassList *p = CPrec_GetBClassListPatch(cobjc_classdefs); + if (doWrite) + cprec_header->cobjc_classdefs = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cobjc_protocols) { + ObjCProtocol *p = CPrec_GetObjCProtocolPatch(cobjc_protocols); + if (doWrite) + cprec_header->cobjc_protocols = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (init_expressions) { + InitExpr *p = CPrec_GetIExpressionPatch(init_expressions); + if (doWrite) + cprec_header->init_expressions = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + if (cinline_tactionlist) { + CI_Action *p = CPrec_GetInlineActionPatch(cinline_tactionlist); + if (doWrite) + cprec_header->cinline_tactionlist = p; + if ((err = CPrec_FlushRawBuffer()) != noErr) + return err; + } + + return noErr; +} + +static OSErr CPrec_FileAlign(short refnum, SInt32 *len) { + OSErr err; + SInt32 n; + char buf[8]; + + n = *len; + if ((n & 7) == 0) + return noErr; + + memclrw(buf, 8); + err = COS_FileWrite(refnum, buf, n = 8 - (n & 7)); + *len += n; + + return err; +} + +static OSErr CPrec_WriteFile(void) { + char str[128]; + int i; + HashNameNode *name; + OSErr err; + SInt32 offset; + + if (InitGList(&cprec_glist, 0x40000)) + CError_NoMem(); + + CompilerGetCString(10, str); + CWShowStatus(cparams.context, str, ""); + CPrep_RemoveSpecialMacros(); + + for (i = 0; i < 0x800; i++) { + for (name = name_hash_nodes[i]; name; name = name->next) + name->id = 0; + } + + if ((err = CPrec_DumpColorSymbolTable(0)) != noErr) + return err; + + CompilerGetCString(11, str); + CWShowStatus(cparams.context, str, ""); + + cprec_header = galloc(sizeof(Header)); + memclrw(cprec_header, sizeof(Header)); + + cprec_header->magic = 0xBEEFFACE; + cprec_header->version = 1047; + cprec_header->target = 2; + cprec_header->check_header_flags = copts.checkprecompflags; + cprec_header->cplusplus = copts.cplusplus; + cprec_header->uniqueID = CParser_GetUniqueID(); + cprec_header->cobjc_selrefcount = cobjc_selrefcount; + cprec_header->cobjc_classrefcount = cobjc_classrefcount; + cprec_header->cobjc_stringcount = cobjc_stringcount; + + if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) + return err; + + offset = sizeof(Header); + + if ((err = CPrec_DumpColorSymbolTable(1)) != noErr) + return err; + + cprec_header->x28 = cprec_offset; + cprec_header->x30 = offset; + + if ((err = COS_FileGetPos(cprec_refnum, &offset)) != noErr) + return err; + + cprec_header->x2C = offset - cprec_header->x30; + + cprec_header->compressedPatchCount = CPrec_CompressPatches(); + cprec_header->compressedPatchSize = cprec_glist.size; + cprec_header->compressedPatchOffset = offset; + + if (cprec_header->compressedPatchCount) { + if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) + return err; + offset += cprec_glist.size; + } + + if ((err = CPrec_FileAlign(cprec_refnum, &offset)) != noErr) + return err; + + cprec_glist.size = 0; + CPrec_GenerateBuiltinPatches(); + cprec_header->builtinPatchSize = cprec_glist.size; + cprec_header->builtinPatchOffset = offset; + + if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) + return err; + offset += cprec_glist.size; + + if (cprec_tokenpatches) { + cprec_glist.size = 0; + CPrec_GenerateTokenStreamPatches(); + cprec_header->tokenStreamPatchSize = cprec_glist.size; + cprec_header->tokenStreamPatchOffset = offset; + + if ((err = COS_FileWrite(cprec_refnum, *cprec_glist.data, cprec_glist.size)) != noErr) + return err; + offset += cprec_glist.size; + } + + if ((err = COS_FileSetPos(cprec_refnum, 0)) != noErr) + return err; + + if ((err = COS_FileWrite(cprec_refnum, cprec_header, sizeof(Header))) != noErr) + return err; + + return noErr; +} + +void PrecompilerWrite(void) { + OSErr err; + short strindex; + char str[128]; + FSSpec spec; + + spec = cparamblkptr->sourcefile; + if (CWGetPrecompiledHeaderSpec(cparamblkptr->context, &spec, precomp_target_str) == cwNoErr) { + strindex = 3; + err = COS_FileNew(&spec, &cprec_refnum, copts.appltype, copts.headtype); + if (err == noErr) { + strindex = 4; + err = CPrec_WriteFile(); + } + CleanupPrecompiler(); + + if (err != noErr) { + CompilerGetCString(strindex, str); + sprintf(string, str, err); + CWReportMessage(cparamblkptr->context, NULL, string, NULL, messagetypeError, 0); + } else { + CWFileTime time = 0; + CWSetModDate(cparamblkptr->context, &spec, &time, 1); + } + } +} + +static void CPrec_ReadData(SInt32 offset, void *buffer, SInt32 size) { + if ( + COS_FileSetPos(cprec_refnum, offset) != noErr || + COS_FileRead(cprec_refnum, buffer, size) != noErr + ) + CError_ErrorTerm(CErrorStr181); +} + +static void CPrec_ReadRawBuffer(void) { + UInt8 *buffer; + UInt8 *work; + UInt8 *end; + UInt32 size; + int ch; + + if (!cprec_buffer) { + size = cprec_header->x28 + (cprec_header->x28 >> 7) + 64; + buffer = galloc(size); + cprec_rawbuffer = buffer; + + work = buffer + size - cprec_header->x2C; + CPrec_ReadData(cprec_header->x30, work, cprec_header->x2C); + } else { + buffer = galloc(cprec_header->x28); + cprec_rawbuffer = buffer; + work = (UInt8 *) cprec_buffer + cprec_header->x30; + } + + end = work + cprec_header->x2C; + + while (work < end) { + if ((ch = *(work++)) >= 0xE0) { + ch -= 0xE0; + do { + *(buffer++) = 0; + } while (--ch >= 0); + } else { + do { + *(buffer++) = *(work++); + } while (--ch >= 0); + } + } + + if (work != end || buffer != RESOLVE_RAW_BUFFER(cprec_header->x28)) + CError_ErrorTerm(CErrorStr181); +} + +static void CPrec_RelocateRawBuffer(void) { + UInt8 *patches; + UInt32 offset; + UInt8 *dest; + SInt32 count; + UInt8 *patch; + UInt32 var; + + if ((count = cprec_header->compressedPatchCount)) { + if (!cprec_buffer) { + patches = lalloc(cprec_header->compressedPatchSize); + CPrec_ReadData(cprec_header->compressedPatchOffset, patches, cprec_header->compressedPatchSize); + } else { + patches = RESOLVE_BUFFER(cprec_header->compressedPatchOffset); + } + + offset = 0; + patch = patches; + dest = cprec_rawbuffer; + do { + if (!(*patch & 0x80)) { + ((UInt8 *) &var)[0] = *(patch++); + ((UInt8 *) &var)[1] = *(patch++); + ((UInt8 *) &var)[2] = *(patch++); + ((UInt8 *) &var)[3] = *(patch++); + offset = var; + } else { + offset += (char) (*(patch++) * 2); + } + *((uintptr_t *) (dest + offset)) += (uintptr_t) dest; + } while (--count > 0); + + freelheap(); + + if (patch != (patches + cprec_header->compressedPatchSize)) + CError_ErrorTerm(CErrorStr181); + } +} + +static void CPrec_RelocateBuiltins(void) { + UInt32 *patches; + void *builtin; + UInt32 count; + UInt8 *buffer; + + if (cprec_header->builtinPatchSize) { + CPrec_SetupBuiltInArray(); + if (!cprec_buffer) { + patches = lalloc(cprec_header->builtinPatchSize); + CPrec_ReadData(cprec_header->builtinPatchOffset, patches, cprec_header->builtinPatchSize); + } else { + patches = RESOLVE_BUFFER(cprec_header->builtinPatchOffset); + } + + buffer = cprec_rawbuffer; + while (1) { + if (!(count = *(patches++))) + break; + + builtin = cprec_builtin_array[*(patches++)]; + do { + *((void **) (buffer + *(patches++))) = builtin; + } while (--count); + } + } +} + +static void CPrec_RelocateTokenStreams(void) { + UInt32 *patches; + UInt32 count; + TStreamElement *tokens; + UInt8 *buffer; + CPrepFileInfo *file; + SInt32 pos; + + if (cprec_header->tokenStreamPatchSize) { + CPrep_GetPrepPos(&file, &pos); + + if (!cprec_buffer) { + patches = lalloc(cprec_header->tokenStreamPatchSize); + CPrec_ReadData(cprec_header->tokenStreamPatchOffset, patches, cprec_header->tokenStreamPatchSize); + } else { + patches = RESOLVE_BUFFER(cprec_header->tokenStreamPatchOffset); + } + + buffer = cprec_rawbuffer; + while (1) { + if (!*patches) + break; + + tokens = (TStreamElement *) (buffer + *(patches++)); + count = *(patches++); + + while (count--) { + tokens->tokenfile = file; + tokens->tokenoffset = pos; + tokens++; + } + } + } +} + +static void CPrec_RelocateMacroTable(void) { + int i; + int j; + int count; + UInt8 *buffer; + Macro **prec_table; + Macro **table; + Macro *macro; + uintptr_t offset; + + buffer = cprec_rawbuffer; + prec_table = cprec_header->macrotable; + table = macrohashtable; + + i = 0; + do { + for (macro = *table; macro; macro = macro->next) { + macro->name = GetHashNameNodeExport(macro->name->name); + count = macro->xC & 0x7FFF; + for (j = 1; j < count; j++) + macro->names[j - 1] = GetHashNameNodeExport(macro->names[j - 1]->name); + } + + if ((offset = (uintptr_t) *prec_table)) { + if (*table) { + macro = (Macro *) (buffer + offset); + while (macro->next) + macro = macro->next; + macro->next = *table; + } + *table = (Macro *) (buffer + offset); + } + + prec_table++; + table++; + } while (++i < 0x800); +} + +static void CPrec_RelocateTable(void **table, int size, void **dest) { + int i; + void *buffer = cprec_rawbuffer; + + for (i = 0; i < size; i++) { + if (*table) + *dest = (char *) buffer + (uintptr_t) *table; + else + *dest = NULL; + table++; + dest++; + } +} + +static void CPrec_RelocateRootNameSpace(void) { + CError_ASSERT(4981, cscope_root->is_hash); + + cscope_root->names = cprec_header->root_names; + CPrec_RelocateTable( + (void **) cprec_header->root_nametable, + 0x400, + (void **) cscope_root->data.hash); +} + +static void CPrec_FixNameIds(void) { + int i; + HashNameNode *node; + + for (i = 0; i < 2048; i++) { + for (node = name_hash_nodes[i]; node; node = node->next) + node->id = -1; + } +} + +static void CPrec_DefineStaticData(void) { + StaticData *sd = cprec_staticdata; + cprec_staticdata = NULL; + + while (sd) { + CInit_DeclareData(sd->object, sd->buffer, sd->links, sd->size); + sd = sd->next; + } +} + +void PrecompilerRead(short refnum, void *buffer) { + cprec_refnum = refnum; + cprec_buffer = buffer; + + CPrep_RemoveSpecialMacros(); + + if (!CScope_IsEmptySymTable()) + CError_ErrorTerm(CErrorStr180); + + if (!cprec_buffer) { + cprec_header = galloc(sizeof(Header)); + CPrec_ReadData(0, cprec_header, sizeof(Header)); + } else { + cprec_header = cprec_buffer; + } + + if (cprec_header->magic != 0xBEEFFACE) + CError_ErrorTerm(CErrorStr181); + if (cprec_header->version != 1047) + CError_ErrorTerm(CErrorStr222); + if (cprec_header->target != 2) + CError_ErrorTerm(CErrorStr223); + + copts.checkprecompflags = cprec_header->check_header_flags; + + CPrec_ReadRawBuffer(); + CPrec_RelocateRawBuffer(); + CPrec_RelocateBuiltins(); + CPrec_RelocateTable((void **) cprec_header->nametable, 0x800, (void **) name_hash_nodes); + CPrec_FixNameIds(); + CPrec_RelocateMacroTable(); + CPrec_RelocateTokenStreams(); + CPrec_RelocateRootNameSpace(); + + if (!cprec_header->usings) + cscope_root->usings = NULL; + else + cscope_root->usings = RESOLVE_RAW_BUFFER(cprec_header->usings); + + ctempl_templates = RESOLVE_SAFE(cprec_header->ctempl_templates); + ctempl_templatefuncs = RESOLVE_SAFE(cprec_header->ctempl_templatefuncs); + csom_stubs = RESOLVE_SAFE(cprec_header->csom_stubs); + cprec_staticdata = RESOLVE_SAFE(cprec_header->cprec_staticdata); + callbackactions = RESOLVE_SAFE(cprec_header->callbackactions); + cobjc_type_class = RESOLVE_SAFE(cprec_header->cobjc_type_class); + cobjc_type_id = RESOLVE_SAFE(cprec_header->cobjc_type_id); + cobjc_type_sel = RESOLVE_SAFE(cprec_header->cobjc_type_sel); + cobjc_selhashtable = RESOLVE_SAFE(cprec_header->cobjc_selhashtable); + cobjc_classdefs = RESOLVE_SAFE(cprec_header->cobjc_classdefs); + cobjc_protocols = RESOLVE_SAFE(cprec_header->cobjc_protocols); + init_expressions = RESOLVE_SAFE(cprec_header->init_expressions); + cinline_tactionlist = RESOLVE_SAFE(cprec_header->cinline_tactionlist); + CParser_SetUniqueID(cprec_header->uniqueID); + cobjc_selrefcount = cprec_header->cobjc_selrefcount; + cobjc_classrefcount = cprec_header->cobjc_classrefcount; + cobjc_stringcount = cprec_header->cobjc_stringcount; + + cprec_refnum = 0; + + CleanupPrecompiler(); + cscope_current = cscope_root; + + if (!CParser_ReInitRuntimeObjects(1)) + CError_ErrorTerm(CErrorStr181); + + CPrep_InsertSpecialMacros(); + + if (cparamblkptr->precompile != 1) + CPrec_DefineStaticData(); +} |