aboutsummaryrefslogtreecommitdiff
path: root/libbb/appletlib.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2016-04-04 16:22:54 +0100
committerRon Yorston <rmy@pobox.com>2016-04-04 16:22:54 +0100
commit253dbd612b2d2f041f4263e15a3b94df70f41e36 (patch)
treef6c6e12a0541233058a7f7ccb1251afeb457da06 /libbb/appletlib.c
parent3cf56a021d7a62512b477640e930e1a78288075c (diff)
parentd7d4750e1e213e7448147186dddfe3bfbb47eea0 (diff)
downloadbusybox-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.c166
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
144static 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
150int FAST_FUNC find_applet_by_name(const char *name) 143int 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
801void FAST_FUNC run_applet_and_exit(const char *name, char **argv) 899void 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)
817int main(int argc UNUSED_PARAM, char **argv) 918int 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