/* * CalmaReadio.c -- * * Input of Calma GDS-II stream format. * Low-level input. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/calma/CalmaRdio.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $"; #endif /* not lint */ #include #include #include #include #include "utils/magic.h" #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/utils.h" #include "utils/hash.h" #include "database/database.h" #include "database/databaseInt.h" #include "utils/malloc.h" #include "utils/tech.h" #include "cif/cif.h" #include "cif/CIFint.h" #include "cif/CIFread.h" #include "utils/signals.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "utils/styles.h" #include "textio/textio.h" #include "calma/calmaInt.h" /* C99 compat */ #include "calma/calma.h" /* Forward declarations */ bool calmaReadR8(double *pd); bool calmaSkipBytes(int nbytes); /* * ---------------------------------------------------------------------------- * * calmaReadTransform -- * * Read a CALMA_STRANS, CALMA_MAG, CALMA_ANGLE sequence and construct * the corresponding geometric transform. * * Results: * TRUE normally, FALSE on EOF or fatal syntax error. * * Side effects: * Consumes input. * Modifies the Transform pointed to by 'ptrans'. * * ---------------------------------------------------------------------------- */ bool calmaReadTransform( Transform *ptrans, /* Fill in this transform */ char *name) /* Name of subcell (for errors) */ { int nbytes, rtype, flags, angle; double dangle; double dmag; Transform t; /* Default is the identity transform */ *ptrans = GeoIdentityTransform; /* Is there any transform at all? */ READRH(nbytes, rtype); if (nbytes < 0) return (FALSE); if (rtype != CALMA_STRANS) { UNREADRH(nbytes, rtype); return (TRUE); } if (nbytes != 6) { (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); return (FALSE); } READI2(flags); /* Look for magnification and angle */ READRH(nbytes, rtype); if (nbytes < 0) return (FALSE); if (rtype == CALMA_MAG) { if (nbytes != CALMAHEADERLENGTH + 8) { (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); return (FALSE); } if (!calmaReadR8(&dmag)) return (FALSE); if (dmag != (double)((int)(dmag + 0.5))) { CalmaReadError("Non-integer magnification (%g) in transform\n", dmag); CalmaReadError("Rounding to %d.\n", (int)(dmag + 0.5)); } GeoScaleTrans(ptrans, (int)(dmag + 0.5), &t); *ptrans = t; } else UNREADRH(nbytes, rtype); READRH(nbytes, rtype); if (nbytes < 0) return (FALSE); dangle = 0.0; if (rtype == CALMA_ANGLE) { if (nbytes != CALMAHEADERLENGTH + 8) { (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); return (FALSE); } if (!calmaReadR8(&dangle)) return (FALSE); } else UNREADRH(nbytes, rtype); /* Make sure the angle is Manhattan */ angle = (int) dangle; while (angle < 0) angle += 360; while (angle > 360) angle -= 360; switch (angle) { case 360: angle = 0; break; case 0: case 90: case 180: case 270: break; default: CalmaReadError("Non-Manhattan angle (%d) in transform\n", angle); if (angle < 45) angle = 0; else if (angle < 135) angle = 90; else if (angle < 225) angle = 180; else if (angle < 315) angle = 270; else angle = 0; CalmaReadError(" Rounding to %d degrees.\n", angle); } /* * Construct the transform. * Magic angles are clockwise; Calma angles are counterclockwise. */ if (flags & CALMA_STRANS_UPSIDEDOWN) { GeoTransTrans(ptrans, &GeoUpsideDownTransform, &t); *ptrans = t; } switch (angle) { case 90: GeoTransTrans(ptrans, &Geo270Transform, &t); *ptrans = t; break; case 180: GeoTransTrans(ptrans, &Geo180Transform, &t); *ptrans = t; break; case 270: GeoTransTrans(ptrans, &Geo90Transform, &t); *ptrans = t; break; } return (TRUE); } /* * ---------------------------------------------------------------------------- * * calmaReadI2Record -- * * Read a record that should contain a two-byte integer. * * Results: * TRUE on success, FALSE if the record type we read is not * what we're expecting, or if it is of the wrong size. * * Side effects: * Consumes input. * Stores the result value in *pvalue (note that this is a normal * int, even though we're reading only 16 bits from the input). * * ---------------------------------------------------------------------------- */ bool calmaReadI2Record( int type, /* Type of record expected */ int *pvalue) /* Store value here */ { int nbytes, rtype, n; READRH(nbytes, rtype); if (nbytes < 0) goto eof; if (type != rtype) { calmaUnexpected(type, rtype); return (FALSE); } /* Read the value */ READI2(n); if (FEOF(calmaInputFile)) goto eof; *pvalue = n; return (TRUE); eof: CalmaReadError("Unexpected EOF.\n"); return (FALSE); } /* * ---------------------------------------------------------------------------- * * calmaReadI4Record -- * * Read a record that should contain a four-byte integer. * * Results: * TRUE on success, FALSE if the record type we read is not * what we're expecting, or if it is of the wrong size. * * Side effects: * Consumes input. * Stores the result value in *pvalue. * * ---------------------------------------------------------------------------- */ bool calmaReadI4Record( int type, /* Type of record expected */ int *pvalue) /* Store value here */ { int nbytes, rtype, n; READRH(nbytes, rtype); if (nbytes < 0) goto eof; if (type != rtype) { calmaUnexpected(type, rtype); return (FALSE); } /* Read the value */ READI4(n); if (FEOF(calmaInputFile)) goto eof; *pvalue = n; return (TRUE); eof: CalmaReadError("Unexpected EOF.\n"); return (FALSE); } /* * ---------------------------------------------------------------------------- * * calmaReadStampRecord -- * * Read a record that contains a pair of timestamps for creation and * modification dates. * * Results: * TRUE on success, FALSE if the record type we read is not * what we're expecting. * * Side effects: * Consumes input. * Translates the creation timestamp from GDS format to a standard * UNIX (time.h) timestamp (seconds since the epoch). * Stores the result in the integer pointed to by 'stampptr'. * * ---------------------------------------------------------------------------- */ bool calmaReadStampRecord( int type, int *stampptr) { int nbytes, rtype; struct tm gds_timestamp; READRH(nbytes, rtype); if (nbytes < 0) goto eof; if (type != rtype) { calmaUnexpected(type, rtype); return (FALSE); } nbytes -= CALMAHEADERLENGTH; if (nbytes != 24) { /* Not dealing with any timestamp that is not in I2 format */ calmaSkipBytes(nbytes); if (stampptr) *stampptr = 0; CalmaReadError("Unknown timestamp format; setting timestamp to zero.\n"); return TRUE; } gds_timestamp.tm_wday = 0; /* Not used by mktime() */ gds_timestamp.tm_yday = 0; /* Not used by mktime() */ gds_timestamp.tm_isdst = -1; READI2(gds_timestamp.tm_year); READI2(gds_timestamp.tm_mon); READI2(gds_timestamp.tm_mday); READI2(gds_timestamp.tm_hour); READI2(gds_timestamp.tm_min); READI2(gds_timestamp.tm_sec); /* GDS timestamps differ from UNIX time structure only by a */ /* difference of 1 in the month count. */ gds_timestamp.tm_mon--; /* Skip the modification date timestamp */ (void) calmaSkipBytes(nbytes - 12); if (stampptr) *stampptr = (int)mktime(&gds_timestamp); return (TRUE); eof: CalmaReadError("Unexpected EOF.\n"); return (FALSE); } /* * ---------------------------------------------------------------------------- * * calmaReadStringRecord -- * * Read a record that should contain an ASCII string. * * Results: * TRUE on success, FALSE if the record type we read is not * what we're expecting. * * Side effects: * Consumes input. * Allocates memory for string str (must be freed by the caller) * Stores the result in the string pointed to by 'str'. * * ---------------------------------------------------------------------------- */ bool calmaReadStringRecord( int type, char **str) { int nbytes, rtype; READRH(nbytes, rtype); if (nbytes < 0) goto eof; if (type != rtype) { calmaUnexpected(type, rtype); return (FALSE); } nbytes -= CALMAHEADERLENGTH; *str = (char *) mallocMagic(nbytes + 1); if (magicFREAD(*str, sizeof (char), nbytes, calmaInputFile) != nbytes) goto eof; *(*str + nbytes) = '\0'; return (TRUE); eof: CalmaReadError("Unexpected EOF.\n"); return (FALSE); } /* * ---------------------------------------------------------------------------- * * calmaReadR8 -- * * Read a single 8-byte real number in Calma stream format. * Convert to internal double-precision format and store in * the double pointed to by 'pd'. * * Results: * TRUE on success, FALSE if EOF is encountered. * * Side effects: * Consumes input. * Stores the result in the *pd. * * ---------------------------------------------------------------------------- */ bool calmaReadR8( double *pd) /* Store result in *pd */ { int i, exponent; unsigned char dchars[8]; double mantissa, d; bool isneg; if (magicFREAD((char *) dchars, sizeof (char), sizeof dchars, calmaInputFile) != sizeof dchars) return (FALSE); /* Extract the sign and exponent */ exponent = dchars[0]; if ((isneg = (exponent & 0x80))) exponent &= ~0x80; exponent -= 64; /* Construct the mantissa */ mantissa = 0.0; for (i = 7; i > 0; i--) { mantissa += dchars[i]; mantissa /= 256.0; } /* Now raise the mantissa to the exponent */ d = mantissa; if (exponent > 0) { while (exponent-- > 0) d *= 16.0; } else if (exponent < 0) { while (exponent++ < 0) d /= 16.0; } /* Make it negative if necessary */ if (isneg) d = -d; *pd = d; return (TRUE); } /* * ---------------------------------------------------------------------------- * * calmaSkipSet -- * * Skip all records falling in a specified set of types. * Leave the input stream positioned to the start of the first * record not in the specified set. * * The array pointed to by 'skipwhat' contains the record types * of all records to be skipped, terminated with -1. * * Results: * None. * * Side effects: * Consumes input. * * ---------------------------------------------------------------------------- */ void calmaSkipSet( const int *skipwhat) { const int *skipp; int nbytes, rtype; for (;;) { READRH(nbytes, rtype); if (nbytes < 0) return; for (skipp = skipwhat; *skipp >= 0; skipp++) if (*skipp == rtype) goto skipit; UNREADRH(nbytes, rtype); break; skipit: (void) calmaSkipBytes(nbytes - CALMAHEADERLENGTH); } } /* * ---------------------------------------------------------------------------- * * calmaSkipExact -- * * Skip a single stream record, which must be of the type 'type'. * Leave the input positioned to the start of the record following * this one. Complain if the record is not the one expected. * * Results: * TRUE if successful, FALSE if we encountered an error and * the caller should abort. * * Side effects: * Consumes input. * * ---------------------------------------------------------------------------- */ bool calmaSkipExact( int type) { int nbytes, rtype; /* Eat up the record header */ READRH(nbytes, rtype); if (nbytes < 0) goto eof; /* Skip remainder of record */ if (!calmaSkipBytes(nbytes - CALMAHEADERLENGTH)) goto eof; if (rtype != type) { calmaUnexpected(type, rtype); return (FALSE); } return (TRUE); eof: CalmaReadError("Unexpected EOF.\n"); return (FALSE); } /* * ---------------------------------------------------------------------------- * * calmaSkipTo -- * * Skip to a record of a particular type. Leaves the input stream * positioned AFTER the record whose type is given by 'what'. * * Results: * TRUE if we found this record, FALSE if EOF was encountered. * * Side effects: * Consumes input. * * ---------------------------------------------------------------------------- */ bool calmaSkipTo( int what) { int nbytes, rtype; do { READRH(nbytes, rtype); if (nbytes < 0) return (FALSE); calmaSkipBytes(nbytes - CALMAHEADERLENGTH); } while (rtype != what); return (TRUE); } /* * ---------------------------------------------------------------------------- * * calmaSkipBytes -- * * Skip 'nbytes' bytes from the input. * WARNING: this procedure doesn't know about input saved via UNREADRH(), * so if the caller wants this input to be discarded, it must call READRH() * itself. * * Results: * TRUE if successful, FALSE if EOF was encountered. * * Side effects: * Consumes nbytes of input. * * ---------------------------------------------------------------------------- */ bool calmaSkipBytes( int nbytes) /* Skip this many bytes */ { while (nbytes-- > 0) if (FGETC(calmaInputFile) < 0) return (FALSE); return (TRUE); }