Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5205 clevermous 1
/*
2
** $Id: lauxlib.c,v 1.240 2011/12/06 16:33:55 roberto Exp $
3
** Auxiliary functions for building Lua libraries
4
** See Copyright Notice in lua.h
5
*/
6
 
7
 
8
#include 
9
#include 
10
#include 
11
#include 
12
#include 
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
*/
43
static 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
 
67
static 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
 
83
static 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
 
101
static 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
 
116
LUALIB_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
 
153
LUALIB_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
 
170
static 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
 
177
static void tag_error (lua_State *L, int narg, int tag) {
178
  typeerror(L, narg, lua_typename(L, tag));
179
}
180
 
181
 
182
LUALIB_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
 
195
LUALIB_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
 
206
LUALIB_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 
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
 
246
LUALIB_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
 
271
LUALIB_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
 
283
LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) {
284
  luaL_getmetatable(L, tname);
285
  lua_setmetatable(L, -2);
286
}
287
 
288
 
289
LUALIB_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
 
304
LUALIB_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
 
319
LUALIB_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
 
332
LUALIB_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
 
344
LUALIB_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
 
350
LUALIB_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
 
356
LUALIB_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
 
363
LUALIB_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
 
374
LUALIB_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
 
383
LUALIB_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
 
388
LUALIB_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
 
397
LUALIB_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
 
406
LUALIB_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
 
412
LUALIB_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
*/
436
LUALIB_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
 
458
LUALIB_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
 
465
LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
466
  luaL_addlstring(B, s, strlen(s));
467
}
468
 
469
 
470
LUALIB_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
 
478
LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) {
479
  luaL_addsize(B, sz);
480
  luaL_pushresult(B);
481
}
482
 
483
 
484
LUALIB_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
 
495
LUALIB_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
 
503
LUALIB_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
 
521
LUALIB_API int luaL_ref (lua_State *L, int t) {
522
  int ref;
523
  t = lua_absindex(L, t);
524
  if (lua_isnil(L, -1)) {
525
    lua_pop(L, 1);  /* remove from stack */
526
    return LUA_REFNIL;  /* `nil' has a unique fixed reference */
527
  }
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
 
542
LUALIB_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
 
561
typedef 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
 
568
static 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
 
586
static 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
 
595
static 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
*/
616
static int skipcomment (LoadF *lf, int *cp) {
617
  int c = *cp = skipBOM(lf);
618
  if (c == '#') {  /* first line is a comment (Unix exec. file)? */
619
    while ((c = getc(lf->f)) != EOF && c != '\n') ;  /* skip first line */
620
    *cp = getc(lf->f);  /* skip end-of-line */
621
    return 1;  /* there was a comment */
622
  }
623
  else return 0;  /* no comment */
624
}
625
 
626
 
627
LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
628
                                             const char *mode) {
629
  LoadF lf;
630
  int status, readstatus;
631
  int c;
632
  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
633
  if (filename == NULL) {
634
    lua_pushliteral(L, "=stdin");
635
    lf.f = stdin;
636
  }
637
  else {
638
    lua_pushfstring(L, "@%s", filename);
639
    lf.f = fopen(filename, "r");
640
    if (lf.f == NULL) return errfile(L, "open", fnameindex);
641
  }
642
  if (skipcomment(&lf, &c))  /* read initial portion */
643
    lf.buff[lf.n++] = '\n';  /* add line to correct line numbers */
644
  if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */
645
    lf.f = freopen(filename, "rb", lf.f);  /* reopen in binary mode */
646
    if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
647
    skipcomment(&lf, &c);  /* re-read initial portion */
648
  }
649
  if (c != EOF)
650
    lf.buff[lf.n++] = c;  /* 'c' is the first character of the stream */
651
  status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
652
  readstatus = ferror(lf.f);
653
  if (filename) fclose(lf.f);  /* close file (even in case of errors) */
654
  if (readstatus) {
655
    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
656
    return errfile(L, "read", fnameindex);
657
  }
658
  lua_remove(L, fnameindex);
659
  return status;
660
}
661
 
662
 
663
typedef struct LoadS {
664
  const char *s;
665
  size_t size;
666
} LoadS;
667
 
668
 
669
static const char *getS (lua_State *L, void *ud, size_t *size) {
670
  LoadS *ls = (LoadS *)ud;
671
  (void)L;  /* not used */
672
  if (ls->size == 0) return NULL;
673
  *size = ls->size;
674
  ls->size = 0;
675
  return ls->s;
676
}
677
 
