Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(972)

Side by Side Diff: third_party/grpc/src/core/support/cmdline.c

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright 2015, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34 #include <grpc/support/cmdline.h>
35
36 #include <limits.h>
37 #include <stdio.h>
38 #include <string.h>
39
40 #include "src/core/support/string.h"
41 #include <grpc/support/alloc.h>
42 #include <grpc/support/log.h>
43 #include <grpc/support/string_util.h>
44
45 typedef enum { ARGTYPE_INT, ARGTYPE_BOOL, ARGTYPE_STRING } argtype;
46
47 typedef struct arg {
48 const char *name;
49 const char *help;
50 argtype type;
51 void *value;
52 struct arg *next;
53 } arg;
54
55 struct gpr_cmdline {
56 const char *description;
57 arg *args;
58 const char *argv0;
59
60 const char *extra_arg_name;
61 const char *extra_arg_help;
62 void (*extra_arg)(void *user_data, const char *arg);
63 void *extra_arg_user_data;
64
65 int (*state)(gpr_cmdline *cl, char *arg);
66 arg *cur_arg;
67
68 int survive_failure;
69 };
70
71 static int normal_state(gpr_cmdline *cl, char *arg);
72
73 gpr_cmdline *gpr_cmdline_create(const char *description) {
74 gpr_cmdline *cl = gpr_malloc(sizeof(gpr_cmdline));
75 memset(cl, 0, sizeof(gpr_cmdline));
76
77 cl->description = description;
78 cl->state = normal_state;
79
80 return cl;
81 }
82
83 void gpr_cmdline_set_survive_failure(gpr_cmdline *cl) {
84 cl->survive_failure = 1;
85 }
86
87 void gpr_cmdline_destroy(gpr_cmdline *cl) {
88 while (cl->args) {
89 arg *a = cl->args;
90 cl->args = a->next;
91 gpr_free(a);
92 }
93 gpr_free(cl);
94 }
95
96 static void add_arg(gpr_cmdline *cl, const char *name, const char *help,
97 argtype type, void *value) {
98 arg *a;
99
100 for (a = cl->args; a; a = a->next) {
101 GPR_ASSERT(0 != strcmp(a->name, name));
102 }
103
104 a = gpr_malloc(sizeof(arg));
105 memset(a, 0, sizeof(arg));
106 a->name = name;
107 a->help = help;
108 a->type = type;
109 a->value = value;
110 a->next = cl->args;
111 cl->args = a;
112 }
113
114 void gpr_cmdline_add_int(gpr_cmdline *cl, const char *name, const char *help,
115 int *value) {
116 add_arg(cl, name, help, ARGTYPE_INT, value);
117 }
118
119 void gpr_cmdline_add_flag(gpr_cmdline *cl, const char *name, const char *help,
120 int *value) {
121 add_arg(cl, name, help, ARGTYPE_BOOL, value);
122 }
123
124 void gpr_cmdline_add_string(gpr_cmdline *cl, const char *name, const char *help,
125 char **value) {
126 add_arg(cl, name, help, ARGTYPE_STRING, value);
127 }
128
129 void gpr_cmdline_on_extra_arg(
130 gpr_cmdline *cl, const char *name, const char *help,
131 void (*on_extra_arg)(void *user_data, const char *arg), void *user_data) {
132 GPR_ASSERT(!cl->extra_arg);
133 GPR_ASSERT(on_extra_arg);
134
135 cl->extra_arg = on_extra_arg;
136 cl->extra_arg_user_data = user_data;
137 cl->extra_arg_name = name;
138 cl->extra_arg_help = help;
139 }
140
141 /* recursively descend argument list, adding the last element
142 to s first - so that arguments are added in the order they were
143 added to the list by api calls */
144 static void add_args_to_usage(gpr_strvec *s, arg *a) {
145 char *tmp;
146
147 if (!a) return;
148 add_args_to_usage(s, a->next);
149
150 switch (a->type) {
151 case ARGTYPE_BOOL:
152 gpr_asprintf(&tmp, " [--%s|--no-%s]", a->name, a->name);
153 gpr_strvec_add(s, tmp);
154 break;
155 case ARGTYPE_STRING:
156 gpr_asprintf(&tmp, " [--%s=string]", a->name);
157 gpr_strvec_add(s, tmp);
158 break;
159 case ARGTYPE_INT:
160 gpr_asprintf(&tmp, " [--%s=int]", a->name);
161 gpr_strvec_add(s, tmp);
162 break;
163 }
164 }
165
166 char *gpr_cmdline_usage_string(gpr_cmdline *cl, const char *argv0) {
167 /* TODO(ctiller): make this prettier */
168 gpr_strvec s;
169 char *tmp;
170 const char *name = strrchr(argv0, '/');
171
172 if (name) {
173 name++;
174 } else {
175 name = argv0;
176 }
177
178 gpr_strvec_init(&s);
179
180 gpr_asprintf(&tmp, "Usage: %s", name);
181 gpr_strvec_add(&s, tmp);
182 add_args_to_usage(&s, cl->args);
183 if (cl->extra_arg) {
184 gpr_asprintf(&tmp, " [%s...]", cl->extra_arg_name);
185 gpr_strvec_add(&s, tmp);
186 }
187 gpr_strvec_add(&s, gpr_strdup("\n"));
188
189 tmp = gpr_strvec_flatten(&s, NULL);
190 gpr_strvec_destroy(&s);
191 return tmp;
192 }
193
194 static int print_usage_and_die(gpr_cmdline *cl) {
195 char *usage = gpr_cmdline_usage_string(cl, cl->argv0);
196 fprintf(stderr, "%s", usage);
197 gpr_free(usage);
198 if (!cl->survive_failure) {
199 exit(1);
200 }
201 return 0;
202 }
203
204 static int extra_state(gpr_cmdline *cl, char *str) {
205 if (!cl->extra_arg) {
206 return print_usage_and_die(cl);
207 }
208 cl->extra_arg(cl->extra_arg_user_data, str);
209 return 1;
210 }
211
212 static arg *find_arg(gpr_cmdline *cl, char *name) {
213 arg *a;
214
215 for (a = cl->args; a; a = a->next) {
216 if (0 == strcmp(a->name, name)) {
217 break;
218 }
219 }
220
221 if (!a) {
222 fprintf(stderr, "Unknown argument: %s\n", name);
223 return NULL;
224 }
225
226 return a;
227 }
228
229 static int value_state(gpr_cmdline *cl, char *str) {
230 long intval;
231 char *end;
232
233 GPR_ASSERT(cl->cur_arg);
234
235 switch (cl->cur_arg->type) {
236 case ARGTYPE_INT:
237 intval = strtol(str, &end, 0);
238 if (*end || intval < INT_MIN || intval > INT_MAX) {
239 fprintf(stderr, "expected integer, got '%s' for %s\n", str,
240 cl->cur_arg->name);
241 return print_usage_and_die(cl);
242 }
243 *(int *)cl->cur_arg->value = (int)intval;
244 break;
245 case ARGTYPE_BOOL:
246 if (0 == strcmp(str, "1") || 0 == strcmp(str, "true")) {
247 *(int *)cl->cur_arg->value = 1;
248 } else if (0 == strcmp(str, "0") || 0 == strcmp(str, "false")) {
249 *(int *)cl->cur_arg->value = 0;
250 } else {
251 fprintf(stderr, "expected boolean, got '%s' for %s\n", str,
252 cl->cur_arg->name);
253 return print_usage_and_die(cl);
254 }
255 break;
256 case ARGTYPE_STRING:
257 *(char **)cl->cur_arg->value = str;
258 break;
259 }
260
261 cl->state = normal_state;
262 return 1;
263 }
264
265 static int normal_state(gpr_cmdline *cl, char *str) {
266 char *eq = NULL;
267 char *tmp = NULL;
268 char *arg_name = NULL;
269 int r = 1;
270
271 if (0 == strcmp(str, "-help") || 0 == strcmp(str, "--help") ||
272 0 == strcmp(str, "-h")) {
273 return print_usage_and_die(cl);
274 }
275
276 cl->cur_arg = NULL;
277
278 if (str[0] == '-') {
279 if (str[1] == '-') {
280 if (str[2] == 0) {
281 /* handle '--' to move to just extra args */
282 cl->state = extra_state;
283 return 1;
284 }
285 str += 2;
286 } else {
287 str += 1;
288 }
289 /* first byte of str is now past the leading '-' or '--' */
290 if (str[0] == 'n' && str[1] == 'o' && str[2] == '-') {
291 /* str is of the form '--no-foo' - it's a flag disable */
292 str += 3;
293 cl->cur_arg = find_arg(cl, str);
294 if (cl->cur_arg == NULL) {
295 return print_usage_and_die(cl);
296 }
297 if (cl->cur_arg->type != ARGTYPE_BOOL) {
298 fprintf(stderr, "%s is not a flag argument\n", str);
299 return print_usage_and_die(cl);
300 }
301 *(int *)cl->cur_arg->value = 0;
302 return 1; /* early out */
303 }
304 eq = strchr(str, '=');
305 if (eq != NULL) {
306 /* copy the string into a temp buffer and extract the name */
307 tmp = arg_name = gpr_malloc((size_t)(eq - str + 1));
308 memcpy(arg_name, str, (size_t)(eq - str));
309 arg_name[eq - str] = 0;
310 } else {
311 arg_name = str;
312 }
313 cl->cur_arg = find_arg(cl, arg_name);
314 if (cl->cur_arg == NULL) {
315 return print_usage_and_die(cl);
316 }
317 if (eq != NULL) {
318 /* str was of the type --foo=value, parse the value */
319 r = value_state(cl, eq + 1);
320 } else if (cl->cur_arg->type != ARGTYPE_BOOL) {
321 /* flag types don't have a '--foo value' variant, other types do */
322 cl->state = value_state;
323 } else {
324 /* flag parameter: just set the value */
325 *(int *)cl->cur_arg->value = 1;
326 }
327 } else {
328 r = extra_state(cl, str);
329 }
330
331 gpr_free(tmp);
332 return r;
333 }
334
335 int gpr_cmdline_parse(gpr_cmdline *cl, int argc, char **argv) {
336 int i;
337
338 GPR_ASSERT(argc >= 1);
339 cl->argv0 = argv[0];
340
341 for (i = 1; i < argc; i++) {
342 if (!cl->state(cl, argv[i])) {
343 return 0;
344 }
345 }
346 return 1;
347 }
OLDNEW
« no previous file with comments | « third_party/grpc/src/core/support/block_annotate.h ('k') | third_party/grpc/src/core/support/cpu_iphone.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698