Merge branch 'slimconfigure'
[m6w6/ext-psi] / src / types / impl_def_val.c
index 0d176f309eea9845d6ff2222243ef761c6d4f98a..c6778f9bf917716f3e6e0e5af139d69cb004eae1 100644 (file)
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#else
-# include "php_config.h"
-#endif
+#include "php_psi_stdinc.h"
+#include "data.h"
 
-#include <stdlib.h>
-#include <stdio.h>
+#include <assert.h>
 
-#include "impl_def_val.h"
+struct psi_impl_def_val *psi_impl_def_val_init(token_t t, void *data)
+{
+       struct psi_impl_def_val *def = calloc(1, sizeof(*def));
 
-void free_impl_def_val(impl_def_val *def) {
-       free(def->text);
-       free(def);
-}
+       switch ((def->type = t)) {
+       case PSI_T_TRUE:
+       case PSI_T_FALSE:
+       case PSI_T_NULL:
+               break;
+       case PSI_T_QUOTED_STRING:
+               /* immediate upgrade */
+               def->type = PSI_T_STRING;
+               /* no break */
+       case PSI_T_STRING:
+               if (data) {
+                       def->ival.zend.str = zend_string_init(data, strlen(data), 1);
+               }
+               break;
+
+       case PSI_T_NUMBER:
+               def->data.num = data;
+               break;
+
+       default:
+               assert(0);
+       }
 
-impl_def_val *init_impl_def_val(token_t t, const char *text) {
-       impl_def_val *def = calloc(1, sizeof(*def));
-       def->type = t;
-       def->text = strdup(text);
        return def;
 }
 
-void dump_impl_def_val(int fd, impl_def_val *val) {
-       if (val->type == PSI_T_QUOTED_STRING) {
-               dprintf(fd, "\"%s\"", val->text);
-       } else {
-               dprintf(fd, "%s", val->text);
+void psi_impl_def_val_free(struct psi_impl_def_val **def_ptr)
+{
+       if (*def_ptr) {
+               struct psi_impl_def_val *def = *def_ptr;
+
+               *def_ptr = NULL;
+               if (def->token) {
+                       free(def->token);
+               }
+               switch (def->type) {
+               case PSI_T_NUMBER:
+                       psi_num_exp_free(&def->data.num);
+                       break;
+
+               case PSI_T_STRING:
+                       if (def->ival.zend.str) {
+                               zend_string_release(def->ival.zend.str);
+                       }
+                       break;
+               default:
+                       break;
+               }
+               free(def);
+       }
+}
+
+bool psi_impl_def_val_validate(struct psi_data *data,
+               struct psi_impl_def_val *def, struct psi_impl_type *cmp,
+               struct psi_validate_scope *scope)
+{
+       if (def->type == PSI_T_NULL) {
+               return true;
+       }
+
+       switch (cmp->type) {
+       case PSI_T_BOOL:
+               def->ival.zend.bval = def->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);
+
+                       switch (typ) {
+                       case PSI_T_FLOAT:
+                               def->ival.dval = def->ival.fval;
+                               /* no break */
+                       case PSI_T_DOUBLE:
+                               def->type = PSI_T_FLOAT;
+                               cmp->type = PSI_T_FLOAT;
+                               strcpy(cmp->name, "float");
+                               break;
+                       default:
+                               def->type = PSI_T_INT;
+                               cmp->type = PSI_T_INT;
+                               strcpy(cmp->name, "int");
+                               break;
+                       }
+                       psi_num_exp_free(&def->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 (def->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 (def->type == PSI_T_DOUBLE) {
+                       return true;
+               }
+               break;
+
+       case PSI_T_STRING:
+               if (def->type == PSI_T_STRING) {
+                       return true;
+               }
+               break;
+
+       default:
+               data->error(data, def->token, PSI_WARNING,
+                               "Invalid default value type '%s', "
+                               "expected one of bool, int, float, string.",
+                               cmp->name);
        }
 
+       return false;
+}
+
+void psi_impl_def_val_dump(int fd, struct psi_impl_def_val *val) {
+       switch (val->type) {
+       case PSI_T_TRUE:
+               dprintf(fd, "true");
+               break;
+       case PSI_T_FALSE:
+               dprintf(fd, "false");
+               break;
+       case PSI_T_BOOL:
+               dprintf(fd, "%s", val->ival.zend.bval ? "true" : "false");
+               break;
+       case PSI_T_INT:
+               dprintf(fd, "%ld", val->ival.zend.lval);
+               break;
+       case PSI_T_FLOAT:
+       case PSI_T_DOUBLE:
+               dprintf(fd, "%" PRIdval, val->ival.dval);
+               break;
+       case PSI_T_STRING:
+               dprintf(fd, "\"%s\"", val->ival.zend.str->val);
+               break;
+       default:
+               assert(0);
+       }
 }