state.py revision 986c8b3d
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)
77d4401354Smrg        self.add_type('INT8', '', ('int8_t',), tint8)
78d4401354Smrg        self.add_type('INT16', '', ('int16_t',), tint16)
79d4401354Smrg        self.add_type('INT32', '', ('int32_t',), tint32)
80d4401354Smrg        self.add_type('BYTE', '', ('uint8_t',), tcard8)
81d4401354Smrg        self.add_type('BOOL', '', ('uint8_t',), tcard8)
82d4401354Smrg        self.add_type('char', '', ('char',), tchar)
83d4401354Smrg        self.add_type('float', '', ('float',), tfloat)
84d4401354Smrg        self.add_type('double', '', ('double',), tdouble)
85d4401354Smrg        self.add_type('void', '', ('void',), tcard8)
86d4401354Smrg
87d4401354Smrg    # This goes out and parses the rest of the XML
88d4401354Smrg    def register(self):
89d4401354Smrg        matcher.execute(self, self.namespace)
90d4401354Smrg
91d4401354Smrg    # Recursively resolve all types
92d4401354Smrg    def resolve(self):
93d4401354Smrg        for (name, item) in self.all:
94d4401354Smrg            item.resolve(self)
95d4401354Smrg
96d4401354Smrg    # Call all the output methods
97d4401354Smrg    def generate(self):
98d4401354Smrg        self.open()
99d4401354Smrg
100d4401354Smrg        for (name, item) in self.all:
101d4401354Smrg            item.out(name)
102d4401354Smrg
103d4401354Smrg        self.close()
104d4401354Smrg
105d4401354Smrg    # Keeps track of what's been imported so far.
106d4401354Smrg    def add_import(self, name, namespace):
107d4401354Smrg        self.imports.append((name, namespace.header))
108d4401354Smrg
109d4401354Smrg    def has_import(self, name):
110d4401354Smrg        for (name_, header) in self.imports:
111d4401354Smrg            if name_ == name:
112d4401354Smrg                return True
113d4401354Smrg        return False
114d4401354Smrg
115d4401354Smrg    # Keeps track of non-request/event/error datatypes
116d4401354Smrg    def add_type(self, id, ns, name, item):
117d4401354Smrg        key = ns + id
118d4401354Smrg        if key in self.types:
119d4401354Smrg            return
120d4401354Smrg        self.types[key] = (name, item)
121d4401354Smrg        if name[:-1] == self.namespace.prefix:
122d4401354Smrg            self.all.append((name, item))
123d4401354Smrg
124d4401354Smrg    def get_type_impl(self, id, idx):
125d4401354Smrg        key = id
126d4401354Smrg        if key in self.types:
127d4401354Smrg            return self.types[key][idx]
128d4401354Smrg
129d4401354Smrg        key = self.namespace.ns + id
130d4401354Smrg        if key in self.types:
131d4401354Smrg            return self.types[key][idx]
132d4401354Smrg
133d4401354Smrg        for key in self.types.keys():
134d4401354Smrg            if key.rpartition(':')[2] == id:
135d4401354Smrg                return self.types[key][idx]
136d4401354Smrg
137d4401354Smrg        raise ResolveException('Type %s not found' % id)
138d4401354Smrg
139d4401354Smrg    def get_type(self, id):
140d4401354Smrg        return self.get_type_impl(id, 1)
141d4401354Smrg
142d4401354Smrg    def get_type_name(self, id):
143d4401354Smrg        return self.get_type_impl(id, 0)
144d4401354Smrg
145d4401354Smrg    # Keeps track of request datatypes
146d4401354Smrg    def add_request(self, id, name, item):
147d4401354Smrg        if name[:-1] == self.namespace.prefix:
148d4401354Smrg            self.all.append((name, item))
149d4401354Smrg
150d4401354Smrg    # Keeps track of event datatypes
151d4401354Smrg    def add_event(self, id, name, item):
152d4401354Smrg        self.events[id] = (name, item)
153d4401354Smrg        if name[:-1] == self.namespace.prefix:
154d4401354Smrg            self.all.append((name, item))
155d4401354Smrg
156d4401354Smrg    def get_event(self, id):
157d4401354Smrg        return self.events[id][1]
158d4401354Smrg
159d4401354Smrg    # Keeps track of error datatypes
160d4401354Smrg    def add_error(self, id, name, item):
161d4401354Smrg        self.errors[id] = (name, item)
162d4401354Smrg        if name[:-1] == self.namespace.prefix:
163d4401354Smrg            self.all.append((name, item))
164d4401354Smrg
165d4401354Smrg    def get_error(self, id):
166d4401354Smrg        return self.errors[id][1]
167