PHP 8 compatibility
[m6w6/ext-psi] / src / types / number.c
index 54831964b9fc98468baf517035f80ff44d0514e6..e6edb40b342960f0177658c072accbdd90f20971 100644 (file)
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/
 
-#include "php_psi_stdinc.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
 
 #include <assert.h>
 #include <math.h>
@@ -32,6 +36,7 @@
 #include "calc.h"
 #include "call.h"
 #include "parser.h"
+#include "debug.h"
 
 #include "Zend/zend_constants.h"
 #include "Zend/zend_operators.h"
@@ -46,6 +51,7 @@ struct psi_number *psi_number_init(token_t t, void *num, unsigned flags)
        case PSI_T_INT8:
                exp->data.ival.i8 = *(int8_t *) num;
                break;
+       case PSI_T_DEFINED:
        case PSI_T_UINT8:
                exp->data.ival.u8 = *(uint8_t *) num;
                break;
@@ -84,6 +90,7 @@ struct psi_number *psi_number_init(token_t t, void *num, unsigned flags)
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
        case PSI_T_DEFINE:
+       case PSI_T_CPP_HEADER:
                exp->data.numb = zend_string_copy(num);
                break;
        case PSI_T_NAME:
@@ -113,6 +120,7 @@ struct psi_number *psi_number_copy(struct psi_number *exp)
        }
        switch (num->type) {
        case PSI_T_INT8:
+       case PSI_T_DEFINED:
        case PSI_T_UINT8:
        case PSI_T_INT16:
        case PSI_T_UINT16:
@@ -133,6 +141,7 @@ struct psi_number *psi_number_copy(struct psi_number *exp)
        case PSI_T_NSNAME:
        case PSI_T_DEFINE:
        case PSI_T_QUOTED_CHAR:
+       case PSI_T_CPP_HEADER:
                num->data.numb = zend_string_copy(num->data.numb);
                break;
        case PSI_T_NAME:
@@ -159,6 +168,7 @@ void psi_number_free(struct psi_number **exp_ptr)
                psi_token_free(&exp->token);
                switch (exp->type) {
                case PSI_T_INT8:
+               case PSI_T_DEFINED:
                case PSI_T_UINT8:
                case PSI_T_INT16:
                case PSI_T_UINT16:
@@ -182,6 +192,7 @@ void psi_number_free(struct psi_number **exp_ptr)
                case PSI_T_NUMBER:
                case PSI_T_DEFINE:
                case PSI_T_QUOTED_CHAR:
+               case PSI_T_CPP_HEADER:
                        zend_string_release(exp->data.numb);
                        break;
                case PSI_T_NAME:
@@ -201,6 +212,8 @@ struct psi_plist *psi_number_tokens(struct psi_number *exp,
                struct psi_plist *list)
 {
        struct psi_token *ntoken;
+       size_t i;
+
        if (!list) {
                list = psi_plist_init((psi_plist_dtor) psi_token_free);
        }
@@ -247,7 +260,35 @@ struct psi_plist *psi_number_tokens(struct psi_number *exp,
                list = psi_plist_add(list, &ntoken);
                break;
 
+       case PSI_T_FUNCTION:
+               ntoken = psi_token_copy(exp->token);
+               list = psi_plist_add(list, &ntoken);
+               ntoken = psi_token_init(PSI_T_LPAREN, "(", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
+               list = psi_plist_add(list, &ntoken);
+               for (i = 0; i < psi_plist_count(exp->data.call->args); ++i) {
+                       struct psi_num_exp *tmp_exp;
+
+                       if (i) {
+                               ntoken = psi_token_init(PSI_T_COMMA, ",", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
+                               list = psi_plist_add(list, &ntoken);
+                       }
+                       if (psi_plist_get(exp->data.call->args, i, &tmp_exp)) {
+                               struct psi_plist *tmp = psi_num_exp_tokens(tmp_exp, NULL);
+                               list = psi_plist_add_r(list, psi_plist_count(tmp), psi_plist_eles(tmp));
+                               psi_plist_top(list, &ntoken);
+                               free(tmp);
+                       }
+               }
+               ntoken = psi_token_init(PSI_T_RPAREN, ")", 1, ntoken->col+ntoken->text->len, ntoken->line, ntoken->file);
+               list = psi_plist_add(list, &ntoken);
+               break;
+
+       case PSI_T_DEFINED:
+               ntoken = psi_token_init(PSI_T_DEFINED, "defined", sizeof("defined")-1, exp->token->col, exp->token->line, exp->token->file);
+               list = psi_plist_add(list, &ntoken);
+               /* no break */
        default:
+               assert(exp->token);
                ntoken = psi_token_copy(exp->token);
                list = psi_plist_add(list, &ntoken);
                break;
@@ -256,91 +297,46 @@ struct psi_plist *psi_number_tokens(struct psi_number *exp,
        return list;
 }
 
-void psi_number_dump(int fd, struct psi_number *exp)
+void psi_number_dump(struct psi_dump *dump, struct psi_number *exp)
 {
        switch (exp->type) {
-       case PSI_T_INT8:
-               dprintf(fd, "%" PRId8, exp->data.ival.i8);
-               break;
-       case PSI_T_UINT8:
-               dprintf(fd, "%" PRIu8, exp->data.ival.u8);
-               break;
-       case PSI_T_INT16:
-               dprintf(fd, "%" PRId16, exp->data.ival.i16);
-               break;
-       case PSI_T_UINT16:
-               dprintf(fd, "%" PRIu16, exp->data.ival.u16);
-               break;
-       case PSI_T_INT32:
-               dprintf(fd, "%" PRId32, exp->data.ival.i32);
-               break;
-       case PSI_T_UINT32:
-               dprintf(fd, "%" PRIu32, exp->data.ival.u32);
-               break;
-       case PSI_T_INT64:
-               dprintf(fd, "%" PRId64, exp->data.ival.i64);
-               break;
-       case PSI_T_UINT64:
-               dprintf(fd, "%" PRIu64, exp->data.ival.u64);
-               break;
-       case PSI_T_FLOAT:
-               if (isinf(exp->data.ival.dval)) {
-                       dprintf(fd, "\\INF");
-               } else if (isnan(exp->data.ival.dval)) {
-                       dprintf(fd, "\\NAN");
-               } else {
-                       dprintf(fd, "%" PRIfval, exp->data.ival.dval);
-               }
-               break;
-       case PSI_T_DOUBLE:
-               if (isinf(exp->data.ival.dval)) {
-                       dprintf(fd, "\\INF");
-               } else if (isnan(exp->data.ival.dval)) {
-                       dprintf(fd, "\\NAN");
-               } else {
-                       dprintf(fd, "%" PRIdval, exp->data.ival.dval);
-               }
-               break;
-#if HAVE_LONG_DOUBLE
-       case PSI_T_LONG_DOUBLE:
-               if (isinfl(exp->data.ival.ldval)) {
-                       dprintf(fd, "\\INF");
-               } else if (isnanl(exp->data.ival.ldval)) {
-                       dprintf(fd, "\\NAN");
-               } else {
-                       dprintf(fd, "%" PRIldval, exp->data.ival.ldval);
-               }
-               break;
-#endif
+       case PSI_T_DEFINED:
+       CASE_IMPLVAL_NUM_DUMP(dump, exp->data.ival, true);
        case PSI_T_NULL:
-               dprintf(fd, "NULL");
+               PSI_DUMP(dump, "NULL");
                break;
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
-       case PSI_T_DEFINE:
        case PSI_T_QUOTED_CHAR:
-               dprintf(fd, "%s", exp->data.numb->val);
+       case PSI_T_CPP_HEADER:
+               PSI_DUMP(dump, "%s", exp->data.numb->val);
+               break;
+       case PSI_T_DEFINE:
+               PSI_DUMP(dump, "%s /* DEFINE */", exp->data.numb->val);
                break;
        case PSI_T_FUNCTION:
-               psi_cpp_macro_call_dump(fd, exp->data.call);
+               psi_cpp_macro_call_dump(dump, exp->data.call);
                break;
        case PSI_T_CONST:
-               dprintf(fd, "%s", exp->data.cnst->name->val);
+               PSI_DUMP(dump, "%s", exp->data.cnst->name->val);
                break;
        case PSI_T_ENUM:
-               dprintf(fd, "%s", exp->data.enm->name->val);
+               PSI_DUMP(dump, "%s /* ENUM */ ", exp->data.enm->name->val);
                break;
        case PSI_T_NAME:
-               psi_decl_var_dump(fd, exp->data.dvar);
+               psi_decl_var_dump(dump, exp->data.dvar);
                break;
        case PSI_T_SIZEOF:
-               dprintf(fd, "sizeof(");
-               psi_decl_type_dump(fd, exp->data.dtyp, 0);
-               dprintf(fd, ")");
+               PSI_DUMP(dump, "sizeof(");
+               psi_decl_type_dump(dump, exp->data.dtyp, 0);
+               PSI_DUMP(dump, ")");
                break;
        default:
                assert(0);
        }
+#if 0
+       PSI_DUMP(dump, "\t/* number.type=%d */ ", exp->type);
+#endif
 }
 
 static inline bool psi_number_validate_enum(struct psi_data *data,
@@ -507,7 +503,6 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_
                case PSI_NUMBER_FLT:
                        switch (exp->flags & 0x0ff00) {
                        case PSI_NUMBER_F:
-                       case PSI_NUMBER_DF:
                                tmp.fval = strtof(exp->data.numb->val, NULL);
                                zend_string_release(exp->data.numb);
                                exp->type = PSI_T_FLOAT;
@@ -524,6 +519,7 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_
 #endif
                        case PSI_NUMBER_DD:
                        default:
+                       case PSI_NUMBER_DF:
                                tmp.dval = strtod(exp->data.numb->val, NULL);
                                zend_string_release(exp->data.numb);
                                exp->type = PSI_T_DOUBLE;
@@ -536,7 +532,12 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_
                        break;
                }
        } else {
-               switch (is_numeric_str_function(exp->data.numb, (zend_long *) &tmp, (double *) &tmp)) {
+               int type = is_numeric_string(exp->data.numb->val, exp->data.numb->len, (zend_long *) &tmp, (double *)&tmp, 0);
+               char *stop = NULL;
+               long lval;
+               unsigned long ulval;
+
+               switch (type) {
                case IS_LONG:
                        zend_string_release(exp->data.numb);
                        exp->type = PSI_T_INT64;
@@ -548,6 +549,47 @@ static inline bool psi_number_validate_number(struct psi_data *data, struct psi_
                        exp->type = PSI_T_DOUBLE;
                        exp->data.ival.dval = tmp.dval;
                        return true;
+
+               default:
+
+                       errno = 0;
+
+                       stop = exp->data.numb->val + exp->data.numb->len;
+                       lval = strtol(exp->data.numb->val, &stop, 0);
+                       switch (lval) {
+                       case 0:
+                               assert(stop == exp->data.numb->val + exp->data.numb->len);
+                               /* no break */
+                       case LONG_MIN:
+                               assert(!errno);
+                               /* no break */
+                       case LONG_MAX:
+                               if (errno == ERANGE) {
+                                       errno = 0;
+
+                                       stop = exp->data.numb->val + exp->data.numb->len;
+                                       ulval = strtoul(exp->data.numb->val, &stop, 0);
+                                       switch (ulval) {
+                                       case 0:
+                                               assert(stop == exp->data.numb->val + exp->data.numb->len);
+                                       case ULONG_MAX:
+                                               assert(!errno);
+                                       default:
+                                               zend_string_release(exp->data.numb);
+                                               exp->type = PSI_T_UINT64;
+                                               exp->data.ival.u64 = ulval;
+                                               return true;
+                                       }
+                               }
+                               /* no break */
+                       default:
+                               zend_string_release(exp->data.numb);
+                               exp->type = PSI_T_INT64;
+                               exp->data.ival.i64 = lval;
+                               return true;
+                       }
+
+                       data->error(data, exp->token, PSI_WARNING, "Not a numeric string: '%s'", exp->data.numb->val);
                }
        }
        data->error(data, exp->token, PSI_WARNING, "Expected numeric entity (parser error?)");
@@ -560,6 +602,7 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
        size_t i = 0;
        struct psi_const *cnst;
        struct psi_decl_enum *enm;
+       struct psi_decl_extvar *evar;
 
        switch (exp->type) {
        case PSI_T_NULL:
@@ -574,18 +617,24 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
        case PSI_T_UINT32:
        case PSI_T_INT64:
        case PSI_T_UINT64:
+#if HAVE_INT128
+       case PSI_T_INT128:
+       case PSI_T_UINT128:
+#endif
        case PSI_T_FLOAT:
        case PSI_T_DOUBLE:
 #if HAVE_LONG_DOUBLE
        case PSI_T_LONG_DOUBLE:
 #endif
        case PSI_T_ENUM:
+       case PSI_T_DEFINED:
                return true;
 
        case PSI_T_NAME:
-               if (scope && scope->defs && zend_hash_exists(scope->defs, exp->data.dvar->name)) {
-                       return true;
-               }
+               //if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.dvar->name)) {
+               //      exp->type = PSI_T_DEFINE;
+               //      goto define;
+               //}
                if (scope && scope->current_enum && psi_number_validate_enum(data, exp, scope)) {
                        return true;
                }
@@ -599,22 +648,47 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
                if (exp->data.dvar->arg) {
                        return true;
                }
+               for (i = 0; psi_plist_get(data->vars, i, &evar); ++i) {
+                       if (zend_string_equals(exp->data.dvar->name, evar->arg->var->name)) {
+                               exp->data.dvar->arg = evar->arg;
+                               return true;
+                       }
+               }
                if (psi_decl_var_validate(data, exp->data.dvar, scope)) {
                        return true;
+               } else {
+                       data->error(data, exp->token, PSI_WARNING,
+                                       "Unknown variable '%s' in numeric expression",
+                                       exp->data.dvar->name->val);
+                       return false;
                }
-               data->error(data, exp->token, PSI_WARNING,
-                               "Unknown variable '%s' in numeric expression",
-                               exp->data.dvar->name->val);
-               return false;
+               break;
 
        case PSI_T_FUNCTION:
-               if (scope && scope->defs && zend_hash_exists(scope->defs, exp->data.numb)) {
+               if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.call->name)) {
+                       size_t i, argc;
+                       struct psi_cpp_macro_call *call = exp->data.call;
+
+                       for (i = 0, argc = psi_plist_count(call->args); i < argc; ++i) {
+                               struct psi_num_exp *arg;
+
+                               if (!psi_plist_get(call->args, i, &arg)) {
+                                       return false;
+                               }
+                               if (!psi_num_exp_validate(data, arg, scope)) {
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               if (psi_builtin_exists(exp->data.call->name)) {
+                       exp->data.call->builtin = psi_builtin_get(exp->data.call->name);
                        return true;
                }
                return false;
 
        case PSI_T_DEFINE:
-               if (scope && scope->defs && zend_hash_exists(scope->defs, exp->data.numb)) {
+               if (scope && scope->cpp && zend_hash_exists(&scope->cpp->defs, exp->data.numb)) {
                        if (!scope->macro || !zend_string_equals(scope->macro->token->text, exp->data.numb)) {
                                return true;
                        }
@@ -627,6 +701,7 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
                                return true;
                        }
                }
+               /* undefined */
                return false;
 
        case PSI_T_SIZEOF:
@@ -697,6 +772,9 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
        case PSI_T_QUOTED_CHAR:
                return psi_number_validate_char(data, exp);
 
+       case PSI_T_CPP_HEADER:
+               return true;
+
        default:
                assert(0);
        }
@@ -707,7 +785,9 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
 static inline token_t psi_number_eval_constant(struct psi_number *exp,
                impl_val *res, struct psi_call_frame *frame)
 {
-       switch (exp->data.cnst->type->type) {
+       token_t typ = exp->data.cnst->type ? exp->data.cnst->type->type : PSI_T_MIXED;
+
+       switch (typ) {
        case PSI_T_INT:
                res->i64 = zend_get_constant(exp->data.cnst->name)->value.lval;
                if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
@@ -735,10 +815,13 @@ static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
        var = exp->data.dvar;
        real = psi_decl_type_get_real(var->arg->type);
        size = psi_decl_arg_get_size(var->arg);
-       sym = psi_call_frame_fetch_symbol(frame, var);
-       ref = deref_impl_val(sym->ptr, var);
 
-       memcpy(res, ref, size);
+       if (frame) {
+               sym = psi_call_frame_fetch_symbol(frame, var);
+               ref = deref_impl_val(sym->ptr, var);
+
+               memcpy(res, ref, size);
+       }
 
        if (var->arg->var->pointer_level > var->pointer_level) {
                switch (SIZEOF_VOID_P) {
@@ -754,28 +837,40 @@ static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
 }
 
 static inline token_t psi_number_eval_define(struct psi_number *exp,
-               impl_val *res, HashTable *defs, struct psi_num_exp *rec_guard)
+               impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
 {
-       if (defs) {
+       if (cpp) {
                struct psi_cpp_macro_decl *macro;
 
-               macro = zend_hash_find_ptr(defs, exp->data.numb);
+               macro = zend_hash_find_ptr(&cpp->defs, exp->data.numb);
                if (macro && macro->exp && macro->exp != rec_guard) {
-                       return psi_num_exp_exec(macro->exp, res, NULL, defs);
+                       return psi_num_exp_exec(macro->exp, res, NULL, cpp);
                }
        }
+
+       res->u8 = 0;
+       return PSI_T_UINT8;
+}
+
+static inline token_t psi_number_eval_function(struct psi_number *exp,
+               impl_val *res, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
+{
+       if (cpp) {
+               PSI_DEBUG_PRINT(cpp->parser, "psi_number_eval(PSI_T_FUNCTION): %s\n", exp->token->text->val);
+       }
        res->u8 = 0;
        return PSI_T_UINT8;
 }
 
 token_t psi_number_eval(struct psi_number *exp, impl_val *res,
-               struct psi_call_frame *frame, HashTable *defs, struct psi_num_exp *rec_guard)
+               struct psi_call_frame *frame, struct psi_cpp *cpp, struct psi_num_exp *rec_guard)
 {
        switch (exp->type) {
        case PSI_T_INT8:
                *res = exp->data.ival;
                if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi8, res->i8);
                return PSI_T_INT8;
+       case PSI_T_DEFINED:
        case PSI_T_UINT8:
                *res = exp->data.ival;
                if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu8, res->u8);
@@ -804,7 +899,16 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res,
                *res = exp->data.ival;
                if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu64, res->u64);
                return PSI_T_UINT64;
-
+#if HAVE_INT128
+       case PSI_T_INT128:
+               *res = exp->data.ival;
+               //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi128, res->i128);
+               return PSI_T_INT128;
+       case PSI_T_UINT128:
+               *res = exp->data.ival;
+               //if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIu128, res->u128);
+               return PSI_T_UINT128;
+#endif
        case PSI_T_FLOAT:
                *res = exp->data.ival;
                if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIfval, res->fval);
@@ -838,9 +942,12 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res,
                return psi_number_eval_decl_var(exp, res, frame);
 
        case PSI_T_DEFINE:
-               return psi_number_eval_define(exp, res, defs, rec_guard);
+               return psi_number_eval_define(exp, res, cpp, rec_guard);
 
        case PSI_T_FUNCTION:
+               return psi_number_eval_function(exp, res, cpp, rec_guard);
+
+       case PSI_T_CPP_HEADER:
                res->u8 = 0;
                return PSI_T_UINT8;