1# udis86 - scripts/ud_optable.py (optable.xml parser)
2#
3# Copyright (c) 2009 Vivek Thampi
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without modification,
7# are permitted provided that the following conditions are met:
8#
9#     * Redistributions of source code must retain the above copyright notice,
10#       this list of conditions and the following disclaimer.
11#     * Redistributions in binary form must reproduce the above copyright notice,
12#       this list of conditions and the following disclaimer in the documentation
13#       and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
22# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26import os
27import sys
28from xml.dom import minidom
29
30class UdOptableXmlParser:
31
32    def parseDef( self, node ):
33        ven = ''
34        pfx = []
35        opc = []
36        opr = []
37        for def_node in node.childNodes:
38            if not def_node.localName:
39                continue
40            if def_node.localName == 'pfx':
41                pfx = def_node.firstChild.data.split();
42            elif def_node.localName == 'opc':
43                opc = def_node.firstChild.data.split();
44            elif def_node.localName == 'opr':
45                opr = def_node.firstChild.data.split();
46            elif def_node.localName == 'mode':
47                pfx.extend( def_node.firstChild.data.split() );
48            elif def_node.localName == 'syn':
49                pfx.extend( def_node.firstChild.data.split() );
50            elif def_node.localName == 'vendor':
51                ven = ( def_node.firstChild.data );
52            else:
53                print "warning: invalid node - %s" % def_node.localName
54                continue
55        return ( pfx, opc, opr, ven )
56
57    def parse( self, xml, fn ):
58        xmlDoc = minidom.parse( xml )
59        self.TlNode = xmlDoc.firstChild
60
61        while self.TlNode and self.TlNode.localName != "x86optable":
62            self.TlNode = self.TlNode.nextSibling
63
64        for insnNode in self.TlNode.childNodes:
65            if not insnNode.localName:
66                continue
67            if insnNode.localName != "instruction":
68                print "warning: invalid insn node - %s" % insnNode.localName
69                continue
70
71            mnemonic = insnNode.getElementsByTagName( 'mnemonic' )[ 0 ].firstChild.data
72            vendor   = ''
73
74            for node in insnNode.childNodes:
75                if node.localName == 'vendor':
76                    vendor = node.firstChild.data
77                elif node.localName == 'def':
78                    ( prefixes, opcodes, operands, local_vendor ) = \
79                        self.parseDef( node )
80                    if ( len( local_vendor ) ):
81                        vendor = local_vendor
82                    # callback
83                    fn( prefixes, mnemonic, opcodes, operands, vendor )
84
85
86def printFn( pfx, mnm, opc, opr, ven ):
87    print 'def: ',
88    if len( pfx ):
89        print ' '.join( pfx ),
90    print "%s %s %s %s" % \
91            ( mnm, ' '.join( opc ), ' '.join( opr ), ven )
92
93
94def parse( xml, callback ):
95    parser = UdOptableXmlParser()
96    parser.parse( xml, callback )
97
98def main():
99    parser = UdOptableXmlParser()
100    parser.parse( sys.argv[ 1 ], printFn )
101
102if __name__ == "__main__":
103    main()
104