parsav  Diff

Differences From Artifact [ce74a1083d]:

To Artifact [2f4ebceee0]:


    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         -	for start, mode, key, stop in string.gmatch(str,'()'..tplchar..'([:!$]?)([-a-zA-Z0-9_]+)()') do
           41  +	for start, mode, key, stop in string.gmatch(str,'()'..tplchar..'([+:!$#%^]?)([-a-zA-Z0-9_]+)()') do
    42     42   		if string.sub(str,start-1,start-1) ~= '\\' then
    43     43   			segs[#segs+1] = string.sub(str,last,start-1)
    44     44   			fields[#segs] = { key = key:gsub('-','_'), mode = (mode ~= '' and mode or nil) }
    45     45   			last = stop
    46     46   		end
    47     47   	end
    48     48   	segs[#segs+1] = string.sub(str,last)
................................................................................
    65     65   	local tallyup = {quote
    66     66   		var [runningtally] = 1 + constlen
    67     67   	end}
    68     68   	local rec = terralib.types.newstruct(string.format('template<%s>',tplspec.id or ''))
    69     69   	local symself = symbol(&rec)
    70     70   	do local kfac = {}
    71     71   		local sanmode = {}
           72  +		local types = { ['^'] = uint64, ['#'] = uint64 }
           73  +		local recmap = {}
    72     74   		for afterseg,fld in ipairs(fields) do
    73     75   			if not kfac[fld.key] then
    74     76   				rec.entries[#rec.entries + 1] = {
    75     77   					field = fld.key;
    76         -					type = lib.mem.ptr(int8);
           78  +					type = types[fld.mode] or pstr;
    77     79   				}
           80  +				recmap[fld.key] = rec.entries[#rec.entries]
    78     81   			end
    79     82   			kfac[fld.key] = (kfac[fld.key] or 0) + 1
    80     83   			sanmode[fld.key] = fld.mode == ':' and 6
    81     84   				or fld.mode == '!' and 5
    82         -				or fld.mode == '$' and 2 or 1
           85  +				or (fld.mode == '$' or fld.mode == '+') and 2
           86  +				or fld.mode == '^' and lib.math.shorthand.maxlen
           87  +				or fld.mode == '#' and 20
           88  +				or 1
    83     89   		end
    84     90   		for key, fac in pairs(kfac) do
    85     91   			local sanfac = sanmode[key]
    86         -			
    87         -			tallyup[#tallyup + 1] = quote
    88         -				[runningtally] = [runningtally] + ([symself].[key].ct)*fac*sanfac
           92  +			if recmap[key].type ~= pstr then
           93  +				tallyup[#tallyup + 1] = quote
           94  +					[runningtally] = [runningtally] + fac*sanfac
           95  +				end
           96  +			else
           97  +				tallyup[#tallyup + 1] = quote
           98  +					[runningtally] = [runningtally] + ([symself].[key].ct)*fac*sanfac
           99  +				end
    89    100   			end
    90    101   		end
    91    102   	end
    92    103   
    93    104   	local copiers = {}
    94    105   	local senders = {}
    95    106   	local appenders = {}
................................................................................
   102    113   		copiers[#copiers+1] = quote [cpypos] = lib.mem.cpy([cpypos], [&opaque]([seg]), [#seg]) end
   103    114   		senders[#senders+1] = quote lib.net.mg_send([destcon], [seg], [#seg]) end
   104    115   		appenders[#appenders+1] = quote [accumulator]:push([seg], [#seg]) end
   105    116   		if fields[idx] and fields[idx].mode then
   106    117   			local f = fields[idx]
   107    118   			local fp = `symself.[f.key]
   108    119   			local sanexp
   109         -			if f.mode == '$' then
   110         -				sanexp = `lib.str.qesc(pool, fp)
   111         -			else
   112         -				sanexp = `lib.html.sanitize(pool, fp, [f.mode == ':'])
   113         -			end
          120  +			local nulexp
          121  +			if f.mode == '$' then sanexp = `lib.str.qesc(pool, fp, true)
          122  +			elseif f.mode == '+' then sanexp = `lib.str.qesc(pool, fp, false)
          123  +			elseif f.mode == '#' then
          124  +				sanexp = quote
          125  +					var ibuf: int8[21]
          126  +					var ptr = lib.math.decstr(fp, &ibuf[20])
          127  +				in pstr {ptr=ptr, ct=&ibuf[20] - ptr} end
          128  +			elseif f.mode == '^' then
          129  +
          130  +				sanexp = quote
          131  +					var shbuf: lib.math.shorthand.t
          132  +					var len = lib.math.shorthand.gen(fp, &shbuf[0])
          133  +				in pstr {ptr=&shbuf[0],ct=len} end
          134  +			else sanexp = `lib.html.sanitize(pool, fp, [f.mode == ':']) end
          135  +			if f.mode == '^' or f.mode == '#' then nulexp = `true
          136  +			else nulexp = `fp.ct > 0 end
   114    137   			copiers[#copiers+1] = quote 
   115         -				if fp.ct > 0 then
          138  +				if [nulexp] then
   116    139   					var san = sanexp
   117    140   					[cpypos] = lib.mem.cpy([cpypos], [&opaque](san.ptr), san.ct)
   118    141   					--san:free()
   119    142   				end
   120    143   			end
   121    144   			senders[#senders+1] = quote
   122         -				if fp.ct > 0 then
          145  +				if [nulexp] then
   123    146   					var san = sanexp
   124    147   					lib.net.mg_send([destcon], san.ptr, san.ct)
   125    148   					--san:free()
   126    149   				end
   127    150   			end
   128    151   			appenders[#appenders+1] = quote
   129         -				if fp.ct > 0 then
          152  +				if [nulexp] then
   130    153   					var san = sanexp
   131    154   					[accumulator]:ppush(san)
   132    155   					--san:free()
   133    156   				end
   134    157   			end
   135    158   		elseif fields[idx] then
   136    159   			local f = fields[idx]