Index: gconvert.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gconvert.c,v
retrieving revision 1.16
diff -r1.16 gconvert.c
26a27
> #include <stdio.h>
48a50,405
> typedef struct _GIconvModule GIconvModule;
> 
> struct _GIconvModule
> {
>   gchar *codeset;
>   gsize alias_num;
>   gchar **aliases;
> };
> 
> static GList *iconv_modules = NULL;
> 
> #ifdef G_OS_WIN32
> static gchar *
> get_glib_dll_name (void)
> {
>   static gchar *glib_dll = NULL;
> 
>   if (!glib_dll)
>     glib_dll = g_strdup_printf ("glib-%d.%d.dll", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION);
> 
>   return glib_dll;
> }
> #endif /* G_OS_WIN32 */
> 
> static gchar*
> g_iconv_get_alias_file (void)
> {
>   gchar *result = g_strdup (g_getenv ("G_ICONV_ALIAS_FILE"));
> 
>   if (!result)
> #ifndef G_OS_WIN32
>     result = g_strdup (SYSCONFDIR G_DIR_SEPARATOR_S "glib-2.0" G_DIR_SEPARATOR_S "giconv.aliases");
> #else
>     result = g_strdup_printf ("%s\\giconv.aliases", g_win32_get_package_installation_directory (GETTEXT_PACKAGE, get_glib_dll_name ()));
> #endif
> 
>   return result;
> }
> 
> gint
> g_iconv_read_line (FILE *stream, GString *str)
> {
>   gboolean quoted = FALSE;
>   gboolean comment = FALSE;
>   int n_read = 0;
>   int lines = 1;
>   
>   flockfile (stream);
> 
>   g_string_truncate (str, 0);
>   
>   while (1)
>     {
>       int c;
>       
>       c = getc_unlocked (stream);
> 
>       if (c == EOF)
> 	{
> 	  if (quoted)
> 	    g_string_append_c (str, '\\');
> 	  
> 	  goto done;
> 	}
>       else
> 	n_read++;
> 
>       if (quoted)
> 	{
> 	  quoted = FALSE;
> 	  
> 	  switch (c)
> 	    {
> 	    case '#':
> 	      g_string_append_c (str, '#');
> 	      break;
> 	    case '\r':
> 	    case '\n':
> 	      {
> 		int next_c = getc_unlocked (stream);
> 
> 		if (!(next_c == EOF ||
> 		      (c == '\r' && next_c == '\n') ||
> 		      (c == '\n' && next_c == '\r')))
> 		  ungetc (next_c, stream);
> 
> 		lines++;
> 		
> 		break;
> 	      }
> 	    default:
> 	      g_string_append_c (str, '\\');	      
> 	      g_string_append_c (str, c);
> 	    }
> 	}
>       else
> 	{
> 	  switch (c)
> 	    {
> 	    case '#':
> 	      comment = TRUE;
> 	      break;
> 	    case '\\':
> 	      if (!comment)
> 		quoted = TRUE;
> 	      break;
> 	    case '\n':
> 	      {
> 		int next_c = getc_unlocked (stream);
> 
> 		if (!(c == EOF ||
> 		      (c == '\r' && next_c == '\n') ||
> 		      (c == '\n' && next_c == '\r')))
> 		  ungetc (next_c, stream);
> 
> 		goto done;
> 	      }
> 	    default:
> 	      if (!comment)
> 		g_string_append_c (str, c);
> 	    }
> 	}
>     }
> 
>  done:
> 
>   funlockfile (stream);
> 
>   return (n_read > 0) ? lines : 0;
> }
> 
> /**
>  * scan_string:
>  * @pos: in/out string position
>  * @out: a #GString into which to write the result
>  * 
>  * Scan a string into a #GString buffer. The string may either
>  * be a sequence of non-white-space characters, or a quoted
>  * string with '"'. Instead a quoted string, '\"' represents
>  * a literal quote. Leading white space outside of quotes is skipped.
>  * 
>  * Return value: %FALSE if a parse error occured.
>  **/
> gboolean
> scan_string (const char **pos, GString *out)
> {
>   const char *p = *pos;
>   
>   while (isspace (*p))
>     p++;
> 
>   if (!*p)
>     return FALSE;
>   else if (*p == '"')
>     {
>       gboolean quoted = FALSE;
>       g_string_truncate (out, 0);
> 
>       p++;
> 
>       while (TRUE)
> 	{
> 	  if (quoted)
> 	    {
> 	      int c = *p;
> 	      
> 	      switch (c)
> 		{
> 		case '\0':
> 		  return FALSE;
> 		case 'n':
> 		  c = '\n';
> 		  break;
> 		case 't':
> 		  c = '\t';
> 		  break;
> 		}
> 	      
> 	      quoted = FALSE;
> 	      g_string_append_c (out, c);
> 	    }
> 	  else
> 	    {
> 	      switch (*p)
> 		{
> 		case '\0':
> 		  return FALSE;
> 		case '\\':
> 		  quoted = TRUE;
> 		  break;
> 		case '"':
> 		  p++;
> 		  goto done;
> 		default:
> 		  g_string_append_c (out, *p);
> 		  break;
> 		}
> 	    }
> 	  p++;
> 	}
>     done:
>       ;
>     }
>   else
>     {
>       g_string_truncate (out, 0);
> 
>       while (*p && !isspace (*p))
> 	{
> 	  g_string_append_c (out, *p);
> 	  p++;
> 	}
>     }
> 
>   *pos = p;
> 
>   return TRUE;
> }
> 
> /**
>  * skip_space:
>  * @pos: in/out string position
>  * 
>  * Skips 0 or more characters of white space.
>  * 
>  * Return value: %FALSE if skipping the white space leaves
>  * the position at a '\0' character.
>  **/
> static gboolean
> skip_space (const char **pos)
> {
>   const char *p = *pos;
>   
>   while (isspace (*p))
>     p++;
> 
>   *pos = p;
> 
>   return !(*p == '\0');
> }
> 
> /**
>  * trim_string:
>  * @str: a string
>  * 
>  * Trim leading and trailing whitespace from a string.
>  * 
>  * Return value: A newly allocated string that must be freed with g_free()
>  **/
> static char *
> trim_string (const char *str)
> {
>   int len;
> 
>   g_return_val_if_fail (str != NULL, NULL);
>   
>   while (*str && isspace (*str))
>     str++;
> 
>   len = strlen (str);
>   while (len > 0 && isspace (str[len-1]))
>     len--;
> 
>   return g_strndup (str, len);
> }
> 
> static void
> g_iconv_read_alias_file(void)
> {
>   FILE *file;
>   gchar *filename;
>   GIconvModule *data;
>   GString *line_buffer;
>   GString *tmp_buffer;
>   const char *pos;
>   gchar **modules;
>   int i;
> 
>   filename = g_iconv_get_alias_file ();
>   if (!filename || !(file = fopen (filename, "r")))
>     {
>       g_free (filename);
>       return;
>     }
> 
>   g_free (filename);
> 
>   line_buffer = g_string_new (NULL);
>   tmp_buffer = g_string_new (NULL);
> 
>   while (g_iconv_read_line (file, line_buffer))
>     {
>       pos = line_buffer->str;
> 
>       if (!skip_space (&pos))
> 	continue;
> 
>       if (!scan_string (&pos, tmp_buffer))
> 	goto error;
> 
>       data = g_malloc (sizeof(GIconvModule));
>       data->codeset = g_strdup (tmp_buffer->str);
> 
>       if (!scan_string (&pos, tmp_buffer))
> 	{
> 	  g_free ((char*)data);
> 	  goto error;
> 	}
> 
>       /* Remove excess whitespace and check for complete fields */
>       modules = g_strsplit (tmp_buffer->str, ",", -1);
>       for (i = 0; modules[i]; i++)
> 	{
> 	  char *trimmed = trim_string (modules[i]);
> 	  g_free (modules[i]);
> 	  modules[i] = trimmed;
> 	}
>       data->alias_num = i;
>       data->aliases = modules;
> 
>       iconv_modules = g_list_append (iconv_modules, data);
>     }
> 
>  error:
> 
>   fclose (file);
> 
>   return;
> }
> 
> static gchar**
> g_iconv_alias(const gchar *codeset, gint *list_num)
> {
>   GList* it;
>   GIconvModule *data;
> 
>   if (iconv_modules == (GList*)NULL)
>     g_iconv_read_alias_file ();
> 
>   g_return_if_fail (iconv_modules != NULL);
> 
>   for (it = iconv_modules; it; it = g_list_next(it))
>     {
>       data = (GIconvModule*)it->data;
>       if (data->codeset && !strcmp (data->codeset, codeset))
> 	{
> 	  *list_num = data->alias_num;
> 	  return (gchar**)data->aliases;
> 	}
>     }
> 
>   /* not found */
>   *list_num = 0;
>   return 0;
> }
> 
75c432,450
<   
---
> 
>   if (cd == (iconv_t)-1)
>     {
>       /* try different names */
>       gchar **to_list, **from_list, **p, **q;
>       gint from_list_num, to_list_num;
> 
>       from_list = g_iconv_alias(from_codeset, &from_list_num);
>       to_list = g_iconv_alias(to_codeset, &to_list_num);
> 
>       for (p = from_list; p < &from_list[from_list_num]; p++)
> 	for (q = to_list; q < &to_list[to_list_num]; q++)
> 	  {
> 	    cd = iconv_open (*q, *p);
> 	    if (cd != (iconv_t)-1)
> 	      break;
> 	  }
>     }
> 
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/glib/glib/Makefile.am,v
retrieving revision 1.89
diff -r1.89 Makefile.am
3a4
> 	-DSYSCONFDIR=\"$(sysconfdir)\" 		\
