Mercurial > pub > dyncall > dyncall
view test/common/mk-cases.lua @ 522:f7fec6699e21
- test code generator code: var abstraction
author | Tassilo Philipp |
---|---|
date | Wed, 13 Apr 2022 10:19:49 +0200 |
parents | a2de1d0a73f3 |
children |
line wrap: on
line source
function trim(s) 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 local n = nil -- not an array local i = s:find('%[') if i ~= nil then name = name:sub(1, i-1) n = tonumber(s:sub(i):match('[0123456789]+')) end 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) -- cpsimple: whether or not to copy aggregates via '=' or field by field 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 cpsimple == 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 = '' if with_cast == true then cast = '('..t..')' end for i = 0, n-1 do s[#s+1] = "\t"..cast.."&"..prefix..i..",\n" end s[#s+1] = "};\n" 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"} for k,v in pairs(sigs) do s[#s+1] = '\t"'..sigprefix..v..'",\n' end s[#s+1] = "};\n" return table.concat(s,"") end