From 5c62ec2d8f281901a1ee0ffdcac6d8bf7ce4617c Mon Sep 17 00:00:00 2001
From: George Koehler <xkernigh@netscape.net>
Date: Sat, 5 Nov 2016 16:24:18 -0400
Subject: [PATCH 1/7] Assume ANSI C in modules/src/flt_arith

Remove the #include "ansi.h" and always use the prototypes.
---
 modules/src/flt_arith/flt_arith.h | 26 ++++++++++++--------------
 modules/src/flt_arith/flt_misc.h  | 10 +++++-----
 2 files changed, 17 insertions(+), 19 deletions(-)

diff --git a/modules/src/flt_arith/flt_arith.h b/modules/src/flt_arith/flt_arith.h
index bd6ecb157..964c19580 100644
--- a/modules/src/flt_arith/flt_arith.h
+++ b/modules/src/flt_arith/flt_arith.h
@@ -7,8 +7,6 @@
 #ifndef __FLT_INCLUDED__
 #define __FLT_INCLUDED__
 
-#include "ansi.h"
-
 #ifndef arith
 #define arith long
 #endif
@@ -33,17 +31,17 @@ extern int	flt_status;
 
 #define FLT_STRLEN	32	/* max length of result of flt_flt2str() */
 
-_PROTOTYPE(void flt_add, (flt_arith *, flt_arith *, flt_arith *));
-_PROTOTYPE(void flt_sub, (flt_arith *, flt_arith *, flt_arith *));
-_PROTOTYPE(void flt_mul, (flt_arith *, flt_arith *, flt_arith *));
-_PROTOTYPE(void flt_div, (flt_arith *, flt_arith *, flt_arith *));
-_PROTOTYPE(void flt_modf, (flt_arith *, flt_arith *, flt_arith *));
-_PROTOTYPE(int flt_cmp, (flt_arith *, flt_arith *));
-_PROTOTYPE(void flt_str2flt, (char *, flt_arith *));
-_PROTOTYPE(void flt_flt2str, (flt_arith *, char *, int));
-_PROTOTYPE(void flt_arith2flt, (arith, flt_arith *, int));
-_PROTOTYPE(arith flt_flt2arith, (flt_arith *, int));
-_PROTOTYPE(void flt_b64_sft, (struct flt_mantissa *, int));
-_PROTOTYPE(void flt_umin, (flt_arith *));
+void flt_add(flt_arith *, flt_arith *, flt_arith *);
+void flt_sub(flt_arith *, flt_arith *, flt_arith *);
+void flt_mul(flt_arith *, flt_arith *, flt_arith *);
+void flt_div(flt_arith *, flt_arith *, flt_arith *);
+void flt_modf(flt_arith *, flt_arith *, flt_arith *);
+int flt_cmp(flt_arith *, flt_arith *);
+void flt_str2flt(char *, flt_arith *);
+void flt_flt2str(flt_arith *, char *, int);
+void flt_arith2flt(arith, flt_arith *, int);
+arith flt_flt2arith(flt_arith *, int);
+void flt_b64_sft(struct flt_mantissa *, int);
+void flt_umin(flt_arith *);
 
 #endif /* __FLT_INCLUDED__ */
diff --git a/modules/src/flt_arith/flt_misc.h b/modules/src/flt_arith/flt_misc.h
index ec850697f..c5cf5a7cf 100644
--- a/modules/src/flt_arith/flt_misc.h
+++ b/modules/src/flt_arith/flt_misc.h
@@ -21,8 +21,8 @@
 #define flt_b64_add	_flt_64add
 #define flt_split	_flt_split
 
-_PROTOTYPE(int ucmp, (long, long));
-_PROTOTYPE(void flt_nrm, (flt_arith *));
-_PROTOTYPE(void flt_chk, (flt_arith *));
-_PROTOTYPE(int flt_b64_add, (struct flt_mantissa *, struct flt_mantissa *));
-_PROTOTYPE(void flt_split, (flt_arith *, unsigned short *));
+int ucmp(long, long);
+void flt_nrm(flt_arith *);
+void flt_chk(flt_arith *);
+int flt_b64_add(struct flt_mantissa *, struct flt_mantissa *);
+void flt_split(flt_arith *, unsigned short *);

From 3bb41d391038f56b74bd5e34a820d31a4dbd658f Mon Sep 17 00:00:00 2001
From: George Koehler <xkernigh@netscape.net>
Date: Sat, 5 Nov 2016 17:00:24 -0400
Subject: [PATCH 2/7] Switch flt_mantissa fields from long to uint32_t.

This seems to fix an error when flt_arith converts a literal
double-precision float to IEEE format.  For example, 0.5 and 0.75 got
converted to slightly below their correct values.

My host gcc for amd64 has 64-bit long, but flt_arith needs only 32
bits.  The code (at least flt_add.c) can make 32-bit overflows.  Such
overflows would set the higher bits of a 64-bit long, which might
cause problems later.

