Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #41, render union members if all in same EDS #45

Merged
merged 1 commit into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 41 additions & 20 deletions edslib/eds/40-seds_write_headers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,39 +59,58 @@ end
-- -------------------------------------------------
local function write_c_struct_typedef(output,node)
local checksum = node.resolved_size.checksum
local struct_name = string.format("struct %s", SEDS.to_safe_identifier(node:get_qualified_name()))
local struct_flavor = node.is_union and "union" or "struct"
local struct_name = string.format("%s %s", struct_flavor, SEDS.to_safe_identifier(node:get_qualified_name()))

-- this potentially renders create more than one struct with same checksum.
-- This just records the first/initial occurrence of this checksum
if (not output.checksum_table[checksum]) then
output.checksum_table[checksum] = struct_name
end

-- Structures which are union members do not need to be rendered as a separate typedef
if (node.basetype and node.basetype.is_union) then
return
end

-- Note that the XML allows one to specify a container/interface with no members.
-- but C language generally frowns upon structs with no members. So this check is
-- in place to avoid generating such code.
if (#node.decode_sequence > 0) then
if (#node.decode_sequence > 0 or node.is_union) then
output:add_documentation(string.format("Structure definition for %s \'%s\'", node.entity_type, node:get_qualified_name()),
"Data definition signature " .. checksum)
output:write(string.format("%s /* checksum=%s */", struct_name, checksum))
output:start_group("{")
for idx,ref in ipairs(node.decode_sequence) do
local c_name = ref.type:get_flattened_name()
-- If the entry refers to a base type, then use a buffer instead of a direct instance here,
-- but only if the derivatives actually do extend the type (i.e. add fields).
if (ref.name and ref.type.max_size and ref.type.max_size.bits > ref.type.resolved_size.bits) then
c_name = c_name .. "_Buffer"
if (node.is_union) then
local derivmap = node.derivative_decisiontree_map
for _,deriv in ipairs(derivmap.derivatives) do
local entry = deriv.decode_sequence[1]
if (entry.type) then
output:write(string.format("%-30s %s;", entry.type:get_flattened_name() .. "_t", SEDS.to_safe_identifier(entry.name)))
end
end
if (ref.entry) then
output:add_documentation(ref.entry.attributes.shortdescription, ref.entry.longdescription)
else
for idx,ref in ipairs(node.decode_sequence) do
local c_name = ref.type:get_flattened_name()
-- If the entry refers to a base type, then use a buffer instead of a direct instance here,
-- but only if the derivatives actually do extend the type (i.e. add fields).
if (ref.name and ref.type.max_size and (ref.type.max_size.bits > ref.type.resolved_size.bits) and not ref.type.is_union) then
c_name = c_name .. "_Buffer"
end
if (ref.entry) then
output:add_documentation(ref.entry.attributes.shortdescription, ref.entry.longdescription)
end
output:write(string.format("%-50s %-30s /* %-3d bits/%-3d bytes */",
c_name .. "_t",
(ref.name or ref.type.name) .. ";",
ref.type.resolved_size.bits,
ref.type.resolved_size.bytes))
end
output:write(string.format("%-50s %-30s /* %-3d bits/%-3d bytes */",
c_name .. "_t",
(ref.name or ref.type.name) .. ";",
ref.type.resolved_size.bits,
ref.type.resolved_size.bytes))
end
output:end_group("};")
else
-- Just output something as a clue that this structure was in the EDS but did not get rendered into a C type
output:write(string.format("/* Empty Structure: %s */",struct_name))
end

return { ctype = struct_name }
Expand All @@ -104,7 +123,7 @@ local function write_c_array_typedef(output,node)
local basetype_name = node.datatyperef:get_flattened_name()
local basetype_modifier = ""

if (node.datatyperef.max_size) then
if (node.datatyperef.max_size and not node.datatyperef.is_union) then
basetype_name = basetype_name .. "_Buffer"
end

Expand Down Expand Up @@ -306,10 +325,13 @@ for ds in SEDS.root:iterate_children(SEDS.basenode_filter) do
if (node.resolved_size) then
local packedsize = 0
local buffname = node:get_flattened_name()
if (node.max_size) then
if (node.max_size and not node.is_union) then
output:write(string.format("union %s_Buffer", buffname))
output:start_group("{")
output:write(string.format("%-50s BaseObject;", node.header_data.typedef_name))
-- The base object may be empty in EDS, so do not make a C ref to an empty object
if (#node.decode_sequence > 0) then
output:write(string.format("%-50s BaseObject;", node.header_data.typedef_name))
end
output:write(string.format("%-50s Byte[%d];", "uint8_t", node.max_size.bytes))
local aligntype = (node.max_size.alignment <= 64) and tostring(node.max_size.alignment) or "max"
output:write(string.format("%-50s Align%d;", "uint" .. aligntype .. "_t", node.max_size.alignment))
Expand All @@ -330,11 +352,10 @@ for ds in SEDS.root:iterate_children(SEDS.basenode_filter) do
end
end


output:section_marker("Components")
for comp in ds:iterate_subtree("COMPONENT") do
comp.header_data = write_c_struct_typedef(output,comp)
if (comp.resolved_size) then
if (comp.resolved_size and comp.header_data) then
local c_name = comp:get_flattened_name()
comp.edslib_refobj_local_index = c_name .. "_DATADICTIONARY"
comp.edslib_refobj_initializer = string.format("{ %s, %s }", ds.edslib_refobj_global_index,
Expand Down
6 changes: 6 additions & 0 deletions tool/scripts/20-seds_resolve_sizes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -681,8 +681,12 @@ while (SEDS.get_error_count() == 0) do

-- Make a pass through the "derived" table, to calculate
-- the _maximum_ size of these objects (which is helpful for sizing buffers)
-- This also recognizes a special case of container inheritance where an empty base
-- is derived by several containers, each having only one single entry. In this context
-- this becomes a union of all the derived container entries.
for node,deriv_list in pairs(derived_node_table) do
if (node.resolved_size) then
local is_union = (not node.basetype) and (#node.decode_sequence == 0)
local pending_max_size = SEDS.new_size_object(node.resolved_size)
for i,deriv_node in ipairs(deriv_list) do
if (derived_node_table[deriv_node]) then
Expand All @@ -695,9 +699,11 @@ while (SEDS.get_error_count() == 0) do
break
end
pending_max_size:union(deriv_size)
is_union = is_union and (#deriv_node.decode_sequence == 1)
end
if (pending_max_size) then
resolved_count = resolved_count + 1
node.is_union = is_union
node.max_size = pending_max_size
derived_node_table[node] = nil
elseif (resolve_error) then
Expand Down