summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog58
-rw-r--r--locale/programs/charmap-dir.c6
-rw-r--r--locale/programs/charmap.c35
-rw-r--r--locale/programs/ld-address.c90
-rw-r--r--locale/programs/ld-collate.c64
-rw-r--r--locale/programs/ld-ctype.c258
-rw-r--r--locale/programs/ld-identification.c24
-rw-r--r--locale/programs/ld-measurement.c14
-rw-r--r--locale/programs/ld-messages.c35
-rw-r--r--locale/programs/ld-monetary.c59
-rw-r--r--locale/programs/ld-name.c20
-rw-r--r--locale/programs/ld-numeric.c23
-rw-r--r--locale/programs/ld-paper.c14
-rw-r--r--locale/programs/ld-telephone.c26
-rw-r--r--locale/programs/ld-time.c97
-rw-r--r--locale/programs/linereader.h26
-rw-r--r--locale/programs/locale.c6
-rw-r--r--locale/programs/localedef.c62
-rw-r--r--locale/programs/localedef.h18
-rw-r--r--locale/programs/locarchive.c4
-rw-r--r--locale/programs/locfile.c15
-rw-r--r--locale/programs/record-status.h227
-rw-r--r--locale/programs/repertoire.c11
-rw-r--r--localedata/gen-locale.sh26
-rwxr-xr-xlocaledata/tst-fmon.sh19
-rwxr-xr-xlocaledata/tst-locale.sh19
26 files changed, 767 insertions, 489 deletions
diff --git a/ChangeLog b/ChangeLog
index d0bc31749e..fd3fe787df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,61 @@
+2017-10-13  Carlos O'Donell  <carlos@redhat.com>
+
+	[BZ #22292]
+	* locale/programs/record-status.h: New file
+	* locale/programs/locale.c: Add comment.
+	* locale/programs/charmap-dir.c: Don't include error.h.
+	(charmap_opendir): Use record_error.
+	* locale/programs/charmap.c: Don't include error.h.
+	(charmap_read): Use record_error, and record_warning.
+	(parse_charmap): Likewise.
+	* locale/programs/ld-address.c: Don't include error.h.
+	(address_finish): Use record_error, and record_warning.
+	* locale/programs/ld-collate.c: Don't include error.h.
+	(collate_finish): Use record_error, and record_error_at_line.
+	* locale/programs/ld-ctype.c (ctype_finish): Use record_error.
+	(ctype_class_new): Likewise.
+	(ctype_map_new): Likewise.
+	(set_one_default): Likewise.
+	(set_class_defaults): Likewise.
+	(translit_flatten): Likewise.
+	(allocate_arrays): Use record_error, and record_verbose.
+	* locale/programs/ld-identification.c: Don't include error.h.
+	(indentation_finish): Use record_error and record_warning.
+	* locale/programs/ld-measurement.c: Don't include error.h.
+	(measurement_finish): Use record_error.
+	* locale/programs/ld-messages.c
+	(message_finish): Likewise.
+	* locale/programs/ld-monetary.c
+	(monetary_finish): Likewise.
+	* locale/programs/ld-name.c (name_finish): Use record_error
+	and record_warning.
+	* locale/programs/ld-numeric.c
+	(numeric_finish): Use record_error.
+	* locale/programs/ld-paper.c: Don't include error.h.
+	(paper_finish): Use record_error.
+	* locale/programs/ld-telephone.c: Don't include error.h.
+	(telephone_finish): Use record_error.
+	* locale/programs/ld-time.c (time_finish): Likewise.
+	* locale/programs/linereader.h (lr_error): Make inline func.
+	* locale/programs/localedef.c: Define recorded_warning_count,
+	and recorded_error_count.
+	(main): Use record_error. Use recorded_error_count and
+	recorded_warning_count to issue correct error returns.
+	(add_to_readlist): Use record_error.
+	(find_locale): Likewise.
+	(load_locale): Likewise.
+	* locale/programs/localedef.h: Remove be_quiet
+	and WITH_CUR_LOCALE.
+	* locale/programs/locarchive.c (compare_from_file): Use
+	record_error.
+	* locale/programs/locfile.c (write_locale_data): Use
+	record_error.
+	* locale/programs/repertoire.c: Dont include error.h.
+	(repertoire_complain): Use record_error.
+	* localedata/tst-fmon.sh: Expect failures from localedef.
+	* localedata/tst-locale.sh: Likewise.
+	* localedata/gen-locale.sh: Expect failures from SHIFT_JIS.
+
 2017-10-12  Carlos O'Donell  <carlos@redhat.com>
 
 	* localedata/unicode-gen/Makefile (GENERATED): Use i18n_ctype.
diff --git a/locale/programs/charmap-dir.c b/locale/programs/charmap-dir.c
index e55ab86e28..a9212b72fb 100644
--- a/locale/programs/charmap-dir.c
+++ b/locale/programs/charmap-dir.c
@@ -16,7 +16,6 @@
 
 #include <dirent.h>
 #include <errno.h>
-#include <error.h>
 #include <fcntl.h>
 #include <libintl.h>
 #include <spawn.h>
@@ -54,8 +53,9 @@ charmap_opendir (const char *directory)
   dir = opendir (directory);
   if (dir == NULL)
     {
-      WITH_CUR_LOCALE (error (1, errno, gettext ("\
-cannot read character map directory `%s'"), directory));
+      record_error (1, errno, gettext ("\
+cannot read character map directory `%s'"),
+		    directory);
       return NULL;
     }
 
diff --git a/locale/programs/charmap.c b/locale/programs/charmap.c
index 129aefffc1..a670db9532 100644
--- a/locale/programs/charmap.c
+++ b/locale/programs/charmap.c
@@ -26,7 +26,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <error.h>
 #include <stdint.h>
 
 #include "localedef.h"
@@ -135,8 +134,9 @@ charmap_read (const char *filename, int verbose, int error_not_found,
 	result = parse_charmap (cmfile, verbose, be_quiet);
 
       if (result == NULL && error_not_found)
-	WITH_CUR_LOCALE (error (0, errno, _("\
-character map file `%s' not found"), filename));
+	record_error (0, errno,
+		      _("character map file `%s' not found"),
+		      filename);
     }
 
   if (result == NULL && filename != NULL && strchr (filename, '/') == NULL)
@@ -192,8 +192,9 @@ character map file `%s' not found"), filename));
 	result = parse_charmap (cmfile, verbose, be_quiet);
 
       if (result == NULL)
-	WITH_CUR_LOCALE (error (4, errno, _("\
-default character map file `%s' not found"), DEFAULT_CHARMAP));
+	record_error (4, errno,
+		      _("default character map file `%s' not found"),
+		      DEFAULT_CHARMAP);
     }
 
   if (result != NULL && result->code_set_name == NULL)
@@ -255,9 +256,9 @@ default character map file `%s' not found"), DEFAULT_CHARMAP));
 
       if (failed)
 	{
-	  WITH_CUR_LOCALE (fprintf (stderr, _("\
+	  record_warning (_("\
 character map `%s' is not ASCII compatible, locale not ISO C compliant\n"),
-				    result->code_set_name));
+			  result->code_set_name);
 	  enc_not_ascii_compatible = true;
 	}
     }
@@ -333,10 +334,9 @@ parse_charmap (struct linereader *cmfile, int verbose, int be_quiet)
 		result->mb_cur_min = result->mb_cur_max;
 	      if (result->mb_cur_min > result->mb_cur_max)
 		{
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: <mb_cur_max> must be greater than <mb_cur_min>\n"),
-					    cmfile->fname));
+				cmfile->fname);
 
 		  result->mb_cur_min = result->mb_cur_max;
 		}
@@ -395,11 +395,10 @@ parse_charmap (struct linereader *cmfile, int verbose, int be_quiet)
 	      if (arg->tok != tok_number)
 		goto badarg;
 
-	      if (verbose
-		  && ((nowtok == tok_mb_cur_max
+	      if ((nowtok == tok_mb_cur_max
 		       && result->mb_cur_max != 0)
 		      || (nowtok == tok_mb_cur_max
-			  && result->mb_cur_max != 0)))
+			  && result->mb_cur_max != 0))
 		lr_error (cmfile, _("duplicate definition of <%s>"),
 			  nowtok == tok_mb_cur_min
 			  ? "mb_cur_min" : "mb_cur_max");
@@ -839,16 +838,16 @@ only WIDTH definitions are allowed to follow the CHARMAP definition"));
 	  continue;
 
 	default:
-	  WITH_CUR_LOCALE (error (5, 0, _("%s: error in state machine"),
-				  __FILE__));
+	  record_error (5, 0, _("%s: error in state machine"),
+			__FILE__);
 	  /* NOTREACHED */
 	}
       break;
     }
 
-  if (state != 91 && !be_quiet)
-    WITH_CUR_LOCALE (error (0, 0, _("%s: premature end of file"),
-			    cmfile->fname));
+  if (state != 91)
+    record_error (0, 0, _("%s: premature end of file"),
+		  cmfile->fname);
 
   lr_close (cmfile);
 
diff --git a/locale/programs/ld-address.c b/locale/programs/ld-address.c
index 2488a5ce5c..a2892c71a2 100644
--- a/locale/programs/ld-address.c
+++ b/locale/programs/ld-address.c
@@ -20,7 +20,6 @@
 #endif
 
 #include <byteswap.h>
-#include <error.h>
 #include <langinfo.h>
 #include <string.h>
 #include <stdint.h>
@@ -131,9 +130,8 @@ address_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (address == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_ADDRESS"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_ADDRESS");
 	  address_startup (NULL, locale, 0);
 	  address = locale->categories[LC_ADDRESS].address;
 	  nothing = 1;
@@ -143,8 +141,8 @@ No definition for %s category found"), "LC_ADDRESS"));
   if (address->postal_fmt == NULL)
     {
       if (! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_ADDRESS", "postal_fmt"));
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_ADDRESS", "postal_fmt");
       /* Use as the default value the value of the i18n locale.  */
       address->postal_fmt = "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N";
     }
@@ -155,8 +153,8 @@ No definition for %s category found"), "LC_ADDRESS"));
       const char *cp = address->postal_fmt;
 
       if (*cp == '\0')
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
-				"LC_ADDRESS", "postal_fmt"));
+	record_error (0, 0, _("%s: field `%s' must not be empty"),
+		      "LC_ADDRESS", "postal_fmt");
       else
 	while (*cp != '\0')
 	  {
@@ -167,9 +165,9 @@ No definition for %s category found"), "LC_ADDRESS"));
 		  ++cp;
 		if (strchr ("nafdbshNtreClzTSc%", *cp) == NULL)
 		  {
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		    record_error (0, 0, _("\
 %s: invalid escape `%%%c' sequence in field `%s'"),
-					    "LC_ADDRESS", *cp, "postal_fmt"));
+				  "LC_ADDRESS", *cp, "postal_fmt");
 		    break;
 		  }
 	      }
@@ -181,8 +179,7 @@ No definition for %s category found"), "LC_ADDRESS"));
   if (address->cat == NULL)						      \
     {									      \
       if (verbose && ! nothing)						      \
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				"LC_ADDRESS", #cat));  	    		      \
+	record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS", #cat); \
       address->cat = "";						      \
     }
 
@@ -199,16 +196,16 @@ No definition for %s category found"), "LC_ADDRESS"));
   if (address->lang_term == NULL)
     {
       if (verbose && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_ADDRESS", "lang_term"));
+	record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS",
+			"lang_term");
       address->lang_term = "";
       cnt = sizeof (iso639) / sizeof (iso639[0]);
     }
   else if (address->lang_term[0] == '\0')
     {
       if (verbose)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
-				"LC_ADDRESS", "lang_term"));
+	record_warning (_("%s: field `%s' must not be empty"), "LC_ADDRESS",
+			"lang_term");
       cnt = sizeof (iso639) / sizeof (iso639[0]);
     }
   else
