From 964d28ed4391c639c60c392807c9dfb09f933ba8 Mon Sep 17 00:00:00 2001 From: anthony Date: Thu, 17 May 2012 23:39:46 +0000 Subject: [PATCH] Interpret all Option arguments (apart from a select few) --- MagickCore/option.c | 16 +- MagickCore/option.h | 5 +- MagickCore/property.c | 5 +- MagickWand/magick-cli.c | 306 +++++++++++++++++---------------- MagickWand/operation.c | 318 ++++++++++++++++++++--------------- MagickWand/tests/README | 19 +++ MagickWand/wandcli-private.h | 9 +- config/english.xml | 6 + config/francais.xml | 6 + 9 files changed, 393 insertions(+), 297 deletions(-) create mode 100644 MagickWand/tests/README diff --git a/MagickCore/option.c b/MagickCore/option.c index b9cd40fb8..8faa7536c 100644 --- a/MagickCore/option.c +++ b/MagickCore/option.c @@ -199,7 +199,7 @@ static const OptionInfo { "+alpha", 1L, DeprecateOptionFlag, MagickTrue }, { "-alpha", 1L, SimpleOperatorFlag, MagickFalse }, { "+annotate", 0L, DeprecateOptionFlag, MagickTrue }, - { "-annotate", 2L, SimpleOperatorFlag, MagickFalse }, + { "-annotate", 2L, SimpleOperatorFlag | AlwaysInterpretArgsFlag, MagickFalse }, { "+antialias", 0L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse }, { "-antialias", 0L, ImageInfoOptionFlag | DrawInfoOptionFlag, MagickFalse }, { "+append", 0L, ListOperatorFlag | FireOptionFlag, MagickFalse }, @@ -339,8 +339,8 @@ static const OptionInfo { "-dissolve", 1L, NonMagickOptionFlag, MagickFalse }, { "+dissimilarity-threshold", 0L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, { "-dissimilarity-threshold", 1L, NonMagickOptionFlag | ImageInfoOptionFlag, MagickFalse }, - { "+distort", 2L, SimpleOperatorFlag, MagickFalse }, - { "-distort", 2L, SimpleOperatorFlag, MagickFalse }, + { "+distort", 2L, SimpleOperatorFlag | AlwaysInterpretArgsFlag, MagickFalse }, + { "-distort", 2L, SimpleOperatorFlag | AlwaysInterpretArgsFlag, MagickFalse }, { "+dither", 0L, ImageInfoOptionFlag | QuantizeInfoOptionFlag, MagickFalse }, { "-dither", 1L, ImageInfoOptionFlag | QuantizeInfoOptionFlag, MagickFalse }, { "+draw", 0L, DeprecateOptionFlag, MagickTrue }, @@ -399,7 +399,7 @@ static const OptionInfo { "+frame", 1L, DeprecateOptionFlag, MagickTrue }, { "-frame", 1L, SimpleOperatorFlag, MagickFalse }, { "+function", 2L, DeprecateOptionFlag, MagickTrue }, - { "-function", 2L,SimpleOperatorFlag, MagickFalse }, + { "-function", 2L,SimpleOperatorFlag | AlwaysInterpretArgsFlag, MagickFalse }, { "+fuzz", 0L, ImageInfoOptionFlag, MagickFalse }, { "-fuzz", 1L, ImageInfoOptionFlag, MagickFalse }, { "+fx", 1L, DeprecateOptionFlag | FireOptionFlag, MagickTrue }, @@ -542,7 +542,7 @@ static const OptionInfo { "+preview", 0L, DeprecateOptionFlag, MagickTrue }, { "-preview", 1L, GlobalOptionFlag, MagickFalse }, { "+print", 1L, DeprecateOptionFlag | FireOptionFlag, MagickTrue }, - { "-print", 1L, ListOperatorFlag | FireOptionFlag, MagickFalse }, + { "-print", 1L, ListOperatorFlag | AlwaysInterpretArgsFlag | FireOptionFlag, MagickFalse }, { "+process", 1L, DeprecateOptionFlag | FireOptionFlag, MagickTrue }, { "-process", 1L, ListOperatorFlag | FireOptionFlag, MagickFalse }, { "+profile", 1L, SimpleOperatorFlag, MagickFalse }, @@ -617,8 +617,8 @@ static const OptionInfo { "-separate", 0L, SimpleOperatorFlag | FireOptionFlag, MagickFalse }, { "+sepia-tone", 1L, DeprecateOptionFlag, MagickTrue }, { "-sepia-tone", 1L, SimpleOperatorFlag, MagickFalse }, - { "+set", 1L, SimpleOperatorFlag, MagickFalse }, - { "-set", 2L, SimpleOperatorFlag, MagickFalse }, + { "+set", 1L, SimpleOperatorFlag | NeverInterpretArgsFlag, MagickFalse }, + { "-set", 2L, SimpleOperatorFlag | NeverInterpretArgsFlag, MagickFalse }, { "+shade", 0L, DeprecateOptionFlag, MagickTrue }, { "-shade", 1L, SimpleOperatorFlag, MagickFalse }, { "+shadow", 1L, DeprecateOptionFlag, MagickTrue }, @@ -646,7 +646,7 @@ static const OptionInfo { "+solarize", 1L, DeprecateOptionFlag, MagickTrue }, { "-solarize", 1L, SimpleOperatorFlag, MagickFalse }, { "+sparse-color", 1L, DeprecateOptionFlag, MagickTrue }, - { "-sparse-color", 2L, SimpleOperatorFlag, MagickFalse }, + { "-sparse-color", 2L, SimpleOperatorFlag | AlwaysInterpretArgsFlag, MagickFalse }, { "+splice", 1L, DeprecateOptionFlag, MagickTrue }, { "-splice", 1L, SimpleOperatorFlag, MagickFalse }, { "+spread", 1L, DeprecateOptionFlag, MagickTrue }, diff --git a/MagickCore/option.h b/MagickCore/option.h index 3a045e5e2..ad32b0ec9 100644 --- a/MagickCore/option.h +++ b/MagickCore/option.h @@ -125,7 +125,7 @@ typedef enum DrawInfoOptionFlag = 0x0002, /* Setting stored in DrawInfo */ QuantizeInfoOptionFlag = 0x0004, /* Setting stored in QuantizeInfo */ GlobalOptionFlag = 0x0008, /* Global Setting or Control */ - SettingOptionFlags = 0x000F, /* mask for all setting options */ + SettingOptionFlags = 0x000F, /* mask any setting option */ NoImageOperatorFlag = 0x0010, /* Images not required operator */ SimpleOperatorFlag = 0x0020, /* Simple Image processing operator */ @@ -135,6 +135,9 @@ typedef enum SpecialOptionFlag = 0x0100, /* Operator with Special Requirements */ /* EG: for specific CLI commands */ + AlwaysInterpretArgsFlag = 0x0400, /* Always Interpret escapes in Args */ + NeverInterpretArgsFlag = 0x0800, /* Never Interpret escapes in Args */ + NonMagickOptionFlag = 0x1000, /* Option not used by Magick Command */ FireOptionFlag = 0x2000, /* Convert operation seq firing point */ DeprecateOptionFlag = 0x4000, /* Deprecate option (no code) */ diff --git a/MagickCore/property.c b/MagickCore/property.c index 56ebaaf05..14df00750 100644 --- a/MagickCore/property.c +++ b/MagickCore/property.c @@ -2955,10 +2955,13 @@ MagickExport char *InterpretImageProperties(const ImageInfo *image_info, if( IfMagickTrue(image->debug) ) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); - if ((embed_text == (const char *) NULL) || (*embed_text == '\0')) + if ((embed_text == (const char *) NULL)) return((char *) NULL); p=embed_text; + if (*p == '\0') + return(ConstantString("")); + /* handle a '@' replace string from file */ if (*p == '@') { p++; diff --git a/MagickWand/magick-cli.c b/MagickWand/magick-cli.c index 74a383d27..b4d9cd18e 100644 --- a/MagickWand/magick-cli.c +++ b/MagickWand/magick-cli.c @@ -64,7 +64,6 @@ */ #define MagickCommandDebug 0 - #if MagickCommandDebug >= 9 /* Temporary Debugging Information @@ -77,13 +76,13 @@ static void OutputOptions(ImageInfo *image_info) *option, *value; - (void) FormatLocaleFile(stdout," Global Options:\n"); + (void) FormatLocaleFile(stderr," Global Options:\n"); ResetImageOptionIterator(image_info); while ((option=GetNextImageOption(image_info)) != (const char *) NULL ) { - (void) FormatLocaleFile(stdout," %s: ",option); + (void) FormatLocaleFile(stderr," %s: ",option); value=GetImageOption(image_info,option); if (value != (const char *) NULL) - (void) FormatLocaleFile(stdout,"%s\n",value); + (void) FormatLocaleFile(stderr,"%s\n",value); } ResetImageOptionIterator(image_info); } @@ -94,13 +93,13 @@ static void OutputArtifacts(Image *image) *artifact, *value; - (void) FormatLocaleFile(stdout," Image Artifacts:\n"); + (void) FormatLocaleFile(stderr," Image Artifacts:\n"); ResetImageArtifactIterator(image); while ((artifact=GetNextImageArtifact(image)) != (const char *) NULL ) { - (void) FormatLocaleFile(stdout," %s: ",artifact); + (void) FormatLocaleFile(stderr," %s: ",artifact); value=GetImageArtifact(image,artifact); if (value != (const char *) NULL) - (void) FormatLocaleFile(stdout,"%s\n",value); + (void) FormatLocaleFile(stderr,"%s\n",value); } ResetImageArtifactIterator(image); } @@ -111,13 +110,13 @@ static void OutputProperties(Image *image,ExceptionInfo *exception) *property, *value; - (void) FormatLocaleFile(stdout," Image Properity:\n"); + (void) FormatLocaleFile(stderr," Image Properity:\n"); ResetImagePropertyIterator(image); while ((property=GetNextImageProperty(image)) != (const char *) NULL ) { - (void) FormatLocaleFile(stdout," %s: ",property); + (void) FormatLocaleFile(stderr," %s: ",property); value=GetImageProperty(image,property,exception); if (value != (const char *) NULL) - (void) FormatLocaleFile(stdout,"%s\n",value); + (void) FormatLocaleFile(stderr,"%s\n",value); } ResetImagePropertyIterator(image); } @@ -216,93 +215,94 @@ WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv, break; /* error or end of options */ } - /* save option details */ - CloneString(&option,token_info->token); + do { /* use break to loop to exception handler and loop */ + + /* save option details */ + CloneString(&option,token_info->token); - /* get option, its argument count, and option type */ - cli_wand->command = GetCommandOptionInfo(option); - count=cli_wand->command->type; - option_type=(CommandOptionFlags) cli_wand->command->flags; + /* get option, its argument count, and option type */ + cli_wand->command = GetCommandOptionInfo(option); + count=cli_wand->command->type; + option_type=(CommandOptionFlags) cli_wand->command->flags; #if 0 - (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n", + (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n", cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic ); #endif - /* handle a undefined option - image read? */ - if ( option_type == UndefinedOptionFlag || - (option_type & NonMagickOptionFlag) != 0 ) { + /* handle a undefined option - image read - always for "magick-script" */ + if ( option_type == UndefinedOptionFlag || + (option_type & NonMagickOptionFlag) != 0 ) { #if MagickCommandDebug >= 3 - (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n", - cli_wand->line, cli_wand->line, option); + (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n", + cli_wand->line, cli_wand->line, option); #endif - if ( IfMagickFalse(IsCommandOption(option))) { - /* non-option -- treat as a image read */ - cli_wand->command=(const OptionInfo *)NULL; - CLIOption(cli_wand,"-read",option); - goto next_token; + if ( IfMagickFalse(IsCommandOption(option))) { + /* non-option -- treat as a image read */ + cli_wand->command=(const OptionInfo *)NULL; + CLIOption(cli_wand,"-read",option); + break; /* next option */ + } + CLIWandException(OptionFatalError,"UnrecognizedOption",option); + break; /* next option */ } - CLIWandExceptionBreak(OptionFatalError,"UnrecognizedOption",option); - goto next_token; - } - if ( count >= 1 ) { - if( IfMagickFalse(GetScriptToken(token_info)) ) - CLIWandException(OptionFatalError,"MissingArgument",option); - CloneString(&arg1,token_info->token); - } - else - CloneString(&arg1,(char *)NULL); - - if ( count >= 2 ) { - if( IfMagickFalse(GetScriptToken(token_info)) ) - CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option); - CloneString(&arg2,token_info->token); - } - else - CloneString(&arg2,(char *)NULL); + if ( count >= 1 ) { + if( IfMagickFalse(GetScriptToken(token_info)) ) + CLIWandException(OptionFatalError,"MissingArgument",option); + CloneString(&arg1,token_info->token); + } + else + CloneString(&arg1,(char *)NULL); + if ( count >= 2 ) { + if( IfMagickFalse(GetScriptToken(token_info)) ) + CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option); + CloneString(&arg2,token_info->token); + } + else + CloneString(&arg2,(char *)NULL); - /* - Process Options - */ + /* + Process Options + */ #if MagickCommandDebug >= 3 - (void) FormatLocaleFile(stderr, - "Script %u,%u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", - cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2); + (void) FormatLocaleFile(stderr, + "Script %u,%u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", + cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2); #endif - /* Hard Depreciated Options, no code to execute - error */ - if ( (option_type & DeprecateOptionFlag) != 0 ) { - CLIWandException(OptionError,"DeprecatedOptionNoCode",option); - if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) ) - break; - goto next_token; - } - - /* MagickCommandGenesis() options have no place in a magick script */ - if ( (option_type & GenesisOptionFlag) != 0 ) { - CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option); - goto next_token; - } + /* Hard Depreciated Options, no code to execute - error */ + if ( (option_type & DeprecateOptionFlag) != 0 ) { + CLIWandException(OptionError,"DeprecatedOptionNoCode",option); + break; /* next option */ + } - if ( (option_type & SpecialOptionFlag) != 0 ) { - if ( LocaleCompare(option,"-exit") == 0 ) { - break; /* forced end of script */ + /* MagickCommandGenesis() options have no place in a magick script */ + if ( (option_type & GenesisOptionFlag) != 0 ) { + CLIWandException(OptionError,"InvalidUseOfOption",option); + break; /* next option */ } - if ( LocaleCompare(option,"-script") == 0 ) { - /* FUTURE: call new script from this script */ - CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option); - goto next_token; + + /* handle any special 'script' options */ + if ( (option_type & SpecialOptionFlag) != 0 ) { + if ( LocaleCompare(option,"-exit") == 0 ) { + break; /* forced end of script */ + } + if ( LocaleCompare(option,"-script") == 0 ) { + /* FUTURE: call new script from this script - error for now */ + CLIWandException(OptionError,"InvalidUseOfOption",option); + break; /* next option */ + } + /* FUTURE: handle special script-argument options here */ + /* handle any other special operators now */ + CLIWandException(OptionError,"InvalidUseOfOption",option); + break; /* next option */ } - /* FUTURE: handle special script-argument options here */ - /* handle any other special operators now */ - CLIWandExceptionBreak(OptionError,"InvalidUseOfOption",option); - goto next_token; - } - /* Process non-specific Option */ - CLIOption(cli_wand, option, arg1, arg2); + /* Process non-specific Option */ + CLIOption(cli_wand, option, arg1, arg2); + + } while (0); /* break block to next option */ -next_token: #if MagickCommandDebug >= 9 OutputOptions(cli_wand->wand.image_info); if ( cli_wand->wand.images != (Image *)NULL ) { @@ -310,10 +310,13 @@ next_token: OutputProperties(cli_wand->wand.images,cli_wand->wand.exception); } #endif - if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) - break; + if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) ) + break; /* exit loop */ } + /* + Loop exit - check for some tokenization error + */ #if MagickCommandDebug >= 3 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status); #endif @@ -428,7 +431,7 @@ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, cli_wand->filename="CLI"; end = argc; - if ( (cli_wand->process_flags & ProcessImpliedWrite) != 0 ) + if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 ) end--; /* the last arument is an implied write, do not process directly */ for (i=index; i < end; i += count +1) { @@ -436,82 +439,87 @@ WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc, if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index ) return(i); - option=argv[i]; - cli_wand->line=i; /* note the argument for this option */ + do { /* use break to loop to exception handler and loop */ + + option=argv[i]; + cli_wand->line=i; /* note the argument for this option */ - /* get option, its argument count, and option type */ - cli_wand->command = GetCommandOptionInfo(argv[i]); - count=cli_wand->command->type; - option_type=(CommandOptionFlags) cli_wand->command->flags; + /* get option, its argument count, and option type */ + cli_wand->command = GetCommandOptionInfo(argv[i]); + count=cli_wand->command->type; + option_type=(CommandOptionFlags) cli_wand->command->flags; #if 0 - (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n", - i, argv[i], cli_wand->command->mnemonic ); + (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n", + i, argv[i], cli_wand->command->mnemonic ); #endif - if ( option_type == UndefinedOptionFlag || - (option_type & NonMagickOptionFlag) != 0 ) { + if ( option_type == UndefinedOptionFlag || + (option_type & NonMagickOptionFlag) != 0 ) { #if MagickCommandDebug >= 3 - (void) FormatLocaleFile(stderr, "CLI %d Non-Option: \"%s\"\n", i, option); + (void) FormatLocaleFile(stderr, "CLI %d Non-Option: \"%s\"\n", i, option); #endif - if ( IfMagickFalse(IsCommandOption(option)) ) { - if ( (cli_wand->process_flags & ProcessNonOptionImageRead) != 0 ) { - /* non-option -- treat as a image read */ - cli_wand->command=(const OptionInfo *)NULL; - CLIOption(cli_wand,"-read",option); - goto next_argument; + if ( IfMagickFalse(IsCommandOption(option)) ) { + if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) { + /* non-option -- treat as a image read */ + cli_wand->command=(const OptionInfo *)NULL; + CLIOption(cli_wand,"-read",option); + break; /* next option */ + } } + CLIWandException(OptionFatalError,"UnrecognizedOption",option); + break; /* next option */ } - CLIWandException(OptionFatalError,"UnrecognizedOption",option); - goto next_argument; - } - if ( ((option_type & SpecialOptionFlag) != 0 ) && - ((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 the 'implict write filename' argument - so it must be handled specially to prevent a 'missing argument' error. - */ - if ( (i+count) >= argc ) - CLIWandException(OptionFatalError,"MissingArgument",option); - ProcessScriptOptions(cli_wand,argc,argv,i+1); - return(argc); /* Script does not return to CLI -- Yet */ - /* FUTURE: when it does, their may be no write arg! */ - } + if ( ((option_type & SpecialOptionFlag) != 0 ) && + ((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 the 'implict write filename' argument + so it must be handled specially to prevent a 'missing argument' error. + */ + if ( (i+count) >= argc ) + CLIWandException(OptionFatalError,"MissingArgument",option); + ProcessScriptOptions(cli_wand,argc,argv,i+1); + return(argc); /* Script does not return to CLI -- Yet */ + /* FUTURE: when it does, their may be no write arg! */ + } - if ((i+count) >= end ) { - CLIWandException(OptionFatalError,"MissingArgument",option); - if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) - return(end); - goto next_argument; /* no more arguments unable to proceed */ - } + if ((i+count) >= end ) { + CLIWandException(OptionFatalError,"MissingArgument",option); + if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) + return(end); + break; /* next option - not that their is any! */ + } - arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL; - arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL; + arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL; + arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL; - /* - Process Known Options - */ + /* + Process Known Options + */ #if MagickCommandDebug >= 3 - (void) FormatLocaleFile(stderr, - "CLI %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", - i,option,count,option_type,arg1,arg2); + (void) FormatLocaleFile(stderr, + "CLI %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n", + i,option,count,option_type,arg1,arg2); #endif - if ( (option_type & GenesisOptionFlag) != 0 ) - goto next_argument; /* ignored this from command line args */ + /* ignore 'genesis options' in command line args */ + if ( (option_type & GenesisOptionFlag) != 0 ) + break; /* next option */ - if ( (option_type & SpecialOptionFlag) != 0 ) { - if ( (cli_wand->process_flags & ProcessExitOption) != 0 - && LocaleCompare(option,"-exit") == 0 ) - return(i+count); - goto next_argument; - } + /* Handle any special options for CLI (-script handled above) */ + if ( (option_type & SpecialOptionFlag) != 0 ) { + if ( (cli_wand->process_flags & ProcessExitOption) != 0 + && LocaleCompare(option,"-exit") == 0 ) + return(i+count); + break; /* next option */ + } - /* Process a Normal Option */ - CLIOption(cli_wand, option, arg1, arg2); + /* Process standard image option */ + CLIOption(cli_wand, option, arg1, arg2); + + } while (0); /* break block to next option */ -next_argument: #if MagickCommandDebug >= 9 OutputOptions(cli_wand->wand.image_info); if ( cli_wand->wand.images != (Image *)NULL ) { @@ -524,7 +532,7 @@ next_argument: } assert(i==end); - if ( (cli_wand->process_flags & ProcessImpliedWrite) == 0 ) + if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 ) return(end); /* no implied write -- just return to caller */ assert(end==argc-1); /* end should not include last argument */ @@ -535,19 +543,19 @@ next_argument: option=argv[i]; cli_wand->line=i; -#if MagickCommandDebug >= 3 - (void) FormatLocaleFile(stderr, "CLI %d Write File: \"%s\"\n", i, option ); -#endif - - /* check that stacks are empty */ + /* check that stacks are empty - or cause exception */ if (cli_wand->image_list_stack != (Stack *)NULL) - CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)"); + CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)"); else if (cli_wand->image_info_stack != (Stack *)NULL) - CLIWandException(OptionError,"UnbalancedBraces", "(eof)"); + CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)"); if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse ) return(argc); - /* This is a valid 'do no write' option - no images needed */ +#if MagickCommandDebug >= 3 + (void) FormatLocaleFile(stderr, "CLI %d Write File: \"%s\"\n", i, option ); +#endif + + /* Valid 'do no write' replacement option (instead of "null:") */ if (LocaleCompare(option,"-exit") == 0 ) return(argc); /* just exit, no image write */ diff --git a/MagickWand/operation.c b/MagickWand/operation.c index 8c5cc49fb..9f531542c 100644 --- a/MagickWand/operation.c +++ b/MagickWand/operation.c @@ -1600,7 +1600,7 @@ WandExport void CLISettingOptionInfo(MagickCLI *cli_wand, return the Image pointer to the first image in list. */ static void CLISimpleOperatorImage(MagickCLI *cli_wand, - const char *option, const char *arg1, const char *arg2) + const char *option, const char *arg1n, const char *arg2n) { Image * new_image; @@ -1617,11 +1617,17 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, ssize_t parse; + const char /* For percent escape interpretImageProperties() */ + *arg1, + *arg2; + #define _image_info (cli_wand->wand.image_info) #define _image (cli_wand->wand.images) #define _exception (cli_wand->wand.exception) #define _draw_info (cli_wand->draw_info) #define _quantize_info (cli_wand->quantize_info) +#define _process_flags (cli_wand->process_flags) +#define _option_type ((CommandOptionFlags) cli_wand->command->flags) #define IfNormalOp (*option=='-') #define IfPlusOp (*option!='-') #define normal_op IsMagickTrue(IfNormalOp) @@ -1634,13 +1640,38 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, if (IfMagickTrue(cli_wand->wand.debug)) (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); - SetGeometryInfo(&geometry_info); + /* Interpret Percent Escapes in Arguments - using first image */ + arg1 = arg1n, + arg2 = arg2n; + if ( (((_process_flags & ProcessInterpretProperities) != 0 ) + || ((_option_type & AlwaysInterpretArgsFlag) != 0) + ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) { + /* Interpret Percent escapes in argument 1 */ + if (arg1n != (char *) NULL) { + arg1=InterpretImageProperties(_image_info,_image,arg1n,_exception); + if (arg1 == (char *) NULL) { + CLIWandException(OptionWarning,"InterpretPropertyFailure",option); + arg1=arg1n; /* use the given argument as is */ + } + } + if (arg2n != (char *) NULL) { + arg2=InterpretImageProperties(_image_info,_image,arg2n,_exception); + if (arg2 == (char *) NULL) { + CLIWandException(OptionWarning,"InterpretPropertyFailure",option); + arg2=arg2n; /* use the given argument as is */ + } + } + } +#undef _option_type + +#if 0 + (void) FormatLocaleFile(stderr, + "CLISimpleOperatorImage: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2); +#endif new_image = (Image *)NULL; /* the replacement image, if not null at end */ + SetGeometryInfo(&geometry_info); - /* FUTURE: We may need somthing a little more optimized than this! - Perhaps, do the 'sync' if 'settings tainted' before next operator. - */ switch (*(option+1)) { case 'a': @@ -1690,7 +1721,6 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, if (LocaleCompare("annotate",option+1) == 0) { char - *text, geometry[MaxTextExtent]; SetGeometryInfo(&geometry_info); @@ -1699,12 +1729,7 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1); if ((flags & SigmaValue) == 0) geometry_info.sigma=geometry_info.rho; - text=InterpretImageProperties(_image_info,_image,arg2, - _exception); - if (text == (char *) NULL) - break; - (void) CloneString(&_draw_info->text,text); - text=DestroyString(text); + (void) CloneString(&_draw_info->text,arg2); (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f", geometry_info.xi,geometry_info.psi); (void) CloneString(&_draw_info->geometry,geometry); @@ -2133,9 +2158,6 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, } if (LocaleCompare("distort",option+1) == 0) { - char - *arg; - double *args; @@ -2164,13 +2186,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, (size_t)2,resize_args,MagickTrue,_exception); break; } - /* allow percent escapes in argument string */ - arg=InterpretImageProperties(_image_info,_image,arg2,_exception); - if (arg == (char *) NULL) - break; /* convert argument string into an array of doubles */ - args = StringToArrayOfDoubles(arg,&count,_exception); - arg=DestroyString(arg); + args = StringToArrayOfDoubles(arg2,&count,_exception); if (args == (double *)NULL ) CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2); @@ -2337,9 +2354,6 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, } if (LocaleCompare("function",option+1) == 0) { - char - *arg; - double *args; @@ -2350,13 +2364,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, if ( parse < 0 ) CLIWandExceptArgBreak(OptionError,"UnrecognizedFunction", option,arg1); - /* allow percent escapes in argument string */ - arg=InterpretImageProperties(_image_info,_image,arg2,_exception); - if (arg == (char *) NULL) - break; /* convert argument string into an array of doubles */ - args = StringToArrayOfDoubles(arg,&count,_exception); - arg=DestroyString(arg); + args = StringToArrayOfDoubles(arg2,&count,_exception); if (args == (double *)NULL ) CLIWandExceptArgBreak(OptionError,"InvalidNumberList",option,arg2); @@ -2431,15 +2440,14 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, *text; format=GetImageOption(_image_info,"format"); - if (format == (char *) NULL) - { - (void) IdentifyImage(_image,stdout,_image_info->verbose, - _exception); - break; - } + if (format == (char *) NULL) { + (void) IdentifyImage(_image,stdout,_image_info->verbose,_exception); + break; + } text=InterpretImageProperties(_image_info,_image,format,_exception); if (text == (char *) NULL) - break; + CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure", + option); (void) fputs(text,stdout); (void) fputc('\n',stdout); text=DestroyString((char *)text); @@ -3070,7 +3078,8 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, } value=InterpretImageProperties(_image_info,_image,arg2,_exception); if (value == (char *) NULL) - break; + CLIWandExceptionBreak(OptionWarning,"InterpretPropertyFailure", + option); if (LocaleNCompare(arg1,"registry:",9) == 0) (void) SetImageRegistry(StringRegistryType,arg1+9,value,_exception); else @@ -3176,19 +3185,12 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, } if (LocaleCompare("sparse-color",option+1) == 0) { - char - *arguments; - parse= ParseCommandOption(MagickSparseColorOptions,MagickFalse,arg1); if ( parse < 0 ) CLIWandExceptArgBreak(OptionError,"UnrecognizedSparseColorMethod", option,arg1); - arguments=InterpretImageProperties(_image_info,_image,arg2,_exception); - if (arguments == (char *) NULL) - CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg2); - new_image=SparseColorOption(_image,(SparseColorMethod)parse, - arguments,_exception); - arguments=DestroyString(arguments); + new_image=SparseColorOption(_image,(SparseColorMethod)parse,arg2, + _exception); break; } if (LocaleCompare("splice",option+1) == 0) @@ -3404,10 +3406,14 @@ static void CLISimpleOperatorImage(MagickCLI *cli_wand, default: CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); } - /* - Replace current image with any image that was generated - and set image point to last image (so image->next is correct) - */ + /* clean up percent escape interpreted strings */ + if (arg1 != arg1n ) + arg1=DestroyString((char *)arg1); + if (arg2 != arg2n ) + arg2=DestroyString((char *)arg2); + + /* Replace current image with any image that was generated + and set image point to last image (so image->next is correct) */ if (new_image != (Image *) NULL) ReplaceImageInListReturnLast(&_image,new_image); @@ -3491,7 +3497,7 @@ WandExport void CLISimpleOperatorImages(MagickCLI *cli_wand, % */ WandExport void CLIListOperatorImages(MagickCLI *cli_wand, - const char *option,const char *arg1, const char *magick_unused(arg2)) + const char *option,const char *arg1n, const char *arg2n) { ssize_t parse; @@ -3499,11 +3505,17 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand, Image *new_images; + const char /* For percent escape interpretImageProperties() */ + *arg1, + *arg2; + #define _image_info (cli_wand->wand.image_info) #define _images (cli_wand->wand.images) #define _exception (cli_wand->wand.exception) #define _draw_info (cli_wand->draw_info) #define _quantize_info (cli_wand->quantize_info) +#define _process_flags (cli_wand->process_flags) +#define _option_type ((CommandOptionFlags) cli_wand->command->flags) #define IfNormalOp (*option=='-') #define IfPlusOp (*option!='-') #define normal_op IsMagickTrue(IfNormalOp) @@ -3515,6 +3527,36 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand, if (IfMagickTrue(cli_wand->wand.debug)) (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); + /* Interpret Percent Escapes in Arguments - using first image */ + arg1 = arg1n; + arg2 = arg2n; + if ( (((_process_flags & ProcessInterpretProperities) != 0 ) + || ((_option_type & AlwaysInterpretArgsFlag) != 0) + ) && ((_option_type & NeverInterpretArgsFlag) == 0) ) { + /* Interpret Percent escapes in argument 1 */ + if (arg1n != (char *) NULL) { + arg1=InterpretImageProperties(_image_info,_images,arg1n,_exception); + if (arg1 == (char *) NULL) { + CLIWandException(OptionWarning,"InterpretPropertyFailure",option); + arg1=arg1n; /* use the given argument as is */ + } + } + if (arg2n != (char *) NULL) { + arg2=InterpretImageProperties(_image_info,_images,arg2n,_exception); + if (arg2 == (char *) NULL) { + CLIWandException(OptionWarning,"InterpretPropertyFailure",option); + arg2=arg2n; /* use the given argument as is */ + } + } + } +#undef _option_type + +#if 0 + (void) FormatLocaleFile(stderr, + "CLIListOperatorImages: \"%s\" \"%s\" \"%s\"\n",option,arg1,arg2); +#endif + + new_images=NewImageList(); switch (*(option+1)) @@ -3981,14 +4023,7 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand, { if (LocaleCompare("print",option+1) == 0) { - char - *string; - - string=InterpretImageProperties(_image_info,_images,arg1,_exception); - if (string == (char *) NULL) - break; - (void) FormatLocaleFile(stdout,"%s",string); - string=DestroyString(string); + (void) FormatLocaleFile(stdout,"%s",arg1); break; } if (LocaleCompare("process",option+1) == 0) @@ -4192,11 +4227,17 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand, default: CLIWandExceptionBreak(OptionError,"UnrecognizedOption",option); } + + /* clean up percent escape interpreted strings */ + if (arg1 != arg1n ) + arg1=DestroyString((char *)arg1); + if (arg2 != arg2n ) + arg2=DestroyString((char *)arg2); + + /* if new image list generated, replace existing image list */ if (new_images == (Image *) NULL) return; - - if (_images != (Image *) NULL) - _images=DestroyImageList(_images); + _images=DestroyImageList(_images); _images=GetFirstImageInList(new_images); return; @@ -4215,21 +4256,21 @@ WandExport void CLIListOperatorImages(MagickCLI *cli_wand, % % % % % % -+ C L I S p e c i a l O p e r a t i o n s % ++ C L I N o I m a g e O p e r a t i o n s % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CLINoImageOperator() Applies operations that may not actually need images -% in an image list wen it is applied. +% in an image list. % % The classic operators of this type is -read, which actually creates images % even when no images are present. Or image stack operators, which can be -% applied to empty image lists. +% applied (push or pop) to an empty image list. % % Note: unlike other Operators, these may involve other special 'option' -% character prefixes, other than simply '-' or '+'. +% characters other than '-' or '+', namely parenthesis and braces. % % The format of the CLINoImageOption method is: % @@ -4330,7 +4371,7 @@ WandExport void CLINoImageOperator(MagickCLI *cli_wand, Image * new_images; #if 0 -fprintf(stderr, "DEBUG: Reading image: \"%s\"\n", argv[i]); + fprintf(stderr, "DEBUG: Reading image: \"%s\"\n", argv[i]); #endif if (IfMagickTrue(_image_info->ping)) new_images=PingImages(_image_info,argv[i],_exception); @@ -4613,19 +4654,25 @@ fprintf(stderr, "DEBUG: Reading image: \"%s\"\n", argv[i]); % % % % % % -+ C L I O p t i o n O p e r a t i o n s % ++ C L I O p t i o n % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % CLIOption() Processes the given option using the given CLI Magick Wand. +% The option arguments can be variable in number, though at this time no more +% that two is actually used by any option (this may change). Excess options +% are simply ignored. % % If the cli_wand->command pointer is non-null, then it is assumed that the % option has already been search for up from the CommandOptions[] table in -% "MagickCore/options.c" using GetCommandOptionInfo(), so that any command -% specific options (such as "magick" scripting options, or "display" settings) -% can be handled separatally. +% "MagickCore/options.c" using GetCommandOptionInfo(). If not set this +% routine will do the lookup instead. The pointer is reset afterward. +% +% This action allows the caller to lookup and pre-handle any 'special' +% options, (such as implicit reads) before calling this general option +% handler to deal with 'standard' command line options. % % The format of the CLIOption method is: % @@ -4637,7 +4684,7 @@ fprintf(stderr, "DEBUG: Reading image: \"%s\"\n", argv[i]); % % o option: The special option (with any switch char) to process % -% o args: any required arguments for an option +% o args: any required arguments for an option (variable number) % % Example Usage... % @@ -4662,88 +4709,91 @@ WandExport void CLIOption(MagickCLI *cli_wand,const char *option,...) if (IfMagickTrue(cli_wand->wand.debug)) (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name); - if ( cli_wand->command == (const OptionInfo *) NULL ) - cli_wand->command = GetCommandOptionInfo(option); + do { /* Break Code Block for error handling */ + + /* get information about option */ + if ( cli_wand->command == (const OptionInfo *) NULL ) + cli_wand->command = GetCommandOptionInfo(option); #if 0 - (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n", - option, cli_wand->command->mnemonic ); + (void) FormatLocaleFile(stderr, "CLIOption \"%s\" matched \"%s\"\n", + option, cli_wand->command->mnemonic ); #endif + option_type=(CommandOptionFlags) cli_wand->command->flags; - option_type=(CommandOptionFlags) cli_wand->command->flags; + if ( option_type == UndefinedOptionFlag ) + CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option); - if ( option_type == UndefinedOptionFlag ) - CLIWandExceptionReturn(OptionFatalError,"UnrecognizedOption",option); + assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 ); - assert( LocaleCompare(cli_wand->command->mnemonic,option) == 0 ); + /* depreciated options */ + if ( (option_type & DeprecateOptionFlag) != 0 ) + CLIWandExceptionBreak(OptionError,"DeprecatedOptionNoCode",option); - if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 ) - CLIWandExceptionReturn(OptionFatalError,"InvalidUseOfOption",option); + /* options that this module does not handle */ + if ((option_type & (SpecialOptionFlag|GenesisOptionFlag)) != 0 ) + CLIWandExceptionBreak(OptionFatalError,"InvalidUseOfOption",option); - if ( (option_type & DeprecateOptionFlag) != 0 ) - CLIWandExceptionReturn(OptionError,"DeprecatedOptionNoCode",option); + /* Get argument strings from VarArgs + How can you determine arguments is enough was supplied? */ + { size_t + count = cli_wand->command->type; - if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) ) - return; + va_list + operands; + va_start(operands,option); - { size_t - count = cli_wand->command->type; + arg1=arg2=NULL; + if ( count >= 1 ) + arg1=(const char *) va_arg(operands, const char *); + if ( count >= 2 ) + arg2=(const char *) va_arg(operands, const char *); - va_list - operands; - - va_start(operands,option); - - arg1=arg2=NULL; - if ( count >= 1 ) - arg1=(const char *) va_arg(operands, const char *); - if ( count >= 2 ) - arg2=(const char *) va_arg(operands, const char *); - - va_end(operands); + va_end(operands); #if 0 - (void) FormatLocaleFile(stderr, - "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n", - option,(long) count,option_type,arg1,arg2); + (void) FormatLocaleFile(stderr, + "CLIOption: \"%s\" Count: %ld Flags: %04x Args: \"%s\" \"%s\"\n", + option,(long) count,option_type,arg1,arg2); #endif - } + } - cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */ + /* + Call the appropriate option handler + */ + /* FUTURE: this is temporary - get 'settings' to handle distribution of + settings to images attributes,proprieties,artifacts */ + if ( cli_wand->wand.images != (Image *)NULL ) + SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images, + cli_wand->wand.exception); - /* - Call the appropriate option handler - */ + if ( (option_type & SettingOptionFlags) != 0 ) { + CLISettingOptionInfo(cli_wand, option, arg1, arg2); + // FUTURE: Sync Specific Settings into Image Properities (not global) + } - /* FUTURE: this is temporary - get 'settings' to handle - distribution of settings to images attributes,proprieties,artifacts */ - if ( cli_wand->wand.images != (Image *)NULL ) - SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images, - cli_wand->wand.exception); + /* Operators that do not need images - read, write, stack, clone */ + if ( (option_type & NoImageOperatorFlag) != 0) + CLINoImageOperator(cli_wand, option, arg1, arg2); - if ( (option_type & SettingOptionFlags) != 0 ) { - CLISettingOptionInfo(cli_wand, option, arg1, arg2); - // FUTURE: Sync Specific Settings into Image Properities (not global) - } + /* FUTURE: The not a setting part below is a temporary hack due to + * some options being both a Setting and a Simple operator. + * Specifically -monitor, -depth, and -colorspace */ + if ( cli_wand->wand.images == (Image *)NULL ) + if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) && + ((option_type & SettingOptionFlags) == 0 )) /* temp hack */ + CLIWandExceptionBreak(OptionError,"NoImagesFound",option); - if ( (option_type & NoImageOperatorFlag) != 0) - CLINoImageOperator(cli_wand, option, arg1, arg2); - - /* FUTURE: The not a setting part below is a temporary hack due to - * some options being both a Setting and a Simple operator. - * Specifically -monitor, -depth, and -colorspace */ - if ( cli_wand->wand.images == (Image *)NULL ) { - if ( ((option_type & (SimpleOperatorFlag|ListOperatorFlag)) != 0 ) && - ((option_type & SettingOptionFlags) == 0 )) /* temp hack */ - CLIWandException(OptionError,"NoImagesFound",option); - return; /* on its own this is not an error */ - } + /* Operators work on single images, and needs a loop over the images */ + if ( (option_type & SimpleOperatorFlag) != 0) + CLISimpleOperatorImages(cli_wand, option, arg1, arg2); - if ( (option_type & SimpleOperatorFlag) != 0) - CLISimpleOperatorImages(cli_wand, option, arg1, arg2); + /* Operators that work on the image list as a whole */ + if ( (option_type & ListOperatorFlag) != 0 ) + CLIListOperatorImages(cli_wand, option, arg1, arg2); - if ( (option_type & ListOperatorFlag) != 0 ) - CLIListOperatorImages(cli_wand, option, arg1, arg2); + } while (0); /* end Break code block */ + cli_wand->command = (const OptionInfo *) NULL; /* prevent re-use later */ } diff --git a/MagickWand/tests/README b/MagickWand/tests/README new file mode 100644 index 000000000..88475d8d6 --- /dev/null +++ b/MagickWand/tests/README @@ -0,0 +1,19 @@ + +These file provide simple examples and testing of aspects of the +MagickWand API. + +Specifically + + MagickAddImage() (also use by MagickReadImage() ) in various situations + with a single images, or a list of images. Study of the examples + details exactly what the API does. + + + GetScriptToken () doing low level testing of the tokenization (argument + separation) the "magick" command applies when reading command options + from a script, or pipeline. The Tokenization is designed specifically to + emulate the BASH shell. In this way you would write scripts in exactly the + same way you would write BASH shell command line arguments. + + Tests include quoting, mixed quoting, backslash escapes, line + continuation, extremely long tokens, and various error conditions. + + diff --git a/MagickWand/wandcli-private.h b/MagickWand/wandcli-private.h index d0b0b6d42..4e84a6d15 100644 --- a/MagickWand/wandcli-private.h +++ b/MagickWand/wandcli-private.h @@ -59,11 +59,12 @@ extern "C" { /* Define how options should be processed */ typedef enum { - /* NonOption Handling */ - ProcessNonOptionImageRead = 0x0001, /* A non-option is a image read + /* General Option Handling */ + ProcessImplictRead = 0x0001, /* Non-options are image reads. If not set then skip implied read without producing an error. For use with "mogrify" handling */ + ProcessInterpretProperities = 0x0010, /* allow general escapes in args */ /* Special Option Handling */ ProcessExitOption = 0x0100, /* allow '-exit' use */ @@ -73,10 +74,10 @@ typedef enum /* Option Processing Flags */ ProcessOneOptionOnly = 0x4000, /* Process one option only */ - ProcessImpliedWrite = 0x8000, /* Last arg is an implied write */ + ProcessImplictWrite = 0x8000, /* Last arg is an implict write */ /* Flag Groups for specific Situations */ - MagickCommandOptionFlags = 0x8F0F, /* Magick Command Flags */ + MagickCommandOptionFlags = 0x8FFF, /* Magick Command Flags */ ConvertCommandOptionFlags = 0x800F, /* Convert Command Flags */ MagickScriptArgsFlags = 0x000F, /* Script CLI Process Args Flags */ } ProcessOptionFlags; diff --git a/config/english.xml b/config/english.xml index e4b333c13..2a4f42e52 100644 --- a/config/english.xml +++ b/config/english.xml @@ -613,6 +613,9 @@ geometry does not contain image + + failure in interpret image property escapes + invalid argument for option @@ -942,6 +945,9 @@ geometry does not contain image + + failure in interpret image property escapes + invalid setting diff --git a/config/francais.xml b/config/francais.xml index 616ea39b2..0c5c87dbb 100644 --- a/config/francais.xml +++ b/config/francais.xml @@ -607,6 +607,9 @@ image non incluse dans la géométrie + + *** failure in interpret image property escapes *** + argument invalide pour l'option @@ -933,6 +936,9 @@ image non incluse dans la géométrie + + *** failure in interpret image property escapes *** + invalide de réglage -- 2.40.0