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 */
TIFFModeCCITTFax3(void)46 void TIFFModeCCITTFax3(void){}
47 #endif
48 
49 static tsize_t
_tiffReadProc(thandle_t fd,tdata_t buf,tsize_t size)50 _tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
51 {
52 	return (read((int) fd, buf, size));
53 }
54 
55 static tsize_t
_tiffWriteProc(thandle_t fd,tdata_t buf,tsize_t size)56 _tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
57 {
58 	return (write((int) fd, buf, size));
59 }
60 
61 static toff_t
_tiffSeekProc(thandle_t fd,toff_t off,int whence)62 _tiffSeekProc(thandle_t fd, toff_t off, int whence)
63 {
64 	return ((toff_t) lseek((int) fd, (off_t) off, whence));
65 }
66 
67 static int
_tiffCloseProc(thandle_t fd)68 _tiffCloseProc(thandle_t fd)
69 {
70 	return (close((int) fd));
71 }
72 
73 #include <sys/stat.h>
74 
75 static toff_t
_tiffSizeProc(thandle_t fd)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
92 static int no_mapped = 0;
93 static 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  */
112 static int
_tiffMapProc(thandle_t fd,tdata_t * pbase,toff_t * psize)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  */
173 static void
_tiffUnmapProc(thandle_t fd,tdata_t base,toff_t size)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 */
196 static int
_tiffMapProc(thandle_t fd,tdata_t * pbase,toff_t * psize)197 _tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
198 {
199 	return (0);
200 }
201 
202 static void
_tiffUnmapProc(thandle_t fd,tdata_t base,toff_t size)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  */
211 TIFF*
TIFFFdOpen(int fd,const char * name,const char * mode)212 TIFFFdOpen(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  */
228 TIFF*
TIFFOpen(const char * name,const char * mode)229 TIFFOpen(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 
259 tdata_t
_TIFFmalloc(tsize_t s)260 _TIFFmalloc(tsize_t s)
261 {
262 	return (malloc((size_t) s));
263 }
264 
265 void
_TIFFfree(tdata_t p)266 _TIFFfree(tdata_t p)
267 {
268 	free(p);
269 }
270 
271 tdata_t
_TIFFrealloc(tdata_t p,tsize_t s)272 _TIFFrealloc(tdata_t p, tsize_t s)
273 {
274 	return (realloc(p, (size_t) s));
275 }
276 
277 void
_TIFFmemset(tdata_t p,int v,tsize_t c)278 _TIFFmemset(tdata_t p, int v, tsize_t c)
279 {
280 	memset(p, v, (size_t) c);
281 }
282 
283 void
_TIFFmemcpy(tdata_t d,const tdata_t s,tsize_t c)284 _TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
285 {
286 	memcpy(d, s, (size_t) c);
287 }
288 
289 int
_TIFFmemcmp(const tdata_t p1,const tdata_t p2,tsize_t c)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 
306 static void
vmsWarningHandler(const char * module,const char * fmt,va_list ap)307 vmsWarningHandler(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 
316 NOSHARE TIFFErrorHandler _TIFFwarningHandler = vmsWarningHandler
317 #if defined(VAX) && defined(__GNUC__)
318 asm("_$$PsectAttributes_NOSHR$$_TIFFwarningHandler")
319 #endif
320 ;
321 
322 static void
vmsErrorHandler(const char * module,const char * fmt,va_list ap)323 vmsErrorHandler(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 
331 NOSHARE TIFFErrorHandler _TIFFerrorHandler = vmsErrorHandler
332 #if defined(VAX) && defined(__GNUC__)
333 asm("_$$PsectAttributes_NOSHR$$_TIFFerrorHandler")
334 #endif
335 ;
336 
337 
338 #if !HAVE_IEEEFP
339 /* IEEE floting point handling */
340 
341 typedef	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;
347 typedef	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 
358 typedef	struct {
359 	u_long	mant1	: 7,
360 		exp	: 8,
361 		sign	: 1,
362 		mant2	: 16,
363 		mant3   : 16,
364 		mant4   : 16;
365 } nativedouble;
366 typedef	struct {
367 	u_long	mant1	: 7,
368 		exp	: 8,
369 		sign	: 1,
370 		mant2	: 16;
371 } nativefloat;
372 
373 typedef	union {
374 	ieeedouble	ieee;
375 	nativedouble	native;
376 	char		b[8];
377 	uint32		l[2];
378 	double		d;
379 } double_t;
380 
381 typedef	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  */
419 INLINE static void
ieeetod(double * dp)420 ieeetod(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 
459 INLINE static void
dtoieee(double * dp)460 dtoieee(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  */
546 void
TIFFCvtIEEEFloatToNative(TIFF * tif,u_int n,float * f)547 TIFFCvtIEEEFloatToNative(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 
557 void
TIFFCvtNativeToIEEEFloat(TIFF * tif,u_int n,float * f)558 TIFFCvtNativeToIEEEFloat(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 }
567 void
TIFFCvtIEEEDoubleToNative(TIFF * tif,u_int n,double * f)568 TIFFCvtIEEEDoubleToNative(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 
578 void
TIFFCvtNativeToIEEEDouble(TIFF * tif,u_int n,double * f)579 TIFFCvtNativeToIEEEDouble(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