1 /*
2 ** $Id: lbaselib.c,v 1.2 2002/07/12 07:49:04 jcatki Exp $
3 ** Basic library
4 ** See Copyright Notice in lua.h
5 */
6 
7 
8 
9 #include <ctype.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "lua.h"
15 
16 #include "lauxlib.h"
17 #include "luadebug.h"
18 #include "lualib.h"
19 
20 
21 
22 /*
23 ** If your system does not support `stderr', redefine this function, or
24 ** redefine _ERRORMESSAGE so that it won't need _ALERT.
25 */
luaB__ALERT(lua_State * L)26 static int luaB__ALERT (lua_State *L) {
27   fputs(luaL_check_string(L, 1), stderr);
28   return 0;
29 }
30 
31 
32 /*
33 ** Basic implementation of _ERRORMESSAGE.
34 ** The library `liolib' redefines _ERRORMESSAGE for better error information.
35 */
luaB__ERRORMESSAGE(lua_State * L)36 static int luaB__ERRORMESSAGE (lua_State *L) {
37   luaL_checktype(L, 1, LUA_TSTRING);
38   lua_getglobal(L, LUA_ALERT);
39   if (lua_isfunction(L, -1)) {  /* avoid error loop if _ALERT is not defined */
40     lua_Debug ar;
41     lua_pushstring(L, "error: ");
42     lua_pushvalue(L, 1);
43     if (lua_getstack(L, 1, &ar)) {
44       lua_getinfo(L, "Sl", &ar);
45       if (ar.source && ar.currentline > 0) {
46         char buff[100];
47         sprintf(buff, "\n  <%.70s: line %d>", ar.short_src, ar.currentline);
48         lua_pushstring(L, buff);
49         lua_concat(L, 2);
50       }
51     }
52     lua_pushstring(L, "\n");
53     lua_concat(L, 3);
54     lua_rawcall(L, 1, 0);
55   }
56   return 0;
57 }
58 
59 
60 /*
61 ** If your system does not support `stdout', you can just remove this function.
62 ** If you need, you can define your own `print' function, following this
63 ** model but changing `fputs' to put the strings at a proper place
64 ** (a console window or a log file, for instance).
65 */
luaB_print(lua_State * L)66 static int luaB_print (lua_State *L) {
67   int n = lua_gettop(L);  /* number of arguments */
68   int i;
69   lua_getglobal(L, "tostring");
70   for (i=1; i<=n; i++) {
71     const char *s;
72     lua_pushvalue(L, -1);  /* function to be called */
73     lua_pushvalue(L, i);   /* value to print */
74     lua_rawcall(L, 1, 1);
75     s = lua_tostring(L, -1);  /* get result */
76     if (s == NULL)
77       lua_error(L, "`tostring' must return a string to `print'");
78     if (i>1) fputs("\t", stdout);
79     fputs(s, stdout);
80     lua_pop(L, 1);  /* pop result */
81   }
82   fputs("\n", stdout);
83   return 0;
84 }
85 
86 
luaB_tonumber(lua_State * L)87 static int luaB_tonumber (lua_State *L) {
88   int base = luaL_opt_int(L, 2, 10);
89   if (base == 10) {  /* standard conversion */
90     luaL_checkany(L, 1);
91     if (lua_isnumber(L, 1)) {
92       lua_pushnumber(L, lua_tonumber(L, 1));
93       return 1;
94     }
95   }
96   else {
97     const char *s1 = luaL_check_string(L, 1);
98     char *s2;
99     unsigned long n;
100     luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range");
101     n = strtoul(s1, &s2, base);
102     if (s1 != s2) {  /* at least one valid digit? */
103       while (isspace((unsigned char)*s2)) s2++;  /* skip trailing spaces */
104       if (*s2 == '\0') {  /* no invalid trailing characters? */
105         lua_pushnumber(L, n);
106         return 1;
107       }
108     }
109   }
110   lua_pushnil(L);  /* else not a number */
111   return 1;
112 }
113 
114 
luaB_error(lua_State * L)115 static int luaB_error (lua_State *L) {
116   lua_error(L, luaL_opt_string(L, 1, NULL));
117   return 0;  /* to avoid warnings */
118 }
119 
luaB_setglobal(lua_State * L)120 static int luaB_setglobal (lua_State *L) {
121   luaL_checkany(L, 2);
122   lua_setglobal(L, luaL_check_string(L, 1));
123   return 0;
124 }
125 
luaB_getglobal(lua_State * L)126 static int luaB_getglobal (lua_State *L) {
127   lua_getglobal(L, luaL_check_string(L, 1));
128   return 1;
129 }
130 
luaB_tag(lua_State * L)131 static int luaB_tag (lua_State *L) {
132   luaL_checkany(L, 1);
133   lua_pushnumber(L, lua_tag(L, 1));
134   return 1;
135 }
136 
luaB_settag(lua_State * L)137 static int luaB_settag (lua_State *L) {
138   luaL_checktype(L, 1, LUA_TTABLE);
139   lua_pushvalue(L, 1);  /* push table */
140   lua_settag(L, luaL_check_int(L, 2));
141   return 1;  /* return table */
142 }
143 
luaB_newtag(lua_State * L)144 static int luaB_newtag (lua_State *L) {
145   lua_pushnumber(L, lua_newtag(L));
146   return 1;
147 }
148 
luaB_copytagmethods(lua_State * L)149 static int luaB_copytagmethods (lua_State *L) {
150   lua_pushnumber(L, lua_copytagmethods(L, luaL_check_int(L, 1),
151                                           luaL_check_int(L, 2)));
152   return 1;
153 }
154 
luaB_globals(lua_State * L)155 static int luaB_globals (lua_State *L) {
156   lua_getglobals(L);  /* value to be returned */
157   if (!lua_isnull(L, 1)) {
158     luaL_checktype(L, 1, LUA_TTABLE);
159     lua_pushvalue(L, 1);  /* new table of globals */
160     lua_setglobals(L);
161   }
162   return 1;
163 }
164 
luaB_rawget(lua_State * L)165 static int luaB_rawget (lua_State *L) {
166   luaL_checktype(L, 1, LUA_TTABLE);
167   luaL_checkany(L, 2);
168   lua_rawget(L, 1);
169   return 1;
170 }
171 
luaB_rawset(lua_State * L)172 static int luaB_rawset (lua_State *L) {
173   luaL_checktype(L, 1, LUA_TTABLE);
174   luaL_checkany(L, 2);
175   luaL_checkany(L, 3);
176   lua_rawset(L, 1);
177   return 1;
178 }
179 
luaB_settagmethod(lua_State * L)180 static int luaB_settagmethod (lua_State *L) {
181   int tag = luaL_check_int(L, 1);
182   const char *event = luaL_check_string(L, 2);
183   luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3,
184                  "function or nil expected");
185   if (strcmp(event, "gc") == 0)
186     lua_error(L, "deprecated use: cannot set the `gc' tag method from Lua");
187   lua_gettagmethod(L, tag, event);
188   lua_pushvalue(L, 3);
189   lua_settagmethod(L, tag, event);
190   return 1;
191 }
192 
193 
luaB_gettagmethod(lua_State * L)194 static int luaB_gettagmethod (lua_State *L) {
195   int tag = luaL_check_int(L, 1);
196   const char *event = luaL_check_string(L, 2);
197   if (strcmp(event, "gc") == 0)
198     lua_error(L, "deprecated use: cannot get the `gc' tag method from Lua");
199   lua_gettagmethod(L, tag, event);
200   return 1;
201 }
202 
203 
luaB_gcinfo(lua_State * L)204 static int luaB_gcinfo (lua_State *L) {
205   lua_pushnumber(L, lua_getgccount(L));
206   lua_pushnumber(L, lua_getgcthreshold(L));
207   return 2;
208 }
209 
210 
luaB_collectgarbage(lua_State * L)211 static int luaB_collectgarbage (lua_State *L) {
212   lua_setgcthreshold(L, luaL_opt_int(L, 1, 0));
213   return 0;
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, lua_typename(L, lua_type(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 
passresults(lua_State * L,int status,int oldtop)236 static int passresults (lua_State *L, int status, int oldtop) {
237   static const char *const errornames[] =
238     {"ok", "run-time error", "file error", "syntax error",
239      "memory error", "error in error handling"};
240   if (status == 0) {
241     int nresults = lua_gettop(L) - oldtop;
242     if (nresults > 0)
243       return nresults;  /* results are already on the stack */
244     else {
245       lua_pushuserdata(L, NULL);  /* at least one result to signal no errors */
246       return 1;
247     }
248   }
249   else {  /* error */
250     lua_pushnil(L);
251     lua_pushstring(L, errornames[status]);  /* error code */
252     return 2;
253   }
254 }
255 
luaB_dostring(lua_State * L)256 static int luaB_dostring (lua_State *L) {
257   int oldtop = lua_gettop(L);
258   size_t l;
259   const char *s = luaL_check_lstr(L, 1, &l);
260   if (*s == '\33')  /* binary files start with ESC... */
261     lua_error(L, "`dostring' cannot run pre-compiled code");
262   return passresults(L, lua_dobuffer(L, s, l, luaL_opt_string(L, 2, s)), oldtop);
263 }
264 
265 
luaB_dofile(lua_State * L)266 static int luaB_dofile (lua_State *L) {
267   int oldtop = lua_gettop(L);
268   const char *fname = luaL_opt_string(L, 1, NULL);
269   return passresults(L, lua_dofile(L, fname), oldtop);
270 }
271 
272 
luaB_call(lua_State * L)273 static int luaB_call (lua_State *L) {
274   int oldtop;
275   const char *options = luaL_opt_string(L, 3, "");
276   int err = 0;  /* index of old error method */
277   int i, status;
278   int n;
279   luaL_checktype(L, 2, LUA_TTABLE);
280   n = lua_getn(L, 2);
281   if (!lua_isnull(L, 4)) {  /* set new error method */
282     lua_getglobal(L, LUA_ERRORMESSAGE);
283     err = lua_gettop(L);  /* get index */
284     lua_pushvalue(L, 4);
285     lua_setglobal(L, LUA_ERRORMESSAGE);
286   }
287   oldtop = lua_gettop(L);  /* top before function-call preparation */
288   /* push function */
289   lua_pushvalue(L, 1);
290   luaL_checkstack(L, n, "too many arguments");
291   for (i=0; i<n; i++)  /* push arg[1...n] */
292     lua_rawgeti(L, 2, i+1);
293   status = lua_call(L, n, LUA_MULTRET);
294   if (err != 0) {  /* restore old error method */
295     lua_pushvalue(L, err);
296     lua_setglobal(L, LUA_ERRORMESSAGE);
297   }
298   if (status != 0) {  /* error in call? */
299     if (strchr(options, 'x'))
300       lua_pushnil(L);  /* return nil to signal the error */
301     else
302       lua_error(L, NULL);  /* propagate error without additional messages */
303     return 1;
304   }
305   if (strchr(options, 'p'))  /* pack results? */
306     lua_error(L, "deprecated option `p' in `call'");
307   return lua_gettop(L) - oldtop;  /* results are already on the stack */
308 }
309 
310 
luaB_tostring(lua_State * L)311 static int luaB_tostring (lua_State *L) {
312   char buff[64];
313   switch (lua_type(L, 1)) {
314     case LUA_TNUMBER:
315       lua_pushstring(L, lua_tostring(L, 1));
316       return 1;
317     case LUA_TSTRING:
318       lua_pushvalue(L, 1);
319       return 1;
320     case LUA_TTABLE:
321       sprintf(buff, "table: %p", lua_topointer(L, 1));
322       break;
323     case LUA_TFUNCTION:
324       sprintf(buff, "function: %p", lua_topointer(L, 1));
325       break;
326     case LUA_TUSERDATA:
327       sprintf(buff, "userdata(%d): %p", lua_tag(L, 1), lua_touserdata(L, 1));
328       break;
329     case LUA_TNIL:
330       lua_pushstring(L, "nil");
331       return 1;
332     default:
333       luaL_argerror(L, 1, "value expected");
334   }
335   lua_pushstring(L, buff);
336   return 1;
337 }
338 
339 
luaB_foreachi(lua_State * L)340 static int luaB_foreachi (lua_State *L) {
341   int n, i;
342   luaL_checktype(L, 1, LUA_TTABLE);
343   luaL_checktype(L, 2, LUA_TFUNCTION);
344   n = lua_getn(L, 1);
345   for (i=1; i<=n; i++) {
346     lua_pushvalue(L, 2);  /* function */
347     lua_pushnumber(L, i);  /* 1st argument */
348     lua_rawgeti(L, 1, i);  /* 2nd argument */
349     lua_rawcall(L, 2, 1);
350     if (!lua_isnil(L, -1))
351       return 1;
352     lua_pop(L, 1);  /* remove nil result */
353   }
354   return 0;
355 }
356 
357 
luaB_foreach(lua_State * L)358 static int luaB_foreach (lua_State *L) {
359   luaL_checktype(L, 1, LUA_TTABLE);
360   luaL_checktype(L, 2, LUA_TFUNCTION);
361   lua_pushnil(L);  /* first index */
362   for (;;) {
363     if (lua_next(L, 1) == 0)
364       return 0;
365     lua_pushvalue(L, 2);  /* function */
366     lua_pushvalue(L, -3);  /* key */
367     lua_pushvalue(L, -3);  /* value */
368     lua_rawcall(L, 2, 1);
369     if (!lua_isnil(L, -1))
370       return 1;
371     lua_pop(L, 2);  /* remove value and result */
372   }
373 }
374 
375 
luaB_assert(lua_State * L)376 static int luaB_assert (lua_State *L) {
377   luaL_checkany(L, 1);
378   if (lua_isnil(L, 1))
379     luaL_verror(L, "assertion failed!  %.90s", luaL_opt_string(L, 2, ""));
380   return 0;
381 }
382 
383 
luaB_getn(lua_State * L)384 static int luaB_getn (lua_State *L) {
385   luaL_checktype(L, 1, LUA_TTABLE);
386   lua_pushnumber(L, lua_getn(L, 1));
387   return 1;
388 }
389 
390 
luaB_tinsert(lua_State * L)391 static int luaB_tinsert (lua_State *L) {
392   int v = lua_gettop(L);  /* last argument: to be inserted */
393   int n, pos;
394   luaL_checktype(L, 1, LUA_TTABLE);
395   n = lua_getn(L, 1);
396   if (v == 2)  /* called with only 2 arguments */
397     pos = n+1;
398   else
399     pos = luaL_check_int(L, 2);  /* 2nd argument is the position */
400   lua_pushstring(L, "n");
401   lua_pushnumber(L, n+1);
402   lua_rawset(L, 1);  /* t.n = n+1 */
403   for (; n>=pos; n--) {
404     lua_rawgeti(L, 1, n);
405     lua_rawseti(L, 1, n+1);  /* t[n+1] = t[n] */
406   }
407   lua_pushvalue(L, v);
408   lua_rawseti(L, 1, pos);  /* t[pos] = v */
409   return 0;
410 }
411 
412 
luaB_tremove(lua_State * L)413 static int luaB_tremove (lua_State *L) {
414   int pos, n;
415   luaL_checktype(L, 1, LUA_TTABLE);
416   n = lua_getn(L, 1);
417   pos = luaL_opt_int(L, 2, n);
418   if (n <= 0) return 0;  /* table is "empty" */
419   lua_rawgeti(L, 1, pos);  /* result = t[pos] */
420   for ( ;pos<n; pos++) {
421     lua_rawgeti(L, 1, pos+1);
422     lua_rawseti(L, 1, pos);  /* a[pos] = a[pos+1] */
423   }
424   lua_pushstring(L, "n");
425   lua_pushnumber(L, n-1);
426   lua_rawset(L, 1);  /* t.n = n-1 */
427   lua_pushnil(L);
428   lua_rawseti(L, 1, n);  /* t[n] = nil */
429   return 1;
430 }
431 
432 
433 
434 
435 /*
436 ** {======================================================
437 ** Quicksort
438 ** (based on `Algorithms in MODULA-3', Robert Sedgewick;
439 **  Addison-Wesley, 1993.)
440 */
441 
442 
set2(lua_State * L,int i,int j)443 static void set2 (lua_State *L, int i, int j) {
444   lua_rawseti(L, 1, i);
445   lua_rawseti(L, 1, j);
446 }
447 
sort_comp(lua_State * L,int a,int b)448 static int sort_comp (lua_State *L, int a, int b) {
449   /* WARNING: the caller (auxsort) must ensure stack space */
450   if (!lua_isnil(L, 2)) {  /* function? */
451     int res;
452     lua_pushvalue(L, 2);
453     lua_pushvalue(L, a-1);  /* -1 to compensate function */
454     lua_pushvalue(L, b-2);  /* -2 to compensate function and `a' */
455     lua_rawcall(L, 2, 1);
456     res = !lua_isnil(L, -1);
457     lua_pop(L, 1);
458     return res;
459   }
460   else  /* a < b? */
461     return lua_lessthan(L, a, b);
462 }
463 
auxsort(lua_State * L,int l,int u)464 static void auxsort (lua_State *L, int l, int u) {
465   while (l < u) {  /* for tail recursion */
466     int i, j;
467     /* sort elements a[l], a[(l+u)/2] and a[u] */
468     lua_rawgeti(L, 1, l);
469     lua_rawgeti(L, 1, u);
470     if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */
471       set2(L, l, u);  /* swap a[l] - a[u] */
472     else
473       lua_pop(L, 2);
474     if (u-l == 1) break;  /* only 2 elements */
475     i = (l+u)/2;
476     lua_rawgeti(L, 1, i);
477     lua_rawgeti(L, 1, l);
478     if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */
479       set2(L, i, l);
480     else {
481       lua_pop(L, 1);  /* remove a[l] */
482       lua_rawgeti(L, 1, u);
483       if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */
484         set2(L, i, u);
485       else
486         lua_pop(L, 2);
487     }
488     if (u-l == 2) break;  /* only 3 elements */
489     lua_rawgeti(L, 1, i);  /* Pivot */
490     lua_pushvalue(L, -1);
491     lua_rawgeti(L, 1, u-1);
492     set2(L, i, u-1);
493     /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */
494     i = l; j = u-1;
495     for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */
496       /* repeat ++i until a[i] >= P */
497       while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {
498         if (i>u) lua_error(L, "invalid order function for sorting");
499         lua_pop(L, 1);  /* remove a[i] */
500       }
501       /* repeat --j until a[j] <= P */
502       while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {
503         if (j<l) lua_error(L, "invalid order function for sorting");
504         lua_pop(L, 1);  /* remove a[j] */
505       }
506       if (j<i) {
507         lua_pop(L, 3);  /* pop pivot, a[i], a[j] */
508         break;
509       }
510       set2(L, i, j);
511     }
512     lua_rawgeti(L, 1, u-1);
513     lua_rawgeti(L, 1, i);
514     set2(L, u-1, i);  /* swap pivot (a[u-1]) with a[i] */
515     /* a[l..i-1] <= a[i] == P <= a[i+1..u] */
516     /* adjust so that smaller "half" is in [j..i] and larger one in [l..u] */
517     if (i-l < u-i) {
518       j=l; i=i-1; l=i+2;
519     }
520     else {
521       j=i+1; i=u; u=j-2;
522     }
523     auxsort(L, j, i);  /* call recursively the smaller one */
524   }  /* repeat the routine for the larger one */
525 }
526 
luaB_sort(lua_State * L)527 static int luaB_sort (lua_State *L) {
528   int n;
529   luaL_checktype(L, 1, LUA_TTABLE);
530   n = lua_getn(L, 1);
531   if (!lua_isnull(L, 2))  /* is there a 2nd argument? */
532     luaL_checktype(L, 2, LUA_TFUNCTION);
533   lua_settop(L, 2);  /* make sure there is two arguments */
534   auxsort(L, 1, n);
535   return 0;
536 }
537 
538 /* }====================================================== */
539 
540 
541 
542 /*
543 ** {======================================================
544 ** Deprecated functions to manipulate global environment.
545 ** =======================================================
546 */
547 
548 
549 #define num_deprecated	4
550 
551 static const struct luaL_reg deprecated_names [num_deprecated] = {
552   {"foreachvar", luaB_foreach},
553   {"nextvar", luaB_next},
554   {"rawgetglobal", luaB_rawget},
555   {"rawsetglobal", luaB_rawset}
556 };
557 
558 
559 #ifdef LUA_DEPRECATEDFUNCS
560 
561 /*
562 ** call corresponding function inserting `globals' as first argument
563 */
deprecated_func(lua_State * L)564 static int deprecated_func (lua_State *L) {
565   lua_insert(L, 1);  /* upvalue is the function to be called */
566   lua_getglobals(L);
567   lua_insert(L, 2);  /* table of globals is 1o argument */
568   lua_rawcall(L, lua_gettop(L)-1, LUA_MULTRET);
569   return lua_gettop(L);  /* return all results */
570 }
571 
572 
deprecated_funcs(lua_State * L)573 static void deprecated_funcs (lua_State *L) {
574   int i;
575   for (i=0; i<num_deprecated; i++) {
576     lua_pushcfunction(L, deprecated_names[i].func);
577     lua_pushcclosure(L, deprecated_func, 1);
578     lua_setglobal(L, deprecated_names[i].name);
579   }
580 }
581 
582 
583 #else
584 
585 /*
586 ** gives an explicit error in any attempt to call a deprecated function
587 */
deprecated_func(lua_State * L)588 static int deprecated_func (lua_State *L) {
589   luaL_verror(L, "function `%.20s' is deprecated", lua_tostring(L, -1));
590   return 0;  /* to avoid warnings */
591 }
592 
593 
deprecated_funcs(lua_State * L)594 static void deprecated_funcs (lua_State *L) {
595   int i;
596   for (i=0; i<num_deprecated; i++) {
597     lua_pushstring(L, deprecated_names[i].name);
598     lua_pushcclosure(L, deprecated_func, 1);
599     lua_setglobal(L, deprecated_names[i].name);
600   }
601 }
602 
603 #endif
604 
605 /* }====================================================== */
606 
607 static const struct luaL_reg base_funcs[] = {
608   {LUA_ALERT, luaB__ALERT},
609   {LUA_ERRORMESSAGE, luaB__ERRORMESSAGE},
610   {"call", luaB_call},
611   {"collectgarbage", luaB_collectgarbage},
612   {"copytagmethods", luaB_copytagmethods},
613   {"dofile", luaB_dofile},
614   {"dostring", luaB_dostring},
615   {"error", luaB_error},
616   {"foreach", luaB_foreach},
617   {"foreachi", luaB_foreachi},
618   {"gcinfo", luaB_gcinfo},
619   {"getglobal", luaB_getglobal},
620   {"gettagmethod", luaB_gettagmethod},
621   {"globals", luaB_globals},
622   {"newtag", luaB_newtag},
623   {"next", luaB_next},
624   {"print", luaB_print},
625   {"rawget", luaB_rawget},
626   {"rawset", luaB_rawset},
627   {"rawgettable", luaB_rawget},  /* for compatibility */
628   {"rawsettable", luaB_rawset},  /* for compatibility */
629   {"setglobal", luaB_setglobal},
630   {"settag", luaB_settag},
631   {"settagmethod", luaB_settagmethod},
632   {"tag", luaB_tag},
633   {"tonumber", luaB_tonumber},
634   {"tostring", luaB_tostring},
635   {"type", luaB_type},
636   {"assert", luaB_assert},
637   {"getn", luaB_getn},
638   {"sort", luaB_sort},
639   {"tinsert", luaB_tinsert},
640   {"tremove", luaB_tremove}
641 };
642 
643 
644 
lua_baselibopen(lua_State * L)645 LUALIB_API void lua_baselibopen (lua_State *L) {
646   luaL_openl(L, base_funcs);
647   lua_pushstring(L, LUA_VERSION);
648   lua_setglobal(L, "_VERSION");
649   deprecated_funcs(L);
650 }
651 
652