From: anthony Date: Tue, 10 Apr 2012 13:02:37 +0000 (+0000) Subject: Exception handling for CLI Wands. X-Git-Tag: 7.0.1-0~5840 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5216f82250f6a3a9fe652a6534a46e0a69f5c6f7;p=imagemagick Exception handling for CLI Wands. Preparations to disable depreciation meessages in "convert" --- diff --git a/MagickCore/exception.c b/MagickCore/exception.c index 9971d052b..492ef2367 100644 --- a/MagickCore/exception.c +++ b/MagickCore/exception.c @@ -951,8 +951,9 @@ MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception, % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% ThrowMagickException logs an exception as determined by the log configuration -% file. If an error occurs, MagickFalse is returned otherwise MagickTrue. +% ThrowMagickException logs an exception as determined by the log +% configuration file. If an error occurs, MagickFalse is returned +% otherwise MagickTrue. % % The format of the ThrowMagickException method is: % @@ -978,7 +979,7 @@ MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception, % */ -static MagickBooleanType ThrowMagickExceptionList(ExceptionInfo *exception, +MagickExport MagickBooleanType ThrowMagickExceptionList(ExceptionInfo *exception, const char *module,const char *function,const size_t line, const ExceptionType severity,const char *tag,const char *format, va_list operands) diff --git a/MagickCore/exception.h b/MagickCore/exception.h index f6558f336..581c035b1 100644 --- a/MagickCore/exception.h +++ b/MagickCore/exception.h @@ -153,6 +153,8 @@ extern MagickExport FatalErrorHandler extern MagickExport MagickBooleanType ThrowException(ExceptionInfo *,const ExceptionType,const char *, const char *), + ThrowMagickExceptionList(ExceptionInfo *,const char *,const char *,const size_t, + const ExceptionType,const char *,const char *,va_list), ThrowMagickException(ExceptionInfo *,const char *,const char *,const size_t, const ExceptionType,const char *,const char *,...) magick_attribute((__format__ (__printf__,7,8))); diff --git a/MagickWand/magick-cli.c b/MagickWand/magick-cli.c index 4677e3243..27d3c3a01 100644 --- a/MagickWand/magick-cli.c +++ b/MagickWand/magick-cli.c @@ -55,6 +55,7 @@ #include "MagickWand/magick-cli.h" #include "MagickWand/script-token.h" #include "MagickCore/utility-private.h" +#include "MagickCore/exception-private.h" #include "MagickCore/version.h" /* verbose debugging, @@ -63,16 +64,6 @@ */ #define MagickCommandDebug 0 -#define ThrowFileException(exception,severity,tag,context) \ -{ \ - char \ - *message; \ - \ - message=GetExceptionMessage(errno); \ - (void) ThrowMagickException(exception,GetMagickModule(),severity, \ - tag == (const char *) NULL ? "unknown" : tag,"'%s': %s",context,message); \ - message=DestroyString(message); \ -} #if MagickCommandDebug >= 9 /* @@ -94,7 +85,7 @@ static void OutputOptions(ImageInfo *image_info) if (value != (const char *) NULL) (void) FormatLocaleFile(stdout,"%s\n",value); } - ResetImageOptionIterator(image_info); + ResetImageOptionIterator(image_info); } static void OutputArtifacts(Image *image) @@ -202,15 +193,13 @@ WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv, /* open file script or stream, and set up tokenizer */ token_info = AcquireScriptTokenInfo(argv[index]); if (token_info == (ScriptTokenInfo *) NULL) { - ThrowFileException(cli_wand->wand.exception,OptionFatalError, - "UnableToOpenScript",argv[index]); + CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",argv[index]); return; } /* define the error location string for use in exceptions - order of input escapes: option, (arg), filename, line, column */ - cli_wand->location="'%s' in \"%s\" line %u column %u"; - cli_wand->location2="'%s' '%s' in \"%s\" line %u column %u"; + order of localtion format escapes: filename, line, column */ + cli_wand->location="in \"%s\" at line %u,column %u"; if ( LocaleCompare("-", argv[index]) == 0 ) cli_wand->filename="stdin"; else @@ -434,7 +423,7 @@ next_token: % */ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, - char **argv, int index, ProcessOptionFlags process_flags ) + char **argv, int index ) { const char *option, @@ -459,22 +448,21 @@ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); /* define the error location string for use in exceptions - order of input escapes: option, (arg), filename, line, column */ - cli_wand->location="'%s' %s arg %u"; - cli_wand->location2="'%s' '%s' %s arg %u"; + order of localtion format escapes: filename, line, column */ + cli_wand->location="at %s argument %u"; cli_wand->filename="CLI"; end = argc; - if ( ( process_flags & ProcessOutputFile ) != 0 ) - end--; + if ( (cli_wand->process_flags & ProcessImpliedWrite) != 0 ) + end--; /* the last arument is an implied write, do not process directly */ for (i=index; i < end; i += count +1) { /* Finished processing one option? */ - if ( ( process_flags & ProcessOneOptionOnly ) != 0 && i != index ) + if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index ) return(i); option=argv[i]; - cli_wand->line=i; + cli_wand->line=i; /* note the argument for this option */ { const OptionInfo *option_info = GetCommandOptionInfo(argv[i]); count=option_info->type; @@ -491,14 +479,14 @@ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, (void) FormatLocaleFile(stderr, "CLI %d Non-Option: \"%s\"\n", i, option); #endif if ( IfMagickFalse(IsCommandOption(option)) ) { - if ( (process_flags & ProcessNonOptionImageRead) != 0 ) + if ( (cli_wand->process_flags & ProcessNonOptionImageRead) != 0 ) /* non-option -- treat as a image read */ CLISpecialOperator(cli_wand,"-read",option); else CLIWandException(OptionFatalError,"UnrecognizedOption",option); goto next_argument; } - if ( ((process_flags & ProcessScriptOption) != 0) && + if ( ((cli_wand->process_flags & ProcessScriptOption) != 0) && (LocaleCompare(option,"-script") == 0) ) { /* Call Script from CLI, with a filename as a zeroth argument. NOTE: -script may need to use 'implict write filename' so it @@ -543,7 +531,7 @@ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, } if ( (option_type & SpecialOptionFlag) != 0 ) { - if ( ( process_flags & ProcessExitOption ) != 0 + if ( (cli_wand->process_flags & ProcessExitOption) != 0 && LocaleCompare(option,"-exit") == 0 ) return(i+count); /* handle any other special operators now */ @@ -577,10 +565,10 @@ next_argument: } assert(i==end); - if ( ( process_flags & ProcessOutputFile ) == 0 ) - return(end); + if ( (cli_wand->process_flags & ProcessImpliedWrite) == 0 ) + return(end); /* no implied write -- just return to caller */ - assert(end==argc-1); + assert(end==argc-1); /* end should not include last argument */ /* Implicit Write of images to final CLI argument @@ -723,7 +711,7 @@ static void MagickUsage(MagickBooleanType verbose) however the last argument provides the output filename. */ static MagickBooleanType ConcatenateImages(int argc,char **argv, - ExceptionInfo *exception) + ExceptionInfo *exception ) { FILE *input, @@ -737,8 +725,7 @@ static MagickBooleanType ConcatenateImages(int argc,char **argv, output=fopen_utf8(argv[argc-1],"wb"); if (output == (FILE *) NULL) { - ThrowFileException(exception,FileOpenError,"UnableToOpenFile", - argv[argc-1]); + ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]); return(MagickFalse); } for (i=2; i < (ssize_t) (argc-1); i++) { @@ -760,15 +747,9 @@ WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info, MagickCLI *cli_wand; - const char - *option; - size_t len; - ProcessOptionFlags - process_flags = MagickCommandOptionFlags; - /* For specific OS command line requirements */ ReadCommandlLine(argc,&argv); @@ -791,7 +772,7 @@ WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info, /* "convert" command - give a "depreciation" warning" */ if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) { - process_flags = ConvertCommandOptionFlags; + cli_wand->process_flags = ConvertCommandOptionFlags; /*(void) FormatLocaleFile(stderr,"WARNING: %s\n", "The convert is depreciated in IMv7, use \"magick\"\n");*/ } @@ -807,17 +788,16 @@ WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info, /* Special Case: Version Information and Abort */ if (argc == 2) { - option=argv[1]; - if (LocaleCompare("-version",option) == 0) { + if (LocaleCompare("-version",argv[1]) == 0) { CLISpecialOperator(cli_wand, "-version", (char *)NULL); goto Magick_Command_Exit; } - if ((LocaleCompare("-help",option) == 0) || /* GNU standard option */ - (LocaleCompare("--help",option) == 0) ) { + if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */ + (LocaleCompare("--help",argv[1]) == 0) ) { MagickUsage(MagickFalse); goto Magick_Command_Exit; } - if (LocaleCompare("-usage",option) == 0) { + if (LocaleCompare("-usage",argv[1]) == 0) { CLISpecialOperator(cli_wand, "-version", (char *)NULL); MagickUsage(MagickTrue); goto Magick_Command_Exit; @@ -857,12 +837,13 @@ WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info, } else { /* Normal Command Line, assumes output file as last option */ - ProcessCommandOptions(cli_wand,argc,argv,1, process_flags); + ProcessCommandOptions(cli_wand,argc,argv,1); } /* ------------- */ Magick_Command_Cleanup: - /* recover original image_info and clean up stacks */ + /* recover original image_info and clean up stacks + FUTURE: "-reset stacks" option */ while (cli_wand->image_list_stack != (Stack *)NULL) CLISpecialOperator(cli_wand,")",(const char *)NULL); while (cli_wand->image_info_stack != (Stack *)NULL) diff --git a/MagickWand/magick-cli.h b/MagickWand/magick-cli.h index ecf8f5cbb..692eabeaa 100644 --- a/MagickWand/magick-cli.h +++ b/MagickWand/magick-cli.h @@ -22,38 +22,11 @@ extern "C" { #endif -typedef enum -{ - /* What options should be processed */ - /* NonOption Handling */ - ProcessNonOptionImageRead = 0x0001, /* non-option is a image read - If not set then skip implied read - without producing an error. - For use with "mogrify" handling - */ - - /* Special Option Handling */ - ProcessExitOption = 0x0100, /* allow '-exit' use */ - ProcessScriptOption = 0x0200, /* allow '-script' use */ - ProcessReadOption = 0x0400, /* allow '-read' use */ - - /* Option Processing Flags */ - ProcessOneOptionOnly = 0x4000, /* Process One Option Only */ - ProcessOutputFile = 0x8000, /* Process the output file */ - - /* Flag Groups for specific Situations */ - MagickCommandOptionFlags = 0x8FFF, /* Magick Command Flags */ - ConvertCommandOptionFlags = 0x80FF, /* Convert Command Flags */ - MagickScriptArgsFlags = 0x00FF, /* Script Args Flags */ - MagickScriptReadFlags = 0x01FF /* Script Read Flags - unused */ - -} ProcessOptionFlags; - extern WandExport void ProcessScriptOptions(MagickCLI *,int,char **,int); extern WandExport int - ProcessCommandOptions(MagickCLI *,int,char **,int,ProcessOptionFlags); + ProcessCommandOptions(MagickCLI *,int,char **,int); extern WandExport MagickBooleanType MagickImageCommand(ImageInfo *,int,char **,char **,ExceptionInfo *); diff --git a/MagickWand/operation.c b/MagickWand/operation.c index 9925816ab..4f2f2849b 100644 --- a/MagickWand/operation.c +++ b/MagickWand/operation.c @@ -4663,7 +4663,7 @@ WandExport void CLISpecialOperator(MagickCLI *cli_wand, #if 0 // Other 'special' options this should handle - // "region" + // "region" "reset" "arg" if ( ( process_flags & ProcessUnknownOptionError ) != 0 ) #endif CLIWandException(OptionError,"UnrecognizedOption",option); diff --git a/MagickWand/wandcli-private.h b/MagickWand/wandcli-private.h index e0b8a834f..9c17b249b 100644 --- a/MagickWand/wandcli-private.h +++ b/MagickWand/wandcli-private.h @@ -23,26 +23,56 @@ extern "C" { #endif #define CLIWandException(severity,tag,option) \ - (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(), \ - severity,tag,cli_wand->location,option,cli_wand->filename, \ - cli_wand->line,cli_wand->column) + (void) CLIThrowException(cli_wand,GetMagickModule(),severity,tag, \ + "'%s'",option) #define CLIWandExceptionArg(severity,tag,option,arg) \ - (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(), \ - severity,tag,cli_wand->location2,option,arg,cli_wand->filename, \ - cli_wand->line,cli_wand->column) + (void) CLIThrowException(cli_wand,GetMagickModule(),severity,tag, \ + "'%s' '%s'",option, arg) + +#define CLIWandExceptionFile(severity,tag,context) \ +{ char *message=GetExceptionMessage(errno); \ + (void) CLIThrowException(cli_wand,GetMagickModule(),severity,tag, \ + "'%s': %s",context,message); \ + message=DestroyString(message); \ +} #define CLIWandExceptionBreak(severity,tag,option) \ { CLIWandException(severity,tag,option); break; } #define CLIWandExceptionReturn(severity,tag,option) \ - { CLIWandException(severity,tag,option); return; } + { CLIWandException(severity,tag,option); return; } #define CLIWandExceptArgBreak(severity,tag,option,arg) \ - { CLIWandExceptionArg(severity,tag,option,arg); break; } + { CLIWandExceptionArg(severity,tag,option,arg); break; } #define CLIWandExceptArgReturn(severity,tag,option,arg) \ - { CLIWandExceptionArg(severity,tag,option,arg); return; } + { CLIWandExceptionArg(severity,tag,option,arg); return; } + + +/* Define how options should be processed */ +typedef enum +{ + /* NonOption Handling */ + ProcessNonOptionImageRead = 0x0001, /* A non-option is a image read + If not set then skip implied read + without producing an error. + For use with "mogrify" handling */ + + /* Special Option Handling */ + ProcessExitOption = 0x0100, /* allow '-exit' use */ + ProcessScriptOption = 0x0200, /* allow '-script' use */ + ProcessReadOption = 0x0400, /* allow '-read' use */ + + /* Option Processing Flags */ + ProcessOneOptionOnly = 0x4000, /* Process one option only */ + ProcessImpliedWrite = 0x8000, /* Last arg is an implied write */ + + /* Flag Groups for specific Situations */ + MagickCommandOptionFlags = 0x8F0F, /* Magick Command Flags */ + ConvertCommandOptionFlags = 0x800F, /* Convert Command Flags */ + MagickScriptArgsFlags = 0x000F, /* Script CLI Process Args Flags */ +} ProcessOptionFlags; /* Define a generic stack linked list, for pushing and popping @@ -75,22 +105,23 @@ struct _MagickCLI /* CLI interface version of MagickWand */ *image_list_stack, /* Stacks of Image Lists and Image Info settings */ *image_info_stack; - const char /* Location string for exception reporting */ - *filename, /* See CLIWandException() macro above */ - *location, /* EG: "'%s' @ \"%s\" line %u column %u" - option, filename, line, column */ - *location2; /* EG: "'%s' '%s' @ \"%s\" line %u column %u" - option, arg, filename, line, column */ + ProcessOptionFlags + process_flags; /* when handling CLI, what options do we process? */ + + const char /* Location of option being processed for exception */ + *location, /* location format string for exception reports */ + *filename; /* "CLI", "unknown", or script filename */ size_t - line, /* location of current option for error above */ - column; + line, /* location of current option from source */ + column; /* note: line also used for cli argument count */ size_t signature; }; + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/MagickWand/wandcli.c b/MagickWand/wandcli.c index e6c025934..8363edf97 100644 --- a/MagickWand/wandcli.c +++ b/MagickWand/wandcli.c @@ -47,6 +47,7 @@ #include "MagickWand/magick-wand-private.h" #include "MagickWand/wandcli.h" #include "MagickWand/wandcli-private.h" +#include "MagickCore/exception.h" /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -118,13 +119,17 @@ WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info, cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info); cli_wand->image_list_stack=(Stack *)NULL; cli_wand->image_info_stack=(Stack *)NULL; - cli_wand->location="'%s'"; /* option location not known by default */ - cli_wand->location2="'%s' '%s'"; - cli_wand->filename=cli_wand->wand.name; + cli_wand->process_flags=MagickCommandOptionFlags; /* assume "magick" CLI */ + + /* default exception location... + EG: sprintf(locaiton, filename, line, column); + */ + cli_wand->location="from \"%s\""; /* location format: */ + cli_wand->filename="unknown"; /* unknown source */ cli_wand->line=0; cli_wand->column=0; - cli_wand->signature=WandSignature; + cli_wand->signature=WandSignature; if (IfMagickTrue(cli_wand->wand.debug)) (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); return(cli_wand); @@ -242,3 +247,54 @@ WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand, return(status); } + +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% % +% % ++ C L I T h r o w E x c e p t i o n % +% % +% % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% CLIThrowException() formats and records an exception condition, adding to +% it the location of the option that caused the exception to occur. +*/ +WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand, + const char *module,const char *function,const size_t line, + const ExceptionType severity,const char *tag,const char *format,...) +{ + char + new_format[MaxTextExtent]; + + size_t + len; + + MagickBooleanType + status; + + va_list + operands; + + /* HACK - append location to format string. + The better way would be append location formats and add more arguments to + operands, but that does not appear to be posible! + Note: ThrowMagickExceptionList() was exported specifically for + the use of this function. + */ + (void) CopyMagickString(new_format,format,MaxTextExtent); + (void) ConcatenateMagickString(new_format," ",MaxTextExtent); + + len=strlen(new_format); + (void) FormatLocaleString(new_format+len,MaxTextExtent-len,cli_wand->location, + cli_wand->filename, cli_wand->line, cli_wand->column); + + va_start(operands,format); + status=ThrowMagickExceptionList(cli_wand->wand.exception, + module,function,line, + severity,tag,new_format,operands); + va_end(operands); + return(status); +} diff --git a/MagickWand/wandcli.h b/MagickWand/wandcli.h index d386395cd..0d07f154a 100644 --- a/MagickWand/wandcli.h +++ b/MagickWand/wandcli.h @@ -30,7 +30,11 @@ extern WandExport MagickCLI *DestroyMagickCLI(MagickCLI *); extern WandExport MagickBooleanType - CLICatchException(MagickCLI *,const MagickBooleanType); + CLICatchException(MagickCLI *,const MagickBooleanType), + CLIThrowException(MagickCLI *,const char *,const char *,const size_t, + const ExceptionType,const char *,const char *,...) + magick_attribute((__format__ (__printf__,7,8))); + #if defined(__cplusplus) || defined(c_plusplus) }