flush
authorMichael Wallner <mike@php.net>
Fri, 11 Dec 2015 10:35:14 +0000 (11:35 +0100)
committerMichael Wallner <mike@php.net>
Fri, 11 Dec 2015 10:35:14 +0000 (11:35 +0100)
m4/psi.m4
m4/psi_struct.m4
m4/psi_type.m4
m4/time.m4
php_psi.h
src/context.c
src/module.c
src/parser.h
src/parser.re
src/parser_proc.h
src/parser_proc.y

index ea8d7fb..e9955f0 100644 (file)
--- a/m4/psi.m4
+++ b/m4/psi.m4
@@ -32,6 +32,13 @@ AC_DEFUN([PSI_PKG_CONFIG], [
        export PKG_CONFIG_PATH="$PHP_PSI_LIBFFI/lib/pkgconfig:$PHP_PSI_LIBJIT/lib/pkgconfig:$PKG_CONFIG_PATH"
 ])
 
+AC_DEFUN(PSI_CHECK_SIZEOF, [
+       AC_CHECK_SIZEOF($1, [], $2)
+       if test "$AS_TR_SH([ac_cv_sizeof_]$1)"; then
+               add_int_const "AS_TR_CPP([SIZEOF_]$1)" "$AS_TR_SH([ac_cv_sizeof_]$1)"
+       fi
+])
+
 AC_DEFUN(PSI_CHECK_OFFSETOF, [
        _AC_CACHE_CHECK_INT(
                [offset of $2 in $1],
index 3255c94..430baf7 100644 (file)
@@ -1,7 +1,7 @@
 AC_DEFUN(PSI_STRUCT_MEMBER, [
        m4_define([member_name], PSI_VAR_NAME($2))
        m4_define([member_type], PSI_VAR_TYPE($2))
-       AC_CHECK_SIZEOF(AS_TR_SH($1)[_]member_name, [], PSI_INCLUDES
+       PSI_CHECK_SIZEOF(AS_TR_SH($1)[_]member_name, PSI_INCLUDES
                [#define ]AS_TR_SH($1)[_]member_name (($1 *)0)->member_name
        )
        if test -n "$AS_TR_SH([ac_cv_sizeof_$1][_]member_name)" \
@@ -13,7 +13,7 @@ AC_DEFUN(PSI_STRUCT_MEMBER, [
 ])
 
 AC_DEFUN(PSI_STRUCT, [
-       AC_CHECK_SIZEOF($1, [], PSI_INCLUDES)
+       PSI_CHECK_SIZEOF($1, PSI_INCLUDES)
        psi_struct_name=m4_bregexp([$1], [^\(struct \)?\(\w+\)], [\2])
        psi_struct_members="{PSI_T_STRUCT, \"struct\", \"$psi_struct_name\", 0, $AS_TR_SH([ac_cv_sizeof_]$1), 0, 0}"
        ifelse([$2],,,[m4_map_args_sep([PSI_STRUCT_MEMBER($1, m4_normalize(], [))], [], $2)])
index d1e0fbf..3b0a22e 100644 (file)
@@ -24,7 +24,7 @@ psi_type_pair() {
 dnl PSI_TYPE(type name, basic type, includes)
 AC_DEFUN(PSI_TYPE, [
        ifdef(AS_TR_CPP(AC_TYPE_$1), AS_TR_CPP(AC_TYPE_$1))
-       AC_CHECK_SIZEOF($1, [], PSI_INCLUDES)
+       PSI_CHECK_SIZEOF($1, PSI_INCLUDES)
        psi_basic_type=$2
        case $psi_basic_type in
        int)
@@ -95,28 +95,28 @@ AC_DEFUN(PSI_CHECK_STD_TYPES, [
        AC_CHECK_HEADERS(stdint.h)
 
        AC_TYPE_INT8_T
-       AC_CHECK_SIZEOF(int8_t)
+       PSI_CHECK_SIZEOF(int8_t)
        AC_CHECK_ALIGNOF(int8_t)
        AC_TYPE_UINT8_T
-       AC_CHECK_SIZEOF(uint8_t)
+       PSI_CHECK_SIZEOF(uint8_t)
        AC_CHECK_ALIGNOF(uint8_t)
        AC_TYPE_INT16_T
-       AC_CHECK_SIZEOF(int16_t)
+       PSI_CHECK_SIZEOF(int16_t)
        AC_CHECK_ALIGNOF(int16_t)
        AC_TYPE_UINT16_T
-       AC_CHECK_SIZEOF(uint16_t)
+       PSI_CHECK_SIZEOF(uint16_t)
        AC_CHECK_ALIGNOF(uint16_t)
        AC_TYPE_INT32_T
-       AC_CHECK_SIZEOF(int32_t)
+       PSI_CHECK_SIZEOF(int32_t)
        AC_CHECK_ALIGNOF(int32_t)
        AC_TYPE_UINT32_T
-       AC_CHECK_SIZEOF(uint32_t)
+       PSI_CHECK_SIZEOF(uint32_t)
        AC_CHECK_ALIGNOF(uint32_t)
        AC_TYPE_INT64_T
-       AC_CHECK_SIZEOF(int64_t)
+       PSI_CHECK_SIZEOF(int64_t)
        AC_CHECK_ALIGNOF(int64_t)
        AC_TYPE_UINT64_T
-       AC_CHECK_SIZEOF(uint64_t)
+       PSI_CHECK_SIZEOF(uint64_t)
        AC_CHECK_ALIGNOF(uint64_t)
 
        PSI_TYPE(float)
index 3d50e69..a4cb58e 100644 (file)
@@ -54,6 +54,6 @@ AC_DEFUN(PSI_CHECK_TIME, [
        PSI_DECL(int timer_delete, [(timer_t t)])
        PSI_DECL(int timer_getoverrun, [(timer_t t)])
        PSI_DECL(int timer_gettime, [(timer_t t, struct itimerspec *ts)])
-       PSI_DECL(int timer_settime, [(timer_t t, struct itimerspec *value, struct itimerspec *ovalue)])
+       PSI_DECL(int timer_settime, [(timer_t t, int flags, struct itimerspec *value, struct itimerspec *ovalue)])
        PSI_DECL(void tzset, [()])
 ])
index 84b73c2..54d78b0 100644 (file)
--- a/php_psi.h
+++ b/php_psi.h
@@ -29,6 +29,19 @@ static inline int psi_check_env(const char *var) {
        return (set && *set && '0' != *set);
 }
 
+typedef struct psi_object {
+       void *data;
+       size_t size;
+       zend_object std;
+} psi_object;
+
+static inline psi_object *PSI_OBJ(zval *zv, zend_object *zo) {
+       if (zv) {
+               zo = Z_OBJ_P(zv);
+       }
+       return (void *) (((char *) zo) - zo->handlers->offset);
+}
+
 size_t psi_t_alignment(token_t t);
 size_t psi_t_size(token_t t);
 size_t psi_t_align(token_t t, size_t s);
@@ -37,11 +50,13 @@ int psi_internal_type(impl_type *type);
 zend_internal_arg_info *psi_internal_arginfo(impl *impl);
 size_t psi_num_min_args(impl *impl);
 
+void psi_to_void(zval *return_value, set_value *set, impl_val *ret_val);
 void psi_to_bool(zval *return_value, set_value *set, impl_val *ret_val);
 void psi_to_int(zval *return_value, set_value *set, impl_val *ret_val);
 void psi_to_double(zval *return_value, set_value *set, impl_val *ret_val);
 void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val);
 void psi_to_array(zval *return_value, set_value *set, impl_val *ret_val);
+void psi_to_object(zval *return_value, set_value *set, impl_val *ret_val);
 
 void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl);
 
index cbcfbc6..134acdd 100644 (file)
@@ -439,6 +439,12 @@ static inline int validate_set_value(PSI_Data *data, set_value *set, decl_arg *r
        case PSI_T_TO_ARRAY:
                set->func->handler = psi_to_array;
                break;
+       case PSI_T_TO_OBJECT:
+               set->func->handler = psi_to_object;
+               break;
+       case PSI_T_VOID:
+               set->func->handler = psi_to_void;
+               break;
        EMPTY_SWITCH_DEFAULT_CASE();
        }
 
@@ -1029,6 +1035,7 @@ zend_function_entry *PSI_ContextCompile(PSI_Context *C)
 
 void PSI_ContextCall(PSI_Context *C, impl_val *ret_val, decl *decl)
 {
+       errno = 0;
        C->ops->call(C, ret_val, decl);
 }
 
index 469fb4d..da623b2 100644 (file)
@@ -6,6 +6,7 @@
 #include "php.h"
 #include "php_ini.h"
 #include "ext/standard/info.h"
+#include "zend_exceptions.h"
 
 #include "php_psi.h"
 #include "parser.h"
@@ -28,6 +29,9 @@ PHP_INI_BEGIN()
        STD_PHP_INI_ENTRY("psi.directory", "psi.d", PHP_INI_SYSTEM, OnUpdateString, directory, zend_psi_globals, psi_globals)
 PHP_INI_END();
 
+static zend_object_handlers psi_object_handlers;
+static zend_class_entry *psi_class_entry;
+
 void psi_error(int type, const char *msg, ...)
 {
        char buf[0x1000];
@@ -151,6 +155,11 @@ size_t psi_num_min_args(impl *impl)
        return n;
 }
 
+void psi_to_void(zval *return_value, set_value *set, impl_val *ret_val)
+{
+       RETVAL_NULL();
+}
+
 void psi_to_bool(zval *return_value, set_value *set, impl_val *ret_val)
 {
        psi_to_int(return_value, set, ret_val);
@@ -263,6 +272,7 @@ void psi_to_string(zval *return_value, set_value *set, impl_val *ret_val)
        token_t t = real_decl_type(var->arg->type)->type;
 
        switch (t) {
+       case PSI_T_VOID:
        case PSI_T_INT8:
        case PSI_T_UINT8:
                if (!var->arg->var->pointer_level) {
@@ -450,15 +460,36 @@ void psi_to_array(zval *return_value, set_value *set, impl_val *r_val)
        } else {
                ZEND_ASSERT(0);
        }
+}
 
+void psi_to_object(zval *return_value, set_value *set, impl_val *r_val)
+{
+       decl_var *var = set->vars->vars[0];
+       impl_val *ret_val = deref_impl_val(r_val, var);
+       psi_object *obj;
+
+       if (ret_val->ptr) {
+               object_init_ex(return_value, psi_class_entry);
+               obj = PSI_OBJ(return_value, NULL);
+               obj->data = ret_val->ptr;
+       } else {
+               RETVAL_NULL();
+       }
 }
 
 static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl)
 {
        impl_arg *iarg;
+       zend_error_handling zeh;
+
+       zend_replace_error_handling(EH_THROW, zend_exception_get_default(), &zeh);
 
        if (!impl->func->args->count) {
-               return zend_parse_parameters_none();
+               ZEND_RESULT_CODE rv;
+
+               rv = zend_parse_parameters_none();
+               zend_restore_error_handling(&zeh);
+               return rv;
        }
 
        ZEND_PARSE_PARAMETERS_START(psi_num_min_args(impl), impl->func->args->count)
@@ -497,7 +528,9 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i
                        }
                } else if (PSI_T_ARRAY == iarg->type->type) {
                        /* handled as _zv in let or set */
-                       Z_PARAM_PROLOGUE(0);
+                       Z_PARAM_ARRAY_EX(iarg->_zv, 1, 0);
+               } else if (PSI_T_OBJECT == iarg->type->type) {
+                       Z_PARAM_OBJECT_EX(iarg->_zv, 1, 0);
                } else {
                        error_code = ZPP_ERROR_FAILURE;
                        break;
@@ -506,8 +539,12 @@ static inline ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, i
                if (_i < _max_num_args) {
                        goto nextarg;
                }
-       ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
+       ZEND_PARSE_PARAMETERS_END_EX(
+               zend_restore_error_handling(&zeh);
+               return FAILURE
+       );
 
+       zend_restore_error_handling(&zeh);
        return SUCCESS;
 }
 
@@ -565,6 +602,7 @@ static inline void *psi_do_let(decl_arg *darg)
                                arg_val->lval = zval_get_long(iarg->_zv);
                        }
                        break;
+               case PSI_T_PATHVAL:
                case PSI_T_STRVAL:
                        if (iarg->type->type == PSI_T_STRING) {
                                arg_val->ptr = estrdup(iarg->val.zend.str->val);
@@ -576,6 +614,12 @@ static inline void *psi_do_let(decl_arg *darg)
                                darg->let->mem = arg_val->ptr;
                                zend_string_release(zs);
                        }
+                       if (PSI_T_PATHVAL == darg->let->val->func->type) {
+                               if (SUCCESS != php_check_open_basedir(arg_val->ptr)) {
+                                       efree(arg_val->ptr);
+                                       return NULL;
+                               }
+                       }
                        break;
                case PSI_T_STRLEN:
                        if (iarg->type->type == PSI_T_STRING) {
@@ -599,6 +643,18 @@ static inline void *psi_do_let(decl_arg *darg)
                                }
                        }
                        break;
+               case PSI_T_OBJVAL:
+                       if (iarg->type->type == PSI_T_OBJECT) {
+                               psi_object *obj;
+
+                               if (!instanceof_function(Z_OBJCE_P(iarg->_zv), psi_class_entry)) {
+                                       return NULL;
+                               }
+
+                               obj = PSI_OBJ(iarg->_zv, NULL);
+                               arg_val->ptr = obj->data;
+                       }
+                       break;
                EMPTY_SWITCH_DEFAULT_CASE();
                }
        }
@@ -691,7 +747,9 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl)
                for (i = 0; i < impl->decl->args->count; ++i) {
                        decl_arg *darg = impl->decl->args->args[i];
 
-                       impl->decl->call.args[i] = psi_do_let(darg);
+                       if (!(impl->decl->call.args[i] = psi_do_let(darg))) {
+                               goto cleanup;
+                       }
                }
        }
 
@@ -713,16 +771,52 @@ void psi_call(zend_execute_data *execute_data, zval *return_value, impl *impl)
 
                psi_do_free(fre);
        }
+       psi_do_clean(impl);
+       return;
 
+cleanup:
+       memset(&ret_val, 0, sizeof(ret_val));
+       psi_do_return(return_value, impl->stmts->ret.list[0], &ret_val);
        psi_do_clean(impl);
 }
 
+static void psi_object_free(zend_object *o)
+{
+       psi_object *obj = PSI_OBJ(NULL, o);
+
+       if (obj->data) {
+               // free(obj->data);
+               obj->data = NULL;
+       }
+       zend_object_std_dtor(o);
+}
+
+static zend_object *psi_object_init(zend_class_entry *ce)
+{
+       psi_object *o = ecalloc(1, sizeof(*o) + zend_object_properties_size(ce));
+
+       zend_object_std_init(&o->std, ce);
+       object_properties_init(&o->std, ce);
+       o->std.handlers = &psi_object_handlers;
+       return &o->std;
+}
+
 PHP_MINIT_FUNCTION(psi)
 {
        PSI_ContextOps *ops = NULL;
+       zend_class_entry ce = {0};
 
        REGISTER_INI_ENTRIES();
 
+       INIT_NS_CLASS_ENTRY(ce, "psi", "object", NULL);
+       psi_class_entry = zend_register_internal_class_ex(&ce, NULL);
+       psi_class_entry->create_object = psi_object_init;
+
+       memcpy(&psi_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+       psi_object_handlers.offset = XtOffsetOf(psi_object, std);
+       psi_object_handlers.free_obj = psi_object_free;
+       psi_object_handlers.clone_obj = NULL;
+
 #ifdef HAVE_LIBJIT
        if (!strcasecmp(PSI_G(engine), "jit")) {
                ops = PSI_Libjit();
index 5ec0b95..faa95e4 100644 (file)
@@ -12,6 +12,7 @@
 
 #define BSIZE 256
 
+#define PSI_T_POINTER PSI_T_ASTERISK
 typedef int token_t;
 
 /* in php_psi.h */
@@ -377,6 +378,7 @@ static inline impl_val *enref_impl_val(void *ptr, decl_var *var) {
        val_ptr->ptr = ptr;
        return val;
 }
+
 typedef struct impl_type {
        char *name;
        token_t type;
@@ -429,6 +431,68 @@ static inline void free_impl_def_val(impl_def_val *def) {
        free(def);
 }
 
+typedef struct const_type {
+       token_t type;
+       char *name;
+} const_type;
+
+static inline const_type *init_const_type(token_t type, const char *name) {
+       const_type *ct = calloc(1, sizeof(*ct));
+       ct->type = type;
+       ct->name = strdup(name);
+       return ct;
+}
+
+static inline void free_const_type(const_type *type) {
+       free(type->name);
+       free(type);
+}
+
+typedef struct constant {
+       const_type *type;
+       char *name;
+       impl_def_val *val;
+} constant;
+
+static inline constant *init_constant(const_type *type, const char *name, impl_def_val *val) {
+       constant *c = calloc(1, sizeof(*c));
+       c->type = type;
+       c->name = strdup(name);
+       c->val = val;
+       return c;
+}
+
+static inline void free_constant(constant *constant) {
+       free_const_type(constant->type);
+       free(constant->name);
+       free_impl_def_val(constant->val);
+       free(constant);
+}
+
+typedef struct constants {
+       size_t count;
+       constant **list;
+} constants;
+
+static inline constants *add_constant(constants *constants, constant *constant) {
+       if (!constants) {
+               constants = calloc(1, sizeof(*constants));
+       }
+       constants->list = realloc(constants->list, ++constants->count * sizeof(*constants->list));
+       constants->list[constants->count-1] = constant;
+       return constants;
+}
+
+static inline void free_constants(constants *c) {
+       size_t i;
+
+       for (i = 0; i < c->count; ++i) {
+               free_constant(c->list[i]);
+       }
+       free(c->list);
+       free(c);
+}
+
 typedef struct impl_arg {
        impl_type *type;
        impl_var *var;
@@ -508,20 +572,68 @@ static inline void free_impl_func(impl_func *f) {
        free(f);
 }
 
+typedef struct num_exp {
+       token_t t;
+       union {
+               char *numb;
+               char *cnst;
+               decl_var *dvar;
+       } u;
+       token_t operator;
+       struct num_exp *operand;
+} num_exp;
+
+static inline num_exp *init_num_exp(token_t t, void *num) {
+       num_exp *exp = calloc(1, sizeof(*exp));
+       switch (exp->t = t) {
+       case PSI_T_NUMBER:
+               exp->u.numb = strdup(num);
+               break;
+       case PSI_T_NSNAME:
+               exp->u.cnst = strdup(num);
+               break;
+       case PSI_T_NAME:
+               exp->u.dvar = num;
+               break;
+       EMPTY_SWITCH_DEFAULT_CASE();
+       }
+       return exp;
+}
+
+static inline void free_num_exp(num_exp *exp) {
+       switch (exp->t) {
+       case PSI_T_NUMBER:
+               free(exp->u.numb);
+               break;
+       case PSI_T_NSNAME:
+               free(exp->u.cnst);
+               break;
+       case PSI_T_NAME:
+               free_decl_var(exp->u.dvar);
+               break;
+       EMPTY_SWITCH_DEFAULT_CASE();
+       }
+       if (exp->operand) {
+               free_num_exp(exp->operand);
+       }
+       free(exp);
+}
+
 typedef struct let_calloc {
-       size_t n;
-       decl_type *type;
+       num_exp *nmemb;
+       num_exp *size;
 } let_calloc;
 
-static inline let_calloc *init_let_calloc(long n, decl_type *type) {
+static inline let_calloc *init_let_calloc(num_exp *nmemb, num_exp *size) {
        let_calloc *alloc = calloc(1, sizeof(*alloc));
-       alloc->n = n;
-       alloc->type = type;
+       alloc->nmemb = nmemb;
+       alloc->size = size;
        return alloc;
 }
 
 static inline void free_let_calloc(let_calloc *alloc) {
-       free_decl_type(alloc->type);
+       free_num_exp(alloc->nmemb);
+       free_num_exp(alloc->size);
        free(alloc);
 }
 
@@ -902,67 +1014,6 @@ static void free_impls(impls *impls) {
        free(impls);
 }
 
-typedef struct const_type {
-       token_t type;
-       char *name;
-} const_type;
-
-static inline const_type *init_const_type(token_t type, const char *name) {
-       const_type *ct = calloc(1, sizeof(*ct));
-       ct->type = type;
-       ct->name = strdup(name);
-       return ct;
-}
-
-static inline void free_const_type(const_type *type) {
-       free(type->name);
-       free(type);
-}
-
-typedef struct constant {
-       const_type *type;
-       char *name;
-       impl_def_val *val;
-} constant;
-
-static inline constant *init_constant(const_type *type, const char *name, impl_def_val *val) {
-       constant *c = calloc(1, sizeof(*c));
-       c->type = type;
-       c->name = strdup(name);
-       c->val = val;
-       return c;
-}
-
-static inline void free_constant(constant *constant) {
-       free_const_type(constant->type);
-       free(constant->name);
-       free_impl_def_val(constant->val);
-       free(constant);
-}
-
-typedef struct constants {
-       size_t count;
-       constant **list;
-} constants;
-
-static inline constants *add_constant(constants *constants, constant *constant) {
-       if (!constants) {
-               constants = calloc(1, sizeof(*constants));
-       }
-       constants->list = realloc(constants->list, ++constants->count * sizeof(*constants->list));
-       constants->list[constants->count-1] = constant;
-       return constants;
-}
-
-static inline void free_constants(constants *c) {
-       size_t i;
-
-       for (i = 0; i < c->count; ++i) {
-               free_constant(c->list[i]);
-       }
-       free(c->list);
-       free(c);
-}
 
 #define PSI_ERROR 16
 #define PSI_WARNING 32
index d4a25d2..d5a0f8e 100644 (file)
@@ -179,8 +179,11 @@ token_t PSI_ParserScan(PSI_Parser *P)
                "]" {RETURN(PSI_T_RBRACKET);}
                "=" {RETURN(PSI_T_EQUALS);}
                "$" {RETURN(PSI_T_DOLLAR);}
-               "*" {RETURN(PSI_T_POINTER);}
-               "&" {RETURN(PSI_T_REFERENCE);}
+               "*" {RETURN(PSI_T_ASTERISK);}
+               "&" {RETURN(PSI_T_AMPERSAND);}
+               "+" {RETURN(PSI_T_PLUS);}
+               "-" {RETURN(PSI_T_MINUS);}
+               "/" {RETURN(PSI_T_SLASH);}
                [\r\n] { ++P->line; continue; }
                [\t ]+ { continue; }
                'TRUE' {RETURN(PSI_T_TRUE);}
@@ -203,6 +206,7 @@ token_t PSI_ParserScan(PSI_Parser *P)
                'UNSIGNED' {RETURN(PSI_T_UNSIGNED);}
                'STRING' {RETURN(PSI_T_STRING);}
                'ARRAY' {RETURN(PSI_T_ARRAY);}
+               'OBJECT' {RETURN(PSI_T_OBJECT);}
                'FUNCTION' {RETURN(PSI_T_FUNCTION);}
                'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
                'STRUCT' {RETURN(PSI_T_STRUCT);}
@@ -214,11 +218,14 @@ token_t PSI_ParserScan(PSI_Parser *P)
                'FREE' {RETURN(PSI_T_FREE);}
                'STRLEN' {RETURN(PSI_T_STRLEN);}
                'STRVAL' {RETURN(PSI_T_STRVAL);}
+               'PATHVAL' {RETURN(PSI_T_PATHVAL);}
                'INTVAL' {RETURN(PSI_T_INTVAL);}
                'FLOATVAL' {RETURN(PSI_T_FLOATVAL);}
                'BOOLVAL' {RETURN(PSI_T_BOOLVAL);}
                'ARRVAL' {RETURN(PSI_T_ARRVAL);}
+               'OBJVAL' {RETURN(PSI_T_OBJVAL);}
                'CALLOC' {RETURN(PSI_T_CALLOC);}
+               'TO_OBJECT' {RETURN(PSI_T_TO_OBJECT);}
                'TO_ARRAY' {RETURN(PSI_T_TO_ARRAY);}
                'TO_STRING' {RETURN(PSI_T_TO_STRING);}
                'TO_INT' {RETURN(PSI_T_TO_INT);}
index 62530ca..615581d 100644 (file)
@@ -1,59 +1,66 @@
 #define PSI_T_NAME                             1
-#define PSI_T_FREE                             2
-#define PSI_T_SET                              3
-#define PSI_T_LET                              4
-#define PSI_T_RETURN                           5
-#define PSI_T_LIB                              6
-#define PSI_T_INT                              7
-#define PSI_T_UNSIGNED                         8
-#define PSI_T_EOF                              9
-#define PSI_T_QUOTED_STRING                   10
-#define PSI_T_EOS                             11
-#define PSI_T_STRUCT                          12
-#define PSI_T_LBRACE                          13
-#define PSI_T_RBRACE                          14
-#define PSI_T_COLON                           15
-#define PSI_T_LPAREN                          16
-#define PSI_T_NUMBER                          17
-#define PSI_T_RPAREN                          18
-#define PSI_T_BOOL                            19
-#define PSI_T_FLOAT                           20
-#define PSI_T_STRING                          21
-#define PSI_T_CONST                           22
-#define PSI_T_NSNAME                          23
-#define PSI_T_EQUALS                          24
-#define PSI_T_TYPEDEF                         25
-#define PSI_T_VOID                            26
-#define PSI_T_LBRACKET                        27
-#define PSI_T_RBRACKET                        28
-#define PSI_T_COMMA                           29
-#define PSI_T_DOUBLE                          30
-#define PSI_T_INT8                            31
-#define PSI_T_UINT8                           32
-#define PSI_T_INT16                           33
-#define PSI_T_UINT16                          34
-#define PSI_T_INT32                           35
-#define PSI_T_UINT32                          36
-#define PSI_T_INT64                           37
-#define PSI_T_UINT64                          38
-#define PSI_T_FUNCTION                        39
-#define PSI_T_REFERENCE                       40
-#define PSI_T_NULL                            41
-#define PSI_T_TRUE                            42
-#define PSI_T_FALSE                           43
-#define PSI_T_DOLLAR                          44
-#define PSI_T_CALLOC                          45
-#define PSI_T_ARRVAL                          46
-#define PSI_T_STRLEN                          47
-#define PSI_T_STRVAL                          48
-#define PSI_T_FLOATVAL                        49
-#define PSI_T_INTVAL                          50
-#define PSI_T_BOOLVAL                         51
-#define PSI_T_TO_ARRAY                        52
-#define PSI_T_TO_STRING                       53
-#define PSI_T_TO_INT                          54
-#define PSI_T_TO_FLOAT                        55
-#define PSI_T_TO_BOOL                         56
-#define PSI_T_MIXED                           57
-#define PSI_T_ARRAY                           58
-#define PSI_T_POINTER                         59
+#define PSI_T_PLUS                             2
+#define PSI_T_MINUS                            3
+#define PSI_T_SLASH                            4
+#define PSI_T_ASTERISK                         5
+#define PSI_T_FREE                             6
+#define PSI_T_SET                              7
+#define PSI_T_LET                              8
+#define PSI_T_RETURN                           9
+#define PSI_T_LIB                             10
+#define PSI_T_INT                             11
+#define PSI_T_UNSIGNED                        12
+#define PSI_T_EOF                             13
+#define PSI_T_QUOTED_STRING                   14
+#define PSI_T_EOS                             15
+#define PSI_T_STRUCT                          16
+#define PSI_T_LBRACE                          17
+#define PSI_T_RBRACE                          18
+#define PSI_T_COLON                           19
+#define PSI_T_LPAREN                          20
+#define PSI_T_NUMBER                          21
+#define PSI_T_RPAREN                          22
+#define PSI_T_BOOL                            23
+#define PSI_T_FLOAT                           24
+#define PSI_T_STRING                          25
+#define PSI_T_CONST                           26
+#define PSI_T_NSNAME                          27
+#define PSI_T_EQUALS                          28
+#define PSI_T_TYPEDEF                         29
+#define PSI_T_VOID                            30
+#define PSI_T_LBRACKET                        31
+#define PSI_T_RBRACKET                        32
+#define PSI_T_COMMA                           33
+#define PSI_T_DOUBLE                          34
+#define PSI_T_INT8                            35
+#define PSI_T_UINT8                           36
+#define PSI_T_INT16                           37
+#define PSI_T_UINT16                          38
+#define PSI_T_INT32                           39
+#define PSI_T_UINT32                          40
+#define PSI_T_INT64                           41
+#define PSI_T_UINT64                          42
+#define PSI_T_FUNCTION                        43
+#define PSI_T_AMPERSAND                       44
+#define PSI_T_NULL                            45
+#define PSI_T_TRUE                            46
+#define PSI_T_FALSE                           47
+#define PSI_T_DOLLAR                          48
+#define PSI_T_CALLOC                          49
+#define PSI_T_OBJVAL                          50
+#define PSI_T_ARRVAL                          51
+#define PSI_T_PATHVAL                         52
+#define PSI_T_STRLEN                          53
+#define PSI_T_STRVAL                          54
+#define PSI_T_FLOATVAL                        55
+#define PSI_T_INTVAL                          56
+#define PSI_T_BOOLVAL                         57
+#define PSI_T_TO_OBJECT                       58
+#define PSI_T_TO_ARRAY                        59
+#define PSI_T_TO_STRING                       60
+#define PSI_T_TO_INT                          61
+#define PSI_T_TO_FLOAT                        62
+#define PSI_T_TO_BOOL                         63
+#define PSI_T_MIXED                           64
+#define PSI_T_ARRAY                           65
+#define PSI_T_OBJECT                          66
index c18cec9..0a7259e 100644 (file)
@@ -23,6 +23,7 @@
 }
 
 %nonassoc NAME.
+%left PLUS MINUS SLASH ASTERISK.
 %fallback NAME FREE SET LET RETURN LIB INT UNSIGNED.
 
 file ::= blocks.
@@ -273,7 +274,7 @@ impl_func(func) ::= FUNCTION NSNAME(NAME) impl_args(args) COLON impl_type(type).
        func = init_impl_func(NAME->text, args, type, 0);
        free(NAME);
 }
-impl_func(func) ::= FUNCTION REFERENCE NSNAME(NAME) impl_args(args) COLON impl_type(type). {
+impl_func(func) ::= FUNCTION AMPERSAND NSNAME(NAME) impl_args(args) COLON impl_type(type). {
        func = init_impl_func(NAME->text, args, type, 1);
        free(NAME);
 }
@@ -292,7 +293,7 @@ impl_var(var) ::= DOLLAR NAME(T). {
        var = init_impl_var(T->text, 0);
        free(T);
 }
-impl_var(var) ::= REFERENCE DOLLAR NAME(T). {
+impl_var(var) ::= AMPERSAND DOLLAR NAME(T). {
        var = init_impl_var(T->text, 1);
        free(T);
 }
@@ -358,17 +359,35 @@ let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. {
 
 %type let_value {let_value*}
 %destructor let_value {free_let_value($$);}
-let_value(val) ::= CALLOC(F) LPAREN NUMBER(N) COMMA decl_type(t) RPAREN. {
-       val = init_let_value(
-               init_let_func(F->type, F->text,
-                       init_let_calloc(
-                               atol(N->text), t
-                       )
-               ), NULL, 0
-       );
+let_value(val) ::= CALLOC(F) LPAREN let_calloc(alloc) RPAREN. {
+       val = init_let_value(init_let_func(F->type, F->text, alloc), NULL, 0);
        free(F);
-       free(N);
 }
+
+%type let_calloc {let_calloc*}
+%destructor let_calloc {free_let_calloc($$);}
+let_calloc(alloc) ::= num_exp(nmemb) COMMA num_exp(size). {
+       alloc = init_let_calloc(nmemb, size);
+}
+
+%token_class num_exp_token NUMBER NSNAME.
+%token_class num_exp_op_token PLUS MINUS ASTERISK SLASH.
+%type num_exp {num_exp*}
+%destructor num_exp {free_num_exp($$);}
+num_exp(exp) ::= num_exp_token(tok). {
+       exp = init_num_exp(tok->type, tok->text);
+       free(tok);
+}
+num_exp(exp) ::= decl_var(var). {
+       exp = init_num_exp(PSI_T_NAME, var);
+}
+num_exp(exp) ::= num_exp(exp_) num_exp_op_token(operator_) num_exp(operand_). {
+       exp_->operator = operator_->type;
+       exp_->operand = operand_;
+       exp = exp_;
+       free(operator_);
+}
+
 let_value(val) ::= reference(r) let_func(func) LPAREN impl_var(var) RPAREN. {
        val = init_let_value(func, var, r);
 }
@@ -376,7 +395,7 @@ let_value(val) ::= reference(r) NULL. {
        val = init_let_value(NULL, NULL, r);
 }
 
-%token_class let_func_token ARRVAL STRLEN STRVAL FLOATVAL INTVAL BOOLVAL.
+%token_class let_func_token OBJVAL ARRVAL PATHVAL STRLEN STRVAL FLOATVAL INTVAL BOOLVAL.
 %type let_func {let_func*}
 %destructor let_func {free_let_func($$);}
 let_func(func) ::= let_func_token(T). {
@@ -409,7 +428,7 @@ set_vals(vals) ::= set_vals(vals_) COMMA set_value(val). {
        vals = add_inner_set_value(vals_, val);
 }
 
-%token_class set_func_token TO_ARRAY TO_STRING TO_INT TO_FLOAT TO_BOOL VOID.
+%token_class set_func_token TO_OBJECT TO_ARRAY TO_STRING TO_INT TO_FLOAT TO_BOOL VOID.
 %type set_func {set_func*}
 %destructor set_func {free_set_func($$);}
 set_func(func) ::= set_func_token(T). {
@@ -444,7 +463,7 @@ free_call(call) ::= NAME(F) LPAREN decl_vars(vars) RPAREN. {
        call = init_free_call(F->text, vars);
 }
 
-%token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY.
+%token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY OBJECT.
 %type impl_type {impl_type*}
 %destructor impl_type {free_impl_type($$);}
 impl_type(type_) ::= impl_type_token(T). {
@@ -454,12 +473,12 @@ impl_type(type_) ::= impl_type_token(T). {
 
 %type reference {char}
 reference(r) ::= . {r = 0;}
-reference(r) ::= REFERENCE. {r = 1;}
+reference(r) ::= AMPERSAND. {r = 1;}
 
 %type indirection {unsigned}
 indirection(i) ::= . {i = 0;}
 indirection(i) ::= pointers(p). {i = p;}
 
 %type pointers {unsigned}
-pointers(p) ::= POINTER. {p = 1;}
-pointers(p) ::= pointers(P) POINTER. {p = P+1;}
+pointers(p) ::= ASTERISK. {p = 1;}
+pointers(p) ::= pointers(P) ASTERISK. {p = P+1;}