blob: a573e6b23858037d0e678f9cf1179096277ccb23 [file] [log] [blame]
anthony756cd0d2012-04-08 12:41:44 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
Cristy930328a2015-12-14 07:29:48 -05006% W W AA N N DDD CCC L III %
7% W W A A NN N D D C L I %
8% W W W AAAA N N N D D C L I %
9% W W W A A N NN D D C L I %
10% W W A A N N DDD CCC LLLL III %
anthony756cd0d2012-04-08 12:41:44 +000011% %
12% WandCLI Structure Methods %
13% %
14% Dragon Computing %
15% Anthony Thyssen %
16% April 2011 %
17% %
Cristy7ce65e72015-12-12 18:03:16 -050018% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
anthony756cd0d2012-04-08 12:41:44 +000019% dedicated to making software imaging solutions freely available. %
20% %
21% You may not use this file except in compliance with the License. You may %
22% obtain a copy of the License at %
23% %
24% http://www.imagemagick.org/script/license.php %
25% %
26% Unless required by applicable law or agreed to in writing, software %
27% distributed under the License is distributed on an "AS IS" BASIS, %
28% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
29% See the License for the specific language governing permissions and %
30% limitations under the License. %
31% %
32%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33%
34% General methds for handling the WandCLI structure used for Command Line.
35%
36% Anthony Thyssen, April 2011
37*/
38
39/*
40 Include declarations.
41*/
42#include "MagickWand/studio.h"
43#include "MagickWand/MagickWand.h"
anthonyea068a52012-04-09 05:46:25 +000044#include "MagickWand/wand.h"
anthony756cd0d2012-04-08 12:41:44 +000045#include "MagickWand/magick-wand-private.h"
46#include "MagickWand/wandcli.h"
47#include "MagickWand/wandcli-private.h"
anthony5216f822012-04-10 13:02:37 +000048#include "MagickCore/exception.h"
anthony756cd0d2012-04-08 12:41:44 +000049
50/*
51%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52% %
53% %
54% %
55+ A c q u i r e W a n d C L I %
56% %
57% %
58% %
59%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60%
61% AcquireMagickCLI() creates a new CLI wand (an expanded form of Magick
62% Wand). The given image_info and exception is included as is if provided.
63%
64% Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
65% needed.
66%
67% The format of the NewMagickWand method is:
68%
69% MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
70% ExceptionInfo *exception)
71%
72*/
73WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
74 ExceptionInfo *exception)
75{
76 MagickCLI
77 *cli_wand;
78
79 /* precaution - as per NewMagickWand() */
80 {
81 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
82 const char *quantum = GetMagickQuantumDepth(&depth);
83 if (depth != MAGICKCORE_QUANTUM_DEPTH)
84 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
85 }
86
87 /* allocate memory for MgaickCLI */
88 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
89 if (cli_wand == (MagickCLI *) NULL)
dirka75a7072014-03-13 19:02:15 +000090 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
91 GetExceptionMessage(errno));
anthony756cd0d2012-04-08 12:41:44 +000092
93 /* Initialize Wand Part of MagickCLI
94 FUTURE: this is a repeat of code from NewMagickWand()
95 However some parts may be given fro man external source!
96 */
97 cli_wand->wand.id=AcquireWandId();
cristy151b66d2015-04-15 10:50:31 +000098 (void) FormatLocaleString(cli_wand->wand.name,MagickPathExtent,
anthony756cd0d2012-04-08 12:41:44 +000099 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
100 cli_wand->wand.images=NewImageList();
cristyf432c632014-12-07 15:11:28 +0000101 if ( image_info == (ImageInfo *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000102 cli_wand->wand.image_info=AcquireImageInfo();
103 else
104 cli_wand->wand.image_info=image_info;
cristyf432c632014-12-07 15:11:28 +0000105 if ( exception == (ExceptionInfo *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000106 cli_wand->wand.exception=AcquireExceptionInfo();
107 else
108 cli_wand->wand.exception=exception;
109 cli_wand->wand.debug=IsEventLogging();
cristye1c94d92015-06-28 12:16:33 +0000110 cli_wand->wand.signature=MagickWandSignature;
anthony756cd0d2012-04-08 12:41:44 +0000111
112 /* Initialize CLI Part of MagickCLI */
113 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
114 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
anthony464f1c42012-04-22 08:51:01 +0000115 cli_wand->process_flags=MagickCommandOptionFlags; /* assume "magick" CLI */
cristyf432c632014-12-07 15:11:28 +0000116 cli_wand->command=(const OptionInfo *) NULL; /* no option at this time */
117 cli_wand->image_list_stack=(Stack *) NULL;
118 cli_wand->image_info_stack=(Stack *) NULL;
anthony5216f822012-04-10 13:02:37 +0000119
120 /* default exception location...
121 EG: sprintf(locaiton, filename, line, column);
122 */
anthony464f1c42012-04-22 08:51:01 +0000123 cli_wand->location="from \"%s\""; /* location format using arguments: */
124 /* filename, line, column */
125 cli_wand->filename="unknown"; /* script filename, unknown source */
126 cli_wand->line=0; /* line from script OR CLI argument */
127 cli_wand->column=0; /* column from script */
anthony756cd0d2012-04-08 12:41:44 +0000128
cristye1c94d92015-06-28 12:16:33 +0000129 cli_wand->signature=MagickWandSignature;
anthony756cd0d2012-04-08 12:41:44 +0000130 if (IfMagickTrue(cli_wand->wand.debug))
131 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
132 return(cli_wand);
133}
134
135/*
136%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137% %
138% %
139% %
140+ D e s t r o y W a n d C L I %
141% %
142% %
143% %
144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145%
146% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
147% and any exceptions, if still present in the wand.
148%
149% The format of the NewMagickWand method is:
150%
151% MagickWand *DestroyMagickCLI()
152% Exception *exception)
153%
154*/
155WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
156{
157 Stack
158 *node;
159
160 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000161 assert(cli_wand->signature == MagickWandSignature);
162 assert(cli_wand->wand.signature == MagickWandSignature);
anthony756cd0d2012-04-08 12:41:44 +0000163 if (IfMagickTrue(cli_wand->wand.debug))
164 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
165
166 /* Destroy CLI part of MagickCLI */
167 if (cli_wand->draw_info != (DrawInfo *) NULL )
168 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
169 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
170 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
cristyf432c632014-12-07 15:11:28 +0000171 while(cli_wand->image_list_stack != (Stack *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000172 {
173 node=cli_wand->image_list_stack;
174 cli_wand->image_list_stack=node->next;
175 (void) DestroyImageList((Image *)node->data);
176 (void) RelinquishMagickMemory(node);
177 }
cristyf432c632014-12-07 15:11:28 +0000178 while(cli_wand->image_info_stack != (Stack *) NULL)
anthony756cd0d2012-04-08 12:41:44 +0000179 {
180 node=cli_wand->image_info_stack;
181 cli_wand->image_info_stack=node->next;
182 (void) DestroyImageInfo((ImageInfo *)node->data);
183 (void) RelinquishMagickMemory(node);
184 }
cristye1c94d92015-06-28 12:16:33 +0000185 cli_wand->signature=(~MagickWandSignature);
anthony756cd0d2012-04-08 12:41:44 +0000186
187 /* Destroy Wand part MagickCLI */
188 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
189 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
190 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
191 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
192 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
193 RelinquishWandId(cli_wand->wand.id);
cristye1c94d92015-06-28 12:16:33 +0000194 cli_wand->wand.signature=(~MagickWandSignature);
Cristy930328a2015-12-14 07:29:48 -0500195 cli_wand=(MagickCLI *) RelinquishMagickMemory(cli_wand);
cristyf432c632014-12-07 15:11:28 +0000196 return((MagickCLI *) NULL);
anthony756cd0d2012-04-08 12:41:44 +0000197}
198
199/*
200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201% %
202% %
203% %
204+ C L I C a t c h E x c e p t i o n %
205% %
206% %
207% %
208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209%
210% CLICatchException() will report exceptions, either just non-fatal warnings
211% only, or all errors, according to 'all_execeptions' boolean argument.
212%
anthony464f1c42012-04-22 08:51:01 +0000213% The function returns true if errors are fatal, in which case the caller
anthony756cd0d2012-04-08 12:41:44 +0000214% should abort and re-call with an 'all_exceptions' argument of true before
215% quitting.
216%
217% The cut-off level between fatal and non-fatal may be controlled by options
218% (FUTURE), but defaults to 'Error' exceptions.
219%
220% The format of the CLICatchException method is:
221%
222% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
223% const MagickBooleanType all_exceptions );
224%
anthony464f1c42012-04-22 08:51:01 +0000225% Arguments are
226%
227% o cli_wand: The Wand CLI that holds the exception Information
228%
229% o all_exceptions: Report all exceptions, including the fatal one
230%
anthony756cd0d2012-04-08 12:41:44 +0000231*/
232WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
dirkb9dbc292015-07-26 09:50:00 +0000233 const MagickBooleanType all_exceptions)
anthony756cd0d2012-04-08 12:41:44 +0000234{
235 MagickBooleanType
236 status;
dirkb9dbc292015-07-26 09:50:00 +0000237
anthony756cd0d2012-04-08 12:41:44 +0000238 assert(cli_wand != (MagickCLI *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000239 assert(cli_wand->signature == MagickWandSignature);
240 assert(cli_wand->wand.signature == MagickWandSignature);
dirkb9dbc292015-07-26 09:50:00 +0000241 if (cli_wand->wand.debug != MagickFalse)
anthony756cd0d2012-04-08 12:41:44 +0000242 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
243
244 // FUTURE: '-regard_warning' should make this more sensitive.
245 // Note pipelined options may like more control over this level
246
dirkb9dbc292015-07-26 09:50:00 +0000247 status=cli_wand->wand.exception->severity > ErrorException ? MagickTrue :
248 MagickFalse;
anthony756cd0d2012-04-08 12:41:44 +0000249
dirkb9dbc292015-07-26 09:50:00 +0000250 if ((status == MagickFalse) || (all_exceptions != MagickFalse))
anthony756cd0d2012-04-08 12:41:44 +0000251 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
252
cristy220c4d52013-11-27 19:31:32 +0000253 return(status);
anthony756cd0d2012-04-08 12:41:44 +0000254}
anthony5216f822012-04-10 13:02:37 +0000255
256/*
257%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
258% %
259% %
260% %
anthonya322a832013-04-27 06:28:03 +0000261+ C L I L o g E v e n t %
262% %
263% %
264% %
265%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266%
267% CLILogEvent() is a wrapper around LogMagickEvent(), adding to it the
268% location of the option that is (about) to be executed.
269%
270*/
271WandExport MagickBooleanType CLILogEvent(MagickCLI *cli_wand,
272 const LogEventType type,const char *module,const char *function,
273 const size_t line,const char *format,...)
274{
275 char
cristy151b66d2015-04-15 10:50:31 +0000276 new_format[MagickPathExtent];
anthonya322a832013-04-27 06:28:03 +0000277
278 MagickBooleanType
279 status;
280
281 va_list
282 operands;
283
284 /* HACK - prepend the CLI location to format string.
285 The better way would be add more arguments to to the 'va' oparands
286 list, but that does not appear to be possible! So we do some
287 pre-formating of the location info here.
288 */
cristy151b66d2015-04-15 10:50:31 +0000289 (void) FormatLocaleString(new_format,MagickPathExtent,cli_wand->location,
anthonya322a832013-04-27 06:28:03 +0000290 cli_wand->filename, cli_wand->line, cli_wand->column);
cristy151b66d2015-04-15 10:50:31 +0000291 (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
292 (void) ConcatenateMagickString(new_format,format,MagickPathExtent);
anthonya322a832013-04-27 06:28:03 +0000293
294 va_start(operands,format);
295 status=LogMagickEventList(type,module,function,line,new_format,operands);
296 va_end(operands);
297
cristy220c4d52013-11-27 19:31:32 +0000298 return(status);
anthonya322a832013-04-27 06:28:03 +0000299}
300
301/*
302%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303% %
304% %
305% %
anthony5216f822012-04-10 13:02:37 +0000306+ C L I T h r o w E x c e p t i o n %
307% %
308% %
309% %
310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311%
anthonya322a832013-04-27 06:28:03 +0000312% CLIThrowException() is a wrapper around ThrowMagickException(), adding to
anthony5216f822012-04-10 13:02:37 +0000313% it the location of the option that caused the exception to occur.
314*/
315WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand,
Cristy930328a2015-12-14 07:29:48 -0500316 const char *module,const char *function,const size_t line,
317 const ExceptionType severity,const char *tag,const char *format,...)
anthony5216f822012-04-10 13:02:37 +0000318{
319 char
cristy151b66d2015-04-15 10:50:31 +0000320 new_format[MagickPathExtent];
anthony5216f822012-04-10 13:02:37 +0000321
322 size_t
323 len;
324
325 MagickBooleanType
326 status;
327
328 va_list
329 operands;
330
331 /* HACK - append location to format string.
anthonya322a832013-04-27 06:28:03 +0000332 The better way would be add more arguments to to the 'va' oparands
333 list, but that does not appear to be possible! So we do some
334 pre-formating of the location info here.
anthony5216f822012-04-10 13:02:37 +0000335 */
cristy151b66d2015-04-15 10:50:31 +0000336 (void) CopyMagickString(new_format,format,MagickPathExtent);
337 (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
anthony5216f822012-04-10 13:02:37 +0000338
339 len=strlen(new_format);
Cristy930328a2015-12-14 07:29:48 -0500340 (void) FormatLocaleString(new_format+len,MagickPathExtent-len,
341 cli_wand->location,cli_wand->filename,cli_wand->line,cli_wand->column);
anthony5216f822012-04-10 13:02:37 +0000342
343 va_start(operands,format);
Cristy930328a2015-12-14 07:29:48 -0500344 status=ThrowMagickExceptionList(cli_wand->wand.exception,module,function,
345 line,severity,tag,new_format,operands);
anthony5216f822012-04-10 13:02:37 +0000346 va_end(operands);
cristy220c4d52013-11-27 19:31:32 +0000347 return(status);
anthony5216f822012-04-10 13:02:37 +0000348}