diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-08-04 16:23:42 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-08-04 16:33:23 +0200 |
commit | 727948e585cb133c32c8d42570e5524c58190307 (patch) | |
tree | f2beb48ded47f9d8ebef707516e7bbb00335b1a8 | |
parent | 7f9d62d7f5b67b6b1cc7e0b94826ba2a6e193586 (diff) | |
download | busybox-w32-727948e585cb133c32c8d42570e5524c58190307.tar.gz busybox-w32-727948e585cb133c32c8d42570e5524c58190307.tar.bz2 busybox-w32-727948e585cb133c32c8d42570e5524c58190307.zip |
getopt32: factor out code to treat all args as options
Working towards making getopt32() xmalloc-free
function old new delta
make_all_argv_opts - 58 +58
top_main 914 912 -2
getopt32 1517 1458 -59
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 0/2 up/down: 58/-61) Total: -3 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | include/libbb.h | 4 | ||||
-rw-r--r-- | libbb/Kbuild.src | 1 | ||||
-rw-r--r-- | libbb/getopt32.c | 31 | ||||
-rw-r--r-- | libbb/getopt_allopts.c | 27 | ||||
-rw-r--r-- | procps/ps.c | 5 | ||||
-rw-r--r-- | procps/top.c | 5 |
6 files changed, 41 insertions, 32 deletions
diff --git a/include/libbb.h b/include/libbb.h index 46180c5aa..bb27c59a1 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1183,7 +1183,9 @@ extern const char *opt_complementary; | |||
1183 | extern const char *applet_long_options; | 1183 | extern const char *applet_long_options; |
1184 | #endif | 1184 | #endif |
1185 | extern uint32_t option_mask32; | 1185 | extern uint32_t option_mask32; |
1186 | extern uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; | 1186 | uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; |
1187 | /* For top, ps. Some argv[i] are replaced by malloced "-opt" strings */ | ||
1188 | void make_all_argv_opts(char **argv) FAST_FUNC; | ||
1187 | /* BSD-derived getopt() functions require that optind be set to 1 in | 1189 | /* BSD-derived getopt() functions require that optind be set to 1 in |
1188 | * order to reset getopt() state. This used to be generally accepted | 1190 | * order to reset getopt() state. This used to be generally accepted |
1189 | * way of resetting getopt(). However, glibc's getopt() | 1191 | * way of resetting getopt(). However, glibc's getopt() |
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 458973f17..73201a6bd 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -40,7 +40,6 @@ lib-y += full_write.o | |||
40 | lib-y += get_console.o | 40 | lib-y += get_console.o |
41 | lib-y += get_last_path_component.o | 41 | lib-y += get_last_path_component.o |
42 | lib-y += get_line_from_file.o | 42 | lib-y += get_line_from_file.o |
43 | lib-y += getopt32.o | ||
44 | lib-y += getpty.o | 43 | lib-y += getpty.o |
45 | lib-y += get_volsize.o | 44 | lib-y += get_volsize.o |
46 | lib-y += herror_msg.o | 45 | lib-y += herror_msg.o |
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 80f4cc060..129840cea 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -6,12 +6,13 @@ | |||
6 | * | 6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
8 | */ | 8 | */ |
9 | |||
10 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG | 9 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG |
11 | # include <getopt.h> | 10 | # include <getopt.h> |
12 | #endif | 11 | #endif |
13 | #include "libbb.h" | 12 | #include "libbb.h" |
14 | 13 | ||
14 | //kbuild:lib-y += getopt32.o | ||
15 | |||
15 | /* Documentation | 16 | /* Documentation |
16 | 17 | ||
17 | uint32_t | 18 | uint32_t |
@@ -170,21 +171,6 @@ const char *opt_complementary | |||
170 | 171 | ||
171 | Special characters: | 172 | Special characters: |
172 | 173 | ||
173 | "-" A group consisting of just a dash forces all arguments | ||
174 | to be treated as options, even if they have no leading dashes. | ||
175 | Next char in this case can't be a digit (0-9), use ':' or end of line. | ||
176 | Example: | ||
177 | |||
178 | opt_complementary = "-:w-x:x-w"; // "-w-x:x-w" would also work, | ||
179 | getopt32(argv, "wx"); // but is less readable | ||
180 | |||
181 | This makes it possible to use options without a dash (./program w x) | ||
182 | as well as with a dash (./program -x). | ||
183 | |||
184 | NB: getopt32() will leak a small amount of memory if you use | ||
185 | this option! Do not use it if there is a possibility of recursive | ||
186 | getopt32() calls. | ||
187 | |||
188 | "--" A double dash at the beginning of opt_complementary means the | 174 | "--" A double dash at the beginning of opt_complementary means the |
189 | argv[1] string should always be treated as options, even if it isn't | 175 | argv[1] string should always be treated as options, even if it isn't |
190 | prefixed with a "-". This is useful for special syntax in applets | 176 | prefixed with a "-". This is useful for special syntax in applets |
@@ -373,8 +359,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
373 | int max_arg = -1; | 359 | int max_arg = -1; |
374 | 360 | ||
375 | #define SHOW_USAGE_IF_ERROR 1 | 361 | #define SHOW_USAGE_IF_ERROR 1 |
376 | #define ALL_ARGV_IS_OPTS 2 | 362 | #define FIRST_ARGV_IS_OPT 2 |
377 | #define FIRST_ARGV_IS_OPT 4 | ||
378 | 363 | ||
379 | int spec_flgs = 0; | 364 | int spec_flgs = 0; |
380 | 365 | ||
@@ -486,8 +471,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
486 | if (c == '-') { | 471 | if (c == '-') { |
487 | spec_flgs |= FIRST_ARGV_IS_OPT; | 472 | spec_flgs |= FIRST_ARGV_IS_OPT; |
488 | s++; | 473 | s++; |
489 | } else | 474 | } |
490 | spec_flgs |= ALL_ARGV_IS_OPTS; | ||
491 | } else { | 475 | } else { |
492 | min_arg = c - '0'; | 476 | min_arg = c - '0'; |
493 | s++; | 477 | s++; |
@@ -551,9 +535,9 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
551 | opt_complementary = NULL; | 535 | opt_complementary = NULL; |
552 | va_end(p); | 536 | va_end(p); |
553 | 537 | ||
554 | if (spec_flgs & (FIRST_ARGV_IS_OPT | ALL_ARGV_IS_OPTS)) { | 538 | if (spec_flgs & FIRST_ARGV_IS_OPT) { |
555 | pargv = argv + 1; | 539 | pargv = argv + 1; |
556 | while (*pargv) { | 540 | if (*pargv) { |
557 | if (pargv[0][0] != '-' && pargv[0][0] != '\0') { | 541 | if (pargv[0][0] != '-' && pargv[0][0] != '\0') { |
558 | /* Can't use alloca: opts with params will | 542 | /* Can't use alloca: opts with params will |
559 | * return pointers to stack! | 543 | * return pointers to stack! |
@@ -563,9 +547,6 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
563 | strcpy(pp + 1, *pargv); | 547 | strcpy(pp + 1, *pargv); |
564 | *pargv = pp; | 548 | *pargv = pp; |
565 | } | 549 | } |
566 | if (!(spec_flgs & ALL_ARGV_IS_OPTS)) | ||
567 | break; | ||
568 | pargv++; | ||
569 | } | 550 | } |
570 | } | 551 | } |
571 | 552 | ||
diff --git a/libbb/getopt_allopts.c b/libbb/getopt_allopts.c new file mode 100644 index 000000000..a67d2b70e --- /dev/null +++ b/libbb/getopt_allopts.c | |||
@@ -0,0 +1,27 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Copyright (C) 2017 Denys Vlasenko | ||
4 | * | ||
5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
6 | */ | ||
7 | #include "libbb.h" | ||
8 | |||
9 | //kbuild:lib-y += getopt_allopts.o | ||
10 | |||
11 | void FAST_FUNC make_all_argv_opts(char **argv) | ||
12 | { | ||
13 | /* Note: we skip argv[0] */ | ||
14 | while (*++argv) { | ||
15 | char *p; | ||
16 | |||
17 | if (argv[0][0] == '-') | ||
18 | continue; | ||
19 | /* Neither top nor ps care if "" arg turns into "-" */ | ||
20 | /*if (argv[0][0] == '\0') | ||
21 | continue;*/ | ||
22 | p = xmalloc(strlen(*argv) + 2); | ||
23 | *p = '-'; | ||
24 | strcpy(p + 1, *argv); | ||
25 | *argv = p; | ||
26 | } | ||
27 | } | ||
diff --git a/procps/ps.c b/procps/ps.c index eb1946d27..081479b33 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -715,7 +715,8 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
715 | # if ENABLE_FEATURE_PS_WIDE | 715 | # if ENABLE_FEATURE_PS_WIDE |
716 | /* -w is a bit complicated */ | 716 | /* -w is a bit complicated */ |
717 | int w_count = 0; | 717 | int w_count = 0; |
718 | opt_complementary = "-:ww"; | 718 | make_all_argv_opts(argv); |
719 | opt_complementary = "ww"; | ||
719 | opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l") | 720 | opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l") |
720 | "w", &w_count); | 721 | "w", &w_count); |
721 | /* if w is given once, GNU ps sets the width to 132, | 722 | /* if w is given once, GNU ps sets the width to 132, |
@@ -731,7 +732,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
731 | } | 732 | } |
732 | # else | 733 | # else |
733 | /* -w is not supported, only -Z and/or -T */ | 734 | /* -w is not supported, only -Z and/or -T */ |
734 | opt_complementary = "-"; | 735 | make_all_argv_opts(argv); |
735 | opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l")); | 736 | opts = getopt32(argv, IF_SELINUX("Z")IF_FEATURE_SHOW_THREADS("T")IF_FEATURE_PS_LONG("l")); |
736 | # endif | 737 | # endif |
737 | 738 | ||
diff --git a/procps/top.c b/procps/top.c index 015d1ab74..1bc432fc9 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -1110,15 +1110,14 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1110 | #endif | 1110 | #endif |
1111 | 1111 | ||
1112 | /* all args are options; -n NUM */ | 1112 | /* all args are options; -n NUM */ |
1113 | opt_complementary = "-"; /* options can be specified w/o dash */ | 1113 | make_all_argv_opts(argv); /* options can be specified w/o dash */ |
1114 | col = getopt32(argv, "d:n:b"IF_FEATURE_TOPMEM("m"), &str_interval, &str_iterations); | 1114 | col = getopt32(argv, "d:n:b"IF_FEATURE_TOPMEM("m"), &str_interval, &str_iterations); |
1115 | #if ENABLE_FEATURE_TOPMEM | 1115 | #if ENABLE_FEATURE_TOPMEM |
1116 | if (col & OPT_m) /* -m (busybox specific) */ | 1116 | if (col & OPT_m) /* -m (busybox specific) */ |
1117 | scan_mask = TOPMEM_MASK; | 1117 | scan_mask = TOPMEM_MASK; |
1118 | #endif | 1118 | #endif |
1119 | if (col & OPT_d) { | 1119 | if (col & OPT_d) { |
1120 | /* work around for "-d 1" -> "-d -1" done by getopt32 | 1120 | /* work around for "-d 1" -> "-d -1" done by make_all_argv_opts() */ |
1121 | * (opt_complementary == "-" does this) */ | ||
1122 | if (str_interval[0] == '-') | 1121 | if (str_interval[0] == '-') |
1123 | str_interval++; | 1122 | str_interval++; |
1124 | /* Need to limit it to not overflow poll timeout */ | 1123 | /* Need to limit it to not overflow poll timeout */ |