Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2011 Canonical Limited
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public
8 : : * License as published by the Free Software Foundation; either
9 : : * version 2.1 of the License, or (at your option) any later version.
10 : : *
11 : : * This library is distributed in the hope that it will be useful, but
12 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 : : *
19 : : * Author: Ryan Lortie <desrt@desrt.ca>
20 : : */
21 : :
22 : : #include "config.h"
23 : :
24 : : #include "glib-init.h"
25 : : #include "glib-private.h"
26 : : #include "gmacros.h"
27 : : #include "gtypes.h"
28 : : #include "gutils.h" /* for GDebugKey */
29 : : #include "gconstructor.h"
30 : : #include "gconstructorprivate.h"
31 : : #include "gmem.h" /* for g_mem_gc_friendly */
32 : :
33 : : #include <string.h>
34 : : #include <stdlib.h>
35 : : #include <stdio.h>
36 : : #include <ctype.h>
37 : :
38 : : /* Deliberately not checking HAVE_STDINT_H here: we officially require a
39 : : * C99 toolchain, which implies <stdint.h>, int8_t and so on. If your
40 : : * toolchain does not have this, now would be a good time to upgrade. */
41 : : #include <stdint.h>
42 : :
43 : : /* This seems as good a place as any to make static assertions about platform
44 : : * assumptions we make throughout GLib. */
45 : :
46 : : /* Test that private macro G_SIGNEDNESS_OF() works as intended */
47 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (int) == 1);
48 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (unsigned int) == 0);
49 : :
50 : : /* We do not support 36-bit bytes or other historical curiosities. */
51 : : G_STATIC_ASSERT (CHAR_BIT == 8);
52 : :
53 : : /* We assume that data pointers are the same size as function pointers... */
54 : : G_STATIC_ASSERT (sizeof (gpointer) == sizeof (GFunc));
55 : : G_STATIC_ASSERT (G_ALIGNOF (gpointer) == G_ALIGNOF (GFunc));
56 : : /* ... and that all function pointers are the same size. */
57 : : G_STATIC_ASSERT (sizeof (GFunc) == sizeof (GCompareDataFunc));
58 : : G_STATIC_ASSERT (G_ALIGNOF (GFunc) == G_ALIGNOF (GCompareDataFunc));
59 : :
60 : : /* We assume that "small" enums (those where all values fit in INT32_MIN
61 : : * to INT32_MAX) are exactly int-sized. In particular, we assume that if
62 : : * an enum has no members that exceed the range of char/short, the
63 : : * compiler will make it int-sized anyway, so adding a member later that
64 : : * *does* exceed the range of char/short is not an ABI break. */
65 : : typedef enum {
66 : : TEST_CHAR_0 = 0
67 : : } TestChar;
68 : : typedef enum {
69 : : TEST_SHORT_0 = 0,
70 : : TEST_SHORT_256 = 256
71 : : } TestShort;
72 : : typedef enum {
73 : : TEST_INT32_MIN = G_MININT32,
74 : : TEST_INT32_MAX = G_MAXINT32
75 : : } TestInt;
76 : : G_STATIC_ASSERT (sizeof (TestChar) == sizeof (int));
77 : : G_STATIC_ASSERT (sizeof (TestShort) == sizeof (int));
78 : : G_STATIC_ASSERT (sizeof (TestInt) == sizeof (int));
79 : : G_STATIC_ASSERT (G_ALIGNOF (TestChar) == G_ALIGNOF (int));
80 : : G_STATIC_ASSERT (G_ALIGNOF (TestShort) == G_ALIGNOF (int));
81 : : G_STATIC_ASSERT (G_ALIGNOF (TestInt) == G_ALIGNOF (int));
82 : :
83 : : G_STATIC_ASSERT (sizeof (gchar) == 1);
84 : : G_STATIC_ASSERT (sizeof (guchar) == 1);
85 : :
86 : : /* It is platform-dependent whether gchar is signed or unsigned, so there
87 : : * is no assertion here for it */
88 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (guchar) == 0);
89 : :
90 : : G_STATIC_ASSERT (sizeof (gint8) * CHAR_BIT == 8);
91 : : G_STATIC_ASSERT (sizeof (guint8) * CHAR_BIT == 8);
92 : : G_STATIC_ASSERT (sizeof (gint16) * CHAR_BIT == 16);
93 : : G_STATIC_ASSERT (sizeof (guint16) * CHAR_BIT == 16);
94 : : G_STATIC_ASSERT (sizeof (gint32) * CHAR_BIT == 32);
95 : : G_STATIC_ASSERT (sizeof (guint32) * CHAR_BIT == 32);
96 : : G_STATIC_ASSERT (sizeof (gint64) * CHAR_BIT == 64);
97 : : G_STATIC_ASSERT (sizeof (guint64) * CHAR_BIT == 64);
98 : :
99 : : G_STATIC_ASSERT (sizeof (void *) == GLIB_SIZEOF_VOID_P);
100 : : G_STATIC_ASSERT (sizeof (gintptr) == sizeof (void *));
101 : : G_STATIC_ASSERT (sizeof (guintptr) == sizeof (void *));
102 : :
103 : : G_STATIC_ASSERT (sizeof (short) == sizeof (gshort));
104 : : G_STATIC_ASSERT (G_MINSHORT == SHRT_MIN);
105 : : G_STATIC_ASSERT (G_MAXSHORT == SHRT_MAX);
106 : : G_STATIC_ASSERT (sizeof (unsigned short) == sizeof (gushort));
107 : : G_STATIC_ASSERT (G_MAXUSHORT == USHRT_MAX);
108 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gshort) == 1);
109 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gushort) == 0);
110 : :
111 : : G_STATIC_ASSERT (sizeof (int) == sizeof (gint));
112 : : G_STATIC_ASSERT (G_MININT == INT_MIN);
113 : : G_STATIC_ASSERT (G_MAXINT == INT_MAX);
114 : : G_STATIC_ASSERT (sizeof (unsigned int) == sizeof (guint));
115 : : G_STATIC_ASSERT (G_MAXUINT == UINT_MAX);
116 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint) == 1);
117 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint) == 0);
118 : :
119 : : G_STATIC_ASSERT (sizeof (long) == GLIB_SIZEOF_LONG);
120 : : G_STATIC_ASSERT (sizeof (long) == sizeof (glong));
121 : : G_STATIC_ASSERT (G_MINLONG == LONG_MIN);
122 : : G_STATIC_ASSERT (G_MAXLONG == LONG_MAX);
123 : : G_STATIC_ASSERT (sizeof (unsigned long) == sizeof (gulong));
124 : : G_STATIC_ASSERT (G_MAXULONG == ULONG_MAX);
125 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (glong) == 1);
126 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gulong) == 0);
127 : :
128 : : G_STATIC_ASSERT (G_HAVE_GINT64 == 1);
129 : :
130 : : G_STATIC_ASSERT (sizeof (size_t) == GLIB_SIZEOF_SIZE_T);
131 : : /* Not a typo: ssize_t is POSIX, not Standard C, but if it exists then
132 : : * it's the same size as size_t. */
133 : : G_STATIC_ASSERT (sizeof (size_t) == GLIB_SIZEOF_SSIZE_T);
134 : : G_STATIC_ASSERT (sizeof (gsize) == GLIB_SIZEOF_SSIZE_T);
135 : : G_STATIC_ASSERT (sizeof (gsize) == sizeof (size_t));
136 : : G_STATIC_ASSERT (G_MAXSIZE == SIZE_MAX);
137 : : /* Again this is size_t not ssize_t, because ssize_t is POSIX, not C99 */
138 : : G_STATIC_ASSERT (sizeof (gssize) == sizeof (size_t));
139 : : G_STATIC_ASSERT (G_ALIGNOF (gsize) == G_ALIGNOF (size_t));
140 : : G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (size_t));
141 : : /* We assume that GSIZE_TO_POINTER is reversible by GPOINTER_TO_SIZE
142 : : * without losing information.
143 : : * However, we do not assume that GPOINTER_TO_SIZE can store an arbitrary
144 : : * pointer in a gsize (known to be false on CHERI). */
145 : : G_STATIC_ASSERT (sizeof (size_t) <= sizeof (void *));
146 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (size_t) == 0);
147 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gsize) == 0);
148 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gssize) == 1);
149 : :
150 : : /* Standard C does not guarantee that size_t is the same as uintptr_t,
151 : : * but GLib currently assumes they are the same: see
152 : : * <https://gitlab.gnome.org/GNOME/glib/-/issues/2842>.
153 : : *
154 : : * To enable working on bringup for new architectures these assertions
155 : : * can be disabled with -DG_ENABLE_EXPERIMENTAL_ABI_COMPILATION.
156 : : *
157 : : * FIXME: remove these assertions once the API/ABI has stabilized. */
158 : : #ifndef G_ENABLE_EXPERIMENTAL_ABI_COMPILATION
159 : : G_STATIC_ASSERT (sizeof (size_t) == sizeof (uintptr_t));
160 : : G_STATIC_ASSERT (G_ALIGNOF (size_t) == G_ALIGNOF (uintptr_t));
161 : : #endif
162 : :
163 : : /* goffset is always 64-bit, even if off_t is only 32-bit
164 : : * (compiling without large-file-support on 32-bit) */
165 : : G_STATIC_ASSERT (sizeof (goffset) == sizeof (gint64));
166 : : G_STATIC_ASSERT (G_ALIGNOF (goffset) == G_ALIGNOF (gint64));
167 : : /* goffset is always signed */
168 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (goffset) == 1);
169 : :
170 : : G_STATIC_ASSERT (sizeof (gfloat) == sizeof (float));
171 : : G_STATIC_ASSERT (G_ALIGNOF (gfloat) == G_ALIGNOF (float));
172 : : G_STATIC_ASSERT (sizeof (gdouble) == sizeof (double));
173 : : G_STATIC_ASSERT (G_ALIGNOF (gdouble) == G_ALIGNOF (double));
174 : :
175 : : G_STATIC_ASSERT (sizeof (gintptr) == sizeof (intptr_t));
176 : : G_STATIC_ASSERT (sizeof (guintptr) == sizeof (uintptr_t));
177 : : G_STATIC_ASSERT (G_ALIGNOF (gintptr) == G_ALIGNOF (intptr_t));
178 : : G_STATIC_ASSERT (G_ALIGNOF (guintptr) == G_ALIGNOF (uintptr_t));
179 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gintptr) == 1);
180 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (guintptr) == 0);
181 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (intptr_t) == 1);
182 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (uintptr_t) == 0);
183 : :
184 : : G_STATIC_ASSERT (sizeof (gint8) == sizeof (int8_t));
185 : : G_STATIC_ASSERT (sizeof (guint8) == sizeof (uint8_t));
186 : : G_STATIC_ASSERT (G_ALIGNOF (gint8) == G_ALIGNOF (int8_t));
187 : : G_STATIC_ASSERT (G_ALIGNOF (guint8) == G_ALIGNOF (uint8_t));
188 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint8) == 1);
189 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint8) == 0);
190 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (int8_t) == 1);
191 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint8_t) == 0);
192 : :
193 : : G_STATIC_ASSERT (sizeof (gint16) == sizeof (int16_t));
194 : : G_STATIC_ASSERT (sizeof (guint16) == sizeof (uint16_t));
195 : : G_STATIC_ASSERT (G_ALIGNOF (gint16) == G_ALIGNOF (int16_t));
196 : : G_STATIC_ASSERT (G_ALIGNOF (guint16) == G_ALIGNOF (uint16_t));
197 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (int16_t) == 1);
198 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint16_t) == 0);
199 : :
200 : : G_STATIC_ASSERT (sizeof (gint32) == sizeof (int32_t));
201 : : G_STATIC_ASSERT (sizeof (guint32) == sizeof (uint32_t));
202 : : G_STATIC_ASSERT (G_ALIGNOF (gint32) == G_ALIGNOF (int32_t));
203 : : G_STATIC_ASSERT (G_ALIGNOF (guint32) == G_ALIGNOF (uint32_t));
204 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint32) == 1);
205 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint32) == 0);
206 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (int32_t) == 1);
207 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint32_t) == 0);
208 : :
209 : : G_STATIC_ASSERT (sizeof (gint64) == sizeof (int64_t));
210 : : G_STATIC_ASSERT (sizeof (guint64) == sizeof (uint64_t));
211 : : G_STATIC_ASSERT (G_ALIGNOF (gint64) == G_ALIGNOF (int64_t));
212 : : G_STATIC_ASSERT (G_ALIGNOF (guint64) == G_ALIGNOF (uint64_t));
213 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (gint64) == 1);
214 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (guint64) == 0);
215 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (int64_t) == 1);
216 : : G_STATIC_ASSERT (G_SIGNEDNESS_OF (uint64_t) == 0);
217 : :
218 : : /* C11 §6.7, item 3 allows us to rely on this being allowed */
219 : : typedef struct Foo Foo;
220 : : typedef struct Foo Foo;
221 : :
222 : : /**
223 : : * g_mem_gc_friendly:
224 : : *
225 : : * This variable is %TRUE if the `G_DEBUG` environment variable
226 : : * includes the key `gc-friendly`.
227 : : */
228 : : gboolean g_mem_gc_friendly = FALSE;
229 : :
230 : : GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING |
231 : : G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
232 : : GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
233 : :
234 : : static gboolean
235 : 4604 : debug_key_matches (const gchar *key,
236 : : const gchar *token,
237 : : guint length)
238 : : {
239 : : /* may not call GLib functions: see note in g_parse_debug_string() */
240 : 16574 : for (; length; length--, key++, token++)
241 : : {
242 : 15396 : char k = (*key == '_') ? '-' : tolower (*key );
243 : 15396 : char t = (*token == '_') ? '-' : tolower (*token);
244 : :
245 : 15396 : if (k != t)
246 : 3426 : return FALSE;
247 : : }
248 : :
249 : 1178 : return *key == '\0';
250 : : }
251 : :
252 : : /* The GVariant documentation indirectly says that int is at least 32 bits
253 : : * (by saying that b, y, n, q, i, u, h are promoted to int). On any
254 : : * reasonable platform, int is in fact *exactly* 32 bits long, because
255 : : * otherwise, {signed char, short, int} wouldn't be sufficient to provide
256 : : * {int8_t, int16_t, int32_t}. */
257 : : G_STATIC_ASSERT (sizeof (int) == sizeof (gint32));
258 : :
259 : : /**
260 : : * g_parse_debug_string:
261 : : * @string: (nullable): a list of debug options separated by colons, spaces, or
262 : : * commas, or %NULL.
263 : : * @keys: (array length=nkeys): pointer to an array of #GDebugKey which associate
264 : : * strings with bit flags.
265 : : * @nkeys: the number of #GDebugKeys in the array.
266 : : *
267 : : * Parses a string containing debugging options
268 : : * into a %guint containing bit flags. This is used
269 : : * within GDK and GTK to parse the debug options passed on the
270 : : * command line or through environment variables.
271 : : *
272 : : * If @string is equal to "all", all flags are set. Any flags
273 : : * specified along with "all" in @string are inverted; thus,
274 : : * "all,foo,bar" or "foo,bar,all" sets all flags except those
275 : : * corresponding to "foo" and "bar".
276 : : *
277 : : * If @string is equal to "help", all the available keys in @keys
278 : : * are printed out to standard error.
279 : : *
280 : : * Returns: the combined set of bit flags.
281 : : */
282 : : guint
283 : 1087 : g_parse_debug_string (const gchar *string,
284 : : const GDebugKey *keys,
285 : : guint nkeys)
286 : : {
287 : : guint i;
288 : 1087 : guint result = 0;
289 : :
290 : 1087 : if (string == NULL)
291 : 10 : return 0;
292 : :
293 : : /* this function is used during the initialisation of gmessages, gmem
294 : : * and gslice, so it may not do anything that causes memory to be
295 : : * allocated or risks messages being emitted.
296 : : *
297 : : * this means, more or less, that this code may not call anything
298 : : * inside GLib.
299 : : */
300 : :
301 : 1077 : if (!strcasecmp (string, "help"))
302 : : {
303 : : /* using stdio directly for the reason stated above */
304 : 5 : fprintf (stderr, "Supported debug values:");
305 : 20 : for (i = 0; i < nkeys; i++)
306 : 15 : fprintf (stderr, " %s", keys[i].key);
307 : 5 : fprintf (stderr, " all help\n");
308 : : }
309 : : else
310 : : {
311 : 1072 : const gchar *p = string;
312 : : const gchar *q;
313 : 1072 : gboolean invert = FALSE;
314 : :
315 : 2234 : while (*p)
316 : : {
317 : 1162 : q = strpbrk (p, ":;, \t");
318 : 1162 : if (!q)
319 : 1072 : q = p + strlen (p);
320 : :
321 : 1162 : if (debug_key_matches ("all", p, q - p))
322 : : {
323 : 10 : invert = TRUE;
324 : : }
325 : : else
326 : : {
327 : 4594 : for (i = 0; i < nkeys; i++)
328 : 3442 : if (debug_key_matches (keys[i].key, p, q - p))
329 : 1088 : result |= keys[i].value;
330 : : }
331 : :
332 : 1162 : p = q;
333 : 1162 : if (*p)
334 : 90 : p++;
335 : : }
336 : :
337 : 1072 : if (invert)
338 : : {
339 : 10 : guint all_flags = 0;
340 : :
341 : 40 : for (i = 0; i < nkeys; i++)
342 : 30 : all_flags |= keys[i].value;
343 : :
344 : 10 : result = all_flags & (~result);
345 : : }
346 : : }
347 : :
348 : 1077 : return result;
349 : : }
350 : :
351 : : static guint
352 : 2194 : g_parse_debug_envvar (const gchar *envvar,
353 : : const GDebugKey *keys,
354 : : gint n_keys,
355 : : guint default_value)
356 : : {
357 : : const gchar *value;
358 : :
359 : : #ifdef OS_WIN32
360 : : /* "fatal-warnings,fatal-criticals,all,help" is pretty short */
361 : : gchar buffer[100];
362 : :
363 : : if (GetEnvironmentVariable (envvar, buffer, 100) < 100)
364 : : value = buffer;
365 : : else
366 : : return 0;
367 : : #else
368 : 2194 : value = getenv (envvar);
369 : : #endif
370 : :
371 : 2194 : if (value == NULL)
372 : 1206 : return default_value;
373 : :
374 : 988 : return g_parse_debug_string (value, keys, n_keys);
375 : : }
376 : :
377 : : static void
378 : 1097 : g_messages_prefixed_init (void)
379 : : {
380 : 1097 : const GDebugKey keys[] = {
381 : : { "error", G_LOG_LEVEL_ERROR },
382 : : { "critical", G_LOG_LEVEL_CRITICAL },
383 : : { "warning", G_LOG_LEVEL_WARNING },
384 : : { "message", G_LOG_LEVEL_MESSAGE },
385 : : { "info", G_LOG_LEVEL_INFO },
386 : : { "debug", G_LOG_LEVEL_DEBUG }
387 : : };
388 : :
389 : 1097 : g_log_msg_prefix = g_parse_debug_envvar ("G_MESSAGES_PREFIXED", keys, G_N_ELEMENTS (keys), g_log_msg_prefix);
390 : 1097 : }
391 : :
392 : : static void
393 : 1097 : g_debug_init (void)
394 : : {
395 : 1097 : const GDebugKey keys[] = {
396 : : { "gc-friendly", 1 },
397 : : {"fatal-warnings", G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL },
398 : : {"fatal-criticals", G_LOG_LEVEL_CRITICAL }
399 : : };
400 : : GLogLevelFlags flags;
401 : :
402 : 1097 : flags = g_parse_debug_envvar ("G_DEBUG", keys, G_N_ELEMENTS (keys), 0);
403 : :
404 : 1097 : g_log_always_fatal |= flags & G_LOG_LEVEL_MASK;
405 : :
406 : 1097 : g_mem_gc_friendly = flags & 1;
407 : 1097 : }
408 : :
409 : : void
410 : 1642 : glib_init (void)
411 : : {
412 : : static gboolean glib_inited;
413 : :
414 : 1642 : if (glib_inited)
415 : 545 : return;
416 : :
417 : 1097 : glib_inited = TRUE;
418 : :
419 : 1097 : g_messages_prefixed_init ();
420 : 1097 : g_debug_init ();
421 : 1097 : g_quark_init ();
422 : 1097 : g_error_init ();
423 : : }
424 : :
425 : : #ifdef G_PLATFORM_WIN32
426 : :
427 : : HMODULE glib_dll = NULL;
428 : : void glib_win32_init (void);
429 : :
430 : : void
431 : : glib_win32_init (void)
432 : : {
433 : : /* May be called more than once in static compilation mode */
434 : : static gboolean win32_already_init = FALSE;
435 : : if (!win32_already_init)
436 : : {
437 : : win32_already_init = TRUE;
438 : :
439 : : g_crash_handler_win32_init ();
440 : : #ifdef THREADS_WIN32
441 : : g_thread_win32_init ();
442 : : #endif
443 : :
444 : : g_clock_win32_init ();
445 : : glib_init ();
446 : : /* must go after glib_init */
447 : : g_console_win32_init ();
448 : : }
449 : : }
450 : :
451 : : static void
452 : : glib_win32_deinit (gboolean detach_thread)
453 : : {
454 : : #ifdef THREADS_WIN32
455 : : if (detach_thread)
456 : : g_thread_win32_process_detach ();
457 : : #endif
458 : : g_crash_handler_win32_deinit ();
459 : : }
460 : :
461 : : #ifndef GLIB_STATIC_COMPILATION
462 : :
463 : : BOOL WINAPI DllMain (HINSTANCE hinstDLL,
464 : : DWORD fdwReason,
465 : : LPVOID lpvReserved);
466 : :
467 : : BOOL WINAPI
468 : : DllMain (HINSTANCE hinstDLL,
469 : : DWORD fdwReason,
470 : : LPVOID lpvReserved)
471 : : {
472 : : switch (fdwReason)
473 : : {
474 : : case DLL_PROCESS_ATTACH:
475 : : glib_dll = hinstDLL;
476 : : glib_win32_init ();
477 : : break;
478 : :
479 : : case DLL_THREAD_DETACH:
480 : : #ifdef THREADS_WIN32
481 : : g_thread_win32_thread_detach ();
482 : : #endif
483 : : break;
484 : :
485 : : case DLL_PROCESS_DETACH:
486 : : glib_win32_deinit (lpvReserved == NULL);
487 : : break;
488 : :
489 : : default:
490 : : /* do nothing */
491 : : ;
492 : : }
493 : :
494 : : return TRUE;
495 : : }
496 : :
497 : : #else
498 : :
499 : : #ifndef G_HAS_CONSTRUCTORS
500 : : #error static compilation on Windows requires constructor support
501 : : #endif
502 : :
503 : : #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
504 : : #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_priv_constructor)
505 : : #endif
506 : :
507 : : static gboolean tls_callback_invoked;
508 : :
509 : : G_DEFINE_CONSTRUCTOR (glib_priv_constructor)
510 : :
511 : : static void
512 : : glib_priv_constructor (void)
513 : : {
514 : : glib_win32_init ();
515 : :
516 : : if (!tls_callback_invoked)
517 : : g_critical ("TLS callback not invoked");
518 : : }
519 : :
520 : : #ifndef G_HAS_TLS_CALLBACKS
521 : : #error static compilation on Windows requires TLS callbacks support
522 : : #endif
523 : :
524 : : G_DEFINE_TLS_CALLBACK (glib_priv_tls_callback)
525 : :
526 : : static void NTAPI
527 : : glib_priv_tls_callback (LPVOID hinstance,
528 : : DWORD reason,
529 : : LPVOID reserved)
530 : : {
531 : : switch (reason)
532 : : {
533 : : case DLL_PROCESS_ATTACH:
534 : : glib_dll = hinstance;
535 : : tls_callback_invoked = TRUE;
536 : : break;
537 : : case DLL_THREAD_DETACH:
538 : : #ifdef THREADS_WIN32
539 : : g_thread_win32_thread_detach ();
540 : : #endif
541 : : break;
542 : : case DLL_PROCESS_DETACH:
543 : : glib_win32_deinit (reserved == NULL);
544 : : break;
545 : :
546 : : default:
547 : : break;
548 : : }
549 : : }
550 : :
551 : : #endif /* GLIB_STATIC_COMPILATION */
552 : :
553 : : #elif defined(G_HAS_CONSTRUCTORS) /* && !G_PLATFORM_WIN32 */
554 : :
555 : : #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
556 : : #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_init_ctor)
557 : : #endif
558 : : G_DEFINE_CONSTRUCTOR(glib_init_ctor)
559 : :
560 : : static void
561 : 1097 : glib_init_ctor (void)
562 : : {
563 : 1097 : glib_init ();
564 : 1097 : }
565 : :
566 : : #else /* !G_PLATFORM_WIN32 && !G_HAS_CONSTRUCTORS */
567 : : # error Your platform/compiler is missing constructor support
568 : : #endif /* G_PLATFORM_WIN32 */
|