Re: select syntax violates the POLA

2021-04-08 Thread Robert Elz
Date:Wed, 07 Apr 2021 22:24:27 -0400
From:wor...@alum.mit.edu (Dale R. Worley)
Message-ID:  <87a6q9ikdg@hobgoblin.ariadne.com>

  | "The documentation is the contract between the user and
  | the implementer."  If something undocumented happens to work, there is
  | no requirement on the implementer to maintain its functionality.

That might, or might not, be true - in both directions (implementors
are often constrained to keep old things, that were never documented,
working, because they became known, and are used - similarly some
things were once documented, but are no longer, as a better solution
was implemented - but the old undocumented code has to stay, essentially
forever, for the benefit of those who used it when it was documented).

But whatever all that ends up meaning, if anything significant here,
it certainly does not mean that the implementation is required to
reject extensions that are not documented.   Or that it is any kind
of bug for it not to do so.

As long as you stick to using the implementation as documented (you
keep up your end of the "contract"), you will never observe this happening.
But when someone else does not, and asks about something that looks like
it is using undocumented behaviour, it might be OK to suggest to them
that what they're doing is unsafe - but not to suggest that the implementation
should reject what they are doing.


That is ' "{" should not be recognized as a reserved word in this situation. '
is simply wrong.  The situation mentioned was "else {", which actually is
documented as working, but never mind.

kre





Re: select syntax violates the POLA

2021-04-07 Thread Dale R. Worley
Robert Elz  writes:
> You're assuming that the manual is a precise specification of what
> is allowed.

Um, of course.  "The documentation is the contract between the user and
the implementer."  If something undocumented happens to work, there is
no requirement on the implementer to maintain its functionality.

Dale



Re: select syntax violates the POLA

2021-04-05 Thread Greywolf

On 4/5/2021 14:21, Chet Ramey wrote:

This presented an opportunity to marginally simplify the grammar, so it's a
win all around.

The change will be in the next devel branch push.


You have my sincere gratitude.  I did not expect so much to come of it.


Chet


--*greywolf;




Re: select syntax violates the POLA

2021-04-05 Thread Greywolf

On 4/5/2021 13:52, Chet Ramey wrote:

On 4/1/21 5:40 PM, Greywolf wrote:


Or do you mean my coding style (which has been valid for over 25 years)?



Hey, if you want to go there, `select' has been in  bash with its current
syntax for longer than that. ;-)

(A month over 27 years, if you're curious.)



HAH!  And I only just found about it very recently while perusing the
man page!  Go figure!

In any case, I apologise if, at any point, I came across as hostile
(never my intent), and I thank you for taking the time to parley.
I've learned a few things.

--*greywolf;



Re: select syntax violates the POLA

2021-04-05 Thread Chet Ramey

On 4/1/21 5:54 PM, Greywolf wrote:


On 4/1/2021 8:57, Chet Ramey wrote:


It's more like `select' doesn't inherit some of the shell's special cases.


    select dir in ${d[@]}; do {
    break;
    } done;

...but select breaks on the "} done;" syntax 


Yes, you need a list terminator so that `done' is recognized as a reserved
word here. `;' is sufficient. Select doesn't allow the `done' unless it's
in a command position. Some of the other compound commands have special
cases, mostly inherited from the Bourne shell, to allow it.


I took a look at bash-1.14, where the `select' command first appeared. At
the time, it was identical to the `for' command -- which makes sense, since
the syntaxes are essentially identical (and internally, they are
represented the same way). They both used the `list' grammar production.

When I updated the grammar to use the `compound_list' production in
bash-2.0, to be closer to how POSIX specified the compound commands in the
POSIX grammar, I left the select command alone. It's been the same way
since late 1994, though bash-2.0 wasn't released until 1996.

I took this opportunity to examine the grammar again, and there's no good
reason `select' and `for' should be different -- they started out the same,
and they should both use compound_list now. So they will.

This presented an opportunity to marginally simplify the grammar, so it's a
win all around.

The change will be in the next devel branch push.

Chet

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: select syntax violates the POLA

2021-04-05 Thread Chet Ramey

On 4/1/21 9:23 PM, Dale R. Worley wrote:

Greg Wooledge  writes:

It's amazing how many people manage to post their code with NO comments
or explanations of what it's supposed to do, what assumptions are being
made about the inputs, etc.  This leaves us to guess.


It seems to be a modern style.  When I was learning to program, poorly
commented code was considered a failing.  But recently, I have had
managers object that I put too many comments in.


If it was hard to write, it should be hard to understand!

