Skip to content

Commit 6e96dce

Browse files
committed
Added support for Lua 5.2 and 5.3. Fixed some error handling stuff.
1 parent af7bcb0 commit 6e96dce

File tree

2 files changed

+84
-24
lines changed

2 files changed

+84
-24
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
A small and straightforward Lua preprocessor featuring a simple syntax.
66
Write embedded metaprograms to generate code using normal Lua inside your Lua files.
77

8-
*LuaPreprocess* is written in pure Lua 5.1.
8+
*LuaPreprocess* is written in pure Lua.
99
[The library](preprocess.lua) is a single file with no external dependencies.
1010
[MIT license](LICENSE.txt).
1111
A separate [command line program](main.lua) is available too.
@@ -66,7 +66,7 @@ See the [examples folder](examples) for more.
6666

6767

6868
## Usage
69-
First you of course need [Lua 5.1](https://www.lua.org/versions.html#5.1) installed on your system. (Binaries can be
69+
First you of course need [Lua](https://www.lua.org/versions.html) installed on your system. (Binaries can be
7070
downloaded from [LuaBinaries via SourceForge](https://sourceforge.net/projects/luabinaries/files/5.1.5/Tools%20Executables/)
7171
if you don't want to, or can't, compile Lua from source. For Windows I can recommend installing
7272
[LuaForWindows](https://github.com/rjpcomputing/luaforwindows) which is a "batteries included" Lua package.)

preprocess.lua

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
--= License: MIT (see the bottom of this file)
77
--= Website: https://github.com/ReFreezed/LuaPreprocess
88
--=
9-
--= Tested for Lua 5.1.
9+
--= Tested with Lua 5.1, 5.2 and 5.3.
1010
--=
1111
--==============================================================
1212
@@ -88,18 +88,22 @@
8888
8989
--============================================================]]
9090

91-
local VERSION = "1.3.0"
91+
local VERSION = "1.3.1"
9292

9393
local KEYWORDS = {
9494
"and","break","do","else","elseif","end","false","for","function","if","in",
9595
"local","nil","not","or","repeat","return","then","true","until","while",
96+
-- Lua 5.2
97+
"goto",
9698
} for i, v in ipairs(KEYWORDS) do KEYWORDS[v], KEYWORDS[i] = true, nil end
9799

98100
local PUNCTUATION = {
99101
"+", "-", "*", "/", "%", "^", "#",
100102
"==", "~=", "<=", ">=", "<", ">", "=",
101103
"(", ")", "{", "}", "[", "]",
102104
";", ":", ",", ".", "..", "...",
105+
-- Lua 5.3
106+
"//", "&", "|", "~", ">>", "<<",
103107
} for i, v in ipairs(PUNCTUATION) do PUNCTUATION[v], PUNCTUATION[i] = true, nil end
104108

105109
local ESCAPE_SEQUENCES = {
@@ -117,6 +121,20 @@ local ESCAPE_SEQUENCES = {
117121

118122
local ERROR_UNFINISHED_VALUE = 1
119123

124+
local major, minor = _VERSION:match"Lua (%d+)%.(%d+)"
125+
if not major then
126+
print("[LuaPreprocess] Warning: Could not detect Lua version.")
127+
else
128+
major = tonumber(major)
129+
minor = tonumber(minor)
130+
end
131+
local IS_LUA_51 = (major == 5 and minor == 1)
132+
local IS_LUA_52 = (major == 5 and minor == 2)
133+
local IS_LUA_53 = (major == 5 and minor == 3)
134+
local IS_LUA_51_OR_LATER = (major == 5 and minor >= 1) or (major ~= nil and major > 5)
135+
local IS_LUA_52_OR_LATER = (major == 5 and minor >= 2) or (major ~= nil and major > 5)
136+
local IS_LUA_53_OR_LATER = (major == 5 and minor >= 3) or (major ~= nil and major > 5)
137+
120138
local _error = error
121139

122140
local metaEnv = nil
@@ -141,8 +159,9 @@ local escapePattern
141159
local F
142160
local getFileContents, fileExists
143161
local isAny
162+
local loadLuaString, loadLuaFile
144163
local maybeOutputLineNumber
145-
local pack
164+
local pack, unpack
146165
local parseStringlike
147166
local printf, printTokens
148167
local serialize, toLua
@@ -358,7 +377,7 @@ function tokenize(s, path, allowMetaTokens)
358377

359378
local repr = s:sub(reprStart, reprEnd)
360379

361-
local valueChunk = loadstring("return"..repr)
380+
local valueChunk = loadLuaString("return"..repr)
362381
if not valueChunk then
363382
return nil, errorInFile(s, path, reprStart, "Tokenizer", "Malformed string.")
364383
end
@@ -382,7 +401,7 @@ function tokenize(s, path, allowMetaTokens)
382401
end
383402
end
384403

385-
local valueChunk = loadstring("return"..tok.representation)
404+
local valueChunk = loadLuaString("return"..tok.representation)
386405
if not valueChunk then
387406
return nil, errorInFile(s, path, reprStart, "Tokenizer", "Malformed long string.")
388407
end
@@ -401,11 +420,12 @@ function tokenize(s, path, allowMetaTokens)
401420
tok = {type="whitespace", representation=whitespace, value=whitespace}
402421

403422
-- Punctuation etc.
423+
-- "//", ">>", "<<",
404424
elseif s:find("^%.%.%.", ptr) then
405425
local repr = s:sub(ptr, ptr+2)
406426
tok = {type="punctuation", representation=repr, value=repr}
407427
ptr = ptr+#repr
408-
elseif s:find("^%.%.", ptr) or s:find("^[=~<>]=", ptr) then
428+
elseif s:find("^%.%.", ptr) or s:find("^[=~<>]=", ptr) or s:find("^//", ptr) or s:find("^<<", ptr) or s:find("^>>", ptr) then
409429
local repr = s:sub(ptr, ptr+1)
410430
tok = {type="punctuation", representation=repr, value=repr}
411431
ptr = ptr+#repr
@@ -668,12 +688,48 @@ end
668688

669689
-- values = pack( value1, ... )
670690
-- values.n is the amount of values. Values can be nil.
671-
function pack(...)
672-
return {n=select("#", ...), ...}
691+
if IS_LUA_52_OR_LATER then
692+
pack = table.pack
693+
else
694+
function pack(...)
695+
return {n=select("#", ...), ...}
696+
end
697+
end
698+
699+
unpack = IS_LUA_52_OR_LATER and table.unpack or _G.unpack
700+
701+
if IS_LUA_52_OR_LATER then
702+
function loadLuaString(lua, chunkName, env)
703+
return load(lua, chunkName, "bt", env)
704+
end
705+
else
706+
function loadLuaString(lua, chunkName, env)
707+
local chunk, err = loadstring(lua, chunkName)
708+
if not chunk then return chunk, err end
709+
710+
if env then setfenv(chunk, env) end
711+
712+
return chunk
713+
end
714+
end
715+
716+
if IS_LUA_52_OR_LATER then
717+
function loadLuaFile(path, env)
718+
return loadfile(path, "bt", env)
719+
end
720+
else
721+
function loadLuaFile(path, env)
722+
local chunk, err = loadfile(path)
723+
if not chunk then return chunk, err end
724+
725+
if env then setfenv(chunk, env) end
726+
727+
return chunk
728+
end
673729
end
674730

675731
--==============================================================
676-
--= Preprocessor Function ======================================
732+
--= Preprocessor Functions =====================================
677733
--==============================================================
678734

679735

@@ -721,11 +777,8 @@ metaFuncs.escapePattern = escapePattern
721777
function metaFuncs.run(path)
722778
assertarg(1, path, "string")
723779

724-
local chunk, err = loadfile(path)
725-
if not chunk then
726-
errorline(err)
727-
end
728-
setfenv(chunk, metaEnv)
780+
local chunk, err = loadLuaFile(path, metaEnv)
781+
if not chunk then errorline(err) end
729782

730783
-- We want multiple return values while avoiding a tail call to preserve stack info.
731784
local returnValues = pack(chunk())
@@ -1158,7 +1211,7 @@ local function _processFileOrString(params, isFile)
11581211

11591212
local metaBlock = concatTokens(tokensInBlock, nil, params.addLineNumbers)
11601213

1161-
if loadstring("return("..metaBlock..")") then
1214+
if loadLuaString("return("..metaBlock..")") then
11621215
table.insert(metaParts, (doOutputLua and "__LUA((" or "__VAL(("))
11631216
table.insert(metaParts, metaBlock)
11641217
table.insert(metaParts, "))\n")
@@ -1245,25 +1298,25 @@ local function _processFileOrString(params, isFile)
12451298
--]]
12461299

12471300
metaPathForErrorMessages = params.pathMeta or "<meta>"
1248-
outputFromMeta = {}
1301+
outputFromMeta = {}
12491302

12501303
if params.pathMeta then
12511304
local file = assert(io.open(params.pathMeta, "wb"))
12521305
file:write(luaMeta)
12531306
file:close()
12541307
end
12551308

1256-
local chunk, err = loadstring(luaMeta, metaPathForErrorMessages)
1309+
local chunk, err = loadLuaString(luaMeta, metaPathForErrorMessages, metaEnv)
12571310
if not chunk then
12581311
local ln, err = err:match'^%[string ".-"%]:(%d+): (.*)'
12591312
errorOnLine(metaPathForErrorMessages, tonumber(ln), nil, "%s", err)
1313+
return nil, err
12601314
end
1261-
setfenv(chunk, metaEnv)
12621315

12631316
if params.onBeforeMeta then params.onBeforeMeta() end
12641317

12651318
isRunningMeta = true
1266-
xpcall(chunk, function(err0)
1319+
local ok, err = xpcall(chunk, function(err0)
12671320
local path, ln, err = tostring(err0):match'^%[string "(.-)"%]:(%d+): (.*)'
12681321
if err then
12691322
errorOnLine(path, tonumber(ln), nil, "%s", err)
@@ -1273,6 +1326,11 @@ local function _processFileOrString(params, isFile)
12731326
end)
12741327
isRunningMeta = false
12751328

1329+
if not ok then
1330+
-- Note: The caller should clean up metaPathForErrorMessages etc. on error.
1331+
return nil, err
1332+
end
1333+
12761334
if not isDebug and params.pathMeta then
12771335
os.remove(params.pathMeta)
12781336
end
@@ -1300,7 +1358,7 @@ local function _processFileOrString(params, isFile)
13001358
-- Write output file.
13011359
----------------------------------------------------------------
13021360

1303-
pathOut = isFile and params.pathOut or "<output>"
1361+
local pathOut = isFile and params.pathOut or "<output>"
13041362

13051363
if isFile then
13061364
local file = assert(io.open(pathOut, "wb"))
@@ -1310,10 +1368,11 @@ local function _processFileOrString(params, isFile)
13101368
end
13111369

13121370
-- Test if the output is valid Lua.
1313-
local chunk, err = loadstring(lua, pathOut)
1371+
local chunk, err = loadLuaString(lua, pathOut)
13141372
if not chunk then
13151373
local ln, err = err:match'^%[string ".-"%]:(%d+): (.*)'
13161374
errorOnLine(pathOut, tonumber(ln), nil, "%s", err)
1375+
return nil, err
13171376
end
13181377

13191378
-- :ProcessInfo
@@ -1337,6 +1396,7 @@ end
13371396

13381397
local function processFileOrString(params, isFile)
13391398
local returnValues = nil
1399+
local err = nil
13401400

13411401
isDebug = params.debug
13421402
onError = function(_err)
@@ -1406,7 +1466,7 @@ local lib = {
14061466
-- processString()
14071467
-- Process Lua code.
14081468
--
1409-
-- code, info = processString( params )
1469+
-- luaString, info = processString( params )
14101470
-- info: Table with various information, or a message if an error happened. See 'ProcessInfo' for more info.
14111471
--
14121472
-- params: Table with these fields:

0 commit comments

Comments
 (0)