glapi: Move to src/mapi/.
[mesa.git] / src / mapi / glapi / gen / 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 # 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[ len(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[ len(self.expr) - 1 ]
267 return tn.pointer
268
269
270 def format_string(self):
271 tn = self.expr[ len(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())