diff -Naur --exclude Makefile --exclude info wfdb-10.5.8/app/snip.c wfdb-10.5.9/app/snip.c --- wfdb-10.5.8/app/snip.c 2010-07-27 13:59:43.000000000 -0400 +++ wfdb-10.5.9/app/snip.c 2011-08-05 16:53:30.000000000 -0400 @@ -225,11 +225,12 @@ void copy_sig(char *nrec, char *irec, WFDB_Time from, WFDB_Time to, int recurse) { char *ofname, *p, tstring[24]; - int i, nsig; + int i, j, nsig, maxseg; long nsamp; WFDB_Sample *v; WFDB_Siginfo *si; WFDB_Time t, tf; + WFDB_Seginfo *seginfo; wfdbquit(); if ((nsig = isigopen(irec, NULL, 0)) < 0) { @@ -252,139 +253,116 @@ } p = mstimstr(-from); - if (*p == '[') strncpy(tstring, mstimstr(-from)+1, 23); + if (*p == '[') { + strncpy(tstring, mstimstr(-from)+1, 23); + tstring[23] = 0; + } else tstring[0] = '\0'; - if (recurse && (si[0].fmt == 0 || si[0].nsamp != 0) && - si[0].nsamp != strtim("e")) { + if (recurse && (maxseg = getseginfo(&seginfo)) > 0) { /* irec has multiple segments */ - static char buf[256], *p, *ihfname, *ohfname; - static char *ihlfname, *olhfname, *orseg; - int i, first_seg, last_seg, maxseg, nseg; + char *ohfname, *orseg; + int first_seg, last_seg, nseg; WFDB_Frequency sfreq = sampfreq(NULL); - WFDB_FILE *ihfile; FILE *ohfile; - - p = wfdbfile("hea", irec); - ihfname = malloc(strlen(p)+1); - strcpy(ihfname, p); - ihfile = wfdb_fopen(ihfname, "rb"); + WFDB_Seginfo *tmp; + + SUALLOC(tmp, maxseg, sizeof(WFDB_Seginfo)); + memcpy(tmp, seginfo, maxseg * sizeof(WFDB_Seginfo)); + seginfo = tmp; + ohfname = malloc((strlen(nrec)+5) * sizeof(char)); sprintf(ohfname, "%s.hea", nrec); ohfile = fopen(ohfname, "wb"); - - /* read and parse the first line of the multi-segment header */ - if (wfdb_fgets(buf, sizeof(buf), ihfile) == NULL) { - fprintf(stderr, "%s: error reading %s\n", pname, ihfname); + if (ohfile == NULL) { + fprintf(stderr, "%s: can't create master header\n", pname); exit(2); } - for (p = buf; *p != '/'; p++) - ; - maxseg = atoi(p+1); /* number of segments in irec */ - if (si[0].nsamp == 0) { /* irec has variable layout */ - char *ilhfname, *olhfname; - WFDB_FILE *ilhfile; - FILE *olhfile; - - maxseg--; /* don't count layout segment */ - wfdb_fgets(buf, sizeof(buf), ihfile); /* 2nd line of irec.hea */ - for (p = buf; *p != ' '; p++) - ; - *p = '\0'; - p = wfdbfile("hea", buf); /* irec_layout.hea */ - ilhfname = malloc(strlen(p) + 1); - strcpy(ilhfname, p); - ilhfile = wfdb_fopen(ilhfname, "rb"); - olhfname = malloc((strlen(nrec)+12) * sizeof(char)); - sprintf(olhfname, "%s_layout.hea", nrec); - olhfile = fopen(olhfname, "wb"); - fprintf(olhfile, "%s_layout %d %.12g 0", nrec, nsig, sfreq); - if (tstring[0]) fprintf(olhfile, " %s", tstring); - fprintf(olhfile, "\r\n"); - wfdb_fgets(buf, sizeof(buf), ilhfile); + + if (seginfo[0].nsamp == 0) { /* irec has variable layout */ + char *olrecname; + + SUALLOC(olrecname, strlen(nrec) + 8, sizeof(char)); + sprintf(olrecname, "%s_layout", nrec); + for (i = 0; i < nsig; i++) { - wfdb_fgets(buf, sizeof(buf), ilhfile); - fputs(buf, olhfile); + si[i].fname = "~"; + si[i].fmt = 0; + si[i].nsamp = 0; + si[i].cksum = 0; } + + if (tstring[0]) setbasetime(tstring); + + if (0 > setheader(olrecname, si, nsig)) { + fprintf(stderr, "%s: can't create layout header\n", pname); + exit(2); + } + if (sflag == 0) { char *info; wfdbquiet(); /* Suppress errors from the WFDB library. */ if (info = getinfo(irec)) do { - fprintf(olhfile, "# %s\r\n", info); + putinfo(info); } while (info = getinfo((char *)NULL)); wfdbverbose(); sflag = 1; } - fclose(olhfile); - wfdb_fclose(ilhfile); - } + } /* Figure out which input segments contain data to be copied */ - for (i = first_seg = 0, last_seg=maxseg, tf = 0L; i < maxseg; i++) { - wfdb_fgets(buf, sizeof(buf), ihfile); /* read a segment def */ - for (p = buf; *p != ' '; p++) - ; - t = tf; - tf = t + atol(p+1) + 1; /* first sample of next segment */ + for (i = first_seg = 0, last_seg = maxseg - 1; i < maxseg; i++) { + t = seginfo[i].samp0; + tf = seginfo[i].samp0 + seginfo[i].nsamp; if (t <= from && from < tf) first_seg = i; - if (t <= to && to < tf) { last_seg = i; break; } + if (t <= to && to <= tf) { last_seg = i; break; } } nseg = last_seg - first_seg + 1; - if (si[0].nsamp == 0) nseg++; + if (seginfo[0].nsamp == 0) nseg++; orseg = malloc((strlen(nrec)+6) * sizeof(char)); - - /* Close and reopen the input header. */ - wfdb_fclose(ihfile); - ihfile = wfdb_fopen(ihfname, "rb"); - wfdb_fgets(buf, sizeof(buf), ihfile); + + tf = seginfo[last_seg].samp0 + seginfo[last_seg].nsamp; + if (to > tf) + to = tf; /* Start writing the master output header. */ fprintf(ohfile, "%s/%d %d %.12g %ld", nrec, nseg, nsig, sfreq, to-from); if (tstring[0]) fprintf(ohfile, " %s", tstring); fprintf(ohfile, "\r\n"); - if (si[0].nsamp == 0) { - wfdb_fgets(buf, sizeof(buf), ihfile); - fprintf(ohfile, "%s_layout 0\r\n", nrec); + if (seginfo[0].nsamp == 0) { + fprintf(ohfile, "%s_layout 0\r\n", nrec); nseg--; } - for (i = 0, t = 0; t < to; ) { + for (i = 0, j = first_seg; j <= last_seg; j++) { long len; WFDB_Time start; - - wfdb_fgets(buf, sizeof(buf), ihfile); - for (p = buf; *p != ' '; p++) - ; - *p = '\0'; - tf = t + atol(p+1); /* time of first sample of next segment */ + + t = seginfo[j].samp0; + tf = seginfo[j].samp0 + seginfo[j].nsamp; if (to < tf) /* this is the last segment with data to copy */ tf = to; - if (from >= tf) { - t = tf; - continue; - } if (from > t) { start = from - t; len = tf - from; } else { start = 0L; len = tf - t; } - if (*buf == '~') + if (!strcmp(seginfo[j].recname, "~")) sprintf(orseg, "~"); else { sprintf(orseg, "%s_%04d", nrec, ++i); - copy_sig(orseg, buf, start, start + len, 0); + copy_sig(orseg, seginfo[j].recname, start, start + len, 0); } fprintf(ohfile, "%s %ld\r\n", orseg, len); - t = tf; } fclose(ohfile); return; } - + /* Open the output signals. */ (void)sprintf(ofname, "%s.dat", nrec); for (i = 0; i < nsig; i++) { diff -Naur --exclude Makefile --exclude info wfdb-10.5.8/lib/signal.c wfdb-10.5.9/lib/signal.c --- wfdb-10.5.8/lib/signal.c 2011-03-11 08:51:29.000000000 -0500 +++ wfdb-10.5.9/lib/signal.c 2011-08-05 16:53:14.000000000 -0400 @@ -2509,11 +2509,11 @@ case 8: case 16: case 61: + case 160: default: *vector = -1 << 15; break; case 80: - case 160: - *vector = 0; break; + *vector = -1 << 7; break; case 212: *vector = -1 << 11; break; case 310: diff -Naur --exclude Makefile --exclude info wfdb-10.5.8/lib/wfdb.h wfdb-10.5.9/lib/wfdb.h --- wfdb-10.5.8/lib/wfdb.h 2011-03-12 13:07:47.000000000 -0500 +++ wfdb-10.5.9/lib/wfdb.h 2011-08-05 17:06:03.000000000 -0400 @@ -32,7 +32,7 @@ /* WFDB library version. */ #define WFDB_MAJOR 10 #define WFDB_MINOR 5 -#define WFDB_RELEASE 8 +#define WFDB_RELEASE 9 #define WFDB_NETFILES 1 /* if 1, library includes code for HTTP, FTP clients */ #define WFDB_NETFILES_LIBCURL 1 diff -Naur --exclude Makefile --exclude info wfdb-10.5.8/NEWS wfdb-10.5.9/NEWS --- wfdb-10.5.8/NEWS 2011-03-12 17:30:51.000000000 -0500 +++ wfdb-10.5.9/NEWS 2011-09-10 15:06:37.957632286 -0400 @@ -1,3 +1,28 @@ +10.5.9 (10 September 2011): + When an application passes an array containing WFDB_INVALID_SAMPLE + values to putvec(), the function translates these into the + corresponding invalid-sample sentinel values used by the file format. + (This is the inverse of the transformation done by getvec() and + getframe(), so the effect is that at the application level, invalid + samples are always represented by the value WFDB_INVALID_SAMPLE.) + + Previous versions of the library did not perform this transformation + correctly for formats 80 and 160 (they used a value of zero rather than + -128 or -32768, respectively.) This bug was mainly an issue for + programs such as 'snip' and 'xform' that read and modify existing data + files. + + In multi-segment mode, 'snip' will attempt to copy the segment + structure of the input record. In older versions, this was done by + parsing the master and layout headers by hand; this version uses the + library function getseginfo() instead, which should be more robust. + + This version also fixes a bug that would cause snip to crash or produce + garbage output if asked to read past the end of a multi-segment record. + + Thanks to Benjamin Moody for identifying these problems and providing + patches to remedy them. + 10.5.8 (11 March 2011): Previous versions of the WFDB library did not behave properly if setbasetime() was invoked before setsampfreq(). Also, when dealing