Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

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