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

📄 lauxlib.c

📁 絲路server源碼 Silk Road server source
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
** $Id: lauxlib.c,v 1.159 2006/03/21 19:31:09 roberto Exp $
** Auxiliary functions for building PVE libraries
** See Copyright Notice in PVE.h
*/


#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/* This file uses only the official API of PVE.
** Any function declared here could be written as an application function.
*/

#define lauxlib_c
#define PVE_LIB

#include "PVE.h"

#include "lauxlib.h"


#define FREELIST_REF	0	/* free list of references */


/* convert a stack index to positive */
#define abs_index(L, i)		((i) > 0 || (i) <= PVE_REGISTRYINDEX ? (i) : \
					PVE_gettop(L) + (i) + 1)


/*
** {======================================================
** Error-report functions
** =======================================================
*/


PVELIB_API int PVEL_argerror (PVE_State *L, int narg, const char *extramsg) {
  PVE_Debug ar;
  if (!PVE_getstack(L, 0, &ar))  /* no stack frame? */
    return PVEL_error(L, "bad argument #%d (%s)", narg, extramsg);
  PVE_getinfo(L, "n", &ar);
  if (strcmp(ar.namewhat, "method") == 0) {
    narg--;  /* do not count `self' */
    if (narg == 0)  /* error is in the self argument itself? */
      return PVEL_error(L, "calling " PVE_QS " on bad self (%s)",
                           ar.name, extramsg);
  }
  if (ar.name == NULL)
    ar.name = "?";
  return PVEL_error(L, "bad argument #%d to " PVE_QS " (%s)",
                        narg, ar.name, extramsg);
}


PVELIB_API int PVEL_typerror (PVE_State *L, int narg, const char *tname) {
  const char *msg = PVE_pushfstring(L, "%s expected, got %s",
                                    tname, PVEL_typename(L, narg));
  return PVEL_argerror(L, narg, msg);
}


static void tag_error (PVE_State *L, int narg, int tag) {
  PVEL_typerror(L, narg, PVE_typename(L, tag));
}


PVELIB_API void PVEL_where (PVE_State *L, int level) {
  PVE_Debug ar;
  if (PVE_getstack(L, level, &ar)) {  /* check function at level */
    PVE_getinfo(L, "Sl", &ar);  /* get info about it */
    if (ar.currentline > 0) {  /* is there info? */
      PVE_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
      return;
    }
  }
  PVE_pushliteral(L, "");  /* else, no information available... */
}


PVELIB_API int PVEL_error (PVE_State *L, const char *fmt, ...) {
  va_list argp;
  va_start(argp, fmt);
  PVEL_where(L, 1);
  PVE_pushvfstring(L, fmt, argp);
  va_end(argp);
  PVE_concat(L, 2);
  return PVE_error(L);
}

/* }====================================================== */


PVELIB_API int PVEL_checkoption (PVE_State *L, int narg, const char *def,
                                 const char *const lst[]) {
  const char *name = (def) ? PVEL_optstring(L, narg, def) :
                             PVEL_checkstring(L, narg);
  int i;
  for (i=0; lst[i]; i++)
    if (strcmp(lst[i], name) == 0)
      return i;
  return PVEL_argerror(L, narg,
                       PVE_pushfstring(L, "invalid option " PVE_QS, name));
}


PVELIB_API int PVEL_newmetatable (PVE_State *L, const char *tname) {
  PVE_getfield(L, PVE_REGISTRYINDEX, tname);  /* get registry.name */
  if (!PVE_isnil(L, -1))  /* name already in use? */
    return 0;  /* leave previous value on top, but return 0 */
  PVE_pop(L, 1);
  PVE_newtable(L);  /* create metatable */
  PVE_pushvalue(L, -1);
  PVE_setfield(L, PVE_REGISTRYINDEX, tname);  /* registry.name = metatable */
  return 1;
}


PVELIB_API void *PVEL_checkudata (PVE_State *L, int ud, const char *tname) {
  void *p = PVE_touserdata(L, ud);
  if (p != NULL) {  /* value is a userdata? */
    if (PVE_getmetatable(L, ud)) {  /* does it have a metatable? */
      PVE_getfield(L, PVE_REGISTRYINDEX, tname);  /* get correct metatable */
      if (PVE_rawequal(L, -1, -2)) {  /* does it have the correct mt? */
        PVE_pop(L, 2);  /* remove both metatables */
        return p;
      }
    }
  }
  PVEL_typerror(L, ud, tname);  /* else error */
  return NULL;  /* to avoid warnings */
}


PVELIB_API void PVEL_checkstack (PVE_State *L, int space, const char *mes) {
  if (!PVE_checkstack(L, space))
    PVEL_error(L, "stack overflow (%s)", mes);
}


PVELIB_API void PVEL_checktype (PVE_State *L, int narg, int t) {
  if (PVE_type(L, narg) != t)
    tag_error(L, narg, t);
}


PVELIB_API void PVEL_checkany (PVE_State *L, int narg) {
  if (PVE_type(L, narg) == PVE_TNONE)
    PVEL_argerror(L, narg, "value expected");
}


PVELIB_API const char *PVEL_checklstring (PVE_State *L, int narg, size_t *len) {
  const char *s = PVE_tolstring(L, narg, len);
  if (!s) tag_error(L, narg, PVE_TSTRING);
  return s;
}


PVELIB_API const char *PVEL_optlstring (PVE_State *L, int narg,
                                        const char *def, size_t *len) {
  if (PVE_isnoneornil(L, narg)) {
    if (len)
      *len = (def ? strlen(def) : 0);
    return def;
  }
  else return PVEL_checklstring(L, narg, len);
}


