Subject: [PROPOSED PATCH] Use curved quoting in C-generated errors

From: Paul Eggert <[email-masked]>
Date: Mon, 1 Jun 2015 00:39:21 -0700

Quote with curved single quotes, ‘like this’, in diagnostics
generated from C code.  This mostly uses C11-style UTF-8 strings,
e.g., u8"quote ‘like this’", with a backward compatibility macro
u8 for pre-C11 compilers.
* src/buffer.c (Fmake_indirect_buffer, Frename_buffer)
(Fset_buffer_multibyte):
* src/callint.c (Fcall_interactively):
* src/category.c (Fmake_category_set, Fdefine_category):
* src/chartab.c (Fchar_table_range, Fset_char_table_range):
* src/coding.c (Ffind_operation_coding_system)
(Fdefine_coding_system_internal):
* src/dispnew.c (add_window_display_history):
* src/editfns.c (Fsubst_char_in_region):
* src/eval.c (FletX, Flet, eval_sub, Ffuncall):
* src/fileio.c (Ffile_name_nondirectory)
(Ffile_name_as_directory, Fdirectory_file_name)
(Fexpand_file_name, Fsubstitute_in_file_name):
* src/fns.c (Frequire):
* src/font.c (Ffont_spec):
* src/fontset.c (check_fontset_name):
* src/frame.c (x_set_font):
* src/image.c (xbm_read_bitmap_data, xbm_load_image, xbm_load)
(xpm_load, xpm_load_image, xpm_load, pbm_load, png_load_body)
(jpeg_load_body, tiff_load, gif_load, imagemagick_load_image)
(imagemagick_load, svg_load, svg_load_image, gs_load)
(x_kill_gs_process):
* src/keymap.c (store_in_keymap, Fdescribe_buffer_bindings):
* src/lread.c (load_warn_old_style_backquotes, Fload):
* src/nsfns.m (Fns_list_colors):
* src/regex.c (PUSH_FAILURE_POINT, POP_FAILURE_POINT)
(re_match_2_internal):
* src/search.c (Freplace_match):
* src/syntax.c (Finternal_describe_syntax_value):
* src/sysdep.c (serial_configure):
* src/w32.c (serial_configure):
* src/window.c (Fset_frame_selected_window, Fset_window_buffer)
(Frecenter):
* src/xfaces.c (load_pixmap):
Reword to avoid quoting with grave accent and apostrophe
in diagnostics.
* src/conf_post.h (u8): New macro, for compatibility with pre-C11.
* src/doc.c (Fsubstitute_command_keys):
Use curved quotes when generating keymap info.
* src/lisp.h (uLSQM, uRSQM): New macros.
---
 src/buffer.c    |   8 ++--
 src/callint.c   |   5 ++-
 src/category.c  |   4 +-
 src/chartab.c   |   4 +-
 src/coding.c    |   6 +--
 src/conf_post.h |   4 ++
 src/dispnew.c   |   2 +-
 src/doc.c       |   4 +-
 src/editfns.c   |   2 +-
 src/eval.c      |   8 ++--
 src/fileio.c    |  14 +++---
 src/fns.c       |   4 +-
 src/font.c      |   2 +-
 src/fontset.c   |   2 +-
 src/frame.c     |   4 +-
 src/image.c     | 130 ++++++++++++++++++++++++++++----------------------------
 src/keymap.c    |   6 +--
 src/lisp.h      |   7 +++
 src/lread.c     |   8 ++--
 src/nsfns.m     |   2 +-
 src/regex.c     |  14 +++---
 src/search.c    |   6 +--
 src/syntax.c    |   2 +-
 src/sysdep.c    |   4 +-
 src/w32.c       |   4 +-
 src/window.c    |   6 +--
 src/xfaces.c    |   2 +-
 27 files changed, 138 insertions(+), 126 deletions(-)

diff --git a/src/buffer.c b/src/buffer.c
index 0b98431..f95a726 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -745,12 +745,12 @@ CLONE nil means the indirect buffer's state is reset to default values.  */)
   CHECK_STRING (name);
   buf = Fget_buffer (name);
   if (!NILP (buf))
-    error ("Buffer name `%s' is in use", SDATA (name));
+    error (u8"Buffer name ‘%s’ is in use", SDATA (name));
 
   tem = base_buffer;
   base_buffer = Fget_buffer (base_buffer);
   if (NILP (base_buffer))
-    error ("No such buffer: `%s'", SDATA (tem));
+    error (u8"No such buffer: ‘%s’", SDATA (tem));
   if (!BUFFER_LIVE_P (XBUFFER (base_buffer)))
     error ("Base buffer has been killed");
 
@@ -1429,7 +1429,7 @@ This does not change the name of the visited file (if any).  */)
       if (!NILP (unique))
 	newname = Fgenerate_new_buffer_name (newname, BVAR (current_buffer, name));
       else
-	error ("Buffer name `%s' is in use", SDATA (newname));
+	error (u8"Buffer name ‘%s’ is in use", SDATA (newname));
     }
 
   bset_name (current_buffer, newname);
@@ -2412,7 +2412,7 @@ current buffer is cleared.  */)
   struct gcpro gcpro1;
 
   if (current_buffer->base_buffer)
-    error ("Cannot do `set-buffer-multibyte' on an indirect buffer");
+    error (u8"Cannot do ‘set-buffer-multibyte’ on an indirect buffer");
 
   /* Do nothing if nothing actually changes.  */
   if (NILP (flag) == NILP (BVAR (current_buffer, enable_multibyte_characters)))
