Beispiel #1
0
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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}