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