@@ -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 */
71477221struct 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+
71547235static 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