Commit 31af32cf authored by Petr Machata's avatar Petr Machata

Add lenses

- this adds the lens framework, although there are currently no interesting
  lenses.  display_args.c was mostly moved to lens_default.c
parent 64262609
2012-01-08 Petr Machata <[email protected]>
* lens.c, lens.h: New module
* display_args.c: Move this code...
* lens_default.c, lens_default.h: ... here
* read_config_file.c
(unshare_type_info, name2lens, parse_lens): New functions
* type.c, type.h: Add lenses throughout
2012-01-07 Petr Machata <[email protected]>
* backend.h: New file
......
......@@ -17,7 +17,6 @@ libltrace_la_SOURCES = \
debug.c \
demangle.c \
dict.c \
display_args.c \
ltrace-elf.c \
execute_program.c \
handle_event.c \
......@@ -38,7 +37,9 @@ libltrace_la_SOURCES = \
vect.c \
param.c \
printf.c \
zero.c
zero.c \
lens.c \
lens_default.c
libltrace_la_LIBADD = \
$(libelf_LIBS) \
......@@ -85,7 +86,9 @@ noinst_HEADERS = \
vect.h \
param.h \
printf.h \
zero.h
zero.h \
lens.h \
lens_default.h
dist_man1_MANS = \
ltrace.1
......
/*
* This file is part of ltrace.
* Copyright (C) 2011 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
*/
#include <assert.h>
#include "lens.h"
#include "lens_default.h"
#include "type.h"
#include "value.h"
int
format_argument(FILE *stream, struct value *value,
struct value_dict *arguments)
{
/* Find the closest enclosing parental value whose type has a
* lens assigned. */
struct value *parent;
for (parent = value; (parent != NULL && parent->type != NULL
&& parent->type->lens == NULL);
parent = parent->parent)
;
struct lens *lens = &default_lens;
if (parent != NULL && parent->type != NULL
&& parent->type->lens != NULL)
lens = parent->type->lens;
return lens_format(lens, stream, value, arguments);
}
int
lens_format(struct lens *lens, FILE *stream, struct value *value,
struct value_dict *arguments)
{
assert(lens->format_cb != NULL);
return lens->format_cb(lens, stream, value, arguments);
}
void
lens_destroy(struct lens *lens)
{
if (lens != NULL
&& lens->destroy_cb != NULL)
lens->destroy_cb(lens);
}
/*
* This file is part of ltrace.
* Copyright (C) 2011 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 LENS_H
#define LENS_H
#include <stdio.h>
#include "forward.h"
struct lens {
/* Format VALUE into STREAM. The dictionary of all arguments
* is given for purposes of evaluating array lengths and other
* dynamic expressions. Returns number of characters
* outputted, -1 in case of failure. */
int (*format_cb)(struct lens *lens, FILE *stream, struct value *value,
struct value_dict *arguments);
/* Erase any memory allocated for LENS. Keep the LENS pointer
* itself intact. */
void (*destroy_cb)(struct lens *lens);
};
/* Extracts a lens from VALUE and calls lens_format on that. */
int format_argument(FILE *stream, struct value *value,
struct value_dict *arguments);
/* Calls format callback associated with LENS. */
int lens_format(struct lens *lens, FILE *stream, struct value *value,
struct value_dict *arguments);
/* Calls destroy callback associated with LENS. */
void lens_destroy(struct lens *lens);
#endif /* LENS_H */
......@@ -28,8 +28,8 @@
#include <stdarg.h>
#include <stdio.h>
#include "common.h"
#include "proc.h"
#include "lens_default.h"
#include "value.h"
#include "expr.h"
#include "type.h"
......@@ -71,7 +71,7 @@ READER(read_double, double)
case INT_FMT_u: \
return fprintf(stream, "%"PRIu##BITS, i); \
case INT_FMT_o: \
return fprintf(stream, "%"PRIo##BITS, i); \
return fprintf(stream, "0%"PRIo##BITS, i); \
} \
} while (0)
......@@ -271,7 +271,7 @@ format_array(FILE *stream, struct value *value, struct value_dict *arguments,
/* We need "long" to be long enough to cover the whole address
* space. */
typedef char assert__long_enough_long[-(sizeof(long) < sizeof(void *))];
long l = options.strlen;
long l;
if (expr_eval_word(length, value, arguments, &l) < 0)
return -1;
size_t len = (size_t)l;
......@@ -307,8 +307,9 @@ format_array(FILE *stream, struct value *value, struct value_dict *arguments,
return written;
}
int
format_argument(FILE *stream, struct value *value, struct value_dict *arguments)
static int
toplevel_format_lens(struct lens *lens, FILE *stream,
struct value *value, struct value_dict *arguments)
{
switch (value->type->type) {
struct value *tmp;
......@@ -373,3 +374,14 @@ format_argument(FILE *stream, struct value *value, struct value_dict *arguments)
}
abort();
}
static int
default_lens_format_cb(struct lens *lens, FILE *stream,
struct value *value, struct value_dict *arguments)
{
return toplevel_format_lens(lens, stream, value, arguments);
}
struct lens default_lens = {
.format_cb = default_lens_format_cb,
};
/*
* This file is part of ltrace.
* Copyright (C) 2011 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 LENS_DEFAULT_H
#define LENS_DEFAULT_H
#include "lens.h"
/* Default lens that does reasonable job for most cases. */
extern struct lens default_lens;
#endif /* LENS_DEFAULT_H */
......@@ -186,6 +186,7 @@ param_printf_next(struct param_enum *self, struct arg_type_info *infop,
enum arg_type elt_type = ARGTYPE_UNKNOWN;
char len_buf[25] = {};
size_t len_buf_len = 0;
struct lens *lens = NULL;
for (; self->ptr < self->end; ++self->ptr) {
if (!self->percent) {
......@@ -321,6 +322,9 @@ param_printf_next(struct param_enum *self, struct arg_type_info *infop,
len_buf, len_buf_len, infop) < 0)
return -1;
infop->lens = lens;
infop->own_lens = 0;
return 0;
}
......
......@@ -37,12 +37,18 @@
#include "printf.h"
#include "zero.h"
#include "type.h"
#include "lens.h"
static int line_no;
static char *filename;
static struct arg_type_info *parse_nonpointer_type(char **str,
struct param **extra_param,
size_t param_num, int *ownp);
static struct arg_type_info *parse_type(char **str, struct param **extra_param,
size_t param_num, int *ownp);
static struct arg_type_info *parse_lens(char **str, struct param **extra_param,
size_t param_num, int *ownp);
Function *list_of_functions = NULL;
......@@ -435,7 +441,7 @@ parse_struct(char **str, struct arg_type_info *info)
eat_spaces(str);
int own;
struct arg_type_info *field = parse_type(str, NULL, 0, &own);
struct arg_type_info *field = parse_lens(str, NULL, 0, &own);
if (field == NULL || type_struct_add(info, field, own)) {
type_destroy(info);
return -1;
......@@ -540,6 +546,26 @@ build_printf_pack(struct param **packp, size_t param_num)
return 0;
}
/* Make a copy of INFO and set the *OWN bit if it's not already
* owned. */
static int
unshare_type_info(struct arg_type_info **infop, int *ownp)
{
if (*ownp)
return 0;
struct arg_type_info *ninfo = malloc(sizeof(*ninfo));
if (ninfo == NULL) {
report_error(filename, line_no,
"malloc: %s", strerror(errno));
return -1;
}
*ninfo = **infop;
*infop = ninfo;
*ownp = 1;
return 0;
}
/* XXX extra_param and param_num are a kludge to get in
* backward-compatible support for "format" parameter type. The
* latter is only valid if the former is non-NULL, which is only in
......@@ -586,7 +612,7 @@ parse_array(char **str, struct arg_type_info *info)
eat_spaces(str);
int own;
struct arg_type_info *elt_info = parse_type(str, NULL, 0, &own);
struct arg_type_info *elt_info = parse_lens(str, NULL, 0, &own);
if (elt_info == NULL)
return -1;
......@@ -742,6 +768,28 @@ parse_nonpointer_type(char **str, struct param **extra_param, size_t param_num,
return info;
}
static struct named_lens {
const char *name;
struct lens *lens;
} lenses[] = {
};
static struct lens *
name2lens(char **str, int *own_lensp)
{
char *str2 = *str;
char *ident = parse_ident(&str2);
size_t i;
for (i = 0; i < sizeof(lenses)/sizeof(*lenses); ++i)
if (strcmp(ident, lenses[i].name) == 0) {
*str = str2;
*own_lensp = 0;
return lenses[i].lens;
}
return NULL;
}
static struct arg_type_info *
parse_type(char **str, struct param **extra_param, size_t param_num, int *ownp)
{
......@@ -773,6 +821,52 @@ parse_type(char **str, struct param **extra_param, size_t param_num, int *ownp)
return info;
}
static struct arg_type_info *
parse_lens(char **str, struct param **extra_param, size_t param_num, int *ownp)
{
int own_lens;
struct lens *lens = name2lens(str, &own_lens);
int has_args = 1;
struct arg_type_info *info;
if (lens != NULL) {
eat_spaces(str);
if (parse_char(str, '(') < 0) {
report_error(filename, line_no,
"expected type argument after the lens");
return NULL;
}
}
if (has_args) {
eat_spaces(str);
info = parse_type(str, extra_param, param_num, ownp);
if (info == NULL) {
fail:
if (own_lens && lens != NULL)
lens_destroy(lens);
return NULL;
}
}
if (lens != NULL && has_args) {
eat_spaces(str);
parse_char(str, ')');
}
/* We can't modify shared types. Make a copy if we have a
* lens. */
if (lens != NULL && unshare_type_info(&info, ownp) < 0)
goto fail;
if (lens != NULL) {
info->lens = lens;
info->own_lens = own_lens;
}
return info;
}
static int
add_param(Function *fun, size_t *allocdp)
{
......@@ -815,7 +909,7 @@ process_line(char *buf) {
return NULL;
}
fun->return_info = parse_type(&str, NULL, 0, &fun->own_return_info);
fun->return_info = parse_lens(&str, NULL, 0, &fun->own_return_info);
if (fun->return_info == NULL
|| fun->return_info->type == ARGTYPE_UNKNOWN) {
err:
......@@ -866,7 +960,7 @@ process_line(char *buf) {
}
int own;
struct arg_type_info *type = parse_type(&str, &extra_param,
struct arg_type_info *type = parse_lens(&str, &extra_param,
fun->num_params, &own);
if (type == NULL) {
report_error(filename, line_no,
......
......@@ -25,6 +25,7 @@
#include "type.h"
#include "sysdep.h"
#include "expr.h"
#include "lens.h"
struct arg_type_info *
type_get_simple(enum arg_type type)
......@@ -62,6 +63,14 @@ type_get_simple(enum arg_type type)
abort();
}
static void
type_init_common(struct arg_type_info *info, enum arg_type type)
{
info->type = type;
info->lens = NULL;
info->own_lens = 0;
}
struct enum_entry {
char *key;
int own_key;
......@@ -71,7 +80,7 @@ struct enum_entry {
void
type_init_enum(struct arg_type_info *info)
{
info->type = ARGTYPE_ENUM;
type_init_common(info, ARGTYPE_ENUM);
VECT_INIT(&info->u.entries, struct enum_entry);
}
......@@ -127,7 +136,7 @@ struct struct_field {
void
type_init_struct(struct arg_type_info *info)
{
info->type = ARGTYPE_STRUCT;
type_init_common(info, ARGTYPE_STRUCT);
VECT_INIT(&info->u.entries, struct struct_field);
}
......@@ -229,7 +238,7 @@ type_init_array(struct arg_type_info *info,
struct arg_type_info *element_info, int own_info,
struct expr_node *length_expr, int own_length)
{
info->type = ARGTYPE_ARRAY;
type_init_common(info, ARGTYPE_ARRAY);
info->u.array_info.elt_type = element_info;
info->u.array_info.own_info = own_info;
info->u.array_info.length = length_expr;
......@@ -240,7 +249,7 @@ void
type_init_string(struct arg_type_info *info,
struct expr_node *length_expr, int own_length)
{
info->type = ARGTYPE_STRING_N;
type_init_common(info, ARGTYPE_STRING_N);
info->u.string_n_info.length = length_expr;
info->u.string_n_info.own_length = own_length;
}
......@@ -271,7 +280,7 @@ void
type_init_pointer(struct arg_type_info *info,
struct arg_type_info *pointee_info, int own_info)
{
info->type = ARGTYPE_POINTER;
type_init_common(info, ARGTYPE_POINTER);
info->u.ptr_info.info = pointee_info;
info->u.ptr_info.own_info = own_info;
}
......@@ -293,7 +302,8 @@ type_destroy(struct arg_type_info *info)
switch (info->type) {
case ARGTYPE_ENUM:
return type_enum_destroy(info);
type_enum_destroy(info);
break;
case ARGTYPE_STRUCT:
type_struct_destroy(info);
......@@ -324,6 +334,11 @@ type_destroy(struct arg_type_info *info)
case ARGTYPE_DOUBLE:
break;
}
if (info->own_lens) {
lens_destroy(info->lens);
free(info->lens);
}
}
#ifdef ARCH_HAVE_SIZEOF
......
......@@ -71,6 +71,9 @@ struct arg_type_info {
int own_info:1;
} ptr_info;
} u;
struct lens *lens;
int own_lens;
};
/* Return a type info for simple type TYPE (which shall not be array,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment