View Issue Details

IDProjectCategoryView StatusLast Update
00004491003.1(2008)/Issue 7Shell and Utilitiespublic2024-06-11 08:53
Reportereblake Assigned Toajosey  
PrioritynormalSeverityCommentTypeEnhancement Request
Status ClosedResolutionAccepted As Marked 
NameEric Blake
OrganizationRed Hat
User Referenceebb.case
Section2.9.4.3 Case Conditional Construct
Page Number2322
Line Number73308
Interp Status---
Final Accepted Text0000449:0000968
Summary0000449: add ;& case statement fallthrough to sh
DescriptionWayne Pollock requested standardizing the ksh extension of the case
statement fall-through delimiter ';&' in Issue 8.

For an example:

case 'b' in
  a) echo a ;&
  b) echo b ;&
  c) echo c ;&
  *) echo x ;&
esac

Results in the output:
b
c
x
Desired ActionAt line 73307 [XCU 2.9.4.3 Case Conditional Construct], change:

The control operator ')' terminates a list of patterns corresponding
to a given action. The compound-list for each list of patterns, with
the possible exception of the last, shall be terminated with ";;".

to:

The control operator ')' terminates a list of patterns corresponding
to a given action. The terminated pattern list and the following
compound-list is called a case statement clause. Each case
statement clause, with the possible exception of the last, shall be
terminated with either ";;" or ";&".

At line 73322, change:

After the first match, no more patterns shall be expanded, and the
compound-list shall be executed.

to:

After the first match, no more patterns in the case statement shall be
expanded, and the compound-list of the matching clause shall be executed.
If the case statement clause is terminated by ";;", no further clauses
shall be examined. If the case statement clause is terminated by ";&",
then execution shall continue with the compound-list of the next clause,
if any.

At line 73326, change:

Otherwise, the exit status shall be the exit status of the last command
executed in the compound-list.

to:

Otherwise, the exit status shall be the exit status of the last command
executed in the compound-list of the last clause to be executed.

At line 73501 [XCU 2.10.2 Shell Grammar Rules], change:

%token AND_IF OR_IF DSEMI
/* '&&' '||' ';;' */

to:

%token AND_IF OR_IF DSEMI SEMI_AND
/* '&&' '||' ';;' ';&' */

At line 73588, change:

case_item : pattern ')' linebreak DSEMI linebreak
            | pattern ’)’ compound_list DSEMI linebreak
            | ’(’ pattern ’)’ linebreak DSEMI linebreak
            | ’(’ pattern ’)’ compound_list DSEMI linebreak

to:

case_item : pattern ')' linebreak DSEMI linebreak
            | pattern ’)’ compound_list DSEMI linebreak
            | ’(’ pattern ’)’ linebreak DSEMI linebreak
            | ’(’ pattern ’)’ compound_list DSEMI linebreak
            | pattern ')' linebreak SEMI_AND linebreak
            | pattern ’)’ compound_list SEMI_AND linebreak
            | ’(’ pattern ’)’ linebreak SEMI_AND linebreak
            | ’(’ pattern ’)’ compound_list SEMI_AND linebreak

At line 124793 [XRAT C.2.9.4 Compound Commands], change:

Consideration was given to requiring break inside the compound-list to
prevent falling through to the next pattern action list. This was
rejected as being nonexisting practice. An interesting undocumented
feature of the KornShell is that using ";&" instead of ";;" as a
terminator causes the exact opposite behavior—the flow of control
continues with the next compound-list.

to:

Consideration was given to requiring break inside the compound-list to
prevent falling through to the next pattern action list. This was
rejected as being nonexisting practice. Instead, the standard now
requires a feature first added in KornShell that using ";&" instead of
";;" as a terminator causes the exact opposite behavior—the flow of
control continues with the next compound-list.

Although the standard is explicit that the order of side-effects due
to pattern expansion within a single clause is unspecified, it is clear
that patterns are expanded in clause order, and that no further pattern
expansions are attempted after the first match. That is, the following
example is required to output "1.0":

