summaryrefslogtreecommitdiffstats
path: root/src/isode/psap/prim2real.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/isode/psap/prim2real.c')
-rw-r--r--src/isode/psap/prim2real.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/isode/psap/prim2real.c b/src/isode/psap/prim2real.c
new file mode 100644
index 000000000..b30d92a05
--- /dev/null
+++ b/src/isode/psap/prim2real.c
@@ -0,0 +1,151 @@
+/* prim2real.c - presentation element to real */
+
+#ifndef lint
+static char *rcsid = "$Header$";
+#endif
+
+/*
+ * $Header$
+ *
+ * Contributed by Julian Onions, Nottingham University.
+ * July 1989 - this stuff is awful. If you're going to use it seriously then
+ * write a machine specific version rather than any attempt at portability.
+ *
+ *
+ * $Log$
+ * Revision 1.1 1994/06/10 03:33:50 eichin
+ * autoconfed isode for kerberos work
+ *
+ * Revision 1.1 1994/06/01 00:38:04 eichin
+ * add psap too
+ *
+ * Revision 8.0 91/07/17 12:47:04 isode
+ * Release 7.0
+ *
+ *
+ */
+
+/*
+ * NOTICE
+ *
+ * Acquisition, use, and distribution of this module and related
+ * materials are subject to the restrictions of a license agreement.
+ * Consult the Preface in the User's Manual for the full terms of
+ * this agreement.
+ *
+ */
+
+
+/* LINTLIBRARY */
+
+#include "psap.h"
+
+/* */
+
+static double decode_binary (), decode_decimal ();
+
+double prim2real (pe)
+register PE pe;
+{
+ if (pe -> pe_form != PE_FORM_PRIM)
+ return pe_seterr (pe, PE_ERR_PRIM, NOTOK);
+ if (pe -> pe_len == 0)
+ return 0.0;
+ if (pe -> pe_prim == NULLPED)
+ return pe_seterr (pe, PE_ERR_PRIM, NOTOK);
+
+ if (pe -> pe_len > sizeof (double) + 1)
+ return pe_seterr (pe, PE_ERR_OVER, NOTOK);
+
+ pe -> pe_errno = PE_ERR_NONE; /* in case it's -1 */
+
+ if ((*(pe -> pe_prim) & 0x80) == 0x80)
+ return decode_binary (pe);
+
+ switch (*(pe -> pe_prim) & PE_REAL_FLAGS) {
+ case PE_REAL_DECENC:
+ return decode_decimal (pe);
+
+ case PE_REAL_SPECENC:
+ if (pe -> pe_len > 1)
+ return pe_seterr (pe, PE_ERR_OVER, NOTOK);
+
+ switch (*(pe -> pe_prim)) {
+ case PE_REAL_MINUSINF:
+ return HUGE;
+ case PE_REAL_PLUSINF:
+ return -HUGE;
+ default:
+ return pe_seterr (pe, PE_ERR_NOSUPP, NOTOK);
+ }
+ }
+ /* NOTREACHED */
+}
+
+/* */
+
+static double decode_binary (pe)
+PE pe;
+{
+ int sign, base, factor;
+ int exponent, i;
+ double mantissa, di;
+ PElementData dp, ep;
+
+ dp = pe -> pe_prim;
+ sign = (*dp & PE_REAL_B_S) ? -1 : 1;
+ switch (*dp & PE_REAL_B_BASE) {
+ case PE_REAL_B_B2:
+ base = 2;
+ break;
+
+ case PE_REAL_B_B8:
+ base = 8;
+ break;
+
+ case PE_REAL_B_B16:
+ base = 16;
+ break;
+ default:
+ return pe_seterr(pe, PE_ERR_NOSUPP, NOTOK);
+ }
+
+ factor = ((int)(*dp & PE_REAL_B_F)) >> 2;
+
+ exponent = (dp[1] & 0x80) ? (-1) : 0;
+ switch (*dp++ & PE_REAL_B_EXP) {
+ case PE_REAL_B_EF3:
+ exponent = (exponent << 8) | (*dp++ & 0xff);
+ /* fall */
+ case PE_REAL_B_EF2:
+ exponent = (exponent << 8) | (*dp++ & 0xff);
+ /* fall */
+ case PE_REAL_B_EF1:
+ exponent = (exponent << 8) | (*dp++ & 0xff);
+ break;
+ case PE_REAL_B_EF4:
+ i = *dp++ & 0xff;
+ if (i > sizeof(int))
+ return pe_seterr (pe, PE_ERR_OVER, NOTOK);
+ for (; i > 0; i--)
+ exponent = (exponent << 8) | (*dp++ & 0xff);
+ break;
+ }
+ for (di = 0.0, ep = pe -> pe_prim + pe -> pe_len; dp < ep;) {
+ di *= 1 << 8; ;
+ di += (int)(*dp++ & 0xff);
+ }
+
+ mantissa = sign * di * (1 << factor);
+ return mantissa * pow ((double)base, (double)exponent);
+}
+
+/* */
+
+static double decode_decimal (pe)
+PE pe;
+{
+ /* sorry - don't have the standard ! */
+ return pe_seterr (pe, PE_ERR_NOSUPP, NOTOK);
+}
+