VirtualBox

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

最後變更 在這個檔案從105420是 105420,由 vboxsync 提交於 7 月 前

libxml2-2.12.6: Applied and adjusted our libxml2 changes to 2.12.6. bugref:10730

  • 屬性 svn:eol-style 設為 native
檔案大小: 31.2 KB
 
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 <[email protected]>
8 * [email protected]
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#ifdef LIBXML_THREAD_ENABLED
599 xmlMainThreadRngState[0] = xmlGlobalRandom();
600 xmlMainThreadRngState[1] = xmlGlobalRandom();
601#endif
602}
603
604/**
605 * xmlCleanupGlobals:
606 *
607 * DEPRECATED: This function is a no-op. Call xmlCleanupParser
608 * to free global state but see the warnings there. xmlCleanupParser
609 * should be only called once at program exit. In most cases, you don't
610 * have call cleanup functions at all.
611 */
612void xmlCleanupGlobals(void) {
613}
614
615/**
616 * xmlCleanupGlobalsInternal:
617 *
618 * Additional cleanup for multi-threading
619 */
620void xmlCleanupGlobalsInternal(void) {
621 xmlResetError(&xmlLastError);
622
623 xmlCleanupMutex(&xmlThrDefMutex);
624
625#ifdef HAVE_POSIX_THREADS
626#ifdef XML_PTHREAD_WEAK
627 if (libxml_is_threaded == 0)
628 return;
629#endif /* XML_PTHREAD_WEAK */
630 pthread_key_delete(globalkey);
631#elif defined(HAVE_WIN32_THREADS)
632#ifndef USE_TLS
633 if (globalkey != TLS_OUT_OF_INDEXES) {
634 TlsFree(globalkey);
635 globalkey = TLS_OUT_OF_INDEXES;
636 }
637#endif
638#endif
639
640 parserInitialized = 0;
641}
642
643/**
644 * xmlInitializeGlobalState:
645 * @gs: a pointer to a newly allocated global state
646 *
647 * DEPRECATED: No-op.
648 */
649void
650xmlInitializeGlobalState(xmlGlobalStatePtr gs ATTRIBUTE_UNUSED)
651{
652}
653
654/**
655 * xmlGetGlobalState:
656 *
657 * DEPRECATED
658 *
659 * Returns NULL.
660 */
661xmlGlobalStatePtr
662xmlGetGlobalState(void)
663{
664 return(NULL);
665}
666
667static int
668xmlIsMainThreadInternal(void) {
669 if (parserInitialized == 0) {
670 xmlInitParser();
671 parserInitialized = 1;
672 }
673
674#ifdef HAVE_POSIX_THREADS
675#ifdef XML_PTHREAD_WEAK
676 if (libxml_is_threaded == 0)
677 return (1);
678#endif
679 return (pthread_equal(mainthread, pthread_self()));
680#elif defined HAVE_WIN32_THREADS
681 return (mainthread == GetCurrentThreadId());
682#else
683 return (1);
684#endif
685}
686
687/**
688 * xmlIsMainThread:
689 *
690 * DEPRECATED: Internal function, do not use.
691 *
692 * Check whether the current thread is the main thread.
693 *
694 * Returns 1 if the current thread is the main thread, 0 otherwise
695 */
696int
697xmlIsMainThread(void) {
698 return(xmlIsMainThreadInternal());
699}
700
701#ifdef LIBXML_THREAD_ENABLED
702
703static void
704xmlFreeGlobalState(void *state)
705{
706 xmlGlobalState *gs = (xmlGlobalState *) state;
707
708 /*
709 * Free any memory allocated in the thread's xmlLastError. If it
710 * weren't for this indirect allocation, we wouldn't need
711 * a destructor with thread-local storage at all!
712 *
713 * It would be nice if we could make xmlLastError a special error
714 * type which uses statically allocated, fixed-size buffers.
715 * But the xmlError struct is fully public and widely used,
716 * so changes are dangerous.
717 */
718 xmlResetError(&(gs->gs_xmlLastError));
719#ifndef USE_TLS
720 free(state);
721#endif
722}
723
724#if defined(HAVE_WIN32_THREADS) && \
725 defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
726static void WINAPI
727xmlGlobalStateDtor(void *ctxt, unsigned char timedOut ATTRIBUTE_UNUSED) {
728 xmlGlobalStatePtr gs = ctxt;
729
730 UnregisterWait(gs->waitHandle);
731 CloseHandle(gs->threadHandle);
732 xmlFreeGlobalState(gs);
733}
734
735static int
736xmlRegisterGlobalStateDtor(xmlGlobalState *gs) {
737 void *processHandle = GetCurrentProcess();
738 void *threadHandle;
739 void *waitHandle;
740
741 if (DuplicateHandle(processHandle, GetCurrentThread(), processHandle,
742 &threadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS) == 0) {
743 return(-1);
744 }
745
746 if (RegisterWaitForSingleObject(&waitHandle, threadHandle,
747 xmlGlobalStateDtor, gs, INFINITE, WT_EXECUTEONLYONCE) == 0) {
748 CloseHandle(threadHandle);
749 return(-1);
750 }
751
752 gs->threadHandle = threadHandle;
753 gs->waitHandle = waitHandle;
754 return(0);
755}
756#endif /* LIBXML_STATIC */
757
758static void
759xmlInitGlobalState(xmlGlobalStatePtr gs) {
760 xmlMutexLock(&xmlThrDefMutex);
761
762#ifdef LIBXML_THREAD_ENABLED
763 gs->localRngState[0] = xmlGlobalRandom();
764 gs->localRngState[1] = xmlGlobalRandom();
765#endif
766
767 gs->gs_xmlBufferAllocScheme = xmlBufferAllocSchemeThrDef;
768 gs->gs_xmlDefaultBufferSize = xmlDefaultBufferSizeThrDef;
769 gs->gs_xmlDoValidityCheckingDefaultValue =
770 xmlDoValidityCheckingDefaultValueThrDef;
771#ifdef LIBXML_THREAD_ALLOC_ENABLED
772 gs->gs_xmlFree = free;
773 gs->gs_xmlMalloc = malloc;
774 gs->gs_xmlMallocAtomic = malloc;
775 gs->gs_xmlRealloc = realloc;
776 gs->gs_xmlMemStrdup = xmlPosixStrdup;
777#endif
778 gs->gs_xmlGetWarningsDefaultValue = xmlGetWarningsDefaultValueThrDef;
779#ifdef LIBXML_OUTPUT_ENABLED
780 gs->gs_xmlIndentTreeOutput = xmlIndentTreeOutputThrDef;
781 gs->gs_xmlTreeIndentString = xmlTreeIndentStringThrDef;
782 gs->gs_xmlSaveNoEmptyTags = xmlSaveNoEmptyTagsThrDef;
783#endif
784 gs->gs_xmlKeepBlanksDefaultValue = xmlKeepBlanksDefaultValueThrDef;
785 gs->gs_xmlLineNumbersDefaultValue = xmlLineNumbersDefaultValueThrDef;
786 gs->gs_xmlLoadExtDtdDefaultValue = xmlLoadExtDtdDefaultValueThrDef;
787 gs->gs_xmlPedanticParserDefaultValue = xmlPedanticParserDefaultValueThrDef;
788 gs->gs_xmlSubstituteEntitiesDefaultValue =
789 xmlSubstituteEntitiesDefaultValueThrDef;
790
791 gs->gs_xmlGenericError = xmlGenericErrorThrDef;
792 gs->gs_xmlStructuredError = xmlStructuredErrorThrDef;
793 gs->gs_xmlGenericErrorContext = xmlGenericErrorContextThrDef;
794 gs->gs_xmlStructuredErrorContext = xmlStructuredErrorContextThrDef;
795 gs->gs_xmlRegisterNodeDefaultValue = xmlRegisterNodeDefaultValueThrDef;
796 gs->gs_xmlDeregisterNodeDefaultValue = xmlDeregisterNodeDefaultValueThrDef;
797
798 gs->gs_xmlParserInputBufferCreateFilenameValue =
799 xmlParserInputBufferCreateFilenameValueThrDef;
800 gs->gs_xmlOutputBufferCreateFilenameValue =
801 xmlOutputBufferCreateFilenameValueThrDef;
802 memset(&gs->gs_xmlLastError, 0, sizeof(xmlError));
803
804 xmlMutexUnlock(&xmlThrDefMutex);
805
806#ifdef HAVE_POSIX_THREADS
807 pthread_setspecific(globalkey, gs);
808#elif defined HAVE_WIN32_THREADS
809#ifndef USE_TLS
810 TlsSetValue(globalkey, gs);
811#endif
812#if defined(LIBXML_STATIC) && !defined(LIBXML_STATIC_FOR_DLL)
813 xmlRegisterGlobalStateDtor(gs);
814#endif
815#endif
816
817 gs->initialized = 1;
818}
819
820#ifndef USE_TLS
821/**
822 * xmlNewGlobalState:
823 *
824 * xmlNewGlobalState() allocates a global state. This structure is used to
825 * hold all data for use by a thread when supporting backwards compatibility
826 * of libxml2 to pre-thread-safe behaviour.
827 *
828 * Returns the newly allocated xmlGlobalStatePtr or NULL in case of error
829 */
830static xmlGlobalStatePtr
831xmlNewGlobalState(int allowFailure)
832{
833 xmlGlobalState *gs;
834
835 gs = malloc(sizeof(xmlGlobalState));
836 if (gs == NULL) {
837 if (allowFailure)
838 return(NULL);
839
840 /*
841 * If an application didn't call xmlCheckThreadLocalStorage to make
842 * sure that global state could be allocated, it's too late to
843 * handle the error.
844 */
845 fprintf(stderr, "libxml2: Failed to allocate globals for thread\n"
846 "libxml2: See xmlCheckThreadLocalStorage\n");
847 abort();
848 }
849
850 memset(gs, 0, sizeof(xmlGlobalState));
851 xmlInitGlobalState(gs);
852 return (gs);
853}
854#endif
855
856static xmlGlobalStatePtr
857xmlGetThreadLocalStorage(int allowFailure) {
858 xmlGlobalState *gs;
859
860 (void) allowFailure;
861
862#ifdef USE_TLS
863 gs = &globalState;
864 if (gs->initialized == 0)
865 xmlInitGlobalState(gs);
866#elif defined(HAVE_POSIX_THREADS)
867 gs = (xmlGlobalState *) pthread_getspecific(globalkey);
868 if (gs == NULL)
869 gs = xmlNewGlobalState(allowFailure);
870#elif defined(HAVE_WIN32_THREADS)
871 gs = (xmlGlobalState *) TlsGetValue(globalkey);
872 if (gs == NULL)
873 gs = xmlNewGlobalState(allowFailure);
874#else
875 gs = NULL;
876#endif
877
878 return(gs);
879}
880
881/* Define thread-local storage accessors with macro magic */
882
883#define XML_DEFINE_GLOBAL_WRAPPER(name, type, attrs) \
884 type *__##name(void) { \
885 if (IS_MAIN_THREAD) \
886 return (&name); \
887 else \
888 return (&xmlGetThreadLocalStorage(0)->gs_##name); \
889 }
890
891#define XML_OP XML_DEFINE_GLOBAL_WRAPPER
892XML_GLOBALS_ALLOC
893XML_GLOBALS_ERROR
894XML_GLOBALS_IO
895XML_GLOBALS_PARSER
896XML_GLOBALS_TREE
897#undef XML_OP
898
899#ifdef LIBXML_THREAD_ENABLED
900/**
901 * xmlGetLocalRngState:
902 *
903 * Returns the local RNG state.
904 */
905unsigned *
906xmlGetLocalRngState(void) {
907 if (IS_MAIN_THREAD)
908 return(xmlMainThreadRngState);
909 else
910 return(xmlGetThreadLocalStorage(0)->localRngState);
911}
912#endif
913
914/* For backward compatibility */
915
916const char *const *
917__xmlParserVersion(void) {
918 return &xmlParserVersion;
919}
920
921const int *
922__oldXMLWDcompatibility(void) {
923 return &oldXMLWDcompatibility;
924}
925
926const int *
927__xmlParserDebugEntities(void) {
928 return &xmlParserDebugEntities;
929}
930
931const xmlSAXLocator *
932__xmlDefaultSAXLocator(void) {
933 return &xmlDefaultSAXLocator;
934}
935
936#ifdef LIBXML_SAX1_ENABLED
937const xmlSAXHandlerV1 *
938__xmlDefaultSAXHandler(void) {
939 return &xmlDefaultSAXHandler;
940}
941
942#ifdef LIBXML_HTML_ENABLED
943const xmlSAXHandlerV1 *
944__htmlDefaultSAXHandler(void) {
945 return &htmlDefaultSAXHandler;
946}
947#endif /* LIBXML_HTML_ENABLED */
948#endif /* LIBXML_SAX1_ENABLED */
949
950#endif /* LIBXML_THREAD_ENABLED */
951
952/**
953 * xmlCheckThreadLocalStorage:
954 *
955 * Check whether thread-local storage could be allocated.
956 *
957 * In cross-platform code running in multithreaded environments, this
958 * function should be called once in each thread before calling other
959 * library functions to make sure that thread-local storage was
960 * allocated properly.
961 *
962 * Returns 0 on success or -1 if a memory allocation failed. A failed
963 * allocation signals a typically fatal and irrecoverable out-of-memory
964 * situation. Don't call any library functions in this case.
965 *
966 * This function never fails if the library is compiled with support
967 * for thread-local storage.
968 *
969 * This function never fails for the "main" thread which is the first
970 * thread calling xmlInitParser.
971 *
972 * Available since v2.12.0.
973 */
974int
975xmlCheckThreadLocalStorage(void) {
976#if defined(LIBXML_THREAD_ENABLED) && !defined(USE_TLS)
977 if ((!xmlIsMainThreadInternal()) && (xmlGetThreadLocalStorage(1) == NULL))
978 return(-1);
979#endif
980 return(0);
981}
982
983/** DOC_DISABLE */
984
985/**
986 * DllMain:
987 * @hinstDLL: handle to DLL instance
988 * @fdwReason: Reason code for entry
989 * @lpvReserved: generic pointer (depends upon reason code)
990 *
991 * Entry point for Windows library. It is being used to free thread-specific
992 * storage.
993 *
994 * Returns TRUE always
995 */
996#if defined(HAVE_WIN32_THREADS) && \
997 (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL))
998#if defined(LIBXML_STATIC_FOR_DLL)
999int
1000xmlDllMain(ATTRIBUTE_UNUSED void *hinstDLL, unsigned long fdwReason,
1001 ATTRIBUTE_UNUSED void *lpvReserved)
1002#else
1003/* declare to avoid "no previous prototype for 'DllMain'" warning */
1004/* Note that we do NOT want to include this function declaration in
1005 a public header because it's meant to be called by Windows itself,
1006 not a program that uses this library. This also has to be exported. */
1007
1008XMLPUBFUN BOOL WINAPI
1009DllMain (HINSTANCE hinstDLL,
1010 DWORD fdwReason,
1011 LPVOID lpvReserved);
1012
1013BOOL WINAPI
1014DllMain(ATTRIBUTE_UNUSED HINSTANCE hinstDLL, DWORD fdwReason,
1015 ATTRIBUTE_UNUSED LPVOID lpvReserved)
1016#endif
1017{
1018 switch (fdwReason) {
1019 case DLL_THREAD_DETACH:
1020#ifdef USE_TLS
1021 xmlFreeGlobalState(&globalState);
1022#else
1023 if (globalkey != TLS_OUT_OF_INDEXES) {
1024 xmlGlobalState *globalval;
1025
1026 globalval = (xmlGlobalState *) TlsGetValue(globalkey);
1027 if (globalval) {
1028 xmlFreeGlobalState(globalval);
1029 TlsSetValue(globalkey, NULL);
1030 }
1031 }
1032#endif
1033 break;
1034 }
1035 return TRUE;
1036}
1037#endif
1038
1039void
1040xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
1041 xmlMutexLock(&xmlThrDefMutex);
1042 xmlGenericErrorContextThrDef = ctx;
1043 if (handler != NULL)
1044 xmlGenericErrorThrDef = handler;
1045 else
1046 xmlGenericErrorThrDef = xmlGenericErrorDefaultFunc;
1047 xmlMutexUnlock(&xmlThrDefMutex);
1048}
1049
1050void
1051xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler) {
1052 xmlMutexLock(&xmlThrDefMutex);
1053 xmlStructuredErrorContextThrDef = ctx;
1054 xmlStructuredErrorThrDef = handler;
1055 xmlMutexUnlock(&xmlThrDefMutex);
1056}
1057
1058xmlBufferAllocationScheme xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v) {
1059 xmlBufferAllocationScheme ret;
1060 xmlMutexLock(&xmlThrDefMutex);
1061 ret = xmlBufferAllocSchemeThrDef;
1062 xmlBufferAllocSchemeThrDef = v;
1063 xmlMutexUnlock(&xmlThrDefMutex);
1064 return ret;
1065}
1066
1067int xmlThrDefDefaultBufferSize(int v) {
1068 int ret;
1069 xmlMutexLock(&xmlThrDefMutex);
1070 ret = xmlDefaultBufferSizeThrDef;
1071 xmlDefaultBufferSizeThrDef = v;
1072 xmlMutexUnlock(&xmlThrDefMutex);
1073 return ret;
1074}
1075
1076int xmlThrDefDoValidityCheckingDefaultValue(int v) {
1077 int ret;
1078 xmlMutexLock(&xmlThrDefMutex);
1079 ret = xmlDoValidityCheckingDefaultValueThrDef;
1080 xmlDoValidityCheckingDefaultValueThrDef = v;
1081 xmlMutexUnlock(&xmlThrDefMutex);
1082 return ret;
1083}
1084
1085int xmlThrDefGetWarningsDefaultValue(int v) {
1086 int ret;
1087 xmlMutexLock(&xmlThrDefMutex);
1088 ret = xmlGetWarningsDefaultValueThrDef;
1089 xmlGetWarningsDefaultValueThrDef = v;
1090 xmlMutexUnlock(&xmlThrDefMutex);
1091 return ret;
1092}
1093
1094#ifdef LIBXML_OUTPUT_ENABLED
1095int xmlThrDefIndentTreeOutput(int v) {
1096 int ret;
1097 xmlMutexLock(&xmlThrDefMutex);
1098 ret = xmlIndentTreeOutputThrDef;
1099 xmlIndentTreeOutputThrDef = v;
1100 xmlMutexUnlock(&xmlThrDefMutex);
1101 return ret;
1102}
1103
1104const char * xmlThrDefTreeIndentString(const char * v) {
1105 const char * ret;
1106 xmlMutexLock(&xmlThrDefMutex);
1107 ret = xmlTreeIndentStringThrDef;
1108 xmlTreeIndentStringThrDef = v;
1109 xmlMutexUnlock(&xmlThrDefMutex);
1110 return ret;
1111}
1112
1113int xmlThrDefSaveNoEmptyTags(int v) {
1114 int ret;
1115 xmlMutexLock(&xmlThrDefMutex);
1116 ret = xmlSaveNoEmptyTagsThrDef;
1117 xmlSaveNoEmptyTagsThrDef = v;
1118 xmlMutexUnlock(&xmlThrDefMutex);
1119 return ret;
1120}
1121#endif
1122
1123int xmlThrDefKeepBlanksDefaultValue(int v) {
1124 int ret;
1125 xmlMutexLock(&xmlThrDefMutex);
1126 ret = xmlKeepBlanksDefaultValueThrDef;
1127 xmlKeepBlanksDefaultValueThrDef = v;
1128 xmlMutexUnlock(&xmlThrDefMutex);
1129 return ret;
1130}
1131
1132int xmlThrDefLineNumbersDefaultValue(int v) {
1133 int ret;
1134 xmlMutexLock(&xmlThrDefMutex);
1135 ret = xmlLineNumbersDefaultValueThrDef;
1136 xmlLineNumbersDefaultValueThrDef = v;
1137 xmlMutexUnlock(&xmlThrDefMutex);
1138 return ret;
1139}
1140
1141int xmlThrDefLoadExtDtdDefaultValue(int v) {
1142 int ret;
1143 xmlMutexLock(&xmlThrDefMutex);
1144 ret = xmlLoadExtDtdDefaultValueThrDef;
1145 xmlLoadExtDtdDefaultValueThrDef = v;
1146 xmlMutexUnlock(&xmlThrDefMutex);
1147 return ret;
1148}
1149
1150int xmlThrDefParserDebugEntities(int v ATTRIBUTE_UNUSED) {
1151 return(xmlParserDebugEntities);
1152}
1153
1154int xmlThrDefPedanticParserDefaultValue(int v) {
1155 int ret;
1156 xmlMutexLock(&xmlThrDefMutex);
1157 ret = xmlPedanticParserDefaultValueThrDef;
1158 xmlPedanticParserDefaultValueThrDef = v;
1159 xmlMutexUnlock(&xmlThrDefMutex);
1160 return ret;
1161}
1162
1163int xmlThrDefSubstituteEntitiesDefaultValue(int v) {
1164 int ret;
1165 xmlMutexLock(&xmlThrDefMutex);
1166 ret = xmlSubstituteEntitiesDefaultValueThrDef;
1167 xmlSubstituteEntitiesDefaultValueThrDef = v;
1168 xmlMutexUnlock(&xmlThrDefMutex);
1169 return ret;
1170}
1171
1172xmlRegisterNodeFunc
1173xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func)
1174{
1175 xmlRegisterNodeFunc old;
1176
1177 xmlMutexLock(&xmlThrDefMutex);
1178 old = xmlRegisterNodeDefaultValueThrDef;
1179
1180 __xmlRegisterCallbacks = 1;
1181 xmlRegisterNodeDefaultValueThrDef = func;
1182 xmlMutexUnlock(&xmlThrDefMutex);
1183
1184 return(old);
1185}
1186
1187xmlDeregisterNodeFunc
1188xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func)
1189{
1190 xmlDeregisterNodeFunc old;
1191
1192 xmlMutexLock(&xmlThrDefMutex);
1193 old = xmlDeregisterNodeDefaultValueThrDef;
1194
1195 __xmlRegisterCallbacks = 1;
1196 xmlDeregisterNodeDefaultValueThrDef = func;
1197 xmlMutexUnlock(&xmlThrDefMutex);
1198
1199 return(old);
1200}
1201
1202xmlParserInputBufferCreateFilenameFunc
1203xmlThrDefParserInputBufferCreateFilenameDefault(xmlParserInputBufferCreateFilenameFunc func)
1204{
1205 xmlParserInputBufferCreateFilenameFunc old;
1206
1207 xmlMutexLock(&xmlThrDefMutex);
1208 old = xmlParserInputBufferCreateFilenameValueThrDef;
1209 if (old == NULL) {
1210 old = __xmlParserInputBufferCreateFilename;
1211 }
1212
1213 xmlParserInputBufferCreateFilenameValueThrDef = func;
1214 xmlMutexUnlock(&xmlThrDefMutex);
1215
1216 return(old);
1217}
1218
1219xmlOutputBufferCreateFilenameFunc
1220xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func)
1221{
1222 xmlOutputBufferCreateFilenameFunc old;
1223
1224 xmlMutexLock(&xmlThrDefMutex);
1225 old = xmlOutputBufferCreateFilenameValueThrDef;
1226#ifdef LIBXML_OUTPUT_ENABLED
1227 if (old == NULL) {
1228 old = __xmlOutputBufferCreateFilename;
1229 }
1230#endif
1231 xmlOutputBufferCreateFilenameValueThrDef = func;
1232 xmlMutexUnlock(&xmlThrDefMutex);
1233
1234 return(old);
1235}
1236
1237/** DOC_ENABLE */
1238
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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