ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lj_lib.c (7627B)


      1 /*
      2 ** Library function support.
      3 ** Copyright (C) 2005-2016 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_strfmt.h"
     22 #include "lj_lex.h"
     23 #include "lj_bcdump.h"
     24 #include "lj_lib.h"
     25 
     26 /* -- Library initialization ---------------------------------------------- */
     27 
     28 static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize)
     29 {
     30   if (libname) {
     31     luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
     32     lua_getfield(L, -1, libname);
     33     if (!tvistab(L->top-1)) {
     34       L->top--;
     35       if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, hsize) != NULL)
     36 	lj_err_callerv(L, LJ_ERR_BADMODN, libname);
     37       settabV(L, L->top, tabV(L->top-1));
     38       L->top++;
     39       lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */
     40     }
     41     L->top--;
     42     settabV(L, L->top-1, tabV(L->top));
     43   } else {
     44     lua_createtable(L, 0, hsize);
     45   }
     46   return tabV(L->top-1);
     47 }
     48 
     49 static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab)
     50 {
     51   int len = *p++;
     52   GCstr *name = lj_str_new(L, (const char *)p, len);
     53   LexState ls;
     54   GCproto *pt;
     55   GCfunc *fn;
     56   memset(&ls, 0, sizeof(ls));
     57   ls.L = L;
     58   ls.p = (const char *)(p+len);
     59   ls.pe = (const char *)~(uintptr_t)0;
     60   ls.c = -1;
     61   ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE));
     62   ls.chunkname = name;
     63   pt = lj_bcread_proto(&ls);
     64   pt->firstline = ~(BCLine)0;
     65   fn = lj_func_newL_empty(L, pt, tabref(L->env));
     66   /* NOBARRIER: See below for common barrier. */
     67   setfuncV(L, lj_tab_setstr(L, tab, name), fn);
     68   return (const uint8_t *)ls.p;
     69 }
     70 
     71 void lj_lib_register(lua_State *L, const char *libname,
     72 		     const uint8_t *p, const lua_CFunction *cf)
     73 {
     74   GCtab *env = tabref(L->env);
     75   GCfunc *ofn = NULL;
     76   int ffid = *p++;
     77   BCIns *bcff = &L2GG(L)->bcff[*p++];
     78   GCtab *tab = lib_create_table(L, libname, *p++);
     79   ptrdiff_t tpos = L->top - L->base;
     80 
     81   /* Avoid barriers further down. */
     82   lj_gc_anybarriert(L, tab);
     83   tab->nomm = 0;
     84 
     85   for (;;) {
     86     uint32_t tag = *p++;
     87     MSize len = tag & LIBINIT_LENMASK;
     88     tag &= LIBINIT_TAGMASK;
     89     if (tag != LIBINIT_STRING) {
     90       const char *name;
     91       MSize nuv = (MSize)(L->top - L->base - tpos);
     92       GCfunc *fn = lj_func_newC(L, nuv, env);
     93       if (nuv) {
     94 	L->top = L->base + tpos;
     95 	memcpy(fn->c.upvalue, L->top, sizeof(TValue)*nuv);
     96       }
     97       fn->c.ffid = (uint8_t)(ffid++);
     98       name = (const char *)p;
     99       p += len;
    100       if (tag == LIBINIT_CF)
    101 	setmref(fn->c.pc, &G(L)->bc_cfunc_int);
    102       else
    103 	setmref(fn->c.pc, bcff++);
    104       if (tag == LIBINIT_ASM_)
    105 	fn->c.f = ofn->c.f;  /* Copy handler from previous function. */
    106       else
    107 	fn->c.f = *cf++;  /* Get cf or handler from C function table. */
    108       if (len) {
    109 	/* NOBARRIER: See above for common barrier. */
    110 	setfuncV(L, lj_tab_setstr(L, tab, lj_str_new(L, name, len)), fn);
    111       }
    112       ofn = fn;
    113     } else {
    114       switch (tag | len) {
    115       case LIBINIT_LUA:
    116 	p = lib_read_lfunc(L, p, tab);
    117 	break;
    118       case LIBINIT_SET:
    119 	L->top -= 2;
    120 	if (tvisstr(L->top+1) && strV(L->top+1)->len == 0)
    121 	  env = tabV(L->top);
    122 	else  /* NOBARRIER: See above for common barrier. */
    123 	  copyTV(L, lj_tab_set(L, tab, L->top+1), L->top);
    124 	break;
    125       case LIBINIT_NUMBER:
    126 	memcpy(&L->top->n, p, sizeof(double));
    127 	L->top++;
    128 	p += sizeof(double);
    129 	break;
    130       case LIBINIT_COPY:
    131 	copyTV(L, L->top, L->top - *p++);
    132 	L->top++;
    133 	break;
    134       case LIBINIT_LASTCL:
    135 	setfuncV(L, L->top++, ofn);
    136 	break;
    137       case LIBINIT_FFID:
    138 	ffid++;
    139 	break;
    140       case LIBINIT_END:
    141 	return;
    142       default:
    143 	setstrV(L, L->top++, lj_str_new(L, (const char *)p, len));
    144 	p += len;
    145 	break;
    146       }
    147     }
    148   }
    149 }
    150 
    151 /* Push internal function on the stack. */
    152 GCfunc *lj_lib_pushcc(lua_State *L, lua_CFunction f, int id, int n)
    153 {
    154   GCfunc *fn;
    155   lua_pushcclosure(L, f, n);
    156   fn = funcV(L->top-1);
    157   fn->c.ffid = (uint8_t)id;
    158   setmref(fn->c.pc, &G(L)->bc_cfunc_int);
    159   return fn;
    160 }
    161 
    162 void lj_lib_prereg(lua_State *L, const char *name, lua_CFunction f, GCtab *env)
    163 {
    164   luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD", 4);
    165   lua_pushcfunction(L, f);
    166   /* NOBARRIER: The function is new (marked white). */
    167   setgcref(funcV(L->top-1)->c.env, obj2gco(env));
    168   lua_setfield(L, -2, name);
    169   L->top--;
    170 }
    171 
    172 int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, const char *name)
    173 {
    174   GCfunc *fn = lj_lib_pushcf(L, cf, id);
    175   GCtab *t = tabref(curr_func(L)->c.env);  /* Reference to parent table. */
    176   setfuncV(L, lj_tab_setstr(L, t, lj_str_newz(L, name)), fn);
    177   lj_gc_anybarriert(L, t);
    178   setfuncV(L, L->top++, fn);
    179   return 1;
    180 }
    181 
    182 /* -- Type checks --------------------------------------------------------- */
    183 
    184 TValue *lj_lib_checkany(lua_State *L, int narg)
    185 {
    186   TValue *o = L->base + narg-1;
    187   if (o >= L->top)
    188     lj_err_arg(L, narg, LJ_ERR_NOVAL);
    189   return o;
    190 }
    191 
    192 GCstr *lj_lib_checkstr(lua_State *L, int narg)
    193 {
    194   TValue *o = L->base + narg-1;
    195   if (o < L->top) {
    196     if (LJ_LIKELY(tvisstr(o))) {
    197       return strV(o);
    198     } else if (tvisnumber(o)) {
    199       GCstr *s = lj_strfmt_number(L, o);
    200       setstrV(L, o, s);
    201       return s;
    202     }
    203   }
    204   lj_err_argt(L, narg, LUA_TSTRING);
    205   return NULL;  /* unreachable */
    206 }
    207 
    208 GCstr *lj_lib_optstr(lua_State *L, int narg)
    209 {
    210   TValue *o = L->base + narg-1;
    211   return (o < L->top && !tvisnil(o)) ? lj_lib_checkstr(L, narg) : NULL;
    212 }
    213 
    214 #if LJ_DUALNUM
    215 void lj_lib_checknumber(lua_State *L, int narg)
    216 {
    217   TValue *o = L->base + narg-1;
    218   if (!(o < L->top && lj_strscan_numberobj(o)))
    219     lj_err_argt(L, narg, LUA_TNUMBER);
    220 }
    221 #endif
    222 
    223 lua_Number lj_lib_checknum(lua_State *L, int narg)
    224 {
    225   TValue *o = L->base + narg-1;
    226   if (!(o < L->top &&
    227 	(tvisnumber(o) || (tvisstr(o) && lj_strscan_num(strV(o), o)))))
    228     lj_err_argt(L, narg, LUA_TNUMBER);
    229   if (LJ_UNLIKELY(tvisint(o))) {
    230     lua_Number n = (lua_Number)intV(o);
    231     setnumV(o, n);
    232     return n;
    233   } else {
    234     return numV(o);
    235   }
    236 }
    237 
    238 int32_t lj_lib_checkint(lua_State *L, int narg)
    239 {
    240   TValue *o = L->base + narg-1;
    241   if (!(o < L->top && lj_strscan_numberobj(o)))
    242     lj_err_argt(L, narg, LUA_TNUMBER);
    243   if (LJ_LIKELY(tvisint(o))) {
    244     return intV(o);
    245   } else {
    246     int32_t i = lj_num2int(numV(o));
    247     if (LJ_DUALNUM) setintV(o, i);
    248     return i;
    249   }
    250 }
    251 
    252 int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)
    253 {
    254   TValue *o = L->base + narg-1;
    255   return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def;
    256 }
    257 
    258 GCfunc *lj_lib_checkfunc(lua_State *L, int narg)
    259 {
    260   TValue *o = L->base + narg-1;
    261   if (!(o < L->top && tvisfunc(o)))
    262     lj_err_argt(L, narg, LUA_TFUNCTION);
    263   return funcV(o);
    264 }
    265 
    266 GCtab *lj_lib_checktab(lua_State *L, int narg)
    267 {
    268   TValue *o = L->base + narg-1;
    269   if (!(o < L->top && tvistab(o)))
    270     lj_err_argt(L, narg, LUA_TTABLE);
    271   return tabV(o);
    272 }
    273 
    274 GCtab *lj_lib_checktabornil(lua_State *L, int narg)
    275 {
    276   TValue *o = L->base + narg-1;
    277   if (o < L->top) {
    278     if (tvistab(o))
    279       return tabV(o);
    280     else if (tvisnil(o))
    281       return NULL;
    282   }
    283   lj_err_arg(L, narg, LJ_ERR_NOTABN);
    284   return NULL;  /* unreachable */
    285 }
    286 
    287 int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst)
    288 {
    289   GCstr *s = def >= 0 ? lj_lib_optstr(L, narg) : lj_lib_checkstr(L, narg);
    290   if (s) {
    291     const char *opt = strdata(s);
    292     MSize len = s->len;
    293     int i;
    294     for (i = 0; *(const uint8_t *)lst; i++) {
    295       if (*(const uint8_t *)lst == len && memcmp(opt, lst+1, len) == 0)
    296 	return i;
    297       lst += 1+*(const uint8_t *)lst;
    298     }
    299     lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt);
    300   }
    301   return def;
    302 }
    303