(That's snark, for those who are wondering.)

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: select syntax violates the POLA

2021-04-05 Thread Chet Ramey

On 4/1/21 5:40 PM, Greywolf wrote:


Or do you mean my coding style (which has been valid for over 25 years)?



Hey, if you want to go there, `select' has been in  bash with its current
syntax for longer than that. ;-)

(A month over 27 years, if you're curious.)

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: select syntax violates the POLA

2021-04-05 Thread Greywolf

On 4/5/2021 6:27, Chet Ramey wrote:

On 4/5/21 5:06 AM, Greywolf wrote:


but if you want to go down that track, it's kind of interesting to note
that {} on a single line demands a ; before the }, while () prohibits
it. 


This isn't true:

$ ./bash -c '(echo a b c;)'
a b c

but it is the case that } is a reserved word, while ) is an operator.



D'OH!  You're right!

I was thinking

$ foo &;

Can't put a semicolon after a null statement.

My mistake.  Carry on...

--*greywolf;



Re: select syntax violates the POLA

2021-04-05 Thread Chet Ramey

On 4/5/21 5:06 AM, Greywolf wrote:


the same level of
egregious brokenness as select.


Good god, take a breath.


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: select syntax violates the POLA

2021-04-05 Thread Chet Ramey

On 4/5/21 5:06 AM, Greywolf wrote:


but if you want to go down that track, it's kind of interesting to note
that {} on a single line demands a ; before the }, while () prohibits
it. 


This isn't true:

$ ./bash -c '(echo a b c;)'
a b c

but it is the case that } is a reserved word, while ) is an operator.


--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: select syntax violates the POLA

2021-04-05 Thread Greywolf

On 4/2/2021 8:21, konsolebox wrote:
That's not a rule but a special compromise.  [[ ]] and (( )) are a 
form of reserved words themselves just like () and {} as they can be 
used multi-line but they aren't allowed to be adjacent to else et al 
without a semicolon.  [[ ]], (( )), {}, and () are practically just 
commands with first-class parsing that consistently have to end with

a semicolon if followed by another reserved word or command.



I'd call it less a compromise than a mechanism; of all listed,
{} represents a block of code in the current shell, () represents
a block of code in a subshell...

but if you want to go down that track, it's kind of interesting to note
that {} on a single line demands a ; before the }, while () prohibits
it. This also seems inconsistent to me, but not at the same level of
egregious brokenness as select.

--*greywolf;



Re: select syntax violates the POLA

2021-04-05 Thread Greywolf

On 4/1/2021 8:57, Chet Ramey wrote:

Yes, you need a list terminator so that `done' is recognized as a reserved
word here. `;' is sufficient. Select doesn't allow the `done' unless it's
in a command position. Some of the other compound commands have special
cases, mostly inherited from the Bourne shell, to allow it.


I don't know that I'd call them "special cases" if sh has pretty much 
condoned it from the get-go; 'select' is the outlier, from my POV.


--*greywolf;




Re: select syntax violates the POLA

2021-04-05 Thread Greywolf

On 4/4/2021 23:13, konsolebox wrote:

On Sat, Apr 3, 2021 at 1:09 AM Robert Elz  wrote:

   |  [[ ]] and (( )) are a form of reserved words themselves

Those are bash specials, and I am fairly sure that (( and )) will be
operators, not reserved words (they cannot really be the latter, as ( and
) are operators) and I suspect that [[ and ]] might be as well, but there
I'm not sure.   operators and reserved words are quite different things.
Operators (unquoted) are recognised as themselves wherever they appear.


Stop suspecting and read the source code.  Look at parse.y starting at
line 2150.  They are labeled as "Reserved words".




[[ and ]] behave like reserved words requiring whitespace between
themselves and their operands.  (( and )) do not carry that restriction;
within (( )), neither do any of */%^&|+- (or their respective OP=),
nor == || && !.  This effectively classifies (( )) as operators.

But we've drifted considerably afield.

--*greywolf;



Re: select syntax violates the POLA

2021-04-05 Thread Oğuz
5 Nisan 2021 Pazartesi tarihinde konsolebox  yazdı:
>
> The manual itself may be lacking in some places but the syntax here is
> explicit. There's no reason to follow otherwise. These "other methods"
> can only be an implementation mistake or a compromise that's not
> exactly a supported functionality or feature. This case where () and
> {} are allowed to not end with semicolon before 'else' when others
> aren't is likely one.


These all work (as expected) on the development branch:

bash-5.1$ if : ; then case _ in esac else : ; fi
bash-5.1$ if : ; then for _ do : ; done else : ; fi
bash-5.1$ if : ; then [[ _ ]] else : ; fi
bash-5.1$ if : ; then (( 0 )) else : ; fi
bash-5.1$ if { : ; } then while { : ; } do break ; done else : ; fi
bash-5.1$

If they didn't that'd be a defect in the shell, POSIX allows these
constructs, and it also makes sense that a list separator is optional
between else and the preceding command when that command is terminated with
a reserved word.


> > and the ';' there is just an
> > indication that something must ensure that the word that follows is
> > correctly interpreted as a reserved word (when one is required).
>
> Then why does it not work with other keywords that begin a block?


It does work with then, do, elif, else, done, esac, and }.


-- 
Oğuz


Re: select syntax violates the POLA

2021-04-05 Thread konsolebox
On Sat, Apr 3, 2021 at 1:09 AM Robert Elz  wrote:
>   |  [[ ]] and (( )) are a form of reserved words themselves
>
> Those are bash specials, and I am fairly sure that (( and )) will be
> operators, not reserved words (they cannot really be the latter, as ( and
> ) are operators) and I suspect that [[ and ]] might be as well, but there
> I'm not sure.   operators and reserved words are quite different things.
> Operators (unquoted) are recognised as themselves wherever they appear.

Stop suspecting and read the source code.  Look at parse.y starting at
line 2150.  They are labeled as "Reserved words".


-- 
konsolebox



Re: select syntax violates the POLA

2021-04-04 Thread konsolebox
On Mon, Apr 5, 2021 at 12:46 PM Robert Elz  wrote:
>
> Date:Sun, 04 Apr 2021 20:27:15 -0400
> From:wor...@alum.mit.edu (Dale R. Worley)
> Message-ID:  <87wntha84c@hobgoblin.ariadne.com>
>
>
>   | The manual page says
>   |
>   |if list; then list; [ elif list; then list; ] ... [ else list; ] fi
>   |
>   | so clearly there should be a ; or newline before the list in the
>   | else-clause.
>
> You're assuming that the manual is a precise specification of what
> is allowed.  It isn't.  At least in this case it shows something that
> works, so if you write an if statement that way, it will function.
> That does not imply that there are not other methods.

The manual itself may be lacking in some places but the syntax here is
explicit. There's no reason to follow otherwise. These "other methods"
can only be an implementation mistake or a compromise that's not
exactly a supported functionality or feature. This case where () and
{} are allowed to not end with semicolon before 'else' when others
aren't is likely one.

> and the ';' there is just an
> indication that something must ensure that the word that follows is
> correctly interpreted as a reserved word (when one is required).

Then why does it not work with other keywords that begin a block?  The
enclosure of {} and () should make semicolons optional for parsing
with them as well.  This should have been explicitly allowed by the
shell.  It's highly doable even if they are followed with
non-keywords.  Just look at awk's syntax.



--
konsolebox



Re: select syntax violates the POLA

2021-04-04 Thread Robert Elz
Date:Sun, 04 Apr 2021 20:27:15 -0400
From:wor...@alum.mit.edu (Dale R. Worley)
Message-ID:  <87wntha84c@hobgoblin.ariadne.com>


  | The manual page says
  |
  |if list; then list; [ elif list; then list; ] ... [ else list; ] fi
  |
  | so clearly there should be a ; or newline before the list in the
  | else-clause.

You're assuming that the manual is a precise specification of what
is allowed.  It isn't.  At least in this case it shows something that
works, so if you write an if statement that way, it will function.
That does not imply that there are not other methods.

In general, when reading the bash man page, anywhere it says "list;"
(except apparently in select statements) you should read that as meaning
the same as the POSIX compound_list, and the ';' there is just an
indication that something must ensure that the word that follows is
correctly interpreted as a reserved word (when one is required).  A ';'
will do that.   So do other things.

