[nasm:master] preproc: add %num() to format a number in an arbitrary base

nasm-bot for H. Peter Anvin hpa at zytor.com
Tue Nov 15 17:00:09 PST 2022


Commit-ID:  1d1ba9c7d795124b2b0ea4f69bb8b2328269ef13
Gitweb:     http://repo.or.cz/w/nasm.git?a=commitdiff;h=1d1ba9c7d795124b2b0ea4f69bb8b2328269ef13
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Tue, 15 Nov 2022 16:55:37 -0800
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Tue, 15 Nov 2022 16:58:20 -0800

preproc: add %num() to format a number in an arbitrary base

Add the %num() preprocessor function, which returns a quoted string
with a number formatted in any base between 2 and 64 (using bash
encoding with '@' for 62 and '_' for 63.)

It can specify a fixed number of digits with or without truncation.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 asm/preproc.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/asm/preproc.c b/asm/preproc.c
index 4f3baa58..8f3a2cb5 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -7143,6 +7143,80 @@ stdmac_count(const SMacro *s, Token **params, int nparams)
     return make_tok_num(NULL, nparams);
 }
 
+/* %num() */
+static Token *
+stdmac_num(const SMacro *s, Token **params, int nparams)
+{
+    static const char num_digits[] =
+        "0123456789"
+        "abcdefghijklmnopqrstuvwxyz"
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+        "@_";                   /* Compatible with bash */
+    int64_t parm[3];
+    uint64_t n;
+    int64_t dparm, bparm;
+    int i, nd;
+    unsigned int base;
+    char numstr[256];
+    char * const endstr = numstr + sizeof numstr - 1;
+    const int maxlen = sizeof numstr - 3;
+    const int maxbase = sizeof num_digits - 1;
+    char *p;
+    bool moredigits;
+
+    if (nparams < 1 || nparams > (int)ARRAY_SIZE(parm)) {
+        nasm_nonfatal("invalid number of parameters to %s()", s->name);
+        return NULL;
+    }
+
+    parm[1] = 10;               /* Default base */
+    parm[2] = -1;               /* Default digits */
+
+    for (i = 0; i < nparams; i++) {
+        bool err;
+        parm[i] = get_tok_num(params[i], &err);
+        if (err)
+            return NULL;
+    }
+
+    n      = parm[0];
+    bparm  = parm[1];
+    dparm  = parm[2];
+
+    if (bparm < 2 || bparm > maxbase) {
+        nasm_nonfatal("invalid base %"PRId64" given to %s()",
+                      bparm, s->name);
+        return NULL;
+    }
+
+    base = bparm;
+    
+    if (dparm < -maxlen || dparm > maxlen) {
+        nasm_nonfatal("digit count %"PRId64" specified to %s() too large",
+                      dparm, s->name);
+        moredigits = true;
+        nd = 1;
+    } else if (dparm <= 0) {
+        moredigits = true;
+        nd = -dparm;
+    } else {
+        moredigits = false;
+        nd = dparm;
+    }
+
+    p = endstr;
+    *p = '\0';
+    *--p = '\'';
+
+    while (nd-- > 0 || (moredigits && n)) {
+        *--p = num_digits[n % base];
+        n /= base;
+    }
+    *--p = '\'';
+
+    return new_Token(NULL, TOKEN_STR, p, endstr - p);
+}
+
 /* Add magic standard macros */
 struct magic_macros {
     const char *name;
@@ -7151,6 +7225,13 @@ struct magic_macros {
     enum sparmflags flags;
     ExpandSMacro func;
 };
+
+struct num_macros {
+    const char name[6];
+    uint8_t base;
+    char prefix;
+};
+
 static void pp_add_magic_stdmac(void)
 {
     static const struct magic_macros magic_macros[] = {
@@ -7160,6 +7241,7 @@ static void pp_add_magic_stdmac(void)
         { "__?PTR?__",  true, 0, 0, stdmac_ptr },
         { "%count",     false, 1, SPARM_VARADIC, stdmac_count },
         { "%eval",      false, 1, SPARM_EVAL|SPARM_VARADIC, stdmac_join },
+        { "%num",       false, 1, SPARM_EVAL|SPARM_VARADIC, stdmac_num },
         { "%str",       false, 1, SPARM_GREEDY|SPARM_STR, stdmac_join },
         { "%strcat",    false, 1, SPARM_GREEDY, stdmac_strcat },
         { "%strlen",    false, 1, 0, stdmac_strlen },


More information about the Nasm-commits mailing list