Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2010 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. #include <assert.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include "glcpp.h"
  28. #include "main/core.h" /* for isblank() on MSVC */
  29.  
  30. void
  31. glcpp_error (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
  32. {
  33.         va_list ap;
  34.  
  35.         parser->error = 1;
  36.         ralloc_asprintf_rewrite_tail(&parser->info_log,
  37.                                      &parser->info_log_length,
  38.                                      "%u:%u(%u): "
  39.                                      "preprocessor error: ",
  40.                                      locp->source,
  41.                                      locp->first_line,
  42.                                      locp->first_column);
  43.         va_start(ap, fmt);
  44.         ralloc_vasprintf_rewrite_tail(&parser->info_log,
  45.                                       &parser->info_log_length,
  46.                                       fmt, ap);
  47.         va_end(ap);
  48.         ralloc_asprintf_rewrite_tail(&parser->info_log,
  49.                                      &parser->info_log_length, "\n");
  50. }
  51.  
  52. void
  53. glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
  54. {
  55.         va_list ap;
  56.  
  57.         ralloc_asprintf_rewrite_tail(&parser->info_log,
  58.                                      &parser->info_log_length,
  59.                                      "%u:%u(%u): "
  60.                                      "preprocessor warning: ",
  61.                                      locp->source,
  62.                                      locp->first_line,
  63.                                      locp->first_column);
  64.         va_start(ap, fmt);
  65.         ralloc_vasprintf_rewrite_tail(&parser->info_log,
  66.                                       &parser->info_log_length,
  67.                                       fmt, ap);
  68.         va_end(ap);
  69.         ralloc_asprintf_rewrite_tail(&parser->info_log,
  70.                                      &parser->info_log_length, "\n");
  71. }
  72.  
  73. /* Remove any line continuation characters in the shader, (whether in
  74.  * preprocessing directives or in GLSL code).
  75.  */
  76. static char *
  77. remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
  78. {
  79.         char *clean = ralloc_strdup(ctx, "");
  80.         const char *backslash, *newline, *search_start;
  81.         int collapsed_newlines = 0;
  82.  
  83.         search_start = shader;
  84.  
  85.         while (true) {
  86.                 backslash = strchr(search_start, '\\');
  87.  
  88.                 /* If we have previously collapsed any line-continuations,
  89.                  * then we want to insert additional newlines at the next
  90.                  * occurrence of a newline character to avoid changing any
  91.                  * line numbers.
  92.                  */
  93.                 if (collapsed_newlines) {
  94.                         newline = strchr(search_start, '\n');
  95.                         if (newline &&
  96.                             (backslash == NULL || newline < backslash))
  97.                         {
  98.                                 ralloc_strncat(&clean, shader,
  99.                                                newline - shader + 1);
  100.                                 while (collapsed_newlines) {
  101.                                         ralloc_strcat(&clean, "\n");
  102.                                         collapsed_newlines--;
  103.                                 }
  104.                                 shader = newline + 1;
  105.                                 search_start = shader;
  106.                         }
  107.                 }
  108.  
  109.                 search_start = backslash + 1;
  110.  
  111.                 if (backslash == NULL)
  112.                         break;
  113.  
  114.                 /* At each line continuation, (backslash followed by a
  115.                  * newline), copy all preceding text to the output, then
  116.                  * advance the shader pointer to the character after the
  117.                  * newline.
  118.                  */
  119.                 if (backslash[1] == '\n' ||
  120.                     (backslash[1] == '\r' && backslash[2] == '\n'))
  121.                 {
  122.                         collapsed_newlines++;
  123.                         ralloc_strncat(&clean, shader, backslash - shader);
  124.                         if (backslash[1] == '\n')
  125.                                 shader = backslash + 2;
  126.                         else
  127.                                 shader = backslash + 3;
  128.                         search_start = shader;
  129.                 }
  130.         }
  131.  
  132.         ralloc_strcat(&clean, shader);
  133.  
  134.         return clean;
  135. }
  136.  
  137. int
  138. glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
  139.            const struct gl_extensions *extensions, struct gl_context *gl_ctx)
  140. {
  141.         int errors;
  142.         glcpp_parser_t *parser = glcpp_parser_create (extensions, gl_ctx->API);
  143.  
  144.         if (! gl_ctx->Const.DisableGLSLLineContinuations)
  145.                 *shader = remove_line_continuations(parser, *shader);
  146.  
  147.         glcpp_lex_set_source_string (parser, *shader);
  148.  
  149.         glcpp_parser_parse (parser);
  150.  
  151.         if (parser->skip_stack)
  152.                 glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n");
  153.  
  154.         ralloc_strcat(info_log, parser->info_log);
  155.  
  156.         ralloc_steal(ralloc_ctx, parser->output);
  157.         *shader = parser->output;
  158.  
  159.         errors = parser->error;
  160.         glcpp_parser_destroy (parser);
  161.         return errors;
  162. }
  163.