mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
Added CI job to check for likely mame.lst errors.
This commit is contained in:
parent
4a5196149b
commit
6176c84768
2 changed files with 143 additions and 0 deletions
2
.github/workflows/ci-linux.yml
vendored
2
.github/workflows/ci-linux.yml
vendored
|
@ -55,6 +55,8 @@ jobs:
|
||||||
run: make -j2
|
run: make -j2
|
||||||
- name: Validate
|
- name: Validate
|
||||||
run: ./mame -validate
|
run: ./mame -validate
|
||||||
|
- name: Reconcile driver list
|
||||||
|
run: ./mame -listxml | python scripts/build/makedep.py reconcilelist -l src/mame/mame.lst -
|
||||||
- name: ORM check
|
- name: ORM check
|
||||||
run: python scripts/minimaws/minimaws.py load --executable ./mame --softwarepath hash
|
run: python scripts/minimaws/minimaws.py load --executable ./mame --softwarepath hash
|
||||||
- uses: actions/upload-artifact@master
|
- uses: actions/upload-artifact@master
|
||||||
|
|
|
@ -8,6 +8,7 @@ import glob
|
||||||
import io
|
import io
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
|
import xml.sax
|
||||||
|
|
||||||
|
|
||||||
class ParserBase:
|
class ParserBase:
|
||||||
|
@ -581,6 +582,128 @@ class DriverCollector(DriverFilter):
|
||||||
self.sources = sorted(sources)
|
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):
|
def split_path(path):
|
||||||
path = os.path.normpath(path)
|
path = os.path.normpath(path)
|
||||||
result = [ ]
|
result = [ ]
|
||||||
|
@ -619,6 +742,10 @@ def parse_command_line():
|
||||||
subparser.add_argument('-f', '--filter', metavar='<fltfile>', help='input filter file')
|
subparser.add_argument('-f', '--filter', metavar='<fltfile>', help='input filter file')
|
||||||
subparser.add_argument('list', metavar='<lstfile>', help='input list 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()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
@ -905,3 +1032,17 @@ if __name__ == '__main__':
|
||||||
write_filter(options, sys.stdout)
|
write_filter(options, sys.stdout)
|
||||||
elif options.command == 'driverlist':
|
elif options.command == 'driverlist':
|
||||||
DriverLister(options).write_source(sys.stdout)
|
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)
|
||||||
|
|
Loading…
Reference in a new issue