1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
29 # include "php_config.h"
40 struct psi_num_exp
*psi_num_exp_init_ternary(token_t op
,
41 struct psi_num_exp
*cond
, struct psi_num_exp
*truthy
,
42 struct psi_num_exp
*falsy
)
44 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
47 exp
->data
.t
.cond
= cond
;
48 exp
->data
.t
.truthy
= truthy
;
49 exp
->data
.t
.falsy
= falsy
;
54 struct psi_num_exp
*psi_num_exp_init_binary(token_t op
,
55 struct psi_num_exp
*lhs
, struct psi_num_exp
*rhs
)
57 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
60 exp
->data
.b
.lhs
= lhs
;
61 exp
->data
.b
.rhs
= rhs
;
66 struct psi_num_exp
*psi_num_exp_init_unary(token_t op
,
67 struct psi_num_exp
*u
)
69 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
77 struct psi_num_exp
*psi_num_exp_init_num(struct psi_number
*n
)
79 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
81 exp
->op
= PSI_T_NUMBER
;
87 struct psi_num_exp
*psi_num_exp_init_cast(struct psi_decl_type
*typ
,
88 struct psi_num_exp
*num
)
90 struct psi_num_exp
*exp
= pecalloc(1, sizeof(*exp
), 1);
93 exp
->data
.c
.typ
= typ
;
94 exp
->data
.c
.num
= num
;
99 struct psi_num_exp
*psi_num_exp_copy(struct psi_num_exp
*exp
)
101 struct psi_num_exp
*cpy
;
107 cpy
= pemalloc(sizeof(*cpy
), 1);
112 cpy
->data
.n
= psi_number_copy(exp
->data
.n
);
116 cpy
->data
.c
.typ
= psi_decl_type_copy(exp
->data
.c
.typ
);
117 cpy
->data
.c
.num
= psi_num_exp_copy(exp
->data
.c
.num
);
123 cpy
->data
.u
= psi_num_exp_copy(exp
->data
.u
);
138 case PSI_T_AMPERSAND
:
146 cpy
->data
.b
.lhs
= psi_num_exp_copy(exp
->data
.b
.lhs
);
147 cpy
->data
.b
.rhs
= psi_num_exp_copy(exp
->data
.b
.rhs
);
151 cpy
->data
.t
.cond
= psi_num_exp_copy(exp
->data
.t
.cond
);
152 cpy
->data
.t
.truthy
= psi_num_exp_copy(exp
->data
.t
.truthy
);
153 cpy
->data
.t
.falsy
= psi_num_exp_copy(exp
->data
.t
.falsy
);
161 cpy
->token
= psi_token_copy(exp
->token
);
167 void psi_num_exp_copy_ctor(struct psi_num_exp
**exp_ptr
)
169 *exp_ptr
= psi_num_exp_copy(*exp_ptr
);
172 void psi_num_exp_free(struct psi_num_exp
**c_ptr
)
175 struct psi_num_exp
*c
= *c_ptr
;
181 psi_number_free(&c
->data
.n
);
185 psi_decl_type_free(&c
->data
.c
.typ
);
186 psi_num_exp_free(&c
->data
.c
.num
);
192 psi_num_exp_free(&c
->data
.u
);
207 case PSI_T_AMPERSAND
:
215 psi_num_exp_free(&c
->data
.b
.lhs
);
216 psi_num_exp_free(&c
->data
.b
.rhs
);
220 psi_num_exp_free(&c
->data
.t
.cond
);
221 psi_num_exp_free(&c
->data
.t
.truthy
);
222 psi_num_exp_free(&c
->data
.t
.falsy
);
229 psi_token_free(&c
->token
);
235 static inline const char *psi_num_exp_op_tok(token_t op
)
251 case PSI_T_AMPERSAND
:
298 struct psi_plist
*psi_num_exp_tokens(struct psi_num_exp
*exp
,
299 struct psi_plist
*list
)
301 struct psi_token
*ntoken
;
304 list
= psi_plist_init((psi_plist_dtor
) psi_token_free
);
309 list
= psi_number_tokens(exp
->data
.n
, list
);
313 ntoken
= exp
->data
.c
.typ
->token
;
314 ntoken
= psi_token_init(PSI_T_LPAREN
, "(", 1, ntoken
->col
-1, ntoken
->line
, ntoken
->file
);
315 list
= psi_plist_add(list
, &ntoken
);
316 ntoken
= psi_token_copy(exp
->data
.c
.typ
->token
);
317 list
= psi_plist_add(list
, &ntoken
);
318 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
319 list
= psi_plist_add(list
, &ntoken
);
325 ntoken
= psi_token_copy(exp
->token
);
326 list
= psi_plist_add(list
, &ntoken
);
327 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
331 ntoken
= psi_token_copy(exp
->token
);
332 list
= psi_plist_add(list
, &ntoken
);
333 list
= psi_num_exp_tokens(exp
->data
.u
, list
);
334 psi_plist_top(list
, &ntoken
);
335 ntoken
= psi_token_init(PSI_T_RPAREN
, ")", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
336 list
= psi_plist_add(list
, &ntoken
);
341 if (!exp
->data
.b
.rhs
) {
347 case PSI_T_AMPERSAND
:
363 list
= psi_num_exp_tokens(exp
->data
.b
.lhs
, list
);
364 ntoken
= psi_token_copy(exp
->token
);
365 list
= psi_plist_add(list
, &ntoken
);
366 list
= psi_num_exp_tokens(exp
->data
.b
.rhs
, list
);
370 list
= psi_num_exp_tokens(exp
->data
.t
.cond
, list
);
371 ntoken
= psi_token_copy(exp
->token
);
372 list
= psi_plist_add(list
, &ntoken
);
373 list
= psi_num_exp_tokens(exp
->data
.t
.truthy
, list
);
374 psi_plist_top(list
, &ntoken
);
375 ntoken
= psi_token_init(PSI_T_COLON
, ":", 1, ntoken
->col
+ntoken
->text
->len
, ntoken
->line
, ntoken
->file
);
376 list
= psi_plist_add(list
, &ntoken
);
377 list
= psi_plist_add(list
, &ntoken
);
378 list
= psi_num_exp_tokens(exp
->data
.t
.falsy
, list
);
388 void psi_num_exp_dump(struct psi_dump
*dump
, struct psi_num_exp
*exp
)
392 psi_number_dump(dump
, exp
->data
.n
);
397 psi_decl_type_dump(dump
, exp
->data
.c
.typ
, 0);
399 psi_num_exp_dump(dump
, exp
->data
.c
.num
);
405 PSI_DUMP(dump
, "%s", psi_num_exp_op_tok(exp
->op
));
406 psi_num_exp_dump(dump
, exp
->data
.u
);
411 psi_num_exp_dump(dump
, exp
->data
.u
);
417 if (!exp
->data
.b
.rhs
) {
423 case PSI_T_AMPERSAND
:
438 psi_num_exp_dump(dump
, exp
->data
.b
.lhs
);
439 PSI_DUMP(dump
, " %s ", psi_num_exp_op_tok(exp
->op
));
440 psi_num_exp_dump(dump
, exp
->data
.b
.rhs
);
444 psi_num_exp_dump(dump
, exp
->data
.t
.cond
);
445 PSI_DUMP(dump
, " ? ");
446 psi_num_exp_dump(dump
, exp
->data
.t
.truthy
);
447 PSI_DUMP(dump
, " : ");
448 psi_num_exp_dump(dump
, exp
->data
.t
.falsy
);
457 bool psi_num_exp_validate(struct psi_data
*data
, struct psi_num_exp
*exp
,
458 struct psi_validate_scope
*scope
)
460 if (exp
->op
&& exp
->op
!= PSI_T_NUMBER
) {
463 exp
->calc
= psi_calc_bool_not
;
466 exp
->calc
= psi_calc_bin_not
;
470 exp
->calc
= psi_calc_bool_or
;
473 exp
->calc
= psi_calc_bool_and
;
476 exp
->calc
= psi_calc_cmp_eq
;
479 exp
->calc
= psi_calc_cmp_ne
;
482 exp
->calc
= psi_calc_cmp_le
;
485 exp
->calc
= psi_calc_cmp_ge
;
488 exp
->calc
= psi_calc_cmp_lt
;
491 exp
->calc
= psi_calc_cmp_gt
;
500 exp
->calc
= psi_calc_bin_or
;
503 exp
->calc
= psi_calc_bin_xor
;
505 case PSI_T_AMPERSAND
:
506 exp
->calc
= psi_calc_bin_and
;
509 exp
->calc
= psi_calc_bin_lshift
;
512 exp
->calc
= psi_calc_bin_rshift
;
515 if (exp
->data
.b
.rhs
) {
516 exp
->calc
= psi_calc_add
;
520 if (exp
->data
.b
.rhs
) {
521 exp
->calc
= psi_calc_sub
;
523 exp
->calc
= psi_calc_minus
;
527 exp
->calc
= psi_calc_mul
;
530 exp
->calc
= psi_calc_div
;
533 exp
->calc
= psi_calc_mod
;
536 data
->error(data
, exp
->token
, PSI_WARNING
,
537 "Unknown numeric operator (%d)", exp
->op
);
544 return psi_number_validate(data
, exp
->data
.n
, scope
);
547 return psi_num_exp_validate(data
, exp
->data
.c
.num
, scope
)
548 && psi_decl_type_validate(data
, exp
->data
.c
.typ
, NULL
, scope
);
555 return psi_num_exp_validate(data
, exp
->data
.u
, scope
);
560 if (!exp
->data
.b
.rhs
) {
566 case PSI_T_AMPERSAND
:
582 return psi_num_exp_validate(data
, exp
->data
.b
.lhs
, scope
)
583 && psi_num_exp_validate(data
, exp
->data
.b
.rhs
, scope
);
586 return psi_num_exp_validate(data
, exp
->data
.t
.cond
, scope
)
587 && psi_num_exp_validate(data
, exp
->data
.t
.truthy
, scope
)
588 && psi_num_exp_validate(data
, exp
->data
.t
.falsy
, scope
);
597 static inline void psi_impl_val_dump(token_t t
, impl_val
*res
,
598 struct psi_call_frame
*frame
)
603 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi8
, res
->i8
);
607 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi16
, res
->i16
);
611 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi32
, res
->i32
);
615 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIi64
, res
->i64
);
618 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIfval
, res
->fval
);
621 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIdval
, res
->dval
);
624 case PSI_T_LONG_DOUBLE
:
625 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %" PRIldval
, res
->ldval
);
633 static inline void psi_num_exp_verify_result(token_t t
, impl_val
*res
, struct psi_call_frame
*frame
)
635 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", " = ");
636 psi_impl_val_dump(t
, res
, frame
);
637 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
640 static void psi_num_exp_reduce(struct psi_num_exp
*exp
, struct psi_plist
**output_ptr
,
641 struct psi_plist
**input_ptr
, struct psi_call_frame
*frame
, struct psi_cpp
*cpp
)
643 struct psi_plist
*output
= *output_ptr
, *input
= *input_ptr
;
649 struct psi_decl_type
*cast
;
655 entry
.type
= psi_number_eval(exp
->data
.n
, &entry
.data
.value
, frame
, cpp
, exp
);
656 output
= psi_plist_add(output
, &entry
);
660 entry
.type
= exp
->op
;
661 input
= psi_plist_add(input
, &entry
);
662 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, cpp
);
663 while (psi_plist_pop(input
, &entry
)) {
664 if (entry
.type
== PSI_T_LPAREN
) {
667 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
668 output
= psi_plist_add(output
, &entry
);
673 while (psi_plist_top(input
, &entry
)) {
674 /* bail out if exp->op >= entry.type */
675 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
678 psi_plist_pop(input
, NULL
);
679 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
680 output
= psi_plist_add(output
, &entry
);
682 entry
.type
= exp
->op
;
683 entry
.data
.cast
= exp
->data
.c
.typ
;
684 input
= psi_plist_add(input
, &entry
);
685 psi_num_exp_reduce(exp
->data
.c
.num
, &output
, &input
, frame
, cpp
);
690 while (psi_plist_top(input
, &entry
)) {
691 /* bail out if exp->op >= entry.type */
692 if (psi_calc_oper(exp
->op
, entry
.type
) != 1) {
695 psi_plist_pop(input
, NULL
);
696 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
697 output
= psi_plist_add(output
, &entry
);
699 entry
.type
= exp
->op
;
700 entry
.data
.calc
= exp
->calc
;
701 input
= psi_plist_add(input
, &entry
);
702 psi_num_exp_reduce(exp
->data
.u
, &output
, &input
, frame
, cpp
);
707 impl_val cond_val
= {0};
708 token_t cond_typ
= psi_num_exp_exec(exp
->data
.t
.cond
, &cond_val
, frame
, cpp
);
710 psi_calc_bool_not(cond_typ
, &cond_val
, 0, NULL
, &cond_val
);
712 psi_num_exp_reduce(exp
->data
.t
.falsy
, &output
, &input
, frame
, cpp
);
714 psi_num_exp_reduce(exp
->data
.t
.truthy
, &output
, &input
, frame
, cpp
);
722 if (!exp
->data
.b
.rhs
) {
723 entry
.type
= psi_num_exp_exec(exp
->data
.b
.lhs
, &entry
.data
.value
, frame
, cpp
);
726 entry
.type
= exp
->calc(entry
.type
, &entry
.data
.value
, 0, NULL
, &entry
.data
.value
);
728 output
= psi_plist_add(output
, &entry
);
733 psi_num_exp_reduce(exp
->data
.b
.lhs
, &output
, &input
, frame
, cpp
);
734 while (psi_plist_top(input
, &entry
)) {
735 /* bail out if exp->op > entry.type */
736 if (psi_calc_oper(exp
->op
, entry
.type
) == -1) {
739 psi_plist_pop(input
, NULL
);
740 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
741 output
= psi_plist_add(output
, &entry
);
743 entry
.type
= exp
->op
;
744 entry
.data
.calc
= exp
->calc
;
745 input
= psi_plist_add(input
, &entry
);
746 psi_num_exp_reduce(exp
->data
.b
.rhs
, &output
, &input
, frame
, cpp
);
750 *output_ptr
= output
;
754 token_t
psi_num_exp_exec(struct psi_num_exp
*exp
, impl_val
*res
,
755 struct psi_call_frame
*frame
, struct psi_cpp
*cpp
)
757 struct psi_plist
*output
, *input
;
763 struct psi_decl_type
*cast
;
767 output
= psi_plist_init_ex(sizeof(entry
), NULL
);
768 input
= psi_plist_init_ex(sizeof(entry
), NULL
);
770 psi_num_exp_reduce(exp
, &output
, &input
, frame
, cpp
);
772 while (psi_plist_pop(input
, &entry
)) {
773 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
774 output
= psi_plist_add(output
, &entry
);
776 if (frame
) PSI_DEBUG_PRINT(frame
->context
, "%s", "\n");
778 while (psi_plist_shift(output
, &entry
)) {
779 switch (entry
.type
) {
781 input
= psi_plist_add(input
, &entry
);
785 psi_plist_pop(input
, &rhs
);
786 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
787 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
789 entry
.type
= psi_decl_type_get_real(entry
.data
.cast
)->type
;
790 psi_calc_cast(rhs
.type
, &rhs
.data
.value
, entry
.type
, &entry
.data
.value
);
791 input
= psi_plist_add(input
, &entry
);
792 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
797 psi_plist_pop(input
, &rhs
);
798 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
799 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
801 entry
.type
= entry
.data
.calc(rhs
.type
, &rhs
.data
.value
, 0, NULL
, &entry
.data
.value
);
802 input
= psi_plist_add(input
, &entry
);
803 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
818 case PSI_T_AMPERSAND
:
826 psi_plist_pop(input
, &rhs
);
827 psi_plist_pop(input
, &lhs
);
829 psi_impl_val_dump(lhs
.type
, &lhs
.data
.value
, frame
);
830 if (frame
) PSI_DEBUG_PRINT(frame
->context
, " %s", psi_num_exp_op_tok(entry
.type
));
831 psi_impl_val_dump(rhs
.type
, &rhs
.data
.value
, frame
);
833 entry
.type
= entry
.data
.calc(
834 lhs
.type
, &lhs
.data
.value
,
835 rhs
.type
, &rhs
.data
.value
,
837 input
= psi_plist_add(input
, &entry
);
838 psi_num_exp_verify_result(entry
.type
, &entry
.data
.value
, frame
);
842 if (!psi_plist_count(output
)) {
847 psi_plist_free(output
);
848 psi_plist_free(input
);
850 *res
= entry
.data
.value
;