source: SH_SHM/trunk/source/seed_io/seed_lib.c @ 34

Revision 34, 128.8 KB checked in by marcus, 14 years ago (diff)

r19 | svn | 2008-02-01 17:53:55 +0100 (Fr, 01 Feb 2008) | 1 line

seed512to4096 for PC Linux

Line 
1
2/* file seed_lib.c
3 *      ==========
4 *
5 * $Revision: 19 $, $Date: 2008-02-01 17:53:55 +0100 (Fr, 01 Feb 2008) $
6 *
7 * SEED library
8 * K. Stammler, 29-Dec-93
9 * v 16, 22-Nov-94, K. Stammler, added headers for VAX-GCC
10 * v 18, 23-Nov-94, K. Stammler, automatic detection of necessary byte swaps
11 * v 43,  7-Dec-97, K. Stammler, fixed calib-bug when reading starts in a gap
12 * v 44,  9-Dec-97, K. Stammler, fixed bug in ReadNextRecord (appeared in Linux)
13 * v 46,  2-Mar-98, K. Stammler, fixed bug on records with too many samples
14 * v 47, 24-Mar-98, K. Stammler, was still a bug in records with too many smples
15 * v 48, 24-Apr-98, K. Stammler, replaced some printf's by fprintf's
16 * v 49,  1-Jun-98, K. Stammler, still another bug at records with bad samples
17 * v 50, 11-Aug-98, K. Stammler, implemented offset positions in SEED files
18 * v 51, 16-Mar-99, K. Stammler, use time correction field in SEED records
19 * v 52, 11-Jan-00, K. Stammler, variable SEED record length
20 * v 53, 14-Jun-00, K. Stammler, SeedSwapNecessary until 2030
21 * v 54, 11-Jul-00, K. Stammler, handle seed->databegin other than 64er numbers
22 * v 56,  6-Dec-01, K. Stammler, implementation of Steim2 input
23 * v 57, 11-Jan-02, K. Stammler, increased max samples/rec to 14000
24 * v 58,  8-Jul-02, K. Stammler, implement VAX word order
25 * v 59, 26-Aug-02, K. Stammler, only output printable chars on SeedLibWarning
26 * v 60,  9-Sep-02, K. Stammler, check for illegal 'first' entry (bus error)
27 * v 61, 17-Oct-02, K. Stammler, in SeedReadStreamReal, set fdat=NULL, first
28 * v 62, 17-Nov-02, K. Stammler, SeedStoreRec: swap 'first' entry on swapped rec
29 * v 63, 14-Apr-05, K. Stammler, insert blockette 1000 when writing miniSeed
30 * v 64, 18-Nov-05, K. Stammler, compiler error on Suse10, empty default switch
31 * v 65, 21-Nov-05, K. Stammler, change long to int32
32 * v 66, 25-Nov-05, K. Stammler, possibility to insert time quality in data recs
33 * v 67,  7-Mar-06, K. Stammler, netcode+locid used for reading
34 * v 68, 28-Apr-06, K. Stammler, fixed bug in SeedGetReclth (was no test for swap)
35 * v 70, 20-May-06, K. Stammler, new file format for calibration info
36 * v 71, 22-May-06, K. Stammler, new flag-parameter in SeedReadStream for qc
37 * v 72, 14-Jun-06, K. Stammler, missing fclose fixed on new sensitivities file
38 * v 73, 22-Oct-06, K. Stammler, string lists on sensitivity file
39 * v 74,  4-Nov-06, K. Stammler, add sfdb interface
40 * v 75, 12-Nov-06, K. Stammler, add routine to remove temp file of sfdb request
41 * v 76, 15-Dec-06, K. Stammler, date and time in INT and DOUBLE format
42 * v 77, 18-Dec-06, K. Stammler, added some debug printout
43 * v 78, 21-Dec-06, K. Stammler, restructered sfdb interface (sqliface.c)
44 * v 79, 28-Dec-06, K. Stammler, 'default' sensitivity replaced by $SH_INPUTS/sensitivities.txt
45 * v 80, 29-Dec-06, K. Stammler, implementation of data lock flag
46 * v 81,  3-Jan-07, K. Stammler, set default of seedv_use_timecorr to TRUE, TIMECORRUNIT to 10000
47 * v 82, 13-Feb-07, K. Stammler, swap blockette 1000 in SwapHeader
48 * v 83, 28-Nov-07, K. Stammler, accept also Q and R as data record identifier
49 */
50
51
52#include <stdio.h>
53#include <string.h>
54#include <math.h>
55#include BASECNST
56#ifdef BC_INC_UNISTD
57#include BC_INC_UNISTD
58#endif
59#ifdef BC_INC_STDLIB
60#include BC_INC_STDLIB
61#endif
62#ifdef BC_SUN
63#include <fcntl.h>
64#include <sys/types.h>
65/* #include <sys/uio.h> */
66#endif
67#ifdef BC_VAX
68#include <file.h>
69#endif
70#include BC_SYSBASE
71#include BC_TCUSRDEF
72#include BC_ERUSRDEF
73#include BC_UTUSRDEF
74#include "globalparams.h"
75#include "seedcfg.h"
76#include "seed_lib.h"
77
78#define ANSI_EXTENSIONS
79#include "steim1.h"
80#undef ANSI_EXTENSIONS
81
82#ifdef BC_VAX
83#define SEEK_SET 0
84#endif
85
86
87
88/*
89 * constants
90 * ---------
91 */
92
93#define PREV_XN_INVALID 0x7fffffffL
94#define ROOTDIR "$ROOT"
95#define ROOTDIRLTH 5
96#define MAX_SMP_PER_REC 14000
97#define TIMECORRUNIT 10000.0
98#define DEFAULT_RECLTH 4096
99
100
101
102
103/*
104 * global variables
105 * ----------------
106 */
107
108static SeedSetupParT   seedv_setup;                 /* setup parameters */
109static SeedFileDescrT  seedv_fd[Seed_C_MAXCHAN];    /* file descriptors */
110static SeedDataHeaderT seedv_rec[Seed_C_MAX_RECLTH/sizeof(SeedDataHeaderT)];
111                                                    /* SEED record */
112static int             seedv_out_reclth=DEFAULT_RECLTH;
113                                            /* record length of output files */
114static BOOLEAN         seedv_logrec;                /* log records */
115static BOOLEAN         seedv_warnings=TRUE;         /* print warnings */
116static BOOLEAN         seedv_invert_swap_hdr=FALSE; /* invert swap hdr flag */
117static BOOLEAN         seedv_capfiles=FALSE;        /* capitalized filenames */
118static BOOLEAN         seedv_decerr_abort=TRUE;     /* abort on decode errors */
119static BOOLEAN         seedv_use_timecorr=TRUE;     /* use time corrections */
120static char            seedv_last_fname[cBcFileLth+1]; /* last file read */
121static int             seedv_timequal= -1;          /* time quality */
122
123static SeedDataHeaderT seedv_hdr_proto = {        /* SEED header prototype */
124        "",                     /* seqno, sequence number string */
125        'D',                    /* indicator */
126        '\0',                   /* Reserved_bytes_A */
127        {'X','X','X',' ',' '},  /* statcode, station name */
128        {' ',' '},              /* locid, location identifier */
129        {'X','X','X'},          /* channel */
130        {'\0','\0'},            /* Reserved_bytes_B */
131        {0,0,0,0,0,0,0},        /* starttime */
132        0,                      /* no_of_samples */
133        1,                      /* smprate_fact */
134        1,                      /* smprate_mult */
135        0,                      /* activity */
136        0,                      /* ioflags */
137        0,                      /* quality */
138        0,                      /* no_of_blockettes */
139        0,                      /* timecorr */
140        0,                      /* databegin */
141        0                       /* first */
142}; /* end of SEED header prototype */
143
144/*
145 * prototypes of local routines
146 * ----------------------------
147 */
148
149static void SeedDecodeSteim1Frame( SeedSbyteT frame[], BOOLEAN swap,
150        BOOLEAN wo, INT32 diff[], int *lth );
151static void SeedDecodeSteim2Frame( SeedSbyteT frame[], BOOLEAN swap,
152        BOOLEAN wo, INT32 diff[], int *lth );
153static void SeedAdjustFilename( SeedFileDescrT *dsc, STATUS *status );
154static void SeedLibWarning( char text[] );
155static void SeedSwapLinuxRecord( SeedSbyteT *rec, int reclth );
156static void SeedSplitStreamName( char inpname[], char outname[],
157        char station[], char addinf[] );
158static void SeedFindFileInDatabase( char stream_str[], char start[],
159        char dbfile[], SeedFileDescrT *fdescr, STATUS *status );
160
161/* #define SeedLibWarning(t) fprintf( stderr, "%s", t ); */
162
163
164
165/*---------------------------------------------------------------------*/
166
167
168
169void SeedLibInitialize( STATUS *status )
170
171/* Initializes SEED library routines
172 *
173 * parameters of routine
174 * STATUS     *status;      output; return status
175 */
176{
177        /* local variables */
178        int      i;            /* counter */
179
180        /* executable code */
181
182        SeedGetSetup( &seedv_setup );
183        for  (i=0; i<Seed_C_MAXCHAN; seedv_fd[i++].ufd = Seed_C_ILLEGAL ) {}
184
185} /* end of SeedLibInitialize */
186
187
188
189/*---------------------------------------------------------------------*/
190
191
192
193void SeedDecodeSteim1( SeedSbyteT rec[], BOOLEAN swap, INT32 maxsmplth,
194        INT32 smp[], INT32 *smplth )
195
196/* Decodes Steim1-compressed data record of length specified within record.
197 * Data are returned in array 'smp', its length in 'smplth'.  No more than
198 * maxsmplth samples are copied to the output array.  If more samples would
199 * be available an error message is printed.
200 * A NULL pointer for 'rec' resets internal variables to initial state.
201 *
202 * Can now also read Steim2 compression, 10-Dec-2001, K. Stammler
203 *
204 * parameters of routine
205 * SeedSbyteT rec[];          input; SEED record
206 * BOOLEAN    swap;           input; swap bytes
207 * INT32      maxsmplth;      input; maximum length of output array
208 * INT32      smp[];          output; decoded samples
209 * INT32      *smplth;        output; number of output samples
210 */
211{
212        /* local variables */
213        static INT32 prev_xn=PREV_XN_INVALID;      /* previous xn */
214        static int err_cnt=0;          /* error count for diff[0]==x0 */
215        SeedSbyteT *frame;             /* byte pointer */
216        int        frames_per_rec;     /* number of frames/record (incl. header) */
217        int        framecnt;           /* frame counter */
218        int        framecnt_start;     /* frame count start value */
219        INT32      x0, xn;             /* integration constants */
220        INT32      diffs[Seed_C_MAXFRAMESMP];  /* differences of one frame */
221        int        declth;             /* number of differences in a frame */
222        char       str[BC_LINELTH+1];  /* scratch string */
223        INT32      cursmp;             /* current sample */
224        INT32      fsampleno;          /* number of samples in frame */
225        SeedDataHeaderT *rec_h;        /* data header structure */
226        INT32      rsampleno;          /* number of samples in record */
227        int        reclth;             /* record length */
228        int        comprs;             /* compression ID */
229        int        worder;             /* word order 0=VAX,8086 1=Sparc,68000 */
230
231        /* executable code */
232
233        if  (rec == NULL)  {
234                prev_xn = PREV_XN_INVALID;
235                return;
236        } /*endif*/
237
238        rec_h = (SeedDataHeaderT *)rec;
239        rsampleno = (INT32)(rec_h->no_of_samples);
240        if  (maxsmplth < rsampleno)  {
241                sprintf( str,
242                        "SeedDecodeSteim1: passed array is too short by %ld samples\n",
243                        rsampleno-maxsmplth );
244                SeedLibWarning( str );
245                rsampleno = maxsmplth;
246        } /*endif*/
247        /* printf( "--> databegin: %d\n", (int)rec_h->databegin ); */
248
249        reclth = SeedGetReclth( rec_h, FALSE );
250        frames_per_rec = reclth / Seed_C_FRAMELTH;
251        *smplth = 0;
252        frame = rec;
253        if  (rsampleno <= 0)  return;
254
255        comprs = SeedGetCompression( rec_h );
256        /* assume Steim1 compression if no blockette 1000 */
257        if  (comprs == 0)  {
258                comprs = Seed_C_DcmpSteim1;
259                /*
260                SeedLibWarning( "no blockette 1000 found, assume Steim1 compression\n" );
261                */
262        } /*endif*/
263        if  (comprs != Seed_C_DcmpSteim1 && comprs != Seed_C_DcmpSteim2)  {
264                sprintf( str, "unimplemented Compression %d\n", comprs );
265                SeedLibWarning( str );
266                return;
267        } /*endif*/
268        worder = SeedGetWordOrder( rec_h );
269
270        /* skip all frames wich are not data frames (minus one which is */
271        /* incremented inside the following loop)                       */
272        if  ((int)(rec_h->databegin) % Seed_C_FRAMELTH != 0)  {
273                /* illegal value of databegin, print warning and assume it as 64 */
274                sprintf( str, "SeedDecodeSteim1: illegal databegin %d\n",
275                        (int)(rec_h->databegin) );
276                SeedLibWarning( str );
277                /* increase databegin over the next 64er border, will be rounded off */
278                rec_h->databegin += Seed_C_FRAMELTH;
279        } /*endif*/
280        framecnt_start = 1;
281        /* a value of 0 is corrected to 64 */
282        /* values of 128 and more cause a increment of data start frame */
283        if  (rec_h->databegin > Seed_C_FRAMELTH)  {
284                /*printf( "--> found databegin of %d\n", (int)(rec_h->databegin) );*/
285                framecnt_start = (int)(rec_h->databegin) / Seed_C_FRAMELTH;
286                frame += (framecnt_start-1)*Seed_C_FRAMELTH;
287        } /*endif*/
288
289        /* loop over all frames in record (first frame is header) */
290        for  (framecnt=framecnt_start; framecnt<frames_per_rec; framecnt++)  {
291
292                frame += Seed_C_FRAMELTH;
293
294                /* get integration constants */
295                if  (framecnt == framecnt_start)  {
296                        x0 = SeedGet4Bytes( frame+4, swap );
297                        xn = SeedGet4Bytes( frame+8, swap );
298                } /*endif*/
299
300                /* get all differences of this frame */
301                if  (comprs == Seed_C_DcmpSteim1)  {
302                        SeedDecodeSteim1Frame( frame, swap, worder, diffs, &declth );
303                } else {
304                        /* printf( "--> decompressing Steim2\n" ); */
305                        SeedDecodeSteim2Frame( frame, swap, worder, diffs, &declth );
306                } /*endif*/
307                if  (declth > Seed_C_MAXFRAMESMP)  {printf("*****1*****\n"); exit(111);}
308
309                /* check difference to last record */
310                if  (framecnt == framecnt_start)  {
311                        if  (prev_xn+diffs[0] != x0 && prev_xn != PREV_XN_INVALID)  {
312                                if  (diffs[0] == x0)  {
313                                        /* this is probably a common error in compression */
314                                        if  (err_cnt++ % 100 == 0)  {
315                                                sprintf( str,
316                                                        "\n--- Steim1: diff[0] is always equal to x0\n" );
317                                                SeedLibWarning( str );
318                                        } /*endif*/
319                                } else {
320                                        sprintf( str, "\n--- first sample in record: wrong diff\n" );
321                                        SeedLibWarning( str );
322                                        sprintf( str,
323                                        "    should be (x[-1]+diff[0]) %d, x[0] is %d, diff[0] is %ld\n",
324                                                prev_xn+diffs[0], x0, diffs[0] );
325                                        SeedLibWarning( str );
326                                        /* grn_printhdr( &hdr ); */
327                                } /*endif*/
328                        } /*endif*/
329                        cursmp = x0 - diffs[0];  /* is undone in following loop */
330                } /*endif*/
331
332                /* integrate samples and copy to output array */
333                for  (fsampleno=0; fsampleno<declth; fsampleno++)  {
334                        cursmp += diffs[fsampleno];
335                        *smp++ = cursmp;
336                        if  (++(*smplth) == rsampleno)  break;
337                } /*endfor*/
338
339                if  (*smplth == rsampleno)  break;
340
341        } /*endfor*/
342
343        if  (cursmp != xn)  {
344                sprintf( str, "*** checksum not ok in record\n" );
345                SeedLibWarning( str );
346        } /*endif*/
347
348        prev_xn = xn;
349
350} /* end of SeedDecodeSteim1 */
351
352
353
354/*----------------------------------------------------------------------------*/
355
356
357
358static void SeedDecodeSteim1Frame( SeedSbyteT frame[], BOOLEAN swap,
359        BOOLEAN wo, INT32 diff[], int *lth )
360
361/* Decodes differences of a single frame.
362 *
363 * parameters of routine
364 * SeedSbyteT *frame;     input; byte stream
365 * BOOLEAN    swap;       input; swap bytes
366 * BOOLEAN    wo;         input; word order
367 * INT32      diff[];     output; decoded differences
368 * int        *lth;       output; number of differences
369 */
370{
371        /* local variables */
372        unsigned INT32  nibbles;    /* 2-bit nibbles */
373        int             diffcnt;    /* difference counter */
374        int             shift;      /* bit shift length */
375        int             diff_id;    /* difference 2-bit ID (0,1,2,3) */
376        short int       si;         /* scratch */
377        unsigned INT32  ultmp;      /* scratch */
378        SeedSbyteT      sbyte;      /* scratch */
379
380        /* executable code */
381
382        nibbles = SeedGet4Bytes( frame, swap );
383        *lth = 0;
384        for  (diffcnt=0; diffcnt<Seed_C_FRAMEDIFFS; diffcnt++)  {
385                shift = 30 - diffcnt*2;
386                diff_id = (int)((nibbles >> shift) & 3);
387                switch  (diff_id)  {
388                case 1:
389                        ultmp = SeedGet4Bytes( frame, swap );
390                        frame += 4;
391                        if  (wo == 0)  {
392                                sbyte = (SeedSbyteT)(ultmp & 0x000000ffL);
393                                diff[(*lth)++] = sbyte;
394                                sbyte = (SeedSbyteT)((ultmp & 0x0000ff00L) >>  8);
395                                diff[(*lth)++] = sbyte;
396                                sbyte = (SeedSbyteT)((ultmp & 0x00ff0000L) >> 16);
397                                diff[(*lth)++] = sbyte;
398                                sbyte = (SeedSbyteT)((ultmp & 0xff000000L) >> 24);
399                                diff[(*lth)++] = sbyte;
400                        } else {
401                                sbyte = (SeedSbyteT)((ultmp & 0xff000000L) >> 24);
402                                diff[(*lth)++] = sbyte;
403                                sbyte = (SeedSbyteT)((ultmp & 0x00ff0000L) >> 16);
404                                diff[(*lth)++] = sbyte;
405                                sbyte = (SeedSbyteT)((ultmp & 0x0000ff00L) >>  8);
406                                diff[(*lth)++] = sbyte;
407                                sbyte = (SeedSbyteT)(ultmp & 0x000000ffL);
408                                diff[(*lth)++] = sbyte;
409                        } /*endif*/
410                        break;
411                case 2:
412                        ultmp = SeedGet4Bytes( frame, swap );
413                        frame += 4;
414                        if  (wo == 0)  {
415                                si = (short int)(ultmp & 0x0000ffffL);
416                                diff[(*lth)++] = si;
417                                si = (short int)((ultmp & 0xffff0000L) >> 16);
418                                diff[(*lth)++] = si;
419                        } else {
420                                si = (short int)((ultmp & 0xffff0000L) >> 16);
421                                diff[(*lth)++] = si;
422                                si = (short int)(ultmp & 0x0000ffffL);
423                                diff[(*lth)++] = si;
424                        } /*endif*/
425                        break;
426                case 3:
427                        diff[(*lth)++] = (INT32)SeedGet4Bytes( frame, swap );
428                        frame += 4;
429                        break;
430                default:
431                        frame += 4;  /* no data */
432                } /*endswitch*/
433        } /*endfor*/
434
435} /* end of SeedDecodeSteim1Frame */
436
437
438
439/*----------------------------------------------------------------------------*/
440
441
442
443static void SeedDecodeSteim2Frame( SeedSbyteT frame[], BOOLEAN swap,
444        int wo, INT32 diff[], int *lth )
445
446/* Decodes differences of a single frame, Steim2.
447 *
448 * parameters of routine
449 * SeedSbyteT *frame;     input; byte stream
450 * BOOLEAN    swap;       input; swap bytes
451 * int        wo;         input; word order
452 * INT32      diff[];     output; decoded differences
453 * int        *lth;       output; number of differences
454 */
455{
456        /* local variables */
457        unsigned INT32  nibbles;    /* 2-bit nibbles */
458        int             diffcnt;    /* difference counter */
459        int             shift;      /* bit shift length */
460        int             diff_id;    /* difference 2-bit ID (0,1,2,3) */
461        unsigned int    dnib;       /* decode nibble in decoded longword */
462        unsigned int    udiff[8];   /* difference decoded */
463        short int       si;         /* scratch */
464        unsigned INT32  ultmp;      /* scratch */
465        SeedSbyteT      sbyte;      /* scratch */
466        int             i;          /* counter */
467
468        /* executable code */
469
470        if  (wo == 0)  {
471                fprintf( stderr,
472                        "  Steim2: word order 0 (80x86) not implemented, check data\n" );
473        } /*endif*/
474
475        nibbles = SeedGet4Bytes( frame, swap );
476        *lth = 0;
477        for  (diffcnt=0; diffcnt<Seed_C_FRAMEDIFFS; diffcnt++)  {
478                shift = 30 - diffcnt*2;
479                diff_id = (int)((nibbles >> shift) & 3);
480                switch  (diff_id)  {
481                case 1:  /* 01 */
482                        /* this is four 8-bit differences */
483                        ultmp = SeedGet4Bytes( frame, swap );
484                        frame += 4;
485                        sbyte = (SeedSbyteT)((ultmp & 0xff000000L) >> 24);
486                        diff[(*lth)++] = sbyte;
487                        sbyte = (SeedSbyteT)((ultmp & 0x00ff0000L) >> 16);
488                        diff[(*lth)++] = sbyte;
489                        sbyte = (SeedSbyteT)((ultmp & 0x0000ff00L) >>  8);
490                        diff[(*lth)++] = sbyte;
491                        sbyte = (SeedSbyteT)(ultmp & 0x000000ffL);
492                        diff[(*lth)++] = sbyte;
493                        break;
494                case 2:  /* 10 */
495                        /* ask high order two bits of decoded longword */
496                        ultmp = SeedGet4Bytes( frame, swap );
497                        frame += 4;
498                        dnib = (ultmp >> 30) & 3;
499                        switch  (dnib)  {
500                        case 1:  /* 01 */
501                                /* one 30-bit difference, set high oder bits acc. bit number 30 */
502                                if  (ultmp & 0x20000000L)
503                                        diff[(*lth)++] = (int)(ultmp | 0xc0000000L);
504                                else
505                                        diff[(*lth)++] = (int)(ultmp & 0x3fffffffL);
506                                break;
507                        case 2:  /* 10 */
508                                /* two 15 bit differences */
509                                udiff[0] = (ultmp >> 15) & 0x00007fffL;
510                                udiff[1] =  ultmp        & 0x00007fffL;
511                                for  (i=0; i<2; i++)
512                                        if  (udiff[i] & 0x00004000L)
513                                                diff[(*lth)++] = (int)(udiff[i] | 0xffff8000L);
514                                        else
515                                                diff[(*lth)++] = udiff[i];
516                                break;
517                        case 3:  /* 11 */
518                                udiff[0] = (ultmp >> 20) & 0x000003ffL;
519                                udiff[1] = (ultmp >> 10) & 0x000003ffL;
520                                udiff[2] =  ultmp        & 0x000003ffL;
521                                for  (i=0; i<3; i++)
522                                        if  (udiff[i] & 0x00000200L)
523                                                diff[(*lth)++] = (int)(udiff[i] | 0xfffffc00L);
524                                        else
525                                                diff[(*lth)++] = udiff[i];
526                                break;
527                        default:
528                                /* no data, ignore */;
529                        } /*endswitch*/
530                        break;
531                case 3:  /* 11 */
532                        /* ask high order two bits of decoded longword */
533                        ultmp = SeedGet4Bytes( frame, swap );
534                        frame += 4;
535                        dnib = (ultmp >> 30) & 3;
536                        switch  (dnib)  {
537                        case 0:  /* 00 */
538                                udiff[0] = (ultmp >> 24) & 0x0000003fL;
539                                udiff[1] = (ultmp >> 18) & 0x0000003fL;
540                                udiff[2] = (ultmp >> 12) & 0x0000003fL;
541                                udiff[3] = (ultmp >>  6) & 0x0000003fL;
542                                udiff[4] =  ultmp        & 0x0000003fL;
543                                for  (i=0; i<5; i++)
544                                        if  (udiff[i] & 0x00000020L)
545                                                diff[(*lth)++] = (int)(udiff[i] | 0xffffffc0L);
546                                        else
547                                                diff[(*lth)++] = udiff[i];
548                                break;
549                        case 1:  /* 01 */
550                                udiff[0] = (ultmp >> 25) & 0x0000001fL;
551                                udiff[1] = (ultmp >> 20) & 0x0000001fL;
552                                udiff[2] = (ultmp >> 15) & 0x0000001fL;
553                                udiff[3] = (ultmp >> 10) & 0x0000001fL;
554                                udiff[4] = (ultmp >>  5) & 0x0000001fL;
555                                udiff[5] =  ultmp        & 0x0000001fL;
556                                for  (i=0; i<6; i++)
557                                        if  (udiff[i] & 0x00000010L)
558                                                diff[(*lth)++] = (int)(udiff[i] | 0xffffffe0L);
559                                        else
560                                                diff[(*lth)++] = udiff[i];
561                                break;
562                        case 2:  /* 10 */
563                                udiff[0] = (ultmp >> 24) & 0x0000000fL;
564                                udiff[1] = (ultmp >> 20) & 0x0000000fL;
565                                udiff[2] = (ultmp >> 16) & 0x0000000fL;
566                                udiff[3] = (ultmp >> 12) & 0x0000000fL;
567                                udiff[4] = (ultmp >>  8) & 0x0000000fL;
568                                udiff[5] = (ultmp >>  4) & 0x0000000fL;
569                                udiff[6] =  ultmp        & 0x0000000fL;
570                                for  (i=0; i<7; i++)
571                                        if  (udiff[i] & 0x00000008L)
572                                                diff[(*lth)++] = (int)(udiff[i] | 0xfffffff0L);
573                                        else
574                                                diff[(*lth)++] = udiff[i];
575                                break;
576                        default:
577                                /* no data, ignore */;
578                        } /*endswitch*/
579                        break;
580                default: /* 00 */
581                        frame += 4;  /* no data */
582                } /*endswitch*/
583        } /*endfor*/
584
585} /* end of SeedDecodeSteim2Frame */
586
587
588
589/*----------------------------------------------------------------------------*/
590
591
592
593unsigned short int SeedGet2Bytes( SeedSbyteT b[], BOOLEAN swap )
594
595/* returns word from byte stream
596 *
597 * parameters of routine
598 * SeedSbyteT b[];     input;   byte stream
599 * BOOLEAN    swap;    input;   swap bytes
600 */
601{
602        /* local variables */
603        unsigned short int   word;
604
605        /* executable code */
606
607        if  (swap)  {
608                word = ((unsigned short)(b[0]) & 0xff) * 0x100;
609                word += (unsigned short)(b[1]) & 0xff;
610        } else {
611                word = ((unsigned short)(b[1]) & 0xff) * 0x100;
612                word += (unsigned short)(b[0]) & 0xff;
613        } /*endif*/
614        return word;
615
616} /* end of SeedGet2Bytes */
617
618
619
620/*----------------------------------------------------------------------------*/
621
622
623
624unsigned INT32 SeedGet4Bytes( SeedSbyteT b[], BOOLEAN swap )
625
626/* returns word from byte stream
627 *
628 * parameters of routine
629 * SeedSbyteT b[];     input;   byte stream
630 * BOOLEAN    swap;    input;   swap bytes
631 */
632{
633        /* local variables */
634        unsigned INT32   lword;
635
636        /* executable code */
637
638        if  (swap)  {
639                lword = ((unsigned INT32)(b[0]) & 0xffL) * 0x1000000L;
640                lword += ((unsigned INT32)(b[1]) & 0xffL) * 0x10000L;
641                lword += ((unsigned INT32)(b[2]) & 0xffL) * 0x100;
642                lword += (unsigned INT32)b[3] & 0xffL;
643        } else {
644                lword = ((unsigned INT32)(b[3]) & 0xffL) * 0x1000000L;
645                lword += ((unsigned INT32)(b[2]) & 0xffL) * 0x10000L;
646                lword += ((unsigned INT32)(b[1]) & 0xffL) * 0x100;
647                lword += (unsigned INT32)b[0] & 0xffL;
648        } /*endif*/
649        return lword;
650
651} /* end of SeedGet4Bytes */
652
653
654
655/*---------------------------------------------------------------------*/
656
657
658
659void SeedFindFileInSfd( char stream_str[], char start[], char sfdfile[],
660        SeedFileDescrT *fdescr, STATUS *status )
661
662/* Finds SEED file in sfd-file of given stream and containing given
663 * start time.  If no file is found the file with the next possible
664 * time is returned
665 *
666 * parameters of routine
667 * char       stream_str[];      input; stream string like "bfo-vbb-z"
668 * char       start[];           input; start time
669 * char       sfdfile[];         input; SEED file directory
670 * SeedFileDescrT *fdescr;       output; SEED file descriptor
671 * STATUS     *status;           output; return status
672 */
673{
674        /* local variables */
675        FILE     *sfd;                          /* pointer to sfd-file */
676        char     line[Seed_C_SFDLINELTH+1];     /* current line */
677        float    tdiff;                         /* time difference */
678        float    min_tdiff;                     /* minimum tdiff */
679        SeedFileDescrT next;                    /* file with next time */
680        SeedFileDescrT curr;                    /* current line */
681        char     lstream_str[BC_SHORTSTRLTH+1]; /* local lowercase stream string */
682        char     station[cBcShortStrLth+1];     /* station name */
683        char     xaddinf[Seed_C_AddinfLth+1];   /* netcode+locid searched */
684        TSyBoolean from_db;                     /* DB file instead of sfdfile */
685        TSyBoolean firstline;                   /* first line of sfdfile */
686
687        /* executable code */
688
689        if  (strlen(stream_str) > BC_SHORTSTRLTH)  {
690                *status = SeedERR_STROVFL;
691                err_setcontext( " ## stream " );
692                err_setcontext( stream_str );
693                return;
694        } /*endif*/
695
696        SeedSplitStreamName( stream_str, lstream_str, station, xaddinf );
697
698        /* make stream string lowercase */
699        ut_uncap( lstream_str );
700
701        if  (GpGetInt(cGpI_debug_level) > 5)
702                printf( "SEED-dbg6: bench: in SeedFindFileInSfd, conventional sfdfile\n" );
703
704        /* initialize local descriptors */
705        strcpy( next.stream, lstream_str );
706        strcpy( curr.stream, lstream_str );
707        next.t_start[0] = curr.t_start[0] = '\0';
708        next.t_end[0] = curr.t_end[0] = '\0';
709        next.name[0] = curr.name[0] = '\0';
710        strcpy( next.sfdfile, sfdfile );
711        strcpy( curr.sfdfile, sfdfile );
712        next.recno = curr.recno = 0;
713        next.ufd = curr.ufd = Seed_C_ILLEGAL;
714        next.pos = curr.pos = 0;
715        next.sample = curr.sample = 0;
716        next.calib = curr.calib = 0.0;
717        next.dataflags = curr.dataflags = 0;
718        next.reclth = curr.reclth = DEFAULT_RECLTH;
719        next.byteoff = curr.byteoff = 0;
720        next.pri = curr.pri = 0;
721        next.dataformat = curr.dataformat = Seed_C_FORMAT_MSEED;
722        strcpy( next.addinf, Seed_C_EmptyAddinfStr );
723        strcpy( curr.addinf, Seed_C_EmptyAddinfStr );
724
725        sfd = sy_fopen( sfdfile, "r" );
726        if  (sfd == NULL)  {
727                *status = SeedERR_OPENINPUT;
728                err_setcontext( " ## file " );
729                err_setcontext( sfdfile );
730                return;
731        } /*endif*/
732
733        /* find requested stream and time in sfd-file*/
734        from_db = FALSE;  /* assume 'standard' sfdfile */
735        firstline = TRUE;
736        next.name[0] = '\0';
737        min_tdiff = 1.0e10;
738        fdescr->t_start[0] = '\0';
739        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
740                if  (*line == '!')  continue;
741                if  (firstline)  {
742                        firstline = FALSE;
743                        if  (strncmp(line,"station",7) == 0)  {
744                                from_db = TRUE;
745                                continue; /* first line in db file contains no data */
746                        } /*endif*/
747                } /*endif*/
748                if  (from_db)  {
749                        SqlParseSftabLine( line, station, &curr, status );
750                        if  (seedv_invert_swap_hdr)  curr.swap_hdr = ! curr.swap_hdr;
751                } else {
752                        SeedParseSfdLine( line, &curr, status );
753                } /*endif*/
754                if  (Severe(status))  {fclose(sfd); return;}
755                if  (strcmp(curr.stream,lstream_str) != 0)  continue;
756                if  (strcmp(xaddinf,Seed_C_EmptyAddinfStr) != 0
757                        && strcmp(xaddinf,curr.addinf) != 0)  continue;
758                tdiff = tc_tdiff( start, curr.t_start, status );
759                if  (Severe(status))  {fclose(sfd); return;}
760                if  (!GpGetBoolean(cGpB_ignore_data_lock)
761                        && (curr.dataflags & Seed_F_QUAL_DATA_LOCKED))  continue;
762                if  (tdiff >= 0.0 && tc_tdiff(start,curr.t_end,status) < 0.0)  {
763                        /* found matching entry */
764                        if  (fdescr->t_start[0] != '\0')  {
765                                /* already found a previous matching entry */
766                                if  (fdescr->pri >= curr.pri)  continue; /* this has lower priority */
767                        } /*endif*/
768                        *fdescr = curr;
769                        if  (fdescr->calib == 0.0)  {
770                                fdescr->calib =
771                                        SeedFindStreamCalibration( fdescr->stream, start, status );
772                                if  (*status == SeedERR_NOCALIB)  {
773                                        *status = cBcNoError;
774                                        fdescr->dataflags |= Seed_F_QUAL_NOCALIB;
775                                } /*endif*/
776                        } /*endif*/
777                        if  (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0)
778                                SeedAdjustFilename( fdescr, status );
779                        if  (GpGetInt(cGpI_debug_level) > 5)
780                                printf( "SEED-dbg6: bench: returning from SeedFindFileInSfd, conventional sfdfile (1)\n" );
781                        if  (!from_db)  {
782                                /* take first matching entry only in sfdfile */
783                                fclose( sfd );
784                                return;
785                        } /*endif*/
786                } else if  (tdiff < 0.0)  {
787                        /* entries ordered by time, return if a matching entry previously found */
788                        if  (fdescr->t_start[0] != '\0')  {
789                                fclose( sfd );
790                                return;
791                        } /*endif*/
792                        /* store file with time next to requested */
793                        if  (Severe(status))  {fclose(sfd); return;}
794                        if  (next.name[0] == '\0' || tdiff > min_tdiff)  {
795                                min_tdiff = tdiff;
796                                next = curr;
797                        } /*endif*/
798                        if  (next.calib == 0.0)  {
799                                next.calib =
800                                        SeedFindStreamCalibration( next.stream, start, status );
801                                if  (*status == SeedERR_NOCALIB)  {
802                                        *status = cBcNoError;
803                                        next.dataflags |= Seed_F_QUAL_NOCALIB;
804                                } /*endif*/
805                        } /*endif*/
806                } /*endif*/
807                if  (Severe(status))  {fclose(sfd); return;}
808        } /*endwhile*/
809
810        /* if a matching entry has been found, return here */
811        if  (fdescr->t_start[0] != '\0')  {
812                fclose( sfd );
813                return;
814        } /*endif*/
815
816        *status = (next.name[0] == '\0') ? SeedERR_SFD_NOTFOUND : SeedERR_SFD_NEXT;
817        if  (*status == SeedERR_SFD_NOTFOUND)  {
818                err_setcontext( " ## stream " );
819                err_setcontext( lstream_str );
820                err_setcontext( ", addinf " );
821                err_setcontext( xaddinf );
822                err_setcontext( ", time " );
823                err_setcontext( start );
824        } /*endif*/
825        fclose( sfd );
826        *fdescr = next;
827        if  (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0)
828                SeedAdjustFilename( fdescr, status );
829        if  (GpGetInt(cGpI_debug_level) > 5)
830                printf( "SEED-dbg6: bench: returning from SeedFindFileInSfd, conventional sfdfile (2)\n" );
831        return;
832
833} /* end of SeedFindFileInSfd */
834
835
836
837/*---------------------------------------------------------------------*/
838
839#ifdef XXX
840
841static void SeedFindFileInDatabase( char stream_str[], char start[],
842        char dbfile[], SeedFileDescrT *fdescr, STATUS *status )
843
844/* Finds SEED file in sfdb database. If no file is found the file with the
845 * next possible time is returned
846 *
847 * parameters of routine
848 * char       stream_str[];      input; stream string like "bfo-vbb-z"
849 * char       start[];           input; start time
850 * char       dbfile[];          input; DB output file
851 * SeedFileDescrT *fdescr;       output; SEED file descriptor
852 * STATUS     *status;           output; return status
853 */
854{
855        /* local variables */
856        static char last_start[cBcTimeLth+1]="";  /* last start time */
857        char     shellcmd[cBcVeryLongStrLth+1];   /* shell command */
858        char     tmpfileb[cBcFileLth+1];          /* scratch file 2 */
859        FILE     *fp;                             /* pointer to file */
860        char     tmpstr[cBcShortStrLth+1];        /* scratch string */
861        char     station[cBcShortStrLth+1];       /* passed station name */
862        char     chan[cBcShortStrLth+1];          /* passed channel name */
863        char     comp;                            /* passed component name */
864        char     tstation[cBcShortStrLth+1];      /* current station name */
865        char     tchan[cBcShortStrLth+1];         /* current channel name */
866        char     tcomp;                           /* current component name */
867        int      i;                               /* counter */
868        NTIME    ntime, ntimeb;                   /* numeric read time */
869        char     line[cBcLineLth+1];              /* current line of file */
870        int      pathid, pathidx;                 /* path ID */
871        char     relpath[cBcLineLth+1];           /* relative pathname */
872        SeedFileDescrT descr, descrx;             /* Seed file descr */
873        float    tdiff;                           /* time difference */
874        char     *rootpath;                       /* pointer to root path */
875        int      pri, prix;                       /* priority of entry */
876        int      dataformat;                      /* data format (not used yet) */
877        int      datea, dateb;                    /* dates of seed entry */
878        double   timea, timeb;                    /* times of entry */
879        int      rddate;                          /* read date as integer */
880        double   rdtime;                          /* read time as double */
881
882        /* executable code */
883
884        /* parse stream string */
885        if  (strlen(stream_str) > cBcShortStrLth)  {
886                *status = SeedERR_STROVFL;
887                return;
888        } /*endif*/
889        strcpy( tmpstr, stream_str );
890        ut_uncap( tmpstr );
891        for  (i=0; tmpstr[i] != '\0'; i++)
892                if  (tmpstr[i] == '-')  tmpstr[i] = ' ';
893        i = sscanf( tmpstr, "%s %s %c", station, chan, &comp );
894        if  (i < 3)  comp = ' ';
895        if  (i < 2)  strcpy( chan , "  " );
896        if  (i < 1)  strcpy( station , "   " );
897
898        fp = fopen( dbfile, "r" );
899        if  (fp == NULL)  {
900                *status = SeedERR_BUG;
901                err_setcontext( " ## error opening database file " );
902                err_setcontext( dbfile );
903                return;
904        } /*endif*/
905        /* read off header */
906        fgets( line, cBcLineLth, fp );
907
908        /* read through all entries (shouldn't be more than 2) */
909        descr.ufd = Seed_C_ILLEGAL;
910        descr.pos = 0;
911        descr.sample = 0;
912        strcpy( descr.addinf, Seed_C_EmptyAddinfStr );
913        descr.sfdfile[0] = descrx.sfdfile[0] = '\0';
914        descr.calib = 0.0;
915        pri = prix = 0;
916        while  (fgets(line,cBcLineLth,fp) != NULL)  {
917                /* parse line read */
918                if  (sscanf(line,"%s %s %c %d %s %d %lf %d %lf %d %d %d %d %d %d %d",
919                        tstation,tchan,&tcomp,&pathid,relpath,&datea,&timea,&dateb,&timeb,
920                        &descr.recno,&descr.swap_hdr,&descr.reclth,&descr.byteoff,
921                        &descr.dataflags,&pri,&dataformat) != 16)  {
922                        *status = SeedERR_DBREAD;
923                        fclose( fp );
924                        return;
925                } /*endif*/
926                if  (strcmp(station,tstation) != 0)  continue;
927                if  (strcmp(chan,tchan) != 0)  continue;
928                if  (comp != tcomp )  continue;
929                if  (GpGetInt(cGpI_debug_level) > 5)
930                        printf( "SHM-dbg6: got line %sSHM-dbg6: read times %d,%lf %d,%lf\n",
931                                line, datea, timea, dateb, timeb );
932                ntime.year = datea / 10000;
933                ntime.month = (datea % 10000) / 100;
934                ntime.day = datea % 100;
935                ntime.hour = Nint( timea / 10000.0 - 0.499 );
936                timea -= (double)ntime.hour*10000.0;
937                ntime.min = Nint( timea / 100.0 - 0.499 );
938                timea -= (double)ntime.min*100.0;
939                ntime.sec = Nint( timea - 0.499 );
940                timea -= (double)ntime.sec;
941                ntime.ms = Nint( timea*1000.0 );
942                if  (GpGetInt(cGpI_debug_level) > 5)
943                        printf( "SHM-dbg6: start ntime: %d,%d,%d,%d,%d,%d,%d\n", ntime.year,
944                                ntime.month, ntime.day, ntime.hour, ntime.min, ntime.sec, ntime.ms);
945                tc_n2t( &ntime, descr.t_start, status );
946                if  (SySevere(status))  {fclose(fp); return;}
947                ntime.year = dateb / 10000;
948                ntime.month = (dateb % 10000) / 100;
949                ntime.day = dateb % 100;
950                ntime.hour = Nint( timeb / 10000.0 - 0.499 );
951                timeb -= (double)ntime.hour*10000.0;
952                ntime.min = Nint( timeb / 100.0 - 0.499 );
953                timeb -= (double)ntime.min*100.0;
954                ntime.sec = Nint( timeb - 0.499 );
955                timeb -= (double)ntime.sec;
956                ntime.ms = Nint( timeb*1000.0 );
957                if  (GpGetInt(cGpI_debug_level) > 5)
958                        printf( "SHM-dbg6: start ntime: %d,%d,%d,%d,%d,%d,%d\n", ntime.year,
959                                ntime.month, ntime.day, ntime.hour, ntime.min, ntime.sec, ntime.ms);
960                tc_n2t( &ntime, descr.t_end, status );
961                if  (SySevere(status))  {fclose(fp); return;}
962                if  (strlen(station)+strlen(chan)+3 > cBcShortStrLth)  {
963                        *status = SeedERR_STROVFL;
964                        return;         
965                } /*endif*/
966                /* database list may contain files which do not match the requested time */
967                /* if priority is lower than the one we have, ignore entry */
968                if  (pri < prix)  continue;
969                /* if we already have a matching entry, compare with this here */
970                if  (descrx.sfdfile[0] != '\0')  {
971                        /* take the one with earlier start time */
972                        tdiff = tc_tdiff( descr.t_start, descrx.t_start, status );
973                        if  (SySevere(status))  return;
974                        if  (tdiff > 0.0)  continue;
975                } /*endif*/
976                sprintf( descr.stream, "%s-%s-%c", station, chan, comp );
977                strcpy( descr.name, relpath );
978                strcpy( descr.sfdfile, "db:" );
979                descrx = descr;
980                prix = pri;
981                pathidx = pathid;
982        } /*endfor*/
983
984        fclose( fp );
985
986        if  (descrx.sfdfile[0] == '\0')  {
987                *status = SeedERR_SFD_NOTFOUND;
988                return;
989        } /*endif*/
990        descr = descrx;
991        strcpy( relpath, descr.name );
992        pathid = pathidx;
993
994        /* now find absolute path, first look in cache */
995        rootpath = SeedGetRootPath( pathid );
996        if  (rootpath == NULL)  {
997                /* second temporary file */
998                i = 1;
999                FOREVER  {
1000                        sprintf( tmpfileb, "/tmp/sfdb_read_b_%d.000", i++ );
1001                        fp = fopen( tmpfileb, "r" );
1002                        if  (fp == NULL)  break;
1003                        fclose( fp );
1004                } /*endfor*/
1005                /* create empty file to reserve name */
1006                fp = fopen( tmpfileb, "w" );
1007                fclose( fp );
1008                /* not in cache, get it from database */
1009                sprintf( shellcmd,
1010                        "\\rm %s; %s %s \"select rootpath from pathtab where id = \'%d\'\" >%s",
1011                        tmpfileb, GpGetString(cGpS_sfdb_command),
1012                        GpGetString(cGpS_sfdb_exec_qual), pathid, tmpfileb );
1013                /*printf( "--> executing %s\n", shellcmd );*/
1014                system( shellcmd );
1015
1016                /* read output file */
1017                fp = fopen( tmpfileb, "r" );
1018                if  (fp == NULL)  {
1019                        *status = SeedERR_BUG;
1020                        err_setcontext( " ## error opening scratch file" );
1021                        return;
1022                } /*endif*/
1023                /* read off header */
1024                fgets( line, cBcLineLth, fp );
1025                fgets( descr.name, cBcFileLth, fp );
1026                i = strlen( descr.name );
1027                if  (i > 0 && descr.name[i-1] == '\n')  descr.name[i-1] = '\0';
1028                fclose( fp );
1029                /* put it to cache */
1030                SeedCacheRootPath( pathid, descr.name, status );
1031                sy_fdelete( tmpfileb );
1032        } else {
1033                strcpy( descr.name, rootpath );
1034        } /*endif*/
1035
1036        strcat( descr.name, "/" );
1037        strcat( descr.name, relpath );
1038
1039        if  (strlen(start) > cBcTimeLth)  {
1040                *status = SeedERR_BUG;
1041                err_setcontext( " ## time tring too long" );
1042                return;
1043        } /*endif*/
1044
1045        descr.calib = SeedFindStreamCalibration( descr.stream, start, status );
1046        if  (*status == SeedERR_NOCALIB)  {
1047                *status = cBcNoError;
1048                descr.dataflags |= Seed_F_QUAL_NOCALIB;
1049        } /*endif*/
1050        if  (seedv_invert_swap_hdr)  descr.swap_hdr = ! descr.swap_hdr;
1051        *fdescr = descr;
1052
1053} /* end of SeedFindFileInDatabase */
1054
1055#endif
1056
1057/*---------------------------------------------------------------------*/
1058
1059#ifdef XXX
1060
1061static void SeedFindFileInDatabaseOld( char stream_str[], char start[],
1062        SeedFileDescrT *fdescr, STATUS *status )
1063
1064/* Finds SEED file in sfdb database. If no file is found the file with the
1065 * next possible time is returned
1066 *
1067 * parameters of routine
1068 * char       stream_str[];      input; stream string like "bfo-vbb-z"
1069 * char       start[];           input; start time
1070 * char       sfdfile[];         input; SEED file directory
1071 * SeedFileDescrT *fdescr;       output; SEED file descriptor
1072 * STATUS     *status;           output; return status
1073 */
1074{
1075        /* local variables */
1076        static char last_start[cBcTimeLth+1]="";  /* last start time */
1077        char     shellcmd[cBcVeryLongStrLth+1];   /* shell command */
1078        char     tmpfileb[cBcFileLth+1];          /* scratch file 2 */
1079        FILE     *fp;                             /* pointer to file */
1080        char     tmpstr[cBcShortStrLth+1];        /* scratch string */
1081        char     station[cBcShortStrLth+1];       /* passed station name */
1082        char     chan[cBcShortStrLth+1];          /* passed channel name */
1083        char     comp;                            /* passed component name */
1084        char     tstation[cBcShortStrLth+1];      /* current station name */
1085        char     tchan[cBcShortStrLth+1];         /* current channel name */
1086        char     tcomp;                           /* current component name */
1087        int      i;                               /* counter */
1088        NTIME    ntime, ntimeb;                   /* numeric read time */
1089        char     line[cBcLineLth+1];              /* current line of file */
1090        int      pathid, pathidx;                 /* path ID */
1091        char     relpath[cBcLineLth+1];           /* relative pathname */
1092        SeedFileDescrT descr, descrx;             /* Seed file descr */
1093        float    tdiff;                           /* time difference */
1094        char     *rootpath;                       /* pointer to root path */
1095        int      pri, prix;                       /* priority of entry */
1096        int      dataformat;                      /* data format (not used yet) */
1097#ifdef USE_DATETIME
1098        char     datea[cBcShortStrLth+1];         /* date 1 */
1099        char     timea[cBcShortStrLth+1];         /* time 1 */
1100        int      msa;                             /* millisecs 1 */
1101        char     dateb[cBcShortStrLth+1];         /* date 2 */
1102        char     timeb[cBcShortStrLth+1];         /* time 2 */
1103        int      msb;                             /* millisecs 2 */
1104#else
1105        int      datea, dateb;                    /* dates of seed entry */
1106        double   timea, timeb;                    /* times of entry */
1107        int      rddate;                          /* read date as integer */
1108        double   rdtime;                          /* read time as double */
1109#endif
1110
1111        /* executable code */
1112
1113        /* parse stream string */
1114        if  (strlen(stream_str) > cBcShortStrLth)  {
1115                *status = SeedERR_STROVFL;
1116                return;
1117        } /*endif*/
1118        strcpy( tmpstr, stream_str );
1119        ut_uncap( tmpstr );
1120        for  (i=0; tmpstr[i] != '\0'; i++)
1121                if  (tmpstr[i] == '-')  tmpstr[i] = ' ';
1122        i = sscanf( tmpstr, "%s %s %c", station, chan, &comp );
1123        if  (i < 3)  comp = ' ';
1124        if  (i < 2)  strcpy( chan , "  " );
1125        if  (i < 1)  strcpy( station , "   " );
1126
1127        /* static temporary file, create if no call to db before */
1128        if  (last_start[0] == '\0')  {
1129                i = 1;
1130                FOREVER  {
1131                        sprintf( seedv_sfdb_tmp, "/tmp/sfdb_read_a_%d.000", i++ );
1132                        fp = fopen( seedv_sfdb_tmp, "r" );
1133                        if  (fp == NULL)  break;
1134                        fclose( fp );
1135                } /*endfor*/
1136                /* create empty file to reserve name */
1137                fp = fopen( seedv_sfdb_tmp, "w" );
1138                fclose( fp );
1139        } /*endif*/
1140
1141        /* convert time to numeric format */
1142        tc_t2n( start, &ntime, status );
1143        if  (SySevere(status))  return;
1144        tc_nadd( &ntime, 1.0, &ntimeb, status );
1145        if  (SySevere(status))  return;
1146
1147        if  (strcmp(start,last_start) != 0)  {
1148                /* call to db if new start time given */
1149#ifdef USE_DATETIME
1150                sprintf( shellcmd,
1151                        "\\rm %s; %s %s \"select * from sftab where stime <= \'%4d-%02d-%02d %02d:%02d:%02d\' and etime >= \'%4d-%02d-%02d %02d:%02d:%02d\'\" >%s",
1152                        seedv_sfdb_tmp, GpGetString(cGpS_sfdb_command), GpGetString(cGpS_sfdb_exec_qual),
1153                        ntime.year, ntime.month, ntime.day,
1154                        ntime.hour, ntime.min, ntime.sec, ntimeb.year, ntimeb.month, ntimeb.day,
1155                        ntimeb.hour, ntimeb.min, ntimeb.sec, seedv_sfdb_tmp );
1156#else
1157                rddate = ntime.year*10000 + ntime.month*100 + ntime.day;
1158                rdtime = (double)ntime.hour*10000.0 + (double)ntime.min*100.0
1159                        + (double)ntime.sec + (double)ntime.ms/1000.0;
1160                sprintf( shellcmd,
1161                        "\\rm %s; %s %s \"select * from sftab where ((sdate < %d) OR (sdate = %d AND stime <= %10.3f)) AND ((%d < edate) OR (%d = edate AND %10.3f <= etime))\" >%s",
1162                        seedv_sfdb_tmp, GpGetString(cGpS_sfdb_command),
1163                        GpGetString(cGpS_sfdb_exec_qual), rddate, rddate, rdtime, rddate,
1164                        rddate, rdtime, seedv_sfdb_tmp );
1165#endif
1166                if  (GpGetInt(cGpI_debug_level) > 3)
1167                        printf( "SH-dbg4: executing %s\n", shellcmd );
1168                system( shellcmd );
1169                strcpy( last_start, start );
1170        } /*endif*/
1171
1172        fp = fopen( seedv_sfdb_tmp, "r" );
1173        if  (fp == NULL)  {
1174                *status = SeedERR_BUG;
1175                err_setcontext( " ## error opening scratch file " );
1176                err_setcontext( seedv_sfdb_tmp );
1177                return;
1178        } /*endif*/
1179        /* read off header */
1180        fgets( line, cBcLineLth, fp );
1181
1182        /* read through all entries (shouldn't be more than 2) */
1183        descr.ufd = Seed_C_ILLEGAL;
1184        descr.pos = 0;
1185        descr.sample = 0;
1186        strcpy( descr.addinf, Seed_C_EmptyAddinfStr );
1187        descr.sfdfile[0] = descrx.sfdfile[0] = '\0';
1188        descr.calib = 0.0;
1189        pri = prix = 0;
1190        while  (fgets(line,cBcLineLth,fp) != NULL)  {
1191                /* parse line read */
1192#ifdef USE_DATETIME
1193                if  (sscanf(line,"%s %s %c %d %s %s %s %d %s %s %d %d %d %d %d %d %d",
1194                        tstation,tchan,&tcomp,&pathid,relpath,datea,timea,&msa,dateb,timeb,
1195                        &msb,&descr.recno,&descr.swap_hdr,&descr.reclth,&descr.byteoff,
1196                        &descr.dataflags,&pri) != 17)  {
1197                        *status = SeedERR_DBREAD;
1198                        fclose( fp );
1199                        return;
1200                } /*endif*/
1201#else
1202                if  (sscanf(line,"%s %s %c %d %s %d %lf %d %lf %d %d %d %d %d %d %d",
1203                        tstation,tchan,&tcomp,&pathid,relpath,&datea,&timea,&dateb,&timeb,
1204                        &descr.recno,&descr.swap_hdr,&descr.reclth,&descr.byteoff,
1205                        &descr.dataflags,&pri,&dataformat) != 16)  {
1206                        *status = SeedERR_DBREAD;
1207                        fclose( fp );
1208                        return;
1209                } /*endif*/
1210#endif
1211                if  (strcmp(station,tstation) != 0)  continue;
1212                if  (strcmp(chan,tchan) != 0)  continue;
1213                if  (comp != tcomp )  continue;
1214                if  (GpGetInt(cGpI_debug_level) > 5)
1215                        printf( "SHM-dbg6: got line %sSHM-dbg6: read times %d,%lf %d,%lf\n",
1216                                line, datea, timea, dateb, timeb );
1217#ifdef USE_DATETIME
1218                /* change '-'s to '/'s in dates, so that tc_... routines can read it */
1219                for  (i=0; datea[i] != '\0'; i++)
1220                        if  (datea[i] == '-')  datea[i] = '/';
1221                for  (i=0; dateb[i] != '\0'; i++)
1222                        if  (dateb[i] == '-')  dateb[i] = '/';
1223                sprintf( descr.t_start, "%s_%s", datea, timea );
1224                sprintf( descr.t_end, "%s_%s", dateb, timeb );
1225                /* add the milliseconds, which were not used in DB search */
1226                tc_tadd( descr.t_start, (float)msa/1000.0, descr.t_start, status );
1227                if  (SySevere(status))  {fclose(fp); return;}
1228                tc_tadd( descr.t_end, (float)msb/1000.0, descr.t_end, status );
1229                if  (SySevere(status))  {fclose(fp); return;}
1230                tdiff = tc_tdiff( start, descr.t_start, status );
1231                if  (SySevere(status))  {fclose(fp); return;}
1232                if  (tdiff < 0.0)  continue;  /* then the milliseconds didn't match */
1233                tdiff = tc_tdiff( descr.t_end, start, status );
1234                if  (SySevere(status))  {fclose(fp); return;}
1235                if  (tdiff < 0.0)  continue;  /* then the milliseconds didn't match */
1236#else
1237                ntime.year = datea / 10000;
1238                ntime.month = (datea % 10000) / 100;
1239                ntime.day = datea % 100;
1240                ntime.hour = Nint( timea / 10000.0 - 0.499 );
1241                timea -= (double)ntime.hour*10000.0;
1242                ntime.min = Nint( timea / 100.0 - 0.499 );
1243                timea -= (double)ntime.min*100.0;
1244                ntime.sec = Nint( timea - 0.499 );
1245                timea -= (double)ntime.sec;
1246                ntime.ms = Nint( timea*1000.0 );
1247                if  (GpGetInt(cGpI_debug_level) > 5)
1248                        printf( "SHM-dbg6: start ntime: %d,%d,%d,%d,%d,%d,%d\n", ntime.year,
1249                                ntime.month, ntime.day, ntime.hour, ntime.min, ntime.sec, ntime.ms);
1250                tc_n2t( &ntime, descr.t_start, status );
1251                if  (SySevere(status))  {fclose(fp); return;}
1252                ntime.year = dateb / 10000;
1253                ntime.month = (dateb % 10000) / 100;
1254                ntime.day = dateb % 100;
1255                ntime.hour = Nint( timeb / 10000.0 - 0.499 );
1256                timeb -= (double)ntime.hour*10000.0;
1257                ntime.min = Nint( timeb / 100.0 - 0.499 );
1258                timeb -= (double)ntime.min*100.0;
1259                ntime.sec = Nint( timeb - 0.499 );
1260                timeb -= (double)ntime.sec;
1261                ntime.ms = Nint( timeb*1000.0 );
1262                if  (GpGetInt(cGpI_debug_level) > 5)
1263                        printf( "SHM-dbg6: start ntime: %d,%d,%d,%d,%d,%d,%d\n", ntime.year,
1264                                ntime.month, ntime.day, ntime.hour, ntime.min, ntime.sec, ntime.ms);
1265                tc_n2t( &ntime, descr.t_end, status );
1266                if  (SySevere(status))  {fclose(fp); return;}
1267#endif
1268                if  (strlen(station)+strlen(chan)+3 > cBcShortStrLth)  {
1269                        *status = SeedERR_STROVFL;
1270                        return;         
1271                } /*endif*/
1272                /* if priority is lower than the one we have, ignore entry */
1273                if  (pri < prix)  continue;
1274                /* if we already have a matching entry, compare with this here */
1275                if  (descrx.sfdfile[0] != '\0')  {
1276                        /* take the one with earlier start time */
1277                        tdiff = tc_tdiff( descr.t_start, descrx.t_start, status );
1278                        if  (SySevere(status))  return;
1279                        if  (tdiff > 0.0)  continue;
1280                } /*endif*/
1281                sprintf( descr.stream, "%s-%s-%c", station, chan, comp );
1282                strcpy( descr.name, relpath );
1283                strcpy( descr.sfdfile, "db:" );
1284                descrx = descr;
1285                prix = pri;
1286                pathidx = pathid;
1287        } /*endfor*/
1288
1289        fclose( fp );
1290
1291        if  (descrx.sfdfile[0] == '\0')  {
1292                *status = SeedERR_SFD_NOTFOUND;
1293                return;
1294        } /*endif*/
1295        descr = descrx;
1296        strcpy( relpath, descr.name );
1297        pathid = pathidx;
1298
1299        /* now find absolute path, first look in cache */
1300        rootpath = SeedGetRootPath( pathid );
1301        if  (rootpath == NULL)  {
1302                /* second temporary file */
1303                i = 1;
1304                FOREVER  {
1305                        sprintf( tmpfileb, "/tmp/sfdb_read_b_%d.000", i++ );
1306                        fp = fopen( tmpfileb, "r" );
1307                        if  (fp == NULL)  break;
1308                        fclose( fp );
1309                } /*endfor*/
1310                /* create empty file to reserve name */
1311                fp = fopen( tmpfileb, "w" );
1312                fclose( fp );
1313                /* not in cache, get it from database */
1314                sprintf( shellcmd,
1315                        "\\rm %s; %s %s \"select rootpath from pathtab where id = \'%d\'\" >%s",
1316                        tmpfileb, GpGetString(cGpS_sfdb_command),
1317                        GpGetString(cGpS_sfdb_exec_qual), pathid, tmpfileb );
1318                /*printf( "--> executing %s\n", shellcmd );*/
1319                system( shellcmd );
1320
1321                /* read output file */
1322                fp = fopen( tmpfileb, "r" );
1323                if  (fp == NULL)  {
1324                        *status = SeedERR_BUG;
1325                        err_setcontext( " ## error opening scratch file" );
1326                        return;
1327                } /*endif*/
1328                /* read off header */
1329                fgets( line, cBcLineLth, fp );
1330                fgets( descr.name, cBcFileLth, fp );
1331                i = strlen( descr.name );
1332                if  (i > 0 && descr.name[i-1] == '\n')  descr.name[i-1] = '\0';
1333                fclose( fp );
1334                /* put it to cache */
1335                SeedCacheRootPath( pathid, descr.name, status );
1336                sy_fdelete( tmpfileb );
1337        } else {
1338                strcpy( descr.name, rootpath );
1339        } /*endif*/
1340
1341        strcat( descr.name, "/" );
1342        strcat( descr.name, relpath );
1343
1344        if  (strlen(start) > cBcTimeLth)  {
1345                *status = SeedERR_BUG;
1346                err_setcontext( " ## time tring too long" );
1347                return;
1348        } /*endif*/
1349
1350        descr.calib = SeedFindStreamCalibration( descr.stream, start, status );
1351        if  (*status == SeedERR_NOCALIB)  {
1352                *status = cBcNoError;
1353                descr.dataflags |= Seed_F_QUAL_NOCALIB;
1354        } /*endif*/
1355        if  (seedv_invert_swap_hdr)  descr.swap_hdr = ! descr.swap_hdr;
1356        *fdescr = descr;
1357
1358} /* end of SeedFindFileInDatabaseOld */
1359
1360#endif
1361
1362/*---------------------------------------------------------------------*/
1363
1364
1365
1366void SeedSearchPosition( int chan, char sfdfile[], char stream_str[],
1367        char req_start[], char act_start[], STATUS *status )
1368
1369/* Searches for given time position in a stream file.  The corresponding
1370 * SEED file is opened and positioned, its file descriptor stored
1371 * in an internal variable.  'chan' must range from 0..Seed_C_MAXCHAN-1.
1372 * If the channel is already used the previously opened file is closed.
1373 *
1374 * parameters of routine
1375 * int        chan;             input; channel number
1376 * char       sfdfile[];        input; sfd-file
1377 * char       stream_str[];     input; stream string
1378 * char       req_start[];      input; requested start time
1379 * char       act_start[];      output; actual start time
1380 * STATUS     *status;          output; return status
1381 */
1382{
1383        /* local variables */
1384        BOOLEAN  next_time;      /* only next time possible */
1385        float    tdiff_tot;      /* total time window of file */
1386        float    tdiff_start;    /* difference to request time */
1387        SeedFileDescrT *fd;      /* pointer to file descriptor */
1388        INT32    seek_pos;       /* seek position */
1389        NTIME    req_ntime;      /* requested time in NTIME format */
1390        NTIME    cur_ntime;      /* start time of current SEED record */
1391        float    cur_span;       /* time span (sec) of current SEED record */
1392        float    dt;             /* sample distance in sec */
1393        int      jump_rec;       /* number of records to jump */
1394        int      new_pos;        /* new record position */
1395        int      jump_cnt;       /* jump counter */
1396
1397        /* executable code */
1398
1399        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  {
1400                *status = SeedERR_CHAN_OOR;
1401                return;
1402        } /*endif*/
1403        fd = seedv_fd + chan;
1404
1405        if  (fd->ufd != Seed_C_ILLEGAL)  {
1406                close( fd->ufd );
1407                fd->ufd = Seed_C_ILLEGAL;
1408        } /*endif*/
1409
1410        SeedFindFileInSfd( stream_str, req_start, sfdfile, fd, status );
1411        next_time =  (*status == SeedERR_SFD_NEXT);
1412        if  (next_time)  *status = BC_NOERROR;
1413        if  (Severe(status))  return;
1414
1415        if  (GpGetInt(cGpI_debug_level) > 4)
1416                printf( "Seed-dbg5: opening file %s\n", fd->name );
1417        fd->ufd = open( fd->name, O_RDONLY );
1418        if  (fd->ufd < 0)  {
1419                *status = SeedERR_OPENINPUT;
1420                err_setcontext( " ## file " );
1421                err_setcontext( fd->name );
1422                fd->ufd = Seed_C_ILLEGAL;
1423                return;
1424        } /*endif*/
1425
1426        /* opened new file, jump to offset position if any */
1427        if  (fd->byteoff > 0)  {
1428                if  (lseek(fd->ufd,fd->byteoff,SEEK_SET) != fd->byteoff)  {
1429                        *status = SeedERR_SEEDSEEK;
1430                        err_setcontext( " ## file " );
1431                        err_setcontext( fd->name );
1432                        return;
1433                } /*endif*/
1434        } /*endif*/
1435
1436        if  (next_time)  {
1437                strcpy( act_start, fd->t_start );
1438                *status = SeedERR_NEXTTIMEPOS;
1439                return;
1440        } /*endif*/
1441        tc_t2n( req_start, &req_ntime, status );
1442        if  (Severe(status))  return;
1443
1444        /* compute approximate record position */
1445        tdiff_tot = tc_tdiff( fd->t_end, fd->t_start, status );
1446        if  (Severe(status))  return;
1447        tdiff_start = tc_tdiff( req_start, fd->t_start, status );
1448        if  (Severe(status))  return;
1449        new_pos = Nint( (float)((fd->recno)-1)/tdiff_tot * tdiff_start );
1450
1451        for  (jump_cnt=0; jump_cnt<4; jump_cnt++)  {
1452
1453                /* position SEED file */
1454                if  (new_pos != fd->pos)  {
1455                        if  (new_pos >= fd->recno)  new_pos = fd->recno-1;
1456                        if  (new_pos < 0)  new_pos = 0;
1457                        fd->pos = new_pos;
1458                        seek_pos = (INT32)(fd->pos) * (INT32)(fd->reclth) + (INT32)(fd->byteoff);
1459                        if  (seedv_logrec)  printf( "-" );
1460                        if  (lseek(fd->ufd,seek_pos,SEEK_SET) != seek_pos)  {
1461                                *status = SeedERR_SEEDSEEK;
1462                                err_setcontext( " ## file " );
1463                                err_setcontext( fd->name );
1464                                return;
1465                        } /*endif*/
1466                } /*endif*/
1467
1468                /* read current SEED record */
1469                if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
1470                if  (read(fd->ufd,(char *)seedv_rec,fd->reclth) != fd->reclth)  {
1471                        *status = SeedERR_SEEDREAD;
1472                        err_setcontext( " ## file " );
1473                        err_setcontext( fd->name );
1474                        return;
1475                } /*endif*/
1476                (fd->pos)++;
1477                SeedStoreReclth( seedv_rec, fd->reclth );
1478                if  (fd->swap_hdr)  SeedSwapHeader( seedv_rec );
1479                dt = SeedGetSampleDist( seedv_rec );
1480
1481                /* check time found (return if time found) */
1482                SeedBtimeToNtime( &(seedv_rec->starttime), &cur_ntime, status );
1483                if  (Severe(status))  return;
1484                /* check for time correction, K.S. 16-Mar-99 */
1485                /* In old sfdfiles where the time correction is not applied */
1486                /* this may cause problems, since the specified time windows are */
1487                /* not exact.  This case is handled later. */
1488                if  (seedv_use_timecorr && (seedv_rec->timecorr != 0)
1489                        && (((int)(seedv_rec->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
1490                        tc_nadd( &cur_ntime, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
1491                                &cur_ntime, status );
1492                        if  (Severe(status))  return;
1493                } /*endif*/
1494                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
1495                if  (Severe(status))  return;
1496                cur_span = (float)(seedv_rec->no_of_samples) * dt;
1497                if  (tdiff_start >= 0.0)  {
1498                        if  (cur_span > tdiff_start)  {
1499                                /* found it ! */
1500                                seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->reclth)
1501                                        + (INT32)(fd->byteoff);
1502                                lseek( fd->ufd, seek_pos, SEEK_SET );
1503                                fd->sample = Nint( tdiff_start/dt );
1504                                if  (fd->sample >/*=*/ (int)(seedv_rec->no_of_samples))  {
1505                                        printf( "! SeedSearchPosition: sample position adjusted (1)\n" );
1506                                        fd->sample = seedv_rec->no_of_samples /*- 1*/;
1507                                } /*endif*/
1508                                tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status );
1509                                if  (Severe(status))  return;
1510                                tc_n2t( &req_ntime, act_start, status );
1511                                return;
1512                        } /*endif*/
1513                } /*endif*/
1514
1515                /* estimate next jump */
1516                if  (tdiff_start > 0.0)  tdiff_start -= cur_span;
1517                jump_rec = Nint( floor(tdiff_start/cur_span) );
1518                if  (jump_rec >= 0)  jump_rec++;  else  jump_rec--;
1519                new_pos = fd->pos - 1 + jump_rec;
1520
1521        } /*endfor*/
1522
1523        /* if still not found then read record by record */
1524        if  (seedv_logrec)  printf( "|" );
1525
1526        /* go back to time before */
1527        tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
1528        while  (tdiff_start < 0.0)  {
1529                fd->pos -= 2;
1530                if  (fd->pos < 0)  {
1531                        if  ((tdiff_start > ((-1.5)*(float)(seedv_rec->timecorr)/TIMECORRUNIT))
1532                                && seedv_use_timecorr)  {
1533                                /* This may happen if the sfdfile does not contain possible time  */
1534                                /* corrections of the data.  Try to fix this by positioning to    */
1535                                /* a time shifted by the correction.  The samples before this time*/
1536                                /* are not read.  Call this routine recursively.                  */
1537                                {
1538                                        char  newtime[cBcTimeLth+1];    /* new time position */
1539                                        tc_tadd( req_start, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
1540                                                newtime, status );
1541                                        if  (SySevere(status))  {
1542                                                fprintf( stderr,
1543                                                        "*** SeedSearchPosition: error in time calc\n");
1544                                                *status = SeedERR_BUG;
1545                                                return;
1546                                        } /*endif*/
1547                                        fprintf( stderr,
1548                                                "SeedSearchPosition: try to fix time correction bug\n" );
1549                                        SeedSearchPosition( chan, sfdfile, stream_str, newtime,
1550                                                act_start, status );
1551                                        return;
1552                                }
1553                        } else {
1554                                fprintf( stderr, "*** SeedSearchPosition: check sfdfile\n" );
1555                                *status = SeedERR_BUG;
1556                                return;
1557                        } /*endif*/
1558                } /*endif*/
1559                seek_pos = (INT32)(fd->pos) * (INT32)(fd->reclth) + (INT32)(fd->byteoff);
1560                if  (seedv_logrec)  printf( "-" );
1561                if  (lseek(fd->ufd,seek_pos,SEEK_SET) != seek_pos)  {
1562                        *status = SeedERR_SEEDSEEK;
1563                        err_setcontext( " ## file " );
1564                        err_setcontext( fd->name );
1565                        return;
1566                } /*endif*/
1567                if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
1568                if  (read(fd->ufd,(char *)seedv_rec,fd->reclth) != fd->reclth)  {
1569                        *status = SeedERR_SEEDREAD;
1570                        err_setcontext( " ## file " );
1571                        err_setcontext( fd->name );
1572                        return;
1573                } /*endif*/
1574                (fd->pos)++;
1575                SeedStoreReclth( seedv_rec, fd->reclth );
1576                if  (fd->swap_hdr)  SeedSwapHeader( seedv_rec );
1577                dt = SeedGetSampleDist( seedv_rec );
1578                SeedBtimeToNtime( &(seedv_rec->starttime), &cur_ntime, status );
1579                if  (Severe(status))  return;
1580                /* check for time correction, K.S. 16-Mar-99 */
1581                if  (seedv_use_timecorr && (seedv_rec->timecorr != 0)
1582                        && (((int)(seedv_rec->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
1583                        tc_nadd( &cur_ntime, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
1584                                &cur_ntime, status );
1585                        if  (Severe(status))  return;
1586                } /*endif*/
1587                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
1588                if  (Severe(status))  return;
1589                cur_span = (float)(seedv_rec->no_of_samples) * dt;
1590        } /*endwhile*/
1591
1592        /* now find forward */
1593        while  (tdiff_start >= cur_span)  {
1594                if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
1595                if  (read(fd->ufd,(char *)seedv_rec,fd->reclth) != fd->reclth)  {
1596                        *status = SeedERR_SEEDREAD;
1597                        err_setcontext( " ## file " );
1598                        err_setcontext( fd->name );
1599                        return;
1600                } /*endif*/
1601                (fd->pos)++;
1602                SeedStoreReclth( seedv_rec, fd->reclth );
1603                if  (fd->swap_hdr)  SeedSwapHeader( seedv_rec );
1604                dt = SeedGetSampleDist( seedv_rec );
1605                SeedBtimeToNtime( &(seedv_rec->starttime), &cur_ntime, status );
1606                if  (Severe(status))  return;
1607                /* check for time correction, K.S. 16-Mar-99 */
1608                if  (seedv_use_timecorr && (seedv_rec->timecorr != 0)
1609                        && (((int)(seedv_rec->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
1610                        tc_nadd( &cur_ntime, (float)(seedv_rec->timecorr)/TIMECORRUNIT,
1611                                &cur_ntime, status );
1612                        if  (Severe(status))  return;
1613                } /*endif*/
1614                tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status );
1615                if  (Severe(status))  return;
1616                cur_span = (float)(seedv_rec->no_of_samples) * dt;
1617        } /*endwhile*/
1618
1619        /* step one record back to get it again on next read command */
1620        seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->reclth) + (INT32)(fd->byteoff);
1621        lseek( fd->ufd, seek_pos, SEEK_SET );
1622
1623        if  (tdiff_start >= 0.0)  {
1624                /* now found it */
1625                fd->sample = Nint( tdiff_start/dt );
1626                if  (fd->sample >/*=*/ (int)(seedv_rec->no_of_samples))  {
1627                        printf( "! SeedSearchPosition: sample position adjusted (2)\n" );
1628                        fd->sample = seedv_rec->no_of_samples /*- 1*/;
1629                } /*endif*/
1630                tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status );
1631                if  (Severe(status))  return;
1632                tc_n2t( &req_ntime, act_start, status );
1633        } else {
1634                /* time gap */
1635                /* printf( "*** time gap: next possible time positioned ***\n" ); */
1636                tc_n2t( &cur_ntime, act_start, status );
1637                *status = SeedERR_NEXTTIMEPOS;
1638        } /*endif*/
1639
1640} /* end of SeedSearchPosition */
1641
1642
1643
1644/*----------------------------------------------------------------------------*/
1645
1646
1647
1648void SeedBtimeToNtime( SeedBtimeT *btime, NTIME *ntime, STATUS *status )
1649
1650/* converts SeedBtimeT to NTIME
1651 *
1652 * parameters of routine
1653 * SeedBtimeT *bt;      input; SEED binary time
1654 * NTIME      *nt;      output; KS numeric time
1655 * STATUS     *status;  output; return status
1656 */
1657{
1658        /* executable code */
1659
1660        ntime->year = btime->year;
1661        tc_dayofmn( btime->year, btime->day, &(ntime->month),
1662                &(ntime->day), status );
1663        if  (Severe(status))  return;
1664        ntime->hour = btime->hours;
1665        ntime->min = btime->minutes;
1666        ntime->sec = btime->seconds;
1667        ntime->ms = btime->frac_secs/10;
1668
1669} /* end of SeedBtimeToNtime */
1670
1671
1672
1673/*----------------------------------------------------------------------------*/
1674
1675
1676
1677void SeedNtimeToBtime( NTIME *ntime, SeedBtimeT *btime, STATUS *status )
1678
1679/* converts NTIME to BTIME
1680 *
1681 * parameters of routine
1682 * NTIME      *nt;      input; KS numeric time
1683 * BTIME      *bt;      output; SEED binary time
1684 * STATUS     *status;  output; return status
1685 */
1686{
1687        /* executable code */
1688
1689        btime->year = ntime->year;
1690        btime->day = tc_julian( ntime->year, ntime->month,
1691                ntime->day, status );
1692        if  (Severe(status))  return;
1693        btime->hours = ntime->hour;
1694        btime->minutes = ntime->min;
1695        btime->seconds = ntime->sec;
1696        btime->frac_secs = ntime->ms*10;
1697
1698} /* end of SeedNtimeToBtime */
1699
1700
1701
1702/*---------------------------------------------------------------------*/
1703
1704
1705
1706float SeedGetSampleDist( SeedDataHeaderT *hdr )
1707
1708/* Returns sample distance in sec.
1709 *
1710 * parameters of routine
1711 * SeedDataHeaderT  *hdr;        input; SEED data header
1712 *                               returns sample distance in sec
1713 */
1714{
1715        /* executable code */
1716
1717        if  (hdr->smprate_fact > 0 && hdr->smprate_mult > 0)  {
1718                return (1.0/((float)(hdr->smprate_fact) * (float)(hdr->smprate_mult)));
1719        } else if  (hdr->smprate_fact > 0 && hdr->smprate_mult < 0)  {
1720                return (-1.0/((float)(hdr->smprate_fact)/(float)(hdr->smprate_mult)));
1721        } else if  (hdr->smprate_fact < 0 && hdr->smprate_mult > 0)  {
1722                return (-1.0/((float)(hdr->smprate_mult)/(float)(hdr->smprate_fact)));
1723        } else if  (hdr->smprate_fact < 0 && hdr->smprate_mult < 0)  {
1724                return (1.0/((float)(hdr->smprate_fact)/(float)(hdr->smprate_mult)));
1725        } else {
1726                fprintf( stderr, "*** illegal sample rate, set dt=1.0\n" );
1727                return 1.0;
1728        } /*endif*/
1729
1730} /* end of SeedGetSampleDist */
1731
1732
1733
1734/*---------------------------------------------------------------------*/
1735
1736
1737
1738void SeedReadNextRecord( int chan, SeedSbyteT *rec, BOOLEAN *hdr_swapped,
1739        STATUS *status )
1740
1741/* Reads next available record from SEED file.  If the header must be
1742 * swapped this is done and indicated in '*hdr_swapped'.
1743 *
1744 * parameters of routine
1745 * int        chan;               input; channel number
1746 * SeedSbyteT *rec;               output; SEED record
1747 * BOOLEAN    *hdr_swapped;       output; tells whether header was swapped
1748 * STATUS     *status;            output; return status
1749 */
1750{
1751        /* local variables */
1752        SeedFileDescrT *fd;                  /* SEED file descriptor */
1753        char     l_sfdfile[BC_FILELTH+1];    /* local sfdfile */
1754        char     l_stream[BC_SHORTSTRLTH+1]; /* local stream string */
1755        char     l_t_end[BC_TIMELTH+1];      /* end of file time */
1756        char     act_time[BC_TIMELTH+1];     /* positioned time */
1757        BOOLEAN  time_gap;                   /* time gap found */
1758
1759        /* executable code */
1760
1761        /* check channel number */
1762        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  {
1763                *status = SeedERR_CHAN_OOR;
1764                return;
1765        } /*endif*/
1766        fd = seedv_fd + chan;
1767
1768        if  (fd->ufd == Seed_C_ILLEGAL)  {
1769                *status = SeedERR_NOT_OPEN;
1770                return;
1771        } /*endif*/
1772
1773        /* store filename for last used file request */
1774        strcpy( seedv_last_fname, fd->name );
1775
1776        time_gap = FALSE;
1777        if  (fd->pos >= fd->recno)  {
1778                /* is at end of file */
1779                strcpy( l_sfdfile, fd->sfdfile );
1780                strcpy( l_stream, fd->stream );
1781                strcpy( l_t_end, fd->t_end );
1782                SeedSearchPosition( chan, l_sfdfile, l_stream, l_t_end,
1783                        act_time, status );
1784                time_gap = (*status == SeedERR_NEXTTIMEPOS);
1785                if  (time_gap)  *status = BC_NOERROR;
1786                if  (Severe(status))  return;
1787        } /*endif*/
1788
1789        if  (seedv_logrec)  printf( "[%d]", fd->pos );  /* log */
1790        if  (read(fd->ufd,(char *)rec,fd->reclth) != fd->reclth)  {
1791                *status = SeedERR_SEEDREAD;
1792                err_setcontext( " ## file " );
1793                err_setcontext( fd->name );
1794                return;
1795        } /*endif*/
1796        (fd->pos)++;
1797        SeedStoreReclth( (SeedDataHeaderT *)rec, fd->reclth );
1798        if  (fd->swap_hdr)  SeedSwapHeader( (SeedDataHeaderT *)rec );
1799        *hdr_swapped = fd->swap_hdr;
1800
1801        if  (time_gap)  *status = SeedERR_NEXTTIMEPOS;
1802
1803} /* end of SeedReadNextRecord */
1804
1805
1806
1807/*---------------------------------------------------------------------*/
1808
1809
1810
1811void SeedEncodeSteim1( int fd, INT32 smp[], INT32 *prev_smp, INT32 *idx,
1812        NTIME *ctime, SeedSbyteT *wrk, int wrklth, BOOLEAN complete, STATUS *status )
1813
1814/* Encodes sample array smp to SEED output file fd (UNIX file descriptor).
1815 * If complete is set to TRUE the last (probably not completely used)
1816 * record is written to the file, otherwise the samples of the
1817 * last record remain in the sample array.
1818 *
1819 * parameters of routine
1820 * int        fd;            input; UNIX file descr of output file
1821 * INT32      smp[];         modify; sample array to encode
1822 * INT32      *prev_smp;     modify; last sample before smp[0]
1823 * INT32      *idx;          modify; length of sample array
1824 * NTIME      *ctime;        modify; input: start time, output: new start time
1825 * SeedSbyteT *wrk;          scratch; work space for encoding
1826 * int        wrklth;        input; length of work space in records
1827 * BOOLEAN    complete;      input; finish up all records (-> *idx == 0)
1828 * STATUS     *status;       output; return status
1829 */
1830{
1831        /* local variables */
1832        static int rec_cnt=1;            /* record counter */
1833        int      recs_used;              /* number of records used */
1834        SeedDataHeaderT *hdr;            /* SEED data header */
1835        int      i;                      /* counter */
1836        char     str[BC_SHORTSTRLTH+1];  /* scratch string */
1837        int      write_ret;              /* write return value */
1838        int      smp_written;            /* total number of samples written to file*/
1839        float    dt;                     /* sample distance */
1840        int      rlexp;                  /* record length exponent */
1841        SeedBlockette1000T *b1000;       /* blockette 1000 */
1842        SeedBlockette1001T *b1001;       /* blockette 1001 */
1843
1844        /* executable code */
1845
1846        /* put start time to header prototype */
1847        SeedNtimeToBtime( ctime, &seedv_hdr_proto.starttime, status );
1848        if  (Severe(status))  return;
1849
1850        if  (*idx <= 0)  return;
1851
1852        /* compute record length exponent, needed for blockette 1000 */
1853        i = 1;
1854        rlexp = 0;
1855        while  (i < seedv_out_reclth)  {
1856                i *= 2;
1857                rlexp++;
1858        } /*endif*/
1859
1860        /* encode data */
1861        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)&seedv_hdr_proto,
1862                (UINT32)(*idx), (WORD)(seedv_out_reclth), (INT32 *)wrk, *prev_smp);
1863        if  (recs_used > wrklth)  {
1864                fprintf( stderr,
1865                        "***!!! SeedEncodeSteim1: record array exceeded -> abort !!!***\n" );
1866                exit( 1 );
1867        } /*endif*/
1868
1869        /* if last record not to be written, keep it in smp-buffer */
1870        if  (complete)  {
1871                *prev_smp = (*idx > 0) ? smp[(*idx)-1] : 0;
1872                *idx = 0;
1873        } else {
1874                if  (recs_used == 1)  {
1875                        /* printf( "*** SeedEncodeSteim1: only 1 record, no flush\n" ); */
1876                        return;
1877                } /*endif*/
1878                hdr = (SeedDataHeaderT *)(wrk + (recs_used-1)*seedv_out_reclth);
1879                *prev_smp = smp[(*idx)-hdr->no_of_samples-1];
1880                memcpy( (char *)smp, (char *)(smp+(*idx)-(int)(hdr->no_of_samples)),
1881                        (int)(hdr->no_of_samples)*sizeof(INT32) );
1882                *idx = hdr->no_of_samples;
1883                recs_used--;
1884        } /*endif*/
1885
1886        /* write records to file */
1887        smp_written = 0;
1888        for  (i=0; i<recs_used; i++)  {
1889                hdr = (SeedDataHeaderT *)(wrk+i*seedv_out_reclth);
1890                sprintf( str, "%06d", rec_cnt++ );
1891                strncpy( (char *)hdr, str, 6 );
1892                hdr->Reserved_bytes_A = ' ';
1893                /* insert blockette 1000, 14-Apr-2005 */
1894                hdr->no_of_blockettes = 1;
1895                hdr->first = 48;
1896                b1000 = (SeedBlockette1000T *)((char *)hdr + (unsigned)(hdr->first));
1897                b1000->type = 1000;
1898                b1000->nextblock = 0;
1899                b1000->format = (UBYTE)Seed_C_DcmpSteim1;
1900                b1000->wordorder = (UBYTE)1;
1901                b1000->reclthexp = (UBYTE)rlexp;
1902                b1000->reserved = (UBYTE)0;
1903                /* end of blockette 1000 code */
1904                /* insert blockette 1001 if time quality >= 0 */
1905                if  (seedv_timequal >= 0)  {
1906                        hdr->no_of_blockettes = 2;
1907                        b1000->nextblock = 56;
1908                        b1001 = (SeedBlockette1001T *)((char *)hdr + (unsigned)(b1000->nextblock));
1909                        b1001->type = 1001;
1910                        b1001->nextblock = 0;
1911                        b1001->timequal = (UBYTE)seedv_timequal;
1912                        b1001->reserved = (UBYTE)0;
1913                        /* reset timequal to -1 */
1914                        seedv_timequal = -1;
1915                } /*endif*/
1916                /* end of blockette 1001 code */
1917#               ifdef cBc_OS_LINUX
1918                SeedStoreReclth( hdr, seedv_out_reclth );
1919                SeedSwapHeader( hdr );
1920                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
1921#               endif
1922                write_ret = (int)write( fd, (char *)hdr, seedv_out_reclth );
1923#               ifdef cBc_OS_LINUX
1924                /* swap it back otherwise not readable any more */
1925                SeedSwapHeader( hdr );
1926                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
1927#               endif
1928                if  (write_ret != seedv_out_reclth)  {
1929                        *status = SeedERR_SEEDWRITE;
1930                        return;
1931                } /*endif*/
1932                smp_written += hdr->no_of_samples;
1933        } /*endfor*/
1934
1935        /* update start time */
1936        dt = SeedGetSampleDist( hdr );
1937        tc_nadd( ctime, (float)smp_written*dt, ctime, status );
1938
1939} /* end of SeedEncodeSteim1 */
1940
1941
1942
1943/*---------------------------------------------------------------------*/
1944
1945
1946
1947void SeedEncodeSteim1Chan( int fd, INT32 smp[], INT32 *prev_smp, INT32 *idx,
1948        NTIME *ctime, int *reccnt, SeedDataHeaderT *seedhdr, SeedSbyteT *wrk,
1949        int wrklth, BOOLEAN complete, STATUS *status )
1950
1951/* Encodes sample array smp to SEED output file fd (UNIX file descriptor).
1952 * If complete is set to TRUE the last (probably not completely used)
1953 * record is written to the file, otherwise the samples of the
1954 * last record remain in the sample array.
1955 *
1956 * This is the same routine as SeedEncodeSteim1Chan except two additional
1957 * parameters reccnt and seedhdr.
1958 *
1959 * parameters of routine
1960 * int        fd;            input; UNIX file descr of output file
1961 * INT32      smp[];         modify; sample array to encode
1962 * INT32      *prev_smp;     modify; last sample before smp[0]
1963 * INT32      *idx;          modify; length of sample array
1964 * NTIME      *ctime;        modify; input: start time, output: new start time
1965 * int        *reccnt;       modify; record counter
1966 * SeedDataHeaderT *seedhdr; modify; SEED data header
1967 * SeedSbyteT *wrk;          scratch; work space for encoding
1968 * int        wrklth;        input; length of work space in records
1969 * BOOLEAN    complete;      input; finish up all records (-> *idx == 0)
1970 * STATUS     *status;       output; return status
1971 */
1972{
1973        /* local variables */
1974        int      recs_used;              /* number of records used */
1975        SeedDataHeaderT *hdr;            /* SEED data header */
1976        int      i;                      /* counter */
1977        char     str[BC_SHORTSTRLTH+1];  /* scratch string */
1978        int      write_ret;              /* write return value */
1979        int      smp_written;            /* total number of samples written to file*/
1980        float    dt;                     /* sample distance */
1981
1982        /* executable code */
1983
1984        /* put start time to header prototype */
1985        SeedNtimeToBtime( ctime, &(seedhdr->starttime), status );
1986        if  (Severe(status))  return;
1987
1988        if  (*idx <= 0)  return;
1989
1990        /* encode data */
1991        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)seedhdr,
1992                (UINT32)(*idx), (WORD)(seedv_out_reclth), (INT32 *)wrk, *prev_smp );
1993        if  (recs_used > wrklth)  {
1994                fprintf( stderr,
1995                        "***!!! SeedEncodeSteim1: record array exceeded -> abort !!!***\n" );
1996                exit( 1 );
1997        } /*endif*/
1998
1999        /* if last record not to be written, keep it in smp-buffer */
2000        if  (complete)  {
2001                *prev_smp = (*idx > 0) ? smp[(*idx)-1] : 0;
2002                *idx = 0;
2003        } else {
2004                if  (recs_used == 1)  {
2005                        /* printf( "*** SeedEncodeSteim1: only 1 record, no flush\n" ); */
2006                        return;
2007                } /*endif*/
2008                hdr = (SeedDataHeaderT *)(wrk + (recs_used-1)*seedv_out_reclth);
2009                *prev_smp = smp[(*idx)-hdr->no_of_samples-1];
2010                memcpy( (char *)smp, (char *)(smp+(*idx)-(int)(hdr->no_of_samples)),
2011                        (int)(hdr->no_of_samples)*sizeof(INT32) );
2012                *idx = hdr->no_of_samples;
2013                recs_used--;
2014        } /*endif*/
2015
2016        /* write records to file */
2017        smp_written = 0;
2018        for  (i=0; i<recs_used; i++)  {
2019                hdr = (SeedDataHeaderT *)(wrk+i*seedv_out_reclth);
2020                sprintf( str, "%06d", *(reccnt)++ );
2021                strncpy( (char *)hdr, str, 6 );
2022                hdr->Reserved_bytes_A = ' ';
2023#               ifdef cBc_OS_LINUX
2024                SeedStoreReclth( hdr, seedv_out_reclth );
2025                SeedSwapHeader( hdr );
2026                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
2027#               endif
2028                write_ret = (int)write( fd, (char *)hdr, seedv_out_reclth );
2029#               ifdef cBc_OS_LINUX
2030                /* swap it back otherwise not readable any more */
2031                SeedSwapHeader( hdr );
2032                SeedSwapLinuxRecord( (SeedSbyteT *)hdr, seedv_out_reclth );
2033#               endif
2034                if  (write_ret != seedv_out_reclth)  {
2035                        *status = SeedERR_SEEDWRITE;
2036                        return;
2037                } /*endif*/
2038                smp_written += hdr->no_of_samples;
2039        } /*endfor*/
2040
2041        /* update start time */
2042        dt = SeedGetSampleDist( hdr );
2043        tc_nadd( ctime, (float)smp_written*dt, ctime, status );
2044
2045} /* end of SeedEncodeSteim1Chan */
2046
2047
2048
2049/*---------------------------------------------------------------------*/
2050
2051
2052
2053void SeedSetHeaderPrototype( SeedDataHeaderT *hdr )
2054
2055/* copies data header to global variables
2056 *
2057 * parameters of routine
2058 * SeedDataHeaderT *hdr;        input; data header prototype
2059 */
2060{
2061        /* executable code */
2062
2063        seedv_hdr_proto = *hdr;
2064
2065} /* end of SeedSetHeaderPrototype */
2066
2067
2068
2069/*---------------------------------------------------------------------*/
2070
2071
2072
2073void SeedRecordTime( SeedSbyteT *rec, NTIME *start, NTIME *end,
2074        STATUS *status )
2075
2076/* Returns start and end time of SEED record
2077 *
2078 * parameters of routine
2079 * SeedSbyteT *rec;           input; SEED record
2080 * NTIME      *start;         output; start time of record
2081 * NTIME      *end;           output; end time of record
2082 * STATUS     *status;        output; return status
2083 */
2084{
2085        /* local variables */
2086        SeedDataHeaderT *hdr;    /* pointer to data header */
2087        float    dt;            /* sample distance in sec */
2088
2089        /* executable code */
2090
2091        hdr = (SeedDataHeaderT *)rec;
2092
2093        SeedBtimeToNtime( &(hdr->starttime), start, status );
2094        if  (Severe(status))  return;
2095        dt = SeedGetSampleDist( hdr );
2096        tc_nadd( start, dt*(float)(hdr->no_of_samples), end, status );
2097        if  (Severe(status))  return;
2098
2099        if  (seedv_use_timecorr && (hdr->timecorr != 0)
2100                && (((int)(hdr->activity) & Seed_F_ACT_TIMECORRAPP) == 0))  {
2101                tc_nadd( start, (float)(hdr->timecorr)/TIMECORRUNIT, start, status );
2102                tc_nadd( end, (float)(hdr->timecorr)/TIMECORRUNIT, end, status );
2103        } /*endif*/
2104
2105} /* end of SeedRecordTime */
2106
2107
2108
2109/*---------------------------------------------------------------------*/
2110
2111
2112
2113/* #ifdef XXX */
2114
2115#define BUFLTH 4096
2116/* should be enough for decoding one record */
2117
2118#define FREE_AND_RETURN         sy_deallocmem( smp ); \
2119                                                                        sy_deallocmem( buf ); \
2120                                                                        sy_deallocmem( encode ); \
2121                                                                        close( out ); \
2122                                                                        return
2123/* on failure free all memory */
2124
2125
2126
2127
2128void SeedCopy( int chan, char sfdfile[], char fname[], char stream[],
2129        char req_begin[], char req_end[], char act_begin[], char act_end[],
2130        STATUS *status )
2131
2132/* Copies SEED stream to SEED file
2133 *
2134 * parameters of routine
2135 * int        chan;           input; channel to be used
2136 * char       sfdfile[];      input; name of sfd-file for input data
2137 * char       fname[];        input; name of output file
2138 * char       stream[];       input; stream string
2139 * char       req_begin[];    input; requested start time
2140 * char       req_end[];      input; requested end time
2141 * char       act_begin[];    output; actual start time
2142 * char       act_end[];      output; actual end time
2143 * char       *status;        output; return status
2144 */
2145{
2146        /* local variables */
2147        NTIME    rec_start;        /* record start time */
2148        NTIME    rec_end;          /* record end time */
2149        NTIME    n_end;            /* request end time */
2150        INT32    *smp;             /* pointer to sample array */
2151        INT32    idx;              /* sample index */
2152        INT32    *buf;             /* one record buffer */
2153        INT32    buflth;           /* length of buffer */
2154        SeedSbyteT *encode;        /* encode buffer */
2155        int      encode_lth;       /* length of encode buffer in records */
2156        float    tdiff;            /* time difference */
2157        float    dt;               /* sample distance in sec */
2158        int      out;              /* UNIX file descriptor of output file */
2159        float    rec_span;         /* time span of record */
2160        int      i;                /* counter */
2161        BOOLEAN  quit;             /* quit loop */
2162        INT32    smp_written;      /* number of samples written */
2163        NTIME    ntime;            /* scratch time */
2164        BOOLEAN  hdr_swapped;      /* header was swapped */
2165
2166        /* executable code */
2167
2168        /* allocate memory */
2169        smp = (INT32 *)sy_allocmem( seedv_setup.copy_buf_lth, (int)sizeof(INT32),
2170                status );
2171        if  (Severe(status))  return;
2172        buf = (INT32 *)sy_allocmem( BUFLTH, (int)sizeof(INT32), status );
2173        if  (Severe(status))  {
2174                sy_deallocmem( smp );
2175                return;
2176        } /*endif*/
2177        /* encode buffer approximately of equal size as sample buffer 'smp'. */
2178        /* In the worst case this is not enough, but it is very unlikely.    */
2179        encode_lth = (int)(seedv_setup.copy_buf_lth*(int)sizeof(INT32)
2180                / seedv_out_reclth + 1);
2181        encode = (SeedSbyteT *)sy_allocmem( encode_lth, seedv_out_reclth,
2182                status );
2183        if  (Severe(status))  {
2184                sy_deallocmem( smp );
2185                sy_deallocmem( buf );
2186                return;
2187        } /*endif*/
2188
2189        /* open output file */
2190        out = open( fname, O_WRONLY|O_CREAT|O_TRUNC, 0x1ff );
2191        if  (out < 0)  {
2192                *status = SeedERR_OPENOUTPUT;
2193                err_setcontext( " ## file " );
2194                err_setcontext( fname );
2195                sy_deallocmem( smp );
2196                sy_deallocmem( buf );
2197                sy_deallocmem( encode );
2198        } /*endif*/
2199
2200        /* position input file to requested time */
2201        SeedSearchPosition( chan, sfdfile, stream, req_begin, act_begin, status );
2202        if  (Severe(status))  {FREE_AND_RETURN;}
2203        /* check if there are any data in this time window */
2204        if  (tc_tdiff(act_begin,req_end,status) >= 0.0)  {
2205                *status = SeedERR_TIMEGAP;
2206                err_setcontext( " ## no data in requested time window" );
2207                FREE_AND_RETURN;
2208        } /*endif*/
2209        /* initialize values for loop */
2210        tc_t2n( act_begin, &rec_end, status );
2211        if  (Severe(status))  {FREE_AND_RETURN;}
2212        tc_t2n( req_end, &n_end, status );
2213        if  (Severe(status))  {FREE_AND_RETURN;}
2214        SeedNtimeToBtime( &rec_end, &seedv_hdr_proto.starttime, status );
2215        if  (Severe(status))  {FREE_AND_RETURN;}
2216        /* !!! set record number !!! */
2217        /* !!! apply time correction !!! */
2218       
2219        idx = 0;
2220        quit = FALSE;
2221
2222        do  {
2223
2224                /* decode next record */
2225                SeedReadNextRecord( chan, (SeedSbyteT *)seedv_rec, &hdr_swapped, status );
2226                if  (Severe(status))  {FREE_AND_RETURN;}
2227                SeedBtimeToNtime( &(seedv_rec->starttime), &rec_start, status );
2228                if  (Severe(status))  {FREE_AND_RETURN;}
2229                SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, !hdr_swapped,
2230                        BUFLTH, buf, &buflth );
2231                if  (buflth != (INT32)(seedv_rec->no_of_samples))  {
2232                        fprintf( stderr, "*** inconsistency in sample length: should be %ld, is %ld\n",
2233                                (INT32)(seedv_rec->no_of_samples), buflth );
2234                } /*endif*/
2235                dt = SeedGetSampleDist( seedv_rec );
2236                /* if decoded values do not fit into smp-array, write it out */
2237                if  (idx+buflth > seedv_setup.copy_buf_lth)  {
2238                        SeedBtimeToNtime( &seedv_hdr_proto.starttime, &ntime, status );
2239                        if  (Severe(status))  {FREE_AND_RETURN;}
2240                        smp_written = idx;
2241                        SeedEncodeSteim1( out, smp, 0, &idx, &ntime, encode, encode_lth,
2242                                FALSE, status );
2243                        if  (Severe(status))  {FREE_AND_RETURN;}
2244                        smp_written -= idx;
2245                        /* tc_nadd( &ntime, (float)smp_written*dt, &ntime, status ); */
2246                        /* if  (Severe(status))  {FREE_AND_RETURN;} */
2247                        /* SeedNtimeToBtime( &ntime, &seedv_hdr_proto.starttime, status ); */
2248                        /* if  (Severe(status))  {FREE_AND_RETURN;} */
2249                } /*endif*/
2250                /* now check for time gap */
2251                rec_span = dt * (float)(seedv_rec->no_of_samples);
2252                tdiff = tc_ndiff( &rec_start, &rec_end, status );
2253                if  (Severe(status))  {FREE_AND_RETURN;}
2254                /* if there is a time gap, flush smp-buffer and start new record */
2255                if  (Abs(tdiff) > dt)  {
2256                        printf( "! time gap\n" );
2257                        SeedEncodeSteim1( out, smp, 0, &idx, &ntime, encode, encode_lth, TRUE,
2258                                status );
2259                        if  (Severe(status))  {FREE_AND_RETURN;}
2260                        seedv_hdr_proto.starttime = seedv_rec->starttime;
2261                } /*endif*/
2262                /* compute end time for this record, used in next loop */
2263                tc_nadd( &rec_start, rec_span, &rec_end, status );
2264                if  (Severe(status))  {FREE_AND_RETURN;}
2265                /* check whether requested end time is reached */
2266                tdiff = tc_ndiff( &rec_end, &n_end, status );
2267                if  (tdiff >= 0.0)  {
2268                        /* if end time reached decrease buflth ... */
2269                        tdiff = tc_ndiff( &n_end, &rec_start, status );
2270                        if  (Severe(status))  {FREE_AND_RETURN;}
2271                        buflth = Nint( tdiff / dt );
2272                        /* ... and compute actual end time */
2273                        tc_nadd( &rec_start, dt*(float)buflth, &n_end, status );
2274                        if  (Severe(status))  {FREE_AND_RETURN;}
2275                        tc_n2t( &n_end, act_end, status );
2276                        if  (Severe(status))  {FREE_AND_RETURN;}
2277                        quit = TRUE;
2278                } /*endif*/
2279                /* now add decoded values to smp-array */
2280                for  (i=0; i<buflth; i++)
2281                        smp[idx++] = buf[i];
2282                /* if end time found, flush buffer and exit loop */
2283                if  (quit)
2284                        SeedEncodeSteim1( out, smp, 0, &idx, &ntime, encode, encode_lth, TRUE,
2285                                status );
2286
2287        }  while (!quit);
2288
2289        FREE_AND_RETURN;
2290
2291} /* end of SeedCopy */
2292
2293
2294#undef FREE_AND_RETURN
2295
2296/* #endif */
2297
2298/*---------------------------------------------------------------------*/
2299
2300
2301
2302#define DO_ABORT \
2303        *status = SeedERR_SFD_READ; \
2304        err_setcontext( " ## string " ); err_setcontext( line-1 ); \
2305        return;
2306
2307
2308
2309
2310void SeedParseSfdLine( char line[], SeedFileDescrT *fd, STATUS *status )
2311
2312/* parses line of SFD file.  Returns structure elements 'stream',
2313 * 't_start', 't_end', 'name', 'recno' and 'calib'.
2314 *
2315 * parameters of routine
2316 * char       line[];       input; SFD line
2317 * SeedFileDescrT *fd;      output; SEED file descriptor
2318 * STATUS     *status;      output; return status
2319 */
2320{
2321        /* local variables */
2322
2323        /* executable code */
2324
2325        fd->t_start[0] = '\0';
2326        fd->t_end[0] = '\0';
2327        fd->name[0] = '\0';
2328        fd->stream[0] = '\0';
2329        fd->recno = 0;
2330        fd->reclth = DEFAULT_RECLTH;
2331        fd->byteoff = 0;
2332        fd->calib = 0.0;
2333        fd->dataflags = 0;
2334        fd->swap_hdr = FALSE;
2335        fd->pri = 0;
2336        fd->dataformat = Seed_C_FORMAT_MSEED;
2337        strcpy( fd->addinf, Seed_C_EmptyAddinfStr );
2338
2339        FOREVER  {
2340
2341                if  (*line == '>')  line++;
2342                line = strchr( line, '>' );
2343                if  (line == NULL)  break;
2344                switch  (*(line-1))  {
2345                case Seed_C_SfdTStart:
2346                        if  (sscanf(line+1,"%s",fd->t_start) != 1)  { DO_ABORT }
2347                        break;
2348                case Seed_C_SfdTEnd:
2349                        if  (sscanf(line+1,"%s",fd->t_end) != 1)  { DO_ABORT }
2350                        break;
2351                case Seed_C_SfdName:
2352                        if  (sscanf(line+1,"%s",fd->name) != 1)  { DO_ABORT }
2353                        break;
2354                case Seed_C_SfdStream:
2355                        if  (sscanf(line+1,"%s",fd->stream) != 1)  { DO_ABORT }
2356                        break;
2357                case Seed_C_SfdRecno:
2358                        if  (sscanf(line+1,"%d",&(fd->recno)) != 1)  { DO_ABORT }
2359                        break;
2360                case Seed_C_SfdReclth:
2361                        if  (sscanf(line+1,"%d",&(fd->reclth)) != 1)  { DO_ABORT }
2362                        break;
2363                case Seed_C_SfdOffset:
2364                        if  (sscanf(line+1,"%d",&(fd->byteoff)) != 1)  { DO_ABORT }
2365                        break;
2366                case Seed_C_SfdCalib:
2367                        if  (sscanf(line+1,"%f",&(fd->calib)) != 1)  { DO_ABORT }
2368                        break;
2369                case Seed_C_SfdSwapH:
2370                        if  (sscanf(line+1,"%d",&(fd->swap_hdr)) != 1)  { DO_ABORT }
2371                        if  (seedv_invert_swap_hdr)  fd->swap_hdr = ! fd->swap_hdr;
2372                        break;
2373                case Seed_C_SfdAddinf:
2374                        strncpy( fd->addinf, line+1, Seed_C_AddinfLth);
2375                        fd->addinf[Seed_C_AddinfLth] = '\0';
2376                        ut_uncap( fd->addinf );
2377                        break;
2378                } /*endswitch*/
2379
2380        } /*endfor*/
2381
2382} /* end of SeedParseSfdLine */
2383
2384
2385
2386#undef DO_ABORT
2387
2388
2389
2390/*---------------------------------------------------------------------*/
2391
2392
2393
2394void SeedReadStream( int chan, char sfdfile[], char stream_str[],
2395        BOOLEAN swap, char req_start[], float seclth, INT32 **ldat,
2396        INT32 *smplth, char act_start[], float *dt, float *calib,
2397        int *flags, STATUS *status )
2398
2399/* Reads sample data from SEED stream.  The memory for the sample
2400 * data is allocated by the routine.  The channel number is chosen
2401 * by the caller of the routine.  It is legal to use always channel
2402 * number 0 but it is faster to use a separate channel number for
2403 * each stream used if the streams are read repeatedly.
2404 *
2405 * parameters of routine
2406 * int        chan;         input; channel number (0..Seed_C_MAXCHAN-1)
2407 * char       sfdfile[];    input; name of sfd file to use
2408 * char       stream_str[]; input; stream string (like "bfo-vbb-z")
2409 * BOOLEAN    swap;         input; swap bytes on file
2410 * char       req_start[];  input; requested start time
2411 * float      seclth;       input; number of seconds to be read
2412 * INT32      **ldat;       output; sample array read
2413 * INT32      *smplth;      output; number of samples read
2414 * char       act_start[];  output; actual start time
2415 * float      *dt;          output; sample distance in sec
2416 * float      *calib;       output; calibration constant
2417 * int        *flags;       output; data flags found
2418 * STATUS     *status;      output; return status
2419 */
2420{
2421        /* local variables */
2422        SeedFileDescrT *fd;   /* pointer to SEED file descriptor */
2423        INT32    getlth;      /* number of samples to read */
2424        INT32    maxrecsmp;   /* maximum number of samples per record */
2425        INT32    actrecsmp;   /* actual number of samples in record */
2426        INT32    *recsmp;     /* pointer to samples of record */
2427        INT32    *lsrc, *ldst;/* moving pointers */
2428        NTIME    recstart;    /* record start time */
2429        NTIME    recend;      /* record end time */
2430        NTIME    expectime;   /* expected time */
2431        float    tdiff;       /* time gap in sec */
2432        INT32    padcnt;      /* counter for zero padding */
2433        char     str[BC_TIMELTH+1];  /* scratch string for time output */
2434        BOOLEAN  swap_data;   /* swap data */
2435        int      i;           /* counter */
2436        char     recmsg[cBcLineLth+1];  /* output string */
2437
2438        /* executable code */
2439
2440        /* check channel number */
2441        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  {
2442                *status = SeedERR_CHAN_OOR;
2443                return;
2444        } /*endif*/
2445        fd = seedv_fd + chan;
2446
2447        /* find requested position */
2448        tdiff = 0.0;
2449        SeedSearchPosition( chan, sfdfile, stream_str, req_start,
2450                act_start, status );
2451        if  (*status == SeedERR_NEXTTIMEPOS)  {
2452                *status = BC_NOERROR;
2453                tdiff = tc_tdiff( act_start, req_start, status );
2454                if  (Severe(status))  return;
2455                if  (tdiff >= seclth)  {*status = SeedERR_DATA_UNAVAIL; return;}
2456                fprintf( stderr,
2457                        "SeedReadStream: time %s not found, start at %s\n",
2458                        req_start, act_start );
2459        } /*endif*/
2460        if  (Severe(status))  return;
2461
2462        maxrecsmp = MAX_SMP_PER_REC;
2463        *smplth = 0;
2464        *ldat = NULL;
2465        recsmp = NULL;
2466        *dt = 0.0;
2467        expectime.year = 0;
2468        /* reset decode routine */
2469        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
2470
2471        FOREVER  {
2472
2473                /* read next record */
2474                SeedReadNextRecord( chan, (SeedSbyteT *)seedv_rec, &swap_data, status );
2475                if  (swap)  swap_data = !swap_data;
2476                if  (*status == SeedERR_NEXTTIMEPOS)  *status = BC_NOERROR;
2477                if  (Severe(status))  return;
2478
2479                /* decode SEED record and select samples */
2480                /* ------------------------------------- */
2481                if  (*ldat == NULL)  {
2482
2483                        /* this is for first loop only */
2484                        /* --------------------------- */
2485                        *calib = fd->calib;
2486                        *flags = fd->dataflags;
2487                        if  (seedv_rec->quality != 0)  {
2488                                if  (GpGetInt(cGpI_debug_level > 0))
2489                                        printf( "SHM-dbg1: SEED quality flags: 0x%x\n",
2490                                                (int)seedv_rec->quality );
2491                                (*flags) |= seedv_rec->quality;
2492                        } /*endif*/
2493                        *dt = SeedGetSampleDist( seedv_rec );
2494                        getlth = Nint32( seclth / *dt );
2495                        if  (getlth <= 0)  {*status = SeedERR_ZEROLTH; return;}
2496                        *ldat = (INT32 *)sy_allocmem( getlth, (int)sizeof(INT32), status );
2497                        if  (Severe(status))  return;
2498                        ldst = *ldat;
2499                        recsmp = (INT32 *)sy_allocmem( maxrecsmp, (int)sizeof(INT32), status );
2500                        if  (Severe(status))  {sy_deallocmem(*ldat); return;}
2501                        /* if time gap at beginning, pad zeroes */
2502                        if  (tdiff > 0.0)  {
2503                                /* pad with zeroes and adjust start time */
2504                                padcnt = Nint32( tdiff / (*dt) );
2505                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
2506                                        seedv_rec->seqno, act_start );
2507                                fprintf( stderr, "   gap %5.3f sec, start with %ld zeroes\n",
2508                                        tdiff, padcnt );
2509                                tc_tadd( act_start, -(*dt)*(float)padcnt, act_start, status );
2510                                if  (Severe(status))  *status = BC_NOERROR; /* ok, not elegant */
2511                                while  (padcnt-- > 0)  {
2512                                        ldst[(*smplth)++] = 0;
2513                                        if  (*smplth == getlth)  {
2514                                                sy_deallocmem( recsmp );
2515                                                fprintf( stderr,
2516                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
2517                                                strcpy( act_start, req_start );
2518                                                return;
2519                                        } /*endif*/
2520                                } /*endwhile*/
2521                        } /*endif*/
2522                        SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, swap_data,
2523                                maxrecsmp, recsmp, &actrecsmp );
2524                        if  (actrecsmp != seedv_rec->no_of_samples)  {
2525                                fprintf( stderr,
2526                                        "*** seed record samples: expected %d, actual: %d\n",
2527                                        seedv_rec->no_of_samples, actrecsmp );
2528                                if  (seedv_decerr_abort)  {
2529                                        sy_deallocmem( *ldat );
2530                                        *ldat = NULL;
2531                                        sy_deallocmem( recsmp );
2532                                        *status = SeedERR_DECODE_ERR;
2533                                        return;
2534                                } else {
2535                                        INT32    zeronum;       /* number of sample to zero */
2536                                        zeronum = seedv_rec->no_of_samples;
2537                                        if  (zeronum > maxrecsmp)  zeronum = maxrecsmp;
2538                                        fprintf( stderr, "   zero %d samples and continue\n", zeronum );
2539                                        for  (i=0; i<zeronum; i++)
2540                                                recsmp[i] = 0;
2541                                } /*endif*/
2542#                               ifdef XXX
2543                                /* excluded this on 1-Jul-98, K.S. */
2544                                fd->sample = 0;
2545                                fprintf( stderr,
2546                                        "   read position within zeroed record set to zero\n" );
2547#                               endif
2548                                actrecsmp = seedv_rec->no_of_samples;
2549                        } /*endif*/
2550                        lsrc = recsmp + fd->sample;
2551                        actrecsmp -= fd->sample;
2552                        if  (actrecsmp < 0)  {
2553                                sy_deallocmem( *ldat );
2554                                *ldat = NULL;
2555                                sy_deallocmem( recsmp );
2556                                *status = SeedERR_BUG;
2557                                fprintf( stderr, "*** SeedReadStream: bug (1) [sample: %d] ***\n",
2558                                        fd->sample );
2559                                return;
2560                        } /*endif*/
2561                        SeedRecordTime( (SeedSbyteT *)seedv_rec, &recstart, &expectime,
2562                                status );
2563                        if  (Severe(status))  return;
2564
2565                } else {
2566
2567                        /* this is for all other loops */
2568                        /* --------------------------- */
2569
2570                        /* collect data quality flags */
2571                        if  (seedv_rec->quality != 0)  {
2572                                if  (GpGetInt(cGpI_debug_level > 0))
2573                                        printf( "SHM-dbg1: SEED quality flags: %x\n",
2574                                                (int)seedv_rec->quality );
2575                                (*flags) |= seedv_rec->quality;
2576                        } /*endif*/
2577
2578                        /* decode record */
2579                        SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, swap_data,
2580                                maxrecsmp, recsmp, &actrecsmp );
2581                        if  (actrecsmp != seedv_rec->no_of_samples)  {
2582                                fprintf( stderr,
2583                                        "*** seed record samples: expected %d, actual: %d\n",
2584                                        seedv_rec->no_of_samples, actrecsmp );
2585                                if  (seedv_decerr_abort)  {
2586                                        sy_deallocmem( *ldat );
2587                                        *ldat = NULL;
2588                                        sy_deallocmem( recsmp );
2589                                        *status = SeedERR_DECODE_ERR;
2590                                        return;
2591                                } else {
2592                                        INT32    zeronum;       /* number of sample to zero */
2593                                        zeronum = seedv_rec->no_of_samples;
2594                                        if  (zeronum > maxrecsmp)  zeronum = maxrecsmp;
2595                                        fprintf( stderr, "   zero %d samples and continue\n", zeronum );
2596                                        for  (i=0; i<zeronum; i++)
2597                                                recsmp[i] = 0;
2598                                } /*endif*/
2599                                actrecsmp = seedv_rec->no_of_samples;
2600                        } /*endif*/
2601                        lsrc = recsmp;
2602
2603                        /* check for time gaps, pad with zeroes */
2604                        SeedRecordTime( (SeedSbyteT *)seedv_rec, &recstart, &recend, status );
2605                        if  (Severe(status))  return;
2606                        tdiff = tc_ndiff( &recstart, &expectime, status );
2607                        if  (Severe(status))  return;
2608                        if  (tdiff <= -(*dt))  {
2609                                /* double data */
2610                                padcnt = Nint32( -tdiff / (*dt) );
2611                                tc_n2t( &recstart, str, status );
2612                                strncpy( recmsg, seedv_rec->seqno, 6 );
2613                                recmsg[6] = '\0';
2614                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
2615                                        recmsg, str );
2616                                fprintf( stderr, "   double data, %ld samples skipped\n",
2617                                        padcnt );
2618                                if  (padcnt > (INT32)(seedv_rec->no_of_samples))  {
2619                                        /*
2620                                        *status = SeedERR_DOUBLEDATA;
2621                                        sy_deallocmem( recsmp );
2622                                        return;
2623                                        */
2624                                        fprintf( stderr, "double data; complete record skipped\n" );
2625                                        continue;
2626                                } /*endif*/
2627                                /* skip samples */
2628                                lsrc += padcnt;
2629                                actrecsmp -= padcnt;
2630                        } else if  (tdiff >= (*dt))  {
2631                                /* time gap */
2632                                padcnt = Nint32( tdiff / (*dt) );
2633                                tc_n2t( &recstart, str, status );
2634                                strncpy( recmsg, seedv_rec->seqno, 6 );
2635                                recmsg[6] = '\0';
2636                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
2637                                        recmsg, str );
2638                                fprintf( stderr,
2639                                        "   gap %5.3f sec, padding %ld zeroes at sample %ld\n",
2640                                        tdiff, padcnt, *smplth );
2641                                /* pad zeroes */
2642                                while  (padcnt-- > 0)  {
2643                                        ldst[(*smplth)++] = 0;
2644                                        if  (*smplth == getlth)  {
2645                                                sy_deallocmem( recsmp );
2646                                                fprintf( stderr,
2647                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
2648                                                return;
2649                                        } /*endif*/
2650                                } /*endwhile*/
2651                        } /*endif*/
2652                        expectime = recend;
2653
2654                } /*endif*/
2655
2656                /* copy samples to output array */
2657                while  (actrecsmp-- > 0)  {
2658                        ldst[(*smplth)++] = *lsrc++;
2659                        if  (*smplth == getlth)  {  /* finished ! */
2660                                sy_deallocmem( recsmp );
2661                                return;
2662                        } /*endif*/
2663                } /*endwhile*/
2664
2665        } /*endfor*/
2666
2667} /* end of SeedReadStream */
2668
2669
2670
2671/*---------------------------------------------------------------------*/
2672
2673
2674
2675void SeedReadStreamReal( int chan, char sfdfile[], char stream_str[],
2676        BOOLEAN swap, char req_start[], float seclth, float **fdat,
2677        INT32 *smplth, char act_start[], float *dt, float *calib,
2678        int *flags, STATUS *status )
2679
2680/* Same as SeedReadStream except that a float array is returned
2681 *
2682 * parameters of routine
2683 * see SeedReadStream above
2684 */
2685{
2686        /* local variables */
2687        INT32    *lptr;         /* INT32 pointer to data array */
2688        INT32    *lp;           /* moving pointer */
2689        float    *fp;           /* moving pointer */
2690        INT32    i;             /* counter */
2691
2692        /* executable code */
2693
2694        *fdat = NULL;
2695
2696        SeedReadStream( chan, sfdfile, stream_str, swap, req_start,
2697                seclth, &lptr, smplth, act_start, dt, calib, flags, status );
2698        if  (Severe(status))  return;
2699
2700        if  (sizeof(INT32) != sizeof(float))  {
2701                printf( "--> sizeof(float) != sizeof(INT32)\n" );
2702                *status = 1;
2703                sy_deallocmem( lptr );
2704                return;
2705        } /*endif*/
2706
2707        lp = lptr;
2708        fp = *fdat = (float *)lptr;
2709        for  (i=0; i<(*smplth); i++)
2710                *fp++ = (float)(*lp++) * (*calib);
2711
2712} /* end of SeedReadStreamReal */
2713
2714
2715
2716/*---------------------------------------------------------------------*/
2717
2718
2719
2720float SeedFindStreamCalibration( char stream[], char stime[], STATUS *status )
2721
2722/* returns calibration value for counts for given stream 'stream' at time
2723 * 'stime'.
2724 *
2725 * parameters of routine
2726 * char           stream[];     input; stream string
2727 * char           stime[];      input; time
2728 * STATUS         *status;      output; return status
2729 *                              returns calibration or 0.0
2730 */
2731{
2732        /* local variables */
2733        char     calfile[BC_FILELTH+1];    /* name of calibration file */
2734        char     *eptr;                    /* pointer to environment variable */
2735        FILE     *fp;                      /* pointer to input file */
2736        char     line[BC_LINELTH+1];       /* current line of input file */
2737        char     v_start[BC_LINELTH+1];    /* start of valid time */
2738        char     v_end[BC_LINELTH+1];      /* end of valid time */
2739        float    lcalib;                   /* current value of calibration */
2740        int      cmpidx;                   /* position of component */
2741        int      filecnt;                  /* file counter */
2742        char     *sf;                      /* pointer to sensitivity file name */
2743
2744        /* executable code */
2745
2746        if  (strcmp(GpGetStringElem(cGpL_sensitivity_file,0),"old-style") == 0)  {
2747
2748                /* this is the old-style part, dealing with many, many
2749                 * seedcalib_... files in $SEED_INPUTS
2750                 */
2751
2752                /* build filename */
2753                *calfile = '\0';
2754                eptr = getenv( "SEED_INPUTS" );
2755                if  (eptr != NULL)  {
2756                        if  (strlen(eptr)+strlen(stream)+11 > BC_FILELTH)  {
2757                                *status = SeedERR_STROVFL;
2758                                return 0.0;
2759                        } /*endif*/
2760                        strcpy( calfile, eptr );
2761                        strcat( calfile, "/" );
2762                } /*endif*/
2763                strcat( calfile, "seedcalib_" );
2764                strcat( calfile, stream );
2765
2766                /* open file */
2767                fp = sy_fopen( calfile, "r" );
2768                if  (fp == NULL)  {
2769                        *status = SeedERR_NOCALIB;
2770                        fprintf( stderr, "*Seed: no calibration for %s, set to 1.0\n", stream );
2771                        return 1.0;
2772                } /*endif*/
2773
2774                while  (fgets(line,BC_LINELTH,fp) != NULL)  {
2775                        if  (*line == '!' || *line == '\n')  continue;
2776                        if  (sscanf(line,"%s %s %f",v_start,v_end,&lcalib) != 3)  {
2777                                fprintf( stderr, "*Seed: format error in calibration file %s\n", stream );
2778                                continue;
2779                        } /*endif*/
2780                        if  (tc_tdiff(stime,v_start,status) < 0.0)  continue;
2781                        if  (Severe(status))  return 0.0;
2782                        if  (tc_tdiff(stime,v_end,status) > 0.0)  continue;
2783                        if  (Severe(status))  return 0.0;
2784                        sy_fclose( fp );
2785                        return lcalib;
2786                } /*endwhile*/
2787
2788                sy_fclose( fp );
2789                *status = SeedERR_NOCALIB;
2790                fprintf( stderr, "*Seed: no valid calibration for %s %s, set to 1.0\n",
2791                        stream, stime );
2792                return 1.0;
2793
2794        } else {
2795
2796                /* this is the new version introduced 20-May-2006, all information
2797                 * is in a single file, by default in $SH_INPUTS/sensitivities.txt
2798                 */
2799
2800                /* loop all sensitivity files given */
2801                for  (filecnt=0;;filecnt++)  {
2802
2803                        /* get next sensitivity file name */
2804                        sf = GpGetStringElem( cGpL_sensitivity_file, filecnt );
2805                        if  (sf == NULL)  break;
2806
2807                        /* check for 'default' value, happens if GpReadParfile is not called */
2808                        if  (strcmp(sf,"default") == 0)  {
2809                                *calfile = '\0';
2810                                eptr = getenv( "SH_INPUTS" );
2811                                if  (eptr != NULL)  {
2812                                        if  (strlen(eptr)+18 > BC_FILELTH)  {
2813                                                *status = SeedERR_STROVFL;
2814                                                return 0.0;
2815                                        } /*endif*/
2816                                        strcpy( calfile, eptr );
2817                                        strcat( calfile, "/" );
2818                                } /*endif*/
2819                                strcat( calfile, "sensitivities.txt" );
2820                                sf = calfile;
2821                        } /*endif*/
2822
2823                        /* open it */
2824                        if  (GpGetInt(cGpI_debug_level) > 5)
2825                                printf( "SH-dbg6: open sensitivity file %s\n", sf );
2826                        fp = sy_fopen( sf, "r" );
2827                        if  (fp == NULL)  {
2828                                fprintf( stderr, "*Seed: sensitivity file %s not found\n", sf );
2829                                *status = SeedERR_NOCALIB;
2830                                return 1.0;
2831                        } /*endif*/
2832
2833                        /* wildcard takes stream with '?' as component */
2834                        cmpidx = strlen( stream ) - 1;
2835
2836                        /* read through file */
2837                        while  (fgets(line,cBcLineLth,fp) != NULL)  {
2838                                if  (*line == '!' || *line == '#' || *line == '\n')  continue;
2839                                if  (strncasecmp(line,stream,cmpidx) == 0)  {
2840                                        if  (line[cmpidx] == '?' || line[cmpidx] == stream[cmpidx])  {
2841                                                if  (sscanf(line+cmpidx+2,"%s %s %f",v_start,v_end,&lcalib) != 3)  {
2842                                                        fprintf( stderr, "*Seed: format error in calibration file at %s\n",
2843                                                                stream );
2844                                                        continue;
2845                                                } /*endif*/
2846                                                if  (strcmp(v_start,"...") != 0)
2847                                                        if  (tc_tdiff(stime,v_start,status) < 0.0)  continue;
2848                                                if  (Severe(status))  {
2849                                                        sy_fclose( fp );
2850                                                        return 0.0;
2851                                                } /*endif*/
2852                                                if  (strcmp(v_end,"...") != 0)
2853                                                        if  (tc_tdiff(stime,v_end,status) > 0.0)  continue;
2854                                                if  (Severe(status))  {
2855                                                        sy_fclose( fp );
2856                                                        return 0.0;
2857                                                } /*endif*/
2858                                                sy_fclose( fp );
2859                                                return lcalib;
2860                                        } /*endif*/
2861                                } /*endif*/
2862                        } /*endif*/
2863
2864                        sy_fclose( fp );
2865
2866                } /*endfor*/
2867
2868                *status = SeedERR_NOCALIB;
2869                fprintf( stderr, "*Seed: no valid calibration for %s %s, set to 1.0\n",
2870                        stream, stime );
2871                return 1.0;
2872
2873        } /*endif*/
2874
2875} /* end of SeedFindStreamCalibration */
2876
2877
2878
2879/*---------------------------------------------------------------------*/
2880
2881
2882
2883void SeedGetTimeSpan( char sfdfile[], char stream[], char start[],
2884        char end[], STATUS *status )
2885
2886/* Returns first and last time of channel 'stream' in sfd-file
2887 *
2888 * parameters of routine
2889 * char       sfdfile[];        input; name of sfd-file
2890 * char       stream[];         input; stream string to be checked
2891 * char       start[];          output; first start time
2892 * char       end[];            output; last end time
2893 * STATUS     *status;          output; return status
2894 */
2895{
2896        /* local variables */
2897        FILE     *sfd;                      /* pointer to sfd-file */
2898        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
2899        SeedFileDescrT dsc;                 /* sfd descriptor */
2900        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
2901
2902        /* executable code */
2903
2904        sfd = sy_fopen( sfdfile, "r" );
2905        if  (sfd == NULL)  {
2906                *status = SeedERR_OPENINPUT;
2907                err_setcontext( " ## file " );
2908                err_setcontext( sfdfile );
2909                return;
2910        } /*endif*/
2911
2912        strcpy( lstream, stream );
2913        ut_uncap( lstream );
2914
2915        /* find requested stream */
2916        *start = *end = '\0';
2917        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
2918                if  (*line == '!')  continue;
2919                SeedParseSfdLine( line, &dsc, status );
2920                if  (strcmp(dsc.stream,lstream) != 0)  continue;
2921                if  (*start == '\0')  {
2922                        strcpy( start, dsc.t_start );
2923                } else {
2924                        if  (tc_tdiff(dsc.t_start,start,status) < 0.0)
2925                                strcpy( start, dsc.t_start );
2926                } /*endif*/
2927                if  (Severe(status))  return;
2928                if  (*end == '\0')  {
2929                        strcpy( end, dsc.t_end );
2930                } else {
2931                        if  (tc_tdiff(dsc.t_end,end,status) > 0.0)
2932                                strcpy( end, dsc.t_end );
2933                } /*endif*/
2934                if  (Severe(status))  return;
2935        } /*endwhile*/
2936
2937        sy_fclose( sfd );
2938
2939} /* end of SeedGetTimeSpan */
2940
2941
2942
2943/*---------------------------------------------------------------------*/
2944
2945
2946
2947BOOLEAN SeedInquireTime( char sfdfile[], char stream[], char start[],
2948        char end[], STATUS *status )
2949
2950/* Checks whether the specified time span from 'start' to 'end' is
2951 * available for channel 'stream' in sfd-file 'sfdfile'
2952 *
2953 * parameters of routine
2954 * char       sfdfile[];        input; name of sfd-file
2955 * char       stream[];         input; stream string
2956 * char       start[];          input; start time
2957 * char       end[];            input; end time
2958 * STATUS     *status;          output; return status
2959 *                              returns TRUE if data are available
2960 */
2961{
2962        /* local variables */
2963        FILE     *sfd;                      /* pointer to sfd-file */
2964        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
2965        SeedFileDescrT dsc;                 /* sfd descriptor */
2966        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
2967        TIME     a_start, a_end;            /* absolute times of inquied span */
2968        TIME     a1, a2;                    /* absolute times of SEED file */
2969
2970        /* executable code */
2971
2972        sfd = sy_fopen( sfdfile, "r" );
2973        if  (sfd == NULL)  {
2974                *status = SeedERR_OPENINPUT;
2975                err_setcontext( " ## file " );
2976                err_setcontext( sfdfile );
2977                return FALSE;
2978        } /*endif*/
2979
2980        strcpy( lstream, stream );
2981        ut_uncap( lstream );
2982
2983        tc_t2a( start, &a_start, status );
2984        if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2985        tc_t2a( end, &a_end, status );
2986        if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2987        if  (tc_adiff(&a_end,&a_start) < 0.0)  {sy_fclose(sfd); return FALSE;}
2988
2989        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
2990                if  (*line == '!')  continue;
2991                SeedParseSfdLine( line, &dsc, status );
2992                if  (strcmp(dsc.stream,lstream) != 0)  continue;
2993                tc_t2a( dsc.t_start, &a1, status );
2994                if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2995                tc_t2a( dsc.t_end, &a2, status );
2996                if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
2997                if  (tc_adiff(&a_start,&a1) < 0.0)  continue;
2998                if  (tc_adiff(&a2,&a_end) < 0.0)  continue;
2999                sy_fclose( sfd );
3000                return TRUE;
3001        } /*endwhile*/
3002
3003        sy_fclose( sfd );
3004
3005        return FALSE;
3006
3007} /* end of SeedInquireTime */
3008
3009
3010
3011/*---------------------------------------------------------------------*/
3012
3013
3014
3015void SeedInquireTimeList( char sfdfile[], char stations[], int itemlth,
3016        int listlth, char chan[], char comp, char start[], char end[],
3017        INT32 *avail, STATUS *status )
3018
3019/* Checks whether the specified time span from 'start' to 'end' is
3020 * available for all stations (stream 'station-chan-comp') in sfd-file
3021 * 'sfdfile'.  'station' is a char string with 'listlth' equidistant
3022 * strings of length 'itemlth'.
3023 *
3024 * parameters of routine
3025 * char       sfdfile[];        input; name of sfd-file
3026 * char       stations[];       input; list of stations
3027 * int        itemlth;          input; chars used for a station name
3028 * int        listlth;          input; length of list (# of stations) (<= 32)
3029 * char       chan[];           input; 2-char channel string
3030 * char       comp;             input; component
3031 * char       start[];          input; start time
3032 * char       end[];            input; end time
3033 * INT32      *avail;           output; station bits
3034 * STATUS     *status;          output; return status
3035 */
3036{
3037        /* local variables */
3038        FILE     *sfd;                      /* pointer to sfd-file */
3039        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
3040        SeedFileDescrT dsc;                 /* sfd descriptor */
3041        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
3042        TIME     a_start, a_end;            /* absolute times of inquied span */
3043        TIME     a1, a2;                    /* absolute times of SEED file */
3044        char     *sptr;                     /* current station name */
3045        int      scnt;                      /* station counter */
3046        char     cmpstr[2];                 /* component */
3047
3048        /* executable code */
3049
3050        sfd = sy_fopen( sfdfile, "r" );
3051        if  (sfd == NULL)  {
3052                *status = SeedERR_OPENINPUT;
3053                err_setcontext( " ## file " );
3054                err_setcontext( sfdfile );
3055                return;
3056        } /*endif*/
3057
3058        tc_t2a( start, &a_start, status );
3059        if  (Severe(status))  {sy_fclose(sfd); return;}
3060        tc_t2a( end, &a_end, status );
3061        if  (Severe(status))  {sy_fclose(sfd); return;}
3062        if  (tc_adiff(&a_end,&a_start) < 0.0)  {sy_fclose(sfd); return;}
3063
3064        cmpstr[0] = comp;
3065        cmpstr[1] = '\0';
3066
3067        *avail = 0;
3068
3069        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
3070
3071                /* get & parse next sfd line */
3072                if  (*line == '!')  continue;
3073                SeedParseSfdLine( line, &dsc, status );
3074
3075                /* check time */
3076                tc_t2a( dsc.t_start, &a1, status );
3077                if  (Severe(status))  {sy_fclose(sfd); return;}
3078                tc_t2a( dsc.t_end, &a2, status );
3079                if  (Severe(status))  {sy_fclose(sfd); return;}
3080                if  (tc_adiff(&a_start,&a1) < 0.0)  continue;
3081                if  (tc_adiff(&a2,&a_end) < 0.0)  continue;
3082
3083                /* now loop all stations */
3084                sptr = stations;
3085                for  (scnt=0; scnt<listlth; scnt++)  {
3086                        if  (*sptr != '-')  {
3087                                /* build stream name */
3088                                strcpy( lstream, sptr );
3089                                        strcat( lstream, "-" );
3090                                strcat( lstream, chan );
3091                                strcat( lstream, "-" );
3092                                strcat( lstream, cmpstr );
3093                                ut_uncap( lstream );
3094                                if  (strcmp(dsc.stream,lstream) == 0)
3095                                        *avail |= (1<<scnt);
3096                        } /*endif*/
3097                        /* increment station pointer */
3098                        sptr += itemlth;
3099                } /*endfor*/
3100
3101        } /*endwhile*/
3102
3103        sy_fclose( sfd );
3104
3105} /* end of SeedInquireTimeList */
3106
3107
3108
3109/*---------------------------------------------------------------------*/
3110
3111
3112
3113BOOLEAN SeedSwapNecessary( SeedDataHeaderT *hdr )
3114
3115/* Checks whether a swap is necessary on data header
3116 *
3117 * parameters of routine
3118 * SeedDataHeaderT *hdr;     input; header to check
3119 *                           returns TRUE if swap must be performed
3120 */
3121{
3122        /* executable code */
3123
3124        return  (hdr->starttime.year < 1950 || hdr->starttime.year > 2030);
3125
3126} /* end of SeedSwapNecessary */
3127
3128
3129
3130/*---------------------------------------------------------------------*/
3131
3132
3133
3134void SeedSwapHeader( SeedDataHeaderT *hdr )
3135
3136/* Swaps words and longwords in header
3137 *
3138 * parameters of routine
3139 * SeedDataHeaderT *hdr;          modify; data header to be swapped
3140 */
3141{
3142        /* local variables */
3143        WORD     v_word;      /* scratch */
3144        UWORD    v_uword;     /* scratch */
3145        INT32    v_long;      /* scratch */
3146        SeedBlockette1000T *b1000;  /* pointer to Blockette 1000 */
3147        UWORD    next_block;   /* next blockette pointer */
3148
3149        /* executable code */
3150
3151        v_uword = hdr->starttime.year;
3152        hdr->starttime.year = (v_uword & 0xff) * 0x100;
3153        hdr->starttime.year += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3154
3155        v_uword = hdr->starttime.day;
3156        hdr->starttime.day = (v_uword & 0xff) * 0x100;
3157        hdr->starttime.day += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3158
3159        v_uword = hdr->starttime.frac_secs;
3160        hdr->starttime.frac_secs = (v_uword & 0xff) * 0x100;
3161        hdr->starttime.frac_secs += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3162
3163        v_uword = hdr->no_of_samples;
3164        hdr->no_of_samples = (v_uword & 0xff) * 0x100;
3165        hdr->no_of_samples += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3166
3167        v_uword = (UWORD)(hdr->smprate_fact);
3168        hdr->smprate_fact = (int)( ((v_uword << 8) & 0xff00) |
3169                ((v_uword >> 8) & 0x00ff) );
3170
3171        v_uword = (UWORD)(hdr->smprate_mult);
3172        hdr->smprate_mult = (int)( ((v_uword << 8) & 0xff00) |
3173                ((v_uword >> 8) & 0x00ff) );
3174
3175        v_long = hdr->timecorr;
3176        hdr->timecorr =  (INT32)(((UINT32)v_long & 0x000000ffL) * (UINT32)0x1000000L);
3177        hdr->timecorr += (INT32)(((UINT32)v_long & 0x0000ff00L) * (UINT32)0x100L);
3178        hdr->timecorr += (INT32)(((UINT32)v_long & 0x00ff0000L) >> (UINT32)8L);
3179        hdr->timecorr += (INT32)(((UINT32)v_long & 0xff000000L) >> (UINT32)24L);
3180
3181        v_uword = hdr->databegin;
3182        hdr->databegin = (v_uword & 0xff) * 0x100;
3183        hdr->databegin += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3184
3185        /* swap pointer to first blockette and store unswapped value */
3186        next_block = 0;
3187        v_uword = hdr->first;
3188        if  (v_uword >= 48 && v_uword < 64)  next_block = v_uword;
3189        hdr->first = (v_uword & 0xff) * 0x100;
3190        hdr->first += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3191        if  (hdr->first >= 48 && hdr->first < 64)  next_block = hdr->first;
3192
3193        /* if a pointer > 0 was found swap type and nextblock entry of this blockette */
3194        while  (next_block > 0)  {
3195                b1000 = (SeedBlockette1000T *)((char *)hdr + (unsigned)(next_block));
3196                next_block = 0;
3197                /* check for blockette 1000 and 1001 */
3198                if  (b1000->type == 1000)  b1000->type = 0xe803;
3199                else if  (b1000->type == 1001)  b1000->type = 0xe903;
3200                else if  (b1000->type == 0xe803)  b1000->type = 1000;
3201                else if  (b1000->type == 0xe903)  b1000->type = 1001;
3202                /* swap pointer to next blockette and store pointer value */
3203                v_uword = b1000->nextblock;
3204                if  (v_uword >= 48 && v_uword < 64)  next_block = v_uword;
3205                b1000->nextblock = (v_uword & 0xff) * 0x100;
3206                b1000->nextblock += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3207                if  ((b1000->nextblock) >= 48 && (b1000->nextblock) < 64)
3208                        next_block = b1000->nextblock;
3209        } /*endif*/
3210
3211} /* end of SeedSwapHeader */
3212
3213
3214
3215/*---------------------------------------------------------------------*/
3216
3217
3218
3219void SeedCloseFiles( void )
3220
3221/* closes all open SEED files
3222 *
3223 * no parameters
3224 */
3225{
3226        /* local variables */
3227        int      i;         /* counter */
3228
3229        /* executable code */
3230
3231        for  (i=0; i<Seed_C_MAXCHAN; i++)
3232                if  (seedv_fd[i].ufd != Seed_C_ILLEGAL)  {
3233                        close( seedv_fd[i].ufd );
3234                        seedv_fd[i].ufd = Seed_C_ILLEGAL;
3235                } /*endif*/
3236
3237} /* end of SeedCloseFiles */
3238
3239
3240
3241/*---------------------------------------------------------------------*/
3242
3243
3244
3245static void SeedAdjustFilename( SeedFileDescrT *dsc, STATUS *status )
3246
3247/* copies directory of sfd-file to data filename
3248 *
3249 * parameters of routine
3250 * SeedFileDescrT  *dsc;        modify; SEED file descriptor
3251 * STATUS          *status;     output; return status
3252 */
3253{
3254        /* local variables */
3255        int      i;                      /* counter */
3256        int      strlth;                 /* string length */
3257        char     path[BC_FILELTH+1];     /* path name */
3258        BOOLEAN  iscolon;                /* is there a colon ? */
3259        char     upname[cBcFileLth+1];   /* uppercase filename */
3260
3261        /* executable code */
3262
3263        /* find path in sfdfile */
3264        i = strlen( dsc->sfdfile ) - 1;
3265        while  (i >= 0 && dsc->sfdfile[i] != '/' && dsc->sfdfile[i] != ':'
3266                && dsc->sfdfile[i] != '\\')  i--;
3267        if  (i > 0)  {
3268                strncpy( path, dsc->sfdfile, i );
3269                path[i] = '\0';
3270                iscolon = (dsc->sfdfile[i] == ':');
3271        } else {
3272                *path = '\0';
3273                iscolon = FALSE;
3274        } /*endif*/
3275
3276        if  (strlen(dsc->name)-ROOTDIRLTH+strlen(path) > BC_FILELTH)  {
3277                *status = SeedERR_STROVFL;
3278                return;
3279        } /*endif*/
3280
3281        if  (*path != '\0')  {
3282                strlth = strlen( path );
3283                for  (i=0; i<strlth; i++)
3284                        if  (path[i] == '\\')  path[i] = '/';
3285                if  (iscolon)  {
3286                        strcat( path, ":" );
3287                        if  (seedv_capfiles)  {
3288                                strcpy( upname, dsc->name+ROOTDIRLTH+1 );
3289                                ut_cap( upname );
3290                                strcat( path, upname );
3291                        } else {
3292                                strcat( path, dsc->name+ROOTDIRLTH+1 );
3293                        } /*endif*/
3294                } else {
3295                        if  (seedv_capfiles)  {
3296                                strcpy( upname, dsc->name+ROOTDIRLTH );
3297                                ut_cap( upname );
3298                                strcat( path, upname );
3299                        } else {
3300                                strcat( path, dsc->name+ROOTDIRLTH );
3301                        } /*endif*/
3302                } /*endif*/
3303        } else {
3304                strcpy( path, dsc->name+ROOTDIRLTH+1 );
3305        } /*endif*/
3306        strcpy( dsc->name, path );
3307
3308} /* end of SeedAdjustFilename */
3309
3310
3311
3312/*---------------------------------------------------------------------*/
3313
3314
3315static void SeedLibWarning( char text[] )
3316
3317/* prints warning messages
3318 *
3319 * parameters of routine
3320 * char       text[];      input; output text
3321 */
3322{
3323        /* local variables */
3324        char     str[cBcLineLth+1];    /* output string */
3325        int      i;                    /* counter */
3326
3327        /* executable code */
3328
3329        if  (!seedv_warnings)  return;
3330
3331#ifdef XXX
3332        i = 0;
3333        while  (i < cBcLineLth && text[i] != '\0')  {
3334                if  ((text[i] >= ' ' && text[i] <= 'z') || text[i] == '\n')  {
3335                        str[i] = text[i];
3336                } else {
3337                        str[i] = '.';
3338                } /*endif*/
3339                i++;
3340        } /*endwhile*/
3341        str[i] = '\0';
3342
3343        fprintf( stderr, "%s", str );
3344#endif
3345        fprintf( stderr, "%s", text );
3346
3347} /* end of SeedLibWarning */
3348
3349
3350
3351/*---------------------------------------------------------------------*/
3352
3353
3354
3355void SeedPrintWarnings( BOOLEAN on_off )
3356
3357/* switches warning messages on or off
3358 *
3359 * parameters of routine
3360 * BOOLEAN    on_off;       input; switch
3361 */
3362{
3363        /* executable code */
3364
3365        seedv_warnings = on_off;
3366
3367} /* end of SeedPrintWarnings */
3368
3369
3370
3371/*---------------------------------------------------------------------*/
3372
3373
3374
3375void SeedAcceptCapfiles( BOOLEAN on_off )
3376
3377/* switches on/off whether capitalized filenames on $ROOT-paths are accepted
3378 *
3379 * parameters of routine
3380 * BOOLEAN    on_off;       input; switch
3381 */
3382{
3383        /* executable code */
3384
3385        seedv_capfiles = on_off;
3386
3387} /* end of SeedPrintWarnings */
3388
3389
3390
3391/*---------------------------------------------------------------------*/
3392
3393
3394
3395BOOLEAN SeedSetInvertSwapHeader( BOOLEAN on_off )
3396
3397/* Sets the global variable seedv_invert_swap_hdr to invert header swap
3398 * info in sfd-file.  Returns old value.
3399 *
3400 * parameters of routine
3401 * BOOLEAN    on_off;    input; switch value
3402 */
3403{
3404        /* local variables */
3405        BOOLEAN  old;
3406
3407        /* executable code */
3408
3409        old = seedv_invert_swap_hdr;
3410        seedv_invert_swap_hdr = on_off;
3411        return old;
3412
3413} /* end of SeedSetInvertSwapHeader */
3414
3415
3416
3417/*---------------------------------------------------------------------*/
3418
3419
3420
3421BOOLEAN SeedSetDecodeErrorAbort( BOOLEAN on_off )
3422
3423/* Sets the global value seedv_decerr_abort (abort on occurrence of
3424 * SEED decoding errors.  Returns old value.
3425 *
3426 * parameters of routine
3427 * BOOLEAN    on_off;        input; switch value
3428 */
3429{
3430        /* local variables */
3431        BOOLEAN  old;        /* old value */
3432
3433        /* executable code */
3434
3435        old = seedv_decerr_abort;
3436        seedv_decerr_abort = on_off;
3437        return old;
3438
3439} /* end of SeedSetDecodeErrorAbort */
3440
3441
3442
3443/*---------------------------------------------------------------------*/
3444
3445
3446
3447BOOLEAN SeedUseTimeCorrection( BOOLEAN on_off )
3448
3449/* Sets the global value seedv_use_timecorr (use timec orrection field
3450 * within SEED data records).  Returns old value.
3451 *
3452 * parameters of routine
3453 * BOOLEAN    on_off;        input; switch value
3454 */
3455{
3456        /* local variables */
3457        BOOLEAN  old;        /* old value */
3458
3459        /* executable code */
3460
3461        old = seedv_use_timecorr;
3462        seedv_use_timecorr = on_off;
3463        return old;
3464
3465} /* end of SeedUseTimeCorrection */
3466
3467
3468
3469/*---------------------------------------------------------------------*/
3470
3471
3472
3473void SeedCutStartRecord( SeedSbyteT *seedrec, char extime[], BOOLEAN swap,
3474        STATUS *status )
3475
3476/* Throws away the first samples in record until given time
3477 *
3478 * parameters of routine
3479 * char       *seedrec;         modify; SEED record to cut
3480 * char       extime[];         input; exact time
3481 * BOOLEAN    swap;             input; swap bytes ?
3482 * STATUS     *status;          output; return status
3483 */
3484{
3485        /* local variables */
3486        SeedDataHeaderT *hdrptr;   /* pointer to data header */
3487        SeedDataHeaderT *outrec;   /* output records */
3488        SeedDataHeaderT tmphdr;    /* temp store */
3489        float    dt;               /* sample rate */
3490        NTIME    rstart, rend;     /* record start and end times */
3491        NTIME    ntime;            /* numeric exact time */
3492        float    tdiff;            /* time difference in sec */
3493        int      cutlth;           /* number of samples to cut */
3494        INT32    smp[MAX_SMP_PER_REC]; /* space for decoded samples */
3495        INT32    smplth;           /* number of sample decoded */
3496        int      i;                /* counter */
3497        int      recs_used;        /* records used for encoding (should be 1) */
3498        int      reclth;           /* record length */
3499
3500        /* executable code */
3501
3502        /* retrieve header information needed here */
3503        hdrptr = (SeedDataHeaderT *)seedrec;
3504        dt = SeedGetSampleDist( hdrptr );
3505        reclth = SeedGetReclth( hdrptr, FALSE );
3506        SeedRecordTime( seedrec, &rstart, &rend, status );
3507        if  (SySevere(status))  return;
3508        tc_t2n( extime, &ntime, status );
3509        if  (SySevere(status))  return;
3510        tdiff = tc_ndiff( &ntime, &rstart, status );
3511        if  (SySevere(status))  return;
3512        cutlth = Nint( tdiff / dt );
3513        if  (cutlth > (int)(hdrptr->no_of_samples))  {
3514                *status = SeedERR_ILLCUT;
3515                return;
3516        } else if  (cutlth == (int)(hdrptr->no_of_samples))  {
3517                hdrptr->no_of_samples = 0;
3518                return;
3519        } else if  (cutlth <= 0)  {
3520                /* nothing to be done */
3521                return;
3522        } /*endif*/
3523
3524        /* decode record */
3525        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
3526        SeedDecodeSteim1( seedrec, swap, MAX_SMP_PER_REC, smp, &smplth );
3527        if  (smplth != (INT32)(hdrptr->no_of_samples))  {
3528                *status = SeedERR_DECODE_ERR;
3529                return;
3530        } /*endif*/
3531
3532        /* throw away cutlth samples from the beginning */
3533        for  (i=cutlth; i<(int)smplth; i++)
3534                smp[i-cutlth] = smp[i];
3535        smplth -= (INT32)cutlth;
3536        tdiff = (float)cutlth * dt;
3537        tc_nadd( &rstart, tdiff, &rstart, status );
3538        if  (SySevere(status))  return;
3539
3540        /* prepare changed record */
3541        outrec = (SeedDataHeaderT *)sy_allocmem( 2, reclth, status );
3542        /* get two records; need only one but who knows ... */
3543        hdrptr->no_of_samples = (UWORD)smplth;
3544        SeedNtimeToBtime( &rstart, &(hdrptr->starttime), status );
3545        if  (SySevere(status))  {
3546                sy_deallocmem( outrec );
3547                return;
3548        } /*endif*/
3549        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)hdrptr, (UINT32)smplth,
3550                (WORD)(reclth), (INT32 *)outrec, 0 /*prev.smp*/ );
3551        if  (recs_used != 1)  {
3552                *status = SeedERR_BUG;
3553                sy_deallocmem( outrec );
3554                return;
3555        } /*endif*/
3556        /* copy result to output record and keep header */
3557        tmphdr = *hdrptr;
3558        memcpy( (char *)seedrec, (char *)outrec, reclth );
3559        SeedStoreReclth( (SeedDataHeaderT *)seedrec, reclth );
3560        *hdrptr = tmphdr;
3561        sy_deallocmem( outrec );
3562
3563} /* end of SeedCutStartRecord */
3564
3565
3566
3567/*---------------------------------------------------------------------*/
3568
3569
3570
3571void SeedCutEndRecord( SeedSbyteT *seedrec, char extime[], BOOLEAN swap,
3572        STATUS *status )
3573
3574/* Throws away the first samples in record until given time
3575 *
3576 * parameters of routine
3577 * char       *seedrec;         modify; SEED record to cut
3578 * char       extime[];         input; exact time
3579 * BOOLEAN    swap;             input; swap bytes ?
3580 * STATUS     *status;          output; return status
3581 */
3582{
3583        /* local variables */
3584        SeedDataHeaderT *hdrptr;   /* pointer to data header */
3585        SeedDataHeaderT *outrec;   /* output records */
3586        SeedDataHeaderT tmphdr;    /* temp store */
3587        float    dt;               /* sample rate */
3588        NTIME    rstart, rend;     /* record start and end times */
3589        NTIME    ntime;            /* numeric exact time */
3590        float    tdiff;            /* time difference in sec */
3591        int      cutlth;           /* number of samples to cut */
3592        INT32    smp[MAX_SMP_PER_REC]; /* space for decoded samples */
3593        INT32    smplth;           /* number of sample decoded */
3594        int      i;                /* counter */
3595        int      recs_used;        /* records used for encoding (should be 1) */
3596        int      reclth;           /* record length */
3597
3598        /* executable code */
3599
3600        /* retrieve header information needed here */
3601        hdrptr = (SeedDataHeaderT *)seedrec;
3602        dt = SeedGetSampleDist( hdrptr );
3603        reclth = SeedGetReclth( hdrptr, FALSE );
3604        SeedRecordTime( seedrec, &rstart, &rend, status );
3605        if  (SySevere(status))  return;
3606        tc_t2n( extime, &ntime, status );
3607        if  (SySevere(status))  return;
3608        tdiff = tc_ndiff( &rend, &ntime, status );
3609        if  (SySevere(status))  return;
3610        cutlth = Nint( tdiff / dt );
3611        if  (cutlth > (int)(hdrptr->no_of_samples))  {
3612                *status = SeedERR_ILLCUT;
3613                return;
3614        } else if  (cutlth == (int)(hdrptr->no_of_samples))  {
3615                hdrptr->no_of_samples = 0;
3616                return;
3617        } else if  (cutlth <= 0)  {
3618                /* nothing to be done */
3619                return;
3620        } /*endif*/
3621
3622        /* decode record */
3623        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
3624        SeedDecodeSteim1( seedrec, swap, MAX_SMP_PER_REC, smp, &smplth );
3625        if  (smplth != (INT32)(hdrptr->no_of_samples))  {
3626                *status = SeedERR_DECODE_ERR;
3627                return;
3628        } /*endif*/
3629
3630        /* throw away cutlth samples at the end */
3631        smplth -= (INT32)cutlth;
3632
3633        /* prepare changed record */
3634        outrec = (SeedDataHeaderT *)sy_allocmem( 2, reclth, status );
3635        /* get two records; need only one but who knows ... */
3636        hdrptr->no_of_samples = (UWORD)smplth;
3637        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)hdrptr, (UINT32)smplth,
3638                (WORD)(reclth), (INT32 *)outrec, 0 /*prev.smp*/ );
3639        if  (recs_used != 1)  {
3640                *status = SeedERR_BUG;
3641                sy_deallocmem( outrec );
3642                return;
3643        } /*endif*/
3644        /* copy result to output record and keep header */
3645        tmphdr = *hdrptr;
3646        memcpy( (char *)seedrec, (char *)outrec, reclth );
3647        SeedStoreReclth( (SeedDataHeaderT *)seedrec, reclth );
3648        *hdrptr = tmphdr;
3649        sy_deallocmem( outrec );
3650
3651} /* end of SeedCutEndRecord */
3652
3653
3654
3655/*---------------------------------------------------------------------*/
3656
3657
3658
3659char *SeedGetFilename( int chan )
3660
3661/* returns name of currently opened file on channel 'chan'.  If no filename
3662 * is found, a pointer to an empty string is returned.
3663 *
3664 * parameters of routine
3665 * int        chan;        input; channel number
3666 *                         returns name of file
3667 */
3668{
3669        /* local variables */
3670        static char nullstr[2] = "";  /* null string */
3671        SeedFileDescrT *fd;   /* pointer to SEED file descriptor */
3672
3673        /* executable code */
3674
3675        /* check channel number */
3676        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  return nullstr;
3677        fd = seedv_fd + chan;
3678        return ((fd->name[0] == '\0') ? seedv_last_fname : fd->name);
3679
3680} /* end of SeedGetFilename */
3681
3682
3683
3684/*---------------------------------------------------------------------*/
3685
3686
3687
3688void SeedStoreReclth( SeedDataHeaderT *rec, int reclth )
3689
3690/* Stores record length in SEED record. Uses Reserved_bytes_A for this purpose
3691 * if no blockette 1000 is available.
3692 *
3693 * parameters of routine
3694 * SeedDataHeaderT   *rec;   modify;  SEED record
3695 */
3696{
3697        /* local variables */
3698        int      num, i;        /* value and exp counter */
3699        TSyBoolean b1000;       /* blockette 1000 found */
3700        UWORD    *uw;           /* pointer to UWORD */
3701        char     *cp;           /* pointer to char */
3702        UWORD    recfirst;      /* offset to first blockette */
3703        UWORD    tmp;           /* scratch */
3704
3705        /* executable code */
3706
3707        /* determine which power of 2 */
3708        num = 1;
3709        i = 0;
3710        while  (num < reclth)  {
3711                i++;
3712                num *= 2;
3713        } /*endwhile*/
3714
3715        /* if a blockette 1000 is there use it */
3716        b1000 = TRUE;
3717        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3718        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3719
3720        if  (b1000)  {
3721                if  (rec->first > reclth)  {
3722                        tmp = rec->first;
3723                        recfirst = (tmp & 0xff) * 0x100;
3724                        recfirst += (UWORD)(tmp & 0xff00) / (UWORD)0x100;
3725                } else {
3726                        recfirst = rec->first;
3727                } /*endif*/
3728                if  (recfirst % 2 == 1)  {
3729                        SeedLibWarning(
3730                                "*** illegal 'first' entry in record (StoreReclth) ***\n" );
3731                        b1000 = FALSE;
3732                } /*endif*/
3733        } /*endif*/
3734
3735        if  (b1000)  {
3736                uw = (UWORD *)((char *)rec + (int)recfirst);
3737                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3738        } /*endif*/
3739
3740        if  (b1000)  {
3741                cp = (char *)rec + (int)recfirst + 6;
3742                *cp = (char)i;
3743        } else {
3744                rec->Reserved_bytes_A = (char)i;
3745        } /*endif*/
3746
3747} /* end of SeedStoreReclth */
3748
3749
3750
3751/*---------------------------------------------------------------------*/
3752
3753
3754
3755int SeedGetReclth( SeedDataHeaderT *rec, TSyBoolean clean )
3756
3757/* Returns SEED record length stored in record (by SeedStoreReclth)
3758 * If 'clean' is TRUE, the record length info is deleted from the record.
3759 *
3760 * parameters of routine
3761 * SeedDataHeaderT  *rec;      modify; SEED record
3762 * TSyBoolean       clean;     input; if TRUE, record length info is deleted
3763 */
3764{
3765        /* local variables */
3766        int      reclth;        /* record length */
3767        TSyBoolean b1000;       /* blockette 1000 found */
3768        UWORD    *uw;           /* pointer to UWORD */
3769        UWORD    recfirst;      /* offset to first blockette */
3770        char     *cp;           /* pointer to char */
3771        UWORD    tmp;           /* scratch */
3772
3773        /* executable code */
3774
3775        /* if a blockette 1000 is there use it */
3776        b1000 = TRUE;
3777        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3778        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3779        if  (b1000)  {
3780                if  (rec->first > (UWORD)sizeof(SeedDataHeaderT))  {
3781                        tmp = rec->first;
3782                        recfirst = (tmp & 0xff) * 0x100;
3783                        recfirst += (UWORD)(tmp & 0xff00) / (UWORD)0x100;
3784                } else {
3785                        recfirst = rec->first;
3786                } /*endif*/
3787                if  (recfirst % 2 == 1)  {
3788                        SeedLibWarning(
3789                                "*** illegal 'first' entry in record (StoreReclth) ***\n" );
3790                        b1000 = FALSE;
3791                } /*endif*/
3792        } /*endif*/
3793        if  (b1000)  {
3794                uw = (UWORD *)((char *)rec + (int)(recfirst));
3795                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3796        } /*endif*/
3797
3798        if  (b1000)  {
3799                cp = (char *)rec + (int)(recfirst) + 6;
3800                reclth = (*cp);
3801                reclth = (1 << reclth);
3802        } else {
3803                if  (rec->Reserved_bytes_A == '\0' || rec->Reserved_bytes_A == ' ')  {
3804                        fprintf( stderr,
3805                                "SeedGetReclth: no record length found in record. Abort.\n" );
3806                        exit( 1 );
3807                } /*endif*/
3808                reclth = (1 << (int)(rec->Reserved_bytes_A));
3809                if (clean)  rec->Reserved_bytes_A = ' ';
3810        } /*endif*/
3811
3812        return reclth;
3813
3814} /* end of SeedGetReclth */
3815
3816
3817
3818/*---------------------------------------------------------------------*/
3819
3820
3821
3822int SeedGetCompression( SeedDataHeaderT *rec )
3823
3824/* Returns compression algorithm ID if blockette 1000 is found,
3825 * otherwise 0.
3826 *
3827 * parameters of routine
3828 * SeedDataHeaderT  *rec;      input; SEED record
3829 */
3830{
3831        /* local variables */
3832        TSyBoolean b1000;       /* blockette 1000 found */
3833        UWORD    *uw;           /* pointer to UWORD */
3834        char     *cp;           /* pointer to char */
3835
3836        /* executable code */
3837
3838        /* if a blockette 1000 is there use it */
3839        b1000 = TRUE;
3840        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3841        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3842        if  (rec->first % 2 == 1)  {
3843                SeedLibWarning(
3844                        "*** illegal 'first' entry in record (GetCompression) ***\n" );
3845                return 0;
3846        } /*endif*/
3847        if  (b1000)  {
3848                uw = (UWORD *)((char *)rec + (int)(rec->first));
3849                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3850        } /*endif*/
3851        if  (!b1000)  return 0;
3852
3853        cp = (char *)rec + (int)(rec->first) + 4;
3854        return (int)(*cp);
3855
3856} /* end of SeedGetCompression */
3857
3858
3859
3860/*---------------------------------------------------------------------*/
3861
3862
3863
3864int SeedGetTimequal( SeedDataHeaderT *rec )
3865
3866/* Returns time quality or -1
3867 *
3868 * parameters of routine
3869 * SeedDataHeaderT   *rec;
3870 */
3871{
3872        /* local variables */
3873        SeedBlockette1001T *b1001;       /* blockette 1001 */
3874
3875        /* executable code */
3876
3877        if  (rec->no_of_blockettes <= 0)  return (-1);
3878
3879        b1001 = (SeedBlockette1001T *)((char *)rec + (unsigned)(rec->first));
3880        if  (b1001->type == 1001)  return (int)(b1001->timequal);
3881        if  (rec->no_of_blockettes == 1)  return (-1);
3882        b1001 = (SeedBlockette1001T *)((char *)rec + (unsigned)(b1001->nextblock));
3883        if  (b1001->type == 1001)  return (int)(b1001->timequal);
3884        return (-1);
3885        /* not more than 2 blockettes checked, should implement loop */
3886
3887} /* end of SeedGetTimequal */
3888
3889
3890
3891/*---------------------------------------------------------------------*/
3892
3893
3894
3895int SeedGetWordOrder( SeedDataHeaderT *rec )
3896
3897/* Returns word order ID if blockette 1000 is found,
3898 * otherwise 1 (=Sparc).
3899 *
3900 * parameters of routine
3901 * SeedDataHeaderT  *rec;      input; SEED record
3902 */
3903{
3904        /* local variables */
3905        TSyBoolean b1000;       /* blockette 1000 found */
3906        UWORD    *uw;           /* pointer to UWORD */
3907        char     *cp;           /* pointer to char */
3908
3909        /* executable code */
3910
3911        /* if a blockette 1000 is there use it */
3912        b1000 = TRUE;
3913        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3914        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3915        if  (rec->first % 2 == 1)  {
3916                SeedLibWarning( "*** illegal 'first' entry in record ***\n" );
3917                return 1;
3918        } /*endif*/
3919        if  (b1000)  {
3920                uw = (UWORD *)((char *)rec + (int)(rec->first));
3921                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3922        } /*endif*/
3923        if  (!b1000)  return 1;  /* Sparc word order is default */
3924
3925        cp = (char *)rec + (int)(rec->first) + 5;
3926        return (int)(*cp);
3927
3928} /* end of SeedGetWordOrder */
3929
3930
3931
3932/*---------------------------------------------------------------------*/
3933
3934
3935
3936void SeedSetOutputReclth( int reclth )
3937
3938/* Sets size of SEED output records (default is 4096, if not called)
3939 *
3940 * parameters of routine
3941 * int        reclth;       input; size of output records in bytes
3942 */
3943{
3944        /* executable code */
3945
3946        seedv_out_reclth = reclth;
3947
3948} /* end of SeedSetOutputReclth */
3949
3950
3951
3952/*----------------------------------------------------------------------------*/
3953
3954
3955
3956void SeedSetNextTimequal( int tq )
3957
3958/* Sets time quality for next Steim output record
3959 *
3960 * parameters of routine
3961 * int        tq;         input; time quality
3962 */
3963{
3964        /* executable code */
3965
3966        seedv_timequal = tq;
3967
3968} /* end of SeedSetNextTimequal */
3969
3970
3971
3972/*----------------------------------------------------------------------------*/
3973
3974
3975#define IDOFFSET 6
3976#define DATCHARS "DQR"
3977
3978
3979void SeedQuickFindReclth( FILE *fp, int *recsize, int *byteoff )
3980
3981/* Returns record size in bytes or 0 and the byte offset where data records
3982 * start.
3983 *
3984 * parameters of routine
3985 * FILE          *fp;          input; input file already opened
3986 * int           *recsize;     output; record size found
3987 * int           *byteoff;     output; byte offset found
3988 */
3989{
3990        /* local variables */
3991        char     id1, id2;  /* ID chars */
3992        TSyBoolean isdigit1, isdigit2; /* is number string */
3993        int      i;         /* counter */
3994
3995        /* executable code */
3996
3997        *recsize = 0;
3998        *byteoff = 0;
3999        isdigit1 = isdigit2 = TRUE;
4000
4001        /* position file and read number string and ID */
4002        fseek( fp, 0, 0 );
4003        for  (i=0; i<IDOFFSET; i++)  {
4004                id1 = getc( fp );
4005                if  (id1 < '0' || id1 > '9')  isdigit1 = FALSE;
4006        } /*endfor*/
4007        id1 = getc( fp );
4008        fseek( fp, 512, 0 );
4009        for  (i=0; i<IDOFFSET; i++)  {
4010                id2 = getc( fp );
4011                if  (id2 < '0' || id2 > '9')  isdigit2 = FALSE;
4012        } /*endfor*/
4013        id2 = getc( fp );
4014        if  (id1 == EOF || isdigit1 == FALSE)  {
4015                /* no SEED file, leave recsize zero */
4016        } else if  (strchr(DATCHARS,id1) != NULL && strchr(DATCHARS,id2) == NULL)  {
4017                /* definitely not 512 */
4018                *recsize = 4096;
4019                *byteoff = 0;
4020        } else if  (id1 == 'V' && strchr(DATCHARS,id2) != NULL && isdigit2 == TRUE)  {
4021                /* very likely 512 */
4022                *recsize = 512;
4023                *byteoff = 512;
4024        } else if  (isdigit2 == FALSE)  {
4025                *recsize = 4096;
4026                *byteoff = 0;  /* this is a guess */
4027        } else if  (strchr(DATCHARS,id1) != NULL && strchr(DATCHARS,id2) != NULL)  {
4028                *byteoff = 0;
4029                fseek( fp, 1024+IDOFFSET, 0 );
4030                id1 = getc( fp );
4031                fseek( fp, 1024+512+IDOFFSET, 0 );
4032                id2 = getc( fp );
4033                if  (strchr(DATCHARS,id1) != NULL && strchr(DATCHARS,id2) != NULL)  {
4034                        *recsize = 512;
4035                } else if  (strchr(DATCHARS,id1) != NULL && id2 == EOF)  {
4036                        *recsize = 512;
4037                } else if  (id1 == EOF)  {
4038                        *recsize = 512;
4039                } else {
4040                        *recsize = 4096;
4041                } /*endfif*/
4042        } else {
4043                /* cannot determine */
4044                *recsize = -1;
4045        } /*endif*/
4046
4047        /* rewind file */
4048        fseek( fp, 0, 0 );
4049
4050} /* end of SeedQuickFindReclth */
4051
4052
4053
4054/*---------------------------------------------------------------------*/
4055
4056
4057
4058static void SeedSwapLinuxRecord( SeedSbyteT *rec, int reclth )
4059
4060
4061/* Modifies record for writing on Linux system
4062 *
4063 * parameters of routine
4064 * SeedSbyteT *rec;                modify; SEED record
4065 * int        reclth;              input; record length, if 0 found by SeedGetReclth
4066 */
4067{
4068        /* local variables */
4069        SeedSbyteT     *ptr;                /* moving pointer */
4070        SeedSbyteT     tmp;                 /* scratch */
4071
4072        /* executable code */
4073
4074        if  (reclth == 0)
4075                reclth = SeedGetReclth( (SeedDataHeaderT *)rec, FALSE );
4076
4077        for  (ptr = rec+Seed_C_FRAMELTH; ptr < rec+reclth;
4078                ptr += 4)  {
4079                /* flip 0 and 3 */
4080                tmp = ptr[0];  ptr[0] = ptr[3];  ptr[3] = tmp;
4081                /* flip 1 and 2 */
4082                tmp = ptr[1];  ptr[1] = ptr[2];  ptr[2] = tmp;
4083        } /*endfor*/
4084
4085} /* end of SeedSwapLinuxRecord */
4086
4087
4088
4089/*---------------------------------------------------------------------*/
4090
4091
4092
4093static void SeedSplitStreamName( char inpname[], char outname[],
4094        char station[], char addinf[] )
4095
4096/* Splits extended stream name (e.g. anmo.iu00-bh-z) into standard stream
4097 * name (e.g. anmo-bh-z) and addinfo string (iu00).  Minimum output length
4098 * of addinf is Seed_C_AddinfLth+1.
4099 *
4100 * parameters of routine
4101 * char       inpname[];     input; extended stream name
4102 * char       outname[];     output; standard stream name
4103 * char       station[];     output; station name
4104 * char       addinf[];      output; addinfo string
4105 */
4106{
4107        /* local variables */
4108        int      i, j, k;         /* counter */
4109        int      slen;            /* length of stream string */
4110        TSyBoolean add;           /* addinfo string */
4111        TSyBoolean first;         /* first point */
4112        TSyBoolean isstat;        /* station part */
4113
4114        /* executable code */
4115
4116        /* default addinf */
4117        strcpy( addinf, Seed_C_EmptyAddinfStr );
4118        *station = '\0';
4119
4120        first = TRUE;
4121        slen = strlen( inpname );
4122        j = k = 0;
4123        add = FALSE;
4124        isstat = TRUE;
4125        for  (i=0; i<slen; i++)  {
4126                if  (inpname[i] == '.' && first)  {
4127                        add = TRUE;
4128                        first = FALSE;
4129                        if  (isstat)  {
4130                                station[i] = '\0';
4131                                isstat = FALSE;
4132                        } /*endif*/
4133                } else if  (inpname[i] == '-')  {
4134                        add = FALSE;
4135                        outname[k++] = inpname[i];
4136                        if  (isstat)  {
4137                                station[i] = '\0';
4138                                isstat = FALSE;
4139                        } /*endif*/
4140                } else {
4141                        if  (isstat)  station[i] = Uncap( inpname[i] );
4142                        if  (add && j < Seed_C_AddinfLth)  {
4143                                addinf[j++] = Uncap( inpname[i] );
4144                        } else {
4145                                outname[k++] = inpname[i];
4146                        } /*endif*/
4147                } /*endif*/
4148        } /*endfor*/
4149
4150        outname[k] = '\0';
4151
4152        /*printf( "--> %s -> %s,%s\n", inpname, outname, addinf );*/
4153
4154} /* end of SeedSplitStreamName */
4155
4156
4157/*---------------------------------------------------------------------*/
4158
4159
4160
4161/* FORTRAN interface routine */
4162
4163
4164void SeedReadStreamReal_( int chan, char sfdfile[], char stream_str[],
4165        BOOLEAN swap, char req_start[], float seclth, float **fdat,
4166        INT32 *smplth, char act_start[], float *dt, float *calib,
4167        int *flags, STATUS *status )
4168{
4169
4170        SeedReadStreamReal( chan, sfdfile, stream_str, swap, req_start,
4171                seclth, fdat, smplth, act_start, dt, calib, flags, status );
4172
4173} /* end of SeedReadStreamReal_ */
4174
4175
4176void SeedLibInitialize_( STATUS *status )
4177{
4178
4179        SeedLibInitialize( status );
4180
4181} /* end of SeedLibInitialize_ */
4182
4183
4184void SeedSetup_( STATUS *status )
4185{
4186        static SeedSetupParT setup;
4187
4188        SeedSetup( &setup, status );
4189
4190} /* end of SeedSetup_ */
4191
4192
4193/*---------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.