1/*	$NetBSD: lauxlib.c,v 1.13 2023/06/08 21:12:08 nikita Exp $	*/
2
3/*
4** Id: lauxlib.c
5** Auxiliary functions for building Lua libraries
6** See Copyright Notice in lua.h
7*/
8
9#define lauxlib_c
10#define LUA_LIB
11
12#include "lprefix.h"
13
14
15#ifndef _KERNEL
16#include <errno.h>
17#endif /* _KERNEL */
18#include <stdarg.h>
19#ifndef _KERNEL
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#endif /* _KERNEL */
24
25
26/*
27** This file uses only the official API of Lua.
28** Any function declared here could be written as an application function.
29*/
30
31#include "lua.h"
32
33#include "lauxlib.h"
34
35
36#if !defined(MAX_SIZET)
37/* maximum value for size_t */
38#define MAX_SIZET	((size_t)(~(size_t)0))
39#endif
40
41
42/*
43** {======================================================
44** Traceback
45** =======================================================
46*/
47
48
49#define LEVELS1	10	/* size of the first part of the stack */
50#define LEVELS2	11	/* size of the second part of the stack */
51
52
53
54/*
55** Search for 'objidx' in table at index -1. ('objidx' must be an
56** absolute index.) Return 1 + string at top if it found a good name.
57*/
58static int findfield (lua_State *L, int objidx, int level) {
59  if (level == 0 || !lua_istable(L, -1))
60    return 0;  /* not found */
61  lua_pushnil(L);  /* start 'next' loop */
62  while (lua_next(L, -2)) {  /* for each pair in table */
63    if (lua_type(L, -2) == LUA_TSTRING) {  /* ignore non-string keys */
64      if (lua_rawequal(L, objidx, -1)) {  /* found object? */
65        lua_pop(L, 1);  /* remove value (but keep name) */
66        return 1;
67      }
68      else if (findfield(L, objidx, level - 1)) {  /* try recursively */
69        /* stack: lib_name, lib_table, field_name (top) */
70        lua_pushliteral(L, ".");  /* place '.' between the two names */
71        lua_replace(L, -3);  /* (in the slot occupied by table) */
72        lua_concat(L, 3);  /* lib_name.field_name */
73        return 1;
74      }
75    }
76    lua_pop(L, 1);  /* remove value */
77  }
78  return 0;  /* not found */
79}
80
81
82/*
83** Search for a name for a function in all loaded modules
84*/
85static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
86  int top = lua_gettop(L);
87  lua_getinfo(L, "f", ar);  /* push function */
88  lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
89  if (findfield(L, top + 1, 2)) {
90    const char *name = lua_tostring(L, -1);
91    if (strncmp(name, LUA_GNAME ".", 3) == 0) {  /* name start with '_G.'? */
92      lua_pushstring(L, name + 3);  /* push name without prefix */
93      lua_remove(L, -2);  /* remove original name */
94    }
95    lua_copy(L, -1, top + 1);  /* copy name to proper place */
96    lua_settop(L, top + 1);  /* remove table "loaded" and name copy */
97    return 1;
98  }
99  else {
100    lua_settop(L, top);  /* remove function and global table */
101    return 0;
102  }
103}
104
105
106static void pushfuncname (lua_State *L, lua_Debug *ar) {
107  if (pushglobalfuncname(L, ar)) {  /* try first a global name */
108    lua_pushfstring(L, "function '%s'", lua_tostring(L, -1));
109    lua_remove(L, -2);  /* remove name */
110  }
111  else if (*ar->namewhat != '\0')  /* is there a name from code? */
112    lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name);  /* use it */
113  else if (*ar->what == 'm')  /* main? */
114      lua_pushliteral(L, "main chunk");
115  else if (*ar->what != 'C')  /* for Lua functions, use <file:line> */
116    lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
117  else  /* nothing left... */
118    lua_pushliteral(L, "?");
119}
120
121
122static int lastlevel (lua_State *L) {
123  lua_Debug ar;
124  int li = 1, le = 1;
125  /* find an upper bound */
126  while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
127  /* do a binary search */
128  while (li < le) {
129    int m = (li + le)/2;
130    if (lua_getstack(L, m, &ar)) li = m + 1;
131    else le = m;
132  }
133  return le - 1;
134}
135
136
137LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1,
138                                const char *msg, int level) {
139  luaL_Buffer b;
140  lua_Debug ar;
141  int last = lastlevel(L1);
142  int limit2show = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1;
143  luaL_buffinit(L, &b);
144  if (msg) {
145    luaL_addstring(&b, msg);
146    luaL_addchar(&b, '\n');
147  }
148  luaL_addstring(&b, "stack traceback:");
149  while (lua_getstack(L1, level++, &ar)) {
150    if (limit2show-- == 0) {  /* too many levels? */
151      int n = last - level - LEVELS2 + 1;  /* number of levels to skip */
152      lua_pushfstring(L, "\n\t...\t(skipping %d levels)", n);
153      luaL_addvalue(&b);  /* add warning about skip */
154      level += n;  /* and skip to last levels */
155    }
156    else {
157      lua_getinfo(L1, "Slnt", &ar);
158      if (ar.currentline <= 0)
159        lua_pushfstring(L, "\n\t%s: in ", ar.short_src);
160      else
161        lua_pushfstring(L, "\n\t%s:%d: in ", ar.short_src, ar.currentline);
162      luaL_addvalue(&b);
163      pushfuncname(L, &ar);
164      luaL_addvalue(&b);
165      if (ar.istailcall)
166        luaL_addstring(&b, "\n\t(...tail calls...)");
167    }
168  }
169  luaL_pushresult(&b);
170}
171
172/* }====================================================== */
173
174
175/*
176** {======================================================
177** Error-report functions
178** =======================================================
179*/
180
181LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
182  lua_Debug ar;
183  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */
184    return luaL_error(L, "bad argument #%d (%s)", arg, extramsg);
185  lua_getinfo(L, "n", &ar);
186  if (strcmp(ar.namewhat, "method") == 0) {
187    arg--;  /* do not count 'self' */
188    if (arg == 0)  /* error is in the self argument itself? */
189      return luaL_error(L, "calling '%s' on bad self (%s)",
190                           ar.name, extramsg);
191  }
192  if (ar.name == NULL)
193    ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?";
194  return luaL_error(L, "bad argument #%d to '%s' (%s)",
195                        arg, ar.name, extramsg);
196}
197
198
199LUALIB_API int luaL_typeerror (lua_State *L, int arg, const char *tname) {
200  const char *msg;
201  const char *typearg;  /* name for the type of the actual argument */
202  if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING)
203    typearg = lua_tostring(L, -1);  /* use the given type name */
204  else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA)
205    typearg = "light userdata";  /* special name for messages */
206  else
207    typearg = luaL_typename(L, arg);  /* standard name */
208  msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg);
209  return luaL_argerror(L, arg, msg);
210}
211
212
213static void tag_error (lua_State *L, int arg, int tag) {
214  luaL_typeerror(L, arg, lua_typename(L, tag));
215}
216
217
218/*
219** The use of 'lua_pushfstring' ensures this function does not
220** need reserved stack space when called.
221*/
222LUALIB_API void luaL_where (lua_State *L, int level) {
223  lua_Debug ar;
224  if (lua_getstack(L, level, &ar)) {  /* check function at level */
225    lua_getinfo(L, "Sl", &ar);  /* get info about it */
226    if (ar.currentline > 0) {  /* is there info? */
227      lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
228      return;
229    }
230  }
231  lua_pushfstring(L, "");  /* else, no information available... */
232}
233
234
235/*
236** Again, the use of 'lua_pushvfstring' ensures this function does
237** not need reserved stack space when called. (At worst, it generates
238** an error with "stack overflow" instead of the given message.)
239*/
240LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
241  va_list argp;
242  va_start(argp, fmt);
243  luaL_where(L, 1);
244  lua_pushvfstring(L, fmt, argp);
245  va_end(argp);
246  lua_concat(L, 2);
247  return lua_error(L);
248}
249
250
251#ifndef _KERNEL
252LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
253  int en = errno;  /* calls to Lua API may change this value */
254  if (stat) {
255    lua_pushboolean(L, 1);
256    return 1;
257  }
258  else {
259    luaL_pushfail(L);
260    if (fname)
261      lua_pushfstring(L, "%s: %s", fname, strerror(en));
262    else
263      lua_pushstring(L, strerror(en));
264    lua_pushinteger(L, en);
265    return 3;
266  }
267}
268#endif /* _KERNEL */
269
270
271#if !defined(l_inspectstat)	/* { */
272
273#if defined(LUA_USE_POSIX)
274
275#include <sys/wait.h>
276
277/*
278** use appropriate macros to interpret 'pclose' return status
279*/
280#define l_inspectstat(stat,what)  \
281   if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
282   else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
283
284#else
285
286#define l_inspectstat(stat,what)  /* no op */
287
288#endif
289
290#endif				/* } */
291
292
293#ifndef _KERNEL
294LUALIB_API int luaL_execresult (lua_State *L, int stat) {
295  if (stat != 0 && errno != 0)  /* error with an 'errno'? */
296    return luaL_fileresult(L, 0, NULL);
297  else {
298    const char *what = "exit";  /* type of termination */
299    l_inspectstat(stat, what);  /* interpret result */
300    if (*what == 'e' && stat == 0)  /* successful termination? */
301      lua_pushboolean(L, 1);
302    else
303      luaL_pushfail(L);
304    lua_pushstring(L, what);
305    lua_pushinteger(L, stat);
306    return 3;  /* return true/fail,what,code */
307  }
308}
309#endif /* _KERNEL */
310
311/* }====================================================== */
312
313
314
315/*
316** {======================================================
317** Userdata's metatable manipulation
318** =======================================================
319*/
320
321LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
322  if (luaL_getmetatable(L, tname) != LUA_TNIL)  /* name already in use? */
323    return 0;  /* leave previous value on top, but return 0 */
324  lua_pop(L, 1);
325  lua_createtable(L, 0, 2);  /* create metatable */
326  lua_pushstring(L, tname);
327  lua_setfield(L, -2, "__name");  /* metatable.__name = tname */
328  lua_pushvalue(L, -1);
329  lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */
330  return 1;
331}
332
333
334LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
335  luaL_getmetatable(L, tname);
336  lua_setmetatable(L, -2);
337}
338
339
340LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
341  void *p = lua_touserdata(L, ud);
342  if (p != NULL) {  /* value is a userdata? */
343    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */
344      luaL_getmetatable(L, tname);  /* get correct metatable */
345      if (!lua_rawequal(L, -1, -2))  /* not the same? */
346        p = NULL;  /* value is a userdata with wrong metatable */
347      lua_pop(L, 2);  /* remove both metatables */
348      return p;
349    }
350  }
351  return NULL;  /* value is not a userdata with a metatable */
352}
353
354
355LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
356  void *p = luaL_testudata(L, ud, tname);
357  luaL_argexpected(L, p != NULL, ud, tname);
358  return p;
359}
360
361/* }====================================================== */
362
363
364/*
365** {======================================================
366** Argument check functions
367** =======================================================
368*/
369
370LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
371                                 const char *const lst[]) {
372  const char *name = (def) ? luaL_optstring(L, arg, def) :
373                             luaL_checkstring(L, arg);
374  int i;
375  for (i=0; lst[i]; i++)
376    if (strcmp(lst[i], name) == 0)
377      return i;
378  return luaL_argerror(L, arg,
379                       lua_pushfstring(L, "invalid option '%s'", name));
380}
381
382
383/*
384** Ensures the stack has at least 'space' extra slots, raising an error
385** if it cannot fulfill the request. (The error handling needs a few
386** extra slots to format the error message. In case of an error without
387** this extra space, Lua will generate the same 'stack overflow' error,
388** but without 'msg'.)
389*/
390LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
391  if (l_unlikely(!lua_checkstack(L, space))) {
392    if (msg)
393      luaL_error(L, "stack overflow (%s)", msg);
394    else
395      luaL_error(L, "stack overflow");
396  }
397}
398
399
400LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) {
401  if (l_unlikely(lua_type(L, arg) != t))
402    tag_error(L, arg, t);
403}
404
405
406LUALIB_API void luaL_checkany (lua_State *L, int arg) {
407  if (l_unlikely(lua_type(L, arg) == LUA_TNONE))
408    luaL_argerror(L, arg, "value expected");
409}
410
411
412LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) {
413  const char *s = lua_tolstring(L, arg, len);
414  if (l_unlikely(!s)) tag_error(L, arg, LUA_TSTRING);
415  return s;
416}
417
418
419LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
420                                        const char *def, size_t *len) {
421  if (lua_isnoneornil(L, arg)) {
422    if (len)
423      *len = (def ? strlen(def) : 0);
424    return def;
425  }
426  else return luaL_checklstring(L, arg, len);
427}
428
429
430LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) {
431  int isnum;
432  lua_Number d = lua_tonumberx(L, arg, &isnum);
433  if (l_unlikely(!isnum))
434    tag_error(L, arg, LUA_TNUMBER);
435  return d;
436}
437
438
439LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) {
440  return luaL_opt(L, luaL_checknumber, arg, def);
441}
442
443
444#ifndef _KERNEL
445static void interror (lua_State *L, int arg) {
446  if (lua_isnumber(L, arg))
447    luaL_argerror(L, arg, "number has no integer representation");
448  else
449    tag_error(L, arg, LUA_TNUMBER);
450}
451
452
453LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) {
454  int isnum;
455  lua_Integer d = lua_tointegerx(L, arg, &isnum);
456  if (l_unlikely(!isnum)) {
457    interror(L, arg);
458  }
459  return d;
460}
461
462
463LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
464                                                      lua_Integer def) {
465  return luaL_opt(L, luaL_checkinteger, arg, def);
466}
467#endif /* _KERNEL */
468
469/* }====================================================== */
470
471
472/*
473** {======================================================
474** Generic Buffer manipulation
475** =======================================================
476*/
477
478/* userdata to box arbitrary data */
479typedef struct UBox {
480  void *box;
481  size_t bsize;
482} UBox;
483
484
485static void *resizebox (lua_State *L, int idx, size_t newsize) {
486  void *ud;
487  lua_Alloc allocf = lua_getallocf(L, &ud);
488  UBox *box = (UBox *)lua_touserdata(L, idx);
489  void *temp = allocf(ud, box->box, box->bsize, newsize);
490  if (l_unlikely(temp == NULL && newsize > 0)) {  /* allocation error? */
491    lua_pushliteral(L, "not enough memory");
492    lua_error(L);  /* raise a memory error */
493  }
494  box->box = temp;
495  box->bsize = newsize;
496  return temp;
497}
498
499
500static int boxgc (lua_State *L) {
501  resizebox(L, 1, 0);
502  return 0;
503}
504
505
506static const luaL_Reg boxmt[] = {  /* box metamethods */
507  {"__gc", boxgc},
508  {"__close", boxgc},
509  {NULL, NULL}
510};
511
512
513static void newbox (lua_State *L) {
514  UBox *box = (UBox *)lua_newuserdatauv(L, sizeof(UBox), 0);
515  box->box = NULL;
516  box->bsize = 0;
517  if (luaL_newmetatable(L, "_UBOX*"))  /* creating metatable? */
518    luaL_setfuncs(L, boxmt, 0);  /* set its metamethods */
519  lua_setmetatable(L, -2);
520}
521
522
523/*
524** check whether buffer is using a userdata on the stack as a temporary
525** buffer
526*/
527#define buffonstack(B)	((B)->b != (B)->init.b)
528
529
530/*
531** Whenever buffer is accessed, slot 'idx' must either be a box (which
532** cannot be NULL) or it is a placeholder for the buffer.
533*/
534#define checkbufferlevel(B,idx)  \
535  lua_assert(buffonstack(B) ? lua_touserdata(B->L, idx) != NULL  \
536                            : lua_touserdata(B->L, idx) == (void*)B)
537
538
539/*
540** Compute new size for buffer 'B', enough to accommodate extra 'sz'
541** bytes. (The test for "not big enough" also gets the case when the
542** computation of 'newsize' overflows.)
543*/
544static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
545  size_t newsize = (B->size / 2) * 3;  /* buffer size * 1.5 */
546  if (l_unlikely(MAX_SIZET - sz < B->n))  /* overflow in (B->n + sz)? */
547    return luaL_error(B->L, "buffer too large");
548  if (newsize < B->n + sz)  /* not big enough? */
549    newsize = B->n + sz;
550  return newsize;
551}
552
553
554/*
555** Returns a pointer to a free area with at least 'sz' bytes in buffer
556** 'B'. 'boxidx' is the relative position in the stack where is the
557** buffer's box or its placeholder.
558*/
559static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
560  checkbufferlevel(B, boxidx);
561  if (B->size - B->n >= sz)  /* enough space? */
562    return B->b + B->n;
563  else {
564    lua_State *L = B->L;
565    char *newbuff;
566    size_t newsize = newbuffsize(B, sz);
567    /* create larger buffer */
568    if (buffonstack(B))  /* buffer already has a box? */
569      newbuff = (char *)resizebox(L, boxidx, newsize);  /* resize it */
570    else {  /* no box yet */
571      lua_remove(L, boxidx);  /* remove placeholder */
572      newbox(L);  /* create a new box */
573      lua_insert(L, boxidx);  /* move box to its intended position */
574      lua_toclose(L, boxidx);
575      newbuff = (char *)resizebox(L, boxidx, newsize);
576      memcpy(newbuff, B->b, B->n * sizeof(char));  /* copy original content */
577    }
578    B->b = newbuff;
579    B->size = newsize;
580    return newbuff + B->n;
581  }
582}
583
584/*
585** returns a pointer to a free area with at least 'sz' bytes
586*/
587LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
588  return prepbuffsize(B, sz, -1);
589}
590
591
592LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
593  if (l > 0) {  /* avoid 'memcpy' when 's' can be NULL */
594    char *b = prepbuffsize(B, l, -1);
595    memcpy(b, s, l * sizeof(char));
596    luaL_addsize(B, l);
597  }
598}
599
600
601LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
602  luaL_addlstring(B, s, strlen(s));
603}
604
605
606LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
607  lua_State *L = B->L;
608  checkbufferlevel(B, -1);
609  lua_pushlstring(L, B->b, B->n);
610  if (buffonstack(B))
611    lua_closeslot(L, -2);  /* close the box */
612  lua_remove(L, -2);  /* remove box or placeholder from the stack */
613}
614
615
616LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
617  luaL_addsize(B, sz);
618  luaL_pushresult(B);
619}
620
621
622/*
623** 'luaL_addvalue' is the only function in the Buffer system where the
624** box (if existent) is not on the top of the stack. So, instead of
625** calling 'luaL_addlstring', it replicates the code using -2 as the
626** last argument to 'prepbuffsize', signaling that the box is (or will
627** be) below the string being added to the buffer. (Box creation can
628** trigger an emergency GC, so we should not remove the string from the
629** stack before we have the space guaranteed.)
630*/
631LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
632  lua_State *L = B->L;
633  size_t len;
634  const char *s = lua_tolstring(L, -1, &len);
635  char *b = prepbuffsize(B, len, -2);
636  memcpy(b, s, len * sizeof(char));
637  luaL_addsize(B, len);
638  lua_pop(L, 1);  /* pop string */
639}
640
641
642LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
643  B->L = L;
644  B->b = B->init.b;
645  B->n = 0;
646  B->size = LUAL_BUFFERSIZE;
647  lua_pushlightuserdata(L, (void*)B);  /* push placeholder */
648}
649
650
651LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
652  luaL_buffinit(L, B);
653  return prepbuffsize(B, sz, -1);
654}
655
656/* }====================================================== */
657
658
659/*
660** {======================================================
661** Reference system
662** =======================================================
663*/
664
665/* index of free-list header (after the predefined values) */
666#define freelist	(LUA_RIDX_LAST + 1)
667
668/*
669** The previously freed references form a linked list:
670** t[freelist] is the index of a first free index, or zero if list is
671** empty; t[t[freelist]] is the index of the second element; etc.
672*/
673LUALIB_API int luaL_ref (lua_State *L, int t) {
674  int ref;
675  if (lua_isnil(L, -1)) {
676    lua_pop(L, 1);  /* remove from stack */
677    return LUA_REFNIL;  /* 'nil' has a unique fixed reference */
678  }
679  t = lua_absindex(L, t);
680  if (lua_rawgeti(L, t, freelist) == LUA_TNIL) {  /* first access? */
681    ref = 0;  /* list is empty */
682    lua_pushinteger(L, 0);  /* initialize as an empty list */
683    lua_rawseti(L, t, freelist);  /* ref = t[freelist] = 0 */
684  }
685  else {  /* already initialized */
686    lua_assert(lua_isinteger(L, -1));
687    ref = (int)lua_tointeger(L, -1);  /* ref = t[freelist] */
688  }
689  lua_pop(L, 1);  /* remove element from stack */
690  if (ref != 0) {  /* any free element? */
691    lua_rawgeti(L, t, ref);  /* remove it from list */
692    lua_rawseti(L, t, freelist);  /* (t[freelist] = t[ref]) */
693  }
694  else  /* no free elements */
695    ref = (int)lua_rawlen(L, t) + 1;  /* get a new reference */
696  lua_rawseti(L, t, ref);
697  return ref;
698}
699
700
701LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
702  if (ref >= 0) {
703    t = lua_absindex(L, t);
704    lua_rawgeti(L, t, freelist);
705    lua_assert(lua_isinteger(L, -1));
706    lua_rawseti(L, t, ref);  /* t[ref] = t[freelist] */
707    lua_pushinteger(L, ref);
708    lua_rawseti(L, t, freelist);  /* t[freelist] = ref */
709  }
710}
711
712/* }====================================================== */
713
714
715/*
716** {======================================================
717** Load functions
718** =======================================================
719*/
720
721#ifndef _KERNEL
722typedef struct LoadF {
723  int n;  /* number of pre-read characters */
724  FILE *f;  /* file being read */
725  char buff[BUFSIZ];  /* area for reading file */
726} LoadF;
727
728
729static const char *getF (lua_State *L, void *ud, size_t *size) {
730  LoadF *lf = (LoadF *)ud;
731  (void)L;  /* not used */
732  if (lf->n > 0) {  /* are there pre-read characters to be read? */
733    *size = lf->n;  /* return them (chars already in buffer) */
734    lf->n = 0;  /* no more pre-read characters */
735  }
736  else {  /* read a block from file */
737    /* 'fread' can return > 0 *and* set the EOF flag. If next call to
738       'getF' called 'fread', it might still wait for user input.
739       The next check avoids this problem. */
740    if (feof(lf->f)) return NULL;
741    *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);  /* read block */
742  }
743  return lf->buff;
744}
745
746
747static int errfile (lua_State *L, const char *what, int fnameindex) {
748  const char *serr = strerror(errno);
749  const char *filename = lua_tostring(L, fnameindex) + 1;
750  lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
751  lua_remove(L, fnameindex);
752  return LUA_ERRFILE;
753}
754
755
756/*
757** Skip an optional BOM at the start of a stream. If there is an
758** incomplete BOM (the first character is correct but the rest is
759** not), returns the first character anyway to force an error
760** (as no chunk can start with 0xEF).
761*/
762static int skipBOM (FILE *f) {
763  int c = getc(f);  /* read first character */
764  if (c == 0xEF && getc(f) == 0xBB && getc(f) == 0xBF)  /* correct BOM? */
765    return getc(f);  /* ignore BOM and return next char */
766  else  /* no (valid) BOM */
767    return c;  /* return first character */
768}
769
770
771/*
772** reads the first character of file 'f' and skips an optional BOM mark
773** in its beginning plus its first line if it starts with '#'. Returns
774** true if it skipped the first line.  In any case, '*cp' has the
775** first "valid" character of the file (after the optional BOM and
776** a first-line comment).
777*/
778static int skipcomment (FILE *f, int *cp) {
779  int c = *cp = skipBOM(f);
780  if (c == '#') {  /* first line is a comment (Unix exec. file)? */
781    do {  /* skip first line */
782      c = getc(f);
783    } while (c != EOF && c != '\n');
784    *cp = getc(f);  /* next character after comment, if present */
785    return 1;  /* there was a comment */
786  }
787  else return 0;  /* no comment */
788}
789
790
791LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
792                                             const char *mode) {
793  LoadF lf;
794  int status, readstatus;
795  int c;
796  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
797  if (filename == NULL) {
798    lua_pushliteral(L, "=stdin");
799    lf.f = stdin;
800  }
801  else {
802    lua_pushfstring(L, "@%s", filename);
803    lf.f = fopen(filename, "r");
804    if (lf.f == NULL) return errfile(L, "open", fnameindex);
805  }
806  lf.n = 0;
807  if (skipcomment(lf.f, &c))  /* read initial portion */
808    lf.buff[lf.n++] = '\n';  /* add newline to correct line numbers */
809  if (c == LUA_SIGNATURE[0]) {  /* binary file? */
810    lf.n = 0;  /* remove possible newline */
811    if (filename) {  /* "real" file? */
812      lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
813      if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
814      skipcomment(lf.f, &c);  /* re-read initial portion */
815    }
816  }
817  if (c != EOF)
818    lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
819  status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
820  readstatus = ferror(lf.f);
821  if (filename) fclose(lf.f);  /* close file (even in case of errors) */
822  if (readstatus) {
823    lua_settop(L, fnameindex);  /* ignore results from 'lua_load' */
824    return errfile(L, "read", fnameindex);
825  }
826  lua_remove(L, fnameindex);
827  return status;
828}
829#endif /* _KERNEL */
830
831
832typedef struct LoadS {
833  const char *s;
834  size_t size;
835} LoadS;
836
837
838static const char *getS (lua_State *L, void *ud, size_t *size) {
839  LoadS *ls = (LoadS *)ud;
840  (void)L;  /* not used */
841  if (ls->size == 0) return NULL;
842  *size = ls->size;
843  ls->size = 0;
844  return ls->s;
845}
846
847
848LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
849                                 const char *name, const char *mode) {
850  LoadS ls;
851  ls.s = buff;
852  ls.size = size;
853  return lua_load(L, getS, &ls, name, mode);
854}
855
856
857LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
858  return luaL_loadbuffer(L, s, strlen(s), s);
859}
860
861/* }====================================================== */
862
863
864
865LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
866  if (!lua_getmetatable(L, obj))  /* no metatable? */
867    return LUA_TNIL;
868  else {
869    int tt;
870    lua_pushstring(L, event);
871    tt = lua_rawget(L, -2);
872    if (tt == LUA_TNIL)  /* is metafield nil? */
873      lua_pop(L, 2);  /* remove metatable and metafield */
874    else
875      lua_remove(L, -2);  /* remove only metatable */
876    return tt;  /* return metafield type */
877  }
878}
879
880
881LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
882  obj = lua_absindex(L, obj);
883  if (luaL_getmetafield(L, obj, event) == LUA_TNIL)  /* no metafield? */
884    return 0;
885  lua_pushvalue(L, obj);
886  lua_call(L, 1, 1);
887  return 1;
888}
889
890
891LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
892  lua_Integer l;
893  int isnum;
894  lua_len(L, idx);
895  l = lua_tointegerx(L, -1, &isnum);
896  if (l_unlikely(!isnum))
897    luaL_error(L, "object length is not an integer");
898  lua_pop(L, 1);  /* remove object */
899  return l;
900}
901
902
903LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
904  idx = lua_absindex(L,idx);
905  if (luaL_callmeta(L, idx, "__tostring")) {  /* metafield? */
906    if (!lua_isstring(L, -1))
907      luaL_error(L, "'__tostring' must return a string");
908  }
909  else {
910    switch (lua_type(L, idx)) {
911      case LUA_TNUMBER: {
912#ifndef _KERNEL
913        if (lua_isinteger(L, idx))
914#endif
915          lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx));
916#ifndef _KERNEL
917        else
918          lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx));
919#endif
920        break;
921      }
922      case LUA_TSTRING:
923        lua_pushvalue(L, idx);
924        break;
925      case LUA_TBOOLEAN:
926        lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
927        break;
928      case LUA_TNIL:
929        lua_pushliteral(L, "nil");
930        break;
931      default: {
932        int tt = luaL_getmetafield(L, idx, "__name");  /* try name */
933        const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) :
934                                                 luaL_typename(L, idx);
935        lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx));
936        if (tt != LUA_TNIL)
937          lua_remove(L, -2);  /* remove '__name' */
938        break;
939      }
940    }
941  }
942  return lua_tolstring(L, -1, len);
943}
944
945
946/*
947** set functions from list 'l' into table at top - 'nup'; each
948** function gets the 'nup' elements at the top as upvalues.
949** Returns with only the table at the stack.
950*/
951LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
952  luaL_checkstack(L, nup, "too many upvalues");
953  for (; l->name != NULL; l++) {  /* fill the table with given functions */
954    if (l->func == NULL)  /* place holder? */
955      lua_pushboolean(L, 0);
956    else {
957      int i;
958      for (i = 0; i < nup; i++)  /* copy upvalues to the top */
959        lua_pushvalue(L, -nup);
960      lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
961    }
962    lua_setfield(L, -(nup + 2), l->name);
963  }
964  lua_pop(L, nup);  /* remove upvalues */
965}
966
967
968/*
969** ensure that stack[idx][fname] has a table and push that table
970** into the stack
971*/
972LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
973  if (lua_getfield(L, idx, fname) == LUA_TTABLE)
974    return 1;  /* table already there */
975  else {
976    lua_pop(L, 1);  /* remove previous result */
977    idx = lua_absindex(L, idx);
978    lua_newtable(L);
979    lua_pushvalue(L, -1);  /* copy to be left at top */
980    lua_setfield(L, idx, fname);  /* assign new table to field */
981    return 0;  /* false, because did not find table there */
982  }
983}
984
985
986/*
987** Stripped-down 'require': After checking "loaded" table, calls 'openf'
988** to open a module, registers the result in 'package.loaded' table and,
989** if 'glb' is true, also registers the result in the global table.
990** Leaves resulting module on the top.
991*/
992LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
993                               lua_CFunction openf, int glb) {
994  luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
995  lua_getfield(L, -1, modname);  /* LOADED[modname] */
996  if (!lua_toboolean(L, -1)) {  /* package not already loaded? */
997    lua_pop(L, 1);  /* remove field */
998    lua_pushcfunction(L, openf);
999    lua_pushstring(L, modname);  /* argument to open function */
1000    lua_call(L, 1, 1);  /* call 'openf' to open module */
1001    lua_pushvalue(L, -1);  /* make copy of module (call result) */
1002    lua_setfield(L, -3, modname);  /* LOADED[modname] = module */
1003  }
1004  lua_remove(L, -2);  /* remove LOADED table */
1005  if (glb) {
1006    lua_pushvalue(L, -1);  /* copy of module */
1007    lua_setglobal(L, modname);  /* _G[modname] = module */
1008  }
1009}
1010
1011
1012LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s,
1013                                     const char *p, const char *r) {
1014  const char *wild;
1015  size_t l = strlen(p);
1016  while ((wild = strstr(s, p)) != NULL) {
1017    luaL_addlstring(b, s, wild - s);  /* push prefix */
1018    luaL_addstring(b, r);  /* push replacement in place of pattern */
1019    s = wild + l;  /* continue after 'p' */
1020  }
1021  luaL_addstring(b, s);  /* push last suffix */
1022}
1023
1024
1025LUALIB_API const char *luaL_gsub (lua_State *L, const char *s,
1026                                  const char *p, const char *r) {
1027  luaL_Buffer b;
1028  luaL_buffinit(L, &b);
1029  luaL_addgsub(&b, s, p, r);
1030  luaL_pushresult(&b);
1031  return lua_tostring(L, -1);
1032}
1033
1034
1035#ifndef _KERNEL
1036static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
1037  (void)ud; (void)osize;  /* not used */
1038  if (nsize == 0) {
1039    free(ptr);
1040    return NULL;
1041  }
1042  else
1043    return realloc(ptr, nsize);
1044}
1045
1046
1047static int panic (lua_State *L) {
1048  const char *msg = lua_tostring(L, -1);
1049  if (msg == NULL) msg = "error object is not a string";
1050  lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
1051                        msg);
1052  return 0;  /* return to Lua to abort */
1053}
1054
1055
1056/*
1057** Warning functions:
1058** warnfoff: warning system is off
1059** warnfon: ready to start a new message
1060** warnfcont: previous message is to be continued
1061*/
1062static void warnfoff (void *ud, const char *message, int tocont);
1063static void warnfon (void *ud, const char *message, int tocont);
1064static void warnfcont (void *ud, const char *message, int tocont);
1065
1066
1067/*
1068** Check whether message is a control message. If so, execute the
1069** control or ignore it if unknown.
1070*/
1071static int checkcontrol (lua_State *L, const char *message, int tocont) {
1072  if (tocont || *(message++) != '@')  /* not a control message? */
1073    return 0;
1074  else {
1075    if (strcmp(message, "off") == 0)
1076      lua_setwarnf(L, warnfoff, L);  /* turn warnings off */
1077    else if (strcmp(message, "on") == 0)
1078      lua_setwarnf(L, warnfon, L);   /* turn warnings on */
1079    return 1;  /* it was a control message */
1080  }
1081}
1082
1083
1084static void warnfoff (void *ud, const char *message, int tocont) {
1085  checkcontrol((lua_State *)ud, message, tocont);
1086}
1087
1088
1089/*
1090** Writes the message and handle 'tocont', finishing the message
1091** if needed and setting the next warn function.
1092*/
1093static void warnfcont (void *ud, const char *message, int tocont) {
1094  lua_State *L = (lua_State *)ud;
1095  lua_writestringerror("%s", message);  /* write message */
1096  if (tocont)  /* not the last part? */
1097    lua_setwarnf(L, warnfcont, L);  /* to be continued */
1098  else {  /* last part */
1099    lua_writestringerror("%s", "\n");  /* finish message with end-of-line */
1100    lua_setwarnf(L, warnfon, L);  /* next call is a new message */
1101  }
1102}
1103
1104
1105static void warnfon (void *ud, const char *message, int tocont) {
1106  if (checkcontrol((lua_State *)ud, message, tocont))  /* control message? */
1107    return;  /* nothing else to be done */
1108  lua_writestringerror("%s", "Lua warning: ");  /* start a new warning */
1109  warnfcont(ud, message, tocont);  /* finish processing */
1110}
1111
1112
1113LUALIB_API lua_State *luaL_newstate (void) {
1114  lua_State *L = lua_newstate(l_alloc, NULL);
1115  if (l_likely(L)) {
1116    lua_atpanic(L, &panic);
1117    lua_setwarnf(L, warnfoff, L);  /* default is warnings off */
1118  }
1119  return L;
1120}
1121#endif /* _KERNEL */
1122
1123
1124LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
1125  lua_Number v = lua_version(L);
1126  if (sz != LUAL_NUMSIZES)  /* check numeric types */
1127    luaL_error(L, "core and library have incompatible numeric types");
1128#ifndef _KERNEL
1129  else if (v != ver)
1130    luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
1131                  (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)v);
1132#endif
1133}
1134
1135