|
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(¶m->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(¶m->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 |
}
|