| #!/usr/bin/env python |
| |
| # (C) Copyright IBM Corporation 2005 |
| # All Rights Reserved. |
| # |
| # Permission is hereby granted, free of charge, to any person obtaining a |
| # copy of this software and associated documentation files (the "Software"), |
| # to deal in the Software without restriction, including without limitation |
| # on the rights to use, copy, modify, merge, publish, distribute, sub |
| # license, and/or sell copies of the Software, and to permit persons to whom |
| # the Software is furnished to do so, subject to the following conditions: |
| # |
| # The above copyright notice and this permission notice (including the next |
| # paragraph) shall be included in all copies or substantial portions of the |
| # Software. |
| # |
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
| # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| # IN THE SOFTWARE. |
| # |
| # Authors: |
| # Ian Romanick <idr@us.ibm.com> |
| |
| import string, copy |
| |
| class type_node: |
| def __init__(self): |
| self.pointer = 0 # bool |
| self.const = 0 # bool |
| self.signed = 1 # bool |
| self.integer = 1 # bool |
| |
| # If elements is set to non-zero, then field is an array. |
| self.elements = 0 |
| |
| self.name = None |
| self.size = 0 # type's size in bytes |
| return |
| |
| |
| def string(self): |
| """Return string representation of this type_node.""" |
| s = "" |
| |
| if self.pointer: |
| s = "* " |
| |
| if self.const: |
| s += "const " |
| |
| if not self.pointer: |
| if self.integer: |
| if self.signed: |
| s += "signed " |
| else: |
| s += "unsigned " |
| |
| if self.name: |
| s += "%s " % (self.name) |
| |
| return s |
| |
| |
| class type_table: |
| def __init__(self): |
| self.types_by_name = {} |
| return |
| |
| |
| def add_type(self, type_expr): |
| self.types_by_name[ type_expr.get_base_name() ] = type_expr |
| return |
| |
| |
| def find_type(self, name): |
| if name in self.types_by_name: |
| return self.types_by_name[ name ] |
| else: |
| return None |
| |
| |
| def create_initial_types(): |
| tt = type_table() |
| |
| basic_types = [ |
| ("char", 1, 1), |
| ("short", 2, 1), |
| ("int", 4, 1), |
| ("long", 4, 1), |
| ("float", 4, 0), |
| ("double", 8, 0), |
| ("enum", 4, 1) |
| ] |
| |
| for (type_name, type_size, integer) in basic_types: |
| te = type_expression(None) |
| tn = type_node() |
| tn.name = type_name |
| tn.size = type_size |
| tn.integer = integer |
| te.expr.append(tn) |
| tt.add_type( te ) |
| |
| type_expression.built_in_types = tt |
| return |
| |
| |
| class type_expression: |
| built_in_types = None |
| |
| def __init__(self, type_string, extra_types = None): |
| self.expr = [] |
| |
| if not type_string: |
| return |
| |
| self.original_string = type_string |
| |
| if not type_expression.built_in_types: |
| raise RuntimeError("create_initial_types must be called before creating type_expression objects.") |
| |
| # Replace '*' with ' * ' in type_string. Then, split the string |
| # into tokens, separated by spaces. |
| tokens = string.split( string.replace( type_string, "*", " * " ) ) |
| |
| const = 0 |
| t = None |
| signed = 0 |
| unsigned = 0 |
| |
| for i in tokens: |
| if i == "const": |
| if t and t.pointer: |
| t.const = 1 |
| else: |
| const = 1 |
| elif i == "signed": |
| signed = 1 |
| elif i == "unsigned": |
| unsigned = 1 |
| elif i == "*": |
| # This is a quirky special-case because of the |
| # way the C works for types. If 'unsigned' is |
| # specified all by itself, it is treated the |
| # same as "unsigned int". |
| |
| if unsigned: |
| self.set_base_type( "int", signed, unsigned, const, extra_types ) |
| const = 0 |
| signed = 0 |
| unsigned = 0 |
| |
| if not self.expr: |
| raise RuntimeError("Invalid type expression (dangling pointer)") |
| |
| if signed: |
| raise RuntimeError("Invalid type expression (signed / unsigned applied to pointer)") |
| |
| t = type_node() |
| t.pointer = 1 |
| self.expr.append( t ) |
| else: |
| if self.expr: |
| raise RuntimeError('Invalid type expression (garbage after pointer qualifier -> "%s")' % (self.original_string)) |
| |
| self.set_base_type( i, signed, unsigned, const, extra_types ) |
| const = 0 |
| signed = 0 |
| unsigned = 0 |
| |
| if signed and unsigned: |
| raise RuntimeError("Invalid type expression (both signed and unsigned specified)") |
| |
| |
| if const: |
| raise RuntimeError("Invalid type expression (dangling const)") |
| |
| if unsigned: |
| raise RuntimeError("Invalid type expression (dangling signed)") |
| |
| if signed: |
| raise RuntimeError("Invalid type expression (dangling unsigned)") |
| |
| return |
| |
| |
| def set_base_type(self, type_name, signed, unsigned, const, extra_types): |
| te = type_expression.built_in_types.find_type( type_name ) |
| if not te: |
| te = extra_types.find_type( type_name ) |
| |
| if not te: |
| raise RuntimeError('Unknown base type "%s".' % (type_name)) |
| |
| self.expr = copy.deepcopy(te.expr) |
| |
| t = self.expr[ len(self.expr) - 1 ] |
| t.const = const |
| if signed: |
| t.signed = 1 |
| elif unsigned: |
| t.signed = 0 |
| |
| |
| def set_base_type_node(self, tn): |
| self.expr = [tn] |
| return |
| |
| |
| def set_elements(self, count): |
| tn = self.expr[0] |
| |
| tn.elements = count |
| return |
| |
| |
| def string(self): |
| s = "" |
| for t in self.expr: |
| s += t.string() |
| |
| return s |
| |
| |
| def get_base_type_node(self): |
| return self.expr[0] |
| |
| |
| def get_base_name(self): |
| if len(self.expr): |
| return self.expr[0].name |
| else: |
| return None |
| |
| |
| def get_element_size(self): |
| tn = self.expr[0] |
| |
| if tn.elements: |
| return tn.elements * tn.size |
| else: |
| return tn.size |
| |
| |
| def get_element_count(self): |
| tn = self.expr[0] |
| return tn.elements |
| |
| |
| def get_stack_size(self): |
| tn = self.expr[ -1 ] |
| |
| if tn.elements or tn.pointer: |
| return 4 |
| elif not tn.integer: |
| return tn.size |
| else: |
| return 4 |
| |
| |
| def is_pointer(self): |
| tn = self.expr[ -1 ] |
| return tn.pointer |
| |
| |
| def format_string(self): |
| tn = self.expr[ -1 ] |
| if tn.pointer: |
| return "%p" |
| elif not tn.integer: |
| return "%f" |
| else: |
| return "%d" |
| |
| |
| |
| if __name__ == '__main__': |
| |
| types_to_try = [ "int", "int *", "const int *", "int * const", "const int * const", \ |
| "unsigned * const *", \ |
| "float", "const double", "double * const"] |
| |
| create_initial_types() |
| |
| for t in types_to_try: |
| print 'Trying "%s"...' % (t) |
| te = type_expression( t ) |
| print 'Got "%s" (%u, %u).' % (te.string(), te.get_stack_size(), te.get_element_size()) |