js-stream-sas7bdat 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding.gyp +58 -0
- package/dist/class/datasetSas7BDat.d.ts.map +1 -1
- package/dist/class/datasetSas7BDat.js +4 -3
- package/dist/class/datasetSas7BDat.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +16 -7
- package/prebuilds/darwin-arm64/js-stream-sas7bdat.node +0 -0
- package/prebuilds/darwin-x64/js-stream-sas7bdat.node +0 -0
- package/prebuilds/linux-arm64/js-stream-sas7bdat.node +0 -0
- package/prebuilds/linux-x64/js-stream-sas7bdat.node +0 -0
- package/prebuilds/win32-ia32/js-stream-sas7bdat.node +0 -0
- package/prebuilds/win32-x64/js-stream-sas7bdat.node +0 -0
- package/src/binding/ReadStat/LICENSE +19 -0
- package/src/binding/ReadStat/README.md +483 -0
- package/src/binding/ReadStat/src/CKHashTable.c +309 -0
- package/src/binding/ReadStat/src/CKHashTable.h +37 -0
- package/src/binding/ReadStat/src/readstat.h +627 -0
- package/src/binding/ReadStat/src/readstat_bits.c +69 -0
- package/src/binding/ReadStat/src/readstat_bits.h +20 -0
- package/src/binding/ReadStat/src/readstat_convert.c +36 -0
- package/src/binding/ReadStat/src/readstat_convert.h +2 -0
- package/src/binding/ReadStat/src/readstat_error.c +126 -0
- package/src/binding/ReadStat/src/readstat_iconv.h +15 -0
- package/src/binding/ReadStat/src/readstat_io_unistd.c +147 -0
- package/src/binding/ReadStat/src/readstat_io_unistd.h +11 -0
- package/src/binding/ReadStat/src/readstat_malloc.c +34 -0
- package/src/binding/ReadStat/src/readstat_malloc.h +4 -0
- package/src/binding/ReadStat/src/readstat_metadata.c +53 -0
- package/src/binding/ReadStat/src/readstat_parser.c +121 -0
- package/src/binding/ReadStat/src/readstat_strings.h +6 -0
- package/src/binding/ReadStat/src/readstat_value.c +178 -0
- package/src/binding/ReadStat/src/readstat_variable.c +123 -0
- package/src/binding/ReadStat/src/readstat_writer.c +677 -0
- package/src/binding/ReadStat/src/readstat_writer.h +21 -0
- package/src/binding/ReadStat/src/sas/ieee.c +420 -0
- package/src/binding/ReadStat/src/sas/ieee.h +6 -0
- package/src/binding/ReadStat/src/sas/readstat_sas.c +528 -0
- package/src/binding/ReadStat/src/sas/readstat_sas.h +131 -0
- package/src/binding/ReadStat/src/sas/readstat_sas7bcat_read.c +515 -0
- package/src/binding/ReadStat/src/sas/readstat_sas7bcat_write.c +218 -0
- package/src/binding/ReadStat/src/sas/readstat_sas7bdat_read.c +1304 -0
- package/src/binding/ReadStat/src/sas/readstat_sas7bdat_write.c +812 -0
- package/src/binding/ReadStat/src/sas/readstat_sas_rle.c +286 -0
- package/src/binding/ReadStat/src/sas/readstat_sas_rle.h +8 -0
- package/src/binding/ReadStat/src/sas/readstat_xport.c +28 -0
- package/src/binding/ReadStat/src/sas/readstat_xport.h +47 -0
- package/src/binding/ReadStat/src/sas/readstat_xport_parse_format.c +265 -0
- package/src/binding/ReadStat/src/sas/readstat_xport_parse_format.h +4 -0
- package/src/binding/ReadStat/src/sas/readstat_xport_parse_format.rl +68 -0
- package/src/binding/ReadStat/src/sas/readstat_xport_read.c +777 -0
- package/src/binding/ReadStat/src/sas/readstat_xport_write.c +561 -0
- package/src/binding/readstat_binding.cc +393 -0
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
#include <stdint.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
|
|
4
|
+
#include "ieee.h"
|
|
5
|
+
#include "../readstat_bits.h"
|
|
6
|
+
|
|
7
|
+
/* These routines are modified versions of those found in SAS publication TS-140,
|
|
8
|
+
* "RECORD LAYOUT OF A SAS VERSION 5 OR 6 DATA SET IN SAS TRANSPORT (XPORT) FORMAT"
|
|
9
|
+
* https://support.sas.com/techsup/technote/ts140.pdf
|
|
10
|
+
*
|
|
11
|
+
* Modifications include using stdint.h and supporting infinite IEEE values.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
static void xpt2ieee(unsigned char *xport, unsigned char *ieee);
|
|
15
|
+
static void ieee2xpt(unsigned char *ieee, unsigned char *xport);
|
|
16
|
+
|
|
17
|
+
#ifndef FLOATREP
|
|
18
|
+
#define FLOATREP get_native()
|
|
19
|
+
int get_native(void);
|
|
20
|
+
#endif
|
|
21
|
+
|
|
22
|
+
void memreverse(void *intp_void, int l) {
|
|
23
|
+
if (!machine_is_little_endian())
|
|
24
|
+
return;
|
|
25
|
+
|
|
26
|
+
int i,j;
|
|
27
|
+
char save;
|
|
28
|
+
char *intp = (char *)intp_void;
|
|
29
|
+
|
|
30
|
+
j = l/2;
|
|
31
|
+
for (i=0;i<j;i++) {
|
|
32
|
+
save = intp[i];
|
|
33
|
+
intp[i] = intp[l-i-1];
|
|
34
|
+
intp[l-i-1] = save;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
int cnxptiee(const void *from_bytes, int fromtype, void *to_bytes, int totype)
|
|
39
|
+
{
|
|
40
|
+
unsigned char *from = (unsigned char *)from_bytes;
|
|
41
|
+
unsigned char *to = (unsigned char *)to_bytes;
|
|
42
|
+
unsigned char temp[8];
|
|
43
|
+
int i;
|
|
44
|
+
|
|
45
|
+
if (fromtype == CN_TYPE_NATIVE) {
|
|
46
|
+
fromtype = FLOATREP;
|
|
47
|
+
}
|
|
48
|
+
switch(fromtype) {
|
|
49
|
+
case CN_TYPE_IEEEL :
|
|
50
|
+
if (totype == CN_TYPE_IEEEL)
|
|
51
|
+
break;
|
|
52
|
+
for (i=7;i>=0;i--) {
|
|
53
|
+
temp[7-i] = from[i];
|
|
54
|
+
}
|
|
55
|
+
from = temp;
|
|
56
|
+
fromtype = CN_TYPE_IEEEB;
|
|
57
|
+
/* Break intentionally omitted. */
|
|
58
|
+
case CN_TYPE_IEEEB :
|
|
59
|
+
/* Break intentionally omitted. */
|
|
60
|
+
case CN_TYPE_XPORT :
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
return(-1);
|
|
64
|
+
}
|
|
65
|
+
if (totype == CN_TYPE_NATIVE) {
|
|
66
|
+
totype = FLOATREP;
|
|
67
|
+
}
|
|
68
|
+
switch(totype) {
|
|
69
|
+
case CN_TYPE_XPORT :
|
|
70
|
+
case CN_TYPE_IEEEB :
|
|
71
|
+
case CN_TYPE_IEEEL :
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
return(-2);
|
|
75
|
+
}
|
|
76
|
+
if (fromtype == totype) {
|
|
77
|
+
memcpy(to,from,8);
|
|
78
|
+
return(0);
|
|
79
|
+
}
|
|
80
|
+
switch(fromtype) {
|
|
81
|
+
case CN_TYPE_IEEEB :
|
|
82
|
+
if (totype == CN_TYPE_XPORT)
|
|
83
|
+
ieee2xpt(from,to);
|
|
84
|
+
else memcpy(to,from,8);
|
|
85
|
+
break;
|
|
86
|
+
case CN_TYPE_XPORT :
|
|
87
|
+
xpt2ieee(from,to);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
if (totype == CN_TYPE_IEEEL) {
|
|
91
|
+
memcpy(temp,to,8);
|
|
92
|
+
for (i=7;i>=0;i--) {
|
|
93
|
+
to[7-i] = temp[i];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return(0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
int get_native(void) {
|
|
100
|
+
static unsigned char float_reps[][8] = {
|
|
101
|
+
{0x41,0x10,0x00,0x00,0x00,0x00,0x00,0x00},
|
|
102
|
+
{0x3f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00},
|
|
103
|
+
{0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x3f}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
static double one = 1.00;
|
|
107
|
+
|
|
108
|
+
int i,j;
|
|
109
|
+
j = sizeof(float_reps)/8;
|
|
110
|
+
for (i=0;i<j;i++) {
|
|
111
|
+
if (memcmp(&one,float_reps+i,8) == 0)
|
|
112
|
+
return(i+1);
|
|
113
|
+
}
|
|
114
|
+
return(-1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void xpt2ieee(unsigned char *xport, unsigned char *ieee) {
|
|
118
|
+
char temp[8];
|
|
119
|
+
register int shift;
|
|
120
|
+
register int nib;
|
|
121
|
+
uint32_t ieee1,ieee2;
|
|
122
|
+
uint32_t xport1 = 0;
|
|
123
|
+
uint32_t xport2 = 0;
|
|
124
|
+
|
|
125
|
+
memcpy(temp,xport,8);
|
|
126
|
+
memset(ieee,0,8);
|
|
127
|
+
|
|
128
|
+
if (*temp && memcmp(temp+1,ieee,7) == 0) {
|
|
129
|
+
ieee[0] = ieee[1] = 0xff;
|
|
130
|
+
ieee[2] = ~(*temp);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
memcpy(&xport1,temp,sizeof(uint32_t));
|
|
135
|
+
memreverse(&xport1,sizeof(uint32_t));
|
|
136
|
+
memcpy(&xport2,temp+4,sizeof(uint32_t));
|
|
137
|
+
memreverse(&xport2,sizeof(uint32_t));
|
|
138
|
+
|
|
139
|
+
/***************************************************************/
|
|
140
|
+
/* Translate IBM format floating point numbers into IEEE */
|
|
141
|
+
/* format floating point numbers. */
|
|
142
|
+
/* */
|
|
143
|
+
/* IEEE format: */
|
|
144
|
+
/* */
|
|
145
|
+
/* 6 5 0 */
|
|
146
|
+
/* 3 1 0 */
|
|
147
|
+
/* */
|
|
148
|
+
/* SEEEEEEEEEEEMMMM ............ MMMM */
|
|
149
|
+
/* */
|
|
150
|
+
/* Sign bit, 11 bits exponent, 52 bit fraction. Exponent is */
|
|
151
|
+
/* excess 1023. The fraction is multiplied by a power of 2 of */
|
|
152
|
+
|
|
153
|
+
/* the actual exponent. Normalized floating point numbers are */
|
|
154
|
+
/* represented with the binary point immediately to the left */
|
|
155
|
+
/* of the fraction with an implied "1" to the left of the */
|
|
156
|
+
/* binary point. */
|
|
157
|
+
/* */
|
|
158
|
+
/* IBM format: */
|
|
159
|
+
/* */
|
|
160
|
+
/* 6 5 0 */
|
|
161
|
+
/* 3 1 0 */
|
|
162
|
+
/* */
|
|
163
|
+
/* SEEEEEEEMMMM ......... MMMM */
|
|
164
|
+
/* */
|
|
165
|
+
/* Sign bit, 7 bit exponent, 56 bit fraction. Exponent is */
|
|
166
|
+
/* excess 64. The fraction is multiplied bya power of 16 of */
|
|
167
|
+
/* the actual exponent. Normalized floating point numbers are */
|
|
168
|
+
/* represented with the radix point immediately to the left of*/
|
|
169
|
+
/* the high order hex fraction digit. */
|
|
170
|
+
/* */
|
|
171
|
+
/* How do you translate from IBM format to IEEE? */
|
|
172
|
+
/* */
|
|
173
|
+
/* Translating back to ieee format from ibm is easier than */
|
|
174
|
+
/* going the other way. You lose at most, 3 bits of fraction, */
|
|
175
|
+
/* but nothing can be done about that. The only tricky parts */
|
|
176
|
+
/* are setting up the correct binary exponent from the ibm */
|
|
177
|
+
/* hex exponent, and removing the implicit "1" bit of the ieee*/
|
|
178
|
+
/* fraction (see vzctdbl). We must shift down the high order */
|
|
179
|
+
/* nibble of the ibm fraction until it is 1. This is the */
|
|
180
|
+
/* implicit 1. The bit is then cleared and the exponent */
|
|
181
|
+
/* adjusted by the number of positions shifted. A more */
|
|
182
|
+
/* thorough discussion is in vzctdbl.c. */
|
|
183
|
+
|
|
184
|
+
if ((xport1 & 0x7fffffff) == 0x7fffffff && xport2 == 0xffffffff) {
|
|
185
|
+
ieee1 = (xport1 & 0x80000000) | 0x7ff00000;
|
|
186
|
+
ieee2 = 0;
|
|
187
|
+
goto doret;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Get the first half of the ibm number without the exponent */
|
|
191
|
+
/* into the ieee number */
|
|
192
|
+
ieee1 = xport1 & 0x00ffffff;
|
|
193
|
+
|
|
194
|
+
/* get the second half of the ibm number into the second half */
|
|
195
|
+
/* of the ieee number . If both halves were 0. then just */
|
|
196
|
+
/* return since the ieee number is zero. */
|
|
197
|
+
if ((!(ieee2 = xport2)) && !xport1)
|
|
198
|
+
return;
|
|
199
|
+
|
|
200
|
+
/* The fraction bit to the left of the binary point in the */
|
|
201
|
+
/* ieee format was set and the number was shifted 0, 1, 2, or */
|
|
202
|
+
/* 3 places. This will tell us how to adjust the ibm exponent */
|
|
203
|
+
/* to be a power of 2 ieee exponent and how to shift the */
|
|
204
|
+
/* fraction bits to restore the correct magnitude. */
|
|
205
|
+
|
|
206
|
+
if ((nib = (int)xport1) & 0x00800000) {
|
|
207
|
+
shift = 3;
|
|
208
|
+
} else if (nib & 0x00400000) {
|
|
209
|
+
shift = 2;
|
|
210
|
+
} else if (nib & 0x00200000) {
|
|
211
|
+
shift = 1;
|
|
212
|
+
} else {
|
|
213
|
+
shift = 0;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (shift) {
|
|
217
|
+
/* shift the ieee number down the correct number of places */
|
|
218
|
+
/* then set the second half of the ieee number to be the */
|
|
219
|
+
/* second half of the ibm number shifted appropriately, */
|
|
220
|
+
/* ored with the bits from the first half that would have */
|
|
221
|
+
/* been shifted in if we could shift a double. All we are */
|
|
222
|
+
/* worried about are the low order 3 bits of the first */
|
|
223
|
+
/* half since we're only shifting by 1, 2, or 3. */
|
|
224
|
+
ieee1 >>= shift;
|
|
225
|
+
ieee2 = (xport2 >> shift) |
|
|
226
|
+
((xport1 & 0x00000007) << (29 + (3 - shift)));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* clear the 1 bit to the left of the binary point */
|
|
230
|
+
ieee1 &= 0xffefffff;
|
|
231
|
+
|
|
232
|
+
/* set the exponent of the ieee number to be the actual */
|
|
233
|
+
/* exponent plus the shift count + 1023. Or this into the */
|
|
234
|
+
/* first half of the ieee number. The ibm exponent is excess */
|
|
235
|
+
/* 64 but is adjusted by 65 since during conversion to ibm */
|
|
236
|
+
/* format the exponent is incremented by 1 and the fraction */
|
|
237
|
+
/* bits left 4 positions to the right of the radix point. */
|
|
238
|
+
ieee1 |=
|
|
239
|
+
(((((int32_t)(*temp & 0x7f) - 65) * 4) + shift + 1023) << 20) |
|
|
240
|
+
(xport1 & 0x80000000);
|
|
241
|
+
|
|
242
|
+
doret:
|
|
243
|
+
memreverse(&ieee1,sizeof(uint32_t));
|
|
244
|
+
memcpy(ieee,&ieee1,sizeof(uint32_t));
|
|
245
|
+
memreverse(&ieee2,sizeof(uint32_t));
|
|
246
|
+
memcpy(ieee+4,&ieee2,sizeof(uint32_t));
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/*-------------------------------------------------------------*/
|
|
251
|
+
/* Name: ieee2xpt */
|
|
252
|
+
/* Purpose: converts IEEE to transport */
|
|
253
|
+
/* Usage: rc = ieee2xpt(to_ieee,p_data); */
|
|
254
|
+
/* Notes: this routine is an adaptation of the wzctdbl routine */
|
|
255
|
+
/* from the Apollo. */
|
|
256
|
+
/*-------------------------------------------------------------*/
|
|
257
|
+
|
|
258
|
+
void ieee2xpt(unsigned char *ieee, unsigned char *xport) {
|
|
259
|
+
register int shift;
|
|
260
|
+
unsigned char misschar;
|
|
261
|
+
int ieee_exp;
|
|
262
|
+
uint32_t xport1,xport2;
|
|
263
|
+
uint32_t ieee1 = 0;
|
|
264
|
+
uint32_t ieee2 = 0;
|
|
265
|
+
|
|
266
|
+
char ieee8[8];
|
|
267
|
+
|
|
268
|
+
memcpy(ieee8,ieee,8);
|
|
269
|
+
|
|
270
|
+
/*------get 2 longs for shifting------------------------------*/
|
|
271
|
+
memcpy(&ieee1,ieee8,sizeof(uint32_t));
|
|
272
|
+
memreverse(&ieee1,sizeof(uint32_t));
|
|
273
|
+
memcpy(&ieee2,ieee8+4,sizeof(uint32_t));
|
|
274
|
+
memreverse(&ieee2,sizeof(uint32_t));
|
|
275
|
+
|
|
276
|
+
memset(xport,0,8);
|
|
277
|
+
|
|
278
|
+
/*-----if IEEE value is missing (1st 2 bytes are FFFF)-----*/
|
|
279
|
+
if (*ieee8 == (char)0xff && ieee8[1] == (char)0xff) {
|
|
280
|
+
misschar = ~ieee8[2];
|
|
281
|
+
*xport = (misschar == 0xD2) ? 0x6D : misschar;
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**************************************************************/
|
|
286
|
+
/* Translate IEEE floating point number into IBM format float */
|
|
287
|
+
/* */
|
|
288
|
+
/* IEEE format: */
|
|
289
|
+
/* */
|
|
290
|
+
/* 6 5 0 */
|
|
291
|
+
/* 3 1 0 */
|
|
292
|
+
/* */
|
|
293
|
+
/* SEEEEEEEEEEEMMMM ........ MMMM */
|
|
294
|
+
/* */
|
|
295
|
+
/* Sign bit, 11 bit exponent, 52 fraction. Exponent is excess */
|
|
296
|
+
/* 1023. The fraction is multiplied by a power of 2 of the */
|
|
297
|
+
/* actual exponent. Normalized floating point numbers are */
|
|
298
|
+
/* represented with the binary point immediately to the left */
|
|
299
|
+
/* of the fraction with an implied "1" to the left of the */
|
|
300
|
+
/* binary point. */
|
|
301
|
+
/* */
|
|
302
|
+
/* IBM format: */
|
|
303
|
+
/* */
|
|
304
|
+
/* 6 5 0 */
|
|
305
|
+
/* 3 5 0 */
|
|
306
|
+
/* */
|
|
307
|
+
/* SEEEEEEEMMMM ......... MMMM */
|
|
308
|
+
/* */
|
|
309
|
+
/* Sign bit, 7 bit exponent, 56 bit fraction. Exponent is */
|
|
310
|
+
/* excess 64. The fraction is multiplied by a power of 16 of */
|
|
311
|
+
/* of the actual exponent. Normalized floating point numbers */
|
|
312
|
+
/* are presented with the radix point immediately to the left */
|
|
313
|
+
/* of the high order hex fraction digit. */
|
|
314
|
+
/* */
|
|
315
|
+
/* How do you translate from local to IBM format? */
|
|
316
|
+
/* */
|
|
317
|
+
/* The ieee format gives you a number that has a power of 2 */
|
|
318
|
+
/* exponent and a fraction of the form "1.<fraction bits>". */
|
|
319
|
+
/* The first step is to get that "1" bit back into the */
|
|
320
|
+
/* fraction. Right shift it down 1 position, set the high */
|
|
321
|
+
/* order bit and reduce the binary exponent by 1. Now we have */
|
|
322
|
+
|
|
323
|
+
/* a fraction that looks like ".1<fraction bits>" and it's */
|
|
324
|
+
/* ready to be shoved into ibm format. The ibm fraction has 4 */
|
|
325
|
+
/* more bits than the ieee, the ieee fraction must therefore */
|
|
326
|
+
/* be shifted left 4 positions before moving it in. We must */
|
|
327
|
+
/* also correct the fraction bits to account for the loss of 2*/
|
|
328
|
+
/* bits when converting from a binary exponent to a hex one */
|
|
329
|
+
/* (>> 2). We must shift the fraction left for 0, 1, 2, or 3 */
|
|
330
|
+
/* positions to maintain the proper magnitude. Doing */
|
|
331
|
+
/* conversion this way would tend to lose bits in the fraction*/
|
|
332
|
+
/* which is not desirable or necessary if we cheat a bit. */
|
|
333
|
+
/* First of all, we know that we are going to have to shift */
|
|
334
|
+
/* the ieee fraction left 4 places to put it in the right */
|
|
335
|
+
/* position; we won't do that, we'll just leave it where it is*/
|
|
336
|
+
/* and increment the ibm exponent by one, this will have the */
|
|
337
|
+
/* same effect and we won't have to do any shifting. Now, */
|
|
338
|
+
/* since we have 4 bits in front of the fraction to work with,*/
|
|
339
|
+
/* we won't lose any bits. We set the bit to the left of the */
|
|
340
|
+
/* fraction which is the implicit "1" in the ieee fraction. We*/
|
|
341
|
+
/* then adjust the fraction to account for the loss of bits */
|
|
342
|
+
/* when going to a hex exponent. This adjustment will never */
|
|
343
|
+
/* involve shifting by more than 3 positions so no bits are */
|
|
344
|
+
/* lost. */
|
|
345
|
+
|
|
346
|
+
/* Get ieee number less the exponent into the first half of */
|
|
347
|
+
/* the ibm number */
|
|
348
|
+
|
|
349
|
+
xport1 = ieee1 & 0x000fffff;
|
|
350
|
+
|
|
351
|
+
/* get the second half of the number into the second half of */
|
|
352
|
+
/* the ibm number and see if both halves are 0. If so, ibm is */
|
|
353
|
+
/* also 0 and we just return */
|
|
354
|
+
|
|
355
|
+
if ((!(xport2 = ieee2)) && !ieee1) {
|
|
356
|
+
ieee_exp = 0;
|
|
357
|
+
goto doret;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/* get the actual exponent value out of the ieee number. The */
|
|
361
|
+
/* ibm fraction is a power of 16 and the ieee fraction a power*/
|
|
362
|
+
/* of 2 (16 ** n == 2 ** 4n). Save the low order 2 bits since */
|
|
363
|
+
/* they will get lost when we divide the exponent by 4 (right */
|
|
364
|
+
/* shift by 2) and we will have to shift the fraction by the */
|
|
365
|
+
/* appropriate number of bits to keep the proper magnitude. */
|
|
366
|
+
shift = (int)
|
|
367
|
+
(ieee_exp = (int)(((ieee1 >> 16) & 0x7ff0) >> 4) - 1023)
|
|
368
|
+
& 3;
|
|
369
|
+
/* the ieee format has an implied "1" immediately to the left */
|
|
370
|
+
/* of the binary point. Show it in here. */
|
|
371
|
+
xport1 |= 0x00100000;
|
|
372
|
+
if (shift)
|
|
373
|
+
{
|
|
374
|
+
/* set the first half of the ibm number by shifting it left */
|
|
375
|
+
|
|
376
|
+
/* the appropriate number of bits and oring in the bits */
|
|
377
|
+
/* from the lower half that would have been shifted in (if */
|
|
378
|
+
/* we could shift a double). The shift count can never */
|
|
379
|
+
/* exceed 3, so all we care about are the high order 3 */
|
|
380
|
+
/* bits. We don't want sign extension so make sure it's an */
|
|
381
|
+
/* unsigned char. We'll shift either5, 6, or 7 places to */
|
|
382
|
+
/* keep 3, 2, or 1 bits. After that, shift the second half */
|
|
383
|
+
/* of the number the right number of places. We always get */
|
|
384
|
+
/* zero fill on left shifts. */
|
|
385
|
+
xport1 = (xport1 << shift) |
|
|
386
|
+
((unsigned char) (((ieee2 >> 24) & 0xE0) >>
|
|
387
|
+
(5 + (3 - shift))));
|
|
388
|
+
|
|
389
|
+
xport2 <<= shift;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* Now set the ibm exponent and the sign of the fraction. The */
|
|
393
|
+
/* power of 2 ieee exponent must be divided by 4 and made */
|
|
394
|
+
/* excess 64 (we add 65 here because of the position of the */
|
|
395
|
+
/* fraction bits, essentially 4 positions lower than they */
|
|
396
|
+
/* should be so we increment the ibm exponent). */
|
|
397
|
+
|
|
398
|
+
xport1 |=
|
|
399
|
+
|
|
400
|
+
(((ieee_exp >>2) + 65) | ((ieee1 >> 24) & 0x80)) << 24;
|
|
401
|
+
/* If the ieee exponent is greater than 248 or less than -260, */
|
|
402
|
+
/* then it cannot fit in the ibm exponent field. Send back the */
|
|
403
|
+
/* appropriate flag. */
|
|
404
|
+
|
|
405
|
+
doret:
|
|
406
|
+
if (ieee_exp < -260) {
|
|
407
|
+
memset(xport,0x00,8);
|
|
408
|
+
} else if (ieee_exp > 248) {
|
|
409
|
+
memset(xport+1,0xFF,7);
|
|
410
|
+
|
|
411
|
+
*xport = 0x7F | ((ieee1 >> 24) & 0x80);
|
|
412
|
+
} else {
|
|
413
|
+
memreverse(&xport1,sizeof(uint32_t));
|
|
414
|
+
memcpy(xport,&xport1,sizeof(uint32_t));
|
|
415
|
+
memreverse(&xport2,sizeof(uint32_t));
|
|
416
|
+
memcpy(xport+4,&xport2,sizeof(uint32_t));
|
|
417
|
+
}
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
|