blob: a408a6f7513946149f50b116a24198209d2b8bba [file] [log] [blame]
anthonyfa1e43d2012-02-12 12:55:45 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
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 %
11% %
12% CCCC L IIIII %
13% C L I %
14% C L I %
15% C L I %
16% CCCC LLLLL IIIII %
17% %
18% Perform "Magick" on Images via the Command Line Interface %
19% %
20% Dragon Computing %
21% Anthony Thyssen %
22% January 2012 %
23% %
24% %
Cristy7ce65e72015-12-12 18:03:16 -050025% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
anthonyfa1e43d2012-02-12 12:55:45 +000026% dedicated to making software imaging solutions freely available. %
27% %
28% You may not use this file except in compliance with the License. You may %
29% obtain a copy of the License at %
30% %
31% http://www.imagemagick.org/script/license.php %
32% %
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. %
38% %
39%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40%
41% Read CLI arguments, script files, and pipelines, to provide options that
42% manipulate images from many different formats.
43%
44*/
45
46/*
47 Include declarations.
48*/
49#include "MagickWand/studio.h"
50#include "MagickWand/MagickWand.h"
51#include "MagickWand/magick-wand-private.h"
anthony756cd0d2012-04-08 12:41:44 +000052#include "MagickWand/wandcli.h"
53#include "MagickWand/wandcli-private.h"
anthony43f425d2012-02-26 12:58:58 +000054#include "MagickWand/operation.h"
anthony2052d272012-02-28 12:48:29 +000055#include "MagickWand/magick-cli.h"
anthony1cdc5b72012-03-03 02:31:18 +000056#include "MagickWand/script-token.h"
anthonyfa1e43d2012-02-12 12:55:45 +000057#include "MagickCore/utility-private.h"
anthony5216f822012-04-10 13:02:37 +000058#include "MagickCore/exception-private.h"
anthony668f43a2012-02-20 14:55:32 +000059#include "MagickCore/version.h"
60
anthony43f425d2012-02-26 12:58:58 +000061/* verbose debugging,
anthonya322a832013-04-27 06:28:03 +000062 0 - no debug lines
63 3 - show option details (better to use -debug Command now)
64 5 - image counts (after option runs)
anthony24aa8822012-03-11 00:56:06 +000065*/
anthony2cfa1a12012-05-12 05:18:07 +000066#define MagickCommandDebug 0
anthony668f43a2012-02-20 14:55:32 +000067
anthonyfa1e43d2012-02-12 12:55:45 +000068
69/*
70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71% %
72% %
73% %
anthony668f43a2012-02-20 14:55:32 +000074+ P r o c e s s S c r i p t O p t i o n s %
anthonyfa1e43d2012-02-12 12:55:45 +000075% %
76% %
77% %
78%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79%
anthony668f43a2012-02-20 14:55:32 +000080% ProcessScriptOptions() reads options and processes options as they are
81% found in the given file, or pipeline. The filename to open and read
anthony0b46ebe2012-03-06 04:15:35 +000082% options is given as the 'index' argument of the argument array given.
anthonyfa1e43d2012-02-12 12:55:45 +000083%
anthony0b46ebe2012-03-06 04:15:35 +000084% 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.
anthonyfa1e43d2012-02-12 12:55:45 +000087%
anthony0b46ebe2012-03-06 04:15:35 +000088% 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.
90%
91% There are no 'ProcessOptionFlags' control flags at this time.
anthony668f43a2012-02-20 14:55:32 +000092%
93% The format of the ProcessScriptOptions method is:
94%
anthonya322a832013-04-27 06:28:03 +000095% void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
96% int argc,char **argv,int index)
anthonyfa1e43d2012-02-12 12:55:45 +000097%
98% A description of each parameter follows:
99%
anthony43f425d2012-02-26 12:58:58 +0000100% o cli_wand: the main CLI Wand to use.
anthonyfa1e43d2012-02-12 12:55:45 +0000101%
anthonya322a832013-04-27 06:28:03 +0000102% o filename: the filename of script to process
anthonyfa1e43d2012-02-12 12:55:45 +0000103%
anthonya322a832013-04-27 06:28:03 +0000104% o argc: the number of elements in the argument vector. (optional)
anthonyfa1e43d2012-02-12 12:55:45 +0000105%
anthonya322a832013-04-27 06:28:03 +0000106% o argv: A text array containing the command line arguments. (optional)
107%
108% o index: offset of next argment in argv (script arguments) (optional)
anthony0b46ebe2012-03-06 04:15:35 +0000109%
anthonyfa1e43d2012-02-12 12:55:45 +0000110*/
anthonya322a832013-04-27 06:28:03 +0000111WandExport void ProcessScriptOptions(MagickCLI *cli_wand,const char *filename,
cristy0aec3202014-09-22 11:26:48 +0000112 int argc,char **argv,int index)
anthony668f43a2012-02-20 14:55:32 +0000113{
anthony1cdc5b72012-03-03 02:31:18 +0000114 ScriptTokenInfo
115 *token_info;
anthony668f43a2012-02-20 14:55:32 +0000116
anthony668f43a2012-02-20 14:55:32 +0000117 CommandOptionFlags
118 option_type;
119
anthony0b46ebe2012-03-06 04:15:35 +0000120 int
anthony1cdc5b72012-03-03 02:31:18 +0000121 count;
anthony668f43a2012-02-20 14:55:32 +0000122
anthony1cdc5b72012-03-03 02:31:18 +0000123 char
124 *option,
125 *arg1,
126 *arg2;
127
cristyf432c632014-12-07 15:11:28 +0000128 assert(filename != (char *) NULL ); /* at least one argument - script name */
anthony43f425d2012-02-26 12:58:58 +0000129 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000130 assert(cli_wand->signature == MagickWandSignature);
anthonya322a832013-04-27 06:28:03 +0000131 if (IfMagickTrue(cli_wand->wand.debug))
132 (void) LogMagickEvent(CommandEvent,GetMagickModule(),
133 "Processing script \"%s\"", filename);
anthony668f43a2012-02-20 14:55:32 +0000134
anthony0b46ebe2012-03-06 04:15:35 +0000135 /* open file script or stream, and set up tokenizer */
anthonya322a832013-04-27 06:28:03 +0000136 token_info = AcquireScriptTokenInfo(filename);
anthony8ac75b52012-03-18 11:56:44 +0000137 if (token_info == (ScriptTokenInfo *) NULL) {
anthonya322a832013-04-27 06:28:03 +0000138 CLIWandExceptionFile(OptionFatalError,"UnableToOpenScript",filename);
anthony1cdc5b72012-03-03 02:31:18 +0000139 return;
140 }
anthony668f43a2012-02-20 14:55:32 +0000141
anthony0b46ebe2012-03-06 04:15:35 +0000142 /* define the error location string for use in exceptions
anthony5216f822012-04-10 13:02:37 +0000143 order of localtion format escapes: filename, line, column */
144 cli_wand->location="in \"%s\" at line %u,column %u";
anthonya322a832013-04-27 06:28:03 +0000145 if ( LocaleCompare("-", filename) == 0 )
anthony0b46ebe2012-03-06 04:15:35 +0000146 cli_wand->filename="stdin";
147 else
anthonya322a832013-04-27 06:28:03 +0000148 cli_wand->filename=filename;
anthony668f43a2012-02-20 14:55:32 +0000149
anthony0b46ebe2012-03-06 04:15:35 +0000150 /* Process Options from Script */
cristyf432c632014-12-07 15:11:28 +0000151 option = arg1 = arg2 = (char*) NULL;
dirk93b02b72013-11-16 16:03:36 +0000152DisableMSCWarning(4127)
anthony1cdc5b72012-03-03 02:31:18 +0000153 while (1) {
dirk93b02b72013-11-16 16:03:36 +0000154RestoreMSCWarning
anthony668f43a2012-02-20 14:55:32 +0000155
anthony0b46ebe2012-03-06 04:15:35 +0000156 { MagickBooleanType status = GetScriptToken(token_info);
157 cli_wand->line=token_info->token_line;
158 cli_wand->column=token_info->token_column;
cristycb190b72014-08-31 20:04:42 +0000159 if (status == MagickFalse)
anthony84d42792012-03-30 14:08:38 +0000160 break; /* error or end of options */
anthony0b46ebe2012-03-06 04:15:35 +0000161 }
anthony668f43a2012-02-20 14:55:32 +0000162
anthony964d28e2012-05-17 23:39:46 +0000163 do { /* use break to loop to exception handler and loop */
anthony1cdc5b72012-03-03 02:31:18 +0000164
anthony964d28e2012-05-17 23:39:46 +0000165 /* save option details */
166 CloneString(&option,token_info->token);
167
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;
anthonyf125a5e2012-04-03 13:14:42 +0000172#if 0
anthony964d28e2012-05-17 23:39:46 +0000173 (void) FormatLocaleFile(stderr, "Script: %u,%u: \"%s\" matched \"%s\"\n",
anthony464f1c42012-04-22 08:51:01 +0000174 cli_wand->line, cli_wand->line, option, cli_wand->command->mnemonic );
anthony668f43a2012-02-20 14:55:32 +0000175#endif
anthony668f43a2012-02-20 14:55:32 +0000176
anthony964d28e2012-05-17 23:39:46 +0000177 /* handle a undefined option - image read - always for "magick-script" */
178 if ( option_type == UndefinedOptionFlag ||
179 (option_type & NonMagickOptionFlag) != 0 ) {
anthonyf125a5e2012-04-03 13:14:42 +0000180#if MagickCommandDebug >= 3
anthony964d28e2012-05-17 23:39:46 +0000181 (void) FormatLocaleFile(stderr, "Script %u,%u Non-Option: \"%s\"\n",
182 cli_wand->line, cli_wand->line, option);
anthony668f43a2012-02-20 14:55:32 +0000183#endif
anthony964d28e2012-05-17 23:39:46 +0000184 if ( IfMagickFalse(IsCommandOption(option))) {
185 /* non-option -- treat as a image read */
cristyf432c632014-12-07 15:11:28 +0000186 cli_wand->command=(const OptionInfo *) NULL;
anthony964d28e2012-05-17 23:39:46 +0000187 CLIOption(cli_wand,"-read",option);
188 break; /* next option */
189 }
190 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
191 break; /* next option */
anthony756cd0d2012-04-08 12:41:44 +0000192 }
anthony1cdc5b72012-03-03 02:31:18 +0000193
anthony964d28e2012-05-17 23:39:46 +0000194 if ( count >= 1 ) {
195 if( IfMagickFalse(GetScriptToken(token_info)) )
196 CLIWandException(OptionFatalError,"MissingArgument",option);
197 CloneString(&arg1,token_info->token);
198 }
199 else
cristyf432c632014-12-07 15:11:28 +0000200 CloneString(&arg1,(char *) NULL);
anthony2052d272012-02-28 12:48:29 +0000201
anthony964d28e2012-05-17 23:39:46 +0000202 if ( count >= 2 ) {
203 if( IfMagickFalse(GetScriptToken(token_info)) )
204 CLIWandExceptionBreak(OptionFatalError,"MissingArgument",option);
205 CloneString(&arg2,token_info->token);
206 }
207 else
cristyf432c632014-12-07 15:11:28 +0000208 CloneString(&arg2,(char *) NULL);
anthony668f43a2012-02-20 14:55:32 +0000209
anthony964d28e2012-05-17 23:39:46 +0000210 /*
211 Process Options
212 */
anthonyf125a5e2012-04-03 13:14:42 +0000213#if MagickCommandDebug >= 3
anthony964d28e2012-05-17 23:39:46 +0000214 (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);
anthony668f43a2012-02-20 14:55:32 +0000217#endif
glennrpe248fc22014-01-17 16:16:12 +0000218 /* Hard Deprecated Options, no code to execute - error */
anthony964d28e2012-05-17 23:39:46 +0000219 if ( (option_type & DeprecateOptionFlag) != 0 ) {
220 CLIWandException(OptionError,"DeprecatedOptionNoCode",option);
221 break; /* next option */
anthony8226e722012-04-05 14:25:46 +0000222 }
anthony964d28e2012-05-17 23:39:46 +0000223
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 */
anthony8226e722012-04-05 14:25:46 +0000228 }
anthonyb1d483a2012-04-14 12:53:56 +0000229
anthony964d28e2012-05-17 23:39:46 +0000230 /* handle any special 'script' options */
231 if ( (option_type & SpecialOptionFlag) != 0 ) {
232 if ( LocaleCompare(option,"-exit") == 0 ) {
anthony4837ac22012-05-18 23:39:48 +0000233 goto loop_exit; /* break out of loop - return from script */
anthony964d28e2012-05-17 23:39:46 +0000234 }
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 */
239 }
240 /* FUTURE: handle special script-argument options here */
241 /* handle any other special operators now */
242 CLIWandException(OptionError,"InvalidUseOfOption",option);
243 break; /* next option */
244 }
anthony1cdc5b72012-03-03 02:31:18 +0000245
anthony964d28e2012-05-17 23:39:46 +0000246 /* Process non-specific Option */
247 CLIOption(cli_wand, option, arg1, arg2);
cristy0aec3202014-09-22 11:26:48 +0000248 (void) fflush(stdout);
249 (void) fflush(stderr);
anthony964d28e2012-05-17 23:39:46 +0000250
dirk93b02b72013-11-16 16:03:36 +0000251DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +0000252 } while (0); /* break block to next option */
dirk93b02b72013-11-16 16:03:36 +0000253RestoreMSCWarning
anthony964d28e2012-05-17 23:39:46 +0000254
anthonybe39e6f2012-10-05 06:26:31 +0000255#if MagickCommandDebug >= 5
256 fprintf(stderr, "Script Image Count = %ld\n",
257 GetImageListLength(cli_wand->wand.images) );
258#endif
anthony964d28e2012-05-17 23:39:46 +0000259 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
260 break; /* exit loop */
anthony1cdc5b72012-03-03 02:31:18 +0000261 }
262
anthony964d28e2012-05-17 23:39:46 +0000263 /*
264 Loop exit - check for some tokenization error
265 */
anthony4837ac22012-05-18 23:39:48 +0000266loop_exit:
anthonyf125a5e2012-04-03 13:14:42 +0000267#if MagickCommandDebug >= 3
anthony1cdc5b72012-03-03 02:31:18 +0000268 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
269#endif
270 switch( token_info->status ) {
271 case TokenStatusOK:
272 case TokenStatusEOF:
cristyf432c632014-12-07 15:11:28 +0000273 if (cli_wand->image_list_stack != (Stack *) NULL)
anthony8226e722012-04-05 14:25:46 +0000274 CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
cristyf432c632014-12-07 15:11:28 +0000275 else if (cli_wand->image_info_stack != (Stack *) NULL)
anthony8226e722012-04-05 14:25:46 +0000276 CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
anthony1cdc5b72012-03-03 02:31:18 +0000277 break;
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';
285 }
anthonyafa3dfc2012-03-03 11:31:30 +0000286 CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
287 token_info->token);
anthony1cdc5b72012-03-03 02:31:18 +0000288 break;
289 case TokenStatusMemoryFailed:
anthonyafa3dfc2012-03-03 11:31:30 +0000290 CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
anthony1cdc5b72012-03-03 02:31:18 +0000291 break;
292 case TokenStatusBinary:
anthonyafa3dfc2012-03-03 11:31:30 +0000293 CLIWandException(OptionFatalError,"ScriptIsBinary","");
anthony1cdc5b72012-03-03 02:31:18 +0000294 break;
295 }
cristy0aec3202014-09-22 11:26:48 +0000296 (void) fflush(stdout);
297 (void) fflush(stderr);
anthonya322a832013-04-27 06:28:03 +0000298 if (IfMagickTrue(cli_wand->wand.debug))
299 (void) LogMagickEvent(CommandEvent,GetMagickModule(),
300 "Script End \"%s\"", filename);
anthony1cdc5b72012-03-03 02:31:18 +0000301
302 /* Clean up */
303 token_info = DestroyScriptTokenInfo(token_info);
304
cristyf432c632014-12-07 15:11:28 +0000305 CloneString(&option,(char *) NULL);
306 CloneString(&arg1,(char *) NULL);
307 CloneString(&arg2,(char *) NULL);
anthony1cdc5b72012-03-03 02:31:18 +0000308
309 return;
anthony668f43a2012-02-20 14:55:32 +0000310}
311
312/*
313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314% %
315% %
316% %
317+ P r o c e s s C o m m a n d O p t i o n s %
318% %
319% %
320% %
321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322%
323% ProcessCommandOptions() reads and processes arguments in the given
anthonya322a832013-04-27 06:28:03 +0000324% command line argument array. The 'index' defines where in the array we
325% should begin processing
anthony668f43a2012-02-20 14:55:32 +0000326%
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).
331%
332% The format of the ProcessCommandOptions method is:
333%
cristy0aec3202014-09-22 11:26:48 +0000334% int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
335% int index)
anthony668f43a2012-02-20 14:55:32 +0000336%
337% A description of each parameter follows:
338%
anthony43f425d2012-02-26 12:58:58 +0000339% o cli_wand: the main CLI Wand to use.
anthony668f43a2012-02-20 14:55:32 +0000340%
341% o argc: the number of elements in the argument vector.
342%
343% o argv: A text array containing the command line arguments.
344%
anthony0ea037a2012-04-03 12:14:39 +0000345% o process_flags: What type of arguments will be processed, ignored
346% or return errors.
anthony668f43a2012-02-20 14:55:32 +0000347%
anthony0b46ebe2012-03-06 04:15:35 +0000348% o index: index in the argv array to start processing from
349%
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
352% flag.
353%
anthony668f43a2012-02-20 14:55:32 +0000354*/
cristyf4bfcc52014-05-26 20:55:58 +0000355WandExport int ProcessCommandOptions(MagickCLI *cli_wand,int argc,char **argv,
356 int index)
anthonyfa1e43d2012-02-12 12:55:45 +0000357{
358 const char
359 *option,
360 *arg1,
361 *arg2;
362
anthony0b46ebe2012-03-06 04:15:35 +0000363 int
anthonyfa1e43d2012-02-12 12:55:45 +0000364 i,
anthony668f43a2012-02-20 14:55:32 +0000365 end,
anthonyfa1e43d2012-02-12 12:55:45 +0000366 count;
367
368 CommandOptionFlags
anthony686b1a32012-02-15 14:50:53 +0000369 option_type;
anthonyfa1e43d2012-02-12 12:55:45 +0000370
anthony0b46ebe2012-03-06 04:15:35 +0000371 assert(argc>=index); /* you may have no arguments left! */
cristyf432c632014-12-07 15:11:28 +0000372 assert(argv != (char **) NULL);
373 assert(argv[index] != (char *) NULL);
374 assert(argv[argc-1] != (char *) NULL);
anthony43f425d2012-02-26 12:58:58 +0000375 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000376 assert(cli_wand->signature == MagickWandSignature);
anthonyfa1e43d2012-02-12 12:55:45 +0000377
anthony92c93bd2012-03-19 14:02:47 +0000378 /* define the error location string for use in exceptions
anthony5216f822012-04-10 13:02:37 +0000379 order of localtion format escapes: filename, line, column */
anthonya322a832013-04-27 06:28:03 +0000380 cli_wand->location="at %s arg %u";
anthonyafa3dfc2012-03-03 11:31:30 +0000381 cli_wand->filename="CLI";
anthonya322a832013-04-27 06:28:03 +0000382 cli_wand->line=index; /* note first argument we will process */
383
384 if (IfMagickTrue(cli_wand->wand.debug))
385 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
386 "- Starting (\"%s\")", argv[index]);
anthonyafa3dfc2012-03-03 11:31:30 +0000387
anthony668f43a2012-02-20 14:55:32 +0000388 end = argc;
anthony964d28e2012-05-17 23:39:46 +0000389 if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
anthony5216f822012-04-10 13:02:37 +0000390 end--; /* the last arument is an implied write, do not process directly */
anthony0b46ebe2012-03-06 04:15:35 +0000391
392 for (i=index; i < end; i += count +1) {
anthonyafa3dfc2012-03-03 11:31:30 +0000393 /* Finished processing one option? */
anthony5216f822012-04-10 13:02:37 +0000394 if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
anthony0b46ebe2012-03-06 04:15:35 +0000395 return(i);
anthony668f43a2012-02-20 14:55:32 +0000396
anthony964d28e2012-05-17 23:39:46 +0000397 do { /* use break to loop to exception handler and loop */
anthonyfa1e43d2012-02-12 12:55:45 +0000398
anthony964d28e2012-05-17 23:39:46 +0000399 option=argv[i];
400 cli_wand->line=i; /* note the argument for this option */
401
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;
anthonyf125a5e2012-04-03 13:14:42 +0000406#if 0
anthony964d28e2012-05-17 23:39:46 +0000407 (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
408 i, argv[i], cli_wand->command->mnemonic );
anthony686b1a32012-02-15 14:50:53 +0000409#endif
anthonyfa1e43d2012-02-12 12:55:45 +0000410
anthony964d28e2012-05-17 23:39:46 +0000411 if ( option_type == UndefinedOptionFlag ||
412 (option_type & NonMagickOptionFlag) != 0 ) {
anthonyf125a5e2012-04-03 13:14:42 +0000413#if MagickCommandDebug >= 3
anthonya322a832013-04-27 06:28:03 +0000414 (void) FormatLocaleFile(stderr, "CLI arg %d Non-Option: \"%s\"\n",
415 i, option);
anthonyfa1e43d2012-02-12 12:55:45 +0000416#endif
anthony964d28e2012-05-17 23:39:46 +0000417 if ( IfMagickFalse(IsCommandOption(option)) ) {
418 if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) {
419 /* non-option -- treat as a image read */
cristyf432c632014-12-07 15:11:28 +0000420 cli_wand->command=(const OptionInfo *) NULL;
anthony964d28e2012-05-17 23:39:46 +0000421 CLIOption(cli_wand,"-read",option);
422 break; /* next option */
423 }
anthony464f1c42012-04-22 08:51:01 +0000424 }
anthony964d28e2012-05-17 23:39:46 +0000425 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
426 break; /* next option */
anthony756cd0d2012-04-08 12:41:44 +0000427 }
anthonyfa1e43d2012-02-12 12:55:45 +0000428
anthony964d28e2012-05-17 23:39:46 +0000429 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.
435 */
436 if ( (i+count) >= argc )
437 CLIWandException(OptionFatalError,"MissingArgument",option);
anthonya322a832013-04-27 06:28:03 +0000438 ProcessScriptOptions(cli_wand,argv[i+1],argc,argv,i+count);
anthony964d28e2012-05-17 23:39:46 +0000439 return(argc); /* Script does not return to CLI -- Yet */
440 /* FUTURE: when it does, their may be no write arg! */
441 }
442
443 if ((i+count) >= end ) {
anthony464f1c42012-04-22 08:51:01 +0000444 CLIWandException(OptionFatalError,"MissingArgument",option);
anthony964d28e2012-05-17 23:39:46 +0000445 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
446 return(end);
447 break; /* next option - not that their is any! */
448 }
anthony464f1c42012-04-22 08:51:01 +0000449
cristyf432c632014-12-07 15:11:28 +0000450 arg1 = ( count >= 1 ) ? argv[i+1] : (char *) NULL;
451 arg2 = ( count >= 2 ) ? argv[i+2] : (char *) NULL;
anthonyafa3dfc2012-03-03 11:31:30 +0000452
anthony964d28e2012-05-17 23:39:46 +0000453 /*
454 Process Known Options
455 */
anthonyf125a5e2012-04-03 13:14:42 +0000456#if MagickCommandDebug >= 3
anthony964d28e2012-05-17 23:39:46 +0000457 (void) FormatLocaleFile(stderr,
anthonya322a832013-04-27 06:28:03 +0000458 "CLI arg %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
anthony964d28e2012-05-17 23:39:46 +0000459 i,option,count,option_type,arg1,arg2);
anthonyafa3dfc2012-03-03 11:31:30 +0000460#endif
anthony964d28e2012-05-17 23:39:46 +0000461 /* ignore 'genesis options' in command line args */
462 if ( (option_type & GenesisOptionFlag) != 0 )
463 break; /* next option */
anthony8226e722012-04-05 14:25:46 +0000464
anthony964d28e2012-05-17 23:39:46 +0000465 /* 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 )
469 return(i+count);
470 break; /* next option */
471 }
anthonyb1d483a2012-04-14 12:53:56 +0000472
anthony964d28e2012-05-17 23:39:46 +0000473 /* Process standard image option */
474 CLIOption(cli_wand, option, arg1, arg2);
anthonyafa3dfc2012-03-03 11:31:30 +0000475
dirk93b02b72013-11-16 16:03:36 +0000476DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +0000477 } while (0); /* break block to next option */
dirk93b02b72013-11-16 16:03:36 +0000478RestoreMSCWarning
anthony964d28e2012-05-17 23:39:46 +0000479
anthonybe39e6f2012-10-05 06:26:31 +0000480#if MagickCommandDebug >= 5
anthonya322a832013-04-27 06:28:03 +0000481 (void) FormatLocaleFile(stderr, "CLI-post Image Count = %ld\n",
482 (long) GetImageListLength(cli_wand->wand.images) );
anthonybe39e6f2012-10-05 06:26:31 +0000483#endif
anthonyafa3dfc2012-03-03 11:31:30 +0000484 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
anthony0b46ebe2012-03-06 04:15:35 +0000485 return(i+count);
anthonyafa3dfc2012-03-03 11:31:30 +0000486 }
anthony0b46ebe2012-03-06 04:15:35 +0000487 assert(i==end);
anthony2052d272012-02-28 12:48:29 +0000488
anthony964d28e2012-05-17 23:39:46 +0000489 if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
anthony5216f822012-04-10 13:02:37 +0000490 return(end); /* no implied write -- just return to caller */
anthony0b46ebe2012-03-06 04:15:35 +0000491
anthony5216f822012-04-10 13:02:37 +0000492 assert(end==argc-1); /* end should not include last argument */
anthony668f43a2012-02-20 14:55:32 +0000493
494 /*
anthony43f425d2012-02-26 12:58:58 +0000495 Implicit Write of images to final CLI argument
anthony668f43a2012-02-20 14:55:32 +0000496 */
497 option=argv[i];
anthony799889a2012-03-11 11:00:32 +0000498 cli_wand->line=i;
anthony686b1a32012-02-15 14:50:53 +0000499
anthony964d28e2012-05-17 23:39:46 +0000500 /* check that stacks are empty - or cause exception */
cristyf432c632014-12-07 15:11:28 +0000501 if (cli_wand->image_list_stack != (Stack *) NULL)
anthony964d28e2012-05-17 23:39:46 +0000502 CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
cristyf432c632014-12-07 15:11:28 +0000503 else if (cli_wand->image_info_stack != (Stack *) NULL)
anthony964d28e2012-05-17 23:39:46 +0000504 CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
505 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
506 return(argc);
507
anthonyf125a5e2012-04-03 13:14:42 +0000508#if MagickCommandDebug >= 3
anthonya322a832013-04-27 06:28:03 +0000509 (void) FormatLocaleFile(stderr,"CLI arg %d Write File: \"%s\"\n",i,option);
anthonyfa1e43d2012-02-12 12:55:45 +0000510#endif
511
anthony964d28e2012-05-17 23:39:46 +0000512 /* Valid 'do no write' replacement option (instead of "null:") */
anthonyfa1e43d2012-02-12 12:55:45 +0000513 if (LocaleCompare(option,"-exit") == 0 )
anthony0b46ebe2012-03-06 04:15:35 +0000514 return(argc); /* just exit, no image write */
anthonyfa1e43d2012-02-12 12:55:45 +0000515
anthonye5b39652012-04-21 05:37:29 +0000516 /* 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') ) {
anthony0b46ebe2012-03-06 04:15:35 +0000521 CLIWandException(OptionError,"MissingOutputFilename",option);
522 return(argc);
523 }
anthonyfa1e43d2012-02-12 12:55:45 +0000524
cristyf432c632014-12-07 15:11:28 +0000525 cli_wand->command=(const OptionInfo *) NULL;
anthony464f1c42012-04-22 08:51:01 +0000526 CLIOption(cli_wand,"-write",option);
anthony0b46ebe2012-03-06 04:15:35 +0000527 return(argc);
anthonyfa1e43d2012-02-12 12:55:45 +0000528}
529
530/*
531%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532% %
533% %
534% %
535+ M a g i c k I m a g e C o m m a n d %
536% %
537% %
538% %
539%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
540%
anthony668f43a2012-02-20 14:55:32 +0000541% MagickImageCommand() Handle special use CLI arguments and prepare a
anthony43f425d2012-02-26 12:58:58 +0000542% CLI MagickCLI to process the command line or directly specified script.
anthony668f43a2012-02-20 14:55:32 +0000543%
544% This is essentualy interface function between the MagickCore library
anthony43f425d2012-02-26 12:58:58 +0000545% initialization function MagickCommandGenesis(), and the option MagickCLI
anthony668f43a2012-02-20 14:55:32 +0000546% processing functions ProcessCommandOptions() or ProcessScriptOptions()
anthonyfa1e43d2012-02-12 12:55:45 +0000547%
548% The format of the MagickImageCommand method is:
549%
cristy3ec9e8d2013-01-30 16:29:51 +0000550% MagickBooleanType MagickImageCommand(ImageInfo *image_info,int argc,
551% char **argv,char **metadata,ExceptionInfo *exception)
anthonyfa1e43d2012-02-12 12:55:45 +0000552%
553% A description of each parameter follows:
554%
555% o image_info: the starting image_info structure
cristy3ec9e8d2013-01-30 16:29:51 +0000556% (for compatibilty with MagickCommandGenisis())
anthonyfa1e43d2012-02-12 12:55:45 +0000557%
558% o argc: the number of elements in the argument vector.
559%
560% o argv: A text array containing the command line arguments.
561%
anthony0ea037a2012-04-03 12:14:39 +0000562% o metadata: any metadata (for VBS) is returned here.
cristy3ec9e8d2013-01-30 16:29:51 +0000563% (for compatibilty with MagickCommandGenisis())
anthonyfa1e43d2012-02-12 12:55:45 +0000564%
565% o exception: return any errors or warnings in this structure.
566%
567*/
568
anthony40b60152012-04-04 06:13:37 +0000569static void MagickUsage(MagickBooleanType verbose)
anthonyfa1e43d2012-02-12 12:55:45 +0000570{
anthonye5fcd362012-04-09 04:02:09 +0000571 const char
572 *name;
573
574 size_t
575 len;
576
577 name=GetClientName();
578 len=strlen(name);
579
anthonyd22bf402012-04-10 01:32:03 +0000580 if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
anthonye5fcd362012-04-09 04:02:09 +0000581 /* convert usage */
582 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000583 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
anthonye5fcd362012-04-09 04:02:09 +0000584 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000585 " %s -help | -version | -usage | -list {option}\n\n",name);
anthonyd22bf402012-04-10 01:32:03 +0000586 return;
587 }
588 else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
589 /* magick-script usage */
590 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000591 "Usage: %s {filename} [ {script_args} ... ]\n",name);
anthonye5fcd362012-04-09 04:02:09 +0000592 }
593 else {
594 /* magick usage */
595 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000596 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
anthonye5fcd362012-04-09 04:02:09 +0000597 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000598 " %s [ {option} | {image} ... ] -script {filename} [ {script_args} ...]\n",
anthonye5fcd362012-04-09 04:02:09 +0000599 name);
anthonye5fcd362012-04-09 04:02:09 +0000600 }
anthonyd22bf402012-04-10 01:32:03 +0000601 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000602 " %s -help | -version | -usage | -list {option}\n\n",name);
anthony40b60152012-04-04 06:13:37 +0000603
604 if (IfMagickFalse(verbose))
605 return;
606
anthonyd22bf402012-04-10 01:32:03 +0000607 (void) FormatLocaleFile(stdout,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
anthony40b60152012-04-04 06:13:37 +0000608 "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",
610 "\n",
611 "Magick Script files can use any of the following forms...\n",
612 " #!/path/to/magick -script\n",
613 "or\n",
614 " #!/bin/sh\n",
615 " :; exec magick -script \"$0\" \"$@\"; exit 10\n",
616 " # Magick script from here...\n",
617 "or\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",
621 "\n",
622 "For more information on usage, options, examples, and techniques\n",
623 "see the ImageMagick website at ", MagickAuthoritativeURL);
624
625 return;
anthonyfa1e43d2012-02-12 12:55:45 +0000626}
627
628/*
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.
632
633 magick -concatenate files... output
634
635 This is much like the UNIX "cat" command, but for both UNIX and Windows,
636 however the last argument provides the output filename.
637*/
anthonyfa1e43d2012-02-12 12:55:45 +0000638static MagickBooleanType ConcatenateImages(int argc,char **argv,
anthony5216f822012-04-10 13:02:37 +0000639 ExceptionInfo *exception )
anthonyfa1e43d2012-02-12 12:55:45 +0000640{
641 FILE
642 *input,
643 *output;
644
645 int
646 c;
647
648 register ssize_t
649 i;
650
anthony451f9092012-05-11 01:56:24 +0000651 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
anthony3b2e6072012-05-03 13:00:39 +0000652 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
653 GetExceptionMessage(errno));
654
anthonyfa1e43d2012-02-12 12:55:45 +0000655 output=fopen_utf8(argv[argc-1],"wb");
anthonyafa3dfc2012-03-03 11:31:30 +0000656 if (output == (FILE *) NULL) {
anthony5216f822012-04-10 13:02:37 +0000657 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
anthonyafa3dfc2012-03-03 11:31:30 +0000658 return(MagickFalse);
659 }
660 for (i=2; i < (ssize_t) (argc-1); i++) {
anthony3b2e6072012-05-03 13:00:39 +0000661#if 0
662 fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
663#endif
anthonyfa1e43d2012-02-12 12:55:45 +0000664 input=fopen_utf8(argv[i],"rb");
anthony3b2e6072012-05-03 13:00:39 +0000665 if (input == (FILE *) NULL) {
cristy6a0d3612012-05-02 15:39:55 +0000666 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
667 continue;
668 }
anthonyfa1e43d2012-02-12 12:55:45 +0000669 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]);
673 }
674 (void) fclose(output);
675 return(MagickTrue);
676}
677
cristyf4bfcc52014-05-26 20:55:58 +0000678WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,int argc,
679 char **argv,char **metadata,ExceptionInfo *exception)
anthonyfa1e43d2012-02-12 12:55:45 +0000680{
anthony43f425d2012-02-26 12:58:58 +0000681 MagickCLI
682 *cli_wand;
anthonyfa1e43d2012-02-12 12:55:45 +0000683
anthonye5fcd362012-04-09 04:02:09 +0000684 size_t
685 len;
686
cristyf432c632014-12-07 15:11:28 +0000687 assert(image_info != (ImageInfo *) NULL);
anthonya322a832013-04-27 06:28:03 +0000688
anthony4cb37262012-03-18 11:18:45 +0000689 /* For specific OS command line requirements */
690 ReadCommandlLine(argc,&argv);
691
anthony668f43a2012-02-20 14:55:32 +0000692 /* Initialize special "CLI Wand" to hold images and settings (empty) */
anthony43f425d2012-02-26 12:58:58 +0000693 cli_wand=AcquireMagickCLI(image_info,exception);
anthonya322a832013-04-27 06:28:03 +0000694 cli_wand->location="Initializing";
695 cli_wand->filename=argv[0];
anthony8226e722012-04-05 14:25:46 +0000696 cli_wand->line=1;
anthonyfa1e43d2012-02-12 12:55:45 +0000697
anthonya322a832013-04-27 06:28:03 +0000698 if (IfMagickTrue(cli_wand->wand.debug))
699 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
700 "\"%s\"",argv[0]);
701
702
anthonyeff71f52012-03-29 12:59:09 +0000703 GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
anthonye5fcd362012-04-09 04:02:09 +0000704 SetClientName(cli_wand->wand.name);
cristy151b66d2015-04-15 10:50:31 +0000705 ConcatenateMagickString(cli_wand->wand.name,"-CLI",MagickPathExtent);
anthonyeff71f52012-03-29 12:59:09 +0000706
anthonye5fcd362012-04-09 04:02:09 +0000707 len=strlen(argv[0]); /* precaution */
708
glennrpe248fc22014-01-17 16:16:12 +0000709 /* "convert" command - give a "deprecated" warning" */
anthonye5fcd362012-04-09 04:02:09 +0000710 if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
anthony5216f822012-04-10 13:02:37 +0000711 cli_wand->process_flags = ConvertCommandOptionFlags;
anthonya322a832013-04-27 06:28:03 +0000712 (void) FormatLocaleFile(stderr,"WARNING: %s\n",
glennrpe248fc22014-01-17 16:16:12 +0000713 "The convert command is deprecated in IMv7, use \"magick\"\n");
anthonyeff71f52012-03-29 12:59:09 +0000714 }
anthonyeff71f52012-03-29 12:59:09 +0000715
anthony8226e722012-04-05 14:25:46 +0000716 /* Special Case: If command name ends with "script" implied "-script" */
anthonye5fcd362012-04-09 04:02:09 +0000717 if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
anthonyd22bf402012-04-10 01:32:03 +0000718 if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
anthonye5fcd362012-04-09 04:02:09 +0000719 GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
anthonya322a832013-04-27 06:28:03 +0000720 ProcessScriptOptions(cli_wand,argv[1],argc,argv,2);
anthonye5fcd362012-04-09 04:02:09 +0000721 goto Magick_Command_Cleanup;
722 }
anthony52bef752012-03-27 13:54:47 +0000723 }
724
725 /* Special Case: Version Information and Abort */
726 if (argc == 2) {
cristye4ef2952013-08-16 14:24:00 +0000727 if ((LocaleCompare("-version",argv[1]) == 0) || /* GNU standard option */
728 (LocaleCompare("--version",argv[1]) == 0) ) { /* just version */
anthony464f1c42012-04-22 08:51:01 +0000729 CLIOption(cli_wand, "-version");
anthony52bef752012-03-27 13:54:47 +0000730 goto Magick_Command_Exit;
731 }
anthony5216f822012-04-10 13:02:37 +0000732 if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */
anthony464f1c42012-04-22 08:51:01 +0000733 (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */
anthonya322a832013-04-27 06:28:03 +0000734 if (IfMagickTrue(cli_wand->wand.debug))
735 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
736 "- Special Option \"%s\"", argv[1]);
anthony40b60152012-04-04 06:13:37 +0000737 MagickUsage(MagickFalse);
738 goto Magick_Command_Exit;
739 }
anthony464f1c42012-04-22 08:51:01 +0000740 if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */
anthonya322a832013-04-27 06:28:03 +0000741 if (IfMagickTrue(cli_wand->wand.debug))
742 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
743 "- Special Option \"%s\"", argv[1]);
anthonyca487682012-04-27 07:59:27 +0000744 CLIOption(cli_wand, "-version" );
anthony40b60152012-04-04 06:13:37 +0000745 MagickUsage(MagickTrue);
746 goto Magick_Command_Exit;
747 }
anthony52bef752012-03-27 13:54:47 +0000748 }
749
750 /* not enough arguments -- including -help */
751 if (argc < 3) {
anthony40b60152012-04-04 06:13:37 +0000752 (void) FormatLocaleFile(stderr,
753 "Error: Invalid argument or not enough arguments\n\n");
754 MagickUsage(MagickFalse);
anthony52bef752012-03-27 13:54:47 +0000755 goto Magick_Command_Exit;
756 }
757
anthony0ea037a2012-04-03 12:14:39 +0000758 /* Special "concatenate option (hidden) for delegate usage */
759 if (LocaleCompare("-concatenate",argv[1]) == 0) {
anthonya322a832013-04-27 06:28:03 +0000760 if (IfMagickTrue(cli_wand->wand.debug))
761 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
762 "- Special Option \"%s\"", argv[1]);
anthony0ea037a2012-04-03 12:14:39 +0000763 ConcatenateImages(argc,argv,exception);
764 goto Magick_Command_Exit;
765 }
766
anthony06762232012-04-29 11:45:40 +0000767 /* 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;
771 }
772
anthony52bef752012-03-27 13:54:47 +0000773 /* ------------- */
774 /* The Main Call */
775
776 if (LocaleCompare("-script",argv[1]) == 0) {
anthonyafa3dfc2012-03-03 11:31:30 +0000777 /* Start processing directly from script, no pre-script options
anthony0b46ebe2012-03-06 04:15:35 +0000778 Replace wand command name with script name
779 First argument in the argv array is the script name to read.
anthonyafa3dfc2012-03-03 11:31:30 +0000780 */
781 GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
anthonya322a832013-04-27 06:28:03 +0000782 ProcessScriptOptions(cli_wand,argv[2],argc,argv,3);
anthonyafa3dfc2012-03-03 11:31:30 +0000783 }
anthony0b46ebe2012-03-06 04:15:35 +0000784 else {
anthony52bef752012-03-27 13:54:47 +0000785 /* Normal Command Line, assumes output file as last option */
anthony5216f822012-04-10 13:02:37 +0000786 ProcessCommandOptions(cli_wand,argc,argv,1);
anthony0b46ebe2012-03-06 04:15:35 +0000787 }
anthony52bef752012-03-27 13:54:47 +0000788 /* ------------- */
anthonyfa1e43d2012-02-12 12:55:45 +0000789
anthony4cb37262012-03-18 11:18:45 +0000790Magick_Command_Cleanup:
anthonya322a832013-04-27 06:28:03 +0000791 cli_wand->location="Cleanup";
792 cli_wand->filename=argv[0];
793 if (IfMagickTrue(cli_wand->wand.debug))
794 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
795 "\"%s\"",argv[0]);
796
anthony5216f822012-04-10 13:02:37 +0000797 /* recover original image_info and clean up stacks
798 FUTURE: "-reset stacks" option */
cristyf432c632014-12-07 15:11:28 +0000799 while (cli_wand->image_list_stack != (Stack *) NULL)
anthony464f1c42012-04-22 08:51:01 +0000800 CLIOption(cli_wand,")");
cristyf432c632014-12-07 15:11:28 +0000801 while (cli_wand->image_info_stack != (Stack *) NULL)
anthony464f1c42012-04-22 08:51:01 +0000802 CLIOption(cli_wand,"}");
anthony2052d272012-02-28 12:48:29 +0000803
anthony1cdc5b72012-03-03 02:31:18 +0000804 /* assert we have recovered the original structures */
anthony43f425d2012-02-26 12:58:58 +0000805 assert(cli_wand->wand.image_info == image_info);
806 assert(cli_wand->wand.exception == exception);
anthonyfa1e43d2012-02-12 12:55:45 +0000807
808 /* Handle metadata for ImageMagickObject COM object for Windows VBS */
anthonyafa3dfc2012-03-03 11:31:30 +0000809 if (metadata != (char **) NULL) {
810 const char
811 *format;
anthonyfa1e43d2012-02-12 12:55:45 +0000812
anthonyafa3dfc2012-03-03 11:31:30 +0000813 char
814 *text;
anthonyfa1e43d2012-02-12 12:55:45 +0000815
anthonyafa3dfc2012-03-03 11:31:30 +0000816 format="%w,%h,%m"; // Get this from image_info Option splaytree
anthonyfa1e43d2012-02-12 12:55:45 +0000817
anthonyafa3dfc2012-03-03 11:31:30 +0000818 text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
cristy3ec9e8d2013-01-30 16:29:51 +0000819 exception);
anthonyafa3dfc2012-03-03 11:31:30 +0000820 if (text == (char *) NULL)
821 ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
cristy3ec9e8d2013-01-30 16:29:51 +0000822 "MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
anthonyafa3dfc2012-03-03 11:31:30 +0000823 else {
824 (void) ConcatenateString(&(*metadata),text);
825 text=DestroyString(text);
anthonyfa1e43d2012-02-12 12:55:45 +0000826 }
anthonyafa3dfc2012-03-03 11:31:30 +0000827 }
anthony4cb37262012-03-18 11:18:45 +0000828
anthony52bef752012-03-27 13:54:47 +0000829Magick_Command_Exit:
anthonya322a832013-04-27 06:28:03 +0000830 cli_wand->location="Exiting";
831 cli_wand->filename=argv[0];
832 if (IfMagickTrue(cli_wand->wand.debug))
833 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
834 "\"%s\"",argv[0]);
835
anthonyfa1e43d2012-02-12 12:55:45 +0000836 /* Destroy the special CLI Wand */
cristyf432c632014-12-07 15:11:28 +0000837 cli_wand->wand.image_info = (ImageInfo *) NULL; /* not these */
838 cli_wand->wand.exception = (ExceptionInfo *) NULL;
anthony43f425d2012-02-26 12:58:58 +0000839 cli_wand=DestroyMagickCLI(cli_wand);
anthonyfa1e43d2012-02-12 12:55:45 +0000840
dirkb9dbc292015-07-26 09:50:00 +0000841 return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
anthonyfa1e43d2012-02-12 12:55:45 +0000842}