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

Revision 302, 133.2 KB checked in by marcus, 12 years ago (diff)

r144 | klaus | 2010-12-21 11:08:28 +0100 (Di, 21 Dez 2010) | 1 line

implemented endless loop preventer in SeedReadStream?: ill data files could lead to endless loops via SeedReadNextReccord? always reading the same record or looping the same sequence of records

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