Merge branch 'makefile' into haiku
[grub2/phcoder.git] / script / lua / grub_main.c
blobb39141f75d8e6ae1dd5151d8cddb93f415ebebfe
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include "lua.h"
20 #include "lauxlib.h"
21 #include "lualib.h"
22 #include "grub_lib.h"
24 #include <grub/dl.h>
25 #include <grub/parser.h>
27 static const char *
28 scan_str (const char *s1, const char *s2)
30 while (*s1)
32 const char *p = s2;
34 while (*p)
36 if (*s1 == *p)
37 return s1;
38 p++;
41 s1++;
44 return s1;
47 int
48 strcspn (const char *s1, const char *s2)
50 const char *r;
52 r = scan_str (s1, s2);
53 return r - s1;
56 char *
57 strpbrk (const char *s1, const char *s2)
59 const char *r;
61 r = scan_str (s1, s2);
62 return (*r) ? (char *) r : 0;
65 void *
66 memchr (const void *s, int c, size_t n)
68 const unsigned char *p = s;
70 while (n)
72 if (*p == c)
73 return (void *) p;
75 n--;
76 p++;
79 return 0;
82 static lua_State *state;
84 /* Call `grub_error' to report a Lua error. The error message string must be
85 on the top of the Lua stack (at index -1). The error message is popped off
86 the Lua stack before this function returns. */
87 static void
88 handle_lua_error (const char *error_type)
90 const char *error_msg;
91 error_msg = lua_tostring (state, -1);
92 if (error_msg == NULL)
93 error_msg = "(error message not a string)";
94 grub_error (GRUB_ERR_BAD_ARGUMENT, "%s: %s", error_type, error_msg);
95 /* Pop the error message. */
96 lua_pop (state, 1);
99 static grub_err_t
100 grub_lua_parse_line (char *line, grub_reader_getline_t getline)
102 int r;
103 char *old_line = 0;
105 lua_settop(state, 0);
106 while (1)
108 r = luaL_loadbuffer (state, line, grub_strlen (line), "=grub");
109 if (! r)
111 /* No error: Execute the statement. */
112 r = lua_pcall (state, 0, 0, 0);
113 if (r)
115 handle_lua_error ("Lua");
116 break;
118 else
120 grub_free (old_line);
121 return grub_errno;
125 if (r == LUA_ERRSYNTAX)
127 /* Check whether the syntax error is a result of an incomplete
128 statement. If it is, then try to complete the statement by
129 reading more lines. */
130 size_t lmsg;
131 const char *msg = lua_tolstring (state, -1, &lmsg);
132 const char *tp = msg + lmsg - (sizeof (LUA_QL ("<eof>")) - 1);
133 if (grub_strstr (msg, LUA_QL ("<eof>")) == tp)
135 char *n, *t;
136 int len;
138 /* Discard the error message. */
139 lua_pop (state, 1);
140 /* Try to read another line to complete the statement. */
141 if ((getline (&n, 1)) || (! n))
143 grub_error (GRUB_ERR_BAD_ARGUMENT, "incomplete command");
144 break;
147 /* More input was available: Add it to the current statement
148 contents. */
149 len = grub_strlen (line);
150 t = grub_malloc (len + grub_strlen (n) + 2);
151 if (! t)
152 break;
154 grub_strcpy (t, line);
155 t[len] = '\n';
156 grub_strcpy (t + len + 1, n);
157 grub_free (old_line);
158 line = old_line = t;
159 /* Try again to execute the statement now that more input has
160 been appended. */
161 continue;
163 /* The syntax error was not the result of an incomplete line. */
164 handle_lua_error ("Lua syntax error");
166 else
168 /* Handle errors other than syntax errors (out of memory, etc.). */
169 handle_lua_error ("Lua parser failed");
172 break;
175 grub_free (old_line);
176 lua_gc (state, LUA_GCCOLLECT, 0);
178 return grub_errno;
181 static struct grub_parser grub_lua_parser =
183 .name = "lua",
184 .parse_line = grub_lua_parse_line
187 GRUB_MOD_INIT(lua)
189 (void) mod;
191 state = lua_open ();
192 if (state)
194 lua_gc (state, LUA_GCSTOP, 0);
195 luaL_openlibs (state);
196 luaL_register (state, "grub", grub_lua_lib);
197 lua_gc (state, LUA_GCRESTART, 0);
198 grub_parser_register ("lua", &grub_lua_parser);
202 GRUB_MOD_FINI(lua)
204 if (state)
206 grub_parser_unregister (&grub_lua_parser);
207 lua_close (state);