[gnu.gcc.bug] unsigned/double conversions on i386

kupfer@orc.olivetti.com (Mike Kupfer) (12/22/89)

Using gcc 1.36 on a Mach/i386 system, we had problems converting
between unsigned ints and doubles.  In particular, consider the
appended test program ntptest.c, which comes with the Network Time
Protocol code.

Both test3 and test4 fail.  test3 tests conversion of large unsigned
ints to doubles.  It gags because dbl != 2147483649.0 (2**31 + 1).
The hex representation of 2147483649.0 is 0x41e0000000200000.
Unfortunately, gdb says that dbl's value is 0x41e00000001fffe0.

Why is this?  Well, compiling ntptest.c with "-g -S" we see that 
"dbl = ul" generates:

	fildl -4(%ebp)
	addl $-8,%esp
	fstpl (%esp)
	popl %edx
	popl %ecx
	pushl %ecx
	pushl %edx
	fldl (%esp) 
	addl $8,%esp
	ftst
	fstp %st(0)
	fnstsw %ax
	sahf
	jae L12
	pushl %ecx
	pushl %edx
	fldl (%esp) 
	addl $8,%esp
	faddl LC15
	addl $-8,%esp
	fstpl (%esp)
	popl %edx
	popl %ecx
L12:
	movl %edx,-12(%ebp)
	movl %ecx,-8(%ebp)

where LC15 is

LC15:
	.double 0d4.29496729600000000000e+09

So, what's happening is that "ul" is treated as a signed integer and
converted to a double.  If the result is less than zero, a magic
number (2**32, LC15 here) is added to correct the value.  This should
work.  The problem is that the magic number is inaccurately assembled.
gdb shows it with a value of 0x41efffffffffffe0, when it should really
be 0x41f0000000000000.

So, one fix for test3 is a more accurate atof in gas.  Of course, as
long as the compiler is generating magic constants anyway, why not
just generate the appropriate hex constant and be done with it?

Onward to test4.  Here the test is to convert doubles to unsigned
ints, for values that can't be represented as signed ints.  This
conversion is done by the gnulib routine __fixunsdfsi().  The code
that I have for that function is just plain wrong.  For test4, it
tries to convert the double to a signed integer and drops core because
it can't.  In fact, __fixunsdfsi and __fixdfsi have the same code.
So, along with the test program, I've included C versions of
__fixunsdfsi and __fixunsdfdi.  (I've tested the former, but not the
latter.)  I've also included a test that specifically works the
boundaries between signed and unsigned integers.

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# 
# -rw-r--r--  1 kupfer        128 Dec 21 16:43 Makefile
# 
# -r--r--r--  1 kupfer        627 Dec 21 16:41 _fixunsdfdi.c
# 
# -r--r--r--  1 kupfer       1513 Dec 21 16:41 _fixunsdfsi.c
# 
# -rw-r--r--  1 kupfer        292 Dec 21 16:42 convtest.c
# 
# -rw-r--r--  1 kupfer      12578 Dec 21 16:42 ntp.h
# 
# -rw-r--r--  1 kupfer       5880 Dec 21 16:42 ntpsubs.c
# 
# -rw-r--r--  1 kupfer       4384 Dec 21 16:42 ntptest.c
#
echo 'x - Makefile'
if test -f Makefile; then echo 'shar: not overwriting Makefile'; else
sed 's/^X//' << '________This_Is_The_END________' > Makefile
XCFLAGS=-g
X
Xntptest: ntptest.o ntpsubs.o
X	cc -o ntptest ntptest.o ntpsubs.o
X
Xconvtest: convtest.o 
X	cc -o convtest -g convtest.o
________This_Is_The_END________
if test `wc -l < Makefile` -ne 7; then
	echo 'shar: Makefile was damaged during transit (should have been 7 lines)'
fi
fi		; : end of overwriting check
echo 'x - _fixunsdfdi.c'
if test -f _fixunsdfdi.c; then echo 'shar: not overwriting _fixunsdfdi.c'; else
sed 's/^X//' << '________This_Is_The_END________' > _fixunsdfdi.c
X/* **********************************************************************
X File:         fixunsdfdi.c
X Description:  convert double to ??? (runtime support for gcc)
X Author:       Mike Kupfer, Olivetti Research Center
X********************************************************************** */
X
X/* 
X * $Log:	_fixunsdfdi.c,v $
X * Revision 1.1  89/12/21  15:00:15  kupfer
X * Initial revision
X * 
X */
X
Xunsigned int __fixunsdfsi();
Xunion double_di { double d; int i[2]; };
X#define HIGH 1
X#define LOW 0
X
Xdouble
X__fixunsdfdi(arg)
X     double arg;
X{
X  union double_di u;
X  u.i[LOW] = __fixunsdfsi(arg);
X  u.i[HIGH] = 0;
X  return u.d;
X}
________This_Is_The_END________
if test `wc -l < _fixunsdfdi.c` -ne 27; then
	echo 'shar: _fixunsdfdi.c was damaged during transit (should have been 27 lines)'
