Welcome to little lamb

Code » limb » commit 1cbee03

buffer_putmsg(): Add support for decimal values

author Olivier Brunel
2023-03-23 11:52:10 UTC
committer Olivier Brunel
2023-03-23 18:45:37 UTC
parent 8b2fc094fd589d256119dbd6cfeed3815d25cbed

buffer_putmsg(): Add support for decimal values

Add special constants PUTMSG_UINT_NEXT/PUTMSG_INT_NEXT to indicate the
next element should be treated as a number (and not a pointer), whose
value should be written into buffer in decimal form.

Add macros PUTMSG_ASUINT()/PUTMSG_ASINT() to do the typecasting of such
a number, so it can be added into a string array easily.

Lastly, also add macros PUTMSG_UINT()/PUTMSG_INT() to add both the
appropriate constant and the typecasted value into a coma-separated
list.
This is useful when initializing a string array, or more likely for use
with the many macros from output.h

doc/buffer.h.0.md +29 -0
doc/buffer_putmsg.3.md +38 -0
doc/out.3.md +13 -0
include/limb/buffer.h +8 -0
meta/bins/mkrabintables +1 -0
src/buffer_putmsg.c +11 -0
src/dbg_putmsg.c +5 -8

diff --git a/doc/buffer.h.0.md b/doc/buffer.h.0.md
index d579ac3..62512cb 100644
--- a/doc/buffer.h.0.md
+++ b/doc/buffer.h.0.md
@@ -32,6 +32,35 @@ The following constants are defined :
 :: Can be used as special string given to [buffer_putmsg](3) to add a new line
 :: and flush the buffer
 
+: *PUTMSG_UINT_NEXT*
+:: Can be used as special string given to [buffer_putmsg](3) to indicate that
+:: the next element should be treated as an unsigned integer, whose decimal
+:: representation should be written into the buffer
+
+: *PUTMSG_INT_NEXT*
+:: Same as *PUTMSG_UINT_NEXT* only for a signed integer
+
+## Macros
+
+The following macros are defined :
+
+: *PUTMSG_ASUINT(`n`)*
+:: Typecast `n` so it can be passed into an array of strings to
+:: [buffer_putmsg](3), following *PUTMSG_UINT_NEXT*, in order to have its
+:: decimal representation written into the buffer
+
+: *PUTMSG_ASINT(n)*
+:: Same as *PUTMSG_ASUINT(`n`)* but with a signed integer (following
+:: *PUTMSG_INT_NEXT*)
+
+: *PUTMSG_UINT(`n`)*
+:: Shorthand to easily add an unsigned number into a message. This is intended
+:: for use in a coma-separated list, as it expands to:
+:: `PUTMSG_UINT_NEXT, PUTMSG_ASUINT(n)`
+
+: *PUTMSG_INT(n)*
+:: Same as *PUTMSG_UINT(n)* only for a signed integer
+
 ## Functions
 
 The following functions are defined :
diff --git a/doc/buffer_putmsg.3.md b/doc/buffer_putmsg.3.md
index 3c0271d..e12c578 100644
--- a/doc/buffer_putmsg.3.md
+++ b/doc/buffer_putmsg.3.md
@@ -32,6 +32,25 @@ description of `errno`, as returned by [strerror](3).
 When *PUTMSG_LFF* was given as one of the strings, in its place is added a new
 line and the buffer is flushed.
 
+When *PUTMSG_UINT_NEXT* was given as one of the strings, it acts as an indicator
+that the next element in `strings` should be treated as an unsigned integer
+(instead of a pointer to a string) whose value should be written in decimal form
+into the buffer.
+
+When *PUTMSG_INT_NEXT* was given as one of the strings, it does the same as
+*PUTMSG_UINT_NEXT* only treating the next element as a signed integer.
+
+! INFO:
+! A few macros are available, in order to simply things:
+! : *PUTMSG_ASUINT(`n`)*, *PUTMSG_ASINT(`n`)*
+! :: To cast `n` as unsigned or signed integer, respectively, to be added into
+! :: a string array.
+!
+! : *PUTMSG_UINT(`n`)*, *PUTMSG_INT(`n`)*
+! :: Shorthand to easily add an unsigned or signed number, respectively, into a
+! :: message. This is intended for use in a coma-separated list, as it expands
+! :: to, e.g: `PUTMSG_UINT_NEXT, PUTMSG_ASUINT(n)`
+
 # ESCAPING
 
 It is possible to pass the special constant *PUTMSG_ESC* (or *ESC*) as one of
@@ -41,3 +60,22 @@ It can be specified again to stop escaping and return to "normal" processing.
 Additionally, a double quote (`"`) will be put in place of each constant.
 
 This escaping can be enabled as many times as needed.
+
+# EXAMPLES
+
+To write into a buffer a message containing a number one could use the
+following :
+
+```c
+int r = 42;
+const char *strings[] = { "The answer is ", PUTMSG_UINT_NEXT, PUTMSG_ASUINT(r), PUTMSG_LFF };
+buffer_putmsg(buffer_1, strings, sizeof(strings) / sizeof(*strings));
+```
+
+Which is identical to the following :
+
+```c
+int r = 42;
+const char *strings[] = { "The answer is ", PUTMSG_UINT(r), PUTMSG_LFF };
+buffer_putmsg(buffer_1, strings, 4);
+```
diff --git a/doc/out.3.md b/doc/out.3.md
index a30da5e..02b8f54 100644
--- a/doc/out.3.md
+++ b/doc/out.3.md
@@ -80,6 +80,19 @@ the calling process (via [\_exit](3) using `e`).
 It is possible to use *PUTMSG_ESC* (or simply *ESC*) as one of the strings in
 order to toggle escaping. See to [buffer_putmsg](3) for more.
 
