diff options
Diffstat (limited to 'jerror.c')
-rw-r--r-- | jerror.c | 214 |
1 files changed, 172 insertions, 42 deletions
@@ -1,81 +1,211 @@ /* * jerror.c * - * Copyright (C) 1991, 1992, Thomas G. Lane. + * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains simple error-reporting and trace-message routines. * These are suitable for Unix-like systems and others where writing to - * stderr is the right thing to do. If the JPEG software is integrated - * into a larger application, you may well need to replace these. - * - * The error_exit() routine should not return to its caller. Within a - * larger application, you might want to have it do a longjmp() to return - * control to the outer user interface routine. This should work since - * the portable JPEG code doesn't use setjmp/longjmp. You should make sure - * that free_all is called either within error_exit or after the return to - * the outer-level routine. + * stderr is the right thing to do. Many applications will want to replace + * some or all of these routines. * * These routines are used by both the compression and decompression code. */ +/* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" -#ifdef INCLUDES_ARE_ANSI -#include <stdlib.h> /* to declare exit() */ -#endif +#include "jpeglib.h" +#include "jversion.h" + +#include "jerror.h" /* get error codes */ +#define JMAKE_MSG_TABLE +#include "jerror.h" /* create message string table */ #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif -static external_methods_ptr methods; /* saved for access to message_parm, free_all */ +/* + * Error exit handler: must not return to caller. + * + * Applications may override this if they want to get control back after + * an error. Typically one would longjmp somewhere instead of exiting. + * The setjmp buffer can be made a private field within an expanded error + * handler object. Note that the info needed to generate an error message + * is stored in the error object, so you can generate the message now or + * later, at your convenience. + * You should make sure that the JPEG object is cleaned up (with jpeg_abort + * or jpeg_destroy) at some point. + */ + +METHODDEF void +error_exit (j_common_ptr cinfo) +{ + /* Always display the message */ + (*cinfo->err->output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + exit(EXIT_FAILURE); +} + + +/* + * Actual output of an error or trace message. + * Applications may override this method to send JPEG messages somewhere + * other than stderr. + */ METHODDEF void -trace_message (const char *msgtext) +output_message (j_common_ptr cinfo) { - fprintf(stderr, msgtext, - methods->message_parm[0], methods->message_parm[1], - methods->message_parm[2], methods->message_parm[3], - methods->message_parm[4], methods->message_parm[5], - methods->message_parm[6], methods->message_parm[7]); - fprintf(stderr, "\n"); + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + + /* Send it to stderr, adding a newline */ + fprintf(stderr, "%s\n", buffer); } +/* + * Decide whether to emit a trace or warning message. + * msg_level is one of: + * -1: recoverable corrupt-data warning, may want to abort. + * 0: important advisory messages (always display to user). + * 1: first level of tracing detail. + * 2,3,...: successively more detailed tracing messages. + * An application might override this method if it wanted to abort on warnings + * or change the policy about which messages to display. + */ + METHODDEF void -error_exit (const char *msgtext) +emit_message (j_common_ptr cinfo, int msg_level) { - (*methods->trace_message) (msgtext); - (*methods->free_all) (); /* clean up memory allocation */ - exit(EXIT_FAILURE); + struct jpeg_error_mgr * err = cinfo->err; + + if (msg_level < 0) { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if (err->num_warnings == 0 || err->trace_level >= 3) + (*err->output_message) (cinfo); + /* Always count warnings in num_warnings. */ + err->num_warnings++; + } else { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if (err->trace_level >= msg_level) + (*err->output_message) (cinfo); + } } /* - * The method selection routine for simple error handling. - * The system-dependent setup routine should call this routine - * to install the necessary method pointers in the supplied struct. + * Format a message string for the most recent JPEG error or message. + * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX + * characters. Note that no '\n' character is added to the string. + * Few applications should need to override this method. */ -GLOBAL void -jselerror (external_methods_ptr emethods) +METHODDEF void +format_message (j_common_ptr cinfo, char * buffer) +{ + struct jpeg_error_mgr * err = cinfo->err; + int msg_code = err->msg_code; + const char * msgtext = NULL; + const char * msgptr; + char ch; + boolean isstring; + + /* Look up message string in proper table */ + if (msg_code > 0 && msg_code <= err->last_jpeg_message) { + msgtext = err->jpeg_message_table[msg_code]; + } else if (err->addon_message_table != NULL && + msg_code >= err->first_addon_message && + msg_code <= err->last_addon_message) { + msgtext = err->addon_message_table[msg_code - err->first_addon_message]; + } + + /* Defend against bogus message number */ + if (msgtext == NULL) { + err->msg_parm.i[0] = msg_code; + msgtext = err->jpeg_message_table[0]; + } + + /* Check for string parameter, as indicated by %s in the message text */ + isstring = FALSE; + msgptr = msgtext; + while ((ch = *msgptr++) != '\0') { + if (ch == '%') { + if (*msgptr == 's') isstring = TRUE; + break; + } + } + + /* Format the message into the passed buffer */ + if (isstring) + sprintf(buffer, msgtext, err->msg_parm.s); + else + sprintf(buffer, msgtext, + err->msg_parm.i[0], err->msg_parm.i[1], + err->msg_parm.i[2], err->msg_parm.i[3], + err->msg_parm.i[4], err->msg_parm.i[5], + err->msg_parm.i[6], err->msg_parm.i[7]); +} + + +/* + * Reset error state variables at start of a new image. + * This is called during compression startup to reset trace/error + * processing to default state, without losing any application-specific + * method pointers. An application might possibly want to override + * this method if it has additional error processing state. + */ + +METHODDEF void +reset_error_mgr (j_common_ptr cinfo) { - methods = emethods; /* save struct addr for later access */ + cinfo->err->num_warnings = 0; + /* trace_level is not reset since it is an application-supplied parameter */ + cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ +} + + +/* + * Fill in the standard error-handling methods in a jpeg_error_mgr object. + * Typical call is: + * struct jpeg_compress_struct cinfo; + * struct jpeg_error_mgr err; + * + * cinfo.err = jpeg_std_error(&err); + * after which the application may override some of the methods. + */ + +GLOBAL struct jpeg_error_mgr * +jpeg_std_error (struct jpeg_error_mgr * err) +{ + err->error_exit = error_exit; + err->emit_message = emit_message; + err->output_message = output_message; + err->format_message = format_message; + err->reset_error_mgr = reset_error_mgr; + + err->trace_level = 0; /* default = no tracing */ + err->num_warnings = 0; /* no warnings emitted yet */ + err->msg_code = 0; /* may be useful as a flag for "no error" */ - emethods->error_exit = error_exit; - emethods->trace_message = trace_message; + /* Initialize message table pointers */ + err->jpeg_message_table = jpeg_message_table; + err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; - emethods->trace_level = 0; /* default = no tracing */ + err->addon_message_table = NULL; + err->first_addon_message = 0; /* for safety */ + err->last_addon_message = 0; - emethods->num_warnings = 0; /* no warnings emitted yet */ - /* By default, the first corrupt-data warning will be displayed, - * but additional ones will appear only if trace level is at least 3. - * A corrupt data file could generate many warnings, so it's a good idea - * to suppress additional messages except at high tracing levels. - */ - emethods->first_warning_level = 0; - emethods->more_warning_level = 3; + return err; } |