This is an automated email from Gerrit.

"Antonio Borneo <borneo.anto...@gmail.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8433

-- gerrit

commit 8971e2035a4c9162741070907c7ea3034b62e140
Author: Antonio Borneo <borneo.anto...@gmail.com>
Date:   Mon Aug 12 14:27:37 2024 +0200

    helper: util: add command 'x' for binary values and separators
    
    TCL syntax doesn't provide any support for handling binary numbers
    that can be useful for HW oriented manipulations in OpenOCD.
    Plus, long strings of numbers could be way more readable if a
    special separator character could be allowed.
    
    Add the new command 'x' that:
    - recognizes the special prefixes '0b' and '0B' for binary numbers
      and converts it to hexadecimal;
    - recognizes the special separator '_' in a number and strips it
      away.
    In all cases, the output is a standard TCL value that can be used
    by other TCL or OpenOCD commands.
    
    E.g.:
            > x 0x_1_2345_6789
            0x123456789
    
            > x 0b_1000_1111_0001
            0x8f1
    
            > format 0x%x [expr {[x 0xff00_0000] + [x 0b10_0000_0001]}]
            0xff000201
    
    Change-Id: Iaed5d2a7613ba2dac785f87d14ac49613929181c
    Signed-off-by: Antonio Borneo <borneo.anto...@gmail.com>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index c786382768..9bd76a3126 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9627,6 +9627,22 @@ Returns current time since the Epoch in ms
 Useful to compute delays in TCL.
 @end deffn
 
+@deffn {Command} {x} value
+Strips the separator character '_' from the number @var{value}.
+The number @var{value} can be expressed as hexadecimal (with '0x' or '0X'
+prefix) or octal (with '0' prefix) or binary (with '0b' or '0B' prefix) or
+decimal.
+
+In case of a binary number, the number is converted to hexadecimal to be
+handled by any standard TCL command.
+
+Example:
+@example
+> format 0x%x [expr @{[x 0xff00_0000] + [x 0b10_0000_0001]@}]
+0xff000201
+@end example
+@end deffn
+
 @node Architecture and Core Commands
 @chapter Architecture and Core Commands
 @cindex Architecture Specific Commands
diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c
index 3e09143c68..e7dc098242 100644
--- a/src/helper/binarybuffer.c
+++ b/src/helper/binarybuffer.c
@@ -35,7 +35,7 @@ static const unsigned char bit_reverse_table256[] = {
        0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 
0x3F, 0xBF, 0x7F, 0xFF
 };
 
-static const char hex_digits[] = {
+const char hex_digits[] = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'a', 'b', 'c', 'd', 'e', 'f'
 };
diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h
index 441374330e..3b5401f3e3 100644
--- a/src/helper/binarybuffer.h
+++ b/src/helper/binarybuffer.h
@@ -231,6 +231,8 @@ struct bit_copy_queue_entry {
        struct list_head list;
 };
 
+extern const char hex_digits[];
+
 void bit_copy_queue_init(struct bit_copy_queue *q);
 int bit_copy_queued(struct bit_copy_queue *q, uint8_t *dst, unsigned 
dst_offset, const uint8_t *src,
                    unsigned src_offset, unsigned bit_count);
diff --git a/src/helper/util.c b/src/helper/util.c
index 2e9f6155ee..f6d84da0d4 100644
--- a/src/helper/util.c
+++ b/src/helper/util.c
@@ -10,6 +10,9 @@
 #include "config.h"
 #endif
 
+#include <stdbool.h>
+#include <string.h>
+#include "binarybuffer.h"
 #include "log.h"
 #include "time_support.h"
 #include "util.h"
@@ -24,6 +27,114 @@ COMMAND_HANDLER(handler_util_ms)
        return ERROR_OK;
 }
 
+COMMAND_HANDLER(handler_x_converter)
+{
+       /* in reversed order to extract the substrings */
+       const char *valid_hex = "fedcbaFEDCBA9876543210";
+       const char *valid_dec = valid_hex + 6 + 6; /* "9876543210" */
+       const char *valid_oct = valid_dec + 2;     /* "76543210"   */
+       const char *valid_bin = valid_dec + 8;     /* "01"         */
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       char *out = strdup(CMD_ARGV[0]);
+       if (!out) {
+               LOG_ERROR("Out of memory");
+               return ERROR_FAIL;
+       }
+
+       char *s = out;
+
+       bool is_negative = false;
+       if (s[0] == '-') {
+               ++s;
+               is_negative = true;
+       }
+
+       const char *valid_chars;
+       bool is_binary = false;
+       if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
+               /* HEX */
+               s += 2;
+               valid_chars = valid_hex;
+       } else if (s[0] == '0' && (s[1] == 'b' || s[1] == 'B')) {
+               /* Binary */
+               s += 2;
+               valid_chars = valid_bin;
+               is_binary = true;
+       } else if (s[0] == '0' && s[1]) {
+               /* Octal */
+               s += 1;
+               valid_chars = valid_oct;
+       } else {
+               /* Decimal */
+               s += 0;
+               valid_chars = valid_dec;
+       }
+
+       /* Check string and drop separators '_' */
+       if (!s[0])
+               goto invalid;
+
+       char *d = s;
+       do {
+               if (*s == '_') {
+                       ++s;
+                       continue;
+               }
+
+               if (!strchr(valid_chars, *s))
+                       goto invalid;
+
+               *d++ = *s++;
+       } while (*s);
+       *d = '\0';
+
+       if (is_binary) {
+               s = out + (is_negative ? 3 : 2);
+               d = s;
+               d[-1] = 'x';
+
+               size_t len = strlen(s);
+               unsigned int hex = 0;
+               switch (len % 4) {
+               case 3:
+                       hex += (*s++ == '1') ? 4 : 0;
+                       /* fall-through */
+               case 2:
+                       hex += (*s++ == '1') ? 2 : 0;
+                       /* fall-through */
+               case 1:
+                       hex += (*s++ == '1') ? 1 : 0;
+                       *d++ = hex_digits[hex];
+                       break;
+
+               case 0:
+               default:
+                       break;
+               }
+
+               while (*s) {
+                       hex =  (*s++ == '1') ? 8 : 0;
+                       hex += (*s++ == '1') ? 4 : 0;
+                       hex += (*s++ == '1') ? 2 : 0;
+                       hex += (*s++ == '1') ? 1 : 0;
+                       *d++ = hex_digits[hex];
+               }
+               *d = '\0';
+       }
+
+       command_print(CMD, "%s", out);
+       free(out);
+       return ERROR_OK;
+
+invalid:
+       command_print(CMD, "Invalid value %s", CMD_ARGV[0]);
+       free(out);
+       return ERROR_INVALID_NUMBER;
+}
+
 static const struct command_registration util_command_handlers[] = {
        {
                .name = "ms",
@@ -33,6 +144,13 @@ static const struct command_registration 
util_command_handlers[] = {
                        "Returns ever increasing milliseconds. Used to 
calculate differences in time.",
                .usage = "",
        },
+       {
+               .name = "x",
+               .mode = COMMAND_ANY,
+               .handler = handler_x_converter,
+               .help = "drop '_' separators from numeric values, convert 
binary to hexadecimal.",
+               .usage = "value",
+       },
        COMMAND_REGISTRATION_DONE
 };
 

-- 

Reply via email to