diff --git a/src/callint.c b/src/callint.c
index 2ff2f80..d31aade 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -413,7 +413,7 @@ invoke it.  If KEYS is omitted or nil, the return value of
   while (1)
     {
       if (*string == '+')
-	error ("`+' is not used in `interactive' for ordinary commands");
+	error (u8"‘+’ is not used in ‘interactive’ for ordinary commands");
       else if (*string == '*')
 	{
 	  string++;
@@ -785,7 +785,8 @@ invoke it.  If KEYS is omitted or nil, the return value of
 	     if anyone tries to define one here.  */
 	case '+':
 	default:
-	  error ("Invalid control letter `%c' (#o%03o, #x%04x) in interactive calling string",
+	  error ((u8"Invalid control letter ‘%c’ (#o%03o, #x%04x)"
+		  u8" in interactive calling string"),
 		 STRING_CHAR ((unsigned char *) tem),
 		 (unsigned) STRING_CHAR ((unsigned char *) tem),
 		 (unsigned) STRING_CHAR ((unsigned char *) tem));
diff --git a/src/category.c b/src/category.c
index ab90f5f..5dadea4 100644
--- a/src/category.c
+++ b/src/category.c
@@ -100,7 +100,7 @@ those categories.  */)
   val = MAKE_CATEGORY_SET;
 
   if (STRING_MULTIBYTE (categories))
-    error ("Multibyte string in `make-category-set'");
+    error (u8"Multibyte string in ‘make-category-set’");
 
   len = SCHARS (categories);
   while (--len >= 0)
@@ -134,7 +134,7 @@ the current buffer's category table.  */)
   table = check_category_table (table);
 
   if (!NILP (CATEGORY_DOCSTRING (table, XFASTINT (category))))
-    error ("Category `%c' is already defined", (int) XFASTINT (category));
+    error (u8"Category ‘%c’ is already defined", (int) XFASTINT (category));
   if (!NILP (Vpurify_flag))
     docstring = Fpurecopy (docstring);
   SET_CATEGORY_DOCSTRING (table, XFASTINT (category), docstring);
diff --git a/src/chartab.c b/src/chartab.c
index acaabce..b0d3d9a 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -622,7 +622,7 @@ a cons of character codes (for characters in the range), or a character code.  *
       /* Not yet implemented. */
     }
   else
-    error ("Invalid RANGE argument to `char-table-range'");
+    error (u8"Invalid RANGE argument to ‘char-table-range’");
   return val;
 }
 
@@ -655,7 +655,7 @@ or a character code.  Return VALUE.  */)
 			    XINT (XCAR (range)), XINT (XCDR (range)), value);
     }
   else
-    error ("Invalid RANGE argument to `set-char-table-range'");
+    error (u8"Invalid RANGE argument to ‘set-char-table-range’");
 
   return value;
 }
diff --git a/src/coding.c b/src/coding.c
index 9342c38..8f536d4 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -9853,14 +9853,14 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS...)  */)
       || (target_idx = Fget (operation, Qtarget_idx), !NATNUMP (target_idx)))
     error ("Invalid first argument");
   if (nargs <= 1 + XFASTINT (target_idx))
-    error ("Too few arguments for operation `%s'",
+    error (u8"Too few arguments for operation ‘%s’",
 	   SDATA (SYMBOL_NAME (operation)));
   target = args[XFASTINT (target_idx) + 1];
   if (!(STRINGP (target)
 	|| (EQ (operation, Qinsert_file_contents) && CONSP (target)
 	    && STRINGP (XCAR (target)) && BUFFERP (XCDR (target)))
 	|| (EQ (operation, Qopen_network_stream) && INTEGERP (target))))
-    error ("Invalid argument %"pI"d of operation `%s'",
+    error ("Invalid argument %"pI"d of operation "uLSQM"%s"uRSQM,
 	   XFASTINT (target_idx) + 1, SDATA (SYMBOL_NAME (operation)));
   if (CONSP (target))
     target = XCAR (target);
@@ -10094,7 +10094,7 @@ usage: (define-coding-system-internal ...)  */)
 	      : EQ (coding_type, Qemacs_mule)
 	      ? CHARSET_EMACS_MULE_ID (charset) < 0
 	      : 0)
-	    error ("Can't handle charset `%s'",
+	    error (u8"Can't handle charset ‘%s’",
 		   SDATA (SYMBOL_NAME (CHARSET_NAME (charset))));
 
 	  XSETCAR (tail, make_number (charset->id));
diff --git a/src/conf_post.h b/src/conf_post.h
index 1a080fa..e9c7863 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -43,6 +43,10 @@ typedef unsigned int bool_bf;
 typedef bool bool_bf;
 #endif
 
+/* On older compilers that do not support C11-style UTF-8 string literals,
+   treat the u8 encoding prefix as a no-op.  */
+#define u8
+
 #ifndef WINDOWSNT
 /* On AIX 3 this must be included before any other include file.  */
 #include <alloca.h>
diff --git a/src/dispnew.c b/src/dispnew.c
index 1fc3cfe..ede7adf 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -177,7 +177,7 @@ add_window_display_history (struct window *w, const char *msg, bool paused_p)
   ++history_idx;
 
   snprintf (buf, sizeof redisplay_history[0].trace,
-	    "%"pMu": window %p (`%s')%s\n%s",
+	    "%"pMu": window %p ("uLSQM"%s"uRSQM")%s\n%s",
 	    history_tick++,
 	    ptr,
 	    ((BUFFERP (w->contents)
diff --git a/src/doc.c b/src/doc.c
index f1ba643..aa87282 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -891,11 +891,11 @@ Otherwise, return a new string.  */)
 	  if (NILP (tem))
 	    {
 	      name = Fsymbol_name (name);
-	      insert_string ("\nUses keymap `");
+	      insert_string (u8"\nUses keymap ‘");
 	      insert_from_string (name, 0, 0,
 				  SCHARS (name),
 				  SBYTES (name), 1);
-	      insert_string ("', which is not currently defined.\n");
+	      insert_string (u8"’, which is not currently defined.\n");
 	      if (start[-1] == '<') keymap = Qnil;
 	    }
 	  else if (start[-1] == '<')
diff --git a/src/editfns.c b/src/editfns.c
index c387dc7..8dc2a47 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2994,7 +2994,7 @@ Both characters must have the same length of multi-byte form.  */)
     {
       len = CHAR_STRING (fromc, fromstr);
       if (CHAR_STRING (toc, tostr) != len)
-	error ("Characters in `subst-char-in-region' have different byte-lengths");
+	error (u8"Characters in ‘subst-char-in-region’ have different byte-lengths");
       if (!ASCII_CHAR_P (*tostr))
 	{
 	  /* If *TOSTR is in the range 0x80..0x9F and TOCHAR is not a
diff --git a/src/eval.c b/src/eval.c
index 4655095..92b5653 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -864,7 +864,7 @@ usage: (let* VARLIST BODY...)  */)
 	  val = Qnil;
 	}
       else if (! NILP (Fcdr (Fcdr (elt))))
-	signal_error ("`let' bindings can have only one value-form", elt);
+	signal_error (u8"‘let’ bindings can have only one value-form", elt);
       else
 	{
 	  var = Fcar (elt);
@@ -931,7 +931,7 @@ usage: (let VARLIST BODY...)  */)
       if (SYMBOLP (elt))
 	temps [argnum++] = Qnil;
       else if (! NILP (Fcdr (Fcdr (elt))))
-	signal_error ("`let' bindings can have only one value-form", elt);
+	signal_error (u8"‘let’ bindings can have only one value-form", elt);
       else
 	temps [argnum++] = eval_sub (Fcar (Fcdr (elt)));
       gcpro2.nvars = argnum;
@@ -2087,7 +2087,7 @@ eval_sub (Lisp_Object form)
       if (max_lisp_eval_depth < 100)
 	max_lisp_eval_depth = 100;
       if (lisp_eval_depth > max_lisp_eval_depth)
-	error ("Lisp nesting exceeds `max-lisp-eval-depth'");
+	error (u8"Lisp nesting exceeds ‘max-lisp-eval-depth’");
     }
 
   original_fun = XCAR (form);
@@ -2658,7 +2658,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS)  */)
       if (max_lisp_eval_depth < 100)
 	max_lisp_eval_depth = 100;
       if (lisp_eval_depth > max_lisp_eval_depth)