@@ -218,9 +215,9 @@ No definition for %s category found"), "LC_ADDRESS"));
 	if (strcmp (address->lang_term, iso639[cnt].term) == 0)
 	  break;
       if (cnt == sizeof (iso639) / sizeof (iso639[0]))
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: terminology language code `%s' not defined"),
-				"LC_ADDRESS", address->lang_term));
+		      "LC_ADDRESS", address->lang_term);
     }
 
   if (address->lang_ab == NULL)
@@ -228,8 +225,8 @@ No definition for %s category found"), "LC_ADDRESS"));
       if ((cnt == sizeof (iso639) / sizeof (iso639[0])
 	   || iso639[cnt].ab[0] != '\0')
 	  && verbose && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_ADDRESS", "lang_ab"));
+	record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS",
+			"lang_ab");
       address->lang_ab = "";
     }
   else if (address->lang_ab[0] == '\0')
@@ -237,14 +234,14 @@ No definition for %s category found"), "LC_ADDRESS"));
       if ((cnt == sizeof (iso639) / sizeof (iso639[0])
 	   || iso639[cnt].ab[0] != '\0')
 	  && verbose)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
-				"LC_ADDRESS", "lang_ab"));
+	record_warning (_("%s: field `%s' must not be empty"),
+			"LC_ADDRESS", "lang_ab");
     }
   else if (cnt < sizeof (iso639) / sizeof (iso639[0])
 	   && iso639[cnt].ab[0] == '\0')
     {
-      WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be defined"),
-			      "LC_ADDRESS", "lang_ab"));
+      record_error (0, 0, _("%s: field `%s' must not be defined"),
+		    "LC_ADDRESS", "lang_ab");
 
       address->lang_ab = "";
     }
@@ -257,16 +254,16 @@ No definition for %s category found"), "LC_ADDRESS"));
 	    if (strcmp (address->lang_ab, iso639[cnt].ab) == 0)
 	      break;
 	  if (cnt == sizeof (iso639) / sizeof (iso639[0]))
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	    record_error (0, 0, _("\
 %s: language abbreviation `%s' not defined"),
-				    "LC_ADDRESS", address->lang_ab));
+			  "LC_ADDRESS", address->lang_ab);
 	}
       else
 	if (strcmp (iso639[cnt].ab, address->lang_ab) != 0
 	    && iso639[cnt].ab[0] != '\0')
-	  WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: `%s' value does not match `%s' value"),
-				  "LC_ADDRESS", "lang_ab", "lang_term"));
+			"LC_ADDRESS", "lang_ab", "lang_term");
     }
 
   if (address->lang_lib == NULL)
@@ -275,8 +272,8 @@ No definition for %s category found"), "LC_ADDRESS"));
   else if (address->lang_lib[0] == '\0')
     {
       if (verbose)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
-				"LC_ADDRESS", "lang_lib"));
+	record_warning (_("%s: field `%s' must not be empty"),
+			"LC_ADDRESS", "lang_lib");
     }
   else
     {
@@ -286,22 +283,22 @@ No definition for %s category found"), "LC_ADDRESS"));
 	    if (strcmp (address->lang_lib, iso639[cnt].lib) == 0)
 	      break;
 	  if (cnt == sizeof (iso639) / sizeof (iso639[0]))
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	    record_error (0, 0, _("\
 %s: language abbreviation `%s' not defined"),
-				    "LC_ADDRESS", address->lang_lib));
+			  "LC_ADDRESS", address->lang_lib);
 	}
       else
 	if (strcmp (iso639[cnt].ab, address->lang_ab) != 0)
-	  WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: `%s' value does not match `%s' value"), "LC_ADDRESS", "lang_lib",
-				  helper == 1 ? "lang_term" : "lang_ab"));
+			helper == 1 ? "lang_term" : "lang_ab");
     }
 
   if (address->country_num == 0)
     {
       if (verbose && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_ADDRESS", "country_num"));
+	record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS",
+			"country_num");
       cnt = sizeof (iso3166) / sizeof (iso3166[0]);
     }
   else
@@ -311,36 +308,35 @@ No definition for %s category found"), "LC_ADDRESS"));
 	  break;
 
       if (cnt == sizeof (iso3166) / sizeof (iso3166[0]))
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: numeric country code `%d' not valid"),
-				"LC_ADDRESS", address->country_num));
+		      "LC_ADDRESS", address->country_num);
     }
 
   if (address->country_ab2 == NULL)
     {
       if (verbose && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_ADDRESS", "country_ab2"));
+	record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS",
+			"country_ab2");
       address->country_ab2 = "  ";
     }
   else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
 	   && strcmp (address->country_ab2, iso3166[cnt].ab2) != 0)
-    WITH_CUR_LOCALE (error (0, 0,
-			    _("%s: `%s' value does not match `%s' value"),
-			    "LC_ADDRESS", "country_ab2", "country_num"));
+    record_error (0, 0, _("%s: `%s' value does not match `%s' value"),
+		  "LC_ADDRESS", "country_ab2", "country_num");
 
   if (address->country_ab3 == NULL)
     {
       if (verbose && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_ADDRESS", "country_ab3"));
+	record_warning (_("%s: field `%s' not defined"), "LC_ADDRESS",
+			"country_ab3");
       address->country_ab3 = "   ";
     }
   else if (cnt != sizeof (iso3166) / sizeof (iso3166[0])
 	   && strcmp (address->country_ab3, iso3166[cnt].ab3) != 0)
-    WITH_CUR_LOCALE (error (0, 0, _("\
+    record_error (0, 0, _("\
 %s: `%s' value does not match `%s' value"),
-			    "LC_ADDRESS", "country_ab3", "country_num"));
+		  "LC_ADDRESS", "country_ab3", "country_num");
 }
 
 
diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
index cec848cb7c..94864ae430 100644
--- a/locale/programs/ld-collate.c
+++ b/locale/programs/ld-collate.c
@@ -20,7 +20,6 @@
 #endif
 
 #include <errno.h>
-#include <error.h>
 #include <stdlib.h>
 #include <wchar.h>
 #include <stdint.h>
@@ -1560,10 +1559,9 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 
   if (collate == NULL)
     {
-      /* No data, no check.  */
-      if (! be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("No definition for %s category found"),
-				"LC_COLLATE"));
+      /* No data, no check. Issue a warning.  */
+      record_warning (_("No definition for %s category found"),
+		      "LC_COLLATE");
       return;
     }
 
@@ -1579,9 +1577,9 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	  && ((sect->rules[i] & sort_position)
 	      != (collate->current_section->rules[i] & sort_position)))
 	{
-	  WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: `position' must be used for a specific level in all sections or none"),
-				  "LC_COLLATE"));
+			"LC_COLLATE");
 	  break;
 	}
 
@@ -1602,10 +1600,9 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 		  {
 		    if (runp->weights[i].w[j]->weights == NULL)
 		      {
-			WITH_CUR_LOCALE (error_at_line (0, 0, runp->file,
-							runp->line,
-							_("symbol `%s' not defined"),
-							runp->weights[i].w[j]->name));
+			record_error_at_line (0, 0, runp->file, runp->line,
+					      _("symbol `%s' not defined"),
+					      runp->weights[i].w[j]->name);
 
 			need_undefined = 1;
 			runp->weights[i].w[j] = &collate->undefined;
@@ -1678,14 +1675,13 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 		      /* This should not happen.  It means that we have
 			 to symbols with the same byte sequence.  It is
 			 of course an error.  */
-		      WITH_CUR_LOCALE (error_at_line (0, 0, (*eptr)->file,
-						      (*eptr)->line,
-						      _("\
+		      record_error_at_line (0, 0, (*eptr)->file,
+					    (*eptr)->line,
+					    _("\
 symbol `%s' has the same encoding as"), (*eptr)->name);
-				       error_at_line (0, 0, runp->file,
-						      runp->line,
-						      _("symbol `%s'"),
-						      runp->name));
+
+		      record_error_at_line (0, 0, runp->file, runp->line,
+					    _("symbol `%s'"), runp->name);
 		      goto dont_insert;
 		    }
 		  else if (c < 0)
@@ -1784,14 +1780,13 @@ symbol `%s' has the same encoding as"), (*eptr)->name);
 		      /* This should not happen.  It means that we have
 			 two symbols with the same byte sequence.  It is
 			 of course an error.  */
-		      WITH_CUR_LOCALE (error_at_line (0, 0, (*eptr)->file,
-						      (*eptr)->line,
-						      _("\
+		      record_error_at_line (0, 0, (*eptr)->file,
+					    (*eptr)->line,
+					    _("\
 symbol `%s' has the same encoding as"), (*eptr)->name);
-				       error_at_line (0, 0, runp->file,
-						      runp->line,
-						      _("symbol `%s'"),
-						      runp->name));
+
+		      record_error_at_line (0, 0, runp->file, runp->line,
+					    _("symbol `%s'"), runp->name);
 		      goto dont_insertwc;
 		    }
 		  else if (c < 0)
@@ -1829,10 +1824,6 @@ symbol `%s' has the same encoding as"), (*eptr)->name);
 	{
 	  /* This seems not to be enforced by recent standards.  Don't
 	     emit an error, simply append UNDEFINED at the end.  */
-	  if (0)
-	    WITH_CUR_LOCALE (error (0, 0, _("no definition of `UNDEFINED'")));
-
-	  /* Add UNDEFINED at the end.  */
 	  collate->undefined.mborder =
 	    (int *) obstack_alloc (&collate->mempool, nrules * sizeof (int));
 
@@ -1858,8 +1849,7 @@ symbol `%s' has the same encoding as"), (*eptr)->name);
   /* Bail out if we have no sections because of earlier errors.  */
   if (sect == NULL)
     {
-      WITH_CUR_LOCALE (error (EXIT_FAILURE, 0,
-			      _("too many errors; giving up")));
+      record_error (EXIT_FAILURE, 0, _("too many errors; giving up"));
       return;
     }
 
@@ -3408,8 +3398,8 @@ error while adding equivalent collating symbol"));
 	    }
 	  else if (state == 3)
 	    {
-	      WITH_CUR_LOCALE (error (0, 0, _("\
-%s: missing `reorder-end' keyword"), "LC_COLLATE"));
+	      record_error (0, 0, _("\
+%s: missing `reorder-end' keyword"), "LC_COLLATE");
 	      state = 4;
 	    }
 	  else if (state != 2 && state != 4)
@@ -3769,11 +3759,11 @@ error while adding equivalent collating symbol"));
 		    }
 		}
 	      else if (state == 3)
-		WITH_CUR_LOCALE (error (0, 0, _("\
-%s: missing `reorder-end' keyword"), "LC_COLLATE"));
+		record_error (0, 0, _("\
+%s: missing `reorder-end' keyword"), "LC_COLLATE");
 	      else if (state == 5)
-		WITH_CUR_LOCALE (error (0, 0, _("\
-%s: missing `reorder-sections-end' keyword"), "LC_COLLATE"));
+		record_error (0, 0, _("\
+%s: missing `reorder-sections-end' keyword"), "LC_COLLATE");
 	    }
 	  arg = lr_token (ldfile, charmap, result, NULL, verbose);
 	  if (arg->tok == tok_eof)
diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
index df266c20d6..251e7a7a12 100644
--- a/locale/programs/ld-ctype.c
+++ b/locale/programs/ld-ctype.c
@@ -427,9 +427,8 @@ ctype_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (ctype == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_CTYPE"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_CTYPE");
 	  ctype_startup (NULL, locale, charmap, NULL, 0);
 	  ctype = locale->categories[LC_CTYPE].ctype;
 	}
