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