1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distri8buted in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 /**
24 * This code is heavily based on the pluto code base. Copyright below
25 */
26
27 /* Tamed Pluto - Heavy-duty persistence for Lua
28 * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public
29 * domain. People making use of this software as part of an application
30 * are politely requested to email the author at sneftel@gmail.com
31 * with a brief description of the application, primarily to satisfy his
32 * curiosity.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
37 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
38 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
39 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
40 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 *
42 * Instrumented by Stefan Reich (info@luaos.net)
43 * for Mobile Lua (http://luaos.net/pages/mobile-lua.php)
44 */
45
46 /**
47 * This code is heavily based on the Pluto code base. Copyright below
48 */
49
50 /* Tamed Pluto - Heavy-duty persistence for Lua
51 * Copyright (C) 2004 by Ben Sunshine-Hill, and released into the public
52 * domain. People making use of this software as part of an application
53 * are politely requested to email the author at sneftel@gmail.com
54 * with a brief description of the application, primarily to satisfy his
55 * curiosity.
56 *
57 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
58 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
59 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
60 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
61 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
62 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
63 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64 *
65 * Instrumented by Stefan Reich (info@luaos.net)
66 * for Mobile Lua (http://luaos.net/pages/mobile-lua.php)
67 */
68
69
70 #include "lua_persistence_util.h"
71
72 #include "common/scummsys.h"
73
74 #include "lobject.h"
75 #include "lstate.h"
76 #include "lgc.h"
77 #include "lopcodes.h"
78
79
80 namespace Lua {
81
lua_realloc(lua_State * luaState,void * block,size_t osize,size_t nsize)82 void *lua_realloc(lua_State *luaState, void *block, size_t osize, size_t nsize) {
83 global_State *globalState = G(luaState);
84
85 block = (*globalState->frealloc)(globalState->ud, block, osize, nsize);
86 globalState->totalbytes = (globalState->totalbytes - osize) + nsize;
87
88 return block;
89 }
90
pushObject(lua_State * luaState,TValue * obj)91 void pushObject(lua_State *luaState, TValue *obj) {
92 setobj2s(luaState, luaState->top, obj);
93
94 api_check(luaState, luaState->top < luaState->ci->top);
95 luaState->top++;
96 }
97
pushProto(lua_State * luaState,Proto * proto)98 void pushProto(lua_State *luaState, Proto *proto) {
99 TValue obj;
100 setptvalue(luaState, &obj, proto);
101
102 pushObject(luaState, &obj);
103 }
104
pushUpValue(lua_State * luaState,UpVal * upval)105 void pushUpValue(lua_State *luaState, UpVal *upval) {
106 TValue obj;
107
108 obj.value.gc = cast(GCObject *, upval);
109 obj.tt = LUA_TUPVAL;
110 checkliveness(G(L), obj);
111
112 pushObject(luaState, &obj);
113 }
114
pushString(lua_State * luaState,TString * str)115 void pushString(lua_State *luaState, TString *str) {
116 TValue o;
117 setsvalue(luaState, &o, str);
118
119 pushObject(luaState, &o);
120 }
121
122 /* A simple reimplementation of the unfortunately static function luaA_index.
123 * Does not support the global table, registry, or upvalues. */
getObject(lua_State * luaState,int stackpos)124 StkId getObject(lua_State *luaState, int stackpos) {
125 if (stackpos > 0) {
126 lua_assert(luaState->base + stackpos - 1 < luaState->top);
127 return luaState->base + stackpos - 1;
128 } else {
129 lua_assert(L->top - stackpos >= L->base);
130 return luaState->top + stackpos;
131 }
132 }
133
lua_linkObjToGC(lua_State * luaState,GCObject * obj,lu_byte type)134 void lua_linkObjToGC(lua_State *luaState, GCObject *obj, lu_byte type) {
135 global_State *globalState = G(luaState);
136
137 obj->gch.next = globalState->rootgc;
138 globalState->rootgc = obj;
139 obj->gch.marked = luaC_white(globalState);
140 obj->gch.tt = type;
141 }
142
lua_newLclosure(lua_State * luaState,int numElements,Table * elementTable)143 Closure *lua_newLclosure(lua_State *luaState, int numElements, Table *elementTable) {
144 Closure *c = (Closure *)lua_malloc(luaState, sizeLclosure(numElements));
145 lua_linkObjToGC(luaState, obj2gco(c), LUA_TFUNCTION);
146
147 c->l.isC = 0;
148 c->l.env = elementTable;
149 c->l.nupvalues = cast_byte(numElements);
150
151 while (numElements--) {
152 c->l.upvals[numElements] = NULL;
153 }
154
155 return c;
156 }
157
pushClosure(lua_State * luaState,Closure * closure)158 void pushClosure(lua_State *luaState, Closure *closure) {
159 TValue obj;
160 setclvalue(luaState, &obj, closure);
161 pushObject(luaState, &obj);
162 }
163
createProto(lua_State * luaState)164 Proto *createProto(lua_State *luaState) {
165 Proto *newProto = (Proto *)lua_malloc(luaState, sizeof(Proto));
166 lua_linkObjToGC(luaState, obj2gco(newProto), LUA_TPROTO);
167
168 newProto->k = NULL;
169 newProto->sizek = 0;
170 newProto->p = NULL;
171 newProto->sizep = 0;
172 newProto->code = NULL;
173 newProto->sizecode = 0;
174 newProto->sizelineinfo = 0;
175 newProto->sizeupvalues = 0;
176 newProto->nups = 0;
177 newProto->upvalues = NULL;
178 newProto->numparams = 0;
179 newProto->is_vararg = 0;
180 newProto->maxstacksize = 0;
181 newProto->lineinfo = NULL;
182 newProto->sizelocvars = 0;
183 newProto->locvars = NULL;
184 newProto->linedefined = 0;
185 newProto->lastlinedefined = 0;
186 newProto->source = NULL;
187
188 return newProto;
189 }
190
createString(lua_State * luaState,const char * str,size_t len)191 TString *createString(lua_State *luaState, const char *str, size_t len) {
192 TString *res;
193 lua_pushlstring(luaState, str, len);
194
195 res = rawtsvalue(luaState->top - 1);
196 lua_pop(luaState, 1);
197
198 return res;
199 }
200
makeFakeProto(lua_State * L,lu_byte nups)201 Proto *makeFakeProto(lua_State *L, lu_byte nups) {
202 Proto *p = createProto(L);
203
204 p->sizelineinfo = 1;
205 p->lineinfo = lua_newVector(L, 1, int);
206 p->lineinfo[0] = 1;
207 p->sizecode = 1;
208 p->code = lua_newVector(L, 1, Instruction);
209 p->code[0] = CREATE_ABC(OP_RETURN, 0, 1, 0);
210 p->source = createString(L, "", 0);
211 p->maxstacksize = 2;
212 p->nups = nups;
213 p->sizek = 0;
214 p->sizep = 0;
215
216 return p;
217 }
218
createUpValue(lua_State * luaState,int stackpos)219 UpVal *createUpValue(lua_State *luaState, int stackpos) {
220 UpVal *upValue = (UpVal *)lua_malloc(luaState, sizeof(UpVal));
221 lua_linkObjToGC(luaState, (GCObject *)upValue, LUA_TUPVAL);
222 upValue->tt = LUA_TUPVAL;
223 upValue->v = &upValue->u.value;
224 upValue->u.l.prev = NULL;
225 upValue->u.l.next = NULL;
226
227 const TValue *o2 = (TValue *)getObject(luaState, stackpos);
228 upValue->v->value = o2->value;
229 upValue->v->tt = o2->tt;
230 checkliveness(G(L), upValue->v);
231
232 return upValue;
233 }
234
unboxUpValue(lua_State * luaState)235 void unboxUpValue(lua_State *luaState) {
236 // >>>>> ...... func
237 LClosure *lcl;
238 UpVal *uv;
239
240 lcl = (LClosure *)clvalue(getObject(luaState, -1));
241 uv = lcl->upvals[0];
242
243 lua_pop(luaState, 1);
244 // >>>>> ......
245
246 pushUpValue(luaState, uv);
247 // >>>>> ...... upValue
248 }
249
appendStackToStack_reverse(lua_State * from,lua_State * to)250 size_t appendStackToStack_reverse(lua_State *from, lua_State *to) {
251 for (StkId id = from->top - 1; id >= from->stack; --id) {
252 setobj2s(to, to->top, id);
253 to->top++;
254 }
255
256 return from->top - from->stack;
257 }
258
correctStack(lua_State * L,TValue * oldstack)259 void correctStack(lua_State *L, TValue *oldstack) {
260 CallInfo *ci;
261 GCObject *up;
262 L->top = (L->top - oldstack) + L->stack;
263 for (up = L->openupval; up != NULL; up = up->gch.next)
264 gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;
265 for (ci = L->base_ci; ci <= L->ci; ci++) {
266 ci->top = (ci->top - oldstack) + L->stack;
267 ci->base = (ci->base - oldstack) + L->stack;
268 ci->func = (ci->func - oldstack) + L->stack;
269 }
270 L->base = (L->base - oldstack) + L->stack;
271 }
272
lua_reallocstack(lua_State * L,int newsize)273 void lua_reallocstack(lua_State *L, int newsize) {
274 TValue *oldstack = L->stack;
275 int realsize = newsize + 1 + EXTRA_STACK;
276
277 lua_reallocvector(L, L->stack, L->stacksize, realsize, TValue);
278 L->stacksize = realsize;
279 L->stack_last = L->stack + newsize;
280 correctStack(L, oldstack);
281 }
282
lua_reallocCallInfo(lua_State * lauState,int newsize)283 void lua_reallocCallInfo(lua_State *lauState, int newsize) {
284 CallInfo *oldci = lauState->base_ci;
285 lua_reallocvector(lauState, lauState->base_ci, lauState->size_ci, newsize, CallInfo);
286
287 lauState->size_ci = newsize;
288 lauState->ci = (lauState->ci - oldci) + lauState->base_ci;
289 lauState->end_ci = lauState->base_ci + lauState->size_ci - 1;
290 }
291
GCUnlink(lua_State * luaState,GCObject * gco)292 void GCUnlink(lua_State *luaState, GCObject *gco) {
293 GCObject *prevslot;
294 if (G(luaState)->rootgc == gco) {
295 G(luaState)->rootgc = G(luaState)->rootgc->gch.next;
296 return;
297 }
298
299 prevslot = G(luaState)->rootgc;
300 while (prevslot->gch.next != gco) {
301 prevslot = prevslot->gch.next;
302 }
303
304 prevslot->gch.next = prevslot->gch.next->gch.next;
305 }
306
lua_newlstr(lua_State * luaState,const char * str,size_t len)307 TString *lua_newlstr(lua_State *luaState, const char *str, size_t len) {
308 lua_pushlstring(luaState, str, len);
309 TString *luaStr = &(luaState->top - 1)->value.gc->ts;
310
311 lua_pop(luaState, 1);
312
313 return luaStr;
314 }
315
lua_link(lua_State * luaState,GCObject * o,lu_byte tt)316 void lua_link(lua_State *luaState, GCObject *o, lu_byte tt) {
317 global_State *g = G(luaState);
318 o->gch.next = g->rootgc;
319 g->rootgc = o;
320 o->gch.marked = luaC_white(g);
321 o->gch.tt = tt;
322 }
323
lua_newproto(lua_State * luaState)324 Proto *lua_newproto(lua_State *luaState) {
325 Proto *f = (Proto *)lua_malloc(luaState, sizeof(Proto));
326 lua_link(luaState, obj2gco(f), LUA_TPROTO);
327 f->k = NULL;
328 f->sizek = 0;
329 f->p = NULL;
330 f->sizep = 0;
331 f->code = NULL;
332 f->sizecode = 0;
333 f->sizelineinfo = 0;
334 f->sizeupvalues = 0;
335 f->nups = 0;
336 f->upvalues = NULL;
337 f->numparams = 0;
338 f->is_vararg = 0;
339 f->maxstacksize = 0;
340 f->lineinfo = NULL;
341 f->sizelocvars = 0;
342 f->locvars = NULL;
343 f->linedefined = 0;
344 f->lastlinedefined = 0;
345 f->source = NULL;
346 return f;
347 }
348
makeUpValue(lua_State * luaState,int stackPos)349 UpVal *makeUpValue(lua_State *luaState, int stackPos) {
350 UpVal *uv = lua_new(luaState, UpVal);
351 lua_link(luaState, (GCObject *)uv, LUA_TUPVAL);
352 uv->tt = LUA_TUPVAL;
353 uv->v = &uv->u.value;
354 uv->u.l.prev = NULL;
355 uv->u.l.next = NULL;
356
357 setobj(luaState, uv->v, getObject(luaState, stackPos));
358
359 return uv;
360 }
361
boxUpValue_start(lua_State * luaState)362 void boxUpValue_start(lua_State *luaState) {
363 LClosure *closure;
364 closure = (LClosure *)lua_newLclosure(luaState, 1, hvalue(&luaState->l_gt));
365 pushClosure(luaState, (Closure *)closure);
366 // >>>>> ...... func
367 closure->p = makeFakeProto(luaState, 1);
368
369 // Temporarily initialize the upvalue to nil
370 lua_pushnil(luaState);
371 closure->upvals[0] = makeUpValue(luaState, -1);
372 lua_pop(luaState, 1);
373 }
374
boxUpValue_finish(lua_State * luaState)375 void boxUpValue_finish(lua_State *luaState) {
376 // >>>>> ...... func obj
377 LClosure *lcl = (LClosure *)clvalue(getObject(luaState, -2));
378
379 lcl->upvals[0]->u.value = *getObject(luaState, -1);
380 lua_pop(luaState, 1);
381 // >>>>> ...... func
382 }
383
384 } // End of namespace Lua
385