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_context.h"
32 #include "sl_pp_public.h"
33 #include "sl_pp_macro.h"
34 #include "sl_pp_process.h"
35 #include "sl_pp_token.h"
39 _macro_init(struct sl_pp_macro
*macro
)
50 struct sl_pp_macro
*macro
;
52 macro
= calloc(1, sizeof(struct sl_pp_macro
));
60 _macro_destroy(struct sl_pp_macro
*macro
)
62 struct sl_pp_macro_formal_arg
*arg
= macro
->arg
;
65 struct sl_pp_macro_formal_arg
*next_arg
= arg
->next
;
75 sl_pp_macro_free(struct sl_pp_macro
*macro
)
78 struct sl_pp_macro
*next_macro
= macro
->next
;
80 _macro_destroy(macro
);
87 sl_pp_macro_reset(struct sl_pp_macro
*macro
)
89 _macro_destroy(macro
);
94 _out_number(struct sl_pp_context
*context
,
95 struct sl_pp_process_state
*state
,
99 struct sl_pp_token_info ti
;
101 sprintf(buf
, "%u", number
);
103 ti
.token
= SL_PP_UINT
;
104 ti
.data
._uint
= sl_pp_context_add_unique_str(context
, buf
);
105 if (sl_pp_process_out(state
, &ti
)) {
106 strcpy(context
->error_msg
, "out of memory");
114 sl_pp_macro_expand(struct sl_pp_context
*context
,
115 struct sl_pp_token_buffer
*tokens
,
116 struct sl_pp_macro
*local
,
117 struct sl_pp_process_state
*state
,
118 enum sl_pp_macro_expand_behaviour behaviour
)
120 int mute
= (behaviour
== sl_pp_macro_expand_mute
);
121 struct sl_pp_token_info input
;
123 struct sl_pp_macro
*macro
= NULL
;
124 struct sl_pp_macro
*actual_arg
= NULL
;
127 if (sl_pp_token_buffer_get(tokens
, &input
)) {
131 if (input
.token
!= SL_PP_IDENTIFIER
) {
132 strcpy(context
->error_msg
, "expected an identifier");
136 macro_name
= input
.data
.identifier
;
138 /* First look for predefined macros.
141 if (macro_name
== context
->dict
.___LINE__
) {
142 if (!mute
&& _out_number(context
, state
, context
->line
)) {
147 if (macro_name
== context
->dict
.___FILE__
) {
148 if (!mute
&& _out_number(context
, state
, context
->file
)) {
153 if (macro_name
== context
->dict
.___VERSION__
) {
154 if (!mute
&& _out_number(context
, state
, 110)) {
160 for (j
= 0; j
< context
->num_predefined
; j
++) {
161 if (macro_name
== context
->predefined
[j
].name
) {
163 struct sl_pp_token_info ti
;
165 ti
.token
= SL_PP_UINT
;
166 ti
.data
._uint
= context
->predefined
[j
].value
;
167 if (sl_pp_process_out(state
, &ti
)) {
168 strcpy(context
->error_msg
, "out of memory");
176 /* Replace extension names with 1.
178 for (j
= 0; j
< context
->num_extensions
; j
++) {
179 if (macro_name
== context
->extensions
[j
].name
) {
180 if (!mute
&& _out_number(context
, state
, 1)) {
188 for (macro
= local
; macro
; macro
= macro
->next
) {
189 if (macro
->name
== macro_name
) {
196 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
197 if (macro
->name
== macro_name
) {
204 if (behaviour
== sl_pp_macro_expand_unknown_to_0
) {
205 if (_out_number(context
, state
, 0)) {
206 strcpy(context
->error_msg
, "out of memory");
210 if (sl_pp_process_out(state
, &input
)) {
211 strcpy(context
->error_msg
, "out of memory");
218 if (macro
->num_args
>= 0) {
219 if (sl_pp_token_buffer_skip_white(tokens
, &input
)) {
222 if (input
.token
!= SL_PP_LPAREN
) {
223 strcpy(context
->error_msg
, "expected `('");
226 if (sl_pp_token_buffer_skip_white(tokens
, &input
)) {
229 sl_pp_token_buffer_unget(tokens
, &input
);
232 if (macro
->num_args
> 0) {
233 struct sl_pp_macro_formal_arg
*formal_arg
= macro
->arg
;
234 struct sl_pp_macro
**pmacro
= &actual_arg
;
236 for (j
= 0; j
< (unsigned int)macro
->num_args
; j
++) {
237 struct sl_pp_process_state arg_state
;
239 unsigned int paren_nesting
= 0;
240 struct sl_pp_token_info eof
;
242 memset(&arg_state
, 0, sizeof(arg_state
));
245 if (sl_pp_token_buffer_get(tokens
, &input
)) {
248 switch (input
.token
) {
249 case SL_PP_WHITESPACE
:
253 if (!paren_nesting
) {
254 if (j
< (unsigned int)macro
->num_args
- 1) {
257 strcpy(context
->error_msg
, "too many actual macro arguments");
261 if (sl_pp_process_out(&arg_state
, &input
)) {
262 strcpy(context
->error_msg
, "out of memory");
270 if (sl_pp_process_out(&arg_state
, &input
)) {
276 if (!paren_nesting
) {
277 if (j
== (unsigned int)macro
->num_args
- 1) {
280 strcpy(context
->error_msg
, "too few actual macro arguments");
285 if (sl_pp_process_out(&arg_state
, &input
)) {
291 case SL_PP_IDENTIFIER
:
292 sl_pp_token_buffer_unget(tokens
, &input
);
293 if (sl_pp_macro_expand(context
, tokens
, local
, &arg_state
, sl_pp_macro_expand_normal
)) {
299 strcpy(context
->error_msg
, "too few actual macro arguments");
303 if (sl_pp_process_out(&arg_state
, &input
)) {
309 eof
.token
= SL_PP_EOF
;
310 if (sl_pp_process_out(&arg_state
, &eof
)) {
314 *pmacro
= sl_pp_macro_new();
319 (**pmacro
).name
= formal_arg
->name
;
320 (**pmacro
).body
= arg_state
.out
;
322 formal_arg
= formal_arg
->next
;
323 pmacro
= &(**pmacro
).next
;
328 strcpy(context
->error_msg
, "out of memory");
335 /* Right paren for non-empty argument list has already been eaten. */
336 if (macro
->num_args
== 0) {
337 if (sl_pp_token_buffer_skip_white(tokens
, &input
)) {
340 if (input
.token
!= SL_PP_RPAREN
) {
341 strcpy(context
->error_msg
, "expected `)'");
346 /* XXX: This is all wrong, we should be ungetting all tokens
347 * back to the main token buffer.
350 struct sl_pp_token_buffer buffer
;
354 for (j
= 0; macro
->body
[j
].token
!= SL_PP_EOF
; j
++) {
358 /* Create a context-less token buffer since we are not going to underrun
359 * its internal buffer.
361 if (sl_pp_token_buffer_init(&buffer
, NULL
)) {
362 strcpy(context
->error_msg
, "out of memory");
366 /* Unget the tokens in reverse order so later they will be fetched correctly.
369 sl_pp_token_buffer_unget(&buffer
, ¯o
->body
[j
- 1]);
375 struct sl_pp_token_info input
;
377 sl_pp_token_buffer_get(&buffer
, &input
);
378 switch (input
.token
) {
380 if (sl_pp_process_out(state
, &input
)) {
381 strcpy(context
->error_msg
, "out of memory");
382 sl_pp_token_buffer_destroy(&buffer
);
387 case SL_PP_IDENTIFIER
:
388 sl_pp_token_buffer_unget(&buffer
, &input
);
389 if (sl_pp_macro_expand(context
, &buffer
, actual_arg
, state
, behaviour
)) {
390 sl_pp_token_buffer_destroy(&buffer
);
396 sl_pp_token_buffer_destroy(&buffer
);
397 sl_pp_macro_free(actual_arg
);
402 if (sl_pp_process_out(state
, &input
)) {
403 strcpy(context
->error_msg
, "out of memory");
404 sl_pp_token_buffer_destroy(&buffer
);
413 sl_pp_macro_free(actual_arg
);