SphinxBase  5prealpha
err.c
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* ====================================================================
3  * Copyright (c) 1999-2004 Carnegie Mellon University. All rights
4  * reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * This work was supported in part by funding from the Defense Advanced
19  * Research Projects Agency and the National Science Foundation of the
20  * United States of America, and the CMU Sphinx Speech Consortium.
21  *
22  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND
23  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
26  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * ====================================================================
35  *
36  */
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <stdarg.h>
49 #include <string.h>
50 #include <errno.h>
51 
52 #include "sphinxbase/err.h"
53 #include "sphinxbase/prim_type.h"
54 #include "sphinxbase/filename.h"
55 #include "sphinxbase/ckd_alloc.h"
56 
57 static FILE* logfp = NULL;
58 static int logfp_disabled = FALSE;
59 
60 static int sphinx_debug_level;
61 
62 #if defined(__ANDROID__)
63 #include <android/log.h>
64 static void
65 err_logcat_cb(void* user_data, err_lvl_t level, const char *fmt, ...);
66 #elif defined(_WIN32_WCE)
67 #include <windows.h>
68 #define vsnprintf _vsnprintf
69 static void
70 err_wince_cb(void* user_data, err_lvl_t level, const char *fmt, ...);
71 #endif
72 
73 #if defined(__ANDROID__)
74 static err_cb_f err_cb = err_logcat_cb;
75 #elif defined(_WIN32_WCE)
76 static err_cb_f err_cb = err_wince_cb;
77 #else
78 static err_cb_f err_cb = err_logfp_cb;
79 #endif
80 static void* err_user_data;
81 
82 void
83 err_msg(err_lvl_t lvl, const char *path, long ln, const char *fmt, ...)
84 {
85  static const char *err_prefix[ERR_MAX] = {
86  "DEBUG", "INFO", "INFOCONT", "WARN", "ERROR", "FATAL"
87  };
88 
89  char msg[1024];
90  va_list ap;
91 
92  if (!err_cb)
93  return;
94 
95  va_start(ap, fmt);
96  vsnprintf(msg, sizeof(msg), fmt, ap);
97  va_end(ap);
98 
99  if (path) {
100  const char *fname = path2basename(path);
101  if (lvl == ERR_INFOCONT)
102  err_cb(err_user_data, lvl, "%s(%ld): %s", fname, ln, msg);
103  else if (lvl == ERR_INFO)
104  err_cb(err_user_data, lvl, "%s: %s(%ld): %s", err_prefix[lvl], fname, ln, msg);
105  else
106  err_cb(err_user_data, lvl, "%s: \"%s\", line %ld: %s", err_prefix[lvl], fname, ln, msg);
107  } else {
108  err_cb(err_user_data, lvl, "%s", msg);
109  }
110 }
111 
112 #ifdef _WIN32_WCE /* No strerror for WinCE, so a separate implementation */
113 void
114 err_msg_system(err_lvl_t lvl, const char *path, long ln, const char *fmt, ...)
115 {
116  static const char *err_prefix[ERR_MAX] = {
117  "DEBUG", "INFO", "INFOCONT", "WARN", "ERROR", "FATAL"
118  };
119 
120  va_list ap;
121  LPVOID error_wstring;
122  DWORD error;
123  char msg[1024];
124  char error_string[1024];
125 
126  if (!err_cb)
127  return;
128 
129  error = GetLastError();
130  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
131  FORMAT_MESSAGE_FROM_SYSTEM |
132  FORMAT_MESSAGE_IGNORE_INSERTS,
133  NULL,
134  error,
135  0, // Default language
136  (LPTSTR) &error_wstring,
137  0,
138  NULL);
139  wcstombs(error_string, error_wstring, 1023);
140  LocalFree(error_wstring);
141 
142  va_start(ap, fmt);
143  vsnprintf(msg, sizeof(msg), fmt, ap);
144  va_end(ap);
145 
146  if (path) {
147  const char *fname = path2basename(path);
148  if (lvl == ERR_INFOCONT)
149  err_cb(err_user_data, lvl, "%s(%ld): %s: %s\n", fname, ln, msg, error_string);
150  else if (lvl == ERR_INFO)
151  err_cb(err_user_data, lvl, "%s: %s(%ld): %s: %s\n", err_prefix[lvl], fname, ln, msg, error_string);
152  else
153  err_cb(err_user_data, lvl, "%s: \"%s\", line %ld: %s: %s\n", err_prefix[lvl], fname, ln, msg, error_string);
154  } else {
155  err_cb(err_user_data, lvl, "%s: %s\n", msg, error_string);
156  }
157 }
158 #else
159 void
160 err_msg_system(err_lvl_t lvl, const char *path, long ln, const char *fmt, ...)
161 {
162  int local_errno = errno;
163 
164  static const char *err_prefix[ERR_MAX] = {
165  "DEBUG", "INFO", "INFOCONT", "WARN", "ERROR", "FATAL"
166  };
167 
168  char msg[1024];
169  va_list ap;
170 
171  if (!err_cb)
172  return;
173 
174  va_start(ap, fmt);
175  vsnprintf(msg, sizeof(msg), fmt, ap);
176  va_end(ap);
177 
178  if (path) {
179  const char *fname = path2basename(path);
180  if (lvl == ERR_INFOCONT)
181  err_cb(err_user_data, lvl, "%s(%ld): %s: %s\n", fname, ln, msg, strerror(local_errno));
182  else if (lvl == ERR_INFO)
183  err_cb(err_user_data, lvl, "%s: %s(%ld): %s: %s\n", err_prefix[lvl], fname, ln, msg, strerror(local_errno));
184  else
185  err_cb(err_user_data, lvl, "%s: \"%s\", line %ld: %s: %s\n", err_prefix[lvl], fname, ln, msg, strerror(local_errno));
186  } else {
187  err_cb(err_user_data, lvl, "%s: %s\n", msg, strerror(local_errno));
188  }
189 }
190 #endif
191 
192 #if defined(__ANDROID__)
193 static void
194 err_logcat_cb(void *user_data, err_lvl_t lvl, const char *fmt, ...)
195 {
196  static const int android_level[ERR_MAX] = {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO,
197  ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_ERROR};
198 
199  va_list ap;
200  va_start(ap, fmt);
201  __android_log_vprint(android_level[lvl], "cmusphinx", fmt, ap);
202  va_end(ap);
203 }
204 #elif defined(_WIN32_WCE)
205 static void
206 err_wince_cb(void *user_data, err_lvl_t lvl, const char *fmt, ...)
207 {
208  char msg[1024];
209  WCHAR *wmsg;
210  size_t size;
211  va_list ap;
212 
213  va_start(ap, fmt);
214  _vsnprintf(msg, sizeof(msg), fmt, ap);
215  va_end(ap);
216 
217  size = mbstowcs(NULL, msg, 0) + 1;
218  wmsg = ckd_calloc(size, sizeof(*wmsg));
219  mbstowcs(wmsg, msg, size);
220 
221  OutputDebugStringW(wmsg);
222  ckd_free(wmsg);
223 }
224 #else
225 void
226 err_logfp_cb(void *user_data, err_lvl_t lvl, const char *fmt, ...)
227 {
228  va_list ap;
229  FILE *fp = err_get_logfp();
230 
231  if (!fp)
232  return;
233 
234  va_start(ap, fmt);
235  vfprintf(fp, fmt, ap);
236  va_end(ap);
237 }
238 #endif
239 
240 int
241 err_set_logfile(const char *path)
242 {
243  FILE *newfp, *oldfp;
244 
245  if ((newfp = fopen(path, "a")) == NULL)
246  return -1;
247  oldfp = err_get_logfp();
248  err_set_logfp(newfp);
249  if (oldfp != NULL && oldfp != stdout && oldfp != stderr)
250  fclose(oldfp);
251  return 0;
252 }
253 
254 void
255 err_set_logfp(FILE *stream)
256 {
257  if (stream == NULL) {
258  logfp_disabled = TRUE;
259  logfp = NULL;
260  return;
261  }
262  logfp_disabled = FALSE;
263  logfp = stream;
264  return;
265 }
266 
267 FILE *
269 {
270  if (logfp_disabled)
271  return NULL;
272  if (logfp == NULL)
273  return stderr;
274 
275  return logfp;
276 }
277 
278 int
280 {
281  int prev = sphinx_debug_level;
282  sphinx_debug_level = level;
283  return prev;
284 }
285 
286 int
288 {
289  return sphinx_debug_level;
290 }
291 
292 void
293 err_set_callback(err_cb_f cb, void* user_data)
294 {
295  err_cb = cb;
296  err_user_data= user_data;
297 }
SPHINXBASE_EXPORT const char * path2basename(const char *path)
Returns the last part of the path, without modifying anything in memory.
Definition: filename.c:53
SPHINXBASE_EXPORT void err_set_logfp(FILE *stream)
Direct all logging to a given filehandle if default logfp callback is set.
Definition: err.c:255
#define ckd_calloc(n, sz)
Macros to simplify the use of above functions.
Definition: ckd_alloc.h:248
SPHINXBASE_EXPORT FILE * err_get_logfp(void)
Get the current logging filehandle.
Definition: err.c:268
SPHINXBASE_EXPORT int err_set_debug_level(int level)
Set debugging verbosity level.
Definition: err.c:279
SPHINXBASE_EXPORT void err_set_callback(err_cb_f callback, void *user_data)
Sets function to output error messages.
Definition: err.c:293
Sphinx&#39;s memory allocation/deallocation routines.
SPHINXBASE_EXPORT int err_get_debug_level(void)
Get debugging verbosity level.
Definition: err.c:287
File names related operation.
Basic type definitions used in Sphinx.
SPHINXBASE_EXPORT void ckd_free(void *ptr)
Test and free a 1-D array.
Definition: ckd_alloc.c:244
Implementation of logging routines.
SPHINXBASE_EXPORT int err_set_logfile(const char *path)
Append all log messages to a given file.
Definition: err.c:241