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
) {
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
].u
.condition
) {
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
].value
= 0;
186 context
->if_stack
[context
->if_ptr
].u
.condition
= result
? 1 : 0;
187 context
->if_value
= _evaluate_if_stack(context
);
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'");
202 if (state
->u
.went_thru_else
) {
203 strcpy(context
->error_msg
, "no matching `#if'");
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
);
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
,
233 if (!context
->if_ptr
) {
234 strcpy(context
->error_msg
, "`#if' nesting too deep");
238 for (i
= first
; i
< last
; i
++) {
239 switch (input
[i
].token
) {
240 case SL_PP_IDENTIFIER
:
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
);
247 case SL_PP_WHITESPACE
:
251 strcpy(context
->error_msg
, "expected an identifier");
256 strcpy(context
->error_msg
, "expected an identifier");
261 sl_pp_process_ifndef(struct sl_pp_context
*context
,
262 const struct sl_pp_token_info
*input
,
268 if (!context
->if_ptr
) {
269 strcpy(context
->error_msg
, "`#if' nesting too deep");
273 for (i
= first
; i
< last
; i
++) {
274 switch (input
[i
].token
) {
275 case SL_PP_IDENTIFIER
:
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
);
282 case SL_PP_WHITESPACE
:
286 strcpy(context
->error_msg
, "expected an identifier");
291 strcpy(context
->error_msg
, "expected an identifier");
296 sl_pp_process_elif(struct sl_pp_context
*context
,
297 struct sl_pp_token_buffer
*buffer
)
299 if (_parse_else(context
)) {
303 if (context
->if_stack
[context
->if_ptr
].u
.condition
) {
305 if (_parse_if(context
, buffer
)) {
310 /* We are still in the #if block. */
311 context
->if_stack
[context
->if_ptr
].u
.went_thru_else
= 0;
317 sl_pp_process_else(struct sl_pp_context
*context
,
318 const struct sl_pp_token_info
*input
,
322 return _parse_else(context
);
326 sl_pp_process_endif(struct sl_pp_context
*context
,
327 const struct sl_pp_token_info
*input
,
331 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
332 strcpy(context
->error_msg
, "no matching `#if'");
337 context
->if_value
= _evaluate_if_stack(context
);