Allow formatting floats, doubles in hex

Include a test suite case.
Describe the extension in ltrace.conf.5.
Mention it in NEWS.

There's no similar agreed-upon convention for oct, and displaying which
bits are set in a floating number like what bitvect does is certainly not
helpful.  Hence, remove the corresponding TODO item.  Add a different
(unrelated) one instead.
diff --git a/NEWS b/NEWS
index 211bd55..2f30772 100644
--- a/NEWS
+++ b/NEWS
@@ -40,6 +40,8 @@
     For reasons of consistency with "hex".  "octal" is still valid and
     will be for forseeable future.
 
+*** The hex lens can now format floating point arguments
+
 * Version 0.7.0
 ** Tracing
 *** Full support for tracing multi-threaded processes
diff --git a/TODO b/TODO
index 9ce6041..acee057 100644
--- a/TODO
+++ b/TODO
@@ -131,12 +131,8 @@
 
    | typedef ulong = uint8_t |
 
-** Formatting floats, doubles in hex etc.
-   hex(float) should show the floating point number in hex mode.
-   bitvec(float) should show it in binary mode.  (Or perhaps it's
-   desirable to have a separate "bin" lens for this.)  Not sure if
-   there's anything like octal way of showing floats, but oct should
-   be made consistent with hex.
+** Some more functions in vect might be made to take const*
+   Or even marked __attribute__((pure)).
 
 * BUGS
 ** After a clone(), syscalls may be seen as sysrets in s390 (see trace.c:syscall_p())
diff --git a/lens_default.c b/lens_default.c
index 093b803..ed3d0e1 100644
--- a/lens_default.c
+++ b/lens_default.c
@@ -186,7 +186,17 @@
 }
 
 static int
-format_floating(FILE *stream, struct value *value, struct value_dict *arguments)
+format_double(FILE *stream, double value, enum int_fmt_t format)
+{
+	if (format == INT_FMT_x)
+		return fprintf(stream, "%a", value);
+	else
+		return fprintf(stream, "%f", value);
+}
+
+static int
+format_floating(FILE *stream, struct value *value, struct value_dict *arguments,
+		enum int_fmt_t format)
 {
 	switch (value->type->type) {
 		float f;
@@ -194,11 +204,11 @@
 	case ARGTYPE_FLOAT:
 		if (read_float(value, &f, arguments) < 0)
 			return -1;
-		return fprintf(stream, "%f", (double)f);
+		return format_double(stream, f, format);
 	case ARGTYPE_DOUBLE:
 		if (read_double(value, &d, arguments) < 0)
 			return -1;
-		return fprintf(stream, "%f", d);
+		return format_double(stream, d, format);
 	default:
 		abort();
 	}
@@ -400,7 +410,7 @@
 
 	case ARGTYPE_FLOAT:
 	case ARGTYPE_DOUBLE:
-		return format_floating(stream, value, arguments);
+		return format_floating(stream, value, arguments, int_fmt);
 
 	case ARGTYPE_STRUCT:
 		return format_struct(stream, value, arguments);
diff --git a/ltrace.conf.5 b/ltrace.conf.5
index 7e18e3f..957fe8b 100644
--- a/ltrace.conf.5
+++ b/ltrace.conf.5
@@ -127,8 +127,9 @@
 
 .TP
 .B hex(\fITYPE\fB)
-The argument, which should be an integer type, is formatted in
-base-16.
+The argument, which should be an integer or floating point type, is
+formatted in base-16.  Floating point arguments are converted to
+double and then displayed using the \fB%a\fR fprintf modifier.
 
 .TP
 .B hide(\fITYPE\fB)
@@ -136,7 +137,7 @@
 
 .TP
 .B bool(\fITYPE\fB)
-Arguments with zero value are shown as "false", other are shown as
+Arguments with zero value are shown as "false", others are shown as
 "true".
 
 .TP
diff --git a/testsuite/ltrace.main/parameters2.exp b/testsuite/ltrace.main/parameters2.exp
index ff61d21..aa1e3d2 100644
--- a/testsuite/ltrace.main/parameters2.exp
+++ b/testsuite/ltrace.main/parameters2.exp
@@ -166,4 +166,21 @@
     {{fun2\(<8-15,255>\) *= <void>} == 1}
 }
 
+ltraceParamTest {
+    hex(float) hex_float(hex(float));
+    hex(double) hex_double(hex(double));
+} {
+    float hex_float(float f);
+    double hex_double(double d);
+} {
+    float hex_float(float f) { return f + 1; }
+    double hex_double(double d) { return d + 1; }
+} {
+    hex_float(1.5);
+    hex_double(1.5);
+} {
+    {{hex_float\(0x1.8p\+0\) *= 0x1.4p\+1} == 1}
+    {{hex_double\(0x1.8p\+0\) *= 0x1.4p\+1} == 1}
+}
+
 ltraceDone