static void addfield (lv_State *L, lvL_Buffer *b, int i) { lv_rawgeti(L, 1, i); if (!lv_isstring(L, -1)) lvL_error(L, "invalid value (%s) at index %d in table for " LV_QL("concat"), lvL_typename(L, -1), i); lvL_addvalue(b); }
static int db_errorfb (lv_State *L) { int level; int firstpart = 1; /* still before eventual `...' */ int arg; lv_State *L1 = getthread(L, &arg); lv_Debug ar; if (lv_isnumber(L, arg+2)) { level = (int)lv_tointeger(L, arg+2); lv_pop(L, 1); } else level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ if (lv_gettop(L) == arg) lv_pushliteral(L, ""); else if (!lv_isstring(L, arg+1)) return 1; /* message is not a string */ else lv_pushliteral(L, "\n"); lv_pushliteral(L, "调用栈:"); while (lv_getstack(L1, level++, &ar)) { if (level > LEVELS1 && firstpart) { /* no more than `LEVELS2' more levels? */ if (!lv_getstack(L1, level+LEVELS2, &ar)) level--; /* keep going */ else { lv_pushliteral(L, "\n\t..."); /* too many levels */ while (lv_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ level++; } firstpart = 0; continue; } lv_pushliteral(L, "\n\t"); lv_getinfo(L1, "Snl", &ar); lv_pushfstring(L, "%s:", ar.source); if (ar.currentline > 0) lv_pushfstring(L, "%d:", ar.currentline); if (*ar.namewhat != '\0') /* is there a name? */ lv_pushfstring(L, " in function " LV_QS, ar.name); else { if (*ar.what == 'm') /* main? */ lv_pushfstring(L, " in main chunk"); else if (*ar.what == 'C' || *ar.what == 't') lv_pushliteral(L, " ?"); /* C function or tail call */ else lv_pushfstring(L, " in function <%s:%d>", ar.source, ar.linedefined); } lv_concat(L, lv_gettop(L) - arg); } lv_concat(L, lv_gettop(L) - arg); return 1; }
void err_explain(int err, lframe_t *frame) { lclosure_t *caller; lfunc_t *func; lframe_t *caller_frame = frame; assert(frame != NULL); while (caller_frame->closure->type != LUAF_LUA) { assert(caller_frame->caller != NULL); assert(caller_frame->caller != caller_frame); caller_frame = caller_frame->caller; } caller = caller_frame->closure; func = caller->function.lua; int len = 0; u32 pc = GETPC(caller_frame, func); /* TODO: this is a result of JIT code not updating its PC, we should change in the JIT code? */ pc -= !!pc; /* Figure out debug information from the luac file of where the call came from (source line) */ assert(pc < func->num_lines); switch (err) { case ERR_MISSING: len = sprintf(err_desc, "%.25s:%u: bad argument #%d to '%s' (%s expected, " "got no value)", func->file, func->lines[pc], err_info[0] + 1, funstr(vm_running->closure), err_typestr(err_info[1])); break; case ERR_BADTYPE: len = sprintf(err_desc, "%.25s:%u: bad argument #%d to '%s' (%s expected, got %s)", func->file, func->lines[pc], err_info[0] + 1, funstr(vm_running->closure), err_typestr(err_info[1]), err_typestr(err_info[2])); break; case ERR_STR: len = sprintf(err_desc, "%.25s:%u: bad argument #%d to '%s' (%s)", func->file, func->lines[pc], err_info[0] + 1, funstr(vm_running->closure), err_custom); break; case ERR_RAWSTR: if (err_info[0]) { len = sprintf(err_desc, "%.25s:%u: %s", func->file, func->lines[pc], err_custom); } else { len = sprintf(err_desc, "%s", err_custom); } break; case ERR_LUAV: if (err_catcher) { if (lv_isstring(err_value) && frame->closure->type == LUAF_LUA) { len = sprintf(err_desc, "%.25s:%u: %s", func->file, func->lines[pc], lv_caststring(err_value, 0)->data); err_desc[len] = 0; err_value = lv_string(lstr_literal(err_desc, FALSE)); } } else { len = sprintf(err_desc, "(error object is not a string)"); } break; default: panic("Unknown error type: %d", err); } if (err_catcher != NULL) { if (err != ERR_LUAV) { err_desc[len] = 0; err_value = lv_string(lstr_literal(err_desc, FALSE)); } _longjmp(*err_catcher, 1); } assert(lua_program != NULL); printf("%s: %s\n", lua_program, err_desc); printf("stack traceback:\n"); while (frame != NULL) { lclosure_t *closure = frame->closure; printf("\t"); if (closure->type == LUAF_C) { printf("[C]: in function '%s'", closure->function.c->name); } else { lfunc_t *function = closure->function.lua; pc = GETPC(frame, function); pc -= !!pc; assert(pc < function->num_lines); printf("%s:%d: ", function->file, function->lines[pc]); lstring_t *fname = function->name; if (fname->length == 0) { printf("in function <%s:%d>", function->file, function->start_line); } else if (fname->data[0] == '@') { printf("in main chunk"); } else { printf("in function '%.*s'", (int) fname->length, fname->data); } } printf("\n"); frame = frame->caller; } exit(1); }