From 7de8a017059b21dda0c0afbd1dd05cece9ce7588 Mon Sep 17 00:00:00 2001 From: galjonsfigur <44552519+galjonsfigur@users.noreply.github.com> Date: Fri, 28 Jun 2019 06:53:19 +0200 Subject: [PATCH] Add luacheck config and configuration for Travis CI (#2790) * Move luacheck conf and fix Travis for all possible filenames * Add lua script to help with luacheck config * Add xargs approach for current luac.cross file checking * Enable luacheck but do not break build --- .travis.yml | 8 +- CONTRIBUTING.md | 7 + tools/luacheck_config.lua | 883 +++++++++++++++++++++++++++++++ tools/luacheck_config_helper.lua | 139 +++++ tools/travis/localua.sh | 113 ++++ tools/travis/run-luacheck.sh | 17 + 6 files changed, 1164 insertions(+), 3 deletions(-) create mode 100644 tools/luacheck_config.lua create mode 100755 tools/luacheck_config_helper.lua create mode 100755 tools/travis/localua.sh create mode 100644 tools/travis/run-luacheck.sh diff --git a/.travis.yml b/.travis.yml index 6a808926..90e27f0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,8 @@ script: - if [ "$OS" = "windows" ]; then bash "$TRAVIS_BUILD_DIR"/tools/travis/ci-build-windows-ms.sh; fi - if [ "$OS" = "linux" -a "$TRAVIS_PULL_REQUEST" != "false" ]; then bash "$TRAVIS_BUILD_DIR"/tools/travis/pr-build.sh; fi - cd "$TRAVIS_BUILD_DIR" -- LUA_FILES=`find lua_modules lua_examples -iname "*.lua"` -- echo checking $LUA_FILES -- $LUACC -p $LUA_FILES +- echo "checking:" +- find lua_modules lua_examples -iname "*.lua" -print0 | xargs -0 echo +- find lua_modules lua_examples -iname "*.lua" -print0 | xargs -0 $LUACC -p +- if [ "$OS" = "linux" ]; then bash "$TRAVIS_BUILD_DIR"/tools/travis/run-luacheck.sh || true ; fi + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index faa05ed6..2dba89b5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,6 +26,13 @@ Use the platform and tools you feel most comfortable with. There are no constrai - [Full-fledged Linux environment](http://www.esp8266.com/wiki/doku.php?id=toolchain#how_to_setup_a_vm_to_host_your_toolchain), either physical or virtual. - [Docker image](https://hub.docker.com/r/marcelstoer/nodemcu-build/) which allows running the build inside the container as if you were running a build script on your local machine. +## Writing Lua Code +A great resource about writing Lua for NodeMCU can be found in [Lua Developer FAQ](https://nodemcu.readthedocs.io/en/latest/lua-developer-faq/) - make sure to read it! When you're writing your Lua code and it's not working as it should you can test it with `luacheck` tool that can help you find various types of bugs. To install it you have to install [luarocks](https://luarocks.org/) and use command `sudo luarocks install luacheck` to install the tool. Now you're ready to go! By using this command (assuming you're in `nodemcu-firmware` directory): + +`luacheck --config tools/luacheck_config.lua ` + +you can look for bugs and problems within the code! + ## Writing Documentation The NodeMCU documentation is maintained within the same repository as the code. The primary reason is to keep the two in sync more easily. It's thus trivial for the NodeMCU team to verify that a PR includes the necessary documentation. Furthermore, the documentation is merged automatically with the code if it moves from branch X to Y. diff --git a/tools/luacheck_config.lua b/tools/luacheck_config.lua new file mode 100644 index 00000000..34a8b6eb --- /dev/null +++ b/tools/luacheck_config.lua @@ -0,0 +1,883 @@ +local empty = { } +local read_write = {read_only = false} + +stds.nodemcu_libs = { + read_globals = { + adc = { + fields = { + INIT_ADC = empty, + INIT_VDD33 = empty, + force_init_mode = empty, + read = empty, + readvdd33 = empty + } + }, + ads1115 = { + fields = { + ADDR_GND = empty, + ADDR_SCL = empty, + ADDR_SDA = empty, + ADDR_VDD = empty, + CMODE_TRAD = empty, + CMODE_WINDOW = empty, + COMP_1CONV = empty, + COMP_2CONV = empty, + COMP_4CONV = empty, + CONTINUOUS = empty, + CONV_RDY_1 = empty, + CONV_RDY_2 = empty, + CONV_RDY_4 = empty, + DIFF_0_1 = empty, + DIFF_0_3 = empty, + DIFF_1_3 = empty, + DIFF_2_3 = empty, + DR_128SPS = empty, + DR_1600SPS = empty, + DR_16SPS = empty, + DR_2400SPS = empty, + DR_250SPS = empty, + DR_32SPS = empty, + DR_3300SPS = empty, + DR_475SPS = empty, + DR_490SPS = empty, + DR_64SPS = empty, + DR_860SPS = empty, + DR_8SPS = empty, + DR_920SPS = empty, + GAIN_0_256V = empty, + GAIN_0_512V = empty, + GAIN_1_024V = empty, + GAIN_2_048V = empty, + GAIN_4_096V = empty, + GAIN_6_144V = empty, + SINGLE_0 = empty, + SINGLE_1 = empty, + SINGLE_2 = empty, + SINGLE_3 = empty, + SINGLE_SHOT = empty, + ads1015 = empty, + ads1115 = empty, + read = empty, + reset = empty, + } + }, + adxl345 = { + fields = { + read = empty, + setup = empty + } + }, + am2320 = { + fields = { + read = empty, + setup = empty + } + }, + apa102 = { + fields = { + write = empty + } + }, + bit = { + fields = { + arshift = empty, + band = empty, + bit = empty, + bnot = empty, + bor = empty, + bxor = empty, + clear = empty, + isclear = empty, + isset = empty, + lshift = empty, + rshift = empty, + set = empty + } + }, + bloom = { + fields = { + create = empty + } + }, + bme280 = { + fields = { + altitude = empty, + baro = empty, + dewpoint = empty, + humi = empty, + qfe2qnh = empty, + read = empty, + setup = empty, + startreadout = empty, + temp = empty + } + }, + bme680 = { + fields = { + altitude = empty, + dewpoint = empty, + qfe2qnh = empty, + read = empty, + setup = empty, + startreadout = empty + } + }, + bmp085 = { + fields = { + pressure = empty, + pressure_raw = empty, + setup = empty, + temperature = empty + } + }, + coap = { + fields = { + CON = empty, + Client = empty, + EXI = empty, + JSON = empty, + LINKFORMAT = empty, + NON = empty, + OCTET_STREAM = empty, + Server = empty, + TEXT_PLAIN = empty, + XML = empty + } + }, + color_utils = { + fields = { + colorWheel = empty, + grb2hsv = empty, + hsv2grb = empty, + hsv2grbw = empty + } + }, + cron = { + fields = { + reset = empty, + schedule = empty + } + }, + crypto = { + fields = { + decrypt = empty, + encrypt = empty, + fhash = empty, + hash = empty, + hmac = empty, + mask = empty, + new_hash = empty, + new_hmac = empty, + sha1 = empty, + toBase64 = empty, + toHex = empty + } + }, + dht = { + fields = { + ERROR_CHECKSUM = empty, + ERROR_TIMEOUT = empty, + OK = empty, + read = empty, + read11 = empty, + readxx = empty + } + }, + encoder = { + fields = { + fromBase64 = empty, + fromHex = empty, + toBase64 = empty, + toHex = empty + } + }, + enduser_setup = { + fields = { + manual = empty, + start = empty, + stop = empty + } + }, + file = { + fields = { + close = empty, + exists = empty, + flush = empty, + fsinfo = empty, + getcontents = empty, + list = empty, + on = empty, + open = empty, + putcontents = empty, + read = empty, + readline = empty, + remove = empty, + rename = empty, + seek = empty, + stat = empty, + write = empty, + writeline = empty + } + }, + gdbstub = { + fields = { + brk = empty, + gdboutput = empty, + open = empty + } + }, + gpio = { + fields = { + FLOAT = empty, + HIGH = empty, + INPUT = empty, + INT = empty, + LOW = empty, + OPENDRAIN = empty, + OUTPUT = empty, + PULLUP = empty, + mode = empty, + read = empty, + serout = empty, + trig = empty, + write = empty, + pulse = { + fields = { + adjust = empty, + cancel = empty, + getstate = empty, + start = empty, + stop = empty, + update = empty + } + } + } + }, + hdc1080 = { + fields = { + read = empty, + setup = empty + } + }, + hmc5883 = { + fields = { + read = empty, + setup = empty + } + }, + http = { + fields = { + ERROR = empty, + OK = empty, + delete = empty, + get = empty, + post = empty, + put = empty, + request = empty + } + }, + hx711 = { + fields = { + init = empty, + read = empty + } + }, + i2c = { + fields = { + FAST = empty, + FASTPLUS = empty, + RECEIVER = empty, + SLOW = empty, + TRANSMITTER = empty, + address = empty, + read = empty, + setup = empty, + start = empty, + stop = empty, + write = empty + } + }, + l3g4200d = { + fields = { + read = empty, + setup = empty + } + }, + mcp4725 = { + fields = { + PWRDN_100K = empty, + PWRDN_1K = empty, + PWRDN_500K = empty, + PWRDN_NONE = empty, + read = empty, + write = empty + } + }, + mdns = { + fields = { + close = empty, + register = empty + } + }, + mqtt = { + fields = { + CONNACK_ACCEPTED = empty, + CONNACK_REFUSED_BAD_USER_OR_PASS = empty, + CONNACK_REFUSED_ID_REJECTED = empty, + CONNACK_REFUSED_NOT_AUTHORIZED = empty, + CONNACK_REFUSED_PROTOCOL_VER = empty, + CONNACK_REFUSED_SERVER_UNAVAILABLE = empty, + CONN_FAIL_DNS = empty, + CONN_FAIL_NOT_A_CONNACK_MSG = empty, + CONN_FAIL_SERVER_NOT_FOUND = empty, + CONN_FAIL_TIMEOUT_RECEIVING = empty, + CONN_FAIL_TIMEOUT_SENDING = empty, + Client = empty + } + }, + net = { + fields = { + TCP = empty, + UDP = empty, + cert = empty, + createConnection = empty, + createServer = empty, + createUDPSocket = empty, + dns = { + fields = { + getdnsserver = empty, + resolve = empty, + setdnsserver = empty + } + }, + multicastJoin = empty, + multicastLeave = empty + } + }, + node = { + fields = { + CPU160MHZ = empty, + CPU80MHZ = empty, + bootreason = empty, + chipid = empty, + compile = empty, + dsleep = empty, + dsleepMax = empty, + dsleepsetoption = empty, + flashid = empty, + flashindex = empty, + flashreload = empty, + flashsize = empty, + getcpufreq = empty, + getpartitiontable = empty, + heap = empty, + info = empty, + input = empty, + osprint = empty, + output = empty, + random = empty, + readrcr = empty, + readvdd33 = empty, + restart = empty, + restore = empty, + setcpufreq = empty, + setpartitiontable = empty, + sleep = empty, + stripdebug = empty, + writercr = empty, + egc = { + fields = { + setmode = empty, + meminfo = empty + } + }, + task = { + fields = { + post = empty + } + } + } + }, + ow = { + fields = { + check_crc16 = empty, + crc16 = empty, + crc8 = empty, + depower = empty, + read = empty, + read_bytes = empty, + reset = empty, + reset_search = empty, + search = empty, + select = empty, + setup = empty, + skip = empty, + target_search = empty, + write = empty, + write_bytes = empty + } + }, + pcm = { + fields = { + RATE_10K = empty, + RATE_12K = empty, + RATE_16K = empty, + RATE_1K = empty, + RATE_2K = empty, + RATE_4K = empty, + RATE_5K = empty, + RATE_8K = empty, + SD = empty, + new = empty + } + }, + pwm = { + fields = { + close = empty, + getclock = empty, + getduty = empty, + setclock = empty, + setduty = empty, + setup = empty, + start = empty, + stop = empty + } + }, + pwm2 = { + fields = { + get_pin_data = empty, + get_timer_data = empty, + release_pin = empty, + set_duty = empty, + setup_pin_hz = empty, + setup_pin_sec = empty, + start = empty, + stop = empty, + } + }, + rc = { + fields = { + send = empty + } + }, + rfswitch = { + fields = { + send = empty + } + }, + rotary = { + fields = { + ALL = empty, + CLICK = empty, + DBLCLICK = empty, + LONGPRESS = empty, + PRESS = empty, + RELEASE = empty, + TURN = empty, + close = empty, + getpos = empty, + on = empty, + setup = empty + } + }, + rtcfifo = { + fields = { + count = empty, + drop = empty, + dsleep_until_sample = empty, + peek = empty, + pop = empty, + prepare = empty, + put = empty, + ready = empty + } + }, + rtcmem = { + fields = { + read32 = empty, + write32 = empty + } + }, + rtctime = { + fields = { + adjust_delta = empty, + dsleep = empty, + dsleep_aligned = empty, + epoch2cal = empty, + get = empty, + set = empty + } + }, + si7021 = { + fields = { + HEATER_DISABLE = empty, + HEATER_ENABLE = empty, + RH08_TEMP12 = empty, + RH10_TEMP13 = empty, + RH11_TEMP11 = empty, + RH12_TEMP14 = empty, + firmware = empty, + read = empty, + serial = empty, + setting = empty, + setup = empty + } + }, + sigma_delta = { + fields = { + close = empty, + setprescale = empty, + setpwmduty = empty, + settarget = empty, + setup = empty + } + }, + sjson = { + fields = { + decode = empty, + decoder = empty, + encode = empty, + encoder = empty + } + }, + sntp = { + fields = { + getoffset = empty, + setoffset = empty, + sync = empty + } + }, + somfy = { + fields = { + DOWN = empty, + PROG = empty, + STOP = empty, + UP = empty, + sendcommand = empty + } + }, + spi = { + fields = { + CPHA_HIGH = empty, + CPHA_LOW = empty, + CPOL_HIGH = empty, + CPOL_LOW = empty, + DATABITS_8 = empty, + FULLDUPLEX = empty, + HALFDUPLEX = empty, + MASTER = empty, + SLAVE = empty, + get_miso = empty, + recv = empty, + send = empty, + set_clock_div = empty, + set_mosi = empty, + setup = empty, + transaction = empty + } + }, + switec = { + fields = { + close = empty, + dequeue = empty, + getpos = empty, + moveto = empty, + reset = empty, + setup = empty + } + }, + tcs34725 = { + fields = { + disable = empty, + enable = empty, + raw = empty, + setGain = empty, + setIntegrationTime = empty, + setup = empty + } + }, + tls = { + fields = { + createConnection = empty, + setDebug = empty, + cert = { + fields = { + auth = empty, + verify = empty + } + } + } + }, + tm1829 = { + fields = { + write = empty + } + }, + tmr = { + fields = { + ALARM_AUTO = empty, + ALARM_SEMI = empty, + ALARM_SINGLE = empty, + create = empty, + delay = empty, + now = empty, + resume_all = empty, + softwd = empty, + suspend_all = empty, + time = empty, + wdclr = empty + } + }, + tsl2561 = { + fields = { + ADDRESS_FLOAT = empty, + ADDRESS_GND = empty, + ADDRESS_VDD = empty, + GAIN_16X = empty, + GAIN_1X = empty, + INTEGRATIONTIME_101MS = empty, + INTEGRATIONTIME_13MS = empty, + INTEGRATIONTIME_402MS = empty, + PACKAGE_CS = empty, + PACKAGE_T_FN_CL = empty, + TSL2561_ERROR_I2CBUSY = empty, + TSL2561_ERROR_I2CINIT = empty, + TSL2561_ERROR_LAST = empty, + TSL2561_ERROR_NOINIT = empty, + TSL2561_OK = empty, + getlux = empty, + getrawchannels = empty, + init = empty, + settiming = empty + } + }, + -- There would be too many fields for all the fonts and displays + u8g2 = {other_fields = true}, + uart = { + fields = { + PARITY_EVEN = empty, + PARITY_NONE = empty, + PARITY_ODD = empty, + STOPBITS_1 = empty, + STOPBITS_1_5 = empty, + STOPBITS_2 = empty, + alt = empty, + getconfig = empty, + on = empty, + setup = empty, + write = empty + } + }, + -- There would be too many fields for all the fonts and displays + ucg = {other_fields = true}, + websocket = { + fields = { + createClient = empty + } + }, + wifi = { + fields = { + COUNTRY_AUTO = empty, + COUNTRY_MANUAL = empty, + LIGHT_SLEEP = empty, + MODEM_SLEEP = empty, + NONE_SLEEP = empty, + NULLMODE = empty, + OPEN = empty, + PHYMODE_B = empty, + PHYMODE_G = empty, + PHYMODE_N = empty, + SOFTAP = empty, + STATION = empty, + STATIONAP = empty, + STA_APNOTFOUND = empty, + STA_CONNECTING = empty, + STA_FAIL = empty, + STA_GOTIP = empty, + STA_IDLE = empty, + STA_WRONGPWD = empty, + WEP = empty, + WPA2_PSK = empty, + WPA_PSK = empty, + WPA_WPA2_PSK = empty, + getchannel = empty, + getcountry = empty, + getdefaultmode = empty, + getmode = empty, + getphymode = empty, + nullmodesleep = empty, + resume = empty, + setcountry = empty, + setmaxtxpower = empty, + setmode = empty, + setphymode = empty, + sleeptype = empty, + startsmart = empty, + stopsmart = empty, + suspend = empty, + sta = { + fields = { + autoconnect = empty, + changeap = empty, + clearconfig = empty, + config = empty, + connect = empty, + disconnect = empty, + getap = empty, + getapindex = empty, + getapinfo = empty, + getbroadcast = empty, + getconfig = empty, + getdefaultconfig = empty, + gethostname = empty, + getip = empty, + getmac = empty, + getrssi = empty, + setaplimit = empty, + sethostname = empty, + setip = empty, + setmac = empty, + sleeptype = empty, + status = empty + } + }, + ap = { + fields = { + config = empty, + deauth = empty, + getbroadcast = empty, + getclient = empty, + getconfig = empty, + getdefaultconfig = empty, + getip = empty, + getmac = empty, + setip = empty, + setmac = empty, + dhcp = { + fields = { + config = empty, + start = empty, + stop = empty + } + }, + } + }, + eventmon = { + fields = { + AP_PROBEREQRECVED = empty, + AP_STACONNECTED = empty, + AP_STADISCONNECTED = empty, + EVENT_MAX = empty, + STA_AUTHMODE_CHANGE = empty, + STA_CONNECTED = empty, + STA_DHCP_TIMEOUT = empty, + STA_DISCONNECTED = empty, + STA_GOT_IP = empty, + WIFI_MODE_CHANGED = empty, + register = empty, + unregister = empty, + reason = { + fields = { + ["4WAY_HANDSHAKE_TIMEOUT"] = empty, + ["802_1X_AUTH_FAILED"] = empty, + AKMP_INVALID = empty, + ASSOC_EXPIRE = empty, + ASSOC_FAIL = empty, + ASSOC_LEAVE = empty, + ASSOC_NOT_AUTHED = empty, + ASSOC_TOOMANY = empty, + AUTH_EXPIRE = empty, + AUTH_FAIL = empty, + AUTH_LEAVE = empty, + BEACON_TIMEOUT = empty, + CIPHER_SUITE_REJECTED = empty, + DISASSOC_PWRCAP_BAD = empty, + DISASSOC_SUPCHAN_BAD = empty, + GROUP_CIPHER_INVALID = empty, + GROUP_KEY_UPDATE_TIMEOUT = empty, + HANDSHAKE_TIMEOUT = empty, + IE_INVALID = empty, + IE_IN_4WAY_DIFFERS = empty, + INVALID_RSN_IE_CAP = empty, + MIC_FAILURE = empty, + NOT_ASSOCED = empty, + NOT_AUTHED = empty, + NO_AP_FOUND = empty, + PAIRWISE_CIPHER_INVALID = empty, + UNSPECIFIED = empty, + UNSUPP_RSN_IE_VERSION = empty + } + } + } + }, + monitor = { + fields = { + channel = empty, + start = empty, + stop = empty + } + } + } + }, + wps = { + fields = { + FAILED = empty, + SCAN_ERR = empty, + SUCCESS = empty, + TIMEOUT = empty, + WEP = empty, + disable = empty, + enable = empty, + start = empty + } + }, + ws2801 = { + fields = { + init = empty, + write = empty + } + }, + ws2812 = { + fields = { + FADE_IN = empty, + FADE_OUT = empty, + MODE_DUAL = empty, + MODE_SINGLE = empty, + SHIFT_CIRCULAR = empty, + SHIFT_LOGICAL = empty, + init = empty, + newBuffer = empty, + write = empty + } + }, + ws2812_effects = { + fields = { + get_delay = empty, + get_speed = empty, + init = empty, + set_brightness = empty, + set_color = empty, + set_delay = empty, + set_mode = empty, + set_speed = empty, + start = empty, + stop = empty + } + }, + xpt2046 = { + fields = { + getPosition = empty, + getPositionAvg = empty, + getRaw = empty, + init = empty, + isTouched = empty, + setCalibration = empty + } + }, + pack = empty, + unpack = empty, + size = empty + } +} + +std = "lua51+nodemcu_libs" \ No newline at end of file diff --git a/tools/luacheck_config_helper.lua b/tools/luacheck_config_helper.lua new file mode 100755 index 00000000..f7b5bb2e --- /dev/null +++ b/tools/luacheck_config_helper.lua @@ -0,0 +1,139 @@ +#!/usr/bin/lua + +--- +-- Script to extract names and the functions themselves from NodeMCU modules and +-- to help creating luacheck configuration. +-- Usage: ../../tools/luacheck_config_helper.lua *.c (or filename for single module) + +local M = {} + +-- Recursive object dumper, for debugging. +-- (c) 2010 David Manura, MIT License. +-- From: https://github.com/davidm/lua-inspect/blob/master/lib/luainspect/dump.lua +local ignore_keys_ = {lineinfo = true} +local norecurse_keys_ = {parent = true, ast = true} +local function dumpstring_key_(k, isseen, newindent) + local ks = type(k) == 'string' and k:match'^[%a_][%w_]*$' and k or + '[' .. M.dumpstring(k, isseen, newindent) .. ']' + return ks +end + +local function sort_keys_(a, b) + if type(a) == 'number' and type(b) == 'number' then + return a < b + elseif type(a) == 'number' then + return false + elseif type(b) == 'number' then + return true + elseif type(a) == 'string' and type(b) == 'string' then + return a < b + else + return tostring(a) < tostring(b) -- arbitrary + end +end + +function M.dumpstring(o, isseen, indent, key) + isseen = isseen or {} + indent = indent or '' + + if type(o) == 'table' then + if isseen[o] or norecurse_keys_[key] then + return (type(o.tag) == 'string' and '`' .. o.tag .. ':' or '') .. tostring(o) + else isseen[o] = true end -- avoid recursion + + local used = {} + + local tag = o.tag + local s = '{' + if type(o.tag) == 'string' then + s = '`' .. tag .. s; used['tag'] = true + end + local newindent = indent .. ' ' + + local ks = {}; for k in pairs(o) do ks[#ks+1] = k end + table.sort(ks, sort_keys_) + + local forcenummultiline + for k in pairs(o) do + if type(k) == 'number' and type(o[k]) == 'table' then forcenummultiline = true end + end + + -- inline elements + for _,k in ipairs(ks) do + if ignore_keys_[k] then used[k] = true + elseif (type(k) ~= 'number' or not forcenummultiline) and + type(k) ~= 'table' and (type(o[k]) ~= 'table' or norecurse_keys_[k]) + then + s = s .. dumpstring_key_(k, isseen, newindent) .. ' = ' .. M.dumpstring(o[k], isseen, newindent, k) .. ', ' + used[k] = true + end + end + + -- elements on separate lines + local done + for _,k in ipairs(ks) do + if not used[k] then + if not done then s = s .. '\n'; done = true end + s = s .. newindent .. dumpstring_key_(k, isseen) .. ' = ' .. M.dumpstring(o[k], isseen, newindent, k) .. ',\n' + end + end + s = s:gsub(',(%s*)$', '%1') + s = s .. (done and indent or '') .. '}' + return s + elseif type(o) == 'string' then + return string.format('%q', o) + else + return tostring(o) + end +end +-- End of dump.lua code + +local function printTables(fileName) + + local findBegin, field + if type(fileName) ~= "string" then error("Wrong argument") end + local file = io.open(fileName, "r") + if not file then error("Can't open file") end + local result = {} + result.fields = {} + + for line in file:lines() do + findBegin, _, field = string.find(line, "LROT_BEGIN%((%g+)%)") + if findBegin then + io.write(field.." = ") + end + findBegin, _, field = string.find(line, "LROT_PUBLIC_BEGIN%((%g+)%)") + if findBegin then + print(field.." = ") + end + + findBegin, _, field = string.find(line, "LROT_FUNCENTRY%(%s?(%g+),") + if not findBegin then + findBegin, _, field = string.find(line, "LROT_NUMENTRY%(%s?(%g+),") + end + if not findBegin then + findBegin, _, field = string.find(line, "LROT_TABENTRY%(%s?(%g+),") + end + + if findBegin then + if not string.find(field, "__") then + result.fields[field] = {} + end + end + + findBegin = string.find(line, "LROT_END") + if findBegin then + print(string.gsub(M.dumpstring(result), "{}", "empty")..',') + result = {} + result.fields = {} + end + end +end + +local function main() + for i = 1, #arg do + printTables(arg[i]) + end +end + +main() \ No newline at end of file diff --git a/tools/travis/localua.sh b/tools/travis/localua.sh new file mode 100755 index 00000000..124a2fe5 --- /dev/null +++ b/tools/travis/localua.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +# Downloads and installs a self-contained Lua and LuaRocks. +# Supports Linux, macOS and MSYS2. +# Copyright (c) 2015-2019 Pierre Chapuis, MIT Licensed. +# Latest stable version available at: https://loadk.com/localua.sh +# Maintained at: https://github.com/oploadk/localua + +DEFAULT_LUA_V="5.3.5" +DEFAULT_LR_V="3.0.4" + +usage () { + >&2 echo -e "USAGE: $0 output-dir [lua-version] [luarocks-version]\n" + >&2 echo -n "The first optional argument is the Lua version, " + >&2 echo -n "the second one is the LuaRocks version. " + >&2 echo -e "Defaults are Lua $DEFAULT_LUA_V and LuaRocks $DEFAULT_LR_V.\n" + >&2 echo -n "You can set a custom build directory with environment " + >&2 echo -e "variable LOCALUA_BUILD_DIRECTORY (not useful in general).\n" + >&2 echo -e "You can set a custom makefile target with LOCALUA_TARGET.\n" + >&2 echo -e "You can disable LUA_COMPAT by setting LOCALUA_NO_COMPAT.\n" + >&2 echo -e "You can skip luarocks by setting LOCALUA_NO_LUAROCKS." + exit 1 +} + +# Set output directory, Lua version and LuaRocks version + +ODIR="$1" +[ -z "$ODIR" ] && usage + +LUA_V="$2" +[ -z "$LUA_V" ] && LUA_V="$DEFAULT_LUA_V" + +LUA_SHORTV="$(echo $LUA_V | cut -c 1-3)" + +LR_V="$3" +[ -z "$LR_V" ] && LR_V="$DEFAULT_LR_V" + +# Set build directory + +BDIR="$LOCALUA_BUILD_DIRECTORY" +[ -z "$BDIR" ] && BDIR="$(mktemp -d /tmp/localua-XXXXXX)" + +# Create output directory and get absolute path + +mkdir -p "$ODIR" +>/dev/null pushd "$ODIR" + ODIR="$(pwd)" +>/dev/null popd + +# Download, unpack and build Lua and LuaRocks + +if [ -z "$LOCALUA_TARGET" ]; then + case "$(uname)" in + Linux) + LOCALUA_TARGET="linux";; + Darwin) + LOCALUA_TARGET="macosx";; + MSYS*) + LOCALUA_TARGET="msys";; + *) + LOCALUA_TARGET="posix";; + esac +fi + +pushd "$BDIR" + wget "http://www.lua.org/ftp/lua-${LUA_V}.tar.gz" + tar xf "lua-${LUA_V}.tar.gz" + pushd "lua-${LUA_V}" + sed 's#"/usr/local/"#"'"$ODIR"'/"#' "src/luaconf.h" > "$BDIR/t" + mv "$BDIR/t" "src/luaconf.h" + if [ ! -z "$LOCALUA_NO_COMPAT" ]; then + sed 's#-DLUA_COMPAT_5_2##' "src/Makefile" > "$BDIR/t" + sed 's#-DLUA_COMPAT_ALL##' "$BDIR/t" > "src/Makefile" + fi + + if [ "$LOCALUA_TARGET" = "msys" ]; then + >> "src/Makefile" echo + >> "src/Makefile" echo 'msys:' >> "src/Makefile" + >> "src/Makefile" echo -ne "\t" + >> "src/Makefile" echo '$(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \' + >> "src/Makefile" echo -ne "\t" + >> "src/Makefile" echo '"AR=$(CC) -shared -Wl,--out-implib,liblua.dll.a -o" "RANLIB=strip --strip-unneeded" \' + >> "src/Makefile" echo -ne "\t" + >> "src/Makefile" echo '"SYSCFLAGS=-DLUA_BUILD_AS_DLL -DLUA_USE_POSIX -DLUA_USE_DLOPEN" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe' + >> "src/Makefile" echo -ne "\t" + >> "src/Makefile" echo '$(MAKE) "LUAC_T=luac.exe" luac.exe' + + make -C src "$LOCALUA_TARGET" || exit 1 + make \ + TO_BIN="lua.exe luac.exe lua53.dll" \ + TO_LIB="liblua.a liblua.dll.a" \ + INSTALL_TOP="$ODIR" install || exit 1 + else + make "$LOCALUA_TARGET" || exit 1 + make INSTALL_TOP="$ODIR" install || exit 1 + fi + + popd + if [ -z "$LOCALUA_NO_LUAROCKS" ]; then + wget "http://luarocks.org/releases/luarocks-${LR_V}.tar.gz" + tar xf "luarocks-${LR_V}.tar.gz" + pushd "luarocks-${LR_V}" + ./configure --with-lua="$ODIR" --prefix="$ODIR" \ + --lua-version="$LUA_SHORTV" \ + --sysconfdir="$ODIR/luarocks" --force-config + make bootstrap + popd + fi +popd + +# Cleanup + +rm -rf "$BDIR" diff --git a/tools/travis/run-luacheck.sh b/tools/travis/run-luacheck.sh new file mode 100644 index 00000000..d97241f7 --- /dev/null +++ b/tools/travis/run-luacheck.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +echo "Installing Lua 5.3, LuaRocks and Luacheck" +( + cd "$TRAVIS_BUILD_DIR" || exit + bash tools/travis/localua.sh cache/localua || exit + cache/localua/bin/luarocks install luacheck || exit +) + +( + echo "Static analysys of:" + find lua_modules lua_examples -iname "*.lua" -print0 | xargs -0 echo +) + +(find lua_modules lua_examples -iname "*.lua" -print0 | xargs -0 cache/localua/bin/luacheck --config tools/luacheck_config.lua) || exit