-	error ("Lisp nesting exceeds `max-lisp-eval-depth'");
+	error (u8"Lisp nesting exceeds ‘max-lisp-eval-depth’");
     }
 
   /* This also GCPROs them.  */
diff --git a/src/fileio.c b/src/fileio.c
index aad0270..13ee4c0 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -410,7 +410,7 @@ or the entire name if it contains no slash.  */)
 					filename);
       if (STRINGP (handled_name))
 	return handled_name;
-      error ("Invalid handler in `file-name-handler-alist'");
+      error (u8"Invalid handler in ‘file-name-handler-alist’");
     }
 
   beg = SSDATA (filename);
@@ -514,7 +514,7 @@ For a Unix-syntax file name, just appends a slash.  */)
 					file);
       if (STRINGP (handled_name))
 	return handled_name;
-      error ("Invalid handler in `file-name-handler-alist'");
+      error (u8"Invalid handler in ‘file-name-handler-alist’");
     }
 
 #ifdef WINDOWSNT
@@ -580,7 +580,7 @@ In Unix-syntax, this function just removes the final slash.  */)
 					directory);
       if (STRINGP (handled_name))
 	return handled_name;
-      error ("Invalid handler in `file-name-handler-alist'");
+      error (u8"Invalid handler in ‘file-name-handler-alist’");
     }
 
 #ifdef WINDOWSNT
@@ -798,7 +798,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
 			    name, default_directory);
       if (STRINGP (handled_name))
 	return handled_name;
-      error ("Invalid handler in `file-name-handler-alist'");
+      error (u8"Invalid handler in ‘file-name-handler-alist’");
     }

@@ -831,7 +831,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
 				name, default_directory);
 	  if (STRINGP (handled_name))
 	    return handled_name;
-	  error ("Invalid handler in `file-name-handler-alist'");
+	  error (u8"Invalid handler in ‘file-name-handler-alist’");
 	}
     }
 
@@ -1424,7 +1424,7 @@ filesystem tree, not (expand-file-name ".."  dirname).  */)
       handled_name = call3 (handler, Qexpand_file_name,
 			    result, default_directory);
       if (! STRINGP (handled_name))
-	error ("Invalid handler in `file-name-handler-alist'");
+	error (u8"Invalid handler in ‘file-name-handler-alist’");
       result = handled_name;
     }
 
@@ -1680,7 +1680,7 @@ those `/' is discarded.  */)
 					filename);
       if (STRINGP (handled_name))
 	return handled_name;
-      error ("Invalid handler in `file-name-handler-alist'");
+      error (u8"Invalid handler in ‘file-name-handler-alist’");
     }
 
   /* Always work on a copy of the string, in case GC happens during
diff --git a/src/fns.c b/src/fns.c
index 235a4f6..642df5c 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2878,7 +2878,7 @@ The normal messages at start and end of loading FILENAME are suppressed.  */)
 	  tem = XCDR (tem);
 	}
       if (nesting > 3)
-	error ("Recursive `require' for feature `%s'",
+	error (u8"Recursive ‘require’ for feature ‘%s’",
 	       SDATA (SYMBOL_NAME (feature)));
 
       /* Update the list for any nested `require's that occur.  */
@@ -2901,7 +2901,7 @@ The normal messages at start and end of loading FILENAME are suppressed.  */)
 
       tem = Fmemq (feature, Vfeatures);
       if (NILP (tem))
-	error ("Required feature `%s' was not provided",
+	error (u8"Required feature ‘%s’ was not provided",
 	       SDATA (SYMBOL_NAME (feature)));
 
       /* Once loading finishes, don't undo it.  */
diff --git a/src/font.c b/src/font.c
index 1405d43..4fb5d52 100644
--- a/src/font.c
+++ b/src/font.c
@@ -3885,7 +3885,7 @@ usage: (font-spec ARGS...)  */)
 
       CHECK_SYMBOL (key);
       if (i + 1 >= nargs)
-	error ("No value for key `%s'", SDATA (SYMBOL_NAME (key)));
+	error (u8"No value for key ‘%s’", SDATA (SYMBOL_NAME (key)));
       val = args[i + 1];
 
       if (EQ (key, QCname))
diff --git a/src/fontset.c b/src/fontset.c
index e957c38..848bc7a 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1303,7 +1303,7 @@ check_fontset_name (Lisp_Object name, Lisp_Object *frame)
 	/* For backward compatibility, try again NAME as pattern.  */
 	id = fs_query_fontset (name, 0);
       if (id < 0)
-	error ("Fontset `%s' does not exist", SDATA (name));
+	error (u8"Fontset ‘%s’ does not exist", SDATA (name));
     }
   return FONTSET_FROM_ID (id);
 }