fi
fi		; : end of overwriting check
echo 'x - _fixunsdfsi.c'
if test -f _fixunsdfsi.c; then echo 'shar: not overwriting _fixunsdfsi.c'; else
sed 's/^X//' << '________This_Is_The_END________' > _fixunsdfsi.c
X/* **********************************************************************
X File:         fixunsdfsi.c
X Description:  convert double to unsigned int (runtime support for gcc)
X Author:       Mike Kupfer, Olivetti Research Center
X********************************************************************** */
X
X/* 
X * $Log:	_fixunsdfsi.c,v $
X * Revision 1.2  89/12/21  16:39:31  kupfer
X * Use constants rather than invoking ldexp.
X * 
X * Revision 1.1  89/12/21  15:00:21  kupfer
X * Initial revision
X * 
X */
X
X/* 
X * This code has a wart, because the '387 does conversions to 
X * integers, but not conversions to unsigned integers.  So, for values 
X * between max(int) and max(unsigned int), we have use a trick.
X */
X
Xdouble ldexp();
Xint __fixdfsi();
Xunion double_di { double d; int i[2]; };
X#define HIGH 1
X#define LOW 0
X
Xunsigned int
X__fixunsdfsi(arg)
X     double arg;
X{
X  union double_di maxint, maxunsigned;
X  unsigned int result;
X
X  maxint.i[HIGH] = 0x41dfffff;		/* ldexp(1.0, 31) - 1.0 */
X  maxint.i[LOW] =  0xffc00000;
X  maxunsigned.i[HIGH] = 0x41efffff;	/* ldexp(1.0, 32) - 1.0 */
X  maxunsigned.i[LOW] =  0xffe00000;
X
X  if (arg <= maxint.d)			/* includes negative values */
X    result = (unsigned int)__fixdfsi(arg);
X  else if (arg > maxunsigned.d)
X    result = __fixdfsi(arg);		/* will cause exception */
X  else 
X    {
X      int onesbit;
X      union double_di my_dbl;
X
X      my_dbl.d = arg;
X      onesbit = my_dbl.i[LOW] & 0x200000;
X      result = __fixdfsi(arg/2) * 2 + (onesbit ? 1 : 0);
X    }
X
X  return result;
X}
________This_Is_The_END________
if test `wc -l < _fixunsdfsi.c` -ne 56; then
	echo 'shar: _fixunsdfsi.c was damaged during transit (should have been 56 lines)'
fi
fi		; : end of overwriting check
echo 'x - convtest.c'
if test -f convtest.c; then echo 'shar: not overwriting convtest.c'; else
sed 's/^X//' << '________This_Is_The_END________' > convtest.c
X#include <stdio.h>
X
Xdouble ldexp();
X
Xmain()
X{
X	double val = ldexp(1.0, 31) - 1.0;
X	printf("0x%x\n", (unsigned int)val);
X	val += 1.0;
X	printf("0x%x\n", (unsigned int)val);
X
X	val = ldexp(1.0, 32) - 1.0;
X	printf("0x%x\n", (unsigned int)val);
X	val += 1.0;
X	printf("0x%x\n", (unsigned int)val);
X}
________This_Is_The_END________
if test `wc -l < convtest.c` -ne 16; then
	echo 'shar: convtest.c was damaged during transit (should have been 16 lines)'
