1 /*
2 * Copyright © 2011 Canonical Limited
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Author: Ryan Lortie <desrt@desrt.ca>
18 */
19
20 #include "config.h"
21
22 #include "glib-init.h"
23 #include "gmacros.h"
24 #include "gtypes.h"
25 #include "gutils.h" /* for GDebugKey */
26 #include "gconstructor.h"
27 #include "gmem.h" /* for g_mem_gc_friendly */
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <ctype.h>
33
34 /* Deliberately not checking HAVE_STDINT_H here: we officially require a
35 * C99 toolchain, which implies <stdint.h>, int8_t and so on. If your
36 * toolchain does not have this, now would be a good time to upgrade. */
37 #include <stdint.h>
38
39 /* This seems as good a place as any to make static assertions about platform
40 * assumptions we make throughout GLib. */
41
42 /* We do not support 36-bit bytes or other historical curiosities. */
43 G_STATIC_ASSERT (CHAR_BIT == 8);
44
45 /* We assume that data pointers are the same size as function pointers... */
46 G_STATIC_ASSERT (sizeof (gpointer) == sizeof (GFunc));
47 G_STATIC_ASSERT (G_ALIGNOF (gpointer) == G_ALIGNOF (GFunc));
48 /* ... and that all function pointers are the same size. */
49 G_STATIC_ASSERT (sizeof (GFunc) == sizeof (GCompareDataFunc));
50 G_STATIC_ASSERT (G_ALIGNOF (GFunc) == G_ALIGNOF (GCompareDataFunc));
51
52 /* We assume that "small" enums (those where all values fit in INT32_MIN
53 * to INT32_MAX) are exactly int-sized. In particular, we assume that if
54 * an enum has no members that exceed the range of char/short, the
55 * compiler will make it int-sized anyway, so adding a member later that
56 * *does* exceed the range of char/short is not an ABI break. */
57 typedef enum {
58 TEST_CHAR_0 = 0
59 } TestChar;
60 typedef enum {
61 TEST_SHORT_0 = 0,
62 TEST_SHORT_256 = 256
63 } TestShort;
64 typedef enum {
65 TEST_INT32_MIN = G_MININT32,
66 TEST_INT32_MAX = G_MAXINT32
67 } TestInt;
68 G_STATIC_ASSERT (sizeof (TestChar) == sizeof (int));
69 G_STATIC_ASSERT (sizeof (TestShort) == sizeof (int));
70 G_STATIC_ASSERT (sizeof (TestInt) == sizeof (int));
71 G_STATIC_ASSERT (G_ALIGNOF (TestChar) == G_ALIGNOF (int));
72 G_STATIC_ASSERT (G_ALIGNOF (TestShort) == G_ALIGNOF (int));
73 G_STATIC_ASSERT (G_ALIGNOF (TestInt) == G_ALIGNOF (int));
74
75 G_STATIC_ASSERT (sizeof (gchar) == 1);
76 G_STATIC_ASSERT (sizeof (guchar) == 1);
77 G_STATIC_ASSERT (sizeof (gint8) * CHAR_BIT == 8);
78 G_STATIC_ASSERT (sizeof (guint8) * CHAR_BIT == 8);
79 G_STATIC_ASSERT (sizeof (gint16) * CHAR_BIT == 16);
80 G_STATIC_ASSERT (sizeof (guint16) * CHAR_BIT == 16);
81 G_STATIC_ASSERT (sizeof (gint32) * CHAR_BIT == 32);
82 G_STATIC_ASSERT (sizeof (guint32) * CHAR_BIT == 32);
83 G_STATIC_ASSERT (sizeof (gint64) * CHAR_BIT == 64);
84 G_STATIC_ASSERT (sizeof (guint64) * CHAR_BIT == 64);
85
86 G_STATIC_ASSERT (sizeof (void *) == GLIB_SIZEOF_VOID_P);
87 G_STATIC_ASSERT (sizeof (gintptr) == sizeof (void *));
88 G_STATIC_ASSERT (sizeof (guintptr) == sizeof (void *));
89
90 G_STATIC_ASSERT (sizeof (long) == GLIB_SIZEOF_LONG);
91
92 G_STATIC_ASSERT (G_HAVE_GINT64 == 1);
93
94 G_STATIC_ASSERT (sizeof (size_t) == GLIB_SIZEOF_SIZE_T);
95 /* Not a typo: ssize_t is POSIX, not Standard C, but if it exists then
96 * it's the same size as size_t. */
97 G_STATIC_ASSERT (sizeof (size_t) == GLIB_SIZEOF_SSIZE_T);
98 G_STATIC_ASSERT (sizeof (gsize) == GLIB_SIZEOF_SSIZE_T);
99 G_STATIC_ASSERT (sizeof (gsize) == sizeof (size_t));
100 /* Again this is size_t not ssize_t, because ssize_t is POSIX, not C99 */
101 G_STATIC_ASSERT (sizeof (gssize) == sizeof (size_t));
102 G_STATIC_ASSERT (G_ALIGNOF (gsize) == G_ALIGNOF (size_t));
103 G_STATIC_ASSERT (G_ALIGNOF (gssize) == G_ALIGNOF (size_t));
104
105 /* goffset is always 64-bit, even if off_t is only 32-bit
106 * (compiling without large-file-support on 32-bit) */
107 G_STATIC_ASSERT (sizeof (goffset) == sizeof (gint64));
108 G_STATIC_ASSERT (G_ALIGNOF (goffset) == G_ALIGNOF (gint64));
109
110 G_STATIC_ASSERT (sizeof (gfloat) == sizeof (float));
111 G_STATIC_ASSERT (G_ALIGNOF (gfloat) == G_ALIGNOF (float));
112 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (double));
113 G_STATIC_ASSERT (G_ALIGNOF (gdouble) == G_ALIGNOF (double));
114
115 G_STATIC_ASSERT (sizeof (gintptr) == sizeof (intptr_t));
116 G_STATIC_ASSERT (sizeof (guintptr) == sizeof (uintptr_t));
117 G_STATIC_ASSERT (G_ALIGNOF (gintptr) == G_ALIGNOF (intptr_t));
118 G_STATIC_ASSERT (G_ALIGNOF (guintptr) == G_ALIGNOF (uintptr_t));
119
120 G_STATIC_ASSERT (sizeof (gint8) == sizeof (int8_t));
121 G_STATIC_ASSERT (sizeof (guint8) == sizeof (uint8_t));
122 G_STATIC_ASSERT (G_ALIGNOF (gint8) == G_ALIGNOF (int8_t));
123 G_STATIC_ASSERT (G_ALIGNOF (guint8) == G_ALIGNOF (uint8_t));
124
125 G_STATIC_ASSERT (sizeof (gint16) == sizeof (int16_t));
126 G_STATIC_ASSERT (sizeof (guint16) == sizeof (uint16_t));
127 G_STATIC_ASSERT (G_ALIGNOF (gint16) == G_ALIGNOF (int16_t));
128 G_STATIC_ASSERT (G_ALIGNOF (guint16) == G_ALIGNOF (uint16_t));
129
130 G_STATIC_ASSERT (sizeof (gint32) == sizeof (int32_t));
131 G_STATIC_ASSERT (sizeof (guint32) == sizeof (uint32_t));
132 G_STATIC_ASSERT (G_ALIGNOF (gint32) == G_ALIGNOF (int32_t));
133 G_STATIC_ASSERT (G_ALIGNOF (guint32) == G_ALIGNOF (uint32_t));
134
135 G_STATIC_ASSERT (sizeof (gint64) == sizeof (int64_t));
136 G_STATIC_ASSERT (sizeof (guint64) == sizeof (uint64_t));
137 G_STATIC_ASSERT (G_ALIGNOF (gint64) == G_ALIGNOF (int64_t));
138 G_STATIC_ASSERT (G_ALIGNOF (guint64) == G_ALIGNOF (uint64_t));
139
140 /**
141 * g_mem_gc_friendly:
142 *
143 * This variable is %TRUE if the `G_DEBUG` environment variable
144 * includes the key `gc-friendly`.
145 */
146 gboolean g_mem_gc_friendly = FALSE;
147
148 GLogLevelFlags g_log_msg_prefix = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING |
149 G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_DEBUG;
150 GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
151
152 static gboolean
debug_key_matches(const gchar * key,const gchar * token,guint length)153 debug_key_matches (const gchar *key,
154 const gchar *token,
155 guint length)
156 {
157 /* may not call GLib functions: see note in g_parse_debug_string() */
158 for (; length; length--, key++, token++)
159 {
160 char k = (*key == '_') ? '-' : tolower (*key );
161 char t = (*token == '_') ? '-' : tolower (*token);
162
163 if (k != t)
164 return FALSE;
165 }
166
167 return *key == '\0';
168 }
169
170 /* The GVariant documentation indirectly says that int is at least 32 bits
171 * (by saying that b, y, n, q, i, u, h are promoted to int). On any
172 * reasonable platform, int is in fact *exactly* 32 bits long, because
173 * otherwise, {signed char, short, int} wouldn't be sufficient to provide
174 * {int8_t, int16_t, int32_t}. */
175 G_STATIC_ASSERT (sizeof (int) == sizeof (gint32));
176
177 /**
178 * g_parse_debug_string:
179 * @string: (nullable): a list of debug options separated by colons, spaces, or
180 * commas, or %NULL.
181 * @keys: (array length=nkeys): pointer to an array of #GDebugKey which associate
182 * strings with bit flags.
183 * @nkeys: the number of #GDebugKeys in the array.
184 *
185 * Parses a string containing debugging options
186 * into a %guint containing bit flags. This is used
187 * within GDK and GTK+ to parse the debug options passed on the
188 * command line or through environment variables.
189 *
190 * If @string is equal to "all", all flags are set. Any flags
191 * specified along with "all" in @string are inverted; thus,
192 * "all,foo,bar" or "foo,bar,all" sets all flags except those
193 * corresponding to "foo" and "bar".
194 *
195 * If @string is equal to "help", all the available keys in @keys
196 * are printed out to standard error.
197 *
198 * Returns: the combined set of bit flags.
199 */
200 guint
g_parse_debug_string(const gchar * string,const GDebugKey * keys,guint nkeys)201 g_parse_debug_string (const gchar *string,
202 const GDebugKey *keys,
203 guint nkeys)
204 {
205 guint i;
206 guint result = 0;
207
208 if (string == NULL)
209 return 0;
210
211 /* this function is used during the initialisation of gmessages, gmem
212 * and gslice, so it may not do anything that causes memory to be
213 * allocated or risks messages being emitted.
214 *
215 * this means, more or less, that this code may not call anything
216 * inside GLib.
217 */
218
219 if (!strcasecmp (string, "help"))
220 {
221 /* using stdio directly for the reason stated above */
222 fprintf (stderr, "Supported debug values:");
223 for (i = 0; i < nkeys; i++)
224 fprintf (stderr, " %s", keys[i].key);
225 fprintf (stderr, " all help\n");
226 }
227 else
228 {
229 const gchar *p = string;
230 const gchar *q;
231 gboolean invert = FALSE;
232
233 while (*p)
234 {
235 q = strpbrk (p, ":;, \t");
236 if (!q)
237 q = p + strlen (p);
238
239 if (debug_key_matches ("all", p, q - p))
240 {
241 invert = TRUE;
242 }
243 else
244 {
245 for (i = 0; i < nkeys; i++)
246 if (debug_key_matches (keys[i].key, p, q - p))
247 result |= keys[i].value;
248 }
249
250 p = q;
251 if (*p)
252 p++;
253 }
254
255 if (invert)
256 {
257 guint all_flags = 0;
258
259 for (i = 0; i < nkeys; i++)
260 all_flags |= keys[i].value;
261
262 result = all_flags & (~result);
263 }
264 }
265
266 return result;
267 }
268
269 static guint
g_parse_debug_envvar(const gchar * envvar,const GDebugKey * keys,gint n_keys,guint default_value)270 g_parse_debug_envvar (const gchar *envvar,
271 const GDebugKey *keys,
272 gint n_keys,
273 guint default_value)
274 {
275 const gchar *value;
276
277 #ifdef OS_WIN32
278 /* "fatal-warnings,fatal-criticals,all,help" is pretty short */
279 gchar buffer[100];
280
281 if (GetEnvironmentVariable (envvar, buffer, 100) < 100)
282 value = buffer;
283 else
284 return 0;
285 #else
286 value = getenv (envvar);
287 #endif
288
289 if (value == NULL)
290 return default_value;
291
292 return g_parse_debug_string (value, keys, n_keys);
293 }
294
295 static void
g_messages_prefixed_init(void)296 g_messages_prefixed_init (void)
297 {
298 const GDebugKey keys[] = {
299 { "error", G_LOG_LEVEL_ERROR },
300 { "critical", G_LOG_LEVEL_CRITICAL },
301 { "warning", G_LOG_LEVEL_WARNING },
302 { "message", G_LOG_LEVEL_MESSAGE },
303 { "info", G_LOG_LEVEL_INFO },
304 { "debug", G_LOG_LEVEL_DEBUG }
305 };
306
307 g_log_msg_prefix = g_parse_debug_envvar ("G_MESSAGES_PREFIXED", keys, G_N_ELEMENTS (keys), g_log_msg_prefix);
308 }
309
310 static void
g_debug_init(void)311 g_debug_init (void)
312 {
313 const GDebugKey keys[] = {
314 { "gc-friendly", 1 },
315 {"fatal-warnings", G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL },
316 {"fatal-criticals", G_LOG_LEVEL_CRITICAL }
317 };
318 GLogLevelFlags flags;
319
320 flags = g_parse_debug_envvar ("G_DEBUG", keys, G_N_ELEMENTS (keys), 0);
321
322 g_log_always_fatal |= flags & G_LOG_LEVEL_MASK;
323
324 g_mem_gc_friendly = flags & 1;
325 }
326
327 void
glib_init(void)328 glib_init (void)
329 {
330 static gboolean glib_inited;
331
332 if (glib_inited)
333 return;
334
335 glib_inited = TRUE;
336
337 g_messages_prefixed_init ();
338 g_debug_init ();
339 g_quark_init ();
340 g_error_init ();
341 }
342
343 #if defined (G_OS_WIN32)
344
345 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
346 DWORD fdwReason,
347 LPVOID lpvReserved);
348
349 HMODULE glib_dll;
350
351 BOOL WINAPI
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)352 DllMain (HINSTANCE hinstDLL,
353 DWORD fdwReason,
354 LPVOID lpvReserved)
355 {
356 switch (fdwReason)
357 {
358 case DLL_PROCESS_ATTACH:
359 glib_dll = hinstDLL;
360 g_crash_handler_win32_init ();
361 g_clock_win32_init ();
362 #ifdef THREADS_WIN32
363 g_thread_win32_init ();
364 #endif
365 glib_init ();
366 /* must go after glib_init */
367 g_console_win32_init ();
368 break;
369
370 case DLL_THREAD_DETACH:
371 #ifdef THREADS_WIN32
372 g_thread_win32_thread_detach ();
373 #endif
374 break;
375
376 case DLL_PROCESS_DETACH:
377 #ifdef THREADS_WIN32
378 if (lpvReserved == NULL)
379 g_thread_win32_process_detach ();
380 #endif
381 g_crash_handler_win32_deinit ();
382 break;
383
384 default:
385 /* do nothing */
386 ;
387 }
388
389 return TRUE;
390 }
391
392 #elif defined (G_HAS_CONSTRUCTORS)
393
394 #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
395 #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(glib_init_ctor)
396 #endif
G_DEFINE_CONSTRUCTOR(glib_init_ctor)397 G_DEFINE_CONSTRUCTOR(glib_init_ctor)
398
399 static void
400 glib_init_ctor (void)
401 {
402 glib_init ();
403 }
404
405 #else
406 # error Your platform/compiler is missing constructor support
407 #endif
408