scummvm/lua/lsave.cpp

298 lines
9 KiB
C++
Raw Normal View History

#include <stdlib.h>
#include <stdio.h>
#include <search.h>
#include <assert.h>
#include "ltask.h"
#include "lauxlib.h"
#include "lmem.h"
#include "ldo.h"
#include "ltm.h"
#include "ltable.h"
#include "lvm.h"
#include "lopcodes.h"
#include "lstring.h"
SaveRestoreCallback saveCallback = NULL;
static void saveObjectValue(TObject *object, SaveRestoreFunc saveFunc) {
saveFunc(&object->ttype, sizeof(lua_Type));
if (object->ttype == LUA_T_CPROTO) {
luaL_libList *list = list_of_libs;
unsigned int idObj = 0;
while (list != NULL) {
for (int l = 0; l < list->number; l++) {
if (list->list[l].func == object->value.f) {
idObj = (idObj << 16) | l;
saveFunc(&idObj, sizeof(unsigned int));
return;
}
}
list = list->next;
idObj++;
}
assert(0);
} else {
saveFunc(&object->value, sizeof(Value));
}
}
static int opcodeSizeTable[] = {
1, 2, 1, 2, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1,
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3,
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1,
3, 2, 1, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1,
1, 1, 1, 3, 1, 2, 3, 2, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 1, 1,
3, 2, 2, 2, 2, 3, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 3, 2, 1, 1,
1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3,
2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 1, 3, 2, 1, 1, 1, 1, 1,
1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, 3, 2, 4, 2, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3, 2, 3,
2, 3, 2, 3, 2, 3, 2, 1, 1, 3, 2, 2, 2, 2, 3, 2, 1, 1
};
void lua_Save(SaveRestoreFunc saveFunc) {
printf("lua_Save() started.\n");
lua_collectgarbage(0);
int i, l;
int countElements = 0;
int maxStringLength = 0;
for (i = 0; i < NUM_HASHS; i++) {
stringtable *tempStringTable = &L->string_root[i];
for (int l = 0; l < tempStringTable->size; l++) {
if ((tempStringTable->hash[l] != NULL) && (tempStringTable->hash[l] != &EMPTY)) {
countElements++;
if (tempStringTable->hash[l]->constindex != -1) {
if (maxStringLength < tempStringTable->hash[l]->u.s.len) {
maxStringLength = tempStringTable->hash[l]->u.s.len;
}
}
}
}
}
saveFunc(&countElements, sizeof(int));
countElements = 0;
GCnode *tempNode;
tempNode = L->rootcl.next;
while (tempNode != NULL) {
countElements++;
tempNode = tempNode->next;
}
saveFunc(&countElements, sizeof(int));
countElements = 0;
tempNode = L->roottable.next;
while (tempNode != NULL) {
countElements++;
tempNode = tempNode->next;
}
saveFunc(&countElements, sizeof(int));
countElements = 0;
tempNode = L->rootproto.next;
while (tempNode != NULL) {
countElements++;
tempNode = tempNode->next;
}
saveFunc(&countElements, sizeof(int));
countElements = 0;
tempNode = L->rootglobal.next;
while (tempNode != NULL) {
countElements++;
tempNode = tempNode->next;
}
saveFunc(&countElements, sizeof(int));
saveFunc(&maxStringLength, sizeof(int));
TaggedString *tempString;
for (i = 0; i < NUM_HASHS; i++) {
stringtable *tempStringTable = &L->string_root[i];
for (l = 0; l < tempStringTable->size; l++) {
if ((tempStringTable->hash[l] != NULL) && (tempStringTable->hash[l] != &EMPTY)) {
tempString = tempStringTable->hash[l];
saveFunc(&tempString, sizeof(TaggedString *));
saveFunc(&tempString->constindex, sizeof(int));
if (tempString->constindex != -1) {
saveObjectValue(&tempString->u.s.globalval, saveFunc);
saveFunc(&tempString->u.s.len, sizeof(long));
saveFunc(tempString->str, tempString->u.s.len);
} else {
if (saveCallback != NULL) {
tempString->u.s.globalval.value.ts = (TaggedString *)saveCallback(tempString->u.s.globalval.ttype, (int)tempString->u.s.globalval.value.ts, saveFunc);
}
saveObjectValue(&tempString->u.s.globalval, saveFunc);
}
}
}
}
Closure *tempClosure = (Closure *)L->rootcl.next;
while (tempClosure != NULL) {
saveFunc(&tempClosure, sizeof(Closure *));
saveFunc(&tempClosure->nelems, sizeof(int));
for(i = 0; i <= tempClosure->nelems; i++) {
saveObjectValue(&tempClosure->consts[i], saveFunc);
}
tempClosure = (Closure *)tempClosure->head.next;
}
Hash *tempHash = (Hash *)L->roottable.next;
while (tempHash != NULL) {
saveFunc(&tempHash, sizeof(Hash *));
saveFunc(&tempHash->nhash, sizeof(unsigned int));
int countUsedHash = 0;
for(i = 0; i < tempHash->nhash; i++) {
Node *newNode = &tempHash->node[i];
if ((newNode->ref.ttype != LUA_T_NIL) && (newNode->val.ttype != LUA_T_NIL)) {
countUsedHash++;
}
}
saveFunc(&countUsedHash, sizeof(int));
saveFunc(&tempHash->htag, sizeof(int));
for (i = 0; i < tempHash->nhash; i++) {
Node *newNode = &tempHash->node[i];
if ((newNode->val.ttype != LUA_T_NIL) && (newNode->ref.ttype != LUA_T_NIL)) {
saveObjectValue(&tempHash->node[i].ref, saveFunc);
saveObjectValue(&tempHash->node[i].val, saveFunc);
}
}
tempHash = (Hash *)tempHash->head.next;
}
TProtoFunc *tempProtoFunc = (TProtoFunc *)L->rootproto.next;
while (tempProtoFunc != NULL) {
saveFunc(&tempProtoFunc, sizeof(TProtoFunc *));
saveFunc(&tempProtoFunc->fileName, sizeof(TaggedString *));
saveFunc(&tempProtoFunc->lineDefined, sizeof(unsigned int));
saveFunc(&tempProtoFunc->nconsts, sizeof(unsigned int));
for (i = 0; i < tempProtoFunc->nconsts; i++) {
saveObjectValue(&tempProtoFunc->consts[i], saveFunc);
}
int countVariables = 0;
if (tempProtoFunc->locvars) {
for (; tempProtoFunc->locvars[countVariables++].line != -1;) { }
}
saveFunc(&countVariables, sizeof(int));
for (i = 0; i < countVariables; i++) {
saveFunc(&tempProtoFunc->locvars[i].varname, sizeof(TaggedString *));
saveFunc(&tempProtoFunc->locvars[i].line, sizeof(int));
}
Byte *codePtr = tempProtoFunc->code + 2;
Byte *tmpPtr = codePtr;
int opcodeId;
do {
opcodeId = *tmpPtr;
tmpPtr += opcodeSizeTable[opcodeId];
} while (opcodeId != ENDCODE);
int codeSize = (tmpPtr - codePtr) + 2;
saveFunc(&codeSize, sizeof(int));
saveFunc(tempProtoFunc->code, codeSize);
tempProtoFunc = (TProtoFunc *)tempProtoFunc->head.next;
}
tempString = (TaggedString *)L->rootglobal.next;
while (tempString != NULL) {
saveFunc(&tempString, sizeof(TaggedString *));
tempString = (TaggedString *)tempString->head.next;
}
saveObjectValue(&L->errorim, saveFunc);
IM *tempIm = L->IMtable;
saveFunc(&L->IMtable_size, sizeof(int));
for (i = 0; i < L->IMtable_size; i++) {
for (l = 0; l < IM_N; l++) {
saveObjectValue(&tempIm->int_method[l], saveFunc);
}
tempIm++;
}
saveFunc(&L->last_tag, sizeof(int));
saveFunc(&L->refSize, sizeof(int));
for (i = 0 ; i < L->refSize; i++) {
saveObjectValue(&L->refArray[i].o, saveFunc);
saveFunc(&L->refArray[i].status, sizeof(Status));
}
saveFunc(&L->GCthreshold, sizeof(unsigned long));
saveFunc(&L->nblocks, sizeof(unsigned long));
saveFunc(&L->Mbuffsize, sizeof(int));
saveFunc(L->Mbuffer, L->Mbuffsize);
int MbaseOffset = L->Mbuffbase - L->Mbuffer;
saveFunc(&MbaseOffset, sizeof(int));
saveFunc(&L->Mbuffnext, sizeof(int));
int countTasks = 0;
lua_Task *tempTask = L->root_task->next;
while (tempTask != NULL) {
countTasks++;
tempTask = tempTask->next;
}
saveFunc(&countTasks, sizeof(int));
tempTask = L->root_task->next;
while (tempTask != NULL) {
int stackLastSize = (tempTask->stack.last - tempTask->stack.stack) + 1;
saveFunc(&stackLastSize, sizeof(int));
int stackTopSize = tempTask->stack.top - tempTask->stack.stack;
saveFunc(&stackTopSize, sizeof(int));
for (i = 0; i < stackTopSize; i++) {
saveObjectValue(&tempTask->stack.stack[i], saveFunc);
}
saveFunc(&tempTask->Cstack.base, sizeof(StkId));
saveFunc(&tempTask->Cstack.lua2C, sizeof(StkId));
saveFunc(&tempTask->Cstack.num, sizeof(int));
saveFunc(&tempTask->numCblocks, sizeof(int));
for (i = 0; i < tempTask->numCblocks; i++) {
saveFunc(&tempTask->Cblocks[i].base, sizeof(StkId));
saveFunc(&tempTask->Cblocks[i].lua2C, sizeof(StkId));
saveFunc(&tempTask->Cblocks[i].num, sizeof(int));
}
int pcOffset, taskCi = -1;
saveFunc(&tempTask->base_ci_size, sizeof(int));
assert(tempTask->base_ci);
CallInfo *tempCi = tempTask->base_ci;
int countCi = tempTask->base_ci_size / sizeof(CallInfo);
for (i = 0; i < countCi; i++) {
saveFunc(&tempCi->c, sizeof(Closure *));
saveFunc(&tempCi->tf, sizeof(TProtoFunc *));
if ((tempCi->pc != NULL) && (tempTask->ci->tf != NULL))
pcOffset = tempCi->pc - tempCi->tf->code;
else
pcOffset = 0;
saveFunc(&pcOffset, sizeof(int));
saveFunc(&tempCi->base, sizeof(StkId));
saveFunc(&tempCi->nResults, sizeof(int));
if (tempCi == tempTask->ci)
taskCi = i;
tempCi++;
}
assert(taskCi != -1);
saveFunc(&taskCi, sizeof(int));
MbaseOffset = tempTask->Mbuffbase - tempTask->Mbuffer;
saveFunc(&MbaseOffset, sizeof(int));
saveFunc(&tempTask->Mbuffnext, sizeof(int));
saveFunc(&tempTask->Tstate, sizeof(TaskState));
saveFunc(&tempTask->auto_delete, sizeof(int));
tempTask = tempTask->next;
}
printf("lua_Save() finished.\n");
}