aboutsummaryrefslogtreecommitdiff
path: root/ltm.c
diff options
context:
space:
mode:
Diffstat (limited to 'ltm.c')
-rw-r--r--ltm.c64
1 files changed, 51 insertions, 13 deletions
diff --git a/ltm.c b/ltm.c
index 8d64235e..39ac59d4 100644
--- a/ltm.c
+++ b/ltm.c
@@ -242,6 +242,7 @@ static void createvarargtab (lua_State *L, StkId f, int n) {
242 luaH_set(L, t, &key, &value); /* t.n = n */ 242 luaH_set(L, t, &key, &value); /* t.n = n */
243 for (i = 0; i < n; i++) 243 for (i = 0; i < n; i++)
244 luaH_setint(L, t, i + 1, s2v(f + i)); 244 luaH_setint(L, t, i + 1, s2v(f + i));
245 luaC_checkGC(L);
245} 246}
246 247
247 248
@@ -265,11 +266,11 @@ void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) {
265 setobjs2s(L, L->top.p++, ci->func.p + i); 266 setobjs2s(L, L->top.p++, ci->func.p + i);
266 setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ 267 setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */
267 } 268 }
268 if (p->flag & PF_VAVAR) { /* is there a vararg parameter? */ 269 if (p->flag & PF_VATAB) /* does it need a vararg table? */
269 if (p->flag & PF_VATAB) /* does it need a vararg table? */ 270 createvarargtab(L, ci->func.p + nfixparams + 1, nextra);
270 createvarargtab(L, ci->func.p + nfixparams + 1, nextra); 271 else { /* no table; set parameter to nil */
271 else /* no table; set parameter to nil */ 272 setnilvalue(s2v(L->top.p));
272 setnilvalue(s2v(L->top.p)); 273 L->top.p++;
273 } 274 }
274 ci->func.p += totalargs + 1; 275 ci->func.p += totalargs + 1;
275 ci->top.p += totalargs + 1; 276 ci->top.p += totalargs + 1;
@@ -299,16 +300,53 @@ void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc) {
299} 300}
300 301
301 302
302void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { 303/*
303 int i; 304** Get the number of extra arguments in a vararg function. If vararg
304 int nextra = ci->u.l.nextraargs; 305** table has been optimized away, that number is in the call info.
306** Otherwise, get the field 'n' from the vararg table and check that it
307** has a proper value (non-negative integer not larger than the stack
308** limit).
309*/
310static int getnumargs (lua_State *L, CallInfo *ci, Table *h) {
311 if (h == NULL) /* no vararg table? */
312 return ci->u.l.nextraargs;
313 else {
314 TValue res;
315 if (luaH_getshortstr(h, luaS_new(L, "n"), &res) != LUA_VNUMINT ||
316 l_castS2U(ivalue(&res)) > cast_uint(INT_MAX/2))
317 luaG_runerror(L, "vararg table has no proper 'n'");
318 return cast_int(ivalue(&res));
319 }
320}
321
322
323/*
324** Get 'wanted' vararg arguments and put them in 'where'. 'vatab' is
325** the register of the vararg table or -1 if there is no vararg table.
326*/
327void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted,
328 int vatab) {
329 Table *h = (vatab < 0) ? NULL : hvalue(s2v(ci->func.p + vatab + 1));
330 int nargs = getnumargs(L, ci, h); /* number of available vararg args. */
331 int i, touse; /* 'touse' is minimum between 'wanted' and 'nargs' */
305 if (wanted < 0) { 332 if (wanted < 0) {
306 wanted = nextra; /* get all extra arguments available */ 333 touse = wanted = nargs; /* get all extra arguments available */
307 checkstackp(L, nextra, where); /* ensure stack space */ 334 checkstackp(L, nargs, where); /* ensure stack space */
308 L->top.p = where + nextra; /* next instruction will need top */ 335 L->top.p = where + nargs; /* next instruction will need top */
336 }
337 else
338 touse = (nargs > wanted) ? wanted : nargs;
339 if (h == NULL) { /* no vararg table? */
340 for (i = 0; i < touse; i++) /* get vararg values from the stack */
341 setobjs2s(L, where + i, ci->func.p - nargs + i);
342 }
343 else { /* get vararg values from vararg table */
344 for (i = 0; i < touse; i++) {
345 lu_byte tag = luaH_getint(h, i + 1, s2v(where + i));
346 if (tagisempty(tag))
347 setnilvalue(s2v(where + i));
348 }
309 } 349 }
310 for (i = 0; i < wanted && i < nextra; i++)
311 setobjs2s(L, where + i, ci->func.p - nextra + i);
312 for (; i < wanted; i++) /* complete required results with nil */ 350 for (; i < wanted; i++) /* complete required results with nil */
313 setnilvalue(s2v(where + i)); 351 setnilvalue(s2v(where + i));
314} 352}