| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209 |
- /*
- * globals.c: definition and handling of the set of global variables
- * of the library
- *
- * See Copyright for the status of this software.
- *
- * Gary Pennington <Gary.Pennington@uk.sun.com>
- * daniel@veillard.com
- */
- #define IN_LIBXML
- #include "libxml.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define XML_GLOBALS_NO_REDEFINITION
- #include <libxml/globals.h>
- #include <libxml/xmlerror.h>
- #include <libxml/xmlmemory.h>
- #include <libxml/xmlIO.h>
- #include <libxml/HTMLparser.h>
- #include <libxml/parser.h>
- #include <libxml/threads.h>
- #include <libxml/tree.h>
- #include <libxml/SAX.h>
- #include <libxml/SAX2.h>
- #include "private/error.h"
- #include "private/globals.h"
- #include "private/threads.h"
- #include "private/tree.h"
- /*
- * Thread-local storage emulation.
- *
- * This works by replacing a global variable
- *
- * extern xmlError xmlLastError;
- *
- * with a macro that calls a function returning a pointer to the global in
- * thread-local storage:
- *
- * xmlError *__xmlLastError(void);
- * #define xmlError (*__xmlLastError());
- *
- * The code can operate in a multitude of ways depending on the environment.
- * First we support POSIX and Windows threads. Then we support both thread-local
- * storage provided by the compiler and older methods like thread-specific data
- * (pthreads) or TlsAlloc (Windows).
- *
- * To clean up thread-local storage, we use thread-specific data on POSIX.
- * On Windows, we either use DllMain when compiling a DLL or a registered wait
- * function for static builds.
- */
- /*
- * Helpful Macro
- */
- #ifdef LIBXML_THREAD_ENABLED
- #define IS_MAIN_THREAD (xmlIsMainThreadInternal())
- #else
- #define IS_MAIN_THREAD 1
- #endif
- #define XML_DECLARE_MEMBER(name, type, attrs) \
- type gs_##name;
- struct _xmlGlobalState {
- int initialized;
- #if defined(HAVE_WIN32_THREADS) && \
- defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
- void *threadHandle;
- void *waitHandle;
- #endif
- #define XML_OP XML_DECLARE_MEMBER
- XML_GLOBALS_ALLOC
- XML_GLOBALS_ERROR
- XML_GLOBALS_HTML
- XML_GLOBALS_IO
- XML_GLOBALS_PARSER
- XML_GLOBALS_TREE
- #undef XML_OP
- };
- static int parserInitialized;
- /*
- * Mutex to protect "ForNewThreads" variables
- */
- static xmlMutex xmlThrDefMutex;
- #ifdef LIBXML_THREAD_ENABLED
- /*
- * On Darwin, thread-local storage destructors seem to be run before
- * pthread thread-specific data destructors. This causes ASan to
- * report a use-after-free.
- *
- * On Windows, we can't use TLS in static builds. The RegisterWait
- * callback would run after TLS was deallocated.
- */
- #if defined(XML_THREAD_LOCAL) && \
- !defined(__APPLE__) && \
- (!defined(HAVE_WIN32_THREADS) || \
- !defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
- #define USE_TLS
- #endif
- #ifdef USE_TLS
- static XML_THREAD_LOCAL xmlGlobalState globalState;
- #endif
- #ifdef HAVE_POSIX_THREADS
- /*
- * Weak symbol hack, see threads.c
- */
- #if defined(__GNUC__) && \
- defined(__GLIBC__) && \
- __GLIBC__ * 100 + __GLIBC_MINOR__ < 234
- #pragma weak pthread_getspecific
- #pragma weak pthread_setspecific
- #pragma weak pthread_key_create
- #pragma weak pthread_key_delete
- #pragma weak pthread_equal
- #pragma weak pthread_self
- #define XML_PTHREAD_WEAK
- static int libxml_is_threaded = -1;
- #endif
- /*
- * On POSIX, we need thread-specific data even with thread-local storage
- * to destroy indirect references from global state (xmlLastError) at
- * thread exit.
- */
- static pthread_key_t globalkey;
- static pthread_t mainthread;
- #elif defined HAVE_WIN32_THREADS
- #ifndef USE_TLS
- static DWORD globalkey = TLS_OUT_OF_INDEXES;
- #endif
- static DWORD mainthread;
- #endif /* HAVE_WIN32_THREADS */
- static void
- xmlFreeGlobalState(void *state);
- #endif /* LIBXML_THREAD_ENABLED */
- /************************************************************************
- * *
- * All the user accessible global variables of the library *
- * *
- ************************************************************************/
- /*
- * Memory allocation routines
- */
- #if defined(DEBUG_MEMORY_LOCATION)
- xmlFreeFunc xmlFree = (xmlFreeFunc) xmlMemFree;
- xmlMallocFunc xmlMalloc = (xmlMallocFunc) xmlMemMalloc;
- xmlMallocFunc xmlMallocAtomic = (xmlMallocFunc) xmlMemMalloc;
- xmlReallocFunc xmlRealloc = (xmlReallocFunc) xmlMemRealloc;
- xmlStrdupFunc xmlMemStrdup = (xmlStrdupFunc) xmlMemoryStrdup;
- #else
- /**
- * xmlFree:
- * @mem: an already allocated block of memory
- *
- * The variable holding the libxml free() implementation
- */
- xmlFreeFunc xmlFree = free;
- /**
- * xmlMalloc:
- * @size: the size requested in bytes
- *
- * The variable holding the libxml malloc() implementation
- *
- * Returns a pointer to the newly allocated block or NULL in case of error
- */
- xmlMallocFunc xmlMalloc = malloc;
- /**
- * xmlMallocAtomic:
- * @size: the size requested in bytes
- *
- * The variable holding the libxml malloc() implementation for atomic
- * data (i.e. blocks not containing pointers), useful when using a
- * garbage collecting allocator.
- *
- * Returns a pointer to the newly allocated block or NULL in case of error
- */
- xmlMallocFunc xmlMallocAtomic = malloc;
- /**
- * xmlRealloc:
- * @mem: an already allocated block of memory
- * @size: the new size requested in bytes
- *
- * The variable holding the libxml realloc() implementation
- *
- * Returns a pointer to the newly reallocated block or NULL in case of error
- */
- xmlReallocFunc xmlRealloc = realloc;
- /**
- * xmlPosixStrdup
- * @cur: the input char *
- *
- * a strdup implementation with a type signature matching POSIX
- *
- * Returns a new xmlChar * or NULL
- */
- static char *
- xmlPosixStrdup(const char *cur) {
- return((char*) xmlCharStrdup(cur));
- }
- /**
- * xmlMemStrdup:
- * @str: a zero terminated string
- *
- * The variable holding the libxml strdup() implementation
- *
- * Returns the copy of the string or NULL in case of error
- */
- xmlStrdupFunc xmlMemStrdup = xmlPosixStrdup;
- #endif /* DEBUG_MEMORY_LOCATION */
- /**
- * xmlBufferAllocScheme:
- *
- * DEPRECATED: Don't use.
- *
- * Global setting, default allocation policy for buffers, default is
- * XML_BUFFER_ALLOC_EXACT
- */
- xmlBufferAllocationScheme xmlBufferAllocScheme = XML_BUFFER_ALLOC_EXACT;
- static xmlBufferAllocationScheme xmlBufferAllocSchemeThrDef = XML_BUFFER_ALLOC_EXACT;
- /**
- * xmlDefaultBufferSize:
- *
- * DEPRECATED: Don't use.
- *
- * Global setting, default buffer size. Default value is BASE_BUFFER_SIZE
- */
- int xmlDefaultBufferSize = BASE_BUFFER_SIZE;
- static int xmlDefaultBufferSizeThrDef = BASE_BUFFER_SIZE;
- /*
- * Parser defaults
- */
- /**
- * oldXMLWDcompatibility:
- *
- * Global setting, DEPRECATED.
- */
- int oldXMLWDcompatibility = 0; /* DEPRECATED */
- /**
- * xmlParserDebugEntities:
- *
- * DEPRECATED: Don't use
- *
- * Global setting, asking the parser to print out debugging information.
- * while handling entities.
- * Disabled by default
- */
- int xmlParserDebugEntities = 0;
- static int xmlParserDebugEntitiesThrDef = 0;
- /**
- * xmlDoValidityCheckingDefaultValue:
- *
- * DEPRECATED: Use the modern options API with XML_PARSE_DTDVALID.
- *
- * Global setting, indicate that the parser should work in validating mode.
- * Disabled by default.
- */
- int xmlDoValidityCheckingDefaultValue = 0;
- static int xmlDoValidityCheckingDefaultValueThrDef = 0;
- /**
- * xmlGetWarningsDefaultValue:
- *
- * DEPRECATED: Don't use
- *
- * Global setting, indicate that the DTD validation should provide warnings.
- * Activated by default.
- */
- int xmlGetWarningsDefaultValue = 1;
- static int xmlGetWarningsDefaultValueThrDef = 1;
- /**
- * xmlLoadExtDtdDefaultValue:
- *
- * DEPRECATED: Use the modern options API with XML_PARSE_DTDLOAD.
- *
- * Global setting, indicate that the parser should load DTD while not
- * validating.
- * Disabled by default.
- */
- int xmlLoadExtDtdDefaultValue = 0;
- static int xmlLoadExtDtdDefaultValueThrDef = 0;
- /**
- * xmlPedanticParserDefaultValue:
- *
- * DEPRECATED: Use the modern options API with XML_PARSE_PEDANTIC.
- *
- * Global setting, indicate that the parser be pedantic
- * Disabled by default.
- */
- int xmlPedanticParserDefaultValue = 0;
- static int xmlPedanticParserDefaultValueThrDef = 0;
- /**
- * xmlLineNumbersDefaultValue:
- *
- * DEPRECATED: The modern options API always enables line numbers.
- *
- * Global setting, indicate that the parser should store the line number
- * in the content field of elements in the DOM tree.
- * Disabled by default since this may not be safe for old classes of
- * application.
- */
- int xmlLineNumbersDefaultValue = 0;
- static int xmlLineNumbersDefaultValueThrDef = 0;
- /**
- * xmlKeepBlanksDefaultValue:
- *
- * DEPRECATED: Use the modern options API with XML_PARSE_NOBLANKS.
- *
- * Global setting, indicate that the parser should keep all blanks
- * nodes found in the content
- * Activated by default, this is actually needed to have the parser
- * conformant to the XML Recommendation, however the option is kept
- * for some applications since this was libxml1 default behaviour.
- */
- int xmlKeepBlanksDefaultValue = 1;
- static int xmlKeepBlanksDefaultValueThrDef = 1;
- /**
- * xmlSubstituteEntitiesDefaultValue:
- *
- * DEPRECATED: Use the modern options API with XML_PARSE_NOENT.
- *
- * Global setting, indicate that the parser should not generate entity
- * references but replace them with the actual content of the entity
- * Disabled by default, this should be activated when using XPath since
- * the XPath data model requires entities replacement and the XPath
- * engine does not handle entities references transparently.
- */
- int xmlSubstituteEntitiesDefaultValue = 0;
- static int xmlSubstituteEntitiesDefaultValueThrDef = 0;
- /**
- * xmlRegisterNodeDefaultValue:
- *
- * DEPRECATED: Don't use
- */
- xmlRegisterNodeFunc xmlRegisterNodeDefaultValue = NULL;
- static xmlRegisterNodeFunc xmlRegisterNodeDefaultValueThrDef = NULL;
- /**
- * xmlDeregisterNodeDefaultValue:
- *
- * DEPRECATED: Don't use
- */
- xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue = NULL;
- static xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValueThrDef = NULL;
- /**
- * xmlParserInputBufferCreateFilenameValue:
- *
- * DEPRECATED: Don't use
- */
- xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue = NULL;
- static xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValueThrDef = NULL;
- /**
- * xmlOutputBufferCreateFilenameValue:
- *
- * DEPRECATED: Don't use
- */
- xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue = NULL;
- static xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValueThrDef = NULL;
- /**
- * xmlGenericError:
- *
- * Global setting: function used for generic error callbacks
- */
- xmlGenericErrorFunc xmlGenericError = xmlGenericErrorDefaultFunc;
- static xmlGenericErrorFunc xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
- /**
- * xmlStructuredError:
- *
- * Global setting: function used for structured error callbacks
- */
- xmlStructuredErrorFunc xmlStructuredError = NULL;
- static xmlStructuredErrorFunc xmlStructuredErrorThrDef = NULL;
- /**
- * xmlGenericErrorContext:
- *
- * Global setting passed to generic error callbacks
- */
- void *xmlGenericErrorContext = NULL;
- static void *xmlGenericErrorContextThrDef = NULL;
- /**
- * xmlStructuredErrorContext:
- *
- * Global setting passed to structured error callbacks
- */
- void *xmlStructuredErrorContext = NULL;
- static void *xmlStructuredErrorContextThrDef = NULL;
- xmlError xmlLastError;
- #ifdef LIBXML_OUTPUT_ENABLED
- /*
- * output defaults
- */
- /**
- * xmlIndentTreeOutput:
- *
- * Global setting, asking the serializer to indent the output tree by default
- * Enabled by default
- */
- int xmlIndentTreeOutput = 1;
- static int xmlIndentTreeOutputThrDef = 1;
- /**
- * xmlTreeIndentString:
- *
- * The string used to do one-level indent. By default is equal to " " (two spaces)
- */
- const char *xmlTreeIndentString = " ";
- static const char *xmlTreeIndentStringThrDef = " ";
- /**
- * xmlSaveNoEmptyTags:
- *
- * Global setting, asking the serializer to not output empty tags
- * as <empty/> but <empty></empty>. those two forms are indistinguishable
- * once parsed.
- * Disabled by default
- */
- int xmlSaveNoEmptyTags = 0;
- static int xmlSaveNoEmptyTagsThrDef = 0;
- #endif /* LIBXML_OUTPUT_ENABLED */
- #ifdef LIBXML_SAX1_ENABLED
- /**
- * xmlDefaultSAXHandler:
- *
- * DEPRECATED: This handler is unused and will be removed from future
- * versions.
- *
- * Default SAX version1 handler for XML, builds the DOM tree
- */
- xmlSAXHandlerV1 xmlDefaultSAXHandler = {
- xmlSAX2InternalSubset,
- xmlSAX2IsStandalone,
- xmlSAX2HasInternalSubset,
- xmlSAX2HasExternalSubset,
- xmlSAX2ResolveEntity,
- xmlSAX2GetEntity,
- xmlSAX2EntityDecl,
- xmlSAX2NotationDecl,
- xmlSAX2AttributeDecl,
- xmlSAX2ElementDecl,
- xmlSAX2UnparsedEntityDecl,
- xmlSAX2SetDocumentLocator,
- xmlSAX2StartDocument,
- xmlSAX2EndDocument,
- xmlSAX2StartElement,
- xmlSAX2EndElement,
- xmlSAX2Reference,
- xmlSAX2Characters,
- xmlSAX2Characters,
- xmlSAX2ProcessingInstruction,
- xmlSAX2Comment,
- xmlParserWarning,
- xmlParserError,
- xmlParserError,
- xmlSAX2GetParameterEntity,
- xmlSAX2CDataBlock,
- xmlSAX2ExternalSubset,
- 1,
- };
- #endif /* LIBXML_SAX1_ENABLED */
- /**
- * xmlDefaultSAXLocator:
- *
- * DEPRECATED: Don't use
- *
- * The default SAX Locator
- * { getPublicId, getSystemId, getLineNumber, getColumnNumber}
- */
- xmlSAXLocator xmlDefaultSAXLocator = {
- xmlSAX2GetPublicId,
- xmlSAX2GetSystemId,
- xmlSAX2GetLineNumber,
- xmlSAX2GetColumnNumber
- };
- #if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_SAX1_ENABLED)
- /**
- * htmlDefaultSAXHandler:
- *
- * DEPRECATED: This handler is unused and will be removed from future
- * versions.
- *
- * Default old SAX v1 handler for HTML, builds the DOM tree
- */
- xmlSAXHandlerV1 htmlDefaultSAXHandler = {
- xmlSAX2InternalSubset,
- NULL,
- NULL,
- NULL,
- NULL,
- xmlSAX2GetEntity,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- xmlSAX2SetDocumentLocator,
- xmlSAX2StartDocument,
- xmlSAX2EndDocument,
- xmlSAX2StartElement,
- xmlSAX2EndElement,
- NULL,
- xmlSAX2Characters,
- xmlSAX2IgnorableWhitespace,
- xmlSAX2ProcessingInstruction,
- xmlSAX2Comment,
- xmlParserWarning,
- xmlParserError,
- xmlParserError,
- NULL,
- xmlSAX2CDataBlock,
- NULL,
- 1,
- };
- #endif /* LIBXML_HTML_ENABLED */
- /************************************************************************
- * *
- * Per thread global state handling *
- * *
- ************************************************************************/
- /**
- * xmlInitGlobals:
- *
- * DEPRECATED: Alias for xmlInitParser.
- */
- void xmlInitGlobals(void) {
- xmlInitParser();
- }
- /**
- * xmlInitGlobalsInternal:
- *
- * Additional initialisation for multi-threading
- */
- void xmlInitGlobalsInternal(void) {
- xmlInitMutex(&xmlThrDefMutex);
- #ifdef HAVE_POSIX_THREADS
- #ifdef XML_PTHREAD_WEAK
- if (libxml_is_threaded == -1)
- libxml_is_threaded =
- (pthread_getspecific != NULL) &&
- (pthread_setspecific != NULL) &&
- (pthread_key_create != NULL) &&
- (pthread_key_delete != NULL) &&
- /*
- * pthread_equal can be inline, resuting in -Waddress warnings.
- * Let's assume it's available if all the other functions are.
- */
- /* (pthread_equal != NULL) && */
- (pthread_self != NULL);
- if (libxml_is_threaded == 0)
- return;
- #endif /* XML_PTHREAD_WEAK */
- pthread_key_create(&globalkey, xmlFreeGlobalState);
- mainthread = pthread_self();
- #elif defined(HAVE_WIN32_THREADS)
- #ifndef USE_TLS
- globalkey = TlsAlloc();
- #endif
- mainthread = GetCurrentThreadId();
- #endif
- }
- /**
- * xmlCleanupGlobals:
- *
- * DEPRECATED: This function is a no-op. Call xmlCleanupParser
- * to free global state but see the warnings there. xmlCleanupParser
- * should be only called once at program exit. In most cases, you don't
- * have call cleanup functions at all.
- */
- void xmlCleanupGlobals(void) {
- }
- /**
- * xmlCleanupGlobalsInternal:
- *
- * Additional cleanup for multi-threading
- */
- void xmlCleanupGlobalsInternal(void) {
- xmlResetError(&xmlLastError);
- xmlCleanupMutex(&xmlThrDefMutex);
- #ifdef HAVE_POSIX_THREADS
- #ifdef XML_PTHREAD_WEAK
- if (libxml_is_threaded == 0)
- return;
- #endif /* XML_PTHREAD_WEAK */
- pthread_key_delete(globalkey);
- #elif defined(HAVE_WIN32_THREADS)
- #ifndef USE_TLS
- if (globalkey != TLS_OUT_OF_INDEXES) {
- TlsFree(globalkey);
- globalkey = TLS_OUT_OF_INDEXES;
- }
- #endif
- #endif
- parserInitialized = 0;
- }
- /**
- * xmlInitializeGlobalState:
- * @gs: a pointer to a newly allocated global state
- *
- * DEPRECATED: No-op.
- */
- void
- xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)
- {
- }
- /**
- * xmlGetGlobalState:
- *
- * DEPRECATED
- *
- * Returns NULL.
- */
- xmlGlobalStatePtr
- xmlGetGlobalState(void)
- {
- return(NULL);
- }
- static int
- xmlIsMainThreadInternal(void) {
- if (parserInitialized == 0) {
- xmlInitParser();
- parserInitialized = 1;
- }
- #ifdef HAVE_POSIX_THREADS
- #ifdef XML_PTHREAD_WEAK
- if (libxml_is_threaded == 0)
- return (1);
- #endif
- return (pthread_equal(mainthread, pthread_self()));
- #elif defined HAVE_WIN32_THREADS
- return (mainthread == GetCurrentThreadId());
- #else
- return (1);
- #endif
- }
- /**
- * xmlIsMainThread:
- *
- * DEPRECATED: Internal function, do not use.
- *
- * Check whether the current thread is the main thread.
- *
- * Returns 1 if the current thread is the main thread, 0 otherwise
- */
- int
- xmlIsMainThread(void) {
- return(xmlIsMainThreadInternal());
- }
- #ifdef LIBXML_THREAD_ENABLED
- static void
- xmlFreeGlobalState(void *state)
- {
- xmlGlobalState *gs = (xmlGlobalState *) state;
- /*
- * Free any memory allocated in the thread's xmlLastError. If it
- * weren't for this indirect allocation, we wouldn't need
- * a destructor with thread-local storage at all!
- *
- * It would be nice if we could make xmlLastError a special error
- * type which uses statically allocated, fixed-size buffers.
- * But the xmlError struct is fully public and widely used,
- * so changes are dangerous.
- */
- xmlResetError(&(gs->gs_xmlLastError));
- #ifndef USE_TLS
- free(state);
- #endif
- }
- #if defined(HAVE_WIN32_THREADS) && \
- defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
- static void WINAPI
- xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
- xmlGlobalStatePtr gs = ctxt;
- UnregisterWait(gs->waitHandle);
- CloseHandle(gs->threadHandle);
- xmlFreeGlobalState(gs);
- }
- static int
- xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
- void *processHandle = GetCurrentProcess();
- void *threadHandle;
- void *waitHandle;
- if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
- &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
- return(-1);
- }
- if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
- xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
- CloseHandle(threadHandle);
- return(-1);
- }
- gs->threadHandle = threadHandle;
- gs->waitHandle = waitHandle;
- return(0);
- }
- #endif /* LIBXML_STATIC */
- static void
- xmlInitGlobalState(xmlGlobalStatePtr gs) {
- xmlMutexLock(&xmlThrDefMutex);
- #if defined(LIBXML_HTML_ENABLED) && defined(LIBXML_LEGACY_ENABLED) && defined(LIBXML_SAX1_ENABLED)
- inithtmlDefaultSAXHandler(&gs->gs_htmlDefaultSAXHandler);
- #endif
- gs->gs_oldXMLWDcompatibility = 0;
- gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
- gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
- #if defined(LIBXML_SAX1_ENABLED) && defined(LIBXML_LEGACY_ENABLED)
- initxmlDefaultSAXHandler(&gs->gs_xmlDefaultSAXHandler, 1);
- #endif /* LIBXML_SAX1_ENABLED */
- gs->gs_xmlDefaultSAXLocator.getPublicId = xmlSAX2GetPublicId;
- gs->gs_xmlDefaultSAXLocator.getSystemId = xmlSAX2GetSystemId;
- gs->gs_xmlDefaultSAXLocator.getLineNumber = xmlSAX2GetLineNumber;
- gs->gs_xmlDefaultSAXLocator.getColumnNumber = xmlSAX2GetColumnNumber;
- gs->gs_xmlDoValidityCheckingDefaultValue =
- xmlDoValidityCheckingDefaultValueThrDef;
- #ifdef LIBXML_THREAD_ALLOC_ENABLED
- #ifdef DEBUG_MEMORY_LOCATION
- gs->gs_xmlFree = xmlMemFree;
- gs->gs_xmlMalloc = xmlMemMalloc;
- gs->gs_xmlMallocAtomic = xmlMemMalloc;
- gs->gs_xmlRealloc = xmlMemRealloc;
- gs->gs_xmlMemStrdup = xmlMemoryStrdup;
- #else
- gs->gs_xmlFree = free;
- gs->gs_xmlMalloc = malloc;
- gs->gs_xmlMallocAtomic = malloc;
- gs->gs_xmlRealloc = realloc;
- gs->gs_xmlMemStrdup = xmlPosixStrdup;
- #endif
- #endif
- gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
- #ifdef LIBXML_OUTPUT_ENABLED
- gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
- gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef;
- gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
- #endif
- gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
- gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
- gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
- gs->gs_xmlParserDebugEntities = xmlParserDebugEntitiesThrDef;
- gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
- gs->gs_xmlSubstituteEntitiesDefaultValue =
- xmlSubstituteEntitiesDefaultValueThrDef;
- gs->gs_xmlGenericError = xmlGenericErrorThrDef;
- gs->gs_xmlStructuredError = xmlStructuredErrorThrDef;
- gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef;
- gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
- gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
- gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
- gs->gs_xmlParserInputBufferCreateFilenameValue =
- xmlParserInputBufferCreateFilenameValueThrDef;
- gs->gs_xmlOutputBufferCreateFilenameValue =
- xmlOutputBufferCreateFilenameValueThrDef;
- memset(&gs->gs_xmlLastError, 0, sizeof(xmlError));
- xmlMutexUnlock(&xmlThrDefMutex);
- #ifdef HAVE_POSIX_THREADS
- pthread_setspecific(globalkey, gs);
- #elif defined HAVE_WIN32_THREADS
- #ifndef USE_TLS
- TlsSetValue(globalkey, gs);
- #endif
- #if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
- xmlRegisterGlobalStateDtor(gs);
- #endif
- #endif
- gs->initialized = 1;
- }
- #ifndef USE_TLS
- /**
- * xmlNewGlobalState:
- *
- * xmlNewGlobalState() allocates a global state. This structure is used to
- * hold all data for use by a thread when supporting backwards compatibility
- * of libxml2 to pre-thread-safe behaviour.
- *
- * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
- */
- static xmlGlobalStatePtr
- xmlNewGlobalState(int allowFailure)
- {
- xmlGlobalState *gs;
- gs = malloc(sizeof(xmlGlobalState));
- if (gs == NULL) {
- if (allowFailure)
- return(NULL);
- /*
- * If an application didn't call xmlCheckThreadLocalStorage to make
- * sure that global state could be allocated, it's too late to
- * handle the error.
- */
- fprintf(stderr, "libxml2: Failed to allocate globals for thread\n"
- "libxml2: See xmlCheckThreadLocalStorage\n");
- abort();
- }
- memset(gs, 0, sizeof(xmlGlobalState));
- xmlInitGlobalState(gs);
- return (gs);
- }
- #endif
- static xmlGlobalStatePtr
- xmlGetThreadLocalStorage(int allowFailure) {
- xmlGlobalState *gs;
- (void) allowFailure;
- #ifdef USE_TLS
- gs = &globalState;
- if (gs->initialized == 0)
- xmlInitGlobalState(gs);
- #elif defined(HAVE_POSIX_THREADS)
- gs = (xmlGlobalState *) pthread_getspecific(globalkey);
- if (gs == NULL)
- gs = xmlNewGlobalState(allowFailure);
- #elif defined(HAVE_WIN32_THREADS)
- gs = (xmlGlobalState *) TlsGetValue(globalkey);
- if (gs == NULL)
- gs = xmlNewGlobalState(allowFailure);
- #else
- gs = NULL;
- #endif
- return(gs);
- }
- /* Define thread-local storage accessors with macro magic */
- #define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \
- type *__##name(void) { \
- if (IS_MAIN_THREAD) \
- return (&name); \
- else \
- return (&xmlGetThreadLocalStorage(0)->gs_##name); \
- }
- #define XML_OP XML_DEFINE_GLOBAL_WRAPPER
- XML_GLOBALS_ALLOC
- XML_GLOBALS_ERROR
- XML_GLOBALS_HTML
- XML_GLOBALS_IO
- XML_GLOBALS_PARSER
- XML_GLOBALS_TREE
- #undef XML_OP
- /* For backward compatibility */
- const char *const *
- __xmlParserVersion(void) {
- return &xmlParserVersion;
- }
- #endif /* LIBXML_THREAD_ENABLED */
- /**
- * xmlCheckThreadLocalStorage:
- *
- * Check whether thread-local storage could be allocated.
- *
- * In cross-platform code running in multithreaded environments, this
- * function should be called once in each thread before calling other
- * library functions to make sure that thread-local storage was
- * allocated properly.
- *
- * Returns 0 on success or -1 if a memory allocation failed. A failed
- * allocation signals a typically fatal and irrecoverable out-of-memory
- * situation. Don't call any library functions in this case.
- *
- * This function never fails if the library is compiled with support
- * for thread-local storage.
- *
- * This function never fails for the "main" thread which is the first
- * thread calling xmlInitParser.
- *
- * Available since v2.12.0.
- */
- int
- xmlCheckThreadLocalStorage(void) {
- #if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
- if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
- return(-1);
- #endif
- return(0);
- }
- /**
- * DllMain:
- * @hinstDLL: handle to DLL instance
- * @fdwReason: Reason code for entry
- * @lpvReserved: generic pointer (depends upon reason code)
- *
- * Entry point for Windows library. It is being used to free thread-specific
- * storage.
- *
- * Returns TRUE always
- */
- #if defined(HAVE_WIN32_THREADS) && \
- (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
- #if defined(LIBXML_STATIC_FOR_DLL)
- int
- xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
- ATTRIBUTE_UNUSED void *lpvReserved)
- #else
- /* declare to avoid "no previous prototype for 'DllMain'" warning */
- /* Note that we do NOT want to include this function declaration in
- a public header because it's meant to be called by Windows itself,
- not a program that uses this library. This also has to be exported. */
- XMLPUBFUN BOOL WINAPI
- DllMain (HINSTANCE hinstDLL,
- DWORD fdwReason,
- LPVOID lpvReserved);
- BOOL WINAPI
- DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
- ATTRIBUTE_UNUSED LPVOID lpvReserved)
- #endif
- {
- switch (fdwReason) {
- case DLL_THREAD_DETACH:
- #ifdef USE_TLS
- xmlFreeGlobalState(&globalState);
- #else
- if (globalkey != TLS_OUT_OF_INDEXES) {
- xmlGlobalState *globalval;
- globalval = (xmlGlobalState *) TlsGetValue(globalkey);
- if (globalval) {
- xmlFreeGlobalState(globalval);
- TlsSetValue(globalkey, NULL);
- }
- }
- #endif
- break;
- }
- return TRUE;
- }
- #endif
- void
- xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
- xmlMutexLock(&xmlThrDefMutex);
- xmlGenericErrorContextThrDef = ctx;
- if (handler != NULL)
- xmlGenericErrorThrDef = handler;
- else
- xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
- xmlMutexUnlock(&xmlThrDefMutex);
- }
- void
- xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
- xmlMutexLock(&xmlThrDefMutex);
- xmlStructuredErrorContextThrDef = ctx;
- xmlStructuredErrorThrDef = handler;
- xmlMutexUnlock(&xmlThrDefMutex);
- }
- xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
- xmlBufferAllocationScheme ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlBufferAllocSchemeThrDef;
- xmlBufferAllocSchemeThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefDefaultBufferSize(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlDefaultBufferSizeThrDef;
- xmlDefaultBufferSizeThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefDoValidityCheckingDefaultValue(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlDoValidityCheckingDefaultValueThrDef;
- xmlDoValidityCheckingDefaultValueThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefGetWarningsDefaultValue(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlGetWarningsDefaultValueThrDef;
- xmlGetWarningsDefaultValueThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- #ifdef LIBXML_OUTPUT_ENABLED
- int xmlThrDefIndentTreeOutput(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlIndentTreeOutputThrDef;
- xmlIndentTreeOutputThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- const char * xmlThrDefTreeIndentString(const char * v) {
- const char * ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlTreeIndentStringThrDef;
- xmlTreeIndentStringThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefSaveNoEmptyTags(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlSaveNoEmptyTagsThrDef;
- xmlSaveNoEmptyTagsThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- #endif
- int xmlThrDefKeepBlanksDefaultValue(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlKeepBlanksDefaultValueThrDef;
- xmlKeepBlanksDefaultValueThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefLineNumbersDefaultValue(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlLineNumbersDefaultValueThrDef;
- xmlLineNumbersDefaultValueThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefLoadExtDtdDefaultValue(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlLoadExtDtdDefaultValueThrDef;
- xmlLoadExtDtdDefaultValueThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefParserDebugEntities(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlParserDebugEntitiesThrDef;
- xmlParserDebugEntitiesThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefPedanticParserDefaultValue(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlPedanticParserDefaultValueThrDef;
- xmlPedanticParserDefaultValueThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
- int ret;
- xmlMutexLock(&xmlThrDefMutex);
- ret = xmlSubstituteEntitiesDefaultValueThrDef;
- xmlSubstituteEntitiesDefaultValueThrDef = v;
- xmlMutexUnlock(&xmlThrDefMutex);
- return ret;
- }
- xmlRegisterNodeFunc
- xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
- {
- xmlRegisterNodeFunc old;
- xmlMutexLock(&xmlThrDefMutex);
- old = xmlRegisterNodeDefaultValueThrDef;
- __xmlRegisterCallbacks = 1;
- xmlRegisterNodeDefaultValueThrDef = func;
- xmlMutexUnlock(&xmlThrDefMutex);
- return(old);
- }
- xmlDeregisterNodeFunc
- xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
- {
- xmlDeregisterNodeFunc old;
- xmlMutexLock(&xmlThrDefMutex);
- old = xmlDeregisterNodeDefaultValueThrDef;
- __xmlRegisterCallbacks = 1;
- xmlDeregisterNodeDefaultValueThrDef = func;
- xmlMutexUnlock(&xmlThrDefMutex);
- return(old);
- }
- xmlParserInputBufferCreateFilenameFunc
- xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
- {
- xmlParserInputBufferCreateFilenameFunc old;
- xmlMutexLock(&xmlThrDefMutex);
- old = xmlParserInputBufferCreateFilenameValueThrDef;
- if (old == NULL) {
- old = __xmlParserInputBufferCreateFilename;
- }
- xmlParserInputBufferCreateFilenameValueThrDef = func;
- xmlMutexUnlock(&xmlThrDefMutex);
- return(old);
- }
- xmlOutputBufferCreateFilenameFunc
- xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
- {
- xmlOutputBufferCreateFilenameFunc old;
- xmlMutexLock(&xmlThrDefMutex);
- old = xmlOutputBufferCreateFilenameValueThrDef;
- #ifdef LIBXML_OUTPUT_ENABLED
- if (old == NULL) {
- old = __xmlOutputBufferCreateFilename;
- }
- #endif
- xmlOutputBufferCreateFilenameValueThrDef = func;
- xmlMutexUnlock(&xmlThrDefMutex);
- return(old);
- }
|