1/* $Header$ */
2
3/*
4 * Copyright (c) 1988-1997 Sam Leffler
5 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and
8 * its documentation for any purpose is hereby granted without fee, provided
9 * that (i) the above copyright notices and this permission notice appear in
10 * all copies of the software and related documentation, and (ii) the names of
11 * Sam Leffler and Silicon Graphics may not be used in any advertising or
12 * publicity relating to the software without the specific, prior written
13 * permission of Sam Leffler and Silicon Graphics.
14 *
15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18 *
19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE.
25 */
26
27/*
28 * TIFF Library VMS-specific Routines.
29 */
30
31#include <stdlib.h>
32#include <unixio.h>
33#include "tiffiop.h"
34#if !HAVE_IEEEFP
35#include <math.h>
36#endif
37
38#ifdef VAXC
39#define	NOSHARE	noshare
40#else
41#define	NOSHARE
42#endif
43
44#ifdef __alpha
45/* Dummy entry point for backwards compatibility */
46void TIFFModeCCITTFax3(void){}
47#endif
48
49static tsize_t
50_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
51{
52	return (read((int) fd, buf, size));
53}
54
55static tsize_t
56_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
57{
58	return (write((int) fd, buf, size));
59}
60
61static toff_t
62_tiffSeekProc(thandle_t fd, toff_t off, int whence)
63{
64	return ((toff_t) lseek((int) fd, (off_t) off, whence));
65}
66
67static int
68_tiffCloseProc(thandle_t fd)
69{
70	return (close((int) fd));
71}
72
73#include <sys/stat.h>
74
75static toff_t
76_tiffSizeProc(thandle_t fd)
77{
78	struct stat sb;
79	return (toff_t) (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
80}
81
82#ifdef HAVE_MMAP
83#include <starlet.h>
84#include <fab.h>
85#include <secdef.h>
86
87/*
88 * Table for storing information on current open sections.
89 * (Should really be a linked list)
90 */
91#define MAX_MAPPED 100
92static int no_mapped = 0;
93static struct {
94	char *base;
95	char *top;
96	unsigned short channel;
97} map_table[MAX_MAPPED];
98
99/*
100 * This routine maps a file into a private section. Note that this
101 * method of accessing a file is by far the fastest under VMS.
102 * The routine may fail (i.e. return 0) for several reasons, for
103 * example:
104 * - There is no more room for storing the info on sections.
105 * - The process is out of open file quota, channels, ...
106 * - fd does not describe an opened file.
107 * - The file is already opened for write access by this process
108 *   or another process
109 * - There is no free "hole" in virtual memory that fits the
110 *   size of the file
111 */
112static int
113_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
114{
115	char name[256];
116	struct FAB fab;
117	unsigned short channel;
118	char *inadr[2], *retadr[2];
119	unsigned long status;
120	long size;
121
122	if (no_mapped >= MAX_MAPPED)
123		return(0);
124	/*
125	 * We cannot use a file descriptor, we
126	 * must open the file once more.
127	 */
128	if (getname((int)fd, name, 1) == NULL)
129		return(0);
130	/* prepare the FAB for a user file open */
131	fab = cc$rms_fab;
132	fab.fab$l_fop |= FAB$V_UFO;
133	fab.fab$b_fac = FAB$M_GET;
134	fab.fab$b_shr = FAB$M_SHRGET;
135	fab.fab$l_fna = name;
136	fab.fab$b_fns = strlen(name);
137	status = sys$open(&fab);	/* open file & get channel number */
138	if ((status&1) == 0)
139		return(0);
140	channel = (unsigned short)fab.fab$l_stv;
141	inadr[0] = inadr[1] = (char *)0; /* just an address in P0 space */
142	/*
143	 * Map the blocks of the file up to
144	 * the EOF block into virtual memory.
145	 */
146	size = _tiffSizeProc(fd);
147	status = sys$crmpsc(inadr, retadr, 0, SEC$M_EXPREG, 0,0,0, channel,
148		TIFFhowmany(size,512), 0,0,0);
149	if ((status&1) == 0){
150		sys$dassgn(channel);
151		return(0);
152	}
153	*pbase = (tdata_t) retadr[0];	/* starting virtual address */
154	/*
155	 * Use the size of the file up to the
156	 * EOF mark for UNIX compatibility.
157	 */
158	*psize = (toff_t) size;
159	/* Record the section in the table */
160	map_table[no_mapped].base = retadr[0];
161	map_table[no_mapped].top = retadr[1];
162	map_table[no_mapped].channel = channel;
163	no_mapped++;
164
165        return(1);
166}
167
168/*
169 * This routine unmaps a section from the virtual address space of
170 * the process, but only if the base was the one returned from a
171 * call to TIFFMapFileContents.
172 */
173static void
174_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
175{
176	char *inadr[2];
177	int i, j;
178
179	/* Find the section in the table */
180	for (i = 0;i < no_mapped; i++) {
181		if (map_table[i].base == (char *) base) {
182			/* Unmap the section */
183			inadr[0] = (char *) base;
184			inadr[1] = map_table[i].top;
185			sys$deltva(inadr, 0, 0);
186			sys$dassgn(map_table[i].channel);
187			/* Remove this section from the list */
188			for (j = i+1; j < no_mapped; j++)
189				map_table[j-1] = map_table[j];
190			no_mapped--;
191			return;
192		}
193	}
194}
195#else /* !HAVE_MMAP */
196static int
197_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
198{
199	return (0);
200}
201
202static void
203_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
204{
205}
206#endif /* !HAVE_MMAP */
207
208/*
209 * Open a TIFF file descriptor for read/writing.
210 */
211TIFF*
212TIFFFdOpen(int fd, const char* name, const char* mode)
213{
214	TIFF* tif;
215
216	tif = TIFFClientOpen(name, mode,
217	    (thandle_t) fd,
218	    _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
219	    _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
220	if (tif)
221		tif->tif_fd = fd;
222	return (tif);
223}
224
225/*
226 * Open a TIFF file for read/writing.
227 */
228TIFF*
229TIFFOpen(const char* name, const char* mode)
230{
231	static const char module[] = "TIFFOpen";
232	int m, fd;
233
234	m = _TIFFgetMode(mode, module);
235	if (m == -1)
236		return ((TIFF*)0);
237        if (m&O_TRUNC){
238                /*
239		 * There is a bug in open in VAXC. If you use
240		 * open w/ m=O_RDWR|O_CREAT|O_TRUNC the
241		 * wrong thing happens.  On the other hand
242		 * creat does the right thing.
243                 */
244                fd = creat((char *) /* bug in stdio.h */ name, 0666,
245		    "alq = 128", "deq = 64", "mbc = 32",
246		    "fop = tef");
247	} else if (m&O_RDWR) {
248		fd = open(name, m, 0666,
249		    "deq = 64", "mbc = 32", "fop = tef", "ctx = stm");
250	} else
251		fd = open(name, m, 0666, "mbc = 32", "ctx = stm");
252	if (fd < 0) {
253		TIFFError(module, "%s: Cannot open", name);
254		return ((TIFF*)0);
255	}
256	return (TIFFFdOpen(fd, name, mode));
257}
258
259tdata_t
260_TIFFmalloc(tsize_t s)
261{
262	return (malloc((size_t) s));
263}
264
265void
266_TIFFfree(tdata_t p)
267{
268	free(p);
269}
270
271tdata_t
272_TIFFrealloc(tdata_t p, tsize_t s)
273{
274	return (realloc(p, (size_t) s));
275}
276
277void
278_TIFFmemset(tdata_t p, int v, tsize_t c)
279{
280	memset(p, v, (size_t) c);
281}
282
283void
284_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
285{
286	memcpy(d, s, (size_t) c);
287}
288
289int
290_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
291{
292	return (memcmp(p1, p2, (size_t) c));
293}
294
295/*
296 * On the VAX, we need to make those global, writable pointers
297 * non-shareable, otherwise they would be made shareable by default.
298 * On the AXP, this brain damage has been corrected.
299 *
300 * I (Karsten Spang, krs@kampsax.dk) have dug around in the GCC
301 * manual and the GAS code and have come up with the following
302 * construct, but I don't have GCC on my VAX, so it is untested.
303 * Please tell me if it does not work.
304 */
305
306static void
307vmsWarningHandler(const char* module, const char* fmt, va_list ap)
308{
309	if (module != NULL)
310		fprintf(stderr, "%s: ", module);
311	fprintf(stderr, "Warning, ");
312	vfprintf(stderr, fmt, ap);
313	fprintf(stderr, ".\n");
314}
315
316NOSHARE TIFFErrorHandler _TIFFwarningHandler = vmsWarningHandler
317#if defined(VAX) && defined(__GNUC__)
318asm("_$$PsectAttributes_NOSHR$$_TIFFwarningHandler")
319#endif
320;
321
322static void
323vmsErrorHandler(const char* module, const char* fmt, va_list ap)
324{
325	if (module != NULL)
326		fprintf(stderr, "%s: ", module);
327	vfprintf(stderr, fmt, ap);
328	fprintf(stderr, ".\n");
329}
330
331NOSHARE TIFFErrorHandler _TIFFerrorHandler = vmsErrorHandler
332#if defined(VAX) && defined(__GNUC__)
333asm("_$$PsectAttributes_NOSHR$$_TIFFerrorHandler")
334#endif
335;
336
337
338#if !HAVE_IEEEFP
339/* IEEE floting point handling */
340
341typedef	struct ieeedouble {
342	u_long	mant2;			/* fix NDR: full 8-byte swap */
343	u_long	mant	: 20,
344		exp	: 11,
345		sign	: 1;
346} ieeedouble;
347typedef	struct ieeefloat {
348	u_long	mant	: 23,
349		exp	: 8,
350		sign	: 1;
351} ieeefloat;
352
353/*
354 * NB: These are D_FLOAT's, not G_FLOAT's. A G_FLOAT is
355 *  simply a reverse-IEEE float/double.
356 */
357
358typedef	struct {
359	u_long	mant1	: 7,
360		exp	: 8,
361		sign	: 1,
362		mant2	: 16,
363		mant3   : 16,
364		mant4   : 16;
365} nativedouble;
366typedef	struct {
367	u_long	mant1	: 7,
368		exp	: 8,
369		sign	: 1,
370		mant2	: 16;
371} nativefloat;
372
373typedef	union {
374	ieeedouble	ieee;
375	nativedouble	native;
376	char		b[8];
377	uint32		l[2];
378	double		d;
379} double_t;
380
381typedef	union {
382	ieeefloat	ieee;
383	nativefloat	native;
384	char		b[4];
385	uint32		l;
386	float		f;
387} float_t;
388
389#if defined(VAXC) || defined(DECC)
390#pragma inline(ieeetod,dtoieee)
391#endif
392
393/*
394 * Convert an IEEE double precision number to native double precision.
395 * The source is contained in two longwords, the second holding the sign,
396 * exponent and the higher order bits of the mantissa, and the first
397 * holding the rest of the mantissa as follows:
398 * (Note: It is assumed that the number has been eight-byte swapped to
399 * LSB first.)
400 *
401 * First longword:
402 *	32 least significant bits of mantissa
403 * Second longword:
404 *	0-19:	20 most significant bits of mantissa
405 *	20-30:	exponent
406 *	31:	sign
407 * The exponent is stored as excess 1023.
408 * The most significant bit of the mantissa is implied 1, and not stored.
409 * If the exponent and mantissa are zero, the number is zero.
410 * If the exponent is 0 (i.e. -1023) and the mantissa is non-zero, it is an
411 * unnormalized number with the most significant bit NOT implied.
412 * If the exponent is 2047, the number is invalid, in case the mantissa is zero,
413 * this means overflow (+/- depending of the sign bit), otherwise
414 * it simply means invalid number.
415 *
416 * If the number is too large for the machine or was specified as overflow,
417 * +/-HUGE_VAL is returned.
418 */
419INLINE static void
420ieeetod(double *dp)
421{
422	double_t source;
423	long sign,exp,mant;
424	double dmant;
425
426	source.ieee = ((double_t*)dp)->ieee;
427	sign = source.ieee.sign;
428	exp = source.ieee.exp;
429	mant = source.ieee.mant;
430
431	if (exp == 2047) {
432		if (mant)			/* Not a Number (NAN) */
433			*dp = HUGE_VAL;
434		else				/* +/- infinity */
435			*dp = (sign ? -HUGE_VAL : HUGE_VAL);
436		return;
437	}
438	if (!exp) {
439		if (!(mant || source.ieee.mant2)) {	/* zero */
440			*dp=0;
441			return;
442		} else {			/* Unnormalized number */
443			/* NB: not -1023, the 1 bit is not implied */
444			exp= -1022;
445		}
446	} else {
447		mant |= 1<<20;
448		exp -= 1023;
449	}
450	dmant = (((double) mant) +
451		((double) source.ieee.mant2) / (((double) (1<<16)) *
452		((double) (1<<16)))) / (double) (1<<20);
453	dmant = ldexp(dmant, exp);
454	if (sign)
455		dmant= -dmant;
456	*dp = dmant;
457}
458
459INLINE static void
460dtoieee(double *dp)
461{
462	double_t num;
463	double x;
464	int exp;
465
466	num.d = *dp;
467	if (!num.d) {			/* Zero is just binary all zeros */
468		num.l[0] = num.l[1] = 0;
469		return;
470	}
471
472	if (num.d < 0) {		/* Sign is encoded separately */
473		num.d = -num.d;
474		num.ieee.sign = 1;
475	} else {
476		num.ieee.sign = 0;
477	}
478
479	/* Now separate the absolute value into mantissa and exponent */
480	x = frexp(num.d, &exp);
481
482	/*
483	 * Handle cases where the value is outside the
484	 * range for IEEE floating point numbers.
485	 * (Overflow cannot happen on a VAX, but underflow
486	 * can happen for G float.)
487	 */
488	if (exp < -1022) {		/* Unnormalized number */
489		x = ldexp(x, -1023-exp);
490		exp = 0;
491	} else if (exp > 1023) {	/* +/- infinity */
492		x = 0;
493		exp = 2047;
494	} else {			/* Get rid of most significant bit */
495		x *= 2;
496		x -= 1;
497		exp += 1022; /* fix NDR: 1.0 -> x=0.5, exp=1 -> ieee.exp = 1023 */
498	}
499	num.ieee.exp = exp;
500
501	x *= (double) (1<<20);
502	num.ieee.mant = (long) x;
503	x -= (double) num.ieee.mant;
504	num.ieee.mant2 = (long) (x*((double) (1<<16)*(double) (1<<16)));
505
506	if (!(num.ieee.mant || num.ieee.exp || num.ieee.mant2)) {
507		/* Avoid negative zero */
508		num.ieee.sign = 0;
509	}
510	((double_t*)dp)->ieee = num.ieee;
511}
512
513/*
514 * Beware, these do not handle over/under-flow
515 * during conversion from ieee to native format.
516 */
517#define	NATIVE2IEEEFLOAT(fp) { \
518    float_t t; \
519    if (t.ieee.exp = (fp)->native.exp) \
520	t.ieee.exp += -129 + 127; \
521    t.ieee.sign = (fp)->native.sign; \
522    t.ieee.mant = ((fp)->native.mant1<<16)|(fp)->native.mant2; \
523    *(fp) = t; \
524}
525#define	IEEEFLOAT2NATIVE(fp) { \
526    float_t t; int v = (fp)->ieee.exp; \
527    if (v) v += -127 + 129;		/* alter bias of exponent */\
528    t.native.exp = v;			/* implicit truncation of exponent */\
529    t.native.sign = (fp)->ieee.sign; \
530    v = (fp)->ieee.mant; \
531    t.native.mant1 = v >> 16; \
532    t.native.mant2 = v;\
533    *(fp) = t; \
534}
535
536#define IEEEDOUBLE2NATIVE(dp) ieeetod(dp)
537
538#define NATIVE2IEEEDOUBLE(dp) dtoieee(dp)
539
540
541/*
542 * These unions are used during floating point
543 * conversions.  The above macros define the
544 * conversion operations.
545 */
546void
547TIFFCvtIEEEFloatToNative(TIFF* tif, u_int n, float* f)
548{
549	float_t* fp = (float_t*) f;
550
551	while (n-- > 0) {
552		IEEEFLOAT2NATIVE(fp);
553		fp++;
554	}
555}
556
557void
558TIFFCvtNativeToIEEEFloat(TIFF* tif, u_int n, float* f)
559{
560	float_t* fp = (float_t*) f;
561
562	while (n-- > 0) {
563		NATIVE2IEEEFLOAT(fp);
564		fp++;
565	}
566}
567void
568TIFFCvtIEEEDoubleToNative(TIFF* tif, u_int n, double* f)
569{
570	double_t* fp = (double_t*) f;
571
572	while (n-- > 0) {
573		IEEEDOUBLE2NATIVE(fp);
574		fp++;
575	}
576}
577
578void
579TIFFCvtNativeToIEEEDouble(TIFF* tif, u_int n, double* f)
580{
581	double_t* fp = (double_t*) f;
582
583	while (n-- > 0) {
584		NATIVE2IEEEDOUBLE(fp);
585		fp++;
586	}
587}
588#endif
589