[Ltrace-devel] [PATCH 2/11] string[argN]

Steve Fink sphink at gmail.com
Sat Aug 5 23:54:43 UTC 2006


-------------- next part --------------
From 1c01ce80c69ac100bc0bb714c31aa181ba45e7f5 Mon Sep 17 00:00:00 2001
From: Steve Fink sphink at gmail.com <sphink at gmail.com>
Date: Sat, 22 Jul 2006 21:39:30 -0700
Subject: [PATCH 2/11] parameter specs string[argN], string[retval], and string[N]

Implement argument spec string[argN], equivalent to the preexisting
stringN, except that N is now unlimited. Also, string[retval] can
be used in place of string0 or string[arg0].

In addition, string[N] can be used to give a fixed max length.
---
 ChangeLog          |    4 ++
 display_args.c     |   68 ++++++++++++++++++----------------------
 etc/ltrace.conf    |   11 +++++--
 ltrace.h           |   10 +-----
 read_config_file.c |   88 +++++++++++++++++++++++++++++++++++++++++++---------
 5 files changed, 119 insertions(+), 62 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f23e7cd..2b2443c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2006-07-20    Steve Fink <sphink at gmail.com>
+
+	* Implement string[argN] and string[N] parameter descriptors.
+
 2006-07-27    Steve Fink <sphink at gmail.com>
 
 	* read_config_file.c: use arg_type_info in place of arg_type in
diff --git a/display_args.c b/display_args.c
index 083c9dc..1c15f22 100644
--- a/display_args.c
+++ b/display_args.c
@@ -11,19 +11,29 @@ #include "ltrace.h"
 #include "options.h"
 
 static int display_char(int what);
-static int display_string(enum tof type, struct process *proc, int arg_num);
-static int display_stringN(int arg2, enum tof type, struct process *proc,
-			   int arg_num);
+static int display_string(enum tof type, struct process *proc,
+			  int arg_num, arg_type_info *info,
+			  size_t maxlen);
 static int display_unknown(enum tof type, struct process *proc, int arg_num);
 static int display_format(enum tof type, struct process *proc, int arg_num);
 
+static int string_maxlength = INT_MAX;
+
+static long get_length(enum tof type, struct process *proc, int len_spec)
+{
+    if (len_spec > 0)
+	return len_spec;
+    return gimme_arg(type, proc, -len_spec - 1);
+}
+
 int
