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-2015 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 == MagickWandSignature);
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 (status == MagickFalse)
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);
248 (void) fflush(stdout);
249 (void) fflush(stderr);
251 DisableMSCWarning(4127)
252 } while (0); /* break block to next option */
255 #if MagickCommandDebug >= 5
256 fprintf(stderr, "Script Image Count = %ld\n",
257 GetImageListLength(cli_wand->wand.images) );
259 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
260 break; /* exit loop */
264 Loop exit - check for some tokenization error
267 #if MagickCommandDebug >= 3
268 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
270 switch( token_info->status ) {
273 if (cli_wand->image_list_stack != (Stack *) NULL)
274 CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
275 else if (cli_wand->image_info_stack != (Stack *) NULL)
276 CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
278 case TokenStatusBadQuotes:
279 /* Ensure last token has a sane length for error report */
280 if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
281 token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
282 token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
283 token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
284 token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
286 CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
289 case TokenStatusMemoryFailed:
290 CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
292 case TokenStatusBinary:
293 CLIWandException(OptionFatalError,"ScriptIsBinary","");
296 (void) fflush(stdout);
297 (void) fflush(stderr);
298 if (IfMagickTrue(cli_wand->wand.debug))
299 (void) LogMagickEvent(CommandEvent,GetMagickModule(),
300 "Script End \"%s\"", filename);
303 token_info = DestroyScriptTokenInfo(token_info);
305 CloneString(&option,(char *) NULL);
306 CloneString(&arg1,(char *) NULL);
307 CloneString(&arg2,(char *) NULL);
313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317 + P r o c e s s C o m m a n d O p t i o n s %
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
323 % ProcessCommandOptions() reads and processes arguments in the given
324 % command line argument array. The 'index' defines where in the array we
325 % should begin processing
327 % The 'process_flags' can be used to control and limit option processing.
328 % For example, to only process one option, or how unknown and special options
329 % are to be handled, and if the last argument in array is to be regarded as a
330 % final image write argument (filename or special coder).
332 % The format of the ProcessCommandOptions method is:
334 % int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
337 % A description of each parameter follows:
339 % o cli_wand: the main CLI Wand to use.
341 % o argc: the number of elements in the argument vector.
343 % o argv: A text array containing the command line arguments.
345 % o process_flags: What type of arguments will be processed, ignored
348 % o index: index in the argv array to start processing from
350 % The function returns the index ot the next option to be processed. This
351 % is really only releven if process_flags contains a ProcessOneOptionOnly
355 WandExport int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
371 assert(argc>=index); /* you may have no arguments left! */
372 assert(argv != (char **) NULL);
373 assert(argv[index] != (char *) NULL);
374 assert(argv[argc-1] != (char *) NULL);
375 assert(cli_wand != (MagickCLI *) NULL);
376 assert(cli_wand->signature == MagickWandSignature);
378 /* define the error location string for use in exceptions
379 order of localtion format escapes: filename, line, column */
380 cli_wand->location="at %s arg %u";
381 cli_wand->filename="CLI";
382 cli_wand->line=index; /* note first argument we will process */
384 if (IfMagickTrue(cli_wand->wand.debug))
385 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
386 "- Starting (\"%s\")", argv[index]);
389 if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
390 end--; /* the last arument is an implied write, do not process directly */
392 for (i=index; i < end; i += count +1) {
393 /* Finished processing one option? */
394 if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
397 do { /* use break to loop to exception handler and loop */
400 cli_wand->line=i; /* note the argument for this option */
402 /* get option, its argument count, and option type */
403 cli_wand->command = GetCommandOptionInfo(argv[i]);
404 count=cli_wand->command->type;
405 option_type=(CommandOptionFlags) cli_wand->command->flags;
407 (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
408 i, argv[i], cli_wand->command->mnemonic );
411 if ( option_type == UndefinedOptionFlag ||
412 (option_type & NonMagickOptionFlag) != 0 ) {
413 #if MagickCommandDebug >= 3
414 (void) FormatLocaleFile(stderr, "CLI arg %d Non-Option: \"%s\"\n",
417 if ( IfMagickFalse(IsCommandOption(option)) ) {
418 if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) {
419 /* non-option -- treat as a image read */
420 cli_wand->command=(const OptionInfo *) NULL;
421 CLIOption(cli_wand,"-read",option);
422 break; /* next option */
425 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
426 break; /* next option */
429 if ( ((option_type & SpecialOptionFlag) != 0 ) &&
430 ((cli_wand->process_flags & ProcessScriptOption) != 0) &&
431 (LocaleCompare(option,"-script") == 0) ) {
432 /* Call Script from CLI, with a filename as a zeroth argument.
433 NOTE: -script may need to use the 'implict write filename' argument
434 so it must be handled specially to prevent a 'missing argument' error.
436 if ( (i+count) >= argc )
437 CLIWandException(OptionFatalError,"MissingArgument",option);
438 ProcessScriptOptions(cli_wand,argv[i+1],argc,argv,i+count);
439 return(argc); /* Script does not return to CLI -- Yet */
440 /* FUTURE: when it does, their may be no write arg! */
443 if ((i+count) >= end ) {
444 CLIWandException(OptionFatalError,"MissingArgument",option);
445 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
447 break; /* next option - not that their is any! */
450 arg1 = ( count >= 1 ) ? argv[i+1] : (char *) NULL;
451 arg2 = ( count >= 2 ) ? argv[i+2] : (char *) NULL;
454 Process Known Options
456 #if MagickCommandDebug >= 3
457 (void) FormatLocaleFile(stderr,
458 "CLI arg %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
459 i,option,count,option_type,arg1,arg2);
461 /* ignore 'genesis options' in command line args */
462 if ( (option_type & GenesisOptionFlag) != 0 )
463 break; /* next option */
465 /* Handle any special options for CLI (-script handled above) */
466 if ( (option_type & SpecialOptionFlag) != 0 ) {
467 if ( (cli_wand->process_flags & ProcessExitOption) != 0
468 && LocaleCompare(option,"-exit") == 0 )
470 break; /* next option */
473 /* Process standard image option */
474 CLIOption(cli_wand, option, arg1, arg2);
476 DisableMSCWarning(4127)
477 } while (0); /* break block to next option */
480 #if MagickCommandDebug >= 5
481 (void) FormatLocaleFile(stderr, "CLI-post Image Count = %ld\n",
482 (long) GetImageListLength(cli_wand->wand.images) );
484 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
489 if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
490 return(end); /* no implied write -- just return to caller */
492 assert(end==argc-1); /* end should not include last argument */
495 Implicit Write of images to final CLI argument
500 /* check that stacks are empty - or cause exception */
501 if (cli_wand->image_list_stack != (Stack *) NULL)
502 CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
503 else if (cli_wand->image_info_stack != (Stack *) NULL)
504 CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
505 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
508 #if MagickCommandDebug >= 3
509 (void) FormatLocaleFile(stderr,"CLI arg %d Write File: \"%s\"\n",i,option);
512 /* Valid 'do no write' replacement option (instead of "null:") */
513 if (LocaleCompare(option,"-exit") == 0 )
514 return(argc); /* just exit, no image write */
516 /* If filename looks like an option,
517 Or the common 'end of line' error of a single space.
518 -- produce an error */
519 if (IfMagickTrue(IsCommandOption(option)) ||
520 (option[0] == ' ' && option[1] == '\0') ) {
521 CLIWandException(OptionError,"MissingOutputFilename",option);
525 cli_wand->command=(const OptionInfo *) NULL;
526 CLIOption(cli_wand,"-write",option);
531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
535 + M a g i c k I m a g e C o m m a n d %
539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
541 % MagickImageCommand() Handle special use CLI arguments and prepare a
542 % CLI MagickCLI to process the command line or directly specified script.
544 % This is essentualy interface function between the MagickCore library
545 % initialization function MagickCommandGenesis(), and the option MagickCLI
546 % processing functions ProcessCommandOptions() or ProcessScriptOptions()
548 % The format of the MagickImageCommand method is:
550 % MagickBooleanType MagickImageCommand(ImageInfo *image_info,int argc,
551 % char **argv,char **metadata,ExceptionInfo *exception)
553 % A description of each parameter follows:
555 % o image_info: the starting image_info structure
556 % (for compatibilty with MagickCommandGenisis())
558 % o argc: the number of elements in the argument vector.
560 % o argv: A text array containing the command line arguments.
562 % o metadata: any metadata (for VBS) is returned here.
563 % (for compatibilty with MagickCommandGenisis())
565 % o exception: return any errors or warnings in this structure.
569 static void MagickUsage(MagickBooleanType verbose)
577 name=GetClientName();
580 if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
582 (void) FormatLocaleFile(stdout,
583 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
584 (void) FormatLocaleFile(stdout,
585 " %s -help | -version | -usage | -list {option}\n\n",name);
588 else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
589 /* magick-script usage */
590 (void) FormatLocaleFile(stdout,
591 "Usage: %s {filename} [ {script_args} ... ]\n",name);
595 (void) FormatLocaleFile(stdout,
596 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
597 (void) FormatLocaleFile(stdout,
598 " %s [ {option} | {image} ... ] -script {filename} [ {script_args} ...]\n",
601 (void) FormatLocaleFile(stdout,
602 " %s -help | -version | -usage | -list {option}\n\n",name);
604 if (IfMagickFalse(verbose))
607 (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
608 "All options are performed in a strict 'as you see them' order\n",
609 "You must read-in images before you can operate on them.\n",
611 "Magick Script files can use any of the following forms...\n",
612 " #!/path/to/magick -script\n",
615 " :; exec magick -script \"$0\" \"$@\"; exit 10\n",
616 " # Magick script from here...\n",
618 " #!/usr/bin/env magick-script\n",
619 "The latter two forms do not require the path to the command hard coded.\n",
620 "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n",
622 "For more information on usage, options, examples, and techniques\n",
623 "see the ImageMagick website at ", MagickAuthoritativeURL);
629 Concatanate given file arguments to the given output argument.
630 Used for a special -concatenate option used for specific 'delegates'.
631 The option is not formally documented.
633 magick -concatenate files... output
635 This is much like the UNIX "cat" command, but for both UNIX and Windows,
636 however the last argument provides the output filename.
638 static MagickBooleanType ConcatenateImages(int argc,char **argv,
639 ExceptionInfo *exception )
651 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
652 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
653 GetExceptionMessage(errno));
655 output=fopen_utf8(argv[argc-1],"wb");
656 if (output == (FILE *) NULL) {
657 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
660 for (i=2; i < (ssize_t) (argc-1); i++) {
662 fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
664 input=fopen_utf8(argv[i],"rb");
665 if (input == (FILE *) NULL) {
666 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
669 for (c=fgetc(input); c != EOF; c=fgetc(input))
670 (void) fputc((char) c,output);
671 (void) fclose(input);
672 (void) remove_utf8(argv[i]);
674 (void) fclose(output);
678 WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,int argc,
679 char **argv,char **metadata,ExceptionInfo *exception)
687 assert(image_info != (ImageInfo *) NULL);
689 /* For specific OS command line requirements */
690 ReadCommandlLine(argc,&argv);
692 /* Initialize special "CLI Wand" to hold images and settings (empty) */
693 cli_wand=AcquireMagickCLI(image_info,exception);
694 cli_wand->location="Initializing";
695 cli_wand->filename=argv[0];
698 if (IfMagickTrue(cli_wand->wand.debug))
699 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
703 GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
704 SetClientName(cli_wand->wand.name);
705 ConcatenateMagickString(cli_wand->wand.name,"-CLI",MagickPathExtent);
707 len=strlen(argv[0]); /* precaution */
709 /* "convert" command - give a "deprecated" warning" */
710 if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
711 cli_wand->process_flags = ConvertCommandOptionFlags;
712 (void) FormatLocaleFile(stderr,"WARNING: %s\n",
713 "The convert command is deprecated in IMv7, use \"magick\"\n");
716 /* Special Case: If command name ends with "script" implied "-script" */
717 if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
718 if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
719 GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
720 ProcessScriptOptions(cli_wand,argv[1],argc,argv,2);
721 goto Magick_Command_Cleanup;
725 /* Special Case: Version Information and Abort */
727 if ((LocaleCompare("-version",argv[1]) == 0) || /* GNU standard option */
728 (LocaleCompare("--version",argv[1]) == 0) ) { /* just version */
729 CLIOption(cli_wand, "-version");
730 goto Magick_Command_Exit;
732 if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */
733 (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */
734 if (IfMagickTrue(cli_wand->wand.debug))
735 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
736 "- Special Option \"%s\"", argv[1]);
737 MagickUsage(MagickFalse);
738 goto Magick_Command_Exit;
740 if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */
741 if (IfMagickTrue(cli_wand->wand.debug))
742 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
743 "- Special Option \"%s\"", argv[1]);
744 CLIOption(cli_wand, "-version" );
745 MagickUsage(MagickTrue);
746 goto Magick_Command_Exit;
750 /* not enough arguments -- including -help */
752 (void) FormatLocaleFile(stderr,
753 "Error: Invalid argument or not enough arguments\n\n");
754 MagickUsage(MagickFalse);
755 goto Magick_Command_Exit;
758 /* Special "concatenate option (hidden) for delegate usage */
759 if (LocaleCompare("-concatenate",argv[1]) == 0) {
760 if (IfMagickTrue(cli_wand->wand.debug))
761 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
762 "- Special Option \"%s\"", argv[1]);
763 ConcatenateImages(argc,argv,exception);
764 goto Magick_Command_Exit;
767 /* List Information and Abort */
768 if (argc == 3 && LocaleCompare("-list",argv[1]) == 0) {
769 CLIOption(cli_wand, argv[1], argv[2]);
770 goto Magick_Command_Exit;
776 if (LocaleCompare("-script",argv[1]) == 0) {
777 /* Start processing directly from script, no pre-script options
778 Replace wand command name with script name
779 First argument in the argv array is the script name to read.
781 GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
782 ProcessScriptOptions(cli_wand,argv[2],argc,argv,3);
785 /* Normal Command Line, assumes output file as last option */
786 ProcessCommandOptions(cli_wand,argc,argv,1);
790 Magick_Command_Cleanup:
791 cli_wand->location="Cleanup";
792 cli_wand->filename=argv[0];
793 if (IfMagickTrue(cli_wand->wand.debug))
794 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
797 /* recover original image_info and clean up stacks
798 FUTURE: "-reset stacks" option */
799 while (cli_wand->image_list_stack != (Stack *) NULL)
800 CLIOption(cli_wand,")");
801 while (cli_wand->image_info_stack != (Stack *) NULL)
802 CLIOption(cli_wand,"}");
804 /* assert we have recovered the original structures */
805 assert(cli_wand->wand.image_info == image_info);
806 assert(cli_wand->wand.exception == exception);
808 /* Handle metadata for ImageMagickObject COM object for Windows VBS */
809 if (metadata != (char **) NULL) {
816 format="%w,%h,%m"; // Get this from image_info Option splaytree
818 text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
820 if (text == (char *) NULL)
821 ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
822 "MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
824 (void) ConcatenateString(&(*metadata),text);
825 text=DestroyString(text);
830 cli_wand->location="Exiting";
831 cli_wand->filename=argv[0];
832 if (IfMagickTrue(cli_wand->wand.debug))
833 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
836 /* Destroy the special CLI Wand */
837 cli_wand->wand.image_info = (ImageInfo *) NULL; /* not these */
838 cli_wand->wand.exception = (ExceptionInfo *) NULL;
839 cli_wand=DestroyMagickCLI(cli_wand);
841 return(exception->severity < ErrorException ? MagickTrue : MagickFalse);