VirtualBox

source: vbox/trunk/src/libs/libxml2-2.13.2/globals.c@ 106180

Last change on this file since 106180 was 105448, checked in by vboxsync, 4 months ago

libxml2-2.13.2: builds and runs on Linux. bugref:10730

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette