1281 lines · 29.0 KB · C
RawDownload
/*** $Id: lapi.c,v 2.164 2012/06/08 15:14:04 roberto Exp $** Lua API** See Copyright Notice in lua.h*/  #include <stdarg.h>#include <string.h> #define lapi_c#define LUA_CORE #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) #define api_checkvalidindex(L, i)  api_check(L, isvalid(i), "invalid index")  static TValue *index2addr (lua_State *L, int idx) {  CallInfo *ci = L->ci;  if (idx > 0) {    TValue *o = ci->func + idx;    api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");    if (o >= L->top) return NONVALIDVALUE;    else return o;  }  else if (idx > LUA_REGISTRYINDEX) {    api_check(L, 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(L, 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 size) {  int res;  CallInfo *ci = L->ci;  lua_lock(L);  if (L->stack_last - L->top > size)  /* 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 - size)  /* can grow without overflow? */      res = 0;  /* no */    else  /* try to grow stack */      res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK);  }  if (res && ci->top < L->top + size)    ci->top = L->top + size;  /* 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(from, G(from) == G(to), "moving among independent states");  api_check(from, 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 || idx <= LUA_REGISTRYINDEX)         ? 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(L, 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(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");    L->top += idx+1;  /* `subtract' index (index is negative) */  }  lua_unlock(L);}  LUA_API void lua_remove (lua_State *L, int idx) {  StkId p;  lua_lock(L);  p = index2addr(L, idx);  api_checkvalidindex(L, p);  while (++p < L->top) setobjs2s(L, p-1, p);  L->top--;  lua_unlock(L);}  LUA_API void lua_insert (lua_State *L, int idx) {  StkId p;  StkId q;  lua_lock(L);  p = index2addr(L, idx);  api_checkvalidindex(L, p);  for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);  setobjs2s(L, p, L->top);  lua_unlock(L);}  static void moveto (lua_State *L, TValue *fr, int idx) {  TValue *to = index2addr(L, idx);  api_checkvalidindex(L, to);  setobj(L, to, fr);  if (idx < LUA_REGISTRYINDEX)  /* function upvalue? */    luaC_barrier(L, clCvalue(L->ci->func), fr);  /* LUA_REGISTRYINDEX does not need gc barrier     (collector revisits it before finishing collection) */}  LUA_API void lua_replace (lua_State *L, int idx) {  lua_lock(L);  api_checknelems(L, 1);  moveto(L, L->top - 1, idx);  L->top--;  lua_unlock(L);}  LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {  TValue *fr;  lua_lock(L);  fr = index2addr(L, fromidx);  api_checkvalidindex(L, fr);  moveto(L, fr, toidx);  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) ? ttypenv(o) : LUA_TNONE);}  LUA_API const char *lua_typename (lua_State *L, int t) {  UNUSED(L);  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_isnumber (lua_State *L, int idx) {  TValue n;  const TValue *o = index2addr(L, idx);  return tonumber(o, &n);}  LUA_API int lua_isstring (lua_State *L, int idx) {  int t = lua_type(L, idx);  return (t == LUA_TSTRING || t == LUA_TNUMBER);}  LUA_API int lua_isuserdata (lua_State *L, int idx) {  const TValue *o = index2addr(L, idx);  return (ttisuserdata(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) {  StkId o1;  /* 1st operand */  StkId o2;  /* 2nd operand */  lua_lock(L);  if (op != LUA_OPUNM) /* all other operations expect two operands */    api_checknelems(L, 2);  else {  /* for unary minus, add fake 2nd operand */    api_checknelems(L, 1);    setobjs2s(L, L->top, L->top - 1);    L->top++;  }  o1 = L->top - 2;  o2 = L->top - 1;  if (ttisnumber(o1) && ttisnumber(o2)) {    changenvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2)));  }  else    luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD));  L->top--;  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 = 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(L, 0, "invalid option");    }  }  lua_unlock(L);  return i;}  LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) {  TValue n;  const TValue *o = index2addr(L, idx);  if (tonumber(o, &n)) {    if (isnum) *isnum = 1;    return nvalue(o);  }  else {    if (isnum) *isnum = 0;    return 0;  }}  LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) {  TValue n;  const TValue *o = index2addr(L, idx);  if (tonumber(o, &n)) {    lua_Integer res;    lua_Number num = nvalue(o);    lua_number2integer(res, num);    if (isnum) *isnum = 1;    return res;  }  else {    if (isnum) *isnum = 0;    return 0;  }}  LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) {  TValue n;  const TValue *o = index2addr(L, idx);  if (tonumber(o, &n)) {    lua_Unsigned res;    lua_Number num = nvalue(o);    lua_number2unsigned(res, num);    if (isnum) *isnum = 1;    return res;  }  else {    if (isnum) *isnum = 0;    return 0;  }}  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)) {    lua_lock(L);  /* `luaV_tostring' may create a new string */    if (!luaV_tostring(L, o)) {  /* conversion failed? */      if (len != NULL) *len = 0;      lua_unlock(L);      return NULL;    }    luaC_checkGC(L);    o = index2addr(L, idx);  /* previous call may reallocate the stack */    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 (ttypenv(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 (ttypenv(o)) {    case LUA_TUSERDATA: return (rawuvalue(o) + 1);    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);  setnvalue(L->top, n);  luai_checknum(L, L->top,    luaG_runerror(L, "C API - attempt to push a signaling NaN"));  api_incr_top(L);  lua_unlock(L);}  LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {  lua_lock(L);  setnvalue(L->top, cast_num(n));  api_incr_top(L);  lua_unlock(L);}  LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) {  lua_Number n;  lua_lock(L);  n = lua_unsigned2number(u);  setnvalue(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);

Lines 1–500 of 1281.