@@ -446,9 +445,8 @@ No definition for %s category found"), "LC_CTYPE"));
   ctype->codeset_name = charmap->code_set_name;
   if (ctype->codeset_name == NULL)
     {
-      if (! be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("\
-No character set name specified in charmap")));
+      record_error (0, 0, _("\
+No character set name specified in charmap"));
       ctype->codeset_name = "//UNKNOWN//";
     }
 
@@ -475,13 +473,12 @@ No character set name specified in charmap")));
 			  {
 			    uint32_t value = ctype->charnames[cnt];
 
-			    if (!be_quiet)
-			      WITH_CUR_LOCALE (error (0, 0, _("\
+			    record_error (0, 0, _("\
 character L'\\u%0*x' in class `%s' must be in class `%s'"),
-						      value > 0xffff ? 8 : 4,
-						      value,
-						      valid_table[cls1].name,
-						      valid_table[cls2].name));
+					  value > 0xffff ? 8 : 4,
+					  value,
+					  valid_table[cls1].name,
+					  valid_table[cls2].name);
 			  }
 			break;
 
@@ -490,13 +487,12 @@ character L'\\u%0*x' in class `%s' must be in class `%s'"),
 			  {
 			    uint32_t value = ctype->charnames[cnt];
 
-			    if (!be_quiet)
-			      WITH_CUR_LOCALE (error (0, 0, _("\
+			    record_error (0, 0, _("\
 character L'\\u%0*x' in class `%s' must not be in class `%s'"),
-						      value > 0xffff ? 8 : 4,
-						      value,
-						      valid_table[cls1].name,
-						      valid_table[cls2].name));
+					  value > 0xffff ? 8 : 4,
+					  value,
+					  valid_table[cls1].name,
+					  valid_table[cls2].name);
 			  }
 			break;
 
@@ -505,8 +501,8 @@ character L'\\u%0*x' in class `%s' must not be in class `%s'"),
 			break;
 
 		      default:
-			WITH_CUR_LOCALE (error (5, 0, _("\
-internal error in %s, line %u"), __FUNCTION__, __LINE__));
+			record_error (5, 0, _("\
+internal error in %s, line %u"), __FUNCTION__, __LINE__);
 		      }
 		  }
 	}
@@ -533,12 +529,11 @@ internal error in %s, line %u"), __FUNCTION__, __LINE__));
 
 			    snprintf (buf, sizeof buf, "\\%Zo", cnt);
 
-			    if (!be_quiet)
-			      WITH_CUR_LOCALE (error (0, 0, _("\
+			    record_error (0, 0, _("\
 character '%s' in class `%s' must be in class `%s'"),
-						      buf,
-						      valid_table[cls1].name,
-						      valid_table[cls2].name));
+					  buf,
+					  valid_table[cls1].name,
+					  valid_table[cls2].name);
 			  }
 			break;
 
@@ -549,12 +544,11 @@ character '%s' in class `%s' must be in class `%s'"),
 
 			    snprintf (buf, sizeof buf, "\\%Zo", cnt);
 
-			    if (!be_quiet)
-			      WITH_CUR_LOCALE (error (0, 0, _("\
+			    record_error (0, 0, _("\
 character '%s' in class `%s' must not be in class `%s'"),
-						      buf,
-						      valid_table[cls1].name,
-						      valid_table[cls2].name));
+					  buf,
+					  valid_table[cls1].name,
+					  valid_table[cls2].name);
 			  }
 			break;
 
@@ -563,8 +557,8 @@ character '%s' in class `%s' must not be in class `%s'"),
 			break;
 
 		      default:
-			WITH_CUR_LOCALE (error (5, 0, _("\
-internal error in %s, line %u"), __FUNCTION__, __LINE__));
+			record_error (5, 0, _("\
+internal error in %s, line %u"), __FUNCTION__, __LINE__);
 		      }
 		  }
 	}
@@ -579,9 +573,8 @@ internal error in %s, line %u"), __FUNCTION__, __LINE__));
 	   (ELEM (ctype, class_collection, , space_value)
 	    & BITw (tok_blank)) == 0)))
     {
-      if (!be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("<SP> character not in class `%s'"),
-				valid_table[cnt].name));
+      record_error (0, 0, _("<SP> character not in class `%s'"),
+		    valid_table[cnt].name);
     }
   else if (((cnt = BITPOS (tok_punct),
 	     (ELEM (ctype, class_collection, , space_value)
@@ -591,10 +584,9 @@ internal error in %s, line %u"), __FUNCTION__, __LINE__));
 		 & BITw (tok_graph))
 		!= 0)))
     {
-      if (!be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+      record_error (0, 0, _("\
 <SP> character must not be in class `%s'"),
-				valid_table[cnt].name));
+				valid_table[cnt].name);
     }
   else
     ELEM (ctype, class_collection, , space_value) |= BITw (tok_print);
@@ -606,9 +598,8 @@ internal error in %s, line %u"), __FUNCTION__, __LINE__));
     space_seq = charmap_find_value (charmap, "U00000020", 9);
   if (space_seq == NULL || space_seq->nbytes != 1)
     {
-      if (!be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("\
-character <SP> not defined in character map")));
+      record_error (0, 0, _("\
+character <SP> not defined in character map"));
     }
   else if (((cnt = BITPOS (tok_space),
 	     (ctype->class256_collection[space_seq->bytes[0]]
@@ -617,9 +608,8 @@ character <SP> not defined in character map")));
 		(ctype->class256_collection[space_seq->bytes[0]]
 		 & BIT (tok_blank)) == 0)))
     {
-      if (!be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("<SP> character not in class `%s'"),
-				valid_table[cnt].name));
+       record_error (0, 0, _("<SP> character not in class `%s'"),
+		     valid_table[cnt].name);
     }
   else if (((cnt = BITPOS (tok_punct),
 	     (ctype->class256_collection[space_seq->bytes[0]]
@@ -628,10 +618,9 @@ character <SP> not defined in character map")));
 		(ctype->class256_collection[space_seq->bytes[0]]
 		 & BIT (tok_graph)) != 0)))
     {
-      if (!be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+      record_error (0, 0, _("\
 <SP> character must not be in class `%s'"),
-				valid_table[cnt].name));
+		    valid_table[cnt].name);
     }
   else
     ctype->class256_collection[space_seq->bytes[0]] |= BIT (tok_print);
@@ -743,8 +732,8 @@ character <SP> not defined in character map")));
       assert (ctype->mbdigits_act == ctype->wcdigits_act);
       ctype->wcdigits_act -= ctype->mbdigits_act % 10;
       ctype->mbdigits_act -= ctype->mbdigits_act % 10;
-      WITH_CUR_LOCALE (error (0, 0, _("\
-`digit' category has not entries in groups of ten")));
+      record_error (0, 0, _("\
+`digit' category has not entries in groups of ten"));
     }
 
   /* Check the input digits.  There must be a multiple of ten available.
@@ -792,8 +781,8 @@ character <SP> not defined in character map")));
 	      if (ctype->mbdigits[cnt] == NULL)
 		{
 		  /* Hum, this ain't good.  */
-		  WITH_CUR_LOCALE (error (0, 0, _("\
-no input digits defined and none of the standard names in the charmap")));
+		  record_error (0, 0, _("\
+no input digits defined and none of the standard names in the charmap"));
 
 		  ctype->mbdigits[cnt] = obstack_alloc (&((struct charmap_t *) charmap)->mem_pool,
 							sizeof (struct charseq) + 1);
@@ -857,8 +846,8 @@ no input digits defined and none of the standard names in the charmap")));
 
 	if (!warned)
 	  {
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-not all characters used in `outdigit' are available in the charmap")));
+	    record_error (0, 0, _("\
+not all characters used in `outdigit' are available in the charmap"));
 	    warned = 1;
 	  }
 
@@ -874,8 +863,8 @@ not all characters used in `outdigit' are available in the charmap")));
       {
 	if (!warned)
 	  {
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-not all characters used in `outdigit' are available in the repertoire")));
+	    record_error (0, 0, _("\
+not all characters used in `outdigit' are available in the repertoire"));
 	    warned = 1;
 	  }
 
@@ -1145,9 +1134,9 @@ ctype_class_new (struct linereader *lr, struct locale_ctype_t *ctype,
 
   if (ctype->nr_charclass == MAX_NR_CHARCLASS)
     /* Exit code 2 is prescribed in P1003.2b.  */
-    WITH_CUR_LOCALE (error (2, 0, _("\
+    record_error (2, 0, _("\
 implementation limit: no more than %Zd character classes allowed"),
-			    MAX_NR_CHARCLASS));
+		  MAX_NR_CHARCLASS);
 
   ctype->classnames[ctype->nr_charclass++] = name;
 }
@@ -1177,9 +1166,9 @@ ctype_map_new (struct linereader *lr, struct locale_ctype_t *ctype,
 
   if (ctype->map_collection_nr == MAX_NR_CHARMAP)
     /* Exit code 2 is prescribed in P1003.2b.  */
-    WITH_CUR_LOCALE (error (2, 0, _("\
+    record_error (2, 0, _("\
 implementation limit: no more than %d character maps allowed"),
-			    MAX_NR_CHARMAP));
+		  MAX_NR_CHARMAP);
 
   ctype->mapnames[cnt] = name;
 
@@ -2743,11 +2732,11 @@ with character code range values one must use the absolute ellipsis `...'"));
 			    {
 			      lr_error (ldfile, _("\
 %s: duplicate `default_missing' definition"), "LC_CTYPE");
-			      WITH_CUR_LOCALE (error_at_line (0, 0,
-							      ctype->default_missing_file,
-							      ctype->default_missing_lineno,
-							      _("\
-previous definition was here")));
+			      record_error_at_line (0, 0,
+						    ctype->default_missing_file,
+						    ctype->default_missing_lineno,
+						    _("\
+previous definition was here"));
 			    }
 			  else
 			    {
@@ -2885,15 +2874,14 @@ set_one_default (struct locale_ctype_t *ctype,
         }
       if (seq == NULL)
         {
-          if (!be_quiet)
-            WITH_CUR_LOCALE (error (0, 0, _("\
+          record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-                                    "LC_CTYPE", tmp));
+			"LC_CTYPE", tmp);
         }
       else if (seq->nbytes != 1)
-        WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-                                "LC_CTYPE", tmp));
+		      "LC_CTYPE", tmp);
       else
         ctype->class256_collection[seq->bytes[0]] |= bit;
 
@@ -2982,15 +2970,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U00000020", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<space>"));
+			"LC_CTYPE", "<space>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<space>"));
+		      "LC_CTYPE", "<space>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
 
@@ -3002,15 +2989,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U0000000C", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<form-feed>"));
+				    "LC_CTYPE", "<form-feed>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<form-feed>"));
+		      "LC_CTYPE", "<form-feed>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
 
@@ -3023,15 +3009,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U0000000A", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<newline>"));
+			"LC_CTYPE", "<newline>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<newline>"));
+		      "LC_CTYPE", "<newline>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
 
@@ -3044,15 +3029,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U0000000D", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<carriage-return>"));
+			"LC_CTYPE", "<carriage-return>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<carriage-return>"));
+		      "LC_CTYPE", "<carriage-return>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
 
@@ -3065,15 +3049,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U00000009", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<tab>"));
+			"LC_CTYPE", "<tab>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<tab>"));
+		      "LC_CTYPE", "<tab>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
 
@@ -3086,15 +3069,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U0000000B", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<vertical-tab>"));
+			"LC_CTYPE", "<vertical-tab>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<vertical-tab>"));
+		      "LC_CTYPE", "<vertical-tab>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_space);
 
@@ -3126,15 +3108,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U00000020", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<space>"));
+			"LC_CTYPE", "<space>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<space>"));
+		      "LC_CTYPE", "<space>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_blank);
 
