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-2012 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"
62 3 - option type details
63 9 - output options/artifacts/propertys
65 #define MagickCommandDebug 0
67 #if MagickCommandDebug >= 9
69 Temporary Debugging Information
70 FUTURE: these should be able to be printed out using 'percent escapes'
71 Actually 'Properities' can already be output with "%[*]"
73 static void OutputOptions(ImageInfo *image_info)
79 (void) FormatLocaleFile(stderr," Global Options:\n");
80 ResetImageOptionIterator(image_info);
81 while ((option=GetNextImageOption(image_info)) != (const char *) NULL ) {
82 (void) FormatLocaleFile(stderr," %s: ",option);
83 value=GetImageOption(image_info,option);
84 if (value != (const char *) NULL)
85 (void) FormatLocaleFile(stderr,"%s\n",value);
87 ResetImageOptionIterator(image_info);
90 static void OutputArtifacts(Image *image)
96 (void) FormatLocaleFile(stderr," Image Artifacts:\n");
97 ResetImageArtifactIterator(image);
98 while ((artifact=GetNextImageArtifact(image)) != (const char *) NULL ) {
99 (void) FormatLocaleFile(stderr," %s: ",artifact);
100 value=GetImageArtifact(image,artifact);
101 if (value != (const char *) NULL)
102 (void) FormatLocaleFile(stderr,"%s\n",value);
104 ResetImageArtifactIterator(image);
107 static void OutputProperties(Image *image,ExceptionInfo *exception)
113 (void) FormatLocaleFile(stderr," Image Properity:\n");
114 ResetImagePropertyIterator(image);
115 while ((property=GetNextImageProperty(image)) != (const char *) NULL ) {
116 (void) FormatLocaleFile(stderr," %s: ",property);
117 value=GetImageProperty(image,property,exception);
118 if (value != (const char *) NULL)
119 (void) FormatLocaleFile(stderr,"%s\n",value);
121 ResetImagePropertyIterator(image);
127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
131 + P r o c e s s S c r i p t O p t i o n s %
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 % ProcessScriptOptions() reads options and processes options as they are
138 % found in the given file, or pipeline. The filename to open and read
139 % options is given as the 'index' argument of the argument array given.
141 % Other arguments following index may be read by special script options
142 % as settings (strings), images, or as operations to be processed in various
143 % ways. How they are treated is up to the script being processed.
145 % Note that a script not 'return' to the command line processing, nor can
146 % they call (and return from) other scripts. At least not at this time.
148 % There are no 'ProcessOptionFlags' control flags at this time.
150 % The format of the ProcessScriptOptions method is:
152 % void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv,
155 % A description of each parameter follows:
157 % o cli_wand: the main CLI Wand to use.
159 % o argc: the number of elements in the argument vector.
161 % o argv: A text array containing the command line arguments.
163 % o index: offset for argc to CLI argumnet count
166 WandExport void ProcessScriptOptions(MagickCLI *cli_wand,int argc,char **argv,
183 assert(argc>index); /* at least one argument - script name */
184 assert(argv != (char **)NULL);
185 assert(argv[index] != (char *)NULL);
186 assert(argv[argc-1] != (char *)NULL);
187 assert(cli_wand != (MagickCLI *) NULL);
188 assert(cli_wand->signature == WandSignature);
189 if (cli_wand->wand.debug != MagickFalse)
190 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
192 /* open file script or stream, and set up tokenizer */
193 token_info = AcquireScriptTokenInfo(argv[index]);
194 if (token_info == (ScriptTokenInfo *) NULL) {
195 CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",argv[index]);
199 /* define the error location string for use in exceptions
200 order of localtion format escapes: filename, line, column */
201 cli_wand->location="in \"%s\" at line %u,column %u";
202 if ( LocaleCompare("-", argv[index]) == 0 )
203 cli_wand->filename="stdin";
205 cli_wand->filename=argv[index];
207 /* Process Options from Script */
208 option = arg1 = arg2 = (char*)NULL;
211 { MagickBooleanType status = GetScriptToken(token_info);
212 cli_wand->line=token_info->token_line;
213 cli_wand->column=token_info->token_column;
214 if( IfMagickFalse(status) )
215 break; /* error or end of options */
218 do { /* use break to loop to exception handler and loop */
220 /* save option details */
221 CloneString(&option,token_info->token);
223 /* get option, its argument count, and option type */
224 cli_wand->command = GetCommandOptionInfo(option);
225 count=cli_wand->command->type;
226 option_type=(CommandOptionFlags) cli_wand->command->flags;
228 (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n",
229 cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic );
232 /* handle a undefined option - image read - always for "magick-script" */
233 if ( option_type == UndefinedOptionFlag ||
234 (option_type & NonMagickOptionFlag) != 0 ) {
235 #if MagickCommandDebug >= 3
236 (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n",
237 cli_wand->line, cli_wand->line, option);
239 if ( IfMagickFalse(IsCommandOption(option))) {
240 /* non-option -- treat as a image read */
241 cli_wand->command=(const OptionInfo *)NULL;
242 CLIOption(cli_wand,"-read",option);
243 break; /* next option */
245 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
246 break; /* next option */
250 if( IfMagickFalse(GetScriptToken(token_info)) )
251 CLIWandException(OptionFatalError,"MissingArgument",option);
252 CloneString(&arg1,token_info->token);
255 CloneString(&arg1,(char *)NULL);
258 if( IfMagickFalse(GetScriptToken(token_info)) )
259 CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option);
260 CloneString(&arg2,token_info->token);
263 CloneString(&arg2,(char *)NULL);
268 #if MagickCommandDebug >= 3
269 (void) FormatLocaleFile(stderr,
270 "Script %u,%u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
271 cli_wand->line,cli_wand->line,option,count,option_type,arg1,arg2);
273 /* Hard Depreciated Options, no code to execute - error */
274 if ( (option_type & DeprecateOptionFlag) != 0 ) {
275 CLIWandException(OptionError,"DeprecatedOptionNoCode",option);
276 break; /* next option */
279 /* MagickCommandGenesis() options have no place in a magick script */
280 if ( (option_type & GenesisOptionFlag) != 0 ) {
281 CLIWandException(OptionError,"InvalidUseOfOption",option);
282 break; /* next option */
285 /* handle any special 'script' options */
286 if ( (option_type & SpecialOptionFlag) != 0 ) {
287 if ( LocaleCompare(option,"-exit") == 0 ) {
288 goto loop_exit; /* break out of loop - return from script */
290 if ( LocaleCompare(option,"-script") == 0 ) {
291 /* FUTURE: call new script from this script - error for now */
292 CLIWandException(OptionError,"InvalidUseOfOption",option);
293 break; /* next option */
295 /* FUTURE: handle special script-argument options here */
296 /* handle any other special operators now */
297 CLIWandException(OptionError,"InvalidUseOfOption",option);
298 break; /* next option */
301 /* Process non-specific Option */
302 CLIOption(cli_wand, option, arg1, arg2);
304 } while (0); /* break block to next option */
306 #if MagickCommandDebug >= 9
307 OutputOptions(cli_wand->wand.image_info);
308 if ( cli_wand->wand.images != (Image *)NULL ) {
309 OutputArtifacts(cli_wand->wand.images);
310 OutputProperties(cli_wand->wand.images,cli_wand->wand.exception);
313 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
314 break; /* exit loop */
318 Loop exit - check for some tokenization error
321 #if MagickCommandDebug >= 3
322 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
324 switch( token_info->status ) {
327 if (cli_wand->image_list_stack != (Stack *)NULL)
328 CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
329 else if (cli_wand->image_info_stack != (Stack *)NULL)
330 CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
332 case TokenStatusBadQuotes:
333 /* Ensure last token has a sane length for error report */
334 if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
335 token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
336 token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
337 token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
338 token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
340 CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
343 case TokenStatusMemoryFailed:
344 CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
346 case TokenStatusBinary:
347 CLIWandException(OptionFatalError,"ScriptIsBinary","");
352 token_info = DestroyScriptTokenInfo(token_info);
354 CloneString(&option,(char *)NULL);
355 CloneString(&arg1,(char *)NULL);
356 CloneString(&arg2,(char *)NULL);
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 + P r o c e s s C o m m a n d O p t i o n s %
370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 % ProcessCommandOptions() reads and processes arguments in the given
373 % command line argument array. The array does not contain the command
374 % being processed, only the options.
376 % The 'process_flags' can be used to control and limit option processing.
377 % For example, to only process one option, or how unknown and special options
378 % are to be handled, and if the last argument in array is to be regarded as a
379 % final image write argument (filename or special coder).
381 % The format of the ProcessCommandOptions method is:
383 % int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
384 % int index, ProcessOptionFlags process_flags )
386 % A description of each parameter follows:
388 % o cli_wand: the main CLI Wand to use.
390 % o argc: the number of elements in the argument vector.
392 % o argv: A text array containing the command line arguments.
394 % o process_flags: What type of arguments will be processed, ignored
397 % o index: index in the argv array to start processing from
399 % The function returns the index ot the next option to be processed. This
400 % is really only releven if process_flags contains a ProcessOneOptionOnly
404 WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc,
405 char **argv, int index )
420 assert(argc>=index); /* you may have no arguments left! */
421 assert(argv != (char **)NULL);
422 assert(argv[index] != (char *)NULL);
423 assert(argv[argc-1] != (char *)NULL);
424 assert(cli_wand != (MagickCLI *) NULL);
425 assert(cli_wand->signature == WandSignature);
426 if (cli_wand->wand.debug != MagickFalse)
427 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
429 /* define the error location string for use in exceptions
430 order of localtion format escapes: filename, line, column */
431 cli_wand->location="at %s argument %u";
432 cli_wand->filename="CLI";
435 if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
436 end--; /* the last arument is an implied write, do not process directly */
438 for (i=index; i < end; i += count +1) {
439 /* Finished processing one option? */
440 if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
443 do { /* use break to loop to exception handler and loop */
446 cli_wand->line=i; /* note the argument for this option */
448 /* get option, its argument count, and option type */
449 cli_wand->command = GetCommandOptionInfo(argv[i]);
450 count=cli_wand->command->type;
451 option_type=(CommandOptionFlags) cli_wand->command->flags;
453 (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
454 i, argv[i], cli_wand->command->mnemonic );
457 if ( option_type == UndefinedOptionFlag ||
458 (option_type & NonMagickOptionFlag) != 0 ) {
459 #if MagickCommandDebug >= 3
460 (void) FormatLocaleFile(stderr, "CLI %d Non-Option: \"%s\"\n", i, option);
462 if ( IfMagickFalse(IsCommandOption(option)) ) {
463 if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) {
464 /* non-option -- treat as a image read */
465 cli_wand->command=(const OptionInfo *)NULL;
466 CLIOption(cli_wand,"-read",option);
467 break; /* next option */
470 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
471 break; /* next option */
474 if ( ((option_type & SpecialOptionFlag) != 0 ) &&
475 ((cli_wand->process_flags & ProcessScriptOption) != 0) &&
476 (LocaleCompare(option,"-script") == 0) ) {
477 /* Call Script from CLI, with a filename as a zeroth argument.
478 NOTE: -script may need to use the 'implict write filename' argument
479 so it must be handled specially to prevent a 'missing argument' error.
481 if ( (i+count) >= argc )
482 CLIWandException(OptionFatalError,"MissingArgument",option);
483 ProcessScriptOptions(cli_wand,argc,argv,i+1);
484 return(argc); /* Script does not return to CLI -- Yet */
485 /* FUTURE: when it does, their may be no write arg! */
488 if ((i+count) >= end ) {
489 CLIWandException(OptionFatalError,"MissingArgument",option);
490 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
492 break; /* next option - not that their is any! */
495 arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL;
496 arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL;
499 Process Known Options
501 #if MagickCommandDebug >= 3
502 (void) FormatLocaleFile(stderr,
503 "CLI %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
504 i,option,count,option_type,arg1,arg2);
507 /* ignore 'genesis options' in command line args */
508 if ( (option_type & GenesisOptionFlag) != 0 )
509 break; /* next option */
511 /* Handle any special options for CLI (-script handled above) */
512 if ( (option_type & SpecialOptionFlag) != 0 ) {
513 if ( (cli_wand->process_flags & ProcessExitOption) != 0
514 && LocaleCompare(option,"-exit") == 0 )
516 break; /* next option */
519 /* Process standard image option */
520 CLIOption(cli_wand, option, arg1, arg2);
522 } while (0); /* break block to next option */
524 #if MagickCommandDebug >= 9
525 OutputOptions(cli_wand->wand.image_info);
526 if ( cli_wand->wand.images != (Image *)NULL ) {
527 OutputArtifacts(cli_wand->wand.images);
528 OutputProperties(cli_wand->wand.images,cli_wand->wand.exception);
531 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
536 if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
537 return(end); /* no implied write -- just return to caller */
539 assert(end==argc-1); /* end should not include last argument */
542 Implicit Write of images to final CLI argument
547 /* check that stacks are empty - or cause exception */
548 if (cli_wand->image_list_stack != (Stack *)NULL)
549 CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
550 else if (cli_wand->image_info_stack != (Stack *)NULL)
551 CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
552 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
555 #if MagickCommandDebug >= 3
556 (void) FormatLocaleFile(stderr, "CLI %d Write File: \"%s\"\n", i, option );
559 /* Valid 'do no write' replacement option (instead of "null:") */
560 if (LocaleCompare(option,"-exit") == 0 )
561 return(argc); /* just exit, no image write */
563 /* If filename looks like an option,
564 Or the common 'end of line' error of a single space.
565 -- produce an error */
566 if (IfMagickTrue(IsCommandOption(option)) ||
567 (option[0] == ' ' && option[1] == '\0') ) {
568 CLIWandException(OptionError,"MissingOutputFilename",option);
572 cli_wand->command=(const OptionInfo *)NULL;
573 CLIOption(cli_wand,"-write",option);
578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 + M a g i c k I m a g e C o m m a n d %
586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 % MagickImageCommand() Handle special use CLI arguments and prepare a
589 % CLI MagickCLI to process the command line or directly specified script.
591 % This is essentualy interface function between the MagickCore library
592 % initialization function MagickCommandGenesis(), and the option MagickCLI
593 % processing functions ProcessCommandOptions() or ProcessScriptOptions()
595 % The format of the MagickImageCommand method is:
597 % MagickBooleanType MagickImageCommand(ImageInfo *image_info,
598 % int argc, char **argv, char **metadata, ExceptionInfo *exception)
600 % A description of each parameter follows:
602 % o image_info: the starting image_info structure
603 % (for compatibilty with MagickCommandGenisis())
605 % o argc: the number of elements in the argument vector.
607 % o argv: A text array containing the command line arguments.
609 % o metadata: any metadata (for VBS) is returned here.
610 % (for compatibilty with MagickCommandGenisis())
612 % o exception: return any errors or warnings in this structure.
616 static void MagickUsage(MagickBooleanType verbose)
624 name=GetClientName();
627 if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
629 (void) FormatLocaleFile(stdout,
630 "Usage: %s [{option}|{image}...] {output_image}\n",name);
631 (void) FormatLocaleFile(stdout,
632 " %s -help|-version|-usage|-list {option}\n\n",name);
635 else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
636 /* magick-script usage */
637 (void) FormatLocaleFile(stdout,
638 "Usage: %s {filename} [{script_args}...]\n",name);
642 (void) FormatLocaleFile(stdout,
643 "Usage: %s [{option}|{image}...] {output_image}\n",name);
644 (void) FormatLocaleFile(stdout,
645 " %s [{option}|{image}...] -script {filename} [{script_args}...]\n",
648 (void) FormatLocaleFile(stdout,
649 " %s -help|-version|-usage|-list {option}\n\n",name);
651 if (IfMagickFalse(verbose))
654 (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
655 "All options are performed in a strict 'as you see them' order\n",
656 "You must read-in images before you can operate on them.\n",
658 "Magick Script files can use any of the following forms...\n",
659 " #!/path/to/magick -script\n",
662 " :; exec magick -script \"$0\" \"$@\"; exit 10\n",
663 " # Magick script from here...\n",
665 " #!/usr/bin/env magick-script\n",
666 "The latter two forms do not require the path to the command hard coded.\n",
667 "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n",
669 "For more information on usage, options, examples, and techniques\n",
670 "see the ImageMagick website at ", MagickAuthoritativeURL);
676 Concatanate given file arguments to the given output argument.
677 Used for a special -concatenate option used for specific 'delegates'.
678 The option is not formally documented.
680 magick -concatenate files... output
682 This is much like the UNIX "cat" command, but for both UNIX and Windows,
683 however the last argument provides the output filename.
685 static MagickBooleanType ConcatenateImages(int argc,char **argv,
686 ExceptionInfo *exception )
698 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
699 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
700 GetExceptionMessage(errno));
702 output=fopen_utf8(argv[argc-1],"wb");
703 if (output == (FILE *) NULL) {
704 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
707 for (i=2; i < (ssize_t) (argc-1); i++) {
709 fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
711 input=fopen_utf8(argv[i],"rb");
712 if (input == (FILE *) NULL) {
713 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
716 for (c=fgetc(input); c != EOF; c=fgetc(input))
717 (void) fputc((char) c,output);
718 (void) fclose(input);
719 (void) remove_utf8(argv[i]);
721 (void) fclose(output);
725 WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,
726 int argc,char **argv,char **metadata,ExceptionInfo *exception)
734 /* For specific OS command line requirements */
735 ReadCommandlLine(argc,&argv);
737 /* Initialize special "CLI Wand" to hold images and settings (empty) */
738 cli_wand=AcquireMagickCLI(image_info,exception);
741 GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
742 SetClientName(cli_wand->wand.name);
743 ConcatenateMagickString(cli_wand->wand.name,"-CLI",MaxTextExtent);
745 len=strlen(argv[0]); /* precaution */
747 /* "convert" command - give a "depreciation" warning" */
748 if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
749 cli_wand->process_flags = ConvertCommandOptionFlags;
750 /*(void) FormatLocaleFile(stderr,"WARNING: %s\n",
751 "The convert is depreciated in IMv7, use \"magick\"\n");*/
754 /* Special Case: If command name ends with "script" implied "-script" */
755 if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
756 if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
757 GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
758 ProcessScriptOptions(cli_wand,argc,argv,1);
759 goto Magick_Command_Cleanup;
763 /* Special Case: Version Information and Abort */
765 if (LocaleCompare("-version",argv[1]) == 0) { /* just version */
766 CLIOption(cli_wand, "-version");
767 goto Magick_Command_Exit;
769 if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */
770 (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */
771 MagickUsage(MagickFalse);
772 goto Magick_Command_Exit;
774 if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */
775 CLIOption(cli_wand, "-version" );
776 MagickUsage(MagickTrue);
777 goto Magick_Command_Exit;
781 /* not enough arguments -- including -help */
783 (void) FormatLocaleFile(stderr,
784 "Error: Invalid argument or not enough arguments\n\n");
785 MagickUsage(MagickFalse);
786 goto Magick_Command_Exit;
789 /* Special "concatenate option (hidden) for delegate usage */
790 if (LocaleCompare("-concatenate",argv[1]) == 0) {
791 ConcatenateImages(argc,argv,exception);
792 goto Magick_Command_Exit;
795 /* List Information and Abort */
796 if (argc == 3 && LocaleCompare("-list",argv[1]) == 0) {
797 CLIOption(cli_wand, argv[1], argv[2]);
798 goto Magick_Command_Exit;
804 if (LocaleCompare("-script",argv[1]) == 0) {
805 /* Start processing directly from script, no pre-script options
806 Replace wand command name with script name
807 First argument in the argv array is the script name to read.
809 GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
810 ProcessScriptOptions(cli_wand,argc,argv,2);
813 /* Normal Command Line, assumes output file as last option */
814 ProcessCommandOptions(cli_wand,argc,argv,1);
818 Magick_Command_Cleanup:
819 /* recover original image_info and clean up stacks
820 FUTURE: "-reset stacks" option */
821 while (cli_wand->image_list_stack != (Stack *)NULL)
822 CLIOption(cli_wand,")");
823 while (cli_wand->image_info_stack != (Stack *)NULL)
824 CLIOption(cli_wand,"}");
826 /* assert we have recovered the original structures */
827 assert(cli_wand->wand.image_info == image_info);
828 assert(cli_wand->wand.exception == exception);
830 /* Handle metadata for ImageMagickObject COM object for Windows VBS */
831 if (metadata != (char **) NULL) {
838 format="%w,%h,%m"; // Get this from image_info Option splaytree
840 text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
842 if (text == (char *) NULL)
843 ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
844 "MemoryAllocationFailed","'%s'", GetExceptionMessage(errno));
846 (void) ConcatenateString(&(*metadata),text);
847 text=DestroyString(text);
852 /* Destroy the special CLI Wand */
853 cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */
854 cli_wand->wand.exception = (ExceptionInfo *)NULL;
855 cli_wand=DestroyMagickCLI(cli_wand);
857 return(IsMagickTrue(exception->severity > ErrorException));