diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-04-08 21:13:28 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-04-08 21:13:28 +0000 |
| commit | 79cedcb2c0d88531323e5c2a31fd8465241fbffa (patch) | |
| tree | d4a8ab06d87bb96cf8d5c003b464f8e1dfb53fbb | |
| parent | 643dcf00e32bb131b8a8b77ef570289ed27dae57 (diff) | |
| download | busybox-w32-79cedcb2c0d88531323e5c2a31fd8465241fbffa.tar.gz busybox-w32-79cedcb2c0d88531323e5c2a31fd8465241fbffa.tar.bz2 busybox-w32-79cedcb2c0d88531323e5c2a31fd8465241fbffa.zip | |
Avoid linking in printf/bsearch if possible. -20k for static bbox with
"basename", "true" and "false" only.
function old new delta
full_write2_str - 25 +25
bb_show_usage 183 202 +19
main 883 898 +15
run_applet_and_exit 501 507 +6
| -rw-r--r-- | applets/applet_tables.c | 14 | ||||
| -rw-r--r-- | libbb/appletlib.c | 96 |
2 files changed, 83 insertions, 27 deletions
diff --git a/applets/applet_tables.c b/applets/applet_tables.c index 35b099eb4..17135ddc1 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c | |||
| @@ -47,6 +47,7 @@ int main(int argc, char **argv) | |||
| 47 | { | 47 | { |
| 48 | int i; | 48 | int i; |
| 49 | int ofs; | 49 | int ofs; |
| 50 | unsigned MAX_APPLET_NAME_LEN = 1; | ||
| 50 | 51 | ||
| 51 | qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name); | 52 | qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name); |
| 52 | 53 | ||
| @@ -71,18 +72,21 @@ int main(int argc, char **argv) | |||
| 71 | 72 | ||
| 72 | puts("/* This is a generated file, don't edit */\n"); | 73 | puts("/* This is a generated file, don't edit */\n"); |
| 73 | 74 | ||
| 75 | printf("#define NUM_APPLETS %u\n", NUM_APPLETS); | ||
| 74 | if (NUM_APPLETS == 1) { | 76 | if (NUM_APPLETS == 1) { |
| 75 | printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name); | 77 | printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name); |
| 76 | printf("#define SINGLE_APPLET_MAIN %s_main\n\n", applets[0].name); | 78 | printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].name); |
| 77 | } | 79 | } |
| 78 | 80 | ||
| 79 | puts("const char applet_names[] ALIGN1 = \"\""); | 81 | puts("\nconst char applet_names[] ALIGN1 = \"\""); |
| 80 | for (i = 0; i < NUM_APPLETS; i++) { | 82 | for (i = 0; i < NUM_APPLETS; i++) { |
| 81 | printf("\"%s\" \"\\0\"\n", applets[i].name); | 83 | printf("\"%s\" \"\\0\"\n", applets[i].name); |
| 84 | if (MAX_APPLET_NAME_LEN < strlen(applets[i].name)) | ||
| 85 | MAX_APPLET_NAME_LEN = strlen(applets[i].name); | ||
| 82 | } | 86 | } |
| 83 | puts(";"); | 87 | puts(";"); |
| 84 | 88 | ||
| 85 | puts("int (*const applet_main[])(int argc, char **argv) = {"); | 89 | puts("\nint (*const applet_main[])(int argc, char **argv) = {"); |
| 86 | for (i = 0; i < NUM_APPLETS; i++) { | 90 | for (i = 0; i < NUM_APPLETS; i++) { |
| 87 | printf("%s_main,\n", applets[i].main); | 91 | printf("%s_main,\n", applets[i].main); |
| 88 | } | 92 | } |
| @@ -113,8 +117,10 @@ int main(int argc, char **argv) | |||
| 113 | printf("0x%02x,\n", v); | 117 | printf("0x%02x,\n", v); |
| 114 | i++; | 118 | i++; |
| 115 | } | 119 | } |
| 116 | puts("};"); | 120 | puts("};\n"); |
| 117 | #endif | 121 | #endif |
| 118 | 122 | ||
| 123 | printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN); | ||
| 124 | |||
| 119 | return 0; | 125 | return 0; |
| 120 | } | 126 | } |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a48a26003..ed7d3912b 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
| @@ -12,6 +12,21 @@ | |||
| 12 | * Licensed under GPLv2 or later, see file License in this tarball for details. | 12 | * Licensed under GPLv2 or later, see file License in this tarball for details. |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | /* We are trying to not use printf, this benefits the case when selected | ||
| 16 | * applets are really simple. Example: | ||
| 17 | * | ||
| 18 | * $ ./busybox | ||
| 19 | * ... | ||
| 20 | * Currently defined functions: | ||
| 21 | * basename, false, true | ||
| 22 | * | ||
| 23 | * $ size busybox | ||
| 24 | * text data bss dec hex filename | ||
| 25 | * 4473 52 72 4597 11f5 busybox | ||
| 26 | * | ||
| 27 | * FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :( | ||
| 28 | */ | ||
| 29 | |||
| 15 | #include <assert.h> | 30 | #include <assert.h> |
| 16 | #include "busybox.h" | 31 | #include "busybox.h" |
| 17 | 32 | ||
| @@ -81,6 +96,11 @@ static const char *unpack_usage_messages(void) | |||
| 81 | #endif /* FEATURE_COMPRESS_USAGE */ | 96 | #endif /* FEATURE_COMPRESS_USAGE */ |
| 82 | 97 | ||
| 83 | 98 | ||
| 99 | static void full_write2_str(const char *str) | ||
| 100 | { | ||
| 101 | full_write(2, str, strlen(str)); | ||
| 102 | } | ||
| 103 | |||
| 84 | void bb_show_usage(void) | 104 | void bb_show_usage(void) |
| 85 | { | 105 | { |
| 86 | if (ENABLE_SHOW_USAGE) { | 106 | if (ENABLE_SHOW_USAGE) { |
| @@ -90,18 +110,14 @@ void bb_show_usage(void) | |||
| 90 | const char *usage_string = p = unpack_usage_messages(); | 110 | const char *usage_string = p = unpack_usage_messages(); |
| 91 | 111 | ||
| 92 | if (*p == '\b') { | 112 | if (*p == '\b') { |
| 93 | write(2, "\nNo help available.\n\n", | 113 | full_write2_str("\nNo help available.\n\n"); |
| 94 | sizeof("\nNo help available.\n\n") - 1); | ||
| 95 | } else { | 114 | } else { |
| 96 | write(2, "\nUsage: "SINGLE_APPLET_STR" ", | 115 | full_write2_str("\nUsage: "SINGLE_APPLET_STR" "); |
| 97 | sizeof("\nUsage: "SINGLE_APPLET_STR" ") - 1); | 116 | full_write2_str(p); |
| 98 | write(2, p, strlen(p)); | 117 | full_write2_str("\n\n"); |
| 99 | write(2, "\n\n", 2); | ||
| 100 | } | 118 | } |
| 101 | dealloc_usage_messages((char*)usage_string); | 119 | dealloc_usage_messages((char*)usage_string); |
| 102 | #else | 120 | #else |
| 103 | // TODO: in this case, stdio is sucked in by busybox_main() anyway... | ||
| 104 | const char *format_string; | ||
| 105 | const char *p; | 121 | const char *p; |
| 106 | const char *usage_string = p = unpack_usage_messages(); | 122 | const char *usage_string = p = unpack_usage_messages(); |
| 107 | int ap = find_applet_by_name(applet_name); | 123 | int ap = find_applet_by_name(applet_name); |
| @@ -112,32 +128,52 @@ void bb_show_usage(void) | |||
| 112 | while (*p++) continue; | 128 | while (*p++) continue; |
| 113 | ap--; | 129 | ap--; |
| 114 | } | 130 | } |
| 115 | fprintf(stderr, "%s multi-call binary\n", bb_banner); | 131 | full_write2_str(bb_banner); |
| 116 | format_string = "\nUsage: %s %s\n\n"; | 132 | full_write2_str(" multi-call binary\n"); |
| 117 | if (*p == '\b') | 133 | if (*p == '\b') |
| 118 | format_string = "\nNo help available.\n\n"; | 134 | full_write2_str("\nNo help available.\n\n"); |
| 119 | fprintf(stderr, format_string, applet_name, p); | 135 | else { |
| 136 | full_write2_str("\nUsage: "); | ||
| 137 | full_write2_str(applet_name); | ||
| 138 | full_write2_str(" "); | ||
| 139 | full_write2_str(p); | ||
| 140 | full_write2_str("\n\n"); | ||
| 141 | } | ||
| 120 | dealloc_usage_messages((char*)usage_string); | 142 | dealloc_usage_messages((char*)usage_string); |
| 121 | #endif | 143 | #endif |
| 122 | } | 144 | } |
| 123 | xfunc_die(); | 145 | xfunc_die(); |
| 124 | } | 146 | } |
| 125 | 147 | ||
| 126 | 148 | #if NUM_APPLETS > 8 | |
| 127 | /* NB: any char pointer will work as well, not necessarily applet_names */ | 149 | /* NB: any char pointer will work as well, not necessarily applet_names */ |
| 128 | static int applet_name_compare(const void *name, const void *v) | 150 | static int applet_name_compare(const void *name, const void *v) |
| 129 | { | 151 | { |
| 130 | int i = (const char *)v - applet_names; | 152 | int i = (const char *)v - applet_names; |
| 131 | return strcmp(name, APPLET_NAME(i)); | 153 | return strcmp(name, APPLET_NAME(i)); |
| 132 | } | 154 | } |
| 155 | #endif | ||
| 133 | int find_applet_by_name(const char *name) | 156 | int find_applet_by_name(const char *name) |
| 134 | { | 157 | { |
| 158 | #if NUM_APPLETS > 8 | ||
| 135 | /* Do a binary search to find the applet entry given the name. */ | 159 | /* Do a binary search to find the applet entry given the name. */ |
| 136 | const char *p; | 160 | const char *p; |
| 137 | p = bsearch(name, applet_names, ARRAY_SIZE(applet_main), 1, applet_name_compare); | 161 | p = bsearch(name, applet_names, ARRAY_SIZE(applet_main), 1, applet_name_compare); |
| 138 | if (!p) | 162 | if (!p) |
| 139 | return -1; | 163 | return -1; |
| 140 | return p - applet_names; | 164 | return p - applet_names; |
| 165 | #else | ||
| 166 | /* A version which does not pull in bsearch */ | ||
| 167 | int i = 0; | ||
| 168 | const char *p = applet_names; | ||
| 169 | while (i < NUM_APPLETS) { | ||
| 170 | if (strcmp(name, p) == 0) | ||
| 171 | return i; | ||
| 172 | p += strlen(p) + 1; | ||
| 173 | i++; | ||
| 174 | } | ||
| 175 | return -1; | ||
| 176 | #endif | ||
| 141 | } | 177 | } |
| 142 | 178 | ||
| 143 | 179 | ||
| @@ -604,10 +640,11 @@ static int busybox_main(char **argv) | |||
| 604 | get_terminal_width_height(0, &output_width, NULL); | 640 | get_terminal_width_height(0, &output_width, NULL); |
| 605 | } | 641 | } |
| 606 | /* leading tab and room to wrap */ | 642 | /* leading tab and room to wrap */ |
| 607 | output_width -= sizeof("start-stop-daemon, ") + 8; | 643 | output_width -= MAX_APPLET_NAME_LEN + 8; |
| 608 | 644 | ||
| 609 | printf("%s multi-call binary\n", bb_banner); /* reuse const string... */ | 645 | full_write2_str(bb_banner); /* reuse const string... */ |
| 610 | printf("Copyright (C) 1998-2007 Erik Andersen, Rob Landley, Denys Vlasenko\n" | 646 | full_write2_str(" multi-call binary\n" |
| 647 | "Copyright (C) 1998-2007 Erik Andersen, Rob Landley, Denys Vlasenko\n" | ||
| 611 | "and others. Licensed under GPLv2.\n" | 648 | "and others. Licensed under GPLv2.\n" |
| 612 | "See source distribution for full notice.\n" | 649 | "See source distribution for full notice.\n" |
| 613 | "\n" | 650 | "\n" |
| @@ -623,14 +660,18 @@ static int busybox_main(char **argv) | |||
| 623 | col = 0; | 660 | col = 0; |
| 624 | a = applet_names; | 661 | a = applet_names; |
| 625 | while (*a) { | 662 | while (*a) { |
| 663 | int len; | ||
| 626 | if (col > output_width) { | 664 | if (col > output_width) { |
| 627 | puts(","); | 665 | full_write2_str(",\n"); |
| 628 | col = 0; | 666 | col = 0; |
| 629 | } | 667 | } |
| 630 | col += printf("%s%s", (col ? ", " : "\t"), a); | 668 | full_write2_str(col ? ", " : "\t"); |
| 631 | a += strlen(a) + 1; | 669 | full_write2_str(a); |
| 670 | len = strlen(a); | ||
| 671 | col += len + 2; | ||
| 672 | a += len + 1; | ||
| 632 | } | 673 | } |
| 633 | puts("\n"); | 674 | full_write2_str("\n\n"); |
| 634 | return 0; | 675 | return 0; |
| 635 | } | 676 | } |
| 636 | 677 | ||
| @@ -659,7 +700,11 @@ static int busybox_main(char **argv) | |||
| 659 | * "#!/bin/busybox"-style wrappers */ | 700 | * "#!/bin/busybox"-style wrappers */ |
| 660 | applet_name = bb_get_last_path_component_nostrip(argv[0]); | 701 | applet_name = bb_get_last_path_component_nostrip(argv[0]); |
| 661 | run_applet_and_exit(applet_name, argv); | 702 | run_applet_and_exit(applet_name, argv); |
| 662 | bb_error_msg_and_die("applet not found"); | 703 | |
| 704 | /*bb_error_msg_and_die("applet not found"); - sucks in printf */ | ||
| 705 | full_write2_str(applet_name); | ||
| 706 | full_write2_str(": applet not found\n"); | ||
| 707 | xfunc_die(); | ||
| 663 | } | 708 | } |
| 664 | 709 | ||
| 665 | void run_applet_no_and_exit(int applet_no, char **argv) | 710 | void run_applet_no_and_exit(int applet_no, char **argv) |
| @@ -701,7 +746,8 @@ int main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 701 | { | 746 | { |
| 702 | #if ENABLE_FEATURE_INDIVIDUAL | 747 | #if ENABLE_FEATURE_INDIVIDUAL |
| 703 | /* Only one applet is selected by the user! */ | 748 | /* Only one applet is selected by the user! */ |
| 704 | lbb_prepare(SINGLE_APPLET_STR USE_FEATURE_INDIVIDUAL(, argv)); | 749 | /* applet_names in this case is just "applet\0\0" */ |
| 750 | lbb_prepare(applet_names USE_FEATURE_INDIVIDUAL(, argv)); | ||
| 705 | return SINGLE_APPLET_MAIN(argc, argv); | 751 | return SINGLE_APPLET_MAIN(argc, argv); |
| 706 | #else | 752 | #else |
| 707 | lbb_prepare("busybox" USE_FEATURE_INDIVIDUAL(, argv)); | 753 | lbb_prepare("busybox" USE_FEATURE_INDIVIDUAL(, argv)); |
| @@ -721,6 +767,10 @@ int main(int argc ATTRIBUTE_UNUSED, char **argv) | |||
| 721 | parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ | 767 | parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ |
| 722 | 768 | ||
| 723 | run_applet_and_exit(applet_name, argv); | 769 | run_applet_and_exit(applet_name, argv); |
| 724 | bb_error_msg_and_die("applet not found"); | 770 | |
| 771 | /*bb_error_msg_and_die("applet not found"); - sucks in printf */ | ||
| 772 | full_write2_str(applet_name); | ||
| 773 | full_write2_str(": applet not found\n"); | ||
| 774 | xfunc_die(); | ||
| 725 | #endif | 775 | #endif |
| 726 | } | 776 | } |
