Home | History | Annotate | Download | only in gen
      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 (at] us.ibm.com>
     26 
     27 import string, copy
     28 
     29 class 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 
     67 class 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 
     85 def 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 
    111 class 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 = string.split( string.replace( type_string, "*", " * " ) )
    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 
    280 if __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