diff options
Diffstat (limited to '')
-rw-r--r-- | lapi.c | 32 | ||||
-rw-r--r-- | ldump.c | 30 | ||||
-rw-r--r-- | lstrlib.c | 19 | ||||
-rw-r--r-- | lundump.c | 8 | ||||
-rw-r--r-- | lundump.h | 2 | ||||
-rw-r--r-- | manual/manual.of | 21 |
6 files changed, 66 insertions, 46 deletions
@@ -1116,36 +1116,18 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, | |||
1116 | 1116 | ||
1117 | 1117 | ||
1118 | /* | 1118 | /* |
1119 | ** Dump a function, calling 'writer' to write its parts. Because the | 1119 | ** Dump a Lua function, calling 'writer' to write its parts. Ensure |
1120 | ** writer can use the stack in unkown ways, this function should not | 1120 | ** the stack returns with its original size. |
1121 | ** push things on the stack, but it must anchor an auxiliary table | ||
1122 | ** used by 'luaU_dump'. To do so, it creates the table, anchors the | ||
1123 | ** function that is on the stack in the table, and substitutes the | ||
1124 | ** table for the function in the stack. | ||
1125 | */ | 1121 | */ |
1126 | |||
1127 | LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { | 1122 | LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { |
1128 | int status; | 1123 | int status; |
1129 | StkId fstk; /* pointer to function */ | 1124 | ptrdiff_t otop = savestack(L, L->top.p); /* original top */ |
1130 | TValue *o; | 1125 | TValue *f = s2v(L->top.p - 1); /* function to be dumped */ |
1131 | lua_lock(L); | 1126 | lua_lock(L); |
1132 | api_checknelems(L, 1); | 1127 | api_checknelems(L, 1); |
1133 | fstk = L->top.p - 1; | 1128 | api_check(L, isLfunction(f), "Lua function expected"); |
1134 | o = s2v(fstk); | 1129 | status = luaU_dump(L, clLvalue(f)->p, writer, data, strip); |
1135 | if (!isLfunction(o)) | 1130 | L->top.p = restorestack(L, otop); /* restore top */ |
1136 | status = 1; | ||
1137 | else { | ||
1138 | LClosure *f = clLvalue(o); | ||
1139 | ptrdiff_t fidx = savestack(L, fstk); /* function index */ | ||
1140 | Table *h = luaH_new(L); /* auxiliary table used by 'luaU_dump' */ | ||
1141 | sethvalue2s(L, L->top.p, h); /* anchor it (luaH_set may call GC) */ | ||
1142 | L->top.p++; /* (assume extra slot) */ | ||
1143 | luaH_set(L, h, o, o); /* anchor function into table */ | ||
1144 | setobjs2s(L, fstk, L->top.p - 1); /* move table over function */ | ||
1145 | L->top.p--; /* stack back to initial size */ | ||
1146 | status = luaU_dump(L, f->p, writer, data, strip, h); | ||
1147 | setclLvalue2s(L, restorestack(L, fidx), f); /* put function back */ | ||
1148 | } | ||
1149 | lua_unlock(L); | 1131 | lua_unlock(L); |
1150 | return status; | 1132 | return status; |
1151 | } | 1133 | } |
@@ -43,8 +43,13 @@ typedef struct { | |||
43 | #define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char)) | 43 | #define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char)) |
44 | 44 | ||
45 | 45 | ||
46 | /* | ||
47 | ** Dump the block of memory pointed by 'b' with given 'size'. | ||
48 | ** 'b' should not be NULL, except for the last call signaling the end | ||
49 | ** of the dump. | ||
50 | */ | ||
46 | static void dumpBlock (DumpState *D, const void *b, size_t size) { | 51 | static void dumpBlock (DumpState *D, const void *b, size_t size) { |
47 | if (D->status == 0 && size > 0) { | 52 | if (D->status == 0) { /* do not write anything after an error */ |
48 | lua_unlock(D->L); | 53 | lua_unlock(D->L); |
49 | D->status = (*D->writer)(D->L, b, size, D->data); | 54 | D->status = (*D->writer)(D->L, b, size, D->data); |
50 | lua_lock(D->L); | 55 | lua_lock(D->L); |
@@ -53,13 +58,18 @@ static void dumpBlock (DumpState *D, const void *b, size_t size) { | |||
53 | } | 58 | } |
54 | 59 | ||
55 | 60 | ||
61 | /* | ||
62 | ** Dump enough zeros to ensure that current position is a multiple of | ||
63 | ** 'align'. | ||
64 | */ | ||
56 | static void dumpAlign (DumpState *D, int align) { | 65 | static void dumpAlign (DumpState *D, int align) { |
57 | int padding = align - (D->offset % align); | 66 | int padding = align - (D->offset % align); |
58 | if (padding < align) { /* apd == align means no padding */ | 67 | if (padding < align) { /* padding == align means no padding */ |
59 | static lua_Integer paddingContent = 0; | 68 | static lua_Integer paddingContent = 0; |
69 | lua_assert(cast_uint(align) <= sizeof(lua_Integer)); | ||
60 | dumpBlock(D, &paddingContent, padding); | 70 | dumpBlock(D, &paddingContent, padding); |
61 | lua_assert(D->offset % align == 0); | ||
62 | } | 71 | } |
72 | lua_assert(D->offset % align == 0); | ||
63 | } | 73 | } |
64 | 74 | ||
65 | 75 | ||
@@ -91,6 +101,7 @@ static void dumpSize (DumpState *D, size_t x) { | |||
91 | 101 | ||
92 | 102 | ||
93 | static void dumpInt (DumpState *D, int x) { | 103 | static void dumpInt (DumpState *D, int x) { |
104 | lua_assert(x >= 0); | ||
94 | dumpSize(D, x); | 105 | dumpSize(D, x); |
95 | } | 106 | } |
96 | 107 | ||
@@ -140,6 +151,7 @@ static void dumpString (DumpState *D, TString *ts) { | |||
140 | static void dumpCode (DumpState *D, const Proto *f) { | 151 | static void dumpCode (DumpState *D, const Proto *f) { |
141 | dumpInt(D, f->sizecode); | 152 | dumpInt(D, f->sizecode); |
142 | dumpAlign(D, sizeof(f->code[0])); | 153 | dumpAlign(D, sizeof(f->code[0])); |
154 | lua_assert(f->code != NULL); | ||
143 | dumpVector(D, f->code, f->sizecode); | 155 | dumpVector(D, f->code, f->sizecode); |
144 | } | 156 | } |
145 | 157 | ||
@@ -196,7 +208,8 @@ static void dumpDebug (DumpState *D, const Proto *f) { | |||
196 | int i, n; | 208 | int i, n; |
197 | n = (D->strip) ? 0 : f->sizelineinfo; | 209 | n = (D->strip) ? 0 : f->sizelineinfo; |
198 | dumpInt(D, n); | 210 | dumpInt(D, n); |
199 | dumpVector(D, f->lineinfo, n); | 211 | if (f->lineinfo != NULL) |
212 | dumpVector(D, f->lineinfo, n); | ||
200 | n = (D->strip) ? 0 : f->sizeabslineinfo; | 213 | n = (D->strip) ? 0 : f->sizeabslineinfo; |
201 | dumpInt(D, n); | 214 | dumpInt(D, n); |
202 | for (i = 0; i < n; i++) { | 215 | for (i = 0; i < n; i++) { |
@@ -248,20 +261,23 @@ static void dumpHeader (DumpState *D) { | |||
248 | /* | 261 | /* |
249 | ** dump Lua function as precompiled chunk | 262 | ** dump Lua function as precompiled chunk |
250 | */ | 263 | */ |
251 | int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, | 264 | int luaU_dump (lua_State *L, const Proto *f, lua_Writer w, void *data, |
252 | int strip, Table *h) { | 265 | int strip) { |
253 | DumpState D; | 266 | DumpState D; |
267 | D.h = luaH_new(L); /* aux. table to keep strings already dumped */ | ||
268 | sethvalue2s(L, L->top.p, D.h); /* anchor it */ | ||
269 | L->top.p++; | ||
254 | D.L = L; | 270 | D.L = L; |
255 | D.writer = w; | 271 | D.writer = w; |
256 | D.offset = 0; | 272 | D.offset = 0; |
257 | D.data = data; | 273 | D.data = data; |
258 | D.strip = strip; | 274 | D.strip = strip; |
259 | D.status = 0; | 275 | D.status = 0; |
260 | D.h = h; | ||
261 | D.nstr = 0; | 276 | D.nstr = 0; |
262 | dumpHeader(&D); | 277 | dumpHeader(&D); |
263 | dumpByte(&D, f->sizeupvalues); | 278 | dumpByte(&D, f->sizeupvalues); |
264 | dumpFunction(&D, f); | 279 | dumpFunction(&D, f); |
280 | dumpBlock(&D, NULL, 0); /* signal end of dump */ | ||
265 | return D.status; | 281 | return D.status; |
266 | } | 282 | } |
267 | 283 | ||
@@ -225,7 +225,12 @@ static int writer (lua_State *L, const void *b, size_t size, void *ud) { | |||
225 | state->init = 1; | 225 | state->init = 1; |
226 | luaL_buffinit(L, &state->B); | 226 | luaL_buffinit(L, &state->B); |
227 | } | 227 | } |
228 | luaL_addlstring(&state->B, (const char *)b, size); | 228 | if (b == NULL) { /* finishing dump? */ |
229 | luaL_pushresult(&state->B); /* push result */ | ||
230 | lua_replace(L, 1); /* move it to reserved slot */ | ||
231 | } | ||
232 | else | ||
233 | luaL_addlstring(&state->B, (const char *)b, size); | ||
229 | return 0; | 234 | return 0; |
230 | } | 235 | } |
231 | 236 | ||
@@ -233,13 +238,13 @@ static int writer (lua_State *L, const void *b, size_t size, void *ud) { | |||
233 | static int str_dump (lua_State *L) { | 238 | static int str_dump (lua_State *L) { |
234 | struct str_Writer state; | 239 | struct str_Writer state; |
235 | int strip = lua_toboolean(L, 2); | 240 | int strip = lua_toboolean(L, 2); |
236 | luaL_checktype(L, 1, LUA_TFUNCTION); | 241 | luaL_argcheck(L, lua_type(L, 1) == LUA_TFUNCTION && !lua_iscfunction(L, 1), |
237 | lua_settop(L, 1); /* ensure function is on the top of the stack */ | 242 | 1, "Lua function expected"); |
243 | /* ensure function is on the top of the stack and vacate slot 1 */ | ||
244 | lua_pushvalue(L, 1); | ||
238 | state.init = 0; | 245 | state.init = 0; |
239 | if (l_unlikely(lua_dump(L, writer, &state, strip) != 0)) | 246 | lua_dump(L, writer, &state, strip); |
240 | return luaL_error(L, "unable to dump given function"); | 247 | lua_settop(L, 1); /* leave final result on top */ |
241 | luaL_pushresult(&state.B); | ||
242 | lua_assert(lua_isfunction(L, 1)); /* lua_dump kept that value */ | ||
243 | return 1; | 248 | return 1; |
244 | } | 249 | } |
245 | 250 | ||
@@ -152,7 +152,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
152 | luaH_getint(S->h, idx, &stv); | 152 | luaH_getint(S->h, idx, &stv); |
153 | *sl = ts = tsvalue(&stv); | 153 | *sl = ts = tsvalue(&stv); |
154 | luaC_objbarrier(L, p, ts); | 154 | luaC_objbarrier(L, p, ts); |
155 | return; | 155 | return; /* do not save it again */ |
156 | } | 156 | } |
157 | else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */ | 157 | else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */ |
158 | char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ | 158 | char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ |
@@ -168,10 +168,10 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
168 | else { /* create internal copy */ | 168 | else { /* create internal copy */ |
169 | *sl = ts = luaS_createlngstrobj(L, size); /* create string */ | 169 | *sl = ts = luaS_createlngstrobj(L, size); /* create string */ |
170 | luaC_objbarrier(L, p, ts); | 170 | luaC_objbarrier(L, p, ts); |
171 | loadVector(S, getlngstr(ts), size); /* load directly in final place */ | 171 | loadVector(S, getlngstr(ts), size + 1); /* load directly in final place */ |
172 | loadByte(S); /* skip ending '\0' */ | ||
173 | } | 172 | } |
174 | S->nstr++; /* add string to list of saved strings */ | 173 | /* add string to list of saved strings */ |
174 | S->nstr++; | ||
175 | setsvalue(L, &sv, ts); | 175 | setsvalue(L, &sv, ts); |
176 | luaH_setint(L, S->h, S->nstr, &sv); | 176 | luaH_setint(L, S->h, S->nstr, &sv); |
177 | luaC_objbarrierback(L, obj2gco(S->h), ts); | 177 | luaC_objbarrierback(L, obj2gco(S->h), ts); |
@@ -31,6 +31,6 @@ LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name, | |||
31 | 31 | ||
32 | /* dump one chunk; from ldump.c */ | 32 | /* dump one chunk; from ldump.c */ |
33 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, | 33 | LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, |
34 | void* data, int strip, Table *h); | 34 | void* data, int strip); |
35 | 35 | ||
36 | #endif | 36 | #endif |
diff --git a/manual/manual.of b/manual/manual.of index 8607e57d..ef1bdfd2 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
@@ -3266,6 +3266,13 @@ As it produces parts of the chunk, | |||
3266 | with the given @id{data} | 3266 | with the given @id{data} |
3267 | to write them. | 3267 | to write them. |
3268 | 3268 | ||
3269 | The function @Lid{lua_dump} fully preserves the Lua stack | ||
3270 | through the calls to the writer function, | ||
3271 | except that it may push some values for internal use | ||
3272 | before the first call, | ||
3273 | and it restores the stack size to its original size | ||
3274 | after the last call. | ||
3275 | |||
3269 | If @id{strip} is true, | 3276 | If @id{strip} is true, |
3270 | the binary representation may not include all debug information | 3277 | the binary representation may not include all debug information |
3271 | about the function, | 3278 | about the function, |
@@ -3275,8 +3282,6 @@ The value returned is the error code returned by the last | |||
3275 | call to the writer; | 3282 | call to the writer; |
3276 | @N{0 means} no errors. | 3283 | @N{0 means} no errors. |
3277 | 3284 | ||
3278 | This function does not pop the Lua function from the stack. | ||
3279 | |||
3280 | } | 3285 | } |
3281 | 3286 | ||
3282 | @APIEntry{int lua_error (lua_State *L);| | 3287 | @APIEntry{int lua_error (lua_State *L);| |
@@ -4688,6 +4693,10 @@ passing along the buffer to be written (@id{p}), | |||
4688 | its size (@id{sz}), | 4693 | its size (@id{sz}), |
4689 | and the @id{ud} parameter supplied to @Lid{lua_dump}. | 4694 | and the @id{ud} parameter supplied to @Lid{lua_dump}. |
4690 | 4695 | ||
4696 | After @Lid{lua_dump} writes its last piece, | ||
4697 | it will signal that by calling the writer function one more time, | ||
4698 | with a @id{NULL} buffer (and size 0). | ||
4699 | |||
4691 | The writer returns an error code: | 4700 | The writer returns an error code: |
4692 | @N{0 means} no errors; | 4701 | @N{0 means} no errors; |
4693 | any other value means an error and stops @Lid{lua_dump} from | 4702 | any other value means an error and stops @Lid{lua_dump} from |
@@ -9260,6 +9269,14 @@ it is equivalent to @Lid{lua_closethread} with | |||
9260 | } | 9269 | } |
9261 | 9270 | ||
9262 | @item{ | 9271 | @item{ |
9272 | The function @Lid{lua_dump} changed the way it keeps the stack | ||
9273 | through the calls to the writer function. | ||
9274 | (That was not specified in previous versions.) | ||
9275 | Also, it calls the writer function one extra time, | ||
9276 | to signal the end of the dump. | ||
9277 | } | ||
9278 | |||
9279 | @item{ | ||
9263 | There were several changes in the parameters | 9280 | There were several changes in the parameters |
9264 | for the options @Lid{LUA_GCINC} and @Lid{LUA_GCGEN} | 9281 | for the options @Lid{LUA_GCINC} and @Lid{LUA_GCGEN} |
9265 | of the function @Lid{lua_gc}. | 9282 | of the function @Lid{lua_gc}. |