source: trunk/src/lua/lauxlib.c @ 2540

Last change on this file since 2540 was 2540, checked in by sam, 10 years ago

core: import pristine lua 5.2.1 in the engine code.

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