kre

ps: you can also use '&' in place of ';' or newline, when a separator
is required.   Though that gives the preceding command a different
operational behaviour of course.




Re: select syntax violates the POLA

2021-04-04 Thread Dale R. Worley
Robert Elz  writes:
> From:wor...@alum.mit.edu (Dale R. Worley)
>
>   | I was going to ask why "else {" works,
>
> The right question would be why '} else' works.

Yeah, typo on my part.  The manual page says

   if list; then list; [ elif list; then list; ] ... [ else list; ] fi

so clearly there should be a ; or newline before the list in the
else-clause.  But the grammar doesn't seem to enforce that:

if_clause  : If compound_list Then compound_list else_part Fi

I'm sure that the real answer involves decrypting the logic inside Bash
that turns on recognition of reserved words, and that must be more
complicated than the rule in the manual page.

Dale



Re: select syntax violates the POLA

2021-04-02 Thread Ilkka Virta
On Thu, Apr 1, 2021 at 7:59 PM Robert Elz  wrote:

> Alternatively
> d=( $( ls -d /usr/src/pkg/*/$1 ) )
> or just
> d=( $( printf %s\\n /usr/src/pkg/*/$1 ) )
>
> Just to be sure.Personally I'd do
>
> set -- /usr/src/pkg/*/$1
>

Just the glob is fine in the array assignment, it splits and globs the same
as in arguments to  'set':

d=( /usr/src/pkg/*/$1 )

(If there was any context that splits but doesn't glob, this isn't one)


Re: select syntax violates the POLA

2021-04-02 Thread Ilkka Virta
On Fri, Apr 2, 2021 at 2:04 AM Robert Elz  wrote:

> chet.ra...@case.edu said:
>   | Yes, you need a list terminator so that `done' is recognized as a
> reserved
>   | word here. `;' is sufficient. Select doesn't allow the `done' unless
> it's
>   | in a command position.
>
> isn't really all that appealing as an explanation.   select isn't part
> of the standard, so its syntax is arbitrary, which means that nothing can
> really be considered wrong, but while we often think of reserved words
> (not counting the special cases in case and for statements) as only working
> in the command word position, that's not how it really is.  They work
> there,
> they also should work following other reserved words (most of them, but
> '}' is not one of the exceptions).   so '} done' should work correctly,
> always, if the '}' is a reserved word, and a ';' or newline between them
> should not be needed.
>

FWIW, it works in the other shells I know that support select:

 $ cat select.sh
select x in foo bar; do {
echo $x;
break;
} done;

$ for sh in bash ksh mksh zsh; do echo "== $sh"; $sh select.sh <<< 1; done
== bash
select.sh: line 5: syntax error near unexpected token ‘done’
select.sh: line 5: `} done;'
== ksh
1) foo
2) bar
foo
== mksh
1) foo
2) bar
#? foo
== zsh
1) foo  2) bar
?# foo


Re: select syntax violates the POLA

2021-04-02 Thread Robert Elz
Date:Fri, 02 Apr 2021 09:02:40 +0200
From:Andreas Schwab 
Message-ID:  <87o8exp3sf@linux-m68k.org>

  | The two case are not really different, they are covered by the same
  | rule:

Yes, I knew that ... but they are different, as in the "else {" case
the '{' is in the command word position (which "else" is not in "} else")
and so is a reserved word for that reason as well.

Everyone (well, everyone who understands something about shell syntax)
knows the "reserved words happen in the command word position" rule, it
is what makes

echo if I do it while the case is ! done then in payment for ...

work without there being anything which is a reserved word there, but
(as is obvious by some of this discussion) not everyone realises the
consecutive reserved words rule exists.

kre




Re: select syntax violates the POLA

2021-04-02 Thread Robert Elz
Date:Fri, 2 Apr 2021 23:06:40 +0800
From:konsolebox 
Message-ID:  


  | > The right question would be why '} else' works.
  |
  | This inconsistency should be fixed and prevent people from
  | using it wrong.  `}; else` should work

Yes.

  | but not `} else`

No, that should work too.  The "then" part of an if statement (which is what
the '}' is the last element of in that example, obviously, takes a list

if_clause  : If compound_list Then compound_list else_part Fi

and the list (compound_list in posix speak) can be

compound_list : linebreak term

where linebreak is an optional newline (but is before the term anyway
so isn't relevant here as we're looking at the ending, not the beginning)

and term can be

term  : and_or

and and-or can be

and_or  :  pipeline

and pipeline can be

pipeline  : pipe_sequence

and pipe_sequence can be

pipe_sequence :  command

and command can be

command  :   compound_command

and compound_command can be

compound_command : brace_group

and brace_group is

brace_group  : Lbrace compound_list Rbrace
 ;

Observe that following that sequence, there is no separator (';' etc)
required between the Rbrace ('}') that terminates the brace_group
which is the compound_command which is the command which is the pipe_sequence
which is the pipeline which is the and_or which is the term which is the
last thing in the compound_list after which "else" follows immediately.

Of course, all the "can be" rules above have alternatives, other things
are possible, in particular, the full rule for compound_list is

compound_list  : linebreak term
   | linebreak term separator
   ;

so it is obvious (very obvious) that a separator is allowed after the
term, but not required.

  | just like how `{ :; } :` doesn't.

That is an entirely different thing.  ':' isn't a reserved word, so the
reserved word rule isn't relevant, and sequential commands (like the group,
and the second ':' in that example) need to be separated by some kind of
separator (';' '&' or newline).

And from your other message:

  | That's not a rule but a special compromise.

No, it is a rule, it is required to allow the 'else' in the example above
to be a reserved word, otherwise it would just be a normal word, and that
would be a syntax error.

  |  [[ ]] and (( )) are a form of reserved words themselves

Those are bash specials, and I am fairly sure that (( and )) will be
operators, not reserved words (they cannot really be the latter, as ( and
) are operators) and I suspect that [[ and ]] might be as well, but there
I'm not sure.   operators and reserved words are quite different things.
Operators (unquoted) are recognised as themselves wherever they appear.

  | just like () and {}

'(' and ')' are operators.  '{' and '}' are reserved words.

  | as they can be used multi-line but

That has nothing to do with anything.   Anywhere where the grammar allows
linebreak or separator (maybe more) can be used multi-line.   Anwhere those
things are not in the grammar, line breaks (not counting \newline or quoted
newlines) are not permitted.

  | but they aren't allowed to be adjacent to else et al without a semicolon.

