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 }

Generated on Tue May 6 09:15:59 2003 for Earthworm Libs by doxygen1.3-rc3