root/lj_lib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lib_create_table
  2. lj_lib_register
  3. lj_lib_checkany
  4. lj_lib_checkstr
  5. lj_lib_optstr
  6. lj_lib_checknumber
  7. lj_lib_checknum
  8. lj_lib_checkint
  9. lj_lib_optint
  10. lj_lib_checkbit
  11. lj_lib_checkfunc
  12. lj_lib_checktab
  13. lj_lib_checktabornil
  14. lj_lib_checkopt

   1 /*
   2 ** Library function support.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 */
   5 
   6 #define lj_lib_c
   7 #define LUA_CORE
   8 
   9 #include "lauxlib.h"
  10 
  11 #include "lj_obj.h"
  12 #include "lj_gc.h"
  13 #include "lj_err.h"
  14 #include "lj_str.h"
  15 #include "lj_tab.h"
  16 #include "lj_func.h"
  17 #include "lj_bc.h"
  18 #include "lj_dispatch.h"
  19 #include "lj_vm.h"
  20 #include "lj_strscan.h"
  21 #include "lj_lib.h"
  22 
  23 /* -- Library initialization ---------------------------------------------- */
  24 
  25 static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize)
  26 {
  27   if (libname) {
  28     luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
  29     lua_getfield(L, -1, libname);
  30     if (!tvistab(L->top-1)) {
  31       L->top--;
  32       if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, hsize) != NULL)
  33         lj_err_callerv(L, LJ_ERR_BADMODN, libname);
  34       settabV(L, L->top, tabV(L->top-1));
  35       L->top++;
  36       lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */
  37     }
  38     L->top--;
  39     settabV(L, L->top-1, tabV(L->top));
  40   } else {
  41     lua_createtable(L, 0, hsize);
  42   }
  43   return tabV(L->top-1);
  44 }
  45 
  46 void lj_lib_register(lua_State *L, const char *libname,
  47                      const uint8_t *p, const lua_CFunction *cf)
  48 {
  49   GCtab *env = tabref(L->env);
  50   GCfunc *ofn = NULL;
  51   int ffid = *p++;
  52   BCIns *bcff = &L2GG(L)->bcff[*p++];
  53   GCtab *tab = lib_create_table(L, libname, *p++);
  54   ptrdiff_t tpos = L->top - L->base;
  55 
  56   /* Avoid barriers further down. */
  57   lj_gc_anybarriert(L, tab);
  58   tab->nomm = 0;
  59 
  60   for (;;) {
  61     uint32_t tag = *p++;
  62     MSize len = tag & LIBINIT_LENMASK;
  63     tag &= LIBINIT_TAGMASK;
  64     if (tag != LIBINIT_STRING) {
  65       const char *name;
  66       MSize nuv = (MSize)(L->top - L->base - tpos);
  67       GCfunc *fn = lj_func_newC(L, nuv, env);
  68       if (nuv) {
  69         L->top = L->base + tpos;
  70         memcpy(fn->c.upvalue, L->top, sizeof(TValue)*nuv);
  71       }
  72       fn->c.ffid = (uint8_t)(ffid++);
  73       name = (const char *)p;
  74       p += len;
  75       if (tag == LIBINIT_CF)
  76         setmref(fn->c.pc, &G(L)->bc_cfunc_int);
  77       else
  78         setmref(fn->c.pc, bcff++);
  79       if (tag == LIBINIT_ASM_)
  80         fn->c.f = ofn->c.f;  /* Copy handler from previous function. */
  81       else
  82         fn->c.f = *cf++;  /* Get cf or handler from C function table. */
  83       if (len) {
  84         /* NOBARRIER: See above for common barrier. */
  85         setfuncV(L, lj_tab_setstr(L, tab, lj_str_new(L, name, len)), fn);
  86       }
  87       ofn = fn;
  88     } else {
  89       switch (tag | len) {
  90       case LIBINIT_SET:
  91         L->top -= 2;
  92         if (tvisstr(L->top+1) && strV(L->top+1)->len == 0)
  93           env = tabV(L->top);
  94         else  /* NOBARRIER: See above for common barrier. */
  95           copyTV(L, lj_tab_set(L, tab, L->top+1), L->top);
  96         break;
  97       case LIBINIT_NUMBER:
  98         memcpy(&L->top->n, p, sizeof(double));
  99         L->top++;
 100         p += sizeof(double);
 101         break;
 102       case LIBINIT_COPY:
 103         copyTV(L, L->top, L->top - *p++);
 104         L->top++;
 105         break;
 106       case LIBINIT_LASTCL:
 107         setfuncV(L, L->top++, ofn);
 108         break;
 109       case LIBINIT_FFID:
 110         ffid++;
 111         break;
 112       case LIBINIT_END:
 113         return;
 114       default:
 115         setstrV(L, L->top++, lj_str_new(L, (const char *)p, len));
 116         p += len;
 117         break;
 118       }
 119     }
 120   }
 121 }
 122 
 123 /* -- Type checks --------------------------------------------------------- */
 124 
 125 TValue *lj_lib_checkany(lua_State *L, int narg)
 126 {
 127   TValue *o = L->base + narg-1;
 128   if (o >= L->top)
 129     lj_err_arg(L, narg, LJ_ERR_NOVAL);
 130   return o;
 131 }
 132 
 133 GCstr *lj_lib_checkstr(lua_State *L, int narg)
 134 {
 135   TValue *o = L->base + narg-1;
 136   if (o < L->top) {
 137     if (LJ_LIKELY(tvisstr(o))) {
 138       return strV(o);
 139     } else if (tvisnumber(o)) {
 140       GCstr *s = lj_str_fromnumber(L, o);
 141       setstrV(L, o, s);
 142       return s;
 143     }
 144   }
 145   lj_err_argt(L, narg, LUA_TSTRING);
 146   return NULL;  /* unreachable */
 147 }
 148 
 149 GCstr *lj_lib_optstr(lua_State *L, int narg)
 150 {
 151   TValue *o = L->base + narg-1;
 152   return (o < L->top && !tvisnil(o)) ? lj_lib_checkstr(L, narg) : NULL;
 153 }
 154 
 155 #if LJ_DUALNUM
 156 void lj_lib_checknumber(lua_State *L, int narg)
 157 {
 158   TValue *o = L->base + narg-1;
 159   if (!(o < L->top && lj_strscan_numberobj(o)))
 160     lj_err_argt(L, narg, LUA_TNUMBER);
 161 }
 162 #endif
 163 
 164 lua_Number lj_lib_checknum(lua_State *L, int narg)
 165 {
 166   TValue *o = L->base + narg-1;
 167   if (!(o < L->top &&
 168         (tvisnumber(o) || (tvisstr(o) && lj_strscan_num(strV(o), o)))))
 169     lj_err_argt(L, narg, LUA_TNUMBER);
 170   if (LJ_UNLIKELY(tvisint(o))) {
 171     lua_Number n = (lua_Number)intV(o);
 172     setnumV(o, n);
 173     return n;
 174   } else {
 175     return numV(o);
 176   }
 177 }
 178 
 179 int32_t lj_lib_checkint(lua_State *L, int narg)
 180 {
 181   TValue *o = L->base + narg-1;
 182   if (!(o < L->top && lj_strscan_numberobj(o)))
 183     lj_err_argt(L, narg, LUA_TNUMBER);
 184   if (LJ_LIKELY(tvisint(o))) {
 185     return intV(o);
 186   } else {
 187     int32_t i = lj_num2int(numV(o));
 188     if (LJ_DUALNUM) setintV(o, i);
 189     return i;
 190   }
 191 }
 192 
 193 int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)
 194 {
 195   TValue *o = L->base + narg-1;
 196   return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def;
 197 }
 198 
 199 int32_t lj_lib_checkbit(lua_State *L, int narg)
 200 {
 201   TValue *o = L->base + narg-1;
 202   if (!(o < L->top && lj_strscan_numberobj(o)))
 203     lj_err_argt(L, narg, LUA_TNUMBER);
 204   if (LJ_LIKELY(tvisint(o))) {
 205     return intV(o);
 206   } else {
 207     int32_t i = lj_num2bit(numV(o));
 208     if (LJ_DUALNUM) setintV(o, i);
 209     return i;
 210   }
 211 }
 212 
 213 GCfunc *lj_lib_checkfunc(lua_State *L, int narg)
 214 {
 215   TValue *o = L->base + narg-1;
 216   if (!(o < L->top && tvisfunc(o)))
 217     lj_err_argt(L, narg, LUA_TFUNCTION);
 218   return funcV(o);
 219 }
 220 
 221 GCtab *lj_lib_checktab(lua_State *L, int narg)
 222 {
 223   TValue *o = L->base + narg-1;
 224   if (!(o < L->top && tvistab(o)))
 225     lj_err_argt(L, narg, LUA_TTABLE);
 226   return tabV(o);
 227 }
 228 
 229 GCtab *lj_lib_checktabornil(lua_State *L, int narg)
 230 {
 231   TValue *o = L->base + narg-1;
 232   if (o < L->top) {
 233     if (tvistab(o))
 234       return tabV(o);
 235     else if (tvisnil(o))
 236       return NULL;
 237   }
 238   lj_err_arg(L, narg, LJ_ERR_NOTABN);
 239   return NULL;  /* unreachable */
 240 }
 241 
 242 int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst)
 243 {
 244   GCstr *s = def >= 0 ? lj_lib_optstr(L, narg) : lj_lib_checkstr(L, narg);
 245   if (s) {
 246     const char *opt = strdata(s);
 247     MSize len = s->len;
 248     int i;
 249     for (i = 0; *(const uint8_t *)lst; i++) {
 250       if (*(const uint8_t *)lst == len && memcmp(opt, lst+1, len) == 0)
 251         return i;
 252       lst += 1+*(const uint8_t *)lst;
 253     }
 254     lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt);
 255   }
 256   return def;
 257 }
 258 

/* [<][>][^][v][top][bottom][index][help] */