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