diff options
author | Ron Yorston <rmy@pobox.com> | 2021-02-05 11:24:06 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-02-05 11:24:06 +0000 |
commit | 32e19e7ae8b0d76d69871ba234e8f0af31baff4e (patch) | |
tree | 6fdc833a444e0dd6fd359b21a8d463856917a387 /libbb/appletlib.c | |
parent | 4fb71406b884c6ac0a9a4d2acf7a32b544611f70 (diff) | |
parent | cad3fc743aa7c7744e4fcf044371f0fda50fa51f (diff) | |
download | busybox-w32-32e19e7ae8b0d76d69871ba234e8f0af31baff4e.tar.gz busybox-w32-32e19e7ae8b0d76d69871ba234e8f0af31baff4e.tar.bz2 busybox-w32-32e19e7ae8b0d76d69871ba234e8f0af31baff4e.zip |
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb/appletlib.c')
-rw-r--r-- | libbb/appletlib.c | 96 |
1 files changed, 17 insertions, 79 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index ecee45ae2..320cb5b13 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -191,7 +191,7 @@ void FAST_FUNC bb_show_usage(void) | |||
191 | 191 | ||
192 | int FAST_FUNC find_applet_by_name(const char *name) | 192 | int FAST_FUNC find_applet_by_name(const char *name) |
193 | { | 193 | { |
194 | unsigned i, max; | 194 | unsigned i; |
195 | int j; | 195 | int j; |
196 | const char *p; | 196 | const char *p; |
197 | 197 | ||
@@ -215,105 +215,43 @@ int FAST_FUNC find_applet_by_name(const char *name) | |||
215 | #endif | 215 | #endif |
216 | 216 | ||
217 | p = applet_names; | 217 | p = applet_names; |
218 | i = 0; | ||
219 | #if KNOWN_APPNAME_OFFSETS <= 0 | 218 | #if KNOWN_APPNAME_OFFSETS <= 0 |
220 | max = NUM_APPLETS; | 219 | i = 0; |
221 | #else | 220 | #else |
222 | max = NUM_APPLETS * KNOWN_APPNAME_OFFSETS; | 221 | i = NUM_APPLETS * (KNOWN_APPNAME_OFFSETS - 1); |
223 | for (j = ARRAY_SIZE(applet_nameofs)-1; j >= 0; j--) { | 222 | for (j = ARRAY_SIZE(applet_nameofs)-1; j >= 0; j--) { |
224 | const char *pp = applet_names + applet_nameofs[j]; | 223 | const char *pp = applet_names + applet_nameofs[j]; |
225 | if (strcmp(name, pp) >= 0) { | 224 | if (strcmp(name, pp) >= 0) { |
226 | //bb_error_msg("name:'%s' >= pp:'%s'", name, pp); | 225 | //bb_error_msg("name:'%s' >= pp:'%s'", name, pp); |
227 | p = pp; | 226 | p = pp; |
228 | i = max - NUM_APPLETS; | ||
229 | break; | 227 | break; |
230 | } | 228 | } |
231 | max -= NUM_APPLETS; | 229 | i -= NUM_APPLETS; |
232 | } | 230 | } |
233 | max /= (unsigned)KNOWN_APPNAME_OFFSETS; | ||
234 | i /= (unsigned)KNOWN_APPNAME_OFFSETS; | 231 | i /= (unsigned)KNOWN_APPNAME_OFFSETS; |
235 | //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max); | 232 | //bb_error_msg("name:'%s' starting from:'%s' i:%u", name, p, i); |
236 | #endif | 233 | #endif |
237 | 234 | ||
238 | /* Open-coded linear search without strcmp/strlen calls for speed */ | 235 | /* Open-coded linear search without strcmp/strlen calls for speed */ |
239 | 236 | while (*p) { | |
240 | #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ | 237 | /* Do we see "name\0" at current position in applet_names? */ |
241 | /* skip "[\0" name, it's surely not it */ | 238 | for (j = 0; *p == name[j]; ++j) { |
242 | if (ENABLE_TEST && LONE_CHAR(p, '[')) | 239 | if (*p++ == '\0') { |
243 | i++, p += 2; | ||
244 | /* All remaining applet names in p[] are at least 2 chars long */ | ||
245 | /* name[] is also at least 2 chars long */ | ||
246 | |||
247 | n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16); | ||
248 | while (i < max) { | ||
249 | uint32_t p32; | ||
250 | char ch; | ||
251 | |||
252 | /* Quickly check match of the first 3 bytes */ | ||
253 | move_from_unaligned32(p32, p); | ||
254 | p += 3; | ||
255 | if ((p32 & 0x00ffffff) != n32) { | ||
256 | /* Most likely case: 3 first bytes do not match */ | ||
257 | i++; | ||
258 | if ((p32 & 0x00ff0000) == '\0') | ||
259 | continue; // p[2] was NUL | ||
260 | p++; | ||
261 | if ((p32 & 0xff000000) == '\0') | ||
262 | continue; // p[3] was NUL | ||
263 | /* p[0..3] aren't matching and none is NUL, check the rest */ | ||
264 | while (*p++ != '\0') | ||
265 | continue; | ||
266 | continue; | ||
267 | } | ||
268 | |||
269 | /* Unlikely branch: first 3 bytes ([0..2]) match */ | ||
270 | if ((p32 & 0x00ff0000) == '\0') { | ||
271 | /* name is 2-byte long, it is full match */ | ||
272 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
273 | return i; | ||
274 | } | ||
275 | /* Check remaining bytes [3..NUL] */ | ||
276 | ch = (p32 >> 24); | ||
277 | j = 3; | ||
278 | while (ch == name[j]) { | ||
279 | if (ch == '\0') { | ||
280 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
281 | return i; | ||
282 | } | ||
283 | ch = *++p; | ||
284 | j++; | ||
285 | } | ||
286 | /* Not a match. Skip it, including NUL */ | ||
287 | while (ch != '\0') | ||
288 | ch = *++p; | ||
289 | p++; | ||
290 | i++; | ||
291 | } | ||
292 | return -1; | ||
293 | #else | ||
294 | while (i < max) { | ||
295 | char ch; | ||
296 | j = 0; | ||
297 | /* Do we see "name\0" in applet_names[p] position? */ | ||
298 | while ((ch = *p) == name[j]) { | ||
299 | if (ch == '\0') { | ||
300 | //bb_error_msg("found:'%s' i:%u", name, i); | 240 | //bb_error_msg("found:'%s' i:%u", name, i); |
301 | return i; /* yes */ | 241 | return i; /* yes */ |
302 | } | 242 | } |
303 | p++; | ||
304 | j++; | ||
305 | } | 243 | } |
306 | /* No. | 244 | /* No. Have we gone too far, alphabetically? */ |
307 | * p => 1st non-matching char in applet_names[], | 245 | if (*p > name[j]) { |
308 | * skip to and including NUL. | 246 | //bb_error_msg("break:'%s' i:%u", name, i); |
309 | */ | 247 | break; |
310 | while (ch != '\0') | 248 | } |
311 | ch = *++p; | 249 | /* No. Move to the start of the next applet name. */ |
312 | p++; | 250 | while (*p++ != '\0') |
251 | continue; | ||
313 | i++; | 252 | i++; |
314 | } | 253 | } |
315 | return -1; | 254 | return -1; |
316 | #endif | ||
317 | } | 255 | } |
318 | 256 | ||
319 | 257 | ||