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 **************************************************************************/
31 #include "sl_pp_public.h"
32 #include "sl_pp_macro.h"
33 #include "sl_pp_process.h"
37 _macro_init(struct sl_pp_macro
*macro
)
48 struct sl_pp_macro
*macro
;
50 macro
= calloc(1, sizeof(struct sl_pp_macro
));
58 _macro_destroy(struct sl_pp_macro
*macro
)
60 struct sl_pp_macro_formal_arg
*arg
= macro
->arg
;
63 struct sl_pp_macro_formal_arg
*next_arg
= arg
->next
;
73 sl_pp_macro_free(struct sl_pp_macro
*macro
)
76 struct sl_pp_macro
*next_macro
= macro
->next
;
78 _macro_destroy(macro
);
85 sl_pp_macro_reset(struct sl_pp_macro
*macro
)
87 _macro_destroy(macro
);
92 skip_whitespace(const struct sl_pp_token_info
*input
,
95 while (input
[*pi
].token
== SL_PP_WHITESPACE
) {
101 _out_number(struct sl_pp_context
*context
,
102 struct sl_pp_process_state
*state
,
106 struct sl_pp_token_info ti
;
108 sprintf(buf
, "%u", number
);
110 ti
.token
= SL_PP_UINT
;
111 ti
.data
._uint
= sl_pp_context_add_unique_str(context
, buf
);
112 if (sl_pp_process_out(state
, &ti
)) {
113 strcpy(context
->error_msg
, "out of memory");
121 sl_pp_macro_expand(struct sl_pp_context
*context
,
122 const struct sl_pp_token_info
*input
,
124 struct sl_pp_macro
*local
,
125 struct sl_pp_process_state
*state
,
126 enum sl_pp_macro_expand_behaviour behaviour
)
128 int mute
= (behaviour
== sl_pp_macro_expand_mute
);
130 struct sl_pp_macro
*macro
= NULL
;
131 struct sl_pp_macro
*actual_arg
= NULL
;
134 if (input
[*pi
].token
!= SL_PP_IDENTIFIER
) {
135 strcpy(context
->error_msg
, "expected an identifier");
139 macro_name
= input
[*pi
].data
.identifier
;
141 /* First look for predefined macros.
144 if (macro_name
== context
->dict
.___LINE__
) {
145 if (!mute
&& _out_number(context
, state
, context
->line
)) {
151 if (macro_name
== context
->dict
.___FILE__
) {
152 if (!mute
&& _out_number(context
, state
, context
->file
)) {
158 if (macro_name
== context
->dict
.___VERSION__
) {
159 if (!mute
&& _out_number(context
, state
, 110)) {
166 /* Replace extension names with 1.
168 for (j
= 0; j
< context
->num_extensions
; j
++) {
169 if (macro_name
== context
->extensions
[j
].name
) {
170 if (!mute
&& _out_number(context
, state
, 1)) {
178 /* TODO: For FEATURE_es2_glsl, expand to 1 the following symbols.
180 * GL_FRAGMENT_PRECISION_HIGH
184 for (macro
= local
; macro
; macro
= macro
->next
) {
185 if (macro
->name
== macro_name
) {
192 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
193 if (macro
->name
== macro_name
) {
200 if (behaviour
== sl_pp_macro_expand_unknown_to_0
) {
201 if (_out_number(context
, state
, 0)) {
202 strcpy(context
->error_msg
, "out of memory");
206 if (sl_pp_process_out(state
, &input
[*pi
])) {
207 strcpy(context
->error_msg
, "out of memory");
217 if (macro
->num_args
>= 0) {
218 skip_whitespace(input
, pi
);
219 if (input
[*pi
].token
!= SL_PP_LPAREN
) {
220 strcpy(context
->error_msg
, "expected `('");
224 skip_whitespace(input
, pi
);
227 if (macro
->num_args
> 0) {
228 struct sl_pp_macro_formal_arg
*formal_arg
= macro
->arg
;
229 struct sl_pp_macro
**pmacro
= &actual_arg
;
231 for (j
= 0; j
< (unsigned int)macro
->num_args
; j
++) {
232 struct sl_pp_process_state arg_state
;
235 unsigned int paren_nesting
= 0;
236 struct sl_pp_token_info eof
;
238 memset(&arg_state
, 0, sizeof(arg_state
));
240 for (i
= *pi
; !done
;) {
241 switch (input
[i
].token
) {
242 case SL_PP_WHITESPACE
:
247 if (!paren_nesting
) {
248 if (j
< (unsigned int)macro
->num_args
- 1) {
252 strcpy(context
->error_msg
, "too many actual macro arguments");
256 if (sl_pp_process_out(&arg_state
, &input
[i
])) {
257 strcpy(context
->error_msg
, "out of memory");
267 if (sl_pp_process_out(&arg_state
, &input
[i
])) {
268 strcpy(context
->error_msg
, "out of memory");
276 if (!paren_nesting
) {
277 if (j
== (unsigned int)macro
->num_args
- 1) {
281 strcpy(context
->error_msg
, "too few actual macro arguments");
286 if (sl_pp_process_out(&arg_state
, &input
[i
])) {
287 strcpy(context
->error_msg
, "out of memory");
295 case SL_PP_IDENTIFIER
:
296 if (sl_pp_macro_expand(context
, input
, &i
, local
, &arg_state
, sl_pp_macro_expand_normal
)) {
303 strcpy(context
->error_msg
, "too few actual macro arguments");
307 if (sl_pp_process_out(&arg_state
, &input
[i
])) {
308 strcpy(context
->error_msg
, "out of memory");
318 eof
.token
= SL_PP_EOF
;
319 if (sl_pp_process_out(&arg_state
, &eof
)) {
320 strcpy(context
->error_msg
, "out of memory");
325 *pmacro
= sl_pp_macro_new();
327 strcpy(context
->error_msg
, "out of memory");
332 (**pmacro
).name
= formal_arg
->name
;
333 (**pmacro
).body
= arg_state
.out
;
335 formal_arg
= formal_arg
->next
;
336 pmacro
= &(**pmacro
).next
;
340 /* Right paren for non-empty argument list has already been eaten. */
341 if (macro
->num_args
== 0) {
342 skip_whitespace(input
, pi
);
343 if (input
[*pi
].token
!= SL_PP_RPAREN
) {
344 strcpy(context
->error_msg
, "expected `)'");
351 switch (macro
->body
[j
].token
) {
353 if (sl_pp_process_out(state
, ¯o
->body
[j
])) {
354 strcpy(context
->error_msg
, "out of memory");
360 case SL_PP_IDENTIFIER
:
361 if (sl_pp_macro_expand(context
, macro
->body
, &j
, actual_arg
, state
, behaviour
)) {
367 sl_pp_macro_free(actual_arg
);
372 if (sl_pp_process_out(state
, ¯o
->body
[j
])) {
373 strcpy(context
->error_msg
, "out of memory");