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