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