Drop ARGTYPE_UNKNOWN, use guess_lens instead
diff --git a/ChangeLog b/ChangeLog
index 773fc94..d35adc0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2012-01-08  Petr Machata  <pmachata@redhat.com>
 
+	* lens_default.c, lens_default.h (guess_lens): New global variable
+	* type.h, type.c (enum arg_type): Drop ARGTYPE_UNKNOWN
+	* read_config_file.c, printf.c: Adjust to above changes
+	* output.c: Likewise
+	(get_unknown_type): New function
+
+2012-01-08  Petr Machata  <pmachata@redhat.com>
+
 	* lens_default.c, lens_default.h (hex_lens, octal_lens): New
 	global variables
 	* read_config_file.c: Use it
diff --git a/lens_default.c b/lens_default.c
index 2693734..e55aae6 100644
--- a/lens_default.c
+++ b/lens_default.c
@@ -319,10 +319,6 @@
 	case ARGTYPE_VOID:
 		return fprintf(stream, "<void>");
 
-	case ARGTYPE_UNKNOWN:
-		return format_integer(stream, value, INT_FMT_unknown,
-				      arguments);
-
 	case ARGTYPE_SHORT:
 	case ARGTYPE_INT:
 	case ARGTYPE_LONG:
@@ -421,3 +417,16 @@
 struct lens hex_lens = {
 	.format_cb = hex_lens_format_cb,
 };
+
+
+static int
+guess_lens_format_cb(struct lens *lens, FILE *stream,
+		     struct value *value, struct value_dict *arguments)
+{
+	return toplevel_format_lens(lens, stream, value, arguments,
+				    INT_FMT_unknown);
+}
+
+struct lens guess_lens = {
+	.format_cb = guess_lens_format_cb,
+};
diff --git a/lens_default.h b/lens_default.h
index 9269fea..e84fd3e 100644
--- a/lens_default.h
+++ b/lens_default.h
@@ -35,4 +35,9 @@
 /* A lens that formats integers in hexadecimal.  */
 extern struct lens hex_lens;
 
+/* A lens that tries to guess whether the value is "large" (i.e. a
+ * pointer, and should be formatted in hex), or "small" (and should be
+ * formatted in decimal).  */
+extern struct lens guess_lens;
+
 #endif /* LENS_DEFAULT_H */
diff --git a/output.c b/output.c
index 0276b25..3151701 100644
--- a/output.c
+++ b/output.c
@@ -42,6 +42,7 @@
 #include "value_dict.h"
 #include "param.h"
 #include "fetch.h"
+#include "lens_default.h"
 
 /* TODO FIXME XXX: include in common.h: */
 extern struct timeval current_time_spent;
@@ -129,6 +130,22 @@
 	}
 }
 
+static struct arg_type_info *
+get_unknown_type(void)
+{
+	static struct arg_type_info *info = NULL;
+	if (info == NULL) {
+		info = malloc(sizeof(*info));
+		if (info == NULL) {
+			report_global_error("malloc: %s", strerror(errno));
+			abort();
+		}
+		*info = *type_get_simple(ARGTYPE_LONG);
+		info->lens = &guess_lens;
+	}
+	return info;
+}
+
 /* The default prototype is: long X(long, long, long, long).  */
 static Function *
 build_default_prototype(void)
@@ -139,7 +156,7 @@
 		goto err;
 	memset(ret, 0, sizeof(*ret));
 
-	struct arg_type_info *unknown_type = type_get_simple(ARGTYPE_UNKNOWN);
+	struct arg_type_info *unknown_type = get_unknown_type();
 
 	ret->return_info = unknown_type;
 	ret->own_return_info = 0;
@@ -248,6 +265,7 @@
 		struct arg_type_info *tmp = malloc(sizeof(*tmp));
 		if (tmp != NULL) {
 			type_init_pointer(tmp, info, 0);
+			tmp->lens = info->lens;
 			info = tmp;
 			own = 1;
 		}
diff --git a/printf.c b/printf.c
index 34d2813..748c0d0 100644
--- a/printf.c
+++ b/printf.c
@@ -119,10 +119,9 @@
 		  ARGTYPE_ULONG, ARGTYPE_ULONG };
 
 	struct arg_type_info *elt_info = NULL;
