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 _out_number(struct sl_pp_context
*context
,
93 struct sl_pp_process_state
*state
,
97 struct sl_pp_token_info ti
;
99 sprintf(buf
, "%u", number
);
101 ti
.token
= SL_PP_UINT
;
102 ti
.data
._uint
= sl_pp_context_add_unique_str(context
, buf
);
103 if (sl_pp_process_out(state
, &ti
)) {
104 strcpy(context
->error_msg
, "out of memory");
112 sl_pp_macro_expand(struct sl_pp_context
*context
,
113 struct sl_pp_token_buffer
*tokens
,
114 struct sl_pp_macro
*local
,
115 struct sl_pp_process_state
*state
,
116 enum sl_pp_macro_expand_behaviour behaviour
)
118 int mute
= (behaviour
== sl_pp_macro_expand_mute
);
119 struct sl_pp_token_info input
;
121 struct sl_pp_macro
*macro
= NULL
;
122 struct sl_pp_macro
*actual_arg
= NULL
;
125 if (sl_pp_token_buffer_get(tokens
, &input
)) {
129 if (input
.token
!= SL_PP_IDENTIFIER
) {
130 strcpy(context
->error_msg
, "expected an identifier");
134 macro_name
= input
.data
.identifier
;
136 /* First look for predefined macros.
139 if (macro_name
== context
->dict
.___LINE__
) {
140 if (!mute
&& _out_number(context
, state
, context
->line
)) {
145 if (macro_name
== context
->dict
.___FILE__
) {
146 if (!mute
&& _out_number(context
, state
, context
->file
)) {
151 if (macro_name
== context
->dict
.___VERSION__
) {
152 if (!mute
&& _out_number(context
, state
, 110)) {
158 for (j
= 0; j
< context
->num_predefined
; j
++) {
159 if (macro_name
== context
->predefined
[j
].name
) {
161 struct sl_pp_token_info ti
;
163 ti
.token
= SL_PP_UINT
;
164 ti
.data
._uint
= context
->predefined
[j
].value
;
165 if (sl_pp_process_out(state
, &ti
)) {
166 strcpy(context
->error_msg
, "out of memory");
174 /* Replace extension names with 1.
176 for (j
= 0; j
< context
->num_extensions
; j
++) {
177 if (macro_name
== context
->extensions
[j
].name
) {
178 if (!mute
&& _out_number(context
, state
, 1)) {
186 for (macro
= local
; macro
; macro
= macro
->next
) {
187 if (macro
->name
== macro_name
) {
194 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
195 if (macro
->name
== macro_name
) {
202 if (behaviour
== sl_pp_macro_expand_unknown_to_0
) {
203 if (_out_number(context
, state
, 0)) {
204 strcpy(context
->error_msg
, "out of memory");
208 if (sl_pp_process_out(state
, &input
)) {
209 strcpy(context
->error_msg
, "out of memory");
216 if (macro
->num_args
>= 0) {
217 if (sl_pp_token_buffer_skip_white(tokens
, &input
)) {
220 if (input
.token
!= SL_PP_LPAREN
) {
221 strcpy(context
->error_msg
, "expected `('");
224 if (sl_pp_token_buffer_skip_white(tokens
, &input
)) {
227 sl_pp_token_buffer_unget(tokens
, &input
);
230 if (macro
->num_args
> 0) {
231 struct sl_pp_macro_formal_arg
*formal_arg
= macro
->arg
;
232 struct sl_pp_macro
**pmacro
= &actual_arg
;
234 for (j
= 0; j
< (unsigned int)macro
->num_args
; j
++) {
235 struct sl_pp_process_state arg_state
;
237 unsigned int paren_nesting
= 0;
238 struct sl_pp_token_info eof
;
240 memset(&arg_state
, 0, sizeof(arg_state
));
243 if (sl_pp_token_buffer_get(tokens
, &input
)) {
246 switch (input
.token
) {
247 case SL_PP_WHITESPACE
:
251 if (!paren_nesting
) {
252 if (j
< (unsigned int)macro
->num_args
- 1) {
255 strcpy(context
->error_msg
, "too many actual macro arguments");
259 if (sl_pp_process_out(&arg_state
, &input
)) {
260 strcpy(context
->error_msg
, "out of memory");
268 if (sl_pp_process_out(&arg_state
, &input
)) {
274 if (!paren_nesting
) {
275 if (j
== (unsigned int)macro
->num_args
- 1) {
278 strcpy(context
->error_msg
, "too few actual macro arguments");
283 if (sl_pp_process_out(&arg_state
, &input
)) {
289 case SL_PP_IDENTIFIER
:
290 sl_pp_token_buffer_unget(tokens
, &input
);
291 if (sl_pp_macro_expand(context
, tokens
, local
, &arg_state
, sl_pp_macro_expand_normal
)) {
297 strcpy(context
->error_msg
, "too few actual macro arguments");
301 if (sl_pp_process_out(&arg_state
, &input
)) {
307 eof
.token
= SL_PP_EOF
;
308 if (sl_pp_process_out(&arg_state
, &eof
)) {
312 *pmacro
= sl_pp_macro_new();
317 (**pmacro
).name
= formal_arg
->name
;
318 (**pmacro
).body
= arg_state
.out
;
320 formal_arg
= formal_arg
->next
;
321 pmacro
= &(**pmacro
).next
;
326 strcpy(context
->error_msg
, "out of memory");
333 /* Right paren for non-empty argument list has already been eaten. */
334 if (macro
->num_args
== 0) {
335 if (sl_pp_token_buffer_skip_white(tokens
, &input
)) {
338 if (input
.token
!= SL_PP_RPAREN
) {
339 strcpy(context
->error_msg
, "expected `)'");
344 /* XXX: This is all wrong, we should be ungetting all tokens
345 * back to the main token buffer.
348 struct sl_pp_token_buffer buffer
;
352 for (j
= 0; macro
->body
[j
].token
!= SL_PP_EOF
; j
++) {
356 /* Create a context-less token buffer since we are not going to underrun
357 * its internal buffer.
359 if (sl_pp_token_buffer_init(&buffer
, NULL
)) {
360 strcpy(context
->error_msg
, "out of memory");
364 /* Unget the tokens in reverse order so later they will be fetched correctly.
367 sl_pp_token_buffer_unget(&buffer
, ¯o
->body
[j
- 1]);
373 struct sl_pp_token_info input
;
375 sl_pp_token_buffer_get(&buffer
, &input
);
376 switch (input
.token
) {
378 if (sl_pp_process_out(state
, &input
)) {
379 strcpy(context
->error_msg
, "out of memory");
380 sl_pp_token_buffer_destroy(&buffer
);
385 case SL_PP_IDENTIFIER
:
386 sl_pp_token_buffer_unget(&buffer
, &input
);
387 if (sl_pp_macro_expand(context
, &buffer
, actual_arg
, state
, behaviour
)) {
388 sl_pp_token_buffer_destroy(&buffer
);
394 sl_pp_token_buffer_destroy(&buffer
);
395 sl_pp_macro_free(actual_arg
);
400 if (sl_pp_process_out(state
, &input
)) {
401 strcpy(context
->error_msg
, "out of memory");
402 sl_pp_token_buffer_destroy(&buffer
);
411 sl_pp_macro_free(actual_arg
);