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/param.h>
34 #include "bootstrap.h"
39 * Like loader.perform, except args are passed already parsed
43 lua_command(lua_State *L)
47 int argc = lua_gettop(L);
50 argv = malloc(sizeof(char *) * (argc + 1));
53 for (i = 0; i < argc; i++)
54 argv[i] = (char *)(intptr_t)luaL_checkstring(L, i + 1);
56 res = interp_builtin_cmd(argc, argv);
58 lua_pushinteger(L, res);
64 lua_has_command(lua_State *L)
68 cmd = luaL_checkstring(L, 1);
69 if (interp_has_builtin_cmd(cmd)) {
70 lua_pushboolean(L, 1);
75 lua_pushstring(L, "Builtin command not found");
80 lua_has_feature(lua_State *L)
85 feature = luaL_checkstring(L, 1);
87 if (feature_name_is_enabled(feature)) {
88 lua_pushboolean(L, 1);
93 lua_pushstring(L, "Feature not enabled");
99 lua_perform(lua_State *L)
105 if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
106 res = interp_builtin_cmd(argc, argv);
109 lua_pushinteger(L, res);
115 lua_command_error(lua_State *L)
118 lua_pushstring(L, command_errbuf);
123 * Accepts a space-delimited loader command and runs it through the standard
124 * loader parsing, as if it were executed at the loader prompt by the user.
127 lua_interpret(lua_State *L)
129 const char *interp_string;
131 if (lua_gettop(L) != 1) {
136 interp_string = luaL_checkstring(L, 1);
137 lua_pushinteger(L, interp_run(interp_string));
142 lua_parse(lua_State *L)
147 if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
148 for (nargc = 0; nargc < argc; ++nargc) {
149 lua_pushstring(L, argv[nargc]);
160 lua_getchar(lua_State *L)
163 lua_pushinteger(L, getchar());
168 lua_ischar(lua_State *L)
171 lua_pushboolean(L, ischar());
176 lua_gets(lua_State *L)
181 lua_pushstring(L, buf);
186 lua_time(lua_State *L)
189 lua_pushinteger(L, time(NULL));
194 lua_delay(lua_State *L)
197 delay((int)luaL_checknumber(L, 1));
202 lua_getenv(lua_State *L)
204 lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
210 lua_setenv(lua_State *L)
212 const char *key, *val;
214 key = luaL_checkstring(L, 1);
215 val = luaL_checkstring(L, 2);
216 lua_pushinteger(L, setenv(key, val, 1));
222 lua_unsetenv(lua_State *L)
226 ev = luaL_checkstring(L, 1);
227 lua_pushinteger(L, unsetenv(ev));
233 lua_printc(lua_State *L)
236 const char *s = luaL_checklstring(L, 1, &l);
238 for (cur = 0; cur < l; ++cur)
239 putchar((unsigned char)*(s++));
245 lua_openfile(lua_State *L)
247 const char *mode, *str;
250 nargs = lua_gettop(L);
251 if (nargs < 1 || nargs > 2) {
255 str = lua_tostring(L, 1);
258 mode = lua_tostring(L, 2);
264 FILE * f = fopen(str, mode);
266 FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**));
274 lua_closefile(lua_State *L)
277 if (lua_gettop(L) != 1) {
278 lua_pushboolean(L, 0);
282 f = (FILE**)lua_touserdata(L, 1);
283 if (f != NULL && *f != NULL) {
284 lua_pushboolean(L, fclose(*f) == 0 ? 1 : 0);
287 lua_pushboolean(L, 0);
293 lua_readfile(lua_State *L)
299 if (lua_gettop(L) < 1 || lua_gettop(L) > 2) {
301 lua_pushinteger(L, 0);
305 f = (FILE**)lua_touserdata(L, 1);
307 if (f == NULL || *f == NULL) {
309 lua_pushinteger(L, 0);
313 if (lua_gettop(L) == 2)
314 size = (size_t)lua_tonumber(L, 2);
319 buf = (char*)malloc(size);
320 r = fread(buf, 1, size, *f);
321 lua_pushlstring(L, buf, r);
323 lua_pushinteger(L, r);
329 * Implements io.write(file, ...)
330 * Any number of string and number arguments may be passed to it,
331 * and it will return the number of bytes written, or nil, an error string, and
335 lua_writefile(lua_State *L)
340 size_t bufsz, w, wrsz;
346 nargs = lua_gettop(L);
349 return luaL_fileresult(L, 0, NULL);
352 f = (FILE**)lua_touserdata(L, 1);
354 if (f == NULL || *f == NULL) {
356 return luaL_fileresult(L, 0, NULL);
359 /* Do a validation pass first */
360 for (i = 0; i < nargs - 1; i++) {
362 * With Lua's API, lua_isstring really checks if the argument
363 * is a string or a number. The latter will be implicitly
364 * converted to a string by our later call to lua_tolstring.
366 if (!lua_isstring(L, i + 2)) {
368 return luaL_fileresult(L, 0, NULL);
371 for (i = 0; i < nargs - 1; i++) {
372 /* We've already validated; there's no chance of failure */
373 buf = lua_tolstring(L, i + 2, &bufsz);
374 wrsz = fwrite(buf, 1, bufsz, *f);
376 return luaL_fileresult(L, 0, NULL);
379 lua_pushinteger(L, w);
384 * put image using terminal coordinates.
387 lua_term_putimage(lua_State *L)
391 uint32_t x1, y1, x2, y2, f;
392 int nargs, ret = 0, error;
394 nargs = lua_gettop(L);
396 lua_pushboolean(L, 0);
400 name = luaL_checkstring(L, 1);
401 x1 = luaL_checknumber(L, 2);
402 y1 = luaL_checknumber(L, 3);
403 x2 = luaL_checknumber(L, 4);
404 y2 = luaL_checknumber(L, 5);
405 f = luaL_checknumber(L, 6);
407 x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
408 y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
410 x2 = gfx_state.tg_origin.tp_col +
411 x2 * gfx_state.tg_font.vf_width;
414 y2 = gfx_state.tg_origin.tp_row +
415 y2 * gfx_state.tg_font.vf_height;
418 if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
419 if (f & FL_PUTIMAGE_DEBUG)
420 printf("%s\n", png_error_string(error));
422 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
424 (void) png_close(&png);
426 lua_pushboolean(L, ret);
431 lua_fb_putimage(lua_State *L)
435 uint32_t x1, y1, x2, y2, f;
436 int nargs, ret = 0, error;
438 nargs = lua_gettop(L);
440 lua_pushboolean(L, 0);
444 name = luaL_checkstring(L, 1);
445 x1 = luaL_checknumber(L, 2);
446 y1 = luaL_checknumber(L, 3);
447 x2 = luaL_checknumber(L, 4);
448 y2 = luaL_checknumber(L, 5);
449 f = luaL_checknumber(L, 6);
451 if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
452 if (f & FL_PUTIMAGE_DEBUG)
453 printf("%s\n", png_error_string(error));
455 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
457 (void) png_close(&png);
459 lua_pushboolean(L, ret);
464 lua_fb_setpixel(lua_State *L)
469 nargs = lua_gettop(L);
475 x = luaL_checknumber(L, 1);
476 y = luaL_checknumber(L, 2);
477 gfx_fb_setpixel(x, y);
482 lua_fb_line(lua_State *L)
484 uint32_t x0, y0, x1, y1, wd;
487 nargs = lua_gettop(L);
493 x0 = luaL_checknumber(L, 1);
494 y0 = luaL_checknumber(L, 2);
495 x1 = luaL_checknumber(L, 3);
496 y1 = luaL_checknumber(L, 4);
497 wd = luaL_checknumber(L, 5);
498 gfx_fb_line(x0, y0, x1, y1, wd);
503 lua_fb_bezier(lua_State *L)
505 uint32_t x0, y0, x1, y1, x2, y2, width;
508 nargs = lua_gettop(L);
514 x0 = luaL_checknumber(L, 1);
515 y0 = luaL_checknumber(L, 2);
516 x1 = luaL_checknumber(L, 3);
517 y1 = luaL_checknumber(L, 4);
518 x2 = luaL_checknumber(L, 5);
519 y2 = luaL_checknumber(L, 6);
520 width = luaL_checknumber(L, 7);
521 gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
526 lua_fb_drawrect(lua_State *L)
528 uint32_t x0, y0, x1, y1, fill;
531 nargs = lua_gettop(L);
537 x0 = luaL_checknumber(L, 1);
538 y0 = luaL_checknumber(L, 2);
539 x1 = luaL_checknumber(L, 3);
540 y1 = luaL_checknumber(L, 4);
541 fill = luaL_checknumber(L, 5);
542 gfx_fb_drawrect(x0, y0, x1, y1, fill);
547 lua_term_drawrect(lua_State *L)
549 uint32_t x0, y0, x1, y1;
552 nargs = lua_gettop(L);
558 x0 = luaL_checknumber(L, 1);
559 y0 = luaL_checknumber(L, 2);
560 x1 = luaL_checknumber(L, 3);
561 y1 = luaL_checknumber(L, 4);
562 gfx_term_drawrect(x0, y0, x1, y1);
566 #define REG_SIMPLE(n) { #n, lua_ ## n }
567 static const struct luaL_Reg loaderlib[] = {
569 REG_SIMPLE(command_error),
571 REG_SIMPLE(interpret),
574 REG_SIMPLE(has_command),
575 REG_SIMPLE(has_feature),
577 REG_SIMPLE(printc), /* Also registered as the global 'printc' */
580 REG_SIMPLE(unsetenv),
584 static const struct luaL_Reg gfxlib[] = {
585 REG_SIMPLE(fb_bezier),
586 REG_SIMPLE(fb_drawrect),
588 REG_SIMPLE(fb_putimage),
589 REG_SIMPLE(fb_setpixel),
590 REG_SIMPLE(term_drawrect),
591 REG_SIMPLE(term_putimage),
595 static const struct luaL_Reg iolib[] = {
596 { "close", lua_closefile },
600 { "open", lua_openfile },
601 { "read", lua_readfile },
602 { "write", lua_writefile },
608 lua_add_feature(void *cookie, const char *name, const char *desc, bool enabled)
610 lua_State *L = cookie;
613 * The feature table consists solely of features that are enabled, and
614 * their associated descriptions for debugging purposes.
616 lua_pushstring(L, desc);
617 lua_setfield(L, -2, name);
621 lua_add_features(lua_State *L)
625 feature_iter(&lua_add_feature, L);
628 * We should still have just the table on the stack after we're done
631 lua_setfield(L, -2, "features");
635 luaopen_gfx(lua_State *L)
637 luaL_newlib(L, gfxlib);
641 luaopen_loader(lua_State *L)
643 luaL_newlib(L, loaderlib);
645 /* Add loader.machine and loader.machine_arch properties */
646 lua_pushstring(L, MACHINE);
647 lua_setfield(L, -2, "machine");
648 lua_pushstring(L, MACHINE_ARCH);
649 lua_setfield(L, -2, "machine_arch");
650 lua_pushstring(L, LUA_PATH);
651 lua_setfield(L, -2, "lua_path");
652 lua_pushinteger(L, bootprog_rev);
653 lua_setfield(L, -2, "version");
654 lua_pushinteger(L, CMD_OK);
655 lua_setfield(L, -2, "CMD_OK");
656 lua_pushinteger(L, CMD_WARN);
657 lua_setfield(L, -2, "CMD_WARN");
658 lua_pushinteger(L, CMD_ERROR);
659 lua_setfield(L, -2, "CMD_ERROR");
660 lua_pushinteger(L, CMD_CRIT);
661 lua_setfield(L, -2, "CMD_CRIT");
662 lua_pushinteger(L, CMD_FATAL);
663 lua_setfield(L, -2, "CMD_FATAL");
665 /* Set global printc to loader.printc */
666 lua_register(L, "printc", lua_printc);
671 luaopen_io(lua_State *L)
673 luaL_newlib(L, iolib);