2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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 %
13 % WandCLI Structure Methods %
20 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 % General methds for handling the WandCLI structure used for Command Line.
38 % Anthony Thyssen, April 2011
44 #include "MagickWand/studio.h"
45 #include "MagickWand/MagickWand.h"
46 #include "MagickWand/wand.h"
47 #include "MagickWand/magick-wand-private.h"
48 #include "MagickWand/wandcli.h"
49 #include "MagickWand/wandcli-private.h"
50 #include "MagickCore/exception.h"
53 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 + A c q u i r e W a n d C L I %
61 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
66 % Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
69 % The format of the NewMagickWand method is:
71 % MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
72 % ExceptionInfo *exception)
75 WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
76 ExceptionInfo *exception)
81 /* precaution - as per NewMagickWand() */
83 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
84 const char *quantum = GetMagickQuantumDepth(&depth);
85 if (depth != MAGICKCORE_QUANTUM_DEPTH)
86 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
89 /* allocate memory for MgaickCLI */
90 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
91 if (cli_wand == (MagickCLI *) NULL)
92 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
93 GetExceptionMessage(errno));
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!
99 cli_wand->wand.id=AcquireWandId();
100 (void) FormatLocaleString(cli_wand->wand.name,MaxTextExtent,
101 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
102 cli_wand->wand.images=NewImageList();
103 if ( image_info == (ImageInfo *)NULL)
104 cli_wand->wand.image_info=AcquireImageInfo();
106 cli_wand->wand.image_info=image_info;
107 if ( exception == (ExceptionInfo *)NULL)
108 cli_wand->wand.exception=AcquireExceptionInfo();
110 cli_wand->wand.exception=exception;
111 cli_wand->wand.debug=IsEventLogging();
112 cli_wand->wand.signature=WandSignature;
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);
117 cli_wand->process_flags=MagickCommandOptionFlags; /* assume "magick" CLI */
118 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;
122 /* default exception location...
123 EG: sprintf(locaiton, filename, line, column);
125 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 */
131 cli_wand->signature=WandSignature;
132 if (IfMagickTrue(cli_wand->wand.debug))
133 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
138 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
142 + D e s t r o y W a n d C L I %
146 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 % DestroyMagickCLI() destorys everything in a CLI wand, including image_info
149 % and any exceptions, if still present in the wand.
151 % The format of the NewMagickWand method is:
153 % MagickWand *DestroyMagickCLI()
154 % Exception *exception)
157 WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
162 assert(cli_wand != (MagickCLI *) NULL);
163 assert(cli_wand->signature == WandSignature);
164 assert(cli_wand->wand.signature == WandSignature);
165 if (IfMagickTrue(cli_wand->wand.debug))
166 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
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);
173 while(cli_wand->image_list_stack != (Stack *)NULL)
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);
180 while(cli_wand->image_info_stack != (Stack *)NULL)
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);
187 cli_wand->signature=(~WandSignature);
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);
196 cli_wand->wand.signature=(~WandSignature);
198 return((MagickCLI *)NULL);
202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206 + C L I C a t c h E x c e p t i o n %
210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212 % CLICatchException() will report exceptions, either just non-fatal warnings
213 % only, or all errors, according to 'all_execeptions' boolean argument.
215 % The function returns true if errors are fatal, in which case the caller
216 % should abort and re-call with an 'all_exceptions' argument of true before
219 % The cut-off level between fatal and non-fatal may be controlled by options
220 % (FUTURE), but defaults to 'Error' exceptions.
222 % The format of the CLICatchException method is:
224 % MagickBooleanType CLICatchException(MagickCLI *cli_wand,
225 % const MagickBooleanType all_exceptions );
229 % o cli_wand: The Wand CLI that holds the exception Information
231 % o all_exceptions: Report all exceptions, including the fatal one
234 WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
235 const MagickBooleanType all_exceptions )
239 assert(cli_wand != (MagickCLI *) NULL);
240 assert(cli_wand->signature == WandSignature);
241 assert(cli_wand->wand.signature == WandSignature);
242 if (IfMagickTrue(cli_wand->wand.debug))
243 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
245 // FUTURE: '-regard_warning' should make this more sensitive.
246 // Note pipelined options may like more control over this level
248 status = IsMagickTrue(cli_wand->wand.exception->severity > ErrorException);
250 if ( IfMagickFalse(status) || IfMagickTrue(all_exceptions) )
251 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 + C L I L o g E v e n t %
265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 % CLILogEvent() is a wrapper around LogMagickEvent(), adding to it the
268 % location of the option that is (about) to be executed.
271 WandExport MagickBooleanType CLILogEvent(MagickCLI *cli_wand,
272 const LogEventType type,const char *module,const char *function,
273 const size_t line,const char *format,...)
276 new_format[MaxTextExtent];
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.
289 (void) FormatLocaleString(new_format,MaxTextExtent,cli_wand->location,
290 cli_wand->filename, cli_wand->line, cli_wand->column);
291 (void) ConcatenateMagickString(new_format," ",MaxTextExtent);
292 (void) ConcatenateMagickString(new_format,format,MaxTextExtent);
294 va_start(operands,format);
295 status=LogMagickEventList(type,module,function,line,new_format,operands);
303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
307 + C L I T h r o w E x c e p t i o n %
311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313 % CLIThrowException() is a wrapper around ThrowMagickException(), adding to
314 % it the location of the option that caused the exception to occur.
316 WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand,
317 const char *module,const char *function,const size_t line,
318 const ExceptionType severity,const char *tag,const char *format,...)
321 new_format[MaxTextExtent];
332 /* HACK - append location to format string.
333 The better way would be add more arguments to to the 'va' oparands
334 list, but that does not appear to be possible! So we do some
335 pre-formating of the location info here.
337 (void) CopyMagickString(new_format,format,MaxTextExtent);
338 (void) ConcatenateMagickString(new_format," ",MaxTextExtent);
340 len=strlen(new_format);
341 (void) FormatLocaleString(new_format+len,MaxTextExtent-len,cli_wand->location,
342 cli_wand->filename, cli_wand->line, cli_wand->column);
344 va_start(operands,format);
345 status=ThrowMagickExceptionList(cli_wand->wand.exception,
346 module,function,line,
347 severity,tag,new_format,operands);