state.py revision f591e195
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 + ':'
35d4401354Smrg
36d4401354Smrg        # Get root element attributes
37d4401354Smrg        if self.root.get('extension-xname', False):
38d4401354Smrg            self.is_ext = True
39d4401354Smrg            self.major_version = self.root.get('major-version')
40d4401354Smrg            self.minor_version = self.root.get('minor-version')
41d4401354Smrg            self.ext_xname = self.root.get('extension-xname')
42d4401354Smrg            self.ext_name = self.root.get('extension-name')
43d4401354Smrg            self.prefix = ('xcb', self.ext_name)
44d4401354Smrg        else:
45d4401354Smrg            self.is_ext = False
46d4401354Smrg            self.ext_name = ''
47d4401354Smrg            self.prefix = ('xcb',)
48d4401354Smrg
49d4401354Smrg
50d4401354Smrgclass Module(object):
51d4401354Smrg    '''
52d4401354Smrg    This is the grand, encompassing class that represents an entire XCB specification.
53d4401354Smrg    Only gets instantiated once, in the main() routine.
54d4401354Smrg
55d4401354Smrg    Don't need to worry about this much except to declare it and to get the namespace.
56d4401354Smrg
57d4401354Smrg    Public fields:
58d4401354Smrg    namespace contains the namespace info for the spec.
59d4401354Smrg    '''
60d4401354Smrg    open = __main__.output['open']
61d4401354Smrg    close = __main__.output['close']
62d4401354Smrg
63d4401354Smrg    def __init__(self, filename, output):
64d4401354Smrg        self.namespace = Namespace(filename)
65d4401354Smrg        self.output = output
66d4401354Smrg
67d4401354Smrg        self.imports = []
68d4401354Smrg        self.types = {}
69d4401354Smrg        self.events = {}
70d4401354Smrg        self.errors = {}
71d4401354Smrg        self.all = []
72d4401354Smrg
73d4401354Smrg        # Register some common types
74d4401354Smrg        self.add_type('CARD8', '', ('uint8_t',), tcard8)
75d4401354Smrg        self.add_type('CARD16', '', ('uint16_t',), tcard16)
76d4401354Smrg        self.add_type('CARD32', '', ('uint32_t',), tcard32)
77f591e195Smrg        self.add_type('CARD64', '', ('uint64_t',), tcard64)
78d4401354Smrg        self.add_type('INT8', '', ('int8_t',), tint8)
79d4401354Smrg        self.add_type('INT16', '', ('int16_t',), tint16)
80d4401354Smrg        self.add_type('INT32', '', ('int32_t',), tint32)
81f591e195Smrg        self.add_type('INT64', '', ('int64_t',), tint64)
82d4401354Smrg        self.add_type('BYTE', '', ('uint8_t',), tcard8)
83d4401354Smrg        self.add_type('BOOL', '', ('uint8_t',), tcard8)
84d4401354Smrg        self.add_type('char', '', ('char',), tchar)
85d4401354Smrg        self.add_type('float', '', ('float',), tfloat)
86d4401354Smrg        self.add_type('double', '', ('double',), tdouble)
87d4401354Smrg        self.add_type('void', '', ('void',), tcard8)
88d4401354Smrg
89d4401354Smrg    # This goes out and parses the rest of the XML
90d4401354Smrg    def register(self):
91d4401354Smrg        matcher.execute(self, self.namespace)
92d4401354Smrg
93d4401354Smrg    # Recursively resolve all types
94d4401354Smrg    def resolve(self):
95d4401354Smrg        for (name, item) in self.all:
96d4401354Smrg            item.resolve(self)
97d4401354Smrg
98d4401354Smrg    # Call all the output methods
99d4401354Smrg    def generate(self):
100d4401354Smrg        self.open()
101d4401354Smrg
102d4401354Smrg        for (name, item) in self.all:
103d4401354Smrg            item.out(name)
104d4401354Smrg
105d4401354Smrg        self.close()
106d4401354Smrg
107d4401354Smrg    # Keeps track of what's been imported so far.
108d4401354Smrg    def add_import(self, name, namespace):
109d4401354Smrg        self.imports.append((name, namespace.header))
110d4401354Smrg
111d4401354Smrg    def has_import(self, name):
112d4401354Smrg        for (name_, header) in self.imports:
113d4401354Smrg            if name_ == name:
114d4401354Smrg                return True
115d4401354Smrg        return False
116d4401354Smrg
117d4401354Smrg    # Keeps track of non-request/event/error datatypes
118d4401354Smrg    def add_type(self, id, ns, name, item):
119d4401354Smrg        key = ns + id
120d4401354Smrg        if key in self.types:
121d4401354Smrg            return
122d4401354Smrg        self.types[key] = (name, item)
123d4401354Smrg        if name[:-1] == self.namespace.prefix:
124d4401354Smrg            self.all.append((name, item))
125d4401354Smrg
126d4401354Smrg    def get_type_impl(self, id, idx):
127d4401354Smrg        key = id
128d4401354Smrg        if key in self.types:
129d4401354Smrg            return self.types[key][idx]
130d4401354Smrg
131d4401354Smrg        key = self.namespace.ns + id
132d4401354Smrg        if key in self.types:
133d4401354Smrg            return self.types[key][idx]
134d4401354Smrg
135d4401354Smrg        for key in self.types.keys():
136d4401354Smrg            if key.rpartition(':')[2] == id:
137d4401354Smrg                return self.types[key][idx]
138d4401354Smrg
139d4401354Smrg        raise ResolveException('Type %s not found' % id)
140d4401354Smrg
141d4401354Smrg    def get_type(self, id):
142d4401354Smrg        return self.get_type_impl(id, 1)
143d4401354Smrg
144d4401354Smrg    def get_type_name(self, id):
145d4401354Smrg        return self.get_type_impl(id, 0)
146d4401354Smrg
147d4401354Smrg    # Keeps track of request datatypes
148d4401354Smrg    def add_request(self, id, name, item):
149d4401354Smrg        if name[:-1] == self.namespace.prefix:
150d4401354Smrg            self.all.append((name, item))
151d4401354Smrg
152d4401354Smrg    # Keeps track of event datatypes
153d4401354Smrg    def add_event(self, id, name, item):
154d4401354Smrg        self.events[id] = (name, item)
155d4401354Smrg        if name[:-1] == self.namespace.prefix:
156d4401354Smrg            self.all.append((name, item))
157d4401354Smrg
158d4401354Smrg    def get_event(self, id):
159d4401354Smrg        return self.events[id][1]
160d4401354Smrg
161d4401354Smrg    # Keeps track of error datatypes
162d4401354Smrg    def add_error(self, id, name, item):
163d4401354Smrg        self.errors[id] = (name, item)
164d4401354Smrg        if name[:-1] == self.namespace.prefix:
165d4401354Smrg            self.all.append((name, item))
166d4401354Smrg
167d4401354Smrg    def get_error(self, id):
168d4401354Smrg        return self.errors[id][1]
169