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_macro.h"
31 #include "sl_pp_process.h"
35 _macro_init(struct sl_pp_macro
*macro
)
46 struct sl_pp_macro
*macro
;
48 macro
= calloc(1, sizeof(struct sl_pp_macro
));
56 _macro_destroy(struct sl_pp_macro
*macro
)
58 struct sl_pp_macro_formal_arg
*arg
= macro
->arg
;
61 struct sl_pp_macro_formal_arg
*next_arg
= arg
->next
;
71 sl_pp_macro_free(struct sl_pp_macro
*macro
)
74 struct sl_pp_macro
*next_macro
= macro
->next
;
76 _macro_destroy(macro
);
83 sl_pp_macro_reset(struct sl_pp_macro
*macro
)
85 _macro_destroy(macro
);
90 skip_whitespace(const struct sl_pp_token_info
*input
,
93 while (input
[*pi
].token
== SL_PP_WHITESPACE
) {
99 _out_number(struct sl_pp_context
*context
,
100 struct sl_pp_process_state
*state
,
104 struct sl_pp_token_info ti
;
106 sprintf(buf
, "%u", number
);
108 ti
.token
= SL_PP_NUMBER
;
109 ti
.data
.number
= sl_pp_context_add_unique_str(context
, buf
);
110 if (sl_pp_process_out(state
, &ti
)) {
111 strcpy(context
->error_msg
, "out of memory");
119 sl_pp_macro_expand(struct sl_pp_context
*context
,
120 const struct sl_pp_token_info
*input
,
122 struct sl_pp_macro
*local
,
123 struct sl_pp_process_state
*state
,
127 struct sl_pp_macro
*macro
= NULL
;
128 struct sl_pp_macro
*actual_arg
= NULL
;
131 if (input
[*pi
].token
!= SL_PP_IDENTIFIER
) {
132 strcpy(context
->error_msg
, "expected an identifier");
136 macro_name
= input
[*pi
].data
.identifier
;
138 if (macro_name
== context
->dict
.___LINE__
) {
139 if (!mute
&& _out_number(context
, state
, context
->line
)) {
145 if (macro_name
== context
->dict
.___FILE__
) {
146 if (!mute
&& _out_number(context
, state
, context
->file
)) {
152 if (macro_name
== context
->dict
.__VERSION__
) {
153 if (!mute
&& _out_number(context
, state
, 110)) {
161 for (macro
= local
; macro
; macro
= macro
->next
) {
162 if (macro
->name
== macro_name
) {
169 for (macro
= context
->macro
; macro
; macro
= macro
->next
) {
170 if (macro
->name
== macro_name
) {
178 if (sl_pp_process_out(state
, &input
[*pi
])) {
179 strcpy(context
->error_msg
, "out of memory");
189 if (macro
->num_args
>= 0) {
190 skip_whitespace(input
, pi
);
191 if (input
[*pi
].token
!= SL_PP_LPAREN
) {
192 strcpy(context
->error_msg
, "expected `('");
196 skip_whitespace(input
, pi
);
199 if (macro
->num_args
> 0) {
200 struct sl_pp_macro_formal_arg
*formal_arg
= macro
->arg
;
201 struct sl_pp_macro
**pmacro
= &actual_arg
;
203 for (j
= 0; j
< (unsigned int)macro
->num_args
; j
++) {
204 unsigned int body_len
;
207 unsigned int paren_nesting
= 0;
210 *pmacro
= sl_pp_macro_new();
212 strcpy(context
->error_msg
, "out of memory");
216 (**pmacro
).name
= formal_arg
->name
;
219 for (i
= *pi
; !done
; i
++) {
220 switch (input
[i
].token
) {
221 case SL_PP_WHITESPACE
:
225 if (!paren_nesting
) {
226 if (j
< (unsigned int)macro
->num_args
- 1) {
229 strcpy(context
->error_msg
, "too many actual macro arguments");
243 if (!paren_nesting
) {
244 if (j
== (unsigned int)macro
->num_args
- 1) {
247 strcpy(context
->error_msg
, "too few actual macro arguments");
257 strcpy(context
->error_msg
, "too few actual macro arguments");
265 (**pmacro
).body
= malloc(sizeof(struct sl_pp_token_info
) * body_len
);
266 if (!(**pmacro
).body
) {
267 strcpy(context
->error_msg
, "out of memory");
271 for (done
= 0, k
= 0, i
= *pi
; !done
; i
++) {
272 switch (input
[i
].token
) {
273 case SL_PP_WHITESPACE
:
277 if (!paren_nesting
&& j
< (unsigned int)macro
->num_args
- 1) {
280 (**pmacro
).body
[k
++] = input
[i
];
286 (**pmacro
).body
[k
++] = input
[i
];
290 if (!paren_nesting
&& j
== (unsigned int)macro
->num_args
- 1) {
294 (**pmacro
).body
[k
++] = input
[i
];
299 (**pmacro
).body
[k
++] = input
[i
];
303 (**pmacro
).body
[k
++].token
= SL_PP_EOF
;
306 formal_arg
= formal_arg
->next
;
307 pmacro
= &(**pmacro
).next
;
311 /* Right paren for non-empty argument list has already been eaten. */
312 if (macro
->num_args
== 0) {
313 skip_whitespace(input
, pi
);
314 if (input
[*pi
].token
!= SL_PP_RPAREN
) {
315 strcpy(context
->error_msg
, "expected `)'");
322 switch (macro
->body
[j
].token
) {
324 if (sl_pp_process_out(state
, ¯o
->body
[j
])) {
325 strcpy(context
->error_msg
, "out of memory");
331 case SL_PP_IDENTIFIER
:
332 if (sl_pp_macro_expand(context
, macro
->body
, &j
, actual_arg
, state
, mute
)) {
338 sl_pp_macro_free(actual_arg
);
343 if (sl_pp_process_out(state
, ¯o
->body
[j
])) {
344 strcpy(context
->error_msg
, "out of memory");