Skip to content

Commit 1d1ba9c

Browse files
author
H. Peter Anvin
committed
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 <[email protected]>
1 parent 5a25ad1 commit 1d1ba9c

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

asm/preproc.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7143,6 +7143,80 @@ stdmac_count(const SMacro *s, Token **params, int nparams)
71437143
return make_tok_num(NULL, nparams);
71447144
}
71457145

7146+
/* %num() */
7147+
static Token *
7148+
stdmac_num(const SMacro *s, Token **params, int nparams)
7149+
{
7150+
static const char num_digits[] =
7151+
"0123456789"
7152+
"abcdefghijklmnopqrstuvwxyz"
7153+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7154+
"@_"; /* Compatible with bash */
7155+
int64_t parm[3];
7156+
uint64_t n;
7157+
int64_t dparm, bparm;
7158+
int i, nd;
7159+
unsigned int base;
7160+
char numstr[256];
7161+
char * const endstr = numstr + sizeof numstr - 1;
7162+
const int maxlen = sizeof numstr - 3;
7163+
const int maxbase = sizeof num_digits - 1;
7164+
char *p;
7165+
bool moredigits;
7166+
7167+
if (nparams < 1 || nparams > (int)ARRAY_SIZE(parm)) {
7168+
nasm_nonfatal("invalid number of parameters to %s()", s->name);
7169+
return NULL;
7170+
}
7171+
7172+
parm[1] = 10; /* Default base */
7173+
parm[2] = -1; /* Default digits */
7174+
7175+
for (i = 0; i < nparams; i++) {
7176+
bool err;
7177+
parm[i] = get_tok_num(params[i], &err);
7178+
if (err)
7179+
return NULL;
7180+
}
7181+
7182+
n = parm[0];
7183+
bparm = parm[1];
7184+
dparm = parm[2];
7185+
7186+
if (bparm < 2 || bparm > maxbase) {
7187+
nasm_nonfatal("invalid base %"PRId64" given to %s()",
7188+
bparm, s->name);
7189+
return NULL;
7190+
}
7191+
7192+
base = bparm;
7193+
7194+
if (dparm < -maxlen || dparm > maxlen) {
7195+
nasm_nonfatal("digit count %"PRId64" specified to %s() too large",
7196+
dparm, s->name);
7197+
moredigits = true;
7198+
nd = 1;
7199+
} else if (dparm <= 0) {
7200+
moredigits = true;
7201+
nd = -dparm;
7202+
} else {
7203+
moredigits = false;
7204+
nd = dparm;
7205+
}
7206+
7207+
p = endstr;
7208+
*p = '\0';
7209+
*--p = '\'';
7210+
7211+
while (nd-- > 0 || (moredigits && n)) {
7212+
*--p = num_digits[n % base];
7213+
n /= base;
7214+
}
7215+
*--p = '\'';
7216+
7217+
return new_Token(NULL, TOKEN_STR, p, endstr - p);
7218+
}
7219+
71467220
/* Add magic standard macros */
71477221
struct magic_macros {
71487222
const char *name;
@@ -7151,6 +7225,13 @@ struct magic_macros {
71517225
enum sparmflags flags;
71527226
ExpandSMacro func;
71537227
};
7228+
7229+
struct num_macros {
7230+
const char name[6];
7231+
uint8_t base;
7232+
char prefix;
7233+
};
7234+
71547235
static void pp_add_magic_stdmac(void)
71557236
{
71567237
static const struct magic_macros magic_macros[] = {
@@ -7160,6 +7241,7 @@ static void pp_add_magic_stdmac(void)
71607241
{ "__?PTR?__", true, 0, 0, stdmac_ptr },
71617242
{ "%count", false, 1, SPARM_VARADIC, stdmac_count },
71627243
{ "%eval", false, 1, SPARM_EVAL|SPARM_VARADIC, stdmac_join },
7244+
{ "%num", false, 1, SPARM_EVAL|SPARM_VARADIC, stdmac_num },
71637245
{ "%str", false, 1, SPARM_GREEDY|SPARM_STR, stdmac_join },
71647246
{ "%strcat", false, 1, SPARM_GREEDY, stdmac_strcat },
71657247
{ "%strlen", false, 1, 0, stdmac_strlen },

0 commit comments

Comments
 (0)