Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: PATCH: Re: Files modified after a given date



Zefram wrote:

> Sven Wischnowsky wrote:
> >;-) I first tried to implement it that way, but then... No, we can't
> >do it that way because as soon as something is executed $_ gets set
> >from exec.c to the last command word, as usual. And then it's too late 
> >to get at the filname.
> 
> Hmm.  Probably better to put it in $1 then.  Actually, execute the code
> as if it were the body of a shell function.

I couldn't convince myself to do that, so I just turned `REPLY' into
an in/out parameter (initially set to the filename and after the execution the
value is used as before).

Most of this patch is to save/restore the global globbing state,
though (in case the string or a function called from it does itself
some globbing).

Bye
 Sven

diff -u os/glob.c Src/glob.c
--- os/glob.c	Thu Aug 26 13:36:26 1999
+++ Src/glob.c	Fri Aug 27 10:03:29 1999
@@ -82,14 +82,6 @@
 /**/
 char *pathbuf;		/* pathname buffer (needed by pattern code) */
 
-static int matchsz;		/* size of matchbuf                     */
-static int matchct;		/* number of matches found              */
-static int pathbufsz;		/* size of pathbuf			*/
-static int pathbufcwd;		/* where did we chdir()'ed		*/
-static Gmatch matchbuf;		/* array of matches                     */
-static Gmatch matchptr;		/* &matchbuf[matchct]                   */
-static char *colonmod;		/* colon modifiers in qualifier list    */
-
 typedef struct stat *Statptr;	 /* This makes the Ultrix compiler happy.  Go figure. */
 
 /* modifier for unit conversions */
@@ -121,20 +113,86 @@
     char *sdata;		/* currently only: expression to eval        */
 };
 
-/* Qualifiers pertaining to current pattern */
-static struct qual *quals;
-
-/* Other state values for current pattern */
-static int qualct, qualorct;
-static int range, amc, units;
-static int gf_nullglob, gf_markdirs, gf_noglobdots, gf_listtypes, gf_follow;
-static int gf_sorts, gf_nsorts, gf_sortlist[11];
-
 /* Prefix, suffix for doing zle trickery */
 
 /**/
 char *glob_pre, *glob_suf;
 
