2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M AAA GGGG IIIII CCCC K K %
7 % MM MM A A G I C K K %
8 % M M M AAAAA G GGG I C KKK %
9 % M M A A G G I C K K %
10 % M M A A GGGG IIIII CCCC K K %
18 % Perform "Magick" on Images via the Command Line Interface %
25 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
26 % dedicated to making software imaging solutions freely available. %
28 % You may not use this file except in compliance with the License. You may %
29 % obtain a copy of the License at %
31 % http://www.imagemagick.org/script/license.php %
33 % Unless required by applicable law or agreed to in writing, software %
34 % distributed under the License is distributed on an "AS IS" BASIS, %
35 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
36 % See the License for the specific language governing permissions and %
37 % limitations under the License. %
39 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 % Read CLI arguments, script files, and pipelines, to provide options that
42 % manipulate images from many different formats.
49 #include "MagickWand/studio.h"
50 #include "MagickWand/MagickWand.h"
51 #include "MagickWand/magick-wand-private.h"
52 #include "MagickWand/wandcli.h"
53 #include "MagickWand/wandcli-private.h"
54 #include "MagickWand/operation.h"
55 #include "MagickWand/magick-cli.h"
56 #include "MagickWand/script-token.h"
57 #include "MagickCore/utility-private.h"
58 #include "MagickCore/exception-private.h"
59 #include "MagickCore/version.h"
63 3 - show option details (better to use -debug Command now)
64 5 - image counts (after option runs)
66 #define MagickCommandDebug 0
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74 + P r o c e s s S c r i p t O p t i o n s %
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 % ProcessScriptOptions() reads options and processes options as they are
81 % found in the given file, or pipeline. The filename to open and read
82 % options is given as the 'index' argument of the argument array given.
84 % Other arguments following index may be read by special script options
85 % as settings (strings), images, or as operations to be processed in various
86 % ways. How they are treated is up to the script being processed.
88 % Note that a script not 'return' to the command line processing, nor can
89 % they call (and return from) other scripts. At least not at this time.
91 % There are no 'ProcessOptionFlags' control flags at this time.
93 % The format of the ProcessScriptOptions method is:
95 % void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
96 % int argc,char **argv,int index)
98 % A description of each parameter follows:
100 % o cli_wand: the main CLI Wand to use.
102 % o filename: the filename of script to process
104 % o argc: the number of elements in the argument vector. (optional)
106 % o argv: A text array containing the command line arguments. (optional)
108 % o index: offset of next argment in argv (script arguments) (optional)
111 WandExport void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
112 int argc,char **argv,int index)
128 assert(filename != (char *)NULL ); /* at least one argument - script name */
129 assert(cli_wand != (MagickCLI *) NULL);
130 assert(cli_wand->signature == WandSignature);
131 if (IfMagickTrue(cli_wand->wand.debug))
132 (void) LogMagickEvent(CommandEvent,GetMagickModule(),
133 "Processing script \"%s\"", filename);
135 /* open file script or stream, and set up tokenizer */
136 token_info = AcquireScriptTokenInfo(filename);
137 if (token_info == (ScriptTokenInfo *) NULL) {
138 CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",filename);
142 /* define the error location string for use in exceptions
143 order of localtion format escapes: filename, line, column */
144 cli_wand->location="in \"%s\" at line %u,column %u";
145 if ( LocaleCompare("-", filename) == 0 )
146 cli_wand->filename="stdin";
148 cli_wand->filename=filename;
150 /* Process Options from Script */
151 option = arg1 = arg2 = (char*)NULL;
152 DisableMSCWarning(4127)
156 { MagickBooleanType status = GetScriptToken(token_info);
157 cli_wand->line=token_info->token_line;
158 cli_wand->column=token_info->token_column;
159 if( IfMagickFalse(status) )
160 break; /* error or end of options */
163 do { /* use break to loop to exception handler and loop */
165 /* save option details */
166 CloneString(&option,token_info->token);
168 /* get option, its argument count, and option type */
169 cli_wand->command = GetCommandOptionInfo(option);
170 count=cli_wand->command->type;
171 option_type=(CommandOptionFlags) cli_wand->command->flags;
173 (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n",
174 cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic );
177 /* handle a undefined option - image read - always for "magick-script" */
178 if ( option_type == UndefinedOptionFlag ||
179 (option_type & NonMagickOptionFlag) != 0 ) {
180 #if MagickCommandDebug >= 3
181 (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n",
182 cli_wand->line, cli_wand->line, option);
184 if ( IfMagickFalse(IsCommandOption(option))) {
185 /* non-option -- treat as a image read */
186 cli_wand->command=(const OptionInfo *)NULL;
187 CLIOption(cli_wand,"-read",option);
188 break; /* next option */
190 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
191 break; /* next option */
195 if( IfMagickFalse(GetScriptToken(token_info)) )
196 CLIWandException(OptionFatalError,"MissingArgument",option);
197 CloneString(&arg1,token_info->token);
200 CloneString(&arg1,(char *)NULL);
203 if( IfMagickFalse(GetScriptToken(token_info)) )
204 CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option);
205 CloneString(&arg2,token_info->token);
208 CloneString(&arg2,(char *)NULL);
213 #if MagickCommandDebug >= 3
214 (void) FormatLocaleFile(stderr,
215 "Script %u,%u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
216 cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2);
218 /* Hard Deprecated Options, no code to execute - error */
219 if ( (option_type & DeprecateOptionFlag) != 0 ) {
220 CLIWandException(OptionError,"DeprecatedOptionNoCode",option);
221 break; /* next option */
224 /* MagickCommandGenesis() options have no place in a magick script */
225 if ( (option_type & GenesisOptionFlag) != 0 ) {
226 CLIWandException(OptionError,"InvalidUseOfOption",option);
227 break; /* next option */
230 /* handle any special 'script' options */
231 if ( (option_type & SpecialOptionFlag) != 0 ) {
232 if ( LocaleCompare(option,"-exit") == 0 ) {
233 goto loop_exit; /* break out of loop - return from script */
235 if ( LocaleCompare(option,"-script") == 0 ) {
236 /* FUTURE: call new script from this script - error for now */
237 CLIWandException(OptionError,"InvalidUseOfOption",option);
238 break; /* next option */
240 /* FUTURE: handle special script-argument options here */
241 /* handle any other special operators now */
242 CLIWandException(OptionError,"InvalidUseOfOption",option);
243 break; /* next option */
246 /* Process non-specific Option */
247 CLIOption(cli_wand, option, arg1, arg2);
249 DisableMSCWarning(4127)
250 } while (0); /* break block to next option */
253 #if MagickCommandDebug >= 5
254 fprintf(stderr, "Script Image Count = %ld\n",
255 GetImageListLength(cli_wand->wand.images) );
257 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
258 break; /* exit loop */
262 Loop exit - check for some tokenization error
265 #if MagickCommandDebug >= 3
266 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
268 switch( token_info->status ) {
271 if (cli_wand->image_list_stack != (Stack *)NULL)
272 CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
273 else if (cli_wand->image_info_stack != (Stack *)NULL)
274 CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
276 case TokenStatusBadQuotes:
277 /* Ensure last token has a sane length for error report */
278 if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
279 token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
280 token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
281 token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
282 token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
284 CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
287 case TokenStatusMemoryFailed:
288 CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
290 case TokenStatusBinary:
291 CLIWandException(OptionFatalError,"ScriptIsBinary","");
294 if (IfMagickTrue(cli_wand->wand.debug))
295 (void) LogMagickEvent(CommandEvent,GetMagickModule(),
296 "Script End \"%s\"", filename);
299 token_info = DestroyScriptTokenInfo(token_info);
301 CloneString(&option,(char *)NULL);
302 CloneString(&arg1,(char *)NULL);
303 CloneString(&arg2,(char *)NULL);
309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313 + P r o c e s s C o m m a n d O p t i o n s %
317 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319 % ProcessCommandOptions() reads and processes arguments in the given
320 % command line argument array. The 'index' defines where in the array we
321 % should begin processing
323 % The 'process_flags' can be used to control and limit option processing.
324 % For example, to only process one option, or how unknown and special options
325 % are to be handled, and if the last argument in array is to be regarded as a
326 % final image write argument (filename or special coder).
328 % The format of the ProcessCommandOptions method is:
330 % int ProcessCommandOptions(MagickCLI *cli_wand,
331 % int argc,char **argv,int index)
333 % A description of each parameter follows:
335 % o cli_wand: the main CLI Wand to use.
337 % o argc: the number of elements in the argument vector.
339 % o argv: A text array containing the command line arguments.
341 % o process_flags: What type of arguments will be processed, ignored
344 % o index: index in the argv array to start processing from
346 % The function returns the index ot the next option to be processed. This
347 % is really only releven if process_flags contains a ProcessOneOptionOnly
351 WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc,
352 char **argv, int index )
367 assert(argc>=index); /* you may have no arguments left! */
368 assert(argv != (char **)NULL);
369 assert(argv[index] != (char *)NULL);
370 assert(argv[argc-1] != (char *)NULL);
371 assert(cli_wand != (MagickCLI *) NULL);
372 assert(cli_wand->signature == WandSignature);
374 /* define the error location string for use in exceptions
375 order of localtion format escapes: filename, line, column */
376 cli_wand->location="at %s arg %u";
377 cli_wand->filename="CLI";
378 cli_wand->line=index; /* note first argument we will process */
380 if (IfMagickTrue(cli_wand->wand.debug))
381 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
382 "- Starting (\"%s\")", argv[index]);
385 if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
386 end--; /* the last arument is an implied write, do not process directly */
388 for (i=index; i < end; i += count +1) {
389 /* Finished processing one option? */
390 if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
393 do { /* use break to loop to exception handler and loop */
396 cli_wand->line=i; /* note the argument for this option */
398 /* get option, its argument count, and option type */
399 cli_wand->command = GetCommandOptionInfo(argv[i]);
400 count=cli_wand->command->type;
401 option_type=(CommandOptionFlags) cli_wand->command->flags;
403 (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
404 i, argv[i], cli_wand->command->mnemonic );
407 if ( option_type == UndefinedOptionFlag ||
408 (option_type & NonMagickOptionFlag) != 0 ) {
409 #if MagickCommandDebug >= 3
410 (void) FormatLocaleFile(stderr, "CLI arg %d Non-Option: \"%s\"\n",
413 if ( IfMagickFalse(IsCommandOption(option)) ) {
414 if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) {
415 /* non-option -- treat as a image read */
416 cli_wand->command=(const OptionInfo *)NULL;
417 CLIOption(cli_wand,"-read",option);
418 break; /* next option */
421 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
422 break; /* next option */
425 if ( ((option_type & SpecialOptionFlag) != 0 ) &&
426 ((cli_wand->process_flags & ProcessScriptOption) != 0) &&
427 (LocaleCompare(option,"-script") == 0) ) {
428 /* Call Script from CLI, with a filename as a zeroth argument.
429 NOTE: -script may need to use the 'implict write filename' argument
430 so it must be handled specially to prevent a 'missing argument' error.
432 if ( (i+count) >= argc )
433 CLIWandException(OptionFatalError,"MissingArgument",option);
434 ProcessScriptOptions(cli_wand,argv[i+1],argc,argv,i+count);
435 return(argc); /* Script does not return to CLI -- Yet */
436 /* FUTURE: when it does, their may be no write arg! */
439 if ((i+count) >= end ) {
440 CLIWandException(OptionFatalError,"MissingArgument",option);
441 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
443 break; /* next option - not that their is any! */
446 arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL;
447 arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL;
450 Process Known Options
452 #if MagickCommandDebug >= 3
453 (void) FormatLocaleFile(stderr,
454 "CLI arg %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
455 i,option,count,option_type,arg1,arg2);
457 /* ignore 'genesis options' in command line args */
458 if ( (option_type & GenesisOptionFlag) != 0 )
459 break; /* next option */
461 /* Handle any special options for CLI (-script handled above) */
462 if ( (option_type & SpecialOptionFlag) != 0 ) {
463 if ( (cli_wand->process_flags & ProcessExitOption) != 0
464 && LocaleCompare(option,"-exit") == 0 )
466 break; /* next option */
469 /* Process standard image option */
470 CLIOption(cli_wand, option, arg1, arg2);
472 DisableMSCWarning(4127)
473 } while (0); /* break block to next option */
476 #if MagickCommandDebug >= 5
477 (void) FormatLocaleFile(stderr, "CLI-post Image Count = %ld\n",
478 (long) GetImageListLength(cli_wand->wand.images) );
480 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
485 if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
486 return(end); /* no implied write -- just return to caller */
488 assert(end==argc-1); /* end should not include last argument */
491 Implicit Write of images to final CLI argument
496 /* check that stacks are empty - or cause exception */
497 if (cli_wand->image_list_stack != (Stack *)NULL)
498 CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
499 else if (cli_wand->image_info_stack != (Stack *)NULL)
500 CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
501 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
504 #if MagickCommandDebug >= 3
505 (void) FormatLocaleFile(stderr,"CLI arg %d Write File: \"%s\"\n",i,option);
508 /* Valid 'do no write' replacement option (instead of "null:") */
509 if (LocaleCompare(option,"-exit") == 0 )
510 return(argc); /* just exit, no image write */
512 /* If filename looks like an option,
513 Or the common 'end of line' error of a single space.
514 -- produce an error */
515 if (IfMagickTrue(IsCommandOption(option)) ||
516 (option[0] == ' ' && option[1] == '\0') ) {
517 CLIWandException(OptionError,"MissingOutputFilename",option);
521 cli_wand->command=(const OptionInfo *)NULL;
522 CLIOption(cli_wand,"-write",option);
527 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
531 + M a g i c k I m a g e C o m m a n d %
535 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
537 % MagickImageCommand() Handle special use CLI arguments and prepare a
538 % CLI MagickCLI to process the command line or directly specified script.
540 % This is essentualy interface function between the MagickCore library
541 % initialization function MagickCommandGenesis(), and the option MagickCLI
542 % processing functions ProcessCommandOptions() or ProcessScriptOptions()
544 % The format of the MagickImageCommand method is:
546 % MagickBooleanType MagickImageCommand(ImageInfo *image_info,int argc,
547 % char **argv,char **metadata,ExceptionInfo *exception)
549 % A description of each parameter follows:
551 % o image_info: the starting image_info structure
552 % (for compatibilty with MagickCommandGenisis())
554 % o argc: the number of elements in the argument vector.
556 % o argv: A text array containing the command line arguments.
558 % o metadata: any metadata (for VBS) is returned here.
559 % (for compatibilty with MagickCommandGenisis())
561 % o exception: return any errors or warnings in this structure.
565 static void MagickUsage(MagickBooleanType verbose)
573 name=GetClientName();
576 if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
578 (void) FormatLocaleFile(stdout,
579 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
580 (void) FormatLocaleFile(stdout,
581 " %s -help | -version | -usage | -list {option}\n\n",name);
584 else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
585 /* magick-script usage */
586 (void) FormatLocaleFile(stdout,
587 "Usage: %s {filename} [ {script_args} ... ]\n",name);
591 (void) FormatLocaleFile(stdout,
592 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
593 (void) FormatLocaleFile(stdout,
594 " %s [ {option} | {image} ... ] -script {filename} [ {script_args} ...]\n",
597 (void) FormatLocaleFile(stdout,
598 " %s -help | -version | -usage | -list {option}\n\n",name);
600 if (IfMagickFalse(verbose))
603 (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
604 "All options are performed in a strict 'as you see them' order\n",
605 "You must read-in images before you can operate on them.\n",
607 "Magick Script files can use any of the following forms...\n",
608 " #!/path/to/magick -script\n",
611 " :; exec magick -script \"$0\" \"$@\"; exit 10\n",
612 " # Magick script from here...\n",
614 " #!/usr/bin/env magick-script\n",
615 "The latter two forms do not require the path to the command hard coded.\n",
616 "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n",
618 "For more information on usage, options, examples, and techniques\n",
619 "see the ImageMagick website at ", MagickAuthoritativeURL);
625 Concatanate given file arguments to the given output argument.
626 Used for a special -concatenate option used for specific 'delegates'.
627 The option is not formally documented.
629 magick -concatenate files... output
631 This is much like the UNIX "cat" command, but for both UNIX and Windows,
632 however the last argument provides the output filename.
634 static MagickBooleanType ConcatenateImages(int argc,char **argv,
635 ExceptionInfo *exception )
647 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
648 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
649 GetExceptionMessage(errno));
651 output=fopen_utf8(argv[argc-1],"wb");
652 if (output == (FILE *) NULL) {
653 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
656 for (i=2; i < (ssize_t) (argc-1); i++) {
658 fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
660 input=fopen_utf8(argv[i],"rb");
661 if (input == (FILE *) NULL) {
662 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
665 for (c=fgetc(input); c != EOF; c=fgetc(input))
666 (void) fputc((char) c,output);
667 (void) fclose(input);
668 (void) remove_utf8(argv[i]);
670 (void) fclose(output);
674 WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,
675 int argc,char **argv,char **metadata,ExceptionInfo *exception)
683 assert(image_info != (ImageInfo *)NULL);
685 /* For specific OS command line requirements */
686 ReadCommandlLine(argc,&argv);
688 /* Initialize special "CLI Wand" to hold images and settings (empty) */
689 cli_wand=AcquireMagickCLI(image_info,exception);
690 cli_wand->location="Initializing";
691 cli_wand->filename=argv[0];
694 if (IfMagickTrue(cli_wand->wand.debug))
695 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
699 GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
700 SetClientName(cli_wand->wand.name);
701 ConcatenateMagickString(cli_wand->wand.name,"-CLI",MaxTextExtent);
703 len=strlen(argv[0]); /* precaution */
705 /* "convert" command - give a "deprecated" warning" */
706 if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
707 cli_wand->process_flags = ConvertCommandOptionFlags;
708 (void) FormatLocaleFile(stderr,"WARNING: %s\n",
709 "The convert command is deprecated in IMv7, use \"magick\"\n");
712 /* Special Case: If command name ends with "script" implied "-script" */
713 if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
714 if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
715 GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
716 ProcessScriptOptions(cli_wand,argv[1],argc,argv,2);
717 goto Magick_Command_Cleanup;
721 /* Special Case: Version Information and Abort */
723 if ((LocaleCompare("-version",argv[1]) == 0) || /* GNU standard option */
724 (LocaleCompare("--version",argv[1]) == 0) ) { /* just version */
725 CLIOption(cli_wand, "-version");
726 goto Magick_Command_Exit;
728 if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */
729 (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */
730 if (IfMagickTrue(cli_wand->wand.debug))
731 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
732 "- Special Option \"%s\"", argv[1]);
733 MagickUsage(MagickFalse);
734 goto Magick_Command_Exit;
736 if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */
737 if (IfMagickTrue(cli_wand->wand.debug))
738 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
739 "- Special Option \"%s\"", argv[1]);
740 CLIOption(cli_wand, "-version" );
741 MagickUsage(MagickTrue);
742 goto Magick_Command_Exit;
746 /* not enough arguments -- including -help */
748 (void) FormatLocaleFile(stderr,
749 "Error: Invalid argument or not enough arguments\n\n");
750 MagickUsage(MagickFalse);
751 goto Magick_Command_Exit;
754 /* Special "concatenate option (hidden) for delegate usage */
755 if (LocaleCompare("-concatenate",argv[1]) == 0) {
756 if (IfMagickTrue(cli_wand->wand.debug))
757 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
758 "- Special Option \"%s\"", argv[1]);
759 ConcatenateImages(argc,argv,exception);
760 goto Magick_Command_Exit;
763 /* List Information and Abort */
764 if (argc == 3 && LocaleCompare("-list",argv[1]) == 0) {
765 CLIOption(cli_wand, argv[1], argv[2]);
766 goto Magick_Command_Exit;
772 if (LocaleCompare("-script",argv[1]) == 0) {
773 /* Start processing directly from script, no pre-script options
774 Replace wand command name with script name
775 First argument in the argv array is the script name to read.
777 GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
778 ProcessScriptOptions(cli_wand,argv[2],argc,argv,3);
781 /* Normal Command Line, assumes output file as last option */
782 ProcessCommandOptions(cli_wand,argc,argv,1);
786 Magick_Command_Cleanup:
787 cli_wand->location="Cleanup";
788 cli_wand->filename=argv[0];
789 if (IfMagickTrue(cli_wand->wand.debug))
790 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
793 /* recover original image_info and clean up stacks
794 FUTURE: "-reset stacks" option */
795 while (cli_wand->image_list_stack != (Stack *)NULL)
796 CLIOption(cli_wand,")");
797 while (cli_wand->image_info_stack != (Stack *)NULL)
798 CLIOption(cli_wand,"}");
800 /* assert we have recovered the original structures */
801 assert(cli_wand->wand.image_info == image_info);
802 assert(cli_wand->wand.exception == exception);
804 /* Handle metadata for ImageMagickObject COM object for Windows VBS */
805 if (metadata != (char **) NULL) {
812 format="%w,%h,%m"; // Get this from image_info Option splaytree
814 text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
816 if (text == (char *) NULL)
817 ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
818 "MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
820 (void) ConcatenateString(&(*metadata),text);
821 text=DestroyString(text);
826 cli_wand->location="Exiting";
827 cli_wand->filename=argv[0];
828 if (IfMagickTrue(cli_wand->wand.debug))
829 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
832 /* Destroy the special CLI Wand */
833 cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */
834 cli_wand->wand.exception = (ExceptionInfo *)NULL;
835 cli_wand=DestroyMagickCLI(cli_wand);
837 return(IsMagickTrue(exception->severity > ErrorException));