When looking for symbols in the "main" module we must search both the main
[platform/upstream/glib.git] / gutils.c
index 698986b..30c3bb7 100644 (file)
--- a/gutils.c
+++ b/gutils.c
  * Boston, MA 02111-1307, USA.
  */
 
+/*
+ * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
 /* 
  * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
  */
@@ -25,8 +32,6 @@
 #include <config.h>
 #endif
 
-#include "glibconfig.h"
-
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #include <sys/param.h>
 #endif
 
-#ifdef NATIVE_WIN32
-#  define STRICT                       /* Strict typing, please */
-#  include <windows.h>
-#  include <direct.h>
-#  include <errno.h>
-#  include <ctype.h>
-#  ifdef _MSC_VER
-#    include <io.h>
-#  endif /* _MSC_VER */
-#endif /* NATIVE_WIN32 */
-
 /* implement Glib's inline functions
  */
 #define        G_INLINE_FUNC extern
 #include "glib.h"
 
 #ifdef MAXPATHLEN
-#define        G_PATH_LENGTH   (MAXPATHLEN + 1)
+#define        G_PATH_LENGTH   MAXPATHLEN
 #elif  defined (PATH_MAX)
-#define        G_PATH_LENGTH   (PATH_MAX + 1)
-#else  /* !MAXPATHLEN */
-#define G_PATH_LENGTH   (2048 + 1)
-#endif /* !MAXPATHLEN && !PATH_MAX */
+#define        G_PATH_LENGTH   PATH_MAX
+#elif   defined (_PC_PATH_MAX)
+#define        G_PATH_LENGTH   sysconf(_PC_PATH_MAX)
+#else  
+#define G_PATH_LENGTH   2048
+#endif
+
+#ifdef G_OS_WIN32
+#  define STRICT                       /* Strict typing, please */
+#  include <windows.h>
+#  include <ctype.h>
+#  include <direct.h>
+#  include <io.h>
+#endif /* G_OS_WIN32 */
 
 const guint glib_major_version = GLIB_MAJOR_VERSION;
 const guint glib_minor_version = GLIB_MINOR_VERSION;
@@ -74,15 +78,31 @@ const guint glib_micro_version = GLIB_MICRO_VERSION;
 const guint glib_interface_age = GLIB_INTERFACE_AGE;
 const guint glib_binary_age = GLIB_BINARY_AGE;
 
-#if defined (NATIVE_WIN32) && defined (__LCC__)
-int __stdcall 
-LibMain (void         *hinstDll,
-        unsigned long dwReason,
-        void         *reserved)
+#if !defined (HAVE_MEMMOVE) && !defined (HAVE_WORKING_BCOPY)
+void 
+g_memmove (gpointer dest, gconstpointer src, gulong len)
 {
-  return 1;
+  gchar* destptr = dest;
+  const gchar* srcptr = src;
+  if (src + len < dest || dest + len < src)
+    {
+      bcopy (src, dest, len);
+      return;
+    }
+  else if (dest <= src)
+    {
+      while (len--)
+       *(destptr++) = *(srcptr++);
+    }
+  else
+    {
+      destptr += len;
+      srcptr += len;
+      while (len--)
+       *(--destptr) = *(--srcptr);
+    }
 }
-#endif /* NATIVE_WIN32 && __LCC__ */
+#endif /* !HAVE_MEMMOVE && !HAVE_WORKING_BCOPY */
 
 void
 g_atexit (GVoidFunc func)
