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