fight with signalling NANs and floating point exceptions on alpha64

diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index 3316ee5..9380c9d 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -3,8 +3,9 @@
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #if	defined(__alpha)
-#define	_ISOC99_SOURCE	/* For quiet NAN, indirectly through bits/nan.h */
-#define	_BSD_SOURCE	/* To reintroduce finite(3) */
+#define	_ISOC99_SOURCE		/* For quiet NAN, through bits/nan.h */
+#define	_BSD_SOURCE		/* To reintroduce finite(3) */
+#include <sys/resource.h>	/* For INFINITY */
 #endif
 #include <asn_internal.h>
 #include <stdlib.h>	/* for strtod(3) */
@@ -16,10 +17,15 @@
 #undef	INT_MAX
 #define	INT_MAX	((int)(((unsigned int)-1) >> 1))
 
-static volatile double real_zero = 0.0;
+#if	!(defined(NAN) || defined(INFINITY))
+static volatile double real_zero __attribute__ ((unused)) = 0.0;
+#endif
 #ifndef	NAN
 #define	NAN	(real_zero/real_zero)
 #endif
+#ifndef	INFINITY
+#define	INFINITY	(1.0/real_zero)
+#endif
 
 /*
  * REAL basic type description.
@@ -54,12 +60,12 @@
 static struct specialRealValue_s {
 	char *string;
 	size_t length;
-	double dv;
+	long dv;
 } specialRealValue[] = {
 #define	SRV_SET(foo, val)	{ foo, sizeof(foo) - 1, val }
-	SRV_SET("<NOT-A-NUMBER/>", 0.0),
-	SRV_SET("<MINUS-INFINITY/>", -1.0),
-	SRV_SET("<PLUS-INFINITY/>", 1.0),
+	SRV_SET("<NOT-A-NUMBER/>", 0),
+	SRV_SET("<MINUS-INFINITY/>", -1),
+	SRV_SET("<PLUS-INFINITY/>", 1),
 #undef	SRV_SET
 };
 
@@ -269,12 +275,25 @@
 		for(i = 0; i < sizeof(specialRealValue)
 				/ sizeof(specialRealValue[0]); i++) {
 			struct specialRealValue_s *srv = &specialRealValue[i];
+			double dv;
+
 			if(srv->length != chunk_size
 			|| memcmp(srv->string, chunk_buf, chunk_size))
 				continue;
 
-			if(asn_double2REAL(st, srv->dv / real_zero))
-				return -1;
+			/*
+			 * It could've been done using
+			 * (double)srv->dv / real_zero,
+			 * but it summons fp exception on some platforms.
+			 */
+			switch(srv->dv) {
+			case -1: dv = - INFINITY; break;
+			case 0: dv = NAN;	break;
+			case 1: dv = INFINITY;	break;
+			default: return -1;
+			}
+
+			if(asn_double2REAL(st, dv)) return -1;
 
 			return chunk_size;
 		}
@@ -337,10 +356,10 @@
 
 		switch(st->buf[0]) {
 		case 0x40:	/* 01000000: PLUS-INFINITY */
-			*dbl_value = 1.0/real_zero;
+			*dbl_value = INFINITY;
 			return 0;
 		case 0x41:	/* 01000001: MINUS-INFINITY */
-			*dbl_value = -1.0/real_zero;
+			*dbl_value = - INFINITY;
 			return 0;
 			/*
 			 * The following cases are defined by
diff --git a/skeletons/tests/check-REAL.c b/skeletons/tests/check-REAL.c
index 094017d..dc8de26 100644
--- a/skeletons/tests/check-REAL.c
+++ b/skeletons/tests/check-REAL.c
@@ -88,8 +88,8 @@
 		printf("%02x", *p);
 	printf("] (ilogb %d)\n", ilogb(val));
 
-	printf("%.12f vs %.12f\n", orig_dbl, val);
-	assert(orig_dbl == val || (isnan(orig_dbl) && isnan(val)));
+	printf("%.12f vs %.12f\n", val, orig_dbl);
+	assert((isnan(orig_dbl) && isnan(val)) || val == orig_dbl);
 	printf("OK\n");
 
 	check_str_repr(val, sample, canonical_sample);
@@ -98,7 +98,7 @@
 uint8_t buf_1_0[]  = { 0x80, 0xcc, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 uint8_t buf_1_1[]  = { 0x80, 0xcc, 0x11, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a };
 uint8_t buf_3_14[] = { 0x80, 0xcd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f };
-/* These ones are very interesting! It checks mantissa overflow! */
+/* These ones are very interesting! They check mantissa overflow! */
 uint8_t buf_mo1[]  = { 0xC0, 0xc5, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3};
 uint8_t buf_mo2[]  = { 0x80, 0xbd, 0x19, 0x1e, 0xb8, 0x51, 0xeb, 0x85, 0x1f,3,2};
 
@@ -189,11 +189,11 @@
 	ret = asn_REAL2double(newst1, &value1);
 	assert(ret == 0);
 
-	assert(value0 == orig_value
-		|| (isnan(value0) && isnan(orig_value))
+	assert((isnan(value0) && isnan(orig_value))
+		|| value0 == orig_value
 		|| fuzzy);
-	assert(value1 == orig_value
-		|| (isnan(value1) && isnan(orig_value)));
+	assert((isnan(value1) && isnan(orig_value))
+		|| value1 == orig_value);
 
 	assert(newst0->size == st.size || fuzzy);
 	assert(newst1->size == st.size);
@@ -250,9 +250,18 @@
 	check_buf(buf_mo2, sizeof(buf_mo2),	3.14, "3.14", "3.14E0");
 
 
+#ifdef	NAN
+	check_xer(0, NAN);	/* "<NOT-A-NUMBER/>" */
+#else
 	check_xer(0, zero/zero);	/* "<NOT-A-NUMBER/>" */
+#endif
+#ifdef	INFINITY
+	check_xer(0, INFINITY);		/* "<PLUS-INFINITY/>" */
+	check_xer(0, -INFINITY);	/* "<MINUS-INFINITY/>" */
+#else
 	check_xer(0, 1.0/zero);		/* "<PLUS-INFINITY/>" */
 	check_xer(0, -1.0/zero);	/* "<MINUS-INFINITY/>" */
+#endif
 	check_xer(0, 1.0);
 	check_xer(0, -1.0);
 	check_xer(0, 1.5);