diff test/common/mk-cases.lua @ 521:a2de1d0a73f3

- more test code generator code sharing/abstraction/simplifications
author Tassilo Philipp
date Wed, 13 Apr 2022 10:06:40 +0200
parents 99819b874bac
children f7fec6699e21
line wrap: on
line diff
--- a/test/common/mk-cases.lua	Mon Apr 11 22:49:04 2022 +0200
+++ b/test/common/mk-cases.lua	Wed Apr 13 10:06:40 2022 +0200
@@ -2,6 +2,7 @@
   return s:gsub("^%s+",""):gsub("%s+$","")
 end
 
+
 -- parse array notation, e.g. returns "a", 4 for "a[4]"
 function split_array_decl(s)
   local name = s
@@ -14,6 +15,118 @@
   return name, n
 end
 
+
+-- returns sig with return type first, and no ')' separator, e.g.:
+-- 'ijf)v' -> 'vijf'
+-- '){ii}' -> '{ii}'
+function put_sig_rtype_first(sig)
+  return sig:sub(sig:find(')')+1,-1)..sig:sub(1,sig:find(')')-1)
+end
+
+
+-- aggrs: (sequential) idx => aggr-sig
+-- seen_aggrs: aggr-sig => {{type0, name0, ...}, aggr_name}
+-- packing: 0=off, pos values set fixed packing, neg values set a random
+--          power-of-2 packing per aggregate, within [1,abs(aggrpacking)]
+-- packing_seed: seed for random packing (if used)
+function mkaggrdefs(aggrs, seen_aggrs, packing, packingseed)
+  local agg_defs  = { }
+  local agg_sizes = { }
+  local agg_sigs  = { }
+  local agg_names = { }
+
+  math.randomseed(packingseed)
+
+  for a = 1, #aggrs do
+    local k = aggrs[a]
+    local v = seen_aggrs[k]
+    local am = v[1]            -- aggregate members
+    local at = v[2]            -- aggregate type
+    local an = at:match('A.*') -- aggregate name (w/o struct or union)
+
+    -- aggregate def
+    aggr_def = '/* '..k..' */\n'
+    if packing ~= 0 then
+      local pack = packing
+      if pack < 0 then
+        pack = math.floor(math.pow(2,math.floor(math.log(math.random(math.abs(pack)),2))))
+      end
+      aggr_def = aggr_def..'#pragma pack(push,'..pack..')\n'
+    end
+
+    aggr_def = aggr_def..at..' { '
+    for i = 1, #am, 2 do
+      aggr_def = aggr_def..am[i]..' '..am[i+1]..'; '
+    end
+    aggr_def = aggr_def..'};\n'
+
+    if packing ~= 0 then
+      aggr_def = aggr_def..'#pragma pack(pop)\n'
+    end
+
+    -- aggregate cp and cmp funcs
+    s = {
+      'void f_cp'..an..'('..at..' *x, const '..at..' *y) { ',
+      'int f_cmp'..an..'(const '..at..' *x, const '..at..' *y) { return '
+    }
+    o = { '=', '==', 'f_cp', 'f_cmp', '; ', ' && ', '', '1' }
+    for t = 1, 2 do
+      if t ~= 1 or aggrcpsimple == false then
+        aggr_def = aggr_def..s[t]
+        local b = {}
+        for i = 1, #am, 2 do
+          local mn, mc = split_array_decl(am[i+1]) -- aggr member name and (array) count
+          local fmt = ''
+          if mc ~= nil then -- need array suffixes?
+            fmt = '[%d]'
+          else
+            mc = 1
+          end
+
+          for j = 1, mc do
+            name = mn..fmt:format(j-1)
+            amn = am[i]:match('A.*')
+            if amn then -- is aggr?
+              b[#b+1] = o[t+2]..amn..'(&x->'..name..', &y->'..name..')'
+            else
+              b[#b+1] = 'x->'..name..' '..o[t]..' y->'..name
+            end
+          end
+        end
+        if #b == 0 then  -- to handle empty aggregates
+          b[1] = o[t+6]
+        end
+        aggr_def = aggr_def..table.concat(b,o[t+4])..'; };\n'
+      end
+    end
+
+    -- write convenient dcNewAggr() helper/wrapper funcs
+    aggr_def = aggr_def..'DCaggr* f_touch'..an..'() {\n\tstatic DCaggr* a = NULL;\n\tif(!a) {\n\t\ta = dcNewAggr('..(#am>>1)..', sizeof('..at..'));\n\t\t'
+    for i = 1, #am, 2 do
+      local mn, mc = split_array_decl(am[i+1])
+      if mc == nil then
+        mc = 1
+      end
+      amn = am[i]:match('A.*')
+      if amn then -- is aggr?
+        --aggr_def = aggr_def..'dcAggrField(at, DC_SIGCHAR_AGGREGATE, offsetof('..at..', '..mn..'), '..mc..', f_touch'..amn..'());\n\t\t'
+        aggr_def = aggr_def.."AFa("..at..','..mn..','..mc..','..amn..')\n\t\t'
+      else
+        --aggr_def = aggr_def.."dcAggrField(at, '"..am[i].."', offsetof("..at..', '..mn..'), '..mc..');\n\t\t'
+        aggr_def = aggr_def.."AF('"..am[i].."',"..at..','..mn..','..mc..')\n\t\t'
+      end
+    end
+
+    agg_defs [#agg_defs  + 1] = aggr_def..'dcCloseAggr(a);\n\t}\n\treturn a;\n};'
+    agg_sizes[#agg_sizes + 1] = 'sizeof('..at..')'
+    agg_sigs [#agg_sigs  + 1] = k
+    agg_names[#agg_names + 1] = an
+  end
+
+  return agg_defs, agg_sizes, agg_sigs, agg_names
+end
+
+
 function mkfuntab(n, prefix, t, array_name, with_cast)
   local s = { t.." "..array_name.."[] = {\n"}
   local cast = ''
@@ -27,6 +140,7 @@
   return table.concat(s,"")
 end
 
+
 -- @@@ sigprefix should be added by generators, not here
 function mksigtab(sigs, sigprefix, array_name)
   local s = { "const char * "..array_name.."[] = {\n"}