📄 lbaselib.c.svn-base
字号:
static int PVEB_dofile (PVE_State *L) {
const char *fname = PVEL_optstring(L, 1, NULL);
int n = PVE_gettop(L);
if (PVEL_loadfile(L, fname) != 0) PVE_error(L);
PVE_call(L, 0, PVE_MULTRET);
return PVE_gettop(L) - n;
}
static int PVEB_assert (PVE_State *L) {
PVEL_checkany(L, 1);
if (!PVE_toboolean(L, 1))
return PVEL_error(L, "%s", PVEL_optstring(L, 2, "assertion failed!"));
return PVE_gettop(L);
}
static int PVEB_unpack (PVE_State *L) {
int i, e, n;
PVEL_checktype(L, 1, PVE_TTABLE);
i = PVEL_optint(L, 2, 1);
e = PVEL_opt(L, PVEL_checkint, 3, PVEL_getn(L, 1));
n = e - i + 1; /* number of elements */
if (n <= 0) return 0; /* empty range */
PVEL_checkstack(L, n, "table too big to unpack");
for (; i<=e; i++) /* push arg[i...e] */
PVE_rawgeti(L, 1, i);
return n;
}
static int PVEB_select (PVE_State *L) {
int n = PVE_gettop(L);
if (PVE_type(L, 1) == PVE_TSTRING && *PVE_tostring(L, 1) == '#') {
PVE_pushinteger(L, n-1);
return 1;
}
else {
int i = PVEL_checkint(L, 1);
if (i < 0) i = n + i;
else if (i > n) i = n;
PVEL_argcheck(L, 1 <= i, 1, "index out of range");
return n - i;
}
}
static int PVEB_pcall (PVE_State *L) {
int status;
PVEL_checkany(L, 1);
status = PVE_pcall(L, PVE_gettop(L) - 1, PVE_MULTRET, 0);
PVE_pushboolean(L, (status == 0));
PVE_insert(L, 1);
return PVE_gettop(L); /* return status + all results */
}
static int PVEB_xpcall (PVE_State *L) {
int status;
PVEL_checkany(L, 2);
PVE_settop(L, 2);
PVE_insert(L, 1); /* put error function under function to be called */
status = PVE_pcall(L, 0, PVE_MULTRET, 1);
PVE_pushboolean(L, (status == 0));
PVE_replace(L, 1);
return PVE_gettop(L); /* return status + all results */
}
static int PVEB_tostring (PVE_State *L) {
PVEL_checkany(L, 1);
if (PVEL_callmeta(L, 1, "__tostring")) /* is there a metafield? */
return 1; /* use its value */
switch (PVE_type(L, 1)) {
case PVE_TNUMBER:
PVE_pushstring(L, PVE_tostring(L, 1));
break;
case PVE_TSTRING:
PVE_pushvalue(L, 1);
break;
case PVE_TBOOLEAN:
PVE_pushstring(L, (PVE_toboolean(L, 1) ? "true" : "false"));
break;
case PVE_TNIL:
PVE_pushliteral(L, "nil");
break;
default:
PVE_pushfstring(L, "%s: %p", PVEL_typename(L, 1), PVE_topointer(L, 1));
break;
}
return 1;
}
static int PVEB_newproxy (PVE_State *L) {
PVE_settop(L, 1);
PVE_newuserdata(L, 0); /* create proxy */
if (PVE_toboolean(L, 1) == 0)
return 1; /* no metatable */
else if (PVE_isboolean(L, 1)) {
PVE_newtable(L); /* create a new metatable `m' ... */
PVE_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */
PVE_pushboolean(L, 1);
PVE_rawset(L, PVE_upvalueindex(1)); /* weaktable[m] = true */
}
else {
int validproxy = 0; /* to check if weaktable[metatable(u)] == true */
if (PVE_getmetatable(L, 1)) {
PVE_rawget(L, PVE_upvalueindex(1));
validproxy = PVE_toboolean(L, -1);
PVE_pop(L, 1); /* remove value */
}
PVEL_argcheck(L, validproxy, 1, "boolean or proxy expected");
PVE_getmetatable(L, 1); /* metatable is valid; get it */
}
PVE_setmetatable(L, 2);
return 1;
}
static const PVEL_Reg base_funcs[] = {
{"assert", PVEB_assert},
{"collectgarbage", PVEB_collectgarbage},
{"dofile", PVEB_dofile},
{"error", PVEB_error},
{"gcinfo", PVEB_gcinfo},
{"getfenv", PVEB_getfenv},
{"getmetatable", PVEB_getmetatable},
{"loadfile", PVEB_loadfile},
{"load", PVEB_load},
{"loadstring", PVEB_loadstring},
{"next", PVEB_next},
{"pcall", PVEB_pcall},
{"print", PVEB_print},
{"rawequal", PVEB_rawequal},
{"rawget", PVEB_rawget},
{"rawset", PVEB_rawset},
{"select", PVEB_select},
{"setfenv", PVEB_setfenv},
{"setmetatable", PVEB_setmetatable},
{"tonumber", PVEB_tonumber},
{"tostring", PVEB_tostring},
{"type", PVEB_type},
{"unpack", PVEB_unpack},
{"xpcall", PVEB_xpcall},
{NULL, NULL}
};
/*
** {======================================================
** Coroutine library
** =======================================================
*/
static int auxresume (PVE_State *L, PVE_State *co, int narg) {
int status;
if (!PVE_checkstack(co, narg))
PVEL_error(L, "too many arguments to resume");
if (PVE_status(co) == 0 && PVE_gettop(co) == 0) {
PVE_pushliteral(L, "cannot resume dead coroutine");
return -1; /* error flag */
}
PVE_xmove(L, co, narg);
status = PVE_resume(co, narg);
if (status == 0 || status == PVE_YIELD) {
int nres = PVE_gettop(co);
if (!PVE_checkstack(L, nres))
PVEL_error(L, "too many results to resume");
PVE_xmove(co, L, nres); /* move yielded values */
return nres;
}
else {
PVE_xmove(co, L, 1); /* move error message */
return -1; /* error flag */
}
}
static int PVEB_coresume (PVE_State *L) {
PVE_State *co = PVE_tothread(L, 1);
int r;
PVEL_argcheck(L, co, 1, "coroutine expected");
r = auxresume(L, co, PVE_gettop(L) - 1);
if (r < 0) {
PVE_pushboolean(L, 0);
PVE_insert(L, -2);
return 2; /* return false + error message */
}
else {
PVE_pushboolean(L, 1);
PVE_insert(L, -(r + 1));
return r + 1; /* return true + `resume' returns */
}
}
static int PVEB_auxwrap (PVE_State *L) {
PVE_State *co = PVE_tothread(L, PVE_upvalueindex(1));
int r = auxresume(L, co, PVE_gettop(L));
if (r < 0) {
if (PVE_isstring(L, -1)) { /* error object is a string? */
PVEL_where(L, 1); /* add extra info */
PVE_insert(L, -2);
PVE_concat(L, 2);
}
PVE_error(L); /* propagate error */
}
return r;
}
static int PVEB_cocreate (PVE_State *L) {
PVE_State *NL = PVE_newthread(L);
PVEL_argcheck(L, PVE_isfunction(L, 1) && !PVE_iscfunction(L, 1), 1,
"PVE function expected");
PVE_pushvalue(L, 1); /* move function to top */
PVE_xmove(L, NL, 1); /* move function from L to NL */
return 1;
}
static int PVEB_cowrap (PVE_State *L) {
PVEB_cocreate(L);
PVE_pushcclosure(L, PVEB_auxwrap, 1);
return 1;
}
static int PVEB_yield (PVE_State *L) {
return PVE_yield(L, PVE_gettop(L));
}
static int PVEB_costatus (PVE_State *L) {
PVE_State *co = PVE_tothread(L, 1);
PVEL_argcheck(L, co, 1, "coroutine expected");
if (L == co) PVE_pushliteral(L, "running");
else {
switch (PVE_status(co)) {
case PVE_YIELD:
PVE_pushliteral(L, "suspended");
break;
case 0: {
PVE_Debug ar;
if (PVE_getstack(co, 0, &ar) > 0) /* does it have frames? */
PVE_pushliteral(L, "normal"); /* it is running */
else if (PVE_gettop(co) == 0)
PVE_pushliteral(L, "dead");
else
PVE_pushliteral(L, "suspended"); /* initial state */
break;
}
default: /* some error occured */
PVE_pushliteral(L, "dead");
break;
}
}
return 1;
}
static int PVEB_corunning (PVE_State *L) {
if (PVE_pushthread(L))
return 0; /* main thread is not a coroutine */
else
return 1;
}
static const PVEL_Reg co_funcs[] = {
{"create", PVEB_cocreate},
{"resume", PVEB_coresume},
{"running", PVEB_corunning},
{"status", PVEB_costatus},
{"wrap", PVEB_cowrap},
{"yield", PVEB_yield},
{NULL, NULL}
};
/* }====================================================== */
static void auxopen (PVE_State *L, const char *name,
PVE_CFunction f, PVE_CFunction u) {
PVE_pushcfunction(L, u);
PVE_pushcclosure(L, f, 1);
PVE_setfield(L, -2, name);
}
static void base_open (PVE_State *L) {
/* set global _G */
PVE_pushvalue(L, PVE_GLOBALSINDEX);
PVE_setglobal(L, "_G");
/* open lib into global table */
PVEL_register(L, "_G", base_funcs);
PVE_pushliteral(L, PVE_VERSION);
PVE_setglobal(L, "_VERSION"); /* set global _VERSION */
/* `ipairs' and `pairs' need auxliliary functions as upvalues */
auxopen(L, "ipairs", PVEB_ipairs, ipairsaux);
auxopen(L, "pairs", PVEB_pairs, PVEB_next);
/* `newproxy' needs a weaktable as upvalue */
PVE_createtable(L, 0, 1); /* new table `w' */
PVE_pushvalue(L, -1); /* `w' will be its own metatable */
PVE_setmetatable(L, -2);
PVE_pushliteral(L, "kv");
PVE_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
PVE_pushcclosure(L, PVEB_newproxy, 1);
PVE_setglobal(L, "newproxy"); /* set global `newproxy' */
}
PVELIB_API int PVEopen_base (PVE_State *L) {
base_open(L);
PVEL_register(L, PVE_COLIBNAME, co_funcs);
return 2;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -