ls: code shrink
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 3 Oct 2009 09:43:48 +0000 (11:43 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 3 Oct 2009 09:43:48 +0000 (11:43 +0200)
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>
coreutils/ls.c

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