]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
wc: goto considered harmful
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 24 Sep 2023 00:07:33 +0000 (17:07 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 24 Sep 2023 00:07:52 +0000 (17:07 -0700)
* src/wc.c: Do not include assure.h.  Replace the only
use of ‘assure’ with ‘unreachable’ which is good enough.
(wc, main): Remove labels and gotos.  This doesn’t affect
performance in any way I can measure, and makes the code
a bit easier to follow.

src/wc.c

index 254b92e401a987de848cc88216ef5f524a218738..e69ad0d51fdb7d9e807438d718af5f490c560955 100644 (file)
--- a/src/wc.c
+++ b/src/wc.c
@@ -25,7 +25,6 @@
 #include <sys/types.h>
 #include <uchar.h>
 
-#include <assure.h>
 #include <argmatch.h>
 #include <argv-iter.h>
 #include <fadvise.h>
@@ -497,37 +496,46 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos)
                   if (linepos > linelength)
                     linelength = linepos;
                   linepos = 0;
-                  goto mb_word_separator;
+                  in_word = false;
+                  break;
+
                 case '\t':
                   linepos += 8 - (linepos % 8);
-                  goto mb_word_separator;
+                  in_word = false;
+                  break;
+
                 case ' ':
                   linepos++;
                   FALLTHROUGH;
                 case '\v':
-                mb_word_separator:
                   in_word = false;
                   break;
-                default:
-                  /* c32width can be expensive on macOS for example,
-                     so avoid if not needed.  */
+
+                default:;
+                  bool in_word2;
                   if (single_byte)
-                    linepos += wc_isprint[wide_char];
-                  else if (print_linelength)
                     {
-                      int width = c32width (wide_char);
-                      if (width > 0)
-                        linepos += width;
+                      linepos += wc_isprint[wide_char];
+                      in_word2 = !wc_isspace[wide_char];
+                    }
+                  else
+                    {
+                      /* c32width can be expensive on macOS for example,
+                         so avoid if not needed.  */
+                      if (print_linelength)
+                        {
+                          int width = c32width (wide_char);
+                          if (width > 0)
+                            linepos += width;
+                        }
+                      in_word2 = !iswnbspace (wide_char);
                     }
-                  if (single_byte ? wc_isspace[wide_char]
-                      : c32isspace (wide_char) || iswnbspace (wide_char))
-                    goto mb_word_separator;
 
                   /* Count words by counting word starts, i.e., each
                      white space character (or the start of input)
                      followed by non white space.  */
-                  words += !in_word;
-                  in_word = true;
+                  words += !in_word & in_word2;
+                  in_word = in_word2;
                   break;
                 }
 
@@ -567,23 +575,26 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos)
                   if (linepos > linelength)
                     linelength = linepos;
                   linepos = 0;
-                  goto word_separator;
+                  in_word = false;
+                  break;
+
                 case '\t':
                   linepos += 8 - (linepos % 8);
-                  goto word_separator;
+                  in_word = false;
+                  break;
+
                 case ' ':
                   linepos++;
                   FALLTHROUGH;
                 case '\v':
-                word_separator:
                   in_word = false;
                   break;
+
                 default:
                   linepos += wc_isprint[c];
-                  if (wc_isspace[c])
-                    goto word_separator;
-                  words += !in_word;
-                  in_word = true;
+                  bool in_word2 = !wc_isspace[c];
+                  words += !in_word & in_word2;
+                  in_word = in_word2;
                   break;
                 }
             }
@@ -711,7 +722,6 @@ compute_number_width (idx_t nfiles, struct fstatus const *fstatus)
 int
 main (int argc, char **argv)
 {
-  bool ok;
   int optc;
   idx_t nfiles;
   char **files;
@@ -858,29 +868,12 @@ main (int argc, char **argv)
   else
     number_width = compute_number_width (nfiles, fstatus);
 
-  ok = true;
-  for (int i = 0; /* */; i++)
+  bool ok = true;
+  enum argv_iter_err ai_err;
+  char *file_name;
+  for (int i = 0; (file_name = argv_iter (ai, &ai_err)); i++)
     {
       bool skip_file = false;
-      enum argv_iter_err ai_err;
-      char *file_name = argv_iter (ai, &ai_err);
-      if (!file_name)
-        {
-          switch (ai_err)
-            {
-            case AI_ERR_EOF:
-              goto argv_iter_done;
-            case AI_ERR_READ:
-              error (0, errno, _("%s: read error"),
-                     quotef (files_from));
-              ok = false;
-              goto argv_iter_done;
-            case AI_ERR_MEM:
-              xalloc_die ();
-            default:
-              affirm (!"unexpected error code from argv_iter");
-            }
-        }
       if (files_from && STREQ (files_from, "-") && STREQ (file_name, "-"))
         {
           /* Give a better diagnostic in an unusual case:
@@ -918,7 +911,22 @@ main (int argc, char **argv)
       if (! nfiles)
         fstatus[0].failed = 1;
     }
- argv_iter_done:
+  switch (ai_err)
+    {
+    case AI_ERR_EOF:
+      break;
+
+    case AI_ERR_READ:
+      error (0, errno, _("%s: read error"), quotef (files_from));
+      ok = false;
+      break;
+
+    case AI_ERR_MEM:
+      xalloc_die ();
+
+    default:
+      unreachable ();
+    }
 
   /* No arguments on the command line is fine.  That means read from stdin.
      However, no arguments on the --files0-from input stream is an error