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 }