[comp.sys.ibm.pc.digest] Info-IBMPC Digest V6 #53

Info-IBMPC@C.ISI.EDU (Info-IBMPC Digest) (07/31/87)

Info-IBMPC Digest      Thursday, July 30, 1987      Volume 6 : Issue 53

This Week's Editor:  Phyllis O'Neil

Today's Topics:
                   TurboC Bug Replies (7 messages)
                  Re:  MS C Compiler V 4.00 Problem
                   Kaypro --> PC Disks (2 messages)
            8085 to 8086 Assembler Translator (2 messages)
                  Re:  Request for Roundoff Constant

----------------------------------------------------------------------
INFO-IBMPC BBS Phone Numbers: (213)827-2635 (213)827-2515

------------------------------

Date: Thu, 23 Jul 87 12:34:15 edt
From: John P. Nelson <decvax!genrad!panda!teddy!jpn@ucbvax.Berkeley.EDU>
To: ucbvax!C.ISI.EDU!Info-IBMPC
Subject: TurboC Replies	

This is a reply to two queries in Digest #52 about TurboC.  The first
(from J Law), is NOT a TurboC bug, it is a programming error.  The code
in question was:

    {
    double a, b;
    scanf("%g %g", &a, &b);
    ...

The scanf format is incorrect.  %g can only be used with variables of
type "float".  To read a "double" you must modify the format with an
'l' (for long) character.  This is not necessary in printf, where you
pass the floating point value itself, because "float"s are promoted to
"double" when passed as a parameter.  Because you are passing the
ADDRESS of the floating point object, C does not have any way to
promote/demote the size of the number.  So the scanf line SHOULD read:

    scanf("%lg %lg", &a, &b);

			       ---------

The second query, from Esmail Bondakdarian, IS a TurboC bug, and there
is no patch currently available.  The code in question is:

main()
    { float a, b;
    ...
    operate(a,b)
    }

operate(a,b)
float a,b;

Since this program uses old-style function delarations, the floating
point parameters to "operate" are promoted to "double" before the
function call.  This is correct behavior.  The BUG is in the code
generated for the "operate" function.  Again, because an old-style
function declaration is used, the "float" parameters should be
adjusted to be "double" (See K&R Appendix A "External function
definitions").  The confusion is easy to understand, since if the
function was declared using the new-style ANSI format, then a
prototype would be necessary, and the parameter types would REALLY be
"float", not "double".

Until Borland comes up with a fix for this one (don't hold your
breath), the workaround is simple.  Either declare the parameters to
"operate" as "double" (The compiler should be doing this FOR you), or
use new-style function declarations, and insert a function prototype
before "operate" is invoked.

John P. Nelson
   decvax!genrad!teddy!jpn
   seismo!mit-eddie!genrad!teddy!jpn
   ARPA!talcott!panda!teddy!jpn

------------------------------

Date: Thu, 23 Jul 87 11:37:17 PDT
From: rss%ucscf.UCSC.EDU@ucscc.UCSC.EDU (95008000)
To: Info-IBMPC@C.ISI.EDU
Subject: Alleged Turbo C Bugs

Two alleged Turbo C bugs were posted.  They are not bugs.

The message from J. Law noted that scanf can read a float with
"%g" but not a double.  This is correct.  The scanf function has
no way of knowing what type of address you are passing to it
unless you tell it.  You can read a double with "%lg".  All other
C compilers work this way.

The message from Esmail Bonakdarian has to do with function
taking float parameters, as in
         operate( a, b)
         float a, b;
Programs written this way demonstrate an incompatibility between
K&R C and ANSI C.  According to K&R, all function arguments are
doubles.  Compilers allow you to declare an argument float, but
they treat the argument as double.  According to ANSI C, function
arguments can be either float or double.  If a function is called
without an ANSI prototype, then float arguments are coerced to
double.

Bonakdarian's program does indeed work on MS C 4.0, but only because
it is *not* and ANSI-conforming compiler.  It treats function
arguments as double even if they are declared as float.  You can see
this by running a program like:

               foo(x)
               float x;
               {  printf("Type number: ");  scanf("%f",&x);
                       printf(" = %f",x);}

Such a program will work under Turbo C but not MS C.

If you want to write portable C programs using real parameters,
you have two choices.

1. [K&R Style]  Declare all of your function arguments double,
since a K&R compiler will make them all double anyway.

2. [ANSI Style]  Use function prototypes.  Make sure every
function call is preceded by a prototype so the compiler will do
argument checking.  (The Turbo C swith "-w" will enforce this.)

Roger Schlafly
Borland

------------------------------

Date:  Fri, 24 Jul 87 11:49:07 EDT
From:  Peter Allsop (Dept. of Chemical Eng.) <ALLSOP%WATACS.BITNET@wiscvm.wisc.edu>
To:  Info-IBMPC@C.ISI.EDU
Subject:  Re: TurboC "Bug"? Query

PHYJLAW%UOGUELPH asked:

>...  Maybe it's the scanf function which can't handle "double"?

   You're close... scanf can handle double, but only if you tell it
that you are passing it a pointer to a double.  Pointers are always
a (system dependant) fixed length, regardless of what type of variable
they point to (after all, a pointer is just a memory location).  Floats
are always pushed onto the stack as doubles, so printf and the like
don't require any special flags for long variables.  For functions like
scanf, however, you are pushing pointers, so you have to flag them as
long.  Your manual should tell you how to do this under the fscanf
function, but a common way is to prefix the format type with an 'l'.
This would make your scanf line:

         scanf("%lg %lg",&a,&b);


                  Peter Allsop
                  Biochemical Engineering Group
                  Department of Chemical Engineering
                  University of Waterloo

 PS:  You would have to use the 'l' prefix for any long variable.
      A long integer would be read as %ld for example.

------------------------------

Date: Mon, 27 Jul 87 13:56:29 EDT
From: John Owens <john@xanth.cs.odu.edu>
To: INFO-IBMPC@C.ISI.EDU, bonak@cs.uiowa.edu
Subject: Re: (Yet Another) Turbo C Bug?

>          { float a,b;
	...
>            operate(a, b);
>          }
>          
>          operate( a, b)
>          float a, b;

In C, floats are always passed as doubles.  A nice compiler will take
your format parameter declaration of "float" in operate and handle
this situation for you, but apparently Turbo C does not.  You should
declare operate as

         operate( a, b)
         double a, b;

To decide if this is a bug in Turbo C or not, you'll have to check
whatever standard they are claiming for C (probably K&R) to see
whether the conversion back to float (or forcing the variables to
double) in the called routine is required or optional.

John Owens		Old Dominion University - Norfolk, Virginia, USA
john@ODU.EDU		old arpa: john%odu.edu@RELAY.CS.NET
+1 804 440 4529		old uucp: {decuac,harvard,hoptoad,mcnc}!xanth!john

------------------------------

Date: Sun, 26 Jul 87 10:19:15 CDT
From: Esmail Bonakdarian <bonak%cs.uiowa.edu@RELAY.CS.NET>
To: INFO-IBMPC-REQUEST@C.ISI.EDU
Subject: Turbo "Bug" Explanation

i had a similar problem but solved it in the following way. instead of
using %g (or %e) i used %lg (or %le). see the reference guide page
201, it took me a long time to find this information.

the program below works on my machine.

esmail bonakdarian


main()
{ 
   /* same as the original that did not work with the    */
   /* exception that %lg is used in scanf rather than %g */

        double a,b,ratio,prod;
        printf("Enter 2 numbers: ");
        scanf("%lg %lg",&a,&b);
        ratio = a/b ;prod=a*b;
        printf("Ratio is %g  product is %g\n",ratio,prod);
}

------------------------------

Date: Mon, 27 Jul 87 13:11:10 edt
From: neoucom!wtm@seismo.CSS.GOV (Bill Mayhew)
To: info-ibmpc@c.isi.edu
Subject: Turbo C Floating Point Bug

In issue #52, Esmail Bonakdarian points out that Turbo C goofs up
when passing floating point arguments to subroutines.  This is
apparently caused by inadvertant coversion of the parameters to
double before passing the values.  I seem to recall from somewhere
in K&R that if not stated explicitly, that passed parameters are
cast as double or something to that effect.  (My major job function
is *not* C programming, so sorry for any fuzzyness on the above.)
Apparently, tc doesn't completely follow the specification.  For the
moment, the following will produce the desired results:

main()
 
{
float a,b;
 
a = b = 1;
 
printf("Enter two numbers:  ");
scanf("%f %f", &a, &b);
printf("You entered %4.2f %4.2f.\n", a, b);
printf("In main:  %4.2f %4.2f = %4.2f\n", a, b, a*b);
operate(a, b);
}
 
operate(double a, double b)
 
{
printf("In sub:  %4.2f %4.2f = %4.2f\n", a, b, a*b);
}

Running the program:
  C:\TURBOC>mult
  Enter two numbers:  3 4
  You entered 3.00 4.00.
  In main:  3.00 4.00 = 12.00
  In sub:  3.00 4.00 = 12.00

  C:\TURBOC>

Bill Mayhew
Division of Basic Medical Sciences
Northeastern Ohio Universities College of Medicine
Rootstown, OH  44272-9989  USA   phone:  216-325-2511
(wtm@neoucom.UUCP   ...!cbatt!neoucom!wtm)

------------------------------

Date:     Wed, 29 Jul 87  21:07:11 ADT
From:     <REGE210%DAL.BITNET@wiscvm.wisc.edu>
Subject:  More on Turbo C Bugs
To:       <INFO-IBMPC@C.ISI.EDU>

     I have been exploring the recent discussion of bugs
in Turbo C and have discovered several things.
     I tried to patch my version of Turbo C according to
the patches published in V6 #50 of Info-IBMPC and discovered
that the my copy of Turbo C is *not* the same as the one
which the patches apply to.  This became evident when I
did everything correctly and got different original values
while I was supposed to be entering the patch values.  I
didn't change anything.
     This implies that Borland is fixing these bugs *VERY*
rapidly.  As my version number is 1.0, it also seems to
imply that Borland does not consider bug fixes to be
new versions.  This really impresses me as many major
software companies seem to charge a fee for "updates"
which are really bug fixes.  Well done guys!
     The following program was posted here with a question
as to whether or not it was a bug:

main()
{  float a, b;

  a = b = 1;

  printf("Enter two numbers: ");
  scanf("%f %f", &a, &b);
  printf("You entered %4.2f %4.2f.\n", a, b);
  printf("%4.2f * %4.2f = %4.2f\n\n", a, b, a * b);
  operate(a,b);
}

  operate(float a, float b)
  {
   printf("in sub:\n%4.2f * %4.2f = %4.2f", a, b, a * b);
  }

     The output from this program was reported as being
(in part):

                in sub: 0.00 * 2.12 = 0.00

     Sad to say, but I get this as well.  The following program
provides a way to work around this by passing pointers
rather than explicit values:

main()
{
  float a;
  float b;

  a = b = 1;

  printf("Enter two numbers: ");
  scanf("%f %f", &a, &b);
  printf("You entered %4.2f %4.2f.\n", a, b);
  printf("%4.2f * %4.2f = %4.2f\n\n", a, b, a * b);
  operate(&a,&b);
  }
/* Originally, this code received its arguments
   by value, not reference.  It did not work.  Passing
   the arguments by reference instead of value works. */

  operate( float *a, float *b)
  {
   printf("in sub:\n%4.2f * %4.2f = %4.2f", *a, *b, *a * *b);
  }

Does anybody have a fix for this problem?  If so, please
post it ASAP!  Many thanks!

     This program was also reported as a bug:

struct
{
    int   e:15;
} t;

main()
{
   t.e = 0;
   t.e +=1;
   t.e++;
}

     I see nothing wrong with this, and I get a fatal
compiler error (Irreducible Expression Tree) as reported.
     Anybody know of a fix for this one?

     The last problem I saw does not appear to be a bug
but I could be mis-reading my documentation (which is
vague on this point).  This is the program:

main()
{

double a,b,ratio,product;

printf("Enter 2 numbers: ");
scanf("%g %g",&a,&b);
product=a*b;
ratio=a/b;
printf("Ratio is %g  product is %g\n",ratio,product);
}

     It is reported to bomb out with an Underflow error
message at runtime and I got this message the first time
I ran the program.  Further investigation revealed two
problems:

1 - The author was entering 10.0,3.0 at the prompt.
    Notice there is no comma between the specifiers
    in scanf.  If the comma is included in the input
    but left out of the description string passed to
    scanf you *should* get some kind of error message.
    See page 148 of Kernighan and Ritchie.

2 - This is where the documentation (all sources I
    have) gets vague.  If you make no other
    changes than changing %g to %G in scanf and
    enter 10.0 3.0 (not 10.0,3.0) the program
    works correctly.  The Turbo C reference manual
    mentions %G in passing on page 199 but no where
    that I can find does it actually say what %G
    is.  Page 62 of The C Programmer's Handbook
    Published by AT&T Bell Laboratories says that
    f, e, and g are equivalent, but doesn't say
    much about G.  Here is the working program:

#include<stdio.h>
main()
{

/* This program was initially listed as giving an underflow error
   message.  It did this to me the first time I tried it and them
   it changed to a domains error.  I'm not sure why.
   Changing the scanf definition from %g to %G worked however. */

double a,b,ratio,product;
printf("Enter 2 numbers: ");
scanf("%G %G",&a,&b);
product=a*b;
ratio=a/b;
printf("Ratio is %g  product is %g\n",ratio,product);
}

    Does anybody know if the #include<stdio.h> must
be include for reasons other than form?  What about
other include files?
     If anybody else can throw more light on this
please post a message here.  I am just learning C
so maybe a person who is more experienced with C
can provide us with more data.

John Robinson

------------------------------

Date: Thu, 23 Jul 1987  18:40 EDT
From: LENOIL@XX.LCS.MIT.EDU
To:   "Joshua D. Males" <josh%ILJCT.BITNET@WISCVM.WISC.EDU>
Cc:   Info-IBMPC@C.ISI.EDU
Subject: Re:  MS C Compiler V 4.00 Problem

    ... I started recently to work with the Microsoft C compiler V 4.00,
    but, unfortunately, when I tried to use the library function "printf",
    the linker (MS V 3.05) claimed that "printf" is an invalid object code.
    the same error was encountered when I tried to compile with the /Zi option,
    even for the minimal program: main(){}...

    Could you help me find out what is the problem?

----- 
You were using an older version of LINK, perhaps one that came with
DOS or another MS language product.  C 4.0 comes with LINK version
3.51; use it.

------------------------------

Date: Thu, 23 Jul 87 10:49:16 EDT
From: Jim.Moore@WB1.CS.CMU.EDU
To: rbw@cs.williams.edu
Subject: Kaypro --> PC Disks
Cc: info-ibmpc@c.isi.edu, jm6m@andrew

I use Media Master, and it works just fine.

There is one problem, however.  In the case of kaypro 4/10 disks, it seems as 
though MM can't handle disks FORMATTED ON THE KAYPRO.  However, if you format 
them with MM (for the K-10/4), then both machines can use them just fine.

Good Luck.

Jim Moore
(IBM Artificial Intelligence Liaison for Carnegie Mellon University)

	
------------------------------

Date: Fri, 24 Jul 87 08:05:45 edt
From: jkerby@nswc-wo.ARPA
To: rbw@cs.williams.edu
Subject:  Re: Kaypro -> PC Transfer
Cc: info-ibmpc@c.isi.edu

In response to your request for a program to read floppies from a Kaypro
CP/M machine and convert them to PC format, I would suggest "Media Master"
from Intersecting Concepts, Inc.  The last address I have is 

	4573 Heatherglen Ct.
	Moorpark, CA 93021
	(805) 529-5073

It's about a year old but may still be good.  I have used the program on a
Zenith 158 and a Zenith 248 successfully.  It supports SEVERAL formats and
is relatively cheap (~$40).  Hope this helps.

	Fred Kerby (jkerby@nswc-wo.arpa)

------------------------------

Date: Thu 23 Jul 87 17:17:43-PDT
From: Bob Knight <KNIGHT@SRI-NIC.ARPA>
Subject: 8085 to 8086 Assembler Translator Needed
To: info-ibmpc@C.ISI.EDU, info-micro@BRL-VGR.ARPA

Anyone know of one available on the net?  I'm in desperate need of
one.  Please reply to this accounts.

Thanks in advance,
Bob

------------------------------

Date: Fri 24 Jul 87 10:29:11-EDT
From: Gern <GUBBINS@RADC-TOPS20.ARPA>
Subject: Re: 8085 to 8086 Assembler Translator?
To: KNIGHT@SRI-NIC.ARPA
cc: info-ibmpc@C.ISI.EDU, info-micro@BRL-VGR.ARPA

Yes, I believe I have a PD one, written (I believe) at Clarkson
by a student.  It is in Zenith Z-100 ZBASIC which should run directly
under IBMPC GWBASIC (BASICA).  I have never tried it.   If you want
it, flag me and I will upload it.

Cheers,
Gern

------------------------------

Date:  Fri, 24 Jul 87 11:48:14 EDT
From: Peter Allsop <ALLSOP%WATACS.BITNET@wiscvm.wisc.edu>
To:  Info-IBMPC@C.ISI.EDU
Subject:  Re:  Request for Roundoff Constant

  Gloria Wren <wren@BRL.MIL> asked:

>I need to set a machine round-off constant for a public domain code
>called Episode from Lawrence Livermore Lab.  The code is the older
>version of what is today known as DGEAR, an ODE integrator...
>Does anyone
>know the correct value for an IBM-AT or any way to determine it since
>neither value above works? ...

   Based on the value of UROUND quoted for an IBM-360/70, the
technical term for the number you are after is the 'Machine Epsilon'
(Em), sometimes called the Machine Precision.  It is defined as the
smallest number which you can add to X and get a number not equal to
X.  It is related in a complex way to the format used by the computer
when it stores numbers, and should really be calculated based on this
representation.  You can get an approximate value using the following
program (in fortran, which I assume you are using):
                                                                        EM 00010
      IMPLICIT REAL*4 (A-H,O-Z)                                         EM 00020
      X = 1                                                             EM 00040
      IX = 1                                                            EM 00050
      DO 1000 I=1,1000                                                  EM 00060
         IX = IX*2                                                      EM 00070
         DX = 1./IX                                                     EM 00080
         DX = X + DX                                                    EM 00090
         IF(DX.EQ.X)GOTO 2000                                           EM 00100
 1000    CONTINUE                                                       EM 00110
      WRITE(6,1100)                                                     EM 00120
 1100 FORMAT(' Loop terminated by counter')                             EM 00130
      STOP                                                              EM 00140
C                                                                       EM 00150
 2000 IX = IX/2                                                         EM 00160
      DX = 1./IX                                                        EM 00170
      WRITE(6,2100)IX,DX                                                EM 00180
 2100 FORMAT(' Em = 1/',I10,' = ',1PD10.3)                              EM 00190
      STOP                                                              EM 00210
      END                                                               EM 00220

   A few comments:

   - The use of integers vs reals in the above is quite intentional, as
     is the use of an iterative multiply rather than power.

   - The 80287 has several methods of rounding available.  You should
     treat the value of Em from the above as a limiting lower limit.
     Your DGEAR-like program may run better with a slightly larger value

   - Of course Em changes with the precision used (REAL*8 vs REAL*4)
     and the hardware (with vs without 80287).  The value cited for an
     IBM-360/370 is for single precision (REAL*4), so if the program
     you are converting is all double precision you know that they
     are really after a limiting case.  This is not uncommon.

   - My reference on this sort of stuff is:
     'Numerical Methods, Software and Analysis - IMLS Reference Edition'
      by John R. Rice
      (McGraw-Hill, Toronto; 1983)
      - see chapter 3

                  Peter Allsop
                  Biochemical Engineering Group
                  Department of Chemical Engineering
                  University of Waterloo

------------------------------

End of Info-IBMPC Digest
************************

-------