% January 2012 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
#include "MagickWand/studio.h"
#include "MagickWand/MagickWand.h"
#include "MagickWand/magick-wand-private.h"
+#include "MagickWand/wandcli.h"
+#include "MagickWand/wandcli-private.h"
#include "MagickWand/operation.h"
-#include "MagickWand/operation-private.h"
#include "MagickWand/magick-cli.h"
-#include "MagickCore/memory_.h"
-#include "MagickCore/string-private.h"
+#include "MagickWand/script-token.h"
#include "MagickCore/utility-private.h"
+#include "MagickCore/exception-private.h"
#include "MagickCore/version.h"
\f
/* verbose debugging,
- 1 - option type
- 2 - source of option
- 3 - mnemonic lookup */
-#define MagickCommandDebug 0
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% G e t S c r i p t T o k e n %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%
-% GetScriptToken() is fairly general, finite state token parser. That will
-% divide a input file stream into tokens, in a way that is as close to a
-% UNIX shell, as is feasable. Only shell variable, and command
-% substitutions will not be performed.
-%
-% Tokens are white space separated, and may be quoted, or even partially
-% quoted by either single or double quotes, or the use of backslashes,
-% or any mix of the three.
-%
-% For example: This\ is' a 'single" token"
-%
-% A token is returned immediatally the end of token is found. That is as soon
-% as a ending white-space or EOF condition was determined. That is to say
-% the file stream is parsed purely character-by-character, regardless any
-% buffering constraints set by the system.
-%
-% The function will return 'MagickTrue' if a valid token was found, while
-% the token status will be set accordingally to 'OK' or 'EOF', according to
-% the cause of the end of token. The token may be an empty string if the
-% input was a quoted empty string. Other error conditions return a value of
-% MagickFalse, indicating any token found was incomplete due to the error
-% condition.
-%
-% Single quotes will preserve all characters including backslashes. Double
-% quotes will also preserve backslashes unless escaping a double quote,
-% or another backslashes. Other shell meta-characters are not treated as
-% special by this tokenizer.
-%
-% For example Quoting the quote chars:
-% \' "'" \" '"' "\"" \\ '\' "\\"
-%
-% Outside quotes, backslash characters will make spaces, tabs and quotes part
-% of a token returned. However a backslash at the end of a line (and outside
-% quotes) will cause the newline to be completely ignored (as per the shell
-% line continuation).
-%
-% Comments start with a '#' character at the start of a new token, will be
-% completely ignored upto the end of line, regardless of any backslash at the
-% end of the line. You can escape a comment '#', using quotes or backlsashes
-% just as you can in a shell.
-%
-% The format of the MagickImageCommand method is:
-%
-% MagickBooleanType GetScriptToken(ScriptTokenInfo *token_info)
-%
-% A description of each parameter follows:
-%
-% o token_info pointer to a structure holding token details
-%
+ 0 - no debug lines
+ 3 - show option details (better to use -debug Command now)
+ 5 - image counts (after option runs)
*/
+#define MagickCommandDebug 0
-/* States of the parser */
-#define IN_WHITE 0
-#define IN_TOKEN 1
-#define IN_QUOTE 2
-#define IN_COMMENT 3
-
-typedef enum {
- TokenStatusOK = 0,
- TokenStatusEOF,
- TokenStatusBadQuotes,
- TokenStatusTokenTooBig,
- TokenStatusBinary
-} TokenStatus;
-
-typedef struct
-{
- FILE
- *stream; /* the file stream we are reading from */
-
- char
- *token; /* array of characters to holding details of he token */
-
- size_t
- length, /* length of token char array */
- curr_line, /* current location in script file */
- curr_column,
- token_line, /* location of the start of this token */
- token_column;
-
- TokenStatus
- status; /* Have we reached EOF? see Token Status */
-} ScriptTokenInfo;
-
-/* macro to read character from stream */
-#define GetChar(c) \
-{ \
- c=fgetc(token_info->stream); \
- token_info->curr_column++; \
- if ( c == '\n' ) \
- token_info->curr_line++, token_info->curr_column=0; \
-}
-/* macro to collect the token characters */
-#define SaveChar(c) \
-{ \
- if ((size_t) offset >= (token_info->length-1)) \
- { token_info->token[offset++]='\0'; \
- token_info->status=TokenStatusTokenTooBig; \
- return(MagickFalse); \
- } \
- token_info->token[offset++]=(char) (c); \
-}
-
-static MagickBooleanType GetScriptToken(ScriptTokenInfo *token_info)
-{
-
- int
- quote,
- c;
-
- int
- state;
-
- ssize_t
- offset;
-
- /* EOF - no more tokens! */
- if (token_info->status != TokenStatusOK)
- {
- token_info->token[0]='\0';
- return(MagickFalse);
- }
-
- state=IN_WHITE;
- quote='\0';
- offset=0;
- while(1)
- {
- /* get character */
- GetChar(c);
- if (c == '\0' || c == EOF)
- break;
-
- /* hash comment handling */
- if ( state == IN_COMMENT )
- { if ( c == '\n' )
- state=IN_WHITE;
- continue;
- }
- if (c == '#' && state == IN_WHITE)
- state=IN_COMMENT;
- /* whitespace break character */
- if (strchr(" \n\r\t",c) != (char *)NULL)
- {
- switch (state)
- {
- case IN_TOKEN:
- token_info->token[offset]='\0';
- return(MagickTrue);
- case IN_QUOTE:
- SaveChar(c);
- break;
- }
- continue;
- }
- /* quote character */
- if (strchr("'\"",c) != (char *)NULL)
- {
- switch (state)
- {
- case IN_WHITE:
- token_info->token_line=token_info->curr_line;
- token_info->token_column=token_info->curr_column;
- case IN_TOKEN:
- state=IN_QUOTE;
- quote=c;
- break;
- case IN_QUOTE:
- if (c == quote)
- {
- state=IN_TOKEN;
- quote='\0';
- }
- else
- SaveChar(c);
- break;
- }
- continue;
- }
- /* escape char (preserve in quotes - unless escaping the same quote) */
- if (c == '\\')
- {
- if ( state==IN_QUOTE && quote == '\'' )
- {
- SaveChar('\\');
- continue;
- }
- GetChar(c);
- if (c == '\0' || c == EOF)
- {
- SaveChar('\\');
- break;
- }
- if (c == '\n')
- switch (state)
- {
- case IN_COMMENT:
- state=IN_WHITE; /* end comment */
- case IN_WHITE:
- case IN_TOKEN:
- continue; /* line continuation (outside quotes and comment) */
- }
- switch (state)
- {
- case IN_WHITE:
- token_info->token_line=token_info->curr_line;
- token_info->token_column=token_info->curr_column;
- state=IN_TOKEN;
- break;
- case IN_QUOTE:
- if (c != quote && c != '\\')
- SaveChar('\\');
- break;
- }
- SaveChar(c);
- continue;
- }
- /* ordinary character */
- switch (state)
- {
- case IN_WHITE:
- token_info->token_line=token_info->curr_line;
- token_info->token_column=token_info->curr_column;
- state=IN_TOKEN;
- case IN_TOKEN:
- case IN_QUOTE:
- SaveChar(c);
- break;
- case IN_COMMENT:
- break;
- }
- }
- /* stream has EOF or produced a fatal error */
- token_info->token[offset]='\0';
- token_info->status = TokenStatusEOF;
- if (state == IN_QUOTE)
- token_info->status = TokenStatusBadQuotes;
- if (c == '\0' )
- token_info->status = TokenStatusBinary;
- if (state == IN_TOKEN && token_info->status == TokenStatusEOF)
- return(MagickTrue);
- return(MagickFalse);
-}
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ProcessScriptOptions() reads options and processes options as they are
% found in the given file, or pipeline. The filename to open and read
-% options is given as the zeroth argument of the argument array given.
+% options is given as the 'index' argument of the argument array given.
%
-% A script not 'return' to the command line processing, nor can they
-% call (and return from) other scripts. At least not at this time.
+% Other arguments following index may be read by special script options
+% as settings (strings), images, or as operations to be processed in various
+% ways. How they are treated is up to the script being processed.
%
-% However special script options may used to read and process the other
-% argument provided, typically those that followed a "-script" option on the
-% command line. These extra script arguments may be interpreted as being
-% images to read or write, settings (strings), or more options to be
-% processed. How they are treated is up to the script being processed.
+% Note that a script not 'return' to the command line processing, nor can
+% they call (and return from) other scripts. At least not at this time.
+%
+% There are no 'ProcessOptionFlags' control flags at this time.
%
% The format of the ProcessScriptOptions method is:
%
-% void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv)
+% void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
+% int argc,char **argv,int index)
%
% A description of each parameter follows:
%
% o cli_wand: the main CLI Wand to use.
%
-% o argc: the number of elements in the argument vector.
+% o filename: the filename of script to process
%
-% o argv: A text array containing the command line arguments.
+% o argc: the number of elements in the argument vector. (optional)
+%
+% o argv: A text array containing the command line arguments. (optional)
+%
+% o index: offset of next argment in argv (script arguments) (optional)
%
*/
-#define MagickExceptionScript(severity,tag,arg,line,col) \
- (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(), \
- severity,tag, "'%s' : Line %u Column %u of script \"%s\"", \
- arg, line, col, cli_wand->wand.name);
-
-WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv)
+WandExport void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
+ int argc,char **argv,int index)
{
- char
- *option,
- *arg1,
- *arg2;
-
- ssize_t
- count;
-
- size_t
- option_line, /* line and column of current option */
- option_column;
+ ScriptTokenInfo
+ *token_info;
CommandOptionFlags
option_type;
- ScriptTokenInfo
- token_info;
+ int
+ count;
- MagickBooleanType
- plus_alt_op,
- file_opened;
+ char
+ *option,
+ *arg1,
+ *arg2;
- assert(argc>0 && argv[argc-1] != (char *)NULL);
+ assert(filename != (char *)NULL ); /* at least one argument - script name */
assert(cli_wand != (MagickCLI *) NULL);
assert(cli_wand->signature == WandSignature);
- if (cli_wand->wand.debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
-
- /* Initialize variables */
- /* FUTURE handle file opening for '-' 'fd:N' or script filename */
- file_opened=MagickFalse;
- if ( LocaleCompare(argv[0],"-") == 0 )
- {
- CopyMagickString(cli_wand->wand.name,"stdin",MaxTextExtent);
- token_info.stream=stdin;
- file_opened=MagickFalse;
- }
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) LogMagickEvent(CommandEvent,GetMagickModule(),
+ "Processing script \"%s\"", filename);
+
+ /* open file script or stream, and set up tokenizer */
+ token_info = AcquireScriptTokenInfo(filename);
+ if (token_info == (ScriptTokenInfo *) NULL) {
+ CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",filename);
+ return;
+ }
+
+ /* define the error location string for use in exceptions
+ order of localtion format escapes: filename, line, column */
+ cli_wand->location="in \"%s\" at line %u,column %u";
+ if ( LocaleCompare("-", filename) == 0 )
+ cli_wand->filename="stdin";
else
- {
- GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
- token_info.stream=fopen(argv[0], "r");
- file_opened=MagickTrue;
- }
+ cli_wand->filename=filename;
+ /* Process Options from Script */
option = arg1 = arg2 = (char*)NULL;
- token_info.curr_line=1;
- token_info.curr_column=0;
- token_info.status=TokenStatusOK;
- token_info.length=MaxTextExtent;
- token_info.token=(char *) AcquireQuantumMemory(MaxTextExtent,sizeof(char));
- if (token_info.token == (char *) NULL)
- {
- if ( file_opened != MagickFalse )
- fclose(token_info.stream);
- MagickExceptionScript(ResourceLimitError,"MemoryAllocationFailed","",0,0);
- (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","script token buffer");
- return;
+ while (1) {
+
+ { MagickBooleanType status = GetScriptToken(token_info);
+ cli_wand->line=token_info->token_line;
+ cli_wand->column=token_info->token_column;
+ if( IfMagickFalse(status) )
+ break; /* error or end of options */
}
- /* Process Options from Script */
- while (1)
- {
- /* Get a option */
- if( GetScriptToken(&token_info) == MagickFalse )
- break;
-
- /* option length sanity check */
- if( strlen(token_info.token) > 40 )
- { token_info.token[37] = '.';
- token_info.token[38] = '.';
- token_info.token[39] = '.';
- token_info.token[40] = '\0';
- MagickExceptionScript(OptionFatalError,"UnrecognizedOption",
- token_info.token,token_info.token_line,token_info.token_column);
- break;
- }
+ do { /* use break to loop to exception handler and loop */
/* save option details */
- CloneString(&option,token_info.token);
- option_line=token_info.token_line;
- option_column=token_info.token_column;
+ CloneString(&option,token_info->token);
-#if MagickCommandDebug >=2
- (void) FormatLocaleFile(stderr, "Script Option Token: %u,%u: \"%s\"\n",
- option_line, option_column, option );
-#endif
- /* get option type and argument count */
- { const OptionInfo *option_info = GetCommandOptionInfo(option);
- count=option_info->type;
- option_type=option_info->flags;
-#if MagickCommandDebug >= 3
- (void) FormatLocaleFile(stderr, "option \"%s\" matched \"%s\"\n",
- option, option_info->mnemonic );
+ /* 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",
+ cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic );
#endif
- }
- /* handle a undefined option - image read? */
+ /* handle a undefined option - image read - always for "magick-script" */
if ( option_type == UndefinedOptionFlag ||
- (option_type & NonMagickOptionFlag) != 0 )
- {
-#if MagickCommandDebug
- (void) FormatLocaleFile(stderr, "Script Non-Option: \"%s\"\n", option);
+ (option_type & NonMagickOptionFlag) != 0 ) {
+#if MagickCommandDebug >= 3
+ (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n",
+ cli_wand->line, cli_wand->line, option);
#endif
- if ( IsCommandOption(option) == MagickFalse)
- {
- /* non-option -- treat as a image read */
- CLISpecialOperator(cli_wand,"-read",option);
- count = 0;
- }
- else
- MagickExceptionScript(OptionFatalError,"UnrecognizedOption",
- option,option_line,option_column);
-
- if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
- break;
-
- continue;
+ 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 */
+ }
- plus_alt_op = MagickFalse;
- if (*option=='+') plus_alt_op = MagickTrue;
-
- if ( count >= 1 )
- {
- if( GetScriptToken(&token_info) == MagickFalse )
- {
- MagickExceptionScript(OptionError,"MissingArgument",option,
- option_line,option_column);
- break;
- }
- CloneString(&arg1,token_info.token);
- }
+ if ( count >= 1 ) {
+ if( IfMagickFalse(GetScriptToken(token_info)) )
+ CLIWandException(OptionFatalError,"MissingArgument",option);
+ CloneString(&arg1,token_info->token);
+ }
else
- CloneString(&arg1,(*option!='+')?"true":(char *)NULL);
-
- if ( count >= 2 )
- {
- if( GetScriptToken(&token_info) == MagickFalse )
- {
- MagickExceptionScript(OptionError,"MissingArgument",option,
- option_line,option_column);
- break;
- }
- CloneString(&arg2,token_info.token);
- }
+ 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);
- /* handle script special options */
- //either continue processing command line
- // or making use of the command line options.
- //CLICommandOptions(cli_wand,count+1,argv, MagickScriptArgsFlags);
-
-#if MagickCommandDebug
+ /*
+ Process Options
+ */
+#if MagickCommandDebug >= 3
(void) FormatLocaleFile(stderr,
- "Script Option: \"%s\" \tCount: %d Flags: %04x Args: \"%s\" \"%s\"\n",
- option,(int) count,option_type,arg1,arg2);
+ "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);
+ break; /* next option */
+ }
- /* Process non-script specific option from file */
- if ( (option_type & SpecialOptionFlag) != 0 )
- {
- if ( LocaleCompare(option,"-exit") == 0 )
- break;
- /* No "-script" from script at this time */
- CLISpecialOperator(cli_wand,option,arg1);
- }
+ /* MagickCommandGenesis() options have no place in a magick script */
+ if ( (option_type & GenesisOptionFlag) != 0 ) {
+ CLIWandException(OptionError,"InvalidUseOfOption",option);
+ break; /* next option */
+ }
- if ( (option_type & SettingOptionFlags) != 0 )
- {
- CLISettingOptionInfo(cli_wand, option+1, arg1);
- // FUTURE: Sync Specific Settings into Images
+ /* handle any special 'script' options */
+ if ( (option_type & SpecialOptionFlag) != 0 ) {
+ if ( LocaleCompare(option,"-exit") == 0 ) {
+ goto loop_exit; /* break out of loop - return from 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 */
+ }
- if ( (option_type & SimpleOperatorOptionFlag) != 0)
- CLISimpleOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
-
- if ( (option_type & ListOperatorOptionFlag) != 0 )
- CLIListOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
+ /* Process non-specific Option */
+ CLIOption(cli_wand, option, arg1, arg2);
- if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
- break;
- }
+ } while (0); /* break block to next option */
-#if MagickCommandDebug
- (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info.status);
+#if MagickCommandDebug >= 5
+ fprintf(stderr, "Script Image Count = %ld\n",
+ GetImageListLength(cli_wand->wand.images) );
#endif
- /* token sanity for error report */
- if( strlen(token_info.token) > 40 )
- { token_info.token[37] = '.';
- token_info.token[38] = '.';
- token_info.token[39] = '.';
- token_info.token[40] = '\0';
- }
+ if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
+ break; /* exit loop */
+ }
- switch( token_info.status )
- {
- case TokenStatusBadQuotes:
- MagickExceptionScript(OptionFatalError,"ScriptUnbalancedQuotes",
- token_info.token,token_info.token_line,token_info.token_column);
- break;
- case TokenStatusTokenTooBig:
- MagickExceptionScript(OptionFatalError,"ScriptTokenTooBig",
- token_info.token,token_info.token_line,token_info.token_column);
- break;
- case TokenStatusBinary:
- MagickExceptionScript(OptionFatalError,"ScriptIsBinary","",
- token_info.curr_line,token_info.curr_column);
- break;
- case TokenStatusOK:
- case TokenStatusEOF:
- break;
- }
+ /*
+ Loop exit - check for some tokenization error
+ */
+loop_exit:
+#if MagickCommandDebug >= 3
+ (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
+#endif
+ switch( token_info->status ) {
+ case TokenStatusOK:
+ case TokenStatusEOF:
+ if (cli_wand->image_list_stack != (Stack *)NULL)
+ CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
+ else if (cli_wand->image_info_stack != (Stack *)NULL)
+ CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
+ break;
+ case TokenStatusBadQuotes:
+ /* Ensure last token has a sane length for error report */
+ if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
+ token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
+ token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
+ token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
+ token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
+ }
+ CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
+ token_info->token);
+ break;
+ case TokenStatusMemoryFailed:
+ CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
+ break;
+ case TokenStatusBinary:
+ CLIWandException(OptionFatalError,"ScriptIsBinary","");
+ break;
+ }
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) LogMagickEvent(CommandEvent,GetMagickModule(),
+ "Script End \"%s\"", filename);
- /* Clean up */
- if ( file_opened != MagickFalse )
- fclose(token_info.stream);
+ /* Clean up */
+ token_info = DestroyScriptTokenInfo(token_info);
- CloneString(&option,(char *)NULL);
- CloneString(&arg1,(char *)NULL);
- CloneString(&arg2,(char *)NULL);
+ CloneString(&option,(char *)NULL);
+ CloneString(&arg1,(char *)NULL);
+ CloneString(&arg2,(char *)NULL);
- return;
+ return;
}
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ProcessCommandOptions() reads and processes arguments in the given
-% command line argument array. The array does not contain the command
-% being processed, only the options.
+% command line argument array. The 'index' defines where in the array we
+% should begin processing
%
% The 'process_flags' can be used to control and limit option processing.
% For example, to only process one option, or how unknown and special options
%
% The format of the ProcessCommandOptions method is:
%
-% int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
-% int *index, ProcessOptionFlags process_flags )
+% int ProcessCommandOptions(MagickCLI *cli_wand,
+% int argc,char **argv,int index)
%
% A description of each parameter follows:
%
%
% o argv: A text array containing the command line arguments.
%
-% o process_flags: What type of arguments we are allowed to process
+% o process_flags: What type of arguments will be processed, ignored
+% or return errors.
+%
+% o index: index in the argv array to start processing from
+%
+% The function returns the index ot the next option to be processed. This
+% is really only releven if process_flags contains a ProcessOneOptionOnly
+% flag.
%
*/
-/* FUTURE: correctly identify option... CLI arg, Script line,column */
-#define MagickExceptionContinue(severity,tag,arg,index) \
- (void) ThrowMagickException(cli_wand->wand.exception,GetMagickModule(),severity,tag, \
- "'%s' : CLI Arg #%d", arg, (int) index); \
-
-#define MagickExceptionReturn(severity,tag,option,arg) \
-{ \
- MagickExceptionContinue(severity,tag,option,arg); \
- return; \
-}
-
-WandExport void ProcessCommandOptions(MagickCLI *cli_wand,int argc,
- char **argv, ProcessOptionFlags process_flags )
+WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc,
+ char **argv, int index )
{
const char
*option,
*arg1,
*arg2;
- MagickBooleanType
- plus_alt_op;
-
- ssize_t
+ int
i,
end,
count;
CommandOptionFlags
option_type;
- assert(argc>0 && argv[argc-1] != (char *)NULL);
+ assert(argc>=index); /* you may have no arguments left! */
+ assert(argv != (char **)NULL);
+ assert(argv[index] != (char *)NULL);
+ assert(argv[argc-1] != (char *)NULL);
assert(cli_wand != (MagickCLI *) NULL);
assert(cli_wand->signature == WandSignature);
- if (cli_wand->wand.debug != MagickFalse)
- (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
- /*
- Parse command-line options.
- */
+ /* define the error location string for use in exceptions
+ order of localtion format escapes: filename, line, column */
+ cli_wand->location="at %s arg %u";
+ cli_wand->filename="CLI";
+ cli_wand->line=index; /* note first argument we will process */
+
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+ "- Starting (\"%s\")", argv[index]);
+
end = argc;
- if ( ( process_flags & ProcessOutputFile ) != 0 )
- end--;
- for (i=0; i < end; i += count +1)
- {
-#if MagickCommandDebug >= 2
- (void) FormatLocaleFile(stderr, "index= %d option="%s\"\n", i, argv[i]);
-#endif
- /* Finished processing one option? */
- if ( ( process_flags & ProcessOneOptionOnly ) != 0 && i != 0 )
- return;
+ if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
+ end--; /* the last arument is an implied write, do not process directly */
- option=argv[i];
- plus_alt_op = MagickFalse;
- arg1=(char *)NULL;
- arg2=(char *)NULL;
+ for (i=index; i < end; i += count +1) {
+ /* Finished processing one option? */
+ if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
+ return(i);
+ do { /* use break to loop to exception handler and loop */
- { const OptionInfo *option_info = GetCommandOptionInfo(argv[i]);
- count=option_info->type;
- option_type=option_info->flags;
-#if MagickCommandDebug >= 3
- (void) FormatLocaleFile(stderr, "option \"%s\" matched \"%s\"\n",
- argv[i], option_info->mnemonic );
+ 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;
+#if 0
+ (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 MagickCommandDebug
- (void) FormatLocaleFile(stderr, "CLI Non-Option: \"%s\"\n", option);
+ (option_type & NonMagickOptionFlag) != 0 ) {
+#if MagickCommandDebug >= 3
+ (void) FormatLocaleFile(stderr, "CLI arg %d Non-Option: \"%s\"\n",
+ i, option);
#endif
- if ( ( IsCommandOption(option) == MagickFalse ) &&
- ( (process_flags & ProcessNonOptionImageRead) != 0 ) )
- {
- /* non-option -- treat as a image read */
- CLISpecialOperator(cli_wand,"-read",option);
- count = 0;
- }
- else if ( (process_flags & ProcessUnknownOptionError) != 0 )
- MagickExceptionReturn(OptionFatalError,"UnrecognizedOption",
- option,i);
-
- if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
- break;
-
- continue;
+ 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 */
+ }
+ 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,argv[i+1],argc,argv,i+count);
+ return(argc); /* Script does not return to CLI -- Yet */
+ /* FUTURE: when it does, their may be no write arg! */
+ }
- if ( (option_type & DeprecateOptionFlag) != 0 )
- {
- MagickExceptionContinue(OptionWarning,"DeprecatedOption",option,i);
- if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
- break;
- /* FALLTHRU - continue processing */
- }
-
- if ((i+count) >= end )
- {
- MagickExceptionReturn(OptionError,"MissingArgument",option,i);
- if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
- break;
- continue; /* 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! */
+ }
- if (*option=='+') plus_alt_op = MagickTrue;
- if (*option!='+') arg1 = "true";
- if ( count >= 1 ) arg1 = argv[i+1];
- if ( count >= 2 ) arg2 = argv[i+2];
+ arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL;
+ arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL;
-#if MagickCommandDebug
+ /*
+ Process Known Options
+ */
+#if MagickCommandDebug >= 3
(void) FormatLocaleFile(stderr,
- "CLI Option: \"%s\" \tCount: %d Flags: %04x Args: \"%s\" \"%s\"\n",
- option,(int) count,option_type,arg1,arg2);
+ "CLI arg %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
+ i,option,count,option_type,arg1,arg2);
#endif
+ /* ignore 'genesis options' in command line args */
+ if ( (option_type & GenesisOptionFlag) != 0 )
+ break; /* next option */
+
+ /* 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 */
+ }
- if ( (option_type & SpecialOptionFlag) != 0 )
- {
- if ( ( process_flags & ProcessExitOption ) != 0
- && LocaleCompare(option,"-exit") == 0 )
- return;
- if ( ( process_flags & ProcessScriptOption ) != 0
- && LocaleCompare(option,"-script") == 0)
- {
- // Unbalanced Parenthesis if stack not empty
- // Call Script, with a filename as a zeroth argument
- ProcessScriptOptions(cli_wand,argc-(i+1),argv+(i+1));
- return;
- }
- CLISpecialOperator(cli_wand,option,arg1);
- }
-
-
- if ( (option_type & SettingOptionFlags) != 0 )
- {
- CLISettingOptionInfo(cli_wand, option+1, arg1);
- // FUTURE: Sync Specific Settings into Images
- }
-
- if ( (option_type & SimpleOperatorOptionFlag) != 0)
- CLISimpleOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
-
- if ( (option_type & ListOperatorOptionFlag) != 0 )
- CLIListOperatorImages(cli_wand, plus_alt_op, option+1, arg1, arg2);
+ /* Process standard image option */
+ CLIOption(cli_wand, option, arg1, arg2);
- if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
- break;
+ } while (0); /* break block to next option */
- }
+#if MagickCommandDebug >= 5
+ (void) FormatLocaleFile(stderr, "CLI-post Image Count = %ld\n",
+ (long) GetImageListLength(cli_wand->wand.images) );
+#endif
+ if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
+ return(i+count);
+ }
+ assert(i==end);
- if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
- return;
+ if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
+ return(end); /* no implied write -- just return to caller */
- if ( ( process_flags & ProcessOutputFile ) == 0 )
- return;
- assert(end==argc-1);
+ assert(end==argc-1); /* end should not include last argument */
/*
Implicit Write of images to final CLI argument
*/
option=argv[i];
+ cli_wand->line=i;
-#if MagickCommandDebug
- (void) FormatLocaleFile(stderr, "CLI Output: \"%s\"\n", option );
-#endif
+ /* check that stacks are empty - or cause exception */
+ if (cli_wand->image_list_stack != (Stack *)NULL)
+ CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
+ else if (cli_wand->image_info_stack != (Stack *)NULL)
+ CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
+ if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
+ return(argc);
- // if stacks are not empty
- // ThrowConvertException(OptionError,"UnbalancedParenthesis",option,i);
+#if MagickCommandDebug >= 3
+ (void) FormatLocaleFile(stderr,"CLI arg %d Write File: \"%s\"\n",i,option);
+#endif
- /* This is a valid 'do no write' option for a CLI */
+ /* Valid 'do no write' replacement option (instead of "null:") */
if (LocaleCompare(option,"-exit") == 0 )
- return; /* just exit, no image write */
-
- /* If there is an option -- produce an error */
- if (IsCommandOption(option) != MagickFalse)
- /* FUTURE: Better Error - Output Filename not Found */
- MagickExceptionReturn(OptionError,"MissingOutputFilename",option,i);
-
- /* If no images in MagickCLI */
- if ( cli_wand->wand.images == (Image *) NULL )
- {
- /* a "null:" output coder with no images is not an error! */
- if ( LocaleCompare(option,"null:") == 0 )
- return;
- MagickExceptionReturn(OptionError,"NoImagesForFinalWrite",option,i);
- }
+ return(argc); /* just exit, no image write */
+
+ /* If filename looks like an option,
+ Or the common 'end of line' error of a single space.
+ -- produce an error */
+ if (IfMagickTrue(IsCommandOption(option)) ||
+ (option[0] == ' ' && option[1] == '\0') ) {
+ CLIWandException(OptionError,"MissingOutputFilename",option);
+ return(argc);
+ }
-#if 0
- WandListOperatorImages(cli_wand,MagickFalse,"write",option,(const char *)NULL);
-#else
- (void) SyncImagesSettings(cli_wand->wand.image_info,cli_wand->wand.images,
- cli_wand->wand.exception);
- (void) WriteImages(cli_wand->wand.image_info,cli_wand->wand.images,option,
- cli_wand->wand.exception);
-#endif
- return;
+ cli_wand->command=(const OptionInfo *)NULL;
+ CLIOption(cli_wand,"-write",option);
+ return(argc);
}
\f
/*
%
% The format of the MagickImageCommand method is:
%
-% MagickBooleanType MagickImageCommand(ImageInfo *image_info,
-% int argc, char **argv, char **metadata, ExceptionInfo *exception)
+% MagickBooleanType MagickImageCommand(ImageInfo *image_info,int argc,
+% char **argv,char **metadata,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the starting image_info structure
-% (for compatibilty with MagickCommandGenisis())
+% (for compatibilty with MagickCommandGenisis())
%
% o argc: the number of elements in the argument vector.
%
% o argv: A text array containing the command line arguments.
%
-% o metadata: any metadata is returned here.
-% (for compatibilty with MagickCommandGenisis())
+% o metadata: any metadata (for VBS) is returned here.
+% (for compatibilty with MagickCommandGenisis())
%
% o exception: return any errors or warnings in this structure.
%
*/
-static MagickBooleanType MagickUsage(void)
+static void MagickUsage(MagickBooleanType verbose)
{
- printf("Version: %s\n",GetMagickVersion((size_t *) NULL));
- printf("Copyright: %s\n",GetMagickCopyright());
- printf("Features: %s\n\n",GetMagickFeatures());
- printf("\n");
-
- printf("Usage: %s [(options|images) ...] output_image\n", GetClientName());
- printf(" %s -script filename [script args...]\n", GetClientName());
- printf(" ... | %s -script - | ...\n", GetClientName());
- printf("\n");
-
- printf(" For more information on usage, options, examples, and technqiues\n");
- printf(" see the ImageMagick website at\n %s\n", MagickAuthoritativeURL);
- printf(" Or the web pages in ImageMagick Sources\n");
- return(MagickFalse);
+ const char
+ *name;
+
+ size_t
+ len;
+
+ name=GetClientName();
+ len=strlen(name);
+
+ if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
+ /* convert usage */
+ (void) FormatLocaleFile(stdout,
+ "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
+ (void) FormatLocaleFile(stdout,
+ " %s -help | -version | -usage | -list {option}\n\n",name);
+ return;
+ }
+ else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
+ /* magick-script usage */
+ (void) FormatLocaleFile(stdout,
+ "Usage: %s {filename} [ {script_args} ... ]\n",name);
+ }
+ else {
+ /* magick usage */
+ (void) FormatLocaleFile(stdout,
+ "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
+ (void) FormatLocaleFile(stdout,
+ " %s [ {option} | {image} ... ] -script {filename} [ {script_args} ...]\n",
+ name);
+ }
+ (void) FormatLocaleFile(stdout,
+ " %s -help | -version | -usage | -list {option}\n\n",name);
+
+ if (IfMagickFalse(verbose))
+ return;
+
+ (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ "All options are performed in a strict 'as you see them' order\n",
+ "You must read-in images before you can operate on them.\n",
+ "\n",
+ "Magick Script files can use any of the following forms...\n",
+ " #!/path/to/magick -script\n",
+ "or\n",
+ " #!/bin/sh\n",
+ " :; exec magick -script \"$0\" \"$@\"; exit 10\n",
+ " # Magick script from here...\n",
+ "or\n",
+ " #!/usr/bin/env magick-script\n",
+ "The latter two forms do not require the path to the command hard coded.\n",
+ "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n",
+ "\n",
+ "For more information on usage, options, examples, and techniques\n",
+ "see the ImageMagick website at ", MagickAuthoritativeURL);
+
+ return;
}
/*
This is much like the UNIX "cat" command, but for both UNIX and Windows,
however the last argument provides the output filename.
*/
-#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); \
-}
-
static MagickBooleanType ConcatenateImages(int argc,char **argv,
- ExceptionInfo *exception)
+ ExceptionInfo *exception )
{
FILE
*input,
register ssize_t
i;
+ if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
+ ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
+ GetExceptionMessage(errno));
+
output=fopen_utf8(argv[argc-1],"wb");
- if (output == (FILE *) NULL)
- {
- ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
- argv[argc-1]);
- return(MagickFalse);
- }
- for (i=2; i < (ssize_t) (argc-1); i++)
- {
+ if (output == (FILE *) NULL) {
+ ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
+ return(MagickFalse);
+ }
+ for (i=2; i < (ssize_t) (argc-1); i++) {
+#if 0
+ fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
+#endif
input=fopen_utf8(argv[i],"rb");
- if (input == (FILE *) NULL)
- ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
+ if (input == (FILE *) NULL) {
+ ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
+ continue;
+ }
for (c=fgetc(input); c != EOF; c=fgetc(input))
(void) fputc((char) c,output);
(void) fclose(input);
MagickCLI
*cli_wand;
- const char
- *option;
-
- /* Handle special single use options */
- if (argc == 2)
- {
- option=argv[1];
- if ((LocaleCompare("-version",option+1) == 0) ||
- (LocaleCompare("--version",option+1) == 0) )
- {
- (void) FormatLocaleFile(stdout,"Version: %s\n",
- GetMagickVersion((size_t *) NULL));
- (void) FormatLocaleFile(stdout,"Copyright: %s\n",
- GetMagickCopyright());
- (void) FormatLocaleFile(stdout,"Features: %s\n\n",
- GetMagickFeatures());
- return(MagickFalse);
- }
- }
- /* The "magick" command must have at least two arguments */
- if (argc < 3)
- return(MagickUsage());
- ReadCommandlLine(argc,&argv);
+ size_t
+ len;
-#if 0
- /* FUTURE: This does not make sense! Remove it.
- Only a 'image read' needs to expand file name glob patterns
- */
- status=ExpandFilenames(&argc,&argv);
- if (status == MagickFalse)
- ThrowConvertException(ResourceLimitError,"MemoryAllocationFailed",
- GetExceptionMessage(errno));
-#endif
+ assert(image_info != (ImageInfo *)NULL);
- /* Special option (hidden) for delegate usage - no wand needed */
- if (LocaleCompare("-concatenate",argv[1]) == 0)
- return(ConcatenateImages(argc,argv,exception));
+ /* For specific OS command line requirements */
+ ReadCommandlLine(argc,&argv);
/* Initialize special "CLI Wand" to hold images and settings (empty) */
- /* FUTURE: add this to 'operations.c' */
cli_wand=AcquireMagickCLI(image_info,exception);
+ cli_wand->location="Initializing";
+ cli_wand->filename=argv[0];
+ cli_wand->line=1;
- if (LocaleCompare("-script",argv[1]) == 0)
- {
- /* Start processing directly from script, no pre-script options
- Replace wand command name with script name
- */
- GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
- ProcessScriptOptions(cli_wand,argc-2,argv+2);
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+ "\"%s\"",argv[0]);
+
+
+ GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
+ SetClientName(cli_wand->wand.name);
+ ConcatenateMagickString(cli_wand->wand.name,"-CLI",MaxTextExtent);
+
+ len=strlen(argv[0]); /* precaution */
+
+ /* "convert" command - give a "depreciation" warning" */
+ if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
+ cli_wand->process_flags = ConvertCommandOptionFlags;
+ (void) FormatLocaleFile(stderr,"WARNING: %s\n",
+ "The convert is depreciated in IMv7, use \"magick\"\n");
+ }
+
+ /* Special Case: If command name ends with "script" implied "-script" */
+ if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
+ if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
+ GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
+ ProcessScriptOptions(cli_wand,argv[1],argc,argv,2);
+ goto Magick_Command_Cleanup;
}
- else if (LocaleCompare("-list",argv[1]) == 0)
- /* Special option, list information and exit
- FUTURE: this should be a MagickCore option, no wand is actually needed
- */
+ }
- CLISpecialOperator(cli_wand, argv[1]+1, argv[2]);
- else
- /* Processing Command line, assuming output file as last option */
- ProcessCommandOptions(cli_wand,argc-1,argv+1,MagickCommandOptionFlags);
+ /* Special Case: Version Information and Abort */
+ if (argc == 2) {
+ if ((LocaleCompare("-version",argv[1]) == 0) || /* GNU standard option */
+ (LocaleCompare("--version",argv[1]) == 0) ) { /* just version */
+ CLIOption(cli_wand, "-version");
+ goto Magick_Command_Exit;
+ }
+ if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */
+ (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+ "- Special Option \"%s\"", argv[1]);
+ MagickUsage(MagickFalse);
+ goto Magick_Command_Exit;
+ }
+ if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+ "- Special Option \"%s\"", argv[1]);
+ CLIOption(cli_wand, "-version" );
+ MagickUsage(MagickTrue);
+ goto Magick_Command_Exit;
+ }
+ }
+
+ /* not enough arguments -- including -help */
+ if (argc < 3) {
+ (void) FormatLocaleFile(stderr,
+ "Error: Invalid argument or not enough arguments\n\n");
+ MagickUsage(MagickFalse);
+ goto Magick_Command_Exit;
+ }
+
+ /* Special "concatenate option (hidden) for delegate usage */
+ if (LocaleCompare("-concatenate",argv[1]) == 0) {
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+ "- Special Option \"%s\"", argv[1]);
+ ConcatenateImages(argc,argv,exception);
+ goto Magick_Command_Exit;
+ }
+
+ /* List Information and Abort */
+ if (argc == 3 && LocaleCompare("-list",argv[1]) == 0) {
+ CLIOption(cli_wand, argv[1], argv[2]);
+ goto Magick_Command_Exit;
+ }
+
+ /* ------------- */
+ /* The Main Call */
- /* recover original image_info - check we get the right image_info */
+ if (LocaleCompare("-script",argv[1]) == 0) {
+ /* Start processing directly from script, no pre-script options
+ Replace wand command name with script name
+ First argument in the argv array is the script name to read.
+ */
+ GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
+ ProcessScriptOptions(cli_wand,argv[2],argc,argv,3);
+ }
+ else {
+ /* Normal Command Line, assumes output file as last option */
+ ProcessCommandOptions(cli_wand,argc,argv,1);
+ }
+ /* ------------- */
+
+Magick_Command_Cleanup:
+ cli_wand->location="Cleanup";
+ cli_wand->filename=argv[0];
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+ "\"%s\"",argv[0]);
+
+ /* recover original image_info and clean up stacks
+ FUTURE: "-reset stacks" option */
+ while (cli_wand->image_list_stack != (Stack *)NULL)
+ CLIOption(cli_wand,")");
while (cli_wand->image_info_stack != (Stack *)NULL)
- CLISpecialOperator(cli_wand,"}",(const char *)NULL);
+ CLIOption(cli_wand,"}");
+ /* assert we have recovered the original structures */
assert(cli_wand->wand.image_info == image_info);
assert(cli_wand->wand.exception == exception);
/* Handle metadata for ImageMagickObject COM object for Windows VBS */
- if (metadata != (char **) NULL)
- {
- const char
- *format;
-
- char
- *text;
+ if (metadata != (char **) NULL) {
+ const char
+ *format;
+
+ char
+ *text;
+
+ format="%w,%h,%m"; // Get this from image_info Option splaytree
+
+ text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
+ exception);
+ if (text == (char *) NULL)
+ ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
+ "MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
+ else {
+ (void) ConcatenateString(&(*metadata),text);
+ text=DestroyString(text);
+ }
+ }
- format="%w,%h,%m"; // Get this from image_info Option splaytree
+Magick_Command_Exit:
+ cli_wand->location="Exiting";
+ cli_wand->filename=argv[0];
+ if (IfMagickTrue(cli_wand->wand.debug))
+ (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
+ "\"%s\"",argv[0]);
- text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
- exception);
- if (text == (char *) NULL)
- ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
- "MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
- else
- {
- (void) ConcatenateString(&(*metadata),text);
- text=DestroyString(text);
- }
- }
/* Destroy the special CLI Wand */
cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */
cli_wand->wand.exception = (ExceptionInfo *)NULL;
cli_wand=DestroyMagickCLI(cli_wand);
- return((exception->severity > ErrorException) ? MagickFalse : MagickTrue);
+ return(IsMagickTrue(exception->severity > ErrorException));
}