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

Revision 499, 114.2 KB checked in by marcus, 11 years ago (diff)

r260 | walther | 2011-11-24 17:04:40 +0100 (Do, 24. Nov 2011) | 1 Zeile

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