zsh-users
 help / color / mirror / code / Atom feed
* Determining the length of "long"?
@ 2014-09-11 21:36 Dominik Vogt
  2014-09-12  2:58 ` Kurtis Rader
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Dominik Vogt @ 2014-09-11 21:36 UTC (permalink / raw)
  To: Zsh Users

Is there a way to determine the length of the C type long from
inside a zsh script (without using external programs, of course).

As an alternative, is there a direct way to print out a "long"
integer value as binary bytes in host byte order?

I.e. given a value, say 0x12345, I need to print that as

  \\x00\\x01\\x23\\x45

on a 32 bit platform, and as

  \\x00\\x00\\x00\\x00\\x00\\x01\\x23\\x45

on a 64 bit platform (possibly in reverse byte order, depending on
the hardware).

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt



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

* Re: Determining the length of "long"?
  2014-09-11 21:36 Determining the length of "long"? Dominik Vogt
@ 2014-09-12  2:58 ` Kurtis Rader
  2014-09-12  4:39 ` Bart Schaefer
  2014-09-12 16:17 ` Roman Neuhauser
  2 siblings, 0 replies; 13+ messages in thread
From: Kurtis Rader @ 2014-09-12  2:58 UTC (permalink / raw)
  To: dominik.vogt, Zsh Users

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

There may be a way but why? A command shell is the wrong tool for that task.

You don't need to compile a C program to do this. If you have perl or
python it's an almost trivial problem. For example,

#!/usr/bin/env python
import ctypes

l = ctypes.c_long(0x12345)
print(ctypes.sizeof(l))

b = ctypes.string_at(ctypes.addressof(l), ctypes.sizeof(l))
print(''.join('\\x{:02x}'.format(ord(x)) for x in b))


On Thu, Sep 11, 2014 at 2:36 PM, Dominik Vogt <dominik.vogt@gmx.de> wrote:

> Is there a way to determine the length of the C type long from
> inside a zsh script (without using external programs, of course).
>
> As an alternative, is there a direct way to print out a "long"
> integer value as binary bytes in host byte order?
>
> I.e. given a value, say 0x12345, I need to print that as
>
>   \\x00\\x01\\x23\\x45
>
> on a 32 bit platform, and as
>
>   \\x00\\x00\\x00\\x00\\x00\\x01\\x23\\x45
>
> on a 64 bit platform (possibly in reverse byte order, depending on
> the hardware).
>
> Ciao
>
> Dominik ^_^  ^_^
>
> --
>
> Dominik Vogt
>
>
>


-- 
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

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

* Re: Determining the length of "long"?
  2014-09-11 21:36 Determining the length of "long"? Dominik Vogt
  2014-09-12  2:58 ` Kurtis Rader
@ 2014-09-12  4:39 ` Bart Schaefer
  2014-09-12  8:42   ` Dominik Vogt
  2014-09-12  8:51   ` Peter Stephenson
  2014-09-12 16:17 ` Roman Neuhauser
  2 siblings, 2 replies; 13+ messages in thread
From: Bart Schaefer @ 2014-09-12  4:39 UTC (permalink / raw)
  To: Zsh Users

On Sep 11, 10:36pm, Dominik Vogt wrote:
}
} Is there a way to determine the length of the C type long from
} inside a zsh script (without using external programs, of course).

As Kurtis mentioned, the shell really isn't the right tool for this,
but:

if (( ${#:-"$(( [#2] (1<<31)))"} > ${#:-"$(( [#2] (1<<63)))"} ))
then print "zsh integer type is 32 bits"
elif (( ${#:-"$(( [#2] (1<<63)))"} > ${#:-"$(( [#2] (1<<64)))"} ))
then print "zsh integer type is 64 bits"
else print "zsh integer type is more than 64 bits"
fi

} As an alternative, is there a direct way to print out a "long"
} integer value as binary bytes in host byte order?

There's no guarantee that zsh's integer type is "long", so no, there
is not.  You can try fiddling with bitwise operators, e.g.:

setopt C_BASES
integer i=0x12345
while (( i )) {
  printf '\\\\x%x\n' $(( [#16] (i & 0xff) ))
  (( i = i >> 8 ))
}

Printing the zero bytes and not messing up the byte order is left as
an exercise for the reader.


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

* Re: Determining the length of "long"?
  2014-09-12  4:39 ` Bart Schaefer
