MagickWand  7.0.10
wandcli.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
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 %
11 % %
12 % WandCLI Structure Methods %
13 % %
14 % Dragon Computing %
15 % Anthony Thyssen %
16 % April 2011 %
17 % %
18 % Copyright 1999-2020 ImageMagick Studio LLC, a non-profit organization %
19 % 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 % https://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"
44 #include "MagickWand/wand.h"
46 #include "MagickWand/wandcli.h"
48 #include "MagickCore/exception.h"
49 
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 */
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)
90  ThrowWandFatalException(ResourceLimitFatalError,"MemoryAllocationFailed",
91  GetExceptionMessage(errno));
92 
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();
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();
103  else
104  cli_wand->wand.image_info=image_info;
105  if ( exception == (ExceptionInfo *) NULL)
106  cli_wand->wand.exception=AcquireExceptionInfo();
107  else
108  cli_wand->wand.exception=exception;
109  cli_wand->wand.debug=IsEventLogging();
111 
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;
119 
120  /* default exception location...
121  EG: sprintf(locaiton, filename, line, column);
122  */
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 */
128 
129  cli_wand->signature=MagickWandSignature;
130  if (cli_wand->wand.debug != MagickFalse)
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 */
156 {
157  Stack
158  *node;
159 
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);
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);
171  while(cli_wand->image_list_stack != (Stack *) NULL)
172  {
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  }
178  while(cli_wand->image_info_stack != (Stack *) NULL)
179  {
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  }
185  cli_wand->signature=(~MagickWandSignature);
186 
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);
197 }
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 %
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
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 %
225 % 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 %
231 */
232 WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand,
233  const MagickBooleanType all_exceptions)
234 {
235  MagickBooleanType
236  status;
237 
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);
243 
244  /*
245  FUTURE: '-regard_warning' should make this more sensitive.
246  Note pipelined options may like more control over this level
247  */
248 
249  status=cli_wand->wand.exception->severity > ErrorException ? MagickTrue :
250  MagickFalse;
251 
252  if ((status == MagickFalse) || (all_exceptions != MagickFalse))
253  CatchException(cli_wand->wand.exception); /* output and clear exceptions */
254 
255  return(status);
256 }
257 
258 /*
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 % %
261 % %
262 % %
263 + 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 */
273 WandExport MagickBooleanType CLILogEvent(MagickCLI *cli_wand,
274  const LogEventType type,const char *magick_module,const char *function,
275  const size_t line,const char *format,...)
276 {
277  char
278  new_format[MagickPathExtent];
279 
280  MagickBooleanType
281  status;
282 
283  va_list
284  operands;
285 
286  if (IsEventLogging() == MagickFalse)
287  return(MagickFalse);
288 
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.
293  */
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);
298 
299  va_start(operands,format);
300  status=LogMagickEventList(type,magick_module,function,line,new_format,
301  operands);
302  va_end(operands);
303 
304  return(status);
305 }
306 
307 /*
308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309 % %
310 % %
311 % %
312 + C L I T h r o w E x c e p t i o n %
313 % %
314 % %
315 % %
316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317 %
318 % CLIThrowException() is a wrapper around ThrowMagickException(), adding to
319 % it the location of the option that caused the exception to occur.
320 */
321 WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand,
322  const char *magick_module,const char *function,const size_t line,
323  const ExceptionType severity,const char *tag,const char *format,...)
324 {
325  char
326  new_format[MagickPathExtent];
327 
328  size_t
329  len;
330 
331  MagickBooleanType
332  status;
333 
334  va_list
335  operands;
336 
337  /* HACK - append location to format string.
338  The better way would be add more arguments to to the 'va' oparands
339  list, but that does not appear to be possible! So we do some
340  pre-formating of the location info here.
341  */
342  (void) CopyMagickString(new_format,format,MagickPathExtent);
343  (void) ConcatenateMagickString(new_format," ",MagickPathExtent);
344 
345  len=strlen(new_format);
346  (void) FormatLocaleString(new_format+len,MagickPathExtent-len,
347  cli_wand->location,cli_wand->filename,cli_wand->line,cli_wand->column);
348 
349  va_start(operands,format);
350  status=ThrowMagickExceptionList(cli_wand->wand.exception,magick_module,
351  function,line,severity,tag,new_format,operands);
352  va_end(operands);
353  return(status);
354 }
WandExport MagickBooleanType CLIThrowException(MagickCLI *cli_wand, const char *magick_module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: wandcli.c:321
#define ThrowWandFatalException(severity, tag, context)
const char * location
QuantizeInfo * quantize_info
#define MagickWandSignature
WandExport size_t AcquireWandId(void)
Definition: wand.c:74
WandExport MagickBooleanType CLILogEvent(MagickCLI *cli_wand, const LogEventType type, const char *magick_module, const char *function, const size_t line, const char *format,...)
Definition: wandcli.c:273
#define WandExport
WandExport MagickBooleanType CLICatchException(MagickCLI *cli_wand, const MagickBooleanType all_exceptions)
Definition: wandcli.c:232
WandExport void RelinquishWandId(const size_t id)
Definition: wand.c:150
MagickBooleanType debug
struct _MagickWand wand
WandExport MagickCLI * DestroyMagickCLI(MagickCLI *cli_wand)
Definition: wandcli.c:155
#define MagickPathExtent
size_t signature
Stack * image_info_stack
const OptionInfo * command
ImageInfo * image_info
char name[MagickPathExtent]
DrawInfo * draw_info
void * data
ProcessOptionFlags process_flags
struct _Stack * next
const char * filename
Stack * image_list_stack
ExceptionInfo * exception
WandExport MagickCLI * AcquireMagickCLI(ImageInfo *image_info, ExceptionInfo *exception)
Definition: wandcli.c:73