File: convert_hardwareconfig2.py

package info (click to toggle)
openmsx 0.5.1-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 6,976 kB
  • ctags: 10,295
  • sloc: cpp: 63,525; xml: 37,105; sh: 1,403; python: 681; tcl: 207; makefile: 64
file content (161 lines) | stat: -rwxr-xr-x 4,629 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/usr/bin/env python
# $Id: convert_hardwareconfig2.py,v 1.1 2004/10/23 23:22:21 mthuurne Exp $
#
# Script for updating openMSX 0.5.0 configurations (hardwareconfig.xml)
# to the new format used by CVS HEAD. Even though CVS HEAD is compatible
# with the 0.5.0 format (msxconfig2), the new format is preferred.
# If you run this script and see "NOTE:" in the output, please verify the
# created XML files manually.

import os, os.path, sys
from StringIO import StringIO
from xml.dom.minidom import parse

def convertDoc(dom, checksums):
	assert dom.nodeType == dom.DOCUMENT_NODE
	if dom.doctype.systemId == 'msxconfig.dtd':
		print '  old unsupported format, skipping'
		return
	elif dom.doctype.systemId != 'msxconfig2.dtd':
		print '  NOTE: unknown format, skipping'
		return

	sawCVSid = False
	for child in dom.childNodes:
		if child.nodeType == dom.COMMENT_NODE:
			if child.nodeValue.startswith(' $Id') \
			and child.nodeValue.endswith('$ '):
				sawCVSid = True
		elif child.nodeType == dom.DOCUMENT_TYPE_NODE:
			if child.nodeName != 'msxconfig':
				print '  NOTE: unknown document type "%s", skipping' % \
					child.nodeName
				return
		elif child.nodeType == dom.ELEMENT_NODE:
			if child.nodeName == 'msxconfig':
				convertRoot(child, checksums)
			else:
				print '  NOTE: wrong root node "%s", skipping' % child.nodeName
				return
	if not sawCVSid:
		print '  NOTE: no CVS id'

def convertRoot(node, checksums):
	def removeSlowDrainOnReset(memNode):
		for child in memNode.childNodes:
			if child.nodeType == node.ELEMENT_NODE \
			and child.nodeName == 'slow_drain_on_reset':
				print '  remove slow_drain_on_reset'
				memNode.removeChild(child)
				child.unlink()
				return
	for child in node.getElementsByTagName('RAM') \
			+ node.getElementsByTagName('MemoryMapper') \
			+ node.getElementsByTagName('PanasonicRAM'):
		removeSlowDrainOnReset(child)

def stripSpaces(node):
	if node.nodeType == node.TEXT_NODE:
		if node.nodeValue.isspace():
			node.parentNode.removeChild(node)
			node.unlink()
	else:
		for child in list(node.childNodes):
			stripSpaces(child)

def layoutDocument(dom):
	for child in dom.childNodes:
		if child.nodeType == dom.ELEMENT_NODE:
			layoutNode(child)

def layoutNode(node, indent = '', lineSpacing = 2):
	hasElements = False
	for child in list(node.childNodes):
		if child.nodeType == node.ELEMENT_NODE:
			if child.tagName == 'secondary': lineSpacing = 2
			hasElements = True
			node.insertBefore(
				child.ownerDocument.createTextNode(
					'\n' * lineSpacing + '  ' + indent
					),
				child
				)
			layoutNode(
				child,
				indent + '  ',
				1 + int(child.tagName in ['devices'])
				)
		elif child.nodeType == node.COMMENT_NODE:
			node.insertBefore(
				child.ownerDocument.createTextNode(
					'\n' * lineSpacing + '  ' + indent
					),
				child
				)
	if hasElements:
		node.appendChild(node.ownerDocument.createTextNode(
			'\n' * lineSpacing + indent
			))

if len(sys.argv) != 3:
	print 'Usage: convert_hardwareconfig.py <indir> <outdir>'
	sys.exit(2)
indir = sys.argv[1]
outdir = sys.argv[2]
if outdir[-1] != '/': outdir += '/'

for root, dirs, files in os.walk(indir):
	if 'hardwareconfig.xml' in files:
		print 'Converting ' + root.split('/')[-1] + '...'
		assert root.startswith(indir)
		outpath = outdir + root[len(indir) : ]
		
		checksums = {}
		if os.path.isdir(root + '/roms') \
		and os.path.isfile(root + '/roms/SHA1SUMS'):
			for line in open(root + '/roms/SHA1SUMS'):
				checksum, empty, fileName = line[ : -1].split(' ')
				assert empty == ''
				checksums[fileName] = checksum
		
		dom = parse(root + '/hardwareconfig.xml')
		dom.normalize()
		stripSpaces(dom)
		convertDoc(dom, checksums)
		layoutDocument(dom)
		if not os.path.isdir(outpath):
			os.makedirs(outpath)
		out = StringIO()
		dom.writexml(out)
		out.seek(0)
		outFile = open(outpath + '/hardwareconfig.xml', 'w')
		
		# Minidom doesn't seem to allow text nodes at document level,
		# so do some postprocessing using string manipulation.
		afterDoctype = False
		for line in out.readlines():
			if line.startswith('<!--'):
				index = 0
				while True:
					start = index
					index = line.find('-->', start)
					if index == -1:
						line = line[start : ]
						break
					index += 3
					outFile.write(line[start : index] + '\n')
			if line.startswith('<!DOCTYPE'):
				outFile.write(line[ : -1])
				afterDoctype = True
			elif afterDoctype:
				index = 0
				while line[index].isspace(): index += 1
				outFile.write(' ' + line[index : ])
				afterDoctype = False
			else:
				outFile.write(line)
		outFile.write('\n')
		
		outFile.close()
		out.close()
		dom.unlink()