+/* struct to easily save/restore current state */
+
+struct globdata {
+    int gd_badcshglob;
+    int gd_pathpos;
+    char *gd_pathbuf;
+
+    int gd_matchsz;		/* size of matchbuf                     */
+    int gd_matchct;		/* number of matches found              */
+    int gd_pathbufsz;		/* size of pathbuf			*/
+    int gd_pathbufcwd;		/* where did we chdir()'ed		*/
+    Gmatch gd_matchbuf;		/* array of matches                     */
+    Gmatch gd_matchptr;		/* &matchbuf[matchct]                   */
+    char *gd_colonmod;		/* colon modifiers in qualifier list    */
+
+    /* Qualifiers pertaining to current pattern */
+    struct qual *gd_quals;
+
+    /* Other state values for current pattern */
+    int gd_qualct, gd_qualorct;
+    int gd_range, gd_amc, gd_units;
+    int gd_gf_nullglob, gd_gf_markdirs, gd_gf_noglobdots, gd_gf_listtypes;
+    int gd_gf_follow, gd_gf_sorts, gd_gf_nsorts, gd_gf_sortlist[11];
+
+    char *gd_glob_pre, *gd_glob_suf;
+};
+
+/* The variable with the current globbing state and convenience macros */
+
+static struct globdata curglobdata;
+
+#define matchsz       (curglobdata.gd_matchsz)
+#define matchct       (curglobdata.gd_matchct)
+#define pathbufsz     (curglobdata.gd_pathbufsz)
+#define pathbufcwd    (curglobdata.gd_pathbufcwd)
+#define matchbuf      (curglobdata.gd_matchbuf)
+#define matchptr      (curglobdata.gd_matchptr)
+#define colonmod      (curglobdata.gd_colonmod)
+#define quals         (curglobdata.gd_quals)
+#define qualct        (curglobdata.gd_qualct)
+#define qualorct      (curglobdata.gd_qualorct)
+#define g_range       (curglobdata.gd_range)
+#define g_amc         (curglobdata.gd_amc)
+#define g_units       (curglobdata.gd_units)
+#define gf_nullglob   (curglobdata.gd_gf_nullglob)
+#define gf_markdirs   (curglobdata.gd_gf_markdirs)
+#define gf_noglobdots (curglobdata.gd_gf_noglobdots)
+#define gf_listtypes  (curglobdata.gd_gf_listtypes)
+#define gf_follow     (curglobdata.gd_gf_follow)
+#define gf_sorts      (curglobdata.gd_gf_sorts)
+#define gf_nsorts     (curglobdata.gd_gf_nsorts)
+#define gf_sortlist   (curglobdata.gd_gf_sortlist)
+
+/* and macros for save/restore */
+
+#define save_globstate(N) \
+  do { \
+    memcpy(&(N), &curglobdata, sizeof(struct globdata)); \
+    (N).gd_badcshglob = badcshglob; \
+    (N).gd_pathpos = pathpos; \
+    (N).gd_pathbuf = pathbuf; \
+    (N).gd_glob_pre = glob_pre; \
+    (N).gd_glob_suf = glob_suf; \
+  } while (0)
+
+#define restore_globstate(N) \
+  do { \
+    memcpy(&curglobdata, &(N), sizeof(struct globdata)); \
+    badcshglob = (N).gd_badcshglob; \
+    pathpos = (N).gd_pathpos; \
+    pathbuf = (N).gd_pathbuf; \
+    glob_pre = (N).gd_glob_pre; \
+    glob_suf = (N).gd_glob_suf; \
+  } while (0)
+
 /* pathname component in filename patterns */
 
 struct complist {
@@ -250,9 +308,9 @@
 	statted = 1;
 	qo = quals;
 	for (qn = qo; qn && qn->func;) {
-	    range = qn->range;
-	    amc = qn->amc;
-	    units = qn->units;
+	    g_range = qn->range;
+	    g_amc = qn->amc;
+	    g_units = qn->units;
 	    if ((qn->sense & 2) && !(statted & 2)) {
 		/* If (sense & 2), we're following links */
 		if (!S_ISLNK(buf.st_mode) || statfullpath(s, &buf2, 0))
@@ -819,11 +877,15 @@
 					/* chops it up                   */
     int first = 0, last = -1;		/* index of first/last match to  */
 				        /* return */
+    struct globdata saved;		/* saved glob state              */
+
     MUSTUSEHEAP("glob");
     if (unset(GLOBOPT) || !haswilds(ostr)) {
 	untokenize(ostr);
 	return;
     }
+    save_globstate(saved);
+
     str = dupstring(ostr);
     sl = strlen(str);
     uremnode(list, np);
@@ -997,7 +1059,7 @@
 		    case 'l':
 			/* Match files with the given no. of hard links */
 			func = qualnlink;
-			amc = -1;
+			g_amc = -1;
 			goto getrange;
 		    case 'U':
 			/* Match files owned by effective user ID */
@@ -1115,48 +1177,48 @@
 			break;
 		    case 'a':
 			/* Access time in given range */
-			amc = 0;
+			g_amc = 0;
 			func = qualtime;
 			goto getrange;
 		    case 'm':
 			/* Modification time in given range */
-			amc = 1;
+			g_amc = 1;
 			func = qualtime;
 			goto getrange;
 		    case 'c':
 			/* Inode creation time in given range */
-			amc = 2;
+			g_amc = 2;
 			func = qualtime;
 			goto getrange;
 		    case 'L':
 			/* File size (Length) in given range */
 			func = qualsize;
-			amc = -1;
+			g_amc = -1;
 			/* Get size multiplier */
-			units = TT_BYTES;
+			g_units = TT_BYTES;
 			if (*s == 'p' || *s == 'P')
-			    units = TT_POSIX_BLOCKS, ++s;
+			    g_units = TT_POSIX_BLOCKS, ++s;
 			else if (*s == 'k' || *s == 'K')
-			    units = TT_KILOBYTES, ++s;
+			    g_units = TT_KILOBYTES, ++s;
 			else if (*s == 'm' || *s == 'M')
-			    units = TT_MEGABYTES, ++s;
+			    g_units = TT_MEGABYTES, ++s;
 		      getrange:
 			/* Get time multiplier */
-			if (amc >= 0) {
-			    units = TT_DAYS;
+			if (g_amc >= 0) {
+			    g_units = TT_DAYS;
 			    if (*s == 'h')
-				units = TT_HOURS, ++s;
+				g_units = TT_HOURS, ++s;
 			    else if (*s == 'm')
-				units = TT_MINS, ++s;
+				g_units = TT_MINS, ++s;
 			    else if (*s == 'w')
-				units = TT_WEEKS, ++s;
+				g_units = TT_WEEKS, ++s;
 			    else if (*s == 'M')
-				units = TT_MONTHS, ++s;
+				g_units = TT_MONTHS, ++s;
 			    else if (*s == 's')
-				units = TT_SECONDS, ++s;
+				g_units = TT_SECONDS, ++s;
 			}
 			/* See if it's greater than, equal to, or less than */
-			if ((range = *s == '+' ? 1 : *s == '-' ? -1 : 0))
+			if ((g_range = *s == '+' ? 1 : *s == '-' ? -1 : 0))
 			    ++s;
 			data = qgetnum(&s);
 			break;
@@ -1175,12 +1237,14 @@
 			    case 'c': t = GS_CTIME; break;
 			    default:
 				zerr("unknown sort specifier", NULL, 0);
+				restore_globstate(saved);
 				return;
 			    }
 			    if ((sense & 2) && t != GS_NAME)
 				t <<= GS_SHIFT;
 			    if (gf_sorts & t) {
 				zerr("doubled sort specifier", NULL, 0);
+				restore_globstate(saved);
 				return;
 			    }
 			    gf_sorts |= t;
@@ -1202,16 +1266,11 @@
 				func = qualsheval;
 				sdata = dupstring(s + 1);
 				untokenize(sdata);
-				if (!parsestr(sdata)) {
-				    *tt = sav;
-				    if (sav)
-					s = tt + 1;
-				    else
-					s = tt;
-				} else {
-				    func = NULL;
-				    sdata = NULL;
-				}
+				*tt = sav;
+				if (sav)
+				    s = tt + 1;
+				else
+				    s = tt;
 			    }
 			    break;
 			}
@@ -1227,6 +1286,7 @@
 			    v.inv = 0;
 			    if (getindex(&s, &v) || s == os) {
 				zerr("invalid subscript", NULL, 0);
+				restore_globstate(saved);
 				return;
 			    }
 			    first = v.a;
@@ -1235,6 +1295,7 @@
 			}
 		    default:
 			zerr("unknown file attribute", NULL, 0);
