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

PATCH: stat option to set hash



This patch is relavite to Peter Stephenson's patched 3.1.5 archive,
dated November 17th (no sub-version number?)

This patch does two things:
 (1) adds a -H flag to the stat module-builtin, similar to -A.  Keys are
     those from `stat -l`.  Other flags to stat affect values stored; if
     the name is requested then an extra key "name" is used.
     % stat -nsH foo myfile
     % print $foo[inode]
     12345
     % print ${(kv)foo}

 (2) Adds a sethparam() to params.c;
     THIS IS BUGGY!  (for other uses)
     Basically, it doesn't check the special cases such as PM_UNIQUE etc
     etc.  It implements enough to provide an exported function which
     the stat module can use.  I can't just createparam() and
     arrhashsetfn() as the latter is declared static.

Someone who's familiar with all the semantics for various variables will
need to expand my sethparam() to handle the other cases before anything
other than bin_stat() uses it.  Note that the current sethparam() just
relies upon currently being able to just refuse to touch specials.

If there parameter expansion flags such as j could be extended to handle
the distinction betwwen key/value and value/key boundaries, it would
become simple to emulate the default stat behaviour with a function and
then to consider changing the default behaviour.  It seems to me
anomalous that stat primarily generates textual output.

Now someone will tell me I've screwed up again ...

*** dSrc/Modules/stat.c	Sat Oct 31 15:25:09 1998
--- Src/Modules/stat.c	Wed Dec  9 00:25:35 1998
***************
*** 34,44 ****
  		   ST_RDEV, ST_SIZE, ST_ATIM, ST_MTIM, ST_CTIM,
  		   ST_BLKSIZE, ST_BLOCKS, ST_READLINK, ST_COUNT };
  enum statflags { STF_NAME = 1,  STF_FILE = 2, STF_STRING = 4, STF_RAW = 8,
! 		     STF_PICK = 16, STF_ARRAY = 32, STF_GMT = 64 };
  static char *statelts[] = { "device", "inode", "mode", "nlink",
  				"uid", "gid", "rdev", "size", "atime",
  				"mtime", "ctime", "blksize", "blocks",
  				"link", NULL };
  
  /**/
  static void
--- 34,46 ----
  		   ST_RDEV, ST_SIZE, ST_ATIM, ST_MTIM, ST_CTIM,
  		   ST_BLKSIZE, ST_BLOCKS, ST_READLINK, ST_COUNT };
  enum statflags { STF_NAME = 1,  STF_FILE = 2, STF_STRING = 4, STF_RAW = 8,
! 		     STF_PICK = 16, STF_ARRAY = 32, STF_GMT = 64,
! 		     STF_HASH = 128 };
  static char *statelts[] = { "device", "inode", "mode", "nlink",
  				"uid", "gid", "rdev", "size", "atime",
  				"mtime", "ctime", "blksize", "blocks",
  				"link", NULL };
+ #define HNAMEKEY "name"
  
  /**/
  static void
***************
*** 287,292 ****
--- 289,296 ----
   *        file names are returned as a separate array element, type names as
   *        prefix to element.  Note the formatting deliberately contains
   *        fewer frills when -A is used.
+  *  -H hash:  as for -A array, but returns a hash with the keys being those
+  *        from stat -l
   *  -F fmt: specify a $TIME-like format for printing times; the default
   *        is the (CTIME-like) "%a %b %e %k:%M:%S".  This option implies
   *        -s as it is not useful for numerical times.
***************
*** 305,310 ****
--- 309,315 ----
  bin_stat(char *name, char **args, char *ops, int func)
  {
      char **aptr, *arrnam = NULL, **array = NULL, **arrptr = NULL;
+     char *hashnam = NULL, **hash = NULL, **hashptr = NULL;
      int len, iwhich = -1, ret = 0, flags = 0, arrsize = 0, fd = 0;
      struct stat statbuf;
      int found = 0, nargs;
***************
*** 352,357 ****
--- 357,372 ----
  		    }
  		    flags |= STF_ARRAY;
  		    break;
+ 		} else if (*arg == 'H') {
+ 		    if (arg[1]) {
+ 			hashnam = arg+1;
+ 		    } else if (!(hashnam = *++args)) {
+ 			zerrnam(name, "missing parameter name\n",
+ 				NULL, 0);
+ 			return 1;
+ 		    }
+ 		    flags |= STF_HASH;
+ 		    break;
  		} else if (*arg == 'f') {
  		    char *sfd;
  		    ops['f'] = 1;
***************
*** 385,390 ****
--- 400,414 ----
  	}
      }
  
