1865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata/*
2865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * This file is part of ltrace.
3865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata *
5865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * This program is free software; you can redistribute it and/or
6865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * modify it under the terms of the GNU General Public License as
7865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * published by the Free Software Foundation; either version 2 of the
8865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * License, or (at your option) any later version.
9865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata *
10865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * This program is distributed in the hope that it will be useful, but
11865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
12865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * General Public License for more details.
14865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata *
15865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * You should have received a copy of the GNU General Public License
16865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * along with this program; if not, write to the Free Software
17865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata * 02110-1301 USA
19865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata */
20865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
21865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata#include <assert.h>
22865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata#include <stdlib.h>
23865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
24865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata#include "param.h"
25865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata#include "type.h"
26865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata#include "value.h"
27865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata#include "expr.h"
28865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
29865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatavoid
30865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataparam_init_type(struct param *param, struct arg_type_info *type, int own)
31865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
32865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->flavor = PARAM_FLAVOR_TYPE;
33865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.type.type = type;
34865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.type.own_type = own;
35865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
36865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
37865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatavoid
38865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataparam_init_stop(struct param *param)
39865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
40865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->flavor = PARAM_FLAVOR_STOP;
41865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
42865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
43865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatavoid
44e36298a706b96bfdf9335fbe8288827761d77957Petr Machataparam_init_pack(struct param *param, enum param_pack_flavor ppflavor,
45865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		struct expr_node *args, size_t nargs, int own_args,
46865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		struct param_enum *(*init)(struct value *cb_args,
47865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata					   size_t nargs,
48865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata					   struct value_dict *arguments),
49865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		int (*next)(struct param_enum *context,
50865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			    struct arg_type_info *infop,
51865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			    int *insert_stop),
52865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		enum param_status (*stop)(struct param_enum *ctx,
53865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata					  struct value *value),
54865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		void (*done)(struct param_enum *))
55865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
56865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->flavor = PARAM_FLAVOR_PACK;
57865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.pack.args = args;
58865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.pack.nargs = nargs;
59865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.pack.own_args = own_args;
60e36298a706b96bfdf9335fbe8288827761d77957Petr Machata	param->u.pack.ppflavor = ppflavor;
61865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.pack.init = init;
62865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.pack.next = next;
63865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.pack.stop = stop;
64865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	param->u.pack.done = done;
65865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
66865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
67865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatastruct param_enum *
68865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataparam_pack_init(struct param *param, struct value_dict *fargs)
69865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
70865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	struct value cb_args[param->u.pack.nargs];
71865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	size_t i;
72865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
73865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	/* For evaluation of argument expressions, we pass in this as
74865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	 * a "current" value.  */
75865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	struct arg_type_info *void_type = type_get_simple(ARGTYPE_VOID);
76865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	struct value void_val;
77865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	value_init_detached(&void_val, NULL, void_type, 0);
78865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
79865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	struct param_enum *ret = NULL;
80865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	for (i = 0; i < param->u.pack.nargs; ++i) {
81865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		if (expr_eval(&param->u.pack.args[i], &void_val,
82865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			      fargs, &cb_args[i]) < 0)
83865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			goto release;
84865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	}
85865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
86865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	ret = param->u.pack.init(cb_args, param->u.pack.nargs, fargs);
87865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
88865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatarelease:
89865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	while (i-- > 0)
90865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		value_destroy(&cb_args[i]);
91865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	return ret;
92865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
93865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
94865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataint
95865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataparam_pack_next(struct param *param, struct param_enum *context,
96865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		struct arg_type_info *infop, int *insert_stop)
97865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
98865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	return param->u.pack.next(context, infop, insert_stop);
99865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
100865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
101865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataenum param_status
102865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataparam_pack_stop(struct param *param,
103865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		struct param_enum *context, struct value *value)
104865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
105865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	return param->u.pack.stop(context, value);
106865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
107865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
108865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatavoid
109865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataparam_pack_done(struct param *param, struct param_enum *context)
110865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
111865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	return param->u.pack.done(context);
112865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
113865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
114865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machatavoid
115865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machataparam_destroy(struct param *param)
116865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata{
117865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	if (param == NULL)
118865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		return;
119865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
120865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	switch (param->flavor) {
121865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	case PARAM_FLAVOR_TYPE:
122865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		if (param->u.type.own_type) {
123865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			type_destroy(param->u.type.type);
124865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			free(param->u.type.type);
125865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		}
126865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		return;
127865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
128865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	case PARAM_FLAVOR_PACK:
129865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		if (param->u.pack.own_args) {
130865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			size_t i;
131865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			for (i = 0; i < param->u.pack.nargs; ++i)
132865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata				expr_destroy(&param->u.pack.args[i]);
133865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata			free(param->u.pack.args);
134865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		}
1356e570e5bf8e0a9049cb1bad3ca4f82fae116c741Petr Machata		return;
1366e570e5bf8e0a9049cb1bad3ca4f82fae116c741Petr Machata
137865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	case PARAM_FLAVOR_STOP:
138865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata		return;
139865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	}
140865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata
141865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	assert(!"Unknown value of param flavor!");
142865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata	abort();
143865303f5abd934aff8e054ff8d8117e9cd36dda3Petr Machata}
144