diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/app/Makefile.tpl wfdb-10.4.6/app/Makefile.tpl --- wfdb-10.4.5/app/Makefile.tpl 2006-05-11 15:06:03.000000000 -0400 +++ wfdb-10.4.6/app/Makefile.tpl 2008-04-09 15:17:31.000000000 -0400 @@ -1,19 +1,19 @@ # file: Makefile.tpl G. Moody 23 May 2000 -# Last revised: 11 May 2006 +# Last revised: 9 April 2008 # This section of the Makefile should not need to be changed. CFILES = ann2rr.c bxb.c calsig.c ecgeval.c epicmp.c fir.c ihr.c mfilt.c \ mrgann.c mxm.c nguess.c nst.c plotstm.c pscgen.c pschart.c psfd.c rdann.c \ - rdsamp.c rr2ann.c rxr.c sampfreq.c sigamp.c sigavg.c skewedit.c \ - snip.c sortann.c sqrs.c sqrs125.c sumann.c sumstats.c tach.c time2sec.c \ - wabp.c wfdbcat.c wfdbcollate.c wfdbdesc.c \ + rdsamp.c rr2ann.c rxr.c sampfreq.c sigamp.c sigavg.c signame.c signum.c \ + skewedit.c snip.c sortann.c sqrs.c sqrs125.c sumann.c sumstats.c tach.c \ + time2sec.c wabp.c wfdbcat.c wfdbcollate.c wfdbdesc.c \ wfdbwhich.c wqrs.c wrann.c wrsamp.c xform.c XFILES = ann2rr bxb calsig ecgeval epicmp fir ihr mfilt \ mrgann mxm nguess nst plotstm pscgen pschart psfd rdann \ - rdsamp rr2ann rxr sampfreq sigamp sigavg skewedit \ - snip sortann sqrs sqrs125 sumann sumstats tach time2sec \ - wabp wfdbcat wfdbcollate wfdbdesc wfdbwhich wqrs \ - wrann wrsamp xform + rdsamp rr2ann rxr sampfreq sigamp sigavg signame signum \ + skewedit snip sortann sqrs sqrs125 sumann sumstats tach \ + time2sec wabp wfdbcat wfdbcollate wfdbdesc\ + wfdbwhich wqrs wrann wrsamp xform SCRIPTS = cshsetwfdb setwfdb PSFILES = pschart.pro psfd.pro 12lead.pro MFILES = Makefile diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/app/rxr.c wfdb-10.4.6/app/rxr.c --- wfdb-10.4.5/app/rxr.c 2002-05-20 19:17:35.000000000 -0400 +++ wfdb-10.4.6/app/rxr.c 2008-03-31 12:02:27.000000000 -0400 @@ -1,9 +1,9 @@ /* file: rxr.c G. Moody 16 August 1989 - Last revised: 20 May 2002 + Last revised: 31 March 2008 ------------------------------------------------------------------------------- rxr: ANSI/AAMI-standard run-by-run annotation file comparator -Copyright (C) 2002 George B. Moody +Copyright (C) 1989-2008 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -52,7 +52,7 @@ char *pname; /* name by which this program was invoked */ char *record; WFDB_Anninfo an[2]; -WFDB_Annotation annot[2]; +WFDB_Annotation annot[2], tempann; int fflag = 3; FILE *ofile, *sfile; long start, end_time, match_dt; @@ -86,7 +86,7 @@ void rxr(stat, type) int stat, type; { - int i, j; + int i, j, goflag = 1; int run_length[2]; unsigned int a, b; long run_start, run_end; @@ -258,8 +258,15 @@ break; } } - } while (getann(a, &annot[a]) >= 0 && - (end_time <= 0L || annot[a].time <= end_time)); + if (getann(a, &tempann) < 0) { + if (run_length[a] > 0) + annot[a].anntyp = NORMAL; + else + goflag = 0; + } + else + annot[a] = tempann; + } while (goflag > 0 && (end_time <= 0L || annot[a].time <= end_time)); } /* `pstat' prints a statistic described by s, defined as the quotient of a and @@ -369,6 +376,8 @@ return (']'); } case RHYTHM: + if (annot.aux == NULL || *(annot.aux) == 0) + return('O'); /* An `(AF' rhythm change annotation is mapped to `{' only if AF is not already in progress. If VF was in progress, it is assumed to have ended. */ diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/app/signame.c wfdb-10.4.6/app/signame.c --- wfdb-10.4.5/app/signame.c 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.6/app/signame.c 2008-04-09 15:14:44.000000000 -0400 @@ -0,0 +1,138 @@ +/* file: signum.c G. Moody 9 April 2008 + +------------------------------------------------------------------------------- +signum: Print signal names for signal numbers given as arguments +Copyright (C) 2008 George B. Moody + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA. + +You may contact the author by e-mail (george@mit.edu) or postal mail +(MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, +please visit PhysioNet (http://www.physionet.org/). +_______________________________________________________________________________ + +*/ + +#include +#include + +char *pname; + +main(int argc, char **argv) +{ + char *p, *record = NULL, *prog_name(); + int i, isiglist = 0, j, nsig, nosig = 0; + WFDB_Siginfo *si; + void help(); + + pname = prog_name(argv[0]); + + for (i = 1; i < argc; i++) { + if (*argv[i] == '-') switch (*(argv[i]+1)) { + case 'h': /* help requested */ + help(); + exit(0); + break; + case 'r': /* record name */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: record name must follow -r\n", + pname); + exit(1); + } + record = argv[i]; + break; + case 's': /* signal list follows */ + isiglist = i+1; /* index of 1st argument containing a signal # */ + while (i+1 < argc && *argv[i+1] != '-') { + i++; + nosig++; /* number of elements in signal list */ + } + if (nosig == 0) { + (void)fprintf(stderr, "%s: signal list must follow -s\n", + pname); + exit(1); + } + break; + default: + (void)fprintf(stderr, "%s: unrecognized option %s\n", pname, + argv[i]); + exit(1); + } + else { + (void)fprintf(stderr, "%s: unrecognized argument %s\n", pname, + argv[i]); + exit(1); + } + } + if (record == NULL) { + help(); + exit(1); + } + if ((nsig = isigopen(record, NULL, 0)) <= 0) exit(2); + if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if ((nsig = isigopen(record, si, -nsig)) <= 0) exit(2); + if (isiglist) + for (i = 0; i < nosig; i++) { + j = atoi(argv[isiglist+i]); + if (0 <= j && j <= nsig) p = si[j].desc; + else p = "[INVALID]"; + printf("%s\n", p); + } + else + for (i = 0; i < nsig; i++) + printf("%s\n", si[i].desc); + wfdbquit(); + 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); +} + +static char *help_strings[] = { + "usage: %s -r RECORD [OPTIONS ...]\n", + "where RECORD is the name of the input record, and OPTIONS may include:", + " -h print this usage summary", + " -s SIGNAL [SIGNAL ...] print signal name(s) for the specified signal(s)", + "If no -s option is given, the names of all signals in the record are output.", +NULL +}; + +void help() +{ + int i; + + (void)fprintf(stderr, help_strings[0], pname); + for (i = 1; help_strings[i] != NULL; i++) + (void)fprintf(stderr, "%s\n", help_strings[i]); +} diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/app/signum.c wfdb-10.4.6/app/signum.c --- wfdb-10.4.5/app/signum.c 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.6/app/signum.c 2008-04-09 18:16:47.000000000 -0400 @@ -0,0 +1,140 @@ +/* file: signum.c G. Moody 9 April 2008 + +------------------------------------------------------------------------------- +signum: Print signal numbers for signals named as arguments +Copyright (C) 2008 George B. Moody + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA. + +You may contact the author by e-mail (george@mit.edu) or postal mail +(MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, +please visit PhysioNet (http://www.physionet.org/). +_______________________________________________________________________________ + +*/ + +#include +#include + +char *pname; + +main(int argc, char **argv) +{ + char *record = NULL, *prog_name(); + int found, i, isiglist = 0, j, nsig, nosig = 0; + WFDB_Siginfo *si; + void help(); + + pname = prog_name(argv[0]); + + for (i = 1; i < argc; i++) { + if (*argv[i] == '-') switch (*(argv[i]+1)) { + case 'h': /* help requested */ + help(); + exit(0); + break; + case 'r': /* record name */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: record name must follow -r\n", + pname); + exit(1); + } + record = argv[i]; + break; + case 's': /* signal list follows */ + isiglist = i+1; /* index of 1st argument containing a signal name */ + while (i+1 < argc && *argv[i+1] != '-') { + i++; + nosig++; /* number of elements in signal list */ + } + if (nosig == 0) { + (void)fprintf(stderr, "%s: signal list must follow -s\n", + pname); + exit(1); + } + break; + default: + (void)fprintf(stderr, "%s: unrecognized option %s\n", pname, + argv[i]); + exit(1); + } + else { + (void)fprintf(stderr, "%s: unrecognized argument %s\n", pname, + argv[i]); + exit(1); + } + } + if (record == NULL || isiglist == 0) { + help(); + exit(1); + } + if ((nsig = isigopen(record, NULL, 0)) <= 0) exit(2); + if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if ((nsig = isigopen(record, si, -nsig)) <= 0) exit(2); + for (i = 0; i < nosig; i++) { + found = 0; + for (j = 0; j < nsig; j++) { + if (found) printf("\t"); + if (si[j].desc && (strcmp(argv[isiglist+i], si[j].desc) == 0)) { + printf("%d", j); + break; + } + found = 1; + } + if (!found) printf("X"); + printf("\n"); + } + wfdbquit(); + 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); +} + +static char *help_strings[] = { + "usage: %s -r RECORD [OPTIONS ...]\n", + "where RECORD is the name of the input record, and OPTIONS may include:", + " -h print this usage summary", + " -s SIGNAL [SIGNAL ...] print signal number(s) for the specified signal(s)", +NULL +}; + +void help() +{ + int i; + + (void)fprintf(stderr, help_strings[0], pname); + for (i = 1; help_strings[i] != NULL; i++) + (void)fprintf(stderr, "%s\n", help_strings[i]); +} diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/app/wrann.c wfdb-10.4.6/app/wrann.c --- wfdb-10.4.5/app/wrann.c 2008-01-06 19:45:57.000000000 -0500 +++ wfdb-10.4.6/app/wrann.c 2008-03-14 13:52:09.000000000 -0400 @@ -1,9 +1,9 @@ /* file wrann.c G. Moody 6 July 1983 - Last revised: 12 February 2000 + Last revised: 14 March 2008 ------------------------------------------------------------------------------- wrann: Translate an ASCII file in 'rdann' output format to an annotation file -Copyright (C) 2000 George B. Moody +Copyright (C) 1983-2008 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -98,6 +98,7 @@ exit(1); } + setafreq(sampfreq(record)); ai.stat = WFDB_WRITE; if (annopen(record, &ai, 1) < 0) /* open annotation file */ exit(2); diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/checkpkg/expected/100s.wra wfdb-10.4.6/checkpkg/expected/100s.wra --- wfdb-10.4.5/checkpkg/expected/100s.wra 2001-09-09 23:32:12.000000000 -0400 +++ wfdb-10.4.6/checkpkg/expected/100s.wra 2008-04-04 13:45:51.000000000 -0400 @@ -1 +1 @@ -pü(N;%$&ë f0$.4(*((9($&*0" 5/)!-'0=(!$-+)$#/,+"41(&$ \ No newline at end of file +Xü## time resolution: 360ìÿÿÿÿpü(N;%$&ë f0$.4(*((9($&*0" 5/)!-'0=(!$-+)$#/,+"41(&$ \ No newline at end of file diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/checkpkg/expected/lcheck_cal wfdb-10.4.6/checkpkg/expected/lcheck_cal --- wfdb-10.4.5/checkpkg/expected/lcheck_cal 2004-03-05 12:10:07.000000000 -0500 +++ wfdb-10.4.6/checkpkg/expected/lcheck_cal 2008-04-04 13:41:15.000000000 -0400 @@ -39,6 +39,8 @@ Atip - - undefined 1 mV HVA - - undefined 5 mV Vtip - - undefined 10 mV +Thorax - - undefined 2 mV +Abdomen - - undefined 200 uV record - - undefined 1 mV record - - undefined 10 V record - - undefined 100 mmHg diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/conf/version.def wfdb-10.4.6/conf/version.def --- wfdb-10.4.5/conf/version.def 2007-03-23 11:57:44.000000000 -0400 +++ wfdb-10.4.6/conf/version.def 2008-02-08 10:31:06.000000000 -0500 @@ -1,10 +1,10 @@ # file: version.def G. Moody 24 May 2000 -# Last revised: 23 March 2007 +# Last revised: 8 February 2008 # Each release of the WFDB Software Package is identified by a three-part # version number, defined here: MAJOR = 10 MINOR = 4 -RELEASE = 5 +RELEASE = 6 VERSION = $(MAJOR).$(MINOR).$(RELEASE) # RPMRELEASE can be incremented if changes are made between official diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/convert/Makefile.tpl wfdb-10.4.6/convert/Makefile.tpl --- wfdb-10.4.5/convert/Makefile.tpl 2006-05-11 13:25:57.000000000 -0400 +++ wfdb-10.4.6/convert/Makefile.tpl 2008-04-04 14:35:47.000000000 -0400 @@ -1,10 +1,11 @@ # file: Makefile.tpl G. Moody 24 May 2000 -# Last revised: 11 May 2006 +# Last revised: 4 April 2008 # This section of the Makefile should not need to be changed. CFILES = a2m.c ad2m.c m2a.c md2a.c readid.c makeid.c edf2mit.c mit2edf.c \ - wav2mit.c mit2wav.c revise.c -XFILES = a2m ad2m m2a md2a readid makeid edf2mit mit2edf wav2mit mit2wav revise + rdedfann.c wav2mit.c mit2wav.c revise.c +XFILES = a2m ad2m m2a md2a readid makeid edf2mit mit2edf rdedfann wav2mit \ + mit2wav revise SCRIPTS = ahaconvert MFILES = Makefile diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/convert/rdedfann.c wfdb-10.4.6/convert/rdedfann.c --- wfdb-10.4.5/convert/rdedfann.c 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.6/convert/rdedfann.c 2008-04-04 14:32:07.000000000 -0400 @@ -0,0 +1,242 @@ +/* file: rdedfann.c G. Moody 14 March 2008 + Last revised: 4 April 2008 + +------------------------------------------------------------------------------- +rdedfann: Print annotations from an EDF+ file +Copyright (C) 2008 George B. Moody + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place - Suite 330, Boston, MA 02111-1307, USA. + +You may contact the author by e-mail (george@mit.edu) or postal mail +(MIT Room E25-505A, Cambridge, MA 02139 USA). For updates to this software, +please visit PhysioNet (http://www.physionet.org/). +_______________________________________________________________________________ + +This program prints the annotations from an EDF+ file in the same format as +'rdann' does for WFDB-compatible annotation files. Note, however, that the +annotation mnemonics in EDF+ files do not in general match those used in +WFDB-compatible annotation files, so that it will usually be necessary to +translate those that come from EDF+ file before the text can be converted +by 'wrann'. For example, this command can be used to extract annotations +from 'foo.edf', change the EDF+ annotation type "QRS" to the WFDB type "N", +and then produce a WFDB-compatible annotation file 'foo.edf.qrs': + rdedf -r foo.edf | sed "s/QRS/ N" | wrann -r foo.edf -a qrs +*/ + +#include +#include + +char *pname; +double sfreq; +int state; + +main(int argc, char **argv) +{ + char *record = NULL, *prog_name(); + int aindex = 0, alen = 0, framelen = 0; + int highres = 0, i, nsig, s, vflag = 0; + WFDB_Sample *frame; + WFDB_Siginfo *si; + void help(); + + pname = prog_name(argv[0]); + for (i = 1; i < argc; i++) { + if (*argv[i] == '-') switch (*(argv[i]+1)) { + case 'h': /* help requested */ + help(); + exit(0); + break; + case 'r': /* record name */ + if (++i >= argc) { + (void)fprintf(stderr, "%s: record name must follow -r\n", + pname); + exit(1); + } + record = argv[i]; + break; + case 'v': /* verbose output -- include column headings */ + vflag = 1; + break; + default: + (void)fprintf(stderr, "%s: unrecognized option %s\n", pname, + argv[i]); + exit(1); + } + else { + (void)fprintf(stderr, "%s: unrecognized argument %s\n", pname, + argv[i]); + exit(1); + } + } + if (record == NULL) { + help(); + exit(1); + } + if ((nsig = isigopen(record, NULL, 0)) <= 0) exit(2); + if ((si = malloc(nsig * sizeof(WFDB_Siginfo))) == NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + exit(2); + } + if ((nsig = isigopen(record, si, nsig)) <= 0) + exit(2); + for (i = framelen = 0; i < nsig; i++) { + if (strcmp(si[i].desc, "EDF Annotations") == 0) { + aindex = framelen; + alen = si[i].spf; + } + framelen += si[i].spf; + } + if (alen == 0) { + (void)fprintf(stderr, "%s: record %s has no EDF annotations\n", + pname, record); + (void)free(si); + wfdbquit(); + exit(3); + } + if ((frame = (int *)malloc((unsigned)framelen*sizeof(WFDB_Sample)))==NULL) { + (void)fprintf(stderr, "%s: insufficient memory\n", pname); + (void)free(si); + exit(2); + } + + sfreq = sampfreq(NULL); + + /* Print column headers if '-v' option selected. */ + if (vflag) + (void)printf(" Time Sample # Type Sub Chan Num\tAux\n"); + + while (getframe(frame) > 0) { + WFDB_Sample *p; + + state = 0; + for (i = 0, p = (frame + aindex); i < alen; i++, p++) { + if (*p) { + proc(*p); + proc(*p >> 8); + } + else + break; + } + } + + (void)free(frame); + (void)free(si); + wfdbquit(); + exit(0); /*NOTREACHED*/ +} + +proc(int x) +{ + static char onset[1024], duration[1024], text[1024]; + static char *onsetp, *durationp, *textp; + + x &= 0xff; + + switch (state) { + case 0: /* looking for a new TAL */ + if (x == '\0') + break; + if (x != '+') + fprintf(stderr, "%s: unexpected character '%c' in input\n", + pname, x); + else { + state = 1; + onsetp = onset; + durationp = duration; + textp = text; + *textp = 0; + } + break; + case 1: /* accumulate characters from onset until 024 or 025 */ + if (x == '\025') { /* end of onset, start of duration */ + x = 0; + state = 2; + } + else if (x == '\024') { /* end of onset, start of annotation */ + x = 0; + state = 3; + } + *(onsetp++) = x; + break; + case 2: /* accumulate characters from duration until 024 */ + if (x == '\024') { /* end of onset, start of annotation */ + x = 0; + state = 3; + } + *(durationp++) = x; + break; + case 3: /* accumulate characters from annotation until 024 */ + if (x == '\024') { /* end of annotation */ + x = 0; + state = 4; + } + *(textp++) = x; + break; + case 4: /* annot just ended, there may be another */ + if (text[0]) { /* the annotation was not empty -- output it */ + long t = (long)(atof(onset) * sfreq + 0.5); + printf("%s %7ld%6s%5d%5d%5d", + mstimstr(t), t, text, 0, 0, 0); + if (duration[0]) printf("\tduration: %s", duration); + printf("\n"); + } + if (x) { + text[0] = x; + textp = text + 1; + state = 3; + } + else /* end of TAL */ + state = 0; + break; + } +} + +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); +} + +static char *help_strings[] = { + "usage: %s -r RECORD [OPTIONS ...]\n", + "where RECORD is the name of the input EDF+ record, and OPTIONS may include:", + " -f TIME begin at specified time", + " -h print this usage summary", + " -t TIME stop at specified time", + " -v print column headings", +NULL +}; + +void help() +{ + int i; + + (void)fprintf(stderr, help_strings[0], pname); + for (i = 1; help_strings[i] != NULL; i++) + (void)fprintf(stderr, "%s\n", help_strings[i]); +} diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/data/wfdbcal wfdb-10.4.6/data/wfdbcal --- wfdb-10.4.5/data/wfdbcal 2004-03-05 11:31:02.000000000 -0500 +++ wfdb-10.4.6/data/wfdbcal 2008-03-14 16:31:33.000000000 -0400 @@ -1,5 +1,5 @@ # file: wfdbcal G. Moody June 1991 -# Last revised: 5 March 2004 +# Last revised: 14 March 2008 # Default calibration database for WFDB library # # Format: @@ -66,6 +66,10 @@ HVA - - undefined 5 mV Vtip - - undefined 10 mV +# ECG from Non-Invasive Fetal ECG Database +Thorax - - undefined 2 mV +Abdomen - - undefined 200 uV + # Definitions for nameless signals with defined units record - - undefined 1 mV record - - undefined 1000 uV diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/Makefile.tpl wfdb-10.4.6/doc/wag-src/Makefile.tpl --- wfdb-10.4.5/doc/wag-src/Makefile.tpl 2006-05-11 15:04:53.000000000 -0400 +++ wfdb-10.4.6/doc/wag-src/Makefile.tpl 2008-02-19 09:47:27.000000000 -0500 @@ -1,5 +1,5 @@ # file: Makefile.tpl G. Moody 24 May 2000 -# Last revised: 11 May 2006 +# Last revised: 19 February 2008 # Change the settings below as appropriate for your setup. # D2PARGS is a list of options for dvips. Uncomment one of these to set the @@ -159,10 +159,12 @@ # 'make wag.pdf': format the WFDB Applications Guide as PDF wag.pdf: wag0.ps ps2pdf wag0.ps wag.pdf + $(SETPERMISSIONS) wag.pdf # 'make wag.ps': format the WFDB Applications Guide as PostScript wag.ps: $(WAGPSREQ) $(MAKEWAGPS) + $(SETPERMISSIONS) wag.ps wag0.ps: wag.tex $(MAKE) wag2.ps diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/rdann.1 wfdb-10.4.6/doc/wag-src/rdann.1 --- wfdb-10.4.5/doc/wag-src/rdann.1 2004-11-28 13:00:41.000000000 -0500 +++ wfdb-10.4.6/doc/wag-src/rdann.1 2008-03-27 10:23:12.000000000 -0400 @@ -57,7 +57,8 @@ \fB-x\fR Use an alternate time format for output (the first three columns are the elapsed times in seconds, in minutes, and in hours, replacing the -\fIhh:mm:ss\fR and sample number columns in the default output). +\fIhh:mm:ss\fR and sample number columns in the default output). Note +that this format is incompatible with \fBwrann\fR. .PP The \fB-f\fR and \fB-t\fR options may be used to select a portion of an annotation file for printing. Their arguments are usually given in diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/rdedfann.1 wfdb-10.4.6/doc/wag-src/rdedfann.1 --- wfdb-10.4.5/doc/wag-src/rdedfann.1 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.6/doc/wag-src/rdedfann.1 2008-04-09 15:54:39.000000000 -0400 @@ -0,0 +1,46 @@ +.TH RDEDFANN 1 "9 April 2008" "WFDB 10.4.6" "WFDB Applications Guide" +.SH NAME +rdedfann \- extract annotations from an EDF+ file +.SH SYNOPSIS +\fBrdedfann -r\fR \fIedffile\fR [ \fIoptions\fR ... ] +.SH DESCRIPTION +This program prints the annotations from an EDF+ file in the same format as +\fBrdann\fR does for WFDB-compatible annotation files. + +.PP +Options include: +.TP +\fB-h\fR +Print a brief usage summary. +\fB-v\fR +Verbose mode (print column headings). + +.PP +Note that the annotation mnemonics in EDF+ files do not in general +match those used in WFDB-compatible annotation files, so that it will +usually be necessary to translate those that come from EDF+ file +before the text can be converted by \fBwrann\fR. For example, this +command can be used to extract annotations from \fBfoo.edf\fR, change +the EDF+ annotation type "QRS" to the WFDB type "N", and then produce +a WFDB-compatible annotation file \fBfoo.edf.qrs\fR: +.br + \fBrdedfann -r foo.edf | sed "s/QRS/ N" | wrann -r foo.edf -a qrs\fR + +.SH ENVIRONMENT +.PP +It may be necessary to set and export the shell variable \fBWFDB\fR (see +\fBsetwfdb\fR(1)). +.SH AVAILABILITY +This program is provided in the \fIconvert\fR directory of the WFDB Software +Package. Run \fBmake\fR in that directory to compile and install it if it +has not been installed already. +.SH SEE ALSO +\fBedftomit\fR(1) +.HP +http://www.edfplus.info/spscs/edfplus.html +Full specification of EDF+, by Bob Kemp and Jesus Olivan. +.SH AUTHOR +George B. Moody (george@mit.edu) +.SH SOURCES +http://www.physionet.org/physiotools/wfdb/convert/rdedfann.c + diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/signame.1 wfdb-10.4.6/doc/wag-src/signame.1 --- wfdb-10.4.5/doc/wag-src/signame.1 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.6/doc/wag-src/signame.1 2008-04-09 15:51:07.000000000 -0400 @@ -0,0 +1,30 @@ +.TH SIGNAME 1 "9 April 2008" "WFDB 10.4.6" "WFDB Applications Guide" +.SH NAME +signame \- print names of signals of a WFDB record +.SH SYNOPSIS +\fBsigname -r\fR \fIrecord\fR [ \fIoptions\fR ... ] +.SH DESCRIPTION +.PP +\fBsigname\fR prints the names of the signals in the specified \fIrecord\fR +(one per line). Using the \fB-s\fR option, only the names of the signals +specified by signal number are printed. +.PP +\fIOptions\fR include: +.TP +\fB-h\fR +Print a usage summary. +.TP +\fB-s\fR \fIsignal\fR [ \fIsignal\fR ... ] +Print names for the specified \fIsignal\fR(s) only. Signals are numbered +0, 1, 2 .... If the specified signal does not exist in \fIrecord\fR, +\fBsigname\fR outputs "[INVALID]". +.SH ENVIRONMENT +.PP +It may be necessary to set and export the shell variable \fBWFDB\fR (see +\fBsetwfdb\fR(1)). +.SH SEE ALSO +\fBsignum\fR(1) +.SH AUTHOR +George B. Moody (george@mit.edu) +.SH SOURCE +http://www.physionet.org/physiotools/wfdb/app/signame.c diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/signum.1 wfdb-10.4.6/doc/wag-src/signum.1 --- wfdb-10.4.5/doc/wag-src/signum.1 1969-12-31 19:00:00.000000000 -0500 +++ wfdb-10.4.6/doc/wag-src/signum.1 2008-04-09 15:41:55.000000000 -0400 @@ -0,0 +1,32 @@ +.TH SIGNUM 1 "9 April 2008" "WFDB 10.4.6" "WFDB Applications Guide" +.SH NAME +signum \- print signal numbers of a WFDB record having specified names +.SH SYNOPSIS +\fBsignum -r\fR \fIrecord\fR [ \fIoptions\fR ... ] +.SH DESCRIPTION +.PP +\fBsignum\fR prints the signal numbers in the specified \fIrecord\fR +(one per line) corresponding to the specified signal names. +.PP +\fIOptions\fR include: +.TP +\fB-h\fR +Print a usage summary. +.TP +\fB-s\fR \fIname\fR [ \fIname\fR ... ] +Print signal numbers of signals that have the specified \fIname\fRs. Signals +are numbered 0, 1, 2 .... If the specified signal does not exist in +\fIrecord\fR, \fBsigname\fR outputs "X". +.PP +If two or more signals in a record match a specified \fIname\fR, \fBsignum\fR +outputs the numbers of all the matching signals on a single line. +.SH ENVIRONMENT +.PP +It may be necessary to set and export the shell variable \fBWFDB\fR (see +\fBsetwfdb\fR(1)). +.SH SEE ALSO +\fBsigname\fR(1) +.SH AUTHOR +George B. Moody (george@mit.edu) +.SH SOURCE +http://www.physionet.org/physiotools/wfdb/app/signum.c diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/wag.ht0 wfdb-10.4.6/doc/wag-src/wag.ht0 --- wfdb-10.4.5/doc/wag-src/wag.ht0 2006-02-27 11:11:35.000000000 -0500 +++ wfdb-10.4.6/doc/wag-src/wag.ht0 2008-04-09 16:12:21.000000000 -0400 @@ -20,7 +20,7 @@ George B. Moody
Harvard-MIT Division of Health Sciences and Technology

