2 * "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $"
4 * Private functions for Mini-XML, a small XML-like file parsing library.
6 * Copyright 2003-2014 by Michael R Sweet.
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:
14 * http://www.msweet.org/projects.php/Mini-XML
18 * Include necessary headers...
21 #include "mxml-private.h"
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.
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.
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.
38 #if defined(__sun) || defined(_AIX)
39 # pragma fini(_mxml_fini)
40 # define _MXML_FINI _mxml_fini
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
47 # define _MXML_FINI _fini
52 * 'mxml_error()' - Display an error message.
56 mxml_error(const char *format, /* I - Printf-style format string */
57 ...) /* I - Additional arguments as needed */
59 va_list ap; /* Pointer to arguments */
60 char s[1024]; /* Message string */
61 _mxml_global_t *global = _mxml_global();
66 * Range check input...
73 * Format the error message string...
78 vsnprintf(s, sizeof(s), format, ap);
83 * And then display the error message...
87 (*global->error_cb)(s);
89 fprintf(stderr, "mxml: %s\n", s);
94 * 'mxml_ignore_cb()' - Default callback for ignored values.
97 mxml_type_t /* O - Node type */
98 mxml_ignore_cb(mxml_node_t *node) /* I - Current node */
102 return (MXML_IGNORE);
107 * 'mxml_integer_cb()' - Default callback for integer values.
110 mxml_type_t /* O - Node type */
111 mxml_integer_cb(mxml_node_t *node) /* I - Current node */
115 return (MXML_INTEGER);
120 * 'mxml_opaque_cb()' - Default callback for opaque values.
123 mxml_type_t /* O - Node type */
124 mxml_opaque_cb(mxml_node_t *node) /* I - Current node */
128 return (MXML_OPAQUE);
133 * 'mxml_real_cb()' - Default callback for real number values.
136 mxml_type_t /* O - Node type */
137 mxml_real_cb(mxml_node_t *node) /* I - Current node */
145 #ifdef HAVE_PTHREAD_H /**** POSIX threading ****/
146 # include <pthread.h>
148 static pthread_key_t _mxml_key = -1; /* Thread local storage key */
149 static pthread_once_t _mxml_key_once = PTHREAD_ONCE_INIT;
150 /* One-time initialization object */
151 static void _mxml_init(void);
152 static void _mxml_destructor(void *g);
156 * '_mxml_destructor()' - Free memory used for globals...
160 _mxml_destructor(void *g) /* I - Global data */
167 * '_mxml_fini()' - Clean up when unloaded.
173 _mxml_global_t *global; /* Global data */
178 if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) != NULL)
179 _mxml_destructor(global);
181 pthread_key_delete(_mxml_key);
188 * '_mxml_global()' - Get global data.
191 _mxml_global_t * /* O - Global data */
194 _mxml_global_t *global; /* Global data */
197 pthread_once(&_mxml_key_once, _mxml_init);
199 if ((global = (_mxml_global_t *)pthread_getspecific(_mxml_key)) == NULL)
201 global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
202 pthread_setspecific(_mxml_key, global);
204 global->num_entity_cbs = 1;
205 global->entity_cbs[0] = _mxml_entity_cb;
214 * '_mxml_init()' - Initialize global data...
220 pthread_key_create(&_mxml_key, _mxml_destructor);
224 #elif defined(WIN32) && defined(MXML1_EXPORTS) /**** WIN32 threading ****/
225 # include <windows.h>
227 static DWORD _mxml_tls_index; /* Index for global storage */
231 * 'DllMain()' - Main entry for library.
234 BOOL WINAPI /* O - Success/failure */
235 DllMain(HINSTANCE hinst, /* I - DLL module handle */
236 DWORD reason, /* I - Reason */
237 LPVOID reserved) /* I - Unused */
239 _mxml_global_t *global; /* Global data */
247 case DLL_PROCESS_ATTACH : /* Called on library initialization */
248 if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
252 case DLL_THREAD_DETACH : /* Called when a thread terminates */
253 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
257 case DLL_PROCESS_DETACH : /* Called when library is unloaded */
258 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
261 TlsFree(_mxml_tls_index);
273 * '_mxml_global()' - Get global data.
276 _mxml_global_t * /* O - Global data */
279 _mxml_global_t *global; /* Global data */
282 if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) == NULL)
284 global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
286 global->num_entity_cbs = 1;
287 global->entity_cbs[0] = _mxml_entity_cb;
290 TlsSetValue(_mxml_tls_index, (LPVOID)global);
297 #else /**** No threading ****/
299 * '_mxml_global()' - Get global data.
302 _mxml_global_t * /* O - Global data */
305 static _mxml_global_t global = /* Global data */
308 1, /* num_entity_cbs */
309 { _mxml_entity_cb }, /* entity_cbs */
311 NULL, /* custom_load_cb */
312 NULL /* custom_save_cb */
318 #endif /* HAVE_PTHREAD_H */
322 * End of "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $".