[unix-pc.general] 3B1 C runtime library bug; do you have it too?

thad@cup.portal.com (Thad P Floryan) (01/04/91)

Incredible as it may seem, I believe I've actually found a bug in the 3B1's
C library.  Discovered this while porting something really neat to the 3B1,
so I checked it out on 4 other systems (Amiga w/Manx C and w/Lattice/SAS C,
VAX/VMS C 3.1, and HP-UX V7's C) which all produce the correct:

		01.230
		 1.230

All 3B1 systems I have here (with 3.5 & 3.5 dev. set and 3.51m w/3.51 dev set)
produce the (incorrect) results:

		*.*f
		 1.230

On the off-chance I may have somehow screwed (or not updated (how?)) my C
runtime libraries or they got clobbered by some "random" install script for
some other package(s), would you please try this program on your system and
see if you get the correct results?

What the two "*" mean (in C) is that the precision and scaling values will be
supplied by the (correctly positioned) "int" arguments listed just prior to
the floating point value to be displayed in the printf().

Of course I can "work around" this, but I'd like to know if it's necessary to
do so (i.e. are only my libraries screwed or are everyone's screwed).

Here's the test program.  The problem occurs (on my systems) either with or
without the shared libs and with or without optimization and with cc or gcc.

main()
{
	int p = 3;
	double frac = 1.23;

	printf ("%0*.*f\n", p+3, p, frac);
	printf ("%*.*f\n",  p+3, p, frac);
}

Thad Floryan  [ thad@cup.portal.com (OR) ..!sun!portal!cup.portal.com!thad ]

marz@cbnewsm.att.com (martin.zam) (01/04/91)

In article <37567@cup.portal.com>, thad@cup.portal.com (Thad P Floryan) writes:
> Incredible as it may seem, I believe I've actually found a bug in the 3B1's
> C library.  Discovered this while porting something really neat to the 3B1,
> so I checked it out on 4 other systems (Amiga w/Manx C and w/Lattice/SAS C,
> VAX/VMS C 3.1, and HP-UX V7's C) which all produce the correct:
> 
> 		01.230
> 		 1.230
> 
> All 3B1 systems I have here (with 3.5 & 3.5 dev. set and 3.51m w/3.51 dev set)
> produce the (incorrect) results:
> 
> 		*.*f
> 		 1.230
> 
> Thad Floryan  [ thad@cup.portal.com (OR) ..!sun!portal!cup.portal.com!thad ]


I've got it too ...
	3.51m system with 3.51 Dev set.
 
 		*.*f
 		 1.230
 
						Martin Zam
						(201)564-2554

dave@das13.snide.com (Dave Snyder) (01/05/91)

In article <37567@cup.portal.com>, thad@cup.portal.com (Thad P Floryan) writes:
> Incredible as it may seem, I believe I've actually found a bug in the 3B1's
> C library.
> 
> On the off-chance I may have somehow screwed (or not updated (how?)) my C
> runtime libraries or they got clobbered by some "random" install script for
> some other package(s), would you please try this program on your system and
> see if you get the correct results?
> 
You did not whack your libraries Thad, before I discovered "the net" I was
foolish enough to call the AT&T hotline and pay $120 an hour to have a
technician tell me, "Yep, your right, it is a bug", for the exact same type
of problem you describe (I know, I was stupid, $120 an hour).  To top that
off... the tech then told me, "We can't do anything because that machine and
it's software are no longer supported".  Anyway my solution was to grab a PD
version of printf and use it only when I needed the *.*f, *.*d, etc
capabilities.

DAS
-- 
David A. Snyder @ Snide Inc. - Folcroft, PA

UUCP:  ..!uunet!trac2000!das13!dave     INTERNET:  dave@das13.snide.com

john@chance.UUCP (John R. MacMillan) (01/05/91)

|All 3B1 systems I have here (with 3.5 & 3.5 dev. set and 3.51m w/3.51 dev set)
|produce the (incorrect) results:
|
|		*.*f
|		 1.230

I'm not convinced these are incorrect results...

|main()
|{
|	int p = 3;
|	double frac = 1.23;
|
|	printf ("%0*.*f\n", p+3, p, frac);
                  ^
|	printf ("%*.*f\n",  p+3, p, frac);
|}

The printf(3) man page says the spec is "...the character %...zero
or more flags...an optional decimal digit specifying minimum field
width...a period followed by a decimal digit", and "a field width or
precision may be indicated by an asterisk instead of a digit string"

Now the '0' after the '%' above is not one of the listed flag chars,
but the '*' is only acceptable *instead of* a field width.  So I'd
say that by the 3.51 man page I have, the specification is illegal.

Am I missing something?
-- 
John R. MacMillan       | I wish I had a nickname like Crusher, Snake or Dennis
john@chance.UUCP        | Because guys with nicknames always get the gal.
...!scocan!chance!john  |       -- barenaked ladies

bruce@balilly.UUCP (Bruce Lilly) (01/06/91)

In article <37567@cup.portal.com> thad@cup.portal.com (Thad P Floryan) writes:
>
>All 3B1 systems I have here (with 3.5 & 3.5 dev. set and 3.51m w/3.51 dev set)
>produce the (incorrect) results:
>
>		*.*f
>		 1.230
>	printf ("%0*.*f\n", p+3, p, frac);
>	printf ("%*.*f\n",  p+3, p, frac);


It's not clear that this is, in fact, ``incorrect.''  From the printf(3S)
man page:

``A field width or precision or both may be indicated by an asterisk (*)
instead of a digit string.''
^^^^^^^^^^  N.B. it doesn't say ``in addition to.''

If you really need the '0' (to pad on the left with zeros), I suggest
generating a format string using sprintf, e.g.

char	fmt[30]; /* set size to taste */

...

sprintf(fmt, "%%0%d.%df\n", p+3, p)
printf(fmt, frac);

...

If the "%0*.*f" happens to do want you want on other systems, that doesn't
mean that that (unspecified) behaviour is ``standard.''

Good luck with your project.
--
	Bruce Lilly		blilly!balilly!bruce@sonyd1.Broadcast.Sony.COM

thad@cup.portal.com (Thad P Floryan) (01/06/91)

bruce@balilly.UUCP (Bruce Lilly) in <1991Jan5.174829.18682@blilly.UUCP> writes:

	[...]
	If the "%0*.*f" happens to do want you want on other systems, that
	doesn't mean that that (unspecified) behaviour is ``standard.''

Thanks for posting that "workaround" for the benefit of those to whom it might
not have been obvious!

My "problem" was that I've been using K&R (both editions) and H&S (both eds.)
for so long that I just "assumed" the "0" would work with the 3B1's doprnt().

I picked up the BSD doprnt() stuff and will see if IT works; if it does, I'll
post all the stuff required to fix one's libc.a, shlib and shlib.ifile since
I really don't like workarounds that are only needed for one system.

On the off-chance that others are interested, the program I'm porting is the
ephemeris program (from a Sun) since "astronomy" (in the general sense) is one
of my hobbies.  I already have it working perfectly (in terms of all the math)
calculating observational data for all the planets, moon, and other objects,
and just need to adapt the displays to the 3B1's bitmap.

Some of the calcs are simply humongous.  In fact, even during compilation,
gcc exhausted ALL my swap space on one system and, to my surprise, the kernel
started killing off "random" processes to free up space ... this action by the
kernel was NOT appreciated, but at least it put up the error icon "[!!]" and
told me what it did, and I was able to restart various daemons, etc.

For HEAVY software development on the 3B1, it's now clear (to me) that MORE
than 5MB swap space is needed.  Sigh, now gotta offload, repartition for more
swap (I'm going to 4 x RAM size), then reload all the files.

Does anyone have any "rules of thumb" for selecting a good swap partition size?
I'm presently using 5MB on all systems, and am contemplating 12-16MB.  And,
yes, I *know* I should use "mapmem" to monitor swap usage, but when that
thought occurs it's already too late.  Such is life!  :-)

Thad Floryan [ thad@cup.portal.com (OR) ..!sun!portal!cup.portal.com!thad ]

floyd@ims.alaska.edu (Floyd Davidson) (01/07/91)

In article <37645@cup.portal.com> thad@cup.portal.com (Thad P Floryan) writes:

>For HEAVY software development on the 3B1, it's now clear (to me) that MORE
>than 5MB swap space is needed.  Sigh, now gotta offload, repartition for more
>swap (I'm going to 4 x RAM size), then reload all the files.
>
>Does anyone have any "rules of thumb" for selecting a good swap partition size?
>I'm presently using 5MB on all systems, and am contemplating 12-16MB.  And,
>yes, I *know* I should use "mapmem" to monitor swap usage, but when that
>thought occurs it's already too late.  Such is life!  :-)
>
>Thad Floryan [ thad@cup.portal.com (OR) ..!sun!portal!cup.portal.com!thad ]

I use a very hacked version of Lenny's sysinfo program that, amoung
other things, displays free swap space.  It also goes to inverse video
for the display of any parameter that goes beyond a set of limits.

Right now I've got 7Mb of swap space.  It has never actually been
overrun to the point you describe, but it got so close a couple times
that it gave me a bad scare.

Unless one does crazy things, I'd guess 7Mb is enough.  Anyone who
likes to start three compiles going before dinner should think about
8-10 Mb.

I'm about to replace one of my two 70Mb drives with an XT1140 and
at the top of my list are more swap, more /tmp, and more /usr/tmp.
Maybe 10Mb each for the first two and 6Mb for /usr/tmp.  That
appears to be safe for just about anything, but it is dependent
on having a lot of disk space to start with.

Floyd

-- 
Floyd L. Davidson                                  floyd@ims.alaska.edu
Salcha, AK 99714                    paycheck connection to Alascom, Inc.
 When I speak for them, one of us will be *out* of business in a hurry.

thad@cup.portal.com (Thad P Floryan) (01/07/91)

john@chance.UUCP (John R. MacMillan) in <1991Jan5.152216.18838@chance.UUCP>
writes:

	|	printf ("%0*.*f\n", p+3, p, frac);
	                  ^
	The printf(3) man page says the spec is "...the character %...zero
	or more flags...an optional decimal digit specifying minimum field
	width...a period followed by a decimal digit", and "a field width or
	precision may be indicated by an asterisk instead of a digit string"

	Now the '0' after the '%' above is not one of the listed flag chars,
	but the '*' is only acceptable *instead of* a field width.  So I'd
	say that by the 3.51 man page I have, the specification is illegal.

	Am I missing something?

Nope.  I read the 3.51m "man" page and interpret it the same way as you.  As
mentioned in a prior posting, I've been using the K&R ("The C Programming
Language", Kernighan & Ritchie)) and the H&S ("C: A Reference Manual", Harbison
and Steele) for so long that I've come to take certain things for granted.

It's clear the 3B1's C library is simply obsolete.  Every other compiler's
runtime I've used (on other systems, even those dated prior to 3.51's 1987
date) do perform per the K&R and H&S specs.

I'm going to be "looking into" a replacement for the pertinent functions as
mentioned in the just-prior posting.

Thad Floryan [ thad@cup.portal.com (OR) ..!sun!portal!cup.portal.com!thad ]

jon@jonlab.UUCP (Jon H. LaBadie) (01/08/91)

In article <37567@cup.portal.com>, thad@cup.portal.com (Thad P Floryan) writes:

[ Bulk of article reporting erroneous results with printf specifiers

	%06.3f   and   %0*.*f

  is deleted ]

Thad reports that the 3B1 printf(3S) does not work as do other (most?)
printf's.  When given a field width begining with a 0, most printf's
will pad with spaces rather than blanks.

However, the Reference Manual supplied with the 3B1 makes no mention
of the use of a 0 in the field width.  Thus, the function is performing
as documented and this can not be considered a "bug".

Aren't semantics wonderful?  Maybe I could get a job at AT&T support ;-)

Jon

-- 
Jon LaBadie
{att, princeton, bcr, attmail!auxnj}!jonlab!jon

thad@cup.portal.com (Thad P Floryan) (01/13/91)

Nothing like more fuel on the fire, eh?

Just when you thought you could resign yourself to never getting leading
zeroes in your printf() output, the 3B1's standard libraries are a bit
inconsistent, producing:

	      1        0000001
	 123456        0123456
	      1        0000001
	7654321        7654321
	      1        0000001
	 162534        0162534
	     1.234       1.234
	 12345.789   12345.789

with the following simple test program.  It now seems there are in fact two
bugs with "f" formats: one where the format is NOT processed at all if there's
a leading zero spec before dynamic field sizing (my original report), and one
where it simply doesn't "do" the leading zero for a more-copacetic format per:

#include <stdio.h>

char *decfmt = "%7d        %07d\n";
char *octfmt = "%7o        %07o\n";
char *hexfmt = "%7x        %07x\n";
char *fltfmt = "%10.3f  %010.3f\n";

#define d1 1
#define d2 123456
#define o1 1
#define o2 07654321
#define h1 1
#define h2 0x162534
#define f1 1.234
#define f2 12345.789

main()
{
	printf(decfmt, d1, d1); printf(decfmt, d2, d2);
	printf(octfmt, o1, o1); printf(octfmt, o2, o2);
	printf(hexfmt, h1, h1); printf(hexfmt, h2, h2);
	printf(fltfmt, f1, f1); printf(fltfmt, f2, f2);
}


Time allowing, I'll be checking-out the BSD format cracker and printer.

Thad Floryan [ thad@cup.portal.com ]