state.py revision d5c9b07b
1d4401354Smrg'''
2d4401354SmrgThis module contains the namespace class and the singleton module class.
3d4401354Smrg'''
4d4401354Smrgfrom os.path import dirname, basename
5d5c9b07bSmrgfrom sys import version_info
6d5c9b07bSmrg
7d5c9b07bSmrgif version_info[:2] >= (3, 3):
8d5c9b07bSmrg    from xml.etree.ElementTree import parse
9d5c9b07bSmrgelse:
10d5c9b07bSmrg    from xml.etree.cElementTree import parse
11d4401354Smrg
12986c8b3dSmrgfrom xcbgen import matcher
13986c8b3dSmrgfrom xcbgen.error import *
14986c8b3dSmrgfrom xcbgen.xtypes import *
15d4401354Smrg
16d4401354Smrgimport __main__
17d4401354Smrg
18d4401354Smrgclass Namespace(object):
19d4401354Smrg    '''
20d4401354Smrg    Contains the naming information for an extension.
21d4401354Smrg
22d4401354Smrg    Public fields:
23d4401354Smrg
24d4401354Smrg    header is the header attribute ("header file" name).
25d4401354Smrg    is_ext is true for extensions, false for xproto.
26d4401354Smrg    major_version and minor_version are extension version info.
27d4401354Smrg    ext_xname is the X extension name string.
28d4401354Smrg    ext_name is the XCB extension name prefix.
29d4401354Smrg    '''
30d4401354Smrg    def __init__(self, filename):
31d4401354Smrg        # Path info
32d4401354Smrg        self.path = filename
33d4401354Smrg        self.dir = dirname(filename)
34d4401354Smrg        self.file = basename(filename)
35d4401354Smrg
36d4401354Smrg        # Parse XML
37d4401354Smrg        self.root = parse(filename).getroot()
38d4401354Smrg        self.header = self.root.get('header')
39d4401354Smrg        self.ns = self.header + ':'
40a27842ffSmrg
41a27842ffSmrg        # Events
42a27842ffSmrg        self.events = {}
43d4401354Smrg
44d4401354Smrg        # Get root element attributes
45d4401354Smrg        if self.root.get('extension-xname', False):
46d4401354Smrg            self.is_ext = True
47d4401354Smrg            self.major_version = self.root.get('major-version')
48d4401354Smrg            self.minor_version = self.root.get('minor-version')
49d4401354Smrg            self.ext_xname = self.root.get('extension-xname')
50d4401354Smrg            self.ext_name = self.root.get('extension-name')
51d4401354Smrg            self.prefix = ('xcb', self.ext_name)
52d4401354Smrg        else:
53d4401354Smrg            self.is_ext = False
54d4401354Smrg            self.ext_name = ''
55d4401354Smrg            self.prefix = ('xcb',)
56d4401354Smrg
57a27842ffSmrg    def add_event(self, id, name, item):
58a27842ffSmrg        self.events[id] = (name, item)
59a27842ffSmrg
60a27842ffSmrg    def get_event_by_opcode(self, opcode, is_ge_event):
61a27842ffSmrg        for id, (name, event) in self.events.items():
62a27842ffSmrg            if event.is_ge_event == is_ge_event:
63a27842ffSmrg                opcode_specific_name = event.get_name_for_opcode( opcode )
64a27842ffSmrg                if opcode_specific_name is not None:
65a27842ffSmrg                    return (opcode_specific_name, event)
66a27842ffSmrg        return None
67a27842ffSmrg
68d4401354Smrg
69d4401354Smrgclass Module(object):
70d4401354Smrg    '''
71d4401354Smrg    This is the grand, encompassing class that represents an entire XCB specification.
72d4401354Smrg    Only gets instantiated once, in the main() routine.
73d4401354Smrg
74d4401354Smrg    Don't need to worry about this much except to declare it and to get the namespace.
75d4401354Smrg
76d4401354Smrg    Public fields:
77d4401354Smrg    namespace contains the namespace info for the spec.
78d4401354Smrg    '''
79d4401354Smrg    open = __main__.output['open']
80d4401354Smrg    close = __main__.output['close']
81d4401354Smrg
82d4401354Smrg    def __init__(self, filename, output):
83d4401354Smrg        self.namespace = Namespace(filename)
84d4401354Smrg        self.output = output
85d4401354Smrg
86d4401354Smrg        self.imports = []
87b26960f7Smrg        self.direct_imports = []
88b26960f7Smrg        self.import_level = 0
89d4401354Smrg        self.types = {}
90d4401354Smrg        self.events = {}
91d4401354Smrg        self.errors = {}
92d4401354Smrg        self.all = []
93d4401354Smrg
94a27842ffSmrg        # dict of namespaces by ext_name
95a27842ffSmrg        self.namespaces = {}
96a27842ffSmrg        # enter the main namespace here
97a27842ffSmrg        self.namespaces[self.namespace.ext_name] = self.namespace
98a27842ffSmrg
99d4401354Smrg        # Register some common types
100d4401354Smrg        self.add_type('CARD8', '', ('uint8_t',), tcard8)
101d4401354Smrg        self.add_type('CARD16', '', ('uint16_t',), tcard16)
102d4401354Smrg        self.add_type('CARD32', '', ('uint32_t',), tcard32)
103f591e195Smrg        self.add_type('CARD64', '', ('uint64_t',), tcard64)
104d4401354Smrg        self.add_type('INT8', '', ('int8_t',), tint8)
105d4401354Smrg        self.add_type('INT16', '', ('int16_t',), tint16)
106d4401354Smrg        self.add_type('INT32', '', ('int32_t',), tint32)
107f591e195Smrg        self.add_type('INT64', '', ('int64_t',), tint64)
1088d8e295fSmrg        self.add_type('BYTE', '', ('uint8_t',), tbyte)
1098d8e295fSmrg        self.add_type('BOOL', '', ('uint8_t',), tbool)
110d4401354Smrg        self.add_type('char', '', ('char',), tchar)
111d4401354Smrg        self.add_type('float', '', ('float',), tfloat)
112d4401354Smrg        self.add_type('double', '', ('double',), tdouble)
1138d8e295fSmrg        self.add_type('void', '', ('void',), tvoid)
114d4401354Smrg
115d4401354Smrg    # This goes out and parses the rest of the XML
116d4401354Smrg    def register(self):
117d4401354Smrg        matcher.execute(self, self.namespace)
118d4401354Smrg
119d4401354Smrg    # Recursively resolve all types
120d4401354Smrg    def resolve(self):
121a27842ffSmrg        self.add_events_to_namespaces()
122d4401354Smrg        for (name, item) in self.all:
123b26960f7Smrg            self.pads = 0
124d4401354Smrg            item.resolve(self)
125d4401354Smrg
126d4401354Smrg    # Call all the output methods
127d4401354Smrg    def generate(self):
128d4401354Smrg        self.open()
129d4401354Smrg
130d4401354Smrg        for (name, item) in self.all:
131d4401354Smrg            item.out(name)
132d4401354Smrg
133d4401354Smrg        self.close()
134d4401354Smrg
135d4401354Smrg    # Keeps track of what's been imported so far.
136d4401354Smrg    def add_import(self, name, namespace):
137b26960f7Smrg        if self.import_level == 0:
138b26960f7Smrg            self.direct_imports.append((name, namespace.header))
139d4401354Smrg        self.imports.append((name, namespace.header))
140a27842ffSmrg        self.namespaces[namespace.ext_name] = namespace
141d4401354Smrg
142d4401354Smrg    def has_import(self, name):
143d4401354Smrg        for (name_, header) in self.imports:
144d4401354Smrg            if name_ == name:
145d4401354Smrg                return True
146d4401354Smrg        return False
147d4401354Smrg
148d4401354Smrg    # Keeps track of non-request/event/error datatypes
149d4401354Smrg    def add_type(self, id, ns, name, item):
150d4401354Smrg        key = ns + id
151d4401354Smrg        if key in self.types:
152d4401354Smrg            return
153d4401354Smrg        self.types[key] = (name, item)
154d4401354Smrg        if name[:-1] == self.namespace.prefix:
155d4401354Smrg            self.all.append((name, item))
156d4401354Smrg
157d4401354Smrg    def get_type_impl(self, id, idx):
158d4401354Smrg        key = id
159d4401354Smrg        if key in self.types:
160d4401354Smrg            return self.types[key][idx]
161d4401354Smrg
162d4401354Smrg        key = self.namespace.ns + id
163d4401354Smrg        if key in self.types:
164d4401354Smrg            return self.types[key][idx]
165d4401354Smrg
166d4401354Smrg        for key in self.types.keys():
167d4401354Smrg            if key.rpartition(':')[2] == id:
168d4401354Smrg                return self.types[key][idx]
169d4401354Smrg
170d4401354Smrg        raise ResolveException('Type %s not found' % id)
171d4401354Smrg
172d4401354Smrg    def get_type(self, id):
173d4401354Smrg        return self.get_type_impl(id, 1)
174d4401354Smrg
175d4401354Smrg    def get_type_name(self, id):
176d4401354Smrg        return self.get_type_impl(id, 0)
177d4401354Smrg
178a27842ffSmrg    def get_namespace(self, ext_name):
179a27842ffSmrg        return self.namespaces[ext_name]
180a27842ffSmrg
181d4401354Smrg    # Keeps track of request datatypes
182d4401354Smrg    def add_request(self, id, name, item):
183d4401354Smrg        if name[:-1] == self.namespace.prefix:
184d4401354Smrg            self.all.append((name, item))
185d4401354Smrg
186d4401354Smrg    # Keeps track of event datatypes
187d4401354Smrg    def add_event(self, id, name, item):
188d4401354Smrg        self.events[id] = (name, item)
189d4401354Smrg        if name[:-1] == self.namespace.prefix:
190d4401354Smrg            self.all.append((name, item))
191d4401354Smrg
192a27842ffSmrg
193a27842ffSmrg    def add_events_to_namespaces(self):
194a27842ffSmrg        # add to its namespace object
195a27842ffSmrg        for id, (name,item) in self.events.items():
196a27842ffSmrg            if name[:-1] == ('xcb',):
197a27842ffSmrg                # core event
198a27842ffSmrg                namespace_name = ''
199a27842ffSmrg            else:
200a27842ffSmrg                # extension event
201a27842ffSmrg                namespace_name = name[-2]
202a27842ffSmrg
203a27842ffSmrg            namespace = self.namespaces[namespace_name]
204a27842ffSmrg
205a27842ffSmrg            if namespace is not None:
206a27842ffSmrg                namespace.add_event(id, name, item)
207a27842ffSmrg
208a27842ffSmrg
209d4401354Smrg    def get_event(self, id):
210d4401354Smrg        return self.events[id][1]
211d4401354Smrg
212d4401354Smrg    # Keeps track of error datatypes
213d4401354Smrg    def add_error(self, id, name, item):
214d4401354Smrg        self.errors[id] = (name, item)
215d4401354Smrg        if name[:-1] == self.namespace.prefix:
216d4401354Smrg            self.all.append((name, item))
217d4401354Smrg
218d4401354Smrg    def get_error(self, id):
219d4401354Smrg        return self.errors[id][1]
220