diff --git a/src/frame.c b/src/frame.c
index e3ad82f..368775e 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3562,14 +3562,14 @@ x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 	{
 	  font_object = font_open_by_name (f, arg);
 	  if (NILP (font_object))
-	    error ("Font `%s' is not defined", SSDATA (arg));
+	    error (u8"Font ‘%s’ is not defined", SSDATA (arg));
 	  arg = AREF (font_object, FONT_NAME_INDEX);
 	}
       else if (fontset > 0)
 	{
 	  font_object = font_open_by_name (f, fontset_ascii (fontset));
 	  if (NILP (font_object))
-	    error ("Font `%s' is not defined", SDATA (arg));
+	    error (u8"Font ‘%s’ is not defined", SDATA (arg));
 	  arg = AREF (font_object, FONT_NAME_INDEX);
 	}
       else
diff --git a/src/image.c b/src/image.c
index dfa8941..a33448c 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2791,7 +2791,7 @@ xbm_read_bitmap_data (struct frame *f, unsigned char *contents, unsigned char *e
   if (!check_image_size (f, *width, *height))
     {
       if (!inhibit_image_error)
-	image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+	image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       goto failure;
     }
   else if (data == NULL)
@@ -2936,13 +2936,13 @@ xbm_load_image (struct frame *f, struct image *img, unsigned char *contents,
       if (img->pixmap == NO_PIXMAP)
 	{
 	  x_clear_image (f, img);
-	  image_error ("Unable to create X pixmap for `%s'", img->spec, Qnil);
+	  image_error (u8"Unable to create X pixmap for ‘%s’", img->spec, Qnil);
 	}
       else
 	success_p = 1;
     }
   else
-    image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+    image_error (u8"Error loading XBM image ‘%s’", img->spec, Qnil);
 
   return success_p;
 }
@@ -2983,14 +2983,14 @@ xbm_load (struct frame *f, struct image *img)
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", file_name, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", file_name, Qnil);
 	  return 0;
 	}
 
       contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
 	{
-	  image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+	  image_error (u8"Error loading XBM image ‘%s’", img->spec, Qnil);
 	  return 0;
 	}
 
