1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA
19  */
20 
21 #include <assert.h>
22 #include <stdlib.h>
23 
24 #include "param.h"
25 #include "type.h"
26 #include "value.h"
27 #include "expr.h"
28 
29 void
param_init_type(struct param * param,struct arg_type_info * type,int own)30 param_init_type(struct param *param, struct arg_type_info *type, int own)
31 {
32 	param->flavor = PARAM_FLAVOR_TYPE;
33 	param->u.type.type = type;
34 	param->u.type.own_type = own;
35 }
36 
37 void
param_init_stop(struct param * param)38 param_init_stop(struct param *param)
39 {
40 	param->flavor = PARAM_FLAVOR_STOP;
41 }
42 
43 void
param_init_pack(struct param * param,enum param_pack_flavor ppflavor,struct expr_node * args,size_t nargs,int own_args,struct param_enum * (* init)(struct value * cb_args,size_t nargs,struct value_dict * arguments),int (* next)(struct param_enum * context,struct arg_type_info * infop,int * insert_stop),enum param_status (* stop)(struct param_enum * ctx,struct value * value),void (* done)(struct param_enum *))44 param_init_pack(struct param *param, enum param_pack_flavor ppflavor,
45 		struct expr_node *args, size_t nargs, int own_args,
46 		struct param_enum *(*init)(struct value *cb_args,
47 					   size_t nargs,
48 					   struct value_dict *arguments),
49 		int (*next)(struct param_enum *context,
50 			    struct arg_type_info *infop,
51 			    int *insert_stop),
52 		enum param_status (*stop)(struct param_enum *ctx,
53 					  struct value *value),
54 		void (*done)(struct param_enum *))
55 {
56 	param->flavor = PARAM_FLAVOR_PACK;
57 	param->u.pack.args = args;
58 	param->u.pack.nargs = nargs;
59 	param->u.pack.own_args = own_args;
60 	param->u.pack.ppflavor = ppflavor;
61 	param->u.pack.init = init;
62 	param->u.pack.next = next;
63 	param->u.pack.stop = stop;
64 	param->u.pack.done = done;
65 }
66 
67 struct param_enum *
param_pack_init(struct param * param,struct value_dict * fargs)68 param_pack_init(struct param *param, struct value_dict *fargs)
69 {
70 	struct value cb_args[param->u.pack.nargs];
71 	size_t i;
72 
73 	/* For evaluation of argument expressions, we pass in this as
74 	 * a "current" value.  */
75 	struct arg_type_info *void_type = type_get_simple(ARGTYPE_VOID);
76 	struct value void_val;
77 	value_init_detached(&void_val, NULL, void_type, 0);
78 
79 	struct param_enum *ret = NULL;
80 	for (i = 0; i < param->u.pack.nargs; ++i) {
81 		if (expr_eval(&param->u.pack.args[i], &void_val,
82 			      fargs, &cb_args[i]) < 0)
83 			goto release;
84 	}
85 
86 	ret = param->u.pack.init(cb_args, param->u.pack.nargs, fargs);
87 
88 release:
89 	while (i-- > 0)
90 		value_destroy(&cb_args[i]);
91 	return ret;
92 }
93 
94 int
param_pack_next(struct param * param,struct param_enum * context,struct arg_type_info * infop,int * insert_stop)95 param_pack_next(struct param *param, struct param_enum *context,
96 		struct arg_type_info *infop, int *insert_stop)
97 {
98 	return param->u.pack.next(context, infop, insert_stop);
99 }
100 
101 enum param_status
param_pack_stop(struct param * param,struct param_enum * context,struct value * value)102 param_pack_stop(struct param *param,
103 		struct param_enum *context, struct value *value)
104 {
105 	return param->u.pack.stop(context, value);
106 }
107 
108 void
param_pack_done(struct param * param,struct param_enum * context)109 param_pack_done(struct param *param, struct param_enum *context)
110 {
111 	return param->u.pack.done(context);
112 }
113 
114 void
param_destroy(struct param * param)115 param_destroy(struct param *param)
116 {
117 	if (param == NULL)
118 		return;
119 
120 	switch (param->flavor) {
121 	case PARAM_FLAVOR_TYPE:
122 		if (param->u.type.own_type) {
123 			type_destroy(param->u.type.type);
124 			free(param->u.type.type);
125 		}
126 		return;
127 
128 	case PARAM_FLAVOR_PACK:
129 		if (param->u.pack.own_args) {
130 			size_t i;
131 			for (i = 0; i < param->u.pack.nargs; ++i)
132 				expr_destroy(&param->u.pack.args[i]);
133 			free(param->u.pack.args);
134 		}
135 		return;
136 
137 	case PARAM_FLAVOR_STOP:
138 		return;
139 	}
140 
141 	assert(!"Unknown value of param flavor!");
142 	abort();
143 }
144