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_macro.h"
33 #include "sl_pp_process.h"
34 #include "sl_pp_public.h"
35 #include "sl_pp_token.h"
39 sl_pp_process_out(struct sl_pp_process_state
*state
,
40 const struct sl_pp_token_info
*token
)
42 if (state
->out_len
>= state
->out_max
) {
43 unsigned int new_max
= state
->out_max
;
45 if (new_max
< 0x100) {
47 } else if (new_max
< 0x10000) {
53 state
->out
= realloc(state
->out
, new_max
* sizeof(struct sl_pp_token_info
));
57 state
->out_max
= new_max
;
60 state
->out
[state
->out_len
++] = *token
;
65 sl_pp_process_get(struct sl_pp_context
*context
,
66 struct sl_pp_token_info
*output
)
68 if (!context
->process_state
.out
) {
69 if (context
->line
> 1) {
70 struct sl_pp_token_info ti
;
72 ti
.token
= SL_PP_LINE
;
73 ti
.data
.line
.lineno
= context
->line
- 1;
74 ti
.data
.line
.fileno
= context
->file
;
75 if (sl_pp_process_out(&context
->process_state
, &ti
)) {
76 strcpy(context
->error_msg
, "out of memory");
80 ti
.token
= SL_PP_NEWLINE
;
81 if (sl_pp_process_out(&context
->process_state
, &ti
)) {
82 strcpy(context
->error_msg
, "out of memory");
89 struct sl_pp_token_info input
;
92 if (context
->process_state
.out_len
) {
93 assert(context
->process_state
.out
);
94 *output
= context
->process_state
.out
[0];
96 if (context
->process_state
.out_len
> 1) {
99 for (i
= 1; i
< context
->process_state
.out_len
; i
++) {
100 context
->process_state
.out
[i
- 1] = context
->process_state
.out
[i
];
103 context
->process_state
.out_len
--;
108 if (sl_pp_token_buffer_skip_white(&context
->tokens
, &input
)) {
111 if (input
.token
== SL_PP_HASH
) {
112 if (sl_pp_token_buffer_skip_white(&context
->tokens
, &input
)) {
115 switch (input
.token
) {
116 case SL_PP_IDENTIFIER
:
120 struct sl_pp_token_info endof
;
121 struct sl_pp_token_peek peek
;
124 /* Directive name. */
125 name
= input
.data
.identifier
;
127 if (sl_pp_token_buffer_skip_white(&context
->tokens
, &input
)) {
130 sl_pp_token_buffer_unget(&context
->tokens
, &input
);
132 if (sl_pp_token_peek_init(&peek
, &context
->tokens
)) {
137 if (sl_pp_token_peek_get(&peek
, &input
)) {
138 sl_pp_token_peek_destroy(&peek
);
141 switch (input
.token
) {
143 /* Preserve newline just for the sake of line numbering. */
159 if (name
== context
->dict
._if
) {
160 struct sl_pp_token_buffer buffer
;
162 result
= sl_pp_token_peek_to_buffer(&peek
, &buffer
);
164 result
= sl_pp_process_if(context
, &buffer
);
165 sl_pp_token_buffer_destroy(&buffer
);
167 } else if (name
== context
->dict
.ifdef
) {
168 result
= sl_pp_process_ifdef(context
, peek
.tokens
, 0, peek
.size
- 1);
169 } else if (name
== context
->dict
.ifndef
) {
170 result
= sl_pp_process_ifndef(context
, peek
.tokens
, 0, peek
.size
- 1);
171 } else if (name
== context
->dict
.elif
) {
172 struct sl_pp_token_buffer buffer
;
174 result
= sl_pp_token_peek_to_buffer(&peek
, &buffer
);
176 result
= sl_pp_process_elif(context
, &buffer
);
177 sl_pp_token_buffer_destroy(&buffer
);
179 } else if (name
== context
->dict
._else
) {
180 result
= sl_pp_process_else(context
, peek
.tokens
, 0, peek
.size
- 1);
181 } else if (name
== context
->dict
.endif
) {
182 result
= sl_pp_process_endif(context
, peek
.tokens
, 0, peek
.size
- 1);
183 } else if (context
->if_value
) {
184 if (name
== context
->dict
.define
) {
185 result
= sl_pp_process_define(context
, peek
.tokens
, 0, peek
.size
- 1);
186 } else if (name
== context
->dict
.error
) {
187 sl_pp_process_error(context
, peek
.tokens
, 0, peek
.size
- 1);
189 } else if (name
== context
->dict
.extension
) {
190 result
= sl_pp_process_extension(context
, peek
.tokens
, 0, peek
.size
- 1, &context
->process_state
);
191 } else if (name
== context
->dict
.line
) {
192 struct sl_pp_token_buffer buffer
;
194 result
= sl_pp_token_peek_to_buffer(&peek
, &buffer
);
196 result
= sl_pp_process_line(context
, &buffer
, &context
->process_state
);
197 sl_pp_token_buffer_destroy(&buffer
);
199 } else if (name
== context
->dict
.pragma
) {
200 result
= sl_pp_process_pragma(context
, peek
.tokens
, 0, peek
.size
- 1, &context
->process_state
);
201 } else if (name
== context
->dict
.undef
) {
202 result
= sl_pp_process_undef(context
, peek
.tokens
, 0, peek
.size
- 1);
204 strcpy(context
->error_msg
, "unrecognised directive name");
209 sl_pp_token_peek_commit(&peek
);
210 sl_pp_token_peek_destroy(&peek
);
216 if (sl_pp_process_out(&context
->process_state
, &endof
)) {
217 strcpy(context
->error_msg
, "out of memory");
225 /* Empty directive. */
226 if (sl_pp_process_out(&context
->process_state
, &input
)) {
227 strcpy(context
->error_msg
, "out of memory");
234 /* Empty directive. */
235 if (sl_pp_process_out(&context
->process_state
, &input
)) {
236 strcpy(context
->error_msg
, "out of memory");
243 strcpy(context
->error_msg
, "expected a directive name");
249 sl_pp_token_buffer_unget(&context
->tokens
, &input
);
252 if (sl_pp_token_buffer_get(&context
->tokens
, &input
)) {
256 switch (input
.token
) {
257 case SL_PP_WHITESPACE
:
258 /* Drop whitespace all together at this point. */
262 /* Preserve newline just for the sake of line numbering. */
263 if (sl_pp_process_out(&context
->process_state
, &input
)) {
264 strcpy(context
->error_msg
, "out of memory");
272 if (sl_pp_process_out(&context
->process_state
, &input
)) {
273 strcpy(context
->error_msg
, "out of memory");
280 case SL_PP_IDENTIFIER
:
281 sl_pp_token_buffer_unget(&context
->tokens
, &input
);
282 if (sl_pp_macro_expand(context
, &context
->tokens
, NULL
, &context
->process_state
,
283 context
->if_value
? sl_pp_macro_expand_normal
: sl_pp_macro_expand_mute
)) {
289 if (context
->if_value
) {
290 if (sl_pp_process_out(&context
->process_state
, &input
)) {
291 strcpy(context
->error_msg
, "out of memory");
300 if (context
->if_ptr
!= SL_PP_MAX_IF_NESTING
) {
301 strcpy(context
->error_msg
, "expected `#endif' directive");
309 sl_pp_process(struct sl_pp_context
*context
,
310 struct sl_pp_token_info
**output
)
312 struct sl_pp_process_state state
;
314 memset(&state
, 0, sizeof(state
));
316 struct sl_pp_token_info input
;
318 if (sl_pp_process_get(context
, &input
)) {
322 if (sl_pp_process_out(&state
, &input
)) {
326 if (input
.token
== SL_PP_EOF
) {