⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lvm.c

📁 世界上最快的脚本语言lua的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** $Id: lvm.c,v 1.284b 2003/04/03 13:35:34 roberto Exp $** Lua virtual machine** See Copyright Notice in lua.h*/#include <stdarg.h>#include <stdlib.h>#include <string.h>/* needed only when `lua_number2str' uses `sprintf' */#include <stdio.h>#define lvm_c#include "lua.h"#include "ldebug.h"#include "ldo.h"#include "lfunc.h"#include "lgc.h"#include "lobject.h"#include "lopcodes.h"#include "lstate.h"#include "lstring.h"#include "ltable.h"#include "ltm.h"#include "lvm.h"/* function to convert a lua_Number to a string */#ifndef lua_number2str#define lua_number2str(s,n)     sprintf((s), LUA_NUMBER_FMT, (n))#endif/* limit for table tag-method chains (to avoid loops) */#define MAXTAGLOOP	100const TObject *luaV_tonumber (const TObject *obj, TObject *n) {  lua_Number num;  if (ttisnumber(obj)) return obj;  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {    setnvalue(n, num);    return n;  }  else    return NULL;}int luaV_tostring (lua_State *L, StkId obj) {  if (!ttisnumber(obj))    return 0;  else {    char s[32];  /* 16 digits, sign, point and \0  (+ some extra...) */    lua_number2str(s, nvalue(obj));    setsvalue2s(obj, luaS_new(L, s));    return 1;  }}static void traceexec (lua_State *L) {  lu_byte mask = L->hookmask;  if (mask & LUA_MASKCOUNT) {  /* instruction-hook set? */    if (L->hookcount == 0) {      resethookcount(L);      luaD_callhook(L, LUA_HOOKCOUNT, -1);      return;    }  }  if (mask & LUA_MASKLINE) {    CallInfo *ci = L->ci;    Proto *p = ci_func(ci)->l.p;    int newline = getline(p, pcRel(*ci->u.l.pc, p));    if (!L->hookinit) {      luaG_inithooks(L);      return;    }    lua_assert(ci->state & CI_HASFRAME);    if (pcRel(*ci->u.l.pc, p) == 0)  /* tracing may be starting now? */      ci->u.l.savedpc = *ci->u.l.pc;  /* initialize `savedpc' */    /* calls linehook when enters a new line or jumps back (loop) */    if (*ci->u.l.pc <= ci->u.l.savedpc ||        newline != getline(p, pcRel(ci->u.l.savedpc, p))) {      luaD_callhook(L, LUA_HOOKLINE, newline);      ci = L->ci;  /* previous call may reallocate `ci' */    }    ci->u.l.savedpc = *ci->u.l.pc;  }}static void callTMres (lua_State *L, const TObject *f,                       const TObject *p1, const TObject *p2) {  setobj2s(L->top, f);  /* push function */  setobj2s(L->top+1, p1);  /* 1st argument */  setobj2s(L->top+2, p2);  /* 2nd argument */  luaD_checkstack(L, 3);  /* cannot check before (could invalidate p1, p2) */  L->top += 3;  luaD_call(L, L->top - 3, 1);  L->top--;  /* result will be in L->top */}static void callTM (lua_State *L, const TObject *f,                    const TObject *p1, const TObject *p2, const TObject *p3) {  setobj2s(L->top, f);  /* push function */  setobj2s(L->top+1, p1);  /* 1st argument */  setobj2s(L->top+2, p2);  /* 2nd argument */  setobj2s(L->top+3, p3);  /* 3th argument */  luaD_checkstack(L, 4);  /* cannot check before (could invalidate p1...p3) */  L->top += 4;  luaD_call(L, L->top - 4, 0);}static const TObject *luaV_index (lua_State *L, const TObject *t,                                  TObject *key, int loop) {  const TObject *tm = fasttm(L, hvalue(t)->metatable, TM_INDEX);  if (tm == NULL) return &luaO_nilobject;  /* no TM */  if (ttisfunction(tm)) {    callTMres(L, tm, t, key);    return L->top;  }  else return luaV_gettable(L, tm, key, loop);}static const TObject *luaV_getnotable (lua_State *L, const TObject *t,                                       TObject *key, int loop) {  const TObject *tm = luaT_gettmbyobj(L, t, TM_INDEX);  if (ttisnil(tm))    luaG_typeerror(L, t, "index");  if (ttisfunction(tm)) {    callTMres(L, tm, t, key);    return L->top;  }  else return luaV_gettable(L, tm, key, loop);}/*** Function to index a table.** Receives the table at `t' and the key at `key'.** leaves the result at `res'.*/const TObject *luaV_gettable (lua_State *L, const TObject *t, TObject *key,                              int loop) {  if (loop > MAXTAGLOOP)    luaG_runerror(L, "loop in gettable");  if (ttistable(t)) {  /* `t' is a table? */    Table *h = hvalue(t);    const TObject *v = luaH_get(h, key);  /* do a primitive get */    if (!ttisnil(v)) return v;    else return luaV_index(L, t, key, loop+1);  }  else return luaV_getnotable(L, t, key, loop+1);}/*** Receives table at `t', key at `key' and value at `val'.*/void luaV_settable (lua_State *L, const TObject *t, TObject *key, StkId val) {  const TObject *tm;  int loop = 0;  do {    if (ttistable(t)) {  /* `t' is a table? */      Table *h = hvalue(t);      TObject *oldval = luaH_set(L, h, key); /* do a primitive set */      if (!ttisnil(oldval) ||  /* result is no nil? */          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */        setobj2t(oldval, val);  /* write barrier */        return;      }      /* else will try the tag method */    }    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))      luaG_typeerror(L, t, "index");    if (ttisfunction(tm)) {      callTM(L, tm, t, key, val);      return;    }    t = tm;  /* else repeat with `tm' */   } while (++loop <= MAXTAGLOOP);  luaG_runerror(L, "loop in settable");}static int call_binTM (lua_State *L, const TObject *p1, const TObject *p2,                       StkId res, TMS event) {  ptrdiff_t result = savestack(L, res);  const TObject *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */  if (ttisnil(tm))    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */  if (!ttisfunction(tm)) return 0;  callTMres(L, tm, p1, p2);  res = restorestack(L, result);  /* previous call may change stack */  setobjs2s(res, L->top);  return 1;}static const TObject *get_compTM (lua_State *L, Table *mt1, Table *mt2,                                  TMS event) {  const TObject *tm1 = fasttm(L, mt1, event);  const TObject *tm2;  if (tm1 == NULL) return NULL;  /* no metamethod */  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */  tm2 = fasttm(L, mt2, event);  if (tm2 == NULL) return NULL;  /* no metamethod */  if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */    return tm1;  return NULL;}static int call_orderTM (lua_State *L, const TObject *p1, const TObject *p2,                         TMS event) {  const TObject *tm1 = luaT_gettmbyobj(L, p1, event);  const TObject *tm2;  if (ttisnil(tm1)) return -1;  /* no metamethod? */  tm2 = luaT_gettmbyobj(L, p2, event);  if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */    return -1;  callTMres(L, tm1, p1, p2);  return !l_isfalse(L->top);}static int luaV_strcmp (const TString *ls, const TString *rs) {  const char *l = getstr(ls);  size_t ll = ls->tsv.len;  const char *r = getstr(rs);  size_t lr = rs->tsv.len;  for (;;) {    int temp = strcoll(l, r);    if (temp != 0) return temp;    else {  /* strings are equal up to a `\0' */      size_t len = strlen(l);  /* index of first `\0' in both strings */      if (len == lr)  /* r is finished? */        return (len == ll) ? 0 : 1;      else if (len == ll)  /* l is finished? */        return -1;  /* l is smaller than r (because r is not finished) */      /* both strings longer than `len'; go on comparing (after the `\0') */      len++;      l += len; ll -= len; r += len; lr -= len;    }  }}int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r) {  int res;  if (ttype(l) != ttype(r))    return luaG_ordererror(L, l, r);  else if (ttisnumber(l))    return nvalue(l) < nvalue(r);  else if (ttisstring(l))    return luaV_strcmp(tsvalue(l), tsvalue(r)) < 0;  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)    return res;  return luaG_ordererror(L, l, r);}static int luaV_lessequal (lua_State *L, const TObject *l, const TObject *r) {  int res;  if (ttype(l) != ttype(r))    return luaG_ordererror(L, l, r);  else if (ttisnumber(l))    return nvalue(l) <= nvalue(r);  else if (ttisstring(l))    return luaV_strcmp(tsvalue(l), tsvalue(r)) <= 0;  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */    return res;  else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */    return !res;  return luaG_ordererror(L, l, r);}int luaV_equalval (lua_State *L, const TObject *t1, const TObject *t2) {  const TObject *tm;  lua_assert(ttype(t1) == ttype(t2));  switch (ttype(t1)) {    case LUA_TNIL: return 1;    case LUA_TNUMBER: return nvalue(t1) == nvalue(t2);    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);    case LUA_TUSERDATA: {      if (uvalue(t1) == uvalue(t2)) return 1;      tm = get_compTM(L, uvalue(t1)->uv.metatable, uvalue(t2)->uv.metatable,                         TM_EQ);      break;  /* will try TM */    }    case LUA_TTABLE: {      if (hvalue(t1) == hvalue(t2)) return 1;      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);      break;  /* will try TM */    }    default: return gcvalue(t1) == gcvalue(t2);  }  if (tm == NULL) return 0;  /* no TM? */  callTMres(L, tm, t1, t2);  /* call TM */  return !l_isfalse(L->top);}void luaV_concat (lua_State *L, int total, int last) {  do {    StkId top = L->base + last + 1;    int n = 2;  /* number of elements handled in this pass (at least 2) */    if (!tostring(L, top-2) || !tostring(L, top-1)) {      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))        luaG_concaterror(L, top-2, top-1);    } else if (tsvalue(top-1)->tsv.len > 0) {  /* if len=0, do nothing */      /* at least two string values; get as many as possible */      lu_mem tl = cast(lu_mem, tsvalue(top-1)->tsv.len) +                  cast(lu_mem, tsvalue(top-2)->tsv.len);      char *buffer;      int i;      while (n < total && tostring(L, top-n-1)) {  /* collect total length */        tl += tsvalue(top-n-1)->tsv.len;        n++;      }      if (tl > MAX_SIZET) luaG_runerror(L, "string size overflow");      buffer = luaZ_openspace(L, &G(L)->buff, tl);      tl = 0;      for (i=n; i>0; i--) {  /* concat all strings */        size_t l = tsvalue(top-i)->tsv.len;        memcpy(buffer+tl, svalue(top-i), l);        tl += l;      }      setsvalue2s(top-n, luaS_newlstr(L, buffer, tl));    }    total -= n-1;  /* got `n' strings to create 1 new */    last -= n-1;  } while (total > 1);  /* repeat until only 1 result left */}static void Arith (lua_State *L, StkId ra,                   const TObject *rb, const TObject *rc, TMS op) {  TObject tempb, tempc;  const TObject *b, *c;  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&      (c = luaV_tonumber(rc, &tempc)) != NULL) {    switch (op) {      case TM_ADD: setnvalue(ra, nvalue(b) + nvalue(c)); break;      case TM_SUB: setnvalue(ra, nvalue(b) - nvalue(c)); break;      case TM_MUL: setnvalue(ra, nvalue(b) * nvalue(c)); break;      case TM_DIV: setnvalue(ra, nvalue(b) / nvalue(c)); break;      case TM_POW: {        const TObject *f = luaH_getstr(hvalue(gt(L)), G(L)->tmname[TM_POW]);        ptrdiff_t res = savestack(L, ra);        if (!ttisfunction(f))          luaG_runerror(L, "`__pow' (`^' operator) is not a function");        callTMres(L, f, b, c);        ra = restorestack(L, res);  /* previous call may change stack */        setobjs2s(ra, L->top);        break;      }      default: lua_assert(0); break;    }  }  else if (!call_binTM(L, rb, rc, ra, op))    luaG_aritherror(L, rb, rc);}/*** some macros for common tasks in `luaV_execute'*/#define runtime_check(L, c)	{ if (!(c)) return 0; }#define RA(i)	(base+GETARG_A(i))/* to be used after possible stack reallocation */#define XRA(i)	(L->base+GETARG_A(i))#define RB(i)	(base+GETARG_B(i))#define RKB(i)	((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)#define RC(i)	(base+GETARG_C(i))#define RKC(i)	((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)#define KBx(i)	(k+GETARG_Bx(i))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -