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_context.h"
31 #include "sl_pp_expression.h"
32 #include "sl_pp_macro.h"
33 #include "sl_pp_process.h"
34 #include "sl_pp_token.h"
38 _macro_is_defined(struct sl_pp_context
*context
,
42 struct sl_pp_macro
*macro
;
44 for (i
= 0; i
< context
->num_extensions
; i
++) {
45 if (macro_name
== context
->extensions
[i
].name
) {
50 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
51 if (macro_name
== macro
->name
) {
60 _parse_defined(struct sl_pp_context
*context
,
61 struct sl_pp_token_buffer
*buffer
,
62 struct sl_pp_process_state
*state
)
64 struct sl_pp_token_info input
;
67 struct sl_pp_token_info result
;
69 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
73 if (input
.token
== SL_PP_LPAREN
) {
74 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
80 if (input
.token
!= SL_PP_IDENTIFIER
) {
81 strcpy(context
->error_msg
, "expected an identifier");
85 defined
= _macro_is_defined(context
, input
.data
.identifier
);
88 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
91 if (input
.token
!= SL_PP_RPAREN
) {
92 strcpy(context
->error_msg
, "expected `)'");
97 result
.token
= SL_PP_UINT
;
98 result
.data
._uint
= (defined
? context
->dict
._1
: context
->dict
._0
);
100 if (sl_pp_process_out(state
, &result
)) {
101 strcpy(context
->error_msg
, "out of memory");
109 _evaluate_if_stack(struct sl_pp_context
*context
)
113 for (i
= context
->if_ptr
; i
< SL_PP_MAX_IF_NESTING
; i
++) {
114 if (!context
->if_stack
[i
].u
.condition
) {
122 _parse_if(struct sl_pp_context
*context
,
123 struct sl_pp_token_buffer
*buffer
)
125 struct sl_pp_process_state state
;
127 struct sl_pp_token_info eof
;
130 if (!context
->if_ptr
) {
131 strcpy(context
->error_msg
, "`#if' nesting too deep");
135 memset(&state
, 0, sizeof(state
));
137 struct sl_pp_token_info input
;
139 sl_pp_token_buffer_get(buffer
, &input
);
140 switch (input
.token
) {
141 case SL_PP_WHITESPACE
:
144 case SL_PP_IDENTIFIER
:
145 if (input
.data
.identifier
== context
->dict
.defined
) {
146 if (_parse_defined(context
, buffer
, &state
)) {
151 sl_pp_token_buffer_unget(buffer
, &input
);
152 if (sl_pp_macro_expand(context
, buffer
, NULL
, &state
, sl_pp_macro_expand_unknown_to_0
)) {
165 if (sl_pp_process_out(&state
, &input
)) {
166 strcpy(context
->error_msg
, "out of memory");
173 eof
.token
= SL_PP_EOF
;
174 if (sl_pp_process_out(&state
, &eof
)) {
175 strcpy(context
->error_msg
, "out of memory");
180 if (sl_pp_execute_expression(context
, state
.out
, &result
)) {
188 context
->if_stack
[context
->if_ptr
].value
= 0;
189 context
->if_stack
[context
->if_ptr
].u
.condition
= result
? 1 : 0;
190 context
->if_value
= _evaluate_if_stack(context
);
196 _parse_else(struct sl_pp_context
*context
)
198 union sl_pp_if_state
*state
= &context
->if_stack
[context
->if_ptr
];
200 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
201 strcpy(context
->error_msg
, "no matching `#if'");
205 if (state
->u
.went_thru_else
) {
206 strcpy(context
->error_msg
, "no matching `#if'");
210 /* Once we had a true condition, the subsequent #elifs should always be false. */
211 state
->u
.had_true_cond
|= state
->u
.condition
;
213 /* Update current condition value and mark that we are in the #else block. */
214 state
->u
.condition
= !(state
->u
.had_true_cond
| state
->u
.condition
);
215 state
->u
.went_thru_else
= 1;
216 context
->if_value
= _evaluate_if_stack(context
);
222 sl_pp_process_if(struct sl_pp_context
*context
,
223 struct sl_pp_token_buffer
*buffer
)
225 return _parse_if(context
, buffer
);
229 sl_pp_process_ifdef(struct sl_pp_context
*context
,
230 const struct sl_pp_token_info
*input
,
236 if (!context
->if_ptr
) {
237 strcpy(context
->error_msg
, "`#if' nesting too deep");
241 for (i
= first
; i
< last
; i
++) {
242 switch (input
[i
].token
) {
243 case SL_PP_IDENTIFIER
:
245 context
->if_stack
[context
->if_ptr
].value
= 0;
246 context
->if_stack
[context
->if_ptr
].u
.condition
= _macro_is_defined(context
, input
[i
].data
.identifier
);
247 context
->if_value
= _evaluate_if_stack(context
);
250 case SL_PP_WHITESPACE
:
254 strcpy(context
->error_msg
, "expected an identifier");
259 strcpy(context
->error_msg
, "expected an identifier");
264 sl_pp_process_ifndef(struct sl_pp_context
*context
,
265 const struct sl_pp_token_info
*input
,
271 if (!context
->if_ptr
) {
272 strcpy(context
->error_msg
, "`#if' nesting too deep");
276 for (i
= first
; i
< last
; i
++) {
277 switch (input
[i
].token
) {
278 case SL_PP_IDENTIFIER
:
280 context
->if_stack
[context
->if_ptr
].value
= 0;
281 context
->if_stack
[context
->if_ptr
].u
.condition
= !_macro_is_defined(context
, input
[i
].data
.identifier
);
282 context
->if_value
= _evaluate_if_stack(context
);
285 case SL_PP_WHITESPACE
:
289 strcpy(context
->error_msg
, "expected an identifier");
294 strcpy(context
->error_msg
, "expected an identifier");
299 sl_pp_process_elif(struct sl_pp_context
*context
,
300 struct sl_pp_token_buffer
*buffer
)
302 if (_parse_else(context
)) {
306 if (context
->if_stack
[context
->if_ptr
].u
.condition
) {
308 if (_parse_if(context
, buffer
)) {
313 /* We are still in the #if block. */
314 context
->if_stack
[context
->if_ptr
].u
.went_thru_else
= 0;
320 sl_pp_process_else(struct sl_pp_context
*context
,
321 const struct sl_pp_token_info
*input
,
325 return _parse_else(context
);
329 sl_pp_process_endif(struct sl_pp_context
*context
,
330 const struct sl_pp_token_info
*input
,
334 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
335 strcpy(context
->error_msg
, "no matching `#if'");
340 context
->if_value
= _evaluate_if_stack(context
);