Home | History | Annotate | Download | only in gen
      1 #!/usr/bin/python2
      2 # -*- Mode: Python; py-indent-offset: 8 -*-
      3 
      4 # (C) Copyright Zack Rusin 2005
      5 # All Rights Reserved.
      6 # 
      7 # Permission is hereby granted, free of charge, to any person obtaining a
      8 # copy of this software and associated documentation files (the "Software"),
      9 # to deal in the Software without restriction, including without limitation
     10 # on the rights to use, copy, modify, merge, publish, distribute, sub
     11 # license, and/or sell copies of the Software, and to permit persons to whom
     12 # the Software is furnished to do so, subject to the following conditions:
     13 #
     14 # The above copyright notice and this permission notice (including the next
     15 # paragraph) shall be included in all copies or substantial portions of the
     16 # Software.
     17 #
     18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20 # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
     21 # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     22 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     23 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     24 # IN THE SOFTWARE.
     25 #
     26 # Authors:
     27 #    Zack Rusin <zack (at] kde.org>
     28 
     29 import license
     30 import gl_XML
     31 import sys, getopt
     32 
     33 class PrintGlEnums(gl_XML.gl_print_base):
     34 
     35 	def __init__(self):
     36 		gl_XML.gl_print_base.__init__(self)
     37 
     38 		self.name = "gl_enums.py (from Mesa)"
     39 		self.license = license.bsd_license_template % ( \
     40 """Copyright (C) 1999-2005 Brian Paul All Rights Reserved.""", "BRIAN PAUL")
     41 		self.enum_table = {}
     42 
     43 
     44 	def printRealHeader(self):
     45 		print '#include "main/glheader.h"'
     46 		print '#include "main/mfeatures.h"'
     47 		print '#include "main/enums.h"'
     48 		print '#include "main/imports.h"'
     49 		print '#include "main/mtypes.h"'
     50 		print ''
     51 		print 'typedef struct {'
     52 		print '   size_t offset;'
     53 		print '   int n;'
     54 		print '} enum_elt;'
     55 		print ''
     56 		return
     57 
     58 	def print_code(self):
     59 		print """
     60 typedef int (*cfunc)(const void *, const void *);
     61 
     62 /**
     63  * Compare a key name to an element in the \c all_enums array.
     64  *
     65  * \c bsearch always passes the key as the first parameter and the pointer
     66  * to the array element as the second parameter.  We can elimiate some
     67  * extra work by taking advantage of that fact.
     68  *
     69  * \param a  Pointer to the desired enum name.
     70  * \param b  Pointer to an element of the \c all_enums array.
     71  */
     72 static int compar_name( const char *a, const enum_elt *b )
     73 {
     74    return strcmp( a, & enum_string_table[ b->offset ] );
     75 }
     76 
     77 /**
     78  * Compare a key enum value to an element in the \c all_enums array.
     79  *
     80  * \c bsearch always passes the key as the first parameter and the pointer
     81  * to the array element as the second parameter.  We can elimiate some
     82  * extra work by taking advantage of that fact.
     83  *
     84  * \param a  Pointer to the desired enum name.
     85  * \param b  Pointer to an index into the \c all_enums array.
     86  */
     87 static int compar_nr( const int *a, const unsigned *b )
     88 {
     89    return a[0] - all_enums[*b].n;
     90 }
     91 
     92 
     93 static char token_tmp[20];
     94 
     95 const char *_mesa_lookup_enum_by_nr( int nr )
     96 {
     97    unsigned * i;
     98 
     99    i = (unsigned *) _mesa_bsearch(& nr, reduced_enums,
    100                                   Elements(reduced_enums),
    101                                   sizeof(reduced_enums[0]),
    102                                   (cfunc) compar_nr);
    103 
    104    if ( i != NULL ) {
    105       return & enum_string_table[ all_enums[ *i ].offset ];
    106    }
    107    else {
    108       /* this is not re-entrant safe, no big deal here */
    109       _mesa_snprintf(token_tmp, sizeof(token_tmp) - 1, "0x%x", nr);
    110       token_tmp[sizeof(token_tmp) - 1] = '\\0';
    111       return token_tmp;
    112    }
    113 }
    114 
    115 /**
    116  * Primitive names
    117  */
    118 static const char *prim_names[PRIM_UNKNOWN + 1] = {
    119    "GL_POINTS",
    120    "GL_LINES",
    121    "GL_LINE_LOOP",
    122    "GL_LINE_STRIP",
    123    "GL_TRIANGLES",
    124    "GL_TRIANGLE_STRIP",
    125    "GL_TRIANGLE_FAN",
    126    "GL_QUADS",
    127    "GL_QUAD_STRIP",
    128    "GL_POLYGON",
    129    "outside begin/end",
    130    "inside unknown primitive",
    131    "unknown state"
    132 };
    133 
    134 
    135 /* Get the name of an enum given that it is a primitive type.  Avoids
    136  * GL_FALSE/GL_POINTS ambiguity and others.
    137  */
    138 const char *
    139 _mesa_lookup_prim_by_nr(GLuint nr)
    140 {
    141    if (nr < Elements(prim_names))
    142       return prim_names[nr];
    143    else
    144       return "invalid mode";
    145 }
    146 
    147 
    148 int _mesa_lookup_enum_by_name( const char *symbol )
    149 {
    150    enum_elt * f = NULL;
    151 
    152    if ( symbol != NULL ) {
    153       f = (enum_elt *) _mesa_bsearch(symbol, all_enums,
    154                                      Elements(all_enums),
    155                                      sizeof( enum_elt ),
    156                                      (cfunc) compar_name);
    157    }
    158 
    159    return (f != NULL) ? f->n : -1;
    160 }
    161 
    162 """
    163 		return
    164 
    165 
    166 	def printBody(self, api_list):
    167 		self.enum_table = {}
    168 		for api in api_list:
    169 			self.process_enums( api )
    170 
    171 		keys = self.enum_table.keys()
    172 		keys.sort()
    173 
    174 		name_table = []
    175 		enum_table = {}
    176 
    177 		for enum in keys:
    178 			low_pri = 9
    179 			for [name, pri] in self.enum_table[ enum ]:
    180 				name_table.append( [name, enum] )
    181 
    182 				if pri < low_pri:
    183 					low_pri = pri
    184 					enum_table[enum] = name
    185 						
    186 
    187 		name_table.sort()
    188 
    189 		string_offsets = {}
    190 		i = 0;
    191 		print 'LONGSTRING static const char enum_string_table[] = '
    192 		for [name, enum] in name_table:
    193 			print '   "%s\\0"' % (name)
    194 			string_offsets[ name ] = i
    195 			i += len(name) + 1
    196 
    197 		print '   ;'
    198 		print ''
    199 
    200 
    201 		print 'static const enum_elt all_enums[%u] =' % (len(name_table))
    202 		print '{'
    203 		for [name, enum] in name_table:
    204 			print '   { %5u, 0x%08X }, /* %s */' % (string_offsets[name], enum, name)
    205 		print '};'
    206 		print ''
    207 
    208 		print 'static const unsigned reduced_enums[%u] =' % (len(keys))
    209 		print '{'
    210 		for enum in keys:
    211 			name = enum_table[ enum ]
    212 			if [name, enum] not in name_table:
    213 				print '      /* Error! %s, 0x%04x */ 0,' % (name, enum)
    214 			else:
    215 				i = name_table.index( [name, enum] )
    216 
    217 				print '      %4u, /* %s */' % (i, name)
    218 		print '};'
    219 
    220 
    221 		self.print_code()
    222 		return
    223 
    224 
    225 	def process_enums(self, api):
    226 		for obj in api.enumIterateByName():
    227 			if obj.value not in self.enum_table:
    228 				self.enum_table[ obj.value ] = []
    229 
    230 
    231 			enum = self.enum_table[ obj.value ]
    232 			name = "GL_" + obj.name
    233 			priority = obj.priority()
    234 			already_in = False;
    235 			for n, p in enum:
    236 				if n == name:
    237 					already_in = True
    238 			if not already_in:
    239 				enum.append( [name, priority] )
    240 
    241 
    242 def show_usage():
    243 	print "Usage: %s [-f input_file_name]" % sys.argv[0]
    244 	sys.exit(1)
    245 
    246 if __name__ == '__main__':
    247 	try:
    248 		(args, trail) = getopt.getopt(sys.argv[1:], "f:")
    249 	except Exception,e:
    250 		show_usage()
    251 
    252 	api_list = []
    253 	for (arg,val) in args:
    254 		if arg == "-f":
    255 			api = gl_XML.parse_GL_API( val )
    256 			api_list.append(api);
    257 
    258 	printer = PrintGlEnums()
    259 	printer.Print( api_list )
    260