impl_def_val: handle INF/NAN
authorMichael Wallner <mike@php.net>
Thu, 26 Jul 2018 07:24:25 +0000 (09:24 +0200)
committerMichael Wallner <mike@php.net>
Thu, 26 Jul 2018 07:24:25 +0000 (09:24 +0200)
src/types/impl_def_val.c

index c5bf7444a0ebb0e8e592f4989880b328dc32d3d8..fe11b269f6e3a02d6883f07fb7db3e5c5ce9f590 100644 (file)
@@ -27,6 +27,7 @@
 #include "data.h"
 
 #include <assert.h>
+#include <math.h>
 
 struct psi_impl_def_val *psi_impl_def_val_init(token_t t, void *data)
 {
@@ -85,77 +86,81 @@ void psi_impl_def_val_free(struct psi_impl_def_val **def_ptr)
 }
 
 bool psi_impl_def_val_validate(struct psi_data *data,
-               struct psi_impl_def_val *def, struct psi_impl_type *cmp,
+               struct psi_impl_def_val *val, struct psi_impl_type *type,
                struct psi_validate_scope *scope)
 {
-       if (def->type == PSI_T_NULL) {
+       if (val->type == PSI_T_NULL) {
                return true;
+       } else if (val->type == PSI_T_NUMBER) {
+               if (!psi_num_exp_validate(data, val->data.num, scope)) {
+                       return false;
+               }
        }
 
-       switch (cmp->type) {
+       switch (type->type) {
        case PSI_T_BOOL:
-               def->ival.zend.bval = def->type == PSI_T_TRUE ? 1 : 0;
+               val->ival.zend.bval = val->type == PSI_T_TRUE ? 1 : 0;
                break;
 
        /* macros */
        case PSI_T_NUMBER:
-               if (def->type == PSI_T_NUMBER) {
-                       token_t typ = psi_num_exp_exec(def->data.num, &def->ival, NULL, scope->defs);
+               if (val->type == PSI_T_NUMBER) {
+                       token_t typ = psi_num_exp_exec(val->data.num, &val->ival, NULL, scope->defs);
 
                        switch (typ) {
                        case PSI_T_FLOAT:
-                               def->ival.dval = def->ival.fval;
+                               val->ival.dval = val->ival.fval;
                                /* no break */
                        case PSI_T_DOUBLE:
-                               def->type = PSI_T_FLOAT;
-                               cmp->type = PSI_T_FLOAT;
-                               strcpy(cmp->name, "float");
+                               val->type = PSI_T_FLOAT;
+                               type->type = PSI_T_FLOAT;
+                               strcpy(type->name, "float");
                                break;
                        default:
-                               def->type = PSI_T_INT;
-                               cmp->type = PSI_T_INT;
-                               strcpy(cmp->name, "int");
+                               val->type = PSI_T_INT;
+                               type->type = PSI_T_INT;
+                               strcpy(type->name, "int");
                                break;
                        }
-                       psi_num_exp_free(&def->data.num);
+                       psi_num_exp_free(&val->data.num);
                        return true;
                }
                break;
 
        case PSI_T_INT:
-               if (def->type == PSI_T_NUMBER) {
-                       def->type = PSI_T_INT;
-                       def->ival.zend.lval = psi_num_exp_get_long(def->data.num, NULL, scope->defs);
-                       psi_num_exp_free(&def->data.num);
+               if (val->type == PSI_T_NUMBER) {
+                       val->type = PSI_T_INT;
+                       val->ival.zend.lval = psi_num_exp_get_long(val->data.num, NULL, scope->defs);
+                       psi_num_exp_free(&val->data.num);
                }
-               if (def->type == PSI_T_INT) {
+               if (val->type == PSI_T_INT) {
                        return true;
                }
                break;
 
        case PSI_T_FLOAT:
        case PSI_T_DOUBLE:
-               if (def->type == PSI_T_NUMBER) {
-                       def->type = PSI_T_DOUBLE;
-                       def->ival.dval = psi_num_exp_get_double(def->data.num, NULL, scope->defs);
-                       psi_num_exp_free(&def->data.num);
+               if (val->type == PSI_T_NUMBER) {
+                       val->type = PSI_T_DOUBLE;
+                       val->ival.dval = psi_num_exp_get_double(val->data.num, NULL, scope->defs);
+                       psi_num_exp_free(&val->data.num);
                }
-               if (def->type == PSI_T_DOUBLE) {
+               if (val->type == PSI_T_DOUBLE) {
                        return true;
                }
                break;
 
        case PSI_T_STRING:
-               if (def->type == PSI_T_STRING) {
+               if (val->type == PSI_T_STRING) {
                        return true;
                }
                break;
 
        default:
-               data->error(data, def->token, PSI_WARNING,
+               data->error(data, val->token, PSI_WARNING,
                                "Invalid default value type '%s', "
                                "expected one of bool, int, float, string.",
-                               cmp->name);
+                               type->name);
        }
 
        return false;
@@ -180,7 +185,13 @@ void psi_impl_def_val_dump(int fd, struct psi_impl_def_val *val) {
                break;
        case PSI_T_FLOAT:
        case PSI_T_DOUBLE:
-               dprintf(fd, "%" PRIdval, val->ival.dval);
+               if (isinf(val->ival.dval)) {
+                       dprintf(fd, "\\INF");
+               } else if (isnan(val->ival.dval)) {
+                       dprintf(fd, "\\NAN");
+               } else {
+                       dprintf(fd, "%" PRIdval, val->ival.dval);
+               }
                break;
        case PSI_T_STRING:
                dprintf(fd, "\"%s\"", val->ival.zend.str->val);