diff test/suite_aggrs/mk-cases.lua @ 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
line wrap: on
line diff
--- 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