2 * Wrc preprocessor syntax analysis
4 * Copyright 1999-2000 Bertho A. Stultiens (BS)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * 24-Apr-2000 BS Restructured the lot to fit the new scanner
23 * and reintegrate into the wine-tree.
24 * 01-Jan-2000 BS FIXME: win16 preprocessor calculates with
25 * 16 bit ints and overflows...?
26 * 26-Dec-1999 BS Started this file
32 #include "wine/port.h"
41 #include "wpp_private.h"
44 #define UNARY_OP(r, v, OP) \
47 case cv_sint
: r.val.si
= OP v.val.si
; break
; \
48 case cv_uint
: r.val.ui
= OP v.val.ui
; break
; \
49 case cv_slong
: r.val.sl
= OP v.val.sl
; break
; \
50 case cv_ulong
: r.val.ul
= OP v.val.ul
; break
; \
51 case cv_sll
: r.val.sll
= OP v.val.sll
; break
; \
52 case cv_ull
: r.val.ull
= OP v.val.ull
; break
; \
55 #define cv_signed(v) ((v.type & FLAG_SIGNED) != 0)
57 #define BIN_OP_INT(r, v1, v2, OP) \
59 if
(cv_signed
(v1
) && cv_signed
(v2
)) \
60 r.val.si
= v1.val.si OP v2.val.si
; \
61 else if
(cv_signed
(v1
) && !cv_signed
(v2
)) \
62 r.val.si
= v1.val.si OP v2.val.ui
; \
63 else if
(!cv_signed
(v1
) && cv_signed
(v2
)) \
64 r.val.ui
= v1.val.ui OP v2.val.si
; \
66 r.val.ui
= v1.val.ui OP v2.val.ui
;
68 #define BIN_OP_LONG(r, v1, v2, OP) \
70 if
(cv_signed
(v1
) && cv_signed
(v2
)) \
71 r.val.sl
= v1.val.sl OP v2.val.sl
; \
72 else if
(cv_signed
(v1
) && !cv_signed
(v2
)) \
73 r.val.sl
= v1.val.sl OP v2.val.ul
; \
74 else if
(!cv_signed
(v1
) && cv_signed
(v2
)) \
75 r.val.ul
= v1.val.ul OP v2.val.sl
; \
77 r.val.ul
= v1.val.ul OP v2.val.ul
;
79 #define BIN_OP_LONGLONG(r, v1, v2, OP) \
81 if
(cv_signed
(v1
) && cv_signed
(v2
)) \
82 r.val.sll
= v1.val.sll OP v2.val.sll
; \
83 else if
(cv_signed
(v1
) && !cv_signed
(v2
)) \
84 r.val.sll
= v1.val.sll OP v2.val.ull
; \
85 else if
(!cv_signed
(v1
) && cv_signed
(v2
)) \
86 r.val.ull
= v1.val.ull OP v2.val.sll
; \
88 r.val.ull
= v1.val.ull OP v2.val.ull
;
90 #define BIN_OP(r, v1, v2, OP) \
91 switch
(v1.type
& SIZE_MASK
) \
93 case SIZE_INT
: BIN_OP_INT
(r
, v1
, v2
, OP
); break
; \
94 case SIZE_LONG
: BIN_OP_LONG
(r
, v1
, v2
, OP
); break
; \
95 case SIZE_LONGLONG
: BIN_OP_LONGLONG
(r
, v1
, v2
, OP
); break
; \
96 default
: pp_internal_error
(__FILE__
, __LINE__
, "Invalid type indicator (0x%04x)", v1.type
); \
103 static int boolean
(cval_t
*v
);
104 static void promote_equal_size
(cval_t
*v1
, cval_t
*v2
);
105 static void cast_to_sint
(cval_t
*v
);
106 static void cast_to_uint
(cval_t
*v
);
107 static void cast_to_slong
(cval_t
*v
);
108 static void cast_to_ulong
(cval_t
*v
);
109 static void cast_to_sll
(cval_t
*v
);
110 static void cast_to_ull
(cval_t
*v
);
111 static marg_t
*new_marg
(char *str
, def_arg_t type
);
112 static marg_t
*add_new_marg
(char *str
, def_arg_t type
);
113 static int marg_index
(char *id
);
114 static mtext_t
*new_mtext
(char *str
, int idx
, def_exp_t type
);
115 static mtext_t
*combine_mtext
(mtext_t
*tail
, mtext_t
*mtp
);
116 static char *merge_text
(char *s1
, char *s2
);
121 static marg_t
**macro_args
; /* Macro parameters array while parsing */
122 static int nmacro_args
;
141 %token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL
142 %token tINCLUDE tLINE tGCCLINE tERROR tWARNING tPRAGMA tPPIDENT
143 %token tUNDEF tMACROEND tCONCAT tELIPSIS tSTRINGIZE
144 %token
<cptr
> tIDENT tLITERAL tMACRO tDEFINE
145 %token
<cptr
> tDQSTRING tSQSTRING tIQSTRING
148 %token
<ulong
> tULONG
149 %token
<slong
> tSLONG
150 %token
<ull
> tULONGLONG
151 %token
<sll
> tSLONGLONG
152 %token
<cptr
> tRCINCLUDEPATH
161 %left
'<' tLTE
'>' tGTE
162 %left tLSHIFT tRSHIFT
168 %type
<marg
> emargs margs
169 %type
<mtext
> opt_mtexts mtexts mtext
170 %type
<sint
> allmargs
171 %type
<cptr
> opt_text text
174 **************************************************************************
175 * The parser starts here
176 **************************************************************************
181 pp_file
: /* Empty */
182 | pp_file preprocessor
186 : tINCLUDE tDQSTRING tNL
{ pp_do_include
($2, 1); }
187 | tINCLUDE tIQSTRING tNL
{ pp_do_include
($2, 0); }
188 | tIF pp_expr tNL
{ pp_next_if_state
(boolean
(&$2)); }
189 | tIFDEF tIDENT tNL
{ pp_next_if_state
(pplookup
($2) != NULL
); free
($2); }
190 | tIFNDEF tIDENT tNL
{
191 int t
= pplookup
($2) == NULL
;
192 if
(pp_incl_state.state
== 0 && t
&& !pp_incl_state.seen_junk
)
194 pp_incl_state.state
= 1;
195 pp_incl_state.ppp
= $2;
196 pp_incl_state.ifdepth
= pp_get_if_depth
();
198 else if
(pp_incl_state.state
!= 1)
200 pp_incl_state.state
= -1;
207 fprintf
(stderr
, "tIFNDEF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
208 pp_status.input
, pp_status.line_number
, pp_incl_state.state
, pp_incl_state.ppp
, pp_incl_state.ifdepth
);
210 | tELIF pp_expr tNL
{
211 pp_if_state_t s
= pp_pop_if
();
219 pp_push_if
(boolean
(&$2) ? if_true
: if_false
);
222 pp_push_if
(if_ignore
);
226 ppy_error
("#elif cannot follow #else");
231 pp_internal_error
(__FILE__
, __LINE__
, "Invalid pp_if_state (%d) in #elif directive", s
);
235 pp_if_state_t s
= pp_pop_if
();
239 pp_push_if
(if_elsefalse
);
245 pp_push_if
(if_elsetrue
);
248 pp_push_if
(if_ignore
);
252 ppy_error
("#else clause already defined");
257 pp_internal_error
(__FILE__
, __LINE__
, "Invalid pp_if_state (%d) in #else directive", s
);
261 if
(pp_pop_if
() != if_error
)
263 if
(pp_incl_state.ifdepth
== pp_get_if_depth
() && pp_incl_state.state
== 1)
265 pp_incl_state.state
= 2;
266 pp_incl_state.seen_junk
= 0;
268 else if
(pp_incl_state.state
!= 1)
270 pp_incl_state.state
= -1;
273 fprintf
(stderr
, "tENDIF: %s:%d: include_state=%d, include_ppp='%s', include_ifdepth=%d\n",
274 pp_status.input
, pp_status.line_number
, pp_incl_state.state
, pp_incl_state.ppp
, pp_incl_state.ifdepth
);
277 | tUNDEF tIDENT tNL
{ pp_del_define
($2); free
($2); }
278 | tDEFINE opt_text tNL
{ pp_add_define
($1, $2); }
279 | tMACRO res_arg allmargs tMACROEND opt_mtexts tNL
{
280 pp_add_macro
($1, macro_args
, nmacro_args
, $5);
282 | tLINE tSINT tDQSTRING tNL
{ if
($3) pp_writestring
("# %d %s\n", $2 , $3); free
($3); }
283 | tGCCLINE tSINT tDQSTRING tNL
{ if
($3) pp_writestring
("# %d %s\n", $2 , $3); free
($3); }
284 | tGCCLINE tSINT tDQSTRING tSINT tNL
285 { if
($3) pp_writestring
("# %d %s %d\n", $2, $3, $4); free
($3); }
286 | tGCCLINE tSINT tDQSTRING tSINT tSINT tNL
287 { if
($3) pp_writestring
("# %d %s %d %d\n", $2 ,$3, $4, $5); free
($3); }
288 | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tNL
289 { if
($3) pp_writestring
("# %d %s %d %d %d\n", $2 ,$3 ,$4 ,$5, $6); free
($3); }
290 | tGCCLINE tSINT tDQSTRING tSINT tSINT tSINT tSINT tNL
291 { if
($3) pp_writestring
("# %d %s %d %d %d %d\n", $2 ,$3 ,$4 ,$5, $6, $7); free
($3); }
292 | tGCCLINE tNL
/* The null-token */
293 | tERROR opt_text tNL
{ ppy_error
("#error directive: '%s'", $2); free
($2); }
294 | tWARNING opt_text tNL
{ ppy_warning
("#warning directive: '%s'", $2); free
($2); }
295 | tPRAGMA opt_text tNL
{ pp_writestring
("#pragma %s\n", $2 ?
$2 : ""); free
($2); }
296 | tPPIDENT opt_text tNL
{ if
(pp_status.pedantic
) ppy_warning
("#ident ignored (arg: '%s')", $2); free
($2); }
297 | tRCINCLUDE tRCINCLUDEPATH
{
300 int nl
=strlen
($2) +3;
301 char *fn
=pp_xmalloc
(nl
);
304 sprintf
(fn
,"\"%s\"",$2);
310 | tRCINCLUDE tDQSTRING
{
316 opt_text: /* Empty */ { $$
= NULL
; }
320 text
: tLITERAL
{ $$
= $1; }
321 | tDQSTRING
{ $$
= $1; }
322 | tSQSTRING
{ $$
= $1; }
323 | text tLITERAL
{ $$
= merge_text
($1, $2); }
324 | text tDQSTRING
{ $$
= merge_text
($1, $2); }
325 | text tSQSTRING
{ $$
= merge_text
($1, $2); }
328 res_arg
: /* Empty */ { macro_args
= NULL
; nmacro_args
= 0; }
331 allmargs: /* Empty */ { $$
= 0; macro_args
= NULL
; nmacro_args
= 0; }
332 | emargs
{ $$
= nmacro_args
; }
335 emargs
: margs
{ $$
= $1; }
336 | margs
',' tELIPSIS
{ $$
= add_new_marg
(NULL
, arg_list
); nmacro_args
*= -1; }
339 margs
: margs
',' tIDENT
{ $$
= add_new_marg
($3, arg_single
); }
340 | tIDENT
{ $$
= add_new_marg
($1, arg_single
); }
344 : /* Empty */ { $$
= NULL
; }
346 for
($$
= $1; $$
&& $$
->prev
; $$
= $$
->prev
)
351 mtexts
: mtext
{ $$
= $1; }
352 | mtexts mtext
{ $$
= combine_mtext
($1, $2); }
355 mtext
: tLITERAL
{ $$
= new_mtext
($1, 0, exp_text
); }
356 | tDQSTRING
{ $$
= new_mtext
($1, 0, exp_text
); }
357 | tSQSTRING
{ $$
= new_mtext
($1, 0, exp_text
); }
358 | tCONCAT
{ $$
= new_mtext
(NULL
, 0, exp_concat
); }
359 | tSTRINGIZE tIDENT
{
360 int mat
= marg_index
($2);
362 ppy_error
("Stringification identifier must be an argument parameter");
364 $$
= new_mtext
(NULL
, mat
, exp_stringize
);
367 int mat
= marg_index
($1);
369 $$
= new_mtext
(NULL
, mat
, exp_subst
);
371 $$
= new_mtext
($1, 0, exp_text
);
375 pp_expr
: tSINT
{ $$.type
= cv_sint
; $$.val.si
= $1; }
376 | tUINT
{ $$.type
= cv_uint
; $$.val.ui
= $1; }
377 | tSLONG
{ $$.type
= cv_slong
; $$.val.sl
= $1; }
378 | tULONG
{ $$.type
= cv_ulong
; $$.val.ul
= $1; }
379 | tSLONGLONG
{ $$.type
= cv_sll
; $$.val.sll
= $1; }
380 | tULONGLONG
{ $$.type
= cv_ull
; $$.val.ull
= $1; }
381 | tDEFINED tIDENT
{ $$.type
= cv_sint
; $$.val.si
= pplookup
($2) != NULL
; }
382 | tDEFINED
'(' tIDENT
')' { $$.type
= cv_sint
; $$.val.si
= pplookup
($3) != NULL
; }
383 | tIDENT
{ $$.type
= cv_sint
; $$.val.si
= 0; }
384 | pp_expr tLOGOR pp_expr
{ $$.type
= cv_sint
; $$.val.si
= boolean
(&$1) || boolean
(&$3); }
385 | pp_expr tLOGAND pp_expr
{ $$.type
= cv_sint
; $$.val.si
= boolean
(&$1) && boolean
(&$3); }
386 | pp_expr tEQ pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, ==) }
387 | pp_expr tNE pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, !=) }
388 | pp_expr
'<' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, <) }
389 | pp_expr
'>' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, >) }
390 | pp_expr tLTE pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, <=) }
391 | pp_expr tGTE pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, >=) }
392 | pp_expr
'+' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, +) }
393 | pp_expr
'-' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, -) }
394 | pp_expr
'^' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, ^
) }
395 | pp_expr
'&' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, &) }
396 | pp_expr
'|' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, |
) }
397 | pp_expr
'*' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, *) }
398 | pp_expr
'/' pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, /) }
399 | pp_expr tLSHIFT pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, <<) }
400 | pp_expr tRSHIFT pp_expr
{ promote_equal_size
(&$1, &$3); BIN_OP
($$
, $1, $3, >>) }
401 |
'+' pp_expr
{ $$
= $2; }
402 |
'-' pp_expr
{ UNARY_OP
($$
, $2, -) }
403 |
'~' pp_expr
{ UNARY_OP
($$
, $2, ~
) }
404 |
'!' pp_expr
{ $$.type
= cv_sint
; $$.val.si
= !boolean
(&$2); }
405 |
'(' pp_expr
')' { $$
= $2; }
406 | pp_expr
'?' pp_expr
':' pp_expr
{ $$
= boolean
(&$1) ?
$3 : $5; }
412 **************************************************************************
414 **************************************************************************
417 static void cast_to_sint
(cval_t
*v
)
423 case cv_slong
: v
->val.si
= v
->val.sl
; break
;
424 case cv_ulong
: v
->val.si
= v
->val.ul
; break
;
425 case cv_sll
: v
->val.si
= v
->val.sll
; break
;
426 case cv_ull
: v
->val.si
= v
->val.ull
; break
;
431 static void cast_to_uint
(cval_t
*v
)
437 case cv_slong
: v
->val.ui
= v
->val.sl
; break
;
438 case cv_ulong
: v
->val.ui
= v
->val.ul
; break
;
439 case cv_sll
: v
->val.ui
= v
->val.sll
; break
;
440 case cv_ull
: v
->val.ui
= v
->val.ull
; break
;
445 static void cast_to_slong
(cval_t
*v
)
449 case cv_sint
: v
->val.sl
= v
->val.si
; break
;
450 case cv_uint
: v
->val.sl
= v
->val.ui
; break
;
451 case cv_slong
: break
;
452 case cv_ulong
: break
;
453 case cv_sll
: v
->val.sl
= v
->val.sll
; break
;
454 case cv_ull
: v
->val.sl
= v
->val.ull
; break
;
459 static void cast_to_ulong
(cval_t
*v
)
463 case cv_sint
: v
->val.ul
= v
->val.si
; break
;
464 case cv_uint
: v
->val.ul
= v
->val.ui
; break
;
465 case cv_slong
: break
;
466 case cv_ulong
: break
;
467 case cv_sll
: v
->val.ul
= v
->val.sll
; break
;
468 case cv_ull
: v
->val.ul
= v
->val.ull
; break
;
473 static void cast_to_sll
(cval_t
*v
)
477 case cv_sint
: v
->val.sll
= v
->val.si
; break
;
478 case cv_uint
: v
->val.sll
= v
->val.ui
; break
;
479 case cv_slong
: v
->val.sll
= v
->val.sl
; break
;
480 case cv_ulong
: v
->val.sll
= v
->val.ul
; break
;
487 static void cast_to_ull
(cval_t
*v
)
491 case cv_sint
: v
->val.ull
= v
->val.si
; break
;
492 case cv_uint
: v
->val.ull
= v
->val.ui
; break
;
493 case cv_slong
: v
->val.ull
= v
->val.sl
; break
;
494 case cv_ulong
: v
->val.ull
= v
->val.ul
; break
;
502 static void promote_equal_size
(cval_t
*v1
, cval_t
*v2
)
504 #define cv_sizeof(v) ((int)(v->type & SIZE_MASK))
505 int s1
= cv_sizeof
(v1
);
506 int s2
= cv_sizeof
(v2
);
515 case cv_sint
: cast_to_sint
(v2
); break
;
516 case cv_uint
: cast_to_uint
(v2
); break
;
517 case cv_slong
: cast_to_slong
(v2
); break
;
518 case cv_ulong
: cast_to_ulong
(v2
); break
;
519 case cv_sll
: cast_to_sll
(v2
); break
;
520 case cv_ull
: cast_to_ull
(v2
); break
;
527 case cv_sint
: cast_to_sint
(v1
); break
;
528 case cv_uint
: cast_to_uint
(v1
); break
;
529 case cv_slong
: cast_to_slong
(v1
); break
;
530 case cv_ulong
: cast_to_ulong
(v1
); break
;
531 case cv_sll
: cast_to_sll
(v1
); break
;
532 case cv_ull
: cast_to_ull
(v1
); break
;
538 static int boolean
(cval_t
*v
)
542 case cv_sint
: return v
->val.si
!= (int)0;
543 case cv_uint
: return v
->val.ui
!= (unsigned int)0;
544 case cv_slong
: return v
->val.sl
!= (long)0;
545 case cv_ulong
: return v
->val.ul
!= (unsigned long)0;
546 case cv_sll
: return v
->val.sll
!= (wrc_sll_t
)0;
547 case cv_ull
: return v
->val.ull
!= (wrc_ull_t
)0;
552 static marg_t
*new_marg
(char *str
, def_arg_t type
)
554 marg_t
*ma
= pp_xmalloc
(sizeof
(marg_t
));
563 static marg_t
*add_new_marg
(char *str
, def_arg_t type
)
565 marg_t
**new_macro_args
;
569 new_macro_args
= pp_xrealloc
(macro_args
, (nmacro_args
+1) * sizeof
(macro_args
[0]));
572 macro_args
= new_macro_args
;
573 ma
= new_marg
(str
, type
);
576 macro_args
[nmacro_args
] = ma
;
581 static int marg_index
(char *id
)
586 for
(t
= 0; t
< nmacro_args
; t
++)
588 if
(!strcmp
(id
, macro_args
[t
]->arg
))
591 return t
< nmacro_args ? t
: -1;
594 static mtext_t
*new_mtext
(char *str
, int idx
, def_exp_t type
)
596 mtext_t
*mt
= pp_xmalloc
(sizeof
(mtext_t
));
600 mt
->subst.argidx
= idx
;
602 mt
->subst.text
= str
;
604 mt
->next
= mt
->prev
= NULL
;
608 static mtext_t
*combine_mtext
(mtext_t
*tail
, mtext_t
*mtp
)
616 if
(tail
->type
== exp_text
&& mtp
->type
== exp_text
)
619 new_text
= pp_xrealloc
(tail
->subst.text
, strlen
(tail
->subst.text
)+strlen
(mtp
->subst.text
)+1);
622 tail
->subst.text
= new_text
;
623 strcat
(tail
->subst.text
, mtp
->subst.text
);
624 free
(mtp
->subst.text
);
629 if
(tail
->type
== exp_concat
&& mtp
->type
== exp_concat
)
635 if
(tail
->type
== exp_concat
&& mtp
->type
== exp_text
)
637 int len
= strlen
(mtp
->subst.text
);
640 /* FIXME: should delete space from head of string */
641 if
(isspace
(mtp
->subst.text
[len
-1] & 0xff))
642 mtp
->subst.text
[--len
] = '\0';
649 free
(mtp
->subst.text
);
655 if
(tail
->type
== exp_text
&& mtp
->type
== exp_concat
)
657 int len
= strlen
(tail
->subst.text
);
660 if
(isspace
(tail
->subst.text
[len
-1] & 0xff))
661 tail
->subst.text
[--len
] = '\0';
668 mtp
->prev
= tail
->prev
;
669 mtp
->next
= tail
->next
;
671 tail
->prev
->next
= mtp
;
672 free
(tail
->subst.text
);
684 static char *merge_text
(char *s1
, char *s2
)
695 snew
= pp_xrealloc
(s1
, l1
+l2
+1);
702 memcpy
(s1
+l1
, s2
, l2
+1);