summaryrefslogtreecommitdiff
path: root/src/mapi/glapi/gen/typeexpr.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mapi/glapi/gen/typeexpr.py')
-rw-r--r--src/mapi/glapi/gen/typeexpr.py292
1 files changed, 292 insertions, 0 deletions
diff --git a/src/mapi/glapi/gen/typeexpr.py b/src/mapi/glapi/gen/typeexpr.py
new file mode 100644
index 00000000000..8ba7de48627
--- /dev/null
+++ b/src/mapi/glapi/gen/typeexpr.py
@@ -0,0 +1,292 @@
+#!/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[ len(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[ len(self.expr) - 1 ]
+ return tn.pointer
+
+
+ def format_string(self):
+ tn = self.expr[ len(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())