mirror of https://git.wuffs.org/MWCC
1231 lines
29 KiB
C
1231 lines
29 KiB
C
|
#include "CompilerTools.h"
|
||
|
|
||
|
static short lheaplockcount;
|
||
|
static void (*heaperror)();
|
||
|
static Allocator bheap;
|
||
|
static Allocator oheap;
|
||
|
static Allocator aheap;
|
||
|
static Allocator lheap;
|
||
|
static Allocator gheap;
|
||
|
long hash_name_id;
|
||
|
StringNode **name_hash_nodes;
|
||
|
void (*GListErrorProc)();
|
||
|
|
||
|
void CompilerGetPString(short index, unsigned char *str) {
|
||
|
COS_GetPString(str, 10100, index);
|
||
|
}
|
||
|
|
||
|
void CompilerGetCString(short index, char *str) {
|
||
|
COS_GetString(str, 10100, index);
|
||
|
}
|
||
|
|
||
|
unsigned char *CTool_CtoPstr(char *input) {
|
||
|
char *work = input;
|
||
|
int length = 0;
|
||
|
int i;
|
||
|
|
||
|
while (*work) {
|
||
|
++length;
|
||
|
++work;
|
||
|
}
|
||
|
|
||
|
for (i = length; i > 0; i--) {
|
||
|
work[0] = work[-1];
|
||
|
--work;
|
||
|
}
|
||
|
|
||
|
input[0] = length;
|
||
|
return (unsigned char *) input;
|
||
|
}
|
||
|
|
||
|
static void GListError() {
|
||
|
if (GListErrorProc)
|
||
|
GListErrorProc();
|
||
|
}
|
||
|
|
||
|
int InitGList(GList *list, long capacity) {
|
||
|
if ((list->data = COS_NewOSHandle(capacity)) == 0)
|
||
|
if ((list->data = COS_NewHandle(capacity)) == 0)
|
||
|
return -1;
|
||
|
list->size = 0;
|
||
|
list->expansion = capacity >> 1;
|
||
|
list->capacity = capacity;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void FreeGList(GList *list) {
|
||
|
if (list->data != 0) {
|
||
|
COS_FreeHandle(list->data);
|
||
|
list->data = 0;
|
||
|
}
|
||
|
list->capacity = 0;
|
||
|
list->size = 0;
|
||
|
}
|
||
|
|
||
|
void LockGList(GList *list) {
|
||
|
COS_LockHandleHi(list->data);
|
||
|
}
|
||
|
|
||
|
void UnlockGList(GList *list) {
|
||
|
COS_UnlockHandle(list->data);
|
||
|
}
|
||
|
|
||
|
void ShrinkGList(GList *list) {
|
||
|
COS_ResizeHandle(list->data, list->capacity = list->size);
|
||
|
}
|
||
|
|
||
|
void AppendGListData(GList *list, const void *data, long size) {
|
||
|
if ((list->size + size) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += size + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
memcpy(*list->data + list->size, data, size);
|
||
|
list->size += size;
|
||
|
}
|
||
|
|
||
|
void AppendGListNoData(GList *list, long size) {
|
||
|
if ((list->size + size) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += size + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
list->size += size;
|
||
|
}
|
||
|
|
||
|
void AppendGListByte(GList *list, char v) {
|
||
|
if ((list->size + 1) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += 1 + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
(*list->data)[list->size++] = v;
|
||
|
}
|
||
|
|
||
|
void AppendGListWord(GList *list, short v) {
|
||
|
char *p;
|
||
|
|
||
|
if ((list->size + 2) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += 2 + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
p = *list->data + list->size;
|
||
|
list->size += 2;
|
||
|
*(p++) = ((unsigned char *) &v)[0];
|
||
|
*(p++) = ((unsigned char *) &v)[1];
|
||
|
}
|
||
|
|
||
|
void AppendGListTargetEndianWord(GList *list, short v) {
|
||
|
char *p;
|
||
|
|
||
|
if ((list->size + 2) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += 2 + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
p = *list->data + list->size;
|
||
|
list->size += 2;
|
||
|
*(p++) = ((unsigned char *) &v)[0];
|
||
|
*(p++) = ((unsigned char *) &v)[1];
|
||
|
}
|
||
|
|
||
|
void AppendGListLong(GList *list, long v) {
|
||
|
char *p;
|
||
|
|
||
|
if ((list->size + 4) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += 4 + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
p = *list->data + list->size;
|
||
|
list->size += 4;
|
||
|
*(p++) = ((unsigned char *) &v)[0];
|
||
|
*(p++) = ((unsigned char *) &v)[1];
|
||
|
*(p++) = ((unsigned char *) &v)[2];
|
||
|
*(p++) = ((unsigned char *) &v)[3];
|
||
|
}
|
||
|
|
||
|
void AppendGListTargetEndianLong(GList *list, long v) {
|
||
|
char *p;
|
||
|
|
||
|
if ((list->size + 4) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += 4 + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
p = *list->data + list->size;
|
||
|
list->size += 4;
|
||
|
*(p++) = ((unsigned char *) &v)[0];
|
||
|
*(p++) = ((unsigned char *) &v)[1];
|
||
|
*(p++) = ((unsigned char *) &v)[2];
|
||
|
*(p++) = ((unsigned char *) &v)[3];
|
||
|
}
|
||
|
|
||
|
void AppendGListID(GList *list, const char *str) {
|
||
|
unsigned long size = strlen(str) + 1;
|
||
|
if ((list->size + size) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += size + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
memcpy(*list->data + list->size, str, size);
|
||
|
list->size += size;
|
||
|
}
|
||
|
|
||
|
void AppendGListName(GList *list, const char *str) {
|
||
|
unsigned long size = strlen(str);
|
||
|
if ((list->size + size) > list->capacity) {
|
||
|
if (!COS_ResizeHandle(list->data, list->capacity += size + list->expansion))
|
||
|
GListError();
|
||
|
}
|
||
|
|
||
|
memcpy(*list->data + list->size, str, size);
|
||
|
list->size += size;
|
||
|
}
|
||
|
|
||
|
void RemoveGListData(GList *list, long size) {
|
||
|
list->size -= size;
|
||
|
if (list->capacity > (list->size + list->expansion * 2))
|
||
|
COS_ResizeHandle(list->data, list->capacity = list->size + list->expansion);
|
||
|
}
|
||
|
|
||
|
char GetGListByte(GList *list) {
|
||
|
unsigned char *p;
|
||
|
|
||
|
p = (unsigned char *) (*list->data + list->size);
|
||
|
list->size++;
|
||
|
return p[0];
|
||
|
}
|
||
|
|
||
|
short GetGListWord(GList *list) {
|
||
|
unsigned char *p;
|
||
|
union { unsigned char bytes[2]; short s; } data;
|
||
|
|
||
|
p = (unsigned char *) (*list->data + list->size);
|
||
|
list->size += 2;
|
||
|
data.bytes[0] = p[0];
|
||
|
data.bytes[1] = p[1];
|
||
|
return data.s;
|
||
|
}
|
||
|
|
||
|
long GetGListLong(GList *list) {
|
||
|
unsigned char *p;
|
||
|
union { unsigned char bytes[4]; long l; } data;
|
||
|
|
||
|
p = (unsigned char *) (*list->data + list->size);
|
||
|
list->size += 4;
|
||
|
data.bytes[0] = p[0];
|
||
|
data.bytes[1] = p[1];
|
||
|
data.bytes[2] = p[2];
|
||
|
data.bytes[3] = p[3];
|
||
|
return data.l;
|
||
|
}
|
||
|
|
||
|
short GetGListID(GList *list, char *buf) {
|
||
|
short len;
|
||
|
char *p;
|
||
|
|
||
|
len = 1;
|
||
|
p = *list->data + list->size;
|
||
|
while (*p) {
|
||
|
*(buf++) = *(p++);
|
||
|
len++;
|
||
|
}
|
||
|
|
||
|
*buf = *p;
|
||
|
list->size += len;
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
void GetGListData(GList *list, char *buf, long size) {
|
||
|
memcpy(buf, *list->data + list->size, size);
|
||
|
list->size += size;
|
||
|
}
|
||
|
|
||
|
static long hashpjw(const char *str) {
|
||
|
unsigned long work = 0;
|
||
|
unsigned long tmp;
|
||
|
|
||
|
while (*str) {
|
||
|
work = (work << 4) + *str;
|
||
|
tmp = work & 0xF0000000;
|
||
|
if (tmp) {
|
||
|
work ^= (tmp >> 24);
|
||
|
work ^= tmp;
|
||
|
}
|
||
|
str++;
|
||
|
}
|
||
|
|
||
|
return work % 0xFFFFFD;
|
||
|
}
|
||
|
|
||
|
static short PHash(const unsigned char *str) {
|
||
|
short result;
|
||
|
short counter;
|
||
|
unsigned char work;
|
||
|
const unsigned char *p;
|
||
|
|
||
|
result = str[0];
|
||
|
result &= 0xFF;
|
||
|
p = &str[1];
|
||
|
if (str[0]) {
|
||
|
counter = result;
|
||
|
work = 0;
|
||
|
while (counter > 0) {
|
||
|
work = (work >> 3) | (work << 5);
|
||
|
work += *p;
|
||
|
--counter;
|
||
|
++p;
|
||
|
}
|
||
|
|
||
|
result = (result << 8) | work;
|
||
|
}
|
||
|
|
||
|
return result & 0x7FF;
|
||
|
}
|
||
|
|
||
|
short CHash(const char *str) {
|
||
|
/* not matching :( */
|
||
|
short result; // orig r4
|
||
|
unsigned char work; // orig r5
|
||
|
short counter; // orig r3
|
||
|
|
||
|
// i am: r4 = result, r5 = counter, r3 = work
|
||
|
|
||
|
if (result = strlen(str) & 0xFF) {
|
||
|
counter = result;
|
||
|
work = 0;
|
||
|
while (counter > 0) {
|
||
|
work = (work >> 3) | (work << 5);
|
||
|
work = work + *(str++);
|
||
|
counter--;
|
||
|
}
|
||
|
result = (result << 8) | work;
|
||
|
}
|
||
|
|
||
|
return result & 0x7FF;
|
||
|
}
|
||
|
|
||
|
StringNode *GetHashNameNode(const char *str) {
|
||
|
StringNode *node;
|
||
|
short hash;
|
||
|
|
||
|
hash = CHash(str);
|
||
|
node = name_hash_nodes[hash];
|
||
|
if (node == 0) {
|
||
|
node = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
name_hash_nodes[hash] = node;
|
||
|
node->next = 0;
|
||
|
node->index = hash_name_id++;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
for (;;) {
|
||
|
if (strcmp(str, node->data) == 0) {
|
||
|
if (node->index < 0)
|
||
|
node->index = hash_name_id++;
|
||
|
return node;
|
||
|
}
|
||
|
|
||
|
if (node->next == 0) {
|
||
|
node->next = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
node = node->next;
|
||
|
node->next = 0;
|
||
|
node->index = hash_name_id++;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
node = node->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StringNode *GetHashNameNodeHash(const char *str, short hash) {
|
||
|
StringNode *node;
|
||
|
|
||
|
node = name_hash_nodes[hash];
|
||
|
if (node == 0) {
|
||
|
node = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
name_hash_nodes[hash] = node;
|
||
|
node->next = 0;
|
||
|
node->index = hash_name_id++;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
for (;;) {
|
||
|
if (strcmp(str, node->data) == 0)
|
||
|
return node;
|
||
|
|
||
|
if (node->next == 0) {
|
||
|
node->next = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
node = node->next;
|
||
|
node->next = 0;
|
||
|
node->index = hash_name_id++;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
node = node->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StringNode *GetHashNameNodeHash2(const char *str, short hash) {
|
||
|
StringNode *node;
|
||
|
|
||
|
node = name_hash_nodes[hash];
|
||
|
if (node == 0) {
|
||
|
node = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
name_hash_nodes[hash] = node;
|
||
|
node->next = 0;
|
||
|
node->index = -1;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
for (;;) {
|
||
|
if (strcmp(str, node->data) == 0)
|
||
|
return node;
|
||
|
|
||
|
if (node->next == 0) {
|
||
|
node->next = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
node = node->next;
|
||
|
node->next = 0;
|
||
|
node->index = -1;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
node = node->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
StringNode *GetHashNameNodeExport(const char *str) {
|
||
|
// not matching
|
||
|
StringNode *node;
|
||
|
short hash;
|
||
|
|
||
|
hash = CHash(str);
|
||
|
if ((node = name_hash_nodes[hash]) == 0) {
|
||
|
node = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
name_hash_nodes[hash] = node;
|
||
|
node->next = 0;
|
||
|
node->index = -1;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
for (;;) {
|
||
|
if (strcmp(str, node->data) == 0)
|
||
|
return node;
|
||
|
|
||
|
if (node->next == 0) {
|
||
|
node->next = (StringNode *) galloc(strlen(str) + sizeof(StringNode));
|
||
|
node = node->next;
|
||
|
node->next = 0;
|
||
|
node->index = -1;
|
||
|
node->hash = hash;
|
||
|
strcpy(node->data, str);
|
||
|
return node;
|
||
|
} else {
|
||
|
node = node->next;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
long GetHashNameNodeExportID(StringNode *node) {
|
||
|
if (node->index < 0)
|
||
|
node->index = hash_name_id++;
|
||
|
return node->index;
|
||
|
}
|
||
|
|
||
|
StringNode *GetHashNameNodeByID(long id) {
|
||
|
StringNode *node;
|
||
|
short i;
|
||
|
|
||
|
for (i = 0; i < 2048; i++) {
|
||
|
for (node = name_hash_nodes[i]; node; node = node->next) {
|
||
|
if (id == node->index)
|
||
|
return node;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void NameHashExportReset() {
|
||
|
short i;
|
||
|
StringNode *node;
|
||
|
|
||
|
for (i = 0; i < 0x800; i++) {
|
||
|
node = name_hash_nodes[i];
|
||
|
while (node) {
|
||
|
node->index = -1;
|
||
|
node = node->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hash_name_id = 1;
|
||
|
}
|
||
|
|
||
|
void NameHashWriteNameTable(GList *list) {
|
||
|
StringNode *node;
|
||
|
StringNode **nodes;
|
||
|
short grp;
|
||
|
int i;
|
||
|
|
||
|
nodes = (StringNode **) galloc(sizeof(StringNode *) * hash_name_id);
|
||
|
|
||
|
for (grp = 0; grp < 0x800; grp++) {
|
||
|
node = name_hash_nodes[grp];
|
||
|
while (node) {
|
||
|
if (node->index > 0)
|
||
|
nodes[node->index] = node;
|
||
|
node = node->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 1; i < hash_name_id; i++) {
|
||
|
node = nodes[i];
|
||
|
AppendGListWord(list, node->hash);
|
||
|
AppendGListID(list, node->data);
|
||
|
}
|
||
|
|
||
|
if (list->size & 1)
|
||
|
AppendGListByte(list, 0);
|
||
|
}
|
||
|
|
||
|
void NameHashWriteTargetEndianNameTable(GList *list) {
|
||
|
StringNode *node;
|
||
|
StringNode **nodes;
|
||
|
short grp;
|
||
|
int i;
|
||
|
|
||
|
nodes = (StringNode **) galloc(sizeof(StringNode *) * hash_name_id);
|
||
|
memclrw(nodes, sizeof(StringNode *) * hash_name_id);
|
||
|
|
||
|
for (grp = 0; grp < 0x800; grp++) {
|
||
|
node = name_hash_nodes[grp];
|
||
|
while (node) {
|
||
|
if (node->index > 0)
|
||
|
nodes[node->index] = node;
|
||
|
node = node->next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 1; i < hash_name_id; i++) {
|
||
|
node = nodes[i];
|
||
|
if (node == 0) {
|
||
|
AppendGListTargetEndianWord(list, 0);
|
||
|
AppendGListID(list, "");
|
||
|
} else {
|
||
|
AppendGListTargetEndianWord(list, node->hash);
|
||
|
AppendGListID(list, node->data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (list->size & 1)
|
||
|
AppendGListByte(list, 0);
|
||
|
}
|
||
|
|
||
|
void InitNameHash() {
|
||
|
name_hash_nodes = (StringNode **) galloc(0x800 * sizeof(StringNode *));
|
||
|
memclrw(name_hash_nodes, 0x800 * sizeof(StringNode *));
|
||
|
hash_name_id = 1;
|
||
|
}
|
||
|
|
||
|
long CTool_TotalHeapSize() {
|
||
|
long total = 0;
|
||
|
AllocatorBlock *block;
|
||
|
|
||
|
for (block = gheap.blockList; block; block = block->nextBlock) {
|
||
|
total += block->size;
|
||
|
}
|
||
|
for (block = lheap.blockList; block; block = block->nextBlock) {
|
||
|
total += block->size;
|
||
|
}
|
||
|
for (block = aheap.blockList; block; block = block->nextBlock) {
|
||
|
total += block->size;
|
||
|
}
|
||
|
for (block = oheap.blockList; block; block = block->nextBlock) {
|
||
|
total += block->size;
|
||
|
}
|
||
|
for (block = bheap.blockList; block; block = block->nextBlock) {
|
||
|
total += block->size;
|
||
|
}
|
||
|
|
||
|
return total;
|
||
|
}
|
||
|
|
||
|
static void getheapinfo(HeapInfo *result, Allocator *heap) {
|
||
|
AllocatorBlock *block;
|
||
|
|
||
|
result->_4 = heap->paddingSize;
|
||
|
for (block = heap->blockList; block; block = block->nextBlock) {
|
||
|
result->_8 += block->size - sizeof(AllocatorBlock);
|
||
|
result->xx_C += block->remaining;
|
||
|
result->_0++;
|
||
|
if (block->remaining > result->_18)
|
||
|
result->_18 = block->remaining;
|
||
|
}
|
||
|
|
||
|
result->_10 = result->_8 / result->_0;
|
||
|
result->_14 = result->xx_C / result->_0;
|
||
|
}
|
||
|
|
||
|
void CTool_GetHeapInfo(HeapInfo *result, unsigned char heapID) {
|
||
|
memclrw(result, sizeof(HeapInfo));
|
||
|
|
||
|
switch (heapID) {
|
||
|
case 0:
|
||
|
getheapinfo(result, &gheap);
|
||
|
break;
|
||
|
case 1:
|
||
|
getheapinfo(result, &lheap);
|
||
|
break;
|
||
|
case 2:
|
||
|
getheapinfo(result, &aheap);
|
||
|
break;
|
||
|
case 3:
|
||
|
getheapinfo(result, &oheap);
|
||
|
break;
|
||
|
case 4:
|
||
|
getheapinfo(result, &bheap);
|
||
|
break;
|
||
|
case 5:
|
||
|
getheapinfo(result, &gheap);
|
||
|
getheapinfo(result, &lheap);
|
||
|
getheapinfo(result, &aheap);
|
||
|
getheapinfo(result, &oheap);
|
||
|
getheapinfo(result, &bheap);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void MoreHeapSpace(Allocator *alloc, long size) {
|
||
|
Handle blockHandle;
|
||
|
long blockSize;
|
||
|
AllocatorBlock *block;
|
||
|
|
||
|
block = alloc->blockList;
|
||
|
if (block) {
|
||
|
alloc->lastBlockUsed->remaining = alloc->remaining;
|
||
|
while (block) {
|
||
|
if (block->remaining >= size)
|
||
|
goto gotBlock;
|
||
|
block = block->nextBlock;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* create new block */
|
||
|
blockSize = size + alloc->paddingSize;
|
||
|
if (systemHandles) {
|
||
|
blockHandle = COS_NewOSHandle(blockSize << 1);
|
||
|
if (blockHandle != 0)
|
||
|
goto createdTempDoubleBlock;
|
||
|
blockHandle = COS_NewOSHandle(blockSize);
|
||
|
if (blockHandle != 0)
|
||
|
goto createdBlock;
|
||
|
}
|
||
|
blockHandle = COS_NewHandle(blockSize);
|
||
|
if (blockHandle != 0)
|
||
|
goto createdBlock;
|
||
|
|
||
|
if (heaperror)
|
||
|
heaperror();
|
||
|
return;
|
||
|
|
||
|
createdTempDoubleBlock:
|
||
|
blockSize <<= 1;
|
||
|
goto createdBlock;
|
||
|
createdBlock:
|
||
|
COS_LockHandleHi(blockHandle);
|
||
|
block = (AllocatorBlock *) *blockHandle;
|
||
|
block->nextBlock = alloc->blockList;
|
||
|
alloc->blockList = block;
|
||
|
block->handle = blockHandle;
|
||
|
block->size = blockSize;
|
||
|
block->remaining = blockSize - sizeof(AllocatorBlock);
|
||
|
gotBlock:
|
||
|
alloc->lastBlockUsed = block;
|
||
|
alloc->remaining = block->remaining;
|
||
|
alloc->ptrToFreeArea = ((char *) block) + block->size - block->remaining;
|
||
|
}
|
||
|
|
||
|
int initheaps(heaperror_t failureCallback) {
|
||
|
heaperror = 0;
|
||
|
lheaplockcount = 0;
|
||
|
|
||
|
memclrw(&gheap, sizeof(Allocator));
|
||
|
memclrw(&lheap, sizeof(Allocator));
|
||
|
memclrw(&aheap, sizeof(Allocator));
|
||
|
memclrw(&oheap, sizeof(Allocator));
|
||
|
memclrw(&bheap, sizeof(Allocator));
|
||
|
|
||
|
gheap.paddingSize = 0x38000;
|
||
|
lheap.paddingSize = 0x10000;
|
||
|
aheap.paddingSize = 0x4000;
|
||
|
oheap.paddingSize = 0x40000;
|
||
|
bheap.paddingSize = 0x4000;
|
||
|
|
||
|
MoreHeapSpace(&gheap, 0);
|
||
|
MoreHeapSpace(&lheap, 0);
|
||
|
MoreHeapSpace(&aheap, 0);
|
||
|
MoreHeapSpace(&oheap, 0);
|
||
|
MoreHeapSpace(&bheap, 0);
|
||
|
|
||
|
gheap.paddingSize = 0x8000;
|
||
|
lheap.paddingSize = 0x8000;
|
||
|
|
||
|
heaperror = failureCallback;
|
||
|
|
||
|
if (!gheap.lastBlockUsed || !lheap.lastBlockUsed || !aheap.lastBlockUsed || !oheap.lastBlockUsed || !bheap.lastBlockUsed)
|
||
|
return -1;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int initgheap(heaperror_t failureCallback) {
|
||
|
heaperror = 0;
|
||
|
lheaplockcount = 0;
|
||
|
|
||
|
memclrw(&gheap, sizeof(Allocator));
|
||
|
memclrw(&lheap, sizeof(Allocator));
|
||
|
memclrw(&aheap, sizeof(Allocator));
|
||
|
memclrw(&oheap, sizeof(Allocator));
|
||
|
memclrw(&bheap, sizeof(Allocator));
|
||
|
|
||
|
gheap.paddingSize = 0x38000;
|
||
|
MoreHeapSpace(&gheap, 0);
|
||
|
gheap.paddingSize = 0x8000;
|
||
|
|
||
|
heaperror = failureCallback;
|
||
|
|
||
|
if (!gheap.lastBlockUsed)
|
||
|
return -1;
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
heaperror_t getheaperror() {
|
||
|
return heaperror;
|
||
|
}
|
||
|
|
||
|
void setheaperror(heaperror_t failureCallback) {
|
||
|
heaperror = failureCallback;
|
||
|
}
|
||
|
|
||
|
static void relheap(Allocator *alloc) {
|
||
|
AllocatorBlock *block;
|
||
|
Handle handle;
|
||
|
|
||
|
block = alloc->blockList;
|
||
|
while (block) {
|
||
|
handle = block->handle;
|
||
|
block = block->nextBlock;
|
||
|
COS_FreeHandle(handle);
|
||
|
}
|
||
|
|
||
|
memclrw(alloc, sizeof(Allocator));
|
||
|
}
|
||
|
|
||
|
void releaseheaps() {
|
||
|
relheap(&gheap);
|
||
|
relheap(&lheap);
|
||
|
relheap(&aheap);
|
||
|
relheap(&oheap);
|
||
|
relheap(&bheap);
|
||
|
}
|
||
|
|
||
|
void releasegheap() {
|
||
|
relheap(&gheap);
|
||
|
}
|
||
|
|
||
|
void releaseoheap() {
|
||
|
relheap(&gheap);
|
||
|
oheap.paddingSize = 0x40000;
|
||
|
MoreHeapSpace(&oheap, 0);
|
||
|
}
|
||
|
|
||
|
char *galloc(long size) {
|
||
|
long alignedSize;
|
||
|
char *ptr;
|
||
|
|
||
|
alignedSize = (size & ~7) + 8;
|
||
|
if (gheap.remaining < alignedSize)
|
||
|
MoreHeapSpace(&gheap, alignedSize);
|
||
|
|
||
|
gheap.remaining -= alignedSize;
|
||
|
ptr = (char *) gheap.ptrToFreeArea;
|
||
|
gheap.ptrToFreeArea = ptr + alignedSize;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
char *lalloc(long size) {
|
||
|
long alignedSize;
|
||
|
char *ptr;
|
||
|
|
||
|
alignedSize = (size & ~7) + 8;
|
||
|
if (lheap.remaining < alignedSize)
|
||
|
MoreHeapSpace(&lheap, alignedSize);
|
||
|
|
||
|
lheap.remaining -= alignedSize;
|
||
|
ptr = (char *) lheap.ptrToFreeArea;
|
||
|
lheap.ptrToFreeArea = ptr + alignedSize;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
char *aalloc(long size) {
|
||
|
long alignedSize;
|
||
|
char *ptr;
|
||
|
|
||
|
alignedSize = (size & ~7) + 8;
|
||
|
if (aheap.remaining < alignedSize)
|
||
|
MoreHeapSpace(&aheap, alignedSize);
|
||
|
|
||
|
aheap.remaining -= alignedSize;
|
||
|
ptr = (char *) aheap.ptrToFreeArea;
|
||
|
aheap.ptrToFreeArea = ptr + alignedSize;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
char *oalloc(long size) {
|
||
|
long alignedSize;
|
||
|
char *ptr;
|
||
|
|
||
|
alignedSize = (size & ~7) + 8;
|
||
|
if (oheap.remaining < alignedSize)
|
||
|
MoreHeapSpace(&oheap, alignedSize);
|
||
|
|
||
|
oheap.remaining -= alignedSize;
|
||
|
ptr = (char *) oheap.ptrToFreeArea;
|
||
|
oheap.ptrToFreeArea = ptr + alignedSize;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
char *balloc(long size) {
|
||
|
long alignedSize;
|
||
|
char *ptr;
|
||
|
|
||
|
alignedSize = (size & ~7) + 8;
|
||
|
if (bheap.remaining < alignedSize)
|
||
|
MoreHeapSpace(&bheap, alignedSize);
|
||
|
|
||
|
bheap.remaining -= alignedSize;
|
||
|
ptr = (char *) bheap.ptrToFreeArea;
|
||
|
bheap.ptrToFreeArea = ptr + alignedSize;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
void locklheap() {
|
||
|
lheaplockcount++;
|
||
|
}
|
||
|
|
||
|
void unlocklheap() {
|
||
|
if (lheaplockcount > 0)
|
||
|
--lheaplockcount;
|
||
|
}
|
||
|
|
||
|
void freelheap() {
|
||
|
AllocatorBlock *block;
|
||
|
|
||
|
if (lheaplockcount == 0) {
|
||
|
block = lheap.blockList;
|
||
|
lheap.lastBlockUsed = block;
|
||
|
lheap.ptrToFreeArea = ((char *) block) + sizeof(AllocatorBlock);
|
||
|
lheap.remaining = block->size - sizeof(AllocatorBlock);
|
||
|
|
||
|
while (block) {
|
||
|
block->remaining = block->size - sizeof(AllocatorBlock);
|
||
|
block = block->nextBlock;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void freeaheap() {
|
||
|
AllocatorBlock *block;
|
||
|
|
||
|
block = aheap.blockList;
|
||
|
aheap.lastBlockUsed = block;
|
||
|
aheap.ptrToFreeArea = ((char *) block) + sizeof(AllocatorBlock);
|
||
|
aheap.remaining = block->size - sizeof(AllocatorBlock);
|
||
|
|
||
|
while (block) {
|
||
|
block->remaining = block->size - sizeof(AllocatorBlock);
|
||
|
block = block->nextBlock;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void freeoheap() {
|
||
|
AllocatorBlock *block;
|
||
|
|
||
|
block = oheap.blockList;
|
||
|
oheap.lastBlockUsed = block;
|
||
|
oheap.ptrToFreeArea = ((char *) block) + sizeof(AllocatorBlock);
|
||
|
oheap.remaining = block->size - sizeof(AllocatorBlock);
|
||
|
|
||
|
while (block) {
|
||
|
block->remaining = block->size - sizeof(AllocatorBlock);
|
||
|
block = block->nextBlock;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void freebheap() {
|
||
|
AllocatorBlock *block;
|
||
|
|
||
|
block = bheap.blockList;
|
||
|
bheap.lastBlockUsed = block;
|
||
|
bheap.ptrToFreeArea = ((char *) block) + sizeof(AllocatorBlock);
|
||
|
bheap.remaining = block->size - sizeof(AllocatorBlock);
|
||
|
|
||
|
while (block) {
|
||
|
block->remaining = block->size - sizeof(AllocatorBlock);
|
||
|
block = block->nextBlock;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *ScanHex(char *str, long *output, Boolean *overflow) {
|
||
|
long work;
|
||
|
int ch;
|
||
|
|
||
|
work = 0;
|
||
|
*overflow = 0;
|
||
|
|
||
|
for (;;) {
|
||
|
ch = *str;
|
||
|
if (ch >= '0' && ch <= '9') {
|
||
|
ch = ch - '0';
|
||
|
} else if (ch >= 'A' && ch <= 'F') {
|
||
|
ch = ch - 'A' + 10;
|
||
|
} else if (ch >= 'a' && ch <= 'f') {
|
||
|
ch = ch - 'a' + 10;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (work & 0xF0000000)
|
||
|
*overflow = 1;
|
||
|
work = (work << 4) | (short) ch;
|
||
|
++str;
|
||
|
}
|
||
|
|
||
|
*output = work;
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
char *ScanOct(char *str, long *output, Boolean *overflow) {
|
||
|
short digit;
|
||
|
long work;
|
||
|
|
||
|
work = 0;
|
||
|
*overflow = 0;
|
||
|
|
||
|
for (;;) {
|
||
|
digit = *str - '0';
|
||
|
if (digit >= 0 && digit <= 9) {
|
||
|
if (digit >= 8) {
|
||
|
*overflow = 1;
|
||
|
++str;
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (work & 0xE0000000)
|
||
|
*overflow = 1;
|
||
|
work = (work << 3) | digit;
|
||
|
++str;
|
||
|
}
|
||
|
|
||
|
*output = work;
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
char *ScanDec(char *str, long *output, Boolean *overflow) {
|
||
|
short digit;
|
||
|
unsigned long work;
|
||
|
|
||
|
work = 0;
|
||
|
*overflow = 0;
|
||
|
|
||
|
for (;;) {
|
||
|
digit = *str - '0';
|
||
|
if (digit >= 0 && digit <= 9) {
|
||
|
if (work >= 0x19999999 && (work > 0x19999999 || digit > 5))
|
||
|
*overflow = 1;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
work = (work << 3) + (work << 1) + digit;
|
||
|
++str;
|
||
|
}
|
||
|
|
||
|
*output = work;
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
static char *UnmangleClassname(char *work, char **pNameStart, short *pNameLength, char **a4, short *a5, Boolean a6) {
|
||
|
char ch;
|
||
|
short len;
|
||
|
char *p2;
|
||
|
short len2;
|
||
|
short i;
|
||
|
short wtf;
|
||
|
|
||
|
*pNameLength = 0;
|
||
|
if (*(work++) != '_')
|
||
|
return work;
|
||
|
if (*(work++) != '_') {
|
||
|
return work;
|
||
|
} else {
|
||
|
len = 0;
|
||
|
while (work[0] >= '0' && work[0] <= '9') {
|
||
|
len = (len * 10) + work[0] - '0';
|
||
|
++work;
|
||
|
}
|
||
|
|
||
|
if (len > 0) {
|
||
|
*pNameStart = work;
|
||
|
*pNameLength = len;
|
||
|
|
||
|
if (a6) {
|
||
|
p2 = *a4;
|
||
|
len2 = *a5;
|
||
|
i = 0;
|
||
|
wtf = len;
|
||
|
while (i < wtf && len2 < 255) {
|
||
|
*(p2++) = work[i];
|
||
|
++i;
|
||
|
++len2;
|
||
|
}
|
||
|
if (len2 < 255) {
|
||
|
*(p2++) = ':';
|
||
|
len2++;
|
||
|
}
|
||
|
if (len2 < 255) {
|
||
|
*(p2++) = ':';
|
||
|
len2++;
|
||
|
}
|
||
|
*a4 = p2;
|
||
|
*a5 = len2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return work + len;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static char *UnmangleAppend(char *src, char srcLen, char **pOutput, short *pOutputLen) {
|
||
|
char *output;
|
||
|
short i;
|
||
|
short outputLen;
|
||
|
|
||
|
output = *pOutput;
|
||
|
outputLen = *pOutputLen;
|
||
|
|
||
|
for (i = 0; i < srcLen && outputLen < 255; i++, outputLen++) {
|
||
|
*(output++) = src[i];
|
||
|
}
|
||
|
|
||
|
*pOutput = output;
|
||
|
*pOutputLen = outputLen;
|
||
|
}
|
||
|
|
||
|
void OldUnmangle(char *input, char *output, Boolean flag) {
|
||
|
short var26;
|
||
|
char *nameStart;
|
||
|
short nameLength;
|
||
|
char *saved;
|
||
|
int i;
|
||
|
|
||
|
if (*input == '.')
|
||
|
++input;
|
||
|
|
||
|
var26 = 0;
|
||
|
saved = input;
|
||
|
if (input[0] == '_' && input[1] == '_') {
|
||
|
if (input[2] == 'c' && input[3] == 't') {
|
||
|
saved = UnmangleClassname(&input[4], &nameStart, &nameLength, &output, &var26, flag);
|
||
|
if (nameLength == 0)
|
||
|
goto invalid;
|
||
|
UnmangleAppend(nameStart, nameLength, &output, &var26);
|
||
|
} else if (input[2] == 'd' && input[3] == 't') {
|
||
|
saved = UnmangleClassname(&input[4], &nameStart, &nameLength, &output, &var26, flag);
|
||
|
if (nameLength == 0)
|
||
|
goto invalid;
|
||
|
if (var26 <= 255) {
|
||
|
*(output++) = '~';
|
||
|
var26++;
|
||
|
}
|
||
|
UnmangleAppend(nameStart, nameLength, &output, &var26);
|
||
|
} else if (input[2] == 'n' && input[3] == 'w') {
|
||
|
saved = UnmangleClassname(&input[4], &nameStart, &nameLength, &output, &var26, flag);
|
||
|
UnmangleAppend("operator new", 15, &output, &var26);
|
||
|
} else if (input[2] == 'd' && input[3] == 'l') {
|
||
|
saved = UnmangleClassname(&input[4], &nameStart, &nameLength, &output, &var26, flag);
|
||
|
UnmangleAppend("operator delete", 15, &output, &var26);
|
||
|
} else {
|
||
|
invalid:
|
||
|
strncpy(output, input, 256);
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
i = 0;
|
||
|
while (*saved) {
|
||
|
++saved;
|
||
|
++i;
|
||
|
if (saved[0] == '_' && saved[1] == '_') {
|
||
|
saved = UnmangleClassname(saved, &nameStart, &nameLength, &output, &var26, flag);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
UnmangleAppend(input, i, &output, &var26);
|
||
|
}
|
||
|
|
||
|
if (flag && saved[0] == 'F') {
|
||
|
if (saved[1] == 'v') {
|
||
|
UnmangleAppend("(void)", 6, &output, &var26);
|
||
|
} else {
|
||
|
UnmangleAppend("(...)", 5, &output, &var26);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*output = 0;
|
||
|
}
|
||
|
|
||
|
short hash(char *str) {
|
||
|
char hash = 0;
|
||
|
|
||
|
while (*str) {
|
||
|
hash = hash << 1;
|
||
|
hash ^= *(str++);
|
||
|
}
|
||
|
|
||
|
return hash & 0x7F;
|
||
|
}
|
||
|
|
||
|
void memclr(void *buffer, long size) {
|
||
|
memset(buffer, 0, size);
|
||
|
}
|
||
|
|
||
|
void memclrw(void *buffer, long size) {
|
||
|
memset(buffer, 0, size);
|
||
|
}
|
||
|
|
||
|
void CToLowercase(char *src, char *dst) {
|
||
|
char ch;
|
||
|
|
||
|
do {
|
||
|
ch = tolower(*(src++));
|
||
|
*(dst++) = ch;
|
||
|
} while (ch);
|
||
|
}
|
||
|
|
||
|
int getbit(long v) {
|
||
|
switch (v) {
|
||
|
case 0: return -1;
|
||
|
case 1: return 0;
|
||
|
case 2: return 1;
|
||
|
case 4: return 2;
|
||
|
case 8: return 3;
|
||
|
case 0x10: return 4;
|
||
|
case 0x20: return 5;
|
||
|
case 0x40: return 6;
|
||
|
case 0x80: return 7;
|
||
|
case 0x100: return 8;
|
||
|
case 0x200: return 9;
|
||
|
case 0x400: return 10;
|
||
|
case 0x800: return 11;
|
||
|
case 0x1000: return 12;
|
||
|
case 0x2000: return 13;
|
||
|
case 0x4000: return 14;
|
||
|
case 0x8000: return 15;
|
||
|
case 0x10000: return 16;
|
||
|
case 0x20000: return 17;
|
||
|
case 0x40000: return 18;
|
||
|
case 0x80000: return 19;
|
||
|
case 0x100000: return 20;
|
||
|
case 0x200000: return 21;
|
||
|
case 0x400000: return 22;
|
||
|
case 0x800000: return 23;
|
||
|
case 0x1000000: return 24;
|
||
|
case 0x2000000: return 25;
|
||
|
case 0x4000000: return 26;
|
||
|
case 0x8000000: return 27;
|
||
|
case 0x10000000: return 28;
|
||
|
case 0x20000000: return 29;
|
||
|
case 0x40000000: return 30;
|
||
|
case 0x80000000: return 31;
|
||
|
default: return -2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CTool_EndianConvertWord64(WtfWord64 value, unsigned long long *p) {
|
||
|
union { unsigned char bytes[8]; WtfWord64 w; } data;
|
||
|
data.w.a = value.a;
|
||
|
data.w.b = value.b;
|
||
|
memcpy(p, data.bytes, 8);
|
||
|
}
|
||
|
|
||
|
unsigned short CTool_EndianConvertInPlaceWord16Ptr(unsigned short *p) {
|
||
|
unsigned short v;
|
||
|
v = *p;
|
||
|
// this probably has a conversion on non-ppc
|
||
|
*p = v;
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
unsigned long CTool_EndianConvertInPlaceWord32Ptr(unsigned long *p) {
|
||
|
unsigned long v;
|
||
|
v = *p;
|
||
|
// this probably has a conversion on non-ppc
|
||
|
*p = v;
|
||
|
return v;
|
||
|
}
|
||
|
|
||
|
void CTool_EndianConvertVector128() {
|
||
|
// not correct but idc
|
||
|
}
|
||
|
|
||
|
StringNode *CTool_GetPathName(const FSSpec *spec, long *mdDat) {
|
||
|
char buffer[256];
|
||
|
COS_FileGetPathName(buffer, spec, mdDat);
|
||
|
return GetHashNameNodeExport(buffer);
|
||
|
}
|
||
|
|
||
|
Boolean strcat_safe(char *dst, const char *src, int maxLen) {
|
||
|
int len;
|
||
|
char ch;
|
||
|
|
||
|
len = strlen(dst);
|
||
|
dst += len;
|
||
|
maxLen -= len;
|
||
|
if (maxLen < 0)
|
||
|
return 1;
|
||
|
|
||
|
while (maxLen != 0) {
|
||
|
ch = *(dst++) = *(src++);
|
||
|
if (ch == 0)
|
||
|
break;
|
||
|
--maxLen;
|
||
|
}
|
||
|
|
||
|
if (maxLen == 0 && dst[-1]) {
|
||
|
dst[-1] = 0;
|
||
|
return 1;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|