coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] wc: add -v option to print total counts every second.


From: Sina Siadat
Subject: [PATCH] wc: add -v option to print total counts every second.
Date: Fri, 11 Mar 2016 12:49:13 +0330

* src/wc.c: add -v option and write live counts to stderr.
---
 src/wc.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 114 insertions(+), 19 deletions(-)

diff --git a/src/wc.c b/src/wc.c
index 94cbaff..52ca437 100644
--- a/src/wc.c
+++ b/src/wc.c
@@ -60,9 +60,16 @@ static uintmax_t total_chars;
 static uintmax_t total_bytes;
 static uintmax_t max_line_length;
 
+static uintmax_t live_total_lines;
+static uintmax_t live_total_words;
+static uintmax_t live_total_chars;
+static uintmax_t live_total_bytes;
+static uintmax_t live_max_line_length;
+
 /* Which counts to print. */
 static bool print_lines, print_words, print_chars, print_bytes;
 static bool print_linelength;
+static bool print_verbose;
 
 /* The print width of each count.  */
 static int number_width;
@@ -96,6 +103,7 @@ static struct option const longopts[] =
   {"words", no_argument, NULL, 'w'},
   {"files0-from", required_argument, NULL, FILES0_FROM_OPTION},
   {"max-line-length", no_argument, NULL, 'L'},
+  {"verbose", no_argument, NULL, 'v'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -135,6 +143,7 @@ the following order: newline, word, character, byte, 
maximum line length.\n\
                            If F is - then read names from standard input\n\
   -L, --max-line-length  print the maximum display width\n\
   -w, --words            print the word counts\n\
+  -v, --verbose          print the counts every second\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -143,10 +152,11 @@ the following order: newline, word, character, byte, 
maximum line length.\n\
   exit (status);
 }
 
-/* FILE is the name of the file (or NULL for standard input)
+/* file is the name of the file (or NULL for standard input)
    associated with the specified counters.  */
 static void
-write_counts (uintmax_t lines,
+write_counts (FILE * restrict stream,
+              uintmax_t lines,
               uintmax_t words,
               uintmax_t chars,
               uintmax_t bytes,
@@ -159,31 +169,70 @@ write_counts (uintmax_t lines,
 
   if (print_lines)
     {
-      printf (format_int, number_width, umaxtostr (lines, buf));
+      fprintf (stream, format_int, number_width, umaxtostr (lines, buf));
       format_int = format_sp_int;
     }
   if (print_words)
     {
-      printf (format_int, number_width, umaxtostr (words, buf));
+      fprintf (stream, format_int, number_width, umaxtostr (words, buf));
       format_int = format_sp_int;
     }
   if (print_chars)
     {
-      printf (format_int, number_width, umaxtostr (chars, buf));
+      fprintf (stream, format_int, number_width, umaxtostr (chars, buf));
       format_int = format_sp_int;
     }
   if (print_bytes)
     {
-      printf (format_int, number_width, umaxtostr (bytes, buf));
+      fprintf (stream, format_int, number_width, umaxtostr (bytes, buf));
       format_int = format_sp_int;
     }
   if (print_linelength)
     {
-      printf (format_int, number_width, umaxtostr (linelength, buf));
+      fprintf (stream, format_int, number_width, umaxtostr (linelength, buf));
     }
   if (file)
-    printf (" %s", strchr (file, '\n') ? quotef (file) : file);
-  putchar ('\n');
+    fprintf (stream, " %s", strchr (file, '\n') ? quotef (file) : file);
+}
+
+static void
+write_live_counts (int signum)
+{
+  if (isatty (STDERR_FILENO))
+    fprintf (stderr, "\r");
+
+  write_counts (stderr, live_total_lines, live_total_words,
+                live_total_chars, live_total_bytes, live_max_line_length, 
NULL);
+
+  if (isatty (STDERR_FILENO))
+    fflush (stderr);
+  else
+    fprintf (stderr, "\n");
+
+  alarm (1);
+}
+
+static void
+write_counts_final (uintmax_t lines,
+                    uintmax_t words,
+                    uintmax_t chars,
+                    uintmax_t bytes,
+                    uintmax_t linelength,
+                    const char *file)
+{
+  if (print_verbose) {
+      if (isatty (STDERR_FILENO))
+        fprintf (stderr, "\r");
+
+      /* Update the counts for the final time, if stdout is not a tty.  */
+      if (!isatty (STDOUT_FILENO)) {
+          write_live_counts (0);
+          fprintf (stderr, "\n");
+      }
+  }
+
+  write_counts (stdout, lines, words, chars, bytes, linelength, file);
+  fprintf (stdout, "\n");
 }
 
 /* Count words.  FILE_X is the name of the file (or NULL for standard
@@ -249,7 +298,10 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
             current_pos = lseek (fd, 0, SEEK_CUR);
           if (0 <= current_pos && current_pos < hi_pos
               && 0 <= lseek (fd, hi_pos, SEEK_CUR))
-            bytes = hi_pos - current_pos;
+            {
+              bytes = hi_pos - current_pos;
+              live_total_bytes = bytes;
+            }
         }
 
       fdadvise (fd, 0, 0, FADVISE_SEQUENTIAL);
@@ -262,6 +314,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
               break;
             }
           bytes += bytes_read;
+          live_total_bytes += bytes_read;
         }
     }
   else if (!count_chars && !count_complicated)
@@ -279,6 +332,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
             }
 
           bytes += bytes_read;
+          live_total_bytes += bytes_read;
 
           char *p = buf;
           char *end = p + bytes_read;
@@ -288,7 +342,12 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
             {
               /* Avoid function call overhead for shorter lines.  */
               while (p != end)
-                lines += *p++ == '\n';
+                {
+                  if (*p++ == '\n') {
+                      lines ++;
+                      live_total_lines ++;
+                  }
+                }
             }
           else
             {
@@ -297,6 +356,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
                 {
                   ++p;
                   ++lines;
+                  ++live_total_lines;
                 }
             }
 
@@ -347,6 +407,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
             }
 
           bytes += bytes_read;
