/* ** return false if folding can raise an error */ static int validop (int op, TValue *v1, TValue *v2) { lua_Number a, b; lua_Integer i; cast_void(a); cast_void(b); /* macro may not use its arguments */ if (luai_numinvalidop(op, (cast_void(tonumber(v1, &a)), a), (cast_void(tonumber(v2, &b)), b))) return 0; switch (op) { case LUA_OPIDIV: /* division by 0 and conversion errors */ return (tointeger(v1, &i) && tointeger(v2, &i) && i != 0); case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: /* conversion errors */ return (tointeger(v1, &i) && tointeger(v2, &i)); case LUA_OPMOD: /* integer module by 0 */ return !(ttisinteger(v1) && ttisinteger(v2) && ivalue(v2) == 0); default: return 1; /* everything else is valid */ } }
/* ** Main operation for concatenation: concat 'total' values in the stack, ** from 'L->top - total' up to 'L->top - 1'. */ void luaV_concat (lua_State *L, int total) { lua_assert(total >= 2); do { StkId top = L->top; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); else if (isemptystr(top - 1)) /* second operand is empty? */ cast_void(tostring(L, top - 2)); /* result is first operand */ else if (isemptystr(top - 2)) { /* first operand is an empty string? */ setobjs2s(L, top - 2, top - 1); /* result is second op. */ } else { /* at least two non-empty string values; get as many as possible */ size_t tl = vslen(top - 1); TString *ts; /* collect total length and number of strings */ for (n = 1; n < total && tostring(L, top - n - 1); n++) { size_t l = vslen(top - n - 1); if (l >= (MAX_SIZE/sizeof(char)) - tl) luaG_runerror(L, "string length overflow"); tl += l; } if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ char buff[LUAI_MAXSHORTLEN]; copy2buff(top, n, buff); /* copy strings to buffer */ ts = luaS_newlstr(L, buff, tl); } else { /* long string; copy strings directly to final result */ ts = luaS_createlngstrobj(L, tl); copy2buff(top, n, getstr(ts)); } setsvalue2s(L, top - n, ts); /* create result */ } total -= n-1; /* got 'n' strings to create 1 new */ L->top -= n-1; /* popped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ }