@@ -300,7 +300,7 @@ format_expand_arg(struct format_context *format, const char *name, const char *e
300300 const char * value ;
301301 const char * msgstart = name + STRING_SIZE ("%(prompt" );
302302 const int msglen = end - msgstart - 1 ;
303-
303+ char * tmp ;
304304 if (end && msglen > 0 && string_format (msgbuf , "%.*s" , msglen , msgstart )) {
305305 const char * msg = msgbuf ;
306306
@@ -310,7 +310,9 @@ format_expand_arg(struct format_context *format, const char *name, const char *e
310310 prompt = msg ;
311311 }
312312
313- value = read_prompt (prompt );
313+ tmp = argv_format_arg (& argv_env , prompt );
314+ value = read_prompt (tmp );
315+ free (tmp );
314316 if (value == NULL )
315317 return false;
316318 return string_format_from (format -> buf , & format -> bufpos , "%s" , value );
@@ -322,6 +324,7 @@ format_expand_arg(struct format_context *format, const char *name, const char *e
322324 const char * cstart = name + STRING_SIZE ("%(sh" );
323325 const int clen = end - cstart - 1 ;
324326 int size ;
327+ char * tmp ;
325328 FILE * cp ;
326329 if (end && clen > 0 && string_format (cbuf , "%.*s" , clen , cstart )) {
327330 c = cbuf ;
@@ -330,7 +333,9 @@ format_expand_arg(struct format_context *format, const char *name, const char *e
330333 }
331334 if (!* c || strlen (c )== 8 )
332335 return false;
333- cp = popen (c ,"r" );
336+ tmp = argv_format_arg (& argv_env , c );
337+ cp = popen (tmp ,"r" );
338+ free (tmp );
334339 size = fread (value ,1 ,SIZEOF_STR - 1 ,cp );
335340 if (value [0 ]== 0 || size == 0 )
336341 return false;
@@ -352,6 +357,64 @@ format_expand_arg(struct format_context *format, const char *name, const char *e
352357 return false;
353358}
354359
360+ static const char *
361+ get_closing_brace (const char * input )
362+ {
363+ const char * s = input ,* cur , * tmp ;
364+ int idx ,level = 0 ,pair_idx ;
365+ int level_to_pos [3000 ]= {[0 ... 2998 ]= -1 , -2 };
366+ int pos_to_level [256 ]= {[0 ... 254 ]= -1 , -2 };
367+ int pair_map [3000 ]= {[0 ... 2998 ]= -1 , -2 };
368+ int final_pairs [3000 ]= {[0 ... 2998 ]= -1 , -2 };
369+ int first = -1 ;
370+ while ( (cur = strstr (s ,"(" )), (tmp = strstr (s ,")" )), (cur && cur < tmp ?cur :(cur = tmp ))) {
371+ s = cur + 1 ;
372+ idx = cur - input ;
373+ if ( * cur == '(' ) {
374+ pos_to_level [idx ]= ++ level ;
375+ level_to_pos [level ]= idx ;
376+ } else if ( * cur == ')' ) {
377+ if ( level > 0 ) {
378+ pair_idx = level_to_pos [level ];
379+ pos_to_level [idx ]= level -- ;
380+ if (input [pair_idx ]== '(' && input [idx ]== ')' ||
381+ input [pair_idx ]== ')' && input [idx ]== '(' ) {
382+ final_pairs [idx ]= pair_idx ;
383+ final_pairs [pair_idx ]= idx ;
384+ }
385+ } else {
386+ pos_to_level [idx ]= -1 ;
387+ }
388+ }
389+ }
390+
391+ for (idx = 0 ;pos_to_level [idx ]!= -2 ; idx ++ ) {
392+ bool ok = false;
393+ if (pos_to_level [idx ]== -1 )
394+ continue ;
395+ for (int j = 0 ; final_pairs [j ]!= -2 ;j ++ ) {
396+ if (final_pairs [j ]== -1 )
397+ continue ;
398+ if (final_pairs [j ]== idx ) {
399+ if (idx == 0 )
400+ first = j ;
401+ ok = true;
402+ break ;
403+ }
404+ }
405+ if (!ok )
406+ return NULL ;
407+ }
408+
409+ if (pos_to_level [0 ] < 0 )
410+ return NULL ;
411+ if (first < 0 )
412+ return NULL ;
413+
414+ return input + first ;
415+ }
416+
417+
355418static bool
356419format_append_arg (struct format_context * format , const char * * * dst_argv , const char * arg )
357420{
@@ -362,7 +425,7 @@ format_append_arg(struct format_context *format, const char ***dst_argv, const c
362425 const char * var = strstr (arg , "%(" );
363426 const char * esc = strstr (arg , "%%" );
364427 bool is_escaped = esc && (esc < var || !var );
365- const char * closing = var && !is_escaped ? strchr (var , ')' ) : NULL ;
428+ const char * closing = var && !is_escaped ? get_closing_brace (var + 1 ) : NULL ;
366429 const char * next = is_escaped ? esc + 2 : closing ? closing + 1 : NULL ;
367430 int len = var && !is_escaped ? var - arg : esc ? esc - arg + 1 : strlen (arg );
368431
@@ -372,7 +435,7 @@ format_append_arg(struct format_context *format, const char ***dst_argv, const c
372435 if (len && !string_format_from (format -> buf , & format -> bufpos , "%.*s" , len , arg ))
373436 return false;
374437
375- if (var && !is_escaped && !format_expand_arg (format , var , next ))
438+ if (var && !is_escaped && !format_expand_arg (format , var , next ))
376439 return false;
377440
378441 arg = next ;
0 commit comments