Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1988-1991 Apple Computer, Inc.
2
 * All Rights Reserved.
3
 *
4
 * Warranty Information
5
 * Even though Apple has reviewed this software, Apple makes no warranty
6
 * or representation, either express or implied, with respect to this
7
 * software, its quality, accuracy, merchantability, or fitness for a
8
 * particular purpose.  As a result, this software is provided "as is,"
9
 * and you, its user, are assuming the entire risk as to its quality
10
 * and accuracy.
11
 *
12
 * This code may be used and freely distributed as long as it includes
13
 * this copyright notice and the warranty information.
14
 *
15
 *
16
 * Motorola processors (Macintosh, Sun, Sparc, MIPS, etc)
17
 * pack bytes from high to low (they are big-endian).
18
 * Use the HighLow routines to match the native format
19
 * of these machines.
20
 *
21
 * Intel-like machines (PCs, Sequent)
22
 * pack bytes from low to high (the are little-endian).
23
 * Use the LowHigh routines to match the native format
24
 * of these machines.
25
 *
26
 * These routines have been tested on the following machines:
27
 *	Apple Macintosh, MPW 3.1 C compiler
28
 *	Apple Macintosh, THINK C compiler
29
 *	Silicon Graphics IRIS, MIPS compiler
30
 *	Cray X/MP and Y/MP
31
 *	Digital Equipment VAX
32
 *
33
 *
34
 * Implemented by Malcolm Slaney and Ken Turkowski.
35
 *
36
 * Malcolm Slaney contributions during 1988-1990 include big- and little-
37
 * endian file I/O, conversion to and from Motorola's extended 80-bit
38
 * floating-point format, and conversions to and from IEEE single-
39
 * precision floating-point format.
40
 *
41
 * In 1991, Ken Turkowski implemented the conversions to and from
42
 * IEEE double-precision format, added more precision to the extended
43
 * conversions, and accommodated conversions involving +/- infinity,
44
 * NaN's, and denormalized numbers.
45
 *
46
 * $Id: portableio.c,v 1.11 2001/01/07 23:47:38 markt Exp $
47
 */
48
 
49
#ifdef HAVE_CONFIG_H
50
# include <config.h>
51
#endif
52
 
53
#include	<stdio.h>
54
#if defined(__riscos__) && defined(FPA10)
55
#include	"ymath.h"
56
#else
57
#include	<math.h>
58
#endif
59
#include	"portableio.h"
60
 
61
#ifdef WITH_DMALLOC
62
#include <dmalloc.h>
63
#endif
64
 
65
/****************************************************************
66
 * Big/little-endian independent I/O routines.
67
 ****************************************************************/
68
 
69
/*
70
 * It is a hoax to call this code portable-IO:
71
 * 
72
 *   - It doesn't work on machines with CHAR_BIT != 8
73
 *   - it also don't test this error condition
74
 *   - otherwise it tries to handle CHAR_BIT != 8 by things like 
75
 *     masking 'putc(i&0xff,fp)'
76
 *   - It doesn't handle EOF in any way
77
 *   - it only works with ints with 32 or more bits
78
 *   - It is a collection of initial buggy code with patching the known errors
79
 *     instead of CORRECTING them! 
80
 *     For that see comments on the old Read16BitsHighLow()
81
 */
82
 
83
#ifdef KLEMM_36
84
 
85
signed int    ReadByte ( FILE* fp )
86
{
87
    int  result = getc (fp);
88
    return result == EOF  ?  0  :  (signed char) (result & 0xFF);
89
}
90
 
91
unsigned int  ReadByteUnsigned ( FILE* fp )
92
{
93
    int  result = getc (fp);
94
    return result == EOF  ?  0  :  (unsigned char) (result & 0xFF);
95
}
96
 
97
#else
98
 
99
int
100
ReadByte(FILE *fp)
101
{
102
	int	result;
103
 
104
	result = getc(fp) & 0xff;
105
	if (result & 0x80)
106
		result = result - 0x100;
107
	return result;
108
}
109
 
