2 * Copyright (c) 2014 Pedro Souza <pedrosouza@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 #include <sys/param.h>
35 #include "bootstrap.h"
40 * Like loader.perform, except args are passed already parsed
44 lua_command(lua_State *L)
48 int argc = lua_gettop(L);
51 argv = malloc(sizeof(char *) * (argc + 1));
54 for (i = 0; i < argc; i++)
55 argv[i] = (char *)(intptr_t)luaL_checkstring(L, i + 1);
57 res = interp_builtin_cmd(argc, argv);
59 lua_pushinteger(L, res);
65 lua_has_command(lua_State *L)
69 if (lua_gettop(L) != 1) {
73 cmd = luaL_checkstring(L, 1);
74 lua_pushinteger(L, interp_has_builtin_cmd(cmd));
80 lua_perform(lua_State *L)
86 if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
87 res = interp_builtin_cmd(argc, argv);
90 lua_pushinteger(L, res);
96 lua_command_error(lua_State *L)
99 lua_pushstring(L, command_errbuf);
104 * Accepts a space-delimited loader command and runs it through the standard
105 * loader parsing, as if it were executed at the loader prompt by the user.
108 lua_interpret(lua_State *L)
110 const char *interp_string;
112 if (lua_gettop(L) != 1) {
117 interp_string = luaL_checkstring(L, 1);
118 lua_pushinteger(L, interp_run(interp_string));
123 lua_parse(lua_State *L)
128 if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
129 for (nargc = 0; nargc < argc; ++nargc) {
130 lua_pushstring(L, argv[nargc]);
141 lua_getchar(lua_State *L)
144 lua_pushinteger(L, getchar());
149 lua_ischar(lua_State *L)
152 lua_pushboolean(L, ischar());
157 lua_gets(lua_State *L)
162 lua_pushstring(L, buf);
167 lua_time(lua_State *L)
170 lua_pushinteger(L, time(NULL));
175 lua_delay(lua_State *L)
178 delay((int)luaL_checknumber(L, 1));
183 lua_getenv(lua_State *L)
185 lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
191 lua_setenv(lua_State *L)
193 const char *key, *val;
195 key = luaL_checkstring(L, 1);
196 val = luaL_checkstring(L, 2);
197 lua_pushinteger(L, setenv(key, val, 1));
203 lua_unsetenv(lua_State *L)
207 ev = luaL_checkstring(L, 1);
208 lua_pushinteger(L, unsetenv(ev));
214 lua_printc(lua_State *L)
217 const char *s = luaL_checklstring(L, 1, &l);
219 for (cur = 0; cur < l; ++cur)
220 putchar((unsigned char)*(s++));
226 lua_openfile(lua_State *L)
228 const char *mode, *str;
231 nargs = lua_gettop(L);
232 if (nargs < 1 || nargs > 2) {
236 str = lua_tostring(L, 1);
239 mode = lua_tostring(L, 2);
245 FILE * f = fopen(str, mode);
247 FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**));
255 lua_closefile(lua_State *L)
258 if (lua_gettop(L) != 1) {
259 lua_pushboolean(L, 0);
263 f = (FILE**)lua_touserdata(L, 1);
264 if (f != NULL && *f != NULL) {
265 lua_pushboolean(L, fclose(*f) == 0 ? 1 : 0);
268 lua_pushboolean(L, 0);
274 lua_readfile(lua_State *L)
280 if (lua_gettop(L) < 1 || lua_gettop(L) > 2) {
282 lua_pushinteger(L, 0);
286 f = (FILE**)lua_touserdata(L, 1);
288 if (f == NULL || *f == NULL) {
290 lua_pushinteger(L, 0);
294 if (lua_gettop(L) == 2)
295 size = (size_t)lua_tonumber(L, 2);
300 buf = (char*)malloc(size);
301 r = fread(buf, 1, size, *f);
302 lua_pushlstring(L, buf, r);
304 lua_pushinteger(L, r);
310 * Implements io.write(file, ...)
311 * Any number of string and number arguments may be passed to it,
312 * and it will return the number of bytes written, or nil, an error string, and
316 lua_writefile(lua_State *L)
321 size_t bufsz, w, wrsz;
327 nargs = lua_gettop(L);
330 return luaL_fileresult(L, 0, NULL);
333 f = (FILE**)lua_touserdata(L, 1);
335 if (f == NULL || *f == NULL) {
337 return luaL_fileresult(L, 0, NULL);
340 /* Do a validation pass first */
341 for (i = 0; i < nargs - 1; i++) {
343 * With Lua's API, lua_isstring really checks if the argument
344 * is a string or a number. The latter will be implicitly
345 * converted to a string by our later call to lua_tolstring.
347 if (!lua_isstring(L, i + 2)) {
349 return luaL_fileresult(L, 0, NULL);
352 for (i = 0; i < nargs - 1; i++) {
353 /* We've already validated; there's no chance of failure */
354 buf = lua_tolstring(L, i + 2, &bufsz);
355 wrsz = fwrite(buf, 1, bufsz, *f);
357 return luaL_fileresult(L, 0, NULL);
360 lua_pushinteger(L, w);
365 * put image using terminal coordinates.
368 lua_term_putimage(lua_State *L)
372 uint32_t x1, y1, x2, y2, f;
373 int nargs, ret = 0, error;
375 nargs = lua_gettop(L);
377 lua_pushboolean(L, 0);
381 name = luaL_checkstring(L, 1);
382 x1 = luaL_checknumber(L, 2);
383 y1 = luaL_checknumber(L, 3);
384 x2 = luaL_checknumber(L, 4);
385 y2 = luaL_checknumber(L, 5);
386 f = luaL_checknumber(L, 6);
388 x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
389 y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
391 x2 = gfx_state.tg_origin.tp_col +
392 x2 * gfx_state.tg_font.vf_width;
395 y2 = gfx_state.tg_origin.tp_row +
396 y2 * gfx_state.tg_font.vf_height;
399 if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
400 if (f & FL_PUTIMAGE_DEBUG)
401 printf("%s\n", png_error_string(error));
403 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
405 (void) png_close(&png);
407 lua_pushboolean(L, ret);
412 lua_fb_putimage(lua_State *L)
416 uint32_t x1, y1, x2, y2, f;
417 int nargs, ret = 0, error;
419 nargs = lua_gettop(L);
421 lua_pushboolean(L, 0);
425 name = luaL_checkstring(L, 1);
426 x1 = luaL_checknumber(L, 2);
427 y1 = luaL_checknumber(L, 3);
428 x2 = luaL_checknumber(L, 4);
429 y2 = luaL_checknumber(L, 5);
430 f = luaL_checknumber(L, 6);
432 if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
433 if (f & FL_PUTIMAGE_DEBUG)
434 printf("%s\n", png_error_string(error));
436 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
438 (void) png_close(&png);
440 lua_pushboolean(L, ret);
445 lua_fb_setpixel(lua_State *L)
450 nargs = lua_gettop(L);
456 x = luaL_checknumber(L, 1);
457 y = luaL_checknumber(L, 2);
458 gfx_fb_setpixel(x, y);
463 lua_fb_line(lua_State *L)
465 uint32_t x0, y0, x1, y1, wd;
468 nargs = lua_gettop(L);
474 x0 = luaL_checknumber(L, 1);
475 y0 = luaL_checknumber(L, 2);
476 x1 = luaL_checknumber(L, 3);
477 y1 = luaL_checknumber(L, 4);
478 wd = luaL_checknumber(L, 5);
479 gfx_fb_line(x0, y0, x1, y1, wd);
484 lua_fb_bezier(lua_State *L)
486 uint32_t x0, y0, x1, y1, x2, y2, width;
489 nargs = lua_gettop(L);
495 x0 = luaL_checknumber(L, 1);
496 y0 = luaL_checknumber(L, 2);
497 x1 = luaL_checknumber(L, 3);
498 y1 = luaL_checknumber(L, 4);
499 x2 = luaL_checknumber(L, 5);
500 y2 = luaL_checknumber(L, 6);
501 width = luaL_checknumber(L, 7);
502 gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
507 lua_fb_drawrect(lua_State *L)
509 uint32_t x0, y0, x1, y1, fill;
512 nargs = lua_gettop(L);
518 x0 = luaL_checknumber(L, 1);
519 y0 = luaL_checknumber(L, 2);
520 x1 = luaL_checknumber(L, 3);
521 y1 = luaL_checknumber(L, 4);
522 fill = luaL_checknumber(L, 5);
523 gfx_fb_drawrect(x0, y0, x1, y1, fill);
528 lua_term_drawrect(lua_State *L)
530 uint32_t x0, y0, x1, y1;
533 nargs = lua_gettop(L);
539 x0 = luaL_checknumber(L, 1);
540 y0 = luaL_checknumber(L, 2);
541 x1 = luaL_checknumber(L, 3);
542 y1 = luaL_checknumber(L, 4);
543 gfx_term_drawrect(x0, y0, x1, y1);
547 #define REG_SIMPLE(n) { #n, lua_ ## n }
548 static const struct luaL_Reg loaderlib[] = {
550 REG_SIMPLE(command_error),
552 REG_SIMPLE(interpret),
555 REG_SIMPLE(has_command),
557 REG_SIMPLE(printc), /* Also registered as the global 'printc' */
560 REG_SIMPLE(unsetenv),
561 REG_SIMPLE(fb_bezier),
562 REG_SIMPLE(fb_drawrect),
564 REG_SIMPLE(fb_putimage),
565 REG_SIMPLE(fb_setpixel),
566 REG_SIMPLE(term_drawrect),
567 REG_SIMPLE(term_putimage),
571 static const struct luaL_Reg iolib[] = {
572 { "close", lua_closefile },
576 { "open", lua_openfile },
577 { "read", lua_readfile },
578 { "write", lua_writefile },
584 luaopen_loader(lua_State *L)
586 luaL_newlib(L, loaderlib);
587 /* Add loader.machine and loader.machine_arch properties */
588 lua_pushstring(L, MACHINE);
589 lua_setfield(L, -2, "machine");
590 lua_pushstring(L, MACHINE_ARCH);
591 lua_setfield(L, -2, "machine_arch");
592 lua_pushstring(L, LUA_PATH);
593 lua_setfield(L, -2, "lua_path");
594 lua_pushinteger(L, bootprog_rev);
595 lua_setfield(L, -2, "version");
596 /* Set global printc to loader.printc */
597 lua_register(L, "printc", lua_printc);
602 luaopen_io(lua_State *L)
604 luaL_newlib(L, iolib);