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 # 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 50class 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', '', ('u8',), tcard8) 77 self.add_type('CARD16', '', ('u16',), tcard16) 78 self.add_type('CARD32', '', ('u32',), tcard32) 79 self.add_type('CARD64', '', ('u64',), tcard64) 80 self.add_type('INT8', '', ('i8',), tint8) 81 self.add_type('INT16', '', ('i16',), tint16) 82 self.add_type('INT32', '', ('i32',), tint32) 83 self.add_type('INT64', '', ('i64',), tint64) 84 self.add_type('BYTE', '', ('u8',), tcard8) 85 self.add_type('BOOL', '', ('BOOL',), tbool) 86 self.add_type('char', '', ('c_char',), tchar) 87 self.add_type('float', '', ('f32',), tfloat) 88 self.add_type('double', '', ('f64',), tdouble) 89 self.add_type('void', '', ('c_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] 174