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

Revision 45, 129.4 KB checked in by marcus, 14 years ago (diff)

r30 | svn | 2008-02-23 23:36:22 +0100 (Sa, 23 Feb 2008) | 1 line

read output file of ingres database

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