comparison srf2fastq/io_lib-1.12.2/io_lib/expFileIO.c @ 0:d901c9f41a6a default tip

Migrated tool version 1.0.1 from old tool shed archive to new tool shed repository
author dawe
date Tue, 07 Jun 2011 17:48:05 -0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:d901c9f41a6a
1 /*
2 * Copyright (c) Medical Research Council 1994. All rights reserved.
3 *
4 * Permission to use, copy, modify and distribute this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * this copyright and notice appears in all copies.
7 *
8 * This file was written by James Bonfield, Simon Dear, Rodger Staden,
9 * as part of the Staden Package at the MRC Laboratory of Molecular
10 * Biology, Hills Road, Cambridge, CB2 2QH, United Kingdom.
11 *
12 * MRC disclaims all warranties with regard to this software.
13 */
14
15 /*
16 * File: expFileIO.c
17 * Version:
18 *
19 * Description: Routines for reading and writing to experiment files.
20 *
21 * 1. Opening experiment files
22 * 2. Reading information from an experiment file
23 * 3. Appending to experiment files
24 * 4. Closing an opened experiment file
25 *
26 * Created:
27 * Updated:
28 *
29 */
30
31 /*
32 * Tag format:
33 *
34 * 0 10
35 * |----.----|-
36 * TG TYPE S position..length
37 * TG One or more comment lines starting at character position 10
38 * TG Each line represents a line of tag.
39 * TG Extra indentation is simply added to the comment.
40 *
41 * Where S is the strand, either "+", "-", or "=" (both).
42 * Eg:
43 *
44 * TG COMM = 100..110
45 * TG This comment contains
46 * TG several lines.
47 *
48 * So the above is a COMMent tag on both strands from bases 100 to 110
49 * inclusive containing the annotation
50 * "This comment contains\n several lines.\n"
51 *
52 * This is written using exp_put_str giving the multi line string:
53 * "COMM = 100..110\nThis comment contains\n several lines."
54 *
55 * (ie the indentation is added by the experiment file format, not by the
56 * calling routines. Similarly this indentation is stripped out again when
57 * reading back.)
58 */
59
60
61 #include <stdio.h>
62 #include <string.h> /* IMPORT: strdup (hopefully!) */
63 #include <ctype.h>
64
65 /* 6/1/99 johnt - includes needed for Visual C++ */
66 #ifdef _MSC_VER
67 # include <io.h>
68 # include <fcntl.h>
69 #endif
70
71 #include "io_lib/expFileIO.h"
72 #include "io_lib/xalloc.h"
73 #include "io_lib/misc.h"
74 #include "io_lib/stdio_hack.h"
75
76 /* Fixup for broken SunOS 4.x systems */
77 #ifndef FOPEN_MAX
78 #define FOPEN_MAX 20
79 #endif
80
81 static int exp_check_eid_read(Exp_info *e,int id);
82
83 /*************************************************************
84 * Line types for experiment file
85 *************************************************************/
86
87 char eflt_feature_ids[MAXIMUM_EFLTS][MAXIMUM_EFLT_LENGTH+1] = {
88 "CF", /* 0 cloning vector sequence file */
89 "CN", /* 1 clone name */
90 "CS", /* 2 cloning vector sequence present in sequence */
91 "CV", /* 3 cloning vector type */
92 "DR", /* 4 direction of read */
93 "DT", /* 5 date of experiment */
94 "EN", /* 6 experiment name */
95 "EX", /* 7 experimental notes */
96 "FM", /* 8 sequencing vector fragmentation method */
97 "LN", /* 9 local format trace file name */
98 "LT", /* 10 local format trace file type */
99 "MC", /* 11 machine on which experiment ran */
100 "MN", /* 12 machine generated trace file name */
101 "MT", /* 13 machine generated trace file type */
102 "OP", /* 14 operator */
103 "PN", /* 15 primer name */
104 "QR", /* 16 poor quality sequence present at right (3') end */
105 "SC", /* 17 sequencing vector cloning site */
106 "SF", /* 18 sequencing vector sequence file */
107 "SI", /* 19 sequencing vector insertion length */
108 "SL", /* 20 sequencing vector present at left (5') end */
109 "SP", /* 21 sequencing vector primer site (relative to cloning site) */
110 "SQ", /* 22 sequence */
111 "SR", /* 23 sequencing vector present at right (3') end */
112 "ST", /* 24 strands */
113 "SV", /* 25 sequencing vector type */
114 "TN", /* 26 template name */
115 "QL", /* 27 poor quality sequence present at left (5') end */
116 "PS", /* 28 processing status */
117 "CC", /* 29 comments */
118 "SS", /* 30 sequence to screen against */
119 /* added 27-May-93 */
120 "TG", /* 31 gel tag line */
121 "ID", /* 32 identifier */
122 /* added 24-Sep-93 */
123 "AQ", /* 33 average quality measure */
124 /* added 15-Oct-93 */
125 "PR", /* 34 primer type */
126 "LI", /* 35 subclone library (mtd) */
127 "LE", /* 36 subclone library entry (well) */
128 /* added 19-Apr-94 */
129 "TC", /* 37 contig tag line */
130 "AC", /* 38 accession number */
131 /* added 11-Nov-94 */
132 "BC", /* 39 base calling software */
133 "ON", /* 40 original base numbers (positions) */
134 "AV", /* 41 accuracy (quality) values */
135 "PC", /* 42 position in contig */
136 "SE", /* 43 sense, whether it is complemented */
137 /* added 5-4-95 */
138 "CL", /* 44 cloning vector left end*/
139 "CR", /* 45 cloning vector right end*/
140 "AP", /* 46 assembly position */
141 "CH", /* 47 special chemistry used (eg taq) */
142 "PD", /* 48 primer data - the sequence of a primer */
143 "WT", /* 49 wild type trace */
144 "NT", /* 50 note */
145 "GD", /* 51 Gap4 database file */
146 "WL", /* 52 wildtype trace left clip point */
147 "WR", /* 53 wildtype trace right clip point */
148 "FT", /* 54 EMBL format feature table */
149 "LG" /* 55 LiGation: an amalgamation of LI and LE */
150 };
151
152
153
154
155 /*************************************************************
156 * Output/update lines
157 *************************************************************/
158
159 static int exp_print_line_(FILE *fp, char *eflt, char *entry)
160 /*
161 * Output an experiment file line
162 */
163 {
164 return fprintf(fp,
165 "%-5s%s\n",
166 eflt,
167 entry
168 ) < 0;
169 }
170
171 int exp_print_line(FILE *fp, Exp_info *e, int eflt, int i)
172 /*
173 * Output an experiment file line
174 */
175 {
176 return exp_print_line_(fp,
177 eflt_feature_ids[eflt],
178 arr(char *,e->entries[eflt],i)
179 );
180 }
181
182 /*
183 * Outputs a multi-line experiment file line.
184 * Continuation lines are automatically added by adding 5 characters of extra
185 * indentation at the start of each continuation.
186 *
187 * returns -1 for failure, 0 for success.
188 */
189 int exp_print_mline(FILE *fp, Exp_info *e, int eflt, int i) {
190 char *p, *c;
191
192 p = arr(char *, e->entries[eflt], i);
193
194 /* first line */
195 if (c = strchr(p, '\n'))
196 *c = '\0';
197 if (-1 == exp_print_line_(fp, eflt_feature_ids[eflt], p))
198 return -1;
199
200 while (c) {
201 *c = '\n';
202 p = c+1;
203
204 if (c = strchr(p, '\n')) {
205 *c = '\0';
206 }
207
208 if (-1 == fprintf(fp, "%-10s%s\n", eflt_feature_ids[eflt], p))
209 return -1;
210 }
211
212 return 0;
213 }
214
215
216 int exp_print_seq(FILE *fp, Exp_info *e, int eflt, int i)
217 /*
218 * Output an experiment file multi line
219 */
220 {
221 int j, l;
222 char *seq;
223 if (fprintf(fp,"%-5s",eflt_feature_ids[eflt])<0) return 1;
224
225 l = strlen(seq = arr(char *,e->entries[eflt],i));
226 for(j=0;j<l;j++) {
227 if (j%60==0) if ( fprintf(fp,"\n ") < 0 ) return 1;
228 if (j%10==0) if ( fprintf(fp," ") < 0 ) return 1;
229 if ( fprintf(fp,"%c",seq[j]) < 0 ) return 1;
230 }
231 if ( fprintf(fp,"\n//\n") < 0 ) return 1;
232
233 return 0;
234 }
235
236 int exp_get_feature_index(char *e)
237 {
238 int i;
239 for (i = 0; i < MAXIMUM_EFLTS; i++) {
240 if (eflt_feature_ids[i][0] == e[0] &&
241 eflt_feature_ids[i][1] == e[1])
242 return i;
243 }
244
245 return -1;
246 }
247
248
249 /*************************************************************
250 * Utility routines
251 *************************************************************/
252
253 /*
254 * Creates a string of 'range format' from the start and end points.
255 * The string (of form start..end) is also returned.
256 */
257 char *exp_create_range(char *str, int start, int end) {
258 sprintf(str, "%d..%d", start, end);
259 return str;
260 }
261
262 /*
263 * Extracts the start and end points from a range string.
264 * Returns 0 for success and -1 for failure.
265 */
266 int exp_extract_range(char *str, int *start, int *end) {
267 return sscanf(str, "%d..%d", start, end) != 2;
268 }
269
270 Exp_info *exp_create_info(void)
271 /*
272 * Allocate space for new experiment file information
273 */
274 {
275 Exp_info *new;
276 int i;
277
278 new = (Exp_info *)xmalloc(sizeof(Exp_info));
279 if (new != NULL) {
280 for(i=0; i< MAXIMUM_EFLTS ; i++) {
281 new->Nentries[i] = 0;
282 new->entries[i] = ArrayCreate(sizeof(char *), 1/*one entry*/);
283 }
284 new->fp = NULL;
285 }
286
287 return new;
288 }
289
290
291 void exp_destroy_info(Exp_info *e)
292 /*
293 * Destroy experiment file information
294 */
295 {
296 int i;
297 int j;
298 if (e != NULL_Exp_info) {
299 for (i = 0; i < MAXIMUM_EFLTS; i++) {
300 Array a = e->entries[i];
301 for(j=0;j<e->Nentries[i];j++)
302 if (arr(char *,a,j) != NULL) xfree(arr(char *,a,j));
303 ArrayDestroy(a);
304 }
305 if (e->fp != NULL) fclose(e->fp);
306 xfree(e);
307 }
308 }
309
310
311
312
313 /*
314 * Read from file a sequence, discarding all white space til a // is
315 * encountered
316 */
317 static char *exp_read_sequence(FILE *fp)
318 {
319 char *seq = NULL;
320 size_t seq_len = 0, seq_alloc;
321 char line[EXP_FILE_LINE_LENGTH+1];
322 char *l;
323 static int valid_char[256], init = 0;
324
325 /* Initialise lookup tables for efficiency later on.*/
326 if (!init) {
327 int i;
328 for (i = 0; i < 256; i++) {
329 if (i < 128 && !isspace(i) && !isdigit(i) && !iscntrl(i))
330 valid_char[i] = 1;
331 else
332 valid_char[i] = 0;
333 }
334 init = 1;
335 }
336
337 /* Initialise memory */
338 seq_alloc = EXP_FILE_LINE_LENGTH * 8;
339 seq = (char *)xmalloc(seq_alloc);
340 if (NULL == seq)
341 return NULL;
342 seq[0] = '\0';
343
344 /* Reading line by line, until we get "//" */
345 l = fgets(line,EXP_FILE_LINE_LENGTH,fp);
346 while (l!= NULL && strncmp(l,"//",2)) {
347 char *a, *b;
348
349 /* make sure the seq buffer is large enough */
350 if (seq_len + EXP_FILE_LINE_LENGTH + 1 > seq_alloc) {
351 seq_alloc *= 2;
352 if (NULL == (seq = (char *)xrealloc(seq, seq_alloc)))
353 return NULL;
354 }
355
356 /* copy to seq, stripping spaces on the fly */
357 for(a=line, b = &seq[seq_len]; *a; a++)
358 if (valid_char[(unsigned char)*a])
359 *b++ = *a;
360 *b = '\0';
361 seq_len = b-seq;
362
363 l = fgets(line,EXP_FILE_LINE_LENGTH,fp);
364 }
365
366 /* Shrink the allocated string to reduce memory usage */
367 seq = (char *)xrealloc(seq, seq_len + 1);
368
369 return seq;
370 }
371
372
373 /*
374 * Converts the opos[] array into a char array.
375 * In doing so this shrinks the data size by using a .. notation.
376 * No check is made that buf is large enough. It is recommended that buf is
377 * allocated to 5*len which covers the worst case (for sequences less that
378 * 9999 bases long).
379 *
380 * Note that on older systems sprintf may return the first argument rather
381 * than the number of characters written.
382 * For this reason we have to do the counting ourselves.
383 */
384 char *opos2str(int2 *opos, int len, char *buf) {
385 int i, st, f, dir = 0;
386 char *r = buf, *rs = buf;
387
388 f = opos[st = 0];
389 for (i = 1; i < len; f=opos[i++]) {
390 if (dir == 0)
391 if (opos[i] == f+1)
392 dir=1;
393 else if (opos[i] == f-1)
394 dir=-1;
395
396 if (dir && opos[i] != f + dir) {
397 if (st != i-1)
398 sprintf(buf, "%d..%d ", opos[st], opos[i-1]);
399 else
400 sprintf(buf, "%d ", opos[st]);
401 st = i;
402 dir = 0;
403
404 buf += strlen(buf);
405
406 } else if (dir == 0) {
407 sprintf(buf, "%d ", f);
408
409 st = i;
410 buf += strlen(buf);
411 }
412
413 if (buf - rs > 60) {
414 *buf++ = '\n';
415 *buf = '\0';
416 rs = buf - 6;
417 }
418 }
419
420 if (st != i-1)
421 sprintf(buf, "%d..%d", opos[st], opos[i-1]);
422 else
423 sprintf(buf, "%d", opos[st]);
424
425 return r;
426 }
427
428
429
430 /*
431 * Expands from the character string .. notation to the opos[] array, up to
432 * a maximum of len elements in opos[].
433 *
434 * Returns the length of the opos array.
435 */
436 int str2opos(int2 *opos, int len, char *buf) {
437 /* int i, n1, n2, st, en, m, j = 0; */
438 int i, j = 0, st, en;
439 char *cp;
440
441 while (j < len && *buf) {
442 st = strtol(buf, &cp, 10);
443 if (buf == cp) {
444 buf++;
445 continue;
446 }
447 buf = cp;
448 if (buf[0] == '.' && buf[1] == '.') {
449 en = strtol(buf += 2, &cp, 10);
450 if (buf == cp) {
451 opos[j++] = st;
452 buf++;
453 continue;
454 }
455 buf = cp;
456
457 if (en >= st)
458 for (i = st; i <= en && j < len; i++)
459 opos[j++] = i;
460 else
461 for (i = st; i >= en && j < len; i--)
462 opos[j++] = i;
463 } else {
464 opos[j++] = st;
465 }
466 }
467
468 return j;
469 }
470
471
472 /*
473 * Converts the accuracy value string (AV) to the confidence array up to
474 * a maximum of len elements in conf[].
475 *
476 * The AV string is of format:
477 * "x y z ..." where x, y and z are confidence values for the first three
478 * called bases. Or:
479 * "a,b,c,d e,f,g,h i,j,k,l ..." where the 4-tuples represent the four
480 * confidence values for each base.
481 *
482 * Returns: number of confidence values read, or -1 for error.
483 */
484 int str2conf(int1 *conf, int len, char *buf) {
485 int ind = 0;
486
487 while (*buf && ind < len) {
488 char *new_buf;
489 int val1;
490
491 val1 = strtol(buf, &new_buf, 10);
492 if (new_buf == buf)
493 break;
494
495 if (*new_buf == ',') {
496 fprintf(stderr, "4-tuple system is currently unsupported\n");
497 return -1;
498 }
499
500 conf[ind++] = val1;
501 buf = new_buf;
502 }
503
504 return ind;
505 }
506
507
508 /*
509 * Converts the confidence array to the accuracy value string (AV).
510 *
511 * Note no memory overrun checks are performed on buf. It is recommended
512 * that it is allocated to 4*len (worst case of "255 " for each base) plus.
513 * a couple of terminating newline and null plus another byte per 15 values
514 * to allow for the 60-char line length.
515 * For ease, allocating to 5*len+2 is more than sufficient.
516 *
517 * Returns the buf argument.
518 */
519 char *conf2str(int1 *conf, int len, char *buf) {
520 int i;
521 char *ret = buf, *rs = buf;
522
523 for (i = 0; i < len; i++) {
524 sprintf(buf, "%d ", conf[i]);
525 buf += strlen(buf);
526
527 if (buf - rs > 60) {
528 *buf++ = '\n';
529 *buf = '\0';
530 rs = buf - 6;
531 }
532 }
533
534 return ret;
535 }
536
537 /*************************************************************
538 * Main C interface routines
539 *************************************************************/
540
541
542 /*
543 * Closes an experiment file (if open), but does not free it.
544 */
545 void exp_close(Exp_info *e) {
546 if (e->fp) {
547 fclose(e->fp);
548 e->fp = NULL;
549 }
550 }
551
552
553 Exp_info *exp_read_info(char *file)
554 /*
555 * Read in an experiment file and return handle
556 */
557 {
558 Exp_info *e;
559 FILE *fp;
560
561 /*
562 * open for read
563 */
564 if ((fp = fopen(file,"r"))==NULL) {
565 return NULL_Exp_info;
566 }
567
568 e = exp_fread_info(fp);
569 fclose(fp);
570
571 if (NULL_Exp_info == e) {
572 return NULL_Exp_info;
573 }
574
575 /*
576 * reopen for appending
577 */
578 e->fp = fopen(file,"a");
579
580 return e;
581
582 }
583
584
585 /*
586 * Read in an experiment file and return handle
587 */
588 Exp_info *exp_fread_info(FILE *fp)
589 {
590 Exp_info *e;
591 char line[EXP_FILE_LINE_LENGTH+1];
592 char *aline;
593 int alloced_length = EXP_FILE_LINE_LENGTH+1;
594 int apos, len;
595 int last_entry = -1;
596 size_t entry_len = 0;
597
598 e = exp_create_info();
599
600
601 /*
602 * No longer has an effect due to mFILE already being loaded. Ifdef not
603 * triggered under mingw anyway.
604 */
605 #ifdef _WIN32
606 /* 6/1/99 johnt - need to ensure text mode to translate \r\n to \n */
607 /* _setmode(fileno(fp),_O_TEXT); */
608 mfascii(fp);
609 #endif
610
611 /*
612 * open for read, set this temporarily in this function. Should be NULL
613 * when exiting as this isn't our file pointer to own, but the destroy
614 * function does attempt to automatically close it.
615 */
616 e->fp = fp;
617
618 if (NULL == (aline = (char *)xmalloc(alloced_length)))
619 return NULL;
620
621 if (e != NULL_Exp_info) {
622 int at_end = 0;
623
624 for(;;) {
625 char *c;
626 int entry;
627
628 /* Read into aline, joining and allocating as necessary */
629 apos = 0;
630 do {
631 if (fgets(line,EXP_FILE_LINE_LENGTH,e->fp) == NULL) {
632 at_end = 1;
633 break;
634 }
635
636 len = strlen(line);
637 if (apos + len >= alloced_length) {
638 alloced_length *= 2;
639 if (NULL == (aline = (char *)xrealloc(aline,
640 alloced_length))) {
641 e->fp = NULL;
642 return NULL;
643 }
644 }
645
646 strcpy(aline+apos, line);
647 apos += len;
648 } while (line[len-1] != '\n');
649
650 if (at_end)
651 break;
652
653 /*
654 * zero terminate first argument
655 * set c to point to second argument
656 *
657 * FIXME: c should point to character 6 always. Indentation is
658 * important when considering continuation lines.
659 */
660 for (c=aline;*c && !isspace(*c); c++) ;
661 if (*c) {
662 *c++ = '\0';
663 for (;*c && isspace(*c); c++) ;
664 }
665
666 entry = exp_get_feature_index(aline);
667 if (entry >= 0) {
668 /*
669 * Tag lines may be split over multiple lines. If we have no
670 * tag type then we append to the existing tag.
671 */
672 if (entry == last_entry &&
673 (int)(c-aline) >= 10/* continuation lines */
674 && (entry == EFLT_TG || entry == EFLT_TC ||
675 entry == EFLT_ON || entry == EFLT_AV ||
676 entry == EFLT_NT || entry == EFLT_FT)) {
677 char *en;
678 size_t l1, l2;
679
680 /*
681 * Extend our current line by the appropriate amount
682 */
683 if( exp_check_eid_read(e,entry) )
684 return NULL;
685 en = exp_get_entry(e,entry);
686 l1 = entry_len;
687 l2 = strlen(&aline[10]);
688
689 if (NULL == (en = exp_get_entry(e, entry) =
690 (char *)xrealloc(en, l1 + l2 + 1))) {
691 e->fp = NULL;
692 return NULL;
693 }
694
695
696 /*
697 * Append the new line (without the \n char)
698 */
699 en[l1] = '\n';
700 aline[l2+9] = '\0';
701 strcpy(&en[l1+1], &aline[10]);
702
703 entry_len += l2;
704 } else {
705 /*
706 * Increment number of entries for line type entry
707 * This will force exp_get_entry() to return pointer to
708 * next free element in array
709 */
710 (void)ArrayRef(e->entries[entry],e->Nentries[entry]++);
711
712 if (entry == EFLT_SQ)
713 exp_get_entry(e,entry) = exp_read_sequence(e->fp);
714 else {
715 char *eoln = strchr(c,'\n');
716 int i;
717
718 if (eoln!=NULL) *eoln='\0';
719
720 if (entry == EFLT_LT)
721 for (i=3; isspace(c[i]) && i >= 0; c[i--]='\0');
722
723 exp_get_entry(e,entry) = (char *)strdup(c);
724 entry_len = strlen(c);
725 }
726 }
727 }
728
729 last_entry = entry;
730 }
731 }
732
733 e->fp = NULL;
734 xfree(aline);
735
736 return e;
737 }
738
739 static int exp_check_eid_read(Exp_info *e,int id)
740 /*
741 * Check these are a valid combination and that
742 * an entry exists for read
743 */
744 {
745 return (
746 e == NULL ||
747 id < 0 ||
748 id >= MAXIMUM_EFLTS ||
749 e->Nentries[id] == 0 ||
750 eflt_feature_ids[id][0]=='\0'
751 );
752 }
753
754 static int exp_check_eid_write(Exp_info *e,int id)
755 /*
756 * Check these are a valid combination and that
757 * an entry exists for write
758 */
759 {
760 return (e == NULL ||
761 id < 0 ||
762 id >= MAXIMUM_EFLTS ||
763 e->fp == NULL ||
764 eflt_feature_ids[id][0]=='\0');
765 }
766
767
768
769
770
771
772 int exp_get_int(Exp_info *e, int id, int *val)
773 /*
774 * Get the integer for entry id
775 * returns:
776 * 0 - success
777 * 1 - no entry
778 */
779 {
780 if ( exp_check_eid_read(e,id) ) return 1;
781 *val = atoi(exp_get_entry(e,id));
782 return 0;
783 }
784
785
786 int exp_get_rng(Exp_info *e, int id, int *from, int *to)
787 /*
788 * Get the integer pair for entry id
789 * returns:
790 * 0 - success
791 * 1 - no entry
792 */
793 {
794 if ( exp_check_eid_read(e,id) ) return 1;
795 (void)exp_extract_range(exp_get_entry(e,id), from, to);
796
797 return 0;
798 }
799
800
801
802 int exp_get_str(Exp_info *e, int id, char *s, f_implicit s_l)
803 /*
804 * Get the string for entry id
805 * returns:
806 * 0 - success
807 * 1 - no entry
808 */
809 {
810 if ( exp_check_eid_read(e,id) ) return 1;
811 strncpy(s,exp_get_entry(e,id),s_l);
812
813 return 0;
814 }
815
816
817 static int exp_append_str(Exp_info *e, int id, char *s, int len)
818 /*
819 * Append the string to experiment file for entry id
820 * returns:
821 * 0 - success
822 * 1 - no update
823 */
824 {
825 (void)ArrayRef(e->entries[id],e->Nentries[id]++);
826 exp_get_entry(e,id) = (char *)xmalloc(len+1);
827 strncpy(exp_get_entry(e,id), s, len);
828 exp_get_entry(e,id)[len] = '\0';
829
830 if ( id == EFLT_SQ )
831 return exp_print_seq(e->fp,e,id,e->Nentries[id]-1);
832 else if (id == EFLT_TG || id == EFLT_TC ||
833 id == EFLT_ON || id == EFLT_AV ||
834 id == EFLT_NT || id == EFLT_FT)
835 return exp_print_mline(e->fp,e,id,e->Nentries[id]-1);
836 else
837 return exp_print_line(e->fp,e,id,e->Nentries[id]-1);
838 }
839
840
841 int exp_put_int(Exp_info *e, int id, int *val)
842 /*
843 * Append the integer for entry id to the experiment file
844 * returns:
845 * 0 - success
846 * 1 - no update
847 */
848 {
849 char buf[EXP_FILE_LINE_LENGTH];
850 if ( exp_check_eid_write(e,id) ) return 1;
851 sprintf(buf,"%d",*val);
852 return exp_append_str(e,id,buf,strlen(buf));
853 }
854
855
856 int exp_put_rng(Exp_info *e, int id, int *from, int *to)
857 /*
858 * Append the integer pair for entry id to the experiment file
859 * returns:
860 * 0 - success
861 * 1 - no update
862 */
863 {
864 char buf[EXP_FILE_LINE_LENGTH];
865 if ( exp_check_eid_write(e,id) ) return 1;
866
867 (void )exp_create_range(buf, *from, *to);
868
869 return exp_append_str(e,id,buf,strlen(buf));
870 }
871
872
873
874 int exp_put_str(Exp_info *e, int id, char *s, f_implicit s_l)
875 /*
876 * Append the string for entry id to the experiment file
877 * returns:
878 * 0 - success
879 * 1 - no update
880 */
881 {
882 if ( exp_check_eid_write(e,id) ) return 1;
883 return exp_append_str(e,id,s,s_l);
884 }
885
886
887 /*************************************************************
888 * FORTRAN INTERFACE
889 *************************************************************/
890
891
892
893 static int init_done = 0;
894 static int NHandles = 0;
895 static Exp_info **Handles = NULL;
896
897 static int initialise(void)
898 {
899 int i;
900
901 if (init_done) return 0;
902 init_done++;
903
904 NHandles = FOPEN_MAX;
905
906 if ( (Handles = (Exp_info **)xmalloc(sizeof(Exp_info *) * NHandles)) == NULL) {
907 NHandles = 0;
908 return 1;
909 }
910
911 for (i=0; i<NHandles; i++) Handles[i] = NULL;
912
913 return 0;
914 }
915
916
917 static int get_free_handle(void)
918 /*
919 * find a free entry in the Exp array
920 * returns -1 if there is none
921 */
922 {
923 int i;
924
925 (void) initialise();
926
927 if (!NHandles) return -1; /* no slots! */
928 for (i=0; i<NHandles && Handles[i]!=NULL; i++) ;
929 return (i==NHandles)?-1:i;
930 }
931
932
933 static int check_handle(f_int *handle)
934 {
935 return (handle == NULL ||
936 (int) (*handle) <= 0 ||
937 (int) (*handle) > NHandles);
938 }
939
940
941
942 f_int expopn_(char *fn, f_implicit fn_l)
943 /*
944 * FORTRAN interface to exp_open_file()
945 */
946 {
947 char cfn[1025];
948 int handle;
949
950 if ( (handle = get_free_handle()) >= 0 ) {
951 f2cstr(fn,fn_l,cfn,1024);
952 Handles[handle] = exp_read_info(cfn);
953 }
954
955 return (f_int) (handle+1);
956 }
957
958
959
960 f_proc_ret expkil_(f_int *handle)
961 /*
962 * FORTRAN interface to exp_destroy_info
963 */
964 {
965 Exp_info *e;
966 if ( check_handle(handle) ) f_proc_return();
967 e = (Exp_info *) Handles[(int)(*handle)-1];
968
969 exp_destroy_info(e);
970
971 Handles[(int)(*handle)-1] = NULL;
972 *handle = 0;
973
974 f_proc_return();
975 }
976
977 f_int expri_(f_int *handle, f_int *id, f_int *val)
978 /*
979 * FORTRAN interface to exp_get_int
980 */
981 {
982 Exp_info *e;
983 if ( check_handle(handle) ) return 1;
984 e = (Exp_info *) Handles[(int)(*handle)-1];
985
986 return exp_get_int(e, (int)*id, (int *)val);
987 }
988
989
990 f_int exprr_(f_int *handle, f_int *id, f_int *from, f_int *to)
991 /*
992 * FORTRAN interface to exp_get_rng
993 */
994 {
995 Exp_info *e;
996 if ( check_handle(handle) ) return 1;
997 e = (Exp_info *) Handles[(int)(*handle)-1];
998
999 return exp_get_rng(e,(int)*id,(int *)from,(int *)to);
1000
1001 }
1002
1003 /* ARGSUSED */
1004 f_int exprsa_(f_int *handle, f_int *id, char *s, f_int *max_len, f_implicit s_l)
1005 /*
1006 * FORTRAN interface to exp_get_str workalike
1007 * NOTE: for use with FORTRAN CHARACTER arrays instead CHARACTER strings
1008 */
1009 {
1010 Exp_info *e;
1011 if ( check_handle(handle) ) return 1;
1012 e = (Exp_info *) Handles[(int)(*handle)-1];
1013
1014 if ( exp_check_eid_read(e,*id) ) return 1;
1015 c2fstr(exp_get_entry(e,*id),(int)*max_len,s,(int)*max_len);
1016 return 0;
1017 }
1018
1019
1020 f_int exprs_(f_int *handle, f_int *id, char *s, f_implicit s_l)
1021 /*
1022 * FORTRAN interface to exp_get_str workalike
1023 * NOTE: for use with FORTRAN CHARACTER strings instead CHARACTER arrays
1024 */
1025 {
1026 Exp_info *e;
1027 if ( check_handle(handle) ) return 1;
1028 e = (Exp_info *) Handles[(int)(*handle)-1];
1029
1030 if ( exp_check_eid_read(e,*id) ) return 1;
1031 c2fstr(exp_get_entry(e,*id),s_l,s,s_l);
1032 return 0;
1033 }
1034
1035
1036 f_int expwi_(f_int *handle, f_int *id, f_int *val)
1037 /*
1038 * FORTRAN interface to exp_put_int
1039 */
1040 {
1041 Exp_info *e;
1042 if ( check_handle(handle) ) return 1;
1043 e = (Exp_info *) Handles[(int)(*handle)-1];
1044
1045 return exp_put_int(e, (int)*id, (int *)val);
1046 }
1047
1048
1049 f_int expwr_(f_int *handle, f_int *id, f_int *from, f_int *to)
1050 /*
1051 * FORTRAN interface to exp_put_rng
1052 */
1053 {
1054 Exp_info *e;
1055 if ( check_handle(handle) ) return 1;
1056 e = (Exp_info *) Handles[(int)(*handle)-1];
1057
1058 return exp_put_rng(e, (int)*id, (int *)from, (int *)to);
1059 }
1060
1061
1062 /* ARGSUSED */
1063 f_int expwsa_(f_int *handle, f_int *id, char *s, f_int *max_len, f_implicit s_l)
1064 /*
1065 * FORTRAN interface to exp_put_str workalike
1066 * NOTE: for use with FORTRAN CHARACTER arrays instead CHARACTER strings
1067 */
1068 {
1069 Exp_info *e;
1070 char buf[EXP_FILE_LINE_LENGTH];
1071 if ( check_handle(handle) ) return 1;
1072 e = (Exp_info *) Handles[(int)(*handle)-1];
1073
1074
1075 if ( exp_check_eid_write(e,*id) ) return 1;
1076 /* don't allow multi-line entries to be written */
1077 if (*id == EFLT_SQ ) return 1;
1078 f2cstr(s,(int)*max_len,buf,sizeof(buf));
1079 return exp_append_str(e,*id,buf,strlen(buf));
1080
1081 }
1082
1083 f_int expws_(f_int *handle, f_int *id, char *s, f_implicit s_l)
1084 /*
1085 * FORTRAN interface to exp_put_str workalike
1086 * NOTE: for use with FORTRAN CHARACTER strings instead CHARACTER arrays
1087 */
1088 {
1089 char buf[EXP_FILE_LINE_LENGTH];
1090 Exp_info *e;
1091 if ( check_handle(handle) ) return 1;
1092 e = (Exp_info *) Handles[(int)(*handle)-1];
1093
1094
1095 if ( exp_check_eid_write(e,*id) ) return 1;
1096 /* don't allow multi-line entries to be written */
1097 if (*id == EFLT_SQ ) return 1;
1098 f2cstr(s,s_l,buf,sizeof(buf));
1099 return exp_append_str(e,*id,buf,s_l);
1100 }
1101
1102 /*
1103 * FORTRAN interface to exp_create_range()
1104 */
1105 void expcr_(char *str, f_int *start, f_int *end, f_implicit str_l) {
1106 exp_create_range(str, *start, *end);
1107 c2fstr(str, str_l, str, str_l);
1108
1109 f_proc_return();
1110 }
1111
1112 /*
1113 * FORTRAN interface to exp_extract_range()
1114 */
1115 /* ARGSUSED */
1116 f_int exper_(char *str, f_int *start, f_int *end, f_implicit str_l) {
1117 return exp_extract_range(str, start, end);
1118 }
1119
1120
1121
1122
1123 /*************************************************************
1124 * Go for it!
1125 *************************************************************/
1126
1127 static void print_line(FILE *fp, Exp_info *e, int eflt, int all)
1128 {
1129 if (all) {
1130 int i;
1131 for(i=0;i<e->Nentries[eflt];i++) exp_print_line(fp,e,eflt,i);
1132 } else if (e->Nentries[eflt] > 0) {
1133 exp_print_line(fp,e,eflt,e->Nentries[eflt]-1);
1134 }
1135 }
1136
1137
1138 static void print_mline(FILE *fp, Exp_info *e, int eflt, int all)
1139 {
1140 if (all) {
1141 int i;
1142 for(i=0;i<e->Nentries[eflt];i++) exp_print_mline(fp,e,eflt,i);
1143 } else if (e->Nentries[eflt] > 0) {
1144 exp_print_mline(fp,e,eflt,e->Nentries[eflt]-1);
1145 }
1146 }
1147
1148
1149
1150 static void print_seq(FILE *fp, Exp_info *e, int eflt)
1151 {
1152 if (e->Nentries[eflt] > 0)
1153 exp_print_seq(fp,e,eflt,e->Nentries[eflt]-1);
1154 }
1155
1156
1157
1158
1159 void exp_print_file(FILE *fp, Exp_info *e)
1160 {
1161 print_line(fp,e,EFLT_ID, 0);
1162 print_line(fp,e,EFLT_AC, 0);
1163 print_line(fp,e,EFLT_EN, 0);
1164
1165 print_line(fp,e,EFLT_CC, 1);
1166 print_line(fp,e,EFLT_EX, 1);
1167 print_line(fp,e,EFLT_PS, 1);
1168
1169 print_line(fp,e,EFLT_LN, 0);
1170 print_line(fp,e,EFLT_LT, 0);
1171
1172 print_line(fp,e,EFLT_CF, 0);
1173 print_line(fp,e,EFLT_CV, 0);
1174 print_line(fp,e,EFLT_CS, 0);
1175 print_line(fp,e,EFLT_CL, 0);
1176 print_line(fp,e,EFLT_CR, 0);
1177
1178 print_line(fp,e,EFLT_SF, 0);
1179 print_line(fp,e,EFLT_SV, 0);
1180 print_line(fp,e,EFLT_SI, 0);
1181 print_line(fp,e,EFLT_SC, 0);
1182 print_line(fp,e,EFLT_SP, 0);
1183 print_line(fp,e,EFLT_PD, 0);
1184 print_line(fp,e,EFLT_FM, 0);
1185 print_line(fp,e,EFLT_SL, 0);
1186 print_line(fp,e,EFLT_SR, 0);
1187
1188 print_line(fp,e,EFLT_QL, 0);
1189 print_line(fp,e,EFLT_QR, 0);
1190
1191 print_mline(fp,e,EFLT_TG,1);
1192 print_mline(fp,e,EFLT_TC,1);
1193 print_mline(fp,e,EFLT_NT,1);
1194
1195 print_line(fp,e,EFLT_CN, 0);
1196 print_line(fp,e,EFLT_TN, 0);
1197 print_line(fp,e,EFLT_PN, 0);
1198 print_line(fp,e,EFLT_PR, 0);
1199 print_line(fp,e,EFLT_LI, 0);
1200 print_line(fp,e,EFLT_LE, 0);
1201 print_line(fp,e,EFLT_CH, 0);
1202
1203 print_mline(fp,e,EFLT_ON,0);
1204 print_line(fp,e,EFLT_AQ, 0);
1205 print_mline(fp,e,EFLT_AV,0);
1206
1207 print_line(fp,e,EFLT_DR, 0);
1208 print_line(fp,e,EFLT_SE, 0);
1209 print_line(fp,e,EFLT_PC, 0);
1210 print_line(fp,e,EFLT_AP, 0);
1211 print_line(fp,e,EFLT_ST, 0);
1212
1213 print_line(fp,e,EFLT_DT, 0);
1214 print_line(fp,e,EFLT_MC, 0);
1215 print_line(fp,e,EFLT_MN, 0);
1216 print_line(fp,e,EFLT_MT, 0);
1217 print_line(fp,e,EFLT_OP, 1);
1218 print_line(fp,e,EFLT_BC, 0);
1219 print_line(fp,e,EFLT_SS, 0);
1220
1221 print_line(fp,e,EFLT_WT, 0);
1222 print_line(fp,e,EFLT_WL, 0);
1223 print_line(fp,e,EFLT_WR, 0);
1224
1225 print_mline(fp,e,EFLT_FT,1);
1226
1227 print_seq (fp,e,EFLT_SQ);
1228 }
1229
1230
1231 /*
1232 * Allocate an set a new experiment file entry
1233 */
1234 char *exp_set_entry(Exp_info *e, int eflt, char *str) {
1235 char *s;
1236 size_t l;
1237
1238 if (NULL == ArrayRef(e->entries[eflt], e->Nentries[eflt]))
1239 return NULL;
1240 else
1241 e->Nentries[eflt]++;
1242
1243 l = strlen(str);
1244 if (NULL == (s = exp_get_entry(e, eflt) = (char *)xmalloc(l+1))) {
1245 e->Nentries[eflt]--;
1246 return NULL;
1247 }
1248 strcpy(s, str);
1249
1250 return s;
1251 }