fi
fi		; : end of overwriting check
echo 'x - ntp.h'
if test -f ntp.h; then echo 'shar: not overwriting ntp.h'; else
sed 's/^X//' << '________This_Is_The_END________' > ntp.h
X/* $Source: /usr/users/louie/ntp/RCS/ntp.h,v $ $Revision: 3.4.1.7 $ $Date: 89/05/18 18:22:14 $ */
X
X/*
X *  $Log:	ntp.h,v $
X * Revision 3.4.1.7  89/05/18  18:22:14  louie
X * A few extra diddles in ntp.h for the reference clock feature.
X * 
X * Revision 3.4.1.6  89/05/03  15:11:06  louie
X * Specify default file for drift value and more peer flag definitions to
X * reflect various stages of clock selection critera.
X * 
X * Revision 3.4.1.5  89/04/10  15:55:42  louie
X * Provide default value for number of bits/byte if not defined.  Compute the
X * Window shift mask inside of conditional code on XTAL so we get the correct
X * value if configured without a crystal controled clock (!!)
X * 
X * Revision 3.4.1.4  89/03/31  16:34:50  louie
X * Add bit in flags which allow a peer to be synced to.  Changed a char to a bit
X * field so that it is always signed.
X * 
X * Revision 3.4.1.3  89/03/29  12:26:18  louie
X * Removed some unused #defines.  Replaced MAXSTRATUM with NTP_INFIN per new
X * spec.  The variable 'mode' in the peer structure has been renamed 'hmode'
X * per the new spec.
X * 
X * Revision 3.4.1.2  89/03/22  18:28:18  louie
X * patch3: Use new RCS headers.
X * 
X * Revision 3.4.1.1  89/03/20  00:02:53  louie
X * 1
X * 
X * Revision 3.4  89/03/17  18:37:00  louie
X * Latest test release.
X * 
X * Revision 3.3.1.1  89/03/17  18:23:49  louie
X * Change CLOCK_FACTOR to be a power of 2.
X * 
X * Revision 3.3  89/03/15  14:19:36  louie
X * New baseline for next release.
X * 
X * Revision 3.2.1.2  89/03/15  13:46:52  louie
X * The version number for that particular flavor of ntpd <--> ntpdc interaction
X * is now defined by NTPDC_VERSION.  The packet format for the ntpdc program
X * has changed slightly to improve robustness when dealing with multiple packets
X * of status data.
X * 
X * Revision 3.2.1.1  89/03/09  17:11:24  louie
X * patch1: Updated constants, which were previously in incorrect units.
X * 
X * Revision 3.2  89/03/07  18:21:45  louie
X * New version of UNIX NTP daemon and software based on the 6 March 1989
X * draft of the new NTP protocol specification.  This version doesn't
X * implement authentication, and accepts and send only NTP Version 1
X * packets.
X * 
X * Revision 3.1.1.1  89/02/15  08:54:42  louie
X * *** empty log message ***
X * 
X *
X * Revision 3.1  89/01/30  14:43:07  louie
X * Second UNIX NTP test release.
X * 
X * Revision 3.0  88/12/12  16:01:07  louie
X * Test release of new UNIX NTP software.  This version should conform to the
X * revised NTP protocol specification.
X * 
X */
X
X#ifndef FD_SET
X#define	NFDBITS		32
X#define	FD_SETSIZE	32
X#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
X#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
X#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
X#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
X#endif
X
X#ifndef	NBBY
X#define	NBBY	8	/* number of bits per byte */
X#endif
X
X#define	MAXNETIF	10
X
Xstruct intf {
X	int fd;
X	char *name;
X	struct sockaddr_in sin;
X	struct sockaddr_in bcast;
X	struct sockaddr_in mask;
X	int uses;
X	int if_flags;
X};
Xextern struct intf addrs[];
Xextern int nintf;
X
X/*
X *  Definitions for the masses
X */
X#define	JAN_1970	2208988800	/* 1970 - 1900 in seconds */
X
X/*
X *  Daemon specific (ntpd.c)
X */
X#define	SHIFT_MASK	0xff	/* number of intervals to wait */
X
X#ifndef	WAYTOOBIG
X#define	WAYTOOBIG	1000.0	/* Too many seconds to correct, something is
X				 * really wrong */
X#endif
X
X#ifndef	XTAL
X#define	XTAL	1	/* crystal controlled clock by default */
X#endif
X
X#ifndef	NTPINITFILE
X#define	NTPINITFILE	"/etc/ntp.conf"
X#endif
X#ifndef	NTPDRIFTCOMP
X#define	NTPDRIFTCOMP	"/etc/ntp.drift"
X#endif
X
Xstruct list {
X	struct ntp_peer *head;
X	struct ntp_peer *tail;
X	int members;
X};
X
X#define	STRMCMP(a, cond, b) \
X	(((a) == UNSPECIFIED ? NTP_INFIN+1 : a) cond \
X	 ((b) == UNSPECIFIED ? NTP_INFIN+1 : (b)))
X
X
X/*
X *  Definitions outlined in the NTP spec
X */
X#define	NTP_VERSION	1
X#define	NTP_PORT	123	/* for ref only (see /etc/services) */
X#define	NTP_INFIN	15
X#define	NTP_MAXAGE	86400
X#define	NTP_MAXSKW	0.01	/* seconds */
X#define	NTP_MINDIST	0.02	/* seconds */
X#ifdef	REFCLOCK
X#define	NTP_REFMAXSKW	0.001	/* seconds (for REFCLOCKs) */
X#define	NTP_REFMINDIST	0.001	/* seconds (for REFCLOCKs) */
X#endif
X#define	NTP_MINPOLL	6	/* (64) seconds between messages */
X#define	NTP_MAXPOLL	10	/* (1024) secs to poll */
X#define	NTP_WINDOW	8	/* size of shift register */
X#define	NTP_MAXWGT	8	/* maximum allowable dispersion */
X#define	NTP_MAXLIST	5	/* max size of selection list */
X#define	NTP_MAXSTRA	2	/* max number of strata in selection list */
X#define	X_NTP_CANDIDATES 64	/* number of peers to consider when doing
X				   clock selection */
X#define NTP_SELECT	0.75	/* weight used to compute dispersion */
X
X#define	PEER_MAXDISP	64.0	/* Maximum dispersion  */
X#define	PEER_THRESHOLD	0.5	/* dispersion threshold */
X#define	PEER_FILTER	0.5	/* filter weight */
X
X#if	XTAL == 0
X#define	PEER_SHIFT	4
X#define	NTP_WINDOW_SHIFT_MASK 0x0f
X#else
X#define	PEER_SHIFT	8
X#define	NTP_WINDOW_SHIFT_MASK 0xff
X#endif
X
X
X/*
X *  5.1 Uniform Phase Adjustments
X *  Clock parameters
X */
X#define	CLOCK_UPDATE	8	/* update interval (1<<CLOCK_UPDATE secs) */
X#if	XTAL
X#define	CLOCK_ADJ	2	/* adjustment interval (1<<CLOCK_ADJ secs) */
X#define	CLOCK_PHASE	8	/* phase shift */
X#define	CLOCK_MAX	0.128	/* maximum aperture (milliseconds) */
X#else
X#define	CLOCK_ADJ	0
X#define	CLOCK_PHASE	6	/* phase shift */
X#define	CLOCK_MAX	0.512	/* maximum aperture (milliseconds) */
X#endif
X#define	CLOCK_FREQ	10	/* frequency shift */
X#define	CLOCK_TRACK	8
X#define	CLOCK_COMP	4
X#define	CLOCK_FACTOR	18
X
X/*
X * Structure definitions for NTP fixed point values
X *
X *    0			  1		      2			  3
X *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |			       Integer Part			     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |			       Fraction Part			     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *
X *    0			  1		      2			  3
X *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |		  Integer Part	     |	   Fraction Part	     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X*/
Xstruct l_fixedpt {
X	u_long int_part;
X	u_long fraction;
X};
X
Xstruct s_fixedpt {
X	u_short int_part;
X	u_short fraction;
X};
X
X/*  =================  Table 3.3. Packet Variables   ================= */
X/*
X *    0			  1		      2			  3
X *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |LI | VN  | Mode|	  Stratum    |	    Poll     |	 Precision   |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |			   Synchronizing Distance		     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |			  Synchronizing Dispersion		     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |			Reference Clock Identifier		     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |								     |
X *   |		       Reference Timestamp (64 bits)		     |
X *   |								     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |								     |
X *   |		       Originate Timestamp (64 bits)		     |
X *   |								     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |								     |
X *   |			Receive Timestamp (64 bits)		     |
X *   |								     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X *   |								     |
X *   |			Transmit Timestamp (64 bits)		     |
X *   |								     |
X *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
X*/
Xstruct ntpdata {
X	u_char status;		/* status of local clock and leap info */
X	u_char stratum;		/* Stratum level */
X	u_char ppoll;		/* poll value */
X	int precision:8;
X	struct s_fixedpt distance;
X	struct s_fixedpt dispersion;
X	u_long refid;
X	struct l_fixedpt reftime;
X	struct l_fixedpt org;
X	struct l_fixedpt rec;
X	struct l_fixedpt xmt;
X};
X/*
X *	Leap Second Codes (high order two bits)
X */
X#define	NO_WARNING	0x00	/* no warning */
X#define	PLUS_SEC	0x40	/* add a second (61 seconds) */
X#define	MINUS_SEC	0x80	/* minus a second (59 seconds) */
X#define	ALARM		0xc0	/* alarm condition (clock unsynchronized) */
X
X/*
X *	Clock Status Bits that Encode Version
X */
X#define	NTPVERSION_1	0x08
X#define	VERSIONMASK	0x38
X#define LEAPMASK	0xc0
X#define	MODEMASK	0x07
X
X/*
X *	Code values
X */
X#define	MODE_UNSPEC	0	/* unspecified */
X#define	MODE_SYM_ACT	1	/* symmetric active */
X#define	MODE_SYM_PAS	2	/* symmetric passive */
X#define	MODE_CLIENT	3	/* client */
X#define	MODE_SERVER	4	/* server */
X#define	MODE_BROADCAST	5	/* broadcast */
X#define	MODE_RES1	6	/* reserved */
X#define	MODE_RES2	7	/* reserved */
X
X/*
X *	Stratum Definitions
X */
X#define	UNSPECIFIED	0
X#define	PRIM_REF	1	/* radio clock */
X#define	INFO_QUERY	62	/* **** THIS implementation dependent **** */
X#define	INFO_REPLY	63	/* **** THIS implementation dependent **** */
X
X
X/* =================  table 3.2 Peer Variables	================= */
Xstruct ntp_peer {
X	struct ntp_peer *next, *prev;
X	struct sockaddr_in src;		/* both peer.srcadr and 
X					   peer.srcport */
X	int	flags;			/* local flags */
X#define	PEER_FL_CONFIG		1
X#define	PEER_FL_AUTHENABLE	2
X#define	PEER_FL_SANE		0x0100	/* sane peer */
X#define	PEER_FL_CANDIDATE	0x0200	/* candidate peer */
X#define	PEER_FL_SYNC		0x1000	/* peer can bet sync'd to */
X#define	PEER_FL_BCAST		0x2000	/* broadcast peer */
X#define	PEER_FL_REFCLOCK	0x4000	/* peer is a local reference clock */
X#define	PEER_FL_SELECTED	0x8000	/* actually used by query routine */
X
X	int	sock;			/* index into sockets to derive
X					   peer.dstadr and peer.dstport */
X	u_char	leap;			/* receive */
X	u_char	hmode;			/* receive */
X	u_char	stratum;		/* receive */
X	u_char	ppoll;			/* receive */
X	u_char	hpoll;			/* poll update */
X	short	precision;		/* receive */
X	struct	s_fixedpt distance;	/* receive */
X	struct	s_fixedpt dispersion;	/* receive */
X	u_long	refid;			/* receive */
X	struct	l_fixedpt reftime;	/* receive */
X	struct	l_fixedpt org;		/* receive, clear */
X	struct	l_fixedpt rec;		/* receive, clear */
X	struct	l_fixedpt xmt;		/* transmit, clear */
X	u_long	reach;			/* receive, transmit, clear */
X	u_long	valid;			/* packet, transmit, clear */
X	u_long	timer;			/* receive, transmit, poll update */
X	long	stopwatch;		/* <<local>> for timing */
X	/*
X	 * first order offsets
X	 */
X	struct	filter {
X		short samples;		/* <<local>> */
X		double offset[PEER_SHIFT];
X		double delay[PEER_SHIFT];
X	} filter;			/* filter, clear */
X
X	double	estdelay;		/* filter */
X	double	estoffset;		/* filter */
X	double	estdisp;		/* filter */
X
X	u_long	pkt_sent;		/* <<local>> */
X	u_long 	pkt_rcvd;		/* <<local>> */
X	u_long	pkt_dropped;		/* <<local>> */
X};
X
X/* ================= table 3.1:  System Variables ================= */
X
Xstruct sysdata {			/* procedure */
X	u_char leap;			/* clock update */
X	u_char stratum;			/* clock update */
X	short precision;		/* system */
X	struct s_fixedpt distance;	/* clock update */
X	struct s_fixedpt dispersion;	/* clock update */
X	u_long refid;			/* clock update */
X	struct l_fixedpt reftime;	/* clock update */
X	int hold;			/* clock update */
X	struct ntp_peer *peer;		/* selection */
X	int maxpeers;			/* <<local>> */
X	u_char filler;		/* put here for %&*%$$ SUNs */
X};
X
X#define	NTPDC_VERSION	2
X
X/*
X *  These structures are used to pass information to the ntpdc (control)
X *  program.  They are unique to this implementation and not part of the
X *  NTP specification.
X */
Xstruct clockinfo {
X	u_long net_address;
X	u_long my_address;
X	u_short port;
X	u_short flags;
X	u_long pkt_sent;
X	u_long pkt_rcvd;
X	u_long pkt_dropped;
X	u_long timer;
X	u_char leap;
X	u_char stratum;
X	u_char ppoll;
X	int precision:8;
X
X	u_char hpoll;
X	u_char filler1;
X	u_short reach;
X
X	long	estdisp;			/* scaled by 1000 */
X	long	estdelay;			/* in milliseconds */
X	long	estoffset;			/* in milliseconds */
X	u_long refid;
X	struct l_fixedpt reftime;
X	struct info_filter {
X		short index;
X		short filler;
X		long offset[PEER_SHIFT];	/* in milliseconds */
X		long delay[PEER_SHIFT];		/* in milliseconds */
X	} info_filter;
X};
X
Xstruct ntpinfo {
X	u_char version;
X	u_char type;		/* request type (stratum in ntp packets) */
X	u_char count;		/* number of entries in this packet */
X	u_char seq;		/* sequence number of this packet */
X
X	u_char npkts;		/* total number of packets */
X	u_char peers;
X	u_char fill3;
X	u_char fill4;
X};
X
X
________This_Is_The_END________
if test `wc -l < ntp.h` -ne 413; then
	echo 'shar: ntp.h was damaged during transit (should have been 413 lines)'
