1 |
/* |
2 |
* jerror.c |
3 |
* |
4 |
* Copyright (C) 1991-1998, Thomas G. Lane. |
5 |
* This file is part of the Independent JPEG Group's software. |
6 |
* For conditions of distribution and use, see the accompanying README file. |
7 |
* |
8 |
* This file contains simple error-reporting and trace-message routines. |
9 |
* These are suitable for Unix-like systems and others where writing to |
10 |
* stderr is the right thing to do. Many applications will want to replace |
11 |
* some or all of these routines. |
12 |
* |
13 |
* If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile, |
14 |
* you get a Windows-specific hack to display error messages in a dialog box. |
15 |
* It ain't much, but it beats dropping error messages into the bit bucket, |
16 |
* which is what happens to output to stderr under most Windows C compilers. |
17 |
* |
18 |
* These routines are used by both the compression and decompression code. |
19 |
*/ |
20 |
|
21 |
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ |
22 |
#include "jinclude.h" |
23 |
#include "jpeglib.h" |
24 |
#include "jversion.h" |
25 |
#include "jerror.h" |
26 |
|
27 |
#ifdef USE_WINDOWS_MESSAGEBOX |
28 |
#include <windows.h> |
29 |
#endif |
30 |
|
31 |
#ifndef EXIT_FAILURE /* define exit() codes if not provided */ |
32 |
#define EXIT_FAILURE 1 |
33 |
#endif |
34 |
|
35 |
|
36 |
/* |
37 |
* Create the message string table. |
38 |
* We do this from the master message list in jerror.h by re-reading |
39 |
* jerror.h with a suitable definition for macro JMESSAGE. |
40 |
* The message table is made an external symbol just in case any applications |
41 |
* want to refer to it directly. |
42 |
*/ |
43 |
|
44 |
#ifdef NEED_SHORT_EXTERNAL_NAMES |
45 |
#define jpeg_std_message_table jMsgTable |
46 |
#endif |
47 |
|
48 |
#define JMESSAGE(code,string) string , |
49 |
|
50 |
const char * const jpeg_std_message_table[] = { |
51 |
#include "jerror.h" |
52 |
NULL |
53 |
}; |
54 |
|
55 |
|
56 |
/* |
57 |
* Error exit handler: must not return to caller. |
58 |
* |
59 |
* Applications may override this if they want to get control back after |
60 |
* an error. Typically one would longjmp somewhere instead of exiting. |
61 |
* The setjmp buffer can be made a private field within an expanded error |
62 |
* handler object. Note that the info needed to generate an error message |
63 |
* is stored in the error object, so you can generate the message now or |
64 |
* later, at your convenience. |
65 |
* You should make sure that the JPEG object is cleaned up (with jpeg_abort |
66 |
* or jpeg_destroy) at some point. |
67 |
*/ |
68 |
|
69 |
METHODDEF(void) |
70 |
error_exit (j_common_ptr cinfo) |
71 |
{ |
72 |
/* Always display the message */ |
73 |
(*cinfo->err->output_message) (cinfo); |
74 |
|
75 |
/* Let the memory manager delete any temp files before we die */ |
76 |
jpeg_destroy(cinfo); |
77 |
|
78 |
exit(EXIT_FAILURE); |
79 |
} |
80 |
|
81 |
|
82 |
/* |
83 |
* Actual output of an error or trace message. |
84 |
* Applications may override this method to send JPEG messages somewhere |
85 |
* other than stderr. |
86 |
* |
87 |
* On Windows, printing to stderr is generally completely useless, |
88 |
* so we provide optional code to produce an error-dialog popup. |
89 |
* Most Windows applications will still prefer to override this routine, |
90 |
* but if they don't, it'll do something at least marginally useful. |
91 |
* |
92 |
* NOTE: to use the library in an environment that doesn't support the |
93 |
* C stdio library, you may have to delete the call to fprintf() entirely, |
94 |
* not just not use this routine. |
95 |
*/ |
96 |
|
97 |
METHODDEF(void) |
98 |
output_message (j_common_ptr cinfo) |
99 |
{ |
100 |
char buffer[JMSG_LENGTH_MAX]; |
101 |
|
102 |
/* Create the message */ |
103 |
(*cinfo->err->format_message) (cinfo, buffer); |
104 |
|
105 |
#ifdef USE_WINDOWS_MESSAGEBOX |
106 |
/* Display it in a message dialog box */ |
107 |
MessageBox(GetActiveWindow(), buffer, "JPEG Library Error", |
108 |
MB_OK | MB_ICONERROR); |
109 |
#else |
110 |
/* Send it to stderr, adding a newline */ |
111 |
fprintf(stderr, "%s\n", buffer); |
112 |
#endif |
113 |
} |
114 |
|
115 |
|
116 |
/* |
117 |
* Decide whether to emit a trace or warning message. |
118 |
* msg_level is one of: |
119 |
* -1: recoverable corrupt-data warning, may want to abort. |
120 |
* 0: important advisory messages (always display to user). |
121 |
* 1: first level of tracing detail. |
122 |
* 2,3,...: successively more detailed tracing messages. |
123 |
* An application might override this method if it wanted to abort on warnings |
124 |
* or change the policy about which messages to display. |
125 |
*/ |
126 |
|
127 |
METHODDEF(void) |
128 |
emit_message (j_common_ptr cinfo, int msg_level) |
129 |
{ |
130 |
struct jpeg_error_mgr * err = cinfo->err; |
131 |
|
132 |
if (msg_level < 0) { |
133 |
/* It's a warning message. Since corrupt files may generate many warnings, |
134 |
* the policy implemented here is to show only the first warning, |
135 |
* unless trace_level >= 3. |
136 |
*/ |
137 |
if (err->num_warnings == 0 || err->trace_level >= 3) |
138 |
(*err->output_message) (cinfo); |
139 |
/* Always count warnings in num_warnings. */ |
140 |
err->num_warnings++; |
141 |
} else { |
142 |
/* It's a trace message. Show it if trace_level >= msg_level. */ |
143 |
if (err->trace_level >= msg_level) |
144 |
(*err->output_message) (cinfo); |
145 |
} |
146 |
} |
147 |
|
148 |
|
149 |
/* |
150 |
* Format a message string for the most recent JPEG error or message. |
151 |
* The message is stored into buffer, which should be at least JMSG_LENGTH_MAX |
152 |
* characters. Note that no '\n' character is added to the string. |
153 |
* Few applications should need to override this method. |
154 |
*/ |
155 |
|
156 |
METHODDEF(void) |
157 |
format_message (j_common_ptr cinfo, char * buffer) |
158 |
{ |
159 |
struct jpeg_error_mgr * err = cinfo->err; |
160 |
int msg_code = err->msg_code; |
161 |
const char * msgtext = NULL; |
162 |
const char * msgptr; |
163 |
char ch; |
164 |
boolean isstring; |
165 |
|
166 |
/* Look up message string in proper table */ |
167 |
if (msg_code > 0 && msg_code <= err->last_jpeg_message) { |
168 |
msgtext = err->jpeg_message_table[msg_code]; |
169 |
} else if (err->addon_message_table != NULL && |
170 |
msg_code >= err->first_addon_message && |
171 |
msg_code <= err->last_addon_message) { |
172 |
msgtext = err->addon_message_table[msg_code - err->first_addon_message]; |
173 |
} |
174 |
|
175 |
/* Defend against bogus message number */ |
176 |
if (msgtext == NULL) { |
177 |
err->msg_parm.i[0] = msg_code; |
178 |
msgtext = err->jpeg_message_table[0]; |
179 |
} |
180 |
|
181 |
/* Check for string parameter, as indicated by %s in the message text */ |
182 |
isstring = FALSE; |
183 |
msgptr = msgtext; |
184 |
while ((ch = *msgptr++) != '\0') { |
185 |
if (ch == '%') { |
186 |
if (*msgptr == 's') isstring = TRUE; |
187 |
break; |
188 |
} |
189 |
} |
190 |
|
191 |
/* Format the message into the passed buffer */ |
192 |
if (isstring) |
193 |
sprintf(buffer, msgtext, err->msg_parm.s); |
194 |
else |
195 |
sprintf(buffer, msgtext, |
196 |
err->msg_parm.i[0], err->msg_parm.i[1], |
197 |
err->msg_parm.i[2], err->msg_parm.i[3], |
198 |
err->msg_parm.i[4], err->msg_parm.i[5], |
199 |
err->msg_parm.i[6], err->msg_parm.i[7]); |
200 |
} |
201 |
|
202 |
|
203 |
/* |
204 |
* Reset error state variables at start of a new image. |
205 |
* This is called during compression startup to reset trace/error |
206 |
* processing to default state, without losing any application-specific |
207 |
* method pointers. An application might possibly want to override |
208 |
* this method if it has additional error processing state. |
209 |
*/ |
210 |
|
211 |
METHODDEF(void) |
212 |
reset_error_mgr (j_common_ptr cinfo) |
213 |
{ |
214 |
cinfo->err->num_warnings = 0; |
215 |
/* trace_level is not reset since it is an application-supplied parameter */ |
216 |
cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ |
217 |
} |
218 |
|
219 |
|
220 |
/* |
221 |
* Fill in the standard error-handling methods in a jpeg_error_mgr object. |
222 |
* Typical call is: |
223 |
* struct jpeg_compress_struct cinfo; |
224 |
* struct jpeg_error_mgr err; |
225 |
* |
226 |
* cinfo.err = jpeg_std_error(&err); |
227 |
* after which the application may override some of the methods. |
228 |
*/ |
229 |
|
230 |
GLOBAL(struct jpeg_error_mgr *) |
231 |
jpeg_std_error (struct jpeg_error_mgr * err) |
232 |
{ |
233 |
err->error_exit = error_exit; |
234 |
err->emit_message = emit_message; |
235 |
err->output_message = output_message; |
236 |
err->format_message = format_message; |
237 |
err->reset_error_mgr = reset_error_mgr; |
238 |
|
239 |
err->trace_level = 0; /* default = no tracing */ |
240 |
err->num_warnings = 0; /* no warnings emitted yet */ |
241 |
err->msg_code = 0; /* may be useful as a flag for "no error" */ |
242 |
|
243 |
/* Initialize message table pointers */ |
244 |
err->jpeg_message_table = jpeg_std_message_table; |
245 |
err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; |
246 |
|
247 |
err->addon_message_table = NULL; |
248 |
err->first_addon_message = 0; /* for safety */ |
249 |
err->last_addon_message = 0; |
250 |
|
251 |
return err; |
252 |
} |