@@ -132,7 +152,13 @@ g_snprintf (gchar  *str,
   va_start (args, fmt);
   retval = vsnprintf (str, n, fmt, args);
   va_end (args);
-  
+
+  if (retval < 0)
+    {
+      str[n-1] = '\0';
+      retval = strlen (str);
+    }
+
   return retval;
 #else  /* !HAVE_VSNPRINTF */
   gchar *printed;
@@ -162,6 +188,12 @@ g_vsnprintf (gchar  *str,
   
   retval = vsnprintf (str, n, fmt, args);
   
+  if (retval < 0)
+    {
+      str[n-1] = '\0';
+      retval = strlen (str);
+    }
+
   return retval;
 #else  /* !HAVE_VSNPRINTF */
   gchar *printed;
@@ -233,10 +265,10 @@ g_basename (const gchar      *file_name)
   if (base)
     return base + 1;
 
-#ifdef NATIVE_WIN32
+#ifdef G_OS_WIN32
   if (isalpha (file_name[0]) && file_name[1] == ':')
     return (gchar*) file_name + 2;
-#endif /* NATIVE_WIN32 */
+#endif /* G_OS_WIN32 */
   
   return (gchar*) file_name;
 }
@@ -249,7 +281,7 @@ g_path_is_absolute (const gchar *file_name)
   if (file_name[0] == G_DIR_SEPARATOR)
     return TRUE;
 
-#ifdef NATIVE_WIN32
+#ifdef G_OS_WIN32
   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
     return TRUE;
 #endif
@@ -265,7 +297,7 @@ g_path_skip_root (gchar *file_name)
   if (file_name[0] == G_DIR_SEPARATOR)
     return file_name + 1;
 
-#ifdef NATIVE_WIN32
+#ifdef G_OS_WIN32
   if (isalpha (file_name[0]) && file_name[1] == ':' && file_name[2] == G_DIR_SEPARATOR)
     return file_name + 3;
 #endif
@@ -298,19 +330,30 @@ g_dirname (const gchar       *file_name)
 gchar*
 g_get_current_dir (void)
 {
-  gchar *buffer;
-  gchar *dir;
-
-  buffer = g_new (gchar, G_PATH_LENGTH);
-  *buffer = 0;
+  gchar *buffer = NULL;
+  gchar *dir = NULL;
+  static gulong max_len = (G_PATH_LENGTH == -1) ? 2048 : G_PATH_LENGTH;
   
   /* We don't use getcwd(3) on SUNOS, because, it does a popen("pwd")
    * and, if that wasn't bad enough, hangs in doing so.
    */
 #if    defined (sun) && !defined (__SVR4)
+  buffer = g_new (gchar, max_len + 1);
+  *buffer = 0;
   dir = getwd (buffer);
 #else  /* !sun */
-  dir = getcwd (buffer, G_PATH_LENGTH - 1);
+  while (max_len < G_MAXULONG / 2)
+    {
+      buffer = g_new (gchar, max_len + 1);
+      *buffer = 0;
+      dir = getcwd (buffer, max_len);
+
+      if (dir || errno != ERANGE)
+       break;
+
+      g_free (buffer);
+      max_len *= 2;
+    }
 #endif /* !sun */
   
   if (!dir || !*buffer)
@@ -331,7 +374,7 @@ g_get_current_dir (void)
 gchar*
 g_getenv (const gchar *variable)
 {
-#ifndef NATIVE_WIN32
+#ifndef G_OS_WIN32
   g_return_val_if_fail (variable != NULL, NULL);
 
   return getenv (variable);
@@ -372,7 +415,7 @@ g_getenv (const gchar *variable)
 }
 
 
-G_LOCK_DECLARE_STATIC (g_utils_global);
+G_LOCK_DEFINE_STATIC (g_utils_global);
 
 static gchar   *g_tmp_dir = NULL;
 static gchar   *g_user_name = NULL;
@@ -401,79 +444,109 @@ g_get_any_init (void)
            g_tmp_dir[k-1] = '\0';
        }
 #endif
-
+      
       if (!g_tmp_dir)
        {
-#ifndef NATIVE_WIN32
+#ifndef G_OS_WIN32
          g_tmp_dir = g_strdup ("/tmp");
-#else /* NATIVE_WIN32 */
+#else /* G_OS_WIN32 */
          g_tmp_dir = g_strdup ("C:\\");
-#endif /* NATIVE_WIN32 */
-       }
-      
-#ifdef NATIVE_WIN32
-      /* The official way to specify a home directory on NT is
-       * the HOMEDRIVE and HOMEPATH environment variables.
-       *
-       * This is inside #ifdef NATIVE_WIN32 because with the cygwin dll,
-       * HOME should be a POSIX style pathname.
-       */
-      
-      if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
-       {
-         gchar *homedrive, *homepath;
-
-         homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
-         homepath = g_strdup (g_getenv ("HOMEPATH"));
-
-         g_home_dir = g_strconcat (homedrive, homepath, NULL);
-         g_free (homedrive);
-         g_free (homepath);
+#endif /* G_OS_WIN32 */
        }
-#endif /* !NATIVE_WIN32 */
       
       if (!g_home_dir)
        g_home_dir = g_strdup (g_getenv ("HOME"));
       
+#ifdef G_OS_WIN32
+      if (!g_home_dir)
+       {
+         /* The official way to specify a home directory on NT is
+          * the HOMEDRIVE and HOMEPATH environment variables.
+          *
+          * This is inside #ifdef G_OS_WIN32 because with the cygwin dll,
+          * HOME should be a POSIX style pathname.
+          */
+         
+         if (getenv ("HOMEDRIVE") != NULL && getenv ("HOMEPATH") != NULL)
+           {
+             gchar *homedrive, *homepath;
+             
+             homedrive = g_strdup (g_getenv ("HOMEDRIVE"));
+             homepath = g_strdup (g_getenv ("HOMEPATH"));
+             
+             g_home_dir = g_strconcat (homedrive, homepath, NULL);
+             g_free (homedrive);
+             g_free (homepath);
+           }
+       }
+#endif /* G_OS_WIN32 */
       
 #ifdef HAVE_PWD_H
       {
        struct passwd *pw = NULL;
        gpointer buffer = NULL;
-
+       
 #  ifdef HAVE_GETPWUID_R
         struct passwd pwd;
-        guint bufsize = 1; /* sizeof (struct passwd); */
+#    ifdef _SC_GETPW_R_SIZE_MAX  
+       /* This reurns the maximum length */
+        guint bufsize = sysconf (_SC_GETPW_R_SIZE_MAX);
+#    else /* _SC_GETPW_R_SIZE_MAX */
+        guint bufsize = 64;
+#    endif /* _SC_GETPW_R_SIZE_MAX */
         gint error;
-
+       
         do
           {
             g_free (buffer);
             buffer = g_malloc (bufsize);
-
+           errno = 0;
+           
 #    ifdef HAVE_GETPWUID_R_POSIX
-            error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
+           error = getpwuid_r (getuid (), &pwd, buffer, bufsize, &pw);
             error = error < 0 ? errno : error;
 #    else /* !HAVE_GETPWUID_R_POSIX */
+#      ifdef _AIX
+           error = getpwuid_r (getuid (), &pwd, buffer, bufsize);
+           pw = error == 0 ? &pwd : NULL;
+#      else /* !_AIX */
             pw = getpwuid_r (getuid (), &pwd, buffer, bufsize);
             error = pw ? 0 : errno;
+#      endif /* !_AIX */            
 #    endif /* !HAVE_GETPWUID_R_POSIX */
-
-            bufsize *= 2;
-          }
-        while (error == ERANGE);
-
-        if (error)
-          g_warning ("getpwuid_r(): failed due to: %s", g_strerror (error));
-
-#  else /* !HAVE_GETPWUID_R */
-
-        setpwent ();
-        pw = getpwuid (getuid ());
-        endpwent ();
-
+           
+           if (!pw)
+             {
+               /* we bail out prematurely if the user id can't be found
+                * (should be pretty rare case actually), or if the buffer
+                * should be sufficiently big and lookups are still not
+                * successfull.
+                */
+               if (error == 0 || error == ENOENT)
+                 {
+                   g_warning ("getpwuid_r(): failed due to unknown user id (%lu)",
+                              (gulong) getuid ());
+                   break;
+                 }
+               if (bufsize > 32 * 1024)
+                 {
+                   g_warning ("getpwuid_r(): failed due to: %s.",
+                              g_strerror (error));
+                   break;
+                 }
+               
+               bufsize *= 2;
+             }
+         }
+       while (!pw);
 #  endif /* !HAVE_GETPWUID_R */
        
+       if (!pw)
+         {
+           setpwent ();
+           pw = getpwuid (getuid ());
+           endpwent ();
+         }
        if (pw)
          {
            g_user_name = g_strdup (pw->pw_name);
@@ -483,10 +556,10 @@ g_get_any_init (void)
          }
        g_free (buffer);
       }
