1 /* -----------------------------------------------------------------------------
2 * This file is part of SWIG, which is licensed as a whole under version 3
3 * (or any later version) of the GNU General Public License. Some additional
4 * terms also apply to certain portions of SWIG. The full details of the SWIG
5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
6 * included with the SWIG source code as distributed by the SWIG developers
7 * and at http://www.swig.org/legal.html.
8 *
9 * error.c
10 *
11 * Error handling functions. These are used to issue warnings and
12 * error messages.
13 * ----------------------------------------------------------------------------- */
14
15 #include "swig.h"
16 #include <stdarg.h>
17 #include <ctype.h>
18
19 /* -----------------------------------------------------------------------------
20 * Commentary on the warning filter.
21 *
22 * The warning filter is a string of numbers prefaced by (-) or (+) to
23 * indicate whether or not a warning message is displayed. For example:
24 *
25 * "-304-201-140+210+201"
26 *
27 * The filter string is scanned left to right and the first occurrence
28 * of a warning number is used to determine printing behavior.
29 *
30 * The same number may appear more than once in the string. For example, in the
31 * above string, "201" appears twice. This simply means that warning 201
32 * was disabled after it was previously enabled. This may only be temporary
33 * setting--the first number may be removed later in which case the warning
34 * is reenabled.
35 * ----------------------------------------------------------------------------- */
36
37 #if defined(_WIN32)
38 # define DEFAULT_ERROR_MSG_FORMAT EMF_MICROSOFT
39 #else
40 # define DEFAULT_ERROR_MSG_FORMAT EMF_STANDARD
41 #endif
42 static ErrorMessageFormat msg_format = DEFAULT_ERROR_MSG_FORMAT;
43 static int silence = 0; /* Silent operation */
44 static String *filter = 0; /* Warning filter */
45 static int warnall = 0;
46 static int nwarning = 0;
47 static int nerrors = 0;
48
49 static int init_fmt = 0;
50 static char wrn_wnum_fmt[64];
51 static char wrn_nnum_fmt[64];
52 static char err_line_fmt[64];
53 static char err_eof_fmt[64];
54 static char diag_line_fmt[64];
55 static char diag_eof_fmt[64];
56
57 static String *format_filename(const_String_or_char_ptr filename);
58
59 /* -----------------------------------------------------------------------------
60 * Swig_warning()
61 *
62 * Issue a warning message on stderr.
63 * ----------------------------------------------------------------------------- */
64
Swig_warning(int wnum,const_String_or_char_ptr filename,int line,const char * fmt,...)65 void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const char *fmt, ...) {
66 String *out;
67 char *msg;
68 int wrn = 1;
69 va_list ap;
70 if (silence)
71 return;
72 if (!init_fmt)
73 Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
74
75 va_start(ap, fmt);
76
77 out = NewStringEmpty();
78 vPrintf(out, fmt, ap);
79
80 msg = Char(out);
81 if (isdigit((unsigned char) *msg)) {
82 unsigned long result = strtoul(msg, &msg, 10);
83 if (msg != Char(out)) {
84 msg++;
85 wnum = result;
86 }
87 }
88
89 /* Check in the warning filter */
90 if (filter) {
91 char temp[32];
92 char *c;
93 char *f = Char(filter);
94 sprintf(temp, "%d", wnum);
95 while (*f != '\0' && (c = strstr(f, temp))) {
96 if (*(c - 1) == '-') {
97 wrn = 0; /* Warning disabled */
98 break;
99 }
100 if (*(c - 1) == '+') {
101 wrn = 1; /* Warning enabled */
102 break;
103 }
104 f += strlen(temp);
105 }
106 }
107 if (warnall || wrn) {
108 String *formatted_filename = format_filename(filename);
109 String *full_message = NewString("");
110 if (wnum) {
111 Printf(full_message, wrn_wnum_fmt, formatted_filename, line, wnum);
112 } else {
113 Printf(full_message, wrn_nnum_fmt, formatted_filename, line);
114 }
115 Printf(full_message, "%s", msg);
116 Printv(stderr, full_message, NIL);
117 nwarning++;
118 Delete(full_message);
119 Delete(formatted_filename);
120 }
121 Delete(out);
122 va_end(ap);
123 }
124
125 /* -----------------------------------------------------------------------------
126 * Swig_error()
127 *
128 * Issue an error message on stderr.
129 * ----------------------------------------------------------------------------- */
130
Swig_error(const_String_or_char_ptr filename,int line,const char * fmt,...)131 void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
132 va_list ap;
133 String *formatted_filename = NULL;
134 String *full_message = NULL;
135
136 if (silence)
137 return;
138 if (!init_fmt)
139 Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
140
141 va_start(ap, fmt);
142 formatted_filename = format_filename(filename);
143 full_message = NewString("");
144 if (line > 0) {
145 Printf(full_message, err_line_fmt, formatted_filename, line);
146 } else {
147 Printf(full_message, err_eof_fmt, formatted_filename);
148 }
149 vPrintf(full_message, fmt, ap);
150 Printv(stderr, full_message, NIL);
151 va_end(ap);
152 nerrors++;
153 Delete(full_message);
154 Delete(formatted_filename);
155 }
156
157 /* -----------------------------------------------------------------------------
158 * Swig_error_count()
159 *
160 * Returns number of errors received.
161 * ----------------------------------------------------------------------------- */
162
Swig_error_count(void)163 int Swig_error_count(void) {
164 return nerrors;
165 }
166
167 /* -----------------------------------------------------------------------------
168 * Swig_error_silent()
169 *
170 * Set silent flag
171 * ----------------------------------------------------------------------------- */
172
Swig_error_silent(int s)173 void Swig_error_silent(int s) {
174 silence = s;
175 }
176
177
178 /* -----------------------------------------------------------------------------
179 * Swig_warnfilter()
180 *
181 * Takes a comma separate list of warning numbers and puts in the filter.
182 * ----------------------------------------------------------------------------- */
183
Swig_warnfilter(const_String_or_char_ptr wlist,int add)184 void Swig_warnfilter(const_String_or_char_ptr wlist, int add) {
185 char *c;
186 char *cw;
187 String *s;
188 if (!filter)
189 filter = NewStringEmpty();
190
191 s = NewString("");
192 Clear(s);
193 cw = Char(wlist);
194 while (*cw != '\0') {
195 if (*cw != ' ') {
196 Putc(*cw, s);
197 }
198 ++cw;
199 }
200 c = Char(s);
201 c = strtok(c, ", ");
202 while (c) {
203 if (isdigit((int) *c) || (*c == '+') || (*c == '-')) {
204 /* Even if c is a digit, the rest of the string might not be, eg in the case of typemap
205 * warnings (a bit odd really), eg: %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK_MSG) */
206 if (add) {
207 Insert(filter, 0, c);
208 if (isdigit((int) *c)) {
209 Insert(filter, 0, "-");
210 }
211 } else {
212 char *temp = (char *)malloc(sizeof(char)*strlen(c) + 2);
213 if (isdigit((int) *c)) {
214 sprintf(temp, "-%s", c);
215 } else {
216 strcpy(temp, c);
217 }
218 Replace(filter, temp, "", DOH_REPLACE_FIRST);
219 free(temp);
220 }
221 }
222 c = strtok(NULL, ", ");
223 }
224 Delete(s);
225 }
226
Swig_warnall(void)227 void Swig_warnall(void) {
228 warnall = 1;
229 }
230
231
232 /* -----------------------------------------------------------------------------
233 * Swig_warn_count()
234 *
235 * Return the number of warnings
236 * ----------------------------------------------------------------------------- */
237
Swig_warn_count(void)238 int Swig_warn_count(void) {
239 return nwarning;
240 }
241
242 /* -----------------------------------------------------------------------------
243 * Swig_error_msg_format()
244 *
245 * Set the type of error/warning message display
246 * ----------------------------------------------------------------------------- */
247
Swig_error_msg_format(ErrorMessageFormat format)248 void Swig_error_msg_format(ErrorMessageFormat format) {
249 const char *error = "Error";
250 const char *warning = "Warning";
251
252 const char *fmt_eof = 0;
253 const char *fmt_line = 0;
254
255 /* here 'format' could be directly a string instead of an enum, but
256 by now a switch is used to translated into one. */
257 switch (format) {
258 case EMF_MICROSOFT:
259 fmt_line = "%s(%d) ";
260 fmt_eof = "%s(999999) "; /* Is there a special character for EOF? Just use a large number. */
261 break;
262 case EMF_STANDARD:
263 default:
264 fmt_line = "%s:%d";
265 fmt_eof = "%s:EOF";
266 }
267
268 sprintf(wrn_wnum_fmt, "%s: %s %%d: ", fmt_line, warning);
269 sprintf(wrn_nnum_fmt, "%s: %s: ", fmt_line, warning);
270 sprintf(err_line_fmt, "%s: %s: ", fmt_line, error);
271 sprintf(err_eof_fmt, "%s: %s: ", fmt_eof, error);
272 sprintf(diag_line_fmt, "%s: ", fmt_line);
273 sprintf(diag_eof_fmt, "%s: ", fmt_eof);
274
275 msg_format = format;
276 init_fmt = 1;
277 }
278
279 /* -----------------------------------------------------------------------------
280 * format_filename()
281 *
282 * Remove double backslashes in Windows filename paths for display
283 * ----------------------------------------------------------------------------- */
format_filename(const_String_or_char_ptr filename)284 static String *format_filename(const_String_or_char_ptr filename) {
285 String *formatted_filename = NewString(filename);
286 #if defined(_WIN32)
287 Replaceall(formatted_filename, "\\\\", "\\");
288 #endif
289 return formatted_filename;
290 }
291
292 /* -----------------------------------------------------------------------------
293 * Swig_stringify_with_location()
294 *
295 * Return a string representation of any DOH object with line and file location
296 * information in the appropriate error message format. The string representation
297 * is enclosed within [] brackets after the line and file information.
298 * ----------------------------------------------------------------------------- */
299
Swig_stringify_with_location(DOH * object)300 String *Swig_stringify_with_location(DOH *object) {
301 String *str = NewStringEmpty();
302
303 if (!init_fmt)
304 Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
305
306 if (object) {
307 int line = Getline(object);
308 String *formatted_filename = format_filename(Getfile(object));
309 if (line > 0) {
310 Printf(str, diag_line_fmt, formatted_filename, line);
311 } else {
312 Printf(str, diag_eof_fmt, formatted_filename);
313 }
314 if (Len(object) == 0) {
315 Printf(str, "[EMPTY]");
316 } else {
317 Printf(str, "[%s]", object);
318 }
319 Delete(formatted_filename);
320 } else {
321 Printf(str, "[NULL]");
322 }
323
324 return str;
325 }
326
327 /* -----------------------------------------------------------------------------
328 * Swig_diagnostic()
329 *
330 * Issue a diagnostic message on stdout.
331 * ----------------------------------------------------------------------------- */
332
Swig_diagnostic(const_String_or_char_ptr filename,int line,const char * fmt,...)333 void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
334 va_list ap;
335 String *formatted_filename = NULL;
336
337 if (!init_fmt)
338 Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
339
340 va_start(ap, fmt);
341 formatted_filename = format_filename(filename);
342 if (line > 0) {
343 Printf(stdout, diag_line_fmt, formatted_filename, line);
344 } else {
345 Printf(stdout, diag_eof_fmt, formatted_filename);
346 }
347 vPrintf(stdout, fmt, ap);
348 va_end(ap);
349 Delete(formatted_filename);
350 }
351
352