summaryrefslogtreecommitdiffstats
path: root/docs/release/scripts/build/complay.py
diff options
context:
space:
mode:
author Robbbert <Robbbert@users.noreply.github.com>2020-09-30 11:17:54 +1000
committer Robbbert <Robbbert@users.noreply.github.com>2020-09-30 11:17:54 +1000
commitf185ed096c1555adc108fb679b3e0a60671e0d3c (patch)
tree4f718686e8fc83881d6950c062d0e1f274e3e8b0 /docs/release/scripts/build/complay.py
parenteb71a8564c36fd14098bb24d7acb76b2d6e0c7dc (diff)
0.225 Release filestag225
Diffstat (limited to 'docs/release/scripts/build/complay.py')
-rw-r--r--docs/release/scripts/build/complay.py154
1 files changed, 109 insertions, 45 deletions
diff --git a/docs/release/scripts/build/complay.py b/docs/release/scripts/build/complay.py
index ce760185015..34a43992b7c 100644
--- a/docs/release/scripts/build/complay.py
+++ b/docs/release/scripts/build/complay.py
@@ -97,7 +97,6 @@ class LayoutChecker(Minifyer):
VARPATTERN = re.compile('^.*~[0-9A-Za-z_]+~.*$')
FLOATCHARS = re.compile('^.*[.eE].*$')
SHAPES = frozenset(('disk', 'dotmatrix', 'dotmatrix5dot', 'dotmatrixdot', 'led14seg', 'led14segsc', 'led16seg', 'led16segsc', 'led7seg', 'led8seg_gts1', 'rect'))
- OBJECTS = frozenset(('backdrop', 'bezel', 'cpanel', 'marquee', 'overlay'))
ORIENTATIONS = frozenset((0, 90, 180, 270))
YESNO = frozenset(('yes', 'no'))
BLENDMODES = frozenset(('none', 'alpha', 'multiply', 'add'))
@@ -111,6 +110,8 @@ class LayoutChecker(Minifyer):
self.views = { }
self.referenced_elements = { }
self.referenced_groups = { }
+ self.group_collections = { }
+ self.current_collections = None
def formatLocation(self):
return '%s:%d:%d' % (self.locator.getSystemId(), self.locator.getLineNumber(), self.locator.getColumnNumber())
@@ -218,10 +219,6 @@ class LayoutChecker(Minifyer):
self.variable_scopes[-1][attrs['name']] = False
def checkBounds(self, attrs):
- if self.have_bounds[-1]:
- self.handleError('Duplicate element bounds')
- else:
- self.have_bounds[-1] = True
left = self.checkFloatAttribute('bounds', attrs, 'left', 0.0)
top = self.checkFloatAttribute('bounds', attrs, 'top', 0.0)
right = self.checkFloatAttribute('bounds', attrs, 'right', 1.0)
@@ -257,9 +254,15 @@ class LayoutChecker(Minifyer):
if self.checkIntAttribute('orientation', attrs, 'rotate', 0) not in self.ORIENTATIONS:
self.handleError('Element orientation attribute rotate "%s" is unsupported' % (attrs['rotate'], ))
for name in ('swapxy', 'flipx', 'flipy'):
- if attrs.get(name, 'no') not in self.YESNO:
+ if (attrs.get(name, 'no') not in self.YESNO) and (not self.VARPATTERN.match(attrs['yesno'])):
self.handleError('Element orientation attribute %s "%s" is not "yes" or "no"' % (name, attrs[name]))
+ def checkColor(self, attrs):
+ self.checkColorChannel(attrs, 'red')
+ self.checkColorChannel(attrs, 'green')
+ self.checkColorChannel(attrs, 'blue')
+ self.checkColorChannel(attrs, 'alpha')
+
def checkColorChannel(self, attrs, name):
channel = self.checkFloatAttribute('color', attrs, name, None)
if (channel is not None) and ((0.0 > channel) or (1.0 < channel)):
@@ -267,7 +270,7 @@ class LayoutChecker(Minifyer):
def checkTag(self, tag, element, attr):
if '' == tag:
- self.handleError('Element %s attribute %s is empty', (element, attr))
+ self.handleError('Element %s attribute %s is empty' % (element, attr))
else:
if tag.find('^') >= 0:
self.handleError('Element %s attribute %s "%s" contains parent device reference' % (element, attr, tag))
@@ -277,12 +280,22 @@ class LayoutChecker(Minifyer):
self.handleError('Element %s attribute %s "%s" contains double separator' % (element, attr, tag))
def checkComponent(self, name, attrs):
- state = self.checkIntAttribute(name, attrs, 'state', None)
- if (state is not None) and (0 > state):
- self.handleError('Element %s attribute state "%s" is negative' % (name, attrs['state']))
+ statemask = self.checkIntAttribute(name, attrs, 'statemask', None)
+ stateval = self.checkIntAttribute(name, attrs, 'state', None)
+ if stateval is not None:
+ if 0 > stateval:
+ self.handleError('Element %s attribute state "%s" is negative' % (name, attrs['state']))
+ if (statemask is not None) and (stateval & ~statemask):
+ self.handleError('Element %s attribute state "%s" has bits set that are clear in attribute statemask "%s"' % (name, attrs['state'], attrs['statemask']))
self.handlers.append((self.componentStartHandler, self.componentEndHandler))
- self.have_bounds.append(False)
- self.have_color.append(False)
+ self.have_bounds.append({ })
+ self.have_color.append({ })
+
+ def startObject(self):
+ self.handlers.append((self.objectStartHandler, self.objectEndHandler))
+ self.have_bounds.append(None)
+ self.have_orientation.append(False)
+ self.have_color.append(None)
def rootStartHandler(self, name, attrs):
if 'mamelayout' != name:
@@ -320,6 +333,7 @@ class LayoutChecker(Minifyer):
self.handleError('Element element attribute defstate "%s" is negative' % (attrs['defstate'], ))
self.handlers.append((self.elementStartHandler, self.elementEndHandler))
elif 'group' == name:
+ self.current_collections = { }
if 'name' not in attrs:
self.handleError('Element group missing attribute name')
else:
@@ -328,13 +342,16 @@ class LayoutChecker(Minifyer):
self.generated_group_names = True
if attrs['name'] not in self.groups:
self.groups[attrs['name']] = self.formatLocation()
+ if not generated_name:
+ self.group_collections[attrs['name']] = self.current_collections
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({ })
self.repeat_depth.append(0)
- self.have_bounds.append(False)
+ self.have_bounds.append(None)
elif ('view' == name) and (not self.repeat_depth[-1]):
+ self.current_collections = { }
if 'name' not in attrs:
self.handleError('Element view missing attribute name')
else:
@@ -345,7 +362,7 @@ class LayoutChecker(Minifyer):
self.handlers.append((self.groupViewStartHandler, self.groupViewEndHandler))
self.variable_scopes.append({ })
self.repeat_depth.append(0)
- self.have_bounds.append(False)
+ self.have_bounds.append(None)
elif 'repeat' == name:
if 'count' not in attrs:
self.handleError('Element repeat missing attribute count')
@@ -428,16 +445,25 @@ class LayoutChecker(Minifyer):
def componentStartHandler(self, name, attrs):
if 'bounds' == name:
+ state = self.checkIntAttribute(name, attrs, 'state', 0)
+ if state is not None:
+ if 0 > state:
+ self.handleError('Element bounds attribute state "%s" is negative' % (attrs['state'], ))
+ if state in self.have_bounds[-1]:
+ self.handleError('Duplicate bounds for state %d (previous %s)' % (state, self.have_bounds[-1][state]))
+ else:
+ self.have_bounds[-1][state] = self.formatLocation()
self.checkBounds(attrs)
elif 'color' == name:
- if self.have_color[-1]:
- self.handleError('Duplicate color element')
- else:
- self.have_color[-1] = True
- self.checkColorChannel(attrs, 'red')
- self.checkColorChannel(attrs, 'green')
- self.checkColorChannel(attrs, 'blue')
- self.checkColorChannel(attrs, 'alpha')
+ state = self.checkIntAttribute(name, attrs, 'state', 0)
+ if state is not None:
+ if 0 > state:
+ self.handleError('Element color attribute state "%s" is negative' % (attrs['state'], ))
+ if state in self.have_color[-1]:
+ self.handleError('Duplicate color for state %d (previous %s)' % (state, self.have_color[-1][state]))
+ else:
+ self.have_color[-1][state] = self.formatLocation()
+ self.checkColor(attrs)
self.ignored_depth = 1
def componentEndHandler(self, name):
@@ -446,12 +472,11 @@ class LayoutChecker(Minifyer):
self.handlers.pop()
def groupViewStartHandler(self, name, attrs):
- if (name in self.OBJECTS) or ('element' == name):
- refattr = 'ref' if 'element' == name else 'element'
- if refattr not in attrs:
- self.handleError('Element %s missing attribute %s' % (name, refattr))
- elif attrs[refattr] not in self.referenced_elements:
- self.referenced_elements[attrs[refattr]] = self.formatLocation()
+ if 'element' == name:
+ if 'ref' not in attrs:
+ self.handleError('Element %s missing attribute ref' % (name, ))
+ elif attrs['ref'] not in self.referenced_elements:
+ self.referenced_elements[attrs['ref']] = self.formatLocation()
if ('blend' in attrs) and (attrs['blend'] not in self.BLENDMODES) and not self.VARPATTERN.match(attrs['blend']):
self.handleError('Element %s attribute blend "%s" is unsupported' % (name, attrs['blend']))
if 'inputtag' in attrs:
@@ -460,21 +485,21 @@ class LayoutChecker(Minifyer):
self.checkTag(attrs['inputtag'], name, 'inputtag')
elif 'inputmask' in attrs:
self.handleError('Element %s has inputmask attribute without inputtag attribute' % (name, ))
- inputraw = self.checkIntAttribute(name, attrs, 'inputraw', None)
- if (inputraw is not None):
+ inputraw = None
+ if 'inputraw' in attrs:
+ if (attrs['inputraw'] not in self.YESNO) and (not self.VARPATTERN.match(attrs['inputraw'])):
+ self.handleError('Element %s attribute inputraw "%s" is not "yes" or "no"' % (name, attrs['inputraw']))
+ else:
+ inputraw = 'yes' == attrs['inputraw']
if 'inputmask' not in attrs:
self.handleError('Element %s has inputraw attribute without inputmask attribute' % (name, ))
if 'inputtag' not in attrs:
self.handleError('Element %s has inputraw attribute without inputtag attribute' % (name, ))
- if ((0 > inputraw) or (1 < inputraw)):
- self.handleError('Element %s attribute inputraw "%s" not in valid range 0-1' % (name, attrs['inputraw']))
inputmask = self.checkIntAttribute(name, attrs, 'inputmask', None)
if (inputmask is not None) and (0 == inputmask):
if (inputraw is None) or (0 == inputraw):
- self.handleError('Element %s has attribute inputmask "%s" is zero' % (name, attrs['inputmask']))
- self.handlers.append((self.objectStartHandler, self.objectEndHandler))
- self.have_bounds.append(False)
- self.have_orientation.append(False)
+ self.handleError('Element %s attribute inputmask "%s" is zero' % (name, attrs['inputmask']))
+ self.startObject();
elif 'screen' == name:
if 'index' in attrs:
index = self.checkIntAttribute(name, attrs, 'index', None)
@@ -487,17 +512,20 @@ class LayoutChecker(Minifyer):
self.checkTag(tag, name, 'tag')
if self.BADTAGPATTERN.search(tag):
self.handleError('Element screen attribute tag "%s" contains invalid characters' % (tag, ))
- self.handlers.append((self.objectStartHandler, self.objectEndHandler))
- self.have_bounds.append(False)
- self.have_orientation.append(False)
+ self.startObject();
elif 'group' == name:
if 'ref' not in attrs:
self.handleError('Element group missing attribute ref')
- elif attrs['ref'] not in self.referenced_groups:
- self.referenced_groups[attrs['ref']] = self.formatLocation()
- self.handlers.append((self.objectStartHandler, self.objectEndHandler))
- self.have_bounds.append(False)
- self.have_orientation.append(False)
+ else:
+ if attrs['ref'] not in self.referenced_groups:
+ self.referenced_groups[attrs['ref']] = self.formatLocation()
+ if (not self.VARPATTERN.match(attrs['ref'])) and (attrs['ref'] in self.group_collections):
+ for n, l in self.group_collections[attrs['ref']].items():
+ if n not in self.current_collections:
+ self.current_collections[n] = l
+ else:
+ self.handleError('Element group instantiates collection with duplicate name "%s" from %s (previous %s)' % (n, l, self.current_collections[n]))
+ self.startObject();
elif 'repeat' == name:
if 'count' not in attrs:
self.handleError('Element repeat missing attribute count')
@@ -507,13 +535,31 @@ class LayoutChecker(Minifyer):
self.handleError('Element repeat attribute count "%s" is negative' % (attrs['count'], ))
self.variable_scopes.append({ })
self.repeat_depth[-1] += 1
+ elif 'collection' == name:
+ if 'name' not in attrs:
+ self.handleError('Element collection missing attribute name')
+ elif not self.VARPATTERN.match(attrs['name']):
+ if attrs['name'] not in self.current_collections:
+ self.current_collections[attrs['name']] = self.formatLocation()
+ else:
+ self.handleError('Element collection has duplicate name (previous %s)' % (self.current_collections[attrs['name']], ))
+ if attrs.get('visible', 'yes') not in self.YESNO:
+ self.handleError('Element collection attribute visible "%s" is not "yes" or "no"' % (attrs['visible'], ))
+ self.variable_scopes.append({ })
+ self.collection_depth += 1
elif 'param' == name:
self.checkParameter(attrs)
self.ignored_depth = 1
elif 'bounds' == name:
+ if self.have_bounds[-1] is not None:
+ self.handleError('Duplicate element bounds (previous %s)' % (self.have_bounds[-1], ))
+ else:
+ self.have_bounds[-1] = self.formatLocation()
self.checkBounds(attrs)
if self.repeat_depth[-1]:
self.handleError('Element bounds inside repeat')
+ elif self.collection_depth:
+ self.handleError('Element bounds inside collection')
self.ignored_depth = 1
else:
self.handleError('Encountered unexpected element %s' % (name, ))
@@ -521,23 +567,37 @@ class LayoutChecker(Minifyer):
def groupViewEndHandler(self, name):
self.variable_scopes.pop()
- if self.repeat_depth[-1]:
+ if 'collection' == name:
+ self.collection_depth -= 1
+ elif self.repeat_depth[-1]:
self.repeat_depth[-1] -= 1
else:
+ self.current_collections = None
self.repeat_depth.pop()
self.have_bounds.pop()
self.handlers.pop()
def objectStartHandler(self, name, attrs):
if 'bounds' == name:
+ if self.have_bounds[-1] is not None:
+ self.handleError('Duplicate element bounds (previous %s)' % (self.have_bounds[-1], ))
+ else:
+ self.have_bounds[-1] = self.formatLocation()
self.checkBounds(attrs)
elif 'orientation' == name:
self.checkOrientation(attrs)
+ if 'color' == name:
+ if self.have_color[-1] is not None:
+ self.handleError('Duplicate element color (previous %s)' % (self.have_color[-1], ))
+ else:
+ self.have_color[-1] = self.formatLocation()
+ self.checkColor(attrs)
self.ignored_depth = 1
def objectEndHandler(self, name):
self.have_bounds.pop()
self.have_orientation.pop()
+ self.have_color.pop()
self.handlers.pop()
def setDocumentLocator(self, locator):
@@ -549,6 +609,7 @@ class LayoutChecker(Minifyer):
self.ignored_depth = 0
self.variable_scopes = [ ]
self.repeat_depth = [ ]
+ self.collection_depth = 0
self.have_bounds = [ ]
self.have_orientation = [ ]
self.have_color = [ ]
@@ -563,10 +624,13 @@ class LayoutChecker(Minifyer):
self.views.clear()
self.referenced_elements.clear()
self.referenced_groups.clear()
+ self.group_collections.clear()
+ self.current_collections = None
del self.handlers
del self.ignored_depth
del self.variable_scopes
del self.repeat_depth
+ del self.collection_depth
del self.have_bounds
del self.have_orientation
del self.have_color