aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lapi.c32
-rw-r--r--ldump.c30
-rw-r--r--lstrlib.c19
-rw-r--r--lundump.c8
-rw-r--r--lundump.h2
-rw-r--r--manual/manual.of21
6 files changed, 66 insertions, 46 deletions
diff --git a/lapi.c b/lapi.c
index 374b3872..fd9ec4e4 100644
--- a/lapi.c
+++ b/lapi.c
@@ -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
1127LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { 1122LUA_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}
diff --git a/ldump.c b/ldump.c
index 9c315cdd..6cd5671f 100644
--- a/ldump.c
+++ b/ldump.c
@@ -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*/
46static void dumpBlock (DumpState *D, const void *b, size_t size) { 51static 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*/
56static void dumpAlign (DumpState *D, int align) { 65static 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
93static void dumpInt (DumpState *D, int x) { 103static 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) {
140static void dumpCode (DumpState *D, const Proto *f) { 151static 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*/
251int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, 264int 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
diff --git a/lstrlib.c b/lstrlib.c
index e29c09b9..a90c4fd1 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -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) {
233static int str_dump (lua_State *L) { 238static 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
diff --git a/lundump.c b/lundump.c
index 3f18343a..f850dc4a 100644
--- a/lundump.c
+++ b/lundump.c
@@ -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);
diff --git a/lundump.h b/lundump.h
index 05ac7f85..b10307e4 100644
--- a/lundump.h
+++ b/lundump.h
@@ -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 */
33LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, 33LUAI_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,
3266with the given @id{data} 3266with the given @id{data}
3267to write them. 3267to write them.
3268 3268
3269The function @Lid{lua_dump} fully preserves the Lua stack
3270through the calls to the writer function,
3271except that it may push some values for internal use
3272before the first call,
3273and it restores the stack size to its original size
3274after the last call.
3275
3269If @id{strip} is true, 3276If @id{strip} is true,
3270the binary representation may not include all debug information 3277the binary representation may not include all debug information
3271about the function, 3278about the function,
@@ -3275,8 +3282,6 @@ The value returned is the error code returned by the last
3275call to the writer; 3282call to the writer;
3276@N{0 means} no errors. 3283@N{0 means} no errors.
3277 3284
3278This 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}),
4688its size (@id{sz}), 4693its size (@id{sz}),
4689and the @id{ud} parameter supplied to @Lid{lua_dump}. 4694and the @id{ud} parameter supplied to @Lid{lua_dump}.
4690 4695
4696After @Lid{lua_dump} writes its last piece,
4697it will signal that by calling the writer function one more time,
4698with a @id{NULL} buffer (and size 0).
4699
4691The writer returns an error code: 4700The writer returns an error code:
4692@N{0 means} no errors; 4701@N{0 means} no errors;
4693any other value means an error and stops @Lid{lua_dump} from 4702any 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{
9272The function @Lid{lua_dump} changed the way it keeps the stack
9273through the calls to the writer function.
9274(That was not specified in previous versions.)
9275Also, it calls the writer function one extra time,
9276to signal the end of the dump.
9277}
9278
9279@item{
9263There were several changes in the parameters 9280There were several changes in the parameters
9264for the options @Lid{LUA_GCINC} and @Lid{LUA_GCGEN} 9281for the options @Lid{LUA_GCINC} and @Lid{LUA_GCGEN}
9265of the function @Lid{lua_gc}. 9282of the function @Lid{lua_gc}.