blob: 7fd4d8a1ff7a3dd67335764879aa8d6af2425f75 [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% %
cristy45ef08f2012-12-07 13:13:34 +000020% Copyright 1999-2013 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)
92 {
93 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
94 GetExceptionMessage(errno));
95 return((MagickCLI *)NULL);
96 }
97
98 /* Initialize Wand Part of MagickCLI
99 FUTURE: this is a repeat of code from NewMagickWand()
100 However some parts may be given fro man external source!
101 */
102 cli_wand->wand.id=AcquireWandId();
103 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
104 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
105 cli_wand->wand.images=NewImageList();
106 if ( image_info == (ImageInfo *)NULL)
107 cli_wand->wand.image_info=AcquireImageInfo();
108 else
109 cli_wand->wand.image_info=image_info;
110 if ( exception == (ExceptionInfo *)NULL)
111 cli_wand->wand.exception=AcquireExceptionInfo();
112 else
113 cli_wand->wand.exception=exception;
114 cli_wand->wand.debug=IsEventLogging();
115 cli_wand->wand.signature=WandSignature;
116
117 /* Initialize CLI Part of MagickCLI */
118 cli_wand->draw_info=CloneDrawInfo(cli_wand->wand.image_info,(DrawInfo *) NULL);
119 cli_wand->quantize_info=AcquireQuantizeInfo(cli_wand->wand.image_info);
anthony464f1c42012-04-22 08:51:01 +0000120 cli_wand->process_flags=MagickCommandOptionFlags; /* assume "magick" CLI */
121 cli_wand->command=(const OptionInfo *)NULL; /* no option at this time */
anthony756cd0d2012-04-08 12:41:44 +0000122 cli_wand->image_list_stack=(Stack *)NULL;
123 cli_wand->image_info_stack=(Stack *)NULL;
anthony5216f822012-04-10 13:02:37 +0000124
125 /* default exception location...
126 EG: sprintf(locaiton, filename, line, column);
127 */
anthony464f1c42012-04-22 08:51:01 +0000128 cli_wand->location="from \"%s\""; /* location format using arguments: */
129 /* filename, line, column */
130 cli_wand->filename="unknown"; /* script filename, unknown source */
131 cli_wand->line=0; /* line from script OR CLI argument */
132 cli_wand->column=0; /* column from script */
anthony756cd0d2012-04-08 12:41:44 +0000133
anthony5216f822012-04-10 13:02:37 +0000134 cli_wand->signature=WandSignature;
anthony756cd0d2012-04-08 12:41:44 +0000135 if (IfMagickTrue(cli_wand->wand.debug))
136 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
137 return(cli_wand);
138}
139
140/*
141%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142% %
143% %
144% %
145+ D e s t r o y W a n d C L I %
146% %
147% %
148% %
149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150%
151% DestroyMagickCLI() destorys everything in a CLI wand, including image_info
152% and any exceptions, if still present in the wand.
153%
154% The format of the NewMagickWand method is:
155%
156% MagickWand *DestroyMagickCLI()
157% Exception *exception)
158%
159*/
160WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
161{
162 Stack
163 *node;
164
165 assert(cli_wand != (MagickCLI *) NULL);
166 assert(cli_wand->signature == WandSignature);
167 assert(cli_wand->wand.signature == WandSignature);
168 if (IfMagickTrue(cli_wand->wand.debug))
169 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
170
171 /* Destroy CLI part of MagickCLI */
172 if (cli_wand->draw_info != (DrawInfo *) NULL )
173 cli_wand->draw_info=DestroyDrawInfo(cli_wand->draw_info);
174 if (cli_wand->quantize_info != (QuantizeInfo *) NULL )
175 cli_wand->quantize_info=DestroyQuantizeInfo(cli_wand->quantize_info);
176 while(cli_wand->image_list_stack != (Stack *)NULL)
177 {
178 node=cli_wand->image_list_stack;
179 cli_wand->image_list_stack=node->next;
180 (void) DestroyImageList((Image *)node->data);
181 (void) RelinquishMagickMemory(node);
182 }
183 while(cli_wand->image_info_stack != (Stack *)NULL)
184 {
185 node=cli_wand->image_info_stack;
186 cli_wand->image_info_stack=node->next;
187 (void) DestroyImageInfo((ImageInfo *)node->data);
188 (void) RelinquishMagickMemory(node);
189 }
190 cli_wand->signature=(~WandSignature);
191
192 /* Destroy Wand part MagickCLI */
193 cli_wand->wand.images=DestroyImageList(cli_wand->wand.images);
194 if (cli_wand->wand.image_info != (ImageInfo *) NULL )
195 cli_wand->wand.image_info=DestroyImageInfo(cli_wand->wand.image_info);
196 if (cli_wand->wand.exception != (ExceptionInfo *) NULL )
197 cli_wand->wand.exception=DestroyExceptionInfo(cli_wand->wand.exception);
198 RelinquishWandId(cli_wand->wand.id);
199 cli_wand->wand.signature=(~WandSignature);
200
201 return((MagickCLI *)NULL);
202}
203
204/*
205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206% %
207% %
208% %
209+ C L I C a t c h E x c e p t i o n %
210% %
211% %
212% %
213%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
214%
215% CLICatchException() will report exceptions, either just non-fatal warnings
216% only, or all errors, according to 'all_execeptions' boolean argument.
217%
anthony464f1c42012-04-22 08:51:01 +0000218% The function returns true if errors are fatal, in which case the caller
anthony756cd0d2012-04-08 12:41:44 +0000219% should abort and re-call with an 'all_exceptions' argument of true before
220% quitting.
221%
222% The cut-off level between fatal and non-fatal may be controlled by options
223% (FUTURE), but defaults to 'Error' exceptions.
224%
225% The format of the CLICatchException method is:
226%
227% MagickBooleanType CLICatchException(MagickCLI *cli_wand,
228% const MagickBooleanType all_exceptions );
229%
anthony464f1c42012-04-22 08:51:01 +0000230% Arguments are
231%
232% o cli_wand: The Wand CLI that holds the exception Information
233%
234% o all_exceptions: Report all exceptions, including the fatal one
235%
anthony756cd0d2012-04-08 12:41:44 +0000236*/
237WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
238 const MagickBooleanType all_exceptions )
239{
240 MagickBooleanType
241 status;
242 assert(cli_wand != (MagickCLI *) NULL);
243 assert(cli_wand->signature == WandSignature);
244 assert(cli_wand->wand.signature == WandSignature);
245 if (IfMagickTrue(cli_wand->wand.debug))
246 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
247
248 // FUTURE: '-regard_warning' should make this more sensitive.
249 // Note pipelined options may like more control over this level
250
251 status = IsMagickTrue(cli_wand->wand.exception->severity > ErrorException);
252
253 if ( IfMagickFalse(status) || IfMagickTrue(all_exceptions) )
254 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
255
256 return(status);
257}
anthony5216f822012-04-10 13:02:37 +0000258
259/*
260%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261% %
262% %
263% %
264+ C L I T h r o w E x c e p t i o n %
265% %
266% %
267% %
268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269%
270% CLIThrowException() formats and records an exception condition, adding to
271% it the location of the option that caused the exception to occur.
272*/
273WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand,
274 const char *module,const char *function,const size_t line,
275 const ExceptionType severity,const char *tag,const char *format,...)
276{
277 char
278 new_format[MaxTextExtent];
279
280 size_t
281 len;
282
283 MagickBooleanType
284 status;
285
286 va_list
287 operands;
288
289 /* HACK - append location to format string.
290 The better way would be append location formats and add more arguments to
291 operands, but that does not appear to be posible!
292 Note: ThrowMagickExceptionList() was exported specifically for
293 the use of this function.
294 */
295 (void) CopyMagickString(new_format,format,MaxTextExtent);
296 (void) ConcatenateMagickString(new_format," ",MaxTextExtent);
297
298 len=strlen(new_format);
299 (void) FormatLocaleString(new_format+len,MaxTextExtent-len,cli_wand->location,
300 cli_wand->filename, cli_wand->line, cli_wand->column);
301
302 va_start(operands,format);
303 status=ThrowMagickExceptionList(cli_wand->wand.exception,
304 module,function,line,
305 severity,tag,new_format,operands);
306 va_end(operands);
307 return(status);
308}