diff options
author | 2018-03-08 17:39:22 -0800 | |
---|---|---|
committer | 2018-03-08 17:39:22 -0800 | |
commit | 697ade6190b23c80e7f60963983786e679759393 (patch) | |
tree | dd9782d1e936b8342163b26795e23571d4b1b415 /src/framework/common/base/liblinuxapi/nsfw_getopt.c | |
parent | 71a4e2f34afa8018426f0e830050e50a1de6d375 (diff) |
dmm initial commit
Change-Id: I049ee277cf4efdb83f9c2ac439365fcd421c159b
Signed-off-by: qchang <qing.chang1@huawei.com>
Diffstat (limited to 'src/framework/common/base/liblinuxapi/nsfw_getopt.c')
-rw-r--r-- | src/framework/common/base/liblinuxapi/nsfw_getopt.c | 455 |
1 files changed, 455 insertions, 0 deletions
diff --git a/src/framework/common/base/liblinuxapi/nsfw_getopt.c b/src/framework/common/base/liblinuxapi/nsfw_getopt.c new file mode 100644 index 0000000..ac7d6bf --- /dev/null +++ b/src/framework/common/base/liblinuxapi/nsfw_getopt.c @@ -0,0 +1,455 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include "nsfw_getopt.h" +#include "nstack_log.h" + +char *nsfw_optarg = NULL; +int nsfw_optind = 1; +int nsfw_opterr = 1; +int nsfw_optopt = '?'; +NSTACK_STATIC char *nsfw_optnext = NULL; +NSTACK_STATIC int posixly_correct = -1; +NSTACK_STATIC int handle_nonopt_argv = 0; +NSTACK_STATIC int start = 0; +NSTACK_STATIC int end = 0; + +NSTACK_STATIC void check_gnu_extension (const char *optstring); +NSTACK_STATIC int nsfw_getopt_internal (int argc, char *const argv[], + const char *optstring, + const struct option *longopts, + int *longindex, int long_only); +NSTACK_STATIC int nsfw_getopt_shortopts (int argc, char *const argv[], + const char *optstring, + int long_only); +NSTACK_STATIC int nsfw_getopt_longopts (int argc, char *const argv[], + char *arg, const char *optstring, + const struct option *longopts, + int *longindex, int *long_only_flag); +NSTACK_STATIC inline int nsfw_getopt_internal_check_opts (const char + *optstring); +NSTACK_STATIC inline int nsfw_getopt_check_optind (); +NSTACK_STATIC inline int nsfw_getopt_internal_init (char *const argv[]); +NSTACK_STATIC inline int nsfw_getopt_longopts_check_longonly (int + *long_only_flag, + const char + *optstring, + char *const + argv[]); + +NSTACK_STATIC void +check_gnu_extension (const char *optstring) +{ + if (optstring[0] == '+' || getenv ("POSIXLY_CORRECT") != NULL) + { + posixly_correct = 1; + } + else + { + posixly_correct = 0; + } + if (optstring[0] == '-') + { + handle_nonopt_argv = 1; + } + else + { + handle_nonopt_argv = 0; + } +} + +int +nsfw_getopt_long (int argc, char *const argv[], const char *optstring, + const struct option *longopts, int *longindex) +{ + return nsfw_getopt_internal (argc, argv, optstring, longopts, longindex, 0); +} + +NSTACK_STATIC inline int +nsfw_getopt_internal_check_opts (const char *optstring) +{ + if (NULL == optstring) + { + return -1; + } + + if (nsfw_optopt == '?') + { + nsfw_optopt = 0; + } + + if (posixly_correct == -1) + { + check_gnu_extension (optstring); + } + + if (nsfw_optind == 0) + { + check_gnu_extension (optstring); + nsfw_optind = 1; + nsfw_optnext = NULL; + } + + switch (optstring[0]) + { + case '+': + case '-': + optstring++; + break; + default: + break; + } + return 0; +} + +NSTACK_STATIC inline int +nsfw_getopt_check_optind () +{ + if (nsfw_optind <= 0) + nsfw_optind = 1; + return 0; +} + +NSTACK_STATIC inline int +nsfw_getopt_internal_init (char *const argv[]) +{ + if (nsfw_optnext == NULL && start != 0) + { + int last_pos = nsfw_optind - 1; + + nsfw_optind -= end - start; + (void) nsfw_getopt_check_optind (); + + while (start < end--) + { + int i; + char *arg = argv[end]; + + for (i = end; i < last_pos; i++) + { + int j = i + 1; + ((char **) argv)[i] = argv[j]; + } + ((char const **) argv)[i] = arg; + last_pos--; + } + start = 0; + } + return 0; +} + +NSTACK_STATIC int +nsfw_getopt_internal (int argc, char *const argv[], const char *optstring, + const struct option *longopts, int *longindex, + int long_only) +{ + + (void) nsfw_getopt_internal_check_opts (optstring); + + (void) nsfw_getopt_internal_init (argv); + + if (nsfw_optind >= argc) + { + nsfw_optarg = NULL; + return -1; + } + if (nsfw_optnext == NULL) + { + const char *arg = argv[nsfw_optind]; + if (*arg != '-') + { + if (handle_nonopt_argv) + { + nsfw_optarg = argv[nsfw_optind++]; + start = 0; + return 1; + } + else if (posixly_correct) + { + nsfw_optarg = NULL; + return -1; + } + else + { + int i; + + start = nsfw_optind; + for (i = nsfw_optind + 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + end = i; + break; + } + } + if (i == argc) + { + nsfw_optarg = NULL; + return -1; + } + nsfw_optind = i; + arg = argv[nsfw_optind]; + } + } + if (strcmp (arg, "--") == 0) + { + nsfw_optind++; + return -1; + } + if (longopts != NULL && arg[1] == '-') + { + return nsfw_getopt_longopts (argc, argv, argv[nsfw_optind] + 2, + optstring, longopts, longindex, NULL); + } + } + + if (nsfw_optnext == NULL) + { + nsfw_optnext = argv[nsfw_optind] + 1; + } + if (long_only) + { + int long_only_flag = 0; + int rv = + nsfw_getopt_longopts (argc, argv, nsfw_optnext, optstring, longopts, + longindex, &long_only_flag); + if (!long_only_flag) + { + nsfw_optnext = NULL; + return rv; + } + } + + return nsfw_getopt_shortopts (argc, argv, optstring, long_only); +} + +NSTACK_STATIC int +nsfw_getopt_shortopts (int argc, char *const argv[], const char *optstring, + int long_only) +{ + int opt = *nsfw_optnext; + const char *os; + if (optstring != NULL) + { + os = strchr (optstring, opt); + } + else + { + /* here try to keep same with below behavior */ + return '?'; + } + + if (os == NULL) + { + nsfw_optarg = NULL; + if (long_only) + { + if (':' != optstring[0]) + { + NSFW_LOGERR ("unrecognized option] argv_0=%s, netopt=%s", + argv[0], nsfw_optnext); + } + nsfw_optind++; + nsfw_optnext = NULL; + } + else + { + nsfw_optopt = opt; + if (':' != optstring[0]) + { + NSFW_LOGERR ("invalid option] argv_0=%s, opt=%c", argv[0], opt); + } + if (*(++nsfw_optnext) == 0) + { + nsfw_optind++; + nsfw_optnext = NULL; + } + } + return '?'; + } + if (os[1] == ':') + { + if (nsfw_optnext[1] == 0) + { + nsfw_optind++; + if (os[2] == ':') + { + nsfw_optarg = NULL; + } + else + { + if (nsfw_optind == argc) + { + nsfw_optarg = NULL; + nsfw_optopt = opt; + if (':' != optstring[0]) + { + NSFW_LOGERR + ("option requires an argument] argv_0=%s, opt=%c", + argv[0], opt); + } + return optstring[0] == ':' ? ':' : '?'; + } + nsfw_optarg = argv[nsfw_optind]; + nsfw_optind++; + } + } + else + { + nsfw_optarg = nsfw_optnext + 1; + nsfw_optind++; + } + nsfw_optnext = NULL; + } + else + { + nsfw_optarg = NULL; + if (nsfw_optnext[1] == 0) + { + nsfw_optnext = NULL; + nsfw_optind++; + } + else + { + nsfw_optnext++; + } + } + return opt; +} + +NSTACK_STATIC inline int +nsfw_getopt_longopts_check_longonly (int *long_only_flag, + const char *optstring, + char *const argv[]) +{ + if (long_only_flag) + { + *long_only_flag = 1; + } + else + { + if (':' != optstring[0]) + { + NSFW_LOGERR ("unrecognized option] argv_0=%s, option=%s", argv[0], + argv[nsfw_optind]); + } + nsfw_optind++; + } + return 0; +} + +NSTACK_STATIC int +nsfw_getopt_longopts (int argc, char *const argv[], char *arg, + const char *optstring, const struct option *longopts, + int *longindex, int *long_only_flag) +{ + char *val = NULL; + const struct option *opt; + size_t namelen; + int idx; + + if ((longopts == NULL) || (arg == NULL)) + { + return -1; + } + + for (idx = 0; longopts[idx].name != NULL; idx++) + { + opt = &longopts[idx]; + namelen = strlen (opt->name); + + if (strncmp (arg, opt->name, namelen) == 0) + { + switch (arg[namelen]) + { + case '\0': + switch (opt->has_arg) + { + case nsfw_required_argument: + nsfw_optind++; + + if (nsfw_optind == argc) + { + nsfw_optarg = NULL; + nsfw_optopt = opt->val; + if (':' != optstring[0]) + { + NSFW_LOGERR + ("requires an argument] argv_0=%s, opt name=%s", + argv[0], opt->name); + } + return optstring[0] == ':' ? ':' : '?'; + } + + val = argv[nsfw_optind]; + break; + + default: + break; + } + + goto found; + + case '=': + if (opt->has_arg == nsfw_no_argument) + { + const char *hyphens = + (argv[nsfw_optind][1] == '-') ? "--" : "-"; + nsfw_optind++; + nsfw_optarg = NULL; + nsfw_optopt = opt->val; + if (':' != optstring[0]) + { + NSFW_LOGERR + ("doesn't allow an argument] argv_0=%s, hyphens=%s, opt name=%s", + argv[0], hyphens, opt->name); + } + return '?'; + } + + val = arg + namelen + 1; + goto found; + + default: + break; + } + } + } + + (void) nsfw_getopt_longopts_check_longonly (long_only_flag, optstring, + argv); + return '?'; + +found: + nsfw_optarg = val; + nsfw_optind++; + + if (opt->flag) + { + *opt->flag = opt->val; + } + + if (longindex) + { + *longindex = idx; + } + + return opt->flag ? 0 : opt->val; +} |