+     if ((flags & STF_ARRAY) && (flags & STF_HASH)) {
+     	/* We don't implement setting multiple variables at once */
+ 	zwarnnam(name, "both array and hash requested", NULL, 0);
+ 	return 1;
+ 	/* Alternate method would be to make -H blank arrnam etc etc *
+ 	 * and so get 'silent loss' of earlier choice, which would   *
+ 	 * be similar to stat -A foo -A bar filename                 */
+     }
+ 
      if (ops['l']) {
  	/* list types and return:  can also list to array */
  	if (arrnam) {
***************
*** 435,441 ****
      if (ops['g'])
  	flags |= STF_GMT;
  
!     if (!arrnam) {
  	if (nargs > 1)
  	    flags |= STF_FILE;
  	if (!(flags & STF_PICK))
--- 459,465 ----
      if (ops['g'])
  	flags |= STF_GMT;
  
!     if (!(arrnam || hashnam)) {
  	if (nargs > 1)
  	    flags |= STF_FILE;
  	if (!(flags & STF_PICK))
***************
*** 444,452 ****
  
      if (ops['N'] || ops['f'])
  	flags &= ~STF_FILE;
!     if (ops['T'])
  	flags &= ~STF_NAME;
  
      if (arrnam) {
  	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
  	if (flags & STF_FILE)
--- 468,487 ----
  
      if (ops['N'] || ops['f'])
  	flags &= ~STF_FILE;
!     if (ops['T'] || ops['H'])
  	flags &= ~STF_NAME;
  
+     if (hashnam) {
+     	if (nargs > 1) {
+ 	    zwarnnam(name, "only one file allowed with -H", NULL, 0);
+ 	    return 1;
+ 	}
+ 	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
+ 	if (flags & STF_FILE)
+ 	    arrsize++;
+ 	hashptr = hash = (char **)zcalloc((arrsize+1)*2*sizeof(char *));
+     }
+ 
      if (arrnam) {
  	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
  	if (flags & STF_FILE)
***************
*** 473,485 ****
  	if (flags & STF_FILE)
  	    if (arrnam)
  		*arrptr++ = ztrdup(*args);
! 	    else
  		printf("%s%s", *args, (flags & STF_PICK) ? " " : ":\n");
  	if (iwhich > -1) {
  	    statprint(&statbuf, outbuf, *args, iwhich, flags);
  	    if (arrnam)
  		*arrptr++ = ztrdup(outbuf);
! 	    else
  		printf("%s\n", outbuf);
  	} else {
  	    int i;
--- 508,527 ----
  	if (flags & STF_FILE)
  	    if (arrnam)
  		*arrptr++ = ztrdup(*args);
! 	    else if (hashnam) {
! 	    	*hashptr++ = ztrdup(HNAMEKEY);
! 		*hashptr++ = ztrdup(*args);
! 	    } else
  		printf("%s%s", *args, (flags & STF_PICK) ? " " : ":\n");
  	if (iwhich > -1) {
  	    statprint(&statbuf, outbuf, *args, iwhich, flags);
  	    if (arrnam)
  		*arrptr++ = ztrdup(outbuf);
! 	    else if (hashnam) {
! 		/* STF_NAME explicitly turned off for ops['H'] above */
! 	    	*hashptr++ = ztrdup(statelts[iwhich]);
! 		*hashptr++ = ztrdup(outbuf);
! 	    } else
  		printf("%s\n", outbuf);
  	} else {
  	    int i;
***************
*** 487,510 ****
  		statprint(&statbuf, outbuf, *args, i, flags);
  		if (arrnam)
  		    *arrptr++= ztrdup(outbuf);
! 		else
  		    printf("%s\n", outbuf);
  	    }
  	}
  	if (ops['f'])
  	    break;
  
! 	if (!arrnam && args[1] && !(flags & STF_PICK))
  	    putchar('\n');
      }
  
      if (arrnam)
! 	if (ret) {
! 	    for (aptr = array; *aptr; aptr++)
! 		zsfree(*aptr);
! 	    zfree(array, arrsize+1);
! 	} else {
  	    setaparam(arrnam, array);
  	    if (errflag)
  		return 1;
  	}
--- 529,563 ----
  		statprint(&statbuf, outbuf, *args, i, flags);
  		if (arrnam)
  		    *arrptr++= ztrdup(outbuf);
! 		else if (hashnam) {
! 		    /* STF_NAME explicitly turned off for ops['H'] above */
! 		    *hashptr++ = ztrdup(statelts[i]);
! 		    *hashptr++ = ztrdup(outbuf);
! 		} else
  		    printf("%s\n", outbuf);
  	    }
  	}
  	if (ops['f'])
  	    break;
  
! 	if (!arrnam && !hashnam && args[1] && !(flags & STF_PICK))
  	    putchar('\n');
      }
  
      if (arrnam)
! 	if (ret)
! 	    freearray(array);
! 	else {
  	    setaparam(arrnam, array);
+ 	    if (errflag)
+ 		return 1;
+ 	}
+ 
+     if (hashnam)
+     	if (ret)
+ 	    freearray(hash);
+ 	else {
+ 	    sethparam(hashnam, hash);
  	    if (errflag)
  		return 1;
  	}
*** dSrc/zsh.export	Sat Nov 14 14:27:28 1998
--- Src/zsh.export	Wed Dec  9 00:21:21 1998
***************
*** 159,164 ****
--- 159,165 ----
  retflag
  scanhashtable
  setaparam
+ sethparam
  setlimits
  setsparam
  settyinfo
*** dSrc/params.c	Tue Nov 17 12:48:08 1998
--- Src/params.c	Wed Dec  9 00:50:22 1998
***************
*** 1488,1493 ****
--- 1488,1526 ----
  
  /**/
  Param
+ sethparam(char *s, char **kvarr)
+ {
+     Value v;
+     Param pm;
+     char *t;
+ 
+     if (!isident(s)) {
+ 	zerr("not an identifier: %s", s, 0);
+ 	freearray(kvarr);
+ 	errflag = 1;
+ 	return NULL;
+     }
+     t=ztrdup(s); /* Is this a memory leak? */
+     /* Why does getvalue(s, 1) set s to empty string? */
+     if ((v = getvalue(&t, 1)))
+ 	if (v->pm->flags & PM_SPECIAL) {
+ 	    zerr("not overriding a special: %s", s, 0);
+ 	    freearray(kvarr);
+ 	    errflag = 1;
+ 	    return NULL;
+ 	} else
+ 	    unsetparam(s);
+ 
+     pm = createparam(s, PM_HASHED);
+     DPUTS(!pm, "BUG: parameter not created");
+ 
+     arrhashsetfn(pm, kvarr);
+ 
+     return pm;
+ }
+ 
+ /**/
+ Param
  setiparam(char *s, long val)
  {
      Value v;
*** dDoc/Zsh/mod_stat.yo	Thu Mar 27 01:57:34 1997
--- Doc/Zsh/mod_stat.yo	Wed Dec  9 00:59:06 1998
***************
*** 6,12 ****
  findex(stat)
  cindex(files, listing)
  cindex(files, examining)
! item(tt(stat) [ tt(-gnNlLtTrs) ] [ tt(-f) var(fd) ] [ tt(-A) var(array) ] \
      [ tt(-F) var(fmt) ] [ tt(PLUS())var(element) ] [ var(file) ... ])(
  The command acts as a front end to the tt(stat) system call (see
  manref(stat)(2)).
--- 6,13 ----
  findex(stat)
  cindex(files, listing)
  cindex(files, examining)
! item(tt(stat) [ tt(-gnNlLtTrs) ] [ tt(-f) var(fd) ] \
!     [ tt(-H) var(hash) ] [ tt(-A) var(array) ] \
      [ tt(-F) var(fmt) ] [ tt(PLUS())var(element) ] [ var(file) ... ])(
  The command acts as a front end to the tt(stat) system call (see
  manref(stat)(2)).
***************
*** 90,95 ****
--- 91,101 ----
  appropriate array element and in the latter case the file name
  appears as a separate array element preceding all the others.
  Other formatting options are respected.
+ )
+ item(tt(-H) var(hash))(
+ Similar to tt(-A), but instead assign the values to var(hash).  The keys
+ are the elements listed above.  If the tt(-n) option is provided then the
+ name of the file is included in the hash with key tt(name).
  )
  item(tt(-f) var(fd))(
  Use the file on file descriptor var(fd) instead of

-- 
--> Phil Pennock ; GAT d- s+:+ a22 C++(++++) UL++++/I+++/S+++/H+ P++@ L+++
E-@ W(+) N>++ o !K w--- O>+ M V !PS PE Y+ PGP+ t-- 5++ X+ R !tv b++>+++ DI+ D+
G+ e+ h* r y?



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