Mammoth update to the Python code generator scripts that live in
[mesa.git] / src / mesa / glapi / typeexpr.py
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@us.ibm.com>
27
28 import string, copy
29
30 class type_node:
31 def __init__(self):
32 self.pointer = 0
33 self.const = 0
34 self.signed = 1
35 self.integer = 1
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
42 return
43
44
45 def string(self):
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:
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 = [ ["char", 1, 1], \
89 ["short", 2, 1], \
90 ["int", 4, 1], \
91 ["long", 4, 1], \
92 ["float", 4, 0], \
93 ["double", 8, 0], \
94 ["enum", 4, 1] ]
95
96
97 for [type_name, type_size, integer] in basic_types:
98 te = type_expression(None)
99 tn = type_node()
100 tn.name = type_name
101 tn.size = type_size
102 tn.integer = integer
103 te.expr.append(tn)
104 tt.add_type( te )
105
106 type_expression.built_in_types = tt
107 return
108
109
110 class type_expression:
111 built_in_types = None
112
113 def __init__(self, type_string, extra_types = None):
114 self.expr = []
115
116 if not type_string: return
117
118 self.original_string = type_string
119
120 if not type_expression.built_in_types:
121 raise RuntimeError("create_initial_types must be called before creating type_expression objects.")
122
123
124 elements = string.split( string.replace( type_string, "*", " * " ) )
125
126 const = 0
127 t = None
128 signed = 0
129 unsigned = 0
130
131 for i in elements:
132 if i == "const":
133 if t and t.pointer:
134 t.const = 1
135 else:
136 const = 1
137 elif i == "signed":
138 signed = 1
139 elif i == "unsigned":
140 unsigned = 1
141 elif i == "*":
142 # This is a quirky special-case because of the
143 # way the C works for types. If 'unsigned' is
144 # specified all by itself, it is treated the
145 # same as "unsigned int".
146
147 if unsigned:
148 self.set_base_type( "int", signed, unsigned, const, extra_types )
149 const = 0
150 signed = 0
151 unsigned = 0
152
153 if not self.expr:
154 raise RuntimeError("Invalid type expression (dangling pointer)")
155
156 if signed:
157 raise RuntimeError("Invalid type expression (signed / unsigned applied to pointer)")
158
159 t = type_node()
160 t.pointer = 1
161 self.expr.append( t )
162 else:
163 if self.expr:
164 raise RuntimeError('Invalid type expression (garbage after pointer qualifier -> "%s")' % (self.original_string))
165
166 self.set_base_type( i, signed, unsigned, const, extra_types )
167 const = 0
168 signed = 0
169 unsigned = 0
170
171 if signed and unsigned:
172 raise RuntimeError("Invalid type expression (both signed and unsigned specified)")
173
174
175 if const:
176 raise RuntimeError("Invalid type expression (dangling const)")
177
178 if unsigned:
179 raise RuntimeError("Invalid type expression (dangling signed)")
180
181 if signed:
182 raise RuntimeError("Invalid type expression (dangling unsigned)")
183
184 return
185
186
187 def set_base_type(self, type_name, signed, unsigned, const, extra_types):
188 te = type_expression.built_in_types.find_type( type_name )
189 if not te:
190 te = extra_types.find_type( type_name )
191
192 if not te:
193 raise RuntimeError('Unknown base type "%s".' % (type_name))
194
195 self.expr = copy.deepcopy(te.expr)
196
197 t = self.expr[ len(self.expr) - 1 ]
198 t.const = const
199 if signed:
200 t.signed = 1
201 elif unsigned:
202 t.signed = 0
203
204
205 def set_base_type_node(self, tn):
206 self.expr = [tn]
207 return
208
209
210 def set_elements(self, count):
211 tn = self.expr[0]
212
213 tn.elements = count
214 return
215
216
217 def string(self):
218 s = ""
219 for t in self.expr:
220 s += t.string()
221
222 return s
223
224
225 def get_base_type_node(self):
226 return self.expr[0]
227
228
229 def get_base_name(self):
230 if len(self.expr):
231 return self.expr[0].name
232 else:
233 return None
234
235
236 def get_element_size(self):
237 tn = self.expr[0]
238
239 if tn.elements:
240 return tn.elements * tn.size
241 else:
242 return tn.size
243
244
245 def get_element_count(self):
246 tn = self.expr[0]
247 return tn.elements
248
249
250 def get_stack_size(self):
251 tn = self.expr[ len(self.expr) - 1 ]
252
253 if tn.elements or tn.pointer:
254 return 4
255 elif not tn.integer:
256 return tn.size
257 else:
258 return 4
259
260
261 def is_pointer(self):
262 tn = self.expr[ len(self.expr) - 1 ]
263 return tn.pointer
264
265
266 def format_string(self):
267 tn = self.expr[ len(self.expr) - 1 ]
268 if tn.pointer:
269 return "%p"
270 elif not tn.integer:
271 return "%f"
272 else:
273 return "%d"
274
275
276
277 if __name__ == '__main__':
278
279 types_to_try = [ "int", "int *", "const int *", "int * const", "const int * const", \
280 "unsigned * const *", \
281 "float", "const double", "double * const"]
282
283 create_initial_types()
284
285 for t in types_to_try:
286 print 'Trying "%s"...' % (t)
287 te = type_expression( t )
288 print 'Got "%s" (%u, %u).' % (te.string(), te.get_stack_size(), te.get_element_size())