summaryrefslogtreecommitdiff
path: root/libtiff/tif_vms.c
diff options
context:
space:
mode:
Diffstat (limited to 'libtiff/tif_vms.c')
-rw-r--r--libtiff/tif_vms.c588
1 files changed, 588 insertions, 0 deletions
diff --git a/libtiff/tif_vms.c b/libtiff/tif_vms.c
new file mode 100644
index 00000000..0b00de31
--- /dev/null
+++ b/libtiff/tif_vms.c
@@ -0,0 +1,588 @@
+/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_vms.c,v 1.1 1999-07-27 21:50:27 mike Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library VMS-specific Routines.
+ */
+
+#include <stdlib.h>
+#include <unixio.h>
+#include "tiffiop.h"
+#if !HAVE_IEEEFP
+#include <math.h>
+#endif
+
+#ifdef VAXC
+#define NOSHARE noshare
+#else
+#define NOSHARE
+#endif
+
+#ifdef __alpha
+/* Dummy entry point for backwards compatibility */
+void TIFFModeCCITTFax3(void){}
+#endif
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (read((int) fd, buf, size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (write((int) fd, buf, size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ return ((toff_t) lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (close((int) fd));
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ struct stat sb;
+ return (toff_t) (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+}
+
+#ifdef HAVE_MMAP
+#include <starlet.h>
+#include <fab.h>
+#include <secdef.h>
+
+/*
+ * Table for storing information on current open sections.
+ * (Should really be a linked list)
+ */
+#define MAX_MAPPED 100
+static int no_mapped = 0;
+static struct {
+ char *base;
+ char *top;
+ unsigned short channel;
+} map_table[MAX_MAPPED];
+
+/*
+ * This routine maps a file into a private section. Note that this
+ * method of accessing a file is by far the fastest under VMS.
+ * The routine may fail (i.e. return 0) for several reasons, for
+ * example:
+ * - There is no more room for storing the info on sections.
+ * - The process is out of open file quota, channels, ...
+ * - fd does not describe an opened file.
+ * - The file is already opened for write access by this process
+ * or another process
+ * - There is no free "hole" in virtual memory that fits the
+ * size of the file
+ */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ char name[256];
+ struct FAB fab;
+ unsigned short channel;
+ char *inadr[2], *retadr[2];
+ unsigned long status;
+ long size;
+
+ if (no_mapped >= MAX_MAPPED)
+ return(0);
+ /*
+ * We cannot use a file descriptor, we
+ * must open the file once more.
+ */
+ if (getname((int)fd, name, 1) == NULL)
+ return(0);
+ /* prepare the FAB for a user file open */
+ fab = cc$rms_fab;
+ fab.fab$l_fop |= FAB$V_UFO;
+ fab.fab$b_fac = FAB$M_GET;
+ fab.fab$b_shr = FAB$M_SHRGET;
+ fab.fab$l_fna = name;
+ fab.fab$b_fns = strlen(name);
+ status = sys$open(&fab); /* open file & get channel number */
+ if ((status&1) == 0)
+ return(0);
+ channel = (unsigned short)fab.fab$l_stv;
+ inadr[0] = inadr[1] = (char *)0; /* just an address in P0 space */
+ /*
+ * Map the blocks of the file up to
+ * the EOF block into virtual memory.
+ */
+ size = _tiffSizeProc(fd);
+ status = sys$crmpsc(inadr, retadr, 0, SEC$M_EXPREG, 0,0,0, channel,
+ TIFFhowmany(size,512), 0,0,0);
+ if ((status&1) == 0){
+ sys$dassgn(channel);
+ return(0);
+ }
+ *pbase = (tdata_t) retadr[0]; /* starting virtual address */
+ /*
+ * Use the size of the file up to the
+ * EOF mark for UNIX compatibility.
+ */
+ *psize = (toff_t) size;
+ /* Record the section in the table */
+ map_table[no_mapped].base = retadr[0];
+ map_table[no_mapped].top = retadr[1];
+ map_table[no_mapped].channel = channel;
+ no_mapped++;
+
+ return(1);
+}
+
+/*
+ * This routine unmaps a section from the virtual address space of
+ * the process, but only if the base was the one returned from a
+ * call to TIFFMapFileContents.
+ */
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ char *inadr[2];
+ int i, j;
+
+ /* Find the section in the table */
+ for (i = 0;i < no_mapped; i++) {
+ if (map_table[i].base == (char *) base) {
+ /* Unmap the section */
+ inadr[0] = (char *) base;
+ inadr[1] = map_table[i].top;
+ sys$deltva(inadr, 0, 0);
+ sys$dassgn(map_table[i].channel);
+ /* Remove this section from the list */
+ for (j = i+1; j < no_mapped; j++)
+ map_table[j-1] = map_table[j];
+ no_mapped--;
+ return;
+ }
+ }
+}
+#else /* !HAVE_MMAP */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+#endif /* !HAVE_MMAP */
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+ _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ int m, fd;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ return ((TIFF*)0);
+ if (m&O_TRUNC){
+ /*
+ * There is a bug in open in VAXC. If you use
+ * open w/ m=O_RDWR|O_CREAT|O_TRUNC the
+ * wrong thing happens. On the other hand
+ * creat does the right thing.
+ */
+ fd = creat((char *) /* bug in stdio.h */ name, 0666,
+ "alq = 128", "deq = 64", "mbc = 32",
+ "fop = tef");
+ } else if (m&O_RDWR) {
+ fd = open(name, m, 0666,
+ "deq = 64", "mbc = 32", "fop = tef", "ctx = stm");
+ } else
+ fd = open(name, m, 0666, "mbc = 32", "ctx = stm");
+ if (fd < 0) {
+ TIFFError(module, "%s: Cannot open", name);
+ return ((TIFF*)0);
+ }
+ return (TIFFFdOpen(fd, name, mode));
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+/*
+ * On the VAX, we need to make those global, writable pointers
+ * non-shareable, otherwise they would be made shareable by default.
+ * On the AXP, this brain damage has been corrected.
+ *
+ * I (Karsten Spang, krs@kampsax.dk) have dug around in the GCC
+ * manual and the GAS code and have come up with the following
+ * construct, but I don't have GCC on my VAX, so it is untested.
+ * Please tell me if it does not work.
+ */
+
+static void
+vmsWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+
+NOSHARE TIFFErrorHandler _TIFFwarningHandler = vmsWarningHandler
+#if defined(VAX) && defined(__GNUC__)
+asm("_$$PsectAttributes_NOSHR$$_TIFFwarningHandler")
+#endif
+;
+
+static void
+vmsErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+
+NOSHARE TIFFErrorHandler _TIFFerrorHandler = vmsErrorHandler
+#if defined(VAX) && defined(__GNUC__)
+asm("_$$PsectAttributes_NOSHR$$_TIFFerrorHandler")
+#endif
+;
+
+
+#if !HAVE_IEEEFP
+/* IEEE floting point handling */
+
+typedef struct ieeedouble {
+ u_long mant2; /* fix NDR: full 8-byte swap */
+ u_long mant : 20,
+ exp : 11,
+ sign : 1;
+} ieeedouble;
+typedef struct ieeefloat {
+ u_long mant : 23,
+ exp : 8,
+ sign : 1;
+} ieeefloat;
+
+/*
+ * NB: These are D_FLOAT's, not G_FLOAT's. A G_FLOAT is
+ * simply a reverse-IEEE float/double.
+ */
+
+typedef struct {
+ u_long mant1 : 7,
+ exp : 8,
+ sign : 1,
+ mant2 : 16,
+ mant3 : 16,
+ mant4 : 16;
+} nativedouble;
+typedef struct {
+ u_long mant1 : 7,
+ exp : 8,
+ sign : 1,
+ mant2 : 16;
+} nativefloat;
+
+typedef union {
+ ieeedouble ieee;
+ nativedouble native;
+ char b[8];
+ uint32 l[2];
+ double d;
+} double_t;
+
+typedef union {
+ ieeefloat ieee;
+ nativefloat native;
+ char b[4];
+ uint32 l;
+ float f;
+} float_t;
+
+#if defined(VAXC) || defined(DECC)
+#pragma inline(ieeetod,dtoieee)
+#endif
+
+/*
+ * Convert an IEEE double precision number to native double precision.
+ * The source is contained in two longwords, the second holding the sign,
+ * exponent and the higher order bits of the mantissa, and the first
+ * holding the rest of the mantissa as follows:
+ * (Note: It is assumed that the number has been eight-byte swapped to
+ * LSB first.)
+ *
+ * First longword:
+ * 32 least significant bits of mantissa
+ * Second longword:
+ * 0-19: 20 most significant bits of mantissa
+ * 20-30: exponent
+ * 31: sign
+ * The exponent is stored as excess 1023.
+ * The most significant bit of the mantissa is implied 1, and not stored.
+ * If the exponent and mantissa are zero, the number is zero.
+ * If the exponent is 0 (i.e. -1023) and the mantissa is non-zero, it is an
+ * unnormalized number with the most significant bit NOT implied.
+ * If the exponent is 2047, the number is invalid, in case the mantissa is zero,
+ * this means overflow (+/- depending of the sign bit), otherwise
+ * it simply means invalid number.
+ *
+ * If the number is too large for the machine or was specified as overflow,
+ * +/-HUGE_VAL is returned.
+ */
+INLINE static void
+ieeetod(double *dp)
+{
+ double_t source;
+ long sign,exp,mant;
+ double dmant;
+
+ source.ieee = ((double_t*)dp)->ieee;
+ sign = source.ieee.sign;
+ exp = source.ieee.exp;
+ mant = source.ieee.mant;
+
+ if (exp == 2047) {
+ if (mant) /* Not a Number (NAN) */
+ *dp = HUGE_VAL;
+ else /* +/- infinity */
+ *dp = (sign ? -HUGE_VAL : HUGE_VAL);
+ return;
+ }
+ if (!exp) {
+ if (!(mant || source.ieee.mant2)) { /* zero */
+ *dp=0;
+ return;
+ } else { /* Unnormalized number */
+ /* NB: not -1023, the 1 bit is not implied */
+ exp= -1022;
+ }
+ } else {
+ mant |= 1<<20;
+ exp -= 1023;
+ }
+ dmant = (((double) mant) +
+ ((double) source.ieee.mant2) / (((double) (1<<16)) *
+ ((double) (1<<16)))) / (double) (1<<20);
+ dmant = ldexp(dmant, exp);
+ if (sign)
+ dmant= -dmant;
+ *dp = dmant;
+}
+
+INLINE static void
+dtoieee(double *dp)
+{
+ double_t num;
+ double x;
+ int exp;
+
+ num.d = *dp;
+ if (!num.d) { /* Zero is just binary all zeros */
+ num.l[0] = num.l[1] = 0;
+ return;
+ }
+
+ if (num.d < 0) { /* Sign is encoded separately */
+ num.d = -num.d;
+ num.ieee.sign = 1;
+ } else {
+ num.ieee.sign = 0;
+ }
+
+ /* Now separate the absolute value into mantissa and exponent */
+ x = frexp(num.d, &exp);
+
+ /*
+ * Handle cases where the value is outside the
+ * range for IEEE floating point numbers.
+ * (Overflow cannot happen on a VAX, but underflow
+ * can happen for G float.)
+ */
+ if (exp < -1022) { /* Unnormalized number */
+ x = ldexp(x, -1023-exp);
+ exp = 0;
+ } else if (exp > 1023) { /* +/- infinity */
+ x = 0;
+ exp = 2047;
+ } else { /* Get rid of most significant bit */
+ x *= 2;
+ x -= 1;
+ exp += 1022; /* fix NDR: 1.0 -> x=0.5, exp=1 -> ieee.exp = 1023 */
+ }
+ num.ieee.exp = exp;
+
+ x *= (double) (1<<20);
+ num.ieee.mant = (long) x;
+ x -= (double) num.ieee.mant;
+ num.ieee.mant2 = (long) (x*((double) (1<<16)*(double) (1<<16)));
+
+ if (!(num.ieee.mant || num.ieee.exp || num.ieee.mant2)) {
+ /* Avoid negative zero */
+ num.ieee.sign = 0;
+ }
+ ((double_t*)dp)->ieee = num.ieee;
+}
+
+/*
+ * Beware, these do not handle over/under-flow
+ * during conversion from ieee to native format.
+ */
+#define NATIVE2IEEEFLOAT(fp) { \
+ float_t t; \
+ if (t.ieee.exp = (fp)->native.exp) \
+ t.ieee.exp += -129 + 127; \
+ t.ieee.sign = (fp)->native.sign; \
+ t.ieee.mant = ((fp)->native.mant1<<16)|(fp)->native.mant2; \
+ *(fp) = t; \
+}
+#define IEEEFLOAT2NATIVE(fp) { \
+ float_t t; int v = (fp)->ieee.exp; \
+ if (v) v += -127 + 129; /* alter bias of exponent */\
+ t.native.exp = v; /* implicit truncation of exponent */\
+ t.native.sign = (fp)->ieee.sign; \
+ v = (fp)->ieee.mant; \
+ t.native.mant1 = v >> 16; \
+ t.native.mant2 = v;\
+ *(fp) = t; \
+}
+
+#define IEEEDOUBLE2NATIVE(dp) ieeetod(dp)
+
+#define NATIVE2IEEEDOUBLE(dp) dtoieee(dp)
+
+
+/*
+ * These unions are used during floating point
+ * conversions. The above macros define the
+ * conversion operations.
+ */
+void
+TIFFCvtIEEEFloatToNative(TIFF* tif, u_int n, float* f)
+{
+ float_t* fp = (float_t*) f;
+
+ while (n-- > 0) {
+ IEEEFLOAT2NATIVE(fp);
+ fp++;
+ }
+}
+
+void
+TIFFCvtNativeToIEEEFloat(TIFF* tif, u_int n, float* f)
+{
+ float_t* fp = (float_t*) f;
+
+ while (n-- > 0) {
+ NATIVE2IEEEFLOAT(fp);
+ fp++;
+ }
+}
+void
+TIFFCvtIEEEDoubleToNative(TIFF* tif, u_int n, double* f)
+{
+ double_t* fp = (double_t*) f;
+
+ while (n-- > 0) {
+ IEEEDOUBLE2NATIVE(fp);
+ fp++;
+ }
+}
+
+void
+TIFFCvtNativeToIEEEDouble(TIFF* tif, u_int n, double* f)
+{
+ double_t* fp = (double_t*) f;
+
+ while (n-- > 0) {
+ NATIVE2IEEEDOUBLE(fp);
+ fp++;
+ }
+}
+#endif