@@ -3025,7 +3025,7 @@ xbm_load (struct frame *f, struct image *img)
 	  eassert (img->width > 0 && img->height > 0);
 	  if (!check_image_size (f, img->width, img->height))
 	    {
-	      image_error ("Invalid image size (see `max-image-size')",
+	      image_error (u8"Invalid image size (see ‘max-image-size’)",
 			   Qnil, Qnil);
 	      return 0;
 	    }
@@ -3103,7 +3103,7 @@ xbm_load (struct frame *f, struct image *img)
 	    success_p = 1;
 	  else
 	    {
-	      image_error ("Unable to create pixmap for XBM image `%s'",
+	      image_error (u8"Unable to create pixmap for XBM image ‘%s’",
 			   img->spec, Qnil);
 	      x_clear_image (f, img);
 	    }
@@ -3626,7 +3626,7 @@ xpm_load (struct frame *f, struct image *img)
       Lisp_Object file = x_find_image_file (specified_file);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", specified_file, Qnil);
 #ifdef ALLOC_XPM_COLORS
 	  xpm_free_color_cache ();
 #endif
@@ -3657,7 +3657,7 @@ xpm_load (struct frame *f, struct image *img)
       Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (buffer))
 	{
-	  image_error ("Invalid image data `%s'", buffer, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", buffer, Qnil);
 #ifdef ALLOC_XPM_COLORS
 	  xpm_free_color_cache ();
 #endif
@@ -4101,7 +4101,7 @@ xpm_load_image (struct frame *f,
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       goto failure;
     }
 
@@ -4291,14 +4291,14 @@ xpm_load (struct frame *f,
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", file_name, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", file_name, Qnil);
 	  return 0;
 	}
 
       contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
 	{
-	  image_error ("Error loading XPM image `%s'", img->spec, Qnil);
+	  image_error (u8"Error loading XPM image ‘%s’", img->spec, Qnil);
 	  return 0;
 	}
 
@@ -4312,7 +4312,7 @@ xpm_load (struct frame *f,
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
 	{
-	  image_error ("Invalid image data `%s'", data, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", data, Qnil);
 	  return 0;
 	}
       success_p = xpm_load_image (f, img, SDATA (data),
@@ -5266,14 +5266,14 @@ pbm_load (struct frame *f, struct image *img)
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", specified_file, Qnil);
 	  return 0;
 	}
 
       contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
 	{
-	  image_error ("Error reading `%s'", file, Qnil);
+	  image_error (u8"Error reading ‘%s’", file, Qnil);
 	  return 0;
 	}
 
@@ -5286,7 +5286,7 @@ pbm_load (struct frame *f, struct image *img)
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
 	{
-	  image_error ("Invalid image data `%s'", data, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", data, Qnil);
 	  return 0;
 	}
       p = SDATA (data);
@@ -5296,7 +5296,7 @@ pbm_load (struct frame *f, struct image *img)
   /* Check magic number.  */
   if (end - p < 2 || *p++ != 'P')
     {
-      image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+      image_error (u8"Not a PBM image: ‘%s’", img->spec, Qnil);
     error:
       xfree (contents);
       img->pixmap = NO_PIXMAP;
@@ -5330,7 +5330,7 @@ pbm_load (struct frame *f, struct image *img)
       break;
 
     default:
-      image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+      image_error (u8"Not a PBM image: ‘%s’", img->spec, Qnil);
       goto error;
     }
 
@@ -5356,7 +5356,7 @@ pbm_load (struct frame *f, struct image *img)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       goto error;
     }
 
@@ -5429,7 +5429,7 @@ pbm_load (struct frame *f, struct image *img)
 			x_destroy_x_image (ximg);
 #endif
 			x_clear_image (f, img);
-			image_error ("Invalid image size in image `%s'",
+			image_error (u8"Invalid image size in image ‘%s’",
 				     img->spec, Qnil);
 			goto error;
 		      }
@@ -5464,7 +5464,7 @@ pbm_load (struct frame *f, struct image *img)
 	  x_destroy_x_image (ximg);
 #endif
 	  x_clear_image (f, img);
-	  image_error ("Invalid image size in image `%s'",
+	  image_error (u8"Invalid image size in image ‘%s’",
 		       img->spec, Qnil);
 	  goto error;
 	}
@@ -5508,7 +5508,7 @@ pbm_load (struct frame *f, struct image *img)
 #else
 		x_destroy_x_image (ximg);
 #endif
-		image_error ("Invalid pixel value in image `%s'",
+		image_error (u8"Invalid pixel value in image ‘%s’",
 			     img->spec, Qnil);
 		goto error;
 	      }
@@ -5904,7 +5904,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", specified_file, Qnil);
 	  return 0;
 	}
 
@@ -5912,7 +5912,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       fp = emacs_fopen (SSDATA (file), "rb");
       if (!fp)
 	{
-	  image_error ("Cannot open image file `%s'", file, Qnil);
+	  image_error (u8"Cannot open image file ‘%s’", file, Qnil);
 	  return 0;
 	}
 
@@ -5921,7 +5921,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
 	  || png_sig_cmp (sig, 0, sizeof sig))
 	{
 	  fclose (fp);
-	  image_error ("Not a PNG file: `%s'", file, Qnil);
+	  image_error (u8"Not a PNG file: ‘%s’", file, Qnil);
 	  return 0;
 	}
     }
@@ -5929,7 +5929,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
     {
       if (!STRINGP (specified_data))
 	{
-	  image_error ("Invalid image data `%s'", specified_data, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", specified_data, Qnil);
 	  return 0;
 	}
 
@@ -5942,7 +5942,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
       if (tbr.len < sizeof sig
 	  || png_sig_cmp (tbr.bytes, 0, sizeof sig))
 	{
-	  image_error ("Not a PNG image: `%s'", img->spec, Qnil);
+	  image_error (u8"Not a PNG image: ‘%s’", img->spec, Qnil);
 	  return 0;
 	}
 
@@ -6010,7 +6010,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
   if (! (width <= INT_MAX && height <= INT_MAX
 	 && check_image_size (f, width, height)))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       goto error;
     }
 
@@ -6668,20 +6668,20 @@ jpeg_load_body (struct frame *f, struct image *img,
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", specified_file, Qnil);
 	  return 0;
 	}
 
       fp = emacs_fopen (SSDATA (file), "rb");
       if (fp == NULL)
 	{
-	  image_error ("Cannot open `%s'", file, Qnil);
+	  image_error (u8"Cannot open ‘%s’", file, Qnil);
 	  return 0;
 	}
     }
   else if (!STRINGP (specified_data))
     {
-      image_error ("Invalid image data `%s'", specified_data, Qnil);
+      image_error (u8"Invalid image data ‘%s’", specified_data, Qnil);
       return 0;
     }
 
@@ -6697,13 +6697,13 @@ jpeg_load_body (struct frame *f, struct image *img,
 	  {
 	    char buf[JMSG_LENGTH_MAX];
 	    mgr->cinfo.err->format_message ((j_common_ptr) &mgr->cinfo, buf);
-	    image_error ("Error reading JPEG image `%s': %s", img->spec,
+	    image_error (u8"Error reading JPEG image ‘%s’: %s", img->spec,
 			 build_string (buf));
 	    break;
 	  }
 
 	case MY_JPEG_INVALID_IMAGE_SIZE:
-	  image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+	  image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
 	  break;
 
 	case MY_JPEG_CANNOT_CREATE_X:
@@ -7183,7 +7183,7 @@ tiff_load (struct frame *f, struct image *img)
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", specified_file, Qnil);
 	  return 0;
 	}
 # ifdef WINDOWSNT
@@ -7194,7 +7194,7 @@ tiff_load (struct frame *f, struct image *img)
       tiff = TIFFOpen (SSDATA (file), "r");
       if (tiff == NULL)
 	{
-	  image_error ("Cannot open `%s'", file, Qnil);
+	  image_error (u8"Cannot open ‘%s’", file, Qnil);
 	  return 0;
 	}
     }
@@ -7202,7 +7202,7 @@ tiff_load (struct frame *f, struct image *img)
     {
       if (!STRINGP (specified_data))
 	{
-	  image_error ("Invalid image data `%s'", specified_data, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", specified_data, Qnil);
 	  return 0;
 	}
 
@@ -7222,7 +7222,7 @@ tiff_load (struct frame *f, struct image *img)
 
       if (!tiff)
 	{
-	  image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
+	  image_error (u8"Cannot open memory source for ‘%s’", img->spec, Qnil);
 	  return 0;
 	}
     }
@@ -7234,7 +7234,7 @@ tiff_load (struct frame *f, struct image *img)
       if (! (TYPE_MINIMUM (tdir_t) <= ino && ino <= TYPE_MAXIMUM (tdir_t)
 	     && TIFFSetDirectory (tiff, ino)))
 	{
-	  image_error ("Invalid image number `%s' in image `%s'",
+	  image_error (u8"Invalid image number ‘%s’ in image ‘%s’",
 		       image, img->spec);
 	  TIFFClose (tiff);
 	  return 0;
@@ -7248,7 +7248,7 @@ tiff_load (struct frame *f, struct image *img)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       TIFFClose (tiff);
       return 0;
     }
@@ -7278,7 +7278,7 @@ tiff_load (struct frame *f, struct image *img)
   TIFFClose (tiff);
   if (!rc)
     {
-      image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
+      image_error (u8"Error reading TIFF image ‘%s’", img->spec, Qnil);
       xfree (buf);
       return 0;
     }
@@ -7615,7 +7615,7 @@ gif_load (struct frame *f, struct image *img)
       file = x_find_image_file (specified_file);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", specified_file, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", specified_file, Qnil);
 	  return 0;
 	}
 #ifdef WINDOWSNT
@@ -7627,14 +7627,14 @@ gif_load (struct frame *f, struct image *img)
       gif = DGifOpenFileName (SSDATA (file));
       if (gif == NULL)
 	{
-	  image_error ("Cannot open `%s'", file, Qnil);
+	  image_error (u8"Cannot open ‘%s’", file, Qnil);
 	  return 0;
 	}
 #else
       gif = DGifOpenFileName (SSDATA (file), &gif_err);
       if (gif == NULL)
 	{
-	  image_error ("Cannot open `%s': %s",
+	  image_error (u8"Cannot open ‘%s’: %s",
 		       file, build_string (GifErrorString (gif_err)));
 	  return 0;
 	}
@@ -7644,7 +7644,7 @@ gif_load (struct frame *f, struct image *img)
     {
       if (!STRINGP (specified_data))
 	{
-	  image_error ("Invalid image data `%s'", specified_data, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", specified_data, Qnil);
 	  return 0;
 	}
 
@@ -7658,14 +7658,14 @@ gif_load (struct frame *f, struct image *img)
       gif = DGifOpen (&memsrc, gif_read_from_memory);
       if (!gif)
 	{
-	  image_error ("Cannot open memory source `%s'", img->spec, Qnil);
+	  image_error (u8"Cannot open memory source ‘%s’", img->spec, Qnil);
 	  return 0;
 	}
 #else
       gif = DGifOpen (&memsrc, gif_read_from_memory, &gif_err);
       if (!gif)
 	{
-	  image_error ("Cannot open memory source `%s': %s",
+	  image_error (u8"Cannot open memory source ‘%s’: %s",
 		       img->spec, build_string (GifErrorString (gif_err)));
 	  return 0;
 	}
@@ -7675,7 +7675,7 @@ gif_load (struct frame *f, struct image *img)
   /* Before reading entire contents, check the declared image size. */
   if (!check_image_size (f, gif->SWidth, gif->SHeight))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       gif_close (gif, NULL);
       return 0;
     }
@@ -7684,7 +7684,7 @@ gif_load (struct frame *f, struct image *img)
   rc = DGifSlurp (gif);
   if (rc == GIF_ERROR || gif->ImageCount <= 0)
     {
-      image_error ("Error reading `%s'", img->spec, Qnil);
+      image_error (u8"Error reading ‘%s’", img->spec, Qnil);
       gif_close (gif, NULL);
       return 0;
     }
@@ -7695,7 +7695,7 @@ gif_load (struct frame *f, struct image *img)
     idx = INTEGERP (image_number) ? XFASTINT (image_number) : 0;
     if (idx < 0 || idx >= gif->ImageCount)
       {
-	image_error ("Invalid image number `%s' in image `%s'",
+	image_error (u8"Invalid image number ‘%s’ in image ‘%s’",
 		     image_number, img->spec);
 	gif_close (gif, NULL);
 	return 0;
@@ -7714,7 +7714,7 @@ gif_load (struct frame *f, struct image *img)
 
   if (!check_image_size (f, width, height))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       gif_close (gif, NULL);
       return 0;
     }
@@ -7968,10 +7968,10 @@ gif_load (struct frame *f, struct image *img)
       char *error_text = GifErrorString (gif_err);
 
       if (error_text)
-	image_error ("Error closing `%s': %s",
+	image_error (u8"Error closing ‘%s’: %s",
 		     img->spec, build_string (error_text));
 #else
-      image_error ("Error closing `%s'", img->spec, Qnil);
+      image_error (u8"Error closing ‘%s’", img->spec, Qnil);
 #endif
     }
 
@@ -8516,7 +8516,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   if (ino < 0 || ino >= MagickGetNumberImages (image_wand))
     {
-      image_error ("Invalid image number `%s' in image `%s'",
+      image_error (u8"Invalid image number ‘%s’ in image ‘%s’",
 		   image, img->spec);
       DestroyMagickWand (image_wand);
       return 0;
@@ -8651,7 +8651,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
   if (! (image_width <= INT_MAX && image_height <= INT_MAX
 	 && check_image_size (f, image_width, image_height)))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       goto imagemagick_error;
     }
 
@@ -8787,7 +8787,7 @@ imagemagick_load_image (struct frame *f, struct image *img,
 
   MagickWandTerminus ();
   /* TODO more cleanup.  */
-  image_error ("Error parsing IMAGEMAGICK image `%s'", img->spec, Qnil);
+  image_error (u8"Error parsing IMAGEMAGICK image ‘%s’", img->spec, Qnil);
   return 0;
 }
 
@@ -8811,7 +8811,7 @@ imagemagick_load (struct frame *f, struct image *img)
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", file_name, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", file_name, Qnil);
 	  return 0;
 	}
 #ifdef WINDOWSNT
@@ -8828,7 +8828,7 @@ imagemagick_load (struct frame *f, struct image *img)
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
 	{
-	  image_error ("Invalid image data `%s'", data, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", data, Qnil);
 	  return 0;
 	}
       success_p = imagemagick_load_image (f, img, SDATA (data),
@@ -9092,7 +9092,7 @@ svg_load (struct frame *f, struct image *img)
       file = x_find_image_file (file_name);
       if (!STRINGP (file))
 	{
-	  image_error ("Cannot find image file `%s'", file_name, Qnil);
+	  image_error (u8"Cannot find image file ‘%s’", file_name, Qnil);
 	  return 0;
 	}
 
@@ -9100,7 +9100,7 @@ svg_load (struct frame *f, struct image *img)
       contents = slurp_file (SSDATA (file), &size);
       if (contents == NULL)
 	{
-	  image_error ("Error loading SVG image `%s'", img->spec, Qnil);
+	  image_error (u8"Error loading SVG image ‘%s’", img->spec, Qnil);
 	  return 0;
 	}
       /* If the file was slurped into memory properly, parse it.  */
@@ -9116,7 +9116,7 @@ svg_load (struct frame *f, struct image *img)
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
 	{
-	  image_error ("Invalid image data `%s'", data, Qnil);
+	  image_error (u8"Invalid image data ‘%s’", data, Qnil);
 	  return 0;
 	}
       original_filename = BVAR (current_buffer, filename);
@@ -9183,7 +9183,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   rsvg_handle_get_dimensions (rsvg_handle, &dimension_data);
   if (! check_image_size (f, dimension_data.width, dimension_data.height))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       goto rsvg_error;
     }
 
@@ -9315,7 +9315,7 @@ svg_load_image (struct frame *f,         /* Pointer to emacs frame structure.  *
   g_object_unref (rsvg_handle);
   /* FIXME: Use error->message so the user knows what is the actual
      problem with the image.  */
-  image_error ("Error parsing SVG image `%s'", img->spec, Qnil);
+  image_error (u8"Error parsing SVG image ‘%s’", img->spec, Qnil);
   g_error_free (err);
   return 0;
 }
@@ -9468,7 +9468,7 @@ gs_load (struct frame *f, struct image *img)
   if (! (in_width <= INT_MAX && in_height <= INT_MAX
 	 && check_image_size (f, in_width, in_height)))
     {
-      image_error ("Invalid image size (see `max-image-size')", Qnil, Qnil);
+      image_error (u8"Invalid image size (see ‘max-image-size’)", Qnil, Qnil);
       return 0;
     }
   img->width = in_width;
@@ -9489,7 +9489,7 @@ gs_load (struct frame *f, struct image *img)
 
   if (!img->pixmap)
     {
-      image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
+      image_error (u8"Unable to create pixmap for ‘%s’", img->spec, Qnil);
       return 0;
     }
 
@@ -9601,7 +9601,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
 #endif
 	}
       else
-	image_error ("Cannot get X image of `%s'; colors will not be freed",
+	image_error (u8"Cannot get X image of ‘%s’; colors will not be freed",
 		     img->spec, Qnil);
 
       unblock_input ();
diff --git a/src/keymap.c b/src/keymap.c
index 8f4ac0d..6e370a4 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -770,7 +770,7 @@ store_in_keymap (Lisp_Object keymap, register Lisp_Object idx, Lisp_Object def)
   where_is_cache_keymaps = Qt;
 
   if (EQ (idx, Qkeymap))
-    error ("`keymap' is reserved for embedded parent maps");
+    error (u8"‘keymap’ is reserved for embedded parent maps");
 
   /* If we are preparing to dump, and DEF is a menu element
      with a menu item indicator, copy it to ensure it is not pure.  */
@@ -2858,7 +2858,7 @@ You type        Translation\n\
       if (!NILP (start1))
 	{
 	  describe_map_tree (start1, 1, shadow, prefix,
-			     "\f\n`keymap' Property Bindings", nomenu,
+			     u8"\f\n‘keymap’ Property Bindings", nomenu,
 			     0, 0, 0);
 	  shadow = Fcons (start1, shadow);
 	}
@@ -2903,7 +2903,7 @@ You type        Translation\n\
 			       "\f\nMajor Mode Bindings", nomenu, 0, 0, 0);
 	  else
 	    describe_map_tree (start1, 1, shadow, prefix,
-			       "\f\n`local-map' Property Bindings",
+			       u8"\f\n‘local-map’ Property Bindings",
 			       nomenu, 0, 0, 0);
 
 	  shadow = Fcons (start1, shadow);
diff --git a/src/lisp.h b/src/lisp.h
index 198f116..82d5f8f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -156,6 +156,13 @@ typedef EMACS_UINT uprintmax_t;
 # define pMu pI"u"
 #endif
 
+/* UTF-8 sequences for U+2018 LEFT SINGLE QUOTATION MARK and U+2019
+   RIGHT SINGLE QUOTATION MARK.  These may be useful in string
+   literals that use pI and similar macros, since these literals
+   cannot also portably use the u8 encoding prefix.  */
+#define uLSQM "\xE2\x80\x98"
+#define uRSQM "\xE2\x80\x99"
+
 /* Use pD to format ptrdiff_t values, which suffice for indexes into
    buffers and strings.  Emacs never allocates objects larger than
    PTRDIFF_MAX bytes, as they cause problems with pointer subtraction.
diff --git a/src/lread.c b/src/lread.c
index 11c8d00..5402494 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -947,7 +947,7 @@ load_warn_old_style_backquotes (Lisp_Object file)
 {
   if (!NILP (Vold_style_backquotes))
     {
-      AUTO_STRING (format, "Loading `%s': old-style backquotes detected!");
+      AUTO_STRING (format, u8"Loading ‘%s’: old-style backquotes detected!");
       CALLN (Fmessage, format, file);
     }
 }
@@ -1211,9 +1211,9 @@ Return t if the file exists and loads successfully.  */)
 	    {
 	      safe_p = 0;
 	      if (!load_dangerous_libraries)
-		error ("File `%s' was not compiled in Emacs", SDATA (found));
+		error (u8"File ‘%s’ was not compiled in Emacs", SDATA (found));
 	      else if (!NILP (nomessage) && !force_load_messages)
-		message_with_string ("File `%s' not compiled in Emacs", found, 1);
+		message_with_string (u8"File ‘%s’ not compiled in Emacs", found, 1);
 	    }
 
 	  compiled = 1;
@@ -1245,7 +1245,7 @@ Return t if the file exists and loads successfully.  */)
                     {
                       Lisp_Object msg_file;
                       msg_file = Fsubstring (found, make_number (0), make_number (-1));
-                      message_with_string ("Source file `%s' newer than byte-compiled file",
+                      message_with_string (u8"Source file ‘%s’ newer than byte-compiled file",
                                            msg_file, 1);
                     }
                 }
diff --git a/src/nsfns.m b/src/nsfns.m
index 6a2e2ff..264e53b 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -1948,7 +1948,7 @@ The optional argument FRAME is currently ignored.  */)
     {
       CHECK_FRAME (frame);
       if (! FRAME_NS_P (XFRAME (frame)))
-        error ("non-Nextstep frame used in `ns-list-colors'");
+        error (u8"non-Nextstep frame used in ‘ns-list-colors’");
     }
 
   block_input ();
diff --git a/src/regex.c b/src/regex.c
index 38c5e35..dcf2864 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -1544,9 +1544,9 @@ do {									\
   DEBUG_PRINT ("  Push frame index: %zd\n", fail_stack.frame);		\
   PUSH_FAILURE_INT (fail_stack.frame);					\
   									\
-  DEBUG_PRINT ("  Push string %p: `", string_place);			\
+  DEBUG_PRINT ("  Push string %p: \"", string_place);			\
   DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, size2);\
-  DEBUG_PRINT ("'\n");							\
+  DEBUG_PRINT ("\"\n");							\
   PUSH_FAILURE_POINTER (string_place);					\
   									\
   DEBUG_PRINT ("  Push pattern %p: ", pattern);				\
@@ -1598,9 +1598,9 @@ do {									\
      on_failure_keep_string_jump opcode, and we want to throw away the	\
      saved NULL, thus retaining our current position in the string.  */	\
   str = POP_FAILURE_POINTER ();						\
-  DEBUG_PRINT ("  Popping string %p: `", str);				\
+  DEBUG_PRINT ("  Popping string %p: \"", str);				\
   DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
-  DEBUG_PRINT ("'\n");							\
+  DEBUG_PRINT ("\"\n");							\
 									\
   fail_stack.frame = POP_FAILURE_INT ();				\
   DEBUG_PRINT ("  Popping  frame index: %zd\n", fail_stack.frame);	\
@@ -5127,9 +5127,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1,
 
   DEBUG_PRINT ("The compiled pattern is: ");
   DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
-  DEBUG_PRINT ("The string to match is: `");
+  DEBUG_PRINT ("The string to match is: \"");
   DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
-  DEBUG_PRINT ("'\n");
+  DEBUG_PRINT ("\"\n");
 
   /* This loops over pattern commands.  It exits by returning from the
      function if the match is complete, or it drops through if the match
@@ -5435,7 +5435,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1,
 		    && buf_ch == '\000'))
 	      goto fail;
 
-	    DEBUG_PRINT ("  Matched `%d'.\n", *d);
+	    DEBUG_PRINT ("  Matched \"%d\".\n", *d);
 	    d += buf_charlen;
 	  }
 	  break;
diff --git a/src/search.c b/src/search.c
index 5da99c4..5a6549e 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2346,7 +2346,7 @@ since only regular expressions have distinguished subexpressions.  */)
 				/* but some C compilers blew it */
 
   if (search_regs.num_regs <= 0)
-    error ("`replace-match' called before any match found");
+    error (u8"‘replace-match’ called before any match found");
 
   if (NILP (subexp))
     sub = 0;
@@ -2510,7 +2510,7 @@ since only regular expressions have distinguished subexpressions.  */)
 		  else if (c == '\\')
 		    delbackslash = 1;
 		  else if (c != '?')