Nonsense.

  | practically just commands with first-class parsing that consistently
  | have to end with a semicolon

No, they don't (even if you extend semicolon to include ampersand and newline).

  | if followed by another reserved word or command

if followed by another command yes, as the separator is just that, a separator,
it separates different commands, it is not a terminator (unlike the ';' in
C expression statements for example).

Where reserved words are allowed entirely depends upon what the grammar
allows.   And as above, "} else {" is a perfectly valid sequence as part of
an "if" statement.

kre




Re: select syntax violates the POLA

2021-04-02 Thread konsolebox
On Fri, Apr 2, 2021 at 3:03 PM Andreas Schwab  wrote:
>
> On Apr 02 2021, Robert Elz wrote:
>
> > Date:Thu, 01 Apr 2021 21:33:31 -0400
> > From:wor...@alum.mit.edu (Dale R. Worley)
> > Message-ID:  <874kgpqxlg@hobgoblin.ariadne.com>
> >
> >   | I was going to ask why "else {" works,
> >
> > Wrong question.  That one is easy.  What follows
> > 'else' is a list and the simplest form of a list
> > is a simple command, which starts with a command
> > word, so reserved words are always going to work
> > there, even without the "follows a reserved word'
> > rule.
> >
> > The right question would be why '} else' works.
>
> The two case are not really different, they are covered by the same
> rule:
>
> This recognition shall only occur when none of the characters is
> quoted and when the word is used as:
>
> * The first word following one of the reserved words other than
>   case, for, or in
>
That's not a rule but a special compromise.  [[ ]] and (( )) are a
form of reserved words themselves just like () and {} as they can be
used multi-line but they aren't allowed to be adjacent to else et al
without a semicolon.  [[ ]], (( )), {}, and () are practically just
commands with first-class parsing that consistently have to end with a
semicolon if followed by another reserved word or command.


-- 
konsolebox



Re: select syntax violates the POLA

2021-04-02 Thread konsolebox
On Fri, Apr 2, 2021 at 11:41 AM Robert Elz  wrote:
>
> Date:Thu, 01 Apr 2021 21:33:31 -0400
> From:wor...@alum.mit.edu (Dale R. Worley)
> Message-ID:  <874kgpqxlg@hobgoblin.ariadne.com>
>
>   | I was going to ask why "else {" works,
>
> Wrong question.  That one is easy.  What follows
> 'else' is a list and the simplest form of a list
> is a simple command, which starts with a command
> word, so reserved words are always going to work
> there, even without the "follows a reserved word'
> rule.
>
> The right question would be why '} else' works.

Indeed.  This inconsistency should be fixed and prevent people from
using it wrong.  `}; else` should work but not `} else` just like how
`{ :; } :` doesn't.


-- 
konsolebox



Re: select syntax violates the POLA

2021-04-02 Thread Andreas Schwab
On Apr 02 2021, Robert Elz wrote:

> Date:Thu, 01 Apr 2021 21:33:31 -0400
> From:wor...@alum.mit.edu (Dale R. Worley)
> Message-ID:  <874kgpqxlg@hobgoblin.ariadne.com>
>
>   | I was going to ask why "else {" works,
>
> Wrong question.  That one is easy.  What follows
> 'else' is a list and the simplest form of a list
> is a simple command, which starts with a command
> word, so reserved words are always going to work
> there, even without the "follows a reserved word'
> rule.
>
> The right question would be why '} else' works.

The two case are not really different, they are covered by the same
rule:

This recognition shall only occur when none of the characters is
quoted and when the word is used as:

* The first word following one of the reserved words other than
  case, for, or in

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



Re: select syntax violates the POLA

2021-04-01 Thread Robert Elz
Date:Thu, 01 Apr 2021 21:33:31 -0400
From:wor...@alum.mit.edu (Dale R. Worley)
Message-ID:  <874kgpqxlg@hobgoblin.ariadne.com>

  | I was going to ask why "else {" works,

Wrong question.  That one is easy.  What follows
'else' is a list and the simplest form of a list
is a simple command, which starts with a command
word, so reserved words are always going to work
there, even without the "follows a reserved word'
rule.

The right question would be why '} else' works.

kre



Re: select syntax violates the POLA

2021-04-01 Thread Greywolf

On 4/1/2021 16:03, Robert Elz wrote:

Partly because if you didn't use the braces, the issue wouldn't have arisen.
(And because to most of us it just looks weird, kind of like people
who write functions like f() {( commands to run in a subshell )}
where the braces do nothing useful at all. and should just be omitted.


Heh.  Nope -- if it's to be subshelled, I do not use the braces
around the parens.


that's not an unreasonable use explanation.  I find that a consistent
style and correct indentation work well enough for this though.


I have a consistent style and indentation ("correct" is subjective) :)


... so '} done' should work correctly,
always, if the '}' is a reserved word, and a ';' or newline between them
should not be needed.


Which was why I was kind of taken aback when it failed.


kre


Thank you, again!

--*greywolf;




Re: select syntax violates the POLA

2021-04-01 Thread Dale R. Worley
Chet Ramey  writes:
> Yes, you need a list terminator so that `done' is recognized as a reserved
> word here. `;' is sufficient. Select doesn't allow the `done' unless it's
> in a command position. Some of the other compound commands have special
> cases, mostly inherited from the Bourne shell, to allow it.

I was going to ask why "else {" works, since according to the manual
page, "{" should not be recognized as a reserved word in this situation.

Dale



Re: select syntax violates the POLA

2021-04-01 Thread Dale R. Worley
Greg Wooledge  writes:
> It's amazing how many people manage to post their code with NO comments
> or explanations of what it's supposed to do, what assumptions are being
> made about the inputs, etc.  This leaves us to guess.

It seems to be a modern style.  When I was learning to program, poorly
commented code was considered a failing.  But recently, I have had
managers object that I put too many comments in.

Dale



Re: select syntax violates the POLA

2021-04-01 Thread Robert Elz
Date:Thu, 1 Apr 2021 14:40:13 -0700
From:Greywolf 
Message-ID:  <354ec4df-c24e-d82a-32ad-788a352a5...@starwolf.com>

  | Or do you mean my coding style

It was that,

  | (which has been valid for over 25 years)?
  | (why's everyone bagging on my style and ignoring my original point, the
  | outlying brokenness, anyway?)

Partly because if you didn't use the braces, the issue wouldn't have arisen.
(And because to most of us it just looks weird, kind of like people
who write functions like f() {( commands to run in a subshell )}
where the braces do nothing useful at all. and should just be omitted.

But

  | I started using the curly braces because every (worthwhile) editor has a
  | paren-match function

that's not an unreasonable use explanation.  I find that a consistent
style and correct indentation work well enough for this though.

  | I just thought I'd try out select and was astonished when
  |
  | select x in ${list}; do {
  | break;
  | } done;
  |
  | was the only one that failed.

Yes, and on second thoughts, the:

chet.ra...@case.edu said:
  | Yes, you need a list terminator so that `done' is recognized as a reserved
  | word here. `;' is sufficient. Select doesn't allow the `done' unless it's
  | in a command position.