678
 
679
LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
680
                                 const char *name, const char *mode) {
681
  LoadS ls;
682
  ls.s = buff;
683
  ls.size = size;
684
  return lua_load(L, getS, &ls, name, mode);
685
}
686
 
687
 
688
LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
689
  return luaL_loadbuffer(L, s, strlen(s), s);
690
}
691
 
692
/* }====================================================== */
693
 
694
 
695
 
696
LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
697
  if (!lua_getmetatable(L, obj))  /* no metatable? */
698
    return 0;
699
  lua_pushstring(L, event);
700
  lua_rawget(L, -2);
701
  if (lua_isnil(L, -1)) {
702
    lua_pop(L, 2);  /* remove metatable and metafield */
703
    return 0;
704
  }
705
  else {
706
    lua_remove(L, -2);  /* remove only metatable */
707
    return 1;
708
  }
709
}
710
 
711
 
712
LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
713
  obj = lua_absindex(L, obj);
714
  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */
715
    return 0;
716
  lua_pushvalue(L, obj);
717
  lua_call(L, 1, 1);
718
  return 1;
719
}
720
 
721
 
722
LUALIB_API int luaL_len (lua_State *L, int idx) {
723
  int l;
724
  int isnum;
725
  lua_len(L, idx);
726
  l = (int)lua_tointegerx(L, -1, &isnum);
727
  if (!isnum)
728
    luaL_error(L, "object length is not a number");
729
  lua_pop(L, 1);  /* remove object */
730
  return l;
731
}
732
 
733
 
734
LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
735
  if (!luaL_callmeta(L, idx, "__tostring")) {  /* no metafield? */
736
    switch (lua_type(L, idx)) {
737
      case LUA_TNUMBER:
738
      case LUA_TSTRING:
739
        lua_pushvalue(L, idx);
740
        break;
741
      case LUA_TBOOLEAN:
742
        lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
743
        break;
744
      case LUA_TNIL:
745
        lua_pushliteral(L, "nil");
746
        break;
747
      default:
748
        lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
749
                                            lua_topointer(L, idx));
750
        break;
751
    }
752
  }
753
  return lua_tolstring(L, -1, len);
754
}
755
 
756
 
757
/*
758
** {======================================================
759
** Compatibility with 5.1 module functions
760
** =======================================================
761
*/
762
#if defined(LUA_COMPAT_MODULE)
763
 
764
static const char *luaL_findtable (lua_State *L, int idx,
765
                                   const char *fname, int szhint) {
766
  const char *e;
767
  if (idx) lua_pushvalue(L, idx);
768
  do {
769
    e = strchr(fname, '.');
770
    if (e == NULL) e = fname + strlen(fname);
771
    lua_pushlstring(L, fname, e - fname);
772
    lua_rawget(L, -2);
773
    if (lua_isnil(L, -1)) {  /* no such field? */
774
      lua_pop(L, 1);  /* remove this nil */
775
      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
776
      lua_pushlstring(L, fname, e - fname);
777
      lua_pushvalue(L, -2);
778
      lua_settable(L, -4);  /* set new table into field */
779
    }
780
    else if (!lua_istable(L, -1)) {  /* field has a non-table value? */
781
      lua_pop(L, 2);  /* remove table and value */
782
      return fname;  /* return problematic part of the name */
783
    }
784
    lua_remove(L, -2);  /* remove previous table */
785
    fname = e + 1;
786
  } while (*e == '.');
787
  return NULL;
788
}
789
 
790
 
791
/*
792
** Count number of elements in a luaL_Reg list.
793
*/
794
static int libsize (const luaL_Reg *l) {
795
  int size = 0;
796
  for (; l && l->name; l++) size++;
797
  return size;
798
}
799
 
800
 
801
/*
802
** Find or create a module table with a given name. The function
803
** first looks at the _LOADED table and, if that fails, try a
804
** global variable with that name. In any case, leaves on the stack
805
** the module table.
806
*/
807
LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname,
808
                                 int sizehint) {
809
  luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);  /* get _LOADED table */
810
  lua_getfield(L, -1, modname);  /* get _LOADED[modname] */
811
  if (!lua_istable(L, -1)) {  /* not found? */
812
    lua_pop(L, 1);  /* remove previous result */
813
    /* try global variable (and create one if it does not exist) */
814
    lua_pushglobaltable(L);
815
    if (luaL_findtable(L, 0, modname, sizehint) != NULL)
816
      luaL_error(L, "name conflict for module " LUA_QS, modname);
817
    lua_pushvalue(L, -1);
818
    lua_setfield(L, -3, modname);  /* _LOADED[modname] = new table */
819
  }
