@@ -206,13 +206,14 @@ typedef Token *(*ExpandSMacro)(const SMacro *s, Token **params, int nparams);
206206 * if SPARM_GREEDY is set.
207207 */
208208enum sparmflags {
209- SPARM_PLAIN = 0 ,
210- SPARM_EVAL = 1 , /* Evaluate as a numeric expression (=) */
211- SPARM_STR = 2 , /* Convert to quoted string ($) */
212- SPARM_NOSTRIP = 4 , /* Don't strip braces (!) */
213- SPARM_GREEDY = 8 , /* Greedy final parameter (+) */
214- SPARM_VARADIC = 16 , /* Any number of separate arguments */
215- SPARM_OPTIONAL = 32 /* Optional argument */
209+ SPARM_PLAIN = 0 ,
210+ SPARM_EVAL = 1 , /* Evaluate as a numeric expression (=) */
211+ SPARM_STR = 2 , /* Convert to quoted string ($) */
212+ SPARM_NOSTRIP = 4 , /* Don't strip braces (!) */
213+ SPARM_GREEDY = 8 , /* Greedy final parameter (+) */
214+ SPARM_VARADIC = 16 , /* Any number of separate arguments */
215+ SPARM_OPTIONAL = 32 , /* Optional argument */
216+ SPARM_CONDQUOTE = 64 /* With SPARM_STR, don't re-quote a string */
216217};
217218
218219struct smac_param {
@@ -2875,11 +2876,11 @@ list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
28752876 if (m -> nparam ) {
28762877 /*
28772878 * Space for ( and either , or ) around each
2878- * parameter, plus up to 4 flags.
2879+ * parameter, plus up to 5 flags.
28792880 */
28802881 int i ;
28812882
2882- size += 1 + 4 * m -> nparam ;
2883+ size += 1 + 5 * m -> nparam ;
28832884 for (i = 0 ; i < m -> nparam ; i ++ )
28842885 size += m -> params [i ].name .len ;
28852886 }
@@ -2910,8 +2911,11 @@ list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
29102911
29112912 if (flags & SPARM_NOSTRIP )
29122913 * -- p = '!' ;
2913- if (flags & SPARM_STR )
2914+ if (flags & SPARM_STR ) {
29142915 * -- p = '&' ;
2916+ if (flags & SPARM_CONDQUOTE )
2917+ * -- p = '&' ;
2918+ }
29152919 if (flags & SPARM_EVAL )
29162920 * -- p = '=' ;
29172921 * -- p = ',' ;
@@ -3019,6 +3023,9 @@ static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
30193023 case '&' :
30203024 flags |= SPARM_STR ;
30213025 break ;
3026+ case TOKEN_DBL_AND :
3027+ flags |= SPARM_STR |SPARM_CONDQUOTE ;
3028+ break ;
30223029 case '!' :
30233030 flags |= SPARM_NOSTRIP ;
30243031 break ;
@@ -3691,15 +3698,16 @@ static Token *pp_strcat(Token *tline, const char *dname)
36913698 return res ;
36923699}
36933700
3701+
36943702/*
36953703 * Implement substring extraction as used by the %substr directive
36963704 * and function.
36973705 */
3706+ static Token * pp_substr_common (Token * t , int64_t start , int64_t count );
3707+
36983708static Token * pp_substr (Token * tline , const char * dname )
36993709{
37003710 int64_t start , count ;
3701- const char * txt ;
3702- size_t len ;
37033711 struct ppscan pps ;
37043712 Token * t ;
37053713 Token * res = NULL ;
@@ -3730,7 +3738,7 @@ static Token *pp_substr(Token *tline, const char *dname)
37303738 nasm_nonfatal ("non-constant value given to `%s'" , dname );
37313739 goto err ;
37323740 }
3733- start = evalresult -> value - 1 ;
3741+ start = evalresult -> value ;
37343742
37353743 pps .tptr = skip_white (pps .tptr );
37363744 if (!pps .tptr ) {
@@ -3747,10 +3755,24 @@ static Token *pp_substr(Token *tline, const char *dname)
37473755 count = evalresult -> value ;
37483756 }
37493757
3758+ res = pp_substr_common (t , start , count );
3759+
3760+ err :
3761+ free_tlist (tline );
3762+ return res ;
3763+ }
3764+
3765+ static Token * pp_substr_common (Token * t , int64_t start , int64_t count )
3766+ {
3767+ size_t len ;
3768+ const char * txt ;
3769+
37503770 unquote_token (t );
37513771 len = t -> len ;
37523772
37533773 /* make start and count being in range */
3774+ start -= 1 ; /* First character is 1 */
3775+
37543776 if (start < 0 )
37553777 start = 0 ;
37563778 if (count < 0 )
@@ -3761,10 +3783,7 @@ static Token *pp_substr(Token *tline, const char *dname)
37613783 start = -1 , count = 0 ; /* empty string */
37623784
37633785 txt = (start < 0 ) ? "" : tok_text (t ) + start ;
3764- res = make_tok_qstr_len (NULL , txt , count );
3765- err :
3766- free_tlist (tline );
3767- return res ;
3786+ return make_tok_qstr_len (NULL , txt , count );
37683787}
37693788
37703789/**
@@ -5893,14 +5912,19 @@ static SMacro *expand_one_smacro(Token ***tpp)
58935912
58945913 if (flags & SPARM_STR ) {
58955914 /* Convert expansion to a quoted string */
5896- char * arg ;
58975915 Token * qs ;
58985916
58995917 qs = expand_smacro_noreset (params [i ]);
5900- arg = detoken (qs , false);
5901- free_tlist (qs );
5902- params [i ] = make_tok_qstr (NULL , arg );
5903- nasm_free (arg );
5918+ if ((flags & SPARM_CONDQUOTE ) &&
5919+ tok_is (qs , TOKEN_STR ) && !qs -> next ) {
5920+ /* A single quoted string token */
5921+ params [i ] = qs ;
5922+ } else {
5923+ char * arg = detoken (qs , false);
5924+ free_tlist (qs );
5925+ params [i ] = make_tok_qstr (NULL , arg );
5926+ nasm_free (arg );
5927+ }
59045928 }
59055929 }
59065930 }
@@ -7051,78 +7075,61 @@ stdmac_join(const SMacro *s, Token **params, int nparams)
70517075static Token *
70527076stdmac_strcat (const SMacro * s , Token * * params , int nparams )
70537077{
7054- Token * tline ;
7055- (void )nparams ;
7078+ int i ;
7079+ size_t len = 0 ;
7080+ char * str , * p ;
70567081
7057- tline = params [0 ];
7058- params [0 ] = NULL ; /* Don't free this later */
7059- return pp_strcat (expand_smacro_noreset (tline ), s -> name );
7082+ (void )s ;
7083+
7084+ for (i = 0 ; i < nparams ; i ++ ) {
7085+ unquote_token (params [i ]);
7086+ len += params [i ]-> len ;
7087+ }
7088+
7089+ nasm_newn (str , len + 1 );
7090+ p = str ;
7091+
7092+ for (i = 0 ; i < nparams ; i ++ ) {
7093+ p = mempcpy (p , tok_text (params [i ]), params [i ]-> len );
7094+ }
7095+
7096+ return make_tok_qstr_len (NULL , str , len );
70607097}
70617098
70627099/* %substr() function */
70637100static Token *
70647101stdmac_substr (const SMacro * s , Token * * params , int nparams )
70657102{
7066- Token * tline ;
7067- (void )nparams ;
7068-
7069- tline = params [0 ];
7070- params [0 ] = NULL ; /* Don't free this later */
7071- return pp_substr (expand_smacro_noreset (tline ), s -> name );
7072- }
7073-
7074- /* Expand a the argument and enforce it being a single quoted string */
7075- static Token * expand_to_string (Token * * tp , const char * dname )
7076- {
7077- Token * tlist , * t ;
7078-
7079- tlist = * tp ;
7080- * tp = NULL ; /* Don't free this later */
7081- t = zap_white (expand_smacro_noreset (tlist ));
7103+ int64_t start , count ;
70827104
7083- if (!tok_is (t , TOKEN_STR )) {
7084- nasm_nonfatal ("`%s' requires string as parameter" , dname );
7085- return NULL ;
7086- }
7105+ (void )nparams ;
7106+ (void )s ;
70877107
7088- t -> next = zap_white (t -> next );
7089- if (t -> next ) {
7090- nasm_nonfatal ("`%s' requires exactly one string as parameter" , dname );
7091- return NULL ;
7092- }
7108+ start = get_tok_num (params [1 ], NULL );
7109+ count = get_tok_num (params [2 ], NULL );
70937110
7094- return t ;
7111+ return pp_substr_common ( params [ 0 ], start , count ) ;
70957112}
70967113
70977114/* %strlen() function */
70987115static Token *
70997116stdmac_strlen (const SMacro * s , Token * * params , int nparams )
71007117{
7101- Token * t ;
7102-
71037118 (void )nparams ;
7119+ (void )s ;
71047120
7105- t = expand_to_string (& params [0 ], s -> name );
7106- if (!t )
7107- return NULL ;
7108-
7109- unquote_token (t );
7110- return make_tok_num (NULL , t -> len );
7121+ unquote_token (params [0 ]);
7122+ return make_tok_num (NULL , params [0 ]-> len );
71117123}
71127124
71137125/* %tok() function */
71147126static Token *
71157127stdmac_tok (const SMacro * s , Token * * params , int nparams )
71167128{
7117- Token * t ;
7118-
71197129 (void )nparams ;
7130+ (void )s ;
71207131
7121- t = expand_to_string (& params [0 ], s -> name );
7122- if (!t )
7123- return NULL ;
7124-
7125- return reverse_tokens (tokenize (unquote_token_cstr (t )));
7132+ return reverse_tokens (tokenize (unquote_token_cstr (params [0 ])));
71267133}
71277134
71287135/* %cond() or %sel() */
@@ -7272,12 +7279,6 @@ struct magic_macros {
72727279 ExpandSMacro func ;
72737280};
72747281
7275- struct num_macros {
7276- const char name [6 ];
7277- uint8_t base ;
7278- char prefix ;
7279- };
7280-
72817282static void pp_add_magic_stdmac (void )
72827283{
72837284 static const struct magic_macros magic_macros [] = {
@@ -7289,10 +7290,9 @@ static void pp_add_magic_stdmac(void)
72897290 { "%count" , false, 1 , SPARM_VARADIC , stdmac_count },
72907291 { "%eval" , false, 1 , SPARM_EVAL |SPARM_VARADIC , stdmac_join },
72917292 { "%str" , false, 1 , SPARM_GREEDY |SPARM_STR , stdmac_join },
7292- { "%strcat" , false, 1 , SPARM_GREEDY , stdmac_strcat },
7293- { "%strlen" , false, 1 , 0 , stdmac_strlen },
7294- { "%substr" , false, 1 , SPARM_GREEDY , stdmac_substr },
7295- { "%tok" , false, 1 , 0 , stdmac_tok },
7293+ { "%strcat" , false, 1 , SPARM_STR |SPARM_CONDQUOTE |SPARM_VARADIC , stdmac_strcat },
7294+ { "%strlen" , false, 1 , SPARM_STR |SPARM_CONDQUOTE , stdmac_strlen },
7295+ { "%tok" , false, 1 , SPARM_STR |SPARM_CONDQUOTE , stdmac_tok },
72967296 { NULL , false, 0 , 0 , NULL }
72977297 };
72987298 const struct magic_macros * m ;
@@ -7361,6 +7361,18 @@ static void pp_add_magic_stdmac(void)
73617361 tmpl .params [2 ].def = make_tok_num (NULL , 10 );
73627362 define_smacro ("%num" , false, NULL , & tmpl );
73637363
7364+ /* %substr() function */
7365+ nasm_zero (tmpl );
7366+ tmpl .nparam = 3 ;
7367+ tmpl .expand = stdmac_substr ;
7368+ tmpl .recursive = true;
7369+ nasm_newn (tmpl .params , tmpl .nparam );
7370+ tmpl .params [0 ].flags = SPARM_STR |SPARM_CONDQUOTE ;
7371+ tmpl .params [1 ].flags = SPARM_EVAL ;
7372+ tmpl .params [2 ].flags = SPARM_EVAL |SPARM_OPTIONAL ;
7373+ tmpl .params [2 ].def = make_tok_num (NULL , -1 );
7374+ define_smacro ("%substr" , false, NULL , & tmpl );
7375+
73647376 /* %is...() macro functions */
73657377 nasm_zero (tmpl );
73667378 tmpl .nparam = 1 ;
0 commit comments