[comp.bugs.sys5] Csh-style brace patterns in Korn shell

scl@uvaarpa.virginia.edu (Steve Losen) (10/18/89)

Here are some patches to apply to the version of ksh dated  06/15/88.
This is the new version that introduces quite a few more file name
matching operators such as !( ... ),  and the new [[ ... ]] command, etc.
Apply these patches and edit the OPTIONS file so that BRACEPAT=1 and
recompile.  This feature is undocumented (the distributed code has
a few bugs).

For those of you unfamiliar with C-shell brace patterns, they are a
shorthand for generating multiple words.  Brace patterns are not pathname
matches, so you can generate words that do not match existing pathnames.
Suppose I need to create several new directories whose names are nearly
identical.

mkdir new/directory.{1,2,3}

expands to

mkdir new/directory.1 new/directory.2 new/directory.3

Note that new/directory.[1-3] doesn't work because the directories
don't exist.

The brace pattern is expanded first into multiple words and then these
words go through the normal pathname expansion if necessary.  Thus,

/usr/src/{local,ksh,gnu,dwb}/*.o

is expanded to

/usr/src/local/*.o /usr/src/ksh/*.o /usr/src/gnu/*.o /usr/src/dwb/*.o

and then file name expansion takes places.

Brace patterns can be nested.

a{b,{c,{d,e}f}g}h

expands to

abh acgh adfgh aefgh

Note that the order of the patterns is preserved.  Null patterns are legal.

mv /usr/local/bin/ksh{,.old}

is shorthand for

mv /usr/local/bin/ksh /usr/local/bin/ksh.old

Brace patterns have no effect (are left unexpanded) if any of the
following are true:

o unquoted white space between { and }

o no unquoted comma between { and }

o missing } or missing {

Enough of this rambling, here are the patches:

*** sh/expand.c.orig	Thu Jun  1 09:56:15 1989
--- sh/expand.c	Tue Oct 17 14:14:49 1989
***************
*** 452,458 ****
  	char *sp;
  	char comma;
  	int count = 0;
- 	ap->argchn = 0;
  again:
  	apin = ap = todo;
  	todo = ap->argchn;
--- 452,457 ----
***************
*** 526,533 ****
  		}
  	endloop2:
  		/* check for match of '{' */
! 		if(*cp != '}')
  			ap = (struct argnod*)stak_begin();
  		else
  			ap = apin;
  		*cp = 0;
--- 525,534 ----
  		}
  	endloop2:
  		/* check for match of '{' */
! 		if(*cp != '}') {
  			ap = (struct argnod*)stak_begin();
+ 			ap->argflag = 0;
+ 		}
  		else
  			ap = apin;
  		*cp = 0;
*** sh/args.c.orig	Thu Jun  1 09:55:59 1989
--- sh/args.c	Tue Oct 17 11:45:04 1989
***************
*** 561,566 ****
--- 561,567 ----
  		if(sh.trapnote&SIGSET)
  			sh_exit(SIGFAIL);
  		ap = (struct argnod*)stak_begin();
+ 		ap->argchn = 0;
  		argp = ap->argval;
  		while(c= *s++)
  		{



-- 
Steve Losen     scl@virginia.edu
University of Virginia Academic Computing Center