820
  lua_remove(L, -2);  /* remove _LOADED table */
821
}
822
 
823
 
824
LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
825
                               const luaL_Reg *l, int nup) {
826
  luaL_checkversion(L);
827
  if (libname) {
828
    luaL_pushmodule(L, libname, libsize(l));  /* get/create library table */
829
    lua_insert(L, -(nup + 1));  /* move library table to below upvalues */
830
  }
831
  if (l)
832
    luaL_setfuncs(L, l, nup);
833
  else
834
    lua_pop(L, nup);  /* remove upvalues */
835
}
836
 
837
#endif
838
/* }====================================================== */
839
 
840
/*
841
** set functions from list 'l' into table at top - 'nup'; each
842
** function gets the 'nup' elements at the top as upvalues.
843
** Returns with only the table at the stack.
844
*/
845
LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
846
  luaL_checkstack(L, nup, "too many upvalues");
847
  for (; l->name != NULL; l++) {  /* fill the table with given functions */
848
    int i;
849
    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
850
      lua_pushvalue(L, -nup);
851
    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
852
    lua_setfield(L, -(nup + 2), l->name);
853
  }
854
  lua_pop(L, nup);  /* remove upvalues */
855
}
856
 
857
 
858
/*
859
** ensure that stack[idx][fname] has a table and push that table
860
** into the stack
861
*/
862
LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) {
863
  lua_getfield(L, idx, fname);
864
  if (lua_istable(L, -1)) return 1;  /* table already there */
865
  else {
866
    idx = lua_absindex(L, idx);
867
    lua_pop(L, 1);  /* remove previous result */
868
    lua_newtable(L);
869
    lua_pushvalue(L, -1);  /* copy to be left at top */
870
    lua_setfield(L, idx, fname);  /* assign new table to field */
871
    return 0;  /* false, because did not find table there */
872
  }
873
}
874
 
875
 
876
/*
877
** stripped-down 'require'. Calls 'openf' to open a module,
878
** registers the result in 'package.loaded' table and, if 'glb'
879
** is true, also registers the result in the global table.
880
** Leaves resulting module on the top.
881
*/
882
LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
883
                               lua_CFunction openf, int glb) {
884
  lua_pushcfunction(L, openf);
885
  lua_pushstring(L, modname);  /* argument to open function */
886
  lua_call(L, 1, 1);  /* open module */
887
  luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
888
  lua_pushvalue(L, -2);  /* make copy of module (call result) */
889
  lua_setfield(L, -2, modname);  /* _LOADED[modname] = module */
890
  lua_pop(L, 1);  /* remove _LOADED table */
891
  if (glb) {
892
    lua_pushglobaltable(L);
893
    lua_pushvalue(L, -2);  /* copy of 'mod' */
894
    lua_setfield(L, -2, modname);  /* _G[modname] = module */
895
    lua_pop(L, 1);  /* remove _G table */
896
  }
897
}
898
 
899
 
900
LUALIB_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
 
916
 
917
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
918
  (void)ud; (void)osize;  /* not used */
919
  if (nsize == 0) {
920
    free(ptr);
921
    return NULL;
922
  }
923
  else
924
    return realloc(ptr, nsize);
925
}
926
 
927
 
928
static int panic (lua_State *L) {
929
  luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
930
                   lua_tostring(L, -1));
931
  return 0;  /* return to Lua to abort */
932
}
933
 
934
 
935
LUALIB_API lua_State *luaL_newstate (void) {
936
  lua_State *L = lua_newstate(l_alloc, NULL);
937
  if (L) lua_atpanic(L, &panic);
938
  return L;
939
}
940
 
941
 
942
LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) {
943
  const lua_Number *v = lua_version(L);
944
  if (v != lua_version(NULL))
945
    luaL_error(L, "multiple Lua VMs detected");
946
  else if (*v != ver)
947
    luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
948
                  ver, *v);
949
  /* check conversions number -> integer types */
950
  lua_pushnumber(L, -(lua_Number)0x1234);
951
  if (lua_tointeger(L, -1) != -0x1234 ||
952
      lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234)
953
    luaL_error(L, "bad conversion number->int;"
954
                  " must recompile Lua with proper settings");
955
  lua_pop(L, 1);
956
}
957