@@ -3147,15 +3128,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U00000009", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	   record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<tab>"));
+		         "LC_CTYPE", "<tab>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<tab>"));
+		      "LC_CTYPE", "<tab>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_blank);
 
@@ -3212,15 +3192,14 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	seq = charmap_find_value (charmap, "U00000020", 9);
       if (seq == NULL)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-				    "LC_CTYPE", "<space>"));
+			"LC_CTYPE", "<space>");
 	}
       else if (seq->nbytes != 1)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: character `%s' in charmap not representable with one byte"),
-				"LC_CTYPE", "<space>"));
+		      "LC_CTYPE", "<space>");
       else
 	ctype->class256_collection[seq->bytes[0]] |= BIT (tok_print);
 
@@ -3254,17 +3233,15 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	    }
 	  if (seq_from == NULL)
 	    {
-	      if (!be_quiet)
-		WITH_CUR_LOCALE (error (0, 0, _("\
+	      record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-					"LC_CTYPE", tmp));
+			    "LC_CTYPE", tmp);
 	    }
 	  else if (seq_from->nbytes != 1)
 	    {
-	      if (!be_quiet)
-		WITH_CUR_LOCALE (error (0, 0, _("\
+	      record_error (0, 0, _("\
 %s: character `%s' needed as default value not representable with one byte"),
-					"LC_CTYPE", tmp));
+			    "LC_CTYPE", tmp);
 	    }
 	  else
 	    {
@@ -3279,17 +3256,15 @@ set_class_defaults (struct locale_ctype_t *ctype,
 		}
 	      if (seq_to == NULL)
 		{
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: character `%s' not defined while needed as default value"),
-					    "LC_CTYPE", tmp));
+				"LC_CTYPE", tmp);
 		}
 	      else if (seq_to->nbytes != 1)
 		{
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: character `%s' needed as default value not representable with one byte"),
-					    "LC_CTYPE", tmp));
+				"LC_CTYPE", tmp);
 		}
 	      else
 		/* The index [0] is determined by the order of the
@@ -3321,9 +3296,9 @@ set_class_defaults (struct locale_ctype_t *ctype,
   if (ctype->outdigits_act != 10)
     {
       if (ctype->outdigits_act != 0)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+	record_error (0, 0, _("\
 %s: field `%s' does not contain exactly ten entries"),
-				"LC_CTYPE", "outdigit"));
+		      "LC_CTYPE", "outdigit");
 
       for (size_t cnt = ctype->outdigits_act; cnt < 10; ++cnt)
 	{
@@ -3343,8 +3318,8 @@ set_class_defaults (struct locale_ctype_t *ctype,
 	  if (ctype->mboutdigits[cnt] == NULL)
 	    {
 	      /* Provide a replacement.  */
-	      WITH_CUR_LOCALE (error (0, 0, _("\
-no output digits defined and none of the standard names in the charmap")));
+	      record_error (0, 0, _("\
+no output digits defined and none of the standard names in the charmap"));
 
 	      ctype->mboutdigits[cnt] = obstack_alloc (&((struct charmap_t *) charmap)->mem_pool,
 						       sizeof (struct charseq)
@@ -3592,9 +3567,9 @@ translit_flatten (struct locale_ctype_t *ctype,
 
       if (other == NULL || other->categories[LC_CTYPE].ctype == NULL)
 	{
-	  WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: transliteration data from locale `%s' not available"),
-				  "LC_CTYPE", copy_locale));
+			"LC_CTYPE", copy_locale);
 	}
       else
 	{
@@ -3691,11 +3666,10 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
 	if (ctype->class_collection[idx] & _ISwbit (nr))
 	  wctype_table_add (t, ctype->charnames[idx]);
 
-      if (verbose)
-	WITH_CUR_LOCALE (fprintf (stderr, _("\
+      record_verbose (stderr, _("\
 %s: table for class \"%s\": %lu bytes\n"),
-				 "LC_CTYPE", ctype->classnames[nr],
-				 (unsigned long int) t->result_size));
+		      "LC_CTYPE", ctype->classnames[nr],
+		      (unsigned long int) t->result_size);
     }
 
   /* Room for table of mappings.  */
@@ -3756,11 +3730,10 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
 	  wctrans_table_add (t, ctype->charnames[idx],
 			     ctype->map_collection[nr][idx]);
 
-      if (verbose)
-	WITH_CUR_LOCALE (fprintf (stderr, _("\
+      record_verbose (stderr, _("\
 %s: table for map \"%s\": %lu bytes\n"),
-				 "LC_CTYPE", ctype->mapnames[nr],
-				 (unsigned long int) t->result_size));
+		      "LC_CTYPE", ctype->mapnames[nr],
+		      (unsigned long int) t->result_size);
     }
 
   /* Extra array for class and map names.  */
@@ -3881,9 +3854,8 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
     /* Set the width of L'\0' to 0.  */
     wcwidth_table_add (t, 0, 0);
 
-    if (verbose)
-      WITH_CUR_LOCALE (fprintf (stderr, _("%s: table for width: %lu bytes\n"),
-			       "LC_CTYPE", (unsigned long int) t->result_size));
+    record_verbose (stderr, _("%s: table for width: %lu bytes\n"),
+		    "LC_CTYPE", (unsigned long int) t->result_size);
   }
 
   /* Set MB_CUR_MAX.  */
diff --git a/locale/programs/ld-identification.c b/locale/programs/ld-identification.c
index 3e3ea649d7..6adee6a398 100644
--- a/locale/programs/ld-identification.c
+++ b/locale/programs/ld-identification.c
@@ -19,7 +19,6 @@
 # include <config.h>
 #endif
 
-#include <error.h>
 #include <langinfo.h>
 #include <stdlib.h>
 #include <string.h>
@@ -129,9 +128,8 @@ identification_finish (struct localedef_t *locale,
 	 empty one.  */
       if (identification == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_IDENTIFICATION"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_IDENTIFICATION");
 	  identification_startup (NULL, locale, 0);
 	  identification
 	    = locale->categories[LC_IDENTIFICATION].identification;
@@ -143,8 +141,8 @@ No definition for %s category found"), "LC_IDENTIFICATION"));
   if (identification->cat == NULL)					      \
     {									      \
       if (verbose && ! nothing)						      \
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				"LC_IDENTIFICATION", #cat));		      \
+	record_warning (_("%s: field `%s' not defined"), "LC_IDENTIFICATION", \
+			#cat);						      \
       identification->cat = "";						      \
     }
 
@@ -172,9 +170,9 @@ No definition for %s category found"), "LC_IDENTIFICATION"));
       if (identification->category[num] == NULL)
 	{
 	  if (verbose && ! nothing)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-%s: no identification for category `%s'"),
-				    "LC_IDENTIFICATION", category_name[num]));
+	    record_warning (_("\
+%s: no identification for category `%s'"), "LC_IDENTIFICATION",
+			    category_name[num]);
 	  identification->category[num] = "";
 	}
       else
@@ -196,11 +194,11 @@ No definition for %s category found"), "LC_IDENTIFICATION"));
 	      matched = true;
 
 	  if (matched != true)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	    record_error (0, 0, _("\
 %s: unknown standard `%s' for category `%s'"),
-				    "LC_IDENTIFICATION",
-				    identification->category[num],
-				    category_name[num]));
+			  "LC_IDENTIFICATION",
+			  identification->category[num],
+			  category_name[num]);
 	}
     }
 }
diff --git a/locale/programs/ld-measurement.c b/locale/programs/ld-measurement.c
index 92c849ebfb..7bafefe1a1 100644
--- a/locale/programs/ld-measurement.c
+++ b/locale/programs/ld-measurement.c
@@ -19,7 +19,6 @@
 # include <config.h>
 #endif
 
-#include <error.h>
 #include <langinfo.h>
 #include <string.h>
 #include <stdint.h>
@@ -90,9 +89,8 @@ measurement_finish (struct localedef_t *locale,
 	 empty one.  */
       if (measurement == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_MEASUREMENT"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_MEASUREMENT");
 	  measurement_startup (NULL, locale, 0);
 	  measurement = locale->categories[LC_MEASUREMENT].measurement;
 	  nothing = 1;
@@ -102,16 +100,16 @@ No definition for %s category found"), "LC_MEASUREMENT"));
   if (measurement->measurement == 0)
     {
       if (! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_MEASUREMENT", "measurement"));
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_MEASUREMENT", "measurement");
       /* Use as the default value the value of the i18n locale.  */
       measurement->measurement = 1;
     }
   else
     {
       if (measurement->measurement > 3)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: invalid value for field `%s'"),
-				"LC_MEASUREMENT", "measurement"));
+	record_error (0, 0, _("%s: invalid value for field `%s'"),
+		      "LC_MEASUREMENT", "measurement");
     }
 }
 
diff --git a/locale/programs/ld-messages.c b/locale/programs/ld-messages.c
index bc86ec0ccf..a8c2cd2084 100644
--- a/locale/programs/ld-messages.c
+++ b/locale/programs/ld-messages.c
@@ -93,9 +93,8 @@ messages_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (messages == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_MESSAGES"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_MESSAGES");
 	  messages_startup (NULL, locale, 0);
 	  messages = locale->categories[LC_MESSAGES].messages;
 	  nothing = 1;
@@ -110,17 +109,16 @@ No definition for %s category found"), "LC_MESSAGES"));
 
   if (messages->yesexpr == NULL)
     {
-      if (! be_quiet && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' undefined"),
-				"LC_MESSAGES", "yesexpr"));
+      if (! nothing)
+	record_error (0, 0, _("%s: field `%s' undefined"),
+		      "LC_MESSAGES", "yesexpr");
       messages->yesexpr = "^[yY]";
     }
   else if (messages->yesexpr[0] == '\0')
     {
-      if (!be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+      record_error (0, 0, _("\
 %s: value for field `%s' must not be an empty string"),
-				"LC_MESSAGES", "yesexpr"));
+		    "LC_MESSAGES", "yesexpr");
     }
   else
     {
@@ -134,9 +132,9 @@ No definition for %s category found"), "LC_MESSAGES"));
 	  char errbuf[BUFSIZ];
 
 	  (void) regerror (result, &re, errbuf, BUFSIZ);
-	  WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: no correct regular expression for field `%s': %s"),
-				  "LC_MESSAGES", "yesexpr", errbuf));
+			"LC_MESSAGES", "yesexpr", errbuf);
 	}
       else if (result != 0)
 	regfree (&re);
@@ -144,17 +142,16 @@ No definition for %s category found"), "LC_MESSAGES"));
 
   if (messages->noexpr == NULL)
     {
-      if (! be_quiet && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' undefined"),
-				"LC_MESSAGES", "noexpr"));
+      if (! nothing)
+	record_error (0, 0, _("%s: field `%s' undefined"),
+		      "LC_MESSAGES", "noexpr");
       messages->noexpr = "^[nN]";
     }
   else if (messages->noexpr[0] == '\0')
     {
-      if (!be_quiet)
-	WITH_CUR_LOCALE (error (0, 0, _("\
+      record_error (0, 0, _("\
 %s: value for field `%s' must not be an empty string"),
-				"LC_MESSAGES", "noexpr"));
+		    "LC_MESSAGES", "noexpr");
     }
   else
     {
@@ -168,9 +165,9 @@ No definition for %s category found"), "LC_MESSAGES"));
 	  char errbuf[BUFSIZ];
 
 	  (void) regerror (result, &re, errbuf, BUFSIZ);
-	  WITH_CUR_LOCALE (error (0, 0, _("\
+	  record_error (0, 0, _("\
 %s: no correct regular expression for field `%s': %s"),
-				  "LC_MESSAGES", "noexpr", errbuf));
+			"LC_MESSAGES", "noexpr", errbuf);
 	}
       else if (result != 0)
 	regfree (&re);
diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
index cd50541603..35d17490cb 100644
--- a/locale/programs/ld-monetary.c
+++ b/locale/programs/ld-monetary.c
@@ -185,13 +185,12 @@ monetary_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	    = from->categories[LC_MONETARY].monetary;
 	}
 
-      /* If there is still no definition issue an warning and create an
+      /* If there is still no definition issue a warning and create an
 	 empty one.  */
       if (monetary == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_MONETARY"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_MONETARY");
 	  monetary_startup (NULL, locale, 0);
 	  monetary = locale->categories[LC_MONETARY].monetary;
 	  nothing = 1;
@@ -201,9 +200,9 @@ No definition for %s category found"), "LC_MONETARY"));
 #define TEST_ELEM(cat, initval) \
   if (monetary->cat == NULL)						      \
     {									      \
-      if (! be_quiet && ! nothing)					      \
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				"LC_MONETARY", #cat));			      \
+      if (! nothing)							      \
+	record_error (0, 0, _("%s: field `%s' not defined"),		      \
+		      "LC_MONETARY", #cat);				      \
       monetary->cat = initval;						      \
     }
 
@@ -219,10 +218,10 @@ No definition for %s category found"), "LC_MONETARY"));
     {
       if (strlen (monetary->int_curr_symbol) != 4)
 	{
-	  if (! be_quiet && ! nothing)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+	  if (! nothing)
+	    record_error (0, 0, _("\
 %s: value of field `int_curr_symbol' has wrong length"),
-				    "LC_MONETARY"));
+			  "LC_MONETARY");
 	}
       else
 	{ /* Check the first three characters against ISO 4217 */
@@ -231,12 +230,11 @@ No definition for %s category found"), "LC_MONETARY"));
 	  symbol[3] = '\0';
 	  if (bsearch (symbol, valid_int_curr, NR_VALID_INT_CURR,
 		       sizeof (const char *),
-		       (comparison_fn_t) curr_strcmp) == NULL
-	       && !be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
+		       (comparison_fn_t) curr_strcmp) == NULL)
+	    record_warning (_("\
 %s: value of field `int_curr_symbol' does \
 not correspond to a valid name in ISO 4217"),
-				"LC_MONETARY"));
+			    "LC_MONETARY");
 	}
     }
 
@@ -245,25 +243,25 @@ not correspond to a valid name in ISO 4217"),
      != "".  */
   if (monetary->mon_decimal_point == NULL)
     {
-      if (! be_quiet && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_MONETARY", "mon_decimal_point"));
+      if (! nothing)
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_MONETARY", "mon_decimal_point");
       monetary->mon_decimal_point = ".";
     }
   else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing)
     {
-      WITH_CUR_LOCALE (error (0, 0, _("\
+      record_error (0, 0, _("\
 %s: value for field `%s' must not be an empty string"),
-			      "LC_MONETARY", "mon_decimal_point"));
+		    "LC_MONETARY", "mon_decimal_point");
     }
   if (monetary->mon_decimal_point_wc == L'\0')
     monetary->mon_decimal_point_wc = L'.';
 
   if (monetary->mon_grouping_len == 0)
     {
-      if (! be_quiet && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_MONETARY", "mon_grouping"));
+      if (! nothing)
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_MONETARY", "mon_grouping");
 
       monetary->mon_grouping = (char *) "\177";
       monetary->mon_grouping_len = 1;
@@ -273,17 +271,17 @@ not correspond to a valid name in ISO 4217"),
 #define TEST_ELEM(cat, min, max, initval) \
   if (monetary->cat == -2)						      \
     {									      \
-       if (! be_quiet && ! nothing)					      \
-	 WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				 "LC_MONETARY", #cat));			      \
+       if (! nothing)							      \
+	 record_error (0, 0, _("%s: field `%s' not defined"),		      \
+		       "LC_MONETARY", #cat);				      \
        monetary->cat = initval;						      \
     }									      \
   else if ((monetary->cat < min || monetary->cat > max)			      \
 	   && min < max							      \
 	   && !be_quiet && !nothing)					      \
-    WITH_CUR_LOCALE (error (0, 0, _("\
+    record_error (0, 0, _("\
 %s: value for field `%s' must be in range %d...%d"),			      \
-			    "LC_MONETARY", #cat, min, max))
+		  "LC_MONETARY", #cat, min, max)
 
   TEST_ELEM (int_frac_digits, 1, 0, -1);
   TEST_ELEM (frac_digits, 1, 0, -1);
@@ -309,11 +307,10 @@ not correspond to a valid name in ISO 4217"),
 #define TEST_ELEM(cat, alt, min, max) \
   if (monetary->cat == -2)						      \
     monetary->cat = monetary->alt;					      \
-  else if ((monetary->cat < min || monetary->cat > max) && !be_quiet	      \
-	   && ! nothing)						      \
-    WITH_CUR_LOCALE (error (0, 0, _("\
+  else if ((monetary->cat < min || monetary->cat > max)	&& ! nothing)	      \
+    record_error (0, 0, _("\
 %s: value for field `%s' must be in range %d...%d"),			      \
-			    "LC_MONETARY", #cat, min, max))
+		  "LC_MONETARY", #cat, min, max)
 
   TEST_ELEM (int_p_cs_precedes, p_cs_precedes, -1, 1);
   TEST_ELEM (int_p_sep_by_space, p_sep_by_space, -1, 2);
diff --git a/locale/programs/ld-name.c b/locale/programs/ld-name.c
index ee50ae7322..2de82d5975 100644
--- a/locale/programs/ld-name.c
+++ b/locale/programs/ld-name.c
@@ -90,9 +90,8 @@ name_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (name == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_NAME"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_NAME");
 	  name_startup (NULL, locale, 0);
 	  name = locale->categories[LC_NAME].name;
 	  nothing = 1;
@@ -102,8 +101,8 @@ No definition for %s category found"), "LC_NAME"));
   if (name->name_fmt == NULL)
     {
       if (! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_NAME", "name_fmt"));
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_NAME", "name_fmt");
       /* Use as the default value the value of the i18n locale.  */
       name->name_fmt = "%p%t%g%t%m%t%f";
     }
@@ -114,8 +113,8 @@ No definition for %s category found"), "LC_NAME"));
       const char *cp = name->name_fmt;
 
       if (*cp == '\0')
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
-				"LC_NAME", "name_fmt"));
+	record_error (0, 0, _("%s: field `%s' must not be empty"),
+		      "LC_NAME", "name_fmt");
       else
 	while (*cp != '\0')
 	  {
@@ -126,8 +125,8 @@ No definition for %s category found"), "LC_NAME"));
 		  ++cp;
 		if (strchr ("dfFgGlomMpsSt", *cp) == NULL)
 		  {
-		    WITH_CUR_LOCALE (error (0, 0, _("\
-%s: invalid escape sequence in field `%s'"), "LC_NAME", "name_fmt"));
+		    record_error (0, 0, _("\
+%s: invalid escape sequence in field `%s'"), "LC_NAME", "name_fmt");
 		    break;
 		  }
 	      }
@@ -139,8 +138,7 @@ No definition for %s category found"), "LC_NAME"));
   if (name->cat == NULL)						      \
     {									      \
       if (verbose && ! nothing)						      \
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				"LC_NAME", #cat));          		      \
+	record_warning (_("%s: field `%s' not defined"), "LC_NAME", #cat);    \
       name->cat = "";							      \
     }
 
diff --git a/locale/programs/ld-numeric.c b/locale/programs/ld-numeric.c
index a81ff04f93..bdede34d0d 100644
--- a/locale/programs/ld-numeric.c
+++ b/locale/programs/ld-numeric.c
@@ -94,9 +94,8 @@ numeric_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (numeric == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_NUMERIC"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_NUMERIC");
 	  numeric_startup (NULL, locale, 0);
 	  numeric = locale->categories[LC_NUMERIC].numeric;
 	  nothing = 1;
@@ -108,23 +107,23 @@ No definition for %s category found"), "LC_NUMERIC"));
      != "".  */
   if (numeric->decimal_point == NULL)
     {
-      if (! be_quiet && ! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_NUMERIC", "decimal_point"));
+      if (! nothing)
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_NUMERIC", "decimal_point");
       numeric->decimal_point = ".";
     }
-  else if (numeric->decimal_point[0] == '\0' && ! be_quiet && ! nothing)
+  else if (numeric->decimal_point[0] == '\0' && ! nothing)
     {
-      WITH_CUR_LOCALE (error (0, 0, _("\
+      record_error (0, 0, _("\
 %s: value for field `%s' must not be an empty string"),
-			      "LC_NUMERIC", "decimal_point"));
+		    "LC_NUMERIC", "decimal_point");
     }
   if (numeric->decimal_point_wc == L'\0')
     numeric->decimal_point_wc = L'.';
 
-  if (numeric->grouping_len == 0 && ! be_quiet && ! nothing)
-    WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-			    "LC_NUMERIC", "grouping"));
+  if (numeric->grouping_len == 0 && ! nothing)
+    record_error (0, 0, _("%s: field `%s' not defined"),
+		  "LC_NUMERIC", "grouping");
 }
 
 
diff --git a/locale/programs/ld-paper.c b/locale/programs/ld-paper.c
index df7ce12036..9ac094b3a6 100644
--- a/locale/programs/ld-paper.c
+++ b/locale/programs/ld-paper.c
@@ -19,7 +19,6 @@
 # include <config.h>
 #endif
 
-#include <error.h>
 #include <langinfo.h>
 #include <string.h>
 #include <stdint.h>
@@ -87,9 +86,8 @@ paper_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (paper == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_PAPER"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_PAPER");
 	  paper_startup (NULL, locale, 0);
 	  paper = locale->categories[LC_PAPER].paper;
 	  nothing = 1;
@@ -99,8 +97,8 @@ No definition for %s category found"), "LC_PAPER"));
   if (paper->height == 0)
     {
       if (! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_PAPER", "height"));
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_PAPER", "height");
       /* Use as default values the values from the i18n locale.  */
       paper->height = 297;
     }
@@ -108,8 +106,8 @@ No definition for %s category found"), "LC_PAPER"));
   if (paper->width == 0)
     {
       if (! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_PAPER", "width"));
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_PAPER", "width");
       /* Use as default values the values from the i18n locale.  */
       paper->width = 210;
     }
diff --git a/locale/programs/ld-telephone.c b/locale/programs/ld-telephone.c
index b62280aeec..31623ceefb 100644
--- a/locale/programs/ld-telephone.c
+++ b/locale/programs/ld-telephone.c
@@ -19,7 +19,6 @@
 # include <config.h>
 #endif
 
-#include <error.h>
 #include <langinfo.h>
 #include <string.h>
 #include <stdint.h>
@@ -90,9 +89,8 @@ telephone_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (telephone == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_TELEPHONE"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_TELEPHONE");
 	  telephone_startup (NULL, locale, 0);
 	  telephone = locale->categories[LC_TELEPHONE].telephone;
 	  nothing = 1;
@@ -102,8 +100,8 @@ No definition for %s category found"), "LC_TELEPHONE"));
   if (telephone->tel_int_fmt == NULL)
     {
       if (! nothing)
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),
-				"LC_TELEPHONE", "tel_int_fmt"));
+	record_error (0, 0, _("%s: field `%s' not defined"),
+		      "LC_TELEPHONE", "tel_int_fmt");
       /* Use as the default value the value of the i18n locale.  */
       telephone->tel_int_fmt = "+%c %a%t%l";
     }
@@ -114,8 +112,8 @@ No definition for %s category found"), "LC_TELEPHONE"));
       const char *cp = telephone->tel_int_fmt;
 
       if (*cp == '\0')
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' must not be empty"),
-				"LC_TELEPHONE", "tel_int_fmt"));
+	record_error (0, 0, _("%s: field `%s' must not be empty"),
+		      "LC_TELEPHONE", "tel_int_fmt");
       else
 	while (*cp != '\0')
 	  {
@@ -123,8 +121,8 @@ No definition for %s category found"), "LC_TELEPHONE"));
 	      {
 		if (strchr ("aAcCelt", *++cp) == NULL)
 		  {
-		    WITH_CUR_LOCALE (error (0, 0, _("\
-%s: invalid escape sequence in field `%s'"), "LC_TELEPHONE", "tel_int_fmt"));
+		    record_error (0, 0, _("\
+%s: invalid escape sequence in field `%s'"), "LC_TELEPHONE", "tel_int_fmt");
 		    break;
 		  }
 	      }
@@ -146,8 +144,8 @@ No definition for %s category found"), "LC_TELEPHONE"));
 	    {
 	      if (strchr ("aAcCelt", *++cp) == NULL)
 		{
-		  WITH_CUR_LOCALE (error (0, 0, _("\
-%s: invalid escape sequence in field `%s'"), "LC_TELEPHONE", "tel_dom_fmt"));
+		  record_error (0, 0, _("\
+%s: invalid escape sequence in field `%s'"), "LC_TELEPHONE", "tel_dom_fmt");
 		  break;
 		}
 	    }
@@ -159,8 +157,8 @@ No definition for %s category found"), "LC_TELEPHONE"));
   if (telephone->cat == NULL)						      \
     {									      \
       if (verbose && ! nothing)						      \
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				"LC_TELEPHONE", #cat));     		      \
+	record_warning (_("%s: field `%s' not defined"), "LC_TELEPHONE",      \
+			#cat);						      \
       telephone->cat = "";						      \
     }
 
diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c
index 32e9c41e35..2c92bc9ece 100644
--- a/locale/programs/ld-time.c
+++ b/locale/programs/ld-time.c
@@ -155,9 +155,8 @@ time_finish (struct localedef_t *locale, const struct charmap_t *charmap)
 	 empty one.  */
       if (time == NULL)
 	{
-	  if (! be_quiet)
-	    WITH_CUR_LOCALE (error (0, 0, _("\
-No definition for %s category found"), "LC_TIME"));
+	  record_warning (_("\
+No definition for %s category found"), "LC_TIME");
 	  time_startup (NULL, locale, 0);
 	  time = locale->categories[LC_TIME].time;
 	  nothing = 1;
@@ -171,9 +170,9 @@ No definition for %s category found"), "LC_TIME"));
       const char *initval[] = { noparen val };				      \
       unsigned int i;							      \
 									      \
-      if (! be_quiet && ! nothing)					      \
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				"LC_TIME", #cat));          		      \
+      if (! nothing)					    		      \
+	record_error (0, 0, _("%s: field `%s' not defined"),	      	      \
+		      "LC_TIME", #cat);          			      \
 									      \
       for (i = 0; i < sizeof (initval) / sizeof (initval[0]); ++i)	      \
 	time->cat[i] = initval[i];					      \
@@ -192,9 +191,9 @@ No definition for %s category found"), "LC_TIME"));
 #define TEST_ELEM(cat, initval) \
   if (time->cat == NULL)						      \
     {									      \
-      if (! be_quiet && ! nothing)					      \
-	WITH_CUR_LOCALE (error (0, 0, _("%s: field `%s' not defined"),	      \
-				"LC_TIME", #cat));          		      \
+      if (! nothing)							      \
+	record_error (0, 0, _("%s: field `%s' not defined"),		      \
+		      "LC_TIME", #cat);          			      \
 									      \
       time->cat = initval;						      \
     }
@@ -243,10 +242,9 @@ No definition for %s category found"), "LC_TIME"));
 	  /* First character must be + or - for the direction.  */
 	  if (*str != '+' && *str != '-')
 	    {
-	      if (!be_quiet)
-		WITH_CUR_LOCALE (error (0, 0, _("\
+	      record_error (0, 0, _("\
 %s: direction flag in string %Zd in `era' field is not '+' nor '-'"),
-					"LC_TIME", idx + 1));
+			    "LC_TIME", idx + 1);
 	      /* Default arbitrarily to '+'.  */
 	      time->era_entries[idx].direction = '+';
 	    }
@@ -254,10 +252,9 @@ No definition for %s category found"), "LC_TIME"));
 	    time->era_entries[idx].direction = *str;
 	  if (*++str != ':')
 	    {
-	      if (!be_quiet)
-		WITH_CUR_LOCALE (error (0, 0, _("\
+	      record_error (0, 0, _("\
 %s: direction flag in string %Zd in `era' field is not a single character"),
-					"LC_TIME", idx + 1));
+			    "LC_TIME", idx + 1);
 	      (void) strsep (&str, ":");
 	    }
 	  else
@@ -267,18 +264,16 @@ No definition for %s category found"), "LC_TIME"));
 	  time->era_entries[idx].offset = strtol (str, &endp, 10);
 	  if (endp == str)
 	    {
-	      if (!be_quiet)
-		WITH_CUR_LOCALE (error (0, 0, _("\
+	      record_error (0, 0, _("\
 %s: invalid number for offset in string %Zd in `era' field"),
-					"LC_TIME", idx + 1));
+			    "LC_TIME", idx + 1);
 	      (void) strsep (&str, ":");
 	    }
 	  else if (*endp != ':')
 	    {
-	      if (!be_quiet)
-		WITH_CUR_LOCALE (error (0, 0, _("\
+	      record_error (0, 0, _("\
 %s: garbage at end of offset value in string %Zd in `era' field"),
-					"LC_TIME", idx + 1));
+			    "LC_TIME", idx + 1);
 	      (void) strsep (&str, ":");
 	    }
 	  else
@@ -326,19 +321,17 @@ No definition for %s category found"), "LC_TIME"));
 	      if (endp == str)
 		{
 		invalid_start_date:
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: invalid starting date in string %Zd in `era' field"),
-					    "LC_TIME", idx + 1));
+				"LC_TIME", idx + 1);
 		  (void) strsep (&str, ":");
 		}
 	      else if (*endp != ':')
 		{
 		garbage_start_date:
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: garbage at end of starting date in string %Zd in `era' field "),
-					    "LC_TIME", idx + 1));
+				"LC_TIME", idx + 1);
 		  (void) strsep (&str, ":");
 		}
 	      else
@@ -353,11 +346,10 @@ No definition for %s category found"), "LC_TIME"));
 			   > days_per_month[time->era_entries[idx].start_date[1]])
 		       || (time->era_entries[idx].start_date[1] == 2
 			   && time->era_entries[idx].start_date[2] == 29
-			   && !__isleap (time->era_entries[idx].start_date[0])))
-		      && !be_quiet)
-			  WITH_CUR_LOCALE (error (0, 0, _("\
+			   && !__isleap (time->era_entries[idx].start_date[0]))))
+		    record_error (0, 0, _("\
 %s: starting date is invalid in string %Zd in `era' field"),
-						  "LC_TIME", idx + 1));
+				  "LC_TIME", idx + 1);
 		}
 	    }
 
@@ -403,19 +395,17 @@ No definition for %s category found"), "LC_TIME"));
 	      if (endp == str)
 		{
 		invalid_stop_date:
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: invalid stopping date in string %Zd in `era' field"),
-					    "LC_TIME", idx + 1));
+				"LC_TIME", idx + 1);
 		  (void) strsep (&str, ":");
 		}
 	      else if (*endp != ':')
 		{
 		garbage_stop_date:
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: garbage at end of stopping date in string %Zd in `era' field"),
-					    "LC_TIME", idx + 1));
+				"LC_TIME", idx + 1);
 		  (void) strsep (&str, ":");
 		}
 	      else
@@ -430,19 +420,17 @@ No definition for %s category found"), "LC_TIME"));
 			   > days_per_month[time->era_entries[idx].stop_date[1]])
 		       || (time->era_entries[idx].stop_date[1] == 2
 			   && time->era_entries[idx].stop_date[2] == 29
-			   && !__isleap (time->era_entries[idx].stop_date[0])))
-		      && !be_quiet)
-			  WITH_CUR_LOCALE (error (0, 0, _("\
+			   && !__isleap (time->era_entries[idx].stop_date[0]))))
+		    record_error (0, 0, _("\
 %s: invalid stopping date in string %Zd in `era' field"),
-						  "LC_TIME", idx + 1));
+				  "LC_TIME", idx + 1);
 		}
 	    }
 
 	  if (str == NULL || *str == '\0')
 	    {
-	      if (!be_quiet)
-		WITH_CUR_LOCALE (error (0, 0, _("\
-%s: missing era name in string %Zd in `era' field"), "LC_TIME", idx + 1));
+	      record_error (0, 0, _("\
+%s: missing era name in string %Zd in `era' field"), "LC_TIME", idx + 1);
 	      time->era_entries[idx].name =
 		time->era_entries[idx].format = "";
 	    }
