changeset 434:3d2c5d156d78

- test/suite_aggrs: support for nested structs, now
author Tassilo Philipp
date Sun, 23 Jan 2022 23:20:02 +0100
parents 45662241d9cd
children a29baee68340
files test/suite_aggrs/config.lua test/suite_aggrs/design.txt test/suite_aggrs/main.c test/suite_aggrs/mk-cases.lua test/suite_aggrs/rand-sig.lua
diffstat 5 files changed, 82 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/test/suite_aggrs/config.lua	Sat Jan 22 16:07:57 2022 +0100
+++ b/test/suite_aggrs/config.lua	Sun Jan 23 23:20:02 2022 +0100
@@ -1,10 +1,10 @@
 -- user config for rand-sig.lua:
 minargs      = 0
-maxargs      = 32
+maxargs      = 16
 maxaggrdepth = 3    -- max nesting depth of aggregates, 1 = no nesting
-ncases       = 400
+ncases       = 800
 types        = "csijlpfd{}"
-seed         = 2108
+seed         = 2112
 
 -- specify types more than once to increase relative occurance, e.g.:
 
--- a/test/suite_aggrs/design.txt	Sat Jan 22 16:07:57 2022 +0100
+++ b/test/suite_aggrs/design.txt	Sun Jan 23 23:20:02 2022 +0100
@@ -1,3 +1,4 @@
+ljdcjsl{}i{c}{}s
 v{ddd}
 vd{ddd}
 vdd{ddd}
--- a/test/suite_aggrs/main.c	Sat Jan 22 16:07:57 2022 +0100
+++ b/test/suite_aggrs/main.c	Sun Jan 23 23:20:02 2022 +0100
@@ -44,7 +44,7 @@
   return -1;
 }
 
-int invoke(char const* signature, void* t)
+static int invoke(char const* signature, void* t)
 {
   DCCallVM   * p = (DCCallVM*) G_callvm;
   char const * sig = signature;
@@ -71,7 +71,7 @@
     sig += len;
 
 	rtype_st_cmp = G_agg_cmpfuncs[i];
-    rtype_st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])();
+    rtype_st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])(NULL);
     dcBeginCallStruct(p, rtype_st, DC_FALSE);
   }
   else
@@ -98,7 +98,7 @@
           printf("unknown sig at '%s' ;", sig);
           return 0;
         }
-        DCstruct *st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])();
+        DCstruct *st = ((DCstruct*(*)())G_agg_newdcstfuncs[i])(NULL);
         dcArgStruct(p, st, K_a[pos]);
         sig += len-1; /* advance to next arg char */
         break;
--- a/test/suite_aggrs/mk-cases.lua	Sat Jan 22 16:07:57 2022 +0100
+++ b/test/suite_aggrs/mk-cases.lua	Sun Jan 23 23:20:02 2022 +0100
@@ -2,10 +2,18 @@
 local max = math.max
 local maxargs = 0
 
-local n_aggrs = 0
+local aggrs = { }
 local seen_aggrs = { }
 
 
+function canon_type(t)
+  -- struct types have more than one char
+  if #t > 1 then
+    return 'struct '..t
+  end
+  return t
+end
+
 function trim(l) return l:gsub("^%s+",""):gsub("%s+$","") end
 function mkcase(id,sig)
   local sig = trim(sig)
@@ -13,47 +21,48 @@
   local t = { "" }
   local pos = 0
   local n_nest = 0
-  local aggr
-  local aggr_sig = ''
+  local aggr = { }
+  local aggr_sig = { }
+  aggr[0] = { }     -- non-sequential [0] collects all non-aggr types
+  aggr_sig[0] = ''
   for i = 1, #sig do
     local name = "a"..pos
     local ch   = sig:sub(i,i)
 
-    aggr_sig = aggr_sig..ch
-
     -- aggregate nest level change?
     if ch == '{' then
       n_nest = n_nest + 1
