zsh-workers
 help / color / mirror / code / Atom feed
* Patch for giga- and terabyte size specifiers
@ 2014-02-19 13:12 Manuel Presnitz
  2014-02-19 13:52 ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: Manuel Presnitz @ 2014-02-19 13:12 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 5897 bytes --]

Dear zsh workers,

I thought it is time to have globbing size specifiers at hand also for gigabytes,
and while at it for terabytes, too.
As that seemed pretty straight forward, I tried to do the modification myself.

So please find attached my patch to allow e.g. *(Lg+10) as well as *(Lt+1).

On second thought I was not so straight forward as expected, so I hope I've done it
correct; here are my thoughts:

(1, glob.c) I included a check if ZSH_64_BIT_TYPE or LONG_IS_64 is defined, hence a 64-bit
long type is available. If long is 32-bit the code isn't effectively changed at all.

Although 1GB is small enough to fit in a 32-bit long, I included this case in the #if block,
too -- just in case I have overlooked some logic and to prevent an overrun in case of a file
size slightly larger than 3GB.

(2, expn.yo) In the documentation I first mentioned the term ,,size specifiers'' which is
used in the completion but is not showing up in the doc so far. I included the G and T
specifiers of course, but introduced this sentence with ,,on some systems''. I wanted to
keep it simple, hence I didn't mention the 64-bit condition.

(3, _globquals) With the patch to the completion function I'm not satisfied completely,
but I don't know how to do it better. First thing, the G and T madifiers are shown also
with a 32-bit zsh executable. I tried to figure out a possibility to check if zsh is a
64-bit executable during runtime, but failed.
Second, the items are ordered alphabetical in the completion list, resulting in an ugly
arrangement: GB - KB - MB - blocks (p) - TB
So far the list is -- either by change or by a very clever design decision -- ordered in a
sensible way, first with increasing size the common unit prefixes and then blocks:
KB - MB - blocks (p).

Regarding these weak points, I'd appreciate your feedback. And of course if there
are other problems I don't think of so far.


Best regards,
Manuel.


---
 Completion/Zsh/Type/_globquals |    6 +++---
 Doc/Zsh/expn.yo                |   10 ++++++----
 Src/glob.c                     |   18 ++++++++++++++++++
 3 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals
index 9de7742..c98bd0c 100644
--- a/Completion/Zsh/Type/_globquals
+++ b/Completion/Zsh/Type/_globquals
@@ -132,13 +132,13 @@ while [[ -n $PREFIX ]]; do

     (L)
     # complete/skip file size
-    if ! compset -P '([kKmMpP]|)([-+]|)<->'; then
+    if ! compset -P '([kKmMgGtTpP]|)([-+]|)<->'; then
       # complete/skip size spec
       alts=()