isn't really all that appealing as an explanation.   select isn't part
of the standard, so its syntax is arbitrary, which means that nothing can
really be considered wrong, but while we often think of reserved words
(not counting the special cases in case and for statements) as only working
in the command word position, that's not how it really is.  They work there,
they also should work following other reserved words (most of them, but
'}' is not one of the exceptions).   so '} done' should work correctly,
always, if the '}' is a reserved word, and a ';' or newline between them
should not be needed.

kre




Re: select syntax violates the POLA

2021-04-01 Thread Greg Wooledge
On Thu, Apr 01, 2021 at 02:54:55PM -0700, Greywolf wrote:
> the requirement
> to have ${var[ix]} instead of honouring $var[ix] with regard to arrays
> is another one).

Before the introduction of arrays, $var[ix] already had a meaning:
the value of the "var" parameter, followed by the 4-character string [ix].
Redefining $var[ix] to mean the same thing as ${var[ix]} would have
broken existing scripts.



Re: select syntax violates the POLA

2021-04-01 Thread Greywolf

Hi, Chet!  I've read a lot of your posts long ago, as well!

On 4/1/2021 8:57, Chet Ramey wrote:


It's more like `select' doesn't inherit some of the shell's special cases.


    select dir in ${d[@]}; do {
    break;
    } done;

>>
...but select breaks on the "} done;" syntax 


