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 skip_whitespace(const struct sl_pp_token_info
*input
,
38 while (input
[*pi
].token
== SL_PP_WHITESPACE
) {
44 _parse_defined(struct sl_pp_context
*context
,
45 const struct sl_pp_token_info
*input
,
47 struct sl_pp_process_state
*state
)
51 struct sl_pp_macro
*macro
;
53 struct sl_pp_token_info result
;
55 skip_whitespace(input
, pi
);
56 if (input
[*pi
].token
== SL_PP_LPAREN
) {
58 skip_whitespace(input
, pi
);
62 if (input
[*pi
].token
!= SL_PP_IDENTIFIER
) {
63 strcpy(context
->error_msg
, "expected an identifier");
67 macro_name
= input
[*pi
].data
.identifier
;
68 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
69 if (macro
->name
== macro_name
) {
77 skip_whitespace(input
, pi
);
78 if (input
[*pi
].token
!= SL_PP_RPAREN
) {
79 strcpy(context
->error_msg
, "expected `)'");
85 result
.token
= SL_PP_UINT
;
86 result
.data
._uint
= (defined
? context
->dict
._1
: context
->dict
._0
);
88 if (sl_pp_process_out(state
, &result
)) {
89 strcpy(context
->error_msg
, "out of memory");
97 _evaluate_if_stack(struct sl_pp_context
*context
)
101 for (i
= context
->if_ptr
; i
< SL_PP_MAX_IF_NESTING
; i
++) {
102 if (!(context
->if_stack
[i
] & 1)) {
110 _parse_if(struct sl_pp_context
*context
,
111 const struct sl_pp_token_info
*input
,
116 struct sl_pp_process_state state
;
117 struct sl_pp_token_info eof
;
120 if (!context
->if_ptr
) {
121 strcpy(context
->error_msg
, "`#if' nesting too deep");
125 memset(&state
, 0, sizeof(state
));
126 for (i
= first
; i
< last
;) {
127 switch (input
[i
].token
) {
128 case SL_PP_WHITESPACE
:
132 case SL_PP_IDENTIFIER
:
133 if (input
[i
].data
.identifier
== context
->dict
.defined
) {
135 if (_parse_defined(context
, input
, &i
, &state
)) {
140 if (sl_pp_macro_expand(context
, input
, &i
, NULL
, &state
, sl_pp_macro_expand_unknown_to_0
)) {
148 if (sl_pp_process_out(&state
, &input
[i
])) {
149 strcpy(context
->error_msg
, "out of memory");
157 eof
.token
= SL_PP_EOF
;
158 if (sl_pp_process_out(&state
, &eof
)) {
159 strcpy(context
->error_msg
, "out of memory");
164 if (sl_pp_execute_expression(context
, state
.out
, &result
)) {
172 context
->if_stack
[context
->if_ptr
] = result
? 1 : 0;
173 context
->if_value
= _evaluate_if_stack(context
);
179 _parse_else(struct sl_pp_context
*context
)
181 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
182 strcpy(context
->error_msg
, "no matching `#if'");
186 /* Bit b1 indicates we already went through #else. */
187 if (context
->if_stack
[context
->if_ptr
] & 2) {
188 strcpy(context
->error_msg
, "no matching `#if'");
192 /* Invert current condition value and mark that we are in the #else block. */
193 context
->if_stack
[context
->if_ptr
] = (1 - (context
->if_stack
[context
->if_ptr
] & 1)) | 2;
194 context
->if_value
= _evaluate_if_stack(context
);
200 sl_pp_process_if(struct sl_pp_context
*context
,
201 const struct sl_pp_token_info
*input
,
205 return _parse_if(context
, input
, first
, last
);
209 sl_pp_process_ifdef(struct sl_pp_context
*context
,
210 const struct sl_pp_token_info
*input
,
216 if (!context
->if_ptr
) {
217 strcpy(context
->error_msg
, "`#if' nesting too deep");
221 for (i
= first
; i
< last
; i
++) {
222 switch (input
[i
].token
) {
223 case SL_PP_IDENTIFIER
:
225 struct sl_pp_macro
*macro
;
226 int macro_name
= input
[i
].data
.identifier
;
229 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
230 if (macro
->name
== macro_name
) {
237 context
->if_stack
[context
->if_ptr
] = defined
? 1 : 0;
238 context
->if_value
= _evaluate_if_stack(context
);
242 case SL_PP_WHITESPACE
:
246 strcpy(context
->error_msg
, "expected an identifier");
251 strcpy(context
->error_msg
, "expected an identifier");
256 sl_pp_process_ifndef(struct sl_pp_context
*context
,
257 const struct sl_pp_token_info
*input
,
263 if (!context
->if_ptr
) {
264 strcpy(context
->error_msg
, "`#if' nesting too deep");
268 for (i
= first
; i
< last
; i
++) {
269 switch (input
[i
].token
) {
270 case SL_PP_IDENTIFIER
:
272 struct sl_pp_macro
*macro
;
273 int macro_name
= input
[i
].data
.identifier
;
276 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
277 if (macro
->name
== macro_name
) {
284 context
->if_stack
[context
->if_ptr
] = defined
? 0 : 1;
285 context
->if_value
= _evaluate_if_stack(context
);
289 case SL_PP_WHITESPACE
:
293 strcpy(context
->error_msg
, "expected an identifier");
298 strcpy(context
->error_msg
, "expected an identifier");
303 sl_pp_process_elif(struct sl_pp_context
*context
,
304 const struct sl_pp_token_info
*input
,
308 if (_parse_else(context
)) {
312 if (context
->if_stack
[context
->if_ptr
] & 1) {
314 if (_parse_if(context
, input
, first
, last
)) {
319 /* We are still in the #if block. */
320 context
->if_stack
[context
->if_ptr
] = context
->if_stack
[context
->if_ptr
] & ~2;
326 sl_pp_process_else(struct sl_pp_context
*context
,
327 const struct sl_pp_token_info
*input
,
331 return _parse_else(context
);
335 sl_pp_process_endif(struct sl_pp_context
*context
,
336 const struct sl_pp_token_info
*input
,
340 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
341 strcpy(context
->error_msg
, "no matching `#if'");
346 context
->if_value
= _evaluate_if_stack(context
);