fi
fi		; : end of overwriting check
echo 'x - ntpsubs.c'
if test -f ntpsubs.c; then echo 'shar: not overwriting ntpsubs.c'; else
sed 's/^X//' << '________This_Is_The_END________' > ntpsubs.c
X#ifndef	lint
Xstatic char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntpsubs.c,v $ $Revision: 3.4.1.3 $ $Date: 89/05/18 18:33:50 $";
X#endif	lint
X
X/*
X *  $Log:	ntpsubs.c,v $
X * Revision 3.4.1.3  89/05/18  18:33:50  louie
X * Added support few a new type of unsigned long to double compiler brokenness,
X * called GENERIC_UNS_BUG.  If this is defined, then the unsigned long is
X * shifted right one bit, the high-order bit of the result is cleared, then
X * converted to a double.  The double is multiplied by 2.0, and the a 1.0 is
X * optionall added to it if the low order bit of the original unsigned long
X * was set.  Whew!
X * 
X * Revision 3.4.1.2  89/03/29  12:46:02  louie
X * Check for success sending query before trying to listen for answers.  Will 
X * catch case of no server running and an ICMP port unreachable being returned.
X * 
X * Revision 3.4.1.1  89/03/22  18:32:19  louie
X * patch3: Use new RCS headers.
X * 
X * Revision 3.4  89/03/17  18:37:18  louie
X * Latest test release.
X * 
X * Revision 3.3  89/03/15  14:20:03  louie
X * New baseline for next release.
X * 
X * Revision 3.2  89/03/07  18:29:22  louie
X * New version of UNIX NTP daemon based on the 6 March 1989 draft of the new
X * NTP protocol spec.  This module has mostly cosmetic changes.
X * 
X * Revision 3.1.1.1  89/02/15  08:59:27  louie
X * *** empty log message ***
X * 
X * 
X * Revision 3.1  89/01/30  14:43:18  louie
X * Second UNIX NTP test release.
X * 
X * Revision 3.0  88/12/12  15:58:59  louie
X * Test release of new UNIX NTP software.  This version should conform to the
X * revised NTP protocol specification.
X * 
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/time.h>
X#include <sys/uio.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <arpa/inet.h>
X#include <errno.h>
X#include <syslog.h>
X
X#include "ntp.h"
X
Xextern int errno;
X
X#define	TRUE	1
X#define	FALSE	0
X
X/*
X *  The nice thing here is that the quantity is NEVER signed.
X */
Xdouble
Xul_fixed_to_double(t)
X	struct l_fixedpt *t;
X{
X	double a, b;
X#ifdef	GENERIC_UNS_BUG
X	register int i;
X
X	i = ntohl(t->fraction);
X	a = (long)((i >> 1) & 0x7fffffff);
X	a *= 2.0;
X	if (i & 1)
X		a += 1.0;
X	a = a / (4.294967296e9);	/* shift dec point over by 32 bits */
X	i = ntohl(t->int_part);
X	b = (long)((i >> 1) & 0x7fffffff);
X	b *= 2.0;
X	if (i & 1)
X		b += 1.0;
X#else	/* GENERIC_UNS_BUG */
X	a = (unsigned long) ntohl(t->fraction);
X#ifdef	VAX_COMPILER_FLT_BUG
X	if (a < 0.0) a += 4.294967296e9;
X#endif
X	a = a / (4.294967296e9);/* shift dec point over by 32 bits */
X	b = (unsigned long) ntohl(t->int_part);
X#ifdef	VAX_COMPILER_FLT_BUG
X	if (b < 0.0) b += 4.294967296e9;
X#endif
X#endif	/* GENERIC_UNS_BUG */
X	return (a + b);
X}
X
X/*
X *  Here we have to worry about the high order bit being signed
X */
X
X#if	0
Xdouble
Xl_fixed_to_double(t)
X	struct l_fixedpt *t;
X{
X	double a,b;
X
X	if (ntohl(t->int_part) & 0x80000000) {
X		a = ntohl(~t->fraction);
X#ifdef	VAX_COMPILER_FLT_BUG
X		if (a < 0.0) a += 4.294967296e9;
X#endif
X		a = a / (4.294967296e9);
X		b = ntohl(~t->int_part);
X#ifdef	VAX_COMPILER_FLT_BUG
X		if (b < 0.0) b += 4.294967296e9;
X#endif
X		a += b;
X		a = -a;
X	} else {
X		a = ntohl(t->fraction);
X#ifdef	VAX_COMPILER_FLT_BUG
X		if (a < 0.0) a += 4.294967296e9;
X#endif
X		a = a / (4.294967296e9);
X		b = ntohl(t->int_part);
X#ifdef	VAX_COMPILER_FLT_BUG
X		if (b < 0.0) b += 4.294967296e9;
X#endif
X		a += b;
X	}
X	return (a);
X}
X#endif
X
X/*
X *  Here we have to worry about the high order bit being signed
X */
Xdouble
Xs_fixed_to_double(t)
X	struct s_fixedpt *t;
X{
X	double a;
X
X	if (ntohs(t->int_part) & 0x8000) {
X		a = ntohs(~t->fraction & 0xFFFF);
X		a = a / 65536.0;	/* shift dec point over by 16 bits */
X		a +=  ntohs(~t->int_part & 0xFFFF);
X		a = -a;
X	} else {
X		a = ntohs(t->fraction);
X		a = a / 65536.0;	/* shift dec point over by 16 bits */
X		a += ntohs(t->int_part);
X	}
X	return (a);
X}
X
Xvoid
Xdouble_to_l_fixed(t, value)
X	struct l_fixedpt *t;
X	double value;
X{
X	double temp;
X
X	if (value >= (double) 0.0) {
X		t->int_part = value;
X		temp = value - t->int_part;
X		temp *= 4.294967296e9;
X		t->fraction = temp;
X		t->int_part = htonl(t->int_part);
X		t->fraction = htonl(t->fraction);
X	} else {
X		value = -value;
X		t->int_part = value;
X		temp = value - t->int_part;
X		temp *= 4.294967296e9;
X		t->fraction = temp;
X		t->int_part = htonl(~t->int_part);
X		t->fraction = htonl(~t->fraction);
X	}
X}
X
Xvoid
Xdouble_to_s_fixed(t, value)
X	struct s_fixedpt *t;
X	double value;
X{
X	double temp;
X
X	if (value >= (double) 0.0) {
X		t->int_part = value;
X		temp = value - t->int_part;
X		temp *= 65536.0;
X		t->fraction = temp;
X		t->int_part = htons(t->int_part);
X		t->fraction = htons(t->fraction);
X	} else {
X		value = -value;
X		t->int_part = value;
X		temp = value - t->int_part;
X		temp *= 65536.0;
X		t->fraction = temp;
X		t->int_part = htons(~t->int_part);
X		t->fraction = htons(~t->fraction);
X	}
X}
X/*
X	in the sun, trying to assign a float between 2^31 and 2^32
X	results in the value 2^31.  Neither 4.2bsd nor VMS have this
X	problem.  Reported it to Bob O'Brien of SMI
X*/
X#ifdef	SUN_FLT_BUG
Xtstamp(stampp, tvp)
X	struct l_fixedpt *stampp;
X	struct timeval *tvp;
X{
X	int tt;
X	double dd;
X
X	stampp->int_part = ntohl(JAN_1970 + tvp->tv_sec);
X	dd = (float) tvp->tv_usec / 1000000.0;
X	tt = dd * 2147483648.0;
X	stampp->fraction = ntohl((tt << 1));
X}
X#else
Xtstamp(stampp, tvp)
X	struct l_fixedpt *stampp;
X	struct timeval *tvp;
X{
X	stampp->int_part = ntohl((u_long) (JAN_1970 + tvp->tv_sec));
X	stampp->fraction = ntohl((u_long) ((float) tvp->tv_usec * 4294.967295));
X}
X#endif
X
X/*
X * ntoa is similar to inet_ntoa, but cycles through a set of 8 buffers
X * so it can be invoked several times in a function parameter list.
X */
X
Xchar *
Xntoa (in_addr)
Xstruct in_addr in_addr;
X{
X	static int i = 0;
X	static char bufs[8][20];
X	unsigned char *p = (unsigned char *) &in_addr.s_addr;
X
X	i = (i + 1) % (sizeof bufs / sizeof bufs[0]);
X	sprintf (bufs[i], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
X	return bufs[i];
X}
________This_Is_The_END________
if test `wc -l < ntpsubs.c` -ne 253; then
	echo 'shar: ntpsubs.c was damaged during transit (should have been 253 lines)'
fi
fi		; : end of overwriting check
echo 'x - ntptest.c'
if test -f ntptest.c; then echo 'shar: not overwriting ntptest.c'; else
sed 's/^X//' << '________This_Is_The_END________' > ntptest.c
X#ifndef	lint
Xstatic char *RCSid = "$Source: /usr/users/louie/ntp/RCS/test.c,v $ $Revision: 3.4.1.4 $ $Date: 89/05/18 18:37:39 $";
X#endif
X
X/*
X * $Log:	test.c,v $
X * Revision 3.4.1.4  89/05/18  18:37:39  louie
X * Add test for GENERIC_UNS_BUG to test.c
X * 
X * Revision 3.4.1.3  89/04/07  19:10:41  louie
X * Add check for SUN_FLT_BUG problem in test.c
X * 
X * Revision 3.4.1.2  89/03/31  16:39:19  louie
X * Bug fix for VAX_COMPILER_FLT_BUG test, start of test for Sun problem.
X * 
X * Revision 3.4.1.1  89/03/22  18:32:26  louie
X * patch3: Use new RCS headers.
X * 
X * Revision 3.4  89/03/17  18:37:32  louie
X * Latest test release.
X * 
X * Revision 3.3  89/03/15  14:20:16  louie
X * New baseline for next release.
X * 
X * Revision 3.2.1.1  89/03/15  14:11:08  louie
X * Add in kludge for old VAX pcc compiler bug that incorrectly converts unsigned
X * longs to doubles.  This enables the ntest program to run when
X * VAX_COMPILER_FLT_BUG is defined on those systems.
X * 
X * Revision 3.2  89/03/07  18:30:16  louie
X * New version of UNIX NTP daemon based on the 6 March 1989 draft of the new
X * NTP protocol spec.  This module has mostly cosmetic changes.
X * 
X * Revision 3.1.1.1  89/02/15  08:49:34  louie
X * *** empty log message ***
X * 
X * 
X * Revision 3.1  89/01/30  14:43:19  louie
X * Second UNIX NTP test release.
X * 
X * Revision 3.0  88/12/12  16:01:37  louie
X * Test release of new UNIX NTP software.  This version should conform to the
X * revised NTP protocol specification.
X * 
X */
X
X#include <stdio.h>
X#include <sys/param.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netinet/in_systm.h>
X#include <netinet/ip.h>
X#include <netinet/udp.h>
X#include <netdb.h>
X#include <sys/ioctl.h>
X#include <signal.h>
X#include <errno.h>
X#include <syslog.h>
X
X#include "ntp.h"
X
X#define	TRUE	1
X#define	FALSE	0
X
Xint test1(), test2(), test3(), test4();
X
Xdouble value[8] = {5.1, -5.1, 1.5, -1.5, 0.5, -0.5, -0.05, 0.0};
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	if (argc > 1 && strcmp(argv[1], "-v") == 0) {
X		exit(test1(1)
X		     + test2(1)
X		     + test3(1)
X		     + test4(1));
X	} else {
X		if (test3(0))
X			exit(3);
X		if (test4(0))
X			exit(4);
X	}
X	exit(0);
X}
X
X
Xtest1()
X{
X	int i;
X	double l_fixed_to_double();
X	struct l_fixedpt sample;
X	double s_fixed_to_double();
X	struct s_fixedpt s_sample;
X
X	for (i = 0; i < 8; i++) {
X		printf(" %4.2f ", value[i]);
X		double_to_l_fixed(&sample, value[i]);
X		printf(" x%#8X.%#8X ", sample.int_part, sample.fraction);
X#if	0
X		printf(" %4.2f", l_fixed_to_double(&sample));
X#endif
X		printf("\t");
X		double_to_s_fixed(&s_sample, value[i]);
X		printf(" x%#4X.%#4X ", s_sample.int_part, s_sample.fraction);
X		printf(" %4.2f\n", s_fixed_to_double(&s_sample));
X	}
X	return 0;
X}
X
Xtest2()
X{
X	struct timeval tp;
X	struct l_fixedpt time_lm;
X
X	(void)gettimeofday(&tp, (struct timezone *) 0);
X	tstamp(&time_lm, &tp);
X
X	printf("tv_sec:  %d tv_usec:  %d \n", tp.tv_sec, tp.tv_usec);
X	printf("intpart: %lu fraction: %lu \n",
X	       ntohl(time_lm.int_part), ntohl(time_lm.fraction));
X	printf("intpart: %lX fraction: %lX \n",
X	       ntohl(time_lm.int_part), ntohl(time_lm.fraction));
X	return 0;
X}
X
Xtest3(v)
X	int v;
X{
X	unsigned long ul = 0x80000001;
X	double dbl;
X
X#ifdef	GENERIC_UNS_BUG
X	/*
X	 *  Hopefully, we can avoid the unsigned issue altogether.  Make sure
X	 *  that the high-order (sign) bit is zero, and fiddle from there 
X	 */
X	dbl = (long)((ul >> 1) & 0x7fffffff);
X	dbl *= 2.0;
X	if (ul & 1)
X		dbl += 1.0;
X#else
X	dbl = ul;
X#ifdef	VAX_COMPILER_FLT_BUG
X	if (dbl < 0.0) dbl += 4.294967296e9;
X#endif
X#endif
X	if (dbl != 2147483649.0) {
X		printf("test3 fails: can't convert from unsigned long to float\n");
X		printf("             (%lu != %15g)\n", ul, dbl);
X		printf(
X  "Try defining VAX_COMPILER_FLT_BUG or GENERIC_UNS_BUG in the Makefile.\n");
X		return 1;
X	} else {
X		if (v)
X			printf("test3 passes\n");
X		return 0;
X	}
X}
X
Xtest4(v)
X	int v;
X{
X	double dbl = 1024.0 * 1024.0 * 1024.0;	/* 2^30 */
X#ifdef SUN_FLT_BUG
X	int l = 1.5 * dbl;
X	u_long ul = (l<<1);
X#else
X	u_long ul = 3.0 * dbl;			/* between 2^31 and 2^32 */
X#endif
X	if (v)
X		printf("test4: 3.0*1024.0*1024.0*1024.0 = 0x%08x\n", ul);
X
X	if (ul != 0xc0000000) {
X		printf("test4 fails:\n");
X		printf("Can't convert unsigned long to double.\n");
X		printf("Try defining SUN_FLT_BUG in the Makefile\n");
X		return 1;
X	} else {
X		if (v)
X			printf("test4 passes\n");
X			return 0;
X	}
X}
________This_Is_The_END________
if test `wc -l < ntptest.c` -ne 185; then
	echo 'shar: ntptest.c was damaged during transit (should have been 185 lines)'
fi
fi		; : end of overwriting check
exit 0

Mike Kupfer		kupfer@orc.olivetti.com		415-496-6238
{decwrl!oli-stl, ames!oli-stl, oliveb}!orc!kupfer	ucbvax!kupfer