110
#endif
111
 
112
#ifdef KLEMM_36
113
 
114
int  Read16BitsLowHigh ( FILE* fp )
115
{
116
    int  low  = ReadByteUnsigned (fp);
117
    int  high = ReadByte         (fp);
118
 
119
    return (high << 8) | low;
120
}
121
 
122
#else
123
int
124
Read16BitsLowHigh(FILE *fp)
125
{
126
	int	first, second, result;
127
 
128
	first = 0xff & getc(fp);
129
	second = 0xff & getc(fp);
130
 
131
	result = (second << 8) + first;
132
#ifndef	THINK_C42
133
	if (result & 0x8000)
134
		result = result - 0x10000;
135
#endif	/* THINK_C */
136
	return(result);
137
}
138
#endif
139
 
140
 
141
#ifdef KLEMM_36
142
 
143
int  Read16BitsHighLow ( FILE* fp )
144
{
145
    int  high = ReadByte         (fp);
146
    int  low  = ReadByteUnsigned (fp);
147
 
148
    return (high << 8) | low;
149
}
150
 
151
#else
152
int
153
Read16BitsHighLow(FILE *fp)
154
{
155
	int	first, second, result;
156
 
157
        /* Reads the High bits, the value is -128...127 
158
	 * (which gave after upscaling the -32768...+32512
159
	 * Why this value is not converted to signed char?
160
	 */
161
        first = 0xff & getc(fp);
162
        /* Reads the Lows bits, the value is 0...255 
163
	 * This is correct. This value gives an additional offset
164
	 * for the High bits
165
	 */
166
	second = 0xff & getc(fp);
167
 
168
        /* This is right */
169
	result = (first << 8) + second;
170
 
171
        /* Now we are starting to correct the nasty bug of the first instruction
172
	 * The value of the high bits is wrong. Always. So we must correct this
173
	 * value. This seems to be not necessary for THINK_C42. This is either
174
	 * a 16 bit compiler with 16 bit ints (where this bug is hidden and 0x10000
175
	 * is not in the scope of an int) or it is not a C compiler, but only a
176
	 * C like compiler. In the first case the '#ifndef THINK_C42' is wrong
177
	 * because it's not a property of the THINK_C42 compiler, but of all compilers
178
	 * with sizeof(int)*CHAR_BIT < 18.
179
	 * Another nasty thing is that the rest of the code doesn't work for 16 bit ints,
180
	 * so this patch don't solve the 16 bit problem.
181
         */
182
#ifndef	THINK_C42
183
	if (result & 0x8000)
184
		result = result - 0x10000;
185
#endif	/* THINK_C */
186
	return(result);
187
}
188
#endif
189
 
190
void
191
Write8Bits(FILE *fp, int i)
192
{
193
	putc(i&0xff,fp);
194
}
195
 
196
 
197
void
198
Write16BitsLowHigh(FILE *fp, int i)
199
{
200
	putc(i&0xff,fp);
201
	putc((i>>8)&0xff,fp);
202
}
203
 
204
 
205
void
206
Write16BitsHighLow(FILE *fp, int i)
207
{
208
	putc((i>>8)&0xff,fp);
209
	putc(i&0xff,fp);
210
}
211
 
212
#ifdef KLEMM_36
213
 
214
int  Read24BitsHighLow ( FILE* fp )
215
{
216
    int  high = ReadByte         (fp);
217
    int  med  = ReadByteUnsigned (fp);
218
    int  low  = ReadByteUnsigned (fp);
219
 
220
    return (high << 16) | (med << 8) | low;
221
}
222
 
223
#else
224
int
225
Read24BitsHighLow(FILE *fp)
226
{
227
	int	first, second, third;
228
	int	result;
229
 
230
	first = 0xff & getc(fp);
231
	second = 0xff & getc(fp);
232
	third = 0xff & getc(fp);
233
 
234
	result = (first << 16) + (second << 8) + third;
235
	if (result & 0x800000)
236
		result = result - 0x1000000;
237
	return(result);
238
}
239
#endif
240
 
