Home | History | Annotate | Download | only in gen
      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 (at] us.ibm.com>
     27 
     28 import string, copy
     29 
     30 class 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 
     68 class 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 
     86 def 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 
    112 class 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 
    281 if __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