I need to use uint32_t and not int32_t because the code still uses
long, and the sign extension from int32_t to long would cause
problems.  The mantissa represents a value in [0, 2) that can't be
negative, so unsigned type is better.  Also, signed overflow is
undefined behavior in C, so flt_add.c better make overflows with
uint32_t and not int32_t.

This commit doesn't touch lang/cem/libcc.ansi/stdlib/ext_fmt.h which
continues to use unsigned long for its mantissa fields.
---
 modules/src/flt_arith/flt_arith.h | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/modules/src/flt_arith/flt_arith.h b/modules/src/flt_arith/flt_arith.h
index 964c19580..9a21e5135 100644
--- a/modules/src/flt_arith/flt_arith.h
+++ b/modules/src/flt_arith/flt_arith.h
@@ -7,13 +7,15 @@
 #ifndef __FLT_INCLUDED__
 #define __FLT_INCLUDED__
 
+#include <stdint.h>
+
 #ifndef arith
 #define arith long
 #endif
 
 struct flt_mantissa {
-	long	flt_h_32;	/* high order 32 bits of mantissa */
-	long	flt_l_32;	/* low order 32 bits of mantissa */
+	uint32_t flt_h_32;	/* high order 32 bits of mantissa */
+	uint32_t flt_l_32;	/* low order 32 bits of mantissa */
 };
 
 typedef struct flt_arith {

From daeeb5aca3a18ff8e240a534bad1f0941523cf9c Mon Sep 17 00:00:00 2001
From: George Koehler <xkernigh@netscape.net>
Date: Sat, 5 Nov 2016 21:29:03 -0400
Subject: [PATCH 3/7] Simplify flt_arith now that mantissa uses uint32_t.

It seems that someone wanted to build flt_arith with a compiler that
had long but not unsigned long.  This required extra code to
accomplish unsigned right shift, unsigned division, and unsigned
comparison using the signed operations.  Now that we use uint32_t, we
can simply use the unsigned operations and remove the ucmp() function.
We have similar code in mach/proto/fp/ and in
lang/cem/libcc.ansi/stdlib/ext_comp.c where we use the unsigned
operations.

Some long variables become uint32_t, and some masks with 0xFFFFFFFF
disappear because uint32_t has only 32 bits.

Update flt_arith.3 to show that mantissa uses uint32_t.

Provide a target to install modules/src/flt_arith/test.c as flt_test
so I can run the tests.
---
 modules/src/flt_arith/b64_add.c   | 10 +++----
 modules/src/flt_arith/b64_sft.c   | 15 ++++------
 modules/src/flt_arith/build.lua   | 15 +++++++++-
 modules/src/flt_arith/flt_add.c   |  9 +++---
 modules/src/flt_arith/flt_arith.3 |  4 +--
 modules/src/flt_arith/flt_div.c   | 47 +++++++++++++------------------
 modules/src/flt_arith/flt_misc.h  |  2 --
 modules/src/flt_arith/flt_mul.c   | 13 +++++----
 modules/src/flt_arith/flt_nrm.c   |  5 ++--
 modules/src/flt_arith/test.c      |  5 +++-
 modules/src/flt_arith/ucmp.c      | 21 --------------
 11 files changed, 64 insertions(+), 82 deletions(-)
 delete mode 100644 modules/src/flt_arith/ucmp.c

diff --git a/modules/src/flt_arith/b64_add.c b/modules/src/flt_arith/b64_add.c
index ca03e84a0..71bd66607 100644
--- a/modules/src/flt_arith/b64_add.c
+++ b/modules/src/flt_arith/b64_add.c
@@ -5,6 +5,7 @@
 
 /* $Id$ */
 
+#include <stdint.h>
 #include "flt_misc.h"
 
 int
@@ -15,16 +16,15 @@ flt_b64_add(e1,e2)
 	int	carry;
 
 	/* add higher pair of 32 bits */
-	overflow = ucmp((long)0xFFFFFFFF - e1->flt_h_32, e2->flt_h_32) < 0;
+	overflow = (0xFFFFFFFFUL - e1->flt_h_32 < e2->flt_h_32);
 	e1->flt_h_32 += e2->flt_h_32;
 
 	/* add lower pair of 32 bits */
-	carry = ucmp((long)0xFFFFFFFF - e1->flt_l_32, e2->flt_l_32) < 0;
+	carry = (0xFFFFFFFFUL - e1->flt_l_32 < e2->flt_l_32);
 	e1->flt_l_32 += e2->flt_l_32;
 
-	if ((carry) && ((++e1->flt_h_32 &~0xFFFFFFFF) || e1->flt_h_32 == 0)) {
-		e1->flt_h_32 = 0;
+	if ((carry) && (++e1->flt_h_32 == 0))
 		return(1);		/* had a 64 bit overflow */
-	}
+
 	return(overflow);	/* return status from higher add */
 }
