From 2421d323be79e4a811a4197914330a8c0124b130 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Fri, 11 Dec 2015 11:35:14 +0100 Subject: [PATCH] flush --- m4/psi.m4 | 7 ++ m4/psi_struct.m4 | 4 +- m4/psi_type.m4 | 18 ++--- m4/time.m4 | 2 +- php_psi.h | 15 ++++ src/context.c | 7 ++ src/module.c | 102 ++++++++++++++++++++++++- src/parser.h | 185 +++++++++++++++++++++++++++++----------------- src/parser.re | 11 ++- src/parser_proc.h | 123 +++++++++++++++--------------- src/parser_proc.y | 53 ++++++++----- 11 files changed, 367 insertions(+), 160 deletions(-) diff --git a/m4/psi.m4 b/m4/psi.m4 index ea8d7fb..e9955f0 100644 --- 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], diff --git a/m4/psi_struct.m4 b/m4/psi_struct.m4 index 3255c94..430baf7 100644 --- a/m4/psi_struct.m4 +++ b/m4/psi_struct.m4 @@ -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)]) diff --git a/m4/psi_type.m4 b/m4/psi_type.m4 index d1e0fbf..3b0a22e 100644 --- a/m4/psi_type.m4 +++ b/m4/psi_type.m4 @@ -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) diff --git a/m4/time.m4 b/m4/time.m4 index 3d50e69..a4cb58e 100644 --- a/m4/time.m4 +++ b/m4/time.m4 @@ -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, [()]) ]) diff --git a/php_psi.h b/php_psi.h index 84b73c2..54d78b0 100644 --- 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); diff --git a/src/context.c b/src/context.c index cbcfbc6..134acdd 100644 --- a/src/context.c +++ b/src/context.c @@ -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); } diff --git a/src/module.c b/src/module.c index 469fb4d..da623b2 100644 --- a/src/module.c +++ b/src/module.c @@ -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(); diff --git a/src/parser.h b/src/parser.h index 5ec0b95..faa95e4 100644 --- a/src/parser.h +++ b/src/parser.h @@ -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 diff --git a/src/parser.re b/src/parser.re index d4a25d2..d5a0f8e 100644 --- a/src/parser.re +++ b/src/parser.re @@ -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);} diff --git a/src/parser_proc.h b/src/parser_proc.h index 62530ca..615581d 100644 --- a/src/parser_proc.h +++ b/src/parser_proc.h @@ -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 diff --git a/src/parser_proc.y b/src/parser_proc.y index c18cec9..0a7259e 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -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;} -- 2.30.2