@@ -644,6 +644,7 @@ static Token *expand_smacro(Token * tline);
644
644
static Token * expand_id (Token * tline );
645
645
static Context * get_ctx (const char * name , const char * * namep );
646
646
static Token * make_tok_num (Token * next , int64_t val );
647
+ static int64_t get_tok_num (const Token * t , bool * err );
647
648
static Token * make_tok_qstr (Token * next , const char * str );
648
649
static Token * make_tok_qstr_len (Token * next , const char * str , size_t len );
649
650
static Token * make_tok_char (Token * next , char op );
@@ -3584,6 +3585,7 @@ static Token *pp_strcat(Token *tline, const char *dname)
3584
3585
3585
3586
size_t len ;
3586
3587
Token * t ;
3588
+ Token * res = NULL ;
3587
3589
char * q , * qbuf ;
3588
3590
3589
3591
len = 0 ;
@@ -3601,8 +3603,7 @@ static Token *pp_strcat(Token *tline, const char *dname)
3601
3603
default :
3602
3604
nasm_nonfatal ("non-string passed to `%s': %s" , dname ,
3603
3605
tok_text (t ));
3604
- free_tlist (tline );
3605
- return NULL ;
3606
+ goto err ;
3606
3607
}
3607
3608
}
3608
3609
@@ -3613,9 +3614,11 @@ static Token *pp_strcat(Token *tline, const char *dname)
3613
3614
}
3614
3615
* q = '\0' ;
3615
3616
3616
- return make_tok_qstr_len (NULL , qbuf , len );
3617
+ res = make_tok_qstr_len (NULL , qbuf , len );
3617
3618
nasm_free (qbuf );
3618
- return t ;
3619
+ err :
3620
+ free_tlist (tline );
3621
+ return res ;
3619
3622
}
3620
3623
3621
3624
/*
@@ -3629,32 +3632,33 @@ static Token *pp_substr(Token *tline, const char *dname)
3629
3632
size_t len ;
3630
3633
struct ppscan pps ;
3631
3634
Token * t ;
3635
+ Token * res = NULL ;
3632
3636
expr * evalresult ;
3633
3637
struct tokenval tokval ;
3634
3638
3635
3639
t = skip_white (tline );
3636
3640
3637
3641
if (!tok_is (t , TOKEN_STR )) {
3638
3642
nasm_nonfatal ("`%s' requires a string as parameter" , dname );
3639
- return NULL ;
3643
+ goto err ;
3640
3644
}
3641
3645
3642
3646
pps .tptr = skip_white (t -> next );
3643
3647
if (tok_is (pps .tptr , TOKEN_COMMA ))
3644
3648
pps .tptr = skip_white (pps .tptr -> next );
3645
3649
if (!pps .tptr ) {
3646
3650
nasm_nonfatal ("`%s' requires a starting index" , dname );
3647
- return NULL ;
3651
+ goto err ;
3648
3652
}
3649
3653
3650
3654
pps .ntokens = -1 ;
3651
3655
tokval .t_type = TOKEN_INVALID ;
3652
3656
evalresult = evaluate (ppscan , & pps , & tokval , NULL , true, NULL );
3653
3657
if (!evalresult ) {
3654
- return NULL ;
3658
+ goto err ;
3655
3659
} else if (!is_simple (evalresult )) {
3656
3660
nasm_nonfatal ("non-constant value given to `%s'" , dname );
3657
- return NULL ;
3661
+ goto err ;
3658
3662
}
3659
3663
start = evalresult -> value - 1 ;
3660
3664
@@ -3665,10 +3669,10 @@ static Token *pp_substr(Token *tline, const char *dname)
3665
3669
tokval .t_type = TOKEN_INVALID ;
3666
3670
evalresult = evaluate (ppscan , & pps , & tokval , NULL , true, NULL );
3667
3671
if (!evalresult ) {
3668
- return NULL ;
3672
+ goto err ;
3669
3673
} else if (!is_simple (evalresult )) {
3670
3674
nasm_nonfatal ("non-constant value given to `%s'" , dname );
3671
- return NULL ;
3675
+ goto err ;
3672
3676
}
3673
3677
count = evalresult -> value ;
3674
3678
}
@@ -3687,7 +3691,10 @@ static Token *pp_substr(Token *tline, const char *dname)
3687
3691
start = -1 , count = 0 ; /* empty string */
3688
3692
3689
3693
txt = (start < 0 ) ? "" : tok_text (t ) + start ;
3690
- return make_tok_qstr_len (NULL , txt , count );
3694
+ res = make_tok_qstr_len (NULL , txt , count );
3695
+ err :
3696
+ free_tlist (tline );
3697
+ return res ;
3691
3698
}
3692
3699
3693
3700
/**
@@ -4850,7 +4857,6 @@ static int do_directive(Token *tline, Token **output)
4850
4857
*/
4851
4858
if (macro_start )
4852
4859
define_smacro (mname , casesense , macro_start , NULL );
4853
- free_tlist (tline );
4854
4860
break ;
4855
4861
4856
4862
case PP_SUBSTR :
@@ -4869,7 +4875,6 @@ static int do_directive(Token *tline, Token **output)
4869
4875
*/
4870
4876
if (macro_start )
4871
4877
define_smacro (mname , casesense , macro_start , NULL );
4872
- free_tlist (tline );
4873
4878
break ;
4874
4879
4875
4880
case PP_ASSIGN :
@@ -6909,22 +6914,34 @@ stdmac_join(const SMacro *s, Token **params, int nparams)
6909
6914
static Token *
6910
6915
stdmac_strcat (const SMacro * s , Token * * params , int nparams )
6911
6916
{
6912
- nasm_assert (nparams == 1 );
6913
- return pp_strcat (expand_smacro_noreset (params [0 ]), s -> name );
6917
+ Token * tline ;
6918
+ (void )nparams ;
6919
+
6920
+ tline = params [0 ];
6921
+ params [0 ] = NULL ; /* Don't free this later */
6922
+ return pp_strcat (expand_smacro_noreset (tline ), s -> name );
6914
6923
}
6915
6924
6916
6925
/* %substr() function */
6917
6926
static Token *
6918
6927
stdmac_substr (const SMacro * s , Token * * params , int nparams )
6919
6928
{
6920
- nasm_assert (nparams == 1 );
6921
- return pp_substr (expand_smacro_noreset (params [0 ]), s -> name );
6929
+ Token * tline ;
6930
+ (void )nparams ;
6931
+
6932
+ tline = params [0 ];
6933
+ params [0 ] = NULL ; /* Don't free this later */
6934
+ return pp_substr (expand_smacro_noreset (tline ), s -> name );
6922
6935
}
6923
6936
6924
6937
/* Expand a the argument and enforce it being a single quoted string */
6925
- static Token * expand_to_string (Token * tlist , const char * dname )
6938
+ static Token * expand_to_string (Token * * tp , const char * dname )
6926
6939
{
6927
- Token * t = zap_white (expand_smacro_noreset (tlist ));
6940
+ Token * tlist , * t ;
6941
+
6942
+ tlist = * tp ;
6943
+ * tp = NULL ; /* Don't free this later */
6944
+ t = zap_white (expand_smacro_noreset (tlist ));
6928
6945
6929
6946
if (!tok_is (t , TOKEN_STR )) {
6930
6947
nasm_nonfatal ("`%s' requires string as parameter" , dname );
@@ -6948,7 +6965,7 @@ stdmac_strlen(const SMacro *s, Token **params, int nparams)
6948
6965
6949
6966
(void )nparams ;
6950
6967
6951
- t = expand_to_string (params [0 ], s -> name );
6968
+ t = expand_to_string (& params [0 ], s -> name );
6952
6969
if (!t )
6953
6970
return NULL ;
6954
6971
@@ -6964,13 +6981,38 @@ stdmac_tok(const SMacro *s, Token **params, int nparams)
6964
6981
6965
6982
(void )nparams ;
6966
6983
6967
- t = expand_to_string (params [0 ], s -> name );
6984
+ t = expand_to_string (& params [0 ], s -> name );
6968
6985
if (!t )
6969
6986
return NULL ;
6970
6987
6971
6988
return reverse_tokens (tokenize (unquote_token_cstr (t )));
6972
6989
}
6973
6990
6991
+ /* %cond() or %sel() */
6992
+ static Token *
6993
+ stdmac_cond_sel (const SMacro * s , Token * * params , int nparams )
6994
+ {
6995
+ int64_t which ;
6996
+ bool err ;
6997
+
6998
+ /*
6999
+ * params[0] will have been generated by make_tok_num.
7000
+ */
7001
+ which = get_tok_num (params [0 ], & err );
7002
+ if (err )
7003
+ return NULL ; /* Nothing to expand */
7004
+
7005
+ if (s -> expandpvt .u ) {
7006
+ /* Booleanize (for %cond): true -> 1, false -> 2 (else) */
7007
+ which = which ? 1 : 2 ;
7008
+ }
7009
+
7010
+ if (which < 1 || which >= nparams )
7011
+ return NULL ;
7012
+
7013
+ return new_Token (NULL , tok_smac_param (which ), "" , 0 );
7014
+ }
7015
+
6974
7016
/* Add magic standard macros */
6975
7017
struct magic_macros {
6976
7018
const char * name ;
@@ -7027,9 +7069,26 @@ static void pp_add_magic_stdmac(void)
7027
7069
}
7028
7070
}
7029
7071
7072
+ /* %sel() function */
7073
+ tmpl .nparam = 2 ;
7074
+ tmpl .recursive = true;
7075
+ tmpl .expand = stdmac_cond_sel ;
7076
+ nasm_newn (tmpl .params , 2 );
7077
+ tmpl .params [0 ].flags = SPARM_EVAL ;
7078
+ tmpl .params [1 ].flags = SPARM_VARADIC ;
7079
+ define_smacro ("%sel" , false, NULL , & tmpl );
7080
+
7081
+ /* %cond() function, a variation on %sel */
7082
+ tmpl .expandpvt .u = 1 ; /* Booleanize */
7083
+ for (tmpl .nparam = 2 ; tmpl .nparam <= 3 ; tmpl .nparam ++ ) {
7084
+ nasm_newn (tmpl .params , tmpl .nparam );
7085
+ tmpl .params [0 ].flags = SPARM_EVAL ;
7086
+ define_smacro ("%cond" , false, NULL , & tmpl );
7087
+ }
7088
+
7030
7089
/* %is...() macro functions */
7090
+ nasm_zero (tmpl );
7031
7091
tmpl .nparam = 1 ;
7032
- tmpl .varadic = true;
7033
7092
tmpl .expand = stdmac_is ;
7034
7093
tmpl .recursive = true;
7035
7094
name_buf [0 ] = '%' ;
@@ -7644,6 +7703,29 @@ static Token *make_tok_num(Token *next, int64_t val)
7644
7703
return next ;
7645
7704
}
7646
7705
7706
+ /*
7707
+ * Do the inverse of make_tok_num(). This only needs to be able
7708
+ * to parse the output of make_tok_num().
7709
+ */
7710
+ static int64_t get_tok_num (const Token * t , bool * err )
7711
+ {
7712
+ bool minus = false;
7713
+ int64_t v ;
7714
+
7715
+ if (tok_is (t , '-' )) {
7716
+ minus = true;
7717
+ t = t -> next ;
7718
+ }
7719
+ if (!tok_is (t , TOKEN_NUM )) {
7720
+ if (err )
7721
+ * err = true;
7722
+ return 0 ;
7723
+ }
7724
+
7725
+ v = readnum (tok_text (t ), err );
7726
+ return minus ? - v : v ;
7727
+ }
7728
+
7647
7729
/* Create a quoted string token */
7648
7730
static Token * make_tok_qstr_len (Token * next , const char * str , size_t len )
7649
7731
{
0 commit comments