1 2# (C) Copyright IBM Corporation 2005 3# All Rights Reserved. 4# 5# Permission is hereby granted, free of charge, to any person obtaining a 6# copy of this software and associated documentation files (the "Software"), 7# to deal in the Software without restriction, including without limitation 8# on the rights to use, copy, modify, merge, publish, distribute, sub 9# license, and/or sell copies of the Software, and to permit persons to whom 10# the Software is furnished to do so, subject to the following conditions: 11# 12# The above copyright notice and this permission notice (including the next 13# paragraph) shall be included in all copies or substantial portions of the 14# Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22# IN THE SOFTWARE. 23# 24# Authors: 25# Ian Romanick <idr@us.ibm.com> 26 27import copy 28 29class type_node(object): 30 def __init__(self): 31 self.pointer = 0 # bool 32 self.const = 0 # bool 33 self.signed = 1 # bool 34 self.integer = 1 # bool 35 36 # If elements is set to non-zero, then field is an array. 37 self.elements = 0 38 39 self.name = None 40 self.size = 0 # type's size in bytes 41 return 42 43 44 def string(self): 45 """Return string representation of this type_node.""" 46 s = "" 47 48 if self.pointer: 49 s = "* " 50 51 if self.const: 52 s += "const " 53 54 if not self.pointer: 55 if self.integer: 56 if self.signed: 57 s += "signed " 58 else: 59 s += "unsigned " 60 61 if self.name: 62 s += "%s " % (self.name) 63 64 return s 65 66 67class type_table(object): 68 def __init__(self): 69 self.types_by_name = {} 70 return 71 72 73 def add_type(self, type_expr): 74 self.types_by_name[ type_expr.get_base_name() ] = type_expr 75 return 76 77 78 def find_type(self, name): 79 if name in self.types_by_name: 80 return self.types_by_name[ name ] 81 else: 82 return None 83 84 85def create_initial_types(): 86 tt = type_table() 87 88 basic_types = [ 89 ("char", 1, 1), 90 ("short", 2, 1), 91 ("int", 4, 1), 92 ("long", 4, 1), 93 ("float", 4, 0), 94 ("double", 8, 0), 95 ("enum", 4, 1) 96 ] 97 98 for (type_name, type_size, integer) in basic_types: 99 te = type_expression(None) 100 tn = type_node() 101 tn.name = type_name 102 tn.size = type_size 103 tn.integer = integer 104 te.expr.append(tn) 105 tt.add_type( te ) 106 107 type_expression.built_in_types = tt 108 return 109 110 111class type_expression(object): 112 built_in_types = None 113 114 def __init__(self, type_string, extra_types = None): 115 self.expr = [] 116 117 if not type_string: 118 return 119 120 self.original_string = type_string 121 122 if not type_expression.built_in_types: 123 raise RuntimeError("create_initial_types must be called before creating type_expression objects.") 124 125 # Replace '*' with ' * ' in type_string. Then, split the string 126 # into tokens, separated by spaces. 127 tokens = type_string.replace("*", " * ").split() 128 129 const = 0 130 t = None 131 signed = 0 132 unsigned = 0 133 134 for i in tokens: 135 if i == "const": 136 if t and t.pointer: 137 t.const = 1 138 else: 139 const = 1 140 elif i == "signed": 141 signed = 1 142 elif i == "unsigned": 143 unsigned = 1 144 elif i == "*": 145 # This is a quirky special-case because of the 146 # way the C works for types. If 'unsigned' is 147 # specified all by itself, it is treated the 148 # same as "unsigned int". 149 150 if unsigned: 151 self.set_base_type( "int", signed, unsigned, const, extra_types ) 152 const = 0 153 signed = 0 154 unsigned = 0 155 156 if not self.expr: 157 raise RuntimeError("Invalid type expression (dangling pointer)") 158 159 if signed: 160 raise RuntimeError("Invalid type expression (signed / unsigned applied to pointer)") 161 162 t = type_node() 163 t.pointer = 1 164 self.expr.append( t ) 165 else: 166 if self.expr: 167 raise RuntimeError('Invalid type expression (garbage after pointer qualifier -> "%s")' % (self.original_string)) 168 169 self.set_base_type( i, signed, unsigned, const, extra_types ) 170 const = 0 171 signed = 0 172 unsigned = 0 173 174 if signed and unsigned: 175 raise RuntimeError("Invalid type expression (both signed and unsigned specified)") 176 177 178 if const: 179 raise RuntimeError("Invalid type expression (dangling const)") 180 181 if unsigned: 182 raise RuntimeError("Invalid type expression (dangling signed)") 183 184 if signed: 185 raise RuntimeError("Invalid type expression (dangling unsigned)") 186 187 return 188 189 190 def set_base_type(self, type_name, signed, unsigned, const, extra_types): 191 te = type_expression.built_in_types.find_type( type_name ) 192 if not te: 193 te = extra_types.find_type( type_name ) 194 195 if not te: 196 raise RuntimeError('Unknown base type "%s".' % (type_name)) 197 198 self.expr = copy.deepcopy(te.expr) 199 200 t = self.expr[ len(self.expr) - 1 ] 201 t.const = const 202 if signed: 203 t.signed = 1 204 elif unsigned: 205 t.signed = 0 206 207 208 def set_base_type_node(self, tn): 209 self.expr = [tn] 210 return 211 212 213 def set_elements(self, count): 214 tn = self.expr[0] 215 216 tn.elements = count 217 return 218 219 220 def string(self): 221 s = "" 222 for t in self.expr: 223 s += t.string() 224 225 return s 226 227 228 def get_base_type_node(self): 229 return self.expr[0] 230 231 232 def get_base_name(self): 233 if len(self.expr): 234 return self.expr[0].name 235 else: 236 return None 237 238 239 def get_element_size(self): 240 tn = self.expr[0] 241 242 if tn.elements: 243 return tn.elements * tn.size 244 else: 245 return tn.size 246 247 248 def get_element_count(self): 249 tn = self.expr[0] 250 return tn.elements 251 252 253 def get_stack_size(self): 254 tn = self.expr[ -1 ] 255 256 if tn.elements or tn.pointer: 257 return 4 258 elif not tn.integer: 259 return tn.size 260 else: 261 return 4 262 263 264 def is_pointer(self): 265 tn = self.expr[ -1 ] 266 return tn.pointer 267 268 269 def format_string(self): 270 tn = self.expr[ -1 ] 271 if tn.pointer: 272 return "%p" 273 elif not tn.integer: 274 return "%f" 275 else: 276 return "%d" 277 278 279 280if __name__ == '__main__': 281 282 types_to_try = [ "int", "int *", "const int *", "int * const", "const int * const", \ 283 "unsigned * const *", \ 284 "float", "const double", "double * const"] 285 286 create_initial_types() 287 288 for t in types_to_try: 289 print('Trying "%s"...' % (t)) 290 te = type_expression( t ) 291 print('Got "%s" (%u, %u).' % (te.string(), te.get_stack_size(), te.get_element_size())) 292