import source from 1.3.40
[external/swig.git] / Source / Swig / error.c
1 /* ----------------------------------------------------------------------------- 
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * error.c
6  *
7  * Error handling functions.   These are used to issue warnings and
8  * error messages.
9  * ----------------------------------------------------------------------------- */
10
11 char cvsroot_error_c[] = "$Id: error.c 11080 2009-01-24 13:15:51Z bhy $";
12
13 #include "swig.h"
14 #include <stdarg.h>
15 #include <ctype.h>
16
17 /* -----------------------------------------------------------------------------
18  * Commentary on the warning filter.
19  *
20  * The warning filter is a string of numbers prefaced by (-) or (+) to
21  * indicate whether or not a warning message is displayed.  For example:
22  *
23  *      "-304-201-140+210+201"
24  *
25  * The filter string is scanned left to right and the first occurrence
26  * of a warning number is used to determine printing behavior.
27  *
28  * The same number may appear more than once in the string.  For example, in the 
29  * above string, "201" appears twice.  This simply means that warning 201
30  * was disabled after it was previously enabled.  This may only be temporary
31  * setting--the first number may be removed later in which case the warning
32  * is reenabled.
33  * ----------------------------------------------------------------------------- */
34
35 #if defined(_WIN32)
36 #  define  DEFAULT_ERROR_MSG_FORMAT EMF_MICROSOFT
37 #else
38 #  define  DEFAULT_ERROR_MSG_FORMAT EMF_STANDARD
39 #endif
40 static ErrorMessageFormat msg_format = DEFAULT_ERROR_MSG_FORMAT;
41 static int silence = 0;         /* Silent operation */
42 static String *filter = 0;      /* Warning filter */
43 static int warnall = 0;
44 static int nwarning = 0;
45 static int nerrors = 0;
46
47 static int init_fmt = 0;
48 static char wrn_wnum_fmt[64];
49 static char wrn_nnum_fmt[64];
50 static char err_line_fmt[64];
51 static char err_eof_fmt[64];
52
53 static String *format_filename(const_String_or_char_ptr filename);
54
55 /* -----------------------------------------------------------------------------
56  * Swig_warning()
57  *
58  * Issue a warning message
59  * ----------------------------------------------------------------------------- */
60
61 void Swig_warning(int wnum, const_String_or_char_ptr filename, int line, const char *fmt, ...) {
62   String *out;
63   char *msg;
64   int wrn = 1;
65   va_list ap;
66   if (silence)
67     return;
68   if (!init_fmt)
69     Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
70
71   va_start(ap, fmt);
72
73   out = NewStringEmpty();
74   vPrintf(out, fmt, ap);
75
76   msg = Char(out);
77   if (isdigit((unsigned char) *msg)) {
78     unsigned long result = strtoul(msg, &msg, 10);
79     if (msg != Char(out)) {
80       msg++;
81       wnum = result;
82     }
83   }
84
85   /* Check in the warning filter */
86   if (filter) {
87     char temp[32];
88     char *c;
89     char *f = Char(filter);
90     sprintf(temp, "%d", wnum);
91     while (*f != '\0' && (c = strstr(f, temp))) {
92       if (*(c - 1) == '-') {
93         wrn = 0;                /* Warning disabled */
94         break;
95       }
96       if (*(c - 1) == '+') {
97         wrn = 1;                /* Warning enabled */
98         break;
99       }
100       f += strlen(temp);
101     }
102   }
103   if (warnall || wrn) {
104     String *formatted_filename = format_filename(filename);
105     if (wnum) {
106       Printf(stderr, wrn_wnum_fmt, formatted_filename, line, wnum);
107     } else {
108       Printf(stderr, wrn_nnum_fmt, formatted_filename, line);
109     }
110     Printf(stderr, "%s", msg);
111     nwarning++;
112     Delete(formatted_filename);
113   }
114   Delete(out);
115   va_end(ap);
116 }
117
118 /* -----------------------------------------------------------------------------
119  * Swig_error()
120  *
121  * Issue an error message
122  * ----------------------------------------------------------------------------- */
123
124 void Swig_error(const_String_or_char_ptr filename, int line, const char *fmt, ...) {
125   va_list ap;
126   String *formatted_filename = NULL;
127
128   if (silence)
129     return;
130   if (!init_fmt)
131     Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
132
133   va_start(ap, fmt);
134   formatted_filename = format_filename(filename);
135   if (line > 0) {
136     Printf(stderr, err_line_fmt, formatted_filename, line);
137   } else {
138     Printf(stderr, err_eof_fmt, formatted_filename);
139   }
140   vPrintf(stderr, fmt, ap);
141   va_end(ap);
142   nerrors++;
143   Delete(formatted_filename);
144 }
145
146 /* -----------------------------------------------------------------------------
147  * Swig_error_count()
148  *
149  * Returns number of errors received.
150  * ----------------------------------------------------------------------------- */
151
152 int Swig_error_count(void) {
153   return nerrors;
154 }
155
156 /* -----------------------------------------------------------------------------
157  * Swig_error_silent()
158  *
159  * Set silent flag
160  * ----------------------------------------------------------------------------- */
161
162 void Swig_error_silent(int s) {
163   silence = s;
164 }
165
166
167 /* -----------------------------------------------------------------------------
168  * Swig_warnfilter()
169  *
170  * Takes a comma separate list of warning numbers and puts in the filter.
171  * ----------------------------------------------------------------------------- */
172
173 void Swig_warnfilter(const_String_or_char_ptr wlist, int add) {
174   char *c;
175   char *cw;
176   String *s;
177   if (!filter)
178     filter = NewStringEmpty();
179
180   s = NewString("");
181   Clear(s);
182   cw = Char(wlist);
183   while (*cw != '\0') {
184     if (*cw != ' ') {
185       Putc(*cw, s);
186     }
187     ++cw;
188   }
189   c = Char(s);
190   c = strtok(c, ", ");
191   while (c) {
192     if (isdigit((int) *c) || (*c == '+') || (*c == '-')) {
193       /* Even if c is a digit, the rest of the string might not be, eg in the case of typemap 
194        * warnings (a bit odd really), eg: %warnfilter(SWIGWARN_TYPEMAP_CHARLEAK_MSG) */
195       if (add) {
196         Insert(filter, 0, c);
197         if (isdigit((int) *c)) {
198           Insert(filter, 0, "-");
199         }
200       } else {
201         char *temp = (char *)malloc(sizeof(char)*strlen(c) + 2);
202         if (isdigit((int) *c)) {
203           sprintf(temp, "-%s", c);
204         } else {
205           strcpy(temp, c);
206         }
207         Replace(filter, temp, "", DOH_REPLACE_FIRST);
208         free(temp);
209       }
210     }
211     c = strtok(NULL, ", ");
212   }
213   Delete(s);
214 }
215
216 void Swig_warnall(void) {
217   warnall = 1;
218 }
219
220
221 /* ----------------------------------------------------------------------------- 
222  * Swig_warn_count()
223  *
224  * Return the number of warnings
225  * ----------------------------------------------------------------------------- */
226
227 int Swig_warn_count(void) {
228   return nwarning;
229 }
230
231 /* -----------------------------------------------------------------------------
232  * Swig_error_msg_format()
233  *
234  * Set the type of error/warning message display
235  * ----------------------------------------------------------------------------- */
236
237 void Swig_error_msg_format(ErrorMessageFormat format) {
238   const char *error = "Error";
239   const char *warning = "Warning";
240
241   const char *fmt_eof = 0;
242   const char *fmt_line = 0;
243
244   /* here 'format' could be directly a string instead of an enum, but
245      by now a switch is used to translated into one. */
246   switch (format) {
247   case EMF_MICROSOFT:
248     fmt_line = "%s(%d)";
249     fmt_eof = "%s(999999)";     /* Is there a special character for EOF? Just use a large number. */
250     break;
251   case EMF_STANDARD:
252   default:
253     fmt_line = "%s:%d";
254     fmt_eof = "%s:EOF";
255   }
256
257   sprintf(wrn_wnum_fmt, "%s: %s(%%d): ", fmt_line, warning);
258   sprintf(wrn_nnum_fmt, "%s: %s: ", fmt_line, warning);
259   sprintf(err_line_fmt, "%s: %s: ", fmt_line, error);
260   sprintf(err_eof_fmt, "%s: %s: ", fmt_eof, error);
261
262   msg_format = format;
263   init_fmt = 1;
264 }
265
266 /* -----------------------------------------------------------------------------
267  * format_filename()
268  *
269  * Remove double backslashes in Windows filename paths for display
270  * ----------------------------------------------------------------------------- */
271 static String *format_filename(const_String_or_char_ptr filename) {
272   String *formatted_filename = NewString(filename);
273 #if defined(_WIN32)
274   Replaceall(formatted_filename, "\\\\", "\\");
275 #endif
276   return formatted_filename;
277 }