+			restore_globstate(saved);
 			return;
 		    }
 		if (func) {
@@ -1250,19 +1311,22 @@
 		    qn->sense = sense;
 		    qn->data = data;
 		    qn->sdata = sdata;
-		    qn->range = range;
-		    qn->units = units;
-		    qn->amc = amc;
+		    qn->range = g_range;
+		    qn->units = g_units;
+		    qn->amc = g_amc;
 		    qn = NULL;
 		    qualct++;
 		}
-		if (errflag)
+		if (errflag) {
+		    restore_globstate(saved);
 		    return;
+		}
 	    }
 	}
     }
     q = parsepat(str);
     if (!q || errflag) {	/* if parsing failed */
+	restore_globstate(saved);
 	if (unset(BADPATTERN)) {
 	    untokenize(ostr);
 	    insertlinknode(list, node, ostr);
@@ -1326,6 +1390,8 @@
 	}
     }
     free(matchbuf);
+
+    restore_globstate(saved);
 }
 
 /* Return the order of two strings, taking into account *
@@ -2234,8 +2300,8 @@
 static int
 qualnlink(char *name, struct stat *buf, off_t ct, char *dummy)
 {
-    return (range < 0 ? buf->st_nlink < ct :
-	    range > 0 ? buf->st_nlink > ct :
+    return (g_range < 0 ? buf->st_nlink < ct :
+	    g_range > 0 ? buf->st_nlink > ct :
 	    buf->st_nlink == ct);
 }
 
@@ -2372,7 +2438,7 @@
     unsigned long scaled = (unsigned long)buf->st_size;
 #endif
 
-    switch (units) {
+    switch (g_units) {
     case TT_POSIX_BLOCKS:
 	scaled += 511l;
 	scaled /= 512l;
@@ -2387,8 +2453,8 @@
 	break;
     }
 
-    return (range < 0 ? scaled < QS_CAST_SIZE() size :
-	    range > 0 ? scaled > QS_CAST_SIZE() size :
+    return (g_range < 0 ? scaled < QS_CAST_SIZE() size :
+	    g_range > 0 ? scaled > QS_CAST_SIZE() size :
 	    scaled == QS_CAST_SIZE() size);
 #undef QS_CAST_SIZE
 }
@@ -2402,10 +2468,10 @@
     time_t now, diff;
 
     time(&now);
-    diff = now - (amc == 0 ? buf->st_atime : amc == 1 ? buf->st_mtime :
+    diff = now - (g_amc == 0 ? buf->st_atime : g_amc == 1 ? buf->st_mtime :
 		  buf->st_ctime);
     /* handle multipliers indicating units */
