Search
lxdream.org :: lxdream/src/tools/genglsl.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/tools/genglsl.c
changeset 1235:8da2f3dad9c0
prev1234:1b836bf92653
next1240:190df8a791ca
author nkeynes
date Fri Feb 24 21:11:58 2012 +1000 (7 years ago)
permissions -rw-r--r--
last change Add preprocessing support to genglsl
file annotate diff log raw
1.1 --- a/src/tools/genglsl.c Fri Feb 24 17:31:18 2012 +1000
1.2 +++ b/src/tools/genglsl.c Fri Feb 24 21:11:58 2012 +1000
1.3 @@ -28,7 +28,9 @@
1.4 #include <string.h>
1.5 #include <getopt.h>
1.6 #include <glib/gstrfuncs.h>
1.7 +#include <glib/gshell.h>
1.8 #include <glib/glist.h>
1.9 +#include "../../config.h"
1.10
1.11 #define MAX_LINE 4096
1.12 #define DEF_ALLOC_SIZE 4096
1.13 @@ -144,14 +146,65 @@
1.14
1.15 }
1.16
1.17 +static GList *temp_filenames = NULL;
1.18
1.19 -static void readInput( const char *filename, glsldata_t result )
1.20 +static void cleanup_tempfiles(void)
1.21 +{
1.22 + while( temp_filenames != NULL ) {
1.23 + unlink( (char *)temp_filenames->data );
1.24 + g_free(temp_filenames->data);
1.25 + temp_filenames = temp_filenames->next;
1.26 + }
1.27 +}
1.28 +
1.29 +/**
1.30 + * Preprocess the input file and return a temporary filename containing the result
1.31 + */
1.32 +static FILE *preprocessInput( const char *filename, GList *cpp_opts )
1.33 +{
1.34 + char tmpname[] = "/tmp/genglsl.XXXXXXXX";
1.35 + int fd = mkstemp(tmpname);
1.36 + if( fd == -1 ) {
1.37 + fprintf( stderr, "Error: unable to get a temporary filename (%s)\n", strerror(errno) );
1.38 + exit(2);
1.39 + }
1.40 + char *quoted_filename = g_shell_quote(filename);
1.41 +
1.42 + int nOpts = g_list_length(cpp_opts);
1.43 + gchar *quoted_opts_arr[nOpts];
1.44 + int length = 0, count=0;
1.45 + for( GList *ptr = cpp_opts; ptr != NULL; ptr = ptr->next ) {
1.46 + quoted_opts_arr[count] = g_shell_quote((gchar *)ptr->data);
1.47 + length += strlen(quoted_opts_arr[count++]) + 1;
1.48 + }
1.49 + gchar quoted_cpp_opts[length];
1.50 + quoted_cpp_opts[0] = '\0';
1.51 + for( count=0; count<nOpts; count++ ) {
1.52 + if( count != 0 )
1.53 + strcat(quoted_cpp_opts, " ");
1.54 + strcat(quoted_cpp_opts, quoted_opts_arr[count]);
1.55 + g_free(quoted_opts_arr[count++]);
1.56 + }
1.57 +
1.58 + const char *command = g_strdup_printf("%s -E 's/^#(program|vertex|fragment)/#pragma \\1/' %s | %s %s - > %s",
1.59 + BUILD_SED_PROG, quoted_filename, BUILD_CPP_PROG, quoted_cpp_opts, tmpname );
1.60 + if( system(command) != 0 ) {
1.61 + fprintf( stderr, "Error: unable to run preprocessor command '%s' (%s)\n", command, strerror(errno) );
1.62 + exit(2);
1.63 + }
1.64 +
1.65 + temp_filenames = g_list_append(temp_filenames, g_strdup(tmpname));
1.66 + return fdopen(fd, "r");
1.67 +}
1.68 +
1.69 +static void readInput( const char *filename, GList *cpp_opts, glsldata_t result )
1.70 {
1.71 char buf[MAX_LINE];
1.72 size_t current_size = 0, current_posn = 0;
1.73 unsigned i;
1.74
1.75 - FILE *f = fopen( filename, "ro" );
1.76 +
1.77 + FILE *f = preprocessInput(filename, cpp_opts );
1.78 if( f == NULL ) {
1.79 fprintf( stderr, "Error: unable to open input file '%s': %s\n", filename, strerror(errno) );
1.80 exit(2);
1.81 @@ -170,42 +223,49 @@
1.82 if( strlen(buf) == 0 )
1.83 continue;
1.84
1.85 - if( strncmp(buf, "#vertex ", 8) == 0 ) {
1.86 - shader = g_malloc0(sizeof(struct shader));
1.87 - assert( shader != NULL );
1.88 - shader->type = VERTEX_SHADER;
1.89 - shader->name = strdup(g_strstrip(buf+8));
1.90 - shader->body = malloc(DEF_ALLOC_SIZE);
1.91 - shader->body[0] = '\0';
1.92 - current_size = DEF_ALLOC_SIZE;
1.93 - current_posn = 0;
1.94 - result->shaders = g_list_append(result->shaders, shader);
1.95 - } else if( strncmp( buf, "#fragment ", 10 ) == 0 ) {
1.96 - shader = g_malloc0(sizeof(struct shader));
1.97 - assert( shader != NULL );
1.98 - shader->type = FRAGMENT_SHADER;
1.99 - shader->name = strdup(g_strstrip(buf+10));
1.100 - shader->body = malloc(DEF_ALLOC_SIZE);
1.101 - shader->body[0] = '\0';
1.102 - current_size = DEF_ALLOC_SIZE;
1.103 - current_posn = 0;
1.104 - result->shaders = g_list_append(result->shaders, shader);
1.105 - } else if( strncmp( buf, "#program ", 9 ) == 0 ) {
1.106 - shader = NULL;
1.107 - program_t program = g_malloc0(sizeof(struct program));
1.108 - char *rest = buf+9;
1.109 - char *equals = strchr(rest, '=');
1.110 - if( equals == NULL ) {
1.111 - fprintf( stderr, "Error: invalid program line %s\n", buf );
1.112 - exit(2);
1.113 + if( buf[0] == '#' ) {
1.114 + char *p = buf+1;
1.115 + if( strncmp(p, "pragma ", 7) == 0 ) {
1.116 + p += 7;
1.117 }
1.118 - *equals = '\0';
1.119 - program->name = g_strdup(g_strstrip(rest));
1.120 - program->shader_names = g_strsplit_set(g_strstrip(equals+1), " \t\r,", 0);
1.121 - result->programs = g_list_append(result->programs, program);
1.122 - for(i=0;program->shader_names[i] != NULL; i++ );
1.123 - if( i > result->max_shaders )
1.124 - result->max_shaders = i;
1.125 + if( strncmp(p, "vertex ", 7) == 0 ) {
1.126 + shader = g_malloc0(sizeof(struct shader));
1.127 + assert( shader != NULL );
1.128 + shader->type = VERTEX_SHADER;
1.129 + shader->name = strdup(g_strstrip(p+7));
1.130 + shader->body = malloc(DEF_ALLOC_SIZE);
1.131 + shader->body[0] = '\0';
1.132 + current_size = DEF_ALLOC_SIZE;
1.133 + current_posn = 0;
1.134 + result->shaders = g_list_append(result->shaders, shader);
1.135 + } else if( strncmp( p, "fragment ", 9 ) == 0 ) {
1.136 + shader = g_malloc0(sizeof(struct shader));
1.137 + assert( shader != NULL );
1.138 + shader->type = FRAGMENT_SHADER;
1.139 + shader->name = strdup(g_strstrip(p+9));
1.140 + shader->body = malloc(DEF_ALLOC_SIZE);
1.141 + shader->body[0] = '\0';
1.142 + current_size = DEF_ALLOC_SIZE;
1.143 + current_posn = 0;
1.144 + result->shaders = g_list_append(result->shaders, shader);
1.145 + } else if( strncmp( p, "program ", 8 ) == 0 ) {
1.146 + shader = NULL;
1.147 + program_t program = g_malloc0(sizeof(struct program));
1.148 + char *rest = p+8;
1.149 + char *equals = strchr(rest, '=');
1.150 + if( equals == NULL ) {
1.151 + fprintf( stderr, "Error: invalid program line %s\n", buf );
1.152 + exit(2);
1.153 + }
1.154 + *equals = '\0';
1.155 + program->name = g_strdup(g_strstrip(rest));
1.156 + program->shader_names = g_strsplit_set(g_strstrip(equals+1), " \t\r,", 0);
1.157 + result->programs = g_list_append(result->programs, program);
1.158 + for(i=0;program->shader_names[i] != NULL; i++ );
1.159 + if( i > result->max_shaders )
1.160 + result->max_shaders = i;
1.161 + }
1.162 + /* Else discard any other # lines */
1.163 } else if( shader != NULL ) {
1.164 size_t len = strlen(buf);
1.165 if( current_posn + len > current_size ) {
1.166 @@ -446,10 +506,10 @@
1.167 }
1.168 }
1.169
1.170 -static char *option_list = "hi:o:";
1.171 +static char *option_list = "hi:I:D:U:o:";
1.172 static struct option long_option_list[] = {
1.173 { "help", no_argument, NULL, 'h' },
1.174 - { "interface", required_argument, 'i' },
1.175 + { "interface", required_argument, NULL, 'i' },
1.176 { "output", required_argument, NULL, 'o' },
1.177 { NULL, 0, 0, 0 } };
1.178
1.179 @@ -460,6 +520,7 @@
1.180 {
1.181 const char *output_file = NULL;
1.182 const char *iface_file = NULL;
1.183 + GList *cpp_opts = NULL;
1.184 int opt;
1.185
1.186 while( (opt = getopt_long( argc, argv, option_list, long_option_list, NULL )) != -1 ) {
1.187 @@ -468,6 +529,9 @@
1.188 usage();
1.189 exit(0);
1.190 break;
1.191 + case 'D': case 'I': case 'U':
1.192 + cpp_opts = g_list_append(cpp_opts, g_strdup_printf( "-%c%s", opt, optarg ));
1.193 + break;
1.194 case 'i':
1.195 if( iface_file != NULL ) {
1.196 fprintf( stderr, "Error: at most one interface file can be supplied\n" );
1.197 @@ -498,9 +562,10 @@
1.198 iface_file = makeExtension(output_file, ".h");
1.199 }
1.200
1.201 + atexit(cleanup_tempfiles);
1.202 glsldata_t data = g_malloc0(sizeof(struct glsldata));
1.203 while( optind < argc ) {
1.204 - readInput(argv[optind++], data);
1.205 + readInput(argv[optind++], cpp_opts, data);
1.206 }
1.207 linkPrograms(data);
1.208
.