1 /*
2 ** $Id$
3 ** Basic library
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 #define FORBIDDEN_SYMBOL_EXCEPTION_fputs
9 #define FORBIDDEN_SYMBOL_EXCEPTION_stdout
10 
11 #include "common/util.h"
12 
13 #define lbaselib_c
14 #define LUA_LIB
15 
16 #include "lua.h"
17 
18 #include "lauxlib.h"
19 #include "lualib.h"
20 
21 
22 
23 /*
24 ** If your system does not support `stdout', you can just remove this function.
25 ** If you need, you can define your own `print' function, following this
26 ** model but changing `fputs' to put the strings at a proper place
27 ** (a console window or a log file, for instance).
28 */
luaB_print(lua_State * L)29 static int luaB_print (lua_State *L) {
30   int n = lua_gettop(L);  /* number of arguments */
31   int i;
32   lua_getglobal(L, "tostring");
33   for (i=1; i<=n; i++) {
34     const char *s;
35     lua_pushvalue(L, -1);  /* function to be called */
36     lua_pushvalue(L, i);   /* value to print */
37     lua_call(L, 1, 1);
38     s = lua_tostring(L, -1);  /* get result */
39     if (s == NULL)
40       return luaL_error(L, LUA_QL("tostring") " must return a string to "
41                            LUA_QL("print"));
42     if (i>1) fputs("\t", stdout);
43     fputs(s, stdout);
44     lua_pop(L, 1);  /* pop result */
45   }
46   fputs("\n", stdout);
47   return 0;
48 }
49 
50 
luaB_tonumber(lua_State * L)51 static int luaB_tonumber (lua_State *L) {
52   int base = luaL_optint(L, 2, 10);
53   if (base == 10) {  /* standard conversion */
54     luaL_checkany(L, 1);
55     if (lua_isnumber(L, 1)) {
56       lua_pushnumber(L, lua_tonumber(L, 1));
57       return 1;
58     }
59   }
60   else {
61     const char *s1 = luaL_checkstring(L, 1);
62     char *s2;
63     unsigned long n;
64     luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
65     n = strtoul(s1, &s2, base);
66     if (s1 != s2) {  /* at least one valid digit? */
67       while (Common::isSpace(*s2)) s2++;  /* skip trailing spaces */
68       if (*s2 == '\0') {  /* no invalid trailing characters? */
69         lua_pushnumber(L, (lua_Number)n);
70         return 1;
71       }
72     }
73   }
74   lua_pushnil(L);  /* else not a number */
75   return 1;
76 }
77 
78 
luaB_error(lua_State * L)79 static int luaB_error (lua_State *L) {
80   int level = luaL_optint(L, 2, 1);
81   lua_settop(L, 1);
82   if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */
83     luaL_where(L, level);
84     lua_pushvalue(L, 1);
85     lua_concat(L, 2);
86   }
87   return lua_error(L);
88 }
89 
90 
luaB_getmetatable(lua_State * L)91 static int luaB_getmetatable (lua_State *L) {
92   luaL_checkany(L, 1);
93   if (!lua_getmetatable(L, 1)) {
94     lua_pushnil(L);
95     return 1;  /* no metatable */
96   }
97   luaL_getmetafield(L, 1, "__metatable");
98   return 1;  /* returns either __metatable field (if present) or metatable */
99 }
100 
101 
luaB_setmetatable(lua_State * L)102 static int luaB_setmetatable (lua_State *L) {
103   int t = lua_type(L, 2);
104   luaL_checktype(L, 1, LUA_TTABLE);
105   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
106                     "nil or table expected");
107   if (luaL_getmetafield(L, 1, "__metatable"))
108     luaL_error(L, "cannot change a protected metatable");
109   lua_settop(L, 2);
110   lua_setmetatable(L, 1);
111   return 1;
112 }
113 
114 
getfunc(lua_State * L,int opt)115 static void getfunc (lua_State *L, int opt) {
116   if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
117   else {
118     lua_Debug ar;
119     int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
120     luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
121     if (lua_getstack(L, level, &ar) == 0)
122       luaL_argerror(L, 1, "invalid level");
123     lua_getinfo(L, "f", &ar);
124     if (lua_isnil(L, -1))
125       luaL_error(L, "no function environment for tail call at level %d",
126                     level);
127   }
128 }
129 
130 
luaB_getfenv(lua_State * L)131 static int luaB_getfenv (lua_State *L) {
132   getfunc(L, 1);
133   if (lua_iscfunction(L, -1))  /* is a C function? */
134     lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */
135   else
136     lua_getfenv(L, -1);
137   return 1;
138 }
139 
140 
luaB_setfenv(lua_State * L)141 static int luaB_setfenv (lua_State *L) {
142   luaL_checktype(L, 2, LUA_TTABLE);
143   getfunc(L, 0);
144   lua_pushvalue(L, 2);
145   if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
146     /* change environment of current thread */
147     lua_pushthread(L);
148     lua_insert(L, -2);
149     lua_setfenv(L, -2);
150     return 0;
151   }
152   else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
153     luaL_error(L,
154           LUA_QL("setfenv") " cannot change environment of given object");
155   return 1;
156 }
157 
158 
luaB_rawequal(lua_State * L)159 static int luaB_rawequal (lua_State *L) {
160   luaL_checkany(L, 1);
161   luaL_checkany(L, 2);
162   lua_pushboolean(L, lua_rawequal(L, 1, 2));
163   return 1;
164 }
165 
166 
luaB_rawget(lua_State * L)167 static int luaB_rawget (lua_State *L) {
168   luaL_checktype(L, 1, LUA_TTABLE);
169   luaL_checkany(L, 2);
170   lua_settop(L, 2);
171   lua_rawget(L, 1);
172   return 1;
173 }
174 
luaB_rawset(lua_State * L)175 static int luaB_rawset (lua_State *L) {
176   luaL_checktype(L, 1, LUA_TTABLE);
177   luaL_checkany(L, 2);
178   luaL_checkany(L, 3);
179   lua_settop(L, 3);
180   lua_rawset(L, 1);
181   return 1;
182 }
183 
184 
luaB_gcinfo(lua_State * L)185 static int luaB_gcinfo (lua_State *L) {
186   lua_pushinteger(L, lua_getgccount(L));
187   return 1;
188 }
189 
190 
luaB_collectgarbage(lua_State * L)191 static int luaB_collectgarbage (lua_State *L) {
192   static const char *const opts[] = {"stop", "restart", "collect",
193     "count", "step", "setpause", "setstepmul", NULL};
194   static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
195     LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
196   int o = luaL_checkoption(L, 1, "collect", opts);
197   int ex = luaL_optint(L, 2, 0);
198   int res = lua_gc(L, optsnum[o], ex);
199   switch (optsnum[o]) {
200     case LUA_GCCOUNT: {
201       int b = lua_gc(L, LUA_GCCOUNTB, 0);
202       lua_pushnumber(L, res + ((lua_Number)b/1024));
203       return 1;
204     }
205     case LUA_GCSTEP: {
206       lua_pushboolean(L, res);
207       return 1;
208     }
209     default: {
210       lua_pushnumber(L, res);
211       return 1;
212     }
213   }
214 }
215 
216 
luaB_type(lua_State * L)217 static int luaB_type (lua_State *L) {
218   luaL_checkany(L, 1);
219   lua_pushstring(L, luaL_typename(L, 1));
220   return 1;
221 }
222 
223 
luaB_next(lua_State * L)224 static int luaB_next (lua_State *L) {
225   luaL_checktype(L, 1, LUA_TTABLE);
226   lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
227   if (lua_next(L, 1))
228     return 2;
229   else {
230     lua_pushnil(L);
231     return 1;
232   }
233 }
234 
235 
luaB_pairs(lua_State * L)236 static int luaB_pairs (lua_State *L) {
237   luaL_checktype(L, 1, LUA_TTABLE);
238   lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
239   lua_pushvalue(L, 1);  /* state, */
240   lua_pushnil(L);  /* and initial value */
241   return 3;
242 }
243 
244 
ipairsaux(lua_State * L)245 static int ipairsaux (lua_State *L) {
246   int i = luaL_checkint(L, 2);
247   luaL_checktype(L, 1, LUA_TTABLE);
248   i++;  /* next value */
249   lua_pushinteger(L, i);
250   lua_rawgeti(L, 1, i);
251   return (lua_isnil(L, -1)) ? 0 : 2;
252 }
253 
254 
luaB_ipairs(lua_State * L)255 static int luaB_ipairs (lua_State *L) {
256   luaL_checktype(L, 1, LUA_TTABLE);
257   lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
258   lua_pushvalue(L, 1);  /* state, */
259   lua_pushinteger(L, 0);  /* and initial value */
260   return 3;
261 }
262 
263 
load_aux(lua_State * L,int status)264 static int load_aux (lua_State *L, int status) {
265   if (status == 0)  /* OK? */
266     return 1;
267   else {
268     lua_pushnil(L);
269     lua_insert(L, -2);  /* put before error message */
270     return 2;  /* return nil plus error message */
271   }
272 }
273 
274 
luaB_loadstring(lua_State * L)275 static int luaB_loadstring (lua_State *L) {
276   size_t l;
277   const char *s = luaL_checklstring(L, 1, &l);
278   const char *chunkname = luaL_optstring(L, 2, s);
279   return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
280 }
281 
282 
luaB_loadfile(lua_State * L)283 static int luaB_loadfile (lua_State *L) {
284   const char *fname = luaL_optstring(L, 1, NULL);
285   return load_aux(L, luaL_loadfile(L, fname));
286 }
287 
288 
289 /*
290 ** Reader for generic `load' function: `lua_load' uses the
291 ** stack for internal stuff, so the reader cannot change the
292 ** stack top. Instead, it keeps its resulting string in a
293 ** reserved slot inside the stack.
294 */
generic_reader(lua_State * L,void * ud,size_t * size)295 static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
296   (void)ud;  /* to avoid warnings */
297   luaL_checkstack(L, 2, "too many nested functions");
298   lua_pushvalue(L, 1);  /* get function */
299   lua_call(L, 0, 1);  /* call it */
300   if (lua_isnil(L, -1)) {
301     *size = 0;
302     return NULL;
303   }
304   else if (lua_isstring(L, -1)) {
305     lua_replace(L, 3);  /* save string in a reserved stack slot */
306     return lua_tolstring(L, 3, size);
307   }
308   else luaL_error(L, "reader function must return a string");
309   return NULL;  /* to avoid warnings */
310 }
311 
312 
luaB_load(lua_State * L)313 static int luaB_load (lua_State *L) {
314   int status;
315   const char *cname = luaL_optstring(L, 2, "=(load)");
316   luaL_checktype(L, 1, LUA_TFUNCTION);
317   lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */
318   status = lua_load(L, generic_reader, NULL, cname);
319   return load_aux(L, status);
320 }
321 
322 
luaB_dofile(lua_State * L)323 static int luaB_dofile (lua_State *L) {
324   const char *fname = luaL_optstring(L, 1, NULL);
325   int n = lua_gettop(L);
326   if (luaL_loadfile(L, fname) != 0) lua_error(L);
327   lua_call(L, 0, LUA_MULTRET);
328   return lua_gettop(L) - n;
329 }
330 
331 
luaB_assert(lua_State * L)332 static int luaB_assert (lua_State *L) {
333   luaL_checkany(L, 1);
334   if (!lua_toboolean(L, 1))
335     return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
336   return lua_gettop(L);
337 }
338 
339 
luaB_unpack(lua_State * L)340 static int luaB_unpack (lua_State *L) {
341   int i, e, n;
342   luaL_checktype(L, 1, LUA_TTABLE);
343   i = luaL_optint(L, 2, 1);
344   e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
345   n = e - i + 1;  /* number of elements */
346   if (n <= 0) return 0;  /* empty range */
347   luaL_checkstack(L, n, "table too big to unpack");
348   for (; i<=e; i++)  /* push arg[i...e] */
349     lua_rawgeti(L, 1, i);
350   return n;
351 }
352 
353 
luaB_select(lua_State * L)354 static int luaB_select (lua_State *L) {
355   int n = lua_gettop(L);
356   if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
357     lua_pushinteger(L, n-1);
358     return 1;
359   }
360   else {
361     int i = luaL_checkint(L, 1);
362     if (i < 0) i = n + i;
363     else if (i > n) i = n;
364     luaL_argcheck(L, 1 <= i, 1, "index out of range");
365     return n - i;
366   }
367 }
368 
369 
luaB_pcall(lua_State * L)370 static int luaB_pcall (lua_State *L) {
371   int status;
372   luaL_checkany(L, 1);
373   status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
374   lua_pushboolean(L, (status == 0));
375   lua_insert(L, 1);
376   return lua_gettop(L);  /* return status + all results */
377 }
378 
379 
luaB_xpcall(lua_State * L)380 static int luaB_xpcall (lua_State *L) {
381   int status;
382   luaL_checkany(L, 2);
383   lua_settop(L, 2);
384   lua_insert(L, 1);  /* put error function under function to be called */
385   status = lua_pcall(L, 0, LUA_MULTRET, 1);
386   lua_pushboolean(L, (status == 0));
387   lua_replace(L, 1);
388   return lua_gettop(L);  /* return status + all results */
389 }
390 
391 
luaB_tostring(lua_State * L)392 static int luaB_tostring (lua_State *L) {
393   luaL_checkany(L, 1);
394   if (luaL_callmeta(L, 1, "__tostring"))  /* is there a metafield? */
395     return 1;  /* use its value */
396   switch (lua_type(L, 1)) {
397     case LUA_TNUMBER:
398       lua_pushstring(L, lua_tostring(L, 1));
399       break;
400     case LUA_TSTRING:
401       lua_pushvalue(L, 1);
402       break;
403     case LUA_TBOOLEAN:
404       lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
405       break;
406     case LUA_TNIL:
407       lua_pushliteral(L, "nil");
408       break;
409     default:
410       lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
411       break;
412   }
413   return 1;
414 }
415 
416 
luaB_newproxy(lua_State * L)417 static int luaB_newproxy (lua_State *L) {
418   lua_settop(L, 1);
419   lua_newuserdata(L, 0);  /* create proxy */
420   if (lua_toboolean(L, 1) == 0)
421     return 1;  /* no metatable */
422   else if (lua_isboolean(L, 1)) {
423     lua_newtable(L);  /* create a new metatable `m' ... */
424     lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */
425     lua_pushboolean(L, 1);
426     lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */
427   }
428   else {
429     int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */
430     if (lua_getmetatable(L, 1)) {
431       lua_rawget(L, lua_upvalueindex(1));
432       validproxy = lua_toboolean(L, -1);
433       lua_pop(L, 1);  /* remove value */
434     }
435     luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
436     lua_getmetatable(L, 1);  /* metatable is valid; get it */
437   }
438   lua_setmetatable(L, 2);
439   return 1;
440 }
441 
442 
443 static const luaL_Reg base_funcs[] = {
444   {"assert", luaB_assert},
445   {"collectgarbage", luaB_collectgarbage},
446   {"dofile", luaB_dofile},
447   {"error", luaB_error},
448   {"gcinfo", luaB_gcinfo},
449   {"getfenv", luaB_getfenv},
450   {"getmetatable", luaB_getmetatable},
451   {"loadfile", luaB_loadfile},
452   {"load", luaB_load},
453   {"loadstring", luaB_loadstring},
454   {"next", luaB_next},
455   {"pcall", luaB_pcall},
456   {"print", luaB_print},
457   {"rawequal", luaB_rawequal},
458   {"rawget", luaB_rawget},
459   {"rawset", luaB_rawset},
460   {"select", luaB_select},
461   {"setfenv", luaB_setfenv},
462   {"setmetatable", luaB_setmetatable},
463   {"tonumber", luaB_tonumber},
464   {"tostring", luaB_tostring},
465   {"type", luaB_type},
466   {"unpack", luaB_unpack},
467   {"xpcall", luaB_xpcall},
468   {NULL, NULL}
469 };
470 
471 
472 /*
473 ** {======================================================
474 ** Coroutine library
475 ** =======================================================
476 */
477 
478 #define CO_RUN	0	/* running */
479 #define CO_SUS	1	/* suspended */
480 #define CO_NOR	2	/* 'normal' (it resumed another coroutine) */
481 #define CO_DEAD	3
482 
483 static const char *const statnames[] =
484     {"running", "suspended", "normal", "dead"};
485 
costatus(lua_State * L,lua_State * co)486 static int costatus (lua_State *L, lua_State *co) {
487   if (L == co) return CO_RUN;
488   switch (lua_status(co)) {
489     case LUA_YIELD:
490       return CO_SUS;
491     case 0: {
492       lua_Debug ar;
493       if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
494         return CO_NOR;  /* it is running */
495       else if (lua_gettop(co) == 0)
496           return CO_DEAD;
497       else
498         return CO_SUS;  /* initial state */
499     }
500     default:  /* some error occurred */
501       return CO_DEAD;
502   }
503 }
504 
505 
luaB_costatus(lua_State * L)506 static int luaB_costatus (lua_State *L) {
507   lua_State *co = lua_tothread(L, 1);
508   luaL_argcheck(L, co, 1, "coroutine expected");
509   lua_pushstring(L, statnames[costatus(L, co)]);
510   return 1;
511 }
512 
513 
auxresume(lua_State * L,lua_State * co,int narg)514 static int auxresume (lua_State *L, lua_State *co, int narg) {
515   int status = costatus(L, co);
516   if (!lua_checkstack(co, narg))
517     luaL_error(L, "too many arguments to resume");
518   if (status != CO_SUS) {
519     lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
520     return -1;  /* error flag */
521   }
522   lua_xmove(L, co, narg);
523   lua_setlevel(L, co);
524   status = lua_resume(co, narg);
525   if (status == 0 || status == LUA_YIELD) {
526     int nres = lua_gettop(co);
527     if (!lua_checkstack(L, nres))
528       luaL_error(L, "too many results to resume");
529     lua_xmove(co, L, nres);  /* move yielded values */
530     return nres;
531   }
532   else {
533     lua_xmove(co, L, 1);  /* move error message */
534     return -1;  /* error flag */
535   }
536 }
537 
538 
luaB_coresume(lua_State * L)539 static int luaB_coresume (lua_State *L) {
540   lua_State *co = lua_tothread(L, 1);
541   int r;
542   luaL_argcheck(L, co, 1, "coroutine expected");
543   r = auxresume(L, co, lua_gettop(L) - 1);
544   if (r < 0) {
545     lua_pushboolean(L, 0);
546     lua_insert(L, -2);
547     return 2;  /* return false + error message */
548   }
549   else {
550     lua_pushboolean(L, 1);
551     lua_insert(L, -(r + 1));
552     return r + 1;  /* return true + `resume' returns */
553   }
554 }
555 
556 
luaB_auxwrap(lua_State * L)557 static int luaB_auxwrap (lua_State *L) {
558   lua_State *co = lua_tothread(L, lua_upvalueindex(1));
559   int r = auxresume(L, co, lua_gettop(L));
560   if (r < 0) {
561     if (lua_isstring(L, -1)) {  /* error object is a string? */
562       luaL_where(L, 1);  /* add extra info */
563       lua_insert(L, -2);
564       lua_concat(L, 2);
565     }
566     lua_error(L);  /* propagate error */
567   }
568   return r;
569 }
570 
571 
luaB_cocreate(lua_State * L)572 static int luaB_cocreate (lua_State *L) {
573   lua_State *NL = lua_newthread(L);
574   luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
575     "Lua function expected");
576   lua_pushvalue(L, 1);  /* move function to top */
577   lua_xmove(L, NL, 1);  /* move function from L to NL */
578   return 1;
579 }
580 
581 
luaB_cowrap(lua_State * L)582 static int luaB_cowrap (lua_State *L) {
583   luaB_cocreate(L);
584   lua_pushcclosure(L, luaB_auxwrap, 1);
585   return 1;
586 }
587 
588 
luaB_yield(lua_State * L)589 static int luaB_yield (lua_State *L) {
590   return lua_yield(L, lua_gettop(L));
591 }
592 
593 
luaB_corunning(lua_State * L)594 static int luaB_corunning (lua_State *L) {
595   if (lua_pushthread(L))
596     lua_pushnil(L);  /* main thread is not a coroutine */
597   return 1;
598 }
599 
600 
601 static const luaL_Reg co_funcs[] = {
602   {"create", luaB_cocreate},
603   {"resume", luaB_coresume},
604   {"running", luaB_corunning},
605   {"status", luaB_costatus},
606   {"wrap", luaB_cowrap},
607   {"yield", luaB_yield},
608   {NULL, NULL}
609 };
610 
611 /* }====================================================== */
612 
613 
auxopen(lua_State * L,const char * name,lua_CFunction f,lua_CFunction u)614 static void auxopen (lua_State *L, const char *name,
615                      lua_CFunction f, lua_CFunction u) {
616   lua_pushcfunction(L, u);
617   /* BS25 ==== */
618   lua_pushstring(L, name);
619   lua_pushstring(L, "_next");
620   lua_concat(L, 2);
621   lua_pushvalue(L, -2);
622   lua_settable(L, LUA_GLOBALSINDEX);
623   /* ==== BS25 */
624   lua_pushcclosure(L, f, 1);
625   lua_setfield(L, -2, name);
626 }
627 
628 
base_open(lua_State * L)629 static void base_open (lua_State *L) {
630   /* set global _G */
631   lua_pushvalue(L, LUA_GLOBALSINDEX);
632   lua_setglobal(L, "_G");
633   /* open lib into global table */
634   luaL_register(L, "_G", base_funcs);
635   lua_pushliteral(L, LUA_VERSION);
636   lua_setglobal(L, "_VERSION");  /* set global _VERSION */
637   /* `ipairs' and `pairs' need auxliliary functions as upvalues */
638   auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
639   auxopen(L, "pairs", luaB_pairs, luaB_next);
640   /* `newproxy' needs a weaktable as upvalue */
641   lua_createtable(L, 0, 1);  /* new table `w' */
642   lua_pushvalue(L, -1);  /* `w' will be its own metatable */
643   lua_setmetatable(L, -2);
644   lua_pushliteral(L, "kv");
645   lua_setfield(L, -2, "__mode");  /* metatable(w).__mode = "kv" */
646   lua_pushcclosure(L, luaB_newproxy, 1);
647   lua_setglobal(L, "newproxy");  /* set global `newproxy' */
648 }
649 
650 
luaopen_base(lua_State * L)651 LUALIB_API int luaopen_base (lua_State *L) {
652   base_open(L);
653   luaL_register(L, LUA_COLIBNAME, co_funcs);
654   return 2;
655 }
656