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