PVELIB_API PVE_Number PVEL_checknumber (PVE_State *L, int narg) {
  PVE_Number d = PVE_tonumber(L, narg);
  if (d == 0 && !PVE_isnumber(L, narg))  /* avoid extra test when d is not 0 */
    tag_error(L, narg, PVE_TNUMBER);
  return d;
}


PVELIB_API PVE_Number PVEL_optnumber (PVE_State *L, int narg, PVE_Number def) {
  return PVEL_opt(L, PVEL_checknumber, narg, def);
}


PVELIB_API PVE_Integer PVEL_checkinteger (PVE_State *L, int narg) {
  PVE_Integer d = PVE_tointeger(L, narg);
  if (d == 0 && !PVE_isnumber(L, narg))  /* avoid extra test when d is not 0 */
    tag_error(L, narg, PVE_TNUMBER);
  return d;
}


PVELIB_API PVE_Integer PVEL_optinteger (PVE_State *L, int narg,
                                                      PVE_Integer def) {
  return PVEL_opt(L, PVEL_checkinteger, narg, def);
}


PVELIB_API int PVEL_getmetafield (PVE_State *L, int obj, const char *event) {
  if (!PVE_getmetatable(L, obj))  /* no metatable? */
    return 0;
  PVE_pushstring(L, event);
  PVE_rawget(L, -2);
  if (PVE_isnil(L, -1)) {
    PVE_pop(L, 2);  /* remove metatable and metafield */
    return 0;
  }
  else {
    PVE_remove(L, -2);  /* remove only metatable */
    return 1;
  }
}


PVELIB_API int PVEL_callmeta (PVE_State *L, int obj, const char *event) {
  obj = abs_index(L, obj);
  if (!PVEL_getmetafield(L, obj, event))  /* no metafield? */
    return 0;
  PVE_pushvalue(L, obj);
  PVE_call(L, 1, 1);
  return 1;
}


PVELIB_API void (PVEL_register) (PVE_State *L, const char *libname,
                                const PVEL_Reg *l) {
  PVEI_openlib(L, libname, l, 0);
}


static int libsize (const PVEL_Reg *l) {
  int size = 0;
  for (; l->name; l++) size++;
  return size;
}


PVELIB_API void PVEI_openlib (PVE_State *L, const char *libname,
                              const PVEL_Reg *l, int nup) {
  if (libname) {
    int size = libsize(l);
    /* check whether lib already exists */
    PVEL_findtable(L, PVE_REGISTRYINDEX, "_LOADED", size);
    PVE_getfield(L, -1, libname);  /* get _LOADED[libname] */
    if (!PVE_istable(L, -1)) {  /* not found? */
      PVE_pop(L, 1);  /* remove previous result */
      /* try global variable (and create one if it does not exist) */
      if (PVEL_findtable(L, PVE_GLOBALSINDEX, libname, size) != NULL)
        PVEL_error(L, "name conflict for module " PVE_QS, libname);
      PVE_pushvalue(L, -1);
      PVE_setfield(L, -3, libname);  /* _LOADED[libname] = new table */
    }
    PVE_remove(L, -2);  /* remove _LOADED table */
    PVE_insert(L, -(nup+1));  /* move library table to below upvalues */
  }
  for (; l->name; l++) {
    int i;
    for (i=0; i<nup; i++)  /* copy upvalues to the top */
      PVE_pushvalue(L, -nup);
    PVE_pushcclosure(L, l->func, nup);
    PVE_setfield(L, -(nup+2), l->name);
  }
  PVE_pop(L, nup);  /* remove upvalues */
}



/*
** {======================================================
** getn-setn: size for arrays
** =======================================================
*/

#if defined(PVE_COMPAT_GETN)

static int checkint (PVE_State *L, int topop) {
  int n = (PVE_type(L, -1) == PVE_TNUMBER) ? PVE_tointeger(L, -1) : -1;
  PVE_pop(L, topop);
  return n;
}


static void getsizes (PVE_State *L) {
  PVE_getfield(L, PVE_REGISTRYINDEX, "PVE_SIZES");
  if (PVE_isnil(L, -1)) {  /* no `size' table? */
    PVE_pop(L, 1);  /* remove nil */
    PVE_newtable(L);  /* create it */
    PVE_pushvalue(L, -1);  /* `size' will be its own metatable */
    PVE_setmetatable(L, -2);
    PVE_pushliteral(L, "kv");
    PVE_setfield(L, -2, "__mode");  /* metatable(N).__mode = "kv" */
    PVE_pushvalue(L, -1);
    PVE_setfield(L, PVE_REGISTRYINDEX, "PVE_SIZES");  /* store in register */
  }
}


PVELIB_API void PVEL_setn (PVE_State *L, int t, int n) {
  t = abs_index(L, t);
  PVE_pushliteral(L, "n");
  PVE_rawget(L, t);
  if (checkint(L, 1) >= 0) {  /* is there a numeric field `n'? */
    PVE_pushliteral(L, "n");  /* use it */
    PVE_pushinteger(L, n);
    PVE_rawset(L, t);
  }
  else {  /* use `sizes' */
    getsizes(L);
    PVE_pushvalue(L, t);
    PVE_pushinteger(L, n);
    PVE_rawset(L, -3);  /* sizes[t] = n */
    PVE_pop(L, 1);  /* remove `sizes' */
  }
}


PVELIB_API int PVEL_getn (PVE_State *L, int t) {
  int n;
  t = abs_index(L, t);
  PVE_pushliteral(L, "n");  /* try t.n */
  PVE_rawget(L, t);
  if ((n = checkint(L, 1)) >= 0) return n;
  getsizes(L);  /* else try sizes[t] */

⌨️ 快捷键说明

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