~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/compiler/glsl/glcpp/pp.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
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/mtypes.h"
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
 
        _mesa_string_buffer_printf(parser->info_log,
37
 
                                   "%u:%u(%u): "
38
 
                                   "preprocessor error: ",
39
 
                                   locp->source,
40
 
                                   locp->first_line,
41
 
                                   locp->first_column);
42
 
        va_start(ap, fmt);
43
 
        _mesa_string_buffer_vprintf(parser->info_log, fmt, ap);
44
 
        va_end(ap);
45
 
        _mesa_string_buffer_append_char(parser->info_log, '\n');
46
 
}
47
 
 
48
 
void
49
 
glcpp_warning (YYLTYPE *locp, glcpp_parser_t *parser, const char *fmt, ...)
50
 
{
51
 
        va_list ap;
52
 
 
53
 
        _mesa_string_buffer_printf(parser->info_log,
54
 
                                     "%u:%u(%u): "
55
 
                                     "preprocessor warning: ",
56
 
                                     locp->source,
57
 
                                     locp->first_line,
58
 
                                     locp->first_column);
59
 
        va_start(ap, fmt);
60
 
        _mesa_string_buffer_vprintf(parser->info_log, fmt, ap);
61
 
        va_end(ap);
62
 
        _mesa_string_buffer_append_char(parser->info_log, '\n');
63
 
}
64
 
 
65
 
/* Given str, (that's expected to start with a newline terminator of some
66
 
 * sort), return a pointer to the first character in str after the newline.
67
 
 *
68
 
 * A newline terminator can be any of the following sequences:
69
 
 *
70
 
 *      "\r\n"
71
 
 *      "\n\r"
72
 
 *      "\n"
73
 
 *      "\r"
74
 
 *
75
 
 * And the longest such sequence will be skipped.
76
 
 */
77
 
static const char *
78
 
skip_newline (const char *str)
79
 
{
80
 
        const char *ret = str;
81
 
 
82
 
        if (ret == NULL)
83
 
                return ret;
84
 
 
85
 
        if (*ret == '\0')
86
 
                return ret;
87
 
 
88
 
        if (*ret == '\r') {
89
 
                ret++;
90
 
                if (*ret && *ret == '\n')
91
 
                        ret++;
92
 
        } else if (*ret == '\n') {
93
 
                ret++;
94
 
                if (*ret && *ret == '\r')
95
 
                        ret++;
96
 
        }
97
 
 
98
 
        return ret;
99
 
}
100
 
 
101
 
/* Initial output buffer size, 4096 minus ralloc() overhead. It was selected
102
 
 * to minimize total amount of allocated memory during shader-db run.
103
 
 */
104
 
#define INITIAL_PP_OUTPUT_BUF_SIZE 4048
105
 
 
106
 
/* Remove any line continuation characters in the shader, (whether in
107
 
 * preprocessing directives or in GLSL code).
108
 
 */
109
 
static char *
110
 
remove_line_continuations(glcpp_parser_t *ctx, const char *shader)
111
 
