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