diff --git a/man/swarm.1 b/man/swarm.1 index 1b9c51b5..9874c8fb 100644 --- a/man/swarm.1 +++ b/man/swarm.1 @@ -1,5 +1,5 @@ .\" ============================================================================ -.TH swarm 1 "February 24, 2016" "version 2.1.6" "USER COMMANDS" +.TH swarm 1 "February 24, 2016" "version 2.1.7" "USER COMMANDS" .\" ============================================================================ .SH NAME swarm \(em find clusters of nearly-identical nucleotide amplicons @@ -279,11 +279,11 @@ Concept by Frédéric Mahé, implementation by Torbjørn Rognes. .SH CITATION Mahé F, Rognes T, Quince C, de Vargas C, Dunthorn M. (2014) Swarm: robust and fast clustering method for amplicon-based studies. -\fIPeerJ\fR 2:e593 +\fIPeerJ\fR 2:e593 .PP Mahé F, Rognes T, Quince C, de Vargas C, Dunthorn M. (2015) Swarm v2: highly-scalable and high-resolution amplicon clustering. -\fIPeerJ\fR 3:e1420 +\fIPeerJ\fR 3:e1420 .\" ============================================================================ .SH REPORTING BUGS Submit suggestions and bug-reports at @@ -296,7 +296,7 @@ Torbjørn Rognes . The software is available from .\" ============================================================================ .SH COPYRIGHT -Copyright (C) 2012, 2013, 2014, 2015, 2016 Frédéric Mahé & Torbjørn Rognes +Copyright (C) 2012-2016 Frédéric Mahé & Torbjørn Rognes .PP This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as @@ -329,10 +329,17 @@ New features and important modifications of \fBswarm\fR (short lived or minor bug releases are not mentioned): .RS .TP +.BR v2.1.7\~ "released February 24, 2016" +Version 2.1.7 fixes a bug in the output of seeds with the \-w option +when \fId\fR > 1 that was not properly fixed in version 2.1.6. It also +handles ascii character no 13 (CR) in FASTA files better. Swarm will +now exit with status 0 if the \-h or the \-v option is specified. The +help text and some error messages have been improved. +.TP .BR v2.1.6\~ "released December 14, 2015" Version 2.1.6 fixes problems with older compilers that do not have the x86intrin.h header file. It also fixes a bug in the output of seeds -with the `-w` option when \fId\fR > 1. +with the \-w option when \fId\fR > 1. .TP .BR v2.1.5\~ "released September 8, 2015" Version 2.1.5 fixes minor bugs. diff --git a/man/swarm_manual.pdf b/man/swarm_manual.pdf index 4da63529..c9d0ba47 100644 Binary files a/man/swarm_manual.pdf and b/man/swarm_manual.pdf differ diff --git a/src/Makefile b/src/Makefile index 174808f9..407ebe68 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ # SWARM # -# Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe +# Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/src/algo.cc b/src/algo.cc index 75a57008..31741924 100644 --- a/src/algo.cc +++ b/src/algo.cc @@ -1,24 +1,24 @@ /* - SWARM + SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + 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 Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway */ #include "swarm.h" @@ -515,9 +515,8 @@ void algo_run() unsigned long mass = 0; unsigned previd = amps[0].swarmid; - unsigned prevamp = amps[0].ampliconid; - unsigned seed = prevamp; - mass += db_getabundance(prevamp); + unsigned seed = amps[0].ampliconid; + mass += db_getabundance(seed); for (unsigned long i=1; i"); fprint_id_with_new_abundance(fp_seeds, seed, mass); fprintf(fp_seeds, "\n"); - db_fprintseq(fp_seeds, prevamp, 0); + db_fprintseq(fp_seeds, seed, 0); + mass = 0; seed = amps[i].ampliconid; } + mass += db_getabundance(amps[i].ampliconid); previd = id; - prevamp = amps[i].ampliconid; - mass += db_getabundance(prevamp); progress_update(i); } fprintf(fp_seeds, ">"); fprint_id_with_new_abundance(fp_seeds, seed, mass); fprintf(fp_seeds, "\n"); - db_fprintseq(fp_seeds, prevamp, 0); + db_fprintseq(fp_seeds, seed, 0); progress_done(); } diff --git a/src/algod1.cc b/src/algod1.cc index f7f4cc06..57336e92 100644 --- a/src/algod1.cc +++ b/src/algod1.cc @@ -1,30 +1,30 @@ /* - SWARM + SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + 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 Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway */ /* This version of the swarm algorithm uses Frederic's idea for d=1 to - enumerate all of the maximum 7L+4 possible variants of a sequence with only - one difference, where L is the length of the sequence. + enumerate all of the maximum 7L+4 possible variants of a sequence + with only one difference, where L is the length of the sequence. */ #include "swarm.h" diff --git a/src/arch.cc b/src/arch.cc index 3959723d..e223c926 100644 --- a/src/arch.cc +++ b/src/arch.cc @@ -1,5 +1,7 @@ /* - Copyright (C) 2014-2015 Torbjorn Rognes + SWARM + + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/bitmap.h b/src/bitmap.h index f07ed3fd..429afac7 100644 --- a/src/bitmap.h +++ b/src/bitmap.h @@ -1,5 +1,7 @@ /* - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + SWARM + + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/bloom.h b/src/bloom.h index aab69087..95c72ce9 100644 --- a/src/bloom.h +++ b/src/bloom.h @@ -1,5 +1,7 @@ /* - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + SWARM + + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/db.cc b/src/db.cc index eeee70df..56df3e5b 100644 --- a/src/db.cc +++ b/src/db.cc @@ -1,24 +1,24 @@ /* - SWARM + SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. + 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 Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . - Contact: Torbjorn Rognes , - Department of Informatics, University of Oslo, - PO Box 1080 Blindern, NO-0316 Oslo, Norway + Contact: Torbjorn Rognes , + Department of Informatics, University of Oslo, + PO Box 1080 Blindern, NO-0316 Oslo, Norway */ #include "swarm.h" @@ -215,7 +215,7 @@ void db_read(const char * filename) fatal("Illegal header line in fasta file."); long headerlen = 0; - if (char * stop = strpbrk(line+1, " \n")) + if (char * stop = strpbrk(line+1, " \r\n")) headerlen = stop - (line+1); else headerlen = strlen(line+1); @@ -278,10 +278,13 @@ void db_read(const char * filename) *(datap+datalen) = m; datalen++; } - else if (c != '\n') + else if ((c != 10) && (c != 13)) { char msg[100]; - snprintf(msg, 100, "Illegal character '%c' in sequence on line %u", c, lineno); + if ((c >= 32) && (c <= 126)) + snprintf(msg, 100, "Illegal character '%c' in sequence on line %u", c, lineno); + else + snprintf(msg, 100, "Illegal character (ascii no %d) in sequence on line %u", c, lineno); fatal(msg); } line[0] = 0; @@ -434,12 +437,10 @@ void db_read(const char * filename) { char * msg; if (asprintf(&msg, - "Abundance annotations not found for %d sequences, " - "starting on line %u.\n" - "Fasta headers must end with abundance annotations " - "(_INT or ;size=INT)\n" - "Abundance annotations can be produced by " - "dereplicating the sequences\n", + "Abundance annotations not found for %d sequences, starting on line %u.\n" + "Fasta headers must end with abundance annotations (_INT or ;size=INT).\n" + "The -z option must be used if the abundance annotation is in the latter format.\n" + "Abundance annotations can be produced by dereplicating the sequences.\n", missingabundance, missingabundance_lineno) == -1) fatal("Out of memory"); diff --git a/src/derep.cc b/src/derep.cc index 1114e278..7bfd69be 100644 --- a/src/derep.cc +++ b/src/derep.cc @@ -1,5 +1,7 @@ /* - Copyright (C) 2014-2015 Torbjorn Rognes + SWARM + + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/matrix.cc b/src/matrix.cc index 558d7141..820e90ee 100644 --- a/src/matrix.cc +++ b/src/matrix.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/nw.cc b/src/nw.cc index 1acd2eca..585e64b6 100644 --- a/src/nw.cc +++ b/src/nw.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/qgram.cc b/src/qgram.cc index ddedcffe..496b7f40 100644 --- a/src/qgram.cc +++ b/src/qgram.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2014 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/scan.cc b/src/scan.cc index ea8e1839..db15e544 100644 --- a/src/scan.cc +++ b/src/scan.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/search16.cc b/src/search16.cc index 174ba22d..0129a8e3 100644 --- a/src/search16.cc +++ b/src/search16.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2014 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/search8.cc b/src/search8.cc index 4d3f13da..e022940c 100644 --- a/src/search8.cc +++ b/src/search8.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2014 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/ssse3.cc b/src/ssse3.cc index 3c593565..03fb0df8 100644 --- a/src/ssse3.cc +++ b/src/ssse3.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2014 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/swarm.cc b/src/swarm.cc index 31ed2566..3e822f76 100644 --- a/src/swarm.cc +++ b/src/swarm.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as @@ -189,30 +189,36 @@ void args_usage() /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ fprintf(stderr, "Usage: swarm [OPTIONS] [filename]\n"); - fprintf(stderr, " -b, --boundary INTEGER min mass of large OTU for fastidious (3)\n"); - fprintf(stderr, " -c, --ceiling INTEGER max memory in MB used for fastidious\n"); - fprintf(stderr, " -d, --differences INTEGER resolution (1)\n"); - fprintf(stderr, " -f, --fastidious link nearby low-abundance swarms\n"); - fprintf(stderr, " -h, --help display this help and exit\n"); - fprintf(stderr, " -n, --no-otu-breaking never break OTUs\n"); - fprintf(stderr, " -t, --threads INTEGER number of threads to use (1)\n"); - fprintf(stderr, " -v, --version display version information and exit\n"); - fprintf(stderr, " -y, --bloom-bits INTEGER bits used per Bloom filter entry (16)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "General options:\n"); + fprintf(stderr, " -h, --help display this help and exit\n"); + fprintf(stderr, " -t, --threads INTEGER number of threads to use (1)\n"); + fprintf(stderr, " -v, --version display version information and exit\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Clustering options:\n"); + fprintf(stderr, " -b, --boundary INTEGER min mass of large OTU for fastidious (3)\n"); + fprintf(stderr, " -c, --ceiling INTEGER max memory in MB used for fastidious\n"); + fprintf(stderr, " -d, --differences INTEGER resolution (1)\n"); + fprintf(stderr, " -f, --fastidious link nearby low-abundance swarms\n"); + fprintf(stderr, " -n, --no-otu-breaking never break OTUs\n"); + fprintf(stderr, " -y, --bloom-bits INTEGER bits used per Bloom filter entry (16)\n"); + fprintf(stderr, "\n"); fprintf(stderr, "Input/output options:\n"); - fprintf(stderr, " -a, --append-abundance INTEGER value to use when abundance is missing\n"); - fprintf(stderr, " -i, --internal-structure FILENAME write internal swarm structure to file\n"); - fprintf(stderr, " -l, --log FILENAME log to file, not to stderr\n"); - fprintf(stderr, " -o, --output-file FILENAME output result filename (stdout)\n"); - fprintf(stderr, " -r, --mothur output in mothur list file format\n"); - fprintf(stderr, " -s, --statistics-file FILENAME dump swarm statistics to file\n"); - fprintf(stderr, " -u, --uclust-file FILENAME output in UCLUST-like format to file\n"); - fprintf(stderr, " -w, --seeds FILENAME write seed seqs with abundances to FASTA\n"); - fprintf(stderr, " -z, --usearch-abundance abundance annotation in usearch style\n"); + fprintf(stderr, " -a, --append-abundance INTEGER value to use when abundance is missing\n"); + fprintf(stderr, " -i, --internal-structure FILENAME write internal swarm structure to file\n"); + fprintf(stderr, " -l, --log FILENAME log to file, not to stderr\n"); + fprintf(stderr, " -o, --output-file FILENAME output result filename (stdout)\n"); + fprintf(stderr, " -r, --mothur output in mothur list file format\n"); + fprintf(stderr, " -s, --statistics-file FILENAME dump OTU statistics to file\n"); + fprintf(stderr, " -u, --uclust-file FILENAME output in UCLUST-like format to file\n"); + fprintf(stderr, " -w, --seeds FILENAME write seed seqs with abundances to FASTA\n"); + fprintf(stderr, " -z, --usearch-abundance abundance annotation in usearch style\n"); + fprintf(stderr, "\n"); fprintf(stderr, "Pairwise alignment advanced options:\n"); - fprintf(stderr, " -m, --match-reward INTEGER reward for nucleotide match (5)\n"); - fprintf(stderr, " -p, --mismatch-penalty INTEGER penalty for nucleotide mismatch (4)\n"); - fprintf(stderr, " -g, --gap-opening-penalty INTEGER gap open penalty (12)\n"); - fprintf(stderr, " -e, --gap-extension-penalty INTEGER gap extension penalty (4)\n"); + fprintf(stderr, " -m, --match-reward INTEGER reward for nucleotide match (5)\n"); + fprintf(stderr, " -p, --mismatch-penalty INTEGER penalty for nucleotide mismatch (4)\n"); + fprintf(stderr, " -g, --gap-opening-penalty INTEGER gap open penalty (12)\n"); + fprintf(stderr, " -e, --gap-extension-penalty INTEGER gap extension penalty (4)\n"); fprintf(stderr, "\n"); fprintf(stderr, "See 'man swarm' for more details.\n"); } @@ -220,13 +226,17 @@ void args_usage() void show_header() { char title[] = "Swarm " SWARM_VERSION; - char ref[] = "Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe"; + char ref[] = "Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe"; char url[] = "https://github.com/torognes/swarm"; fprintf(logfile, "%s [%s %s]\n%s\n%s\n\n", title, __DATE__, __TIME__, ref, url); - fprintf(logfile, "Please cite: Mahe F, Rognes T, Quince C, de Vargas C, Dunthorn M (2014)\n"); - fprintf(logfile, "Swarm: robust and fast clustering method for amplicon-based studies.\n"); - fprintf(logfile, "PeerJ 2:e593 https://dx.doi.org/10.7717/peerj.593\n"); + fprintf(logfile, "Mahe F, Rognes T, Quince C, de Vargas C, Dunthorn M (2014)\n"); + fprintf(logfile, "Swarm: robust and fast clustering method for amplicon-based studies\n"); + fprintf(logfile, "PeerJ 2:e593 https://doi.org/10.7717/peerj.593\n"); + fprintf(logfile, "\n"); + fprintf(logfile, "Mahe F, Rognes T, Quince C, de Vargas C, Dunthorn M (2015)\n"); + fprintf(logfile, "Swarm v2: highly-scalable and high-resolution amplicon clustering\n"); + fprintf(logfile, "PeerJ 3:e1420 https://doi.org/10.7717/peerj.1420\n"); fprintf(logfile, "\n"); } @@ -304,7 +314,7 @@ void args_init(int argc, char **argv) /* help */ show_header(); args_usage(); - exit(1); + exit(0); break; case 'o': @@ -320,7 +330,7 @@ void args_init(int argc, char **argv) case 'v': /* version */ show_header(); - exit(1); + exit(0); break; case 'm': diff --git a/src/swarm.h b/src/swarm.h index fe705d01..2137e91a 100644 --- a/src/swarm.h +++ b/src/swarm.h @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as @@ -52,7 +52,7 @@ #define LINE_MAX 2048 #endif -#define SWARM_VERSION "2.1.6" +#define SWARM_VERSION "2.1.7" #define WIDTH 32 #define WIDTH_SHIFT 5 #define BLOCKWIDTH 32 diff --git a/src/threads.h b/src/threads.h index ebae3cbd..a7d475f0 100644 --- a/src/threads.h +++ b/src/threads.h @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2015 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as diff --git a/src/util.cc b/src/util.cc index 3a2e022a..c68667c4 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1,7 +1,7 @@ /* SWARM - Copyright (C) 2012-2014 Torbjorn Rognes and Frederic Mahe + Copyright (C) 2012-2016 Torbjorn Rognes and Frederic Mahe This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as @@ -74,12 +74,13 @@ long gcd(long a, long b) void fatal(const char * msg) { - fprintf(stderr, "Error: %s\n", msg); + fprintf(stderr, "\nError: %s\n", msg); exit(1); } void fatal(const char * format, const char * message) { + fprintf(stderr, "\n"); fprintf(stderr, format, message); fprintf(stderr, "\n"); exit(1);