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( <ime ); 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 }