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