]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
New module 'libglib'.
authorBruno Haible <bruno@clisp.org>
Tue, 14 Nov 2006 10:35:14 +0000 (10:35 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:14:22 +0000 (12:14 +0200)
18 files changed:
gnulib-local/ChangeLog
gnulib-local/Makefile.am
gnulib-local/lib/glib/ghash.c [new file with mode: 0644]
gnulib-local/lib/glib/ghash_.h [new file with mode: 0644]
gnulib-local/lib/glib/glist.c [new file with mode: 0644]
gnulib-local/lib/glib/glist_.h [new file with mode: 0644]
gnulib-local/lib/glib/gmessages.c [new file with mode: 0644]
gnulib-local/lib/glib/gprimes.c [new file with mode: 0644]
gnulib-local/lib/glib/gprimes_.h [new file with mode: 0644]
gnulib-local/lib/glib/gstrfuncs.c [new file with mode: 0644]
gnulib-local/lib/glib/gstrfuncs_.h [new file with mode: 0644]
gnulib-local/lib/glib/gstring.c [new file with mode: 0644]
gnulib-local/lib/glib/gstring_.h [new file with mode: 0644]
gnulib-local/lib/glib/gtypes_.h [new file with mode: 0644]
gnulib-local/lib/glib_.h [new file with mode: 0644]
gnulib-local/lib/glibconfig_.h [new file with mode: 0644]
gnulib-local/m4/libglib.m4 [new file with mode: 0644]
gnulib-local/modules/libglib [new file with mode: 0644]

index fa53991078ecd6ab8875be1c0b30c89ca08ca344..4e6afbcbf0837d5ffed86740974178e96f1d1e17 100644 (file)
@@ -1,3 +1,23 @@
+2006-11-12  Bruno Haible  <bruno@clisp.org>
+
+       * modules/libglib: New file.
+       * m4/libglib.m4: New file.
+       * lib/glib_.h: New file, from glib-2.12.4 with modifications.
+       * lib/glibconfig_.h: New file, based on glib-2.12.4.
+       * lib/glib/ghash.c: New file, from glib-2.12.4 with modifications.
+       * lib/glib/ghash_.h: New file, from glib-2.12.4 with modifications.
+       * lib/glib/glist.c: New file, from glib-2.12.4 with modifications.
+       * lib/glib/glist_.h: New file, from glib-2.12.4 with modifications.
+       * lib/glib/gmessages.c: New file.
+       * lib/glib/gprimes.c: New file, from glib-2.12.4 with modifications.
+       * lib/glib/gprimes_.h: New file, from glib-2.12.4 with modifications.
+       * lib/glib/gstrfuncs.c: New file, from glib-2.12.4 with modifications.
+       * lib/glib/gstrfuncs_.h: New file, from glib-2.12.4 with modifications.
+       * lib/glib/gstring.c: New file, from glib-2.12.4 with modifications.
+       * lib/glib/gstring_.h: New file, from glib-2.12.4 with modifications.
+       * lib/glib/gtypes_.h: New file, from glib-2.12.4 with modifications.
+       * Makefile.am (EXTRA_DIST): Add the new files.
+
 2006-11-12  Bruno Haible  <bruno@clisp.org>
 
        * modules/xalloc (Depends-on): Add error, gettext-h, exit.
index dcc38ccdc764c7c4dc5ffb706f6aa92e5a1a48e3..dbd301d01b3e1ef0191c585ffefc55f7c0fc98eb 100644 (file)
@@ -50,6 +50,20 @@ lib/fstrcmp.h \
 lib/gen-lbrkprop.c \
 lib/getopt_.h.diff \
 lib/gettext.h \
+lib/glib_.h \
+lib/glibconfig_.h \
+lib/glib/ghash.c \
+lib/glib/ghash_.h \
+lib/glib/glist.c \
+lib/glib/glist_.h \
+lib/glib/gmessages.c \
+lib/glib/gprimes.c \
+lib/glib/gprimes_.h \
+lib/glib/gstrfuncs.c \
+lib/glib/gstrfuncs_.h \
+lib/glib/gstring.c \
+lib/glib/gstring_.h \
+lib/glib/gtypes_.h \
 lib/hash.c \
 lib/hash.h \
 lib/html-ostream.oo.c \
@@ -183,6 +197,7 @@ m4/ChangeLog.1 \
 m4/exitfail.m4.diff \
 m4/gcj.m4 \
 m4/hard-locale.m4.diff \
+m4/libglib.m4 \
 m4/libxml.m4 \
 m4/java.m4 \
 m4/quotearg.m4.diff \
@@ -212,6 +227,7 @@ modules/html-ostream \
 modules/iconv-ostream \
 modules/java \
 modules/javacomp.diff \
+modules/libglib \
 modules/libxml \
 modules/memory-ostream \
 modules/moo \
diff --git a/gnulib-local/lib/glib/ghash.c b/gnulib-local/lib/glib/ghash.c
new file mode 100644 (file)
index 0000000..d8fdfd5
--- /dev/null
@@ -0,0 +1,816 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+/* 
+ * MT safe
+ */
+
+#include "config.h"
+
+#include "glib.h"
+#if 0
+#include "galias.h"
+#endif
+
+#undef  CLAMP
+#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+
+
+#define HASH_TABLE_MIN_SIZE 11
+#define HASH_TABLE_MAX_SIZE 13845163
+
+
+typedef struct _GHashNode      GHashNode;
+
+struct _GHashNode
+{
+  gpointer   key;
+  gpointer   value;
+  GHashNode *next;
+};
+
+struct _GHashTable
+{
+  gint             size;
+  gint             nnodes;
+  GHashNode      **nodes;
+  GHashFunc        hash_func;
+  GEqualFunc       key_equal_func;
+  volatile guint   ref_count;
+  GDestroyNotify   key_destroy_func;
+  GDestroyNotify   value_destroy_func;
+};
+
+#define G_HASH_TABLE_RESIZE(hash_table)                                \
+   G_STMT_START {                                              \
+     if ((hash_table->size >= 3 * hash_table->nnodes &&                \
+         hash_table->size > HASH_TABLE_MIN_SIZE) ||            \
+        (3 * hash_table->size <= hash_table->nnodes &&         \
+         hash_table->size < HASH_TABLE_MAX_SIZE))              \
+          g_hash_table_resize (hash_table);                    \
+   } G_STMT_END
+
+static void            g_hash_table_resize       (GHashTable     *hash_table);
+static GHashNode**     g_hash_table_lookup_node  (GHashTable     *hash_table,
+                                                   gconstpointer   key);
+static GHashNode*      g_hash_node_new           (gpointer        key,
+                                                   gpointer        value);
+#if 0
+static void            g_hash_node_destroy       (GHashNode      *hash_node,
+                                                   GDestroyNotify  key_destroy_func,
+                                                   GDestroyNotify  value_destroy_func);
+static void            g_hash_nodes_destroy      (GHashNode      *hash_node,
+                                                 GDestroyNotify   key_destroy_func,
+                                                 GDestroyNotify   value_destroy_func);
+static guint g_hash_table_foreach_remove_or_steal (GHashTable     *hash_table,
+                                                   GHRFunc        func,
+                                                   gpointer       user_data,
+                                                   gboolean        notify);
+#endif
+
+
+/**
+ * g_hash_table_new:
+ * @hash_func: a function to create a hash value from a key.
+ *   Hash values are used to determine where keys are stored within the
+ *   #GHashTable data structure. The g_direct_hash(), g_int_hash() and 
+ *   g_str_hash() functions are provided for some common types of keys. 
+ *   If hash_func is %NULL, g_direct_hash() is used.
+ * @key_equal_func: a function to check two keys for equality.  This is
+ *   used when looking up keys in the #GHashTable.  The g_direct_equal(),
+ *   g_int_equal() and g_str_equal() functions are provided for the most
+ *   common types of keys. If @key_equal_func is %NULL, keys are compared
+ *   directly in a similar fashion to g_direct_equal(), but without the
+ *   overhead of a function call.
+ *
+ * Creates a new #GHashTable with a reference count of 1.
+ * 
+ * Return value: a new #GHashTable.
+ **/
+GHashTable*
+g_hash_table_new (GHashFunc    hash_func,
+                 GEqualFunc   key_equal_func)
+{
+  return g_hash_table_new_full (hash_func, key_equal_func, NULL, NULL);
+}
+
+
+/**
+ * g_hash_table_new_full:
+ * @hash_func: a function to create a hash value from a key.
+ * @key_equal_func: a function to check two keys for equality.
+ * @key_destroy_func: a function to free the memory allocated for the key 
+ *   used when removing the entry from the #GHashTable or %NULL if you 
+ *   don't want to supply such a function.
+ * @value_destroy_func: a function to free the memory allocated for the 
+ *   value used when removing the entry from the #GHashTable or %NULL if 
+ *   you don't want to supply such a function.
+ * 
+ * Creates a new #GHashTable like g_hash_table_new() with a reference count
+ * of 1 and allows to specify functions to free the memory allocated for the
+ * key and value that get called when removing the entry from the #GHashTable.
+ * 
+ * Return value: a new #GHashTable.
+ **/
+GHashTable*
+g_hash_table_new_full (GHashFunc       hash_func,
+                      GEqualFunc      key_equal_func,
+                      GDestroyNotify  key_destroy_func,
+                      GDestroyNotify  value_destroy_func)
+{
+  GHashTable *hash_table;
+  
+  hash_table = g_slice_new (GHashTable);
+  hash_table->size               = HASH_TABLE_MIN_SIZE;
+  hash_table->nnodes             = 0;
+  hash_table->hash_func          = hash_func;
+  hash_table->key_equal_func     = key_equal_func;
+  hash_table->ref_count          = 1;
+  hash_table->key_destroy_func   = key_destroy_func;
+  hash_table->value_destroy_func = value_destroy_func;
+  hash_table->nodes              = g_new0 (GHashNode*, hash_table->size);
+  
+  return hash_table;
+}
+
+#if 0
+
+/**
+ * g_hash_table_ref:
+ * @hash_table: a valid #GHashTable.
+ * 
+ * Atomically increments the reference count of @hash_table by one.
+ * This function is MT-safe and may be called from any thread.
+ * 
+ * Return value: the passed in #GHashTable.
+ * 
+ * Since: 2.10
+ **/
+GHashTable*
+g_hash_table_ref (GHashTable *hash_table)
+{
+  g_return_val_if_fail (hash_table != NULL, NULL);
+  g_return_val_if_fail (hash_table->ref_count > 0, hash_table);
+
+  g_atomic_int_add (&hash_table->ref_count, 1);
+  return hash_table;
+}
+
+/**
+ * g_hash_table_unref:
+ * @hash_table: a valid #GHashTable.
+ * 
+ * Atomically decrements the reference count of @hash_table by one.
+ * If the reference count drops to 0, all keys and values will be
+ * destroyed, and all memory allocated by the hash table is released.
+ * This function is MT-safe and may be called from any thread.
+ * 
+ * Since: 2.10
+ **/
+void
+g_hash_table_unref (GHashTable *hash_table)
+{
+  g_return_if_fail (hash_table != NULL);
+  g_return_if_fail (hash_table->ref_count > 0);
+
+  if (g_atomic_int_exchange_and_add (&hash_table->ref_count, -1) - 1 == 0)
+    {
+      gint i;
+
+      for (i = 0; i < hash_table->size; i++)
+        g_hash_nodes_destroy (hash_table->nodes[i], 
+                              hash_table->key_destroy_func,
+                              hash_table->value_destroy_func);
+      g_free (hash_table->nodes);
+      g_slice_free (GHashTable, hash_table);
+    }
+}
+
+/**
+ * g_hash_table_destroy:
+ * @hash_table: a #GHashTable.
+ * 
+ * Destroys all keys and values in the #GHashTable and decrements its
+ * reference count by 1. If keys and/or values are dynamically allocated,
+ * you should either free them first or create the #GHashTable with destroy
+ * notifiers using g_hash_table_new_full(). In the latter case the destroy
+ * functions you supplied will be called on all keys and values during the
+ * destruction phase.
+ **/
+void
+g_hash_table_destroy (GHashTable *hash_table)
+{
+  g_return_if_fail (hash_table != NULL);
+  g_return_if_fail (hash_table->ref_count > 0);
+  
+  g_hash_table_remove_all (hash_table);
+  g_hash_table_unref (hash_table);
+}
+
+#endif
+
+static inline GHashNode**
+g_hash_table_lookup_node (GHashTable   *hash_table,
+                         gconstpointer  key)
+{
+  GHashNode **node;
+  
+  node = &hash_table->nodes
+    [(* hash_table->hash_func) (key) % hash_table->size];
+  
+  /* Hash table lookup needs to be fast.
+   *  We therefore remove the extra conditional of testing
+   *  whether to call the key_equal_func or not from
+   *  the inner loop.
+   */
+  if (hash_table->key_equal_func)
+    while (*node && !(*hash_table->key_equal_func) ((*node)->key, key))
+      node = &(*node)->next;
+  else
+    while (*node && (*node)->key != key)
+      node = &(*node)->next;
+  
+  return node;
+}
+
+/**
+ * g_hash_table_lookup:
+ * @hash_table: a #GHashTable.
+ * @key: the key to look up.
+ * 
+ * Looks up a key in a #GHashTable. Note that this function cannot
+ * distinguish between a key that is not present and one which is present
+ * and has the value %NULL. If you need this distinction, use
+ * g_hash_table_lookup_extended().
+ * 
+ * Return value: the associated value, or %NULL if the key is not found.
+ **/
+gpointer
+g_hash_table_lookup (GHashTable          *hash_table,
+                    gconstpointer key)
+{
+  GHashNode *node;
+  
+  g_return_val_if_fail (hash_table != NULL, NULL);
+  
+  node = *g_hash_table_lookup_node (hash_table, key);
+  
+  return node ? node->value : NULL;
+}
+
+#if 0
+
+/**
+ * g_hash_table_lookup_extended:
+ * @hash_table: a #GHashTable.
+ * @lookup_key: the key to look up.
+ * @orig_key: returns the original key.
+ * @value: returns the value associated with the key.
+ * 
+ * Looks up a key in the #GHashTable, returning the original key and the
+ * associated value and a #gboolean which is %TRUE if the key was found. This 
+ * is useful if you need to free the memory allocated for the original key, 
+ * for example before calling g_hash_table_remove().
+ * 
+ * Return value: %TRUE if the key was found in the #GHashTable.
+ **/
+gboolean
+g_hash_table_lookup_extended (GHashTable    *hash_table,
+                             gconstpointer  lookup_key,
+                             gpointer      *orig_key,
+                             gpointer      *value)
+{
+  GHashNode *node;
+  
+  g_return_val_if_fail (hash_table != NULL, FALSE);
+  
+  node = *g_hash_table_lookup_node (hash_table, lookup_key);
+  
+  if (node)
+    {
+      if (orig_key)
+       *orig_key = node->key;
+      if (value)
+       *value = node->value;
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+#endif
+
+/**
+ * g_hash_table_insert:
+ * @hash_table: a #GHashTable.
+ * @key: a key to insert.
+ * @value: the value to associate with the key.
+ * 
+ * Inserts a new key and value into a #GHashTable.
+ * 
+ * If the key already exists in the #GHashTable its current value is replaced
+ * with the new value. If you supplied a @value_destroy_func when creating the 
+ * #GHashTable, the old value is freed using that function. If you supplied
+ * a @key_destroy_func when creating the #GHashTable, the passed key is freed 
+ * using that function.
+ **/
+void
+g_hash_table_insert (GHashTable *hash_table,
+                    gpointer    key,
+                    gpointer    value)
+{
+  GHashNode **node;
+  
+  g_return_if_fail (hash_table != NULL);
+  g_return_if_fail (hash_table->ref_count > 0);
+  
+  node = g_hash_table_lookup_node (hash_table, key);
+  
+  if (*node)
+    {
+      /* do not reset node->key in this place, keeping
+       * the old key is the intended behaviour. 
+       * g_hash_table_replace() can be used instead.
+       */
+
+      /* free the passed key */
+      if (hash_table->key_destroy_func)
+       hash_table->key_destroy_func (key);
+      
+      if (hash_table->value_destroy_func)
+       hash_table->value_destroy_func ((*node)->value);
+
+      (*node)->value = value;
+    }
+  else
+    {
+      *node = g_hash_node_new (key, value);
+      hash_table->nnodes++;
+      G_HASH_TABLE_RESIZE (hash_table);
+    }
+}
+
+#if 0
+
+/**
+ * g_hash_table_replace:
+ * @hash_table: a #GHashTable.
+ * @key: a key to insert.
+ * @value: the value to associate with the key.
+ * 
+ * Inserts a new key and value into a #GHashTable similar to 
+ * g_hash_table_insert(). The difference is that if the key already exists 
+ * in the #GHashTable, it gets replaced by the new key. If you supplied a 
+ * @value_destroy_func when creating the #GHashTable, the old value is freed 
+ * using that function. If you supplied a @key_destroy_func when creating the 
+ * #GHashTable, the old key is freed using that function. 
+ **/
+void
+g_hash_table_replace (GHashTable *hash_table,
+                     gpointer    key,
+                     gpointer    value)
+{
+  GHashNode **node;
+  
+  g_return_if_fail (hash_table != NULL);
+  g_return_if_fail (hash_table->ref_count > 0);
+  
+  node = g_hash_table_lookup_node (hash_table, key);
+  
+  if (*node)
+    {
+      if (hash_table->key_destroy_func)
+       hash_table->key_destroy_func ((*node)->key);
+      
+      if (hash_table->value_destroy_func)
+       hash_table->value_destroy_func ((*node)->value);
+
+      (*node)->key   = key;
+      (*node)->value = value;
+    }
+  else
+    {
+      *node = g_hash_node_new (key, value);
+      hash_table->nnodes++;
+      G_HASH_TABLE_RESIZE (hash_table);
+    }
+}
+
+/**
+ * g_hash_table_remove:
+ * @hash_table: a #GHashTable.
+ * @key: the key to remove.
+ * 
+ * Removes a key and its associated value from a #GHashTable.
+ *
+ * If the #GHashTable was created using g_hash_table_new_full(), the
+ * key and value are freed using the supplied destroy functions, otherwise
+ * you have to make sure that any dynamically allocated values are freed 
+ * yourself.
+ * 
+ * Return value: %TRUE if the key was found and removed from the #GHashTable.
+ **/
+gboolean
+g_hash_table_remove (GHashTable           *hash_table,
+                    gconstpointer  key)
+{
+  GHashNode **node, *dest;
+  
+  g_return_val_if_fail (hash_table != NULL, FALSE);
+  
+  node = g_hash_table_lookup_node (hash_table, key);
+  if (*node)
+    {
+      dest = *node;
+      (*node) = dest->next;
+      g_hash_node_destroy (dest, 
+                          hash_table->key_destroy_func,
+                          hash_table->value_destroy_func);
+      hash_table->nnodes--;
+  
+      G_HASH_TABLE_RESIZE (hash_table);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/**
+ * g_hash_table_remove_all:
+ * @hash_table: a #GHashTable
+ *
+ * Removes all keys and their associated values from a #GHashTable.
+ *
+ * If the #GHashTable was created using g_hash_table_new_full(), the keys
+ * and values are freed using the supplied destroy functions, otherwise you
+ * have to make sure that any dynamically allocated values are freed
+ * yourself.
+ *
+ * Since: 2.12
+ **/
+void
+g_hash_table_remove_all (GHashTable *hash_table)
+{
+  guint i;
+
+  g_return_if_fail (hash_table != NULL);
+
+  for (i = 0; i < hash_table->size; i++)
+    {
+      g_hash_nodes_destroy (hash_table->nodes[i],
+                            hash_table->key_destroy_func,
+                            hash_table->value_destroy_func);
+      hash_table->nodes[i] = NULL;
+    }
+  hash_table->nnodes = 0;
+  
+  G_HASH_TABLE_RESIZE (hash_table);
+}
+
+/**
+ * g_hash_table_steal:
+ * @hash_table: a #GHashTable.
+ * @key: the key to remove.
+ * 
+ * Removes a key and its associated value from a #GHashTable without
+ * calling the key and value destroy functions.
+ *
+ * Return value: %TRUE if the key was found and removed from the #GHashTable.
+ **/
+gboolean
+g_hash_table_steal (GHashTable    *hash_table,
+                    gconstpointer  key)
+{
+  GHashNode **node, *dest;
+  
+  g_return_val_if_fail (hash_table != NULL, FALSE);
+  
+  node = g_hash_table_lookup_node (hash_table, key);
+  if (*node)
+    {
+      dest = *node;
+      (*node) = dest->next;
+      g_hash_node_destroy (dest, NULL, NULL);
+      hash_table->nnodes--;
+  
+      G_HASH_TABLE_RESIZE (hash_table);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/**
+ * g_hash_table_steal_all:
+ * @hash_table: a #GHashTable.
+ *
+ * Removes all keys and their associated values from a #GHashTable 
+ * without calling the key and value destroy functions.
+ *
+ * Since: 2.12
+ **/
+void
+g_hash_table_steal_all (GHashTable *hash_table)
+{
+  guint i;
+
+  g_return_if_fail (hash_table != NULL);
+
+  for (i = 0; i < hash_table->size; i++)
+    {
+      g_hash_nodes_destroy (hash_table->nodes[i], NULL, NULL);
+      hash_table->nodes[i] = NULL;
+    }
+
+  hash_table->nnodes = 0;
+
+  G_HASH_TABLE_RESIZE (hash_table);
+}
+
+/**
+ * g_hash_table_foreach_remove:
+ * @hash_table: a #GHashTable.
+ * @func: the function to call for each key/value pair.
+ * @user_data: user data to pass to the function.
+ * 
+ * Calls the given function for each key/value pair in the #GHashTable.
+ * If the function returns %TRUE, then the key/value pair is removed from the
+ * #GHashTable. If you supplied key or value destroy functions when creating
+ * the #GHashTable, they are used to free the memory allocated for the removed
+ * keys and values.
+ * 
+ * Return value: the number of key/value pairs removed.
+ **/
+guint
+g_hash_table_foreach_remove (GHashTable        *hash_table,
+                            GHRFunc     func,
+                            gpointer    user_data)
+{
+  g_return_val_if_fail (hash_table != NULL, 0);
+  g_return_val_if_fail (func != NULL, 0);
+  
+  return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, TRUE);
+}
+
+/**
+ * g_hash_table_foreach_steal:
+ * @hash_table: a #GHashTable.
+ * @func: the function to call for each key/value pair.
+ * @user_data: user data to pass to the function.
+ * 
+ * Calls the given function for each key/value pair in the #GHashTable.
+ * If the function returns %TRUE, then the key/value pair is removed from the
+ * #GHashTable, but no key or value destroy functions are called.
+ * 
+ * Return value: the number of key/value pairs removed.
+ **/
+guint
+g_hash_table_foreach_steal (GHashTable *hash_table,
+                            GHRFunc    func,
+                            gpointer   user_data)
+{
+  g_return_val_if_fail (hash_table != NULL, 0);
+  g_return_val_if_fail (func != NULL, 0);
+  
+  return g_hash_table_foreach_remove_or_steal (hash_table, func, user_data, FALSE);
+}
+
+static guint
+g_hash_table_foreach_remove_or_steal (GHashTable *hash_table,
+                                      GHRFunc    func,
+                                      gpointer   user_data,
+                                      gboolean    notify)
+{
+  GHashNode *node, *prev;
+  gint i;
+  guint deleted = 0;
+  
+  for (i = 0; i < hash_table->size; i++)
+    {
+    restart:
+      
+      prev = NULL;
+      
+      for (node = hash_table->nodes[i]; node; prev = node, node = node->next)
+       {
+         if ((* func) (node->key, node->value, user_data))
+           {
+             deleted += 1;
+             
+             hash_table->nnodes -= 1;
+             
+             if (prev)
+               {
+                 prev->next = node->next;
+                 g_hash_node_destroy (node,
+                                      notify ? hash_table->key_destroy_func : NULL,
+                                      notify ? hash_table->value_destroy_func : NULL);
+                 node = prev;
+               }
+             else
+               {
+                 hash_table->nodes[i] = node->next;
+                 g_hash_node_destroy (node,
+                                      notify ? hash_table->key_destroy_func : NULL,
+                                      notify ? hash_table->value_destroy_func : NULL);
+                 goto restart;
+               }
+           }
+       }
+    }
+  
+  G_HASH_TABLE_RESIZE (hash_table);
+  
+  return deleted;
+}
+
+/**
+ * g_hash_table_foreach:
+ * @hash_table: a #GHashTable.
+ * @func: the function to call for each key/value pair.
+ * @user_data: user data to pass to the function.
+ * 
+ * Calls the given function for each of the key/value pairs in the
+ * #GHashTable.  The function is passed the key and value of each
+ * pair, and the given @user_data parameter.  The hash table may not
+ * be modified while iterating over it (you can't add/remove
+ * items). To remove all items matching a predicate, use
+ * g_hash_table_foreach_remove().
+ **/
+void
+g_hash_table_foreach (GHashTable *hash_table,
+                     GHFunc      func,
+                     gpointer    user_data)
+{
+  GHashNode *node;
+  gint i;
+  
+  g_return_if_fail (hash_table != NULL);
+  g_return_if_fail (func != NULL);
+  
+  for (i = 0; i < hash_table->size; i++)
+    for (node = hash_table->nodes[i]; node; node = node->next)
+      (* func) (node->key, node->value, user_data);
+}
+
+/**
+ * g_hash_table_find:
+ * @hash_table: a #GHashTable.
+ * @predicate:  function to test the key/value pairs for a certain property.
+ * @user_data:  user data to pass to the function.
+ * 
+ * Calls the given function for key/value pairs in the #GHashTable until 
+ * @predicate returns %TRUE.  The function is passed the key and value of 
+ * each pair, and the given @user_data parameter. The hash table may not
+ * be modified while iterating over it (you can't add/remove items). 
+ *
+ * Return value: The value of the first key/value pair is returned, for which 
+ * func evaluates to %TRUE. If no pair with the requested property is found, 
+ * %NULL is returned.
+ *
+ * Since: 2.4
+ **/
+gpointer
+g_hash_table_find (GHashTable     *hash_table,
+                   GHRFunc         predicate,
+                   gpointer        user_data)
+{
+  GHashNode *node;
+  gint i;
+  
+  g_return_val_if_fail (hash_table != NULL, NULL);
+  g_return_val_if_fail (predicate != NULL, NULL);
+  
+  for (i = 0; i < hash_table->size; i++)
+    for (node = hash_table->nodes[i]; node; node = node->next)
+      if (predicate (node->key, node->value, user_data))
+        return node->value;       
+  return NULL;
+}
+
+/**
+ * g_hash_table_size:
+ * @hash_table: a #GHashTable.
+ * 
+ * Returns the number of elements contained in the #GHashTable.
+ * 
+ * Return value: the number of key/value pairs in the #GHashTable.
+ **/
+guint
+g_hash_table_size (GHashTable *hash_table)
+{
+  g_return_val_if_fail (hash_table != NULL, 0);
+  
+  return hash_table->nnodes;
+}
+
+#endif
+
+static void
+g_hash_table_resize (GHashTable *hash_table)
+{
+  GHashNode **new_nodes;
+  GHashNode *node;
+  GHashNode *next;
+  guint hash_val;
+  gint new_size;
+  gint i;
+
+  new_size = g_spaced_primes_closest (hash_table->nnodes);
+  new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE);
+  new_nodes = g_new0 (GHashNode*, new_size);
+  
+  for (i = 0; i < hash_table->size; i++)
+    for (node = hash_table->nodes[i]; node; node = next)
+      {
+       next = node->next;
+
+       hash_val = (* hash_table->hash_func) (node->key) % new_size;
+
+       node->next = new_nodes[hash_val];
+       new_nodes[hash_val] = node;
+      }
+  
+  g_free (hash_table->nodes);
+  hash_table->nodes = new_nodes;
+  hash_table->size = new_size;
+}
+
+static GHashNode*
+g_hash_node_new (gpointer key,
+                gpointer value)
+{
+  GHashNode *hash_node = g_slice_new (GHashNode);
+  
+  hash_node->key = key;
+  hash_node->value = value;
+  hash_node->next = NULL;
+  
+  return hash_node;
+}
+
+#if 0
+
+static void
+g_hash_node_destroy (GHashNode      *hash_node,
+                    GDestroyNotify  key_destroy_func,
+                    GDestroyNotify  value_destroy_func)
+{
+  if (key_destroy_func)
+    key_destroy_func (hash_node->key);
+  if (value_destroy_func)
+    value_destroy_func (hash_node->value);
+  g_slice_free (GHashNode, hash_node);
+}
+
+static void
+g_hash_nodes_destroy (GHashNode *hash_node,
+                     GFreeFunc  key_destroy_func,
+                     GFreeFunc  value_destroy_func)
+{
+  while (hash_node)
+    {
+      GHashNode *next = hash_node->next;
+      if (key_destroy_func)
+       key_destroy_func (hash_node->key);
+      if (value_destroy_func)
+       value_destroy_func (hash_node->value);
+      g_slice_free (GHashNode, hash_node);
+      hash_node = next;
+    }
+}
+
+
+#define __G_HASH_C__
+#include "galiasdef.c"
+#endif
diff --git a/gnulib-local/lib/glib/ghash_.h b/gnulib-local/lib/glib/ghash_.h
new file mode 100644 (file)
index 0000000..960c7fc
--- /dev/null
@@ -0,0 +1,132 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#ifndef __G_HASH_H__
+#define __G_HASH_H__
+
+#include <glib/gtypes.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GHashTable  GHashTable;
+
+typedef gboolean  (*GHRFunc)  (gpointer  key,
+                               gpointer  value,
+                               gpointer  user_data);
+
+/* Hash tables
+ */
+GHashTable* g_hash_table_new              (GHashFunc       hash_func,
+                                           GEqualFunc      key_equal_func);
+GHashTable* g_hash_table_new_full                 (GHashFunc       hash_func,
+                                           GEqualFunc      key_equal_func,
+                                           GDestroyNotify  key_destroy_func,
+                                           GDestroyNotify  value_destroy_func);
+#if 0
+void       g_hash_table_destroy           (GHashTable     *hash_table);
+#endif
+void       g_hash_table_insert            (GHashTable     *hash_table,
+                                           gpointer        key,
+                                           gpointer        value);
+#if 0
+void        g_hash_table_replace           (GHashTable     *hash_table,
+                                           gpointer        key,
+                                           gpointer        value);
+gboolean    g_hash_table_remove                   (GHashTable     *hash_table,
+                                           gconstpointer   key);
+void        g_hash_table_remove_all        (GHashTable     *hash_table);
+gboolean    g_hash_table_steal             (GHashTable     *hash_table,
+                                           gconstpointer   key);
+void        g_hash_table_steal_all         (GHashTable     *hash_table);
+#endif
+gpointer    g_hash_table_lookup                   (GHashTable     *hash_table,
+                                           gconstpointer   key);
+#if 0
+gboolean    g_hash_table_lookup_extended   (GHashTable    *hash_table,
+                                           gconstpointer   lookup_key,
+                                           gpointer       *orig_key,
+                                           gpointer       *value);
+void       g_hash_table_foreach           (GHashTable     *hash_table,
+                                           GHFunc          func,
+                                           gpointer        user_data);
+gpointer    g_hash_table_find             (GHashTable     *hash_table,
+                                           GHRFunc         predicate,
+                                           gpointer        user_data);
+guint      g_hash_table_foreach_remove    (GHashTable     *hash_table,
+                                           GHRFunc         func,
+                                           gpointer        user_data);
+guint      g_hash_table_foreach_steal     (GHashTable     *hash_table,
+                                           GHRFunc         func,
+                                           gpointer        user_data);
+guint      g_hash_table_size              (GHashTable     *hash_table);
+
+/* keeping hash tables alive */
+GHashTable* g_hash_table_ref                      (GHashTable     *hash_table);
+void        g_hash_table_unref             (GHashTable     *hash_table);
+
+#ifndef G_DISABLE_DEPRECATED
+
+/* The following two functions are deprecated and will be removed in
+ * the next major release. They do no good. */
+#define g_hash_table_freeze(hash_table) ((void)0)
+#define g_hash_table_thaw(hash_table) ((void)0)
+
+#endif /* G_DISABLE_DEPRECATED */
+
+#endif
+
+/* Hash Functions
+ */
+gboolean g_str_equal (gconstpointer  v1,
+                      gconstpointer  v2);
+guint    g_str_hash  (gconstpointer  v);
+
+#if 0
+
+gboolean g_int_equal (gconstpointer  v1,
+                      gconstpointer  v2);
+guint    g_int_hash  (gconstpointer  v);
+
+/* This "hash" function will just return the key's address as an
+ * unsigned integer. Useful for hashing on plain addresses or
+ * simple integer values.
+ * Passing NULL into g_hash_table_new() as GHashFunc has the
+ * same effect as passing g_direct_hash().
+ */
+guint    g_direct_hash  (gconstpointer  v) G_GNUC_CONST;
+gboolean g_direct_equal (gconstpointer  v1,
+                         gconstpointer  v2) G_GNUC_CONST;
+
+#endif
+
+G_END_DECLS
+
+#endif /* __G_HASH_H__ */
+
diff --git a/gnulib-local/lib/glib/glist.c b/gnulib-local/lib/glib/glist.c
new file mode 100644 (file)
index 0000000..df47827
--- /dev/null
@@ -0,0 +1,688 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+/* 
+ * MT safe
+ */
+
+#include "config.h"
+
+#include "glib.h"
+#if 0
+#include "galias.h"
+#endif
+
+
+#if 0
+void g_list_push_allocator (gpointer dummy) { /* present for binary compat only */ }
+void g_list_pop_allocator  (void)           { /* present for binary compat only */ }
+#endif
+
+#define _g_list_alloc()         g_slice_new (GList)
+#define _g_list_alloc0()        g_slice_new0 (GList)
+#define _g_list_free1(list)     g_slice_free (GList, list)
+
+#if 0
+
+GList*
+g_list_alloc (void)
+{
+  return _g_list_alloc0 ();
+}
+
+#endif
+
+void
+g_list_free (GList *list)
+{
+  while (list)
+    {
+      GList *n = list->next;
+      g_slice_free (GList, list);
+      list = n;
+    }
+}
+
+#if 0
+
+void
+g_list_free_1 (GList *list)
+{
+  _g_list_free1 (list);
+}
+
+#endif
+
+GList*
+g_list_append (GList   *list,
+              gpointer  data)
+{
+  GList *new_list;
+  GList *last;
+  
+  new_list = _g_list_alloc ();
+  new_list->data = data;
+  new_list->next = NULL;
+  
+  if (list)
+    {
+      last = g_list_last (list);
+      /* g_assert (last != NULL); */
+      last->next = new_list;
+      new_list->prev = last;
+
+      return list;
+    }
+  else
+    {
+      new_list->prev = NULL;
+      return new_list;
+    }
+}
+
+GList*
+g_list_prepend (GList   *list,
+               gpointer  data)
+{
+  GList *new_list;
+  
+  new_list = _g_list_alloc ();
+  new_list->data = data;
+  new_list->next = list;
+  
+  if (list)
+    {
+      new_list->prev = list->prev;
+      if (list->prev)
+       list->prev->next = new_list;
+      list->prev = new_list;
+    }
+  else
+    new_list->prev = NULL;
+  
+  return new_list;
+}
+
+#if 0
+
+GList*
+g_list_insert (GList   *list,
+              gpointer  data,
+              gint      position)
+{
+  GList *new_list;
+  GList *tmp_list;
+  
+  if (position < 0)
+    return g_list_append (list, data);
+  else if (position == 0)
+    return g_list_prepend (list, data);
+  
+  tmp_list = g_list_nth (list, position);
+  if (!tmp_list)
+    return g_list_append (list, data);
+  
+  new_list = _g_list_alloc ();
+  new_list->data = data;
+  new_list->prev = tmp_list->prev;
+  if (tmp_list->prev)
+    tmp_list->prev->next = new_list;
+  new_list->next = tmp_list;
+  tmp_list->prev = new_list;
+  
+  if (tmp_list == list)
+    return new_list;
+  else
+    return list;
+}
+
+GList*
+g_list_insert_before (GList   *list,
+                     GList   *sibling,
+                     gpointer data)
+{
+  if (!list)
+    {
+      list = g_list_alloc ();
+      list->data = data;
+      g_return_val_if_fail (sibling == NULL, list);
+      return list;
+    }
+  else if (sibling)
+    {
+      GList *node;
+
+      node = _g_list_alloc ();
+      node->data = data;
+      node->prev = sibling->prev;
+      node->next = sibling;
+      sibling->prev = node;
+      if (node->prev)
+       {
+         node->prev->next = node;
+         return list;
+       }
+      else
+       {
+         g_return_val_if_fail (sibling == list, node);
+         return node;
+       }
+    }
+  else
+    {
+      GList *last;
+
+      last = list;
+      while (last->next)
+       last = last->next;
+
+      last->next = _g_list_alloc ();
+      last->next->data = data;
+      last->next->prev = last;
+      last->next->next = NULL;
+
+      return list;
+    }
+}
+
+GList *
+g_list_concat (GList *list1, GList *list2)
+{
+  GList *tmp_list;
+  
+  if (list2)
+    {
+      tmp_list = g_list_last (list1);
+      if (tmp_list)
+       tmp_list->next = list2;
+      else
+       list1 = list2;
+      list2->prev = tmp_list;
+    }
+  
+  return list1;
+}
+
+GList*
+g_list_remove (GList        *list,
+              gconstpointer  data)
+{
+  GList *tmp;
+  
+  tmp = list;
+  while (tmp)
+    {
+      if (tmp->data != data)
+       tmp = tmp->next;
+      else
+       {
+         if (tmp->prev)
+           tmp->prev->next = tmp->next;
+         if (tmp->next)
+           tmp->next->prev = tmp->prev;
+         
+         if (list == tmp)
+           list = list->next;
+         
+         _g_list_free1 (tmp);
+         
+         break;
+       }
+    }
+  return list;
+}
+
+GList*
+g_list_remove_all (GList       *list,
+                  gconstpointer data)
+{
+  GList *tmp = list;
+
+  while (tmp)
+    {
+      if (tmp->data != data)
+       tmp = tmp->next;
+      else
+       {
+         GList *next = tmp->next;
+
+         if (tmp->prev)
+           tmp->prev->next = next;
+         else
+           list = next;
+         if (next)
+           next->prev = tmp->prev;
+
+         _g_list_free1 (tmp);
+         tmp = next;
+       }
+    }
+  return list;
+}
+
+#endif
+
+static inline GList*
+_g_list_remove_link (GList *list,
+                    GList *link)
+{
+  if (link)
+    {
+      if (link->prev)
+       link->prev->next = link->next;
+      if (link->next)
+       link->next->prev = link->prev;
+      
+      if (link == list)
+       list = list->next;
+      
+      link->next = NULL;
+      link->prev = NULL;
+    }
+  
+  return list;
+}
+
+#if 0
+
+GList*
+g_list_remove_link (GList *list,
+                   GList *link)
+{
+  return _g_list_remove_link (list, link);
+}
+
+#endif
+
+GList*
+g_list_delete_link (GList *list,
+                   GList *link)
+{
+  list = _g_list_remove_link (list, link);
+  _g_list_free1 (link);
+
+  return list;
+}
+
+#if 0
+
+GList*
+g_list_copy (GList *list)
+{
+  GList *new_list = NULL;
+
+  if (list)
+    {
+      GList *last;
+
+      new_list = _g_list_alloc ();
+      new_list->data = list->data;
+      new_list->prev = NULL;
+      last = new_list;
+      list = list->next;
+      while (list)
+       {
+         last->next = _g_list_alloc ();
+         last->next->prev = last;
+         last = last->next;
+         last->data = list->data;
+         list = list->next;
+       }
+      last->next = NULL;
+    }
+
+  return new_list;
+}
+
+GList*
+g_list_reverse (GList *list)
+{
+  GList *last;
+  
+  last = NULL;
+  while (list)
+    {
+      last = list;
+      list = last->next;
+      last->next = last->prev;
+      last->prev = list;
+    }
+  
+  return last;
+}
+
+GList*
+g_list_nth (GList *list,
+           guint  n)
+{
+  while ((n-- > 0) && list)
+    list = list->next;
+  
+  return list;
+}
+
+GList*
+g_list_nth_prev (GList *list,
+                guint  n)
+{
+  while ((n-- > 0) && list)
+    list = list->prev;
+  
+  return list;
+}
+
+gpointer
+g_list_nth_data (GList     *list,
+                guint      n)
+{
+  while ((n-- > 0) && list)
+    list = list->next;
+  
+  return list ? list->data : NULL;
+}
+
+GList*
+g_list_find (GList         *list,
+            gconstpointer  data)
+{
+  while (list)
+    {
+      if (list->data == data)
+       break;
+      list = list->next;
+    }
+  
+  return list;
+}
+
+GList*
+g_list_find_custom (GList         *list,
+                   gconstpointer  data,
+                   GCompareFunc   func)
+{
+  g_return_val_if_fail (func != NULL, list);
+
+  while (list)
+    {
+      if (! func (list->data, data))
+       return list;
+      list = list->next;
+    }
+
+  return NULL;
+}
+
+
+gint
+g_list_position (GList *list,
+                GList *link)
+{
+  gint i;
+
+  i = 0;
+  while (list)
+    {
+      if (list == link)
+       return i;
+      i++;
+      list = list->next;
+    }
+
+  return -1;
+}
+
+gint
+g_list_index (GList         *list,
+             gconstpointer  data)
+{
+  gint i;
+
+  i = 0;
+  while (list)
+    {
+      if (list->data == data)
+       return i;
+      i++;
+      list = list->next;
+    }
+
+  return -1;
+}
+
+#endif
+
+GList*
+g_list_last (GList *list)
+{
+  if (list)
+    {
+      while (list->next)
+       list = list->next;
+    }
+  
+  return list;
+}
+
+#if 0
+
+GList*
+g_list_first (GList *list)
+{
+  if (list)
+    {
+      while (list->prev)
+       list = list->prev;
+    }
+  
+  return list;
+}
+
+guint
+g_list_length (GList *list)
+{
+  guint length;
+  
+  length = 0;
+  while (list)
+    {
+      length++;
+      list = list->next;
+    }
+  
+  return length;
+}
+
+void
+g_list_foreach (GList   *list,
+               GFunc     func,
+               gpointer  user_data)
+{
+  while (list)
+    {
+      GList *next = list->next;
+      (*func) (list->data, user_data);
+      list = next;
+    }
+}
+
+static GList*
+g_list_insert_sorted_real (GList    *list,
+                          gpointer  data,
+                          GFunc     func,
+                          gpointer  user_data)
+{
+  GList *tmp_list = list;
+  GList *new_list;
+  gint cmp;
+
+  g_return_val_if_fail (func != NULL, list);
+  
+  if (!list) 
+    {
+      new_list = _g_list_alloc0 ();
+      new_list->data = data;
+      return new_list;
+    }
+  
+  cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
+
+  while ((tmp_list->next) && (cmp > 0))
+    {
+      tmp_list = tmp_list->next;
+
+      cmp = ((GCompareDataFunc) func) (data, tmp_list->data, user_data);
+    }
+
+  new_list = _g_list_alloc0 ();
+  new_list->data = data;
+
+  if ((!tmp_list->next) && (cmp > 0))
+    {
+      tmp_list->next = new_list;
+      new_list->prev = tmp_list;
+      return list;
+    }
+   
+  if (tmp_list->prev)
+    {
+      tmp_list->prev->next = new_list;
+      new_list->prev = tmp_list->prev;
+    }
+  new_list->next = tmp_list;
+  tmp_list->prev = new_list;
+  if (tmp_list == list)
+    return new_list;
+  else
+    return list;
+}
+
+GList*
+g_list_insert_sorted (GList        *list,
+                     gpointer      data,
+                     GCompareFunc  func)
+{
+  return g_list_insert_sorted_real (list, data, (GFunc) func, NULL);
+}
+
+GList*
+g_list_insert_sorted_with_data (GList            *list,
+                               gpointer          data,
+                               GCompareDataFunc  func,
+                               gpointer          user_data)
+{
+  return g_list_insert_sorted_real (list, data, (GFunc) func, user_data);
+}
+
+static GList *
+g_list_sort_merge (GList     *l1, 
+                  GList     *l2,
+                  GFunc     compare_func,
+                  gpointer  user_data)
+{
+  GList list, *l, *lprev;
+  gint cmp;
+
+  l = &list; 
+  lprev = NULL;
+
+  while (l1 && l2)
+    {
+      cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data);
+
+      if (cmp <= 0)
+        {
+         l->next = l1;
+         l1 = l1->next;
+        } 
+      else 
+       {
+         l->next = l2;
+         l2 = l2->next;
+        }
+      l = l->next;
+      l->prev = lprev; 
+      lprev = l;
+    }
+  l->next = l1 ? l1 : l2;
+  l->next->prev = l;
+
+  return list.next;
+}
+
+static GList* 
+g_list_sort_real (GList    *list,
+                 GFunc     compare_func,
+                 gpointer  user_data)
+{
+  GList *l1, *l2;
+  
+  if (!list) 
+    return NULL;
+  if (!list->next) 
+    return list;
+  
+  l1 = list; 
+  l2 = list->next;
+
+  while ((l2 = l2->next) != NULL)
+    {
+      if ((l2 = l2->next) == NULL) 
+       break;
+      l1 = l1->next;
+    }
+  l2 = l1->next; 
+  l1->next = NULL; 
+
+  return g_list_sort_merge (g_list_sort_real (list, compare_func, user_data),
+                           g_list_sort_real (l2, compare_func, user_data),
+                           compare_func,
+                           user_data);
+}
+
+GList *
+g_list_sort (GList        *list,
+            GCompareFunc  compare_func)
+{
+  return g_list_sort_real (list, (GFunc) compare_func, NULL);
+                           
+}
+
+GList *
+g_list_sort_with_data (GList            *list,
+                      GCompareDataFunc  compare_func,
+                      gpointer          user_data)
+{
+  return g_list_sort_real (list, (GFunc) compare_func, user_data);
+}
+
+#define __G_LIST_C__
+#include "galiasdef.c"
+#endif
diff --git a/gnulib-local/lib/glib/glist_.h b/gnulib-local/lib/glib/glist_.h
new file mode 100644 (file)
index 0000000..2f1e627
--- /dev/null
@@ -0,0 +1,136 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#ifndef __G_LIST_H__
+#define __G_LIST_H__
+
+#if 0
+#include <glib/gmem.h>
+#endif
+
+G_BEGIN_DECLS
+
+typedef struct _GList GList;
+
+struct _GList
+{
+  gpointer data;
+  GList *next;
+  GList *prev;
+};
+
+/* Doubly linked lists
+ */
+#if 0
+GList*   g_list_alloc                   (void) G_GNUC_WARN_UNUSED_RESULT;
+#endif
+void     g_list_free                    (GList            *list);
+#if 0
+void     g_list_free_1                  (GList            *list);
+#define  g_list_free1                   g_list_free_1
+#endif
+GList*   g_list_append                  (GList            *list,
+                                        gpointer          data) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_prepend                 (GList            *list,
+                                        gpointer          data) G_GNUC_WARN_UNUSED_RESULT;
+#if 0
+GList*   g_list_insert                  (GList            *list,
+                                        gpointer          data,
+                                        gint              position) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_insert_sorted           (GList            *list,
+                                        gpointer          data,
+                                        GCompareFunc      func) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_insert_sorted_with_data (GList            *list,
+                                        gpointer          data,
+                                        GCompareDataFunc  func,
+                                        gpointer          user_data) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_insert_before           (GList            *list,
+                                        GList            *sibling,
+                                        gpointer          data) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_concat                  (GList            *list1,
+                                        GList            *list2) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_remove                  (GList            *list,
+                                        gconstpointer     data) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_remove_all              (GList            *list,
+                                        gconstpointer     data) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_remove_link             (GList            *list,
+                                        GList            *llink) G_GNUC_WARN_UNUSED_RESULT;
+#endif
+GList*   g_list_delete_link             (GList            *list,
+                                        GList            *link_) G_GNUC_WARN_UNUSED_RESULT;
+#if 0
+GList*   g_list_reverse                 (GList            *list) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_copy                    (GList            *list) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_nth                     (GList            *list,
+                                        guint             n);
+GList*   g_list_nth_prev                (GList            *list,
+                                        guint             n);
+GList*   g_list_find                    (GList            *list,
+                                        gconstpointer     data);
+GList*   g_list_find_custom             (GList            *list,
+                                        gconstpointer     data,
+                                        GCompareFunc      func);
+gint     g_list_position                (GList            *list,
+                                        GList            *llink);
+gint     g_list_index                   (GList            *list,
+                                        gconstpointer     data);
+#endif
+GList*   g_list_last                    (GList            *list);
+#if 0
+GList*   g_list_first                   (GList            *list);
+guint    g_list_length                  (GList            *list);
+void     g_list_foreach                 (GList            *list,
+                                        GFunc             func,
+                                        gpointer          user_data);
+GList*   g_list_sort                    (GList            *list,
+                                        GCompareFunc      compare_func) G_GNUC_WARN_UNUSED_RESULT;
+GList*   g_list_sort_with_data          (GList            *list,
+                                        GCompareDataFunc  compare_func,
+                                        gpointer          user_data)  G_GNUC_WARN_UNUSED_RESULT;
+gpointer g_list_nth_data                (GList            *list,
+                                        guint             n);
+
+
+#define g_list_previous(list)          ((list) ? (((GList *)(list))->prev) : NULL)
+#endif
+#define g_list_next(list)              ((list) ? (((GList *)(list))->next) : NULL)
+#if 0
+
+#ifndef G_DISABLE_DEPRECATED
+void     g_list_push_allocator          (gpointer          allocator);
+void     g_list_pop_allocator           (void);
+#endif
+
+#endif
+
+G_END_DECLS
+
+#endif /* __G_LIST_H__ */
+
diff --git a/gnulib-local/lib/glib/gmessages.c b/gnulib-local/lib/glib/gmessages.c
new file mode 100644 (file)
index 0000000..c35cbb6
--- /dev/null
@@ -0,0 +1,68 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#include "config.h"
+
+#include "glib.h"
+#include "xvasprintf.h"
+#include <stdio.h>
+
+void
+g_printerr (const gchar *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  vfprintf (stderr, format, args);
+  va_end (args);
+}
+
+void
+g_warning (const gchar *format, ...)
+{
+  va_list args;
+  char *msg;
+
+  va_start (args, format);
+  msg = xvasprintf (format, args);
+  va_end (args);
+
+  fprintf (stderr, "warning: %s", msg);
+}
+
+void
+g_log (const char *domain, int level, const char *format, ...)
+{
+  va_list args;
+
+  va_start (args, format);
+  vfprintf (stderr, format, args);
+  va_end (args);
+}
diff --git a/gnulib-local/lib/glib/gprimes.c b/gnulib-local/lib/glib/gprimes.c
new file mode 100644 (file)
index 0000000..bf4cab4
--- /dev/null
@@ -0,0 +1,98 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+/* 
+ * MT safe
+ */
+
+#include "config.h"
+
+#include "glib.h"
+#if 0
+#include "galias.h"
+#endif
+
+
+static const guint g_primes[] =
+{
+  11,
+  19,
+  37,
+  73,
+  109,
+  163,
+  251,
+  367,
+  557,
+  823,
+  1237,
+  1861,
+  2777,
+  4177,
+  6247,
+  9371,
+  14057,
+  21089,
+  31627,
+  47431,
+  71143,
+  106721,
+  160073,
+  240101,
+  360163,
+  540217,
+  810343,
+  1215497,
+  1823231,
+  2734867,
+  4102283,
+  6153409,
+  9230113,
+  13845163,
+};
+
+static const guint g_nprimes = sizeof (g_primes) / sizeof (g_primes[0]);
+
+guint
+g_spaced_primes_closest (guint num)
+{
+  gint i;
+
+  for (i = 0; i < g_nprimes; i++)
+    if (g_primes[i] > num)
+      return g_primes[i];
+
+  return g_primes[g_nprimes - 1];
+}
+
+#if 0
+#define __G_PRIMES_C__
+#include "galiasdef.c"
+#endif
diff --git a/gnulib-local/lib/glib/gprimes_.h b/gnulib-local/lib/glib/gprimes_.h
new file mode 100644 (file)
index 0000000..7c04d31
--- /dev/null
@@ -0,0 +1,51 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#ifndef __G_PRIMES_H__
+#define __G_PRIMES_H__
+
+#include <glib/gtypes.h>
+
+G_BEGIN_DECLS
+
+/* Prime numbers.
+ */
+
+/* This function returns prime numbers spaced by approximately 1.5-2.0
+ * and is for use in resizing data structures which prefer
+ * prime-valued sizes. The closest spaced prime function returns the
+ * next largest prime, or the highest it knows about which is about
+ * MAXINT/4.
+ */
+guint     g_spaced_primes_closest (guint num) G_GNUC_CONST;
+
+G_END_DECLS
+
+#endif /* __G_PRIMES_H__ */
diff --git a/gnulib-local/lib/glib/gstrfuncs.c b/gnulib-local/lib/glib/gstrfuncs.c
new file mode 100644 (file)
index 0000000..7e0cedd
--- /dev/null
@@ -0,0 +1,2848 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+/*
+ * MT safe
+ */
+
+#include "config.h"
+
+#if 0
+#define _GNU_SOURCE            /* For stpcpy */
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <errno.h>
+#include <ctype.h>             /* For tolower() */
+#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
+#include <signal.h>
+#endif
+
+#include "glib.h"
+#if 0
+#include "gprintf.h"
+#include "gprintfint.h"
+
+#include "galias.h"
+
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+#endif
+
+/* do not include <unistd.h> in this place since it
+ * interferes with g_strsignal() on some OSes
+ */
+
+static const guint16 ascii_table_data[256] = {
+  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
+  0x004, 0x104, 0x104, 0x004, 0x104, 0x104, 0x004, 0x004,
+  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
+  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
+  0x140, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
+  0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
+  0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459,
+  0x459, 0x459, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
+  0x0d0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253,
+  0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
+  0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
+  0x253, 0x253, 0x253, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
+  0x0d0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073,
+  0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
+  0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
+  0x073, 0x073, 0x073, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x004
+  /* the upper 128 are all zeroes */
+};
+
+const guint16 * const g_ascii_table = ascii_table_data;
+
+gchar*
+g_strdup (const gchar *str)
+{
+  gchar *new_str;
+  gsize length;
+
+  if (str)
+    {
+      length = strlen (str) + 1;
+      new_str = g_new (char, length);
+      memcpy (new_str, str, length);
+    }
+  else
+    new_str = NULL;
+
+  return new_str;
+}
+
+#if 0
+
+gpointer
+g_memdup (gconstpointer mem,
+         guint         byte_size)
+{
+  gpointer new_mem;
+
+  if (mem)
+    {
+      new_mem = g_malloc (byte_size);
+      memcpy (new_mem, mem, byte_size);
+    }
+  else
+    new_mem = NULL;
+
+  return new_mem;
+}
+
+#endif
+
+gchar*
+g_strndup (const gchar *str,
+          gsize        n)    
+{
+  gchar *new_str;
+
+  if (str)
+    {
+      new_str = g_new (gchar, n + 1);
+      strncpy (new_str, str, n);
+      new_str[n] = '\0';
+    }
+  else
+    new_str = NULL;
+
+  return new_str;
+}
+
+#if 0
+
+gchar*
+g_strnfill (gsize length,     
+           gchar fill_char)
+{
+  gchar *str;
+
+  str = g_new (gchar, length + 1);
+  memset (str, (guchar)fill_char, length);
+  str[length] = '\0';
+
+  return str;
+}
+
+#endif
+
+/**
+ * g_stpcpy:
+ * @dest: destination buffer.
+ * @src: source string.
+ * 
+ * Copies a nul-terminated string into the dest buffer, include the
+ * trailing nul, and return a pointer to the trailing nul byte.
+ * This is useful for concatenating multiple strings together
+ * without having to repeatedly scan for the end.
+ * 
+ * Return value: a pointer to trailing nul byte.
+ **/
+gchar *
+g_stpcpy (gchar       *dest,
+          const gchar *src)
+{
+#ifdef HAVE_STPCPY
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src != NULL, NULL);
+  return stpcpy (dest, src);
+#else
+  register gchar *d = dest;
+  register const gchar *s = src;
+
+  g_return_val_if_fail (dest != NULL, NULL);
+  g_return_val_if_fail (src != NULL, NULL);
+  do
+    *d++ = *s;
+  while (*s++ != '\0');
+
+  return d - 1;
+#endif
+}
+
+gchar*
+g_strdup_vprintf (const gchar *format,
+                 va_list      args)
+{
+  gchar *string = NULL;
+
+  g_vasprintf (&string, format, args);
+
+  return string;
+}
+
+gchar*
+g_strdup_printf (const gchar *format,
+                ...)
+{
+  gchar *buffer;
+  va_list args;
+
+  va_start (args, format);
+  buffer = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  return buffer;
+}
+
+gchar*
+g_strconcat (const gchar *string1, ...)
+{
+  gsize          l;     
+  va_list args;
+  gchar          *s;
+  gchar          *concat;
+  gchar   *ptr;
+
+  if (!string1)
+    return NULL;
+
+  l = 1 + strlen (string1);
+  va_start (args, string1);
+  s = va_arg (args, gchar*);
+  while (s)
+    {
+      l += strlen (s);
+      s = va_arg (args, gchar*);
+    }
+  va_end (args);
+
+  concat = g_new (gchar, l);
+  ptr = concat;
+
+  ptr = g_stpcpy (ptr, string1);
+  va_start (args, string1);
+  s = va_arg (args, gchar*);
+  while (s)
+    {
+      ptr = g_stpcpy (ptr, s);
+      s = va_arg (args, gchar*);
+    }
+  va_end (args);
+
+  return concat;
+}
+
+#if 0
+
+/**
+ * g_strtod:
+ * @nptr:    the string to convert to a numeric value.
+ * @endptr:  if non-%NULL, it returns the character after
+ *           the last character used in the conversion.
+ * 
+ * Converts a string to a #gdouble value.
+ * It calls the standard strtod() function to handle the conversion, but
+ * if the string is not completely converted it attempts the conversion
+ * again with g_ascii_strtod(), and returns the best match.
+ *
+ * This function should seldomly be used. The normal situation when reading
+ * numbers not for human consumption is to use g_ascii_strtod(). Only when
+ * you know that you must expect both locale formatted and C formatted numbers
+ * should you use this. Make sure that you don't pass strings such as comma
+ * separated lists of values, since the commas may be interpreted as a decimal
+ * point in some locales, causing unexpected results.
+ * 
+ * Return value: the #gdouble value.
+ **/
+gdouble
+g_strtod (const gchar *nptr,
+         gchar      **endptr)
+{
+  gchar *fail_pos_1;
+  gchar *fail_pos_2;
+  gdouble val_1;
+  gdouble val_2 = 0;
+
+  g_return_val_if_fail (nptr != NULL, 0);
+
+  fail_pos_1 = NULL;
+  fail_pos_2 = NULL;
+
+  val_1 = strtod (nptr, &fail_pos_1);
+
+  if (fail_pos_1 && fail_pos_1[0] != 0)
+    val_2 = g_ascii_strtod (nptr, &fail_pos_2);
+
+  if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
+    {
+      if (endptr)
+       *endptr = fail_pos_1;
+      return val_1;
+    }
+  else
+    {
+      if (endptr)
+       *endptr = fail_pos_2;
+      return val_2;
+    }
+}
+
+/**
+ * g_ascii_strtod:
+ * @nptr:    the string to convert to a numeric value.
+ * @endptr:  if non-%NULL, it returns the character after
+ *           the last character used in the conversion.
+ * 
+ * Converts a string to a #gdouble value.
+ * This function behaves like the standard strtod() function
+ * does in the C locale. It does this without actually
+ * changing the current locale, since that would not be
+ * thread-safe.
+ *
+ * This function is typically used when reading configuration
+ * files or other non-user input that should be locale independent.
+ * To handle input from the user you should normally use the
+ * locale-sensitive system strtod() function.
+ *
+ * To convert from a #gdouble to a string in a locale-insensitive
+ * way, use g_ascii_dtostr().
+ *
+ * If the correct value would cause overflow, plus or minus %HUGE_VAL
+ * is returned (according to the sign of the value), and %ERANGE is
+ * stored in %errno. If the correct value would cause underflow,
+ * zero is returned and %ERANGE is stored in %errno.
+ * 
+ * This function resets %errno before calling strtod() so that
+ * you can reliably detect overflow and underflow.
+ *
+ * Return value: the #gdouble value.
+ **/
+gdouble
+g_ascii_strtod (const gchar *nptr,
+               gchar      **endptr)
+{
+  gchar *fail_pos;
+  gdouble val;
+  struct lconv *locale_data;
+  const char *decimal_point;
+  int decimal_point_len;
+  const char *p, *decimal_point_pos;
+  const char *end = NULL; /* Silence gcc */
+  int strtod_errno;
+
+  g_return_val_if_fail (nptr != NULL, 0);
+
+  fail_pos = NULL;
+
+  locale_data = localeconv ();
+  decimal_point = locale_data->decimal_point;
+  decimal_point_len = strlen (decimal_point);
+
+  g_assert (decimal_point_len != 0);
+  
+  decimal_point_pos = NULL;
+  end = NULL;
+
+  if (decimal_point[0] != '.' || 
+      decimal_point[1] != 0)
+    {
+      p = nptr;
+      /* Skip leading space */
+      while (g_ascii_isspace (*p))
+       p++;
+      
+      /* Skip leading optional sign */
+      if (*p == '+' || *p == '-')
+       p++;
+      
+      if (p[0] == '0' && 
+         (p[1] == 'x' || p[1] == 'X'))
+       {
+         p += 2;
+         /* HEX - find the (optional) decimal point */
+         
+         while (g_ascii_isxdigit (*p))
+           p++;
+         
+         if (*p == '.')
+           decimal_point_pos = p++;
+             
+         while (g_ascii_isxdigit (*p))
+           p++;
+         
+         if (*p == 'p' || *p == 'P')
+           p++;
+         if (*p == '+' || *p == '-')
+           p++;
+         while (g_ascii_isdigit (*p))
+           p++;
+
+         end = p;
+       }
+      else if (g_ascii_isdigit (*p) || *p == '.')
+       {
+         while (g_ascii_isdigit (*p))
+           p++;
+         
+         if (*p == '.')
+           decimal_point_pos = p++;
+         
+         while (g_ascii_isdigit (*p))
+           p++;
+         
+         if (*p == 'e' || *p == 'E')
+           p++;
+         if (*p == '+' || *p == '-')
+           p++;
+         while (g_ascii_isdigit (*p))
+           p++;
+
+         end = p;
+       }
+      /* For the other cases, we need not convert the decimal point */
+    }
+
+  if (decimal_point_pos)
+    {
+      char *copy, *c;
+
+      /* We need to convert the '.' to the locale specific decimal point */
+      copy = g_malloc (end - nptr + 1 + decimal_point_len);
+      
+      c = copy;
+      memcpy (c, nptr, decimal_point_pos - nptr);
+      c += decimal_point_pos - nptr;
+      memcpy (c, decimal_point, decimal_point_len);
+      c += decimal_point_len;
+      memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
+      c += end - (decimal_point_pos + 1);
+      *c = 0;
+
+      errno = 0;
+      val = strtod (copy, &fail_pos);
+      strtod_errno = errno;
+
+      if (fail_pos)
+       {
+         if (fail_pos - copy > decimal_point_pos - nptr)
+           fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
+         else
+           fail_pos = (char *)nptr + (fail_pos - copy);
+       }
+      
+      g_free (copy);
+         
+    }
+  else if (end)
+    {
+      char *copy;
+      
+      copy = g_malloc (end - (char *)nptr + 1);
+      memcpy (copy, nptr, end - nptr);
+      *(copy + (end - (char *)nptr)) = 0;
+      
+      errno = 0;
+      val = strtod (copy, &fail_pos);
+      strtod_errno = errno;
+
+      if (fail_pos)
+       {
+         fail_pos = (char *)nptr + (fail_pos - copy);
+       }
+      
+      g_free (copy);
+    }
+  else
+    {
+      errno = 0;
+      val = strtod (nptr, &fail_pos);
+      strtod_errno = errno;
+    }
+
+  if (endptr)
+    *endptr = fail_pos;
+
+  errno = strtod_errno;
+
+  return val;
+}
+
+
+/**
+ * g_ascii_dtostr:
+ * @buffer: A buffer to place the resulting string in
+ * @buf_len: The length of the buffer.
+ * @d: The #gdouble to convert
+ *
+ * Converts a #gdouble to a string, using the '.' as
+ * decimal point. 
+ * 
+ * This functions generates enough precision that converting
+ * the string back using g_ascii_strtod() gives the same machine-number
+ * (on machines with IEEE compatible 64bit doubles). It is
+ * guaranteed that the size of the resulting string will never
+ * be larger than @G_ASCII_DTOSTR_BUF_SIZE bytes.
+ *
+ * Return value: The pointer to the buffer with the converted string.
+ **/
+gchar *
+g_ascii_dtostr (gchar       *buffer,
+               gint         buf_len,
+               gdouble      d)
+{
+  return g_ascii_formatd (buffer, buf_len, "%.17g", d);
+}
+
+/**
+ * g_ascii_formatd:
+ * @buffer: A buffer to place the resulting string in
+ * @buf_len: The length of the buffer.
+ * @format: The printf()-style format to use for the
+ *          code to use for converting. 
+ * @d: The #gdouble to convert
+ *
+ * Converts a #gdouble to a string, using the '.' as
+ * decimal point. To format the number you pass in
+ * a printf()-style format string. Allowed conversion
+ * specifiers are 'e', 'E', 'f', 'F', 'g' and 'G'. 
+ * 
+ * If you just want to want to serialize the value into a
+ * string, use g_ascii_dtostr().
+ *
+ * Return value: The pointer to the buffer with the converted string.
+ **/
+gchar *
+g_ascii_formatd (gchar       *buffer,
+                gint         buf_len,
+                const gchar *format,
+                gdouble      d)
+{
+  struct lconv *locale_data;
+  const char *decimal_point;
+  int decimal_point_len;
+  gchar *p;
+  int rest_len;
+  gchar format_char;
+
+  g_return_val_if_fail (buffer != NULL, NULL);
+  g_return_val_if_fail (format[0] == '%', NULL);
+  g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL);
+  format_char = format[strlen (format) - 1];
+  
+  g_return_val_if_fail (format_char == 'e' || format_char == 'E' ||
+                       format_char == 'f' || format_char == 'F' ||
+                       format_char == 'g' || format_char == 'G',
+                       NULL);
+
+  if (format[0] != '%')
+    return NULL;
+
+  if (strpbrk (format + 1, "'l%"))
+    return NULL;
+
+  if (!(format_char == 'e' || format_char == 'E' ||
+       format_char == 'f' || format_char == 'F' ||
+       format_char == 'g' || format_char == 'G'))
+    return NULL;
+
+      
+  _g_snprintf (buffer, buf_len, format, d);
+
+  locale_data = localeconv ();
+  decimal_point = locale_data->decimal_point;
+  decimal_point_len = strlen (decimal_point);
+
+  g_assert (decimal_point_len != 0);
+
+  if (decimal_point[0] != '.' ||
+      decimal_point[1] != 0)
+    {
+      p = buffer;
+
+      while (g_ascii_isspace (*p))
+       p++;
+
+      if (*p == '+' || *p == '-')
+       p++;
+
+      while (isdigit ((guchar)*p))
+       p++;
+
+      if (strncmp (p, decimal_point, decimal_point_len) == 0)
+       {
+         *p = '.';
+         p++;
+         if (decimal_point_len > 1) {
+           rest_len = strlen (p + (decimal_point_len-1));
+           memmove (p, p + (decimal_point_len-1),
+                    rest_len);
+           p[rest_len] = 0;
+           
+         }
+       }
+    }
+  
+  return buffer;
+}
+
+static guint64
+g_parse_long_long (const gchar *nptr,
+                  gchar      **endptr,
+                  guint        base,
+                  gboolean    *negative)
+{
+  /* this code is based on on the strtol(3) code from GNU libc released under
+   * the GNU Lesser General Public License.
+   *
+   * Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02
+   *        Free Software Foundation, Inc.
+   */
+#define ISSPACE(c)             ((c) == ' ' || (c) == '\f' || (c) == '\n' || \
+                                (c) == '\r' || (c) == '\t' || (c) == '\v')
+#define ISUPPER(c)             ((c) >= 'A' && (c) <= 'Z')
+#define ISLOWER(c)             ((c) >= 'a' && (c) <= 'z')
+#define ISALPHA(c)             (ISUPPER (c) || ISLOWER (c))
+#define        TOUPPER(c)              (ISLOWER (c) ? (c) - 'a' + 'A' : (c))
+#define        TOLOWER(c)              (ISUPPER (c) ? (c) - 'A' + 'a' : (c))
+  gboolean overflow;
+  guint64 cutoff;
+  guint64 cutlim;
+  guint64 ui64;
+  const gchar *s, *save;
+  guchar c;
+  
+  g_return_val_if_fail (nptr != NULL, 0);
+  
+  if (base == 1 || base > 36)
+    {
+      errno = EINVAL;
+      return 0;
+    }
+  
+  save = s = nptr;
+  
+  /* Skip white space.  */
+  while (ISSPACE (*s))
+    ++s;
+
+  if (G_UNLIKELY (!*s))
+    goto noconv;
+  
+  /* Check for a sign.  */
+  *negative = FALSE;
+  if (*s == '-')
+    {
+      *negative = TRUE;
+      ++s;
+    }
+  else if (*s == '+')
+    ++s;
+  
+  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
+  if (*s == '0')
+    {
+      if ((base == 0 || base == 16) && TOUPPER (s[1]) == 'X')
+       {
+         s += 2;
+         base = 16;
+       }
+      else if (base == 0)
+       base = 8;
+    }
+  else if (base == 0)
+    base = 10;
+  
+  /* Save the pointer so we can check later if anything happened.  */
+  save = s;
+  cutoff = G_MAXUINT64 / base;
+  cutlim = G_MAXUINT64 % base;
+  
+  overflow = FALSE;
+  ui64 = 0;
+  c = *s;
+  for (; c; c = *++s)
+    {
+      if (c >= '0' && c <= '9')
+       c -= '0';
+      else if (ISALPHA (c))
+       c = TOUPPER (c) - 'A' + 10;
+      else
+       break;
+      if (c >= base)
+       break;
+      /* Check for overflow.  */
+      if (ui64 > cutoff || (ui64 == cutoff && c > cutlim))
+       overflow = TRUE;
+      else
+       {
+         ui64 *= base;
+         ui64 += c;
+       }
+    }
+  
+  /* Check if anything actually happened.  */
+  if (s == save)
+    goto noconv;
+  
+  /* Store in ENDPTR the address of one character
+     past the last character we converted.  */
+  if (endptr)
+    *endptr = (gchar*) s;
+  
+  if (G_UNLIKELY (overflow))
+    {
+      errno = ERANGE;
+      return G_MAXUINT64;
+    }
+
+  return ui64;
+  
+ noconv:
+  /* We must handle a special case here: the base is 0 or 16 and the
+     first two characters are '0' and 'x', but the rest are no
+     hexadecimal digits.  This is no error case.  We return 0 and
+     ENDPTR points to the `x`.  */
+  if (endptr)
+    {
+      if (save - nptr >= 2 && TOUPPER (save[-1]) == 'X'
+         && save[-2] == '0')
+       *endptr = (gchar*) &save[-1];
+      else
+       /*  There was no number to convert.  */
+       *endptr = (gchar*) nptr;
+    }
+  return 0;
+}
+
+/**
+ * g_ascii_strtoull:
+ * @nptr:    the string to convert to a numeric value.
+ * @endptr:  if non-%NULL, it returns the character after
+ *           the last character used in the conversion.
+ * @base:    to be used for the conversion, 2..36 or 0
+ *
+ * Converts a string to a #guint64 value.
+ * This function behaves like the standard strtoull() function
+ * does in the C locale. It does this without actually
+ * changing the current locale, since that would not be
+ * thread-safe.
+ *
+ * This function is typically used when reading configuration
+ * files or other non-user input that should be locale independent.
+ * To handle input from the user you should normally use the
+ * locale-sensitive system strtoull() function.
+ *
+ * If the correct value would cause overflow, %G_MAXUINT64
+ * is returned, and %ERANGE is stored in %errno.  If the base is
+ * outside the valid range, zero is returned, and %EINVAL is stored
+ * in %errno.  If the string conversion fails, zero is returned, and
+ * @endptr returns @nptr (if @endptr is non-%NULL).
+ *
+ * Return value: the #guint64 value or zero on error.
+ *
+ * Since: 2.2
+ **/
+guint64
+g_ascii_strtoull (const gchar *nptr,
+                 gchar      **endptr,
+                 guint        base)
+{
+  gboolean negative;
+  guint64 result;
+
+  result = g_parse_long_long (nptr, endptr, base, &negative);
+
+  /* Return the result of the appropriate sign.  */
+  return negative ? -result : result;
+}
+
+/**
+ * g_ascii_strtoll:
+ * @nptr:    the string to convert to a numeric value.
+ * @endptr:  if non-%NULL, it returns the character after
+ *           the last character used in the conversion.
+ * @base:    to be used for the conversion, 2..36 or 0
+ *
+ * Converts a string to a #gint64 value.
+ * This function behaves like the standard strtoll() function
+ * does in the C locale. It does this without actually
+ * changing the current locale, since that would not be
+ * thread-safe.
+ *
+ * This function is typically used when reading configuration
+ * files or other non-user input that should be locale independent.
+ * To handle input from the user you should normally use the
+ * locale-sensitive system strtoll() function.
+ *
+ * If the correct value would cause overflow, %G_MAXINT64 or %G_MININT64
+ * is returned, and %ERANGE is stored in %errno.  If the base is
+ * outside the valid range, zero is returned, and %EINVAL is stored
+ * in %errno.  If the string conversion fails, zero is returned, and
+ * @endptr returns @nptr (if @endptr is non-%NULL).
+ *
+ * Return value: the #gint64 value or zero on error.
+ *
+ * Since: 2.12
+ **/
+gint64 
+g_ascii_strtoll (const gchar *nptr,
+                gchar      **endptr,
+                guint        base)
+{
+  gboolean negative;
+  guint64 result;
+
+  result = g_parse_long_long (nptr, endptr, base, &negative);
+
+  if (negative && result > (guint64) G_MININT64)
+    {
+      errno = ERANGE;
+      return G_MININT64;
+    }
+  else if (!negative && result > (guint64) G_MAXINT64)
+    {
+      errno = ERANGE;
+      return G_MAXINT64;
+    }
+  else
+    return (gint64) result;
+}
+
+G_CONST_RETURN gchar*
+g_strerror (gint errnum)
+{
+  static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
+  char *msg;
+  int saved_errno = errno;
+
+#ifdef HAVE_STRERROR
+  const char *msg_locale;
+
+  msg_locale = strerror (errnum);
+  if (g_get_charset (NULL))
+    {
+      errno = saved_errno;
+      return msg_locale;
+    }
+  else
+    {
+      gchar *msg_utf8 = g_locale_to_utf8 (msg_locale, -1, NULL, NULL, NULL);
+      if (msg_utf8)
+       {
+         /* Stick in the quark table so that we can return a static result
+          */
+         GQuark msg_quark = g_quark_from_string (msg_utf8);
+         g_free (msg_utf8);
+         
+         msg_utf8 = (gchar *) g_quark_to_string (msg_quark);
+         errno = saved_errno;
+         return msg_utf8;
+       }
+    }
+#elif NO_SYS_ERRLIST
+  switch (errnum)
+    {
+#ifdef E2BIG
+    case E2BIG: return "argument list too long";
+#endif
+#ifdef EACCES
+    case EACCES: return "permission denied";
+#endif
+#ifdef EADDRINUSE
+    case EADDRINUSE: return "address already in use";
+#endif
+#ifdef EADDRNOTAVAIL
+    case EADDRNOTAVAIL: return "can't assign requested address";
+#endif
+#ifdef EADV
+    case EADV: return "advertise error";
+#endif
+#ifdef EAFNOSUPPORT
+    case EAFNOSUPPORT: return "address family not supported by protocol family";
+#endif
+#ifdef EAGAIN
+    case EAGAIN: return "try again";
+#endif
+#ifdef EALIGN
+    case EALIGN: return "EALIGN";
+#endif
+#ifdef EALREADY
+    case EALREADY: return "operation already in progress";
+#endif
+#ifdef EBADE
+    case EBADE: return "bad exchange descriptor";
+#endif
+#ifdef EBADF
+    case EBADF: return "bad file number";
+#endif
+#ifdef EBADFD
+    case EBADFD: return "file descriptor in bad state";
+#endif
+#ifdef EBADMSG
+    case EBADMSG: return "not a data message";
+#endif
+#ifdef EBADR
+    case EBADR: return "bad request descriptor";
+#endif
+#ifdef EBADRPC
+    case EBADRPC: return "RPC structure is bad";
+#endif
+#ifdef EBADRQC
+    case EBADRQC: return "bad request code";
+#endif
+#ifdef EBADSLT
+    case EBADSLT: return "invalid slot";
+#endif
+#ifdef EBFONT
+    case EBFONT: return "bad font file format";
+#endif
+#ifdef EBUSY
+    case EBUSY: return "mount device busy";
+#endif
+#ifdef ECHILD
+    case ECHILD: return "no children";
+#endif
+#ifdef ECHRNG
+    case ECHRNG: return "channel number out of range";
+#endif
+#ifdef ECOMM
+    case ECOMM: return "communication error on send";
+#endif
+#ifdef ECONNABORTED
+    case ECONNABORTED: return "software caused connection abort";
+#endif
+#ifdef ECONNREFUSED
+    case ECONNREFUSED: return "connection refused";
+#endif
+#ifdef ECONNRESET
+    case ECONNRESET: return "connection reset by peer";
+#endif
+#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
+    case EDEADLK: return "resource deadlock avoided";
+#endif
+#ifdef EDEADLOCK
+    case EDEADLOCK: return "resource deadlock avoided";
+#endif
+#ifdef EDESTADDRREQ
+    case EDESTADDRREQ: return "destination address required";
+#endif
+#ifdef EDIRTY
+    case EDIRTY: return "mounting a dirty fs w/o force";
+#endif
+#ifdef EDOM
+    case EDOM: return "math argument out of range";
+#endif
+#ifdef EDOTDOT
+    case EDOTDOT: return "cross mount point";
+#endif
+#ifdef EDQUOT
+    case EDQUOT: return "disk quota exceeded";
+#endif
+#ifdef EDUPPKG
+    case EDUPPKG: return "duplicate package name";
+#endif
+#ifdef EEXIST
+    case EEXIST: return "file already exists";
+#endif
+#ifdef EFAULT
+    case EFAULT: return "bad address in system call argument";
+#endif
+#ifdef EFBIG
+    case EFBIG: return "file too large";
+#endif
+#ifdef EHOSTDOWN
+    case EHOSTDOWN: return "host is down";
+#endif
+#ifdef EHOSTUNREACH
+    case EHOSTUNREACH: return "host is unreachable";
+#endif
+#ifdef EIDRM
+    case EIDRM: return "identifier removed";
+#endif
+#ifdef EINIT
+    case EINIT: return "initialization error";
+#endif
+#ifdef EINPROGRESS
+    case EINPROGRESS: return "operation now in progress";
+#endif
+#ifdef EINTR
+    case EINTR: return "interrupted system call";
+#endif
+#ifdef EINVAL
+    case EINVAL: return "invalid argument";
+#endif
+#ifdef EIO
+    case EIO: return "I/O error";
+#endif
+#ifdef EISCONN
+    case EISCONN: return "socket is already connected";
+#endif
+#ifdef EISDIR
+    case EISDIR: return "is a directory";
+#endif
+#ifdef EISNAME
+    case EISNAM: return "is a name file";
+#endif
+#ifdef ELBIN
+    case ELBIN: return "ELBIN";
+#endif
+#ifdef EL2HLT
+    case EL2HLT: return "level 2 halted";
+#endif
+#ifdef EL2NSYNC
+    case EL2NSYNC: return "level 2 not synchronized";
+#endif
+#ifdef EL3HLT
+    case EL3HLT: return "level 3 halted";
+#endif
+#ifdef EL3RST
+    case EL3RST: return "level 3 reset";
+#endif
+#ifdef ELIBACC
+    case ELIBACC: return "can not access a needed shared library";
+#endif
+#ifdef ELIBBAD
+    case ELIBBAD: return "accessing a corrupted shared library";
+#endif
+#ifdef ELIBEXEC
+    case ELIBEXEC: return "can not exec a shared library directly";
+#endif
+#ifdef ELIBMAX
+    case ELIBMAX: return "attempting to link in more shared libraries than system limit";
+#endif
+#ifdef ELIBSCN
+    case ELIBSCN: return ".lib section in a.out corrupted";
+#endif
+#ifdef ELNRNG
+    case ELNRNG: return "link number out of range";
+#endif
+#ifdef ELOOP
+    case ELOOP: return "too many levels of symbolic links";
+#endif
+#ifdef EMFILE
+    case EMFILE: return "too many open files";
+#endif
+#ifdef EMLINK
+    case EMLINK: return "too many links";
+#endif
+#ifdef EMSGSIZE
+    case EMSGSIZE: return "message too long";
+#endif
+#ifdef EMULTIHOP
+    case EMULTIHOP: return "multihop attempted";
+#endif
+#ifdef ENAMETOOLONG
+    case ENAMETOOLONG: return "file name too long";
+#endif
+#ifdef ENAVAIL
+    case ENAVAIL: return "not available";
+#endif
+#ifdef ENET
+    case ENET: return "ENET";
+#endif
+#ifdef ENETDOWN
+    case ENETDOWN: return "network is down";
+#endif
+#ifdef ENETRESET
+    case ENETRESET: return "network dropped connection on reset";
+#endif
+#ifdef ENETUNREACH
+    case ENETUNREACH: return "network is unreachable";
+#endif
+#ifdef ENFILE
+    case ENFILE: return "file table overflow";
+#endif
+#ifdef ENOANO
+    case ENOANO: return "anode table overflow";
+#endif
+#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
+    case ENOBUFS: return "no buffer space available";
+#endif
+#ifdef ENOCSI
+    case ENOCSI: return "no CSI structure available";
+#endif
+#ifdef ENODATA
+    case ENODATA: return "no data available";
+#endif
+#ifdef ENODEV
+    case ENODEV: return "no such device";
+#endif
+#ifdef ENOENT
+    case ENOENT: return "no such file or directory";
+#endif
+#ifdef ENOEXEC
+    case ENOEXEC: return "exec format error";
+#endif
+#ifdef ENOLCK
+    case ENOLCK: return "no locks available";
+#endif
+#ifdef ENOLINK
+    case ENOLINK: return "link has be severed";
+#endif
+#ifdef ENOMEM
+    case ENOMEM: return "not enough memory";
+#endif
+#ifdef ENOMSG
+    case ENOMSG: return "no message of desired type";
+#endif
+#ifdef ENONET
+    case ENONET: return "machine is not on the network";
+#endif
+#ifdef ENOPKG
+    case ENOPKG: return "package not installed";
+#endif
+#ifdef ENOPROTOOPT
+    case ENOPROTOOPT: return "bad proocol option";
+#endif
+#ifdef ENOSPC
+    case ENOSPC: return "no space left on device";
+#endif
+#ifdef ENOSR
+    case ENOSR: return "out of stream resources";
+#endif
+#ifdef ENOSTR
+    case ENOSTR: return "not a stream device";
+#endif
+#ifdef ENOSYM
+    case ENOSYM: return "unresolved symbol name";
+#endif
+#ifdef ENOSYS
+    case ENOSYS: return "function not implemented";
+#endif
+#ifdef ENOTBLK
+    case ENOTBLK: return "block device required";
+#endif
+#ifdef ENOTCONN
+    case ENOTCONN: return "socket is not connected";
+#endif
+#ifdef ENOTDIR
+    case ENOTDIR: return "not a directory";
+#endif
+#ifdef ENOTEMPTY
+    case ENOTEMPTY: return "directory not empty";
+#endif
+#ifdef ENOTNAM
+    case ENOTNAM: return "not a name file";
+#endif
+#ifdef ENOTSOCK
+    case ENOTSOCK: return "socket operation on non-socket";
+#endif
+#ifdef ENOTTY
+    case ENOTTY: return "inappropriate device for ioctl";
+#endif
+#ifdef ENOTUNIQ
+    case ENOTUNIQ: return "name not unique on network";
+#endif
+#ifdef ENXIO
+    case ENXIO: return "no such device or address";
+#endif
+#ifdef EOPNOTSUPP
+    case EOPNOTSUPP: return "operation not supported on socket";
+#endif
+#ifdef EPERM
+    case EPERM: return "not owner";
+#endif
+#ifdef EPFNOSUPPORT
+    case EPFNOSUPPORT: return "protocol family not supported";
+#endif
+#ifdef EPIPE
+    case EPIPE: return "broken pipe";
+#endif
+#ifdef EPROCLIM
+    case EPROCLIM: return "too many processes";
+#endif
+#ifdef EPROCUNAVAIL
+    case EPROCUNAVAIL: return "bad procedure for program";
+#endif
+#ifdef EPROGMISMATCH
+    case EPROGMISMATCH: return "program version wrong";
+#endif
+#ifdef EPROGUNAVAIL
+    case EPROGUNAVAIL: return "RPC program not available";
+#endif
+#ifdef EPROTO
+    case EPROTO: return "protocol error";
+#endif
+#ifdef EPROTONOSUPPORT
+    case EPROTONOSUPPORT: return "protocol not suppored";
+#endif
+#ifdef EPROTOTYPE
+    case EPROTOTYPE: return "protocol wrong type for socket";
+#endif
+#ifdef ERANGE
+    case ERANGE: return "math result unrepresentable";
+#endif
+#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
+    case EREFUSED: return "EREFUSED";
+#endif
+#ifdef EREMCHG
+    case EREMCHG: return "remote address changed";
+#endif
+#ifdef EREMDEV
+    case EREMDEV: return "remote device";
+#endif
+#ifdef EREMOTE
+    case EREMOTE: return "pathname hit remote file system";
+#endif
+#ifdef EREMOTEIO
+    case EREMOTEIO: return "remote i/o error";
+#endif
+#ifdef EREMOTERELEASE
+    case EREMOTERELEASE: return "EREMOTERELEASE";
+#endif
+#ifdef EROFS
+    case EROFS: return "read-only file system";
+#endif
+#ifdef ERPCMISMATCH
+    case ERPCMISMATCH: return "RPC version is wrong";
+#endif
+#ifdef ERREMOTE
+    case ERREMOTE: return "object is remote";
+#endif
+#ifdef ESHUTDOWN
+    case ESHUTDOWN: return "can't send afer socket shutdown";
+#endif
+#ifdef ESOCKTNOSUPPORT
+    case ESOCKTNOSUPPORT: return "socket type not supported";
+#endif
+#ifdef ESPIPE
+    case ESPIPE: return "invalid seek";
+#endif
+#ifdef ESRCH
+    case ESRCH: return "no such process";
+#endif
+#ifdef ESRMNT
+    case ESRMNT: return "srmount error";
+#endif
+#ifdef ESTALE
+    case ESTALE: return "stale remote file handle";
+#endif
+#ifdef ESUCCESS
+    case ESUCCESS: return "Error 0";
+#endif
+#ifdef ETIME
+    case ETIME: return "timer expired";
+#endif
+#ifdef ETIMEDOUT
+    case ETIMEDOUT: return "connection timed out";
+#endif
+#ifdef ETOOMANYREFS
+    case ETOOMANYREFS: return "too many references: can't splice";
+#endif
+#ifdef ETXTBSY
+    case ETXTBSY: return "text file or pseudo-device busy";
+#endif
+#ifdef EUCLEAN
+    case EUCLEAN: return "structure needs cleaning";
+#endif
+#ifdef EUNATCH
+    case EUNATCH: return "protocol driver not attached";
+#endif
+#ifdef EUSERS
+    case EUSERS: return "too many users";
+#endif
+#ifdef EVERSION
+    case EVERSION: return "version mismatch";
+#endif
+#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+    case EWOULDBLOCK: return "operation would block";
+#endif
+#ifdef EXDEV
+    case EXDEV: return "cross-domain link";
+#endif
+#ifdef EXFULL
+    case EXFULL: return "message tables full";
+#endif
+    }
+#else /* NO_SYS_ERRLIST */
+  extern int sys_nerr;
+  extern char *sys_errlist[];
+
+  if ((errnum > 0) && (errnum <= sys_nerr))
+    return sys_errlist [errnum];
+#endif /* NO_SYS_ERRLIST */
+
+  msg = g_static_private_get (&msg_private);
+  if (!msg)
+    {
+      msg = g_new (gchar, 64);
+      g_static_private_set (&msg_private, msg, g_free);
+    }
+
+  _g_sprintf (msg, "unknown error (%d)", errnum);
+
+  errno = saved_errno;
+  return msg;
+}
+
+G_CONST_RETURN gchar*
+g_strsignal (gint signum)
+{
+  static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
+  char *msg;
+
+#ifdef HAVE_STRSIGNAL
+  const char *msg_locale;
+  
+#if defined(G_OS_BEOS) || defined(G_WITH_CYGWIN)
+extern const char *strsignal(int);
+#else
+  /* this is declared differently (const) in string.h on BeOS */
+  extern char *strsignal (int sig);
+#endif /* !G_OS_BEOS && !G_WITH_CYGWIN */
+  msg_locale = strsignal (signum);
+  if (g_get_charset (NULL))
+    return msg_locale;
+  else
+    {
+      gchar *msg_utf8 = g_locale_to_utf8 (msg_locale, -1, NULL, NULL, NULL);
+      if (msg_utf8)
+       {
+         /* Stick in the quark table so that we can return a static result
+          */
+         GQuark msg_quark = g_quark_from_string (msg_utf8);
+         g_free (msg_utf8);
+         
+         return g_quark_to_string (msg_quark);
+       }
+    }
+#elif NO_SYS_SIGLIST
+  switch (signum)
+    {
+#ifdef SIGHUP
+    case SIGHUP: return "Hangup";
+#endif
+#ifdef SIGINT
+    case SIGINT: return "Interrupt";
+#endif
+#ifdef SIGQUIT
+    case SIGQUIT: return "Quit";
+#endif
+#ifdef SIGILL
+    case SIGILL: return "Illegal instruction";
+#endif
+#ifdef SIGTRAP
+    case SIGTRAP: return "Trace/breakpoint trap";
+#endif
+#ifdef SIGABRT
+    case SIGABRT: return "IOT trap/Abort";
+#endif
+#ifdef SIGBUS
+    case SIGBUS: return "Bus error";
+#endif
+#ifdef SIGFPE
+    case SIGFPE: return "Floating point exception";
+#endif
+#ifdef SIGKILL
+    case SIGKILL: return "Killed";
+#endif
+#ifdef SIGUSR1
+    case SIGUSR1: return "User defined signal 1";
+#endif
+#ifdef SIGSEGV
+    case SIGSEGV: return "Segmentation fault";
+#endif
+#ifdef SIGUSR2
+    case SIGUSR2: return "User defined signal 2";
+#endif
+#ifdef SIGPIPE
+    case SIGPIPE: return "Broken pipe";
+#endif
+#ifdef SIGALRM
+    case SIGALRM: return "Alarm clock";
+#endif
+#ifdef SIGTERM
+    case SIGTERM: return "Terminated";
+#endif
+#ifdef SIGSTKFLT
+    case SIGSTKFLT: return "Stack fault";
+#endif
+#ifdef SIGCHLD
+    case SIGCHLD: return "Child exited";
+#endif
+#ifdef SIGCONT
+    case SIGCONT: return "Continued";
+#endif
+#ifdef SIGSTOP
+    case SIGSTOP: return "Stopped (signal)";
+#endif
+#ifdef SIGTSTP
+    case SIGTSTP: return "Stopped";
+#endif
+#ifdef SIGTTIN
+    case SIGTTIN: return "Stopped (tty input)";
+#endif
+#ifdef SIGTTOU
+    case SIGTTOU: return "Stopped (tty output)";
+#endif
+#ifdef SIGURG
+    case SIGURG: return "Urgent condition";
+#endif
+#ifdef SIGXCPU
+    case SIGXCPU: return "CPU time limit exceeded";
+#endif
+#ifdef SIGXFSZ
+    case SIGXFSZ: return "File size limit exceeded";
+#endif
+#ifdef SIGVTALRM
+    case SIGVTALRM: return "Virtual time alarm";
+#endif
+#ifdef SIGPROF
+    case SIGPROF: return "Profile signal";
+#endif
+#ifdef SIGWINCH
+    case SIGWINCH: return "Window size changed";
+#endif
+#ifdef SIGIO
+    case SIGIO: return "Possible I/O";
+#endif
+#ifdef SIGPWR
+    case SIGPWR: return "Power failure";
+#endif
+#ifdef SIGUNUSED
+    case SIGUNUSED: return "Unused signal";
+#endif
+    }
+#else /* NO_SYS_SIGLIST */
+
+#ifdef NO_SYS_SIGLIST_DECL
+  extern char *sys_siglist[];  /*(see Tue Jan 19 00:44:24 1999 in changelog)*/
+#endif
+
+  return (char*) /* this function should return const --josh */ sys_siglist [signum];
+#endif /* NO_SYS_SIGLIST */
+
+  msg = g_static_private_get (&msg_private);
+  if (!msg)
+    {
+      msg = g_new (gchar, 64);
+      g_static_private_set (&msg_private, msg, g_free);
+    }
+
+  _g_sprintf (msg, "unknown signal (%d)", signum);
+  
+  return msg;
+}
+
+/* Functions g_strlcpy and g_strlcat were originally developed by
+ * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
+ * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
+ * for more information.
+ */
+
+#ifdef HAVE_STRLCPY
+/* Use the native ones, if available; they might be implemented in assembly */
+gsize
+g_strlcpy (gchar       *dest,
+          const gchar *src,
+          gsize        dest_size)
+{
+  g_return_val_if_fail (dest != NULL, 0);
+  g_return_val_if_fail (src  != NULL, 0);
+  
+  return strlcpy (dest, src, dest_size);
+}
+
+gsize
+g_strlcat (gchar       *dest,
+          const gchar *src,
+          gsize        dest_size)
+{
+  g_return_val_if_fail (dest != NULL, 0);
+  g_return_val_if_fail (src  != NULL, 0);
+  
+  return strlcat (dest, src, dest_size);
+}
+
+#else /* ! HAVE_STRLCPY */
+/* g_strlcpy
+ *
+ * Copy string src to buffer dest (of buffer size dest_size).  At most
+ * dest_size-1 characters will be copied.  Always NUL terminates
+ * (unless dest_size == 0).  This function does NOT allocate memory.
+ * Unlike strncpy, this function doesn't pad dest (so it's often faster).
+ * Returns size of attempted result, strlen(src),
+ * so if retval >= dest_size, truncation occurred.
+ */
+gsize
+g_strlcpy (gchar       *dest,
+           const gchar *src,
+           gsize        dest_size)
+{
+  register gchar *d = dest;
+  register const gchar *s = src;
+  register gsize n = dest_size;
+  
+  g_return_val_if_fail (dest != NULL, 0);
+  g_return_val_if_fail (src  != NULL, 0);
+  
+  /* Copy as many bytes as will fit */
+  if (n != 0 && --n != 0)
+    do
+      {
+       register gchar c = *s++;
+       
+       *d++ = c;
+       if (c == 0)
+         break;
+      }
+    while (--n != 0);
+  
+  /* If not enough room in dest, add NUL and traverse rest of src */
+  if (n == 0)
+    {
+      if (dest_size != 0)
+       *d = 0;
+      while (*s++)
+       ;
+    }
+  
+  return s - src - 1;  /* count does not include NUL */
+}
+
+/* g_strlcat
+ *
+ * Appends string src to buffer dest (of buffer size dest_size).
+ * At most dest_size-1 characters will be copied.
+ * Unlike strncat, dest_size is the full size of dest, not the space left over.
+ * This function does NOT allocate memory.
+ * This always NUL terminates (unless siz == 0 or there were no NUL characters
+ * in the dest_size characters of dest to start with).
+ * Returns size of attempted result, which is
+ * MIN (dest_size, strlen (original dest)) + strlen (src),
+ * so if retval >= dest_size, truncation occurred.
+ */
+gsize
+g_strlcat (gchar       *dest,
+           const gchar *src,
+           gsize        dest_size)
+{
+  register gchar *d = dest;
+  register const gchar *s = src;
+  register gsize bytes_left = dest_size;
+  gsize dlength;  /* Logically, MIN (strlen (d), dest_size) */
+  
+  g_return_val_if_fail (dest != NULL, 0);
+  g_return_val_if_fail (src  != NULL, 0);
+  
+  /* Find the end of dst and adjust bytes left but don't go past end */
+  while (*d != 0 && bytes_left-- != 0)
+    d++;
+  dlength = d - dest;
+  bytes_left = dest_size - dlength;
+  
+  if (bytes_left == 0)
+    return dlength + strlen (s);
+  
+  while (*s != 0)
+    {
+      if (bytes_left != 1)
+       {
+         *d++ = *s;
+         bytes_left--;
+       }
+      s++;
+    }
+  *d = 0;
+  
+  return dlength + (s - src);  /* count does not include NUL */
+}
+#endif /* ! HAVE_STRLCPY */
+
+/**
+ * g_ascii_strdown:
+ * @str: a string.
+ * @len: length of @str in bytes, or -1 if @str is nul-terminated.
+ * 
+ * Converts all upper case ASCII letters to lower case ASCII letters.
+ * 
+ * Return value: a newly-allocated string, with all the upper case
+ *               characters in @str converted to lower case, with
+ *               semantics that exactly match g_ascii_tolower(). (Note
+ *               that this is unlike the old g_strdown(), which modified
+ *               the string in place.)
+ **/
+gchar*
+g_ascii_strdown (const gchar *str,
+                gssize       len)
+{
+  gchar *result, *s;
+  
+  g_return_val_if_fail (str != NULL, NULL);
+
+  if (len < 0)
+    len = strlen (str);
+
+  result = g_strndup (str, len);
+  for (s = result; *s; s++)
+    *s = g_ascii_tolower (*s);
+  
+  return result;
+}
+
+#endif
+
+/**
+ * g_ascii_strup:
+ * @str: a string.
+ * @len: length of @str in bytes, or -1 if @str is nul-terminated.
+ * 
+ * Converts all lower case ASCII letters to upper case ASCII letters.
+ * 
+ * Return value: a newly allocated string, with all the lower case
+ *               characters in @str converted to upper case, with
+ *               semantics that exactly match g_ascii_toupper(). (Note
+ *               that this is unlike the old g_strup(), which modified
+ *               the string in place.)
+ **/
+gchar*
+g_ascii_strup (const gchar *str,
+              gssize       len)
+{
+  gchar *result, *s;
+
+  g_return_val_if_fail (str != NULL, NULL);
+
+  if (len < 0)
+    len = strlen (str);
+
+  result = g_strndup (str, len);
+  for (s = result; *s; s++)
+    *s = g_ascii_toupper (*s);
+
+  return result;
+}
+
+#if 0
+
+/**
+ * g_strdown:
+ * @string: the string to convert.
+ * 
+ * Converts a string to lower case.  
+ * 
+ * Return value: the string 
+ *
+ * Deprecated:2.2: This function is totally broken for the reasons discussed 
+ * in the g_strncasecmp() docs - use g_ascii_strdown() or g_utf8_strdown() 
+ * instead.
+ **/
+gchar*
+g_strdown (gchar *string)
+{
+  register guchar *s;
+  
+  g_return_val_if_fail (string != NULL, NULL);
+  
+  s = (guchar *) string;
+  
+  while (*s)
+    {
+      if (isupper (*s))
+       *s = tolower (*s);
+      s++;
+    }
+  
+  return (gchar *) string;
+}
+
+/**
+ * g_strup:
+ * @string: the string to convert.
+ * 
+ * Converts a string to upper case. 
+ * 
+ * Return value: the string
+ *
+ * Deprecated:2.2: This function is totally broken for the reasons discussed 
+ * in the g_strncasecmp() docs - use g_ascii_strup() or g_utf8_strup() instead.
+ **/
+gchar*
+g_strup (gchar *string)
+{
+  register guchar *s;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  s = (guchar *) string;
+
+  while (*s)
+    {
+      if (islower (*s))
+       *s = toupper (*s);
+      s++;
+    }
+
+  return (gchar *) string;
+}
+
+gchar*
+g_strreverse (gchar *string)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+
+  if (*string)
+    {
+      register gchar *h, *t;
+
+      h = string;
+      t = string + strlen (string) - 1;
+
+      while (h < t)
+       {
+         register gchar c;
+
+         c = *h;
+         *h = *t;
+         h++;
+         *t = c;
+         t--;
+       }
+    }
+
+  return string;
+}
+
+/**
+ * g_ascii_tolower:
+ * @c: any character.
+ * 
+ * Convert a character to ASCII lower case.
+ *
+ * Unlike the standard C library tolower() function, this only
+ * recognizes standard ASCII letters and ignores the locale, returning
+ * all non-ASCII characters unchanged, even if they are lower case
+ * letters in a particular character set. Also unlike the standard
+ * library function, this takes and returns a char, not an int, so
+ * don't call it on %EOF but no need to worry about casting to #guchar
+ * before passing a possibly non-ASCII character in.
+ * 
+ * Return value: the result of converting @c to lower case.
+ *               If @c is not an ASCII upper case letter,
+ *               @c is returned unchanged.
+ **/
+gchar
+g_ascii_tolower (gchar c)
+{
+  return g_ascii_isupper (c) ? c - 'A' + 'a' : c;
+}
+
+#endif
+
+/**
+ * g_ascii_toupper:
+ * @c: any character.
+ * 
+ * Convert a character to ASCII upper case.
+ *
+ * Unlike the standard C library toupper() function, this only
+ * recognizes standard ASCII letters and ignores the locale, returning
+ * all non-ASCII characters unchanged, even if they are upper case
+ * letters in a particular character set. Also unlike the standard
+ * library function, this takes and returns a char, not an int, so
+ * don't call it on %EOF but no need to worry about casting to #guchar
+ * before passing a possibly non-ASCII character in.
+ * 
+ * Return value: the result of converting @c to upper case.
+ *               If @c is not an ASCII lower case letter,
+ *               @c is returned unchanged.
+ **/
+gchar
+g_ascii_toupper (gchar c)
+{
+  return g_ascii_islower (c) ? c - 'a' + 'A' : c;
+}
+
+#if 0
+
+/**
+ * g_ascii_digit_value:
+ * @c: an ASCII character.
+ *
+ * Determines the numeric value of a character as a decimal
+ * digit. Differs from g_unichar_digit_value() because it takes
+ * a char, so there's no worry about sign extension if characters
+ * are signed.
+ *
+ * Return value: If @c is a decimal digit (according to
+ * g_ascii_isdigit()), its numeric value. Otherwise, -1.
+ **/
+int
+g_ascii_digit_value (gchar c)
+{
+  if (g_ascii_isdigit (c))
+    return c - '0';
+  return -1;
+}
+
+/**
+ * g_ascii_xdigit_value:
+ * @c: an ASCII character.
+ *
+ * Determines the numeric value of a character as a hexidecimal
+ * digit. Differs from g_unichar_xdigit_value() because it takes
+ * a char, so there's no worry about sign extension if characters
+ * are signed.
+ *
+ * Return value: If @c is a hex digit (according to
+ * g_ascii_isxdigit()), its numeric value. Otherwise, -1.
+ **/
+int
+g_ascii_xdigit_value (gchar c)
+{
+  if (c >= 'A' && c <= 'F')
+    return c - 'A' + 10;
+  if (c >= 'a' && c <= 'f')
+    return c - 'a' + 10;
+  return g_ascii_digit_value (c);
+}
+
+/**
+ * g_ascii_strcasecmp:
+ * @s1: string to compare with @s2.
+ * @s2: string to compare with @s1.
+ * 
+ * Compare two strings, ignoring the case of ASCII characters.
+ *
+ * Unlike the BSD strcasecmp() function, this only recognizes standard
+ * ASCII letters and ignores the locale, treating all non-ASCII
+ * bytes as if they are not letters.
+ *
+ * This function should be used only on strings that are known to be
+ * in encodings where the bytes corresponding to ASCII letters always
+ * represent themselves. This includes UTF-8 and the ISO-8859-*
+ * charsets, but not for instance double-byte encodings like the
+ * Windows Codepage 932, where the trailing bytes of double-byte
+ * characters include all ASCII letters. If you compare two CP932
+ * strings using this function, you will get false matches.
+ *
+ * Return value: 0 if the strings match, a negative value if @s1 &lt; @s2, 
+ *   or a positive value if @s1 &gt; @s2.
+ **/
+gint
+g_ascii_strcasecmp (const gchar *s1,
+                   const gchar *s2)
+{
+  gint c1, c2;
+
+  g_return_val_if_fail (s1 != NULL, 0);
+  g_return_val_if_fail (s2 != NULL, 0);
+
+  while (*s1 && *s2)
+    {
+      c1 = (gint)(guchar) TOLOWER (*s1);
+      c2 = (gint)(guchar) TOLOWER (*s2);
+      if (c1 != c2)
+       return (c1 - c2);
+      s1++; s2++;
+    }
+
+  return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
+}
+
+/**
+ * g_ascii_strncasecmp:
+ * @s1: string to compare with @s2.
+ * @s2: string to compare with @s1.
+ * @n:  number of characters to compare.
+ * 
+ * Compare @s1 and @s2, ignoring the case of ASCII characters and any
+ * characters after the first @n in each string.
+ *
+ * Unlike the BSD strcasecmp() function, this only recognizes standard
+ * ASCII letters and ignores the locale, treating all non-ASCII
+ * characters as if they are not letters.
+ * 
+ * The same warning as in g_ascii_strcasecmp() applies: Use this
+ * function only on strings known to be in encodings where bytes
+ * corresponding to ASCII letters always represent themselves.
+ *
+ * Return value: 0 if the strings match, a negative value if @s1 &lt; @s2, 
+ *   or a positive value if @s1 &gt; @s2.
+ **/
+gint
+g_ascii_strncasecmp (const gchar *s1,
+                    const gchar *s2,
+                    gsize n)
+{
+  gint c1, c2;
+
+  g_return_val_if_fail (s1 != NULL, 0);
+  g_return_val_if_fail (s2 != NULL, 0);
+
+  while (n && *s1 && *s2)
+    {
+      n -= 1;
+      c1 = (gint)(guchar) TOLOWER (*s1);
+      c2 = (gint)(guchar) TOLOWER (*s2);
+      if (c1 != c2)
+       return (c1 - c2);
+      s1++; s2++;
+    }
+
+  if (n)
+    return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
+  else
+    return 0;
+}
+
+/**
+ * g_strcasecmp:
+ * @s1: a string.
+ * @s2: a string to compare with @s1.
+ * 
+ * A case-insensitive string comparison, corresponding to the standard
+ * strcasecmp() function on platforms which support it.
+ *
+ * Return value: 0 if the strings match, a negative value if @s1 &lt; @s2, 
+ *   or a positive value if @s1 &gt; @s2.
+ *
+ * Deprecated:2.2: See g_strncasecmp() for a discussion of why this function 
+ *   is deprecated and how to replace it.
+ **/
+gint
+g_strcasecmp (const gchar *s1,
+             const gchar *s2)
+{
+#ifdef HAVE_STRCASECMP
+  g_return_val_if_fail (s1 != NULL, 0);
+  g_return_val_if_fail (s2 != NULL, 0);
+
+  return strcasecmp (s1, s2);
+#else
+  gint c1, c2;
+
+  g_return_val_if_fail (s1 != NULL, 0);
+  g_return_val_if_fail (s2 != NULL, 0);
+
+  while (*s1 && *s2)
+    {
+      /* According to A. Cox, some platforms have islower's that
+       * don't work right on non-uppercase
+       */
+      c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
+      c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
+      if (c1 != c2)
+       return (c1 - c2);
+      s1++; s2++;
+    }
+
+  return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
+#endif
+}
+
+/**
+ * g_strncasecmp:
+ * @s1: a string.
+ * @s2: a string to compare with @s1.
+ * @n: the maximum number of characters to compare.
+ * 
+ * A case-insensitive string comparison, corresponding to the standard
+ * strncasecmp() function on platforms which support it.
+ * It is similar to g_strcasecmp() except it only compares the first @n 
+ * characters of the strings.
+ * 
+ * Return value: 0 if the strings match, a negative value if @s1 &lt; @s2, 
+ *   or a positive value if @s1 &gt; @s2.
+ *
+ * Deprecated:2.2: The problem with g_strncasecmp() is that it does the 
+ * comparison by calling toupper()/tolower(). These functions are
+ * locale-specific and operate on single bytes. However, it is impossible
+ * to handle things correctly from an I18N standpoint by operating on
+ * bytes, since characters may be multibyte. Thus g_strncasecmp() is
+ * broken if your string is guaranteed to be ASCII, since it's
+ * locale-sensitive, and it's broken if your string is localized, since
+ * it doesn't work on many encodings at all, including UTF-8, EUC-JP,
+ * etc.
+ *
+ * There are therefore two replacement functions: g_ascii_strncasecmp(),
+ * which only works on ASCII and is not locale-sensitive, and
+ * g_utf8_casefold(), which is good for case-insensitive sorting of UTF-8.
+ **/
+gint
+g_strncasecmp (const gchar *s1,
+              const gchar *s2,
+              guint n)     
+{
+#ifdef HAVE_STRNCASECMP
+  return strncasecmp (s1, s2, n);
+#else
+  gint c1, c2;
+
+  g_return_val_if_fail (s1 != NULL, 0);
+  g_return_val_if_fail (s2 != NULL, 0);
+
+  while (n && *s1 && *s2)
+    {
+      n -= 1;
+      /* According to A. Cox, some platforms have islower's that
+       * don't work right on non-uppercase
+       */
+      c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
+      c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
+      if (c1 != c2)
+       return (c1 - c2);
+      s1++; s2++;
+    }
+
+  if (n)
+    return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
+  else
+    return 0;
+#endif
+}
+
+gchar*
+g_strdelimit (gchar      *string,
+             const gchar *delimiters,
+             gchar        new_delim)
+{
+  register gchar *c;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  if (!delimiters)
+    delimiters = G_STR_DELIMITERS;
+
+  for (c = string; *c; c++)
+    {
+      if (strchr (delimiters, *c))
+       *c = new_delim;
+    }
+
+  return string;
+}
+
+gchar*
+g_strcanon (gchar       *string,
+           const gchar *valid_chars,
+           gchar        substitutor)
+{
+  register gchar *c;
+
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (valid_chars != NULL, NULL);
+
+  for (c = string; *c; c++)
+    {
+      if (!strchr (valid_chars, *c))
+       *c = substitutor;
+    }
+
+  return string;
+}
+
+gchar*
+g_strcompress (const gchar *source)
+{
+  const gchar *p = source, *octal;
+  gchar *dest = g_malloc (strlen (source) + 1);
+  gchar *q = dest;
+  
+  while (*p)
+    {
+      if (*p == '\\')
+       {
+         p++;
+         switch (*p)
+           {
+           case '\0':
+             g_warning ("g_strcompress: trailing \\");
+             goto out;
+           case '0':  case '1':  case '2':  case '3':  case '4':
+           case '5':  case '6':  case '7':
+             *q = 0;
+             octal = p;
+             while ((p < octal + 3) && (*p >= '0') && (*p <= '7'))
+               {
+                 *q = (*q * 8) + (*p - '0');
+                 p++;
+               }
+             q++;
+             p--;
+             break;
+           case 'b':
+             *q++ = '\b';
+             break;
+           case 'f':
+             *q++ = '\f';
+             break;
+           case 'n':
+             *q++ = '\n';
+             break;
+           case 'r':
+             *q++ = '\r';
+             break;
+           case 't':
+             *q++ = '\t';
+             break;
+           default:            /* Also handles \" and \\ */
+             *q++ = *p;
+             break;
+           }
+       }
+      else
+       *q++ = *p;
+      p++;
+    }
+out:
+  *q = 0;
+  
+  return dest;
+}
+
+gchar *
+g_strescape (const gchar *source,
+            const gchar *exceptions)
+{
+  const guchar *p;
+  gchar *dest;
+  gchar *q;
+  guchar excmap[256];
+  
+  g_return_val_if_fail (source != NULL, NULL);
+
+  p = (guchar *) source;
+  /* Each source byte needs maximally four destination chars (\777) */
+  q = dest = g_malloc (strlen (source) * 4 + 1);
+
+  memset (excmap, 0, 256);
+  if (exceptions)
+    {
+      guchar *e = (guchar *) exceptions;
+
+      while (*e)
+       {
+         excmap[*e] = 1;
+         e++;
+       }
+    }
+
+  while (*p)
+    {
+      if (excmap[*p])
+       *q++ = *p;
+      else
+       {
+         switch (*p)
+           {
+           case '\b':
+             *q++ = '\\';
+             *q++ = 'b';
+             break;
+           case '\f':
+             *q++ = '\\';
+             *q++ = 'f';
+             break;
+           case '\n':
+             *q++ = '\\';
+             *q++ = 'n';
+             break;
+           case '\r':
+             *q++ = '\\';
+             *q++ = 'r';
+             break;
+           case '\t':
+             *q++ = '\\';
+             *q++ = 't';
+             break;
+           case '\\':
+             *q++ = '\\';
+             *q++ = '\\';
+             break;
+           case '"':
+             *q++ = '\\';
+             *q++ = '"';
+             break;
+           default:
+             if ((*p < ' ') || (*p >= 0177))
+               {
+                 *q++ = '\\';
+                 *q++ = '0' + (((*p) >> 6) & 07);
+                 *q++ = '0' + (((*p) >> 3) & 07);
+                 *q++ = '0' + ((*p) & 07);
+               }
+             else
+               *q++ = *p;
+             break;
+           }
+       }
+      p++;
+    }
+  *q = 0;
+  return dest;
+}
+
+gchar*
+g_strchug (gchar *string)
+{
+  guchar *start;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  for (start = (guchar*) string; *start && g_ascii_isspace (*start); start++)
+    ;
+
+  g_memmove (string, start, strlen ((gchar *) start) + 1);
+
+  return string;
+}
+
+gchar*
+g_strchomp (gchar *string)
+{
+  gsize len;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  len = strlen (string);
+  while (len--)
+    {
+      if (g_ascii_isspace ((guchar) string[len]))
+       string[len] = '\0';
+      else
+       break;
+    }
+
+  return string;
+}
+
+/**
+ * g_strsplit:
+ * @string: a string to split.
+ * @delimiter: a string which specifies the places at which to split the string.
+ *     The delimiter is not included in any of the resulting strings, unless
+ *     @max_tokens is reached.
+ * @max_tokens: the maximum number of pieces to split @string into. If this is
+ *              less than 1, the string is split completely.
+ * 
+ * Splits a string into a maximum of @max_tokens pieces, using the given
+ * @delimiter. If @max_tokens is reached, the remainder of @string is appended
+ * to the last token. 
+ *
+ * As a special case, the result of splitting the empty string "" is an empty
+ * vector, not a vector containing a single string. The reason for this
+ * special case is that being able to represent a empty vector is typically
+ * more useful than consistent handling of empty elements. If you do need
+ * to represent empty elements, you'll need to check for the empty string
+ * before calling g_strsplit().
+ * 
+ * Return value: a newly-allocated %NULL-terminated array of strings. Use 
+ *    g_strfreev() to free it.
+ **/
+gchar**
+g_strsplit (const gchar *string,
+           const gchar *delimiter,
+           gint         max_tokens)
+{
+  GSList *string_list = NULL, *slist;
+  gchar **str_array, *s;
+  guint n = 0;
+  const gchar *remainder;
+
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (delimiter != NULL, NULL);
+  g_return_val_if_fail (delimiter[0] != '\0', NULL);
+
+  if (max_tokens < 1)
+    max_tokens = G_MAXINT;
+
+  remainder = string;
+  s = strstr (remainder, delimiter);
+  if (s)
+    {
+      gsize delimiter_len = strlen (delimiter);   
+
+      while (--max_tokens && s)
+       {
+         gsize len;     
+         gchar *new_string;
+
+         len = s - remainder;
+         new_string = g_new (gchar, len + 1);
+         strncpy (new_string, remainder, len);
+         new_string[len] = 0;
+         string_list = g_slist_prepend (string_list, new_string);
+         n++;
+         remainder = s + delimiter_len;
+         s = strstr (remainder, delimiter);
+       }
+    }
+  if (*string)
+    {
+      n++;
+      string_list = g_slist_prepend (string_list, g_strdup (remainder));
+    }
+
+  str_array = g_new (gchar*, n + 1);
+
+  str_array[n--] = NULL;
+  for (slist = string_list; slist; slist = slist->next)
+    str_array[n--] = slist->data;
+
+  g_slist_free (string_list);
+
+  return str_array;
+}
+
+/**
+ * g_strsplit_set:
+ * @string: The string to be tokenized
+ * @delimiters: A nul-terminated string containing bytes that are used
+ *              to split the string.
+ * @max_tokens: The maximum number of tokens to split @string into. 
+ *              If this is less than 1, the string is split completely
+ * 
+ * Splits @string into a number of tokens not containing any of the characters
+ * in @delimiter. A token is the (possibly empty) longest string that does not
+ * contain any of the characters in @delimiters. If @max_tokens is reached, the
+ * remainder is appended to the last token.
+ *
+ * For example the result of g_strsplit_set ("abc:def/ghi", ":/", -1) is a
+ * %NULL-terminated vector containing the three strings "abc", "def", 
+ * and "ghi".
+ *
+ * The result if g_strsplit_set (":def/ghi:", ":/", -1) is a %NULL-terminated
+ * vector containing the four strings "", "def", "ghi", and "".
+ * 
+ * As a special case, the result of splitting the empty string "" is an empty
+ * vector, not a vector containing a single string. The reason for this
+ * special case is that being able to represent a empty vector is typically
+ * more useful than consistent handling of empty elements. If you do need
+ * to represent empty elements, you'll need to check for the empty string
+ * before calling g_strsplit_set().
+ *
+ * Note that this function works on bytes not characters, so it can't be used 
+ * to delimit UTF-8 strings for anything but ASCII characters.
+ * 
+ * Return value: a newly-allocated %NULL-terminated array of strings. Use 
+ *    g_strfreev() to free it.
+ * 
+ * Since: 2.4
+ **/
+gchar **
+g_strsplit_set (const gchar *string,
+               const gchar *delimiters,
+               gint         max_tokens)
+{
+  gboolean delim_table[256];
+  GSList *tokens, *list;
+  gint n_tokens;
+  const gchar *s;
+  const gchar *current;
+  gchar *token;
+  gchar **result;
+  
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (delimiters != NULL, NULL);
+
+  if (max_tokens < 1)
+    max_tokens = G_MAXINT;
+
+  if (*string == '\0')
+    {
+      result = g_new (char *, 1);
+      result[0] = NULL;
+      return result;
+    }
+  
+  memset (delim_table, FALSE, sizeof (delim_table));
+  for (s = delimiters; *s != '\0'; ++s)
+    delim_table[*(guchar *)s] = TRUE;
+
+  tokens = NULL;
+  n_tokens = 0;
+
+  s = current = string;
+  while (*s != '\0')
+    {
+      if (delim_table[*(guchar *)s] && n_tokens + 1 < max_tokens)
+       {
+         gchar *token;
+
+         token = g_strndup (current, s - current);
+         tokens = g_slist_prepend (tokens, token);
+         ++n_tokens;
+
+         current = s + 1;
+       }
+      
+      ++s;
+    }
+
+  token = g_strndup (current, s - current);
+  tokens = g_slist_prepend (tokens, token);
+  ++n_tokens;
+
+  result = g_new (gchar *, n_tokens + 1);
+
+  result[n_tokens] = NULL;
+  for (list = tokens; list != NULL; list = list->next)
+    result[--n_tokens] = list->data;
+
+  g_slist_free (tokens);
+  
+  return result;
+}
+
+/**
+ * g_strfreev:
+ * @str_array: a %NULL-terminated array of strings to free.
+
+ * Frees a %NULL-terminated array of strings, and the array itself.
+ * If called on a %NULL value, g_strfreev() simply returns. 
+ **/
+void
+g_strfreev (gchar **str_array)
+{
+  if (str_array)
+    {
+      int i;
+
+      for(i = 0; str_array[i] != NULL; i++)
+       g_free(str_array[i]);
+
+      g_free (str_array);
+    }
+}
+
+/**
+ * g_strdupv:
+ * @str_array: %NULL-terminated array of strings.
+ * 
+ * Copies %NULL-terminated array of strings. The copy is a deep copy;
+ * the new array should be freed by first freeing each string, then
+ * the array itself. g_strfreev() does this for you. If called
+ * on a %NULL value, g_strdupv() simply returns %NULL.
+ * 
+ * Return value: a new %NULL-terminated array of strings.
+ **/
+gchar**
+g_strdupv (gchar **str_array)
+{
+  if (str_array)
+    {
+      gint i;
+      gchar **retval;
+
+      i = 0;
+      while (str_array[i])
+        ++i;
+          
+      retval = g_new (gchar*, i + 1);
+
+      i = 0;
+      while (str_array[i])
+        {
+          retval[i] = g_strdup (str_array[i]);
+          ++i;
+        }
+      retval[i] = NULL;
+
+      return retval;
+    }
+  else
+    return NULL;
+}
+
+gchar*
+g_strjoinv (const gchar  *separator,
+           gchar       **str_array)
+{
+  gchar *string;
+  gchar *ptr;
+
+  g_return_val_if_fail (str_array != NULL, NULL);
+
+  if (separator == NULL)
+    separator = "";
+
+  if (*str_array)
+    {
+      gint i;
+      gsize len;
+      gsize separator_len;     
+
+      separator_len = strlen (separator);
+      /* First part, getting length */
+      len = 1 + strlen (str_array[0]);
+      for (i = 1; str_array[i] != NULL; i++)
+        len += strlen (str_array[i]);
+      len += separator_len * (i - 1);
+
+      /* Second part, building string */
+      string = g_new (gchar, len);
+      ptr = g_stpcpy (string, *str_array);
+      for (i = 1; str_array[i] != NULL; i++)
+       {
+          ptr = g_stpcpy (ptr, separator);
+          ptr = g_stpcpy (ptr, str_array[i]);
+       }
+      }
+  else
+    string = g_strdup ("");
+
+  return string;
+}
+
+gchar*
+g_strjoin (const gchar  *separator,
+          ...)
+{
+  gchar *string, *s;
+  va_list args;
+  gsize len;               
+  gsize separator_len;     
+  gchar *ptr;
+
+  if (separator == NULL)
+    separator = "";
+
+  separator_len = strlen (separator);
+
+  va_start (args, separator);
+
+  s = va_arg (args, gchar*);
+
+  if (s)
+    {
+      /* First part, getting length */
+      len = 1 + strlen (s);
+
+      s = va_arg (args, gchar*);
+      while (s)
+       {
+         len += separator_len + strlen (s);
+         s = va_arg (args, gchar*);
+       }
+      va_end (args);
+
+      /* Second part, building string */
+      string = g_new (gchar, len);
+
+      va_start (args, separator);
+
+      s = va_arg (args, gchar*);
+      ptr = g_stpcpy (string, s);
+
+      s = va_arg (args, gchar*);
+      while (s)
+       {
+         ptr = g_stpcpy (ptr, separator);
+          ptr = g_stpcpy (ptr, s);
+         s = va_arg (args, gchar*);
+       }
+    }
+  else
+    string = g_strdup ("");
+
+  va_end (args);
+
+  return string;
+}
+
+#endif
+
+/**
+ * g_strstr_len:
+ * @haystack: a string.
+ * @haystack_len: the maximum length of @haystack.
+ * @needle: the string to search for.
+ *
+ * Searches the string @haystack for the first occurrence
+ * of the string @needle, limiting the length of the search
+ * to @haystack_len. 
+ *
+ * Return value: a pointer to the found occurrence, or
+ *    %NULL if not found.
+ **/
+gchar *
+g_strstr_len (const gchar *haystack,
+             gssize       haystack_len,
+             const gchar *needle)
+{
+  g_return_val_if_fail (haystack != NULL, NULL);
+  g_return_val_if_fail (needle != NULL, NULL);
+  
+  if (haystack_len < 0)
+    return strstr (haystack, needle);
+  else
+    {
+      const gchar *p = haystack;
+      gsize needle_len = strlen (needle);
+      const gchar *end;
+      gsize i;
+
+      if (needle_len == 0)
+       return (gchar *)haystack;
+
+      if (haystack_len < needle_len)
+       return NULL;
+      
+      end = haystack + haystack_len - needle_len;
+      
+      while (*p && p <= end)
+       {
+         for (i = 0; i < needle_len; i++)
+           if (p[i] != needle[i])
+             goto next;
+         
+         return (gchar *)p;
+         
+       next:
+         p++;
+       }
+      
+      return NULL;
+    }
+}
+
+#if 0
+
+/**
+ * g_strrstr:
+ * @haystack: a nul-terminated string.
+ * @needle: the nul-terminated string to search for.
+ *
+ * Searches the string @haystack for the last occurrence
+ * of the string @needle.
+ *
+ * Return value: a pointer to the found occurrence, or
+ *    %NULL if not found.
+ **/
+gchar *
+g_strrstr (const gchar *haystack,
+          const gchar *needle)
+{
+  gsize i;
+  gsize needle_len;
+  gsize haystack_len;
+  const gchar *p;
+      
+  g_return_val_if_fail (haystack != NULL, NULL);
+  g_return_val_if_fail (needle != NULL, NULL);
+
+  needle_len = strlen (needle);
+  haystack_len = strlen (haystack);
+
+  if (needle_len == 0)
+    return (gchar *)haystack;
+
+  if (haystack_len < needle_len)
+    return NULL;
+  
+  p = haystack + haystack_len - needle_len;
+
+  while (p >= haystack)
+    {
+      for (i = 0; i < needle_len; i++)
+       if (p[i] != needle[i])
+         goto next;
+      
+      return (gchar *)p;
+      
+    next:
+      p--;
+    }
+  
+  return NULL;
+}
+
+/**
+ * g_strrstr_len:
+ * @haystack: a nul-terminated string.
+ * @haystack_len: the maximum length of @haystack.
+ * @needle: the nul-terminated string to search for.
+ *
+ * Searches the string @haystack for the last occurrence
+ * of the string @needle, limiting the length of the search
+ * to @haystack_len. 
+ *
+ * Return value: a pointer to the found occurrence, or
+ *    %NULL if not found.
+ **/
+gchar *
+g_strrstr_len (const gchar *haystack,
+              gssize        haystack_len,
+              const gchar *needle)
+{
+  g_return_val_if_fail (haystack != NULL, NULL);
+  g_return_val_if_fail (needle != NULL, NULL);
+  
+  if (haystack_len < 0)
+    return g_strrstr (haystack, needle);
+  else
+    {
+      gsize needle_len = strlen (needle);
+      const gchar *haystack_max = haystack + haystack_len;
+      const gchar *p = haystack;
+      gsize i;
+
+      while (p < haystack_max && *p)
+       p++;
+
+      if (p < haystack + needle_len)
+       return NULL;
+       
+      p -= needle_len;
+
+      while (p >= haystack)
+       {
+         for (i = 0; i < needle_len; i++)
+           if (p[i] != needle[i])
+             goto next;
+         
+         return (gchar *)p;
+         
+       next:
+         p--;
+       }
+
+      return NULL;
+    }
+}
+
+
+/**
+ * g_str_has_suffix:
+ * @str: a nul-terminated string.
+ * @suffix: the nul-terminated suffix to look for.
+ *
+ * Looks whether the string @str ends with @suffix.
+ *
+ * Return value: %TRUE if @str end with @suffix, %FALSE otherwise.
+ *
+ * Since: 2.2
+ **/
+gboolean
+g_str_has_suffix (const gchar  *str,
+                 const gchar  *suffix)
+{
+  int str_len;
+  int suffix_len;
+  
+  g_return_val_if_fail (str != NULL, FALSE);
+  g_return_val_if_fail (suffix != NULL, FALSE);
+
+  str_len = strlen (str);
+  suffix_len = strlen (suffix);
+
+  if (str_len < suffix_len)
+    return FALSE;
+
+  return strcmp (str + str_len - suffix_len, suffix) == 0;
+}
+
+/**
+ * g_str_has_prefix:
+ * @str: a nul-terminated string.
+ * @prefix: the nul-terminated prefix to look for.
+ *
+ * Looks whether the string @str begins with @prefix.
+ *
+ * Return value: %TRUE if @str begins with @prefix, %FALSE otherwise.
+ *
+ * Since: 2.2
+ **/
+gboolean
+g_str_has_prefix (const gchar  *str,
+                 const gchar  *prefix)
+{
+  int str_len;
+  int prefix_len;
+  
+  g_return_val_if_fail (str != NULL, FALSE);
+  g_return_val_if_fail (prefix != NULL, FALSE);
+
+  str_len = strlen (str);
+  prefix_len = strlen (prefix);
+
+  if (str_len < prefix_len)
+    return FALSE;
+  
+  return strncmp (str, prefix, prefix_len) == 0;
+}
+
+
+/**
+ * g_strip_context:
+ * @msgid: a string
+ * @msgval: another string
+ * 
+ * An auxiliary function for gettext() support (see Q_()).
+ * 
+ * Return value: @msgval, unless @msgval is identical to @msgid and contains
+ *   a '|' character, in which case a pointer to the substring of msgid after
+ *   the first '|' character is returned. 
+ *
+ * Since: 2.4
+ **/
+G_CONST_RETURN gchar *
+g_strip_context  (const gchar *msgid, 
+                 const gchar *msgval)
+{
+  if (msgval == msgid)
+    {
+      const char *c = strchr (msgid, '|');
+      if (c != NULL)
+       return c + 1;
+    }
+  
+  return msgval;
+}
+
+
+/**
+ * g_strv_length:
+ * @str_array: a %NULL-terminated array of strings.
+ * 
+ * Returns the length of the given %NULL-terminated 
+ * string array @str_array.
+ * 
+ * Return value: length of @str_array.
+ *
+ * Since: 2.6
+ **/
+guint
+g_strv_length (gchar **str_array)
+{
+  guint i = 0;
+
+  g_return_val_if_fail (str_array != NULL, 0);
+
+  while (str_array[i])
+    ++i;
+
+  return i;
+}
+
+#define __G_STRFUNCS_C__
+#include "galiasdef.c"
+#endif
diff --git a/gnulib-local/lib/glib/gstrfuncs_.h b/gnulib-local/lib/glib/gstrfuncs_.h
new file mode 100644 (file)
index 0000000..1ed9f34
--- /dev/null
@@ -0,0 +1,269 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#ifndef __G_STRFUNCS_H__
+#define __G_STRFUNCS_H__
+
+#include <stdarg.h>
+#include <glib/gtypes.h>
+
+G_BEGIN_DECLS
+
+/* Functions like the ones in <ctype.h> that are not affected by locale. */
+typedef enum {
+  G_ASCII_ALNUM  = 1 << 0,
+  G_ASCII_ALPHA  = 1 << 1,
+  G_ASCII_CNTRL  = 1 << 2,
+  G_ASCII_DIGIT  = 1 << 3,
+  G_ASCII_GRAPH  = 1 << 4,
+  G_ASCII_LOWER  = 1 << 5,
+  G_ASCII_PRINT  = 1 << 6,
+  G_ASCII_PUNCT  = 1 << 7,
+  G_ASCII_SPACE  = 1 << 8,
+  G_ASCII_UPPER  = 1 << 9,
+  G_ASCII_XDIGIT = 1 << 10
+} GAsciiType;
+
+GLIB_VAR const guint16 * const g_ascii_table;
+
+#define g_ascii_isalnum(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_ALNUM) != 0)
+
+#define g_ascii_isalpha(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_ALPHA) != 0)
+
+#define g_ascii_iscntrl(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_CNTRL) != 0)
+
+#define g_ascii_isdigit(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_DIGIT) != 0)
+
+#define g_ascii_isgraph(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_GRAPH) != 0)
+
+#define g_ascii_islower(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_LOWER) != 0)
+
+#define g_ascii_isprint(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_PRINT) != 0)
+
+#define g_ascii_ispunct(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_PUNCT) != 0)
+
+#define g_ascii_isspace(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_SPACE) != 0)
+
+#define g_ascii_isupper(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_UPPER) != 0)
+
+#define g_ascii_isxdigit(c) \
+  ((g_ascii_table[(guchar) (c)] & G_ASCII_XDIGIT) != 0)
+
+#if 0
+gchar                 g_ascii_tolower  (gchar        c) G_GNUC_CONST;
+#endif
+gchar                 g_ascii_toupper  (gchar        c) G_GNUC_CONST;
+
+#if 0
+gint                  g_ascii_digit_value  (gchar    c) G_GNUC_CONST;
+gint                  g_ascii_xdigit_value (gchar    c) G_GNUC_CONST;
+
+/* String utility functions that modify a string argument or
+ * return a constant string that must not be freed.
+ */
+#define         G_STR_DELIMITERS       "_-|> <."
+gchar*               g_strdelimit     (gchar        *string,
+                                       const gchar  *delimiters,
+                                       gchar         new_delimiter);
+gchar*               g_strcanon       (gchar        *string,
+                                       const gchar  *valid_chars,
+                                       gchar         substitutor);
+G_CONST_RETURN gchar* g_strerror       (gint         errnum) G_GNUC_CONST;
+G_CONST_RETURN gchar* g_strsignal      (gint         signum) G_GNUC_CONST;
+gchar*               g_strreverse     (gchar        *string);
+gsize                g_strlcpy        (gchar        *dest,
+                                       const gchar  *src,
+                                       gsize         dest_size);
+gsize                g_strlcat        (gchar        *dest,
+                                       const gchar  *src,
+                                       gsize         dest_size);
+#endif
+gchar *               g_strstr_len     (const gchar  *haystack,
+                                       gssize        haystack_len,
+                                       const gchar  *needle);
+#if 0
+gchar *               g_strrstr        (const gchar  *haystack,
+                                       const gchar  *needle);
+gchar *               g_strrstr_len    (const gchar  *haystack,
+                                       gssize        haystack_len,
+                                       const gchar  *needle);
+
+gboolean              g_str_has_suffix (const gchar  *str,
+                                       const gchar  *suffix);
+gboolean              g_str_has_prefix (const gchar  *str,
+                                       const gchar  *prefix);
+
+/* String to/from double conversion functions */
+
+gdouble                      g_strtod         (const gchar  *nptr,
+                                       gchar       **endptr);
+gdouble                      g_ascii_strtod   (const gchar  *nptr,
+                                       gchar       **endptr);
+guint64                      g_ascii_strtoull (const gchar *nptr,
+                                       gchar      **endptr,
+                                       guint        base);
+gint64               g_ascii_strtoll  (const gchar *nptr,
+                                       gchar      **endptr,
+                                       guint        base);
+/* 29 bytes should enough for all possible values that
+ * g_ascii_dtostr can produce.
+ * Then add 10 for good measure */
+#define G_ASCII_DTOSTR_BUF_SIZE (29 + 10)
+gchar *               g_ascii_dtostr   (gchar        *buffer,
+                                       gint          buf_len,
+                                       gdouble       d);
+gchar *               g_ascii_formatd  (gchar        *buffer,
+                                       gint          buf_len,
+                                       const gchar  *format,
+                                       gdouble       d);
+
+/* removes leading spaces */
+gchar*                g_strchug        (gchar        *string);
+/* removes trailing spaces */
+gchar*                g_strchomp       (gchar        *string);
+/* removes leading & trailing spaces */
+#define g_strstrip( string )   g_strchomp (g_strchug (string))
+
+gint                  g_ascii_strcasecmp  (const gchar *s1,
+                                          const gchar *s2);
+gint                  g_ascii_strncasecmp (const gchar *s1,
+                                          const gchar *s2,
+                                          gsize        n);
+gchar*                g_ascii_strdown     (const gchar *str,
+                                          gssize       len) G_GNUC_MALLOC;
+#endif
+gchar*                g_ascii_strup       (const gchar *str,
+                                          gssize       len) G_GNUC_MALLOC;
+
+#if 0
+
+#ifndef G_DISABLE_DEPRECATED
+
+/* The following four functions are deprecated and will be removed in
+ * the next major release. They use the locale-specific tolower and
+ * toupper, which is almost never the right thing.
+ */
+
+gint                 g_strcasecmp     (const gchar *s1,
+                                       const gchar *s2);
+gint                 g_strncasecmp    (const gchar *s1,
+                                       const gchar *s2,
+                                       guint        n);
+gchar*               g_strdown        (gchar        *string);
+gchar*               g_strup          (gchar        *string);
+
+#endif /* G_DISABLE_DEPRECATED */
+
+#endif
+
+/* String utility functions that return a newly allocated string which
+ * ought to be freed with g_free from the caller at some point.
+ */
+gchar*               g_strdup         (const gchar *str) G_GNUC_MALLOC;
+gchar*               g_strdup_printf  (const gchar *format,
+                                       ...) G_GNUC_PRINTF (1, 2) G_GNUC_MALLOC;
+#if 0
+gchar*               g_strdup_vprintf (const gchar *format,
+                                       va_list      args) G_GNUC_MALLOC;
+#endif
+gchar*               g_strndup        (const gchar *str,
+                                       gsize        n) G_GNUC_MALLOC;  
+#if 0
+gchar*               g_strnfill       (gsize        length,  
+                                       gchar        fill_char) G_GNUC_MALLOC;
+#endif
+gchar*               g_strconcat      (const gchar *string1,
+                                       ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED;
+#if 0
+gchar*                g_strjoin               (const gchar  *separator,
+                                       ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED;
+
+/* Make a copy of a string interpreting C string -style escape
+ * sequences. Inverse of g_strescape. The recognized sequences are \b
+ * \f \n \r \t \\ \" and the octal format.
+ */
+gchar*                g_strcompress    (const gchar *source) G_GNUC_MALLOC;
+
+/* Copy a string escaping nonprintable characters like in C strings.
+ * Inverse of g_strcompress. The exceptions parameter, if non-NULL, points
+ * to a string containing characters that are not to be escaped.
+ *
+ * Deprecated API: gchar* g_strescape (const gchar *source);
+ * Luckily this function wasn't used much, using NULL as second parameter
+ * provides mostly identical semantics.
+ */
+gchar*                g_strescape      (const gchar *source,
+                                       const gchar *exceptions) G_GNUC_MALLOC;
+
+gpointer              g_memdup        (gconstpointer mem,
+                                       guint          byte_size) G_GNUC_MALLOC;
+
+/* NULL terminated string arrays.
+ * g_strsplit(), g_strsplit_set() split up string into max_tokens tokens
+ * at delim and return a newly allocated string array.
+ * g_strjoinv() concatenates all of str_array's strings, sliding in an
+ * optional separator, the returned string is newly allocated.
+ * g_strfreev() frees the array itself and all of its strings.
+ * g_strdupv() copies a NULL-terminated array of strings
+ * g_strv_length() returns the length of a NULL-terminated array of strings
+ */
+gchar**                      g_strsplit       (const gchar  *string,
+                                       const gchar  *delimiter,
+                                       gint          max_tokens) G_GNUC_MALLOC;
+gchar **             g_strsplit_set   (const gchar *string,
+                                       const gchar *delimiters,
+                                       gint         max_tokens) G_GNUC_MALLOC;
+gchar*                g_strjoinv       (const gchar  *separator,
+                                       gchar       **str_array) G_GNUC_MALLOC;
+void                  g_strfreev       (gchar       **str_array);
+gchar**               g_strdupv        (gchar       **str_array) G_GNUC_MALLOC;
+guint                 g_strv_length    (gchar       **str_array);
+
+gchar*                g_stpcpy         (gchar        *dest,
+                                        const char   *src);
+
+G_CONST_RETURN gchar *g_strip_context  (const gchar *msgid, 
+                                       const gchar *msgval);
+
+#endif
+
+G_END_DECLS
+
+#endif /* __G_STRFUNCS_H__ */
diff --git a/gnulib-local/lib/glib/gstring.c b/gnulib-local/lib/glib/gstring.c
new file mode 100644 (file)
index 0000000..3111eb1
--- /dev/null
@@ -0,0 +1,958 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+/* 
+ * MT safe
+ */
+
+#include "config.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "glib.h"
+#if 0
+#include "gprintf.h"
+
+#include "galias.h"
+
+struct _GStringChunk
+{
+  GHashTable *const_table;
+  GSList     *storage_list;
+  gsize       storage_next;    
+  gsize       this_size;       
+  gsize       default_size;    
+};
+#endif
+
+/* Hash Functions.
+ */
+
+/**
+ * g_str_equal:
+ * @v1: a key. 
+ * @v2: a key to compare with @v1.
+ * 
+ * Compares two strings and returns %TRUE if they are equal.
+ * It can be passed to g_hash_table_new() as the @key_equal_func
+ * parameter, when using strings as keys in a #GHashTable.
+ *
+ * Returns: %TRUE if the two keys match.
+ */
+gboolean
+g_str_equal (gconstpointer v1,
+            gconstpointer v2)
+{
+  const gchar *string1 = v1;
+  const gchar *string2 = v2;
+  
+  return strcmp (string1, string2) == 0;
+}
+
+/**
+ * g_str_hash:
+ * @v: a string key.
+ *
+ * Converts a string to a hash value.
+ * It can be passed to g_hash_table_new() as the @hash_func parameter, 
+ * when using strings as keys in a #GHashTable.
+ *
+ * Returns: a hash value corresponding to the key.
+ */
+guint
+g_str_hash (gconstpointer v)
+{
+  /* 31 bit hash function */
+  const signed char *p = v;
+  guint32 h = *p;
+
+  if (h)
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
+
+  return h;
+}
+
+#define MY_MAXSIZE ((gsize)-1)
+
+static inline gsize
+nearest_power (gsize base, gsize num)    
+{
+  if (num > MY_MAXSIZE / 2)
+    {
+      return MY_MAXSIZE;
+    }
+  else
+    {
+      gsize n = base;
+
+      while (n < num)
+       n <<= 1;
+      
+      return n;
+    }
+}
+
+#if 0
+
+/* String Chunks.
+ */
+
+GStringChunk*
+g_string_chunk_new (gsize default_size)    
+{
+  GStringChunk *new_chunk = g_new (GStringChunk, 1);
+  gsize size = 1;    
+
+  size = nearest_power (1, default_size);
+
+  new_chunk->const_table       = NULL;
+  new_chunk->storage_list      = NULL;
+  new_chunk->storage_next      = size;
+  new_chunk->default_size      = size;
+  new_chunk->this_size         = size;
+
+  return new_chunk;
+}
+
+void
+g_string_chunk_free (GStringChunk *chunk)
+{
+  GSList *tmp_list;
+
+  g_return_if_fail (chunk != NULL);
+
+  if (chunk->storage_list)
+    {
+      for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
+       g_free (tmp_list->data);
+
+      g_slist_free (chunk->storage_list);
+    }
+
+  if (chunk->const_table)
+    g_hash_table_destroy (chunk->const_table);
+
+  g_free (chunk);
+}
+
+gchar*
+g_string_chunk_insert (GStringChunk *chunk,
+                      const gchar  *string)
+{
+  g_return_val_if_fail (chunk != NULL, NULL);
+
+  return g_string_chunk_insert_len (chunk, string, -1);
+}
+
+gchar*
+g_string_chunk_insert_const (GStringChunk *chunk,
+                            const gchar  *string)
+{
+  char* lookup;
+
+  g_return_val_if_fail (chunk != NULL, NULL);
+
+  if (!chunk->const_table)
+    chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+  lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
+
+  if (!lookup)
+    {
+      lookup = g_string_chunk_insert (chunk, string);
+      g_hash_table_insert (chunk->const_table, lookup, lookup);
+    }
+
+  return lookup;
+}
+
+/**
+ * g_string_chunk_insert_len:
+ * @chunk: a #GStringChunk
+ * @string: bytes to insert
+ * @len: number of bytes of @string to insert, or -1 to insert a 
+ *     nul-terminated string. 
+ * 
+ * Adds a copy of the first @len bytes of @string to the #GStringChunk. The
+ * copy is nul-terminated.
+ * 
+ * The characters in the string can be changed, if necessary, though you
+ * should not change anything after the end of the string.
+ * 
+ * Return value: a pointer to the copy of @string within the #GStringChunk
+ * 
+ * Since: 2.4
+ **/
+gchar*
+g_string_chunk_insert_len (GStringChunk *chunk,
+                          const gchar  *string, 
+                          gssize        len)
+{
+  gssize size;
+  gchar* pos;
+
+  g_return_val_if_fail (chunk != NULL, NULL);
+
+  if (len < 0)
+    size = strlen (string);
+  else
+    size = len;
+  
+  if ((chunk->storage_next + size + 1) > chunk->this_size)
+    {
+      gsize new_size = nearest_power (chunk->default_size, size + 1);
+
+      chunk->storage_list = g_slist_prepend (chunk->storage_list,
+                                            g_new (gchar, new_size));
+
+      chunk->this_size = new_size;
+      chunk->storage_next = 0;
+    }
+
+  pos = ((gchar *) chunk->storage_list->data) + chunk->storage_next;
+
+  *(pos + size) = '\0';
+
+  strncpy (pos, string, size);
+  if (len > 0)
+    size = strlen (pos);
+
+  chunk->storage_next += size + 1;
+
+  return pos;
+}
+
+#endif
+
+/* Strings.
+ */
+static void
+g_string_maybe_expand (GString* string,
+                      gsize    len) 
+{
+  if (string->len + len >= string->allocated_len)
+    {
+      string->allocated_len = nearest_power (1, string->len + len + 1);
+      string->str = g_realloc (string->str, string->allocated_len);
+    }
+}
+
+GString*
+g_string_sized_new (gsize dfl_size)    
+{
+  GString *string = g_slice_new (GString);
+
+  string->allocated_len = 0;
+  string->len   = 0;
+  string->str   = NULL;
+
+  g_string_maybe_expand (string, MAX (dfl_size, 2));
+  string->str[0] = 0;
+
+  return string;
+}
+
+GString*
+g_string_new (const gchar *init)
+{
+  GString *string;
+
+  if (init == NULL || *init == '\0')
+    string = g_string_sized_new (2);
+  else 
+    {
+      gint len;
+
+      len = strlen (init);
+      string = g_string_sized_new (len + 2);
+
+      g_string_append_len (string, init, len);
+    }
+
+  return string;
+}
+
+GString*
+g_string_new_len (const gchar *init,
+                  gssize       len)    
+{
+  GString *string;
+
+  if (len < 0)
+    return g_string_new (init);
+  else
+    {
+      string = g_string_sized_new (len);
+      
+      if (init)
+        g_string_append_len (string, init, len);
+      
+      return string;
+    }
+}
+
+gchar*
+g_string_free (GString *string,
+              gboolean free_segment)
+{
+  gchar *segment;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  if (free_segment)
+    {
+      g_free (string->str);
+      segment = NULL;
+    }
+  else
+    segment = string->str;
+
+  g_slice_free (GString, string);
+
+  return segment;
+}
+
+#if 0
+
+gboolean
+g_string_equal (const GString *v,
+                const GString *v2)
+{
+  gchar *p, *q;
+  GString *string1 = (GString *) v;
+  GString *string2 = (GString *) v2;
+  gsize i = string1->len;    
+
+  if (i != string2->len)
+    return FALSE;
+
+  p = string1->str;
+  q = string2->str;
+  while (i)
+    {
+      if (*p != *q)
+       return FALSE;
+      p++;
+      q++;
+      i--;
+    }
+  return TRUE;
+}
+
+/* 31 bit hash function */
+guint
+g_string_hash (const GString *str)
+{
+  const gchar *p = str->str;
+  gsize n = str->len;    
+  guint h = 0;
+
+  while (n--)
+    {
+      h = (h << 5) - h + *p;
+      p++;
+    }
+
+  return h;
+}
+
+GString*
+g_string_assign (GString     *string,
+                const gchar *rval)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (rval != NULL, string);
+
+  /* Make sure assigning to itself doesn't corrupt the string.  */
+  if (string->str != rval)
+    {
+      /* Assigning from substring should be ok since g_string_truncate
+        does not realloc.  */
+      g_string_truncate (string, 0);
+      g_string_append (string, rval);
+    }
+
+  return string;
+}
+
+GString*
+g_string_truncate (GString *string,
+                  gsize    len)    
+{
+  g_return_val_if_fail (string != NULL, NULL);
+
+  string->len = MIN (len, string->len);
+  string->str[string->len] = 0;
+
+  return string;
+}
+
+/**
+ * g_string_set_size:
+ * @string: a #GString
+ * @len: the new length
+ * 
+ * Sets the length of a #GString. If the length is less than
+ * the current length, the string will be truncated. If the
+ * length is greater than the current length, the contents
+ * of the newly added area are undefined. (However, as
+ * always, string->str[string->len] will be a nul byte.) 
+ * 
+ * Return value: @string
+ **/
+GString*
+g_string_set_size (GString *string,
+                  gsize    len)    
+{
+  g_return_val_if_fail (string != NULL, NULL);
+
+  if (len >= string->allocated_len)
+    g_string_maybe_expand (string, len - string->len);
+  
+  string->len = len;
+  string->str[len] = 0;
+
+  return string;
+}
+
+#endif
+
+GString*
+g_string_insert_len (GString     *string,
+                    gssize       pos,    
+                    const gchar *val,
+                    gssize       len)    
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (val != NULL, string);
+
+  if (len < 0)
+    len = strlen (val);
+
+  if (pos < 0)
+    pos = string->len;
+  else
+    g_return_val_if_fail (pos <= string->len, string);
+
+  /* Check whether val represents a substring of string.  This test
+     probably violates chapter and verse of the C standards, since
+     ">=" and "<=" are only valid when val really is a substring.
+     In practice, it will work on modern archs.  */
+  if (val >= string->str && val <= string->str + string->len)
+    {
+      gsize offset = val - string->str;
+      gsize precount = 0;
+
+      g_string_maybe_expand (string, len);
+      val = string->str + offset;
+      /* At this point, val is valid again.  */
+
+      /* Open up space where we are going to insert.  */
+      if (pos < string->len)
+       g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
+
+      /* Move the source part before the gap, if any.  */
+      if (offset < pos)
+       {
+         precount = MIN (len, pos - offset);
+         memcpy (string->str + pos, val, precount);
+       }
+
+      /* Move the source part after the gap, if any.  */
+      if (len > precount)
+       memcpy (string->str + pos + precount,
+               val + /* Already moved: */ precount + /* Space opened up: */ len,
+               len - precount);
+    }
+  else
+    {
+      g_string_maybe_expand (string, len);
+
+      /* If we aren't appending at the end, move a hunk
+       * of the old string to the end, opening up space
+       */
+      if (pos < string->len)
+       g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
+
+      /* insert the new string */
+      if (len == 1)
+        string->str[pos] = *val;
+      else
+        memcpy (string->str + pos, val, len);
+    }
+
+  string->len += len;
+
+  string->str[string->len] = 0;
+
+  return string;
+}
+
+GString*
+g_string_append (GString     *string,
+                const gchar *val)
+{  
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (val != NULL, string);
+
+  return g_string_insert_len (string, -1, val, -1);
+}
+
+GString*
+g_string_append_len (GString    *string,
+                     const gchar *val,
+                     gssize       len)    
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (val != NULL, string);
+
+  return g_string_insert_len (string, -1, val, len);
+}
+
+#undef g_string_append_c
+GString*
+g_string_append_c (GString *string,
+                  gchar    c)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+
+  return g_string_insert_c (string, -1, c);
+}
+
+/**
+ * g_string_append_unichar:
+ * @string: a #GString
+ * @wc: a Unicode character
+ * 
+ * Converts a Unicode character into UTF-8, and appends it
+ * to the string.
+ * 
+ * Return value: @string
+ **/
+GString*
+g_string_append_unichar (GString  *string,
+                        gunichar  wc)
+{  
+  g_return_val_if_fail (string != NULL, NULL);
+  
+  return g_string_insert_unichar (string, -1, wc);
+}
+
+#if 0
+
+GString*
+g_string_prepend (GString     *string,
+                 const gchar *val)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (val != NULL, string);
+  
+  return g_string_insert_len (string, 0, val, -1);
+}
+
+GString*
+g_string_prepend_len (GString    *string,
+                      const gchar *val,
+                      gssize       len)    
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (val != NULL, string);
+
+  return g_string_insert_len (string, 0, val, len);
+}
+
+GString*
+g_string_prepend_c (GString *string,
+                   gchar    c)
+{  
+  g_return_val_if_fail (string != NULL, NULL);
+  
+  return g_string_insert_c (string, 0, c);
+}
+
+/**
+ * g_string_prepend_unichar:
+ * @string: a #GString.
+ * @wc: a Unicode character.
+ * 
+ * Converts a Unicode character into UTF-8, and prepends it
+ * to the string.
+ * 
+ * Return value: @string.
+ **/
+GString*
+g_string_prepend_unichar (GString  *string,
+                         gunichar  wc)
+{  
+  g_return_val_if_fail (string != NULL, NULL);
+  
+  return g_string_insert_unichar (string, 0, wc);
+}
+
+GString*
+g_string_insert (GString     *string,
+                gssize       pos,    
+                const gchar *val)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (val != NULL, string);
+  if (pos >= 0)
+    g_return_val_if_fail (pos <= string->len, string);
+  
+  return g_string_insert_len (string, pos, val, -1);
+}
+
+#endif
+
+GString*
+g_string_insert_c (GString *string,
+                  gssize   pos,    
+                  gchar    c)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+
+  g_string_maybe_expand (string, 1);
+
+  if (pos < 0)
+    pos = string->len;
+  else
+    g_return_val_if_fail (pos <= string->len, string);
+  
+  /* If not just an append, move the old stuff */
+  if (pos < string->len)
+    g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
+
+  string->str[pos] = c;
+
+  string->len += 1;
+
+  string->str[string->len] = 0;
+
+  return string;
+}
+
+/**
+ * g_string_insert_unichar:
+ * @string: a #GString
+ * @pos: the position at which to insert character, or -1 to
+ *       append at the end of the string.
+ * @wc: a Unicode character
+ * 
+ * Converts a Unicode character into UTF-8, and insert it
+ * into the string at the given position.
+ * 
+ * Return value: @string
+ **/
+GString*
+g_string_insert_unichar (GString *string,
+                        gssize   pos,    
+                        gunichar wc)
+{
+  gint charlen, first, i;
+  gchar *dest;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  /* Code copied from g_unichar_to_utf() */
+  if (wc < 0x80)
+    {
+      first = 0;
+      charlen = 1;
+    }
+  else if (wc < 0x800)
+    {
+      first = 0xc0;
+      charlen = 2;
+    }
+  else if (wc < 0x10000)
+    {
+      first = 0xe0;
+      charlen = 3;
+    }
+   else if (wc < 0x200000)
+    {
+      first = 0xf0;
+      charlen = 4;
+    }
+  else if (wc < 0x4000000)
+    {
+      first = 0xf8;
+      charlen = 5;
+    }
+  else
+    {
+      first = 0xfc;
+      charlen = 6;
+    }
+  /* End of copied code */
+
+  g_string_maybe_expand (string, charlen);
+
+  if (pos < 0)
+    pos = string->len;
+  else
+    g_return_val_if_fail (pos <= string->len, string);
+
+  /* If not just an append, move the old stuff */
+  if (pos < string->len)
+    g_memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
+
+  dest = string->str + pos;
+  /* Code copied from g_unichar_to_utf() */
+  for (i = charlen - 1; i > 0; --i)
+    {
+      dest[i] = (wc & 0x3f) | 0x80;
+      wc >>= 6;
+    }
+  dest[0] = wc | first;
+  /* End of copied code */
+  
+  string->len += charlen;
+
+  string->str[string->len] = 0;
+
+  return string;
+}
+
+#if 0
+
+GString*
+g_string_erase (GString *string,
+               gssize   pos,
+               gssize   len)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (pos >= 0, string);
+  g_return_val_if_fail (pos <= string->len, string);
+
+  if (len < 0)
+    len = string->len - pos;
+  else
+    {
+      g_return_val_if_fail (pos + len <= string->len, string);
+
+      if (pos + len < string->len)
+       g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
+    }
+
+  string->len -= len;
+  
+  string->str[string->len] = 0;
+
+  return string;
+}
+
+/**
+ * g_string_ascii_down:
+ * @string: a GString
+ * 
+ * Converts all upper case ASCII letters to lower case ASCII letters.
+ * 
+ * Return value: passed-in @string pointer, with all the upper case
+ *               characters converted to lower case in place, with
+ *               semantics that exactly match g_ascii_tolower.
+ **/
+GString*
+g_string_ascii_down (GString *string)
+{
+  gchar *s;
+  gint n;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  n = string->len;
+  s = string->str;
+
+  while (n)
+    {
+      *s = g_ascii_tolower (*s);
+      s++;
+      n--;
+    }
+
+  return string;
+}
+
+/**
+ * g_string_ascii_up:
+ * @string: a GString
+ * 
+ * Converts all lower case ASCII letters to upper case ASCII letters.
+ * 
+ * Return value: passed-in @string pointer, with all the lower case
+ *               characters converted to upper case in place, with
+ *               semantics that exactly match g_ascii_toupper.
+ **/
+GString*
+g_string_ascii_up (GString *string)
+{
+  gchar *s;
+  gint n;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  n = string->len;
+  s = string->str;
+
+  while (n)
+    {
+      *s = g_ascii_toupper (*s);
+      s++;
+      n--;
+    }
+
+  return string;
+}
+
+/**
+ * g_string_down:
+ * @string: a #GString
+ *  
+ * Converts a #GString to lowercase.
+ *
+ * Returns: the #GString.
+ *
+ * Deprecated:2.2: This function uses the locale-specific tolower() function, 
+ * which is almost never the right thing. Use g_string_ascii_down() or 
+ * g_utf8_strdown() instead.
+ */
+GString*
+g_string_down (GString *string)
+{
+  guchar *s;
+  glong n;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  n = string->len;    
+  s = (guchar *) string->str;
+
+  while (n)
+    {
+      if (isupper (*s))
+       *s = tolower (*s);
+      s++;
+      n--;
+    }
+
+  return string;
+}
+
+/**
+ * g_string_up:
+ * @string: a #GString 
+ * 
+ * Converts a #GString to uppercase.
+ * 
+ * Return value: the #GString
+ *
+ * Deprecated:2.2: This function uses the locale-specific toupper() function, 
+ * which is almost never the right thing. Use g_string_ascii_up() or 
+ * g_utf8_strup() instead.
+ **/
+GString*
+g_string_up (GString *string)
+{
+  guchar *s;
+  glong n;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  n = string->len;
+  s = (guchar *) string->str;
+
+  while (n)
+    {
+      if (islower (*s))
+       *s = toupper (*s);
+      s++;
+      n--;
+    }
+
+  return string;
+}
+
+#endif
+
+static void
+g_string_append_printf_internal (GString     *string,
+                                const gchar *fmt,
+                                va_list      args)
+{
+  gchar *buffer;
+  gint length;
+  
+  length = g_vasprintf (&buffer, fmt, args);
+  g_string_append_len (string, buffer, length);
+  g_free (buffer);
+}
+
+#if 0
+
+void
+g_string_printf (GString *string,
+                const gchar *fmt,
+                ...)
+{
+  va_list args;
+
+  g_string_truncate (string, 0);
+
+  va_start (args, fmt);
+  g_string_append_printf_internal (string, fmt, args);
+  va_end (args);
+}
+
+#endif
+
+void
+g_string_append_printf (GString *string,
+                       const gchar *fmt,
+                       ...)
+{
+  va_list args;
+
+  va_start (args, fmt);
+  g_string_append_printf_internal (string, fmt, args);
+  va_end (args);
+}
+
+#if 0
+#define __G_STRING_C__
+#include "galiasdef.c"
+#endif
diff --git a/gnulib-local/lib/glib/gstring_.h b/gnulib-local/lib/glib/gstring_.h
new file mode 100644 (file)
index 0000000..d167eaf
--- /dev/null
@@ -0,0 +1,179 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#ifndef __G_STRING_H__
+#define __G_STRING_H__
+
+#include <glib/gtypes.h>
+#if 0
+#include <glib/gunicode.h>
+#include <glib/gutils.h>  /* for G_CAN_INLINE */
+#endif
+
+G_BEGIN_DECLS
+
+typedef struct _GString                GString;
+#if 0
+typedef struct _GStringChunk   GStringChunk;
+#endif
+
+struct _GString
+{
+  gchar  *str;
+  gsize len;    
+  gsize allocated_len;
+};
+
+#if 0
+/* String Chunks
+ */
+GStringChunk* g_string_chunk_new          (gsize size);  
+void         g_string_chunk_free          (GStringChunk *chunk);
+gchar*       g_string_chunk_insert        (GStringChunk *chunk,
+                                           const gchar  *string);
+gchar*       g_string_chunk_insert_len    (GStringChunk *chunk,
+                                           const gchar  *string,
+                                           gssize        len);
+gchar*       g_string_chunk_insert_const  (GStringChunk *chunk,
+                                           const gchar  *string);
+#endif
+
+
+/* Strings
+ */
+GString*     g_string_new              (const gchar     *init);
+GString*     g_string_new_len           (const gchar     *init,
+                                         gssize           len);   
+#if 0
+GString*     g_string_sized_new         (gsize            dfl_size);  
+#endif
+gchar*      g_string_free              (GString         *string,
+                                        gboolean         free_segment);
+#if 0
+gboolean     g_string_equal             (const GString  *v,
+                                        const GString   *v2);
+guint        g_string_hash              (const GString   *str);
+GString*     g_string_assign            (GString        *string,
+                                        const gchar     *rval);
+GString*     g_string_truncate          (GString        *string,
+                                        gsize            len);    
+GString*     g_string_set_size          (GString         *string,
+                                        gsize            len);
+GString*     g_string_insert_len        (GString         *string,
+                                         gssize           pos,   
+                                         const gchar     *val,
+                                         gssize           len);  
+#endif
+GString*     g_string_append            (GString        *string,
+                                        const gchar     *val);
+GString*     g_string_append_len        (GString        *string,
+                                        const gchar     *val,
+                                         gssize           len);  
+GString*     g_string_append_c          (GString        *string,
+                                        gchar            c);
+GString*     g_string_append_unichar    (GString        *string,
+                                        gunichar         wc);
+#if 0
+GString*     g_string_prepend           (GString        *string,
+                                        const gchar     *val);
+GString*     g_string_prepend_c         (GString        *string,
+                                        gchar            c);
+GString*     g_string_prepend_unichar   (GString        *string,
+                                        gunichar         wc);
+GString*     g_string_prepend_len       (GString        *string,
+                                        const gchar     *val,
+                                         gssize           len);  
+GString*     g_string_insert            (GString        *string,
+                                        gssize           pos,    
+                                        const gchar     *val);
+#endif
+GString*     g_string_insert_c          (GString        *string,
+                                        gssize           pos,    
+                                        gchar            c);
+GString*     g_string_insert_unichar    (GString        *string,
+                                        gssize           pos,    
+                                        gunichar         wc);
+#if 0
+GString*     g_string_erase            (GString         *string,
+                                        gssize           pos,
+                                        gssize           len);
+GString*     g_string_ascii_down        (GString        *string);
+GString*     g_string_ascii_up          (GString        *string);
+void         g_string_printf            (GString        *string,
+                                        const gchar     *format,
+                                        ...) G_GNUC_PRINTF (2, 3);
+#endif
+void         g_string_append_printf     (GString        *string,
+                                        const gchar     *format,
+                                        ...) G_GNUC_PRINTF (2, 3);
+
+#if 0
+
+/* -- optimize g_strig_append_c --- */
+#ifdef G_CAN_INLINE
+static inline GString*
+g_string_append_c_inline (GString *gstring,
+                          gchar    c)
+{
+  if (gstring->len + 1 < gstring->allocated_len)
+    {
+      gstring->str[gstring->len++] = c;
+      gstring->str[gstring->len] = 0;
+    }
+  else
+    g_string_insert_c (gstring, -1, c);
+  return gstring;
+}
+#define g_string_append_c(gstr,c)       g_string_append_c_inline (gstr, c)
+#endif /* G_CAN_INLINE */
+
+
+#ifndef G_DISABLE_DEPRECATED
+
+/* The following two functions are deprecated and will be removed in
+ * the next major release. They use the locale-specific tolower and
+ * toupper, which is almost never the right thing.
+ */
+
+GString*     g_string_down              (GString        *string);
+GString*     g_string_up                (GString        *string);
+
+/* These aliases are included for compatibility. */
+#define        g_string_sprintf        g_string_printf
+#define        g_string_sprintfa       g_string_append_printf
+
+#endif /* G_DISABLE_DEPRECATED */
+
+#endif
+
+G_END_DECLS
+
+#endif /* __G_STRING_H__ */
+
diff --git a/gnulib-local/lib/glib/gtypes_.h b/gnulib-local/lib/glib/gtypes_.h
new file mode 100644 (file)
index 0000000..4045027
--- /dev/null
@@ -0,0 +1,430 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#ifndef __G_TYPES_H__
+#define __G_TYPES_H__
+
+#include <glibconfig.h>
+
+G_BEGIN_DECLS
+
+/* Provide type definitions for commonly used types.
+ *  These are useful because a "gint8" can be adjusted
+ *  to be 1 byte (8 bits) on all platforms. Similarly and
+ *  more importantly, "gint32" can be adjusted to be
+ *  4 bytes (32 bits) on all platforms.
+ */
+
+typedef char   gchar;
+typedef short  gshort;
+typedef long   glong;
+typedef int    gint;
+typedef gint   gboolean;
+
+typedef unsigned char   guchar;
+typedef unsigned short  gushort;
+typedef unsigned long   gulong;
+typedef unsigned int    guint;
+
+typedef float   gfloat;
+typedef double  gdouble;
+
+/* Define min and max constants for the fixed size numerical types */
+#define G_MININT8      ((gint8)  0x80)
+#define G_MAXINT8      ((gint8)  0x7f)
+#define G_MAXUINT8     ((guint8) 0xff)
+
+#define G_MININT16     ((gint16)  0x8000)
+#define G_MAXINT16     ((gint16)  0x7fff)
+#define G_MAXUINT16    ((guint16) 0xffff)
+
+#define G_MININT32     ((gint32)  0x80000000)
+#define G_MAXINT32     ((gint32)  0x7fffffff)
+#define G_MAXUINT32    ((guint32) 0xffffffff)
+
+#define G_MININT64     ((gint64) G_GINT64_CONSTANT(0x8000000000000000))
+#define G_MAXINT64     G_GINT64_CONSTANT(0x7fffffffffffffff)
+#define G_MAXUINT64    G_GINT64_CONSTANT(0xffffffffffffffffU)
+
+typedef void* gpointer;
+typedef const void *gconstpointer;
+
+typedef gint            (*GCompareFunc)         (gconstpointer  a,
+                                                 gconstpointer  b);
+typedef gint            (*GCompareDataFunc)     (gconstpointer  a,
+                                                 gconstpointer  b,
+                                                gpointer       user_data);
+typedef gboolean        (*GEqualFunc)           (gconstpointer  a,
+                                                 gconstpointer  b);
+typedef void            (*GDestroyNotify)       (gpointer       data);
+typedef void            (*GFunc)                (gpointer       data,
+                                                 gpointer       user_data);
+typedef guint           (*GHashFunc)            (gconstpointer  key);
+typedef void            (*GHFunc)               (gpointer       key,
+                                                 gpointer       value,
+                                                 gpointer       user_data);
+typedef void            (*GFreeFunc)            (gpointer       data);
+typedef const gchar *   (*GTranslateFunc)       (const gchar   *str,
+                                                gpointer       data);
+
+
+/* Define some mathematical constants that aren't available
+ * symbolically in some strict ISO C implementations.
+ */
+#define G_E     2.7182818284590452353602874713526624977572470937000
+#define G_LN2   0.69314718055994530941723212145817656807550013436026
+#define G_LN10  2.3025850929940456840179914546843642076011014886288
+#define G_PI    3.1415926535897932384626433832795028841971693993751
+#define G_PI_2  1.5707963267948966192313216916397514420985846996876
+#define G_PI_4  0.78539816339744830961566084581987572104929234984378
+#define G_SQRT2 1.4142135623730950488016887242096980785696718753769
+
+#if 0
+
+/* Portable endian checks and conversions
+ *
+ * glibconfig.h defines G_BYTE_ORDER which expands to one of
+ * the below macros.
+ */
+#define G_LITTLE_ENDIAN 1234
+#define G_BIG_ENDIAN    4321
+#define G_PDP_ENDIAN    3412           /* unused, need specific PDP check */   
+
+
+/* Basic bit swapping functions
+ */
+#define GUINT16_SWAP_LE_BE_CONSTANT(val)       ((guint16) ( \
+    (guint16) ((guint16) (val) >> 8) | \
+    (guint16) ((guint16) (val) << 8)))
+
+#define GUINT32_SWAP_LE_BE_CONSTANT(val)       ((guint32) ( \
+    (((guint32) (val) & (guint32) 0x000000ffU) << 24) | \
+    (((guint32) (val) & (guint32) 0x0000ff00U) <<  8) | \
+    (((guint32) (val) & (guint32) 0x00ff0000U) >>  8) | \
+    (((guint32) (val) & (guint32) 0xff000000U) >> 24)))
+
+#define GUINT64_SWAP_LE_BE_CONSTANT(val)       ((guint64) ( \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0x00000000000000ffU)) << 56) |     \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0x000000000000ff00U)) << 40) |     \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0x0000000000ff0000U)) << 24) |     \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0x00000000ff000000U)) <<  8) |     \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0x000000ff00000000U)) >>  8) |     \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0x0000ff0000000000U)) >> 24) |     \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0x00ff000000000000U)) >> 40) |     \
+      (((guint64) (val) &                                              \
+       (guint64) G_GINT64_CONSTANT (0xff00000000000000U)) >> 56)))
+
+/* Arch specific stuff for speed
+ */
+#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__)
+#  if defined (__i386__)
+#    define GUINT16_SWAP_LE_BE_IA32(val) \
+       (__extension__                                          \
+       ({ register guint16 __v, __x = ((guint16) (val));       \
+          if (__builtin_constant_p (__x))                      \
+            __v = GUINT16_SWAP_LE_BE_CONSTANT (__x);           \
+          else                                                 \
+            __asm__ ("rorw $8, %w0"                            \
+                     : "=r" (__v)                              \
+                     : "0" (__x)                               \
+                     : "cc");                                  \
+           __v; }))
+#    if !defined (__i486__) && !defined (__i586__) \
+       && !defined (__pentium__) && !defined (__i686__) \
+       && !defined (__pentiumpro__) && !defined (__pentium4__)
+#       define GUINT32_SWAP_LE_BE_IA32(val) \
+         (__extension__                                        \
+          ({ register guint32 __v, __x = ((guint32) (val));    \
+             if (__builtin_constant_p (__x))                   \
+               __v = GUINT32_SWAP_LE_BE_CONSTANT (__x);        \
+             else                                              \
+               __asm__ ("rorw $8, %w0\n\t"                     \
+                        "rorl $16, %0\n\t"                     \
+                        "rorw $8, %w0"                         \
+                        : "=r" (__v)                           \
+                        : "0" (__x)                            \
+                        : "cc");                               \
+             __v; }))
+#    else /* 486 and higher has bswap */
+#       define GUINT32_SWAP_LE_BE_IA32(val) \
+         (__extension__                                        \
+          ({ register guint32 __v, __x = ((guint32) (val));    \
+             if (__builtin_constant_p (__x))                   \
+               __v = GUINT32_SWAP_LE_BE_CONSTANT (__x);        \
+             else                                              \
+               __asm__ ("bswap %0"                             \
+                        : "=r" (__v)                           \
+                        : "0" (__x));                          \
+             __v; }))
+#    endif /* processor specific 32-bit stuff */
+#    define GUINT64_SWAP_LE_BE_IA32(val) \
+       (__extension__                                                  \
+       ({ union { guint64 __ll;                                        \
+                  guint32 __l[2]; } __w, __r;                          \
+          __w.__ll = ((guint64) (val));                                \
+          if (__builtin_constant_p (__w.__ll))                         \
+            __r.__ll = GUINT64_SWAP_LE_BE_CONSTANT (__w.__ll);         \
+          else                                                         \
+            {                                                          \
+              __r.__l[0] = GUINT32_SWAP_LE_BE (__w.__l[1]);            \
+              __r.__l[1] = GUINT32_SWAP_LE_BE (__w.__l[0]);            \
+            }                                                          \
+          __r.__ll; }))
+     /* Possibly just use the constant version and let gcc figure it out? */
+#    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA32 (val))
+#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA32 (val))
+#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA32 (val))
+#  elif defined (__ia64__)
+#    define GUINT16_SWAP_LE_BE_IA64(val) \
+       (__extension__                                          \
+       ({ register guint16 __v, __x = ((guint16) (val));       \
+          if (__builtin_constant_p (__x))                      \
+            __v = GUINT16_SWAP_LE_BE_CONSTANT (__x);           \
+          else                                                 \
+            __asm__ __volatile__ ("shl %0 = %1, 48 ;;"         \
+                                  "mux1 %0 = %0, @rev ;;"      \
+                                   : "=r" (__v)                \
+                                   : "r" (__x));               \
+           __v; }))
+#    define GUINT32_SWAP_LE_BE_IA64(val) \
+       (__extension__                                          \
+        ({ register guint32 __v, __x = ((guint32) (val));      \
+           if (__builtin_constant_p (__x))                     \
+             __v = GUINT32_SWAP_LE_BE_CONSTANT (__x);          \
+           else                                                \
+            __asm__ __volatile__ ("shl %0 = %1, 32 ;;"         \
+                                  "mux1 %0 = %0, @rev ;;"      \
+                                   : "=r" (__v)                \
+                                   : "r" (__x));               \
+           __v; }))
+#    define GUINT64_SWAP_LE_BE_IA64(val) \
+       (__extension__                                          \
+       ({ register guint64 __v, __x = ((guint64) (val));       \
+          if (__builtin_constant_p (__x))                      \
+            __v = GUINT64_SWAP_LE_BE_CONSTANT (__x);           \
+          else                                                 \
+            __asm__ __volatile__ ("mux1 %0 = %1, @rev ;;"      \
+                                  : "=r" (__v)                 \
+                                  : "r" (__x));                \
+          __v; }))
+#    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_IA64 (val))
+#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_IA64 (val))
+#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_IA64 (val))
+#  elif defined (__x86_64__)
+#    define GUINT32_SWAP_LE_BE_X86_64(val) \
+       (__extension__                                          \
+        ({ register guint32 __v, __x = ((guint32) (val));      \
+           if (__builtin_constant_p (__x))                     \
+             __v = GUINT32_SWAP_LE_BE_CONSTANT (__x);          \
+           else                                                \
+            __asm__ ("bswapl %0"                               \
+                     : "=r" (__v)                              \
+                     : "0" (__x));                             \
+           __v; }))
+#    define GUINT64_SWAP_LE_BE_X86_64(val) \
+       (__extension__                                          \
+       ({ register guint64 __v, __x = ((guint64) (val));       \
+          if (__builtin_constant_p (__x))                      \
+            __v = GUINT64_SWAP_LE_BE_CONSTANT (__x);           \
+          else                                                 \
+            __asm__ ("bswapq %0"                               \
+                     : "=r" (__v)                              \
+                     : "0" (__x));                             \
+          __v; }))
+     /* gcc seems to figure out optimal code for this on its own */
+#    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
+#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_X86_64 (val))
+#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_X86_64 (val))
+#  else /* generic gcc */
+#    define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
+#    define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val))
+#    define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val))
+#  endif
+#else /* generic */
+#  define GUINT16_SWAP_LE_BE(val) (GUINT16_SWAP_LE_BE_CONSTANT (val))
+#  define GUINT32_SWAP_LE_BE(val) (GUINT32_SWAP_LE_BE_CONSTANT (val))
+#  define GUINT64_SWAP_LE_BE(val) (GUINT64_SWAP_LE_BE_CONSTANT (val))
+#endif /* generic */
+
+#define GUINT16_SWAP_LE_PDP(val)       ((guint16) (val))
+#define GUINT16_SWAP_BE_PDP(val)       (GUINT16_SWAP_LE_BE (val))
+#define GUINT32_SWAP_LE_PDP(val)       ((guint32) ( \
+    (((guint32) (val) & (guint32) 0x0000ffffU) << 16) | \
+    (((guint32) (val) & (guint32) 0xffff0000U) >> 16)))
+#define GUINT32_SWAP_BE_PDP(val)       ((guint32) ( \
+    (((guint32) (val) & (guint32) 0x00ff00ffU) << 8) | \
+    (((guint32) (val) & (guint32) 0xff00ff00U) >> 8)))
+
+/* The G*_TO_?E() macros are defined in glibconfig.h.
+ * The transformation is symmetric, so the FROM just maps to the TO.
+ */
+#define GINT16_FROM_LE(val)    (GINT16_TO_LE (val))
+#define GUINT16_FROM_LE(val)   (GUINT16_TO_LE (val))
+#define GINT16_FROM_BE(val)    (GINT16_TO_BE (val))
+#define GUINT16_FROM_BE(val)   (GUINT16_TO_BE (val))
+#define GINT32_FROM_LE(val)    (GINT32_TO_LE (val))
+#define GUINT32_FROM_LE(val)   (GUINT32_TO_LE (val))
+#define GINT32_FROM_BE(val)    (GINT32_TO_BE (val))
+#define GUINT32_FROM_BE(val)   (GUINT32_TO_BE (val))
+
+#define GINT64_FROM_LE(val)    (GINT64_TO_LE (val))
+#define GUINT64_FROM_LE(val)   (GUINT64_TO_LE (val))
+#define GINT64_FROM_BE(val)    (GINT64_TO_BE (val))
+#define GUINT64_FROM_BE(val)   (GUINT64_TO_BE (val))
+
+#define GLONG_FROM_LE(val)     (GLONG_TO_LE (val))
+#define GULONG_FROM_LE(val)    (GULONG_TO_LE (val))
+#define GLONG_FROM_BE(val)     (GLONG_TO_BE (val))
+#define GULONG_FROM_BE(val)    (GULONG_TO_BE (val))
+
+#define GINT_FROM_LE(val)      (GINT_TO_LE (val))
+#define GUINT_FROM_LE(val)     (GUINT_TO_LE (val))
+#define GINT_FROM_BE(val)      (GINT_TO_BE (val))
+#define GUINT_FROM_BE(val)     (GUINT_TO_BE (val))
+
+
+/* Portable versions of host-network order stuff
+ */
+#define g_ntohl(val) (GUINT32_FROM_BE (val))
+#define g_ntohs(val) (GUINT16_FROM_BE (val))
+#define g_htonl(val) (GUINT32_TO_BE (val))
+#define g_htons(val) (GUINT16_TO_BE (val))
+
+/* IEEE Standard 754 Single Precision Storage Format (gfloat):
+ *
+ *        31 30           23 22            0
+ * +--------+---------------+---------------+
+ * | s 1bit | e[30:23] 8bit | f[22:0] 23bit |
+ * +--------+---------------+---------------+
+ * B0------------------->B1------->B2-->B3-->
+ *
+ * IEEE Standard 754 Double Precision Storage Format (gdouble):
+ *
+ *        63 62            52 51            32   31            0
+ * +--------+----------------+----------------+ +---------------+
+ * | s 1bit | e[62:52] 11bit | f[51:32] 20bit | | f[31:0] 32bit |
+ * +--------+----------------+----------------+ +---------------+
+ * B0--------------->B1---------->B2--->B3---->  B4->B5->B6->B7->
+ */
+/* subtract from biased_exponent to form base2 exponent (normal numbers) */
+typedef union  _GDoubleIEEE754 GDoubleIEEE754;
+typedef union  _GFloatIEEE754  GFloatIEEE754;
+#define G_IEEE754_FLOAT_BIAS   (127)
+#define G_IEEE754_DOUBLE_BIAS  (1023)
+/* multiply with base2 exponent to get base10 exponent (normal numbers) */
+#define G_LOG_2_BASE_10                (0.30102999566398119521)
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+union _GFloatIEEE754
+{
+  gfloat v_float;
+  struct {
+    guint mantissa : 23;
+    guint biased_exponent : 8;
+    guint sign : 1;
+  } mpn;
+};
+union _GDoubleIEEE754
+{
+  gdouble v_double;
+  struct {
+    guint mantissa_low : 32;
+    guint mantissa_high : 20;
+    guint biased_exponent : 11;
+    guint sign : 1;
+  } mpn;
+};
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+union _GFloatIEEE754
+{
+  gfloat v_float;
+  struct {
+    guint sign : 1;
+    guint biased_exponent : 8;
+    guint mantissa : 23;
+  } mpn;
+};
+union _GDoubleIEEE754
+{
+  gdouble v_double;
+  struct {
+    guint sign : 1;
+    guint biased_exponent : 11;
+    guint mantissa_high : 20;
+    guint mantissa_low : 32;
+  } mpn;
+};
+#else /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+#error unknown ENDIAN type
+#endif /* !G_LITTLE_ENDIAN && !G_BIG_ENDIAN */
+
+typedef struct _GTimeVal                GTimeVal;
+
+struct _GTimeVal
+{
+  glong tv_sec;
+  glong tv_usec;
+};
+
+#endif
+
+G_END_DECLS
+
+/* We prefix variable declarations so they can
+ * properly get exported in windows dlls.
+ */
+#ifndef GLIB_VAR
+#  ifdef G_PLATFORM_WIN32
+#    ifdef GLIB_STATIC_COMPILATION
+#      define GLIB_VAR extern
+#    else /* !GLIB_STATIC_COMPILATION */
+#      ifdef GLIB_COMPILATION
+#        ifdef DLL_EXPORT
+#          define GLIB_VAR __declspec(dllexport)
+#        else /* !DLL_EXPORT */
+#          define GLIB_VAR extern
+#        endif /* !DLL_EXPORT */
+#      else /* !GLIB_COMPILATION */
+#        define GLIB_VAR extern __declspec(dllimport)
+#      endif /* !GLIB_COMPILATION */
+#    endif /* !GLIB_STATIC_COMPILATION */
+#  else /* !G_PLATFORM_WIN32 */
+#    define GLIB_VAR extern
+#  endif /* !G_PLATFORM_WIN32 */
+#endif /* GLIB_VAR */
+
+#endif /* __G_TYPES_H__ */
+
diff --git a/gnulib-local/lib/glib_.h b/gnulib-local/lib/glib_.h
new file mode 100644 (file)
index 0000000..3ffb254
--- /dev/null
@@ -0,0 +1,98 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+#ifndef __G_LIB_H__
+#define __G_LIB_H__
+
+#if 0
+#include <glib/galloca.h>
+#include <glib/garray.h>
+#include <glib/gasyncqueue.h>
+#include <glib/gatomic.h>
+#include <glib/gbacktrace.h>
+#include <glib/gbase64.h>
+#include <glib/gbookmarkfile.h>
+#include <glib/gcache.h>
+#include <glib/gcompletion.h>
+#include <glib/gconvert.h>
+#include <glib/gdataset.h>
+#include <glib/gdate.h>
+#include <glib/gdir.h>
+#include <glib/gerror.h>
+#include <glib/gfileutils.h>
+#endif
+#include <glib/ghash.h>
+#if 0
+#include <glib/ghook.h>
+#include <glib/giochannel.h>
+#include <glib/gkeyfile.h>
+#endif
+#include <glib/glist.h>
+#if 0
+#include <glib/gmacros.h>
+#include <glib/gmain.h>
+#include <glib/gmappedfile.h>
+#include <glib/gmarkup.h>
+#include <glib/gmem.h>
+#include <glib/gmessages.h>
+#include <glib/gnode.h>
+#include <glib/goption.h>
+#include <glib/gpattern.h>
+#endif
+#include <glib/gprimes.h>
+#if 0
+#include <glib/gqsort.h>
+#include <glib/gquark.h>
+#include <glib/gqueue.h>
+#include <glib/grand.h>
+#include <glib/grel.h>
+#include <glib/gscanner.h>
+#include <glib/gshell.h>
+#include <glib/gslist.h>
+#include <glib/gspawn.h>
+#endif
+#include <glib/gstrfuncs.h>
+#include <glib/gstring.h>
+#if 0
+#include <glib/gthread.h>
+#include <glib/gthreadpool.h>
+#include <glib/gtimer.h>
+#include <glib/gtree.h>
+#endif
+#include <glib/gtypes.h>
+#if 0
+#include <glib/gunicode.h>
+#include <glib/gutils.h>
+#ifdef G_PLATFORM_WIN32
+#include <glib/gwin32.h>
+#endif
+#endif
+
+#endif /* __G_LIB_H__ */
diff --git a/gnulib-local/lib/glibconfig_.h b/gnulib-local/lib/glibconfig_.h
new file mode 100644 (file)
index 0000000..1e3dd34
--- /dev/null
@@ -0,0 +1,189 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  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/. 
+ */
+
+/*
+ * Modified by Bruno Haible for use as a gnulib module.
+ */
+
+/* ====================== Substitute for glibconfig.h ====================== */
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+typedef uint16_t guint16;
+typedef uint32_t guint32;
+
+typedef size_t gsize;
+typedef ssize_t gssize;
+
+#define GPOINTER_TO_INT(p)     ((gint)   (p))
+#define GPOINTER_TO_UINT(p)    ((guint)  (p))
+
+#define GINT_TO_POINTER(i)     ((gpointer)  (i))
+#define GUINT_TO_POINTER(u)    ((gpointer)  (u))
+
+#define g_memmove memmove
+
+/* ================ Abridged version of for <glib/macros.h> ================ */
+
+#if    __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+#define G_GNUC_PURE                            \
+  __attribute__((__pure__))
+#define G_GNUC_MALLOC                          \
+  __attribute__((__malloc__))
+#else
+#define G_GNUC_PURE
+#define G_GNUC_MALLOC
+#endif
+
+#if     __GNUC__ >= 4
+#define G_GNUC_NULL_TERMINATED __attribute__((__sentinel__))
+#else
+#define G_GNUC_NULL_TERMINATED
+#endif
+
+#if     __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define G_GNUC_PRINTF( format_idx, arg_idx )    \
+  __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#define G_GNUC_SCANF( format_idx, arg_idx )     \
+  __attribute__((__format__ (__scanf__, format_idx, arg_idx)))
+#define G_GNUC_FORMAT( arg_idx )                \
+  __attribute__((__format_arg__ (arg_idx)))
+#define G_GNUC_NORETURN                         \
+  __attribute__((__noreturn__))
+#define G_GNUC_CONST                            \
+  __attribute__((__const__))
+#define G_GNUC_UNUSED                           \
+  __attribute__((__unused__))
+#define G_GNUC_NO_INSTRUMENT                   \
+  __attribute__((__no_instrument_function__))
+#else   /* !__GNUC__ */
+#define G_GNUC_PRINTF( format_idx, arg_idx )
+#define G_GNUC_SCANF( format_idx, arg_idx )
+#define G_GNUC_FORMAT( arg_idx )
+#define G_GNUC_NORETURN
+#define G_GNUC_CONST
+#define G_GNUC_UNUSED
+#define G_GNUC_NO_INSTRUMENT
+#endif  /* !__GNUC__ */
+
+#if    __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define G_GNUC_WARN_UNUSED_RESULT              \
+  __attribute__((warn_unused_result))
+#else
+#define G_GNUC_WARN_UNUSED_RESULT
+#endif /* __GNUC__ */
+
+#ifdef  __cplusplus
+# define G_BEGIN_DECLS  extern "C" {
+# define G_END_DECLS    }
+#else
+# define G_BEGIN_DECLS
+# define G_END_DECLS
+#endif
+
+#ifndef        FALSE
+#define        FALSE   (0)
+#endif
+
+#ifndef        TRUE
+#define        TRUE    (!FALSE)
+#endif
+
+#undef MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+
+#undef MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+
+#define G_STMT_START
+#define G_STMT_END
+
+/* ====================== Substitute for <glib/gmem.h> ====================== */
+
+#include "xalloc.h"
+
+#define g_malloc(n) xmalloc (n)
+#define g_malloc0(n) xzalloc (n)
+#define g_realloc(p,n) xrealloc (p, n)
+#define g_free(p) free (p)
+#define g_try_malloc(n) xmalloc (n)
+#define g_try_malloc0(n) xzalloc (n)
+#define g_try_realloc(p,n) xrealloc (p, n)
+
+#define g_new(t,n) ((t *) xnmalloc (n, sizeof (t)))
+#define g_new0(t,n) ((t *) xcalloc (n, sizeof (t)))
+#define g_try_new(t,n) ((t *) xnmalloc (n, sizeof (t)))
+#define g_try_new0(t,n) ((t *) xcalloc (n, sizeof (t)))
+
+/* =================== Substitute for <glib/gmessages.h> =================== */
+
+#include <stdlib.h>
+
+#define g_assert(expr)                 if (!(expr)) abort ()
+#define g_assert_not_reached()         abort ()
+
+#define g_return_if_fail(expr)         if (!(expr)) abort ()
+#define g_return_val_if_fail(expr,val) if (!(expr)) abort ()
+#define g_return_if_reached()          abort ()
+#define g_return_val_if_reached(val)   abort ()
+
+#define G_LOG_LEVEL_CRITICAL 0
+#define G_LOG_LEVEL_INFO     0
+#define G_LOG_LEVEL_DEBUG    0
+
+extern void g_printerr (const char *format, ...) G_GNUC_PRINTF (1, 2);
+extern void g_warning (const char *format, ...) G_GNUC_PRINTF (1, 2);
+extern void g_log (const char *domain, int level, const char *format, ...) G_GNUC_PRINTF (3, 4);
+
+/* ==================== Substitute for <glib/gprintf.h> ==================== */
+
+#include "vasprintf.h"
+
+#define g_printf printf
+#define g_fprintf fprintf
+#define g_sprintf sprintf
+#define g_vprintf vprintf
+#define g_vfprintf vfprintf
+#define g_vsprintf vsprintf
+#define g_vasprintf vasprintf
+
+/* ===================== Substitute for <glib/gslice.h> ===================== */
+
+#define g_slice_new(t) XMALLOC (t)
+#define g_slice_new0(t) XZALLOC (t)
+
+#define g_slice_free(t,p) free (p)
+
+/* ======================= Helper for <glib/gtypes.h> ======================= */
+
+/* We don't need to export variables from a shared library.  */
+#define GLIB_VAR extern
+
+/* ==================== Substitute for <glib/gunicode.h> ==================== */
+
+typedef unsigned int gunichar;
diff --git a/gnulib-local/m4/libglib.m4 b/gnulib-local/m4/libglib.m4
new file mode 100644 (file)
index 0000000..952bb89
--- /dev/null
@@ -0,0 +1,111 @@
+# libglib.m4 serial 1 (gettext-0.16.1)
+dnl Copyright (C) 2006 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([gl_LIBGLIB],
+[
+  AC_MSG_CHECKING([whether included glib is requested])
+  AC_ARG_WITH([included-glib],
+    [  --with-included-glib    use the glib2 included here],
+    [gl_cv_libglib_force_included=$withval],
+    [gl_cv_libglib_force_included=no])
+  AC_MSG_RESULT([$gl_cv_libglib_force_included])
+
+  gl_cv_libglib_use_included="$gl_cv_libglib_force_included"
+  LIBGLIB=
+  LTLIBGLIB=
+  INCGLIB=
+  if test "$gl_cv_libglib_use_included" != yes; then
+    dnl Figure out whether we can use a preinstalled libglib-2.0, or have to use
+    dnl the included one.
+    AC_CACHE_VAL([gl_cv_libglib], [
+      gl_cv_libglib=no
+      gl_cv_LIBGLIB=
+      gl_cv_LTLIBGLIB=
+      gl_cv_INCGLIB=
+      gl_save_LIBS="$LIBS"
+      dnl Search for libglib2 and define LIBGLIB_2_0, LTLIBGLIB_2_0 and
+      dnl INCGLIB_2_0 accordingly.
+      dnl Don't use glib-config nor pkg-config, since it doesn't work when
+      dnl cross-compiling or when the C compiler in use is different from the
+      dnl one that built the library.
+      AC_LIB_LINKFLAGS_BODY([glib-2.0])
+      LIBS="$gl_save_LIBS $LIBGLIB_2_0"
+      AC_TRY_LINK([#include <glib.h>],
+        [g_string_new ("foo");],
+        [gl_cv_libglib=yes
+         gl_cv_LIBGLIB="$LIBGLIB_2_0"
+         gl_cv_LTLIBGLIB="$LTLIBGLIB_2_0"
+        ])
+      if test "$gl_cv_libglib" != yes; then
+        gl_save_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $INCGLIB_2_0"
+        AC_TRY_LINK([#include <glib.h>],
+          [g_string_new ("foo");],
+          [gl_cv_libglib=yes
+           gl_cv_LIBGLIB="$LIBGLIB_2_0"
+           gl_cv_LTLIBGLIB="$LTLIBGLIB_2_0"
+           gl_cv_INCGLIB="$INCGLIB_2_0"
+          ])
+        if test "$gl_cv_libglib" != yes; then
+          dnl Often the include files are installed in /usr/include/glib-2.0
+          dnl and /usr/lib/glib-2.0/include.
+          if test -n "$LIBGLIB_2_0_PREFIX"; then
+            CPPFLAGS="$gl_save_CPPFLAGS -I$LIBGLIB_2_0_PREFIX/include/glib-2.0 -I$LIBGLIB_2_0_PREFIX/$acl_libdirstem/glib-2.0/include"
+            AC_TRY_LINK([#include <glib.h>],
+              [g_string_new ("foo");],
+              [gl_cv_libglib=yes
+               gl_cv_LIBGLIB="$LIBGLIB_2_0"
+               gl_cv_LTLIBGLIB="$LTLIBGLIB_2_0"
+               gl_cv_INCGLIB="-I$LIBGLIB_2_0_PREFIX/include/glib-2.0 -I$LIBGLIB_2_0_PREFIX/$acl_libdirstem/glib-2.0/include"
+              ])
+          fi
+        fi
+        CPPFLAGS="$gl_save_CPPFLAGS"
+      fi
+      LIBS="$gl_save_LIBS"
+    ])
+    AC_MSG_CHECKING([for glib])
+    AC_MSG_RESULT([$gl_cv_libglib])
+    if test $gl_cv_libglib = yes; then
+      LIBGLIB="$gl_cv_LIBGLIB"
+      LTLIBGLIB="$gl_cv_LTLIBGLIB"
+      INCGLIB="$gl_cv_INCGLIB"
+    else
+      gl_cv_libglib_use_included=yes
+    fi
+  fi
+  AC_SUBST([LIBGLIB])
+  AC_SUBST([LTLIBGLIB])
+  AC_SUBST([INCGLIB])
+  AC_MSG_CHECKING([whether to use the included glib])
+  AC_MSG_RESULT([$gl_cv_libglib_use_included])
+
+  if test "$gl_cv_libglib_use_included" = yes; then
+    LIBGLIB_H=
+    LIBGLIB_H="$LIBGLIB_H glib.h"
+    LIBGLIB_H="$LIBGLIB_H glibconfig.h"
+    LIBGLIB_H="$LIBGLIB_H glib/ghash.h"
+    LIBGLIB_H="$LIBGLIB_H glib/glist.h"
+    LIBGLIB_H="$LIBGLIB_H glib/gprimes.h"
+    LIBGLIB_H="$LIBGLIB_H glib/gstrfuncs.h"
+    LIBGLIB_H="$LIBGLIB_H glib/gstring.h"
+    LIBGLIB_H="$LIBGLIB_H glib/gtypes.h"
+    AC_LIBOBJ([glib/ghash])
+    AC_LIBOBJ([glib/glist])
+    AC_LIBOBJ([glib/gmessages])
+    AC_LIBOBJ([glib/gprimes])
+    AC_LIBOBJ([glib/gstrfuncs])
+    AC_LIBOBJ([glib/gstring])
+    AC_REQUIRE([AC_GNU_SOURCE])
+    AC_CHECK_HEADERS([unistd.h])
+    dnl Don't bother checking for pthread.h and other multithread facilities.
+  else
+    LIBGLIB_H=
+  fi
+  AC_SUBST([LIBGLIB_H])
+])
diff --git a/gnulib-local/modules/libglib b/gnulib-local/modules/libglib
new file mode 100644 (file)
index 0000000..f72af33
--- /dev/null
@@ -0,0 +1,103 @@
+Description:
+Substitute for a part of glib version 2.12.4.
+
+Files:
+lib/glib_.h
+lib/glibconfig_.h
+lib/glib/ghash.c
+lib/glib/ghash_.h
+lib/glib/glist.c
+lib/glib/glist_.h
+lib/glib/gmessages.c
+lib/glib/gprimes.c
+lib/glib/gprimes_.h
+lib/glib/gstrfuncs.c
+lib/glib/gstrfuncs_.h
+lib/glib/gstring.c
+lib/glib/gstring_.h
+lib/glib/gtypes_.h
+m4/libglib.m4
+
+Depends-on:
+vasprintf
+xalloc
+xvasprintf
+
+configure.ac:
+gl_LIBGLIB
+
+Makefile.am:
+BUILT_SOURCES += $(LIBGLIB_H)
+
+glib.h: glib_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glib_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+glibconfig.h: glibconfig_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glibconfig_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+glib/ghash.h: glib/ghash_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glib/ghash_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+glib/glist.h: glib/glist_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glib/glist_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+glib/gprimes.h: glib/gprimes_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glib/gprimes_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+glib/gstrfuncs.h: glib/gstrfuncs_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glib/gstrfuncs_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+glib/gstring.h: glib/gstring_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glib/gstring_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+glib/gtypes.h: glib/gtypes_.h
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+         cat $(srcdir)/glib/gtypes_.h; \
+       } > $@-t
+       mv -f $@-t $@
+
+MOSTLYCLEANFILES += \
+  glib.h \
+  glibconfig.h \
+  glib/ghash.h \
+  glib/glist.h \
+  glib/gprimes.h \
+  glib/gstrfuncs.h \
+  glib/gstring.h \
+  glib/gtypes.h
+MOSTLYCLEANFILES += glib/*.h-t
+
+if GL_COND_LIBTOOL
+lib_LDFLAGS += $(LTLIBGLIB)
+endif
+
+Include:
+#include <glib.h>
+
+License:
+LGPL
+
+Maintainer:
+GNOME, Bruno Haible
+