parsav  Diff

Differences From Artifact [b153c48352]:

To Artifact [f930d7a874]:


    34     34   	str = str:gsub('%s+[\n$]','')
    35     35   	str = str:gsub('\n','')
    36     36   	str = str:gsub('</a><a ','</a> <a ') -- keep nav links from getting smooshed
    37     37   	str = str:gsub(tplchar .. '%?([-%w]+)', function(file)
    38     38   		if not docs[file] then docs[file] = data.doc[file] end
    39     39   		return string.format('<a href="#help-%s" class="help">?</a>', file)
    40     40   	end)
           41  +	local detritus = ""
    41     42   	for start, mode, key, stop in string.gmatch(str,'()'..tplchar..'([+:!$#%^]?)([-a-zA-Z0-9_]+):?()') do
    42     43   		if string.sub(str,start-1,start-1) ~= '\\' then
    43         -			segs[#segs+1] = string.sub(str,last,start-1)
           44  +			local suffix = ""
           45  +			if mode == '$' then suffix = '"' end
           46  +			segs[#segs+1] = detritus .. string.sub(str,last,start-1) .. suffix
           47  +			detritus = ''
    44     48   			fields[#segs] = { key = key:gsub('-','_'), mode = (mode ~= '' and mode or nil) }
    45     49   			last = stop
           50  +			if mode == '$' then detritus = '"' end
    46     51   		end
    47     52   	end
    48         -	segs[#segs+1] = string.sub(str,last)
           53  +	segs[#segs+1] = detritus .. string.sub(str,last)
    49     54   
    50     55   	for i, s in ipairs(segs) do
    51     56   		segs[i] = string.gsub(s, '\\'..tplchar, tplchar_o)
    52     57   		constlen = constlen + string.len(segs[i])
    53     58   	end
    54     59   
    55     60   	for n,d in pairs(docs) do
................................................................................
   114    119   		senders[#senders+1] = quote lib.net.mg_send([destcon], [seg], [#seg]) end
   115    120   		appenders[#appenders+1] = quote [accumulator]:push([seg], [#seg]) end
   116    121   		if fields[idx] and fields[idx].mode then
   117    122   			local f = fields[idx]
   118    123   			local fp = `symself.[f.key]
   119    124   			local sanexp
   120    125   			local nulexp
   121         -			if f.mode == '$' then sanexp = `lib.str.qesc(pool, fp, true)
          126  +			if f.mode == '$' then sanexp = `lib.str.qesc(pool, fp, false)
          127  +				-- we use the detritus mechanism rather than the quote-wrap mechanism bc, apart
          128  +				-- from being faster, 0-length strings cannot be sanitized into -- >0-length
          129  +				-- strings due to how nullity is indicated (to wit, if fp == 0, ptr can be wild)
   122    130   			elseif f.mode == '+' then sanexp = `lib.str.qesc(pool, fp, false)
   123    131   			elseif f.mode == '#' then
   124    132   				sanexp = quote
   125    133   					var ibuf: int8[21]
   126    134   					var ptr = lib.math.decstr(fp, &ibuf[20])
   127    135   				in pstr {ptr=ptr, ct=&ibuf[20] - ptr} end
   128    136   			elseif f.mode == '^' then