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:
     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:
     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:
    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