Just like with head(1), rev(1)'s main loop is obfuscated.

This patch moves the open/read/write/close portion of the main loop
out of main() into a separate function, rev_file().  "multibyte"
becomes a global.

I think the result is easier to understand at a glance.

In a subsequent patch I want to drop the "rpath" promise in the
no-file branch, but that needs to wait.

ok?

Index: rev.c
===================================================================
RCS file: /cvs/src/usr.bin/rev/rev.c,v
retrieving revision 1.14
diff -u -p -r1.14 rev.c
--- rev.c       13 Jan 2022 05:10:46 -0000      1.14
+++ rev.c       27 Jan 2022 14:50:41 -0000
@@ -40,17 +40,16 @@
 #include <string.h>
 #include <unistd.h>
 
+int multibyte;
+
 int isu8cont(unsigned char);
+int rev_file(const char *);
 void usage(void);
 
 int
 main(int argc, char *argv[])
 {
-       char *filename, *p = NULL, *t, *te, *u;
-       FILE *fp;
-       ssize_t len;
-       size_t ps = 0;
-       int ch, multibyte, rval;
+       int ch, rval;
 
        setlocale(LC_CTYPE, "");
        multibyte = MB_CUR_MAX > 1;
@@ -67,40 +66,13 @@ main(int argc, char *argv[])
        argc -= optind;
        argv += optind;
 
-       fp = stdin;
-       filename = "stdin";
        rval = 0;
-       do {
-               if (*argv) {
-                       if ((fp = fopen(*argv, "r")) == NULL) {
-                               warn("%s", *argv);
-                               rval = 1;
-                               ++argv;
-                               continue;
-                       }
-                       filename = *argv++;
-               }
-               while ((len = getline(&p, &ps, fp)) != -1) {
-                       if (p[len - 1] == '\n')
-                               --len;
-                       for (t = p + len - 1; t >= p; --t) {
-                               te = t;
-                               if (multibyte)
-                                       while (t > p && isu8cont(*t))
-                                               --t;
-                               for (u = t; u <= te; ++u)
-                                       if (putchar(*u) == EOF)
-                                               err(1, "stdout");
-                       }
-                       if (putchar('\n') == EOF)
-                               err(1, "stdout");
-               }
-               if (ferror(fp)) {
-                       warn("%s", filename);
-                       rval = 1;
-               }
-               (void)fclose(fp);
-       } while(*argv);
+       if (argc == 0) {
+               rval = rev_file(NULL);
+       } else {
+               for (; *argv != NULL; argv++)
+                       rval |= rev_file(*argv);
+       }
        return rval;
 }
 
@@ -108,6 +80,54 @@ int
 isu8cont(unsigned char c)
 {
        return (c & (0x80 | 0x40)) == 0x80;
+}
+
+int
+rev_file(const char *path)
+{
+       char *p = NULL, *t, *te, *u;
+       const char *filename;
+       FILE *fp;
+       size_t ps = 0;
+       ssize_t len;
+       int rval = 0;
+
+       if (path != NULL) {
+               fp = fopen(path, "r");
+               if (fp == NULL) {
+                       warn("%s", path);
+                       return 1;
+               }
+               filename = path;
+       } else {
+               fp = stdin;
+               filename = "stdin";
+       }
+
+       while ((len = getline(&p, &ps, fp)) != -1) {
+               if (p[len - 1] == '\n')
+                       --len;
+               for (t = p + len - 1; t >= p; --t) {
+                       te = t;
+                       if (multibyte)
+                               while (t > p && isu8cont(*t))
+                                       --t;
+                       for (u = t; u <= te; ++u)
+                               if (putchar(*u) == EOF)
+                                       err(1, "stdout");
+               }
+               if (putchar('\n') == EOF)
+                       err(1, "stdout");
+       }
+       free(p);
+       if (ferror(fp)) {
+               warn("%s", filename);
+               rval = 1;
+       }
+
+       (void)fclose(fp);
+
+       return rval;
 }
 
 void

Reply via email to