-display_arg(enum tof type, struct process *proc, int arg_num, enum arg_type at)
+display_arg(enum tof type, struct process *proc,
+	    int arg_num, arg_type_info *info)
 {
 	int tmp;
 	long arg;
 
-	switch (at) {
+	switch (info->type) {
 	case ARGTYPE_VOID:
 		return 0;
 	case ARGTYPE_INT:
@@ -62,19 +72,12 @@ display_arg(enum tof type, struct proces
 	case ARGTYPE_FORMAT:
 		return display_format(type, proc, arg_num);
 	case ARGTYPE_STRING:
-		return display_string(type, proc, arg_num);
-	case ARGTYPE_STRING0:
-		return display_stringN(0, type, proc, arg_num);
-	case ARGTYPE_STRING1:
-		return display_stringN(1, type, proc, arg_num);
-	case ARGTYPE_STRING2:
-		return display_stringN(2, type, proc, arg_num);
-	case ARGTYPE_STRING3:
-		return display_stringN(3, type, proc, arg_num);
-	case ARGTYPE_STRING4:
-		return display_stringN(4, type, proc, arg_num);
-	case ARGTYPE_STRING5:
-		return display_stringN(5, type, proc, arg_num);
+		return display_string(type, proc, arg_num, info,
+				      string_maxlength);
+	case ARGTYPE_STRING_N:
+		return display_string(type, proc, arg_num, info,
+				      get_length(type, proc,
+						 info->u.string_n_info.size_spec));
 	case ARGTYPE_UNKNOWN:
 	default:
 		return display_unknown(type, proc, arg_num);
@@ -106,11 +109,10 @@ static int display_char(int what)
 	}
 }
 
-static int string_maxlength = INT_MAX;
-
 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
 
-static int display_string(enum tof type, struct process *proc, int arg_num)
+static int display_string(enum tof type, struct process *proc,
+			  int arg_num, arg_type_info *info, size_t maxlength)
 {
 	void *addr;
 	unsigned char *str1;
@@ -122,13 +124,13 @@ static int display_string(enum tof type,
 		return fprintf(output, "NULL");
 	}
 
-	str1 = malloc(MIN(opt_s, string_maxlength) + 3);
+	str1 = malloc(MIN(opt_s, maxlength) + 3);
 	if (!str1) {
 		return fprintf(output, "???");
 	}
-	umovestr(proc, addr, MIN(opt_s, string_maxlength) + 1, str1);
+	umovestr(proc, addr, MIN(opt_s, maxlength) + 1, str1);
 	len = fprintf(output, "\"");
-	for (i = 0; i < MIN(opt_s, string_maxlength); i++) {
+	for (i = 0; i < MIN(opt_s, maxlength); i++) {
 		if (str1[i]) {
 			len += display_char(str1[i]);
 		} else {
@@ -136,24 +138,13 @@ static int display_string(enum tof type,
 		}
 	}
 	len += fprintf(output, "\"");
-	if (str1[i] && (opt_s <= string_maxlength)) {
+	if (str1[i] && (opt_s <= maxlength)) {
 		len += fprintf(output, "...");
 	}
 	free(str1);
 	return len;
 }
 
-static int
-display_stringN(int arg2, enum tof type, struct process *proc, int arg_num)
-{
-	int a;
-
-	string_maxlength = gimme_arg(type, proc, arg2 - 1);
-	a = display_string(type, proc, arg_num);
-	string_maxlength = INT_MAX;
-	return a;
-}
-
 static int display_unknown(enum tof type, struct process *proc, int arg_num)
 {
 	long tmp;
@@ -292,10 +283,13 @@ static int display_format(enum tof type,
 					len += fprintf(output, "'");
 					break;
 				} else if (c == 's') {
+					arg_type_info *info =
+					    lookup_singleton(ARGTYPE_STRING);
 					len += fprintf(output, ", ");
 					len +=
 					    display_string(type, proc,
-							   ++arg_num);
+							   ++arg_num, info,
+							   string_maxlength);
 					break;
 				} else if (c == 'p' || c == 'n') {
 					len +=
diff --git a/etc/ltrace.conf b/etc/ltrace.conf
index 5c85e19..29c50ec 100644
--- a/etc/ltrace.conf
+++ b/etc/ltrace.conf
@@ -18,7 +18,14 @@
 ; file		== (FILE *)						[TODO]
 ; format	== ((const char *), ...)	[printf() like]		[TODO]
 ; string	== (char *)
-; stringN	== (char *)		[N>=0]	[show only up to (arg N) bytes]
+; string[argN]  == (char *)		[N>0]	[show only up to (arg N) bytes]
+; string[retval] == (char *)			[show only up to (return val) bytes]
+; string[arg0]	== (char *)			[same as string[retval]]
+; string[N]     == (char *)             [N>0]   [show only up to N bytes]
+
+; Backwards-compatibility:
+; string0	== (char *)			[same as string[retval]]
+; stringN	== (char *)		[N>0]	[same as string[argN]]
 
 ; arpa/inet.h
 int inet_aton(string,addr);
@@ -338,7 +345,7 @@ int getpgid(int);
 int isatty(int);
 int link(string,string);
 int mkdir(string,octal);
-long read(int, +string0, ulong);
+long read(int, +string[retval], ulong);
 int rmdir(string);
 int seteuid(uint);
 int setgid(int);
diff --git a/ltrace.h b/ltrace.h
index 5561139..dec2e0b 100644
--- a/ltrace.h
+++ b/ltrace.h
@@ -40,14 +40,8 @@ enum arg_type {
 	ARGTYPE_ADDR,
 	ARGTYPE_FILE,
 	ARGTYPE_FORMAT,		/* printf-like format */
-	ARGTYPE_STRING,
-	ARGTYPE_STRING_N,	/* stringN: string up to (arg N) bytes */
-        ARGTYPE_STRING0,
-        ARGTYPE_STRING1,
-        ARGTYPE_STRING2,
-        ARGTYPE_STRING3,
-        ARGTYPE_STRING4,
-        ARGTYPE_STRING5,
+	ARGTYPE_STRING,		/* NUL-terminated string */
+	ARGTYPE_STRING_N,	/* String of known maxlen */
         ARGTYPE_COUNT		/* number of ARGTYPE_* values */
 };
 
diff --git a/read_config_file.c b/read_config_file.c
index 089d69a..6c9eb5d 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -29,12 +29,6 @@ static struct list_of_pt_t {
 	"file", ARGTYPE_FILE}, {
 	"format", ARGTYPE_FORMAT}, {
 	"string", ARGTYPE_STRING}, {
-	"string0", ARGTYPE_STRING0}, {
-	"string1", ARGTYPE_STRING1}, {
-	"string2", ARGTYPE_STRING2}, {
-	"string3", ARGTYPE_STRING3}, {
-	"string4", ARGTYPE_STRING4}, {
-	"string5", ARGTYPE_STRING5}, {
 	NULL, ARGTYPE_UNKNOWN}	/* Must finish with NULL */
 };
 
@@ -51,12 +45,6 @@ static arg_type_info arg_type_singletons
 	{ ARGTYPE_FORMAT },
 	{ ARGTYPE_STRING },
 	{ ARGTYPE_STRING_N },
-	{ ARGTYPE_STRING0 },
-	{ ARGTYPE_STRING1 },
-	{ ARGTYPE_STRING2 },
-	{ ARGTYPE_STRING3 },
-	{ ARGTYPE_STRING4 },
-	{ ARGTYPE_STRING5 },
 	{ ARGTYPE_UNKNOWN }
 };
 
@@ -74,7 +62,7 @@ static arg_type_info *str2type(char **st
 
 	while (tmp->name) {
 		if (!strncmp(*str, tmp->name, strlen(tmp->name))
-		    && index(" ,)#", *(*str + strlen(tmp->name)))) {
+		    && index(" ,()#;012345[", *(*str + strlen(tmp->name)))) {
 			*str += strlen(tmp->name);
 			return lookup_singleton(tmp->pt);
 		}
@@ -134,6 +122,51 @@ static int simple_type(enum arg_type at)
 static int line_no;
 static char *filename;
 
+static int parse_int(char **str)
+{
+    char *end;
+    long n = strtol(*str, &end, 0);
+    if (end == *str) {
+	output_line(0, "Syntax error in `%s', line %d: Bad number",
+		    filename, line_no);
+	return 0;
+    }
+
+    *str = end;
+    return n;
+}
+
+/*
+ * Input:
+ *  argN   : The value of argument #N, counting from 1 (arg0 = retval)
+ *  eltN   : The value of element #N of the containing structure
+ *  retval : The return value
+ *  0      : Error
+ *  N      : The numeric value N, if N > 0
+ *
+ * Output:
+ * > 0   actual numeric value
+ * = 0   return value
+ * < 0   (arg -n), counting from one
+ */
+static int parse_argnum(char **str)
+{
+    int multiplier = 1;
+    int n = 0;
+
+    if (strncmp(*str, "arg", 3) == 0) {
+	(*str) += 3;
+	multiplier = -1;
+    } else if (strncmp(*str, "retval", 6) == 0) {
+	(*str) += 6;
+	return 0;
+    }
+
+    n = parse_int(str);
+
+    return n * multiplier;
+}
+
 static arg_type_info *parse_type(char **str)
 {
 	arg_type_info *simple;
@@ -144,7 +177,7 @@ static arg_type_info *parse_type(char **
 		return simple;		// UNKNOWN
 	}
 
-	if (simple_type(simple->type))
+	if (simple_type(simple->type) && simple->type != ARGTYPE_STRING)
 		return simple;
 
 	info = malloc(sizeof(*info));
@@ -154,6 +187,29 @@ static arg_type_info *parse_type(char **
 	   switch statement. */
 
 	switch (info->type) {
+
+	case ARGTYPE_STRING:
+	    if (!isdigit(**str) && **str != '[') {
+		/* Oops, was just a simple string after all */
+		free(info);
+		return simple;
+	    }
+
+	    info->type = ARGTYPE_STRING_N;
+
+	    /* Backwards compatibility for string0, string1, ... */
+	    if (isdigit(**str)) {
+		info->u.string_n_info.size_spec = -parse_int(str);
+		return info;
+	    }
+
+	    (*str)++;		// Skip past opening [
+	    eat_spaces(str);
+	    info->u.string_n_info.size_spec = parse_argnum(str);
+	    eat_spaces(str);
+	    (*str)++;		// Skip past closing ]
+	    return info;
+
 	default:
 		output_line(0, "Syntax error in `%s', line %d: Unknown type encountered",
 			    filename, line_no);
@@ -174,7 +230,9 @@ static struct function *process_line(cha
 	debug(3, "Reading line %d of `%s'", line_no, filename);
 	eat_spaces(&str);
 	fun.return_info = parse_type(&str);
-	if (fun.return_info == NULL) {
+	if (fun.return_info == NULL)
+        	return NULL;
+	if (fun.return_info->type == ARGTYPE_UNKNOWN) {
 		debug(3, " Skipping line %d", line_no);
 		return NULL;
 	}
-- 
1.4.1


More information about the Ltrace-devel mailing list