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_context.h"
31 #include "sl_pp_process.h"
32 #include "sl_pp_public.h"
36 sl_pp_process_out(struct sl_pp_process_state
*state
,
37 const struct sl_pp_token_info
*token
)
39 if (state
->out_len
>= state
->out_max
) {
40 unsigned int new_max
= state
->out_max
;
42 if (new_max
< 0x100) {
44 } else if (new_max
< 0x10000) {
50 state
->out
= realloc(state
->out
, new_max
* sizeof(struct sl_pp_token_info
));
54 state
->out_max
= new_max
;
57 state
->out
[state
->out_len
++] = *token
;
62 sl_pp_process_get(struct sl_pp_context
*context
,
63 struct sl_pp_token_info
*output
)
65 if (!context
->process_state
.out
) {
66 if (context
->line
> 1) {
67 struct sl_pp_token_info ti
;
69 ti
.token
= SL_PP_LINE
;
70 ti
.data
.line
.lineno
= context
->line
- 1;
71 ti
.data
.line
.fileno
= context
->file
;
72 if (sl_pp_process_out(&context
->process_state
, &ti
)) {
73 strcpy(context
->error_msg
, "out of memory");
77 ti
.token
= SL_PP_NEWLINE
;
78 if (sl_pp_process_out(&context
->process_state
, &ti
)) {
79 strcpy(context
->error_msg
, "out of memory");
86 struct sl_pp_token_info input
;
89 if (context
->process_state
.out_len
) {
90 assert(context
->process_state
.out
);
91 *output
= context
->process_state
.out
[0];
93 if (context
->process_state
.out_len
> 1) {
96 for (i
= 1; i
< context
->process_state
.out_len
; i
++) {
97 context
->process_state
.out
[i
- 1] = context
->process_state
.out
[i
];
100 context
->process_state
.out_len
--;
105 if (sl_pp_token_buffer_skip_white(&context
->tokens
, &input
)) {
108 if (input
.token
== SL_PP_HASH
) {
109 if (sl_pp_token_buffer_skip_white(&context
->tokens
, &input
)) {
112 switch (input
.token
) {
113 case SL_PP_IDENTIFIER
:
117 struct sl_pp_token_info endof
;
118 struct sl_pp_token_peek peek
;
121 /* Directive name. */
122 name
= input
.data
.identifier
;
124 if (sl_pp_token_buffer_skip_white(&context
->tokens
, &input
)) {
127 sl_pp_token_buffer_unget(&context
->tokens
, &input
);
129 if (sl_pp_token_peek_init(&peek
, &context
->tokens
)) {
134 if (sl_pp_token_peek_get(&peek
, &input
)) {
135 sl_pp_token_peek_destroy(&peek
);
138 switch (input
.token
) {
140 /* Preserve newline just for the sake of line numbering. */
156 if (name
== context
->dict
._if
) {
157 struct sl_pp_token_buffer buffer
;
159 result
= sl_pp_token_peek_to_buffer(&peek
, &buffer
);
161 result
= sl_pp_process_if(context
, &buffer
);
162 sl_pp_token_buffer_destroy(&buffer
);
164 } else if (name
== context
->dict
.ifdef
) {
165 result
= sl_pp_process_ifdef(context
, peek
.tokens
, 0, peek
.size
- 1);
166 } else if (name
== context
->dict
.ifndef
) {
167 result
= sl_pp_process_ifndef(context
, peek
.tokens
, 0, peek
.size
- 1);
168 } else if (name
== context
->dict
.elif
) {
169 struct sl_pp_token_buffer buffer
;
171 result
= sl_pp_token_peek_to_buffer(&peek
, &buffer
);
173 result
= sl_pp_process_elif(context
, &buffer
);
174 sl_pp_token_buffer_destroy(&buffer
);
176 } else if (name
== context
->dict
._else
) {
177 result
= sl_pp_process_else(context
, peek
.tokens
, 0, peek
.size
- 1);
178 } else if (name
== context
->dict
.endif
) {
179 result
= sl_pp_process_endif(context
, peek
.tokens
, 0, peek
.size
- 1);
180 } else if (context
->if_value
) {
181 if (name
== context
->dict
.define
) {
182 result
= sl_pp_process_define(context
, peek
.tokens
, 0, peek
.size
- 1);
183 } else if (name
== context
->dict
.error
) {
184 sl_pp_process_error(context
, peek
.tokens
, 0, peek
.size
- 1);
186 } else if (name
== context
->dict
.extension
) {
187 result
= sl_pp_process_extension(context
, peek
.tokens
, 0, peek
.size
- 1, &context
->process_state
);
188 } else if (name
== context
->dict
.line
) {
189 struct sl_pp_token_buffer buffer
;
191 result
= sl_pp_token_peek_to_buffer(&peek
, &buffer
);
193 result
= sl_pp_process_line(context
, &buffer
, &context
->process_state
);
194 sl_pp_token_buffer_destroy(&buffer
);
196 } else if (name
== context
->dict
.pragma
) {
197 result
= sl_pp_process_pragma(context
, peek
.tokens
, 0, peek
.size
- 1, &context
->process_state
);
198 } else if (name
== context
->dict
.undef
) {
199 result
= sl_pp_process_undef(context
, peek
.tokens
, 0, peek
.size
- 1);
201 strcpy(context
->error_msg
, "unrecognised directive name");
206 sl_pp_token_peek_commit(&peek
);
207 sl_pp_token_peek_destroy(&peek
);
213 if (sl_pp_process_out(&context
->process_state
, &endof
)) {
214 strcpy(context
->error_msg
, "out of memory");
222 /* Empty directive. */
223 if (sl_pp_process_out(&context
->process_state
, &input
)) {
224 strcpy(context
->error_msg
, "out of memory");
231 /* Empty directive. */
232 if (sl_pp_process_out(&context
->process_state
, &input
)) {
233 strcpy(context
->error_msg
, "out of memory");
240 strcpy(context
->error_msg
, "expected a directive name");
246 sl_pp_token_buffer_unget(&context
->tokens
, &input
);
249 if (sl_pp_token_buffer_get(&context
->tokens
, &input
)) {
253 switch (input
.token
) {
254 case SL_PP_WHITESPACE
:
255 /* Drop whitespace all together at this point. */
259 /* Preserve newline just for the sake of line numbering. */
260 if (sl_pp_process_out(&context
->process_state
, &input
)) {
261 strcpy(context
->error_msg
, "out of memory");
269 if (sl_pp_process_out(&context
->process_state
, &input
)) {
270 strcpy(context
->error_msg
, "out of memory");
277 case SL_PP_IDENTIFIER
:
278 sl_pp_token_buffer_unget(&context
->tokens
, &input
);
279 if (sl_pp_macro_expand(context
, &context
->tokens
, NULL
, &context
->process_state
,
280 context
->if_value
? sl_pp_macro_expand_normal
: sl_pp_macro_expand_mute
)) {
286 if (context
->if_value
) {
287 if (sl_pp_process_out(&context
->process_state
, &input
)) {
288 strcpy(context
->error_msg
, "out of memory");
297 if (context
->if_ptr
!= SL_PP_MAX_IF_NESTING
) {
298 strcpy(context
->error_msg
, "expected `#endif' directive");
306 sl_pp_process(struct sl_pp_context
*context
,
307 struct sl_pp_token_info
**output
)
309 struct sl_pp_process_state state
;
311 memset(&state
, 0, sizeof(state
));
313 struct sl_pp_token_info input
;
315 if (sl_pp_process_get(context
, &input
)) {
319 if (sl_pp_process_out(&state
, &input
)) {
323 if (input
.token
== SL_PP_EOF
) {