diff --git a/src/modules/sprintf/sprintf.c b/src/modules/sprintf/sprintf.c
index d0f4b00d89ef3c4645357e648eb840a0b7270c79..4732c71d4f89afb5c9d2e4ca8b3e6740202aade8 100644
--- a/src/modules/sprintf/sprintf.c
+++ b/src/modules/sprintf/sprintf.c
@@ -96,7 +96,7 @@
 */
 
 #include "global.h"
-RCSID("$Id: sprintf.c,v 1.19 1998/05/06 01:04:36 hubbe Exp $");
+RCSID("$Id: sprintf.c,v 1.20 1998/05/24 22:40:53 marcus Exp $");
 #include "error.h"
 #include "array.h"
 #include "svalue.h"
@@ -108,6 +108,14 @@ RCSID("$Id: sprintf.c,v 1.19 1998/05/06 01:04:36 hubbe Exp $");
 #include "pike_memory.h"
 #include "pike_macros.h"
 
+#include <math.h>
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+#ifdef HAVE_FP_CLASS_H
+#include <fp_class.h>
+#endif
+
 #define FORMAT_INFO_STACK_SIZE 200
 #define RETURN_SHARED_STRING
 
@@ -150,6 +158,182 @@ static struct format_info *fsp;
 #define MULTILINE (LINEBREAK | COLUMN_MODE | ROUGH_LINEBREAK | \
 		   INVERSE_COLUMN_MODE | MULTI_LINE | REPEAT)
 
