Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 1 | #!/usr/bin/env python |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 2 | |
Ian Romanick | 5f1f229 | 2005-01-07 02:39:09 +0000 | [diff] [blame] | 3 | # (C) Copyright IBM Corporation 2004, 2005 |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 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 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 28 | import libxml2 |
| 29 | import re, sys, string |
| 30 | import typeexpr |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 31 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 32 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 33 | def parse_GL_API( file_name, factory = None ): |
| 34 | doc = libxml2.readFile( file_name, None, libxml2.XML_PARSE_XINCLUDE + libxml2.XML_PARSE_NOBLANKS + libxml2.XML_PARSE_DTDVALID + libxml2.XML_PARSE_DTDATTR + libxml2.XML_PARSE_DTDLOAD + libxml2.XML_PARSE_NOENT ) |
| 35 | ret = doc.xincludeProcess() |
| 36 | |
| 37 | if not factory: |
| 38 | factory = gl_item_factory() |
| 39 | |
| 40 | api = factory.create_item( "api", None, None ) |
| 41 | api.process_element( doc ) |
| 42 | |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 43 | # After the XML has been processed, we need to go back and assign |
| 44 | # dispatch offsets to the functions that request that their offsets |
| 45 | # be assigned by the scripts. Typically this means all functions |
| 46 | # that are not part of the ABI. |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 47 | |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 48 | for func in api.functionIterateByCategory(): |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 49 | if func.assign_offset: |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 50 | func.offset = api.next_offset; |
| 51 | api.next_offset += 1 |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 52 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 53 | doc.freeDoc() |
| 54 | |
| 55 | return api |
| 56 | |
| 57 | |
| 58 | def is_attr_true( element, name ): |
Ian Romanick | 73b4c1b | 2005-04-14 23:00:34 +0000 | [diff] [blame] | 59 | """Read a name value from an element's attributes. |
| 60 | |
| 61 | The value read from the attribute list must be either 'true' or |
| 62 | 'false'. If the value is 'false', zero will be returned. If the |
| 63 | value is 'true', non-zero will be returned. An exception will be |
| 64 | raised for any other value.""" |
| 65 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 66 | value = element.nsProp( name, None ) |
Ian Romanick | 73b4c1b | 2005-04-14 23:00:34 +0000 | [diff] [blame] | 67 | if value == "true": |
| 68 | return 1 |
| 69 | elif value == "false": |
| 70 | return 0 |
| 71 | else: |
| 72 | raise RuntimeError('Invalid value "%s" for boolean "%s".' % (value, name)) |
| 73 | |
| 74 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 75 | class gl_print_base: |
| 76 | """Base class of all API pretty-printers. |
Ian Romanick | 93d2d54 | 2005-04-18 19:42:23 +0000 | [diff] [blame] | 77 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 78 | In the model-view-controller pattern, this is the view. Any derived |
| 79 | class will want to over-ride the printBody, printRealHader, and |
| 80 | printRealFooter methods. Some derived classes may want to over-ride |
| 81 | printHeader and printFooter, or even Print (though this is unlikely). |
Ian Romanick | 93d2d54 | 2005-04-18 19:42:23 +0000 | [diff] [blame] | 82 | """ |
Ian Romanick | d03ab10 | 2005-04-18 21:30:20 +0000 | [diff] [blame] | 83 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 84 | def __init__(self): |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 85 | # Name of the script that is generating the output file. |
| 86 | # Every derived class should set this to the name of its |
| 87 | # source file. |
| 88 | |
| 89 | self.name = "a" |
| 90 | |
| 91 | |
| 92 | # License on the *generated* source file. This may differ |
| 93 | # from the license on the script that is generating the file. |
| 94 | # Every derived class should set this to some reasonable |
| 95 | # value. |
| 96 | # |
| 97 | # See license.py for an example of a reasonable value. |
| 98 | |
| 99 | self.license = "The license for this file is unspecified." |
| 100 | |
| 101 | |
| 102 | # The header_tag is the name of the C preprocessor define |
| 103 | # used to prevent multiple inclusion. Typically only |
| 104 | # generated C header files need this to be set. Setting it |
| 105 | # causes code to be generated automatically in printHeader |
| 106 | # and printFooter. |
| 107 | |
Ian Romanick | 16c3c74 | 2005-01-28 19:00:54 +0000 | [diff] [blame] | 108 | self.header_tag = None |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 109 | |
| 110 | |
| 111 | # List of file-private defines that must be undefined at the |
| 112 | # end of the file. This can be used in header files to define |
| 113 | # names for use in the file, then undefine them at the end of |
| 114 | # the header file. |
| 115 | |
Ian Romanick | c280358 | 2005-02-01 00:28:47 +0000 | [diff] [blame] | 116 | self.undef_list = [] |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 117 | return |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 118 | |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 119 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 120 | def Print(self, api): |
| 121 | self.printHeader() |
| 122 | self.printBody(api) |
| 123 | self.printFooter() |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 124 | return |
| 125 | |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 126 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 127 | def printHeader(self): |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 128 | """Print the header associated with all files and call the printRealHeader method.""" |
| 129 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 130 | print '/* DO NOT EDIT - This file generated automatically by %s script */' \ |
| 131 | % (self.name) |
| 132 | print '' |
| 133 | print '/*' |
| 134 | print ' * ' + self.license.replace('\n', '\n * ') |
| 135 | print ' */' |
| 136 | print '' |
Ian Romanick | 16c3c74 | 2005-01-28 19:00:54 +0000 | [diff] [blame] | 137 | if self.header_tag: |
| 138 | print '#if !defined( %s )' % (self.header_tag) |
| 139 | print '# define %s' % (self.header_tag) |
| 140 | print '' |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 141 | self.printRealHeader(); |
| 142 | return |
| 143 | |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 144 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 145 | def printFooter(self): |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 146 | """Print the header associated with all files and call the printRealFooter method.""" |
| 147 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 148 | self.printRealFooter() |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 149 | |
| 150 | if self.undef_list: |
| 151 | print '' |
| 152 | for u in self.undef_list: |
| 153 | print "# undef %s" % (u) |
| 154 | |
Ian Romanick | 16c3c74 | 2005-01-28 19:00:54 +0000 | [diff] [blame] | 155 | if self.header_tag: |
Ian Romanick | c280358 | 2005-02-01 00:28:47 +0000 | [diff] [blame] | 156 | print '' |
| 157 | print '#endif /* !defined( %s ) */' % (self.header_tag) |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 158 | |
| 159 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 160 | def printRealHeader(self): |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 161 | """Print the "real" header for the created file. |
| 162 | |
| 163 | In the base class, this function is empty. All derived |
| 164 | classes should over-ride this function.""" |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 165 | return |
| 166 | |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 167 | |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 168 | def printRealFooter(self): |
Ian Romanick | a9d033c | 2004-05-19 23:33:08 +0000 | [diff] [blame] | 169 | """Print the "real" footer for the created file. |
| 170 | |
| 171 | In the base class, this function is empty. All derived |
| 172 | classes should over-ride this function.""" |
Ian Romanick | 73f59b0 | 2004-05-18 18:33:40 +0000 | [diff] [blame] | 173 | return |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 174 | |
| 175 | |
| 176 | def printPure(self): |
| 177 | """Conditionally define `PURE' function attribute. |
| 178 | |
| 179 | Conditionally defines a preprocessor macro `PURE' that wraps |
| 180 | GCC's `pure' function attribute. The conditional code can be |
| 181 | easilly adapted to other compilers that support a similar |
| 182 | feature. |
| 183 | |
| 184 | The name is also added to the file's undef_list. |
| 185 | """ |
| 186 | self.undef_list.append("PURE") |
| 187 | print """# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) |
| 188 | # define PURE __attribute__((pure)) |
| 189 | # else |
| 190 | # define PURE |
| 191 | # endif""" |
| 192 | return |
| 193 | |
| 194 | |
| 195 | def printFastcall(self): |
| 196 | """Conditionally define `FASTCALL' function attribute. |
| 197 | |
| 198 | Conditionally defines a preprocessor macro `FASTCALL' that |
| 199 | wraps GCC's `fastcall' function attribute. The conditional |
| 200 | code can be easilly adapted to other compilers that support a |
| 201 | similar feature. |
| 202 | |
| 203 | The name is also added to the file's undef_list. |
| 204 | """ |
| 205 | |
| 206 | self.undef_list.append("FASTCALL") |
Brian Paul | f468dfd | 2005-10-20 22:51:50 +0000 | [diff] [blame] | 207 | print """# if defined(__i386__) && defined(__GNUC__) && !defined(__CYGWIN__) && !defined(__MINGW32__) |
| 208 | # define FASTCALL __attribute__((fastcall)) |
| 209 | # else |
| 210 | # define FASTCALL |
| 211 | # endif""" |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 212 | return |
| 213 | |
| 214 | |
| 215 | def printVisibility(self, S, s): |
| 216 | """Conditionally define visibility function attribute. |
| 217 | |
| 218 | Conditionally defines a preprocessor macro name S that wraps |
| 219 | GCC's visibility function attribute. The visibility used is |
| 220 | the parameter s. The conditional code can be easilly adapted |
| 221 | to other compilers that support a similar feature. |
| 222 | |
| 223 | The name is also added to the file's undef_list. |
| 224 | """ |
| 225 | |
| 226 | self.undef_list.append(S) |
Adam Jackson | ca1ac98 | 2005-08-26 17:50:39 +0000 | [diff] [blame] | 227 | print """# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) && defined(__ELF__) |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 228 | # define %s __attribute__((visibility("%s"))) |
| 229 | # else |
| 230 | # define %s |
| 231 | # endif""" % (S, s, S) |
| 232 | return |
| 233 | |
| 234 | |
| 235 | def printNoinline(self): |
| 236 | """Conditionally define `NOINLINE' function attribute. |
| 237 | |
| 238 | Conditionally defines a preprocessor macro `NOINLINE' that |
| 239 | wraps GCC's `noinline' function attribute. The conditional |
| 240 | code can be easilly adapted to other compilers that support a |
| 241 | similar feature. |
| 242 | |
| 243 | The name is also added to the file's undef_list. |
| 244 | """ |
| 245 | |
| 246 | self.undef_list.append("NOINLINE") |
| 247 | print """# if defined(__GNUC__) |
| 248 | # define NOINLINE __attribute__((noinline)) |
| 249 | # else |
| 250 | # define NOINLINE |
| 251 | # endif""" |
| 252 | return |
| 253 | |
| 254 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 255 | def real_function_name(element): |
| 256 | name = element.nsProp( "name", None ) |
| 257 | alias = element.nsProp( "alias", None ) |
| 258 | |
| 259 | if alias: |
| 260 | return alias |
| 261 | else: |
| 262 | return name |
| 263 | |
| 264 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 265 | def real_category_name(c): |
| 266 | if re.compile("[1-9][0-9]*[.][0-9]+").match(c): |
| 267 | return "GL_VERSION_" + c.replace(".", "_") |
| 268 | else: |
| 269 | return c |
| 270 | |
| 271 | |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 272 | def classify_category(name, number): |
| 273 | """Based on the category name and number, select a numerical class for it. |
| 274 | |
| 275 | Categories are divided into four classes numbered 0 through 3. The |
| 276 | classes are: |
| 277 | |
| 278 | 0. Core GL versions, sorted by version number. |
| 279 | 1. ARB extensions, sorted by extension number. |
| 280 | 2. Non-ARB extensions, sorted by extension number. |
| 281 | 3. Un-numbered extensions, sorted by extension name. |
| 282 | """ |
| 283 | |
| 284 | try: |
| 285 | core_version = float(name) |
| 286 | except Exception,e: |
| 287 | core_version = 0.0 |
| 288 | |
| 289 | if core_version > 0.0: |
| 290 | cat_type = 0 |
| 291 | key = name |
| 292 | elif name.startswith("GL_ARB_") or name.startswith("GLX_ARB_") or name.startswith("WGL_ARB_"): |
| 293 | cat_type = 1 |
| 294 | key = int(number) |
| 295 | else: |
| 296 | if number != None: |
| 297 | cat_type = 2 |
| 298 | key = int(number) |
| 299 | else: |
| 300 | cat_type = 3 |
| 301 | key = name |
| 302 | |
| 303 | |
| 304 | return [cat_type, key] |
| 305 | |
| 306 | |
Ian Romanick | f0ff50d | 2005-07-02 08:29:57 +0000 | [diff] [blame] | 307 | def create_parameter_string(parameters, include_names): |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 308 | """Create a parameter string from a list of gl_parameters.""" |
| 309 | |
| 310 | list = [] |
| 311 | for p in parameters: |
Ian Romanick | 0f73302 | 2008-12-09 14:43:09 -0800 | [diff] [blame] | 312 | if p.is_padding: |
| 313 | continue |
| 314 | |
Ian Romanick | f0ff50d | 2005-07-02 08:29:57 +0000 | [diff] [blame] | 315 | if include_names: |
| 316 | list.append( p.string() ) |
| 317 | else: |
| 318 | list.append( p.type_string() ) |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 319 | |
| 320 | if len(list) == 0: list = ["void"] |
| 321 | |
| 322 | return string.join(list, ", ") |
| 323 | |
| 324 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 325 | class gl_item: |
| 326 | def __init__(self, element, context): |
| 327 | self.context = context |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 328 | self.name = element.nsProp( "name", None ) |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 329 | self.category = real_category_name( element.parent.nsProp( "name", None ) ) |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 330 | return |
| 331 | |
| 332 | |
| 333 | class gl_type( gl_item ): |
| 334 | def __init__(self, element, context): |
| 335 | gl_item.__init__(self, element, context) |
| 336 | self.size = int( element.nsProp( "size", None ), 0 ) |
| 337 | |
| 338 | te = typeexpr.type_expression( None ) |
| 339 | tn = typeexpr.type_node() |
| 340 | tn.size = int( element.nsProp( "size", None ), 0 ) |
| 341 | tn.integer = not is_attr_true( element, "float" ) |
| 342 | tn.unsigned = is_attr_true( element, "unsigned" ) |
| 343 | tn.name = "GL" + self.name |
| 344 | te.set_base_type_node( tn ) |
| 345 | |
| 346 | self.type_expr = te |
| 347 | return |
| 348 | |
| 349 | |
| 350 | def get_type_expression(self): |
| 351 | return self.type_expr |
| 352 | |
| 353 | |
| 354 | class gl_enum( gl_item ): |
| 355 | def __init__(self, element, context): |
| 356 | gl_item.__init__(self, element, context) |
| 357 | self.value = int( element.nsProp( "value", None ), 0 ) |
| 358 | |
| 359 | temp = element.nsProp( "count", None ) |
| 360 | if not temp or temp == "?": |
| 361 | self.default_count = -1 |
| 362 | else: |
| 363 | try: |
| 364 | c = int(temp) |
| 365 | except Exception,e: |
| 366 | raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n)) |
| 367 | |
| 368 | self.default_count = c |
| 369 | |
| 370 | return |
| 371 | |
| 372 | |
| 373 | def priority(self): |
| 374 | """Calculate a 'priority' for this enum name. |
| 375 | |
| 376 | When an enum is looked up by number, there may be many |
| 377 | possible names, but only one is the 'prefered' name. The |
| 378 | priority is used to select which name is the 'best'. |
| 379 | |
| 380 | Highest precedence is given to core GL name. ARB extension |
| 381 | names have the next highest, followed by EXT extension names. |
| 382 | Vendor extension names are the lowest. |
| 383 | """ |
| 384 | |
| 385 | if self.name.endswith( "_BIT" ): |
| 386 | bias = 1 |
| 387 | else: |
| 388 | bias = 0 |
| 389 | |
| 390 | if self.category.startswith( "GL_VERSION_" ): |
| 391 | priority = 0 |
| 392 | elif self.category.startswith( "GL_ARB_" ): |
| 393 | priority = 2 |
| 394 | elif self.category.startswith( "GL_EXT_" ): |
| 395 | priority = 4 |
| 396 | else: |
| 397 | priority = 6 |
| 398 | |
| 399 | return priority + bias |
| 400 | |
| 401 | |
| 402 | |
| 403 | class gl_parameter: |
| 404 | def __init__(self, element, context): |
| 405 | self.name = element.nsProp( "name", None ) |
| 406 | |
| 407 | ts = element.nsProp( "type", None ) |
| 408 | self.type_expr = typeexpr.type_expression( ts, context ) |
| 409 | |
| 410 | temp = element.nsProp( "variable_param", None ) |
| 411 | if temp: |
| 412 | self.count_parameter_list = temp.split( ' ' ) |
| 413 | else: |
| 414 | self.count_parameter_list = [] |
| 415 | |
| 416 | # The count tag can be either a numeric string or the name of |
| 417 | # a variable. If it is the name of a variable, the int(c) |
| 418 | # statement will throw an exception, and the except block will |
| 419 | # take over. |
| 420 | |
| 421 | c = element.nsProp( "count", None ) |
| 422 | try: |
| 423 | count = int(c) |
| 424 | self.count = count |
| 425 | self.counter = None |
| 426 | except Exception,e: |
| 427 | count = 1 |
| 428 | self.count = 0 |
| 429 | self.counter = c |
| 430 | |
| 431 | self.count_scale = int(element.nsProp( "count_scale", None )) |
| 432 | |
| 433 | elements = (count * self.count_scale) |
| 434 | if elements == 1: |
| 435 | elements = 0 |
| 436 | |
| 437 | #if ts == "GLdouble": |
| 438 | # print '/* stack size -> %s = %u (before)*/' % (self.name, self.type_expr.get_stack_size()) |
| 439 | # print '/* # elements = %u */' % (elements) |
| 440 | self.type_expr.set_elements( elements ) |
| 441 | #if ts == "GLdouble": |
| 442 | # print '/* stack size -> %s = %u (after) */' % (self.name, self.type_expr.get_stack_size()) |
| 443 | |
Brian Paul | 9540c9c | 2006-11-22 16:01:48 +0000 | [diff] [blame] | 444 | self.is_client_only = is_attr_true( element, 'client_only' ) |
| 445 | self.is_counter = is_attr_true( element, 'counter' ) |
| 446 | self.is_output = is_attr_true( element, 'output' ) |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 447 | |
| 448 | |
| 449 | # Pixel data has special parameters. |
| 450 | |
| 451 | self.width = element.nsProp('img_width', None) |
| 452 | self.height = element.nsProp('img_height', None) |
| 453 | self.depth = element.nsProp('img_depth', None) |
| 454 | self.extent = element.nsProp('img_extent', None) |
| 455 | |
| 456 | self.img_xoff = element.nsProp('img_xoff', None) |
| 457 | self.img_yoff = element.nsProp('img_yoff', None) |
| 458 | self.img_zoff = element.nsProp('img_zoff', None) |
| 459 | self.img_woff = element.nsProp('img_woff', None) |
| 460 | |
| 461 | self.img_format = element.nsProp('img_format', None) |
| 462 | self.img_type = element.nsProp('img_type', None) |
| 463 | self.img_target = element.nsProp('img_target', None) |
| 464 | |
| 465 | self.img_pad_dimensions = is_attr_true( element, 'img_pad_dimensions' ) |
| 466 | self.img_null_flag = is_attr_true( element, 'img_null_flag' ) |
| 467 | self.img_send_null = is_attr_true( element, 'img_send_null' ) |
| 468 | |
Ian Romanick | 0f73302 | 2008-12-09 14:43:09 -0800 | [diff] [blame] | 469 | self.is_padding = is_attr_true( element, 'padding' ) |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 470 | return |
| 471 | |
| 472 | |
| 473 | def compatible(self, other): |
| 474 | return 1 |
| 475 | |
| 476 | |
| 477 | def is_array(self): |
| 478 | return self.is_pointer() |
| 479 | |
| 480 | |
| 481 | def is_pointer(self): |
| 482 | return self.type_expr.is_pointer() |
| 483 | |
| 484 | |
| 485 | def is_image(self): |
| 486 | if self.width: |
| 487 | return 1 |
| 488 | else: |
| 489 | return 0 |
| 490 | |
| 491 | |
| 492 | def is_variable_length(self): |
| 493 | return len(self.count_parameter_list) or self.counter |
| 494 | |
| 495 | |
| 496 | def is_64_bit(self): |
| 497 | count = self.type_expr.get_element_count() |
| 498 | if count: |
| 499 | if (self.size() / count) == 8: |
| 500 | return 1 |
| 501 | else: |
| 502 | if self.size() == 8: |
| 503 | return 1 |
| 504 | |
| 505 | return 0 |
| 506 | |
| 507 | |
| 508 | def string(self): |
| 509 | return self.type_expr.original_string + " " + self.name |
| 510 | |
| 511 | |
| 512 | def type_string(self): |
| 513 | return self.type_expr.original_string |
| 514 | |
| 515 | |
| 516 | def get_base_type_string(self): |
| 517 | return self.type_expr.get_base_name() |
| 518 | |
| 519 | |
| 520 | def get_dimensions(self): |
| 521 | if not self.width: |
| 522 | return [ 0, "0", "0", "0", "0" ] |
| 523 | |
| 524 | dim = 1 |
| 525 | w = self.width |
| 526 | h = "1" |
| 527 | d = "1" |
| 528 | e = "1" |
| 529 | |
| 530 | if self.height: |
| 531 | dim = 2 |
| 532 | h = self.height |
| 533 | |
| 534 | if self.depth: |
| 535 | dim = 3 |
| 536 | d = self.depth |
| 537 | |
| 538 | if self.extent: |
| 539 | dim = 4 |
| 540 | e = self.extent |
| 541 | |
| 542 | return [ dim, w, h, d, e ] |
| 543 | |
| 544 | |
| 545 | def get_stack_size(self): |
| 546 | return self.type_expr.get_stack_size() |
| 547 | |
| 548 | |
| 549 | def size(self): |
| 550 | if self.is_image(): |
| 551 | return 0 |
| 552 | else: |
| 553 | return self.type_expr.get_element_size() |
| 554 | |
| 555 | |
| 556 | def get_element_count(self): |
| 557 | c = self.type_expr.get_element_count() |
| 558 | if c == 0: |
| 559 | return 1 |
| 560 | |
| 561 | return c |
| 562 | |
| 563 | |
| 564 | def size_string(self, use_parens = 1): |
| 565 | s = self.size() |
| 566 | if self.counter or self.count_parameter_list: |
| 567 | list = [ "compsize" ] |
| 568 | |
| 569 | if self.counter and self.count_parameter_list: |
| 570 | list.append( self.counter ) |
| 571 | elif self.counter: |
| 572 | list = [ self.counter ] |
| 573 | |
| 574 | if s > 1: |
| 575 | list.append( str(s) ) |
| 576 | |
| 577 | if len(list) > 1 and use_parens : |
| 578 | return "(%s)" % (string.join(list, " * ")) |
| 579 | else: |
| 580 | return string.join(list, " * ") |
| 581 | |
| 582 | elif self.is_image(): |
| 583 | return "compsize" |
| 584 | else: |
| 585 | return str(s) |
| 586 | |
| 587 | |
| 588 | def format_string(self): |
| 589 | if self.type_expr.original_string == "GLenum": |
| 590 | return "0x%x" |
| 591 | else: |
| 592 | return self.type_expr.format_string() |
| 593 | |
| 594 | |
| 595 | |
| 596 | class gl_function( gl_item ): |
| 597 | def __init__(self, element, context): |
| 598 | self.context = context |
| 599 | self.name = None |
| 600 | |
| 601 | self.entry_points = [] |
| 602 | self.return_type = "void" |
| 603 | self.parameters = [] |
| 604 | self.offset = -1 |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 605 | self.initialized = 0 |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 606 | self.images = [] |
| 607 | |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 608 | self.assign_offset = 0 |
| 609 | |
Ian Romanick | 7e9737b | 2006-08-26 21:26:55 +0000 | [diff] [blame] | 610 | self.static_entry_points = [] |
| 611 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 612 | # Track the parameter string (for the function prototype) |
| 613 | # for each entry-point. This is done because some functions |
| 614 | # change their prototype slightly when promoted from extension |
| 615 | # to ARB extension to core. glTexImage3DEXT and glTexImage3D |
| 616 | # are good examples of this. Scripts that need to generate |
| 617 | # code for these differing aliases need to real prototype |
| 618 | # for each entry-point. Otherwise, they may generate code |
| 619 | # that won't compile. |
| 620 | |
| 621 | self.parameter_strings = {} |
| 622 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 623 | self.process_element( element ) |
| 624 | |
| 625 | return |
| 626 | |
| 627 | |
| 628 | def process_element(self, element): |
| 629 | name = element.nsProp( "name", None ) |
| 630 | alias = element.nsProp( "alias", None ) |
| 631 | |
Ian Romanick | 7e9737b | 2006-08-26 21:26:55 +0000 | [diff] [blame] | 632 | if is_attr_true(element, "static_dispatch"): |
| 633 | self.static_entry_points.append(name) |
Ian Romanick | 4e4b5f4 | 2006-08-22 16:34:38 +0000 | [diff] [blame] | 634 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 635 | self.entry_points.append( name ) |
| 636 | if alias: |
| 637 | true_name = alias |
| 638 | else: |
| 639 | true_name = name |
| 640 | |
| 641 | # Only try to set the offset when a non-alias |
| 642 | # entry-point is being processes. |
| 643 | |
| 644 | offset = element.nsProp( "offset", None ) |
| 645 | if offset: |
| 646 | try: |
| 647 | o = int( offset ) |
| 648 | self.offset = o |
| 649 | except Exception, e: |
| 650 | self.offset = -1 |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 651 | if offset == "assign": |
| 652 | self.assign_offset = 1 |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 653 | |
| 654 | |
| 655 | if not self.name: |
| 656 | self.name = true_name |
| 657 | elif self.name != true_name: |
| 658 | raise RuntimeError("Function true name redefined. Was %s, now %s." % (self.name, true_name)) |
| 659 | |
| 660 | |
| 661 | # There are two possible cases. The first time an entry-point |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 662 | # with data is seen, self.initialized will be 0. On that |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 663 | # pass, we just fill in the data. The next time an |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 664 | # entry-point with data is seen, self.initialized will be 1. |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 665 | # On that pass we have to make that the new values match the |
| 666 | # valuse from the previous entry-point. |
| 667 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 668 | parameters = [] |
| 669 | return_type = "void" |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 670 | child = element.children |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 671 | while child: |
| 672 | if child.type == "element": |
| 673 | if child.name == "return": |
| 674 | return_type = child.nsProp( "type", None ) |
| 675 | elif child.name == "param": |
| 676 | param = self.context.factory.create_item( "parameter", child, self.context) |
| 677 | parameters.append( param ) |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 678 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 679 | child = child.next |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 680 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 681 | |
| 682 | if self.initialized: |
| 683 | if self.return_type != return_type: |
| 684 | raise RuntimeError( "Return type changed in %s. Was %s, now %s." % (name, self.return_type, return_type)) |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 685 | |
| 686 | if len(parameters) != len(self.parameters): |
| 687 | raise RuntimeError( "Parameter count mismatch in %s. Was %d, now %d." % (name, len(self.parameters), len(parameters))) |
| 688 | |
| 689 | for j in range(0, len(parameters)): |
| 690 | p1 = parameters[j] |
| 691 | p2 = self.parameters[j] |
| 692 | if not p1.compatible( p2 ): |
| 693 | raise RuntimeError( 'Parameter type mismatch in %s. "%s" was "%s", now "%s".' % (name, p2.name, p2.type_expr.original_string, p1.type_expr.original_string)) |
| 694 | |
| 695 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 696 | if true_name == name or not self.initialized: |
| 697 | self.return_type = return_type |
| 698 | self.parameters = parameters |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 699 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 700 | for param in self.parameters: |
| 701 | if param.is_image(): |
| 702 | self.images.append( param ) |
| 703 | |
| 704 | if element.children: |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 705 | self.initialized = 1 |
Ian Romanick | f0ff50d | 2005-07-02 08:29:57 +0000 | [diff] [blame] | 706 | self.parameter_strings[name] = create_parameter_string(parameters, 1) |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 707 | else: |
| 708 | self.parameter_strings[name] = None |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 709 | |
| 710 | return |
| 711 | |
| 712 | |
| 713 | def get_images(self): |
| 714 | """Return potentially empty list of input images.""" |
| 715 | return self.images |
| 716 | |
| 717 | |
| 718 | def parameterIterator(self): |
| 719 | return self.parameters.__iter__(); |
| 720 | |
| 721 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 722 | def get_parameter_string(self, entrypoint = None): |
| 723 | if entrypoint: |
| 724 | s = self.parameter_strings[ entrypoint ] |
| 725 | if s: |
| 726 | return s |
| 727 | |
Ian Romanick | f0ff50d | 2005-07-02 08:29:57 +0000 | [diff] [blame] | 728 | return create_parameter_string( self.parameters, 1 ) |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 729 | |
Ian Romanick | f3f51bc | 2006-10-11 22:37:14 +0000 | [diff] [blame] | 730 | def get_called_parameter_string(self): |
| 731 | p_string = "" |
| 732 | comma = "" |
| 733 | |
| 734 | for p in self.parameterIterator(): |
| 735 | p_string = p_string + comma + p.name |
| 736 | comma = ", " |
| 737 | |
| 738 | return p_string |
| 739 | |
| 740 | |
Chia-I Wu | 6418f83 | 2009-10-20 14:32:39 +0800 | [diff] [blame] | 741 | def is_abi(self): |
| 742 | return (self.offset >= 0 and not self.assign_offset) |
| 743 | |
Ian Romanick | 7e9737b | 2006-08-26 21:26:55 +0000 | [diff] [blame] | 744 | def is_static_entry_point(self, name): |
| 745 | return name in self.static_entry_points |
| 746 | |
Ian Romanick | 258751f | 2006-08-28 17:40:45 +0000 | [diff] [blame] | 747 | def dispatch_name(self): |
| 748 | if self.name in self.static_entry_points: |
| 749 | return self.name |
| 750 | else: |
| 751 | return "_dispatch_stub_%u" % (self.offset) |
| 752 | |
| 753 | def static_name(self, name): |
| 754 | if name in self.static_entry_points: |
| 755 | return name |
| 756 | else: |
| 757 | return "_dispatch_stub_%u" % (self.offset) |
| 758 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 759 | |
| 760 | class gl_item_factory: |
| 761 | """Factory to create objects derived from gl_item.""" |
| 762 | |
| 763 | def create_item(self, item_name, element, context): |
| 764 | if item_name == "function": |
| 765 | return gl_function(element, context) |
| 766 | if item_name == "type": |
| 767 | return gl_type(element, context) |
| 768 | elif item_name == "enum": |
| 769 | return gl_enum(element, context) |
| 770 | elif item_name == "parameter": |
| 771 | return gl_parameter(element, context) |
| 772 | elif item_name == "api": |
| 773 | return gl_api(self) |
| 774 | else: |
| 775 | return None |
| 776 | |
| 777 | |
| 778 | class gl_api: |
| 779 | def __init__(self, factory): |
| 780 | self.functions_by_name = {} |
| 781 | self.enums_by_name = {} |
| 782 | self.types_by_name = {} |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 783 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 784 | self.category_dict = {} |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 785 | self.categories = [{}, {}, {}, {}] |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 786 | |
| 787 | self.factory = factory |
| 788 | |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 789 | self.next_offset = 0 |
| 790 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 791 | typeexpr.create_initial_types() |
| 792 | return |
| 793 | |
| 794 | |
| 795 | def process_element(self, doc): |
| 796 | element = doc.children |
| 797 | while element.type != "element" or element.name != "OpenGLAPI": |
| 798 | element = element.next |
| 799 | |
| 800 | if element: |
| 801 | self.process_OpenGLAPI(element) |
| 802 | return |
| 803 | |
| 804 | |
| 805 | def process_OpenGLAPI(self, element): |
| 806 | child = element.children |
| 807 | while child: |
| 808 | if child.type == "element": |
| 809 | if child.name == "category": |
| 810 | self.process_category( child ) |
| 811 | elif child.name == "OpenGLAPI": |
| 812 | self.process_OpenGLAPI( child ) |
| 813 | |
| 814 | child = child.next |
| 815 | |
| 816 | return |
| 817 | |
| 818 | |
| 819 | def process_category(self, cat): |
| 820 | cat_name = cat.nsProp( "name", None ) |
| 821 | cat_number = cat.nsProp( "number", None ) |
| 822 | |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 823 | [cat_type, key] = classify_category(cat_name, cat_number) |
| 824 | self.categories[cat_type][key] = [cat_name, cat_number] |
| 825 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 826 | child = cat.children |
| 827 | while child: |
| 828 | if child.type == "element": |
| 829 | if child.name == "function": |
| 830 | func_name = real_function_name( child ) |
| 831 | |
Ian Romanick | 5aafea0 | 2005-06-24 18:35:31 +0000 | [diff] [blame] | 832 | temp_name = child.nsProp( "name", None ) |
| 833 | self.category_dict[ temp_name ] = [cat_name, cat_number] |
| 834 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 835 | if self.functions_by_name.has_key( func_name ): |
| 836 | func = self.functions_by_name[ func_name ] |
| 837 | func.process_element( child ) |
| 838 | else: |
| 839 | func = self.factory.create_item( "function", child, self ) |
| 840 | self.functions_by_name[ func_name ] = func |
| 841 | |
Ian Romanick | bf83e65 | 2006-08-24 20:14:45 +0000 | [diff] [blame] | 842 | if func.offset >= self.next_offset: |
| 843 | self.next_offset = func.offset + 1 |
| 844 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 845 | |
| 846 | elif child.name == "enum": |
| 847 | enum = self.factory.create_item( "enum", child, self ) |
| 848 | self.enums_by_name[ enum.name ] = enum |
| 849 | elif child.name == "type": |
| 850 | t = self.factory.create_item( "type", child, self ) |
| 851 | self.types_by_name[ "GL" + t.name ] = t |
| 852 | |
| 853 | |
| 854 | child = child.next |
| 855 | |
| 856 | return |
| 857 | |
| 858 | |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 859 | def functionIterateByCategory(self, cat = None): |
| 860 | """Iterate over functions by category. |
| 861 | |
| 862 | If cat is None, all known functions are iterated in category |
| 863 | order. See classify_category for details of the ordering. |
| 864 | Within a category, functions are sorted by name. If cat is |
| 865 | not None, then only functions in that category are iterated. |
| 866 | """ |
| 867 | lists = [{}, {}, {}, {}] |
| 868 | |
| 869 | for func in self.functionIterateAll(): |
| 870 | [cat_name, cat_number] = self.category_dict[func.name] |
| 871 | |
| 872 | if (cat == None) or (cat == cat_name): |
| 873 | [func_cat_type, key] = classify_category(cat_name, cat_number) |
| 874 | |
| 875 | if not lists[func_cat_type].has_key(key): |
| 876 | lists[func_cat_type][key] = {} |
| 877 | |
| 878 | lists[func_cat_type][key][func.name] = func |
| 879 | |
| 880 | |
| 881 | functions = [] |
| 882 | for func_cat_type in range(0,4): |
| 883 | keys = lists[func_cat_type].keys() |
| 884 | keys.sort() |
| 885 | |
| 886 | for key in keys: |
| 887 | names = lists[func_cat_type][key].keys() |
| 888 | names.sort() |
| 889 | |
| 890 | for name in names: |
| 891 | functions.append(lists[func_cat_type][key][name]) |
| 892 | |
| 893 | return functions.__iter__() |
| 894 | |
| 895 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 896 | def functionIterateByOffset(self): |
| 897 | max_offset = -1 |
| 898 | for func in self.functions_by_name.itervalues(): |
| 899 | if func.offset > max_offset: |
| 900 | max_offset = func.offset |
| 901 | |
| 902 | |
| 903 | temp = [None for i in range(0, max_offset + 1)] |
| 904 | for func in self.functions_by_name.itervalues(): |
| 905 | if func.offset != -1: |
| 906 | temp[ func.offset ] = func |
| 907 | |
| 908 | |
| 909 | list = [] |
| 910 | for i in range(0, max_offset + 1): |
| 911 | if temp[i]: |
| 912 | list.append(temp[i]) |
| 913 | |
| 914 | return list.__iter__(); |
| 915 | |
| 916 | |
| 917 | def functionIterateAll(self): |
| 918 | return self.functions_by_name.itervalues() |
| 919 | |
| 920 | |
| 921 | def enumIterateByName(self): |
| 922 | keys = self.enums_by_name.keys() |
| 923 | keys.sort() |
| 924 | |
| 925 | list = [] |
| 926 | for enum in keys: |
| 927 | list.append( self.enums_by_name[ enum ] ) |
| 928 | |
| 929 | return list.__iter__() |
| 930 | |
| 931 | |
Ian Romanick | eaeaaf6 | 2006-10-04 20:45:59 +0000 | [diff] [blame] | 932 | def categoryIterate(self): |
| 933 | """Iterate over categories. |
| 934 | |
| 935 | Iterate over all known categories in the order specified by |
| 936 | classify_category. Each iterated value is a tuple of the |
| 937 | name and number (which may be None) of the category. |
| 938 | """ |
| 939 | |
| 940 | list = [] |
| 941 | for cat_type in range(0,4): |
| 942 | keys = self.categories[cat_type].keys() |
| 943 | keys.sort() |
| 944 | |
| 945 | for key in keys: |
| 946 | list.append(self.categories[cat_type][key]) |
| 947 | |
| 948 | return list.__iter__() |
| 949 | |
| 950 | |
Ian Romanick | 66a5548 | 2005-06-21 23:42:43 +0000 | [diff] [blame] | 951 | def get_category_for_name( self, name ): |
| 952 | if self.category_dict.has_key(name): |
| 953 | return self.category_dict[name] |
| 954 | else: |
| 955 | return ["<unknown category>", None] |
| 956 | |
| 957 | |
| 958 | def typeIterate(self): |
| 959 | return self.types_by_name.itervalues() |
| 960 | |
| 961 | |
| 962 | def find_type( self, type_name ): |
| 963 | if type_name in self.types_by_name: |
| 964 | return self.types_by_name[ type_name ].type_expr |
| 965 | else: |
| 966 | print "Unable to find base type matching \"%s\"." % (type_name) |
| 967 | return None |