On Wed, 2010-05-12 at 19:07 -0400, Greg Ames wrote:
> This patch also produces readable error messages on z/OS by defining two new
> svn_cmdline functions which take native string arguments, then calling
> svn_cmdline_fprintf_asis() from print_error(), only in the path where I can
> see that native strings are being used.

Hi Greg.

I get why you need this patch (or some equivalent) for z/OS, but I still
don't quite understand whether or why it's also correct for a 'normal'
build of Subversion.

In an attempt both to understand and to minimize the patch: would you
get the same result by converting 'err->message' from native encoding to
UTF-8 and then printing it in the way that it currently is printed?
Like this:

[[[
Index: subversion/libsvn_subr/error.c
===================================================================
--- subversion/libsvn_subr/error.c      (revision 944163)
+++ subversion/libsvn_subr/error.c      (working copy)
@@ -413,15 +413,18 @@ print_error(svn_error_t *err, FILE *stre
       /* Skip it.  We already printed the file-line coordinates. */
     }
   /* Only print the same APR error string once. */
-  else if (err->message)
-    {
-      svn_error_clear(svn_cmdline_fprintf(stream, err->pool, "%s%s\n",
-                                          prefix, err->message));
-    }
   else
     {
+      if (err->message)
+        {
+          /* Set ERR_STRING to a UTF-8 version of ERR->message. */
+          temp_err = svn_utf_cstring_to_utf8(&err_string, err->message,
+                                             err->pool);
+          if (temp_err)
+            { /* ... */ }
+        }
       /* Is this a Subversion-specific error code? */
-      if ((err->apr_err > APR_OS_START_USEERR)
+      else if ((err->apr_err > APR_OS_START_USEERR)
           && (err->apr_err <= APR_OS_START_CANONERR))
         err_string = svn_strerror(err->apr_err, errbuf, sizeof(errbuf));
       /* Otherwise, this must be an APR error code. */
]]]

It appears that Subversion currently assumes the message is already in
UTF-8.  Is that not strictly true?  Note that the messages nearly always
come from "gettext" (via the _() macro).

The bit that gets me is that if the current conversion (from UTF-8 to
native encoding) is correct, then replacing it with no conversion (or
native -> UTF-8 then UTF-8 to native) must be wrong.

I don't know; I'm asking if you can say something to shed light on it.

Also note that sometimes the message comes not from the client software
but from a network response sent by the server, so there is probably
another place where the encoding will need to be changed.

- Julian


> Greg
> 
> Index: subversion/libsvn_subr/cmdline.c
> ===================================================================
> --- subversion/libsvn_subr/cmdline.c    (revision 943729)
> +++ subversion/libsvn_subr/cmdline.c    (working copy)
> @@ -316,6 +316,19 @@
>  }
> 
>  svn_error_t *
> +svn_cmdline_fprintf_asis(FILE *stream, apr_pool_t *pool, const char *fmt,
> ...)
> +{
> +  const char *message;
> +  va_list ap;
> +
> +  va_start(ap, fmt);
> +  message = apr_pvsprintf(pool, fmt, ap);
> +  va_end(ap);
> +
> +  return svn_cmdline_fputs_asis(message, stream, pool);
> +}
> +
> +svn_error_t *
>  svn_cmdline_fputs(const char *string, FILE* stream, apr_pool_t *pool)
>  {
>    svn_error_t *err;
> @@ -348,6 +361,28 @@
>  }
> 
>  svn_error_t *
> +svn_cmdline_fputs_asis(const char *string, FILE* stream, apr_pool_t *pool)
> +{
> +
> +  /* On POSIX systems, errno will be set on an error in fputs, but this
> might
> +     not be the case on other platforms.  We reset errno and only
> +     use it if it was set by the below fputs call.  Else, we just return
> +     a generic error. */
> +  errno = 0;
> +
> +  if (fputs(string, stream) == EOF)
> +    {
> +      if (errno)
> +        return svn_error_wrap_apr(errno, _("Write error"));
> +      else
> +        return svn_error_create
> +          (SVN_ERR_IO_WRITE_ERROR, NULL, NULL);
> +    }
> +
> +  return SVN_NO_ERROR;
> +}
> +
> +svn_error_t *
>  svn_cmdline_fflush(FILE *stream)
>  {
>    /* See comment in svn_cmdline_fputs about use of errno and stdio. */
> Index: subversion/libsvn_subr/error.c
> ===================================================================
> --- subversion/libsvn_subr/error.c    (revision 943729)
> +++ subversion/libsvn_subr/error.c    (working copy)
> @@ -415,8 +415,8 @@
>    /* Only print the same APR error string once. */
>    else if (err->message)
>      {
> -      svn_error_clear(svn_cmdline_fprintf(stream, err->pool, "%s%s\n",
> -                                          prefix, err->message));
> +      svn_error_clear(svn_cmdline_fprintf_asis(stream, err->pool, "%s%s\n",
> +                                               prefix, err->message));
>      }
>    else
>      {
> Index: subversion/include/svn_cmdline.h
> ===================================================================
> --- subversion/include/svn_cmdline.h    (revision 943729)
> +++ subversion/include/svn_cmdline.h    (working copy)
> @@ -128,6 +128,28 @@
>                    FILE *stream,
>                    apr_pool_t *pool);
> 
> +/** Write to the stdio @a stream, using a printf-like format string @a fmt,
> + * passed through apr_pvsprintf().  All string arguments are in the native
> + * encoding; no codepage conversion is done.  Use @a pool for
> + * temporary allocation.
> + *
> + * @since New in ??
> + */
> +svn_error_t *svn_cmdline_fprintf_asis(FILE *stream,
> +                                      apr_pool_t *pool,
> +                                      const char *fmt,
> +                                      ...)
> +       __attribute__((format(printf, 3, 4)));
> +
> +/** Output the @a string to the stdio @a stream without changing the
> encoding.
> + * Use @a pool for temporary allocation.
> + *
> + * @since New in ??
> + */
> +svn_error_t *svn_cmdline_fputs_asis(const char *string,
> +                                    FILE *stream,
> +                                    apr_pool_t *pool);
> +
>  /** Flush output buffers of the stdio @a stream, returning an error if that
>   * fails.  This is just a wrapper for the standard fflush() function for
>   * consistent error handling.


Reply via email to