Yes, you need a list terminator so that `done' is recognized as a reserved
word here. `;' is sufficient. Select doesn't allow the `done' unless it's
in a command position. Some of the other compound commands have special
cases, mostly inherited from the Bourne shell, to allow it.


Firstly, thank you for your concise reply.

I discovered that making it '}; done;' as you suggested here worked,
shortly after my broken astonishment :).

kre mentioned that it's a ksh holdover.  This explains a great many
things considering how horribly broken I have found ksh to be (and the
weak arguments supporting that brokenness; among them, the need to
say 'fg %4' instead of merely being able to say '%4'; the requirement
to have ${var[ix]} instead of honouring $var[ix] with regard to arrays
is another one).

Lastly, thanks for not bagging on my coding style.  It was somewhat
intentional, somewhat accidental when I started using it 25 years back.
Being able to paren-match my for-in-do-done, while/until-do-done,
if-elif-else-fi has been a timesaver.  It not only helps me spot missing
closures, it helps me spot missing quotes.

[I think the only thing I wish would be enhanced and accepted further
was for it to work with case-esac, but that hasn't changed in 25 years,
either, and it's minor, so I'm not holding my breath. :) ]

Cheers,

--*greywolf;




Re: select syntax violates the POLA

2021-04-01 Thread Greywolf

On 4/1/2021 9:58, Robert Elz wrote:

 Date:Thu, 1 Apr 2021 11:36:14 -0400
 From:Greg Wooledge 
 Message-ID:  

   | On Thu, Apr 01, 2021 at 01:36:59AM -0700, greyw...@starwolf.com wrote:
   | >   The following is valid shell code:
   | >
   | >   d=($(ls /usr/src/pkg/*/$1));
   |
   | Syntactically valid, but semantically wrong


Mr. Elz!  Long time!  I remember reading your posts 30 years ago!

[ much other ado elided ]


   | "${d[@]}" with quotes.

Again, yes, but in practice here, not needed.

   | What purpose do the extra curly braces serve?

Good question, wondered that myself.   Note that if they were omitted
the odd syntax issue wouldn't have arisen, as the done would follow "break;"
and be recognised.


Unfortunately the way bash has implemented arrays, $d[@] doesn't do The
Right Thing.

Or do you mean my coding style (which has been valid for over 25 years)?
(why's everyone bagging on my style and ignoring my original point, the
outlying brokenness, anyway?)

I started using the curly braces because every (worthwhile) editor has a
paren-match function which shows you the matching brace at the other
end, and I was tired of searching for which conditional component
(while, if, for, and so on) was missing its closing word.  This helps me
immensely.



After all that, and ignoring select's syntax (it was invented by
ksh, long long ago, and isn't going to change) it is a dumb interface
that can always be coded better using other mechanisms.   And when you
do that you can allow for much more flexible input than just the line
number the select demands.


Indeed, I have written such animals from scratch; I just thought I'd try
out select and was astonished when

select x in ${list}; do {
break;
} done;

was the only one that failed.



If you avoid select, and avoid arrays, then any Bourne style shell will work.
So, do that.


I will also note that the arrays don't give me grief in the least. :)




kre



Thank you so much for your response!  You got exactly what I was after!

--*greywolf;



Re: select syntax violates the POLA

2021-04-01 Thread Greywolf

On 4/1/2021 9:16, konsolebox wrote:

On Thu, Apr 1, 2021 at 11:25 PM  wrote:


 if ((n > 1)); then {
 echo "Ambiguous dir specification";
 exit 1;
 }
 else {
 dir=${d[0]};
 } fi;


The grouping is unnecessary or should be separate from the first class
syntax.  Bash is not C or Go and shouldn't be written like it.



I didn't ask for your opinion on my coding style.

It's worked correctly for 25 years.  I have my reasons.



Re: select syntax violates the POLA

2021-04-01 Thread Robert Elz
Date:Thu, 1 Apr 2021 13:18:07 -0400
From:Greg Wooledge 
Message-ID:  

  | It's amazing how many people manage to post their code with NO comments
  | or explanations of what it's supposed to do, what assumptions are being
  | made about the inputs, etc.  This leaves us to guess.

Agreed, it is a problem in general.   It just happens that in this
case I can see exactly what is intended (as I know the environment)
so I don't need to guess.

  | I'm guessing that /usr/src/pkg/*/* is a list of files, not a list of
  | directories.  You're guessing that it's a list of directories.

No, I know it is a list of directories.  No guessing involved.

  | In the original code, if it's a list of directories, then we have
  | "ls firstdir seconddir" which expands to a list of mangled filenames

Yes, the original was broken.   But that was not what the message was
about, it was about the syntax of select.   That the rest of the example
code wouldn't have worked was kind of not the point, he wasn't asking
for assistance with that.

What he wanted to know was why his usage of select was giving a syntax error.
Chet answered that.

  | Now, this is obviously just a guess, and I could be extremely wrong
  | about it.  For one thing, they used the variable name "d".  That seems
  | to indicate that it should be a list of directories, rather than a list
  | of files.

More than that, after one of them is selected ("select dir ...") the
code did "cd $dir" (you even commented on the lack of quotes in that
statement) - so a directory name is clearly what is wanted.   Even if
you didn't know the environment, this makes that very clear.

  | So, perhaps their code is simply *broken*, and where they *thought* they
  | would be getting a list of directories, they actually get a list of
  | mangled useless filenames, because they forgot the -d argument to ls.

Yes.

  |
  | >   | d=(/usr/src/pkg/*/"$1")
  | > 
  | > definitely not that, the quotes are wrong in any case
  |
  | They are not!

They are.   As I said, when used $1 is likely to be a pattern 'p5-*'
or similar, and it wants to locate all directories named starting with
p5- not the one (non-existing) directory named literally "p5-*".

  | > Alternatively
  | >   d=( $( ls -d /usr/src/pkg/*/$1 ) )
  |
  | This needs quotes around "$1"

Again, no it doesn't.   Quote everything is a nice starting point,
but it does not universally apply.   Filename expansion of the $1
is definitely wanted here.

  | but yes, it's quite possible that this was
  | their intent.  Of course, this is still *broken*, but it only breaks if
  | one of the directory names contains whitespace characters.

They don't.   They never will.   Of course it could break if IFS was set
to something unusual, but since this script is (I presume) not doing that,
that's also not an issue.

  | It's likely
  | that they didn't happen to have any such directories in their test
  | environment, and therefore, this bug would go unnoticed for a long time.

It would never be noticed, as there will never be a category (the '*')
or package (the $1) name containing a space or any other meta-char.
There are rules for the names.

Too much of pkgsrc (which is what this is dealing with, the NetBSD
packaging system, also available for lots of other systems, including
various linux variants, Solaris, OSX, and more) depends on the names
having specific characteristics for this to ever be changed.

  | > or just
  | >   d=( $( printf %s\\n /usr/src/pkg/*/$1 ) )
  |
  | This is not much better.  It still breaks on whitespace.

It would.  There is none.

  | If a list of directories (not their contents) is the desired outcome,
  | then my original code is perfectly fine:
  |
  | d=(/usr/src/pkg/*/"$1")
  |
  | This will expand to something like
  |
  | d=(/usr/src/pkg/vendor1/netcat /usr/src/pkg/vendor2/netcat)

Except that it can't.There can be only one "netcat" in all of the
category directories, because those things aren't used (or not really
used) for the compiled binary packages.   If you restrict the $1 to being
a literal string (by quoting it) then there could never be more than one
name returned, so using an array, and using select to choose the actual
one which is wanted, would be a waste of coding effort.

I'm not blaming you for not knowing all this, but like I said, I know the
environment, and I can see exactly what is being attempted.

  | > Just to be sure.Personally I'd do
  | > 
  | >   set -- /usr/src/pkg/*/$1
  | > 
  | > and then simply use the positional parameters.
  |
  | This still needs quotes around "$1",

No, it doesn't.

  | and it's basically the same as the array assignment -- just less flexible,
  | and more suited to sh than bash.

Exactly.   It will work with any shell, bash doesn't need to be available.

  | > Yes.   But it turns out not to matter in this case, as none of
  | > the names will ever contain anything but "normal" characters
  | > (no spaces, newlines, 

Re: select syntax violates the POLA

2021-04-01 Thread Eli Schwartz
On 4/1/21 1:18 PM, Greg Wooledge wrote:
> On Thu, Apr 01, 2021 at 11:58:13PM +0700, Robert Elz wrote:
>>
>>   | If $1 is not a directory, then you want:
>>
>> It is a directory, or I'd guess, quite likely a pattern chosen
> 
> It's amazing how many people manage to post their code with NO comments
> or explanations of what it's supposed to do, what assumptions are being
> made about the inputs, etc.  This leaves us to guess.
> 
> I'm guessing that /usr/src/pkg/*/* is a list of files, not a list of
> directories.  You're guessing that it's a list of directories.
> 
> In the original code, if it's a list of directories, then we have
> "ls firstdir seconddir" which expands to a list of mangled filenames
> without directory components.  And since there's more than one directory,
> the array ends up looking like:
> 
> d=(README foo.c foo.h foo README bar.c bar.h foo.c foo.h foobar)
> 
> with repeated filenames, and no knowledge of which filename came out of
> which subdirectory.
> 
> I was assuming that this was *not* how it was intended to work, and thus,
> I made the guess that /usr/src/pkg/*/$1 expanded to a list of *files*,
> and therefore generated a list of full pathnames, e.g.
> 
> d=(/usr/src/pkg/applesauce/Makefile.PL /usr/src/pkg/bananabread/Makefile.PL)
> 
> and then the user can make a meaningful selection from such a list.
> 
> Now, this is obviously just a guess, and I could be extremely wrong
> about it.  For one thing, they used the variable name "d".  That seems
> to indicate that it should be a list of directories, rather than a list
> of files.
> 
> So, perhaps their code is simply *broken*, and where they *thought* they
> would be getting a list of directories, they actually get a list of
> mangled useless filenames, because they forgot the -d argument to ls.
> 
>>   | d=(/usr/src/pkg/*/"$1")
>>
>> definitely not that, the quotes are wrong in any case
> 
> They are not!

The quotes are wrong, *iff* the intent is that people should be allowed
to pass quoted globs as $1 and let those be expanded to produce d=()

Which, I can see where Robert is coming from in assuming this.

>> (but apart from
>> that, if filename expansion happens in array assignments (it doesn't in
>> normal ones, and I dislike arrays, so ...) then without the quotes that
>> might work.
>>
>> Alternatively
>>  d=( $( ls -d /usr/src/pkg/*/$1 ) )
> 
> This needs quotes around "$1" but yes, it's quite possible that this was
> their intent.  Of course, this is still *broken*, but it only breaks if
> one of the directory names contains whitespace characters.  It's likely
> that they didn't happen to have any such directories in their test
> environment, and therefore, this bug would go unnoticed for a long time.
> 
>> or just
>>  d=( $( printf %s\\n /usr/src/pkg/*/$1 ) )
> 
> This is not much better.  It still breaks on whitespace.
> 
> If a list of directories (not their contents) is the desired outcome,
> then my original code is perfectly fine:
> 
> d=(/usr/src/pkg/*/"$1")
> 
> This will expand to something like
> 
> d=(/usr/src/pkg/vendor1/netcat /usr/src/pkg/vendor2/netcat)
> 
>> Just to be sure.Personally I'd do
>>
>>  set -- /usr/src/pkg/*/$1
>>
>> and then simply use the positional parameters.
> 
> This still needs quotes around "$1", and it's basically the same as
> the array assignment -- just less flexible, and more suited to sh than
> bash.  But certainly, this is viable in many cases.
> 
>> Yes.   But it turns out not to matter in this case, as none of
>> the names will ever contain anything but "normal" characters
>> (no spaces, newlines, asterisks, ...)
> 
> Famous Last Words™

It's not too much of a leap if the names are required to be NetBSD ports
tree names of packages, which presumably ban such characters and enforce
that ban in their tooling.

It's not something one would be wise to get into the habit of doing
elsewhere, and the quotes don't hurt, so why not add them... unless,
again, we assume the intent of the script is in fact to pass in globs.

These "Famous Last Words™" are really just a fancy way to repeat your
initial, valid objection that the OP gave zero comments or explanation
and therefore you're left to guess at the intention without having any
contextual knowledge about what /usr/src/pkg is or why one would want to
cd into any of them and run make.

I suspect Robert does know quite a bit about it though. :)

-- 
Eli Schwartz
Arch Linux Bug Wrangler and Trusted User



OpenPGP_signature
Description: OpenPGP digital signature


Re: select syntax violates the POLA

2021-04-01 Thread Greg Wooledge
On Thu, Apr 01, 2021 at 11:58:13PM +0700, Robert Elz wrote:
> 
>   | If $1 is not a directory, then you want:
> 
> It is a directory, or I'd guess, quite likely a pattern chosen

It's amazing how many people manage to post their code with NO comments
or explanations of what it's supposed to do, what assumptions are being
made about the inputs, etc.  This leaves us to guess.

I'm guessing that /usr/src/pkg/*/* is a list of files, not a list of
directories.  You're guessing that it's a list of directories.

In the original code, if it's a list of directories, then we have
"ls firstdir seconddir" which expands to a list of mangled filenames
without directory components.  And since there's more than one directory,
the array ends up looking like:

d=(README foo.c foo.h foo README bar.c bar.h foo.c foo.h foobar)

with repeated filenames, and no knowledge of which filename came out of
which subdirectory.

I was assuming that this was *not* how it was intended to work, and thus,
I made the guess that /usr/src/pkg/*/$1 expanded to a list of *files*,
and therefore generated a list of full pathnames, e.g.

d=(/usr/src/pkg/applesauce/Makefile.PL /usr/src/pkg/bananabread/Makefile.PL)

and then the user can make a meaningful selection from such a list.

Now, this is obviously just a guess, and I could be extremely wrong
about it.  For one thing, they used the variable name "d".  That seems
to indicate that it should be a list of directories, rather than a list
of files.

So, perhaps their code is simply *broken*, and where they *thought* they
would be getting a list of directories, they actually get a list of
mangled useless filenames, because they forgot the -d argument to ls.

>   | d=(/usr/src/pkg/*/"$1")
> 
> definitely not that, the quotes are wrong in any case

They are not!

> (but apart from
> that, if filename expansion happens in array assignments (it doesn't in
> normal ones, and I dislike arrays, so ...) then without the quotes that
> might work.
> 
> Alternatively
>   d=( $( ls -d /usr/src/pkg/*/$1 ) )

This needs quotes around "$1" but yes, it's quite possible that this was
their intent.  Of course, this is still *broken*, but it only breaks if
one of the directory names contains whitespace characters.  It's likely
that they didn't happen to have any such directories in their test
environment, and therefore, this bug would go unnoticed for a long time.

> or just
>   d=( $( printf %s\\n /usr/src/pkg/*/$1 ) )

This is not much better.  It still breaks on whitespace.

If a list of directories (not their contents) is the desired outcome,
then my original code is perfectly fine:

d=(/usr/src/pkg/*/"$1")

This will expand to something like

d=(/usr/src/pkg/vendor1/netcat /usr/src/pkg/vendor2/netcat)

> Just to be sure.Personally I'd do
> 
>   set -- /usr/src/pkg/*/$1
> 
> and then simply use the positional parameters.

This still needs quotes around "$1", and it's basically the same as
the array assignment -- just less flexible, and more suited to sh than
bash.  But certainly, this is viable in many cases.

> Yes.   But it turns out not to matter in this case, as none of
> the names will ever contain anything but "normal" characters
> (no spaces, newlines, asterisks, ...)

Famous Last Words™



Re: select syntax violates the POLA

2021-04-01 Thread Robert Elz
Date:Thu, 1 Apr 2021 11:36:14 -0400
From:Greg Wooledge 
Message-ID:  

  | On Thu, Apr 01, 2021 at 01:36:59AM -0700, greyw...@starwolf.com wrote:
  | >   The following is valid shell code:
  | > 
  | >   d=($(ls /usr/src/pkg/*/$1));
  |
  | Syntactically valid, but semantically wrong.

Greg managed to comment on everything in the original message, except
the actual point of it ... Chet answered that, so I won't bother,
but:

  | If $1 is not a directory, then you want:

It is a directory, or I'd guess, quite likely a pattern chosen
to find where the package that is wanted lives.  The '/*/' represents
a category grouping, and it is not unusual to not know which one applies
to any particular package.

My guess is that $1 might be something like *sed* to find any package
with "sed" in its name.  Or p5-* to select from the perl5 (script) packages.

So:
  | d=(/usr/src/pkg/*/"$1")

definitely not that, the quotes are wrong in any case (but apart from
that, if filename expansion happens in array assignments (it doesn't in
normal ones, and I dislike arrays, so ...) then without the quotes that
might work.

Alternatively
d=( $( ls -d /usr/src/pkg/*/$1 ) )
or just
d=( $( printf %s\\n /usr/src/pkg/*/$1 ) )

Just to be sure.Personally I'd do

set -- /usr/src/pkg/*/$1

and then simply use the positional parameters.

  | If $1 is supposed to be a directory, and therefore you want only filenames
  | and not full pathnames in the array,

It is, but he almost certainly wants the directory names, not the
contents of the directories.   He's going to want the full pathname
so once selected, he can cd to it.

  | >   cd ${dir} &&
  |
  | Quotes.

Yes.   But it turns out not to matter in this case, as none of
the names will ever contain anything but "normal" characters
(no spaces, newlines, asterisks, ...)

But that's the cd which requires dir to be the full pathname.

  | >   make clean && {
  | >   make update ||
  | >   make install;
  | >   }
  |
  | Is the inner || supposed to be && by chance?

Probably not.   This is "if the package is already
installed, update it, if not, install it".   "make update"
will succeed and update the package if needed, if it is installed
already, otherwise it will fail.  In that case make install
will install it (it would fail if a some other version of
the package was already installed).   (The preceding "make clean"
just gets rid of the left overs from any previous compilation,
but will fail if there's insufficient permission, or similar,
in which case attempting an update or install would also fail).

  | >   if ((n > 1)); then {
  | >   select dir in ${d[@]}; do {
  | >   break;
  | >   } done;
  | >   }
  |
  | "${d[@]}" with quotes.

Again, yes, but in practice here, not needed.

  | What purpose do the extra curly braces serve?

Good question, wondered that myself.   Note that if they were omitted
the odd syntax issue wouldn't have arisen, as the done would follow "break;"
and be recognised.

After all that, and ignoring select's syntax (it was invented by
ksh, long long ago, and isn't going to change) it is a dumb interface
that can always be coded better using other mechanisms.   And when you
do that you can allow for much more flexible input than just the line
number the select demands.

If you avoid select, and avoid arrays, then any Bourne style shell will work.
So, do that.

kre




Re: select syntax violates the POLA

2021-04-01 Thread konsolebox
On Thu, Apr 1, 2021 at 11:25 PM  wrote:
>
> if ((n > 1)); then {
> echo "Ambiguous dir specification";
> exit 1;
> }
> else {
> dir=${d[0]};
> } fi;

The grouping is unnecessary or should be separate from the first class
syntax.  Bash is not C or Go and shouldn't be written like it.

-- 
konsolebox



Re: select syntax violates the POLA

2021-04-01 Thread Chet Ramey

On 4/1/21 4:36 AM, greyw...@starwolf.com wrote:


Bash Version: 5.1
Patch Level: 4
Release Status: release

Description:
The 'select' directive's syntax does not correspond to the rest of the 
shell's syntax.
I am not sure if this is by design; if it is, let me know and I'll go 
away.


It's more like `select' doesn't inherit some of the shell's special cases.


