104ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke/* 204ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * Copyright © 2010 Intel Corporation 304ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * 404ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * Permission is hereby granted, free of charge, to any person obtaining a 504ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * copy of this software and associated documentation files (the "Software"), 604ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * to deal in the Software without restriction, including without limitation 704ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * the rights to use, copy, modify, merge, publish, distribute, sublicense, 804ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * and/or sell copies of the Software, and to permit persons to whom the 904ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * Software is furnished to do so, subject to the following conditions: 1004ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * 1104ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * The above copyright notice and this permission notice (including the next 1204ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * paragraph) shall be included in all copies or substantial portions of the 1304ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * Software. 1404ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * 1504ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1604ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1704ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1804ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1904ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2004ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2104ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke * DEALINGS IN THE SOFTWARE. 2204ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke */ 2304ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke 24bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke#include <assert.h> 25204d4cbea0de81f6f162ae0348e476de6c916ca8Jakob Bornecrantz#include <string.h> 26bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke#include <ctype.h> 2704ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke#include "glcpp.h" 28653ddaab2636764b9e7999fa39b37edde7fe7c6dAras Pranckevicius#include "main/core.h" /* for isblank() on MSVC */ 2904ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke 30f1e6c069fac93dd2b7b2026ccd24833a066c895aKenneth Graunkevoid 31f1e6c069fac93dd2b7b2026ccd24833a066c895aKenneth Graunkeglcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) 32f1e6c069fac93dd2b7b2026ccd24833a066c895aKenneth Graunke{ 33d1dda951c85f65612ed6fe080728f67fdc93d232Brian Paul va_list ap; 34d1dda951c85f65612ed6fe080728f67fdc93d232Brian Paul 3562b4b7785a01f11e7fcd9bf76dae6b3c0a16d537Kenneth Graunke parser->error = 1; 361db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth ralloc_asprintf_rewrite_tail(&parser->info_log, 371db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth &parser->info_log_length, 381db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth "%u:%u(%u): " 391db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth "preprocessor error: ", 401db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth locp->source, 411db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth locp->first_line, 421db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth locp->first_column); 4333eaa3e0b3a8f94c2abb23ac3c9cbe571f170fb6Kenneth Graunke va_start(ap, fmt); 441db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth ralloc_vasprintf_rewrite_tail(&parser->info_log, 451db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth &parser->info_log_length, 461db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth fmt, ap); 4733eaa3e0b3a8f94c2abb23ac3c9cbe571f170fb6Kenneth Graunke va_end(ap); 481db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth ralloc_asprintf_rewrite_tail(&parser->info_log, 491db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth &parser->info_log_length, "\n"); 50f1e6c069fac93dd2b7b2026ccd24833a066c895aKenneth Graunke} 51f1e6c069fac93dd2b7b2026ccd24833a066c895aKenneth Graunke 52c9529c4d7727e0ff9da71f0941746e4d213dd689Kenneth Graunkevoid 53c9529c4d7727e0ff9da71f0941746e4d213dd689Kenneth Graunkeglcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...) 54c9529c4d7727e0ff9da71f0941746e4d213dd689Kenneth Graunke{ 55d1dda951c85f65612ed6fe080728f67fdc93d232Brian Paul va_list ap; 56d1dda951c85f65612ed6fe080728f67fdc93d232Brian Paul 571db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth ralloc_asprintf_rewrite_tail(&parser->info_log, 581db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth &parser->info_log_length, 591db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth "%u:%u(%u): " 601db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth "preprocessor warning: ", 611db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth locp->source, 621db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth locp->first_line, 631db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth locp->first_column); 64c9529c4d7727e0ff9da71f0941746e4d213dd689Kenneth Graunke va_start(ap, fmt); 651db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth ralloc_vasprintf_rewrite_tail(&parser->info_log, 661db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth &parser->info_log_length, 671db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth fmt, ap); 68c9529c4d7727e0ff9da71f0941746e4d213dd689Kenneth Graunke va_end(ap); 691db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth ralloc_asprintf_rewrite_tail(&parser->info_log, 701db463ce2e2812c4e41ab4096ff16a148d4bcc90Carl Worth &parser->info_log_length, "\n"); 71c9529c4d7727e0ff9da71f0941746e4d213dd689Kenneth Graunke} 72c9529c4d7727e0ff9da71f0941746e4d213dd689Kenneth Graunke 73bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke/* Searches backwards for '^ *#' from a given starting point. */ 74bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunkestatic int 75bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunkein_directive(const char *shader, const char *ptr) 76bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke{ 77bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke assert(ptr >= shader); 78bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke 79bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* Search backwards for '#'. If we find a \n first, it doesn't count */ 80bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke for (; ptr >= shader && *ptr != '#'; ptr--) { 81bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (*ptr == '\n') 82bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke return 0; 83bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 84bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (ptr >= shader) { 85bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* Found '#'...look for spaces preceded by a newline */ 86bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke for (ptr--; ptr >= shader && isblank(*ptr); ptr--); 87bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke // FIXME: I don't think the '\n' case can happen 88bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (ptr < shader || *ptr == '\n') 89bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke return 1; 90bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 91bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke return 0; 92bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke} 93bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke 94bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke/* Remove any line continuation characters in preprocessing directives. 95bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke * However, ignore any in GLSL code, as "There is no line continuation 96bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke * character" (1.30 page 9) in GLSL. 97bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke */ 98bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunkestatic char * 99bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunkeremove_line_continuations(glcpp_parser_t *ctx, const char *shader) 100bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke{ 101bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke int in_continued_line = 0; 102bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke int extra_newlines = 0; 103d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke char *clean = ralloc_strdup(ctx, ""); 104bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke const char *search_start = shader; 105bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke const char *newline; 106bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke while ((newline = strchr(search_start, '\n')) != NULL) { 107bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke const char *backslash = NULL; 108805cbf39224580fdb85b09a21be7cbc658f0ecf6Kenneth Graunke 109805cbf39224580fdb85b09a21be7cbc658f0ecf6Kenneth Graunke /* # of characters preceding the newline. */ 110805cbf39224580fdb85b09a21be7cbc658f0ecf6Kenneth Graunke int n = newline - shader; 111805cbf39224580fdb85b09a21be7cbc658f0ecf6Kenneth Graunke 112bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* Find the preceding '\', if it exists */ 113805cbf39224580fdb85b09a21be7cbc658f0ecf6Kenneth Graunke if (n >= 1 && newline[-1] == '\\') 114bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke backslash = newline - 1; 115805cbf39224580fdb85b09a21be7cbc658f0ecf6Kenneth Graunke else if (n >= 2 && newline[-1] == '\r' && newline[-2] == '\\') 116bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke backslash = newline - 2; 117805cbf39224580fdb85b09a21be7cbc658f0ecf6Kenneth Graunke 118bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* Double backslashes don't count (the backslash is escaped) */ 119bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (backslash != NULL && backslash[-1] == '\\') { 120bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke backslash = NULL; 121bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 122bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke 123bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (backslash != NULL) { 124bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* We found a line continuation, but do we care? */ 125bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (!in_continued_line) { 126bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (in_directive(shader, backslash)) { 127bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke in_continued_line = 1; 128bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke extra_newlines = 0; 129bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 130bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 131bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke if (in_continued_line) { 132bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* Copy everything before the \ */ 133d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_strncat(&clean, shader, backslash - shader); 134bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke shader = newline + 1; 135bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke extra_newlines++; 136bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 137bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } else if (in_continued_line) { 138bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* Copy everything up to and including the \n */ 139d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_strncat(&clean, shader, newline - shader + 1); 140bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke shader = newline + 1; 141bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke /* Output extra newlines to make line numbers match */ 142bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke for (; extra_newlines > 0; extra_newlines--) 143d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_strcat(&clean, "\n"); 144bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke in_continued_line = 0; 145bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 146bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke search_start = newline + 1; 147bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke } 148d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_strcat(&clean, shader); 149bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke return clean; 150bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke} 151bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke 1521be5d1c887b3308865c8f4770138a9d70251392fBrian Paulint 1537cfd42cefe1949af51ecced9891f415eca2c0e66Dave Airlieglcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log, 1547dcfc44b72f00ba5a38cb02123c80113440f0de9Kenneth Graunke const struct gl_extensions *extensions, int api) 15504ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke{ 15604ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke int errors; 1577dcfc44b72f00ba5a38cb02123c80113440f0de9Kenneth Graunke glcpp_parser_t *parser = glcpp_parser_create (extensions, api); 158bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke *shader = remove_line_continuations(parser, *shader); 159bc1097d151677ace501a1f78c11e40ed5b80fdc6Kenneth Graunke 16004ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke glcpp_lex_set_source_string (parser, *shader); 16104ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke 16204ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke glcpp_parser_parse (parser); 16304ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke 164da6b10a7eb26c8a13056cbae9015d5b84f134142Carl Worth if (parser->skip_stack) 165da6b10a7eb26c8a13056cbae9015d5b84f134142Carl Worth glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n"); 166da6b10a7eb26c8a13056cbae9015d5b84f134142Carl Worth 167d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_strcat(info_log, parser->info_log); 16804ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke 169d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_steal(ralloc_ctx, parser->output); 17004ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke *shader = parser->output; 17104ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke 17262b4b7785a01f11e7fcd9bf76dae6b3c0a16d537Kenneth Graunke errors = parser->error; 17304ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke glcpp_parser_destroy (parser); 17404ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke return errors; 17504ba86a536d76ef24c749e16c785c1634b9187c9Kenneth Graunke} 176