From: Bruno Haible Date: Sat, 11 Nov 2023 15:48:05 +0000 (+0100) Subject: libgettextpo: Remove static variable bullet_stack. X-Git-Tag: v0.23~313 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27d567a4a3ff9546bd46e950924e4738175d0e57;p=thirdparty%2Fgettext.git libgettextpo: Remove static variable bullet_stack. * gettext-tools/src/xg-check.h: New file, extracted from gettext-tools/src/msgl-check.h. * gettext-tools/src/xg-check.c: New file, extracted from gettext-tools/src/msgl-check.c. * gettext-tools/src/msgl-check.h (syntax_check_message_list): Remove declaration. * gettext-tools/src/msgl-check.c: Don't include quote.h, sentence.h, unictype.h, unistr.h. (struct callback_arg, struct bullet_ty, struct bullet_stack_ty, syntax_check_function): Remove types. (bullet_stack, sc_funcs): Remove variables. (syntax_check_ellipsis_unicode, syntax_check_space_ellipsis, syntax_check_quote_unicode_callback, syntax_check_quote_unicode, syntax_check_bullet_unicode, syntax_check_message, syntax_check_message_list): Remove functions. * gettext-tools/src/xgettext.c: Include xg-check.h instead of msgl-check.h. * gettext-tools/src/Makefile.am (noinst_HEADERS): Add xg-check.h. (xgettext_SOURCES): Add xg-check.c. * gettext-tools/src/FILES: Mention xg-check.h, xg-check.c. * gettext-tools/po/POTFILES.in: Add src/xg-check.c. --- diff --git a/gettext-tools/po/POTFILES.in b/gettext-tools/po/POTFILES.in index ec8b29dd2..3cf95463c 100644 --- a/gettext-tools/po/POTFILES.in +++ b/gettext-tools/po/POTFILES.in @@ -1,5 +1,5 @@ # List of files which contain translatable strings. -# Copyright (C) 1995, 1998, 2001-2006, 2011, 2020, 2022 Free Software Foundation, Inc. +# Copyright (C) 1995-2023 Free Software Foundation, Inc. # This file is free software, distributed under GNU GPL v3+. # For updating this file, look at the result of: @@ -120,6 +120,7 @@ src/x-csharp.c src/x-desktop.c src/x-elisp.c src/xg-arglist-parser.c +src/xg-check.c src/xg-encoding.c src/xgettext.c src/xg-message.c diff --git a/gettext-tools/src/FILES b/gettext-tools/src/FILES index ff1fa3dd1..34aa6f3b5 100644 --- a/gettext-tools/src/FILES +++ b/gettext-tools/src/FILES @@ -323,6 +323,9 @@ msgl-check.c | xg-message.h | xg-message.c | Extracting a message. Accumulating the message list. +| xg-check.h +| xg-check.c +| Syntax checks on the extracted messages. | x-po.h | x-properties.h | x-stringtable.h diff --git a/gettext-tools/src/Makefile.am b/gettext-tools/src/Makefile.am index 4f60cc40c..c6d6763ba 100644 --- a/gettext-tools/src/Makefile.am +++ b/gettext-tools/src/Makefile.am @@ -58,7 +58,7 @@ noinst_HEADERS = \ xgettext.h \ if-error.h \ rc-str-list.h xg-pos.h xg-encoding.h xg-mixed-string.h xg-arglist-context.h \ - xg-arglist-callshape.h xg-arglist-parser.h xg-message.h \ + xg-arglist-callshape.h xg-arglist-parser.h xg-message.h xg-check.h \ x-po.h x-properties.h x-stringtable.h \ x-c.h \ x-python.h \ @@ -234,6 +234,7 @@ xgettext_SOURCES += \ xg-mixed-string.c \ xg-arglist-context.c xg-arglist-callshape.c xg-arglist-parser.c \ xg-message.c \ + xg-check.c \ x-po.c \ x-c.c \ x-python.c \ diff --git a/gettext-tools/src/msgl-check.c b/gettext-tools/src/msgl-check.c index c048e71ec..5415edb66 100644 --- a/gettext-tools/src/msgl-check.c +++ b/gettext-tools/src/msgl-check.c @@ -38,10 +38,6 @@ #include "plural-table.h" #include "c-strstr.h" #include "message.h" -#include "quote.h" -#include "sentence.h" -#include "unictype.h" -#include "unistr.h" #include "gettext.h" #define _(str) gettext (str) @@ -878,306 +874,3 @@ check_message_list (message_list_ty *mlp, return seen_errors; } - - -static int -syntax_check_ellipsis_unicode (const message_ty *mp, const char *msgid) -{ - const char *str = msgid; - const char *str_limit = str + strlen (msgid); - int seen_errors = 0; - - while (str < str_limit) - { - const char *end, *cp; - ucs4_t ending_char; - - end = sentence_end (str, &ending_char); - - /* sentence_end doesn't treat '...' specially. */ - cp = end - (ending_char == '.' ? 2 : 3); - if (cp >= str && memcmp (cp, "...", 3) == 0) - { - po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, - _("ASCII ellipsis ('...') instead of Unicode")); - seen_errors++; - } - - str = end + 1; - } - - return seen_errors; -} - - -static int -syntax_check_space_ellipsis (const message_ty *mp, const char *msgid) -{ - const char *str = msgid; - const char *str_limit = str + strlen (msgid); - int seen_errors = 0; - - while (str < str_limit) - { - const char *end, *ellipsis = NULL; - ucs4_t ending_char; - - end = sentence_end (str, &ending_char); - - if (ending_char == 0x2026) - ellipsis = end; - else if (ending_char == '.') - { - /* sentence_end doesn't treat '...' specially. */ - const char *cp = end - 2; - if (cp >= str && memcmp (cp, "...", 3) == 0) - ellipsis = cp; - } - else - { - /* Look for a '...'. */ - const char *cp = end - 3; - if (cp >= str && memcmp (cp, "...", 3) == 0) - ellipsis = cp; - else - { - ucs4_t uc = 0xfffd; - - /* Look for a U+2026. */ - for (cp = end - 1; cp >= str; cp--) - { - u8_mbtouc (&uc, (const unsigned char *) cp, end - cp); - if (uc != 0xfffd) - break; - } - - if (uc == 0x2026) - ellipsis = cp; - } - } - - if (ellipsis) - { - const char *cp; - ucs4_t uc = 0xfffd; - - /* Look at the character before ellipsis. */ - for (cp = ellipsis - 1; cp >= str; cp--) - { - u8_mbtouc (&uc, (const unsigned char *) cp, ellipsis - cp); - if (uc != 0xfffd) - break; - } - - if (uc != 0xfffd && uc_is_space (uc)) - { - po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, - _("space before ellipsis found in user visible strings")); - seen_errors++; - } - } - - str = end + 1; - } - - return seen_errors; -} - - -struct callback_arg -{ - const message_ty *mp; - int seen_errors; -}; - -static void -syntax_check_quote_unicode_callback (char quote, const char *quoted, - size_t quoted_length, void *data) -{ - struct callback_arg *arg = data; - - switch (quote) - { - case '"': - po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false, - _("ASCII double quote used instead of Unicode")); - arg->seen_errors++; - break; - - case '\'': - po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false, - _("ASCII single quote used instead of Unicode")); - arg->seen_errors++; - break; - - default: - break; - } -} - -static int -syntax_check_quote_unicode (const message_ty *mp, const char *msgid) -{ - struct callback_arg arg; - - arg.mp = mp; - arg.seen_errors = 0; - - scan_quoted (msgid, strlen (msgid), - syntax_check_quote_unicode_callback, &arg); - - return arg.seen_errors; -} - -struct bullet_ty -{ - int c; - size_t depth; -}; - -struct bullet_stack_ty -{ - struct bullet_ty *items; - size_t nitems; - size_t nitems_max; -}; - -static struct bullet_stack_ty bullet_stack; - -static int -syntax_check_bullet_unicode (const message_ty *mp, const char *msgid) -{ - const char *str = msgid; - const char *str_limit = str + strlen (msgid); - struct bullet_ty *last_bullet = NULL; - bool seen_error = false; - - bullet_stack.nitems = 0; - - while (str < str_limit) - { - const char *p = str, *end; - - while (p < str_limit && c_isspace (*p)) - p++; - - if ((*p == '*' || *p == '-') && *(p + 1) == ' ') - { - size_t depth = p - str; - if (last_bullet == NULL || depth > last_bullet->depth) - { - struct bullet_ty bullet; - - bullet.c = *p; - bullet.depth = depth; - - if (bullet_stack.nitems >= bullet_stack.nitems_max) - { - bullet_stack.nitems_max = 2 * bullet_stack.nitems_max + 4; - bullet_stack.items = xrealloc (bullet_stack.items, - bullet_stack.nitems_max - * sizeof (struct bullet_ty)); - } - - last_bullet = &bullet_stack.items[bullet_stack.nitems++]; - memcpy (last_bullet, &bullet, sizeof (struct bullet_ty)); - } - else - { - if (depth < last_bullet->depth) - { - if (bullet_stack.nitems > 1) - { - bullet_stack.nitems--; - last_bullet = - &bullet_stack.items[bullet_stack.nitems - 1]; - } - else - last_bullet = NULL; - } - - if (last_bullet && depth == last_bullet->depth) - { - if (last_bullet->c != *p) - last_bullet->c = *p; - else - { - seen_error = true; - break; - } - } - } - } - else - { - bullet_stack.nitems = 0; - last_bullet = NULL; - } - - end = strchrnul (str, '\n'); - str = end + 1; - } - - if (seen_error) - { - char *msg; - msg = xasprintf (_("ASCII bullet ('%c') instead of Unicode"), - last_bullet->c); - po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, msg); - free (msg); - return 1; - } - - return 0; -} - - -typedef int (* syntax_check_function) (const message_ty *mp, const char *msgid); -static const syntax_check_function sc_funcs[NSYNTAXCHECKS] = -{ - syntax_check_ellipsis_unicode, - syntax_check_space_ellipsis, - syntax_check_quote_unicode, - syntax_check_bullet_unicode -}; - -/* Perform all syntax checks on a non-obsolete message. - Return the number of errors that were seen. */ -static int -syntax_check_message (const message_ty *mp) -{ - int seen_errors = 0; - int i; - - for (i = 0; i < NSYNTAXCHECKS; i++) - { - if (mp->do_syntax_check[i] == yes) - { - seen_errors += sc_funcs[i] (mp, mp->msgid); - if (mp->msgid_plural) - seen_errors += sc_funcs[i] (mp, mp->msgid_plural); - } - } - - return seen_errors; -} - - -/* Perform all syntax checks on a message list. - Return the number of errors that were seen. */ -int -syntax_check_message_list (message_list_ty *mlp) -{ - int seen_errors = 0; - size_t j; - - for (j = 0; j < mlp->nitems; j++) - { - message_ty *mp = mlp->item[j]; - - if (!is_header (mp)) - seen_errors += syntax_check_message (mp); - } - - return seen_errors; -} diff --git a/gettext-tools/src/msgl-check.h b/gettext-tools/src/msgl-check.h index 5046b45e7..e5c2be0a3 100644 --- a/gettext-tools/src/msgl-check.h +++ b/gettext-tools/src/msgl-check.h @@ -1,5 +1,5 @@ /* Checking of messages in PO files. - Copyright (C) 2005, 2008, 2010, 2015 Free Software Foundation, Inc. + Copyright (C) 2005-2023 Free Software Foundation, Inc. Written by Bruno Haible , 2005. This program is free software: you can redistribute it and/or modify @@ -60,9 +60,6 @@ extern int check_message_list (message_list_ty *mlp, int check_compatibility, int check_accelerators, char accelerator_char); -/* Perform all syntax checks on a message list. - Return the number of errors that were seen. */ -extern int syntax_check_message_list (message_list_ty *mlp); #ifdef __cplusplus } diff --git a/gettext-tools/src/xg-check.c b/gettext-tools/src/xg-check.c new file mode 100644 index 000000000..4dc707832 --- /dev/null +++ b/gettext-tools/src/xg-check.c @@ -0,0 +1,360 @@ +/* Checking of messages in POT files: so-called "syntax checks". + Copyright (C) 2015-2023 Free Software Foundation, Inc. + + 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; either version 3 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 . */ + +/* Written by Daiki Ueno . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "xg-check.h" + +#include +#include + +#include "xalloc.h" +#include "xvasprintf.h" +#include "message.h" +#include "po-xerror.h" +#include "sentence.h" +#include "c-ctype.h" +#include "unictype.h" +#include "unistr.h" +#include "quote.h" +#include "gettext.h" + +#define _(str) gettext (str) + + +/* Function that implements a single syntax check. + MP is a message. + MSGID is either MP->msgid or MP->msgid_plural. + Returns the number of errors that were seen and reported. */ +typedef int (* syntax_check_function) (const message_ty *mp, const char *msgid); + + +/* Implementation of the sc_ellipsis_unicode syntax check. */ + +static int +syntax_check_ellipsis_unicode (const message_ty *mp, const char *msgid) +{ + const char *str = msgid; + const char *str_limit = str + strlen (msgid); + int seen_errors = 0; + + while (str < str_limit) + { + const char *end, *cp; + ucs4_t ending_char; + + end = sentence_end (str, &ending_char); + + /* sentence_end doesn't treat '...' specially. */ + cp = end - (ending_char == '.' ? 2 : 3); + if (cp >= str && memcmp (cp, "...", 3) == 0) + { + po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, + _("ASCII ellipsis ('...') instead of Unicode")); + seen_errors++; + } + + str = end + 1; + } + + return seen_errors; +} + + +/* Implementation of the sc_space_ellipsis syntax check. */ + +static int +syntax_check_space_ellipsis (const message_ty *mp, const char *msgid) +{ + const char *str = msgid; + const char *str_limit = str + strlen (msgid); + int seen_errors = 0; + + while (str < str_limit) + { + const char *end, *ellipsis = NULL; + ucs4_t ending_char; + + end = sentence_end (str, &ending_char); + + if (ending_char == 0x2026) + ellipsis = end; + else if (ending_char == '.') + { + /* sentence_end doesn't treat '...' specially. */ + const char *cp = end - 2; + if (cp >= str && memcmp (cp, "...", 3) == 0) + ellipsis = cp; + } + else + { + /* Look for a '...'. */ + const char *cp = end - 3; + if (cp >= str && memcmp (cp, "...", 3) == 0) + ellipsis = cp; + else + { + ucs4_t uc = 0xfffd; + + /* Look for a U+2026. */ + for (cp = end - 1; cp >= str; cp--) + { + u8_mbtouc (&uc, (const unsigned char *) cp, end - cp); + if (uc != 0xfffd) + break; + } + + if (uc == 0x2026) + ellipsis = cp; + } + } + + if (ellipsis) + { + const char *cp; + ucs4_t uc = 0xfffd; + + /* Look at the character before ellipsis. */ + for (cp = ellipsis - 1; cp >= str; cp--) + { + u8_mbtouc (&uc, (const unsigned char *) cp, ellipsis - cp); + if (uc != 0xfffd) + break; + } + + if (uc != 0xfffd && uc_is_space (uc)) + { + po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, + _("space before ellipsis found in user visible strings")); + seen_errors++; + } + } + + str = end + 1; + } + + return seen_errors; +} + + +/* Implementation of the sc_quote_unicode syntax check. */ + +struct callback_arg +{ + const message_ty *mp; + int seen_errors; +}; + +static void +syntax_check_quote_unicode_callback (char quote, const char *quoted, + size_t quoted_length, void *data) +{ + struct callback_arg *arg = data; + + switch (quote) + { + case '"': + po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false, + _("ASCII double quote used instead of Unicode")); + arg->seen_errors++; + break; + + case '\'': + po_xerror (PO_SEVERITY_ERROR, arg->mp, NULL, 0, 0, false, + _("ASCII single quote used instead of Unicode")); + arg->seen_errors++; + break; + + default: + break; + } +} + +static int +syntax_check_quote_unicode (const message_ty *mp, const char *msgid) +{ + struct callback_arg arg; + + arg.mp = mp; + arg.seen_errors = 0; + + scan_quoted (msgid, strlen (msgid), + syntax_check_quote_unicode_callback, &arg); + + return arg.seen_errors; +} + + +/* Implementation of the sc_bullet_unicode syntax check. */ + +struct bullet_ty +{ + int c; + size_t depth; +}; + +struct bullet_stack_ty +{ + struct bullet_ty *items; + size_t nitems; + size_t nitems_max; +}; + +static struct bullet_stack_ty bullet_stack; + +static int +syntax_check_bullet_unicode (const message_ty *mp, const char *msgid) +{ + const char *str = msgid; + const char *str_limit = str + strlen (msgid); + struct bullet_ty *last_bullet = NULL; + bool seen_error = false; + + bullet_stack.nitems = 0; + + while (str < str_limit) + { + const char *p = str, *end; + + while (p < str_limit && c_isspace (*p)) + p++; + + if ((*p == '*' || *p == '-') && *(p + 1) == ' ') + { + size_t depth = p - str; + if (last_bullet == NULL || depth > last_bullet->depth) + { + struct bullet_ty bullet; + + bullet.c = *p; + bullet.depth = depth; + + if (bullet_stack.nitems >= bullet_stack.nitems_max) + { + bullet_stack.nitems_max = 2 * bullet_stack.nitems_max + 4; + bullet_stack.items = xrealloc (bullet_stack.items, + bullet_stack.nitems_max + * sizeof (struct bullet_ty)); + } + + last_bullet = &bullet_stack.items[bullet_stack.nitems++]; + memcpy (last_bullet, &bullet, sizeof (struct bullet_ty)); + } + else + { + if (depth < last_bullet->depth) + { + if (bullet_stack.nitems > 1) + { + bullet_stack.nitems--; + last_bullet = + &bullet_stack.items[bullet_stack.nitems - 1]; + } + else + last_bullet = NULL; + } + + if (last_bullet && depth == last_bullet->depth) + { + if (last_bullet->c != *p) + last_bullet->c = *p; + else + { + seen_error = true; + break; + } + } + } + } + else + { + bullet_stack.nitems = 0; + last_bullet = NULL; + } + + end = strchrnul (str, '\n'); + str = end + 1; + } + + if (seen_error) + { + char *msg; + msg = xasprintf (_("ASCII bullet ('%c') instead of Unicode"), + last_bullet->c); + po_xerror (PO_SEVERITY_ERROR, mp, NULL, 0, 0, false, msg); + free (msg); + return 1; + } + + return 0; +} + + +/* List of all syntax checks. */ +static const syntax_check_function sc_funcs[NSYNTAXCHECKS] = +{ + syntax_check_ellipsis_unicode, + syntax_check_space_ellipsis, + syntax_check_quote_unicode, + syntax_check_bullet_unicode +}; + + +/* Perform all syntax checks on a non-obsolete message. + Return the number of errors that were seen. */ +static int +syntax_check_message (const message_ty *mp) +{ + int seen_errors = 0; + int i; + + for (i = 0; i < NSYNTAXCHECKS; i++) + { + if (mp->do_syntax_check[i] == yes) + { + seen_errors += sc_funcs[i] (mp, mp->msgid); + if (mp->msgid_plural) + seen_errors += sc_funcs[i] (mp, mp->msgid_plural); + } + } + + return seen_errors; +} + + +/* Perform all syntax checks on a message list. + Return the number of errors that were seen. */ +int +syntax_check_message_list (message_list_ty *mlp) +{ + int seen_errors = 0; + size_t j; + + for (j = 0; j < mlp->nitems; j++) + { + message_ty *mp = mlp->item[j]; + + if (!is_header (mp)) + seen_errors += syntax_check_message (mp); + } + + return seen_errors; +} diff --git a/gettext-tools/src/xg-check.h b/gettext-tools/src/xg-check.h new file mode 100644 index 000000000..bda684e37 --- /dev/null +++ b/gettext-tools/src/xg-check.h @@ -0,0 +1,39 @@ +/* Checking of messages in POT files: so-called "syntax checks". + Copyright (C) 2015-2023 Free Software Foundation, Inc. + + 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; either version 3 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 . */ + +/* Written by Daiki Ueno . */ + +#ifndef _XG_CHECK_H +#define _XG_CHECK_H 1 + +#include "message.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Perform all syntax checks on a message list. + Return the number of errors that were seen. */ +extern int syntax_check_message_list (message_list_ty *mlp); + + +#ifdef __cplusplus +} +#endif + +#endif /* _XG_CHECK_H */ diff --git a/gettext-tools/src/xgettext.c b/gettext-tools/src/xgettext.c index d44721e50..8abb61ba8 100644 --- a/gettext-tools/src/xgettext.c +++ b/gettext-tools/src/xgettext.c @@ -74,7 +74,7 @@ #include "msgl-iconv.h" #include "msgl-ascii.h" #include "msgl-ofn.h" -#include "msgl-check.h" +#include "xg-check.h" #include "po-time.h" #include "write-catalog.h" #include "write-po.h"