diff --git a/.gitignore b/.gitignore index 0ae73233a..b1ef6cfe6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ *.swp *.sym *~ +.context .depend .kconfig /bin diff --git a/interpreters/README.md b/interpreters/README.md index 0379e1eee..0a1d1c66f 100644 --- a/interpreters/README.md +++ b/interpreters/README.md @@ -10,6 +10,22 @@ http://ficl.sourceforge.net/. It is a _DIY_ port because the Ficl source is not in that directory, only an environment and instructions that will let you build Ficl under NuttX. The rest is up to you. +## Lua + +Fetch and build a Lua interpreter. Versions 5.2 through 5.4 are supported. The +`lua` command will be added to NSH. Lua can run a script for a given path, +execute a string of code, or open a readline compatible REPL on the NSH console. +The `` and `` headers are available to start a new embedded +interpreter or extend Lua with C modules. See the `luamod_hello` example for how +to include a built-in module. + +A math library is required to build. Enable the `LIBM` config or use a +toolchain provided math library. + +The following configs are recommended for a full featured Lua interpreter: +- `LIBC_FLOATINGPOINT` +- `SYSTEM_READLINE` + ## Mini Basic The Mini Basic implementation at `apps/interpreters` derives from version `1.0` diff --git a/interpreters/lua/.gitignore b/interpreters/lua/.gitignore new file mode 100644 index 000000000..f9f1324d4 --- /dev/null +++ b/interpreters/lua/.gitignore @@ -0,0 +1,4 @@ +lua-*.tar.gz +lua-*/ +/luamod_list.h +/luamod_proto.h diff --git a/interpreters/lua/Kconfig b/interpreters/lua/Kconfig new file mode 100644 index 000000000..8afeb0549 --- /dev/null +++ b/interpreters/lua/Kconfig @@ -0,0 +1,67 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menuconfig INTERPRETERS_LUA + bool "Lua interpreter support" + default n + select ARCH_SETJMP_H + select LIBC_LOCALE + ---help--- + Embed Lua language interpreter. + Select the Lua version with the INTERPRETER_LUA_VERSION config. + A math library is required. Use the LIBM config or a toolchain library. + It's suggested to enable the SYSTEM_READLINE and LIBC_FLOATINGPOINT configs. + +if INTERPRETERS_LUA + +config INTERPRETER_LUA_VERSION + string "Lua interpreter version" + default "5.4.0" + ---help--- + Lua release version to fetch and build. + Versions 5.2.0 and up are supported. + +config INTERPRETER_LUA_CORELIBS + bool "Load core Lua modules" + default y + select SYSTEM_SYSTEM + ---help--- + Load core Lua modules like "os", "string", and "table". + +config INTERPRETER_LUA_PATH + string "Lua modules search path" + ---help--- + Override default package.path search path for Lua modules. + +config INTERPRETER_LUA_CPATH + string "Lua C modules search path" + ---help--- + Override default package.cpath search path for C modules. + +config INTERPRETER_LUA_32BIT + bool "Use 32-bit integers and floats" + default y + ---help--- + "Use int and float instead of long and double for Lua numbers." + +config INTERPRETER_LUA_PRIORITY + int "Lua interpreter priority" + default 100 + ---help--- + Task priority of the Lua interpreter main task. + +config INTERPRETER_LUA_STACKSIZE + int "Lua interpreter stack size" + default 32768 + ---help--- + Size of the stack allocated for the Lua interpreter main task. + +config INTERPRETER_LUA_IOBUFSIZE + int "I/O buffer size" + default 1024 + ---help--- + Size of the statically allocated I/O buffer. + +endif # INTERPRETERS_LUA diff --git a/interpreters/lua/Make.defs b/interpreters/lua/Make.defs new file mode 100644 index 000000000..bbdf382ea --- /dev/null +++ b/interpreters/lua/Make.defs @@ -0,0 +1,31 @@ +############################################################################ +# apps/interpreters/lua/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_INTERPRETERS_LUA),) +CONFIGURED_APPS += $(APPDIR)/interpreters/lua + +# Enable and includes. + +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \ + $(APPDIR)/interpreters/lua/lua-$(CONFIG_INTERPRETER_LUA_VERSION)/src} +CXXFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \ + $(APPDIR)/interpreters/lua/lua-$(CONFIG_INTERPRETER_LUA_VERSION)/src} + +endif diff --git a/interpreters/lua/Makefile b/interpreters/lua/Makefile new file mode 100644 index 000000000..246bf58a7 --- /dev/null +++ b/interpreters/lua/Makefile @@ -0,0 +1,133 @@ +############################################################################ +# apps/interpreters/lua/Makefile +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +# Lua built-in application info + +PROGNAME = lua +PRIORITY = $(CONFIG_INTERPRETER_LUA_PRIORITY) +STACKSIZE = $(CONFIG_INTERPRETER_LUA_STACKSIZE) +MODULE = $(CONFIG_INTERPRETERS_LUA) + +# Lua library + +LUA_VERSION = $(patsubst "%",%,$(strip $(CONFIG_INTERPRETER_LUA_VERSION))) +LUA_TARBALL = lua-$(LUA_VERSION).tar.gz +LUA_UNPACK = lua-$(LUA_VERSION) +LUA_URL_BASE = http://www.lua.org/ftp +LUA_URL = $(LUA_URL_BASE)/$(LUA_TARBALL) +LUA_SRC = $(LUA_UNPACK)$(DELIM)src + +MAINSRC = $(LUA_SRC)$(DELIM)lua.c +CORELIBS_SRCS = $(filter-out $(LUA_SRC)$(DELIM)lauxlib.c,$(wildcard $(LUA_SRC)$(DELIM)*lib.c)) +EXCLUDE_SRCS = $(MAINSRC) $(CORELIBS_SRCS) $(LUA_SRC)$(DELIM)luac.c $(LUA_SRC)$(DELIM)linit.c +CSRCS = $(filter-out $(EXCLUDE_SRCS),$(wildcard $(LUA_SRC)$(DELIM)*.c)) +CSRCS += nuttx_linit.c + +CFLAGS += -DLUA_MAXINPUT=$(CONFIG_INTERPRETER_LUA_IOBUFSIZE) +CFLAGS += -DLUA_PROGNAME=\"$(PROGNAME)\" + +ifeq ($(CONFIG_INTERPRETER_LUA_32BITS),y) +CFLAGS += -DLUA_32BITS +endif + +ifneq ($(CONFIG_INTERPRETER_LUA_PATH),"") +CFLAGS += -DLUA_PATH_DEFAULT=\"$(CONFIG_INTERPRETER_LUA_PATH)\" +endif + +ifneq ($(CONFIG_INTERPRETER_LUA_CPATH),"") +CFLAGS += -DLUA_CPATH_DEFAULT=\"$(CONFIG_INTERPRETER_LUA_CPATH)\" +endif + +ifeq ($(CONFIG_SYSTEM_READLINE),y) +CFLAGS += -include "system/readline.h" +CFLAGS += -D'lua_initreadline(L)=((void)L)' +CFLAGS += -D'lua_readline(L,b,p)=((void)L,fputs(p,stdout),fflush(stdout),readline(b,LUA_MAXINPUT,stdin,stdout))' +CFLAGS += -D'lua_saveline(L,line)={(void)L;(void)line;}' +CFLAGS += -D'lua_freeline(L,line)={(void)L;(void)b;}' +endif + +# Lua download and unpack + +$(LUA_TARBALL): + $(Q) echo "Downloading $(LUA_TARBALL)" + $(Q) curl -O -L $(LUA_URL) + +$(LUA_UNPACK): $(LUA_TARBALL) + $(Q) echo "Unpacking $(LUA_TARBALL) to $(LUA_UNPACK)" + $(Q) tar -xvzf $(LUA_TARBALL) + +context:: $(LUA_UNPACK) + +# Register core modules + +ifeq ($(CONFIG_INTERPRETER_LUA_CORELIBS),y) +CSRCS += $(CORELIBS_SRCS) + +register:: + # collect core module names from defines in lualib.h + $(Q) awk '{ if (match($$0,/LUA_[A-Z]+LIBNAME\s"([a-z]+)"$$/,m)) \ + printf "{ \"%s\", luaopen_%s },\n", m[1], m[1] > "registry$(DELIM)"m[1]".bdat" }' \ + $(LUA_SRC)$(DELIM)lualib.h +endif + +# Lua builtin module registry + +PDATLIST = $(strip $(call RWILDCARD, registry, *.pdat)) +BDATLIST = $(strip $(call RWILDCARD, registry, *.bdat)) + +lua_main.c: luamod_list.h luamod_proto.h + +registry$(DELIM).updated: + $(Q) touch registry$(DELIM).updated + +luamod_list.h: registry$(DELIM).updated +ifeq ($(BDATLIST),) + $(call DELFILE, luamod_list.h) + $(Q) touch luamod_list.h +else + $(call CATFILE, luamod_list.h, $(BDATLIST)) +endif + +luamod_proto.h: registry$(DELIM).updated +ifeq ($(PDATLIST),) + $(call DELFILE, luamod_proto.h) + $(Q) touch luamod_proto.h +else + $(call CATFILE, luamod_proto.h, $(PDATLIST)) +endif + +depend:: luamod_list.h luamod_proto.h + +clean:: + $(call DELFILE, luamod_list.h) + $(call DELFILE, luamod_proto.h) + +clean_context:: + $(call DELFILE, $(PDATLIST)) + $(call DELFILE, $(BDATLIST)) + +distclean:: clean_context clean + $(call DELFILE, registry$(DELIM).updated) + $(call DELDIR, $(LUA_UNPACK)) + $(call DELFILE, $(LUA_TARBALL)) + +include $(APPDIR)/Application.mk diff --git a/interpreters/lua/Module.mk b/interpreters/lua/Module.mk new file mode 100644 index 000000000..feab40325 --- /dev/null +++ b/interpreters/lua/Module.mk @@ -0,0 +1,36 @@ +############################################################################ +# apps/interpreters/lua/Module.mk +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +LUAMOD_REGISTRY = $(APPDIR)$(DELIM)interpreters$(DELIM)lua$(DELIM)registry + +define LUAMOD_REGISTER + $(Q) echo Register Lua Module: $1 + $(Q) echo { \"$1\", $2 }, > "$(LUAMOD_REGISTRY)$(DELIM)$1.bdat" + $(Q) echo "int $2(lua_State *L);" > "$(LUAMOD_REGISTRY)$(DELIM)$1.pdat" + $(Q) touch "$(LUAMOD_REGISTRY)$(DELIM).updated" +endef + +ifneq ($(LUAMODNAME),) +LUAMODLIST := $(addprefix $(LUAMOD_REGISTRY)$(DELIM),$(addsuffix .bdat,$(LUAMODNAME))) +$(LUAMODLIST): $(DEPCONFIG) Makefile + $(call LUAMOD_REGISTER,$(LUAMODNAME),luaopen_$(LUAMODNAME)) + +register:: $(LUAMODLIST) +endif diff --git a/interpreters/lua/nuttx_linit.c b/interpreters/lua/nuttx_linit.c new file mode 100644 index 000000000..c15b1ab8c --- /dev/null +++ b/interpreters/lua/nuttx_linit.c @@ -0,0 +1,76 @@ +/**************************************************************************** + * apps/interpreters/lua/nuttx_linit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include "luamod_proto.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef LUA_GNAME +# define LUA_GNAME "_G" +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const luaL_Reg g_loadedlibs[] = +{ +#ifdef CONFIG_INTERPRETER_LUA_CORELIBS + {LUA_GNAME, luaopen_base}, +#endif +#include "luamod_list.h" + {NULL, NULL}, +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: luaL_openlibs + * + * Make core and user-defined modules available to the Lua interpreter. + * This function is called from lua.c during interpreter initialization. + * + ****************************************************************************/ + +void luaL_openlibs(lua_State *L) +{ + const luaL_Reg *lib; + for (lib = g_loadedlibs; lib->func; lib++) + { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); + } +} diff --git a/interpreters/lua/registry/.gitignore b/interpreters/lua/registry/.gitignore new file mode 100644 index 000000000..3fd3b08fc --- /dev/null +++ b/interpreters/lua/registry/.gitignore @@ -0,0 +1,3 @@ +.updated +*.pdat +*.bdat