state.py revision a27842ff
1''' 2This module contains the namespace class and the singleton module class. 3''' 4from os.path import dirname, basename 5from xml.etree.cElementTree import parse 6 7from xcbgen import matcher 8from xcbgen.error import * 9from xcbgen.xtypes import * 10 11import __main__ 12 13class 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 # Events 37 self.events = {} 38 39 # Get root element attributes 40 if self.root.get('extension-xname', False): 41 self.is_ext = True 42 self.major_version = self.root.get('major-version') 43 self.minor_version = self.root.get('minor-version') 44 self.ext_xname = self.root.get('extension-xname') 45 self.ext_name = self.root.get('extension-name') 46 self.prefix = ('xcb', self.ext_name) 47 else: 48 self.is_ext = False 49 self.ext_name = '' 50 self.prefix = ('xcb',) 51 52 def add_event(self, id, name, item): 53 self.events[id] = (name, item) 54 55 def get_event_by_opcode(self, opcode, is_ge_event): 56 for id, (name, event) in self.events.items(): 57 if event.is_ge_event == is_ge_event: 58 opcode_specific_name = event.get_name_for_opcode( opcode ) 59 if opcode_specific_name is not None: 60 return (opcode_specific_name, event) 61 return None 62 63 64class Module(object): 65 ''' 66 This is the grand, encompassing class that represents an entire XCB specification. 67 Only gets instantiated once, in the main() routine. 68 69 Don't need to worry about this much except to declare it and to get the namespace. 70 71 Public fields: 72 namespace contains the namespace info for the spec. 73 ''' 74 open = __main__.output['open'] 75 close = __main__.output['close'] 76 77 def __init__(self, filename, output): 78 self.namespace = Namespace(filename) 79 self.output = output 80 81 self.imports = [] 82 self.direct_imports = [] 83 self.import_level = 0 84 self.types = {} 85 self.events = {} 86 self.errors = {} 87 self.all = [] 88 89 # dict of namespaces by ext_name 90 self.namespaces = {} 91 # enter the main namespace here 92 self.namespaces[self.namespace.ext_name] = self.namespace 93 94 # Register some common types 95 self.add_type('CARD8', '', ('uint8_t',), tcard8) 96 self.add_type('CARD16', '', ('uint16_t',), tcard16) 97 self.add_type('CARD32', '', ('uint32_t',), tcard32) 98 self.add_type('CARD64', '', ('uint64_t',), tcard64) 99 self.add_type('INT8', '', ('int8_t',), tint8) 100 self.add_type('INT16', '', ('int16_t',), tint16) 101 self.add_type('INT32', '', ('int32_t',), tint32) 102 self.add_type('INT64', '', ('int64_t',), tint64) 103 self.add_type('BYTE', '', ('uint8_t',), tcard8) 104 self.add_type('BOOL', '', ('uint8_t',), tcard8) 105 self.add_type('char', '', ('char',), tchar) 106 self.add_type('float', '', ('float',), tfloat) 107 self.add_type('double', '', ('double',), tdouble) 108 self.add_type('void', '', ('void',), tcard8) 109 110 # This goes out and parses the rest of the XML 111 def register(self): 112 matcher.execute(self, self.namespace) 113 114 # Recursively resolve all types 115 def resolve(self): 116 self.add_events_to_namespaces() 117 for (name, item) in self.all: 118 self.pads = 0 119 item.resolve(self) 120 121 # Call all the output methods 122 def generate(self): 123 self.open() 124 125 for (name, item) in self.all: 126 item.out(name) 127 128 self.close() 129 130 # Keeps track of what's been imported so far. 131 def add_import(self, name, namespace): 132 if self.import_level == 0: 133 self.direct_imports.append((name, namespace.header)) 134 self.imports.append((name, namespace.header)) 135 self.namespaces[namespace.ext_name] = namespace 136 137 def has_import(self, name): 138 for (name_, header) in self.imports: 139 if name_ == name: 140 return True 141 return False 142 143 # Keeps track of non-request/event/error datatypes 144 def add_type(self, id, ns, name, item): 145 key = ns + id 146 if key in self.types: 147 return 148 self.types[key] = (name, item) 149 if name[:-1] == self.namespace.prefix: 150 self.all.append((name, item)) 151 152 def get_type_impl(self, id, idx): 153 key = id 154 if key in self.types: 155 return self.types[key][idx] 156 157 key = self.namespace.ns + id 158 if key in self.types: 159 return self.types[key][idx] 160 161 for key in self.types.keys(): 162 if key.rpartition(':')[2] == id: 163 return self.types[key][idx] 164 165 raise ResolveException('Type %s not found' % id) 166 167 def get_type(self, id): 168 return self.get_type_impl(id, 1) 169 170 def get_type_name(self, id): 171 return self.get_type_impl(id, 0) 172 173 def get_namespace(self, ext_name): 174 return self.namespaces[ext_name] 175 176 # Keeps track of request datatypes 177 def add_request(self, id, name, item): 178 if name[:-1] == self.namespace.prefix: 179 self.all.append((name, item)) 180 181 # Keeps track of event datatypes 182 def add_event(self, id, name, item): 183 self.events[id] = (name, item) 184 if name[:-1] == self.namespace.prefix: 185 self.all.append((name, item)) 186 187 188 def add_events_to_namespaces(self): 189 # add to its namespace object 190 for id, (name,item) in self.events.items(): 191 if name[:-1] == ('xcb',): 192 # core event 193 namespace_name = '' 194 else: 195 # extension event 196 namespace_name = name[-2] 197 198 namespace = self.namespaces[namespace_name] 199 200 if namespace is not None: 201 namespace.add_event(id, name, item) 202 203 204 def get_event(self, id): 205 return self.events[id][1] 206 207 # Keeps track of error datatypes 208 def add_error(self, id, name, item): 209 self.errors[id] = (name, item) 210 if name[:-1] == self.namespace.prefix: 211 self.all.append((name, item)) 212 213 def get_error(self, id): 214 return self.errors[id][1] 215