state.py revision 986c8b3d
1'''
2This module contains the namespace class and the singleton module class.
3'''
4from os.path import dirname, basename
5from xml.etree.cElementTree import parse
6
7from xcbgen import matcher
8from xcbgen.error import *
9from xcbgen.xtypes import *
10
11import __main__
12
13class Namespace(object):
14    '''
15    Contains the naming information for an extension.
16
17    Public fields:
18
19    header is the header attribute ("header file" name).
20    is_ext is true for extensions, false for xproto.
21    major_version and minor_version are extension version info.
22    ext_xname is the X extension name string.
23    ext_name is the XCB extension name prefix.
24    '''
25    def __init__(self, filename):
26        # Path info
27        self.path = filename
28        self.dir = dirname(filename)
29        self.file = basename(filename)
30
31        # Parse XML
32        self.root = parse(filename).getroot()
33        self.header = self.root.get('header')
34        self.ns = self.header + ':'
35
36        # Get root element attributes
37        if self.root.get('extension-xname', False):
38            self.is_ext = True
39            self.major_version = self.root.get('major-version')
40            self.minor_version = self.root.get('minor-version')
41            self.ext_xname = self.root.get('extension-xname')
42            self.ext_name = self.root.get('extension-name')
43            self.prefix = ('xcb', self.ext_name)
44        else:
45            self.is_ext = False
46            self.ext_name = ''
47            self.prefix = ('xcb',)
48
49
50class Module(object):
51    '''
52    This is the grand, encompassing class that represents an entire XCB specification.
53    Only gets instantiated once, in the main() routine.
54
55    Don't need to worry about this much except to declare it and to get the namespace.
56
57    Public fields:
58    namespace contains the namespace info for the spec.
59    '''
60    open = __main__.output['open']
61    close = __main__.output['close']
62
63    def __init__(self, filename, output):
64        self.namespace = Namespace(filename)
65        self.output = output
66
67        self.imports = []
68        self.types = {}
69        self.events = {}
70        self.errors = {}
71        self.all = []
72
73        # Register some common types
74        self.add_type('CARD8', '', ('uint8_t',), tcard8)
75        self.add_type('CARD16', '', ('uint16_t',), tcard16)
76        self.add_type('CARD32', '', ('uint32_t',), tcard32)
77        self.add_type('INT8', '', ('int8_t',), tint8)
78        self.add_type('INT16', '', ('int16_t',), tint16)
79        self.add_type('INT32', '', ('int32_t',), tint32)
80        self.add_type('BYTE', '', ('uint8_t',), tcard8)
81        self.add_type('BOOL', '', ('uint8_t',), tcard8)
82        self.add_type('char', '', ('char',), tchar)
83        self.add_type('float', '', ('float',), tfloat)
84        self.add_type('double', '', ('double',), tdouble)
85        self.add_type('void', '', ('void',), tcard8)
86
87    # This goes out and parses the rest of the XML
88    def register(self):
89        matcher.execute(self, self.namespace)
90
91    # Recursively resolve all types
92    def resolve(self):
93        for (name, item) in self.all:
94            item.resolve(self)
95
96    # Call all the output methods
97    def generate(self):
98        self.open()
99
100        for (name, item) in self.all:
101            item.out(name)
102
103        self.close()
104
105    # Keeps track of what's been imported so far.
106    def add_import(self, name, namespace):
107        self.imports.append((name, namespace.header))
108
109    def has_import(self, name):
110        for (name_, header) in self.imports:
111            if name_ == name:
112                return True
113        return False
114
115    # Keeps track of non-request/event/error datatypes
116    def add_type(self, id, ns, name, item):
117        key = ns + id
118        if key in self.types:
119            return
120        self.types[key] = (name, item)
121        if name[:-1] == self.namespace.prefix:
122            self.all.append((name, item))
123
124    def get_type_impl(self, id, idx):
125        key = id
126        if key in self.types:
127            return self.types[key][idx]
128
129        key = self.namespace.ns + id
130        if key in self.types:
131            return self.types[key][idx]
132
133        for key in self.types.keys():
134            if key.rpartition(':')[2] == id:
135                return self.types[key][idx]
136
137        raise ResolveException('Type %s not found' % id)
138
139    def get_type(self, id):
140        return self.get_type_impl(id, 1)
141
142    def get_type_name(self, id):
143        return self.get_type_impl(id, 0)
144
145    # Keeps track of request datatypes
146    def add_request(self, id, name, item):
147        if name[:-1] == self.namespace.prefix:
148            self.all.append((name, item))
149
150    # Keeps track of event datatypes
151    def add_event(self, id, name, item):
152        self.events[id] = (name, item)
153        if name[:-1] == self.namespace.prefix:
154            self.all.append((name, item))
155
156    def get_event(self, id):
157        return self.events[id][1]
158
159    # Keeps track of error datatypes
160    def add_error(self, id, name, item):
161        self.errors[id] = (name, item)
162        if name[:-1] == self.namespace.prefix:
163            self.all.append((name, item))
164
165    def get_error(self, id):
166        return self.errors[id][1]
167