]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/liblua/lutils.c
Merge llvm-project main llvmorg-17-init-19304-gd0b54bb50e51
[FreeBSD/FreeBSD.git] / stand / liblua / lutils.c
1 /*-
2  * Copyright (c) 2014 Pedro Souza <pedrosouza@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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
24  * SUCH DAMAGE.
25  *
26  */
27
28 #include <sys/param.h>
29
30 #include "lua.h"
31 #include "lauxlib.h"
32 #include "lstd.h"
33 #include "lutils.h"
34 #include "bootstrap.h"
35 #include <gfx_fb.h>
36 #include <pnglite.h>
37
38 /*
39  * Like loader.perform, except args are passed already parsed
40  * on the stack.
41  */
42 static int
43 lua_command(lua_State *L)
44 {
45         int     i;
46         int     res = 1;
47         int     argc = lua_gettop(L);
48         char    **argv;
49
50         argv = malloc(sizeof(char *) * (argc + 1));
51         if (argv == NULL)
52                 return 0;
53         for (i = 0; i < argc; i++)
54                 argv[i] = (char *)(intptr_t)luaL_checkstring(L, i + 1);
55         argv[argc] = NULL;
56         res = interp_builtin_cmd(argc, argv);
57         free(argv);
58         lua_pushinteger(L, res);
59
60         return 1;
61 }
62
63 static int
64 lua_has_command(lua_State *L)
65 {
66         const char      *cmd;
67
68         if (lua_gettop(L) != 1) {
69                 lua_pushnil(L);
70                 return 1;
71         }
72         cmd = luaL_checkstring(L, 1);
73         lua_pushinteger(L, interp_has_builtin_cmd(cmd));
74
75         return 1;
76 }
77
78 static int
79 lua_perform(lua_State *L)
80 {
81         int     argc;
82         char    **argv;
83         int     res = 1;
84
85         if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
86                 res = interp_builtin_cmd(argc, argv);
87                 free(argv);
88         }
89         lua_pushinteger(L, res);
90
91         return 1;
92 }
93
94 static int
95 lua_command_error(lua_State *L)
96 {
97
98         lua_pushstring(L, command_errbuf);
99         return 1;
100 }
101
102 /*
103  * Accepts a space-delimited loader command and runs it through the standard
104  * loader parsing, as if it were executed at the loader prompt by the user.
105  */
106 static int
107 lua_interpret(lua_State *L)
108 {
109         const char      *interp_string;
110
111         if (lua_gettop(L) != 1) {
112                 lua_pushnil(L);
113                 return 1;
114         }
115
116         interp_string = luaL_checkstring(L, 1);
117         lua_pushinteger(L, interp_run(interp_string));
118         return 1;
119 }
120
121 static int
122 lua_parse(lua_State *L)
123 {
124         int     argc, nargc;
125         char    **argv;
126
127         if (parse(&argc, &argv, luaL_checkstring(L, 1)) == 0) {
128                 for (nargc = 0; nargc < argc; ++nargc) {
129                         lua_pushstring(L, argv[nargc]);
130                 }
131                 free(argv);
132                 return nargc;
133         }
134
135         lua_pushnil(L);
136         return 1;
137 }
138
139 static int
140 lua_getchar(lua_State *L)
141 {
142
143         lua_pushinteger(L, getchar());
144         return 1;
145 }
146
147 static int
148 lua_ischar(lua_State *L)
149 {
150
151         lua_pushboolean(L, ischar());
152         return 1;
153 }
154
155 static int
156 lua_gets(lua_State *L)
157 {
158         char    buf[129];
159
160         ngets(buf, 128);
161         lua_pushstring(L, buf);
162         return 1;
163 }
164
165 static int
166 lua_time(lua_State *L)
167 {
168
169         lua_pushinteger(L, time(NULL));
170         return 1;
171 }
172
173 static int
174 lua_delay(lua_State *L)
175 {
176
177         delay((int)luaL_checknumber(L, 1));
178         return 0;
179 }
180
181 static int
182 lua_getenv(lua_State *L)
183 {
184         lua_pushstring(L, getenv(luaL_checkstring(L, 1)));
185
186         return 1;
187 }
188
189 static int
190 lua_setenv(lua_State *L)
191 {
192         const char *key, *val;
193
194         key = luaL_checkstring(L, 1);
195         val = luaL_checkstring(L, 2);
196         lua_pushinteger(L, setenv(key, val, 1));
197
198         return 1;
199 }
200
201 static int
202 lua_unsetenv(lua_State *L)
203 {
204         const char      *ev;
205
206         ev = luaL_checkstring(L, 1);
207         lua_pushinteger(L, unsetenv(ev));
208
209         return 1;
210 }
211
212 static int
213 lua_printc(lua_State *L)
214 {
215         ssize_t cur, l;
216         const char *s = luaL_checklstring(L, 1, &l);
217
218         for (cur = 0; cur < l; ++cur)
219                 putchar((unsigned char)*(s++));
220
221         return 1;
222 }
223
224 static int
225 lua_openfile(lua_State *L)
226 {
227         const char      *mode, *str;
228         int     nargs;
229
230         nargs = lua_gettop(L);
231         if (nargs < 1 || nargs > 2) {
232                 lua_pushnil(L);
233                 return 1;
234         }
235         str = lua_tostring(L, 1);
236         mode = "r";
237         if (nargs > 1) {
238                 mode = lua_tostring(L, 2);
239                 if (mode == NULL) {
240                         lua_pushnil(L);
241                         return 1;
242                 }
243         }
244         FILE * f = fopen(str, mode);
245         if (f != NULL) {
246                 FILE ** ptr = (FILE**)lua_newuserdata(L, sizeof(FILE**));
247                 *ptr = f;
248         } else
249                 lua_pushnil(L);
250         return 1;
251 }
252
253 static int
254 lua_closefile(lua_State *L)
255 {
256         FILE ** f;
257         if (lua_gettop(L) != 1) {
258                 lua_pushboolean(L, 0);
259                 return 1;
260         }
261
262         f = (FILE**)lua_touserdata(L, 1);
263         if (f != NULL && *f != NULL) {
264                 lua_pushboolean(L, fclose(*f) == 0 ? 1 : 0);
265                 *f = NULL;
266         } else
267                 lua_pushboolean(L, 0);
268
269         return 1;
270 }
271
272 static int
273 lua_readfile(lua_State *L)
274 {
275         FILE    **f;
276         size_t  size, r;
277         char * buf;
278
279         if (lua_gettop(L) < 1 || lua_gettop(L) > 2) {
280                 lua_pushnil(L);
281                 lua_pushinteger(L, 0);
282                 return 2;
283         }
284
285         f = (FILE**)lua_touserdata(L, 1);
286
287         if (f == NULL || *f == NULL) {
288                 lua_pushnil(L);
289                 lua_pushinteger(L, 0);
290                 return 2;
291         }
292
293         if (lua_gettop(L) == 2)
294                 size = (size_t)lua_tonumber(L, 2);
295         else
296                 size = (*f)->size;
297
298
299         buf = (char*)malloc(size);
300         r = fread(buf, 1, size, *f);
301         lua_pushlstring(L, buf, r);
302         free(buf);
303         lua_pushinteger(L, r);
304
305         return 2;
306 }
307
308 /*
309  * Implements io.write(file, ...)
310  * Any number of string and number arguments may be passed to it,
311  * and it will return the number of bytes written, or nil, an error string, and
312  * the errno.
313  */
314 static int
315 lua_writefile(lua_State *L)
316 {
317         FILE    **f;
318         const char      *buf;
319         int     i, nargs;
320         size_t  bufsz, w, wrsz;
321
322         buf = NULL;
323         bufsz = 0;
324         w = 0;
325         wrsz = 0;
326         nargs = lua_gettop(L);
327         if (nargs < 2) {
328                 errno = EINVAL;
329                 return luaL_fileresult(L, 0, NULL);
330         }
331
332         f = (FILE**)lua_touserdata(L, 1);
333
334         if (f == NULL || *f == NULL) {
335                 errno = EINVAL;
336                 return luaL_fileresult(L, 0, NULL);
337         }
338
339         /* Do a validation pass first */
340         for (i = 0; i < nargs - 1; i++) {
341                 /*
342                  * With Lua's API, lua_isstring really checks if the argument
343                  * is a string or a number.  The latter will be implicitly
344                  * converted to a string by our later call to lua_tolstring.
345                  */
346                 if (!lua_isstring(L, i + 2)) {
347                         errno = EINVAL;
348                         return luaL_fileresult(L, 0, NULL);
349                 }
350         }
351         for (i = 0; i < nargs - 1; i++) {
352                 /* We've already validated; there's no chance of failure */
353                 buf = lua_tolstring(L, i + 2, &bufsz);
354                 wrsz = fwrite(buf, 1, bufsz, *f);
355                 if (wrsz < bufsz)
356                         return luaL_fileresult(L, 0, NULL);
357                 w += wrsz;
358         }
359         lua_pushinteger(L, w);
360         return 1;
361 }
362
363 /*
364  * put image using terminal coordinates.
365  */
366 static int
367 lua_term_putimage(lua_State *L)
368 {
369         const char *name;
370         png_t png;
371         uint32_t x1, y1, x2, y2, f;
372         int nargs, ret = 0, error;
373
374         nargs = lua_gettop(L);
375         if (nargs != 6) {
376                 lua_pushboolean(L, 0);
377                 return 1;
378         }
379
380         name = luaL_checkstring(L, 1);
381         x1 = luaL_checknumber(L, 2);
382         y1 = luaL_checknumber(L, 3);
383         x2 = luaL_checknumber(L, 4);
384         y2 = luaL_checknumber(L, 5);
385         f = luaL_checknumber(L, 6);
386
387         x1 = gfx_state.tg_origin.tp_col + x1 * gfx_state.tg_font.vf_width;
388         y1 = gfx_state.tg_origin.tp_row + y1 * gfx_state.tg_font.vf_height;
389         if (x2 != 0) {
390                 x2 = gfx_state.tg_origin.tp_col +
391                     x2 * gfx_state.tg_font.vf_width;
392         }
393         if (y2 != 0) {
394                 y2 = gfx_state.tg_origin.tp_row +
395                     y2 * gfx_state.tg_font.vf_height;
396         }
397
398         if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
399                 if (f & FL_PUTIMAGE_DEBUG)
400                         printf("%s\n", png_error_string(error));
401         } else {
402                 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
403                         ret = 1;
404                 (void) png_close(&png);
405         }
406         lua_pushboolean(L, ret);
407         return 1;
408 }
409
410 static int
411 lua_fb_putimage(lua_State *L)
412 {
413         const char *name;
414         png_t png;
415         uint32_t x1, y1, x2, y2, f;
416         int nargs, ret = 0, error;
417
418         nargs = lua_gettop(L);
419         if (nargs != 6) {
420                 lua_pushboolean(L, 0);
421                 return 1;
422         }
423
424         name = luaL_checkstring(L, 1);
425         x1 = luaL_checknumber(L, 2);
426         y1 = luaL_checknumber(L, 3);
427         x2 = luaL_checknumber(L, 4);
428         y2 = luaL_checknumber(L, 5);
429         f = luaL_checknumber(L, 6);
430
431         if ((error = png_open(&png, name)) != PNG_NO_ERROR) {
432                 if (f & FL_PUTIMAGE_DEBUG)
433                         printf("%s\n", png_error_string(error));
434         } else {
435                 if (gfx_fb_putimage(&png, x1, y1, x2, y2, f) == 0)
436                         ret = 1;
437                 (void) png_close(&png);
438         }
439         lua_pushboolean(L, ret);
440         return 1;
441 }
442
443 static int
444 lua_fb_setpixel(lua_State *L)
445 {
446         uint32_t x, y;
447         int nargs;
448
449         nargs = lua_gettop(L);
450         if (nargs != 2) {
451                 lua_pushnil(L);
452                 return 1;
453         }
454
455         x = luaL_checknumber(L, 1);
456         y = luaL_checknumber(L, 2);
457         gfx_fb_setpixel(x, y);
458         return 0;
459 }
460
461 static int
462 lua_fb_line(lua_State *L)
463 {
464         uint32_t x0, y0, x1, y1, wd;
465         int nargs;
466
467         nargs = lua_gettop(L);
468         if (nargs != 5) {
469                 lua_pushnil(L);
470                 return 1;
471         }
472
473         x0 = luaL_checknumber(L, 1);
474         y0 = luaL_checknumber(L, 2);
475         x1 = luaL_checknumber(L, 3);
476         y1 = luaL_checknumber(L, 4);
477         wd = luaL_checknumber(L, 5);
478         gfx_fb_line(x0, y0, x1, y1, wd);
479         return 0;
480 }
481
482 static int
483 lua_fb_bezier(lua_State *L)
484 {
485         uint32_t x0, y0, x1, y1, x2, y2, width;
486         int nargs;
487
488         nargs = lua_gettop(L);
489         if (nargs != 7) {
490                 lua_pushnil(L);
491                 return 1;
492         }
493
494         x0 = luaL_checknumber(L, 1);
495         y0 = luaL_checknumber(L, 2);
496         x1 = luaL_checknumber(L, 3);
497         y1 = luaL_checknumber(L, 4);
498         x2 = luaL_checknumber(L, 5);
499         y2 = luaL_checknumber(L, 6);
500         width = luaL_checknumber(L, 7);
501         gfx_fb_bezier(x0, y0, x1, y1, x2, y2, width);
502         return 0;
503 }
504
505 static int
506 lua_fb_drawrect(lua_State *L)
507 {
508         uint32_t x0, y0, x1, y1, fill;
509         int nargs;
510
511         nargs = lua_gettop(L);
512         if (nargs != 5) {
513                 lua_pushnil(L);
514                 return 1;
515         }
516
517         x0 = luaL_checknumber(L, 1);
518         y0 = luaL_checknumber(L, 2);
519         x1 = luaL_checknumber(L, 3);
520         y1 = luaL_checknumber(L, 4);
521         fill = luaL_checknumber(L, 5);
522         gfx_fb_drawrect(x0, y0, x1, y1, fill);
523         return 0;
524 }
525
526 static int
527 lua_term_drawrect(lua_State *L)
528 {
529         uint32_t x0, y0, x1, y1;
530         int nargs;
531
532         nargs = lua_gettop(L);
533         if (nargs != 4) {
534                 lua_pushnil(L);
535                 return 1;
536         }
537
538         x0 = luaL_checknumber(L, 1);
539         y0 = luaL_checknumber(L, 2);
540         x1 = luaL_checknumber(L, 3);
541         y1 = luaL_checknumber(L, 4);
542         gfx_term_drawrect(x0, y0, x1, y1);
543         return 0;
544 }
545
546 #define REG_SIMPLE(n)   { #n, lua_ ## n }
547 static const struct luaL_Reg loaderlib[] = {
548         REG_SIMPLE(delay),
549         REG_SIMPLE(command_error),
550         REG_SIMPLE(command),
551         REG_SIMPLE(interpret),
552         REG_SIMPLE(parse),
553         REG_SIMPLE(getenv),
554         REG_SIMPLE(has_command),
555         REG_SIMPLE(perform),
556         REG_SIMPLE(printc),     /* Also registered as the global 'printc' */
557         REG_SIMPLE(setenv),
558         REG_SIMPLE(time),
559         REG_SIMPLE(unsetenv),
560         REG_SIMPLE(fb_bezier),
561         REG_SIMPLE(fb_drawrect),
562         REG_SIMPLE(fb_line),
563         REG_SIMPLE(fb_putimage),
564         REG_SIMPLE(fb_setpixel),
565         REG_SIMPLE(term_drawrect),
566         REG_SIMPLE(term_putimage),
567         { NULL, NULL },
568 };
569
570 static const struct luaL_Reg iolib[] = {
571         { "close", lua_closefile },
572         REG_SIMPLE(getchar),
573         REG_SIMPLE(gets),
574         REG_SIMPLE(ischar),
575         { "open", lua_openfile },
576         { "read", lua_readfile },
577         { "write", lua_writefile },
578         { NULL, NULL },
579 };
580 #undef REG_SIMPLE
581
582 int
583 luaopen_loader(lua_State *L)
584 {
585         luaL_newlib(L, loaderlib);
586         /* Add loader.machine and loader.machine_arch properties */
587         lua_pushstring(L, MACHINE);
588         lua_setfield(L, -2, "machine");
589         lua_pushstring(L, MACHINE_ARCH);
590         lua_setfield(L, -2, "machine_arch");
591         lua_pushstring(L, LUA_PATH);
592         lua_setfield(L, -2, "lua_path");
593         lua_pushinteger(L, bootprog_rev);
594         lua_setfield(L, -2, "version");
595         /* Set global printc to loader.printc */
596         lua_register(L, "printc", lua_printc);
597         return 1;
598 }
599
600 int
601 luaopen_io(lua_State *L)
602 {
603         luaL_newlib(L, iolib);
604         return 1;
605 }