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_context.h"
33 #include "sl_pp_token.h"
36 #define PURE_ERROR 256
39 _pure_getc(struct sl_pp_context
*context
)
43 if (context
->getc_buf_size
) {
44 return context
->getc_buf
[--context
->getc_buf_size
];
47 if (sl_pp_purify_getc(&context
->pure
, &c
, &context
->error_line
, context
->error_msg
, sizeof(context
->error_msg
)) == 0) {
55 _pure_ungetc(struct sl_pp_context
*context
,
58 assert(c
!= PURE_ERROR
);
60 if (context
->getc_buf_size
== context
->getc_buf_capacity
) {
61 context
->getc_buf_capacity
+= 64;
62 context
->getc_buf
= realloc(context
->getc_buf
, context
->getc_buf_capacity
* sizeof(char));
63 assert(context
->getc_buf
);
66 context
->getc_buf
[context
->getc_buf_size
++] = (char)c
;
70 struct lookahead_state
{
73 struct sl_pp_context
*context
;
78 _lookahead_init(struct lookahead_state
*lookahead
,
79 struct sl_pp_context
*context
)
82 lookahead
->context
= context
;
87 _lookahead_tell(const struct lookahead_state
*lookahead
)
89 return lookahead
->pos
;
94 _lookahead_buf(const struct lookahead_state
*lookahead
)
96 return lookahead
->buf
;
101 _lookahead_revert(struct lookahead_state
*lookahead
,
104 assert(pos
<= lookahead
->pos
);
106 while (lookahead
->pos
> pos
) {
107 _pure_ungetc(lookahead
->context
, lookahead
->buf
[--lookahead
->pos
]);
113 _lookahead_getc(struct lookahead_state
*lookahead
)
117 assert(lookahead
->pos
< sizeof(lookahead
->buf
) / sizeof(lookahead
->buf
[0]));
119 c
= _pure_getc(lookahead
->context
);
120 if (c
!= PURE_ERROR
) {
121 lookahead
->buf
[lookahead
->pos
++] = (char)c
;
128 _is_identifier_char(char c
)
130 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || (c
>= '0' && c
<= '9') || c
== '_';
135 _tokenise_identifier(struct sl_pp_context
*context
,
136 struct sl_pp_token_info
*out
)
139 char identifier
[256]; /* XXX: Remove this artifical limit. */
142 out
->token
= SL_PP_IDENTIFIER
;
143 out
->data
.identifier
= -1;
145 c
= _pure_getc(context
);
146 if (c
== PURE_ERROR
) {
149 identifier
[i
++] = (char)c
;
151 c
= _pure_getc(context
);
152 if (c
== PURE_ERROR
) {
156 if (_is_identifier_char((char)c
)) {
157 if (i
>= sizeof(identifier
) / sizeof(char) - 1) {
158 strcpy(context
->error_msg
, "out of memory");
159 _pure_ungetc(context
, c
);
161 _pure_ungetc(context
, identifier
[--i
]);
165 identifier
[i
++] = (char)c
;
167 _pure_ungetc(context
, c
);
171 identifier
[i
] = '\0';
173 out
->data
.identifier
= sl_pp_context_add_unique_str(context
, identifier
);
174 if (out
->data
.identifier
== -1) {
176 _pure_ungetc(context
, identifier
[--i
]);
186 * Return the number of consecutive decimal digits in the input stream.
189 _parse_float_digits(struct lookahead_state
*lookahead
)
193 for (eaten
= 0;; eaten
++) {
194 unsigned int pos
= _lookahead_tell(lookahead
);
195 char c
= _lookahead_getc(lookahead
);
197 if (c
< '0' || c
> '9') {
198 _lookahead_revert(lookahead
, pos
);
207 * Try to match one of the following patterns for the fractional part
208 * of a floating point number.
213 * Return 0 if the pattern could not be matched, otherwise the number
214 * of eaten characters from the input stream.
217 _parse_float_frac(struct lookahead_state
*lookahead
)
223 pos
= _lookahead_tell(lookahead
);
224 c
= _lookahead_getc(lookahead
);
226 eaten
= _parse_float_digits(lookahead
);
230 _lookahead_revert(lookahead
, pos
);
234 _lookahead_revert(lookahead
, pos
);
235 eaten
= _parse_float_digits(lookahead
);
237 c
= _lookahead_getc(lookahead
);
239 return eaten
+ 1 + _parse_float_digits(lookahead
);
243 _lookahead_revert(lookahead
, pos
);
249 * Try to match the following pattern for the exponential part
250 * of a floating point number.
252 * (e|E) [(+|-)] digits
254 * Return 0 if the pattern could not be matched, otherwise the number
255 * of eaten characters from the input stream.
258 _parse_float_exp(struct lookahead_state
*lookahead
)
260 unsigned int pos
, pos2
;
262 unsigned int eaten
, digits
;
264 pos
= _lookahead_tell(lookahead
);
265 c
= _lookahead_getc(lookahead
);
266 if (c
!= 'e' && c
!= 'E') {
267 _lookahead_revert(lookahead
, pos
);
271 pos2
= _lookahead_tell(lookahead
);
272 c
= _lookahead_getc(lookahead
);
273 if (c
== '-' || c
== '+') {
276 _lookahead_revert(lookahead
, pos2
);
280 digits
= _parse_float_digits(lookahead
);
282 _lookahead_revert(lookahead
, pos
);
286 return eaten
+ digits
;
291 * Try to match one of the following patterns for a floating point number.
293 * fract [exp] [(f|F)]
296 * Return 0 if the pattern could not be matched, otherwise the number
297 * of eaten characters from the input stream.
300 _parse_float(struct lookahead_state
*lookahead
)
304 eaten
= _parse_float_frac(lookahead
);
309 eaten
+= _parse_float_exp(lookahead
);
311 pos
= _lookahead_tell(lookahead
);
312 c
= _lookahead_getc(lookahead
);
313 if (c
== 'f' || c
== 'F') {
316 _lookahead_revert(lookahead
, pos
);
322 eaten
= _parse_float_digits(lookahead
);
324 unsigned int exponent
;
326 exponent
= _parse_float_exp(lookahead
);
333 pos
= _lookahead_tell(lookahead
);
334 c
= _lookahead_getc(lookahead
);
335 if (c
== 'f' || c
== 'F') {
338 _lookahead_revert(lookahead
, pos
);
345 _lookahead_revert(lookahead
, 0);
351 _parse_hex(struct lookahead_state
*lookahead
)
356 c
= _lookahead_getc(lookahead
);
358 _lookahead_revert(lookahead
, 0);
362 c
= _lookahead_getc(lookahead
);
363 if (c
!= 'x' && c
!= 'X') {
364 _lookahead_revert(lookahead
, 0);
369 unsigned int pos
= _lookahead_tell(lookahead
);
371 c
= _lookahead_getc(lookahead
);
372 if ((c
>= '0' && c
<= '9') || (c
>= 'a' && c
<= 'f') || (c
>= 'A' && c
<= 'F')) {
375 _lookahead_revert(lookahead
, pos
);
384 _lookahead_revert(lookahead
, 0);
390 _parse_oct(struct lookahead_state
*lookahead
)
395 c
= _lookahead_getc(lookahead
);
397 _lookahead_revert(lookahead
, 0);
402 unsigned int pos
= _lookahead_tell(lookahead
);
404 c
= _lookahead_getc(lookahead
);
405 if ((c
>= '0' && c
<= '7')) {
408 _lookahead_revert(lookahead
, pos
);
418 _parse_dec(struct lookahead_state
*lookahead
)
423 unsigned int pos
= _lookahead_tell(lookahead
);
424 int c
= _lookahead_getc(lookahead
);
426 if ((c
>= '0' && c
<= '9')) {
429 _lookahead_revert(lookahead
, pos
);
439 _tokenise_number(struct sl_pp_context
*context
,
440 struct sl_pp_token_info
*out
)
442 struct lookahead_state lookahead
;
444 unsigned int is_float
= 0;
447 char number
[256]; /* XXX: Remove this artifical limit. */
449 _lookahead_init(&lookahead
, context
);
451 eaten
= _parse_float(&lookahead
);
453 eaten
= _parse_hex(&lookahead
);
455 eaten
= _parse_oct(&lookahead
);
457 eaten
= _parse_dec(&lookahead
);
465 strcpy(context
->error_msg
, "expected a number");
469 pos
= _lookahead_tell(&lookahead
);
470 c
= _lookahead_getc(&lookahead
);
471 _lookahead_revert(&lookahead
, pos
);
473 if (_is_identifier_char(c
)) {
474 strcpy(context
->error_msg
, "expected a number");
475 _lookahead_revert(&lookahead
, 0);
479 if (eaten
> sizeof(number
) - 1) {
480 strcpy(context
->error_msg
, "out of memory");
481 _lookahead_revert(&lookahead
, 0);
485 assert(_lookahead_tell(&lookahead
) == eaten
);
487 memcpy(number
, _lookahead_buf(&lookahead
), eaten
);
488 number
[eaten
] = '\0';
491 out
->token
= SL_PP_FLOAT
;
492 out
->data
._float
= sl_pp_context_add_unique_str(context
, number
);
493 if (out
->data
._float
== -1) {
494 _lookahead_revert(&lookahead
, 0);
498 out
->token
= SL_PP_UINT
;
499 out
->data
._uint
= sl_pp_context_add_unique_str(context
, number
);
500 if (out
->data
._uint
== -1) {
501 _lookahead_revert(&lookahead
, 0);
511 sl_pp_token_get(struct sl_pp_context
*context
,
512 struct sl_pp_token_info
*out
)
514 int c
= _pure_getc(context
);
519 out
->token
= SL_PP_WHITESPACE
;
523 out
->token
= SL_PP_NEWLINE
;
527 out
->token
= SL_PP_HASH
;
531 out
->token
= SL_PP_COMMA
;
535 out
->token
= SL_PP_SEMICOLON
;
539 out
->token
= SL_PP_LBRACE
;
543 out
->token
= SL_PP_RBRACE
;
547 out
->token
= SL_PP_LPAREN
;
551 out
->token
= SL_PP_RPAREN
;
555 out
->token
= SL_PP_LBRACKET
;
559 out
->token
= SL_PP_RBRACKET
;
564 int c2
= _pure_getc(context
);
566 if (c2
== PURE_ERROR
) {
569 if (c2
>= '0' && c2
<= '9') {
570 _pure_ungetc(context
, c2
);
571 _pure_ungetc(context
, c
);
572 if (_tokenise_number(context
, out
)) {
576 _pure_ungetc(context
, c2
);
577 out
->token
= SL_PP_DOT
;
583 c
= _pure_getc(context
);
584 if (c
== PURE_ERROR
) {
588 out
->token
= SL_PP_INCREMENT
;
589 } else if (c
== '=') {
590 out
->token
= SL_PP_ADDASSIGN
;
592 _pure_ungetc(context
, c
);
593 out
->token
= SL_PP_PLUS
;
598 c
= _pure_getc(context
);
599 if (c
== PURE_ERROR
) {
603 out
->token
= SL_PP_DECREMENT
;
604 } else if (c
== '=') {
605 out
->token
= SL_PP_SUBASSIGN
;
607 _pure_ungetc(context
, c
);
608 out
->token
= SL_PP_MINUS
;
613 out
->token
= SL_PP_BITNOT
;
617 c
= _pure_getc(context
);
618 if (c
== PURE_ERROR
) {
622 out
->token
= SL_PP_NOTEQUAL
;
624 _pure_ungetc(context
, c
);
625 out
->token
= SL_PP_NOT
;
630 c
= _pure_getc(context
);
631 if (c
== PURE_ERROR
) {
635 out
->token
= SL_PP_MULASSIGN
;
637 _pure_ungetc(context
, c
);
638 out
->token
= SL_PP_STAR
;
643 c
= _pure_getc(context
);
644 if (c
== PURE_ERROR
) {
648 out
->token
= SL_PP_DIVASSIGN
;
650 _pure_ungetc(context
, c
);
651 out
->token
= SL_PP_SLASH
;
656 c
= _pure_getc(context
);
657 if (c
== PURE_ERROR
) {
661 out
->token
= SL_PP_MODASSIGN
;
663 _pure_ungetc(context
, c
);
664 out
->token
= SL_PP_MODULO
;
669 c
= _pure_getc(context
);
670 if (c
== PURE_ERROR
) {
674 c
= _pure_getc(context
);
675 if (c
== PURE_ERROR
) {
679 out
->token
= SL_PP_LSHIFTASSIGN
;
681 _pure_ungetc(context
, c
);
682 out
->token
= SL_PP_LSHIFT
;
684 } else if (c
== '=') {
685 out
->token
= SL_PP_LESSEQUAL
;
687 _pure_ungetc(context
, c
);
688 out
->token
= SL_PP_LESS
;
693 c
= _pure_getc(context
);
694 if (c
== PURE_ERROR
) {
698 c
= _pure_getc(context
);
699 if (c
== PURE_ERROR
) {
703 out
->token
= SL_PP_RSHIFTASSIGN
;
705 _pure_ungetc(context
, c
);
706 out
->token
= SL_PP_RSHIFT
;
708 } else if (c
== '=') {
709 out
->token
= SL_PP_GREATEREQUAL
;
711 _pure_ungetc(context
, c
);
712 out
->token
= SL_PP_GREATER
;
717 c
= _pure_getc(context
);
718 if (c
== PURE_ERROR
) {
722 out
->token
= SL_PP_EQUAL
;
724 _pure_ungetc(context
, c
);
725 out
->token
= SL_PP_ASSIGN
;
730 c
= _pure_getc(context
);
731 if (c
== PURE_ERROR
) {
735 out
->token
= SL_PP_AND
;
736 } else if (c
== '=') {
737 out
->token
= SL_PP_BITANDASSIGN
;
739 _pure_ungetc(context
, c
);
740 out
->token
= SL_PP_BITAND
;
745 c
= _pure_getc(context
);
746 if (c
== PURE_ERROR
) {
750 out
->token
= SL_PP_XOR
;
751 } else if (c
== '=') {
752 out
->token
= SL_PP_BITXORASSIGN
;
754 _pure_ungetc(context
, c
);
755 out
->token
= SL_PP_BITXOR
;
760 c
= _pure_getc(context
);
761 if (c
== PURE_ERROR
) {
765 out
->token
= SL_PP_OR
;
766 } else if (c
== '=') {
767 out
->token
= SL_PP_BITORASSIGN
;
769 _pure_ungetc(context
, c
);
770 out
->token
= SL_PP_BITOR
;
775 out
->token
= SL_PP_QUESTION
;
779 out
->token
= SL_PP_COLON
;
783 out
->token
= SL_PP_EOF
;
790 if ((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') || c
== '_') {
791 _pure_ungetc(context
, c
);
792 if (_tokenise_identifier(context
, out
)) {
795 } else if (c
>= '0' && c
<= '9') {
796 _pure_ungetc(context
, c
);
797 if (_tokenise_number(context
, out
)) {
802 out
->token
= SL_PP_OTHER
;
811 sl_pp_tokenise(struct sl_pp_context
*context
,
812 struct sl_pp_token_info
**output
)
814 struct sl_pp_token_info
*out
= NULL
;
815 unsigned int out_len
= 0;
816 unsigned int out_max
= 0;
819 struct sl_pp_token_info info
;
821 if (sl_pp_token_buffer_get(&context
->tokens
, &info
)) {
826 if (out_len
>= out_max
) {
827 unsigned int new_max
= out_max
;
829 if (new_max
< 0x100) {
831 } else if (new_max
< 0x10000) {
837 out
= realloc(out
, new_max
* sizeof(struct sl_pp_token_info
));
839 strcpy(context
->error_msg
, "out of memory");
845 out
[out_len
++] = info
;
847 if (info
.token
== SL_PP_EOF
) {