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