blob: 0ce41603e012a2665aaf44b96b97659e50b60c04 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% CCCC OOO N N FFFFF IIIII GGGG U U RRRR EEEEE %
7% C O O NN N F I G U U R R E %
8% C O O N N N FFF I G GG U U RRRR EEE %
9% C O O N NN F I G G U U R R E %
10% CCCC OOO N N F IIIII GGG UUU R R EEEEE %
11% %
12% %
13% MagickCore Image Configure Methods %
14% %
15% Software Design %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 2003 %
18% %
19% %
cristyfe676ee2013-11-18 13:03:38 +000020% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +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%
37*/
38
39/*
40 Include declarations.
41*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/client.h"
45#include "MagickCore/configure.h"
cristy5ff4eaf2011-09-03 01:38:02 +000046#include "MagickCore/configure-private.h"
cristy4c08aed2011-07-01 19:47:50 +000047#include "MagickCore/exception.h"
48#include "MagickCore/exception-private.h"
49#include "MagickCore/hashmap.h"
50#include "MagickCore/log.h"
51#include "MagickCore/memory_.h"
52#include "MagickCore/semaphore.h"
53#include "MagickCore/string_.h"
cristy7832dc22011-09-05 01:21:53 +000054#include "MagickCore/string-private.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/token.h"
56#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000057#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000058#include "MagickCore/xml-tree.h"
cristy3291f512014-03-16 22:16:22 +000059#include "MagickCore/xml-tree-private.h"
cristy3ed852e2009-09-05 21:47:34 +000060
61/*
62 Define declarations.
63*/
64#define ConfigureFilename "configure.xml"
cristy154f9fa2012-12-05 19:30:42 +000065
66#ifdef _OPENMP
67#define MAGICKCORE_FEATURE_OPENMP_STR "OpenMP "
68#else
69#define MAGICKCORE_FEATURE_OPENMP_STR ""
70#endif
71#ifdef _OPENCL
72#define MAGICKCORE_FEATURE_OPENCL_STR "OpenCL "
73#else
74#define MAGICKCORE_FEATURE_OPENCL_STR ""
75#endif
76#ifdef MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
77#define MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR "Zero-Configuration "
78#else
79#define MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR ""
80#endif
81#ifdef HDRI_SUPPORT
82#define MAGICKCORE_FEATURE_HDRI_STR "HDRI"
83#else
84#define MAGICKCORE_FEATURE_HDRI_STR ""
85#endif
86
87#define MAGICKCORE_FEATURES_STR MAGICKCORE_FEATURE_OPENMP_STR MAGICKCORE_FEATURE_OPENCL_STR MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR MAGICKCORE_FEATURE_HDRI_STR
cristy3ed852e2009-09-05 21:47:34 +000088
89/*
cristy54a531d2009-10-21 17:58:01 +000090 Typedef declarations.
91*/
92typedef struct _ConfigureMapInfo
93{
94 const char
95 *name,
96 *value;
97} ConfigureMapInfo;
98
99/*
cristy3ed852e2009-09-05 21:47:34 +0000100 Static declarations.
101*/
cristy54a531d2009-10-21 17:58:01 +0000102static const ConfigureMapInfo
103 ConfigureMap[] =
104 {
cristy154f9fa2012-12-05 19:30:42 +0000105 { "NAME", "ImageMagick" },
106 { "QuantumDepth", MAGICKCORE_STRING_XQUOTE(MAGICKCORE_QUANTUM_DEPTH) } ,
cristybb017a02012-12-07 00:43:45 +0000107 { "FEATURES", MAGICKCORE_FEATURES_STR }
cristy54a531d2009-10-21 17:58:01 +0000108 };
cristy3ed852e2009-09-05 21:47:34 +0000109
110static LinkedListInfo
cristy86e5ac92014-03-16 19:27:39 +0000111 *configure_cache = (LinkedListInfo *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000112
113static SemaphoreInfo
114 *configure_semaphore = (SemaphoreInfo *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000115
116/*
117 Forward declarations.
118*/
119static MagickBooleanType
cristy86e5ac92014-03-16 19:27:39 +0000120 IsConfigureCacheInstantiated(ExceptionInfo *),
121 LoadConfigureCache(const char *,const char *,const size_t,ExceptionInfo *);
122
123/*
124%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125% %
126% %
127% %
128% A c q u i r e C o n f i g u r e C a c h e %
129% %
130% %
131% %
132%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133%
134% AcquireConfigureCache() caches one or more configure configuration files which
135% provides a mapping between configure attributes and a configure name.
136%
137% The format of the AcquireConfigureCache method is:
138%
139% LinkedListInfo *AcquireConfigureCache(const char *filename,
140% ExceptionInfo *exception)
141%
142% A description of each parameter follows:
143%
144% o filename: the font file name.
145%
146% o exception: return any errors or warnings in this structure.
147%
148*/
149static LinkedListInfo *AcquireConfigureCache(const char *filename,
150 ExceptionInfo *exception)
151{
152 const StringInfo
153 *option;
154
155 LinkedListInfo
156 *configure_cache,
157 *options;
158
159 MagickStatusType
160 status;
161
162 register ssize_t
163 i;
164
165 /*
166 Load external configure map.
167 */
168 configure_cache=NewLinkedList(0);
169 if (configure_cache == (LinkedListInfo *) NULL)
170 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
171 status=MagickTrue;
172 options=GetConfigureOptions(filename,exception);
173 option=(const StringInfo *) GetNextValueInLinkedList(options);
174 while (option != (const StringInfo *) NULL)
175 {
176 status&=LoadConfigureCache((const char *) GetStringInfoDatum(option),
177 GetStringInfoPath(option),0,exception);
178 option=(const StringInfo *) GetNextValueInLinkedList(options);
179 }
180 options=DestroyConfigureOptions(options);
181 /*
182 Load built-in configure map.
183 */
184 for (i=0; i < (ssize_t) (sizeof(ConfigureMap)/sizeof(*ConfigureMap)); i++)
185 {
186 ConfigureInfo
187 *configure_info;
188
189 register const ConfigureMapInfo
190 *p;
191
192 p=ConfigureMap+i;
193 configure_info=(ConfigureInfo *) AcquireMagickMemory(
194 sizeof(*configure_info));
195 if (configure_info == (ConfigureInfo *) NULL)
196 {
197 (void) ThrowMagickException(exception,GetMagickModule(),
198 ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
199 continue;
200 }
201 (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
202 configure_info->path=(char *) "[built-in]";
203 configure_info->name=(char *) p->name;
204 configure_info->value=(char *) p->value;
205 configure_info->exempt=MagickTrue;
206 configure_info->signature=MagickSignature;
207 status&=AppendValueToLinkedList(configure_cache,configure_info);
208 if (status == MagickFalse)
209 (void) ThrowMagickException(exception,GetMagickModule(),
210 ResourceLimitError,"MemoryAllocationFailed","`%s'",
211 configure_info->name);
212 }
213 return(configure_cache);
214}
cristy3ed852e2009-09-05 21:47:34 +0000215
216/*
217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218% %
219% %
220% %
cristyf34a1452009-10-24 22:29:27 +0000221+ C o n f i g u r e C o m p o n e n t G e n e s i s %
cristy3ed852e2009-09-05 21:47:34 +0000222% %
223% %
224% %
225%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226%
cristyf34a1452009-10-24 22:29:27 +0000227% ConfigureComponentGenesis() instantiates the configure component.
cristy3ed852e2009-09-05 21:47:34 +0000228%
cristyf34a1452009-10-24 22:29:27 +0000229% The format of the ConfigureComponentGenesis method is:
cristy3ed852e2009-09-05 21:47:34 +0000230%
cristyf34a1452009-10-24 22:29:27 +0000231% MagickBooleanType ConfigureComponentGenesis(void)
232%
233*/
cristy5ff4eaf2011-09-03 01:38:02 +0000234MagickPrivate MagickBooleanType ConfigureComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000235{
cristy3d162a92014-02-16 14:05:06 +0000236 configure_semaphore=AcquireSemaphoreInfo();
cristyf34a1452009-10-24 22:29:27 +0000237 return(MagickTrue);
238}
239
240/*
241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242% %
243% %
244% %
245+ C o n f i g u r e C o m p o n e n t T e r m i n u s %
246% %
247% %
248% %
249%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250%
251% ConfigureComponentTerminus() destroys the configure component.
252%
253% The format of the ConfigureComponentTerminus method is:
254%
255% ConfigureComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000256%
257*/
258
259static void *DestroyConfigureElement(void *configure_info)
260{
261 register ConfigureInfo
262 *p;
263
264 p=(ConfigureInfo *) configure_info;
cristy54a531d2009-10-21 17:58:01 +0000265 if (p->exempt == MagickFalse)
266 {
267 if (p->value != (char *) NULL)
268 p->value=DestroyString(p->value);
269 if (p->name != (char *) NULL)
270 p->name=DestroyString(p->name);
271 if (p->path != (char *) NULL)
272 p->path=DestroyString(p->path);
273 }
cristy3ed852e2009-09-05 21:47:34 +0000274 p=(ConfigureInfo *) RelinquishMagickMemory(p);
275 return((void *) NULL);
276}
277
cristy5ff4eaf2011-09-03 01:38:02 +0000278MagickPrivate void ConfigureComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000279{
cristy18b17442009-10-25 18:36:48 +0000280 if (configure_semaphore == (SemaphoreInfo *) NULL)
cristy04b11db2014-02-16 15:10:39 +0000281 ActivateSemaphoreInfo(&configure_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000282 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000283 if (configure_cache != (LinkedListInfo *) NULL)
284 configure_cache=DestroyLinkedList(configure_cache,DestroyConfigureElement);
285 configure_cache=(LinkedListInfo *) NULL;
cristyf84a1932010-01-03 18:00:18 +0000286 UnlockSemaphoreInfo(configure_semaphore);
cristy3d162a92014-02-16 14:05:06 +0000287 RelinquishSemaphoreInfo(&configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000288}
289
290/*
291%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292% %
293% %
294% %
295% D e s t r o y C o n f i g u r e O p t i o n s %
296% %
297% %
298% %
299%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
300%
301% DestroyConfigureOptions() releases memory associated with an configure
302% options.
303%
304% The format of the DestroyProfiles method is:
305%
306% LinkedListInfo *DestroyConfigureOptions(Image *image)
307%
308% A description of each parameter follows:
309%
310% o image: the image.
311%
312*/
313
314static void *DestroyOptions(void *option)
315{
316 return(DestroyStringInfo((StringInfo *) option));
317}
318
319MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
320{
321 assert(options != (LinkedListInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000322 return(DestroyLinkedList(options,DestroyOptions));
323}
324
325/*
326%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
327% %
328% %
329% %
330+ G e t C o n f i g u r e I n f o %
331% %
332% %
333% %
334%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335%
336% GetConfigureInfo() searches the configure list for the specified name and if
337% found returns attributes for that element.
338%
339% The format of the GetConfigureInfo method is:
340%
341% const ConfigureInfo *GetConfigureInfo(const char *name,
342% ExceptionInfo *exception)
343%
344% A description of each parameter follows:
345%
346% o configure_info: GetConfigureInfo() searches the configure list for the
347% specified name and if found returns attributes for that element.
348%
349% o name: the configure name.
350%
351% o exception: return any errors or warnings in this structure.
352%
353*/
354MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
355 ExceptionInfo *exception)
356{
357 register const ConfigureInfo
358 *p;
359
360 assert(exception != (ExceptionInfo *) NULL);
cristy86e5ac92014-03-16 19:27:39 +0000361 if (IsConfigureCacheInstantiated(exception) == MagickFalse)
cristy904e5912014-03-15 19:53:14 +0000362 return((const ConfigureInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000363 /*
364 Search for configure tag.
365 */
cristyf84a1932010-01-03 18:00:18 +0000366 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000367 ResetLinkedListIterator(configure_cache);
368 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy49d4d222014-03-16 00:37:58 +0000369 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
370 {
371 UnlockSemaphoreInfo(configure_semaphore);
372 return(p);
373 }
cristy3ed852e2009-09-05 21:47:34 +0000374 while (p != (const ConfigureInfo *) NULL)
375 {
376 if (LocaleCompare(name,p->name) == 0)
377 break;
cristy86e5ac92014-03-16 19:27:39 +0000378 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000379 }
380 if (p != (ConfigureInfo *) NULL)
cristy86e5ac92014-03-16 19:27:39 +0000381 (void) InsertValueInLinkedList(configure_cache,0,
382 RemoveElementByValueFromLinkedList(configure_cache,p));
cristyf84a1932010-01-03 18:00:18 +0000383 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000384 return(p);
385}
386
387/*
388%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
389% %
390% %
391% %
392% G e t C o n f i g u r e I n f o L i s t %
393% %
394% %
395% %
396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
397%
398% GetConfigureInfoList() returns any configure options that match the
399% specified pattern.
400%
401% The format of the GetConfigureInfoList function is:
402%
403% const ConfigureInfo **GetConfigureInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000404% size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000405%
406% A description of each parameter follows:
407%
408% o pattern: Specifies a pointer to a text string containing a pattern.
409%
410% o number_options: This integer returns the number of configure options in
411% the list.
412%
413% o exception: return any errors or warnings in this structure.
414%
415*/
416
417#if defined(__cplusplus) || defined(c_plusplus)
418extern "C" {
419#endif
420
421static int ConfigureInfoCompare(const void *x,const void *y)
422{
423 const ConfigureInfo
424 **p,
425 **q;
426
427 p=(const ConfigureInfo **) x,
428 q=(const ConfigureInfo **) y;
429 if (LocaleCompare((*p)->path,(*q)->path) == 0)
430 return(LocaleCompare((*p)->name,(*q)->name));
431 return(LocaleCompare((*p)->path,(*q)->path));
432}
433
434#if defined(__cplusplus) || defined(c_plusplus)
435}
436#endif
437
438MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000439 size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000440{
441 const ConfigureInfo
442 **options;
443
444 register const ConfigureInfo
445 *p;
446
cristybb503372010-05-27 20:51:26 +0000447 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000448 i;
449
450 /*
451 Allocate configure list.
452 */
453 assert(pattern != (char *) NULL);
454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000455 assert(number_options != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000456 *number_options=0;
457 p=GetConfigureInfo("*",exception);
458 if (p == (const ConfigureInfo *) NULL)
459 return((const ConfigureInfo **) NULL);
460 options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
cristy86e5ac92014-03-16 19:27:39 +0000461 GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
cristy3ed852e2009-09-05 21:47:34 +0000462 if (options == (const ConfigureInfo **) NULL)
463 return((const ConfigureInfo **) NULL);
464 /*
465 Generate configure list.
466 */
cristyf84a1932010-01-03 18:00:18 +0000467 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000468 ResetLinkedListIterator(configure_cache);
469 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000470 for (i=0; p != (const ConfigureInfo *) NULL; )
471 {
472 if ((p->stealth == MagickFalse) &&
473 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
474 options[i++]=p;
cristy86e5ac92014-03-16 19:27:39 +0000475 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000476 }
cristyf84a1932010-01-03 18:00:18 +0000477 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000478 qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
479 options[i]=(ConfigureInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000480 *number_options=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000481 return(options);
482}
483
484/*
485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486% %
487% %
488% %
489% G e t C o n f i g u r e L i s t %
490% %
491% %
492% %
493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494%
495% GetConfigureList() returns any configure options that match the specified
496% pattern.
497%
498% The format of the GetConfigureList function is:
499%
500% char **GetConfigureList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000501% size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000502%
503% A description of each parameter follows:
504%
505% o pattern: Specifies a pointer to a text string containing a pattern.
506%
507% o number_options: This integer returns the number of options in the list.
508%
509% o exception: return any errors or warnings in this structure.
510%
511*/
512
513#if defined(__cplusplus) || defined(c_plusplus)
514extern "C" {
515#endif
516
517static int ConfigureCompare(const void *x,const void *y)
518{
519 register char
520 **p,
521 **q;
522
523 p=(char **) x;
524 q=(char **) y;
525 return(LocaleCompare(*p,*q));
526}
527
528#if defined(__cplusplus) || defined(c_plusplus)
529}
530#endif
531
532MagickExport char **GetConfigureList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000533 size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000534{
535 char
536 **options;
537
538 register const ConfigureInfo
539 *p;
540
cristybb503372010-05-27 20:51:26 +0000541 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000542 i;
543
544 /*
545 Allocate configure list.
546 */
547 assert(pattern != (char *) NULL);
548 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000549 assert(number_options != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000550 *number_options=0;
551 p=GetConfigureInfo("*",exception);
552 if (p == (const ConfigureInfo *) NULL)
553 return((char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000554 options=(char **) AcquireQuantumMemory((size_t)
cristy86e5ac92014-03-16 19:27:39 +0000555 GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
cristy3ed852e2009-09-05 21:47:34 +0000556 if (options == (char **) NULL)
557 return((char **) NULL);
cristyf84a1932010-01-03 18:00:18 +0000558 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000559 ResetLinkedListIterator(configure_cache);
560 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000561 for (i=0; p != (const ConfigureInfo *) NULL; )
562 {
563 if ((p->stealth == MagickFalse) &&
564 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
565 options[i++]=ConstantString(p->name);
cristy86e5ac92014-03-16 19:27:39 +0000566 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000567 }
cristyf84a1932010-01-03 18:00:18 +0000568 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000569 qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
570 options[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000571 *number_options=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000572 return(options);
573}
574
575/*
576%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
577% %
578% %
579% %
580% G e t C o n f i g u r e O p t i o n %
581% %
582% %
583% %
584%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
585%
586% GetConfigureOption() returns the value associated with the configure option.
587%
588% The format of the GetConfigureOption method is:
589%
590% char *GetConfigureOption(const char *option)
591%
592% A description of each parameter follows:
593%
594% o configure_info: The configure info.
595%
596*/
597MagickExport char *GetConfigureOption(const char *option)
598{
599 const char
600 *value;
601
602 const ConfigureInfo
603 *configure_info;
604
605 ExceptionInfo
606 *exception;
607
608 assert(option != (const char *) NULL);
609 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
610 exception=AcquireExceptionInfo();
611 configure_info=GetConfigureInfo(option,exception);
612 exception=DestroyExceptionInfo(exception);
613 if (configure_info == (ConfigureInfo *) NULL)
614 return((char *) NULL);
615 value=GetConfigureValue(configure_info);
616 if ((value == (const char *) NULL) || (*value == '\0'))
617 return((char *) NULL);
618 return(ConstantString(value));
619}
620
621/*
622%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623% %
624% %
625% %
626% G e t C o n f i g u r e O p t i o n s %
627% %
628% %
629% %
630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631%
632% GetConfigureOptions() returns any Magick configuration options associated
633% with the specified filename.
634%
635% The format of the GetConfigureOptions method is:
636%
637% LinkedListInfo *GetConfigureOptions(const char *filename,
638% ExceptionInfo *exception)
639%
640% A description of each parameter follows:
641%
642% o filename: the configure file name.
643%
644% o exception: return any errors or warnings in this structure.
645%
646*/
647MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
648 ExceptionInfo *exception)
649{
650 char
651 path[MaxTextExtent];
652
653 const char
654 *element;
655
656 LinkedListInfo
657 *options,
658 *paths;
659
660 StringInfo
661 *xml;
662
663 assert(filename != (const char *) NULL);
664 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
665 assert(exception != (ExceptionInfo *) NULL);
666 (void) CopyMagickString(path,filename,MaxTextExtent);
667 /*
668 Load XML from configuration files to linked-list.
669 */
670 options=NewLinkedList(0);
671 paths=GetConfigurePaths(filename,exception);
672 if (paths != (LinkedListInfo *) NULL)
673 {
674 ResetLinkedListIterator(paths);
675 element=(const char *) GetNextValueInLinkedList(paths);
676 while (element != (const char *) NULL)
677 {
cristyb51dff52011-05-19 16:55:47 +0000678 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",element,filename);
cristy3ed852e2009-09-05 21:47:34 +0000679 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
680 "Searching for configure file: \"%s\"",path);
681 xml=ConfigureFileToStringInfo(path);
682 if (xml != (StringInfo *) NULL)
683 (void) AppendValueToLinkedList(options,xml);
684 element=(const char *) GetNextValueInLinkedList(paths);
685 }
686 paths=DestroyLinkedList(paths,RelinquishMagickMemory);
687 }
cristy0157aea2010-04-24 21:12:18 +0000688#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy7e247522011-11-29 14:59:23 +0000689 if (GetNumberOfElementsInLinkedList(options) == 0)
690 {
691 char
692 *blob;
cristy3ed852e2009-09-05 21:47:34 +0000693
cristy7e247522011-11-29 14:59:23 +0000694 blob=(char *) NTResourceToBlob(filename);
695 if (blob != (char *) NULL)
696 {
697 xml=AcquireStringInfo(0);
698 SetStringInfoLength(xml,strlen(blob)+1);
cristy52070b42012-02-19 22:03:21 +0000699 SetStringInfoDatum(xml,(unsigned char *) blob);
cristy7e247522011-11-29 14:59:23 +0000700 SetStringInfoPath(xml,filename);
701 (void) AppendValueToLinkedList(options,xml);
702 }
703 }
cristy3ed852e2009-09-05 21:47:34 +0000704#endif
705 if (GetNumberOfElementsInLinkedList(options) == 0)
706 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
cristyefe601c2013-01-05 17:51:12 +0000707 "UnableToOpenConfigureFile","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +0000708 ResetLinkedListIterator(options);
709 return(options);
710}
711
712/*
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714% %
715% %
716% %
717% G e t C o n f i g u r e P a t h s %
718% %
719% %
720% %
721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722%
723% GetConfigurePaths() returns any Magick configuration paths associated
724% with the specified filename.
725%
726% The format of the GetConfigurePaths method is:
727%
728% LinkedListInfo *GetConfigurePaths(const char *filename,
729% ExceptionInfo *exception)
730%
731% A description of each parameter follows:
732%
733% o filename: the configure file name.
734%
735% o exception: return any errors or warnings in this structure.
736%
737*/
738MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
739 ExceptionInfo *exception)
740{
cristy7e247522011-11-29 14:59:23 +0000741#define RegistryKey "ConfigurePath"
cristy6c28ec02011-10-28 11:37:57 +0000742#define MagickCoreDLL "CORE_RL_MagickCore_.dll"
743#define MagickCoreDebugDLL "CORE_DB_MagickCore_.dll"
744
cristy3ed852e2009-09-05 21:47:34 +0000745 char
746 path[MaxTextExtent];
747
748 LinkedListInfo
749 *paths;
750
751 assert(filename != (const char *) NULL);
752 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
753 assert(exception != (ExceptionInfo *) NULL);
754 (void) CopyMagickString(path,filename,MaxTextExtent);
755 paths=NewLinkedList(0);
756 {
757 char
758 *configure_path;
759
760 /*
761 Search $MAGICK_CONFIGURE_PATH.
762 */
763 configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
764 if (configure_path != (char *) NULL)
765 {
766 register char
767 *p,
768 *q;
769
770 for (p=configure_path-1; p != (char *) NULL; )
771 {
772 (void) CopyMagickString(path,p+1,MaxTextExtent);
773 q=strchr(path,DirectoryListSeparator);
774 if (q != (char *) NULL)
775 *q='\0';
776 q=path+strlen(path)-1;
777 if ((q >= path) && (*q != *DirectorySeparator))
778 (void) ConcatenateMagickString(path,DirectorySeparator,
779 MaxTextExtent);
780 (void) AppendValueToLinkedList(paths,ConstantString(path));
781 p=strchr(p+1,DirectoryListSeparator);
782 }
783 configure_path=DestroyString(configure_path);
784 }
785 }
786#if defined(MAGICKCORE_INSTALLED_SUPPORT)
cristy4f820712011-04-01 12:35:43 +0000787#if defined(MAGICKCORE_SHARE_PATH)
cristy6c28ec02011-10-28 11:37:57 +0000788 (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
cristy3ed852e2009-09-05 21:47:34 +0000789#endif
cristy670aa3c2011-11-03 00:54:00 +0000790#if defined(MAGICKCORE_SHAREARCH_PATH)
791 (void) AppendValueToLinkedList(paths,ConstantString(
792 MAGICKCORE_SHAREARCH_PATH));
793#endif
cristy3ed852e2009-09-05 21:47:34 +0000794#if defined(MAGICKCORE_CONFIGURE_PATH)
795 (void) AppendValueToLinkedList(paths,ConstantString(
796 MAGICKCORE_CONFIGURE_PATH));
797#endif
798#if defined(MAGICKCORE_DOCUMENTATION_PATH)
799 (void) AppendValueToLinkedList(paths,ConstantString(
800 MAGICKCORE_DOCUMENTATION_PATH));
801#endif
cristy4f820712011-04-01 12:35:43 +0000802#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
cristy3ed852e2009-09-05 21:47:34 +0000803 {
cristy3ed852e2009-09-05 21:47:34 +0000804 unsigned char
805 *key_value;
806
807 /*
808 Locate file via registry key.
809 */
cristy7e247522011-11-29 14:59:23 +0000810 key_value=NTRegistryKeyLookup(RegistryKey);
cristy3ed852e2009-09-05 21:47:34 +0000811 if (key_value != (unsigned char *) NULL)
812 {
cristyb51dff52011-05-19 16:55:47 +0000813 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",(char *) key_value,
cristy3ed852e2009-09-05 21:47:34 +0000814 DirectorySeparator);
815 (void) AppendValueToLinkedList(paths,ConstantString(path));
816 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
817 }
818 }
819#endif
820#else
821 {
822 char
823 *home;
824
825 /*
826 Search under MAGICK_HOME.
827 */
828 home=GetEnvironmentValue("MAGICK_HOME");
829 if (home != (char *) NULL)
830 {
831#if !defined(MAGICKCORE_POSIX_SUPPORT)
cristyb51dff52011-05-19 16:55:47 +0000832 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",home,
cristy3ed852e2009-09-05 21:47:34 +0000833 DirectorySeparator);
834 (void) AppendValueToLinkedList(paths,ConstantString(path));
835#else
cristyb51dff52011-05-19 16:55:47 +0000836 (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",home,
cristy3ed852e2009-09-05 21:47:34 +0000837 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
838 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristyb51dff52011-05-19 16:55:47 +0000839 (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",home,
cristy4f820712011-04-01 12:35:43 +0000840 MAGICKCORE_SHARE_RELATIVE_PATH);
cristy3ed852e2009-09-05 21:47:34 +0000841 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy780d58c2013-05-03 13:49:00 +0000842 (void) FormatLocaleString(path,MaxTextExtent,"%s",
843 MAGICKCORE_SHAREARCH_PATH);
844 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy3ed852e2009-09-05 21:47:34 +0000845#endif
846 home=DestroyString(home);
847 }
848 }
849 if (*GetClientPath() != '\0')
850 {
851#if !defined(MAGICKCORE_POSIX_SUPPORT)
cristyb51dff52011-05-19 16:55:47 +0000852 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",GetClientPath(),
cristy3ed852e2009-09-05 21:47:34 +0000853 DirectorySeparator);
854 (void) AppendValueToLinkedList(paths,ConstantString(path));
855#else
856 char
857 prefix[MaxTextExtent];
858
859 /*
860 Search based on executable directory if directory is known.
861 */
862 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
863 ChopPathComponents(prefix,1);
cristyb51dff52011-05-19 16:55:47 +0000864 (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",prefix,
cristy3ed852e2009-09-05 21:47:34 +0000865 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
866 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristyb51dff52011-05-19 16:55:47 +0000867 (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",prefix,
cristy4f820712011-04-01 12:35:43 +0000868 MAGICKCORE_SHARE_RELATIVE_PATH);
869 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy780d58c2013-05-03 13:49:00 +0000870 (void) FormatLocaleString(path,MaxTextExtent,"%s",
871 MAGICKCORE_SHAREARCH_PATH);
872 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy3ed852e2009-09-05 21:47:34 +0000873#endif
874 }
cristy51b1ac52010-10-30 02:27:14 +0000875 /*
876 Search current directory.
877 */
878 (void) AppendValueToLinkedList(paths,ConstantString(""));
cristy3ed852e2009-09-05 21:47:34 +0000879#endif
880 {
881 char
882 *home;
883
884 home=GetEnvironmentValue("HOME");
885 if (home == (char *) NULL)
886 home=GetEnvironmentValue("USERPROFILE");
887 if (home != (char *) NULL)
888 {
889 /*
cristy9f3b4fc2014-02-08 14:56:20 +0000890 Search $HOME/.config/ImageMagick.
cristy3ed852e2009-09-05 21:47:34 +0000891 */
cristy9f3b4fc2014-02-08 14:56:20 +0000892 (void) FormatLocaleString(path,MaxTextExtent,
893 "%s%s.config%sImageMagick%s",home,DirectorySeparator,
cristy3ed852e2009-09-05 21:47:34 +0000894 DirectorySeparator,DirectorySeparator);
895 (void) AppendValueToLinkedList(paths,ConstantString(path));
896 home=DestroyString(home);
897 }
898 }
cristy0157aea2010-04-24 21:12:18 +0000899#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000900 {
901 char
902 module_path[MaxTextExtent];
903
cristy6c28ec02011-10-28 11:37:57 +0000904 if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
905 (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +0000906 {
cristy7e247522011-11-29 14:59:23 +0000907 unsigned char
908 *key_value;
cristy3ed852e2009-09-05 21:47:34 +0000909
910 /*
911 Search module path.
912 */
cristyb51dff52011-05-19 16:55:47 +0000913 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000914 DirectorySeparator);
cristy7e247522011-11-29 14:59:23 +0000915 key_value=NTRegistryKeyLookup(RegistryKey);
916 if (key_value == (unsigned char *) NULL)
917 (void) AppendValueToLinkedList(paths,ConstantString(path));
918 else
919 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
cristy3ed852e2009-09-05 21:47:34 +0000920 }
921 if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
922 {
923 /*
924 Search PerlMagick module path.
925 */
cristyb51dff52011-05-19 16:55:47 +0000926 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000927 DirectorySeparator);
928 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristyb51dff52011-05-19 16:55:47 +0000929 (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000930 "\\inc\\lib\\auto\\Image\\Magick\\");
931 (void) AppendValueToLinkedList(paths,ConstantString(path));
932 }
933 }
934#endif
cristy3ed852e2009-09-05 21:47:34 +0000935 return(paths);
936}
937
938/*
939%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940% %
941% %
942% %
943% G e t C o n f i g u r e V a l u e %
944% %
945% %
946% %
947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
948%
949% GetConfigureValue() returns the value associated with the configure info.
950%
951% The format of the GetConfigureValue method is:
952%
953% const char *GetConfigureValue(const ConfigureInfo *configure_info)
954%
955% A description of each parameter follows:
956%
957% o configure_info: The configure info.
958%
959*/
960MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
961{
962 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
963 assert(configure_info != (ConfigureInfo *) NULL);
964 assert(configure_info->signature == MagickSignature);
965 return(configure_info->value);
966}
967
968/*
969%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970% %
971% %
972% %
cristy86e5ac92014-03-16 19:27:39 +0000973+ I s C o n f i g u r e C a c h e I n s t a n t i a t e d %
cristy3ed852e2009-09-05 21:47:34 +0000974% %
975% %
976% %
977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978%
cristy86e5ac92014-03-16 19:27:39 +0000979% IsConfigureCacheInstantiated() determines if the configure list is
cristy904e5912014-03-15 19:53:14 +0000980% instantiated. If not, it instantiates the list and returns it.
cristy3ed852e2009-09-05 21:47:34 +0000981%
cristy904e5912014-03-15 19:53:14 +0000982% The format of the IsConfigureInstantiated method is:
cristy3ed852e2009-09-05 21:47:34 +0000983%
cristy86e5ac92014-03-16 19:27:39 +0000984% MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000985%
986% A description of each parameter follows.
987%
988% o exception: return any errors or warnings in this structure.
989%
990*/
cristy86e5ac92014-03-16 19:27:39 +0000991static MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000992{
cristy86e5ac92014-03-16 19:27:39 +0000993 if (configure_cache == (LinkedListInfo *) NULL)
994 {
995 if (configure_semaphore == (SemaphoreInfo *) NULL)
996 ActivateSemaphoreInfo(&configure_semaphore);
997 LockSemaphoreInfo(configure_semaphore);
998 if (configure_cache == (LinkedListInfo *) NULL)
999 configure_cache=AcquireConfigureCache(ConfigureFilename,exception);
1000 UnlockSemaphoreInfo(configure_semaphore);
1001 }
1002 return(configure_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001003}
1004
1005/*
1006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1007% %
1008% %
1009% %
cristy3ed852e2009-09-05 21:47:34 +00001010% L i s t C o n f i g u r e I n f o %
1011% %
1012% %
1013% %
1014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1015%
1016% ListConfigureInfo() lists the configure info to a file.
1017%
1018% The format of the ListConfigureInfo method is:
1019%
1020% MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
1021%
1022% A description of each parameter follows.
1023%
1024% o file: An pointer to a FILE.
1025%
1026% o exception: return any errors or warnings in this structure.
1027%
1028*/
1029MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
1030 ExceptionInfo *exception)
1031{
1032 const char
1033 *name,
1034 *path,
1035 *value;
1036
1037 const ConfigureInfo
1038 **configure_info;
1039
cristybb503372010-05-27 20:51:26 +00001040 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001041 i;
1042
cristybb503372010-05-27 20:51:26 +00001043 size_t
cristy3ed852e2009-09-05 21:47:34 +00001044 number_options;
1045
cristy9d314ff2011-03-09 01:30:28 +00001046 ssize_t
1047 j;
1048
cristy3ed852e2009-09-05 21:47:34 +00001049 if (file == (const FILE *) NULL)
1050 file=stdout;
1051 configure_info=GetConfigureInfoList("*",&number_options,exception);
1052 if (configure_info == (const ConfigureInfo **) NULL)
1053 return(MagickFalse);
1054 path=(const char *) NULL;
cristybb503372010-05-27 20:51:26 +00001055 for (i=0; i < (ssize_t) number_options; i++)
cristy3ed852e2009-09-05 21:47:34 +00001056 {
1057 if (configure_info[i]->stealth != MagickFalse)
1058 continue;
1059 if ((path == (const char *) NULL) ||
1060 (LocaleCompare(path,configure_info[i]->path) != 0))
1061 {
1062 if (configure_info[i]->path != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00001063 (void) FormatLocaleFile(file,"\nPath: %s\n\n",
1064 configure_info[i]->path);
cristy9f973042012-12-06 01:28:59 +00001065 (void) FormatLocaleFile(file,"Name Value\n");
cristy1e604812011-05-19 18:07:50 +00001066 (void) FormatLocaleFile(file,
1067 "-------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +00001068 "------------------------------\n");
1069 }
1070 path=configure_info[i]->path;
1071 name="unknown";
1072 if (configure_info[i]->name != (char *) NULL)
1073 name=configure_info[i]->name;
cristyb51dff52011-05-19 16:55:47 +00001074 (void) FormatLocaleFile(file,"%s",name);
cristy9f973042012-12-06 01:28:59 +00001075 for (j=(ssize_t) strlen(name); j <= 13; j++)
cristyb51dff52011-05-19 16:55:47 +00001076 (void) FormatLocaleFile(file," ");
1077 (void) FormatLocaleFile(file," ");
cristy3ed852e2009-09-05 21:47:34 +00001078 value="unknown";
1079 if (configure_info[i]->value != (char *) NULL)
1080 value=configure_info[i]->value;
cristyb51dff52011-05-19 16:55:47 +00001081 (void) FormatLocaleFile(file,"%s",value);
1082 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00001083 }
1084 (void) fflush(file);
1085 configure_info=(const ConfigureInfo **)
1086 RelinquishMagickMemory((void *) configure_info);
1087 return(MagickTrue);
1088}
1089
1090/*
1091%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1092% %
1093% %
1094% %
1095+ L o a d C o n f i g u r e L i s t %
1096% %
1097% %
1098% %
1099%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1100%
cristy86e5ac92014-03-16 19:27:39 +00001101% LoadConfigureCache() loads the configure configurations which provides a
cristy3ed852e2009-09-05 21:47:34 +00001102% mapping between configure attributes and a configure name.
1103%
cristy86e5ac92014-03-16 19:27:39 +00001104% The format of the LoadConfigureCache method is:
cristy3ed852e2009-09-05 21:47:34 +00001105%
cristy86e5ac92014-03-16 19:27:39 +00001106% MagickBooleanType LoadConfigureCache(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +00001107% const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001108%
1109% A description of each parameter follows:
1110%
1111% o xml: The configure list in XML format.
1112%
1113% o filename: The configure list filename.
1114%
1115% o depth: depth of <include /> statements.
1116%
1117% o exception: return any errors or warnings in this structure.
1118%
1119*/
cristy86e5ac92014-03-16 19:27:39 +00001120static MagickBooleanType LoadConfigureCache(const char *xml,const char *filename,
cristybb503372010-05-27 20:51:26 +00001121 const size_t depth,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001122{
1123 char
1124 keyword[MaxTextExtent],
1125 *token;
1126
1127 ConfigureInfo
1128 *configure_info;
1129
1130 const char
1131 *q;
1132
1133 MagickBooleanType
1134 status;
1135
1136 /*
1137 Load the configure map file.
1138 */
1139 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1140 "Loading configure file \"%s\" ...",filename);
cristy86e5ac92014-03-16 19:27:39 +00001141 if (configure_cache == (LinkedListInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001142 {
cristy86e5ac92014-03-16 19:27:39 +00001143 configure_cache=NewLinkedList(0);
1144 if (configure_cache == (LinkedListInfo *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001145 {
1146 ThrowFileException(exception,ResourceLimitError,
1147 "MemoryAllocationFailed",filename);
1148 return(MagickFalse);
1149 }
1150 }
1151 status=MagickTrue;
1152 configure_info=(ConfigureInfo *) NULL;
cristy54a531d2009-10-21 17:58:01 +00001153 token=AcquireString((char *) xml);
cristy3ed852e2009-09-05 21:47:34 +00001154 for (q=(char *) xml; *q != '\0'; )
1155 {
1156 /*
1157 Interpret XML.
1158 */
1159 GetMagickToken(q,&q,token);
1160 if (*token == '\0')
1161 break;
1162 (void) CopyMagickString(keyword,token,MaxTextExtent);
1163 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1164 {
1165 /*
1166 Doctype element.
1167 */
1168 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1169 GetMagickToken(q,&q,token);
1170 continue;
1171 }
1172 if (LocaleNCompare(keyword,"<!--",4) == 0)
1173 {
1174 /*
1175 Comment element.
1176 */
1177 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1178 GetMagickToken(q,&q,token);
1179 continue;
1180 }
1181 if (LocaleCompare(keyword,"<include") == 0)
1182 {
1183 /*
1184 Include element.
1185 */
1186 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1187 {
1188 (void) CopyMagickString(keyword,token,MaxTextExtent);
1189 GetMagickToken(q,&q,token);
1190 if (*token != '=')
1191 continue;
1192 GetMagickToken(q,&q,token);
1193 if (LocaleCompare(keyword,"file") == 0)
1194 {
1195 if (depth > 200)
1196 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001197 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
cristy3ed852e2009-09-05 21:47:34 +00001198 else
1199 {
1200 char
1201 path[MaxTextExtent],
1202 *xml;
1203
1204 GetPathComponent(filename,HeadPath,path);
1205 if (*path != '\0')
1206 (void) ConcatenateMagickString(path,DirectorySeparator,
1207 MaxTextExtent);
1208 if (*token == *DirectorySeparator)
1209 (void) CopyMagickString(path,token,MaxTextExtent);
1210 else
1211 (void) ConcatenateMagickString(path,token,MaxTextExtent);
cristy3291f512014-03-16 22:16:22 +00001212 xml=FileToXML(path,~0UL);
cristy3ed852e2009-09-05 21:47:34 +00001213 if (xml != (char *) NULL)
1214 {
cristy86e5ac92014-03-16 19:27:39 +00001215 status=LoadConfigureCache(xml,path,depth+1,exception);
cristy3ed852e2009-09-05 21:47:34 +00001216 xml=(char *) RelinquishMagickMemory(xml);
1217 }
1218 }
1219 }
1220 }
1221 continue;
1222 }
1223 if (LocaleCompare(keyword,"<configure") == 0)
1224 {
1225 /*
1226 Configure element.
1227 */
1228 configure_info=(ConfigureInfo *) AcquireMagickMemory(
1229 sizeof(*configure_info));
1230 if (configure_info == (ConfigureInfo *) NULL)
1231 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1232 (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1233 configure_info->path=ConstantString(filename);
cristy54a531d2009-10-21 17:58:01 +00001234 configure_info->exempt=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00001235 configure_info->signature=MagickSignature;
1236 continue;
1237 }
1238 if (configure_info == (ConfigureInfo *) NULL)
1239 continue;
1240 if (LocaleCompare(keyword,"/>") == 0)
1241 {
cristy86e5ac92014-03-16 19:27:39 +00001242 status=AppendValueToLinkedList(configure_cache,configure_info);
cristy3ed852e2009-09-05 21:47:34 +00001243 if (status == MagickFalse)
1244 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001245 ResourceLimitError,"MemoryAllocationFailed","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001246 configure_info->name);
1247 configure_info=(ConfigureInfo *) NULL;
cristyd45122f2014-01-14 23:46:16 +00001248 continue;
cristy3ed852e2009-09-05 21:47:34 +00001249 }
1250 /*
1251 Parse configure element.
1252 */
1253 GetMagickToken(q,(const char **) NULL,token);
1254 if (*token != '=')
1255 continue;
1256 GetMagickToken(q,&q,token);
1257 GetMagickToken(q,&q,token);
1258 switch (*keyword)
1259 {
1260 case 'N':
1261 case 'n':
1262 {
1263 if (LocaleCompare((char *) keyword,"name") == 0)
1264 {
1265 configure_info->name=ConstantString(token);
1266 break;
1267 }
1268 break;
1269 }
1270 case 'S':
1271 case 's':
1272 {
1273 if (LocaleCompare((char *) keyword,"stealth") == 0)
1274 {
anthony6f201312012-03-30 04:08:15 +00001275 configure_info->stealth=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +00001276 break;
1277 }
1278 break;
1279 }
1280 case 'V':
1281 case 'v':
1282 {
1283 if (LocaleCompare((char *) keyword,"value") == 0)
1284 {
1285 configure_info->value=ConstantString(token);
1286 break;
1287 }
1288 break;
1289 }
1290 default:
1291 break;
1292 }
1293 }
1294 token=(char *) RelinquishMagickMemory(token);
1295 return(status);
1296}