@ 2014-09-12  8:42   ` Dominik Vogt
  2014-09-12 13:17     ` Kurtis Rader
  2014-09-12 23:16     ` Bart Schaefer
  2014-09-12  8:51   ` Peter Stephenson
  1 sibling, 2 replies; 13+ messages in thread
From: Dominik Vogt @ 2014-09-12  8:42 UTC (permalink / raw)
  To: zsh-users

On Thu, Sep 11, 2014 at 07:58:29PM -0700, Kurtis Rader wrote:
> There may be a way but why? A command shell is the wrong tool for
> that task.

To give you a bit of background:  The script is an fvwm module,
and apart from the need of sending two longs to the window manager
core in binary format, the shell is absolutely the right tool here
(combine several unix command line programs in a pipe, filter their
output and generate a wm command from that).

> You don't need to compile a C program to do this. If you have perl or
> python it's an almost trivial problem.

I know, but I never do something in perl if it can be done in zsh.

On Thu, Sep 11, 2014 at 09:39:01PM -0700, Bart Schaefer wrote:
> if (( ${#:-"$(( [#2] (1<<31)))"} > ${#:-"$(( [#2] (1<<63)))"} ))
> then print "zsh integer type is 32 bits"
> elif (( ${#:-"$(( [#2] (1<<63)))"} > ${#:-"$(( [#2] (1<<64)))"} ))
> then print "zsh integer type is 64 bits"
> else print "zsh integer type is more than 64 bits"
> fi

Hm, I'm not really sure that works reliably because the shift
amount may be truncated before it is used.  I.e. on s390 "1 << 32"
and "1 << 64" and "1 << 0" are all the same.  Luckily I don't need
that on s390.

> There's no guarantee that zsh's integer type is "long", so no, there
> is not.

If long is not guaranteed, how does zsh determine which integer
type it uses in arithmetic?  Would it use long long if a long is
four bytes and long long is available?

Is it possible to print pointers or memory contents in zsh?

> setopt C_BASES
> integer i=0x12345
> while (( i )) {
>   printf '\\\\x%x\n' $(( [#16] (i & 0xff) ))
>   (( i = i >> 8 ))
> }

Actually the amount I have to print is just a byte, but with
three or seven null bytes before or after it, so all I really
need to know is the host byte order to pick the right variant.
But that is only a bonus for now.
 
Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany


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

* Re: Determining the length of "long"?
  2014-09-12  4:39 ` Bart Schaefer
  2014-09-12  8:42   ` Dominik Vogt
@ 2014-09-12  8:51   ` Peter Stephenson
  1 sibling, 0 replies; 13+ messages in thread
From: Peter Stephenson @ 2014-09-12  8:51 UTC (permalink / raw)
  To: Zsh Users

On Thu, 11 Sep 2014 21:39:01 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> } As an alternative, is there a direct way to print out a "long"
> } integer value as binary bytes in host byte order?
> 
> There's no guarantee that zsh's integer type is "long", so no, there
> is not.

In fact the shell goes to some lengths to find a 64-bit type to use for
arithmetic even on 32-bit architectures.  So tests on the range may well
be telling you about "long long".

pws


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

* Re: Determining the length of "long"?
  2014-09-12  8:42   ` Dominik Vogt
@ 2014-09-12 13:17     ` Kurtis Rader
  2014-09-12 23:16     ` Bart Schaefer
  1 sibling, 0 replies; 13+ messages in thread
From: Kurtis Rader @ 2014-09-12 13:17 UTC (permalink / raw)
  To: vogt, Zsh Users

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

Sorry, but I disagree. Zsh is absolutely the wrong tool for this task
unless you're striving for an unmaintainable, obfuscated, brittle script.
Please ask your peers, preferably including someone in the Linux level
three support org (where I used to work at IBM), for feedback on your idea.

P.S.., I would only use perl if there wasn't a better option. But perl is
preferable to zsh for this task and python is even better.

On Fri, Sep 12, 2014 at 1:42 AM, Dominik Vogt <vogt@linux.vnet.ibm.com>
wrote:

> On Thu, Sep 11, 2014 at 07:58:29PM -0700, Kurtis Rader wrote:
> > There may be a way but why? A command shell is the wrong tool for
> > that task.
>
> To give you a bit of background:  The script is an fvwm module,
> and apart from the need of sending two longs to the window manager
> core in binary format, the shell is absolutely the right tool here
> (combine several unix command line programs in a pipe, filter their
> output and generate a wm command from that).
>
> > You don't need to compile a C program to do this. If you have perl or
> > python it's an almost trivial problem.
>
> I know, but I never do something in perl if it can be done in zsh.
>
> On Thu, Sep 11, 2014 at 09:39:01PM -0700, Bart Schaefer wrote:
> > if (( ${#:-"$(( [#2] (1<<31)))"} > ${#:-"$(( [#2] (1<<63)))"} ))
> > then print "zsh integer type is 32 bits"
> > elif (( ${#:-"$(( [#2] (1<<63)))"} > ${#:-"$(( [#2] (1<<64)))"} ))
> > then print "zsh integer type is 64 bits"
> > else print "zsh integer type is more than 64 bits"
> > fi
>
> Hm, I'm not really sure that works reliably because the shift
> amount may be truncated before it is used.  I.e. on s390 "1 << 32"
> and "1 << 64" and "1 << 0" are all the same.  Luckily I don't need
> that on s390.
>
> > There's no guarantee that zsh's integer type is "long", so no, there
> > is not.
>
> If long is not guaranteed, how does zsh determine which integer
> type it uses in arithmetic?  Would it use long long if a long is
> four bytes and long long is available?
>
> Is it possible to print pointers or memory contents in zsh?
>
> > setopt C_BASES
> > integer i=0x12345
> > while (( i )) {
> >   printf '\\\\x%x\n' $(( [#16] (i & 0xff) ))
> >   (( i = i >> 8 ))
> > }
>
> Actually the amount I have to print is just a byte, but with
> three or seven null bytes before or after it, so all I really
> need to know is the host byte order to pick the right variant.
> But that is only a bonus for now.
>
> Ciao
>
> Dominik ^_^  ^_^
>
> --
>
> Dominik Vogt
> IBM Germany
>
>


-- 
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

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

* Re: Determining the length of "long"?
  2014-09-11 21:36 Determining the length of "long"? Dominik Vogt
  2014-09-12  2:58 ` Kurtis Rader
  2014-09-12  4:39 ` Bart Schaefer
@ 2014-09-12 16:17 ` Roman Neuhauser
  2014-09-12 17:04   ` Dominik Vogt
  2 siblings, 1 reply; 13+ messages in thread
From: Roman Neuhauser @ 2014-09-12 16:17 UTC (permalink / raw)
  To: Zsh Users

# dominik.vogt@gmx.de / 2014-09-11 22:36:08 +0100:
> Is there a way to determine the length of the C type long from
> inside a zsh script (without using external programs, of course).
> 
> As an alternative, is there a direct way to print out a "long"
> integer value as binary bytes in host byte order?
> 
> I.e. given a value, say 0x12345, I need to print that as
> 
>   \\x00\\x01\\x23\\x45
> 
> on a 32 bit platform, and as
> 
>   \\x00\\x00\\x00\\x00\\x00\\x01\\x23\\x45
> 
> on a 64 bit platform (possibly in reverse byte order, depending on
> the hardware).

see getconf(1)[0] and unistd.h(0P)[1], specifically
_POSIX_V6_ILP32_OFF32 and its brethren.

[0]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html
[1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html

-- 
roman


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

* Re: Determining the length of "long"?
  2014-09-12 16:17 ` Roman Neuhauser
@ 2014-09-12 17:04   ` Dominik Vogt
  2014-09-12 18:10     ` Roman Neuhauser
  0 siblings, 1 reply; 13+ messages in thread
From: Dominik Vogt @ 2014-09-12 17:04 UTC (permalink / raw)
  To: zsh-users

> see getconf(1)[0] and unistd.h(0P)[1], specifically
> _POSIX_V6_ILP32_OFF32 and its brethren.
> 
> [0]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getconf.html
> [1]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html

Ah great, that pointed exactly to what I need.

  $ getconf LONG_BIT

is exactly what I need (ignoring the byte order problem for now).

Thanks a lot

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt


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

* Re: Determining the length of "long"?
  2014-09-12 17:04   ` Dominik Vogt
@ 2014-09-12 18:10     ` Roman Neuhauser
  2014-09-12 18:50       ` Dominik Vogt
  0 siblings, 1 reply; 13+ messages in thread
From: Roman Neuhauser @ 2014-09-12 18:10 UTC (permalink / raw)
  To: Dominik Vogt; +Cc: zsh-users

# dominik.vogt@gmx.de / 2014-09-12 19:04:44 +0200:
> > see getconf(1)[0] and unistd.h(0P)[1], specifically
> > _POSIX_V6_ILP32_OFF32 and its brethren.
> 
> Ah great, that pointed exactly to what I need.

glad to be of help!  i would have brought these up earlier but you said

> inside a zsh script (without using external programs, of course).

which seemed to disqualify getconf(1)...  the clarification was also
very subtle: :)

> the shell is absolutely the right tool here (combine several unix
> command line programs in a pipe, filter their output and generate
> a wm command from that)

overall a good reminder of the need for precise problem statements. :)

-- 
roman


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

* Re: Determining the length of "long"?
  2014-09-12 18:10     ` Roman Neuhauser
@ 2014-09-12 18:50       ` Dominik Vogt
  0 siblings, 0 replies; 13+ messages in thread
From: Dominik Vogt @ 2014-09-12 18:50 UTC (permalink / raw)
  To: zsh-users

On Fri, Sep 12, 2014 at 08:10:19PM +0200, Roman Neuhauser wrote:
> # dominik.vogt@gmx.de / 2014-09-12 19:04:44 +0200:
> > > see getconf(1)[0] and unistd.h(0P)[1], specifically
> > > _POSIX_V6_ILP32_OFF32 and its brethren.
> > 
> > Ah great, that pointed exactly to what I need.
> 
> glad to be of help!  i would have brought these up earlier but you said
> 
> > inside a zsh script (without using external programs, of course).
> 
> which seemed to disqualify getconf(1)...  the clarification was also
> very subtle: :)

I know.  :-)  But I'm not immune to learning when a certain
approach causes more trouble than it saves you.  Actually I didn't
know a simple configuration program was around and wanted to avoid
using a monster like perl or gcc, because latency does matter.

> > the shell is absolutely the right tool here (combine several unix
> > command line programs in a pipe, filter their output and generate
> > a wm command from that)
>
> overall a good reminder of the need for precise problem statements. :)

Yes, but easy to say afterwards when one already know the solution. :)

What the script actually does is:

 * When started by fvwm it is passed an input and an output file
   descriptor to receive and send data from and to the wm core as
   numbers on the command line.  (The direction from fvwm to the
   script is disabled in that case).
 * Then, and that is the new feature, it determines automatically
   if binary longs are 32 bit or 64 bit and chooses a function
   to send strings to fvwm.  (The length of the string is sent as
   a binary long value which is hard coded to 160.)
 * Then it goes into an endless loop and sleeps for a while with
   zselect.  When it wakes up it

    * calls ps to determine the process that uses the most cpu
    * extracts the used memory percentage prom /proc/meminfo
    * uses strftime to get the current time and date in a certain
      format

   All this information is wrapped in wm commands and sent to the
   window manager core which forwards it to another module
   (FvwmButtons) which in turn updates the labels of some buttons
   to these strings.

As I always have a plethora of zshs running anyway, this approach
turned out to be very easy to implement, and does not use much
resources.  In earlier attempts to get this right there was a
noticeable lag, say, when playing kobodeluxe.

Eventually we'll make the fvwm module interface easier to use and
then it won't be necessary to determine details of the machine
architecture anymore.

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt


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

* Re: Determining the length of "long"?
  2014-09-12  8:42   ` Dominik Vogt
  2014-09-12 13:17     ` Kurtis Rader
@ 2014-09-12 23:16     ` Bart Schaefer
  2014-09-12 23:42       ` Dominik Vogt
  1 sibling, 1 reply; 13+ messages in thread
From: Bart Schaefer @ 2014-09-12 23:16 UTC (permalink / raw)
  To: vogt, zsh-users

On Sep 12,  9:42am, Dominik Vogt wrote:
}
} On Thu, Sep 11, 2014 at 09:39:01PM -0700, Bart Schaefer wrote:
} > if (( ${#:-"$(( [#2] (1<<31)))"} > ${#:-"$(( [#2] (1<<63)))"} ))
} > then print "zsh integer type is 32 bits"
} > elif (( ${#:-"$(( [#2] (1<<63)))"} > ${#:-"$(( [#2] (1<<64)))"} ))
} > then print "zsh integer type is 64 bits"
} > else print "zsh integer type is more than 64 bits"
} > fi
} 
} Hm, I'm not really sure that works reliably because the shift
} amount may be truncated before it is used.  I.e. on s390 "1 << 32"
} and "1 << 64" and "1 << 0" are all the same.

That probably means that zsh uses a 32 bit integer type on s390.
There is a reason the shift in my "if" above is 1<<31 not 32.


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

* Re: Determining the length of "long"?
  2014-09-12 23:16     ` Bart Schaefer
@ 2014-09-12 23:42       ` Dominik Vogt
  2014-09-13  0:17         ` Bart Schaefer
  0 siblings, 1 reply; 13+ messages in thread
From: Dominik Vogt @ 2014-09-12 23:42 UTC (permalink / raw)
  To: zsh-users

On Fri, Sep 12, 2014 at 04:16:27PM -0700, Bart Schaefer wrote:
> On Sep 12,  9:42am, Dominik Vogt wrote:
> }
> } On Thu, Sep 11, 2014 at 09:39:01PM -0700, Bart Schaefer wrote:
> } > if (( ${#:-"$(( [#2] (1<<31)))"} > ${#:-"$(( [#2] (1<<63)))"} ))
> } > then print "zsh integer type is 32 bits"
> } > elif (( ${#:-"$(( [#2] (1<<63)))"} > ${#:-"$(( [#2] (1<<64)))"} ))
> } > then print "zsh integer type is 64 bits"
> } > else print "zsh integer type is more than 64 bits"
> } > fi
> } 
> } Hm, I'm not really sure that works reliably because the shift
> } amount may be truncated before it is used.  I.e. on s390 "1 << 32"
> } and "1 << 64" and "1 << 0" are all the same.
> 
> That probably means that zsh uses a 32 bit integer type on s390.
> There is a reason the shift in my "if" above is 1<<31 not 32.

To clarify, on s390 (1 << 31) has the same result as (1 << 63) *if*
the integer type is long (which I doubt, zsh probably uses long
long).  So this is not correct

> } > if (( ${#:-"$(( [#2] (1<<31)))"} > ${#:-"$(( [#2] (1<<63)))"} ))
                                                           ^^^^
                                                             |
                                                     this should be 32

The underlying assumption of the test that shifting an integer
value to the left by its width in bits or more yields zero is
wrong on some platforms.

Anyway, if zsh uses long long when that's available on a 32 bit
platform, the test doesn't tell me anything about long.

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt


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

* Re: Determining the length of "long"?
  2014-09-12 23:42       ` Dominik Vogt
@ 2014-09-13  0:17         ` Bart Schaefer
  0 siblings, 0 replies; 13+ messages in thread
From: Bart Schaefer @ 2014-09-13  0:17 UTC (permalink / raw)
  To: zsh-users

On Sep 13, 12:42am, Dominik Vogt wrote:
} Subject: Re: Determining the length of "long"?
}
} To clarify, on s390 (1 << 31) has the same result as (1 << 63) *if*
} the integer type is long (which I doubt, zsh probably uses long
} long).

Indeed, I wasn't aware (more accurately, forgot) that s390 has those
oddball 31-bit integers.

} The underlying assumption of the test that shifting an integer
} value to the left by its width in bits or more yields zero is
} wrong on some platforms.

That's not the underlying assumption, acctually.  The assumption is
that shifting by (number of bits minus one) will yield a very long
binary number (the ${#:-"..."} in the test: lots of trailing zeroes),
whereas shifting by the number of bits or more yields a number with a 
smaller footprint because multiple leading zeroes are not printed.


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

end of thread, other threads:[~2014-09-13  0:17 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-11 21:36 Determining the length of "long"? Dominik Vogt
2014-09-12  2:58 ` Kurtis Rader
2014-09-12  4:39 ` Bart Schaefer
2014-09-12  8:42   ` Dominik Vogt
2014-09-12 13:17     ` Kurtis Rader
2014-09-12 23:16     ` Bart Schaefer
2014-09-12 23:42       ` Dominik Vogt
2014-09-13  0:17         ` Bart Schaefer
2014-09-12  8:51   ` Peter Stephenson
2014-09-12 16:17 ` Roman Neuhauser
2014-09-12 17:04   ` Dominik Vogt
2014-09-12 18:10     ` Roman Neuhauser
2014-09-12 18:50       ` Dominik Vogt

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).