• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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