#include "parser.h"
void psi_error(int type, const char *msg, ...);
+size_t psi_t_size(token_t t);
int psi_internal_type(impl_type *type);
zend_internal_arg_info *psi_internal_arginfo(impl *impl);
size_t psi_num_min_args(impl *impl);
decl_arg *darg = data->impl->decl->args->args[i];
arg_ptr[i] = psi_do_let(darg);
- arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i];
+ arg_prm[i] = (darg->let->val && darg->let->val->is_reference)
+ ? &arg_ptr[i] : arg_ptr[i];
darg->let->ptr = arg_ptr[i];
}
}
}
+size_t psi_t_size(token_t t)
+{
+ size_t size;
+
+ switch (t) {
+ case PSI_T_CHAR:
+ size = sizeof(char);
+ break;
+ case PSI_T_SINT8:
+ case PSI_T_UINT8:
+ size = 1;
+ break;
+ case PSI_T_SHORT:
+ size = sizeof(short);
+ break;
+ case PSI_T_SINT16:
+ case PSI_T_UINT16:
+ size = 2;
+ break;
+ case PSI_T_INT:
+ size = sizeof(int);
+ break;
+ case PSI_T_SINT32:
+ case PSI_T_UINT32:
+ size = 4;
+ break;
+ case PSI_T_LONG:
+ size = sizeof(long);
+ break;
+ case PSI_T_SINT64:
+ case PSI_T_UINT64:
+ size = 8;
+ break;
+ case PSI_T_FLOAT:
+ size = sizeof(float);
+ break;
+ case PSI_T_DOUBLE:
+ size = sizeof(double);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+ return size;
+}
+
+static impl_val *iterate(impl_val *val, token_t t, unsigned i, impl_val *tmp)
+{
+ size_t size = psi_t_size(t);
+
+ memset(tmp, 0, sizeof(*tmp));
+ memcpy(tmp, val->ptr + size * i, size);
+ return tmp;
+}
+
+void psi_to_array(impl_val *ret_val, decl_arg *func, zval *return_value)
+{
+ zval ele;
+ unsigned i;
+ impl_val tmp;
+ token_t t = real_decl_type(func->type)->type;
+
+ array_init(return_value);
+ ret_val = deref_impl_val(0, ret_val, func);
+ for (i = 0; i < func->var->array_size; ++i) {
+ impl_val *ptr = iterate(ret_val, t, i, &tmp);
+
+ switch (t) {
+ case PSI_T_FLOAT:
+ case PSI_T_DOUBLE:
+ ZVAL_DOUBLE(&ele, ptr->dval);
+ break;
+ default:
+ ZVAL_LONG(&ele, ptr->lval);
+ break;
+ }
+
+ add_next_index_zval(return_value, &ele);
+ }
+}
+
ZEND_RESULT_CODE psi_parse_args(zend_execute_data *execute_data, impl *impl)
{
impl_arg *iarg;
} else if (iarg->def) {
iarg->val.str = zend_string_init(str.val, str.len, 0);
}
+ } else if (PSI_T_ARRAY == iarg->type->type) {
+ /* handled as _zv in let or set */
+ Z_PARAM_PROLOGUE(0);
} else {
error_code = ZPP_ERROR_FAILURE;
break;
impl_arg *iarg = darg->let->arg;
if (!iarg) {
- /* let foo = NULL */
- memset(arg_val, 0, sizeof(*arg_val));
+ /*
+ * let foo = NULL;
+ * let foo;
+ */
+ if (darg->var->array_size) {
+ arg_val->ptr = ecalloc(darg->var->array_size, sizeof(*arg_val));
+ darg->let->mem = arg_val->ptr;
+ } else {
+ memset(arg_val, 0, sizeof(*arg_val));
+ }
return arg_val;
}
switch (darg->let->val->func->type) {
zend_string_release(zs);
}
break;
+ case PSI_T_CALLOC:
+ arg_val->ptr = calloc(1, darg->let->val->func->size);
+ darg->let->mem = arg_val->ptr;
+ break;
EMPTY_SWITCH_DEFAULT_CASE();
}
case PSI_T_TO_STRING:
psi_to_string(val, vars->vars[0]->arg, return_value);
break;
+ case PSI_T_TO_ARRAY:
+ psi_to_array(val, vars->vars[0]->arg, return_value);
+ break;
EMPTY_SWITCH_DEFAULT_CASE();
}
}
typedef struct let_func {
token_t type;
char *name;
+ size_t size;
} let_func;
-static inline let_func *init_let_func(token_t type, char *name) {
+static inline let_func *init_let_func(token_t type, char *name, size_t size) {
let_func *func = malloc(sizeof(*func));
func->type = type;
- func->name = (char *) strdup((const char *) name);
+ func->name = strdup(name);
+ func->size = size;
return func;
}
INTVAL = 'intval';
FLOATVAL = 'floatval';
BOOLVAL = 'boolval';
+ CALLOC = 'calloc';
+ TO_ARRAY = 'to_array';
TO_STRING = 'to_string';
TO_INT = 'to_int';
TO_FLOAT = 'to_float';
INTVAL {RETURN(PSI_T_INTVAL);}
FLOATVAL {RETURN(PSI_T_FLOATVAL);}
BOOLVAL {RETURN(PSI_T_BOOLVAL);}
+ CALLOC {RETURN(PSI_T_CALLOC);}
+ TO_ARRAY {RETURN(PSI_T_TO_ARRAY);}
TO_STRING {RETURN(PSI_T_TO_STRING);}
TO_INT {RETURN(PSI_T_TO_INT);}
TO_FLOAT {RETURN(PSI_T_TO_FLOAT);}
#define PSI_T_FALSE 41
#define PSI_T_DOLLAR 42
#define PSI_T_LET 43
-#define PSI_T_STRLEN 44
-#define PSI_T_STRVAL 45
-#define PSI_T_INTVAL 46
-#define PSI_T_FLOATVAL 47
-#define PSI_T_BOOLVAL 48
-#define PSI_T_SET 49
-#define PSI_T_TO_STRING 50
-#define PSI_T_TO_INT 51
-#define PSI_T_TO_FLOAT 52
-#define PSI_T_TO_BOOL 53
-#define PSI_T_RETURN 54
-#define PSI_T_FREE 55
-#define PSI_T_MIXED 56
-#define PSI_T_ARRAY 57
-#define PSI_T_POINTER 58
+#define PSI_T_CALLOC 44
+#define PSI_T_STRLEN 45
+#define PSI_T_STRVAL 46
+#define PSI_T_INTVAL 47
+#define PSI_T_FLOATVAL 48
+#define PSI_T_BOOLVAL 49
+#define PSI_T_SET 50
+#define PSI_T_TO_ARRAY 51
+#define PSI_T_TO_STRING 52
+#define PSI_T_TO_INT 53
+#define PSI_T_TO_FLOAT 54
+#define PSI_T_TO_BOOL 55
+#define PSI_T_RETURN 56
+#define PSI_T_FREE 57
+#define PSI_T_MIXED 58
+#define PSI_T_ARRAY 59
+#define PSI_T_POINTER 60
}
%type let_stmt {let_stmt*}
+let_stmt(let) ::= LET decl_var(var) EOS. {
+ let = init_let_stmt(var, NULL);
+}
let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. {
let = init_let_stmt(var, val);
}
%type let_value {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,
+ atol(N->text) * psi_t_size(real_decl_type(t)->type)
+ ), NULL, 0
+ );
+ free_decl_type(t);
+ free(F);
+ free(N);
+}
let_value(val) ::= let_func(func) LPAREN impl_var(var) RPAREN. {
val = init_let_value(func, var, 0);
}
%type let_func {let_func*}
let_func(func) ::= STRLEN(T). {
- func = init_let_func(T->type, T->text);
+ func = init_let_func(T->type, T->text, 0);
free(T);
}
let_func(func) ::= STRVAL(T). {
- func = init_let_func(T->type, T->text);
+ func = init_let_func(T->type, T->text, 0);
free(T);
}
let_func(func) ::= INTVAL(T). {
- func = init_let_func(T->type, T->text);
+ func = init_let_func(T->type, T->text, 0);
free(T);
}
let_func(func) ::= FLOATVAL(T). {
- func = init_let_func(T->type, T->text);
+ func = init_let_func(T->type, T->text, 0);
free(T);
}
let_func(func) ::= BOOLVAL(T). {
- func = init_let_func(T->type, T->text);
+ func = init_let_func(T->type, T->text, 0);
free(T);
}
}
%type set_func {set_func*}
+set_func(func) ::= TO_ARRAY(T). {
+ func = init_set_func(T->type, T->text);
+ free(T);
+}
set_func(func) ::= TO_STRING(T). {
func = init_set_func(T->type, T->text);
free(T);
let_stmt *let = stmts->let.list[i];
int check = 0;
- if (let->val->var) {
+ if (let->val && let->val->var) {
for (j = 0; j < impl->func->args->count; ++j) {
impl_arg *iarg = impl->func->args->args[j];
--- /dev/null
+
+extern int pipe(int fds[2]);
+
+function \pipe(array &$fds = null) : int {
+ return to_int(pipe);
+ let fds = calloc(2, int);
+ set $fds = to_array(fds);
+}
--- /dev/null
+--TEST--
+pipe
+--SKIPIF--
+<?php
+extension_loaded("psi") or die("skip - need ext/psi");
+?>
+--INI--
+psi.directory={PWD}
+--FILE--
+===TEST===
+<?php
+
+var_dump(pipe($pipes));
+$r = fopen("php://fd/".$pipes[0], "r");
+$w = fopen("php://fd/".$pipes[1], "w");
+
+fputs($w, "Hello World!\n");
+var_dump(fgets($r));
+
+?>
+===DONE===
+--EXPECT--
+===TEST===
+int(0)
+string(13) "Hello World!
+"
+===DONE===
\ No newline at end of file