-    switch (units) {
+    switch (g_units) {
     case TT_DAYS:
 	diff /= 86400l;
 	break;
@@ -2423,8 +2489,8 @@
 	break;
     }
 
-    return (range < 0 ? diff < days :
-	    range > 0 ? diff > days :
+    return (g_range < 0 ? diff < days :
+	    g_range > 0 ? diff > days :
 	    diff == days);
 }
 
@@ -2435,19 +2501,12 @@
 qualsheval(char *name, struct stat *buf, off_t days, char *str)
 {
     List list;
-    char *usav = underscore;
-
-    underscore = name;
-    str = dupstring(str);
-    singsub(&str);
-    underscore = usav;
-    untokenize(str);
 
     if ((list = parse_string(str, 0))) {
 	int ef = errflag, lv = lastval, ret;
 
 	unsetparam("reply");
-	unsetparam("REPLY");
+	setsparam("REPLY", ztrdup(name));
 
 	execlist(list, 1, 0);
 
diff -u od/Zsh/expn.yo Doc/Zsh/expn.yo
--- od/Zsh/expn.yo	Thu Aug 26 13:36:20 1999
+++ Doc/Zsh/expn.yo	Fri Aug 27 10:10:21 1999
@@ -1384,17 +1384,16 @@
 separator and anything up to the next matching separator will be taken 
 as the var(string) (`tt([)', `tt({)', and `tt(<)' match `tt(])',
 `tt(})', and `tt(>)' respectively, any other character matches
-itself). Before the string is executed, expansion is performed on it
-with the parameter tt($_) being set to the filename currently being
-tested. Note that parameter expansions in the var(string) have to be
-quoted to prevent them from being expanded before globbing is done.
+itself). Note that expansions have to be quoted in the var(string) to
+prevent them from being expanded before globbing is done.
 
-If during the execution of var(string) the parameter tt(reply) is set
-to an array or to a string or if the parameter tt(REPLY) is set to a
-string, then these strings will be inserted into the generated list
-instead of the original filename. For security reasons, these
-parameters will be unset by the shell before the var(string) is
-executed.
+During the execution of var(string) the parameter tt(REPLY) is set to
+the filename currently being tested. It may also be set to any string
+to make this string be inserted into the list instead of the original
+filename. Also, the parameter tt(reply) may be set to an array or a
+string and if it is, these strings will be inserted instead of the
+value of the tt(REPLY) parameter. For security reasons, tt(reply)
+will be unset by the shell before the var(string) is executed.
 )
 item(tt(d)var(dev))(
 files on the device var(dev)

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



Messages sorted by: Reverse Date, Date, Thread, Author