diff --git a/modules/src/flt_arith/b64_sft.c b/modules/src/flt_arith/b64_sft.c
index f891c6936..ef6d74a9e 100644
--- a/modules/src/flt_arith/b64_sft.c
+++ b/modules/src/flt_arith/b64_sft.c
@@ -23,12 +23,10 @@ flt_b64_sft(e,n)
 		n -= 32;
 	}
 	if (n > 0) {
-		e->flt_l_32 = (e->flt_l_32 >> 1) & 0x7FFFFFFF;
-		e->flt_l_32 >>= (n - 1);
+		e->flt_l_32 >>= n;
 		if (e->flt_h_32 != 0) {
-			e->flt_l_32 |= (e->flt_h_32 << (32 - n)) & 0xFFFFFFFF;
-			e->flt_h_32 = (e->flt_h_32 >> 1) & 0x7FFFFFFF;
-			e->flt_h_32 >>= (n - 1);
+			e->flt_l_32 |= (e->flt_h_32 << (32 - n));
+			e->flt_h_32 >>= n;
 		}
 	}
 	n = -n;
@@ -38,11 +36,10 @@ flt_b64_sft(e,n)
 		n -= 32;
 	}
 	if (n > 0) {
-		e->flt_h_32 = (e->flt_h_32 << n) & 0xFFFFFFFF;
+		e->flt_h_32 <<= n;
 		if (e->flt_l_32 != 0) {
-			long l = (e->flt_l_32 >> 1) & 0x7FFFFFFF;
-			e->flt_h_32 |= (l >> (31 - n));
-			e->flt_l_32 = (e->flt_l_32 << n) & 0xFFFFFFFF;
+			e->flt_h_32 |= (e->flt_l_32 >> (32 - n));
+			e->flt_l_32 <<= n;
 		}
 	}
 }
diff --git a/modules/src/flt_arith/build.lua b/modules/src/flt_arith/build.lua
index e6ac2dd40..54aa3b097 100644
--- a/modules/src/flt_arith/build.lua
+++ b/modules/src/flt_arith/build.lua
@@ -15,7 +15,6 @@ clibrary {
 		"./flt_umin.c",
 		"./flt_chk.c",
 		"./split.c",
-		"./ucmp.c",
 	},
 	hdrs = { "./flt_arith.h" },
 	deps = {
@@ -24,4 +23,18 @@ clibrary {
 	}
 }
 
+-- The test program isn't built by default.  Here is a target
+-- modules/src/flt_arith+pkg to install it as flt_test
 
