8ae86ffab5fe31ddb8a591c4245ec70f912a5abb
[olsrd.git] / lib / tas / src / lua / lauxlib.c
1 /*
2 ** $Id: lauxlib.c,v 1.100 2003/04/07 14:35:00 roberto Exp $
3 ** Auxiliary functions for building Lua libraries
4 ** See Copyright Notice in lua.h
5 */
6
7
8 #include <ctype.h>
9 #include <errno.h>
10 #include <stdarg.h>
11 #include <stdio.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
21 #include "lua.h"
22
23 #include "lauxlib.h"
24
25
26 /* number of prereserved references (for internal use) */
27 #define RESERVED_REFS   2
28
29 /* reserved references */
30 #define FREELIST_REF    1       /* free list of references */
31 #define ARRAYSIZE_REF   2       /* array sizes */
32
33
34 /* convert a stack index to positive */
35 #define abs_index(L, i)         ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
36                                         lua_gettop(L) + (i) + 1)
37
38
39 /*
40 ** {======================================================
41 ** Error-report functions
42 ** =======================================================
43 */
44
45
46 LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
47   lua_Debug ar;
48   lua_getstack(L, 0, &ar);
49   lua_getinfo(L, "n", &ar);
50   if (strcmp(ar.namewhat, "method") == 0) {
51     narg--;  /* do not count `self' */
52     if (narg == 0)  /* error is in the self argument itself? */
53       luaL_error(L, "calling `%s' on bad self (%s)", ar.name, extramsg);
54   }
55   if (ar.name == NULL)
56     ar.name = "?";
57   luaL_error(L, "bad argument #%d to `%s' (%s)",
58                         narg, ar.name, extramsg);
59 }
60
61
62 LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {
63   const char *msg = lua_pushfstring(L, "%s expected, got %s",
64                                     tname, lua_typename(L, lua_type(L,narg)));
65   luaL_argerror(L, narg, msg);
66 }
67
68
69 static void tag_error (lua_State *L, int narg, int tag) __attribute__((noreturn));
70 static void tag_error (lua_State *L, int narg, int tag) {
71   luaL_typerror(L, narg, lua_typename(L, tag)); 
72 }
73
74
75 LUALIB_API void luaL_where (lua_State *L, int level) {
76   lua_Debug ar;
77   if (lua_getstack(L, level, &ar)) {  /* check function at level */
78     lua_getinfo(L, "Snl", &ar);  /* get info about it */
79     if (ar.currentline > 0) {  /* is there info? */
80       lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline);
81       return;
82     }
83   }
84   lua_pushliteral(L, "");  /* else, no information available... */
85 }
86
87
88 LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
89   va_list argp;
90   va_start(argp, fmt);
91   luaL_where(L, 1);
92   lua_pushvfstring(L, fmt, argp);
93   va_end(argp);
94   lua_concat(L, 2);
95   lua_error(L);
96 }
97
98 /* }====================================================== */
99
100
101 LUALIB_API int luaL_findstring (const char *name, const char *const list[]) {
102   int i;
103   for (i=0; list[i]; i++)
104     if (strcmp(list[i], name) == 0)
105       return i;
106   return -1;  /* name not found */
107 }
108
109
110 LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
111   lua_pushstring(L, tname);
112   lua_rawget(L, LUA_REGISTRYINDEX);  /* get registry.name */
113   if (!lua_isnil(L, -1))  /* name already in use? */
114     return 0;  /* leave previous value on top, but return 0 */
115   lua_pop(L, 1);
116   lua_newtable(L);  /* create metatable */
117   lua_pushstring(L, tname);
118   lua_pushvalue(L, -2);
119   lua_rawset(L, LUA_REGISTRYINDEX);  /* registry.name = metatable */
120   lua_pushvalue(L, -1);
121   lua_pushstring(L, tname);
122   lua_rawset(L, LUA_REGISTRYINDEX);  /* registry[metatable] = name */
123   return 1;
124 }
125
126
127 LUALIB_API void  luaL_getmetatable (lua_State *L, const char *tname) {
128   lua_pushstring(L, tname);
129   lua_rawget(L, LUA_REGISTRYINDEX);
130 }
131
132
133 LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
134   const char *tn;
135   if (!lua_getmetatable(L, ud)) return NULL;  /* no metatable? */
136   lua_rawget(L, LUA_REGISTRYINDEX);  /* get registry[metatable] */
137   tn = lua_tostring(L, -1);
138   if (tn && (strcmp(tn, tname) == 0)) {
139     lua_pop(L, 1);
140     return lua_touserdata(L, ud);
141   }
142   else {
143     lua_pop(L, 1);
144     return NULL;
145   }
146 }
147
148
149 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
150   if (!lua_checkstack(L, space))
151     luaL_error(L, "stack overflow (%s)", mes);
152 }
153
154
155 LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
156   if (lua_type(L, narg) != t)
157     tag_error(L, narg, t);
158 }
159
160
161 LUALIB_API void luaL_checkany (lua_State *L, int narg) {
162   if (lua_type(L, narg) == LUA_TNONE)
163     luaL_argerror(L, narg, "value expected");
164 }
165
166
167 LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {
168   const char *s = lua_tostring(L, narg);
169   if (!s) tag_error(L, narg, LUA_TSTRING);
170   if (len) *len = lua_strlen(L, narg);
171   return s;
172 }
173
174
175 LUALIB_API const char *luaL_optlstring (lua_State *L, int narg,
176                                         const char *def, size_t *len) {
177   if (lua_isnoneornil(L, narg)) {
178     if (len)
179       *len = (def ? strlen(def) : 0);
180     return def;
181   }
182   else return luaL_checklstring(L, narg, len);
183 }
184
185
186 LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
187   lua_Number d = lua_tonumber(L, narg);
188   if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */
189     tag_error(L, narg, LUA_TNUMBER);
190   return d;
191 }
192
193
194 LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {
195   if (lua_isnoneornil(L, narg)) return def;
196   else return luaL_checknumber(L, narg);
197 }
198
199
200 LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
201   if (!lua_getmetatable(L, obj))  /* no metatable? */
202     return 0;
203   lua_pushstring(L, event);
204   lua_rawget(L, -2);
205   if (lua_isnil(L, -1)) {
206     lua_pop(L, 2);  /* remove metatable and metafield */
207     return 0;
208   }
209   else {
210     lua_remove(L, -2);  /* remove only metatable */
211     return 1;
212   }
213 }
214
215
216 LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
217   obj = abs_index(L, obj);
218   if (!luaL_getmetafield(L, obj, event))  /* no metafield? */
219     return 0;
220   lua_pushvalue(L, obj);
221   lua_call(L, 1, 1);
222   return 1;
223 }
224
225
226 LUALIB_API void luaL_openlib (lua_State *L, const char *libname,
227                               const luaL_reg *l, int nup) {
228   if (libname) {
229     lua_pushstring(L, libname);
230     lua_gettable(L, LUA_GLOBALSINDEX);  /* check whether lib already exists */
231     if (lua_isnil(L, -1)) {  /* no? */
232       lua_pop(L, 1);
233       lua_newtable(L);  /* create it */
234       lua_pushstring(L, libname);
235       lua_pushvalue(L, -2);
236       lua_settable(L, LUA_GLOBALSINDEX);  /* register it with given name */
237     }
238     lua_insert(L, -(nup+1));  /* move library table to below upvalues */
239   }
240   for (; l->name; l++) {
241     int i;
242     lua_pushstring(L, l->name);
243     for (i=0; i<nup; i++)  /* copy upvalues to the top */
244       lua_pushvalue(L, -(nup+1));
245     lua_pushcclosure(L, l->func, nup);
246     lua_settable(L, -(nup+3));
247   }
248   lua_pop(L, nup);  /* remove upvalues */
249 }
250
251
252
253 /*
254 ** {======================================================
255 ** getn-setn: size for arrays
256 ** =======================================================
257 */
258
259 static int checkint (lua_State *L, int topop) {
260   int n = (int)lua_tonumber(L, -1);
261   if (n == 0 && !lua_isnumber(L, -1)) n = -1;
262   lua_pop(L, topop);
263   return n;
264 }
265
266
267 static void getsizes (lua_State *L) {
268   lua_rawgeti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);
269   if (lua_isnil(L, -1)) {  /* no `size' table? */
270     lua_pop(L, 1);  /* remove nil */
271     lua_newtable(L);  /* create it */
272     lua_pushvalue(L, -1);  /* `size' will be its own metatable */
273     lua_setmetatable(L, -2);
274     lua_pushliteral(L, "__mode");
275     lua_pushliteral(L, "k");
276     lua_rawset(L, -3);  /* metatable(N).__mode = "k" */
277     lua_pushvalue(L, -1);
278     lua_rawseti(L, LUA_REGISTRYINDEX, ARRAYSIZE_REF);  /* store in register */
279   }
280 }
281
282
283 void luaL_setn (lua_State *L, int t, int n) {
284   t = abs_index(L, t);
285   lua_pushliteral(L, "n");
286   lua_rawget(L, t);
287   if (checkint(L, 1) >= 0) {  /* is there a numeric field `n'? */
288     lua_pushliteral(L, "n");  /* use it */
289     lua_pushnumber(L, (lua_Number)n);
290     lua_rawset(L, t);
291   }
292   else {  /* use `sizes' */
293     getsizes(L);
294     lua_pushvalue(L, t);
295     lua_pushnumber(L, (lua_Number)n);
296     lua_rawset(L, -3);  /* sizes[t] = n */
297     lua_pop(L, 1);  /* remove `sizes' */
298   }
299 }
300
301
302 int luaL_getn (lua_State *L, int t) {
303   int n;
304   t = abs_index(L, t);
305   lua_pushliteral(L, "n");  /* try t.n */
306   lua_rawget(L, t);
307   if ((n = checkint(L, 1)) >= 0) return n;
308   getsizes(L);  /* else try sizes[t] */
309   lua_pushvalue(L, t);
310   lua_rawget(L, -2);
311   if ((n = checkint(L, 2)) >= 0) return n;
312   for (n = 1; ; n++) {  /* else must count elements */
313     lua_rawgeti(L, t, n);
314     if (lua_isnil(L, -1)) break;
315     lua_pop(L, 1);
316   }
317   lua_pop(L, 1);
318   return n - 1;
319 }
320
321 /* }====================================================== */
322
323
324
325 /*
326 ** {======================================================
327 ** Generic Buffer manipulation
328 ** =======================================================
329 */
330
331
332 #define bufflen(B)      ((B)->p - (B)->buffer)
333 #define bufffree(B)     ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
334
335 #define LIMIT   (LUA_MINSTACK/2)
336
337
338 static int emptybuffer (luaL_Buffer *B) {
339   size_t l = bufflen(B);
340   if (l == 0) return 0;  /* put nothing on stack */
341   else {
342     lua_pushlstring(B->L, B->buffer, l);
343     B->p = B->buffer;
344     B->lvl++;
345     return 1;
346   }
347 }
348
349
350 static void adjuststack (luaL_Buffer *B) {
351   if (B->lvl > 1) {
352     lua_State *L = B->L;
353     int toget = 1;  /* number of levels to concat */
354     size_t toplen = lua_strlen(L, -1);
355     do {
356       size_t l = lua_strlen(L, -(toget+1));
357       if (B->lvl - toget + 1 >= LIMIT || toplen > l) {
358         toplen += l;
359         toget++;
360       }
361       else break;
362     } while (toget < B->lvl);
363     lua_concat(L, toget);
364     B->lvl = B->lvl - toget + 1;
365   }
366 }
367
368
369 LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {
370   if (emptybuffer(B))
371     adjuststack(B);
372   return B->buffer;
373 }
374
375
376 LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {
377   while (l--)
378     luaL_putchar(B, *s++);
379 }
380
381
382 LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
383   luaL_addlstring(B, s, strlen(s));
384 }
385
386
387 LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
388   emptybuffer(B);
389   lua_concat(B->L, B->lvl);
390   B->lvl = 1;
391 }
392
393
394 LUALIB_API void luaL_addvalue (luaL_Buffer *B) {
395   lua_State *L = B->L;
396   size_t vl = lua_strlen(L, -1);
397   if (vl <= bufffree(B)) {  /* fit into buffer? */
398     memcpy(B->p, lua_tostring(L, -1), vl);  /* put it there */
399     B->p += vl;
400     lua_pop(L, 1);  /* remove from stack */
401   }
402   else {
403     if (emptybuffer(B))
404       lua_insert(L, -2);  /* put buffer before new value */
405     B->lvl++;  /* add new value into B stack */
406     adjuststack(B);
407   }
408 }
409
410
411 LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
412   B->L = L;
413   B->p = B->buffer;
414   B->lvl = 0;
415 }
416
417 /* }====================================================== */
418
419
420 LUALIB_API int luaL_ref (lua_State *L, int t) {
421   int ref;
422   t = abs_index(L, t);
423   if (lua_isnil(L, -1)) {
424     lua_pop(L, 1);  /* remove from stack */
425     return LUA_REFNIL;  /* `nil' has a unique fixed reference */
426   }
427   lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */
428   ref = (int)lua_tonumber(L, -1);  /* ref = t[FREELIST_REF] */
429   lua_pop(L, 1);  /* remove it from stack */
430   if (ref != 0) {  /* any free element? */
431     lua_rawgeti(L, t, ref);  /* remove it from list */
432     lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */
433   }
434   else {  /* no free elements */
435     ref = luaL_getn(L, t);
436     if (ref < RESERVED_REFS)
437       ref = RESERVED_REFS;  /* skip reserved references */
438     ref++;  /* create new reference */
439     luaL_setn(L, t, ref);
440   }
441   lua_rawseti(L, t, ref);
442   return ref;
443 }
444
445
446 LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
447   if (ref >= 0) {
448     t = abs_index(L, t);
449     lua_rawgeti(L, t, FREELIST_REF);
450     lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */
451     lua_pushnumber(L, (lua_Number)ref);
452     lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */
453   }
454 }
455
456
457
458 /*
459 ** {======================================================
460 ** Load functions
461 ** =======================================================
462 */
463
464 typedef struct LoadF {
465   FILE *f;
466   char buff[LUAL_BUFFERSIZE];
467 } LoadF;
468
469
470 static const char *getF (lua_State *L, void *ud, size_t *size) {
471   LoadF *lf = (LoadF *)ud;
472   (void)L;
473   if (feof(lf->f)) return NULL;
474   *size = fread(lf->buff, 1, LUAL_BUFFERSIZE, lf->f);
475   return (*size > 0) ? lf->buff : NULL;
476 }
477
478
479 static int errfile (lua_State *L, int fnameindex) {
480   const char *filename = lua_tostring(L, fnameindex) + 1;
481   lua_pushfstring(L, "cannot read %s: %s", filename, strerror(errno));
482   lua_remove(L, fnameindex);
483   return LUA_ERRFILE;
484 }
485
486
487 LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
488   LoadF lf;
489   int status, readstatus;
490   int c;
491   int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */
492   if (filename == NULL) {
493     lua_pushliteral(L, "=stdin");
494     lf.f = stdin;
495   }
496   else {
497     lua_pushfstring(L, "@%s", filename);
498     lf.f = fopen(filename, "r");
499   }
500   if (lf.f == NULL) return errfile(L, fnameindex);  /* unable to open file */
501   c = ungetc(getc(lf.f), lf.f);
502   if (!(isspace(c) || isprint(c)) && lf.f != stdin) {  /* binary file? */
503     fclose(lf.f);
504     lf.f = fopen(filename, "rb");  /* reopen in binary mode */
505     if (lf.f == NULL) return errfile(L, fnameindex); /* unable to reopen file */
506   }
507   status = lua_load(L, getF, &lf, lua_tostring(L, -1));
508   readstatus = ferror(lf.f);
509   if (lf.f != stdin) fclose(lf.f);  /* close file (even in case of errors) */
510   if (readstatus) {
511     lua_settop(L, fnameindex);  /* ignore results from `lua_load' */
512     return errfile(L, fnameindex);
513   }
514   lua_remove(L, fnameindex);
515   return status;
516 }
517
518
519 typedef struct LoadS {
520   const char *s;
521   size_t size;
522 } LoadS;
523
524
525 static const char *getS (lua_State *L, void *ud, size_t *size) {
526   LoadS *ls = (LoadS *)ud;
527   (void)L;
528   if (ls->size == 0) return NULL;
529   *size = ls->size;
530   ls->size = 0;
531   return ls->s;
532 }
533
534
535 LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,
536                                 const char *name) {
537   LoadS ls;
538   ls.s = buff;
539   ls.size = size;
540   return lua_load(L, getS, &ls, name);
541 }
542
543 /* }====================================================== */
544
545
546 /*
547 ** {======================================================
548 ** compatibility code
549 ** =======================================================
550 */
551
552
553 static void callalert (lua_State *L, int status) {
554   if (status != 0) {
555     lua_getglobal(L, "_ALERT");
556     if (lua_isfunction(L, -1)) {
557       lua_insert(L, -2);
558       lua_call(L, 1, 0);
559     }
560     else {  /* no _ALERT function; print it on stderr */
561       fprintf(stderr, "%s\n", lua_tostring(L, -2));
562       lua_pop(L, 2);  /* remove error message and _ALERT */
563     }
564   }
565 }
566
567
568 static int aux_do (lua_State *L, int status) {
569   if (status == 0) {  /* parse OK? */
570     status = lua_pcall(L, 0, LUA_MULTRET, 0);  /* call main */
571   }
572   callalert(L, status);
573   return status;
574 }
575
576
577 LUALIB_API int lua_dofile (lua_State *L, const char *filename) {
578   return aux_do(L, luaL_loadfile(L, filename));
579 }
580
581
582 LUALIB_API int lua_dobuffer (lua_State *L, const char *buff, size_t size,
583                           const char *name) {
584   return aux_do(L, luaL_loadbuffer(L, buff, size, name));
585 }
586
587
588 LUALIB_API int lua_dostring (lua_State *L, const char *str) {
589   return lua_dobuffer(L, str, strlen(str), str);
590 }
591
592 /* }====================================================== */