162 lines
5.6 KiB
C
162 lines
5.6 KiB
C
/*
|
|
* This file is part of ltrace.
|
|
* Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
* 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef PARAM_H
|
|
#define PARAM_H
|
|
|
|
#include "forward.h"
|
|
|
|
/* The structure param holds information about a parameter of a
|
|
* function. It's used to configure a function prototype. There are
|
|
* two flavors of parameters:
|
|
*
|
|
* - simple types
|
|
* - parameter packs
|
|
*
|
|
* Parameter packs are used to describe various vararg constructs.
|
|
* They themselves are parametrized by ltrace expressions. Those will
|
|
* typically be references to other arguments, but constants might
|
|
* also make sense, and it principle, anything can be used. */
|
|
|
|
enum param_flavor {
|
|
PARAM_FLAVOR_TYPE,
|
|
PARAM_FLAVOR_PACK,
|
|
|
|
/* This is for emitting arguments in two bunches. This is
|
|
* where we should stop emitting "left" bunch. All that's
|
|
* after this parameter should be emitted in the "right"
|
|
* bunch. */
|
|
PARAM_FLAVOR_STOP,
|
|
};
|
|
|
|
enum param_pack_flavor {
|
|
/* This parameter pack expands to a list of ordinary
|
|
* arguments. For example if the last argument is sometimes
|
|
* ignored, that would be described by a PARAM_PACK_ARGS
|
|
* parameter pack. ioctl or ptrace are two examples that
|
|
* would benefit from this. */
|
|
PARAM_PACK_ARGS,
|
|
|
|
/* This parameter pack represents a vararg argument. */
|
|
PARAM_PACK_VARARGS,
|
|
};
|
|
|
|
enum param_status {
|
|
PPCB_ERR = -1, /* An error occurred. */
|
|
PPCB_STOP, /* Stop fetching the arguments. */
|
|
PPCB_CONT, /* Display this argument and keep going. */
|
|
};
|
|
|
|
/* Each parameter enumerator defines its own context object.
|
|
* Definitions of these are in respective .c files of each
|
|
* enumerator. */
|
|
struct param_enum;
|
|
|
|
struct param {
|
|
enum param_flavor flavor;
|
|
union {
|
|
struct {
|
|
struct arg_type_info *type;
|
|
int own_type;
|
|
} type;
|
|
struct {
|
|
struct expr_node *args;
|
|
size_t nargs;
|
|
int own_args;
|
|
enum param_pack_flavor ppflavor;
|
|
|
|
struct param_enum *(*init)(struct value *cb_args,
|
|
size_t nargs,
|
|
struct value_dict *arguments);
|
|
int (*next)(struct param_enum *self,
|
|
struct arg_type_info *info,
|
|
int *insert_stop);
|
|
enum param_status (*stop)(struct param_enum *self,
|
|
struct value *value);
|
|
void (*done)(struct param_enum *self);
|
|
} pack;
|
|
} u;
|
|
};
|
|
|
|
/* Initialize simple type parameter. TYPE is owned and released by
|
|
* PARAM if OWN_TYPE. */
|
|
void param_init_type(struct param *param,
|
|
struct arg_type_info *type, int own_type);
|
|
|
|
/* Initialize a stop. */
|
|
void param_init_stop(struct param *param);
|
|
|
|
/* Initialize parameter pack PARAM. ARGS is an array of expressions
|
|
* with parameters. ARGS is owned and released by the pack if
|
|
* OWN_ARGS. NARGS is number of ARGS.
|
|
*
|
|
* When the parameter pack should be expanded, those expressions are
|
|
* evaluated and passed to the INIT callback. This has to return a
|
|
* non-NULL context object.
|
|
*
|
|
* The NEXT callback is then called repeatedly, and should initialize
|
|
* its INFOP argument to a type of the next parameter in the pack.
|
|
* When there are no more parameters in the pack, the NEXT callback
|
|
* will set INFOP to a VOID parameter. If the callback sets
|
|
* INSERT_STOP to a non-zero value, a stop parameter shall be inserted
|
|
* before this actual parameter.
|
|
*
|
|
* Core then uses the passed-in type to fetch the next argument, which
|
|
* is in turn passed to STOP callback. This callback then tells
|
|
* ltrace core what to do next: whether there are more arguments, and
|
|
* if not, whether this argument should be displayed.
|
|
*
|
|
* After the enumeration is ended, DONE callback is called. */
|
|
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 *self,
|
|
struct arg_type_info *infop,
|
|
int *insert_stop),
|
|
enum param_status (*stop)(struct param_enum *self,
|
|
struct value *value),
|
|
void (*done)(struct param_enum *self));
|
|
|
|
/* Start enumerating types in parameter pack. This evaluates the
|
|
* parameter the pack arguments and calls the init callback. See the
|
|
* documentation of param_init_pack for details. */
|
|
struct param_enum *param_pack_init(struct param *param,
|
|
struct value_dict *fargs);
|
|
|
|
/* Ask for next type in enumeration. See the documentation of
|
|
* param_init_pack for details. */
|
|
int param_pack_next(struct param *param, struct param_enum *self,
|
|
struct arg_type_info *infop, int *insert_stop);
|
|
|
|
/* Ask whether we should stop enumerating. See the documentation of
|
|
* param_init_pack for details. */
|
|
enum param_status param_pack_stop(struct param *param,
|
|
struct param_enum *self, struct value *value);
|
|
|
|
/* Finish enumerating types in parameter pack. See the documentation
|
|
* of param_init_pack for details. */
|
|
void param_pack_done(struct param *param, struct param_enum *self);
|
|
|
|
/* Destroy data held by PARAM, but not the PARAM pointer itself. */
|
|
void param_destroy(struct param *param);
|
|
|
|
#endif /* PARAM_H */
|