configure.c revision 1460f26c740619877283a50656e43db099ebfa1c
1/*
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                                %
16%                                   Cristy                                    %
17%                                 July 2003                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
21%  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*/
42#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/client.h"
45#include "MagickCore/configure.h"
46#include "MagickCore/configure-private.h"
47#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"
54#include "MagickCore/string-private.h"
55#include "MagickCore/token.h"
56#include "MagickCore/utility.h"
57#include "MagickCore/utility-private.h"
58#include "MagickCore/xml-tree.h"
59
60/*
61  Define declarations.
62*/
63#define ConfigureFilename  "configure.xml"
64
65#ifdef _OPENMP
66#define MAGICKCORE_FEATURE_OPENMP_STR "OpenMP "
67#else
68#define MAGICKCORE_FEATURE_OPENMP_STR ""
69#endif
70#ifdef _OPENCL
71#define MAGICKCORE_FEATURE_OPENCL_STR "OpenCL "
72#else
73#define MAGICKCORE_FEATURE_OPENCL_STR ""
74#endif
75#ifdef MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
76#define MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR "Zero-Configuration "
77#else
78#define MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR ""
79#endif
80#ifdef HDRI_SUPPORT
81#define MAGICKCORE_FEATURE_HDRI_STR "HDRI"
82#else
83#define MAGICKCORE_FEATURE_HDRI_STR ""
84#endif
85
86#define MAGICKCORE_FEATURES_STR MAGICKCORE_FEATURE_OPENMP_STR MAGICKCORE_FEATURE_OPENCL_STR MAGICKCORE_FEATURE_ZERO_CONFIGURATION_STR MAGICKCORE_FEATURE_HDRI_STR
87
88/*
89  Typedef declarations.
90*/
91typedef struct _ConfigureMapInfo
92{
93  const char
94    *name,
95    *value;
96} ConfigureMapInfo;
97
98/*
99  Static declarations.
100*/
101static const ConfigureMapInfo
102  ConfigureMap[] =
103  {
104    { "NAME", "ImageMagick" },
105    { "QuantumDepth", MAGICKCORE_STRING_XQUOTE(MAGICKCORE_QUANTUM_DEPTH) } ,
106    { "FEATURES", MAGICKCORE_FEATURES_STR }
107  };
108
109static LinkedListInfo
110  *configure_list = (LinkedListInfo *) NULL;
111
112static SemaphoreInfo
113  *configure_semaphore = (SemaphoreInfo *) NULL;
114
115/*
116  Forward declarations.
117*/
118static MagickBooleanType
119  InitializeConfigureList(ExceptionInfo *),
120  LoadConfigureLists(const char *,ExceptionInfo *);
121
122/*
123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124%                                                                             %
125%                                                                             %
126%                                                                             %
127+   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                         %
128%                                                                             %
129%                                                                             %
130%                                                                             %
131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132%
133%  ConfigureComponentGenesis() instantiates the configure component.
134%
135%  The format of the ConfigureComponentGenesis method is:
136%
137%      MagickBooleanType ConfigureComponentGenesis(void)
138%
139*/
140MagickPrivate MagickBooleanType ConfigureComponentGenesis(void)
141{
142  configure_semaphore=AcquireSemaphoreInfo();
143  return(MagickTrue);
144}
145
146/*
147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148%                                                                             %
149%                                                                             %
150%                                                                             %
151+   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                       %
152%                                                                             %
153%                                                                             %
154%                                                                             %
155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156%
157%  ConfigureComponentTerminus() destroys the configure component.
158%
159%  The format of the ConfigureComponentTerminus method is:
160%
161%      ConfigureComponentTerminus(void)
162%
163*/
164
165static void *DestroyConfigureElement(void *configure_info)
166{
167  register ConfigureInfo
168    *p;
169
170  p=(ConfigureInfo *) configure_info;
171  if (p->exempt == MagickFalse)
172    {
173      if (p->value != (char *) NULL)
174        p->value=DestroyString(p->value);
175      if (p->name != (char *) NULL)
176        p->name=DestroyString(p->name);
177      if (p->path != (char *) NULL)
178        p->path=DestroyString(p->path);
179    }
180  p=(ConfigureInfo *) RelinquishMagickMemory(p);
181  return((void *) NULL);
182}
183
184MagickPrivate void ConfigureComponentTerminus(void)
185{
186  if (configure_semaphore == (SemaphoreInfo *) NULL)
187    ActivateSemaphoreInfo(&configure_semaphore);
188  LockSemaphoreInfo(configure_semaphore);
189  if (configure_list != (LinkedListInfo *) NULL)
190    configure_list=DestroyLinkedList(configure_list,DestroyConfigureElement);
191  configure_list=(LinkedListInfo *) NULL;
192  UnlockSemaphoreInfo(configure_semaphore);
193  RelinquishSemaphoreInfo(&configure_semaphore);
194}
195
196/*
197%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
198%                                                                             %
199%                                                                             %
200%                                                                             %
201%   D e s t r o y C o n f i g u r e O p t i o n s                             %
202%                                                                             %
203%                                                                             %
204%                                                                             %
205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
206%
207%  DestroyConfigureOptions() releases memory associated with an configure
208%  options.
209%
210%  The format of the DestroyProfiles method is:
211%
212%      LinkedListInfo *DestroyConfigureOptions(Image *image)
213%
214%  A description of each parameter follows:
215%
216%    o image: the image.
217%
218*/
219
220static void *DestroyOptions(void *option)
221{
222  return(DestroyStringInfo((StringInfo *) option));
223}
224
225MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
226{
227  assert(options != (LinkedListInfo *) NULL);
228  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
229  return(DestroyLinkedList(options,DestroyOptions));
230}
231
232/*
233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
234%                                                                             %
235%                                                                             %
236%                                                                             %
237+   G e t C o n f i g u r e I n f o                                           %
238%                                                                             %
239%                                                                             %
240%                                                                             %
241%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242%
243%  GetConfigureInfo() searches the configure list for the specified name and if
244%  found returns attributes for that element.
245%
246%  The format of the GetConfigureInfo method is:
247%
248%      const ConfigureInfo *GetConfigureInfo(const char *name,
249%        ExceptionInfo *exception)
250%
251%  A description of each parameter follows:
252%
253%    o configure_info: GetConfigureInfo() searches the configure list for the
254%      specified name and if found returns attributes for that element.
255%
256%    o name: the configure name.
257%
258%    o exception: return any errors or warnings in this structure.
259%
260*/
261MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
262  ExceptionInfo *exception)
263{
264  register const ConfigureInfo
265    *p;
266
267  assert(exception != (ExceptionInfo *) NULL);
268  if (configure_list == (LinkedListInfo *) NULL)
269    if (InitializeConfigureList(exception) == MagickFalse)
270      return((const ConfigureInfo *) NULL);
271  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
272    return((const ConfigureInfo *) GetValueFromLinkedList(configure_list,0));
273  /*
274    Search for configure tag.
275  */
276  LockSemaphoreInfo(configure_semaphore);
277  ResetLinkedListIterator(configure_list);
278  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
279  while (p != (const ConfigureInfo *) NULL)
280  {
281    if (LocaleCompare(name,p->name) == 0)
282      break;
283    p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
284  }
285  if (p != (ConfigureInfo *) NULL)
286    (void) InsertValueInLinkedList(configure_list,0,
287      RemoveElementByValueFromLinkedList(configure_list,p));
288  UnlockSemaphoreInfo(configure_semaphore);
289  return(p);
290}
291
292/*
293%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
294%                                                                             %
295%                                                                             %
296%                                                                             %
297%   G e t C o n f i g u r e I n f o L i s t                                   %
298%                                                                             %
299%                                                                             %
300%                                                                             %
301%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302%
303%  GetConfigureInfoList() returns any configure options that match the
304%  specified pattern.
305%
306%  The format of the GetConfigureInfoList function is:
307%
308%      const ConfigureInfo **GetConfigureInfoList(const char *pattern,
309%        size_t *number_options,ExceptionInfo *exception)
310%
311%  A description of each parameter follows:
312%
313%    o pattern: Specifies a pointer to a text string containing a pattern.
314%
315%    o number_options:  This integer returns the number of configure options in
316%    the list.
317%
318%    o exception: return any errors or warnings in this structure.
319%
320*/
321
322#if defined(__cplusplus) || defined(c_plusplus)
323extern "C" {
324#endif
325
326static int ConfigureInfoCompare(const void *x,const void *y)
327{
328  const ConfigureInfo
329    **p,
330    **q;
331
332  p=(const ConfigureInfo **) x,
333  q=(const ConfigureInfo **) y;
334  if (LocaleCompare((*p)->path,(*q)->path) == 0)
335    return(LocaleCompare((*p)->name,(*q)->name));
336  return(LocaleCompare((*p)->path,(*q)->path));
337}
338
339#if defined(__cplusplus) || defined(c_plusplus)
340}
341#endif
342
343MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
344  size_t *number_options,ExceptionInfo *exception)
345{
346  const ConfigureInfo
347    **options;
348
349  register const ConfigureInfo
350    *p;
351
352  register ssize_t
353    i;
354
355  /*
356    Allocate configure list.
357  */
358  assert(pattern != (char *) NULL);
359  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
360  assert(number_options != (size_t *) NULL);
361  *number_options=0;
362  p=GetConfigureInfo("*",exception);
363  if (p == (const ConfigureInfo *) NULL)
364    return((const ConfigureInfo **) NULL);
365  options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
366    GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
367  if (options == (const ConfigureInfo **) NULL)
368    return((const ConfigureInfo **) NULL);
369  /*
370    Generate configure list.
371  */
372  LockSemaphoreInfo(configure_semaphore);
373  ResetLinkedListIterator(configure_list);
374  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
375  for (i=0; p != (const ConfigureInfo *) NULL; )
376  {
377    if ((p->stealth == MagickFalse) &&
378        (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
379      options[i++]=p;
380    p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
381  }
382  UnlockSemaphoreInfo(configure_semaphore);
383  qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
384  options[i]=(ConfigureInfo *) NULL;
385  *number_options=(size_t) i;
386  return(options);
387}
388
389/*
390%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391%                                                                             %
392%                                                                             %
393%                                                                             %
394%   G e t C o n f i g u r e L i s t                                           %
395%                                                                             %
396%                                                                             %
397%                                                                             %
398%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399%
400%  GetConfigureList() returns any configure options that match the specified
401%  pattern.
402%
403%  The format of the GetConfigureList function is:
404%
405%      char **GetConfigureList(const char *pattern,
406%        size_t *number_options,ExceptionInfo *exception)
407%
408%  A description of each parameter follows:
409%
410%    o pattern: Specifies a pointer to a text string containing a pattern.
411%
412%    o number_options:  This integer returns the number of options in the list.
413%
414%    o exception: return any errors or warnings in this structure.
415%
416*/
417
418#if defined(__cplusplus) || defined(c_plusplus)
419extern "C" {
420#endif
421
422static int ConfigureCompare(const void *x,const void *y)
423{
424  register char
425    **p,
426    **q;
427
428  p=(char **) x;
429  q=(char **) y;
430  return(LocaleCompare(*p,*q));
431}
432
433#if defined(__cplusplus) || defined(c_plusplus)
434}
435#endif
436
437MagickExport char **GetConfigureList(const char *pattern,
438  size_t *number_options,ExceptionInfo *exception)
439{
440  char
441    **options;
442
443  register const ConfigureInfo
444    *p;
445
446  register ssize_t
447    i;
448
449  /*
450    Allocate configure list.
451  */
452  assert(pattern != (char *) NULL);
453  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
454  assert(number_options != (size_t *) NULL);
455  *number_options=0;
456  p=GetConfigureInfo("*",exception);
457  if (p == (const ConfigureInfo *) NULL)
458    return((char **) NULL);
459  options=(char **) AcquireQuantumMemory((size_t)
460    GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
461  if (options == (char **) NULL)
462    return((char **) NULL);
463  LockSemaphoreInfo(configure_semaphore);
464  ResetLinkedListIterator(configure_list);
465  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
466  for (i=0; p != (const ConfigureInfo *) NULL; )
467  {
468    if ((p->stealth == MagickFalse) &&
469        (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
470      options[i++]=ConstantString(p->name);
471    p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
472  }
473  UnlockSemaphoreInfo(configure_semaphore);
474  qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
475  options[i]=(char *) NULL;
476  *number_options=(size_t) i;
477  return(options);
478}
479
480/*
481%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482%                                                                             %
483%                                                                             %
484%                                                                             %
485%   G e t C o n f i g u r e O p t i o n                                       %
486%                                                                             %
487%                                                                             %
488%                                                                             %
489%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490%
491%  GetConfigureOption() returns the value associated with the configure option.
492%
493%  The format of the GetConfigureOption method is:
494%
495%      char *GetConfigureOption(const char *option)
496%
497%  A description of each parameter follows:
498%
499%    o configure_info:  The configure info.
500%
501*/
502MagickExport char *GetConfigureOption(const char *option)
503{
504  const char
505    *value;
506
507  const ConfigureInfo
508    *configure_info;
509
510  ExceptionInfo
511    *exception;
512
513  assert(option != (const char *) NULL);
514  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
515  exception=AcquireExceptionInfo();
516  configure_info=GetConfigureInfo(option,exception);
517  exception=DestroyExceptionInfo(exception);
518  if (configure_info == (ConfigureInfo *) NULL)
519    return((char *) NULL);
520  value=GetConfigureValue(configure_info);
521  if ((value == (const char *) NULL) || (*value == '\0'))
522    return((char *) NULL);
523  return(ConstantString(value));
524}
525
526/*
527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
528%                                                                             %
529%                                                                             %
530%                                                                             %
531%  G e t C o n f i g u r e O p t i o n s                                      %
532%                                                                             %
533%                                                                             %
534%                                                                             %
535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
536%
537%  GetConfigureOptions() returns any Magick configuration options associated
538%  with the specified filename.
539%
540%  The format of the GetConfigureOptions method is:
541%
542%      LinkedListInfo *GetConfigureOptions(const char *filename,
543%        ExceptionInfo *exception)
544%
545%  A description of each parameter follows:
546%
547%    o filename: the configure file name.
548%
549%    o exception: return any errors or warnings in this structure.
550%
551*/
552MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
553  ExceptionInfo *exception)
554{
555  char
556    path[MaxTextExtent];
557
558  const char
559    *element;
560
561  LinkedListInfo
562    *options,
563    *paths;
564
565  StringInfo
566    *xml;
567
568  assert(filename != (const char *) NULL);
569  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
570  assert(exception != (ExceptionInfo *) NULL);
571  (void) CopyMagickString(path,filename,MaxTextExtent);
572  /*
573    Load XML from configuration files to linked-list.
574  */
575  options=NewLinkedList(0);
576  paths=GetConfigurePaths(filename,exception);
577  if (paths != (LinkedListInfo *) NULL)
578    {
579      ResetLinkedListIterator(paths);
580      element=(const char *) GetNextValueInLinkedList(paths);
581      while (element != (const char *) NULL)
582      {
583        (void) FormatLocaleString(path,MaxTextExtent,"%s%s",element,filename);
584        (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
585          "Searching for configure file: \"%s\"",path);
586        xml=ConfigureFileToStringInfo(path);
587        if (xml != (StringInfo *) NULL)
588          (void) AppendValueToLinkedList(options,xml);
589        element=(const char *) GetNextValueInLinkedList(paths);
590      }
591      paths=DestroyLinkedList(paths,RelinquishMagickMemory);
592    }
593#if defined(MAGICKCORE_WINDOWS_SUPPORT)
594  if (GetNumberOfElementsInLinkedList(options) == 0)
595    {
596      char
597        *blob;
598
599      blob=(char *) NTResourceToBlob(filename);
600      if (blob != (char *) NULL)
601        {
602          xml=AcquireStringInfo(0);
603          SetStringInfoLength(xml,strlen(blob)+1);
604          SetStringInfoDatum(xml,(unsigned char *) blob);
605          SetStringInfoPath(xml,filename);
606          (void) AppendValueToLinkedList(options,xml);
607        }
608    }
609#endif
610  if (GetNumberOfElementsInLinkedList(options) == 0)
611    (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
612      "UnableToOpenConfigureFile","`%s'",filename);
613  ResetLinkedListIterator(options);
614  return(options);
615}
616
617/*
618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619%                                                                             %
620%                                                                             %
621%                                                                             %
622%  G e t C o n f i g u r e P a t h s                                          %
623%                                                                             %
624%                                                                             %
625%                                                                             %
626%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
627%
628%  GetConfigurePaths() returns any Magick configuration paths associated
629%  with the specified filename.
630%
631%  The format of the GetConfigurePaths method is:
632%
633%      LinkedListInfo *GetConfigurePaths(const char *filename,
634%        ExceptionInfo *exception)
635%
636%  A description of each parameter follows:
637%
638%    o filename: the configure file name.
639%
640%    o exception: return any errors or warnings in this structure.
641%
642*/
643MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
644  ExceptionInfo *exception)
645{
646#define RegistryKey  "ConfigurePath"
647#define MagickCoreDLL  "CORE_RL_MagickCore_.dll"
648#define MagickCoreDebugDLL  "CORE_DB_MagickCore_.dll"
649
650  char
651    path[MaxTextExtent];
652
653  LinkedListInfo
654    *paths;
655
656  assert(filename != (const char *) NULL);
657  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
658  assert(exception != (ExceptionInfo *) NULL);
659  (void) CopyMagickString(path,filename,MaxTextExtent);
660  paths=NewLinkedList(0);
661  {
662    char
663      *configure_path;
664
665    /*
666      Search $MAGICK_CONFIGURE_PATH.
667    */
668    configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
669    if (configure_path != (char *) NULL)
670      {
671        register char
672          *p,
673          *q;
674
675        for (p=configure_path-1; p != (char *) NULL; )
676        {
677          (void) CopyMagickString(path,p+1,MaxTextExtent);
678          q=strchr(path,DirectoryListSeparator);
679          if (q != (char *) NULL)
680            *q='\0';
681          q=path+strlen(path)-1;
682          if ((q >= path) && (*q != *DirectorySeparator))
683            (void) ConcatenateMagickString(path,DirectorySeparator,
684              MaxTextExtent);
685          (void) AppendValueToLinkedList(paths,ConstantString(path));
686          p=strchr(p+1,DirectoryListSeparator);
687        }
688        configure_path=DestroyString(configure_path);
689      }
690  }
691#if defined(MAGICKCORE_INSTALLED_SUPPORT)
692#if defined(MAGICKCORE_SHARE_PATH)
693  (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
694#endif
695#if defined(MAGICKCORE_SHAREARCH_PATH)
696  (void) AppendValueToLinkedList(paths,ConstantString(
697    MAGICKCORE_SHAREARCH_PATH));
698#endif
699#if defined(MAGICKCORE_CONFIGURE_PATH)
700  (void) AppendValueToLinkedList(paths,ConstantString(
701    MAGICKCORE_CONFIGURE_PATH));
702#endif
703#if defined(MAGICKCORE_DOCUMENTATION_PATH)
704  (void) AppendValueToLinkedList(paths,ConstantString(
705    MAGICKCORE_DOCUMENTATION_PATH));
706#endif
707#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
708  {
709    unsigned char
710      *key_value;
711
712    /*
713      Locate file via registry key.
714    */
715    key_value=NTRegistryKeyLookup(RegistryKey);
716    if (key_value != (unsigned char *) NULL)
717      {
718        (void) FormatLocaleString(path,MaxTextExtent,"%s%s",(char *) key_value,
719          DirectorySeparator);
720        (void) AppendValueToLinkedList(paths,ConstantString(path));
721        key_value=(unsigned char *) RelinquishMagickMemory(key_value);
722      }
723  }
724#endif
725#else
726  {
727    char
728      *home;
729
730    /*
731      Search under MAGICK_HOME.
732    */
733    home=GetEnvironmentValue("MAGICK_HOME");
734    if (home != (char *) NULL)
735      {
736#if !defined(MAGICKCORE_POSIX_SUPPORT)
737        (void) FormatLocaleString(path,MaxTextExtent,"%s%s",home,
738          DirectorySeparator);
739        (void) AppendValueToLinkedList(paths,ConstantString(path));
740#else
741        (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",home,
742          MAGICKCORE_CONFIGURE_RELATIVE_PATH);
743        (void) AppendValueToLinkedList(paths,ConstantString(path));
744        (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",home,
745          MAGICKCORE_SHARE_RELATIVE_PATH);
746        (void) AppendValueToLinkedList(paths,ConstantString(path));
747        (void) FormatLocaleString(path,MaxTextExtent,"%s",
748          MAGICKCORE_SHAREARCH_PATH);
749        (void) AppendValueToLinkedList(paths,ConstantString(path));
750#endif
751        home=DestroyString(home);
752      }
753    }
754  if (*GetClientPath() != '\0')
755    {
756#if !defined(MAGICKCORE_POSIX_SUPPORT)
757      (void) FormatLocaleString(path,MaxTextExtent,"%s%s",GetClientPath(),
758        DirectorySeparator);
759      (void) AppendValueToLinkedList(paths,ConstantString(path));
760#else
761      char
762        prefix[MaxTextExtent];
763
764      /*
765        Search based on executable directory if directory is known.
766      */
767      (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
768      ChopPathComponents(prefix,1);
769      (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",prefix,
770        MAGICKCORE_CONFIGURE_RELATIVE_PATH);
771      (void) AppendValueToLinkedList(paths,ConstantString(path));
772      (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",prefix,
773        MAGICKCORE_SHARE_RELATIVE_PATH);
774      (void) AppendValueToLinkedList(paths,ConstantString(path));
775      (void) FormatLocaleString(path,MaxTextExtent,"%s",
776        MAGICKCORE_SHAREARCH_PATH);
777      (void) AppendValueToLinkedList(paths,ConstantString(path));
778#endif
779    }
780  /*
781    Search current directory.
782  */
783  (void) AppendValueToLinkedList(paths,ConstantString(""));
784#endif
785  {
786    char
787      *home;
788
789    home=GetEnvironmentValue("HOME");
790    if (home == (char *) NULL)
791      home=GetEnvironmentValue("USERPROFILE");
792    if (home != (char *) NULL)
793      {
794        /*
795          Search $HOME/.config/ImageMagick.
796        */
797        (void) FormatLocaleString(path,MaxTextExtent,
798          "%s%s.config%sImageMagick%s",home,DirectorySeparator,
799          DirectorySeparator,DirectorySeparator);
800        (void) AppendValueToLinkedList(paths,ConstantString(path));
801        home=DestroyString(home);
802      }
803  }
804#if defined(MAGICKCORE_WINDOWS_SUPPORT)
805  {
806    char
807      module_path[MaxTextExtent];
808
809    if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
810        (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
811      {
812        unsigned char
813          *key_value;
814
815        /*
816          Search module path.
817        */
818        (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
819          DirectorySeparator);
820        key_value=NTRegistryKeyLookup(RegistryKey);
821        if (key_value == (unsigned char *) NULL)
822          (void) AppendValueToLinkedList(paths,ConstantString(path));
823        else
824          key_value=(unsigned char *) RelinquishMagickMemory(key_value);
825      }
826    if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
827      {
828        /*
829          Search PerlMagick module path.
830        */
831        (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
832          DirectorySeparator);
833        (void) AppendValueToLinkedList(paths,ConstantString(path));
834        (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
835          "\\inc\\lib\\auto\\Image\\Magick\\");
836        (void) AppendValueToLinkedList(paths,ConstantString(path));
837      }
838  }
839#endif
840  return(paths);
841}
842
843/*
844%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
845%                                                                             %
846%                                                                             %
847%                                                                             %
848%   G e t C o n f i g u r e V a l u e                                         %
849%                                                                             %
850%                                                                             %
851%                                                                             %
852%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853%
854%  GetConfigureValue() returns the value associated with the configure info.
855%
856%  The format of the GetConfigureValue method is:
857%
858%      const char *GetConfigureValue(const ConfigureInfo *configure_info)
859%
860%  A description of each parameter follows:
861%
862%    o configure_info:  The configure info.
863%
864*/
865MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
866{
867  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
868  assert(configure_info != (ConfigureInfo *) NULL);
869  assert(configure_info->signature == MagickSignature);
870  return(configure_info->value);
871}
872
873/*
874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
875%                                                                             %
876%                                                                             %
877%                                                                             %
878+   I n i t i a l i z e C o n f i g u r e L i s t                             %
879%                                                                             %
880%                                                                             %
881%                                                                             %
882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
883%
884%  InitializeConfigureList() initializes the configure list.
885%
886%  The format of the InitializeConfigureList method is:
887%
888%      MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
889%
890%  A description of each parameter follows.
891%
892%    o exception: return any errors or warnings in this structure.
893%
894*/
895static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
896{
897  if (configure_semaphore == (SemaphoreInfo *) NULL)
898    ActivateSemaphoreInfo(&configure_semaphore);
899  LockSemaphoreInfo(configure_semaphore);
900  if (configure_list == (LinkedListInfo *) NULL)
901    (void) LoadConfigureLists(ConfigureFilename,exception);
902  UnlockSemaphoreInfo(configure_semaphore);
903  return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
904}
905
906/*
907%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908%                                                                             %
909%                                                                             %
910%                                                                             %
911%  L i s t C o n f i g u r e I n f o                                          %
912%                                                                             %
913%                                                                             %
914%                                                                             %
915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916%
917%  ListConfigureInfo() lists the configure info to a file.
918%
919%  The format of the ListConfigureInfo method is:
920%
921%      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
922%
923%  A description of each parameter follows.
924%
925%    o file:  An pointer to a FILE.
926%
927%    o exception: return any errors or warnings in this structure.
928%
929*/
930MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
931  ExceptionInfo *exception)
932{
933  const char
934    *name,
935    *path,
936    *value;
937
938  const ConfigureInfo
939    **configure_info;
940
941  register ssize_t
942    i;
943
944  size_t
945    number_options;
946
947  ssize_t
948    j;
949
950  if (file == (const FILE *) NULL)
951    file=stdout;
952  configure_info=GetConfigureInfoList("*",&number_options,exception);
953  if (configure_info == (const ConfigureInfo **) NULL)
954    return(MagickFalse);
955  path=(const char *) NULL;
956  for (i=0; i < (ssize_t) number_options; i++)
957  {
958    if (configure_info[i]->stealth != MagickFalse)
959      continue;
960    if ((path == (const char *) NULL) ||
961        (LocaleCompare(path,configure_info[i]->path) != 0))
962      {
963        if (configure_info[i]->path != (char *) NULL)
964          (void) FormatLocaleFile(file,"\nPath: %s\n\n",
965            configure_info[i]->path);
966        (void) FormatLocaleFile(file,"Name           Value\n");
967        (void) FormatLocaleFile(file,
968          "-------------------------------------------------"
969          "------------------------------\n");
970      }
971    path=configure_info[i]->path;
972    name="unknown";
973    if (configure_info[i]->name != (char *) NULL)
974      name=configure_info[i]->name;
975    (void) FormatLocaleFile(file,"%s",name);
976    for (j=(ssize_t) strlen(name); j <= 13; j++)
977      (void) FormatLocaleFile(file," ");
978    (void) FormatLocaleFile(file," ");
979    value="unknown";
980    if (configure_info[i]->value != (char *) NULL)
981      value=configure_info[i]->value;
982    (void) FormatLocaleFile(file,"%s",value);
983    (void) FormatLocaleFile(file,"\n");
984  }
985  (void) fflush(file);
986  configure_info=(const ConfigureInfo **)
987    RelinquishMagickMemory((void *) configure_info);
988  return(MagickTrue);
989}
990
991/*
992%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
993%                                                                             %
994%                                                                             %
995%                                                                             %
996+   L o a d C o n f i g u r e L i s t                                         %
997%                                                                             %
998%                                                                             %
999%                                                                             %
1000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001%
1002%  LoadConfigureList() loads the configure configuration file which provides a
1003%  mapping between configure attributes and a configure name.
1004%
1005%  The format of the LoadConfigureList method is:
1006%
1007%      MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
1008%        const size_t depth,ExceptionInfo *exception)
1009%
1010%  A description of each parameter follows:
1011%
1012%    o xml:  The configure list in XML format.
1013%
1014%    o filename:  The configure list filename.
1015%
1016%    o depth: depth of <include /> statements.
1017%
1018%    o exception: return any errors or warnings in this structure.
1019%
1020*/
1021static MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
1022  const size_t depth,ExceptionInfo *exception)
1023{
1024  char
1025    keyword[MaxTextExtent],
1026    *token;
1027
1028  ConfigureInfo
1029    *configure_info;
1030
1031  const char
1032    *q;
1033
1034  MagickBooleanType
1035    status;
1036
1037  /*
1038    Load the configure map file.
1039  */
1040  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1041    "Loading configure file \"%s\" ...",filename);
1042  if (configure_list == (LinkedListInfo *) NULL)
1043    {
1044      configure_list=NewLinkedList(0);
1045      if (configure_list == (LinkedListInfo *) NULL)
1046        {
1047          ThrowFileException(exception,ResourceLimitError,
1048            "MemoryAllocationFailed",filename);
1049          return(MagickFalse);
1050        }
1051    }
1052  status=MagickTrue;
1053  configure_info=(ConfigureInfo *) NULL;
1054  token=AcquireString((char *) xml);
1055  for (q=(char *) xml; *q != '\0'; )
1056  {
1057    /*
1058      Interpret XML.
1059    */
1060    GetMagickToken(q,&q,token);
1061    if (*token == '\0')
1062      break;
1063    (void) CopyMagickString(keyword,token,MaxTextExtent);
1064    if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1065      {
1066        /*
1067          Doctype element.
1068        */
1069        while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1070          GetMagickToken(q,&q,token);
1071        continue;
1072      }
1073    if (LocaleNCompare(keyword,"<!--",4) == 0)
1074      {
1075        /*
1076          Comment element.
1077        */
1078        while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1079          GetMagickToken(q,&q,token);
1080        continue;
1081      }
1082    if (LocaleCompare(keyword,"<include") == 0)
1083      {
1084        /*
1085          Include element.
1086        */
1087        while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1088        {
1089          (void) CopyMagickString(keyword,token,MaxTextExtent);
1090          GetMagickToken(q,&q,token);
1091          if (*token != '=')
1092            continue;
1093          GetMagickToken(q,&q,token);
1094          if (LocaleCompare(keyword,"file") == 0)
1095            {
1096              if (depth > 200)
1097                (void) ThrowMagickException(exception,GetMagickModule(),
1098                  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1099              else
1100                {
1101                  char
1102                    path[MaxTextExtent],
1103                    *xml;
1104
1105                  GetPathComponent(filename,HeadPath,path);
1106                  if (*path != '\0')
1107                    (void) ConcatenateMagickString(path,DirectorySeparator,
1108                      MaxTextExtent);
1109                  if (*token == *DirectorySeparator)
1110                    (void) CopyMagickString(path,token,MaxTextExtent);
1111                  else
1112                    (void) ConcatenateMagickString(path,token,MaxTextExtent);
1113                  xml=FileToString(path,~0UL,exception);
1114                  if (xml != (char *) NULL)
1115                    {
1116                      status=LoadConfigureList(xml,path,depth+1,exception);
1117                      xml=(char *) RelinquishMagickMemory(xml);
1118                    }
1119                }
1120            }
1121        }
1122        continue;
1123      }
1124    if (LocaleCompare(keyword,"<configure") == 0)
1125      {
1126        /*
1127          Configure element.
1128        */
1129        configure_info=(ConfigureInfo *) AcquireMagickMemory(
1130          sizeof(*configure_info));
1131        if (configure_info == (ConfigureInfo *) NULL)
1132          ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1133        (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1134        configure_info->path=ConstantString(filename);
1135        configure_info->exempt=MagickFalse;
1136        configure_info->signature=MagickSignature;
1137        continue;
1138      }
1139    if (configure_info == (ConfigureInfo *) NULL)
1140      continue;
1141    if (LocaleCompare(keyword,"/>") == 0)
1142      {
1143        status=AppendValueToLinkedList(configure_list,configure_info);
1144        if (status == MagickFalse)
1145          (void) ThrowMagickException(exception,GetMagickModule(),
1146            ResourceLimitError,"MemoryAllocationFailed","`%s'",
1147            configure_info->name);
1148        configure_info=(ConfigureInfo *) NULL;
1149        continue;
1150      }
1151    /*
1152      Parse configure element.
1153    */
1154    GetMagickToken(q,(const char **) NULL,token);
1155    if (*token != '=')
1156      continue;
1157    GetMagickToken(q,&q,token);
1158    GetMagickToken(q,&q,token);
1159    switch (*keyword)
1160    {
1161      case 'N':
1162      case 'n':
1163      {
1164        if (LocaleCompare((char *) keyword,"name") == 0)
1165          {
1166            configure_info->name=ConstantString(token);
1167            break;
1168          }
1169        break;
1170      }
1171      case 'S':
1172      case 's':
1173      {
1174        if (LocaleCompare((char *) keyword,"stealth") == 0)
1175          {
1176            configure_info->stealth=IsStringTrue(token);
1177            break;
1178          }
1179        break;
1180      }
1181      case 'V':
1182      case 'v':
1183      {
1184        if (LocaleCompare((char *) keyword,"value") == 0)
1185          {
1186            configure_info->value=ConstantString(token);
1187            break;
1188          }
1189        break;
1190      }
1191      default:
1192        break;
1193    }
1194  }
1195  token=(char *) RelinquishMagickMemory(token);
1196  return(status);
1197}
1198
1199/*
1200%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1201%                                                                             %
1202%                                                                             %
1203%                                                                             %
1204%  L o a d C o n f i g u r e L i s t s                                        %
1205%                                                                             %
1206%                                                                             %
1207%                                                                             %
1208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1209%
1210%  LoadConfigureList() loads one or more configure configuration files which
1211%  provides a mapping between configure attributes and a configure name.
1212%
1213%  The format of the LoadConfigureLists method is:
1214%
1215%      MagickBooleanType LoadConfigureLists(const char *filename,
1216%        ExceptionInfo *exception)
1217%
1218%  A description of each parameter follows:
1219%
1220%    o filename: the font file name.
1221%
1222%    o exception: return any errors or warnings in this structure.
1223%
1224*/
1225static MagickBooleanType LoadConfigureLists(const char *filename,
1226  ExceptionInfo *exception)
1227{
1228  const StringInfo
1229    *option;
1230
1231  LinkedListInfo
1232    *options;
1233
1234  MagickStatusType
1235    status;
1236
1237  register ssize_t
1238    i;
1239
1240  /*
1241    Load external configure map.
1242  */
1243  if (configure_list == (LinkedListInfo *) NULL)
1244    {
1245      configure_list=NewLinkedList(0);
1246      if (configure_list == (LinkedListInfo *) NULL)
1247        {
1248          ThrowFileException(exception,ResourceLimitError,
1249            "MemoryAllocationFailed",filename);
1250          return(MagickFalse);
1251        }
1252    }
1253  status=MagickTrue;
1254  options=GetConfigureOptions(filename,exception);
1255  option=(const StringInfo *) GetNextValueInLinkedList(options);
1256  while (option != (const StringInfo *) NULL)
1257  {
1258    status&=LoadConfigureList((const char *) GetStringInfoDatum(option),
1259      GetStringInfoPath(option),0,exception);
1260    option=(const StringInfo *) GetNextValueInLinkedList(options);
1261  }
1262  options=DestroyConfigureOptions(options);
1263  /*
1264    Load built-in configure map.
1265  */
1266  for (i=0; i < (ssize_t) (sizeof(ConfigureMap)/sizeof(*ConfigureMap)); i++)
1267  {
1268    ConfigureInfo
1269      *configure_info;
1270
1271    register const ConfigureMapInfo
1272      *p;
1273
1274    p=ConfigureMap+i;
1275    configure_info=(ConfigureInfo *) AcquireMagickMemory(
1276      sizeof(*configure_info));
1277    if (configure_info == (ConfigureInfo *) NULL)
1278      {
1279        (void) ThrowMagickException(exception,GetMagickModule(),
1280          ResourceLimitError,"MemoryAllocationFailed","`%s'",p->name);
1281        continue;
1282      }
1283    (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1284    configure_info->path=(char *) "[built-in]";
1285    configure_info->name=(char *) p->name;
1286    configure_info->value=(char *) p->value;
1287    configure_info->exempt=MagickTrue;
1288    configure_info->signature=MagickSignature;
1289    status&=AppendValueToLinkedList(configure_list,configure_info);
1290    if (status == MagickFalse)
1291      (void) ThrowMagickException(exception,GetMagickModule(),
1292        ResourceLimitError,"MemoryAllocationFailed","`%s'",
1293        configure_info->name);
1294  }
1295  return(status != 0 ? MagickTrue : MagickFalse);
1296}
1297