-	if (elt_type != ARGTYPE_UNKNOWN)
+	if (format_type == ARGTYPE_ARRAY || format_type == ARGTYPE_POINTER)
 		elt_info = type_get_simple(elt_type);
-
-	if (format_type == ARGTYPE_INT)
+	else if (format_type == ARGTYPE_INT)
 		format_type = ints[2 + lng - hlf];
 	else if (format_type == ARGTYPE_UINT)
 		format_type = uints[2 + lng - hlf];
@@ -182,8 +181,8 @@
 {
 	unsigned hlf = 0;
 	unsigned lng = 0;
-	enum arg_type format_type = ARGTYPE_UNKNOWN;
-	enum arg_type elt_type = ARGTYPE_UNKNOWN;
+	enum arg_type format_type = ARGTYPE_VOID;
+	enum arg_type elt_type = ARGTYPE_VOID;
 	char len_buf[25] = {};
 	size_t len_buf_len = 0;
 	struct lens *lens = NULL;
@@ -316,7 +315,7 @@
 		}
 
 		/* If we got here, the type must have been set.  */
-		assert(format_type != ARGTYPE_UNKNOWN);
+		assert(format_type != ARGTYPE_VOID);
 
 		if (form_next_param(self, format_type, elt_type, hlf, lng,
 				    len_buf, len_buf_len, infop) < 0)
diff --git a/read_config_file.c b/read_config_file.c
index 2b82272..0ee9547 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -56,7 +56,7 @@
 parse_arg_type(char **name, enum arg_type *ret)
 {
 	char *rest = NULL;
-	enum arg_type candidate = ARGTYPE_UNKNOWN;
+	enum arg_type candidate;
 
 #define KEYWORD(KWD, TYPE)						\
 	do {								\
@@ -711,7 +711,6 @@
 
 	/* For some types that's all we need.  */
 	switch (type) {
-	case ARGTYPE_UNKNOWN:
 	case ARGTYPE_VOID:
 	case ARGTYPE_INT:
 	case ARGTYPE_UINT:
@@ -773,6 +772,7 @@
 	{ "hide", &blind_lens },
 	{ "octal", &octal_lens },
 	{ "hex", &hex_lens },
+	{ "guess", &guess_lens },
 };
 
 static struct lens *
@@ -917,8 +917,7 @@
 	}
 
 	fun->return_info = parse_lens(&str, NULL, 0, &fun->own_return_info);
-	if (fun->return_info == NULL
-	    || fun->return_info->type == ARGTYPE_UNKNOWN) {
+	if (fun->return_info == NULL) {
 	err:
 		debug(3, " Skipping line %d", line_no);
 		destroy_fun(fun);
diff --git a/type.c b/type.c
index ed3f6d8..81c597f 100644
--- a/type.c
+++ b/type.c
@@ -37,7 +37,6 @@
 	}
 
 	switch (type) {
-	HANDLE(ARGTYPE_UNKNOWN)
 	HANDLE(ARGTYPE_VOID)
 	HANDLE(ARGTYPE_INT)
 	HANDLE(ARGTYPE_UINT)
@@ -319,7 +318,6 @@
 	case ARGTYPE_STRING_N:
 		type_string_n_destroy(info);
 
-	case ARGTYPE_UNKNOWN:
 	case ARGTYPE_VOID:
 	case ARGTYPE_INT:
 	case ARGTYPE_UINT:
@@ -439,11 +437,6 @@
 
 	case ARGTYPE_VOID:
 		return 0;
-
-	/* XXX these are in fact formatting conventions, not
-	 * data types.  They should be handled differently.  */
-	case ARGTYPE_UNKNOWN:
-		return sizeof(long);
 	}
 
 	abort();
diff --git a/type.h b/type.h
index 6ad7094..5aff71f 100644
--- a/type.h
+++ b/type.h
@@ -27,7 +27,6 @@
 #include "vect.h"
 
 enum arg_type {
-	ARGTYPE_UNKNOWN = -1,
 	ARGTYPE_VOID,
 	ARGTYPE_INT,
 	ARGTYPE_UINT,