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