+## Numbers
+
+It is possible to add a numbers into a message, to have its value written into
+the buffer into decimal form, through the use of macros :
+
+: *PUTMSG_UINT(`n`)*
+:: To have the value of unsigned number `n` written out
+
+: *PUTMSG_INT(`n`)*
+:: Same as *PUTMSG_UINT(`n`)* but for signed number
+
+Refer to [buffer_putmsg](3) for more.
+
 # SEE ALSO
 
 [out_putmsg](3), [buffer_putmsg](3)
diff --git a/include/limb/buffer.h b/include/limb/buffer.h
index ea8372f..c529e15 100644
--- a/include/limb/buffer.h
+++ b/include/limb/buffer.h
@@ -10,6 +10,14 @@
 #define PUTMSG_SYS          ((void *) 1)    /* add strerror(errno) */
 #define PUTMSG_LFF          ((void *) 2)    /* add \n and flush buffer */
 #define PUTMSG_ESC          ((void *) 3)    /* toggle escaping */
+#define PUTMSG_UINT_NEXT    ((void *) 4)    /* next string is an uint */
+#define PUTMSG_INT_NEXT     ((void *) 5)    /* next string is an int */
+
+#define PUTMSG_ASUINT(n)    ((const char *) (uintptr_t) (n))
+#define PUTMSG_ASINT(n)     ((const char *) ( intptr_t) (n))
+
+#define PUTMSG_UINT(n)      PUTMSG_UINT_NEXT, PUTMSG_ASUINT(n)
+#define PUTMSG_INT(n)       PUTMSG_INT_NEXT,  PUTMSG_ASINT(n)
 
 #define ESC                 PUTMSG_ESC
 
diff --git a/meta/bins/mkrabintables b/meta/bins/mkrabintables
index 6cc1651..51b249e 100644
--- a/meta/bins/mkrabintables
+++ b/meta/bins/mkrabintables
@@ -3,6 +3,7 @@ obj/msb64.o
 obj/buffer_putescall.o
 obj/buffer_putesc.o
 obj/buffer_putescs.o
+obj/u64_fmt_generic.o
 obj/buffer_putmsg.o
 obj/obuffer_putmsg.o
 obj/obuffers_putmsg.o
diff --git a/src/buffer_putmsg.c b/src/buffer_putmsg.c
index 3409038..dc6ca2e 100644
--- a/src/buffer_putmsg.c
+++ b/src/buffer_putmsg.c
@@ -3,6 +3,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 #include <errno.h>
 #include "limb/buffer.h"
+#include "limb/u64.h"
 
 void
 buffer_putmsg(buffer *b, const char * const *as, unsigned int n)
@@ -21,6 +22,16 @@ buffer_putmsg(buffer *b, const char * const *as, unsigned int n)
                 puts = buffer_puts;
         } else if (as[i] == PUTMSG_LFF) {
             buffer_putflush(b, "\n", 1);
+        } else if ((as[i] == PUTMSG_UINT_NEXT || as[i] == PUTMSG_INT_NEXT) && i + 1 < n) {
+            char buf_[U64_FMT], *buf = buf_;
+            u64 u = (uintptr_t) as[++i];
+            if ((as[i - 1] == PUTMSG_INT_NEXT) && ((intptr_t) u < 0)) {
+                *buf++ = '-';
+                u = -u;
+            }
+
+            buf[u64_fmt(buf, u)] = 0;
+            buffer_puts(b, buf_);
         } else if (as[i] && as[i][0]) {
             puts(b, as[i]);
         }
diff --git a/src/dbg_putmsg.c b/src/dbg_putmsg.c
index 6dab03d..805ac39 100644
--- a/src/dbg_putmsg.c
+++ b/src/dbg_putmsg.c
@@ -2,17 +2,14 @@
  * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
 /* SPDX-License-Identifier: GPL-2.0-only */
 #include "limb/output.h"
-#include "limb/u32.h"
 
 void
 dbg_putmsg(u8 level, const char *func, const char *file, int line,
            const char * const *as, unsigned int n)
 {
-    char buf[U32_FMT];
-    buf[u32_fmt(buf, line)] = 0;
-
-    const char *strings[7 + n];
-    memcpy(strings, (const char * const [])  { "[", func, "@", file, ":", buf, "] " }, 7 * sizeof(char *));
-    memcpy(strings + 7, as, n * sizeof(*as));
-    out_putmsg(level, strings, 7 + n);
+    const char *strings[8 + n];
+    /* PUTMSG_INT() expands to 2 arguments, hence the 8 for seemingly 7 elements */
+    memcpy(strings, (const char * const [])  { "[", func, "@", file, ":", PUTMSG_INT(line), "] " }, 8 * sizeof(char *));
+    memcpy(strings + 8, as, n * sizeof(*as));
+    out_putmsg(level, strings, 8 + n);
 }