-Copyright ©1980-2006 George B. Moody +Copyright ©1980-2008 George B. Moody

The most recent versions of the programs described in this guide may be freely downloaded from PhysioNet. For diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/wag.tex wfdb-10.4.6/doc/wag-src/wag.tex --- wfdb-10.4.5/doc/wag-src/wag.tex 2005-06-13 01:05:53.000000000 -0400 +++ wfdb-10.4.6/doc/wag-src/wag.tex 2008-04-09 16:23:17.000000000 -0400 @@ -36,7 +36,7 @@ \pagestyle{empty} \vspace*{\fill} \noindent -Copyright \copyright 1992 -- 2005 George B. Moody +Copyright \copyright 1992 -- 2008 George B. Moody \vspace{1 in} \noindent diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wag-src/wrann.1 wfdb-10.4.6/doc/wag-src/wrann.1 --- wfdb-10.4.5/doc/wag-src/wrann.1 2002-08-01 01:12:22.000000000 -0400 +++ wfdb-10.4.6/doc/wag-src/wrann.1 2008-03-27 10:22:07.000000000 -0400 @@ -5,8 +5,8 @@ \fBwrann -r\fR \fIrecord\fR \fB-a\fR \fIannotator\fR .SH DESCRIPTION \fBwrann\fR translates its standard input into an annotation file. -The format of \fBwrann\fR input should be that produced by \fBrdann\fR(1). -Specifically, the pipeline +The format of \fBwrann\fR input should be that produced by \fBrdann\fR(1) +using its default settings. Specifically, the pipeline .br \fBrdann -r\fR \fIrecord\fR \fB-a\fR \fIiann\fR \fB-f 0 | wrann -r\fR \fIrecord\fR \fB-a\fR \fIoann\fR .br @@ -18,6 +18,9 @@ editing: an annotation file may be translated into ASCII format using \fBrdann\fR, edited using a text editor, and then translated back into annotation file format using \fBwrann\fR. +.PP +Note the alternate format selected by \fBrdann\fR's \fB-x\fR option is +incompatible with \fBwrann\fR. .SH ENVIRONMENT .PP It may be necessary to set and export the shell variable \fBWFDB\fR (see diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wpg-src/wpg0.tex wfdb-10.4.6/doc/wpg-src/wpg0.tex --- wfdb-10.4.5/doc/wpg-src/wpg0.tex 2008-02-06 12:14:53.000000000 -0500 +++ wfdb-10.4.6/doc/wpg-src/wpg0.tex 2008-04-09 16:14:03.000000000 -0400 @@ -21,7 +21,7 @@ @center Harvard-MIT Division of Health Sciences and Technology @page @vskip 0pt plus 1filll -Copyright @copyright{} 1989 -- 2008 George B. Moody +Copyright @copyright{} 1980 -- 2008 George B. Moody @sp 2 The most recent versions of the software described in this guide may be downloaded from @uref{http://www.physionet.org/}. For further @@ -510,6 +510,37 @@ WFDB Software Package distribution, for information on any more recent changes that may not be described here. +@unnumberedsubsec Changes in version 10.4.6 + +The WFDB functions @code{setafreq()} and @code{getafreq()} (for +setting and getting the time resolution of newly-created output +annotation files in ticks per second) were new in version 10.4.5, but +were undocumented. They are now described in this Guide, and wrappers +for these functions are now included in @file{fortran/wfdbf.c}. + +An important change in the WFDB library: memory allocation errors are +now treated as fatal by default (in previous versions, the functions +that encountered them returned error values that permitted the +application to handle them). These errors occur when there is +insufficient memory available to the WFDB library. After invoking +@code{wfdbmemerr(0)}, if such an error occurs, the function in which it +occurs will continue running if possible. By default, however, such an +error will cause the process to terminate. In either case, the WFDB +library emits an appropriate error message to aid in troubleshooting. + +New macros for handling dynamically allocated memory are defined in +@file{lib/wfdblib.h} and used throughout the WFDB library, eliminating most +known memory leaks. Three known leaks remain (in @code{setecgstr()}, +@code{setannstr()}, and @code{setanndesc()}); these are documented and +harmless in current applications. Thanks to Yinqi Zhang for reporting a leak +in @code{copysi()} (an internal WFDB library function defined in +@file{signal.c}), which prompted the cleanup. + +WFDB functions @code{strecg()}, @code{setecgstr()}, @code{strann()}, +@code{setannstr()}, and @code{setanndesc()} now handle NULL string inputs +properly. (Previous versions passed NULL strings to @code{strcmp()}, with +undesirable results.) + @unnumberedsubsec Changes in version 10.4.5 Bob Farrell and Tony Ricke chased down and provided fixes for memory leaks @@ -1779,7 +1810,7 @@ The remainder of the nodes in this section describe functions for: * selecting:: Selecting database records (opening files). -* special input modes:: Setting the input sampling frequency and more. +* special I/O modes:: Setting the input sampling frequency and more. * signal and annotation I/O:: Reading and writing signals and annotations. * non-sequential:: Non-sequential access to WFDB files. * conversion:: Time and other conversion functions. @@ -1861,7 +1892,7 @@ functions that exist to serve unusual applications. @page -@node selecting,special input modes,introduction to functions,Functions +@node selecting,special I/O modes,introduction to functions,Functions @section Selecting Database Records @cindex selecting database records @cindex opening database files @@ -2289,8 +2320,8 @@ for methods of opening output signal files. @page -@node special input modes, signal and annotation I/O, selecting, Functions -@section Special Input Modes +@node special I/O modes, signal and annotation I/O, selecting, Functions +@section Special I/O Modes @menu * setifreq:: Setting the input sampling frequency. @@ -2298,10 +2329,14 @@ * setgvmode:: Setting the resolution for a multifrequency record. * getspf:: Determining the number of samples per frame. +* setafreq:: Setting the time resolution for output + annotations. +* getafreq:: Determining the time resolution for output + annotations. @end menu @c @group -@node setifreq, getifreq, special input modes, special input modes +@node setifreq, getifreq, special I/O modes, special I/O modes @unnumberedsubsec setifreq @findex setifreq (10.2.6) @cindex interpolation @@ -2375,7 +2410,7 @@ Avoid using @code{wfdbinit} and @code{setifreq} in the same program. @c @group -@node getifreq, setgvmode, setifreq, special input modes +@node getifreq, setgvmode, setifreq, special I/O modes @unnumberedsubsec getifreq @findex getifreq (10.2.6) @@ -2397,7 +2432,7 @@ or the frequency chosen using a previous invocation of @code{setifreq}. @c @group -@node setgvmode, getspf, getifreq, special input modes +@node setgvmode, getspf, getifreq, special I/O modes @unnumberedsubsec setgvmode @findex setgvmode (9.0) @cindex interpolation @@ -2446,7 +2481,7 @@ The constant @code{WFDB_GVPAD} is defined in @file{}. @c @group -@node getspf, , setgvmode, special input modes +@node getspf, setafreq, setgvmode, special I/O modes @unnumberedsubsec getspf @findex getspf (9.6) @cindex interpolation @@ -2473,8 +2508,57 @@ samples per signal per frame (hence @code{sampfreq(NULL)/getspf()} is the number of frames per second). +@node setafreq, getafreq, getspf, special I/O modes +@unnumberedsubsec setafreq +@findex setafreq (10.4.5) +@cindex interpolation +@cindex decimation +@cindex resampling +@cindex resolution + +@example +void setafreq(WFDB_Frequency @var{frequency}) +@end example +@noindent +@c @end group + +@noindent +This function sets the time resolution, in ticks per second, for any output +annotation files created after it has been invoked. By default, the time +resolution is equal to the input sampling frequency (and @code{setifreq} +invokes @code{setafreq} to maintain this behavior if the input sampling +frequency is changed). + +@noindent +This function has no effect on output annotation files that are already open +when it is invoked, nor on annotations read from input annotation files +(for which the @code{time} fields always are expressed in units equal to +the input sample intervals). + +@c @group +@node getafreq, , setafreq, special I/O modes +@unnumberedsubsec getafreq +@findex getafreq (10.4.5) + +@example +WFDB_Frequency getafreq(void) +@end example +@noindent +@strong{Return:} +@table @asis +@item @t{>0} +output annotation time resolution, if previously set by @code{setafreq} +@item @t{0} +otherwise +@end table +@c @end group + +@noindent +This function returns the current output annotation time resolution +in ticks per second if it has been set using @code{getafreq}. + @page -@node signal and annotation I/O, non-sequential, special input modes, Functions +@node signal and annotation I/O, non-sequential, special I/O modes, Functions @section Reading and Writing Signals and Annotations @cindex signal I/O @@ -3756,6 +3840,7 @@ * iannclose and oannclose:: Closing annotation files. * wfdbquiet and wfdbverbose:: Suppressing error messages from the WFDB library. * wfdberror:: Retrieving error messages from the WFDB library. +* wfdbmemerr:: Setting WFDB library behavior on memory errors. * sampfreq:: Reading the sampling frequency of a WFDB record. * setsampfreq:: Setting the sampling frequency. * setbasetime:: Setting the base time. @@ -4078,7 +4163,7 @@ version 4.0.) @c @group -@node wfdberror, sampfreq, wfdbquiet and wfdbverbose, miscellaneous functions +@node wfdberror, wfdbmemerr, wfdbquiet and wfdbverbose, miscellaneous functions @unnumberedsubsec wfdberror @findex wfdberror (4.5) @@ -4107,7 +4192,30 @@ rather than the library version number if there have been no errors. @c @group -@node sampfreq, setsampfreq, wfdberror, miscellaneous functions +@node wfdbmemerr, sampfreq, wfdberror, miscellaneous functions +@unnumberedsubsec wfdbmemerr +@findex wfdbmemerr (10.4.6) + +@example +@code{void wfdbmemerr(int behavior)} +@end example +@noindent +@c @end group + +@noindent +This function sets how the WFDB library behaves in the event of a memory +allocation error. If @var{behavior} is any non-zero value, then such an +event causes the WFDB library to emit an appropriate error message and then +terminate the running program. (This behavior is the default.) + +If @var{behavior} is zero, a subsequent memory allocation error will cause +the WFDB library function in which it occurs to continue running if possible +(after emitting an error message as above). + +This function was first introduced in WFDB library version 10.4.6. + +@c @group +@node sampfreq, setsampfreq, wfdbmemerr, miscellaneous functions @unnumberedsubsec sampfreq @findex sampfreq @@ -5506,6 +5614,8 @@ The other topics in this section deal with special types of database access: +* EDF Files:: a popular format readable by WFDB 10.4.5 and + later. * AHA Format Files:: not used for on-line WFDB records. * Standard I/O:: pipes and I/O redirection for WFDB files. * Multiplexed Signal Files:: signal groups. @@ -5564,7 +5674,7 @@ correct). Annotation files are binary, and contain records of variable length that average slightly over 16 bits per annotation. -@node Calibration Files, AHA Format Files, Annotation Files, Database Files +@node Calibration Files, EDF Files, Annotation Files, Database Files @unnumberedsubsec Calibration Files @cindex calibration file @@ -5584,7 +5694,44 @@ The WFDB Software Package includes a standard calibration file, @file{wfdbcal}, in the @file{data} directory. -@node AHA Format Files, Standard I/O, Calibration Files, Database Files +@node EDF Files, AHA Format Files, Calibration Files, Database Files +@unnumberedsubsec EDF Files +@cindex EDF +@cindex European Data Format + +European Data Format (EDF) was defined in 1990, and it has become a very +widely supported open format for exchange of recorded physiologic signals, +especially polysomnograms. EDF files encapsulate functional equivalents of +header and signal files, and EDF+ files can also include annotation streams +(stored as signals). + +EDF files begin with an embedded (text) header containing specifications of the +signals and a limited amount of demographic information, followed by the binary +samples of the signals. Within each block of samples, typically one second to +one minute in length, all samples of the first signal are stored consecutively, +followed by all samples of the second signal, etc. + +EDF files can be read directly using WFDB library version 10.4.5 and later. +The name of the file, which must include a '.' and cannot end in '.hea', can +be passed as a record name to any WFDB library function that accepts record +names. Although the WFDB library does not support EDF as an output format, the +@file{mit2edf} application included in the WFDB Software Package can convert +anything readable by the WFDB library into EDF. + +EDF+, defined in 2003, is backwards-compatible with EDF (any EDF reader, +including the WFDB library, can read EDF+), but the additional features of +EDF+, including methods for reading annotations and recognizing signal +discontinuities (which are marked by annotations), are available only from +EDF+-specific readers. The WFDB library does not currently include built-in +support for the additional features of EDF+, but annotation streams are +available as signals, so it is possible for an application using the WFDB +library to provide its own means of decoding annotation streams as they are +read. + +Further information about EDF and EDF+ is available at +@uref{http://www.edfplus.info/}. + +@node AHA Format Files, Standard I/O, EDF Files, Database Files @unnumberedsubsec AHA Format Files @cindex AHA format @@ -5971,7 +6118,7 @@ (or @code{isigopen}, @code{annopen}, etc.). Current implementations of @code{libcurl} and @code{libwww} permit input from -@uref{http://} URLs in much the same way that local files are read, provided +@code{http://} URLs in much the same way that local files are read, provided that the remote web server supports HTTP 1.1 range requests (most, including PhysioNet's, do). This means that it is not necessary to download an entire file in order to examine part of it, and you may notice little or no speed @@ -8601,6 +8748,7 @@ @itemx MIT-BIH Polysomnographic Database @itemx MIMIC Database @itemx MGH/Marquette Foundation Waveform Database CROMs +@item Long-Term ST Database @itemx Other reference databases of physiologic signals @itemx WFDB Software Package @itemx W3C libwww sources @@ -8639,24 +8787,6 @@ Over half of this database has been contributed to PhysioNet (see above), from which it may be downloaded freely. -@cindex CDROM -@cindex LTST DB -@item Long-Term ST Database -@sp 1 -@display -Franc Jager -Laboratory of Biomedical Computer Systems and Imaging -University of Ljubljana -Faculty of Computer and Information Science -Trzaska 25 -1000 Ljubljana, Slovenia - -email: @email{lbcsi@@fri.uni-lj.si} -@end display - -Over half of this database has been contributed to PhysioNet (see above), from -which it may be downloaded freely. - @cindex AHA DB @item AHA Database for Evaluation of Ventricular Arrhythmia Detectors @sp 1 @@ -8690,15 +8820,17 @@ WWW: @uref{http://www.cinc.org/} @end display -CinC is the major scientific meeting at which current research in ECG signal -processing and modelling is discussed; the proceedings of the conference are -probably the single best source of information in print about these topics. -CinC conferences have taken place annually since 1974, usually in September. -They are usually convened in North America and in Europe in alternate years. -The deadline for submission of abstracts is on or about 1 May each year. -Proceedings of the conferences are published by the IEEE, and usually -appear about 3 months after the date of the conference. CinC will be in -in Valencia (Spain) in 2006, and in Durham, NC (USA) in 2007. +CinC is the major scientific meeting at which current research in ECG +signal processing and modelling is discussed; the proceedings of the +conference are probably the single best source of information in print +about these topics. CinC conferences have taken place annually since +1974, usually in September. They are usually convened in North +America and in Europe in alternate years. The deadline for submission +of abstracts is on or about 1 May each year. Proceedings of CinC +conferences since 2006 are available on-line at +@uref{http://cinc.mit.edu/archives/}, and usually appear about a month +after the date of the conference. CinC will be in in Bologna (Italy) +in 2008, and in Park City, Utah (USA) in 2009. Since 2000, Computers in Cardiology and PhysioNet have jointly sponsored an annual series of open challenges that invite participants to address @@ -8710,7 +8842,10 @@ @item Proceedings of Computers in Cardiology (ISSN 0276-6574) @sp 1 -IEEE members can find complete CinC proceedings from 1988 to the +CinC proceedings from 2006 to present are available on-line at +@uref{http://cinc.mit.edu/archives/}. + +IEEE members can find CinC proceedings from 1988 to the present using IEEEXplore (@uref{http://ieeexplore.ieee.org/}). Many universities provide access to these services for their students, faculty, and staff. Printed volumes of CinC proceedings are available from: @@ -8815,7 +8950,7 @@ @cindex X11 @cindex X Window System -@item X11R6 (the X Window System, Version 11, Release 6) +@item X11 (the X Window System, Version 11) @sp 1 @display @@ -8856,9 +8991,9 @@ WWW: @uref{http://www.debian.org/} -Fedora +Fedora (non-commercial) -WWW: @uref{http://fedora.redhat.com/} +WWW: @uref{http://fedoraproject.org/} Gentoo (non-commercial) @@ -8881,7 +9016,7 @@ WWW: @uref{http://www.redhat.com/} -Slackware +Slackware (non-commercial) WWW: @uref{http://www.slackware.com/} diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wpg-src/wpg.ht0 wfdb-10.4.6/doc/wpg-src/wpg.ht0 --- wfdb-10.4.5/doc/wpg-src/wpg.ht0 2006-02-27 11:13:09.000000000 -0500 +++ wfdb-10.4.6/doc/wpg-src/wpg.ht0 2008-04-09 16:13:35.000000000 -0400 @@ -19,7 +19,7 @@ George B. Moody
Harvard-MIT Division of Health Sciences and Technology

-Copyright ©1980-2006 George B. Moody. +Copyright ©1980-2008 George B. Moody.

The most recent versions of the software described in this guide are freely downloadable from PhysioNet. For diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/doc/wug-src/wug0.tex wfdb-10.4.6/doc/wug-src/wug0.tex --- wfdb-10.4.5/doc/wug-src/wug0.tex 2006-05-05 12:59:12.000000000 -0400 +++ wfdb-10.4.6/doc/wug-src/wug0.tex 2008-04-09 16:14:54.000000000 -0400 @@ -57,7 +57,7 @@ \pagestyle{empty} \vspace*{\fill} \noindent -Copyright \copyright 1992 -- 2006 George B. Moody +Copyright \copyright 1992 -- 2008 George B. Moody \vspace{1 in} \noindent diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/fortran/wfdbf.c wfdb-10.4.6/fortran/wfdbf.c --- wfdb-10.4.5/fortran/wfdbf.c 2006-02-24 23:23:38.000000000 -0500 +++ wfdb-10.4.6/fortran/wfdbf.c 2008-02-08 10:45:50.000000000 -0500 @@ -1,9 +1,9 @@ /* file: wfdbf.c G. Moody 23 August 1995 - Last revised: 24 February 2006 wfdblib 10.4.0 + Last revised: 8 February 2008 wfdblib 10.4.6 _______________________________________________________________________________ wfdbf: Fortran wrappers for the WFDB library functions -Copyright (C) 1995-2006 George B. Moody +Copyright (C) 1995-2008 George B. Moody This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free @@ -46,7 +46,7 @@ Fortran program; thus, for example, `annopen_' should be invoked as `annopen'. UNIX Fortran compilers and translators append a `_' to the names of all external symbols referenced in Fortran source files when -generating object files. Thus the linker can recognize that annopen1_ +generating object files. Thus the linker can recognize that annopen_ (defined below) is the function required by a Fortran program that invokes `annopen'; if the Fortran program were to invoke `annopen_', the linker would search (unsuccessfully) for a function named `annopen__'. @@ -233,6 +233,16 @@ return (getifreq()); } +long setafreq_(double *freq) +{ + return (setafreq(*freq)); +} + +double getafreq_(long int *dummy) +{ + return (getafreq()); +} + long getvec_(long int *long_vector) { #ifndef REPACK diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/lib/annot.c wfdb-10.4.6/lib/annot.c --- wfdb-10.4.5/lib/annot.c 2008-01-14 22:26:52.000000000 -0500 +++ wfdb-10.4.6/lib/annot.c 2008-04-08 14:28:58.000000000 -0400 @@ -1,5 +1,5 @@ /* file: annot.c G. Moody 13 April 1989 - Last revised: 14 January 2008 wfdblib 10.4.5 + Last revised: 8 April 2008 wfdblib 10.4.6 WFDB library functions for annotations _______________________________________________________________________________ @@ -174,21 +174,15 @@ p1 = strtok(annot.aux+1, " \t"); a = atoi(p1); if (0 <= a && a <= ACMAX && (p1 = strtok((char *)NULL, " \t"))) { - p2 = p1 + strlen(p1) + 1; - if ((s1 = (char *)malloc(((unsigned)(strlen(p1) + 1)))) == NULL || - (*p2 && - (s2 = (char *)malloc(((unsigned)(strlen(p2)+1)))) == NULL)) { - wfdb_error("annopen: insufficient memory\n"); - return (-1); - } - (void)strcpy(s1, p1); + SSTRCPY(s1, p1); (void)setannstr(a, s1); + p2 = p1 + strlen(p1) + 1; if (*p2) { - (void)strcpy(s2, p2); + SSTRCPY(s2, p2); (void)setanndesc(a, s2); } else - (void)setanndesc(a, (char*)NULL); + (void)setanndesc(a, (char *)NULL); } } @@ -255,20 +249,10 @@ { if (maxiann < n) { /* allocate input annotator data structures */ unsigned m = maxiann; - struct iadata **iadnew = realloc(iad, n*sizeof(struct iadata *)); - if (iadnew == NULL) { - wfdb_error("annopen: too many (%d) input annotators\n", n); - return (-1); - } - iad = iadnew; + SREALLOC(iad, n, sizeof(struct iadata *)); while (m < n) { - if ((iad[m] = calloc(1, sizeof(struct iadata))) == NULL) { - wfdb_error("annopen: too many (%d) input annotators\n", n); - while (--m > maxiann) - free(iad[m]); - return (-1); - } + SUALLOC(iad[m], 1, sizeof(struct iadata)); m++; } maxiann = n; @@ -281,20 +265,10 @@ { if (maxoann < n) { /* allocate output annotator data structures */ unsigned m = maxoann; - struct oadata **oadnew = realloc(oad, n*sizeof(struct oadata *)); - if (oadnew == NULL) { - wfdb_error("annopen: too many (%d) output annotators\n", n); - return (-1); - } - oad = oadnew; + SREALLOC(oad, n, sizeof(struct oadata *)); while (m < n) { - if ((oad[m] = calloc(1, sizeof(struct oadata))) == NULL) { - wfdb_error("annopen: too many (%d) output annotators\n", n); - while (--m > maxoann) - free(oad[m]); - return (-1); - } + SUALLOC(oad[m], 1, sizeof(struct oadata)); m++; } maxoann = n; @@ -356,13 +330,8 @@ aiarray[i].name, record); return (-3); } - if ((ia->info.name = - (char *)malloc((unsigned)(strlen(aiarray[i].name)+1))) - == NULL) { - wfdb_error("annopen: insufficient memory\n"); - return (-3); - } - (void)strcpy(ia->info.name, aiarray[i].name); + ia->info.name = NULL; + SSTRCPY(ia->info.name, aiarray[i].name); /* Try to figure out what format the file is in. AHA-format files begin with a null byte and an ASCII character which is one @@ -411,20 +380,10 @@ aiarray[i].name, record); return (-4); } - if ((oa->info.name = - (char *)malloc((unsigned)(strlen(aiarray[i].name)+1))) - == NULL) { - wfdb_error("annopen: insufficient memory\n"); - return (-4); - } - (void)strcpy(oa->info.name, aiarray[i].name); - if ((oa->rname = - (char *)malloc((unsigned)(strlen(record)+1))) - == NULL) { - wfdb_error("annopen: insufficient memory\n"); - return (-4); - } - (void)strcpy(oa->rname, record); + oa->info.name = NULL; + SSTRCPY(oa->info.name, aiarray[i].name); + oa->rname = NULL; + SSTRCPY(oa->rname, record); oa->ann.time = 0L; oa->info.stat = aiarray[i].stat; oa->out_of_order = 0; @@ -754,6 +713,7 @@ { int code; + if (str == NULL) str = ""; for (code = 1; code <= ACMAX; code++) if (strcmp(str, cstring[code]) == 0) return (code); @@ -764,10 +724,13 @@ FINT setecgstr(int code, char *string) { if (NOTQRS <= code && code <= ACMAX) { - if (cstring[code] == NULL || strcmp(cstring[code], string)) { - char *p = malloc(strlen(string)+1); - if (p) strcpy(cstring[code] = p, string); - } + if (string == NULL) string = ""; + cstring[code] = NULL; /* This statement (and the corresponding + statements in setannstr and setanndesc) + leak memory if the function is called + more than once with the same value for + code -- which is unlikely. */ + SSTRCPY(cstring[code], string); return (0); } wfdb_error("setecgstr: illegal annotation code %d\n", code); @@ -803,6 +766,7 @@ { int code; + if (str == NULL) str = ""; for (code = 1; code <= ACMAX; code++) if (strcmp(str, astring[code]) == 0) return (code); @@ -811,20 +775,16 @@ FINT setannstr(int code, char *string) { - if (0 < code && code <= ACMAX) { + int mflag = 0; + + if (code > 0) mflag = 1; + else code = -code; + if (code <= ACMAX) { + if (string == NULL) string = ""; if (astring[code] == NULL || strcmp(astring[code], string)) { - char *p = malloc(strlen(string)+1); - if (p) { - strcpy(astring[code] = p, string); - modified[code] = 1; - } - } - return (0); - } - else if (-ACMAX < code && code <= 0) { - if (astring[-code] == NULL || strcmp(astring[-code], string)) { - char *p = malloc(strlen(string)+1); - if (p) strcpy(astring[-code] = p, string); + astring[code] = NULL; + SSTRCPY(astring[code], string); + if (mflag) modified[code] = 1; } return (0); } @@ -897,20 +857,16 @@ FINT setanndesc(int code, char *string) { - if (0 < code && code <= ACMAX) { + int mflag = 0; + + if (code > 0) mflag = 1; + else code = -code; + if (code <= ACMAX) { + if (string == NULL) string = ""; if (tstring[code] == NULL || strcmp(tstring[code], string)) { - char *p = malloc(strlen(string)+1); - if (p) { - strcpy(tstring[code] = p, string); - modified[code] = 1; - } - } - return (0); - } - else if (-ACMAX < code && code <= 0) { - if (tstring[-code] == NULL || strcmp(tstring[-code], string)) { - char *p = malloc(strlen(string)+1); - if (p) strcpy(tstring[-code] = p, string); + tstring[code] = NULL; + SSTRCPY(tstring[code], string); + if (mflag) modified[code] = 1; } return (0); } @@ -941,8 +897,8 @@ if (n < niaf && (ia = iad[n]) != NULL && ia->file != NULL) { (void)wfdb_fclose(ia->file); - (void)free(ia->info.name); - (void)free(ia); + SFREE(ia->info.name); + SFREE(ia); while (n < niaf-1) { iad[n] = iad[n+1]; n++; @@ -999,9 +955,9 @@ oa->rname, oa->info.name); wfdb_error("to rearrange annotations in the correct order.\n"); } - (void)free(oa->info.name); - (void)free(oa->rname); - (void)free(oa); + SFREE(oa->info.name); + SFREE(oa->rname); + SFREE(oa); while (n < noaf-1) { oad[n] = oad[n+1]; n++; diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/lib/calib.c wfdb-10.4.6/lib/calib.c --- wfdb-10.4.5/lib/calib.c 2006-02-23 15:56:01.000000000 -0500 +++ wfdb-10.4.6/lib/calib.c 2008-04-08 14:41:36.000000000 -0400 @@ -1,10 +1,10 @@ /* file: calib.c G. Moody 4 July 1991 - Last revised: 23 February 2006 wfdblib 10.4.0 + Last revised: 8 April 2008 wfdblib 10.4.6 WFDB library functions for signal calibration _______________________________________________________________________________ wfdb: a library for reading and writing annotated waveforms (time series data) -Copyright (C) 1991-2006 George B. Moody +Copyright (C) 1991-2008 George B. Moody This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free @@ -104,27 +104,11 @@ continue; /* This line appears to be a correctly formatted entry. Allocate - memory for a calibration list entry. (There doesn't seem to be any - way to make lint shut up about the pointer casts below, or about - those in getcal; hence the `#ifndef lint' directives.) */ -#ifndef lint - if ((this_cle = (struct cle *)malloc(sizeof(struct cle))) == NULL || - (this_cle->sigtype = - (char *)malloc((unsigned)(strlen(p1)+1))) == NULL || - (this_cle->units = - (char *)malloc((unsigned)(strlen(p6)+1))) == NULL) { - if (this_cle) { - if (this_cle->sigtype) free(this_cle->sigtype); - free((char *)this_cle); - } - wfdb_error("calopen: insufficient memory\n"); - (void)wfdb_fclose(cfile); - return (-1); - } -#endif + memory for a calibration list entry. */ + SUALLOC(this_cle, 1, (sizeof(struct cle))); /* Fill in the fields of the new calibration list entry. */ - (void)strcpy(this_cle->sigtype, p1); + SSTRCPY(this_cle->sigtype, p1); if (strcmp(p2, "-") == 0) { this_cle->caltype = WFDB_AC_COUPLED; this_cle->low = 0.0; @@ -145,7 +129,7 @@ this_cle->caltype |= WFDB_CAL_SAWTOOTH; /* otherwise pulse shape is undefined */ this_cle->scale = atof(p5); - (void)strcpy(this_cle->units, p6); + SSTRCPY(this_cle->units, p6); this_cle->next = NULL; /* Append the new entry to the end of the list. */ @@ -191,27 +175,13 @@ the calibration list. */ FINT putcal(WFDB_Calinfo *cal) { -#ifndef lint - if ((this_cle = (struct cle *)malloc(sizeof(struct cle))) == NULL || - (this_cle->sigtype = - (char *)malloc((unsigned)(strlen(cal->sigtype)+1))) == NULL || - (this_cle->units = - (char *)malloc((unsigned)(strlen(cal->units)+1))) == NULL) { - if (this_cle) { - if (this_cle->sigtype) free(this_cle->sigtype); - free((char *)this_cle); - } - wfdb_error("putcal: insufficient memory\n"); - return (-1); - } -#endif - - (void)strcpy(this_cle->sigtype, cal->sigtype); + SUALLOC(this_cle, 1, sizeof(struct cle)); + SSTRCPY(this_cle->sigtype, cal->sigtype); this_cle->caltype = cal->caltype; this_cle->low = cal->low; this_cle->high = cal->high; this_cle->scale = cal->scale; - (void)strcpy(this_cle->units, cal->units); + SSTRCPY(this_cle->units, cal->units); this_cle->next = NULL; if (first_cle) { @@ -268,12 +238,10 @@ FVOID flushcal(void) { while (first_cle) { - free(first_cle->sigtype); - free(first_cle->units); + SFREE(first_cle->sigtype); + SFREE(first_cle->units); this_cle = first_cle->next; -#ifndef lint - free(first_cle); -#endif + SFREE(first_cle); first_cle = this_cle; } } diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/lib/signal.c wfdb-10.4.6/lib/signal.c --- wfdb-10.4.5/lib/signal.c 2008-02-06 11:24:58.000000000 -0500 +++ wfdb-10.4.6/lib/signal.c 2008-04-08 13:31:07.000000000 -0400 @@ -1,5 +1,5 @@ /* file: signal.c G. Moody 13 April 1989 - Last revised: 6 February 2008 wfdblib 10.4.5 + Last revised: 8 April 2008 wfdblib 10.4.6 WFDB library functions for signals _______________________________________________________________________________ @@ -153,7 +153,7 @@ if (n < 1) { /* no signals -- quit or try another record, etc. */ } /* Allocate WFDB_Siginfo structures before calling isigopen again. */ - si = calloc(n, sizeof(WFDB_Siginfo)); + SUALLOC(si, n, sizeof(WFDB_Siginfo)); nsig = isigopen("record", si, n); /* Note that nsig equals n only if all signals were readable. */ @@ -161,7 +161,7 @@ for (i = framelen = 0; i < nsig; i++) framelen += si[i].spf; /* Allocate WFDB_Samples before calling getframe. */ - vector = calloc(framelen, sizeof(WFDB_Sample)); + SUALLOC(vector, framelen, sizeof(WFDB_Sample)); getframe(vector); } #endif @@ -327,20 +327,10 @@ { if (maxisig < n) { unsigned m = maxisig; - struct isdata **isdnew = realloc(isd, n*sizeof(struct isdata *)); - if (isdnew == NULL) { - wfdb_error("init: too many (%d) input signals\n", n); - return (-1); - } - isd = isdnew; + SREALLOC(isd, n, sizeof(struct isdata *)); while (m < n) { - if ((isd[m] = calloc(1, sizeof(struct isdata))) == NULL) { - wfdb_error("init: too many (%d) input signals\n", n); - while (--m > maxisig) - free(isd[m]); - return (-1); - } + SUALLOC(isd[m], 1, sizeof(struct isdata)); m++; } maxisig = n; @@ -353,20 +343,10 @@ { if (maxigroup < n) { unsigned m = maxigroup; - struct igdata **igdnew = realloc(igd, n*sizeof(struct igdata *)); - if (igdnew == NULL) { - wfdb_error("init: too many (%d) input signal groups\n", n); - return (-1); - } - igd = igdnew; + SREALLOC(igd, n, sizeof(struct igdata *)); while (m < n) { - if ((igd[m] = calloc(1, sizeof(struct igdata))) == NULL) { - wfdb_error("init: too many (%d) input signal groups\n", n); - while (--m > maxigroup) - free(igd[m]); - return (-1); - } + SUALLOC(igd[m], 1, sizeof(struct igdata)); m++; } maxigroup = n; @@ -379,20 +359,10 @@ { if (maxosig < n) { unsigned m = maxosig; - struct osdata **osdnew = realloc(osd, n*sizeof(struct osdata *)); - if (osdnew == NULL) { - wfdb_error("init: too many (%d) output signals\n", n); - return (-1); - } - osd = osdnew; + SREALLOC(osd, n, sizeof(struct osdata *)); while (m < n) { - if ((osd[m] = calloc(1, sizeof(struct osdata))) == NULL) { - wfdb_error("init: too many (%d) output signals\n", n); - while (--m > maxosig) - free(osd[m]); - return (-1); - } + SUALLOC(osd[m], 1, sizeof(struct osdata)); m++; } maxosig = n; @@ -405,20 +375,10 @@ { if (maxogroup < n) { unsigned m = maxogroup; - struct ogdata **ogdnew = realloc(ogd, n*sizeof(struct ogdata *)); - if (ogdnew == NULL) { - wfdb_error("init: too many (%d) output signal groups\n", n); - return (-1); - } - ogd = ogdnew; + SREALLOC(ogd, n, sizeof(struct ogdata *)); while (m < n) { - if ((ogd[m] = calloc(1, sizeof(struct ogdata))) == NULL) { - wfdb_error("init: too many (%d) output signal groups\n", n); - while (--m > maxogroup) - free(ogd[m]); - return (-1); - } + SUALLOC(ogd[m], 1, sizeof(struct ogdata)); m++; } maxogroup = n; @@ -440,31 +400,10 @@ { if (to == NULL || from == NULL) return (0); *to = *from; - /* The next line works around an optimizer bug in gcc (version 2.96, maybe - others). */ to->fname = to->desc = to->units = NULL; - if (from->fname) { - to->fname = (char *)malloc((size_t)strlen(from->fname)+1); - if (to->fname == NULL) return (-1); - (void)strcpy(to->fname, from->fname); - } - if (from->desc) { - to->desc = (char *)malloc((size_t)strlen(from->desc)+1); - if (to->desc == NULL) { - (void)free(to->fname); - return (-1); - } - (void)strcpy(to->desc, from->desc); - } - if (from->units) { - to->units = (char *)malloc((size_t)strlen(from->units)+1); - if (to->units == NULL) { - (void)free(to->desc); - (void)free(to->fname); - return (-1); - } - (void)strcpy(to->units, from->units); - } + SSTRCPY(to->fname, from->fname); + SSTRCPY(to->desc, from->desc); + SSTRCPY(to->units, from->units); return (1); } @@ -514,12 +453,11 @@ int i; need_sigmap = nvsig = tspf = 0; - if (ovec) { free(ovec); ovec = NULL; } + SFREE(ovec); if (smi) { for (i = 0; i < tspf; i += smi[i].spf) - if (smi[i].desc) free(smi[i].desc); - free(smi); - smi = NULL; + SFREE(smi[i].desc); + SFREE(smi); } if (vsd) { @@ -527,13 +465,12 @@ while (maxvsig) if (is = vsd[--maxvsig]) { - if (is->info.fname) (void)free(is->info.fname); - if (is->info.units) (void)free(is->info.units); - if (is->info.desc) (void)free(is->info.desc); - (void)free(is); + SFREE(is->info.fname); + SFREE(is->info.units); + SFREE(is->info.desc); + SFREE(is); } - (void)free(vsd); - vsd = NULL; + SFREE(vsd); } } @@ -548,20 +485,10 @@ if (maxvsig < nvsig) { unsigned m = maxvsig; - struct isdata **vsdnew = realloc(vsd, nvsig*sizeof(struct isdata *)); - if (vsdnew == NULL) { - wfdb_error("init: too many (%d) input signals\n", nvsig); - return (-1); - } - vsd = vsdnew; + SREALLOC(vsd, nvsig, sizeof(struct isdata *)); while (m < nvsig) { - if ((vsd[m] = calloc(1, sizeof(struct isdata))) == NULL) { - wfdb_error("init: too many (%d) input signals\n", nvsig); - while (--m > maxvsig) - free(isd[m]); - return (-1); - } + SUALLOC(vsd[m], 1, sizeof(struct isdata)); m++; } maxvsig = nvsig; @@ -587,18 +514,9 @@ nvsig = nisig; for (s = tspf = 0; s < nisig; s++) tspf += isd[s]->info.spf; - if ((smi = malloc(tspf * sizeof(struct sigmapinfo))) == NULL) { - wfdb_error("sigmap_init: out of memory\n"); - return (-1); - } - + SALLOC(smi, tspf, sizeof(struct sigmapinfo)); for (i = s = 0; i < nisig; i++) { - if (smi[s].desc = malloc(strlen(isd[i]->info.desc)+1)) - strcpy(smi[s].desc, isd[i]->info.desc); - else { - wfdb_error("sigmap_init: out of memory\n"); - return (-1); - } + SSTRCPY(smi[s].desc, isd[i]->info.desc); smi[s].gain = isd[i]->info.gain; smi[s].baseline = isd[i]->info.baseline; k = smi[s].spf = isd[i]->info.spf; @@ -606,11 +524,7 @@ smi[s + j] = smi[s]; s += k; } - - if ((ovec = malloc(tspf * sizeof(WFDB_Sample))) == NULL) { - wfdb_error("sigmap_init: out of memory\n"); - return (-1); - } + SALLOC(ovec, tspf, sizeof(WFDB_Sample)); return (make_vsd()); } @@ -729,35 +643,18 @@ /* Allocate workspace. */ if (maxhsig < nsig) { unsigned m = maxhsig; - struct hsdata **hsdnew = realloc(hsd, nsig*sizeof(struct hsdata *)); - if (hsdnew == NULL) { - wfdb_error("init: too many (%d) signals in header file\n", nsig); - return (-2); - } - hsd = hsdnew; + SREALLOC(hsd, nsig, sizeof(struct hsdata *)); while (m < nsig) { - if ((hsd[m] = calloc(1, sizeof(struct hsdata))) == NULL) { - wfdb_error("init: too many (%d) signals in header file\n", - nsig); - while (--m > maxhsig) - free(hsd[m]); - return (-2); - } + SUALLOC(hsd[m], 1, sizeof(struct hsdata)); m++; } maxhsig = nsig; } - if ((dmax = malloc(nsig * sizeof(long))) == NULL || - (dmin = malloc(nsig * sizeof(long))) == NULL || - (pmax = malloc(nsig * sizeof(double))) == NULL || - (pmin = malloc(nsig * sizeof(double))) == NULL) { - wfdb_error("init: too many (%d) signals in header file\n", nsig); - if (pmax) free(pmax); - if (dmin) free(dmin); - if (dmax) free(dmax); - return (-2); - } + SUALLOC(dmax, nsig, sizeof(long)); + SUALLOC(dmin, nsig, sizeof(long)); + SUALLOC(pmax, nsig, sizeof(double)); + SUALLOC(pmin, nsig, sizeof(double)); /* Strip off any path info from the EDF file name. */ p = edf_fname + strlen(edf_fname) - 4; @@ -768,8 +665,7 @@ for (s = 0; s < nsig; s++) { hsd[s]->start = offset; hsd[s]->skew = 0; - if (hsd[s]->info.fname = (char *)malloc(strlen(edf_fname)+1)) - strcpy(hsd[s]->info.fname, edf_fname); + SSTRCPY(hsd[s]->info.fname, edf_fname); hsd[s]->info.group = hsd[s]->info.bsize = hsd[s]->info.cksum = 0; hsd[s]->info.fmt = 16; hsd[s]->info.nsamp = nframes; @@ -778,8 +674,7 @@ junk[16] = ' '; for (i = 16; i >= 0 && junk[i] == ' '; i--) junk[i] = '\0'; - if (hsd[s]->info.desc = (char *)malloc(strlen(junk)+1)) - strcpy(hsd[s]->info.desc, junk); + SSTRCPY(hsd[s]->info.desc, junk); } for (s = 0; s < nsig; s++) @@ -789,8 +684,7 @@ wfdb_fread(buf, 1, 8, ifile); /* signal units */ for (i = 7; i >= 0 && buf[i] == ' '; i--) buf[i] = '\0'; - if (hsd[s]->info.units = (char *)malloc(strlen(buf)+1)) - strcpy(hsd[s]->info.units, buf); + SSTRCPY(hsd[s]->info.units, buf); } for (s = 0; s < nsig; s++) { @@ -852,10 +746,10 @@ hour, minute, second, day, month, year); setbasetime(buf); - free(pmin); - free(pmax); - free(dmin); - free(dmax); + SFREE(pmin); + SFREE(pmax); + SFREE(dmin); + SFREE(dmax); isedf = 1; return (nsig); } @@ -877,10 +771,9 @@ if (in_msrec && vsd) { char *p; - hsd = calloc(1, sizeof(struct hsdata *)); - hsd[0] = calloc(1, sizeof(struct hsdata)); - p = calloc(2, sizeof(char)); *p = '~'; - hsd[0]->info.desc = p; + SALLOC(hsd, 1, sizeof(struct hsdata *)); + SALLOC(hsd[0], 1, sizeof(struct hsdata)); + SSTRCPY(hsd[0]->info.desc, "~"); hsd[0]->info.spf = 1; hsd[0]->info.fmt = 0; hsd[0]->info.nsamp = nsamples = segp->nsamp; @@ -1059,12 +952,7 @@ msbdate = bdate; msnsamples = nsamples; /* Read the names and lengths of the segment records. */ - segarray = (struct segrec *)calloc(segments, sizeof(struct segrec)); - if (segarray == (struct segrec *)NULL) { - wfdb_error("init: insufficient memory\n"); - segments = 0; - return (-2); - } + SALLOC(segarray, segments, sizeof(struct segrec)); segp = segarray; for (i = 0, ns = (WFDB_Time)0L; i < segments; i++, segp++) { /* Get next segment spec, skip empty lines and comments. */ @@ -1073,8 +961,7 @@ wfdb_error( "init: unexpected EOF in header file for record %s\n", record); - (void)free(segarray); - segarray = (struct segrec *)NULL; + SFREE(segarray); segments = 0; return (-2); } @@ -1083,8 +970,7 @@ wfdb_error( "init: `%s' is too long for a segment name in record %s\n", p, record); - (void)free(segarray); - segarray = (struct segrec *)NULL; + SFREE(segarray); segments = 0; return (-2); } @@ -1094,8 +980,7 @@ wfdb_error( "init: length must be specified for segment %s in record %s\n", segp->recname, record); - (void)free(segarray); - segarray = (struct segrec *)NULL; + SFREE(segarray); segments = 0; return (-2); } @@ -1117,21 +1002,10 @@ /* Allocate workspace. */ if (maxhsig < nsig) { unsigned m = maxhsig; - struct hsdata **hsdnew = realloc(hsd, nsig*sizeof(struct hsdata *)); - if (hsdnew == NULL) { - wfdb_error("init: too many (%d) signals in header file\n", nsig); - return (-2); - } - hsd = hsdnew; + SREALLOC(hsd, nsig, sizeof(struct hsdata *)); while (m < nsig) { - if ((hsd[m] = calloc(1, sizeof(struct hsdata))) == NULL) { - wfdb_error("init: too many (%d) signals in header file\n", - nsig); - while (--m > maxhsig) - free(hsd[m]); - return (-2); - } + SUALLOC(hsd[m], 1, sizeof(struct hsdata)); m++; } maxhsig = nsig; @@ -1160,13 +1034,8 @@ match that of the previous signal, the group number is one greater than that of the previous signal. */ if (s == 0 || strcmp(p, hp->info.fname)) { - hs->info.group = (s == 0) ? 0 : hp->info.group + 1; - if ((hs->info.fname =(char *)malloc((unsigned)(strlen(p)+1))) - == NULL) { - wfdb_error("init: insufficient memory\n"); - return (-2); - } - (void)strcpy(hs->info.fname, p); + hs->info.group = (s == 0) ? 0 : hp->info.group + 1; + SSTRCPY(hs->info.fname, p); } /* If the file names of the current and previous signals match, they are assigned the same group number and share a copy of the @@ -1176,12 +1045,7 @@ this has been done. */ else { hs->info.group = hp->info.group; - if ((hs->info.fname = (char *)malloc(strlen(hp->info.fname)+1)) - == NULL) { - wfdb_error("init: insufficient memory\n"); - return (-2); - } - (void)strcpy(hs->info.fname, hp->info.fname); + SSTRCPY(hs->info.fname, hp->info.fname); } /* Determine the signal format. */ @@ -1228,10 +1092,7 @@ break; } if (p && *p) { - if ((hs->info.units=(char *)malloc(WFDB_MAXUSL+1)) == NULL) { - wfdb_error("init: insufficient memory\n"); - return (-2); - } + SALLOC(hs->info.units, WFDB_MAXUSL+1, 1); (void)strncpy(hs->info.units, p, WFDB_MAXUSL); } else @@ -1288,10 +1149,7 @@ /* Get the signal description. If missing, a description of the form "record xx, signal n" is filled in. */ - if ((hs->info.desc = (char *)malloc(WFDB_MAXDSL+1)) == NULL) { - wfdb_error("init: insufficient memory\n"); - return (-2); - } + SALLOC(hs->info.desc, 1, WFDB_MAXDSL+1); if (p = strtok((char *)NULL, "\n\r")) (void)strncpy(hs->info.desc, p, WFDB_MAXDSL); else @@ -1308,13 +1166,12 @@ if (hsd) { while (maxhsig) if (hs = hsd[--maxhsig]) { - if (hs->info.fname) (void)free(hs->info.fname); - if (hs->info.units) (void)free(hs->info.units); - if (hs->info.desc) (void)free(hs->info.desc); - (void)free(hs); + SFREE(hs->info.fname); + SFREE(hs->info.units); + SFREE(hs->info.desc); + SFREE(hs); } - (void)free(hsd); - hsd = NULL; + SFREE(hsd); } maxhsig = 0; } @@ -1326,20 +1183,18 @@ /* if (nisig == 0) return; */ if (sbuf && !in_msrec) { - (void)free(sbuf); - sbuf = NULL; + SFREE(sbuf); sample_vflag = 0; } if (isd) { while (nisig) if (is = isd[--nisig]) { - if (is->info.fname) (void)free(is->info.fname); - if (is->info.units) (void)free(is->info.units); - if (is->info.desc) (void)free(is->info.desc); - (void)free(is); + SFREE(is->info.fname); + SFREE(is->info.units); + SFREE(is->info.desc); + SFREE(is); } - (void)free(isd); - isd = NULL; + SFREE(isd); } else nisig = 0; @@ -1349,11 +1204,10 @@ while (nigroups) if (ig = igd[--nigroups]) { if (ig->fp) (void)wfdb_fclose(ig->fp); - if (ig->buf) (void)free(ig->buf); - (void)free(ig); + SFREE(ig->buf); + SFREE(ig); } - (void)free(igd); - igd = NULL; + SFREE(igd); } else nigroups = 0; @@ -1378,13 +1232,12 @@ if (osd) { while (nosig) if (os = osd[--nosig]) { - if (os->info.fname) (void)free(os->info.fname); - if (os->info.units) (void)free(os->info.units); - if (os->info.desc) (void)free(os->info.desc); - (void)free(os); + SFREE(os->info.fname); + SFREE(os->info.units); + SFREE(os->info.desc); + SFREE(os); } - (void)free(osd); - osd = NULL; + SFREE(osd); } else nosig = 0; @@ -1407,11 +1260,10 @@ og->fp = NULL; } } - if (og->buf) (void)free(og->buf); - (void)free(og); + SFREE(og->buf); + SFREE(og); } - (void)free(ogd); - ogd = NULL; + SFREE(ogd); } else nogroups = 0; @@ -2029,9 +1881,7 @@ if ((ig->bsize = hs->info.bsize) == 0) ig->bsize = ibsize; ig->seek = 1; } - - /* Skip this group if a buffer can't be allocated. */ - if ((ig->buf = (char *)malloc(ig->bsize)) == NULL) continue; + SALLOC(ig->buf, 1, ig->bsize); /* Check that the signal file is readable. */ if (hs->info.fmt == 0) @@ -2040,8 +1890,7 @@ ig->fp = wfdb_open(hs->info.fname, (char *)NULL, WFDB_READ); /* Skip this group if the signal file can't be opened. */ if (ig->fp == NULL) { - (void)free(ig->buf); - ig->buf = NULL; + SFREE(ig->buf); continue; } } @@ -2051,10 +1900,7 @@ ig->start = hs->start; ig->stat = 1; while (si < sj && s < nsig) { - if (copysi(&is->info, &hs->info) < 0) { - wfdb_error("isigopen: insufficient memory\n"); - return (-3); - } + copysi(&is->info, &hs->info); is->info.group = nigroups + g; is->skew = hs->skew; ++s; @@ -2077,10 +1923,8 @@ maximum number of samples per signal per frame and the maximum skew. */ for (si = 0; si < s; si++) { is = isd[nisig + si]; - if (siarray != NULL && copysi(&siarray[si], &is->info) < 0) { - wfdb_error("isigopen: insufficient memory\n"); - return (-3); - } + if (siarray) + copysi(&siarray[si], &is->info); is->samp = is->info.initval; if (ispfmax < is->info.spf) ispfmax = is->info.spf; if (skewmax < is->skew) skewmax = is->skew; @@ -2098,12 +1942,9 @@ framelen += isd[si]->info.spf; /* Allocate workspace for getvec and isgsettime. */ - if (framelen > tuvlen && - ((tvector = realloc(tvector, sizeof(WFDB_Sample)*framelen)) == NULL || - (uvector = realloc(uvector, sizeof(WFDB_Sample)*framelen)) == NULL)) { - wfdb_error("isigopen: can't allocate frame buffer\n"); - if (tvector) (void)free(tvector); - return (-3); + if (framelen > tuvlen) { + SREALLOC(tvector, framelen, sizeof(WFDB_Sample)); + SREALLOC(uvector, framelen, sizeof(WFDB_Sample)); } tuvlen = framelen; @@ -2112,11 +1953,7 @@ if (skewmax != 0 && (!in_msrec || dsbuf == NULL)) { dsbi = -1; /* mark buffer contents as invalid */ dsblen = framelen * (skewmax + 1); - if (dsbuf) free(dsbuf); - if ((dsbuf=(WFDB_Sample *)malloc(dsblen*sizeof(WFDB_Sample))) == NULL) - wfdb_error("isigopen: can't allocate buffer for deskewing\n"); - /* If the buffer couldn't be allocated, the signals can still be read, - but won't be deskewed. */ + SALLOC(dsbuf, dsblen, sizeof(WFDB_Sample)); } return (s); } @@ -2163,11 +2000,8 @@ os = osd[nosig]; /* Copy signal information from readheader's workspace. */ - if (copysi(&os->info, &hsd[s]->info) < 0 || - copysi(siarray, &hsd[s]->info) < 0) { - wfdb_error("osigopen: insufficient memory\n"); - return (-3); - } + copysi(&os->info, &hsd[s]->info); + copysi(siarray, &hsd[s]->info); if (os->info.spf < 1) os->info.spf = siarray->spf = 1; os->info.cksum = siarray->cksum = 0; os->info.nsamp = siarray->nsamp = (WFDB_Time)0L; @@ -2180,11 +2014,7 @@ og = ogd[os->info.group]; og->bsize = os->info.bsize; obuflen = og->bsize ? og->bsize : obsize; - if ((og->buf = (char *)malloc(obuflen)) == NULL) { - wfdb_error("osigopen: can't allocate buffer for %s\n", - os->info.fname); - return (-3); - } + SALLOC(og->buf, 1, obuflen); og->bp = og->buf; og->be = og->buf + obuflen; if (os->info.fmt == 0) @@ -2194,8 +2024,7 @@ og->fp = wfdb_open(os->info.fname,(char *)NULL, WFDB_WRITE); if (og->fp == NULL) { wfdb_error("osigopen: can't open %s\n", os->info.fname); - free(og->buf); - og->buf = NULL; + SFREE(og->buf); osigclose(); return (-3); } @@ -2290,10 +2119,7 @@ } /* Copy signal information from the caller's array. */ - if (copysi(&os->info, siarray) < 0) { - wfdb_error("osigfopen: insufficient memory\n"); - return (-3); - } + copysi(&os->info, siarray); if (os->info.spf < 1) os->info.spf = 1; os->info.cksum = 0; os->info.nsamp = (WFDB_Time)0L; @@ -2306,11 +2132,7 @@ og->bsize = os->info.bsize; obuflen = og->bsize ? og->bsize : obsize; /* This is the first signal in a new group; allocate buffer. */ - if ((og->buf = (char *)malloc(obuflen)) == NULL) { - wfdb_error("osigfopen: can't allocate buffer for %s\n", - os->info.fname); - return (-3); - } + SALLOC(og->buf, 1,obuflen); og->bp = og->buf; og->be = og->buf + obuflen; if (os->info.fmt == 0) @@ -2320,8 +2142,7 @@ og->fp = wfdb_open(os->info.fname,(char *)NULL, WFDB_WRITE); if (og->fp == NULL) { wfdb_error("osigfopen: can't open %s\n", os->info.fname); - free(og->buf); - og->buf = NULL; + SFREE(og->buf); osigclose(); return (-3); } @@ -2406,14 +2227,8 @@ if (f > 0.0) { WFDB_Frequency error, g = sfreq; - gv0 = realloc(gv0, nisig*sizeof(WFDB_Sample)); - gv1 = realloc(gv1, nisig*sizeof(WFDB_Sample)); - if (gv0 == NULL || gv1 == NULL) { - wfdb_error("setifreq: too many (%d) input signals\n", nisig); - if (gv0) (void)free(gv0); - ifreq = 0.0; - return (-2); - } + SREALLOC(gv0, nisig, sizeof(WFDB_Sample)); + SREALLOC(gv1, nisig, sizeof(WFDB_Sample)); setafreq(ifreq = f); /* The 0.005 below is the maximum tolerable error in the resampling frequency (in Hz). The code in the while loop implements Euclid's @@ -2671,22 +2486,16 @@ /* Remove trailing .hea, if any, from record name. */ wfdb_striphea(record); - if ((osi = malloc(nosig*sizeof(WFDB_Siginfo))) == NULL) { - wfdb_error("newheader: insufficient memory\n"); - return (-1); - } + SUALLOC(osi, nosig, sizeof(WFDB_Siginfo)); for (s = 0; s < nosig; s++) - if (copysi(&osi[s], &osd[s]->info) < 0) { - wfdb_error("newheader: insufficient memory\n"); - return (-1); - } + copysi(&osi[s], &osd[s]->info); stat = setheader(record, osi, nosig); for (s = 0; s < nosig; s++) { - if (osi[s].fname) (void)free(osi[s].fname); - if (osi[s].desc) (void)free(osi[s].desc); - if (osi[s].units) (void)free(osi[s].units); + SFREE(osi[s].fname); + SFREE(osi[s].desc); + SFREE(osi[s].units); } - (void)free(osi); + SFREE(osi); return (stat); } @@ -2793,17 +2602,13 @@ return (-1); } - if ((ns = (long *)malloc((unsigned)(sizeof(long)*nsegments))) == NULL) { - wfdb_error("setmsheader: insufficient memory\n"); - return (-2); - } - + SUALLOC(ns, nsegments, (sizeof(long)*nsegments)); for (i = 0; i < nsegments; i++) { if (strlen(segment_name[i]) > WFDB_MAXRNL) { wfdb_error( "setmsheader: `%s' is too long for a segment name in record %s\n", segment_name[i], record); - (void)free(ns); + SFREE(ns); return (-2); } in_msrec = 1; @@ -2812,13 +2617,13 @@ if (n < 0) { wfdb_error("setmsheader: can't read segment %s header\n", segment_name[i]); - (void)free(ns); + SFREE(ns); return (-3); } if ((ns[i] = hsd[0]->info.nsamp) <= 0L) { wfdb_error("setmsheader: length of segment %s must be specified\n", segment_name[i]); - (void)free(ns); + SFREE(ns); return (-4); } if (i == 0) { @@ -2835,14 +2640,14 @@ wfdb_error( "setmsheader: incorrect number of signals in segment %s\n", segment_name[i]); - (void)free(ns); + SFREE(ns); return (-4); } if (msfreq != ffreq) { wfdb_error( "setmsheader: incorrect sampling frequency in segment %s\n", segment_name[i]); - (void)free(ns); + SFREE(ns); return (-4); } msnsamples += ns[i]; @@ -2853,7 +2658,7 @@ if ((oheader = wfdb_open("hea", record, WFDB_WRITE)) == NULL) { wfdb_error("setmsheader: can't create header file for record %s\n", record); - (void)free(ns); + SFREE(ns); return (-1); } @@ -2881,7 +2686,7 @@ for (i = 0; i < nsegments; i++) (void)wfdb_fprintf(oheader, "%s %ld\r\n", segment_name[i], ns[i]); - (void)free(ns); + SFREE(ns); return (0); } @@ -3313,12 +3118,8 @@ /* Allocate the sample buffer on the first call. */ if (sbuf == NULL) { - sbuf= (WFDB_Sample *)malloc((unsigned)nisig*BUFLN*sizeof(WFDB_Sample)); - if (sbuf) tt = (WFDB_Time)-1L; - else { - (void)fprintf(stderr, "sample(): insufficient memory\n"); - exit(2); - } + SALLOC(sbuf, nisig, BUFLN*sizeof(WFDB_Sample)); + tt = (WFDB_Time)-1L; } /* If the caller requested a sample from an unavailable signal, return @@ -3374,8 +3175,7 @@ void wfdb_sampquit(void) { if (sbuf) { - (void)free(sbuf); - sbuf = NULL; + SFREE(sbuf); sample_vflag = 0; } } @@ -3389,32 +3189,25 @@ pdays = (WFDB_Date)-1; segments = in_msrec = skewmax = 0; if (dsbuf) { - (void)free(dsbuf); - dsbuf = NULL; + SFREE(dsbuf); dsbi = -1; } if (segarray) { int i; - (void)free(segarray); - segarray = segp = segend = (struct segrec *)NULL; + SFREE(segarray); + segp = segend = (struct segrec *)NULL; for (i = 0; i < maxisig; i++) { - if (isd[i]->info.desc) { - (void)free(isd[i]->info.desc); - isd[i]->info.desc = NULL; - } - if (isd[i]->info.units) { - (void)free(isd[i]->info.units); - isd[i]->info.units = NULL; - } + SFREE(isd[i]->info.fname); /* missing before 10.4.6 */ + SFREE(isd[i]->info.desc); + SFREE(isd[i]->info.units); } } - if (gv0) (void)free(gv0); - if (gv1) (void)free(gv1); - if (tvector) (void)free(tvector); - if (uvector) (void)free(uvector); + SFREE(gv0); + SFREE(gv1); + SFREE(tvector); + SFREE(uvector); tuvlen = 0; - gv0 = gv1 = tvector = uvector = NULL; sigmap_cleanup(); } diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/lib/wfdb.h0 wfdb-10.4.6/lib/wfdb.h0 --- wfdb-10.4.5/lib/wfdb.h0 2008-01-11 13:03:57.000000000 -0500 +++ wfdb-10.4.6/lib/wfdb.h0 2008-02-08 10:33:17.000000000 -0500 @@ -1,5 +1,5 @@ /* file: wfdb.h G. Moody 13 June 1983 - Last revised: 11 January 2008 wfdblib 10.4.5 + Last revised: 8 February 2008 wfdblib 10.4.6 WFDB library type, constant, structure, and function interface definitions _______________________________________________________________________________ @@ -33,7 +33,7 @@ /* WFDB library version. */ #define WFDB_MAJOR 10 #define WFDB_MINOR 4 -#define WFDB_RELEASE 5 +#define WFDB_RELEASE 6 #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.4.5/lib/wfdbio.c wfdb-10.4.6/lib/wfdbio.c --- wfdb-10.4.5/lib/wfdbio.c 2008-01-11 13:52:52.000000000 -0500 +++ wfdb-10.4.6/lib/wfdbio.c 2008-04-08 16:56:36.000000000 -0400 @@ -1,5 +1,5 @@ /* file: wfdbio.c G. Moody 18 November 1988 - Last revised: 11 January 2008 wfdblib 10.4.5 + Last revised: 8 April 2008 wfdblib 10.4.6 Low-level I/O functions for the WFDB library _______________________________________________________________________________ @@ -37,9 +37,12 @@ wfdbverbose [4.0] (enables WFDB library error messages) wfdberror [4.5] (returns the most recent WFDB library error message) wfdbfile [4.3] (returns the complete pathname of a WFDB file) + wfdbmemerr [10.4.6] (set behavior on memory errors) These functions, also defined here, are intended only for the use of WFDB library functions defined elsewhere: + + wfdb_me_fatal [10.4.6] (indicates if memory errors are fatal) wfdb_g16 (reads a 16-bit integer) wfdb_g32 (reads a 32-bit integer) wfdb_p16 (writes a 16-bit integer) @@ -181,9 +184,7 @@ if (p == NULL && (p = getenv("WFDB")) == NULL) p = DEFWFDB; wfdb_parse_path(p); - if (wfdbpath) free(wfdbpath); - if (wfdbpath = (char *)malloc(strlen(p)+1)) - strcpy(wfdbpath, p); + SSTRCPY(wfdbpath, p); wfdb_export_config(); } @@ -225,8 +226,24 @@ else return (NULL); } +/* Determine how the WFDB library handles memory allocation errors (running +out of memory). Call wfdbmemerr(0) in order to have these errors returned +to the caller; by default, such errors cause the running process to exit. */ + +static int wfdb_mem_behavior = 1; + +FVOID wfdbmemerr(int behavior) +{ + wfdb_mem_behavior = behavior; +} + /* Private functions (for the use of other WFDB library functions only). */ +int wfdb_me_fatal() /* used by the MEMERR macro defined in wfdblib.h */ +{ + return (wfdb_mem_behavior); +} + /* The next four functions read and write integers in PDP-11 format, which is common to both MIT and AHA database files. The purpose is to achieve interchangeability of binary database files between machines which may use @@ -290,8 +307,8 @@ while (c1) { c0 = c1->next; - if (c1->prefix) (void)free(c1->prefix); - (void)free(c1); + SFREE(c1->prefix); + SFREE(c1); c1 = c0; } wfdb_path_list = NULL; @@ -432,12 +449,8 @@ } while (!found_end); /* current component begins at p, ends at q-1 */ - if ((c1 = calloc(1, sizeof(struct wfdb_path_component))) == NULL || - (c1->prefix = calloc(q-p+1, sizeof(char))) == NULL) { - wfdb_error("wfdb_parse_path: insufficient memory\n"); - if (c1) (void)free(c1); - return (-1); - } + SUALLOC(c1, 1, sizeof(struct wfdb_path_component)); + SALLOC(c1->prefix, q-p+1, sizeof(char)); memcpy(c1->prefix, p, q-p); c1->type = current_type; if (c0) c0->next = c1; @@ -474,13 +487,11 @@ if (fseek(wfdbpfile, 0L, SEEK_END) == 0) len = ftell(wfdbpfile); else len = 255; - if ((p = (char *)malloc((unsigned)len+1)) == NULL) p = ""; - else { - rewind(wfdbpfile); - len = fread(p, 1, (int)len, wfdbpfile); - while (p[len-1] == '\n' || p[len-1] == '\r') - p[--len] = '\0'; - } + SUALLOC(p, 1, len+1); + rewind(wfdbpfile); + len = fread(p, 1, (int)len, wfdbpfile); + while (p[len-1] == '\n' || p[len-1] == '\r') + p[--len] = '\0'; (void)fclose(wfdbpfile); } } @@ -501,28 +512,25 @@ { char *p; - if (p = (char *)malloc(strlen(wfdbpath)+6)) { - sprintf(p, "WFDB=%s", wfdbpath); - putenv(p); - free(p); - } + SUALLOC(p, 1, strlen(wfdbpath)+6); + sprintf(p, "WFDB=%s", wfdbpath); + putenv(p); if (getenv("WFDBCAL") == NULL) { - if (p = malloc(strlen(DEFWFDBCAL)+9)) { - sprintf(p, "WFDBCAL=%s", DEFWFDBCAL); - putenv(p); - free(p); - } + SALLOC(p, 1, strlen(DEFWFDBCAL)+9); + sprintf(p, "WFDBCAL=%s", DEFWFDBCAL); + putenv(p); } if (getenv("WFDBANNSORT") == NULL) { - static char p[14]; + SALLOC(p, 1, 14); sprintf(p, "WFDBANNSORT=%d", DEFWFDBANNSORT == 0 ? 0 : 1); putenv(p); } if (getenv("WFDBGVMODE") == NULL) { - static char p[13]; + SALLOC(p, 1, 13); sprintf(p, "WFDBGVMODE=%d", DEFWFDBGVMODE == 0 ? 0 : 1); putenv(p); } + SFREE(p); } #endif @@ -572,16 +580,13 @@ /* If we've come this far, the path component of s was not found in the current WFDB path; now append it. */ len = strlen(wfdbpath); /* wfdbpath set by getwfdb() -- see above */ - if ((t = (char *)malloc((unsigned)(len + i + 2))) == NULL) { - wfdb_error("wfdb_addtopath: insufficient memory\n"); - return; /* WFDB path is unchanged */ - } + SUALLOC(t, 1, len + i + 2); (void)strcpy(t, wfdbpath); t[len++] = PSEP; /* append a path separator */ (void)strncpy(t+len, s, i); /* append the new path component */ t[len+i] = '\0'; setwfdb(t); - free(t); + SFREE(t); } /* The wfdb_error function handles error messages, normally by printing them @@ -1042,16 +1047,11 @@ { char *libcurl_ver; static char *s = NULL; - if (s) { - free(s); - s = NULL; - } + libcurl_ver = curl_version(); - s = malloc(32 + strlen(libcurl_ver)); - if (s) { - sprintf(s, "libwfdb/%d.%d.%d (%s)", WFDB_MAJOR, WFDB_MINOR, + SALLOC(s, 1, 32 + strlen(libcurl_ver)); + sprintf(s, "libwfdb/%d.%d.%d (%s)", WFDB_MAJOR, WFDB_MINOR, WFDB_RELEASE, libcurl_ver); - } return (s); } @@ -1233,16 +1233,10 @@ /* Create a new, empty chunk. */ static CHUNK *curl_chunk_new(long len) { - struct chunk *c = malloc(sizeof(struct chunk)); - if (!c) { - wfdb_error("curl_chunk_new: not enough memory\n"); - return NULL; - } - if (!(c->data = malloc(len))) { - wfdb_error("curl_chunk_new: not enough memory\n"); - free(c); - return NULL; - } + struct chunk *c; + + SUALLOC(c, 1, sizeof(struct chunk)); + SALLOC(c->data, 1, len); c->size = 0L; c->buffer_size = len; return c; @@ -1252,9 +1246,8 @@ static void curl_chunk_delete(struct chunk *c) { if (c) { - if (c->data) - free(c->data); - free(c); + SFREE(c->data); + SFREE(c); } } @@ -1267,19 +1260,13 @@ { size_t count=0; char *p; - struct chunk *c = (struct chunk *) stream; + while (nmemb > 0) { while ((c->size + size) > c->buffer_size) { c->buffer_size += 1024; - if (p = realloc(c->data, c->buffer_size)) - c->data = p; - else { - wfdb_error("curl_chunk_write: insufficient memory\n"); - return (count); - } + SREALLOC(c->data, 1, c->buffer_size); } - memcpy(c->data + c->size, ptr, size); c->size += size; count += size; @@ -1475,9 +1462,9 @@ static void nf_delete(netfile *nf) { if (nf) { - if (nf->url) free(nf->url); - if (nf->data) free(nf->data); - free(nf); + SFREE(nf->url); + SFREE(nf->data); + SFREE(nf); } } @@ -1498,17 +1485,15 @@ to do this would be to invoke HTLoadToFile(url, request, filename); */ -static netfile* nf_new(const char* url) +static netfile *nf_new(const char* url) { - netfile* nf = NULL; - CHUNK* chunk = NULL; + netfile *nf; + CHUNK *chunk = NULL; long bytes_received = 0L; - nf = malloc(sizeof(netfile)); - + SUALLOC(nf, 1, sizeof(netfile)); if (nf && url && *url) { - nf->url = calloc(strlen(url) + 1, sizeof(char)); - strcpy(nf->url, url); + SSTRCPY(nf->url, url); nf->base_addr = 0; nf->pos = 0; nf->data = NULL; @@ -1535,9 +1520,10 @@ nf->mode = NF_FULL_MODE; bytes_received = nf->cont_len = chunk_size(chunk); } - if (bytes_received > 0L && - (nf->data = calloc(bytes_received, sizeof(char)))) - memcpy(nf->data, chunk_data(chunk), bytes_received); + if (bytes_received > 0L) { + SALLOC(nf->data, bytes_received, sizeof(char)); + memcpy(nf->data, chunk_data(chunk), bytes_received); + } if (nf->data == NULL) { if (bytes_received > 0L) wfdb_error("nf_new: insufficient memory (needed %ld bytes)\n", @@ -1855,19 +1841,16 @@ status = fclose(wp->fp); #endif if (wp->fp != stdin) - (void)free(wp); + SFREE(wp); return (status); } WFDB_FILE *wfdb_fopen(char *fname, const char *mode) { char *p = fname; - WFDB_FILE *wp = (WFDB_FILE *)malloc(sizeof(WFDB_FILE)); + WFDB_FILE *wp; - if (wp == NULL) { - wfdb_error("wfdb_fopen: out of memory\n"); - return (NULL); - } + SUALLOC(wp, 1, sizeof(WFDB_FILE)); while (*p) if (*p++ == ':' && *p++ == '/' && *p++ == '/') { #if WFDB_NETFILES @@ -1876,7 +1859,7 @@ return (wp); } #endif - free(wp); + SFREE(wp); return (NULL); } if (wp->fp = fopen(fname, mode)) { @@ -1909,7 +1892,7 @@ return (wp); } } - free(wp); + SFREE(wp); return (NULL); } diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/lib/wfdblib.h0 wfdb-10.4.6/lib/wfdblib.h0 --- wfdb-10.4.5/lib/wfdblib.h0 2008-01-11 13:14:01.000000000 -0500 +++ wfdb-10.4.6/lib/wfdblib.h0 2008-04-08 17:28:52.000000000 -0400 @@ -1,5 +1,5 @@ /* file: wfdblib.h G. Moody 13 April 1989 - Last revised: 11 January 2008 wfdblib 10.4.5 + Last revised: 8 April 2008 wfdblib 10.4.6 External definitions for WFDB library private functions _______________________________________________________________________________ @@ -200,6 +200,18 @@ #define FALSE 0 #endif +/* Dynamic memory allocation macros for the WFDB library. */ +#define MEMERR(P, N, S) \ + { wfdb_error("WFDB: can't allocate (%ld*%ld) bytes for %s\n", \ + (size_t)N, (size_t)S, #P); \ + if (wfdb_me_fatal()) exit(1); } +#define SFREE(P) { if (P) { free (P); P = 0; } } +#define SUALLOC(P, N, S) { if (!(P = calloc((N), (S)))) MEMERR(P, (N), (S)); } +#define SALLOC(P, N, S) { SFREE(P); SUALLOC(P, (N), (S)) } +#define SREALLOC(P, N, S) { if (!(P = realloc(P, (N)*(S)))) MEMERR(P,(N),(S)); } +#define SSTRCPY(P, Q) { if (Q) { \ + SALLOC(P, (size_t)strlen(Q)+1,1); strcpy(P, Q); } } + /* Structures used by internal WFDB library functions only */ struct netfile { char *url; diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/MANIFEST wfdb-10.4.6/MANIFEST --- wfdb-10.4.5/MANIFEST 2006-05-11 15:18:15.000000000 -0400 +++ wfdb-10.4.6/MANIFEST 2008-04-09 18:18:37.000000000 -0400 @@ -32,6 +32,8 @@ app/setwfdb app/sigamp.c app/sigavg.c +app/signame.c +app/signum.c app/skewedit.c app/snip.c app/sortann.c @@ -158,6 +160,7 @@ convert/md2a.c convert/mit2edf.c convert/mit2wav.c +convert/rdedfann.c convert/readid.c convert/README convert/revise.c @@ -303,6 +306,7 @@ doc/wag-src/pschart.1 doc/wag-src/psfd.1 doc/wag-src/rdann.1 +doc/wag-src/rdedfann.1 doc/wag-src/rdsamp.1 doc/wag-src/README doc/wag-src/rxr.1 @@ -311,6 +315,8 @@ doc/wag-src/sigamp.1 doc/wag-src/sigavg.1 doc/wag-src/signal.5 +doc/wag-src/signame.1 +doc/wag-src/signum.1 doc/wag-src/skewedit.1 doc/wag-src/snip.1 doc/wag-src/sortann.1 diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/NEWS wfdb-10.4.6/NEWS --- wfdb-10.4.5/NEWS 2008-02-06 11:57:05.000000000 -0500 +++ wfdb-10.4.6/NEWS 2008-04-09 15:49:23.000000000 -0400 @@ -1,3 +1,51 @@ +10.4.6: + The WFDB functions setafreq() and getafreq() (for setting and getting + the time resolution of newly-created output annotation files in ticks + per second) were new in version 10.4.5, but were undocumented. They + are now described in the WFDB Programmer's Guide, and wrappers for + these functions are now included in fortran/wfdbf.c. + + An important change in the WFDB library: memory allocation errors are + now treated as fatal by default (in previous versions, the functions + that encountered them returned error values that permitted the + application to handle them). These errors occur when there is + insufficient memory available to the WFDB library. After invoking + wfdbmemerr(0), if such an error occurs, the function in which it + occurs will continue if possible. By default, however, such an + error will cause the process to terminate. In either case, the WFDB + library emits an appropriate error message to aid in troubleshooting. + + New macros for handling dynamically allocated memory are defined in + lib/wfdblib.h and used throughout the WFDB library, eliminating most + known memory leaks. Three known leaks remain (in setecgstr, setannstr, + and setanndesc); these are documented and harmless in current + applications. Thanks to Yinqi Zhang for reporting a leak in copysi() + (an internal WFDB library function defined in signal.c), which prompted + the cleanup. + + WFDB functions strecg(), setecgstr(), strann(), setannstr(), and + setanndesc() now handle NULL string inputs properly. (Previous versions + passed NULL strings to strcmp(), with undesirable results.) + + A pair of new utility applications, signame and signum, convert signal + numbers to signal names and vice versa. + + A new format converter, rdedfann, is included in convert/. It extracts + annotations from EDF+ files and writes them to the standard output in + rdann output format. After changing the EDF+ annotation mnemonics + to WFDB mnemonics (using your favorite scripting language, such as + perl or sed), wrann can then write a WFDB-compatible annotation file + from the transformed text. + + wrann now works when creating annotation files for EDF and other + multifrequency records. The incompatibility between rdann's -x + format and wrann has now been noted in the rdann and wrann man pages. + + rxr did not account properly for runs that are not followed by at + least one beat annotation (common in the cudb). Shibu Kallidukkil + supplied an example that evoked this problem, which has now been + corrected. + 10.4.5: Bob Farrell and Tony Ricke chased down and provided fixes for memory leaks in several WFDB library functions, and also provided revisions diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/wave/annot.c wfdb-10.4.6/wave/annot.c --- wfdb-10.4.5/wave/annot.c 2005-06-10 10:33:55.000000000 -0400 +++ wfdb-10.4.6/wave/annot.c 2008-03-14 15:49:18.000000000 -0400 @@ -1,10 +1,10 @@ /* file: annot.c G. Moody 1 May 1990 - Last revised: 10 June 2005 + Last revised: 14 March 2008 Annotation list handling and display functions for WAVE ------------------------------------------------------------------------------- WAVE: Waveform analyzer, viewer, and editor -Copyright (C) 1990-2005 George B. Moody +Copyright (C) 1990-2008 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -152,11 +152,13 @@ tupdate = time((time_t *)NULL); /* Return 0 if no annotations are requested or available. */ + setafreq(freq); if (nann < 1 || annopen(record, &af, 1) < 0) { ap_start = annp = scope_annp = NULL; if (frame) xv_set(frame, FRAME_BUSY, FALSE, NULL); return (annotations = 0); } + setafreq(freq); if ((ap_start = annp = scope_annp = a = get_ap()) == NULL || getann(0, &(a->this))) { (void)annopen(record, NULL, 0); @@ -956,6 +958,7 @@ } af.stat = (af.stat == WFDB_AHA_READ) ? WFDB_AHA_WRITE : WFDB_WRITE; + setafreq(freq); if (annopen(record, &af, 1)) { /* An error from annopen is most likely to result from not being able to create the output file. Warn the user and try again later. */ @@ -1029,6 +1032,7 @@ } a = a->next; } + setafreq(freq); (void)annopen(record, NULL, 0); /* force flush and close of output */ changes = 0; diff -Naur --exclude Makefile --exclude info wfdb-10.4.5/wave/init.c wfdb-10.4.6/wave/init.c --- wfdb-10.4.5/wave/init.c 2005-08-05 12:02:17.000000000 -0400 +++ wfdb-10.4.6/wave/init.c 2008-03-14 14:20:30.000000000 -0400 @@ -1,10 +1,10 @@ /* file: init.c G. Moody 1 May 1990 - Last revised: 5 August 2005 + Last revised: 14 March 2008 Initialization functions for WAVE ------------------------------------------------------------------------------- WAVE: Waveform analyzer, viewer, and editor -Copyright (C) 1990-2005 George B. Moody +Copyright (C) 1990-2008 George B. Moody This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -145,6 +145,7 @@ if the value were WFDB_DEFFREQ (from wfdb.h); the units are samples per second per signal. */ if (nsig < 0 || (freq = sampfreq(NULL)) <= 0.) freq = WFDB_DEFFREQ; + setifreq(freq); /* Quit if isigopen failed. */ if (nsig < 0)