aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--display_args.c14
-rw-r--r--etc/ltrace.conf9
-rw-r--r--ltrace.h8
-rw-r--r--read_config_file.c120
-rw-r--r--testsuite/ltrace.main/parameters-lib.c5
-rw-r--r--testsuite/ltrace.main/parameters.c18
-rw-r--r--testsuite/ltrace.main/parameters.conf1
-rw-r--r--testsuite/ltrace.main/parameters.exp2
9 files changed, 181 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 0487960..ce911b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2006-08-07 Steve Fink <sphink@gmail.com>
+ * display_args.c, etc/ltrace.conf, ltrace.h, read_config_file.c,
+ testsuite/ltrace.main/parameters-lib.c,
+ testsuite/ltrace.main/parameters.c,
+ testsuite/ltrace.main/parameters.conf,
+ testsuite/ltrace.main/parameters.exp: implement enumerated parameters
+
+2006-08-07 Steve Fink <sphink@gmail.com>
+
* testsuite/ltrace.main/Makefile.in : update testsuite for
new parameters
* testsuite/ltrace.main/parameters-lib.c : added
diff --git a/display_args.c b/display_args.c
index 66a9093..2a6b34f 100644
--- a/display_args.c
+++ b/display_args.c
@@ -42,6 +42,18 @@ static int display_pointer(enum tof type, struct process *proc, long value,
return display_value(type, proc, pointed_to, inner);
}
+static int display_enum(enum tof type, struct process *proc,
+ arg_type_info* info, long value)
+{
+ int ii;
+ for (ii = 0; ii < info->u.enum_info.entries; ++ii) {
+ if (info->u.enum_info.values[ii] == value)
+ return fprintf(output, "%s", info->u.enum_info.keys[ii]);
+ }
+
+ return display_unknown(type, proc, value);
+}
+
/* Args:
type - syscall or shared library function or memory
proc - information about the traced process
@@ -94,6 +106,8 @@ int display_value(enum tof type, struct process *proc,
return display_string(type, proc, (void*) value,
get_length(type, proc,
info->u.string_n_info.size_spec));
+ case ARGTYPE_ENUM:
+ return display_enum(type, proc, info, value);
case ARGTYPE_POINTER:
return display_pointer(type, proc, value, info);
case ARGTYPE_UNKNOWN:
diff --git a/etc/ltrace.conf b/etc/ltrace.conf
index 547a125..bff45fa 100644
--- a/etc/ltrace.conf
+++ b/etc/ltrace.conf
@@ -24,11 +24,20 @@
; string[N] == (char *) [N>0] [show only up to N bytes]
; ignore == (any) [ignore arg, output blank]
; type* == (type *) [pointer to any other type]
+; enum (key=value,key=value,...) [enumeration, see below]
; Backwards-compatibility:
; string0 == (char *) [same as string[retval]]
; stringN == (char *) [N>0] [same as string[argN]]
+; Enumerations
+;
+; The syntax is a parenthesized list of key=value assignments, like so:
+; enum (F_DUPFD=0,F_GETFD=1,F_SETFD=2)
+; an example usage might look like
+; int fcntl(int,enum (F_DUPFD=0,F_GETFD=1,F_SETFD=2))
+;
+
; arpa/inet.h
int inet_aton(string,addr);
string inet_ntoa(addr); ; It isn't a ADDR but an hexa number...
diff --git a/ltrace.h b/ltrace.h
index e649bb1..3b40cb3 100644
--- a/ltrace.h
+++ b/ltrace.h
@@ -42,6 +42,7 @@ enum arg_type {
ARGTYPE_FORMAT, /* printf-like format */
ARGTYPE_STRING, /* NUL-terminated string */
ARGTYPE_STRING_N, /* String of known maxlen */
+ ARGTYPE_ENUM, /* Enumeration */
ARGTYPE_IGNORE, /* Leave parameter blank */
ARGTYPE_POINTER, /* Pointer to some other type */
ARGTYPE_COUNT /* number of ARGTYPE_* values */
@@ -50,6 +51,13 @@ enum arg_type {
typedef struct arg_type_info_t {
enum arg_type type;
union {
+ // ARGTYPE_ENUM
+ struct {
+ size_t entries;
+ char **keys;
+ int *values;
+ } enum_info;
+
// ARGTYPE_STRING_N
struct {
int size_spec;
diff --git a/read_config_file.c b/read_config_file.c
index 15c3f39..5b114de 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -11,6 +11,10 @@
#include "output.h"
#include "debug.h"
+static int line_no;
+static char *filename;
+static int error_count = 0;
+
struct function *list_of_functions = NULL;
static struct list_of_pt_t {
@@ -29,6 +33,7 @@ static struct list_of_pt_t {
"file", ARGTYPE_FILE}, {
"format", ARGTYPE_FORMAT}, {
"string", ARGTYPE_STRING}, {
+ "enum", ARGTYPE_ENUM}, {
"ignore", ARGTYPE_IGNORE}, {
NULL, ARGTYPE_UNKNOWN} /* Must finish with NULL */
};
@@ -46,6 +51,7 @@ static arg_type_info arg_type_singletons[] = {
{ ARGTYPE_FORMAT },
{ ARGTYPE_STRING },
{ ARGTYPE_STRING_N },
+ { ARGTYPE_ENUM },
{ ARGTYPE_IGNORE },
{ ARGTYPE_POINTER },
{ ARGTYPE_UNKNOWN }
@@ -81,6 +87,32 @@ static void eat_spaces(char **str)
}
}
+static char *xstrndup(char *str, size_t len)
+{
+ char *ret = (char *) malloc(len + 1);
+ strncpy(ret, str, len);
+ ret[len] = 0;
+ return ret;
+}
+
+static char *parse_ident(char **str)
+{
+ char *ident = *str;
+
+ if (!isalnum(**str) && **str != '_') {
+ output_line(0, "Syntax error in `%s', line %d: Bad identifier",
+ filename, line_no);
+ error_count++;
+ return NULL;
+ }
+
+ while (**str && (isalnum(**str) || **str == '_')) {
+ ++(*str);
+ }
+
+ return xstrndup(ident, *str - ident);
+}
+
/*
Returns position in string at the left parenthesis which starts the
function's argument signature. Returns NULL on error.
@@ -119,12 +151,17 @@ static char *start_of_arg_sig(char *str)
*/
static int simple_type(enum arg_type at)
{
+ switch (at) {
+ case ARGTYPE_STRING:
+ case ARGTYPE_STRING_N:
+ case ARGTYPE_ENUM:
+ return 0;
+
+ default:
return 1;
+ }
}
-static int line_no;
-static char *filename;
-
static int parse_int(char **str)
{
char *end;
@@ -132,6 +169,7 @@ static int parse_int(char **str)
if (end == *str) {
output_line(0, "Syntax error in `%s', line %d: Bad number",
filename, line_no);
+ error_count++;
return 0;
}
@@ -191,6 +229,73 @@ static arg_type_info *parse_nonpointer_type(char **str)
switch (info->type) {
+ // Syntax: enum ( keyname=value,keyname=value,... )
+ case ARGTYPE_ENUM:{
+ struct enum_opt {
+ char *key;
+ int value;
+ struct enum_opt *next;
+ };
+ struct enum_opt *list = NULL;
+ struct enum_opt *p;
+ int entries = 0;
+ int ii;
+
+ eat_spaces(str);
+ (*str)++; // Get past open paren
+ eat_spaces(str);
+
+ while (**str && **str != ')') {
+ p = (struct enum_opt *) malloc(sizeof(*p));
+ eat_spaces(str);
+ p->key = parse_ident(str);
+ if (error_count) {
+ free(p);
+ return NULL;
+ }
+ eat_spaces(str);
+ if (**str != '=') {
+ free(p->key);
+ free(p);
+ output_line(0,
+ "Syntax error in `%s', line %d: expected '=', got '%c'",
+ filename, line_no, **str);
+ error_count++;
+ return NULL;
+ }
+ ++(*str);
+ eat_spaces(str);
+ p->value = parse_int(str);
+ p->next = list;
+ list = p;
+ ++entries;
+
+ // Skip comma
+ eat_spaces(str);
+ if (**str == ',') {
+ (*str)++;
+ eat_spaces(str);
+ }
+ }
+
+ info->u.enum_info.entries = entries;
+ info->u.enum_info.keys =
+ (char **) malloc(entries * sizeof(char *));
+ info->u.enum_info.values =
+ (int *) malloc(entries * sizeof(int));
+ for (ii = 0, p = NULL; list; ++ii, list = list->next) {
+ if (p)
+ free(p);
+ info->u.enum_info.keys[ii] = list->key;
+ info->u.enum_info.values[ii] = list->value;
+ p = list;
+ }
+ if (p)
+ free(p);
+
+ return info;
+ }
+
case ARGTYPE_STRING:
if (!isdigit(**str) && **str != '[') {
/* Oops, was just a simple string after all */
@@ -217,6 +322,7 @@ static arg_type_info *parse_nonpointer_type(char **str)
output_line(0, "Syntax error in `%s', line %d: Unknown type encountered",
filename, line_no);
free(info);
+ error_count++;
return NULL;
}
}
@@ -258,6 +364,7 @@ static struct function *process_line(char *buf)
if (!tmp) {
output_line(0, "Syntax error in `%s', line %d", filename,
line_no);
+ error_count++;
return NULL;
}
*tmp = '\0';
@@ -281,6 +388,7 @@ static struct function *process_line(char *buf)
output_line(0, "Syntax error in `%s', line %d"
": unknown argument type",
filename, line_no);
+ error_count++;
return NULL;
}
eat_spaces(&str);
@@ -294,6 +402,7 @@ static struct function *process_line(char *buf)
str[strlen(str) - 1] = '\0';
output_line(0, "Syntax error in `%s', line %d at ...\"%s\"",
filename, line_no, str);
+ error_count++;
return NULL;
}
}
@@ -318,7 +427,10 @@ void read_config_file(char *file)
}
line_no = 0;
while (fgets(buf, 1024, stream)) {
- struct function *tmp = process_line(buf);
+ struct function *tmp;
+
+ error_count = 0;
+ tmp = process_line(buf);
if (tmp) {
debug(2, "New function: `%s'", tmp->name);
diff --git a/testsuite/ltrace.main/parameters-lib.c b/testsuite/ltrace.main/parameters-lib.c
index bc320cf..b43de08 100644
--- a/testsuite/ltrace.main/parameters-lib.c
+++ b/testsuite/ltrace.main/parameters-lib.c
@@ -36,3 +36,8 @@ void func_stringp(char** sP)
{
printf("%s\n", *sP);
}
+
+void func_enum(int x)
+{
+ printf("enum: %d\n", x);
+}
diff --git a/testsuite/ltrace.main/parameters.c b/testsuite/ltrace.main/parameters.c
index e26e0a6..d7c225f 100644
--- a/testsuite/ltrace.main/parameters.c
+++ b/testsuite/ltrace.main/parameters.c
@@ -20,6 +20,15 @@ void func_strfixed(char*);
void func_ppp(int***);
void func_stringp(char**);
+typedef enum {
+ RED,
+ GREEN,
+ BLUE,
+ CHARTREUSE,
+ PETUNIA
+} color_t;
+void func_enum(color_t);
+
int
main ()
{
@@ -27,18 +36,27 @@ main ()
int *xP, **xPP;
char buf[200];
char *s;
+
func_ignore(1, 2, 3);
+
func_intptr(&x);
+
func_intptr_ret(&x);
+
func_strlen(buf);
printf("%s\n", buf);
+
func_strfixed(buf);
printf("%s\n", buf);
+
x = 80;
xP = &x;
xPP = &xP;
func_ppp(&xPP);
+
s = (char*) malloc(100);
strcpy(s, "Dude");
func_stringp(&s);
+
+ func_enum(BLUE);
}
diff --git a/testsuite/ltrace.main/parameters.conf b/testsuite/ltrace.main/parameters.conf
index 7690f89..debb1dc 100644
--- a/testsuite/ltrace.main/parameters.conf
+++ b/testsuite/ltrace.main/parameters.conf
@@ -5,3 +5,4 @@ int func_strlen(+string[retval])
void func_strfixed(string[4])
void func_ppp(int***)
void func_stringp(string*)
+void func_enum(enum (RED=0,GREEN=1,BLUE=2,CHARTREUSE=3,PETUNIA=4))
diff --git a/testsuite/ltrace.main/parameters.exp b/testsuite/ltrace.main/parameters.exp
index 21a02b4..024c3f3 100644
--- a/testsuite/ltrace.main/parameters.exp
+++ b/testsuite/ltrace.main/parameters.exp
@@ -50,3 +50,5 @@ set pattern "func_ppp(80)"
ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace $pattern 1
set pattern "func_stringp(\\\"Dude\\\")"
ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace $pattern 1
+set pattern "func_enum(BLUE)"
+ltrace_verify_output ${srcdir}/${subdir}/${testfile}.ltrace $pattern 1