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 _parse_defined(struct sl_pp_context
*context
,
36 struct sl_pp_token_buffer
*buffer
,
37 struct sl_pp_process_state
*state
)
39 struct sl_pp_token_info input
;
42 struct sl_pp_macro
*macro
;
44 struct sl_pp_token_info result
;
46 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
50 if (input
.token
== SL_PP_LPAREN
) {
51 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
57 if (input
.token
!= SL_PP_IDENTIFIER
) {
58 strcpy(context
->error_msg
, "expected an identifier");
62 macro_name
= input
.data
.identifier
;
63 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
64 if (macro
->name
== macro_name
) {
71 if (sl_pp_token_buffer_skip_white(buffer
, &input
)) {
74 if (input
.token
!= SL_PP_RPAREN
) {
75 strcpy(context
->error_msg
, "expected `)'");
80 result
.token
= SL_PP_UINT
;
81 result
.data
._uint
= (defined
? context
->dict
._1
: context
->dict
._0
);
83 if (sl_pp_process_out(state
, &result
)) {
84 strcpy(context
->error_msg
, "out of memory");
92 _evaluate_if_stack(struct sl_pp_context
*context
)
96 for (i
= context
->if_ptr
; i
< SL_PP_MAX_IF_NESTING
; i
++) {
97 if (!(context
->if_stack
[i
] & 1)) {
105 _parse_if(struct sl_pp_context
*context
,
106 struct sl_pp_token_buffer
*buffer
)
108 struct sl_pp_process_state state
;
110 struct sl_pp_token_info eof
;
113 if (!context
->if_ptr
) {
114 strcpy(context
->error_msg
, "`#if' nesting too deep");
118 memset(&state
, 0, sizeof(state
));
120 struct sl_pp_token_info input
;
122 sl_pp_token_buffer_get(buffer
, &input
);
123 switch (input
.token
) {
124 case SL_PP_WHITESPACE
:
127 case SL_PP_IDENTIFIER
:
128 if (input
.data
.identifier
== context
->dict
.defined
) {
129 if (_parse_defined(context
, buffer
, &state
)) {
134 sl_pp_token_buffer_unget(buffer
, &input
);
135 if (sl_pp_macro_expand(context
, buffer
, NULL
, &state
, sl_pp_macro_expand_unknown_to_0
)) {
148 if (sl_pp_process_out(&state
, &input
)) {
149 strcpy(context
->error_msg
, "out of memory");
156 eof
.token
= SL_PP_EOF
;
157 if (sl_pp_process_out(&state
, &eof
)) {
158 strcpy(context
->error_msg
, "out of memory");
163 if (sl_pp_execute_expression(context
, state
.out
, &result
)) {
171 context
->if_stack
[context
->if_ptr
] = result
? 1 : 0;
172 context
->if_value
= _evaluate_if_stack(context
);
178 _parse_else(struct sl_pp_context
*context
)
180 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
181 strcpy(context
->error_msg
, "no matching `#if'");
185 /* Bit b1 indicates we already went through #else. */
186 if (context
->if_stack
[context
->if_ptr
] & 2) {
187 strcpy(context
->error_msg
, "no matching `#if'");
191 /* Invert current condition value and mark that we are in the #else block. */
192 context
->if_stack
[context
->if_ptr
] = (1 - (context
->if_stack
[context
->if_ptr
] & 1)) | 2;
193 context
->if_value
= _evaluate_if_stack(context
);
199 sl_pp_process_if(struct sl_pp_context
*context
,
200 struct sl_pp_token_buffer
*buffer
)
202 return _parse_if(context
, buffer
);
206 sl_pp_process_ifdef(struct sl_pp_context
*context
,
207 const struct sl_pp_token_info
*input
,
213 if (!context
->if_ptr
) {
214 strcpy(context
->error_msg
, "`#if' nesting too deep");
218 for (i
= first
; i
< last
; i
++) {
219 switch (input
[i
].token
) {
220 case SL_PP_IDENTIFIER
:
222 struct sl_pp_macro
*macro
;
223 int macro_name
= input
[i
].data
.identifier
;
226 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
227 if (macro
->name
== macro_name
) {
234 context
->if_stack
[context
->if_ptr
] = defined
? 1 : 0;
235 context
->if_value
= _evaluate_if_stack(context
);
239 case SL_PP_WHITESPACE
:
243 strcpy(context
->error_msg
, "expected an identifier");
248 strcpy(context
->error_msg
, "expected an identifier");
253 sl_pp_process_ifndef(struct sl_pp_context
*context
,
254 const struct sl_pp_token_info
*input
,
260 if (!context
->if_ptr
) {
261 strcpy(context
->error_msg
, "`#if' nesting too deep");
265 for (i
= first
; i
< last
; i
++) {
266 switch (input
[i
].token
) {
267 case SL_PP_IDENTIFIER
:
269 struct sl_pp_macro
*macro
;
270 int macro_name
= input
[i
].data
.identifier
;
273 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
274 if (macro
->name
== macro_name
) {
281 context
->if_stack
[context
->if_ptr
] = defined
? 0 : 1;
282 context
->if_value
= _evaluate_if_stack(context
);
286 case SL_PP_WHITESPACE
:
290 strcpy(context
->error_msg
, "expected an identifier");
295 strcpy(context
->error_msg
, "expected an identifier");
300 sl_pp_process_elif(struct sl_pp_context
*context
,
301 struct sl_pp_token_buffer
*buffer
)
303 if (_parse_else(context
)) {
307 if (context
->if_stack
[context
->if_ptr
] & 1) {
309 if (_parse_if(context
, buffer
)) {
314 /* We are still in the #if block. */
315 context
->if_stack
[context
->if_ptr
] = context
->if_stack
[context
->if_ptr
] & ~2;
321 sl_pp_process_else(struct sl_pp_context
*context
,
322 const struct sl_pp_token_info
*input
,
326 return _parse_else(context
);
330 sl_pp_process_endif(struct sl_pp_context
*context
,
331 const struct sl_pp_token_info
*input
,
335 if (context
->if_ptr
== SL_PP_MAX_IF_NESTING
) {
336 strcpy(context
->error_msg
, "no matching `#if'");
341 context
->if_value
= _evaluate_if_stack(context
);