blob: bec4bbfbf37868f5bcc7c6fd307c30ff81b8c032 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/*
Jon Medhurst96b56152014-10-30 18:01:15 +00002 * "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $"
Jon Medhurstaaf37a32013-06-11 12:10:56 +01003 *
4 * Private functions for Mini-XML, a small XML-like file parsing library.
5 *
Jon Medhurst96b56152014-10-30 18:01:15 +00006 * Copyright 2003-2014 by Michael R Sweet.
Jon Medhurstaaf37a32013-06-11 12:10:56 +01007 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
Jon Medhurst96b56152014-10-30 18:01:15 +000014 * http://www.msweet.org/projects.php/Mini-XML
Jon Medhurstaaf37a32013-06-11 12:10:56 +010015 */
16
17/*
18 * Include necessary headers...
19 */
20
21#include "mxml-private.h"
22
23
24/*
25 * Some crazy people think that unloading a shared object is a good or safe
26 * thing to do. Unfortunately, most objects are simply *not* safe to unload
27 * and bad things *will* happen.
28 *
29 * The following mess of conditional code allows us to provide a destructor
30 * function in Mini-XML for our thread-global storage so that it can possibly
31 * be unloaded safely, although since there is no standard way to do so I
32 * can't even provide any guarantees that you can do it safely on all platforms.
33 *
34 * This code currently supports AIX, HP-UX, Linux, Mac OS X, Solaris, and
35 * Windows. It might work on the BSDs and IRIX, but I haven't tested that.
36 */
37
38#if defined(__sun) || defined(_AIX)
39# pragma fini(_mxml_fini)
40# define _MXML_FINI _mxml_fini
41#elif defined(__hpux)
42# pragma FINI _mxml_fini
43# define _MXML_FINI _mxml_fini
44#elif defined(__GNUC__) /* Linux and Mac OS X */
45# define _MXML_FINI __attribute((destructor)) _mxml_fini
46#else
47# define _MXML_FINI _fini
48#endif /* __sun */
49
50
51/*
52 * 'mxml_error()' - Display an error message.
53 */
54
55void
56mxml_error(const char *format, /* I - Printf-style format string */
57 ...) /* I - Additional arguments as needed */
58{
59 va_list ap; /* Pointer to arguments */
60 char s[1024]; /* Message string */
61 _mxml_global_t *global = _mxml_global();
62 /* Global data */
63
64
65 /*
66 * Range check input...
67 */
68
69 if (!format)
70 return;
71
72 /*
73 * Format the error message string...
74 */
75
76 va_start(ap, format);
77
78 vsnprintf(s, sizeof(s), format, ap);
79
80 va_end(ap);
81
82 /*
83 * And then display the error message...
84 */
85
86 if (global->error_cb)
87 (*global->error_cb)(s);
88 else
89 fprintf(stderr, "mxml: %s\n", s);
90}
91
92
93/*
94 * 'mxml_ignore_cb()' - Default callback for ignored values.
95 */
96
97mxml_type_t /* O - Node type */
98mxml_ignore_cb(mxml_node_t *node) /* I - Current node */
99{
100 (void)node;
101
102 return (MXML_IGNORE);
103}
104
105
106/*
107 * 'mxml_integer_cb()' - Default callback for integer values.
108 */
109
110mxml_type_t /* O - Node type */
111mxml_integer_cb(mxml_node_t *node) /* I - Current node */
112{
113 (void)node;
114
115 return (MXML_INTEGER);
116}
117
118
119/*
120 * 'mxml_opaque_cb()' - Default callback for opaque values.
121 */
122
123mxml_type_t /* O - Node type */
124mxml_opaque_cb(mxml_node_t *node) /* I - Current node */
125{
126 (void)node;
127
128 return (MXML_OPAQUE);
129}
130
131
132/*
133 * 'mxml_real_cb()' - Default callback for real number values.
134 */
135
136mxml_type_t /* O - Node type */
137mxml_real_cb(mxml_node_t *node) /* I - Current node */
138{
139 (void)node;
140
141 return (MXML_REAL);
142}
143
144
145#ifdef HAVE_PTHREAD_H /**** POSIX threading ****/
146# include <pthread.h>
147
148static pthread_key_t _mxml_key = -1; /* Thread local storage key */
149static pthread_once_t _mxml_key_once = PTHREAD_ONCE_INIT;
150 /* One-time initialization object */
151static void _mxml_init(void);
152static void _mxml_destructor(void *g);
153
154
155/*
156 * '_mxml_destructor()' - Free memory used for globals...
157 */
158
159static void
160_mxml_destructor(void *g) /* I - Global data */
161{
162 free(g);
163}
164
165
166/*
167 * '_mxml_fini()' - Clean up when unloaded.
168 */
169
170static void
171_MXML_FINI(void)
172{
173 _mxml_global_t *global; /* Global data */
174
175
176 if (_mxml_key != -1)
177 {
178 if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) != NULL)
179 _mxml_destructor(global);
180
181 pthread_key_delete(_mxml_key);
182 _mxml_key = -1;
183 }
184}
185
186
187/*
188 * '_mxml_global()' - Get global data.
189 */
190
191_mxml_global_t * /* O - Global data */
192_mxml_global(void)
193{
194 _mxml_global_t *global; /* Global data */
195
196
197 pthread_once(&_mxml_key_once, _mxml_init);
198
199 if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) == NULL)
200 {
201 global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
202 pthread_setspecific(_mxml_key, global);
203
204 global->num_entity_cbs = 1;
205 global->entity_cbs[0] = _mxml_entity_cb;
206 global->wrap = 72;
207 }
208
209 return (global);
210}
211
212
213/*
214 * '_mxml_init()' - Initialize global data...
215 */
216
217static void
218_mxml_init(void)
219{
220 pthread_key_create(&_mxml_key, _mxml_destructor);
221}
222
223
224#elif defined(WIN32) && defined(MXML1_EXPORTS) /**** WIN32 threading ****/
225# include <windows.h>
226
227static DWORD _mxml_tls_index; /* Index for global storage */
228
229
230/*
231 * 'DllMain()' - Main entry for library.
232 */
Jon Medhurst96b56152014-10-30 18:01:15 +0000233
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100234BOOL WINAPI /* O - Success/failure */
235DllMain(HINSTANCE hinst, /* I - DLL module handle */
236 DWORD reason, /* I - Reason */
237 LPVOID reserved) /* I - Unused */
238{
239 _mxml_global_t *global; /* Global data */
240
241
242 (void)hinst;
243 (void)reserved;
244
Jon Medhurst96b56152014-10-30 18:01:15 +0000245 switch (reason)
246 {
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100247 case DLL_PROCESS_ATTACH : /* Called on library initialization */
Jon Medhurst96b56152014-10-30 18:01:15 +0000248 if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
249 return (FALSE);
250 break;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100251
252 case DLL_THREAD_DETACH : /* Called when a thread terminates */
253 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
254 free(global);
Jon Medhurst96b56152014-10-30 18:01:15 +0000255 break;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100256
257 case DLL_PROCESS_DETACH : /* Called when library is unloaded */
258 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
259 free(global);
260
Jon Medhurst96b56152014-10-30 18:01:15 +0000261 TlsFree(_mxml_tls_index);
262 break;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100263
Jon Medhurst96b56152014-10-30 18:01:15 +0000264 default:
265 break;
266 }
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100267
268 return (TRUE);
269}
270
271
272/*
273 * '_mxml_global()' - Get global data.
274 */
275
276_mxml_global_t * /* O - Global data */
277_mxml_global(void)
278{
279 _mxml_global_t *global; /* Global data */
280
281
282 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) == NULL)
283 {
284 global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
285
286 global->num_entity_cbs = 1;
287 global->entity_cbs[0] = _mxml_entity_cb;
288 global->wrap = 72;
289
Jon Medhurst96b56152014-10-30 18:01:15 +0000290 TlsSetValue(_mxml_tls_index, (LPVOID)global);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100291 }
292
293 return (global);
294}
295
296
297#else /**** No threading ****/
298/*
299 * '_mxml_global()' - Get global data.
300 */
301
302_mxml_global_t * /* O - Global data */
303_mxml_global(void)
304{
305 static _mxml_global_t global = /* Global data */
306 {
307 NULL, /* error_cb */
308 1, /* num_entity_cbs */
309 { _mxml_entity_cb }, /* entity_cbs */
310 72, /* wrap */
311 NULL, /* custom_load_cb */
312 NULL /* custom_save_cb */
313 };
314
315
316 return (&global);
317}
318#endif /* HAVE_PTHREAD_H */
319
320
321/*
Jon Medhurst96b56152014-10-30 18:01:15 +0000322 * End of "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $".
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100323 */