1 /* argmatch.c -- find a match for a string in an array
2 Copyright (C) 1990, 1998 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by David MacKenzie <djm@ai.mit.edu>
19 Modified by Akim Demaille <demaille@inf.enst.fr> */
32 # define setlocale(Category, Locale) /* empty */
37 # define _(Text) gettext (Text)
39 # define bindtextdomain(Domain, Directory) /* empty */
40 # define textdomain(Domain) /* empty */
45 # define EXIT_BADARG 1
50 /* When reporting a failing argument, make sure to show invisible
51 characters hidden using the quoting style
52 ARGMATCH_QUOTING_STYLE. literal_quoting_style is not good.*/
54 #ifndef ARGMATCH_QUOTING_STYLE
55 # define ARGMATCH_QUOTING_STYLE c_quoting_style
60 /* Compare no more than N characters of S1 and S2,
61 ignoring case, returning less than, equal to or
62 greater than zero if S1 is lexicographically less
63 than, equal to or greater than S2. */
65 strncasecmp (const char *s1, const char *s2, size_t n)
67 register const unsigned char *p1 = (const unsigned char *) s1;
68 register const unsigned char *p2 = (const unsigned char *) s2;
71 if (p1 == p2 || n == 0)
78 if (c1 == '\0' || c1 != c2)
86 extern char *program_name;
88 /* If ARG is an unambiguous match for an element of the
89 null-terminated array ARGLIST, return the index in ARGLIST
90 of the matched element, else -1 if it does not match any element
91 or -2 if it is ambiguous (is a prefix of more than one element).
92 If SENSITIVE, comparison is case sensitive.
94 If VALLIST is none null, use it to resolve ambiguities limited to
98 "y" is a valid argument, for `0', and "n" for `1'. */
101 __argmatch_internal (const char *arg, const char *const *arglist,
102 const char *vallist, size_t valsize,
105 int i; /* Temporary index in ARGLIST. */
106 size_t arglen; /* Length of ARG. */
107 int matchind = -1; /* Index of first nonexact match. */
108 int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
110 arglen = strlen (arg);
112 /* Test all elements for either exact match or abbreviated matches. */
113 for (i = 0; arglist[i]; i++)
115 if (sensitive ? !strncmp (arglist[i], arg, arglen)
116 : !strncasecmp (arglist[i], arg, arglen))
118 if (strlen (arglist[i]) == arglen)
119 /* Exact match found. */
121 else if (matchind == -1)
122 /* First nonexact match found. */
125 /* Second nonexact match found. */
127 || memcmp (vallist + valsize * matchind,
128 vallist + valsize * i, valsize))
129 /* There is a real ambiguity, or we could not
140 /* argmatch - case sensitive version */
142 argmatch (const char *arg, const char *const *arglist,
143 const char *vallist, size_t valsize)
145 return __argmatch_internal (arg, arglist, vallist, valsize, 1);
148 /* argcasematch - case insensitive version */
150 argcasematch (const char *arg, const char *const *arglist,
151 const char *vallist, size_t valsize)
153 return __argmatch_internal (arg, arglist, vallist, valsize, 0);
156 /* Error reporting for argmatch.
157 KIND is a description of the type of entity that was being matched.
158 VALUE is the invalid value that was given.
159 PROBLEM is the return value from argmatch. */
162 argmatch_invalid (const char *kind, const char *value, int problem)
164 enum quoting_style saved_quoting_style;
166 /* Make sure to have a good quoting style to report errors.
167 literal is insane here. */
168 saved_quoting_style = get_quoting_style (NULL);
169 set_quoting_style (NULL, ARGMATCH_QUOTING_STYLE);
171 /* There is an error */
172 fprintf (stderr, "%s: ", program_name);
174 fprintf (stderr, _("invalid argument %s for `%s'"),
175 quotearg (value), kind);
176 else /* Assume -2. */
177 fprintf (stderr, _("ambiguous argument %s for `%s'"),
178 quotearg (value), kind);
181 set_quoting_style (NULL, saved_quoting_style);
184 /* List the valid arguments for argmatch.
185 ARGLIST is the same as in argmatch.
186 VALLIST is a pointer to an array of values.
187 VALSIZE is the size of the elements of VALLIST */
189 argmatch_valid (const char *const *arglist,
190 const char *vallist, size_t valsize)
193 const char * last_val = NULL;
195 /* We try to put synonyms on the same line. The assumption is that
196 synonyms follow each other */
197 fprintf (stderr, _("Valid arguments are:"));
198 for (i = 0 ; arglist[i] ; i++)
200 || memcmp (last_val, vallist + valsize * i, valsize))
202 fprintf (stderr, "\n - `%s'", arglist[i]);
203 last_val = vallist + valsize * i;
207 fprintf (stderr, ", `%s'", arglist[i]);
212 /* Call __argmatch_internal, but handle the error so that it never
213 returns. Errors are reported to the users with a list of valid
216 KIND is a description of the type of entity that was being matched.
217 ARG, ARGLIST, and SENSITIVE are the same as in __argmatch_internal
218 VALIST, and VALSIZE are the same as in valid_args */
220 __xargmatch_internal (const char *kind, const char *arg,
221 const char *const *arglist,
222 const char *vallist, size_t valsize,
227 i = __argmatch_internal (arg, arglist, vallist, valsize, sensitive);
236 argmatch_invalid (kind, arg, i);
237 argmatch_valid (arglist, vallist, valsize);
240 return -1; /* To please some compilers */
243 /* Look for VALUE in VALLIST, an array of objects of size VALSIZE and
244 return the first corresponding argument in ARGLIST */
246 argmatch_to_argument (char * value,
247 const char *const *arglist,
248 const char *vallist, size_t valsize)
252 for (i = 0 ; arglist [i] ; i++)
253 if (!memcmp (value, vallist + valsize * i, valsize))
260 * Based on "getversion.c" by David MacKenzie <djm@gnu.ai.mit.edu>
263 extern const char * getenv ();
265 /* When to make backup files. */
268 /* Never make backups. */
271 /* Make simple backups of every file. */
274 /* Make numbered backups of files that already have numbered backups,
275 and simple backups of the others. */
278 /* Make numbered backups of every file. */
282 /* Two tables describing arguments (keys) and their corresponding
284 static const char *const backup_args[] =
293 static const enum backup_type backup_vals[] =
297 numbered_existing, numbered_existing,
302 main (int argc, const char *const * argv)
305 enum backup_type backup_type = none;
307 program_name = (char *) argv [0];
311 fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name);
315 if ((cp = getenv ("VERSION_CONTROL")))
316 backup_type = XARGCASEMATCH ("$VERSION_CONTROL", cp,
317 backup_args, backup_vals);
320 backup_type = XARGCASEMATCH (program_name, argv [1],
321 backup_args, backup_vals);
323 printf ("The version control is `%s'\n",
324 ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals));