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
8888
8989--============================================================]]
9090
91- local VERSION = " 1.3.0 "
91+ local VERSION = " 1.3.1 "
9292
9393local 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
98100local 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
105109local ESCAPE_SEQUENCES = {
@@ -117,6 +121,20 @@ local ESCAPE_SEQUENCES = {
117121
118122local 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+
120138local _error = error
121139
122140local metaEnv = nil
@@ -141,8 +159,9 @@ local escapePattern
141159local F
142160local getFileContents , fileExists
143161local isAny
162+ local loadLuaString , loadLuaFile
144163local maybeOutputLineNumber
145- local pack
164+ local pack , unpack
146165local parseStringlike
147166local printf , printTokens
148167local 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
673729end
674730
675731-- ==============================================================
676- -- = Preprocessor Function = =====================================
732+ -- = Preprocessor Functions =====================================
677733-- ==============================================================
678734
679735
@@ -721,11 +777,8 @@ metaFuncs.escapePattern = escapePattern
721777function 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
13381397local 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