xref: /netbsd-src/external/mit/lua/dist/src/lauxlib.c (revision 80d9064ac03cbb6a4174695f0d5b237c8766d3d0)
1 /*	$NetBSD: lauxlib.c,v 1.3 2014/07/19 18:38:34 lneto Exp $	*/
2 
3 /*
4 ** $Id: lauxlib.c,v 1.3 2014/07/19 18:38:34 lneto Exp $
5 ** Auxiliary functions for building Lua libraries
6 ** See Copyright Notice in lua.h
7 */
8 
9 
10 #ifndef _KERNEL
11 #include <errno.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #endif
17 
18 
19 /* This file uses only the official API of Lua.
20 ** Any function declared here could be written as an application function.
21 */
22 
23 #define lauxlib_c
24 #define LUA_LIB
25 
26 #include "lua.h"
27 
28 #include "lauxlib.h"
29 
30 
31 /*
32 ** {======================================================
33 ** Traceback
34 ** =======================================================
35 */
36 
37 
38 #define LEVELS1	12	/* size of the first part of the stack */
39 #define LEVELS2	10	/* size of the second part of the stack */
40 
41 
42 
43 /*
44 ** search for 'objidx' in table at index -1.
45 ** return 1 + string at top if find a good name.
46 */
47 static int findfield (lua_State *L, int objidx, int level) {
48   if (level == 0 || !lua_istable(L, -1))
49     return 0;  /* not found */
50   lua_pushnil(L);  /* start 'next' loop */
51   while (lua_next(L, -2)) {  /* for each pair in table */
52     if (lua_type(L, -2) == LUA_TSTRING) {  /* ignore non-string keys */
53       if (lua_rawequal(L, objidx, -1)) {  /* found object? */
54         lua_pop(L, 1);  /* remove value (but keep name) */
55         return 1;
56       }
57       else if (findfield(L, objidx, level - 1)) {  /* try recursively */
58         lua_remove(L, -2);  /* remove table (but keep name) */
59         lua_pushliteral(L, ".");
60         lua_insert(L, -2);  /* place '.' between the two names */
61         lua_concat(L, 3);
62         return 1;
63       }
64     }
65     lua_pop(L, 1);  /* remove value */
66   }
67   return 0;  /* not found */
68 }
69 
70 
71 static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
72   int top = lua_gettop(L);
73   lua_getinfo(L, "f", ar);  /* push function */
74   lua_pushglobaltable(L);
75   if (findfield(L, top + 1, 2)) {
76     lua_copy(L, -1, top + 1);  /* move name to proper place */
77     lua_pop(L, 2);  /* remove pushed values */
78     return 1;
79   }
80   else {
81     lua_settop(L, top);  /* remove function and global table */
82     return 0;
83   }
84 }
85 
86 
87 static void pushfuncname (lua_State *L, lua_Debug *ar) {
88   if (*ar->namewhat != '\0')  /* is there a name? */
89     lua_pushfstring(L, "function " LUA_QS, ar->name);
90   else if (*ar->what == 'm')  /* main? */
91       lua_pushliteral(L, "main chunk");
92   else if (*ar->what == 'C') {
93     if (pushglobalfuncname(L, ar)) {
94       lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
95       lua_remove(L, -2);  /* remove name */
96     }
97     else
98       lua_pushliteral(L, "?");
99   }
100   else
101     lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
102 }
103 
104 
105 static int countlevels (lua_State *L) {
106   lua_Debug ar;
107   int li = 1, le = 1;
108   /* find an upper bound */
109   while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
110   /* do a binary search */
111   while (li < le) {
112     int m = (li + le)/2;
113     if (lua_getstack(L, m, &ar)) li = m + 1;
114     else le = m;
115   }
116   return le - 1;
117 }
118 
119 
120 LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
121                                 const char *msg, int level) {
122   lua_Debug ar;
123   int top = lua_gettop(L);
124   int numlevels = countlevels(L1);
125   int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0;
126   if (msg) lua_pushfstring(L, "%s\n", msg);
127   lua_pushliteral(L, "stack traceback:");
128   while (lua_getstack(L1, level++, &ar)) {
129     if (level == mark) {  /* too many levels? */
130       lua_pushliteral(L, "\n\t...");  /* add a '...' */
131       level = numlevels - LEVELS2;  /* and skip to last ones */
132     }
133     else {
134       lua_getinfo(L1, "Slnt", &ar);
135       lua_pushfstring(L, "\n\t%s:", ar.short_src);
136       if (ar.currentline > 0)
137         lua_pushfstring(L, "%d:", ar.currentline);
138       lua_pushliteral(L, " in ");
139       pushfuncname(L, &ar);
140       if (ar.istailcall)
141         lua_pushliteral(L, "\n\t(...tail calls...)");
142       lua_concat(L, lua_gettop(L) - top);
143     }
144   }
145   lua_concat(L, lua_gettop(L) - top);
146 }
147 
148 /* }====================================================== */
149 
150 
151 /*
152 ** {======================================================
153 ** Error-report functions
154 ** =======================================================
155 */
156 
157 LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
158   lua_Debug ar;
159   if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
160     return luaL_error(L, "bad argument #%d (%s)", arg, extramsg);
161   lua_getinfo(L, "n", &ar);
162   if (strcmp(ar.namewhat, "method") == 0) {
163     arg--;  /* do not count `self' */
164     if (arg == 0)  /* error is in the self argument itself? */
165       return luaL_error(L, "calling " LUA_QS " on bad self (%s)",
166                            ar.name, extramsg);
167   }
168   if (ar.name == NULL)
169     ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
170   return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)",
171                         arg, ar.name, extramsg);
172 }
173 
174 
175 static int typeerror (lua_State *L, int arg, const char *tname) {
176   const char *msg;
177   const char *typearg = luaL_typename(L, arg);
178   if (lua_getmetatable(L, arg)) {
179     if (lua_getfield(L, -1, "__name") == LUA_TSTRING)
180       typearg = lua_tostring(L, -1);
181   }
182   else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA)
183     typearg = "light userdata";
184   msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg);
185   return luaL_argerror(L, arg, msg);
186 }
187 
188 
189 static void tag_error (lua_State *L, int arg, int tag) {
190   typeerror(L, arg, lua_typename(L, tag));
191 }
192 
193 
194 LUALIB_API void luaL_where (lua_State *L, int level) {
195   lua_Debug ar;
196   if (lua_getstack(L, level, &ar)) {  /* check function at level */
197     lua_getinfo(L, "Sl", &ar);  /* get info about it */
198     if (ar.currentline > 0) {  /* is there info? */
199       lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
200       return;
201     }
202   }
203   lua_pushliteral(L, "");  /* else, no information available... */
204 }
205 
206 
207 LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
208   va_list argp;
209   va_start(argp, fmt);
210   luaL_where(L, 1);
211   lua_pushvfstring(L, fmt, argp);
212   va_end(argp);
213   lua_concat(L, 2);
214   return lua_error(L);
215 }
216 
217 
218 #ifndef _KERNEL
219 LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
220   int en = errno;  /* calls to Lua API may change this value */
221   if (stat) {
222     lua_pushboolean(L, 1);
223     return 1;
224   }
225   else {
226     lua_pushnil(L);
227     if (fname)
228       lua_pushfstring(L, "%s: %s", fname, strerror(en));
229     else
230       lua_pushstring(L, strerror(en));
231     lua_pushinteger(L, en);
232     return 3;
233   }
234 }
235 #endif
236 
237 
238 #if !defined(inspectstat)	/* { */
239 
240 #if defined(LUA_USE_POSIX)
241 
242 #include <sys/wait.h>
243 
244 /*
245 ** use appropriate macros to interpret 'pclose' return status
246 */
247 #define inspectstat(stat,what)  \
248    if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
249    else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
250 
251 #else
252 
253 #define inspectstat(stat,what)  /* no op */
254 
255 #endif
256 
257 #endif				/* } */
258 
259 
260 #ifndef _KERNEL
261 LUALIB_API int luaL_execresult (lua_State *L, int stat) {
262   const char *what = "exit";  /* type of termination */
263   if (stat == -1)  /* error? */
264     return luaL_fileresult(L, 0, NULL);
265   else {
266     inspectstat(stat, what);  /* interpret result */
267     if (*what == 'e' && stat == 0)  /* successful termination? */
268       lua_pushboolean(L, 1);
269     else
270       lua_pushnil(L);
271     lua_pushstring(L, what);
272     lua_pushinteger(L, stat);
273     return 3;  /* return true/nil,what,code */
274   }
275 }
276 #endif
277 
278 /* }====================================================== */
279 
280 
281 /*
282 ** {======================================================
283 ** Userdata's metatable manipulation
284 ** =======================================================
285 */
286 
287 LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
288   luaL_getmetatable(L, tname);  /* try to get metatable */
289   if (!lua_isnil(L, -1))  /* name already in use? */
290     return 0;  /* leave previous value on top, but return 0 */
291   lua_pop(L, 1);
292   lua_newtable(L);  /* create metatable */
293   lua_pushstring(L, tname);
294   lua_setfield(L, -2, "__name");  /* metatable.__name = tname */
295   lua_pushvalue(L, -1);
296   lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */
297   return 1;
298 }
299 
300 
301 LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
302   luaL_getmetatable(L, tname);
303   lua_setmetatable(L, -2);
304 }
305 
306 
307 LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
308   void *p = lua_touserdata(L, ud);
309   if (p != NULL) {  /* value is a userdata? */
310     if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
311       luaL_getmetatable(L, tname);  /* get correct metatable */
312       if (!lua_rawequal(L, -1, -2))  /* not the same? */
313         p = NULL;  /* value is a userdata with wrong metatable */
314       lua_pop(L, 2);  /* remove both metatables */
315       return p;
316     }
317   }
318   return NULL;  /* value is not a userdata with a metatable */
319 }
320 
321 
322 LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
323   void *p = luaL_testudata(L, ud, tname);
324   if (p == NULL) typeerror(L, ud, tname);
325   return p;
326 }
327 
328 /* }====================================================== */
329 
330 
331 /*
332 ** {======================================================
333 ** Argument check functions
334 ** =======================================================
335 */
336 
337 LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
338                                  const char *const lst[]) {
339   const char *name = (def) ? luaL_optstring(L, arg, def) :
340                              luaL_checkstring(L, arg);
341   int i;
342   for (i=0; lst[i]; i++)
343     if (strcmp(lst[i], name) == 0)
344       return i;
345   return luaL_argerror(L, arg,
346                        lua_pushfstring(L, "invalid option " LUA_QS, name));
347 }
348 
349 
350 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
351   /* keep some extra space to run error routines, if needed */
352   const int extra = LUA_MINSTACK;
353   if (!lua_checkstack(L, space + extra)) {
354     if (msg)
355       luaL_error(L, "stack overflow (%s)", msg);
356     else
357       luaL_error(L, "stack overflow");
358   }
359 }
360 
361 
362 LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) {
363   if (lua_type(L, arg) != t)
364     tag_error(L, arg, t);
365 }
366 
367 
368 LUALIB_API void luaL_checkany (lua_State *L, int arg) {
369   if (lua_type(L, arg) == LUA_TNONE)
370     luaL_argerror(L, arg, "value expected");
371 }
372 
373 
374 LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) {
375   const char *s = lua_tolstring(L, arg, len);
376   if (!s) tag_error(L, arg, LUA_TSTRING);
377   return s;
378 }
379 
380 
381 LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
382                                         const char *def, size_t *len) {
383   if (lua_isnoneornil(L, arg)) {
384     if (len)
385       *len = (def ? strlen(def) : 0);
386     return def;
387   }
388   else return luaL_checklstring(L, arg, len);
389 }
390 
391 
392 LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) {
393   int isnum;
394   lua_Number d = lua_tonumberx(L, arg, &isnum);
395   if (!isnum)
396     tag_error(L, arg, LUA_TNUMBER);
397   return d;
398 }
399 
400 
401 LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) {
402   return luaL_opt(L, luaL_checknumber, arg, def);
403 }
404 
405 
406 static void interror (lua_State *L, int arg) {
407   if (lua_type(L, arg) == LUA_TNUMBER)
408     luaL_argerror(L, arg, "float value out of integer range");
409   else
410     tag_error(L, arg, LUA_TNUMBER);
411 }
412 
413 
414 LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) {
415   int isnum;
416   lua_Integer d = lua_tointegerx(L, arg, &isnum);
417   if (!isnum) {
418     interror(L, arg);
419   }
420   return d;
421 }
422 
423 
424 LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int arg) {
425   int isnum;
426   lua_Unsigned d = lua_tounsignedx(L, arg, &isnum);
427   if (!isnum)
428     interror(L, arg);
429   return d;
430 }
431 
432 
433 LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
434                                                       lua_Integer def) {
435   return luaL_opt(L, luaL_checkinteger, arg, def);
436 }
437 
438 
439 LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int arg,
440                                                         lua_Unsigned def) {
441   return luaL_opt(L, luaL_checkunsigned, arg, def);
442 }
443 
444 /* }====================================================== */
445 
446 
447 /*
448 ** {======================================================
449 ** Generic Buffer manipulation
450 ** =======================================================
451 */
452 
453 /*
454 ** check whether buffer is using a userdata on the stack as a temporary
455 ** buffer
456 */
457 #define buffonstack(B)	((B)->b != (B)->initb)
458 
459 
460 /*
461 ** returns a pointer to a free area with at least 'sz' bytes
462 */
463 LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
464   lua_State *L = B->L;
465   if (B->size - B->n < sz) {  /* not enough space? */
466     char *newbuff;
467     size_t newsize = B->size * 2;  /* double buffer size */
468     if (newsize - B->n < sz)  /* not big enough? */
469       newsize = B->n + sz;
470     if (newsize < B->n || newsize - B->n < sz)
471       luaL_error(L, "buffer too large");
472     /* create larger buffer */
473     newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
474     /* move content to new buffer */
475     memcpy(newbuff, B->b, B->n * sizeof(char));
476     if (buffonstack(B))
477       lua_remove(L, -2);  /* remove old buffer */
478     B->b = newbuff;
479     B->size = newsize;
480   }
481   return &B->b[B->n];
482 }
483 
484 
485 LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
486   char *b = luaL_prepbuffsize(B, l);
487   memcpy(b, s, l * sizeof(char));
488   luaL_addsize(B, l);
489 }
490 
491 
492 LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
493   luaL_addlstring(B, s, strlen(s));
494 }
495 
496 
497 LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
498   lua_State *L = B->L;
499   lua_pushlstring(L, B->b, B->n);
500   if (buffonstack(B))
501     lua_remove(L, -2);  /* remove old buffer */
502 }
503 
504 
505 LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
506   luaL_addsize(B, sz);
507   luaL_pushresult(B);
508 }
509 
510 
511 LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
512   lua_State *L = B->L;
513   size_t l;
514   const char *s = lua_tolstring(L, -1, &l);
515   if (buffonstack(B))
516     lua_insert(L, -2);  /* put value below buffer */
517   luaL_addlstring(B, s, l);
518   lua_remove(L, (buffonstack(B)) ? -2 : -1);  /* remove value */
519 }
520 
521 
522 LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
523   B->L = L;
524   B->b = B->initb;
525   B->n = 0;
526   B->size = LUAL_BUFFERSIZE;
527 }
528 
529 
530 LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
531   luaL_buffinit(L, B);
532   return luaL_prepbuffsize(B, sz);
533 }
534 
535 /* }====================================================== */
536 
537 
538 /*
539 ** {======================================================
540 ** Reference system
541 ** =======================================================
542 */
543 
544 /* index of free-list header */
545 #define freelist	0
546 
547 
548 LUALIB_API int luaL_ref (lua_State *L, int t) {
549   int ref;
550   if (lua_isnil(L, -1)) {
551     lua_pop(L, 1);  /* remove from stack */
552     return LUA_REFNIL;  /* `nil' has a unique fixed reference */
553   }
554   t = lua_absindex(L, t);
555   lua_rawgeti(L, t, freelist);  /* get first free element */
556   ref = (int)lua_tointeger(L, -1);  /* ref = t[freelist] */
557   lua_pop(L, 1);  /* remove it from stack */
558   if (ref != 0) {  /* any free element? */
559     lua_rawgeti(L, t, ref);  /* remove it from list */
560     lua_rawseti(L, t, freelist);  /* (t[freelist] = t[ref]) */
561   }
562   else  /* no free elements */
563     ref = (int)lua_rawlen(L, t) + 1;  /* get a new reference */
564   lua_rawseti(L, t, ref);
565   return ref;
566 }
567 
568 
569 LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
570   if (ref >= 0) {
571     t = lua_absindex(L, t);
572     lua_rawgeti(L, t, freelist);
573     lua_rawseti(L, t, ref);  /* t[ref] = t[freelist] */
574     lua_pushinteger(L, ref);
575     lua_rawseti(L, t, freelist);  /* t[freelist] = ref */
576   }
577 }
578 
579 /* }====================================================== */
580 
581 
582 /*
583 ** {======================================================
584 ** Load functions
585 ** =======================================================
586 */
587 
588 #ifndef _KERNEL
589 typedef struct LoadF {
590   int n;  /* number of pre-read characters */
591   FILE *f;  /* file being read */
592   char buff[LUAL_BUFFERSIZE];  /* area for reading file */
593 } LoadF;
594 
595 
596 static const char *getF (lua_State *L, void *ud, size_t *size) {
597   LoadF *lf = (LoadF *)ud;
598   (void)L;  /* not used */
599   if (lf->n > 0) {  /* are there pre-read characters to be read? */
600     *size = lf->n;  /* return them (chars already in buffer) */
601     lf->n = 0;  /* no more pre-read characters */
602   }
603   else {  /* read a block from file */
604     /* 'fread' can return > 0 *and* set the EOF flag. If next call to
605        'getF' called 'fread', it might still wait for user input.
606        The next check avoids this problem. */
607     if (feof(lf->f)) return NULL;
608     *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);  /* read block */
609   }
610   return lf->buff;
611 }
612 
613 
614 static int errfile (lua_State *L, const char *what, int fnameindex) {
615   const char *serr = strerror(errno);
616   const char *filename = lua_tostring(L, fnameindex) + 1;
617   lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
618   lua_remove(L, fnameindex);
619   return LUA_ERRFILE;
620 }
621 
622 
623 static int skipBOM (LoadF *lf) {
624   const char *p = "\xEF\xBB\xBF";  /* Utf8 BOM mark */
625   int c;
626   lf->n = 0;
627   do {
628     c = getc(lf->f);
629     if (c == EOF || c != *(const unsigned char *)p++) return c;
630     lf->buff[lf->n++] = c;  /* to be read by the parser */
631   } while (*p != '\0');
632   lf->n = 0;  /* prefix matched; discard it */
633   return getc(lf->f);  /* return next character */
634 }
635 
636 
637 /*
638 ** reads the first character of file 'f' and skips an optional BOM mark
639 ** in its beginning plus its first line if it starts with '#'. Returns
640 ** true if it skipped the first line.  In any case, '*cp' has the
641 ** first "valid" character of the file (after the optional BOM and
642 ** a first-line comment).
643 */
644 static int skipcomment (LoadF *lf, int *cp) {
645   int c = *cp = skipBOM(lf);
646   if (c == '#') {  /* first line is a comment (Unix exec. file)? */
647     do {  /* skip first line */
648       c = getc(lf->f);
649     } while (c != EOF && c != '\n') ;
650     *cp = getc(lf->f);  /* skip end-of-line, if present */
651     return 1;  /* there was a comment */
652   }
653   else return 0;  /* no comment */
654 }
655 
656 
657 LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
658                                              const char *mode) {
659   LoadF lf;
660   int status, readstatus;
661   int c;
662   int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
663   if (filename == NULL) {
664     lua_pushliteral(L, "=stdin");
665     lf.f = stdin;
666   }
667   else {
668     lua_pushfstring(L, "@%s", filename);
669     lf.f = fopen(filename, "r");
670     if (lf.f == NULL) return errfile(L, "open", fnameindex);
671   }
672   if (skipcomment(&lf, &c))  /* read initial portion */
673     lf.buff[lf.n++] = '\n';  /* add line to correct line numbers */
674   if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */
675     lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
676     if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
677     skipcomment(&lf, &c);  /* re-read initial portion */
678   }
679   if (c != EOF)
680     lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
681   status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
682   readstatus = ferror(lf.f);
683   if (filename) fclose(lf.f);  /* close file (even in case of errors) */
684   if (readstatus) {
685     lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
686     return errfile(L, "read", fnameindex);
687   }
688   lua_remove(L, fnameindex);
689   return status;
690 }
691 #endif
692 
693 
694 typedef struct LoadS {
695   const char *s;
696   size_t size;
697 } LoadS;
698 
699 
700 static const char *getS (lua_State *L, void *ud, size_t *size) {
701   LoadS *ls = (LoadS *)ud;
702   (void)L;  /* not used */
703   if (ls->size == 0) return NULL;
704   *size = ls->size;
705   ls->size = 0;
706   return ls->s;
707 }
708 
709 
710 LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
711                                  const char *name, const char *mode) {
712   LoadS ls;
713   ls.s = buff;
714   ls.size = size;
715   return lua_load(L, getS, &ls, name, mode);
716 }
717 
718 
719 LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
720   return luaL_loadbuffer(L, s, strlen(s), s);
721 }
722 
723 /* }====================================================== */
724 
725 
726 
727 LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
728   if (!lua_getmetatable(L, obj))  /* no metatable? */
729     return 0;
730   lua_pushstring(L, event);
731   if (lua_rawget(L, -2) == LUA_TNIL) {  /* is metafield nil? */
732     lua_pop(L, 2);  /* remove metatable and metafield */
733     return 0;
734   }
735   else {
736     lua_remove(L, -2);  /* remove only metatable */
737     return 1;
738   }
739 }
740 
741 
742 LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
743   obj = lua_absindex(L, obj);
744   if (!luaL_getmetafield(L, obj, event))  /* no metafield? */
745     return 0;
746   lua_pushvalue(L, obj);
747   lua_call(L, 1, 1);
748   return 1;
749 }
750 
751 
752 LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
753   lua_Integer l;
754   int isnum;
755   lua_len(L, idx);
756   l = lua_tointegerx(L, -1, &isnum);
757   if (!isnum)
758     luaL_error(L, "object length is not an integer");
759   lua_pop(L, 1);  /* remove object */
760   return l;
761 }
762 
763 
764 LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
765   if (!luaL_callmeta(L, idx, "__tostring")) {  /* no metafield? */
766     switch (lua_type(L, idx)) {
767       case LUA_TNUMBER: {
768         if (lua_isinteger(L, idx))
769           lua_pushfstring(L, "%I", lua_tointeger(L, idx));
770         else
771           lua_pushfstring(L, "%f", lua_tonumber(L, idx));
772         break;
773       }
774       case LUA_TSTRING:
775         lua_pushvalue(L, idx);
776         break;
777       case LUA_TBOOLEAN:
778         lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
779         break;
780       case LUA_TNIL:
781         lua_pushliteral(L, "nil");
782         break;
783       default:
784         lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
785                                             lua_topointer(L, idx));
786         break;
787     }
788   }
789   return lua_tolstring(L, -1, len);
790 }
791 
792 
793 /*
794 ** {======================================================
795 ** Compatibility with 5.1 module functions
796 ** =======================================================
797 */
798 #if defined(LUA_COMPAT_MODULE)
799 
800 static const char *luaL_findtable (lua_State *L, int idx,
801                                    const char *fname, int szhint) {
802   const char *e;
803   if (idx) lua_pushvalue(L, idx);
804   do {
805     e = strchr(fname, '.');
806     if (e == NULL) e = fname + strlen(fname);
807     lua_pushlstring(L, fname, e - fname);
808     if (lua_rawget(L, -2) == LUA_TNIL) {  /* no such field? */
809       lua_pop(L, 1);  /* remove this nil */
810       lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
811       lua_pushlstring(L, fname, e - fname);
812       lua_pushvalue(L, -2);
813       lua_settable(L, -4);  /* set new table into field */
814     }
815     else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
816       lua_pop(L, 2);  /* remove table and value */
817       return fname;  /* return problematic part of the name */
818     }
819     lua_remove(L, -2);  /* remove previous table */
820     fname = e + 1;
821   } while (*e == '.');
822   return NULL;
823 }
824 
825 
826 /*
827 ** Count number of elements in a luaL_Reg list.
828 */
829 static int libsize (const luaL_Reg *l) {
830   int size = 0;
831   for (; l && l->name; l++) size++;
832   return size;
833 }
834 
835 
836 /*
837 ** Find or create a module table with a given name. The function
838 ** first looks at the _LOADED table and, if that fails, try a
839 ** global variable with that name. In any case, leaves on the stack
840 ** the module table.
841 */
842 LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
843                                  int sizehint) {
844   luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);  /* get _LOADED table */
845   if (lua_getfield(L, -1, modname) != LUA_TTABLE) {  /* no _LOADED[modname]? */
846     lua_pop(L, 1);  /* remove previous result */
847     /* try global variable (and create one if it does not exist) */
848     lua_pushglobaltable(L);
849     if (luaL_findtable(L, 0, modname, sizehint) != NULL)
850       luaL_error(L, "name conflict for module " LUA_QS, modname);
851     lua_pushvalue(L, -1);
852     lua_setfield(L, -3, modname);  /* _LOADED[modname] = new table */
853   }
854   lua_remove(L, -2);  /* remove _LOADED table */
855 }
856 
857 
858 LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
859                                const luaL_Reg *l, int nup) {
860   luaL_checkversion(L);
861   if (libname) {
862     luaL_pushmodule(L, libname, libsize(l));  /* get/create library table */
863     lua_insert(L, -(nup + 1));  /* move library table to below upvalues */
864   }
865   if (l)
866     luaL_setfuncs(L, l, nup);
867   else
868     lua_pop(L, nup);  /* remove upvalues */
869 }
870 
871 #endif
872 /* }====================================================== */
873 
874 /*
875 ** set functions from list 'l' into table at top - 'nup'; each
876 ** function gets the 'nup' elements at the top as upvalues.
877 ** Returns with only the table at the stack.
878 */
879 LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
880   luaL_checkstack(L, nup, "too many upvalues");
881   for (; l->name != NULL; l++) {  /* fill the table with given functions */
882     int i;
883     for (i = 0; i < nup; i++)  /* copy upvalues to the top */
884       lua_pushvalue(L, -nup);
885     lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
886     lua_setfield(L, -(nup + 2), l->name);
887   }
888   lua_pop(L, nup);  /* remove upvalues */
889 }
890 
891 
892 /*
893 ** ensure that stack[idx][fname] has a table and push that table
894 ** into the stack
895 */
896 LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
897   if (lua_getfield(L, idx, fname) == LUA_TTABLE)
898     return 1;  /* table already there */
899   else {
900     lua_pop(L, 1);  /* remove previous result */
901     idx = lua_absindex(L, idx);
902     lua_newtable(L);
903     lua_pushvalue(L, -1);  /* copy to be left at top */
904     lua_setfield(L, idx, fname);  /* assign new table to field */
905     return 0;  /* false, because did not find table there */
906   }
907 }
908 
909 
910 /*
911 ** stripped-down 'require'. Calls 'openf' to open a module,
912 ** registers the result in 'package.loaded' table and, if 'glb'
913 ** is true, also registers the result in the global table.
914 ** Leaves resulting module on the top.
915 */
916 LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
917                                lua_CFunction openf, int glb) {
918   lua_pushcfunction(L, openf);
919   lua_pushstring(L, modname);  /* argument to open function */
920   lua_call(L, 1, 1);  /* open module */
921   luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
922   lua_pushvalue(L, -2);  /* make copy of module (call result) */
923   lua_setfield(L, -2, modname);  /* _LOADED[modname] = module */
924   lua_pop(L, 1);  /* remove _LOADED table */
925   if (glb) {
926     lua_pushvalue(L, -1);  /* copy of 'mod' */
927     lua_setglobal(L, modname);  /* _G[modname] = module */
928   }
929 }
930 
931 
932 LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
933                                                                const char *r) {
934   const char *wild;
935   size_t l = strlen(p);
936   luaL_Buffer b;
937   luaL_buffinit(L, &b);
938   while ((wild = strstr(s, p)) != NULL) {
939     luaL_addlstring(&b, s, wild - s);  /* push prefix */
940     luaL_addstring(&b, r);  /* push replacement in place of pattern */
941     s = wild + l;  /* continue after `p' */
942   }
943   luaL_addstring(&b, s);  /* push last suffix */
944   luaL_pushresult(&b);
945   return lua_tostring(L, -1);
946 }
947 
948 
949 #ifndef _KERNEL
950 static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
951   (void)ud; (void)osize;  /* not used */
952   if (nsize == 0) {
953     free(ptr);
954     return NULL;
955   }
956   else
957     return realloc(ptr, nsize);
958 }
959 
960 
961 static int panic (lua_State *L) {
962   luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
963                    lua_tostring(L, -1));
964   return 0;  /* return to Lua to abort */
965 }
966 
967 
968 LUALIB_API lua_State *luaL_newstate (void) {
969   lua_State *L = lua_newstate(l_alloc, NULL);
970   if (L) lua_atpanic(L, &panic);
971   return L;
972 }
973 #endif
974 
975 
976 LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
977   const lua_Number *v = lua_version(L);
978   if (v != lua_version(NULL))
979     luaL_error(L, "multiple Lua VMs detected");
980   else if (*v != ver)
981     luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
982                   ver, *v);
983   /* check numeric types */
984   if (sz != LUAL_NUMSIZES)
985     luaL_error(L, "core and library have incompatible numeric types");
986 }
987 
988