x=0 y=1
case 1 in
  $((y=0)) ) ;;
  $((x=1)) ) ;&
  $((x=2)) ) echo $x.$y ;;
esac
Tagsissue8

Activities

msbrown

2011-06-09 15:59

manager   bugnote:0000810

Targeting for future revision.

nick

2011-09-08 15:52

manager   bugnote:0000955

ksh, bash and zsh all implement this extension currently;
this is standardizing existing practice.

geoffclare

2011-09-09 08:40

manager   bugnote:0000957

I had forgotten that I made a comment about this bug on the mailing list:

> After the first match, no more patterns in the case statement shall be
> expanded, and the compound-list of the matching clause shall be executed.
> If the case statement clause is terminated by ";;", no further clauses
> shall be examined. If the case statement clause is terminated by ";&",
> then execution shall continue with the compound-list of the next clause,
> if any.

The last sentence doesn't describe multiple fall-through clauses
adequately. How about:

  If the case statement clause is terminated by ";&", then the
  compound-list (if any) of each subsequent clause shall be executed,
  in order, until either a clause terminated by ";;" is reached and
  its compound-list (if any) executed or there are no further clauses
  in the case statement.

geoffclare

2011-09-22 15:30

manager   bugnote:0000968

Last edited: 2020-03-05 17:08

At line 1579 [XBD 3.113 Control Operator], change:
;;
to:
;;  ;&

At line 73307 [XCU 2.9.4.3 Case Conditional Construct], change:

The control operator ')' terminates a list of patterns corresponding
to a given action. The compound-list for each list of patterns, with
the possible exception of the last, shall be terminated with ";;".

to:

The control operator ')' terminates a list of patterns corresponding
to a given action. The terminated pattern list and the following
compound-list is called a case statement clause. Each case
statement clause, with the possible exception of the last, shall be
terminated with either ";;" or ";&".

At line 73312 change:
case word in
[(] pattern1 ) compound-list ;;
[[(] pattern[ | pattern] ... ) compound-list ;;] ...
[[(] pattern[ | pattern] ... ) compound-list]
esac
The ";;" is optional for the last compound-list.

to:
case word in
[(] pattern1 ) compound-list terminator
[[(] pattern[ | pattern] ... ) compound-list terminator] ...
[[(] pattern[ | pattern] ... ) compound-list]
esac
Where terminator is either ";;" or ";&" and is optional for the last compound-list.

At line 73322, change:

After the first match, no more patterns shall be expanded, and the
compound-list shall be executed.

to:

After the first match, no more patterns in the case statement shall be
expanded, and the compound-list of the matching clause shall be executed.
If the case statement clause is terminated by ";;", no further clauses
shall be examined. If the case statement clause is terminated by ";&",
then the compound-list (if any) of each subsequent clause shall be
executed, in order, until either a clause terminated by ";;" is reached
and its compound-list (if any) executed or there are no further clauses
in the case statement.

At line 73326, change:

Otherwise, the exit status shall be the exit status of the last command
executed in the compound-list.

to:

Otherwise, the exit status shall be the exit status of the last command
executed in the compound-list of the last clause to be executed.

At line 73501 [XCU 2.10.2 Shell Grammar Rules], change:
%token AND_IF OR_IF DSEMI
/* '&&' '||' ';;' */
to:
%token AND_IF OR_IF DSEMI SEMI_AND
/* '&&' '||' ';;' ';&' */


At line 73588, change:
case_item : pattern ')' linebreak DSEMI linebreak
            | pattern ’)’ compound_list DSEMI linebreak
            | ’(’ pattern ’)’ linebreak DSEMI linebreak
            | ’(’ pattern ’)’ compound_list DSEMI linebreak
to:
case_item : pattern ')' linebreak DSEMI linebreak
            | pattern ’)’ compound_list DSEMI linebreak
            | ’(’ pattern ’)’ linebreak DSEMI linebreak
            | ’(’ pattern ’)’ compound_list DSEMI linebreak
            | pattern ')' linebreak SEMI_AND linebreak
            | pattern ’)’ compound_list SEMI_AND linebreak
            | ’(’ pattern ’)’ linebreak SEMI_AND linebreak
            | ’(’ pattern ’)’ compound_list SEMI_AND linebreak


