1 | |
---|
2 | /* file gcflib.c |
---|
3 | * ======== |
---|
4 | * |
---|
5 | * version 5, 5-Nov-2006 |
---|
6 | * |
---|
7 | * interface for GCF data |
---|
8 | * K. Stammler, 18-Oct-2003 |
---|
9 | */ |
---|
10 | |
---|
11 | |
---|
12 | #include <stdio.h> |
---|
13 | #include <string.h> |
---|
14 | #include "basecnst.h" |
---|
15 | #ifdef BC_INC_STDLIB |
---|
16 | #include BC_INC_STDLIB |
---|
17 | #endif |
---|
18 | #include "sysbase.h" |
---|
19 | #include "tcusrdef.h" |
---|
20 | #include "gcflib.h" |
---|
21 | #include "../seed_io/seedcfg.h" |
---|
22 | #include "../seed_io/seed_lib.h" |
---|
23 | |
---|
24 | #define GcfMAXTAP 20 |
---|
25 | #define DEFAULT_BLKLTH 1024 |
---|
26 | #define ROOTDIR "$ROOT" |
---|
27 | #define ROOTDIRLTH 5 |
---|
28 | #define MAX_SMP_PER_BLK 5000 |
---|
29 | |
---|
30 | /* global variables */ |
---|
31 | static int gcfv_byteorder[4] = { 0, 1, 2, 3 }; /* 4byte order */ |
---|
32 | static TSyBoolean gcfv_capfiles=FALSE; /* capitalized filenames in gfd */ |
---|
33 | static GcfFileDescrT gcfv_fd[Gcf_C_MAXCHAN]; /* file descriptors */ |
---|
34 | static TSyBoolean gcfv_logrec=FALSE; |
---|
35 | static char gcfv_last_fname[cBcFileLth+1]; /* last file read */ |
---|
36 | |
---|
37 | /* default list for translation of tap numbers into channel names: */ |
---|
38 | static char gcfv_tapcode[GcfMAXTAP][GcfCHAN_LENGTH+1] = { |
---|
39 | "HH", "HH", "HH", "BH", "BH", "BH", "LH", "LH", "LH", "UH", |
---|
40 | "VH", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9" |
---|
41 | }; |
---|
42 | |
---|
43 | |
---|
44 | /* prototypes of local routines */ |
---|
45 | static TSyBoolean GcfIsLeapYear( int year ); |
---|
46 | static void GcfAdjustFilename( GcfFileDescrT *dsc, TSyStatus *status ); |
---|
47 | |
---|
48 | |
---|
49 | |
---|
50 | /*----------------------------------------------------------------------------*/ |
---|
51 | |
---|
52 | |
---|
53 | |
---|
54 | void GcfSetByteorder( char byteorder[], TSyStatus *status ) |
---|
55 | |
---|
56 | /* Sets byte order. Bytes are counted from 1 to 4, Legal strings are |
---|
57 | * e.g. "1234" or "2143". |
---|
58 | * |
---|
59 | * parameters of routine |
---|
60 | * char byteorder[]; input; byte order string of length 4 (+term char) |
---|
61 | * TSyStatus *status; output; return status |
---|
62 | */ |
---|
63 | { |
---|
64 | /* local variables */ |
---|
65 | int chk[4]; /* check occurence of all numbers */ |
---|
66 | int bo[4]; /* new byteorder */ |
---|
67 | int i; /* counter */ |
---|
68 | |
---|
69 | /* executable code */ |
---|
70 | |
---|
71 | if (strlen(byteorder) != 4) { |
---|
72 | *status = GcfERR_ILLBYTEORDER; |
---|
73 | return; |
---|
74 | } /*endif*/ |
---|
75 | |
---|
76 | /* reset check array */ |
---|
77 | for (i=0; i<4; i++) chk[i] = 0; |
---|
78 | |
---|
79 | for (i=0; i<4; i++) { |
---|
80 | |
---|
81 | if (byteorder[i] < '1' || byteorder[i] > '4') { |
---|
82 | *status = GcfERR_ILLBYTEORDER; |
---|
83 | return; |
---|
84 | } /*endif*/ |
---|
85 | |
---|
86 | bo[i] = byteorder[i] - '1'; |
---|
87 | chk[bo[i]] = 1; |
---|
88 | |
---|
89 | } /*endif*/ |
---|
90 | |
---|
91 | /* check wether all numbers specified */ |
---|
92 | for (i=0; i<4; i++) |
---|
93 | if (chk[i] != 1) { |
---|
94 | *status = GcfERR_ILLBYTEORDER; |
---|
95 | return; |
---|
96 | } /*endif*/ |
---|
97 | |
---|
98 | /* copy new byteorder to global variable */ |
---|
99 | for (i=0; i<4; i++) |
---|
100 | gcfv_byteorder[i] = byteorder[i]; |
---|
101 | |
---|
102 | } /* end of GcfSetByteorder */ |
---|
103 | |
---|
104 | |
---|
105 | |
---|
106 | /*----------------------------------------------------------------------------*/ |
---|
107 | |
---|
108 | |
---|
109 | |
---|
110 | void GcfSetTapcode( int tapnum, char chan[], TSyStatus *status ) |
---|
111 | |
---|
112 | /* sets tap code, i.e. mapping from tap number to channel name |
---|
113 | * |
---|
114 | * parameters of routine |
---|
115 | * int tapnum; tap number to be set |
---|
116 | * char chan[]; 2 char channel code |
---|
117 | */ |
---|
118 | { |
---|
119 | /* executable code */ |
---|
120 | |
---|
121 | if (tapnum < 0 || tapnum >= GcfMAXTAP) { |
---|
122 | *status = GcfERR_ILLTAP; |
---|
123 | return; |
---|
124 | } /*endif*/ |
---|
125 | |
---|
126 | gcfv_tapcode[tapnum][0] = chan[0]; |
---|
127 | gcfv_tapcode[tapnum][1] = chan[1]; |
---|
128 | gcfv_tapcode[tapnum][2] = '\0'; |
---|
129 | |
---|
130 | } /* end of GcfSetTapcode */ |
---|
131 | |
---|
132 | |
---|
133 | |
---|
134 | /*----------------------------------------------------------------------------*/ |
---|
135 | |
---|
136 | |
---|
137 | |
---|
138 | void GcfReadUserTapcodes( char fname[], TSyStatus *status ) |
---|
139 | |
---|
140 | /* Reads tap code names from file |
---|
141 | * |
---|
142 | * parameters of routine |
---|
143 | * char fname[]; input; name of file or NULL |
---|
144 | * (then read from $HOME/.tapcodes) |
---|
145 | * TSyStatus *status; output; return status |
---|
146 | */ |
---|
147 | { |
---|
148 | /* local variables */ |
---|
149 | char fn[cBcFileLth+1]; /* name of input file */ |
---|
150 | char *env; /* pointer to environment */ |
---|
151 | FILE *fp; /* pointer to input file */ |
---|
152 | char line[cBcLineLth+1]; /* current line of file */ |
---|
153 | int tc; /* tapcode */ |
---|
154 | char chan[cBcLineLth+1]; /* channel name */ |
---|
155 | |
---|
156 | /* executable code */ |
---|
157 | |
---|
158 | if (fname == NULL) { |
---|
159 | env = (char *)getenv( "HOME" ); |
---|
160 | if (strlen(env) >= cBcFileLth-10) { |
---|
161 | *status = GcfERR_STROVFL; |
---|
162 | return; |
---|
163 | } /*endif*/ |
---|
164 | strcpy( fn, env ); |
---|
165 | strcat( fn, "/.tapcodes" ); |
---|
166 | } else { |
---|
167 | if (strlen(fname) >= cBcFileLth) { |
---|
168 | *status = GcfERR_STROVFL; |
---|
169 | return; |
---|
170 | } /*endif*/ |
---|
171 | strcpy( fn, fname ); |
---|
172 | } /*endif*/ |
---|
173 | |
---|
174 | fp = fopen( fn, "r" ); |
---|
175 | if (fp == NULL) { |
---|
176 | fprintf( stderr, |
---|
177 | "gcf: no user defined tapcodes found, using defaults\n" ); |
---|
178 | return; |
---|
179 | } /*endif*/ |
---|
180 | |
---|
181 | while (fgets(line,cBcLineLth,fp) != NULL) { |
---|
182 | if (*line == '!' || *line == '#' || *line == '\n') continue; |
---|
183 | if (sscanf(line,"%d %s",&tc,chan) != 2) { |
---|
184 | *status = GcfERR_TAPCODEFILE; |
---|
185 | return; |
---|
186 | } /*endif*/ |
---|
187 | if (tc < 0 || tc > 9) { |
---|
188 | *status = GcfERR_ILLTAPCODE; |
---|
189 | return; |
---|
190 | } /*endif*/ |
---|
191 | if (strlen(chan) > 2) { |
---|
192 | *status = GcfERR_TAPCODEFILE; |
---|
193 | return; |
---|
194 | } /*endif*/ |
---|
195 | gcfv_tapcode[tc][0] = chan[0]; |
---|
196 | gcfv_tapcode[tc][1] = chan[1]; |
---|
197 | gcfv_tapcode[tc][2] = '\0'; |
---|
198 | } /*endwhile*/ |
---|
199 | |
---|
200 | fclose( fp ); |
---|
201 | |
---|
202 | } /* end of GcfReadUserTapcodes */ |
---|
203 | |
---|
204 | |
---|
205 | |
---|
206 | /*----------------------------------------------------------------------------*/ |
---|
207 | |
---|
208 | |
---|
209 | |
---|
210 | void GcfReadRawHeader( FILE *gcf, GcfRawHeaderT *rhdr, TSyStatus *status ) |
---|
211 | |
---|
212 | /* Reads raw header from GCF file. |
---|
213 | * |
---|
214 | * parameters of routine |
---|
215 | * FILE *gcf; input; pointer to input GCF file (should be rewound) |
---|
216 | * GcfRawHeaderT *rhdr; output; header longwords read from file |
---|
217 | * TSyStatus *status; output; return status |
---|
218 | */ |
---|
219 | { |
---|
220 | /* local variables */ |
---|
221 | |
---|
222 | /* executable code */ |
---|
223 | |
---|
224 | rhdr->system_id = GcfGet4Bytes( gcf, status ); |
---|
225 | if (SySevere(status)) { |
---|
226 | *status = GcfERR_EOF_FOUND; |
---|
227 | return; |
---|
228 | } /*endif*/ |
---|
229 | rhdr->stream_id = GcfGet4Bytes( gcf, status ); |
---|
230 | if (SySevere(status)) return; |
---|
231 | rhdr->date_code = GcfGet4Bytes( gcf, status ); |
---|
232 | if (SySevere(status)) return; |
---|
233 | rhdr->data_format = GcfGet4Bytes( gcf, status ); |
---|
234 | if (SySevere(&status)) return; |
---|
235 | |
---|
236 | } /* end of GcfReadRawHeader */ |
---|
237 | |
---|
238 | |
---|
239 | |
---|
240 | /*----------------------------------------------------------------------------*/ |
---|
241 | |
---|
242 | |
---|
243 | |
---|
244 | void GcfDecodeHeader( GcfRawHeaderT *rhdr, GcfHeaderT *hdr, TSyStatus *status ) |
---|
245 | |
---|
246 | /* Decodes raw header |
---|
247 | * |
---|
248 | * parameters fo routine |
---|
249 | * GcfRawHeaderT *rhdr; input; raw header |
---|
250 | * GcfHeaderT *hdr; output; decoded header |
---|
251 | * TSyStatus *status; output; return status |
---|
252 | */ |
---|
253 | { |
---|
254 | /* local variables */ |
---|
255 | int i; /* counter */ |
---|
256 | NTIME ntime; /* numeric start time */ |
---|
257 | int offset; /* time offset */ |
---|
258 | int denom; /* denominator of fraction of seconds */ |
---|
259 | float secoff; /* offset in seconds */ |
---|
260 | |
---|
261 | /* executable code */ |
---|
262 | |
---|
263 | /* decode two base36 strings */ |
---|
264 | GcfBase36ToString( rhdr->system_id, hdr->system_id ); |
---|
265 | GcfBase36ToString( rhdr->stream_id, hdr->stream_id ); |
---|
266 | |
---|
267 | /* get station, chan, comp */ |
---|
268 | strncpy( hdr->station, hdr->stream_id, GcfSTATION_LENGTH ); |
---|
269 | i = GcfSTATION_LENGTH; |
---|
270 | while (i > 0 && hdr->station[i] <= ' ') |
---|
271 | hdr->station[i--] = '\0'; |
---|
272 | i = hdr->stream_id[GcfSTATION_LENGTH+1] - '0'; |
---|
273 | if (i < 0 || i >= GcfMAXTAP) { |
---|
274 | *status = GcfERR_ILLTAP; |
---|
275 | return; |
---|
276 | } /*endif*/ |
---|
277 | hdr->chan[0] = gcfv_tapcode[i][0]; |
---|
278 | hdr->chan[1] = gcfv_tapcode[i][1]; |
---|
279 | hdr->chan[2] = '\0'; |
---|
280 | hdr->chan[GcfCHAN_LENGTH] = '\0'; |
---|
281 | hdr->comp = hdr->stream_id[GcfSTATION_LENGTH]; |
---|
282 | |
---|
283 | /* get time info */ |
---|
284 | GcfDecodeTime( rhdr->date_code, &ntime ); |
---|
285 | tc_n2t( &ntime, hdr->blktime, status ); |
---|
286 | if (SySevere(status)) return; |
---|
287 | i = strlen( hdr->blktime ) - 4; |
---|
288 | if (strcmp(hdr->blktime+i,".000") == 0) hdr->blktime[i] = '\0'; |
---|
289 | |
---|
290 | /* data format bytes */ |
---|
291 | hdr->smprate = (rhdr->data_format & 0x00ff0000) >> 16; |
---|
292 | hdr->cmpcode = (rhdr->data_format & 0x00000f00) >> 8; |
---|
293 | hdr->numrec = (rhdr->data_format & 0x000000ff); |
---|
294 | |
---|
295 | /* extended settings */ |
---|
296 | offset = (rhdr->data_format & 0x0000f000) >> 12; /* time offset */ |
---|
297 | switch (hdr->smprate) { |
---|
298 | case 157: hdr->smprate = 0; /* should be 0.1 */ denom=0; break; |
---|
299 | case 161: hdr->smprate = 0; /* should be 0.125 */ denom=0; break; |
---|
300 | case 162: hdr->smprate = 0; /* should be 0.2 */ denom=0; break; |
---|
301 | case 164: hdr->smprate = 0; /* should be 0.25 */ denom=0; break; |
---|
302 | case 167: hdr->smprate = 0; /* should be 0.5 */ denom=0; break; |
---|
303 | case 171: hdr->smprate = 400; denom=8; break; |
---|
304 | case 174: hdr->smprate = 500; denom=2; break; |
---|
305 | case 176: hdr->smprate = 1000; denom=4; break; |
---|
306 | case 179: hdr->smprate = 2000; denom=8; break; |
---|
307 | case 181: hdr->smprate = 4000; denom=16; break; |
---|
308 | } /*endswitch*/ |
---|
309 | |
---|
310 | /* add fraction of seconds to start time, if specified */ |
---|
311 | if (denom != 0 && offset > 0) { |
---|
312 | NTIME corrtime; /* corrected time */ |
---|
313 | secoff = (float)offset / (float)denom; |
---|
314 | tc_nadd( &ntime, secoff, &corrtime, status ); |
---|
315 | if (SySevere(status)) return; |
---|
316 | tc_n2t( &corrtime, hdr->blktime, status ); |
---|
317 | } /*endif*/ |
---|
318 | |
---|
319 | } /* end of GcfDecodeHeader */ |
---|
320 | |
---|
321 | |
---|
322 | |
---|
323 | /*----------------------------------------------------------------------------*/ |
---|
324 | |
---|
325 | |
---|
326 | |
---|
327 | void GcfPrintHeader( FILE *out, GcfHeaderT *hdr ) |
---|
328 | |
---|
329 | /* Prints header infomration in one line to given output stream |
---|
330 | * |
---|
331 | * parameters of routine |
---|
332 | * FILE *out; input; output stream |
---|
333 | * GcfHeaderT *hdr; input; header to be printed |
---|
334 | */ |
---|
335 | { |
---|
336 | /* local variables */ |
---|
337 | int numbits; /* number of bits */ |
---|
338 | |
---|
339 | /* executable code */ |
---|
340 | |
---|
341 | switch (hdr->cmpcode) { |
---|
342 | case GcfCMP_8BIT: |
---|
343 | numbits = 8; |
---|
344 | break; |
---|
345 | case GcfCMP_16BIT: |
---|
346 | numbits = 16; |
---|
347 | break; |
---|
348 | case GcfCMP_32BIT: |
---|
349 | numbits = 32; |
---|
350 | break; |
---|
351 | default: |
---|
352 | numbits = 0; |
---|
353 | break; |
---|
354 | } /*endswitch*/ |
---|
355 | |
---|
356 | fprintf( out, "%6s %6s %4s-%2s-%c %20s %3dHz %2dbit %3dr", |
---|
357 | hdr->system_id, hdr->stream_id, hdr->station, hdr->chan, hdr->comp, |
---|
358 | hdr->blktime, hdr->smprate, numbits, hdr->numrec ); |
---|
359 | |
---|
360 | } /* end of GcfPrintHeader */ |
---|
361 | |
---|
362 | |
---|
363 | |
---|
364 | /*----------------------------------------------------------------------------*/ |
---|
365 | |
---|
366 | |
---|
367 | |
---|
368 | void GcfSkipDataBlock( FILE *gcf, GcfRawHeaderT *rhdr ) |
---|
369 | |
---|
370 | /* skips data block (jumps to next header or EOF) after a raw header has been |
---|
371 | * read |
---|
372 | * |
---|
373 | * parameters of routine |
---|
374 | * FILE *gcf; input; GCF data input file |
---|
375 | * GcfRawHeaderT *rhdr; input; raw header previously read |
---|
376 | */ |
---|
377 | { |
---|
378 | /* local variables */ |
---|
379 | int numrec; /* number of records (longwords) following */ |
---|
380 | |
---|
381 | /* executable code */ |
---|
382 | |
---|
383 | numrec = (rhdr->data_format & 0x000000ff); |
---|
384 | |
---|
385 | /*fseek( gcf, (numrec+2)*sizeof(unsigned INT32), SEEK_CUR );*/ |
---|
386 | fseek( gcf, 252*sizeof(unsigned INT32), SEEK_CUR ); |
---|
387 | |
---|
388 | } /* GcfSkipDataBlock */ |
---|
389 | |
---|
390 | |
---|
391 | |
---|
392 | /*----------------------------------------------------------------------------*/ |
---|
393 | |
---|
394 | |
---|
395 | |
---|
396 | GcfLongT *GcfAllocBlockMem( TSyStatus *status ) |
---|
397 | |
---|
398 | /* allocates memory for raw (coded) data block |
---|
399 | * |
---|
400 | * parameters of routine |
---|
401 | * TSyStatus *status; output; return status |
---|
402 | * returns pointer to block memory |
---|
403 | */ |
---|
404 | { |
---|
405 | /* local variables */ |
---|
406 | GcfLongT *blockmem; |
---|
407 | |
---|
408 | /* executable code */ |
---|
409 | |
---|
410 | /* 1kB is enough for max 250 records */ |
---|
411 | blockmem = (GcfLongT *)malloc( 1024 ); |
---|
412 | |
---|
413 | if (blockmem == NULL) *status = GcfERR_ALLOCMEM; |
---|
414 | return blockmem; |
---|
415 | |
---|
416 | } /* end of GcfAllocBlockMem */ |
---|
417 | |
---|
418 | |
---|
419 | |
---|
420 | /*----------------------------------------------------------------------------*/ |
---|
421 | |
---|
422 | |
---|
423 | |
---|
424 | int *GcfAllocBlockSamples( TSyStatus *status ) |
---|
425 | |
---|
426 | /* allocates memory for decoded samples of a block |
---|
427 | * |
---|
428 | * parameters of routine |
---|
429 | * TSyStatus *status; output; return status |
---|
430 | * returns pointer to memory for samples |
---|
431 | */ |
---|
432 | { |
---|
433 | /* local variables */ |
---|
434 | int *mem; |
---|
435 | |
---|
436 | /* executable code */ |
---|
437 | |
---|
438 | /* 4kB is enough for max 250 records of 8bit each */ |
---|
439 | mem = (int *)malloc( 4096 ); |
---|
440 | |
---|
441 | if (mem == NULL) *status = GcfERR_ALLOCMEM; |
---|
442 | return mem; |
---|
443 | |
---|
444 | } /* end of GcfAllocBlockSamples */ |
---|
445 | |
---|
446 | |
---|
447 | |
---|
448 | /*----------------------------------------------------------------------------*/ |
---|
449 | |
---|
450 | |
---|
451 | |
---|
452 | void GcfReadDataBlock( FILE *gcf, GcfRawHeaderT *rhdr, GcfLongT *mem, |
---|
453 | TSyStatus *status ) |
---|
454 | |
---|
455 | /* read in single data block from GCF file. Corresponding header must |
---|
456 | * be already read in. |
---|
457 | * |
---|
458 | * parameters of routine |
---|
459 | * FILE *gcf; input; pointer to input GCF file |
---|
460 | * GcfRawHeaderT *rhdr; input; GCF raw header previously read |
---|
461 | * GcfLongT *mem; output; block read in |
---|
462 | * TSyStatus *status; output; return status |
---|
463 | */ |
---|
464 | { |
---|
465 | /* local variables */ |
---|
466 | int i; /* counter */ |
---|
467 | int numrecs=252; /* number of records to read */ |
---|
468 | |
---|
469 | /* executable code */ |
---|
470 | |
---|
471 | /* assume 1kB data blocks and header already read in */ |
---|
472 | for (i=0; i<numrecs; i++) { |
---|
473 | mem[i] = GcfGet4Bytes( gcf, status ); |
---|
474 | if (SySevere(status)) return; |
---|
475 | } /*endif*/ |
---|
476 | |
---|
477 | } /* end of GcfReadDataBlock */ |
---|
478 | |
---|
479 | |
---|
480 | |
---|
481 | /*----------------------------------------------------------------------------*/ |
---|
482 | |
---|
483 | |
---|
484 | |
---|
485 | void GcfDecodeBlock( GcfRawHeaderT *rhdr, GcfLongT *block, int *samples, |
---|
486 | int *smpnum, TSyStatus *status ) |
---|
487 | |
---|
488 | /* Decodes samples of a block. Memory must be already allocated using |
---|
489 | * appropriate routines |
---|
490 | * |
---|
491 | * paramters of routine |
---|
492 | * GcfRawHeaderT *rhdr; input; GCF raw header previously read |
---|
493 | * GcfLongT *block; input; data block previously read |
---|
494 | * int *samples; output; samples decoded |
---|
495 | * int *smpnum; output; number of samples |
---|
496 | * TSyStatus *status; output; return status |
---|
497 | */ |
---|
498 | { |
---|
499 | /* local variables */ |
---|
500 | int i, j; /* counters */ |
---|
501 | int numrec; /* number of records */ |
---|
502 | int cmpcode; /* compression code */ |
---|
503 | int cursmp; /* current sample */ |
---|
504 | signed char sbyte; /* byte diff */ |
---|
505 | signed short si; /* 16 bit diff */ |
---|
506 | |
---|
507 | /* executable code */ |
---|
508 | |
---|
509 | cmpcode = (rhdr->data_format & 0x00000f00) >> 8; |
---|
510 | numrec = (rhdr->data_format & 0x000000ff); |
---|
511 | |
---|
512 | cursmp = block[0]; |
---|
513 | |
---|
514 | j = 0; |
---|
515 | if (cmpcode == GcfCMP_8BIT) { |
---|
516 | for (i=1; i<=numrec; i++) { |
---|
517 | sbyte = (block[i] & 0xff000000) >> 24; |
---|
518 | cursmp += sbyte; |
---|
519 | samples[j++] = cursmp; |
---|
520 | sbyte = (block[i] & 0x00ff0000) >> 16; |
---|
521 | cursmp += sbyte; |
---|
522 | samples[j++] = cursmp; |
---|
523 | sbyte = (block[i] & 0x0000ff00) >> 8; |
---|
524 | cursmp += sbyte; |
---|
525 | samples[j++] = cursmp; |
---|
526 | sbyte = (block[i] & 0x000000ff); |
---|
527 | cursmp += sbyte; |
---|
528 | samples[j++] = cursmp; |
---|
529 | } /*endif*/ |
---|
530 | } else if (cmpcode == GcfCMP_16BIT) { |
---|
531 | for (i=1; i<=numrec; i++) { |
---|
532 | si = (block[i] & 0xffff0000) >> 16; |
---|
533 | cursmp += si; |
---|
534 | samples[j++] = cursmp; |
---|
535 | si = (block[i] & 0x0000ffff); |
---|
536 | cursmp += si; |
---|
537 | samples[j++] = cursmp; |
---|
538 | } /*endif*/ |
---|
539 | } else if (cmpcode == GcfCMP_32BIT) { |
---|
540 | for (i=1; i<=numrec; i++) { |
---|
541 | cursmp += block[i]; |
---|
542 | samples[j++] = cursmp; |
---|
543 | } /*endif*/ |
---|
544 | } else { |
---|
545 | /* no data block */ |
---|
546 | } /*endif*/ |
---|
547 | |
---|
548 | *smpnum = j; |
---|
549 | |
---|
550 | if (samples[j-1] != block[numrec+1]) |
---|
551 | /* *status = GcfERR_CHKSUM; */ |
---|
552 | printf( "Gcf checksum error (%d != %d)\n", samples[j-1], block[numrec+1] ); |
---|
553 | |
---|
554 | } /* GcfDecodeBlock */ |
---|
555 | |
---|
556 | |
---|
557 | |
---|
558 | /*---------------------------------------------------------------------*/ |
---|
559 | |
---|
560 | |
---|
561 | |
---|
562 | void GcfFindFileInGfd( char stream_str[], char start[], char gfdfile[], |
---|
563 | GcfFileDescrT *fdescr, TSyStatus *status ) |
---|
564 | |
---|
565 | /* Finds GCF file in gfd-file of given stream and containing given |
---|
566 | * start time. If no file is found the file with the next possible |
---|
567 | * time is returned |
---|
568 | * |
---|
569 | * parameters of routine |
---|
570 | * char stream_str[]; input; stream string like "bfo-vbb-z" |
---|
571 | * char start[]; input; start time |
---|
572 | * char gfdfile[]; input; GCF file directory |
---|
573 | * GcfFileDescrT *fdescr; output; GCF file descriptor |
---|
574 | * TSyStatus *status; output; return status |
---|
575 | */ |
---|
576 | { |
---|
577 | /* local variables */ |
---|
578 | FILE *gfd; /* pointer to gfd-file */ |
---|
579 | char line[Gcf_C_GFDLINELTH+1]; /* current line */ |
---|
580 | float tdiff; /* time difference */ |
---|
581 | float min_tdiff; /* minimum tdiff */ |
---|
582 | GcfFileDescrT next; /* file with next time */ |
---|
583 | GcfFileDescrT curr; /* current line */ |
---|
584 | char lstream_str[cBcShortStrLth+1]; /* local lowercase stream string */ |
---|
585 | |
---|
586 | /* executable code */ |
---|
587 | |
---|
588 | if (strlen(stream_str) > cBcShortStrLth) { |
---|
589 | *status = GcfERR_STROVFL; |
---|
590 | err_setcontext( " ## stream " ); |
---|
591 | err_setcontext( stream_str ); |
---|
592 | return; |
---|
593 | } /*endif*/ |
---|
594 | |
---|
595 | /* make stream string lowercase */ |
---|
596 | strcpy( lstream_str, stream_str ); |
---|
597 | ut_uncap( lstream_str ); |
---|
598 | |
---|
599 | /* initialize local descriptors */ |
---|
600 | strcpy( next.stream, lstream_str ); |
---|
601 | strcpy( curr.stream, lstream_str ); |
---|
602 | next.t_start[0] = curr.t_start[0] = '\0'; |
---|
603 | next.t_end[0] = curr.t_end[0] = '\0'; |
---|
604 | next.name[0] = curr.name[0] = '\0'; |
---|
605 | strcpy( next.gfdfile, gfdfile ); |
---|
606 | strcpy( curr.gfdfile, gfdfile ); |
---|
607 | next.blkno = curr.blkno = 0; |
---|
608 | next.fp = curr.fp = NULL; |
---|
609 | next.pos = curr.pos = 0; |
---|
610 | next.sample = curr.sample = 0; |
---|
611 | next.calib = curr.calib = 0.0; |
---|
612 | next.dataflags = curr.dataflags = 0; |
---|
613 | next.blklth = curr.blklth = DEFAULT_BLKLTH; |
---|
614 | |
---|
615 | gfd = sy_fopen( gfdfile, "r" ); |
---|
616 | if (gfd == NULL) { |
---|
617 | *status = GcfERR_OPENINPUT; |
---|
618 | err_setcontext( " ## file " ); |
---|
619 | err_setcontext( gfdfile ); |
---|
620 | return; |
---|
621 | } /*endif*/ |
---|
622 | |
---|
623 | /* find requested stream and time in gfd-file */ |
---|
624 | next.name[0] = '\0'; |
---|
625 | min_tdiff = 1.0e10; |
---|
626 | while (fgets(line,Gcf_C_GFDLINELTH,gfd) != NULL) { |
---|
627 | if (*line == '!') continue; |
---|
628 | GcfParseGfdLine( line, &curr, status ); |
---|
629 | if (SySevere(status)) {fclose(gfd); return;} |
---|
630 | if (strcmp(curr.stream,lstream_str) != 0) continue; |
---|
631 | tdiff = tc_tdiff( start, curr.t_start, status ); |
---|
632 | if (SySevere(status)) {fclose(gfd); return;} |
---|
633 | if (tdiff >= 0.0 && tc_tdiff(start,curr.t_end,status) < 0.0) { |
---|
634 | /* found it ! */ |
---|
635 | *fdescr = curr; |
---|
636 | fclose( gfd ); |
---|
637 | if (fdescr->calib == 0.0) { |
---|
638 | fdescr->calib = |
---|
639 | GcfFindStreamCalibration( fdescr->stream, start, status ); |
---|
640 | if (*status == GcfERR_NOCALIB) { |
---|
641 | *status = cBcNoError; |
---|
642 | fdescr->dataflags |= Gcf_F_QUAL_NOCALIB; |
---|
643 | } /*endif*/ |
---|
644 | } /*endif*/ |
---|
645 | if (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0) |
---|
646 | GcfAdjustFilename( fdescr, status ); |
---|
647 | return; |
---|
648 | } else if (tdiff < 0.0) { |
---|
649 | /* store file with time next to requested */ |
---|
650 | if (SySevere(status)) {fclose(gfd); return;} |
---|
651 | if (next.name[0] == '\0' || tdiff > min_tdiff) { |
---|
652 | min_tdiff = tdiff; |
---|
653 | next = curr; |
---|
654 | } /*endif*/ |
---|
655 | if (next.calib == 0.0) { |
---|
656 | next.calib = |
---|
657 | GcfFindStreamCalibration( next.stream, start, status ); |
---|
658 | if (*status == GcfERR_NOCALIB) { |
---|
659 | *status = cBcNoError; |
---|
660 | next.dataflags |= Gcf_F_QUAL_NOCALIB; |
---|
661 | } /*endif*/ |
---|
662 | } /*endif*/ |
---|
663 | } /*endif*/ |
---|
664 | if (SySevere(status)) {fclose(gfd); return;} |
---|
665 | } /*endwhile*/ |
---|
666 | |
---|
667 | *status = (next.name[0] == '\0') ? GcfERR_GFD_NOTFOUND : GcfERR_GFD_NEXT; |
---|
668 | if (*status == GcfERR_GFD_NOTFOUND) { |
---|
669 | err_setcontext( " ## stream " ); |
---|
670 | err_setcontext( lstream_str ); |
---|
671 | err_setcontext( ", time " ); |
---|
672 | err_setcontext( start ); |
---|
673 | } /*endif*/ |
---|
674 | fclose( gfd ); |
---|
675 | *fdescr = next; |
---|
676 | if (strncmp(fdescr->name,ROOTDIR,ROOTDIRLTH) == 0) |
---|
677 | GcfAdjustFilename( fdescr, status ); |
---|
678 | return; |
---|
679 | |
---|
680 | } /* end of GcfFindFileInGfd */ |
---|
681 | |
---|
682 | |
---|
683 | |
---|
684 | /*---------------------------------------------------------------------*/ |
---|
685 | |
---|
686 | |
---|
687 | |
---|
688 | void GcfSearchPosition( int chan, char gfdfile[], char stream_str[], |
---|
689 | char req_start[], char act_start[], TSyStatus *status ) |
---|
690 | |
---|
691 | /* Searches for given time position in a stream file. The corresponding |
---|
692 | * GCF file is opened and positioned, its file descriptor stored |
---|
693 | * in an internal variable. 'chan' must range from 0..Gcf_C_MAXCHAN-1. |
---|
694 | * If the channel is already used the previously opened file is closed. |
---|
695 | * |
---|
696 | * parameters of routine |
---|
697 | * int chan; input; channel number |
---|
698 | * char gfdfile[]; input; gfd-file |
---|
699 | * char stream_str[]; input; stream string |
---|
700 | * char req_start[]; input; requested start time |
---|
701 | * char act_start[]; output; actual start time |
---|
702 | * TSyStatus *status; output; return status |
---|
703 | */ |
---|
704 | { |
---|
705 | /* local variables */ |
---|
706 | TSyBoolean next_time; /* only next time possible */ |
---|
707 | float tdiff_tot; /* total time window of file */ |
---|
708 | float tdiff_start; /* difference to request time */ |
---|
709 | GcfFileDescrT *fd; /* pointer to file descriptor */ |
---|
710 | INT32 seek_pos; /* seek position */ |
---|
711 | NTIME req_ntime; /* requested time in NTIME format */ |
---|
712 | NTIME cur_ntime; /* start time of current GCF block */ |
---|
713 | float cur_span; /* time span (sec) of current GCF block */ |
---|
714 | float dt; /* sample distance in sec */ |
---|
715 | int jump_blk; /* number of blocks to jump */ |
---|
716 | int new_pos; /* new block position */ |
---|
717 | int jump_cnt; /* jump counter */ |
---|
718 | GcfRawHeaderT rhdr; /* GCF raw header */ |
---|
719 | GcfHeaderT hdr; /* GCF decoded header */ |
---|
720 | |
---|
721 | /* executable code */ |
---|
722 | |
---|
723 | if (chan < 0 || chan >= Gcf_C_MAXCHAN) { |
---|
724 | *status = GcfERR_CHAN_OOR; |
---|
725 | return; |
---|
726 | } /*endif*/ |
---|
727 | fd = gcfv_fd + chan; |
---|
728 | |
---|
729 | if (fd->fp != NULL) { |
---|
730 | fclose( fd->fp ); |
---|
731 | fd->fp = NULL; |
---|
732 | } /*endif*/ |
---|
733 | |
---|
734 | GcfFindFileInGfd( stream_str, req_start, gfdfile, fd, status ); |
---|
735 | next_time = (*status == GcfERR_GFD_NEXT); |
---|
736 | if (next_time) *status = cBcNoError; |
---|
737 | if (SySevere(status)) return; |
---|
738 | |
---|
739 | if (gcfv_logrec) printf( "{%s}", fd->name ); |
---|
740 | fd->fp = fopen( fd->name, "r" ); |
---|
741 | if (fd->fp == NULL) { |
---|
742 | *status = GcfERR_OPENINPUT; |
---|
743 | err_setcontext( " ## file " ); |
---|
744 | err_setcontext( fd->name ); |
---|
745 | fd->fp = NULL; |
---|
746 | return; |
---|
747 | } /*endif*/ |
---|
748 | |
---|
749 | if (next_time) { |
---|
750 | strcpy( act_start, fd->t_start ); |
---|
751 | *status = GcfERR_NEXTTIMEPOS; |
---|
752 | return; |
---|
753 | } /*endif*/ |
---|
754 | tc_t2n( req_start, &req_ntime, status ); |
---|
755 | if (SySevere(status)) return; |
---|
756 | |
---|
757 | /* compute approximate block position */ |
---|
758 | tdiff_tot = tc_tdiff( fd->t_end, fd->t_start, status ); |
---|
759 | if (SySevere(status)) return; |
---|
760 | tdiff_start = tc_tdiff( req_start, fd->t_start, status ); |
---|
761 | if (SySevere(status)) return; |
---|
762 | new_pos = Nint( (float)((fd->blkno)-1)/tdiff_tot * tdiff_start ); |
---|
763 | |
---|
764 | for (jump_cnt=0; jump_cnt<4; jump_cnt++) { |
---|
765 | |
---|
766 | /* position GCF file */ |
---|
767 | if (new_pos != fd->pos) { |
---|
768 | if (new_pos >= fd->blkno) new_pos = fd->blkno-1; |
---|
769 | if (new_pos < 0) new_pos = 0; |
---|
770 | fd->pos = new_pos; |
---|
771 | seek_pos = (INT32)(fd->pos) * (INT32)(fd->blklth); |
---|
772 | if (gcfv_logrec) printf( "-" ); |
---|
773 | if (fseek(fd->fp,seek_pos,SEEK_SET) != 0/*seek_pos*/) { |
---|
774 | *status = GcfERR_GCFSEEK; |
---|
775 | err_setcontext( " ## file " ); |
---|
776 | err_setcontext( fd->name ); |
---|
777 | return; |
---|
778 | } /*endif*/ |
---|
779 | } /*endif*/ |
---|
780 | |
---|
781 | /* read current GCF block */ |
---|
782 | if (gcfv_logrec) printf( "[%d]", fd->pos ); /* log */ |
---|
783 | GcfReadRawHeader( fd->fp, &rhdr, status ); |
---|
784 | if (SySevere(status)) { |
---|
785 | err_setcontext( " ## file " ); |
---|
786 | err_setcontext( fd->name ); |
---|
787 | return; |
---|
788 | } /*endif*/ |
---|
789 | GcfSkipDataBlock( fd->fp, &rhdr ); |
---|
790 | GcfDecodeHeader( &rhdr, &hdr, status ); |
---|
791 | if (SySevere(status)) { |
---|
792 | err_setcontext( " ## file " ); |
---|
793 | err_setcontext( fd->name ); |
---|
794 | return; |
---|
795 | } /*endif*/ |
---|
796 | (fd->pos)++; |
---|
797 | dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate; |
---|
798 | |
---|
799 | /* check time found (return if time found) */ |
---|
800 | tc_t2n( hdr.blktime, &cur_ntime, status ); |
---|
801 | if (SySevere(status)) return; |
---|
802 | tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status ); |
---|
803 | if (SySevere(status)) return; |
---|
804 | cur_span = (hdr.smprate == 0) |
---|
805 | ? 0.0 : (float)(hdr.numrec*hdr.cmpcode/hdr.smprate); |
---|
806 | if (tdiff_start >= 0.0) { |
---|
807 | if (cur_span > tdiff_start) { |
---|
808 | /* found it ! */ |
---|
809 | seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->blklth); |
---|
810 | fseek( fd->fp, seek_pos, SEEK_SET ); |
---|
811 | fd->sample = Nint( tdiff_start/dt ); |
---|
812 | if (fd->sample >/*=*/ (hdr.numrec*hdr.cmpcode)) { |
---|
813 | printf( "! GcfSearchPosition: sample position adjusted (1)\n" ); |
---|
814 | fd->sample = hdr.numrec*hdr.cmpcode /*- 1*/; |
---|
815 | } /*endif*/ |
---|
816 | tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status ); |
---|
817 | if (Severe(status)) return; |
---|
818 | tc_n2t( &req_ntime, act_start, status ); |
---|
819 | return; |
---|
820 | } /*endif*/ |
---|
821 | } /*endif*/ |
---|
822 | |
---|
823 | /* estimate next jump */ |
---|
824 | if (tdiff_start > 0.0) tdiff_start -= cur_span; |
---|
825 | jump_blk = Nint( (tdiff_start/cur_span) - 0.5 ); |
---|
826 | if (jump_blk >= 0) jump_blk++; else jump_blk--; |
---|
827 | new_pos = fd->pos - 1 + jump_blk; |
---|
828 | |
---|
829 | } /*endfor*/ |
---|
830 | |
---|
831 | /* if still not found then read block by block */ |
---|
832 | if (gcfv_logrec) printf( "|" ); |
---|
833 | |
---|
834 | /* go back to time before */ |
---|
835 | tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status ); |
---|
836 | while (tdiff_start < 0.0) { |
---|
837 | fd->pos -= 2; |
---|
838 | if (fd->pos < 0) { |
---|
839 | fprintf( stderr, "*** GcfSearchPosition: check gfdfile\n" ); |
---|
840 | *status = GcfERR_BUG; |
---|
841 | return; |
---|
842 | } /*endif*/ |
---|
843 | seek_pos = (INT32)(fd->pos) * (INT32)(fd->blklth); |
---|
844 | if (gcfv_logrec) printf( "-" ); |
---|
845 | if (fseek(fd->fp,seek_pos,SEEK_SET) != 0/*seek_pos*/) { |
---|
846 | *status = GcfERR_GCFSEEK; |
---|
847 | err_setcontext( " ## file " ); |
---|
848 | err_setcontext( fd->name ); |
---|
849 | return; |
---|
850 | } /*endif*/ |
---|
851 | if (gcfv_logrec) printf( "[%d]", fd->pos ); /* log */ |
---|
852 | GcfReadRawHeader( fd->fp, &rhdr, status ); |
---|
853 | if (SySevere(status)) { |
---|
854 | err_setcontext( " ## file " ); |
---|
855 | err_setcontext( fd->name ); |
---|
856 | return; |
---|
857 | } /*endif*/ |
---|
858 | GcfSkipDataBlock( fd->fp, &rhdr ); |
---|
859 | GcfDecodeHeader( &rhdr, &hdr, status ); |
---|
860 | if (SySevere(status)) return; |
---|
861 | (fd->pos)++; |
---|
862 | dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate; |
---|
863 | tc_t2n( hdr.blktime, &cur_ntime, status ); |
---|
864 | if (Severe(status)) return; |
---|
865 | /* check for time correction, K.S. 16-Mar-99 */ |
---|
866 | tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status ); |
---|
867 | if (Severe(status)) return; |
---|
868 | cur_span = (float)(hdr.numrec*hdr.cmpcode/hdr.smprate); |
---|
869 | } /*endwhile*/ |
---|
870 | |
---|
871 | /* now find forward */ |
---|
872 | while (tdiff_start >= cur_span) { |
---|
873 | if (gcfv_logrec) printf( "[%d]", fd->pos ); /* log */ |
---|
874 | GcfReadRawHeader( fd->fp, &rhdr, status ); |
---|
875 | if (SySevere(status)) { |
---|
876 | err_setcontext( " ## file " ); |
---|
877 | err_setcontext( fd->name ); |
---|
878 | return; |
---|
879 | } /*endif*/ |
---|
880 | (fd->pos)++; |
---|
881 | GcfSkipDataBlock( fd->fp, &rhdr ); |
---|
882 | GcfDecodeHeader( &rhdr, &hdr, status ); |
---|
883 | if (SySevere(status)) return; |
---|
884 | dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate; |
---|
885 | tc_t2n( hdr.blktime, &cur_ntime, status ); |
---|
886 | if (Severe(status)) return; |
---|
887 | tdiff_start = tc_ndiff( &req_ntime, &cur_ntime, status ); |
---|
888 | if (Severe(status)) return; |
---|
889 | cur_span = (hdr.smprate == 0) |
---|
890 | ? 0.0 : (float)(hdr.numrec*hdr.cmpcode/hdr.smprate); |
---|
891 | } /*endwhile*/ |
---|
892 | |
---|
893 | /* step one block back to get it again on next read command */ |
---|
894 | seek_pos = (INT32)(--(fd->pos)) * (INT32)(fd->blklth); |
---|
895 | fseek( fd->fp, seek_pos, SEEK_SET ); |
---|
896 | |
---|
897 | if (tdiff_start >= 0.0) { |
---|
898 | /* now found it */ |
---|
899 | fd->sample = Nint( tdiff_start/dt ); |
---|
900 | if (fd->sample >/*=*/ (int)(hdr.numrec*hdr.cmpcode)) { |
---|
901 | printf( "! GcfSearchPosition: sample position adjusted (2)\n" ); |
---|
902 | fd->sample = hdr.numrec*hdr.cmpcode /*- 1*/; |
---|
903 | } /*endif*/ |
---|
904 | tc_nadd( &cur_ntime, (fd->sample)*dt, &req_ntime, status ); |
---|
905 | if (Severe(status)) return; |
---|
906 | tc_n2t( &req_ntime, act_start, status ); |
---|
907 | } else { |
---|
908 | /* time gap */ |
---|
909 | /* printf( "*** time gap: next possible time positioned ***\n" ); */ |
---|
910 | tc_n2t( &cur_ntime, act_start, status ); |
---|
911 | *status = GcfERR_NEXTTIMEPOS; |
---|
912 | } /*endif*/ |
---|
913 | |
---|
914 | } /* end of GcfSearchPosition */ |
---|
915 | |
---|
916 | |
---|
917 | |
---|
918 | /*---------------------------------------------------------------------*/ |
---|
919 | |
---|
920 | |
---|
921 | |
---|
922 | void GcfReadNextBlock( int chan, GcfRawHeaderT *rhdr, GcfLongT *blk, |
---|
923 | TSyStatus *status ) |
---|
924 | |
---|
925 | /* Reads next available block (header and data) from GCF file. |
---|
926 | * |
---|
927 | * parameters of routine |
---|
928 | * int chan; input; channel number |
---|
929 | * GcfRawHeaderT *rhdr; output; coded header of block |
---|
930 | * GcfLongT *blk; output; coded data of block |
---|
931 | * TSyStatus *status; output; return status |
---|
932 | */ |
---|
933 | { |
---|
934 | /* local variables */ |
---|
935 | GcfFileDescrT *fd; /* GCF file descriptor */ |
---|
936 | char l_gfdfile[cBcFileLth+1]; /* local sfdfile */ |
---|
937 | char l_stream[cBcShortStrLth+1]; /* local stream string */ |
---|
938 | char l_t_end[cBcTimeLth+1]; /* end of file time */ |
---|
939 | char act_time[cBcTimeLth+1]; /* positioned time */ |
---|
940 | TSyBoolean time_gap; /* time gap found */ |
---|
941 | |
---|
942 | /* executable code */ |
---|
943 | |
---|
944 | /* check channel number */ |
---|
945 | if (chan < 0 || chan >= Gcf_C_MAXCHAN) { |
---|
946 | *status = GcfERR_CHAN_OOR; |
---|
947 | return; |
---|
948 | } /*endif*/ |
---|
949 | fd = gcfv_fd + chan; |
---|
950 | |
---|
951 | if (fd->fp == NULL) { |
---|
952 | *status = GcfERR_NOT_OPEN; |
---|
953 | return; |
---|
954 | } /*endif*/ |
---|
955 | |
---|
956 | /* store filename for last used file request */ |
---|
957 | strcpy( gcfv_last_fname, fd->name ); |
---|
958 | |
---|
959 | time_gap = FALSE; |
---|
960 | if (fd->pos >= fd->blkno) { |
---|
961 | /* is at end of file */ |
---|
962 | strcpy( l_gfdfile, fd->gfdfile ); |
---|
963 | strcpy( l_stream, fd->stream ); |
---|
964 | strcpy( l_t_end, fd->t_end ); |
---|
965 | GcfSearchPosition( chan, l_gfdfile, l_stream, l_t_end, |
---|
966 | act_time, status ); |
---|
967 | time_gap = (*status == GcfERR_NEXTTIMEPOS); |
---|
968 | if (time_gap) *status = cBcNoError; |
---|
969 | if (SySevere(status)) return; |
---|
970 | } /*endif*/ |
---|
971 | |
---|
972 | if (gcfv_logrec) printf( "<%d>", fd->pos ); /* log */ |
---|
973 | GcfReadRawHeader( fd->fp, rhdr, status ); |
---|
974 | if (SySevere(status)) return; |
---|
975 | GcfReadDataBlock( fd->fp, rhdr, blk, status ); |
---|
976 | if (SySevere(status)) return; |
---|
977 | (fd->pos)++; |
---|
978 | |
---|
979 | if (time_gap) *status = GcfERR_NEXTTIMEPOS; |
---|
980 | |
---|
981 | } /* end of GcfReadNextBlock */ |
---|
982 | |
---|
983 | |
---|
984 | |
---|
985 | /*---------------------------------------------------------------------*/ |
---|
986 | |
---|
987 | |
---|
988 | |
---|
989 | #define ON_ERROR_RETURN \ |
---|
990 | if (SySevere(status)) { \ |
---|
991 | GcfFreeMem(blk); \ |
---|
992 | GcfFreeMem(blksmp); \ |
---|
993 | return; \ |
---|
994 | } |
---|
995 | |
---|
996 | |
---|
997 | |
---|
998 | void GcfReadStream( int chan, char gfdfile[], char stream_str[], |
---|
999 | TSyBoolean unused, char req_start[], float seclth, INT32 **ldat, |
---|
1000 | INT32 *smplth, char act_start[], float *dt, float *calib, |
---|
1001 | int *flags, TSyStatus *status ) |
---|
1002 | |
---|
1003 | /* Reads sample data from GCF file. The memory for the sample |
---|
1004 | * data is allocated by the routine. The channel number is chosen |
---|
1005 | * by the caller of the routine. It is legal to use always channel |
---|
1006 | * number 0 but it is faster to use a separate channel number for |
---|
1007 | * each stream used if the streams are read repeatedly. |
---|
1008 | * |
---|
1009 | * parameters of routine |
---|
1010 | * int chan; input; channel number (0..Gcf_C_MAXCHAN-1) |
---|
1011 | * char gfdfile[]; input; name of gfd file to use |
---|
1012 | * char stream_str[]; input; stream string (like "bfo-vbb-z") |
---|
1013 | * TSyBoolean unused; |
---|
1014 | * char req_start[]; input; requested start time |
---|
1015 | * float seclth; input; number of seconds to be read |
---|
1016 | * INT32 **ldat; output; sample array read |
---|
1017 | * INT32 *smplth; output; number of samples read |
---|
1018 | * char act_start[]; output; actual start time |
---|
1019 | * float *dt; output; sample distance in sec |
---|
1020 | * float *calib; output; calibration constant |
---|
1021 | * int *flags; output; data flags found |
---|
1022 | * TSyStatus *status; output; return status |
---|
1023 | */ |
---|
1024 | { |
---|
1025 | /* local variables */ |
---|
1026 | GcfFileDescrT *fd; /* pointer to SEED file descriptor */ |
---|
1027 | INT32 getlth; /* number of samples to read */ |
---|
1028 | INT32 maxblksmp; /* maximum number of samples per block */ |
---|
1029 | int actblksmp; /* actual number of samples in block */ |
---|
1030 | int *lsrc, *ldst;/* moving pointers */ |
---|
1031 | NTIME blkstart; /* block start time */ |
---|
1032 | NTIME blkend; /* block end time */ |
---|
1033 | NTIME expectime; /* expected time */ |
---|
1034 | float tdiff; /* time gap in sec */ |
---|
1035 | INT32 padcnt; /* counter for zero padding */ |
---|
1036 | char str[cBcTimeLth+1]; /* scratch string for time output */ |
---|
1037 | int i; /* counter */ |
---|
1038 | GcfLongT *blk; /* coded block data */ |
---|
1039 | int *blksmp; /* decoded samples of a block */ |
---|
1040 | GcfRawHeaderT rhdr; /* coded GCF header */ |
---|
1041 | GcfHeaderT hdr; /* decoded GCF header */ |
---|
1042 | int lastsmp; /* value of last sample (for padding) */ |
---|
1043 | |
---|
1044 | /* executable code */ |
---|
1045 | |
---|
1046 | GcfReadUserTapcodes( NULL, status ); |
---|
1047 | if (SySevere(status)) return; |
---|
1048 | |
---|
1049 | /* check channel number */ |
---|
1050 | if (chan < 0 || chan >= Gcf_C_MAXCHAN) { |
---|
1051 | *status = GcfERR_CHAN_OOR; |
---|
1052 | return; |
---|
1053 | } /*endif*/ |
---|
1054 | fd = gcfv_fd + chan; |
---|
1055 | |
---|
1056 | /* find requested position */ |
---|
1057 | tdiff = 0.0; |
---|
1058 | GcfSearchPosition( chan, gfdfile, stream_str, req_start, |
---|
1059 | act_start, status ); |
---|
1060 | if (*status == GcfERR_NEXTTIMEPOS) { |
---|
1061 | *status = cBcNoError; |
---|
1062 | tdiff = tc_tdiff( act_start, req_start, status ); |
---|
1063 | if (SySevere(status)) return; |
---|
1064 | if (tdiff >= seclth) {*status = GcfERR_DATA_UNAVAIL; return;} |
---|
1065 | fprintf( stderr, |
---|
1066 | "GcfReadStream: time %s not found, start at %s\n", |
---|
1067 | req_start, act_start ); |
---|
1068 | } /*endif*/ |
---|
1069 | if (SySevere(status)) return; |
---|
1070 | |
---|
1071 | maxblksmp = MAX_SMP_PER_BLK; |
---|
1072 | *smplth = 0; |
---|
1073 | *ldat = NULL; |
---|
1074 | *dt = 0.0; |
---|
1075 | expectime.year = 0; |
---|
1076 | blk = GcfAllocBlockMem( status ); |
---|
1077 | if (SySevere(status)) return; |
---|
1078 | blksmp = GcfAllocBlockSamples( status ); |
---|
1079 | if (SySevere(status)) { |
---|
1080 | GcfFreeMem( blk ); |
---|
1081 | return; |
---|
1082 | } /*endif*/ |
---|
1083 | lastsmp = 0; |
---|
1084 | |
---|
1085 | FOREVER { |
---|
1086 | |
---|
1087 | /* read next block */ |
---|
1088 | GcfReadNextBlock( chan, &rhdr, blk, status ); |
---|
1089 | if (*status == GcfERR_NEXTTIMEPOS) *status = cBcNoError; |
---|
1090 | ON_ERROR_RETURN |
---|
1091 | GcfDecodeHeader( &rhdr, &hdr, status ); |
---|
1092 | ON_ERROR_RETURN |
---|
1093 | |
---|
1094 | /* decode GCF block and select samples */ |
---|
1095 | /* ------------------------------------- */ |
---|
1096 | if (*ldat == NULL) { |
---|
1097 | |
---|
1098 | /* this is for first loop only */ |
---|
1099 | /* --------------------------- */ |
---|
1100 | *calib = fd->calib; |
---|
1101 | *dt = (hdr.smprate == 0) ? 0.0 : 1.0/(float)hdr.smprate; |
---|
1102 | getlth = (hdr.smprate == 0) ? 0 : Nint32( seclth / *dt ); |
---|
1103 | if (getlth <= 0) {*status = GcfERR_ZEROLTH; return;} |
---|
1104 | *ldat = (INT32 *)sy_allocmem( getlth, (int)sizeof(INT32), status ); |
---|
1105 | ON_ERROR_RETURN |
---|
1106 | ldst = (int *)*ldat; |
---|
1107 | /* if time gap at beginning, pad zeroes */ |
---|
1108 | if (tdiff > 0.0) { |
---|
1109 | /* pad with zeroes and adjust start time */ |
---|
1110 | padcnt = Nint32( tdiff / (*dt) ); |
---|
1111 | fprintf( stderr, "GcfReadStream: stream %s, time %s\n", |
---|
1112 | hdr.stream_id, act_start ); |
---|
1113 | fprintf( stderr, " gap %5.3f sec, start with %ld zeroes\n", |
---|
1114 | tdiff, padcnt ); |
---|
1115 | tc_tadd( act_start, -(*dt)*(float)padcnt, act_start, status ); |
---|
1116 | if (SySevere(status)) *status = cBcNoError; /* ok, not elegant */ |
---|
1117 | while (padcnt-- > 0) { |
---|
1118 | ldst[(*smplth)++] = 0; |
---|
1119 | if (*smplth == getlth) { |
---|
1120 | GcfFreeMem( blksmp ); |
---|
1121 | fprintf( stderr, |
---|
1122 | " padding aborted, %ld zeroes remaining\n", padcnt ); |
---|
1123 | strcpy( act_start, req_start ); |
---|
1124 | return; |
---|
1125 | } /*endif*/ |
---|
1126 | } /*endwhile*/ |
---|
1127 | } /*endif*/ |
---|
1128 | GcfDecodeBlock( &rhdr, blk, blksmp, &actblksmp, status ); |
---|
1129 | ON_ERROR_RETURN |
---|
1130 | lsrc = blksmp + fd->sample; |
---|
1131 | actblksmp -= fd->sample; |
---|
1132 | if (actblksmp < 0) { |
---|
1133 | sy_deallocmem( *ldat ); |
---|
1134 | *ldat = NULL; |
---|
1135 | GcfFreeMem( blksmp ); |
---|
1136 | GcfFreeMem( blk ); |
---|
1137 | *status = GcfERR_BUG; |
---|
1138 | fprintf( stderr, |
---|
1139 | "*** GcfReadStream: bug (1) [sample: %d, actblksmp %d] ***\n", |
---|
1140 | fd->sample, actblksmp ); |
---|
1141 | return; |
---|
1142 | } /*endif*/ |
---|
1143 | tc_t2n( hdr.blktime, &blkstart, status ); |
---|
1144 | ON_ERROR_RETURN |
---|
1145 | tc_nadd( &blkstart, (float)(hdr.numrec*hdr.cmpcode/hdr.smprate), |
---|
1146 | &expectime, status ); |
---|
1147 | ON_ERROR_RETURN |
---|
1148 | |
---|
1149 | } else { |
---|
1150 | |
---|
1151 | /* this is for all other loops */ |
---|
1152 | /* --------------------------- */ |
---|
1153 | |
---|
1154 | /* decode block */ |
---|
1155 | GcfDecodeBlock( &rhdr, blk, blksmp, &actblksmp, status ); |
---|
1156 | ON_ERROR_RETURN |
---|
1157 | lsrc = blksmp; |
---|
1158 | |
---|
1159 | /* check for time gaps, pad with zeroes */ |
---|
1160 | tc_t2n( hdr.blktime, &blkstart, status ); |
---|
1161 | ON_ERROR_RETURN |
---|
1162 | tc_nadd( &blkstart, (float)(hdr.numrec*hdr.cmpcode/hdr.smprate), |
---|
1163 | &blkend, status ); |
---|
1164 | ON_ERROR_RETURN |
---|
1165 | tdiff = tc_ndiff( &blkstart, &expectime, status ); |
---|
1166 | ON_ERROR_RETURN |
---|
1167 | if (tdiff <= -(*dt)) { |
---|
1168 | /* double data */ |
---|
1169 | padcnt = Nint32( -tdiff / (*dt) ); |
---|
1170 | tc_n2t( &blkstart, str, status ); |
---|
1171 | fprintf( stderr, "SeedReadStream: stream %s, time %s\n", |
---|
1172 | hdr.stream_id, str ); |
---|
1173 | fprintf( stderr, " double data, %ld samples skipped\n", |
---|
1174 | padcnt ); |
---|
1175 | if (padcnt > (INT32)(hdr.numrec*hdr.cmpcode)) { |
---|
1176 | /* |
---|
1177 | *status = GcfERR_DOUBLEDATA; |
---|
1178 | GcfFreeMem( blk ); |
---|
1179 | GcfFreeMem( blksmp ); |
---|
1180 | return; |
---|
1181 | */ |
---|
1182 | /* throw way this block */ |
---|
1183 | continue; |
---|
1184 | } /*endif*/ |
---|
1185 | /* skip samples */ |
---|
1186 | lsrc += padcnt; |
---|
1187 | actblksmp -= padcnt; |
---|
1188 | } else if (tdiff >= (*dt)) { |
---|
1189 | /* time gap */ |
---|
1190 | padcnt = Nint32( tdiff / (*dt) ); |
---|
1191 | tc_n2t( &blkstart, str, status ); |
---|
1192 | fprintf( stderr, "GcfReadStream: stream %s, time %s\n", |
---|
1193 | hdr.stream_id, str ); |
---|
1194 | fprintf( stderr, |
---|
1195 | " gap %5.3f sec, padding %ld zeroes at sample %ld\n", |
---|
1196 | tdiff, padcnt, *smplth ); |
---|
1197 | /* pad zeroes */ |
---|
1198 | while (padcnt-- > 0) { |
---|
1199 | ldst[(*smplth)++] = lastsmp; |
---|
1200 | if (*smplth == getlth) { |
---|
1201 | GcfFreeMem( blksmp ); |
---|
1202 | GcfFreeMem( blk ); |
---|
1203 | fprintf( stderr, |
---|
1204 | " padding aborted, %ld zeroes remaining\n", padcnt ); |
---|
1205 | return; |
---|
1206 | } /*endif*/ |
---|
1207 | } /*endwhile*/ |
---|
1208 | } /*endif*/ |
---|
1209 | expectime = blkend; |
---|
1210 | |
---|
1211 | } /*endif*/ |
---|
1212 | |
---|
1213 | /* copy samples to output array */ |
---|
1214 | while (actblksmp-- > 0) { |
---|
1215 | ldst[(*smplth)++] = *lsrc++; |
---|
1216 | if (*smplth == getlth) { /* finished ! */ |
---|
1217 | GcfFreeMem( blksmp ); |
---|
1218 | GcfFreeMem( blk ); |
---|
1219 | return; |
---|
1220 | } /*endif*/ |
---|
1221 | } /*endwhile*/ |
---|
1222 | if (*smplth > 0) |
---|
1223 | lastsmp = ldst[(*smplth)-1]; |
---|
1224 | |
---|
1225 | } /*endfor*/ |
---|
1226 | |
---|
1227 | } /* end of GcfReadStream */ |
---|
1228 | |
---|
1229 | |
---|
1230 | |
---|
1231 | /*---------------------------------------------------------------------*/ |
---|
1232 | |
---|
1233 | |
---|
1234 | |
---|
1235 | void GcfOrSeedReadStream( int chan, char gfdfile[], char stream_str[], |
---|
1236 | TSyBoolean swap, char req_start[], float seclth, INT32 **ldat, |
---|
1237 | INT32 *smplth, char act_start[], float *dt, float *calib, |
---|
1238 | int *flags, TSyStatus *status ) |
---|
1239 | |
---|
1240 | /* Reads sample data from GCF or MiniSEED file. Checks gfdfile for deciding |
---|
1241 | * GCF or MiniSEED: if the the first character in gfdfile is 'g', GCF format |
---|
1242 | * is read, otherwise MiniSEED format assumed. The memory for the sample |
---|
1243 | * data is allocated by the routine. The channel number is chosen |
---|
1244 | * by the caller of the routine. It is legal to use always channel |
---|
1245 | * number 0 but it is faster to use a separate channel number for |
---|
1246 | * each stream used if the streams are read repeatedly. |
---|
1247 | * |
---|
1248 | * parameters of routine |
---|
1249 | * int chan; input; channel number (0..Gcf_C_MAXCHAN-1) |
---|
1250 | * char gfdfile[]; input; name of gfd file to use |
---|
1251 | * char stream_str[]; input; stream string (like "bfo-vbb-z") |
---|
1252 | * TSyBoolean swap; input; swap data in input |
---|
1253 | * char req_start[]; input; requested start time |
---|
1254 | * float seclth; input; number of seconds to be read |
---|
1255 | * INT32 **ldat; output; sample array read |
---|
1256 | * INT32 *smplth; output; number of samples read |
---|
1257 | * char act_start[]; output; actual start time |
---|
1258 | * float *dt; output; sample distance in sec |
---|
1259 | * float *calib; output; calibration constant |
---|
1260 | * TSyStatus *status; output; return status |
---|
1261 | */ |
---|
1262 | { |
---|
1263 | /* local variables */ |
---|
1264 | FILE *gfd; /* pointer to gfdfile */ |
---|
1265 | char fc; /* first character */ |
---|
1266 | |
---|
1267 | /* executable code */ |
---|
1268 | |
---|
1269 | if (strncmp(gfdfile,"DB:",3) == 0 || strncmp(gfdfile,"db:",3) == 0) { |
---|
1270 | /* db: works for seed only */ |
---|
1271 | fc = 's'; |
---|
1272 | } else { |
---|
1273 | /* check first character in gfdfile */ |
---|
1274 | gfd = sy_fopen( gfdfile, "r" ); |
---|
1275 | if (gfd == NULL) { |
---|
1276 | err_setcontext( " ## file " ); |
---|
1277 | err_setcontext( gfdfile ); |
---|
1278 | *status = GcfERR_OPENINPUT; |
---|
1279 | return; |
---|
1280 | } /*endif*/ |
---|
1281 | fc = (char)fgetc( gfd ); |
---|
1282 | sy_fclose( gfd ); |
---|
1283 | } /*endif*/ |
---|
1284 | |
---|
1285 | if (fc == 'g') { |
---|
1286 | |
---|
1287 | GcfReadStream( chan, gfdfile, stream_str, swap, req_start, |
---|
1288 | seclth, ldat, smplth, act_start, dt, calib, flags, status ); |
---|
1289 | |
---|
1290 | } else { |
---|
1291 | |
---|
1292 | SeedReadStream( chan, gfdfile, stream_str, swap, req_start, |
---|
1293 | seclth, ldat, smplth, act_start, dt, calib, flags, status ); |
---|
1294 | |
---|
1295 | } /*endif*/ |
---|
1296 | |
---|
1297 | } /* end of GcfOrSeedReadStream */ |
---|
1298 | |
---|
1299 | |
---|
1300 | |
---|
1301 | /*---------------------------------------------------------------------*/ |
---|
1302 | |
---|
1303 | |
---|
1304 | |
---|
1305 | float GcfFindStreamCalibration( char stream[], char stime[], TSyStatus *status ) |
---|
1306 | |
---|
1307 | /* returns calibration value for counts for given stream 'stream' at time |
---|
1308 | * 'stime'. |
---|
1309 | * |
---|
1310 | * parameters of routine |
---|
1311 | * char stream[]; input; stream string |
---|
1312 | * char stime[]; input; time |
---|
1313 | * TSyStatus *status; output; return status |
---|
1314 | * returns calibration or 0.0 |
---|
1315 | */ |
---|
1316 | { |
---|
1317 | /* local variables */ |
---|
1318 | char calfile[cBcFileLth+1]; /* name of calibration file */ |
---|
1319 | char *eptr; /* pointer to environment variable */ |
---|
1320 | FILE *fp; /* pointer to input file */ |
---|
1321 | char line[cBcLineLth+1]; /* current line of input file */ |
---|
1322 | char v_start[cBcLineLth+1]; /* start of valid time */ |
---|
1323 | char v_end[cBcLineLth+1]; /* end of valid time */ |
---|
1324 | float lcalib; /* current value of calibration */ |
---|
1325 | |
---|
1326 | /* executable code */ |
---|
1327 | |
---|
1328 | /* build filename */ |
---|
1329 | *calfile = '\0'; |
---|
1330 | eptr = (char *)getenv( "SEED_INPUTS" ); |
---|
1331 | if (eptr != NULL) { |
---|
1332 | if (strlen(eptr)+strlen(stream)+11 > cBcFileLth) { |
---|
1333 | *status = GcfERR_STROVFL; |
---|
1334 | return 0.0; |
---|
1335 | } /*endif*/ |
---|
1336 | strcpy( calfile, eptr ); |
---|
1337 | strcat( calfile, "/" ); |
---|
1338 | } /*endif*/ |
---|
1339 | strcat( calfile, "seedcalib_" ); |
---|
1340 | strcat( calfile, stream ); |
---|
1341 | |
---|
1342 | /* open file */ |
---|
1343 | fp = sy_fopen( calfile, "r" ); |
---|
1344 | if (fp == NULL) { |
---|
1345 | fprintf( stderr, "--> no calibration for %s, set to 1.0\n", stream ); |
---|
1346 | *status = GcfERR_NOCALIB; |
---|
1347 | return 1.0; |
---|
1348 | } /*endif*/ |
---|
1349 | |
---|
1350 | while (fgets(line,cBcLineLth,fp) != NULL) { |
---|
1351 | if (*line == '!' || *line == '\n') continue; |
---|
1352 | if (sscanf(line,"%s %s %f",v_start,v_end,&lcalib) != 3) { |
---|
1353 | fprintf( stderr, "--> format error in calibration file %s\n", stream ); |
---|
1354 | continue; |
---|
1355 | } /*endif*/ |
---|
1356 | if (tc_tdiff(stime,v_start,status) < 0.0) continue; |
---|
1357 | if (SySevere(status)) return 0.0; |
---|
1358 | if (tc_tdiff(stime,v_end,status) > 0.0) continue; |
---|
1359 | if (SySevere(status)) return 0.0; |
---|
1360 | sy_fclose( fp ); |
---|
1361 | return lcalib; |
---|
1362 | } /*endwhile*/ |
---|
1363 | |
---|
1364 | sy_fclose( fp ); |
---|
1365 | fprintf( stderr, "--> no valid calibration for %s %s, set to 1.0\n", |
---|
1366 | stream, stime ); |
---|
1367 | *status = GcfERR_NOCALIB; |
---|
1368 | return 1.0; |
---|
1369 | |
---|
1370 | } /* end of GcfFindStreamCalibration */ |
---|
1371 | |
---|
1372 | |
---|
1373 | |
---|
1374 | /*---------------------------------------------------------------------*/ |
---|
1375 | |
---|
1376 | |
---|
1377 | |
---|
1378 | #define DO_ABORT \ |
---|
1379 | *status = GcfERR_GFD_READ; \ |
---|
1380 | err_setcontext( " ## string " ); err_setcontext( line-1 ); \ |
---|
1381 | return; |
---|
1382 | |
---|
1383 | |
---|
1384 | |
---|
1385 | |
---|
1386 | void GcfParseGfdLine( char line[], GcfFileDescrT *fd, TSyStatus *status ) |
---|
1387 | |
---|
1388 | /* parses line of GFD file. Returns structure elements 'stream', |
---|
1389 | * 't_start', 't_end', 'name', 'blkno' and 'calib'. |
---|
1390 | * |
---|
1391 | * parameters of routine |
---|
1392 | * char line[]; input; GFD line |
---|
1393 | * GcfFileDescrT *fd; output; GCF file descriptor |
---|
1394 | * TSyStatus *status; output; return status |
---|
1395 | */ |
---|
1396 | { |
---|
1397 | /* local variables */ |
---|
1398 | |
---|
1399 | /* executable code */ |
---|
1400 | |
---|
1401 | fd->t_start[0] = '\0'; |
---|
1402 | fd->t_end[0] = '\0'; |
---|
1403 | fd->name[0] = '\0'; |
---|
1404 | fd->stream[0] = '\0'; |
---|
1405 | fd->blkno = 0; |
---|
1406 | fd->blklth = DEFAULT_BLKLTH; |
---|
1407 | fd->calib = 0.0; |
---|
1408 | fd->dataflags = 0; |
---|
1409 | |
---|
1410 | FOREVER { |
---|
1411 | |
---|
1412 | if (*line == '>') line++; |
---|
1413 | line = strchr( line, '>' ); |
---|
1414 | if (line == NULL) break; |
---|
1415 | switch (*(line-1)) { |
---|
1416 | case Gcf_C_GfdTStart: |
---|
1417 | if (sscanf(line+1,"%s",fd->t_start) != 1) { DO_ABORT } |
---|
1418 | break; |
---|
1419 | case Gcf_C_GfdTEnd: |
---|
1420 | if (sscanf(line+1,"%s",fd->t_end) != 1) { DO_ABORT } |
---|
1421 | break; |
---|
1422 | case Gcf_C_GfdName: |
---|
1423 | if (sscanf(line+1,"%s",fd->name) != 1) { DO_ABORT } |
---|
1424 | break; |
---|
1425 | case Gcf_C_GfdStream: |
---|
1426 | if (sscanf(line+1,"%s",fd->stream) != 1) { DO_ABORT } |
---|
1427 | break; |
---|
1428 | case Gcf_C_GfdBlkno: |
---|
1429 | if (sscanf(line+1,"%d",&(fd->blkno)) != 1) { DO_ABORT } |
---|
1430 | break; |
---|
1431 | case Gcf_C_GfdBlklth: |
---|
1432 | if (sscanf(line+1,"%d",&(fd->blklth)) != 1) { DO_ABORT } |
---|
1433 | break; |
---|
1434 | case Gcf_C_GfdCalib: |
---|
1435 | if (sscanf(line+1,"%f",&(fd->calib)) != 1) { DO_ABORT } |
---|
1436 | break; |
---|
1437 | } /*endswitch*/ |
---|
1438 | |
---|
1439 | } /*endfor*/ |
---|
1440 | |
---|
1441 | } /* end of GcfParseGfdLine */ |
---|
1442 | |
---|
1443 | |
---|
1444 | |
---|
1445 | #undef DO_ABORT |
---|
1446 | |
---|
1447 | |
---|
1448 | |
---|
1449 | /*----------------------------------------------------------------------------*/ |
---|
1450 | |
---|
1451 | |
---|
1452 | |
---|
1453 | GcfLongT GcfGet4Bytes( FILE *fp, TSyStatus *status ) |
---|
1454 | |
---|
1455 | /* Reads 4 bytes from file |
---|
1456 | * |
---|
1457 | * parameters of routine |
---|
1458 | * FILE *fp; input; pointer to file |
---|
1459 | * TSyStatus *status; output; return status |
---|
1460 | * returns 4 bytes read |
---|
1461 | */ |
---|
1462 | { |
---|
1463 | /* local variables */ |
---|
1464 | unsigned char b[4]; /* bytes read */ |
---|
1465 | GcfLongT val; /* return value */ |
---|
1466 | |
---|
1467 | /* executable code */ |
---|
1468 | |
---|
1469 | if (fread(b,1,4,fp) != 4) { |
---|
1470 | *status = GcfERR_READFILE; |
---|
1471 | return 0; |
---|
1472 | } /*endif*/ |
---|
1473 | |
---|
1474 | val = (b[gcfv_byteorder[0]] << 24) + (b[gcfv_byteorder[1]] << 16) |
---|
1475 | + (b[gcfv_byteorder[2]] << 8) + b[gcfv_byteorder[3]]; |
---|
1476 | |
---|
1477 | return val; |
---|
1478 | |
---|
1479 | } /* end of GcfGet4Bytes */ |
---|
1480 | |
---|
1481 | |
---|
1482 | |
---|
1483 | /*----------------------------------------------------------------------------*/ |
---|
1484 | |
---|
1485 | |
---|
1486 | |
---|
1487 | GcfLongT GcfOrder4Bytes( unsigned char b[] ) |
---|
1488 | |
---|
1489 | /* Reorders 4 bytes read from stream to get longword |
---|
1490 | * |
---|
1491 | * parameters of routine |
---|
1492 | * unsigned char b[]; input; 4 bytes read from file as char string |
---|
1493 | * returns 4 bytes for longword |
---|
1494 | */ |
---|
1495 | { |
---|
1496 | /* local variables */ |
---|
1497 | GcfLongT val; /* return value */ |
---|
1498 | |
---|
1499 | /* executable code */ |
---|
1500 | |
---|
1501 | val = (b[gcfv_byteorder[0]] << 24) + (b[gcfv_byteorder[1]] << 16) |
---|
1502 | + (b[gcfv_byteorder[2]] << 8) + b[gcfv_byteorder[3]]; |
---|
1503 | |
---|
1504 | return val; |
---|
1505 | |
---|
1506 | } /* end of GcfOrder4Bytes */ |
---|
1507 | |
---|
1508 | |
---|
1509 | |
---|
1510 | /*----------------------------------------------------------------------------*/ |
---|
1511 | |
---|
1512 | |
---|
1513 | |
---|
1514 | void GcfDecodeTime( GcfTimeT gcftime, NTIME *ntime ) |
---|
1515 | |
---|
1516 | /* decodes GCF time |
---|
1517 | * |
---|
1518 | * parameters of routine |
---|
1519 | * GcfTimeT gcftime; input; GCF encoded time |
---|
1520 | * NTIME *ntime; output; numeric time |
---|
1521 | */ |
---|
1522 | { |
---|
1523 | /* local variables */ |
---|
1524 | unsigned wday; /* word containing days */ |
---|
1525 | unsigned wsec; /* word containing seconds */ |
---|
1526 | int daycount[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
---|
1527 | |
---|
1528 | /* executable code */ |
---|
1529 | |
---|
1530 | wsec = gcftime & 0x0001ffff; |
---|
1531 | wday = (gcftime & 0xfffe0000) >> 17; |
---|
1532 | |
---|
1533 | /* date is referenced from 17-Nov-1989 */ |
---|
1534 | ntime->year = 1989; |
---|
1535 | ntime->month = 10; |
---|
1536 | ntime->day = 0; |
---|
1537 | wday += 16; |
---|
1538 | while (wday >= daycount[ntime->month]) { |
---|
1539 | wday -= daycount[ntime->month]; |
---|
1540 | ntime->year += (ntime->month + 1) / 12; |
---|
1541 | ntime->month = (ntime->month + 1) % 12; |
---|
1542 | if (GcfIsLeapYear(ntime->year)) { |
---|
1543 | daycount[1] = 29; |
---|
1544 | } else { |
---|
1545 | daycount[1] = 28; |
---|
1546 | } /*endif*/ |
---|
1547 | } /*endwhile*/ |
---|
1548 | (ntime->month)++; |
---|
1549 | ntime->day = wday+1; |
---|
1550 | |
---|
1551 | ntime->hour = wsec / 3600; |
---|
1552 | ntime->min = (wsec % 3600) / 60; |
---|
1553 | ntime->sec = wsec % 60; |
---|
1554 | ntime->ms = 0; |
---|
1555 | |
---|
1556 | } /* end of GcfDecodeTime */ |
---|
1557 | |
---|
1558 | |
---|
1559 | |
---|
1560 | /*----------------------------------------------------------------------------*/ |
---|
1561 | |
---|
1562 | |
---|
1563 | void GcfBase36ToString( GcfLongT id, char str[] ) |
---|
1564 | |
---|
1565 | /* Converts base36 number to string. Routine taken from Guralp manual. |
---|
1566 | * |
---|
1567 | * parameters of routine |
---|
1568 | * unsigned INT32 id; input; base36 number |
---|
1569 | * char str[]; output; decoded string |
---|
1570 | */ |
---|
1571 | { |
---|
1572 | /* local variables */ |
---|
1573 | int imed; /* some counter */ |
---|
1574 | int i; /* another counter */ |
---|
1575 | |
---|
1576 | /* executable code */ |
---|
1577 | |
---|
1578 | str[6] = '\0'; |
---|
1579 | for (i=5; i>=0; i--) { |
---|
1580 | imed = id % 36; |
---|
1581 | if (imed > 9) |
---|
1582 | imed += 7; |
---|
1583 | str[i] = imed + '0'; |
---|
1584 | id /= 36; |
---|
1585 | } /*endfor*/ |
---|
1586 | |
---|
1587 | } /* end of GcfBase36ToString */ |
---|
1588 | |
---|
1589 | |
---|
1590 | |
---|
1591 | /*---------------------------------------------------------------------*/ |
---|
1592 | |
---|
1593 | |
---|
1594 | |
---|
1595 | void GcfAcceptCapfiles( TSyBoolean on_off ) |
---|
1596 | |
---|
1597 | /* switches on/off whether capitalized filenames on $ROOT-paths are accepted |
---|
1598 | * |
---|
1599 | * parameters of routine |
---|
1600 | * TSyBoolean on_off; input; switch |
---|
1601 | */ |
---|
1602 | { |
---|
1603 | /* executable code */ |
---|
1604 | |
---|
1605 | gcfv_capfiles = on_off; |
---|
1606 | |
---|
1607 | } /* end of GcfAcceptCapfiles */ |
---|
1608 | |
---|
1609 | |
---|
1610 | |
---|
1611 | /*----------------------------------------------------------------------------*/ |
---|
1612 | |
---|
1613 | |
---|
1614 | |
---|
1615 | static TSyBoolean GcfIsLeapYear( int year ) |
---|
1616 | |
---|
1617 | /* Returns whether year is leap year or not. |
---|
1618 | * |
---|
1619 | * parameters of routine |
---|
1620 | * int year; input; year |
---|
1621 | * returns TRUE if year is leap year |
---|
1622 | */ |
---|
1623 | { |
---|
1624 | /* executable code */ |
---|
1625 | |
---|
1626 | return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))); |
---|
1627 | |
---|
1628 | } /* end of GcfIsLeapYear */ |
---|
1629 | |
---|
1630 | |
---|
1631 | |
---|
1632 | /*---------------------------------------------------------------------*/ |
---|
1633 | |
---|
1634 | |
---|
1635 | |
---|
1636 | static void GcfAdjustFilename( GcfFileDescrT *dsc, TSyStatus *status ) |
---|
1637 | |
---|
1638 | /* copies directory of gfd-file to data filename |
---|
1639 | * |
---|
1640 | * parameters of routine |
---|
1641 | * GcfFileDescrT *dsc; modify; GCF file descriptor |
---|
1642 | * TSyStatus *status; output; return status |
---|
1643 | */ |
---|
1644 | { |
---|
1645 | /* local variables */ |
---|
1646 | int i; /* counter */ |
---|
1647 | int strlth; /* string length */ |
---|
1648 | char path[cBcFileLth+1]; /* path name */ |
---|
1649 | BOOLEAN iscolon; /* is there a colon ? */ |
---|
1650 | char upname[cBcFileLth+1]; /* uppercase filename */ |
---|
1651 | |
---|
1652 | /* executable code */ |
---|
1653 | |
---|
1654 | /* find path in gfdfile */ |
---|
1655 | i = strlen( dsc->gfdfile ) - 1; |
---|
1656 | while (i >= 0 && dsc->gfdfile[i] != '/' && dsc->gfdfile[i] != ':' |
---|
1657 | && dsc->gfdfile[i] != '\\') i--; |
---|
1658 | if (i > 0) { |
---|
1659 | strncpy( path, dsc->gfdfile, i ); |
---|
1660 | path[i] = '\0'; |
---|
1661 | iscolon = (dsc->gfdfile[i] == ':'); |
---|
1662 | } else { |
---|
1663 | *path = '\0'; |
---|
1664 | iscolon = FALSE; |
---|
1665 | } /*endif*/ |
---|
1666 | |
---|
1667 | if (strlen(dsc->name)-ROOTDIRLTH+strlen(path) > cBcFileLth) { |
---|
1668 | *status = GcfERR_STROVFL; |
---|
1669 | return; |
---|
1670 | } /*endif*/ |
---|
1671 | |
---|
1672 | if (*path != '\0') { |
---|
1673 | strlth = strlen( path ); |
---|
1674 | for (i=0; i<strlth; i++) |
---|
1675 | if (path[i] == '\\') path[i] = '/'; |
---|
1676 | if (iscolon) { |
---|
1677 | strcat( path, ":" ); |
---|
1678 | if (gcfv_capfiles) { |
---|
1679 | strcpy( upname, dsc->name+ROOTDIRLTH+1 ); |
---|
1680 | ut_cap( upname ); |
---|
1681 | strcat( path, upname ); |
---|
1682 | } else { |
---|
1683 | strcat( path, dsc->name+ROOTDIRLTH+1 ); |
---|
1684 | } /*endif*/ |
---|
1685 | } else { |
---|
1686 | if (gcfv_capfiles) { |
---|
1687 | strcpy( upname, dsc->name+ROOTDIRLTH ); |
---|
1688 | ut_cap( upname ); |
---|
1689 | strcat( path, upname ); |
---|
1690 | } else { |
---|
1691 | strcat( path, dsc->name+ROOTDIRLTH ); |
---|
1692 | } /*endif*/ |
---|
1693 | } /*endif*/ |
---|
1694 | } else { |
---|
1695 | strcpy( path, dsc->name+ROOTDIRLTH+1 ); |
---|
1696 | } /*endif*/ |
---|
1697 | strcpy( dsc->name, path ); |
---|
1698 | |
---|
1699 | } /* end of GcfAdjustFilename */ |
---|
1700 | |
---|
1701 | |
---|
1702 | |
---|
1703 | /*----------------------------------------------------------------------------*/ |
---|