Drop ARGTYPE_STRING, reimplement as lens over array of chars
diff --git a/ChangeLog b/ChangeLog
index 67564bd..06e70b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2012-01-09 Petr Machata <pmachata@redhat.com>
+ * lens_default.c, lens_default.h (string_lens): New global variable
+ (format_naked_char): New function
+ * type.h, type.c (enum arg_type): Drop ARGTYPE_STRING
+ (type_init_string): Drop
+ * printf.c: Drop handling of ARGTYPE_STRING
+ * read_config_file.c: Likewise; support lens syntax of "string"
+ * value.c, value.h (value_string_to_charp): Drop
+
+2012-01-09 Petr Machata <pmachata@redhat.com>
+
* read_config_file.c (try_parse_kwd): New function
(name2lens, parse_alias): Use it
diff --git a/lens_default.c b/lens_default.c
index e55aae6..f4e2bd8 100644
--- a/lens_default.c
+++ b/lens_default.c
@@ -141,15 +141,7 @@
return -1;
int c = (int)lc;
- /* If this value is not wrapped in array, then this is not a
- * string, and we need to display quotes. */
- int quote = !(value->parent != NULL
- && (value->parent->type->type == ARGTYPE_ARRAY
- || value->parent->type->type == ARGTYPE_STRING_N));
int written = 0;
- if (quote && acc_fprintf(&written, stream, "'") < 0)
- return -1;
-
const char *fmt;
switch (c) {
case -1:
@@ -194,8 +186,19 @@
if (fmt != NULL && acc_fprintf(&written, stream, fmt, c) < 0)
return -1;
- if (quote && acc_fprintf(&written, stream, "'") < 0)
+ return written;
+}
+
+static int
+format_naked_char(FILE *stream, struct value *value,
+ struct value_dict *arguments)
+{
+ int written = 0;
+ if (acc_fprintf(&written, stream, "'") < 0
+ || format_char(stream, value, arguments) < 0
+ || acc_fprintf(&written, stream, "'") < 0)
return -1;
+
return written;
}
@@ -313,9 +316,6 @@
enum int_fmt_t int_fmt)
{
switch (value->type->type) {
- struct value *tmp;
- int ret;
-
case ARGTYPE_VOID:
return fprintf(stream, "<void>");
@@ -332,7 +332,7 @@
return format_integer(stream, value, int_fmt, arguments);
case ARGTYPE_CHAR:
- return format_char(stream, value, arguments);
+ return format_naked_char(stream, value, arguments);
case ARGTYPE_FLOAT:
case ARGTYPE_DOUBLE:
@@ -347,23 +347,9 @@
return format_integer(stream, value, INT_FMT_x, arguments);
case ARGTYPE_ARRAY:
- if (value->type->u.array_info.elt_type->type != ARGTYPE_CHAR)
- return format_array(stream, value, arguments,
- value->type->u.array_info.length,
- options.arraylen, 1,
- "[ ", " ]", ", ");
-
return format_array(stream, value, arguments,
value->type->u.array_info.length,
- options.strlen, 0, "\"", "\"", "");
-
- case ARGTYPE_STRING_N:
- tmp = value_string_to_charp(value);
- if (tmp == NULL)
- return -1;
- ret = format_argument(stream, tmp, arguments);
- value_destroy(tmp);
- return ret;
+ options.arraylen, 1, "[ ", " ]", ", ");
case ARGTYPE_ENUM:
return format_enum(stream, value, arguments);
@@ -430,3 +416,65 @@
struct lens guess_lens = {
.format_cb = guess_lens_format_cb,
};
+
+
+static int
+string_lens_format_cb(struct lens *lens, FILE *stream,
+ struct value *value, struct value_dict *arguments)
+{
+ switch (value->type->type) {
+ case ARGTYPE_POINTER:
+ /* This should really be written as either "string",
+ * or, if lens, then string(array(char, zero)*). But
+ * I suspect people are so used to the char * C idiom,
+ * that string(char *) might actually turn up. So
+ * let's just support it. */
+ if (value->type->u.ptr_info.info->type == ARGTYPE_CHAR) {
+ struct arg_type_info info[2];
+ type_init_array(&info[1],
+ value->type->u.ptr_info.info, 0,
+ expr_node_zero(), 0);
+ type_init_pointer(&info[0], &info[1], 0);
+ info->lens = lens;
+ info->own_lens = 0;
+ struct value tmp;
+ if (value_clone(&tmp, value) < 0)
+ return -1;
+ value_set_type(&tmp, info, 0);
+ int ret = string_lens_format_cb(lens, stream, &tmp,
+ arguments);
+ type_destroy(&info[0]);
+ type_destroy(&info[1]);
+ value_destroy(&tmp);
+ return ret;
+ }
+
+ /* fall-through */
+ case ARGTYPE_VOID:
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ case ARGTYPE_STRUCT:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_ENUM:
+ return toplevel_format_lens(lens, stream, value,
+ arguments, INT_FMT_i);
+
+ case ARGTYPE_CHAR:
+ return format_char(stream, value, arguments);
+
+ case ARGTYPE_ARRAY:
+ return format_array(stream, value, arguments,
+ value->type->u.array_info.length,
+ options.strlen, 0, "\"", "\"", "");
+ }
+ abort();
+}
+
+struct lens string_lens = {
+ .format_cb = string_lens_format_cb,
+};
diff --git a/lens_default.h b/lens_default.h
index e84fd3e..7895a91 100644
--- a/lens_default.h
+++ b/lens_default.h
@@ -40,4 +40,7 @@
* formatted in decimal). */
extern struct lens guess_lens;
+/* A lens for strings. */
+extern struct lens string_lens;
+
#endif /* LENS_DEFAULT_H */
diff --git a/printf.c b/printf.c
index 748c0d0..a3d7b30 100644
--- a/printf.c
+++ b/printf.c
@@ -30,6 +30,7 @@
#include "expr.h"
#include "zero.h"
#include "param.h"
+#include "lens_default.h"
struct param_enum {
struct value array;
@@ -47,11 +48,10 @@
assert(nargs == 1);
/* We expect a char array pointer. */
- if (cb_args->type->type != ARGTYPE_STRING_N
- && (cb_args->type->type != ARGTYPE_POINTER
- || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY
- || (cb_args->type->u.ptr_info.info->u.array_info.elt_type->type
- != ARGTYPE_CHAR)))
+ if (cb_args->type->type != ARGTYPE_POINTER
+ || cb_args->type->u.ptr_info.info->type != ARGTYPE_ARRAY
+ || (cb_args->type->u.ptr_info.info->u.array_info.elt_type->type
+ != ARGTYPE_CHAR))
return NULL;
struct param_enum *self = malloc(sizeof(*self));
@@ -61,18 +61,7 @@
return NULL;
}
- if (cb_args->type->type == ARGTYPE_STRING_N) {
- struct value *tmp = value_string_to_charp(cb_args);
- if (tmp == NULL)
- goto fail;
-
- if (value_init_deref(&self->array, tmp) < 0) {
- value_destroy(tmp);
- goto fail;
- }
- free(tmp);
-
- } else if (value_init_deref(&self->array, cb_args) < 0)
+ if (value_init_deref(&self->array, cb_args) < 0)
goto fail;
assert(self->array.type->type == ARGTYPE_ARRAY);
@@ -294,6 +283,7 @@
/* XXX "ls" means wchar_t string. */
elt_type = ARGTYPE_CHAR;
self->percent = 0;
+ lens = &string_lens;
break;
case 'p':
diff --git a/read_config_file.c b/read_config_file.c
index e59df92..bb133b3 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -449,9 +449,9 @@
}
static int
-parse_string(char **str, struct arg_type_info **retp)
+parse_string(char **str, struct arg_type_info **retp, int *ownp)
{
- struct arg_type_info *info = malloc(sizeof(*info));
+ struct arg_type_info *info = malloc(sizeof(*info) * 2);
if (info == NULL) {
fail:
free(info);
@@ -460,6 +460,7 @@
struct expr_node *length;
int own_length;
+ int with_arg = 0;
if (isdigit(**str)) {
/* string0 is string[retval], length is zero(retval)
@@ -500,6 +501,22 @@
eat_spaces(str);
parse_char(str, ']');
+ } else if (**str == '(') {
+ /* Usage of "string" as lens. */
+ ++*str;
+
+ free(info);
+
+ eat_spaces(str);
+ info = parse_type(str, NULL, 0, ownp);
+ if (info == NULL)
+ goto fail;
+
+ eat_spaces(str);
+ parse_char(str, ')');
+
+ with_arg = 1;
+
} else {
/* It was just a simple string after all. */
length = expr_node_zero();
@@ -508,7 +525,16 @@
}
/* String is a pointer to array of chars. */
- type_init_string(info, length, own_length);
+ if (!with_arg) {
+ type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0,
+ length, own_length);
+
+ type_init_pointer(&info[0], &info[1], 0);
+ *ownp = 1;
+ }
+
+ info->lens = &string_lens;
+ info->own_lens = 0;
*retp = info;
return 0;
@@ -594,7 +620,7 @@
* "string" is syntax. */
if (strncmp(*str, "string", 6) == 0) {
(*str) += 6;
- return parse_string(str, retp);
+ return parse_string(str, retp, ownp);
} else if (try_parse_kwd(str, "format") >= 0
&& extra_param != NULL) {
@@ -602,7 +628,7 @@
* "string", but it smuggles to the parameter list of
* a function a "printf" argument pack with this
* parameter as argument. */
- if (parse_string(str, retp) < 0)
+ if (parse_string(str, retp, ownp) < 0)
return -1;
return build_printf_pack(extra_param, param_num);
@@ -748,12 +774,6 @@
parser = parse_struct;
break;
- case ARGTYPE_STRING_N:
- /* Strings are handled in aliases, to support
- * "stringN" syntax cleanly. */
- assert(type != ARGTYPE_STRING_N);
- abort();
-
case ARGTYPE_POINTER:
/* Pointer syntax is not based on keyword, so we
* should never get this type. */
diff --git a/testsuite/ltrace.main/parameters-lib.c b/testsuite/ltrace.main/parameters-lib.c
index 54e6a91..d3ad69c 100644
--- a/testsuite/ltrace.main/parameters-lib.c
+++ b/testsuite/ltrace.main/parameters-lib.c
@@ -207,3 +207,19 @@
func_lens(int a, long b, short c, long d)
{
}
+
+int
+func_bool(int a, int b)
+{
+ return !b;
+}
+
+void
+func_hide(int a, int b, int c, int d, int e, int f)
+{
+}
+
+void
+func_charp_string(char *p)
+{
+}
diff --git a/testsuite/ltrace.main/parameters.c b/testsuite/ltrace.main/parameters.c
index 0377b73..5a3f6b2 100644
--- a/testsuite/ltrace.main/parameters.c
+++ b/testsuite/ltrace.main/parameters.c
@@ -200,5 +200,15 @@
void func_lens(int, long, short, long);
func_lens(22, 23, 24, 25);
+ int func_bool(int a, int b);
+ func_bool(1, 10);
+ func_bool(2, 0);
+
+ void func_hide(int a, int b, int c, int d, int e, int f);
+ func_hide(1, 2, 3, 4, 5, 6);
+
+ void func_charp_string(char *p);
+ func_charp_string("null-terminated string");
+
return 0;
}
diff --git a/testsuite/ltrace.main/parameters.conf b/testsuite/ltrace.main/parameters.conf
index 3f8fea5..419ad1f 100644
--- a/testsuite/ltrace.main/parameters.conf
+++ b/testsuite/ltrace.main/parameters.conf
@@ -17,10 +17,13 @@
void func_struct(struct(int,int,int,array(struct(int,int),elt2)*,array(struct(int,int),3),string[elt3])*)
void func_work(+string);
void func_call(+string, string);
-struct(float,char,char) func_struct_2(int, struct(array(char, 6),float), double);
+struct(float,char,char) func_struct_2(int, struct(string(array(char, 6)),float), double);
struct(long,long,long,long) func_struct_large(struct(long,long,long,long), struct(long,long,long,long));
struct(char,char,long,long) func_struct_large2(struct(char,char,long,long), struct(char,char,long,long));
struct(long,long,char,char) func_struct_large3(struct(long,long,char,char), struct(long,long,char,char));
void func_many_args(int, int, long, double, char, int, float, char, int, double, int, double, char, int, short, int, char, float, float, double, long, float, float, float, float);
int printf(format);
void func_lens(octal, octal(long), hex(short), hex(long));
+bool(int) func_bool(int, bool(int));
+void func_hide(int, hide(int), hide(int), int, hide(int), int);
+void func_charp_string(string(char *));
diff --git a/testsuite/ltrace.main/parameters.exp b/testsuite/ltrace.main/parameters.exp
index 8975abe..9be7b58 100644
--- a/testsuite/ltrace.main/parameters.exp
+++ b/testsuite/ltrace.main/parameters.exp
@@ -117,3 +117,15 @@
set pattern "func_lens(026, 027, 0x18, 0x19)"
ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
+
+set pattern "func_bool(1, true).*= false"
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
+
+set pattern "func_bool(2, false).*= true"
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
+
+set pattern "func_hide(1, 4, 6)"
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
+
+set pattern "func_charp_string(\\\"null-terminated string\\\")"
+ltrace_verify_output ${objdir}/${subdir}/${testfile}.ltrace $pattern 1
diff --git a/type.c b/type.c
index 81c597f..00775aa 100644
--- a/type.c
+++ b/type.c
@@ -50,8 +50,6 @@
#undef HANDLE
- case ARGTYPE_STRING_N:
-
case ARGTYPE_ARRAY:
case ARGTYPE_ENUM:
case ARGTYPE_STRUCT:
@@ -243,15 +241,6 @@
info->u.array_info.own_length = own_length;
}
-void
-type_init_string(struct arg_type_info *info,
- struct expr_node *length_expr, int own_length)
-{
- type_init_common(info, ARGTYPE_STRING_N);
- info->u.string_n_info.length = length_expr;
- info->u.string_n_info.own_length = own_length;
-}
-
static void
type_array_destroy(struct arg_type_info *info)
{
@@ -265,15 +254,6 @@
}
}
-static void
-type_string_n_destroy(struct arg_type_info *info)
-{
- if (info->u.array_info.own_length) {
- expr_destroy(info->u.string_n_info.length);
- free(info->u.string_n_info.length);
- }
-}
-
void
type_init_pointer(struct arg_type_info *info,
struct arg_type_info *pointee_info, int own_info)
@@ -315,9 +295,6 @@
type_pointer_destroy(info);
break;
- case ARGTYPE_STRING_N:
- type_string_n_destroy(info);
-
case ARGTYPE_VOID:
case ARGTYPE_INT:
case ARGTYPE_UINT:
@@ -408,8 +385,6 @@
return (size_t)-1;
return size;
- case ARGTYPE_STRING_N:
- /* String is a char* in disguise. */
case ARGTYPE_POINTER:
return sizeof(void *);
@@ -502,9 +477,7 @@
type_offsetof(struct Process *proc, struct arg_type_info *type, size_t emt)
{
assert(type->type == ARGTYPE_STRUCT
- || type->type == ARGTYPE_ARRAY
- /* XXX Temporary, this will be removed. */
- || type->type == ARGTYPE_STRING_N);
+ || type->type == ARGTYPE_ARRAY);
switch (type->type) {
size_t alignment;
@@ -520,16 +493,13 @@
return emt * align(size, alignment);
- case ARGTYPE_STRING_N:
- return emt;
-
case ARGTYPE_STRUCT:
if (layout_struct(proc, type, NULL, NULL, &emt) < 0)
return (size_t)-1;
return emt;
default:
- abort ();
+ abort();
}
}
@@ -537,9 +507,7 @@
type_element(struct arg_type_info *info, size_t emt)
{
assert(info->type == ARGTYPE_STRUCT
- || info->type == ARGTYPE_ARRAY
- /* XXX Temporary, this will be removed. */
- || info->type == ARGTYPE_STRING_N);
+ || info->type == ARGTYPE_ARRAY);
switch (info->type) {
case ARGTYPE_ARRAY:
@@ -549,10 +517,7 @@
assert(emt < type_struct_size(info));
return type_struct_get(info, emt);
- case ARGTYPE_STRING_N:
- return type_get_simple(ARGTYPE_CHAR);
-
default:
- abort ();
+ abort();
}
}
diff --git a/type.h b/type.h
index 5aff71f..d0b106f 100644
--- a/type.h
+++ b/type.h
@@ -37,7 +37,6 @@
ARGTYPE_USHORT,
ARGTYPE_FLOAT,
ARGTYPE_DOUBLE,
- ARGTYPE_STRING_N, /* String of known maxlen */
ARGTYPE_ARRAY, /* Series of values in memory */
ARGTYPE_ENUM, /* Enumeration */
ARGTYPE_STRUCT, /* Structure of values */
@@ -57,12 +56,6 @@
int own_length:1;
} array_info;
- /* ARGTYPE_STRING_N */
- struct {
- struct expr_node *length;
- int own_length:1;
- } string_n_info;
-
/* ARGTYPE_POINTER */
struct {
struct arg_type_info *info;
@@ -120,12 +113,6 @@
struct arg_type_info *element_info, int own_info,
struct expr_node *length_expr, int own_length);
-/* Initialize INFO so it becomes ARGTYPE_STRING_N. Length is passed
- * in LENGTH_EXPR. If OWN_LENGTH is true, the length is owned and
- * destroyed together with INFO. */
-void type_init_string(struct arg_type_info *info,
- struct expr_node *length, int own_length);
-
/* Initialize INFO so it becomes ARGTYPE_POINTER. The pointee type is
* passed in POINTEE_INFO. If OWN_INFO, the pointee type is owned and
* destroyed together with INFO. */
diff --git a/value.c b/value.c
index 58e36c1..49e2f2c 100644
--- a/value.c
+++ b/value.c
@@ -199,28 +199,6 @@
return 0;
}
-struct value *
-value_string_to_charp(struct value *value)
-{
- struct arg_type_info *info = malloc(sizeof(*info) * 2);
- if (info == NULL) {
- fail:
- free(info);
- return NULL;
- }
- type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0,
- value->type->u.string_n_info.length, 0);
- type_init_pointer(&info[0], &info[1], 0);
-
- struct value *tmp = malloc(sizeof(*tmp));
- if (tmp == NULL)
- goto fail;
-
- value_clone(tmp, value);
- value_set_type(tmp, info, 1);
- return tmp;
-}
-
size_t
value_size(struct value *val, struct value_dict *arguments)
{
diff --git a/value.h b/value.h
index f3238b6..e88b72a 100644
--- a/value.h
+++ b/value.h
@@ -149,10 +149,4 @@
* if it isn't, <0 on error. */
int value_is_zero(struct value *val, struct value_dict *arguments);
-/* Take a VALUE of type ARGTYPE_STRING_N, and allocate a new value
- * that is ARGTYPE_POINTER to ARGTYPE_CHAR with the same length
- * expression. Returns NULL on failure or a value, which you need to
- * free properly (i.e. call value_destroy and free). */
-struct value *value_string_to_charp(struct value *value);
-
#endif /* VALUE_H */