241
#define	Read32BitsLowHigh(f)	Read32Bits(f)
242
 
243
#ifdef KLEMM_36
244
 
245
int  Read32Bits ( FILE* fp )
246
{
247
    int  low  = ReadByteUnsigned (fp);
248
    int  medl = ReadByteUnsigned (fp);
249
    int  medh = ReadByteUnsigned (fp);
250
    int  high = ReadByte         (fp);
251
 
252
    return (high << 24) | (medh << 16) | (medl << 8) | low;
253
}
254
 
255
#else
256
 
257
int
258
Read32Bits(FILE *fp)
259
{
260
	int	first, second, result;
261
 
262
	first = 0xffff & Read16BitsLowHigh(fp);
263
	second = 0xffff & Read16BitsLowHigh(fp);
264
 
265
	result = (second << 16) + first;
266
#ifdef	CRAY
267
	if (result & 0x80000000)
268
		result = result - 0x100000000;
269
#endif	/* CRAY */
270
	return(result);
271
}
272
#endif
273
 
274
 
275
#ifdef KLEMM_36
276
 
277
int  Read32BitsHighLow ( FILE* fp )
278
{
279
    int  high = ReadByte         (fp);
280
    int  medh = ReadByteUnsigned (fp);
281
    int  medl = ReadByteUnsigned (fp);
282
    int  low  = ReadByteUnsigned (fp);
283
 
284
    return (high << 24) | (medh << 16) | (medl << 8) | low;
285
}
286
 
287
#else
288
 
289
int
290
Read32BitsHighLow(FILE *fp)
291
{
292
	int	first, second, result;
293
 
294
	first = 0xffff & Read16BitsHighLow(fp);
295
	second = 0xffff & Read16BitsHighLow(fp);
296
 
297
	result = (first << 16) + second;
298
#ifdef	CRAY
299
	if (result & 0x80000000)
300
		result = result - 0x100000000;
301
#endif
302
	return(result);
303
}
304
 
305
#endif
306
 
307
void
308
Write32Bits(FILE *fp, int i)
309
{
310
	Write16BitsLowHigh(fp,(int)(i&0xffffL));
311
	Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));
312
}
313
 
314
 
315
void
316
Write32BitsLowHigh(FILE *fp, int i)
317
{
318
	Write16BitsLowHigh(fp,(int)(i&0xffffL));
319
	Write16BitsLowHigh(fp,(int)((i>>16)&0xffffL));
320
}
321
 
322
 
323
void
324
Write32BitsHighLow(FILE *fp, int i)
325
{
326
	Write16BitsHighLow(fp,(int)((i>>16)&0xffffL));
327
	Write16BitsHighLow(fp,(int)(i&0xffffL));
328
}
329
 
330
#ifdef KLEMM_36
331
void ReadBytes (FILE     *fp, char *p, int n) 
332
{
333
    memset ( p, 0, n );
334
    fread  ( p, 1, n, fp );
335
}
336
#else
337
void ReadBytes(FILE	*fp, char *p, int n)
338
{
339
	/* What about fread? */
340
 
341
	while (!feof(fp) & (n-- > 0))
342
		*p++ = getc(fp);
343
}
344
#endif
345
 
346
void ReadBytesSwapped(FILE *fp, char *p, int n)
347
{
348
	register char	*q = p;
349
 
350
	/* What about fread? */
351
 
352
	while (!feof(fp) & (n-- > 0))
353
		*q++ = getc(fp);
354
 
355
        /* If not all bytes could be read, the resorting is different
356
	 * from the normal resorting. Is this intention or another bug?
357
	 */
358
	for (q--; p < q; p++, q--){
359
		n = *p;
360
		*p = *q;
361
		*q = n;
362
	}
363
}
364
 
