#ifndef lint static char *sccsid = "@(#)mgmlib.c MgnAlt 2.8 (MIT/CSR) 3/20/92"; #endif /* Function: Access ADF and RDF data fields System: Magellan Altimetry Data Reduction Phase: LIB Module: mgmlib.c Revision: 2.8 Date: 3/20/92 Author: pgf@space.mit.edu Created: Sat Jan 4 14:35:28 EST 1992 Control: SCCS This code has been tested on the following systems: Sun/680x0 SunOS 4.0.3, 4.1 Sun/SPARC SunOS 4.0.3, 4.1, 4.1.1 Decstation: Ultrix 4.1 Microvax: Ultrix 3.3 and 2.2; BSD 4.3; VMS 5.4 NeXT: Mach 2.0 */ #define MGM_ETAG "LIB mgmlib.c 2.8" #define PATCH1 /* accept ADF/RDF files with test labels */ #define FMAX 8000 /* max allowed footprint number range */ #include "mgmlib.h" /* ** Input data records */ static ar_rec ar; /* altimetry input record */ static rr_rec rr; /* radiometry input record */ static oh_rec oh; /* orbit header input record */ /* ** Input data field tables */ static struct { float *ptr; /* pointer to input value */ ulong flag; /* bad flag for this value */ } alt_ptr[] = { &ar.ar_lon, AOK, /* 1 Footprint Longitude (deg, VBF85) */ &ar.ar_lat, AOK, /* 2 Footprint Latitude (deg, VBF85) */ &ar.ar_xfoot, AOK, /* 3 Along-track Footprint Size (km) */ &ar.ar_yfoot, AOK, /* 4 Cross-track Footprint Size (km) */ &ar.ar_rcal, AOK, /* 5 Receiver Noise Calibration (km-sq) */ &ar.ar_range, RBAD, /* 6 Uncorrected range to nadir (km) */ &ar.ar_atmos, AOK, /* 7 Atmospheric corrn to range (km) */ &ar.ar_radius, RBAD, /* 8 Derived Planetary Radius (km) */ &ar.ar_slope, CBAD, /* 9 Derived RMS Surface Slope (deg) */ &ar.ar_rho, FBAD, /* 10 Derived Fresnel Reflectivity */ &ar.ar_rhocor, AOK, /* 11 Rho Diffuse Scatt Corrn Factor */ ar.ar_error, RBAD, /* 12 Formal error in Radius */ ar.ar_error+1, CBAD, /* 13 Formal error in Slope */ ar.ar_error+2, FBAD, /* 14 Formal error in Rho */ ar.ar_correl, ABAD, /* 15 Formal correlations radius/slope */ ar.ar_correl+1, DBAD, /* 16 Formal correlations slope/rho */ ar.ar_correl+2, BBAD, /* 17 Formal correlations rho/radius */ ar.ar_correl+3, ABAD, /* 18 Formal correlations slope/radius */ ar.ar_correl+4, DBAD, /* 19 Formal correlations rho/slope */ ar.ar_correl+5, BBAD, /* 20 Formal correlations radius/rho */ &ar.ar_drad, RBAD, /* 21 Ephemeris Radius Correction (km) */ &ar.ar_dlon, RBAD, /* 22 Ephemeris Long Corrn. (deg, VBF85) */ &ar.ar_dlat, RBAD, /* 23 Ephemeris Lat Corrn. (deg, VBF85) */ &ar.ar_fit, AOK, /* 24 Non-range-sharp goodness of fit */ &ar.ar_rsfit, AOK, /* 25 Range-sharpened goodness-of-fit */ &ar.ar_rhofact, FBAD, /* 26 Multi-Peak Corrn. to ar_rho */ &ar.ar_radius2, R2BAD, /* 27 Radius from Threshold Detector */ &ar.ar_sqi, RBAD, /* 28 Signal Quality Indicator (dB) */ &ar.ar_scale, AOK, /* 29 Profile Scaling Factor (km-sq) */ &ar.ar_rsscale, AOK, /* 30 Range-sharp Scaling Factor (km-sq)*/ (float*)&ar.ar_looks, IOK, /* 31 Number of non-range-sharpened looks */ (float*)&ar.ar_rslooks, IOK, /* 32 Number of range-sharpened looks */ (float*)&ar.ar_thresh, IOK, /* 33 Threshold Detector Index */ }, rad_ptr[] = { &rr.rr_lon, ROK, /* -1 Footprint Longitude (deg, VBF85) */ &rr.rr_lat, ROK, /* -2 Footprint Latitude (deg, VBF85) */ &rr.rr_xfoot, ROK2, /* -3 Along Track Footprint Size (km) */ &rr.rr_yfoot, ROK2, /* -4 Cross Track Footprint Size (km) */ rr.rr_sfoot, NOS1, /* -5 SAR Footprint Diameter (km) */ rr.rr_sfoot+1, NOS2, /* -6 SAR Footprint Diameter (km) */ rr.rr_sar, NOS1, /* -7 SAR Average Backscatter Val (dB) */ rr.rr_sar+1, NOS2, /* -8 SAR Average Backscatter Val (dB) */ &rr.rr_angle, ROK2, /* -9 Incidence Angle (deg) */ &rr.rr_bright, ROK, /* -10 Brightness Temperature (K) */ &rr.rr_radius, ROK2, /* -11 Average Planetary Radius (km) */ &rr.rr_anttemp, ROK, /* -12 System Temperature of Antenna (K) */ &rr.rr_skytemp, ROK2, /* -13 Assumed Cold Sky Temperature (K) */ &rr.rr_rcvrtemp, ROK, /* -14 System Temperature of Receiver (K) */ &rr.rr_surftemp, ROK2, /* -15 Physical Surface Temperature (K) */ &rr.rr_emiss, ROK2, /* -16 Surface Emissivity */ &rr.rr_dedrad, ROK2, /* -17 Partial of Emissivity wrt Radius */ &rr.rr_phystemp, ROK2, /* -18 Physical Surface Temperature (K) */ &rr.rr_antval, ROK, /* -19 Raw Antenna Signal */ &rr.rr_loadval, ROK, /* -20 Raw Load Signal */ }; #define ALT_SIZE (sizeof(alt_ptr)/sizeof(alt_ptr[0])) #define RAD_SIZE (sizeof(rad_ptr)/sizeof(rad_ptr[0])) /* ** Structure defining location of each requested data type */ static struct ctl { float *f_in; /* input data value */ ulong f_flag; /* bad data flags */ float *f_out; /* output array pointer */ } *fc; /* ** Structure defining file contents */ static struct tps { struct tps *tp_next; /* forward pointer */ int tp_orbit; /* orbit number */ char tp_type; /* 'I' or 'V' (IEEE/VAX) */ ushort tp_hash; /* name hash code */ short tp_len; /* length of header */ short tp_first; /* first footprint number */ short tp_last; /* last footprint number */ char tp_buf[FMAX/8]; /* bitmap */ char tp_name[1]; /* file name */ } *tp_anch, *tp; /* ** Global orbit numbers of last files read */ int adf_orbit; /* latest ADF orbit number */ int rdf_orbit; /* latest RDF orbit number */ int ohf_orbit; /* latest OHF orbit number */ /* ** Miscellaneous */ static char *file; /* input file name */ static FILE *fp; /* input stream pointer */ #ifndef NOUNIX static char tbuffer[32500]; /* file input buffer */ #endif NOUNIX static void (*no_mgm_abort)(); /* abort exit */ static long swap(); /* byte reversal */ static int find_rec(), getrec(); /* block location */ static ushort hash(); /* string hashing */ static void vaxlong(); /* swap 4-byte integers */ static void tovaxf(), fromvaxf(); /* convert floats */ static void tovaxd(), fromvaxd(); /* convert doubles */ static int read_adf(), read_rdf(); /* read ADF and RDF */ static char *alloc(); /* storage allocator */ extern int read(), write(); /* C library */ extern long lseek(); /* C library */ #define copy(a,b,c) bcopy((char *)(a),(char *)(b),(c)) /* ** Read one orbit's data into 'array' */ read_arcdr(afile, rfile, ntype, type, dim, zero, array) char *afile; /* altimetry file name */ char *rfile; /* radiometry file name */ int ntype; /* number of data types */ int *type; /* data type array */ int dim; /* inner array dimension */ int zero; /* inner array zero index */ float *array; /* output array */ { int i; /* index in type[] */ int rc = 0; /* function return code */ int itype; /* number of type[] values */ if (dim < 1) return 0; /* ** Clear the output array */ bzero((char *)array, sizeof(float) * ntype * dim); /* ** Allocate pointer array */ fc = (struct ctl *)alloc(sizeof(struct ctl), ntype); /* ** Fill 'ftype' for altimetry data fields */ for (i = itype = 0; i < ntype; i++) if (type[i] > 0 && type[i] <= ALT_SIZE) { fc[itype].f_in = alt_ptr[type[i]-1].ptr; fc[itype].f_flag = alt_ptr[type[i]-1].flag; fc[itype++].f_out = &array[i * dim]; } /* ** Read the variables from the altimetry data file */ if (itype > 0) { file = afile; rc = read_adf(itype, dim, zero); } /* ** Fill 'ftype' for radiometry data fields */ for (i = itype = 0; i < ntype; i++) if (type[i] < 0 && -type[i] <= RAD_SIZE) { fc[itype].f_in = rad_ptr[-type[i]-1].ptr; fc[itype].f_flag = rad_ptr[-type[i]-1].flag; fc[itype++].f_out = &array[i * dim]; } /* ** Read the variables from the radiometry data file */ if (itype > 0) { file = rfile; rc |= read_rdf(itype, dim, zero); } free((char *)fc); return rc; } /* ** Return pointer to single ADF record */ ar_rec * read_adf_rec(afile, nfoot) char *afile; /* altimetry data file */ int nfoot; /* footprint number */ { int rec; /* record index */ file = afile; adf_orbit = -1; if ((rec = find_rec(nfoot, read_adf)) < 0) return (ar_rec *)NULL; adf_orbit = tp->tp_orbit; io_rec((char *)&ar, sizeof(ar), rec, read); #ifdef vax tovaxf(&ar.ar_sqi, 1, &ar.ar_sqi); if (tp->tp_type == 'I') ar_rec_to_vax(&ar, &ar); #else if (tp->tp_type == 'V') ar_rec_from_vax(&ar, &ar); #ifdef LSB else ar_rec_convert(&ar, &ar, vaxlong, vaxlong, lsbdouble); vaxlong(&ar.ar_sqi, 1, &ar.ar_sqi); #endif LSB #endif vax check_sfdu((char *)&ar, ADF_SFDU_LABEL, 0); return &ar; } /* ** Write a single ADF record */ write_adf_rec(afile, nfoot, arp) char *afile; /* altimetry data file */ int nfoot; /* footprint number */ ar_rec *arp; /* output structure */ { ar_rec ar2; /* converted output record */ int rec; /* record index */ file = afile; adf_orbit = -1; if ((rec = find_rec(nfoot, read_adf)) < 0) return rec; adf_orbit = tp->tp_orbit; #ifdef vax if (tp->tp_type == 'I') ar_rec_from_vax(arp, &ar2); else bcopy(arp, &ar2, sizeof(ar)); fromvaxf(&arp->ar_sqi, 1, &ar2.ar_sqi); #else if (tp->tp_type == 'V') { ar_rec_to_vax(arp, &ar2); ar2.ar_sqi = arp->ar_sqi; } #ifdef LSB else ar_rec_convert(arp, &ar2, vaxlong, vaxlong, lsbdouble), vaxlong(&arp->ar_sqi, 1, &ar2.ar_sqi); #endif LSB #endif vax check_sfdu((char *)&ar2, ADF_SFDU_LABEL, 0); io_rec((char *)&ar2, sizeof(ar), rec, write); return 0; } /* ** Return pointer to single RDF record */ rr_rec * read_rdf_rec(rfile, burst) char *rfile; /* radiometry data file */ int burst; /* burst number */ { int rec; /* record index */ file = rfile; rdf_orbit = -1; if ((rec = find_rec(burst, read_rdf)) < 0) return (rr_rec *)NULL; rdf_orbit = tp->tp_orbit; io_rec((char *)&rr, sizeof(rr), rec, read); #ifdef vax if (tp->tp_type == 'I') rr_rec_to_vax(&rr, &rr); #else if (tp->tp_type == 'V') rr_rec_from_vax(&rr, &rr); #ifdef LSB else rr_rec_convert(&rr, &rr, vaxlong, vaxlong, lsbdouble); #endif LSB #endif vax check_sfdu((char *)&rr, RDF_SFDU_LABEL, 0); return &rr; } /* ** Write a single RDF record */ write_rdf_rec(rfile, burst, rrp) char *rfile; /* radiometry data file */ int burst; /* burst number */ rr_rec *rrp; /* output structure */ { int rec; /* record index */ rr_rec rr2; /* converted output record */ file = rfile; rdf_orbit = -1; if ((rec = find_rec(burst, read_rdf)) < 0) return rec; rdf_orbit = tp->tp_orbit; #ifdef vax if (tp->tp_type == 'I') rr_rec_from_vax(rrp, &rr2), rrp = &rr2; #else if (tp->tp_type == 'V') rr_rec_to_vax(rrp, &rr2), rrp = &rr2; #ifdef LSB else rr_rec_convert(rrp, &rr2, vaxlong, vaxlong, lsbdouble), rrp = &rr2; #endif LSB #endif vax check_sfdu((char *)rrp, RDF_SFDU_LABEL, 0); io_rec((char *)rrp, sizeof(rr), rec, write); return 0; } /* ** Return pointer to OHF record */ oh_rec * read_ohf_rec(ofile) char *ofile; /* input OHF file name */ { char ctype; /* data format */ char rc; /* scratch */ file = ofile; if ((ctype = read_labels("ORBIT_HEADER_RECORD\r\n")) == 1) return NULL; rc = fread((char *)&oh, sizeof(oh_rec), 1, fp); (void)fclose(fp); if (rc != 1) MGMPERROR("read_ohf", ofile); if (strncmp((char *)&oh, OHF_SFDU_LABEL, 12)) MGMERROR("%s: bad label: %-12.12s", ofile, (char *)&oh); #ifdef vax if (ctype == 'I') oh_rec_to_vax(&oh, &oh); #else if (ctype == 'V') oh_rec_from_vax(&oh, &oh); #ifdef LSB else oh_rec_convert(&oh, &oh, vaxlong, lsbdouble); #endif LSB #endif ohf_orbit = oh.oh_norbit; return &oh; } /* ** Read altimetry data file */ static read_adf(itype, dim, zero) int itype; /* number of type[] values */ int dim; /* footprints in array[] */ int zero; /* nfoot==0 index in array[] */ { struct ctl *f, *flim; /* data control pointers */ int n; /* scratch */ /* ** Read the SFDU headers */ if (read_labels("ALTIMETRY_FILE\r\n")) return 1; /* ** Read each altimetry data record */ flim = fc + itype; for (;;) { (void)fread((char *)&ar, sizeof(ar), 1, fp); /* ** Test the SFDU header */ if (strncmp((char *)&ar.ar_sfdu, "CCSD1R000003", 12) == 0) break; if (feof(fp)) { (void)fclose(fp); MGMERROR("read_adf: %s: unexpected EOF", file, ""); } if (ferror(fp)) { (void)fclose(fp); MGMPERROR("read_adf", file); } #ifdef PATCH1 if (strncmp((char *)&ar.ar_sfdu, "NJPL1I000000", 12) != 0) #endif PATCH1 check_sfdu((char *)&ar.ar_sfdu, ADF_SFDU_LABEL, 1); /* ** Possibly convert to local CPU type */ #ifdef vax if (dim) tovaxf(&ar.ar_sqi, 1, &ar.ar_sqi); if (tp->tp_type == 'I') if (dim) ar_rec_to_vax(&ar, &ar); #else #ifdef LSB if (dim) vaxlong(&ar.ar_sqi, 1, &ar.ar_sqi); #endif LSB if (tp->tp_type == 'V') if (dim) ar_rec_from_vax(&ar, &ar); #ifdef LSB else ; else if (dim) ar_rec_convert(&ar, &ar, vaxlong, vaxlong, lsbdouble); #endif LSB #endif vax else ar.ar_nfoot = swap(ar.ar_nfoot); /* ** Update the file table */ n = ar.ar_nfoot; if (tp->tp_first == 9999) tp->tp_first = n; tp->tp_last = n; n -= tp->tp_first; if (n >= 0 && n < FMAX) tp->tp_buf[n>>3] |= 0x80 >> (n&7); /* ** Copy requested data fields */ if ((n = ar.ar_nfoot + zero) >= 0 && n < dim) for (f = fc; f < flim; f++) if (! (ar.ar_flag & f->f_flag)) f->f_out[n] = (f->f_flag & AR_INT) ? *(int *)(f->f_in) : f->f_in[0]; } /* ** Read trailer bytes and close the file */ while (getc(fp) != EOF) ; (void)fclose(fp); return 0; } /* ** Read radiometry data file */ static read_rdf(itype, dim, zero) int itype; /* number of type[] values */ int dim; /* bursts in array[] */ int zero; /* nfoot==0 index in array[] */ { struct ctl *f, *flim; /* data control pointers */ int n; /* scratch */ /* ** Read the SFDU headers */ if (read_labels("RADIOMETRY_FILE\r\n")) return 2; /* ** Read each radiometry data record */ flim = fc + itype; for (;;) { (void)fread((char *)&rr, sizeof(rr), 1, fp); /* ** Test the SFDU header */ if (strncmp((char *)&rr.rr_sfdu, "CCSD1R000003", 12) == 0) break; if (feof(fp)) { (void)fclose(fp); MGMERROR("read_rdf: %s: unexpected EOF", file, ""); } if (ferror(fp)) { (void)fclose(fp); MGMPERROR("read_rdf", file); } #ifdef PATCH1 if (strncmp((char *)&rr.rr_sfdu, "NJPL1I000000", 12) != 0) #endif PATCH1 check_sfdu((char *)&rr.rr_sfdu, RDF_SFDU_LABEL, 1); /* ** Possibly convert to local CPU type */ #ifdef vax if (tp->tp_type == 'I') if (dim) rr_rec_to_vax(&rr, &rr); #else if (tp->tp_type == 'V') if (dim) rr_rec_from_vax(&rr, &rr); #ifdef LSB else ; else if (dim) rr_rec_convert(&rr, &rr, vaxlong, vaxlong, lsbdouble); #endif LSB #endif vax else rr.rr_burst = swap(rr.rr_burst); /* ** Update the file table */ n = rr.rr_burst; if (tp->tp_first == 9999) tp->tp_first = n; tp->tp_last = n; n -= tp->tp_first; if (n >= 0 && n < FMAX) tp->tp_buf[n>>3] |= 0x80 >> (n&7); /* ** Copy requested data fields */ if ((n = rr.rr_burst + zero) >= 0 && n < dim) for (f = fc; f < flim; f++) if (! (rr.rr_flag & f->f_flag)) f->f_out[n] = f->f_in[0]; } /* ** Read trailer bytes and close the file */ while (getc(fp) != EOF) ; (void)fclose(fp); return 0; } /* ** Read the SFDU header label and allocate file structure */ read_labels(ptype) char *ptype; /* expected product type value */ { char *c; /* keyword search string */ char line[1024]; /* input line buffer */ char ctype = '?'; /* first char of DATA_FORMAT_TYPE */ int orbit = -1; /* orbit number */ ushort h; /* hashed name of input file */ int i; /* scratch */ if ((fp = fopen(file, OPENMODE)) == NULL) return 1; /* ** Use large input buffer in case this is tape input. ** Return 1 if null file */ #ifndef NOUNIX setbuffer(fp, tbuffer, sizeof(tbuffer)); #endif NOUNIX if ((i = getc(fp)) == EOF) { (void)fclose(fp); return 1; } (void)ungetc(i, fp); /* ** Read header SFDU label */ (void)read_sfdu("CCSD1Z000001"); /* ** Read keyword header label */ i = read_sfdu("NJPL1K00KL00"); /* ** Read keywords and values */ while (i > 0) { if (fgets(line, sizeof(line)-1, fp) == NULL) { (void)fclose(fp); if (feof(fp)) MGMERROR("read_labels: %s: unexpected EOF", file, ""); else MGMPERROR("read_labels", file); } c = "PRODUCT_TYPE="; if (!strncmp(c, line, strlen(c))) if (strcmp(ptype, c = line+strlen(c))) { (void)fclose(fp); MGMERROR("%s: bad PRODUCT_TYPE: '%s'", file, c); } c = "DATA_FORMAT="; if (!strncmp(c, line, strlen(c))) ctype = line[strlen(c)]; c = "DATA_FORMAT_TYPE="; if (!strncmp(c, line, strlen(c))) ctype = line[strlen(c)]; c = "ORBIT_NUMBER="; if (!strncmp(c, line, strlen(c)) && sscanf(c = line+strlen(c), "%d", &orbit) != 1) { (void)fclose(fp); MGMERROR("%s: bad ORBIT_NUMBER: %s", file, c); } i -= strlen(line); } /* ** Test for known data type keyword value */ if (ctype != 'I' && ctype != 'V') { (void)fclose(fp); MGMERROR("%s: unknown CPU type: %.1s", file, &ctype); } if (ptype[0] == 'A') adf_orbit = orbit; else if (ptype[0] == 'R') rdf_orbit = orbit; else return ctype; if (orbit <= 0) { (void)fclose(fp); MGMERROR("%s: missing ORBIT_NUMBER", file, ""); } /* ** Read SMARKER label */ i = read_sfdu("CCSD1R000003"); while (--i >= 0) (void)getc(fp); /* ** Locate file table element */ h = hash(file); for (tp = tp_anch; tp; tp = tp->tp_next) if (h == tp->tp_hash && strcmp(file, tp->tp_name) == 0) break; /* ** Allocate and/or clear new element */ if (tp == NULL) { i = strlen(file); tp = (struct tps *)alloc(sizeof(*tp) + i, 1); tp->tp_next = tp_anch; tp_anch = tp; tp->tp_hash = h; copy(file, tp->tp_name, i); } else bzero(tp->tp_buf, sizeof(tp->tp_buf)); /* ** Initialize element */ tp->tp_len = ftell(fp); tp->tp_first = 9999; tp->tp_last = -9999; tp->tp_type = ctype; tp->tp_orbit = orbit; return 0; } /* ** Read SFDU header and return length of value */ read_sfdu(s) char *s; /* expected SFDU header */ { sfdu sf; /* SFDU header buffer */ int i, n; /* scratch */ if (fread((char *)&sf, sizeof(sfdu), 1, fp) != 1) { (void)fclose(fp); if (feof(fp)) MGMERROR("read_sfdu: %s: unexpected EOF", file, ""); else MGMPERROR("read_sfdu", file); } if (strncmp((char *)&sf, s, 12)) { (void)fclose(fp); MGMERROR("%s: bad sfdu: %12.12s", file, (char *)&sf); } for (i = n = 0; i < 8; i++) n = 10 * n + sf.sf_length.sf_clen[i] - '0'; return n; } /* ** Byte-reverse a 4-byte integer */ static long swap(n) long n; { return ((n >> 24) & 0xff) | ((n >> 8) & 0xff00) | ((n & 0xff00) << 8) | ((n & 0xff) << 24); } /* ** Hash a character string via CRC algorithm */ static ushort hash(s) register char *s; /* string to be hashed */ { register ushort i = 0; /* result register */ while (*s) i = (((i >> 15) & 1) | (i << 1)) ^ (*s++ & 0xff); return i; } /* ** Locate record number; returns -1 if cannot locate */ static getrec(rec) register int rec; /* requested foot/burst number */ { register int i, n; /* scratch */ ushort h; /* hashed filename */ h = hash(file); for (tp = tp_anch; tp; tp = tp->tp_next) if (h == tp->tp_hash && strcmp(file, tp->tp_name) == 0) break; if (tp == NULL || rec < tp->tp_first || rec > tp->tp_last) return -1; rec -= tp->tp_first; if (rec < FMAX) for (i = n = 0; i <= rec; i++) { if (tp->tp_buf[i>>3] & (0x80 >> (i&7))) if (i == rec) return n; else n++; } return -1; } /* ** Given foot/burst number, locate output record */ static find_rec(rec, readfile) int rec; /* requested foot/burst number */ int (*readfile)(); /* routine to read whole file */ { int n; /* record number */ n = getrec(rec); if (tp == NULL) if ((*readfile)(0,0,0)) return -1; else n = getrec(rec); return n; } /* ** Read or write a specified data record */ io_rec(buf, size, nrec, action) char *buf; /* input or output record */ int size; /* size of record */ int nrec; /* record number */ int (*action)(); /* either read() or write() */ { int fid; /* file descriptor */ if ((fid = open(file, action == read ? 0 : 1)) == EOF || lseek(fid, (long)(tp->tp_len + nrec*size), 0) == -1 || (*action)(fid, buf, size) != size) { (void)close(fid); MGMPERROR(file, action == read ? "read" : "write"); } (void)close(fid); } /* ** Check for valid SFDU label */ check_sfdu(s, label, sw) char *s, *label; int sw; { if (strncmp(s, label, 12) != 0) { if (sw) (void)fclose(fp); MGMERROR("%s: bad sfdu label: %12.12s", file, s); } } /* ** Storage allocation */ static char * alloc(size, count) int size; /* Length of data element */ int count; /* Number of such elements */ { char *block, *calloc(); if (! (block = calloc((unsigned)size, (unsigned)count))) MGMPERROR("alloc", "memory allocation"); return block; } /* ** Convert oh_rec */ static oh_rec_convert(in, out, iconvert, dconvert) oh_rec *in, *out; void (*iconvert)(), (*dconvert)(); { if (in != out) copy(&in->oh_sfdu, &out->oh_sfdu, sizeof(sfdu)); (*iconvert)((uchar *)&in->oh_norbit, 3, (uchar *)&out->oh_norbit); (*dconvert)((char *)&in->oh_alt_start,20,(char *)&in->oh_alt_start); } /* ** Convert oh_rec from IEEE/MIPS format to VAX */ static oh_rec_to_vax(in, out) oh_rec *in, *out; { oh_rec_convert(in, out, SWAP, tovaxd); } /* ** Convert oh_rec from VAX to IEEE/MIPS format */ oh_rec_from_vax(in, out) oh_rec *in, *out; { oh_rec_convert(in, out, SWAP, fromvaxd); } /* ** Convert ar_rec */ static ar_rec_convert(in, out, iconvert, fconvert, dconvert) ar_rec *in, *out; void (*iconvert)(), (*fconvert)(), (*dconvert)(); { if (in != out) { copy(&in->ar_sfdu, &out->ar_sfdu, sizeof(sfdu)); copy(in->ar_prof, out->ar_prof, sizeof(in->ar_prof)); copy(in->ar_tmpl, out->ar_tmpl, sizeof(in->ar_tmpl)); copy(in->ar_rsprof, out->ar_rsprof, sizeof(in->ar_rsprof)); copy(in->ar_rstmpl, out->ar_rstmpl, sizeof(in->ar_rstmpl)); copy(in->ar_spare, out->ar_spare, sizeof(in->ar_spare)); } (*iconvert)((uchar *)&in->ar_nfoot, 3, (uchar *)&out->ar_nfoot); (*dconvert)((uchar *)&in->ar_scet, 14, (uchar *)&out->ar_scet); (*fconvert)((uchar *)&in->ar_lon, 43, (uchar *)&out->ar_lon); (*iconvert)((uchar *)&in->ar_looks, 2, (uchar *)&out->ar_looks); (*fconvert)((uchar *)&in->ar_rsfit, 2, (uchar *)&out->ar_rsfit); (*iconvert)((uchar *)&in->ar_rslooks, 2, (uchar *)&out->ar_rslooks); (*fconvert)((uchar *)&in->ar_rhofact, 2, (uchar *)&out->ar_rhofact); (*iconvert)((uchar *)&in->ar_thresh, 1, (uchar *)&out->ar_thresh); } /* ** Convert ar_rec from IEEE/MIPS to VAX format */ ar_rec_to_vax(in, out) ar_rec *in, *out; { ar_rec_convert(in, out, SWAP, tovaxf, tovaxd); } /* ** Convert ar_rec from VAX to IEEE/MIPS format */ ar_rec_from_vax(in, out) ar_rec *in, *out; { ar_rec_convert(in, out, SWAP, fromvaxf, fromvaxd); } /* ** Convert rr_rec */ static rr_rec_convert(in, out, iconvert, fconvert, dconvert) rr_rec *in, *out; void (*iconvert)(), (*fconvert)(), (*dconvert)(); { if (in != out) { copy(&in->rr_sfdu, &out->rr_sfdu, sizeof(sfdu)); copy(in->rr_spare, out->rr_spare, sizeof(in->rr_spare)); } (*iconvert)((uchar *)&in->rr_burst, 3, (uchar *)&out->rr_burst); (*dconvert)((uchar *)&in->rr_scet, 14, (uchar *)&out->rr_scet); (*fconvert)((uchar *)&in->rr_lon, 38, (uchar *)&out->rr_lon); (*iconvert)((uchar *)&in->rr_acr, 1, (uchar *)&out->rr_acr); } /* ** Convert rr_rec from IEEE/MIPS to VAX format */ rr_rec_to_vax(in, out) rr_rec *in, *out; { rr_rec_convert(in, out, SWAP, tovaxf, tovaxd); } /* ** Convert rr_rec from VAX to IEEE/MIPS format */ rr_rec_from_vax(in, out) rr_rec *in, *out; { rr_rec_convert(in, out, SWAP, fromvaxf, fromvaxd); } /* ** General error reporting routine, then quit. */ mgmerror(sw, tag, msg, insert1, insert2) int sw; /* Type of Message */ char *tag; /* Name, module, version */ char *msg; /* Body of Error Message */ char *insert1; /* First Text Insert */ char *insert2; /* Second Text Insert */ { char errbuf[1024]; /* message buffer */ (void)sprintf(errbuf, "MGM%s ", tag); tag = errbuf + strlen(errbuf); switch (sw) { case MGM_PERR: #ifdef NOUNIX (void)sprintf(tag, "%s: %s: error %d", msg, insert1, errno); #else { extern int sys_nerr; extern char *sys_errlist[]; (void)sprintf(tag, "%s: %s: %s", msg, insert1, (errno < 0 || errno > sys_nerr) ? "unknown error" : sys_errlist[errno]); } #endif NOUNIX break; case MGM_ERR: default: (void)sprintf(tag, msg, insert1, insert2); break; } if (no_mgm_abort) (*no_mgm_abort)(errbuf); (void)fprintf(stderr, "%s\n", errbuf); exit(-1); } mgm_setexit(proc) void (*proc)(); /* user's interrupt handler */ { no_mgm_abort = proc; } /* ** Conversion from ieee to vax floating point */ static void tovaxf(in, n, out) register uchar *in, *out; register int n; { register uchar ch; #ifdef LSB vaxlong(in, n, out); in = out; #endif LSB while (--n >= 0) { if (ch = *in++) ch++; *out++ = *in++; *out++ = ch; ch = *in++; *out++ = *in++; *out++ = ch; } } /* ** Conversion from ieee to vax double precision */ static void tovaxd(in, n, out) register uchar *in, *out; register int n; { register ulong i, j, k; #ifdef LSB lsbdouble(in, n, out); in = out; #endif LSB n >>= 1; while (--n >= 0) { i = ((ulong)in[0] << 24) | ((ulong)in[1] << 16); i |= ((ulong)in[2] << 8) | in[3]; if (j = i & 0x7ff00000) { k = ((ulong)in[4] << 24) | ((ulong)in[5] << 16) | ((ulong)in[6] << 8) | in[7]; i = (i & 0x80000000) | ((j - 0x37e00000) << 3) | ((i & 0xfffff) << 3) | (k >> 29); k <<= 3; } else i = k = 0; *out++ = (i >> 16) & 255; *out++ = i >> 24; *out++ = i & 255; *out++ = (i >> 8) & 255; *out++ = (k >> 16) & 255; *out++ = k >> 24; *out++ = k & 255; *out++ = (k >> 8) & 255; in += 8; } } /* ** Conversion from vax to ieee floating point */ static void fromvaxf(in, n, out) register uchar *in, *out; register int n; { register uchar ch1, ch2; register int l = n; while (--l >= 0) { ch1 = *in++; *out++ = (ch2 = *in++) ? ch2-1 : ch2; *out++ = ch1; ch1 = *in++; *out++ = *in++; *out++ = ch1; } #ifdef LSB vaxlong(out - 4*n, n, out - 4*n); #endif LSB } /* ** Conversion from vax to ieee double precision */ static void fromvaxd(in, n, out) register uchar *in, *out; register int n; { register ulong i, j, k; register int l = n/2; while (--l >= 0) { i = ((ulong)in[1] << 24) | ((ulong)in[0] << 16); i |= ((ulong)in[3] << 8) | in[2]; if (j = i & 0x7f800000) { k = i << 29; k |= ((ulong)in[5] << 21) | ((ulong)in[4] << 13); k |= ((ulong)in[7] << 5) | (in[6] >> 3); i = (i & 0x80000000) | ((i & 0x7fffff) >> 3) | ((j >> 3) + 0x37e00000); } else i = k = 0; *out++ = i >> 24; *out++ = (i >> 16) & 255; *out++ = (i >> 8) & 255; *out++ = i & 255; *out++ = k >> 24; *out++ = (k >> 16) & 255; *out++ = (k >> 8) & 255; *out++ = k & 255; in += 8; } #ifdef LSB lsbdouble(out - 4*n, n, out - 4*n); #endif LSB } /* ** Convert between VAX and IEEE shorts/ushorts */ static void vaxshort(in, n, out) register uchar *in, *out; register int n; { register uchar ch; while (--n >= 0) { ch = *in++; *out++ = *in++; *out++ = ch; } } /* ** Convert between VAX/MIPS and IEEE longs/ulongs ** Also between MIPS and IEEE floats/doubles */ static void vaxlong(in, n, out) register uchar *in, *out; register int n; { register uchar ch1, ch2, ch3; while (--n >= 0) { ch1 = *in++; ch2 = *in++; ch3 = *in++; *out++ = *in++; *out++ = ch3; *out++ = ch2; *out++ = ch1; } } #ifdef LSB static void lsbdouble(in, n, out) register uchar *in, *out; register int n; { register uchar ch1, ch2, ch3, ch4, ch5, ch6, ch7; while (--n >= 0) { ch1 = *in++; ch2 = *in++; ch3 = *in++; ch4 = *in++; ch5 = *in++; ch6 = *in++; ch7 = *in++; *out++ = *in++; *out++ = ch7; *out++ = ch6; *out++ = ch5; *out++ = ch4; *out++ = ch3; *out++ = ch2; *out++ = ch1; n--; } } static void bytecopy(in, n, out) register uchar *in, *out; register int n; { if (in != out) copy((char *)in, (char *)out, 4*n); } #endif LSB #ifdef NOUNIX static bcopy(in, out, n) register char *in, *out; register int n; { if (out > in) while (--n >= 0) *out++ = *in++; else if (out < in) while (--n >= 0) out[n] = in[n]; } static bzero(in, n) register char *in; register int n; { while (--n >= 0) *in++ = 0; } #endif NOUNIX