llvmpipe: Fix rebase typo
[mesa/mesa-lb.git] / src / glsl / pp / sl_pp_if.c
blob25cb7a3ca111273c6fe4a993147b360c34171cc0
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 #include <stdlib.h>
29 #include <string.h>
30 #include "sl_pp_expression.h"
31 #include "sl_pp_process.h"
34 static int
35 _macro_is_defined(struct sl_pp_context *context,
36 int macro_name)
38 unsigned int i;
39 struct sl_pp_macro *macro;
41 for (i = 0; i < context->num_extensions; i++) {
42 if (macro_name == context->extensions[i].name) {
43 return 1;
47 for (macro = context->macro; macro; macro = macro->next) {
48 if (macro_name == macro->name) {
49 return 1;
53 return 0;
56 static int
57 _parse_defined(struct sl_pp_context *context,
58 struct sl_pp_token_buffer *buffer,
59 struct sl_pp_process_state *state)
61 struct sl_pp_token_info input;
62 int parens = 0;
63 int defined;
64 struct sl_pp_token_info result;
66 if (sl_pp_token_buffer_skip_white(buffer, &input)) {
67 return -1;
70 if (input.token == SL_PP_LPAREN) {
71 if (sl_pp_token_buffer_skip_white(buffer, &input)) {
72 return -1;
74 parens = 1;
77 if (input.token != SL_PP_IDENTIFIER) {
78 strcpy(context->error_msg, "expected an identifier");
79 return -1;
82 defined = _macro_is_defined(context, input.data.identifier);
84 if (parens) {
85 if (sl_pp_token_buffer_skip_white(buffer, &input)) {
86 return -1;
88 if (input.token != SL_PP_RPAREN) {
89 strcpy(context->error_msg, "expected `)'");
90 return -1;
94 result.token = SL_PP_UINT;
95 result.data._uint = (defined ? context->dict._1 : context->dict._0);
97 if (sl_pp_process_out(state, &result)) {
98 strcpy(context->error_msg, "out of memory");
99 return -1;
102 return 0;
105 static unsigned int
106 _evaluate_if_stack(struct sl_pp_context *context)
108 unsigned int i;
110 for (i = context->if_ptr; i < SL_PP_MAX_IF_NESTING; i++) {
111 if (!context->if_stack[i].u.condition) {
112 return 0;
115 return 1;
118 static int
119 _parse_if(struct sl_pp_context *context,
120 struct sl_pp_token_buffer *buffer)
122 struct sl_pp_process_state state;
123 int found_end = 0;
124 struct sl_pp_token_info eof;
125 int result;
127 if (!context->if_ptr) {
128 strcpy(context->error_msg, "`#if' nesting too deep");
129 return -1;
132 memset(&state, 0, sizeof(state));
133 while (!found_end) {
134 struct sl_pp_token_info input;
136 sl_pp_token_buffer_get(buffer, &input);
137 switch (input.token) {
138 case SL_PP_WHITESPACE:
139 break;
141 case SL_PP_IDENTIFIER:
142 if (input.data.identifier == context->dict.defined) {
143 if (_parse_defined(context, buffer, &state)) {
144 free(state.out);
145 return -1;
147 } else {
148 sl_pp_token_buffer_unget(buffer, &input);
149 if (sl_pp_macro_expand(context, buffer, NULL, &state, sl_pp_macro_expand_unknown_to_0)) {
150 free(state.out);
151 return -1;
154 break;
156 case SL_PP_NEWLINE:
157 case SL_PP_EOF:
158 found_end = 1;
159 break;
161 default:
162 if (sl_pp_process_out(&state, &input)) {
163 strcpy(context->error_msg, "out of memory");
164 free(state.out);
165 return -1;
170 eof.token = SL_PP_EOF;
171 if (sl_pp_process_out(&state, &eof)) {
172 strcpy(context->error_msg, "out of memory");
173 free(state.out);
174 return -1;
177 if (sl_pp_execute_expression(context, state.out, &result)) {
178 free(state.out);
179 return -1;
182 free(state.out);
184 context->if_ptr--;
185 context->if_stack[context->if_ptr].value = 0;
186 context->if_stack[context->if_ptr].u.condition = result ? 1 : 0;
187 context->if_value = _evaluate_if_stack(context);
189 return 0;
192 static int
193 _parse_else(struct sl_pp_context *context)
195 union sl_pp_if_state *state = &context->if_stack[context->if_ptr];
197 if (context->if_ptr == SL_PP_MAX_IF_NESTING) {
198 strcpy(context->error_msg, "no matching `#if'");
199 return -1;
202 if (state->u.went_thru_else) {
203 strcpy(context->error_msg, "no matching `#if'");
204 return -1;
207 /* Once we had a true condition, the subsequent #elifs should always be false. */
208 state->u.had_true_cond |= state->u.condition;
210 /* Update current condition value and mark that we are in the #else block. */
211 state->u.condition = !(state->u.had_true_cond | state->u.condition);
212 state->u.went_thru_else = 1;
213 context->if_value = _evaluate_if_stack(context);
215 return 0;
219 sl_pp_process_if(struct sl_pp_context *context,
220 struct sl_pp_token_buffer *buffer)
222 return _parse_if(context, buffer);
226 sl_pp_process_ifdef(struct sl_pp_context *context,
227 const struct sl_pp_token_info *input,
228 unsigned int first,
229 unsigned int last)
231 unsigned int i;
233 if (!context->if_ptr) {
234 strcpy(context->error_msg, "`#if' nesting too deep");
235 return -1;
238 for (i = first; i < last; i++) {
239 switch (input[i].token) {
240 case SL_PP_IDENTIFIER:
241 context->if_ptr--;
242 context->if_stack[context->if_ptr].value = 0;
243 context->if_stack[context->if_ptr].u.condition = _macro_is_defined(context, input[i].data.identifier);
244 context->if_value = _evaluate_if_stack(context);
245 return 0;
247 case SL_PP_WHITESPACE:
248 break;
250 default:
251 strcpy(context->error_msg, "expected an identifier");
252 return -1;
256 strcpy(context->error_msg, "expected an identifier");
257 return -1;
261 sl_pp_process_ifndef(struct sl_pp_context *context,
262 const struct sl_pp_token_info *input,
263 unsigned int first,
264 unsigned int last)
266 unsigned int i;
268 if (!context->if_ptr) {
269 strcpy(context->error_msg, "`#if' nesting too deep");
270 return -1;
273 for (i = first; i < last; i++) {
274 switch (input[i].token) {
275 case SL_PP_IDENTIFIER:
276 context->if_ptr--;
277 context->if_stack[context->if_ptr].value = 0;
278 context->if_stack[context->if_ptr].u.condition = !_macro_is_defined(context, input[i].data.identifier);
279 context->if_value = _evaluate_if_stack(context);
280 return 0;
282 case SL_PP_WHITESPACE:
283 break;
285 default:
286 strcpy(context->error_msg, "expected an identifier");
287 return -1;
291 strcpy(context->error_msg, "expected an identifier");
292 return -1;
296 sl_pp_process_elif(struct sl_pp_context *context,
297 struct sl_pp_token_buffer *buffer)
299 if (_parse_else(context)) {
300 return -1;
303 if (context->if_stack[context->if_ptr].u.condition) {
304 context->if_ptr++;
305 if (_parse_if(context, buffer)) {
306 return -1;
310 /* We are still in the #if block. */
311 context->if_stack[context->if_ptr].u.went_thru_else = 0;
313 return 0;
317 sl_pp_process_else(struct sl_pp_context *context,
318 const struct sl_pp_token_info *input,
319 unsigned int first,
320 unsigned int last)
322 return _parse_else(context);
326 sl_pp_process_endif(struct sl_pp_context *context,
327 const struct sl_pp_token_info *input,
328 unsigned int first,
329 unsigned int last)
331 if (context->if_ptr == SL_PP_MAX_IF_NESTING) {
332 strcpy(context->error_msg, "no matching `#if'");
333 return -1;
336 context->if_ptr++;
337 context->if_value = _evaluate_if_stack(context);
339 return 0;