Subject: enhancements to glob code
To: None <current-users@sun-lamp.cs.berkeley.edu>
From: Luke Mewburn <lm@rmit.edu.au>
List: current-users
Date: 01/05/1994 16:47:57
Many moons ago (earlier this year) I hacked the glob code (in its pre-brace
and tilde days) to give it some extra functionality. The extra flags
are:
- GLOB_ALTNOT		use ^ instead of ! inside [...] (from tcsh 6.04)
- GLOB_DOTFILES		match .files without specifying `.' at the start
			of the pattern. 
- GLOB_NODOT		never match . or ..  (When used with with DOTFILES,
			`*' will match every file in the current directory
			sans `.' and `..' - useful huh? :)

A minor manpage typo is fixed, as well as updates to the manual to
reflect my changes.

Would there be any major objections to my request to get this added to the
main distribution?

Oh, I've got patches to csh (and tcsh 6.04) to add 2 new variables `dotfiles'
and `nodot' which change the effects of globbing as you'd expect. If this
code is committed, I'll forward on the csh hacks too.

PS: my patch has some code like:
	static int not_c, m_not_c;
Will this break shared libraries (cause each application may want to set
their own internal values of this)? I don't think it should, but I've never
written code to go into shared libs before ;)


--- context diff follows (cwd was /usr/src)

*** include/glob.h.ORIG	Fri Dec 17 06:18:00 1993
--- include/glob.h	Wed Jan  5 16:29:33 1994
***************
*** 78,83 ****
--- 78,86 ----
  #define	GLOB_NOMAGIC	0x0200	/* GLOB_NOCHECK without magic chars (csh). */
  #define	GLOB_QUOTE	0x0400	/* Quote special chars with \. */
  #define	GLOB_TILDE	0x0800	/* Expand tilde names from the passwd file. */
+ #define GLOB_DOTFILES	0x1000	/* Match . files without explicit . */
+ #define GLOB_NODOT	0x2000	/* Never glob . or .. */
+ #define GLOB_ALTNOT	0x4000	/* Use ^ instead of ! as NOT char */
  #endif

  #define	GLOB_NOSPACE	(-1)	/* Malloc call failed. */
*** lib/libc/gen/glob.c.ORIG	Fri Dec 17 06:23:00 1993
--- lib/libc/gen/glob.c	Wed Jan  5 15:30:03 1994
***************
*** 34,39 ****
--- 34,43 ----
   * SUCH DAMAGE.
   */

+ /*
+  * GLOB_{DOTFILES,NODOT,ALTNOT} added by Luke Mewburn <lm@rmit.edu.au> 940105
+  */
+ 
  #if defined(LIBC_SCCS) && !defined(lint)
  /* from: static char sccsid[] = "@(#)glob.c	8.3 (Berkeley) 10/13/93"; */
  static char *rcsid = "$Id: glob.c,v 1.4 1993/11/06 01:10:18 cgd Exp $";
***************
*** 60,65 ****
--- 64,75 ----
   *	expand ~user/foo to the /home/dir/of/user/foo
   * GLOB_BRACE:
   *	expand {1,2}{a,b} to 1a 1b 2a 2b 
+  * GLOB_DOTFILES:
+  *	. files don't need to be explicitly matched with '.*'
+  * GLOB_NODOT:
+  *	Never match '.' or '..' (mainly used with GLOB_DOTFILES)
+  * GLOB_ALTNOT:
+  *	Use ^ instead of ! for NOT.
   * gl_matchc:
   *	Number of matches in the current invocation of glob.
   */
***************
*** 82,87 ****
--- 92,98 ----
  #define	EOS		'\0'
  #define	LBRACKET	'['
  #define	NOT		'!'
+ #define	ALTNOT		'^'
  #define	QUESTION	'?'
  #define	QUOTE		'\\'
  #define	RANGE		'-'
***************
*** 121,126 ****
--- 132,138 ----
  #define	M_ALL		META('*')
  #define	M_END		META(']')
  #define	M_NOT		META('!')
+ #define	M_ALTNOT	META('^')
  #define	M_ONE		META('?')
  #define	M_RNG		META('-')
  #define	M_SET		META('[')
***************
*** 149,154 ****
--- 161,169 ----
  static void	 qprintf __P((const char *, Char *));
  #endif

+ static int	not_c, m_not_c;
+ 
+ 
  int
  glob(pattern, flags, errfunc, pglob)
  	const char *pattern;
***************
*** 170,175 ****
--- 185,198 ----
  	pglob->gl_errfunc = errfunc;
  	pglob->gl_matchc = 0;

+ 	if (flags & GLOB_ALTNOT) {
+ 		not_c = ALTNOT;
+ 		m_not_c = M_ALTNOT;
+ 	} else {
+ 		not_c = NOT;
+ 		m_not_c = M_NOT;
+ 	}
+ 
  	bufnext = patbuf;
  	bufend = bufnext + MAXPATHLEN;
  	if (flags & GLOB_QUOTE) {
***************
*** 410,427 ****
  		switch (c) {
  		case LBRACKET:
  			c = *qpatnext;
! 			if (c == NOT)
  				++qpatnext;
  			if (*qpatnext == EOS ||
  			    g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
  				*bufnext++ = LBRACKET;
! 				if (c == NOT)
  					--qpatnext;
  				break;
  			}
  			*bufnext++ = M_SET;
! 			if (c == NOT)
! 				*bufnext++ = M_NOT;
  			c = *qpatnext++;
  			do {
  				*bufnext++ = CHAR(c);
--- 433,450 ----
  		switch (c) {
  		case LBRACKET:
  			c = *qpatnext;
! 			if (c == not_c)
  				++qpatnext;
  			if (*qpatnext == EOS ||
  			    g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
  				*bufnext++ = LBRACKET;
! 				if (c == not_c)
  					--qpatnext;
  				break;
  			}
  			*bufnext++ = M_SET;
! 			if (c == not_c)
! 				*bufnext++ = m_not_c;
  			c = *qpatnext++;
  			do {
  				*bufnext++ = CHAR(c);
***************
*** 596,604 ****
  		register u_char *sc;
  		register Char *dc;

! 		/* Initial DOT must be matched literally. */
! 		if (dp->d_name[0] == DOT && *pattern != DOT)
! 			continue;
  		for (sc = (u_char *) dp->d_name, dc = pathend; 
  		     (*dc++ = *sc++) != EOS;)
  			continue;
--- 619,635 ----
  		register u_char *sc;
  		register Char *dc;

! 		/* Initial DOT must be matched literally, unless GLOB_DOTFILES */
! 		if (dp->d_name[0] == DOT) {
! 			if (pglob->gl_flags & GLOB_NODOT)
! 				if ((dp->d_name[1] == EOS) ||
! 				    (dp->d_name[1] == DOT &&
! 				     dp->d_name[2] == EOS))
! 					continue;
! 			if (!(pglob->gl_flags & GLOB_DOTFILES))
! 				if (*pattern != DOT)
! 					continue;
! 		}
  		for (sc = (u_char *) dp->d_name, dc = pathend; 
  		     (*dc++ = *sc++) != EOS;)
  			continue;
***************
*** 700,706 ****
  			ok = 0;
  			if ((k = *name++) == EOS)
  				return(0);
! 			if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
  				++pat;
  			while (((c = *pat++) & M_MASK) != M_END)
  				if ((*pat & M_MASK) == M_RNG) {
--- 731,737 ----
  			ok = 0;
  			if ((k = *name++) == EOS)
  				return(0);
! 			if ((negate_range = ((*pat & M_MASK) == m_not_c)) != EOS)
  				++pat;
  			while (((c = *pat++) & M_MASK) != M_END)
  				if ((*pat & M_MASK) == M_RNG) {
*** lib/libc/gen/glob.3.ORIG	Fri Dec 17 06:23:00 1993
--- lib/libc/gen/glob.3	Wed Jan  5 16:24:09 1994
***************
*** 31,40 ****
  .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  .\" SUCH DAMAGE.
  .\"
! .\"     from: @(#)glob.3	8.1 (Berkeley) 6/9/93
  .\"	$Id: glob.3,v 1.7 1993/12/03 23:02:05 cgd Exp $
  .\"
! .Dd June 9, 1993
  .Dt GLOB 3
  .Os
  .Sh NAME
--- 31,40 ----
  .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  .\" SUCH DAMAGE.
  .\"
! .\"     from: @(#)glob.3	8.1 (Berkeley) 1/5/94
  .\"	$Id: glob.3,v 1.7 1993/12/03 23:02:05 cgd Exp $
  .\"
! .Dd January 5, 1994
  .Dt GLOB 3
  .Os
  .Sh NAME
***************
*** 217,222 ****
--- 217,228 ----
  This extension is provided to allow programs such as
  .Xr restore 8
  to provide globbing from directories stored on tape.
+ .It Dv GLOB_ALTNOT
+ Use
+ .Ql ^
+ instead of
+ .Ql !
+ as the negation character inside brackets.
  .It Dv GLOB_BRACE
  Pre-process the pattern string to expand 
  .Ql {pat,pat,...} 
***************
*** 230,235 ****
--- 236,248 ----
  of 
  .Xr find 1 
  patterns).
+ .It Dv GLOB_DOTFILES
+ Match files that start with a
+ .Ql \&. ,
+ without the explicit need for a
+ .Ql \&.
+ at the start of
+ .Fa pattern .
  .It Dv GLOB_MAGCHAR
  Set by the
  .Fn glob
***************
*** 237,242 ****
--- 250,260 ----
  See the description of the usage of the 
  .Fa gl_matchc
  structure member for more details.
+ .It Dv GLOB_NODOT
+ Never match the filenames
+ .Dq \&.
+ and
+ .Dq \&.. .
  .It Dv GLOB_NOMAGIC
  Is the same as 
  .Dv GLOB_NOCHECK 
***************
*** 413,419 ****
  can be obtained with the
  following code:
  .Bd -literal -offset indent
! GLOB_t g;

  g.gl_offs = 2;
  glob("*.c", GLOB_DOOFFS, NULL, &g);
--- 431,437 ----
  can be obtained with the
  following code:
  .Bd -literal -offset indent
! glob_t g;

  g.gl_offs = 2;
  glob("*.c", GLOB_DOOFFS, NULL, &g);


--
Luke Mewburn			Programmer, Technical Services Group,
Email: <lm@rmit.edu.au>		Department of Computer Science, RMIT

------------------------------------------------------------------------------