]> git.cworth.org Git - tar/blob - gnu/rpmatch.c
upstream: Fix extraction of device nodes.
[tar] / gnu / rpmatch.c
1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* Determine whether string value is affirmation or negative response
4    according to current locale's data.
5
6    Copyright (C) 1996, 1998, 2000, 2002-2003, 2006-2010 Free Software
7    Foundation, Inc.
8
9    This program is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include <config.h>
23
24 /* Specification.  */
25 #include <stdlib.h>
26
27 #include <stdbool.h>
28 #include <stddef.h>
29
30 #if ENABLE_NLS
31 # include <sys/types.h>
32 # include <limits.h>
33 # include <string.h>
34 # if HAVE_LANGINFO_YESEXPR
35 #  include <langinfo.h>
36 # endif
37 # include <regex.h>
38 # include "gettext.h"
39 # define _(msgid) gettext (msgid)
40 # define N_(msgid) gettext_noop (msgid)
41
42 # if HAVE_LANGINFO_YESEXPR
43 /* Return the localized regular expression pattern corresponding to
44    ENGLISH_PATTERN.  NL_INDEX can be used with nl_langinfo.
45    The resulting string may only be used until the next nl_langinfo call.  */
46 static const char *
47 localized_pattern (const char *english_pattern, nl_item nl_index,
48                    bool posixly_correct)
49 {
50   const char *translated_pattern;
51
52   /* We prefer to get the patterns from a PO file.  It would be possible to
53      always use nl_langinfo (YESEXPR) instead of _("^[yY]"), and
54      nl_langinfo (NOEXPR) instead of _("^[nN]"), if we could assume that the
55      system's locale support is good.  But this is not the case e.g. on Cygwin.
56      The localizations of gnulib.pot are of better quality in general.
57      Also, if we use locale info from non-free systems that don't have a
58      'localedef' command, we deprive the users of the freedom to localize
59      this pattern for their preferred language.
60      But some programs, such as 'cp', 'mv', 'rm', 'find', 'xargs', are
61      specified by POSIX to use nl_langinfo (YESEXPR).  We implement this
62      behaviour if POSIXLY_CORRECT is set, for the sake of these programs.  */
63
64   /* If the user wants strict POSIX compliance, use nl_langinfo.  */
65   if (posixly_correct)
66     {
67       translated_pattern = nl_langinfo (nl_index);
68       /* Check against a broken system return value.  */
69       if (translated_pattern != NULL && translated_pattern[0] != '\0')
70         return translated_pattern;
71    }
72
73   /* Look in the gnulib message catalog.  */
74   translated_pattern = _(english_pattern);
75   if (translated_pattern == english_pattern)
76     {
77       /* The gnulib message catalog provides no translation.
78          Try the system's message catalog.  */
79       translated_pattern = nl_langinfo (nl_index);
80       /* Check against a broken system return value.  */
81       if (translated_pattern != NULL && translated_pattern[0] != '\0')
82         return translated_pattern;
83       /* Fall back to English.  */
84       translated_pattern = english_pattern;
85     }
86   return translated_pattern;
87 }
88 # else
89 #  define localized_pattern(english_pattern,nl_index,posixly_correct) \
90      _(english_pattern)
91 # endif
92
93 static int
94 try (const char *response, const char *pattern, char **lastp, regex_t *re)
95 {
96   if (*lastp == NULL || strcmp (pattern, *lastp) != 0)
97     {
98       char *safe_pattern;
99
100       /* The pattern has changed.  */
101       if (*lastp != NULL)
102         {
103           /* Free the old compiled pattern.  */
104           regfree (re);
105           free (*lastp);
106           *lastp = NULL;
107         }
108       /* Put the PATTERN into safe memory before calling regcomp.
109          (regcomp may call nl_langinfo, overwriting PATTERN's storage.  */
110       safe_pattern = strdup (pattern);
111       if (safe_pattern == NULL)
112         return -1;
113       /* Compile the pattern and cache it for future runs.  */
114       if (regcomp (re, safe_pattern, REG_EXTENDED) != 0)
115         return -1;
116       *lastp = safe_pattern;
117     }
118
119   /* See if the regular expression matches RESPONSE.  */
120   return regexec (re, response, 0, NULL, 0) == 0;
121 }
122 #endif
123
124
125 int
126 rpmatch (const char *response)
127 {
128 #if ENABLE_NLS
129   /* Match against one of the response patterns, compiling the pattern
130      first if necessary.  */
131
132   /* We cache the response patterns and compiled regexps here.  */
133   static char *last_yesexpr, *last_noexpr;
134   static regex_t cached_yesre, cached_nore;
135
136 # if HAVE_LANGINFO_YESEXPR
137   bool posixly_correct = (getenv ("POSIXLY_CORRECT") != NULL);
138 # endif
139
140   const char *yesexpr, *noexpr;
141   int result;
142
143   /* TRANSLATORS: A regular expression testing for an affirmative answer
144      (english: "yes").  Testing the first character may be sufficient.
145      Take care to consider upper and lower case.
146      To enquire the regular expression that your system uses for this
147      purpose, you can use the command
148        locale -k LC_MESSAGES | grep '^yesexpr='  */
149   yesexpr = localized_pattern (N_("^[yY]"), YESEXPR, posixly_correct);
150   result = try (response, yesexpr, &last_yesexpr, &cached_yesre);
151   if (result < 0)
152     return -1;
153   if (result)
154     return 1;
155
156   /* TRANSLATORS: A regular expression testing for a negative answer
157      (english: "no").  Testing the first character may be sufficient.
158      Take care to consider upper and lower case.
159      To enquire the regular expression that your system uses for this
160      purpose, you can use the command
161        locale -k LC_MESSAGES | grep '^noexpr='  */
162   noexpr = localized_pattern (N_("^[nN]"), NOEXPR, posixly_correct);
163   result = try (response, noexpr, &last_noexpr, &cached_nore);
164   if (result < 0)
165     return -1;
166   if (result)
167     return 0;
168
169   return -1;
170 #else
171   /* Test against "^[yY]" and "^[nN]", hardcoded to avoid requiring regex */
172   return (*response == 'y' || *response == 'Y' ? 1
173           : *response == 'n' || *response == 'N' ? 0 : -1);
174 #endif
175 }