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