-		    error ("Invalid use of `\\' in replacement text");
+		    error (u8"Invalid use of ‘\\’ in replacement text");
 		}
 	      if (substart >= 0)
 		{
@@ -2642,7 +2642,7 @@ since only regular expressions have distinguished subexpressions.  */)
 	      else
 		{
 		  xfree (substed);
-		  error ("Invalid use of `\\' in replacement text");
+		  error (u8"Invalid use of ‘\\’ in replacement text");
 		}
 	    }
 	  else
diff --git a/src/syntax.c b/src/syntax.c
index 1695815..02c4137 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1333,7 +1333,7 @@ DEFUN ("internal-describe-syntax-value", Finternal_describe_syntax_value,
     insert_string (" (nestable)");
 
   if (prefix)
-    insert_string (",\n\t  is a prefix character for `backward-prefix-chars'");
+    insert_string (u8",\n\t  is a prefix character for ‘backward-prefix-chars’");
 
   return syntax;
 }
diff --git a/src/sysdep.c b/src/sysdep.c
index 0a0b0ac..58dc40a 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2592,7 +2592,7 @@ serial_configure (struct Lisp_Process *p,
   else
     tem = Fplist_get (p->childp, QCparity);
   if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
-    error (":parity must be nil (no parity), `even', or `odd'");
+    error (u8":parity must be nil (no parity), ‘even’, or ‘odd’");
 #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK)
   attr.c_cflag &= ~(PARENB | PARODD);
   attr.c_iflag &= ~(IGNPAR | INPCK);
@@ -2647,7 +2647,7 @@ serial_configure (struct Lisp_Process *p,
   else
     tem = Fplist_get (p->childp, QCflowcontrol);
   if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
-    error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
+    error (u8":flowcontrol must be nil (no flowcontrol), ‘hw’, or ‘sw’");
 #if defined (CRTSCTS)
   attr.c_cflag &= ~CRTSCTS;
 #endif
diff --git a/src/w32.c b/src/w32.c
index 8721ed9..36f9808 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -9391,7 +9391,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
   else
     tem = Fplist_get (p->childp, QCparity);
   if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
-    error (":parity must be nil (no parity), `even', or `odd'");
+    error (u8":parity must be nil (no parity), ‘even’, or ‘odd’");
   dcb.fParity = FALSE;
   dcb.Parity = NOPARITY;
   dcb.fErrorChar = FALSE;
@@ -9438,7 +9438,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact)
   else
     tem = Fplist_get (p->childp, QCflowcontrol);
   if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
-    error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
+    error (u8":flowcontrol must be nil (no flowcontrol), ‘hw’, or ‘sw’");
   dcb.fOutxCtsFlow	= FALSE;
   dcb.fOutxDsrFlow	= FALSE;
   dcb.fDtrControl	= DTR_CONTROL_DISABLE;
diff --git a/src/window.c b/src/window.c
index ad5ac79..24d7c14 100644
--- a/src/window.c
+++ b/src/window.c
@@ -432,7 +432,7 @@ Return WINDOW.  */)
   CHECK_LIVE_WINDOW (window);
 
   if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