-      aggr = { }
-      aggr_sig = ch  -- @@@ handle nesting
-    else
-      if ch == '}' then  -- @@@ handle nesting, here, by reusing structs
-        n_nest = n_nest - 1
-        -- aggr sig complete?
-        if n_nest == 0 then
-          -- register yet unseen aggregates, key is sig, val is body and name
-          if seen_aggrs[aggr_sig] == nil then
-            n_aggrs = n_aggrs + 1
-            ch = 'A'..n_aggrs
-            seen_aggrs[aggr_sig] = { aggr, ch }
-          end
-          ch = seen_aggrs[aggr_sig][2]
-        end
-      else
-        if n_nest > 0 then
-          aggr[#aggr+1] = ch
-          aggr[#aggr+1] = 'm'..(#aggr >> 1)
-        end
-      end
+      aggr[n_nest] = { }
+      aggr_sig[n_nest] = ''
     end
 
+    aggr_sig[n_nest] = aggr_sig[n_nest]..ch
+
+    if ch == '}' then
+      -- register yet unseen aggregates, key is sig, val is body and name
+      if seen_aggrs[aggr_sig[n_nest]] == nil then
+        aggrs[#aggrs+1] = aggr_sig[n_nest]
+        ch = 'A'..#aggrs
+        seen_aggrs[aggr_sig[n_nest]] = { aggr[n_nest], ch }
+      end
+      ch = seen_aggrs[aggr_sig[n_nest]][2]
+
+      n_nest = n_nest - 1
+      aggr_sig[n_nest] = aggr_sig[n_nest]..aggr_sig[n_nest+1]
+    end
+
+    if ch ~= '{' and ch ~= '}' then
+      aggr[n_nest][#aggr[n_nest]+1] = canon_type(ch)
+      aggr[n_nest][#aggr[n_nest]+1] = 'm'..(#aggr[n_nest] >> 1)
+    end
+
+
     if n_nest == 0 then
+      h[#h+1] = canon_type(ch)
       -- struct types (more than one char) need copying via a func
       if #ch > 1 then
-        h[#h+1] = 'struct '..ch
         t[#t+1] = 'f_cp'..ch..'(V_a['..pos.."],&"..name..");"
       else
-        h[#h+1] = ch
         t[#t+1] = "V_"..ch.."["..pos.."]="..name..";"
       end
 
@@ -112,7 +121,9 @@
   agg_sizes = {}
   agg_sigs  = {}
   agg_names = {}
-  for k, v in pairs(seen_aggrs) do
+  for a = 1, #aggrs do
+    k = aggrs[a]
+	v = seen_aggrs[k]
     st = 'struct '..v[2]
 
     agg_sizes[#agg_sizes + 1] = 'sizeof('..st..')'
@@ -121,7 +132,7 @@
 
     -- struct def
     io.write('/* '..k..' */\n')
-    io.write(st..'{ ')
+    io.write(st..' { ')
     for i = 1, #v[1], 2 do
       io.write(v[1][i]..' '..v[1][i+1]..'; ')
     end
@@ -132,25 +143,35 @@
       'void f_cp'..v[2]..'('..st..' *x, const '..st..' *y) { ',
       'int f_cmp'..v[2]..'(const '..st..' *x, const '..st..' *y) { return '
     }
-    o = { '=', '==', '; ', ' && '  }
+    o = { '=', '==', 'f_cp', 'f_cmp', '; ', ' && '  }
     for t = 1, 2 do
       io.write(s[t])
       b = {}
       for i = 1, #v[1], 2 do
-        b[#b+1] = 'x->'..v[1][i+1]..' '..o[t]..' y->'..v[1][i+1];
+        if string.match(v[1][i], '^struct') then
+		  b[#b+1] = o[t+2]..v[1][i]:sub(8)..'(&x->'..v[1][i+1]..', &y->'..v[1][i+1]..')';
+		else
+          b[#b+1] = 'x->'..v[1][i+1]..' '..o[t]..' y->'..v[1][i+1];
+		end
       end
       if #b == 0 then
         b[1] = '1'  -- to handle empty structs
       end
-      io.write(table.concat(b,o[t+2]).."; };\n")
+      io.write(table.concat(b,o[t+4]).."; };\n")
     end
 
     -- convenient dcnewstruct helper funcs
-    io.write('DCstruct* f_newdcst'..v[2]..'() { DCstruct* st = dcNewStruct('..(#v[1]>>1)..', sizeof('..st..'), 0, 1); ')
+    io.write('static int nfields'..v[2]..' = '..(#v[1]>>1)..';\n')
+    io.write('DCstruct* f_newdcst'..v[2]..'(DCstruct* parent) {\n\tDCstruct* st = parent;\n\tif(!st) st = dcNewStruct(nfields'..v[2]..', sizeof('..st..'), 0, 1);\n\t')
     for i = 1, #v[1], 2 do
-      io.write("dcStructField(st, '"..v[1][i].."', offsetof("..st..', '..v[1][i+1]..'), 1); ')
+      if string.match(v[1][i], '^struct') then
+	    io.write('dcSubStruct(st, nfields'..v[1][i]:sub(8)..', offsetof('..st..', '..v[1][i+1]..'), sizeof('..v[1][i]..'), 0, DC_TRUE, 1);\n\t')
+        io.write("f_newdcst"..v[1][i]:sub(8)..'(st);\n\t')
+	  else
+        io.write("dcStructField(st, '"..v[1][i].."', offsetof("..st..', '..v[1][i+1]..'), 1);\n\t')
+	  end
     end
-    io.write(" dcCloseStruct(st); return st; };\n")
+    io.write("dcCloseStruct(st);\n\treturn st;\n};\n")
   end
 
   -- make table.concat work
--- a/test/suite_aggrs/rand-sig.lua	Sat Jan 22 16:07:57 2022 +0100
+++ b/test/suite_aggrs/rand-sig.lua	Sun Jan 23 23:20:02 2022 +0100
@@ -3,27 +3,28 @@
 -- assure aggr chars are present in pairs (can be weighted, though), to avoid
 -- inf loops
 if string.match(types,'{') and not string.match(types,'}') then types = types..'}' end
+-- @@@ unions, arrays
 
 rtypes   = "v"..types
 
 
-function mkstruct(n_nest)
+function mkstruct(n_nest, maxdepth)
   local s = "{"
 
   repeat
     local id = math.random(#types)
     local t = types:sub(id,id)
-    s = s..mktype(t, n_nest)
+    s = s..mktype(t, n_nest, maxdepth)
   until t == '}'
 
   return s
 end
 
-function mktype(t, n_nest)
+function mktype(t, n_nest, maxdepth)
   -- ignore new structs if above depth limit
   if t == '{' then
-    if n_nest < maxaggrdepth then
-      return mkstruct(n_nest + 1)
+    if n_nest < maxdepth then
+      return mkstruct(n_nest + 1, maxdepth)
     else
       return ''
     end
@@ -41,14 +42,18 @@
 math.randomseed(seed)
 local id
 for i = 1, ncases do
-  id = math.random(#rtypes)
   local nargs = math.random(minargs,maxargs)
-  local sig   = { mktype(rtypes:sub(id,id), 0) }
-  for j = 1, nargs do
-    id = math.random(#types)
-    sig[#sig+1] = mktype(types:sub(id,id), 0)
-  end
-  io.write(table.concat(sig))
-  io.write("\n")
+  local l = ''
+  repeat
+    id = math.random(#rtypes)
+    local sig = { mktype(rtypes:sub(id,id), 0, math.random(maxaggrdepth)) } -- random depth avoids excessive nesting
+    for j = 1, nargs do
+      id = math.random(#types)
+      sig[#sig+1] = mktype(types:sub(id,id), 0, math.random(maxaggrdepth)) -- random depth avoids excessive nesting
+    end
+	l = table.concat(sig)
+    -- reject sigs without any aggregate, as this is about aggrs after all
+  until string.match(l, '{') ~= nil
+  io.write(l.."\n")
 end