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