/* file: dbcollate.c G. Moody 28 April 1994 Last revised: 6 February 1995 Collate DB records into a multi-segment record Copyright (C) Massachusetts Institute of Technology 1995. All rights reserved. A multi-segment record is the concatenation of one or more ordinary records. A multi-segment record is a "virtual" record, in the sense that it has no signal files of its own. Its header file contains a list of the records that comprise the multi-segment record. A multi-segment record may have associated annotation files, but these are independent of any annotation files that may exist for its constituent segments. It is permissible (though not particularly useful) to create a multi-segment record with only one segment; it is not permissible to use a multi-segment record as a segment within a multi-segment record, however. This program simply constructs an array of segment names, passing it to the DB library function `setmsheader' to create a multi-segment header file. `dbcollate' can be invoked in either of two ways: (1) dbcollate -i IREC1 IREC2 ... -o OREC [-a ANNOTATOR ] where OREC is the name of the multi-segment (output) record to be created, and IREC1, IREC2, etc. are the names of the (single-segment) input records that are to be included in OREC. At least one IREC must be specified. (2) dbcollate OREC FIRST LAST [ -a ANNOTATOR ] where OREC is the name of the multi-segment (output) record to be created, and FIRST and LAST are numbers between 1 and 99999. In this case, OREC must be 3 characters or fewer (longer names are truncated), and the names of the input records are derived by appending FIRST, FIRST+1, ..., LAST to OREC (representing FIRST, ..., as 5-digit zero-padded decimal numbers). Thus the command dbcollate xyz 9 12 is equivalent to dbcollate -o xyz -i xyz00009 xyz00010 xyz00011 xyz00012 (In both forms, `-a ANNOTATOR' is optional; if included, it specifies the annotator name of annotation files associated with the input records, files to be concatenated to form a similarly-named annotation file for OREC. Note that all of the files to be concatenated must have the same annotator name. It is not necessary that this annotator exist for each input record, however.) In most cases, multi-segment records are indistinguishable from single-segment records (from the point of view of applications built using the DB library, version 9.1 or later). Use `xform' to generate a single-segment record from a multi-segment record if necessary (for example, to make it readable by an application built using an earlier version of the DB library). Note, however, that older applications can generally be updated without source changes simply by recompiling them and linking them with the current DB library. */ #include #include char *pname, *prog_name(); void help(); main(argc, argv) int argc; char *argv[]; { char **irecname, *orecname = NULL, ofname[20]; int first, last, i, nsegments = 0, nsig, segment, v[DB_MAXSIG*DB_MAXSPF]; static DB_Siginfo si[DB_MAXSIG]; static DB_Anninfo ai; static DB_Annotation annot; pname = prog_name(argv[0]); if (argc < 2) { help(); exit(1); } if (*argv[1] == '-') { irecname = (char **)malloc(argc * sizeof(char *)); /* The array is slightly bigger than necessary. */ i = 1; while (i < argc && *argv[i] == '-') { switch (argv[i][1]) { case 'a': /* annotator name follows */ ai.name = argv[++i]; break; case 'i': /* input record names follow */ while (i < argc && *argv[++i] != '-') irecname[nsegments++] = argv[i]; break; case 'o': /* output record name follows */ orecname = argv[++i]; break; default: fprintf(stderr, "%s: unrecognized option `%s'\n", pname, argv[i]); help(); exit(1); } } } else { orecname = argv[1]; if (strlen(orecname) > 3) { fprintf(stderr, "%s: output record name `%s'", pname, orecname); orecname[3] = '\0'; fprintf(stderr, " truncated to `%s'\n", orecname); } if ((first = atoi(argv[2])) < 1) first = 1; if ((last = atoi(argv[3])) < first) last = 999; if (argc > 5 && strcmp(argv[4], "-a") == 0) ai.name = argv[5]; nsegments = last-first+1; irecname = (char **)malloc(sizeof(char *) * nsegments); for (i = first; i <= last; i++) { irecname[i-first] = (char *)malloc(9); sprintf(irecname[i-first], "%s%05d", orecname, i); } } if (orecname == NULL || nsegments < 1) if (newheader(orecname) < 0) exit(2); setmsheader(orecname, irecname, nsegments); dbquit(); if (ai.name) { char buf[20]; long t0 = 0L; ai.stat = WRITE; if (annopen(orecname, &ai, 1) < 0) exit(3); ai.stat = READ; for (i = 0; i < nsegments; i++) { sprintf(buf, "+%s", irecname[i]); if (annopen(buf, &ai, 1) == 0) { while (getann(0, &annot) == 0) { annot.time += t0; putann(0, &annot); } iannclose(0); /* close input file, leave output file open */ } (void)isigopen(irecname[i], si, -DB_MAXSIG); /* If isigopen fails, the contents of si are undisturbed. In this case, we need to guess the length of the segment. A good guess is that it is the same length as the previous segment -- so we can use si[0].nsamp irrespective of the success of isigopen! */ t0 += si[0].nsamp; } dbquit(); } exit(0); } char *prog_name(s) char *s; { char *p = s + strlen(s); #ifdef MSDOS while (p >= s && *p != '\\' && *p != ':') { if (*p == '.') *p = '\0'; /* strip off extension */ if ('A' <= *p && *p <= 'Z') *p += 'a' - 'A'; /* convert to lower case */ p--; } #else while (p >= s && *p != '/') p--; #endif return (p+1); } void help() { fprintf(stderr, "usage: %s -i IREC [ IREC ... ] -o OREC [ -a ANNOTATOR ]\n", pname); fprintf(stderr, " or: %s OREC first-segment-number last-segment-number [-a ANNOTATOR ]\n", pname); }