root/trunk/lib/lua/lbaselib.c

Revision 217, 17.3 KB (checked in by CHDKLover, 2 years ago)

Aktualisierung auf Rev. 864, 865, 866, 867 offizieller Trunk
*  http://tools.assembla.com/chdk/changeset/864/trunk
*  http://tools.assembla.com/chdk/changeset/865/trunk
*  http://tools.assembla.com/chdk/changeset/866/trunk
*  http://tools.assembla.com/chdk/changeset/867/trunk
ixus90_sd790 hinzugefügt
strtoul hinzugefügt
fix: LUA Hexzahlenbehandlung
In lua können jetzt beliebige Funktionspointer aufgerufen werden

  • Property svn:eol-style set to native
Line 
1/*
2** $Id: lbaselib.c,v 1.191.1.4 2008/01/20 13:53:22 roberto Exp $
3** Basic library
4** See Copyright Notice in lua.h
5*/
6
7
8
9#include <ctype.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#ifndef HOST_LUA
14#include <script.h>     // script_console_add_line
15#endif
16
17#define lbaselib_c
18#define LUA_LIB
19
20#include "lua.h"
21
22#include "lauxlib.h"
23#include "lualib.h"
24
25
26
27/*
28** If your system does not support `stdout', you can just remove this function.
29** If you need, you can define your own `print' function, following this
30** model but changing `fputs' to put the strings at a proper place
31** (a console window or a log file, for instance).
32*/
33static int luaB_print (lua_State *L) {
34  int n = lua_gettop(L);  /* number of arguments */
35  int i;
36  lua_getglobal(L, "tostring");
37  char buf[128];
38  const int max_buf_chars=sizeof(buf)-1;
39  char numbuf[16];
40  buf[0] = 0;
41  int buf_chars = 0;
42  for (i=1; i<=n; i++) {
43    const char *s;
44    /* avoid calling tostring on numbers, so we don't
45     generate new string for each unique number */
46    if(lua_type(L,i) == LUA_TNUMBER) {
47      sprintf(numbuf,LUA_NUMBER_FMT,lua_tonumber(L,i));
48      s=numbuf;
49    }
50    else {
51      lua_pushvalue(L, -1);  /* function to be called */
52      lua_pushvalue(L, i);   /* value to print */
53      lua_call(L, 1, 1);
54      s = lua_tostring(L, -1);  /* get result */
55      if (s == NULL)
56        return luaL_error(L, LUA_QL("tostring") " must return a string to "
57                          LUA_QL("print"));
58      lua_pop(L, 1);  /* pop result */
59    }
60    if(i>1) {
61      strcpy(buf+buf_chars," ");
62      ++buf_chars;
63    }
64    if(buf_chars+strlen(s) >= max_buf_chars) {
65      strncpy(buf+buf_chars,s,max_buf_chars-buf_chars);
66      buf[max_buf_chars]=0;
67      break;
68    }
69    strcpy(buf+buf_chars,s);
70    buf_chars = strlen(buf);
71    if(buf_chars >= max_buf_chars-1) // -1 allow for space
72       break;
73
74  }
75#ifdef HOST_LUA
76  fprintf(stdout,"%s\n",buf);
77#else
78  script_console_add_line(buf);
79#endif
80
81  return 0;
82}
83
84
85static int luaB_tonumber (lua_State *L) {
86  int base = luaL_optint(L, 2, 10);
87  if (base == 10) {  /* standard conversion */
88    luaL_checkany(L, 1);
89    if (lua_isnumber(L, 1)) {
90      lua_pushnumber(L, lua_tonumber(L, 1));
91      return 1;
92    }
93  }
94  else {
95    const char *s1 = luaL_checkstring(L, 1);
96    char *s2;
97    unsigned long n;
98    luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
99    n = strtoul(s1, &s2, base);
100    if (s1 != s2) {  /* at least one valid digit? */
101      while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
102      if (*s2 == '\0') {  /* no invalid trailing characters? */
103        lua_pushnumber(L, (lua_Number)n);
104        return 1;
105      }
106    }
107  }
108  lua_pushnil(L);  /* else not a number */
109  return 1;
110}
111
112
113static int luaB_error (lua_State *L) {
114  int level = luaL_optint(L, 2, 1);
115  lua_settop(L, 1);
116  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */
117    luaL_where(L, level);
118    lua_pushvalue(L, 1);
119    lua_concat(L, 2);
120  }
121  return lua_error(L);
122}
123
124
125static int luaB_getmetatable (lua_State *L) {
126  luaL_checkany(L, 1);
127  if (!lua_getmetatable(L, 1)) {
128    lua_pushnil(L);
129    return 1;  /* no metatable */
130  }
131  luaL_getmetafield(L, 1, "__metatable");
132  return 1;  /* returns either __metatable field (if present) or metatable */
133}
134
135
136static int luaB_setmetatable (lua_State *L) {
137  int t = lua_type(L, 2);
138  luaL_checktype(L, 1, LUA_TTABLE);
139  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
140                    "nil or table expected");
141  if (luaL_getmetafield(L, 1, "__metatable"))
142    luaL_error(L, "cannot change a protected metatable");
143  lua_settop(L, 2);
144  lua_setmetatable(L, 1);
145  return 1;
146}
147
148
149static void getfunc (lua_State *L, int opt) {
150  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
151  else {
152    lua_Debug ar;
153    int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
154    luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
155    if (lua_getstack(L, level, &ar) == 0)
156      luaL_argerror(L, 1, "invalid level");
157    lua_getinfo(L, "f", &ar);
158    if (lua_isnil(L, -1))
159      luaL_error(L, "no function environment for tail call at level %d",
160                    level);
161  }
162}
163
164
165static int luaB_getfenv (lua_State *L) {
166  getfunc(L, 1);
167  if (lua_iscfunction(L, -1))  /* is a C function? */
168    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */
169  else
170    lua_getfenv(L, -1);
171  return 1;
172}
173
174
175static int luaB_setfenv (lua_State *L) {
176  luaL_checktype(L, 2, LUA_TTABLE);
177  getfunc(L, 0);
178  lua_pushvalue(L, 2);
179  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
180    /* change environment of current thread */
181    lua_pushthread(L);
182    lua_insert(L, -2);
183    lua_setfenv(L, -2);
184    return 0;
185  }
186  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
187    luaL_error(L,
188          LUA_QL("setfenv") " cannot change environment of given object");
189  return 1;
190}
191
192
193static int luaB_rawequal (lua_State *L) {
194  luaL_checkany(L, 1);
195  luaL_checkany(L, 2);
196  lua_pushboolean(L, lua_rawequal(L, 1, 2));
197  return 1;
198}
199
200
201static int luaB_rawget (lua_State *L) {
202  luaL_checktype(L, 1, LUA_TTABLE);
203  luaL_checkany(L, 2);
204  lua_settop(L, 2);
205  lua_rawget(L, 1);
206  return 1;
207}
208
209static int luaB_rawset (lua_State *L) {
210  luaL_checktype(L, 1, LUA_TTABLE);
211  luaL_checkany(L, 2);
212  luaL_checkany(L, 3);
213  lua_settop(L, 3);
214  lua_rawset(L, 1);
215  return 1;
216}
217
218
219static int luaB_gcinfo (lua_State *L) {
220  lua_pushinteger(L, lua_getgccount(L));
221  return 1;
222}
223
224
225static int luaB_collectgarbage (lua_State *L) {
226  static const char *const opts[] = {"stop", "restart", "collect",
227    "count", "step", "setpause", "setstepmul", NULL};
228  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
229    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
230  int o = luaL_checkoption(L, 1, "collect", opts);
231  int ex = luaL_optint(L, 2, 0);
232  int res = lua_gc(L, optsnum[o], ex);
233  switch (optsnum[o]) {
234    case LUA_GCCOUNT: {
235      int b = lua_gc(L, LUA_GCCOUNTB, 0);
236      lua_pushnumber(L, res + ((lua_Number)b/1024));
237      return 1;
238    }
239    case LUA_GCSTEP: {
240      lua_pushboolean(L, res);
241      return 1;
242    }
243    default: {
244      lua_pushnumber(L, res);
245      return 1;
246    }
247  }
248}
249
250
251static int luaB_type (lua_State *L) {
252  luaL_checkany(L, 1);
253  lua_pushstring(L, luaL_typename(L, 1));
254  return 1;
255}
256
257
258static int luaB_next (lua_State *L) {
259  luaL_checktype(L, 1, LUA_TTABLE);
260  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
261  if (lua_next(L, 1))
262    return 2;
263  else {
264    lua_pushnil(L);
265    return 1;
266  }
267}
268
269
270static int luaB_pairs (lua_State *L) {
271  luaL_checktype(L, 1, LUA_TTABLE);
272  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
273  lua_pushvalue(L, 1);  /* state, */
274  lua_pushnil(L);  /* and initial value */
275  return 3;
276}
277
278
279static int ipairsaux (lua_State *L) {
280  int i = luaL_checkint(L, 2);
281  luaL_checktype(L, 1, LUA_TTABLE);
282  i++;  /* next value */
283  lua_pushinteger(L, i);
284  lua_rawgeti(L, 1, i);
285  return (lua_isnil(L, -1)) ? 0 : 2;
286}
287
288
289static int luaB_ipairs (lua_State *L) {
290  luaL_checktype(L, 1, LUA_TTABLE);
291  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
292  lua_pushvalue(L, 1);  /* state, */
293  lua_pushinteger(L, 0);  /* and initial value */
294  return 3;
295}
296
297
298static int load_aux (lua_State *L, int status) {
299  if (status == 0)  /* OK? */
300    return 1;
301  else {
302    lua_pushnil(L);
303    lua_insert(L, -2);  /* put before error message */
304    return 2;  /* return nil plus error message */
305  }
306}
307
308
309static int luaB_loadstring (lua_State *L) {
310  size_t l;
311  const char *s = luaL_checklstring(L, 1, &l);
312  const char *chunkname = luaL_optstring(L, 2, s);
313  return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
314}
315
316
317static int luaB_loadfile (lua_State *L) {
318  const char *fname = luaL_optstring(L, 1, NULL);
319  return load_aux(L, luaL_loadfile(L, fname));
320}
321
322
323/*
324** Reader for generic `load' function: `lua_load' uses the
325** stack for internal stuff, so the reader cannot change the
326** stack top. Instead, it keeps its resulting string in a
327** reserved slot inside the stack.
328*/
329static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
330  (void)ud;  /* to avoid warnings */
331  luaL_checkstack(L, 2, "too many nested functions");
332  lua_pushvalue(L, 1);  /* get function */
333  lua_call(L, 0, 1);  /* call it */
334  if (lua_isnil(L, -1)) {
335    *size = 0;
336    return NULL;
337  }
338  else if (lua_isstring(L, -1)) {
339    lua_replace(L, 3);  /* save string in a reserved stack slot */
340    return lua_tolstring(L, 3, size);
341  }
342  else luaL_error(L, "reader function must return a string");
343  return NULL;  /* to avoid warnings */
344}
345
346
347static int luaB_load (lua_State *L) {
348  int status;
349  const char *cname = luaL_optstring(L, 2, "=(load)");
350  luaL_checktype(L, 1, LUA_TFUNCTION);
351  lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */
352  status = lua_load(L, generic_reader, NULL, cname);
353  return load_aux(L, status);
354}
355
356
357static int luaB_dofile (lua_State *L) {
358  const char *fname = luaL_optstring(L, 1, NULL);
359  int n = lua_gettop(L);
360  if (luaL_loadfile(L, fname) != 0) lua_error(L);
361  lua_call(L, 0, LUA_MULTRET);
362  return lua_gettop(L) - n;
363}
364
365
366static int luaB_assert (lua_State *L) {
367  luaL_checkany(L, 1);
368  if (!lua_toboolean(L, 1))
369    return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
370  return lua_gettop(L);
371}
372
373
374static int luaB_unpack (lua_State *L) {
375  int i, e, n;
376  luaL_checktype(L, 1, LUA_TTABLE);
377  i = luaL_optint(L, 2, 1);
378  e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
379  n = e - i + 1;  /* number of elements */
380  if (n <= 0) return 0;  /* empty range */
381  luaL_checkstack(L, n, "table too big to unpack");
382  for (; i<=e; i++)  /* push arg[i...e] */
383    lua_rawgeti(L, 1, i);
384  return n;
385}
386
387
388static int luaB_select (lua_State *L) {
389  int n = lua_gettop(L);
390  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
391    lua_pushinteger(L, n-1);
392    return 1;
393  }
394  else {
395    int i = luaL_checkint(L, 1);
396    if (i < 0) i = n + i;
397    else if (i > n) i = n;
398    luaL_argcheck(L, 1 <= i, 1, "index out of range");
399    return n - i;
400  }
401}
402
403
404static int luaB_pcall (lua_State *L) {
405  int status;
406  luaL_checkany(L, 1);
407  status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
408  lua_pushboolean(L, (status == 0));
409  lua_insert(L, 1);
410  return lua_gettop(L);  /* return status + all results */
411}
412
413
414static int luaB_xpcall (lua_State *L) {
415  int status;
416  luaL_checkany(L, 2);
417  lua_settop(L, 2);
418  lua_insert(L, 1);  /* put error function under function to be called */
419  status = lua_pcall(L, 0, LUA_MULTRET, 1);
420  lua_pushboolean(L, (status == 0));
421  lua_replace(L, 1);
422  return lua_gettop(L);  /* return status + all results */
423}
424
425
426static int luaB_tostring (lua_State *L) {
427  luaL_checkany(L, 1);
428  if (luaL_callmeta(L, 1, "__tostring"))  /* is there a metafield? */
429    return 1;  /* use its value */
430  switch (lua_type(L, 1)) {
431    case LUA_TNUMBER:
432      lua_pushstring(L, lua_tostring(L, 1));
433      break;
434    case LUA_TSTRING:
435      lua_pushvalue(L, 1);
436      break;
437    case LUA_TBOOLEAN:
438      lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
439      break;
440    case LUA_TNIL:
441      lua_pushliteral(L, "nil");
442      break;
443    default:
444      lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
445      break;
446  }
447  return 1;
448}
449
450
451static int luaB_newproxy (lua_State *L) {
452  lua_settop(L, 1);
453  lua_newuserdata(L, 0);  /* create proxy */
454  if (lua_toboolean(L, 1) == 0)
455    return 1;  /* no metatable */
456  else if (lua_isboolean(L, 1)) {
457    lua_newtable(L);  /* create a new metatable `m' ... */
458    lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */
459    lua_pushboolean(L, 1);
460    lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */
461  }
462  else {
463    int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */
464    if (lua_getmetatable(L, 1)) {
465      lua_rawget(L, lua_upvalueindex(1));
466      validproxy = lua_toboolean(L, -1);
467      lua_pop(L, 1);  /* remove value */
468    }
469    luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
470    lua_getmetatable(L, 1);  /* metatable is valid; get it */
471  }
472  lua_setmetatable(L, 2);
473  return 1;
474}
475
476
477static const luaL_Reg base_funcs[] = {
478  {"assert", luaB_assert},
479  {"collectgarbage", luaB_collectgarbage},
480  {"dofile", luaB_dofile},
481  {"error", luaB_error},
482  {"gcinfo", luaB_gcinfo},
483  {"getfenv", luaB_getfenv},
484  {"getmetatable", luaB_getmetatable},
485  {"loadfile", luaB_loadfile},
486  {"load", luaB_load},
487  {"loadstring", luaB_loadstring},
488  {"next", luaB_next},
489  {"pcall", luaB_pcall},
490  {"print", luaB_print},
491  {"rawequal", luaB_rawequal},
492  {"rawget", luaB_rawget},
493  {"rawset", luaB_rawset},
494  {"select", luaB_select},
495  {"setfenv", luaB_setfenv},
496  {"setmetatable", luaB_setmetatable},
497  {"tonumber", luaB_tonumber},
498  {"tostring", luaB_tostring},
499  {"type", luaB_type},
500  {"unpack", luaB_unpack},
501  {"xpcall", luaB_xpcall},
502  {NULL, NULL}
503};
504
505
506/*
507** {======================================================
508** Coroutine library
509** =======================================================
510*/
511
512#define CO_RUN  0       /* running */
513#define CO_SUS  1       /* suspended */
514#define CO_NOR  2       /* 'normal' (it resumed another coroutine) */
515#define CO_DEAD 3
516
517static const char *const statnames[] =
518    {"running", "suspended", "normal", "dead"};
519
520static int costatus (lua_State *L, lua_State *co) {
521  if (L == co) return CO_RUN;
522  switch (lua_status(co)) {
523    case LUA_YIELD:
524      return CO_SUS;
525    case 0: {
526      lua_Debug ar;
527      if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
528        return CO_NOR;  /* it is running */
529      else if (lua_gettop(co) == 0)
530          return CO_DEAD;
531      else
532        return CO_SUS;  /* initial state */
533    }
534    default:  /* some error occured */
535      return CO_DEAD;
536  }
537}
538
539
540static int luaB_costatus (lua_State *L) {
541  lua_State *co = lua_tothread(L, 1);
542  luaL_argcheck(L, co, 1, "coroutine expected");
543  lua_pushstring(L, statnames[costatus(L, co)]);
544  return 1;
545}
546
547
548static int auxresume (lua_State *L, lua_State *co, int narg) {
549  int status = costatus(L, co);
550  if (!lua_checkstack(co, narg))
551    luaL_error(L, "too many arguments to resume");
552  if (status != CO_SUS) {
553    lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
554    return -1;  /* error flag */
555  }
556  lua_xmove(L, co, narg);
557  lua_setlevel(L, co);
558  status = lua_resume(co, narg);
559  if (status == 0 || status == LUA_YIELD) {
560    int nres = lua_gettop(co);
561    if (!lua_checkstack(L, nres))
562      luaL_error(L, "too many results to resume");
563    lua_xmove(co, L, nres);  /* move yielded values */
564    return nres;
565  }
566  else {
567    lua_xmove(co, L, 1);  /* move error message */
568    return -1;  /* error flag */
569  }
570}
571
572
573static int luaB_coresume (lua_State *L) {
574  lua_State *co = lua_tothread(L, 1);
575  int r;
576  luaL_argcheck(L, co, 1, "coroutine expected");
577  r = auxresume(L, co, lua_gettop(L) - 1);
578  if (r < 0) {
579    lua_pushboolean(L, 0);
580    lua_insert(L, -2);
581    return 2;  /* return false + error message */
582  }
583  else {
584    lua_pushboolean(L, 1);
585    lua_insert(L, -(r + 1));
586    return r + 1;  /* return true + `resume' returns */
587  }
588}
589
590
591static int luaB_auxwrap (lua_State *L) {
592  lua_State *co = lua_tothread(L, lua_upvalueindex(1));
593  int r = auxresume(L, co, lua_gettop(L));
594  if (r < 0) {
595    if (lua_isstring(L, -1)) {  /* error object is a string? */
596      luaL_where(L, 1);  /* add extra info */
597      lua_insert(L, -2);
598      lua_concat(L, 2);
599    }
600    lua_error(L);  /* propagate error */
601  }
602  return r;
603}
604
605
606static int luaB_cocreate (lua_State *L) {
607  lua_State *NL = lua_newthread(L);
608  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
609    "Lua function expected");
610  lua_pushvalue(L, 1);  /* move function to top */
611  lua_xmove(L, NL, 1);  /* move function from L to NL */
612  return 1;
613}
614
615
616static int luaB_cowrap (lua_State *L) {
617  luaB_cocreate(L);
618  lua_pushcclosure(L, luaB_auxwrap, 1);
619  return 1;
620}
621
622
623static int luaB_yield (lua_State *L) {
624  return lua_yield(L, lua_gettop(L));
625}
626
627
628static int luaB_corunning (lua_State *L) {
629  if (lua_pushthread(L))
630    lua_pushnil(L);  /* main thread is not a coroutine */
631  return 1;
632}
633
634
635static const luaL_Reg co_funcs[] = {
636  {"create", luaB_cocreate},
637  {"resume", luaB_coresume},
638  {"running", luaB_corunning},
639  {"status", luaB_costatus},
640  {"wrap", luaB_cowrap},
641  {"yield", luaB_yield},
642  {NULL, NULL}
643};
644
645/* }====================================================== */
646
647
648static void auxopen (lua_State *L, const char *name,
649                     lua_CFunction f, lua_CFunction u) {
650  lua_pushcfunction(L, u);
651  lua_pushcclosure(L, f, 1);
652  lua_setfield(L, -2, name);
653}
654
655
656static void base_open (lua_State *L) {
657  /* set global _G */
658  lua_pushvalue(L, LUA_GLOBALSINDEX);
659  lua_setglobal(L, "_G");
660  /* open lib into global table */
661  luaL_register(L, "_G", base_funcs);
662  lua_pushliteral(L, LUA_VERSION);
663  lua_setglobal(L, "_VERSION");  /* set global _VERSION */
664  /* `ipairs' and `pairs' need auxliliary functions as upvalues */
665  auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
666  auxopen(L, "pairs", luaB_pairs, luaB_next);
667  /* `newproxy' needs a weaktable as upvalue */
668  lua_createtable(L, 0, 1);  /* new table `w' */
669  lua_pushvalue(L, -1);  /* `w' will be its own metatable */
670  lua_setmetatable(L, -2);
671  lua_pushliteral(L, "kv");
672  lua_setfield(L, -2, "__mode");  /* metatable(w).__mode = "kv" */
673  lua_pushcclosure(L, luaB_newproxy, 1);
674  lua_setglobal(L, "newproxy");  /* set global `newproxy' */
675}
676
677
678LUALIB_API int luaopen_base (lua_State *L) {
679  base_open(L);
680  luaL_register(L, LUA_COLIBNAME, co_funcs);
681  return 2;
682}
683
Note: See TracBrowser for help on using the browser.