~youscribe/parted/3.1

« back to all changes in this revision

Viewing changes to lib/rpmatch.c

  • Committer: Guilhem Lettron
  • Date: 2012-10-22 14:37:59 UTC
  • Revision ID: guilhem+ubuntu@lettron.fr-20121022143759-m403kecgz13sknvp
3.1 from tarball

Show diffs side-by-side

added added

removed removed

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