-      if ! compset -P '[kKmMpP]' && [[ -z $PREFIX ]]; then
+      if ! compset -P '[kKmMgGtTpP]' && [[ -z $PREFIX ]]; then
         alts+=(
           "size-specifiers:size specifier:\
-((k\:kb m\:mb p\:512-byte\ blocks))")
+((k\:kb m\:mb g\:gb t\:tb p\:512-byte\ blocks))")
       fi
       if ! compset -P '[-+]' && [[ -z $PREFIX ]]; then
         alts+=("senses:sense:((-\:less\ than +\:more\ than))")
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 6459c6f..de0f454 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -2521,10 +2521,12 @@ item(tt(L)[tt(PLUS())|tt(-)]var(n))(
 files less than var(n) bytes (tt(-)), more than var(n) bytes (tt(PLUS())), or
 exactly var(n) bytes in length.

-If this flag is directly followed by a `tt(k)' (`tt(K)'), `tt(m)'
-(`tt(M)'), or `tt(p)' (`tt(P)') (e.g. `tt(Lk-50)') the check is performed
-with kilobytes, megabytes, or blocks (of 512 bytes) instead.  In this
-case a file is regarded as "exactly" the size if the file size rounded up
+If this flag is directly followed by a em(size specifier) `tt(k)' (`tt(K)'),
+`tt(m)' (`tt(M)'), or `tt(p)' (`tt(P)') (e.g. `tt(Lk-50)') the check is
+performed with kilobytes, megabytes, or blocks (of 512 bytes) instead.
+(On some systems additional specifiers are available for gigabytes,
+`tt(g)' or `tt(G)', and terabytes, `tt(t)' or `tt(T)'.) If a size specifier
+is used a file is regarded as "exactly" the size if the file size rounded up
 to the next unit is equal to the test size.  Hence `tt(*LPAR()Lm1+RPAR())'
 matches files from 1 byte up to 1 Megabyte inclusive.  Note also that
 the set of files "less than" the test size only includes files that would
diff --git a/Src/glob.c b/Src/glob.c
index 9a34a7f..c4227e0 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -120,6 +120,8 @@ typedef struct stat *Statptr;        /* This makes the Ultrix compiler happy.  Go figu
 #define TT_POSIX_BLOCKS 1
 #define TT_KILOBYTES 2
 #define TT_MEGABYTES 3
+#define TT_GIGABYTES 4
+#define TT_TERABYTES 5


 typedef int (*TestMatchFunc) _((char *, struct stat *, off_t, char *));
@@ -1486,6 +1488,12 @@ zglob(LinkList list, LinkNode np, int nountok)
                        g_units = TT_KILOBYTES, ++s;
                    else if (*s == 'm' || *s == 'M')
                        g_units = TT_MEGABYTES, ++s;
+#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
+                    else if (*s == 'g' || *s == 'G')
+                        g_units = TT_GIGABYTES, ++s;
+                    else if (*s == 't' || *s == 'T')
+                        g_units = TT_TERABYTES, ++s;
+#endif
                  getrange:
                    /* Get time multiplier */
                    if (g_amc >= 0) {
@@ -3559,6 +3567,16 @@ qualsize(UNUSED(char *name), struct stat *buf, off_t size, UNUSED(char *dummy))
        scaled += 1048575l;
        scaled /= 1048576l;
        break;
+#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
+    case TT_GIGABYTES:
+        scaled += 1073741823l;
+        scaled /= 1073741824l;
+        break;
+    case TT_TERABYTES:
+        scaled += 1099511627775l;
+        scaled /= 1099511627776l;
+        break;
+#endif
     }

     return (g_range < 0 ? scaled < QS_CAST_SIZE() size :


[-- Attachment #2: completion.patch --]
[-- Type: application/octet-stream, Size: 832 bytes --]

diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals
index 9de7742..c98bd0c 100644
--- a/Completion/Zsh/Type/_globquals
+++ b/Completion/Zsh/Type/_globquals
@@ -132,13 +132,13 @@ while [[ -n $PREFIX ]]; do
 
     (L)
     # complete/skip file size
-    if ! compset -P '([kKmMpP]|)([-+]|)<->'; then
+    if ! compset -P '([kKmMgGtTpP]|)([-+]|)<->'; then
       # complete/skip size spec
       alts=()
-      if ! compset -P '[kKmMpP]' && [[ -z $PREFIX ]]; then
+      if ! compset -P '[kKmMgGtTpP]' && [[ -z $PREFIX ]]; then
         alts+=(
           "size-specifiers:size specifier:\
-((k\:kb m\:mb p\:512-byte\ blocks))")
+((k\:kb m\:mb g\:gb t\:tb p\:512-byte\ blocks))")
       fi
       if ! compset -P '[-+]' && [[ -z $PREFIX ]]; then
         alts+=("senses:sense:((-\:less\ than +\:more\ than))")

[-- Attachment #3: sizespec.patch --]
[-- Type: application/octet-stream, Size: 2687 bytes --]

diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 6459c6f..de0f454 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -2521,10 +2521,12 @@ item(tt(L)[tt(PLUS())|tt(-)]var(n))(
 files less than var(n) bytes (tt(-)), more than var(n) bytes (tt(PLUS())), or
 exactly var(n) bytes in length.
 
-If this flag is directly followed by a `tt(k)' (`tt(K)'), `tt(m)'
-(`tt(M)'), or `tt(p)' (`tt(P)') (e.g. `tt(Lk-50)') the check is performed
-with kilobytes, megabytes, or blocks (of 512 bytes) instead.  In this
-case a file is regarded as "exactly" the size if the file size rounded up
+If this flag is directly followed by a em(size specifier) `tt(k)' (`tt(K)'),
+`tt(m)' (`tt(M)'), or `tt(p)' (`tt(P)') (e.g. `tt(Lk-50)') the check is
+performed with kilobytes, megabytes, or blocks (of 512 bytes) instead.
+(On some systems additional specifiers are available for gigabytes,
+`tt(g)' or `tt(G)', and terabytes, `tt(t)' or `tt(T)'.) If a size specifier
+is used a file is regarded as "exactly" the size if the file size rounded up
 to the next unit is equal to the test size.  Hence `tt(*LPAR()Lm1+RPAR())'
 matches files from 1 byte up to 1 Megabyte inclusive.  Note also that
 the set of files "less than" the test size only includes files that would
diff --git a/Src/glob.c b/Src/glob.c
index 9a34a7f..c4227e0 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -120,6 +120,8 @@ typedef struct stat *Statptr;	 /* This makes the Ultrix compiler happy.  Go figu
 #define TT_POSIX_BLOCKS 1
 #define TT_KILOBYTES 2
 #define TT_MEGABYTES 3
+#define TT_GIGABYTES 4
+#define TT_TERABYTES 5
 
 
 typedef int (*TestMatchFunc) _((char *, struct stat *, off_t, char *));
@@ -1486,6 +1488,12 @@ zglob(LinkList list, LinkNode np, int nountok)
 			g_units = TT_KILOBYTES, ++s;
 		    else if (*s == 'm' || *s == 'M')
 			g_units = TT_MEGABYTES, ++s;
+#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
+                    else if (*s == 'g' || *s == 'G')
+                        g_units = TT_GIGABYTES, ++s;
+                    else if (*s == 't' || *s == 'T')
+                        g_units = TT_TERABYTES, ++s;
+#endif
 		  getrange:
 		    /* Get time multiplier */
 		    if (g_amc >= 0) {
@@ -3559,6 +3567,16 @@ qualsize(UNUSED(char *name), struct stat *buf, off_t size, UNUSED(char *dummy))
 	scaled += 1048575l;
 	scaled /= 1048576l;
 	break;
+#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
+    case TT_GIGABYTES:
+        scaled += 1073741823l;
+        scaled /= 1073741824l;
+        break;
+    case TT_TERABYTES:
+        scaled += 1099511627775l;
+        scaled /= 1099511627776l;
+        break;
+#endif
     }
 
     return (g_range < 0 ? scaled < QS_CAST_SIZE() size :

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Patch for giga- and terabyte size specifiers
  2014-02-19 13:12 Patch for giga- and terabyte size specifiers Manuel Presnitz
@ 2014-02-19 13:52 ` Peter Stephenson
  2014-02-19 20:03   ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Stephenson @ 2014-02-19 13:52 UTC (permalink / raw)
  To: zsh-workers

On Wed, 19 Feb 2014 14:12:03 +0100
Manuel Presnitz <mpy@gmx.net> wrote:
> I thought it is time to have globbing size specifiers at hand also for
> gigabytes, and while at it for terabytes, too.  As that seemed pretty
> straight forward, I tried to do the modification myself.

Generally looks fine, thanks...

> +#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
> +    case TT_GIGABYTES:
> +        scaled += 1073741823l;
> +        scaled /= 1073741824l;
> +        break;
> +    case TT_TERABYTES:
> +        scaled += 1099511627775l;
> +        scaled /= 1099511627776l;
> +        break;
> +#endif

I suppose we need to be a bit careful here since we don't know the
64-bit type is long, so the suffix may not be right and we might get
overflow of the constant.

I'm not sure if we get away with e.g.

(zlong)1099511627775

--- my C basics aren't up to remembering whether the compiler is
required to look at the type of a cast when interpreting a constant,
but I have a suspicion it isn't.

Otherwise, I guess we need something like...

#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
#ifdef LONG_IS_64_BIT
#define ZLONG_CONST(x)  x ## l
#else
#define ZLONG_CONST(x)  x ## ll
#endif
    case TT_GIGABYTES:
        scaled += ZLONG_CONST(1073741823);
        scaled /= ZLONG_CONST(1073741824);
        break;
    case TT_TERABYTES:
        scaled += ZLONG_CONST(1099511627775);
        scaled /= ZLONG_CONST(1099511627776);
        break;
#endif

although probably even that doesn't work for the mysterious "quad" type
mentioned in some bits of the shell.  Or maybe I'm being too pernickety.

(I have a feeling this is all done much better in D :-/)

pws


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Patch for giga- and terabyte size specifiers
  2014-02-19 13:52 ` Peter Stephenson
@ 2014-02-19 20:03   ` Peter Stephenson
  0 siblings, 0 replies; 3+ messages in thread
From: Peter Stephenson @ 2014-02-19 20:03 UTC (permalink / raw)
  To: zsh-workers

On Wed, 19 Feb 2014 13:52:42 +0000
Peter Stephenson <p.stephenson@samsung.com> wrote:
> #if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
> #ifdef LONG_IS_64_BIT
> #define ZLONG_CONST(x)  x ## l
> #else
> #define ZLONG_CONST(x)  x ## ll
> #endif
>     case TT_GIGABYTES:
>         scaled += ZLONG_CONST(1073741823);
>         scaled /= ZLONG_CONST(1073741824);
>         break;
>     case TT_TERABYTES:
>         scaled += ZLONG_CONST(1099511627775);
>         scaled /= ZLONG_CONST(1099511627776);
>         break;
> #endif

OK, how about

#if defined(ZSH_64_BIT_TYPE) || defined(LONG_IS_64_BIT)
#ifdef LONG_IS_64_BIT
#define ZLONG_CONST(x)  x ## l
#else
#ifdef ZLONG_IS_LONG_LONG
#define ZLONG_CONST(x)  x ## ll
#else
/*
 * There's some 64-bit type, but we don't know what it is.
 * We'll just cast it and hope the compiler does the right thing.
 */
#define ZLONG_CONST(x) ((zlong)x)
#endif
#else
/* We're stuck with long */
#define ZLONG_CONST(x) (x ## l)
#endif

?  That seems to cover everything we can do within standard C.

pws


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2014-02-19 20:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-19 13:12 Patch for giga- and terabyte size specifiers Manuel Presnitz
2014-02-19 13:52 ` Peter Stephenson
2014-02-19 20:03   ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).