diff options
Diffstat (limited to 'ltm.c')
| -rw-r--r-- | ltm.c | 64 |
1 files changed, 51 insertions, 13 deletions
| @@ -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 | ||
| 302 | void 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 | */ | ||
| 310 | static 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 | */ | ||
| 327 | void 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 | } |