{
112
 
        struct _mesa_string_buffer *sb =
113
 
                _mesa_string_buffer_create(ctx, INITIAL_PP_OUTPUT_BUF_SIZE);
114
 
 
115
 
        const char *backslash, *newline, *search_start;
116
 
        const char *cr, *lf;
117
 
        char newline_separator[3];
118
 
        int collapsed_newlines = 0;
119
 
        int separator_len;
120
 
 
121
 
        backslash = strchr(shader, '\\');
122
 
 
123
 
        /* No line continuations were found in this shader, our job is done */
124
 
        if (backslash == NULL)
125
 
                return (char *) shader;
126
 
 
127
 
        search_start = shader;
128
 
 
129
 
        /* Determine what flavor of newlines this shader is using. GLSL
130
 
         * provides for 4 different possible ways to separate lines, (using
131
 
         * one or two characters):
132
 
         *
133
 
         *      "\n" (line-feed, like Linux, Unix, and new Mac OS)
134
 
         *      "\r" (carriage-return, like old Mac files)
135
 
         *      "\r\n" (carriage-return + line-feed, like DOS files)
136
 
         *      "\n\r" (line-feed + carriage-return, like nothing, really)
137
 
         *
138
 
         * This code explicitly supports a shader that uses a mixture of
139
 
         * newline terminators and will properly handle line continuation
140
 
         * backslashes followed by any of the above.
141
 
         *
142
 
         * But, since we must also insert additional newlines in the output
143
 
         * (for any collapsed lines) we attempt to maintain consistency by
144
 
         * examining the first encountered newline terminator, and using the
145
 
         * same terminator for any newlines we insert.
146
 
         */
147
 
        cr = strchr(search_start, '\r');
148
 
        lf = strchr(search_start, '\n');
149
 
 
150
 
        newline_separator[0] = '\n';
151
 
        newline_separator[1] = '\0';
152
 
        newline_separator[2] = '\0';
153
 
 
154
 
        if (cr == NULL) {
155
 
                /* Nothing to do. */
156
 
        } else if (lf == NULL) {
157
 
                newline_separator[0] = '\r';
158
 
        } else if (lf == cr + 1) {
159
 
                newline_separator[0] = '\r';
160
 
                newline_separator[1] = '\n';
161
 
        } else if (cr == lf + 1) {
162
 
                newline_separator[0] = '\n';
163
 
                newline_separator[1] = '\r';
164
 
        }
165
 
        separator_len = strlen(newline_separator);
166
 
 
167
 
        while (true) {
168
 
                /* If we have previously collapsed any line-continuations,
169
 
                 * then we want to insert additional newlines at the next
170
 
                 * occurrence of a newline character to avoid changing any
171
 
                 * line numbers.
172
 
                 */
173
 
                if (collapsed_newlines) {
174
 
                        cr = strchr (search_start, '\r');
175
 
                        lf = strchr (search_start, '\n');
176
 
                        if (cr && lf)
177
 
                                newline = cr < lf ? cr : lf;
178
 
                        else if (cr)
179
 
                                newline = cr;
180
 
                        else
181
 
                                newline = lf;
182
 
                        if (newline &&
183
 
                            (backslash == NULL || newline < backslash))
184
 
                        {
185
 
                                _mesa_string_buffer_append_len(sb, shader,
186
 
                                                               newline - shader + 1);
187
 
                                while (collapsed_newlines) {
188
 
                                        _mesa_string_buffer_append_len(sb,
189
 
                                                                       newline_separator,
190
 
                                                                       separator_len);
191
 
                                        collapsed_newlines--;
192
 
                                }
193
 
                                shader = skip_newline (newline);
194
 
                                search_start = shader;
195
 
                        }
196
 
                }
197
 
 
198
 
                if (backslash == NULL)
199
 
                        break;
200
 
 
201
 
                search_start = backslash + 1;
202
 
 
203
 
                /* At each line continuation, (backslash followed by a
204
 
                 * newline), copy all preceding text to the output, then
205
 
                 * advance the shader pointer to the character after the
206
 
                 * newline.
207
 
                 */
208
 
                if (backslash[1] == '\r' || backslash[1] == '\n')
209
 
                {
210
 
                        collapsed_newlines++;
211
 
                        _mesa_string_buffer_append_len(sb, shader, backslash - shader);
212
 
                        shader = skip_newline (backslash + 1);
213
 
                        search_start = shader;
214
 
                }
215
 
 
216
 
                backslash = strchr(search_start, '\\');
217
 
        }
218
 
 
219
 
        _mesa_string_buffer_append(sb, shader);
220
 
 
221
 
        return sb->buf;
222
 
}
223
 
 
224
 
int
225
 
glcpp_preprocess(void *ralloc_ctx, const char **shader, char **info_log,
226
 
                 glcpp_extension_iterator extensions, void *state,
227
 
                 struct gl_context *gl_ctx)
228
 
{
229
 
        int errors;
230
 
        glcpp_parser_t *parser =
231
 
                glcpp_parser_create(gl_ctx, extensions, state);
232
 
 
233
 
        if (! gl_ctx->Const.DisableGLSLLineContinuations)
234
 
                *shader = remove_line_continuations(parser, *shader);
235
 
 
236
 
        glcpp_lex_set_source_string (parser, *shader);
237
 
 
238
 
        glcpp_parser_parse (parser);
239
 
 
240
 
        if (parser->skip_stack)
241
 
                glcpp_error (&parser->skip_stack->loc, parser, "Unterminated #if\n");
242
 
 
243
 
        glcpp_parser_resolve_implicit_version(parser);
244
 
 
245
 
        ralloc_strcat(info_log, parser->info_log->buf);
246
 
 
247
 
        /* Crimp the buffer first, to conserve memory */
248
 
        _mesa_string_buffer_crimp_to_fit(parser->output);
249
 
 
250
 
        ralloc_steal(ralloc_ctx, parser->output->buf);
251
 
        *shader = parser->output->buf;
252
 
 
253
 
        errors = parser->error;
254
 
        glcpp_parser_destroy (parser);
255
 
        return errors;
256
 
}