2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % 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 %
12 % WandCLI Structure Methods %
18 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
19 % dedicated to making software imaging solutions freely available. %
21 % You may not use this file except in compliance with the License. You may %
22 % obtain a copy of the License at %
24 % https://www.imagemagick.org/script/license.php %
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. %
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 % General methds for handling the WandCLI structure used for Command Line.
36 % Anthony Thyssen, April 2011
42 #include "MagickWand/studio.h"
43 #include "MagickWand/MagickWand.h"
44 #include "MagickWand/wand.h"
45 #include "MagickWand/magick-wand-private.h"
46 #include "MagickWand/wandcli.h"
47 #include "MagickWand/wandcli-private.h"
48 #include "MagickCore/exception.h"
51 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 + A c q u i r e W a n d C L I %
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
64 % Use DestroyMagickCLI() to dispose of the CLI wand when it is no longer
67 % The format of the NewMagickWand method is:
69 % MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
70 % ExceptionInfo *exception)
73 WandExport MagickCLI *AcquireMagickCLI(ImageInfo *image_info,
74 ExceptionInfo *exception)
79 /* precaution - as per NewMagickWand() */
81 size_t depth = MAGICKCORE_QUANTUM_DEPTH;
82 const char *quantum = GetMagickQuantumDepth(&depth);
83 if (depth != MAGICKCORE_QUANTUM_DEPTH)
84 ThrowWandFatalException(WandError,"QuantumDepthMismatch",quantum);
87 /* allocate memory for MgaickCLI */
88 cli_wand=(MagickCLI *) AcquireMagickMemory(sizeof(*cli_wand));
89 if (cli_wand == (MagickCLI *) NULL)
90 ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
91 GetExceptionMessage(errno));
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!
97 cli_wand->wand.id=AcquireWandId();
98 (void) FormatLocaleString(cli_wand->wand.name,MagickPathExtent,
99 "%s-%.20g","MagickWandCLI", (double) cli_wand->wand.id);
100 cli_wand->wand.images=NewImageList();
101 if ( image_info == (ImageInfo *) NULL)
102 cli_wand->wand.image_info=AcquireImageInfo();
104 cli_wand->wand.image_info=image_info;
105 if ( exception == (ExceptionInfo *) NULL)
106 cli_wand->wand.exception=AcquireExceptionInfo();
108 cli_wand->wand.exception=exception;
109 cli_wand->wand.debug=IsEventLogging();
110 cli_wand->wand.signature=MagickWandSignature;
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);
115 cli_wand->process_flags=MagickCommandOptionFlags; /* assume "magick" CLI */
116 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;
120 /* default exception location...
121 EG: sprintf(locaiton, filename, line, column);
123 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 */
129 cli_wand->signature=MagickWandSignature;
130 if (cli_wand->wand.debug != MagickFalse)
131 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 + D e s t r o y W a n d C L I %
144 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146 % DestroyMagickCLI() destorys everything in a CLI wand, including image_info
147 % and any exceptions, if still present in the wand.
149 % The format of the NewMagickWand method is:
151 % MagickWand *DestroyMagickCLI()
152 % Exception *exception)
155 WandExport MagickCLI *DestroyMagickCLI(MagickCLI *cli_wand)
160 assert(cli_wand != (MagickCLI *) NULL);
161 assert(cli_wand->signature == MagickWandSignature);
162 assert(cli_wand->wand.signature == MagickWandSignature);
163 if (cli_wand->wand.debug != MagickFalse)
164 (void) LogMagickEvent(WandEvent,GetMagickModule(),"%s",cli_wand->wand.name);
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);
171 while(cli_wand->image_list_stack != (Stack *) NULL)
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);
178 while(cli_wand->image_info_stack != (Stack *) NULL)
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);
185 cli_wand->signature=(~MagickWandSignature);
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);
194 cli_wand->wand.signature=(~MagickWandSignature);
195 cli_wand=(MagickCLI *) RelinquishMagickMemory(cli_wand);
196 return((MagickCLI *) NULL);
200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 + C L I C a t c h E x c e p t i o n %
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210 % CLICatchException() will report exceptions, either just non-fatal warnings
211 % only, or all errors, according to 'all_execeptions' boolean argument.
213 % The function returns true if errors are fatal, in which case the caller
214 % should abort and re-call with an 'all_exceptions' argument of true before
217 % The cut-off level between fatal and non-fatal may be controlled by options
218 % (FUTURE), but defaults to 'Error' exceptions.
220 % The format of the CLICatchException method is:
222 % MagickBooleanType CLICatchException(MagickCLI *cli_wand,
223 % const MagickBooleanType all_exceptions );
227 % o cli_wand: The Wand CLI that holds the exception Information
229 % o all_exceptions: Report all exceptions, including the fatal one
232 WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
233 const MagickBooleanType all_exceptions)
238 assert(cli_wand != (MagickCLI *) NULL);
239 assert(cli_wand->signature == MagickWandSignature);
240 assert(cli_wand->wand.signature == MagickWandSignature);
241 if (cli_wand->wand.debug != MagickFalse)
242 (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
249 status=cli_wand->wand.exception->severity > ErrorException ? MagickTrue :
252 if ((status == MagickFalse) || (all_exceptions != MagickFalse))
253 CatchException(cli_wand->wand.exception); /* output and clear exceptions */
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
263 + C L I L o g E v e n t %
267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269 % CLILogEvent() is a wrapper around LogMagickEvent(), adding to it the
270 % location of the option that is (about) to be executed.
273 WandExport MagickBooleanType CLILogEvent(MagickCLI *cli_wand,
274 const LogEventType type,const char *module,const char *function,
275 const size_t line,const char *format,...)
278 new_format[MagickPathExtent];
286 if (IsEventLogging() == MagickFalse)
289 /* HACK - prepend the CLI location to format string.
290 The better way would be add more arguments to to the 'va' oparands
291 list, but that does not appear to be possible! So we do some
292 pre-formating of the location info here.
294 (void) FormatLocaleString(new_format,MagickPathExtent,cli_wand->location,
295 cli_wand->filename, cli_wand->line, cli_wand->column);
296 (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
297 (void) ConcatenateMagickString(new_format,format,MagickPathExtent);
299 va_start(operands,format);
300 status=LogMagickEventList(type,module,function,line,new_format,operands);
307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311 + C L I T h r o w E x c e p t i o n %
315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317 % CLIThrowException() is a wrapper around ThrowMagickException(), adding to
318 % it the location of the option that caused the exception to occur.
320 WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand,
321 const char *module,const char *function,const size_t line,
322 const ExceptionType severity,const char *tag,const char *format,...)
325 new_format[MagickPathExtent];
336 /* HACK - append location to format string.
337 The better way would be add more arguments to to the 'va' oparands
338 list, but that does not appear to be possible! So we do some
339 pre-formating of the location info here.
341 (void) CopyMagickString(new_format,format,MagickPathExtent);
342 (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
344 len=strlen(new_format);
345 (void) FormatLocaleString(new_format+len,MagickPathExtent-len,
346 cli_wand->location,cli_wand->filename,cli_wand->line,cli_wand->column);
348 va_start(operands,format);
349 status=ThrowMagickExceptionList(cli_wand->wand.exception,module,function,
350 line,severity,tag,new_format,operands);