bash 5.2 bad substitution for ${x:+${x}[}

2022-10-20 Thread Martin von Gagern
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -g -O2
uname output: Linux … 5.18.16-…-amd64 #1 SMP PREEMPT_DYNAMIC Debian
5.18.16-… (2022-…) x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 5.2
Patch Level: !PATCHLEVEL!
Release Status: release

Description:

Some substitutions that used to work pre 5.2 are failing starting in
5.2. I did a git bisect on that, it's the initial 5.2 commit which
broke this, 
https://git.savannah.gnu.org/cgit/bash.git/commit/?h=bash-5.2&id=74091dd4e8086db518b30df7f222691524469998.

According to my reproducing example below, this appears to be due to a
combination of conditional substitution, a variable enclosed in curly
braces and an unbalanced opening square bracket that I think should
only be considered as text without any semantic relevance in this
position.

Repeat-By:

bash -c 'x=""; echo "a${x:+${x}[}b"'

Work-around:

Omit the inner curly braces, i.e. use "a${x:+$x[}b".



Re: bash tab variable expansion question?

2011-09-04 Thread Martin von Gagern
On -10.01.-28163 20:59, Chet Ramey wrote:
>> Bash-4.2 tries to leave what the
>> user typed alone, but that leads to an inherently ambiguous situation:
>> when do you quote the `$' in a filename (or, in this case, a directory
>> name)?  It could be a shell variable, and it could be a character in
>> the filename.

I'm not sure I'd EVER want completion to escape a $. If I want a
variable, I'll type $, either by itself or inside double quotation
marks. If I want a $ included in a file name, then I'll type \$ or
enclose it in single quotation marks. The above I'd do even for partial
file names. So if bash sees an unquoted $, then I'd call it a variable,
and no ambiguity involved.

> That is the problem, in a nutshell.  I posted a partial patch at the
> end of March that applied a heuristic to avoid quoting variable
> expansions in most cases, but there was no way to get the bash-4.1
> behavior back.

Can you explain these heuristics?

> I am soliciting feedback on this iteration.
> Please try the new option (`direxpand') and let me know if it's missing 
> anything.

The option works, as far as I can see.
"ls $HOM" completes to "ls $HOME " instead of "ls $HOME/", though.

The heuristics apparently don't work well with programmatic completion.
With _longopt <http://tinyurl.com/3va3hyz > from the debian bashcomp
project set up for ls, I get "\$HOME/.bash" as the completion for
"$HOME/.bash". And I get no completion at all for "ls $HOM", probably
because there is no dir of that name.

Can we do the following for programmatic completion?
1. If the insertion point is at a variable reference, and the
   referenced variable does not exist, then complete variable name
   without delegating to programmatic completion
2. Otherwise, store the original String for each word
3. Perform variable expansion for each word
4. Perform completion on the expanded words
5. In the completed words, search for the expanded but uncomleted
   strings from 3. and replace them with the unexpanded forms from 2.

I'm not sure what behaviour I'd expect if the variable contains several
words. Don't care too much for that case, so I'll be happy with any
solution.

Greetings,
 Martin von Gagern



signature.asc
Description: OpenPGP digital signature


Re: Mailcheck during completion

2011-08-12 Thread Martin von Gagern
On 12.08.2011 01:05, Chet Ramey wrote:
> It's eval.  Try the attached patch.

Works like a charm. Thanks a lot!

Martin




signature.asc
Description: OpenPGP digital signature


Re: Mailcheck during completion

2011-08-11 Thread Martin von Gagern
Hi Chet,

thanks for the swift reply!

On 11.08.2011 15:54, Chet Ramey wrote:
> I suspect that you have a completion defined for `ls' and it's running a
> command or process substitution that's causing the mail check.  Can you
> run `set -x', then attempt the completion again and post the results?

Yes, there is a completion function for ls coming from the _longopt
function from the bash-completion project at debian:
http://anonscm.debian.org/gitweb/?p=bash-completion/bash-completion.git;a=blob;f=bash_completion;h=66019379fe1e9ef9b1010bff53a0dc1baf4e73d9;hb=7c81ef895455d0f7543c65789ff62808e7465578#l1540

With -x enabled, I see several subprocess lines, i.e. lines indented by
two + instead of one. Some triggered by eval, others by $(...).

I wonder why this breaks things. After all, those subshells should never
print a prompt, should never even look for interactive input. But I take
it you've got your reasons to suspect them. Can this be fixed?

Greetings,
 Martin



signature.asc
Description: OpenPGP digital signature


completion handles variables inconsistently

2011-08-11 Thread Martin von Gagern
Hi!

If the current word on the command line contains a shell variable, then
the expansion works as if the variable had been expanded, but then
quotes the variable. An example is probably a lot better than theory:

Steps to reproduce
1. Type "echo $HOME/.bas"
2. Press tab
3. Press tab again

Actual results:
2. expands to "echo \$HOME/.bash", assuming that all files ~/.bas* share
the h as the fifth letter of their filename, and that at least two files
differ in their sixth letter.
3. no list of possible completions, as \$HOME no longer is a variable
reference, and there is no directory of that name suitable for expansion.

Expected results:
2. "echo $HOME/.bash"
3. List of file names printed to choose from

Past versions of bash up to 4.1 used to expand the variable when
completing. In those cases, the completed version would look like "echo
/home/user/.bash". A plain 4.2 build without any patches does exhibit
the new behaviour. So it's an issue introduced in that code base.
Unfortunately I know no source repository for bash where I could bisect
this down to a small commit.

I've reported this as https://bugs.gentoo.org/378669 as well, but there
appears to be nothing specific to Gentoo about this. So I'm forwarding
the bug report here.

Greetings,
 Martin von Gagern



signature.asc
Description: OpenPGP digital signature


Mailcheck during completion

2011-08-11 Thread Martin von Gagern
Hi!

I often get a bash message about new mail during command line completion.

Steps to reproduce:
Type "ls ~/.bas" and press tab.

Expected result:
Command line completed to "ls ~/.bash" or whatever is right.

Actual result:
If new mails have arrived, the mail check is performed when pressing
tab, rendering the whole command line like this:

$ ls ~/.basYou have mail in /var/mail/user
h

This is a real problem for both readability and subsequent editing of
the command line.

I would therefore like to see bash modified in such a way that the mail
check is never executed in response to a completion. Instead, the only
places where such a check should be performed are in my opinion the
initial prompt after startup and any prompt after a command was actually
executed. Just pressing enter with an empty command line should also do
the check, I think.

Greetings,
 Martin von Gagern




signature.asc
Description: OpenPGP digital signature


Re: extglobs in case constructs

2009-10-01 Thread Martin von Gagern
Chet Ramey wrote:
> In general, if you enable extglob before a function is parsed and leave
> it on when the function is executed, you should be ok.

I'm thinking about this in terms of bash completion functions. Many of
them use extended globs, but they should not force a specific permanent
extglob setting on the user. And cleanly restoring the setting can a bit
tricky. I believe I have a solution for this, though:
https://alioth.debian.org/tracker/index.php?func=detail&aid=311628&group_id=100114&atid=413095
Still, that solution brings a bit of overhead, and if that could have
been avoided, I'd been even happier.

> The reason that [[ conditional commands don't require extglob to be
> enabled while they're executed (and case commands do) lies in how the
> commands are defined to behave.  case commands are defined by Posix:
> the pattern is always a Posix shell pattern, and any extension to that
> must be enabled manually.  The [[ command, which bash picked up from ksh,
> is defined so that the rhs of `==' is an extended pattern (ksh always
> uses extended patterns, without requiring a special option).  For
> compatibility, bash forces the rhs of the [[ command's == and !=
> operators to be matched as an extended pattern when executed.

That's a good explanation, and a valid reason. If you say it's going to
stay that way, I'll accept that and stop suggesting alternatives.

Still, if there were a way to have the case command remember whether it
was defined with or without extglob, then that state could be recreated
when the command is executed. You'd still have to enable a manual switch
if you wanted to diverge from the Posix standard, only now it would only
have to be when you define the function. The benefit would be that the
semantics of the function would stay unaffected from later modifications
of this shopt.

As an alternative, would you consider things like "local shopts"? I'm
thinking about a flag like "-l" to shopt which would set the option for
the duration of the current function, but neither export it to functions
called therein nor leave it in place when the function returns. I
believe this would be quite a major task, but might be worthwhile for
functions that need to fine-tune these options but don't want to affect
their surroundings. If you are interested, I could try writing a patch.

> In fact, to be perfectly compatible, bash should temporarily enable
> extglob when parsing the rhs of `==' and `!=' inside a conditional
> command.  I will look at doing that for the next version.

I don't know if I speak for a majority of users, but in my daily use I
prefer bash to be usable intuitively, and consider compatibility to
other shells (which I rarely if ever use) second to that. Things change
if I want to write portable scripts, but in this case, I'd take plain sh
as the common denominator, and would also invoke bash with that name.

So yes, compatibility with other shells is nice, and always having
extended globs as the rhs of an == would increase the ease of use.
Different behaviour for different constructs on the other hand is quite
a bit counterintuitive, and for me personally compatibility with other
shells isn't important enough to warrant this quirk.

Greetings,
 Martin



signature.asc
Description: OpenPGP digital signature


Re: extglobs in case constructs

2009-10-01 Thread Martin von Gagern
Martin von Gagern wrote:
>   I've found out that extglobs behave differently in different
>   constructs. To avoid syntax errors, the always have to be
>   enabled at parse time.
>   For comparison constructs like ``[[ $v == a@(a|b|c)c ]]'' this
>   is enough. For case constructs like ``case $v in a@(a|b|c)c)''
>   the extglob shopt has to be set at runtime as well. This is kind
>   of inconsistent.

OK, I guess this is due to the following difference:

execute_cmd.c:3225-3231 in execute_cond_node:
> int oe;
> oe = extended_glob;
> extended_glob = 1;
> result = binary_test (cond->op->word, arg1, arg2, 
> TEST_PATMATCH|TEST_ARITHEXP)
> ? EXECUTION_SUCCESS
> : EXECUTION_FAILURE;
> extended_glob = oe;

execute_cmd.c:2931 in execute_case_command:
> match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != 
> FNM_NOMATCH;

What's interesting is what you don't see here: the case command doesn't
temporarily set extended_glob to 1 as the cond node does. I guess this
is where the different behaviour at runtime comes from.

Is this difference intentionally, or is this a bug? If it is a bug, the
attached patch should fix it, although it might introduce other issues.
At least for my example script, the patch does its job.

I'm a bit surprised that execute_cond_node seems to unconditionally
enable the extended glob mode. I don't see any check whether the thing
has been parsed as an extended glob in the first place.

Is this because things that look like extended globs will always be
invalid syntax if extglob is off? So that if anything got parsed
successfully and still looks like an extended glob, the code can be sure
it was parsed as an extended glob? In that case, is there any point in
not always enabling extended globs, except if you are testing the
portability of your script? If so, I'll second the request to always
enable them, but I have some doubts that's the case.

As an alternative to my patch, one could maybe move all this temporary
extglob stuff to the function definitions. I.e. a function defined with
extglob on will also have extglob on when executed, and vice versa. This
might break some compatibility, though, especially for subshells. And
simply saving and restoring functins by listing their definition would
become a trouble as well. So it's just a thought so far.

Greetings,
 Martin
Allow use of extended globs in case constructs at runtime,
even if the extglob shopt is not set.

2009-10-01 Martin von Gagern

References:
http://thread.gmane.org/gmane.comp.shells.bash.bugs/13518

Index: bash-4.0/execute_cmd.c
===
--- bash-4.0.orig/execute_cmd.c
+++ bash-4.0/execute_cmd.c
@@ -2915,6 +2915,7 @@ execute_case_command (case_command)
   QUIT;
   for (list = clauses->patterns; list; list = list->next)
{
+ int oe;
  es = expand_word_leave_quoted (list->word, 0);
 
  if (es && es->word && es->word->word && *(es->word->word))
@@ -2928,8 +2929,11 @@ execute_case_command (case_command)
  /* Since the pattern does not undergo quote removal (as per
 Posix.2, section 3.9.4.3), the strmatch () call must be able
 to recognize backslashes as escape characters. */
+ oe = extended_glob;
+ extended_glob = 1;
  match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != 
FNM_NOMATCH;
  free (pattern);
+ extended_glob = oe;
 
  dispose_words (es);
 


Re: extglobs in case constructs

2009-10-01 Thread Martin von Gagern
Greg Wooledge wrote:
> You're using extglobs inside a function, and extglob was enabled
> at the time the function was delcared.  The parser parsed them at that
> time, decided that they are extended globs, and therefore that's what
> they are.

Then why don't they work as extended globs if the extglob shopt is set
to off at runtime, from within the function, after it has been parsed?

> Most people have the opposite problem

I know, I understand the reason for this, and I even approve of it,
because after all, the use of extended globs is something the person
defining the function should worry about, not the person using the
function. Sadly, currently both have to worry.




signature.asc
Description: OpenPGP digital signature


extglobs in case constructs

2009-10-01 Thread Martin von Gagern
Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: linux-gnu
Compiler: i686-pc-linux-gnu-gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu'
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib
-DDEFAULT_PATH_VALUE='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
-DSTANDARD_UTILS_PATH='/bin:/usr/bin:/sbin:/usr/sbin'
-DSYS_BASHRC='/etc/bash/bashrc'
-DSYS_BASH_LOGOUT='/etc/bash/bash_logout' -DNON_INTERACTIVE_LOGIN_SHELLS
-DSSH_SOURCE_BASHRC -march=prescott -O2 -ggdb
uname output: Linux server 2.6.30-gentoo-r5 #1 SMP PREEMPT Tue Aug 18
11:26:16 CEST 2009 i686 Intel(R) Pentium(R) 4 CPU 3.00GHz GenuineIntel
GNU/Linux
Machine Type: i686-pc-linux-gnu

Bash Version: 4.0
Patch Level: 33
Release Status: release

Description:

I've found out that extglobs behave differently in different
constructs. To avoid syntax errors, the always have to be
enabled at parse time.
For comparison constructs like ``[[ $v == a@(a|b|c)c ]]'' this
is enough. For case constructs like ``case $v in a@(a|b|c)c)''
the extglob shopt has to be set at runtime as well. This is kind
of inconsistent.

I've read several messages by Chet on the bug-bash mailing list,
all claiming that the extglob shopt should change the parser
only. In this case one would expect that setting it at the time
a function gets defined should be enough, and that it shouldn't
be necessary when the function gets executed. Case constructs
inside a function render this assumption invalid.

Repeat-By:

-- Sample script ---

#!/bin/bash

shopt -s extglob
echo -n "definition: "
shopt extglob

f() {
v=abc

shopt $1 extglob
echo -n "  runtime: "
shopt extglob

echo -n "comparison uses extglob "
if [[ $v == a@(a|b|c)c ]]; then
echo "yes"
else
echo "no"
fi

echo -n "case uses extglob   "
case $v in
a@(a|b|c)c)
echo "yes"
;;
*)
echo "no"
;;
esac

}

f -s
f -u

-- Resulting output 

definition: extglob on
  runtime: extglob  on
comparison uses extglob yes
case uses extglob   yes
  runtime: extglob  off
comparison uses extglob yes
case uses extglob   no







Re: RFE: brace expansion sequences should do zero padding

2007-09-03 Thread Martin von Gagern
Eric Blake wrote:
> Perhaps rather than trying to improve bash {} expansion, you could use
> coreutils seq instead.

Hi Eric, thank's for taking an interest.

seq is not that much different from printf here, although I hadn't known
of its formatting capabilities. This changes nothing of the fact that
there are situations like the wget command in my last posting where
calling a subcommand isn't going to help much.

If I'd follow your argument, brace number sequences would not be needed
at all, as you can somehow use seq in most cases. However brace
sequences are part of bash, and for a good reason. For one they are a
lot easier to write than subcommand invocation, for a second you don't
have to worry so much about word splitting, and finally there are some
more complex cases where using a subcommand will make the command much
more complicated.

To give you another example, highlighting the word-splitting issue:

for i in $'This is record\n'{000..007}" of ${PWD}"; do
  echo "> $i <"
done

OK, yes, I could add all that text inside the loop, but I believe you
can think of uses of word lists where this isn't so easy. As you can
see, the escape string introduces spaces and a newline, and the variable
may introduce arbitrary other characters. Together you have no obvious
save character at which you can split the output of any subprocess into
words. So word splitting now becomes a real problem, whereas with brace
expansion the world splitting is implicit.

Yes, I know, this as well can be solved using other tools, probably
together with bash arrays. However there will be a huge overhead. On the
other hand, brace expansion is intuitive, quick to write, easy to read,
and gets the job done - if the job doesn't need the zero padding, or you
apply my patch.

Greetings,
 Martin von Gagern



signature.asc
Description: OpenPGP digital signature


Re: RFE: brace expansion sequences should do zero padding

2007-09-03 Thread Martin von Gagern
Hi again!

I saw my first post made it to the list eventually as well. Sorry for
the duplicate. I hadn't realized that the newsgroup was moderated.

I'm a bit dishearted at the lack of response. On IRC many people pointed
out that usually this kind of issue can be solved by passing a sequence
to printf. Now I've come up with a real life example that isn't easy to
hack together using printf:
wget -x http://some.really.long/url/prefix/{,{000..123}.{html,jpg}}

There have been some concerns about changing the behaviour and thus
breaking existing scripts. The preferred solution in this case would be
to use "..." instead of ".." if one wanted to activate this feature.
Personally I believe that zero padded sequences in an existing
application that cares for the exact string and not only the numeric
value are so unlikely that adding another piece of syntax is not worth
the trouble, but I'd like your opinion on this.

Another thing worth mentioning is negative numbers. My padding pads all
numbers to a common width, not a common number of digits. This is what
printf does, and it's a wee little bit easier to implement. However it
could be changed to common number of digits as well. On IRC I got the
idea that {-07..003} should do common width, whereas {-007..003} should
do common number of digits. This, however, would add a lot of code. I
think negative numbers are so rare that they are not worth the effort.
Do you agree?

I hope to generate some feedback here. If you think this useful, tell me
about it, and I'll try a bit harder to get this into the offical
sources. If I get no single answer this time as well, I'll probably post
the patch somewhere online, patch my own version of bash, and that's it.

Greetings,
 Martin von Gagern




signature.asc
Description: OpenPGP digital signature


RFE: brace expansion sequences should do zero padding [patch]

2007-08-29 Thread Martin von Gagern
Hi!

Suppose you have a set of files numbered and those numbers zero padded.
Of course you can list them using some magic with printf or some such,
but I would really love a simple feature like this:

cat x{000..123}

to concatenate files x000 through x123, not x0 through x123 as bash
currently does.

The attached patch should do the trick. I hope you agree with the place
where I chose to implement this feature. Do you think this has a chance
of getting implemented into the official source tree? If so, what is
left to do? Documentation? Any kind of test cases? Anything else?

Greetings,
 Martin von Gagern

P.S.: This is the second time I post this message here.
  The first one was via NNTP and it seems like it didn't make it.
Patch by Martin von Gagern <[EMAIL PROTECTED]>
to allow zero-padded numbers in bash brace expansion sequences.

diff -pur bash-3.2/braces.c bash/braces.c
--- bash-3.2/braces.c	2006-09-09 04:57:17.0 +0200
+++ bash/braces.c	2007-08-29 23:02:02.0 +0200
@@ -61,7 +61,7 @@
 static int brace_gobbler __P((char *, size_t, int *, int));
 static char **expand_amble __P((char *, size_t, int));
 static char **expand_seqterm __P((char *, size_t));
-static char **mkseq __P((int, int, int, int));
+static char **mkseq __P((int, int, int, int, int));
 static char **array_concat __P((char **, char **));
 #else
 static int brace_gobbler ();
@@ -303,8 +303,8 @@ mkseq (start, end, incr, type)
 #define ST_CHAR	2
 
 static char **
-mkseq (start, end, incr, type)
- int start, end, incr, type;
+mkseq (start, end, incr, type, width)
+ int start, end, incr, type, width;
 {
   int n, i;
   char **result, *t;
@@ -329,7 +329,7 @@ mkseq (start, end, incr, type)
   QUIT;		/* XXX - memory leak here */
 #endif
   if (type == ST_INT)
-	result[i++] = itos (n);
+	result[i++] = itospad (n, width, '0');
   else
 	{
 	  t = (char *)xmalloc (2);
@@ -353,7 +353,7 @@ expand_seqterm (text, tlen)
  size_t tlen;
 {
   char *t, *lhs, *rhs;
-  int i, lhs_t, rhs_t, lhs_v, rhs_v;
+  int lhs_l, rhs_l, lhs_t, rhs_t, lhs_v, rhs_v, width;
   intmax_t tl, tr;
   char **result;
 
@@ -361,9 +361,9 @@ expand_seqterm (text, tlen)
   if (t == 0)
 return ((char **)NULL);
 
-  i = t - text;		/* index of start of BRACE_SEQ_SPECIFIER */
-  lhs = substring (text, 0, i);
-  rhs = substring (text, i + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
+  lhs_l = t - text;		/* index of start of BRACE_SEQ_SPECIFIER */
+  lhs = substring (text, 0, lhs_l);
+  rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
 
   if (lhs[0] == 0 || rhs[0] == 0)
 {
@@ -399,9 +399,21 @@ expand_seqterm (text, tlen)
 {
   lhs_v = tl;		/* integer truncation */
   rhs_v = tr;
+
+  /* find out if the user wants padding, and if so how much */
+  rhs_l = tlen - lhs_l - sizeof(BRACE_SEQ_SPECIFIER) + 1;
+  width = 0;
+  if (lhs_l > 1 && lhs[0] == '0')
+	width = lhs_l;
+  if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0')
+	width = lhs_l;
+  if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l)
+	width = rhs_l;
+  if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l)
+	width = rhs_l;
 }
 
-  result = mkseq (lhs_v, rhs_v, 1, lhs_t);
+  result = mkseq (lhs_v, rhs_v, 1, lhs_t, width);
 
   free (lhs);
   free (rhs);
diff -pur bash-3.2/externs.h bash/externs.h
--- bash-3.2/externs.h	2006-07-28 03:40:49.0 +0200
+++ bash/externs.h	2007-08-29 22:21:16.0 +0200
@@ -178,6 +178,7 @@ extern char *inttostr __P((intmax_t, cha
 extern char *itos __P((intmax_t));
 extern char *uinttostr __P((uintmax_t, char *, size_t));
 extern char *uitos __P((uintmax_t));
+extern char *itospad __P((intmax_t, int, char));
 
 /* declarations for functions defined in lib/sh/makepath.c */
 #define MP_DOTILDE	0x01
diff -pur bash-3.2/lib/sh/itos.c bash/lib/sh/itos.c
--- bash-3.2/lib/sh/itos.c	2002-01-02 20:38:10.0 +0100
+++ bash/lib/sh/itos.c	2007-08-29 23:01:01.0 +0200
@@ -70,3 +70,43 @@ uitos (i)
   p = fmtumax (i, 10, lbuf, sizeof(lbuf), FL_UNSIGNED);
   return (savestring (p));
 }
+
+/* Integer to string conversion with padding.  This conses the string; the
+   caller should free it. */
+char *
+itospad (i, width, padchar)
+ intmax_t i;
+ int width;
+ char padchar;
+{
+  char *p, *buf, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
+  size_t len;
+
+  if (width + 1 <= sizeof(lbuf)) {
+len = sizeof(lbuf);
+buf = lbuf;
+  }
+  else {
+len = width + 1;
+buf = (char *)xmalloc (len);
+  }
+
+  p = fmtumax (i, 10, buf, len, 0);
+  /* The following padding implementation relies on the fact
+ that fmtumax fills the buffer from its end. */
+
+  if (p[0] != '-') {
+while (buf + len - p <= width)
+  *--p = padchar;
+  }
+  else {
+while (buf + len - p <= width)
+  *p-- = padchar;
+*p = '-';
+  }
+
+  if (buf == lbuf)
+buf = savestring (p);
+
+  return (buf);
+}



RFE: brace expansion sequences should do zero padding [patch]

2007-08-29 Thread Martin von Gagern
Hi!

Suppose you have a set of files numbered and those numbers zero padded.
Of course you can list them using some magic with printf or some such,
but I would really love a simple feature like this:

cat x{000..123}

to concatenate files x000 through x123, not x0 through x123 as bash
currently does.

The attached patch should do the trick. I hope you agree with the place
where I chose to implement this feature. Do you think this has a chance
of getting implemented into the official source tree? If so, what is
left to do? Documentation? Any kind of test cases? Anything else?

Greetings,
 Martin von Gagern
Patch by Martin von Gagern <[EMAIL PROTECTED]>
to allow zero-padded numbers in bash brace expansion sequences.

diff -pur bash-3.2/braces.c bash/braces.c
--- bash-3.2/braces.c	2006-09-09 04:57:17.0 +0200
+++ bash/braces.c	2007-08-29 23:02:02.0 +0200
@@ -61,7 +61,7 @@
 static int brace_gobbler __P((char *, size_t, int *, int));
 static char **expand_amble __P((char *, size_t, int));
 static char **expand_seqterm __P((char *, size_t));
-static char **mkseq __P((int, int, int, int));
+static char **mkseq __P((int, int, int, int, int));
 static char **array_concat __P((char **, char **));
 #else
 static int brace_gobbler ();
@@ -303,8 +303,8 @@ mkseq (start, end, incr, type)
 #define ST_CHAR	2
 
 static char **
-mkseq (start, end, incr, type)
- int start, end, incr, type;
+mkseq (start, end, incr, type, width)
+ int start, end, incr, type, width;
 {
   int n, i;
   char **result, *t;
@@ -329,7 +329,7 @@ mkseq (start, end, incr, type)
   QUIT;		/* XXX - memory leak here */
 #endif
   if (type == ST_INT)
-	result[i++] = itos (n);
+	result[i++] = itospad (n, width, '0');
   else
 	{
 	  t = (char *)xmalloc (2);
@@ -353,7 +353,7 @@ expand_seqterm (text, tlen)
  size_t tlen;
 {
   char *t, *lhs, *rhs;
-  int i, lhs_t, rhs_t, lhs_v, rhs_v;
+  int lhs_l, rhs_l, lhs_t, rhs_t, lhs_v, rhs_v, width;
   intmax_t tl, tr;
   char **result;
 
@@ -361,9 +361,9 @@ expand_seqterm (text, tlen)
   if (t == 0)
 return ((char **)NULL);
 
-  i = t - text;		/* index of start of BRACE_SEQ_SPECIFIER */
-  lhs = substring (text, 0, i);
-  rhs = substring (text, i + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
+  lhs_l = t - text;		/* index of start of BRACE_SEQ_SPECIFIER */
+  lhs = substring (text, 0, lhs_l);
+  rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
 
   if (lhs[0] == 0 || rhs[0] == 0)
 {
@@ -399,9 +399,21 @@ expand_seqterm (text, tlen)
 {
   lhs_v = tl;		/* integer truncation */
   rhs_v = tr;
+
+  /* find out if the user wants padding, and if so how much */
+  rhs_l = tlen - lhs_l - sizeof(BRACE_SEQ_SPECIFIER) + 1;
+  width = 0;
+  if (lhs_l > 1 && lhs[0] == '0')
+	width = lhs_l;
+  if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0')
+	width = lhs_l;
+  if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l)
+	width = rhs_l;
+  if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l)
+	width = rhs_l;
 }
 
-  result = mkseq (lhs_v, rhs_v, 1, lhs_t);
+  result = mkseq (lhs_v, rhs_v, 1, lhs_t, width);
 
   free (lhs);
   free (rhs);
diff -pur bash-3.2/externs.h bash/externs.h
--- bash-3.2/externs.h	2006-07-28 03:40:49.0 +0200
+++ bash/externs.h	2007-08-29 22:21:16.0 +0200
@@ -178,6 +178,7 @@ extern char *inttostr __P((intmax_t, cha
 extern char *itos __P((intmax_t));
 extern char *uinttostr __P((uintmax_t, char *, size_t));
 extern char *uitos __P((uintmax_t));
+extern char *itospad __P((intmax_t, int, char));
 
 /* declarations for functions defined in lib/sh/makepath.c */
 #define MP_DOTILDE	0x01
diff -pur bash-3.2/lib/sh/itos.c bash/lib/sh/itos.c
--- bash-3.2/lib/sh/itos.c	2002-01-02 20:38:10.0 +0100
+++ bash/lib/sh/itos.c	2007-08-29 23:01:01.0 +0200
@@ -70,3 +70,43 @@ uitos (i)
   p = fmtumax (i, 10, lbuf, sizeof(lbuf), FL_UNSIGNED);
   return (savestring (p));
 }
+
+/* Integer to string conversion with padding.  This conses the string; the
+   caller should free it. */
+char *
+itospad (i, width, padchar)
+ intmax_t i;
+ int width;
+ char padchar;
+{
+  char *p, *buf, lbuf[INT_STRLEN_BOUND(intmax_t) + 1];
+  size_t len;
+
+  if (width + 1 <= sizeof(lbuf)) {
+len = sizeof(lbuf);
+buf = lbuf;
+  }
+  else {
+len = width + 1;
+buf = (char *)xmalloc (len);
+  }
+
+  p = fmtumax (i, 10, buf, len, 0);
+  /* The following padding implementation relies on the fact
+ that fmtumax fills the buffer from its end. */
+
+  if (p[0] != '-') {
+while (buf + len - p <= width)
+  *--p = padchar;
+  }
+  else {
+while (buf + len - p <= width)
+  *p-- = padchar;
+*p = '-';
+  }
+
+  if (buf == lbuf)
+buf = savestring (p);
+
+  return (buf);
+}


make -j# for parallel build failed

2005-06-30 Thread Martin von Gagern
There was an issue reported and hopefully solved at gentoo:
http://bugs.gentoo.org/show_bug.cgi?id=87247
http://www.gentoo.org/cgi-bin/viewcvs.cgi/app-shells/bash/files/bash-3.0-parallel.patch?rev=1.1&content-type=text/vnd.viewcvs-markup
This should probably be fixed upstream as well.


___
Bug-bash mailing list
Bug-bash@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-bash