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