summaryrefslogtreecommitdiffstatshomepage
path: root/scripts/build/makedep.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/build/makedep.py')
-rwxr-xr-xscripts/build/makedep.py141
1 files changed, 141 insertions, 0 deletions
diff --git a/scripts/build/makedep.py b/scripts/build/makedep.py
index 07406423ff2..13d0691c3af 100755
--- a/scripts/build/makedep.py
+++ b/scripts/build/makedep.py
@@ -8,6 +8,7 @@ import glob
import io
import os.path
import sys
+import xml.sax
class ParserBase:
@@ -581,6 +582,128 @@ class DriverCollector(DriverFilter):
self.sources = sorted(sources)
+class DriverReconciler(DriverFilter):
+ class InfoHandler:
+ def __init__(self, drivers, **kwargs):
+ super().__init__(**kwargs)
+ self.drivers = drivers
+ self.bad = False
+ self.locator = None
+ self.ignored_depth = 0
+ self.in_document = False
+ self.in_mame = False
+
+ def startElement(self, name, attrs):
+ if not self.in_document:
+ raise xml.sax.SAXParseException('Unexpected start of element "%s"' % (name, ), None, self.locator)
+ elif self.ignored_depth > 0:
+ self.ignored_depth += 1
+ elif not self.in_mame:
+ if name != 'mame':
+ raise xml.sax.SAXParseException('Unexpected start of element "%s"' % (name, ), None, self.locator)
+ self.in_mame = True
+ elif name != 'machine':
+ raise xml.sax.SAXParseException('Unexpected start of element "%s"' % (name, ), None, self.locator)
+ else:
+ runnable = attrs.get('runnable', 'yes')
+ if runnable == 'yes':
+ shortname = attrs['name']
+ source = attrs['sourcefile'].replace('\\', '/')
+ declared = self.drivers.get(shortname)
+ if declared is None:
+ sys.stderr.write('Driver "%s" not declared in list file\n' % (shortname, ))
+ self.bad = True
+ elif declared != source:
+ sys.stderr.write('Driver "%s" found for source file "%s" but defined in source file "%s"\n' % (shortname, declared, source))
+ self.bad = True
+ self.ignored_depth = 1
+
+ def endElement(self, name):
+ if self.ignored_depth > 0:
+ self.ignored_depth -= 1
+ elif self.in_mame:
+ if name != 'mame':
+ raise xml.sax.SAXParseException('Unexpected end of element "%s"' % (name, ), None, self.locator)
+ self.in_mame = False
+ else:
+ raise xml.sax.SAXParseException('Unexpected end of element "%s"' % (name, ), None, self.locator)
+
+ def startDocument(self):
+ if self.in_document:
+ raise xml.sax.SAXParseException('Unexpected start of document', None, self.locator)
+ self.in_document = True
+
+ def endDocument(self):
+ if not self.in_document:
+ raise xml.sax.SAXParseException('Unexpected end of document', None, self.locator)
+ self.in_document = False
+
+ def setDocumentLocator(self, locator):
+ self.locator = locator
+
+ def startPrefixMapping(self, prefix, uri):
+ pass
+
+ def endPrefixMapping(self, prefix):
+ pass
+
+ def characters(self, content):
+ pass
+
+ def ignorableWhitespace(self, whitespace):
+ pass
+
+ def processingInstruction(self, target, data):
+ pass
+
+
+ def __init__(self, options, **kwargs):
+ super().__init__(**kwargs)
+
+ def sourcefile(filename):
+ if (state['prevsource'] is not None) and (not state['prevdrivers']):
+ sys.stderr.write('No drivers for source file "%s"\n' % (state['prevsource'], ))
+ self.bad = True
+ if filename in self.sources:
+ sys.stderr.write('Duplicate source file "%s"\n' % (filename, ))
+ state['prevdrivers'] = self.sources[filename]
+ self.bad = True
+ else:
+ drivers = set()
+ state['prevdrivers'] = drivers
+ self.sources[filename] = drivers
+ state['prevsource'] = filename
+
+ def driver(shortname):
+ if shortname in self.drivers:
+ sys.stderr.write('Duplicate driver "%s" for source file "%s" (previously seen for source file "%s")\n' % (shortname, state['prevsource'], self.drivers[shortname]))
+ self.bad = True
+ else:
+ self.drivers[shortname] = state['prevsource']
+ drivers = state['prevdrivers']
+ if drivers is None:
+ sys.stderr.write('Driver "%s" found outside source file section\n' % (shortname, ))
+ self.bad = True
+ else:
+ drivers.add(shortname)
+
+ state = { 'prevsource': None, 'prevdrivers': None }
+ self.bad = False
+ self.sources = { }
+ self.drivers = { }
+ self.parse_list(options.list, sourcefile, driver)
+
+ def reconcile_xml(self, xmlfile):
+ handler = self.InfoHandler(self.drivers)
+ try:
+ xml.sax.parse(xmlfile, handler=handler)
+ if handler.bad:
+ self.bad = True
+ except xml.sax.SAXException as err:
+ sys.stderr.write('Error parsing system information file: %s\n' % (err, ))
+ self.bad = True
+
+
def split_path(path):
path = os.path.normpath(path)
result = [ ]
@@ -619,6 +742,10 @@ def parse_command_line():
subparser.add_argument('-f', '--filter', metavar='<fltfile>', help='input filter file')
subparser.add_argument('list', metavar='<lstfile>', help='input list file')
+ subparser = subparsers.add_parser('reconcilelist', help='reconcile driver list')
+ subparser.add_argument('-l', '--list', metavar='<lstfile>', required=True, help='master driver list file')
+ subparser.add_argument('infoxml', metavar='<xmlfile>', nargs='?', help='XML system information file')
+
return parser.parse_args()
@@ -905,3 +1032,17 @@ if __name__ == '__main__':
write_filter(options, sys.stdout)
elif options.command == 'driverlist':
DriverLister(options).write_source(sys.stdout)
+ elif options.command == 'reconcilelist':
+ reconciler = DriverReconciler(options)
+ if options.infoxml == '-':
+ reconciler.reconcile_xml(sys.stdin)
+ elif options.infoxml is not None:
+ try:
+ xmlfile = io.open(options.infoxml, 'rb')
+ with xmlfile:
+ reconciler.reconcile_xml(xmlfile)
+ except IOError:
+ sys.stderr.write('Unable to open system information file "%s"\n' % (options.infoxml, ))
+ sys.exit(1)
+ if reconciler.bad:
+ sys.exit(1)