mirror of
https://github.com/nodemcu/nodemcu-firmware.git
synced 2025-02-06 21:18:25 +08:00
Merge branch 'dev-esp32-idf4-lua53' into dev-esp32-idf4
This commit is contained in:
commit
dba57fa0ea
21
.github/workflows/build.yml
vendored
21
.github/workflows/build.yml
vendored
@ -6,10 +6,11 @@ jobs:
|
||||
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
lua_ver: ['5.1']
|
||||
numbers: ['float','integral']
|
||||
target: ['esp32','esp32c3']
|
||||
lua_ver: ['5.1', '5.3']
|
||||
numbers: ['default', 'alternate']
|
||||
target: ['esp32', 'esp32s2', 'esp32s3', 'esp32c3']
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@ -28,19 +29,27 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: ./install.sh
|
||||
shell: bash
|
||||
- name: Build firmware (Lua 5.1)
|
||||
if: ${{ matrix.lua_ver == '5.1' && matrix.numbers == 'float' }}
|
||||
- name: Build firmware (default configuration)
|
||||
if: ${{ matrix.numbers == 'default' }}
|
||||
run: |
|
||||
cp sdkconfig.defaults sdkconfig
|
||||
make IDF_TARGET=${{ matrix.target }}
|
||||
shell: bash
|
||||
- name: Build firmware (Lua 5.1, integer-only)
|
||||
if: ${{ matrix.lua_ver == '5.1' && matrix.numbers == 'integral' }}
|
||||
if: ${{ matrix.lua_ver == '5.1' && matrix.numbers == 'alternate' }}
|
||||
run: |
|
||||
cp sdkconfig.defaults sdkconfig
|
||||
echo CONFIG_LUA_NUMBER_INTEGRAL=y >> sdkconfig
|
||||
make IDF_TARGET=${{ matrix.target }}
|
||||
shell: bash
|
||||
- name: Build firmware (Lua 5.3, 64bit int/double)
|
||||
if: ${{ matrix.lua_ver == '5.3' && matrix.numbers == 'alternate' }}
|
||||
run: |
|
||||
cp sdkconfig.defaults sdkconfig
|
||||
echo CONFIG_LUA_NUMBER_INT64=y >> sdkconfig
|
||||
echo CONFIG_LUA_NUMBER_DOUBLE=y >> sdkconfig
|
||||
make IDF_TARGET=${{ matrix.target }}
|
||||
shell: bash
|
||||
- name: Upload luac.cross
|
||||
uses: actions/upload-artifact@v2
|
||||
if: ${{ success() }}
|
||||
|
@ -1,15 +1,7 @@
|
||||
idf_component_register(
|
||||
SRCS "ip_fmt.c" "lextra.c" "linit.c" "lnodeaux.c" "uart.c" "user_main.c"
|
||||
SRCS "ip_fmt.c" "user_main.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "lua"
|
||||
PRIV_REQUIRES "nvs_flash"
|
||||
LDFRAGMENTS "nodemcu.lf"
|
||||
)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -DCONFIG_NODEMCU_CMODULE_UART)
|
||||
target_link_libraries(${COMPONENT_LIB}
|
||||
"-u UART_module_selected1"
|
||||
"-u lua_rotables_part_map"
|
||||
"-Wl,-defsym=lua_rotables_map=_lua_rotables_map_start"
|
||||
"-Wl,-defsym=lua_libs_map=_lua_libs_map_start"
|
||||
)
|
||||
|
@ -1,8 +1,7 @@
|
||||
#ifndef __MODULE_H__
|
||||
#define __MODULE_H__
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "lrotable.h"
|
||||
#include "lnodemcu.h"
|
||||
|
||||
/* Registering a module within NodeMCU is really easy these days!
|
||||
*
|
||||
@ -18,11 +17,11 @@
|
||||
*
|
||||
* Then simply put a line like this at the bottom of your module file:
|
||||
*
|
||||
* NODEMCU_MODULE(MYNAME, "myname", myname_map, luaopen_myname);
|
||||
* NODEMCU_MODULE(MYNAME, "myname", myname, luaopen_myname);
|
||||
*
|
||||
* or perhaps
|
||||
*
|
||||
* NODEMCU_MODULE(MYNAME, "myname", myname_map, NULL);
|
||||
* NODEMCU_MODULE(MYNAME, "myname", myname, NULL);
|
||||
*
|
||||
* if you don't need an init function.
|
||||
*
|
||||
@ -36,23 +35,6 @@
|
||||
#define MODULE_PASTE_(x,y) x##y
|
||||
#define MODULE_EXPAND_PASTE_(x,y) MODULE_PASTE_(x,y)
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
#ifdef _MSC_VER
|
||||
//on msvc it is necessary to go through more pre-processor hoops to get the
|
||||
//section name built; string merging does not happen in the _declspecs.
|
||||
//NOTE: linker magic is invoked via the magical '$' character. Caveat editor.
|
||||
#define __TOKIFY(s) .rodata1$##s
|
||||
#define __TOTOK(s) __TOKIFY(s)
|
||||
#define __STRINGIFY(x) #x
|
||||
#define __TOSTRING(x) __STRINGIFY(x)
|
||||
#define __ROSECNAME(s) __TOSTRING(__TOTOK(s))
|
||||
#define LOCK_IN_SECTION(s) __declspec ( allocate( __ROSECNAME(s) ) )
|
||||
#else
|
||||
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".rodata1." #s)))
|
||||
#endif
|
||||
#else
|
||||
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s)))
|
||||
#endif
|
||||
/* For the ROM table, we name the variable according to ( | denotes concat):
|
||||
* cfgname | _module_selected | CONFIG_NODEMCU_CMODULE_##cfgname
|
||||
* where the CONFIG_NODEMCU_CMODULE_XYZ macro is first expanded to yield either
|
||||
@ -65,10 +47,10 @@
|
||||
*/
|
||||
#define NODEMCU_MODULE(cfgname, luaname, map, initfunc) \
|
||||
const LOCK_IN_SECTION(libs) \
|
||||
luaR_entry MODULE_PASTE_(lua_lib_,cfgname) = { luaname, LRO_FUNCVAL(initfunc) }; \
|
||||
ROTable_entry MODULE_PASTE_(lua_lib_,cfgname) = { luaname, LRO_FUNCVAL(initfunc) }; \
|
||||
const LOCK_IN_SECTION(rotable) \
|
||||
luaR_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(CONFIG_NODEMCU_CMODULE_,cfgname))) \
|
||||
= {luaname, LRO_ROVAL(map ## _map)}
|
||||
ROTable_entry MODULE_EXPAND_PASTE_(cfgname,MODULE_EXPAND_PASTE_(_module_selected,MODULE_PASTE_(CONFIG_NODEMCU_CMODULE_,cfgname))) \
|
||||
= {luaname, LRO_ROVAL(map)}
|
||||
#endif
|
||||
|
||||
|
||||
@ -89,6 +71,6 @@
|
||||
// NODEMCU_MODULE_STD() defines the entry points for an external module:
|
||||
#define NODEMCU_MODULE_STD() \
|
||||
static const LOCK_IN_SECTION(libs) \
|
||||
luaR_entry lua_lib_module = {MODNAME, LRO_FUNCVAL(module_init)}; \
|
||||
const LOCK_IN_SECTION(rotable) \
|
||||
luaR_entry MODULE_EXPAND_PASTE_(EXTMODNAME, _entry) = {MODNAME, LRO_ROVAL(module_map)};
|
||||
ROTable_entry lua_lib_module = {MODNAME, LRO_FUNCVAL(module_init)}; \
|
||||
const const LOCK_IN_SECTION(rotable) \
|
||||
ROTable_entry MODULE_EXPAND_PASTE_(EXTMODNAME, _entry) = {MODNAME, LRO_ROVAL(module_map)};
|
||||
|
@ -1,167 +0,0 @@
|
||||
/*
|
||||
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Initialization of libraries for lua.c
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#define linit_c
|
||||
#define LUA_LIB
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "luaconf.h"
|
||||
#include "module.h"
|
||||
#include "lstate.h"
|
||||
#include "lrotable.h"
|
||||
#include <assert.h>
|
||||
#include <stdalign.h>
|
||||
|
||||
LROT_EXTERN(strlib);
|
||||
LROT_EXTERN(tab_funcs);
|
||||
LROT_EXTERN(dblib);
|
||||
LROT_EXTERN(co_funcs);
|
||||
LROT_EXTERN(math);
|
||||
#if defined(LUA_CROSS_COMPILER)
|
||||
LROT_EXTERN(oslib);
|
||||
//LROT_EXTERN(iolib);
|
||||
#endif
|
||||
/*
|
||||
* The NodeMCU Lua initalisation has been adapted to use linker-based module
|
||||
* registration. This uses a PSECT naming convention to allow the ROTable and
|
||||
* initialisation function entries to be collected by the linker into two
|
||||
* consoliated ROTables. This significantly simplifies adding new modules and
|
||||
* configuring builds with a small subset of the total modules.
|
||||
*
|
||||
* This linker-based approach is not practical for cross compiler builds which
|
||||
* must link on a range of platforms, and where we don't have control of PSECT
|
||||
* placement. However unlike the target builds, the luac.cross builds only
|
||||
* used a small and fixed list of libraries and so in this case the table can
|
||||
* be defined in this source file, so in this case all library ROTables are
|
||||
* defined here, avoiding the need for linker magic is avoided on host builds.
|
||||
*
|
||||
* Note that a separate ROTable is defined in lbaselib.c for the base functions
|
||||
* and there is a metatable index cascade from _G to this base function table to
|
||||
* the master rotables table. In the target build, the linker marshals the
|
||||
* table, hence the LROT_BREAK() macros which don't 0 terminate the lists.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
//MSVC requires us to declare these sections before we refer to them
|
||||
#pragma section(__ROSECNAME(A), read)
|
||||
#pragma section(__ROSECNAME(zzzzzzzz), read)
|
||||
#pragma section(__ROSECNAME(libs), read)
|
||||
#pragma section(__ROSECNAME(rotable), read)
|
||||
//These help us to find the beginning and ending of the RO data. NOTE: linker
|
||||
//magic is used; the section names are lexically sorted, so 'a' and 'z' are
|
||||
//important to keep the other sections lexically between these two dummy
|
||||
//variables. Check your mapfile output if you need to fiddle with this stuff.
|
||||
const LOCK_IN_SECTION(A) char _ro_start[1] = {0};
|
||||
const LOCK_IN_SECTION(zzzzzzzz) char _ro_end[1] = {0};
|
||||
#endif
|
||||
|
||||
#if defined(LUA_CROSS_COMPILER)
|
||||
|
||||
LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(rotable) lua_rotables)
|
||||
LROT_TABENTRY( string, strlib )
|
||||
LROT_TABENTRY( table, tab_funcs )
|
||||
LROT_TABENTRY( coroutine, co_funcs )
|
||||
LROT_TABENTRY( debug, dblib)
|
||||
LROT_TABENTRY( math, math )
|
||||
LROT_TABENTRY( ROM, lua_rotables )
|
||||
LROT_TABENTRY( os, oslib )
|
||||
//LROT_TABENTRY( io, iolib )
|
||||
LROT_END(lua_rotables, NULL, 0)
|
||||
|
||||
#else
|
||||
|
||||
// Due to limitations in the IDF linker fragment generation, we have to
|
||||
// play with link-time symbol generation/aliasing to set up the rotables
|
||||
// properly. As part of that, we need to use a different name for the
|
||||
// table here.
|
||||
|
||||
LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(rotable) lua_rotables_part)
|
||||
#ifdef CONFIG_LUA_BUILTIN_STRING
|
||||
LROT_TABENTRY( string, strlib )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_TABLE
|
||||
LROT_TABENTRY( table, tab_funcs )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_COROUTINE
|
||||
LROT_TABENTRY( coroutine, co_funcs )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_DEBUG
|
||||
LROT_TABENTRY( debug, dblib)
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_MATH
|
||||
LROT_TABENTRY( math, math )
|
||||
#endif
|
||||
LROT_TABENTRY( ROM, lua_rotables_part )
|
||||
LROT_BREAK(lua_rotables_part)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
LROT_PUBLIC_BEGIN(LOCK_IN_SECTION(libs) lua_libs)
|
||||
LROT_FUNCENTRY( _, luaopen_base )
|
||||
LROT_FUNCENTRY( package, luaopen_package )
|
||||
#ifdef CONFIG_LUA_BUILTIN_STRING
|
||||
LROT_FUNCENTRY( string, luaopen_string )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_TABLE
|
||||
LROT_FUNCENTRY( table, luaopen_table )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_DEBUG
|
||||
LROT_FUNCENTRY( debug, luaopen_debug )
|
||||
#endif
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
LROT_BREAK(lua_libs)
|
||||
#else
|
||||
LROT_FUNCENTRY( io, luaopen_io )
|
||||
LROT_END( lua_libs, NULL, 0)
|
||||
#endif
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
extern void luaL_dbgbreak(void);
|
||||
#endif
|
||||
|
||||
/* Historically the linker script took care of zero terminating both the
|
||||
* lua_libs and lua_rotable arrays, but the IDF currently does not
|
||||
* support injecting LONG(0) entries. To compensate, we have explicit
|
||||
* end markers here which the linker fragment then place appropriately
|
||||
* to terminate aforementioned arrays.
|
||||
*/
|
||||
const luaR_entry LOCK_IN_SECTION(libs_end_marker) libs_end_marker= { 0, };
|
||||
const luaR_entry LOCK_IN_SECTION(rotable_end_marker) rotable_end_marker = { 0, };
|
||||
|
||||
void luaL_openlibs (lua_State *L) {
|
||||
lua_pushrotable(L, LROT_TABLEREF(lua_libs));
|
||||
lua_pushnil(L); /* first key */
|
||||
/* loop round and open libraries */
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
// luaL_dbgbreak(); // This is a test point for debugging library start ups
|
||||
#endif
|
||||
while (lua_next(L, -2) != 0) {
|
||||
if (lua_islightfunction(L,-1) &&
|
||||
fvalue(L->top-1)) { // only process function entries
|
||||
lua_pushvalue(L, -2);
|
||||
lua_call(L, 1, 0); // call luaopen_XXX(libname)
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1); //cleanup stack
|
||||
}
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
# ifdef LUA_NUMBER_INTEGRAL
|
||||
# define COMPARE <=
|
||||
# else
|
||||
# define COMPARE ==
|
||||
# endif
|
||||
_Static_assert(_Alignof(luaR_entry) COMPARE 8, "Unexpected alignment of module registration - update the linker script snippets to match!");
|
||||
_Static_assert(sizeof(luaR_entry) COMPARE 24, "Unexpect size of array member - update the linker script snippets to match!");
|
||||
#endif
|
@ -1,41 +1,17 @@
|
||||
[sections:lua_libs]
|
||||
entries:
|
||||
.lua_libs
|
||||
|
||||
[sections:lua_libs_end_marker]
|
||||
entries:
|
||||
.lua_libs_end_marker
|
||||
|
||||
[sections:lua_rotable]
|
||||
entries:
|
||||
.lua_rotable
|
||||
|
||||
[sections:lua_rotable_end_marker]
|
||||
entries:
|
||||
.lua_rotable_end_marker
|
||||
|
||||
[sections:lua_esp_event_cb_table]
|
||||
entries:
|
||||
.lua_esp_event_cb_table
|
||||
|
||||
[scheme:nodemcu_arrays]
|
||||
entries:
|
||||
lua_libs -> flash_rodata
|
||||
lua_libs_end_marker -> flash_rodata
|
||||
lua_rotable -> flash_rodata
|
||||
lua_rotable_end_marker -> flash_rodata
|
||||
lua_esp_event_cb_table -> flash_rodata
|
||||
|
||||
|
||||
# Important: don't change the alignments below without also updating the
|
||||
# _Static_assert over in linit.c and/or nodemcu_esp_event.h!
|
||||
# _Static_assert over in nodemcu_esp_event.h!
|
||||
|
||||
[mapping:nodemcu]
|
||||
archive: *
|
||||
entries:
|
||||
* (nodemcu_arrays);
|
||||
lua_libs -> flash_rodata KEEP() ALIGN(8) SURROUND(lua_libs_map),
|
||||
lua_libs_end_marker -> flash_rodata KEEP(),
|
||||
lua_rotable -> flash_rodata ALIGN(8) SURROUND(lua_rotables_map),
|
||||
lua_rotable_end_marker -> flash_rodata KEEP(),
|
||||
lua_esp_event_cb_table -> flash_rodata KEEP() ALIGN(4) SURROUND(esp_event_cb_table)
|
||||
|
@ -9,6 +9,7 @@
|
||||
* 2014/1/1, v1.0 create this file.
|
||||
*******************************************************************************/
|
||||
#include "lua.h"
|
||||
#include "linput.h"
|
||||
#include "platform.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -19,7 +20,6 @@
|
||||
#include "nvs_flash.h"
|
||||
#include "flash_api.h"
|
||||
|
||||
#include "driver/console.h"
|
||||
#include "task/task.h"
|
||||
#include "sections.h"
|
||||
#include "nodemcu_esp_event.h"
|
||||
@ -93,24 +93,9 @@ static void handle_default_loop_event(task_param_t param, task_prio_t prio)
|
||||
// +================== New task interface ==================+
|
||||
static void start_lua ()
|
||||
{
|
||||
char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL };
|
||||
NODE_DBG("Task task_lua started.\n");
|
||||
lua_main( 2, lua_argv );
|
||||
}
|
||||
|
||||
static void handle_input(task_param_t flag, task_prio_t priority) {
|
||||
(void)priority;
|
||||
lua_handle_input (flag);
|
||||
}
|
||||
|
||||
static task_handle_t input_task;
|
||||
|
||||
task_handle_t user_get_input_sig(void) {
|
||||
return input_task;
|
||||
}
|
||||
|
||||
bool user_process_input(bool force) {
|
||||
return task_post_low(input_task, force);
|
||||
if (lua_main()) // If it returns true then LFS restart is needed
|
||||
lua_main();
|
||||
}
|
||||
|
||||
void nodemcu_init(void)
|
||||
@ -144,8 +129,6 @@ void __attribute__((noreturn)) app_main(void)
|
||||
{
|
||||
task_init();
|
||||
|
||||
input_task = task_get_id (handle_input);
|
||||
|
||||
relayed_event_handled = xSemaphoreCreateBinary();
|
||||
relayed_event_task = task_get_id(handle_default_loop_event);
|
||||
|
||||
@ -156,19 +139,7 @@ void __attribute__((noreturn)) app_main(void)
|
||||
relay_default_loop_events,
|
||||
NULL);
|
||||
|
||||
ConsoleSetup_t cfg;
|
||||
cfg.bit_rate = CONFIG_NODEMCU_CONSOLE_BIT_RATE;
|
||||
cfg.data_bits = CONSOLE_NUM_BITS_8;
|
||||
cfg.parity = CONSOLE_PARITY_NONE;
|
||||
cfg.stop_bits = CONSOLE_STOP_BITS_1;
|
||||
cfg.auto_baud =
|
||||
#ifdef CONFIG_NODEMCU_CONSOLE_BIT_RATE_AUTO
|
||||
true;
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
|
||||
console_init (&cfg, input_task);
|
||||
platform_uart_start(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
nodemcu_init ();
|
||||
|
@ -1,4 +1,4 @@
|
||||
if(NOT "${IDF_TARGET}" STREQUAL "esp32c3")
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
|
||||
idf_component_register(
|
||||
SRCS "CAN.c"
|
||||
|
@ -1,5 +0,0 @@
|
||||
idf_component_register(
|
||||
SRCS "console.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "task" "esp32"
|
||||
)
|
@ -1,197 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Dius Computing Pty Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of the copyright holders nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @author Johny Mattsson <jmattsson@dius.com.au>
|
||||
*/
|
||||
|
||||
#include "driver/console.h"
|
||||
#include "driver/uart.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "sys/reent.h"
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rom/libc_stubs.h"
|
||||
#include "rom/uart.h"
|
||||
|
||||
#define UART_INPUT_QUEUE_SZ 0x100
|
||||
|
||||
// These used to be available in soc/uart_register.h:
|
||||
#define UART_GET_RXFIFO_RD_BYTE(i) GET_PERI_REG_BITS2(UART_FIFO_REG(i) , UART_RXFIFO_RD_BYTE_V, UART_RXFIFO_RD_BYTE_S)
|
||||
#define UART_GET_RXFIFO_CNT(i) GET_PERI_REG_BITS2(UART_STATUS_REG(i) , UART_RXFIFO_CNT_V, UART_RXFIFO_CNT_S)
|
||||
#define UART_SET_AUTOBAUD_EN(i,val) SET_PERI_REG_BITS(UART_AUTOBAUD_REG(i) ,UART_AUTOBAUD_EN_V,(val),UART_AUTOBAUD_EN_S)
|
||||
|
||||
|
||||
typedef int (*_read_r_fn) (struct _reent *r, int fd, void *buf, int size);
|
||||
|
||||
static _read_r_fn _read_r_app;
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
static _read_r_fn _read_r_pro;
|
||||
#endif
|
||||
|
||||
static xQueueHandle uart0Q;
|
||||
static task_handle_t input_task = 0;
|
||||
|
||||
// --- Syscall support for reading from STDIN_FILENO ---------------
|
||||
|
||||
static int console_read_r (struct _reent *r, int fd, void *buf, int size, _read_r_fn next)
|
||||
{
|
||||
if (fd == STDIN_FILENO)
|
||||
{
|
||||
static _lock_t stdin_lock;
|
||||
_lock_acquire_recursive (&stdin_lock);
|
||||
char *c = (char *)buf;
|
||||
int i = 0;
|
||||
for (; i < size; ++i)
|
||||
{
|
||||
if (!console_getc (c++))
|
||||
break;
|
||||
}
|
||||
_lock_release_recursive (&stdin_lock);
|
||||
return i;
|
||||
}
|
||||
else if (next)
|
||||
return next (r, fd, buf, size);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
static int console_read_r_pro (struct _reent *r, int fd, void *buf, int size)
|
||||
{
|
||||
return console_read_r (r, fd, buf, size, _read_r_pro);
|
||||
}
|
||||
#endif
|
||||
static int console_read_r_app (struct _reent *r, int fd, void *buf, int size)
|
||||
{
|
||||
return console_read_r (r, fd, buf, size, _read_r_app);
|
||||
}
|
||||
|
||||
// --- End syscall support -------------------------------------------
|
||||
|
||||
static void uart0_rx_intr_handler (void *arg)
|
||||
{
|
||||
(void)arg;
|
||||
bool received = false;
|
||||
uint32_t status = READ_PERI_REG(UART_INT_ST_REG(CONSOLE_UART));
|
||||
while (status)
|
||||
{
|
||||
if (status & UART_FRM_ERR_INT_ENA)
|
||||
{
|
||||
// TODO: report somehow?
|
||||
WRITE_PERI_REG(UART_INT_CLR_REG(CONSOLE_UART), UART_FRM_ERR_INT_ENA);
|
||||
}
|
||||
if ((status & UART_RXFIFO_TOUT_INT_ENA) ||
|
||||
(status & UART_RXFIFO_FULL_INT_ENA))
|
||||
{
|
||||
uint32_t fifo_len = UART_GET_RXFIFO_CNT(CONSOLE_UART);
|
||||
for (uint32_t i = 0; i < fifo_len; ++i)
|
||||
{
|
||||
received = true;
|
||||
char c = UART_GET_RXFIFO_RD_BYTE(CONSOLE_UART);
|
||||
if (uart0Q)
|
||||
xQueueSendToBackFromISR (uart0Q, &c, NULL);
|
||||
}
|
||||
WRITE_PERI_REG(UART_INT_CLR_REG(CONSOLE_UART),
|
||||
UART_RXFIFO_TOUT_INT_ENA | UART_RXFIFO_FULL_INT_ENA);
|
||||
}
|
||||
status = READ_PERI_REG(UART_INT_ST_REG(CONSOLE_UART));
|
||||
}
|
||||
if (received && input_task)
|
||||
task_post_isr_low (input_task, false);
|
||||
}
|
||||
|
||||
|
||||
void console_setup (const ConsoleSetup_t *cfg)
|
||||
{
|
||||
esp_rom_uart_tx_wait_idle (CONSOLE_UART);
|
||||
|
||||
uart_config_t uart_conf = {
|
||||
.baud_rate = cfg->bit_rate,
|
||||
.data_bits =
|
||||
cfg->data_bits == CONSOLE_NUM_BITS_5 ? UART_DATA_5_BITS :
|
||||
cfg->data_bits == CONSOLE_NUM_BITS_6 ? UART_DATA_6_BITS :
|
||||
cfg->data_bits == CONSOLE_NUM_BITS_7 ? UART_DATA_7_BITS :
|
||||
UART_DATA_8_BITS,
|
||||
.stop_bits =
|
||||
cfg->stop_bits == CONSOLE_STOP_BITS_1 ? UART_STOP_BITS_1 :
|
||||
cfg->stop_bits == CONSOLE_STOP_BITS_2 ? UART_STOP_BITS_2 :
|
||||
UART_STOP_BITS_1_5,
|
||||
.parity =
|
||||
cfg->parity == CONSOLE_PARITY_NONE ? UART_PARITY_DISABLE :
|
||||
cfg->parity == CONSOLE_PARITY_EVEN ? UART_PARITY_EVEN :
|
||||
UART_PARITY_ODD,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
};
|
||||
uart_param_config(CONSOLE_UART, &uart_conf);
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
// TODO: Make this actually work
|
||||
UART_SET_AUTOBAUD_EN(CONSOLE_UART, cfg->auto_baud);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void console_init (const ConsoleSetup_t *cfg, task_handle_t tsk)
|
||||
{
|
||||
input_task = tsk;
|
||||
uart0Q = xQueueCreate (UART_INPUT_QUEUE_SZ, sizeof (char));
|
||||
|
||||
console_setup (cfg);
|
||||
|
||||
uart_isr_register(CONSOLE_UART, uart0_rx_intr_handler, NULL, 0, NULL);
|
||||
uart_set_rx_timeout(CONSOLE_UART, 2);
|
||||
uart_set_rx_full_threshold(CONSOLE_UART, 10);
|
||||
uart_enable_intr_mask(CONSOLE_UART,
|
||||
UART_RXFIFO_TOUT_INT_ENA_M |
|
||||
UART_RXFIFO_FULL_INT_ENA_M |
|
||||
UART_FRM_ERR_INT_ENA_M);
|
||||
|
||||
// Register our console_read_r_xxx functions to support stdin input
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
_read_r_app = syscall_table_ptr->_read_r;
|
||||
syscall_table_ptr->_read_r = console_read_r_app;
|
||||
#else
|
||||
_read_r_app = syscall_table_ptr_app->_read_r;
|
||||
_read_r_pro = syscall_table_ptr_pro->_read_r;
|
||||
syscall_table_ptr_app->_read_r = console_read_r_app;
|
||||
syscall_table_ptr_pro->_read_r = console_read_r_pro;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool console_getc (char *c)
|
||||
{
|
||||
return (uart0Q && (xQueueReceive (uart0Q, c, 0) == pdTRUE));
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Dius Computing Pty Ltd. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of the copyright holders nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* @author Johny Mattsson <jmattsson@dius.com.au>
|
||||
*/
|
||||
|
||||
#include "esp_rom_uart.h"
|
||||
#include "task/task.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CONSOLE_UART CONFIG_ESP_CONSOLE_UART_NUM
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONSOLE_NUM_BITS_5 = 0x0,
|
||||
CONSOLE_NUM_BITS_6 = 0x1,
|
||||
CONSOLE_NUM_BITS_7 = 0x2,
|
||||
CONSOLE_NUM_BITS_8 = 0x3
|
||||
} ConsoleNumBits_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONSOLE_PARITY_NONE = 0x2,
|
||||
CONSOLE_PARITY_ODD = 0x1,
|
||||
CONSOLE_PARITY_EVEN = 0x0
|
||||
} ConsoleParity_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CONSOLE_STOP_BITS_1 = 0x1,
|
||||
CONSOLE_STOP_BITS_1_5 = 0x2,
|
||||
CONSOLE_STOP_BITS_2 = 0x3
|
||||
} ConsoleStopBits_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bit_rate;
|
||||
ConsoleNumBits_t data_bits;
|
||||
ConsoleParity_t parity;
|
||||
ConsoleStopBits_t stop_bits;
|
||||
bool auto_baud;
|
||||
} ConsoleSetup_t;
|
||||
|
||||
void console_init (const ConsoleSetup_t *cfg, task_handle_t tsk);
|
||||
void console_setup (const ConsoleSetup_t *cfg);
|
||||
bool console_getc (char *c);
|
@ -1,10 +1,117 @@
|
||||
idf_component_register(
|
||||
SRCS "lapi.c" "lauxlib.c" "lbaselib.c" "lcode.c" "ldblib.c" "ldebug.c"
|
||||
"ldo.c" "ldump.c" "legc.c" "lflash.c" "lfunc.c" "lgc.c" "llex.c" "lmathlib.c"
|
||||
"lmem.c" "loadlib.c" "lobject.c" "lopcodes.c" "lparser.c" "lrotable.c"
|
||||
"lstate.c" "lstring.c" "lstrlib.c" "ltable.c" "ltablib.c" "ltm.c"
|
||||
"lua.c" "lundump.c" "lvm.c" "lzio.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES "platform" "uzlib" "driver_console"
|
||||
PRIV_REQUIRES "base_nodemcu" "embedded_lfs"
|
||||
if(CONFIG_LUA_VERSION_51)
|
||||
set(srcs
|
||||
"lua-5.1/lapi.c"
|
||||
"lua-5.1/lauxlib.c"
|
||||
"lua-5.1/lbaselib.c"
|
||||
"lua-5.1/lcode.c"
|
||||
"lua-5.1/ldblib.c"
|
||||
"lua-5.1/ldebug.c"
|
||||
"lua-5.1/ldo.c"
|
||||
"lua-5.1/ldump.c"
|
||||
"lua-5.1/lflash.c"
|
||||
"lua-5.1/lfunc.c"
|
||||
"lua-5.1/lgc.c"
|
||||
"lua-5.1/llex.c"
|
||||
"lua-5.1/lmathlib.c"
|
||||
"lua-5.1/lmem.c"
|
||||
"lua-5.1/lnodemcu.c"
|
||||
"lua-5.1/loadlib.c"
|
||||
"lua-5.1/lobject.c"
|
||||
"lua-5.1/lopcodes.c"
|
||||
"lua-5.1/lparser.c"
|
||||
"lua-5.1/lstate.c"
|
||||
"lua-5.1/lstring.c"
|
||||
"lua-5.1/lstrlib.c"
|
||||
"lua-5.1/ltable.c"
|
||||
"lua-5.1/ltablib.c"
|
||||
"lua-5.1/ltm.c"
|
||||
"lua-5.1/lua.c"
|
||||
"lua-5.1/lundump.c"
|
||||
"lua-5.1/lvm.c"
|
||||
"lua-5.1/lzio.c"
|
||||
)
|
||||
set(luadir "lua-5.1")
|
||||
elseif(CONFIG_LUA_VERSION_53)
|
||||
set(srcs
|
||||
"lua-5.3/lapi.c"
|
||||
"lua-5.3/lauxlib.c"
|
||||
"lua-5.3/lbaselib.c"
|
||||
"lua-5.3/lbitlib.c"
|
||||
"lua-5.3/lcode.c"
|
||||
"lua-5.3/lcorolib.c"
|
||||
"lua-5.3/lctype.c"
|
||||
"lua-5.3/ldblib.c"
|
||||
"lua-5.3/ldebug.c"
|
||||
"lua-5.3/ldo.c"
|
||||
"lua-5.3/ldump.c"
|
||||
"lua-5.3/lfunc.c"
|
||||
"lua-5.3/lgc.c"
|
||||
"lua-5.3/llex.c"
|
||||
"lua-5.3/lmathlib.c"
|
||||
"lua-5.3/lmem.c"
|
||||
"lua-5.3/lnodemcu.c"
|
||||
"lua-5.3/loadlib.c"
|
||||
"lua-5.3/lobject.c"
|
||||
"lua-5.3/lopcodes.c"
|
||||
"lua-5.3/lparser.c"
|
||||
"lua-5.3/lstate.c"
|
||||
"lua-5.3/lstring.c"
|
||||
"lua-5.3/lstrlib.c"
|
||||
"lua-5.3/ltable.c"
|
||||
"lua-5.3/ltablib.c"
|
||||
"lua-5.3/ltm.c"
|
||||
"lua-5.3/lua.c"
|
||||
"lua-5.3/lundump.c"
|
||||
"lua-5.3/lutf8lib.c"
|
||||
"lua-5.3/lvm.c"
|
||||
"lua-5.3/lzio.c"
|
||||
)
|
||||
set(luadir "lua-5.3")
|
||||
endif()
|
||||
|
||||
set(common_srcs
|
||||
"common/lextra.c"
|
||||
"common/lfs.c"
|
||||
"common/linput.c"
|
||||
"common/linit.c"
|
||||
"common/lnodeaux.c"
|
||||
"common/lpanic.c"
|
||||
)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${srcs} ${common_srcs}
|
||||
INCLUDE_DIRS ${luadir} "common"
|
||||
REQUIRES "platform" "nvs_flash" "uzlib"
|
||||
PRIV_REQUIRES "base_nodemcu" "embedded_lfs"
|
||||
LDFRAGMENTS "link_lua.lf"
|
||||
)
|
||||
|
||||
#
|
||||
# Cross compiler targets
|
||||
#
|
||||
|
||||
# Not sure why we can't directly depend on ${SDKCONFIG_HEADER} in our
|
||||
# externalproject_add(), but them's the brakes...
|
||||
|
||||
set(luac_build_dir "${BUILD_DIR}/luac_cross")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT sdkconfig.h
|
||||
COMMAND mkdir -p "${luac_build_dir}" && cp ${SDKCONFIG_HEADER} ${luac_build_dir}/sdkconfig.h
|
||||
DEPENDS ${SDKCONFIG_HEADER}
|
||||
VERBATIM
|
||||
)
|
||||
add_custom_target(sdkconfig_h DEPENDS sdkconfig.h)
|
||||
|
||||
externalproject_add(luac_cross_build
|
||||
PREFIX ${luac_build_dir}
|
||||
SOURCE_DIR ${COMPONENT_DIR}/${luadir}/host
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND make -f ${COMPONENT_DIR}/${luadir}/host/idf.mk LUAC_BUILD_DIR=${luac_build_dir} LUA_PATH=${COMPONENT_DIR}/${luadir} PYTHON=${PYTHON}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS 1
|
||||
DEPENDS sdkconfig_h
|
||||
)
|
||||
|
||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${BUILD_DIR}/luac_cross/luac.cross;${BUILD_DIR}/luac_cross/${luadir}" )
|
||||
|
@ -1,12 +1,46 @@
|
||||
menu "Lua configuration"
|
||||
|
||||
choice LUA_VERSION
|
||||
prompt "Lua version"
|
||||
default LUA_VERSION_51
|
||||
help
|
||||
The version of Lua interpreter to use.
|
||||
|
||||
config LUA_VERSION_51
|
||||
bool "Lua 5.1"
|
||||
|
||||
config LUA_VERSION_53
|
||||
bool "Lua 5.3"
|
||||
|
||||
endchoice
|
||||
|
||||
config LUA_NUMBER_INTEGRAL
|
||||
depends on LUA_VERSION_51
|
||||
bool "Integer-only build"
|
||||
default "n"
|
||||
help
|
||||
Build Lua without support for floating point numbers.
|
||||
Not generally recommended, but can save on code size.
|
||||
|
||||
config LUA_NUMBER_INT64
|
||||
depends on LUA_VERSION_53
|
||||
bool "Use 64bit integers"
|
||||
default "n"
|
||||
help
|
||||
Build Lua with 64bit integers. This provides a greater value
|
||||
range, but at the expense of extra memory usage and somewhat
|
||||
reduced performance over the default 32bit integers.
|
||||
|
||||
config LUA_NUMBER_DOUBLE
|
||||
depends on LUA_VERSION_53
|
||||
bool "Use double precision floating point"
|
||||
default "n"
|
||||
help
|
||||
Build Lua with double floating point precision. This provides
|
||||
a greater value range, but at the expense of extra memory
|
||||
usage and somewhat reduced performance over the default
|
||||
single precision floating point.
|
||||
|
||||
menu "Core Lua modules"
|
||||
|
||||
config LUA_BUILTIN_STRING
|
||||
@ -33,6 +67,13 @@ menu "Lua configuration"
|
||||
help
|
||||
Includes the math module (recommended).
|
||||
|
||||
config LUA_BUILTIN_UTF8
|
||||
depends on !LUA_VERSION_51
|
||||
bool "UTF8 module"
|
||||
default "y"
|
||||
help
|
||||
Includes the debug module (required by our Lua VM).
|
||||
|
||||
config LUA_BUILTIN_DEBUG
|
||||
bool "Debug module"
|
||||
default "n"
|
||||
@ -78,4 +119,11 @@ menu "Lua configuration"
|
||||
|
||||
endmenu
|
||||
|
||||
config LUA_REQUIRED_MODULES
|
||||
bool
|
||||
default y
|
||||
select NODEMCU_CMODULE_PIPE
|
||||
select NODEMCU_CMODULE_UART
|
||||
select LUA_BUILTIN_DEBUG
|
||||
|
||||
endmenu
|
||||
|
103
components/lua/common/lfs.c
Normal file
103
components/lua/common/lfs.c
Normal file
@ -0,0 +1,103 @@
|
||||
#include "lfs.h"
|
||||
|
||||
#include "esp_partition.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if defined(CONFIG_NODEMCU_EMBEDDED_LFS_SIZE)
|
||||
// Symbol provided by embedded_lfs component
|
||||
extern const char lua_flash_store_reserved[0];
|
||||
#endif
|
||||
|
||||
|
||||
bool lfs_get_location(lfs_location_info_t *out)
|
||||
{
|
||||
#if defined(CONFIG_NODEMCU_EMBEDDED_LFS_SIZE)
|
||||
out->size = CONFIG_NODEMCU_EMBEDDED_LFS_SIZE;
|
||||
out->addr_mem = lua_flash_store_reserved;
|
||||
out->addr_phys = spi_flash_cache2phys(lua_flash_store_reserved);
|
||||
if (out->addr_phys == SPI_FLASH_CACHE2PHYS_FAIL) {
|
||||
NODE_ERR("spi_flash_cache2phys failed\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
#else
|
||||
const esp_partition_t *part = esp_partition_find_first(
|
||||
PLATFORM_PARTITION_TYPE_NODEMCU,
|
||||
PLATFORM_PARTITION_SUBTYPE_NODEMCU_LFS,
|
||||
NULL);
|
||||
if (!part)
|
||||
return false; // Nothing to do if no LFS partition available
|
||||
|
||||
out->size = part->size; // in bytes
|
||||
out->addr_mem = spi_flash_phys2cache(out->addr_phys, SPI_FLASH_MMAP_DATA);
|
||||
out->addr_phys = part->address;
|
||||
if (!out->addr_mem) { // not already mmap'd, have to do it ourselves
|
||||
spi_flash_mmap_handle_t ignored;
|
||||
esp_err_t err = spi_flash_mmap(
|
||||
out->addr_phys, out->size, SPI_FLASH_MMAP_DATA, &out->addr_mem, &ignored);
|
||||
if (err != ESP_OK) {
|
||||
NODE_ERR("Unable to access LFS partition - is it 64kB aligned as it needs to be?\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define LFS_LOAD_NS "lfsload"
|
||||
#define LFS_LOAD_FILE_KEY "filename"
|
||||
|
||||
bool lfs_get_load_filename(char *buf, size_t bufsiz)
|
||||
{
|
||||
bool res = false;
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(LFS_LOAD_NS, NVS_READONLY, &handle);
|
||||
if (err != ESP_OK)
|
||||
goto out;
|
||||
err = nvs_get_str(handle, LFS_LOAD_FILE_KEY, buf, &bufsiz);
|
||||
if (err != ESP_OK)
|
||||
goto close_out;
|
||||
res = true;
|
||||
close_out:
|
||||
nvs_close(handle);
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool lfs_set_load_filename(const char *fname)
|
||||
{
|
||||
bool res = false;
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(LFS_LOAD_NS, NVS_READWRITE, &handle);
|
||||
if (err != ESP_OK)
|
||||
goto out;
|
||||
err = nvs_set_str(handle, LFS_LOAD_FILE_KEY, fname);
|
||||
if (err != ESP_OK)
|
||||
goto close_out;
|
||||
res = true;
|
||||
close_out:
|
||||
nvs_close(handle);
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool lfs_clear_load_filename(void)
|
||||
{
|
||||
bool res = false;
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(LFS_LOAD_NS, NVS_READWRITE, &handle);
|
||||
if (err != ESP_OK)
|
||||
goto out;
|
||||
err = nvs_erase_key(handle, LFS_LOAD_FILE_KEY);
|
||||
if (err != ESP_OK)
|
||||
goto close_out;
|
||||
res = true;
|
||||
close_out:
|
||||
nvs_close(handle);
|
||||
out:
|
||||
return res;
|
||||
}
|
21
components/lua/common/lfs.h
Normal file
21
components/lua/common/lfs.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _LFS_H_
|
||||
#define _LFS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
uint32_t addr_phys; // physical address in flash
|
||||
const void *addr_mem; // memory mapped address
|
||||
} lfs_location_info_t;
|
||||
|
||||
bool lfs_get_location(lfs_location_info_t *out);
|
||||
|
||||
// Setting & getting of filename during reboot/load cycle
|
||||
bool lfs_get_load_filename(char *buf, size_t bufsiz);
|
||||
bool lfs_set_load_filename(const char *fname);
|
||||
bool lfs_clear_load_filename(void);
|
||||
|
||||
#endif
|
170
components/lua/common/linit.c
Normal file
170
components/lua/common/linit.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Initialization of libraries for lua.c
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#define linit_c
|
||||
#define LUA_LIB
|
||||
#define LUA_CORE
|
||||
|
||||
/*
|
||||
** NodeMCU uses RO segment based static ROTable declarations for all library
|
||||
** tables, including the index of library tables itself (the ROM table). These
|
||||
** tables can be moved from RAM to flash ROM on the ESPs.
|
||||
**
|
||||
** On the ESPs targets, we can marshal the table entries through linker-based
|
||||
** PSECTs to enable the library initiation tables to be bound during the link
|
||||
** process rather than being statically declared here. This simplifies the
|
||||
** addition of new modules and configuring builds with a subset of the total
|
||||
** modules available.
|
||||
**
|
||||
** Such a linker-based approach is not practical for cross compiler builds that
|
||||
** must link on a range of platforms, and where we don't have control of PSECT
|
||||
** placement. However unlike the target builds, the luac.cross builds only
|
||||
** use a small and fixed list of libraries and so in this case all of libraries
|
||||
** are defined here, avoiding the need for linker magic on host builds.
|
||||
**
|
||||
** Note that a separate ROTable is defined in lbaselib.c on luac.cross builds
|
||||
** for the base functions. (These use linker based entries on target builds)
|
||||
** and there is a metatable index cascade from _G to this base function table
|
||||
** to the master rotables table. In the target build, the linker marshals the
|
||||
** table, hence the LROT_BREAK() macros which don't 0 terminate the lists and
|
||||
** skip generating the ROtable header.
|
||||
*/
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lstate.h"
|
||||
#include "lnodemcu.h"
|
||||
#if LUA_VERSION_NUM == 501
|
||||
#include "lflash.h"
|
||||
#endif
|
||||
|
||||
extern LROT_TABLE(strlib);
|
||||
extern LROT_TABLE(tab_funcs);
|
||||
extern LROT_TABLE(dblib);
|
||||
extern LROT_TABLE(co_funcs);
|
||||
extern LROT_TABLE(mathlib);
|
||||
extern LROT_TABLE(utf8);
|
||||
|
||||
#if defined(LUA_CROSS_COMPILER)
|
||||
|
||||
/* _G __index -> rotables __index -> base_func */
|
||||
extern LROT_TABLE(rotables_meta);
|
||||
extern LROT_TABLE(base_func);
|
||||
#if LUA_VERSION_NUM == 501
|
||||
extern LROT_TABLE(oslib);
|
||||
extern LROT_TABLE(iolib);
|
||||
#endif
|
||||
|
||||
LROT_BEGIN(rotables_meta, NULL, LROT_MASK_INDEX)
|
||||
LROT_TABENTRY( __index, base_func)
|
||||
LROT_END(rotables_meta, NULL, LROT_MASK_INDEX)
|
||||
|
||||
LROT_BEGIN(rotables, LROT_TABLEREF(rotables_meta), 0)
|
||||
LROT_TABENTRY( string, strlib )
|
||||
LROT_TABENTRY( table, tab_funcs )
|
||||
LROT_TABENTRY( coroutine, co_funcs )
|
||||
LROT_TABENTRY( debug, dblib)
|
||||
LROT_TABENTRY( math, mathlib )
|
||||
#if LUA_VERSION_NUM >= 503
|
||||
LROT_TABENTRY( utf8, utf8 )
|
||||
#endif
|
||||
LROT_TABENTRY( ROM, rotables )
|
||||
#if LUA_VERSION_NUM == 501
|
||||
LROT_TABENTRY( os, oslib )
|
||||
LROT_TABENTRY( io, iolib )
|
||||
#endif
|
||||
LROT_END(rotables, LROT_TABLEREF(rotables_meta), 0)
|
||||
|
||||
LROT_BEGIN(lua_libs, NULL, 0)
|
||||
LROT_FUNCENTRY( _G, luaopen_base )
|
||||
LROT_FUNCENTRY( package, luaopen_package )
|
||||
LROT_FUNCENTRY( string, luaopen_string )
|
||||
#if LUA_VERSION_NUM >= 503
|
||||
LROT_FUNCENTRY( nodemcu, luaN_init )
|
||||
#endif
|
||||
LROT_FUNCENTRY( io, luaopen_io )
|
||||
LROT_FUNCENTRY( is, luaopen_os )
|
||||
LROT_END(lua_libs, NULL, 0)
|
||||
|
||||
#else
|
||||
|
||||
/* These symbols get created by the linker fragment mapping:nodemcu
|
||||
* at the head of the lua libs init table and the rotables, respectively.
|
||||
*/
|
||||
extern const ROTable_entry _lua_libs_map_start[];
|
||||
extern const ROTable_entry _lua_rotables_map_start[];
|
||||
|
||||
ROTable rotables_ROTable; /* NOT const in this case */
|
||||
|
||||
LROT_ENTRIES_IN_SECTION(rotables, rotable)
|
||||
#ifdef CONFIG_LUA_BUILTIN_STRING
|
||||
LROT_TABENTRY( string, strlib )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_TABLE
|
||||
LROT_TABENTRY( table, tab_funcs )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_COROUTINE
|
||||
LROT_TABENTRY( coroutine, co_funcs )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_DEBUG
|
||||
LROT_TABENTRY( debug, dblib)
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_MATH
|
||||
LROT_TABENTRY( math, mathlib )
|
||||
#endif
|
||||
#ifdef CONFIG_LUA_BUILTIN_UTF8
|
||||
LROT_TABENTRY( utf8, utf8 )
|
||||
#endif
|
||||
LROT_TABENTRY( ROM, rotables )
|
||||
LROT_BREAK(lua_rotables_part)
|
||||
|
||||
|
||||
LROT_ENTRIES_IN_SECTION(lua_libs, libs)
|
||||
LROT_FUNCENTRY( _G, luaopen_base )
|
||||
LROT_FUNCENTRY( package, luaopen_package )
|
||||
#ifdef CONFIG_LUA_BUILTIN_STRING
|
||||
LROT_FUNCENTRY( string, luaopen_string )
|
||||
#endif
|
||||
LROT_FUNCENTRY( nodemcu, luaN_init )
|
||||
LROT_BREAK(lua_libs)
|
||||
|
||||
#endif
|
||||
|
||||
/* Historically the linker script took care of zero terminating both the
|
||||
* lua_libs and lua_rotable arrays, but the IDF currently does not
|
||||
* support injecting LONG(0) entries. To compensate, we have explicit
|
||||
* end markers here which the linker fragment then place appropriately
|
||||
* to terminate aforementioned arrays.
|
||||
*/
|
||||
const ROTable_entry LOCK_IN_SECTION(libs_end_marker) libs_end_marker= { 0, };
|
||||
const ROTable_entry LOCK_IN_SECTION(rotable_end_marker) rotable_end_marker = { 0, };
|
||||
|
||||
void luaL_openlibs (lua_State *L) {
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
const ROTable_entry *p = LROT_TABLEREF(lua_libs)->entry;
|
||||
#else
|
||||
const ROTable_entry *p = _lua_libs_map_start;
|
||||
lua_createrotable(L, LROT_TABLEREF(rotables), _lua_rotables_map_start, NULL);
|
||||
#endif
|
||||
for ( ; p->key; p++) {
|
||||
#if LUA_VERSION_NUM == 501
|
||||
if (ttislightfunction(&p->value) && fvalue(&p->value)) {
|
||||
lua_pushcfunction(L, fvalue(&p->value));
|
||||
lua_pushstring(L, p->key);
|
||||
lua_call(L, 1, 0); // call luaopen_XXX(libname)
|
||||
}
|
||||
#else
|
||||
if (ttislcf(&p->value) && fvalue(&p->value))
|
||||
luaL_requiref(L, p->key, fvalue(&p->value), 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
_Static_assert(_Alignof(ROTable_entry) <= 8, "Unexpected alignment of module registration - update the linker script snippets to match!");
|
||||
#endif
|
119
components/lua/common/linput.c
Normal file
119
components/lua/common/linput.c
Normal file
@ -0,0 +1,119 @@
|
||||
#include "platform.h"
|
||||
#include "linput.h"
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static struct input_state {
|
||||
char *data;
|
||||
int line_pos;
|
||||
size_t len;
|
||||
const char *prompt;
|
||||
char last_nl_char;
|
||||
} ins = {0};
|
||||
|
||||
#define NUL '\0'
|
||||
#define BS '\010'
|
||||
#define CR '\r'
|
||||
#define LF '\n'
|
||||
#define DEL 0x7f
|
||||
#define BS_OVER "\010 \010"
|
||||
|
||||
bool input_echo = true;
|
||||
bool run_input = true;
|
||||
|
||||
/*
|
||||
** The input state (ins) is private, so input_setup() exposes the necessary
|
||||
** access to public properties and is called in user_init() before the Lua
|
||||
** enviroment is initialised.
|
||||
*/
|
||||
void input_setup(int bufsize, const char *prompt) {
|
||||
// Initialise non-zero elements
|
||||
ins.data = malloc(bufsize);
|
||||
ins.len = bufsize;
|
||||
ins.prompt = prompt;
|
||||
}
|
||||
|
||||
void input_setprompt (const char *prompt) {
|
||||
ins.prompt = prompt;
|
||||
}
|
||||
|
||||
|
||||
size_t feed_lua_input(const char *buf, size_t n)
|
||||
{
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
char ch = buf[i];
|
||||
if (!run_input) // We're no longer interested in the remaining bytes
|
||||
return i;
|
||||
|
||||
/* handle CR & LF characters and aggregate \n\r and \r\n pairs */
|
||||
char tmp_last_nl_char = ins.last_nl_char;
|
||||
/* handle CR & LF characters
|
||||
filters second char of LF&CR (\n\r) or CR&LF (\r\n) sequences */
|
||||
if ((ch == CR && tmp_last_nl_char == LF) || // \n\r sequence -> skip \r
|
||||
(ch == LF && tmp_last_nl_char == CR)) // \r\n sequence -> skip \n
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* backspace key */
|
||||
if (ch == DEL || ch == BS) {
|
||||
if (ins.line_pos > 0) {
|
||||
if(input_echo) printf(BS_OVER);
|
||||
ins.line_pos--;
|
||||
}
|
||||
ins.data[ins.line_pos] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* end of data */
|
||||
if (ch == CR || ch == LF) {
|
||||
ins.last_nl_char = ch;
|
||||
|
||||
if (input_echo) putchar(LF);
|
||||
if (ins.line_pos == 0) {
|
||||
/* Get a empty line, then go to get a new line */
|
||||
printf(ins.prompt);
|
||||
fflush(stdout);
|
||||
} else {
|
||||
ins.data[ins.line_pos++] = LF;
|
||||
lua_input_string(ins.data, ins.line_pos);
|
||||
ins.line_pos = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
ins.last_nl_char = NUL;
|
||||
|
||||
if(input_echo) putchar(ch);
|
||||
|
||||
/* it's a large line, discard it */
|
||||
if ( ins.line_pos + 1 >= ins.len ){
|
||||
ins.line_pos = 0;
|
||||
}
|
||||
|
||||
ins.data[ins.line_pos++] = ch;
|
||||
}
|
||||
|
||||
return n; // we consumed/buffered all the provided data
|
||||
}
|
||||
|
||||
|
||||
void output_redirect(const char *str, size_t l) {
|
||||
lua_State *L = lua_getstate();
|
||||
int n = lua_gettop(L);
|
||||
lua_pushliteral(L, "stdout");
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); /* fetch reg.stdout */
|
||||
if (lua_istable(L, -1)) { /* reg.stdout is pipe */
|
||||
lua_rawgeti(L, -1, 1); /* get the pipe_write func from stdout[1] */
|
||||
lua_insert(L, -2); /* and move above the pipe ref */
|
||||
lua_pushlstring(L, str, l);
|
||||
if (lua_pcall(L, 2, 0, 0) != LUA_OK) { /* Reg.stdout:write(str) */
|
||||
lua_writestringerror("error calling stdout:write(%s)\n", lua_tostring(L, -1));
|
||||
esp_restart();
|
||||
}
|
||||
} else { /* reg.stdout == nil */
|
||||
printf(str, l);
|
||||
}
|
||||
lua_settop(L, n); /* Make sure all code paths leave stack unchanged */
|
||||
}
|
15
components/lua/common/linput.h
Normal file
15
components/lua/common/linput.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef _LINPUT_H_
|
||||
#define _LINPUT_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void input_setup(int bufsize, const char *prompt);
|
||||
void input_setprompt (const char *prompt);
|
||||
|
||||
unsigned feed_lua_input(const char *buf, size_t n);
|
||||
|
||||
extern bool input_echo;
|
||||
extern bool run_input;
|
||||
|
||||
#endif /* READLINE_APP_H */
|
@ -99,7 +99,7 @@ char* luaX_alloc_string(lua_State* L, int idx, int max_length) {
|
||||
// luaX_free_string deallocates memory of a string allocated with luaX_alloc_string
|
||||
void luaX_free_string(lua_State* L, char* st) {
|
||||
if (st)
|
||||
luaM_freearray(L, st, strlen(st) + 1, char);
|
||||
luaN_freearray(L, st, strlen(st) + 1);
|
||||
}
|
||||
|
||||
// luaX_unset_ref unpins a reference to a lua object in the registry
|
@ -36,6 +36,7 @@
|
||||
#define _NODEMCU_LNODEAUX_H_
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
// lua_ref_t represents a reference to a lua object in the registry
|
||||
typedef int lua_ref_t;
|
54
components/lua/common/lpanic.c
Normal file
54
components/lua/common/lpanic.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include "lpanic.h"
|
||||
#include "lauxlib.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
#include "esp_system.h"
|
||||
/* defined in esp_system_internal.h */
|
||||
void esp_reset_reason_set_hint(esp_reset_reason_t hint);
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
/*
|
||||
* upper 28 bit have magic value 0xD1EC0DE0
|
||||
* if paniclevel is valid (i.e. matches magic value)
|
||||
* lower 4 bits have paniclevel:
|
||||
* 0 = no panic occurred
|
||||
* 1..15 = one..fifteen subsequent panic(s) occurred
|
||||
*/
|
||||
static __NOINIT_ATTR uint32_t l_rtc_panic_val;
|
||||
|
||||
void panic_clear_nvval() {
|
||||
l_rtc_panic_val = 0xD1EC0DE0;
|
||||
}
|
||||
|
||||
int panic_get_nvval() {
|
||||
if ((l_rtc_panic_val & 0xfffffff0) == 0xD1EC0DE0) {
|
||||
return (l_rtc_panic_val & 0xf);
|
||||
}
|
||||
panic_clear_nvval();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int lpanic (lua_State *L) {
|
||||
(void)L; /* to avoid warnings */
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
uint8_t paniclevel = panic_get_nvval();
|
||||
if (paniclevel < 15) paniclevel++;
|
||||
l_rtc_panic_val = 0xD1EC0DE0 | paniclevel;
|
||||
#endif
|
||||
lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
|
||||
lua_tostring(L, -1));
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
fflush(stdout);
|
||||
/* call abort() directly - we don't want another reset cause to intervene */
|
||||
esp_reset_reason_set_hint(ESP_RST_PANIC);
|
||||
#endif
|
||||
abort();
|
||||
while (1) {}
|
||||
return 0;
|
||||
}
|
10
components/lua/common/lpanic.h
Normal file
10
components/lua/common/lpanic.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _LUA_PANIC_H_
|
||||
#define _LUA_PANIC_H_
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
void panic_clear_nvval (void);
|
||||
int panic_get_nvval (void);
|
||||
int lpanic (lua_State *L);
|
||||
|
||||
#endif
|
@ -1,12 +0,0 @@
|
||||
// Lua EGC (Emergeny Garbage Collector) interface
|
||||
|
||||
#include "legc.h"
|
||||
#include "lstate.h"
|
||||
|
||||
void legc_set_mode(lua_State *L, int mode, int limit) {
|
||||
global_State *g = G(L);
|
||||
|
||||
g->egcmode = mode;
|
||||
g->memlimit = limit;
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
// Lua EGC (Emergeny Garbage Collector) interface
|
||||
|
||||
#ifndef __LEGC_H__
|
||||
#define __LEGC_H__
|
||||
|
||||
#include "lstate.h"
|
||||
|
||||
// EGC operations modes
|
||||
#define EGC_NOT_ACTIVE 0 // EGC disabled
|
||||
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure
|
||||
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
|
||||
#define EGC_ALWAYS 4 // always run EGC before an allocation
|
||||
|
||||
void legc_set_mode(lua_State *L, int mode, int limit);
|
||||
|
||||
#endif
|
||||
|
35
components/lua/link_lua.lf
Normal file
35
components/lua/link_lua.lf
Normal file
@ -0,0 +1,35 @@
|
||||
[sections:lua_libs]
|
||||
entries:
|
||||
.lua_libs
|
||||
|
||||
[sections:lua_libs_end_marker]
|
||||
entries:
|
||||
.lua_libs_end_marker
|
||||
|
||||
[sections:lua_rotable]
|
||||
entries:
|
||||
.lua_rotable
|
||||
|
||||
[sections:lua_rotable_end_marker]
|
||||
entries:
|
||||
.lua_rotable_end_marker
|
||||
|
||||
[scheme:lua_arrays]
|
||||
entries:
|
||||
lua_libs -> flash_rodata
|
||||
lua_libs_end_marker -> flash_rodata
|
||||
lua_rotable -> flash_rodata
|
||||
lua_rotable_end_marker -> flash_rodata
|
||||
|
||||
|
||||
# Important: don't change the alignments below without also updating the
|
||||
# _Static_assert over in linit.c!
|
||||
|
||||
[mapping:lua]
|
||||
archive: *
|
||||
entries:
|
||||
* (lua_arrays);
|
||||
lua_libs -> flash_rodata KEEP() ALIGN(8) SURROUND(lua_libs_map),
|
||||
lua_libs_end_marker -> flash_rodata KEEP(),
|
||||
lua_rotable -> flash_rodata KEEP() ALIGN(8) SURROUND(lua_rotables_map),
|
||||
lua_rotable_end_marker -> flash_rodata KEEP()
|
@ -1,157 +0,0 @@
|
||||
/* Read-only tables for Lua */
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
#include "lrotable.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lstring.h"
|
||||
#include "lobject.h"
|
||||
#include "lapi.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ALIGNED_STRING __declspec( align( 4 ) ) char
|
||||
#else
|
||||
#define ALIGNED_STRING __attribute__((aligned(4))) char
|
||||
#endif
|
||||
#define LA_LINES 32
|
||||
#define LA_SLOTS 4
|
||||
//#define COLLECT_STATS
|
||||
|
||||
/*
|
||||
* All keyed ROtable access passes through luaR_findentry(). ROTables
|
||||
* are simply a list of <key><TValue value> pairs. The existing algo
|
||||
* did a linear scan of this vector of pairs looking for a match.
|
||||
*
|
||||
* A N×M lookaside cache has been added, with a simple hash on the key's
|
||||
* TString addr and the ROTable addr to identify one of N lines. Each
|
||||
* line has M slots which are scanned. This is all done in RAM and is
|
||||
* perhaps 20x faster than the corresponding random Flash accesses which
|
||||
* will cause flash faults.
|
||||
*
|
||||
* If a match is found and the table addresses match, then this entry is
|
||||
* probed first. In practice the hit-rate here is over 99% so the code
|
||||
* rarely fails back to doing the linear scan in ROM.
|
||||
*
|
||||
* Note that this hash does a couple of prime multiples and a modulus 2^X
|
||||
* with is all evaluated in H/W, and adequately randomizes the lookup.
|
||||
*/
|
||||
#define HASH(a,b) ((((519*(size_t)(a)))>>4) + ((b) ? (b)->tsv.hash: 0))
|
||||
|
||||
static struct {
|
||||
unsigned hash;
|
||||
unsigned addr:24;
|
||||
unsigned ndx:8;
|
||||
} cache[LA_LINES][LA_SLOTS];
|
||||
|
||||
#ifdef COLLECT_STATS
|
||||
unsigned cache_stats[3];
|
||||
#define COUNT(i) cache_stats[i]++
|
||||
#else
|
||||
#define COUNT(i)
|
||||
#endif
|
||||
|
||||
static int lookup_cache(unsigned hash, ROTable *rotable) {
|
||||
int i = (hash>>2) & (LA_LINES-1), j;
|
||||
|
||||
for (j = 0; j<LA_SLOTS; j++) {
|
||||
if (cache[i][j].hash == hash &&
|
||||
((size_t)rotable & 0xffffffu) == cache[i][j].addr) {
|
||||
COUNT(0);
|
||||
return cache[i][j].ndx;
|
||||
}
|
||||
}
|
||||
COUNT(1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void update_cache(unsigned hash, ROTable *rotable, unsigned ndx) {
|
||||
int i = (hash)>>2 & (LA_LINES-1), j;
|
||||
COUNT(2);
|
||||
if (ndx>0xffu)
|
||||
return;
|
||||
for (j = LA_SLOTS-1; j>0; j--)
|
||||
cache[i][j] = cache[i][j-1];
|
||||
cache[i][0].hash = hash;
|
||||
cache[i][0].addr = (size_t) rotable;
|
||||
cache[i][0].ndx = ndx;
|
||||
}
|
||||
/*
|
||||
* Find a string key entry in a rotable and return it. Note that this internally
|
||||
* uses a null key to denote a metatable search.
|
||||
*/
|
||||
const TValue* luaR_findentry(ROTable *rotable, TString *key, unsigned *ppos) {
|
||||
const luaR_entry *pentry = rotable;
|
||||
static const ALIGNED_STRING metatablestr[] = "__metatable";
|
||||
const char *strkey = key ? getstr(key) : metatablestr;
|
||||
unsigned hash = HASH(rotable, key);
|
||||
|
||||
unsigned i = 0;
|
||||
int j = lookup_cache(hash, rotable);
|
||||
unsigned l = key ? key->tsv.len : sizeof("__metatable")-1;
|
||||
|
||||
if (pentry) {
|
||||
if (j >= 0 && !strcmp(pentry[j].key, strkey)) {
|
||||
if (ppos)
|
||||
*ppos = j;
|
||||
//printf("%3d hit %p %s\n", (hash>>2) & (LA_LINES-1), rotable, strkey);
|
||||
return &pentry[j].value;
|
||||
}
|
||||
/*
|
||||
* The invariants for 1st word comparison are deferred to here since they
|
||||
* aren't needed if there is a cache hit. Note that the termination null
|
||||
* is included so a "on\0" has a mask of 0xFFFFFF and "a\0" has 0xFFFF.
|
||||
*/
|
||||
unsigned name4, mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8);
|
||||
memcpy(&name4, strkey, sizeof(name4));
|
||||
|
||||
for(;pentry->key != NULL; i++, pentry++) {
|
||||
if (((*(unsigned *)pentry->key ^ name4) & mask4) == 0 &&
|
||||
!strcmp(pentry->key, strkey)) {
|
||||
//printf("%p %s hit after %d probes \n", rotable, strkey, (int)(pentry-rotable));
|
||||
if (ppos)
|
||||
*ppos = i;
|
||||
update_cache(hash, rotable, pentry - rotable);
|
||||
//printf("%3d %3d %p %s\n", (hash>>2) & (LA_LINES-1), (int)(pentry-rotable), rotable, strkey);
|
||||
return &pentry->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf("%p %s miss after %d probes \n", rotable, strkey, (int)(pentry-rotable));
|
||||
return luaO_nilobject;
|
||||
}
|
||||
|
||||
/* Find the metatable of a given table */
|
||||
void* luaR_getmeta(ROTable *rotable) {
|
||||
const TValue *res = luaR_findentry(rotable, NULL, NULL);
|
||||
return res && ttisrotable(res) ? rvalue(res) : NULL;
|
||||
}
|
||||
|
||||
static void luaR_next_helper(lua_State *L, ROTable *pentries, int pos,
|
||||
TValue *key, TValue *val) {
|
||||
if (pentries[pos].key) {
|
||||
/* Found an entry */
|
||||
setsvalue(L, key, luaS_new(L, pentries[pos].key));
|
||||
setobj2s(L, val, &pentries[pos].value);
|
||||
} else {
|
||||
setnilvalue(key);
|
||||
setnilvalue(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* next (used for iteration) */
|
||||
void luaR_next(lua_State *L, ROTable *rotable, TValue *key, TValue *val) {
|
||||
unsigned keypos;
|
||||
|
||||
/* Special case: if key is nil, return the first element of the rotable */
|
||||
if (ttisnil(key))
|
||||
luaR_next_helper(L, rotable, 0, key, val);
|
||||
else if (ttisstring(key)) {
|
||||
/* Find the previous key again */
|
||||
luaR_findentry(rotable, rawtsvalue(key), &keypos);
|
||||
/* Advance to next key */
|
||||
keypos ++;
|
||||
luaR_next_helper(L, rotable, keypos, key, val);
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/* Read-only tables for Lua */
|
||||
|
||||
#ifndef lrotable_h
|
||||
#define lrotable_h
|
||||
|
||||
#include "lua.h"
|
||||
#include "luaconf.h"
|
||||
#include "lobject.h"
|
||||
#include "llimits.h"
|
||||
|
||||
/* Macros one can use to define rotable entries */
|
||||
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
|
||||
#define LRO_LUDATA(v) {{.p = v}, LUA_TLIGHTUSERDATA}
|
||||
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
|
||||
#define LRO_ROVAL(v) {{.p = (void*)v}, LUA_TROTABLE}
|
||||
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
#define LRO_STRKEY(k) k
|
||||
#else
|
||||
#define LRO_STRKEY(k) ((__attribute__((aligned(4))) char *) k)
|
||||
#endif
|
||||
|
||||
#define LROT_TABLE(t) static const LUA_REG_TYPE t ## _map[];
|
||||
#define LROT_PUBLIC_TABLE(t) const LUA_REG_TYPE t ## _map[];
|
||||
#define LROT_TABLEREF(t) ((void *) t ## _map)
|
||||
#define LROT_BEGIN(t) static const LUA_REG_TYPE t ## _map [] = {
|
||||
#define LROT_PUBLIC_BEGIN(t) const LUA_REG_TYPE t ## _map[] = {
|
||||
#define LROT_EXTERN(t) extern const LUA_REG_TYPE t ## _map[]
|
||||
#define LROT_TABENTRY(n,t) {LRO_STRKEY(#n), LRO_ROVAL(t ## _map)},
|
||||
#define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
|
||||
#define LROT_NUMENTRY(n,x) {LRO_STRKEY(#n), LRO_NUMVAL(x)},
|
||||
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA((void *) x)},
|
||||
#define LROT_END(t,mt, f) {NULL, LRO_NILVAL} };
|
||||
#define LROT_BREAK(t) };
|
||||
|
||||
#define LUA_REG_TYPE luaR_entry
|
||||
#define LREGISTER(L, name, table) return 0
|
||||
|
||||
/* Maximum length of a rotable name and of a string key*/
|
||||
#define LUA_MAX_ROTABLE_NAME 32
|
||||
|
||||
/* Type of a numeric key in a rotable */
|
||||
typedef int luaR_numkey;
|
||||
|
||||
/* An entry in the read only table */
|
||||
typedef struct luaR_entry {
|
||||
const char *key;
|
||||
const TValue value;
|
||||
} luaR_entry;
|
||||
|
||||
/*
|
||||
* The current ROTable implmentation is a vector of luaR_entry terminated by a
|
||||
* nil record. The convention is to use ROtable * to refer to the entire vector
|
||||
* as a logical ROTable.
|
||||
*/
|
||||
typedef const struct luaR_entry ROTable;
|
||||
|
||||
const TValue* luaR_findentry(ROTable *tab, TString *key, unsigned *ppos);
|
||||
const TValue* luaR_findentryN(ROTable *tab, luaR_numkey numkey, unsigned *ppos);
|
||||
void luaR_next(lua_State *L, ROTable *tab, TValue *key, TValue *val);
|
||||
void* luaR_getmeta(ROTable *tab);
|
||||
int luaR_isrotable(void *p);
|
||||
|
||||
/*
|
||||
* Set inRO check depending on platform. Note that this implementation needs
|
||||
* to work on both the host (luac.cross) and ESP targets. The luac.cross
|
||||
* VM is used for the -e option, and is primarily used to be able to debug
|
||||
* VM changes on the more developer-friendly hot gdb environment.
|
||||
*/
|
||||
#if defined(LUA_CROSS_COMPILER)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
//msvc build uses these dummy vars to locate the beginning and ending addresses of the RO data
|
||||
extern const char _ro_start[], _ro_end[];
|
||||
#define IN_RODATA_AREA(p) (((const char*)(p)) >= _ro_start && ((const char *)(p)) <= _ro_end)
|
||||
#else /* one of the POSIX variants */
|
||||
#if defined(__CYGWIN__)
|
||||
#define _RODATA_END __end__
|
||||
#elif defined(__MINGW32__)
|
||||
#define _RODATA_END end
|
||||
#else
|
||||
#define _RODATA_END _edata
|
||||
#endif
|
||||
extern const char _RODATA_END[];
|
||||
#define IN_RODATA_AREA(p) (((const char *)(p)) < _RODATA_END)
|
||||
#endif /* defined(_MSC_VER) */
|
||||
|
||||
#else /* xtensa tool chain for ESP32 target */
|
||||
|
||||
#include "compiler.h"
|
||||
#define IN_RODATA_AREA(p) (((const char *)p) >= RODATA_START_ADDRESS && ((const char *)p) <= RODATA_END_ADDRESS)
|
||||
|
||||
#endif /* defined(LUA_CROSS_COMPILER) */
|
||||
|
||||
/* Return 1 if the given pointer is a rotable */
|
||||
#define luaR_isrotable(p) IN_RODATA_AREA(p)
|
||||
|
||||
#endif
|
68
components/lua/lua-5.1/host/idf.mk
Normal file
68
components/lua/lua-5.1/host/idf.mk
Normal file
@ -0,0 +1,68 @@
|
||||
all: build
|
||||
|
||||
HOSTCC?=$(PYTHON) -m ziglang cc
|
||||
|
||||
ifeq ($V,)
|
||||
Q:=@
|
||||
endif
|
||||
|
||||
LUAC_OBJ_DIR:=$(LUAC_BUILD_DIR)/$(notdir $(LUA_PATH))
|
||||
|
||||
LUAC_CFLAGS:= \
|
||||
-I$(LUAC_BUILD_DIR) \
|
||||
-I$(LUA_PATH) \
|
||||
-I$(LUA_PATH)/host \
|
||||
-I$(LUA_PATH)/../common \
|
||||
-I$(LUA_PATH)/../../uzlib \
|
||||
-O2 -g -Wall -Wextra -Wno-sign-compare
|
||||
|
||||
LUAC_LDFLAGS:= -ldl -lm
|
||||
|
||||
LUAC_DEFINES += \
|
||||
-DLUA_CROSS_COMPILER \
|
||||
-DLUA_USE_HOST \
|
||||
-DLUA_USE_STDIO \
|
||||
|
||||
vpath %.c $(LUA_PATH)/host $(LUA_PATH) $(LUA_PATH)/../common $(LUA_PATH)/../../uzlib
|
||||
|
||||
LUA_SRCS:=\
|
||||
luac.c lflashimg.c loslib.c print.c liolib.c \
|
||||
lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c \
|
||||
ldo.c ldump.c lfunc.c lgc.c llex.c \
|
||||
lmathlib.c lmem.c loadlib.c lobject.c lopcodes.c lparser.c \
|
||||
lnodemcu.c lstate.c lstring.c lstrlib.c ltable.c ltablib.c \
|
||||
ltm.c lundump.c lvm.c lzio.c \
|
||||
linit.c lpanic.c \
|
||||
uzlib_deflate.c crc32.c \
|
||||
|
||||
LUAC_OBJS:=$(LUA_SRCS:%.c=$(LUAC_OBJ_DIR)/%.o)
|
||||
LUAC_CROSS:=$(LUAC_BUILD_DIR)/luac.cross
|
||||
|
||||
$(LUAC_OBJ_DIR):
|
||||
@mkdir -p "$@"
|
||||
|
||||
$(LUAC_OBJ_DIR)/%.o: %.c | $(LUAC_OBJ_DIR)
|
||||
@echo '[hostcc] $(notdir $@)'
|
||||
$Q$(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) "$<" -c -o "$@"
|
||||
|
||||
$(LUAC_OBJ_DIR)/%.d: SHELL=/bin/bash
|
||||
$(LUAC_OBJ_DIR)/%.d: %.c | $(LUAC_OBJ_DIR)
|
||||
@echo '[ dep] $<'
|
||||
@rm -f "$@"
|
||||
$Qset -eo pipefail; $(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) -M "$<" | sed 's,\($*\.o\)[ :]*,$(LUAC_OBJ_DIR)/\1 $@ : ,g' > "$@.tmp"; mv "$@.tmp" "$@"
|
||||
|
||||
build: $(LUAC_DEPS) $(LUAC_CROSS)
|
||||
|
||||
$(LUAC_CROSS): $(LUAC_OBJS)
|
||||
@echo '[ link] $(notdir $@)'
|
||||
$Q$(HOSTCC) $(LUAC_CFLAGS) $^ $(LUAC_LDFLAGS) -o "$@"
|
||||
|
||||
# zig cc (0.8.0 at least) seems to get itself all confused with its cache
|
||||
# when we're running a separate path for dependencies, so we skip them for
|
||||
# now as for most people they're not needed anyway.
|
||||
ifneq ($(findstring zig,$(HOSTCC)),zig)
|
||||
LUAC_DEPS:=$(LUAC_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(LUAC_DEPS)
|
||||
endif
|
||||
endif
|
@ -6,7 +6,6 @@
|
||||
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "luac_cross.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -109,10 +108,11 @@ static uint *flashAddrTag = flashImage + LUA_MAX_FLASH_SIZE;
|
||||
#define setFlashAddrTag(v) flashAddrTag[_TW(v)] |= _TB(v)
|
||||
#define getFlashAddrTag(v) ((flashAddrTag[_TW(v)]&_TB(v)) != 0)
|
||||
|
||||
#define fatal luac_fatal
|
||||
#ifdef _MSC_VER
|
||||
extern void __declspec( noreturn ) fatal( const char* message );
|
||||
extern void __declspec( noreturn ) luac_fatal( const char* message );
|
||||
#else
|
||||
extern void __attribute__((noreturn)) fatal(const char* message);
|
||||
extern void __attribute__((noreturn)) luac_fatal(const char* message);
|
||||
#endif
|
||||
|
||||
#ifdef LOCAL_DEBUG
|
||||
@ -188,10 +188,8 @@ static void scanProtoStrings(lua_State *L, const Proto* f) {
|
||||
if (f->source)
|
||||
addTS(L, f->source);
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
if (f->packedlineinfo)
|
||||
addTS(L, luaS_new(L, cast(const char *, f->packedlineinfo)));
|
||||
#endif
|
||||
|
||||
for (i = 0; i < f->sizek; i++) {
|
||||
if (ttisstring(f->k + i))
|
||||
@ -357,11 +355,7 @@ static void *flashCopy(lua_State* L, int n, const char *fmt, void *src) {
|
||||
}
|
||||
|
||||
/* The debug optimised version has a different Proto layout */
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
#define PROTO_COPY_MASK "AHAAAAAASIIIIIIIAI"
|
||||
#else
|
||||
#define PROTO_COPY_MASK "AHAAAAAASIIIIIIIIAI"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do the actual prototype copy.
|
||||
@ -385,14 +379,10 @@ static void *functionToFlash(lua_State* L, const Proto* orig) {
|
||||
f.k = cast(TValue *, flashCopy(L, f.sizek, "V", f.k));
|
||||
f.code = cast(Instruction *, flashCopy(L, f.sizecode, "I", f.code));
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
if (f.packedlineinfo) {
|
||||
TString *ts=luaS_new(L, cast(const char *,f.packedlineinfo));
|
||||
f.packedlineinfo = cast(unsigned char *, resolveTString(L, ts)) + sizeof (FlashTS);
|
||||
}
|
||||
#else
|
||||
f.lineinfo = cast(int *, flashCopy(L, f.sizelineinfo, "I", f.lineinfo));
|
||||
#endif
|
||||
f.locvars = cast(struct LocVar *, flashCopy(L, f.sizelocvars, "SII", f.locvars));
|
||||
f.upvalues = cast(TString **, flashCopy(L, f.sizeupvalues, "S", f.upvalues));
|
||||
return cast(void *, flashCopy(L, 1, PROTO_COPY_MASK, &f));
|
||||
@ -401,10 +391,10 @@ static void *functionToFlash(lua_State* L, const Proto* orig) {
|
||||
uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
|
||||
void* data, int strip,
|
||||
lu_int32 address, lu_int32 maxSize) {
|
||||
(void)strip;
|
||||
// parameter strip is ignored for now
|
||||
(void)strip;
|
||||
FlashHeader *fh = cast(FlashHeader *, flashAlloc(L, sizeof(FlashHeader)));
|
||||
int status;
|
||||
int i, status;
|
||||
lua_newtable(L);
|
||||
scanProtoStrings(L, main);
|
||||
createROstrt(L, fh);
|
||||
@ -416,7 +406,7 @@ uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
|
||||
fatal ("The image is too large for specfied LFS size");
|
||||
}
|
||||
if (address) { /* in absolute mode convert addresses to mapped address */
|
||||
for (uint i = 0 ; i < curOffset; i++)
|
||||
for (i = 0 ; i < curOffset; i++)
|
||||
if (getFlashAddrTag(i))
|
||||
flashImage[i] = 4*flashImage[i] + address;
|
||||
lua_unlock(L);
|
||||
@ -434,7 +424,7 @@ uint dumpToFlashImage (lua_State* L, const Proto *main, lua_Writer w,
|
||||
status = uzlib_compress (&oBuf, &oLen,
|
||||
(const uint8_t *)flashImage, bmLen+fh->flash_size);
|
||||
if (status != UZLIB_OK) {
|
||||
fatal("Out of memory during image compression");
|
||||
luac_fatal("Out of memory during image compression");
|
||||
}
|
||||
lua_unlock(L);
|
||||
#if 0
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "lrotable.h"
|
||||
#include "lnodemcu.h"
|
||||
|
||||
#define IO_INPUT 1
|
||||
#define IO_OUTPUT 2
|
||||
@ -439,7 +439,10 @@ static int f_flush (lua_State *L) {
|
||||
return pushresult(L, fflush(tofile(L)) == 0, NULL);
|
||||
}
|
||||
|
||||
LROT_PUBLIC_BEGIN(iolib)
|
||||
LROT_TABLE(iolib);
|
||||
|
||||
LROT_BEGIN(iolib, NULL, LROT_MASK_GC_INDEX)
|
||||
LROT_TABENTRY( __index, iolib )
|
||||
LROT_FUNCENTRY( close, io_close )
|
||||
LROT_FUNCENTRY( flush, io_flush )
|
||||
LROT_FUNCENTRY( input, io_input )
|
||||
@ -449,10 +452,14 @@ LROT_PUBLIC_BEGIN(iolib)
|
||||
LROT_FUNCENTRY( read, io_read )
|
||||
LROT_FUNCENTRY( type, io_type )
|
||||
LROT_FUNCENTRY( write, io_write )
|
||||
LROT_TABENTRY( __index, iolib )
|
||||
LROT_END(iolib, NULL, 0)
|
||||
LROT_END(iolib, NULL, LROT_MASK_GC_INDEX)
|
||||
|
||||
LROT_BEGIN(flib)
|
||||
LROT_TABLE(flib);
|
||||
|
||||
LROT_BEGIN(flib, NULL, LROT_MASK_GC_INDEX)
|
||||
LROT_FUNCENTRY( __gc, io_gc )
|
||||
LROT_TABENTRY( __index, flib )
|
||||
LROT_FUNCENTRY( __tostring, io_tostring )
|
||||
LROT_FUNCENTRY( close, io_close )
|
||||
LROT_FUNCENTRY( flush, f_flush )
|
||||
LROT_FUNCENTRY( lines, f_lines )
|
||||
@ -460,9 +467,6 @@ LROT_BEGIN(flib)
|
||||
LROT_FUNCENTRY( seek, f_seek )
|
||||
LROT_FUNCENTRY( setvbuf, f_setvbuf )
|
||||
LROT_FUNCENTRY( write, f_write )
|
||||
LROT_FUNCENTRY( __gc, io_gc )
|
||||
LROT_FUNCENTRY( __tostring, io_tostring )
|
||||
LROT_TABENTRY( __index, flib )
|
||||
LROT_END(flib, NULL, LROT_MASK_GC_INDEX)
|
||||
|
||||
static const luaL_Reg io_base[] = {{NULL, NULL}};
|
@ -6,7 +6,6 @@
|
||||
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "luac_cross.h"
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
@ -20,8 +19,7 @@
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
#include "lnodemcu.h"
|
||||
|
||||
static int os_pushresult (lua_State *L, int i, const char *filename) {
|
||||
int en = errno; /* calls to Lua API may change this value */
|
||||
@ -221,32 +219,26 @@ static int os_exit (lua_State *L) {
|
||||
exit(luaL_optint(L, 1, EXIT_SUCCESS));
|
||||
}
|
||||
|
||||
#undef MIN_OPT_LEVEL
|
||||
#define MIN_OPT_LEVEL 1
|
||||
#include "lrotable.h"
|
||||
LROT_PUBLIC_BEGIN(oslib)
|
||||
LROT_FUNCENTRY(clock, os_clock)
|
||||
LROT_FUNCENTRY(date, os_date)
|
||||
LROT_BEGIN(oslib, NULL, 0)
|
||||
LROT_FUNCENTRY( clock, os_clock )
|
||||
LROT_FUNCENTRY( date, os_date )
|
||||
#if !defined LUA_NUMBER_INTEGRAL
|
||||
LROT_FUNCENTRY(difftime, os_difftime)
|
||||
LROT_FUNCENTRY( difftime, os_difftime )
|
||||
#endif
|
||||
LROT_FUNCENTRY(execute, os_execute)
|
||||
LROT_FUNCENTRY(exit, os_exit)
|
||||
LROT_FUNCENTRY(getenv, os_getenv)
|
||||
LROT_FUNCENTRY(remove, os_remove)
|
||||
LROT_FUNCENTRY(rename, os_rename)
|
||||
LROT_FUNCENTRY(setlocale, os_setlocale)
|
||||
LROT_FUNCENTRY(time, os_time)
|
||||
LROT_FUNCENTRY(tmpname, os_tmpname)
|
||||
LROT_FUNCENTRY( execute, os_execute )
|
||||
LROT_FUNCENTRY( exit, os_exit )
|
||||
LROT_FUNCENTRY( getenv, os_getenv )
|
||||
LROT_FUNCENTRY( remove, os_remove )
|
||||
LROT_FUNCENTRY( rename, os_rename )
|
||||
LROT_FUNCENTRY( setlocale, os_setlocale )
|
||||
LROT_FUNCENTRY( time, os_time )
|
||||
LROT_FUNCENTRY( tmpname, os_tmpname )
|
||||
LROT_END(oslib, NULL, 0)
|
||||
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
LUALIB_API int luaopen_os (lua_State *L) {
|
||||
(void)L;
|
||||
//LREGISTER(L, LUA_OSLIBNAME, oslib); // <------------- ???
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
@ -5,15 +5,15 @@
|
||||
*/
|
||||
|
||||
#define LUAC_CROSS_FILE
|
||||
#define luac_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "luac_cross.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define luac_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
@ -42,11 +42,12 @@ static const char* execute; /* executed a Lua file */
|
||||
static const char* progname=PROGNAME; /* actual program name */
|
||||
static DumpTargetInfo target;
|
||||
|
||||
void fatal(const char* message)
|
||||
void luac_fatal(const char* message)
|
||||
{
|
||||
fprintf(stderr,"%s: %s\n",progname,message);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#define fatal(s) luac_fatal(s)
|
||||
|
||||
static void cannot(const char* what)
|
||||
{
|
||||
@ -280,8 +281,8 @@ static int pmain(lua_State* L)
|
||||
if (!lua_checkstack(L,argc)) fatal("too many input files");
|
||||
if (execute)
|
||||
{
|
||||
if (luaL_loadfile(L,execute)!=0) fatal(lua_tostring(L,-1));
|
||||
luaL_openlibs(L);
|
||||
if (luaL_loadfile(L,execute)!=0) fatal(lua_tostring(L,-1));
|
||||
lua_pushstring(L, execute);
|
||||
if (lua_pcall(L, 1, 1, 0)) fatal(lua_tostring(L,-1));
|
||||
if (!lua_isfunction(L, -1))
|
@ -6,7 +6,6 @@
|
||||
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "luac_cross.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
@ -6,11 +6,9 @@
|
||||
|
||||
#define lapi_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
//#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "lapi.h"
|
||||
@ -26,7 +24,6 @@
|
||||
#include "ltm.h"
|
||||
#include "lundump.h"
|
||||
#include "lvm.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
#if 0
|
||||
const char lua_ident[] =
|
||||
@ -155,6 +152,16 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** convert an acceptable stack index into an absolute index
|
||||
*/
|
||||
LUA_API int lua_absindex (lua_State *L, int idx) {
|
||||
return (idx > 0 || idx <= LUA_REGISTRYINDEX)
|
||||
? idx
|
||||
: cast_int(L->top - L->base) - 1 + idx;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_gettop (lua_State *L) {
|
||||
return cast_int(L->top - L->base);
|
||||
}
|
||||
@ -243,6 +250,12 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) {
|
||||
|
||||
|
||||
LUA_API int lua_type (lua_State *L, int idx) {
|
||||
StkId o = index2adr(L, idx);
|
||||
return (o == luaO_nilobject) ? LUA_TNONE : ttnov(o);
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_fulltype (lua_State *L, int idx) {
|
||||
StkId o = index2adr(L, idx);
|
||||
return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);
|
||||
}
|
||||
@ -250,7 +263,7 @@ LUA_API int lua_type (lua_State *L, int idx) {
|
||||
|
||||
LUA_API const char *lua_typename (lua_State *L, int t) {
|
||||
UNUSED(L);
|
||||
return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
|
||||
return (t == LUA_TNONE || t >= LUA_NUMTAGS) ? "no value" : luaT_typenames[t];
|
||||
}
|
||||
|
||||
|
||||
@ -287,32 +300,25 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_equal (lua_State *L, int index1, int index2) {
|
||||
LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
|
||||
StkId o1, o2;
|
||||
int i;
|
||||
int i = 0;
|
||||
lua_lock(L); /* may call tag method */
|
||||
o1 = index2adr(L, index1);
|
||||
o2 = index2adr(L, index2);
|
||||
i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);
|
||||
if (o1 != luaO_nilobject && o2 != luaO_nilobject) {
|
||||
switch (op) {
|
||||
case LUA_OPEQ: i = luaV_equalval(L, o1, o2); break;
|
||||
case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
|
||||
case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
|
||||
default: api_check(L, 0);
|
||||
}
|
||||
}
|
||||
lua_unlock(L);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
|
||||
StkId o1, o2;
|
||||
int i;
|
||||
lua_lock(L); /* may call tag method */
|
||||
o1 = index2adr(L, index1);
|
||||
o2 = index2adr(L, index2);
|
||||
i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0
|
||||
: luaV_lessthan(L, o1, o2);
|
||||
lua_unlock(L);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
|
||||
TValue n;
|
||||
const TValue *o = index2adr(L, idx);
|
||||
@ -363,11 +369,10 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
|
||||
|
||||
LUA_API size_t lua_objlen (lua_State *L, int idx) {
|
||||
StkId o = index2adr(L, idx);
|
||||
switch (ttype(o)) {
|
||||
switch (ttnov(o)) {
|
||||
case LUA_TSTRING: return tsvalue(o)->len;
|
||||
case LUA_TUSERDATA: return uvalue(o)->len;
|
||||
case LUA_TTABLE: return luaH_getn(hvalue(o));
|
||||
case LUA_TROTABLE: return luaH_getn_ro(rvalue(o));
|
||||
case LUA_TNUMBER: {
|
||||
size_t l;
|
||||
lua_lock(L); /* `luaV_tostring' may create a new string */
|
||||
@ -405,16 +410,14 @@ LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
|
||||
LUA_API const void *lua_topointer (lua_State *L, int idx) {
|
||||
StkId o = index2adr(L, idx);
|
||||
switch (ttype(o)) {
|
||||
case LUA_TTABLE: return hvalue(o);
|
||||
case LUA_TTABLE:
|
||||
case LUA_TROTABLE:
|
||||
return hvalue(o);
|
||||
case LUA_TFUNCTION: return clvalue(o);
|
||||
case LUA_TTHREAD: return thvalue(o);
|
||||
case LUA_TUSERDATA:
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
return lua_touserdata(L, idx);
|
||||
case LUA_TROTABLE:
|
||||
return rvalue(o);
|
||||
case LUA_TLIGHTFUNCTION:
|
||||
return fvalue(o);
|
||||
case LUA_TUSERDATA: return lua_touserdata(L, idx);
|
||||
case LUA_TLIGHTUSERDATA: return pvalue(o);
|
||||
case LUA_TLIGHTFUNCTION: return fvalue(o);
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@ -492,18 +495,23 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
|
||||
|
||||
|
||||
LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
|
||||
Closure *cl;
|
||||
lua_lock(L);
|
||||
luaC_checkGC(L);
|
||||
api_checknelems(L, n);
|
||||
cl = luaF_newCclosure(L, n, getcurrenv(L));
|
||||
cl->c.f = fn;
|
||||
L->top -= n;
|
||||
while (n--)
|
||||
setobj2n(L, &cl->c.upvalue[n], L->top+n);
|
||||
setclvalue(L, L->top, cl);
|
||||
lua_assert(iswhite(obj2gco(cl)));
|
||||
api_incr_top(L);
|
||||
if (n == 0) {
|
||||
setfvalue(L->top, fn);
|
||||
api_incr_top(L);
|
||||
} else {
|
||||
Closure *cl;
|
||||
luaC_checkGC(L);
|
||||
api_checknelems(L, n);
|
||||
cl = luaF_newCclosure(L, n, getcurrenv(L));
|
||||
cl->c.f = fn;
|
||||
L->top -= n;
|
||||
while (n--)
|
||||
setobj2n(L, &cl->c.upvalue[n], L->top+n);
|
||||
setclvalue(L, L->top, cl);
|
||||
lua_assert(iswhite(obj2gco(cl)));
|
||||
api_incr_top(L);
|
||||
}
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
@ -523,16 +531,10 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
LUA_API void lua_pushrotable (lua_State *L, void *p) {
|
||||
lua_lock(L);
|
||||
setrvalue(L->top, p);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
LUA_API void lua_pushlightfunction(lua_State *L, void *p) {
|
||||
LUA_API void lua_pushrotable (lua_State *L, const ROTable *t) {
|
||||
lua_lock(L);
|
||||
setfvalue(L->top, p);
|
||||
sethvalue(L, L->top, cast(ROTable *,t));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
}
|
||||
@ -553,17 +555,17 @@ LUA_API int lua_pushthread (lua_State *L) {
|
||||
*/
|
||||
|
||||
|
||||
LUA_API void lua_gettable (lua_State *L, int idx) {
|
||||
LUA_API int lua_gettable (lua_State *L, int idx) {
|
||||
StkId t;
|
||||
lua_lock(L);
|
||||
t = index2adr(L, idx);
|
||||
api_checkvalidindex(L, t);
|
||||
luaV_gettable(L, t, L->top - 1, L->top - 1);
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
|
||||
LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
|
||||
StkId t;
|
||||
TValue key;
|
||||
lua_lock(L);
|
||||
@ -575,29 +577,58 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) {
|
||||
luaV_gettable(L, t, &key, L->top);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_rawget (lua_State *L, int idx) {
|
||||
LUA_API int lua_geti (lua_State *L, int idx, int n) {
|
||||
StkId t;
|
||||
const TValue *res;
|
||||
TValue key;
|
||||
lua_lock(L);
|
||||
t = index2adr(L, idx);
|
||||
api_check(L, ttistable(t) || ttisrotable(t));
|
||||
res = ttistable(t) ? luaH_get(hvalue(t), L->top - 1) : luaH_get_ro(rvalue(t), L->top - 1);
|
||||
setobj2s(L, L->top - 1, res);
|
||||
api_checkvalidindex(L, t);
|
||||
fixedstack(L);
|
||||
setnvalue(&key, n);
|
||||
unfixedstack(L);
|
||||
luaV_gettable(L, t, &key, L->top);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
}
|
||||
|
||||
LUA_API int lua_rawget (lua_State *L, int idx) {
|
||||
StkId t;
|
||||
lua_lock(L);
|
||||
t = index2adr(L, idx);
|
||||
api_check(L, ttistable(t));
|
||||
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
|
||||
LUA_API int lua_rawgeti (lua_State *L, int idx, int n) {
|
||||
StkId o;
|
||||
lua_lock(L);
|
||||
o = index2adr(L, idx);
|
||||
api_check(L, ttistable(o) || ttisrotable(o));
|
||||
setobj2s(L, L->top, ttistable(o) ? luaH_getnum(hvalue(o), n) : luaH_getnum_ro(rvalue(o), n))
|
||||
api_check(L, ttistable(o));
|
||||
setobj2s(L, L->top, luaH_getnum(hvalue(o), n));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
|
||||
StkId t;
|
||||
TValue k;
|
||||
lua_lock(L);
|
||||
t = index2adr(L, idx);
|
||||
api_check(L, ttistable(t));
|
||||
setpvalue(&k, cast(void *, p));
|
||||
setobj2s(L, L->top, luaH_get(hvalue(t), &k));
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return ttnov(L->top - 1);
|
||||
}
|
||||
|
||||
|
||||
@ -616,27 +647,21 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
|
||||
int res;
|
||||
lua_lock(L);
|
||||
obj = index2adr(L, objindex);
|
||||
switch (ttype(obj)) {
|
||||
switch (ttnov(obj)) {
|
||||
case LUA_TTABLE:
|
||||
mt = hvalue(obj)->metatable;
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
mt = uvalue(obj)->metatable;
|
||||
break;
|
||||
case LUA_TROTABLE:
|
||||
mt = (Table*)luaR_getmeta(rvalue(obj));
|
||||
break;
|
||||
default:
|
||||
mt = G(L)->mt[ttype(obj)];
|
||||
mt = G(L)->mt[ttnov(obj)];
|
||||
break;
|
||||
}
|
||||
if (mt == NULL)
|
||||
res = 0;
|
||||
else {
|
||||
if(luaR_isrotable(mt))
|
||||
setrvalue(L->top, mt)
|
||||
else
|
||||
sethvalue(L, L->top, mt)
|
||||
sethvalue(L, L->top, mt)
|
||||
api_incr_top(L);
|
||||
res = 1;
|
||||
}
|
||||
@ -730,40 +755,54 @@ LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
|
||||
StkId o;
|
||||
TValue k;
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
o = index2adr(L, idx);
|
||||
api_check(L, ttistable(o));
|
||||
fixedstack(L);
|
||||
setpvalue(&k, cast(void *, p))
|
||||
setobj2t(L, luaH_set(L, hvalue(o), &k), L->top-1);
|
||||
unfixedstack(L);
|
||||
luaC_barriert(L, hvalue(o), L->top-1);
|
||||
L->top--;
|
||||
lua_unlock(L);
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_setmetatable (lua_State *L, int objindex) {
|
||||
TValue *obj;
|
||||
Table *mt;
|
||||
int isrometa = 0;
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
obj = index2adr(L, objindex);
|
||||
api_checkvalidindex(L, obj);
|
||||
if (ttisnil(L->top - 1))
|
||||
if (ttisnil(L->top - 1)) {
|
||||
mt = NULL;
|
||||
else {
|
||||
api_check(L, ttistable(L->top - 1) || ttisrotable(L->top - 1));
|
||||
if (ttistable(L->top - 1))
|
||||
mt = hvalue(L->top - 1);
|
||||
else {
|
||||
mt = (Table*)rvalue(L->top - 1);
|
||||
isrometa = 1;
|
||||
}
|
||||
} else {
|
||||
api_check(L, ttistable(L->top - 1));
|
||||
mt = hvalue(L->top - 1);
|
||||
}
|
||||
switch (ttype(obj)) {
|
||||
switch (ttype(obj)) { /* use basetype to retain subtypes*/
|
||||
case LUA_TTABLE: {
|
||||
hvalue(obj)->metatable = mt;
|
||||
if (mt && !isrometa)
|
||||
if (mt && !isrotable(mt))
|
||||
luaC_objbarriert(L, hvalue(obj), mt);
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA: {
|
||||
uvalue(obj)->metatable = mt;
|
||||
if (mt && !isrometa)
|
||||
if (mt && !isrotable(mt))
|
||||
luaC_objbarrier(L, rawuvalue(obj), mt);
|
||||
break;
|
||||
}
|
||||
case LUA_TISROTABLE: { /* Ignore any changes to a ROTable MT */
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
G(L)->mt[ttype(obj)] = mt;
|
||||
G(L)->mt[ttnov(obj)] = mt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -813,7 +852,7 @@ LUA_API int lua_setfenv (lua_State *L, int idx) {
|
||||
|
||||
#define checkresults(L,na,nr) \
|
||||
api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))
|
||||
|
||||
|
||||
|
||||
LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
|
||||
StkId func;
|
||||
@ -914,14 +953,14 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
|
||||
LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int stripping) {
|
||||
int status;
|
||||
TValue *o;
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
o = L->top - 1;
|
||||
if (isLfunction(o))
|
||||
status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);
|
||||
status = luaU_dump(L, clvalue(o)->l.p, writer, data, stripping);
|
||||
else
|
||||
status = 1;
|
||||
lua_unlock(L);
|
||||
@ -929,6 +968,30 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_stripdebug (lua_State *L, int stripping){
|
||||
TValue *o = L->top - 1;
|
||||
Proto *p = NULL;
|
||||
int res = -1;
|
||||
lua_lock(L);
|
||||
api_checknelems(L, 1);
|
||||
if (isLfunction(o)) {
|
||||
p = clvalue(o)->l.p;
|
||||
if (p && !isLFSobject(p) && (unsigned) stripping < 3 ) {
|
||||
// found a valid proto to strip
|
||||
res = luaG_stripdebug(L, p, stripping, 1);
|
||||
}
|
||||
} else if (ttisnil(L->top - 1)) {
|
||||
// get or set the default strip level
|
||||
if ((unsigned) stripping < 3)
|
||||
G(L)->stripdefault = stripping;
|
||||
res = G(L)->stripdefault;
|
||||
}
|
||||
L->top--;
|
||||
lua_unlock(L);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
LUA_API int lua_status (lua_State *L) {
|
||||
return L->status;
|
||||
}
|
||||
@ -1039,8 +1102,8 @@ LUA_API int lua_next (lua_State *L, int idx) {
|
||||
int more;
|
||||
lua_lock(L);
|
||||
t = index2adr(L, idx);
|
||||
api_check(L, ttistable(t) || ttisrotable(t));
|
||||
more = ttistable(t) ? luaH_next(L, hvalue(t), L->top - 1) : luaH_next_ro(L, rvalue(t), L->top - 1);
|
||||
api_check(L, ttistable(t));
|
||||
more = luaH_next(L, hvalue(t), L->top - 1);
|
||||
if (more) {
|
||||
api_incr_top(L);
|
||||
}
|
||||
@ -1149,3 +1212,15 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
|
||||
return name;
|
||||
}
|
||||
|
||||
LUA_API void lua_setegcmode ( lua_State *L, int mode, int limit) {
|
||||
G(L)->egcmode = mode;
|
||||
G(L)->memlimit = limit;
|
||||
}
|
||||
|
||||
LUA_API void lua_getegcinfo (lua_State *L, int *totals) {
|
||||
if (totals) {
|
||||
totals[0] = G(L)->totalbytes;
|
||||
totals[1] = G(L)->estimate;
|
||||
}
|
||||
}
|
||||
|
@ -4,20 +4,16 @@
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
#include "esp_system.h"
|
||||
#include "vfs.h"
|
||||
/* defined in esp_system_internal.h */
|
||||
void esp_reset_reason_set_hint(esp_reset_reason_t hint);
|
||||
#else
|
||||
#endif
|
||||
|
||||
/* This file uses only the official API of Lua.
|
||||
@ -27,14 +23,14 @@ void esp_reset_reason_set_hint(esp_reset_reason_t hint);
|
||||
#define lauxlib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lrotable.h"
|
||||
#include "lnodemcu.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lgc.h"
|
||||
#include "ldo.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "legc.h"
|
||||
#include "lpanic.h"
|
||||
|
||||
#define FREELIST_REF 0 /* free list of references */
|
||||
|
||||
@ -277,7 +273,7 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
LUALIB_API int luaL_rometatable (lua_State *L, const char* tname, void *p) {
|
||||
LUALIB_API int luaL_rometatable (lua_State *L, const char* tname, const ROTable *p) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
|
||||
if (!lua_isnil(L, -1)) /* name already in use? */
|
||||
return 0; /* leave previous value on top, but return 0 */
|
||||
@ -288,21 +284,25 @@ LUALIB_API int luaL_rometatable (lua_State *L, const char* tname, void *p) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
|
||||
LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
|
||||
void *p = lua_touserdata(L, ud);
|
||||
if (p != NULL) { /* value is a userdata? */
|
||||
if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
|
||||
if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
|
||||
lua_pop(L, 2); /* remove both metatables */
|
||||
return p;
|
||||
}
|
||||
if (!lua_rawequal(L, -1, -2)) /* not the same? */
|
||||
p = NULL; /* value is a userdata with wrong metatable */
|
||||
lua_pop(L, 2); /* remove both metatables */
|
||||
return p;
|
||||
}
|
||||
}
|
||||
luaL_typerror(L, ud, tname); /* else error */
|
||||
return NULL; /* to avoid warnings */
|
||||
return NULL; /* value is not a userdata with a metatable */
|
||||
}
|
||||
|
||||
LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
|
||||
void *p = luaL_testudata(L, ud, tname);
|
||||
if (p == NULL) luaL_typerror(L, ud, tname);
|
||||
return p;
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
|
||||
if (!lua_checkstack(L, space))
|
||||
@ -315,22 +315,6 @@ LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {
|
||||
tag_error(L, narg, t);
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_checkanyfunction (lua_State *L, int narg) {
|
||||
if (lua_type(L, narg) != LUA_TFUNCTION && lua_type(L, narg) != LUA_TLIGHTFUNCTION) {
|
||||
const char *msg = lua_pushfstring(L, "function or lightfunction expected, got %s",
|
||||
luaL_typename(L, narg));
|
||||
luaL_argerror(L, narg, msg);
|
||||
}
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_checkanytable (lua_State *L, int narg) {
|
||||
if (lua_type(L, narg) != LUA_TTABLE && lua_type(L, narg) != LUA_TROTABLE) {
|
||||
const char *msg = lua_pushfstring(L, "table or rotable expected, got %s",
|
||||
luaL_typename(L, narg));
|
||||
luaL_argerror(L, narg, msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void luaL_checkany (lua_State *L, int narg) {
|
||||
if (lua_type(L, narg) == LUA_TNONE)
|
||||
@ -449,7 +433,7 @@ LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
|
||||
for (i=0; i<nup; i++) /* copy upvalues to the top */
|
||||
lua_pushvalue(L, -nup);
|
||||
if (ftype == LUA_USELIGHTFUNCTIONS)
|
||||
lua_pushlightfunction(L, l->func);
|
||||
lua_pushcfunction(L, l->func);
|
||||
else
|
||||
lua_pushcclosure(L, l->func, nup);
|
||||
lua_setfield(L, -(nup+2), l->name);
|
||||
@ -561,7 +545,7 @@ LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, -4); /* set new table into field */
|
||||
}
|
||||
else if (!lua_istable(L, -1) && !lua_isrotable(L, -1)) { /* field has a non-table value? */
|
||||
else if (!lua_istable(L, -1)) { /* field has a non-table value? */
|
||||
lua_pop(L, 2); /* remove table and value */
|
||||
return fname; /* return problematic part of the name */
|
||||
}
|
||||
@ -703,6 +687,26 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref) {
|
||||
int reft;
|
||||
/*
|
||||
* If the ref is positive and the entry in table t exists then
|
||||
* overwrite the value otherwise fall through to luaL_ref()
|
||||
*/
|
||||
if (ref) {
|
||||
if (*ref >= 0) {
|
||||
t = abs_index(L, t);
|
||||
lua_rawgeti(L, t, *ref);
|
||||
reft = lua_type(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (reft != LUA_TNIL) {
|
||||
lua_rawseti(L, t, *ref);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*ref = luaL_ref(L, t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
@ -710,14 +714,33 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
|
||||
typedef struct LoadF {
|
||||
int extraline;
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
FILE *f;
|
||||
#else
|
||||
int f;
|
||||
#endif
|
||||
char buff[LUAL_BUFFERSIZE];
|
||||
} LoadF;
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
# define freopen_bin(f,fn) freopen(f,"rb",fn)
|
||||
# define read_buff(b,f) fread(b, 1, sizeof (b), f)
|
||||
#else
|
||||
# define strerror(n) ""
|
||||
#undef feof
|
||||
# define feof(f) vfs_eof(f)
|
||||
#undef fopen
|
||||
# define fopen(f, m) vfs_open(f, m)
|
||||
# define freopen_bin(fn,f) ((void) vfs_close(f), vfs_open(fn, "r"))
|
||||
#undef getc
|
||||
# define getc(f) vfs_getc(f)
|
||||
#undef ungetc
|
||||
# define ungetc(c,f) vfs_ungetc(c, f)
|
||||
# define read_buff(b,f) vfs_read(f, b, sizeof (b))
|
||||
#endif
|
||||
|
||||
|
||||
static const char *getF (lua_State *L, void *ud, size_t *size) {
|
||||
LoadF *lf = (LoadF *)ud;
|
||||
@ -728,7 +751,7 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {
|
||||
return "\n";
|
||||
}
|
||||
if (feof(lf->f)) return NULL;
|
||||
*size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);
|
||||
*size = read_buff(lf->buff, lf->f);
|
||||
return (*size > 0) ? lf->buff : NULL;
|
||||
}
|
||||
|
||||
@ -748,14 +771,19 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
||||
int c;
|
||||
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
|
||||
lf.extraline = 0;
|
||||
|
||||
if (filename == NULL) {
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
lua_pushliteral(L, "=stdin");
|
||||
lf.f = stdin;
|
||||
#else
|
||||
return luaL_error(L, "filename is NULL");
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
lua_pushfstring(L, "@%s", filename);
|
||||
lf.f = fopen(filename, "r");
|
||||
if (lf.f == NULL) return errfile(L, "open", fnameindex);
|
||||
if (!lf.f) return errfile(L, "open", fnameindex);
|
||||
}
|
||||
c = getc(lf.f);
|
||||
if (c == '#') { /* Unix exec. file? */
|
||||
@ -764,8 +792,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
||||
if (c == '\n') c = getc(lf.f);
|
||||
}
|
||||
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
||||
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
||||
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
|
||||
lf.f = freopen_bin(filename, lf.f); /* reopen in binary mode */
|
||||
if (!lf.f) return errfile(L, "reopen", fnameindex);
|
||||
/* skip eventual `#!...' */
|
||||
while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) {}
|
||||
|
||||
@ -773,95 +801,21 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
|
||||
}
|
||||
ungetc(c, lf.f);
|
||||
status = lua_load(L, getF, &lf, lua_tostring(L, -1));
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
readstatus = ferror(lf.f);
|
||||
if (filename) fclose(lf.f); /* close file (even in case of errors) */
|
||||
if (readstatus) {
|
||||
lua_settop(L, fnameindex); /* ignore results from `lua_load' */
|
||||
return errfile(L, "read", fnameindex);
|
||||
}
|
||||
lua_remove(L, fnameindex);
|
||||
return status;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
typedef struct LoadFSF {
|
||||
int extraline;
|
||||
int f;
|
||||
char buff[LUAL_BUFFERSIZE];
|
||||
} LoadFSF;
|
||||
|
||||
|
||||
static const char *getFSF (lua_State *L, void *ud, size_t *size) {
|
||||
LoadFSF *lf = (LoadFSF *)ud;
|
||||
(void)L;
|
||||
|
||||
if (L == NULL && size == NULL) // Direct mode check
|
||||
return NULL;
|
||||
|
||||
if (lf->extraline) {
|
||||
lf->extraline = 0;
|
||||
*size = 1;
|
||||
return "\n";
|
||||
}
|
||||
|
||||
if (vfs_eof(lf->f)) return NULL;
|
||||
*size = vfs_read(lf->f, lf->buff, sizeof(lf->buff));
|
||||
|
||||
return (*size > 0) ? lf->buff : NULL;
|
||||
}
|
||||
|
||||
|
||||
static int errfsfile (lua_State *L, const char *what, int fnameindex) {
|
||||
const char *filename = lua_tostring(L, fnameindex) + 1;
|
||||
lua_pushfstring(L, "cannot %s %s", what, filename);
|
||||
lua_remove(L, fnameindex);
|
||||
return LUA_ERRFILE;
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
|
||||
LoadFSF lf;
|
||||
int status;
|
||||
int c;
|
||||
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
|
||||
lf.extraline = 0;
|
||||
if (filename == NULL) {
|
||||
return luaL_error(L, "filename is NULL");
|
||||
}
|
||||
else {
|
||||
lua_pushfstring(L, "@%s", filename);
|
||||
lf.f = vfs_open(filename, "r");
|
||||
if (!lf.f) return errfsfile(L, "open", fnameindex);
|
||||
}
|
||||
// if(fs_size(lf.f)>LUAL_BUFFERSIZE)
|
||||
// return luaL_error(L, "file is too big");
|
||||
c = vfs_getc(lf.f);
|
||||
if (c == '#') { /* Unix exec. file? */
|
||||
lf.extraline = 1;
|
||||
while ((c = vfs_getc(lf.f)) != VFS_EOF && c != '\n') ; /* skip first line */
|
||||
if (c == '\n') c = vfs_getc(lf.f);
|
||||
}
|
||||
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
||||
vfs_close(lf.f);
|
||||
lf.f = vfs_open(filename, "r"); /* reopen in binary mode */
|
||||
if (!lf.f) return errfsfile(L, "reopen", fnameindex);
|
||||
/* skip eventual `#!...' */
|
||||
while ((c = vfs_getc(lf.f)) != VFS_EOF && c != LUA_SIGNATURE[0])
|
||||
;
|
||||
lf.extraline = 0;
|
||||
}
|
||||
vfs_ungetc(c, lf.f);
|
||||
status = lua_load(L, getFSF, &lf, lua_tostring(L, -1));
|
||||
|
||||
if (filename) vfs_close(lf.f); /* close file (even in case of errors) */
|
||||
(void) readstatus;
|
||||
if (filename) vfs_close(lf.f); /* close file (even in case of errors) */
|
||||
#endif
|
||||
lua_remove(L, fnameindex);
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct LoadS {
|
||||
const char *s;
|
||||
@ -959,56 +913,11 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
/*
|
||||
* upper 28 bit have magic value 0xD1EC0DE0
|
||||
* if paniclevel is valid (i.e. matches magic value)
|
||||
* lower 4 bits have paniclevel:
|
||||
* 0 = no panic occurred
|
||||
* 1..15 = one..fifteen subsequent panic(s) occurred
|
||||
*/
|
||||
static __NOINIT_ATTR uint32_t l_rtc_panic_val;
|
||||
|
||||
int panic_get_nvval() {
|
||||
if ((l_rtc_panic_val & 0xfffffff0) == 0xD1EC0DE0) {
|
||||
return (l_rtc_panic_val & 0xf);
|
||||
}
|
||||
panic_clear_nvval();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void panic_clear_nvval() {
|
||||
l_rtc_panic_val = 0xD1EC0DE0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int panic (lua_State *L) {
|
||||
(void)L; /* to avoid warnings */
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
uint8_t paniclevel = panic_get_nvval();
|
||||
if (paniclevel < 15) paniclevel++;
|
||||
l_rtc_panic_val = 0xD1EC0DE0 | paniclevel;
|
||||
#endif
|
||||
#if defined(LUA_USE_STDIO)
|
||||
fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
|
||||
lua_tostring(L, -1));
|
||||
#else
|
||||
luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
|
||||
lua_tostring(L, -1));
|
||||
#endif
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
/* call abort() directly - we don't want another reset cause to intervene */
|
||||
esp_reset_reason_set_hint(ESP_RST_PANIC);
|
||||
abort();
|
||||
#endif
|
||||
while (1) {}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LUALIB_API lua_State *luaL_newstate (void) {
|
||||
lua_State *L = lua_newstate(l_alloc, NULL);
|
||||
lua_setallocf(L, l_alloc, L); /* allocator need lua_State. */
|
||||
if (L) lua_atpanic(L, &panic);
|
||||
if (L) lua_atpanic(L, lpanic);
|
||||
return L;
|
||||
}
|
||||
|
@ -8,12 +8,13 @@
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include "lua.h"
|
||||
#ifdef LUA_LIB
|
||||
#include "lnodemcu.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#if defined(LUA_COMPAT_GETN)
|
||||
LUALIB_API int (luaL_getn) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_setn) (lua_State *L, int t, int n);
|
||||
@ -43,7 +44,7 @@ LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,
|
||||
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l);
|
||||
LUALIB_API void (luaL_register_light) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l);
|
||||
const luaL_Reg *l);
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
|
||||
@ -62,11 +63,10 @@ LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
|
||||
LUALIB_API void (luaL_checkanyfunction) (lua_State *L, int narg);
|
||||
LUALIB_API void (luaL_checkanytable) (lua_State *L, int narg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API int (luaL_rometatable) (lua_State *L, const char* tname, void *p);
|
||||
LUALIB_API int (luaL_rometatable) (lua_State *L, const char* tname, const ROTable *p);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
@ -77,12 +77,11 @@ LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
#define luaL_unref2(l,t,r) do {luaL_unref(L, (t), (r)); r = LUA_NOREF;} while (0)
|
||||
LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref);
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
|
||||
#else
|
||||
LUALIB_API int (luaL_loadfsfile) (lua_State *L, const char *filename);
|
||||
#endif
|
||||
|
||||
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
@ -112,7 +111,12 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message)
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
#define luaL_optunsigned(L,a,d) ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
|
||||
#define luaL_checktable(L,n) luaL_checktype(L, (n), LUA_TTABLE);
|
||||
#define luaL_checkfunction(L,n) luaL_checktype(L, (n), LUA_TFUNCTION);
|
||||
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
@ -121,7 +125,7 @@ LUALIB_API void luaL_assertfail(const char *file, int line, const char *message)
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
#else
|
||||
#define luaL_dofile(L, fn) \
|
||||
(luaL_loadfsfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
#endif
|
||||
|
||||
#define luaL_dostring(L, s) \
|
||||
@ -165,6 +169,18 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
LUALIB_API int (luaL_pushlfsmodules) (lua_State *L);
|
||||
LUALIB_API int (luaL_pushlfsmodule) (lua_State *L);
|
||||
LUALIB_API int (luaL_pushlfsdts) (lua_State *L);
|
||||
|
||||
LUALIB_API void (luaL_lfsreload) (lua_State *L);
|
||||
LUALIB_API int (luaL_pcallx) (lua_State *L, int narg, int nres);
|
||||
LUALIB_API int (luaL_posttask) ( lua_State* L, int prio );
|
||||
#define LUA_TASK_LOW 0
|
||||
#define LUA_TASK_MEDIUM 1
|
||||
#define LUA_TASK_HIGH 2
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
/* compatibility with ref system */
|
||||
|
||||
@ -184,7 +200,3 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
int panic_get_nvval();
|
||||
void panic_clear_nvval();
|
||||
#endif
|
@ -8,17 +8,14 @@
|
||||
|
||||
#define lbaselib_c
|
||||
#define LUA_LIB
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
@ -27,6 +24,10 @@
|
||||
** model but changing `fputs' to put the strings at a proper place
|
||||
** (a console window or a log file, for instance).
|
||||
*/
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
#undef puts
|
||||
#define puts(s) printf("%s",s)
|
||||
#endif
|
||||
static int luaB_print (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int i;
|
||||
@ -40,20 +41,11 @@ static int luaB_print (lua_State *L) {
|
||||
if (s == NULL)
|
||||
return luaL_error(L, LUA_QL("tostring") " must return a string to "
|
||||
LUA_QL("print"));
|
||||
#if defined(LUA_USE_STDIO)
|
||||
if (i>1) fputs("\t", stdout);
|
||||
fputs(s, stdout);
|
||||
#else
|
||||
if (i>1) luai_writestring("\t", 1);
|
||||
luai_writestring(s, strlen(s));
|
||||
#endif
|
||||
if (i>1) puts("\t");
|
||||
puts(s);
|
||||
lua_pop(L, 1); /* pop result */
|
||||
}
|
||||
#if defined(LUA_USE_STDIO)
|
||||
fputs("\n", stdout);
|
||||
#else
|
||||
luai_writeline();
|
||||
#endif
|
||||
puts("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -112,7 +104,7 @@ static int luaB_getmetatable (lua_State *L) {
|
||||
static int luaB_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE || t == LUA_TROTABLE, 2,
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
"nil or table expected");
|
||||
if (luaL_getmetafield(L, 1, "__metatable"))
|
||||
luaL_error(L, "cannot change a protected metatable");
|
||||
@ -175,7 +167,7 @@ static int luaB_rawequal (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_rawget (lua_State *L) {
|
||||
luaL_checkanytable(L, 1);
|
||||
luaL_checktable(L, 1);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_rawget(L, 1);
|
||||
@ -183,7 +175,7 @@ static int luaB_rawget (lua_State *L) {
|
||||
}
|
||||
|
||||
static int luaB_rawset (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checktable(L, 1);
|
||||
luaL_checkany(L, 2);
|
||||
luaL_checkany(L, 3);
|
||||
lua_settop(L, 3);
|
||||
@ -233,7 +225,7 @@ static int luaB_type (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_next (lua_State *L) {
|
||||
luaL_checkanytable(L, 1);
|
||||
luaL_checktable(L, 1);
|
||||
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
|
||||
if (lua_next(L, 1))
|
||||
return 2;
|
||||
@ -245,7 +237,7 @@ static int luaB_next (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_pairs (lua_State *L) {
|
||||
luaL_checkanytable(L, 1);
|
||||
luaL_checktable(L, 1);
|
||||
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
lua_pushnil(L); /* and initial value */
|
||||
@ -255,7 +247,7 @@ static int luaB_pairs (lua_State *L) {
|
||||
|
||||
static int ipairsaux (lua_State *L) {
|
||||
int i = luaL_checkint(L, 2);
|
||||
luaL_checkanytable(L, 1);
|
||||
luaL_checktable(L, 1);
|
||||
i++; /* next value */
|
||||
lua_pushinteger(L, i);
|
||||
lua_rawgeti(L, 1, i);
|
||||
@ -264,7 +256,7 @@ static int ipairsaux (lua_State *L) {
|
||||
|
||||
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
luaL_checkanytable(L, 1);
|
||||
luaL_checktable(L, 1);
|
||||
lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
lua_pushinteger(L, 0); /* and initial value */
|
||||
@ -296,7 +288,7 @@ static int luaB_loadfile (lua_State *L) {
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
return load_aux(L, luaL_loadfile(L, fname));
|
||||
#else
|
||||
return load_aux(L, luaL_loadfsfile(L, fname));
|
||||
return load_aux(L, luaL_loadfile(L, fname));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -343,7 +335,7 @@ static int luaB_dofile (lua_State *L) {
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
if (luaL_loadfile(L, fname) != 0) lua_error(L);
|
||||
#else
|
||||
if (luaL_loadfsfile(L, fname) != 0) lua_error(L);
|
||||
if (luaL_loadfile(L, fname) != 0) lua_error(L);
|
||||
#endif
|
||||
lua_call(L, 0, LUA_MULTRET);
|
||||
return lua_gettop(L) - n;
|
||||
@ -462,29 +454,24 @@ static int luaB_newproxy (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include "lrotable.h"
|
||||
|
||||
LROT_EXTERN(lua_rotable_base);
|
||||
|
||||
/*
|
||||
* Separate ROTables are used for the base functions and library ROTables, with
|
||||
* the base functions ROTable declared below. The library ROTable is chained
|
||||
* from this using its __index meta-method.
|
||||
*
|
||||
* ESP builds use specific linker directives to marshal all the ROTable entries
|
||||
* for the library modules into a single ROTable in the PSECT ".lua_rotable".
|
||||
* This is not practical on Posix builds using a standard GNU link, so the
|
||||
* equivalent ROTable for the core libraries defined in linit.c for the cross-
|
||||
* compiler build.
|
||||
*/
|
||||
|
||||
LROT_EXTERN(lua_rotables);
|
||||
|
||||
LROT_PUBLIC_BEGIN(base_func_meta)
|
||||
LROT_TABENTRY( __index, lua_rotables )
|
||||
LROT_END(base_func, base_func_meta, LROT_MASK_INDEX)
|
||||
|
||||
LROT_PUBLIC_BEGIN(base_func)
|
||||
** ESP builds use specific linker directives to marshal all the ROTable entries
|
||||
** for the library modules including the base library into an entry vector in
|
||||
** the PSECT ".lua_rotable" including the base library entries; this is bound
|
||||
** into a ROTable in linit.c which then hooked into the __index metaentry for
|
||||
** _G so that base library and ROM tables are directly resolved through _G.
|
||||
**
|
||||
** The host-based luac.cross builds which must use a standard GNU link or
|
||||
** MSVC so this linker-specfic assembly approach can't be used. In this case
|
||||
** luaopen_base returns a base_func ROTable so a two cascade resolution. See
|
||||
** description in init.c for further details.
|
||||
*/
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
LROT_BEGIN(base_func, NULL, 0)
|
||||
#else
|
||||
LROT_ENTRIES_IN_SECTION(base_func, rotable)
|
||||
#endif
|
||||
LROT_FUNCENTRY(assert, luaB_assert)
|
||||
LROT_FUNCENTRY(collectgarbage, luaB_collectgarbage)
|
||||
LROT_FUNCENTRY(dofile, luaB_dofile)
|
||||
@ -509,13 +496,11 @@ LROT_PUBLIC_BEGIN(base_func)
|
||||
LROT_FUNCENTRY(type, luaB_type)
|
||||
LROT_FUNCENTRY(unpack, luaB_unpack)
|
||||
LROT_FUNCENTRY(xpcall, luaB_xpcall)
|
||||
LROT_TABENTRY(__metatable, base_func_meta)
|
||||
LROT_END(base_func, base_func_meta, LROT_MASK_INDEX)
|
||||
|
||||
LROT_BEGIN(G_meta)
|
||||
LROT_TABENTRY( __index, base_func )
|
||||
LROT_END(G_meta, NULL, 0)
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
LROT_END(base_func, NULL, 0)
|
||||
#else
|
||||
LROT_BREAK(base_func)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
@ -645,14 +630,14 @@ static int luaB_corunning (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
LROT_PUBLIC_BEGIN(co_funcs)
|
||||
LROT_BEGIN(co_funcs, NULL, 0)
|
||||
LROT_FUNCENTRY( create, luaB_cocreate )
|
||||
LROT_FUNCENTRY( resume, luaB_coresume )
|
||||
LROT_FUNCENTRY( running, luaB_corunning )
|
||||
LROT_FUNCENTRY( status, luaB_costatus )
|
||||
LROT_FUNCENTRY( wrap, luaB_cowrap )
|
||||
LROT_FUNCENTRY( yield, luaB_yield )
|
||||
LROT_END (co_funcs, NULL, 0)
|
||||
LROT_END(co_funcs, NULL, 0)
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
@ -661,19 +646,13 @@ static void auxopen (lua_State *L, const char *name,
|
||||
lua_CFunction f, lua_CFunction u) {
|
||||
lua_pushcfunction(L, u);
|
||||
lua_pushcclosure(L, f, 1);
|
||||
lua_setfield(L, -2, name);
|
||||
lua_setglobal(L, name);
|
||||
}
|
||||
|
||||
static void base_open (lua_State *L) {
|
||||
/* set global _G */
|
||||
extern LROT_TABLE(rotables);
|
||||
LUALIB_API int luaopen_base (lua_State *L) {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
lua_setglobal(L, "_G");
|
||||
|
||||
/* open lib into global table */
|
||||
luaL_register_light(L, "_G", &((luaL_Reg) {0}));
|
||||
lua_pushrotable(L, LROT_TABLEREF(G_meta));
|
||||
lua_setmetatable(L, LUA_GLOBALSINDEX);
|
||||
|
||||
lua_settable(L, LUA_GLOBALSINDEX); /* set global _G */
|
||||
lua_pushliteral(L, LUA_VERSION);
|
||||
lua_setglobal(L, "_VERSION"); /* set global _VERSION */
|
||||
/* `ipairs' and `pairs' need auxliliary functions as upvalues */
|
||||
@ -681,16 +660,15 @@ static void base_open (lua_State *L) {
|
||||
auxopen(L, "pairs", luaB_pairs, luaB_next);
|
||||
/* `newproxy' needs a weaktable as upvalue */
|
||||
lua_createtable(L, 0, 1); /* new table `w' */
|
||||
lua_pushvalue(L, -1); /* `w' will be its own metatable */
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushliteral(L, "kv");
|
||||
lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */
|
||||
lua_pushcclosure(L, luaB_newproxy, 1);
|
||||
lua_pushvalue(L, -1); /* `w' will be its own metatable */
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushcclosure(L, luaB_newproxy, 1); /* Upval is table w */
|
||||
lua_setglobal(L, "newproxy"); /* set global `newproxy' */
|
||||
}
|
||||
|
||||
|
||||
LUALIB_API int luaopen_base (lua_State *L) {
|
||||
base_open(L);
|
||||
return 1;
|
||||
lua_pushrotable(L, LROT_TABLEREF(rotables));
|
||||
lua_setglobal(L, "__index");
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX); /* _G is its own metatable */
|
||||
lua_setmetatable(L, LUA_GLOBALSINDEX);
|
||||
return 0;
|
||||
}
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lcode_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdlib.h>
|
||||
@ -781,8 +780,6 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
|
||||
/*
|
||||
* Attempted to write to last (null terminator) byte of lineinfo, so need
|
||||
* to grow the lineinfo vector and extend the fill bytes
|
||||
@ -829,10 +826,8 @@ static void generateInfoDeltaLine(FuncState *fs, int line) {
|
||||
fs->lastlineOffset = p - fs->f->packedlineinfo - 1;
|
||||
#undef addDLbyte
|
||||
}
|
||||
#endif
|
||||
|
||||
void luaK_fixline (FuncState *fs, int line) {
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
/* The fixup line can be the same as existing one and in this case there's nothing to do */
|
||||
if (line != fs->lastline) {
|
||||
/* first remove the current line reference */
|
||||
@ -863,9 +858,6 @@ void luaK_fixline (FuncState *fs, int line) {
|
||||
/* Then add the new line reference */
|
||||
generateInfoDeltaLine(fs, line);
|
||||
}
|
||||
#else
|
||||
fs->f->lineinfo[fs->pc - 1] = line;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -877,7 +869,6 @@ static int luaK_code (FuncState *fs, Instruction i, int line) {
|
||||
MAX_INT, "code size overflow");
|
||||
f->code[fs->pc] = i;
|
||||
/* save corresponding line information */
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
/* note that frst time fs->lastline==0 through, so the else branch is taken */
|
||||
if (fs->pc == fs->lineinfoLastPC+1) {
|
||||
if (line == fs->lastline && f->packedlineinfo[fs->lastlineOffset] < INFO_MAX_LINECNT) {
|
||||
@ -891,11 +882,6 @@ static int luaK_code (FuncState *fs, Instruction i, int line) {
|
||||
luaK_fixline(fs,line);
|
||||
}
|
||||
fs->lineinfoLastPC = fs->pc;
|
||||
#else
|
||||
luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
|
||||
MAX_INT, "code size overflow");
|
||||
f->lineinfo[fs->pc] = line;
|
||||
#endif
|
||||
return fs->pc++;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define ldblib_c
|
||||
#define LUA_LIB
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdio.h>
|
||||
@ -18,8 +17,6 @@
|
||||
#include "lualib.h"
|
||||
#include "lstring.h"
|
||||
#include "lflash.h"
|
||||
#include "lrotable.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
static int db_getregistry (lua_State *L) {
|
||||
@ -28,34 +25,16 @@ static int db_getregistry (lua_State *L) {
|
||||
}
|
||||
|
||||
static int db_getstrings (lua_State *L) {
|
||||
size_t i,n=0;
|
||||
stringtable *tb;
|
||||
GCObject *o;
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
const char *opt = lua_tolstring (L, 1, &n);
|
||||
if (n==3 && memcmp(opt, "ROM", 4) == 0) {
|
||||
if (G(L)->ROstrt.hash == NULL)
|
||||
return 0;
|
||||
tb = &G(L)->ROstrt;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
tb = &G(L)->strt;
|
||||
lua_settop(L, 0);
|
||||
lua_createtable(L, tb->nuse, 0); /* create table the same size as the strt */
|
||||
for (i=0, n=1; i<tb->size; i++) {
|
||||
for(o = tb->hash[i]; o; o=o->gch.next) {
|
||||
TString *ts =cast(TString *, o);
|
||||
lua_pushnil(L);
|
||||
setsvalue2s(L, L->top-1, ts);
|
||||
lua_rawseti(L, -2, n++); /* enumerate the strt, adding elements */
|
||||
static const char *const opts[] = {"RAM","ROM",NULL};
|
||||
int opt = luaL_checkoption(L, 1, "RAM", opts);
|
||||
if (lua_pushstringsarray(L, opt)) {
|
||||
if(lua_getglobal(L, "table") == LUA_TTABLE) {
|
||||
lua_getfield(L, -1, "sort"); /* look up table.sort function */
|
||||
lua_replace(L, -2); /* dump the table table */
|
||||
lua_pushvalue(L, -2); /* duplicate the strt_copy ref */
|
||||
lua_call(L, 1, 0); /* table.sort(strt_copy) */
|
||||
}
|
||||
}
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "table");
|
||||
lua_getfield(L, -1, "sort"); /* look up table.sort function */
|
||||
lua_replace(L, -2); /* dump the table table */
|
||||
lua_pushvalue(L, -2); /* duplicate the strt_copy ref */
|
||||
lua_call(L, 1, 0); /* table.sort(strt_copy) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -144,7 +123,7 @@ static int db_getinfo (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (lua_isfunction(L, arg+1) || lua_islightfunction(L, arg+1)) {
|
||||
else if (lua_isfunction(L, arg+1)) {
|
||||
lua_pushfstring(L, ">%s", options);
|
||||
options = lua_tostring(L, -1);
|
||||
lua_pushvalue(L, arg+1);
|
||||
@ -302,7 +281,7 @@ static int db_sethook (lua_State *L) {
|
||||
}
|
||||
else {
|
||||
const char *smask = luaL_checkstring(L, arg+2);
|
||||
luaL_checkanyfunction(L, arg+1);
|
||||
luaL_checkfunction(L, arg+1);
|
||||
count = luaL_optint(L, arg+3, 0);
|
||||
func = hookf; mask = makemask(smask, count);
|
||||
}
|
||||
@ -367,7 +346,7 @@ static int db_debug (lua_State *L) {
|
||||
#define LEVELS1 12 /* size of the first part of the stack */
|
||||
#define LEVELS2 10 /* size of the second part of the stack */
|
||||
|
||||
static int db_errorfb (lua_State *L) {
|
||||
static int debug_errorfb (lua_State *L) {
|
||||
int level;
|
||||
int firstpart = 1; /* still before eventual `...' */
|
||||
int arg;
|
||||
@ -419,7 +398,7 @@ static int db_errorfb (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
LROT_PUBLIC_BEGIN(dblib)
|
||||
LROT_BEGIN(dblib, NULL, 0)
|
||||
#ifndef CONFIG_LUA_BUILTIN_DEBUG_MINIMAL
|
||||
#if defined(LUA_CROSS_COMPILER)
|
||||
LROT_FUNCENTRY( debug, db_debug )
|
||||
@ -440,7 +419,7 @@ LROT_PUBLIC_BEGIN(dblib)
|
||||
LROT_FUNCENTRY( setmetatable, db_setmetatable )
|
||||
LROT_FUNCENTRY( setupvalue, db_setupvalue )
|
||||
#endif
|
||||
LROT_FUNCENTRY( traceback, db_errorfb )
|
||||
LROT_FUNCENTRY( traceback, debug_errorfb )
|
||||
LROT_END(dblib, NULL, 0)
|
||||
|
||||
LUALIB_API int luaopen_debug (lua_State *L) {
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define ldebug_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -183,8 +182,7 @@ static void info_tailcall (lua_Debug *ar) {
|
||||
# define INFO_DELTA_7BITS 0x7F
|
||||
# define INFO_MAX_LINECNT 126
|
||||
|
||||
Table *t = luaH_new(L, 0, 0);
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
Table *t = luaH_new(L, 0, 0);
|
||||
int line = 0;
|
||||
unsigned char *p = f->l.p->packedlineinfo;
|
||||
if (p) {
|
||||
@ -204,18 +202,11 @@ static void info_tailcall (lua_Debug *ar) {
|
||||
setbvalue(luaH_setnum(L, t, line), 1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
int *lineinfo = f->l.p->lineinfo;
|
||||
int i;
|
||||
for (i=0; i<f->l.p->sizelineinfo; i++)
|
||||
setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
|
||||
#endif
|
||||
sethvalue(L, L->top, t);
|
||||
sethvalue(L, L->top, t);
|
||||
}
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
/*
|
||||
* This may seem expensive but this is only accessed frequently in traceexec
|
||||
* and the while loop will be executed roughly half the number of non-blank
|
||||
@ -250,19 +241,18 @@ int luaG_getline (const Proto *f, int pc) {
|
||||
|
||||
static int stripdebug (lua_State *L, Proto *f, int level) {
|
||||
int len = 0, sizepackedlineinfo;
|
||||
TString* dummy;
|
||||
switch (level) {
|
||||
case 3:
|
||||
sizepackedlineinfo = strlen(cast(char *, f->packedlineinfo))+1;
|
||||
f->packedlineinfo = luaM_freearray(L, f->packedlineinfo, sizepackedlineinfo, unsigned char);
|
||||
len += sizepackedlineinfo;
|
||||
// fall-through
|
||||
case 2:
|
||||
len += f->sizelocvars * (sizeof(struct LocVar) + sizeof(dummy->tsv) + sizeof(struct LocVar *));
|
||||
if (f->packedlineinfo) {
|
||||
sizepackedlineinfo = strlen(cast(char *, f->packedlineinfo))+1;
|
||||
f->packedlineinfo = luaM_freearray(L, f->packedlineinfo, sizepackedlineinfo, unsigned char);
|
||||
len += sizepackedlineinfo;
|
||||
}
|
||||
// fall-through
|
||||
case 1:
|
||||
f->locvars = luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
|
||||
f->upvalues = luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
|
||||
len += f->sizelocvars * (sizeof(struct LocVar) + sizeof(dummy->tsv) + sizeof(struct LocVar *)) +
|
||||
f->sizeupvalues * (sizeof(dummy->tsv) + sizeof(TString *));
|
||||
len += f->sizelocvars*sizeof(struct LocVar) + f->sizeupvalues*sizeof(TString *);
|
||||
f->sizelocvars = 0;
|
||||
f->sizeupvalues = 0;
|
||||
}
|
||||
@ -278,7 +268,6 @@ LUA_API int luaG_stripdebug (lua_State *L, Proto *f, int level, int recv){
|
||||
len += stripdebug (L, f, level);
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
|
||||
@ -328,21 +317,21 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||
lua_lock(L);
|
||||
if (*what == '>') {
|
||||
StkId func = L->top - 1;
|
||||
luai_apicheck(L, ttisfunction(func) || ttislightfunction(func));
|
||||
luai_apicheck(L, ttisfunction(func));
|
||||
what++; /* skip the '>' */
|
||||
if (ttisfunction(func))
|
||||
f = clvalue(func);
|
||||
else
|
||||
if (ttislightfunction(func))
|
||||
plight = fvalue(func);
|
||||
else
|
||||
f = clvalue(func);
|
||||
L->top--; /* pop function */
|
||||
}
|
||||
else if (ar->i_ci != 0) { /* no tail call? */
|
||||
ci = L->base_ci + ar->i_ci;
|
||||
lua_assert(ttisfunction(ci->func) || ttislightfunction(ci->func));
|
||||
if (ttisfunction(ci->func))
|
||||
f = clvalue(ci->func);
|
||||
else
|
||||
lua_assert(ttisfunction(ci->func));
|
||||
if (ttislightfunction(ci->func))
|
||||
plight = fvalue(ci->func);
|
||||
else
|
||||
f = clvalue(ci->func);
|
||||
}
|
||||
status = auxgetinfo(L, what, ar, f, plight, ci);
|
||||
if (strchr(what, 'f')) {
|
||||
@ -381,9 +370,6 @@ static int precheck (const Proto *pt) {
|
||||
check(!(pt->is_vararg & VARARG_NEEDSARG) ||
|
||||
(pt->is_vararg & VARARG_HASARG));
|
||||
check(pt->sizeupvalues <= pt->nups);
|
||||
#ifndef LUA_OPTIMIZE_DEBUG
|
||||
check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);
|
||||
#endif
|
||||
check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);
|
||||
return 1;
|
||||
}
|
||||
@ -670,7 +656,7 @@ static int isinstack (CallInfo *ci, const TValue *o) {
|
||||
|
||||
void luaG_typeerror (lua_State *L, const TValue *o, const char *op) {
|
||||
const char *name = NULL;
|
||||
const char *t = luaT_typenames[ttype(o)];
|
||||
const char *t = luaT_typenames[ttnov(o)];
|
||||
const char *kind = (isinstack(L->ci, o)) ?
|
||||
getobjname(L, L->ci, cast_int(o - L->base), &name) :
|
||||
NULL;
|
||||
@ -698,8 +684,8 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
|
||||
|
||||
int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {
|
||||
const char *t1 = luaT_typenames[ttype(p1)];
|
||||
const char *t2 = luaT_typenames[ttype(p2)];
|
||||
const char *t1 = luaT_typenames[ttnov(p1)];
|
||||
const char *t2 = luaT_typenames[ttnov(p2)];
|
||||
if (t1[2] == t2[2])
|
||||
luaG_runerror(L, "attempt to compare two %s values", t1);
|
||||
else
|
||||
@ -722,7 +708,7 @@ static void addinfo (lua_State *L, const char *msg) {
|
||||
void luaG_errormsg (lua_State *L) {
|
||||
if (L->errfunc != 0) { /* is there an error handling function? */
|
||||
StkId errfunc = restorestack(L, L->errfunc);
|
||||
if (!ttisfunction(errfunc) && !ttislightfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
|
||||
if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);
|
||||
setobjs2s(L, L->top, L->top - 1); /* move argument */
|
||||
setobjs2s(L, L->top - 1, errfunc); /* push function */
|
||||
incr_top(L);
|
@ -13,7 +13,6 @@
|
||||
|
||||
#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1)
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
# include "lvm.h"
|
||||
# define getline(f,pc) (((f)->packedlineinfo) ? luaG_getline((f), pc) : 0)
|
||||
# define INFO_FILL_BYTE 0x7F
|
||||
@ -23,9 +22,6 @@
|
||||
# define INFO_DELTA_7BITS 0x7F
|
||||
# define INFO_MAX_LINECNT 126
|
||||
# define lineInfoTop(fs) ((fs)->f->packedlineinfo + (fs)->lastlineOffset)
|
||||
#else
|
||||
# define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0)
|
||||
#endif
|
||||
|
||||
#define resethookcount(L) (L->hookcount = L->basehookcount)
|
||||
|
||||
@ -41,9 +37,7 @@ LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);
|
||||
LUAI_FUNC void luaG_errormsg (lua_State *L);
|
||||
LUAI_FUNC int luaG_checkcode (const Proto *pt);
|
||||
LUAI_FUNC int luaG_checkopenop (Instruction i);
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
LUAI_FUNC int luaG_getline (const Proto *f, int pc);
|
||||
LUAI_FUNC int luaG_stripdebug (lua_State *L, Proto *f, int level, int recv);
|
||||
#endif
|
||||
|
||||
#endif
|
@ -8,7 +8,6 @@
|
||||
|
||||
#define ldo_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -106,7 +105,7 @@ void luaD_throw (lua_State *L, int errcode) {
|
||||
lua_unlock(L);
|
||||
G(L)->panic(L);
|
||||
}
|
||||
// exit(EXIT_FAILURE);
|
||||
// c_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,13 +253,13 @@ static StkId adjust_varargs (lua_State *L, Proto *p, int actual) {
|
||||
return base;
|
||||
}
|
||||
|
||||
|
||||
static StkId tryfuncTM (lua_State *L, StkId func) {
|
||||
const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);
|
||||
StkId p;
|
||||
ptrdiff_t funcr = savestack(L, func);
|
||||
if (!ttisfunction(tm))
|
||||
if (!ttisfunction(tm)) {
|
||||
luaG_typeerror(L, func, "call");
|
||||
}
|
||||
/* Open a hole inside the stack at `func' */
|
||||
for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);
|
||||
incr_top(L);
|
||||
@ -279,10 +278,10 @@ static StkId tryfuncTM (lua_State *L, StkId func) {
|
||||
int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
ptrdiff_t funcr;
|
||||
LClosure *cl = NULL;
|
||||
if (!ttisfunction(func) && !ttislightfunction(func)) /* `func' is not a function? */
|
||||
if (!ttisfunction(func)) /* `func' is not a function? */
|
||||
func = tryfuncTM(L, func); /* check the `function' tag method */
|
||||
funcr = savestack(L, func);
|
||||
if (ttisfunction(func))
|
||||
if (!ttislightfunction(func))
|
||||
cl = &clvalue(func)->l;
|
||||
L->ci->savedpc = L->savedpc;
|
||||
if (cl && !cl->isC) { /* Lua function? prepare its call */
|
||||
@ -332,10 +331,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) {
|
||||
if (L->hookmask & LUA_MASKCALL)
|
||||
luaD_callhook(L, LUA_HOOKCALL, -1);
|
||||
lua_unlock(L);
|
||||
if (ttisfunction(ci->func))
|
||||
n = (*curr_func(L)->c.f)(L); /* do the actual call */
|
||||
else
|
||||
if (ttislightfunction(ci->func))
|
||||
n = ((lua_CFunction)fvalue(ci->func))(L); /* do the actual call */
|
||||
else
|
||||
n = (*curr_func(L)->c.f)(L); /* do the actual call */
|
||||
lua_lock(L);
|
||||
if (n < 0) /* yielding? */
|
||||
return PCRYIELD;
|
||||
@ -384,7 +383,7 @@ int luaD_poscall (lua_State *L, StkId firstResult) {
|
||||
** The arguments are on the stack, right after the function.
|
||||
** When returns, all the results are on the stack, starting at the original
|
||||
** function position.
|
||||
*/
|
||||
*/
|
||||
void luaD_call (lua_State *L, StkId func, int nResults) {
|
||||
if (++L->nCcalls >= LUAI_MAXCCALLS) {
|
||||
if (L->nCcalls == LUAI_MAXCCALLS)
|
@ -6,7 +6,6 @@
|
||||
|
||||
#define ldump_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -229,7 +228,6 @@ static void DumpDebug(const Proto* f, DumpState* D)
|
||||
{
|
||||
int i,n;
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
n = (D->strip || f->packedlineinfo == NULL) ? 0: strlen(cast(char *,f->packedlineinfo))+1;
|
||||
DumpInt(n,D);
|
||||
Align4(D);
|
||||
@ -237,15 +235,6 @@ static void DumpDebug(const Proto* f, DumpState* D)
|
||||
{
|
||||
DumpBlock(f->packedlineinfo, n, D);
|
||||
}
|
||||
#else
|
||||
n= (D->strip) ? 0 : f->sizelineinfo;
|
||||
DumpInt(n,D);
|
||||
Align4(D);
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
DumpInt(f->lineinfo[i],D);
|
||||
}
|
||||
#endif
|
||||
|
||||
n= (D->strip) ? 0 : f->sizelocvars;
|
||||
DumpInt(n,D);
|
@ -5,7 +5,6 @@
|
||||
|
||||
#define lflash_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
#include "lua.h"
|
||||
|
||||
#include "lobject.h"
|
||||
@ -24,6 +23,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lfs.h"
|
||||
|
||||
/*
|
||||
* Flash memory is a fixed memory addressable block that is serially allocated by the
|
||||
* luac build process and the out image can be downloaded into SPIFSS and loaded into
|
||||
@ -72,7 +73,7 @@ struct OUTPUT {
|
||||
outBlock buffer;
|
||||
int ndx;
|
||||
uint32_t crc;
|
||||
int (*fullBlkCB) (void);
|
||||
void (*fullBlkCB) (void);
|
||||
int flashLen;
|
||||
int flagsLen;
|
||||
int flagsNdx;
|
||||
@ -80,12 +81,6 @@ struct OUTPUT {
|
||||
const char *error;
|
||||
} *out;
|
||||
|
||||
|
||||
#ifdef CONFIG_NODEMCU_EMBEDDED_LFS_SIZE
|
||||
extern const char lua_flash_store_reserved[0];
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef NODE_DEBUG
|
||||
extern void printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void dumpStrt(stringtable *tb, const char *type) {
|
||||
@ -97,9 +92,8 @@ void dumpStrt(stringtable *tb, const char *type) {
|
||||
for (i=0; i<tb->size; i++)
|
||||
for(o = tb->hash[i], j=0; o; (o=o->gch.next), j++ ) {
|
||||
TString *ts =cast(TString *, o);
|
||||
NODE_DBG("%5d %5d %08x %08x %5d %1s %s\n",
|
||||
i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len,
|
||||
ts_isreadonly(ts) ? "R" : " ", getstr(ts));
|
||||
NODE_DBG("%5d %5d %08x %08x %5d %s\n",
|
||||
i, j, (size_t) ts, ts->tsv.hash, ts->tsv.len, getstr(ts));
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,17 +111,25 @@ LUA_API void dumpStrings(lua_State *L) {
|
||||
* writes are suppressed if the global writeToFlash is false. This is used in
|
||||
* phase I where the pass is used to size the structures in flash.
|
||||
*/
|
||||
static void flashSetPosition(uint32_t offset){
|
||||
NODE_DBG("flashSetPosition(%04x)\n", offset);
|
||||
curOffset = offset;
|
||||
static const char *flashPosition(void){
|
||||
return flashAddr + curOffset;
|
||||
}
|
||||
|
||||
|
||||
static void flashBlock(const void* b, size_t size) {
|
||||
NODE_DBG("flashBlock((%04x),%08x,%04x)\n", curOffset,(unsigned int)b,size);
|
||||
static const char *flashSetPosition(uint32_t offset){
|
||||
NODE_DBG("flashSetPosition(%04x)\n", offset);
|
||||
curOffset = offset;
|
||||
return flashPosition();
|
||||
}
|
||||
|
||||
|
||||
static const char *flashBlock(const void* b, size_t size) {
|
||||
const void *cur = flashPosition();
|
||||
NODE_DBG("flashBlock((%04x),%p,%04x)\n", curOffset,b,size);
|
||||
lua_assert(ALIGN_BITS(b) == 0 && ALIGN_BITS(size) == 0);
|
||||
platform_flash_write(b, flashAddrPhys+curOffset, size);
|
||||
curOffset += size;
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
@ -142,11 +144,11 @@ static void flashErase(uint32_t start, uint32_t end){
|
||||
|
||||
static int loadLFS (lua_State *L);
|
||||
static int loadLFSgc (lua_State *L);
|
||||
static int procFirstPass (void);
|
||||
static void procFirstPass (void);
|
||||
#endif
|
||||
|
||||
/* =====================================================================================
|
||||
* luaN_init(), luaN_reload_reboot() and luaN_index() are exported via lflash.h.
|
||||
* luaN_init() is exported via lflash.h.
|
||||
* The first is the startup hook used in lstate.c and the last two are
|
||||
* implementations of the node.flash API calls.
|
||||
*/
|
||||
@ -155,40 +157,15 @@ static int procFirstPass (void);
|
||||
* Hook in lstate.c:f_luaopen() to set up ROstrt and ROpvmain if needed
|
||||
*/
|
||||
LUAI_FUNC void luaN_init (lua_State *L) {
|
||||
#ifdef CONFIG_NODEMCU_EMBEDDED_LFS_SIZE
|
||||
flashSize = CONFIG_NODEMCU_EMBEDDED_LFS_SIZE;
|
||||
flashAddr = lua_flash_store_reserved;
|
||||
flashAddrPhys = spi_flash_cache2phys(lua_flash_store_reserved);
|
||||
if (flashAddrPhys == SPI_FLASH_CACHE2PHYS_FAIL) {
|
||||
NODE_ERR("spi_flash_cache2phys failed\n");
|
||||
lfs_location_info_t lfs_loc;
|
||||
if (!lfs_get_location(&lfs_loc))
|
||||
return;
|
||||
}
|
||||
#else
|
||||
const esp_partition_t *part = esp_partition_find_first(
|
||||
PLATFORM_PARTITION_TYPE_NODEMCU,
|
||||
PLATFORM_PARTITION_SUBTYPE_NODEMCU_LFS,
|
||||
NULL);
|
||||
if (!part)
|
||||
return; // Nothing to do if the size is zero
|
||||
|
||||
flashSize = part->size; // in bytes
|
||||
flashAddrPhys = part->address;
|
||||
flashAddr = spi_flash_phys2cache(flashAddrPhys, SPI_FLASH_MMAP_DATA);
|
||||
if (!flashAddr) {
|
||||
spi_flash_mmap_handle_t ignored;
|
||||
esp_err_t err = spi_flash_mmap(
|
||||
flashAddrPhys, flashSize, SPI_FLASH_MMAP_DATA,
|
||||
cast(const void **, &flashAddr), &ignored);
|
||||
if (err != ESP_OK) {
|
||||
NODE_ERR("Unable to access LFS partition - is it 64kB aligned as it needs to be?\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
G(L)->LFSsize = flashSize;
|
||||
flashSector = platform_flash_get_sector_of_address(flashAddrPhys);
|
||||
|
||||
FlashHeader *fh = cast(FlashHeader *, flashAddr);
|
||||
G(L)->LFSsize = flashSize = lfs_loc.size;
|
||||
flashAddr = lfs_loc.addr_mem;
|
||||
flashAddrPhys = lfs_loc.addr_phys;
|
||||
flashSector = platform_flash_get_sector_of_address(lfs_loc.addr_phys);
|
||||
FlashHeader *fh = cast(FlashHeader *, lfs_loc.addr_mem);
|
||||
curOffset = 0;
|
||||
|
||||
/*
|
||||
@ -204,15 +181,15 @@ LUAI_FUNC void luaN_init (lua_State *L) {
|
||||
}
|
||||
|
||||
if ((fh->flash_sig & (~FLASH_SIG_ABSOLUTE)) != FLASH_SIG ) {
|
||||
NODE_ERR("Flash sig not correct: %u vs %u\n",
|
||||
NODE_ERR("LFS sig not correct: 0x%x vs expected 0x%x\n",
|
||||
fh->flash_sig & (~FLASH_SIG_ABSOLUTE), FLASH_SIG);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fh->pROhash == ALL_SET ||
|
||||
((fh->mainProto - cast(FlashAddr, fh)) >= fh->flash_size)) {
|
||||
NODE_ERR("Flash size check failed: %x vs 0xFFFFFFFF; size: %u\n",
|
||||
fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
|
||||
NODE_ERR("Flash size check failed: 0x%08x vs 0xFFFFFFFF; 0x%08x >= 0x%08x\n",
|
||||
fh->pROhash, fh->mainProto - cast(FlashAddr, fh), fh->flash_size);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -222,23 +199,24 @@ LUAI_FUNC void luaN_init (lua_State *L) {
|
||||
G(L)->ROpvmain = cast(Proto *,fh->mainProto);
|
||||
}
|
||||
|
||||
/* luaL_lfsreload() is exported via lauxlib.h */
|
||||
|
||||
/*
|
||||
* Library function called by node.flashreload(filename).
|
||||
*/
|
||||
LUALIB_API int luaN_reload_reboot (lua_State *L) {
|
||||
LUALIB_API void luaL_lfsreload (lua_State *L) {
|
||||
#ifdef CONFIG_NODEMCU_EMBEDDED_LFS_SIZE
|
||||
// Updating the LFS section is disabled for now because any changes to the
|
||||
// image requires updating its checksum to prevent boot failure.
|
||||
lua_pushstring(L, "Not allowed to write to LFS section");
|
||||
return 1;
|
||||
return;
|
||||
#else
|
||||
// luaL_dbgbreak();
|
||||
const char *fn = lua_tostring(L, 1), *msg = "";
|
||||
int status;
|
||||
|
||||
if (G(L)->LFSsize == 0) {
|
||||
lua_pushstring(L, "No LFS partition allocated");
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -270,7 +248,7 @@ LUALIB_API int luaN_reload_reboot (lua_State *L) {
|
||||
lua_cpcall(L, &loadLFSgc, NULL);
|
||||
lua_settop(L, 0);
|
||||
lua_pushstring(L, msg);
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
@ -290,62 +268,22 @@ LUALIB_API int luaN_reload_reboot (lua_State *L) {
|
||||
NODE_ERR("%s\n", msg);
|
||||
|
||||
esp_restart();
|
||||
return 0;
|
||||
#endif // CONFIG_NODEMCU_EMBEDDED_LFS_SIZE
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If the arg is a valid LFS module name then return the LClosure
|
||||
* pointing to it. Otherwise return:
|
||||
* - The Unix time that the LFS was built
|
||||
* - The base address and length of the LFS
|
||||
* - An array of the module names in the LFS
|
||||
*/
|
||||
LUAI_FUNC int luaN_index (lua_State *L) {
|
||||
int n = lua_gettop(L);
|
||||
|
||||
/* Return nil + the LFS base address if the LFS size > 0 and it isn't loaded */
|
||||
if (!(G(L)->ROpvmain)) {
|
||||
lua_settop(L, 0);
|
||||
lua_pushnil(L);
|
||||
if (G(L)->LFSsize) {
|
||||
lua_pushinteger(L, (lua_Integer) flashAddr);
|
||||
lua_pushinteger(L, flashAddrPhys);
|
||||
lua_pushinteger(L, G(L)->LFSsize);
|
||||
return 4;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Push the LClosure of the LFS index function */
|
||||
Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
|
||||
cl->l.p = G(L)->ROpvmain;
|
||||
lua_settop(L, n+1);
|
||||
setclvalue(L, L->top-1, cl);
|
||||
|
||||
/* Move it infront of the arguments and call the index function */
|
||||
lua_insert(L, 1);
|
||||
lua_call(L, n, LUA_MULTRET);
|
||||
|
||||
/* Return it if the response if a single value (the function) */
|
||||
if (lua_gettop(L) == 1)
|
||||
return 1;
|
||||
|
||||
lua_assert(lua_gettop(L) == 2);
|
||||
|
||||
/* Otherwise add the base address of the LFS, and its size bewteen the */
|
||||
/* Unix time and the module list, then return all 4 params. */
|
||||
lua_pushinteger(L, (lua_Integer) flashAddr);
|
||||
lua_insert(L, 2);
|
||||
lua_pushinteger(L, flashAddrPhys);
|
||||
lua_insert(L, 3);
|
||||
lua_pushinteger(L, cast(FlashHeader *, flashAddr)->flash_size);
|
||||
lua_insert(L, 4);
|
||||
return 5;
|
||||
LUA_API void lua_getlfsconfig (lua_State *L, intptr_t *config) {
|
||||
if (!config)
|
||||
return;
|
||||
config[0] = (intptr_t) flashAddr; /* LFS region mapped address */
|
||||
config[1] = flashAddrPhys; /* LFS region base flash address */
|
||||
config[2] = G(L)->LFSsize; /* LFS region actual size */
|
||||
config[3] = (G(L)->ROstrt.hash) ? cast(FlashHeader *, flashAddr)->flash_size : 0;
|
||||
/* LFS region used */
|
||||
config[4] = 0; /* Not used in Lua 5.1 */
|
||||
}
|
||||
|
||||
|
||||
#ifndef CONFIG_NODEMCU_EMBEDDED_LFS_SIZE
|
||||
/* =====================================================================================
|
||||
* The following routines use my uzlib which was based on pfalcon's inflate and
|
||||
@ -440,7 +378,7 @@ static uint8_t recall_byte (uint32_t offset) {
|
||||
* - Once the flags array is in-buffer this is also captured.
|
||||
* This logic is slightly complicated by the last buffer is typically short.
|
||||
*/
|
||||
int procFirstPass (void) {
|
||||
void procFirstPass (void) {
|
||||
int len = (out->ndx % WRITE_BLOCKSIZE) ?
|
||||
out->ndx % WRITE_BLOCKSIZE : WRITE_BLOCKSIZE;
|
||||
if (out->ndx <= WRITE_BLOCKSIZE) {
|
||||
@ -475,12 +413,10 @@ int procFirstPass (void) {
|
||||
memcpy(out->flags + out->flagsNdx, out->block[0]->byte + start, len - start);
|
||||
out->flagsNdx += (len -start) / WORDSIZE; /* flashLen and len are word aligned */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int procSecondPass (void) {
|
||||
void procSecondPass (void) {
|
||||
/*
|
||||
* The length rules are different for the second pass since this only processes
|
||||
* upto the flashLen and not the full image. This also works in word units.
|
||||
@ -518,12 +454,10 @@ int procSecondPass (void) {
|
||||
flashBlock(&out->flash_sig, WORDSIZE);
|
||||
out->fullBlkCB = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* loadLFS)() is protected called from luaN_reload_reboot so that it can recover
|
||||
* loadLFS)() is protected called from luaL_lfsreload so that it can recover
|
||||
* from out of memory and other thrown errors. loadLFSgc() GCs any resources.
|
||||
*/
|
||||
static int loadLFS (lua_State *L) {
|
||||
@ -548,7 +482,7 @@ static int loadLFS (lua_State *L) {
|
||||
in->len = vfs_size(in->fd);
|
||||
if (in->len <= 200 || /* size of an empty luac output */
|
||||
vfs_lseek(in->fd, in->len-4, VFS_SEEK_SET) != in->len-4 ||
|
||||
vfs_read(in->fd, &out->len, sizeof(uint)) != sizeof(uint))
|
||||
vfs_read(in->fd, &out->len, sizeof(uint32_t)) != sizeof(uint32_t))
|
||||
flash_error("read error on LFS image file");
|
||||
vfs_lseek(in->fd, 0, VFS_SEEK_SET);
|
||||
|
@ -43,8 +43,5 @@ typedef struct {
|
||||
} FlashHeader;
|
||||
|
||||
LUAI_FUNC void luaN_init (lua_State *L);
|
||||
LUAI_FUNC int luaN_flashSetup (lua_State *L);
|
||||
LUAI_FUNC int luaN_reload_reboot (lua_State *L);
|
||||
LUAI_FUNC int luaN_index (lua_State *L);
|
||||
#endif
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#define lfunc_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -126,12 +125,7 @@ Proto *luaF_newproto (lua_State *L) {
|
||||
f->numparams = 0;
|
||||
f->is_vararg = 0;
|
||||
f->maxstacksize = 0;
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
f->packedlineinfo = NULL;
|
||||
#else
|
||||
f->sizelineinfo = 0;
|
||||
f->lineinfo = NULL;
|
||||
#endif
|
||||
f->sizelocvars = 0;
|
||||
f->locvars = NULL;
|
||||
f->linedefined = 0;
|
||||
@ -146,15 +140,9 @@ void luaF_freeproto (lua_State *L, Proto *f) {
|
||||
luaM_freearray(L, f->k, f->sizek, TValue);
|
||||
luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
|
||||
luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);
|
||||
if (!proto_isreadonly(f)) {
|
||||
luaM_freearray(L, f->code, f->sizecode, Instruction);
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
if (f->packedlineinfo) {
|
||||
luaM_freearray(L, f->packedlineinfo, strlen(cast(char *, f->packedlineinfo))+1, unsigned char);
|
||||
}
|
||||
#else
|
||||
luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
|
||||
#endif
|
||||
luaM_freearray(L, f->code, f->sizecode, Instruction);
|
||||
if (f->packedlineinfo) {
|
||||
luaM_freearray(L, f->packedlineinfo, strlen(cast(char *, f->packedlineinfo))+1, unsigned char);
|
||||
}
|
||||
luaM_free(L, f);
|
||||
}
|
@ -6,7 +6,6 @@
|
||||
|
||||
#define lgc_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -21,14 +20,12 @@
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "ltm.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
#define GCSTEPSIZE 1024u
|
||||
#define GCSWEEPMAX 40
|
||||
#define GCSWEEPCOST 10
|
||||
#define GCFINALIZECOST 100
|
||||
|
||||
|
||||
#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS))
|
||||
|
||||
#define makewhite(g,x) \
|
||||
@ -55,7 +52,6 @@
|
||||
#define markobject(g,t) { if (iswhite(obj2gco(t))) \
|
||||
reallymarkobject(g, obj2gco(t)); }
|
||||
|
||||
|
||||
#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause)
|
||||
|
||||
|
||||
@ -82,7 +78,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
||||
case LUA_TUSERDATA: {
|
||||
Table *mt = gco2u(o)->metatable;
|
||||
gray2black(o); /* udata are never gray */
|
||||
if (mt && !luaR_isrotable(mt)) markobject(g, mt);
|
||||
if (mt && isrwtable(mt)) markobject(g, mt);
|
||||
markobject(g, gco2u(o)->env);
|
||||
return;
|
||||
}
|
||||
@ -160,7 +156,6 @@ size_t luaC_separateudata (lua_State *L, int all) {
|
||||
return deadmem;
|
||||
}
|
||||
|
||||
|
||||
static int traversetable (global_State *g, Table *h) {
|
||||
int i;
|
||||
int weakkey = 0;
|
||||
@ -168,7 +163,7 @@ static int traversetable (global_State *g, Table *h) {
|
||||
const TValue *mode = luaO_nilobject;
|
||||
|
||||
if (h->metatable) {
|
||||
if (!luaR_isrotable(h->metatable))
|
||||
if (isrwtable(h->metatable))
|
||||
markobject(g, h->metatable);
|
||||
mode = gfasttm(g, h->metatable, TM_MODE);
|
||||
}
|
||||
@ -331,14 +326,8 @@ static l_mem propagatemark (global_State *g) {
|
||||
sizeof(TValue) * p->sizek +
|
||||
sizeof(LocVar) * p->sizelocvars +
|
||||
sizeof(TString *) * p->sizeupvalues +
|
||||
(proto_isreadonly(p) ? 0 : sizeof(Instruction) * p->sizecode +
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
(p->packedlineinfo ?
|
||||
strlen(cast(char *, p->packedlineinfo))+1 :
|
||||
0));
|
||||
#else
|
||||
sizeof(int) * p->sizelineinfo);
|
||||
#endif
|
||||
sizeof(Instruction) * p->sizecode +
|
||||
(p->packedlineinfo ? strlen(cast(char *, p->packedlineinfo))+1 : 0);
|
||||
}
|
||||
default: lua_assert(0); return 0;
|
||||
}
|
||||
@ -522,8 +511,8 @@ void luaC_freeall (lua_State *L) {
|
||||
|
||||
static void markmt (global_State *g) {
|
||||
int i;
|
||||
for (i=0; i<NUM_TAGS; i++)
|
||||
if (g->mt[i] && !luaR_isrotable(g->mt[i])) markobject(g, g->mt[i]);
|
||||
for (i=0; i<LUA_NUMTAGS; i++)
|
||||
if (g->mt[i] && isrwtable(g->mt[i])) markobject(g, g->mt[i]);
|
||||
}
|
||||
|
||||
|
||||
@ -713,7 +702,7 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {
|
||||
global_State *g = G(L);
|
||||
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
|
||||
lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
|
||||
lua_assert(o->gch.tt != LUA_TTABLE);
|
||||
lua_assert((gettt(o) & LUA_TMASK) != LUA_TTABLE);
|
||||
/* must keep invariant? */
|
||||
if (g->gcstate == GCSpropagate)
|
||||
reallymarkobject(g, v); /* Restore invariant */
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define llex_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <ctype.h>
|
||||
@ -62,6 +61,7 @@ static void save (LexState *ls, int c) {
|
||||
|
||||
|
||||
void luaX_init (lua_State *L) {
|
||||
(void)L;
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,6 @@
|
||||
#define llimits_h
|
||||
|
||||
|
||||
//#include <limits.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
typedef LUAI_UINT32 lu_int32;
|
||||
@ -104,7 +102,7 @@ typedef lu_int32 Instruction;
|
||||
|
||||
|
||||
#ifndef lua_lock
|
||||
#define lua_lock(L) ((void) 0)
|
||||
#define lua_lock(L) ((void) 0)
|
||||
#define lua_unlock(L) ((void) 0)
|
||||
#endif
|
||||
|
||||
@ -115,7 +113,7 @@ typedef lu_int32 Instruction;
|
||||
|
||||
/*
|
||||
** macro to control inclusion of some hard tests on stack reallocation
|
||||
*/
|
||||
*/
|
||||
#ifndef HARDSTACKTESTS
|
||||
#define condhardstacktests(x) ((void)0)
|
||||
#else
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lmathlib_c
|
||||
#define LUA_LIB
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdlib.h>
|
||||
@ -15,7 +14,6 @@
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
#undef PI
|
||||
#define PI (3.14159265358979323846)
|
||||
@ -309,7 +307,7 @@ static int math_randomseed (lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LROT_PUBLIC_BEGIN(math)
|
||||
LROT_BEGIN(mathlib, NULL, 0)
|
||||
#ifdef LUA_NUMBER_INTEGRAL
|
||||
LROT_FUNCENTRY( abs, math_abs )
|
||||
LROT_FUNCENTRY( ceil, math_identity )
|
||||
@ -354,7 +352,7 @@ LROT_PUBLIC_BEGIN(math)
|
||||
LROT_NUMENTRY( pi, PI )
|
||||
LROT_NUMENTRY( huge, HUGE_VAL )
|
||||
#endif // #ifdef LUA_NUMBER_INTEGRAL
|
||||
LROT_END(math, NULL, 0)
|
||||
LROT_END(mathlib, NULL, 0)
|
||||
|
||||
|
||||
/*
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lmem_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
|
@ -8,12 +8,6 @@
|
||||
#define lmem_h
|
||||
|
||||
|
||||
//#ifdef LUA_CROSS_COMPILER
|
||||
//#include <stddef.h>
|
||||
//#else
|
||||
//#include "c_stddef.h"
|
||||
//#endif
|
||||
|
||||
#include "llimits.h"
|
||||
#include "lua.h"
|
||||
|
259
components/lua/lua-5.1/lnodemcu.c
Normal file
259
components/lua/lua-5.1/lnodemcu.c
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Tag methods
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#define lnodemcu_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lgc.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "ltm.h"
|
||||
#include "lnodemcu.h"
|
||||
|
||||
//== NodeMCU lauxlib.h API extensions ========================================//
|
||||
#ifdef LUA_USE_ESP
|
||||
#include "task/task.h"
|
||||
#include "platform.h"
|
||||
|
||||
/*
|
||||
** Error Reporting Task. We can't pass a string parameter to the error reporter
|
||||
** directly through the task interface the call is wrapped in a C closure with
|
||||
** the error string as an Upval and this is posted to call the Lua reporter.
|
||||
*/
|
||||
static int errhandler_aux (lua_State *L) {
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "onerror");
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_getglobal(L, "print");
|
||||
}
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
lua_call(L, 1, 0); /* Using an error handler would cause an infinite loop! */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Error handler for luaL_pcallx(), called from the lua_pcall() with a single
|
||||
** argument -- the thrown error. This plus depth=2 is passed to debug.traceback()
|
||||
** to convert into an error message which it handles in a separate posted task.
|
||||
*/
|
||||
static int errhandler (lua_State *L) {
|
||||
lua_getglobal(L, "debug");
|
||||
lua_getfield(L, -1, "traceback");
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_insert(L, 1); /* insert tracback function above error */
|
||||
lua_pop(L, 1); /* dump the debug table entry */
|
||||
lua_pushinteger(L, 2); /* skip this function and traceback */
|
||||
lua_call(L, 2, 1); /* call debug.traceback and return it as a string */
|
||||
lua_pushcclosure(L, errhandler_aux, 1); /* report with str as upval */
|
||||
luaL_posttask(L, LUA_TASK_HIGH);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Use in CBs and other C functions to call a Lua function. This includes
|
||||
** an error handler which will catch any error and then post this to the
|
||||
** registered reporter function as a separate follow-on task.
|
||||
*/
|
||||
LUALIB_API int luaL_pcallx (lua_State *L, int narg, int nres) { // [-narg, +0, v]
|
||||
int status;
|
||||
int base = lua_gettop(L) - narg;
|
||||
lua_pushcfunction(L, errhandler);
|
||||
lua_insert(L, base); /* put under args */
|
||||
status = lua_pcall(L, narg, nres, base);
|
||||
lua_remove(L, base); /* remove traceback function */
|
||||
if (status != LUA_OK && status != LUA_ERRRUN) {
|
||||
lua_gc(L, LUA_GCCOLLECT, 0); /* call onerror directly if handler failed */
|
||||
lua_pushliteral(L, "out of memory");
|
||||
lua_pushcclosure(L, errhandler_aux, 1); /* report EOM as upval */
|
||||
luaL_posttask(L, LUA_TASK_HIGH);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static task_handle_t task_handle = 0;
|
||||
|
||||
/*
|
||||
** Task callback handler. Uses luaN_call to do a protected call with full traceback
|
||||
*/
|
||||
static void do_task (task_param_t task_fn_ref, task_prio_t prio) {
|
||||
lua_State* L = lua_getstate();
|
||||
if (prio < 0|| prio > 2)
|
||||
luaL_error(L, "invalid posk task");
|
||||
|
||||
/* Pop the CB func from the Reg */
|
||||
//dbg_printf("calling Reg[%u]\n", task_fn_ref);
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
|
||||
luaL_checkfunction(L, -1);
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, (int) task_fn_ref);
|
||||
lua_pushinteger(L, prio);
|
||||
luaL_pcallx(L, 1, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Schedule a Lua function for task execution
|
||||
*/
|
||||
LUALIB_API int luaL_posttask( lua_State* L, int prio ) { // [-1, +0, -]
|
||||
if (!task_handle)
|
||||
task_handle = task_get_id(do_task);
|
||||
|
||||
if (!lua_isfunction(L, -1) || prio < LUA_TASK_LOW|| prio > LUA_TASK_HIGH)
|
||||
luaL_error(L, "invalid posk task");
|
||||
//void *cl = clvalue(L->top-1);
|
||||
int task_fn_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
//dbg_printf("posting Reg[%u]=%p\n",task_fn_ref,cl);
|
||||
if(!task_post(prio, task_handle, (task_param_t)task_fn_ref)) {
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, task_fn_ref);
|
||||
luaL_error(L, "Task queue overflow. Task not posted");
|
||||
}
|
||||
return task_fn_ref;
|
||||
}
|
||||
#else
|
||||
LUALIB_API int luaL_posttask( lua_State* L, int prio ) {
|
||||
(void)L; (void)prio;
|
||||
return 0;
|
||||
} /* Dummy stub on host */
|
||||
#endif
|
||||
|
||||
#ifdef LUA_USE_ESP
|
||||
/*
|
||||
* Return an LFS function
|
||||
*/
|
||||
LUALIB_API int luaL_pushlfsmodule (lua_State *L) {
|
||||
if (lua_pushlfsindex(L) == LUA_TNIL) {
|
||||
lua_remove(L,-2); /* dump the name to balance the stack */
|
||||
return 0; /* return nil if LFS not loaded */
|
||||
}
|
||||
lua_insert(L, -2);
|
||||
lua_call(L, 1, 1);
|
||||
if (!lua_isfunction(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
lua_pushnil(L); /* replace DTS by nil */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return an array of functions in LFS
|
||||
*/
|
||||
LUALIB_API int luaL_pushlfsmodules (lua_State *L) {
|
||||
if (lua_pushlfsindex(L) == LUA_TNIL)
|
||||
return 0; /* return nil if LFS not loaded */
|
||||
lua_call(L, 0, 2);
|
||||
lua_remove(L, -2); /* remove DTS leaving array */
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the Unix timestamp of the LFS image creation
|
||||
*/
|
||||
LUALIB_API int luaL_pushlfsdts (lua_State *L) {
|
||||
if (lua_pushlfsindex(L) == LUA_TNIL)
|
||||
return 0; /* return nil if LFS not loaded */
|
||||
lua_call(L, 0, 1);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
//== NodeMCU lua.h API extensions ============================================//
|
||||
|
||||
LUA_API int lua_freeheap (void) {
|
||||
#ifdef LUA_USE_HOST
|
||||
return MAX_INT;
|
||||
#else
|
||||
return (int)esp_get_free_heap_size();
|
||||
#endif
|
||||
}
|
||||
|
||||
#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;}
|
||||
LUA_API int lua_pushstringsarray(lua_State *L, int opt) {
|
||||
stringtable *tb = NULL;
|
||||
int i, j;
|
||||
|
||||
lua_lock(L);
|
||||
if (opt == 0)
|
||||
tb = &G(L)->strt;
|
||||
#ifdef LUA_USE_ESP
|
||||
else if (opt == 1 && G(L)->ROstrt.hash)
|
||||
tb = &G(L)->ROstrt;
|
||||
#endif
|
||||
if (tb == NULL) {
|
||||
setnilvalue(L->top);
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Table *t = luaH_new(L, tb->nuse, 0);
|
||||
sethvalue(L, L->top, t);
|
||||
api_incr_top(L);
|
||||
luaC_checkGC(L);
|
||||
lua_unlock(L);
|
||||
|
||||
for (i = 0, j = 1; i < tb->size; i++) {
|
||||
GCObject *o;
|
||||
for(o = tb->hash[i]; o; o = o->gch.next) {
|
||||
TValue v;
|
||||
setsvalue(L, &v, o);
|
||||
setobj2s(L, luaH_setnum(L, hvalue(L->top-1), j++), &v);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
LUA_API void lua_createrotable (lua_State *L, ROTable *t, const ROTable_entry *e, ROTable *mt) {
|
||||
int i, j;
|
||||
lu_byte flags = ~0;
|
||||
const char *plast = (char *)"_";
|
||||
for (i = 0; e[i].key; i++) {
|
||||
if (e[i].key[0] == '_' && strcmp(e[i].key,plast)) {
|
||||
plast = e[i].key;
|
||||
lua_pushstring(L,e[i].key);
|
||||
for (j=0; j<TM_EQ; j++){
|
||||
if(rawtsvalue(L->top-1)==G(L)->tmname[i]) {
|
||||
flags |= cast_byte(1u<<i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
lua_pop(L,1);
|
||||
}
|
||||
}
|
||||
t->next = (GCObject *)1;
|
||||
t->tt = LUA_TROTABLE;
|
||||
t->marked = LROT_MARKED;
|
||||
t->flags = flags;
|
||||
t->lsizenode = i;
|
||||
t->metatable = cast(Table *, mt);
|
||||
t->entry = cast(ROTable_entry *, e);
|
||||
}
|
||||
|
||||
#ifdef LUA_USE_ESP
|
||||
#include "lfunc.h"
|
||||
|
||||
/* Push the LClosure of the LFS index function */
|
||||
LUA_API int lua_pushlfsindex (lua_State *L) {
|
||||
lua_lock(L);
|
||||
Proto *p = G(L)->ROpvmain;
|
||||
if (p) {
|
||||
Closure *cl = luaF_newLclosure(L, 0, hvalue(gt(L)));
|
||||
cl->l.p = p;
|
||||
setclvalue(L, L->top, cl);
|
||||
} else {
|
||||
setnilvalue(L->top);
|
||||
}
|
||||
api_incr_top(L);
|
||||
lua_unlock(L);
|
||||
return p ? LUA_TFUNCTION : LUA_TNIL;
|
||||
}
|
||||
#endif
|
73
components/lua/lua-5.1/lnodemcu.h
Normal file
73
components/lua/lua-5.1/lnodemcu.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* NodeMCU extensions to Lua 5.1 for readonly Flash memory support
|
||||
*/
|
||||
#ifndef lnodemcu_h
|
||||
#define lnodemcu_h
|
||||
|
||||
#include "lua.h"
|
||||
#include "lobject.h"
|
||||
#include "llimits.h"
|
||||
#include "ltm.h"
|
||||
|
||||
#ifdef LUA_USE_HOST
|
||||
#define LRO_STRKEY(k) k
|
||||
#define LOCK_IN_SECTION(s)
|
||||
#else
|
||||
#define LRO_STRKEY(k) ((__attribute__((aligned(4))) const char *) k)
|
||||
#define LOCK_IN_SECTION(s) __attribute__((used,unused,section(".lua_" #s)))
|
||||
#endif
|
||||
|
||||
/* Macros used to declare rotable entries */
|
||||
|
||||
#define LRO_FUNCVAL(v) {{.p = v}, LUA_TLIGHTFUNCTION}
|
||||
#define LRO_LUDATA(v) {{.p = cast(void*,v)}, LUA_TLIGHTUSERDATA}
|
||||
#define LRO_NILVAL {{.p = NULL}, LUA_TNIL}
|
||||
#define LRO_NUMVAL(v) {{.n = v}, LUA_TNUMBER}
|
||||
#define LRO_INTVAL(v) LRO_NUMVAL(v)
|
||||
#define LRO_FLOATVAL(v) LRO_NUMVAL(v)
|
||||
#define LRO_ROVAL(v) {{.gc = cast(GCObject *, &(v ## _ROTable))}, LUA_TROTABLE}
|
||||
|
||||
#define LROT_MARKED 0 //<<<<<<<<<< *** TBD *** >>>>>>>>>>>
|
||||
|
||||
#define LROT_FUNCENTRY(n,f) {LRO_STRKEY(#n), LRO_FUNCVAL(f)},
|
||||
#define LROT_LUDENTRY(n,x) {LRO_STRKEY(#n), LRO_LUDATA(x)},
|
||||
#define LROT_NUMENTRY(n,x) {LRO_STRKEY(#n), LRO_NUMVAL(x)},
|
||||
#define LROT_INTENTRY(n,x) LROT_NUMENTRY(n,x)
|
||||
#define LROT_FLOATENTRY(n,x) LROT_NUMENTRY(n,x)
|
||||
#define LROT_TABENTRY(n,t) {LRO_STRKEY(#n), LRO_ROVAL(t)},
|
||||
|
||||
#define LROT_TABLE(rt) const ROTable rt ## _ROTable
|
||||
#define LROT_ENTRYREF(rt) (rt ##_entries)
|
||||
#define LROT_TABLEREF(rt) (&rt ##_ROTable)
|
||||
#define LROT_BEGIN(rt,mt,f) LROT_TABLE(rt); \
|
||||
static ROTable_entry rt ## _entries[] = {
|
||||
#define LROT_ENTRIES_IN_SECTION(rt,s) \
|
||||
static ROTable_entry LOCK_IN_SECTION(s) rt ## _entries[] = {
|
||||
#define LROT_END(rt,mt,f) {NULL, LRO_NILVAL} }; \
|
||||
const ROTable rt ## _ROTable = { \
|
||||
(GCObject *)1, LUA_TROTABLE, LROT_MARKED, \
|
||||
cast(lu_byte, ~(f)), (sizeof(rt ## _entries)/sizeof(ROTable_entry)) - 1, \
|
||||
cast(Table *, mt), cast(ROTable_entry *, rt ## _entries) };
|
||||
#define LROT_BREAK(rt) };
|
||||
|
||||
#define LROT_MASK(m) cast(lu_byte, 1<<TM_ ## m)
|
||||
|
||||
/*
|
||||
* These are statically coded can be any combination of the fast index tags
|
||||
* listed in ltm.h: EQ, GC, INDEX, LEN, MODE, NEWINDEX or combined by anding
|
||||
* GC+INDEX is the only common combination used, hence the combinaton macro
|
||||
*/
|
||||
#define LROT_MASK_EQ LROT_MASK(EQ)
|
||||
#define LROT_MASK_GC LROT_MASK(GC)
|
||||
#define LROT_MASK_INDEX LROT_MASK(INDEX)
|
||||
#define LROT_MASK_LEN LROT_MASK(LEN)
|
||||
#define LROT_MASK_MODE LROT_MASK(MODE)
|
||||
#define LROT_MASK_NEWINDEX LROT_MASK(NEWINDEX)
|
||||
#define LROT_MASK_GC_INDEX (LROT_MASK_GC | LROT_MASK_INDEX)
|
||||
|
||||
#define LUA_MAX_ROTABLE_NAME 32 /* Maximum length of a rotable name and of a string key*/
|
||||
|
||||
#ifdef LUA_CORE
|
||||
|
||||
#endif
|
||||
#endif
|
@ -11,7 +11,6 @@
|
||||
|
||||
#define loadlib_c
|
||||
#define LUA_LIB
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdlib.h>
|
||||
@ -24,7 +23,6 @@
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
/* prefix for open functions in C libraries */
|
||||
#define LUA_POF "luaopen_"
|
||||
@ -394,11 +392,7 @@ static int loader_Lua (lua_State *L) {
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
filename = findfile(L, name, "path");
|
||||
if (filename == NULL) return 1; /* library not found in this path */
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
if (luaL_loadfile(L, filename) != 0)
|
||||
#else
|
||||
if (luaL_loadfsfile(L, filename) != 0)
|
||||
#endif
|
||||
loaderror(L, filename);
|
||||
return 1; /* library loaded successfully */
|
||||
}
|
||||
@ -479,7 +473,7 @@ static int ll_require (lua_State *L) {
|
||||
}
|
||||
/* Is this a readonly table? */
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, name);
|
||||
if(lua_isrotable(L,-1)) {
|
||||
if(lua_istable(L,-1)) {
|
||||
return 1;
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
@ -572,7 +566,7 @@ static int ll_module (lua_State *L) {
|
||||
const char *modname = luaL_checkstring(L, 1);
|
||||
/* Is this a readonly table? */
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, modname);
|
||||
if(lua_isrotable(L,-1)) {
|
||||
if(lua_istable(L,-1)) {
|
||||
return 0;
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
@ -658,9 +652,9 @@ static const luaL_Reg ll_funcs[] = {
|
||||
static const lua_CFunction loaders[] =
|
||||
{loader_preload, loader_Lua, loader_C, loader_Croot, NULL};
|
||||
|
||||
LROT_PUBLIC_BEGIN(lmt)
|
||||
LROT_FUNCENTRY(__gc,gctm)
|
||||
LROT_END(lmt,lmt, LROT_MASK_GC)
|
||||
LROT_BEGIN(lmt, NULL, LROT_MASK_GC)
|
||||
LROT_FUNCENTRY( __gc, gctm )
|
||||
LROT_END(lmt, NULL, LROT_MASK_GC)
|
||||
|
||||
LUALIB_API int luaopen_package (lua_State *L) {
|
||||
int i;
|
@ -1,3 +1,4 @@
|
||||
|
||||
/*
|
||||
** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Some generic functions over Lua objects
|
||||
@ -7,7 +8,6 @@
|
||||
|
||||
#define lobject_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdio.h>
|
||||
@ -25,7 +25,6 @@
|
||||
#else
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
const TValue luaO_nilobject_ = {LUA_TVALUE_NIL};
|
||||
|
||||
|
||||
@ -54,7 +53,23 @@ int luaO_fb2int (int x) {
|
||||
|
||||
|
||||
int luaO_log2 (unsigned int x) {
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
static const lu_byte log_2[256] = {
|
||||
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
|
||||
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
|
||||
};
|
||||
int l = -1;
|
||||
while (x >= 256) { l += 8; x >>= 8; }
|
||||
return l + log_2[x];
|
||||
#else
|
||||
return 31 - __builtin_clz(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -70,7 +85,7 @@ int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
return pvalue(t1) == pvalue(t2);
|
||||
case LUA_TROTABLE:
|
||||
return rvalue(t1) == rvalue(t2);
|
||||
return hvalue(t1) == hvalue(t2);
|
||||
case LUA_TLIGHTFUNCTION:
|
||||
return fvalue(t1) == fvalue(t2);
|
||||
default:
|
||||
@ -85,11 +100,11 @@ int luaO_str2d (const char *s, lua_Number *result) {
|
||||
*result = lua_str2number(s, &endptr);
|
||||
if (endptr == s) return 0; /* conversion failed */
|
||||
if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */
|
||||
#if defined(LUA_CROSS_COMPILER)
|
||||
#if defined(LUA_CROSS_COMPILER)
|
||||
{
|
||||
long lres = strtoul(s, &endptr, 16);
|
||||
#if LONG_MAX != 2147483647L
|
||||
if (lres & ~0xffffffffL)
|
||||
#if INT_MAX != 2147483647L
|
||||
if (lres & ~0xffffffffL)
|
||||
*result = cast_num(-1);
|
||||
else if (lres & 0x80000000L)
|
||||
*result = cast_num(lres | ~0x7fffffffL);
|
@ -17,7 +17,7 @@
|
||||
/* tags for values visible from Lua */
|
||||
#define LAST_TAG LUA_TTHREAD
|
||||
|
||||
#define NUM_TAGS (LAST_TAG+1)
|
||||
#define LUA_NUMTAGS (LAST_TAG+1)
|
||||
|
||||
#define READONLYMASK (1<<7) /* denormalised bitmask for READONLYBIT and */
|
||||
#define LFSMASK (1<<6) /* LFSBIT to avoid include proliferation */
|
||||
@ -28,15 +28,18 @@
|
||||
#define LUA_TUPVAL (LAST_TAG+2)
|
||||
#define LUA_TDEADKEY (LAST_TAG+3)
|
||||
|
||||
#ifdef __XTENSA__
|
||||
#ifdef LUA_USE_ESP8266
|
||||
/*
|
||||
** force aligned access to critical fields in Flash-based structures
|
||||
** wo is the offset of aligned word in bytes 0,4,8,..
|
||||
** bo is the field within the word in bits 0..31
|
||||
**
|
||||
** Note that this returns a lu_int32 as returning a byte can cause the
|
||||
** gcc code generator to emit an extra extui instruction.
|
||||
*/
|
||||
#define GET_BYTE_FN(name,t,wo,bo) \
|
||||
static inline lu_byte get ## name(void *o) { \
|
||||
lu_byte res; /* extract named field */ \
|
||||
static inline lu_int32 get ## name(void *o) { \
|
||||
lu_int32 res; /* extract named field */ \
|
||||
asm ("l32i %0, %1, " #wo "; extui %0, %0, " #bo ", 8;" : "=r"(res) : "r"(o) : );\
|
||||
return res; }
|
||||
#else
|
||||
@ -49,14 +52,12 @@ static inline lu_byte get ## name(void *o) { return ((t *)o)->name; }
|
||||
*/
|
||||
typedef union GCObject GCObject;
|
||||
|
||||
|
||||
/*
|
||||
** Common Header for all collectable objects (in macro form, to be
|
||||
** included in other objects)
|
||||
*/
|
||||
#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked
|
||||
|
||||
|
||||
/*
|
||||
** Common header in struct form
|
||||
*/
|
||||
@ -93,43 +94,47 @@ typedef union {
|
||||
#define TValuefields Value value; int tt
|
||||
#define LUA_TVALUE_NIL {NULL}, LUA_TNIL
|
||||
|
||||
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
|
||||
#pragma pack(4)
|
||||
#ifdef LUA_USE_ESP
|
||||
# pragma pack(4)
|
||||
#endif
|
||||
|
||||
typedef struct lua_TValue {
|
||||
TValuefields;
|
||||
} TValue;
|
||||
#if defined(LUA_PACK_TVALUES) && !defined(LUA_CROSS_COMPILER)
|
||||
#pragma pack()
|
||||
|
||||
#ifdef LUA_USE_ESP
|
||||
# pragma pack()
|
||||
#endif
|
||||
|
||||
/* Macros to test type */
|
||||
#define ttisnil(o) (ttype(o) == LUA_TNIL)
|
||||
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
|
||||
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
|
||||
#define ttistable(o) (ttype(o) == LUA_TTABLE)
|
||||
#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION)
|
||||
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
|
||||
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
|
||||
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
|
||||
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
|
||||
#define ttisrotable(o) (ttype(o) == LUA_TROTABLE)
|
||||
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
|
||||
|
||||
#define ttisnil(o) (ttype(o) == LUA_TNIL)
|
||||
#define ttisnumber(o) (ttype(o) == LUA_TNUMBER)
|
||||
#define ttisstring(o) (ttype(o) == LUA_TSTRING)
|
||||
#define ttistable(o) (ttnov(o) == LUA_TTABLE)
|
||||
#define ttisrwtable(o) (type(o) == LUA_TTABLE)
|
||||
#define ttisrotable(o) (ttype(o) & LUA_TISROTABLE)
|
||||
#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN)
|
||||
#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA)
|
||||
#define ttisthread(o) (ttype(o) == LUA_TTHREAD)
|
||||
#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA)
|
||||
#define ttislightfunction(o) (ttype(o) == LUA_TLIGHTFUNCTION)
|
||||
#define ttisclfunction(o) (ttype(o) == LUA_TFUNCTION)
|
||||
#define ttisfunction(o) (ttnov(o) == LUA_TFUNCTION)
|
||||
|
||||
/* Macros to access values */
|
||||
|
||||
#define ttype(o) ((void) (o)->value, (o)->tt)
|
||||
#define ttnov(o) ((void) (o)->value, ((o)->tt & LUA_TMASK))
|
||||
#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc)
|
||||
#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p)
|
||||
#define rvalue(o) check_exp(ttisrotable(o), (o)->value.p)
|
||||
#define fvalue(o) check_exp(ttislightfunction(o), (o)->value.p)
|
||||
#define fvalue(o) check_exp(ttislightfunction(o), (o)->value.p)
|
||||
#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n)
|
||||
#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts)
|
||||
#define tsvalue(o) (&rawtsvalue(o)->tsv)
|
||||
#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u)
|
||||
#define uvalue(o) (&rawuvalue(o)->uv)
|
||||
#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl)
|
||||
#define clvalue(o) check_exp(ttisclfunction(o), &(o)->value.gc->cl)
|
||||
#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h)
|
||||
#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b)
|
||||
#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th)
|
||||
@ -156,9 +161,6 @@ typedef struct lua_TValue {
|
||||
#define setpvalue(obj,x) \
|
||||
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTUSERDATA; }
|
||||
|
||||
#define setrvalue(obj,x) \
|
||||
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TROTABLE; }
|
||||
|
||||
#define setfvalue(obj,x) \
|
||||
{ void *i_x = (x); TValue *i_o=(obj); i_o->value.p=i_x; i_o->tt=LUA_TLIGHTFUNCTION; }
|
||||
|
||||
@ -192,7 +194,7 @@ typedef struct lua_TValue {
|
||||
#define sethvalue(L,obj,x) \
|
||||
{ GCObject *i_x = cast(GCObject *, (x)); \
|
||||
TValue *i_o=(obj); \
|
||||
i_o->value.gc=i_x; i_o->tt=LUA_TTABLE; \
|
||||
i_o->value.gc=i_x; i_o->tt=gettt(x); \
|
||||
checkliveness(G(L),i_o); }
|
||||
|
||||
#define setptvalue(L,obj,x) \
|
||||
@ -227,7 +229,7 @@ typedef struct lua_TValue {
|
||||
|
||||
#define setttype(obj, stt) ((void) (obj)->value, (obj)->tt = (stt))
|
||||
|
||||
#define iscollectable(o) (ttype(o) >= LUA_TSTRING)
|
||||
#define iscollectable(o) (ttype(o) >= LUA_TSTRING && ttype(o) <= LUA_TMASK)
|
||||
|
||||
|
||||
typedef TValue *StkId; /* index to stack elements */
|
||||
@ -245,19 +247,10 @@ typedef union TString {
|
||||
} tsv;
|
||||
} TString;
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
#define isreadonly(o) (0)
|
||||
#else
|
||||
#define isreadonly(o) ((o).marked & READONLYMASK)
|
||||
#endif
|
||||
#define ts_isreadonly(ts) isreadonly((ts)->tsv)
|
||||
#define getstr(ts) (ts_isreadonly(ts) ? \
|
||||
cast(const char *, *(const char**)((ts) + 1)) : \
|
||||
cast(const char *, (ts) + 1))
|
||||
#define getstr(ts) cast(const char *, (ts) + 1)
|
||||
#define svalue(o) getstr(rawtsvalue(o))
|
||||
|
||||
|
||||
|
||||
typedef union Udata {
|
||||
L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */
|
||||
struct {
|
||||
@ -268,7 +261,12 @@ typedef union Udata {
|
||||
} uv;
|
||||
} Udata;
|
||||
|
||||
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
#define isreadonly(o) (0)
|
||||
#else
|
||||
#define isreadonly(o) (getmarked(o) & READONLYMASK)
|
||||
#endif
|
||||
#define islfs(o) (getmarked(o) & LFSMASK)
|
||||
|
||||
|
||||
/*
|
||||
@ -279,20 +277,13 @@ typedef struct Proto {
|
||||
TValue *k; /* constants used by the function */
|
||||
Instruction *code;
|
||||
struct Proto **p; /* functions defined inside the function */
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
unsigned char *packedlineinfo;
|
||||
#else
|
||||
int *lineinfo; /* map from opcodes to source lines */
|
||||
#endif
|
||||
struct LocVar *locvars; /* information about local variables */
|
||||
TString **upvalues; /* upvalue names */
|
||||
TString *source;
|
||||
int sizeupvalues;
|
||||
int sizek; /* size of `k' */
|
||||
int sizecode;
|
||||
#ifndef LUA_OPTIMIZE_DEBUG
|
||||
int sizelineinfo;
|
||||
#endif
|
||||
int sizep; /* size of `p' */
|
||||
int sizelocvars;
|
||||
int linedefined;
|
||||
@ -303,7 +294,6 @@ typedef struct Proto {
|
||||
lu_byte is_vararg;
|
||||
lu_byte maxstacksize;
|
||||
} Proto;
|
||||
#define proto_isreadonly(p) isreadonly(*(p))
|
||||
|
||||
|
||||
/* masks for new-style vararg */
|
||||
@ -373,6 +363,18 @@ typedef union Closure {
|
||||
** Tables
|
||||
*/
|
||||
|
||||
/*
|
||||
** Common Table fields for both table versions (like CommonHeader in
|
||||
** macro form, to be included in table structure definitions).
|
||||
**
|
||||
** Note that the sethvalue() macro works much like the setsvalue()
|
||||
** macro and handles the abstracted type. the hvalue(o) macro can be
|
||||
** used to access CommonTable fields and rw Table fields
|
||||
*/
|
||||
|
||||
#define CommonTable CommonHeader; \
|
||||
lu_byte flags; lu_byte lsizenode; struct Table *metatable
|
||||
|
||||
typedef union TKey {
|
||||
struct {
|
||||
TValuefields;
|
||||
@ -390,10 +392,7 @@ typedef struct Node {
|
||||
|
||||
|
||||
typedef struct Table {
|
||||
CommonHeader;
|
||||
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
||||
lu_byte lsizenode; /* log2 of size of `node' array */
|
||||
struct Table *metatable;
|
||||
CommonTable;
|
||||
TValue *array; /* array part */
|
||||
Node *node;
|
||||
Node *lastfree; /* any free position is before this position */
|
||||
@ -401,7 +400,23 @@ typedef struct Table {
|
||||
int sizearray; /* size of `array' array */
|
||||
} Table;
|
||||
|
||||
typedef const struct luaR_entry ROTable;
|
||||
GET_BYTE_FN(flags,Table,4,16)
|
||||
GET_BYTE_FN(lsizenode,Table,4,24)
|
||||
|
||||
typedef const struct ROTable_entry {
|
||||
const char *key;
|
||||
const TValue value;
|
||||
} ROTable_entry;
|
||||
|
||||
|
||||
typedef struct ROTable {
|
||||
/* next always has the value (GCObject *)((size_t) 1); */
|
||||
/* flags & 1<<p means tagmethod(p) is not present */
|
||||
/* lsizenode is unused */
|
||||
/* Like TStrings, the ROTable_entry vector follows the ROTable */
|
||||
CommonTable;
|
||||
ROTable_entry *entry;
|
||||
} ROTable;
|
||||
|
||||
/*
|
||||
** `module' operation for hashing (size is always a power of 2)
|
@ -6,9 +6,7 @@
|
||||
|
||||
#define lopcodes_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "luac_cross.h"
|
||||
#include "lopcodes.h"
|
||||
|
||||
/* ORDER OP */
|
@ -186,8 +186,8 @@ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
||||
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
||||
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
||||
|
||||
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
|
||||
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
||||
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
|
||||
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
|
||||
|
||||
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||
@ -197,8 +197,8 @@ OP_FORLOOP,/* A sBx R(A)+=R(A+2);
|
||||
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
|
||||
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
|
||||
|
||||
OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
|
||||
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
|
||||
OP_TFORLOOP,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
|
||||
if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++ */
|
||||
OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
|
||||
|
||||
OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/
|
||||
@ -240,7 +240,7 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
|
||||
** bits 4-5: B arg mode
|
||||
** bit 6: instruction set register A
|
||||
** bit 7: operator is a test
|
||||
*/
|
||||
*/
|
||||
|
||||
enum OpArgMask {
|
||||
OpArgN, /* argument is not used */
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lparser_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -344,12 +343,10 @@ static void open_func (LexState *ls, FuncState *fs) {
|
||||
fs->bl = NULL;
|
||||
f->source = ls->source;
|
||||
f->maxstacksize = 2; /* registers 0/1 are always valid */
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
fs->packedlineinfoSize = 0;
|
||||
fs->lastline = 0;
|
||||
fs->lastlineOffset = 0;
|
||||
fs->lineinfoLastPC = -1;
|
||||
#endif
|
||||
fs->h = luaH_new(L, 0, 0);
|
||||
/* anchor table of constants and prototype (to avoid being collected) */
|
||||
sethvalue2s(L, L->top, fs->h);
|
||||
@ -367,15 +364,9 @@ static void close_func (LexState *ls) {
|
||||
luaK_ret(fs, 0, 0); /* final return */
|
||||
luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
|
||||
f->sizecode = fs->pc;
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
f->packedlineinfo[fs->lastlineOffset+1]=0;
|
||||
luaM_reallocvector(L, f->packedlineinfo, fs->packedlineinfoSize,
|
||||
fs->lastlineOffset+2, unsigned char);
|
||||
#else
|
||||
luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);
|
||||
f->sizelineinfo = fs->pc;
|
||||
#endif
|
||||
|
||||
luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);
|
||||
f->sizek = fs->nk;
|
||||
luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);
|
||||
@ -392,20 +383,11 @@ static void close_func (LexState *ls) {
|
||||
L->top -= 2; /* remove table and prototype from the stack */
|
||||
}
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
static void compile_stripdebug(lua_State *L, Proto *f) {
|
||||
int level;
|
||||
lua_pushlightuserdata(L, &luaG_stripdebug );
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
level = lua_isnil(L, -1) ? LUA_OPTIMIZE_DEBUG : lua_tointeger(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (level > 1) {
|
||||
int len = luaG_stripdebug(L, f, level, 1);
|
||||
UNUSED(len);
|
||||
}
|
||||
int level = G(L)->stripdefault;
|
||||
if (level > 0)
|
||||
luaG_stripdebug(L, f, level, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
|
||||
@ -422,9 +404,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {
|
||||
chunk(&lexstate);
|
||||
check(&lexstate, TK_EOS);
|
||||
close_func(&lexstate);
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
compile_stripdebug(L, funcstate.f);
|
||||
#endif
|
||||
L->top--; /* remove 'name' from stack */
|
||||
lua_assert(funcstate.prev == NULL);
|
||||
lua_assert(funcstate.f->nups == 0);
|
@ -72,12 +72,10 @@ typedef struct FuncState {
|
||||
lu_byte nactvar; /* number of active local variables */
|
||||
upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */
|
||||
unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
int packedlineinfoSize; /* only used during compilation for line info */
|
||||
int lastline; /* ditto */
|
||||
int lastlineOffset; /* ditto */
|
||||
int lineinfoLastPC; /* ditto */
|
||||
#endif
|
||||
} FuncState;
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lstate_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
@ -35,7 +34,7 @@ typedef struct LG {
|
||||
lua_State l;
|
||||
global_State g;
|
||||
} LG;
|
||||
|
||||
|
||||
|
||||
|
||||
static void stack_init (lua_State *L1, lua_State *L) {
|
||||
@ -185,6 +184,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||
g->memlimit = 0;
|
||||
g->gcpause = LUAI_GCPAUSE;
|
||||
g->gcstepmul = LUAI_GCMUL;
|
||||
g->stripdefault = CONFIG_LUA_OPTIMIZE_DEBUG;
|
||||
g->gcdept = 0;
|
||||
#ifdef EGC_INITIAL_MODE
|
||||
g->egcmode = EGC_INITIAL_MODE;
|
||||
@ -197,13 +197,14 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||
g->memlimit = 0;
|
||||
#endif
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
g->ROstrt.size = 0;
|
||||
g->ROstrt.nuse = 0;
|
||||
g->ROstrt.hash = NULL;
|
||||
g->ROpvmain = NULL;
|
||||
g->LFSsize = 0;
|
||||
g->ROstrt.size = 0;
|
||||
g->ROstrt.nuse = 0;
|
||||
g->ROstrt.hash = NULL;
|
||||
g->ROpvmain = NULL;
|
||||
g->LFSsize = 0;
|
||||
g->error_reporter = 0;
|
||||
#endif
|
||||
for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;
|
||||
for (i=0; i<LUA_NUMTAGS; i++) g->mt[i] = NULL;
|
||||
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
|
||||
/* memory allocation error: free partial state */
|
||||
close_state(L);
|
||||
@ -225,20 +226,17 @@ extern lua_State *luaL_newstate (void);
|
||||
static lua_State *lua_crtstate;
|
||||
|
||||
lua_State *lua_open(void) {
|
||||
lua_crtstate = luaL_newstate();
|
||||
lua_crtstate = luaL_newstate();
|
||||
return lua_crtstate;
|
||||
}
|
||||
|
||||
lua_State *lua_getstate(void) {
|
||||
return lua_crtstate;
|
||||
}
|
||||
LUA_API void lua_close (lua_State *L) {
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
lua_sethook( L, NULL, 0, 0 );
|
||||
lua_crtstate = NULL;
|
||||
lua_pushnil( L );
|
||||
// lua_rawseti( L, LUA_REGISTRYINDEX, LUA_INT_HANDLER_KEY );
|
||||
#endif
|
||||
#endif
|
||||
L = G(L)->mainthread; /* only the main thread can be closed */
|
||||
lua_lock(L);
|
||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
@ -56,7 +56,7 @@ typedef struct CallInfo {
|
||||
|
||||
|
||||
|
||||
#define curr_func(L) (ttisfunction(L->ci->func) ? clvalue(L->ci->func) : NULL)
|
||||
#define curr_func(L) (ttisclfunction(L->ci->func) ? clvalue(L->ci->func) : NULL)
|
||||
#define ci_func(ci) (ttisfunction((ci)->func) ? clvalue((ci)->func) : NULL)
|
||||
#define f_isLua(ci) (!ttislightfunction((ci)->func) && !ci_func(ci)->c.isC)
|
||||
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
|
||||
@ -87,17 +87,19 @@ typedef struct global_State {
|
||||
lu_mem gcdept; /* how much GC is `behind schedule' */
|
||||
int gcpause; /* size of pause between successive GCs */
|
||||
int gcstepmul; /* GC `granularity' */
|
||||
int stripdefault; /* default stripping level for compilation */
|
||||
int egcmode; /* emergency garbage collection operation mode */
|
||||
lua_CFunction panic; /* to be called in unprotected errors */
|
||||
TValue l_registry;
|
||||
struct lua_State *mainthread;
|
||||
UpVal uvhead; /* head of double-linked list of all open upvalues */
|
||||
struct Table *mt[NUM_TAGS]; /* metatables for basic types */
|
||||
struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */
|
||||
TString *tmname[TM_N]; /* array with tag-method names */
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
stringtable ROstrt; /* Flash-based hash table for RO strings */
|
||||
Proto *ROpvmain; /* Flash-based Proto main */
|
||||
int LFSsize; /* Size of Lua Flash Store */
|
||||
int error_reporter; /* Registry Index of error reporter task */
|
||||
#endif
|
||||
} global_State;
|
||||
|
||||
@ -159,7 +161,7 @@ union GCObject {
|
||||
#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
|
||||
#define gco2u(o) (&rawgco2u(o)->uv)
|
||||
#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
|
||||
#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
|
||||
#define gco2h(o) check_exp(((o)->gch.tt & LUA_TMASK) == LUA_TTABLE, &((o)->h))
|
||||
#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
|
||||
#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
|
||||
#define ngcotouv(o) \
|
@ -8,7 +8,6 @@
|
||||
|
||||
#define lstring_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -18,8 +17,6 @@
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
|
||||
#define LUAS_READONLY_STRING 1
|
||||
#define LUAS_REGULAR_STRING 0
|
||||
|
||||
void luaS_resize (lua_State *L, int newsize) {
|
||||
stringtable *tb;
|
||||
@ -53,26 +50,20 @@ void luaS_resize (lua_State *L, int newsize) {
|
||||
}
|
||||
|
||||
static TString *newlstr (lua_State *L, const char *str, size_t l,
|
||||
unsigned int h, int readonly) {
|
||||
unsigned int h) {
|
||||
TString *ts;
|
||||
stringtable *tb;
|
||||
stringtable *tb = &G(L)->strt;
|
||||
if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
|
||||
luaM_toobig(L);
|
||||
tb = &G(L)->strt;
|
||||
if ((tb->nuse + 1) > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)
|
||||
luaS_resize(L, tb->size*2); /* too crowded */
|
||||
ts = cast(TString *, luaM_malloc(L, sizeof(TString) + (readonly ? sizeof(char**) : (l+1)*sizeof(char))));
|
||||
ts = cast(TString *, luaM_malloc(L, sizeof(TString) + (l+1)*sizeof(char)));
|
||||
ts->tsv.len = l;
|
||||
ts->tsv.hash = h;
|
||||
ts->tsv.marked = luaC_white(G(L));
|
||||
ts->tsv.tt = LUA_TSTRING;
|
||||
if (!readonly) {
|
||||
memcpy(ts+1, str, l*sizeof(char));
|
||||
((char *)(ts+1))[l] = '\0'; /* ending 0 */
|
||||
} else {
|
||||
*(char **)(ts+1) = (char *)str;
|
||||
l_setbit((ts)->tsv.marked, READONLYBIT);
|
||||
}
|
||||
memcpy(ts+1, str, l*sizeof(char));
|
||||
((char *)(ts+1))[l] = '\0'; /* ending 0 */
|
||||
h = lmod(h, tb->size);
|
||||
ts->tsv.next = tb->hash[h]; /* chain new entry */
|
||||
tb->hash[h] = obj2gco(ts);
|
||||
@ -80,15 +71,6 @@ static TString *newlstr (lua_State *L, const char *str, size_t l,
|
||||
return ts;
|
||||
}
|
||||
|
||||
static int lua_is_ptr_in_ro_area(const char *p) {
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
(void)p;
|
||||
return 0; // TStrings are never in RO in luac.cross
|
||||
#else
|
||||
return IN_RODATA_AREA(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The string algorithm has been modified to be LFS-friendly. The previous eLua
|
||||
* algo used the address of the string was in flash and the string was >4 bytes
|
||||
@ -129,11 +111,7 @@ LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* New additions to the RAM strt are tagged as readonly if the string address
|
||||
* is in the CTEXT segment (target only, not luac.cross) */
|
||||
int readonly = (lua_is_ptr_in_ro_area(str) && l+1 > sizeof(char**) &&
|
||||
l == strlen(str) ? LUAS_READONLY_STRING : LUAS_REGULAR_STRING);
|
||||
return newlstr(L, str, l, h, readonly); /* not found */
|
||||
return newlstr(L, str, l, h); /* not found */
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,7 @@
|
||||
#include "lstate.h"
|
||||
|
||||
|
||||
#define sizestring(s) (sizeof(union TString)+(testbit(getmarked(s), READONLYBIT) ? sizeof(char **) : ((s)->len+1)*sizeof(char)))
|
||||
|
||||
#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
|
||||
#define sizeudata(u) (sizeof(union Udata)+(u)->len)
|
||||
|
||||
#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lstrlib_c
|
||||
#define LUA_LIB
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdio.h>
|
||||
@ -15,13 +14,11 @@
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
/* macro to `unsign' a character */
|
||||
#define uchar(c) ((unsigned char)(c))
|
||||
|
||||
|
||||
|
||||
static int str_len (lua_State *L) {
|
||||
size_t l;
|
||||
luaL_checklstring(L, 1, &l);
|
||||
@ -143,17 +140,25 @@ static int writer (lua_State *L, const void* b, size_t size, void* B) {
|
||||
|
||||
static int str_dump (lua_State *L) {
|
||||
luaL_Buffer b;
|
||||
int strip, tstrip = lua_type(L, 2);
|
||||
if (tstrip == LUA_TBOOLEAN) {
|
||||
strip = lua_toboolean(L, 2) ? 2 : 0;
|
||||
} else if (tstrip == LUA_TNONE || tstrip == LUA_TNIL) {
|
||||
strip = -1; /* This tells lua_dump to use the global strip default */
|
||||
} else {
|
||||
strip = lua_tointeger(L, 2);
|
||||
luaL_argcheck(L, (unsigned)(strip) < 3, 2, "strip out of range");
|
||||
}
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
lua_settop(L, 1);
|
||||
luaL_buffinit(L,&b);
|
||||
if (lua_dump(L, writer, &b) != 0)
|
||||
luaL_error(L, "unable to dump given function");
|
||||
if (lua_dump(L, writer, &b, strip) != 0)
|
||||
return luaL_error(L, "unable to dump given function");
|
||||
luaL_pushresult(&b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** PATTERN MATCHING
|
||||
@ -634,7 +639,7 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
|
||||
lua_pushlstring(L, s, e - s); /* keep original text */
|
||||
}
|
||||
else if (!lua_isstring(L, -1))
|
||||
luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
|
||||
luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
|
||||
luaL_addvalue(b); /* add result to accumulator */
|
||||
}
|
||||
|
||||
@ -787,7 +792,7 @@ static int str_format (lua_State *L) {
|
||||
sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
|
||||
break;
|
||||
}
|
||||
#if !defined LUA_NUMBER_INTEGRAL
|
||||
#if !defined LUA_NUMBER_INTEGRAL
|
||||
case 'e': case 'E': case 'f':
|
||||
case 'g': case 'G': {
|
||||
sprintf(buff, form, (double)luaL_checknumber(L, arg));
|
||||
@ -825,7 +830,21 @@ static int str_format (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
LROT_PUBLIC_BEGIN(strlib)
|
||||
static int str_format2 (lua_State *L) {
|
||||
if (lua_type(L, 2) == LUA_TTABLE) {
|
||||
int i,n=lua_objlen(L,2);
|
||||
lua_settop(L,2);
|
||||
for (i = 1; i <= n; i++)
|
||||
lua_rawgeti(L, 2, i);
|
||||
lua_remove(L, 2);
|
||||
}
|
||||
return str_format(L);
|
||||
}
|
||||
|
||||
|
||||
LROT_BEGIN(strlib, NULL, LROT_MASK_INDEX)
|
||||
LROT_TABENTRY( __index, strlib )
|
||||
LROT_FUNCENTRY( __mod, str_format2 )
|
||||
LROT_FUNCENTRY( byte, str_byte )
|
||||
LROT_FUNCENTRY( char, str_char )
|
||||
LROT_FUNCENTRY( dump, str_dump )
|
||||
@ -845,8 +864,7 @@ LROT_PUBLIC_BEGIN(strlib)
|
||||
LROT_FUNCENTRY( reverse, str_reverse )
|
||||
LROT_FUNCENTRY( sub, str_sub )
|
||||
LROT_FUNCENTRY( upper, str_upper )
|
||||
LROT_TABENTRY( __index, strlib )
|
||||
LROT_END(strlib, NULL, 0) // OR DO WE NEED LRTO_MASK_INDEX **TODO**
|
||||
LROT_END(strlib, NULL, LROT_MASK_INDEX)
|
||||
|
||||
/*
|
||||
** Open string library
|
@ -20,7 +20,6 @@
|
||||
|
||||
#define ltable_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <math.h>
|
||||
@ -33,7 +32,8 @@
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "ltable.h"
|
||||
#include "lrotable.h"
|
||||
#include "lstring.h"
|
||||
|
||||
|
||||
/*
|
||||
** max size of array part is 2^MAXBITS
|
||||
@ -48,7 +48,7 @@
|
||||
|
||||
|
||||
#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
|
||||
|
||||
|
||||
#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
|
||||
#define hashboolean(t,p) hashpow2(t, p)
|
||||
|
||||
@ -68,6 +68,10 @@
|
||||
*/
|
||||
#define numints cast_int(sizeof(lua_Number)/sizeof(int))
|
||||
|
||||
static const TValue* rotable_findentry(ROTable *rotable, TString *key, unsigned *ppos);
|
||||
static void rotable_next_helper(lua_State *L, ROTable *pentries, int pos,
|
||||
TValue *key, TValue *val);
|
||||
static void rotable_next(lua_State *L, ROTable *rotable, TValue *key, TValue *val);
|
||||
|
||||
|
||||
#define dummynode (&dummynode_)
|
||||
@ -105,11 +109,11 @@ static Node *mainposition (const Table *t, const TValue *key) {
|
||||
return hashstr(t, rawtsvalue(key));
|
||||
case LUA_TBOOLEAN:
|
||||
return hashboolean(t, bvalue(key));
|
||||
case LUA_TROTABLE:
|
||||
return hashpointer(t, rvalue(key));
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
case LUA_TLIGHTFUNCTION:
|
||||
return hashpointer(t, pvalue(key));
|
||||
case LUA_TROTABLE:
|
||||
return hashpointer(t, hvalue(key));
|
||||
default:
|
||||
return hashpointer(t, gcvalue(key));
|
||||
}
|
||||
@ -163,7 +167,12 @@ static int findindex (lua_State *L, Table *t, StkId key) {
|
||||
|
||||
|
||||
int luaH_next (lua_State *L, Table *t, StkId key) {
|
||||
int i = findindex(L, t, key); /* find original element */
|
||||
int i;
|
||||
if (isrotable(t)) {
|
||||
rotable_next(L, (ROTable *) t, key, key+1);
|
||||
return ttisnil(key) ? 0 : 1;
|
||||
}
|
||||
i = findindex(L, t, key); /* find original element */
|
||||
for (i++; i < t->sizearray; i++) { /* try first array part */
|
||||
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
|
||||
setnvalue(key, cast_num(i+1));
|
||||
@ -182,12 +191,6 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
|
||||
}
|
||||
|
||||
|
||||
int luaH_next_ro (lua_State *L, void *t, StkId key) {
|
||||
luaR_next(L, t, key, key+1);
|
||||
return ttisnil(key) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {=============================================================
|
||||
** Rehash
|
||||
@ -330,7 +333,7 @@ static Node *find_prev_node(Node *mp, Node *next) {
|
||||
** first, check whether the moving node's main position is free. If not, check whether
|
||||
** colliding node is in its main position or not: if it is not, move colliding
|
||||
** node to an empty place and put moving node in its main position; otherwise
|
||||
** (colliding node is in its main position), moving node goes to an empty position.
|
||||
** (colliding node is in its main position), moving node goes to an empty position.
|
||||
*/
|
||||
static int move_node (lua_State *L, Table *t, Node *node) {
|
||||
(void)L;
|
||||
@ -372,7 +375,7 @@ static int move_node (lua_State *L, Table *t, Node *node) {
|
||||
|
||||
|
||||
static int move_number (lua_State *L, Table *t, Node *node) {
|
||||
(void)L; (void)t;
|
||||
(void)L;
|
||||
int key;
|
||||
lua_Number n = nvalue(key2tval(node));
|
||||
lua_number2int(key, n);
|
||||
@ -565,6 +568,8 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) {
|
||||
** search function for integers
|
||||
*/
|
||||
const TValue *luaH_getnum (Table *t, int key) {
|
||||
if (isrotable(t))
|
||||
return luaO_nilobject;
|
||||
/* (1 <= key && key <= t->sizearray) */
|
||||
if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))
|
||||
return &t->array[key-1];
|
||||
@ -580,18 +585,16 @@ const TValue *luaH_getnum (Table *t, int key) {
|
||||
}
|
||||
}
|
||||
|
||||
/* same thing for rotables */
|
||||
const TValue *luaH_getnum_ro (void *t, int key) {
|
||||
(void)t; (void)key;
|
||||
const TValue *res = NULL; // integer values not supported: luaR_findentryN(t, key, NULL);
|
||||
return res ? res : luaO_nilobject;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** search function for strings
|
||||
*/
|
||||
const TValue *luaH_getstr (Table *t, TString *key) {
|
||||
|
||||
if (isrotable(t)) {
|
||||
if (key->tsv.len>LUA_MAX_ROTABLE_NAME)
|
||||
return luaO_nilobject;
|
||||
return rotable_findentry((ROTable*) t, key, NULL);
|
||||
}
|
||||
Node *n = hashstr(t, key);
|
||||
do { /* check whether `key' is somewhere in the chain */
|
||||
if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)
|
||||
@ -601,65 +604,41 @@ const TValue *luaH_getstr (Table *t, TString *key) {
|
||||
return luaO_nilobject;
|
||||
}
|
||||
|
||||
/* same thing for rotables */
|
||||
const TValue *luaH_getstr_ro (void *t, TString *key) {
|
||||
if (!t || key->tsv.len>LUA_MAX_ROTABLE_NAME)
|
||||
return luaO_nilobject;
|
||||
return luaR_findentry(t, key, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** main search function
|
||||
*/
|
||||
const TValue *luaH_get (Table *t, const TValue *key) {
|
||||
switch (ttype(key)) {
|
||||
case LUA_TNIL: return luaO_nilobject;
|
||||
case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));
|
||||
case LUA_TNUMBER: {
|
||||
int k;
|
||||
lua_Number n = nvalue(key);
|
||||
lua_number2int(k, n);
|
||||
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
|
||||
return luaH_getnum(t, k); /* use specialized version */
|
||||
/* else go through */
|
||||
}
|
||||
/* fall-through */
|
||||
default: {
|
||||
Node *n = mainposition(t, key);
|
||||
do { /* check whether `key' is somewhere in the chain */
|
||||
if (luaO_rawequalObj(key2tval(n), key))
|
||||
return gval(n); /* that's it */
|
||||
else n = gnext(n);
|
||||
} while (n);
|
||||
return luaO_nilobject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* same thing for rotables */
|
||||
const TValue *luaH_get_ro (void *t, const TValue *key) {
|
||||
switch (ttype(key)) {
|
||||
case LUA_TNIL: return luaO_nilobject;
|
||||
case LUA_TSTRING: return luaH_getstr_ro(t, rawtsvalue(key));
|
||||
case LUA_TNUMBER: {
|
||||
int k;
|
||||
lua_Number n = nvalue(key);
|
||||
lua_number2int(k, n);
|
||||
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
|
||||
return luaH_getnum_ro(t, k); /* use specialized version */
|
||||
/* else go through */
|
||||
}
|
||||
/* fall-through */
|
||||
default: {
|
||||
return luaO_nilobject;
|
||||
}
|
||||
int type = ttype(key);
|
||||
if (type == LUA_TNIL)
|
||||
return luaO_nilobject;
|
||||
if (type == LUA_TSTRING)
|
||||
return luaH_getstr(t, rawtsvalue(key));
|
||||
if (isrotable(t))
|
||||
return luaO_nilobject;
|
||||
if (type == LUA_TNUMBER) {
|
||||
int k;
|
||||
lua_Number n = nvalue(key);
|
||||
lua_number2int(k, n);
|
||||
if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */
|
||||
return luaH_getnum(t, k); /* use specialized version */
|
||||
}
|
||||
/* default */
|
||||
Node *n = mainposition(t, key);
|
||||
do { /* check whether `key' is somewhere in the chain */
|
||||
if (luaO_rawequalObj(key2tval(n), key))
|
||||
return gval(n); /* that's it */
|
||||
else n = gnext(n);
|
||||
} while (n);
|
||||
return luaO_nilobject;
|
||||
}
|
||||
|
||||
|
||||
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
|
||||
const TValue *p = luaH_get(t, key);
|
||||
const TValue *p;
|
||||
if (isrotable(t))
|
||||
luaG_runerror(L, "table is readonly");
|
||||
p = luaH_get(t, key);
|
||||
t->flags = 0;
|
||||
if (p != luaO_nilobject)
|
||||
return cast(TValue *, p);
|
||||
@ -673,7 +652,10 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
|
||||
|
||||
|
||||
TValue *luaH_setnum (lua_State *L, Table *t, int key) {
|
||||
const TValue *p = luaH_getnum(t, key);
|
||||
const TValue *p;
|
||||
if (isrotable(t))
|
||||
luaG_runerror(L, "table is readonly");
|
||||
p = luaH_getnum(t, key);
|
||||
if (p != luaO_nilobject)
|
||||
return cast(TValue *, p);
|
||||
else {
|
||||
@ -685,7 +667,10 @@ TValue *luaH_setnum (lua_State *L, Table *t, int key) {
|
||||
|
||||
|
||||
TValue *luaH_setstr (lua_State *L, Table *t, TString *key) {
|
||||
const TValue *p = luaH_getstr(t, key);
|
||||
const TValue *p;
|
||||
if (isrotable(t))
|
||||
luaG_runerror(L, "table is readonly");
|
||||
p = luaH_getstr(t, key);
|
||||
if (p != luaO_nilobject)
|
||||
return cast(TValue *, p);
|
||||
else {
|
||||
@ -725,7 +710,10 @@ static int unbound_search (Table *t, unsigned int j) {
|
||||
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
|
||||
*/
|
||||
int luaH_getn (Table *t) {
|
||||
unsigned int j = t->sizearray;
|
||||
unsigned int j;
|
||||
if(isrotable(t))
|
||||
return 0;
|
||||
j = t->sizearray;
|
||||
if (j > 0 && ttisnil(&t->array[j - 1])) {
|
||||
/* there is a boundary in the array part: (binary) search for it */
|
||||
unsigned int i = 0;
|
||||
@ -742,14 +730,138 @@ int luaH_getn (Table *t) {
|
||||
else return unbound_search(t, j);
|
||||
}
|
||||
|
||||
/* same thing for rotables */
|
||||
int luaH_getn_ro (void *t) {
|
||||
(void)t;
|
||||
return 0; // Integer Keys are not currently supported for ROTables
|
||||
}
|
||||
|
||||
int luaH_isdummy (Node *n) { return n == dummynode; }
|
||||
|
||||
|
||||
/*
|
||||
** All keyed ROTable access passes through rotable_findentry(). ROTables
|
||||
** are simply a list of <key><TValue value> pairs.
|
||||
**
|
||||
** The global KeyCache is used to avoid a relatively expensive Flash memory
|
||||
** vector scan. A simple hash on the key's TString addr and the ROTable
|
||||
** addr selects the cache line. The line's slots are then scanned for a
|
||||
** hit.
|
||||
**
|
||||
** Unlike the standard hast which uses a prime line count therefore requires
|
||||
** the use of modulus operation which is expensive on an IoT processor
|
||||
** without H/W divide. This hash is power of 2 based which might not be
|
||||
** quite so uniform but can be calcuated without using H/W-based instructions.
|
||||
**
|
||||
** If a match is found and the table addresses match, then this entry is
|
||||
** probed first. In practice the hit-rate here is over 99% so the code
|
||||
** rarely fails back to doing the linear scan in ROM.
|
||||
** Note that this hash does a couple of prime multiples and a modulus 2^X
|
||||
** with is all evaluated in H/W, and adequately randomizes the lookup.
|
||||
*/
|
||||
#define LA_LINES 32
|
||||
#define LA_SLOTS 4
|
||||
static size_t cache [LA_LINES][LA_SLOTS];
|
||||
|
||||
#define HASH(a,b) ((((29*(size_t)(a)) ^ (37*((b)->tsv.hash)))>>4) % LA_LINES)
|
||||
#define NDX_SHFT 24
|
||||
#define ADDR_MASK (((size_t) 1<<24)-1)
|
||||
|
||||
/*
|
||||
* Find a string key entry in a rotable and return it. Note that this internally
|
||||
* uses a null key to denote a metatable search.
|
||||
*/
|
||||
static const TValue* rotable_findentry(ROTable *t, TString *key, unsigned *ppos) {
|
||||
const ROTable_entry *e = cast(const ROTable_entry *, t->entry);
|
||||
const int tl = getlsizenode(t);
|
||||
const char *strkey = getstr(key);
|
||||
size_t *cl = cache[HASH(t, key)];
|
||||
int i, j = 1, l;
|
||||
|
||||
if (!e || gettt(key) != LUA_TSTRING)
|
||||
return luaO_nilobject;
|
||||
|
||||
l = key->tsv.len;
|
||||
/* scan the ROTable lookaside cache and return if hit found */
|
||||
for (i=0; i<LA_SLOTS; i++) {
|
||||
int cl_ndx = cl[i] >> NDX_SHFT;
|
||||
if ((((size_t)t - cl[i]) & ADDR_MASK) == 0 && cl_ndx < tl &&
|
||||
strcmp(e[cl_ndx].key, strkey) == 0) {
|
||||
if (ppos)
|
||||
*ppos = cl_ndx;
|
||||
return &e[cl_ndx].value;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A lot of search misses are metavalues, but tables typically only have at
|
||||
* most a couple of them, so these are always put at the front of the table
|
||||
* in ascending order and the metavalue scan short circuits using a straight
|
||||
* strcmp()
|
||||
*/
|
||||
lu_int32 name4 = *(lu_int32 *) strkey;
|
||||
if (*(char*)&name4 == '_') {
|
||||
for(i = 0; i < tl; i++) {
|
||||
j = strcmp(e[i].key, strkey);
|
||||
if (j>=0)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Ordinary (non-meta) keys can be unsorted. This is for legacy compatiblity,
|
||||
* plus misses are pretty rare in this case. The masked name4 comparison is
|
||||
* safe 4-byte comparison that nearly always avoids the more costly strcmp()
|
||||
* for an actual hit validation.
|
||||
*/
|
||||
lu_int32 mask4 = l > 2 ? (~0u) : (~0u)>>((3-l)*8);
|
||||
for(i = 0; i < tl; i++) {
|
||||
if (((*(lu_int32 *)e[i].key ^ name4) & mask4) != 0)
|
||||
continue;
|
||||
j = strcmp(e[i].key, strkey);
|
||||
if (j==0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j)
|
||||
return luaO_nilobject;
|
||||
if (ppos)
|
||||
*ppos = i;
|
||||
/* In the case of a hit, update the lookaside cache */
|
||||
for (j = LA_SLOTS-1; j>0; j--)
|
||||
cl[j] = cl[j-1];
|
||||
cl[0] = ((size_t)t & ADDR_MASK) + (i << NDX_SHFT);
|
||||
return &e[i].value;
|
||||
}
|
||||
|
||||
|
||||
static void rotable_next_helper(lua_State *L, ROTable *t, int pos,
|
||||
TValue *key, TValue *val) {
|
||||
const ROTable_entry *e = cast(const ROTable_entry *, t->entry);
|
||||
if (pos < getlsizenode(t)) {
|
||||
/* Found an entry */
|
||||
setsvalue(L, key, luaS_new(L, e[pos].key));
|
||||
setobj2s(L, val, &e[pos].value);
|
||||
} else {
|
||||
setnilvalue(key);
|
||||
setnilvalue(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* next (used for iteration) */
|
||||
static void rotable_next(lua_State *L, ROTable *t, TValue *key, TValue *val) {
|
||||
unsigned keypos = getlsizenode(t);
|
||||
|
||||
/* Special case: if key is nil, return the first element of the rotable */
|
||||
if (ttisnil(key))
|
||||
rotable_next_helper(L, t, 0, key, val);
|
||||
else if (ttisstring(key)) {
|
||||
/* Find the previous key again */
|
||||
if (ttisstring(key)) {
|
||||
rotable_findentry(t, rawtsvalue(key), &keypos);
|
||||
}
|
||||
/* Advance to next key */
|
||||
rotable_next_helper(L, t, ++keypos, key, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(LUA_DEBUG)
|
||||
Node *luaH_mainposition (const Table *t, const TValue *key) {
|
||||
return mainposition(t, key);
|
@ -16,26 +16,24 @@
|
||||
#define gnext(n) ((n)->i_key.nk.next)
|
||||
|
||||
#define key2tval(n) (&(n)->i_key.tvk)
|
||||
|
||||
#define isrotable(t) (gettt(t)==LUA_TROTABLE)
|
||||
#define isrwtable(t) (gettt(t)==LUA_TTABLE)
|
||||
|
||||
LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
|
||||
LUAI_FUNC const TValue *luaH_getnum_ro (void *t, int key);
|
||||
LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
|
||||
LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
|
||||
LUAI_FUNC const TValue *luaH_getstr_ro (void *t, TString *key);
|
||||
LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
|
||||
LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
|
||||
LUAI_FUNC const TValue *luaH_get_ro (void *t, const TValue *key);
|
||||
LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
|
||||
LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
|
||||
LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
|
||||
LUAI_FUNC void luaH_free (lua_State *L, Table *t);
|
||||
LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
|
||||
LUAI_FUNC int luaH_next_ro (lua_State *L, void *t, StkId key);
|
||||
LUAI_FUNC int luaH_getn (Table *t);
|
||||
LUAI_FUNC int luaH_getn_ro (void *t);
|
||||
LUAI_FUNC int luaH_isdummy (Node *n);
|
||||
|
||||
#define LUA_MAX_ROTABLE_NAME 32
|
||||
|
||||
#if defined(LUA_DEBUG)
|
||||
LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
|
||||
#endif
|
@ -7,13 +7,11 @@
|
||||
|
||||
#define ltablib_c
|
||||
#define LUA_LIB
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
|
||||
#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))
|
||||
@ -22,7 +20,7 @@
|
||||
static int foreachi (lua_State *L) {
|
||||
int i;
|
||||
int n = aux_getn(L, 1);
|
||||
luaL_checkanyfunction(L, 2);
|
||||
luaL_checkfunction(L, 2);
|
||||
for (i=1; i <= n; i++) {
|
||||
lua_pushvalue(L, 2); /* function */
|
||||
lua_pushinteger(L, i); /* 1st argument */
|
||||
@ -38,7 +36,7 @@ static int foreachi (lua_State *L) {
|
||||
|
||||
static int foreach (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkanyfunction(L, 2);
|
||||
luaL_checkfunction(L, 2);
|
||||
lua_pushnil(L); /* first key */
|
||||
while (lua_next(L, 1)) {
|
||||
lua_pushvalue(L, 2); /* function */
|
||||
@ -266,7 +264,7 @@ static int sort (lua_State *L) {
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
LROT_PUBLIC_BEGIN(tab_funcs)
|
||||
LROT_BEGIN(tab_funcs, NULL, 0)
|
||||
LROT_FUNCENTRY( concat, tconcat )
|
||||
LROT_FUNCENTRY( foreach, foreach )
|
||||
LROT_FUNCENTRY( foreachi, foreachi )
|
@ -5,37 +5,35 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ltm_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lgc.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "ltm.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
|
||||
/* These must be correspond to the LUA_T* defines in lua.h */
|
||||
|
||||
const char *const luaT_typenames[] = {
|
||||
"nil", "boolean", "romtable", "lightfunction", "userdata", "number",
|
||||
"string", "table", "function", "userdata", "thread",
|
||||
"nil", "boolean", "lightfunction","number", // base type = 0, 1, 2, 3
|
||||
"string", "table", "function", "userdata", "thread", // base type = 4, 5, 6, 7, 8
|
||||
"proto", "upval"
|
||||
};
|
||||
|
||||
|
||||
void luaT_init (lua_State *L) {
|
||||
static const char *const luaT_eventname[] = { /* ORDER TM */
|
||||
"__index", "__newindex",
|
||||
"__gc", "__mode", "__eq",
|
||||
"__add", "__sub", "__mul", "__div", "__mod",
|
||||
"__pow", "__unm", "__len", "__lt", "__le",
|
||||
"__concat", "__call"
|
||||
"__concat", "__call",
|
||||
"__metatable"
|
||||
};
|
||||
int i;
|
||||
for (i=0; i<TM_N; i++) {
|
||||
@ -50,22 +48,14 @@ void luaT_init (lua_State *L) {
|
||||
** tag methods
|
||||
*/
|
||||
const TValue *luaT_gettm (Table *events, TMS event, TString *ename) {
|
||||
const TValue *tm;
|
||||
const TValue *tm = luaH_getstr(events, ename);
|
||||
lua_assert(event <= TM_EQ);
|
||||
|
||||
if (luaR_isrotable(events)) {
|
||||
tm = luaH_getstr_ro(events, ename);
|
||||
if (ttisnil(tm)) { /* no tag method? */
|
||||
if (isrwtable(events)) /* if this a (RW) Table */
|
||||
events->flags |= cast_byte(1u<<event); /* then cache this fact */
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
tm = luaH_getstr(events, ename);
|
||||
if (ttisnil(tm)) { /* no tag method? */
|
||||
events->flags |= cast_byte(1u<<event); /* cache this fact */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return tm;
|
||||
else return tm;
|
||||
}
|
||||
|
||||
|
||||
@ -73,21 +63,14 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
|
||||
Table *mt;
|
||||
switch (ttype(o)) {
|
||||
case LUA_TTABLE:
|
||||
mt = hvalue(o)->metatable;
|
||||
break;
|
||||
case LUA_TROTABLE:
|
||||
mt = (Table*)luaR_getmeta(rvalue(o));
|
||||
mt = hvalue(o)->metatable;
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
mt = uvalue(o)->metatable;
|
||||
break;
|
||||
default:
|
||||
mt = G(L)->mt[ttype(o)];
|
||||
mt = G(L)->mt[ttnov(o)];
|
||||
}
|
||||
if (!mt)
|
||||
return luaO_nilobject;
|
||||
else if (luaR_isrotable(mt))
|
||||
return luaH_getstr_ro(mt, G(L)->tmname[event]);
|
||||
else
|
||||
return luaH_getstr(mt, G(L)->tmname[event]);
|
||||
return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
|
||||
}
|
@ -7,10 +7,6 @@
|
||||
#ifndef ltm_h
|
||||
#define ltm_h
|
||||
|
||||
|
||||
#include "lobject.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
/*
|
||||
* WARNING: if you change the order of this enumeration,
|
||||
* grep "ORDER TM"
|
||||
@ -33,13 +29,16 @@ typedef enum {
|
||||
TM_LE,
|
||||
TM_CONCAT,
|
||||
TM_CALL,
|
||||
TM_METATABLE,
|
||||
TM_N /* number of elements in the enum */
|
||||
} TMS;
|
||||
|
||||
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
|
||||
(!luaR_isrotable(et) && ((et)->flags & (1u<<(e)))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
|
||||
//#include "lobject.h"
|
||||
|
||||
#define fasttm(l,et,e) gfasttm(G(l), et, e)
|
||||
#define gfasttm(g,et,e) ((et) == NULL ? NULL : \
|
||||
(getflags(et) & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))
|
||||
|
||||
#define fasttm(l,et,e) gfasttm(G(l), et, e)
|
||||
|
||||
LUAI_DATA const char *const luaT_typenames[];
|
||||
|
5
components/lua/lua-5.1/lua.c
Normal file
5
components/lua/lua-5.1/lua.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include "llimits.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#define LUA_VERSION_51
|
||||
#include "../lua-5.3/lua.c"
|
@ -8,13 +8,11 @@
|
||||
|
||||
#ifndef lua_h
|
||||
#define lua_h
|
||||
#ifdef LUAC_CROSS_FILE
|
||||
#include "luac_cross.h"
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "luaconf.h"
|
||||
|
||||
|
||||
@ -41,7 +39,8 @@
|
||||
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
|
||||
|
||||
|
||||
/* thread status; 0 is OK */
|
||||
/* thread status */
|
||||
#define LUA_OK 0
|
||||
#define LUA_YIELD 1
|
||||
#define LUA_ERRRUN 2
|
||||
#define LUA_ERRSYNTAX 3
|
||||
@ -72,18 +71,22 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||
** basic types
|
||||
*/
|
||||
#define LUA_TNONE (-1)
|
||||
|
||||
#define LUA_TNIL 0
|
||||
#define LUA_TBOOLEAN 1
|
||||
#define LUA_TROTABLE 2
|
||||
#define LUA_TLIGHTFUNCTION 3
|
||||
#define LUA_TLIGHTUSERDATA 4
|
||||
#define LUA_TNUMBER 5
|
||||
#define LUA_TSTRING 6
|
||||
#define LUA_TTABLE 7
|
||||
#define LUA_TFUNCTION 8
|
||||
#define LUA_TUSERDATA 9
|
||||
#define LUA_TTHREAD 10
|
||||
#define LUA_TLIGHTUSERDATA 2
|
||||
#define LUA_TNUMBER 3
|
||||
#define LUA_TSTRING 4
|
||||
#define LUA_TTABLE 5
|
||||
#define LUA_TFUNCTION 6
|
||||
#define LUA_TUSERDATA 7
|
||||
#define LUA_TTHREAD 8
|
||||
|
||||
#define LUA_TISROTABLE (1<<4)
|
||||
#define LUA_TISLIGHTFUNC (1<<5)
|
||||
#define LUA_TMASK 15
|
||||
|
||||
#define LUA_TROTABLE (LUA_TTABLE + LUA_TISROTABLE)
|
||||
#define LUA_TLIGHTFUNCTION (LUA_TFUNCTION + LUA_TISLIGHTFUNC)
|
||||
|
||||
/* minimum Lua stack available to a C function */
|
||||
#define LUA_MINSTACK 20
|
||||
@ -96,18 +99,14 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||
#include LUA_USER_H
|
||||
#endif
|
||||
|
||||
#if defined(LUA_OPTIMIZE_DEBUG) && LUA_OPTIMIZE_DEBUG == 0
|
||||
#undef LUA_OPTIMIZE_DEBUG
|
||||
#endif
|
||||
|
||||
/* type of numbers in Lua */
|
||||
typedef LUA_NUMBER lua_Number;
|
||||
typedef LUA_FLOAT lua_Float;
|
||||
|
||||
|
||||
/* type for integer functions */
|
||||
typedef LUA_INTEGER lua_Integer;
|
||||
|
||||
|
||||
typedef LUAI_UINT32 lua_Unsigned;
|
||||
|
||||
/*
|
||||
** state manipulation
|
||||
@ -122,6 +121,7 @@ LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||
/*
|
||||
** basic stack manipulation
|
||||
*/
|
||||
LUA_API int (lua_absindex) (lua_State *L, int idx);
|
||||
LUA_API int (lua_gettop) (lua_State *L);
|
||||
LUA_API void (lua_settop) (lua_State *L, int idx);
|
||||
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
|
||||
@ -142,11 +142,14 @@ LUA_API int (lua_isstring) (lua_State *L, int idx);
|
||||
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
|
||||
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
|
||||
LUA_API int (lua_type) (lua_State *L, int idx);
|
||||
LUA_API int (lua_fulltype) (lua_State *L, int idx);
|
||||
LUA_API const char *(lua_typename) (lua_State *L, int tp);
|
||||
|
||||
LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
|
||||
#define LUA_OPEQ 0
|
||||
#define LUA_OPLT 1
|
||||
#define LUA_OPLE 2
|
||||
LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op);
|
||||
|
||||
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
|
||||
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
|
||||
@ -173,18 +176,17 @@ LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
|
||||
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
|
||||
LUA_API void (lua_pushboolean) (lua_State *L, int b);
|
||||
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
|
||||
LUA_API void (lua_pushlightfunction) (lua_State *L, void *p);
|
||||
LUA_API void (lua_pushrotable) (lua_State *L, void *p);
|
||||
LUA_API int (lua_pushthread) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** get functions (Lua -> stack)
|
||||
*/
|
||||
LUA_API void (lua_gettable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawget) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
|
||||
LUA_API int (lua_gettable) (lua_State *L, int idx);
|
||||
LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API int (lua_rawget) (lua_State *L, int idx);
|
||||
LUA_API int (lua_rawgeti) (lua_State *L, int idx, int n);
|
||||
LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
|
||||
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
|
||||
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
|
||||
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
|
||||
@ -198,6 +200,7 @@ LUA_API void (lua_settable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawset) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
|
||||
LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p);
|
||||
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
|
||||
LUA_API int (lua_setfenv) (lua_State *L, int idx);
|
||||
|
||||
@ -210,8 +213,8 @@ LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
|
||||
LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
|
||||
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
|
||||
const char *chunkname);
|
||||
|
||||
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
|
||||
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int stripping);
|
||||
LUA_API int (lua_stripdebug) (lua_State *L, int stripping);
|
||||
|
||||
|
||||
/*
|
||||
@ -271,10 +274,8 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
|
||||
#define lua_strlen(L,i) lua_objlen(L, (i))
|
||||
|
||||
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
|
||||
#define lua_islightfunction(L,n) (lua_type(L, (n)) == LUA_TLIGHTFUNCTION)
|
||||
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
|
||||
#define lua_isrotable(L,n) (lua_type(L, (n)) == LUA_TROTABLE)
|
||||
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
|
||||
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
|
||||
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
|
||||
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
|
||||
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
|
||||
@ -289,14 +290,24 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
|
||||
|
||||
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
|
||||
|
||||
#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ)
|
||||
#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT)
|
||||
|
||||
#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
|
||||
#define lua_tounsigned(L,i) ((lua_Unsigned)lua_tointeger(L,i))
|
||||
|
||||
/* error codes from cross-compiler returned by lua_dump */
|
||||
/* target integer is too small to hold a value */
|
||||
#define LUA_ERR_CC_INTOVERFLOW 101
|
||||
|
||||
/* target lua_Number is integral but a constant is non-integer */
|
||||
#define LUA_ERR_CC_NOTINTEGER 102
|
||||
|
||||
/*
|
||||
** compatibility macros and functions
|
||||
*/
|
||||
|
||||
// BogdanM: modified for eLua interrupt support
|
||||
//#define lua_open() luaL_newstate()
|
||||
lua_State* lua_open(void);
|
||||
lua_State* lua_getstate(void);
|
||||
|
||||
@ -372,24 +383,62 @@ struct lua_Debug {
|
||||
int i_ci; /* active function */
|
||||
};
|
||||
|
||||
int lua_main(void);
|
||||
void lua_input_string (const char *line, int len);
|
||||
|
||||
/* }====================================================================== */
|
||||
|
||||
typedef struct __lua_load{
|
||||
lua_State *L;
|
||||
int firstline;
|
||||
char *line;
|
||||
int line_position;
|
||||
size_t len;
|
||||
int done;
|
||||
const char *prmt;
|
||||
}lua_Load;
|
||||
/* NodeMCU extensions to the standard API */
|
||||
|
||||
int lua_main( int argc, char **argv );
|
||||
typedef struct ROTable ROTable;
|
||||
typedef const struct ROTable_entry ROTable_entry;
|
||||
|
||||
LUA_API void (lua_pushrotable) (lua_State *L, const ROTable *p);
|
||||
LUA_API void (lua_createrotable) (lua_State *L, ROTable *t, ROTable_entry *e, ROTable *mt);
|
||||
LUA_API int (lua_pushstringsarray) (lua_State *L, int opt);
|
||||
LUA_API int (lua_freeheap) (void);
|
||||
|
||||
LUA_API void (lua_getlfsconfig) (lua_State *L, int *);
|
||||
LUA_API int (lua_pushlfsindex) (lua_State *L);
|
||||
|
||||
#define EGC_NOT_ACTIVE 0 // EGC disabled
|
||||
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure
|
||||
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
|
||||
#define EGC_ALWAYS 4 // always run EGC before an allocation
|
||||
|
||||
#ifdef LUA_USE_ESP
|
||||
|
||||
#define LUA_QUEUE_APP 0
|
||||
#define LUA_QUEUE_UART 1
|
||||
|
||||
/**DEBUG**/extern void dbg_printf(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
#define luaN_freearray(L,b,l) luaM_freearray(L,b,l,sizeof(*b))
|
||||
|
||||
LUA_API void (lua_setegcmode) (lua_State *L, int mode, int limit);
|
||||
LUA_API void (lua_getegcinfo) (lua_State *L, int *totals);
|
||||
|
||||
#else
|
||||
|
||||
#define ICACHE_RODATA_ATTR
|
||||
#define dbg_printf printf
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
void lua_handle_input (bool force);
|
||||
#endif
|
||||
|
||||
#ifdef DEVELOPMENT_USE_GDB
|
||||
LUALIB_API void (lua_debugbreak)(void);
|
||||
#else
|
||||
#define lua_debugbreak() (void)(0)
|
||||
#endif
|
||||
|
||||
// EGC operations modes
|
||||
#define EGC_NOT_ACTIVE 0 // EGC disabled
|
||||
#define EGC_ON_ALLOC_FAILURE 1 // run EGC on allocation failure
|
||||
#define EGC_ON_MEM_LIMIT 2 // run EGC when an upper memory limit is hit
|
||||
#define EGC_ALWAYS 4 // always run EGC before an allocation
|
||||
|
||||
void legc_set_mode(lua_State *L, int mode, int limit);
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
||||
*
|
@ -155,6 +155,11 @@
|
||||
#define LUA_EXECDIR "!"
|
||||
#define LUA_IGMARK "-"
|
||||
|
||||
#ifdef CONFIG_LUA_NUMBER_INTEGRAL
|
||||
# define LUA_NUMBER_INTEGRAL
|
||||
#else
|
||||
# define LUA_PACK_TVALUES
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.
|
||||
@ -265,16 +270,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ LUA_PROMPT is the default prompt used by stand-alone Lua.
|
||||
@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.
|
||||
** CHANGE them if you want different prompts. (You can also change the
|
||||
** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)
|
||||
*/
|
||||
#define LUA_PROMPT "> "
|
||||
#define LUA_PROMPT2 ">> "
|
||||
|
||||
|
||||
/*
|
||||
@@ LUA_PROGNAME is the default name for the stand-alone Lua program.
|
||||
** CHANGE it if your stand-alone interpreter has a different name and
|
||||
@ -299,54 +294,34 @@
|
||||
** CHANGE them if you want to improve this functionality (e.g., by using
|
||||
** GNU readline and history facilities).
|
||||
*/
|
||||
#if defined(LUA_USE_STDIO)
|
||||
#if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
|
||||
#include <stdio.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
|
||||
#define lua_saveline(L,idx) \
|
||||
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
|
||||
add_history(lua_tostring(L, idx)); /* add it to history */
|
||||
#define lua_freeline(L,b) ((void)L, free(b))
|
||||
#else // #if defined(LUA_CROSS_COMPILER) && defined(LUA_USE_READLINE)
|
||||
#define lua_readline(L,b,p) \
|
||||
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
|
||||
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
|
||||
#define lua_saveline(L,idx) { (void)L; (void)idx; }
|
||||
#define lua_freeline(L,b) { (void)L; (void)b; }
|
||||
#endif // #if defined(LUA_USE_READLINE)
|
||||
|
||||
#else // #if defined(LUA_USE_STDIO)
|
||||
|
||||
#define lua_readline(L,b,p) (readline4lua(p, b, LUA_MAXINPUT))
|
||||
#define lua_saveline(L,idx) { (void)L; (void)idx; }
|
||||
#define lua_freeline(L,b) { (void)L; (void)b; }
|
||||
|
||||
extern int readline4lua(const char *prompt, char *buffer, int length);
|
||||
|
||||
#endif // #if defined(LUA_USE_STDIO)
|
||||
|
||||
/*
|
||||
@@ luai_writestring/luai_writeline define how 'print' prints its results.
|
||||
@@ lua_writestring/lua_writeline define how 'print' prints its results.
|
||||
** They are only used in libraries and the stand-alone program. (The #if
|
||||
** avoids including 'stdio.h' everywhere.)
|
||||
*/
|
||||
#if !defined(LUA_USE_STDIO)
|
||||
#define luai_writestring(s, l) fwrite(s, 1, l, stdout)
|
||||
#define luai_writeline() puts("")
|
||||
#endif // defined(LUA_USE_STDIO)
|
||||
#ifdef LUA_USE_ESP
|
||||
void output_redirect(const char *str, size_t l);
|
||||
#define lua_writestring(s,l) output_redirect((s),(l))
|
||||
#else
|
||||
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
|
||||
#endif
|
||||
#define luai_writeline() lua_writestring("\n",1)
|
||||
|
||||
/*
|
||||
@@ luai_writestringerror defines how to print error messages.
|
||||
@@ lua_writestringerror defines how to print error messages.
|
||||
** (A format string with one argument is enough for Lua...)
|
||||
*/
|
||||
#if !defined(LUA_USE_STDIO)
|
||||
#define luai_writestringerror(s,p) printf((s), (p))
|
||||
#endif // defined(LUA_USE_STDIO)
|
||||
|
||||
|
||||
/* }================================================================== */
|
||||
#ifdef LUA_USE_ESP
|
||||
#define lua_writestringerror(s,p) dbg_printf((s), (p))
|
||||
#else
|
||||
#define lua_writestringerror(s,p) fprintf(stderr, (s), (p))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@ -586,6 +561,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
|
||||
#define LUA_NUMBER_DOUBLE
|
||||
#define LUA_NUMBER double
|
||||
#endif
|
||||
#define LUA_FLOAT double
|
||||
|
||||
/*
|
||||
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
|
||||
@ -897,4 +873,6 @@ union luai_Cast { double l_d; long l_l; };
|
||||
#error "Pipes not supported NodeMCU firmware"
|
||||
#endif
|
||||
|
||||
#define LUA_DEBUG_HOOK lua_debugbreak
|
||||
|
||||
#endif
|
@ -41,7 +41,7 @@ LUALIB_API int (luaopen_package) (lua_State *L);
|
||||
|
||||
|
||||
/* open all previous libraries */
|
||||
LUALIB_API void (luaL_openlibs) (lua_State *L);
|
||||
LUALIB_API void (luaL_openlibs) (lua_State *L);
|
||||
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#define lundump_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -164,16 +163,9 @@ static TString* LoadString(LoadState* S)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
char* s;
|
||||
if (!luaZ_direct_mode(S->Z)) {
|
||||
s = luaZ_openspace(S->L,S->b,size);
|
||||
LoadBlock(S,s,size);
|
||||
return luaS_newlstr(S->L,s,size-1); /* remove trailing zero */
|
||||
} else {
|
||||
s = (char*)luaZ_get_crt_address(S->Z);
|
||||
LoadBlock(S,NULL,size);
|
||||
return luaS_newlstr(S->L,s,size-1);
|
||||
}
|
||||
char* s = luaZ_openspace(S->L,S->b,size);
|
||||
LoadBlock(S,s,size);
|
||||
return luaS_newlstr(S->L,s,size-1); /* remove trailing zero */
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,13 +173,8 @@ static void LoadCode(LoadState* S, Proto* f)
|
||||
{
|
||||
int n=LoadInt(S);
|
||||
Align4(S);
|
||||
if (!luaZ_direct_mode(S->Z)) {
|
||||
f->code=luaM_newvector(S->L,n,Instruction);
|
||||
LoadVector(S,f->code,n,sizeof(Instruction));
|
||||
} else {
|
||||
f->code=(Instruction*)luaZ_get_crt_address(S->Z);
|
||||
LoadVector(S,NULL,n,sizeof(Instruction));
|
||||
}
|
||||
f->code=luaM_newvector(S->L,n,Instruction);
|
||||
LoadVector(S,f->code,n,sizeof(Instruction));
|
||||
f->sizecode=n;
|
||||
}
|
||||
|
||||
@ -236,28 +223,12 @@ static void LoadDebug(LoadState* S, Proto* f)
|
||||
n=LoadInt(S);
|
||||
Align4(S);
|
||||
|
||||
#ifdef LUA_OPTIMIZE_DEBUG
|
||||
if(n) {
|
||||
if (!luaZ_direct_mode(S->Z)) {
|
||||
f->packedlineinfo=luaM_newvector(S->L,n,unsigned char);
|
||||
LoadBlock(S,f->packedlineinfo,n);
|
||||
} else {
|
||||
f->packedlineinfo=(unsigned char*)luaZ_get_crt_address(S->Z);
|
||||
LoadBlock(S,NULL,n);
|
||||
}
|
||||
f->packedlineinfo=luaM_newvector(S->L,n,unsigned char);
|
||||
LoadBlock(S,f->packedlineinfo,n);
|
||||
} else {
|
||||
f->packedlineinfo=NULL;
|
||||
}
|
||||
#else
|
||||
if (!luaZ_direct_mode(S->Z)) {
|
||||
f->lineinfo=luaM_newvector(S->L,n,int);
|
||||
LoadVector(S,f->lineinfo,n,sizeof(int));
|
||||
} else {
|
||||
f->lineinfo=(int*)luaZ_get_crt_address(S->Z);
|
||||
LoadVector(S,NULL,n,sizeof(int));
|
||||
}
|
||||
f->sizelineinfo=n;
|
||||
#endif
|
||||
n=LoadInt(S);
|
||||
f->locvars=luaM_newvector(S->L,n,LocVar);
|
||||
f->sizelocvars=n;
|
||||
@ -280,7 +251,6 @@ static Proto* LoadFunction(LoadState* S, TString* p)
|
||||
Proto* f;
|
||||
if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep");
|
||||
f=luaF_newproto(S->L);
|
||||
if (luaZ_direct_mode(S->Z)) l_setbit((f)->marked, READONLYBIT);
|
||||
setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
|
||||
f->source=LoadString(S); if (f->source==NULL) f->source=p;
|
||||
f->linedefined=LoadInt(S);
|
@ -50,11 +50,4 @@ LUAI_FUNC void luaU_print (const Proto* f, int full);
|
||||
/* size of header of binary files */
|
||||
#define LUAC_HEADERSIZE 12
|
||||
|
||||
/* error codes from cross-compiler */
|
||||
/* target integer is too small to hold a value */
|
||||
#define LUA_ERR_CC_INTOVERFLOW 101
|
||||
|
||||
/* target lua_Number is integral but a constant is non-integer */
|
||||
#define LUA_ERR_CC_NOTINTEGER 102
|
||||
|
||||
#endif
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lvm_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <stdio.h>
|
||||
@ -25,7 +24,6 @@
|
||||
#include "ltable.h"
|
||||
#include "ltm.h"
|
||||
#include "lvm.h"
|
||||
#include "lrotable.h"
|
||||
|
||||
|
||||
/* limit for table tag-method chains (to avoid loops) */
|
||||
@ -41,7 +39,7 @@ LUA_NUMBER luai_ipow(LUA_NUMBER a, LUA_NUMBER b) {
|
||||
LUA_NUMBER c = 1;
|
||||
for (;;) {
|
||||
if (b & 1)
|
||||
c *= a;
|
||||
c *= a;
|
||||
b = b >> 1;
|
||||
if (b == 0)
|
||||
return c;
|
||||
@ -134,26 +132,17 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
|
||||
if (ttistable(t)) { /* `t' is a table? */
|
||||
Table *h = hvalue(t);
|
||||
const TValue *res = luaH_get(h, key); /* do a primitive get */
|
||||
if (!ttisnil(res) || /* result is no nil? */
|
||||
if (!ttisnil(res) || /* result is no nil? */
|
||||
(tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
|
||||
setobj2s(L, val, res);
|
||||
return;
|
||||
}
|
||||
/* else will try the tag method */
|
||||
} else if (ttisrotable(t)) { /* `t' is a table? */
|
||||
void *h = rvalue(t);
|
||||
const TValue *res = luaH_get_ro(h, key); /* do a primitive get */
|
||||
if (!ttisnil(res) || /* result is no nil? */
|
||||
(tm = fasttm(L, (Table*)luaR_getmeta(h), TM_INDEX)) == NULL) { /* or no TM? */
|
||||
setobj2s(L, val, res);
|
||||
return;
|
||||
}
|
||||
/* else will try the tag method */
|
||||
}
|
||||
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
|
||||
luaG_typeerror(L, t, "index");
|
||||
|
||||
if (ttisfunction(tm) || ttislightfunction(tm)) {
|
||||
if (ttisfunction(tm)) {
|
||||
callTMres(L, val, tm, t, key);
|
||||
return;
|
||||
}
|
||||
@ -193,7 +182,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
|
||||
else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
|
||||
luaG_typeerror(L, t, "index");
|
||||
|
||||
if (ttisfunction(tm) || ttislightfunction(tm)) {
|
||||
if (ttisfunction(tm)) {
|
||||
L->top--;
|
||||
unfixedstack(L);
|
||||
callTM(L, tm, t, key, val);
|
||||
@ -282,7 +271,7 @@ int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
|
||||
}
|
||||
|
||||
|
||||
static int lessequal (lua_State *L, const TValue *l, const TValue *r) {
|
||||
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
|
||||
int res;
|
||||
if (ttype(l) != ttype(r))
|
||||
return luaG_ordererror(L, l, r);
|
||||
@ -305,8 +294,6 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
|
||||
case LUA_TNIL: return 1;
|
||||
case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
|
||||
case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */
|
||||
case LUA_TROTABLE:
|
||||
return rvalue(t1) == rvalue(t2);
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
case LUA_TLIGHTFUNCTION:
|
||||
return pvalue(t1) == pvalue(t2);
|
||||
@ -316,6 +303,8 @@ int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {
|
||||
TM_EQ);
|
||||
break; /* will try TM */
|
||||
}
|
||||
case LUA_TROTABLE:
|
||||
return hvalue(t1) == hvalue(t2);
|
||||
case LUA_TTABLE: {
|
||||
if (hvalue(t1) == hvalue(t2)) return 1;
|
||||
tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
|
||||
@ -440,7 +429,6 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb,
|
||||
}
|
||||
|
||||
|
||||
|
||||
void luaV_execute (lua_State *L, int nexeccalls) {
|
||||
LClosure *cl;
|
||||
StkId base;
|
||||
@ -582,10 +570,9 @@ void luaV_execute (lua_State *L, int nexeccalls) {
|
||||
}
|
||||
case OP_LEN: {
|
||||
const TValue *rb = RB(i);
|
||||
switch (ttype(rb)) {
|
||||
case LUA_TTABLE:
|
||||
case LUA_TROTABLE: {
|
||||
setnvalue(ra, ttistable(rb) ? cast_num(luaH_getn(hvalue(rb))) : cast_num(luaH_getn_ro(rvalue(rb))));
|
||||
switch (ttnov(rb)) {
|
||||
case LUA_TTABLE: {
|
||||
setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));
|
||||
break;
|
||||
}
|
||||
case LUA_TSTRING: {
|
||||
@ -633,7 +620,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
|
||||
}
|
||||
case OP_LE: {
|
||||
Protect(
|
||||
if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
|
||||
if (luaV_lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
|
||||
dojump(L, pc, GETARG_sBx(*pc));
|
||||
)
|
||||
pc++;
|
||||
@ -785,7 +772,7 @@ void luaV_execute (lua_State *L, int nexeccalls) {
|
||||
setobj2t(L, luaH_setnum(L, h, last--), val);
|
||||
luaC_barriert(L, h, val);
|
||||
}
|
||||
L->top = L->ci->top;
|
||||
L->top = L->ci->top;
|
||||
unfixedstack(L);
|
||||
continue;
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
|
||||
|
||||
LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
|
||||
LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
|
||||
LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);
|
||||
LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);
|
||||
LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);
|
@ -7,7 +7,6 @@
|
||||
|
||||
#define lzio_c
|
||||
#define LUA_CORE
|
||||
#define LUAC_CROSS_FILE
|
||||
|
||||
#include "lua.h"
|
||||
#include <string.h>
|
||||
@ -49,7 +48,7 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {
|
||||
z->L = L;
|
||||
z->reader = reader;
|
||||
z->data = data;
|
||||
z->n = z->i = 0;
|
||||
z->n = 0;
|
||||
z->p = NULL;
|
||||
}
|
||||
|
||||
@ -64,7 +63,6 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) {
|
||||
if (b)
|
||||
memcpy(b, z->p, m);
|
||||
z->n -= m;
|
||||
z->i += m;
|
||||
z->p += m;
|
||||
if (b)
|
||||
b = (char *)b + m;
|
@ -43,9 +43,6 @@ typedef struct Mbuffer {
|
||||
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
|
||||
|
||||
#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0)
|
||||
#define luaZ_get_base_address(zio) ((const char *)((zio)->reader(NULL, (zio)->data, NULL)))
|
||||
#define luaZ_direct_mode(zio) (luaZ_get_base_address(zio) != NULL)
|
||||
#define luaZ_get_crt_address(zio) (luaZ_get_base_address(zio) + (zio)->i)
|
||||
|
||||
LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);
|
||||
LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,
|
||||
@ -59,7 +56,6 @@ LUAI_FUNC int luaZ_lookahead (ZIO *z);
|
||||
|
||||
struct Zio {
|
||||
size_t n; /* bytes still unread */
|
||||
size_t i; /* buffer offset */
|
||||
const char *p; /* current position in buffer */
|
||||
lua_Reader reader;
|
||||
void* data; /* additional data */
|
52
components/lua/lua-5.3/Makefile
Normal file
52
components/lua/lua-5.3/Makefile
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
#############################################################
|
||||
# Required variables for each makefile
|
||||
# Discard this section from all parent makefiles
|
||||
# Expected variables (with automatic defaults):
|
||||
# CSRCS (all "C" files in the dir)
|
||||
# SUBDIRS (all subdirs with a Makefile)
|
||||
# GEN_LIBS - list of libs to be generated ()
|
||||
# GEN_IMAGES - list of images to be generated ()
|
||||
# COMPONENTS_xxx - a list of libs/objs in the form
|
||||
# subdir/lib to be extracted and rolled up into
|
||||
# a generated lib/image xxx.a ()
|
||||
#
|
||||
ifndef PDIR
|
||||
SUBDIRS = host
|
||||
GEN_LIBS = liblua.a
|
||||
endif
|
||||
|
||||
STD_CFLAGS=-std=gnu11 -Wimplicit -Wall
|
||||
|
||||
|
||||
# Validate LUA setting
|
||||
ifeq ("$(LUA)","53")
|
||||
# ok
|
||||
else ifeq ("$(LUA)","51")
|
||||
$(error Your variable LUA="$(LUA)" looks like you probably want \
|
||||
app/lua/Makefile instead)
|
||||
else
|
||||
$(error Expected environment variable "LUA" to be "53", not "$(LUA)")
|
||||
endif
|
||||
|
||||
|
||||
#############################################################
|
||||
# Configuration i.e. compile options etc.
|
||||
# Target specific stuff (defines etc.) goes in here!
|
||||
#
|
||||
#DEFINES += -DDEVELOPMENT_TOOLS -DDEVELOPMENT_USE_GDB -DDEVELOPMENT_BREAK_ON_STARTUP_PIN=1
|
||||
#EXTRA_CCFLAGS += -ggdb -O0
|
||||
|
||||
#############################################################
|
||||
# Recursion Magic - Don't touch this!!
|
||||
#
|
||||
|
||||
INCLUDES := $(INCLUDES) -I $(PDIR)include
|
||||
INCLUDES += -I ./
|
||||
INCLUDES += -I ../spiffs
|
||||
INCLUDES += -I ../libc
|
||||
INCLUDES += -I ../modules
|
||||
INCLUDES += -I ../platform
|
||||
INCLUDES += -I ../uzlib
|
||||
PDIR := ../$(PDIR)
|
||||
sinclude $(PDIR)Makefile
|
69
components/lua/lua-5.3/host/idf.mk
Normal file
69
components/lua/lua-5.3/host/idf.mk
Normal file
@ -0,0 +1,69 @@
|
||||
all: build
|
||||
|
||||
HOSTCC?=$(PYTHON) -m ziglang cc
|
||||
|
||||
ifeq ($V,)
|
||||
Q:=@
|
||||
endif
|
||||
|
||||
LUAC_OBJ_DIR:=$(LUAC_BUILD_DIR)/$(notdir $(LUA_PATH))
|
||||
|
||||
LUAC_CFLAGS:= \
|
||||
-I$(LUAC_BUILD_DIR) \
|
||||
-I$(LUA_PATH) \
|
||||
-I$(LUA_PATH)/host \
|
||||
-I$(LUA_PATH)/../common \
|
||||
-I$(LUA_PATH)/../../uzlib \
|
||||
-O2 -g -Wall -Wextra -Wno-sign-compare -Wno-string-plus-int
|
||||
|
||||
LUAC_LDFLAGS:= -ldl -lm
|
||||
|
||||
LUAC_DEFINES += \
|
||||
-DLUA_CROSS_COMPILER \
|
||||
-DLUA_USE_HOST \
|
||||
-DLUA_USE_STDIO \
|
||||
|
||||
vpath %.c $(LUA_PATH)/host $(LUA_PATH) $(LUA_PATH)/../common $(LUA_PATH)/../../uzlib
|
||||
|
||||
LUA_SRCS:=\
|
||||
luac.c loslib.c liolib.c \
|
||||
lapi.c lauxlib.c lbaselib.c lbitlib.c lcode.c lcorolib.c \
|
||||
lctype.c ldblib.c ldebug.c ldo.c ldump.c lfunc.c \
|
||||
lgc.c llex.c lmathlib.c lmem.c lnodemcu.c loadlib.c \
|
||||
lobject.c lopcodes.c lparser.c lstate.c lstring.c lstrlib.c \
|
||||
ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c \
|
||||
lzio.c \
|
||||
linit.c lpanic.c \
|
||||
uzlib_deflate.c crc32.c \
|
||||
|
||||
LUAC_OBJS:=$(LUA_SRCS:%.c=$(LUAC_OBJ_DIR)/%.o)
|
||||
LUAC_CROSS:=$(LUAC_BUILD_DIR)/luac.cross
|
||||
|
||||
$(LUAC_OBJ_DIR):
|
||||
@mkdir -p "$@"
|
||||
|
||||
$(LUAC_OBJ_DIR)/%.o: %.c | $(LUAC_OBJ_DIR)
|
||||
@echo '[hostcc] $(notdir $@)'
|
||||
$Q$(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) "$<" -c -o "$@"
|
||||
|
||||
$(LUAC_OBJ_DIR)/%.d: SHELL=/bin/bash
|
||||
$(LUAC_OBJ_DIR)/%.d: %.c | $(LUAC_OBJ_DIR)
|
||||
@echo '[ dep] $<'
|
||||
@rm -f "$@"
|
||||
$Qset -eo pipefail; $(HOSTCC) $(LUAC_DEFINES) $(LUAC_CFLAGS) -M "$<" | sed 's,\($*\.o\)[ :]*,$(LUAC_OBJ_DIR)/\1 $@ : ,g' > "$@.tmp"; mv "$@.tmp" "$@"
|
||||
|
||||
build: $(LUAC_DEPS) $(LUAC_CROSS)
|
||||
|
||||
$(LUAC_CROSS): $(LUAC_OBJS)
|
||||
@echo '[ link] $(notdir $@)'
|
||||
$Q$(HOSTCC) $(LUAC_CFLAGS) $^ $(LUAC_LDFLAGS) -o "$@"
|
||||
|
||||
# zig cc (0.8.0 at least) seems to get itself all confused with its cache
|
||||
# when we're running a separate path for dependencies, so we skip them for
|
||||
# now as for most people they're not needed anyway.
|
||||
ifneq ($(findstring zig,$(HOSTCC)),zig)
|
||||
LUAC_DEPS:=$(LUAC_OBJS:%.o=%.d)
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(LUAC_DEPS)
|
||||
endif
|
||||
endif
|
776
components/lua/lua-5.3/host/liolib.c
Normal file
776
components/lua/lua-5.3/host/liolib.c
Normal file
@ -0,0 +1,776 @@
|
||||
/*
|
||||
** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Standard I/O (and system) library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define liolib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Change this macro to accept other modes for 'fopen' besides
|
||||
** the standard ones.
|
||||
*/
|
||||
#if !defined(l_checkmode)
|
||||
|
||||
/* accepted extensions to 'mode' in 'fopen' */
|
||||
#if !defined(L_MODEEXT)
|
||||
#define L_MODEEXT "b"
|
||||
#endif
|
||||
|
||||
/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
|
||||
static int l_checkmode (const char *mode) {
|
||||
return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
|
||||
(*mode != '+' || (++mode, 1)) && /* skip if char is '+' */
|
||||
(strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** l_popen spawns a new process connected to the current
|
||||
** one through the file streams.
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#if !defined(l_popen) /* { */
|
||||
|
||||
#if defined(LUA_USE_POSIX) /* { */
|
||||
|
||||
#define l_popen(L,c,m) (fflush(NULL), popen(c,m))
|
||||
#define l_pclose(L,file) (pclose(file))
|
||||
|
||||
#elif defined(LUA_USE_WINDOWS) /* }{ */
|
||||
|
||||
#define l_popen(L,c,m) (_popen(c,m))
|
||||
#define l_pclose(L,file) (_pclose(file))
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/* ISO C definitions */
|
||||
#define l_popen(L,c,m) \
|
||||
((void)((void)c, m), \
|
||||
luaL_error(L, "'popen' not supported"), \
|
||||
(FILE*)0)
|
||||
#define l_pclose(L,file) ((void)L, (void)file, -1)
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif /* } */
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
#if !defined(l_getc) /* { */
|
||||
|
||||
#if defined(LUA_USE_POSIX)
|
||||
#define l_getc(f) getc_unlocked(f)
|
||||
#define l_lockfile(f) flockfile(f)
|
||||
#define l_unlockfile(f) funlockfile(f)
|
||||
#else
|
||||
#define l_getc(f) getc(f)
|
||||
#define l_lockfile(f) ((void)0)
|
||||
#define l_unlockfile(f) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif /* } */
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** l_fseek: configuration for longer offsets
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
#if !defined(l_fseek) /* { */
|
||||
|
||||
#if defined(LUA_USE_POSIX) /* { */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define l_fseek(f,o,w) fseeko(f,o,w)
|
||||
#define l_ftell(f) ftello(f)
|
||||
#define l_seeknum off_t
|
||||
|
||||
#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
|
||||
&& defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
|
||||
|
||||
/* Windows (but not DDK) and Visual C++ 2005 or higher */
|
||||
#define l_fseek(f,o,w) _fseeki64(f,o,w)
|
||||
#define l_ftell(f) _ftelli64(f)
|
||||
#define l_seeknum __int64
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/* ISO C definitions */
|
||||
#define l_fseek(f,o,w) fseek(f,o,w)
|
||||
#define l_ftell(f) ftell(f)
|
||||
#define l_seeknum long
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif /* } */
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
#define IO_PREFIX "_IO_"
|
||||
#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
|
||||
#define IO_INPUT (IO_PREFIX "input")
|
||||
#define IO_OUTPUT (IO_PREFIX "output")
|
||||
|
||||
|
||||
typedef luaL_Stream LStream;
|
||||
|
||||
|
||||
#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
|
||||
|
||||
#define isclosed(p) ((p)->closef == NULL)
|
||||
|
||||
|
||||
static int io_type (lua_State *L) {
|
||||
LStream *p;
|
||||
luaL_checkany(L, 1);
|
||||
p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
|
||||
if (p == NULL)
|
||||
lua_pushnil(L); /* not a file */
|
||||
else if (isclosed(p))
|
||||
lua_pushliteral(L, "closed file");
|
||||
else
|
||||
lua_pushliteral(L, "file");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int f_tostring (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
if (isclosed(p))
|
||||
lua_pushliteral(L, "file (closed)");
|
||||
else
|
||||
lua_pushfstring(L, "file (%p)", p->f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static FILE *tofile (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
if (isclosed(p))
|
||||
luaL_error(L, "attempt to use a closed file");
|
||||
lua_assert(p->f);
|
||||
return p->f;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** When creating file handles, always creates a 'closed' file handle
|
||||
** before opening the actual file; so, if there is a memory error, the
|
||||
** handle is in a consistent state.
|
||||
*/
|
||||
static LStream *newprefile (lua_State *L) {
|
||||
LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
|
||||
p->closef = NULL; /* mark file handle as 'closed' */
|
||||
luaL_setmetatable(L, LUA_FILEHANDLE);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Calls the 'close' function from a file handle. The 'volatile' avoids
|
||||
** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
|
||||
** 32 bits).
|
||||
*/
|
||||
static int aux_close (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
volatile lua_CFunction cf = p->closef;
|
||||
p->closef = NULL; /* mark stream as closed */
|
||||
return (*cf)(L); /* close it */
|
||||
}
|
||||
|
||||
|
||||
static int f_close (lua_State *L) {
|
||||
tofile(L); /* make sure argument is an open stream */
|
||||
return aux_close(L);
|
||||
}
|
||||
|
||||
|
||||
static int io_close (lua_State *L) {
|
||||
if (lua_isnone(L, 1)) /* no argument? */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
|
||||
return f_close(L);
|
||||
}
|
||||
|
||||
|
||||
static int f_gc (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
if (!isclosed(p) && p->f != NULL)
|
||||
aux_close(L); /* ignore closed and incompletely open files */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to close regular files
|
||||
*/
|
||||
static int io_fclose (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
int res = fclose(p->f);
|
||||
return luaL_fileresult(L, (res == 0), NULL);
|
||||
}
|
||||
|
||||
|
||||
static LStream *newfile (lua_State *L) {
|
||||
LStream *p = newprefile(L);
|
||||
p->f = NULL;
|
||||
p->closef = &io_fclose;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static void opencheck (lua_State *L, const char *fname, const char *mode) {
|
||||
LStream *p = newfile(L);
|
||||
p->f = fopen(fname, mode);
|
||||
if (p->f == NULL)
|
||||
luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
static int io_open (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
LStream *p = newfile(L);
|
||||
const char *md = mode; /* to traverse/check mode */
|
||||
luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
|
||||
p->f = fopen(filename, mode);
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to close 'popen' files
|
||||
*/
|
||||
static int io_pclose (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
return luaL_execresult(L, l_pclose(L, p->f));
|
||||
}
|
||||
|
||||
|
||||
static int io_popen (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
LStream *p = newprefile(L);
|
||||
p->f = l_popen(L, filename, mode);
|
||||
p->closef = &io_pclose;
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_tmpfile (lua_State *L) {
|
||||
LStream *p = newfile(L);
|
||||
p->f = tmpfile();
|
||||
return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
|
||||
}
|
||||
|
||||
|
||||
static FILE *getiofile (lua_State *L, const char *findex) {
|
||||
LStream *p;
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, findex);
|
||||
p = (LStream *)lua_touserdata(L, -1);
|
||||
if (isclosed(p))
|
||||
luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
|
||||
return p->f;
|
||||
}
|
||||
|
||||
|
||||
static int g_iofile (lua_State *L, const char *f, const char *mode) {
|
||||
if (!lua_isnoneornil(L, 1)) {
|
||||
const char *filename = lua_tostring(L, 1);
|
||||
if (filename)
|
||||
opencheck(L, filename, mode);
|
||||
else {
|
||||
tofile(L); /* check that it's a valid file handle */
|
||||
lua_pushvalue(L, 1);
|
||||
}
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, f);
|
||||
}
|
||||
/* return current value */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_input (lua_State *L) {
|
||||
return g_iofile(L, IO_INPUT, "r");
|
||||
}
|
||||
|
||||
|
||||
static int io_output (lua_State *L) {
|
||||
return g_iofile(L, IO_OUTPUT, "w");
|
||||
}
|
||||
|
||||
|
||||
static int io_readline (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
|
||||
** in the limit for upvalues of a closure)
|
||||
*/
|
||||
#define MAXARGLINE 250
|
||||
|
||||
static void aux_lines (lua_State *L, int toclose) {
|
||||
int n = lua_gettop(L) - 1; /* number of arguments to read */
|
||||
luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
|
||||
lua_pushinteger(L, n); /* number of arguments to read */
|
||||
lua_pushboolean(L, toclose); /* close/not close file when finished */
|
||||
lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
|
||||
lua_pushcclosure(L, io_readline, 3 + n);
|
||||
}
|
||||
|
||||
|
||||
static int f_lines (lua_State *L) {
|
||||
tofile(L); /* check that it's a valid file handle */
|
||||
aux_lines(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_lines (lua_State *L) {
|
||||
int toclose;
|
||||
if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
|
||||
if (lua_isnil(L, 1)) { /* no file name? */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
|
||||
lua_replace(L, 1); /* put it at index 1 */
|
||||
tofile(L); /* check that it's a valid file handle */
|
||||
toclose = 0; /* do not close it after iteration */
|
||||
}
|
||||
else { /* open a new file */
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
opencheck(L, filename, "r");
|
||||
lua_replace(L, 1); /* put file at index 1 */
|
||||
toclose = 1; /* close it after iteration */
|
||||
}
|
||||
aux_lines(L, toclose);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** READ
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
/* maximum length of a numeral */
|
||||
#if !defined (L_MAXLENNUM)
|
||||
#define L_MAXLENNUM 200
|
||||
#endif
|
||||
|
||||
|
||||
/* auxiliary structure used by 'read_number' */
|
||||
typedef struct {
|
||||
FILE *f; /* file being read */
|
||||
int c; /* current character (look ahead) */
|
||||
int n; /* number of elements in buffer 'buff' */
|
||||
char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
|
||||
} RN;
|
||||
|
||||
|
||||
/*
|
||||
** Add current char to buffer (if not out of space) and read next one
|
||||
*/
|
||||
static int nextc (RN *rn) {
|
||||
if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
|
||||
rn->buff[0] = '\0'; /* invalidate result */
|
||||
return 0; /* fail */
|
||||
}
|
||||
else {
|
||||
rn->buff[rn->n++] = rn->c; /* save current char */
|
||||
rn->c = l_getc(rn->f); /* read next one */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Accept current char if it is in 'set' (of size 2)
|
||||
*/
|
||||
static int test2 (RN *rn, const char *set) {
|
||||
if (rn->c == set[0] || rn->c == set[1])
|
||||
return nextc(rn);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Read a sequence of (hex)digits
|
||||
*/
|
||||
static int readdigits (RN *rn, int hex) {
|
||||
int count = 0;
|
||||
while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Read a number: first reads a valid prefix of a numeral into a buffer.
|
||||
** Then it calls 'lua_stringtonumber' to check whether the format is
|
||||
** correct and to convert it to a Lua number
|
||||
*/
|
||||
static int read_number (lua_State *L, FILE *f) {
|
||||
RN rn;
|
||||
int count = 0;
|
||||
int hex = 0;
|
||||
char decp[2];
|
||||
rn.f = f; rn.n = 0;
|
||||
decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
|
||||
decp[1] = '.'; /* always accept a dot */
|
||||
l_lockfile(rn.f);
|
||||
do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
|
||||
test2(&rn, "-+"); /* optional signal */
|
||||
if (test2(&rn, "00")) {
|
||||
if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
|
||||
else count = 1; /* count initial '0' as a valid digit */
|
||||
}
|
||||
count += readdigits(&rn, hex); /* integral part */
|
||||
if (test2(&rn, decp)) /* decimal point? */
|
||||
count += readdigits(&rn, hex); /* fractional part */
|
||||
if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */
|
||||
test2(&rn, "-+"); /* exponent signal */
|
||||
readdigits(&rn, 0); /* exponent digits */
|
||||
}
|
||||
ungetc(rn.c, rn.f); /* unread look-ahead char */
|
||||
l_unlockfile(rn.f);
|
||||
rn.buff[rn.n] = '\0'; /* finish string */
|
||||
if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */
|
||||
return 1; /* ok */
|
||||
else { /* invalid format */
|
||||
lua_pushnil(L); /* "result" to be removed */
|
||||
return 0; /* read fails */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int test_eof (lua_State *L, FILE *f) {
|
||||
int c = getc(f);
|
||||
ungetc(c, f); /* no-op when c == EOF */
|
||||
lua_pushliteral(L, "");
|
||||
return (c != EOF);
|
||||
}
|
||||
|
||||
|
||||
static int read_line (lua_State *L, FILE *f, int chop) {
|
||||
luaL_Buffer b;
|
||||
int c = '\0';
|
||||
luaL_buffinit(L, &b);
|
||||
while (c != EOF && c != '\n') { /* repeat until end of line */
|
||||
char *buff = luaL_prepbuffer(&b); /* preallocate buffer */
|
||||
int i = 0;
|
||||
l_lockfile(f); /* no memory errors can happen inside the lock */
|
||||
while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
|
||||
buff[i++] = c;
|
||||
l_unlockfile(f);
|
||||
luaL_addsize(&b, i);
|
||||
}
|
||||
if (!chop && c == '\n') /* want a newline and have one? */
|
||||
luaL_addchar(&b, c); /* add ending newline to result */
|
||||
luaL_pushresult(&b); /* close buffer */
|
||||
/* return ok if read something (either a newline or something else) */
|
||||
return (c == '\n' || lua_rawlen(L, -1) > 0);
|
||||
}
|
||||
|
||||
|
||||
static void read_all (lua_State *L, FILE *f) {
|
||||
size_t nr;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
|
||||
char *p = luaL_prepbuffer(&b);
|
||||
nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
|
||||
luaL_addsize(&b, nr);
|
||||
} while (nr == LUAL_BUFFERSIZE);
|
||||
luaL_pushresult(&b); /* close buffer */
|
||||
}
|
||||
|
||||
|
||||
static int read_chars (lua_State *L, FILE *f, size_t n) {
|
||||
size_t nr; /* number of chars actually read */
|
||||
char *p;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
|
||||
nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
|
||||
luaL_addsize(&b, nr);
|
||||
luaL_pushresult(&b); /* close buffer */
|
||||
return (nr > 0); /* true iff read something */
|
||||
}
|
||||
|
||||
|
||||
static int g_read (lua_State *L, FILE *f, int first) {
|
||||
int nargs = lua_gettop(L) - 1;
|
||||
int success;
|
||||
int n;
|
||||
clearerr(f);
|
||||
if (nargs == 0) { /* no arguments? */
|
||||
success = read_line(L, f, 1);
|
||||
n = first+1; /* to return 1 result */
|
||||
}
|
||||
else { /* ensure stack space for all results and for auxlib's buffer */
|
||||
luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
|
||||
success = 1;
|
||||
for (n = first; nargs-- && success; n++) {
|
||||
if (lua_type(L, n) == LUA_TNUMBER) {
|
||||
size_t l = (size_t)luaL_checkinteger(L, n);
|
||||
success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
|
||||
}
|
||||
else {
|
||||
const char *p = luaL_checkstring(L, n);
|
||||
if (*p == '*') p++; /* skip optional '*' (for compatibility) */
|
||||
switch (*p) {
|
||||
case 'n': /* number */
|
||||
success = read_number(L, f);
|
||||
break;
|
||||
case 'l': /* line */
|
||||
success = read_line(L, f, 1);
|
||||
break;
|
||||
case 'L': /* line with end-of-line */
|
||||
success = read_line(L, f, 0);
|
||||
break;
|
||||
case 'a': /* file */
|
||||
read_all(L, f); /* read entire file */
|
||||
success = 1; /* always success */
|
||||
break;
|
||||
default:
|
||||
return luaL_argerror(L, n, "invalid format");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ferror(f))
|
||||
return luaL_fileresult(L, 0, NULL);
|
||||
if (!success) {
|
||||
lua_pop(L, 1); /* remove last result */
|
||||
lua_pushnil(L); /* push nil instead */
|
||||
}
|
||||
return n - first;
|
||||
}
|
||||
|
||||
|
||||
static int io_read (lua_State *L) {
|
||||
return g_read(L, getiofile(L, IO_INPUT), 1);
|
||||
}
|
||||
|
||||
|
||||
static int f_read (lua_State *L) {
|
||||
return g_read(L, tofile(L), 2);
|
||||
}
|
||||
|
||||
|
||||
static int io_readline (lua_State *L) {
|
||||
LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
|
||||
int i;
|
||||
int n = (int)lua_tointeger(L, lua_upvalueindex(2));
|
||||
if (isclosed(p)) /* file is already closed? */
|
||||
return luaL_error(L, "file is already closed");
|
||||
lua_settop(L , 1);
|
||||
luaL_checkstack(L, n, "too many arguments");
|
||||
for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
|
||||
lua_pushvalue(L, lua_upvalueindex(3 + i));
|
||||
n = g_read(L, p->f, 2); /* 'n' is number of results */
|
||||
lua_assert(n > 0); /* should return at least a nil */
|
||||
if (lua_toboolean(L, -n)) /* read at least one value? */
|
||||
return n; /* return them */
|
||||
else { /* first result is nil: EOF or error */
|
||||
if (n > 1) { /* is there error information? */
|
||||
/* 2nd result is error message */
|
||||
return luaL_error(L, "%s", lua_tostring(L, -n + 1));
|
||||
}
|
||||
if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
|
||||
lua_settop(L, 0);
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
aux_close(L); /* close it */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static int g_write (lua_State *L, FILE *f, int arg) {
|
||||
int nargs = lua_gettop(L) - arg;
|
||||
int status = 1;
|
||||
for (; nargs--; arg++) {
|
||||
if (lua_type(L, arg) == LUA_TNUMBER) {
|
||||
/* optimization: could be done exactly as for strings */
|
||||
int len = lua_isinteger(L, arg)
|
||||
? fprintf(f, LUA_INTEGER_FMT,
|
||||
(LUAI_UACINT)lua_tointeger(L, arg))
|
||||
: fprintf(f, LUA_NUMBER_FMT,
|
||||
(LUAI_UACNUMBER)lua_tonumber(L, arg));
|
||||
status = status && (len > 0);
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = luaL_checklstring(L, arg, &l);
|
||||
status = status && (fwrite(s, sizeof(char), l, f) == l);
|
||||
}
|
||||
}
|
||||
if (status) return 1; /* file handle already on stack top */
|
||||
else return luaL_fileresult(L, status, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int io_write (lua_State *L) {
|
||||
return g_write(L, getiofile(L, IO_OUTPUT), 1);
|
||||
}
|
||||
|
||||
|
||||
static int f_write (lua_State *L) {
|
||||
FILE *f = tofile(L);
|
||||
lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
|
||||
return g_write(L, f, 2);
|
||||
}
|
||||
|
||||
|
||||
static int f_seek (lua_State *L) {
|
||||
static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
|
||||
static const char *const modenames[] = {"set", "cur", "end", NULL};
|
||||
FILE *f = tofile(L);
|
||||
int op = luaL_checkoption(L, 2, "cur", modenames);
|
||||
lua_Integer p3 = luaL_optinteger(L, 3, 0);
|
||||
l_seeknum offset = (l_seeknum)p3;
|
||||
luaL_argcheck(L, (lua_Integer)offset == p3, 3,
|
||||
"not an integer in proper range");
|
||||
op = l_fseek(f, offset, mode[op]);
|
||||
if (op)
|
||||
return luaL_fileresult(L, 0, NULL); /* error */
|
||||
else {
|
||||
lua_pushinteger(L, (lua_Integer)l_ftell(f));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int f_setvbuf (lua_State *L) {
|
||||
static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
|
||||
static const char *const modenames[] = {"no", "full", "line", NULL};
|
||||
FILE *f = tofile(L);
|
||||
int op = luaL_checkoption(L, 2, NULL, modenames);
|
||||
lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
|
||||
int res = setvbuf(f, NULL, mode[op], (size_t)sz);
|
||||
return luaL_fileresult(L, res == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int io_flush (lua_State *L) {
|
||||
return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int f_flush (lua_State *L) {
|
||||
return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** functions for 'io' library
|
||||
*/
|
||||
static const luaL_Reg iolib[] = {
|
||||
{"close", io_close},
|
||||
{"flush", io_flush},
|
||||
{"input", io_input},
|
||||
{"lines", io_lines},
|
||||
{"open", io_open},
|
||||
{"output", io_output},
|
||||
{"popen", io_popen},
|
||||
{"read", io_read},
|
||||
{"tmpfile", io_tmpfile},
|
||||
{"type", io_type},
|
||||
{"write", io_write},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** methods for file handles
|
||||
*/
|
||||
static const luaL_Reg flib[] = {
|
||||
{"close", f_close},
|
||||
{"flush", f_flush},
|
||||
{"lines", f_lines},
|
||||
{"read", f_read},
|
||||
{"seek", f_seek},
|
||||
{"setvbuf", f_setvbuf},
|
||||
{"write", f_write},
|
||||
{"__gc", f_gc},
|
||||
{"__tostring", f_tostring},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
static void createmeta (lua_State *L) {
|
||||
luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
|
||||
lua_pushvalue(L, -1); /* push metatable */
|
||||
lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
|
||||
luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
|
||||
lua_pop(L, 1); /* pop new metatable */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to (not) close the standard files stdin, stdout, and stderr
|
||||
*/
|
||||
static int io_noclose (lua_State *L) {
|
||||
LStream *p = tolstream(L);
|
||||
p->closef = &io_noclose; /* keep file opened */
|
||||
lua_pushnil(L);
|
||||
lua_pushliteral(L, "cannot close standard file");
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
static void createstdfile (lua_State *L, FILE *f, const char *k,
|
||||
const char *fname) {
|
||||
LStream *p = newprefile(L);
|
||||
p->f = f;
|
||||
p->closef = &io_noclose;
|
||||
if (k != NULL) {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
|
||||
}
|
||||
lua_setfield(L, -2, fname); /* add file to module */
|
||||
}
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_io (lua_State *L) {
|
||||
luaL_newlib(L, iolib); /* new module */
|
||||
createmeta(L);
|
||||
/* create (and set) default files */
|
||||
createstdfile(L, stdin, IO_INPUT, "stdin");
|
||||
createstdfile(L, stdout, IO_OUTPUT, "stdout");
|
||||
createstdfile(L, stderr, NULL, "stderr");
|
||||
return 1;
|
||||
}
|
||||
|
409
components/lua/lua-5.3/host/loslib.c
Normal file
409
components/lua/lua-5.3/host/loslib.c
Normal file
@ -0,0 +1,409 @@
|
||||
/*
|
||||
** $Id: loslib.c,v 1.65.1.1 2017/04/19 17:29:57 roberto Exp $
|
||||
** Standard Operating System library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define loslib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** List of valid conversion specifiers for the 'strftime' function;
|
||||
** options are grouped by length; group of length 2 start with '||'.
|
||||
** ===================================================================
|
||||
*/
|
||||
#if !defined(LUA_STRFTIMEOPTIONS) /* { */
|
||||
|
||||
/* options for ANSI C 89 (only 1-char options) */
|
||||
#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%"
|
||||
|
||||
/* options for ISO C 99 and POSIX */
|
||||
#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \
|
||||
"||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */
|
||||
|
||||
/* options for Windows */
|
||||
#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \
|
||||
"||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */
|
||||
|
||||
#if defined(LUA_USE_WINDOWS)
|
||||
#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN
|
||||
#elif defined(LUA_USE_C89)
|
||||
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89
|
||||
#else /* C99 specification */
|
||||
#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99
|
||||
#endif
|
||||
|
||||
#endif /* } */
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** Configuration for time-related stuff
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
#if !defined(l_time_t) /* { */
|
||||
/*
|
||||
** type to represent time_t in Lua
|
||||
*/
|
||||
#define l_timet lua_Integer
|
||||
#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t))
|
||||
|
||||
static time_t l_checktime (lua_State *L, int arg) {
|
||||
lua_Integer t = luaL_checkinteger(L, arg);
|
||||
luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds");
|
||||
return (time_t)t;
|
||||
}
|
||||
|
||||
#endif /* } */
|
||||
|
||||
|
||||
#if !defined(l_gmtime) /* { */
|
||||
/*
|
||||
** By default, Lua uses gmtime/localtime, except when POSIX is available,
|
||||
** where it uses gmtime_r/localtime_r
|
||||
*/
|
||||
|
||||
#if defined(LUA_USE_POSIX) /* { */
|
||||
|
||||
#define l_gmtime(t,r) gmtime_r(t,r)
|
||||
#define l_localtime(t,r) localtime_r(t,r)
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/* ISO C definitions */
|
||||
#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t))
|
||||
#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t))
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif /* } */
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** Configuration for 'tmpnam':
|
||||
** By default, Lua uses tmpnam except when POSIX is available, where
|
||||
** it uses mkstemp.
|
||||
** ===================================================================
|
||||
*/
|
||||
#if !defined(lua_tmpnam) /* { */
|
||||
|
||||
#if defined(__GNUC__) /* { */
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define LUA_TMPNAMBUFSIZE 32
|
||||
|
||||
#if !defined(LUA_TMPNAMTEMPLATE)
|
||||
#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX"
|
||||
#endif
|
||||
|
||||
#define lua_tmpnam(b,e) { \
|
||||
strcpy(b, LUA_TMPNAMTEMPLATE); \
|
||||
e = mkstemp(b); \
|
||||
if (e != -1) close(e); \
|
||||
e = (e == -1); }
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
/* ISO C definitions */
|
||||
#define LUA_TMPNAMBUFSIZE L_tmpnam
|
||||
#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
|
||||
|
||||
#endif /* } */
|
||||
|
||||
#endif /* } */
|
||||
/* }================================================================== */
|
||||
|
||||
|
||||
|
||||
|
||||
static int os_execute (lua_State *L) {
|
||||
const char *cmd = luaL_optstring(L, 1, NULL);
|
||||
int stat = system(cmd);
|
||||
if (cmd != NULL)
|
||||
return luaL_execresult(L, stat);
|
||||
else {
|
||||
lua_pushboolean(L, stat); /* true if there is a shell */
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int os_remove (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
return luaL_fileresult(L, remove(filename) == 0, filename);
|
||||
}
|
||||
|
||||
|
||||
static int os_rename (lua_State *L) {
|
||||
const char *fromname = luaL_checkstring(L, 1);
|
||||
const char *toname = luaL_checkstring(L, 2);
|
||||
return luaL_fileresult(L, rename(fromname, toname) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int os_tmpname (lua_State *L) {
|
||||
char buff[LUA_TMPNAMBUFSIZE];
|
||||
int err;
|
||||
lua_tmpnam(buff, err);
|
||||
if (err)
|
||||
return luaL_error(L, "unable to generate a unique filename");
|
||||
lua_pushstring(L, buff);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int os_getenv (lua_State *L) {
|
||||
lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int os_clock (lua_State *L) {
|
||||
lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Time/Date operations
|
||||
** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,
|
||||
** wday=%w+1, yday=%j, isdst=? }
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
static void setfield (lua_State *L, const char *key, int value) {
|
||||
lua_pushinteger(L, value);
|
||||
lua_setfield(L, -2, key);
|
||||
}
|
||||
|
||||
static void setboolfield (lua_State *L, const char *key, int value) {
|
||||
if (value < 0) /* undefined? */
|
||||
return; /* does not set field */
|
||||
lua_pushboolean(L, value);
|
||||
lua_setfield(L, -2, key);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Set all fields from structure 'tm' in the table on top of the stack
|
||||
*/
|
||||
static void setallfields (lua_State *L, struct tm *stm) {
|
||||
setfield(L, "sec", stm->tm_sec);
|
||||
setfield(L, "min", stm->tm_min);
|
||||
setfield(L, "hour", stm->tm_hour);
|
||||
setfield(L, "day", stm->tm_mday);
|
||||
setfield(L, "month", stm->tm_mon + 1);
|
||||
setfield(L, "year", stm->tm_year + 1900);
|
||||
setfield(L, "wday", stm->tm_wday + 1);
|
||||
setfield(L, "yday", stm->tm_yday + 1);
|
||||
setboolfield(L, "isdst", stm->tm_isdst);
|
||||
}
|
||||
|
||||
|
||||
static int getboolfield (lua_State *L, const char *key) {
|
||||
int res;
|
||||
res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* maximum value for date fields (to avoid arithmetic overflows with 'int') */
|
||||
#if !defined(L_MAXDATEFIELD)
|
||||
#define L_MAXDATEFIELD (INT_MAX / 2)
|
||||
#endif
|
||||
|
||||
static int getfield (lua_State *L, const char *key, int d, int delta) {
|
||||
int isnum;
|
||||
int t = lua_getfield(L, -1, key); /* get field and its type */
|
||||
lua_Integer res = lua_tointegerx(L, -1, &isnum);
|
||||
if (!isnum) { /* field is not an integer? */
|
||||
if (t != LUA_TNIL) /* some other value? */
|
||||
return luaL_error(L, "field '%s' is not an integer", key);
|
||||
else if (d < 0) /* absent field; no default? */
|
||||
return luaL_error(L, "field '%s' missing in date table", key);
|
||||
res = d;
|
||||
}
|
||||
else {
|
||||
if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD))
|
||||
return luaL_error(L, "field '%s' is out-of-bound", key);
|
||||
res -= delta;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
|
||||
static const char *checkoption (lua_State *L, const char *conv,
|
||||
ptrdiff_t convlen, char *buff) {
|
||||
const char *option = LUA_STRFTIMEOPTIONS;
|
||||
int oplen = 1; /* length of options being checked */
|
||||
for (; *option != '\0' && oplen <= convlen; option += oplen) {
|
||||
if (*option == '|') /* next block? */
|
||||
oplen++; /* will check options with next length (+1) */
|
||||
else if (memcmp(conv, option, oplen) == 0) { /* match? */
|
||||
memcpy(buff, conv, oplen); /* copy valid option to buffer */
|
||||
buff[oplen] = '\0';
|
||||
return conv + oplen; /* return next item */
|
||||
}
|
||||
}
|
||||
luaL_argerror(L, 1,
|
||||
lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv));
|
||||
return conv; /* to avoid warnings */
|
||||
}
|
||||
|
||||
|
||||
/* maximum size for an individual 'strftime' item */
|
||||
#define SIZETIMEFMT 250
|
||||
|
||||
|
||||
static int os_date (lua_State *L) {
|
||||
size_t slen;
|
||||
const char *s = luaL_optlstring(L, 1, "%c", &slen);
|
||||
time_t t = luaL_opt(L, l_checktime, 2, time(NULL));
|
||||
const char *se = s + slen; /* 's' end */
|
||||
struct tm tmr, *stm;
|
||||
if (*s == '!') { /* UTC? */
|
||||
stm = l_gmtime(&t, &tmr);
|
||||
s++; /* skip '!' */
|
||||
}
|
||||
else
|
||||
stm = l_localtime(&t, &tmr);
|
||||
if (stm == NULL) /* invalid date? */
|
||||
return luaL_error(L,
|
||||
"time result cannot be represented in this installation");
|
||||
if (strcmp(s, "*t") == 0) {
|
||||
lua_createtable(L, 0, 9); /* 9 = number of fields */
|
||||
setallfields(L, stm);
|
||||
}
|
||||
else {
|
||||
char cc[4]; /* buffer for individual conversion specifiers */
|
||||
luaL_Buffer b;
|
||||
cc[0] = '%';
|
||||
luaL_buffinit(L, &b);
|
||||
while (s < se) {
|
||||
if (*s != '%') /* not a conversion specifier? */
|
||||
luaL_addchar(&b, *s++);
|
||||
else {
|
||||
size_t reslen;
|
||||
char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT);
|
||||
s++; /* skip '%' */
|
||||
s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */
|
||||
reslen = strftime(buff, SIZETIMEFMT, cc, stm);
|
||||
luaL_addsize(&b, reslen);
|
||||
}
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int os_time (lua_State *L) {
|
||||
time_t t;
|
||||
if (lua_isnoneornil(L, 1)) /* called without args? */
|
||||
t = time(NULL); /* get current time */
|
||||
else {
|
||||
struct tm ts;
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_settop(L, 1); /* make sure table is at the top */
|
||||
ts.tm_sec = getfield(L, "sec", 0, 0);
|
||||
ts.tm_min = getfield(L, "min", 0, 0);
|
||||
ts.tm_hour = getfield(L, "hour", 12, 0);
|
||||
ts.tm_mday = getfield(L, "day", -1, 0);
|
||||
ts.tm_mon = getfield(L, "month", -1, 1);
|
||||
ts.tm_year = getfield(L, "year", -1, 1900);
|
||||
ts.tm_isdst = getboolfield(L, "isdst");
|
||||
t = mktime(&ts);
|
||||
setallfields(L, &ts); /* update fields with normalized values */
|
||||
}
|
||||
if (t != (time_t)(l_timet)t || t == (time_t)(-1))
|
||||
return luaL_error(L,
|
||||
"time result cannot be represented in this installation");
|
||||
l_pushtime(L, t);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int os_difftime (lua_State *L) {
|
||||
time_t t1 = l_checktime(L, 1);
|
||||
time_t t2 = l_checktime(L, 2);
|
||||
lua_pushnumber(L, (lua_Number)difftime(t1, t2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static int os_setlocale (lua_State *L) {
|
||||
static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
|
||||
LC_NUMERIC, LC_TIME};
|
||||
static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
|
||||
"numeric", "time", NULL};
|
||||
const char *l = luaL_optstring(L, 1, NULL);
|
||||
int op = luaL_checkoption(L, 2, "all", catnames);
|
||||
lua_pushstring(L, setlocale(cat[op], l));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int os_exit (lua_State *L) {
|
||||
int status;
|
||||
if (lua_isboolean(L, 1))
|
||||
status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
else
|
||||
status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS);
|
||||
if (lua_toboolean(L, 2))
|
||||
lua_close(L);
|
||||
if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg syslib[] = {
|
||||
{"clock", os_clock},
|
||||
{"date", os_date},
|
||||
{"difftime", os_difftime},
|
||||
{"execute", os_execute},
|
||||
{"exit", os_exit},
|
||||
{"getenv", os_getenv},
|
||||
{"remove", os_remove},
|
||||
{"rename", os_rename},
|
||||
{"setlocale", os_setlocale},
|
||||
{"time", os_time},
|
||||
{"tmpname", os_tmpname},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_os (lua_State *L) {
|
||||
luaL_newlib(L, syslib);
|
||||
return 1;
|
||||
}
|
||||
|
623
components/lua/lua-5.3/host/luac.c
Normal file
623
components/lua/lua-5.3/host/luac.c
Normal file
@ -0,0 +1,623 @@
|
||||
/*
|
||||
** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $
|
||||
** Lua compiler (saves bytecodes to files; also lists bytecodes)
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define luac_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
#include <alloca.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "ldebug.h"
|
||||
#include "lnodemcu.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
#include "lundump.h"
|
||||
|
||||
static void PrintFunction(const Proto* f, int full);
|
||||
#define luaU_print PrintFunction
|
||||
|
||||
#define PROGNAME "luac.cross" /* default program name */
|
||||
#define OUTPUT PROGNAME ".out" /* default output file */
|
||||
|
||||
static int listing=0; /* list bytecodes? */
|
||||
static int dumping=1; /* dump bytecodes? */
|
||||
static int stripping=0; /* strip debug information? */
|
||||
static char Output[]={ OUTPUT }; /* default output file name */
|
||||
static const char* output=Output; /* actual output file name */
|
||||
static const char* progname=PROGNAME; /* actual program name */
|
||||
static int flash = 0; /* output flash image */
|
||||
static lu_int32 address = 0; /* output flash image at absolute location */
|
||||
static lu_int32 maxSize = 0x40000; /* maximuum uncompressed image size */
|
||||
static int lookup = 0; /* output lookup-style master combination header */
|
||||
static const char *execute; /* executed a Lua file */
|
||||
char *LFSimageName;
|
||||
|
||||
#if 0
|
||||
#define IROM0_SEG 0x40200000ul
|
||||
#define IROM0_SEGMAX 0x00100000ul
|
||||
#define IROM_OFFSET(a) (cast(lu_int32, (a)) - IROM0_SEG)
|
||||
#else
|
||||
// Safety checks disabled for now; would need to handle ESP32/ESP32S/ESP32C3
|
||||
#define IROM_OFFSET(a)
|
||||
#endif
|
||||
|
||||
|
||||
static void fatal(const char *message) {
|
||||
fprintf(stderr, "%s: %s\n", progname, message);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void cannot(const char *what) {
|
||||
fprintf(stderr, "%s: cannot %s %s: %s\n", progname, what, output, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void usage(const char *message) {
|
||||
if ( *message == '-')
|
||||
fprintf(stderr, "%s: unrecognized option '%s'\n", progname, message);
|
||||
else
|
||||
fprintf(stderr, "%s: %s\n", progname, message);
|
||||
fprintf(stderr,
|
||||
"usage: %s [options] [filenames]\n"
|
||||
"Available options are:\n"
|
||||
" -l list (use -l -l for full listing)\n"
|
||||
" -o name output to file 'name' (default is \"%s\")\n"
|
||||
" -e name execute a lua source file\n"
|
||||
" -f output a flash image file\n"
|
||||
" -F name load a flash image file\n"
|
||||
" -a addr generate an absolute, rather than "
|
||||
"position independent flash image file\n"
|
||||
" (use with -F LFSimage -o absLFSimage to "
|
||||
"convert an image to absolute format)\n"
|
||||
" -i generate lookup combination master (default with option -f)\n"
|
||||
" -m size maximum LFS image in bytes\n"
|
||||
" -p parse only\n"
|
||||
" -s strip debug information\n"
|
||||
" -v show version information\n"
|
||||
" -- stop handling options\n"
|
||||
" - stop handling options and process stdin\n", progname, Output);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#define IS(s) (strcmp(argv[i],s)==0)
|
||||
|
||||
static int doargs(int argc, char *argv[]) {
|
||||
int i;
|
||||
int version = 0;
|
||||
lu_int32 offset = 0;
|
||||
if (argv[0] != NULL && *argv[0] != 0) progname = argv[0];
|
||||
for (i = 1; i < argc; i++) {
|
||||
if ( *argv[i] != '-') { /* end of options; keep it */
|
||||
break;
|
||||
} else if (IS("--")) { /* end of options; skip it */
|
||||
++i;
|
||||
if (version) ++version;
|
||||
break;
|
||||
} else if (IS("-")) { /* end of options; use stdin */
|
||||
break;
|
||||
} else if (IS("-e")) { /* execute a lua source file file */
|
||||
execute = argv[++i];
|
||||
if (execute == NULL || *execute == 0 || *execute == '-')
|
||||
usage("\"-e\" needs a file argument");
|
||||
} else if (IS("-F")) { /* execute a lua source file file */
|
||||
LFSimageName = argv[++i];
|
||||
if (LFSimageName == NULL || *LFSimageName == 0 || *LFSimageName == '-')
|
||||
usage("\"-F\" needs an LFS image file argument");
|
||||
} else if (IS("-f")) { /* Flash image file */
|
||||
flash = lookup = 1;
|
||||
} else if (IS("-a")) { /* Absolue flash image file */
|
||||
flash = lookup = 1;
|
||||
address = strtol(argv[++i], NULL, 0);
|
||||
#if 0
|
||||
offset = IROM_OFFSET(address);
|
||||
if (offset == 0 || offset > IROM0_SEGMAX)
|
||||
usage("\"-a\" absolute address must be valid flash address");
|
||||
#endif
|
||||
} else if (IS("-i")) { /* lookup */
|
||||
lookup = 1;
|
||||
} else if (IS("-l")) { /* list */
|
||||
++listing;
|
||||
} else if (IS("-m")) { /* specify a maximum image size */
|
||||
flash = lookup = 1;
|
||||
maxSize = strtol(argv[++i], NULL, 0);
|
||||
if (maxSize & 0xFFF)
|
||||
usage("\"-m\" maximum size must be a multiple of 4,096");
|
||||
} else if (IS("-o")) { /* output file */
|
||||
output = argv[++i];
|
||||
if (output == NULL || *output == 0 || ( *output == '-' && output[1] != 0))
|
||||
usage("'-o' needs argument");
|
||||
if (IS("-")) output = NULL;
|
||||
} else if (IS("-p")) { /* parse only */
|
||||
dumping = 0;
|
||||
} else if (IS("-s")) { /* strip debug information */
|
||||
stripping = 1;
|
||||
} else if (IS("-v")) { /* show version */
|
||||
++version;
|
||||
} else { /* unknown option */
|
||||
usage(argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (offset>0 && (output == NULL || LFSimageName == NULL ||
|
||||
execute != NULL || i != argc))
|
||||
usage("'-a' also requires '-o' and '-f' options without lua source files");
|
||||
|
||||
if (i == argc && (listing || !dumping)) {
|
||||
dumping = 0;
|
||||
argv[--i] = Output;
|
||||
}
|
||||
if (version) {
|
||||
printf("%s\n", LUA_COPYRIGHT);
|
||||
if (version == argc - 1) exit(EXIT_SUCCESS);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static const char *corename(lua_State *L, const TString *filename, int *len) {
|
||||
(void)L;
|
||||
const char *fn = getstr(filename) + 1;
|
||||
const char *s = strrchr(fn, '/');
|
||||
if (!s) s = strrchr(fn, '\\');
|
||||
s = s ? s + 1 : fn;
|
||||
while ( *s == '.') s++;
|
||||
const char *e = strchr(s, '.');
|
||||
if (len)
|
||||
*len = e ? e - s : strlen(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
/*
|
||||
** If the luac command line includes multiple files or has the -f option
|
||||
** then luac generates a main function to reference all sub-main prototypes.
|
||||
** This is one of two types:
|
||||
** Type 0 The standard luac combination main
|
||||
** Type 1 A lookup wrapper that is used for LFS image dumps
|
||||
*/
|
||||
#define toproto(L, i) getproto(L->top + (i))
|
||||
|
||||
static const Proto *combine(lua_State *L, int n, int type) {
|
||||
if (n == 1 && type == 0) {
|
||||
return toproto(L, -1);
|
||||
} else {
|
||||
Proto *f;
|
||||
int i, j;
|
||||
/*
|
||||
* Generate a minimal proto with 1 return, emtpy p, k & uv vectors
|
||||
*/
|
||||
if (luaL_loadbuffer(L, "\n", strlen("\n"), "=("PROGNAME ")") != LUA_OK)
|
||||
fatal(lua_tostring(L, -1));
|
||||
f = toproto(L, -1);
|
||||
/*
|
||||
* Allocate the vector for and bind the sub-protos
|
||||
*/
|
||||
luaM_reallocvector(L, f->p, f->sizep, n, Proto *);
|
||||
f->sizep = n;
|
||||
for (i = 0; i < n; i++) {
|
||||
f->p[i] = toproto(L, i - n - 1);
|
||||
if (f->p[i]->sizeupvalues > 0)
|
||||
f->p[i]->upvalues[0].instack = 0;
|
||||
}
|
||||
f->numparams = 0;
|
||||
f->maxstacksize = 1;
|
||||
if (type == 1) {
|
||||
/*
|
||||
* For Type 1 main(), add a k vector of strings naming the corresponding
|
||||
* protos with the Unixtime of the compile appended.
|
||||
*/
|
||||
luaM_reallocvector(L, f->k, f->sizek, n+1, TValue);
|
||||
f->sizek = n + 1;
|
||||
for (i = 0; i < n; i++) {
|
||||
int len;
|
||||
const char *name = corename(L, f->p[i]->source, &len);
|
||||
TString* sname = luaS_newlstr(L, name, len);
|
||||
for (j = 0; j < i; j++) {
|
||||
if (tsvalue(f->k+j) == sname)
|
||||
fatal(lua_pushfstring(L, "Cannot have duplicate files ('%s') in LFS", name));
|
||||
}
|
||||
setsvalue2n(L, f->k+i, sname);
|
||||
}
|
||||
setivalue(f->k+n, (lua_Integer) time(NULL));
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
static int writer(lua_State *L, const void *p, size_t size, void *u) {
|
||||
UNUSED(L);
|
||||
return (fwrite(p, size, 1, ((FILE **)u)[0]) != 1) && (size != 0);
|
||||
}
|
||||
|
||||
|
||||
static int msghandler (lua_State *L) {
|
||||
const char *msg = lua_tostring(L, 1);
|
||||
if (msg == NULL) /* is error object not a string? */
|
||||
msg = lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1));
|
||||
luaL_traceback(L, L, msg, 1); /* append a standard traceback */
|
||||
return 1; /* return the traceback */
|
||||
}
|
||||
|
||||
|
||||
static int dofile (lua_State *L, const char *name) {
|
||||
int status = luaL_loadfile(L, name);
|
||||
if (status == LUA_OK) {
|
||||
int base = lua_gettop(L);
|
||||
lua_pushcfunction(L, msghandler); /* push message handler */
|
||||
lua_insert(L, base); /* put it under function and args */
|
||||
status = lua_pcall(L, 0, 0, base);
|
||||
lua_remove(L, base); /* remove message handler from the stack */
|
||||
}
|
||||
if (status != LUA_OK) {
|
||||
fprintf(stderr, "%s: %s\n", PROGNAME, lua_tostring(L, -1));
|
||||
lua_pop(L, 1); /* remove message */
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is an inintended consequence of constraints in ltable.c
|
||||
** rotable_findentry(). The file list generates a ROTable in LFS and the
|
||||
** rule for ROTables is that metavalue entries must be at the head of the
|
||||
** ROTableentry list so argv file names with basenames starting with "__"
|
||||
** must be head of the list. This is a botch. Sorry.
|
||||
*/
|
||||
static void reorderfiles(lua_State *L, int argc, char **list, char **argv) {
|
||||
int i, j;
|
||||
for (i = 0; i < argc; i++ ) {
|
||||
TString *file = luaS_new(L,argv[i]);
|
||||
if (strcmp("__", corename(L, file, NULL))) {
|
||||
list[i] = argv[i]; /* add to the end of the new list */
|
||||
} else {
|
||||
for (j = 0; j < i; j++)
|
||||
list[j+1] = list[j];
|
||||
list[0] = argv[i]; /* add to the start of the new list */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int pmain(lua_State *L) {
|
||||
int argc = (int) lua_tointeger(L, 1);
|
||||
char **argv = (char **) lua_touserdata(L, 2);
|
||||
char **filelist = alloca(argc * sizeof(char *));
|
||||
const Proto *f;
|
||||
int i, status;
|
||||
if (!lua_checkstack(L, argc + 1))
|
||||
fatal("too many input files");
|
||||
if (execute || address) {
|
||||
luaL_openlibs(L); /* the nodemcu open will throw to signal an LFS reload */
|
||||
status = dofile(L, execute);
|
||||
if (status != LUA_OK)
|
||||
return 0;
|
||||
}
|
||||
if (argc == 0)
|
||||
return 0;
|
||||
reorderfiles(L, argc, filelist, argv);
|
||||
for (i = 0; i < argc; i++) {
|
||||
const char *filename = IS("-") ? NULL : filelist[i];
|
||||
if (luaL_loadfile(L, filename) != LUA_OK)
|
||||
fatal(lua_tostring(L, -1));
|
||||
//TODO: if strip = 2, replace proto->source by basename
|
||||
}
|
||||
f = combine(L, argc + (execute ? 1 : 0), lookup);
|
||||
if (listing) luaU_print(f, listing > 1);
|
||||
if (dumping) {
|
||||
int result;
|
||||
FILE *D = (output == NULL) ? stdout : fopen(output, "wb");
|
||||
if (D == NULL) cannot("open");
|
||||
lua_lock(L);
|
||||
if (flash) {
|
||||
UNUSED(address);
|
||||
UNUSED(maxSize);
|
||||
result = luaU_DumpAllProtos(L, f, writer, &D, stripping);
|
||||
} else {
|
||||
result = luaU_dump(L, f, writer, cast(void *, &D), stripping);
|
||||
}
|
||||
lua_unlock(L);
|
||||
if (result == LUA_ERR_CC_INTOVERFLOW)
|
||||
fatal("value too big or small for target integer type");
|
||||
if (result == LUA_ERR_CC_NOTINTEGER)
|
||||
fatal("target lua_Number is integral but fractional value found");
|
||||
if (ferror(D)) cannot("write");
|
||||
if (fclose(D)) cannot("close");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
lua_State *L;
|
||||
int i = doargs(argc, argv);
|
||||
int j, status;
|
||||
argc -= i; argv += i;
|
||||
if (argc <= 0 && execute == 0 && address == 0) usage("no input files given");
|
||||
if (address)
|
||||
luaN_setabsolute(address);
|
||||
for (j = 0; j < 2 ; j++) {
|
||||
L = luaL_newstate();
|
||||
if (L == NULL) fatal("not enough memory for state");
|
||||
lua_pushcfunction(L, &pmain);
|
||||
lua_pushinteger(L, argc);
|
||||
lua_pushlightuserdata(L, argv);
|
||||
status = lua_pcall(L, 2, 0, 0);
|
||||
if (status != LUA_OK) {
|
||||
const char *res = luaL_optstring(L, -1, "");
|
||||
if (strcmp(res, "!LFSrestart!") == 0) {
|
||||
/*An LFS image has been loaded */
|
||||
if (address) { /* write out as absolute image and exit */
|
||||
lu_int32 size = cast(LFSHeader *, LFSregion)->flash_size;
|
||||
FILE *af = fopen(output, "wb");
|
||||
if (af == NULL) cannot("open");
|
||||
if (fwrite(LFSregion, size, 1, af) != 1) cannot("write");
|
||||
fclose(af);
|
||||
exit(0);
|
||||
}
|
||||
/*otherwise simulate a restart */
|
||||
lua_close(L);
|
||||
continue; /* and loop around once more simulating restart */
|
||||
}
|
||||
char *err = strdup(lua_tostring(L, -1));
|
||||
lua_close(L);
|
||||
fatal(err);
|
||||
}
|
||||
lua_close(L);
|
||||
break;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
** $Id: luac.c,v 1.76 2018/06/19 01:32:02 lhf Exp $
|
||||
** print bytecodes
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define luac_c
|
||||
#define LUA_CORE
|
||||
|
||||
#include "ldebug.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
|
||||
#define VOID(p) ((const void*)(p))
|
||||
|
||||
static void PrintString(const TString* ts)
|
||||
{
|
||||
const char* s=getstr(ts);
|
||||
size_t i,n=tsslen(ts);
|
||||
printf("%c",'"');
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
int c=(int)(unsigned char)s[i];
|
||||
switch (c)
|
||||
{
|
||||
case '"': printf("\\\""); break;
|
||||
case '\\': printf("\\\\"); break;
|
||||
case '\a': printf("\\a"); break;
|
||||
case '\b': printf("\\b"); break;
|
||||
case '\f': printf("\\f"); break;
|
||||
case '\n': printf("\\n"); break;
|
||||
case '\r': printf("\\r"); break;
|
||||
case '\t': printf("\\t"); break;
|
||||
case '\v': printf("\\v"); break;
|
||||
default: if (isprint(c))
|
||||
printf("%c",c);
|
||||
else
|
||||
printf("\\%03d",c);
|
||||
}
|
||||
}
|
||||
printf("%c",'"');
|
||||
}
|
||||
|
||||
static void PrintConstant(const Proto* f, int i)
|
||||
{
|
||||
const TValue* o=&f->k[i];
|
||||
switch (ttype(o))
|
||||
{
|
||||
case LUA_TNIL:
|
||||
printf("nil");
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
printf(bvalue(o) ? "true" : "false");
|
||||
break;
|
||||
case LUA_TNUMFLT:
|
||||
{
|
||||
char buff[100];
|
||||
sprintf(buff,LUA_NUMBER_FMT,fltvalue(o));
|
||||
printf("%s",buff);
|
||||
if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0");
|
||||
break;
|
||||
}
|
||||
case LUA_TNUMINT:
|
||||
printf(LUA_INTEGER_FMT,ivalue(o));
|
||||
break;
|
||||
case LUA_TSHRSTR: case LUA_TLNGSTR:
|
||||
PrintString(tsvalue(o));
|
||||
break;
|
||||
default: /* cannot happen */
|
||||
printf("? type=%d",ttype(o));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
|
||||
#define MYK(x) (-1-(x))
|
||||
|
||||
static void PrintCode(const Proto* f)
|
||||
{
|
||||
const Instruction* code=f->code;
|
||||
int pc,n=f->sizecode;
|
||||
for (pc=0; pc<n; pc++)
|
||||
{
|
||||
Instruction i=code[pc];
|
||||
OpCode o=GET_OPCODE(i);
|
||||
int a=GETARG_A(i);
|
||||
int b=GETARG_B(i);
|
||||
int c=GETARG_C(i);
|
||||
int ax=GETARG_Ax(i);
|
||||
int bx=GETARG_Bx(i);
|
||||
int sbx=GETARG_sBx(i);
|
||||
int line=getfuncline(f,pc);
|
||||
printf("\t%d\t",pc+1);
|
||||
if (line>0) printf("[%d]\t",line); else printf("[-]\t");
|
||||
printf("%-9s\t",luaP_opnames[o]);
|
||||
switch (getOpMode(o))
|
||||
{
|
||||
case iABC:
|
||||
printf("%d",a);
|
||||
if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b);
|
||||
if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c);
|
||||
break;
|
||||
case iABx:
|
||||
printf("%d",a);
|
||||
if (getBMode(o)==OpArgK) printf(" %d",MYK(bx));
|
||||
if (getBMode(o)==OpArgU) printf(" %d",bx);
|
||||
break;
|
||||
case iAsBx:
|
||||
printf("%d %d",a,sbx);
|
||||
break;
|
||||
case iAx:
|
||||
printf("%d",MYK(ax));
|
||||
break;
|
||||
}
|
||||
switch (o)
|
||||
{
|
||||
case OP_LOADK:
|
||||
printf("\t; "); PrintConstant(f,bx);
|
||||
break;
|
||||
case OP_GETUPVAL:
|
||||
case OP_SETUPVAL:
|
||||
printf("\t; %s",UPVALNAME(b));
|
||||
break;
|
||||
case OP_GETTABUP:
|
||||
printf("\t; %s",UPVALNAME(b));
|
||||
if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
|
||||
break;
|
||||
case OP_SETTABUP:
|
||||
printf("\t; %s",UPVALNAME(a));
|
||||
if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); }
|
||||
if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); }
|
||||
break;
|
||||
case OP_GETTABLE:
|
||||
case OP_SELF:
|
||||
if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); }
|
||||
break;
|
||||
case OP_SETTABLE:
|
||||
case OP_ADD:
|
||||
case OP_SUB:
|
||||
case OP_MUL:
|
||||
case OP_MOD:
|
||||
case OP_POW:
|
||||
case OP_DIV:
|
||||
case OP_IDIV:
|
||||
case OP_BAND:
|
||||
case OP_BOR:
|
||||
case OP_BXOR:
|
||||
case OP_SHL:
|
||||
case OP_SHR:
|
||||
case OP_EQ:
|
||||
case OP_LT:
|
||||
case OP_LE:
|
||||
if (ISK(b) || ISK(c))
|
||||
{
|
||||
printf("\t; ");
|
||||
if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-");
|
||||
printf(" ");
|
||||
if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-");
|
||||
}
|
||||
break;
|
||||
case OP_JMP:
|
||||
case OP_FORLOOP:
|
||||
case OP_FORPREP:
|
||||
case OP_TFORLOOP:
|
||||
printf("\t; to %d",sbx+pc+2);
|
||||
break;
|
||||
case OP_CLOSURE:
|
||||
printf("\t; %p",VOID(f->p[bx]));
|
||||
break;
|
||||
case OP_SETLIST:
|
||||
if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c);
|
||||
break;
|
||||
case OP_EXTRAARG:
|
||||
printf("\t; "); PrintConstant(f,ax);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define SS(x) ((x==1)?"":"s")
|
||||
#define S(x) (int)(x),SS(x)
|
||||
|
||||
static void PrintHeader(const Proto* f)
|
||||
{
|
||||
const char* s=f->source ? getstr(f->source) : "=?";
|
||||
if (*s=='@' || *s=='=')
|
||||
s++;
|
||||
else if (*s==LUA_SIGNATURE[0])
|
||||
s="(bstring)";
|
||||
else
|
||||
s="(string)";
|
||||
printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
|
||||
(f->linedefined==0)?"main":"function",s,
|
||||
f->linedefined,f->lastlinedefined,
|
||||
S(f->sizecode),VOID(f));
|
||||
printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
|
||||
(int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams),
|
||||
S(f->maxstacksize),S(f->sizeupvalues));
|
||||
printf("%d local%s, %d constant%s, %d function%s\n",
|
||||
S(f->sizelocvars),S(f->sizek),S(f->sizep));
|
||||
}
|
||||
|
||||
static void PrintDebug(const Proto* f)
|
||||
{
|
||||
int i,n;
|
||||
n=f->sizek;
|
||||
printf("constants (%d) for %p:\n",n,VOID(f));
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
printf("\t%d\t",i+1);
|
||||
PrintConstant(f,i);
|
||||
printf("\n");
|
||||
}
|
||||
n=f->sizelocvars;
|
||||
printf("locals (%d) for %p:\n",n,VOID(f));
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
printf("\t%d\t%s\t%d\t%d\n",
|
||||
i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
|
||||
}
|
||||
n=f->sizeupvalues;
|
||||
printf("upvalues (%d) for %p:\n",n,VOID(f));
|
||||
for (i=0; i<n; i++)
|
||||
{
|
||||
printf("\t%d\t%s\t%d\t%d\n",
|
||||
i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintFunction(const Proto* f, int full)
|
||||
{
|
||||
int i,n=f->sizep;
|
||||
PrintHeader(f);
|
||||
PrintCode(f);
|
||||
if (full) PrintDebug(f);
|
||||
for (i=0; i<n; i++) PrintFunction(f->p[i],full);
|
||||
}
|
1348
components/lua/lua-5.3/lapi.c
Normal file
1348
components/lua/lua-5.3/lapi.c
Normal file
File diff suppressed because it is too large
Load Diff
24
components/lua/lua-5.3/lapi.h
Normal file
24
components/lua/lua-5.3/lapi.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
** $Id: lapi.h,v 2.9.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions from Lua API
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#ifndef lapi_h
|
||||
#define lapi_h
|
||||
|
||||
|
||||
#include "llimits.h"
|
||||
#include "lstate.h"
|
||||
|
||||
#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \
|
||||
"stack overflow");}
|
||||
|
||||
#define adjustresults(L,nres) \
|
||||
{ if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; }
|
||||
|
||||
#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \
|
||||
"not enough elements in the stack")
|
||||
|
||||
|
||||
#endif
|
1178
components/lua/lua-5.3/lauxlib.c
Normal file
1178
components/lua/lua-5.3/lauxlib.c
Normal file
File diff suppressed because it is too large
Load Diff
306
components/lua/lua-5.3/lauxlib.h
Normal file
306
components/lua/lua-5.3/lauxlib.h
Normal file
@ -0,0 +1,306 @@
|
||||
/*
|
||||
** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#ifdef LUA_LIB
|
||||
#include "lnodemcu.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* extra error code for 'luaL_loadfilex' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
|
||||
/* key, in the registry, for table of loaded modules */
|
||||
#define LUA_LOADED_TABLE "_LOADED"
|
||||
|
||||
|
||||
/* key, in the registry, for table of preloaded loaders */
|
||||
#define LUA_PRELOAD_TABLE "_PRELOAD"
|
||||
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
|
||||
#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number))
|
||||
|
||||
LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz);
|
||||
#define luaL_checkversion(L) \
|
||||
luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES)
|
||||
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg,
|
||||
lua_Integer def);
|
||||
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int arg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API int (luaL_rometatable) (lua_State *L, const char* tname, const ROTable *p);
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname);
|
||||
LUALIB_API int (luaL_execresult) (lua_State *L, int stat);
|
||||
|
||||
/* predefined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
#define luaL_unref2(l,t,r) do {luaL_unref(L, (t), (r)); r = LUA_NOREF;} while (0)
|
||||
LUALIB_API void (luaL_reref) (lua_State *L, int t, int *ref);
|
||||
|
||||
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
|
||||
#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL)
|
||||
|
||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name, const char *mode);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx);
|
||||
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
||||
const char *r);
|
||||
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
|
||||
LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname);
|
||||
|
||||
LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1,
|
||||
const char *msg, int level);
|
||||
|
||||
LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
|
||||
lua_CFunction openf, int glb);
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
|
||||
#define luaL_newlibtable(L,l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
|
||||
#define luaL_newlib(L,l) \
|
||||
(luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
|
||||
|
||||
#define luaL_argcheck(L, cond,arg,extramsg) \
|
||||
((void)((cond) || luaL_argerror(L, (arg), (extramsg))))
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
#define luaL_dofile(L, fn) \
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_dostring(L, s) \
|
||||
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
||||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL)
|
||||
|
||||
|
||||
#define luaL_checkfunction(L,n) luaL_checktype(L, (n), LUA_TFUNCTION);
|
||||
#define luaL_checktable(L,n) luaL_checktype(L, (n), LUA_TTABLE);
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char *b; /* buffer address */
|
||||
size_t size; /* buffer size */
|
||||
size_t n; /* number of characters in buffer */
|
||||
lua_State *L;
|
||||
char initb[LUAL_BUFFERSIZE]; /* initial buffer */
|
||||
} luaL_Buffer;
|
||||
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \
|
||||
((B)->b[(B)->n++] = (c)))
|
||||
|
||||
#define luaL_addsize(B,s) ((B)->n += (s))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz);
|
||||
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
|
||||
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
|
||||
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz);
|
||||
LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz);
|
||||
|
||||
#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE)
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** File handles for IO library
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and
|
||||
** initial structure 'luaL_Stream' (it may contain other fields
|
||||
** after that initial structure).
|
||||
*/
|
||||
|
||||
#define LUA_FILEHANDLE "FILE*"
|
||||
|
||||
|
||||
typedef struct luaL_Stream {
|
||||
FILE *f; /* stream (NULL for incompletely created streams) */
|
||||
lua_CFunction closef; /* to close stream (NULL for closed streams) */
|
||||
} luaL_Stream;
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
LUALIB_API int (luaL_rometatable) (lua_State *L, const char* tname, const ROTable *t);
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
/* compatibility with old module system */
|
||||
#if defined(LUA_COMPAT_MODULE)
|
||||
|
||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
||||
int sizehint);
|
||||
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup);
|
||||
|
||||
#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** "Abstraction Layer" for basic report of messages and errors
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
/* print a string */
|
||||
#if !defined(lua_writestring)
|
||||
#ifdef LUA_USE_ESP
|
||||
void output_redirect(const char *str, size_t l);
|
||||
#define lua_writestring(s,l) output_redirect((s),(l))
|
||||
#else
|
||||
#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* print a newline and flush the output */
|
||||
#if !defined(lua_writeline)
|
||||
#ifdef LUA_USE_ESP8266
|
||||
#define lua_writeline() lua_writestring("\n", 1)
|
||||
#else
|
||||
#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* print an error message. This is a primitive error output */
|
||||
#if !defined(lua_writestringerror)
|
||||
#ifdef LUA_USE_ESP8266
|
||||
extern void dbg_printf(const char *fmt, ...);
|
||||
#define lua_writestringerror(s,p) dbg_printf((s), (p))
|
||||
#else
|
||||
#define lua_writestringerror(s,p) (fprintf(stderr, (s), (p)), fflush(stderr))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* }================================================================== */
|
||||
|
||||
/*
|
||||
** {============================================================
|
||||
** Compatibility with deprecated conversions
|
||||
** =============================================================
|
||||
*/
|
||||
#if defined(LUA_COMPAT_APIINTCASTS)
|
||||
|
||||
#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a))
|
||||
#define luaL_optunsigned(L,a,d) \
|
||||
((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d)))
|
||||
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#endif
|
||||
/* }============================================================ */
|
||||
|
||||
/*
|
||||
** {==================================================================
|
||||
** NodeMCU extensions
|
||||
** ===================================================================
|
||||
*/
|
||||
|
||||
#define LUA_TASK_LOW 0
|
||||
#define LUA_TASK_MEDIUM 1
|
||||
#define LUA_TASK_HIGH 2
|
||||
|
||||
LUALIB_API int (luaL_pushlfsmodules) (lua_State *L);
|
||||
LUALIB_API int (luaL_pushlfsdts) (lua_State *L);
|
||||
LUALIB_API void (luaL_lfsreload) (lua_State *L);
|
||||
LUALIB_API int (luaL_posttask) (lua_State* L, int prio);
|
||||
LUALIB_API int (luaL_pcallx) (lua_State *L, int narg, int nres);
|
||||
#define luaL_pushlfsmodule(l) lua_pushlfsfunc(L)
|
||||
|
||||
/* }============================================================ */
|
||||
|
||||
#ifndef LUA_CROSS_COMPILER
|
||||
int panic_get_nvval(void);
|
||||
void panic_clear_nvval(void);
|
||||
#endif
|
||||
|
||||
#endif
|
525
components/lua/lua-5.3/lbaselib.c
Normal file
525
components/lua/lua-5.3/lbaselib.c
Normal file
@ -0,0 +1,525 @@
|
||||
/*
|
||||
** $Id: lbaselib.c,v 1.314.1.1 2017/04/19 17:39:34 roberto Exp $
|
||||
** Basic library
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lbaselib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
static int luaB_print (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
int i;
|
||||
lua_getglobal(L, "tostring");
|
||||
for (i=1; i<=n; i++) {
|
||||
const char *s;
|
||||
size_t l;
|
||||
lua_pushvalue(L, -1); /* function to be called */
|
||||
lua_pushvalue(L, i); /* value to print */
|
||||
lua_call(L, 1, 1);
|
||||
s = lua_tolstring(L, -1, &l); /* get result */
|
||||
if (s == NULL)
|
||||
return luaL_error(L, "'tostring' must return a string to 'print'");
|
||||
if (i>1) lua_writestring("\t", 1);
|
||||
lua_writestring(s, l);
|
||||
lua_pop(L, 1); /* pop result */
|
||||
}
|
||||
lua_writeline();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define SPACECHARS " \f\n\r\t\v"
|
||||
|
||||
static const char *b_str2int (const char *s, int base, lua_Integer *pn) {
|
||||
lua_Unsigned n = 0;
|
||||
int neg = 0;
|
||||
s += strspn(s, SPACECHARS); /* skip initial spaces */
|
||||
if (*s == '-') { s++; neg = 1; } /* handle signal */
|
||||
else if (*s == '+') s++;
|
||||
if (!isalnum((unsigned char)*s)) /* no digit? */
|
||||
return NULL;
|
||||
do {
|
||||
int digit = (isdigit((unsigned char)*s)) ? *s - '0'
|
||||
: (toupper((unsigned char)*s) - 'A') + 10;
|
||||
if (digit >= base) return NULL; /* invalid numeral */
|
||||
n = n * base + digit;
|
||||
s++;
|
||||
} while (isalnum((unsigned char)*s));
|
||||
s += strspn(s, SPACECHARS); /* skip trailing spaces */
|
||||
*pn = (lua_Integer)((neg) ? (0u - n) : n);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tonumber (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 2)) { /* standard conversion? */
|
||||
luaL_checkany(L, 1);
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */
|
||||
lua_settop(L, 1); /* yes; return it */
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
if (s != NULL && lua_stringtonumber(L, s) == l + 1)
|
||||
return 1; /* successful conversion to number */
|
||||
/* else not a number */
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t l;
|
||||
const char *s;
|
||||
lua_Integer n = 0; /* to avoid warnings */
|
||||
lua_Integer base = luaL_checkinteger(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */
|
||||
s = lua_tolstring(L, 1, &l);
|
||||
luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
|
||||
if (b_str2int(s, (int)base, &n) == s + l) {
|
||||
lua_pushinteger(L, n);
|
||||
return 1;
|
||||
} /* else not a number */
|
||||
} /* else not a number */
|
||||
lua_pushnil(L); /* not a number */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_error (lua_State *L) {
|
||||
int level = (int)luaL_optinteger(L, 2, 1);
|
||||
lua_settop(L, 1);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && level > 0) {
|
||||
luaL_where(L, level); /* add extra information */
|
||||
lua_pushvalue(L, 1);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_getmetatable (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
if (!lua_getmetatable(L, 1)) {
|
||||
lua_pushnil(L);
|
||||
return 1; /* no metatable */
|
||||
}
|
||||
luaL_getmetafield(L, 1, "__metatable");
|
||||
return 1; /* returns either __metatable field (if present) or metatable */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_setmetatable (lua_State *L) {
|
||||
int t = lua_type(L, 2);
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
|
||||
"nil or table expected");
|
||||
if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)
|
||||
return luaL_error(L, "cannot change a protected metatable");
|
||||
lua_settop(L, 2);
|
||||
lua_setmetatable(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawequal (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
luaL_checkany(L, 2);
|
||||
lua_pushboolean(L, lua_rawequal(L, 1, 2));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawlen (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
|
||||
"table or string expected");
|
||||
lua_pushinteger(L, lua_rawlen(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_rawget (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
lua_settop(L, 2);
|
||||
lua_rawget(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luaB_rawset (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
luaL_checkany(L, 2);
|
||||
luaL_checkany(L, 3);
|
||||
lua_settop(L, 3);
|
||||
lua_rawset(L, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_collectgarbage (lua_State *L) {
|
||||
static const char *const opts[] = {"stop", "restart", "collect",
|
||||
"count", "step", "setpause", "setstepmul", "setmemlimit",
|
||||
"isrunning", NULL};
|
||||
static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
|
||||
LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
|
||||
LUA_GCISRUNNING};
|
||||
int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
|
||||
int ex = (int)luaL_optinteger(L, 2, 0);
|
||||
int res = lua_gc(L, o, ex);
|
||||
switch (o) {
|
||||
case LUA_GCCOUNT: {
|
||||
int b = lua_gc(L, LUA_GCCOUNTB, 0);
|
||||
lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024));
|
||||
return 1;
|
||||
}
|
||||
case LUA_GCSTEP: case LUA_GCISRUNNING: {
|
||||
lua_pushboolean(L, res);
|
||||
return 1;
|
||||
}
|
||||
default: {
|
||||
lua_pushinteger(L, res);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_type (lua_State *L) {
|
||||
int t = lua_type(L, 1);
|
||||
luaL_argcheck(L, t != LUA_TNONE, 1, "value expected");
|
||||
lua_pushstring(L, lua_typename(L, t));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int pairsmeta (lua_State *L, const char *method, int iszero,
|
||||
lua_CFunction iter) {
|
||||
luaL_checkany(L, 1);
|
||||
if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */
|
||||
lua_pushcfunction(L, iter); /* will return generator, */
|
||||
lua_pushvalue(L, 1); /* state, */
|
||||
if (iszero) lua_pushinteger(L, 0); /* and initial value */
|
||||
else lua_pushnil(L);
|
||||
}
|
||||
else {
|
||||
lua_pushvalue(L, 1); /* argument 'self' to metamethod */
|
||||
lua_call(L, 1, 3); /* get 3 values from metamethod */
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_next (lua_State *L) {
|
||||
luaL_checktype(L, 1, LUA_TTABLE);
|
||||
lua_settop(L, 2); /* create a 2nd argument if there isn't one */
|
||||
if (lua_next(L, 1))
|
||||
return 2;
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_pairs (lua_State *L) {
|
||||
return pairsmeta(L, "__pairs", 0, luaB_next);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Traversal function for 'ipairs'
|
||||
*/
|
||||
static int ipairsaux (lua_State *L) {
|
||||
lua_Integer i = luaL_checkinteger(L, 2) + 1;
|
||||
lua_pushinteger(L, i);
|
||||
return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** 'ipairs' function. Returns 'ipairsaux', given "table", 0.
|
||||
** (The given "table" may not be a table.)
|
||||
*/
|
||||
static int luaB_ipairs (lua_State *L) {
|
||||
#if defined(LUA_COMPAT_IPAIRS)
|
||||
return pairsmeta(L, "__ipairs", 1, ipairsaux);
|
||||
#else
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushcfunction(L, ipairsaux); /* iteration function */
|
||||
lua_pushvalue(L, 1); /* state */
|
||||
lua_pushinteger(L, 0); /* initial value */
|
||||
return 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int load_aux (lua_State *L, int status, int envidx) {
|
||||
if (status == LUA_OK) {
|
||||
if (envidx != 0) { /* 'env' parameter? */
|
||||
lua_pushvalue(L, envidx); /* environment for loaded function */
|
||||
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
|
||||
lua_pop(L, 1); /* remove 'env' if not used by previous call */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else { /* error (message is on top of the stack) */
|
||||
lua_pushnil(L);
|
||||
lua_insert(L, -2); /* put before error message */
|
||||
return 2; /* return nil plus error message */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_loadfile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
const char *mode = luaL_optstring(L, 2, NULL);
|
||||
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
|
||||
int status = luaL_loadfilex(L, fname, mode);
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Read function
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** reserved slot, above all arguments, to hold a copy of the returned
|
||||
** string to avoid it being collected while parsed. 'load' has four
|
||||
** optional arguments (chunk, source name, mode, and environment).
|
||||
*/
|
||||
#define RESERVEDSLOT 5
|
||||
|
||||
|
||||
/*
|
||||
** Reader for generic 'load' function: 'lua_load' uses the
|
||||
** stack for internal stuff, so the reader cannot change the
|
||||
** stack top. Instead, it keeps its resulting string in a
|
||||
** reserved slot inside the stack.
|
||||
*/
|
||||
static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
|
||||
(void)(ud); /* not used */
|
||||
luaL_checkstack(L, 2, "too many nested functions");
|
||||
lua_pushvalue(L, 1); /* get function */
|
||||
lua_call(L, 0, 1); /* call it */
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 1); /* pop result */
|
||||
*size = 0;
|
||||
return NULL;
|
||||
}
|
||||
else if (!lua_isstring(L, -1))
|
||||
luaL_error(L, "reader function must return a string");
|
||||
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
|
||||
return lua_tolstring(L, RESERVEDSLOT, size);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_load (lua_State *L) {
|
||||
int status;
|
||||
size_t l;
|
||||
const char *s = lua_tolstring(L, 1, &l);
|
||||
const char *mode = luaL_optstring(L, 3, "bt");
|
||||
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
|
||||
if (s != NULL) { /* loading a string? */
|
||||
const char *chunkname = luaL_optstring(L, 2, s);
|
||||
status = luaL_loadbufferx(L, s, l, chunkname, mode);
|
||||
}
|
||||
else { /* loading from a reader function */
|
||||
const char *chunkname = luaL_optstring(L, 2, "=(load)");
|
||||
luaL_checktype(L, 1, LUA_TFUNCTION);
|
||||
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
|
||||
status = lua_load(L, generic_reader, NULL, chunkname, mode);
|
||||
}
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
|
||||
(void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */
|
||||
return lua_gettop(L) - 1;
|
||||
}
|
||||
|
||||
|
||||
static int luaB_dofile (lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
lua_settop(L, 1);
|
||||
if (luaL_loadfile(L, fname) != LUA_OK)
|
||||
return lua_error(L);
|
||||
lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
|
||||
return dofilecont(L, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_assert (lua_State *L) {
|
||||
if (lua_toboolean(L, 1)) /* condition is true? */
|
||||
return lua_gettop(L); /* return all arguments */
|
||||
else { /* error */
|
||||
luaL_checkany(L, 1); /* there must be a condition */
|
||||
lua_remove(L, 1); /* remove it */
|
||||
lua_pushliteral(L, "assertion failed!"); /* default message */
|
||||
lua_settop(L, 1); /* leave only message (default if no other one) */
|
||||
return luaB_error(L); /* call 'error' */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int luaB_select (lua_State *L) {
|
||||
int n = lua_gettop(L);
|
||||
if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
|
||||
lua_pushinteger(L, n-1);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
lua_Integer i = luaL_checkinteger(L, 1);
|
||||
if (i < 0) i = n + i;
|
||||
else if (i > n) i = n;
|
||||
luaL_argcheck(L, 1 <= i, 1, "index out of range");
|
||||
return n - (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Continuation function for 'pcall' and 'xpcall'. Both functions
|
||||
** already pushed a 'true' before doing the call, so in case of success
|
||||
** 'finishpcall' only has to return everything in the stack minus
|
||||
** 'extra' values (where 'extra' is exactly the number of items to be
|
||||
** ignored).
|
||||
*/
|
||||
static int finishpcall (lua_State *L, int status, lua_KContext extra) {
|
||||
if (status != LUA_OK && status != LUA_YIELD) { /* error? */
|
||||
lua_pushboolean(L, 0); /* first result (false) */
|
||||
lua_pushvalue(L, -2); /* error message */
|
||||
return 2; /* return false, msg */
|
||||
}
|
||||
else
|
||||
return lua_gettop(L) - (int)extra; /* return all results */
|
||||
}
|
||||
|
||||
|
||||
static int luaB_pcall (lua_State *L) {
|
||||
int status;
|
||||
luaL_checkany(L, 1);
|
||||
lua_pushboolean(L, 1); /* first result if no errors */
|
||||
lua_insert(L, 1); /* put it in place */
|
||||
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall);
|
||||
return finishpcall(L, status, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Do a protected call with error handling. After 'lua_rotate', the
|
||||
** stack will have <f, err, true, f, [args...]>; so, the function passes
|
||||
** 2 to 'finishpcall' to skip the 2 first values when returning results.
|
||||
*/
|
||||
static int luaB_xpcall (lua_State *L) {
|
||||
int status;
|
||||
int n = lua_gettop(L);
|
||||
luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */
|
||||
lua_pushboolean(L, 1); /* first result */
|
||||
lua_pushvalue(L, 1); /* function */
|
||||
lua_rotate(L, 3, 2); /* move them below function's arguments */
|
||||
status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall);
|
||||
return finishpcall(L, status, 2);
|
||||
}
|
||||
|
||||
|
||||
static int luaB_tostring (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
luaL_tolstring(L, 1, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(LUA_COMPAT_UNPACK)
|
||||
static int luaB_unpack (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of elements to pack */
|
||||
lua_getglobal(L, "table");
|
||||
lua_getfield(L, -1, "unpack");
|
||||
lua_insert(L, 1);
|
||||
lua_pop(L, 1);
|
||||
lua_call(L, n, LUA_MULTRET);
|
||||
return lua_gettop(L);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** ESP builds use specific linker directives to marshal all the ROTable entries
|
||||
** for the library modules including the base library into an entry vector in
|
||||
** the PSECT ".lua_rotable" including the base library entries; this is bound
|
||||
** into a ROTable in linit.c which then hooked into the __index metaentry for
|
||||
** _G so that base library and ROM tables are directly resolved through _G.
|
||||
**
|
||||
** The host-based luac.cross builds which must use a standard GNU link or
|
||||
** MSVC so this linker-specfic assembly approach can't be used. In this case
|
||||
** luaopen_base returns a base_func ROTable so a two cascade resolution. See
|
||||
** description in init.c for further details.
|
||||
*/
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
LROT_BEGIN(base_func, NULL, 0)
|
||||
#else
|
||||
LROT_ENTRIES_IN_SECTION(base_func, rotable)
|
||||
#endif
|
||||
LROT_FUNCENTRY(assert, luaB_assert)
|
||||
LROT_FUNCENTRY(collectgarbage, luaB_collectgarbage)
|
||||
LROT_FUNCENTRY(dofile, luaB_dofile)
|
||||
LROT_FUNCENTRY(error, luaB_error)
|
||||
LROT_FUNCENTRY(getmetatable, luaB_getmetatable)
|
||||
LROT_FUNCENTRY(ipairs, luaB_ipairs)
|
||||
LROT_FUNCENTRY(loadfile, luaB_loadfile)
|
||||
LROT_FUNCENTRY(load, luaB_load)
|
||||
#if defined(LUA_COMPAT_LOADSTRING)
|
||||
LROT_FUNCENTRY(loadstring, luaB_load)
|
||||
#endif
|
||||
LROT_FUNCENTRY(next, luaB_next)
|
||||
LROT_FUNCENTRY(pairs, luaB_pairs)
|
||||
LROT_FUNCENTRY(pcall, luaB_pcall)
|
||||
LROT_FUNCENTRY(print, luaB_print)
|
||||
LROT_FUNCENTRY(rawequal, luaB_rawequal)
|
||||
LROT_FUNCENTRY(rawlen, luaB_rawlen)
|
||||
LROT_FUNCENTRY(rawget, luaB_rawget)
|
||||
LROT_FUNCENTRY(rawset, luaB_rawset)
|
||||
LROT_FUNCENTRY(select, luaB_select)
|
||||
LROT_FUNCENTRY(setmetatable, luaB_setmetatable)
|
||||
LROT_FUNCENTRY(tonumber, luaB_tonumber)
|
||||
LROT_FUNCENTRY(tostring, luaB_tostring)
|
||||
LROT_FUNCENTRY(type, luaB_type)
|
||||
#if defined(LUA_COMPAT_UNPACK)
|
||||
LROT_FUNCENTRY(unpack, luaB_unpack)
|
||||
#endif
|
||||
LROT_FUNCENTRY(xpcall, luaB_xpcall)
|
||||
#ifdef LUA_CROSS_COMPILER
|
||||
LROT_END(base_func, NULL, 0)
|
||||
#else
|
||||
LROT_BREAK(base_func)
|
||||
#endif
|
||||
|
||||
extern LROT_TABLE(rotables);
|
||||
LUAMOD_API int luaopen_base (lua_State *L) {
|
||||
lua_pushglobaltable(L); /* set global _G */
|
||||
lua_pushliteral(L, LUA_VERSION); /* set global _VERSION */
|
||||
lua_setfield(L, -2, "_VERSION");
|
||||
lua_createtable (L, 0, 1); /* mt for _G */
|
||||
lua_pushrotable(L, LROT_TABLEREF(rotables));
|
||||
lua_setfield(L, -2, "__index"); /* mt.__index=ROM table */
|
||||
lua_setmetatable(L, -2);
|
||||
return 1; /* returns _G */
|
||||
}
|
233
components/lua/lua-5.3/lbitlib.c
Normal file
233
components/lua/lua-5.3/lbitlib.c
Normal file
@ -0,0 +1,233 @@
|
||||
/*
|
||||
** $Id: lbitlib.c,v 1.30.1.1 2017/04/19 17:20:42 roberto Exp $
|
||||
** Standard library for bitwise operations
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#define lbitlib_c
|
||||
#define LUA_LIB
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
|
||||
#if defined(LUA_COMPAT_BITLIB) /* { */
|
||||
|
||||
|
||||
#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n))
|
||||
#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i))
|
||||
|
||||
|
||||
/* number of bits to consider in a number */
|
||||
#if !defined(LUA_NBITS)
|
||||
#define LUA_NBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must
|
||||
** be made in two parts to avoid problems when LUA_NBITS is equal to the
|
||||
** number of bits in a lua_Unsigned.)
|
||||
*/
|
||||
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
|
||||
|
||||
|
||||
/* macro to trim extra bits */
|
||||
#define trim(x) ((x) & ALLONES)
|
||||
|
||||
|
||||
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
|
||||
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
|
||||
|
||||
|
||||
|
||||
static lua_Unsigned andaux (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
lua_Unsigned r = ~(lua_Unsigned)0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r &= checkunsigned(L, i);
|
||||
return trim(r);
|
||||
}
|
||||
|
||||
|
||||
static int b_and (lua_State *L) {
|
||||
lua_Unsigned r = andaux(L);
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_test (lua_State *L) {
|
||||
lua_Unsigned r = andaux(L);
|
||||
lua_pushboolean(L, r != 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_or (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
lua_Unsigned r = 0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r |= checkunsigned(L, i);
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_xor (lua_State *L) {
|
||||
int i, n = lua_gettop(L);
|
||||
lua_Unsigned r = 0;
|
||||
for (i = 1; i <= n; i++)
|
||||
r ^= checkunsigned(L, i);
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_not (lua_State *L) {
|
||||
lua_Unsigned r = ~checkunsigned(L, 1);
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {
|
||||
if (i < 0) { /* shift right? */
|
||||
i = -i;
|
||||
r = trim(r);
|
||||
if (i >= LUA_NBITS) r = 0;
|
||||
else r >>= i;
|
||||
}
|
||||
else { /* shift left */
|
||||
if (i >= LUA_NBITS) r = 0;
|
||||
else r <<= i;
|
||||
r = trim(r);
|
||||
}
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_lshift (lua_State *L) {
|
||||
return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_rshift (lua_State *L) {
|
||||
return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_arshift (lua_State *L) {
|
||||
lua_Unsigned r = checkunsigned(L, 1);
|
||||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
|
||||
return b_shift(L, r, -i);
|
||||
else { /* arithmetic shift for 'negative' number */
|
||||
if (i >= LUA_NBITS) r = ALLONES;
|
||||
else
|
||||
r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int b_rot (lua_State *L, lua_Integer d) {
|
||||
lua_Unsigned r = checkunsigned(L, 1);
|
||||
int i = d & (LUA_NBITS - 1); /* i = d % NBITS */
|
||||
r = trim(r);
|
||||
if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */
|
||||
r = (r << i) | (r >> (LUA_NBITS - i));
|
||||
pushunsigned(L, trim(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_lrot (lua_State *L) {
|
||||
return b_rot(L, luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
static int b_rrot (lua_State *L) {
|
||||
return b_rot(L, -luaL_checkinteger(L, 2));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** get field and width arguments for field-manipulation functions,
|
||||
** checking whether they are valid.
|
||||
** ('luaL_error' called without 'return' to avoid later warnings about
|
||||
** 'width' being used uninitialized.)
|
||||
*/
|
||||
static int fieldargs (lua_State *L, int farg, int *width) {
|
||||
lua_Integer f = luaL_checkinteger(L, farg);
|
||||
lua_Integer w = luaL_optinteger(L, farg + 1, 1);
|
||||
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
|
||||
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
|
||||
if (f + w > LUA_NBITS)
|
||||
luaL_error(L, "trying to access non-existent bits");
|
||||
*width = (int)w;
|
||||
return (int)f;
|
||||
}
|
||||
|
||||
|
||||
static int b_extract (lua_State *L) {
|
||||
int w;
|
||||
lua_Unsigned r = trim(checkunsigned(L, 1));
|
||||
int f = fieldargs(L, 2, &w);
|
||||
r = (r >> f) & mask(w);
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int b_replace (lua_State *L) {
|
||||
int w;
|
||||
lua_Unsigned r = trim(checkunsigned(L, 1));
|
||||
lua_Unsigned v = trim(checkunsigned(L, 2));
|
||||
int f = fieldargs(L, 3, &w);
|
||||
lua_Unsigned m = mask(w);
|
||||
r = (r & ~(m << f)) | ((v & m) << f);
|
||||
pushunsigned(L, r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const luaL_Reg bitlib[] = {
|
||||
{"arshift", b_arshift},
|
||||
{"band", b_and},
|
||||
{"bnot", b_not},
|
||||
{"bor", b_or},
|
||||
{"bxor", b_xor},
|
||||
{"btest", b_test},
|
||||
{"extract", b_extract},
|
||||
{"lrotate", b_lrot},
|
||||
{"lshift", b_lshift},
|
||||
{"replace", b_replace},
|
||||
{"rrotate", b_rrot},
|
||||
{"rshift", b_rshift},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_bit32 (lua_State *L) {
|
||||
luaL_newlib(L, bitlib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#else /* }{ */
|
||||
|
||||
|
||||
LUAMOD_API int luaopen_bit32 (lua_State *L) {
|
||||
return luaL_error(L, "library 'bit32' has been deprecated");
|
||||
}
|
||||
|
||||
#endif /* } */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user