1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include <config.h>
24:
25:
26: #include "argmatch.h"
27:
28: #include <stdbool.h>
29: #include <stdio.h>
30: #include <stdlib.h>
31: #include <string.h>
32:
33: #include "gettext.h"
34: #define _(msgid) gettext (msgid)
35:
36: #include "error.h"
37: #include "quotearg.h"
38: #include "quote.h"
39:
40: #if USE_UNLOCKED_IO
41: # include "unlocked-io.h"
42: #endif
43:
44:
45:
46:
47: #ifndef ARGMATCH_QUOTING_STYLE
48: # define ARGMATCH_QUOTING_STYLE locale_quoting_style
49: #endif
50:
51:
52: #ifndef ARGMATCH_DIE
53: # include "exitfail.h"
54: # define ARGMATCH_DIE exit (exit_failure)
55: #endif
56:
57: #ifdef ARGMATCH_DIE_DECL
58: ARGMATCH_DIE_DECL;
59: #endif
60:
61: static void
62: __argmatch_die (void)
63: {
64: ARGMATCH_DIE;
65: }
66:
67:
68:
69: argmatch_exit_fn argmatch_die = __argmatch_die;
70:
71: ^L
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83: ptrdiff_t
84: argmatch (const char *arg, const char *const *arglist,
85: const char *vallist, size_t valsize)
86: {
87: size_t i;
88: size_t arglen;
89: ptrdiff_t matchind = -1;
90: bool ambiguous = false;
91:
92: arglen = strlen (arg);
93:
94:
95: for (i = 0; arglist[i]; i++)
96: {
97: if (!strncmp (arglist[i], arg, arglen))
98: {
99: if (strlen (arglist[i]) == arglen)
100:
101: return i;
102: else if (matchind == -1)
103:
104: matchind = i;
105: else
106: {
107:
108: if (vallist == NULL
109: || memcmp (vallist + valsize * matchind,
110: vallist + valsize * i, valsize))
111: {
112:
113:
114: ambiguous = true;
115: }
116: }
117: }
118: }
119: if (ambiguous)
120: return -2;
121: else
122: return matchind;
123: }
124:
125:
126:
127:
128:
129:
130: void
131: argmatch_invalid (const char *context, const char *value, ptrdiff_t problem)
132: {
133: char const *format = (problem == -1
134: ? _("invalid argument %s for %s")
135: : _("ambiguous argument %s for %s"));
136:
137: error (0, 0, format, quotearg_n_style (0, ARGMATCH_QUOTING_STYLE, value),
138: quote_n (1, context));
139: }
140:
141:
142:
143:
144:
145: void
146: argmatch_valid (const char *const *arglist,
147: const char *vallist, size_t valsize)
148: {
149: size_t i;
150: const char *last_val = NULL;
151:
152:
153:
154: fprintf (stderr, _("Valid arguments are:"));
155: for (i = 0; arglist[i]; i++)
156: if ((i == 0)
157: || memcmp (last_val, vallist + valsize * i, valsize))
158: {
159: fprintf (stderr, "\n - `%s'", arglist[i]);
160: last_val = vallist + valsize * i;
161: }
162: else
163: {
164: fprintf (stderr, ", `%s'", arglist[i]);
165: }
166: putc ('\n', stderr);
167: }
168:
169:
170:
171:
172:
173:
174:
175: ptrdiff_t
176: __xargmatch_internal (const char *context,
177: const char *arg, const char *const *arglist,
178: const char *vallist, size_t valsize,
179: argmatch_exit_fn exit_fn)
180: {
181: ptrdiff_t res = argmatch (arg, arglist, vallist, valsize);
182: if (res >= 0)
183:
184: return res;
185:
186:
187: argmatch_invalid (context, arg, res);
188: argmatch_valid (arglist, vallist, valsize);
189: (*exit_fn) ();
190:
191: return -1;
192: }
193:
194:
195:
196: const char *
197: argmatch_to_argument (const char *value,
198: const char *const *arglist,
199: const char *vallist, size_t valsize)
200: {
201: size_t i;
202:
203: for (i = 0; arglist[i]; i++)
204: if (!memcmp (value, vallist + valsize * i, valsize))
205: return arglist[i];
206: return NULL;
207: }
208:
209: #ifdef TEST
210:
211:
212:
213: char *program_name;
214:
215:
216: enum backup_type
217: {
218:
219: no_backups,
220:
221:
222: simple_backups,
223:
224:
225:
226: numbered_existing_backups,
227:
228:
229: numbered_backups
230: };
231:
232:
233:
234: static const char *const backup_args[] =
235: {
236: "no", "none", "off",
237: "simple", "never",
238: "existing", "nil",
239: "numbered", "t",
240: 0
241: };
242:
243: static const enum backup_type backup_vals[] =
244: {
245: no_backups, no_backups, no_backups,
246: simple_backups, simple_backups,
247: numbered_existing_backups, numbered_existing_backups,
248: numbered_backups, numbered_backups
249: };
250:
251: int
252: main (int argc, const char *const *argv)
253: {
254: const char *cp;
255: enum backup_type backup_type = no_backups;
256:
257: program_name = (char *) argv[0];
258:
259: if (argc > 2)
260: {
261: fprintf (stderr, "Usage: %s [VERSION_CONTROL]\n", program_name);
262: exit (1);
263: }
264:
265: if ((cp = getenv ("VERSION_CONTROL")))
266: backup_type = XARGMATCH ("$VERSION_CONTROL", cp,
267: backup_args, backup_vals);
268:
269: if (argc == 2)
270: backup_type = XARGMATCH (program_name, argv[1],
271: backup_args, backup_vals);
272:
273: printf ("The version control is `%s'\n",
274: ARGMATCH_TO_ARGUMENT (backup_type, backup_args, backup_vals));
275:
276: return 0;
277: }
278: #endif