Remove all uses of G_CONST_RETURN
[platform/upstream/glib.git] / glib / gutils.c
index 406665e..c870152 100644 (file)
  */
 #define        G_IMPLEMENT_INLINES 1
 #define        __G_UTILS_C__
-#include "glib.h"
+#include "gutils.h"
+
+#include "gfileutils.h"
+#include "ghash.h"
+#include "gslist.h"
 #include "gprintfint.h"
+#include "gthread.h"
 #include "gthreadprivate.h"
+#include "gtestutils.h"
+#include "gunicode.h"
+#include "gstrfuncs.h"
+#include "garray.h"
 #include "glibintl.h"
-#include "galias.h"
+
+#ifdef G_PLATFORM_WIN32
+#include "garray.h"
+#include "gconvert.h"
+#include "gwin32.h"
+#endif
 
 #ifdef MAXPATHLEN
 #define        G_PATH_LENGTH   MAXPATHLEN
@@ -697,7 +711,7 @@ g_parse_debug_string  (const gchar     *string,
  * g_path_get_basename() allocates new memory for the returned string, unlike
  * this function which returns a pointer into the argument.
  **/
-G_CONST_RETURN gchar*
+const gchar *
 g_basename (const gchar           *file_name)
 {
   register gchar *base;
@@ -788,11 +802,32 @@ g_path_get_basename (const gchar   *file_name)
  * g_path_is_absolute:
  * @file_name: a file name.
  *
- * Returns %TRUE if the given @file_name is an absolute file name,
- * i.e. it contains a full path from the root directory such as "/usr/local"
- * on UNIX or "C:\windows" on Windows systems.
+ * Returns %TRUE if the given @file_name is an absolute file name.
+ * Note that this is a somewhat vague concept on Windows.
  *
- * Returns: %TRUE if @file_name is an absolute path. 
+ * On POSIX systems, an absolute file name is well-defined. It always
+ * starts from the single root directory. For example "/usr/local".
+ *
+ * On Windows, the concepts of current drive and drive-specific
+ * current directory introduce vagueness. This function interprets as
+ * an absolute file name one that either begins with a directory
+ * separator such as "\Users\tml" or begins with the root on a drive,
+ * for example "C:\Windows". The first case also includes UNC paths
+ * such as "\\myserver\docs\foo". In all cases, either slashes or
+ * backslashes are accepted.
+ *
+ * Note that a file name relative to the current drive root does not
+ * truly specify a file uniquely over time and across processes, as
+ * the current drive is a per-process value and can be changed.
+ *
+ * File names relative the current directory on some specific drive,
+ * such as "D:foo/bar", are not interpreted as absolute by this
+ * function, but they obviously are not relative to the normal current
+ * directory as returned by getcwd() or g_get_current_dir()
+ * either. Such paths should be avoided, or need to be handled using
+ * Windows-specific code.
+ *
+ * Returns: %TRUE if @file_name is absolute. 
  */
 gboolean
 g_path_is_absolute (const gchar *file_name)
@@ -822,7 +857,7 @@ g_path_is_absolute (const gchar *file_name)
  *
  * Returns: a pointer into @file_name after the root component.
  */
-G_CONST_RETURN gchar*
+const gchar *
 g_path_skip_root (const gchar *file_name)
 {
   g_return_val_if_fail (file_name != NULL, NULL);
@@ -1073,7 +1108,7 @@ g_get_current_dir (void)
  * overwritten by the next call to g_getenv(), g_setenv() or
  * g_unsetenv().
  **/
-G_CONST_RETURN gchar*
+const gchar *
 g_getenv (const gchar *variable)
 {
 #ifndef G_OS_WIN32
@@ -1440,6 +1475,45 @@ g_listenv (void)
 #endif
 }
 
+/**
+ * g_get_environ:
+ * 
+ * Gets the list of environment variables for the current process.  The
+ * list is %NULL terminated and each item in the list is of the form
+ * 'NAME=VALUE'.
+ *
+ * This is equivalent to direct access to the 'environ' global variable,
+ * except portable.
+ *
+ * The return value is freshly allocated and it should be freed with
+ * g_strfreev() when it is no longer needed.
+ *
+ * Returns: the list of environment variables
+ *
+ * Since: 2.28
+ */
+gchar **
+g_get_environ (void)
+{
+#ifndef G_OS_WIN32
+  return g_strdupv (environ);
+#else
+  gunichar2 *strings;
+  gchar **result;
+  gint i, n;
+
+  strings = GetEnvironmentStringsW ();
+  for (n = 0; strings[n]; n += wcslen (strings + n) + 1);
+  result = g_new (char *, n + 1);
+  for (i = 0; strings[i]; i += wcslen (strings + i) + 1)
+    result[i] = g_utf16_to_utf8 (strings + i, -1, NULL, NULL, NULL);
+  FreeEnvironmentStringsW (strings);
+  result[i] = NULL;
+
+  return result;
+#endif
+}
+
 G_LOCK_DEFINE_STATIC (g_utils_global);
 
 static gchar   *g_tmp_dir = NULL;
@@ -1526,17 +1600,17 @@ g_get_any_init_do (void)
   gchar hostname[100];
 
   g_tmp_dir = g_strdup (g_getenv ("TMPDIR"));
-  if (!g_tmp_dir)
+  if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
     g_tmp_dir = g_strdup (g_getenv ("TMP"));
-  if (!g_tmp_dir)
+  if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
     g_tmp_dir = g_strdup (g_getenv ("TEMP"));
 
 #ifdef G_OS_WIN32
-  if (!g_tmp_dir)
+  if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
     g_tmp_dir = get_windows_directory_root ();
 #else  
 #ifdef P_tmpdir
-  if (!g_tmp_dir)
+  if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
     {
       gsize k;    
       g_tmp_dir = g_strdup (P_tmpdir);
@@ -1546,7 +1620,7 @@ g_get_any_init_do (void)
     }
 #endif
   
-  if (!g_tmp_dir)
+  if (g_tmp_dir == NULL || *g_tmp_dir == '\0')
     {
       g_tmp_dir = g_strdup ("/tmp");
     }
@@ -1798,7 +1872,7 @@ g_get_any_init_locked (void)
  *
  * Returns: the user name of the current user.
  */
-G_CONST_RETURN gchar*
+const gchar *
 g_get_user_name (void)
 {
   g_get_any_init_locked ();
@@ -1816,7 +1890,7 @@ g_get_user_name (void)
  *
  * Returns: the user's real name.
  */
-G_CONST_RETURN gchar*
+const gchar *
 g_get_real_name (void)
 {
   g_get_any_init_locked ();
@@ -1854,7 +1928,7 @@ g_get_real_name (void)
  *
  * Returns: the current user's home directory
  */
-G_CONST_RETURN gchar*
+const gchar *
 g_get_home_dir (void)
 {
   g_get_any_init_locked ();
@@ -1869,11 +1943,11 @@ g_get_home_dir (void)
  * <envar>TMP</envar>, and <envar>TEMP</envar> in that order. If none 
  * of those are defined "/tmp" is returned on UNIX and "C:\" on Windows. 
  * The encoding of the returned string is system-defined. On Windows, 
- * it is always UTF-8. The return value is never %NULL.
+ * it is always UTF-8. The return value is never %NULL or the empty string.
  *
  * Returns: the directory to use for temporary files.
  */
-G_CONST_RETURN gchar*
+const gchar *
 g_get_tmp_dir (void)
 {
   g_get_any_init_locked ();
@@ -1992,7 +2066,7 @@ static gchar *g_application_name = NULL;
  *
  * Since: 2.2
  **/
-G_CONST_RETURN gchar*
+const gchar *
 g_get_application_name (void)
 {
   gchar* retval;
@@ -2052,14 +2126,16 @@ g_set_application_name (const gchar *application_name)
  * XDG Base Directory Specification</ulink>.
  * In this case the directory retrieved will be XDG_DATA_HOME.
  *
- * On Windows is the virtual folder that represents the My Documents
- * desktop item. See documentation for CSIDL_PERSONAL.
+ * On Windows this is the folder to use for local (as opposed to
+ * roaming) application data. See documentation for
+ * CSIDL_LOCAL_APPDATA. Note that on Windows it thus is the same as
+ * what g_get_user_config_dir() returns.
  *
  * Return value: a string owned by GLib that must not be modified 
  *               or freed.
  * Since: 2.6
  **/
-G_CONST_RETURN gchar*
+const gchar *
 g_get_user_data_dir (void)
 {
   gchar *data_dir;  
@@ -2069,7 +2145,7 @@ g_get_user_data_dir (void)
   if (!g_user_data_dir)
     {
 #ifdef G_OS_WIN32
-      data_dir = get_special_folder (CSIDL_PERSONAL);
+      data_dir = get_special_folder (CSIDL_LOCAL_APPDATA);
 #else
       data_dir = (gchar *) g_getenv ("XDG_DATA_HOME");
 
@@ -2106,7 +2182,7 @@ g_init_user_config_dir (void)
   if (!g_user_config_dir)
     {
 #ifdef G_OS_WIN32
-      config_dir = get_special_folder (CSIDL_APPDATA);
+      config_dir = get_special_folder (CSIDL_LOCAL_APPDATA);
 #else
       config_dir = (gchar *) g_getenv ("XDG_CONFIG_HOME");
 
@@ -2138,16 +2214,16 @@ g_init_user_config_dir (void)
  * XDG Base Directory Specification</ulink>.
  * In this case the directory retrieved will be XDG_CONFIG_HOME.
  *
- * On Windows is the directory that serves as a common repository for
- * application-specific data. A typical path is
- * C:\Documents and Settings\username\Application. See documentation for
- * CSIDL_APPDATA.
+ * On Windows this is the folder to use for local (as opposed to
+ * roaming) application data. See documentation for
+ * CSIDL_LOCAL_APPDATA. Note that on Windows it thus is the same as
+ * what g_get_user_data_dir() returns.
  *
  * Return value: a string owned by GLib that must not be modified 
  *               or freed.
  * Since: 2.6
  **/
-G_CONST_RETURN gchar*
+const gchar *
 g_get_user_config_dir (void)
 {
   G_LOCK (g_utils_global);
@@ -2179,7 +2255,7 @@ g_get_user_config_dir (void)
  *               or freed.
  * Since: 2.6
  **/
-G_CONST_RETURN gchar*
+const gchar *
 g_get_user_cache_dir (void)
 {
   gchar *cache_dir;  
@@ -2215,6 +2291,57 @@ g_get_user_cache_dir (void)
   return cache_dir;
 }
 
+/**
+ * g_get_user_runtime_dir:
+ *
+ * Returns a directory that is unique to the current user on the local
+ * system.
+ *
+ * On UNIX platforms this is determined using the mechanisms described in
+ * the <ulink url="http://www.freedesktop.org/Standards/basedir-spec">
+ * XDG Base Directory Specification</ulink>.  This is the directory
+ * specified in the <envar>XDG_RUNTIME_DIR</envar> environment variable.
+ * In the case that this variable is not set, GLib will issue a warning
+ * message to stderr and return the value of g_get_user_cache_dir().
+ *
+ * On Windows this is the folder to use for local (as opposed to
+ * roaming) application data. See documentation for
+ * CSIDL_LOCAL_APPDATA.  Note that on Windows it thus is the same as
+ * what g_get_user_config_dir() returns.
+ *
+ * Returns: a string owned by GLib that must not be modified or freed.
+ *
+ * Since: 2.28
+ **/
+const gchar *
+g_get_user_runtime_dir (void)
+{
+#ifndef G_OS_WIN32
+  static const gchar *runtime_dir;
+  static gsize initialised;
+
+  if (g_once_init_enter (&initialised))
+    {
+      runtime_dir = g_strdup (getenv ("XDG_RUNTIME_DIR"));
+      
+      if (runtime_dir == NULL)
+        g_warning ("XDG_RUNTIME_DIR variable not set.  "
+                   "Falling back to XDG cache dir.");
+
+      g_once_init_leave (&initialised, 1);
+    }
+
+  if (runtime_dir)
+    return runtime_dir;
+
+  /* Both fallback for UNIX and the default
+   * in Windows: use the user cache directory.
+   */
+#endif
+
+  return g_get_user_cache_dir ();
+}
+
 #ifdef HAVE_CARBON
 
 static gchar *
@@ -2278,13 +2405,15 @@ load_user_special_dirs (void)
                                                    HANDLE hToken,
                                                    PWSTR *ppszPath);
   t_SHGetKnownFolderPath p_SHGetKnownFolderPath;
+
   static const GUID FOLDERID_Downloads =
     { 0x374de290, 0x123f, 0x4565, { 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b } };
   static const GUID FOLDERID_Public =
     { 0xDFDF76A2, 0xC82A, 0x4D63, { 0x90, 0x6A, 0x56, 0x44, 0xAC, 0x45, 0x73, 0x85 } };
+
   wchar_t *wcp;
 
-  p_SHGetKnownFolderPath = (t_SHGetKnownFolderPath) GetProcAddress (LoadLibrary ("shell32.dll"),
+  p_SHGetKnownFolderPath = (t_SHGetKnownFolderPath) GetProcAddress (GetModuleHandle ("shell32.dll"),
                                                                    "SHGetKnownFolderPath");
 
   g_user_special_dirs[G_USER_DIRECTORY_DESKTOP] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
@@ -2298,10 +2427,15 @@ load_user_special_dirs (void)
     {
       wcp = NULL;
       (*p_SHGetKnownFolderPath) (&FOLDERID_Downloads, 0, NULL, &wcp);
-      g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
-      if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL)
-       g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
-      CoTaskMemFree (wcp);
+      if (wcp)
+        {
+          g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
+          if (g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] == NULL)
+              g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
+          CoTaskMemFree (wcp);
+        }
+      else
+          g_user_special_dirs[G_USER_DIRECTORY_DOWNLOAD] = get_special_folder (CSIDL_DESKTOPDIRECTORY);
     }
 
   g_user_special_dirs[G_USER_DIRECTORY_MUSIC] = get_special_folder (CSIDL_MYMUSIC);
@@ -2316,10 +2450,15 @@ load_user_special_dirs (void)
     {
       wcp = NULL;
       (*p_SHGetKnownFolderPath) (&FOLDERID_Public, 0, NULL, &wcp);
-      g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
-      if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL)
-       g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
-      CoTaskMemFree (wcp);
+      if (wcp)
+        {
+          g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = g_utf16_to_utf8 (wcp, -1, NULL, NULL, NULL);
+          if (g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] == NULL)
+              g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
+          CoTaskMemFree (wcp);
+        }
+      else
+          g_user_special_dirs[G_USER_DIRECTORY_PUBLIC_SHARE] = get_special_folder (CSIDL_COMMON_DOCUMENTS);
     }
   
   g_user_special_dirs[G_USER_DIRECTORY_TEMPLATES] = get_special_folder (CSIDL_TEMPLATES);
@@ -2561,7 +2700,7 @@ g_reload_user_special_dirs_cache (void)
  *
  * Since: 2.14
  */
-G_CONST_RETURN gchar *
+const gchar *
 g_get_user_special_dir (GUserDirectory directory)
 {
   g_return_val_if_fail (directory >= G_USER_DIRECTORY_DESKTOP &&
@@ -2610,7 +2749,7 @@ get_module_for_address (gconstpointer address)
   if (!beenhere)
     {
       p_GetModuleHandleExA =
-       (t_GetModuleHandleExA) GetProcAddress (LoadLibrary ("kernel32.dll"),
+       (t_GetModuleHandleExA) GetProcAddress (GetModuleHandle ("kernel32.dll"),
                                               "GetModuleHandleExA");
       beenhere = TRUE;
     }
@@ -2646,7 +2785,7 @@ get_module_share_dir (gconstpointer address)
   return retval;
 }
 
-G_CONST_RETURN gchar * G_CONST_RETURN *
+const gchar * const *
 g_win32_get_system_data_dirs_for_module (void (*address_of_function)())
 {
   GArray *data_dirs;
@@ -2671,7 +2810,7 @@ g_win32_get_system_data_dirs_for_module (void (*address_of_function)())
              if (retval != NULL)
                {
                  G_UNLOCK (g_utils_global);
-                 return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
+                 return (const gchar * const *) retval;
                }
            }
        }
@@ -2739,7 +2878,7 @@ g_win32_get_system_data_dirs_for_module (void (*address_of_function)())
       G_UNLOCK (g_utils_global);
     }
 
-  return (G_CONST_RETURN gchar * G_CONST_RETURN *) retval;
+  return (const gchar * const *) retval;
 }
 
 #endif
@@ -2781,7 +2920,7 @@ g_win32_get_system_data_dirs_for_module (void (*address_of_function)())
  *               not be modified or freed.
  * Since: 2.6
  **/
-G_CONST_RETURN gchar * G_CONST_RETURN * 
+const gchar * const * 
 g_get_system_data_dirs (void)
 {
   gchar **data_dir_vector;
@@ -2808,7 +2947,7 @@ g_get_system_data_dirs (void)
 
   G_UNLOCK (g_utils_global);
 
-  return (G_CONST_RETURN gchar * G_CONST_RETURN *) data_dir_vector;
+  return (const gchar * const *) data_dir_vector;
 }
 
 /**
@@ -2833,7 +2972,7 @@ g_get_system_data_dirs (void)
  *               not be modified or freed.
  * Since: 2.6
  **/
-G_CONST_RETURN gchar * G_CONST_RETURN *
+const gchar * const *
 g_get_system_config_dirs (void)
 {
   gchar *conf_dirs, **conf_dir_vector;
@@ -2869,7 +3008,7 @@ g_get_system_config_dirs (void)
     conf_dir_vector = g_system_config_dirs;
   G_UNLOCK (g_utils_global);
 
-  return (G_CONST_RETURN gchar * G_CONST_RETURN *) conf_dir_vector;
+  return (const gchar * const *) conf_dir_vector;
 }
 
 #ifndef G_OS_WIN32
@@ -3029,36 +3168,39 @@ explode_locale (const gchar *locale,
  *       but it is big, ugly, and complicated, so I'm reluctant
  *       to do so when this should handle 99% of the time...
  */
-GSList *
-_g_compute_locale_variants (const gchar *locale)
+static void
+append_locale_variants (GPtrArray *array,
+                        const gchar *locale)
 {
-  GSList *retval = NULL;
-
   gchar *language = NULL;
   gchar *territory = NULL;
   gchar *codeset = NULL;
   gchar *modifier = NULL;
 
   guint mask;
-  guint i;
+  guint i, j;
 
-  g_return_val_if_fail (locale != NULL, NULL);
+  g_return_if_fail (locale != NULL);
 
   mask = explode_locale (locale, &language, &territory, &codeset, &modifier);
 
   /* Iterate through all possible combinations, from least attractive
    * to most attractive.
    */
-  for (i = 0; i <= mask; i++)
-    if ((i & ~mask) == 0)
-      {
-       gchar *val = g_strconcat (language,
-                                 (i & COMPONENT_TERRITORY) ? territory : "",
-                                 (i & COMPONENT_CODESET) ? codeset : "",
-                                 (i & COMPONENT_MODIFIER) ? modifier : "",
-                                 NULL);
-       retval = g_slist_prepend (retval, val);
-      }
+  for (j = 0; j <= mask; ++j)
+    {
+      i = mask - j;
+
+      if ((i & ~mask) == 0)
+        {
+          gchar *val = g_strconcat (language,
+                                    (i & COMPONENT_TERRITORY) ? territory : "",
+                                    (i & COMPONENT_CODESET) ? codeset : "",
+                                    (i & COMPONENT_MODIFIER) ? modifier : "",
+                                    NULL);
+          g_ptr_array_add (array, val);
+        }
+    }
 
   g_free (language);
   if (mask & COMPONENT_CODESET)
@@ -3067,8 +3209,41 @@ _g_compute_locale_variants (const gchar *locale)
     g_free (territory);
   if (mask & COMPONENT_MODIFIER)
     g_free (modifier);
+}
 
-  return retval;
+/**
+ * g_get_locale_variants:
+ * @locale: a locale identifier
+ *
+ * Returns a list of derived variants of @locale, which can be used to
+ * e.g. construct locale-dependent filenames or search paths. The returned
+ * list is sorted from most desirable to least desirable.
+ * This function handles territory, charset and extra locale modifiers.
+ * 
+ * For example, if @locale is "fr_BE", then the returned list
+ * is "fr_BE", "fr".
+ *
+ * If you need the list of variants for the <emphasis>current locale</emphasis>,
+ * use g_get_language_names().
+ *
+ * Returns: (transfer full) (array zero-terminated="1") (element-type utf8): a newly
+ *   allocated array of newly allocated strings with the locale variants. Free with
+ *   g_strfreev().
+ *
+ * Since: 2.28
+ */
+gchar **
+g_get_locale_variants (const gchar *locale)
+{
+  GPtrArray *array;
+
+  g_return_val_if_fail (locale != NULL, NULL);
+
+  array = g_ptr_array_sized_new (8);
+  append_locale_variants (array, locale);
+  g_ptr_array_add (array, NULL);
+
+  return (gchar **) g_ptr_array_free (array, FALSE);
 }
 
 /* The following is (partly) taken from the gettext package.
@@ -3158,7 +3333,7 @@ language_names_cache_free (gpointer data)
  *
  * Since: 2.6
  **/
-G_CONST_RETURN gchar * G_CONST_RETURN * 
+const gchar * const * 
 g_get_language_names (void)
 {
   static GStaticPrivate cache_private = G_STATIC_PRIVATE_INIT;
@@ -3177,34 +3352,26 @@ g_get_language_names (void)
 
   if (!(cache->languages && strcmp (cache->languages, value) == 0))
     {
-      gchar **languages;
+      GPtrArray *array;
       gchar **alist, **a;
-      GSList *list, *l;
-      gint i;
 
       g_free (cache->languages);
       g_strfreev (cache->language_names);
       cache->languages = g_strdup (value);
 
+      array = g_ptr_array_sized_new (8);
+
       alist = g_strsplit (value, ":", 0);
-      list = NULL;
       for (a = alist; *a; a++)
-       {
-         gchar *b = unalias_lang (*a);
-         list = g_slist_concat (list, _g_compute_locale_variants (b));
-       }
+        append_locale_variants (array, unalias_lang (*a));
       g_strfreev (alist);
-      list = g_slist_append (list, g_strdup ("C"));
-
-      cache->language_names = languages = g_new (gchar *, g_slist_length (list) + 1);
-      for (l = list, i = 0; l; l = l->next, i++)
-       languages[i] = l->data;
-      languages[i] = NULL;
+      g_ptr_array_add (array, g_strdup ("C"));
+      g_ptr_array_add (array, NULL);
 
-      g_slist_free (list);
+      cache->language_names = (gchar **) g_ptr_array_free (array, FALSE);
     }
 
-  return (G_CONST_RETURN gchar * G_CONST_RETURN *) cache->language_names;
+  return (const gchar * const *) cache->language_names;
 }
 
 /**
@@ -3405,7 +3572,7 @@ _g_utils_thread_init (void)
  * have to use system codepage as bindtextdomain() doesn't have a
  * UTF-8 interface.
  */
-static gchar *
+gchar *
 _glib_get_locale_dir (void)
 {
   gchar *install_dir = NULL, *locale_dir;
@@ -3444,18 +3611,8 @@ _glib_get_locale_dir (void)
 
 #endif /* G_OS_WIN32 */
 
-/**
- * glib_gettext:
- * @str: The string to be translated
- *
- * Returns the translated string from the glib translations.
- * This is an internal function and should only be used by
- * the internals of glib (such as libgio).
- *
- * Returns: the transation of @str to the current locale
- */
-G_CONST_RETURN gchar *
-glib_gettext (const gchar *str)
+static void
+ensure_gettext_initialized(void)
 {
   static gboolean _glib_gettext_initialized = FALSE;
 
@@ -3473,10 +3630,50 @@ glib_gettext (const gchar *str)
 #    endif
       _glib_gettext_initialized = TRUE;
     }
-  
+}
+
+/**
+ * glib_gettext:
+ * @str: The string to be translated
+ *
+ * Returns the translated string from the glib translations.
+ * This is an internal function and should only be used by
+ * the internals of glib (such as libgio).
+ *
+ * Returns: the transation of @str to the current locale
+ */
+const gchar *
+glib_gettext (const gchar *str)
+{
+  ensure_gettext_initialized();
+
   return g_dgettext (GETTEXT_PACKAGE, str);
 }
 
+/**
+ * glib_pgettext:
+ * @msgctxtid: a combined message context and message id, separated
+ *   by a \004 character
+ * @msgidoffset: the offset of the message id in @msgctxid
+ *
+ * This function is a variant of glib_gettext() which supports
+ * a disambiguating message context. See g_dpgettext() for full
+ * details.
+ *
+ * This is an internal function and should only be used by
+ * the internals of glib (such as libgio).
+ *
+ * Returns: the transation of @str to the current locale
+ */
+const gchar *
+glib_pgettext(const gchar *msgctxtid,
+              gsize        msgidoffset)
+{
+  ensure_gettext_initialized();
+
+  return g_dpgettext (GETTEXT_PACKAGE, msgctxtid, msgidoffset);
+}
+
 #if defined (G_OS_WIN32) && !defined (_WIN64)
 
 /* Binary compatibility versions. Not for newly compiled code. */
@@ -3512,7 +3709,7 @@ g_get_current_dir (void)
 
 #undef g_getenv
 
-G_CONST_RETURN gchar*
+const gchar *
 g_getenv (const gchar *variable)
 {
   gchar *utf8_variable = g_locale_to_utf8 (variable, -1, NULL, NULL, NULL);
@@ -3561,7 +3758,7 @@ g_unsetenv (const gchar *variable)
 
 #undef g_get_user_name
 
-G_CONST_RETURN gchar*
+const gchar *
 g_get_user_name (void)
 {
   g_get_any_init_locked ();
@@ -3570,7 +3767,7 @@ g_get_user_name (void)
 
 #undef g_get_real_name
 
-G_CONST_RETURN gchar*
+const gchar *
 g_get_real_name (void)
 {
   g_get_any_init_locked ();
@@ -3579,7 +3776,7 @@ g_get_real_name (void)
 
 #undef g_get_home_dir
 
-G_CONST_RETURN gchar*
+const gchar *
 g_get_home_dir (void)
 {
   g_get_any_init_locked ();
@@ -3588,7 +3785,7 @@ g_get_home_dir (void)
 
 #undef g_get_tmp_dir
 
-G_CONST_RETURN gchar*
+const gchar *
 g_get_tmp_dir (void)
 {
   g_get_any_init_locked ();
@@ -3596,6 +3793,3 @@ g_get_tmp_dir (void)
 }
 
 #endif
-
-#define __G_UTILS_C__
-#include "galiasdef.c"