+
+/* Generate binary IEEE strings on a machine which uses a different kind
+   of floating point internally */
+
+#ifndef FLOAT_IS_IEEE_BIG
+#ifndef FLOAT_IS_IEEE_LITTLE
+#define NEED_CUSTOM_IEEE
+#endif
+#endif
+#ifndef NEED_CUSTOM_IEEE
+#ifndef DOUBLE_IS_IEEE_BIG
+#ifndef DOUBLE_IS_IEEE_LITTLE
+#define NEED_CUSTOM_IEEE
+#endif
+#endif
+#endif
+
+#ifdef NEED_CUSTOM_IEEE
+
+#ifndef HAVE_FPCLASS
+#ifdef HAVE_FP_CLASS_D
+#define fpclass fp_class_d
+#define FP_NZERO FP_NEG_ZERO
+#define FP_PZERO FP_POS_ZERO
+#define FP_NINF FP_NEG_INF
+#define FP_PINF FP_POS_INF
+#define FP_NNORM FP_NEG_NORM
+#define FP_PNORM FP_POS_NORM
+#define FP_NDENORM FP_NEG_DENORM
+#define FP_PDENORM FP_POS_DENORM
+#define HAVE_FPCLASS
+#endif
+#endif
+
+#ifdef HAVE_FREXP
+#define FREXP frexp
+#else
+extern double FREXP(double x, int *exp); /* defined in encode.c */
+#endif
+
+#if HAVE_LDEXP
+#define LDEXP ldexp
+#else
+extern double LDEXP(double x, int exp); /* defined in encode.c */
+#endif
+
+INLINE static void low_write_IEEE_float(char *b, double d, int sz)
+{
+  int maxexp;
+  unsigned INT32 maxf;
+  int s = 0, e = -1;
+  unsigned INT32 f = 0, extra_f=0;
+
+  if(sz==4) {
+    maxexp = 255;
+    maxf   = 0x7fffff;
+  } else {
+    maxexp = 2047;
+    maxf   = 0x0fffff; /* This is just the high part of the mantissa... */
+  }
+
+#ifdef HAVE_FPCLASS
+  switch(fpclass(d)) {
+  case FP_SNAN:
+    e = maxexp; f = 2; break;
+  case FP_QNAN:
+    e = maxexp; f = maxf; break;
+  case FP_NINF:
+    s = 1; /* FALLTHRU */
+  case FP_PINF:
+    e = maxexp; break;
+  case FP_NZERO:
+    s = 1; /* FALLTHRU */
+  case FP_PZERO:
+    e = 0; break;
+  case FP_NNORM:
+  case FP_NDENORM:
+    s = 1; d = fabs(d); break;
+  case FP_PNORM:
+  case FP_PDENORM:
+    break;
+  default:
+    if(d<0.0) {
+      s = 1;
+      d = fabs(d);
+    }
+    break;
+  }
+#else
+#ifdef HAVE_ISINF
+  if(isinf(d))
+    e = maxexp;
+  else
+#endif
+#ifdef HAVE_ISNAN
+  if(isnan(d)) {
+    e = maxexp; f = maxf;
+  } else
+#endif
+#ifdef HAVE_ISZERO
+  if(iszero(d))
+    e = 0;
+  else
+#endif
+#ifdef HAVE_FINITE
+  if(!finite(d))
+    e = maxexp;
+#endif
+  ; /* Terminate any remaining else */
+#ifdef HAVE_SIGNBIT
+  if((s = signbit(d)))
+    d = fabs(d);
+#else
+  if(d<0.0) {
+    s = 1;
+    d = fabs(d);
+  }
+#endif
+#endif
+
+  if(e<0) {
+    d = FREXP(d, &e);
+    if(d == 1.0) {
+      d=0.5;
+      e++;
+    }
+    if(d == 0.0) {
+      e = 0;
+      f = 0;
+    } else if(sz==4) {
+      e += 126;
+      d *= 16777216.0;
+      if(e<=0) {
+	d = LDEXP(d, e-1);
+	e = 0;
+      }
+      f = ((INT32)floor(d))&maxf;
+    } else {
+      double d2;
+      e += 1022;
+      d *= 2097152.0;
+      if(e<=0) {
+	d = LDEXP(d, e-1);
+	e = 0;
+      }
+      d2 = floor(d);
+      f = ((INT32)d2)&maxf;
+      d -= d2;
+      d += 1.0;
+      extra_f = (unsigned INT32)(floor(d * 4294967296.0)-4294967296.0);
+    }
+
+    if(e>=maxexp) {
+      e = maxexp;
+      f = extra_f = 0;
+    }
+  }
+
+  if(sz==4) {
+    b[0] = (s? 128:0)|((e&0xfe)>>1);
+    b[1] = ((e&1)<<7)|((f&0x7f0000)>>16);
+    b[2] = (f&0xff00)>>8;
+    b[3] = f&0xff;
+  } else {
+    b[0] = (s? 128:0)|((e&0x7f0)>>4);
+    b[1] = ((e&0xf)<<4)|((f&0x0f0000)>>16);
+    b[2] = (f&0xff00)>>8;
+    b[3] = f&0xff;
+    b[4] = (extra_f&0xff000000)>>24;
+    b[5] = (extra_f&0xff0000)>>16;
+    b[6] = (extra_f&0xff00)>>8;
+    b[7] = extra_f&0xff;
+  }
+}
+#endif
+
 /* Position a string inside a field with fill */
 
 INLINE static void fix_field(char *b,
@@ -716,6 +900,8 @@ static string low_pike_sprintf(char *format,
       case 'e':
       case 'f':
       case 'g':
+      case 'E':
+      case 'G':
 	DO_OP();
 	fsp->b=(char *)xalloc(100+MAXIMUM(fsp->width,8)+
 			      MAXIMUM(fsp->precision,3));
@@ -728,6 +914,58 @@ static string low_pike_sprintf(char *format,
 	fsp->fi_free_string=fsp->b;
 	break;
 
+      case 'F':
+      {
+        INT32 l;
+#ifdef DOUBLE_IS_IEEE_LITTLE
+	double td;
+#endif
+        DO_OP();
+        l=4;
+        if(fsp->width > 0) l=fsp->width;
+	if(l != 4 && l != 8)
+	  sprintf_error("Invalid IEEE witdh %d.\n", l);
+	fsp->b=(char *)alloca(l);
+	fsp->len=l;
+	GET_FLOAT(tf);
+	switch(l) {
+	case 4:
+#ifdef FLOAT_IS_IEEE_BIG
+	  *((float*)fsp->b) = tf;
+#else
+#ifdef FLOAT_IS_IEEE_LITTLE
+	  fsp->b[0] = ((char *)&tf)[3];
+	  fsp->b[1] = ((char *)&tf)[2];
+	  fsp->b[2] = ((char *)&tf)[1];
+	  fsp->b[3] = ((char *)&tf)[0];
+#else
+	  low_write_IEEE_float(fsp->b, (double)tf, 4);
+#endif
+#endif
+	  break;
+	case 8:
+#ifdef DOUBLE_IS_IEEE_BIG
+	  *((double*)fsp->b) = (double)tf;
+#else
+#ifdef DOUBLE_IS_IEEE_LITTLE
+	  td = (double)tf;
+
+	  fsp->b[0] = ((char *)&td)[7];
+	  fsp->b[1] = ((char *)&td)[6];
+	  fsp->b[2] = ((char *)&td)[5];
+	  fsp->b[3] = ((char *)&td)[4];
+	  fsp->b[4] = ((char *)&td)[3];
+	  fsp->b[5] = ((char *)&td)[2];
+	  fsp->b[6] = ((char *)&td)[1];
+	  fsp->b[7] = ((char *)&td)[0];
+#else
+	  low_write_IEEE_float(fsp->b, (double)tf, 8);
+#endif
+#endif
+	}
+	break;
+      }
+
       case 'O':
       {
 	string s;
diff --git a/src/modules/sprintf/testsuite.in b/src/modules/sprintf/testsuite.in
index 5239a2129643c7828b494a38778ad6bfd406c892..cc95418f79dc9ddb141e81b9df0a5b1d0d41d1e9 100644
--- a/src/modules/sprintf/testsuite.in
+++ b/src/modules/sprintf/testsuite.in
@@ -63,6 +63,28 @@ test_true([[sprintf("%{%{%s%}\n%}",({({({"hej"})}),({({"hop"})})}))]])
 
 test_eq([[sprintf("%{%d %d %d\n%}",({ ({1,2,3}), ({4,5,6}) }) )]],"1 2 3\n4 5 6\n")
 
+test_eq([[sprintf("%4F", 0.0)]], "\000\000\000\000")
+test_eq([[sprintf("%4F", 1.0)]], "\077\200\000\000")
+test_eq([[sprintf("%4F", 0.5)]], "\077\000\000\000")
+test_eq([[sprintf("%4F", 2.0)]], "\100\000\000\000")
+test_eq([[sprintf("%4F", 1.5)]], "\077\300\000\000")
+test_eq([[sprintf("%4F", 1048576.125)]], "\111\200\000\001")
+test_eq([[sprintf("%4F", -17.5)]], "\301\214\000\000")
+test_eq([[sprintf("%4F", pow(2.0,-128.0))]], "\000\040\000\000")
+test_eq([[sprintf("%4F", 0.033)]], "\075\007\053\002")
+test_eq([[sprintf("%4F", pow(2.0,128.0))]], "\177\200\000\000")
+test_eq([[sprintf("%8F", 0.0)]], "\000\000\000\000\000\000\000\000")
+test_eq([[sprintf("%8F", 1.0)]], "\077\360\000\000\000\000\000\000")
+test_eq([[sprintf("%8F", 0.5)]], "\077\340\000\000\000\000\000\000")
+test_eq([[sprintf("%8F", 2.0)]], "\100\000\000\000\000\000\000\000")
+test_eq([[sprintf("%8F", 1.5)]], "\077\370\000\000\000\000\000\000")
+test_eq([[sprintf("%8F", 1048576.125)]], "\101\060\000\000\040\000\000\000")
+test_eq([[sprintf("%8F", -17.5)]], "\300\061\200\000\000\000\000\000")
+test_eq([[sprintf("%8F", pow(2.0,-128.0))]], "\067\360\000\000\000\000\000\000")
+test_eq([[sprintf("%8F", 0.032999999821186065673828125)]], "\077\240\345\140\100\000\000\000")
+test_eq([[sprintf("%8F", pow(2.0,1024.0))]], "\177\360\000\000\000\000\000\000")
+
+
 dnl . : and ; hasn't been tested
 dnl ^, @ and _ hasn't been tested yet
 test_eval_error(sprintf("%d"))