diff options
author | Ron Yorston <rmy@pobox.com> | 2016-04-04 16:22:54 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2016-04-04 16:22:54 +0100 |
commit | 253dbd612b2d2f041f4263e15a3b94df70f41e36 (patch) | |
tree | f6c6e12a0541233058a7f7ccb1251afeb457da06 /libbb/appletlib.c | |
parent | 3cf56a021d7a62512b477640e930e1a78288075c (diff) | |
parent | d7d4750e1e213e7448147186dddfe3bfbb47eea0 (diff) | |
download | busybox-w32-253dbd612b2d2f041f4263e15a3b94df70f41e36.tar.gz busybox-w32-253dbd612b2d2f041f4263e15a3b94df70f41e36.tar.bz2 busybox-w32-253dbd612b2d2f041f4263e15a3b94df70f41e36.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb/appletlib.c')
-rw-r--r-- | libbb/appletlib.c | 166 |
1 files changed, 140 insertions, 26 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 1d6a4b274..b71f2dd7e 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -140,32 +140,127 @@ void FAST_FUNC bb_show_usage(void) | |||
140 | xfunc_die(); | 140 | xfunc_die(); |
141 | } | 141 | } |
142 | 142 | ||
143 | #if NUM_APPLETS > 8 | ||
144 | static int applet_name_compare(const void *name, const void *idx) | ||
145 | { | ||
146 | int i = (int)(ptrdiff_t)idx - 1; | ||
147 | return strcmp(name, APPLET_NAME(i)); | ||
148 | } | ||
149 | #endif | ||
150 | int FAST_FUNC find_applet_by_name(const char *name) | 143 | int FAST_FUNC find_applet_by_name(const char *name) |
151 | { | 144 | { |
152 | #if NUM_APPLETS > 8 | 145 | unsigned i, max; |
153 | /* Do a binary search to find the applet entry given the name. */ | 146 | int j; |
154 | const char *p; | 147 | const char *p; |
155 | p = bsearch(name, (void*)(ptrdiff_t)1, ARRAY_SIZE(applet_main), 1, applet_name_compare); | 148 | |
156 | /* | 149 | /* The commented-out word-at-a-time code is ~40% faster, but +160 bytes. |
157 | * if (!p) return -1; | 150 | * "Faster" here saves ~0.5 microsecond of real time - not worth it. |
158 | * ^^^^^^^^^^^^^^^^^^ the code below will do this if p == NULL :) | 151 | */ |
159 | */ | 152 | #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ |
160 | return (int)(ptrdiff_t)p - 1; | 153 | uint32_t n32; |
154 | |||
155 | /* Handle all names < 2 chars long early */ | ||
156 | if (name[0] == '\0') | ||
157 | return -1; /* "" is not a valid applet name */ | ||
158 | if (name[1] == '\0') { | ||
159 | if (!ENABLE_TEST) | ||
160 | return -1; /* 1-char name is not valid */ | ||
161 | if (name[0] != ']') | ||
162 | return -1; /* 1-char name which isn't "[" is not valid */ | ||
163 | /* applet "[" is always applet #0: */ | ||
164 | return 0; | ||
165 | } | ||
166 | #endif | ||
167 | |||
168 | p = applet_names; | ||
169 | i = 0; | ||
170 | #if KNOWN_APPNAME_OFFSETS <= 0 | ||
171 | max = NUM_APPLETS; | ||
161 | #else | 172 | #else |
162 | /* A version which does not pull in bsearch */ | 173 | max = NUM_APPLETS * KNOWN_APPNAME_OFFSETS; |
163 | int i = 0; | 174 | for (j = ARRAY_SIZE(applet_nameofs)-1; j >= 0; j--) { |
164 | const char *p = applet_names; | 175 | const char *pp = applet_names + applet_nameofs[j]; |
165 | while (i < NUM_APPLETS) { | 176 | if (strcmp(name, pp) >= 0) { |
166 | if (strcmp(name, p) == 0) | 177 | //bb_error_msg("name:'%s' >= pp:'%s'", name, pp); |
178 | p = pp; | ||
179 | i = max - NUM_APPLETS; | ||
180 | break; | ||
181 | } | ||
182 | max -= NUM_APPLETS; | ||
183 | } | ||
184 | max /= (unsigned)KNOWN_APPNAME_OFFSETS; | ||
185 | i /= (unsigned)KNOWN_APPNAME_OFFSETS; | ||
186 | //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max); | ||
187 | #endif | ||
188 | |||
189 | /* Open-coded linear search without strcmp/strlen calls for speed */ | ||
190 | |||
191 | #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ | ||
192 | /* skip "[\0" name, it's surely not it */ | ||
193 | if (ENABLE_TEST && LONE_CHAR(p, '[')) | ||
194 | i++, p += 2; | ||
195 | /* All remaining applet names in p[] are at least 2 chars long */ | ||
196 | /* name[] is also at least 2 chars long */ | ||
197 | |||
198 | n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16); | ||
199 | while (i < max) { | ||
200 | uint32_t p32; | ||
201 | char ch; | ||
202 | |||
203 | /* Quickly check match of the first 3 bytes */ | ||
204 | move_from_unaligned32(p32, p); | ||
205 | p += 3; | ||
206 | if ((p32 & 0x00ffffff) != n32) { | ||
207 | /* Most likely case: 3 first bytes do not match */ | ||
208 | i++; | ||
209 | if ((p32 & 0x00ff0000) == '\0') | ||
210 | continue; // p[2] was NUL | ||
211 | p++; | ||
212 | if ((p32 & 0xff000000) == '\0') | ||
213 | continue; // p[3] was NUL | ||
214 | /* p[0..3] aren't matching and none is NUL, check the rest */ | ||
215 | while (*p++ != '\0') | ||
216 | continue; | ||
217 | continue; | ||
218 | } | ||
219 | |||
220 | /* Unlikely branch: first 3 bytes ([0..2]) match */ | ||
221 | if ((p32 & 0x00ff0000) == '\0') { | ||
222 | /* name is 2-byte long, it is full match */ | ||
223 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
167 | return i; | 224 | return i; |
168 | p += strlen(p) + 1; | 225 | } |
226 | /* Check remaining bytes [3..NUL] */ | ||
227 | ch = (p32 >> 24); | ||
228 | j = 3; | ||
229 | while (ch == name[j]) { | ||
230 | if (ch == '\0') { | ||
231 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
232 | return i; | ||
233 | } | ||
234 | ch = *++p; | ||
235 | j++; | ||
236 | } | ||
237 | /* Not a match. Skip it, including NUL */ | ||
238 | while (ch != '\0') | ||
239 | ch = *++p; | ||
240 | p++; | ||
241 | i++; | ||
242 | } | ||
243 | return -1; | ||
244 | #else | ||
245 | while (i < max) { | ||
246 | char ch; | ||
247 | j = 0; | ||
248 | /* Do we see "name\0" in applet_names[p] position? */ | ||
249 | while ((ch = *p) == name[j]) { | ||
250 | if (ch == '\0') { | ||
251 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
252 | return i; /* yes */ | ||
253 | } | ||
254 | p++; | ||
255 | j++; | ||
256 | } | ||
257 | /* No. | ||
258 | * p => 1st non-matching char in applet_names[], | ||
259 | * skip to and including NUL. | ||
260 | */ | ||
261 | while (ch != '\0') | ||
262 | ch = *++p; | ||
263 | p++; | ||
169 | i++; | 264 | i++; |
170 | } | 265 | } |
171 | return -1; | 266 | return -1; |
@@ -588,6 +683,7 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
588 | * busybox.h::bb_install_loc_t, or else... */ | 683 | * busybox.h::bb_install_loc_t, or else... */ |
589 | int (*lf)(const char *, const char *); | 684 | int (*lf)(const char *, const char *); |
590 | char *fpc; | 685 | char *fpc; |
686 | const char *appname = applet_names; | ||
591 | unsigned i; | 687 | unsigned i; |
592 | int rc; | 688 | int rc; |
593 | 689 | ||
@@ -598,7 +694,7 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
598 | for (i = 0; i < ARRAY_SIZE(applet_main); i++) { | 694 | for (i = 0; i < ARRAY_SIZE(applet_main); i++) { |
599 | fpc = concat_path_file( | 695 | fpc = concat_path_file( |
600 | custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], | 696 | custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], |
601 | APPLET_NAME(i)); | 697 | appname); |
602 | // debug: bb_error_msg("%slinking %s to busybox", | 698 | // debug: bb_error_msg("%slinking %s to busybox", |
603 | // use_symbolic_links ? "sym" : "", fpc); | 699 | // use_symbolic_links ? "sym" : "", fpc); |
604 | rc = lf(busybox, fpc); | 700 | rc = lf(busybox, fpc); |
@@ -606,6 +702,8 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
606 | bb_simple_perror_msg(fpc); | 702 | bb_simple_perror_msg(fpc); |
607 | } | 703 | } |
608 | free(fpc); | 704 | free(fpc); |
705 | while (*appname++ != '\0') | ||
706 | continue; | ||
609 | } | 707 | } |
610 | } | 708 | } |
611 | # else | 709 | # else |
@@ -769,7 +867,7 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) | |||
769 | 867 | ||
770 | /* Reinit some shared global data */ | 868 | /* Reinit some shared global data */ |
771 | xfunc_error_retval = EXIT_FAILURE; | 869 | xfunc_error_retval = EXIT_FAILURE; |
772 | applet_name = APPLET_NAME(applet_no); | 870 | applet_name = bb_get_last_path_component_nostrip(argv[0]); |
773 | 871 | ||
774 | /* Special case. POSIX says "test --help" | 872 | /* Special case. POSIX says "test --help" |
775 | * should be no different from e.g. "test --foo". | 873 | * should be no different from e.g. "test --foo". |
@@ -800,11 +898,14 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) | |||
800 | 898 | ||
801 | void FAST_FUNC run_applet_and_exit(const char *name, char **argv) | 899 | void FAST_FUNC run_applet_and_exit(const char *name, char **argv) |
802 | { | 900 | { |
803 | int applet = find_applet_by_name(name); | 901 | int applet; |
804 | if (applet >= 0) | 902 | |
805 | run_applet_no_and_exit(applet, argv); | ||
806 | if (is_prefixed_with(name, "busybox")) | 903 | if (is_prefixed_with(name, "busybox")) |
807 | exit(busybox_main(argv)); | 904 | exit(busybox_main(argv)); |
905 | /* find_applet_by_name() search is more expensive, so goes second */ | ||
906 | applet = find_applet_by_name(name); | ||
907 | if (applet >= 0) | ||
908 | run_applet_no_and_exit(applet, argv); | ||
808 | } | 909 | } |
809 | 910 | ||
810 | #endif /* !defined(SINGLE_APPLET_MAIN) */ | 911 | #endif /* !defined(SINGLE_APPLET_MAIN) */ |
@@ -817,6 +918,19 @@ int lbb_main(char **argv) | |||
817 | int main(int argc UNUSED_PARAM, char **argv) | 918 | int main(int argc UNUSED_PARAM, char **argv) |
818 | #endif | 919 | #endif |
819 | { | 920 | { |
921 | #if 0 | ||
922 | /* TODO: find a use for a block of memory between end of .bss | ||
923 | * and end of page. For example, I'm getting "_end:0x812e698 2408 bytes" | ||
924 | * - more than 2k of wasted memory (in this particular build) | ||
925 | * *per each running process*! | ||
926 | * (If your linker does not generate "_end" name, weak attribute | ||
927 | * makes &_end == NULL, end_len == 0 here.) | ||
928 | */ | ||
929 | extern char _end[] __attribute__((weak)); | ||
930 | unsigned end_len = (-(int)_end) & 0xfff; | ||
931 | printf("_end:%p %u bytes\n", &_end, end_len); | ||
932 | #endif | ||
933 | |||
820 | /* Tweak malloc for reduced memory consumption */ | 934 | /* Tweak malloc for reduced memory consumption */ |
821 | #ifdef M_TRIM_THRESHOLD | 935 | #ifdef M_TRIM_THRESHOLD |
822 | /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory | 936 | /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory |