@@ -644,6 +644,7 @@ static Token *expand_smacro(Token * tline);
644644static Token * expand_id (Token * tline );
645645static Context * get_ctx (const char * name , const char * * namep );
646646static Token * make_tok_num (Token * next , int64_t val );
647+ static int64_t get_tok_num (const Token * t , bool * err );
647648static Token * make_tok_qstr (Token * next , const char * str );
648649static Token * make_tok_qstr_len (Token * next , const char * str , size_t len );
649650static Token * make_tok_char (Token * next , char op );
@@ -3584,6 +3585,7 @@ static Token *pp_strcat(Token *tline, const char *dname)
35843585
35853586 size_t len ;
35863587 Token * t ;
3588+ Token * res = NULL ;
35873589 char * q , * qbuf ;
35883590
35893591 len = 0 ;
@@ -3601,8 +3603,7 @@ static Token *pp_strcat(Token *tline, const char *dname)
36013603 default :
36023604 nasm_nonfatal ("non-string passed to `%s': %s" , dname ,
36033605 tok_text (t ));
3604- free_tlist (tline );
3605- return NULL ;
3606+ goto err ;
36063607 }
36073608 }
36083609
@@ -3613,9 +3614,11 @@ static Token *pp_strcat(Token *tline, const char *dname)
36133614 }
36143615 * q = '\0' ;
36153616
3616- return make_tok_qstr_len (NULL , qbuf , len );
3617+ res = make_tok_qstr_len (NULL , qbuf , len );
36173618 nasm_free (qbuf );
3618- return t ;
3619+ err :
3620+ free_tlist (tline );
3621+ return res ;
36193622}
36203623
36213624/*
@@ -3629,32 +3632,33 @@ static Token *pp_substr(Token *tline, const char *dname)
36293632 size_t len ;
36303633 struct ppscan pps ;
36313634 Token * t ;
3635+ Token * res = NULL ;
36323636 expr * evalresult ;
36333637 struct tokenval tokval ;
36343638
36353639 t = skip_white (tline );
36363640
36373641 if (!tok_is (t , TOKEN_STR )) {
36383642 nasm_nonfatal ("`%s' requires a string as parameter" , dname );
3639- return NULL ;
3643+ goto err ;
36403644 }
36413645
36423646 pps .tptr = skip_white (t -> next );
36433647 if (tok_is (pps .tptr , TOKEN_COMMA ))
36443648 pps .tptr = skip_white (pps .tptr -> next );
36453649 if (!pps .tptr ) {
36463650 nasm_nonfatal ("`%s' requires a starting index" , dname );
3647- return NULL ;
3651+ goto err ;
36483652 }
36493653
36503654 pps .ntokens = -1 ;
36513655 tokval .t_type = TOKEN_INVALID ;
36523656 evalresult = evaluate (ppscan , & pps , & tokval , NULL , true, NULL );
36533657 if (!evalresult ) {
3654- return NULL ;
3658+ goto err ;
36553659 } else if (!is_simple (evalresult )) {
36563660 nasm_nonfatal ("non-constant value given to `%s'" , dname );
3657- return NULL ;
3661+ goto err ;
36583662 }
36593663 start = evalresult -> value - 1 ;
36603664
@@ -3665,10 +3669,10 @@ static Token *pp_substr(Token *tline, const char *dname)
36653669 tokval .t_type = TOKEN_INVALID ;
36663670 evalresult = evaluate (ppscan , & pps , & tokval , NULL , true, NULL );
36673671 if (!evalresult ) {
3668- return NULL ;
3672+ goto err ;
36693673 } else if (!is_simple (evalresult )) {
36703674 nasm_nonfatal ("non-constant value given to `%s'" , dname );
3671- return NULL ;
3675+ goto err ;
36723676 }
36733677 count = evalresult -> value ;
36743678 }
@@ -3687,7 +3691,10 @@ static Token *pp_substr(Token *tline, const char *dname)
36873691 start = -1 , count = 0 ; /* empty string */
36883692
36893693 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 ;
36913698}
36923699
36933700/**
@@ -4850,7 +4857,6 @@ static int do_directive(Token *tline, Token **output)
48504857 */
48514858 if (macro_start )
48524859 define_smacro (mname , casesense , macro_start , NULL );
4853- free_tlist (tline );
48544860 break ;
48554861
48564862 case PP_SUBSTR :
@@ -4869,7 +4875,6 @@ static int do_directive(Token *tline, Token **output)
48694875 */
48704876 if (macro_start )
48714877 define_smacro (mname , casesense , macro_start , NULL );
4872- free_tlist (tline );
48734878 break ;
48744879
48754880 case PP_ASSIGN :
@@ -6909,22 +6914,34 @@ stdmac_join(const SMacro *s, Token **params, int nparams)
69096914static Token *
69106915stdmac_strcat (const SMacro * s , Token * * params , int nparams )
69116916{
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 );
69146923}
69156924
69166925/* %substr() function */
69176926static Token *
69186927stdmac_substr (const SMacro * s , Token * * params , int nparams )
69196928{
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 );
69226935}
69236936
69246937/* 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 )
69266939{
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 ));
69286945
69296946 if (!tok_is (t , TOKEN_STR )) {
69306947 nasm_nonfatal ("`%s' requires string as parameter" , dname );
@@ -6948,7 +6965,7 @@ stdmac_strlen(const SMacro *s, Token **params, int nparams)
69486965
69496966 (void )nparams ;
69506967
6951- t = expand_to_string (params [0 ], s -> name );
6968+ t = expand_to_string (& params [0 ], s -> name );
69526969 if (!t )
69536970 return NULL ;
69546971
@@ -6964,13 +6981,38 @@ stdmac_tok(const SMacro *s, Token **params, int nparams)
69646981
69656982 (void )nparams ;
69666983
6967- t = expand_to_string (params [0 ], s -> name );
6984+ t = expand_to_string (& params [0 ], s -> name );
69686985 if (!t )
69696986 return NULL ;
69706987
69716988 return reverse_tokens (tokenize (unquote_token_cstr (t )));
69726989}
69736990
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+
69747016/* Add magic standard macros */
69757017struct magic_macros {
69767018 const char * name ;
@@ -7027,9 +7069,26 @@ static void pp_add_magic_stdmac(void)
70277069 }
70287070 }
70297071
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+
70307089 /* %is...() macro functions */
7090+ nasm_zero (tmpl );
70317091 tmpl .nparam = 1 ;
7032- tmpl .varadic = true;
70337092 tmpl .expand = stdmac_is ;
70347093 tmpl .recursive = true;
70357094 name_buf [0 ] = '%' ;
@@ -7644,6 +7703,29 @@ static Token *make_tok_num(Token *next, int64_t val)
76447703 return next ;
76457704}
76467705
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+
76477729/* Create a quoted string token */
76487730static Token * make_tok_qstr_len (Token * next , const char * str , size_t len )
76497731{
0 commit comments