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
11char 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
40static ErrorMessageFormat msg_format = DEFAULT_ERROR_MSG_FORMAT;
41static int silence = 0;		/* Silent operation */
42static String *filter = 0;	/* Warning filter */
43static int warnall = 0;
44static int nwarning = 0;
45static int nerrors = 0;
46
47static int init_fmt = 0;
48static char wrn_wnum_fmt[64];
49static char wrn_nnum_fmt[64];
50static char err_line_fmt[64];
51static char err_eof_fmt[64];
52
53static String *format_filename(const_String_or_char_ptr filename);
54
55/* -----------------------------------------------------------------------------
56 * Swig_warning()
57 *
58 * Issue a warning message
59 * ----------------------------------------------------------------------------- */
60
61void 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
124void 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
152int Swig_error_count(void) {
153  return nerrors;
154}
155
156/* -----------------------------------------------------------------------------
157 * Swig_error_silent()
158 *
159 * Set silent flag
160 * ----------------------------------------------------------------------------- */
161
162void 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
173void 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
216void Swig_warnall(void) {
217  warnall = 1;
218}
219
220
221/* -----------------------------------------------------------------------------
222 * Swig_warn_count()
223 *
224 * Return the number of warnings
225 * ----------------------------------------------------------------------------- */
226
227int 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
237void 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 * ----------------------------------------------------------------------------- */
271static 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}
278