Release xcb-proto 1.10
[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             item.resolve(self)
97
98     # Call all the output methods
99     def generate(self):
100         self.open()
101
102         for (name, item) in self.all:
103             item.out(name)
104
105         self.close()
106
107     # Keeps track of what's been imported so far.
108     def add_import(self, name, namespace):
109         self.imports.append((name, namespace.header))
110
111     def has_import(self, name):
112         for (name_, header) in self.imports:
113             if name_ == name:
114                 return True
115         return False
116
117     # Keeps track of non-request/event/error datatypes
118     def add_type(self, id, ns, name, item):
119         key = ns + id
120         if key in self.types:
121             return
122         self.types[key] = (name, item)
123         if name[:-1] == self.namespace.prefix:
124             self.all.append((name, item))
125
126     def get_type_impl(self, id, idx):
127         key = id
128         if key in self.types:
129             return self.types[key][idx]
130
131         key = self.namespace.ns + id
132         if key in self.types:
133             return self.types[key][idx]
134
135         for key in self.types.keys():
136             if key.rpartition(':')[2] == id:
137                 return self.types[key][idx]
138
139         raise ResolveException('Type %s not found' % id)
140
141     def get_type(self, id):
142         return self.get_type_impl(id, 1)
143
144     def get_type_name(self, id):
145         return self.get_type_impl(id, 0)
146
147     # Keeps track of request datatypes
148     def add_request(self, id, name, item):
149         if name[:-1] == self.namespace.prefix:
150             self.all.append((name, item))
151
152     # Keeps track of event datatypes
153     def add_event(self, id, name, item):
154         self.events[id] = (name, item)
155         if name[:-1] == self.namespace.prefix:
156             self.all.append((name, item))
157
158     def get_event(self, id):
159         return self.events[id][1]
160
161     # Keeps track of error datatypes
162     def add_error(self, id, name, item):
163         self.errors[id] = (name, item)
164         if name[:-1] == self.namespace.prefix:
165             self.all.append((name, item))
166
167     def get_error(self, id):
168         return self.errors[id][1]