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

Revision 261, 132.7 KB checked in by marcus, 12 years ago (diff)

r134 | klaus | 2010-08-11 09:51:01 +0200 (Mi, 11 Aug 2010) | 1 line

fixed bug when reading data until midnight with a trailing gap

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