mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-16 17:32:13 +00:00
Lunatic translator: fix quote commands, taking care of corner cases. Add test.
git-svn-id: https://svn.eduke32.com/eduke32@3511 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
9f843fb445
commit
db2c24b7ef
3 changed files with 122 additions and 21 deletions
|
@ -9,11 +9,13 @@ local math = require("math")
|
|||
local geom = require("geom")
|
||||
local con_lang = require("con_lang")
|
||||
|
||||
local byte = require("string").byte
|
||||
local setmetatable = setmetatable
|
||||
|
||||
local assert = assert
|
||||
local error = error
|
||||
local print = print
|
||||
local tostring = tostring
|
||||
local type = type
|
||||
local unpack = unpack
|
||||
|
||||
|
@ -455,12 +457,13 @@ local function strlen(cstr)
|
|||
assert(false)
|
||||
end
|
||||
|
||||
-- NOTE: dst==src is OK (effectively a no-op)
|
||||
local function strcpy(dst, src)
|
||||
local i=-1
|
||||
repeat
|
||||
i = i+1
|
||||
dst[i] = src[i]
|
||||
until (src[i]~=0)
|
||||
until (src[i]==0)
|
||||
end
|
||||
|
||||
function _qstrlen(qnum)
|
||||
|
@ -473,16 +476,42 @@ function _qstrcpy(qdst, qsrc)
|
|||
strcpy(cstr_dst, cstr_src)
|
||||
end
|
||||
|
||||
-- NOTE: qdst==qsrc is OK (duplicates the quote)
|
||||
function _qstrcat(qdst, qsrc)
|
||||
local cstr_dst = bcheck.quote_idx(qdst)
|
||||
local cstr_src = bcheck.quote_idx(qsrc)
|
||||
|
||||
local i, j = strlen(cstr_dst), 0
|
||||
while (i < MAXQUOTELEN-1) do
|
||||
cstr_dst[i] = cstr_src[j]
|
||||
if (cstr_src[0]==0) then
|
||||
return
|
||||
end
|
||||
|
||||
if (cstr_dst[0]==0) then
|
||||
return strcpy(cstr_dst, cstr_src)
|
||||
end
|
||||
|
||||
-- From here on: destination and source quote (potentially aliased) are
|
||||
-- nonempty.
|
||||
|
||||
local slen_dst = strlen(cstr_dst)
|
||||
assert(slen_dst <= MAXQUOTELEN-1)
|
||||
|
||||
if (slen_dst == MAXQUOTELEN-1) then
|
||||
return
|
||||
end
|
||||
|
||||
local i = slen_dst
|
||||
local j = 0
|
||||
|
||||
repeat
|
||||
-- NOTE: don't copy the first char yet, so that the qdst==qsrc case
|
||||
-- works correctly.
|
||||
i = i+1
|
||||
j = j+1
|
||||
end
|
||||
cstr_dst[i] = cstr_src[j]
|
||||
until (i >= MAXQUOTELEN-1 or cstr_src[j]==0)
|
||||
|
||||
-- Now copy the first char!
|
||||
cstr_dst[slen_dst] = cstr_src[0]
|
||||
cstr_dst[i] = 0
|
||||
end
|
||||
|
||||
|
@ -493,7 +522,7 @@ function _qsprintf(qdst, qsrc, ...)
|
|||
local src = bcheck.quote_idx(qsrc)
|
||||
local vals = {...}
|
||||
|
||||
local i, j, vi = 0, 0, 0
|
||||
local i, j, vi = 0, 0, 1
|
||||
|
||||
while (true) do
|
||||
local ch = src[j]
|
||||
|
@ -503,13 +532,13 @@ function _qsprintf(qdst, qsrc, ...)
|
|||
break
|
||||
end
|
||||
|
||||
if (ch=='%') then
|
||||
if (ch==byte'%') then
|
||||
local nch = src[j+1]
|
||||
if (nch=='d' or (nch=='l' and src[j+2]=='d')) then
|
||||
if (nch==byte'd' or (nch==byte'l' and src[j+2]==byte'd')) then
|
||||
-- number
|
||||
didfmt = true
|
||||
|
||||
if (vi == #vals) then
|
||||
if (vi > #vals) then
|
||||
break
|
||||
end
|
||||
|
||||
|
@ -521,23 +550,24 @@ function _qsprintf(qdst, qsrc, ...)
|
|||
ffi.copy(buf+i, numstr, ncopied)
|
||||
|
||||
i = i+ncopied
|
||||
j = j+1+(nch=='d' and 1 or 2)
|
||||
elseif (nch=='s') then
|
||||
j = j+1+(nch==byte'd' and 1 or 2)
|
||||
elseif (nch==byte's') then
|
||||
-- string
|
||||
didfmt = true
|
||||
|
||||
if (vi == #vals) then
|
||||
if (vi > #vals) then
|
||||
break
|
||||
end
|
||||
|
||||
local k = -1
|
||||
local tmpsrc = bcheck.quote_idx(vals[vi])
|
||||
vi = vi+1
|
||||
|
||||
i = i-1
|
||||
repeat
|
||||
i = i+1
|
||||
k = k+1
|
||||
buf[i] = tmpsrc[k]
|
||||
i = i+1
|
||||
until (i < MAXQUOTELEN-1 and tmpsrc[k]~=0)
|
||||
until (i >= MAXQUOTELEN-1 or tmpsrc[k]==0)
|
||||
|
||||
j = j+2
|
||||
end
|
||||
|
|
|
@ -747,11 +747,13 @@ function Cmd.definequote(qnum, quotestr)
|
|||
|
||||
quotestr = stripws(quotestr)
|
||||
|
||||
if (ffi) then
|
||||
if (#quotestr >= conl.MAXQUOTELEN) then
|
||||
warnprintf("quote %d truncated to %d characters.", conl.MAXQUOTELEN-1)
|
||||
end
|
||||
if (#quotestr >= conl.MAXQUOTELEN) then
|
||||
-- NOTE: Actually, C_DefineQuote takes care of this! That is,
|
||||
-- standalone, the string isn't truncated.
|
||||
warnprintf("quote %d truncated to %d characters.", qnum, conl.MAXQUOTELEN-1)
|
||||
end
|
||||
|
||||
if (ffi) then
|
||||
ffiC.C_DefineQuote(qnum, quotestr)
|
||||
end
|
||||
|
||||
|
@ -2720,8 +2722,11 @@ else
|
|||
|
||||
for _, fname in ipairs(filenames) do
|
||||
local ok, msg = pcall(do_include_file, "", fname)
|
||||
if (not ok) then
|
||||
print_on_failure(msg)
|
||||
if (not ok or g_numerrors > 0) then
|
||||
if (not ok) then
|
||||
-- Unexpected error in the Lua code (i.e. a bug here).
|
||||
print_on_failure(msg)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
|
66
polymer/eduke32/source/lunatic/test/quote_ops.con
Normal file
66
polymer/eduke32/source/lunatic/test/quote_ops.con
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Don't try in C-CON!
|
||||
|
||||
gamevar slen 0 0
|
||||
gamevar n -12345678 0 // a number having length 9 in the decimal representation
|
||||
|
||||
// overlong string at definition (should warn)
|
||||
definequote 400 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789=123456789-
|
||||
|
||||
onevent EVENT_ENTERLEVEL
|
||||
redefinequote 114 QWE
|
||||
|
||||
redefinequote 115 012345678|
|
||||
// qstrcat X Y, where X==Y: duplicates the quote
|
||||
qstrcat 115 115
|
||||
userquote 115 // "012345678|012345678|"
|
||||
|
||||
// simple qstrcpy test
|
||||
qstrcpy 116 115
|
||||
userquote 116 // "012345678|012345678|"
|
||||
|
||||
redefinequote 117 %s -- %d -- %s -- %d slen=%d
|
||||
// test:
|
||||
// - same destination quote as the format quote
|
||||
// - multiple conversions
|
||||
qstrlen slen 115 // -> 10
|
||||
qsprintf 117 /*<-*/ 117 /*args:*/ 116 9999 114 5555 slen
|
||||
userquote 117 // "012345678|012345678| -- 9999 -- QWE -- 5555 slen=10"
|
||||
|
||||
redefinequote 117 %s -- %d -- %s -- %d slen=%d
|
||||
// test:
|
||||
// - same destination quote as on of the source quotes under %s conversion
|
||||
qsprintf 116 /*<-*/ 117 /*args:*/ 116 9999 116 5555 slen
|
||||
userquote 116 // "012345678|012345678| -- 9999 -- 012345678|012345678| -- 5555 slen=10"
|
||||
|
||||
// aliased qstrcpy test (a no-op)
|
||||
qstrcpy 115 115
|
||||
userquote 115 // still "012345678|012345678|"
|
||||
|
||||
qstrcat 115 115 // len 40
|
||||
qstrcat 115 115 // len 80
|
||||
qstrcat 115 115
|
||||
// result now: 12 x "012345678|" concantenated with "0123456" (= total length 127 = MAXQUOTELEN-1)
|
||||
qstrcat 115 115 // this one is redundant, but must not overflow the quote buffer
|
||||
userquote 115
|
||||
|
||||
redefinequote 117 X%s
|
||||
qsprintf 117 /*<-*/ 117 /*args:*/ 115
|
||||
userquote 117 // result: "X" .. 12 x "012345678|" .. "012345" (= total length 127 = MAXQUOTELEN-1)
|
||||
|
||||
// 32 %d (or %ld) conversion
|
||||
redefinequote 117 %ld|%d|%ld|%d|%ld|%ld|%d|%ld|%d|%ld/%ld|%d|%ld|%d|%ld|%ld|%d|%ld|%d|%ld/%ld|%d|%ld|%d|%ld|%ld|%d|%ld|%d|%ld/%d/%d
|
||||
// string shorter than MAXQUOTELEN-1:
|
||||
qsprintf 116 /*<-*/ 117 /*args:*/ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// result: "0|1|2|3|4|5|6|7|8|9/0|1|2|3|4|5|6|7|8|9/0|1|2|3|4|5|6|7|8|9/0/1"
|
||||
userquote 116
|
||||
|
||||
// string longer than MAXQUOTELEN-1:
|
||||
qsprintf 116 /*<-*/ 117 /*args:*/ n n n n n n n n n n /**/ n n n n n n n n n n /**/ n n
|
||||
userquote 116
|
||||
// result: 10 x "-12345678" .. "/-12345678|-12345678|-123456" (= total length 127 = MAXQUOTELEN-1)
|
||||
|
||||
// overlong string at redefinition
|
||||
redefinequote 117 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789=123456789-
|
||||
userquote 117 // should end in "=1234567" (= total length 127 = MAXQUOTELEN-1)
|
||||
userquote 400 // same thing
|
||||
endevent
|
Loading…
Reference in a new issue