if ((n > 1)); then {
select dir in ${d[@]}; do {
break;
} done;
}
else { ...

	...but select breaks on the "} done;" syntax 


Yes, you need a list terminator so that `done' is recognized as a reserved
word here. `;' is sufficient. Select doesn't allow the `done' unless it's
in a command position. Some of the other compound commands have special
cases, mostly inherited from the Bourne shell, to allow it.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/



Re: select syntax violates the POLA

2021-04-01 Thread Greg Wooledge
On Thu, Apr 01, 2021 at 01:36:59AM -0700, greyw...@starwolf.com wrote:
>   The following is valid shell code:
> 
>   d=($(ls /usr/src/pkg/*/$1));

Syntactically valid, but semantically wrong.

If $1 is not a directory, then you want:

d=(/usr/src/pkg/*/"$1")

If $1 is supposed to be a directory, and therefore you want only filenames
and not full pathnames in the array, then we can arrange for that as well,
but it's slightly more tedious.

Using ls here is wrong, and will break.  It's Pitfall #1 on my list for
a reason.

https://mywiki.wooledge.org/BashPitfalls#pf1

>   cd ${dir} &&

Quotes.

>   make clean && {
>   make update ||
>   make install;
>   }

Is the inner || supposed to be && by chance?

>   if ((n > 1)); then {
>   select dir in ${d[@]}; do {
>   break;
>   } done;
>   }

"${d[@]}" with quotes.

What purpose do the extra curly braces serve?  Do you want them just
because you think they look pretty?

>   until [ -f ${tmpfile} ]; do {

Quotes.  And again, those extra curly braces don't serve any purpose.

>   for dir in ${d[@]}; do {

Quotes.



select syntax violates the POLA

2021-04-01 Thread greywolf
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: netbsd
Compiler: gcc
Compilation CFLAGS: -O2 -I/usr/local/include -D_FORTIFY_SOURCE=2 -I/usr/include 
uname output: NetBSD eddie.starwolf.com 9.99.81 NetBSD 9.99.81 (EDDIE) #9: Tue 
Mar 23 19:13:25 PDT 2021  greyw...@eddie.starwolf.com:/sys/native/compile/EDDIE 
amd64
Machine Type: x86_64--netbsd

Bash Version: 5.1
Patch Level: 4
Release Status: release

Description:
The 'select' directive's syntax does not correspond to the rest of the 
shell's syntax.
I am not sure if this is by design; if it is, let me know and I'll go 
away.

The following is valid shell code:

d=($(ls /usr/src/pkg/*/$1));
n=${#d[@]};

if ((n > 1)); then {
echo "Ambiguous dir specification";
exit 1;
}
else {
dir=${d[0]};
} fi;

cd ${dir} &&
make clean && {
make update ||
make install;
}

I'd like to replace the first part of the if/else/fi with:

if ((n > 1)); then {
select dir in ${d[@]}; do {
break;
} done;
}
else { ...

...but select breaks on the "} done;" syntax that works with, e.g.,

while sleep 5; do {
date;
} done;

until [ -f ${tmpfile} ]; do {
sleep 5;
} done;

for dir in ${d[@]}; do {
echo ${dir};
} done;

This violates the POLA, from my point of view.

Repeat-By:

d=($(ls /usr/src/pkg/*/$1));
select dir in ${d[@]}; do {
break;
} done;