ls: code shrink

function                                             old     new   delta
count_dirs                                            81      86      +5
dnalloc                                               13      17      +4
showfiles                                            372     370      -2
ls_main                                              833     825      -8
showdirs                                             505     489     -16
splitdnarray                                         189     120     -69
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/4 up/down: 9/-95)             Total: -86 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-10-03 11:43:48 +02:00
parent ffd4774ad2
commit cae409c6aa

View File

@ -385,27 +385,29 @@ static char append_char(mode_t mode)
} }
#endif #endif
#define countdirs(A, B) count_dirs((A), (B), 1) static unsigned count_dirs(struct dnode **dn, int which)
#define countsubdirs(A, B) count_dirs((A), (B), 0)
static unsigned count_dirs(struct dnode **dn, unsigned nfiles, int notsubdirs)
{ {
unsigned i, dirs; unsigned dirs, all;
if (!dn) if (!dn)
return 0; return 0;
dirs = 0;
for (i = 0; i < nfiles; i++) { dirs = all = 0;
for (; *dn; dn++) {
const char *name; const char *name;
if (!S_ISDIR(dn[i]->dstat.st_mode))
all++;
if (!S_ISDIR((*dn)->dstat.st_mode))
continue; continue;
name = dn[i]->name; name = (*dn)->name;
if (notsubdirs if (which != SPLIT_SUBDIR /* if not requested to skip . / .. */
/* or if it's not . or .. */
|| name[0] != '.' || (name[1] && (name[1] != '.' || name[2])) || name[0] != '.' || (name[1] && (name[1] != '.' || name[2]))
) { ) {
dirs++; dirs++;
} }
} }
return dirs; return which != SPLIT_FILE ? dirs : all - dirs;
} }
/* get memory to hold an array of pointers */ /* get memory to hold an array of pointers */
@ -414,18 +416,19 @@ static struct dnode **dnalloc(unsigned num)
if (num < 1) if (num < 1)
return NULL; return NULL;
num++; /* so that we have terminating NULL */
return xzalloc(num * sizeof(struct dnode *)); return xzalloc(num * sizeof(struct dnode *));
} }
#if ENABLE_FEATURE_LS_RECURSIVE #if ENABLE_FEATURE_LS_RECURSIVE
static void dfree(struct dnode **dnp, unsigned nfiles) static void dfree(struct dnode **dnp)
{ {
unsigned i; unsigned i;
if (dnp == NULL) if (dnp == NULL)
return; return;
for (i = 0; i < nfiles; i++) { for (i = 0; dnp[i]; i++) {
struct dnode *cur = dnp[i]; struct dnode *cur = dnp[i];
if (cur->fname_allocated) if (cur->fname_allocated)
free((char*)cur->fullname); free((char*)cur->fullname);
@ -437,40 +440,36 @@ static void dfree(struct dnode **dnp, unsigned nfiles)
#define dfree(...) ((void)0) #define dfree(...) ((void)0)
#endif #endif
static struct dnode **splitdnarray(struct dnode **dn, unsigned nfiles, int which) /* Returns NULL-terminated malloced vector of pointers (or NULL) */
static struct dnode **splitdnarray(struct dnode **dn, int which)
{ {
unsigned dncnt, i, d; unsigned dncnt, d;
struct dnode **dnp; struct dnode **dnp;
if (dn == NULL) if (dn == NULL)
return NULL; return NULL;
/* count how many dirs and regular files there are */ /* count how many dirs or files there are */
if (which == SPLIT_SUBDIR) dncnt = count_dirs(dn, which);
dncnt = countsubdirs(dn, nfiles);
else {
dncnt = countdirs(dn, nfiles); /* assume we are looking for dirs */
if (which == SPLIT_FILE)
dncnt = nfiles - dncnt; /* looking for files */
}
/* allocate a file array and a dir array */ /* allocate a file array and a dir array */
dnp = dnalloc(dncnt); dnp = dnalloc(dncnt);
/* copy the entrys into the file or dir array */ /* copy the entrys into the file or dir array */
for (d = i = 0; i < nfiles; i++) { for (d = 0; *dn; dn++) {
if (S_ISDIR(dn[i]->dstat.st_mode)) { if (S_ISDIR((*dn)->dstat.st_mode)) {
const char *name; const char *name;
if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) if (!(which & (SPLIT_DIR|SPLIT_SUBDIR)))
continue; continue;
name = dn[i]->name; name = (*dn)->name;
if ((which & SPLIT_DIR) if ((which & SPLIT_DIR)
|| name[0]!='.' || (name[1] && (name[1]!='.' || name[2])) || name[0]!='.' || (name[1] && (name[1]!='.' || name[2]))
) { ) {
dnp[d++] = dn[i]; dnp[d++] = *dn;
} }
} else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) { } else if (!(which & (SPLIT_DIR|SPLIT_SUBDIR))) {
dnp[d++] = dn[i]; dnp[d++] = *dn;
} }
} }
return dnp; return dnp;
@ -538,7 +537,7 @@ static void showfiles(struct dnode **dn, unsigned nfiles)
ncols = 1; ncols = 1;
} else { } else {
/* find the longest file name, use that as the column width */ /* find the longest file name, use that as the column width */
for (i = 0; i < nfiles; i++) { for (i = 0; dn[i]; i++) {
int len = bb_mbstrlen(dn[i]->name); int len = bb_mbstrlen(dn[i]->name);
if (column_width < len) if (column_width < len)
column_width = len; column_width = len;
@ -610,11 +609,11 @@ static off_t calculate_blocks(struct dnode **dn, int nfiles)
#endif #endif
static void showdirs(struct dnode **dn, unsigned ndirs, int first) static void showdirs(struct dnode **dn, int first)
{ {
unsigned i, nfiles; unsigned nfiles;
struct dnode **subdnp;
unsigned dndirs; unsigned dndirs;
struct dnode **subdnp;
struct dnode **dnd; struct dnode **dnd;
/* Never happens: /* Never happens:
@ -623,17 +622,17 @@ static void showdirs(struct dnode **dn, unsigned ndirs, int first)
} }
*/ */
for (i = 0; i < ndirs; i++) { for (; *dn; dn++) {
if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
if (!first) if (!first)
bb_putchar('\n'); bb_putchar('\n');
first = 0; first = 0;
printf("%s:\n", dn[i]->fullname); printf("%s:\n", (*dn)->fullname);
} }
subdnp = list_dir(dn[i]->fullname, &nfiles); subdnp = list_dir((*dn)->fullname, &nfiles);
#if ENABLE_DESKTOP #if ENABLE_DESKTOP
if (all_fmt & STYLE_LONG) if (all_fmt & STYLE_LONG)
printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp, nfiles)); printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp));
#endif #endif
if (nfiles > 0) { if (nfiles > 0) {
/* list all files at this level */ /* list all files at this level */
@ -643,22 +642,23 @@ static void showdirs(struct dnode **dn, unsigned ndirs, int first)
&& (all_fmt & DISP_RECURSIVE) && (all_fmt & DISP_RECURSIVE)
) { ) {
/* recursive - list the sub-dirs */ /* recursive - list the sub-dirs */
dnd = splitdnarray(subdnp, nfiles, SPLIT_SUBDIR); dnd = splitdnarray(subdnp, SPLIT_SUBDIR);
dndirs = countsubdirs(subdnp, nfiles); dndirs = count_dirs(subdnp, SPLIT_SUBDIR);
if (dndirs > 0) { if (dndirs > 0) {
dnsort(dnd, dndirs); dnsort(dnd, dndirs);
showdirs(dnd, dndirs, 0); showdirs(dnd, 0);
/* free the array of dnode pointers to the dirs */ /* free the array of dnode pointers to the dirs */
free(dnd); free(dnd);
} }
} }
/* free the dnodes and the fullname mem */ /* free the dnodes and the fullname mem */
dfree(subdnp, nfiles); dfree(subdnp);
} }
} }
} }
/* Returns NULL-terminated malloced vector of pointers (or NULL) */
static struct dnode **list_dir(const char *path, unsigned *nfiles_p) static struct dnode **list_dir(const char *path, unsigned *nfiles_p)
{ {
struct dnode *dn, *cur, **dnp; struct dnode *dn, *cur, **dnp;
@ -1070,9 +1070,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
dnsort(dnp, nfiles); dnsort(dnp, nfiles);
showfiles(dnp, nfiles); showfiles(dnp, nfiles);
} else { } else {
dnd = splitdnarray(dnp, nfiles, SPLIT_DIR); dnd = splitdnarray(dnp, SPLIT_DIR);
dnf = splitdnarray(dnp, nfiles, SPLIT_FILE); dnf = splitdnarray(dnp, SPLIT_FILE);
dndirs = countdirs(dnp, nfiles); dndirs = count_dirs(dnp, SPLIT_DIR);
dnfiles = nfiles - dndirs; dnfiles = nfiles - dndirs;
if (dnfiles > 0) { if (dnfiles > 0) {
dnsort(dnf, dnfiles); dnsort(dnf, dnfiles);
@ -1082,12 +1082,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
} }
if (dndirs > 0) { if (dndirs > 0) {
dnsort(dnd, dndirs); dnsort(dnd, dndirs);
showdirs(dnd, dndirs, dnfiles == 0); showdirs(dnd, dnfiles == 0);
if (ENABLE_FEATURE_CLEAN_UP) if (ENABLE_FEATURE_CLEAN_UP)
free(dnd); free(dnd);
} }
} }
if (ENABLE_FEATURE_CLEAN_UP) if (ENABLE_FEATURE_CLEAN_UP)
dfree(dnp, nfiles); dfree(dnp);
return exit_code; return exit_code;
} }