diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-13 11:16:09 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-13 11:16:09 +0000 |
commit | c7497ea31b84eb3261a64a2e1a8e80643c26fd9d (patch) | |
tree | 4bd058053b81d7d6b829ef684d6be298f4a5c04f | |
parent | 25b463079d963ae4f482db7ced14d14c28b907b8 (diff) | |
download | busybox-w32-c7497ea31b84eb3261a64a2e1a8e80643c26fd9d.tar.gz busybox-w32-c7497ea31b84eb3261a64a2e1a8e80643c26fd9d.tar.bz2 busybox-w32-c7497ea31b84eb3261a64a2e1a8e80643c26fd9d.zip |
build system: introduce FEATURE_ASSUME_UNICODE
ls: use it. also do G trick. with UNICODE off:
function old new delta
ls_main 843 871 +28
show_color 1 - -1
showdirs 500 497 -3
my_stat 100 97 -3
terminal_width 4 - -4
tabstops 4 - -4
status 122 118 -4
static.dotdir 4 - -4
current_time_t 4 - -4
all_fmt 4 - -4
------------------------------------------------------------------------------
(add/remove: 0/6 grow/shrink: 1/3 up/down: 28/-31) Total: -3 bytes
Also was tested with UNICODE on with glibc.
-rw-r--r-- | Config.in | 12 | ||||
-rw-r--r-- | coreutils/ls.c | 149 |
2 files changed, 99 insertions, 62 deletions
@@ -21,6 +21,18 @@ config DESKTOP | |||
21 | Select this only if you plan to use busybox on full-blown | 21 | Select this only if you plan to use busybox on full-blown |
22 | desktop machine with common Linux distro, not on an embedded box. | 22 | desktop machine with common Linux distro, not on an embedded box. |
23 | 23 | ||
24 | config FEATURE_ASSUME_UNICODE | ||
25 | bool "Assume that 1:1 char/glyph correspondence is not true" | ||
26 | default n | ||
27 | help | ||
28 | This makes various applets aware that one byte is not | ||
29 | one character on screen. | ||
30 | |||
31 | Busybox aims to eventually work correctly with Unicode displays. | ||
32 | Any older encodings are not guaranteed to work. | ||
33 | Probably by the time when busybox will be fully Unicode-clean, | ||
34 | other encodings will be mainly of historic interest. | ||
35 | |||
24 | choice | 36 | choice |
25 | prompt "Buffer allocation policy" | 37 | prompt "Buffer allocation policy" |
26 | default FEATURE_BUFFERS_USE_MALLOC | 38 | default FEATURE_BUFFERS_USE_MALLOC |
diff --git a/coreutils/ls.c b/coreutils/ls.c index 985086634..7d33eae8d 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c | |||
@@ -31,6 +31,10 @@ | |||
31 | 31 | ||
32 | #include "libbb.h" | 32 | #include "libbb.h" |
33 | 33 | ||
34 | #if ENABLE_FEATURE_ASSUME_UNICODE | ||
35 | #include <wchar.h> | ||
36 | #endif | ||
37 | |||
34 | /* This is a NOEXEC applet. Be very careful! */ | 38 | /* This is a NOEXEC applet. Be very careful! */ |
35 | 39 | ||
36 | 40 | ||
@@ -114,18 +118,6 @@ SPLIT_SUBDIR = 2, | |||
114 | #define ATTR(mode) ("\00\00\01\00\01\00\01\00"\ | 118 | #define ATTR(mode) ("\00\00\01\00\01\00\01\00"\ |
115 | "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)]) | 119 | "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)]) |
116 | 120 | ||
117 | /* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */ | ||
118 | #if ENABLE_FEATURE_LS_COLOR | ||
119 | static smallint show_color; | ||
120 | /* long option entry used only for --color, which has no short option | ||
121 | * equivalent */ | ||
122 | static const char ls_color_opt[] ALIGN1 = | ||
123 | "color\0" Optional_argument "\xff" /* no short equivalent */ | ||
124 | ; | ||
125 | #else | ||
126 | enum { show_color = 0 }; | ||
127 | #endif | ||
128 | |||
129 | /* | 121 | /* |
130 | * a directory entry and its stat info are stored here | 122 | * a directory entry and its stat info are stored here |
131 | */ | 123 | */ |
@@ -137,25 +129,68 @@ struct dnode { /* the basic node */ | |||
137 | USE_SELINUX(security_context_t sid;) | 129 | USE_SELINUX(security_context_t sid;) |
138 | struct dnode *next; /* point at the next node */ | 130 | struct dnode *next; /* point at the next node */ |
139 | }; | 131 | }; |
140 | typedef struct dnode dnode_t; | ||
141 | 132 | ||
142 | static struct dnode **list_dir(const char *); | 133 | static struct dnode **list_dir(const char *); |
143 | static struct dnode **dnalloc(int); | 134 | static struct dnode **dnalloc(int); |
144 | static int list_single(struct dnode *); | 135 | static int list_single(const struct dnode *); |
145 | 136 | ||
146 | static unsigned all_fmt; | ||
147 | 137 | ||
138 | struct globals { | ||
139 | #if ENABLE_FEATURE_LS_COLOR | ||
140 | smallint show_color; | ||
141 | #endif | ||
142 | smallint exit_failure; | ||
143 | unsigned all_fmt; | ||
144 | #if ENABLE_FEATURE_AUTOWIDTH | ||
145 | unsigned tabstops; // = COLUMN_GAP; | ||
146 | unsigned terminal_width; // = TERMINAL_WIDTH; | ||
147 | #endif | ||
148 | #if ENABLE_FEATURE_LS_TIMESTAMPS | ||
149 | /* Do time() just once. Saves one syscall per file for "ls -l" */ | ||
150 | time_t current_time_t; | ||
151 | #endif | ||
152 | }; | ||
153 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
154 | #if ENABLE_FEATURE_LS_COLOR | ||
155 | #define show_color (G.show_color ) | ||
156 | #else | ||
157 | enum { show_color = 0 }; | ||
158 | #endif | ||
159 | #define exit_failure (G.exit_failure ) | ||
160 | #define all_fmt (G.all_fmt ) | ||
148 | #if ENABLE_FEATURE_AUTOWIDTH | 161 | #if ENABLE_FEATURE_AUTOWIDTH |
149 | static unsigned tabstops = COLUMN_GAP; | 162 | #define tabstops (G.tabstops ) |
150 | static unsigned terminal_width = TERMINAL_WIDTH; | 163 | #define terminal_width (G.terminal_width) |
151 | #else | 164 | #else |
152 | enum { | 165 | enum { |
153 | tabstops = COLUMN_GAP, | 166 | tabstops = COLUMN_GAP, |
154 | terminal_width = TERMINAL_WIDTH, | 167 | terminal_width = TERMINAL_WIDTH, |
155 | }; | 168 | }; |
156 | #endif | 169 | #endif |
170 | #define current_time_t (G.current_time_t) | ||
171 | /* memset: we have to zero it out because of NOEXEC */ | ||
172 | #define INIT_G() { \ | ||
173 | memset(&G, 0, sizeof(G)); \ | ||
174 | tabstops = COLUMN_GAP; \ | ||
175 | terminal_width = TERMINAL_WIDTH; \ | ||
176 | USE_FEATURE_LS_TIMESTAMPS(time(¤t_time_t);) \ | ||
177 | } | ||
178 | |||
179 | |||
180 | #if ENABLE_FEATURE_ASSUME_UNICODE | ||
181 | /* libbb candidate */ | ||
182 | static size_t mbstrlen(const char *string) | ||
183 | { | ||
184 | size_t width = mbsrtowcs(NULL /*dest*/, &string, | ||
185 | MAXINT(size_t) /*len*/, NULL /*state*/); | ||
186 | if (width == (size_t)-1) | ||
187 | return strlen(string); | ||
188 | return width; | ||
189 | } | ||
190 | #else | ||
191 | #define mbstrlen(string) strlen(string) | ||
192 | #endif | ||
157 | 193 | ||
158 | static int status = EXIT_SUCCESS; | ||
159 | 194 | ||
160 | static struct dnode *my_stat(const char *fullname, const char *name, int force_follow) | 195 | static struct dnode *my_stat(const char *fullname, const char *name, int force_follow) |
161 | { | 196 | { |
@@ -171,7 +206,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f | |||
171 | #endif | 206 | #endif |
172 | if (stat(fullname, &dstat)) { | 207 | if (stat(fullname, &dstat)) { |
173 | bb_simple_perror_msg(fullname); | 208 | bb_simple_perror_msg(fullname); |
174 | status = EXIT_FAILURE; | 209 | exit_failure = 1; |
175 | return 0; | 210 | return 0; |
176 | } | 211 | } |
177 | } else { | 212 | } else { |
@@ -182,7 +217,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f | |||
182 | #endif | 217 | #endif |
183 | if (lstat(fullname, &dstat)) { | 218 | if (lstat(fullname, &dstat)) { |
184 | bb_simple_perror_msg(fullname); | 219 | bb_simple_perror_msg(fullname); |
185 | status = EXIT_FAILURE; | 220 | exit_failure = 1; |
186 | return 0; | 221 | return 0; |
187 | } | 222 | } |
188 | } | 223 | } |
@@ -395,7 +430,7 @@ static void showfiles(struct dnode **dn, int nfiles) | |||
395 | } else { | 430 | } else { |
396 | /* find the longest file name, use that as the column width */ | 431 | /* find the longest file name, use that as the column width */ |
397 | for (i = 0; i < nfiles; i++) { | 432 | for (i = 0; i < nfiles; i++) { |
398 | int len = strlen(dn[i]->name); | 433 | int len = mbstrlen(dn[i]->name); |
399 | if (column_width < len) | 434 | if (column_width < len) |
400 | column_width = len; | 435 | column_width = len; |
401 | } | 436 | } |
@@ -494,7 +529,7 @@ static struct dnode **list_dir(const char *path) | |||
494 | nfiles = 0; | 529 | nfiles = 0; |
495 | dir = warn_opendir(path); | 530 | dir = warn_opendir(path); |
496 | if (dir == NULL) { | 531 | if (dir == NULL) { |
497 | status = EXIT_FAILURE; | 532 | exit_failure = 1; |
498 | return NULL; /* could not open the dir */ | 533 | return NULL; /* could not open the dir */ |
499 | } | 534 | } |
500 | while ((entry = readdir(dir)) != NULL) { | 535 | while ((entry = readdir(dir)) != NULL) { |
@@ -538,13 +573,7 @@ static struct dnode **list_dir(const char *path) | |||
538 | } | 573 | } |
539 | 574 | ||
540 | 575 | ||
541 | #if ENABLE_FEATURE_LS_TIMESTAMPS | 576 | static int list_single(const struct dnode *dn) |
542 | /* Do time() just once. Saves one syscall per file for "ls -l" */ | ||
543 | /* Initialized in main() */ | ||
544 | static time_t current_time_t; | ||
545 | #endif | ||
546 | |||
547 | static int list_single(struct dnode *dn) | ||
548 | { | 577 | { |
549 | int i, column = 0; | 578 | int i, column = 0; |
550 | 579 | ||
@@ -658,7 +687,12 @@ static int list_single(struct dnode *dn) | |||
658 | fgcolor(info.st_mode)); | 687 | fgcolor(info.st_mode)); |
659 | } | 688 | } |
660 | #endif | 689 | #endif |
690 | #if ENABLE_FEATURE_ASSUME_UNICODE | ||
691 | printf("%s", dn->name); | ||
692 | column += mbstrlen(dn->name); | ||
693 | #else | ||
661 | column += printf("%s", dn->name); | 694 | column += printf("%s", dn->name); |
695 | #endif | ||
662 | if (show_color) { | 696 | if (show_color) { |
663 | printf("\033[0m"); | 697 | printf("\033[0m"); |
664 | } | 698 | } |
@@ -701,6 +735,7 @@ static int list_single(struct dnode *dn) | |||
701 | return column; | 735 | return column; |
702 | } | 736 | } |
703 | 737 | ||
738 | |||
704 | /* "[-]Cadil1", POSIX mandated options, busybox always supports */ | 739 | /* "[-]Cadil1", POSIX mandated options, busybox always supports */ |
705 | /* "[-]gnsx", POSIX non-mandated options, busybox always supports */ | 740 | /* "[-]gnsx", POSIX non-mandated options, busybox always supports */ |
706 | /* "[-]Ak" GNU options, busybox always supports */ | 741 | /* "[-]Ak" GNU options, busybox always supports */ |
@@ -779,11 +814,18 @@ static const unsigned opt_flags[] = { | |||
779 | }; | 814 | }; |
780 | 815 | ||
781 | 816 | ||
782 | /* THIS IS A "SAFE" APPLET, main() MAY BE CALLED INTERNALLY FROM SHELL */ | 817 | /* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */ |
783 | /* BE CAREFUL! */ | 818 | #if ENABLE_FEATURE_LS_COLOR |
819 | /* long option entry used only for --color, which has no short option | ||
820 | * equivalent */ | ||
821 | static const char ls_color_opt[] ALIGN1 = | ||
822 | "color\0" Optional_argument "\xff" /* no short equivalent */ | ||
823 | ; | ||
824 | #endif | ||
825 | |||
784 | 826 | ||
785 | int ls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 827 | int ls_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
786 | int ls_main(int argc, char **argv) | 828 | int ls_main(int argc ATTRIBUTE_UNUSED, char **argv) |
787 | { | 829 | { |
788 | struct dnode **dnd; | 830 | struct dnode **dnd; |
789 | struct dnode **dnf; | 831 | struct dnode **dnf; |
@@ -791,18 +833,13 @@ int ls_main(int argc, char **argv) | |||
791 | struct dnode *dn; | 833 | struct dnode *dn; |
792 | struct dnode *cur; | 834 | struct dnode *cur; |
793 | unsigned opt; | 835 | unsigned opt; |
794 | int nfiles = 0; | 836 | int nfiles; |
795 | int dnfiles; | 837 | int dnfiles; |
796 | int dndirs; | 838 | int dndirs; |
797 | int oi; | ||
798 | int ac; | ||
799 | int i; | 839 | int i; |
800 | char **av; | ||
801 | USE_FEATURE_LS_COLOR(char *color_opt;) | 840 | USE_FEATURE_LS_COLOR(char *color_opt;) |
802 | 841 | ||
803 | #if ENABLE_FEATURE_LS_TIMESTAMPS | 842 | INIT_G(); |
804 | time(¤t_time_t); | ||
805 | #endif | ||
806 | 843 | ||
807 | all_fmt = LIST_SHORT | | 844 | all_fmt = LIST_SHORT | |
808 | (ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD)); | 845 | (ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD)); |
@@ -883,39 +920,27 @@ int ls_main(int argc, char **argv) | |||
883 | if (!(all_fmt & STYLE_MASK)) | 920 | if (!(all_fmt & STYLE_MASK)) |
884 | all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); | 921 | all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); |
885 | 922 | ||
886 | /* | 923 | argv += optind; |
887 | * when there are no cmd line args we have to supply a default "." arg. | 924 | if (!argv[0]) |
888 | * we will create a second argv array, "av" that will hold either | 925 | *--argv = (char*)"."; |
889 | * our created "." arg, or the real cmd line args. The av array | ||
890 | * just holds the pointers- we don't move the date the pointers | ||
891 | * point to. | ||
892 | */ | ||
893 | ac = argc - optind; /* how many cmd line args are left */ | ||
894 | if (ac < 1) { | ||
895 | static const char *const dotdir[] = { "." }; | ||
896 | |||
897 | av = (char **) dotdir; | ||
898 | ac = 1; | ||
899 | } else { | ||
900 | av = argv + optind; | ||
901 | } | ||
902 | 926 | ||
903 | /* now, everything is in the av array */ | 927 | if (argv[1]) |
904 | if (ac > 1) | 928 | all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ |
905 | all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ | ||
906 | 929 | ||
907 | /* stuff the command line file names into a dnode array */ | 930 | /* stuff the command line file names into a dnode array */ |
908 | dn = NULL; | 931 | dn = NULL; |
909 | for (oi = 0; oi < ac; oi++) { | 932 | nfiles = 0; |
933 | do { | ||
910 | /* ls w/o -l follows links on command line */ | 934 | /* ls w/o -l follows links on command line */ |
911 | cur = my_stat(av[oi], av[oi], !(all_fmt & STYLE_LONG)); | 935 | cur = my_stat(*argv, *argv, !(all_fmt & STYLE_LONG)); |
936 | argv++; | ||
912 | if (!cur) | 937 | if (!cur) |
913 | continue; | 938 | continue; |
914 | cur->allocated = 0; | 939 | cur->allocated = 0; |
915 | cur->next = dn; | 940 | cur->next = dn; |
916 | dn = cur; | 941 | dn = cur; |
917 | nfiles++; | 942 | nfiles++; |
918 | } | 943 | } while (*argv); |
919 | 944 | ||
920 | /* now that we know how many files there are | 945 | /* now that we know how many files there are |
921 | * allocate memory for an array to hold dnode pointers | 946 | * allocate memory for an array to hold dnode pointers |
@@ -950,5 +975,5 @@ int ls_main(int argc, char **argv) | |||
950 | } | 975 | } |
951 | if (ENABLE_FEATURE_CLEAN_UP) | 976 | if (ENABLE_FEATURE_CLEAN_UP) |
952 | dfree(dnp, nfiles); | 977 | dfree(dnp, nfiles); |
953 | return status; | 978 | return (exit_failure == 0); |
954 | } | 979 | } |