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