OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
-#include "php_psi_stdinc.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+# include "php_config.h"
+#endif
#include "data.h"
-struct psi_set_func *psi_set_func_init(token_t type, const char *name,
+struct psi_set_func *psi_set_func_init(token_t type, zend_string *name,
struct psi_decl_var *var)
{
- struct psi_set_func *func = calloc(1, sizeof(*func));
+ struct psi_set_func *func = pecalloc(1, sizeof(*func), 1);
func->type = type;
- func->name = strdup(name);
+ func->name = zend_string_copy(name);
func->var = var;
return func;
struct psi_set_func *func = *func_ptr;
*func_ptr = NULL;
- if (func->token) {
- free(func->token);
- }
+ psi_token_free(&func->token);
psi_decl_var_free(&func->var);
- free(func->name);
+ zend_string_release(func->name);
free(func);
}
}
-void psi_set_func_dump(int fd, struct psi_set_func *func, unsigned level)
+void psi_set_func_dump(struct psi_dump *dump, struct psi_set_func *func, unsigned level)
{
- dprintf(fd, "%s(", func->name);
- psi_decl_var_dump(fd, func->var);
- dprintf(fd, "\t/* fqn=%s */", func->var->fqn);
+ PSI_DUMP(dump, "%s(", func->name->val);
+ psi_decl_var_dump(dump, func->var);
+ PSI_DUMP(dump, "\t/* fqn=%s */", func->var->fqn->val);
if (func->inner && !func->recursive) {
size_t i = 0, count = psi_plist_count(func->inner);
struct psi_set_exp *inner;
- dprintf(fd, ",");
+ PSI_DUMP(dump, ",");
++level;
while (psi_plist_get(func->inner, i++, &inner)) {
- dprintf(fd, "\n");
- psi_set_exp_dump(fd, inner, level, i == count);
+ PSI_DUMP(dump, "\n");
+ psi_set_exp_dump(dump, inner, level, i == count);
}
--level;
}
if (func->recursive) {
- dprintf(fd, ", ...");
+ PSI_DUMP(dump, ", ...");
}
if (func->inner && !func->recursive) {
- dprintf(fd, "\n%s", psi_t_indent(level));
+ PSI_DUMP(dump, "\n%s", psi_t_indent(level));
}
- dprintf(fd, ")");
+ PSI_DUMP(dump, ")");
}
static inline bool psi_set_func_validate_to_string(struct psi_data *data,
PSI_WARNING, "Expected to_type() cast expression");
return false;
}
- if (strcmp(set_var->name, psi_set_exp_get_decl_var(sub_exp)->name)) {
+ if (!zend_string_equals(set_var->name, psi_set_exp_get_decl_var(sub_exp)->name)) {
/* no warning, because of ambiguity with a one-field-struct monstrosity */
goto complex;
}
PSI_WARNING, "Expected to_type() cast expression");
return false;
}
- if (strcmp(set_var->name, psi_set_exp_get_decl_var(sub_exp)->name)) {
+ if (!zend_string_equals(set_var->name, psi_set_exp_get_decl_var(sub_exp)->name)) {
data->error(data, **(struct psi_token ***) &sub_exp->data,
PSI_WARNING,
"Expected %s(%s) cast expression to reference the same"
" variable like the outer `set` statement, '%s'",
- sub_exp->data.func->name,
- psi_set_exp_get_decl_var(sub_exp)->name, set_var);
+ sub_exp->data.func->name->val,
+ psi_set_exp_get_decl_var(sub_exp)->name->val,
+ set_var->name->val);
return false;
}
func->handler = psi_set_to_array_counted;
data->error(data, func->token, PSI_WARNING,
"Expected struct or union type for complex to_array()"
" cast expression, got '%s'",
- set_var->arg->type->name);
+ set_var->arg->type->name->val);
return false;
}
func->handler = psi_set_to_array;
data->error(data, func->token, PSI_WARNING,
"Expected to_array() as parent to recursion in `set` statement"
" of implementation '%s'",
- impl->func->name);
+ impl->func->name->val);
return false;
}
}
bool psi_set_func_validate(struct psi_data *data, struct psi_set_func *func,
- struct psi_set_exp *set, struct psi_impl *impl, struct psi_decl *cb_decl)
+ struct psi_validate_scope *scope)
{
- if (!func->var->arg
- && !psi_decl_var_validate(data, func->var, impl, impl->decl, NULL, set)
- && !psi_decl_var_validate(data, func->var, NULL, cb_decl, NULL, NULL)
- && !psi_impl_get_temp_let_arg(impl, func->var)) {
+ struct psi_set_exp *set = scope->current_set;
+
+ if (!psi_decl_var_validate(data, func->var, scope)
+ && !psi_impl_get_temp_let_arg(scope->impl, func->var)) {
data->error(data, func->var->token, PSI_WARNING,
"Unknown variable '%s' in implementation %s",
- func->var->name, impl->func->name);
+ func->var->name->val, scope->impl->func->name->val);
return false;
}
}
if (func->inner && (!set->outer || set->outer->inner != func->inner)) {
-
size_t i = 0;
struct psi_set_exp *inner;
struct psi_plist *sub_args;
inner->outer = set;
+ scope->current_set = inner;
+ /* skip to "fail:" if field does not exists */
sub_var = psi_set_exp_get_decl_var(inner);
sub_args = psi_decl_type_get_args(func->var->arg->type, NULL);
- if (sub_var && sub_args && !psi_decl_arg_get_by_var(sub_var, sub_args, NULL)) {
- /* remove expr for portability with different struct members */
- psi_plist_del(func->inner, --i, NULL);
- psi_set_exp_free(&inner);
- } else if (!psi_set_exp_validate(data, inner, impl, cb_decl)) {
- /* remove exp for portability */
- psi_plist_del(func->inner, --i, NULL);
+ if (sub_var && sub_args) {
+ if (!psi_decl_arg_get_by_var(sub_var, sub_args, NULL)) {
+ goto fail;
+ }
+ }
+
+ if (psi_set_exp_validate(data, inner, scope)) {
+ scope->current_set = set;
+ continue;
}
+ fail:
+ scope->current_set = set;
+ /* remove expr for portability with different struct members */
+ psi_plist_del(func->inner, --i, NULL);
+ psi_set_exp_free(&inner);
}
}
func->handler = psi_set_to_object;
break;
case PSI_T_TO_STRING:
- if (!psi_set_func_validate_to_string(data, func, set, impl)) {
+ if (!psi_set_func_validate_to_string(data, func, set, scope->impl)) {
return false;
}
break;
case PSI_T_TO_ARRAY:
- if (!psi_set_func_validate_to_array(data, func, set, impl)) {
+ if (!psi_set_func_validate_to_array(data, func, set, scope->impl)) {
return false;
}
break;
default:
data->error(data, func->token, PSI_WARNING,
"Unknown cast '%s' in `set` statement of implementation '%s'",
- func->name, impl->func->name);
+ func->name->val, scope->impl->func->name->val);
return false;
}