Main Page Class Hierarchy Compound List File List Compound Members File Members

# ahputaway.c

Go to the documentation of this file.

    00001
    00002 /*
    00003  *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
    00004  *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
    00005  *
    00006  *    $Id: ahputaway_8c-source.html 2161 2006-05-19 16:55:03Z paulf $
    00007  *
    00008  *    Revision history:
    00009  *     $Log$
    00009  *     Revision 1.1  2006/05/19 16:55:01  paulf
    00009  *     first inclusion
    00009  *
    00010  *     Revision 1.4  2001/04/17 17:21:18  davidk
    00011  *     Added a _STDIO_H_ conditional definition in order to get a function
    00012  *     prototype declared in an includeded header file.  See comment in code
    00013  *     for more detail.
    00014  *
    00015  *     Revision 1.3  2001/04/12 03:47:36  lombard
    00016  *     Major reorganization of AHPA_next to improve efficiency
    00017  *     Reformatted code; cleaned up lots of comments and logit calls
    00018  *     Removed mapping of NC component codes (only needed at UW)
    00019  *
    00020  *     moved mallocs to AHPA_init instead of in AHPA_next_evt.
    00021  *     Removed different path delimiters; '/' works for both NT and Unix.
    00022  *
    00023  *     Revision 1.2  2000/03/10 23:25:51  davidk
    00024  *     changed the ahputaway routines to match the new PA_XXX routines
    00025  *     in putaway.c.  Moved the AHPA_XXX function prototypes to the ah header file.
    00026  *
    00027  *     Revision 1.1  2000/02/14 18:51:48  lucky
    00028  *     Initial revision
    00029  *
    00030  *
    00031  */
    00032
    00033 /* ah.c
    00034 These are the five routines which plug into xxtrace_save, and cause the trace
    00035 data snippets to be put away into a AH format trace files.  These are the
    00036 model for other put away routines, such as flat files of various formats.
    00037
    00038
    00039   Thu Jul 22 14:56:37 MDT 1999 Lucky Vidmar
    00040     Major structural changes to accomodate making all putaway routines
    00041     into library calls so that they can be shared between trig2disk
    00042     and wave2disk. Eliminated global variables set and allocated outside
    00043     of this file. We should only have static globals from now on, with
    00044     everything else being passed in via the putaway.c calls.
    00045    */
    00046
    00047
    00048 #include <math.h>
    00049 #include <stdio.h>
    00050 #include <stdlib.h>
    00051 #include <string.h>
    00052 #include <earthworm.h>
    00053 #include <time.h>
    00054 #include <trace_buf.h>
    00055 #include <swap.h>
    00056 #include <ws_clientII.h>
    00057 #include <ahhead.h>
    00058 #include <pa_subs.h>
    00059 #ifdef _WINNT
    00060 # ifdef _INC_STDIO
    00061 /* DavidK: the version of Microsoft compiler I have defines _INC_STDIO
    00062    in stdio.h, instead of _STDIO_H_ which is defined in the sun stdio.h
    00063    There is an ifdef in rpc_nt/xdr.h that checks for _STDIO_H_ before
    00064    declaring a prototype for xdrstdio_create() */
    00065 #  define _STDIO_H_
    00066 # endif
    00067 #include <rpc_nt/types.h>
    00068 #include <rpc_nt/xdr.h>
    00069 #else
    00070 #include <rpc/types.h>
    00071 #include <rpc/xdr.h>
    00072 #endif
    00073
    00074 #define MAXTXT           150
    00075
    00076 static  char    AHDir[2*MAXTXT + 4];
    00077 static  ahhed *AhHead;                  /* from ahhead.h */
    00078 static  float *mydata;                  /* output data */
    00079
    00080 /* static functions */
    00081 static  int  gethead(ahhed *, FILE *);
    00082 static  int  puthead (ahhed *, FILE *);
    00083 static  int  size (ahhed *);
    00084 static  int  tohead (int, FILE *);
    00085 static  int  getdata (ahhed *, char *, FILE *);
    00086 static  int  putdata (ahhed *, char *, FILE *);
    00087 static  int  putrecord (ahhed *, char *, FILE *);
    00088 static  int  getrecord (ahhed *, char *, FILE *);
    00089 static  int  getrecord2 (ahhed *, char **, FILE *);
    00090 static  int  gogethead (int, ahhed *, FILE *);
    00091 static  int  gogetrecord (int, ahhed *, char *, FILE *);
    00092 static  int  logger (char *, ahhed *);
    00093 static  int  out_is_tty (void);
    00094 static  int  in_is_tty (void);
    00095 static  char *mkdatspace(ahhed *);
    00096 static  int  get_null_head (ahhed *);
    00097 static  int  acpy (char *, char *, unsigned);
    00098 static  void ah_error (char *, char *, int);
    00099 static  int  maxamp (ahhed *, char *);
    00100 static  int  xdr_gethead (ahhed *, XDR *);
    00101 static  int  xdr_puthead (ahhed *, XDR *);
    00102 static  int  xdr_tohead (int, XDR *);
    00103 static  int  xdr_getdata (ahhed *, char *, XDR *);
    00104 static  int  xdr_putdata (ahhed *, char *, XDR *);
    00105 static  int  xdr_putrecord (ahhed *, char *, XDR *);
    00106 static  int  xdr_getrecord (ahhed *, char *, XDR *);
    00107 static  int  xdr_getrecord2 (ahhed *, char **, XDR *);
    00108 static  int  xdr_gogethead (int, ahhed *, XDR *);
    00109 static  int  xdr_gogetrecord (int, ahhed *, char *, XDR *);
    00110 static  int  xdr_ahhead (XDR *, ahhed *);
    00111
    00112
    00113
    00114 /* Initialization function,
    00115 *       This is the Put Away startup intializer. This is called when    *
    00116 *       the system first comes up. Here is a chance to look around      *
    00117 *       and see if it's possible to do business, and to complain        *
    00118 *       if not ,BEFORE an event has to be processed.                    *
    00119  */
    00120 int AHPA_init (long *OutBufferLen, char *OutDir, int debug)
    00121 {
    00122
    00123   if ( (AhHead = (ahhed *)calloc(sizeof(ahhed), 1)) == (ahhed *)NULL)
    00124   {
    00125     logit("e", "AHPA_init: out of memory for ahhed\n");
    00126     return EW_FAILURE;
    00127   }
    00128
    00129   if ( (mydata = (float *)calloc(sizeof(float),
    00130                                  (size_t)(*OutBufferLen/sizeof(float))))
    00131        == (float *)NULL)
    00132   {
    00133     logit("e", "AHPA_init: out of memory for data buffer\n");
    00134     return EW_FAILURE;
    00135   }
    00136
    00137   /* Make sure that the top level output directory exists */
    00138   if (CreateDir (OutDir) != EW_SUCCESS)
    00139   {
    00140     logit ("e", "AHPA_init: Call to CreateDir failed\n");
    00141     return EW_FAILURE;
    00142   }
    00143
    00144   return EW_SUCCESS; /* how could we do less? */
    00145 }
    00146
    00147 /****************************************************************************
    00148 *       This is the Put Away event initializer. It's called when a snippet  *
    00149 *       has been received, and is about to be processed.                    *
    00150 *       It gets to see the pointer to the TraceRequest array,               *
    00151 *       and the number of loaded trace structures.                          *
    00152 *****************************************************************************/
    00153 int AHPA_next_ev (TRACE_REQ *ptrReq, int nReq, char *OutDir,
    00154                   char *EventDate, char *EventTime, int debug)
    00155 {
    00156   /* create directory for this event */
    00157   sprintf (AHDir, "%s/%s%s", OutDir, EventDate, EventTime);
    00158   if (CreateDir (AHDir) != EW_SUCCESS)
    00159   {
    00160     logit ("e", "AHPA_init: Call to CreateDir failed\n");
    00161     return EW_FAILURE;
    00162   }
    00163
    00164   return EW_SUCCESS;
    00165 }
    00166
    00167 /*****************************************************************************
    00168  *   This is the working entry point into the disposal system. This routine  *
    00169  *   gets called for each trace snippet which has been recovered. It gets    *
    00170  *   to see the corresponding SNIPPET structure, and the event id            *
    00171  *****************************************************************************/
    00172 /* Process one channel of data */
    00173 int AHPA_next (TRACE_REQ *getThis, double GapThresh,
    00174                long OutBufferLen, int debug)
    00175 {
    00176   FILE *fid;                      /* xdr routines don't like creat */
    00177   XDR xdr;
    00178   TRACE_HEADER *wf;
    00179   char        *msg_p;        /* pointer into tracebuf data */
    00180   short       *s_data;
    00181   long        *l_data;
    00182   float       *f_data;
    00183   float        fill = 0.0;
    00184   int          j;
    00185   int          gap_count = 0;
    00186   long         nsamp, nfill;
    00187   long         nfill_max = 0l;
    00188   long         nsamp_this_scn = 0l;
    00189   long         this_size;
    00190   double       starttime, endtime; /* times for current scn         */
    00191   double       samprate;
    00192   double       AH_starttime;
    00193   struct tm    *time;
    00194   time_t       ltime;
    00195   char         datatype; /* 's' for short, 'l' for long */
    00196   char         ahfile[MAXTXT];    /* the name of the ah file */
    00197
    00198   if ( (msg_p = getThis->pBuf) == NULL)   /* pointer to first message */
    00199   {
    00200     logit("e", "AHPA_next: message buffer is NULL\n");
    00201     return EW_FAILURE;
    00202   }
    00203
    00204   wf = (TRACE_HEADER *) msg_p;
    00205
    00206   sprintf (ahfile, "%s/%s.%s.%s", AHDir, wf->sta, wf->chan, wf->net);
    00207
    00208   if ( (fid = fopen(ahfile,"w+")) == NULL)
    00209   {
    00210     logit("e", "AHPA_next: cannot create %s\n", ahfile);
    00211     return(EW_FAILURE);
    00212   }
    00213
    00214   if (WaveMsgMakeLocal(wf) < 0)
    00215   {
    00216     logit("e", "AHPA_next: unknown trace data type: %s\n",
    00217           wf->datatype);
    00218     return( EW_FAILURE );
    00219   }
    00220
    00221   nsamp = wf->nsamp;
    00222   starttime = wf->starttime;
    00223   endtime = wf->endtime;
    00224   samprate = wf->samprate;
    00225   if (samprate < 0.01)
    00226   {
    00227     logit("et", "unreasonable samplerate (%f) for <%s.%s.%s>\n",
    00228           samprate, wf->sta, wf->chan, wf->net);
    00229     return( EW_FAILURE );
    00230   }
    00231   AH_starttime = starttime;
    00232   datatype = 'n';
    00233   if (wf->datatype[0] == 's' || wf->datatype[0] == 'i')
    00234   {
    00235     if (wf->datatype[1] == '2') datatype = 's';
    00236     else if (wf->datatype[1] == '4') datatype = 'l';
    00237   }
    00238   else if (wf->datatype[0] == 't' || wf->datatype[0] == 'f')
    00239   {
    00240     if (wf->datatype[1] == '4') datatype = 'f';
    00241   }
    00242   if (datatype == 'n')
    00243   {
    00244     logit("et", "AHPA_next: unsupported datatype: %s\n", datatype);
    00245     return( EW_FAILURE );
    00246   }
    00247
    00248   /* loop through all the messages for this s-c-n */
    00249   while (1)
    00250   {
    00251     /* advance message pointer to the data */
    00252     msg_p += sizeof(TRACE_HEADER);
    00253
    00254     /* check for sufficient memory in output buffer */
    00255     this_size = (nsamp_this_scn + nsamp ) * sizeof(float);
    00256     if ( OutBufferLen < (this_size + (long)sizeof(ahhed) ))
    00257     {
    00258       logit( "e", "out of space for <%s.%s.%s>; saving short trace.\n",
    00259              wf->sta, wf->chan, wf->net);
    00260       break;
    00261     }
    00262
    00263     switch( datatype )
    00264     {
    00265     case 's':
    00266       s_data = (short *)msg_p;
    00267       for ( j = 0; j < nsamp ; j++, nsamp_this_scn++ )
    00268         mydata[nsamp_this_scn] = (float) s_data[j];
    00269       msg_p += sizeof(short) * nsamp;
    00270       break;
    00271     case 'l':
    00272       l_data = (long *)msg_p;
    00273       for ( j = 0; j < nsamp; j++, nsamp_this_scn++ )
    00274         mydata[nsamp_this_scn] = (float) l_data[j];
    00275       msg_p += sizeof(long) * nsamp;
    00276       break;
    00277     case 'f':
    00278       f_data = (float *)msg_p;
    00279       for ( j = 0; j < nsamp; j++, nsamp_this_scn++ )
    00280         mydata[nsamp_this_scn] = f_data[j];
    00281       msg_p += sizeof(float) * nsamp;
    00282       break;
    00283     }
    00284
    00285     /* End-check based on length of snippet buffer */
    00286     if ((long) msg_p >= ((long) getThis->actLen + (long) getThis->pBuf))
    00287     {
    00288       if (debug == 1)
    00289         logit ("", "Setting done for <%s.%s.%s>\n", wf->sta, wf->chan,
    00290                wf->net);
    00291       break; /* Break out of the while(1) loop 'cuz we're done */
    00292     }
    00293
    00294     /* msg_p has been advanced to the next TRACE_BUF; localize bytes *
    00295      * and check for gaps.                                           */
    00296     wf = (TRACE_HEADER *) msg_p;
    00297     if (WaveMsgMakeLocal(wf) < 0)
    00298     {
    00299       logit("e", "AHPA_next: unknown trace data type: %s\n",
    00300             wf->datatype);
    00301       return( EW_FAILURE );
    00302     }
    00303     nsamp = wf->nsamp;
    00304     starttime = wf->starttime;
    00305     /* starttime is set for new packet; endtime is still set for old packet */
    00306     if ( endtime + ( 1.0/samprate ) * GapThresh < starttime )
    00307     {
    00308       /* there's a gap, so fill it */
    00309       logit("e", "gap in %s.%s.%s: %lf: %lf\n", wf->sta, wf->chan, wf->net,
    00310             endtime, starttime - endtime);
    00311       nfill = (long) (samprate * (starttime - endtime) - 1);
    00312       if ( (nsamp_this_scn + nfill) * (long)sizeof(float) > OutBufferLen )
    00313       {
    00314         logit("e",
    00315               "bogus gap (%d); skipping\n", nfill);
    00316         return(EW_FAILURE);
    00317       }
    00318       /* do the filling */
    00319       for ( j = 0; j < nfill; j++, nsamp_this_scn ++ )
    00320         mydata[nsamp_this_scn] = fill;
    00321       /* keep track of how many gaps and the largest one */
    00322       gap_count++;
    00323       if (nfill_max < nfill)
    00324         nfill_max = nfill;
    00325     }
    00326     /* Advance endtime to the new packet;        *
    00327      * process this packet in the next iteration */
    00328     endtime = wf->endtime;
    00329   } /* while(1) */
    00330
    00331   /*  All data read.  Now fill in header and write AH file */
    00332   AhHead->record.ndata = (long)nsamp_this_scn;  /* samples in trace */
    00333   AhHead->record.delta = (float) (1.0/samprate);   /* sample period */
    00334   ltime = (time_t)AH_starttime;
    00335   /* gmt time makes months from 0 - 11 */
    00336   time = gmtime( &ltime );
    00337   AhHead->record.abstime.yr = (short) (time->tm_year + 1900l);
    00338   AhHead->record.abstime.mo = (short)(time->tm_mon + 1);
    00339   AhHead->record.abstime.day = (short)time->tm_mday;
    00340   AhHead->record.abstime.hr = (short)time->tm_hour;
    00341   AhHead->record.abstime.mn = (short)time->tm_min;
    00342   AhHead->record.abstime.sec = (float)time->tm_sec +
    00343     (float)(starttime - (long)starttime);
    00344   AhHead->record.type = FLOAT;
    00345
    00346   /* set the maxamp value */
    00347   if (maxamp(AhHead, (char *)mydata) < 0)
    00348   {
    00349     logit("e", "AHPA_next: bad data type for maxamp\n");
    00350     return EW_FAILURE;
    00351   }
    00352
    00353   strcpy(AhHead->station.code, wf->sta);   /* station name */
    00354   strcpy(AhHead->station.chan, wf->chan);
    00355
    00356   /* here's a kludge using sensor type for network */
    00357   strcpy(AhHead->station.stype, wf->net);
    00358
    00359   /* Write an AH file */
    00360   xdrstdio_create(&xdr, fid, XDR_ENCODE);
    00361   xdr_putrecord(AhHead, (char *) mydata, &xdr);
    00362   fclose(fid);
    00363   XDR_DESTROY(&xdr);
    00364
    00365   if (gap_count)
    00366     logit("e", "AHPA_next: %d gaps; largest %ld for <%s><%s><%s>\n",
    00367           gap_count, nfill_max, wf->sta, wf->chan, wf->net);
    00368
    00369   return(EW_SUCCESS);
    00370 }
    00371
    00372 /************************************************************************
    00373 *       This is the Put Away end event routine. It's called after we've     *
    00374 *       finished processing one event.                                  *
    00375 *************************************************************************/
    00376 int AHPA_end_ev (int debug)
    00377 {
    00378   /* what else is there to do? */
    00379   return( EW_SUCCESS );
    00380 }
    00381
    00382
    00383 /************************************************************************
    00384 *       This is the Put Away close routine. It's called after when      *
    00385 *       we're being shut down.                                          *
    00386 *************************************************************************/
    00387 int AHPA_close (int debug)
    00388 {
    00389   free(AhHead);
    00390   free(mydata);
    00391
    00392   return( EW_SUCCESS );
    00393 }
    00394
    00395
    00396 /*      low level i/o routines for ah format records
    00397
    00398  *              -- witte        6 june 85
    00399  *
    00400  *      gethead routine was altered so it can read the ah structure
    00401  *      on a sun4 machine  - Mahdad Parsi June 4 1992.
    00402  */
    00403
    00404 /* Function prototypes */
    00405 int             get_null_head (ahhed *);
    00406 int             xdr_ahhead(XDR *, ahhed *);
    00407 extern  int             isatty (int);
    00408
    00409 /* ah error processing */
    00410
    00411 int     ah_errno = 0;
    00412 int     ah_nerr = 10;
    00413
    00414 /* ah error numbers */
    00415 #define AE_RHED         1       /* error reading header */
    00416 #define AE_DTYPE        2       /* bad data type        */
    00417 #define AE_WHED         3       /* error writing header */
    00418 #define AE_RDATA        4       /* error reading data   */
    00419 #define AE_WDATA        5       /* error writing data   */
    00420 #define AE_WRECORD      6       /* error writing record */
    00421 #define AE_RRECORD      7       /* error reading record */
    00422 #define AE_TTYOUT       8       /* binary going to tty  */
    00423 #define AE_TTYIN        9       /* binary coming from tty       */
    00424
    00425 /* ah errlist */
    00426
    00427 char    *ah_errlist[] = {
    00428   "no error",           /* 0    no error        */
    00429   "read header error",  /* 1    AE_RHED         */
    00430   "bad data type",      /* 2    AE_DTYPE        */
    00431   "write header error", /* 3    AE_WHED         */
    00432   "read data error",    /* 4    AE_RDATA        */
    00433   "write data error",   /* 5    AE_WDATA        */
    00434   "write record error", /* 6    AE_WRECORD      */
    00435   "read record error",  /* 7    AE_RRECORD      */
    00436   "tty can't get binary",       /* 8    AE_TTYOUT       */
    00437   "tty can't send binary"       /* 9    AE_TTYIN        */
    00438 };
    00439
    00440 /*      gethead
    00441  *              gets the next header from the stream pointed to by
    00442  *              file_pt and returns this header in the structure head.
    00443  *              file_pt is assumed to be positioned at the next header,
    00444  *              and does not search.
    00445  *
    00446  *      added:  Reads the input fiule byte by byte and sets the appropriate
    00447  *              structure fields in the ah header. June 4 1992.
    00448  *
    00449  *      returns:
    00450  *                      1               ->      no error
    00451  *                      -1              ->      not enough head to read
    00452  *                      -2              ->      bad data type
    00453  */
    00454 static  int     gethead(ahhed *head, FILE *file_pt)
    00455 {
    00456   int   ierr=0,    /* error indicator */
    00457     i;         /* counter variable */
    00458   int     sizefloat,  /* sizeofloat()  */
    00459     sizedouble,  /* sizeodouble()  */
    00460     sizelong,  /* sizeolong()  */
    00461     sizeshort;  /* sizeoshort()  */
    00462
    00463   sizedouble = sizeof(double) ;
    00464   sizelong = sizeof(long) ;
    00465   sizefloat = sizeof(float) ;
    00466   sizeshort = sizeof(short) ;
    00467
    00468   /* station info */
    00469   if ((ierr = fread(head->station.code, CODESIZE, 1, file_pt)) == -1) goto CH4ERROR;
    00470   if ((ierr = fread(head->station.chan, CHANSIZE, 1, file_pt)) == -1) goto CH4ERROR;
    00471   if ((ierr = fread(head->station.stype, STYPESIZE, 1, file_pt)) == -1) goto CH4ERROR;
    00472   if ((ierr = fread(&head->station.slat, sizefloat, 1, file_pt)) == -1) goto CH4ERROR;
    00473   if ((ierr = fread(&head->station.slon, sizefloat, 1, file_pt)) == -1) goto CH4ERROR;
    00474   if ((ierr = fread(&head->station.elev, sizefloat, 1, file_pt)) == -1) goto CH4ERROR;
    00475   if ((ierr = fread(&head->station.DS, sizefloat, 1, file_pt)) == -1) goto CH4ERROR;
    00476   if ((ierr = fread(&head->station.A0, sizefloat, 1, file_pt)) == -1) goto CH4ERROR;
    00477   for (i=0; i< NOCALPTS ; i++) {
    00478     if ((ierr=fread(&head->station.cal[i].pole.r,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00479     if ((ierr=fread(&head->station.cal[i].pole.i,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00480     if ((ierr=fread(&head->station.cal[i].zero.r,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00481     if ((ierr=fread(&head->station.cal[i].zero.i,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00482   } /* for */
    00483
    00484   /* event info */
    00485   if ((ierr=fread(&head->event.lat,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00486   if ((ierr=fread(&head->event.lon,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00487   if ((ierr=fread(&head->event.dep,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00488   if ((ierr=fread(&head->event.ot.yr,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00489   if ((ierr=fread(&head->event.ot.mo,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00490   if ((ierr=fread(&head->event.ot.day,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00491   if ((ierr=fread(&head->event.ot.hr,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00492   if ((ierr=fread(&head->event.ot.mn,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00493   if ((ierr=fread(&head->event.ot.sec,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00494   if ((ierr=fread(head->event.ecomment,COMSIZE,1,file_pt)) == -1) goto CH4ERROR;
    00495
    00496
    00497   /* record info */
    00498   if ((ierr=fread(&head->record.type,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00499   if ((ierr=fread(&head->record.ndata,sizelong,1,file_pt)) == -1) goto CH4ERROR;
    00500   if ((ierr=fread(&head->record.delta,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00501   if ((ierr=fread(&head->record.maxamp,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00502   if ((ierr=fread(&head->record.abstime.yr,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00503   if ((ierr=fread(&head->record.abstime.mo,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00504   if ((ierr=fread(&head->record.abstime.day,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00505   if ((ierr=fread(&head->record.abstime.hr,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00506   if ((ierr=fread(&head->record.abstime.mn,sizeshort,1,file_pt)) == -1) goto CH4ERROR;
    00507   if ((ierr=fread(&head->record.abstime.sec,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00508   if ((ierr=fread(&head->record.rmin,sizefloat,1,file_pt)) == -1) goto CH4ERROR;
    00509   if ((ierr=fread(head->record.rcomment,COMSIZE,1,file_pt)) == -1) goto CH4ERROR;
    00510   if ((ierr=fread(head->record.log,LOGSIZE,1,file_pt)) == -1) goto CH4ERROR;
    00511
    00512
    00513   /* extra */
    00514   for (i=0; i < NEXTRAS ; i++) {
    00515     if ((ierr=fread(&head->extra[i],sizefloat, 1,file_pt)) == -1) goto CH4ERROR;
    00516   }
    00517
    00518
    00519   if((head->record.type < TYPEMIN) || (head->record.type > TYPEMAX))
    00520   {
    00521     get_null_head(head);
    00522     ierr = -2;
    00523     ah_errno= AE_DTYPE;
    00524   }
    00525
    00526  CH4ERROR:  if (ierr == -1)
    00527  {
    00528    get_null_head(head);
    00529    ierr = -1;
    00530    ah_errno= AE_RHED;
    00531  }
    00532   return(ierr);
    00533
    00534 }
    00535
    00536
    00537
    00538 /*      puthead
    00539  *              writes the header head onto the stream pointed to by
    00540  *              file_pt.
    00541  *      returns:
    00542  *                      1               ->      no error
    00543  *                      -1              ->      error writing header
    00544  */
    00545 static  int     puthead (ahhed *head, FILE *file_pt)
    00546 {
    00547   int   ierr = 0;
    00548
    00549   if((ierr= fwrite((char *)head,sizeof(ahhed),1,file_pt)) != 1)
    00550   {
    00551     ah_errno= AE_WHED;
    00552     ierr= -1;
    00553   }
    00554   return(ierr);
    00555 }
    00556
    00557
    00558
    00559 /*      size
    00560  *              returns the size (in bytes) of the data type given by
    00561  *              head->record.type.
    00562  *      returns:
    00563  *                      size of data type       ->      no error
    00564  *                      -1                      ->      unknown data type
    00565  */
    00566 static  int     size (ahhed *head)
    00567 {
    00568   int   type_size = 0;
    00569
    00570   switch(head->record.type)
    00571   {
    00572   case 1:               /* real time series */
    00573     type_size= sizeof(float);
    00574     break;
    00575   case 2:               /* complex time series */
    00576     type_size= sizeof(complex);
    00577     break;
    00578   case 3:               /* real x,y pairs */
    00579     type_size= sizeof(vector);
    00580     break;
    00581   case 4:               /* x real, y complex, or real x,y,z */
    00582     type_size= sizeof(tensor);
    00583     break;
    00584   case 5:               /* complex x,y pairs */
    00585     type_size= 2*sizeof(complex);
    00586     break;
    00587   case 6:               /* double */
    00588     type_size=sizeof(double);
    00589     break;
    00590   default:      /* unknown data type */
    00591     type_size= -1;
    00592     ah_errno= AE_DTYPE;
    00593     break;
    00594   }
    00595   return(type_size);
    00596 }
    00597
    00598
    00599 /*      tohead
    00600  *              positions the read/write head to the beginning of the
    00601  *              n-th header in the file pointed to by file_pt.
    00602  *      returns:
    00603  *                      n       ->      no error
    00604  *                      -1      ->      not enough heads
    00605  *                      -2      ->      bad seek
    00606  */
    00607 static  int     tohead (int n, FILE *file_pt)
    00608 {
    00609   ahhed head;
    00610   int   i,ierr;
    00611
    00612   rewind(file_pt);
    00613   for(i=1; i<n; ++i)
    00614   {
    00615     if(gethead(&head,file_pt) == 1)
    00616     {
    00617       if(fseek(file_pt,(long)(head.record.ndata)*(size(&head)),1) == -1)
    00618       {
    00619         ierr = -2;      /* bad seek */
    00620         ah_errno= AE_RHED;
    00621         return(ierr);
    00622       }
    00623     }
    00624     else
    00625     {
    00626       ierr = -1;        /* not enough head */
    00627       ah_errno= AE_RHED;
    00628       return(ierr);
    00629     }
    00630   }
    00631   return(i);    /* success */
    00632 }
    00633
    00634
    00635
    00636 /*      getdata
    00637  *              reads from the file pointed to by file_pt into
    00638  *              the array pointed to by array.  It assumes that
    00639  *              the read/write head is positioned correctly
    00640  *              (i.e., right after the header), and does not
    00641  *              search.  Works for any allowed data type.
    00642  *      returns:
    00643  *                      number of elements read ->      OK
    00644  *                      -1                      ->      error
    00645  */
    00646 static  int     getdata (ahhed *head, char *array, FILE *file_pt)
    00647 {
    00648   int ierr = 0;
    00649
    00650   if((ierr = fread(array,size(head),(int)head->record.ndata,file_pt)) != (int)head->record.ndata)
    00651   {
    00652     ah_errno= AE_RDATA;
    00653     ierr = -1;
    00654   }
    00655
    00656   return(ierr);
    00657 }
    00658
    00659
    00660 /*      putdata
    00661  *              writes array to the file pointed to by
    00662  *              file_pt.  Works for any allowed data type.
    00663  *      returns:
    00664  *                      number of elements written      ->      OK
    00665  *                      -1                      ->      error
    00666  */
    00667 static  int     putdata (ahhed *head, char *array, FILE *file_pt)
    00668 {
    00669   int   ierr = 0;
    00670
    00671   if((ierr = fwrite(array,size(head),(int)head->record.ndata,file_pt)) != (int)head->record.ndata)
    00672   {
    00673     ah_errno= AE_WDATA;
    00674     ierr = -1;
    00675   }
    00676   return(ierr);
    00677 }
    00678
    00679
    00680 /*      putrecord
    00681  *              writes head and array to the file pointed to by
    00682  *              file_pt.  Works for any allowed data type.
    00683  *      returns:
    00684  *                      0       ->      OK
    00685  *                      -1      ->      error writing header
    00686  *                      -2      ->      error writing data
    00687  */
    00688 static  int     putrecord (ahhed *head, char *array, FILE *file_pt)
    00689 {
    00690   int   ierr = 0;
    00691
    00692   (puthead(head,file_pt) == 1) ? ((putdata(head,array,file_pt) < 0) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    00693   if(ierr)
    00694     ah_errno= AE_WRECORD;
    00695
    00696   return(ierr);
    00697 }
    00698
    00699
    00700 /*      getrecord
    00701  *              gets header and data from the file pointed to by
    00702  *              file_pt and puts them in head and array.  It assumes
    00703  *              that the read/write head is positioned at the beginning
    00704  *              of the header, and does not search.  Obviously, calling
    00705  *              routine must have allocated enough space.
    00706  *      returns:
    00707  *                      0       ->      OK
    00708  *                      -1      ->      error reading header
    00709  *                      -2      ->      error reading data
    00710  */
    00711 static  int     getrecord (ahhed *head, char *array, FILE *file_pt)
    00712 {
    00713   int   ierr = 0;
    00714
    00715   (gethead(head,file_pt) == 1) ? ((getdata(head,array,file_pt) < 0) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    00716   if(ierr)
    00717     ah_errno= AE_RRECORD;
    00718   return(ierr);
    00719 }
    00720
    00721 /*
    00722  *      getrecord2
    00723  *              gets header and data from the file pointed to by
    00724  *              file_pt and puts them in head and array.  It assumes
    00725  *              that the read/write head is positioned at the beginning
    00726  *              of the header, and does not search (although it does
    00727  *              some error checking).  Space for array is allocated, so
    00728  *              be sure to pass a pointer to the data pointer. Got it?
    00729  *      returns:
    00730  *                      0       ->      ok
    00731  *                      -1      ->      error reading record
    00732  *                      -2      ->      error allocating space for data
    00733  */
    00734 static  int     getrecord2 (ahhed *head, char **array, FILE *file_pt)
    00735 {
    00736   int   ierr = 0;
    00737   int   gethead();
    00738   char  *mkdatspace();
    00739
    00740   if(gethead(head, file_pt) != 1) {
    00741     ierr = -1;
    00742     return(ierr);
    00743   }
    00744
    00745   *array= mkdatspace(head);
    00746   if(*array == NULL) {
    00747     ierr= -2;
    00748     return(ierr);
    00749   }
    00750
    00751   if(getdata(head,*array,file_pt) < 0)
    00752     ierr= -1;
    00753
    00754   return(ierr);
    00755 }
    00756
    00757
    00758 /*      gogethead
    00759  *              gets n-th header from the stream pointed to by
    00760  *              file_pt and returns this header in the structure
    00761  *              head.
    00762  *      returns:
    00763  *                      0       ->      OK
    00764  *                      -1      ->      stream not long enough
    00765  *                      -2      ->      error reading header
    00766  */
    00767 static  int     gogethead (int n, ahhed *head, FILE *file_pt)
    00768 {
    00769   int   ierr = 0;
    00770
    00771   (tohead(n,file_pt) == n) ? ((gethead(head,file_pt) < 1) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    00772   return(ierr);
    00773 }
    00774
    00775
    00776 /*      gogetrecord
    00777  *              gets n-th record (header and data) from the stream
    00778  *              pointed to by file_pt and places it in head and array.
    00779  *              Calling routine must allocate enough space.
    00780  *      returns:
    00781  *                      0       ->      OK
    00782  *                      -1      ->      stream not long enough
    00783  *                      -2      ->      error reading record
    00784  */
    00785 static  int     gogetrecord (int n, ahhed *head, char *array, FILE *file_pt)
    00786 {
    00787   int   ierr = 0;
    00788
    00789   (tohead(n,file_pt) == n) ? ((getrecord(head,array,file_pt) < 0) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    00790   return(ierr);
    00791 }
    00792
    00793 /* logger adds a 10 character comment to the log section of the header
    00794  * comment should be passed as a character pointer must be terminated
    00795  * by a ';' and a `/0`
    00796  * returns:
    00797  *      logger =  0  -> log info added to header structure
    00798  *      logger = -1  -> no ';', added
    00799  *      logger = -2  -> input string greater than LOGENT
    00800  *                      input truncated to allowable limit
    00801  *      logger = -3  -> attempt to make log string greater than LOGSIZE
    00802  *                      input comment truncated to fit
    00803  *
    00804  *                      written by Tom Boyd   6/10/85
    00805  */
    00806
    00807 static  int logger (char *char_pt, ahhed *head_pt)
    00808 {
    00809   int org,in,err,diff;
    00810   char *strncat();
    00811
    00812   err=0;
    00813
    00814   /* find length of log array and input array  */
    00815
    00816   org=strlen(head_pt->record.log);  /*log array*/
    00817   in=strlen(char_pt);  /*input array*/
    00818
    00819   /* check for a terminating ':' in the input array */
    00820
    00821   if(*(char_pt+in-1) != ';')
    00822   {                   /* no semicolon----add it*/
    00823     err=(-1);
    00824     *(char_pt+in)=';';
    00825     *(char_pt+in+1)='\0';
    00826     in+=1;
    00827   }
    00828
    00829   /* check the length of the input array */
    00830
    00831   if(in > LOGENT)
    00832   {                  /* entry length too long-----truncate it*/
    00833     err=(-2);
    00834     *(char_pt+LOGENT-1)=';';
    00835     *(char_pt+LOGENT)='\0';
    00836     in=LOGENT;
    00837   }
    00838
    00839   /* check combined length of array and new input and add it */
    00840
    00841   diff=LOGSIZE-(org+in);
    00842   if(diff == -in) return(-3);  /* no room left in log array */
    00843   if(diff < 0)diff*=(-1),err=(-3);  /*partial room left----use it */
    00844   strncat(head_pt->record.log,char_pt,diff); /* cat two strings */
    00845
    00846   return(err);
    00847 }
    00848
    00849
    00850
    00851 /*      out_is_tty
    00852  *              determines whether stdout is being sent to screen.
    00853  *      returns:
    00854  *                      0       ->      stdout is not tty
    00855  *                      1       ->      stdout is tty
    00856  */
    00857 static  int     out_is_tty (void)
    00858 {
    00859
    00860   if(isatty(1)) /* sun specific --- stdout */
    00861   {
    00862     ah_errno= AE_TTYOUT;
    00863     return(1);
    00864   }
    00865   return(0);
    00866 }
    00867
    00868
    00869 /*      in_is_tty
    00870  *              determines whether stdin is tty
    00871  *      returns:
    00872  *                      0       ->      stdin is not tty
    00873  *                      1       ->      stdin is tty
    00874  */
    00875 static  int     in_is_tty (void)
    00876 {
    00877
    00878   if(isatty(0)) /* sun specific --- stdin */
    00879   {
    00880     ah_errno= AE_TTYIN;
    00881     return(1);
    00882   }
    00883   return(0);
    00884 }
    00885
    00886
    00887 /*      mkdatspace
    00888  *              allocates enough space for the data array, and
    00889  *              returns a pointer to the memory location, or
    00890  *              NULL if failure.
    00891  *      returns:
    00892  *                      character pointer       ->      success
    00893  *                      NULL                    ->      failure
    00894  */
    00895 static  char *mkdatspace(ahhed *head)
    00896 {
    00897   /*      dont redefine calloc (NT doesn't like it), return the type expected
    00898           withers 9/98
    00899
    00900           char  *calloc();
    00901
    00902           return(calloc((unsigned)head->record.ndata,(unsigned)size(head)));
    00903   */
    00904   return((char *)calloc((unsigned)head->record.ndata,(unsigned)size(head)));
    00905 }
    00906
    00907
    00908
    00909 static int      get_null_head (ahhed *hed)
    00910 {
    00911   int   i;
    00912   char  *strcpy();
    00913
    00914   strcpy(hed->station.code,"null");
    00915   strcpy(hed->station.chan,"null");
    00916   strcpy(hed->station.stype,"null");
    00917   hed->station.slat= 0.0;
    00918   hed->station.slon= 0.0;
    00919   hed->station.elev= 0.0;
    00920   hed->station.DS= 0.0;
    00921   hed->station.A0= 0.0;
    00922   for(i=0; i< NOCALPTS; ++i)
    00923   {
    00924     hed->station.cal[i].pole.r= 0.0;
    00925     hed->station.cal[i].pole.i= 0.0;
    00926     hed->station.cal[i].zero.r= 0.0;
    00927     hed->station.cal[i].zero.i= 0.0;
    00928   }
    00929
    00930   hed->event.lat= 0.0;
    00931   hed->event.lon= 0.0;
    00932   hed->event.dep= 0.0;
    00933   hed->event.ot.yr= (short)0;
    00934   hed->event.ot.mo= (short)0;
    00935   hed->event.ot.day= (short)0;
    00936   hed->event.ot.hr= (short)0;
    00937   hed->event.ot.mn= (short)0;
    00938   hed->event.ot.sec= 0.0;
    00939   strcpy(hed->event.ecomment,"null");
    00940
    00941   hed->record.type= (short)0;
    00942   hed->record.ndata= 0L;
    00943   hed->record.delta= 0.0;
    00944   hed->record.maxamp= 0.0;
    00945   hed->record.abstime.yr= (short)0;
    00946   hed->record.abstime.mo= (short)0;
    00947   hed->record.abstime.day= (short)0;
    00948   hed->record.abstime.hr= (short)0;
    00949   hed->record.abstime.mn= (short)0;
    00950   hed->record.abstime.sec= 0.0;
    00951   hed->record.rmin= 0.0;
    00952   strcpy(hed->record.rcomment,"null");
    00953   strcpy(hed->record.log,"null");
    00954
    00955   for(i=0; i< NEXTRAS; ++i)
    00956     hed->extra[i]= 0.0;
    00957
    00958   return 0;
    00959 }
    00960
    00961 /* acpy(from,to,nbytes) copies nbytes from the array "from" to the
    00962  *      array "to".
    00963  */
    00964 static int      acpy (char *from, char *to, unsigned nbytes)
    00965 {
    00966   while(nbytes--)
    00967     *from++ = *to++;
    00968   return 0;
    00969 }
    00970
    00971
    00972 /* print ah format error message and die */
    00973 static  void ah_error (char *s1, char *s2, int status)
    00974 {
    00975   fprintf(stderr,s1,s2);
    00976   if(ah_errno > 0 && ah_errno < ah_nerr)
    00977     fprintf(stderr," (%s)",ah_errlist[ah_errno]);
    00978   fprintf(stderr,"\n");
    00979   exit(status);
    00980 }
    00981
    00982 #ifndef MAX
    00983 #define MAX(a,b)        (((a) > (b)) ? (a) : (b))
    00984 #endif
    00985 #ifndef MIN
    00986 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
    00987 #endif
    00988
    00989 /*
    00990  *      maxamp
    00991  *              determines the maximum absolute amplitude of the data array, and
    00992  *              places that number in head.record.maxamp.
    00993  *      returns:
    00994  *                      0       ->      ok
    00995  *                      -1      ->      error
    00996  */
    00997 static  int     maxamp (ahhed *head, char *data)
    00998 {
    00999   float *fpt;
    01000   double *dpt, dmin, dmax;
    01001   float max,min;
    01002   long  n_data_pts;
    01003
    01004   switch(head->record.type)
    01005   {
    01006   case FLOAT:
    01007     n_data_pts= head->record.ndata;
    01008     break;
    01009   case COMPLEX:
    01010   case VECTOR:
    01011     n_data_pts= 2 * head->record.ndata;
    01012     break;
    01013   case TENSOR:
    01014     n_data_pts= 3 * head->record.ndata;
    01015     break;
    01016   case 5:
    01017     n_data_pts= 4 * head->record.ndata;
    01018     break;
    01019   case DOUBLE:
    01020     n_data_pts= head->record.ndata;
    01021     break;
    01022   default:
    01023     ah_errno= AE_DTYPE;
    01024     return(-1);
    01025     break;
    01026   }
    01027
    01028   if (head->record.type == DOUBLE) {
    01029     dpt= (double *)data;
    01030     dmax= dmin= *dpt;
    01031     while(n_data_pts--)
    01032     {
    01033       dmax= MAX(dmax,*dpt);
    01034       dmin= MIN(dmin,*dpt);
    01035       ++dpt;
    01036     }
    01037     ((fabs(dmax) > fabs(dmin)) ? (head->record.maxamp= (float) dmax) : (head->record.maxamp= (float) -dmin));
    01038   }
    01039   else {
    01040     fpt= (float *)data;
    01041     max= min= *fpt;
    01042     while(n_data_pts--)
    01043     {
    01044       max= MAX(max,*fpt);
    01045       min= MIN(min,*fpt);
    01046       ++fpt;
    01047     }
    01048     ((fabs((double)max) > fabs((double)min)) ? (head->record.maxamp= max) : (head->record.maxamp= -min));
    01049   }
    01050
    01051   return(0);
    01052 }
    01053 /*      xdr_gethead
    01054  *              gets the next header from the xdr stream pointed to by
    01055  *              xdrs and returns this header in the structure head.
    01056  *              xdrs is assumed to be positioned at the next header,
    01057  *              and does not search.
    01058  *      returns:
    01059  *                      1               ->      no error
    01060  *                      -1              ->      not enough head to read
    01061  *                      -2              ->      bad data type
    01062  */
    01063 static  int     xdr_gethead (ahhed *head, XDR *xdrs)
    01064 {
    01065   int   ierr = 0;
    01066
    01067   if((ierr = xdr_ahhead(xdrs, head)) == 1)
    01068   {
    01069     if((head->record.type < TYPEMIN) || (head->record.type > TYPEMAX))
    01070     {
    01071       get_null_head(head);
    01072       ierr = -2;        /* bad data type */
    01073       ah_errno= AE_DTYPE;
    01074     }
    01075   }
    01076   else          /* not enough head */
    01077   {
    01078     get_null_head(head);
    01079     ierr = -1;
    01080     ah_errno= AE_RHED;
    01081   }
    01082   return(ierr);
    01083 }
    01084
    01085
    01086
    01087 /*      xdr_puthead
    01088  *              writes the header head onto the xdr stream pointed to by
    01089  *              xdrs.
    01090  *      returns:
    01091  *                      1               ->      no error
    01092  *                      -1              ->      error writing header
    01093  */
    01094 static  int     xdr_puthead (ahhed *head, XDR *xdrs)
    01095 {
    01096   int   ierr = 0;
    01097
    01098   if((ierr= xdr_ahhead(xdrs, head)) != 1)
    01099   {
    01100     ah_errno= AE_WHED;
    01101     ierr= -1;
    01102   }
    01103   return(ierr);
    01104 }
    01105
    01106
    01107
    01108 /*      xdr_tohead
    01109  *              positions the read/write head to the beginning of the
    01110  *              n-th header in the xdr stream pointed to by xdrs.
    01111  *      returns:
    01112  *                      n       ->      no error
    01113  *                      -1      ->      not enough heads
    01114  *                      -2      ->      bad seek
    01115  */
    01116 static  int     xdr_tohead (int n, XDR *xdrs)
    01117 {
    01118   ahhed head;
    01119   int   i,ierr,j;
    01120   float float_dum;
    01121   double        double_dum;
    01122   complex complex_dum;
    01123   tensor        tensor_dum;
    01124
    01125   /* be warned: the following xdr_setpos call may not work at all       */
    01126   /* depending on the stream.  The use of 0 to get to the beginning     */
    01127   /* works empirically, but is not documented  ... sigh - dws           */
    01128   xdr_setpos(xdrs, (u_int) 0);
    01129
    01130   for(i=1; i<n; ++i)
    01131   {
    01132     if(xdr_gethead(&head,xdrs) == 1)
    01133     {
    01134       switch (head.record.type) {
    01135       case FLOAT:
    01136         for (j = 0; j < head.record.ndata; j++) {
    01137           if (!xdr_float(xdrs, &float_dum)) {
    01138             ierr = -2;  /* bad seek */
    01139             ah_errno= AE_RHED;
    01140             return(ierr);
    01141           }
    01142         }
    01143
    01144         break;
    01145       case COMPLEX:
    01146       case VECTOR:
    01147         for (j = 0; j < head.record.ndata; j++) {
    01148           if (!xdr_float(xdrs, &complex_dum.i) ||
    01149               !xdr_float(xdrs, &complex_dum.r)) {
    01150             ierr = -2;  /* bad seek */
    01151             ah_errno= AE_RHED;
    01152             return(ierr);
    01153           }
    01154         }
    01155
    01156         break;
    01157       case TENSOR:
    01158         for (j = 0; j < head.record.ndata; j++) {
    01159           if (!xdr_float(xdrs, &tensor_dum.xx) ||
    01160               !xdr_float(xdrs, &tensor_dum.yy) ||
    01161               !xdr_float(xdrs, &tensor_dum.xy)) {
    01162             ierr = -2;  /* bad seek */
    01163             ah_errno= AE_RHED;
    01164             return(ierr);
    01165           }
    01166         }
    01167         break;
    01168       case 5:
    01169         for (j = 0; j < 4 * head.record.ndata; j++) {
    01170           if (!xdr_float(xdrs, &float_dum)) {
    01171             ierr = -2;  /* bad seek */
    01172             ah_errno= AE_RHED;
    01173             return(ierr);
    01174           }
    01175         }
    01176         break;
    01177       case DOUBLE:
    01178         for (j = 0; j < head.record.ndata; j++) {
    01179           if (!xdr_double(xdrs, &double_dum)) {
    01180             ierr = -2;  /* bad seek */
    01181             ah_errno= AE_RHED;
    01182             return(ierr);
    01183           }
    01184         }
    01185         break;
    01186       default:
    01187         ierr = -2;      /* bad seek */
    01188         ah_errno= AE_DTYPE;
    01189         return(ierr);
    01190       }
    01191     }
    01192     else
    01193     {
    01194       ierr = -1;        /* not enough head */
    01195       ah_errno= AE_RHED;
    01196       return(ierr);
    01197     }
    01198   }
    01199   return(i);    /* success */
    01200 }
    01201
    01202
    01203
    01204 /*      xdr_getdata
    01205  *              reads from the xdr stream pointed to by xdrs into
    01206  *              the array pointed to by array.  It assumes that
    01207  *              the read/write head is positioned correctly
    01208  *              (i.e., right after the header), and does not
    01209  *              search.  Works for any allowed data type.
    01210  *      returns:
    01211  *                      number of elements read ->      OK
    01212  *                      -1                      ->      error
    01213  */
    01214 static  int     xdr_getdata (ahhed *head, char *array, XDR *xdrs)
    01215 {
    01216   int ierr = 0;
    01217   float *pfloat;
    01218   double        *pdouble;
    01219   complex *pcomplex;
    01220   tensor        *ptensor;
    01221   int i;
    01222
    01223   switch(head->record.type) {
    01224   case FLOAT:
    01225     pfloat = (float *) array;
    01226     for (i = 0; i < head->record.ndata; i++) {
    01227       if (! xdr_float(xdrs, pfloat++) ) {
    01228         ah_errno= AE_RDATA;
    01229         ierr = -1;
    01230         return(ierr);
    01231       }
    01232       ++ierr;
    01233     }
    01234     break;
    01235   case COMPLEX:
    01236   case VECTOR:
    01237     pcomplex = (complex *) array;
    01238     for (i = 0; i < head->record.ndata; i++) {
    01239       if (!xdr_float(xdrs, &(pcomplex->r)) ||
    01240           !xdr_float(xdrs, &(pcomplex++->i))) {
    01241         ah_errno= AE_RDATA;
    01242         ierr = -1;
    01243         return(ierr);
    01244       }
    01245       ++ierr;
    01246     }
    01247     break;
    01248   case TENSOR:
    01249     ptensor = (tensor *) array;
    01250     for (i = 0; i < head->record.ndata; i++) {
    01251       if (!xdr_float(xdrs, &(ptensor->xx)) ||
    01252           !xdr_float(xdrs, &(ptensor->yy)) ||
    01253           !xdr_float(xdrs, &(ptensor++->xy))) {
    01254         ah_errno= AE_RDATA;
    01255         ierr = -1;
    01256         return(ierr);
    01257       }
    01258       ++ierr;
    01259     }
    01260     break;
    01261   case 5:
    01262     pfloat = (float *) array;
    01263     for (i = 0; i < 4 * head->record.ndata; i++) {
    01264       if (! xdr_float(xdrs, pfloat++) ) {
    01265         ah_errno= AE_RDATA;
    01266         ierr = -1;
    01267         return(ierr);
    01268       }
    01269       ++ierr;
    01270     }
    01271     break;
    01272   case DOUBLE:
    01273     pdouble = (double *) array;
    01274     for (i = 0; i < head->record.ndata; i++) {
    01275       if (! xdr_double(xdrs, pdouble++) ) {
    01276         ah_errno= AE_RDATA;
    01277         ierr = -1;
    01278         return(ierr);
    01279       }
    01280       ++ierr;
    01281     }
    01282     break;
    01283   default:
    01284     ierr = -1;
    01285     ah_errno= AE_DTYPE;
    01286     return(ierr);
    01287   }
    01288   return(ierr);
    01289 }
    01290
    01291
    01292 /*      xdr_putdata
    01293  *              writes array to the xdr stream pointed to by xdrs.
    01294  *              Works for any allowed data type.
    01295  *      returns:
    01296  *                      number of elements written      ->      OK
    01297  *                      -1                      ->      error
    01298  */
    01299 static  int     xdr_putdata (ahhed *head, char *array, XDR *xdrs)
    01300 {
    01301   int   ierr = 0;
    01302   float *pfloat;
    01303   double        *pdouble;
    01304   complex *pcomplex;
    01305   tensor        *ptensor;
    01306   int i;
    01307
    01308   switch(head->record.type) {
    01309   case FLOAT:
    01310     pfloat = (float *) array;
    01311     for (i = 0; i < head->record.ndata; i++) {
    01312       if (! xdr_float(xdrs, pfloat++) ) {
    01313         ah_errno= AE_RDATA;
    01314         ierr = -1;
    01315         return(ierr);
    01316       }
    01317       ++ierr;
    01318     }
    01319     break;
    01320   case COMPLEX:
    01321   case VECTOR:
    01322     pcomplex = (complex *) array;
    01323     for (i = 0; i < head->record.ndata; i++) {
    01324       if (!xdr_float(xdrs, &(pcomplex->r)) ||
    01325           !xdr_float(xdrs, &(pcomplex++->i))) {
    01326         ah_errno= AE_RDATA;
    01327         ierr = -1;
    01328         return(ierr);
    01329       }
    01330       ++ierr;
    01331     }
    01332     break;
    01333   case TENSOR:
    01334     ptensor = (tensor *) array;
    01335     for (i = 0; i < head->record.ndata; i++) {
    01336       if (!xdr_float(xdrs, &(ptensor->xx)) ||
    01337           !xdr_float(xdrs, &(ptensor->yy)) ||
    01338           !xdr_float(xdrs, &(ptensor++->xy))) {
    01339         ah_errno= AE_RDATA;
    01340         ierr = -1;
    01341         return(ierr);
    01342       }
    01343       ++ierr;
    01344     }
    01345     break;
    01346   case 5:
    01347     pfloat = (float *) array;
    01348     for (i = 0; i < 4 * head->record.ndata; i++) {
    01349       if (! xdr_float(xdrs, pfloat++) ) {
    01350         ah_errno= AE_RDATA;
    01351         ierr = -1;
    01352         return(ierr);
    01353       }
    01354       ++ierr;
    01355     }
    01356     break;
    01357   case DOUBLE:
    01358     pdouble = (double *) array;
    01359     for (i = 0; i < head->record.ndata; i++) {
    01360       if (! xdr_double(xdrs, pdouble++) ) {
    01361         ah_errno= AE_RDATA;
    01362         ierr = -1;
    01363         return(ierr);
    01364       }
    01365       ++ierr;
    01366     }
    01367     break;
    01368
    01369   default:
    01370     ierr = -1;
    01371     ah_errno= AE_DTYPE;
    01372     return(ierr);
    01373   }
    01374   return(ierr);
    01375 }
    01376
    01377
    01378 /*      xdr_putrecord
    01379  *              writes head and array to the xdr stream pointed to by xdrs.
    01380  *              Works for any allowed data type.
    01381  *      returns:
    01382  *                      0       ->      OK
    01383  *                      -1      ->      error writing header
    01384  *                      -2      ->      error writing data
    01385  */
    01386 static  int     xdr_putrecord (ahhed *head, char *array, XDR *xdrs)
    01387 {
    01388   int   ierr = 0;
    01389
    01390   (xdr_puthead(head,xdrs) == 1) ? ((xdr_putdata(head,array,xdrs) < 0) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    01391   if(ierr)
    01392     ah_errno= AE_WRECORD;
    01393
    01394   return(ierr);
    01395 }
    01396
    01397
    01398 /*      xdr_getrecord
    01399  *              gets header and data from the xdr stream pointed to by
    01400  *              xdrs and puts them in head and array.  It assumes
    01401  *              that the read/write head is positioned at the beginning
    01402  *              of the header, and does not search.  Obviously, calling
    01403  *              routine must have allocated enough space.
    01404  *      returns:
    01405  *                      0       ->      OK
    01406  *                      -1      ->      error reading header
    01407  *                      -2      ->      error reading data
    01408  */
    01409 static  int     xdr_getrecord (ahhed *head, char *array, XDR *xdrs)
    01410 {
    01411   int   ierr = 0;
    01412
    01413   (xdr_gethead(head,xdrs) == 1) ? ((xdr_getdata(head,array,xdrs) < 0) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    01414   if(ierr)
    01415     ah_errno= AE_RRECORD;
    01416   return(ierr);
    01417 }
    01418
    01419 /*
    01420  *      xdr_getrecord2
    01421  *              gets header and data from the xdr stream pointed to by
    01422  *              xdrs and puts them in head and array.  It assumes
    01423  *              that the read/write head is positioned at the beginning
    01424  *              of the header, and does not search (although it does
    01425  *              some error checking).  Space for array is allocated, so
    01426  *              be sure to pass a pointer to the data pointer. Got it?
    01427  *      returns:
    01428  *                      0       ->      ok
    01429  *                      -1      ->      error reading record
    01430  *                      -2      ->      error allocating space for data
    01431  */
    01432 static  int     xdr_getrecord2 (ahhed *head, char **array, XDR *xdrs)
    01433 {
    01434   int   ierr = 0;
    01435   int   xdr_gethead();
    01436   char  *mkdatspace();
    01437
    01438   if(xdr_gethead(head, xdrs) != 1) {
    01439     ierr = -1;
    01440     return(ierr);
    01441   }
    01442
    01443   *array= mkdatspace(head);
    01444   if(*array == NULL)
    01445   {
    01446     ierr= -2;
    01447     return(ierr);
    01448   }
    01449
    01450   if(xdr_getdata(head,*array,xdrs) < 0)
    01451     ierr= -1;
    01452
    01453   return(ierr);
    01454 }
    01455
    01456
    01457 /*      xdr_gogethead
    01458  *              gets n-th header from the xdr stream pointed to by
    01459  *              xdrs and returns this header in the structure
    01460  *              head.
    01461  *      returns:
    01462  *                      0       ->      OK
    01463  *                      -1      ->      stream not long enough
    01464  *                      -2      ->      error reading header
    01465  */
    01466 static  int     xdr_gogethead (int n, ahhed *head, XDR *xdrs)
    01467 {
    01468   int   ierr = 0;
    01469
    01470   (xdr_tohead(n,xdrs) == n) ? ((xdr_gethead(head,xdrs) < 1) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    01471   return(ierr);
    01472 }
    01473
    01474
    01475 /*      xdr_gogetrecord
    01476  *              gets n-th record (header and data) from the xdr stream
    01477  *              pointed to by xdrs and places it in head and array.
    01478  *              Calling routine must allocate enough space.
    01479  *      returns:
    01480  *                      0       ->      OK
    01481  *                      -1      ->      stream not long enough
    01482  *                      -2      ->      error reading record
    01483  */
    01484 static  int     xdr_gogetrecord (int n, ahhed *head, char *array, XDR *xdrs)
    01485 {
    01486   int   ierr = 0;
    01487
    01488   (xdr_tohead(n,xdrs) == n) ? ((xdr_getrecord(head,array,xdrs) < 0) ? (ierr = -2) : (ierr = 0)) : (ierr = -1);
    01489   return(ierr);
    01490 }
    01491
    01492
    01493
    01494
    01495
    01496
    01497 static int xdr_ahhead (XDR *xdrsp, ahhed *ahheadp)
    01498 {
    01499   u_int l;
    01500   char **pp, *p;
    01501   float **ppf, *pf;
    01502
    01503   l = CODESIZE;
    01504   p = ahheadp->station.code;
    01505   pp = &p;
    01506   if (!xdr_bytes(xdrsp, pp, &l, (u_int) CODESIZE))
    01507     return(0);
    01508   l = CHANSIZE;
    01509   p = ahheadp->station.chan;
    01510   pp = &p;
    01511   if (!xdr_bytes(xdrsp, pp, &l, CHANSIZE))
    01512     return(0);
    01513   l = STYPESIZE;
    01514   p = ahheadp->station.stype;
    01515   pp = &p;
    01516   if (!xdr_bytes(xdrsp, pp, &l, STYPESIZE))
    01517     return(0);
    01518   if (!xdr_float(xdrsp, &ahheadp->station.slat))
    01519     return(0);
    01520   if (!xdr_float(xdrsp, &ahheadp->station.slon))
    01521     return(0);
    01522   if (!xdr_float(xdrsp, &ahheadp->station.elev))
    01523     return(0);
    01524   if (!xdr_float(xdrsp, &ahheadp->station.DS))
    01525     return(0);
    01526   if (!xdr_float(xdrsp, &ahheadp->station.A0))
    01527     return(0);
    01528   for (l = 0; l < NOCALPTS; l++) {
    01529     if (!xdr_float(xdrsp, &ahheadp->station.cal[l].pole.r))
    01530       return(0);
    01531     if (!xdr_float(xdrsp, &ahheadp->station.cal[l].pole.i))
    01532       return(0);
    01533     if (!xdr_float(xdrsp, &ahheadp->station.cal[l].zero.r))
    01534       return(0);
    01535     if (!xdr_float(xdrsp, &ahheadp->station.cal[l].zero.i))
    01536       return(0);
    01537   }
    01538   if (!xdr_float(xdrsp, &ahheadp->event.lat))
    01539     return(0);
    01540   if (!xdr_float(xdrsp, &ahheadp->event.lon))
    01541     return(0);
    01542   if (!xdr_float(xdrsp, &ahheadp->event.dep))
    01543     return(0);
    01544   if (!xdr_short(xdrsp, &ahheadp->event.ot.yr))
    01545     return(0);
    01546   if (!xdr_short(xdrsp, &ahheadp->event.ot.mo))
    01547     return(0);
    01548   if (!xdr_short(xdrsp, &ahheadp->event.ot.day))
    01549     return(0);
    01550   if (!xdr_short(xdrsp, &ahheadp->event.ot.hr))
    01551     return(0);
    01552   if (!xdr_short(xdrsp, &ahheadp->event.ot.mn))
    01553     return(0);
    01554   if (!xdr_float(xdrsp, &ahheadp->event.ot.sec))
    01555     return(0);
    01556   l = COMSIZE;
    01557   p = ahheadp->event.ecomment;
    01558   pp = &p;
    01559   if (!xdr_bytes(xdrsp, pp, &l, COMSIZE))
    01560     return(0);
    01561   if (!xdr_short(xdrsp, &ahheadp->record.type))
    01562     return(0);
    01563   if (!xdr_long(xdrsp, &ahheadp->record.ndata))
    01564     return(0);
    01565   if (!xdr_float(xdrsp, &ahheadp->record.delta))
    01566     return(0);
    01567   if (!xdr_float(xdrsp, &ahheadp->record.maxamp))
    01568     return(0);
    01569   if (!xdr_short(xdrsp, &ahheadp->record.abstime.yr))
    01570     return(0);
    01571   if (!xdr_short(xdrsp, &ahheadp->record.abstime.mo))
    01572     return(0);
    01573   if (!xdr_short(xdrsp, &ahheadp->record.abstime.day))
    01574     return(0);
    01575   if (!xdr_short(xdrsp, &ahheadp->record.abstime.hr))
    01576     return(0);
    01577   if (!xdr_short(xdrsp, &ahheadp->record.abstime.mn))
    01578     return(0);
    01579   if (!xdr_float(xdrsp, &ahheadp->record.abstime.sec))
    01580     return(0);
    01581   if (!xdr_float(xdrsp, &ahheadp->record.rmin))
    01582     return(0);
    01583   l = COMSIZE;
    01584   p = ahheadp->record.rcomment;
    01585   pp = &p;
    01586   if (!xdr_bytes(xdrsp, pp, &l, COMSIZE))
    01587     return(0);
    01588   l = LOGSIZE;
    01589   p = ahheadp->record.log;
    01590   pp = &p;
    01591   if (!xdr_bytes(xdrsp, pp, &l, LOGSIZE))
    01592     return(0);
    01593   l = NEXTRAS;
    01594   pf = ahheadp->extra;
    01595   ppf = &pf;
    01596   if (!xdr_array(xdrsp, (char **)ppf, &l, NEXTRAS, sizeof(float),
    01597                  (xdrproc_t)xdr_float))
    01598     return(0);
    01599
    01600
    01601   return(1);
    01602 }