-
+      
 #else /* !HAVE_PWD_H */
-
-#  ifdef NATIVE_WIN32
+      
+#  ifdef G_OS_WIN32
       {
        guint len = 17;
        gchar buffer[17];
@@ -497,15 +570,33 @@ g_get_any_init (void)
            g_real_name = g_strdup (buffer);
          }
       }
-#  endif /* NATIVE_WIN32 */
-
+#  endif /* G_OS_WIN32 */
+      
 #endif /* !HAVE_PWD_H */
-
+      
+#ifdef __EMX__
+      /* change '\\' in %HOME% to '/' */
+      g_strdelimit (g_home_dir, "\\",'/');
+#endif
       if (!g_user_name)
        g_user_name = g_strdup ("somebody");
       if (!g_real_name)
        g_real_name = g_strdup ("Unknown");
-    }  
+      else
+       {
+         gchar *p;
+
+         for (p = g_real_name; *p; p++)
+           if (*p == ',')
+             {
+               *p = 0;
+               p = g_strdup (g_real_name);
+               g_free (g_real_name);
+               g_real_name = p;
+               break;
+             }
+       }
+    }
 }
 
 gchar*
@@ -601,7 +692,7 @@ gint
 g_direct_equal (gconstpointer v1,
                gconstpointer v2)
 {
-  return GPOINTER_TO_UINT (v1) == GPOINTER_TO_UINT (v2);
+  return v1 == v2;
 }
 
 gint
