mirror of
https://github.com/holub/mame
synced 2025-10-04 16:34:53 +03:00
allow repeating elements and groups - useful if you need e.g. a lot of numbered labels, but it limits complay.py's ability to check for invalid references as it can't evaluate expressions (nw)
This commit is contained in:
parent
7809e9005d
commit
6669489679
@ -274,6 +274,7 @@ class LayoutChecker(Minifyer):
|
||||
except:
|
||||
self.handleError('Element mamelayout attribute version "%s" is not an integer' % (attrs['version'], ))
|
||||
self.variable_scopes.append({ })
|
||||
self.repeat_depth.append(0)
|
||||
self.handlers.append((self.layoutStartHandler, self.layoutEndHandler))
|
||||
|
||||
def rootEndHandler(self, name, attrs):
|
||||
@ -284,18 +285,24 @@ class LayoutChecker(Minifyer):
|
||||
if 'name' not in attrs:
|
||||
self.handleError('Element element missing attribute name')
|
||||
else:
|
||||
generated_name = self.VARPATTERN.match(attrs['name'])
|
||||
if generated_name:
|
||||
self.generated_element_names = True
|
||||
if attrs['name'] not in self.elements:
|
||||
self.elements[attrs['name']] = self.formatLocation()
|
||||
elif not self.VARPATTERN.match(attrs['name']):
|
||||
elif not generated_name:
|
||||
self.handleError('Element element has duplicate name (previous %s)' % (self.elements[attrs['name']], ))
|
||||
self.handlers.append((self.elementStartHandler, self.elementEndHandler))
|
||||
elif 'group' == name:
|
||||
if 'name' not in attrs:
|
||||
self.handleError('Element group missing attribute name')
|
||||
else:
|
||||
generated_name = self.VARPATTERN.match(attrs['name'])
|
||||
if generated_name:
|
||||
self.generated_group_names = True
|
||||
if attrs['name'] not in self.groups:
|
||||
self.groups[attrs['name']] = self.formatLocation()
|
||||
elif not self.VARPATTERN.match(attrs['name']):
|
||||
elif not generated_name:
|
||||
self.handleError('Element group has duplicate name (previous %s)' % (self.groups[attrs['name']], ))
|
||||
self.handlers.append((self.groupViewStartHandler, self.groupViewEndHandler))
|
||||
self.variable_scopes.append({ })
|
||||
@ -313,6 +320,15 @@ class LayoutChecker(Minifyer):
|
||||
self.variable_scopes.append({ })
|
||||
self.repeat_depth.append(0)
|
||||
self.have_bounds.append(False)
|
||||
elif 'repeat' == name:
|
||||
if 'count' not in attrs:
|
||||
self.handleError('Element repeat missing attribute count')
|
||||
else:
|
||||
count = self.checkIntAttribute(name, attrs, 'count', None)
|
||||
if (count is not None) and (0 >= count):
|
||||
self.handleError('Element repeat attribute count "%s" is negative' % (attrs['count'], ))
|
||||
self.variable_scopes.append({ })
|
||||
self.repeat_depth[-1] += 1
|
||||
elif 'param' == name:
|
||||
self.checkParameter(attrs)
|
||||
self.ignored_depth = 1
|
||||
@ -323,13 +339,18 @@ class LayoutChecker(Minifyer):
|
||||
self.ignored_depth = 1
|
||||
|
||||
def layoutEndHandler(self, name):
|
||||
self.variable_scopes.pop()
|
||||
if self.repeat_depth[-1]:
|
||||
self.repeat_depth[-1] -= 1
|
||||
else:
|
||||
if not self.generated_element_names:
|
||||
for element in self.referenced_elements:
|
||||
if (element not in self.elements) and (not self.VARPATTERN.match(element)):
|
||||
self.handleError('Element "%s" not found (first referenced at %s)' % (element, self.referenced_elements[element]))
|
||||
if not self.generated_group_names:
|
||||
for group in self.referenced_groups:
|
||||
if (group not in self.groups) and (not self.VARPATTERN.match(group)):
|
||||
self.handleError('Group "%s" not found (first referenced at %s)' % (group, self.referenced_groups[group]))
|
||||
self.variable_scopes.pop()
|
||||
self.handlers.pop()
|
||||
|
||||
def elementStartHandler(self, name, attrs):
|
||||
@ -456,6 +477,8 @@ class LayoutChecker(Minifyer):
|
||||
self.repeat_depth = [ ]
|
||||
self.have_bounds = [ ]
|
||||
self.have_color = [ ]
|
||||
self.generated_element_names = False
|
||||
self.generated_group_names = False
|
||||
super(LayoutChecker, self).startDocument()
|
||||
|
||||
def endDocument(self):
|
||||
@ -471,6 +494,8 @@ class LayoutChecker(Minifyer):
|
||||
del self.repeat_depth
|
||||
del self.have_bounds
|
||||
del self.have_color
|
||||
del self.generated_element_names
|
||||
del self.generated_group_names
|
||||
super(LayoutChecker, self).endDocument()
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
|
@ -932,6 +932,17 @@ public:
|
||||
view_list const &views() const { return m_viewlist; }
|
||||
|
||||
private:
|
||||
using environment = emu::render::detail::layout_environment;
|
||||
|
||||
// add elements and parameters
|
||||
void add_elements(
|
||||
char const *dirname,
|
||||
environment &env,
|
||||
util::xml::data_node const &parentnode,
|
||||
group_map &groupmap,
|
||||
bool repeat,
|
||||
bool init);
|
||||
|
||||
// internal state
|
||||
element_map m_elemmap; // list of shared layout elements
|
||||
view_list m_viewlist; // list of views
|
||||
|
@ -3356,13 +3356,14 @@ void layout_view::item::resolve_tags()
|
||||
// layout_file - constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
layout_file::layout_file(device_t &device, util::xml::data_node const &rootnode, const char *dirname)
|
||||
layout_file::layout_file(device_t &device, util::xml::data_node const &rootnode, char const *dirname)
|
||||
: m_elemmap()
|
||||
, m_viewlist()
|
||||
{
|
||||
emu::render::detail::layout_environment env(device);
|
||||
try
|
||||
{
|
||||
environment env(device);
|
||||
|
||||
// find the layout node
|
||||
util::xml::data_node const *const mamelayoutnode = rootnode.get_child("mamelayout");
|
||||
if (!mamelayoutnode)
|
||||
@ -3373,30 +3374,9 @@ layout_file::layout_file(device_t &device, util::xml::data_node const &rootnode,
|
||||
if (version != LAYOUT_VERSION)
|
||||
throw layout_syntax_error(util::string_format("unsupported version %d", version));
|
||||
|
||||
// parse all the parameters
|
||||
for (util::xml::data_node const *elemnode = mamelayoutnode->get_child("param") ; elemnode; elemnode = elemnode->get_next_sibling("param"))
|
||||
env.set_parameter(*elemnode);
|
||||
|
||||
// parse all the elements
|
||||
for (util::xml::data_node const *elemnode = mamelayoutnode->get_child("element"); elemnode; elemnode = elemnode->get_next_sibling("element"))
|
||||
{
|
||||
char const *const name(env.get_attribute_string(*elemnode, "name", nullptr));
|
||||
if (!name)
|
||||
throw layout_syntax_error("element lacks name attribute");
|
||||
if (!m_elemmap.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(env, *elemnode, dirname)).second)
|
||||
throw layout_syntax_error(util::string_format("duplicate element name %s", name));
|
||||
}
|
||||
|
||||
// parse all the groups
|
||||
// parse all the parameters, elements and groups
|
||||
group_map groupmap;
|
||||
for (util::xml::data_node const *groupnode = mamelayoutnode->get_child("group"); groupnode; groupnode = groupnode->get_next_sibling("group"))
|
||||
{
|
||||
char const *const name(env.get_attribute_string(*groupnode, "name", nullptr));
|
||||
if (!name)
|
||||
throw layout_syntax_error("group lacks name attribute");
|
||||
if (!groupmap.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(*groupnode)).second)
|
||||
throw layout_syntax_error(util::string_format("duplicate group name %s", name));
|
||||
}
|
||||
add_elements(dirname, env, *mamelayoutnode, groupmap, false, true);
|
||||
|
||||
// parse all the views
|
||||
for (util::xml::data_node const *viewnode = mamelayoutnode->get_child("view"); viewnode != nullptr; viewnode = viewnode->get_next_sibling("view"))
|
||||
@ -3430,3 +3410,56 @@ layout_file::layout_file(device_t &device, util::xml::data_node const &rootnode,
|
||||
layout_file::~layout_file()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void layout_file::add_elements(
|
||||
char const *dirname,
|
||||
environment &env,
|
||||
util::xml::data_node const &parentnode,
|
||||
group_map &groupmap,
|
||||
bool repeat,
|
||||
bool init)
|
||||
{
|
||||
for (util::xml::data_node const *childnode = parentnode.get_first_child(); childnode; childnode = childnode->get_next_sibling())
|
||||
{
|
||||
if (!strcmp(childnode->get_name(), "param"))
|
||||
{
|
||||
if (!repeat)
|
||||
env.set_parameter(*childnode);
|
||||
else
|
||||
env.set_repeat_parameter(*childnode, init);
|
||||
}
|
||||
else if (!strcmp(childnode->get_name(), "element"))
|
||||
{
|
||||
char const *const name(env.get_attribute_string(*childnode, "name", nullptr));
|
||||
if (!name)
|
||||
throw layout_syntax_error("element lacks name attribute");
|
||||
if (!m_elemmap.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(env, *childnode, dirname)).second)
|
||||
throw layout_syntax_error(util::string_format("duplicate element name %s", name));
|
||||
}
|
||||
else if (!strcmp(childnode->get_name(), "group"))
|
||||
{
|
||||
char const *const name(env.get_attribute_string(*childnode, "name", nullptr));
|
||||
if (!name)
|
||||
throw layout_syntax_error("group lacks name attribute");
|
||||
if (!groupmap.emplace(std::piecewise_construct, std::forward_as_tuple(name), std::forward_as_tuple(*childnode)).second)
|
||||
throw layout_syntax_error(util::string_format("duplicate group name %s", name));
|
||||
}
|
||||
else if (!strcmp(childnode->get_name(), "repeat"))
|
||||
{
|
||||
int const count(env.get_attribute_int(*childnode, "count", -1));
|
||||
if (0 >= count)
|
||||
throw layout_syntax_error("repeat must have positive integer count attribute");
|
||||
environment local(env);
|
||||
for (int i = 0; count > i; ++i)
|
||||
{
|
||||
add_elements(dirname, local, *childnode, groupmap, true, !i);
|
||||
local.increment_parameters();
|
||||
}
|
||||
}
|
||||
else if (repeat || (strcmp(childnode->get_name(), "view") && strcmp(childnode->get_name(), "script")))
|
||||
{
|
||||
throw layout_syntax_error(util::string_format("unknown layout item %s", childnode->get_name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,18 +41,12 @@ Intel INTELLEC® 4/MOD 40 layout
|
||||
</rect>
|
||||
</element>
|
||||
|
||||
<element name="label_0"><text string="0"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_1"><text string="1"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_2"><text string="2"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_3"><text string="3"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_4"><text string="4"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_5"><text string="5"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_6"><text string="6"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_7"><text string="7"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_8"><text string="8"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_9"><text string="9"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_10"><text string="10"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_11"><text string="11"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<repeat count="12">
|
||||
<param name="labelnum" start="0" increment="1" />
|
||||
<element name="label_~labelnum~">
|
||||
<text string="~labelnum~"><color red="1.0" green="1.0" blue="1.0" /></text>
|
||||
</element>
|
||||
</repeat>
|
||||
|
||||
<element name="label_a1"><text string="A1"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_a2"><text string="A2"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
|
@ -41,18 +41,12 @@ Intel INTELLEC® 4/MOD 40 layout
|
||||
</rect>
|
||||
</element>
|
||||
|
||||
<element name="label_0"><text string="0"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_1"><text string="1"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_2"><text string="2"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_3"><text string="3"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_4"><text string="4"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_5"><text string="5"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_6"><text string="6"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_7"><text string="7"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_8"><text string="8"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_9"><text string="9"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_10"><text string="10"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_11"><text string="11"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<repeat count="12">
|
||||
<param name="labelnum" start="0" increment="1" />
|
||||
<element name="label_~labelnum~">
|
||||
<text string="~labelnum~"><color red="1.0" green="1.0" blue="1.0" /></text>
|
||||
</element>
|
||||
</repeat>
|
||||
|
||||
<element name="label_a1"><text string="A1"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
<element name="label_a2"><text string="A2"><color red="1.0" green="1.0" blue="1.0" /></text></element>
|
||||
|
Loading…
Reference in New Issue
Block a user