Blame param.c

Packit 0021fb
/*
Packit 0021fb
 * This file is part of ltrace.
Packit 0021fb
 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
Packit 0021fb
 *
Packit 0021fb
 * This program is free software; you can redistribute it and/or
Packit 0021fb
 * modify it under the terms of the GNU General Public License as
Packit 0021fb
 * published by the Free Software Foundation; either version 2 of the
Packit 0021fb
 * License, or (at your option) any later version.
Packit 0021fb
 *
Packit 0021fb
 * This program is distributed in the hope that it will be useful, but
Packit 0021fb
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0021fb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 0021fb
 * General Public License for more details.
Packit 0021fb
 *
Packit 0021fb
 * You should have received a copy of the GNU General Public License
Packit 0021fb
 * along with this program; if not, write to the Free Software
Packit 0021fb
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
Packit 0021fb
 * 02110-1301 USA
Packit 0021fb
 */
Packit 0021fb
Packit 0021fb
#include <assert.h>
Packit 0021fb
#include <stdlib.h>
Packit 0021fb
Packit 0021fb
#include "param.h"
Packit 0021fb
#include "type.h"
Packit 0021fb
#include "value.h"
Packit 0021fb
#include "expr.h"
Packit 0021fb
Packit 0021fb
void
Packit 0021fb
param_init_type(struct param *param, struct arg_type_info *type, int own)
Packit 0021fb
{
Packit 0021fb
	param->flavor = PARAM_FLAVOR_TYPE;
Packit 0021fb
	param->u.type.type = type;
Packit 0021fb
	param->u.type.own_type = own;
Packit 0021fb
}
Packit 0021fb
Packit 0021fb
void
Packit 0021fb
param_init_stop(struct param *param)
Packit 0021fb
{
Packit 0021fb
	param->flavor = PARAM_FLAVOR_STOP;
Packit 0021fb
}
Packit 0021fb
Packit 0021fb
void
Packit 0021fb
param_init_pack(struct param *param, enum param_pack_flavor ppflavor,
Packit 0021fb
		struct expr_node *args, size_t nargs, int own_args,
Packit 0021fb
		struct param_enum *(*init)(struct value *cb_args,
Packit 0021fb
					   size_t nargs,
Packit 0021fb
					   struct value_dict *arguments),
Packit 0021fb
		int (*next)(struct param_enum *context,
Packit 0021fb
			    struct arg_type_info *infop,
Packit 0021fb
			    int *insert_stop),
Packit 0021fb
		enum param_status (*stop)(struct param_enum *ctx,
Packit 0021fb
					  struct value *value),
Packit 0021fb
		void (*done)(struct param_enum *))
Packit 0021fb
{
Packit 0021fb
	param->flavor = PARAM_FLAVOR_PACK;
Packit 0021fb
	param->u.pack.args = args;
Packit 0021fb
	param->u.pack.nargs = nargs;
Packit 0021fb
	param->u.pack.own_args = own_args;
Packit 0021fb
	param->u.pack.ppflavor = ppflavor;
Packit 0021fb
	param->u.pack.init = init;
Packit 0021fb
	param->u.pack.next = next;
Packit 0021fb
	param->u.pack.stop = stop;
Packit 0021fb
	param->u.pack.done = done;
Packit 0021fb
}
Packit 0021fb
Packit 0021fb
struct param_enum *
Packit 0021fb
param_pack_init(struct param *param, struct value_dict *fargs)
Packit 0021fb
{
Packit 0021fb
	struct value cb_args[param->u.pack.nargs];
Packit 0021fb
	size_t i;
Packit 0021fb
Packit 0021fb
	/* For evaluation of argument expressions, we pass in this as
Packit 0021fb
	 * a "current" value.  */
Packit 0021fb
	struct arg_type_info *void_type = type_get_simple(ARGTYPE_VOID);
Packit 0021fb
	struct value void_val;
Packit 0021fb
	value_init_detached(&void_val, NULL, void_type, 0);
Packit 0021fb
Packit 0021fb
	struct param_enum *ret = NULL;
Packit 0021fb
	for (i = 0; i < param->u.pack.nargs; ++i) {
Packit 0021fb
		if (expr_eval(&param->u.pack.args[i], &void_val,
Packit 0021fb
			      fargs, &cb_args[i]) < 0)
Packit 0021fb
			goto release;
Packit 0021fb
	}
Packit 0021fb
Packit 0021fb
	ret = param->u.pack.init(cb_args, param->u.pack.nargs, fargs);
Packit 0021fb
Packit 0021fb
release:
Packit 0021fb
	while (i-- > 0)
Packit 0021fb
		value_destroy(&cb_args[i]);
Packit 0021fb
	return ret;
Packit 0021fb
}
Packit 0021fb
Packit 0021fb
int
Packit 0021fb
param_pack_next(struct param *param, struct param_enum *context,
Packit 0021fb
		struct arg_type_info *infop, int *insert_stop)
Packit 0021fb
{
Packit 0021fb
	return param->u.pack.next(context, infop, insert_stop);
Packit 0021fb
}
Packit 0021fb
Packit 0021fb
enum param_status
Packit 0021fb
param_pack_stop(struct param *param,
Packit 0021fb
		struct param_enum *context, struct value *value)
Packit 0021fb
{
Packit 0021fb
	return param->u.pack.stop(context, value);
Packit 0021fb
}
Packit 0021fb
Packit 0021fb
void
Packit 0021fb
param_pack_done(struct param *param, struct param_enum *context)
Packit 0021fb
{
Packit 0021fb
	return param->u.pack.done(context);
Packit 0021fb
}
Packit 0021fb
Packit 0021fb
void
Packit 0021fb
param_destroy(struct param *param)
Packit 0021fb
{
Packit 0021fb
	if (param == NULL)
Packit 0021fb
		return;
Packit 0021fb
Packit 0021fb
	switch (param->flavor) {
Packit 0021fb
	case PARAM_FLAVOR_TYPE:
Packit 0021fb
		if (param->u.type.own_type) {
Packit 0021fb
			type_destroy(param->u.type.type);
Packit 0021fb
			free(param->u.type.type);
Packit 0021fb
		}
Packit 0021fb
		return;
Packit 0021fb
Packit 0021fb
	case PARAM_FLAVOR_PACK:
Packit 0021fb
		if (param->u.pack.own_args) {
Packit 0021fb
			size_t i;
Packit 0021fb
			for (i = 0; i < param->u.pack.nargs; ++i)
Packit 0021fb
				expr_destroy(&param->u.pack.args[i]);
Packit 0021fb
			free(param->u.pack.args);
Packit 0021fb
		}
Packit 0021fb
	case PARAM_FLAVOR_STOP:
Packit 0021fb
		return;
Packit 0021fb
	}
Packit 0021fb
Packit 0021fb
	assert(!"Unknown value of param flavor!");
Packit 0021fb
	abort();
Packit 0021fb
}