blob: 1cbcc270983e8efc4608446b593435f37624841f [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% %
cristyfe676ee2013-11-18 13:03:38 +000025% Copyright 1999-2014 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,
112 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
anthonya322a832013-04-27 06:28:03 +0000128 assert(filename != (char *)NULL ); /* at least one argument - script name */
anthony43f425d2012-02-26 12:58:58 +0000129 assert(cli_wand != (MagickCLI *) NULL);
130 assert(cli_wand->signature == WandSignature);
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 */
151 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;
anthony84d42792012-03-30 14:08:38 +0000159 if( IfMagickFalse(status) )
160 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 */
186 cli_wand->command=(const OptionInfo *)NULL;
187 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
200 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
208 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);
248
dirk93b02b72013-11-16 16:03:36 +0000249DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +0000250 } while (0); /* break block to next option */
dirk93b02b72013-11-16 16:03:36 +0000251RestoreMSCWarning
anthony964d28e2012-05-17 23:39:46 +0000252
anthonybe39e6f2012-10-05 06:26:31 +0000253#if MagickCommandDebug >= 5
254 fprintf(stderr, "Script Image Count = %ld\n",
255 GetImageListLength(cli_wand->wand.images) );
256#endif
anthony964d28e2012-05-17 23:39:46 +0000257 if ( IfMagickTrue(CLICatchException(cli_wand, MagickFalse)) )
258 break; /* exit loop */
anthony1cdc5b72012-03-03 02:31:18 +0000259 }
260
anthony964d28e2012-05-17 23:39:46 +0000261 /*
262 Loop exit - check for some tokenization error
263 */
anthony4837ac22012-05-18 23:39:48 +0000264loop_exit:
anthonyf125a5e2012-04-03 13:14:42 +0000265#if MagickCommandDebug >= 3
anthony1cdc5b72012-03-03 02:31:18 +0000266 (void) FormatLocaleFile(stderr, "Script End: %d\n", token_info->status);
267#endif
268 switch( token_info->status ) {
269 case TokenStatusOK:
270 case TokenStatusEOF:
anthony8226e722012-04-05 14:25:46 +0000271 if (cli_wand->image_list_stack != (Stack *)NULL)
272 CLIWandException(OptionError,"UnbalancedParenthesis", "(eof)");
273 else if (cli_wand->image_info_stack != (Stack *)NULL)
274 CLIWandException(OptionError,"UnbalancedBraces", "(eof)");
anthony1cdc5b72012-03-03 02:31:18 +0000275 break;
276 case TokenStatusBadQuotes:
277 /* Ensure last token has a sane length for error report */
278 if( strlen(token_info->token) > INITAL_TOKEN_LENGTH-1 ) {
279 token_info->token[INITAL_TOKEN_LENGTH-4] = '.';
280 token_info->token[INITAL_TOKEN_LENGTH-3] = '.';
281 token_info->token[INITAL_TOKEN_LENGTH-2] = '.';
282 token_info->token[INITAL_TOKEN_LENGTH-1] = '\0';
283 }
anthonyafa3dfc2012-03-03 11:31:30 +0000284 CLIWandException(OptionFatalError,"ScriptUnbalancedQuotes",
285 token_info->token);
anthony1cdc5b72012-03-03 02:31:18 +0000286 break;
287 case TokenStatusMemoryFailed:
anthonyafa3dfc2012-03-03 11:31:30 +0000288 CLIWandException(OptionFatalError,"ScriptTokenMemoryFailed","");
anthony1cdc5b72012-03-03 02:31:18 +0000289 break;
290 case TokenStatusBinary:
anthonyafa3dfc2012-03-03 11:31:30 +0000291 CLIWandException(OptionFatalError,"ScriptIsBinary","");
anthony1cdc5b72012-03-03 02:31:18 +0000292 break;
293 }
anthonya322a832013-04-27 06:28:03 +0000294 if (IfMagickTrue(cli_wand->wand.debug))
295 (void) LogMagickEvent(CommandEvent,GetMagickModule(),
296 "Script End \"%s\"", filename);
anthony1cdc5b72012-03-03 02:31:18 +0000297
298 /* Clean up */
299 token_info = DestroyScriptTokenInfo(token_info);
300
301 CloneString(&option,(char *)NULL);
302 CloneString(&arg1,(char *)NULL);
303 CloneString(&arg2,(char *)NULL);
304
305 return;
anthony668f43a2012-02-20 14:55:32 +0000306}
307
308/*
309%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310% %
311% %
312% %
313+ P r o c e s s C o m m a n d O p t i o n s %
314% %
315% %
316% %
317%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
318%
319% ProcessCommandOptions() reads and processes arguments in the given
anthonya322a832013-04-27 06:28:03 +0000320% command line argument array. The 'index' defines where in the array we
321% should begin processing
anthony668f43a2012-02-20 14:55:32 +0000322%
323% The 'process_flags' can be used to control and limit option processing.
324% For example, to only process one option, or how unknown and special options
325% are to be handled, and if the last argument in array is to be regarded as a
326% final image write argument (filename or special coder).
327%
328% The format of the ProcessCommandOptions method is:
329%
anthonya322a832013-04-27 06:28:03 +0000330% int ProcessCommandOptions(MagickCLI *cli_wand,
331% int argc,char **argv,int index)
anthony668f43a2012-02-20 14:55:32 +0000332%
333% A description of each parameter follows:
334%
anthony43f425d2012-02-26 12:58:58 +0000335% o cli_wand: the main CLI Wand to use.
anthony668f43a2012-02-20 14:55:32 +0000336%
337% o argc: the number of elements in the argument vector.
338%
339% o argv: A text array containing the command line arguments.
340%
anthony0ea037a2012-04-03 12:14:39 +0000341% o process_flags: What type of arguments will be processed, ignored
342% or return errors.
anthony668f43a2012-02-20 14:55:32 +0000343%
anthony0b46ebe2012-03-06 04:15:35 +0000344% o index: index in the argv array to start processing from
345%
346% The function returns the index ot the next option to be processed. This
347% is really only releven if process_flags contains a ProcessOneOptionOnly
348% flag.
349%
anthony668f43a2012-02-20 14:55:32 +0000350*/
anthony0b46ebe2012-03-06 04:15:35 +0000351WandExport int ProcessCommandOptions(MagickCLI *cli_wand, int argc,
anthony5216f822012-04-10 13:02:37 +0000352 char **argv, int index )
anthonyfa1e43d2012-02-12 12:55:45 +0000353{
354 const char
355 *option,
356 *arg1,
357 *arg2;
358
anthony0b46ebe2012-03-06 04:15:35 +0000359 int
anthonyfa1e43d2012-02-12 12:55:45 +0000360 i,
anthony668f43a2012-02-20 14:55:32 +0000361 end,
anthonyfa1e43d2012-02-12 12:55:45 +0000362 count;
363
364 CommandOptionFlags
anthony686b1a32012-02-15 14:50:53 +0000365 option_type;
anthonyfa1e43d2012-02-12 12:55:45 +0000366
anthony0b46ebe2012-03-06 04:15:35 +0000367 assert(argc>=index); /* you may have no arguments left! */
368 assert(argv != (char **)NULL);
369 assert(argv[index] != (char *)NULL);
370 assert(argv[argc-1] != (char *)NULL);
anthony43f425d2012-02-26 12:58:58 +0000371 assert(cli_wand != (MagickCLI *) NULL);
372 assert(cli_wand->signature == WandSignature);
anthonyfa1e43d2012-02-12 12:55:45 +0000373
anthony92c93bd2012-03-19 14:02:47 +0000374 /* define the error location string for use in exceptions
anthony5216f822012-04-10 13:02:37 +0000375 order of localtion format escapes: filename, line, column */
anthonya322a832013-04-27 06:28:03 +0000376 cli_wand->location="at %s arg %u";
anthonyafa3dfc2012-03-03 11:31:30 +0000377 cli_wand->filename="CLI";
anthonya322a832013-04-27 06:28:03 +0000378 cli_wand->line=index; /* note first argument we will process */
379
380 if (IfMagickTrue(cli_wand->wand.debug))
381 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
382 "- Starting (\"%s\")", argv[index]);
anthonyafa3dfc2012-03-03 11:31:30 +0000383
anthony668f43a2012-02-20 14:55:32 +0000384 end = argc;
anthony964d28e2012-05-17 23:39:46 +0000385 if ( (cli_wand->process_flags & ProcessImplictWrite) != 0 )
anthony5216f822012-04-10 13:02:37 +0000386 end--; /* the last arument is an implied write, do not process directly */
anthony0b46ebe2012-03-06 04:15:35 +0000387
388 for (i=index; i < end; i += count +1) {
anthonyafa3dfc2012-03-03 11:31:30 +0000389 /* Finished processing one option? */
anthony5216f822012-04-10 13:02:37 +0000390 if ( (cli_wand->process_flags & ProcessOneOptionOnly) != 0 && i != index )
anthony0b46ebe2012-03-06 04:15:35 +0000391 return(i);
anthony668f43a2012-02-20 14:55:32 +0000392
anthony964d28e2012-05-17 23:39:46 +0000393 do { /* use break to loop to exception handler and loop */
anthonyfa1e43d2012-02-12 12:55:45 +0000394
anthony964d28e2012-05-17 23:39:46 +0000395 option=argv[i];
396 cli_wand->line=i; /* note the argument for this option */
397
398 /* get option, its argument count, and option type */
399 cli_wand->command = GetCommandOptionInfo(argv[i]);
400 count=cli_wand->command->type;
401 option_type=(CommandOptionFlags) cli_wand->command->flags;
anthonyf125a5e2012-04-03 13:14:42 +0000402#if 0
anthony964d28e2012-05-17 23:39:46 +0000403 (void) FormatLocaleFile(stderr, "CLI %d: \"%s\" matched \"%s\"\n",
404 i, argv[i], cli_wand->command->mnemonic );
anthony686b1a32012-02-15 14:50:53 +0000405#endif
anthonyfa1e43d2012-02-12 12:55:45 +0000406
anthony964d28e2012-05-17 23:39:46 +0000407 if ( option_type == UndefinedOptionFlag ||
408 (option_type & NonMagickOptionFlag) != 0 ) {
anthonyf125a5e2012-04-03 13:14:42 +0000409#if MagickCommandDebug >= 3
anthonya322a832013-04-27 06:28:03 +0000410 (void) FormatLocaleFile(stderr, "CLI arg %d Non-Option: \"%s\"\n",
411 i, option);
anthonyfa1e43d2012-02-12 12:55:45 +0000412#endif
anthony964d28e2012-05-17 23:39:46 +0000413 if ( IfMagickFalse(IsCommandOption(option)) ) {
414 if ( (cli_wand->process_flags & ProcessImplictRead) != 0 ) {
415 /* non-option -- treat as a image read */
416 cli_wand->command=(const OptionInfo *)NULL;
417 CLIOption(cli_wand,"-read",option);
418 break; /* next option */
419 }
anthony464f1c42012-04-22 08:51:01 +0000420 }
anthony964d28e2012-05-17 23:39:46 +0000421 CLIWandException(OptionFatalError,"UnrecognizedOption",option);
422 break; /* next option */
anthony756cd0d2012-04-08 12:41:44 +0000423 }
anthonyfa1e43d2012-02-12 12:55:45 +0000424
anthony964d28e2012-05-17 23:39:46 +0000425 if ( ((option_type & SpecialOptionFlag) != 0 ) &&
426 ((cli_wand->process_flags & ProcessScriptOption) != 0) &&
427 (LocaleCompare(option,"-script") == 0) ) {
428 /* Call Script from CLI, with a filename as a zeroth argument.
429 NOTE: -script may need to use the 'implict write filename' argument
430 so it must be handled specially to prevent a 'missing argument' error.
431 */
432 if ( (i+count) >= argc )
433 CLIWandException(OptionFatalError,"MissingArgument",option);
anthonya322a832013-04-27 06:28:03 +0000434 ProcessScriptOptions(cli_wand,argv[i+1],argc,argv,i+count);
anthony964d28e2012-05-17 23:39:46 +0000435 return(argc); /* Script does not return to CLI -- Yet */
436 /* FUTURE: when it does, their may be no write arg! */
437 }
438
439 if ((i+count) >= end ) {
anthony464f1c42012-04-22 08:51:01 +0000440 CLIWandException(OptionFatalError,"MissingArgument",option);
anthony964d28e2012-05-17 23:39:46 +0000441 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
442 return(end);
443 break; /* next option - not that their is any! */
444 }
anthony464f1c42012-04-22 08:51:01 +0000445
anthony964d28e2012-05-17 23:39:46 +0000446 arg1 = ( count >= 1 ) ? argv[i+1] : (char *)NULL;
447 arg2 = ( count >= 2 ) ? argv[i+2] : (char *)NULL;
anthonyafa3dfc2012-03-03 11:31:30 +0000448
anthony964d28e2012-05-17 23:39:46 +0000449 /*
450 Process Known Options
451 */
anthonyf125a5e2012-04-03 13:14:42 +0000452#if MagickCommandDebug >= 3
anthony964d28e2012-05-17 23:39:46 +0000453 (void) FormatLocaleFile(stderr,
anthonya322a832013-04-27 06:28:03 +0000454 "CLI arg %u Option: \"%s\" Count: %d Flags: %04x Args: \"%s\" \"%s\"\n",
anthony964d28e2012-05-17 23:39:46 +0000455 i,option,count,option_type,arg1,arg2);
anthonyafa3dfc2012-03-03 11:31:30 +0000456#endif
anthony964d28e2012-05-17 23:39:46 +0000457 /* ignore 'genesis options' in command line args */
458 if ( (option_type & GenesisOptionFlag) != 0 )
459 break; /* next option */
anthony8226e722012-04-05 14:25:46 +0000460
anthony964d28e2012-05-17 23:39:46 +0000461 /* Handle any special options for CLI (-script handled above) */
462 if ( (option_type & SpecialOptionFlag) != 0 ) {
463 if ( (cli_wand->process_flags & ProcessExitOption) != 0
464 && LocaleCompare(option,"-exit") == 0 )
465 return(i+count);
466 break; /* next option */
467 }
anthonyb1d483a2012-04-14 12:53:56 +0000468
anthony964d28e2012-05-17 23:39:46 +0000469 /* Process standard image option */
470 CLIOption(cli_wand, option, arg1, arg2);
anthonyafa3dfc2012-03-03 11:31:30 +0000471
dirk93b02b72013-11-16 16:03:36 +0000472DisableMSCWarning(4127)
anthony964d28e2012-05-17 23:39:46 +0000473 } while (0); /* break block to next option */
dirk93b02b72013-11-16 16:03:36 +0000474RestoreMSCWarning
anthony964d28e2012-05-17 23:39:46 +0000475
anthonybe39e6f2012-10-05 06:26:31 +0000476#if MagickCommandDebug >= 5
anthonya322a832013-04-27 06:28:03 +0000477 (void) FormatLocaleFile(stderr, "CLI-post Image Count = %ld\n",
478 (long) GetImageListLength(cli_wand->wand.images) );
anthonybe39e6f2012-10-05 06:26:31 +0000479#endif
anthonyafa3dfc2012-03-03 11:31:30 +0000480 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
anthony0b46ebe2012-03-06 04:15:35 +0000481 return(i+count);
anthonyafa3dfc2012-03-03 11:31:30 +0000482 }
anthony0b46ebe2012-03-06 04:15:35 +0000483 assert(i==end);
anthony2052d272012-02-28 12:48:29 +0000484
anthony964d28e2012-05-17 23:39:46 +0000485 if ( (cli_wand->process_flags & ProcessImplictWrite) == 0 )
anthony5216f822012-04-10 13:02:37 +0000486 return(end); /* no implied write -- just return to caller */
anthony0b46ebe2012-03-06 04:15:35 +0000487
anthony5216f822012-04-10 13:02:37 +0000488 assert(end==argc-1); /* end should not include last argument */
anthony668f43a2012-02-20 14:55:32 +0000489
490 /*
anthony43f425d2012-02-26 12:58:58 +0000491 Implicit Write of images to final CLI argument
anthony668f43a2012-02-20 14:55:32 +0000492 */
493 option=argv[i];
anthony799889a2012-03-11 11:00:32 +0000494 cli_wand->line=i;
anthony686b1a32012-02-15 14:50:53 +0000495
anthony964d28e2012-05-17 23:39:46 +0000496 /* check that stacks are empty - or cause exception */
497 if (cli_wand->image_list_stack != (Stack *)NULL)
498 CLIWandException(OptionError,"UnbalancedParenthesis", "(end of cli)");
499 else if (cli_wand->image_info_stack != (Stack *)NULL)
500 CLIWandException(OptionError,"UnbalancedBraces", "(end of cli)");
501 if ( CLICatchException(cli_wand, MagickFalse) != MagickFalse )
502 return(argc);
503
anthonyf125a5e2012-04-03 13:14:42 +0000504#if MagickCommandDebug >= 3
anthonya322a832013-04-27 06:28:03 +0000505 (void) FormatLocaleFile(stderr,"CLI arg %d Write File: \"%s\"\n",i,option);
anthonyfa1e43d2012-02-12 12:55:45 +0000506#endif
507
anthony964d28e2012-05-17 23:39:46 +0000508 /* Valid 'do no write' replacement option (instead of "null:") */
anthonyfa1e43d2012-02-12 12:55:45 +0000509 if (LocaleCompare(option,"-exit") == 0 )
anthony0b46ebe2012-03-06 04:15:35 +0000510 return(argc); /* just exit, no image write */
anthonyfa1e43d2012-02-12 12:55:45 +0000511
anthonye5b39652012-04-21 05:37:29 +0000512 /* If filename looks like an option,
513 Or the common 'end of line' error of a single space.
514 -- produce an error */
515 if (IfMagickTrue(IsCommandOption(option)) ||
516 (option[0] == ' ' && option[1] == '\0') ) {
anthony0b46ebe2012-03-06 04:15:35 +0000517 CLIWandException(OptionError,"MissingOutputFilename",option);
518 return(argc);
519 }
anthonyfa1e43d2012-02-12 12:55:45 +0000520
anthony464f1c42012-04-22 08:51:01 +0000521 cli_wand->command=(const OptionInfo *)NULL;
522 CLIOption(cli_wand,"-write",option);
anthony0b46ebe2012-03-06 04:15:35 +0000523 return(argc);
anthonyfa1e43d2012-02-12 12:55:45 +0000524}
525
526/*
527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528% %
529% %
530% %
531+ M a g i c k I m a g e C o m m a n d %
532% %
533% %
534% %
535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536%
anthony668f43a2012-02-20 14:55:32 +0000537% MagickImageCommand() Handle special use CLI arguments and prepare a
anthony43f425d2012-02-26 12:58:58 +0000538% CLI MagickCLI to process the command line or directly specified script.
anthony668f43a2012-02-20 14:55:32 +0000539%
540% This is essentualy interface function between the MagickCore library
anthony43f425d2012-02-26 12:58:58 +0000541% initialization function MagickCommandGenesis(), and the option MagickCLI
anthony668f43a2012-02-20 14:55:32 +0000542% processing functions ProcessCommandOptions() or ProcessScriptOptions()
anthonyfa1e43d2012-02-12 12:55:45 +0000543%
544% The format of the MagickImageCommand method is:
545%
cristy3ec9e8d2013-01-30 16:29:51 +0000546% MagickBooleanType MagickImageCommand(ImageInfo *image_info,int argc,
547% char **argv,char **metadata,ExceptionInfo *exception)
anthonyfa1e43d2012-02-12 12:55:45 +0000548%
549% A description of each parameter follows:
550%
551% o image_info: the starting image_info structure
cristy3ec9e8d2013-01-30 16:29:51 +0000552% (for compatibilty with MagickCommandGenisis())
anthonyfa1e43d2012-02-12 12:55:45 +0000553%
554% o argc: the number of elements in the argument vector.
555%
556% o argv: A text array containing the command line arguments.
557%
anthony0ea037a2012-04-03 12:14:39 +0000558% o metadata: any metadata (for VBS) is returned here.
cristy3ec9e8d2013-01-30 16:29:51 +0000559% (for compatibilty with MagickCommandGenisis())
anthonyfa1e43d2012-02-12 12:55:45 +0000560%
561% o exception: return any errors or warnings in this structure.
562%
563*/
564
anthony40b60152012-04-04 06:13:37 +0000565static void MagickUsage(MagickBooleanType verbose)
anthonyfa1e43d2012-02-12 12:55:45 +0000566{
anthonye5fcd362012-04-09 04:02:09 +0000567 const char
568 *name;
569
570 size_t
571 len;
572
573 name=GetClientName();
574 len=strlen(name);
575
anthonyd22bf402012-04-10 01:32:03 +0000576 if (len>=7 && LocaleCompare("convert",name+len-7) == 0) {
anthonye5fcd362012-04-09 04:02:09 +0000577 /* convert usage */
578 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000579 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
anthonye5fcd362012-04-09 04:02:09 +0000580 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000581 " %s -help | -version | -usage | -list {option}\n\n",name);
anthonyd22bf402012-04-10 01:32:03 +0000582 return;
583 }
584 else if (len>=6 && LocaleCompare("script",name+len-6) == 0) {
585 /* magick-script usage */
586 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000587 "Usage: %s {filename} [ {script_args} ... ]\n",name);
anthonye5fcd362012-04-09 04:02:09 +0000588 }
589 else {
590 /* magick usage */
591 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000592 "Usage: %s [ {option} | {image} ... ] {output_image}\n",name);
anthonye5fcd362012-04-09 04:02:09 +0000593 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000594 " %s [ {option} | {image} ... ] -script {filename} [ {script_args} ...]\n",
anthonye5fcd362012-04-09 04:02:09 +0000595 name);
anthonye5fcd362012-04-09 04:02:09 +0000596 }
anthonyd22bf402012-04-10 01:32:03 +0000597 (void) FormatLocaleFile(stdout,
cristy3ec9e8d2013-01-30 16:29:51 +0000598 " %s -help | -version | -usage | -list {option}\n\n",name);
anthony40b60152012-04-04 06:13:37 +0000599
600 if (IfMagickFalse(verbose))
601 return;
602
anthonyd22bf402012-04-10 01:32:03 +0000603 (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 +0000604 "All options are performed in a strict 'as you see them' order\n",
605 "You must read-in images before you can operate on them.\n",
606 "\n",
607 "Magick Script files can use any of the following forms...\n",
608 " #!/path/to/magick -script\n",
609 "or\n",
610 " #!/bin/sh\n",
611 " :; exec magick -script \"$0\" \"$@\"; exit 10\n",
612 " # Magick script from here...\n",
613 "or\n",
614 " #!/usr/bin/env magick-script\n",
615 "The latter two forms do not require the path to the command hard coded.\n",
616 "Note: \"magick-script\" needs to be linked to the \"magick\" command.\n",
617 "\n",
618 "For more information on usage, options, examples, and techniques\n",
619 "see the ImageMagick website at ", MagickAuthoritativeURL);
620
621 return;
anthonyfa1e43d2012-02-12 12:55:45 +0000622}
623
624/*
625 Concatanate given file arguments to the given output argument.
626 Used for a special -concatenate option used for specific 'delegates'.
627 The option is not formally documented.
628
629 magick -concatenate files... output
630
631 This is much like the UNIX "cat" command, but for both UNIX and Windows,
632 however the last argument provides the output filename.
633*/
anthonyfa1e43d2012-02-12 12:55:45 +0000634static MagickBooleanType ConcatenateImages(int argc,char **argv,
anthony5216f822012-04-10 13:02:37 +0000635 ExceptionInfo *exception )
anthonyfa1e43d2012-02-12 12:55:45 +0000636{
637 FILE
638 *input,
639 *output;
640
641 int
642 c;
643
644 register ssize_t
645 i;
646
anthony451f9092012-05-11 01:56:24 +0000647 if (IfMagickFalse( ExpandFilenames(&argc,&argv) ))
anthony3b2e6072012-05-03 13:00:39 +0000648 ThrowFileException(exception,ResourceLimitError,"MemoryAllocationFailed",
649 GetExceptionMessage(errno));
650
anthonyfa1e43d2012-02-12 12:55:45 +0000651 output=fopen_utf8(argv[argc-1],"wb");
anthonyafa3dfc2012-03-03 11:31:30 +0000652 if (output == (FILE *) NULL) {
anthony5216f822012-04-10 13:02:37 +0000653 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[argc-1]);
anthonyafa3dfc2012-03-03 11:31:30 +0000654 return(MagickFalse);
655 }
656 for (i=2; i < (ssize_t) (argc-1); i++) {
anthony3b2e6072012-05-03 13:00:39 +0000657#if 0
658 fprintf(stderr, "DEBUG: Concatenate Image: \"%s\"\n", argv[i]);
659#endif
anthonyfa1e43d2012-02-12 12:55:45 +0000660 input=fopen_utf8(argv[i],"rb");
anthony3b2e6072012-05-03 13:00:39 +0000661 if (input == (FILE *) NULL) {
cristy6a0d3612012-05-02 15:39:55 +0000662 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",argv[i]);
663 continue;
664 }
anthonyfa1e43d2012-02-12 12:55:45 +0000665 for (c=fgetc(input); c != EOF; c=fgetc(input))
666 (void) fputc((char) c,output);
667 (void) fclose(input);
668 (void) remove_utf8(argv[i]);
669 }
670 (void) fclose(output);
671 return(MagickTrue);
672}
673
674WandExport MagickBooleanType MagickImageCommand(ImageInfo *image_info,
675 int argc,char **argv,char **metadata,ExceptionInfo *exception)
676{
anthony43f425d2012-02-26 12:58:58 +0000677 MagickCLI
678 *cli_wand;
anthonyfa1e43d2012-02-12 12:55:45 +0000679
anthonye5fcd362012-04-09 04:02:09 +0000680 size_t
681 len;
682
anthonya322a832013-04-27 06:28:03 +0000683 assert(image_info != (ImageInfo *)NULL);
684
anthony4cb37262012-03-18 11:18:45 +0000685 /* For specific OS command line requirements */
686 ReadCommandlLine(argc,&argv);
687
anthony668f43a2012-02-20 14:55:32 +0000688 /* Initialize special "CLI Wand" to hold images and settings (empty) */
anthony43f425d2012-02-26 12:58:58 +0000689 cli_wand=AcquireMagickCLI(image_info,exception);
anthonya322a832013-04-27 06:28:03 +0000690 cli_wand->location="Initializing";
691 cli_wand->filename=argv[0];
anthony8226e722012-04-05 14:25:46 +0000692 cli_wand->line=1;
anthonyfa1e43d2012-02-12 12:55:45 +0000693
anthonya322a832013-04-27 06:28:03 +0000694 if (IfMagickTrue(cli_wand->wand.debug))
695 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
696 "\"%s\"",argv[0]);
697
698
anthonyeff71f52012-03-29 12:59:09 +0000699 GetPathComponent(argv[0],TailPath,cli_wand->wand.name);
anthonye5fcd362012-04-09 04:02:09 +0000700 SetClientName(cli_wand->wand.name);
anthonyeff71f52012-03-29 12:59:09 +0000701 ConcatenateMagickString(cli_wand->wand.name,"-CLI",MaxTextExtent);
702
anthonye5fcd362012-04-09 04:02:09 +0000703 len=strlen(argv[0]); /* precaution */
704
glennrpe248fc22014-01-17 16:16:12 +0000705 /* "convert" command - give a "deprecated" warning" */
anthonye5fcd362012-04-09 04:02:09 +0000706 if (len>=7 && LocaleCompare("convert",argv[0]+len-7) == 0) {
anthony5216f822012-04-10 13:02:37 +0000707 cli_wand->process_flags = ConvertCommandOptionFlags;
anthonya322a832013-04-27 06:28:03 +0000708 (void) FormatLocaleFile(stderr,"WARNING: %s\n",
glennrpe248fc22014-01-17 16:16:12 +0000709 "The convert command is deprecated in IMv7, use \"magick\"\n");
anthonyeff71f52012-03-29 12:59:09 +0000710 }
anthonyeff71f52012-03-29 12:59:09 +0000711
anthony8226e722012-04-05 14:25:46 +0000712 /* Special Case: If command name ends with "script" implied "-script" */
anthonye5fcd362012-04-09 04:02:09 +0000713 if (len>=6 && LocaleCompare("script",argv[0]+len-6) == 0) {
anthonyd22bf402012-04-10 01:32:03 +0000714 if (argc >= 2 && ( (*(argv[1]) != '-') || (strlen(argv[1]) == 1) )) {
anthonye5fcd362012-04-09 04:02:09 +0000715 GetPathComponent(argv[1],TailPath,cli_wand->wand.name);
anthonya322a832013-04-27 06:28:03 +0000716 ProcessScriptOptions(cli_wand,argv[1],argc,argv,2);
anthonye5fcd362012-04-09 04:02:09 +0000717 goto Magick_Command_Cleanup;
718 }
anthony52bef752012-03-27 13:54:47 +0000719 }
720
721 /* Special Case: Version Information and Abort */
722 if (argc == 2) {
cristye4ef2952013-08-16 14:24:00 +0000723 if ((LocaleCompare("-version",argv[1]) == 0) || /* GNU standard option */
724 (LocaleCompare("--version",argv[1]) == 0) ) { /* just version */
anthony464f1c42012-04-22 08:51:01 +0000725 CLIOption(cli_wand, "-version");
anthony52bef752012-03-27 13:54:47 +0000726 goto Magick_Command_Exit;
727 }
anthony5216f822012-04-10 13:02:37 +0000728 if ((LocaleCompare("-help",argv[1]) == 0) || /* GNU standard option */
anthony464f1c42012-04-22 08:51:01 +0000729 (LocaleCompare("--help",argv[1]) == 0) ) { /* just a brief summary */
anthonya322a832013-04-27 06:28:03 +0000730 if (IfMagickTrue(cli_wand->wand.debug))
731 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
732 "- Special Option \"%s\"", argv[1]);
anthony40b60152012-04-04 06:13:37 +0000733 MagickUsage(MagickFalse);
734 goto Magick_Command_Exit;
735 }
anthony464f1c42012-04-22 08:51:01 +0000736 if (LocaleCompare("-usage",argv[1]) == 0) { /* both version & usage */
anthonya322a832013-04-27 06:28:03 +0000737 if (IfMagickTrue(cli_wand->wand.debug))
738 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
739 "- Special Option \"%s\"", argv[1]);
anthonyca487682012-04-27 07:59:27 +0000740 CLIOption(cli_wand, "-version" );
anthony40b60152012-04-04 06:13:37 +0000741 MagickUsage(MagickTrue);
742 goto Magick_Command_Exit;
743 }
anthony52bef752012-03-27 13:54:47 +0000744 }
745
746 /* not enough arguments -- including -help */
747 if (argc < 3) {
anthony40b60152012-04-04 06:13:37 +0000748 (void) FormatLocaleFile(stderr,
749 "Error: Invalid argument or not enough arguments\n\n");
750 MagickUsage(MagickFalse);
anthony52bef752012-03-27 13:54:47 +0000751 goto Magick_Command_Exit;
752 }
753
anthony0ea037a2012-04-03 12:14:39 +0000754 /* Special "concatenate option (hidden) for delegate usage */
755 if (LocaleCompare("-concatenate",argv[1]) == 0) {
anthonya322a832013-04-27 06:28:03 +0000756 if (IfMagickTrue(cli_wand->wand.debug))
757 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
758 "- Special Option \"%s\"", argv[1]);
anthony0ea037a2012-04-03 12:14:39 +0000759 ConcatenateImages(argc,argv,exception);
760 goto Magick_Command_Exit;
761 }
762
anthony06762232012-04-29 11:45:40 +0000763 /* List Information and Abort */
764 if (argc == 3 && LocaleCompare("-list",argv[1]) == 0) {
765 CLIOption(cli_wand, argv[1], argv[2]);
766 goto Magick_Command_Exit;
767 }
768
anthony52bef752012-03-27 13:54:47 +0000769 /* ------------- */
770 /* The Main Call */
771
772 if (LocaleCompare("-script",argv[1]) == 0) {
anthonyafa3dfc2012-03-03 11:31:30 +0000773 /* Start processing directly from script, no pre-script options
anthony0b46ebe2012-03-06 04:15:35 +0000774 Replace wand command name with script name
775 First argument in the argv array is the script name to read.
anthonyafa3dfc2012-03-03 11:31:30 +0000776 */
777 GetPathComponent(argv[2],TailPath,cli_wand->wand.name);
anthonya322a832013-04-27 06:28:03 +0000778 ProcessScriptOptions(cli_wand,argv[2],argc,argv,3);
anthonyafa3dfc2012-03-03 11:31:30 +0000779 }
anthony0b46ebe2012-03-06 04:15:35 +0000780 else {
anthony52bef752012-03-27 13:54:47 +0000781 /* Normal Command Line, assumes output file as last option */
anthony5216f822012-04-10 13:02:37 +0000782 ProcessCommandOptions(cli_wand,argc,argv,1);
anthony0b46ebe2012-03-06 04:15:35 +0000783 }
anthony52bef752012-03-27 13:54:47 +0000784 /* ------------- */
anthonyfa1e43d2012-02-12 12:55:45 +0000785
anthony4cb37262012-03-18 11:18:45 +0000786Magick_Command_Cleanup:
anthonya322a832013-04-27 06:28:03 +0000787 cli_wand->location="Cleanup";
788 cli_wand->filename=argv[0];
789 if (IfMagickTrue(cli_wand->wand.debug))
790 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
791 "\"%s\"",argv[0]);
792
anthony5216f822012-04-10 13:02:37 +0000793 /* recover original image_info and clean up stacks
794 FUTURE: "-reset stacks" option */
anthony8226e722012-04-05 14:25:46 +0000795 while (cli_wand->image_list_stack != (Stack *)NULL)
anthony464f1c42012-04-22 08:51:01 +0000796 CLIOption(cli_wand,")");
anthony43f425d2012-02-26 12:58:58 +0000797 while (cli_wand->image_info_stack != (Stack *)NULL)
anthony464f1c42012-04-22 08:51:01 +0000798 CLIOption(cli_wand,"}");
anthony2052d272012-02-28 12:48:29 +0000799
anthony1cdc5b72012-03-03 02:31:18 +0000800 /* assert we have recovered the original structures */
anthony43f425d2012-02-26 12:58:58 +0000801 assert(cli_wand->wand.image_info == image_info);
802 assert(cli_wand->wand.exception == exception);
anthonyfa1e43d2012-02-12 12:55:45 +0000803
804 /* Handle metadata for ImageMagickObject COM object for Windows VBS */
anthonyafa3dfc2012-03-03 11:31:30 +0000805 if (metadata != (char **) NULL) {
806 const char
807 *format;
anthonyfa1e43d2012-02-12 12:55:45 +0000808
anthonyafa3dfc2012-03-03 11:31:30 +0000809 char
810 *text;
anthonyfa1e43d2012-02-12 12:55:45 +0000811
anthonyafa3dfc2012-03-03 11:31:30 +0000812 format="%w,%h,%m"; // Get this from image_info Option splaytree
anthonyfa1e43d2012-02-12 12:55:45 +0000813
anthonyafa3dfc2012-03-03 11:31:30 +0000814 text=InterpretImageProperties(image_info,cli_wand->wand.images,format,
cristy3ec9e8d2013-01-30 16:29:51 +0000815 exception);
anthonyafa3dfc2012-03-03 11:31:30 +0000816 if (text == (char *) NULL)
817 ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
cristy3ec9e8d2013-01-30 16:29:51 +0000818 "MemoryAllocationFailed","`%s'", GetExceptionMessage(errno));
anthonyafa3dfc2012-03-03 11:31:30 +0000819 else {
820 (void) ConcatenateString(&(*metadata),text);
821 text=DestroyString(text);
anthonyfa1e43d2012-02-12 12:55:45 +0000822 }
anthonyafa3dfc2012-03-03 11:31:30 +0000823 }
anthony4cb37262012-03-18 11:18:45 +0000824
anthony52bef752012-03-27 13:54:47 +0000825Magick_Command_Exit:
anthonya322a832013-04-27 06:28:03 +0000826 cli_wand->location="Exiting";
827 cli_wand->filename=argv[0];
828 if (IfMagickTrue(cli_wand->wand.debug))
829 (void) CLILogEvent(cli_wand,CommandEvent,GetMagickModule(),
830 "\"%s\"",argv[0]);
831
anthonyfa1e43d2012-02-12 12:55:45 +0000832 /* Destroy the special CLI Wand */
anthony43f425d2012-02-26 12:58:58 +0000833 cli_wand->wand.image_info = (ImageInfo *)NULL; /* not these */
834 cli_wand->wand.exception = (ExceptionInfo *)NULL;
835 cli_wand=DestroyMagickCLI(cli_wand);
anthonyfa1e43d2012-02-12 12:55:45 +0000836
anthonyc2b913e2012-03-31 00:22:33 +0000837 return(IsMagickTrue(exception->severity > ErrorException));
anthonyfa1e43d2012-02-12 12:55:45 +0000838}