@@ -452,10 +440,9 @@ No definition for %s category found"), "LC_TIME"));
 
 	      if (str == NULL || *str == '\0')
 		{
-		  if (!be_quiet)
-		    WITH_CUR_LOCALE (error (0, 0, _("\
+		  record_error (0, 0, _("\
 %s: missing era format in string %Zd in `era' field"),
-					    "LC_TIME", idx + 1));
+				"LC_TIME", idx + 1);
 		  time->era_entries[idx].name =
 		    time->era_entries[idx].format = "";
 		}
@@ -498,33 +485,33 @@ No definition for %s category found"), "LC_TIME"));
     time->week_1stweek = 7;
 
   if (time->week_1stweek > time->week_ndays)
-    WITH_CUR_LOCALE (error (0, 0, _("\
+    record_error (0, 0, _("\
 %s: third operand for value of field `%s' must not be larger than %d"),
-			    "LC_TIME", "week", 7));
+		  "LC_TIME", "week", 7);
 
   if (time->first_weekday == '\0')
     /* The definition does not specify this so the default is used.  */
     time->first_weekday = 1;
   else if (time->first_weekday > time->week_ndays)
-    WITH_CUR_LOCALE (error (0, 0, _("\
+    record_error (0, 0, _("\
 %s: values for field `%s' must not be larger than %d"),
-			    "LC_TIME", "first_weekday", 7));
+		  "LC_TIME", "first_weekday", 7);
 
   if (time->first_workday == '\0')
     /* The definition does not specify this so the default is used.  */
     time->first_workday = 2;
   else if (time->first_workday > time->week_ndays)
-    WITH_CUR_LOCALE (error (0, 0, _("\
+    record_error (0, 0, _("\
 %s: values for field `%s' must not be larger than %d"),
-			    "LC_TIME", "first_workday", 7));
+		  "LC_TIME", "first_workday", 7);
 
   if (time->cal_direction == '\0')
     /* The definition does not specify this so the default is used.  */
     time->cal_direction = 1;
   else if (time->cal_direction > 3)
-    WITH_CUR_LOCALE (error (0, 0, _("\
+    record_error (0, 0, _("\
 %s: values for field `%s' must not be larger than %d"),
-			    "LC_TIME", "cal_direction", 3));
+		  "LC_TIME", "cal_direction", 3);
 
   /* XXX We don't perform any tests on the timezone value since this is
      simply useless, stupid $&$!@...  */
diff --git a/locale/programs/linereader.h b/locale/programs/linereader.h
index 3965db558c..279d3ffc49 100644
--- a/locale/programs/linereader.h
+++ b/locale/programs/linereader.h
@@ -27,7 +27,7 @@
 #include "error.h"
 #include "locfile-token.h"
 #include "repertoire.h"
-
+#include "record-status.h"
 
 typedef const struct keyword_t *(*kw_hash_fct_t) (const char *, unsigned int);
 struct charset_t;
@@ -96,9 +96,29 @@ extern struct token *lr_token (struct linereader *lr,
 extern void lr_ignore_rest (struct linereader *lr, int verbose);
 
 
-#define lr_error(lr, fmt, args...) \
-  WITH_CUR_LOCALE (error_at_line (0, 0, lr->fname, lr->lineno, fmt, ## args))
+static inline void
+__attribute__ ((__format__ (__printf__, 2, 3), nonnull (1, 2)))
+lr_error (struct linereader *lr, const char *fmt, ...)
+{
+  char *str;
+  va_list arg;
+  struct locale_state ls;
+  int ret;
+
+  va_start (arg, fmt);
+  ls = push_locale ();
+
+  ret = vasprintf (&str, fmt, arg);
+  if (ret == -1)
+    abort ();
 
+  pop_locale (ls);
+  va_end (arg);
+
+  error_at_line (0, 0, lr->fname, lr->lineno, "%s", str);
+
+  free (str);
+}
 
 
 static inline int
diff --git a/locale/programs/locale.c b/locale/programs/locale.c
index 941290089b..a29a32bc1a 100644
--- a/locale/programs/locale.c
+++ b/locale/programs/locale.c
@@ -59,7 +59,11 @@ static int do_all;
 /* Print names of all available character maps.  */
 static int do_charmaps = 0;
 
-/* Nonzero if verbose output is wanted.  */
+/* Nonzero if verbose output is wanted.  Note that this definition is
+   file-local in scope, and does not extended to uses of verbose in
+   record-status.h functions like record_verbose.  This means that this
+   verbose will not enable record_verbose messages for uses from locale,
+   but it does for uses from localdef (where verbose is global).  */
 static int verbose;
 
 /* Name and version of program.  */
diff --git a/locale/programs/localedef.c b/locale/programs/localedef.c
index 6acc1342c7..7d76154228 100644
--- a/locale/programs/localedef.c
+++ b/locale/programs/localedef.c
@@ -51,6 +51,12 @@ int posix_conformance;
 /* If not zero give a lot more messages.  */
 int verbose;
 
+/* Warnings recorded by record_warnings (see localedef.h).  */
+int recorded_warning_count;
+
+/* Errors recorded by record_error (see localedef.h).  */
+int recorded_error_count;
+
 /* If not zero suppress warnings and information messages.  */
 int be_quiet;
 
@@ -236,8 +242,8 @@ main (int argc, char *argv[])
      defines error code 3 for this situation so I think it must be
      a fatal error (see P1003.2 4.35.8).  */
   if (sysconf (_SC_2_LOCALEDEF) < 0)
-    WITH_CUR_LOCALE (error (3, 0, _("\
-FATAL: system does not define `_POSIX2_LOCALEDEF'")));
+    record_error (3, 0, _("\
+FATAL: system does not define `_POSIX2_LOCALEDEF'"));
 
   /* Process charmap file.  */
   charmap = charmap_read (charmap_file, verbose, 1, be_quiet, 1);
@@ -250,8 +256,8 @@ FATAL: system does not define `_POSIX2_LOCALEDEF'")));
 
   /* Now read the locale file.  */
   if (locfile_read (&global, charmap) != 0)
-    WITH_CUR_LOCALE (error (4, errno, _("\
-cannot open locale definition file `%s'"), input_file));
+    record_error (4, errno, _("\
+cannot open locale definition file `%s'"), input_file);
 
   /* Perhaps we saw some `copy' instructions.  */
   while (1)
@@ -266,29 +272,41 @@ cannot open locale definition file `%s'"), input_file));
 	break;
 
       if (locfile_read (runp, charmap) != 0)
-	WITH_CUR_LOCALE (error (4, errno, _("\
-cannot open locale definition file `%s'"), runp->name));
+	record_error (4, errno, _("\
+cannot open locale definition file `%s'"), runp->name);
     }
 
   /* Check the categories we processed in source form.  */
   check_all_categories (locales, charmap);
 
-  /* We are now able to write the data files.  If warning were given we
-     do it only if it is explicitly requested (--force).  */
-  if (error_message_count == 0 || force_output != 0)
+  /* What we do next depends on the number of errors and warnings we
+     have generated in processing the input files.
+
+     * No errors: Write the output file.
+
+     * Some warnings: Write the output file and exit with status 1 to
+     indicate there may be problems using the output file e.g. missing
+     data that makes it difficult to use
+
+     * Errors: We don't write the output file and we exit with status 4
+     to indicate no output files were written.
+
+     The use of -c|--force writes the output file even if errors were
+     seen.  */
+  if (recorded_error_count == 0 || force_output != 0)
     {
       if (cannot_write_why != 0)
-	WITH_CUR_LOCALE (error (4, cannot_write_why, _("\
-cannot write output files to `%s'"), output_path ? : argv[remaining]));
+	record_error (4, cannot_write_why, _("\
+cannot write output files to `%s'"), output_path ? : argv[remaining]);
       else
 	write_all_categories (locales, charmap, argv[remaining], output_path);
     }
   else
-    WITH_CUR_LOCALE (error (4, 0, _("\
-no output file produced because warnings were issued")));
+    record_error (4, 0, _("\
+no output file produced because errors were issued"));
 
   /* This exit status is prescribed by POSIX.2 4.35.7.  */
-  exit (error_message_count != 0);
+  exit (recorded_warning_count != 0);
 }
 
 
@@ -567,14 +585,14 @@ add_to_readlist (int category, const char *name, const char *repertoire_name,
   if (generate
       && (runp->needed & (1 << category)) != 0
       && (runp->avail & (1 << category)) == 0)
-    WITH_CUR_LOCALE (error (5, 0, _("\
-circular dependencies between locale definitions")));
+    record_error (5, 0, _("\
+circular dependencies between locale definitions"));
 
   if (copy_locale != NULL)
     {
       if (runp->categories[category].generic != NULL)
-	WITH_CUR_LOCALE (error (5, 0, _("\
-cannot add already read locale `%s' a second time"), name));
+	record_error (5, 0, _("\
+cannot add already read locale `%s' a second time"), name);
       else
 	runp->categories[category].generic =
 	  copy_locale->categories[category].generic;
@@ -599,8 +617,8 @@ find_locale (int category, const char *name, const char *repertoire_name,
 
   if ((result->avail & (1 << category)) == 0
       && locfile_read (result, charmap) != 0)
-    WITH_CUR_LOCALE (error (4, errno, _("\
-cannot open locale definition file `%s'"), result->name));
+    record_error (4, errno, _("\
+cannot open locale definition file `%s'"), result->name);
 
   return result;
 }
@@ -619,8 +637,8 @@ load_locale (int category, const char *name, const char *repertoire_name,
 
   if ((result->avail & (1 << category)) == 0
       && locfile_read (result, charmap) != 0)
-    WITH_CUR_LOCALE (error (4, errno, _("\
-cannot open locale definition file `%s'"), result->name));
+    record_error (4, errno, _("\
+cannot open locale definition file `%s'"), result->name);
 
   return result;
 }
diff --git a/locale/programs/localedef.h b/locale/programs/localedef.h
index 74a2eba74a..96aa6966a0 100644
--- a/locale/programs/localedef.h
+++ b/locale/programs/localedef.h
@@ -24,7 +24,11 @@
 #include <locale.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
 
+#include "record-status.h"
 #include "repertoire.h"
 #include "../locarchive.h"
 
@@ -111,7 +115,6 @@ struct localedef_t
 
 /* Global variables of the localedef program.  */
 extern int verbose;
-extern int be_quiet;
 extern const char *repertoire_global;
 extern int max_locarchive_open_retry;
 extern bool no_archive;
@@ -122,19 +125,6 @@ extern const char *alias_file;
 #include <programs/xmalloc.h>
 
 
-/* Wrapper to switch LC_CTYPE back to the locale specified in the
-   environment for output.  */
-#define WITH_CUR_LOCALE(stmt)					\
-  do {								\
-      int saved_errno = errno;					\
-      const char *cur_locale_ = setlocale (LC_CTYPE, NULL);	\
-      setlocale (LC_CTYPE, "");					\
-      errno = saved_errno; 					\
-      stmt;							\
-      setlocale (LC_CTYPE, cur_locale_);			\
-  } while (0)
-
-
 /* Mark given locale as to be read.  */
 extern struct localedef_t *add_to_readlist (int locale, const char *name,
 					    const char *repertoire_name,
diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
index f67b7b8d99..633c59b5be 100644
--- a/locale/programs/locarchive.c
+++ b/locale/programs/locarchive.c
@@ -320,8 +320,8 @@ compare_from_file (struct locarhandle *ah, void *p1, uint32_t offset2,
 {
   void *p2 = xmalloc (size);
   if (pread (ah->fd, p2, size, offset2) != size)
-    WITH_CUR_LOCALE (error (4, errno,
-			    _("cannot read data from locale archive")));
+    record_error (4, errno,
+		  _("cannot read data from locale archive"));
 
   int res = memcmp (p1, p2, size);
   free (p2);
diff --git a/locale/programs/locfile.c b/locale/programs/locfile.c
index 0990ef11be..b52efcf1d8 100644
--- a/locale/programs/locfile.c
+++ b/locale/programs/locfile.c
@@ -796,9 +796,8 @@ write_locale_data (const char *output_path, int catidx, const char *category,
 
       if (fd == -1)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, save_err, _("\
-cannot open output file `%s' for category `%s'"), fname, category));
+	  record_error (0, save_err, _("\
+cannot open output file `%s' for category `%s'"), fname, category);
 	  free (fname);
 	  return;
 	}
@@ -820,9 +819,8 @@ cannot open output file `%s' for category `%s'"), fname, category));
 
       if (writev (fd, &vec[cnt], step) < 0)
 	{
-	  if (!be_quiet)
-	    WITH_CUR_LOCALE (error (0, errno, _("\
-failure while writing data for category `%s'"), category));
+	  record_error (0, errno, _("\
+failure while writing data for category `%s'"), category);
 	  break;
 	}
     }
@@ -916,9 +914,8 @@ failure while writing data for category `%s'"), category));
 			      unlink (fname);
 			      if (rename (tmp_fname, fname) < 0)
 				{
-				  if (!be_quiet)
-				    WITH_CUR_LOCALE (error (0, errno, _("\
-cannot create output file `%s' for category `%s'"), fname, category));
+				  record_error (0, errno, _("\
+cannot create output file `%s' for category `%s'"), fname, category);
 				}
 			      free (tmp_fname);
 			      free (other_fname);
diff --git a/locale/programs/record-status.h b/locale/programs/record-status.h
new file mode 100644
index 0000000000..b6bc58cddc
--- /dev/null
+++ b/locale/programs/record-status.h
@@ -0,0 +1,227 @@
+/* General definitions for recording error and warning status.
+   Copyright (C) 1998-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; version 2 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _RECORD_STATUS_H
+#define _RECORD_STATUS_H 1
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <error.h>
+#include <locale.h>
+#include <string.h>
+
+/* We tentatively define all of the global data we use:
+   * recorded_warning_count: Number of warnings counted.
+   * recorded_error_count: Number of errors counted.
+   * be_quiet: Should all calls be silent?
+   * verbose: Should verbose messages be printed?  */
+int recorded_warning_count;
+int recorded_error_count;
+int be_quiet;
+int verbose;
+
+/* Saved locale state.  */
+struct locale_state
+{
+   /* The current in-use locale.  */
+   char *cur_locale;
+};
+
+/* Alter the current locale to match the locale configured by the
+   user, and return the previous saved state.  */
+static struct locale_state
+push_locale (void)
+{
+  int saved_errno;
+  const char *orig;
+  char *copy = NULL;
+
+  saved_errno = errno;
+
+  orig = setlocale (LC_CTYPE, NULL);
+  if (orig == NULL)
+    error (0, 0, "failed to read locale!");
+
+  if (setlocale (LC_CTYPE, "") == NULL)
+    error (0, 0, "failed to set locale!");
+
+  errno = saved_errno;
+
+  if (orig != NULL)
+    copy = strdup (orig);
+
+  /* We will return either a valid locale or NULL if we failed
+     to save the locale.  */
+  return (struct locale_state) { .cur_locale = copy };
+}
+
+/* Use the saved state to restore the locale.  */
+static void
+pop_locale (struct locale_state ls)
+{
+  const char *set = NULL;
+  /* We might have failed to save the locale, so only attempt to
+     restore a validly saved non-NULL locale.  */
+  if (ls.cur_locale != NULL)
+    {
+      set = setlocale (LC_CTYPE, ls.cur_locale);
+      if (set == NULL)
+	error (0, 0, "failed to restore %s locale!", ls.cur_locale);
+
+      free (ls.cur_locale);
+    }
+}
+
+/* Wrapper to print verbose informative messages.
+   Verbose messages are only printed if --verbose
+   is in effect and --quiet is not.  */
+static void
+__attribute__ ((__format__ (__printf__, 2, 3), nonnull (1, 2), unused))
+record_verbose (FILE *stream, const char *format, ...)
+{
+  char *str;
+  va_list arg;
+
+  if (!verbose)
+    return;
+
+  if (!be_quiet)
+    {
+      struct locale_state ls;
+      int ret;
+
+      va_start (arg, format);
+      ls = push_locale ();
+
+      ret = vasprintf (&str, format, arg);
+      if (ret == -1)
+	abort ();
+
+      pop_locale (ls);
+      va_end (arg);
+
+      fprintf (stream, "%s\n", str);
+
+      free (str);
+    }
+}
+
+/* Wrapper to print warning messages.  We keep track of how
+   many were called because this effects our exit code.
+   Nothing is printed if --quiet is in effect, but warnings
+   are always counted.  */
+static void
+__attribute__ ((__format__ (__printf__, 1, 2), nonnull (1), unused))
+record_warning (const char *format, ...)
+{
+  char *str;
+  va_list arg;
+
+  recorded_warning_count++;
+
+  if (!be_quiet)
+    {
+      struct locale_state ls;
+      int ret;
+
+      va_start (arg, format);
+      ls = push_locale ();
+
+      ret = vasprintf (&str, format, arg);
+      if (ret == -1)
+	abort ();
+
+      pop_locale (ls);
+      va_end (arg);
+
+      fprintf (stderr, "%s\n", str);
+
+      free (str);
+    }
+}
+
+/* Wrapper to print error messages.  We keep track of how
+   many were called because this effects our exit code.
+   Nothing is printed if --quiet is in effect, but errors
+   are always counted, and fatal errors always exit the
+   program.  */
+static void
+__attribute__ ((__format__ (__printf__, 3, 4), nonnull (3), unused))
+record_error (int status, int errnum, const char *format, ...)
+{
+  char *str;
+  va_list arg;
+
+  recorded_error_count++;
+
+  /* The existing behaviour is that even if you use --quiet, a fatal
+     error is always printed and terminates the process.  */
+  if (!be_quiet || status != 0)
+    {
+      struct locale_state ls;
+      int ret;
+
+      va_start (arg, format);
+      ls = push_locale ();
+
+      ret = vasprintf (&str, format, arg);
+      if (ret == -1)
+        abort ();
+
+      pop_locale (ls);
+      va_end (arg);
+
+      error (status, errnum, "%s", str);
+
+      free (str);
+    }
+}
+/* ... likewise for error_at_line.  */
+static void
+__attribute__ ((__format__ (__printf__, 5, 6), nonnull (3, 5), unused))
+record_error_at_line (int status, int errnum, const char *filename,
+		      unsigned int linenum, const char *format, ...)
+{
+  char *str;
+  va_list arg;
+
+  recorded_error_count++;
+
+  /* The existing behaviour is that even if you use --quiet, a fatal
+     error is always printed and terminates the process.  */
+  if (!be_quiet || status != 0)
+    {
+      struct locale_state ls;
+      int ret;
+
+      va_start (arg, format);
+      ls = push_locale ();
+
+      ret = vasprintf (&str, format, arg);
+      if (ret == -1)
+        abort ();
+
+      pop_locale (ls);
+      va_end (arg);
+
+      error_at_line (status, errnum, filename, linenum, "%s", str);
+
+      free (str);
+    }
+}
+
+#endif
diff --git a/locale/programs/repertoire.c b/locale/programs/repertoire.c
index 61f2c055e7..68f0f42cf4 100644
--- a/locale/programs/repertoire.c
+++ b/locale/programs/repertoire.c
@@ -20,7 +20,6 @@
 #endif
 
 #include <errno.h>
-#include <error.h>
 #include <limits.h>
 #include <obstack.h>
 #include <search.h>
@@ -321,14 +320,14 @@ argument to <%s> must be a single character"),
     }
 
   if (state != 2 && state != 90 && !be_quiet)
-    WITH_CUR_LOCALE (error (0, 0, _("%s: premature end of file"),
-			    repfile->fname));
+    record_error (0, 0, _("%s: premature end of file"),
+		  repfile->fname);
 
   lr_close (repfile);
 
   if (tsearch (result, &known, &repertoire_compare) == NULL)
     /* Something went wrong.  */
-    WITH_CUR_LOCALE (error (0, errno, _("cannot save new repertoire map")));
+    record_error (0, errno, _("cannot save new repertoire map"));
 
   return result;
 }
@@ -339,8 +338,8 @@ repertoire_complain (const char *name)
 {
   if (tfind (name, &unavailable, (__compar_fn_t) strcmp) == NULL)
     {
-      WITH_CUR_LOCALE (error (0, errno, _("\
-repertoire map file `%s' not found"), name));
+      record_error (0, errno, _("\
+repertoire map file `%s' not found"), name);
 
       /* Remember that we reported this map.  */
       tsearch (name, &unavailable, (__compar_fn_t) strcmp);
diff --git a/localedata/gen-locale.sh b/localedata/gen-locale.sh
index 0ebde468f0..b4ec68c36e 100644
--- a/localedata/gen-locale.sh
+++ b/localedata/gen-locale.sh
@@ -30,10 +30,16 @@ generate_locale ()
   charmap=$1
   input=$2
   out=$3
-  if ${localedef_before_env} ${run_program_env} I18NPATH=../localedata \
-     ${localedef_after_env} --quiet -c -f $charmap -i $input \
-			    ${common_objpfx}localedata/$out
-  then
+  ret=0
+  ${localedef_before_env} ${run_program_env} I18NPATH=../localedata \
+	${localedef_after_env} --quiet -c -f $charmap -i $input \
+	${common_objpfx}localedata/$out || ret=$?
+  # All locales compile fine, except those with SHIFT_JIS charmap
+  # and those fail with exit code 1 because SHIFT_JIS issues a
+  # warning (it is not ASCII compatible).
+  if [ $ret -eq 0 ] \
+     || ( [ $ret -eq 1 ] \
+          && [ "$charmap" = "SHIFT_JIS" ] ); then
     # The makefile checks the timestamp of the LC_CTYPE file,
     # but localedef won't have touched it if it was able to
     # hard-link it to an existing file.
@@ -50,5 +56,13 @@ locale=`echo $locfile|sed 's|\([^.]*\)[.].*/LC_CTYPE|\1|'`
 charmap=`echo $locfile|sed 's|[^.]*[.]\(.*\)/LC_CTYPE|\1|'`
 
 echo "Generating locale $locale.$charmap: this might take a while..."
-generate_locale `echo $charmap | sed -e s/SJIS/SHIFT_JIS/` $locale \
-		$locale.$charmap
+
+# For SJIS the charmap is SHIFT_JIS. We just want the locale to have
+# a slightly nicer name instead of using "*.SHIFT_SJIS", but that
+# means we need a mapping here.
+charmap_real="$charmap"
+if [ "$charmap" = "SJIS" ]; then
+  charmap_real="SHIFT_JIS"
+fi
+
+generate_locale $charmap_real $locale $locale.$charmap
diff --git a/localedata/tst-fmon.sh b/localedata/tst-fmon.sh
index f471ff03e4..029485d109 100755
--- a/localedata/tst-fmon.sh
+++ b/localedata/tst-fmon.sh
@@ -33,13 +33,22 @@ lang=`sed -e '/^#/d' -e '/^$/d' -e '/^C	/d' -e '/^tstfmon/d' -e 's/^\([^	]*\).*/
 
 # Generate data files.
 for cns in `cd ./tst-fmon-locales && ls tstfmon_*`; do
+    ret=0
     cn=tst-fmon-locales/$cns
     fn=charmaps/ISO-8859-1
+    # All of the test locales run with "USC " as their int_curr_symbol,
+    # and the use of this generates a warning because it does not meet
+    # the POSIX requirement that the name be an ISO 4217 compliant
+    # country code e.g. USD.  Therefore we *expect* an exit code of 1.
     ${run_program_prefix_before_env} \
     ${run_program_env} \
     I18NPATH=. \
     ${run_program_prefix_after_env} ${common_objpfx}locale/localedef \
-    --quiet -i $cn -f $fn ${common_objpfx}localedata/$cns
+    --quiet -i $cn -f $fn ${common_objpfx}localedata/$cns || ret=$?
+    if [ $ret -ne 1 ]; then
+	echo "FAIL: Locale compilation for $cn failed (error $ret)."
+	exit 1
+    fi
 done
 
 # Run the tests.
@@ -48,10 +57,14 @@ errcode=0
 while IFS="	" read locale format value expect; do
     case "$locale" in '#'*) continue ;; esac
     if [ -n "$format" ]; then
+	ret=0
 	expect=`echo "$expect" | sed 's/^\"\(.*\)\"$/\1/'`
 	${test_program_prefix} ${common_objpfx}localedata/tst-fmon \
-	"$locale" "$format" "$value" "$expect" < /dev/null ||
-	errcode=$?
+	"$locale" "$format" "$value" "$expect" < /dev/null || ret=$?
+        if [ $ret -ne 0 ]; then
+	    echo "FAIL: Locale $locale failed the test (error $ret)."
+	    errcode=1
+	fi
     fi
 done < $datafile
 
diff --git a/localedata/tst-locale.sh b/localedata/tst-locale.sh
index c73c1087d3..2d7da3c4a1 100755
--- a/localedata/tst-locale.sh
+++ b/localedata/tst-locale.sh
@@ -34,18 +34,29 @@ test_locale ()
     if test $rep; then
       rep="--repertoire-map $rep"
     fi
+    # We expect the test locales to fail with warnings, they are mostly
+    # incomplete and used for testing purposes, but that is OK.
+    ret=0
     ${localedef_before_env} \
     ${run_program_env} \
     I18NPATH=. \
     ${localedef_after_env} --quiet -c -f $charmap -i $input \
-      ${rep} ${common_objpfx}localedata/$out
-
-    if [ $? -ne 0 ]; then
+      ${rep} ${common_objpfx}localedata/$out || ret=$?
+    # Any error greater than one means we ran into an implementation
+    # defined limit or saw an error that caused the output not to
+    # be written, or lastly saw a fatal error that terminated
+    # localedef.
+    if [ $ret -gt 1 ]; then
 	echo "Charmap: \"${charmap}\" Inputfile: \"${input}\"" \
 	     "Outputdir: \"${out}\" failed"
 	exit 1
     else
-	echo "locale $out generated succesfully"
+	echo -n "locale $out generated succesfully"
+        if [ $ret -eq 1 ]; then
+	    echo " (with warnings)"
+        else
+	    echo " (without warnings)"
+        fi
     fi
 }