@@ -206,13 +206,14 @@ typedef Token *(*ExpandSMacro)(const SMacro *s, Token **params, int nparams);
206
206
* if SPARM_GREEDY is set.
207
207
*/
208
208
enum 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 */
216
217
};
217
218
218
219
struct smac_param {
@@ -2875,11 +2876,11 @@ list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2875
2876
if (m -> nparam ) {
2876
2877
/*
2877
2878
* Space for ( and either , or ) around each
2878
- * parameter, plus up to 4 flags.
2879
+ * parameter, plus up to 5 flags.
2879
2880
*/
2880
2881
int i ;
2881
2882
2882
- size += 1 + 4 * m -> nparam ;
2883
+ size += 1 + 5 * m -> nparam ;
2883
2884
for (i = 0 ; i < m -> nparam ; i ++ )
2884
2885
size += m -> params [i ].name .len ;
2885
2886
}
@@ -2910,8 +2911,11 @@ list_smacro_def(enum preproc_token op, const Context *ctx, const SMacro *m)
2910
2911
2911
2912
if (flags & SPARM_NOSTRIP )
2912
2913
* -- p = '!' ;
2913
- if (flags & SPARM_STR )
2914
+ if (flags & SPARM_STR ) {
2914
2915
* -- p = '&' ;
2916
+ if (flags & SPARM_CONDQUOTE )
2917
+ * -- p = '&' ;
2918
+ }
2915
2919
if (flags & SPARM_EVAL )
2916
2920
* -- p = '=' ;
2917
2921
* -- p = ',' ;
@@ -3019,6 +3023,9 @@ static int parse_smacro_template(Token ***tpp, SMacro *tmpl)
3019
3023
case '&' :
3020
3024
flags |= SPARM_STR ;
3021
3025
break ;
3026
+ case TOKEN_DBL_AND :
3027
+ flags |= SPARM_STR |SPARM_CONDQUOTE ;
3028
+ break ;
3022
3029
case '!' :
3023
3030
flags |= SPARM_NOSTRIP ;
3024
3031
break ;
@@ -3691,15 +3698,16 @@ static Token *pp_strcat(Token *tline, const char *dname)
3691
3698
return res ;
3692
3699
}
3693
3700
3701
+
3694
3702
/*
3695
3703
* Implement substring extraction as used by the %substr directive
3696
3704
* and function.
3697
3705
*/
3706
+ static Token * pp_substr_common (Token * t , int64_t start , int64_t count );
3707
+
3698
3708
static Token * pp_substr (Token * tline , const char * dname )
3699
3709
{
3700
3710
int64_t start , count ;
3701
- const char * txt ;
3702
- size_t len ;
3703
3711
struct ppscan pps ;
3704
3712
Token * t ;
3705
3713
Token * res = NULL ;
@@ -3730,7 +3738,7 @@ static Token *pp_substr(Token *tline, const char *dname)
3730
3738
nasm_nonfatal ("non-constant value given to `%s'" , dname );
3731
3739
goto err ;
3732
3740
}
3733
- start = evalresult -> value - 1 ;
3741
+ start = evalresult -> value ;
3734
3742
3735
3743
pps .tptr = skip_white (pps .tptr );
3736
3744
if (!pps .tptr ) {
@@ -3747,10 +3755,24 @@ static Token *pp_substr(Token *tline, const char *dname)
3747
3755
count = evalresult -> value ;
3748
3756
}
3749
3757
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
+
3750
3770
unquote_token (t );
3751
3771
len = t -> len ;
3752
3772
3753
3773
/* make start and count being in range */
3774
+ start -= 1 ; /* First character is 1 */
3775
+
3754
3776
if (start < 0 )
3755
3777
start = 0 ;
3756
3778
if (count < 0 )
@@ -3761,10 +3783,7 @@ static Token *pp_substr(Token *tline, const char *dname)
3761
3783
start = -1 , count = 0 ; /* empty string */
3762
3784
3763
3785
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 );
3768
3787
}
3769
3788
3770
3789
/**
@@ -5893,14 +5912,19 @@ static SMacro *expand_one_smacro(Token ***tpp)
5893
5912
5894
5913
if (flags & SPARM_STR ) {
5895
5914
/* Convert expansion to a quoted string */
5896
- char * arg ;
5897
5915
Token * qs ;
5898
5916
5899
5917
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
+ }
5904
5928
}
5905
5929
}
5906
5930
}
@@ -7051,78 +7075,61 @@ stdmac_join(const SMacro *s, Token **params, int nparams)
7051
7075
static Token *
7052
7076
stdmac_strcat (const SMacro * s , Token * * params , int nparams )
7053
7077
{
7054
- Token * tline ;
7055
- (void )nparams ;
7078
+ int i ;
7079
+ size_t len = 0 ;
7080
+ char * str , * p ;
7056
7081
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 );
7060
7097
}
7061
7098
7062
7099
/* %substr() function */
7063
7100
static Token *
7064
7101
stdmac_substr (const SMacro * s , Token * * params , int nparams )
7065
7102
{
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 ;
7082
7104
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 ;
7087
7107
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 );
7093
7110
7094
- return t ;
7111
+ return pp_substr_common ( params [ 0 ], start , count ) ;
7095
7112
}
7096
7113
7097
7114
/* %strlen() function */
7098
7115
static Token *
7099
7116
stdmac_strlen (const SMacro * s , Token * * params , int nparams )
7100
7117
{
7101
- Token * t ;
7102
-
7103
7118
(void )nparams ;
7119
+ (void )s ;
7104
7120
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 );
7111
7123
}
7112
7124
7113
7125
/* %tok() function */
7114
7126
static Token *
7115
7127
stdmac_tok (const SMacro * s , Token * * params , int nparams )
7116
7128
{
7117
- Token * t ;
7118
-
7119
7129
(void )nparams ;
7130
+ (void )s ;
7120
7131
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 ])));
7126
7133
}
7127
7134
7128
7135
/* %cond() or %sel() */
@@ -7272,12 +7279,6 @@ struct magic_macros {
7272
7279
ExpandSMacro func ;
7273
7280
};
7274
7281
7275
- struct num_macros {
7276
- const char name [6 ];
7277
- uint8_t base ;
7278
- char prefix ;
7279
- };
7280
-
7281
7282
static void pp_add_magic_stdmac (void )
7282
7283
{
7283
7284
static const struct magic_macros magic_macros [] = {
@@ -7289,10 +7290,9 @@ static void pp_add_magic_stdmac(void)
7289
7290
{ "%count" , false, 1 , SPARM_VARADIC , stdmac_count },
7290
7291
{ "%eval" , false, 1 , SPARM_EVAL |SPARM_VARADIC , stdmac_join },
7291
7292
{ "%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 },
7296
7296
{ NULL , false, 0 , 0 , NULL }
7297
7297
};
7298
7298
const struct magic_macros * m ;
@@ -7361,6 +7361,18 @@ static void pp_add_magic_stdmac(void)
7361
7361
tmpl .params [2 ].def = make_tok_num (NULL , 10 );
7362
7362
define_smacro ("%num" , false, NULL , & tmpl );
7363
7363
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
+
7364
7376
/* %is...() macro functions */
7365
7377
nasm_zero (tmpl );
7366
7378
tmpl .nparam = 1 ;
0 commit comments