Lua TeamLua 5.3.0-rc348416b811 years agoHistory
1270 lines · 29.5 KB · C
RawDownload
/*** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp $** Lua API** See Copyright Notice in lua.h*/ #define lapi_c#define LUA_CORE #include "lprefix.h"  #include <stdarg.h>#include <string.h> #include "lua.h" #include "lapi.h"#include "ldebug.h"#include "ldo.h"#include "lfunc.h"#include "lgc.h"#include "lmem.h"#include "lobject.h"#include "lstate.h"#include "lstring.h"#include "ltable.h"#include "ltm.h"#include "lundump.h"#include "lvm.h"   const char lua_ident[] =  "$LuaVersion: " LUA_COPYRIGHT " $"  "$LuaAuthors: " LUA_AUTHORS " $";  /* value at a non-valid index */#define NONVALIDVALUE		cast(TValue *, luaO_nilobject) /* corresponding test */#define isvalid(o)	((o) != luaO_nilobject) /* test for pseudo index */#define ispseudo(i)		((i) <= LUA_REGISTRYINDEX) /* test for upvalue */#define isupvalue(i)		((i) < LUA_REGISTRYINDEX) /* test for valid but not pseudo index */#define isstackindex(i, o)	(isvalid(o) && !ispseudo(i)) #define api_checkvalidindex(o)  api_check(isvalid(o), "invalid index") #define api_checkstackindex(i, o)  \	api_check(isstackindex(i, o), "index not in the stack")  static TValue *index2addr (lua_State *L, int idx) {  CallInfo *ci = L->ci;  if (idx > 0) {    TValue *o = ci->func + idx;    api_check(idx <= ci->top - (ci->func + 1), "unacceptable index");    if (o >= L->top) return NONVALIDVALUE;    else return o;  }  else if (!ispseudo(idx)) {  /* negative index */    api_check(idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");    return L->top + idx;  }  else if (idx == LUA_REGISTRYINDEX)    return &G(L)->l_registry;  else {  /* upvalues */    idx = LUA_REGISTRYINDEX - idx;    api_check(idx <= MAXUPVAL + 1, "upvalue index too large");    if (ttislcf(ci->func))  /* light C function? */      return NONVALIDVALUE;  /* it has no upvalues */    else {      CClosure *func = clCvalue(ci->func);      return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE;    }  }}  /*** to be called by 'lua_checkstack' in protected mode, to grow stack** capturing memory errors*/static void growstack (lua_State *L, void *ud) {  int size = *(int *)ud;  luaD_growstack(L, size);}  LUA_API int lua_checkstack (lua_State *L, int n) {  int res;  CallInfo *ci = L->ci;  lua_lock(L);  api_check(n >= 0, "negative 'n'");  if (L->stack_last - L->top > n)  /* stack large enough? */    res = 1;  /* yes; check is OK */  else {  /* no; need to grow stack */    int inuse = cast_int(L->top - L->stack) + EXTRA_STACK;    if (inuse > LUAI_MAXSTACK - n)  /* can grow without overflow? */      res = 0;  /* no */    else  /* try to grow stack */      res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK);  }  if (res && ci->top < L->top + n)    ci->top = L->top + n;  /* adjust frame top */  lua_unlock(L);  return res;}  LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {  int i;  if (from == to) return;  lua_lock(to);  api_checknelems(from, n);  api_check(G(from) == G(to), "moving among independent states");  api_check(to->ci->top - to->top >= n, "not enough elements to move");  from->top -= n;  for (i = 0; i < n; i++) {    setobj2s(to, to->top++, from->top + i);  }  lua_unlock(to);}  LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {  lua_CFunction old;  lua_lock(L);  old = G(L)->panic;  G(L)->panic = panicf;  lua_unlock(L);  return old;}  LUA_API const lua_Number *lua_version (lua_State *L) {  static const lua_Number version = LUA_VERSION_NUM;  if (L == NULL) return &version;  else return G(L)->version;}   /*** basic stack manipulation*/  /*** convert an acceptable stack index into an absolute index*/LUA_API int lua_absindex (lua_State *L, int idx) {  return (idx > 0 || ispseudo(idx))         ? idx         : cast_int(L->top - L->ci->func + idx);}  LUA_API int lua_gettop (lua_State *L) {  return cast_int(L->top - (L->ci->func + 1));}  LUA_API void lua_settop (lua_State *L, int idx) {  StkId func = L->ci->func;  lua_lock(L);  if (idx >= 0) {    api_check(idx <= L->stack_last - (func + 1), "new top too large");    while (L->top < (func + 1) + idx)      setnilvalue(L->top++);    L->top = (func + 1) + idx;  }  else {    api_check(-(idx+1) <= (L->top - (func + 1)), "invalid new top");    L->top += idx+1;  /* 'subtract' index (index is negative) */  }  lua_unlock(L);}  /*** Reverse the stack segment from 'from' to 'to'** (auxiliary to 'lua_rotate')*/static void reverse (lua_State *L, StkId from, StkId to) {  for (; from < to; from++, to--) {    TValue temp;    setobj(L, &temp, from);    setobjs2s(L, from, to);    setobj2s(L, to, &temp);  }}  /*** Let x = AB, where A is a prefix of length 'n'. Then,** rotate x n == BA. But BA == (A^r . B^r)^r.*/LUA_API void lua_rotate (lua_State *L, int idx, int n) {  StkId p, t, m;  lua_lock(L);  t = L->top - 1;  /* end of stack segment being rotated */  p = index2addr(L, idx);  /* start of segment */  api_checkstackindex(idx, p);  api_check((n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");  m = (n >= 0 ? t - n : p - n - 1);  /* end of prefix */  reverse(L, p, m);  /* reverse the prefix with length 'n' */  reverse(L, m + 1, t);  /* reverse the suffix */  reverse(L, p, t);  /* reverse the entire segment */  lua_unlock(L);}  LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {  TValue *fr, *to;  lua_lock(L);  fr = index2addr(L, fromidx);  to = index2addr(L, toidx);  api_checkvalidindex(to);  setobj(L, to, fr);  if (isupvalue(toidx))  /* function upvalue? */    luaC_barrier(L, clCvalue(L->ci->func), fr);  /* LUA_REGISTRYINDEX does not need gc barrier     (collector revisits it before finishing collection) */  lua_unlock(L);}  LUA_API void lua_pushvalue (lua_State *L, int idx) {  lua_lock(L);  setobj2s(L, L->top, index2addr(L, idx));  api_incr_top(L);  lua_unlock(L);}   /*** access functions (stack -> C)*/  LUA_API int lua_type (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  return (isvalid(o) ? ttnov(o) : LUA_TNONE);}  LUA_API const char *lua_typename (lua_State *L, int t) {  UNUSED(L);  api_check(LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");  return ttypename(t);}  LUA_API int lua_iscfunction (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  return (ttislcf(o) || (ttisCclosure(o)));}  LUA_API int lua_isinteger (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  return ttisinteger(o);}  LUA_API int lua_isnumber (lua_State *L, int idx) {  lua_Number n;  const TValue *o = index2addr(L, idx);  return tonumber(o, &n);}  LUA_API int lua_isstring (lua_State *L, int idx) {  const TValue *o = index2addr(L, idx);  return (ttisstring(o) || cvt2str(o));}  LUA_API int lua_isuserdata (lua_State *L, int idx) {  const TValue *o = index2addr(L, idx);  return (ttisfulluserdata(o) || ttislightuserdata(o));}  LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {  StkId o1 = index2addr(L, index1);  StkId o2 = index2addr(L, index2);  return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0;}  LUA_API void lua_arith (lua_State *L, int op) {  lua_lock(L);  if (op != LUA_OPUNM && op != LUA_OPBNOT)    api_checknelems(L, 2);  /* all other operations expect two operands */  else {  /* for unary operations, add fake 2nd operand */    api_checknelems(L, 1);    setobjs2s(L, L->top, L->top - 1);    L->top++;  }  /* first operand at top - 2, second at top - 1; result go to top - 2 */  luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);  L->top--;  /* remove second operand */  lua_unlock(L);}  LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {  StkId o1, o2;  int i = 0;  lua_lock(L);  /* may call tag method */  o1 = index2addr(L, index1);  o2 = index2addr(L, index2);  if (isvalid(o1) && isvalid(o2)) {    switch (op) {      case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;      case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;      case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;      default: api_check(0, "invalid option");    }  }  lua_unlock(L);  return i;}  LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {  size_t sz = luaO_str2num(s, L->top);  if (sz != 0)    api_incr_top(L);  return sz;}  LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {  lua_Number n;  const TValue *o = index2addr(L, idx);  int isnum = tonumber(o, &n);  if (!isnum)    n = 0;  /* call to 'tonumber' may change 'n' even if it fails */  if (pisnum) *pisnum = isnum;  return n;}  LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {  lua_Integer res;  const TValue *o = index2addr(L, idx);  int isnum = tointeger(o, &res);  if (!isnum)    res = 0;  /* call to 'tointeger' may change 'n' even if it fails */  if (pisnum) *pisnum = isnum;  return res;}  LUA_API int lua_toboolean (lua_State *L, int idx) {  const TValue *o = index2addr(L, idx);  return !l_isfalse(o);}  LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {  StkId o = index2addr(L, idx);  if (!ttisstring(o)) {    if (!cvt2str(o)) {  /* not convertible? */      if (len != NULL) *len = 0;      return NULL;    }    lua_lock(L);  /* 'luaO_tostring' may create a new string */    luaC_checkGC(L);    o = index2addr(L, idx);  /* previous call may reallocate the stack */    luaO_tostring(L, o);    lua_unlock(L);  }  if (len != NULL) *len = tsvalue(o)->len;  return svalue(o);}  LUA_API size_t lua_rawlen (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  switch (ttnov(o)) {    case LUA_TSTRING: return tsvalue(o)->len;    case LUA_TUSERDATA: return uvalue(o)->len;    case LUA_TTABLE: return luaH_getn(hvalue(o));    default: return 0;  }}  LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  if (ttislcf(o)) return fvalue(o);  else if (ttisCclosure(o))    return clCvalue(o)->f;  else return NULL;  /* not a C function */}  LUA_API void *lua_touserdata (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  switch (ttnov(o)) {    case LUA_TUSERDATA: return getudatamem(uvalue(o));    case LUA_TLIGHTUSERDATA: return pvalue(o);    default: return NULL;  }}  LUA_API lua_State *lua_tothread (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  return (!ttisthread(o)) ? NULL : thvalue(o);}  LUA_API const void *lua_topointer (lua_State *L, int idx) {  StkId o = index2addr(L, idx);  switch (ttype(o)) {    case LUA_TTABLE: return hvalue(o);    case LUA_TLCL: return clLvalue(o);    case LUA_TCCL: return clCvalue(o);    case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));    case LUA_TTHREAD: return thvalue(o);    case LUA_TUSERDATA:    case LUA_TLIGHTUSERDATA:      return lua_touserdata(L, idx);    default: return NULL;  }}   /*** push functions (C -> stack)*/  LUA_API void lua_pushnil (lua_State *L) {  lua_lock(L);  setnilvalue(L->top);  api_incr_top(L);  lua_unlock(L);}  LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {  lua_lock(L);  setfltvalue(L->top, n);  api_incr_top(L);  lua_unlock(L);}  LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {  lua_lock(L);  setivalue(L->top, n);  api_incr_top(L);  lua_unlock(L);}  LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {  TString *ts;  lua_lock(L);  luaC_checkGC(L);  ts = luaS_newlstr(L, s, len);  setsvalue2s(L, L->top, ts);  api_incr_top(L);  lua_unlock(L);  return getstr(ts);}  LUA_API const char *lua_pushstring (lua_State *L, const char *s) {  if (s == NULL) {    lua_pushnil(L);    return NULL;  }  else {    TString *ts;    lua_lock(L);    luaC_checkGC(L);    ts = luaS_new(L, s);    setsvalue2s(L, L->top, ts);    api_incr_top(L);    lua_unlock(L);    return getstr(ts);  }} 

Lines 1–500 of 1270.