1#! /usr/bin/perl -w 2 3# This file generates three source files required to build sage 4# This first part of this file extracts the extension names, the #defines 5# and the function names. This process also creates a cutsom glext.h file 6# for use in sage The remaining parts of the file write the header and 7# code file. 8 9# Input Filenames 10$GLEXT_FILE="glext.h"; 11# Output Filenames 12$GLEXT_SAGE_FILE="sage/sage_fptr.h"; 13$SAGE_HEADER_FILE="sage/sage.h"; 14$SAGE_CODE_FILE="sage/sage.c"; 15$LICENSE_FILE="templates/license"; 16 17#regular expressions 18$FUNCTION_REGEXP="([A-Za-z*]*) APIENTRY ([a-zA-Z0-9]*) (.*)"; 19$DEFINE_REGEXP="\#define (GL_[A-Za-z0-9_]*) 1\$"; 20$VERSION_REGEXP="\#ifndef (GL_[A-Za-z0-9_]*)"; 21$TOKEN_REGEXP="\#define (GL_[A-Za-z0-9_]*)[ \t]*((0x[0-9A-F]*)\|(GL_.*))\$"; 22$TYPES_REGEXP="typedef ([ A-Za-z0-9_*]*)[ \t]*(GL[A-Za-z0-9_]*);"; 23 24#flag checking whether we need to add an endif or not 25$WAIT_FOR_ENDIF="false"; 26 27# Open glext.h for input 28open (GLEXT, "<$GLEXT_FILE") or die "Cannot open $GLEXT_FILE\n"; 29#loop through every line in glext.h 30while (<GLEXT>) { 31 if ($_ =~ m|$VERSION_REGEXP|) { 32 push(@FUNCTION_HEADER_DEF, $_); # write into header 33 $WAIT_FOR_ENDIF="true"; # we now need to write a corresponding endif when its next found 34 } elsif ($_ =~ m|$TYPES_REGEXP|) { 35 push(@FUNCTION_HEADER_DEF, $_); # write into header 36 $WAIT_FOR_ENDIF="true"; # we now need to write a corresponding endif when its next found 37 } elsif ($_ =~ m|$FUNCTION_REGEXP|) { 38 ($RET, $FUNCTION, $ARGS) = ($_ =~ m|$FUNCTION_REGEXP|); # Extract function name 39 $PFN_FUNCTION = "SAGE_PFN".uc($FUNCTION)."PROC"; # make the typedef name 40 push(@TYPEDEFS, "typedef $RET (APIENTRYP $PFN_FUNCTION) $ARGS\n"); 41 42 push(@FUNCTION_HEADER_FPTR , "SAGEAPI $PFN_FUNCTION SAGE_$FUNCTION;\n"); # declare function for header 43 push(@FUNCTION_HEADER_DEF, "#ifndef $FUNCTION\n"); 44 push(@FUNCTION_HEADER_DEF, "#define $FUNCTION SAGE_$FUNCTION\n"); 45 push(@FUNCTION_HEADER_DEF, "#endif\n\n"); 46# push (@FUNCTION_CODE, "$PFN_FUNCTION SAGE_$FUNCTION = NULL;\n"); # declaraion of function in c file 47 push (@FUNCTION_CODE, "$PFN_FUNCTION SAGE_$FUNCTION = ($PFN_FUNCTION)&badfunc;\n"); # declaraion of function in c file 48# push (@FUNCTION_INIT," SAGE_$FUNCTION = ($PFN_FUNCTION)SDL_GL_GetProcAddress(\"$FUNCTION\");\n"); # linkup function ptr 49 push (@FUNCTION_INIT," SAGE_$FUNCTION = ($PFN_FUNCTION)getPtr(\"$FUNCTION\");\n"); # linkup function ptr 50 # Grab #defines 51 } elsif ($_ =~ m|$DEFINE_REGEXP|) { 52 ($DEF) = ($_ =~ m|$DEFINE_REGEXP|); # extract #define name 53 if ($DEF =~ m|GL_VERSION|) { 54 # ignore GL_VERSION for BOOLS def 55 } else { 56 push (@BOOLS, $DEF); 57 } 58 push(@FUNCTION_HEADER_DEF, $_); # write into header 59 } elsif ($_ =~ m|$TOKEN_REGEXP|) { 60 push(@FUNCTION_HEADER_DEF, $_); # write into header 61 # grab endif if required 62 } elsif ($_ =~ m|\#endif|) { # write the endif now we have it 63 if ($WAIT_FOR_ENDIF eq "true") { 64 $WAIT_FOR_ENDIF="false"; 65 push(@FUNCTION_HEADER_DEF, "#endif\n\n"); 66 } 67 } 68} 69#copy into two arrays - we use this twice (prob a better way to do this) 70for (@BOOLS) { 71 push(@BOOLS_DEF, $_); 72 push(@BOOLS_ENUM, $_); 73} 74 75 76## Begin writing output files 77 78 79## This header file just contains the function pointer prototypes. 80print "Writing $GLEXT_SAGE_FILE\n"; 81# Open our glext.h for output 82open (GLEXT_SAGE, ">$GLEXT_SAGE_FILE") or die "Cannot open $GLEXT_SAGE_FILE\n"; 83 84 85print GLEXT_SAGE "/* This file is autogenerated by build_sage.pl */\n"; 86open (LICENSE, "<$LICENSE_FILE") or die "Can't open: $LICENSE_FILE\n"; 87while(<LICENSE>) { print GLEXT_SAGE $_; } 88close LICENSE; 89 90print GLEXT_SAGE "\n"; 91print GLEXT_SAGE "#ifndef GLEXT_SAGE_H\n"; 92print GLEXT_SAGE "#define GLEXT_SAGE_H 1\n"; 93print GLEXT_SAGE "\n"; 94 95print GLEXT_SAGE "#ifndef APIENTRY\n"; 96print GLEXT_SAGE "#define APIENTRY\n"; 97print GLEXT_SAGE "#endif\n\n"; 98 99print GLEXT_SAGE "#ifndef APIENTRYP\n"; 100print GLEXT_SAGE "#define APIENTRYP APIENTRY *\n"; 101print GLEXT_SAGE "#endif\n\n"; 102 103for (@TYPEDEFS) { 104 print GLEXT_SAGE $_; 105} 106 107print GLEXT_SAGE "#endif\n"; 108close GLEXT_SAGE; 109 110# This file contains all the definitions from glext.h 111# This file is reponsible for defining the numeric constants used by applications 112# to determine whether a particular extension has been found. 113# This file also transparently #defines normal function names as the functio npointer 114# if is not already defined. Some care needs to be taken to ensure that standard functions 115# are properly guarded against by version number rather than name. 116 117open (SAGE_HEADER, ">$SAGE_HEADER_FILE") or die "Can't open: $SAGE_HEADER_FILE\n"; 118print "Writing $SAGE_HEADER_FILE\n"; 119#Write autogen comment 120print SAGE_HEADER "/* This file is autogenerated by build_sage.pl */\n"; 121 122#Write license header 123open (LICENSE, "<$LICENSE_FILE") or die "Can't open: $LICENSE_FILE\n"; 124while(<LICENSE>) { print SAGE_HEADER $_; } 125close LICENSE; 126print SAGE_HEADER "\n"; 127 128# Write header check 129print SAGE_HEADER "#ifndef SAGE_H\n"; 130print SAGE_HEADER "#define SAGE_H 1\n"; 131print SAGE_HEADER "\n"; 132 133print SAGE_HEADER "#ifdef __glext_h_ \n"; 134print SAGE_HEADER "#error glext.h has already been included.\n"; 135print SAGE_HEADER "#endif\n\n"; 136 137print SAGE_HEADER "#define __glext_h_ 1\n\n"; 138 139# Write defines for use in extensions array 140$INDEX = 0; # Set counter to zero 141for (@BOOLS_ENUM) { 142 print SAGE_HEADER "#define ".uc($_)." $INDEX\n"; # write a #define 143 $INDEX = $INDEX + 1; # increment counter 144} 145# This allows use to determine the size of the extensions array 146print SAGE_HEADER "#define SAGE_LAST_EXTENSION ".$INDEX."\n\n"; 147 148#include the SAGEAPI stuff 149print SAGE_HEADER "#include <sage/header.h>\n"; 150print SAGE_HEADER "#include <sage/GL.h>\n"; 151# This is required to define ptrdiff_t 152print SAGE_HEADER "#include <stddef.h>\n"; 153#define the extensions array 154print SAGE_HEADER "SAGEAPI int sage_ext[SAGE_LAST_EXTENSION];\n\n"; 155 156 157#print all the token definitions 158for (@FUNCTION_HEADER_DEF) { 159 print SAGE_HEADER $_; 160} 161 162## Include prototypes. 163## By now all the OpenGL types should have been defined. 164printf SAGE_HEADER "\n"; 165print SAGE_HEADER "#include <$GLEXT_SAGE_FILE>\n\n"; 166printf SAGE_HEADER "\n"; 167 168#print the function declarations and #if's generated from glext.h 169for (@FUNCTION_HEADER_FPTR) { 170 print SAGE_HEADER $_; 171} 172 173#add the init function prototype 174print SAGE_HEADER "\nSAGEAPI int sage_init(void);\n\n"; 175#endif for header check 176print SAGE_HEADER "#endif\n"; 177#close file handle 178close SAGE_HEADER; 179 180# Write the code file 181 182#open code file for writing 183open (SAGE_CODE, ">$SAGE_CODE_FILE") or die "Can't open: $SAGE_CODE_FILE\n"; 184print "Writing $SAGE_CODE_FILE\n"; 185 186#Write autogen comment 187print SAGE_CODE "/* This file is autogenerated by build_sage.pl */\n"; 188 189#Write license header 190open (LICENSE, "<$LICENSE_FILE") or die "Can't open: $LICENSE_FILE\n"; 191while(<LICENSE>) { print SAGE_CODE $_; } 192close LICENSE; 193print SAGE_CODE "\n"; 194 195#write the #includes 196print SAGE_CODE "#include <$SAGE_HEADER_FILE>\n"; 197print SAGE_CODE "#include \"SDL.h\"\n"; 198print SAGE_CODE "#include <sage/utility.h>\n"; 199print SAGE_CODE "#include <stdlib.h>\n"; 200print SAGE_CODE "\n"; 201print SAGE_CODE "static void badfunc(void*v, ...) {\n"; 202print SAGE_CODE " fprintf(stderr, \"Error: You have tried to call a sage function pointer that is NULL.\\n\");\n"; 203print SAGE_CODE " fflush(stderr);\n"; 204print SAGE_CODE " abort();\n"; 205print SAGE_CODE "}\n"; 206print SAGE_CODE "\n"; 207print SAGE_CODE "static void* getPtr(const char *func) {\n"; 208print SAGE_CODE " void *p = SDL_GL_GetProcAddress(func);\n"; 209print SAGE_CODE " if (p == NULL) p = &badfunc;\n"; 210print SAGE_CODE " return p;\n"; 211print SAGE_CODE "}\n"; 212print SAGE_CODE "\n"; 213 214#start writing the function pointer declarations 215for (@FUNCTION_CODE) { 216 print SAGE_CODE $_; 217} 218print SAGE_CODE "\n"; 219 220# declare the extension array 221print SAGE_CODE "int sage_ext[SAGE_LAST_EXTENSION];\n\n"; 222 223#start writing the init function 224print SAGE_CODE "int sage_init(void) {\n"; 225## Gets the glExtension string each time init is called. 226print SAGE_CODE " GLubyte *ext_str = (GLubyte*)glGetString(GL_EXTENSIONS);\n"; 227print SAGE_CODE " if (ext_str == NULL) {\n"; 228print SAGE_CODE " fprintf(stderr, \"Sage Error: Could not get extension string\\n\");\n"; 229print SAGE_CODE " return 1;\n"; 230print SAGE_CODE " }\n"; 231## Write the code to hook up the function pointers. 232for (@FUNCTION_INIT) { 233 print SAGE_CODE $_; 234} 235 236# start writing the extension check code 237for (@BOOLS_DEF) { 238 print SAGE_CODE " sage_ext[".uc($_)."] = isExtensionSupported(\"$_\", ext_str);\n"; 239} 240#write closing brace for function 241print SAGE_CODE " return 0;\n"; 242print SAGE_CODE "}\n"; 243#close file handle 244close SAGE_CODE; 245 246