@@ -616,233 +707,3 @@ g_int_hash (gconstpointer v)
 {
   return *(const gint*) v;
 }
-
-#if 0 /* Old IO Channels */
-
-GIOChannel*
-g_iochannel_new (gint fd)
-{
-  GIOChannel *channel = g_new (GIOChannel, 1);
-
-  channel->fd = fd;
-
-#ifdef NATIVE_WIN32
-  channel->peer = 0;
-  channel->peer_fd = 0;
-  channel->offset = 0;
-  channel->need_wakeups = 0;
-#endif /* NATIVE_WIN32 */
-
-  return channel;
-}
-
-void
-g_iochannel_free (GIOChannel *channel)
-{
-  g_return_if_fail (channel != NULL);
-
-  g_free (channel);
-}
-
-void
-g_iochannel_close_and_free (GIOChannel *channel)
-{
-  g_return_if_fail (channel != NULL);
-
-  close (channel->fd);
-
-  g_iochannel_free (channel);
-}
-
-#undef g_iochannel_wakeup_peer
-
-void
-g_iochannel_wakeup_peer (GIOChannel *channel)
-{
-#ifdef NATIVE_WIN32
-  static guint message = 0;
-#endif
-
-  g_return_if_fail (channel != NULL);
-
-#ifdef NATIVE_WIN32
-  if (message == 0)
-    message = RegisterWindowMessage ("gdk-pipe-readable");
-
-#  if 0
-  g_print ("g_iochannel_wakeup_peer: calling PostThreadMessage (%#x, %d, %d, %d)\n",
-          channel->peer, message, channel->peer_fd, channel->offset);
-#  endif
-  PostThreadMessage (channel->peer, message,
-                    channel->peer_fd, channel->offset);
-#endif /* NATIVE_WIN32 */
-}
-
-#endif /* Old IO Channels */
-
-#ifdef NATIVE_WIN32
-#ifdef _MSC_VER
-
-int
-gwin_ftruncate (gint  fd,
-               guint size)
-{
-  HANDLE hfile;
-  guint curpos;
-
-  g_return_val_if_fail (fd >= 0, -1);
-  
-  hfile = (HANDLE) _get_osfhandle (fd);
-  curpos = SetFilePointer (hfile, 0, NULL, FILE_CURRENT);
-  if (curpos == 0xFFFFFFFF
-      || SetFilePointer (hfile, size, NULL, FILE_BEGIN) == 0xFFFFFFFF
-      || !SetEndOfFile (hfile))
-    {
-      gint error = GetLastError ();
-
-      switch (error)
-       {
-       case ERROR_INVALID_HANDLE:
-         errno = EBADF;
-         break;
-       default:
-         errno = EIO;
-         break;
-       }
-
-      return -1;
-    }
-
-  return 0;
-}
-
-DIR*
-gwin_opendir (const char *dirname)
-{
-  DIR *result;
-  gchar *mask;
-  guint k;
-
-  g_return_val_if_fail (dirname != NULL, NULL);
-
-  result = g_new0 (DIR, 1);
-  result->find_file_data = g_new0 (WIN32_FIND_DATA, 1);
-  result->dir_name = g_strdup (dirname);
-  
-  k = strlen (result->dir_name);
-  if (k && result->dir_name[k - 1] == '\\')
-    {
-      result->dir_name[k - 1] = '\0';
-      k--;
-    }
-  mask = g_strdup_printf ("%s\\*", result->dir_name);
-
-  result->find_file_handle = (guint) FindFirstFile (mask,
-                                            (LPWIN32_FIND_DATA) result->find_file_data);
-  g_free (mask);
-
-  if (result->find_file_handle == (guint) INVALID_HANDLE_VALUE)
-    {
-      int error = GetLastError ();
-
-      g_free (result->dir_name);
-      g_free (result->find_file_data);
-      g_free (result);
-      switch (error)
-       {
-       default:
-         errno = EIO;
-         return NULL;
-       }
-    }
-  result->just_opened = TRUE;
-
-  return result;
-}
-
-struct dirent*
-gwin_readdir (DIR *dir)
-{
-  static struct dirent result;
-
-  g_return_val_if_fail (dir != NULL, NULL);
-
-  if (dir->just_opened)
-    dir->just_opened = FALSE;
-  else
-    {
-      if (!FindNextFile ((HANDLE) dir->find_file_handle,
-                        (LPWIN32_FIND_DATA) dir->find_file_data))
-       {
-         int error = GetLastError ();
-
-         switch (error)
-           {
-           case ERROR_NO_MORE_FILES:
-             return NULL;
-           default:
-             errno = EIO;
-             return NULL;
-           }
-       }
-    }
-  strcpy (result.d_name, g_basename (((LPWIN32_FIND_DATA) dir->find_file_data)->cFileName));
-      
-  return &result;
-}
-
-void
-gwin_rewinddir (DIR *dir)
-{
-  gchar *mask;
-
-  g_return_if_fail (dir != NULL);
-
-  if (!FindClose ((HANDLE) dir->find_file_handle))
-    g_warning ("gwin_rewinddir(): FindClose() failed\n");
-
-  mask = g_strdup_printf ("%s\\*", dir->dir_name);
-  dir->find_file_handle = (guint) FindFirstFile (mask,
-                                         (LPWIN32_FIND_DATA) dir->find_file_data);
-  g_free (mask);
-
-  if (dir->find_file_handle == (guint) INVALID_HANDLE_VALUE)
-    {
-      int error = GetLastError ();
-
-      switch (error)
-       {
-       default:
-         errno = EIO;
-         return;
-       }
-    }
-  dir->just_opened = TRUE;
-}  
-
-gint
-gwin_closedir (DIR *dir)
-{
-  g_return_val_if_fail (dir != NULL, -1);
-
-  if (!FindClose ((HANDLE) dir->find_file_handle))
-    {
-      int error = GetLastError ();
-
-      switch (error)
-       {
-       default:
-         errno = EIO; return -1;
-       }
-    }
-
-  g_free (dir->dir_name);
-  g_free (dir->find_file_data);
-  g_free (dir);
-
-  return 0;
-}
-
-#endif /* _MSC_VER */
-
-#endif /* NATIVE_WIN32 */