blob: 86e1a9be3dc64f21301860e9bc78cf2b019c9570 [file] [log] [blame]
anthony756cd0d2012-04-08 12:41:44 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% M M AA GGG III CCC W W AA N N DDD CCC L III %
7% MM MM A A G I C W W A A NN N D D C L I %
8% M M M AAAA G GG I C W W W AAAA N N N D D C L I %
9% M M A A G G I C W W W A A N NN D D C L I %
10% M M A A GGG III CCC W W A A N N DDD CCC LLLL III %
11% %
12% %
13% WandCLI Structure Methods %
14% %
15% Dragon Computing %
16% Anthony Thyssen %
17% April 2011 %
18% %
19% %
cristyb56bb242014-11-25 17:12:48 +000020% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
anthony756cd0d2012-04-08 12:41:44 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% General methds for handling the WandCLI structure used for Command Line.
37%
38% Anthony Thyssen, April 2011
39*/
40
41/*
42 Include declarations.
43*/
44#include "MagickWand/studio.h"
45#include "MagickWand/MagickWand.h"
anthonyea068a52012-04-09 05:46:25 +000046#include "MagickWand/wand.h"
anthony756cd0d2012-04-08 12:41:44 +000047#include "MagickWand/magick-wand-private.h"
48#include "MagickWand/wandcli.h"
49#include "MagickWand/wandcli-private.h"
anthony5216f822012-04-10 13:02:37 +000050#include "MagickCore/exception.h"
anthony756cd0d2012-04-08 12:41:44 +000051
52/*
53%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54% %
55% %
56% %
57+ A c q u i r e W a n d C L I %
58% %
59% %
60% %
61%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
62%
63% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
64% Wand). The given image_info and exception is included as is if provided.
65%
66% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
67% needed.
68%
69% The format of the NewMagickWand method is:
70%
71% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
72% ExceptionInfo *exception)
73%
74*/
75WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
76 ExceptionInfo *exception)
77{
78 MagickCLI
79 *cli_wand;
80
81 /* precaution - as per NewMagickWand() */
82 {
83 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
84 const char *quantum = GetMagickQuantumDepth(&depth);
85 if (depth != MAGICKCORE_QUANTUM_DEPTH)
86 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
87 }
88
89 /* allocate memory for MgaickCLI */
90 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
91 if (cli_wand == (MagickCLI *) NULL)
dirka75a7072014-03-13 19:02:15 +000092 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
93 GetExceptionMessage(errno));
anthony756cd0d2012-04-08 12:41:44 +000094
95 /* Initialize Wand Part of MagickCLI
96 FUTURE: this is a repeat of code from NewMagickWand()
97 However some parts may be given fro man external source!
98 */
99 cli_wand->wand.id=AcquireWandId();
cristy151b66d2015-04-15 10:50:31 +0000100 (void) FormatLocaleString(cli_wand->wand.name,MagickPathExtent,
anthony756cd0d2012-04-08 12:41:44 +0000101 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
102 cli_wand->wand.images=NewImageList();
cristyf432c632014-12-07 15:11:28 +0000103 if ( image_info == (ImageInfo *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000104 cli_wand->wand.image_info=AcquireImageInfo();
105 else
106 cli_wand->wand.image_info=image_info;
cristyf432c632014-12-07 15:11:28 +0000107 if ( exception == (ExceptionInfo *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000108 cli_wand->wand.exception=AcquireExceptionInfo();
109 else
110 cli_wand->wand.exception=exception;
111 cli_wand->wand.debug=IsEventLogging();
cristye1c94d92015-06-28 12:16:33 +0000112 cli_wand->wand.signature=MagickWandSignature;
anthony756cd0d2012-04-08 12:41:44 +0000113
114 /* Initialize CLI Part of MagickCLI */
115 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
116 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
anthony464f1c42012-04-22 08:51:01 +0000117 cli_wand->process_flags=MagickCommandOptionFlags; /* assume "magick" CLI */
cristyf432c632014-12-07 15:11:28 +0000118 cli_wand->command=(const OptionInfo *) NULL; /* no option at this time */
119 cli_wand->image_list_stack=(Stack *) NULL;
120 cli_wand->image_info_stack=(Stack *) NULL;
anthony5216f822012-04-10 13:02:37 +0000121
122 /* default exception location...
123 EG: sprintf(locaiton, filename, line, column);
124 */
anthony464f1c42012-04-22 08:51:01 +0000125 cli_wand->location="from \"%s\""; /* location format using arguments: */
126 /* filename, line, column */
127 cli_wand->filename="unknown"; /* script filename, unknown source */
128 cli_wand->line=0; /* line from script OR CLI argument */
129 cli_wand->column=0; /* column from script */
anthony756cd0d2012-04-08 12:41:44 +0000130
cristye1c94d92015-06-28 12:16:33 +0000131 cli_wand->signature=MagickWandSignature;
anthony756cd0d2012-04-08 12:41:44 +0000132 if (IfMagickTrue(cli_wand->wand.debug))
133 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
134 return(cli_wand);
135}
136
137/*
138%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139% %
140% %
141% %
142+ D e s t r o y W a n d C L I %
143% %
144% %
145% %
146%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147%
148% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
149% and any exceptions, if still present in the wand.
150%
151% The format of the NewMagickWand method is:
152%
153% MagickWand *DestroyMagickCLI()
154% Exception *exception)
155%
156*/
157WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
158{
159 Stack
160 *node;
161
162 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000163 assert(cli_wand->signature == MagickWandSignature);
164 assert(cli_wand->wand.signature == MagickWandSignature);
anthony756cd0d2012-04-08 12:41:44 +0000165 if (IfMagickTrue(cli_wand->wand.debug))
166 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
167
168 /* Destroy CLI part of MagickCLI */
169 if (cli_wand->draw_info != (DrawInfo *) NULL )
170 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
171 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
172 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
cristyf432c632014-12-07 15:11:28 +0000173 while(cli_wand->image_list_stack != (Stack *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000174 {
175 node=cli_wand->image_list_stack;
176 cli_wand->image_list_stack=node->next;
177 (void) DestroyImageList((Image *)node->data);
178 (void) RelinquishMagickMemory(node);
179 }
cristyf432c632014-12-07 15:11:28 +0000180 while(cli_wand->image_info_stack != (Stack *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000181 {
182 node=cli_wand->image_info_stack;
183 cli_wand->image_info_stack=node->next;
184 (void) DestroyImageInfo((ImageInfo *)node->data);
185 (void) RelinquishMagickMemory(node);
186 }
cristye1c94d92015-06-28 12:16:33 +0000187 cli_wand->signature=(~MagickWandSignature);
anthony756cd0d2012-04-08 12:41:44 +0000188
189 /* Destroy Wand part MagickCLI */
190 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
191 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
192 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
193 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
194 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
195 RelinquishWandId(cli_wand->wand.id);
cristye1c94d92015-06-28 12:16:33 +0000196 cli_wand->wand.signature=(~MagickWandSignature);
anthony756cd0d2012-04-08 12:41:44 +0000197
cristyf432c632014-12-07 15:11:28 +0000198 return((MagickCLI *) NULL);
anthony756cd0d2012-04-08 12:41:44 +0000199}
200
201/*
202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
203% %
204% %
205% %
206+ C L I C a t c h E x c e p t i o n %
207% %
208% %
209% %
210%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211%
212% CLICatchException() will report exceptions, either just non-fatal warnings
213% only, or all errors, according to 'all_execeptions' boolean argument.
214%
anthony464f1c42012-04-22 08:51:01 +0000215% The function returns true if errors are fatal, in which case the caller
anthony756cd0d2012-04-08 12:41:44 +0000216% should abort and re-call with an 'all_exceptions' argument of true before
217% quitting.
218%
219% The cut-off level between fatal and non-fatal may be controlled by options
220% (FUTURE), but defaults to 'Error' exceptions.
221%
222% The format of the CLICatchException method is:
223%
224% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
225% const MagickBooleanType all_exceptions );
226%
anthony464f1c42012-04-22 08:51:01 +0000227% Arguments are
228%
229% o cli_wand: The Wand CLI that holds the exception Information
230%
231% o all_exceptions: Report all exceptions, including the fatal one
232%
anthony756cd0d2012-04-08 12:41:44 +0000233*/
234WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
dirkb9dbc292015-07-26 09:50:00 +0000235 const MagickBooleanType all_exceptions)
anthony756cd0d2012-04-08 12:41:44 +0000236{
237 MagickBooleanType
238 status;
dirkb9dbc292015-07-26 09:50:00 +0000239
anthony756cd0d2012-04-08 12:41:44 +0000240 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000241 assert(cli_wand->signature == MagickWandSignature);
242 assert(cli_wand->wand.signature == MagickWandSignature);
dirkb9dbc292015-07-26 09:50:00 +0000243 if (cli_wand->wand.debug != MagickFalse)
anthony756cd0d2012-04-08 12:41:44 +0000244 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
245
246 // FUTURE: '-regard_warning' should make this more sensitive.
247 // Note pipelined options may like more control over this level
248
dirkb9dbc292015-07-26 09:50:00 +0000249 status=cli_wand->wand.exception->severity > ErrorException ? MagickTrue :
250 MagickFalse;
anthony756cd0d2012-04-08 12:41:44 +0000251
dirkb9dbc292015-07-26 09:50:00 +0000252 if ((status == MagickFalse) || (all_exceptions != MagickFalse))
anthony756cd0d2012-04-08 12:41:44 +0000253 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
254
cristy220c4d52013-11-27 19:31:32 +0000255 return(status);
anthony756cd0d2012-04-08 12:41:44 +0000256}
anthony5216f822012-04-10 13:02:37 +0000257
258/*
259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260% %
261% %
262% %
anthonya322a832013-04-27 06:28:03 +0000263+ C L I L o g E v e n t %
264% %
265% %
266% %
267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268%
269% CLILogEvent() is a wrapper around LogMagickEvent(), adding to it the
270% location of the option that is (about) to be executed.
271%
272*/
273WandExport MagickBooleanType CLILogEvent(MagickCLI *cli_wand,
274 const LogEventType type,const char *module,const char *function,
275 const size_t line,const char *format,...)
276{
277 char
cristy151b66d2015-04-15 10:50:31 +0000278 new_format[MagickPathExtent];
anthonya322a832013-04-27 06:28:03 +0000279
280 MagickBooleanType
281 status;
282
283 va_list
284 operands;
285
286 /* HACK - prepend the CLI location to format string.
287 The better way would be add more arguments to to the 'va' oparands
288 list, but that does not appear to be possible! So we do some
289 pre-formating of the location info here.
290 */
cristy151b66d2015-04-15 10:50:31 +0000291 (void) FormatLocaleString(new_format,MagickPathExtent,cli_wand->location,
anthonya322a832013-04-27 06:28:03 +0000292 cli_wand->filename, cli_wand->line, cli_wand->column);
cristy151b66d2015-04-15 10:50:31 +0000293 (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
294 (void) ConcatenateMagickString(new_format,format,MagickPathExtent);
anthonya322a832013-04-27 06:28:03 +0000295
296 va_start(operands,format);
297 status=LogMagickEventList(type,module,function,line,new_format,operands);
298 va_end(operands);
299
300
cristy220c4d52013-11-27 19:31:32 +0000301 return(status);
anthonya322a832013-04-27 06:28:03 +0000302}
303
304/*
305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306% %
307% %
308% %
anthony5216f822012-04-10 13:02:37 +0000309+ C L I T h r o w E x c e p t i o n %
310% %
311% %
312% %
313%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314%
anthonya322a832013-04-27 06:28:03 +0000315% CLIThrowException() is a wrapper around ThrowMagickException(), adding to
anthony5216f822012-04-10 13:02:37 +0000316% it the location of the option that caused the exception to occur.
317*/
318WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand,
319 const char *module,const char *function,const size_t line,
320 const ExceptionType severity,const char *tag,const char *format,...)
321{
322 char
cristy151b66d2015-04-15 10:50:31 +0000323 new_format[MagickPathExtent];
anthony5216f822012-04-10 13:02:37 +0000324
325 size_t
326 len;
327
328 MagickBooleanType
329 status;
330
331 va_list
332 operands;
333
334 /* HACK - append location to format string.
anthonya322a832013-04-27 06:28:03 +0000335 The better way would be add more arguments to to the 'va' oparands
336 list, but that does not appear to be possible! So we do some
337 pre-formating of the location info here.
anthony5216f822012-04-10 13:02:37 +0000338 */
cristy151b66d2015-04-15 10:50:31 +0000339 (void) CopyMagickString(new_format,format,MagickPathExtent);
340 (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
anthony5216f822012-04-10 13:02:37 +0000341
342 len=strlen(new_format);
cristy151b66d2015-04-15 10:50:31 +0000343 (void) FormatLocaleString(new_format+len,MagickPathExtent-len,cli_wand->location,
anthony5216f822012-04-10 13:02:37 +0000344 cli_wand->filename, cli_wand->line, cli_wand->column);
345
346 va_start(operands,format);
347 status=ThrowMagickExceptionList(cli_wand->wand.exception,
348 module,function,line,
349 severity,tag,new_format,operands);
350 va_end(operands);
cristy220c4d52013-11-27 19:31:32 +0000351 return(status);
anthony5216f822012-04-10 13:02:37 +0000352}