Home | History | Annotate | Download | only in ltrace
      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
     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
     38 param_init_stop(struct param *param)
     39 {
     40 	param->flavor = PARAM_FLAVOR_STOP;
     41 }
     42 
     43 void
     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 *
     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
     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
    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
    109 param_pack_done(struct param *param, struct param_enum *context)
    110 {
    111 	return param->u.pack.done(context);
    112 }
    113 
    114 void
    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