Build doom on clipv2 and clip+
[kugel-rb.git] / apps / plugins / lua / rocklua.c
blobb92c274fb053c57bfdd717b8f148c9a881078067
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 Dan Everton (safetydan)
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
23 #include "lib/pluginlib_exit.h"
24 #include "lua.h"
25 #include "lauxlib.h"
26 #include "lualib.h"
27 #include "rocklib.h"
28 #include "rockmalloc.h"
29 #include "luadir.h"
31 PLUGIN_HEADER
33 static const luaL_Reg lualibs[] = {
34 {"", luaopen_base},
35 {LUA_TABLIBNAME, luaopen_table},
36 {LUA_STRLIBNAME, luaopen_string},
37 {LUA_OSLIBNAME, luaopen_os},
38 {LUA_ROCKLIBNAME, luaopen_rock},
39 {LUA_BITLIBNAME, luaopen_bit},
40 {LUA_IOLIBNAME, luaopen_io},
41 {LUA_LOADLIBNAME, luaopen_package},
42 {LUA_MATHLIBNAME, luaopen_math},
43 {LUA_DIRLIBNAME, luaopen_luadir},
44 {NULL, NULL}
47 static void rocklua_openlibs(lua_State *L) {
48 const luaL_Reg *lib = lualibs;
49 for (; lib->func; lib++) {
50 lua_pushcfunction(L, lib->func);
51 lua_pushstring(L, lib->name);
52 lua_call(L, 1, 0);
56 /* ldlib.c */
57 static lua_State *getthread (lua_State *L, int *arg) {
58 if (lua_isthread(L, 1)) {
59 *arg = 1;
60 return lua_tothread(L, 1);
62 else {
63 *arg = 0;
64 return L;
68 #define LEVELS1 12 /* size of the first part of the stack */
69 #define LEVELS2 10 /* size of the second part of the stack */
71 static int db_errorfb (lua_State *L) {
72 int level;
73 int firstpart = 1; /* still before eventual `...' */
74 int arg;
75 lua_State *L1 = getthread(L, &arg);
76 lua_Debug ar;
77 if (lua_isnumber(L, arg+2)) {
78 level = (int)lua_tointeger(L, arg+2);
79 lua_pop(L, 1);
81 else
82 level = (L == L1) ? 1 : 0; /* level 0 may be this own function */
83 if (lua_gettop(L) == arg)
84 lua_pushliteral(L, "");
85 else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */
86 else lua_pushliteral(L, "\n");
87 lua_pushliteral(L, "stack traceback:");
88 while (lua_getstack(L1, level++, &ar)) {
89 if (level > LEVELS1 && firstpart) {
90 /* no more than `LEVELS2' more levels? */
91 if (!lua_getstack(L1, level+LEVELS2, &ar))
92 level--; /* keep going */
93 else {
94 lua_pushliteral(L, "\n\t..."); /* too many levels */
95 while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */
96 level++;
98 firstpart = 0;
99 continue;
101 lua_pushliteral(L, "\n\t");
102 lua_getinfo(L1, "Snl", &ar);
103 lua_pushfstring(L, "%s:", ar.short_src);
104 if (ar.currentline > 0)
105 lua_pushfstring(L, "%d:", ar.currentline);
106 if (*ar.namewhat != '\0') /* is there a name? */
107 lua_pushfstring(L, " in function " LUA_QS, ar.name);
108 else {
109 if (*ar.what == 'm') /* main? */
110 lua_pushfstring(L, " in main chunk");
111 else if (*ar.what == 'C' || *ar.what == 't')
112 lua_pushliteral(L, " ?"); /* C function or tail call */
113 else
114 lua_pushfstring(L, " in function <%s:%d>",
115 ar.short_src, ar.linedefined);
117 lua_concat(L, lua_gettop(L) - arg);
119 lua_concat(L, lua_gettop(L) - arg);
120 return 1;
123 /* lua.c */
124 static int traceback (lua_State *L) {
125 lua_pushcfunction(L, db_errorfb);
126 lua_pushvalue(L, 1); /* pass error message */
127 lua_pushinteger(L, 2); /* skip this function and traceback */
128 lua_call(L, 2, 1); /* call debug.traceback */
129 return 1;
132 static int docall (lua_State *L) {
133 int status;
134 int base = lua_gettop(L); /* function index */
135 lua_pushcfunction(L, traceback); /* push traceback function */
136 lua_insert(L, base); /* put it under chunk and args */
137 status = lua_pcall(L, 0, 0, base);
138 lua_remove(L, base); /* remove traceback function */
139 /* force a complete garbage collection in case of errors */
140 if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0);
141 return status;
145 /***************** Plugin Entry Point *****************/
146 enum plugin_status plugin_start(const void* parameter)
148 const char* filename;
149 int status;
151 PLUGINLIB_EXIT_INIT
153 if (parameter == NULL)
155 rb->splash(HZ, "Play a .lua file!");
156 return PLUGIN_ERROR;
158 else
160 filename = (char*) parameter;
162 lua_State *L = luaL_newstate();
164 rocklua_openlibs(L);
165 status = luaL_loadfile(L, filename);
166 if (!status) {
167 rb->lcd_clear_display();
168 status = docall(L);
171 dlmalloc_stats();
173 if (status) {
174 DEBUGF("%s\n", lua_tostring(L, -1));
175 rb->splashf(5 * HZ, "%s", lua_tostring(L, -1));
176 lua_pop(L, 1);
179 lua_close(L);
182 return PLUGIN_OK;