At line 124793 [XRAT C.2.9.4 Compound Commands], change:

Consideration was given to requiring break inside the compound-list to
prevent falling through to the next pattern action list. This was
rejected as being nonexisting practice. An interesting undocumented
feature of the KornShell is that using ";&" instead of ";;" as a
terminator causes the exact opposite behavior—the flow of control
continues with the next compound-list.

to:

Consideration was given to requiring break inside the compound-list to
prevent falling through to the next pattern action list. This was
rejected as being nonexisting practice. Instead, the standard now
requires a feature first added in KornShell that using ";&" instead of
";;" as a terminator causes the exact opposite behavior—the flow of
control continues with the next compound-list.

Although the standard is explicit that the order of side-effects due
to pattern expansion within a single clause is unspecified, it is clear
that patterns are expanded in clause order, and that no further pattern
expansions are attempted after the first match. That is, the following
example is required to output "1.0":
x=0 y=1
case 1 in
  $((y=0)) ) ;;
  $((x=1)) ) ;&
  $((x=2)) ) echo $x.$y ;;
esac
Some implementations of the shell also allow ";;&" as a terminator
which falls through to the next matching pattern (regardless of the choice
of terminator in any intermediate non-matching clauses), in contrast to ";&"
falling through to the next clause (regardless of the pattern guarding that
clause). This is an allowed extension, but is not required by the standard
at this time.

geoffclare

2020-03-05 17:05

manager   bugnote:0004793

Last edited: 2020-03-05 17:08

This resolution was reviewed in the March 5th, 2020 teleconference, and 0000449:0000968 was updated to add the XBD 3.113 change, the line 73312 change, and the last paragraph of the rationale addition.

Issue History

Date Modified Username Field Change
2011-05-19 23:15 eblake New Issue
2011-05-19 23:15 eblake Status New => Under Review
2011-05-19 23:15 eblake Assigned To => ajosey
2011-05-19 23:15 eblake Name => Eric Blake
2011-05-19 23:15 eblake Organization => Red Hat
2011-05-19 23:15 eblake User Reference => ebb.case
2011-05-19 23:15 eblake Section => 2.9.4.3 Case Conditional Construct
2011-05-19 23:15 eblake Page Number => 2322
2011-05-19 23:15 eblake Line Number => 73308
2011-05-19 23:15 eblake Interp Status => ---
2011-05-19 23:16 eblake Tag Attached: issue8
2011-06-09 15:59 msbrown Note Added: 0000810
2011-06-09 15:59 msbrown Resolution Open => Future Enhancement
2011-09-08 15:50 Don Cragun Status Under Review => Resolved
2011-09-08 15:50 Don Cragun Resolution Future Enhancement => Accepted
2011-09-08 15:52 nick Note Added: 0000955
2011-09-09 08:40 geoffclare Note Added: 0000957
2011-09-09 08:40 geoffclare Status Resolved => Under Review
2011-09-09 08:40 geoffclare Resolution Accepted => Reopened
2011-09-22 15:30 geoffclare Note Added: 0000968
2011-09-22 15:31 geoffclare Final Accepted Text => 0000449:0000968
2011-09-22 15:31 geoffclare Status Under Review => Resolved
2011-09-22 15:31 geoffclare Resolution Reopened => Accepted As Marked
2020-03-05 17:02 geoffclare Note Edited: 0000968
2020-03-05 17:03 geoffclare Note Edited: 0000968
2020-03-05 17:05 geoffclare Note Added: 0004793
2020-03-05 17:08 geoffclare Note Edited: 0000968
2020-03-05 17:08 geoffclare Note Edited: 0004793
2020-05-05 14:37 geoffclare Status Resolved => Applied
2024-06-11 08:53 agadmin Status Applied => Closed