diff options
27 files changed, 4624 insertions, 0 deletions
diff --git a/src/SConscript b/src/SConscript index 5440acd135..28105f7191 100644 --- a/src/SConscript +++ b/src/SConscript @@ -1,6 +1,8 @@ Import('*') SConscript('gallium/SConscript') +SConscript('glsl/pp/SConscript') +SConscript('glsl/apps/SConscript') if 'mesa' in env['statetrackers']: SConscript('mesa/SConscript') diff --git a/src/glsl/apps/SConscript b/src/glsl/apps/SConscript new file mode 100644 index 0000000000..12a0018d1c --- /dev/null +++ b/src/glsl/apps/SConscript @@ -0,0 +1,33 @@ +Import('*') + +if env['platform'] not in ['windows']: + Return() + +env = env.Clone() + +if env['platform'] == 'windows': + env.PrependUnique(LIBS = [ + 'user32', + ]) + +env.Prepend(LIBS = [glsl]) + +env.Program( + target = 'purify', + source = ['purify.c'], +) + +env.Program( + target = 'tokenise', + source = ['tokenise.c'], +) + +env.Program( + target = 'version', + source = ['version.c'], +) + +env.Program( + target = 'process', + source = ['process.c'], +) diff --git a/src/glsl/apps/process.c b/src/glsl/apps/process.c new file mode 100644 index 0000000000..71211ccb72 --- /dev/null +++ b/src/glsl/apps/process.c @@ -0,0 +1,365 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include "../pp/sl_pp_context.h" +#include "../pp/sl_pp_purify.h" +#include "../pp/sl_pp_version.h" +#include "../pp/sl_pp_process.h" + + +int +main(int argc, + char *argv[]) +{ + FILE *in; + long size; + char *inbuf; + struct sl_pp_purify_options options; + char *outbuf; + struct sl_pp_context context; + struct sl_pp_token_info *tokens; + unsigned int version; + unsigned int tokens_eaten; + struct sl_pp_token_info *outtokens; + FILE *out; + unsigned int i; + + if (argc != 3) { + return 1; + } + + in = fopen(argv[1], "rb"); + if (!in) { + return 1; + } + + fseek(in, 0, SEEK_END); + size = ftell(in); + fseek(in, 0, SEEK_SET); + + inbuf = malloc(size + 1); + if (!inbuf) { + fclose(in); + return 1; + } + + if (fread(inbuf, 1, size, in) != size) { + free(inbuf); + fclose(in); + return 1; + } + inbuf[size] = '\0'; + + fclose(in); + + memset(&options, 0, sizeof(options)); + + if (sl_pp_purify(inbuf, &options, &outbuf)) { + free(inbuf); + return 1; + } + + free(inbuf); + + sl_pp_context_init(&context); + + if (sl_pp_tokenise(&context, outbuf, &tokens)) { + sl_pp_context_destroy(&context); + free(outbuf); + return 1; + } + + free(outbuf); + + if (sl_pp_version(&context, tokens, &version, &tokens_eaten)) { + sl_pp_context_destroy(&context); + free(tokens); + return -1; + } + + out = fopen(argv[2], "wb"); + if (!out) { + sl_pp_context_destroy(&context); + free(tokens); + return 1; + } + + if (sl_pp_process(&context, &tokens[tokens_eaten], &outtokens)) { + fprintf(out, "$ERROR: `%s'\n", context.error_msg); + + sl_pp_context_destroy(&context); + free(tokens); + fclose(out); + return -1; + } + + free(tokens); + + for (i = 0; outtokens[i].token != SL_PP_EOF; i++) { + switch (outtokens[i].token) { + case SL_PP_NEWLINE: + fprintf(out, "\n"); + break; + + case SL_PP_COMMA: + fprintf(out, ", "); + break; + + case SL_PP_SEMICOLON: + fprintf(out, "; "); + break; + + case SL_PP_LBRACE: + fprintf(out, "{ "); + break; + + case SL_PP_RBRACE: + fprintf(out, "} "); + break; + + case SL_PP_LPAREN: + fprintf(out, "( "); + break; + + case SL_PP_RPAREN: + fprintf(out, ") "); + break; + + case SL_PP_LBRACKET: + fprintf(out, "[ "); + break; + + case SL_PP_RBRACKET: + fprintf(out, "] "); + break; + + case SL_PP_DOT: + fprintf(out, ". "); + break; + + case SL_PP_INCREMENT: + fprintf(out, "++ "); + break; + + case SL_PP_ADDASSIGN: + fprintf(out, "+= "); + break; + + case SL_PP_PLUS: + fprintf(out, "+ "); + break; + + case SL_PP_DECREMENT: + fprintf(out, "-- "); + break; + + case SL_PP_SUBASSIGN: + fprintf(out, "-= "); + break; + + case SL_PP_MINUS: + fprintf(out, "- "); + break; + + case SL_PP_BITNOT: + fprintf(out, "~ "); + break; + + case SL_PP_NOTEQUAL: + fprintf(out, "!= "); + break; + + case SL_PP_NOT: + fprintf(out, "! "); + break; + + case SL_PP_MULASSIGN: + fprintf(out, "*= "); + break; + + case SL_PP_STAR: + fprintf(out, "* "); + break; + + case SL_PP_DIVASSIGN: + fprintf(out, "/= "); + break; + + case SL_PP_SLASH: + fprintf(out, "/ "); + break; + + case SL_PP_MODASSIGN: + fprintf(out, "%= "); + break; + + case SL_PP_MODULO: + fprintf(out, "% "); + break; + + case SL_PP_LSHIFTASSIGN: + fprintf(out, "<<= "); + break; + + case SL_PP_LSHIFT: + fprintf(out, "<< "); + break; + + case SL_PP_LESSEQUAL: + fprintf(out, "<= "); + break; + + case SL_PP_LESS: + fprintf(out, "< "); + break; + + case SL_PP_RSHIFTASSIGN: + fprintf(out, ">>= "); + break; + + case SL_PP_RSHIFT: + fprintf(out, ">> "); + break; + + case SL_PP_GREATEREQUAL: + fprintf(out, ">= "); + break; + + case SL_PP_GREATER: + fprintf(out, "> "); + break; + + case SL_PP_EQUAL: + fprintf(out, "== "); + break; + + case SL_PP_ASSIGN: + fprintf(out, "= "); + break; + + case SL_PP_AND: + fprintf(out, "&& "); + break; + + case SL_PP_BITANDASSIGN: + fprintf(out, "&= "); + break; + + case SL_PP_BITAND: + fprintf(out, "& "); + break; + + case SL_PP_XOR: + fprintf(out, "^^ "); + break; + + case SL_PP_BITXORASSIGN: + fprintf(out, "^= "); + break; + + case SL_PP_BITXOR: + fprintf(out, "^ "); + break; + + case SL_PP_OR: + fprintf(out, "|| "); + break; + + case SL_PP_BITORASSIGN: + fprintf(out, "|= "); + break; + + case SL_PP_BITOR: + fprintf(out, "| "); + break; + + case SL_PP_QUESTION: + fprintf(out, "? "); + break; + + case SL_PP_COLON: + fprintf(out, ": "); + break; + + case SL_PP_IDENTIFIER: + fprintf(out, "%s ", sl_pp_context_cstr(&context, outtokens[i].data.identifier)); + break; + + case SL_PP_NUMBER: + fprintf(out, "%s ", sl_pp_context_cstr(&context, outtokens[i].data.number)); + break; + + case SL_PP_OTHER: + fprintf(out, "%c", outtokens[i].data.other); + break; + + case SL_PP_PRAGMA_OPTIMIZE: + fprintf(out, "#pragma optimize(%s)", outtokens[i].data.pragma ? "on" : "off"); + break; + + case SL_PP_PRAGMA_DEBUG: + fprintf(out, "#pragma debug(%s)", outtokens[i].data.pragma ? "on" : "off"); + break; + + case SL_PP_EXTENSION_REQUIRE: + fprintf(out, "#extension %s : require", sl_pp_context_cstr(&context, outtokens[i].data.extension)); + break; + + case SL_PP_EXTENSION_ENABLE: + fprintf(out, "#extension %s : enable", sl_pp_context_cstr(&context, outtokens[i].data.extension)); + break; + + case SL_PP_EXTENSION_WARN: + fprintf(out, "#extension %s : warn", sl_pp_context_cstr(&context, outtokens[i].data.extension)); + break; + + case SL_PP_EXTENSION_DISABLE: + fprintf(out, "#extension %s : disable", sl_pp_context_cstr(&context, outtokens[i].data.extension)); + break; + + case SL_PP_LINE: + fprintf(out, "#line %u", outtokens[i].data.line); + break; + + case SL_PP_FILE: + fprintf(out, " #file %u", outtokens[i].data.file); + break; + + default: + assert(0); + } + } + + sl_pp_context_destroy(&context); + free(outtokens); + fclose(out); + + return 0; +} diff --git a/src/glsl/apps/purify.c b/src/glsl/apps/purify.c new file mode 100644 index 0000000000..7dff8aea45 --- /dev/null +++ b/src/glsl/apps/purify.c @@ -0,0 +1,93 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include "../pp/sl_pp_purify.h" + + +int +main(int argc, + char *argv[]) +{ + FILE *in; + long size; + char *inbuf; + struct sl_pp_purify_options options; + char *outbuf; + FILE *out; + + if (argc != 3) { + return 1; + } + + in = fopen(argv[1], "rb"); + if (!in) { + return 1; + } + + fseek(in, 0, SEEK_END); + size = ftell(in); + fseek(in, 0, SEEK_SET); + + inbuf = malloc(size + 1); + if (!inbuf) { + fclose(in); + return 1; + } + + if (fread(inbuf, 1, size, in) != size) { + free(inbuf); + fclose(in); + return 1; + } + inbuf[size] = '\0'; + + fclose(in); + + memset(&options, 0, sizeof(options)); + + if (sl_pp_purify(inbuf, &options, &outbuf)) { + free(inbuf); + return 1; + } + + free(inbuf); + + out = fopen(argv[2], "wb"); + if (!out) { + free(outbuf); + return 1; + } + + fwrite(outbuf, 1, strlen(outbuf), out); + + free(outbuf); + fclose(out); + + return 0; +} diff --git a/src/glsl/apps/tokenise.c b/src/glsl/apps/tokenise.c new file mode 100644 index 0000000000..b5092ba35f --- /dev/null +++ b/src/glsl/apps/tokenise.c @@ -0,0 +1,323 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include "../pp/sl_pp_context.h" +#include "../pp/sl_pp_purify.h" +#include "../pp/sl_pp_token.h" + + +int +main(int argc, + char *argv[]) +{ + FILE *in; + long size; + char *inbuf; + struct sl_pp_purify_options options; + char *outbuf; + struct sl_pp_context context; + struct sl_pp_token_info *tokens; + FILE *out; + unsigned int i; + + if (argc != 3) { + return 1; + } + + in = fopen(argv[1], "rb"); + if (!in) { + return 1; + } + + fseek(in, 0, SEEK_END); + size = ftell(in); + fseek(in, 0, SEEK_SET); + + inbuf = malloc(size + 1); + if (!inbuf) { + fclose(in); + return 1; + } + + if (fread(inbuf, 1, size, in) != size) { + free(inbuf); + fclose(in); + return 1; + } + inbuf[size] = '\0'; + + fclose(in); + + memset(&options, 0, sizeof(options)); + + if (sl_pp_purify(inbuf, &options, &outbuf)) { + free(inbuf); + return 1; + } + + free(inbuf); + + sl_pp_context_init(&context); + + if (sl_pp_tokenise(&context, outbuf, &tokens)) { + sl_pp_context_destroy(&context); + free(outbuf); + return 1; + } + + free(outbuf); + + out = fopen(argv[2], "wb"); + if (!out) { + sl_pp_context_destroy(&context); + free(tokens); + return 1; + } + + for (i = 0; tokens[i].token != SL_PP_EOF; i++) { + switch (tokens[i].token) { + case SL_PP_WHITESPACE: + break; + + case SL_PP_NEWLINE: + fprintf(out, "\n"); + break; + + case SL_PP_HASH: + fprintf(out, "# "); + break; + + case SL_PP_COMMA: + fprintf(out, ", "); + break; + + case SL_PP_SEMICOLON: + fprintf(out, "; "); + break; + + case SL_PP_LBRACE: + fprintf(out, "{ "); + break; + + case SL_PP_RBRACE: + fprintf(out, "} "); + break; + + case SL_PP_LPAREN: + fprintf(out, "( "); + break; + + case SL_PP_RPAREN: + fprintf(out, ") "); + break; + + case SL_PP_LBRACKET: + fprintf(out, "[ "); + break; + + case SL_PP_RBRACKET: + fprintf(out, "] "); + break; + + case SL_PP_DOT: + fprintf(out, ". "); + break; + + case SL_PP_INCREMENT: + fprintf(out, "++ "); + break; + + case SL_PP_ADDASSIGN: + fprintf(out, "+= "); + break; + + case SL_PP_PLUS: + fprintf(out, "+ "); + break; + + case SL_PP_DECREMENT: + fprintf(out, "-- "); + break; + + case SL_PP_SUBASSIGN: + fprintf(out, "-= "); + break; + + case SL_PP_MINUS: + fprintf(out, "- "); + break; + + case SL_PP_BITNOT: + fprintf(out, "~ "); + break; + + case SL_PP_NOTEQUAL: + fprintf(out, "!= "); + break; + + case SL_PP_NOT: + fprintf(out, "! "); + break; + + case SL_PP_MULASSIGN: + fprintf(out, "*= "); + break; + + case SL_PP_STAR: + fprintf(out, "* "); + break; + + case SL_PP_DIVASSIGN: + fprintf(out, "/= "); + break; + + case SL_PP_SLASH: + fprintf(out, "/ "); + break; + + case SL_PP_MODASSIGN: + fprintf(out, "%= "); + break; + + case SL_PP_MODULO: + fprintf(out, "% "); + break; + + case SL_PP_LSHIFTASSIGN: + fprintf(out, "<<= "); + break; + + case SL_PP_LSHIFT: + fprintf(out, "<< "); + break; + + case SL_PP_LESSEQUAL: + fprintf(out, "<= "); + break; + + case SL_PP_LESS: + fprintf(out, "< "); + break; + + case SL_PP_RSHIFTASSIGN: + fprintf(out, ">>= "); + break; + + case SL_PP_RSHIFT: + fprintf(out, ">> "); + break; + + case SL_PP_GREATEREQUAL: + fprintf(out, ">= "); + break; + + case SL_PP_GREATER: + fprintf(out, "> "); + break; + + case SL_PP_EQUAL: + fprintf(out, "== "); + break; + + case SL_PP_ASSIGN: + fprintf(out, "= "); + break; + + case SL_PP_AND: + fprintf(out, "&& "); + break; + + case SL_PP_BITANDASSIGN: + fprintf(out, "&= "); + break; + + case SL_PP_BITAND: + fprintf(out, "& "); + break; + + case SL_PP_XOR: + fprintf(out, "^^ "); + break; + + case SL_PP_BITXORASSIGN: + fprintf(out, "^= "); + break; + + case SL_PP_BITXOR: + fprintf(out, "^ "); + break; + + case SL_PP_OR: + fprintf(out, "|| "); + break; + + case SL_PP_BITORASSIGN: + fprintf(out, "|= "); + break; + + case SL_PP_BITOR: + fprintf(out, "| "); + break; + + case SL_PP_QUESTION: + fprintf(out, "? "); + break; + + case SL_PP_COLON: + fprintf(out, ": "); + break; + + case SL_PP_IDENTIFIER: + fprintf(out, "%s ", sl_pp_context_cstr(&context, tokens[i].data.identifier)); + break; + + case SL_PP_NUMBER: + fprintf(out, "(%s) ", sl_pp_context_cstr(&context, tokens[i].data.number)); + break; + + case SL_PP_OTHER: + if (tokens[i].data.other == '\'') { + fprintf(out, "'\\'' "); + } else { + fprintf(out, "'%c' ", tokens[i].data.other); + } + break; + + default: + assert(0); + } + } + + sl_pp_context_destroy(&context); + free(tokens); + fclose(out); + + return 0; +} diff --git a/src/glsl/apps/version.c b/src/glsl/apps/version.c new file mode 100644 index 0000000000..c56ae9dde9 --- /dev/null +++ b/src/glsl/apps/version.c @@ -0,0 +1,119 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include "../pp/sl_pp_purify.h" +#include "../pp/sl_pp_version.h" + + +int +main(int argc, + char *argv[]) +{ + FILE *in; + long size; + char *inbuf; + struct sl_pp_purify_options options; + char *outbuf; + struct sl_pp_context context; + struct sl_pp_token_info *tokens; + unsigned int version; + unsigned int tokens_eaten; + FILE *out; + + if (argc != 3) { + return 1; + } + + in = fopen(argv[1], "rb"); + if (!in) { + return 1; + } + + fseek(in, 0, SEEK_END); + size = ftell(in); + fseek(in, 0, SEEK_SET); + + inbuf = malloc(size + 1); + if (!inbuf) { + fclose(in); + return 1; + } + + if (fread(inbuf, 1, size, in) != size) { + free(inbuf); + fclose(in); + return 1; + } + inbuf[size] = '\0'; + + fclose(in); + + memset(&options, 0, sizeof(options)); + + if (sl_pp_purify(inbuf, &options, &outbuf)) { + free(inbuf); + return 1; + } + + free(inbuf); + + sl_pp_context_init(&context); + + if (sl_pp_tokenise(&context, outbuf, &tokens)) { + sl_pp_context_destroy(&context); + free(outbuf); + return 1; + } + + free(outbuf); + + if (sl_pp_version(&context, tokens, &version, &tokens_eaten)) { + sl_pp_context_destroy(&context); + free(tokens); + return -1; + } + + sl_pp_context_destroy(&context); + free(tokens); + + out = fopen(argv[2], "wb"); + if (!out) { + return 1; + } + + fprintf(out, + "%u\n%u\n", + version, + tokens_eaten); + + fclose(out); + + return 0; +} diff --git a/src/glsl/pp/SConscript b/src/glsl/pp/SConscript new file mode 100644 index 0000000000..cc930380c2 --- /dev/null +++ b/src/glsl/pp/SConscript @@ -0,0 +1,26 @@ +Import('*') + +if env['platform'] not in ['windows']: + Return() + +env = env.Clone() + +glsl = env.StaticLibrary( + target = 'glsl', + source = [ + 'sl_pp_context.c', + 'sl_pp_define.c', + 'sl_pp_error.c', + 'sl_pp_expression.c', + 'sl_pp_extension.c', + 'sl_pp_if.c', + 'sl_pp_line.c', + 'sl_pp_macro.c', + 'sl_pp_pragma.c', + 'sl_pp_process.c', + 'sl_pp_purify.c', + 'sl_pp_token.c', + 'sl_pp_version.c', + ], +) +Export('glsl') diff --git a/src/glsl/pp/sl_pp_context.c b/src/glsl/pp/sl_pp_context.c new file mode 100644 index 0000000000..2fca3791a2 --- /dev/null +++ b/src/glsl/pp/sl_pp_context.c @@ -0,0 +1,98 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_context.h" + + +void +sl_pp_context_init(struct sl_pp_context *context) +{ + memset(context, 0, sizeof(struct sl_pp_context)); + context->macro_tail = &context->macro; + context->if_ptr = SL_PP_MAX_IF_NESTING; + context->if_value = 1; + memset(context->error_msg, 0, sizeof(context->error_msg)); + context->line = 1; + context->file = 0; +} + +void +sl_pp_context_destroy(struct sl_pp_context *context) +{ + free(context->cstr_pool); + sl_pp_macro_free(context->macro); +} + +int +sl_pp_context_add_unique_str(struct sl_pp_context *context, + const char *str) +{ + unsigned int size; + unsigned int offset = 0; + + size = strlen(str) + 1; + + /* Find out if this is a unique string. */ + while (offset < context->cstr_pool_len) { + const char *str2; + unsigned int size2; + + str2 = &context->cstr_pool[offset]; + size2 = strlen(str2) + 1; + if (size == size2 && !memcmp(str, str2, size - 1)) { + return offset; + } + + offset += size2; + } + + if (context->cstr_pool_len + size > context->cstr_pool_max) { + context->cstr_pool_max = (context->cstr_pool_len + size + 0xffff) & ~0xffff; + context->cstr_pool = realloc(context->cstr_pool, context->cstr_pool_max); + } + + if (!context->cstr_pool) { + return -1; + } + + offset = context->cstr_pool_len; + memcpy(&context->cstr_pool[offset], str, size); + context->cstr_pool_len += size; + + return offset; +} + +const char * +sl_pp_context_cstr(const struct sl_pp_context *context, + int offset) +{ + if (offset == -1) { + return NULL; + } + return &context->cstr_pool[offset]; +} diff --git a/src/glsl/pp/sl_pp_context.h b/src/glsl/pp/sl_pp_context.h new file mode 100644 index 0000000000..c7e6770f44 --- /dev/null +++ b/src/glsl/pp/sl_pp_context.h @@ -0,0 +1,70 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_CONTEXT_H +#define SL_PP_CONTEXT_H + +#include "sl_pp_macro.h" + + +#define SL_PP_MAX_IF_NESTING 64 + +#define SL_PP_MAX_ERROR_MSG 1024 + +struct sl_pp_context { + char *cstr_pool; + unsigned int cstr_pool_max; + unsigned int cstr_pool_len; + + struct sl_pp_macro *macro; + struct sl_pp_macro **macro_tail; + + unsigned int if_stack[SL_PP_MAX_IF_NESTING]; + unsigned int if_ptr; + int if_value; + + char error_msg[SL_PP_MAX_ERROR_MSG]; + + unsigned int line; + unsigned int file; +}; + +void +sl_pp_context_init(struct sl_pp_context *context); + +void +sl_pp_context_destroy(struct sl_pp_context *context); + +int +sl_pp_context_add_unique_str(struct sl_pp_context *context, + const char *str); + +const char * +sl_pp_context_cstr(const struct sl_pp_context *context, + int offset); + +#endif /* SL_PP_CONTEXT_H */ diff --git a/src/glsl/pp/sl_pp_define.c b/src/glsl/pp/sl_pp_define.c new file mode 100644 index 0000000000..9bc9fb5359 --- /dev/null +++ b/src/glsl/pp/sl_pp_define.c @@ -0,0 +1,213 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_process.h" + + +static void +skip_whitespace(const struct sl_pp_token_info *input, + unsigned int *first, + unsigned int last) +{ + while (*first < last && input[*first].token == SL_PP_WHITESPACE) { + (*first)++; + } +} + + +static int +_parse_formal_args(const struct sl_pp_token_info *input, + unsigned int *first, + unsigned int last, + struct sl_pp_macro *macro) +{ + struct sl_pp_macro_formal_arg **arg; + + macro->num_args = 0; + + skip_whitespace(input, first, last); + if (*first < last) { + if (input[*first].token == SL_PP_RPAREN) { + (*first)++; + return 0; + } + } else { + /* Expected either an identifier or `)'. */ + return -1; + } + + arg = ¯o->arg; + + for (;;) { + if (*first < last && input[*first].token != SL_PP_IDENTIFIER) { + /* Expected an identifier. */ + return -1; + } + + *arg = malloc(sizeof(struct sl_pp_macro_formal_arg)); + if (!*arg) { + return -1; + } + + (**arg).name = input[*first].data.identifier; + (*first)++; + + (**arg).next = NULL; + arg = &(**arg).next; + + macro->num_args++; + + skip_whitespace(input, first, last); + if (*first < last) { + if (input[*first].token == SL_PP_COMMA) { + (*first)++; + } else if (input[*first].token == SL_PP_RPAREN) { + (*first)++; + return 0; + } else { + /* Expected either `,' or `)'. */ + return -1; + } + } else { + /* Expected either `,' or `)'. */ + return -1; + } + } +} + + +int +sl_pp_process_define(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + int macro_name = -1; + struct sl_pp_macro *macro; + unsigned int i; + unsigned int body_len; + unsigned int j; + + if (first < last && input[first].token == SL_PP_IDENTIFIER) { + macro_name = input[first].data.identifier; + first++; + } + if (macro_name == -1) { + return -1; + } + + for (macro = context->macro; macro; macro = macro->next) { + if (macro->name == macro_name) { + break; + } + } + + if (!macro) { + macro = sl_pp_macro_new(); + if (!macro) { + return -1; + } + + *context->macro_tail = macro; + context->macro_tail = ¯o->next; + } else { + sl_pp_macro_reset(macro); + } + + macro->name = macro_name; + + /* + * If there is no whitespace between macro name and left paren, a macro + * formal argument list follows. This is the only place where the presence + * of a whitespace matters and it's the only reason why we are dealing + * with whitespace at this level. + */ + if (first < last && input[first].token == SL_PP_LPAREN) { + first++; + if (_parse_formal_args(input, &first, last, macro)) { + return -1; + } + } + + /* Calculate body size, trim out whitespace, make room for EOF. */ + body_len = 1; + for (i = first; i < last; i++) { + if (input[i].token != SL_PP_WHITESPACE) { + body_len++; + } + } + + macro->body = malloc(sizeof(struct sl_pp_token_info) * body_len); + if (!macro->body) { + return -1; + } + + for (j = 0, i = first; i < last; i++) { + if (input[i].token != SL_PP_WHITESPACE) { + macro->body[j++] = input[i]; + } + } + macro->body[j++].token = SL_PP_EOF; + + return 0; +} + + +int +sl_pp_process_undef(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + int macro_name = -1; + struct sl_pp_macro **pmacro; + struct sl_pp_macro *macro; + + if (first < last && input[first].token == SL_PP_IDENTIFIER) { + macro_name = input[first].data.identifier; + } + if (macro_name == -1) { + return 0; + } + + for (pmacro = &context->macro; *pmacro; pmacro = &(**pmacro).next) { + if ((**pmacro).name == macro_name) { + break; + } + } + if (!*pmacro) { + return 0; + } + + macro = *pmacro; + *pmacro = macro->next; + macro->next = NULL; + sl_pp_macro_free(macro); + + return 0; +} diff --git a/src/glsl/pp/sl_pp_error.c b/src/glsl/pp/sl_pp_error.c new file mode 100644 index 0000000000..d42568d23d --- /dev/null +++ b/src/glsl/pp/sl_pp_error.c @@ -0,0 +1,263 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_process.h" + + +void +sl_pp_process_error(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + unsigned int out_len = 0; + unsigned int i; + + for (i = first; i < last; i++) { + const char *s = NULL; + char buf[2]; + + switch (input[i].token) { + case SL_PP_WHITESPACE: + s = " "; + break; + + case SL_PP_NEWLINE: + s = "\n"; + break; + + case SL_PP_HASH: + s = "#"; + break; + + case SL_PP_COMMA: + s = ","; + break; + + case SL_PP_SEMICOLON: + s = ";"; + break; + + case SL_PP_LBRACE: + s = "{"; + break; + + case SL_PP_RBRACE: + s = "}"; + break; + + case SL_PP_LPAREN: + s = "("; + break; + + case SL_PP_RPAREN: + s = ")"; + break; + + case SL_PP_LBRACKET: + s = "["; + break; + + case SL_PP_RBRACKET: + s = "]"; + break; + + case SL_PP_DOT: + s = "."; + break; + + case SL_PP_INCREMENT: + s = "++"; + break; + + case SL_PP_ADDASSIGN: + s = "+="; + break; + + case SL_PP_PLUS: + s = "+"; + break; + + case SL_PP_DECREMENT: + s = "--"; + break; + + case SL_PP_SUBASSIGN: + s = "-="; + break; + + case SL_PP_MINUS: + s = "-"; + break; + + case SL_PP_BITNOT: + s = "~"; + break; + + case SL_PP_NOTEQUAL: + s = "!="; + break; + + case SL_PP_NOT: + s = "!"; + break; + + case SL_PP_MULASSIGN: + s = "*="; + break; + + case SL_PP_STAR: + s = "*"; + break; + + case SL_PP_DIVASSIGN: + s = "/="; + break; + + case SL_PP_SLASH: + s = "/"; + break; + + case SL_PP_MODASSIGN: + s = "%="; + break; + + case SL_PP_MODULO: + s = "%"; + break; + + case SL_PP_LSHIFTASSIGN: + s = "<<="; + break; + + case SL_PP_LSHIFT: + s = "<<"; + break; + + case SL_PP_LESSEQUAL: + s = "<="; + break; + + case SL_PP_LESS: + s = "<"; + break; + + case SL_PP_RSHIFTASSIGN: + s = ">>="; + break; + + case SL_PP_RSHIFT: + s = ">>"; + break; + + case SL_PP_GREATEREQUAL: + s = ">="; + break; + + case SL_PP_GREATER: + s = ">"; + break; + + case SL_PP_EQUAL: + s = "=="; + break; + + case SL_PP_ASSIGN: + s = "="; + break; + + case SL_PP_AND: + s = "&&"; + break; + + case SL_PP_BITANDASSIGN: + s = "&="; + break; + + case SL_PP_BITAND: + s = "&"; + break; + + case SL_PP_XOR: + s = "^^"; + break; + + case SL_PP_BITXORASSIGN: + s = "^="; + break; + + case SL_PP_BITXOR: + s = "^"; + break; + + case SL_PP_OR: + s = "||"; + break; + + case SL_PP_BITORASSIGN: + s = "|="; + break; + + case SL_PP_BITOR: + s = "|"; + break; + + case SL_PP_QUESTION: + s = "?"; + break; + + case SL_PP_COLON: + s = ":"; + break; + + case SL_PP_IDENTIFIER: + s = sl_pp_context_cstr(context, input[i].data.identifier); + break; + + case SL_PP_NUMBER: + s = sl_pp_context_cstr(context, input[i].data.number); + break; + + case SL_PP_OTHER: + buf[0] = input[i].data.other; + buf[1] = '\0'; + s = buf; + break; + + default: + strcpy(context->error_msg, "internal error"); + return; + } + + while (*s != '\0' && out_len < sizeof(context->error_msg) - 1) { + context->error_msg[out_len++] = *s++; + } + } + + context->error_msg[out_len] = '\0'; +} diff --git a/src/glsl/pp/sl_pp_expression.c b/src/glsl/pp/sl_pp_expression.c new file mode 100644 index 0000000000..a692430abb --- /dev/null +++ b/src/glsl/pp/sl_pp_expression.c @@ -0,0 +1,407 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_expression.h" + + +struct parse_context { + struct sl_pp_context *context; + const struct sl_pp_token_info *input; +}; + +static int +_parse_or(struct parse_context *ctx, + int *result); + +static int +_parse_primary(struct parse_context *ctx, + int *result) +{ + if (ctx->input->token == SL_PP_NUMBER) { + *result = atoi(sl_pp_context_cstr(ctx->context, ctx->input->data.number)); + ctx->input++; + } else { + if (ctx->input->token != SL_PP_LPAREN) { + return -1; + } + ctx->input++; + if (_parse_or(ctx, result)) { + return -1; + } + if (ctx->input->token != SL_PP_RPAREN) { + return -1; + } + ctx->input++; + } + return 0; +} + +static int +_parse_unary(struct parse_context *ctx, + int *result) +{ + if (!_parse_primary(ctx, result)) { + return 0; + } + + switch (ctx->input->token) { + case SL_PP_PLUS: + ctx->input++; + if (_parse_unary(ctx, result)) { + return -1; + } + *result = +*result; + break; + + case SL_PP_MINUS: + ctx->input++; + if (_parse_unary(ctx, result)) { + return -1; + } + *result = -*result; + break; + + case SL_PP_NOT: + ctx->input++; + if (_parse_unary(ctx, result)) { + return -1; + } + *result = !*result; + break; + + case SL_PP_BITNOT: + ctx->input++; + if (_parse_unary(ctx, result)) { + return -1; + } + *result = ~*result; + break; + + default: + return -1; + } + + return 0; +} + +static int +_parse_multiplicative(struct parse_context *ctx, + int *result) +{ + if (_parse_unary(ctx, result)) { + return -1; + } + for (;;) { + int right; + + switch (ctx->input->token) { + case SL_PP_STAR: + ctx->input++; + if (_parse_unary(ctx, &right)) { + return -1; + } + *result = *result * right; + break; + + case SL_PP_SLASH: + ctx->input++; + if (_parse_unary(ctx, &right)) { + return -1; + } + *result = *result / right; + break; + + case SL_PP_MODULO: + ctx->input++; + if (_parse_unary(ctx, &right)) { + return -1; + } + *result = *result % right; + break; + + default: + return 0; + } + } +} + +static int +_parse_additive(struct parse_context *ctx, + int *result) +{ + if (_parse_multiplicative(ctx, result)) { + return -1; + } + for (;;) { + int right; + + switch (ctx->input->token) { + case SL_PP_PLUS: + ctx->input++; + if (_parse_multiplicative(ctx, &right)) { + return -1; + } + *result = *result + right; + break; + + case SL_PP_MINUS: + ctx->input++; + if (_parse_multiplicative(ctx, &right)) { + return -1; + } + *result = *result - right; + break; + + default: + return 0; + } + } +} + +static int +_parse_shift(struct parse_context *ctx, + int *result) +{ + if (_parse_additive(ctx, result)) { + return -1; + } + for (;;) { + int right; + + switch (ctx->input->token) { + case SL_PP_LSHIFT: + ctx->input++; + if (_parse_additive(ctx, &right)) { + return -1; + } + *result = *result << right; + break; + + case SL_PP_RSHIFT: + ctx->input++; + if (_parse_additive(ctx, &right)) { + return -1; + } + *result = *result >> right; + break; + + default: + return 0; + } + } +} + +static int +_parse_relational(struct parse_context *ctx, + int *result) +{ + if (_parse_shift(ctx, result)) { + return -1; + } + for (;;) { + int right; + + switch (ctx->input->token) { + case SL_PP_LESSEQUAL: + ctx->input++; + if (_parse_shift(ctx, &right)) { + return -1; + } + *result = *result <= right; + break; + + case SL_PP_GREATEREQUAL: + ctx->input++; + if (_parse_shift(ctx, &right)) { + return -1; + } + *result = *result >= right; + break; + + case SL_PP_LESS: + ctx->input++; + if (_parse_shift(ctx, &right)) { + return -1; + } + *result = *result < right; + break; + + case SL_PP_GREATER: + ctx->input++; + if (_parse_shift(ctx, &right)) { + return -1; + } + *result = *result > right; + break; + + default: + return 0; + } + } +} + +static int +_parse_equality(struct parse_context *ctx, + int *result) +{ + if (_parse_relational(ctx, result)) { + return -1; + } + for (;;) { + int right; + + switch (ctx->input->token) { + case SL_PP_EQUAL: + ctx->input++; + if (_parse_relational(ctx, &right)) { + return -1; + } + *result = *result == right; + break; + + case SL_PP_NOTEQUAL: + ctx->input++; + if (_parse_relational(ctx, &right)) { + return -1; + } + *result = *result != right; + break; + + default: + return 0; + } + } +} + +static int +_parse_bitand(struct parse_context *ctx, + int *result) +{ + if (_parse_equality(ctx, result)) { + return -1; + } + while (ctx->input->token == SL_PP_BITAND) { + int right; + + ctx->input++; + if (_parse_equality(ctx, &right)) { + return -1; + } + *result = *result & right; + } + return 0; +} + +static int +_parse_xor(struct parse_context *ctx, + int *result) +{ + if (_parse_bitand(ctx, result)) { + return -1; + } + while (ctx->input->token == SL_PP_XOR) { + int right; + + ctx->input++; + if (_parse_bitand(ctx, &right)) { + return -1; + } + *result = *result ^ right; + } + return 0; +} + +static int +_parse_bitor(struct parse_context *ctx, + int *result) +{ + if (_parse_xor(ctx, result)) { + return -1; + } + while (ctx->input->token == SL_PP_BITOR) { + int right; + + ctx->input++; + if (_parse_xor(ctx, &right)) { + return -1; + } + *result = *result | right; + } + return 0; +} + +static int +_parse_and(struct parse_context *ctx, + int *result) +{ + if (_parse_bitor(ctx, result)) { + return -1; + } + while (ctx->input->token == SL_PP_AND) { + int right; + + ctx->input++; + if (_parse_bitor(ctx, &right)) { + return -1; + } + *result = *result && right; + } + return 0; +} + +static int +_parse_or(struct parse_context *ctx, + int *result) +{ + if (_parse_and(ctx, result)) { + return -1; + } + while (ctx->input->token == SL_PP_OR) { + int right; + + ctx->input++; + if (_parse_and(ctx, &right)) { + return -1; + } + *result = *result || right; + } + return 0; +} + +int +sl_pp_execute_expression(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + int *result) +{ + struct parse_context ctx; + + ctx.context = context; + ctx.input = input; + + return _parse_or(&ctx, result); +} diff --git a/src/glsl/pp/sl_pp_expression.h b/src/glsl/pp/sl_pp_expression.h new file mode 100644 index 0000000000..377d5b4cbd --- /dev/null +++ b/src/glsl/pp/sl_pp_expression.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_EXPRESSION_H +#define SL_PP_EXPRESSION_H + +#include "sl_pp_context.h" +#include "sl_pp_token.h" + + +int +sl_pp_execute_expression(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + int *result); + +#endif /* SL_PP_EXPRESSION_H */ diff --git a/src/glsl/pp/sl_pp_extension.c b/src/glsl/pp/sl_pp_extension.c new file mode 100644 index 0000000000..3d223a1a54 --- /dev/null +++ b/src/glsl/pp/sl_pp_extension.c @@ -0,0 +1,129 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_process.h" + + +int +sl_pp_process_extension(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_process_state *state) +{ + int all_extensions = -1; + const char *extension_name = NULL; + const char *behavior = NULL; + struct sl_pp_token_info out; + + all_extensions = sl_pp_context_add_unique_str(context, "all"); + if (all_extensions == -1) { + return -1; + } + + if (first < last && input[first].token == SL_PP_IDENTIFIER) { + extension_name = sl_pp_context_cstr(context, input[first].data.identifier); + first++; + } + if (!extension_name) { + strcpy(context->error_msg, "expected identifier after `#extension'"); + return -1; + } + + if (!strcmp(extension_name, "all")) { + out.data.extension = all_extensions; + } else { + out.data.extension = -1; + } + + while (first < last && input[first].token == SL_PP_WHITESPACE) { + first++; + } + + if (first < last && input[first].token == SL_PP_COLON) { + first++; + } else { + strcpy(context->error_msg, "expected `:' after extension name"); + return -1; + } + + while (first < last && input[first].token == SL_PP_WHITESPACE) { + first++; + } + + if (first < last && input[first].token == SL_PP_IDENTIFIER) { + behavior = sl_pp_context_cstr(context, input[first].data.identifier); + first++; + } + if (!behavior) { + strcpy(context->error_msg, "expected identifier after `:'"); + return -1; + } + + if (!strcmp(behavior, "require")) { + strcpy(context->error_msg, "unable to enable required extension"); + return -1; + } else if (!strcmp(behavior, "enable")) { + if (out.data.extension == all_extensions) { + strcpy(context->error_msg, "unable to enable all extensions"); + return -1; + } else { + return 0; + } + } else if (!strcmp(behavior, "warn")) { + if (out.data.extension == all_extensions) { + out.token = SL_PP_EXTENSION_WARN; + } else { + return 0; + } + } else if (!strcmp(behavior, "disable")) { + if (out.data.extension == all_extensions) { + out.token = SL_PP_EXTENSION_DISABLE; + } else { + return 0; + } + } else { + strcpy(context->error_msg, "unrecognised behavior name"); + return -1; + } + + while (first < last && input[first].token == SL_PP_WHITESPACE) { + first++; + } + + if (first < last) { + strcpy(context->error_msg, "expected end of line after behavior name"); + return -1; + } + + if (sl_pp_process_out(state, &out)) { + return -1; + } + + return 0; +} diff --git a/src/glsl/pp/sl_pp_if.c b/src/glsl/pp/sl_pp_if.c new file mode 100644 index 0000000000..90b8051237 --- /dev/null +++ b/src/glsl/pp/sl_pp_if.c @@ -0,0 +1,352 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_expression.h" +#include "sl_pp_process.h" + + +static void +skip_whitespace(const struct sl_pp_token_info *input, + unsigned int *pi) +{ + while (input[*pi].token == SL_PP_WHITESPACE) { + (*pi)++; + } +} + +static int +_parse_defined(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int *pi, + struct sl_pp_process_state *state) +{ + int parens = 0; + int macro_name; + struct sl_pp_macro *macro; + int defined = 0; + struct sl_pp_token_info result; + + skip_whitespace(input, pi); + if (input[*pi].token == SL_PP_LPAREN) { + (*pi)++; + skip_whitespace(input, pi); + parens = 1; + } + + if (input[*pi].token != SL_PP_IDENTIFIER) { + /* Identifier expected. */ + return -1; + } + + macro_name = input[*pi].data.identifier; + for (macro = context->macro; macro; macro = macro->next) { + if (macro->name == macro_name) { + defined = 1; + break; + } + } + (*pi)++; + + if (parens) { + skip_whitespace(input, pi); + if (input[*pi].token != SL_PP_RPAREN) { + /* `)' expected */ + return -1; + } + (*pi)++; + } + + result.token = SL_PP_NUMBER; + if (defined) { + result.data.number = sl_pp_context_add_unique_str(context, "1"); + } else { + result.data.number = sl_pp_context_add_unique_str(context, "0"); + } + if (result.data.number == -1) { + return -1; + } + + return sl_pp_process_out(state, &result); +} + +static int +_evaluate_if_stack(struct sl_pp_context *context) +{ + unsigned int i; + + for (i = context->if_ptr; i < SL_PP_MAX_IF_NESTING; i++) { + if (!(context->if_stack[i] & 1)) { + return 0; + } + } + return 1; +} + +static int +_parse_if(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + unsigned int i; + struct sl_pp_process_state state; + struct sl_pp_token_info eof; + int result; + + if (!context->if_ptr) { + /* #if nesting too deep. */ + return -1; + } + + memset(&state, 0, sizeof(state)); + for (i = first; i < last;) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + i++; + break; + + case SL_PP_IDENTIFIER: + { + const char *id = sl_pp_context_cstr(context, input[i].data.identifier); + + if (!strcmp(id, "defined")) { + i++; + if (_parse_defined(context, input, &i, &state)) { + free(state.out); + return -1; + } + } else { + if (sl_pp_macro_expand(context, input, &i, NULL, &state, 0)) { + free(state.out); + return -1; + } + } + } + break; + + default: + if (sl_pp_process_out(&state, &input[i])) { + free(state.out); + return -1; + } + i++; + } + } + + eof.token = SL_PP_EOF; + if (sl_pp_process_out(&state, &eof)) { + free(state.out); + return -1; + } + + if (sl_pp_execute_expression(context, state.out, &result)) { + free(state.out); + return -1; + } + + free(state.out); + + context->if_ptr--; + context->if_stack[context->if_ptr] = result ? 1 : 0; + context->if_value = _evaluate_if_stack(context); + + return 0; +} + +static int +_parse_else(struct sl_pp_context *context) +{ + if (context->if_ptr == SL_PP_MAX_IF_NESTING) { + /* No matching #if. */ + return -1; + } + + /* Bit b1 indicates we already went through #else. */ + if (context->if_stack[context->if_ptr] & 2) { + /* No matching #if. */ + return -1; + } + + /* Invert current condition value and mark that we are in the #else block. */ + context->if_stack[context->if_ptr] = (1 - (context->if_stack[context->if_ptr] & 1)) | 2; + context->if_value = _evaluate_if_stack(context); + + return 0; +} + +int +sl_pp_process_if(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + return _parse_if(context, input, first, last); +} + +int +sl_pp_process_ifdef(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + unsigned int i; + + if (!context->if_ptr) { + /* #if nesting too deep. */ + return -1; + } + + for (i = first; i < last; i++) { + switch (input[i].token) { + case SL_PP_IDENTIFIER: + { + struct sl_pp_macro *macro; + int macro_name = input[i].data.identifier; + int defined = 0; + + for (macro = context->macro; macro; macro = macro->next) { + if (macro->name == macro_name) { + defined = 1; + break; + } + } + + context->if_ptr--; + context->if_stack[context->if_ptr] = defined ? 1 : 0; + context->if_value = _evaluate_if_stack(context); + } + return 0; + + case SL_PP_WHITESPACE: + break; + + default: + /* Expected an identifier. */ + return -1; + } + } + + /* Expected an identifier. */ + return -1; +} + +int +sl_pp_process_ifndef(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + unsigned int i; + + if (!context->if_ptr) { + /* #if nesting too deep. */ + return -1; + } + + for (i = first; i < last; i++) { + switch (input[i].token) { + case SL_PP_IDENTIFIER: + { + struct sl_pp_macro *macro; + int macro_name = input[i].data.identifier; + int defined = 0; + + for (macro = context->macro; macro; macro = macro->next) { + if (macro->name == macro_name) { + defined = 1; + break; + } + } + + context->if_ptr--; + context->if_stack[context->if_ptr] = defined ? 0 : 1; + context->if_value = _evaluate_if_stack(context); + } + return 0; + + case SL_PP_WHITESPACE: + break; + + default: + /* Expected an identifier. */ + return -1; + } + } + + /* Expected an identifier. */ + return -1; +} + +int +sl_pp_process_elif(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + if (_parse_else(context)) { + return -1; + } + + if (context->if_stack[context->if_ptr] & 1) { + context->if_ptr++; + if (_parse_if(context, input, first, last)) { + return -1; + } + } + + /* We are still in the #if block. */ + context->if_stack[context->if_ptr] = context->if_stack[context->if_ptr] & ~2; + + return 0; +} + +int +sl_pp_process_else(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + return _parse_else(context); +} + +int +sl_pp_process_endif(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last) +{ + if (context->if_ptr == SL_PP_MAX_IF_NESTING) { + /* No matching #if. */ + return -1; + } + + context->if_ptr++; + context->if_value = _evaluate_if_stack(context); + + return 0; +} diff --git a/src/glsl/pp/sl_pp_line.c b/src/glsl/pp/sl_pp_line.c new file mode 100644 index 0000000000..a56417a861 --- /dev/null +++ b/src/glsl/pp/sl_pp_line.c @@ -0,0 +1,159 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_process.h" + + +static int +_parse_integer(const char *input, + unsigned int *number) +{ + unsigned int n = 0; + + while (*input >= '0' && *input <= '9') { + if (n * 10 < n) { + /* Overflow. */ + return -1; + } + + n = n * 10 + (*input++ - '0'); + } + + if (*input != '\0') { + /* Invalid decimal number. */ + return -1; + } + + *number = n; + return 0; +} + + +int +sl_pp_process_line(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_process_state *pstate) +{ + unsigned int i; + struct sl_pp_process_state state; + int line_number = -1; + int file_number = -1; + const char *str; + unsigned int line; + + memset(&state, 0, sizeof(state)); + for (i = first; i < last;) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + i++; + break; + + case SL_PP_IDENTIFIER: + if (sl_pp_macro_expand(context, input, &i, NULL, &state, 0)) { + free(state.out); + return -1; + } + break; + + default: + if (sl_pp_process_out(&state, &input[i])) { + free(state.out); + return -1; + } + i++; + } + } + + if (state.out_len > 0 && state.out[0].token == SL_PP_NUMBER) { + line_number = state.out[0].data.number; + } else { + strcpy(context->error_msg, "expected number after `#line'"); + free(state.out); + return -1; + } + + if (state.out_len > 1) { + if (state.out[1].token == SL_PP_NUMBER) { + file_number = state.out[1].data.number; + } else { + strcpy(context->error_msg, "expected number after line number"); + free(state.out); + return -1; + } + + if (state.out_len > 2) { + strcpy(context->error_msg, "expected end of line after file number"); + free(state.out); + return -1; + } + } + + free(state.out); + + str = sl_pp_context_cstr(context, line_number); + if (_parse_integer(str, &line)) { + return -1; + } + + if (context->line != line) { + struct sl_pp_token_info ti; + + ti.token = SL_PP_LINE; + ti.data.line = line; + if (sl_pp_process_out(pstate, &ti)) { + return -1; + } + + context->line = line; + } + + if (file_number != -1) { + unsigned int file; + + str = sl_pp_context_cstr(context, file_number); + if (_parse_integer(str, &file)) { + return -1; + } + + if (context->file != file) { + struct sl_pp_token_info ti; + + ti.token = SL_PP_FILE; + ti.data.file = file; + if (sl_pp_process_out(pstate, &ti)) { + return -1; + } + + context->file = file; + } + } + + return 0; +} diff --git a/src/glsl/pp/sl_pp_macro.c b/src/glsl/pp/sl_pp_macro.c new file mode 100644 index 0000000000..d14c982555 --- /dev/null +++ b/src/glsl/pp/sl_pp_macro.c @@ -0,0 +1,337 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include <stdio.h> +#include "sl_pp_macro.h" +#include "sl_pp_process.h" + + +static void +_macro_init(struct sl_pp_macro *macro) +{ + macro->name = -1; + macro->num_args = -1; + macro->arg = NULL; + macro->body = NULL; +} + +struct sl_pp_macro * +sl_pp_macro_new(void) +{ + struct sl_pp_macro *macro; + + macro = calloc(1, sizeof(struct sl_pp_macro)); + if (macro) { + _macro_init(macro); + } + return macro; +} + +static void +_macro_destroy(struct sl_pp_macro *macro) +{ + struct sl_pp_macro_formal_arg *arg = macro->arg; + + while (arg) { + struct sl_pp_macro_formal_arg *next_arg = arg->next; + + free(arg); + arg = next_arg; + } + + free(macro->body); +} + +void +sl_pp_macro_free(struct sl_pp_macro *macro) +{ + while (macro) { + struct sl_pp_macro *next_macro = macro->next; + + _macro_destroy(macro); + free(macro); + macro = next_macro; + } +} + +void +sl_pp_macro_reset(struct sl_pp_macro *macro) +{ + _macro_destroy(macro); + _macro_init(macro); +} + +static void +skip_whitespace(const struct sl_pp_token_info *input, + unsigned int *pi) +{ + while (input[*pi].token == SL_PP_WHITESPACE) { + (*pi)++; + } +} + +static int +_out_number(struct sl_pp_context *context, + struct sl_pp_process_state *state, + unsigned int number) +{ + char buf[32]; + struct sl_pp_token_info ti; + + sprintf(buf, "%u", number); + + ti.token = SL_PP_NUMBER; + ti.data.number = sl_pp_context_add_unique_str(context, buf); + return sl_pp_process_out(state, &ti); +} + +int +sl_pp_macro_expand(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int *pi, + struct sl_pp_macro *local, + struct sl_pp_process_state *state, + int mute) +{ + int macro_name; + const char *macro_str; + struct sl_pp_macro *macro = NULL; + struct sl_pp_macro *actual_arg = NULL; + unsigned int j; + + if (input[*pi].token != SL_PP_IDENTIFIER) { + return -1; + } + + macro_name = input[*pi].data.identifier; + macro_str = sl_pp_context_cstr(context, macro_name); + + if (!strcmp(macro_str, "__LINE__")) { + if (!mute && _out_number(context, state, context->line)) { + return -1; + } + (*pi)++; + return 0; + } + if (!strcmp(macro_str, "__FILE__")) { + if (!mute && _out_number(context, state, context->file)) { + return -1; + } + (*pi)++; + return 0; + } + if (!strcmp(macro_str, "__VERSION__")) { + if (!mute && _out_number(context, state, 110)) { + return -1; + } + (*pi)++; + return 0; + } + + if (local) { + for (macro = local; macro; macro = macro->next) { + if (macro->name == macro_name) { + break; + } + } + } + + if (!macro) { + for (macro = context->macro; macro; macro = macro->next) { + if (macro->name == macro_name) { + break; + } + } + } + + if (!macro) { + if (!mute) { + if (sl_pp_process_out(state, &input[*pi])) { + return -1; + } + } + (*pi)++; + return 0; + } + + (*pi)++; + + if (macro->num_args >= 0) { + skip_whitespace(input, pi); + if (input[*pi].token != SL_PP_LPAREN) { + return -1; + } + (*pi)++; + skip_whitespace(input, pi); + } + + if (macro->num_args > 0) { + struct sl_pp_macro_formal_arg *formal_arg = macro->arg; + struct sl_pp_macro **pmacro = &actual_arg; + + for (j = 0; j < (unsigned int)macro->num_args; j++) { + unsigned int body_len; + unsigned int i; + int done = 0; + unsigned int paren_nesting = 0; + unsigned int k; + + *pmacro = sl_pp_macro_new(); + if (!*pmacro) { + return -1; + } + + (**pmacro).name = formal_arg->name; + + body_len = 1; + for (i = *pi; !done; i++) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + break; + + case SL_PP_COMMA: + if (!paren_nesting) { + if (j < (unsigned int)macro->num_args - 1) { + done = 1; + } else { + return -1; + } + } else { + body_len++; + } + break; + + case SL_PP_LPAREN: + paren_nesting++; + body_len++; + break; + + case SL_PP_RPAREN: + if (!paren_nesting) { + if (j == (unsigned int)macro->num_args - 1) { + done = 1; + } else { + return -1; + } + } else { + paren_nesting--; + body_len++; + } + break; + + case SL_PP_EOF: + return -1; + + default: + body_len++; + } + } + + (**pmacro).body = malloc(sizeof(struct sl_pp_token_info) * body_len); + if (!(**pmacro).body) { + return -1; + } + + for (done = 0, k = 0, i = *pi; !done; i++) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + break; + + case SL_PP_COMMA: + if (!paren_nesting && j < (unsigned int)macro->num_args - 1) { + done = 1; + } else { + (**pmacro).body[k++] = input[i]; + } + break; + + case SL_PP_LPAREN: + paren_nesting++; + (**pmacro).body[k++] = input[i]; + break; + + case SL_PP_RPAREN: + if (!paren_nesting && j == (unsigned int)macro->num_args - 1) { + done = 1; + } else { + paren_nesting--; + (**pmacro).body[k++] = input[i]; + } + break; + + default: + (**pmacro).body[k++] = input[i]; + } + } + + (**pmacro).body[k++].token = SL_PP_EOF; + (*pi) = i; + + formal_arg = formal_arg->next; + pmacro = &(**pmacro).next; + } + } + + /* Right paren for non-empty argument list has already been eaten. */ + if (macro->num_args == 0) { + skip_whitespace(input, pi); + if (input[*pi].token != SL_PP_RPAREN) { + return -1; + } + (*pi)++; + } + + for (j = 0;;) { + switch (macro->body[j].token) { + case SL_PP_NEWLINE: + if (sl_pp_process_out(state, ¯o->body[j])) { + return -1; + } + j++; + break; + + case SL_PP_IDENTIFIER: + if (sl_pp_macro_expand(context, macro->body, &j, actual_arg, state, mute)) { + return -1; + } + break; + + case SL_PP_EOF: + sl_pp_macro_free(actual_arg); + return 0; + + default: + if (!mute) { + if (sl_pp_process_out(state, ¯o->body[j])) { + return -1; + } + } + j++; + } + } +} diff --git a/src/glsl/pp/sl_pp_macro.h b/src/glsl/pp/sl_pp_macro.h new file mode 100644 index 0000000000..7af11c5ece --- /dev/null +++ b/src/glsl/pp/sl_pp_macro.h @@ -0,0 +1,64 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_MACRO_H +#define SL_PP_MACRO_H + +#include "sl_pp_token.h" + + +struct sl_pp_macro_formal_arg { + int name; + struct sl_pp_macro_formal_arg *next; +}; + +struct sl_pp_macro { + int name; + int num_args; /* -1 means no args, 0 means `()' */ + struct sl_pp_macro_formal_arg *arg; + struct sl_pp_token_info *body; + struct sl_pp_macro *next; +}; + +struct sl_pp_macro * +sl_pp_macro_new(void); + +void +sl_pp_macro_free(struct sl_pp_macro *macro); + +void +sl_pp_macro_reset(struct sl_pp_macro *macro); + +int +sl_pp_macro_expand(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int *pi, + struct sl_pp_macro *local, + struct sl_pp_process_state *state, + int mute); + +#endif /* SL_PP_MACRO_H */ diff --git a/src/glsl/pp/sl_pp_pragma.c b/src/glsl/pp/sl_pp_pragma.c new file mode 100644 index 0000000000..059bc6f288 --- /dev/null +++ b/src/glsl/pp/sl_pp_pragma.c @@ -0,0 +1,106 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_process.h" + + +int +sl_pp_process_pragma(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_process_state *state) +{ + const char *pragma_name = NULL; + struct sl_pp_token_info out; + const char *arg_name = NULL; + + if (first < last && input[first].token == SL_PP_IDENTIFIER) { + pragma_name = sl_pp_context_cstr(context, input[first].data.identifier); + first++; + } + if (!pragma_name) { + return 0; + } + + if (!strcmp(pragma_name, "optimize")) { + out.token = SL_PP_PRAGMA_OPTIMIZE; + } else if (!strcmp(pragma_name, "debug")) { + out.token = SL_PP_PRAGMA_DEBUG; + } else { + return 0; + } + + while (first < last && input[first].token == SL_PP_WHITESPACE) { + first++; + } + + if (first < last && input[first].token == SL_PP_LPAREN) { + first++; + } else { + return 0; + } + + while (first < last && input[first].token == SL_PP_WHITESPACE) { + first++; + } + + if (first < last && input[first].token == SL_PP_IDENTIFIER) { + arg_name = sl_pp_context_cstr(context, input[first].data.identifier); + first++; + } + if (!arg_name) { + return 0; + } + + if (!strcmp(arg_name, "off")) { + out.data.pragma = 0; + } else if (!strcmp(arg_name, "on")) { + out.data.pragma = 1; + } else { + return 0; + } + + while (first < last && input[first].token == SL_PP_WHITESPACE) { + first++; + } + + if (first < last && input[first].token == SL_PP_RPAREN) { + first++; + } else { + return 0; + } + + /* Ignore the tokens that follow. */ + + if (sl_pp_process_out(state, &out)) { + return -1; + } + + return 0; +} diff --git a/src/glsl/pp/sl_pp_process.c b/src/glsl/pp/sl_pp_process.c new file mode 100644 index 0000000000..c4d6efaed3 --- /dev/null +++ b/src/glsl/pp/sl_pp_process.c @@ -0,0 +1,273 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_process.h" + + +static void +skip_whitespace(const struct sl_pp_token_info *input, + unsigned int *pi) +{ + while (input[*pi].token == SL_PP_WHITESPACE) { + (*pi)++; + } +} + +int +sl_pp_process_out(struct sl_pp_process_state *state, + const struct sl_pp_token_info *token) +{ + if (state->out_len >= state->out_max) { + unsigned int new_max = state->out_max; + + if (new_max < 0x100) { + new_max = 0x100; + } else if (new_max < 0x10000) { + new_max *= 2; + } else { + new_max += 0x10000; + } + + state->out = realloc(state->out, new_max * sizeof(struct sl_pp_token_info)); + if (!state->out) { + return -1; + } + state->out_max = new_max; + } + + state->out[state->out_len++] = *token; + return 0; +} + +int +sl_pp_process(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + struct sl_pp_token_info **output) +{ + unsigned int i = 0; + int found_eof = 0; + struct sl_pp_process_state state; + + memset(&state, 0, sizeof(state)); + + if (context->line > 1) { + struct sl_pp_token_info ti; + + ti.token = SL_PP_LINE; + ti.data.line = context->line - 1; + if (sl_pp_process_out(&state, &ti)) { + return -1; + } + + ti.token = SL_PP_NEWLINE; + if (sl_pp_process_out(&state, &ti)) { + return -1; + } + } + + while (!found_eof) { + skip_whitespace(input, &i); + if (input[i].token == SL_PP_HASH) { + i++; + skip_whitespace(input, &i); + switch (input[i].token) { + case SL_PP_IDENTIFIER: + { + const char *name; + int found_eol = 0; + unsigned int first; + unsigned int last; + struct sl_pp_token_info endof; + + /* Directive name. */ + name = sl_pp_context_cstr(context, input[i].data.identifier); + i++; + skip_whitespace(input, &i); + + first = i; + + while (!found_eol) { + switch (input[i].token) { + case SL_PP_NEWLINE: + /* Preserve newline just for the sake of line numbering. */ + endof = input[i]; + i++; + found_eol = 1; + break; + + case SL_PP_EOF: + endof = input[i]; + i++; + found_eof = 1; + found_eol = 1; + break; + + default: + i++; + } + } + + last = i - 1; + + if (!strcmp(name, "if")) { + if (sl_pp_process_if(context, input, first, last)) { + return -1; + } + } else if (!strcmp(name, "ifdef")) { + if (sl_pp_process_ifdef(context, input, first, last)) { + return -1; + } + } else if (!strcmp(name, "ifndef")) { + if (sl_pp_process_ifndef(context, input, first, last)) { + return -1; + } + } else if (!strcmp(name, "elif")) { + if (sl_pp_process_elif(context, input, first, last)) { + return -1; + } + } else if (!strcmp(name, "else")) { + if (sl_pp_process_else(context, input, first, last)) { + return -1; + } + } else if (!strcmp(name, "endif")) { + if (sl_pp_process_endif(context, input, first, last)) { + return -1; + } + } else if (context->if_value) { + if (!strcmp(name, "define")) { + if (sl_pp_process_define(context, input, first, last)) { + return -1; + } + } else if (!strcmp(name, "error")) { + sl_pp_process_error(context, input, first, last); + return -1; + } else if (!strcmp(name, "extension")) { + if (sl_pp_process_extension(context, input, first, last, &state)) { + return -1; + } + } else if (!strcmp(name, "line")) { + if (sl_pp_process_line(context, input, first, last, &state)) { + return -1; + } + } else if (!strcmp(name, "pragma")) { + if (sl_pp_process_pragma(context, input, first, last, &state)) { + return -1; + } + } else if (!strcmp(name, "undef")) { + if (sl_pp_process_undef(context, input, first, last)) { + return -1; + } + } else { + strcpy(context->error_msg, "unrecognised directive name"); + return -1; + } + } + + if (sl_pp_process_out(&state, &endof)) { + return -1; + } + context->line++; + } + break; + + case SL_PP_NEWLINE: + /* Empty directive. */ + if (sl_pp_process_out(&state, &input[i])) { + return -1; + } + context->line++; + i++; + break; + + case SL_PP_EOF: + /* Empty directive. */ + if (sl_pp_process_out(&state, &input[i])) { + return -1; + } + i++; + found_eof = 1; + break; + + default: + return -1; + } + } else { + int found_eol = 0; + + while (!found_eol) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + /* Drop whitespace all together at this point. */ + i++; + break; + + case SL_PP_NEWLINE: + /* Preserve newline just for the sake of line numbering. */ + if (sl_pp_process_out(&state, &input[i])) { + return -1; + } + context->line++; + i++; + found_eol = 1; + break; + + case SL_PP_EOF: + if (sl_pp_process_out(&state, &input[i])) { + return -1; + } + i++; + found_eof = 1; + found_eol = 1; + break; + + case SL_PP_IDENTIFIER: + if (sl_pp_macro_expand(context, input, &i, NULL, &state, !context->if_value)) { + return -1; + } + break; + + default: + if (context->if_value) { + if (sl_pp_process_out(&state, &input[i])) { + return -1; + } + } + i++; + } + } + } + } + + if (context->if_ptr != SL_PP_MAX_IF_NESTING) { + /* #endif expected. */ + return -1; + } + + *output = state.out; + return 0; +} diff --git a/src/glsl/pp/sl_pp_process.h b/src/glsl/pp/sl_pp_process.h new file mode 100644 index 0000000000..adc08c18ae --- /dev/null +++ b/src/glsl/pp/sl_pp_process.h @@ -0,0 +1,126 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_PROCESS_H +#define SL_PP_PROCESS_H + +#include "sl_pp_context.h" +#include "sl_pp_macro.h" +#include "sl_pp_token.h" + + +struct sl_pp_process_state { + struct sl_pp_token_info *out; + unsigned int out_len; + unsigned int out_max; +}; + +int +sl_pp_process(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + struct sl_pp_token_info **output); + +int +sl_pp_process_define(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_undef(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_if(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_ifdef(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_ifndef(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_elif(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_else(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_endif(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +void +sl_pp_process_error(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last); + +int +sl_pp_process_pragma(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_process_state *state); + +int +sl_pp_process_extension(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_process_state *state); + +int +sl_pp_process_line(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int first, + unsigned int last, + struct sl_pp_process_state *state); + +int +sl_pp_process_out(struct sl_pp_process_state *state, + const struct sl_pp_token_info *token); + +#endif /* SL_PP_PROCESS_H */ diff --git a/src/glsl/pp/sl_pp_purify.c b/src/glsl/pp/sl_pp_purify.c new file mode 100644 index 0000000000..3fb91430f3 --- /dev/null +++ b/src/glsl/pp/sl_pp_purify.c @@ -0,0 +1,239 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_purify.h" + + +/* + * Preprocessor purifier performs the following tasks. + * - Convert all variants of newlines into a Unix newline. + * - Merge continued lines into a single long line. + * - Remove line comments and replace block comments with whitespace. + */ + + +static unsigned int +_purify_newline(const char *input, + char *out) +{ + if (input[0] == '\n') { + *out = '\n'; + if (input[1] == '\r') { + /* + * The GLSL spec is not explicit about whether this + * combination is a valid newline or not. + * Let's assume it is acceptable. + */ + return 2; + } + return 1; + } + if (input[0] == '\r') { + *out = '\n'; + if (input[1] == '\n') { + return 2; + } + return 1; + } + *out = input[0]; + return 1; +} + + +static unsigned int +_purify_backslash(const char *input, + char *out) +{ + unsigned int eaten = 0; + + for (;;) { + if (input[0] == '\\') { + char next; + unsigned int next_eaten; + + eaten++; + input++; + + next_eaten = _purify_newline(input, &next); + if (next == '\n') { + /* + * If this is really a line continuation sequence, eat + * it and do not exit the loop. + */ + eaten += next_eaten; + input += next_eaten; + } else { + /* + * It is an error to put anything between a backslash + * and a newline and still expect it to behave like a line + * continuation sequence. + * Even if it is an innocent whitespace. + */ + *out = '\\'; + break; + } + } else { + eaten += _purify_newline(input, out); + break; + } + } + return eaten; +} + + +struct out_buf { + char *out; + unsigned int len; + unsigned int capacity; +}; + + +static int +_out_buf_putc(struct out_buf *obuf, + char c) +{ + if (obuf->len >= obuf->capacity) { + unsigned int new_max = obuf->capacity; + + if (new_max < 0x100) { + new_max = 0x100; + } else if (new_max < 0x10000) { + new_max *= 2; + } else { + new_max += 0x10000; + } + + obuf->out = realloc(obuf->out, new_max); + if (!obuf->out) { + return -1; + } + obuf->capacity = new_max; + } + + obuf->out[obuf->len++] = c; + + return 0; +} + + +static unsigned int +_purify_comment(const char *input, + struct out_buf *obuf) +{ + unsigned int eaten; + char curr; + + eaten = _purify_backslash(input, &curr); + input += eaten; + if (curr == '/') { + char next; + unsigned int next_eaten; + + next_eaten = _purify_backslash(input, &next); + if (next == '/') { + eaten += next_eaten; + input += next_eaten; + + /* Replace a line comment with either a newline or nil. */ + for (;;) { + next_eaten = _purify_backslash(input, &next); + eaten += next_eaten; + input += next_eaten; + if (next == '\n' || next == '\0') { + if (_out_buf_putc(obuf, next)) { + return 0; + } + return eaten; + } + } + } else if (next == '*') { + eaten += next_eaten; + input += next_eaten; + + /* Replace a block comment with a whitespace. */ + for (;;) { + next_eaten = _purify_backslash(input, &next); + eaten += next_eaten; + input += next_eaten; + while (next == '*') { + next_eaten = _purify_backslash(input, &next); + eaten += next_eaten; + input += next_eaten; + if (next == '/') { + if (_out_buf_putc(obuf, ' ')) { + return 0; + } + return eaten; + } + } + if (next == '\n') { + if (_out_buf_putc(obuf, '\n')) { + return 0; + } + } + if (next == '\0') { + return 0; + } + } + } + } + if (_out_buf_putc(obuf, curr)) { + return 0; + } + return eaten; +} + + +int +sl_pp_purify(const char *input, + const struct sl_pp_purify_options *options, + char **output) +{ + struct out_buf obuf; + + obuf.out = NULL; + obuf.len = 0; + obuf.capacity = 0; + + for (;;) { + unsigned int eaten; + + eaten = _purify_comment(input, &obuf); + if (!eaten) { + return -1; + } + input += eaten; + + if (obuf.out[obuf.len - 1] == '\0') { + break; + } + } + + *output = obuf.out; + return 0; +} diff --git a/src/glsl/pp/sl_pp_purify.h b/src/glsl/pp/sl_pp_purify.h new file mode 100644 index 0000000000..011b117937 --- /dev/null +++ b/src/glsl/pp/sl_pp_purify.h @@ -0,0 +1,41 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_PURIFY_H +#define SL_PP_PURIFY_H + +struct sl_pp_purify_options { + unsigned int preserve_columns:1; + unsigned int tab_width:4; +}; + +int +sl_pp_purify(const char *input, + const struct sl_pp_purify_options *options, + char **output); + +#endif /* SL_PP_PURIFY_H */ diff --git a/src/glsl/pp/sl_pp_token.c b/src/glsl/pp/sl_pp_token.c new file mode 100644 index 0000000000..68c8fbe2ec --- /dev/null +++ b/src/glsl/pp/sl_pp_token.c @@ -0,0 +1,401 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdlib.h> +#include "sl_pp_token.h" + + +static int +_tokenise_identifier(struct sl_pp_context *context, + const char **pinput, + struct sl_pp_token_info *info) +{ + const char *input = *pinput; + char identifier[256]; /* XXX: Remove this artifical limit. */ + unsigned int i = 0; + + info->token = SL_PP_IDENTIFIER; + info->data.identifier = -1; + + identifier[i++] = *input++; + while ((*input >= 'a' && *input <= 'z') || + (*input >= 'A' && *input <= 'Z') || + (*input >= '0' && *input <= '9') || + (*input == '_')) { + if (i >= sizeof(identifier) - 1) { + return -1; + } + identifier[i++] = *input++; + } + identifier[i++] = '\0'; + + info->data.identifier = sl_pp_context_add_unique_str(context, identifier); + if (info->data.identifier == -1) { + return -1; + } + + *pinput = input; + return 0; +} + + +static int +_tokenise_number(struct sl_pp_context *context, + const char **pinput, + struct sl_pp_token_info *info) +{ + const char *input = *pinput; + char number[256]; /* XXX: Remove this artifical limit. */ + unsigned int i = 0; + + info->token = SL_PP_NUMBER; + info->data.number = -1; + + number[i++] = *input++; + while ((*input >= '0' && *input <= '9') || + (*input >= 'a' && *input <= 'f') || + (*input >= 'A' && *input <= 'F') || + (*input == 'x') || + (*input == 'X') || + (*input == '+') || + (*input == '-') || + (*input == '.')) { + if (i >= sizeof(number) - 1) { + return -1; + } + number[i++] = *input++; + } + number[i++] = '\0'; + + info->data.number = sl_pp_context_add_unique_str(context, number); + if (info->data.number == -1) { + return -1; + } + + *pinput = input; + return 0; +} + + +int +sl_pp_tokenise(struct sl_pp_context *context, + const char *input, + struct sl_pp_token_info **output) +{ + struct sl_pp_token_info *out = NULL; + unsigned int out_len = 0; + unsigned int out_max = 0; + + for (;;) { + struct sl_pp_token_info info; + + switch (*input) { + case ' ': + case '\t': + input++; + info.token = SL_PP_WHITESPACE; + break; + + case '\n': + input++; + info.token = SL_PP_NEWLINE; + break; + + case '#': + input++; + info.token = SL_PP_HASH; + break; + + case ',': + input++; + info.token = SL_PP_COMMA; + break; + + case ';': + input++; + info.token = SL_PP_SEMICOLON; + break; + + case '{': + input++; + info.token = SL_PP_LBRACE; + break; + + case '}': + input++; + info.token = SL_PP_RBRACE; + break; + + case '(': + input++; + info.token = SL_PP_LPAREN; + break; + + case ')': + input++; + info.token = SL_PP_RPAREN; + break; + + case '[': + input++; + info.token = SL_PP_LBRACKET; + break; + + case ']': + input++; + info.token = SL_PP_RBRACKET; + break; + + case '.': + if (input[1] >= '0' && input[1] <= '9') { + if (_tokenise_number(context, &input, &info)) { + free(out); + return -1; + } + } else { + input++; + info.token = SL_PP_DOT; + } + break; + + case '+': + input++; + if (*input == '+') { + input++; + info.token = SL_PP_INCREMENT; + } else if (*input == '=') { + input++; + info.token = SL_PP_ADDASSIGN; + } else { + info.token = SL_PP_PLUS; + } + break; + + case '-': + input++; + if (*input == '-') { + input++; + info.token = SL_PP_DECREMENT; + } else if (*input == '=') { + input++; + info.token = SL_PP_SUBASSIGN; + } else { + info.token = SL_PP_MINUS; + } + break; + + case '~': + input++; + info.token = SL_PP_BITNOT; + break; + + case '!': + input++; + if (*input == '=') { + input++; + info.token = SL_PP_NOTEQUAL; + } else { + info.token = SL_PP_NOT; + } + break; + + case '*': + input++; + if (*input == '=') { + input++; + info.token = SL_PP_MULASSIGN; + } else { + info.token = SL_PP_STAR; + } + break; + + case '/': + input++; + if (*input == '=') { + input++; + info.token = SL_PP_DIVASSIGN; + } else { + info.token = SL_PP_SLASH; + } + break; + + case '%': + input++; + if (*input == '=') { + input++; + info.token = SL_PP_MODASSIGN; + } else { + info.token = SL_PP_MODULO; + } + break; + + case '<': + input++; + if (*input == '<') { + input++; + if (*input == '=') { + input++; + info.token = SL_PP_LSHIFTASSIGN; + } else { + info.token = SL_PP_LSHIFT; + } + } else if (*input == '=') { + input++; + info.token = SL_PP_LESSEQUAL; + } else { + info.token = SL_PP_LESS; + } + break; + + case '>': + input++; + if (*input == '>') { + input++; + if (*input == '=') { + input++; + info.token = SL_PP_RSHIFTASSIGN; + } else { + info.token = SL_PP_RSHIFT; + } + } else if (*input == '=') { + input++; + info.token = SL_PP_GREATEREQUAL; + } else { + info.token = SL_PP_GREATER; + } + break; + + case '=': + input++; + if (*input == '=') { + input++; + info.token = SL_PP_EQUAL; + } else { + info.token = SL_PP_ASSIGN; + } + break; + + case '&': + input++; + if (*input == '&') { + input++; + info.token = SL_PP_AND; + } else if (*input == '=') { + input++; + info.token = SL_PP_BITANDASSIGN; + } else { + info.token = SL_PP_BITAND; + } + break; + + case '^': + input++; + if (*input == '^') { + input++; + info.token = SL_PP_XOR; + } else if (*input == '=') { + input++; + info.token = SL_PP_BITXORASSIGN; + } else { + info.token = SL_PP_BITXOR; + } + break; + + case '|': + input++; + if (*input == '|') { + input++; + info.token = SL_PP_OR; + } else if (*input == '=') { + input++; + info.token = SL_PP_BITORASSIGN; + } else { + info.token = SL_PP_BITOR; + } + break; + + case '?': + input++; + info.token = SL_PP_QUESTION; + break; + + case ':': + input++; + info.token = SL_PP_COLON; + break; + + case '\0': + info.token = SL_PP_EOF; + break; + + default: + if ((*input >= 'a' && *input <= 'z') || + (*input >= 'A' && *input <= 'Z') || + (*input == '_')) { + if (_tokenise_identifier(context, &input, &info)) { + free(out); + return -1; + } + } else if (*input >= '0' && *input <= '9') { + if (_tokenise_number(context, &input, &info)) { + free(out); + return -1; + } + } else { + info.data.other = *input++; + info.token = SL_PP_OTHER; + } + } + + if (out_len >= out_max) { + unsigned int new_max = out_max; + + if (new_max < 0x100) { + new_max = 0x100; + } else if (new_max < 0x10000) { + new_max *= 2; + } else { + new_max += 0x10000; + } + + out = realloc(out, new_max * sizeof(struct sl_pp_token_info)); + if (!out) { + return -1; + } + out_max = new_max; + } + + out[out_len++] = info; + + if (info.token == SL_PP_EOF) { + break; + } + } + + *output = out; + return 0; +} diff --git a/src/glsl/pp/sl_pp_token.h b/src/glsl/pp/sl_pp_token.h new file mode 100644 index 0000000000..5901959383 --- /dev/null +++ b/src/glsl/pp/sl_pp_token.h @@ -0,0 +1,125 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_TOKEN_H +#define SL_PP_TOKEN_H + +#include "sl_pp_context.h" + + +enum sl_pp_token { + SL_PP_WHITESPACE, + SL_PP_NEWLINE, + SL_PP_HASH, /* # */ + + SL_PP_COMMA, /* , */ + SL_PP_SEMICOLON, /* ; */ + SL_PP_LBRACE, /* { */ + SL_PP_RBRACE, /* } */ + SL_PP_LPAREN, /* ( */ + SL_PP_RPAREN, /* ) */ + SL_PP_LBRACKET, /* [ */ + SL_PP_RBRACKET, /* ] */ + SL_PP_DOT, /* . */ + SL_PP_INCREMENT, /* ++ */ + SL_PP_ADDASSIGN, /* += */ + SL_PP_PLUS, /* + */ + SL_PP_DECREMENT, /* -- */ + SL_PP_SUBASSIGN, /* -= */ + SL_PP_MINUS, /* - */ + SL_PP_BITNOT, /* ~ */ + SL_PP_NOTEQUAL, /* != */ + SL_PP_NOT, /* ! */ + SL_PP_MULASSIGN, /* *= */ + SL_PP_STAR, /* * */ + SL_PP_DIVASSIGN, /* /= */ + SL_PP_SLASH, /* / */ + SL_PP_MODASSIGN, /* %= */ + SL_PP_MODULO, /* % */ + SL_PP_LSHIFTASSIGN, /* <<= */ + SL_PP_LSHIFT, /* << */ + SL_PP_LESSEQUAL, /* <= */ + SL_PP_LESS, /* < */ + SL_PP_RSHIFTASSIGN, /* >>= */ + SL_PP_RSHIFT, /* >> */ + SL_PP_GREATEREQUAL, /* >= */ + SL_PP_GREATER, /* > */ + SL_PP_EQUAL, /* == */ + SL_PP_ASSIGN, /* = */ + SL_PP_AND, /* && */ + SL_PP_BITANDASSIGN, /* &= */ + SL_PP_BITAND, /* & */ + SL_PP_XOR, /* ^^ */ + SL_PP_BITXORASSIGN, /* ^= */ + SL_PP_BITXOR, /* ^ */ + SL_PP_OR, /* || */ + SL_PP_BITORASSIGN, /* |= */ + SL_PP_BITOR, /* | */ + SL_PP_QUESTION, /* ? */ + SL_PP_COLON, /* : */ + + SL_PP_IDENTIFIER, + + SL_PP_NUMBER, + + SL_PP_OTHER, + + SL_PP_PRAGMA_OPTIMIZE, + SL_PP_PRAGMA_DEBUG, + + SL_PP_EXTENSION_REQUIRE, + SL_PP_EXTENSION_ENABLE, + SL_PP_EXTENSION_WARN, + SL_PP_EXTENSION_DISABLE, + + SL_PP_LINE, + SL_PP_FILE, + + SL_PP_EOF +}; + +union sl_pp_token_data { + int identifier; + int number; + char other; + int pragma; + int extension; + unsigned int line; + unsigned int file; +}; + +struct sl_pp_token_info { + enum sl_pp_token token; + union sl_pp_token_data data; +}; + +int +sl_pp_tokenise(struct sl_pp_context *context, + const char *input, + struct sl_pp_token_info **output); + +#endif /* SL_PP_TOKEN_H */ diff --git a/src/glsl/pp/sl_pp_version.c b/src/glsl/pp/sl_pp_version.c new file mode 100644 index 0000000000..80f7e97101 --- /dev/null +++ b/src/glsl/pp/sl_pp_version.c @@ -0,0 +1,179 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "sl_pp_version.h" + + +static int +_parse_integer(const char *input, + unsigned int *number) +{ + unsigned int n = 0; + + while (*input >= '0' && *input <= '9') { + if (n * 10 < n) { + /* Overflow. */ + return -1; + } + + n = n * 10 + (*input++ - '0'); + } + + if (*input != '\0') { + /* Invalid decimal number. */ + return -1; + } + + *number = n; + return 0; +} + + +int +sl_pp_version(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int *version, + unsigned int *tokens_eaten) +{ + unsigned int i = 0; + unsigned int line = context->line; + + /* Default values if `#version' is not present. */ + *version = 110; + *tokens_eaten = 0; + + /* There can be multiple `#version' directives present. + * Accept the value of the last one. + */ + for (;;) { + int found_hash = 0; + int found_version = 0; + int found_number = 0; + int found_end = 0; + + /* Skip whitespace and newlines and seek for hash. */ + while (!found_hash) { + switch (input[i].token) { + case SL_PP_NEWLINE: + line++; + /* pass thru */ + case SL_PP_WHITESPACE: + i++; + break; + + case SL_PP_HASH: + i++; + found_hash = 1; + break; + + default: + return 0; + } + } + + /* Skip whitespace and seek for `version'. */ + while (!found_version) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + i++; + break; + + case SL_PP_IDENTIFIER: + { + const char *id = sl_pp_context_cstr(context, input[i].data.identifier); + + if (!id) { + return -1; + } + if (strcmp(id, "version")) { + return 0; + } + i++; + found_version = 1; + } + break; + + default: + return 0; + } + } + + /* Skip whitespace and seek for version number. */ + while (!found_number) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + i++; + break; + + case SL_PP_NUMBER: + { + const char *num = sl_pp_context_cstr(context, input[i].data.number); + + if (!num) { + return -1; + } + if (_parse_integer(num, version)) { + /* Expected version number. */ + return -1; + } + i++; + found_number = 1; + } + break; + + default: + /* Expected version number. */ + return -1; + } + } + + /* Skip whitespace and seek for either newline or eof. */ + while (!found_end) { + switch (input[i].token) { + case SL_PP_WHITESPACE: + i++; + break; + + case SL_PP_NEWLINE: + line++; + /* pass thru */ + case SL_PP_EOF: + i++; + *tokens_eaten = i; + context->line = line; + found_end = 1; + break; + + default: + /* Expected end of line. */ + return -1; + } + } + } + + /* Should not get here. */ +} diff --git a/src/glsl/pp/sl_pp_version.h b/src/glsl/pp/sl_pp_version.h new file mode 100644 index 0000000000..cee9f55bc6 --- /dev/null +++ b/src/glsl/pp/sl_pp_version.h @@ -0,0 +1,41 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef SL_PP_VERSION_H +#define SL_PP_VERSION_H + +#include "sl_pp_context.h" +#include "sl_pp_token.h" + + +int +sl_pp_version(struct sl_pp_context *context, + const struct sl_pp_token_info *input, + unsigned int *version, + unsigned int *tokens_eaten); + +#endif /* SL_PP_VERSION_H */ |