Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
mxq
Public
Notifications
You must be signed in to change notification settings
Fork
3
Star
3
Code
Issues
20
Pull requests
3
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
b636630
helper
manpages
mysql
web
.gitignore
.vimrc
Doxyfile
LICENSE
Makefile
README.md
keywordset.c
keywordset.h
mx_flock.c
mx_flock.h
mx_getopt.c
mx_getopt.h
mx_log.c
mx_log.h
mx_mysql.c
mx_mysql.h
mx_proc.c
mx_proc.h
mx_util.c
mx_util.h
mxq.h
mxq_daemon.c
mxq_daemon.h
mxq_group.c
mxq_group.h
mxq_job.c
mxq_job.h
mxq_log.c
mxq_reaper.c
mxqadmin.c
mxqd.c
mxqd.h
mxqd_control.c
mxqd_control.h
mxqdctl-hostconfig.sh
mxqdump.c
mxqkill.c
mxqps.c
mxqset.c
mxqsub.c
os-release
parser.y
ppidcache.c
ppidcache.h
test_keywordset.c
test_mx_log.c
test_mx_mysql.c
test_mx_util.c
test_mxqd_control.c
test_parser.c
xmalloc.h
Breadcrumbs
mxq
/
mx_getopt.c
Blame
Blame
Latest commit
History
History
452 lines (340 loc) · 12.4 KB
Breadcrumbs
mxq
/
mx_getopt.c
Top
File metadata and controls
Code
Blame
452 lines (340 loc) · 12.4 KB
Raw
/* ** beegetopt - parse options ** ** Copyright (C) 2009-2012 ** Marius Tolzmann <tolzmann@molgen.mpg.de> ** and other bee developers ** ** This file is part of bee. ** ** bee is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, see <http://www.gnu.org/licenses/>. */ /* what we do support: --r=256 long = "r" value = "256" --r 256 long = "r" value = "256" -r=255 short = 'r' value = "=255" -r255 short = 'r' value = "255" -r 255 short = 'r' value = "255" what we do not support -help long = "help" */ #define _GNU_SOURCE #include <errno.h> #include <stdio.h> #include <string.h> #include <assert.h> #include "mx_getopt.h" int mx_getopt_init(struct mx_getopt_ctl *ctl, int argc, char **argv, struct mx_option *optv) { int err = 0; ctl->optind = 0; ctl->optarg = NULL; ctl->argc = argc; ctl->argv = argv; ctl->program = program_invocation_short_name; /* for (i=0; i < argc; i++) { printf("XXX argv[%d] = %s\n", i, argv[i]); } */ ctl->options = optv; for(ctl->_optcnt=0; optv[ctl->_optcnt].long_opt || optv[ctl->_optcnt].short_opt; ctl->_optcnt++) { if(optv[ctl->_optcnt].long_opt) optv[ctl->_optcnt]._long_len = strlen(optv[ctl->_optcnt].long_opt); if(optv[ctl->_optcnt].value < 0 && optv[ctl->_optcnt].value != MX_GETOPT_NOVALUE) { fprintf(stderr, "*** mx_getopt_init() ERROR: negative value (%d) set for opt %d (long: %s, short: %c)\n", ctl->_optcnt, optv[ctl->_optcnt].value, optv[ctl->_optcnt].long_opt, optv[ctl->_optcnt].short_opt); err++; } } ctl->_argc = argc; ctl->_unhandled_shortopts = NULL; ctl->flags = 0; return err?0:1; } static int find_long_option_by_name(struct mx_option *options, char *name, char **optarg) { int i = 0; for(i=0; options[i].long_opt || options[i].short_opt; i++) { /* skip short-only-opts */ if(!options[i].long_opt) continue; /* check if option starts with full long-name */ if(strncmp(name, options[i].long_opt, options[i]._long_len) != 0) continue; /* if --long-name matches completely we are done */ if(name[options[i]._long_len] == '\0') return i; /* skip option candidates without allowed argument */ if (!options[i].optional_args && !options[i].required_args) continue; /* if --long-name= is not specified we don't have a full match at all */ if(name[options[i]._long_len] != '=') continue; /* we matched --long-name= so set optarg and return success */ if (optarg) *optarg = &(name[options[i]._long_len+1]); return i; } /* not match found */ return MX_GETOPT_OPTUNKNOWN; } static int find_short_option(struct mx_option *options, char **name, char **optarg) { char short_opt; int i; int idx; short_opt = *name[0]; assert(short_opt); if (optarg) *optarg = NULL; for (i=0, idx=-1; options[i].long_opt || options[i].short_opt; i++) { /* skip long-only-opts */ if (!options[i].short_opt) continue; if (options[i].short_opt == short_opt) idx = i; } /* return error if option was not found */ if (idx == -1) { /* reset unhandled options */ *name = NULL; return MX_GETOPT_OPTUNKNOWN; } /* skip this short option */ (*name)++; if (!*name[0]) *name = NULL; /* set optarg if option takes arguments and short_opt is not the last char */ if (*name && (options[idx].required_args || options[idx].optional_args)) { *optarg = *name; *name = NULL; } return idx; } static int find_long_option_by_subname(struct mx_option *options, char *name, char **optarg) { int i; int l; char *s; int idx; l = strlen(name); s = strchr(name, '='); if (l < 1) return -2; for (i=0, idx=-1; options[i].long_opt || options[i].short_opt; i++) { /* skip short-only-opts */ if (!options[i].long_opt) continue; if (strncmp(name, options[i].long_opt, l) != 0) { /* skip if search string has no optarg */ if(!s) continue; /* skip option candidates without allowed argument */ if (!options[i].optional_args && !options[i].required_args) continue; /* skip if string without optarg does not match */ if (strncmp(name, options[i].long_opt, s - name) != 0) continue; } if (idx >= 0) { if (options[i].value != options[idx].value) return MX_GETOPT_AMBIGUOUS; } else { idx = i; } } /* return error if option was not found */ if (idx == -1) return MX_GETOPT_OPTUNKNOWN; /* set optarg if assigned */ if (s && optarg) *optarg = s+1; return idx; } static int handle_option(struct mx_getopt_ctl *ctl, const int index) { struct mx_option *o = &(ctl->options[index]); int argc; ctl->optargc = 0; /* skip the option */ if (!ctl->_unhandled_shortopts) ctl->optind++; if (o->required_args) { /* we don't check required args for possible option matches */ /* argument is required - optarg already set? */ if (!ctl->optarg) { /* no optarg and no more arguments -> required argument missing */ if (ctl->optind == ctl->_argc) return (o->required_args == 1)?MX_GETOPT_NOARG:MX_GETOPT_NOARGS; /* set optarg to this argument and skip it */ ctl->optarg = ctl->argv[ctl->optind++]; } /* if only one argument is required we can return here */ if (o->required_args == 1) return o->value; /* more arguments are required .. check if they are available */ argc = o->required_args-1; if (ctl->optind+argc > ctl->_argc) { /* on error: set optargc to number of args available */ ctl->optargc = ctl->optind - ctl->_argc; return MX_GETOPT_NOARGS; } /* all required args are available */ /* first req argument is optarg */ /* all other required arguments are in ctl->optargv[0 .. ctl->optargc-1] */ ctl->optargc = argc; ctl->optargv = &(ctl->argv[ctl->optind]); /* skip all required args */ ctl->optind += argc; } if (o->optional_args) { /* optional arguments may not start with '-' */ if (!o->required_args) { /* only optional arguments - set optarg if not set */ if (!ctl->optarg) { /* no optarg and no more arguments -> done without optional argument */ if (ctl->optind == ctl->_argc) return o->value; /* we are done if this argument looks like an option */ if (ctl->argv[ctl->optind][0] == '-') return o->value; /* set optarg to this argument and skip it */ ctl->optarg = ctl->argv[ctl->optind++]; } /* if only one optional argument is allowed we can return here */ if (o->optional_args == 1) return o->value; } for (argc = 0; argc < o->optional_args-((o->required_args)?0:1) && ctl->optind < ctl->_argc; argc++) { /* stop on potential option */ if (ctl->argv[ctl->optind][0] == '-') return o->value; ctl->optargc++; ctl->optind++; } } return o->value; } void mx_getopt_pop_current_argument(struct mx_getopt_ctl *optctl) { int i; optctl->argv[optctl->argc] = optctl->argv[optctl->optind]; // fprintf(stderr, "popping %d %s\n", optctl->optind, optctl->argv[optctl->optind]); for(i=optctl->optind; i < optctl->argc; i++) { optctl->argv[i] = optctl->argv[i+1]; } optctl->argv[optctl->argc] = NULL; optctl->_argc--; } static void mx_getopt_pop_all_arguments(struct mx_getopt_ctl *optctl) { while(optctl->optind < optctl->_argc) mx_getopt_pop_current_argument(optctl); } static int _mx_getopt_long(struct mx_getopt_ctl *optctl, int *optindex) { int this; short maybe_option = 0; short maybe_long = 0; char *name; int idx; if(optctl->optind == optctl->_argc) return MX_GETOPT_END; assert(optctl->optind < optctl->_argc); this = optctl->optind; /* "-" is not considered an option but an argument => maybe_option = false */ /* "--" will be processed later */ maybe_option = (optctl->argv[this][0] == '-' && optctl->argv[this][1]); maybe_long = maybe_option && (optctl->argv[this][1] == '-'); name = &(optctl->argv[this][maybe_option+maybe_long]); optctl->optarg = NULL; *optindex = -1; /* not an option: pop argument */ if(!maybe_option) { mx_getopt_pop_current_argument(optctl); return MX_GETOPT_NOOPT; } /* match & skip '--' and pop all remaining arguments */ if(maybe_long && (optctl->argv[this][2] == '\0')) { if(!(optctl->flags & MX_FLAG_KEEPOPTIONEND)) optctl->optind++; mx_getopt_pop_all_arguments(optctl); return MX_GETOPT_END; } /* match long option */ if (maybe_long) { idx = find_long_option_by_name(optctl->options, name, &optctl->optarg); if (idx < 0) idx = find_long_option_by_subname(optctl->options, name, &optctl->optarg); if (idx < 0) return idx; *optindex = idx; return handle_option(optctl, idx); } /* match short option */ if (!optctl->_unhandled_shortopts) optctl->_unhandled_shortopts = name; idx = find_short_option(optctl->options, &optctl->_unhandled_shortopts, &optctl->optarg); if (idx < 0) return idx; *optindex = idx; return handle_option(optctl, idx); } int mx_getopt(struct mx_getopt_ctl *optctl, int *optindex) { int opt; while((opt = _mx_getopt_long(optctl, optindex)) != MX_GETOPT_END) { switch(opt) { case MX_GETOPT_NOVALUE: return MX_GETOPT_NOVALUE; case MX_GETOPT_NOOPT: if (optctl->flags & MX_FLAG_STOPONNOOPT) { mx_getopt_pop_all_arguments(optctl); return MX_GETOPT_END; } break; case MX_GETOPT_AMBIGUOUS: if (optctl->program) fprintf(stderr, "%s: ", optctl->program); fprintf(stderr, "option '%s' is ambiguous.\n", optctl->argv[optctl->optind]); return MX_GETOPT_ERROR; case MX_GETOPT_OPTUNKNOWN: if (optctl->flags & MX_FLAG_STOPONUNKNOWN) { mx_getopt_pop_all_arguments(optctl); return MX_GETOPT_END; } if (!(optctl->flags & MX_FLAG_SKIPUNKNOWN)) { if (optctl->program) fprintf(stderr, "%s: ", optctl->program); fprintf(stderr, "unrecognized option '%s'.\n", optctl->argv[optctl->optind]); return MX_GETOPT_ERROR; } mx_getopt_pop_current_argument(optctl); break; case MX_GETOPT_NOARG: case MX_GETOPT_NOARGS: if (optctl->program) fprintf(stderr, "%s: ", optctl->program); if (optctl->options[*optindex].long_opt) fprintf(stderr, "option '--%s' requires an argument.\n", optctl->options[*optindex].long_opt); else fprintf(stderr, "option '-%c' requires an argument.\n", optctl->options[*optindex].short_opt); return MX_GETOPT_ERROR; default: assert(opt >= 0); return opt; } } return opt; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
You can’t perform that action at this time.