2 * Wrc preprocessor syntax analysis
4 * Copyright 1999-2000 Bertho A. Stultiens (BS)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #include "wpp_private.h"
37 #define UNARY_OP(r, v, OP) \
40 case cv_sint
: r.val.si
= OP v.val.si
; break
; \
41 case cv_uint
: r.val.ui
= OP v.val.ui
; break
; \
42 case cv_slong
: r.val.sl
= OP v.val.sl
; break
; \
43 case cv_ulong
: r.val.ul
= OP v.val.ul
; break
; \
44 case cv_sll
: r.val.sll
= OP v.val.sll
; break
; \
45 case cv_ull
: r.val.ull
= OP v.val.ull
; break
; \
48 #define cv_signed(v) ((v.type & FLAG_SIGNED) != 0)
50 #define BIN_OP_INT(r, v1, v2, OP) \
52 if
(cv_signed
(v1
) && cv_signed
(v2
)) \
53 r.val.si
= v1.val.si OP v2.val.si
; \
54 else if
(cv_signed
(v1
) && !cv_signed
(v2
)) \
55 r.val.si
= v1.val.si OP
(signed) v2.val.ui
; \
56 else if
(!cv_signed
(v1
) && cv_signed
(v2
)) \
57 r.val.si
= (signed) v1.val.ui OP v2.val.si
; \
59 r.val.ui
= v1.val.ui OP v2.val.ui
;
61 #define BIN_OP_LONG(r, v1, v2, OP) \
63 if
(cv_signed
(v1
) && cv_signed
(v2
)) \
64 r.val.sl
= v1.val.sl OP v2.val.sl
; \
65 else if
(cv_signed
(v1
) && !cv_signed
(v2
)) \
66 r.val.sl
= v1.val.sl OP
(signed long) v2.val.ul
; \
67 else if
(!cv_signed
(v1
) && cv_signed
(v2
)) \
68 r.val.sl
= (signed long) v1.val.ul OP v2.val.sl
; \
70 r.val.ul
= v1.val.ul OP v2.val.ul
;
72 #define BIN_OP_LONGLONG(r, v1, v2, OP) \
74 if
(cv_signed
(v1
) && cv_signed
(v2
)) \
75 r.val.sll
= v1.val.sll OP v2.val.sll
; \
76 else if
(cv_signed
(v1
) && !cv_signed
(v2
)) \
77 r.val.sll
= v1.val.sll OP
(__int64
) v2.val.ull
; \
78 else if
(!cv_signed
(v1
) && cv_signed
(v2
)) \
79 r.val.sll
= (__int64
) v1.val.ull OP v2.val.sll
; \
81 r.val.ull
= v1.val.ull OP v2.val.ull
;
83 #define BIN_OP(r, v1, v2, OP) \
84 switch
(v1.type
& SIZE_MASK
) \
86 case SIZE_INT
: BIN_OP_INT
(r
, v1
, v2
, OP
); break
; \
87 case SIZE_LONG
: BIN_OP_LONG
(r
, v1
, v2
, OP
); break
; \
88 case SIZE_LONGLONG
: BIN_OP_LONGLONG
(r
, v1
, v2
, OP
); break
; \
96 static int boolean
(cval_t
*v
);
97 static void promote_equal_size
(cval_t
*v1
, cval_t
*v2
);
98 static void cast_to_sint
(cval_t
*v
);
99 static void cast_to_uint
(cval_t
*v
);
100 static void cast_to_slong
(cval_t
*v
);
101 static void cast_to_ulong
(cval_t
*v
);
102 static void cast_to_sll
(cval_t
*v
);
103 static void cast_to_ull
(cval_t
*v
);
104 static char *add_new_marg
(char *str
);
105 static int marg_index
(char *id
);
106 static mtext_t
*new_mtext
(char *str
, int idx
, def_exp_t type
);
107 static mtext_t
*combine_mtext
(mtext_t
*tail
, mtext_t
*mtp
);
108 static char *merge_text
(char *s1
, char *s2
);
113 static char **macro_args
; /* Macro parameters array while parsing */
114 static int nmacro_args
;
115 static int macro_variadic
; /* Macro arguments end with (or consist entirely of) '...' */
119 %define api.prefix
{ppy_
}
127 unsigned __int64 ull
;
136 %token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL
137 %token tINCLUDE tLINE tGCCLINE tERROR tWARNING tPRAGMA tPPIDENT
138 %token tUNDEF tMACROEND tCONCAT tELLIPSIS tSTRINGIZE
139 %token
<cptr
> tIDENT tLITERAL tMACRO tDEFINE
140 %token
<cptr
> tDQSTRING tSQSTRING tIQSTRING
143 %token
<ulong
> tULONG
144 %token
<slong
> tSLONG
145 %token
<ull
> tULONGLONG
146 %token
<sll
> tSLONGLONG
147 %token
<cptr
> tRCINCLUDEPATH
156 %left
'<' tLTE
'>' tGTE
157 %left tLSHIFT tRSHIFT
163 %type
<marg
> emargs margs
164 %type
<mtext
> opt_mtexts mtexts mtext
165 %type
<sint
> allmargs
166 %type
<cptr
> opt_text text
169 **************************************************************************
170 * The parser starts here
171 **************************************************************************
176 pp_file
: /* Empty */
177 | pp_file preprocessor
181 : tINCLUDE tDQSTRING tNL
{ pp_do_include
($2, 1); }
182 | tINCLUDE tIQSTRING tNL
{ pp_do_include
($2, 0); }
183 | tIF pp_expr tNL
{ pp_next_if_state
(boolean
(&$2)); }
184 | tIFDEF tIDENT tNL
{ pp_next_if_state
(pplookup
($2) != NULL
); free
($2); }
185 | tIFNDEF tIDENT tNL
{
186 int t
= pplookup
($2) == NULL
;
187 if
(pp_incl_state.state
== 0 && t
&& !pp_incl_state.seen_junk
)
189 pp_incl_state.state
= 1;
190 pp_incl_state.ppp
= $2;
191 pp_incl_state.ifdepth
= pp_get_if_depth
();
193 else if
(pp_incl_state.state
!= 1)
195 pp_incl_state.state
= -1;
202 fprintf
(stderr
, "tIFNDEF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
203 pp_status.input
, pp_status.line_number
, pp_incl_state.state
, pp_incl_state.ppp
, pp_incl_state.ifdepth
);
205 | tELIF pp_expr tNL
{
206 pp_if_state_t s
= pp_pop_if
();
214 pp_push_if
(boolean
(&$2) ? if_true
: if_false
);
217 pp_push_if
(if_ignore
);
221 ppy_error
("#elif cannot follow #else");
228 pp_if_state_t s
= pp_pop_if
();
232 pp_push_if
(if_elsefalse
);
238 pp_push_if
(if_elsetrue
);
241 pp_push_if
(if_ignore
);
245 ppy_error
("#else clause already defined");
252 if
(pp_pop_if
() != if_error
)
254 if
(pp_incl_state.ifdepth
== pp_get_if_depth
() && pp_incl_state.state
== 1)
256 pp_incl_state.state
= 2;
257 pp_incl_state.seen_junk
= 0;
259 else if
(pp_incl_state.state
!= 1)
261 pp_incl_state.state
= -1;
264 fprintf
(stderr
, "tENDIF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
265 pp_status.input
, pp_status.line_number
, pp_incl_state.state
, pp_incl_state.ppp
, pp_incl_state.ifdepth
);
268 | tUNDEF tIDENT tNL
{ pp_del_define
($2); free
($2); }
269 | tDEFINE opt_text tNL
{ pp_add_define
($1, $2); free
($1); free
($2); }
270 | tMACRO res_arg allmargs tMACROEND opt_mtexts tNL
{
271 pp_add_macro
($1, macro_args
, nmacro_args
, macro_variadic
, $5);
273 | tLINE tSINT tDQSTRING tNL
{ if
($3) fprintf
(ppy_out
, "# %d %s\n", $2 , $3); free
($3); }
274 | tGCCLINE tSINT tDQSTRING tNL
{ if
($3) fprintf
(ppy_out
, "# %d %s\n", $2 , $3); free
($3); }
275 | tGCCLINE tSINT tDQSTRING tSINT tNL
276 { if
($3) fprintf
(ppy_out
, "# %d %s %d\n", $2, $3, $4); free
($3); }
277 | tGCCLINE tSINT tDQSTRING tSINT tSINT tNL
278 { if
($3) fprintf
(ppy_out
, "# %d %s %d %d\n", $2 ,$3, $4, $5); free
($3); }
279 | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tNL
280 { if
($3) fprintf
(ppy_out
, "# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free
($3); }
281 | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tSINT tNL
282 { if
($3) fprintf
(ppy_out
, "# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free
($3); }
283 | tGCCLINE tNL
/* The null-token */
284 | tERROR opt_text tNL
{ ppy_error
("#error directive: '%s'", $2); free
($2); }
285 | tWARNING opt_text tNL
{ ppy_warning
("#warning directive: '%s'", $2); free
($2); }
286 | tPRAGMA opt_text tNL
{ fprintf
(ppy_out
, "#pragma %s\n", $2 ?
$2 : ""); free
($2); }
287 | tPPIDENT opt_text tNL
{ if
(pedantic
) ppy_warning
("#ident ignored (arg: '%s')", $2); free
($2); }
288 | tRCINCLUDE tRCINCLUDEPATH
{
289 pp_do_include
(strmake
( "\"%s\"", $2 ),1);
291 | tRCINCLUDE tDQSTRING
{
297 opt_text: /* Empty */ { $$
= NULL
; }
301 text
: tLITERAL
{ $$
= $1; }
302 | tDQSTRING
{ $$
= $1; }
303 | tSQSTRING
{ $$
= $1; }
304 | text tLITERAL
{ $$
= merge_text
($1, $2); }
305 | text tDQSTRING
{ $$
= merge_text
($1, $2); }
306 | text tSQSTRING
{ $$
= merge_text
($1, $2); }
309 res_arg
: /* Empty */ { macro_args
= NULL
; nmacro_args
= 0; macro_variadic
= 0; }
312 allmargs: /* Empty */ { $$
= 0; macro_args
= NULL
; nmacro_args
= 0; macro_variadic
= 0; }
313 | emargs
{ $$
= nmacro_args
; }
316 emargs
: margs
{ $$
= $1; }
317 | margs
',' tELLIPSIS
{ macro_variadic
= 1; }
318 | tELLIPSIS
{ macro_args
= NULL
; nmacro_args
= 0; macro_variadic
= 1; }
321 margs
: margs
',' tIDENT
{ $$
= add_new_marg
($3); }
322 | tIDENT
{ $$
= add_new_marg
($1); }
326 : /* Empty */ { $$
= NULL
; }
328 for
($$
= $1; $$
&& $$
->prev
; $$
= $$
->prev
)
333 mtexts
: mtext
{ $$
= $1; }
334 | mtexts mtext
{ $$
= combine_mtext
($1, $2); }
337 mtext
: tLITERAL
{ $$
= new_mtext
($1, 0, exp_text
); }
338 | tDQSTRING
{ $$
= new_mtext
($1, 0, exp_text
); }
339 | tSQSTRING
{ $$
= new_mtext
($1, 0, exp_text
); }
340 | tCONCAT
{ $$
= new_mtext
(NULL
, 0, exp_concat
); }
341 | tSTRINGIZE tIDENT
{
342 int mat
= marg_index
($2);
344 ppy_error
("Stringification identifier must be an argument parameter");
346 $$
= new_mtext
(NULL
, mat
, exp_stringize
);
349 int mat
= marg_index
($1);
351 $$
= new_mtext
(NULL
, mat
, exp_subst
);
353 $$
= new_mtext
($1, 0, exp_text
);
357 pp_expr
: tSINT
{ $$.type
= cv_sint
; $$.val.si
= $1; }
358 | tUINT
{ $$.type
= cv_uint
; $$.val.ui
= $1; }
359 | tSLONG
{ $$.type
= cv_slong
; $$.val.sl
= $1; }
360 | tULONG
{ $$.type
= cv_ulong
; $$.val.ul
= $1; }
361 | tSLONGLONG
{ $$.type
= cv_sll
; $$.val.sll
= $1; }
362 | tULONGLONG
{ $$.type
= cv_ull
; $$.val.ull
= $1; }
363 | tDEFINED tIDENT
{ $$.type
= cv_sint
; $$.val.si
= pplookup
($2) != NULL
; }
364 | tDEFINED
'(' tIDENT
')' { $$.type
= cv_sint
; $$.val.si
= pplookup
($3) != NULL
; }
365 | tIDENT
{ $$.type
= cv_sint
; $$.val.si
= 0; }
366 | pp_expr tLOGOR pp_expr
{ $$.type
= cv_sint
; $$.val.si
= boolean
(&$1) || boolean
(&$3); }
367 | pp_expr tLOGAND pp_expr
{ $$.type
= cv_sint
; $$.val.si
= boolean
(&$1) && boolean
(&$3); }
368 | pp_expr tEQ pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, ==); }
369 | pp_expr tNE pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, !=); }
370 | pp_expr
'<' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, <); }
371 | pp_expr
'>' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, >); }
372 | pp_expr tLTE pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, <=); }
373 | pp_expr tGTE pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, >=); }
374 | pp_expr
'+' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, +); }
375 | pp_expr
'-' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, -); }
376 | pp_expr
'^' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, ^
); }
377 | pp_expr
'&' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, &); }
378 | pp_expr
'|' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, |
); }
379 | pp_expr
'*' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, *); }
380 | pp_expr
'/' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, /); }
381 | pp_expr tLSHIFT pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, <<); }
382 | pp_expr tRSHIFT pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, >>); }
383 |
'+' pp_expr
{ $$
= $2; }
384 |
'-' pp_expr
{ UNARY_OP
($$
, $2, -); }
385 |
'~' pp_expr
{ UNARY_OP
($$
, $2, ~
); }
386 |
'!' pp_expr
{ $$.type
= cv_sint
; $$.val.si
= !boolean
(&$2); }
387 |
'(' pp_expr
')' { $$
= $2; }
388 | pp_expr
'?' pp_expr
':' pp_expr
{ $$
= boolean
(&$1) ?
$3 : $5; }
394 **************************************************************************
396 **************************************************************************
399 static void cast_to_sint
(cval_t
*v
)
405 case cv_slong
: v
->val.si
= v
->val.sl
; break
;
406 case cv_ulong
: v
->val.si
= v
->val.ul
; break
;
407 case cv_sll
: v
->val.si
= v
->val.sll
; break
;
408 case cv_ull
: v
->val.si
= v
->val.ull
; break
;
413 static void cast_to_uint
(cval_t
*v
)
419 case cv_slong
: v
->val.ui
= v
->val.sl
; break
;
420 case cv_ulong
: v
->val.ui
= v
->val.ul
; break
;
421 case cv_sll
: v
->val.ui
= v
->val.sll
; break
;
422 case cv_ull
: v
->val.ui
= v
->val.ull
; break
;
427 static void cast_to_slong
(cval_t
*v
)
431 case cv_sint
: v
->val.sl
= v
->val.si
; break
;
432 case cv_uint
: v
->val.sl
= v
->val.ui
; break
;
433 case cv_slong
: break
;
434 case cv_ulong
: break
;
435 case cv_sll
: v
->val.sl
= v
->val.sll
; break
;
436 case cv_ull
: v
->val.sl
= v
->val.ull
; break
;
441 static void cast_to_ulong
(cval_t
*v
)
445 case cv_sint
: v
->val.ul
= v
->val.si
; break
;
446 case cv_uint
: v
->val.ul
= v
->val.ui
; break
;
447 case cv_slong
: break
;
448 case cv_ulong
: break
;
449 case cv_sll
: v
->val.ul
= v
->val.sll
; break
;
450 case cv_ull
: v
->val.ul
= v
->val.ull
; break
;
455 static void cast_to_sll
(cval_t
*v
)
459 case cv_sint
: v
->val.sll
= v
->val.si
; break
;
460 case cv_uint
: v
->val.sll
= v
->val.ui
; break
;
461 case cv_slong
: v
->val.sll
= v
->val.sl
; break
;
462 case cv_ulong
: v
->val.sll
= v
->val.ul
; break
;
469 static void cast_to_ull
(cval_t
*v
)
473 case cv_sint
: v
->val.ull
= v
->val.si
; break
;
474 case cv_uint
: v
->val.ull
= v
->val.ui
; break
;
475 case cv_slong
: v
->val.ull
= v
->val.sl
; break
;
476 case cv_ulong
: v
->val.ull
= v
->val.ul
; break
;
484 static void promote_equal_size
(cval_t
*v1
, cval_t
*v2
)
486 #define cv_sizeof(v) ((int)(v->type & SIZE_MASK))
487 int s1
= cv_sizeof
(v1
);
488 int s2
= cv_sizeof
(v2
);
497 case cv_sint
: cast_to_sint
(v2
); break
;
498 case cv_uint
: cast_to_uint
(v2
); break
;
499 case cv_slong
: cast_to_slong
(v2
); break
;
500 case cv_ulong
: cast_to_ulong
(v2
); break
;
501 case cv_sll
: cast_to_sll
(v2
); break
;
502 case cv_ull
: cast_to_ull
(v2
); break
;
509 case cv_sint
: cast_to_sint
(v1
); break
;
510 case cv_uint
: cast_to_uint
(v1
); break
;
511 case cv_slong
: cast_to_slong
(v1
); break
;
512 case cv_ulong
: cast_to_ulong
(v1
); break
;
513 case cv_sll
: cast_to_sll
(v1
); break
;
514 case cv_ull
: cast_to_ull
(v1
); break
;
520 static int boolean
(cval_t
*v
)
524 case cv_sint
: return v
->val.si
!= 0;
525 case cv_uint
: return v
->val.ui
!= 0;
526 case cv_slong
: return v
->val.sl
!= 0;
527 case cv_ulong
: return v
->val.ul
!= 0;
528 case cv_sll
: return v
->val.sll
!= 0;
529 case cv_ull
: return v
->val.ull
!= 0;
534 static char *add_new_marg
(char *str
)
537 macro_args
= xrealloc
(macro_args
, (nmacro_args
+1) * sizeof
(macro_args
[0]));
538 macro_args
[nmacro_args
++] = ma
= xstrdup
(str
);
542 static int marg_index
(char *id
)
547 for
(t
= 0; t
< nmacro_args
; t
++)
549 if
(!strcmp
(id
, macro_args
[t
]))
552 return t
< nmacro_args ? t
: -1;
555 static mtext_t
*new_mtext
(char *str
, int idx
, def_exp_t type
)
557 mtext_t
*mt
= xmalloc
(sizeof
(mtext_t
));
560 mt
->subst.argidx
= idx
;
562 mt
->subst.text
= str
;
564 mt
->next
= mt
->prev
= NULL
;
568 static mtext_t
*combine_mtext
(mtext_t
*tail
, mtext_t
*mtp
)
576 if
(tail
->type
== exp_text
&& mtp
->type
== exp_text
)
578 tail
->subst.text
= xrealloc
(tail
->subst.text
, strlen
(tail
->subst.text
)+strlen
(mtp
->subst.text
)+1);
579 strcat
(tail
->subst.text
, mtp
->subst.text
);
580 free
(mtp
->subst.text
);
585 if
(tail
->type
== exp_concat
&& mtp
->type
== exp_concat
)
591 if
(tail
->type
== exp_concat
&& mtp
->type
== exp_text
)
593 int len
= strlen
(mtp
->subst.text
);
596 /* FIXME: should delete space from head of string */
597 if
(isspace
(mtp
->subst.text
[len
-1] & 0xff))
598 mtp
->subst.text
[--len
] = '\0';
605 free
(mtp
->subst.text
);
611 if
(tail
->type
== exp_text
&& mtp
->type
== exp_concat
)
613 int len
= strlen
(tail
->subst.text
);
616 if
(isspace
(tail
->subst.text
[len
-1] & 0xff))
617 tail
->subst.text
[--len
] = '\0';
624 mtp
->prev
= tail
->prev
;
625 mtp
->next
= tail
->next
;
627 tail
->prev
->next
= mtp
;
628 free
(tail
->subst.text
);
640 static char *merge_text
(char *s1
, char *s2
)
644 s1
= xrealloc
(s1
, l1
+l2
+1);
645 memcpy
(s1
+l1
, s2
, l2
+1);