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 27from __future__ import print_function 28 29import copy 30 31class type_node(object): 32 def __init__(self): 33 self.pointer = 0 # bool 34 self.const = 0 # bool 35 self.signed = 1 # bool 36 self.integer = 1 # bool 37 38 # If elements is set to non-zero, then field is an array. 39 self.elements = 0 40 41 self.name = None 42 self.size = 0 # type's size in bytes 43 return 44 45 46 def string(self): 47 """Return string representation of this type_node.""" 48 s = "" 49 50 if self.pointer: 51 s = "* " 52 53 if self.const: 54 s += "const " 55 56 if not self.pointer: 57 if self.integer: 58 if self.signed: 59 s += "signed " 60 else: 61 s += "unsigned " 62 63 if self.name: 64 s += "%s " % (self.name) 65 66 return s 67 68 69class type_table(object): 70 def __init__(self): 71 self.types_by_name = {} 72 return 73 74 75 def add_type(self, type_expr): 76 self.types_by_name[ type_expr.get_base_name() ] = type_expr 77 return 78 79 80 def find_type(self, name): 81 if name in self.types_by_name: 82 return self.types_by_name[ name ] 83 else: 84 return None 85 86 87def create_initial_types(): 88 tt = type_table() 89 90 basic_types = [ 91 ("char", 1, 1), 92 ("short", 2, 1), 93 ("int", 4, 1), 94 ("long", 4, 1), 95 ("float", 4, 0), 96 ("double", 8, 0), 97 ("enum", 4, 1) 98 ] 99 100 for (type_name, type_size, integer) in basic_types: 101 te = type_expression(None) 102 tn = type_node() 103 tn.name = type_name 104 tn.size = type_size 105 tn.integer = integer 106 te.expr.append(tn) 107 tt.add_type( te ) 108 109 type_expression.built_in_types = tt 110 return 111 112 113class type_expression(object): 114 built_in_types = None 115 116 def __init__(self, type_string, extra_types = None): 117 self.expr = [] 118 119 if not type_string: 120 return 121 122 self.original_string = type_string 123 124 if not type_expression.built_in_types: 125 raise RuntimeError("create_initial_types must be called before creating type_expression objects.") 126 127 # Replace '*' with ' * ' in type_string. Then, split the string 128 # into tokens, separated by spaces. 129 tokens = type_string.replace("*", " * ").split() 130 131 const = 0 132 t = None 133 signed = 0 134 unsigned = 0 135 136 for i in tokens: 137 if i == "const": 138 if t and t.pointer: 139 t.const = 1 140 else: 141 const = 1 142 elif i == "signed": 143 signed = 1 144 elif i == "unsigned": 145 unsigned = 1 146 elif i == "*": 147 # This is a quirky special-case because of the 148 # way the C works for types. If 'unsigned' is 149 # specified all by itself, it is treated the 150 # same as "unsigned int". 151 152 if unsigned: 153 self.set_base_type( "int", signed, unsigned, const, extra_types ) 154 const = 0 155 signed = 0 156 unsigned = 0 157 158 if not self.expr: 159 raise RuntimeError("Invalid type expression (dangling pointer)") 160 161 if signed: 162 raise RuntimeError("Invalid type expression (signed / unsigned applied to pointer)") 163 164 t = type_node() 165 t.pointer = 1 166 self.expr.append( t ) 167 else: 168 if self.expr: 169 raise RuntimeError('Invalid type expression (garbage after pointer qualifier -> "%s")' % (self.original_string)) 170 171 self.set_base_type( i, signed, unsigned, const, extra_types ) 172 const = 0 173 signed = 0 174 unsigned = 0 175 176 if signed and unsigned: 177 raise RuntimeError("Invalid type expression (both signed and unsigned specified)") 178 179 180 if const: 181 raise RuntimeError("Invalid type expression (dangling const)") 182 183 if unsigned: 184 raise RuntimeError("Invalid type expression (dangling signed)") 185 186 if signed: 187 raise RuntimeError("Invalid type expression (dangling unsigned)") 188 189 return 190 191 192 def set_base_type(self, type_name, signed, unsigned, const, extra_types): 193 te = type_expression.built_in_types.find_type( type_name ) 194 if not te: 195 te = extra_types.find_type( type_name ) 196 197 if not te: 198 raise RuntimeError('Unknown base type "%s".' % (type_name)) 199 200 self.expr = copy.deepcopy(te.expr) 201 202 t = self.expr[ len(self.expr) - 1 ] 203 t.const = const 204 if signed: 205 t.signed = 1 206 elif unsigned: 207 t.signed = 0 208 209 210 def set_base_type_node(self, tn): 211 self.expr = [tn] 212 return 213 214 215 def set_elements(self, count): 216 tn = self.expr[0] 217 218 tn.elements = count 219 return 220 221 222 def string(self): 223 s = "" 224 for t in self.expr: 225 s += t.string() 226 227 return s 228 229 230 def get_base_type_node(self): 231 return self.expr[0] 232 233 234 def get_base_name(self): 235 if len(self.expr): 236 return self.expr[0].name 237 else: 238 return None 239 240 241 def get_element_size(self): 242 tn = self.expr[0] 243 244 if tn.elements: 245 return tn.elements * tn.size 246 else: 247 return tn.size 248 249 250 def get_element_count(self): 251 tn = self.expr[0] 252 return tn.elements 253 254 255 def get_stack_size(self): 256 tn = self.expr[ -1 ] 257 258 if tn.elements or tn.pointer: 259 return 4 260 elif not tn.integer: 261 return tn.size 262 else: 263 return 4 264 265 266 def is_pointer(self): 267 tn = self.expr[ -1 ] 268 return tn.pointer 269 270 271 def format_string(self): 272 tn = self.expr[ -1 ] 273 if tn.pointer: 274 return "%p" 275 elif not tn.integer: 276 return "%f" 277 else: 278 return "%d" 279 280 281 282if __name__ == '__main__': 283 284 types_to_try = [ "int", "int *", "const int *", "int * const", "const int * const", \ 285 "unsigned * const *", \ 286 "float", "const double", "double * const"] 287 288 create_initial_types() 289 290 for t in types_to_try: 291 print('Trying "%s"...' % (t)) 292 te = type_expression( t ) 293 print('Got "%s" (%u, %u).' % (te.string(), te.get_stack_size(), te.get_element_size())) 294