Bug 170258

Summary: gawk compl function does not work
Product: Red Hat Enterprise Linux 4 Reporter: Tony McConnell <tony.mcconnell>
Component: gawkAssignee: Karel Zak <kzak>
Status: CLOSED WONTFIX QA Contact: Brock Organ <borgan>
Severity: medium Docs Contact:
Priority: medium    
Version: 4.0   
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2005-10-11 08:02:25 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Tony McConnell 2005-10-10 10:01:28 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7

Description of problem:
Output of the following command:

    gawk '{printf("compl = %08x\n", compl(0xFFFF0000));}'

gives

    compl = ffffffff00010000

which is wrong. Should be 0000ffff


Version-Release number of selected component (if applicable):

gawk-3.1.3-10.1

How reproducible:
Always

Steps to Reproduce:
1. Type in gawk command using compl()
2. Run gawk command
3. Observe result.
  

Actual Results:  gawk output is incorrect

Expected Results:  the correct complement should have been returned

Additional info:


Normal bugfix for you, but since our system uses it since Redhat 9.0, and it's now broken in RHEL4.0 - we think this is quite serious.

Comment 1 Tony McConnell 2005-10-10 10:15:07 UTC
Performing a compl(0xFFFFFFFFFFFF0000) actually returns the correct result

Comment 2 Karel Zak 2005-10-10 12:16:44 UTC
Yes, it's unpleasant bug. Thanks from report.

Comment 3 Tony McConnell 2005-10-10 14:47:27 UTC
'info' page of gawk (on RHEL 4) gives the following program:

     function bits2str(bits,        data, mask)
     {
         if (bits == 0)
             return "0"

         mask = 1
         for (; bits != 0; bits = rshift(bits, 1))
             data = (and(bits, mask) ? "1" : "0") data

         while ((length(data) % 8) != 0)
             data = "0" data

         return data
     }


     BEGIN {
         printf "123 = %s\n", bits2str(123)
         printf "0123 = %s\n", bits2str(0123)
         printf "0x99 = %s\n", bits2str(0x99)
         comp = compl(0x99)
         printf "compl(0x99) = %#x = %s\n", comp, bits2str(comp)
         shift = lshift(0x99, 2)
         printf "lshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift)
         shift = rshift(0x99, 2)
         printf "rshift(0x99, 2) = %#x = %s\n", shift, bits2str(shift)
     }

and says the output should be :

     $ gawk -f testbits.awk
     -| 123 = 01111011
     -| 0123 = 01010011
     -| 0x99 = 10011001
     -| compl(0x99) = 0xffffff66 = 11111111111111111111111101100110
     -| lshift(0x99, 2) = 0x264 = 0000001001100100
     -| rshift(0x99, 2) = 0x26 = 00100110

On RH9 it is, on RHEL 4.0 its:

    123 = 01111011
    0123 = 01010011
    0x99 = 10011001
    compl(0x99) = 0x0 = 00000000
    lshift(0x99, 2) = 0x264 = 0000001001100100
    rshift(0x99, 2) = 0x26 = 00100110

So info page doesn't expect it to behave as it does.

Thanks

Comment 4 Karel Zak 2005-10-10 17:12:44 UTC
Possible woraround:
     xor(0xFFFF0000,lshift(1,32)-1))

Comment 5 Karel Zak 2005-10-10 20:04:08 UTC
It seems that there is not any good solution :-(

Cut & past from my discussion with upstream developers:

On Mon, Oct 10, 2005 at 07:27:29PM +0200, Karel Zak wrote:
> On Mon, 2005-10-10 at 09:29 -0400, Andrew J. Schorr wrote:
> > On Mon, Oct 10, 2005 at 02:19:49PM +0200, Karel Zak wrote:
> > > $ gawk 'BEGIN {printf("%#x\n", compl(0xFFFF0000)) }'
> > > 0x1fffff0000ffff
> > > 
> > > I see same output for 3.1.5, 3.1.4 and 3.1.3. It seems that version
> > > 3.1.2 returns correct output (it means 0xffff).
> > 
> > Actually, the code seems to be working correctly.  Your code
> 
> From my point of view it's regression between version 3.1.2 and >=3.1.3.
> It means the code (or docs) is incorrect :-)

Well, the documentation on the bitwise functions says the following:

   http://www.gnu.org/software/gawk/manual/html_node/Bitwise-Functions.html

   For all of these functions, first the double-precision
   floating-point value is converted to the widest C unsigned integer
   type, then the bitwise operation is performed and then the result is
   converted back into a C `double'. (If you don't understand this
   paragraph, don't worry about it.)

An older version of the documentation (from 3.1.0) said the following:

   For all of these functions, first the double-precision floating-point value
   is converted to a C unsigned long, then the bitwise operation is performed
   and then the result is converted back into a C double. (If you don't
   understand this paragraph, don't worry about it.)

So there was a clear change of language from "C unsigned long" to "the widest C
unsigned integer type".  And the code was patched to start using uintmax_t for
the calculations instead of u_long.  I think this was done for good reasons:
there are other situations where the old u_long behavior is not good.  The
patch seems to have initially come up here:

   http://sources.redhat.com/ml/bug-gnu-utils/2003-03/msg00251.html

I agree the documentation is not terribly clear, and it's perhaps a mistake
to encourage people to ignore the paragraph, particularly with respect to the
compl() function.

I'm not sure what the proper solution is here, but it seems to me that
the documentation is OK (not great), and the code works as described
in the docs.  Perhaps some kind of warning message would be helpful.
What do you suggest?  I doubt that reverting to the old behavior is
an option...

Comment 6 Tony McConnell 2005-10-10 22:53:09 UTC
Hmm, the "documentation is OK" stretches the definition of "OK" pretty thin ... ;)

Much of the time, developers will scan documentation and leap upon an example as
a better description of how to use a function - certainly, the example in the
'info'  page ought to be corrected to reflect the true behaviour of compl().

I can change the stuff that uses compl() to use the xor(val, lshift(1,32)-1)
technique instead, but we ought to push for a more explicit definition of
compl() semantics.

Most people would expect it to behave like C "~" bitwise negation :P

Thank you for your help on this :)