Merge branch develop-3.10 into develop-3.10-next
[firefly-linux-kernel-4.4.55.git] / tools / gator / daemon / mxml / mxml-private.c
1 /*
2  * "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $"
3  *
4  * Private functions for Mini-XML, a small XML-like file parsing library.
5  *
6  * Copyright 2003-2014 by Michael R Sweet.
7  *
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  *
14  *     http://www.msweet.org/projects.php/Mini-XML
15  */
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
55 void
56 mxml_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
97 mxml_type_t                             /* O - Node type */
98 mxml_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
110 mxml_type_t                             /* O - Node type */
111 mxml_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
123 mxml_type_t                             /* O - Node type */
124 mxml_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
136 mxml_type_t                             /* O - Node type */
137 mxml_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
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);
153
154
155 /*
156  * '_mxml_destructor()' - Free memory used for globals...
157  */
158
159 static 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
170 static 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
217 static 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
227 static DWORD _mxml_tls_index;           /* Index for global storage */
228
229
230 /*
231  * 'DllMain()' - Main entry for library.
232  */
233
234 BOOL WINAPI                             /* O - Success/failure */
235 DllMain(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
245   switch (reason)
246   {
247     case DLL_PROCESS_ATTACH :           /* Called on library initialization */
248         if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
249           return (FALSE);
250         break;
251
252     case DLL_THREAD_DETACH :            /* Called when a thread terminates */
253         if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
254           free(global);
255         break;
256
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
261         TlsFree(_mxml_tls_index);
262         break;
263
264     default:
265         break;
266   }
267
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
290     TlsSetValue(_mxml_tls_index, (LPVOID)global);
291   }
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 /*
322  * End of "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $".
323  */