+cprogram {
+	name = "test",
+	srcs = { "./test.c" },
+	deps = { "+lib" },
+}
+
+installable {
+	name = "pkg",
+	map = {
+		["$(INSDIR)/bin/flt_test"] = "+test",
+	},
+}
diff --git a/modules/src/flt_arith/flt_add.c b/modules/src/flt_arith/flt_add.c
index d9d4d57c5..ca9830ec3 100644
--- a/modules/src/flt_arith/flt_add.c
+++ b/modules/src/flt_arith/flt_add.c
@@ -44,11 +44,10 @@ flt_add(e1,e2,e3)
 	}
 	if (e1->flt_sign != e2->flt_sign) {
 		/* e2 + e1 = e2 - (-e1) */
-		int tmp = ucmp(e1->m1, e2->m1);
-		int tmp2 = ucmp(e1->m2, e2->m2);
-		if (tmp > 0 || (tmp == 0 && tmp2 > 0)) {
+		if (e1->m1 > e2->m1 ||
+		    (e1->m1 == e2->m1 && e1->m2 > e2->m2)) {
                 	/*      abs(e1) > abs(e2) */
-                	if (tmp2 < 0) {
+			if (e1->m2 < e2->m2) {
                         	e1->m1 -= 1;    /* carry in */
                 	}
                 	e1->m1 -= e2->m1;
@@ -56,7 +55,7 @@ flt_add(e1,e2,e3)
                 	*e3 = *e1;
         	}
         	else {
-                	if (tmp2 > 0)
+			if (e1->m2 > e2->m2)
                         	e2->m1 -= 1;    /* carry in */
                 	e2->m1 -= e1->m1;
                 	e2->m2 -= e1->m2;
diff --git a/modules/src/flt_arith/flt_arith.3 b/modules/src/flt_arith/flt_arith.3
index 2e6a5feb1..91bce44ea 100644
--- a/modules/src/flt_arith/flt_arith.3
+++ b/modules/src/flt_arith/flt_arith.3
@@ -9,8 +9,8 @@ flt_arith \- high precision floating point arithmetic
 .if t .ta 3m 13m 22m
 .if n .ta 5m 25m 40m
 struct flt_mantissa {
-	long	flt_h_32;	/* high order 32 bits of mantissa */
-	long	flt_l_32;	/* low order 32 bits of mantissa */
+	uint32_t flt_h_32;	/* high order 32 bits of mantissa */
+	uint32_t flt_l_32;	/* low order 32 bits of mantissa */
 };
 
 typedef struct {
diff --git a/modules/src/flt_arith/flt_div.c b/modules/src/flt_arith/flt_div.c
index 11b74c0e1..3295fe63b 100644
--- a/modules/src/flt_arith/flt_div.c
+++ b/modules/src/flt_arith/flt_div.c
@@ -5,14 +5,15 @@
 
 /* $Id$ */
 
+#include <stdint.h>
 #include "flt_misc.h"
 
 void
 flt_div(e1,e2,e3)
 	register flt_arith *e1,*e2,*e3;
 {
-	long	result[2];
-	register long	*lp;
+	uint32_t result[2];
+	register uint32_t *rp;
 	unsigned short u[9], v[5];
 	register int j;
 	register unsigned short *u_p = u;
@@ -44,7 +45,7 @@ flt_div(e1,e2,e3)
 	while (! v[maxv]) maxv--;
 	result[0] = 0;
 	result[1] = 0;
-	lp = result;
+	rp = result;
 
 	/*
 	 * Use an algorithm of Knuth (The art of programming, Seminumerical
@@ -52,35 +53,25 @@ flt_div(e1,e2,e3)
 	 * with base 65536. 
 	 */
 	for (j = 0; j <= 3; j++, u_p++) {
-		long q_est, temp;
-		long v1 = v[1];
+		uint32_t q_est, temp;
 
-		if (j == 2) lp++;
+		if (j == 2) rp++;
 		if (u_p[0] == 0 && u_p[1] < v[1]) continue;
-		temp = ((long)u_p[0] << 16) + u_p[1];
+		temp = ((uint32_t)u_p[0] << 16) + u_p[1];
 		if (u_p[0] >= v[1]) {
-			q_est = 0x0000FFFFL;
+			q_est = 0x0000FFFFUL;
 		}
 		else if (v[1] == 1) {
 			q_est = temp;
 		}
-		else if (temp >= 0) {
-			q_est = temp / v1;
-		}
 		else {
-			long rem;
-			q_est = (0x7FFFFFFF/v1)+((temp&0x7FFFFFFF)/v1);
-			rem = (0x7FFFFFFF%v1)+((temp&0x7FFFFFFF)%v1)+1;
-			while (rem >= v1) {
-				q_est++;
-				rem -= v1;
-			}
+			q_est = temp / v[1];
 		}
-		temp -= q_est * v1;
+		temp -= q_est * v[1];
 		while (!(temp&0xFFFF0000) &&
-		       ucmp((long)v[2]*q_est,(temp<<16)+(long)u_p[2]) > 0) {
+		       v[2]*q_est > (temp<<16)+u_p[2]) {
 			q_est--;
-			temp += v1;
+			temp += v[1];
 		}
 		/*	Now, according to Knuth, we have an estimate of the
 			quotient, that is either correct or one too big, but
@@ -88,11 +79,11 @@ flt_div(e1,e2,e3)
 		*/
 		if (q_est != 0)  {
 			int i;
-			long k = 0;
+			uint32_t k = 0;
 			int borrow = 0;
 
 			for (i = maxv; i > 0; i--) {
-				long tmp = q_est * (long)v[i] + k + borrow;
+				uint32_t tmp = q_est * v[i] + k + borrow;
 				unsigned short md = tmp & 0xFFFF;
 
 				borrow = (md > u_p[i]);
@@ -100,7 +91,7 @@ flt_div(e1,e2,e3)
 				k = (tmp >> 16) & 0xFFFF;
 			}
 			k += borrow;
-			borrow = (long)u_p[0] < k;
+			borrow = u_p[0] < k;
 			u_p[0] -= k;
 
 			if (borrow) {
@@ -110,15 +101,15 @@ flt_div(e1,e2,e3)
 				q_est--;
 				borrow = 0;
 				for (i = maxv; i > 0; i--) {
-					long tmp 
-					    = v[i]+(long)u_p[i]+borrow;
-					
+					uint32_t tmp
+					    = v[i]+(uint32_t)u_p[i]+borrow;
+
 					u_p[i] = tmp & 0xFFFF;
 					borrow = (tmp >> 16) & 0xFFFF;
 				}
 				u_p[0] += borrow;
 			}
-			*lp |= (j & 1) ? q_est : (q_est<<16);
+			*rp |= (j & 1) ? q_est : (q_est<<16);
 		}
 	}
 	e3->m1 = result[0];
diff --git a/modules/src/flt_arith/flt_misc.h b/modules/src/flt_arith/flt_misc.h
index c5cf5a7cf..64b6865aa 100644
--- a/modules/src/flt_arith/flt_misc.h
+++ b/modules/src/flt_arith/flt_misc.h
@@ -15,13 +15,11 @@
 #define EXT_MIN		(-16384)	/* min exponent */
 
 /* hiding of names: */
-#define ucmp		_flt_ucmp
 #define flt_nrm		_flt_nrm
 #define flt_chk		_flt_chk
 #define flt_b64_add	_flt_64add
 #define flt_split	_flt_split
 
-int ucmp(long, long);
 void flt_nrm(flt_arith *);
 void flt_chk(flt_arith *);
 int flt_b64_add(struct flt_mantissa *, struct flt_mantissa *);
diff --git a/modules/src/flt_arith/flt_mul.c b/modules/src/flt_arith/flt_mul.c
index e6972ab54..4d989382b 100644
--- a/modules/src/flt_arith/flt_mul.c
+++ b/modules/src/flt_arith/flt_mul.c
@@ -5,6 +5,7 @@
 
 /* $Id$ */
 
+#include <stdint.h>
 #include "flt_misc.h"
 
 void
@@ -43,9 +44,9 @@ flt_mul(e1,e2,e3)
 	 */
 	for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
 		unsigned short k = 0;
-		long mpi = mp[i];
+		uint32_t mpi = mp[i];
 		for(j=4;j--;) {
-			long tmp = (long)pres[j] + k;
+			long tmp = (uint32_t)pres[j] + k;
 			if (mc[j]) tmp += mpi * mc[j];
 			pres[j] = tmp & 0xFFFF;
 			k = (tmp >> 16) & 0xFFFF;
@@ -64,12 +65,12 @@ flt_mul(e1,e2,e3)
 	/*
 	 *	combine the registers to a total
 	 */
-	e3->m1 = ((long)result[0] << 16) + result[1];
-	e3->m2 = ((long)result[2] << 16) + result[3];
+	e3->m1 = ((uint32_t)result[0] << 16) + result[1];
+	e3->m2 = ((uint32_t)result[2] << 16) + result[3];
 	if (result[4] & 0x8000) {
-		if (++e3->m2 == 0 || (e3->m2 & ~ 0xFFFFFFFF)) {
+		if (++e3->m2 == 0) {
 			e3->m2 = 0;
-			if (++e3->m1 == 0 || (e3->m1 & ~ 0xFFFFFFFF)) {
+			if (++e3->m1 == 0) {
 				e3->m1 = 0x80000000;
 				e3->flt_exp++;
 			}
diff --git a/modules/src/flt_arith/flt_nrm.c b/modules/src/flt_arith/flt_nrm.c
index 14762b616..3520ee5b4 100644
--- a/modules/src/flt_arith/flt_nrm.c
+++ b/modules/src/flt_arith/flt_nrm.c
@@ -5,6 +5,7 @@
 
 /* $Id$ */
 
+#include <stdint.h>
 #include "flt_misc.h"
 
 void
@@ -24,8 +25,8 @@ flt_nrm(e)
 		e->m2 = 0L;
 		e->flt_exp -= 32;
 	}
-	if ((e->m1 & 0x80000000) == 0) {
-		long l = 0x40000000;
+	if ((e->m1 & 0x80000000UL) == 0) {
+		uint32_t l = 0x40000000UL;
 		int cnt = -1;
 
 		while (! (l & e->m1)) {
diff --git a/modules/src/flt_arith/test.c b/modules/src/flt_arith/test.c
index bf9c43c69..dfc4a694a 100644
--- a/modules/src/flt_arith/test.c
+++ b/modules/src/flt_arith/test.c
@@ -1,3 +1,5 @@
+#include <stdio.h>
+#include <string.h>
 #include "flt_arith.h"
 
 struct tests {
@@ -22,6 +24,7 @@ struct tests {
 	{ 0, 0, 0, 0}
 };
 
+int
 main()
 {
 	register struct tests *p = tests;
@@ -31,7 +34,7 @@ main()
 		if (! dotest(p)) exit_status = 1;
 		p++;
 	}
-	exit(exit_status);
+	return exit_status;
 }
 
 int
diff --git a/modules/src/flt_arith/ucmp.c b/modules/src/flt_arith/ucmp.c
deleted file mode 100644
index c4b7bc0a4..000000000
--- a/modules/src/flt_arith/ucmp.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-  (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
-  See the copyright notice in the ACK home directory, in the file "Copyright".
-*/
-
-/* $Id$ */
-
-#include "flt_misc.h"
-
-int
-ucmp(l1,l2)
-	long l1,l2;
-{
-	if (l1 == l2) return 0;
-	if (l2 >= 0) {
-		if (l1 > l2 || l1 < 0) return 1;
-		return -1;
-	}
-	if (l1 >= 0 || l1 < l2) return -1;
-	return 1;
-}

From 19ca28e22f6de12cbff8f0be250a0a30b74b3c92 Mon Sep 17 00:00:00 2001
From: George Koehler <xkernigh@netscape.net>
Date: Sun, 6 Nov 2016 15:01:25 -0500
Subject: [PATCH 4/7] Undo commit bfeb736 for
 lang/cem/libcc.ansi/headers/float.h

This restores the correct values of DBL_MAX, DBL_MIN_EXP, and related
constants.  This fixes some range checks within libc, causing
atof("-36e90") and atof("1.44e-288") to return the correct values.
---
 lang/cem/libcc.ansi/headers/float.h | 108 ++++++++++++++++++----------
 1 file changed, 72 insertions(+), 36 deletions(-)

diff --git a/lang/cem/libcc.ansi/headers/float.h b/lang/cem/libcc.ansi/headers/float.h
index 43656651b..8cdb34c4f 100644
--- a/lang/cem/libcc.ansi/headers/float.h
+++ b/lang/cem/libcc.ansi/headers/float.h
@@ -1,43 +1,79 @@
 /*
-    <float.h> -- simple version used by "gimplify"
+ * float.h - implementation limits
+ */
+/* $Id$ */
 
-    last edit:  2007-02-12  D A Gwyn
-*/
+#if	!defined(_FLOAT_H)
+#define	_FLOAT_H
 
-/* Does not exactly fit any model, and is minimal for "universality". */
+#if	defined(__vax) || defined(__pdp)
+#define	FLT_DIG			6
+#define	FLT_EPSILON		5.96046448e-08F
+#define	FLT_MANT_DIG		8
+#define	FLT_MAX			1.70141173e+38F
+#define	FLT_MAX_10_EXP		38
+#define	FLT_MAX_EXP		127
+#define	FLT_MIN			2.93873588e-39F
+#define	FLT_MIN_10_EXP		(-38)
+#define	FLT_MIN_EXP		(-127)
 
-#define FLT_ROUNDS  (-1)
-#define FLT_EVAL_METHOD (-1)
-#define FLT_RADIX   2
-#define DECIMAL_DIG 10
+#define	DBL_DIG			16
+#define	DBL_EPSILON		1.38777878078144568e-17
+#define	DBL_MANT_DIG		8
+#define	DBL_MAX			1.70141183460469229e+38
+#define	DBL_MAX_10_EXP		38
+#define	DBL_MAX_EXP		127
+#define	DBL_MIN			2.93873587705571877e-39
+#define	DBL_MIN_10_EXP		(-38)
+#define	DBL_MIN_EXP		(-127)
 
-/* assumes that "gimplify" specifies "-Dfloat=double" */
-#define FLT_MANT_DIG    10
-#define FLT_EPSILON (1E-9F)
-#define FLT_DIG     10
-#define FLT_MIN_EXP (-31)
-#define FLT_MIN     (1E-37F)
-#define FLT_MIN_10_EXP  (-37)
-#define FLT_MAX_EXP 37
-#define FLT_MAX     (1E+37F)
-#define FLT_MAX_10_EXP  37
+#define	LDBL_DIG		16
+#define	LDBL_EPSILON		1.38777878078144568e-17L
+#define	LDBL_MANT_DIG		8
+#define	LDBL_MAX		1.70141183460469229e+38L
+#define	LDBL_MAX_10_EXP		38
+#define	LDBL_MAX_EXP		127
+#define	LDBL_MIN		2.93873587705571877e-39L
+#define	LDBL_MIN_10_EXP		(-38)
+#define	LDBL_MIN_EXP		(-127)
 
-#define DBL_MANT_DIG    10
-#define DBL_EPSILON (1E-9)
-#define DBL_DIG     10
-#define DBL_MIN_EXP (-31)
-#define DBL_MIN     (1E-37)
-#define DBL_MIN_10_EXP  (-37)
-#define DBL_MAX_EXP 37
-#define DBL_MAX     (1E+37)
-#define DBL_MAX_10_EXP  37
+#define	FLT_ROUNDS		1
+#define	FLT_RADIX		2
 
-#define LDBL_MANT_DIG   10
-#define LDBL_EPSILON    (1E-9L)
-#define LDBL_DIG    10
-#define LDBL_MIN_EXP    (-31)
-#define LDBL_MIN    (1E-37L)
-#define LDBL_MIN_10_EXP (-37)
-#define LDBL_MAX_EXP    37
-#define LDBL_MAX    (1E+37L)
-#define LDBL_MAX_10_EXP 37
+#else		/* IEEE format */
+#define	FLT_DIG			6
+#define	FLT_EPSILON		1.19209290e-07F
+#define	FLT_MANT_DIG		24
+#define	FLT_MAX			3.40282347e+38F
+#define	FLT_MAX_10_EXP		38
+#define	FLT_MAX_EXP		128
+#define	FLT_MIN			1.17549435e-38F
+#define	FLT_MIN_10_EXP		(-37)
+#define	FLT_MIN_EXP		(-125)
+
+#define	DBL_DIG			15
+#define	DBL_EPSILON		2.2204460492503131e-16
+#define	DBL_MANT_DIG		53
+#define	DBL_MAX			1.7976931348623157e+308
+#define	DBL_MAX_10_EXP		308
+#define	DBL_MAX_EXP		1024
+#define	DBL_MIN			2.2250738585072014e-308
+#define	DBL_MIN_10_EXP		(-307)
+#define	DBL_MIN_EXP		(-1021)
+
+#define	LDBL_DIG		15
+#define	LDBL_EPSILON		2.2204460492503131e-16L
+#define	LDBL_MANT_DIG		53
+#define	LDBL_MAX		1.7976931348623157e+308L
+#define	LDBL_MAX_10_EXP		308
+#define	LDBL_MAX_EXP		1024
+#define	LDBL_MIN		2.2250738585072014e-308L
+#define	LDBL_MIN_10_EXP		(-307)
+#define	LDBL_MIN_EXP		(-1021)
+
+#define	FLT_ROUNDS		1
+#define	FLT_RADIX		2
+
+#endif	/* vax, pdp or ieee */
+
+#endif	/* _FLOAT_H */

From 08f9869a63d85a4634ec87c826212b01f935af8e Mon Sep 17 00:00:00 2001
From: George Koehler <xkernigh@netscape.net>
Date: Sun, 6 Nov 2016 15:49:47 -0500
Subject: [PATCH 5/7] Remove unused defines from
 lang/cem/libcc.ansi/math/localmath.h

This undoes part of bfeb736, and returns to using DBL_MAX_EXP and
DBL_MIN_EXP from float.h.

Add a dependency on math/localmath.h and other local header files so
libc is rebuilt when those headers change.
---
 lang/cem/libcc.ansi/build.lua        | 20 ++++++++++++--------
 lang/cem/libcc.ansi/math/localmath.h | 17 ++---------------
 2 files changed, 14 insertions(+), 23 deletions(-)

diff --git a/lang/cem/libcc.ansi/build.lua b/lang/cem/libcc.ansi/build.lua
index 3ca95b629..601a50de4 100644
--- a/lang/cem/libcc.ansi/build.lua
+++ b/lang/cem/libcc.ansi/build.lua
@@ -28,9 +28,9 @@ normalrule {
 }
 
 for _, plat in ipairs(vars.plats) do
-    acklibrary {
-        name = "lib_"..plat,
-        srcs = {
+	acklibrary {
+		name = "lib_"..plat,
+		srcs = {
 			"+ctype_files",
 			"+ctype_tab",
 			"./ctype/*.c",
@@ -43,20 +43,24 @@ for _, plat in ipairs(vars.plats) do
 			"./setjmp/*.c",
 			"./setjmp/*.e",
 			"./signal/*.c",
-            "./assert/*.c",
+			"./assert/*.c",
 			"./stdio/*.c",
 			"./stdlib/*.c",
 			"./string/*.c",
 			"./time/*.c",
-			
-        },
+		},
 		hdrs = {}, -- must be empty
 		deps = {
 			"lang/cem/libcc.ansi/headers+headers",
 			"plat/"..plat.."/include+headers",
+			"./malloc/malloc.h",
+			"./math/localmath.h",
+			"./stdio/loc_incl.h",
+			"./stdlib/ext_fmt.h",
+			"./time/loc_time.h",
 		},
-        vars = { plat = plat }
-    }
+		vars = { plat = plat }
+	}
 
 	ackfile {
 		name = "crt_"..plat,
diff --git a/lang/cem/libcc.ansi/math/localmath.h b/lang/cem/libcc.ansi/math/localmath.h
index 7c9a67465..e85c81c0a 100644
--- a/lang/cem/libcc.ansi/math/localmath.h
+++ b/lang/cem/libcc.ansi/math/localmath.h
@@ -18,18 +18,5 @@
 #define	POLYNOM12(x, a)	(POLYNOM11((x),(a)+1)*(x)+(a)[0])
 #define	POLYNOM13(x, a)	(POLYNOM12((x),(a)+1)*(x)+(a)[0])
 
-/* These are set up for 64-bit doubles. */
-
-#ifndef M_MAX_D
-#define M_MAX_D          1.7976931348623157e+308
-#define M_MIN_D		 2.2250738585072014e-308
-#define M_DEXPLEN	 11
-#endif
-#define M_DMAXEXP	 ((1 << (M_DEXPLEN - 1)) - 1)
-#define M_DMINEXP	 (-M_DMAXEXP)
-#define M_LN_MAX_D	 (M_LN2 * M_DMAXEXP)
-#define M_LN_MIN_D	 (M_LN2 * (M_DMINEXP - 1))
-
-#define HUGE		M_MAX_D
-#define MAXDOUBLE	M_MAX_D
-
+#define	M_LN_MAX_D	(M_LN2 * DBL_MAX_EXP)
+#define	M_LN_MIN_D	(M_LN2 * (DBL_MIN_EXP - 1))

From e5e96d5226c27e4f31d199bc8530885c78c2058d Mon Sep 17 00:00:00 2001
From: George Koehler <xkernigh@netscape.net>
Date: Sun, 6 Nov 2016 19:34:51 -0500
Subject: [PATCH 6/7] Convert 1 to 1.0, not 0.0, for machines with 64-bit long.

This fixes flt_arith2flt() when sizeof(arith) != 4, where arith is
long.  When cemcom.ansi sees an expression like d + 1 (where d is some
double), it calls flt_arith2flt() to convert 1 to floating-point.  On
machines where sizeof(arith) != 4, the code did n >>= 1 when n should
not have been changed.  If n was 1, then n == 0 became true.  This
caused the code to convert 1 or -1 to 0.0.

My fix assumes sizeof(arith) >= 8, so I can use n >> 32.  Machines
with sizeof(arith) of 5 to 7 would need to do (uarith)n >> 32, where
uarith must be an unsigned integer type of same size as arith.

In startrek.c, the Enterprise can now dock with a starbase.  The
compiler no longer translates s1 - 1 to s1 - 0.0 and s1 + 1 to s1 +
0.0, so the game now looks for starbases next to the Enterprise.
---
 modules/src/flt_arith/flt_ar2flt.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/modules/src/flt_arith/flt_ar2flt.c b/modules/src/flt_arith/flt_ar2flt.c
index f1d159a67..6dac35883 100644
--- a/modules/src/flt_arith/flt_ar2flt.c
+++ b/modules/src/flt_arith/flt_ar2flt.c
@@ -25,10 +25,9 @@ flt_arith2flt(n, e, uns)
 		e->m1 = 0; e->m2 = n;
 	}
 	else {
-		e->m2 = n & 0xffffffffL;
-		n >>= 1;
-		n &= ~((arith) 1 << (8*sizeof(arith)-1));
-		e->m1 = (n >> 31);
+		/* assuming sizeof(arith) >= 8 */
+		e->m1 = n >> 32;
+		e->m2 = n;
 	}
 	if (n == 0) {
 		e->flt_exp = 0;

From 82c2d184822c739f4761bee2e26c5974b9e16d1e Mon Sep 17 00:00:00 2001
From: George Koehler <xkernigh@netscape.net>
Date: Sun, 6 Nov 2016 20:21:48 -0500
Subject: [PATCH 7/7] Edit startrek.c so I can compile it with gcc and OpenBSD
 libc.

Rename our getline() to get_line() to prevent a conflict with POSIX
getline() declared in stdio.h.

Remove dangerous call to gets().  OpenBSD does not have gets(), C99
deprecated it and C11 removed it.

Also change spelling "sheild" to "shield".
---
 examples/startrek.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/examples/startrek.c b/examples/startrek.c
index f4f35a8bd..572c53597 100644
--- a/examples/startrek.c
+++ b/examples/startrek.c
@@ -107,7 +107,7 @@ void phaser_control(void);
 void photon_torpedoes(void);
 void torpedo_hit(void);
 void damage_control(void);
-void sheild_control(void);
+void shield_control(void);
 void library_computer(void);
 void galactic_record(void);
 void status_report(void);
@@ -137,7 +137,7 @@ void sub2(void);
 void showfile(char *filename);
 int openfile(char * sFilename, char * sMode);
 void closefile(void);
-int getline(char *s);
+int get_line(char *s);
 void randomize(void);
 int get_rand(int iSpread);
 double rnd(void);
@@ -203,7 +203,7 @@ void
 reads(char* buffer)
 {
   fflush(stdout);
-  gets(buffer);
+  fgets(buffer, sizeof(string), stdin);
 }
 
 /* Main Program */
@@ -292,7 +292,7 @@ new_game(void)
       else if (! strncmp(sTemp, "tor", 3))
         photon_torpedoes();
       else if (! strncmp(sTemp, "she", 3))
-        sheild_control();
+        shield_control();
       else if (! strncmp(sTemp, "dam", 3))
         damage_control();
       else if (! strncmp(sTemp, "com", 3))
@@ -307,7 +307,7 @@ new_game(void)
       printf("  lrs - Long Range Sensors\n");
       printf("  pha - Phasers\n");
       printf("  tor - Photon Torpedoes\n");
-      printf("  she - Sheild Control\n");
+      printf("  she - Shield Control\n");
       printf("  dam - Damage Control\n");
       printf("  com - Library Computer\n");
       printf("  xxx - Resign Command\n");
@@ -1206,14 +1206,14 @@ damage_control(void)
 } 
 
 void
-sheild_control(void)
+shield_control(void)
 {
   int i;
   string sTemp;
 
   if (d[7] < 0.0)
     {
-      printf("Sheild Control inoperable\n");
+      printf("Shield Control inoperable\n");
       return;
     }
 
@@ -1229,15 +1229,15 @@ sheild_control(void)
 
   if (i < 0 || s == i)
     {
-      printf("<Sheilds Unchanged>\n\n");
+      printf("<Shields Unchanged>\n\n");
       return;
     }
 
   if (i >= e + s)
     {
-      printf("Sheild Control Reports:\n");
+      printf("Shield Control Reports:\n");
       printf("  'This is not the Federation Treasury.'\n");
-      printf("<Sheilds Unchanged>\n\n");
+      printf("<Shields Unchanged>\n\n");
       return;
     }
 
@@ -1776,7 +1776,7 @@ get_device_name(void)
 {
   static char * device_name[] = {
     "", "Warp Engines","Short Range Sensors","Long Range Sensors",
-    "Phaser Control","Photon Tubes","Damage Control","Sheild Control",
+    "Phaser Control","Photon Tubes","Damage Control","Shield Control",
     "Library-Computer"};
 
   if (r1 < 0 || r1 > 8)
@@ -1888,7 +1888,7 @@ showfile(char *filename)
   if (openfile(filename, "r") != 0)
     return;
 
-  while (getline(lBuffer) != 0)
+  while (get_line(lBuffer) != 0)
     {
       printf(lBuffer);
       
@@ -1926,7 +1926,7 @@ closefile(void)
 }
 
 int
-getline(char *s)
+get_line(char *s)
 {
   fflush(stdout);
   if (fgets(s, MAXCOL, stream) == NULL)