[104106] | 1 | /*
|
---|
| 2 | * globals.c: definition and handling of the set of global variables
|
---|
| 3 | * of the library
|
---|
| 4 | *
|
---|
| 5 | * See Copyright for the status of this software.
|
---|
| 6 | *
|
---|
| 7 | * Gary Pennington <Gary.Pennington@uk.sun.com>
|
---|
| 8 | * daniel@veillard.com
|
---|
| 9 | */
|
---|
| 10 |
|
---|
| 11 | #define IN_LIBXML
|
---|
| 12 | #include "libxml.h"
|
---|
| 13 |
|
---|
| 14 | #include <stdio.h>
|
---|
| 15 | #include <stdlib.h>
|
---|
| 16 | #include <string.h>
|
---|
| 17 |
|
---|
| 18 | #define XML_GLOBALS_NO_REDEFINITION
|
---|
| 19 | #include <libxml/globals.h>
|
---|
| 20 | #include <libxml/xmlerror.h>
|
---|
| 21 | #include <libxml/xmlmemory.h>
|
---|
| 22 | #include <libxml/xmlIO.h>
|
---|
| 23 | #include <libxml/HTMLparser.h>
|
---|
| 24 | #include <libxml/parser.h>
|
---|
| 25 | #include <libxml/threads.h>
|
---|
| 26 | #include <libxml/tree.h>
|
---|
| 27 | #include <libxml/SAX.h>
|
---|
| 28 | #include <libxml/SAX2.h>
|
---|
| 29 |
|
---|
| 30 | #include "private/error.h"
|
---|
| 31 | #include "private/globals.h"
|
---|
| 32 | #include "private/threads.h"
|
---|
| 33 | #include "private/tree.h"
|
---|
| 34 |
|
---|
| 35 | /*
|
---|
| 36 | * Thread-local storage emulation.
|
---|
| 37 | *
|
---|
| 38 | * This works by replacing a global variable
|
---|
| 39 | *
|
---|
| 40 | * extern xmlError xmlLastError;
|
---|
| 41 | *
|
---|
| 42 | * with a macro that calls a function returning a pointer to the global in
|
---|
| 43 | * thread-local storage:
|
---|
| 44 | *
|
---|
| 45 | * xmlError *__xmlLastError(void);
|
---|
| 46 | * #define xmlError (*__xmlLastError());
|
---|
| 47 | *
|
---|
| 48 | * The code can operate in a multitude of ways depending on the environment.
|
---|
| 49 | * First we support POSIX and Windows threads. Then we support both thread-local
|
---|
| 50 | * storage provided by the compiler and older methods like thread-specific data
|
---|
| 51 | * (pthreads) or TlsAlloc (Windows).
|
---|
| 52 | *
|
---|
| 53 | * To clean up thread-local storage, we use thread-specific data on POSIX.
|
---|
| 54 | * On Windows, we either use DllMain when compiling a DLL or a registered wait
|
---|
| 55 | * function for static builds.
|
---|
| 56 | */
|
---|
| 57 |
|
---|
| 58 | /*
|
---|
| 59 | * Helpful Macro
|
---|
| 60 | */
|
---|
| 61 | #ifdef LIBXML_THREAD_ENABLED
|
---|
| 62 | #define IS_MAIN_THREAD (xmlIsMainThreadInternal())
|
---|
| 63 | #else
|
---|
| 64 | #define IS_MAIN_THREAD 1
|
---|
| 65 | #endif
|
---|
| 66 |
|
---|
| 67 | #define XML_DECLARE_MEMBER(name, type, attrs) \
|
---|
| 68 | type gs_##name;
|
---|
| 69 |
|
---|
| 70 | struct _xmlGlobalState {
|
---|
| 71 | int initialized;
|
---|
| 72 |
|
---|
| 73 | #if defined(HAVE_WIN32_THREADS) && \
|
---|
| 74 | defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
|
---|
| 75 | void *threadHandle;
|
---|
| 76 | void *waitHandle;
|
---|
| 77 | #endif
|
---|
| 78 |
|
---|
| 79 | #define XML_OP XML_DECLARE_MEMBER
|
---|
| 80 | XML_GLOBALS_ALLOC
|
---|
| 81 | XML_GLOBALS_ERROR
|
---|
| 82 | XML_GLOBALS_HTML
|
---|
| 83 | XML_GLOBALS_IO
|
---|
| 84 | XML_GLOBALS_PARSER
|
---|
| 85 | XML_GLOBALS_TREE
|
---|
| 86 | #undef XML_OP
|
---|
| 87 | };
|
---|
| 88 |
|
---|
| 89 | static int parserInitialized;
|
---|
| 90 |
|
---|
| 91 | /*
|
---|
| 92 | * Mutex to protect "ForNewThreads" variables
|
---|
| 93 | */
|
---|
| 94 | static xmlMutex xmlThrDefMutex;
|
---|
| 95 |
|
---|
| 96 | #ifdef LIBXML_THREAD_ENABLED
|
---|
| 97 |
|
---|
| 98 | /*
|
---|
| 99 | * On Darwin, thread-local storage destructors seem to be run before
|
---|
| 100 | * pthread thread-specific data destructors. This causes ASan to
|
---|
| 101 | * report a use-after-free.
|
---|
| 102 | *
|
---|
| 103 | * On Windows, we can't use TLS in static builds. The RegisterWait
|
---|
| 104 | * callback would run after TLS was deallocated.
|
---|
| 105 | */
|
---|
| 106 | #if defined(XML_THREAD_LOCAL) && \
|
---|
| 107 | !defined(__APPLE__) && \
|
---|
| 108 | (!defined(HAVE_WIN32_THREADS) || \
|
---|
| 109 | !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
|
---|
| 110 | #define USE_TLS
|
---|
| 111 | #endif
|
---|
| 112 |
|
---|
| 113 | #ifdef USE_TLS
|
---|
| 114 | static XML_THREAD_LOCAL xmlGlobalState globalState;
|
---|
| 115 | #endif
|
---|
| 116 |
|
---|
| 117 | #ifdef HAVE_POSIX_THREADS
|
---|
| 118 |
|
---|
| 119 | /*
|
---|
| 120 | * Weak symbol hack, see threads.c
|
---|
| 121 | */
|
---|
| 122 | #if defined(__GNUC__) && \
|
---|
| 123 | defined(__GLIBC__) && \
|
---|
| 124 | __GLIBC__ * 100 + __GLIBC_MINOR__ < 234
|
---|
| 125 |
|
---|
| 126 | #pragma weak pthread_getspecific
|
---|
| 127 | #pragma weak pthread_setspecific
|
---|
| 128 | #pragma weak pthread_key_create
|
---|
| 129 | #pragma weak pthread_key_delete
|
---|
| 130 | #pragma weak pthread_equal
|
---|
| 131 | #pragma weak pthread_self
|
---|
| 132 |
|
---|
| 133 | #define XML_PTHREAD_WEAK
|
---|
| 134 |
|
---|
| 135 | static int libxml_is_threaded = -1;
|
---|
| 136 |
|
---|
| 137 | #endif
|
---|
| 138 |
|
---|
| 139 | /*
|
---|
| 140 | * On POSIX, we need thread-specific data even with thread-local storage
|
---|
| 141 | * to destroy indirect references from global state (xmlLastError) at
|
---|
| 142 | * thread exit.
|
---|
| 143 | */
|
---|
| 144 | static pthread_key_t globalkey;
|
---|
| 145 | static pthread_t mainthread;
|
---|
| 146 |
|
---|
| 147 | #elif defined HAVE_WIN32_THREADS
|
---|
| 148 |
|
---|
| 149 | #ifndef USE_TLS
|
---|
| 150 | static DWORD globalkey = TLS_OUT_OF_INDEXES;
|
---|
| 151 | #endif
|
---|
| 152 | static DWORD mainthread;
|
---|
| 153 |
|
---|
| 154 | #endif /* HAVE_WIN32_THREADS */
|
---|
| 155 |
|
---|
| 156 | static void
|
---|
| 157 | xmlFreeGlobalState(void *state);
|
---|
| 158 |
|
---|
| 159 | #endif /* LIBXML_THREAD_ENABLED */
|
---|
| 160 |
|
---|
| 161 | /************************************************************************
|
---|
| 162 | * *
|
---|
| 163 | * All the user accessible global variables of the library *
|
---|
| 164 | * *
|
---|
| 165 | ************************************************************************/
|
---|
| 166 |
|
---|
| 167 | /*
|
---|
| 168 | * Memory allocation routines
|
---|
| 169 | */
|
---|
| 170 |
|
---|
| 171 | #if defined(DEBUG_MEMORY_LOCATION)
|
---|
| 172 | xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
|
---|
| 173 | xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
|
---|
| 174 | xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
|
---|
| 175 | xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
|
---|
| 176 | xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
|
---|
| 177 | #else
|
---|
| 178 | /**
|
---|
| 179 | * xmlFree:
|
---|
| 180 | * @mem: an already allocated block of memory
|
---|
| 181 | *
|
---|
| 182 | * The variable holding the libxml free() implementation
|
---|
| 183 | */
|
---|
| 184 | xmlFreeFunc xmlFree = free;
|
---|
| 185 | /**
|
---|
| 186 | * xmlMalloc:
|
---|
| 187 | * @size: the size requested in bytes
|
---|
| 188 | *
|
---|
| 189 | * The variable holding the libxml malloc() implementation
|
---|
| 190 | *
|
---|
| 191 | * Returns a pointer to the newly allocated block or NULL in case of error
|
---|
| 192 | */
|
---|
| 193 | xmlMallocFunc xmlMalloc = malloc;
|
---|
| 194 | /**
|
---|
| 195 | * xmlMallocAtomic:
|
---|
| 196 | * @size: the size requested in bytes
|
---|
| 197 | *
|
---|
| 198 | * The variable holding the libxml malloc() implementation for atomic
|
---|
| 199 | * data (i.e. blocks not containing pointers), useful when using a
|
---|
| 200 | * garbage collecting allocator.
|
---|
| 201 | *
|
---|
| 202 | * Returns a pointer to the newly allocated block or NULL in case of error
|
---|
| 203 | */
|
---|
| 204 | xmlMallocFunc xmlMallocAtomic = malloc;
|
---|
| 205 | /**
|
---|
| 206 | * xmlRealloc:
|
---|
| 207 | * @mem: an already allocated block of memory
|
---|
| 208 | * @size: the new size requested in bytes
|
---|
| 209 | *
|
---|
| 210 | * The variable holding the libxml realloc() implementation
|
---|
| 211 | *
|
---|
| 212 | * Returns a pointer to the newly reallocated block or NULL in case of error
|
---|
| 213 | */
|
---|
| 214 | xmlReallocFunc xmlRealloc = realloc;
|
---|
| 215 | /**
|
---|
| 216 | * xmlPosixStrdup
|
---|
| 217 | * @cur: the input char *
|
---|
| 218 | *
|
---|
| 219 | * a strdup implementation with a type signature matching POSIX
|
---|
| 220 | *
|
---|
| 221 | * Returns a new xmlChar * or NULL
|
---|
| 222 | */
|
---|
| 223 | static char *
|
---|
| 224 | xmlPosixStrdup(const char *cur) {
|
---|
| 225 | return((char*) xmlCharStrdup(cur));
|
---|
| 226 | }
|
---|
| 227 | /**
|
---|
| 228 | * xmlMemStrdup:
|
---|
| 229 | * @str: a zero terminated string
|
---|
| 230 | *
|
---|
| 231 | * The variable holding the libxml strdup() implementation
|
---|
| 232 | *
|
---|
| 233 | * Returns the copy of the string or NULL in case of error
|
---|
| 234 | */
|
---|
| 235 | xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
|
---|
| 236 | #endif /* DEBUG_MEMORY_LOCATION */
|
---|
| 237 |
|
---|
| 238 | /**
|
---|
| 239 | * xmlBufferAllocScheme:
|
---|
| 240 | *
|
---|
| 241 | * DEPRECATED: Don't use.
|
---|
| 242 | *
|
---|
| 243 | * Global setting, default allocation policy for buffers, default is
|
---|
| 244 | * XML_BUFFER_ALLOC_EXACT
|
---|
| 245 | */
|
---|
| 246 | xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
|
---|
| 247 | static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_EXACT;
|
---|
| 248 | /**
|
---|
| 249 | * xmlDefaultBufferSize:
|
---|
| 250 | *
|
---|
| 251 | * DEPRECATED: Don't use.
|
---|
| 252 | *
|
---|
| 253 | * Global setting, default buffer size. Default value is BASE_BUFFER_SIZE
|
---|
| 254 | */
|
---|
| 255 | int xmlDefaultBufferSize = BASE_BUFFER_SIZE;
|
---|
| 256 | static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE;
|
---|
| 257 |
|
---|
| 258 | /*
|
---|
| 259 | * Parser defaults
|
---|
| 260 | */
|
---|
| 261 |
|
---|
| 262 | /**
|
---|
| 263 | * oldXMLWDcompatibility:
|
---|
| 264 | *
|
---|
| 265 | * Global setting, DEPRECATED.
|
---|
| 266 | */
|
---|
| 267 | int oldXMLWDcompatibility = 0; /* DEPRECATED */
|
---|
| 268 | /**
|
---|
| 269 | * xmlParserDebugEntities:
|
---|
| 270 | *
|
---|
| 271 | * DEPRECATED: Don't use
|
---|
| 272 | *
|
---|
| 273 | * Global setting, asking the parser to print out debugging information.
|
---|
| 274 | * while handling entities.
|
---|
| 275 | * Disabled by default
|
---|
| 276 | */
|
---|
| 277 | int xmlParserDebugEntities = 0;
|
---|
| 278 | static int xmlParserDebugEntitiesThrDef = 0;
|
---|
| 279 | /**
|
---|
| 280 | * xmlDoValidityCheckingDefaultValue:
|
---|
| 281 | *
|
---|
| 282 | * DEPRECATED: Use the modern options API with XML_PARSE_DTDVALID.
|
---|
| 283 | *
|
---|
| 284 | * Global setting, indicate that the parser should work in validating mode.
|
---|
| 285 | * Disabled by default.
|
---|
| 286 | */
|
---|
| 287 | int xmlDoValidityCheckingDefaultValue = 0;
|
---|
| 288 | static int xmlDoValidityCheckingDefaultValueThrDef = 0;
|
---|
| 289 | /**
|
---|
| 290 | * xmlGetWarningsDefaultValue:
|
---|
| 291 | *
|
---|
| 292 | * DEPRECATED: Don't use
|
---|
| 293 | *
|
---|
| 294 | * Global setting, indicate that the DTD validation should provide warnings.
|
---|
| 295 | * Activated by default.
|
---|
| 296 | */
|
---|
| 297 | int xmlGetWarningsDefaultValue = 1;
|
---|
| 298 | static int xmlGetWarningsDefaultValueThrDef = 1;
|
---|
| 299 | /**
|
---|
| 300 | * xmlLoadExtDtdDefaultValue:
|
---|
| 301 | *
|
---|
| 302 | * DEPRECATED: Use the modern options API with XML_PARSE_DTDLOAD.
|
---|
| 303 | *
|
---|
| 304 | * Global setting, indicate that the parser should load DTD while not
|
---|
| 305 | * validating.
|
---|
| 306 | * Disabled by default.
|
---|
| 307 | */
|
---|
| 308 | int xmlLoadExtDtdDefaultValue = 0;
|
---|
| 309 | static int xmlLoadExtDtdDefaultValueThrDef = 0;
|
---|
| 310 | /**
|
---|
| 311 | * xmlPedanticParserDefaultValue:
|
---|
| 312 | *
|
---|
| 313 | * DEPRECATED: Use the modern options API with XML_PARSE_PEDANTIC.
|
---|
| 314 | *
|
---|
| 315 | * Global setting, indicate that the parser be pedantic
|
---|
| 316 | * Disabled by default.
|
---|
| 317 | */
|
---|
| 318 | int xmlPedanticParserDefaultValue = 0;
|
---|
| 319 | static int xmlPedanticParserDefaultValueThrDef = 0;
|
---|
| 320 | /**
|
---|
| 321 | * xmlLineNumbersDefaultValue:
|
---|
| 322 | *
|
---|
| 323 | * DEPRECATED: The modern options API always enables line numbers.
|
---|
| 324 | *
|
---|
| 325 | * Global setting, indicate that the parser should store the line number
|
---|
| 326 | * in the content field of elements in the DOM tree.
|
---|
| 327 | * Disabled by default since this may not be safe for old classes of
|
---|
| 328 | * application.
|
---|
| 329 | */
|
---|
| 330 | int xmlLineNumbersDefaultValue = 0;
|
---|
| 331 | static int xmlLineNumbersDefaultValueThrDef = 0;
|
---|
| 332 | /**
|
---|
| 333 | * xmlKeepBlanksDefaultValue:
|
---|
| 334 | *
|
---|
| 335 | * DEPRECATED: Use the modern options API with XML_PARSE_NOBLANKS.
|
---|
| 336 | *
|
---|
| 337 | * Global setting, indicate that the parser should keep all blanks
|
---|
| 338 | * nodes found in the content
|
---|
| 339 | * Activated by default, this is actually needed to have the parser
|
---|
| 340 | * conformant to the XML Recommendation, however the option is kept
|
---|
| 341 | * for some applications since this was libxml1 default behaviour.
|
---|
| 342 | */
|
---|
| 343 | int xmlKeepBlanksDefaultValue = 1;
|
---|
| 344 | static int xmlKeepBlanksDefaultValueThrDef = 1;
|
---|
| 345 | /**
|
---|
| 346 | * xmlSubstituteEntitiesDefaultValue:
|
---|
| 347 | *
|
---|
| 348 | * DEPRECATED: Use the modern options API with XML_PARSE_NOENT.
|
---|
| 349 | *
|
---|
| 350 | * Global setting, indicate that the parser should not generate entity
|
---|
| 351 | * references but replace them with the actual content of the entity
|
---|
| 352 | * Disabled by default, this should be activated when using XPath since
|
---|
| 353 | * the XPath data model requires entities replacement and the XPath
|
---|
| 354 | * engine does not handle entities references transparently.
|
---|
| 355 | */
|
---|
| 356 | int xmlSubstituteEntitiesDefaultValue = 0;
|
---|
| 357 | static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
|
---|
| 358 |
|
---|
| 359 | /**
|
---|
| 360 | * xmlRegisterNodeDefaultValue:
|
---|
| 361 | *
|
---|
| 362 | * DEPRECATED: Don't use
|
---|
| 363 | */
|
---|
| 364 | xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
|
---|
| 365 | static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
|
---|
| 366 |
|
---|
| 367 | /**
|
---|
| 368 | * xmlDeregisterNodeDefaultValue:
|
---|
| 369 | *
|
---|
| 370 | * DEPRECATED: Don't use
|
---|
| 371 | */
|
---|
| 372 | xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
|
---|
| 373 | static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
|
---|
| 374 |
|
---|
| 375 | /**
|
---|
| 376 | * xmlParserInputBufferCreateFilenameValue:
|
---|
| 377 | *
|
---|
| 378 | * DEPRECATED: Don't use
|
---|
| 379 | */
|
---|
| 380 | xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue = NULL;
|
---|
| 381 | static xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValueThrDef = NULL;
|
---|
| 382 |
|
---|
| 383 | /**
|
---|
| 384 | * xmlOutputBufferCreateFilenameValue:
|
---|
| 385 | *
|
---|
| 386 | * DEPRECATED: Don't use
|
---|
| 387 | */
|
---|
| 388 | xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue = NULL;
|
---|
| 389 | static xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValueThrDef = NULL;
|
---|
| 390 |
|
---|
| 391 | /**
|
---|
| 392 | * xmlGenericError:
|
---|
| 393 | *
|
---|
| 394 | * Global setting: function used for generic error callbacks
|
---|
| 395 | */
|
---|
| 396 | xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
|
---|
| 397 | static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
|
---|
| 398 | /**
|
---|
| 399 | * xmlStructuredError:
|
---|
| 400 | *
|
---|
| 401 | * Global setting: function used for structured error callbacks
|
---|
| 402 | */
|
---|
| 403 | xmlStructuredErrorFunc xmlStructuredError = NULL;
|
---|
| 404 | static xmlStructuredErrorFunc xmlStructuredErrorThrDef = NULL;
|
---|
| 405 | /**
|
---|
| 406 | * xmlGenericErrorContext:
|
---|
| 407 | *
|
---|
| 408 | * Global setting passed to generic error callbacks
|
---|
| 409 | */
|
---|
| 410 | void *xmlGenericErrorContext = NULL;
|
---|
| 411 | static void *xmlGenericErrorContextThrDef = NULL;
|
---|
| 412 | /**
|
---|
| 413 | * xmlStructuredErrorContext:
|
---|
| 414 | *
|
---|
| 415 | * Global setting passed to structured error callbacks
|
---|
| 416 | */
|
---|
| 417 | void *xmlStructuredErrorContext = NULL;
|
---|
| 418 | static void *xmlStructuredErrorContextThrDef = NULL;
|
---|
| 419 | xmlError xmlLastError;
|
---|
| 420 |
|
---|
| 421 | #ifdef LIBXML_OUTPUT_ENABLED
|
---|
| 422 | /*
|
---|
| 423 | * output defaults
|
---|
| 424 | */
|
---|
| 425 | /**
|
---|
| 426 | * xmlIndentTreeOutput:
|
---|
| 427 | *
|
---|
| 428 | * Global setting, asking the serializer to indent the output tree by default
|
---|
| 429 | * Enabled by default
|
---|
| 430 | */
|
---|
| 431 | int xmlIndentTreeOutput = 1;
|
---|
| 432 | static int xmlIndentTreeOutputThrDef = 1;
|
---|
| 433 |
|
---|
| 434 | /**
|
---|
| 435 | * xmlTreeIndentString:
|
---|
| 436 | *
|
---|
| 437 | * The string used to do one-level indent. By default is equal to " " (two spaces)
|
---|
| 438 | */
|
---|
| 439 | const char *xmlTreeIndentString = " ";
|
---|
| 440 | static const char *xmlTreeIndentStringThrDef = " ";
|
---|
| 441 |
|
---|
| 442 | /**
|
---|
| 443 | * xmlSaveNoEmptyTags:
|
---|
| 444 | *
|
---|
| 445 | * Global setting, asking the serializer to not output empty tags
|
---|
| 446 | * as <empty/> but <empty></empty>. those two forms are indistinguishable
|
---|
| 447 | * once parsed.
|
---|
| 448 | * Disabled by default
|
---|
| 449 | */
|
---|
| 450 | int xmlSaveNoEmptyTags = 0;
|
---|
| 451 | static int xmlSaveNoEmptyTagsThrDef = 0;
|
---|
| 452 | #endif /* LIBXML_OUTPUT_ENABLED */
|
---|
| 453 |
|
---|
| 454 | #ifdef LIBXML_SAX1_ENABLED
|
---|
| 455 | /**
|
---|
| 456 | * xmlDefaultSAXHandler:
|
---|
| 457 | *
|
---|
| 458 | * DEPRECATED: This handler is unused and will be removed from future
|
---|
| 459 | * versions.
|
---|
| 460 | *
|
---|
| 461 | * Default SAX version1 handler for XML, builds the DOM tree
|
---|
| 462 | */
|
---|
| 463 | xmlSAXHandlerV1 xmlDefaultSAXHandler = {
|
---|
| 464 | xmlSAX2InternalSubset,
|
---|
| 465 | xmlSAX2IsStandalone,
|
---|
| 466 | xmlSAX2HasInternalSubset,
|
---|
| 467 | xmlSAX2HasExternalSubset,
|
---|
| 468 | xmlSAX2ResolveEntity,
|
---|
| 469 | xmlSAX2GetEntity,
|
---|
| 470 | xmlSAX2EntityDecl,
|
---|
| 471 | xmlSAX2NotationDecl,
|
---|
| 472 | xmlSAX2AttributeDecl,
|
---|
| 473 | xmlSAX2ElementDecl,
|
---|
| 474 | xmlSAX2UnparsedEntityDecl,
|
---|
| 475 | xmlSAX2SetDocumentLocator,
|
---|
| 476 | xmlSAX2StartDocument,
|
---|
| 477 | xmlSAX2EndDocument,
|
---|
| 478 | xmlSAX2StartElement,
|
---|
| 479 | xmlSAX2EndElement,
|
---|
| 480 | xmlSAX2Reference,
|
---|
| 481 | xmlSAX2Characters,
|
---|
| 482 | xmlSAX2Characters,
|
---|
| 483 | xmlSAX2ProcessingInstruction,
|
---|
| 484 | xmlSAX2Comment,
|
---|
| 485 | xmlParserWarning,
|
---|
| 486 | xmlParserError,
|
---|
| 487 | xmlParserError,
|
---|
| 488 | xmlSAX2GetParameterEntity,
|
---|
| 489 | xmlSAX2CDataBlock,
|
---|
| 490 | xmlSAX2ExternalSubset,
|
---|
| 491 | 1,
|
---|
| 492 | };
|
---|
| 493 | #endif /* LIBXML_SAX1_ENABLED */
|
---|
| 494 |
|
---|
| 495 | /**
|
---|
| 496 | * xmlDefaultSAXLocator:
|
---|
| 497 | *
|
---|
| 498 | * DEPRECATED: Don't use
|
---|
| 499 | *
|
---|
| 500 | * The default SAX Locator
|
---|
| 501 | * { getPublicId, getSystemId, getLineNumber, getColumnNumber}
|
---|
| 502 | */
|
---|
| 503 | xmlSAXLocator xmlDefaultSAXLocator = {
|
---|
| 504 | xmlSAX2GetPublicId,
|
---|
| 505 | xmlSAX2GetSystemId,
|
---|
| 506 | xmlSAX2GetLineNumber,
|
---|
| 507 | xmlSAX2GetColumnNumber
|
---|
| 508 | };
|
---|
| 509 |
|
---|
| 510 | #if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED)
|
---|
| 511 | /**
|
---|
| 512 | * htmlDefaultSAXHandler:
|
---|
| 513 | *
|
---|
| 514 | * DEPRECATED: This handler is unused and will be removed from future
|
---|
| 515 | * versions.
|
---|
| 516 | *
|
---|
| 517 | * Default old SAX v1 handler for HTML, builds the DOM tree
|
---|
| 518 | */
|
---|
| 519 | xmlSAXHandlerV1 htmlDefaultSAXHandler = {
|
---|
| 520 | xmlSAX2InternalSubset,
|
---|
| 521 | NULL,
|
---|
| 522 | NULL,
|
---|
| 523 | NULL,
|
---|
| 524 | NULL,
|
---|
| 525 | xmlSAX2GetEntity,
|
---|
| 526 | NULL,
|
---|
| 527 | NULL,
|
---|
| 528 | NULL,
|
---|
| 529 | NULL,
|
---|
| 530 | NULL,
|
---|
| 531 | xmlSAX2SetDocumentLocator,
|
---|
| 532 | xmlSAX2StartDocument,
|
---|
| 533 | xmlSAX2EndDocument,
|
---|
| 534 | xmlSAX2StartElement,
|
---|
| 535 | xmlSAX2EndElement,
|
---|
| 536 | NULL,
|
---|
| 537 | xmlSAX2Characters,
|
---|
| 538 | xmlSAX2IgnorableWhitespace,
|
---|
| 539 | xmlSAX2ProcessingInstruction,
|
---|
| 540 | xmlSAX2Comment,
|
---|
| 541 | xmlParserWarning,
|
---|
| 542 | xmlParserError,
|
---|
| 543 | xmlParserError,
|
---|
| 544 | NULL,
|
---|
| 545 | xmlSAX2CDataBlock,
|
---|
| 546 | NULL,
|
---|
| 547 | 1,
|
---|
| 548 | };
|
---|
| 549 | #endif /* LIBXML_HTML_ENABLED */
|
---|
| 550 |
|
---|
| 551 | /************************************************************************
|
---|
| 552 | * *
|
---|
| 553 | * Per thread global state handling *
|
---|
| 554 | * *
|
---|
| 555 | ************************************************************************/
|
---|
| 556 |
|
---|
| 557 | /**
|
---|
| 558 | * xmlInitGlobals:
|
---|
| 559 | *
|
---|
| 560 | * DEPRECATED: Alias for xmlInitParser.
|
---|
| 561 | */
|
---|
| 562 | void xmlInitGlobals(void) {
|
---|
| 563 | xmlInitParser();
|
---|
| 564 | }
|
---|
| 565 |
|
---|
| 566 | /**
|
---|
| 567 | * xmlInitGlobalsInternal:
|
---|
| 568 | *
|
---|
| 569 | * Additional initialisation for multi-threading
|
---|
| 570 | */
|
---|
| 571 | void xmlInitGlobalsInternal(void) {
|
---|
| 572 | xmlInitMutex(&xmlThrDefMutex);
|
---|
| 573 |
|
---|
| 574 | #ifdef HAVE_POSIX_THREADS
|
---|
| 575 | #ifdef XML_PTHREAD_WEAK
|
---|
| 576 | if (libxml_is_threaded == -1)
|
---|
| 577 | libxml_is_threaded =
|
---|
| 578 | (pthread_getspecific != NULL) &&
|
---|
| 579 | (pthread_setspecific != NULL) &&
|
---|
| 580 | (pthread_key_create != NULL) &&
|
---|
| 581 | (pthread_key_delete != NULL) &&
|
---|
| 582 | /*
|
---|
| 583 | * pthread_equal can be inline, resuting in -Waddress warnings.
|
---|
| 584 | * Let's assume it's available if all the other functions are.
|
---|
| 585 | */
|
---|
| 586 | /* (pthread_equal != NULL) && */
|
---|
| 587 | (pthread_self != NULL);
|
---|
| 588 | if (libxml_is_threaded == 0)
|
---|
| 589 | return;
|
---|
| 590 | #endif /* XML_PTHREAD_WEAK */
|
---|
| 591 | pthread_key_create(&globalkey, xmlFreeGlobalState);
|
---|
| 592 | mainthread = pthread_self();
|
---|
| 593 | #elif defined(HAVE_WIN32_THREADS)
|
---|
| 594 | #ifndef USE_TLS
|
---|
| 595 | globalkey = TlsAlloc();
|
---|
| 596 | #endif
|
---|
| 597 | mainthread = GetCurrentThreadId();
|
---|
| 598 | #endif
|
---|
| 599 | }
|
---|
| 600 |
|
---|
| 601 | /**
|
---|
| 602 | * xmlCleanupGlobals:
|
---|
| 603 | *
|
---|
| 604 | * DEPRECATED: This function is a no-op. Call xmlCleanupParser
|
---|
| 605 | * to free global state but see the warnings there. xmlCleanupParser
|
---|
| 606 | * should be only called once at program exit. In most cases, you don't
|
---|
| 607 | * have call cleanup functions at all.
|
---|
| 608 | */
|
---|
| 609 | void xmlCleanupGlobals(void) {
|
---|
| 610 | }
|
---|
| 611 |
|
---|
| 612 | /**
|
---|
| 613 | * xmlCleanupGlobalsInternal:
|
---|
| 614 | *
|
---|
| 615 | * Additional cleanup for multi-threading
|
---|
| 616 | */
|
---|
| 617 | void xmlCleanupGlobalsInternal(void) {
|
---|
| 618 | xmlResetError(&xmlLastError);
|
---|
| 619 |
|
---|
| 620 | xmlCleanupMutex(&xmlThrDefMutex);
|
---|
| 621 |
|
---|
| 622 | #ifdef HAVE_POSIX_THREADS
|
---|
| 623 | #ifdef XML_PTHREAD_WEAK
|
---|
| 624 | if (libxml_is_threaded == 0)
|
---|
| 625 | return;
|
---|
| 626 | #endif /* XML_PTHREAD_WEAK */
|
---|
| 627 | pthread_key_delete(globalkey);
|
---|
| 628 | #elif defined(HAVE_WIN32_THREADS)
|
---|
| 629 | #ifndef USE_TLS
|
---|
| 630 | if (globalkey != TLS_OUT_OF_INDEXES) {
|
---|
| 631 | TlsFree(globalkey);
|
---|
| 632 | globalkey = TLS_OUT_OF_INDEXES;
|
---|
| 633 | }
|
---|
| 634 | #endif
|
---|
| 635 | #endif
|
---|
| 636 |
|
---|
| 637 | parserInitialized = 0;
|
---|
| 638 | }
|
---|
| 639 |
|
---|
| 640 | /**
|
---|
| 641 | * xmlInitializeGlobalState:
|
---|
| 642 | * @gs: a pointer to a newly allocated global state
|
---|
| 643 | *
|
---|
| 644 | * DEPRECATED: No-op.
|
---|
| 645 | */
|
---|
| 646 | void
|
---|
| 647 | xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)
|
---|
| 648 | {
|
---|
| 649 | }
|
---|
| 650 |
|
---|
| 651 | /**
|
---|
| 652 | * xmlGetGlobalState:
|
---|
| 653 | *
|
---|
| 654 | * DEPRECATED
|
---|
| 655 | *
|
---|
| 656 | * Returns NULL.
|
---|
| 657 | */
|
---|
| 658 | xmlGlobalStatePtr
|
---|
| 659 | xmlGetGlobalState(void)
|
---|
| 660 | {
|
---|
| 661 | return(NULL);
|
---|
| 662 | }
|
---|
| 663 |
|
---|
| 664 | static int
|
---|
| 665 | xmlIsMainThreadInternal(void) {
|
---|
| 666 | if (parserInitialized == 0) {
|
---|
| 667 | xmlInitParser();
|
---|
| 668 | parserInitialized = 1;
|
---|
| 669 | }
|
---|
| 670 |
|
---|
| 671 | #ifdef HAVE_POSIX_THREADS
|
---|
| 672 | #ifdef XML_PTHREAD_WEAK
|
---|
| 673 | if (libxml_is_threaded == 0)
|
---|
| 674 | return (1);
|
---|
| 675 | #endif
|
---|
| 676 | return (pthread_equal(mainthread, pthread_self()));
|
---|
| 677 | #elif defined HAVE_WIN32_THREADS
|
---|
| 678 | return (mainthread == GetCurrentThreadId());
|
---|
| 679 | #else
|
---|
| 680 | return (1);
|
---|
| 681 | #endif
|
---|
| 682 | }
|
---|
| 683 |
|
---|
| 684 | /**
|
---|
| 685 | * xmlIsMainThread:
|
---|
| 686 | *
|
---|
| 687 | * DEPRECATED: Internal function, do not use.
|
---|
| 688 | *
|
---|
| 689 | * Check whether the current thread is the main thread.
|
---|
| 690 | *
|
---|
| 691 | * Returns 1 if the current thread is the main thread, 0 otherwise
|
---|
| 692 | */
|
---|
| 693 | int
|
---|
| 694 | xmlIsMainThread(void) {
|
---|
| 695 | return(xmlIsMainThreadInternal());
|
---|
| 696 | }
|
---|
| 697 |
|
---|
| 698 | #ifdef LIBXML_THREAD_ENABLED
|
---|
| 699 |
|
---|
| 700 | static void
|
---|
| 701 | xmlFreeGlobalState(void *state)
|
---|
| 702 | {
|
---|
| 703 | xmlGlobalState *gs = (xmlGlobalState *) state;
|
---|
| 704 |
|
---|
| 705 | /*
|
---|
| 706 | * Free any memory allocated in the thread's xmlLastError. If it
|
---|
| 707 | * weren't for this indirect allocation, we wouldn't need
|
---|
| 708 | * a destructor with thread-local storage at all!
|
---|
| 709 | *
|
---|
| 710 | * It would be nice if we could make xmlLastError a special error
|
---|
| 711 | * type which uses statically allocated, fixed-size buffers.
|
---|
| 712 | * But the xmlError struct is fully public and widely used,
|
---|
| 713 | * so changes are dangerous.
|
---|
| 714 | */
|
---|
| 715 | xmlResetError(&(gs->gs_xmlLastError));
|
---|
| 716 | #ifndef USE_TLS
|
---|
| 717 | free(state);
|
---|
| 718 | #endif
|
---|
| 719 | }
|
---|
| 720 |
|
---|
| 721 | #if defined(HAVE_WIN32_THREADS) && \
|
---|
| 722 | defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
|
---|
| 723 | static void WINAPI
|
---|
| 724 | xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
|
---|
| 725 | xmlGlobalStatePtr gs = ctxt;
|
---|
| 726 |
|
---|
| 727 | UnregisterWait(gs->waitHandle);
|
---|
| 728 | CloseHandle(gs->threadHandle);
|
---|
| 729 | xmlFreeGlobalState(gs);
|
---|
| 730 | }
|
---|
| 731 |
|
---|
| 732 | static int
|
---|
| 733 | xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
|
---|
| 734 | void *processHandle = GetCurrentProcess();
|
---|
| 735 | void *threadHandle;
|
---|
| 736 | void *waitHandle;
|
---|
| 737 |
|
---|
| 738 | if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
|
---|
| 739 | &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
|
---|
| 740 | return(-1);
|
---|
| 741 | }
|
---|
| 742 |
|
---|
| 743 | if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
|
---|
| 744 | xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
|
---|
| 745 | CloseHandle(threadHandle);
|
---|
| 746 | return(-1);
|
---|
| 747 | }
|
---|
| 748 |
|
---|
| 749 | gs->threadHandle = threadHandle;
|
---|
| 750 | gs->waitHandle = waitHandle;
|
---|
| 751 | return(0);
|
---|
| 752 | }
|
---|
| 753 | #endif /* LIBXML_STATIC */
|
---|
| 754 |
|
---|
| 755 | static void
|
---|
| 756 | xmlInitGlobalState(xmlGlobalStatePtr gs) {
|
---|
| 757 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 758 |
|
---|
| 759 | #if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED)
|
---|
| 760 | inithtmlDefaultSAXHandler(&gs->gs_htmlDefaultSAXHandler);
|
---|
| 761 | #endif
|
---|
| 762 |
|
---|
| 763 | gs->gs_oldXMLWDcompatibility = 0;
|
---|
| 764 | gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
|
---|
| 765 | gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
|
---|
| 766 | #if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED)
|
---|
| 767 | initxmlDefaultSAXHandler(&gs->gs_xmlDefaultSAXHandler, 1);
|
---|
| 768 | #endif /* LIBXML_SAX1_ENABLED */
|
---|
| 769 | gs->gs_xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId;
|
---|
| 770 | gs->gs_xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId;
|
---|
| 771 | gs->gs_xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber;
|
---|
| 772 | gs->gs_xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber;
|
---|
| 773 | gs->gs_xmlDoValidityCheckingDefaultValue =
|
---|
| 774 | xmlDoValidityCheckingDefaultValueThrDef;
|
---|
| 775 | #ifdef LIBXML_THREAD_ALLOC_ENABLED
|
---|
| 776 | #ifdef DEBUG_MEMORY_LOCATION
|
---|
| 777 | gs->gs_xmlFree = xmlMemFree;
|
---|
| 778 | gs->gs_xmlMalloc = xmlMemMalloc;
|
---|
| 779 | gs->gs_xmlMallocAtomic = xmlMemMalloc;
|
---|
| 780 | gs->gs_xmlRealloc = xmlMemRealloc;
|
---|
| 781 | gs->gs_xmlMemStrdup = xmlMemoryStrdup;
|
---|
| 782 | #else
|
---|
| 783 | gs->gs_xmlFree = free;
|
---|
| 784 | gs->gs_xmlMalloc = malloc;
|
---|
| 785 | gs->gs_xmlMallocAtomic = malloc;
|
---|
| 786 | gs->gs_xmlRealloc = realloc;
|
---|
| 787 | gs->gs_xmlMemStrdup = xmlPosixStrdup;
|
---|
| 788 | #endif
|
---|
| 789 | #endif
|
---|
| 790 | gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
|
---|
| 791 | #ifdef LIBXML_OUTPUT_ENABLED
|
---|
| 792 | gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
|
---|
| 793 | gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef;
|
---|
| 794 | gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
|
---|
| 795 | #endif
|
---|
| 796 | gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
|
---|
| 797 | gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
|
---|
| 798 | gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
|
---|
| 799 | gs->gs_xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
|
---|
| 800 | gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
|
---|
| 801 | gs->gs_xmlSubstituteEntitiesDefaultValue =
|
---|
| 802 | xmlSubstituteEntitiesDefaultValueThrDef;
|
---|
| 803 |
|
---|
| 804 | gs->gs_xmlGenericError = xmlGenericErrorThrDef;
|
---|
| 805 | gs->gs_xmlStructuredError = xmlStructuredErrorThrDef;
|
---|
| 806 | gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef;
|
---|
| 807 | gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
|
---|
| 808 | gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
|
---|
| 809 | gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
|
---|
| 810 |
|
---|
| 811 | gs->gs_xmlParserInputBufferCreateFilenameValue =
|
---|
| 812 | xmlParserInputBufferCreateFilenameValueThrDef;
|
---|
| 813 | gs->gs_xmlOutputBufferCreateFilenameValue =
|
---|
| 814 | xmlOutputBufferCreateFilenameValueThrDef;
|
---|
| 815 | memset(&gs->gs_xmlLastError, 0, sizeof(xmlError));
|
---|
| 816 |
|
---|
| 817 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 818 |
|
---|
| 819 | #ifdef HAVE_POSIX_THREADS
|
---|
| 820 | pthread_setspecific(globalkey, gs);
|
---|
| 821 | #elif defined HAVE_WIN32_THREADS
|
---|
| 822 | #ifndef USE_TLS
|
---|
| 823 | TlsSetValue(globalkey, gs);
|
---|
| 824 | #endif
|
---|
| 825 | #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
|
---|
| 826 | xmlRegisterGlobalStateDtor(gs);
|
---|
| 827 | #endif
|
---|
| 828 | #endif
|
---|
| 829 |
|
---|
| 830 | gs->initialized = 1;
|
---|
| 831 | }
|
---|
| 832 |
|
---|
| 833 | #ifndef USE_TLS
|
---|
| 834 | /**
|
---|
| 835 | * xmlNewGlobalState:
|
---|
| 836 | *
|
---|
| 837 | * xmlNewGlobalState() allocates a global state. This structure is used to
|
---|
| 838 | * hold all data for use by a thread when supporting backwards compatibility
|
---|
| 839 | * of libxml2 to pre-thread-safe behaviour.
|
---|
| 840 | *
|
---|
| 841 | * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
|
---|
| 842 | */
|
---|
| 843 | static xmlGlobalStatePtr
|
---|
| 844 | xmlNewGlobalState(int allowFailure)
|
---|
| 845 | {
|
---|
| 846 | xmlGlobalState *gs;
|
---|
| 847 |
|
---|
| 848 | gs = malloc(sizeof(xmlGlobalState));
|
---|
| 849 | if (gs == NULL) {
|
---|
| 850 | if (allowFailure)
|
---|
| 851 | return(NULL);
|
---|
| 852 |
|
---|
| 853 | /*
|
---|
| 854 | * If an application didn't call xmlCheckThreadLocalStorage to make
|
---|
| 855 | * sure that global state could be allocated, it's too late to
|
---|
| 856 | * handle the error.
|
---|
| 857 | */
|
---|
| 858 | fprintf(stderr, "libxml2: Failed to allocate globals for thread\n"
|
---|
| 859 | "libxml2: See xmlCheckThreadLocalStorage\n");
|
---|
| 860 | abort();
|
---|
| 861 | }
|
---|
| 862 |
|
---|
| 863 | memset(gs, 0, sizeof(xmlGlobalState));
|
---|
| 864 | xmlInitGlobalState(gs);
|
---|
| 865 | return (gs);
|
---|
| 866 | }
|
---|
| 867 | #endif
|
---|
| 868 |
|
---|
| 869 | static xmlGlobalStatePtr
|
---|
| 870 | xmlGetThreadLocalStorage(int allowFailure) {
|
---|
| 871 | xmlGlobalState *gs;
|
---|
| 872 |
|
---|
| 873 | (void) allowFailure;
|
---|
| 874 |
|
---|
| 875 | #ifdef USE_TLS
|
---|
| 876 | gs = &globalState;
|
---|
| 877 | if (gs->initialized == 0)
|
---|
| 878 | xmlInitGlobalState(gs);
|
---|
| 879 | #elif defined(HAVE_POSIX_THREADS)
|
---|
| 880 | gs = (xmlGlobalState *) pthread_getspecific(globalkey);
|
---|
| 881 | if (gs == NULL)
|
---|
| 882 | gs = xmlNewGlobalState(allowFailure);
|
---|
| 883 | #elif defined(HAVE_WIN32_THREADS)
|
---|
| 884 | gs = (xmlGlobalState *) TlsGetValue(globalkey);
|
---|
| 885 | if (gs == NULL)
|
---|
| 886 | gs = xmlNewGlobalState(allowFailure);
|
---|
| 887 | #else
|
---|
| 888 | gs = NULL;
|
---|
| 889 | #endif
|
---|
| 890 |
|
---|
| 891 | return(gs);
|
---|
| 892 | }
|
---|
| 893 |
|
---|
| 894 | /* Define thread-local storage accessors with macro magic */
|
---|
| 895 |
|
---|
| 896 | #define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \
|
---|
| 897 | type *__##name(void) { \
|
---|
| 898 | if (IS_MAIN_THREAD) \
|
---|
| 899 | return (&name); \
|
---|
| 900 | else \
|
---|
| 901 | return (&xmlGetThreadLocalStorage(0)->gs_##name); \
|
---|
| 902 | }
|
---|
| 903 |
|
---|
| 904 | #define XML_OP XML_DEFINE_GLOBAL_WRAPPER
|
---|
| 905 | XML_GLOBALS_ALLOC
|
---|
| 906 | XML_GLOBALS_ERROR
|
---|
| 907 | XML_GLOBALS_HTML
|
---|
| 908 | XML_GLOBALS_IO
|
---|
| 909 | XML_GLOBALS_PARSER
|
---|
| 910 | XML_GLOBALS_TREE
|
---|
| 911 | #undef XML_OP
|
---|
| 912 |
|
---|
| 913 | /* For backward compatibility */
|
---|
| 914 |
|
---|
| 915 | const char *const *
|
---|
| 916 | __xmlParserVersion(void) {
|
---|
| 917 | return &xmlParserVersion;
|
---|
| 918 | }
|
---|
| 919 |
|
---|
| 920 | #endif /* LIBXML_THREAD_ENABLED */
|
---|
| 921 |
|
---|
| 922 | /**
|
---|
| 923 | * xmlCheckThreadLocalStorage:
|
---|
| 924 | *
|
---|
| 925 | * Check whether thread-local storage could be allocated.
|
---|
| 926 | *
|
---|
| 927 | * In cross-platform code running in multithreaded environments, this
|
---|
| 928 | * function should be called once in each thread before calling other
|
---|
| 929 | * library functions to make sure that thread-local storage was
|
---|
| 930 | * allocated properly.
|
---|
| 931 | *
|
---|
| 932 | * Returns 0 on success or -1 if a memory allocation failed. A failed
|
---|
| 933 | * allocation signals a typically fatal and irrecoverable out-of-memory
|
---|
| 934 | * situation. Don't call any library functions in this case.
|
---|
| 935 | *
|
---|
| 936 | * This function never fails if the library is compiled with support
|
---|
| 937 | * for thread-local storage.
|
---|
| 938 | *
|
---|
| 939 | * This function never fails for the "main" thread which is the first
|
---|
| 940 | * thread calling xmlInitParser.
|
---|
| 941 | *
|
---|
| 942 | * Available since v2.12.0.
|
---|
| 943 | */
|
---|
| 944 | int
|
---|
| 945 | xmlCheckThreadLocalStorage(void) {
|
---|
| 946 | #if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
|
---|
| 947 | if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
|
---|
| 948 | return(-1);
|
---|
| 949 | #endif
|
---|
| 950 | return(0);
|
---|
| 951 | }
|
---|
| 952 |
|
---|
| 953 | /**
|
---|
| 954 | * DllMain:
|
---|
| 955 | * @hinstDLL: handle to DLL instance
|
---|
| 956 | * @fdwReason: Reason code for entry
|
---|
| 957 | * @lpvReserved: generic pointer (depends upon reason code)
|
---|
| 958 | *
|
---|
| 959 | * Entry point for Windows library. It is being used to free thread-specific
|
---|
| 960 | * storage.
|
---|
| 961 | *
|
---|
| 962 | * Returns TRUE always
|
---|
| 963 | */
|
---|
| 964 | #if defined(HAVE_WIN32_THREADS) && \
|
---|
| 965 | (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
|
---|
| 966 | #if defined(LIBXML_STATIC_FOR_DLL)
|
---|
| 967 | int
|
---|
| 968 | xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
|
---|
| 969 | ATTRIBUTE_UNUSED void *lpvReserved)
|
---|
| 970 | #else
|
---|
| 971 | /* declare to avoid "no previous prototype for 'DllMain'" warning */
|
---|
| 972 | /* Note that we do NOT want to include this function declaration in
|
---|
| 973 | a public header because it's meant to be called by Windows itself,
|
---|
| 974 | not a program that uses this library. This also has to be exported. */
|
---|
| 975 |
|
---|
| 976 | XMLPUBFUN BOOL WINAPI
|
---|
| 977 | DllMain (HINSTANCE hinstDLL,
|
---|
| 978 | DWORD fdwReason,
|
---|
| 979 | LPVOID lpvReserved);
|
---|
| 980 |
|
---|
| 981 | BOOL WINAPI
|
---|
| 982 | DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
|
---|
| 983 | ATTRIBUTE_UNUSED LPVOID lpvReserved)
|
---|
| 984 | #endif
|
---|
| 985 | {
|
---|
| 986 | switch (fdwReason) {
|
---|
| 987 | case DLL_THREAD_DETACH:
|
---|
| 988 | #ifdef USE_TLS
|
---|
| 989 | xmlFreeGlobalState(&globalState);
|
---|
| 990 | #else
|
---|
| 991 | if (globalkey != TLS_OUT_OF_INDEXES) {
|
---|
| 992 | xmlGlobalState *globalval;
|
---|
| 993 |
|
---|
| 994 | globalval = (xmlGlobalState *) TlsGetValue(globalkey);
|
---|
| 995 | if (globalval) {
|
---|
| 996 | xmlFreeGlobalState(globalval);
|
---|
| 997 | TlsSetValue(globalkey, NULL);
|
---|
| 998 | }
|
---|
| 999 | }
|
---|
| 1000 | #endif
|
---|
| 1001 | break;
|
---|
| 1002 | }
|
---|
| 1003 | return TRUE;
|
---|
| 1004 | }
|
---|
| 1005 | #endif
|
---|
| 1006 |
|
---|
| 1007 | void
|
---|
| 1008 | xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
|
---|
| 1009 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1010 | xmlGenericErrorContextThrDef = ctx;
|
---|
| 1011 | if (handler != NULL)
|
---|
| 1012 | xmlGenericErrorThrDef = handler;
|
---|
| 1013 | else
|
---|
| 1014 | xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
|
---|
| 1015 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1016 | }
|
---|
| 1017 |
|
---|
| 1018 | void
|
---|
| 1019 | xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
|
---|
| 1020 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1021 | xmlStructuredErrorContextThrDef = ctx;
|
---|
| 1022 | xmlStructuredErrorThrDef = handler;
|
---|
| 1023 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1024 | }
|
---|
| 1025 |
|
---|
| 1026 | xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
|
---|
| 1027 | xmlBufferAllocationScheme ret;
|
---|
| 1028 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1029 | ret = xmlBufferAllocSchemeThrDef;
|
---|
| 1030 | xmlBufferAllocSchemeThrDef = v;
|
---|
| 1031 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1032 | return ret;
|
---|
| 1033 | }
|
---|
| 1034 |
|
---|
| 1035 | int xmlThrDefDefaultBufferSize(int v) {
|
---|
| 1036 | int ret;
|
---|
| 1037 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1038 | ret = xmlDefaultBufferSizeThrDef;
|
---|
| 1039 | xmlDefaultBufferSizeThrDef = v;
|
---|
| 1040 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1041 | return ret;
|
---|
| 1042 | }
|
---|
| 1043 |
|
---|
| 1044 | int xmlThrDefDoValidityCheckingDefaultValue(int v) {
|
---|
| 1045 | int ret;
|
---|
| 1046 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1047 | ret = xmlDoValidityCheckingDefaultValueThrDef;
|
---|
| 1048 | xmlDoValidityCheckingDefaultValueThrDef = v;
|
---|
| 1049 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1050 | return ret;
|
---|
| 1051 | }
|
---|
| 1052 |
|
---|
| 1053 | int xmlThrDefGetWarningsDefaultValue(int v) {
|
---|
| 1054 | int ret;
|
---|
| 1055 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1056 | ret = xmlGetWarningsDefaultValueThrDef;
|
---|
| 1057 | xmlGetWarningsDefaultValueThrDef = v;
|
---|
| 1058 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1059 | return ret;
|
---|
| 1060 | }
|
---|
| 1061 |
|
---|
| 1062 | #ifdef LIBXML_OUTPUT_ENABLED
|
---|
| 1063 | int xmlThrDefIndentTreeOutput(int v) {
|
---|
| 1064 | int ret;
|
---|
| 1065 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1066 | ret = xmlIndentTreeOutputThrDef;
|
---|
| 1067 | xmlIndentTreeOutputThrDef = v;
|
---|
| 1068 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1069 | return ret;
|
---|
| 1070 | }
|
---|
| 1071 |
|
---|
| 1072 | const char * xmlThrDefTreeIndentString(const char * v) {
|
---|
| 1073 | const char * ret;
|
---|
| 1074 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1075 | ret = xmlTreeIndentStringThrDef;
|
---|
| 1076 | xmlTreeIndentStringThrDef = v;
|
---|
| 1077 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1078 | return ret;
|
---|
| 1079 | }
|
---|
| 1080 |
|
---|
| 1081 | int xmlThrDefSaveNoEmptyTags(int v) {
|
---|
| 1082 | int ret;
|
---|
| 1083 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1084 | ret = xmlSaveNoEmptyTagsThrDef;
|
---|
| 1085 | xmlSaveNoEmptyTagsThrDef = v;
|
---|
| 1086 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1087 | return ret;
|
---|
| 1088 | }
|
---|
| 1089 | #endif
|
---|
| 1090 |
|
---|
| 1091 | int xmlThrDefKeepBlanksDefaultValue(int v) {
|
---|
| 1092 | int ret;
|
---|
| 1093 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1094 | ret = xmlKeepBlanksDefaultValueThrDef;
|
---|
| 1095 | xmlKeepBlanksDefaultValueThrDef = v;
|
---|
| 1096 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1097 | return ret;
|
---|
| 1098 | }
|
---|
| 1099 |
|
---|
| 1100 | int xmlThrDefLineNumbersDefaultValue(int v) {
|
---|
| 1101 | int ret;
|
---|
| 1102 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1103 | ret = xmlLineNumbersDefaultValueThrDef;
|
---|
| 1104 | xmlLineNumbersDefaultValueThrDef = v;
|
---|
| 1105 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1106 | return ret;
|
---|
| 1107 | }
|
---|
| 1108 |
|
---|
| 1109 | int xmlThrDefLoadExtDtdDefaultValue(int v) {
|
---|
| 1110 | int ret;
|
---|
| 1111 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1112 | ret = xmlLoadExtDtdDefaultValueThrDef;
|
---|
| 1113 | xmlLoadExtDtdDefaultValueThrDef = v;
|
---|
| 1114 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1115 | return ret;
|
---|
| 1116 | }
|
---|
| 1117 |
|
---|
| 1118 | int xmlThrDefParserDebugEntities(int v) {
|
---|
| 1119 | int ret;
|
---|
| 1120 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1121 | ret = xmlParserDebugEntitiesThrDef;
|
---|
| 1122 | xmlParserDebugEntitiesThrDef = v;
|
---|
| 1123 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1124 | return ret;
|
---|
| 1125 | }
|
---|
| 1126 |
|
---|
| 1127 | int xmlThrDefPedanticParserDefaultValue(int v) {
|
---|
| 1128 | int ret;
|
---|
| 1129 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1130 | ret = xmlPedanticParserDefaultValueThrDef;
|
---|
| 1131 | xmlPedanticParserDefaultValueThrDef = v;
|
---|
| 1132 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1133 | return ret;
|
---|
| 1134 | }
|
---|
| 1135 |
|
---|
| 1136 | int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
|
---|
| 1137 | int ret;
|
---|
| 1138 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1139 | ret = xmlSubstituteEntitiesDefaultValueThrDef;
|
---|
| 1140 | xmlSubstituteEntitiesDefaultValueThrDef = v;
|
---|
| 1141 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1142 | return ret;
|
---|
| 1143 | }
|
---|
| 1144 |
|
---|
| 1145 | xmlRegisterNodeFunc
|
---|
| 1146 | xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
|
---|
| 1147 | {
|
---|
| 1148 | xmlRegisterNodeFunc old;
|
---|
| 1149 |
|
---|
| 1150 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1151 | old = xmlRegisterNodeDefaultValueThrDef;
|
---|
| 1152 |
|
---|
| 1153 | __xmlRegisterCallbacks = 1;
|
---|
| 1154 | xmlRegisterNodeDefaultValueThrDef = func;
|
---|
| 1155 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1156 |
|
---|
| 1157 | return(old);
|
---|
| 1158 | }
|
---|
| 1159 |
|
---|
| 1160 | xmlDeregisterNodeFunc
|
---|
| 1161 | xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
|
---|
| 1162 | {
|
---|
| 1163 | xmlDeregisterNodeFunc old;
|
---|
| 1164 |
|
---|
| 1165 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1166 | old = xmlDeregisterNodeDefaultValueThrDef;
|
---|
| 1167 |
|
---|
| 1168 | __xmlRegisterCallbacks = 1;
|
---|
| 1169 | xmlDeregisterNodeDefaultValueThrDef = func;
|
---|
| 1170 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1171 |
|
---|
| 1172 | return(old);
|
---|
| 1173 | }
|
---|
| 1174 |
|
---|
| 1175 | xmlParserInputBufferCreateFilenameFunc
|
---|
| 1176 | xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
|
---|
| 1177 | {
|
---|
| 1178 | xmlParserInputBufferCreateFilenameFunc old;
|
---|
| 1179 |
|
---|
| 1180 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1181 | old = xmlParserInputBufferCreateFilenameValueThrDef;
|
---|
| 1182 | if (old == NULL) {
|
---|
| 1183 | old = __xmlParserInputBufferCreateFilename;
|
---|
| 1184 | }
|
---|
| 1185 |
|
---|
| 1186 | xmlParserInputBufferCreateFilenameValueThrDef = func;
|
---|
| 1187 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1188 |
|
---|
| 1189 | return(old);
|
---|
| 1190 | }
|
---|
| 1191 |
|
---|
| 1192 | xmlOutputBufferCreateFilenameFunc
|
---|
| 1193 | xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
|
---|
| 1194 | {
|
---|
| 1195 | xmlOutputBufferCreateFilenameFunc old;
|
---|
| 1196 |
|
---|
| 1197 | xmlMutexLock(&xmlThrDefMutex);
|
---|
| 1198 | old = xmlOutputBufferCreateFilenameValueThrDef;
|
---|
| 1199 | #ifdef LIBXML_OUTPUT_ENABLED
|
---|
| 1200 | if (old == NULL) {
|
---|
| 1201 | old = __xmlOutputBufferCreateFilename;
|
---|
| 1202 | }
|
---|
| 1203 | #endif
|
---|
| 1204 | xmlOutputBufferCreateFilenameValueThrDef = func;
|
---|
| 1205 | xmlMutexUnlock(&xmlThrDefMutex);
|
---|
| 1206 |
|
---|
| 1207 | return(old);
|
---|
| 1208 | }
|
---|
| 1209 |
|
---|