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