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