365
#ifdef KLEMM_36
366
void WriteBytes(FILE *fp, char *p, int n)
367
{
368
    /* return n == */
369
    fwrite ( p, 1, n, fp );
370
}
371
#else
372
void WriteBytes(FILE *fp, char *p, int n)
373
{
374
        /* No error condition checking */
375
        while (n-- > 0)
376
		putc(*p++, fp);
377
}
378
#endif
379
#ifdef KLEMM_36
380
void WriteBytesSwapped(FILE *fp, char *p, int n)
381
{
382
    p += n;
383
    while ( n-- > 0 )
384
	putc ( *--p, fp );
385
}
386
#else
387
void WriteBytesSwapped(FILE *fp, char *p, int n)
388
{
389
	p += n-1;
390
	while (n-- > 0)
391
		putc(*p--, fp);
392
}
393
#endif
394
 
395
 
396
 
397
/****************************************************************
398
 * The following two routines make up for deficiencies in many
399
 * compilers to convert properly between unsigned integers and
400
 * floating-point.  Some compilers which have this bug are the
401
 * THINK_C compiler for the Macintosh and the C compiler for the
402
 * Silicon Graphics MIPS-based Iris.
403
 ****************************************************************/
404
 
405
#ifdef applec	/* The Apple C compiler works */
406
# define FloatToUnsigned(f)	((unsigned long)(f))
407
# define UnsignedToFloat(u)	((double)(u))
408
#else /* applec */
409
# define FloatToUnsigned(f)	((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1))
410
# define UnsignedToFloat(u)	(((double)((long)((u) - 2147483647L - 1))) + 2147483648.0)
411
#endif /* applec */
412
/****************************************************************
413
 * Extended precision IEEE floating-point conversion routines
414
 ****************************************************************/
415
 
416
double
417
ConvertFromIeeeExtended(char* bytes)
418
{
419
	double	f;
420
	long	expon;
421
	unsigned long hiMant, loMant;
422
 
423
#ifdef	TEST
424
printf("ConvertFromIEEEExtended(%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx,%lx\r",
425
	(long)bytes[0], (long)bytes[1], (long)bytes[2], (long)bytes[3],
426
	(long)bytes[4], (long)bytes[5], (long)bytes[6],
427
	(long)bytes[7], (long)bytes[8], (long)bytes[9]);
428
#endif
429
 
430
	expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
431
	hiMant	=	((unsigned long)(bytes[2] & 0xFF) << 24)
432
			|	((unsigned long)(bytes[3] & 0xFF) << 16)
433
			|	((unsigned long)(bytes[4] & 0xFF) << 8)
434
			|	((unsigned long)(bytes[5] & 0xFF));
435
	loMant	=	((unsigned long)(bytes[6] & 0xFF) << 24)
436
			|	((unsigned long)(bytes[7] & 0xFF) << 16)
437
			|	((unsigned long)(bytes[8] & 0xFF) << 8)
438
			|	((unsigned long)(bytes[9] & 0xFF));
439
 
440
        /* This case should also be called if the number is below the smallest
441
	 * positive double variable */
442
	if (expon == 0 && hiMant == 0 && loMant == 0) {
443
		f = 0;
444
	}
445
	else {
446
	        /* This case should also be called if the number is too large to fit into 
447
		 * a double variable */
448
 
449
		if (expon == 0x7FFF) {	/* Infinity or NaN */
450
			f = HUGE_VAL;
451
		}
452
		else {
453
			expon -= 16383;
454
			f  = ldexp(UnsignedToFloat(hiMant), (int) (expon -= 31));
455
			f += ldexp(UnsignedToFloat(loMant), (int) (expon -= 32));
456
		}
457
	}
458
 
459
	if (bytes[0] & 0x80)
460
		return -f;
461
	else
462
		return f;
463
}
464
 
465
 
466
 
467
 
468
 
469
double
470
ReadIeeeExtendedHighLow(FILE *fp)
471
{
472
	char	bytes [10];
473
 
474
	ReadBytes ( fp, bytes, 10 );
475
	return ConvertFromIeeeExtended ( bytes );
476
}
477