1 /**************************************************************************
3 * Copyright 2009 VMware, Inc.
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
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 **************************************************************************/
30 #include "sl_pp_expression.h"
31 #include "sl_pp_process.h"
35 _macro_is_defined(struct sl_pp_context
*context
,
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 context
->extensions
[i
].enabled
;
47 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
48 if (macro_name
== macro
->name
) {
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
;
64 struct sl_pp_token_info result
;
66 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
70 if (input
.token
== SL_PP_LPAREN
) {
71 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
77 if (input
.token
!= SL_PP_IDENTIFIER
) {
78 strcpy(context
->error_msg
, "expected an identifier");
82 defined
= _macro_is_defined(context
, input
.data
.identifier
);
85 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
88 if (input
.token
!= SL_PP_RPAREN
) {
89 strcpy(context
->error_msg
, "expected `)'");
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");
106 _evaluate_if_stack(struct sl_pp_context
*context
)
110 for (i
= context
->if_ptr
; i
< SL_PP_MAX_IF_NESTING
; i
++) {
111 if (!(context
->if_stack
[i
] & 1)) {
119 _parse_if(struct sl_pp_context
*context
,
120 struct sl_pp_token_buffer
*buffer
)
122 struct sl_pp_process_state state
;
124 struct sl_pp_token_info eof
;
127 if (!context
->if_ptr
) {
128 strcpy(context
->error_msg
, "`#if' nesting too deep");
132 memset(&state
, 0, sizeof(state
));
134 struct sl_pp_token_info input
;
136 sl_pp_token_buffer_get(buffer
, &input
);
137 switch (input
.token
) {
138 case SL_PP_WHITESPACE
:
141 case SL_PP_IDENTIFIER
:
142 if (input
.data
.identifier
== context
->dict
.defined
) {
143 if (_parse_defined(context
, buffer
, &state
)) {
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
)) {
162 if (sl_pp_process_out(&state
, &input
)) {
163 strcpy(context
->error_msg
, "out of memory");
170 eof
.token
= SL_PP_EOF
;
171 if (sl_pp_process_out(&state
, &eof
)) {
172 strcpy(context
->error_msg
, "out of memory");
177 if (sl_pp_execute_expression(context
, state
.out
, &result
)) {
185 context
->if_stack
[context
->if_ptr
] = result
? 1 : 0;
186 context
->if_value
= _evaluate_if_stack(context
);
192 _parse_else(struct sl_pp_context
*context
)
194 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
195 strcpy(context
->error_msg
, "no matching `#if'");
199 /* Bit b1 indicates we already went through #else. */
200 if (context
->if_stack
[context
->if_ptr
] & 2) {
201 strcpy(context
->error_msg
, "no matching `#if'");
205 /* Invert current condition value and mark that we are in the #else block. */
206 context
->if_stack
[context
->if_ptr
] = (1 - (context
->if_stack
[context
->if_ptr
] & 1)) | 2;
207 context
->if_value
= _evaluate_if_stack(context
);
213 sl_pp_process_if(struct sl_pp_context
*context
,
214 struct sl_pp_token_buffer
*buffer
)
216 return _parse_if(context
, buffer
);
220 sl_pp_process_ifdef(struct sl_pp_context
*context
,
221 const struct sl_pp_token_info
*input
,
227 if (!context
->if_ptr
) {
228 strcpy(context
->error_msg
, "`#if' nesting too deep");
232 for (i
= first
; i
< last
; i
++) {
233 switch (input
[i
].token
) {
234 case SL_PP_IDENTIFIER
:
236 context
->if_stack
[context
->if_ptr
] = _macro_is_defined(context
, input
[i
].data
.identifier
);
237 context
->if_value
= _evaluate_if_stack(context
);
240 case SL_PP_WHITESPACE
:
244 strcpy(context
->error_msg
, "expected an identifier");
249 strcpy(context
->error_msg
, "expected an identifier");
254 sl_pp_process_ifndef(struct sl_pp_context
*context
,
255 const struct sl_pp_token_info
*input
,
261 if (!context
->if_ptr
) {
262 strcpy(context
->error_msg
, "`#if' nesting too deep");
266 for (i
= first
; i
< last
; i
++) {
267 switch (input
[i
].token
) {
268 case SL_PP_IDENTIFIER
:
270 context
->if_stack
[context
->if_ptr
] = !_macro_is_defined(context
, input
[i
].data
.identifier
);
271 context
->if_value
= _evaluate_if_stack(context
);
274 case SL_PP_WHITESPACE
:
278 strcpy(context
->error_msg
, "expected an identifier");
283 strcpy(context
->error_msg
, "expected an identifier");
288 sl_pp_process_elif(struct sl_pp_context
*context
,
289 struct sl_pp_token_buffer
*buffer
)
291 if (_parse_else(context
)) {
295 if (context
->if_stack
[context
->if_ptr
] & 1) {
297 if (_parse_if(context
, buffer
)) {
302 /* We are still in the #if block. */
303 context
->if_stack
[context
->if_ptr
] = context
->if_stack
[context
->if_ptr
] & ~2;
309 sl_pp_process_else(struct sl_pp_context
*context
,
310 const struct sl_pp_token_info
*input
,
314 return _parse_else(context
);
318 sl_pp_process_endif(struct sl_pp_context
*context
,
319 const struct sl_pp_token_info
*input
,
323 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
324 strcpy(context
->error_msg
, "no matching `#if'");
329 context
->if_value
= _evaluate_if_stack(context
);