-    error ("In `set-frame-selected-window', WINDOW is not on FRAME");
+    error (u8"In ‘set-frame-selected-window’, WINDOW is not on FRAME");
 
   if (EQ (frame, selected_frame))
     return Fselect_window (window, norecord);
@@ -3521,7 +3521,7 @@ This function runs `window-scroll-functions' before running
 	  if (EQ (w->dedicated, Qt))
 	    /* WINDOW is strongly dedicated to its buffer, signal an
 	       error.  */
-	    error ("Window is dedicated to `%s'", SDATA (BVAR (XBUFFER (tem), name)));
+	    error (u8"Window is dedicated to ‘%s’", SDATA (BVAR (XBUFFER (tem), name)));
 	  else
 	    /* WINDOW is weakly dedicated to its buffer, reset
 	       dedication.  */
@@ -5755,7 +5755,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
   int this_scroll_margin;
 
   if (buf != current_buffer)
-    error ("`recenter'ing a window that does not display current-buffer.");
+    error (u8"‘recenter’ing a window that does not display current-buffer.");
 
   /* If redisplay is suppressed due to an error, try again.  */
   buf->display_error_modiff = 0;
diff --git a/src/xfaces.c b/src/xfaces.c
index f0b6d39..a7c74bf 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -797,7 +797,7 @@ load_pixmap (struct frame *f, Lisp_Object name)
 
   if (bitmap_id < 0)
     {
-      add_to_log ("Invalid or undefined bitmap `%s'", name, Qnil);
+      add_to_log (u8"Invalid or undefined bitmap ‘%s’", name, Qnil);
       bitmap_id = 0;
     }
   else
-- 
2.1.0