Differences From
Artifact [ce74a1083d]:
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
................................................................................
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 = {}
................................................................................
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