Apply re-formatting to C++ in src/ tree.
[alexxy/gromacs.git] / src / gromacs / fileio / warninp.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2004, The GROMACS development team.
6  * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
7  * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
8  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
9  * and including many others, as listed in the AUTHORS file in the
10  * top-level source directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 #include "gmxpre.h"
39
40 #include "warninp.h"
41
42 #include <cstring>
43
44 #include <string>
45
46 #include "gromacs/utility/cstringutil.h"
47 #include "gromacs/utility/fatalerror.h"
48 #include "gromacs/utility/smalloc.h"
49
50 typedef struct warninp
51 {
52     gmx_bool    bAllowWarnings;
53     int         nwarn_note;
54     int         nwarn_warn;
55     int         nwarn_error;
56     int         maxwarn;
57     int         lineno;
58     std::string filenm;
59 } t_warninp;
60
61 warninp_t init_warning(gmx_bool bAllowWarnings, int maxwarning)
62 {
63     warninp_t wi = new warninp;
64
65     wi->bAllowWarnings = bAllowWarnings;
66     wi->maxwarn        = maxwarning;
67     warning_reset(wi);
68     wi->filenm = "unknown";
69     wi->lineno = 0;
70
71     return wi;
72 }
73
74 void warning_reset(warninp_t wi)
75 {
76     wi->nwarn_note  = 0;
77     wi->nwarn_warn  = 0;
78     wi->nwarn_error = 0;
79 }
80
81 void set_warning_line(warninp_t wi, const char* s, int line)
82 {
83     if (s != nullptr)
84     {
85         wi->filenm = s;
86     }
87     wi->lineno = line;
88 }
89
90 int get_warning_line(warninp_t wi)
91 {
92     return wi->lineno;
93 }
94
95 const char* get_warning_file(warninp_t wi)
96 {
97     return wi->filenm.c_str();
98 }
99
100 static void low_warning(warninp_t wi, const char* wtype, int n, const char* s)
101 {
102 #define indent 2
103     char *temp, *temp2;
104     int   i;
105
106     if (s == nullptr)
107     {
108         s = "Empty error message.";
109     }
110     snew(temp, std::strlen(s) + indent + 1);
111     for (i = 0; i < indent; i++)
112     {
113         temp[i] = ' ';
114     }
115     temp[indent] = '\0';
116     std::strcat(temp, s);
117     temp2 = wrap_lines(temp, 78 - indent, indent, FALSE);
118     if (!wi->filenm.empty())
119     {
120         if (wi->lineno != -1)
121         {
122             fprintf(stderr, "\n%s %d [file %s, line %d]:\n%s\n\n", wtype, n, wi->filenm.c_str(), wi->lineno, temp2);
123         }
124         else
125         {
126             fprintf(stderr, "\n%s %d [file %s]:\n%s\n\n", wtype, n, wi->filenm.c_str(), temp2);
127         }
128     }
129     else
130     {
131         fprintf(stderr, "\n%s %d:\n%s\n\n", wtype, n, temp2);
132     }
133     sfree(temp);
134     sfree(temp2);
135 }
136
137 void warning(warninp_t wi, const char* s)
138 {
139     if (wi->bAllowWarnings)
140     {
141         wi->nwarn_warn++;
142         low_warning(wi, "WARNING", wi->nwarn_warn, s);
143     }
144     else
145     {
146         warning_error(wi, s);
147     }
148 }
149
150 void warning(warninp_t wi, const std::string& s)
151 {
152     warning(wi, s.c_str());
153 }
154
155 void warning_note(warninp_t wi, const char* s)
156 {
157     wi->nwarn_note++;
158     low_warning(wi, "NOTE", wi->nwarn_note, s);
159 }
160
161 void warning_note(warninp_t wi, const std::string& s)
162 {
163     warning_note(wi, s.c_str());
164 }
165
166 void warning_error(warninp_t wi, const char* s)
167 {
168     wi->nwarn_error++;
169     low_warning(wi, "ERROR", wi->nwarn_error, s);
170 }
171
172 void warning_error(warninp_t wi, const std::string& s)
173 {
174     warning_error(wi, s.c_str());
175 }
176
177 static void print_warn_count(const char* type, int n)
178 {
179     if (n > 0)
180     {
181         fprintf(stderr, "\nThere %s %d %s%s\n", (n == 1) ? "was" : "were", n, type, (n == 1) ? "" : "s");
182     }
183 }
184
185 // Note it is the caller's responsibility to ensure that exiting is correct behaviour
186 [[noreturn]] static void check_warning_error_impl(warninp_t wi, int f_errno, const char* file, int line)
187 {
188     print_warn_count("note", wi->nwarn_note);
189     print_warn_count("warning", wi->nwarn_warn);
190
191     gmx_fatal(f_errno,
192               file,
193               line,
194               "There %s %d error%s in input file(s)",
195               (wi->nwarn_error == 1) ? "was" : "were",
196               wi->nwarn_error,
197               (wi->nwarn_error == 1) ? "" : "s");
198 }
199
200 void check_warning_error(warninp_t wi, int f_errno, const char* file, int line)
201 {
202     if (wi->nwarn_error > 0)
203     {
204         check_warning_error_impl(wi, f_errno, file, line);
205     }
206 }
207
208 void warning_error_and_exit(warninp_t wi, const char* s, int f_errno, const char* file, int line)
209 {
210     warning_error(wi, s);
211     check_warning_error_impl(wi, f_errno, file, line);
212 }
213
214 void warning_error_and_exit(warninp_t wi, const std::string& s, int f_errno, const char* file, int line)
215 {
216     warning_error_and_exit(wi, s.c_str(), f_errno, file, line);
217 }
218
219 gmx_bool warning_errors_exist(warninp_t wi)
220 {
221     return (wi->nwarn_error > 0);
222 }
223
224 void done_warning(warninp_t wi, int f_errno, const char* file, int line)
225 {
226     // If we've had an error, then this will report the number of
227     // notes and warnings, and then exit.
228     check_warning_error(wi, f_errno, file, line);
229
230     // Otherwise, we report the number of notes and warnings.
231     print_warn_count("note", wi->nwarn_note);
232     print_warn_count("warning", wi->nwarn_warn);
233
234     if (wi->maxwarn >= 0 && wi->nwarn_warn > wi->maxwarn)
235     {
236         gmx_fatal(f_errno,
237                   file,
238                   line,
239                   "Too many warnings (%d).\n"
240                   "If you are sure all warnings are harmless, use the -maxwarn option.",
241                   wi->nwarn_warn);
242     }
243
244     free_warning(wi);
245 }
246
247 void free_warning(warninp_t wi)
248 {
249     delete wi;
250 }
251
252 void _too_few(warninp_t wi, const char* fn, int line)
253 {
254     char buf[STRLEN];
255
256     sprintf(buf, "Too few parameters on line (source file %s, line %d)", fn, line);
257     warning(wi, buf);
258 }
259
260 void _incorrect_n_param(warninp_t wi, const char* fn, int line)
261 {
262     char buf[STRLEN];
263
264     sprintf(buf, "Incorrect number of parameters on line (source file %s, line %d)", fn, line);
265     warning(wi, buf);
266 }