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

Revision 68, 132.5 KB checked in by marcus, 14 years ago (diff)

r53 | svn | 2008-10-21 09:13:49 +0200 (Di, 21 Okt 2008) | 1 line

implemented special channels (++) with translation tables

Line 
1
2/* file seed_lib.c
3 *      ==========
4 *
5 * $Revision: 53 $, $Date: 2008-10-21 09:13:49 +0200 (Di, 21 Okt 2008) $
6 *
7 * SEED library
8 * K. Stammler, 29-Dec-93
9 * v 16, 22-Nov-94, K. Stammler, added headers for VAX-GCC
10 * v 18, 23-Nov-94, K. Stammler, automatic detection of necessary byte swaps
11 * v 43,  7-Dec-97, K. Stammler, fixed calib-bug when reading starts in a gap
12 * v 44,  9-Dec-97, K. Stammler, fixed bug in ReadNextRecord (appeared in Linux)
13 * v 46,  2-Mar-98, K. Stammler, fixed bug on records with too many samples
14 * v 47, 24-Mar-98, K. Stammler, was still a bug in records with too many smples
15 * v 48, 24-Apr-98, K. Stammler, replaced some printf's by fprintf's
16 * v 49,  1-Jun-98, K. Stammler, still another bug at records with bad samples
17 * v 50, 11-Aug-98, K. Stammler, implemented offset positions in SEED files
18 * v 51, 16-Mar-99, K. Stammler, use time correction field in SEED records
19 * v 52, 11-Jan-00, K. Stammler, variable SEED record length
20 * v 53, 14-Jun-00, K. Stammler, SeedSwapNecessary until 2030
21 * v 54, 11-Jul-00, K. Stammler, handle seed->databegin other than 64er numbers
22 * v 56,  6-Dec-01, K. Stammler, implementation of Steim2 input
23 * v 57, 11-Jan-02, K. Stammler, increased max samples/rec to 14000
24 * v 58,  8-Jul-02, K. Stammler, implement VAX word order
25 * v 59, 26-Aug-02, K. Stammler, only output printable chars on SeedLibWarning
26 * v 60,  9-Sep-02, K. Stammler, check for illegal 'first' entry (bus error)
27 * v 61, 17-Oct-02, K. Stammler, in SeedReadStreamReal, set fdat=NULL, first
28 * v 62, 17-Nov-02, K. Stammler, SeedStoreRec: swap 'first' entry on swapped rec
29 * v 63, 14-Apr-05, K. Stammler, insert blockette 1000 when writing miniSeed
30 * v 64, 18-Nov-05, K. Stammler, compiler error on Suse10, empty default switch
31 * v 65, 21-Nov-05, K. Stammler, change long to int32
32 * v 66, 25-Nov-05, K. Stammler, possibility to insert time quality in data recs
33 * v 67,  7-Mar-06, K. Stammler, netcode+locid used for reading
34 * v 68, 28-Apr-06, K. Stammler, fixed bug in SeedGetReclth (was no test for swap)
35 * v 70, 20-May-06, K. Stammler, new file format for calibration info
36 * v 71, 22-May-06, K. Stammler, new flag-parameter in SeedReadStream for qc
37 * v 72, 14-Jun-06, K. Stammler, missing fclose fixed on new sensitivities file
38 * v 73, 22-Oct-06, K. Stammler, string lists on sensitivity file
39 * v 74,  4-Nov-06, K. Stammler, add sfdb interface
40 * v 75, 12-Nov-06, K. Stammler, add routine to remove temp file of sfdb request
41 * v 76, 15-Dec-06, K. Stammler, date and time in INT and DOUBLE format
42 * v 77, 18-Dec-06, K. Stammler, added some debug printout
43 * v 78, 21-Dec-06, K. Stammler, restructered sfdb interface (sqliface.c)
44 * v 79, 28-Dec-06, K. Stammler, 'default' sensitivity replaced by $SH_INPUTS/sensitivities.txt
45 * v 80, 29-Dec-06, K. Stammler, implementation of data lock flag
46 * v 81,  3-Jan-07, K. Stammler, set default of seedv_use_timecorr to TRUE, TIMECORRUNIT to 10000
47 * v 82, 13-Feb-07, K. Stammler, swap blockette 1000 in SwapHeader
48 * v 83, 28-Nov-07, K. Stammler, accept also Q and R as data record identifier
49 */
50
51
52#include <stdio.h>
53#include <string.h>
54#include <math.h>
55#include "basecnst.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  (Severe(status))  return;
2497
2498                /* decode SEED record and select samples */
2499                /* ------------------------------------- */
2500                if  (*ldat == NULL)  {
2501
2502                        /* this is for first loop only */
2503                        /* --------------------------- */
2504                        *calib = fd->calib;
2505                        *flags = fd->dataflags;
2506                        if  (seedv_rec->quality != 0)  {
2507                                if  (GpGetInt(cGpI_debug_level > 0))
2508                                        printf( "SHM-dbg1: SEED quality flags: 0x%x\n",
2509                                                (int)seedv_rec->quality );
2510                                (*flags) |= seedv_rec->quality;
2511                        } /*endif*/
2512                        *dt = SeedGetSampleDist( seedv_rec );
2513                        getlth = Nint32( seclth / *dt );
2514                        if  (getlth <= 0)  {*status = SeedERR_ZEROLTH; return;}
2515                        *ldat = (INT32 *)sy_allocmem( getlth, (int)sizeof(INT32), status );
2516                        if  (Severe(status))  return;
2517                        ldst = *ldat;
2518                        recsmp = (INT32 *)sy_allocmem( maxrecsmp, (int)sizeof(INT32), status );
2519                        if  (Severe(status))  {sy_deallocmem(*ldat); return;}
2520                        /* if time gap at beginning, pad zeroes */
2521                        if  (tdiff > 0.0)  {
2522                                /* pad with zeroes and adjust start time */
2523                                padcnt = Nint32( tdiff / (*dt) );
2524                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
2525                                        seedv_rec->seqno, act_start );
2526                                fprintf( stderr, "   gap %5.3f sec, start with %ld zeroes\n",
2527                                        tdiff, padcnt );
2528                                tc_tadd( act_start, -(*dt)*(float)padcnt, act_start, status );
2529                                if  (Severe(status))  *status = BC_NOERROR; /* ok, not elegant */
2530                                while  (padcnt-- > 0)  {
2531                                        ldst[(*smplth)++] = 0;
2532                                        if  (*smplth == getlth)  {
2533                                                sy_deallocmem( recsmp );
2534                                                fprintf( stderr,
2535                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
2536                                                strcpy( act_start, req_start );
2537                                                return;
2538                                        } /*endif*/
2539                                } /*endwhile*/
2540                        } /*endif*/
2541                        SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, swap_data,
2542                                maxrecsmp, recsmp, &actrecsmp );
2543                        if  (actrecsmp != seedv_rec->no_of_samples)  {
2544                                fprintf( stderr,
2545                                        "*** seed record samples: expected %d, actual: %d\n",
2546                                        seedv_rec->no_of_samples, actrecsmp );
2547                                if  (seedv_decerr_abort)  {
2548                                        sy_deallocmem( *ldat );
2549                                        *ldat = NULL;
2550                                        sy_deallocmem( recsmp );
2551                                        *status = SeedERR_DECODE_ERR;
2552                                        return;
2553                                } else {
2554                                        INT32    zeronum;       /* number of sample to zero */
2555                                        zeronum = seedv_rec->no_of_samples;
2556                                        if  (zeronum > maxrecsmp)  zeronum = maxrecsmp;
2557                                        fprintf( stderr, "   zero %d samples and continue\n", zeronum );
2558                                        for  (i=0; i<zeronum; i++)
2559                                                recsmp[i] = 0;
2560                                } /*endif*/
2561#                               ifdef XXX
2562                                /* excluded this on 1-Jul-98, K.S. */
2563                                fd->sample = 0;
2564                                fprintf( stderr,
2565                                        "   read position within zeroed record set to zero\n" );
2566#                               endif
2567                                actrecsmp = seedv_rec->no_of_samples;
2568                        } /*endif*/
2569                        lsrc = recsmp + fd->sample;
2570                        actrecsmp -= fd->sample;
2571                        if  (actrecsmp < 0)  {
2572                                sy_deallocmem( *ldat );
2573                                *ldat = NULL;
2574                                sy_deallocmem( recsmp );
2575                                *status = SeedERR_BUG;
2576                                fprintf( stderr, "*** SeedReadStream: bug (1) [sample: %d] ***\n",
2577                                        fd->sample );
2578                                return;
2579                        } /*endif*/
2580                        SeedRecordTime( (SeedSbyteT *)seedv_rec, &recstart, &expectime,
2581                                status );
2582                        if  (Severe(status))  return;
2583
2584                } else {
2585
2586                        /* this is for all other loops */
2587                        /* --------------------------- */
2588
2589                        /* collect data quality flags */
2590                        if  (seedv_rec->quality != 0)  {
2591                                if  (GpGetInt(cGpI_debug_level > 0))
2592                                        printf( "SHM-dbg1: SEED quality flags: %x\n",
2593                                                (int)seedv_rec->quality );
2594                                (*flags) |= seedv_rec->quality;
2595                        } /*endif*/
2596
2597                        /* decode record */
2598                        SeedDecodeSteim1( (SeedSbyteT *)seedv_rec, swap_data,
2599                                maxrecsmp, recsmp, &actrecsmp );
2600                        if  (actrecsmp != seedv_rec->no_of_samples)  {
2601                                fprintf( stderr,
2602                                        "*** seed record samples: expected %d, actual: %d\n",
2603                                        seedv_rec->no_of_samples, actrecsmp );
2604                                if  (seedv_decerr_abort)  {
2605                                        sy_deallocmem( *ldat );
2606                                        *ldat = NULL;
2607                                        sy_deallocmem( recsmp );
2608                                        *status = SeedERR_DECODE_ERR;
2609                                        return;
2610                                } else {
2611                                        INT32    zeronum;       /* number of sample to zero */
2612                                        zeronum = seedv_rec->no_of_samples;
2613                                        if  (zeronum > maxrecsmp)  zeronum = maxrecsmp;
2614                                        fprintf( stderr, "   zero %d samples and continue\n", zeronum );
2615                                        for  (i=0; i<zeronum; i++)
2616                                                recsmp[i] = 0;
2617                                } /*endif*/
2618                                actrecsmp = seedv_rec->no_of_samples;
2619                        } /*endif*/
2620                        lsrc = recsmp;
2621
2622                        /* check for time gaps, pad with zeroes */
2623                        SeedRecordTime( (SeedSbyteT *)seedv_rec, &recstart, &recend, status );
2624                        if  (Severe(status))  return;
2625                        tdiff = tc_ndiff( &recstart, &expectime, status );
2626                        if  (Severe(status))  return;
2627                        if  (tdiff <= -(*dt))  {
2628                                /* double data */
2629                                padcnt = Nint32( -tdiff / (*dt) );
2630                                tc_n2t( &recstart, str, status );
2631                                strncpy( recmsg, seedv_rec->seqno, 6 );
2632                                recmsg[6] = '\0';
2633                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
2634                                        recmsg, str );
2635                                fprintf( stderr, "   double data, %ld samples skipped\n",
2636                                        padcnt );
2637                                if  (padcnt > (INT32)(seedv_rec->no_of_samples))  {
2638                                        /*
2639                                        *status = SeedERR_DOUBLEDATA;
2640                                        sy_deallocmem( recsmp );
2641                                        return;
2642                                        */
2643                                        fprintf( stderr, "double data; complete record skipped\n" );
2644                                        continue;
2645                                } /*endif*/
2646                                /* skip samples */
2647                                lsrc += padcnt;
2648                                actrecsmp -= padcnt;
2649                        } else if  (tdiff >= (*dt))  {
2650                                /* time gap */
2651                                padcnt = Nint32( tdiff / (*dt) );
2652                                tc_n2t( &recstart, str, status );
2653                                strncpy( recmsg, seedv_rec->seqno, 6 );
2654                                recmsg[6] = '\0';
2655                                fprintf( stderr, "SeedReadStream: record %6s, time %s\n",
2656                                        recmsg, str );
2657                                fprintf( stderr,
2658                                        "   gap %5.3f sec, padding %ld zeroes at sample %ld\n",
2659                                        tdiff, padcnt, *smplth );
2660                                /* pad zeroes */
2661                                while  (padcnt-- > 0)  {
2662                                        ldst[(*smplth)++] = 0;
2663                                        if  (*smplth == getlth)  {
2664                                                sy_deallocmem( recsmp );
2665                                                fprintf( stderr,
2666                                                        "   padding aborted, %ld zeroes remaining\n", padcnt );
2667                                                return;
2668                                        } /*endif*/
2669                                } /*endwhile*/
2670                        } /*endif*/
2671                        expectime = recend;
2672
2673                } /*endif*/
2674
2675                /* copy samples to output array */
2676                while  (actrecsmp-- > 0)  {
2677                        ldst[(*smplth)++] = *lsrc++;
2678                        if  (*smplth == getlth)  {  /* finished ! */
2679                                sy_deallocmem( recsmp );
2680                                return;
2681                        } /*endif*/
2682                } /*endwhile*/
2683
2684        } /*endfor*/
2685
2686} /* end of SeedReadStream */
2687
2688
2689
2690/*---------------------------------------------------------------------*/
2691
2692
2693
2694void SeedReadStreamReal( int chan, char sfdfile[], char stream_str[],
2695        BOOLEAN swap, char req_start[], float seclth, float **fdat,
2696        INT32 *smplth, char act_start[], float *dt, float *calib,
2697        int *flags, STATUS *status )
2698
2699/* Same as SeedReadStream except that a float array is returned
2700 *
2701 * parameters of routine
2702 * see SeedReadStream above
2703 */
2704{
2705        /* local variables */
2706        INT32    *lptr;         /* INT32 pointer to data array */
2707        INT32    *lp;           /* moving pointer */
2708        float    *fp;           /* moving pointer */
2709        INT32    i;             /* counter */
2710
2711        /* executable code */
2712
2713        *fdat = NULL;
2714
2715        SeedReadStream( chan, sfdfile, stream_str, swap, req_start,
2716                seclth, &lptr, smplth, act_start, dt, calib, flags, status );
2717        if  (Severe(status))  return;
2718
2719        if  (sizeof(INT32) != sizeof(float))  {
2720                printf( "--> sizeof(float) != sizeof(INT32)\n" );
2721                *status = 1;
2722                sy_deallocmem( lptr );
2723                return;
2724        } /*endif*/
2725
2726        lp = lptr;
2727        fp = *fdat = (float *)lptr;
2728        for  (i=0; i<(*smplth); i++)
2729                *fp++ = (float)(*lp++) * (*calib);
2730
2731} /* end of SeedReadStreamReal */
2732
2733
2734
2735/*---------------------------------------------------------------------*/
2736
2737
2738
2739float SeedFindStreamCalibration( char stream[], char stime[], STATUS *status )
2740
2741/* returns calibration value for counts for given stream 'stream' at time
2742 * 'stime'.
2743 *
2744 * parameters of routine
2745 * char           stream[];     input; stream string
2746 * char           stime[];      input; time
2747 * STATUS         *status;      output; return status
2748 *                              returns calibration or 0.0
2749 */
2750{
2751        /* local variables */
2752        char     calfile[BC_FILELTH+1];    /* name of calibration file */
2753        char     *eptr;                    /* pointer to environment variable */
2754        FILE     *fp;                      /* pointer to input file */
2755        char     line[BC_LINELTH+1];       /* current line of input file */
2756        char     v_start[BC_LINELTH+1];    /* start of valid time */
2757        char     v_end[BC_LINELTH+1];      /* end of valid time */
2758        float    lcalib;                   /* current value of calibration */
2759        int      cmpidx;                   /* position of component */
2760        int      filecnt;                  /* file counter */
2761        char     *sf;                      /* pointer to sensitivity file name */
2762
2763        /* executable code */
2764
2765        if  (strcmp(GpGetStringElem(cGpL_sensitivity_file,0),"old-style") == 0)  {
2766
2767                /* this is the old-style part, dealing with many, many
2768                 * seedcalib_... files in $SEED_INPUTS
2769                 */
2770
2771                /* build filename */
2772                *calfile = '\0';
2773                eptr = getenv( "SEED_INPUTS" );
2774                if  (eptr != NULL)  {
2775                        if  (strlen(eptr)+strlen(stream)+11 > BC_FILELTH)  {
2776                                *status = SeedERR_STROVFL;
2777                                return 0.0;
2778                        } /*endif*/
2779                        strcpy( calfile, eptr );
2780                        strcat( calfile, "/" );
2781                } /*endif*/
2782                strcat( calfile, "seedcalib_" );
2783                strcat( calfile, stream );
2784
2785                /* open file */
2786                fp = sy_fopen( calfile, "r" );
2787                if  (fp == NULL)  {
2788                        *status = SeedERR_NOCALIB;
2789                        fprintf( stderr, "*Seed: no calibration for %s, set to 1.0\n", stream );
2790                        return 1.0;
2791                } /*endif*/
2792
2793                while  (fgets(line,BC_LINELTH,fp) != NULL)  {
2794                        if  (*line == '!' || *line == '\n')  continue;
2795                        if  (sscanf(line,"%s %s %f",v_start,v_end,&lcalib) != 3)  {
2796                                fprintf( stderr, "*Seed: format error in calibration file %s\n", stream );
2797                                continue;
2798                        } /*endif*/
2799                        if  (tc_tdiff(stime,v_start,status) < 0.0)  continue;
2800                        if  (Severe(status))  return 0.0;
2801                        if  (tc_tdiff(stime,v_end,status) > 0.0)  continue;
2802                        if  (Severe(status))  return 0.0;
2803                        sy_fclose( fp );
2804                        return lcalib;
2805                } /*endwhile*/
2806
2807                sy_fclose( fp );
2808                *status = SeedERR_NOCALIB;
2809                fprintf( stderr, "*Seed: no valid calibration for %s %s, set to 1.0\n",
2810                        stream, stime );
2811                return 1.0;
2812
2813        } else {
2814
2815                /* this is the new version introduced 20-May-2006, all information
2816                 * is in a single file, by default in $SH_INPUTS/sensitivities.txt
2817                 */
2818
2819                /* loop all sensitivity files given */
2820                for  (filecnt=0;;filecnt++)  {
2821
2822                        /* get next sensitivity file name */
2823                        sf = GpGetStringElem( cGpL_sensitivity_file, filecnt );
2824                        if  (sf == NULL)  break;
2825
2826                        /* check for 'default' value, happens if GpReadParfile is not called */
2827                        if  (strcmp(sf,"default") == 0)  {
2828                                *calfile = '\0';
2829                                eptr = getenv( "SH_INPUTS" );
2830                                if  (eptr != NULL)  {
2831                                        if  (strlen(eptr)+18 > BC_FILELTH)  {
2832                                                *status = SeedERR_STROVFL;
2833                                                return 0.0;
2834                                        } /*endif*/
2835                                        strcpy( calfile, eptr );
2836                                        strcat( calfile, "/" );
2837                                } /*endif*/
2838                                strcat( calfile, "sensitivities.txt" );
2839                                sf = calfile;
2840                        } /*endif*/
2841
2842                        /* open it */
2843                        if  (GpGetInt(cGpI_debug_level) > 5)
2844                                printf( "SH-dbg6: open sensitivity file %s\n", sf );
2845                        fp = sy_fopen( sf, "r" );
2846                        if  (fp == NULL)  {
2847                                fprintf( stderr, "*Seed: sensitivity file %s not found\n", sf );
2848                                *status = SeedERR_NOCALIB;
2849                                return 1.0;
2850                        } /*endif*/
2851
2852                        /* wildcard takes stream with '?' as component */
2853                        cmpidx = strlen( stream ) - 1;
2854
2855                        /* read through file */
2856                        while  (fgets(line,cBcLineLth,fp) != NULL)  {
2857                                if  (*line == '!' || *line == '#' || *line == '\n')  continue;
2858                                if  (strncasecmp(line,stream,cmpidx) == 0)  {
2859                                        if  (line[cmpidx] == '?' || line[cmpidx] == stream[cmpidx])  {
2860                                                if  (sscanf(line+cmpidx+2,"%s %s %f",v_start,v_end,&lcalib) != 3)  {
2861                                                        fprintf( stderr, "*Seed: format error in calibration file at %s\n",
2862                                                                stream );
2863                                                        continue;
2864                                                } /*endif*/
2865                                                if  (strcmp(v_start,"...") != 0)
2866                                                        if  (tc_tdiff(stime,v_start,status) < 0.0)  continue;
2867                                                if  (Severe(status))  {
2868                                                        sy_fclose( fp );
2869                                                        return 0.0;
2870                                                } /*endif*/
2871                                                if  (strcmp(v_end,"...") != 0)
2872                                                        if  (tc_tdiff(stime,v_end,status) > 0.0)  continue;
2873                                                if  (Severe(status))  {
2874                                                        sy_fclose( fp );
2875                                                        return 0.0;
2876                                                } /*endif*/
2877                                                sy_fclose( fp );
2878                                                return lcalib;
2879                                        } /*endif*/
2880                                } /*endif*/
2881                        } /*endif*/
2882
2883                        sy_fclose( fp );
2884
2885                } /*endfor*/
2886
2887                *status = SeedERR_NOCALIB;
2888                fprintf( stderr, "*Seed: no valid calibration for %s %s, set to 1.0\n",
2889                        stream, stime );
2890                return 1.0;
2891
2892        } /*endif*/
2893
2894} /* end of SeedFindStreamCalibration */
2895
2896
2897
2898/*---------------------------------------------------------------------*/
2899
2900
2901
2902void SeedGetTimeSpan( char sfdfile[], char stream[], char start[],
2903        char end[], STATUS *status )
2904
2905/* Returns first and last time of channel 'stream' in sfd-file
2906 *
2907 * parameters of routine
2908 * char       sfdfile[];        input; name of sfd-file
2909 * char       stream[];         input; stream string to be checked
2910 * char       start[];          output; first start time
2911 * char       end[];            output; last end time
2912 * STATUS     *status;          output; return status
2913 */
2914{
2915        /* local variables */
2916        FILE     *sfd;                      /* pointer to sfd-file */
2917        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
2918        SeedFileDescrT dsc;                 /* sfd descriptor */
2919        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
2920
2921        /* executable code */
2922
2923        sfd = sy_fopen( sfdfile, "r" );
2924        if  (sfd == NULL)  {
2925                *status = SeedERR_OPENINPUT;
2926                err_setcontext( " ## file " );
2927                err_setcontext( sfdfile );
2928                return;
2929        } /*endif*/
2930
2931        strcpy( lstream, stream );
2932        ut_uncap( lstream );
2933
2934        /* find requested stream */
2935        *start = *end = '\0';
2936        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
2937                if  (*line == '!')  continue;
2938                SeedParseSfdLine( line, &dsc, status );
2939                if  (strcmp(dsc.stream,lstream) != 0)  continue;
2940                if  (*start == '\0')  {
2941                        strcpy( start, dsc.t_start );
2942                } else {
2943                        if  (tc_tdiff(dsc.t_start,start,status) < 0.0)
2944                                strcpy( start, dsc.t_start );
2945                } /*endif*/
2946                if  (Severe(status))  return;
2947                if  (*end == '\0')  {
2948                        strcpy( end, dsc.t_end );
2949                } else {
2950                        if  (tc_tdiff(dsc.t_end,end,status) > 0.0)
2951                                strcpy( end, dsc.t_end );
2952                } /*endif*/
2953                if  (Severe(status))  return;
2954        } /*endwhile*/
2955
2956        sy_fclose( sfd );
2957
2958} /* end of SeedGetTimeSpan */
2959
2960
2961
2962/*---------------------------------------------------------------------*/
2963
2964
2965
2966BOOLEAN SeedInquireTime( char sfdfile[], char stream[], char start[],
2967        char end[], STATUS *status )
2968
2969/* Checks whether the specified time span from 'start' to 'end' is
2970 * available for channel 'stream' in sfd-file 'sfdfile'
2971 *
2972 * parameters of routine
2973 * char       sfdfile[];        input; name of sfd-file
2974 * char       stream[];         input; stream string
2975 * char       start[];          input; start time
2976 * char       end[];            input; end time
2977 * STATUS     *status;          output; return status
2978 *                              returns TRUE if data are available
2979 */
2980{
2981        /* local variables */
2982        FILE     *sfd;                      /* pointer to sfd-file */
2983        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
2984        SeedFileDescrT dsc;                 /* sfd descriptor */
2985        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
2986        TIME     a_start, a_end;            /* absolute times of inquied span */
2987        TIME     a1, a2;                    /* absolute times of SEED file */
2988
2989        /* executable code */
2990
2991        sfd = sy_fopen( sfdfile, "r" );
2992        if  (sfd == NULL)  {
2993                *status = SeedERR_OPENINPUT;
2994                err_setcontext( " ## file " );
2995                err_setcontext( sfdfile );
2996                return FALSE;
2997        } /*endif*/
2998
2999        strcpy( lstream, stream );
3000        ut_uncap( lstream );
3001
3002        tc_t2a( start, &a_start, status );
3003        if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
3004        tc_t2a( end, &a_end, status );
3005        if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
3006        if  (tc_adiff(&a_end,&a_start) < 0.0)  {sy_fclose(sfd); return FALSE;}
3007
3008        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
3009                if  (*line == '!')  continue;
3010                SeedParseSfdLine( line, &dsc, status );
3011                if  (strcmp(dsc.stream,lstream) != 0)  continue;
3012                tc_t2a( dsc.t_start, &a1, status );
3013                if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
3014                tc_t2a( dsc.t_end, &a2, status );
3015                if  (Severe(status))  {sy_fclose(sfd); return FALSE;}
3016                if  (tc_adiff(&a_start,&a1) < 0.0)  continue;
3017                if  (tc_adiff(&a2,&a_end) < 0.0)  continue;
3018                sy_fclose( sfd );
3019                return TRUE;
3020        } /*endwhile*/
3021
3022        sy_fclose( sfd );
3023
3024        return FALSE;
3025
3026} /* end of SeedInquireTime */
3027
3028
3029
3030/*---------------------------------------------------------------------*/
3031
3032
3033
3034void SeedInquireTimeList( char sfdfile[], char stations[], int itemlth,
3035        int listlth, char chan[], char comp, char start[], char end[],
3036        INT32 *avail, STATUS *status )
3037
3038/* Checks whether the specified time span from 'start' to 'end' is
3039 * available for all stations (stream 'station-chan-comp') in sfd-file
3040 * 'sfdfile'.  'station' is a char string with 'listlth' equidistant
3041 * strings of length 'itemlth'.
3042 *
3043 * parameters of routine
3044 * char       sfdfile[];        input; name of sfd-file
3045 * char       stations[];       input; list of stations
3046 * int        itemlth;          input; chars used for a station name
3047 * int        listlth;          input; length of list (# of stations) (<= 32)
3048 * char       chan[];           input; 2-char channel string
3049 * char       comp;             input; component
3050 * char       start[];          input; start time
3051 * char       end[];            input; end time
3052 * INT32      *avail;           output; station bits
3053 * STATUS     *status;          output; return status
3054 */
3055{
3056        /* local variables */
3057        FILE     *sfd;                      /* pointer to sfd-file */
3058        char     line[Seed_C_SFDLINELTH+1]; /* current sfd-line */
3059        SeedFileDescrT dsc;                 /* sfd descriptor */
3060        char     lstream[BC_SHORTSTRLTH+1]; /* lowercase stream name */
3061        TIME     a_start, a_end;            /* absolute times of inquied span */
3062        TIME     a1, a2;                    /* absolute times of SEED file */
3063        char     *sptr;                     /* current station name */
3064        int      scnt;                      /* station counter */
3065        char     cmpstr[2];                 /* component */
3066
3067        /* executable code */
3068
3069        sfd = sy_fopen( sfdfile, "r" );
3070        if  (sfd == NULL)  {
3071                *status = SeedERR_OPENINPUT;
3072                err_setcontext( " ## file " );
3073                err_setcontext( sfdfile );
3074                return;
3075        } /*endif*/
3076
3077        tc_t2a( start, &a_start, status );
3078        if  (Severe(status))  {sy_fclose(sfd); return;}
3079        tc_t2a( end, &a_end, status );
3080        if  (Severe(status))  {sy_fclose(sfd); return;}
3081        if  (tc_adiff(&a_end,&a_start) < 0.0)  {sy_fclose(sfd); return;}
3082
3083        cmpstr[0] = comp;
3084        cmpstr[1] = '\0';
3085
3086        *avail = 0;
3087
3088        while  (fgets(line,Seed_C_SFDLINELTH,sfd) != NULL)  {
3089
3090                /* get & parse next sfd line */
3091                if  (*line == '!')  continue;
3092                SeedParseSfdLine( line, &dsc, status );
3093
3094                /* check time */
3095                tc_t2a( dsc.t_start, &a1, status );
3096                if  (Severe(status))  {sy_fclose(sfd); return;}
3097                tc_t2a( dsc.t_end, &a2, status );
3098                if  (Severe(status))  {sy_fclose(sfd); return;}
3099                if  (tc_adiff(&a_start,&a1) < 0.0)  continue;
3100                if  (tc_adiff(&a2,&a_end) < 0.0)  continue;
3101
3102                /* now loop all stations */
3103                sptr = stations;
3104                for  (scnt=0; scnt<listlth; scnt++)  {
3105                        if  (*sptr != '-')  {
3106                                /* build stream name */
3107                                strcpy( lstream, sptr );
3108                                        strcat( lstream, "-" );
3109                                strcat( lstream, chan );
3110                                strcat( lstream, "-" );
3111                                strcat( lstream, cmpstr );
3112                                ut_uncap( lstream );
3113                                if  (strcmp(dsc.stream,lstream) == 0)
3114                                        *avail |= (1<<scnt);
3115                        } /*endif*/
3116                        /* increment station pointer */
3117                        sptr += itemlth;
3118                } /*endfor*/
3119
3120        } /*endwhile*/
3121
3122        sy_fclose( sfd );
3123
3124} /* end of SeedInquireTimeList */
3125
3126
3127
3128/*---------------------------------------------------------------------*/
3129
3130
3131
3132BOOLEAN SeedSwapNecessary( SeedDataHeaderT *hdr )
3133
3134/* Checks whether a swap is necessary on data header
3135 *
3136 * parameters of routine
3137 * SeedDataHeaderT *hdr;     input; header to check
3138 *                           returns TRUE if swap must be performed
3139 */
3140{
3141        /* executable code */
3142
3143        return  (hdr->starttime.year < 1950 || hdr->starttime.year > 2030);
3144
3145} /* end of SeedSwapNecessary */
3146
3147
3148
3149/*---------------------------------------------------------------------*/
3150
3151
3152
3153void SeedSwapHeader( SeedDataHeaderT *hdr )
3154
3155/* Swaps words and longwords in header
3156 *
3157 * parameters of routine
3158 * SeedDataHeaderT *hdr;          modify; data header to be swapped
3159 */
3160{
3161        /* local variables */
3162        WORD     v_word;      /* scratch */
3163        UWORD    v_uword;     /* scratch */
3164        INT32    v_long;      /* scratch */
3165        SeedBlockette1000T *b1000;  /* pointer to Blockette 1000 */
3166        UWORD    next_block;   /* next blockette pointer */
3167
3168        /* executable code */
3169
3170        v_uword = hdr->starttime.year;
3171        hdr->starttime.year = (v_uword & 0xff) * 0x100;
3172        hdr->starttime.year += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3173
3174        v_uword = hdr->starttime.day;
3175        hdr->starttime.day = (v_uword & 0xff) * 0x100;
3176        hdr->starttime.day += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3177
3178        v_uword = hdr->starttime.frac_secs;
3179        hdr->starttime.frac_secs = (v_uword & 0xff) * 0x100;
3180        hdr->starttime.frac_secs += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3181
3182        v_uword = hdr->no_of_samples;
3183        hdr->no_of_samples = (v_uword & 0xff) * 0x100;
3184        hdr->no_of_samples += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3185
3186        v_uword = (UWORD)(hdr->smprate_fact);
3187        hdr->smprate_fact = (int)( ((v_uword << 8) & 0xff00) |
3188                ((v_uword >> 8) & 0x00ff) );
3189
3190        v_uword = (UWORD)(hdr->smprate_mult);
3191        hdr->smprate_mult = (int)( ((v_uword << 8) & 0xff00) |
3192                ((v_uword >> 8) & 0x00ff) );
3193
3194        v_long = hdr->timecorr;
3195        hdr->timecorr =  (INT32)(((UINT32)v_long & 0x000000ffL) * (UINT32)0x1000000L);
3196        hdr->timecorr += (INT32)(((UINT32)v_long & 0x0000ff00L) * (UINT32)0x100L);
3197        hdr->timecorr += (INT32)(((UINT32)v_long & 0x00ff0000L) >> (UINT32)8L);
3198        hdr->timecorr += (INT32)(((UINT32)v_long & 0xff000000L) >> (UINT32)24L);
3199
3200        v_uword = hdr->databegin;
3201        hdr->databegin = (v_uword & 0xff) * 0x100;
3202        hdr->databegin += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3203
3204        /* swap pointer to first blockette and store unswapped value */
3205        next_block = 0;
3206        v_uword = hdr->first;
3207        if  (v_uword >= 48 && v_uword < 64)  next_block = v_uword;
3208        hdr->first = (v_uword & 0xff) * 0x100;
3209        hdr->first += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3210        if  (hdr->first >= 48 && hdr->first < 64)  next_block = hdr->first;
3211
3212        /* if a pointer > 0 was found swap type and nextblock entry of this blockette */
3213        while  (next_block > 0)  {
3214                b1000 = (SeedBlockette1000T *)((char *)hdr + (unsigned)(next_block));
3215                next_block = 0;
3216                /* check for blockette 1000 and 1001 */
3217                if  (b1000->type == 1000)  b1000->type = 0xe803;
3218                else if  (b1000->type == 1001)  b1000->type = 0xe903;
3219                else if  (b1000->type == 0xe803)  b1000->type = 1000;
3220                else if  (b1000->type == 0xe903)  b1000->type = 1001;
3221                /* swap pointer to next blockette and store pointer value */
3222                v_uword = b1000->nextblock;
3223                if  (v_uword >= 48 && v_uword < 64)  next_block = v_uword;
3224                b1000->nextblock = (v_uword & 0xff) * 0x100;
3225                b1000->nextblock += (UWORD)(v_uword & 0xff00) / (UWORD)0x100;
3226                if  ((b1000->nextblock) >= 48 && (b1000->nextblock) < 64)
3227                        next_block = b1000->nextblock;
3228        } /*endif*/
3229
3230} /* end of SeedSwapHeader */
3231
3232
3233
3234/*---------------------------------------------------------------------*/
3235
3236
3237
3238void SeedCloseFiles( void )
3239
3240/* closes all open SEED files
3241 *
3242 * no parameters
3243 */
3244{
3245        /* local variables */
3246        int      i;         /* counter */
3247
3248        /* executable code */
3249
3250        for  (i=0; i<Seed_C_MAXCHAN; i++)
3251                if  (seedv_fd[i].ufd != Seed_C_ILLEGAL)  {
3252                        close( seedv_fd[i].ufd );
3253                        seedv_fd[i].ufd = Seed_C_ILLEGAL;
3254                } /*endif*/
3255
3256} /* end of SeedCloseFiles */
3257
3258
3259
3260/*---------------------------------------------------------------------*/
3261
3262
3263
3264static void SeedAdjustFilename( SeedFileDescrT *dsc, STATUS *status )
3265
3266/* copies directory of sfd-file to data filename
3267 *
3268 * parameters of routine
3269 * SeedFileDescrT  *dsc;        modify; SEED file descriptor
3270 * STATUS          *status;     output; return status
3271 */
3272{
3273        /* local variables */
3274        int      i;                      /* counter */
3275        int      strlth;                 /* string length */
3276        char     path[BC_FILELTH+1];     /* path name */
3277        BOOLEAN  iscolon;                /* is there a colon ? */
3278        char     upname[cBcFileLth+1];   /* uppercase filename */
3279
3280        /* executable code */
3281
3282        /* find path in sfdfile */
3283        i = strlen( dsc->sfdfile ) - 1;
3284        while  (i >= 0 && dsc->sfdfile[i] != '/' && dsc->sfdfile[i] != ':'
3285                && dsc->sfdfile[i] != '\\')  i--;
3286        if  (i > 0)  {
3287                strncpy( path, dsc->sfdfile, i );
3288                path[i] = '\0';
3289                iscolon = (dsc->sfdfile[i] == ':');
3290        } else {
3291                *path = '\0';
3292                iscolon = FALSE;
3293        } /*endif*/
3294
3295        if  (strlen(dsc->name)-ROOTDIRLTH+strlen(path) > BC_FILELTH)  {
3296                *status = SeedERR_STROVFL;
3297                return;
3298        } /*endif*/
3299
3300        if  (*path != '\0')  {
3301                strlth = strlen( path );
3302                for  (i=0; i<strlth; i++)
3303                        if  (path[i] == '\\')  path[i] = '/';
3304                if  (iscolon)  {
3305                        strcat( path, ":" );
3306                        if  (seedv_capfiles)  {
3307                                strcpy( upname, dsc->name+ROOTDIRLTH+1 );
3308                                ut_cap( upname );
3309                                strcat( path, upname );
3310                        } else {
3311                                strcat( path, dsc->name+ROOTDIRLTH+1 );
3312                        } /*endif*/
3313                } else {
3314                        if  (seedv_capfiles)  {
3315                                strcpy( upname, dsc->name+ROOTDIRLTH );
3316                                ut_cap( upname );
3317                                strcat( path, upname );
3318                        } else {
3319                                strcat( path, dsc->name+ROOTDIRLTH );
3320                        } /*endif*/
3321                } /*endif*/
3322        } else {
3323                strcpy( path, dsc->name+ROOTDIRLTH+1 );
3324        } /*endif*/
3325        strcpy( dsc->name, path );
3326
3327} /* end of SeedAdjustFilename */
3328
3329
3330
3331/*---------------------------------------------------------------------*/
3332
3333
3334static void SeedLibWarning( char text[] )
3335
3336/* prints warning messages
3337 *
3338 * parameters of routine
3339 * char       text[];      input; output text
3340 */
3341{
3342        /* local variables */
3343        char     str[cBcLineLth+1];    /* output string */
3344        int      i;                    /* counter */
3345
3346        /* executable code */
3347
3348        if  (!seedv_warnings)  return;
3349
3350#ifdef XXX
3351        i = 0;
3352        while  (i < cBcLineLth && text[i] != '\0')  {
3353                if  ((text[i] >= ' ' && text[i] <= 'z') || text[i] == '\n')  {
3354                        str[i] = text[i];
3355                } else {
3356                        str[i] = '.';
3357                } /*endif*/
3358                i++;
3359        } /*endwhile*/
3360        str[i] = '\0';
3361
3362        fprintf( stderr, "%s", str );
3363#endif
3364        fprintf( stderr, "%s", text );
3365
3366} /* end of SeedLibWarning */
3367
3368
3369
3370/*---------------------------------------------------------------------*/
3371
3372
3373
3374void SeedPrintWarnings( BOOLEAN on_off )
3375
3376/* switches warning messages on or off
3377 *
3378 * parameters of routine
3379 * BOOLEAN    on_off;       input; switch
3380 */
3381{
3382        /* executable code */
3383
3384        seedv_warnings = on_off;
3385
3386} /* end of SeedPrintWarnings */
3387
3388
3389
3390/*---------------------------------------------------------------------*/
3391
3392
3393
3394void SeedAcceptCapfiles( BOOLEAN on_off )
3395
3396/* switches on/off whether capitalized filenames on $ROOT-paths are accepted
3397 *
3398 * parameters of routine
3399 * BOOLEAN    on_off;       input; switch
3400 */
3401{
3402        /* executable code */
3403
3404        seedv_capfiles = on_off;
3405
3406} /* end of SeedPrintWarnings */
3407
3408
3409
3410/*---------------------------------------------------------------------*/
3411
3412
3413
3414BOOLEAN SeedSetInvertSwapHeader( BOOLEAN on_off )
3415
3416/* Sets the global variable seedv_invert_swap_hdr to invert header swap
3417 * info in sfd-file.  Returns old value.
3418 *
3419 * parameters of routine
3420 * BOOLEAN    on_off;    input; switch value
3421 */
3422{
3423        /* local variables */
3424        BOOLEAN  old;
3425
3426        /* executable code */
3427
3428        old = seedv_invert_swap_hdr;
3429        seedv_invert_swap_hdr = on_off;
3430        return old;
3431
3432} /* end of SeedSetInvertSwapHeader */
3433
3434
3435
3436/*---------------------------------------------------------------------*/
3437
3438
3439
3440BOOLEAN SeedSetDecodeErrorAbort( BOOLEAN on_off )
3441
3442/* Sets the global value seedv_decerr_abort (abort on occurrence of
3443 * SEED decoding errors.  Returns old value.
3444 *
3445 * parameters of routine
3446 * BOOLEAN    on_off;        input; switch value
3447 */
3448{
3449        /* local variables */
3450        BOOLEAN  old;        /* old value */
3451
3452        /* executable code */
3453
3454        old = seedv_decerr_abort;
3455        seedv_decerr_abort = on_off;
3456        return old;
3457
3458} /* end of SeedSetDecodeErrorAbort */
3459
3460
3461
3462/*---------------------------------------------------------------------*/
3463
3464
3465
3466BOOLEAN SeedUseTimeCorrection( BOOLEAN on_off )
3467
3468/* Sets the global value seedv_use_timecorr (use timec orrection field
3469 * within SEED data records).  Returns old value.
3470 *
3471 * parameters of routine
3472 * BOOLEAN    on_off;        input; switch value
3473 */
3474{
3475        /* local variables */
3476        BOOLEAN  old;        /* old value */
3477
3478        /* executable code */
3479
3480        old = seedv_use_timecorr;
3481        seedv_use_timecorr = on_off;
3482        return old;
3483
3484} /* end of SeedUseTimeCorrection */
3485
3486
3487
3488/*---------------------------------------------------------------------*/
3489
3490
3491
3492void SeedCutStartRecord( SeedSbyteT *seedrec, char extime[], BOOLEAN swap,
3493        STATUS *status )
3494
3495/* Throws away the first samples in record until given time
3496 *
3497 * parameters of routine
3498 * char       *seedrec;         modify; SEED record to cut
3499 * char       extime[];         input; exact time
3500 * BOOLEAN    swap;             input; swap bytes ?
3501 * STATUS     *status;          output; return status
3502 */
3503{
3504        /* local variables */
3505        SeedDataHeaderT *hdrptr;   /* pointer to data header */
3506        SeedDataHeaderT *outrec;   /* output records */
3507        SeedDataHeaderT tmphdr;    /* temp store */
3508        float    dt;               /* sample rate */
3509        NTIME    rstart, rend;     /* record start and end times */
3510        NTIME    ntime;            /* numeric exact time */
3511        float    tdiff;            /* time difference in sec */
3512        int      cutlth;           /* number of samples to cut */
3513        INT32    smp[MAX_SMP_PER_REC]; /* space for decoded samples */
3514        INT32    smplth;           /* number of sample decoded */
3515        int      i;                /* counter */
3516        int      recs_used;        /* records used for encoding (should be 1) */
3517        int      reclth;           /* record length */
3518
3519        /* executable code */
3520
3521        /* retrieve header information needed here */
3522        hdrptr = (SeedDataHeaderT *)seedrec;
3523        dt = SeedGetSampleDist( hdrptr );
3524        reclth = SeedGetReclth( hdrptr, FALSE );
3525        SeedRecordTime( seedrec, &rstart, &rend, status );
3526        if  (SySevere(status))  return;
3527        tc_t2n( extime, &ntime, status );
3528        if  (SySevere(status))  return;
3529        tdiff = tc_ndiff( &ntime, &rstart, status );
3530        if  (SySevere(status))  return;
3531        cutlth = Nint( tdiff / dt );
3532        if  (cutlth > (int)(hdrptr->no_of_samples))  {
3533                *status = SeedERR_ILLCUT;
3534                return;
3535        } else if  (cutlth == (int)(hdrptr->no_of_samples))  {
3536                hdrptr->no_of_samples = 0;
3537                return;
3538        } else if  (cutlth <= 0)  {
3539                /* nothing to be done */
3540                return;
3541        } /*endif*/
3542
3543        /* decode record */
3544        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
3545        SeedDecodeSteim1( seedrec, swap, MAX_SMP_PER_REC, smp, &smplth );
3546        if  (smplth != (INT32)(hdrptr->no_of_samples))  {
3547                *status = SeedERR_DECODE_ERR;
3548                return;
3549        } /*endif*/
3550
3551        /* throw away cutlth samples from the beginning */
3552        for  (i=cutlth; i<(int)smplth; i++)
3553                smp[i-cutlth] = smp[i];
3554        smplth -= (INT32)cutlth;
3555        tdiff = (float)cutlth * dt;
3556        tc_nadd( &rstart, tdiff, &rstart, status );
3557        if  (SySevere(status))  return;
3558
3559        /* prepare changed record */
3560        outrec = (SeedDataHeaderT *)sy_allocmem( 2, reclth, status );
3561        /* get two records; need only one but who knows ... */
3562        hdrptr->no_of_samples = (UWORD)smplth;
3563        SeedNtimeToBtime( &rstart, &(hdrptr->starttime), status );
3564        if  (SySevere(status))  {
3565                sy_deallocmem( outrec );
3566                return;
3567        } /*endif*/
3568        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)hdrptr, (UINT32)smplth,
3569                (WORD)(reclth), (INT32 *)outrec, 0 /*prev.smp*/ );
3570        if  (recs_used != 1)  {
3571                *status = SeedERR_BUG;
3572                sy_deallocmem( outrec );
3573                return;
3574        } /*endif*/
3575        /* copy result to output record and keep header */
3576        tmphdr = *hdrptr;
3577        memcpy( (char *)seedrec, (char *)outrec, reclth );
3578        SeedStoreReclth( (SeedDataHeaderT *)seedrec, reclth );
3579        *hdrptr = tmphdr;
3580        sy_deallocmem( outrec );
3581
3582} /* end of SeedCutStartRecord */
3583
3584
3585
3586/*---------------------------------------------------------------------*/
3587
3588
3589
3590void SeedCutEndRecord( SeedSbyteT *seedrec, char extime[], BOOLEAN swap,
3591        STATUS *status )
3592
3593/* Throws away the first samples in record until given time
3594 *
3595 * parameters of routine
3596 * char       *seedrec;         modify; SEED record to cut
3597 * char       extime[];         input; exact time
3598 * BOOLEAN    swap;             input; swap bytes ?
3599 * STATUS     *status;          output; return status
3600 */
3601{
3602        /* local variables */
3603        SeedDataHeaderT *hdrptr;   /* pointer to data header */
3604        SeedDataHeaderT *outrec;   /* output records */
3605        SeedDataHeaderT tmphdr;    /* temp store */
3606        float    dt;               /* sample rate */
3607        NTIME    rstart, rend;     /* record start and end times */
3608        NTIME    ntime;            /* numeric exact time */
3609        float    tdiff;            /* time difference in sec */
3610        int      cutlth;           /* number of samples to cut */
3611        INT32    smp[MAX_SMP_PER_REC]; /* space for decoded samples */
3612        INT32    smplth;           /* number of sample decoded */
3613        int      i;                /* counter */
3614        int      recs_used;        /* records used for encoding (should be 1) */
3615        int      reclth;           /* record length */
3616
3617        /* executable code */
3618
3619        /* retrieve header information needed here */
3620        hdrptr = (SeedDataHeaderT *)seedrec;
3621        dt = SeedGetSampleDist( hdrptr );
3622        reclth = SeedGetReclth( hdrptr, FALSE );
3623        SeedRecordTime( seedrec, &rstart, &rend, status );
3624        if  (SySevere(status))  return;
3625        tc_t2n( extime, &ntime, status );
3626        if  (SySevere(status))  return;
3627        tdiff = tc_ndiff( &rend, &ntime, status );
3628        if  (SySevere(status))  return;
3629        cutlth = Nint( tdiff / dt );
3630        if  (cutlth > (int)(hdrptr->no_of_samples))  {
3631                *status = SeedERR_ILLCUT;
3632                return;
3633        } else if  (cutlth == (int)(hdrptr->no_of_samples))  {
3634                hdrptr->no_of_samples = 0;
3635                return;
3636        } else if  (cutlth <= 0)  {
3637                /* nothing to be done */
3638                return;
3639        } /*endif*/
3640
3641        /* decode record */
3642        SeedDecodeSteim1( NULL, swap, 0, NULL, NULL );
3643        SeedDecodeSteim1( seedrec, swap, MAX_SMP_PER_REC, smp, &smplth );
3644        if  (smplth != (INT32)(hdrptr->no_of_samples))  {
3645                *status = SeedERR_DECODE_ERR;
3646                return;
3647        } /*endif*/
3648
3649        /* throw away cutlth samples at the end */
3650        smplth -= (INT32)cutlth;
3651
3652        /* prepare changed record */
3653        outrec = (SeedDataHeaderT *)sy_allocmem( 2, reclth, status );
3654        /* get two records; need only one but who knows ... */
3655        hdrptr->no_of_samples = (UWORD)smplth;
3656        recs_used = (int)Steim_comp( smp, (DATA_HEADER *)hdrptr, (UINT32)smplth,
3657                (WORD)(reclth), (INT32 *)outrec, 0 /*prev.smp*/ );
3658        if  (recs_used != 1)  {
3659                *status = SeedERR_BUG;
3660                sy_deallocmem( outrec );
3661                return;
3662        } /*endif*/
3663        /* copy result to output record and keep header */
3664        tmphdr = *hdrptr;
3665        memcpy( (char *)seedrec, (char *)outrec, reclth );
3666        SeedStoreReclth( (SeedDataHeaderT *)seedrec, reclth );
3667        *hdrptr = tmphdr;
3668        sy_deallocmem( outrec );
3669
3670} /* end of SeedCutEndRecord */
3671
3672
3673
3674/*---------------------------------------------------------------------*/
3675
3676
3677
3678char *SeedGetFilename( int chan )
3679
3680/* returns name of currently opened file on channel 'chan'.  If no filename
3681 * is found, a pointer to an empty string is returned.
3682 *
3683 * parameters of routine
3684 * int        chan;        input; channel number
3685 *                         returns name of file
3686 */
3687{
3688        /* local variables */
3689        static char nullstr[2] = "";  /* null string */
3690        SeedFileDescrT *fd;   /* pointer to SEED file descriptor */
3691
3692        /* executable code */
3693
3694        /* check channel number */
3695        if  (chan < 0 || chan >= Seed_C_MAXCHAN)  return nullstr;
3696        fd = seedv_fd + chan;
3697        return ((fd->name[0] == '\0') ? seedv_last_fname : fd->name);
3698
3699} /* end of SeedGetFilename */
3700
3701
3702
3703/*---------------------------------------------------------------------*/
3704
3705
3706
3707void SeedStoreReclth( SeedDataHeaderT *rec, int reclth )
3708
3709/* Stores record length in SEED record. Uses Reserved_bytes_A for this purpose
3710 * if no blockette 1000 is available.
3711 *
3712 * parameters of routine
3713 * SeedDataHeaderT   *rec;   modify;  SEED record
3714 */
3715{
3716        /* local variables */
3717        int      num, i;        /* value and exp counter */
3718        TSyBoolean b1000;       /* blockette 1000 found */
3719        UWORD    *uw;           /* pointer to UWORD */
3720        char     *cp;           /* pointer to char */
3721        UWORD    recfirst;      /* offset to first blockette */
3722        UWORD    tmp;           /* scratch */
3723
3724        /* executable code */
3725
3726        /* determine which power of 2 */
3727        num = 1;
3728        i = 0;
3729        while  (num < reclth)  {
3730                i++;
3731                num *= 2;
3732        } /*endwhile*/
3733
3734        /* if a blockette 1000 is there use it */
3735        b1000 = TRUE;
3736        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3737        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3738
3739        if  (b1000)  {
3740                if  (rec->first > reclth)  {
3741                        tmp = rec->first;
3742                        recfirst = (tmp & 0xff) * 0x100;
3743                        recfirst += (UWORD)(tmp & 0xff00) / (UWORD)0x100;
3744                } else {
3745                        recfirst = rec->first;
3746                } /*endif*/
3747                if  (recfirst % 2 == 1)  {
3748                        SeedLibWarning(
3749                                "*** illegal 'first' entry in record (StoreReclth) ***\n" );
3750                        b1000 = FALSE;
3751                } /*endif*/
3752        } /*endif*/
3753
3754        if  (b1000)  {
3755                uw = (UWORD *)((char *)rec + (int)recfirst);
3756                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3757        } /*endif*/
3758
3759        if  (b1000)  {
3760                cp = (char *)rec + (int)recfirst + 6;
3761                *cp = (char)i;
3762        } else {
3763                rec->Reserved_bytes_A = (char)i;
3764        } /*endif*/
3765
3766} /* end of SeedStoreReclth */
3767
3768
3769
3770/*---------------------------------------------------------------------*/
3771
3772
3773
3774int SeedGetReclth( SeedDataHeaderT *rec, TSyBoolean clean )
3775
3776/* Returns SEED record length stored in record (by SeedStoreReclth)
3777 * If 'clean' is TRUE, the record length info is deleted from the record.
3778 *
3779 * parameters of routine
3780 * SeedDataHeaderT  *rec;      modify; SEED record
3781 * TSyBoolean       clean;     input; if TRUE, record length info is deleted
3782 */
3783{
3784        /* local variables */
3785        int      reclth;        /* record length */
3786        TSyBoolean b1000;       /* blockette 1000 found */
3787        UWORD    *uw;           /* pointer to UWORD */
3788        UWORD    recfirst;      /* offset to first blockette */
3789        char     *cp;           /* pointer to char */
3790        UWORD    tmp;           /* scratch */
3791
3792        /* executable code */
3793
3794        /* if a blockette 1000 is there use it */
3795        b1000 = TRUE;
3796        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3797        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3798        if  (b1000)  {
3799                if  (rec->first > (UWORD)sizeof(SeedDataHeaderT))  {
3800                        tmp = rec->first;
3801                        recfirst = (tmp & 0xff) * 0x100;
3802                        recfirst += (UWORD)(tmp & 0xff00) / (UWORD)0x100;
3803                } else {
3804                        recfirst = rec->first;
3805                } /*endif*/
3806                if  (recfirst % 2 == 1)  {
3807                        SeedLibWarning(
3808                                "*** illegal 'first' entry in record (StoreReclth) ***\n" );
3809                        b1000 = FALSE;
3810                } /*endif*/
3811        } /*endif*/
3812        if  (b1000)  {
3813                uw = (UWORD *)((char *)rec + (int)(recfirst));
3814                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3815        } /*endif*/
3816
3817        if  (b1000)  {
3818                cp = (char *)rec + (int)(recfirst) + 6;
3819                reclth = (*cp);
3820                reclth = (1 << reclth);
3821        } else {
3822                if  (rec->Reserved_bytes_A == '\0' || rec->Reserved_bytes_A == ' ')  {
3823                        fprintf( stderr,
3824                                "SeedGetReclth: no record length found in record. Abort.\n" );
3825                        exit( 1 );
3826                } /*endif*/
3827                reclth = (1 << (int)(rec->Reserved_bytes_A));
3828                if (clean)  rec->Reserved_bytes_A = ' ';
3829        } /*endif*/
3830
3831        return reclth;
3832
3833} /* end of SeedGetReclth */
3834
3835
3836
3837/*---------------------------------------------------------------------*/
3838
3839
3840
3841int SeedGetCompression( SeedDataHeaderT *rec )
3842
3843/* Returns compression algorithm ID if blockette 1000 is found,
3844 * otherwise 0.
3845 *
3846 * parameters of routine
3847 * SeedDataHeaderT  *rec;      input; SEED record
3848 */
3849{
3850        /* local variables */
3851        TSyBoolean b1000;       /* blockette 1000 found */
3852        UWORD    *uw;           /* pointer to UWORD */
3853        char     *cp;           /* pointer to char */
3854
3855        /* executable code */
3856
3857        /* if a blockette 1000 is there use it */
3858        b1000 = TRUE;
3859        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3860        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3861        if  (rec->first % 2 == 1)  {
3862                SeedLibWarning(
3863                        "*** illegal 'first' entry in record (GetCompression) ***\n" );
3864                return 0;
3865        } /*endif*/
3866        if  (b1000)  {
3867                uw = (UWORD *)((char *)rec + (int)(rec->first));
3868                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3869        } /*endif*/
3870        if  (!b1000)  return 0;
3871
3872        cp = (char *)rec + (int)(rec->first) + 4;
3873        return (int)(*cp);
3874
3875} /* end of SeedGetCompression */
3876
3877
3878
3879/*---------------------------------------------------------------------*/
3880
3881
3882
3883int SeedGetTimequal( SeedDataHeaderT *rec )
3884
3885/* Returns time quality or -1
3886 *
3887 * parameters of routine
3888 * SeedDataHeaderT   *rec;
3889 */
3890{
3891        /* local variables */
3892        SeedBlockette1001T *b1001;       /* blockette 1001 */
3893
3894        /* executable code */
3895
3896        if  (rec->no_of_blockettes <= 0)  return (-1);
3897
3898        b1001 = (SeedBlockette1001T *)((char *)rec + (unsigned)(rec->first));
3899        if  (b1001->type == 1001)  return (int)(b1001->timequal);
3900        if  (rec->no_of_blockettes == 1)  return (-1);
3901        b1001 = (SeedBlockette1001T *)((char *)rec + (unsigned)(b1001->nextblock));
3902        if  (b1001->type == 1001)  return (int)(b1001->timequal);
3903        return (-1);
3904        /* not more than 2 blockettes checked, should implement loop */
3905
3906} /* end of SeedGetTimequal */
3907
3908
3909
3910/*---------------------------------------------------------------------*/
3911
3912
3913
3914int SeedGetWordOrder( SeedDataHeaderT *rec )
3915
3916/* Returns word order ID if blockette 1000 is found,
3917 * otherwise 1 (=Sparc).
3918 *
3919 * parameters of routine
3920 * SeedDataHeaderT  *rec;      input; SEED record
3921 */
3922{
3923        /* local variables */
3924        TSyBoolean b1000;       /* blockette 1000 found */
3925        UWORD    *uw;           /* pointer to UWORD */
3926        char     *cp;           /* pointer to char */
3927
3928        /* executable code */
3929
3930        /* if a blockette 1000 is there use it */
3931        b1000 = TRUE;
3932        if  (rec->no_of_blockettes == 0)  b1000 = FALSE;
3933        if  (b1000 && rec->first == 0)  b1000 = FALSE;
3934        if  (rec->first % 2 == 1)  {
3935                SeedLibWarning( "*** illegal 'first' entry in record ***\n" );
3936                return 1;
3937        } /*endif*/
3938        if  (b1000)  {
3939                uw = (UWORD *)((char *)rec + (int)(rec->first));
3940                if  (*uw != 1000 && *uw != 59395)  b1000 = FALSE;
3941        } /*endif*/
3942        if  (!b1000)  return 1;  /* Sparc word order is default */
3943
3944        cp = (char *)rec + (int)(rec->first) + 5;
3945        return (int)(*cp);
3946
3947} /* end of SeedGetWordOrder */
3948
3949
3950
3951/*---------------------------------------------------------------------*/
3952
3953
3954
3955void SeedSetOutputReclth( int reclth )
3956
3957/* Sets size of SEED output records (default is 4096, if not called)
3958 *
3959 * parameters of routine
3960 * int        reclth;       input; size of output records in bytes
3961 */
3962{
3963        /* executable code */
3964
3965        seedv_out_reclth = reclth;
3966
3967} /* end of SeedSetOutputReclth */
3968
3969
3970
3971/*----------------------------------------------------------------------------*/
3972
3973
3974
3975void SeedSetNextTimequal( int tq )
3976
3977/* Sets time quality for next Steim output record
3978 *
3979 * parameters of routine
3980 * int        tq;         input; time quality
3981 */
3982{
3983        /* executable code */
3984
3985        seedv_timequal = tq;
3986
3987} /* end of SeedSetNextTimequal */
3988
3989
3990
3991/*----------------------------------------------------------------------------*/
3992
3993
3994#define IDOFFSET 6
3995#define DATCHARS "DQR"
3996
3997
3998void SeedQuickFindReclth( FILE *fp, int *recsize, int *byteoff )
3999
4000/* Returns record size in bytes or 0 and the byte offset where data records
4001 * start.
4002 *
4003 * parameters of routine
4004 * FILE          *fp;          input; input file already opened
4005 * int           *recsize;     output; record size found
4006 * int           *byteoff;     output; byte offset found
4007 */
4008{
4009        /* local variables */
4010        char     id1, id2;  /* ID chars */
4011        TSyBoolean isdigit1, isdigit2; /* is number string */
4012        int      i;         /* counter */
4013
4014        /* executable code */
4015
4016        *recsize = 0;
4017        *byteoff = 0;
4018        isdigit1 = isdigit2 = TRUE;
4019
4020        /* position file and read number string and ID */
4021        fseek( fp, 0, 0 );
4022        for  (i=0; i<IDOFFSET; i++)  {
4023                id1 = getc( fp );
4024                if  (id1 < '0' || id1 > '9')  isdigit1 = FALSE;
4025        } /*endfor*/
4026        id1 = getc( fp );
4027        fseek( fp, 512, 0 );
4028        for  (i=0; i<IDOFFSET; i++)  {
4029                id2 = getc( fp );
4030                if  (id2 < '0' || id2 > '9')  isdigit2 = FALSE;
4031        } /*endfor*/
4032        id2 = getc( fp );
4033        if  (id1 == EOF || isdigit1 == FALSE)  {
4034                /* no SEED file, leave recsize zero */
4035        } else if  (strchr(DATCHARS,id1) != NULL && strchr(DATCHARS,id2) == NULL)  {
4036                /* definitely not 512 */
4037                *recsize = 4096;
4038                *byteoff = 0;
4039        } else if  (id1 == 'V' && strchr(DATCHARS,id2) != NULL && isdigit2 == TRUE)  {
4040                /* very likely 512 */
4041                *recsize = 512;
4042                *byteoff = 512;
4043        } else if  (isdigit2 == FALSE)  {
4044                *recsize = 4096;
4045                *byteoff = 0;  /* this is a guess */
4046        } else if  (strchr(DATCHARS,id1) != NULL && strchr(DATCHARS,id2) != NULL)  {
4047                *byteoff = 0;
4048                fseek( fp, 1024+IDOFFSET, 0 );
4049                id1 = getc( fp );
4050                fseek( fp, 1024+512+IDOFFSET, 0 );
4051                id2 = getc( fp );
4052                if  (strchr(DATCHARS,id1) != NULL && strchr(DATCHARS,id2) != NULL)  {
4053                        *recsize = 512;
4054                } else if  (strchr(DATCHARS,id1) != NULL && id2 == EOF)  {
4055                        *recsize = 512;
4056                } else if  (id1 == EOF)  {
4057                        *recsize = 512;
4058                } else {
4059                        *recsize = 4096;
4060                } /*endfif*/
4061        } else {
4062                /* cannot determine */
4063                *recsize = -1;
4064        } /*endif*/
4065
4066        /* rewind file */
4067        fseek( fp, 0, 0 );
4068
4069} /* end of SeedQuickFindReclth */
4070
4071
4072
4073/*---------------------------------------------------------------------*/
4074
4075
4076
4077static void SeedSwapLinuxRecord( SeedSbyteT *rec, int reclth )
4078
4079
4080/* Modifies record for writing on Linux system
4081 *
4082 * parameters of routine
4083 * SeedSbyteT *rec;                modify; SEED record
4084 * int        reclth;              input; record length, if 0 found by SeedGetReclth
4085 */
4086{
4087        /* local variables */
4088        SeedSbyteT     *ptr;                /* moving pointer */
4089        SeedSbyteT     tmp;                 /* scratch */
4090
4091        /* executable code */
4092
4093        if  (reclth == 0)
4094                reclth = SeedGetReclth( (SeedDataHeaderT *)rec, FALSE );
4095
4096        for  (ptr = rec+Seed_C_FRAMELTH; ptr < rec+reclth;
4097                ptr += 4)  {
4098                /* flip 0 and 3 */
4099                tmp = ptr[0];  ptr[0] = ptr[3];  ptr[3] = tmp;
4100                /* flip 1 and 2 */
4101                tmp = ptr[1];  ptr[1] = ptr[2];  ptr[2] = tmp;
4102        } /*endfor*/
4103
4104} /* end of SeedSwapLinuxRecord */
4105
4106
4107
4108/*---------------------------------------------------------------------*/
4109
4110
4111
4112static void SeedSplitStreamName( char inpname[], char outname[],
4113        char station[], char addinf[] )
4114
4115/* Splits extended stream name (e.g. anmo.iu00-bh-z) into standard stream
4116 * name (e.g. anmo-bh-z) and addinfo string (iu00).  Minimum output length
4117 * of addinf is Seed_C_AddinfLth+1.
4118 *
4119 * parameters of routine
4120 * char       inpname[];     input; extended stream name
4121 * char       outname[];     output; standard stream name
4122 * char       station[];     output; station name
4123 * char       addinf[];      output; addinfo string
4124 */
4125{
4126        /* local variables */
4127        int      i, j, k;         /* counter */
4128        int      slen;            /* length of stream string */
4129        TSyBoolean add;           /* addinfo string */
4130        TSyBoolean first;         /* first point */
4131        TSyBoolean isstat;        /* station part */
4132
4133        /* executable code */
4134
4135        /* default addinf */
4136        strcpy( addinf, Seed_C_EmptyAddinfStr );
4137        *station = '\0';
4138
4139        first = TRUE;
4140        slen = strlen( inpname );
4141        j = k = 0;
4142        add = FALSE;
4143        isstat = TRUE;
4144        for  (i=0; i<slen; i++)  {
4145                if  (inpname[i] == '.' && first)  {
4146                        add = TRUE;
4147                        first = FALSE;
4148                        if  (isstat)  {
4149                                station[i] = '\0';
4150                                isstat = FALSE;
4151                        } /*endif*/
4152                } else if  (inpname[i] == '-')  {
4153                        add = FALSE;
4154                        outname[k++] = inpname[i];
4155                        if  (isstat)  {
4156                                station[i] = '\0';
4157                                isstat = FALSE;
4158                        } /*endif*/
4159                } else {
4160                        if  (isstat)  station[i] = Uncap( inpname[i] );
4161                        if  (add && j < Seed_C_AddinfLth)  {
4162                                addinf[j++] = Uncap( inpname[i] );
4163                        } else {
4164                                outname[k++] = inpname[i];
4165                        } /*endif*/
4166                } /*endif*/
4167        } /*endfor*/
4168
4169        outname[k] = '\0';
4170
4171        /*printf( "--> %s -> %s,%s\n", inpname, outname, addinf );*/
4172
4173} /* end of SeedSplitStreamName */
4174
4175
4176/*---------------------------------------------------------------------*/
4177
4178
4179
4180void SeedTranslateChan( char station[], char inchan[], char outchan[] )
4181
4182/* Translates channel name, e.g. '++' depending on station name
4183 *
4184 * parameters of routine
4185 * char       station[];    input; station name, e.g. 'bfo'
4186 * char       inchan[];     input; channel name (length 2+term), e.g. '++'
4187 * char       outchan[];    output; translated name (length 2 + term)
4188 */
4189{
4190        /* local variables */
4191        int      pathcnt;                      /* path counter (to transl. files) */
4192        char     *transpath;                   /* name of translation file */
4193        FILE     *fp;                          /* pointer to file */
4194        char     fstr[cBcLineLth+1];           /* station+chan name */
4195        int      fstrlen;                      /* length of fstr */
4196        char     dstr[cBcLineLth+1];           /* default station+chan name */
4197        int      dstrlen;                      /* length of dstr */
4198        char     line[cBcLineLth+1];           /* current line of file */
4199        char     *cptr;                        /* moving pointer */
4200        char     defchan[cBcShortStrLth+1];    /* default channel */
4201        TSyBoolean default_found;              /* default string found */
4202
4203        /* executable code */
4204
4205        strcpy( outchan, inchan );
4206        default_found = FALSE;
4207
4208        /* skip this of no special channel given */
4209        if  (strcmp(inchan,"++") != 0)
4210                return;
4211
4212        /* prepare search strings */
4213        if  (strlen(station)+3 > cBcLineLth)  {
4214                printf( "*Seed: station name too long.  Cannot translate chan\n" );
4215                return;
4216        } /*endif*/
4217        /* get string to search in file (station-inchan) */
4218        sprintf( fstr, "%s-%s", station, inchan );
4219        ut_uncap( fstr );
4220        fstrlen = strlen( fstr );
4221        /* default setting is also needed (*-inchan) */
4222        sprintf( dstr, "*-%s", inchan );
4223        ut_uncap( dstr );
4224        dstrlen = strlen( dstr );
4225
4226        for  (pathcnt=0;;pathcnt++)  {
4227                transpath = GpGetStringElem( cGpL_channel_translation, pathcnt );
4228                if  (transpath == NULL)  break;
4229                fp = fopen( transpath, "r" );
4230                if  (fp == NULL)
4231                        continue;
4232                while (fgets(line,cBcLineLth,fp) != NULL)  {
4233                        if  (strncmp(line,fstr,fstrlen) == 0)  {
4234                                /* found entry for this station, read it and return */
4235                                cptr = line+fstrlen;
4236                                while  (*cptr == ' ' || *cptr == ':')
4237                                        cptr++;
4238                                outchan[0] = (cptr[0] > ' ') ? cptr[0] : '\0';
4239                                outchan[1] = (cptr[1] > ' ') ? cptr[1] : '\0';
4240                                outchan[2] = '\0';
4241                                fclose( fp );
4242                                return;
4243                        }  else if  (strncmp(line,dstr,dstrlen) == 0)  {
4244                                /* found at least a default entry, save this */
4245                                cptr = line+dstrlen;
4246                                while  (*cptr == ' ' || *cptr == ':')
4247                                        cptr++;
4248                                defchan[0] = (cptr[0] > ' ') ? cptr[0] : '\0';
4249                                defchan[1] = (cptr[1] > ' ') ? cptr[1] : '\0';
4250                                defchan[2] = '\0';
4251                                default_found = TRUE;
4252                        } /*endif*/
4253                } /*endwhile*/
4254                fclose( fp );
4255        } /*endif*/
4256
4257        if  (default_found)
4258                strcpy( outchan, defchan );
4259
4260} /* end of SeedTranslateChan */
4261
4262
4263
4264/*---------------------------------------------------------------------*/
4265
4266
4267
4268/* FORTRAN interface routine */
4269
4270
4271void SeedReadStreamReal_( int chan, char sfdfile[], char stream_str[],
4272        BOOLEAN swap, char req_start[], float seclth, float **fdat,
4273        INT32 *smplth, char act_start[], float *dt, float *calib,
4274        int *flags, STATUS *status )
4275{
4276
4277        SeedReadStreamReal( chan, sfdfile, stream_str, swap, req_start,
4278                seclth, fdat, smplth, act_start, dt, calib, flags, status );
4279
4280} /* end of SeedReadStreamReal_ */
4281
4282
4283void SeedLibInitialize_( STATUS *status )
4284{
4285
4286        SeedLibInitialize( status );
4287
4288} /* end of SeedLibInitialize_ */
4289
4290
4291void SeedSetup_( STATUS *status )
4292{
4293        static SeedSetupParT setup;
4294
4295        SeedSetup( &setup, status );
4296
4297} /* end of SeedSetup_ */
4298
4299
4300/*---------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.