This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] locale: Fix localedef exit code [BZ #22292]
- From: Florian Weimer <fweimer at redhat dot com>
- To: Carlos O'Donell <carlos at redhat dot com>
- Cc: GNU C Library <libc-alpha at sourceware dot org>
- Date: Fri, 13 Oct 2017 15:19:25 +0200
- Subject: Re: [PATCH] locale: Fix localedef exit code [BZ #22292]
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=fweimer at redhat dot com
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 846AE2576E
- References: <1cc556ab-e8f8-fa8c-a9d9-b707ce577265@redhat.com>
On 10/13/2017 10:24 AM, Carlos O'Donell wrote:
To fix this situation I have adopted the following high-level
changes:
* All errors are counted distinctly.
* All warnings are counted distinctly.
* All informative messages are not counted.
* Increasing verbosity cannot generate*more* errors, and
it previously did for errors conditional on verbose,
this is now fixed.
* Increasing verbosity*can* generate*more* warnings.
* Making the output quiet cannot generate*less* errors,
“fewer errors“ (in case this makes it into the commit message.
The general approach of the patch looks okay to me. I expect that one
day, we might use the support/ infrastructure, potentially compiled for
the host, in these programs as well, but that's not a current priority.
@@ -1602,10 +1600,10 @@ 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);
runp->line fits on the preceding line (similar occurrences below).
@@ -1830,7 +1830,7 @@ 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'")));
+ record_error (0, 0, _("no definition of `UNDEFINED'"));
Either turn this into a pure comment, or into a real warning.
diff --git a/locale/programs/linereader.h b/locale/programs/linereader.h
index 3965db5..2623802 100644
--- a/locale/programs/linereader.h
+++ b/locale/programs/linereader.h
-#define lr_error(lr, fmt, args...) \
- WITH_CUR_LOCALE (error_at_line (0, 0, lr->fname, lr->lineno, fmt, ## args))
-
+static inline void
+lr_error (struct linereader *lr, const char *fmt, ...)
+{
+ char *str;
+ va_list arg;
+ struct locale_state ls;
+ va_start (arg, fmt);
+ ls = push_locale ();
+ vasprintf (&str, fmt, arg);
+ pop_locale (ls);
+ va_end (arg);
+ error_at_line (0, 0, lr->fname, lr->lineno, str);
+ free (str);
+}
Format string bug: This needs to to use error_at_line (0, 0, lr->fname,
lr->lineno, "%s", str). Missing error checking, and missing format
string attribute.
diff --git a/locale/programs/record-status.h b/locale/programs/record-status.h
new file mode 100644
index 0000000..8701f8c
--- /dev/null
+++ b/locale/programs/record-status.h
@@ -0,0 +1,144 @@
+/* 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
Missing empty line.
> +/* The program using these functions must define these: */
> +extern int recorded_warning_count;
> +extern int recorded_error_count;
> +extern int be_quiet;
> +extern int verbose;
You could turn these into tentative definitions (and update the
comment). Then the main program does not have to define them.
+/* Saved state of the current locale. */
+struct locale_state
+{
+ const char *cur_locale;
+};
Drop the const for the change below.
+/* Alter the current locale to match the locale configured by the
+ user, and return the previous saved state. */
+static inline struct locale_state
+push_locale (void)
+{
+ int saved_errno = errno;
+ const char *cl = setlocale (LC_CTYPE, NULL);
+ setlocale (LC_CTYPE, "");
+ errno = saved_errno;
+ return (struct locale_state) { .cur_locale = cl };
+}
+
+/* Use the saved state to restore the locale. */
+static inline void
+pop_locale (struct locale_state ls)
+{
+ setlocale (LC_CTYPE, ls.cur_locale);
+}
The locale string returned by setlocale is only valid until the next
setlocale call, I think, so you need to use strdup and free for the
locale string. strdup and setlocale need error checking. Maybe
introduce xsetlocale?
+/* Wrapper to print verbose informative messages. */
+static inline void
+record_verbose (FILE *stream, const char *format, ...)
+{
+ char *str;
+ va_list arg;
+
+ if (!verbose)
+ return;
+
+ if (!be_quiet)
+ {
+ struct locale_state ls;
+ va_start (arg, format);
+ ls = push_locale ();
+ vasprintf (&str, format, arg);
+ pop_locale (ls);
+ va_end (arg);
+ fprintf (stream, str);
+ free (str);
+ }
+}
These functions should not be inline and have printf/nonnull attributes.
fprintf has a format string bug, should use fputs. vasprintf needs
error checking.
+
+/* Wrapper to print warning messages. We keep track of how
+ many were called because this effects our exit code.
+ Program must provide a definition of recorded_warning_count,
+ and be_quiet. */
+static inline void
+record_warning (int status, int errnum, const char *format, ...)
+{
+ char *str;
+ va_list arg;
+ recorded_warning_count++;
+ if (!be_quiet)
+ {
+ struct locale_state ls;
+ va_start (arg, format);
+ ls = push_locale ();
+ vasprintf (&str, format, arg);
+ pop_locale (ls);
+ va_end (arg);
+ error (status, errnum, str);
+ free (str);
+ }
+}
The status/errnum parameters are unused and should be removed (status in
particularly is conceptually unusable).
error has a format string bug, should use error (status, errnum, "%s", str).
+/* Wrapper to print error messages. We keep track of how
+ many were called because this effects our exit code.
+ Program must provide a definition of recorded_error_count
+ and be_quiet. */
+static inline void
+record_error (int status, int errnum, const char *format, ...)
+{
+ char *str;
+ va_list arg;
+ recorded_error_count++;
+ if (!be_quiet)
+ {
+ struct locale_state ls;
+ va_start (arg, format);
+ ls = push_locale ();
+ vasprintf (&str, format, arg);
+ pop_locale (ls);
+ va_end (arg);
+ error (status, errnum, str);
+ free (str);
+ }
The condition needs to be !be_quiet || status != 0, otherwise be_quiet
also disables fatal errors. This applies to record_error_at_line, too.
Thanks,
Florian