xref: /freebsd/stand/common/interp_lua.c (revision 7cafeaa1fde93dbefa40971343bf9a3bb92f2ede)
1*7cafeaa1SWarner Losh /*-
2*7cafeaa1SWarner Losh  * Copyright (c) 2011 Wojciech A. Koszek <wkoszek@FreeBSD.org>
3*7cafeaa1SWarner Losh  * Copyright (c) 2014 Pedro Souza <pedrosouza@freebsd.org>
4*7cafeaa1SWarner Losh  * All rights reserved.
5*7cafeaa1SWarner Losh  *
6*7cafeaa1SWarner Losh  * Redistribution and use in source and binary forms, with or without
7*7cafeaa1SWarner Losh  * modification, are permitted provided that the following conditions
8*7cafeaa1SWarner Losh  * are met:
9*7cafeaa1SWarner Losh  * 1. Redistributions of source code must retain the above copyright
10*7cafeaa1SWarner Losh  *    notice, this list of conditions and the following disclaimer.
11*7cafeaa1SWarner Losh  * 2. Redistributions in binary form must reproduce the above copyright
12*7cafeaa1SWarner Losh  *    notice, this list of conditions and the following disclaimer in the
13*7cafeaa1SWarner Losh  *    documentation and/or other materials provided with the distribution.
14*7cafeaa1SWarner Losh  *
15*7cafeaa1SWarner Losh  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*7cafeaa1SWarner Losh  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*7cafeaa1SWarner Losh  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*7cafeaa1SWarner Losh  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*7cafeaa1SWarner Losh  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*7cafeaa1SWarner Losh  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*7cafeaa1SWarner Losh  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*7cafeaa1SWarner Losh  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*7cafeaa1SWarner Losh  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*7cafeaa1SWarner Losh  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*7cafeaa1SWarner Losh  * SUCH DAMAGE.
26*7cafeaa1SWarner Losh  */
27*7cafeaa1SWarner Losh 
28*7cafeaa1SWarner Losh #include <sys/cdefs.h>
29*7cafeaa1SWarner Losh __FBSDID("$FreeBSD$");
30*7cafeaa1SWarner Losh 
31*7cafeaa1SWarner Losh #include <stand.h>
32*7cafeaa1SWarner Losh #include "bootstrap.h"
33*7cafeaa1SWarner Losh 
34*7cafeaa1SWarner Losh #define lua_c
35*7cafeaa1SWarner Losh 
36*7cafeaa1SWarner Losh #include "lstd.h"
37*7cafeaa1SWarner Losh 
38*7cafeaa1SWarner Losh #include <lua.h>
39*7cafeaa1SWarner Losh #include <ldebug.h>
40*7cafeaa1SWarner Losh #include <lauxlib.h>
41*7cafeaa1SWarner Losh #include <lualib.h>
42*7cafeaa1SWarner Losh #include <lutils.h>
43*7cafeaa1SWarner Losh 
44*7cafeaa1SWarner Losh struct interp_lua_softc {
45*7cafeaa1SWarner Losh 	lua_State	*luap;
46*7cafeaa1SWarner Losh };
47*7cafeaa1SWarner Losh 
48*7cafeaa1SWarner Losh static struct interp_lua_softc lua_softc;
49*7cafeaa1SWarner Losh 
50*7cafeaa1SWarner Losh #ifdef LUA_DEBUG
51*7cafeaa1SWarner Losh #define	LDBG(...)	do {			\
52*7cafeaa1SWarner Losh 	printf("%s(%d): ", __func__, __LINE__);	\
53*7cafeaa1SWarner Losh 	printf(__VA_ARGS__);			\
54*7cafeaa1SWarner Losh 	printf("\n");				\
55*7cafeaa1SWarner Losh } while (0)
56*7cafeaa1SWarner Losh #else
57*7cafeaa1SWarner Losh #define	LDBG(...)
58*7cafeaa1SWarner Losh #endif
59*7cafeaa1SWarner Losh 
60*7cafeaa1SWarner Losh 
61*7cafeaa1SWarner Losh static void *
62*7cafeaa1SWarner Losh interp_lua_realloc(void *ud __unused, void *ptr, size_t osize __unused, size_t nsize)
63*7cafeaa1SWarner Losh {
64*7cafeaa1SWarner Losh 
65*7cafeaa1SWarner Losh 	if (nsize == 0) {
66*7cafeaa1SWarner Losh 		free(ptr);
67*7cafeaa1SWarner Losh 		return NULL;
68*7cafeaa1SWarner Losh 	}
69*7cafeaa1SWarner Losh 	return realloc(ptr, nsize);
70*7cafeaa1SWarner Losh }
71*7cafeaa1SWarner Losh 
72*7cafeaa1SWarner Losh /*
73*7cafeaa1SWarner Losh  * The libraries commented out below either lack the proper
74*7cafeaa1SWarner Losh  * support from libsa, or they are unlikely to be useful
75*7cafeaa1SWarner Losh  * in the bootloader, so have been commented out.
76*7cafeaa1SWarner Losh  */
77*7cafeaa1SWarner Losh static const luaL_Reg loadedlibs[] = {
78*7cafeaa1SWarner Losh   {"_G", luaopen_base},
79*7cafeaa1SWarner Losh   {LUA_LOADLIBNAME, luaopen_package},
80*7cafeaa1SWarner Losh //  {LUA_COLIBNAME, luaopen_coroutine},
81*7cafeaa1SWarner Losh //  {LUA_TABLIBNAME, luaopen_table},
82*7cafeaa1SWarner Losh   {LUA_STRLIBNAME, luaopen_string},
83*7cafeaa1SWarner Losh //  {LUA_IOLIBNAME, luaopen_io},
84*7cafeaa1SWarner Losh //  {LUA_OSLIBNAME, luaopen_os},
85*7cafeaa1SWarner Losh //  {LUA_MATHLIBNAME, luaopen_math},
86*7cafeaa1SWarner Losh //  {LUA_UTF8LIBNAME, luaopen_utf8},
87*7cafeaa1SWarner Losh //  {LUA_DBLIBNAME, luaopen_debug},
88*7cafeaa1SWarner Losh   {NULL, NULL}
89*7cafeaa1SWarner Losh };
90*7cafeaa1SWarner Losh 
91*7cafeaa1SWarner Losh void
92*7cafeaa1SWarner Losh interp_init(void)
93*7cafeaa1SWarner Losh {
94*7cafeaa1SWarner Losh 	lua_State *luap;
95*7cafeaa1SWarner Losh 	struct interp_lua_softc	*softc = &lua_softc;
96*7cafeaa1SWarner Losh 	const char *filename;
97*7cafeaa1SWarner Losh 	const luaL_Reg *lib;
98*7cafeaa1SWarner Losh 
99*7cafeaa1SWarner Losh 	setenv("script.lang", "lua", 1);
100*7cafeaa1SWarner Losh 	LDBG("creating context");
101*7cafeaa1SWarner Losh 
102*7cafeaa1SWarner Losh 	luap = lua_newstate(interp_lua_realloc, NULL);
103*7cafeaa1SWarner Losh 	if (luap == NULL) {
104*7cafeaa1SWarner Losh 		printf("problem initializing the Lua interpreter\n");
105*7cafeaa1SWarner Losh 		abort();
106*7cafeaa1SWarner Losh 	}
107*7cafeaa1SWarner Losh 	softc->luap = luap;
108*7cafeaa1SWarner Losh 	register_utils(luap);
109*7cafeaa1SWarner Losh 
110*7cafeaa1SWarner Losh 	/* "require" functions from 'loadedlibs' and set results to global table */
111*7cafeaa1SWarner Losh 	for (lib = loadedlibs; lib->func; lib++) {
112*7cafeaa1SWarner Losh 		luaL_requiref(luap, lib->name, lib->func, 1);
113*7cafeaa1SWarner Losh 		lua_pop(luap, 1);  /* remove lib */
114*7cafeaa1SWarner Losh 	}
115*7cafeaa1SWarner Losh 
116*7cafeaa1SWarner Losh 	filename = "/boot/lua/loader.lua";
117*7cafeaa1SWarner Losh 	if (interp_include(filename) != 0) {
118*7cafeaa1SWarner Losh                 const char *errstr = lua_tostring(luap, -1);
119*7cafeaa1SWarner Losh                 errstr = errstr == NULL ? "unknown" : errstr;
120*7cafeaa1SWarner Losh                 printf("Startup errorr in %s:\nLUA ERROR: %s.\n", filename, errstr);
121*7cafeaa1SWarner Losh                 lua_pop(luap, 1);
122*7cafeaa1SWarner Losh 	}
123*7cafeaa1SWarner Losh }
124*7cafeaa1SWarner Losh 
125*7cafeaa1SWarner Losh int
126*7cafeaa1SWarner Losh interp_run(const char *line)
127*7cafeaa1SWarner Losh {
128*7cafeaa1SWarner Losh 	int	argc;
129*7cafeaa1SWarner Losh 	char	**argv;
130*7cafeaa1SWarner Losh 	lua_State *luap;
131*7cafeaa1SWarner Losh 	struct interp_lua_softc	*softc = &lua_softc;
132*7cafeaa1SWarner Losh 	int status;
133*7cafeaa1SWarner Losh 
134*7cafeaa1SWarner Losh 	luap = softc->luap;
135*7cafeaa1SWarner Losh 	LDBG("executing line...");
136*7cafeaa1SWarner Losh 	if ((status = luaL_dostring(luap, line)) != 0) {
137*7cafeaa1SWarner Losh 		/*
138*7cafeaa1SWarner Losh 		 * If we could not parse the line as Lua syntax,
139*7cafeaa1SWarner Losh 		 * try parsing it as a loader command.
140*7cafeaa1SWarner Losh 		 */
141*7cafeaa1SWarner Losh                 lua_pop(luap, 1);
142*7cafeaa1SWarner Losh 		if (parse(&argc, &argv, line) == 0) {
143*7cafeaa1SWarner Losh 			status = interp_builtin_cmd(argc, argv);
144*7cafeaa1SWarner Losh 			if (status != CMD_OK)
145*7cafeaa1SWarner Losh 				printf("Command failed\n");
146*7cafeaa1SWarner Losh 			free(argv);
147*7cafeaa1SWarner Losh 		} else {
148*7cafeaa1SWarner Losh 			printf("Failed to parse \'%s\'\n", line);
149*7cafeaa1SWarner Losh 			status = -1;
150*7cafeaa1SWarner Losh 		}
151*7cafeaa1SWarner Losh 	}
152*7cafeaa1SWarner Losh 
153*7cafeaa1SWarner Losh 	return (status == 0 ? CMD_OK : CMD_ERROR);
154*7cafeaa1SWarner Losh }
155*7cafeaa1SWarner Losh 
156*7cafeaa1SWarner Losh int
157*7cafeaa1SWarner Losh interp_include(const char *filename)
158*7cafeaa1SWarner Losh {
159*7cafeaa1SWarner Losh 	struct interp_lua_softc	*softc = &lua_softc;
160*7cafeaa1SWarner Losh 
161*7cafeaa1SWarner Losh 	LDBG("loading file %s", filename);
162*7cafeaa1SWarner Losh 
163*7cafeaa1SWarner Losh 	return (luaL_dofile(softc->luap, filename));
164*7cafeaa1SWarner Losh }
165