+          live_total_bytes += bytes_read;
           p = buf;
           bytes_read += prev;
           do
@@ -396,15 +457,20 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
               p += n;
               bytes_read -= n;
               chars++;
+              live_total_chars++;
               switch (wide_char)
                 {
                 case '\n':
                   lines++;
+                  live_total_lines++;
                   /* Fall through. */
                 case '\r':
                 case '\f':
                   if (linepos > linelength)
-                    linelength = linepos;
+                    {
+                      linelength = linepos;
+                      live_max_line_length = linepos;
+                    }
                   linepos = 0;
                   goto mb_word_separator;
                 case '\t':
@@ -416,6 +482,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
                 case '\v':
                 mb_word_separator:
                   words += in_word;
+                  live_total_words += in_word;
                   in_word = false;
                   break;
                 default:
@@ -448,8 +515,12 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
 # endif
         }
       if (linepos > linelength)
-        linelength = linepos;
+        {
+          linelength = linepos;
+          live_max_line_length = linepos;
+        }
       words += in_word;
+      live_total_words += in_word;
     }
 #endif
   else
@@ -468,17 +539,22 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
             }
 
           bytes += bytes_read;
+          live_total_bytes += bytes_read;
           do
             {
               switch (*p++)
                 {
                 case '\n':
                   lines++;
+                  live_total_lines++;
                   /* Fall through. */
                 case '\r':
                 case '\f':
                   if (linepos > linelength)
-                    linelength = linepos;
+                    {
+                      linelength = linepos;
+                      live_max_line_length = linepos;
+                    }
                   linepos = 0;
                   goto word_separator;
                 case '\t':
@@ -490,6 +566,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
                 case '\v':
                 word_separator:
                   words += in_word;
+                  live_total_words += in_word;
                   in_word = false;
                   break;
                 default:
@@ -506,14 +583,20 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, 
off_t current_pos)
           while (--bytes_read);
         }
       if (linepos > linelength)
-        linelength = linepos;
+        {
+          linelength = linepos;
+          live_max_line_length = linepos;
+        }
       words += in_word;
+      live_total_words += in_word;
     }
 
   if (count_chars < print_chars)
     chars = bytes;
 
-  write_counts (lines, words, chars, bytes, linelength, file_x);
+  live_total_chars += chars;
+
+  write_counts_final (lines, words, chars, bytes, linelength, file_x);
   total_lines += lines;
   total_words += words;
   total_chars += chars;
@@ -646,7 +729,7 @@ main (int argc, char **argv)
   print_linelength = false;
   total_lines = total_words = total_chars = total_bytes = max_line_length = 0;
 
-  while ((optc = getopt_long (argc, argv, "clLmw", longopts, NULL)) != -1)
+  while ((optc = getopt_long (argc, argv, "clLmwv", longopts, NULL)) != -1)
     switch (optc)
       {
       case 'c':
@@ -665,6 +748,10 @@ main (int argc, char **argv)
         print_words = true;
         break;
 
+      case 'v':
+        print_verbose = true;
+        break;
+
       case 'L':
         print_linelength = true;
         break;
@@ -742,6 +829,14 @@ main (int argc, char **argv)
       ai = argv_iter_init_argv (files);
     }
 
+  if (print_verbose)
+    {
+      struct sigaction action;
+      action.sa_handler = write_live_counts;
+      sigaction (SIGALRM, &action, NULL);
+      alarm (1);
+    }
+
   if (!ai)
     xalloc_die ();
 
@@ -819,8 +914,8 @@ main (int argc, char **argv)
     readtokens0_free (&tok);
 
   if (1 < argv_iter_n_args (ai))
-    write_counts (total_lines, total_words, total_chars, total_bytes,
-                  max_line_length, _("total"));
+    write_counts_final (total_lines, total_words, total_chars, total_bytes,
+                        max_line_length, _("total"));
 
   argv_iter_free (ai);
 
-- 
2.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]