coreutils
[Top][All Lists]
Advanced

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

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


From: Sina Siadat
Subject: Re: [PATCH] wc: add -v option to print total counts every second.
Date: Fri, 1 Apr 2016 14:46:04 +0430

I am sorry for the long delay. Thank you very much for your feedbacks.
I updated the patch to implement what you suggested. The flag is
renamed to --progress[=SECONDS].

>Also note that  you have to choose between bytes and lines, you
>can't have both, that's really two different modes of operations.

I didn't exactly get this part. Does this mean that we cannot show the
counting progress for both lines and bytes? Chars is always zero in
the this patch, but progress for lines and bytes (-l -c) seem to be
working. Please correct me if I'm wrong :).

>Adding timer capability to awk could be another approach.

That sounds interesting! Could you give an example of how you would go
about implementing that? An example usage would be great.

Below is the updated patch with --progress[=SECONDS]:

 src/wc.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 129 insertions(+), 19 deletions(-)

diff --git a/src/wc.c b/src/wc.c
index 94cbaff..43653cf 100644
--- a/src/wc.c
+++ b/src/wc.c
@@ -37,6 +37,8 @@
 #include "stat-size.h"
 #include "xfreopen.h"

+#include "xdectoint.h"
+
 #if !defined iswspace && !HAVE_ISWSPACE
 # define iswspace(wc) \
     ((wc) == to_uchar (wc) && isspace (to_uchar (wc)))
@@ -60,9 +62,17 @@ static uintmax_t total_chars;
 static uintmax_t total_bytes;
 static uintmax_t max_line_length;

+static uintmax_t progress_total_lines;
+static uintmax_t progress_total_words;
+static uintmax_t progress_total_chars;
+static uintmax_t progress_total_bytes;
+static uintmax_t progress_max_line_length;
+
 /* Which counts to print. */
 static bool print_lines, print_words, print_chars, print_bytes;
 static bool print_linelength;
+static bool print_progress;
+static uintmax_t progress_interval_seconds;

 /* The print width of each count.  */
 static int number_width;
@@ -85,7 +95,8 @@ struct fstatus
    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
 enum
 {
-  FILES0_FROM_OPTION = CHAR_MAX + 1
+  FILES0_FROM_OPTION = CHAR_MAX + 1,
+  PROGRESS_OPTION = CHAR_MAX + 2
 };

 static struct option const longopts[] =
@@ -96,6 +107,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'},
+  {"progress", optional_argument, NULL, PROGRESS_OPTION},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -135,6 +147,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\
+  --progress[=SECONDS]   print the counts every SECONDS (default is 1)\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -143,10 +156,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 +173,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_counts_progress (int signum)
+{
+  if (isatty (STDERR_FILENO))
+    fprintf (stderr, "\r");
+
+  write_counts (stderr, progress_total_lines, progress_total_words,
+                progress_total_chars, progress_total_bytes,
progress_max_line_length, NULL);
+
+  if (isatty (STDERR_FILENO))
+    fflush (stderr);
+  else
+    fprintf (stderr, "\n");
+
+  alarm (progress_interval_seconds);
+}
+
+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_progress) {
+      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_counts_progress (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 +302,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;
+              progress_total_bytes = bytes;
+            }
         }

       fdadvise (fd, 0, 0, FADVISE_SEQUENTIAL);
@@ -262,6 +318,7 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
               break;
             }
           bytes += bytes_read;
+          progress_total_bytes += bytes_read;
         }
     }
   else if (!count_chars && !count_complicated)
@@ -279,6 +336,7 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
             }

           bytes += bytes_read;
+          progress_total_bytes += bytes_read;

           char *p = buf;
           char *end = p + bytes_read;
@@ -288,7 +346,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 ++;
+                      progress_total_lines ++;
+                  }
+                }
             }
           else
             {
@@ -297,6 +360,7 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
                 {
                   ++p;
                   ++lines;
+                  ++progress_total_lines;
                 }
             }

@@ -347,6 +411,7 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
             }

           bytes += bytes_read;
+          progress_total_bytes += bytes_read;
           p = buf;
           bytes_read += prev;
           do
@@ -396,15 +461,20 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
               p += n;
               bytes_read -= n;
               chars++;
+              progress_total_chars++;
               switch (wide_char)
                 {
                 case '\n':
                   lines++;
+                  progress_total_lines++;
                   /* Fall through. */
                 case '\r':
                 case '\f':
                   if (linepos > linelength)
-                    linelength = linepos;
+                    {
+                      linelength = linepos;
+                      progress_max_line_length = linepos;
+                    }
                   linepos = 0;
                   goto mb_word_separator;
                 case '\t':
@@ -416,6 +486,7 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
                 case '\v':
                 mb_word_separator:
                   words += in_word;
+                  progress_total_words += in_word;
                   in_word = false;
                   break;
                 default:
@@ -448,8 +519,12 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
 # endif
         }
       if (linepos > linelength)
-        linelength = linepos;
+        {
+          linelength = linepos;
+          progress_max_line_length = linepos;
+        }
       words += in_word;
+      progress_total_words += in_word;
     }
 #endif
   else
@@ -468,17 +543,22 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
             }

           bytes += bytes_read;
+          progress_total_bytes += bytes_read;
           do
             {
               switch (*p++)
                 {
                 case '\n':
                   lines++;
+                  progress_total_lines++;
                   /* Fall through. */
                 case '\r':
                 case '\f':
                   if (linepos > linelength)
-                    linelength = linepos;
+                    {
+                      linelength = linepos;
+                      progress_max_line_length = linepos;
+                    }
                   linepos = 0;
                   goto word_separator;
                 case '\t':
@@ -490,6 +570,7 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
                 case '\v':
                 word_separator:
                   words += in_word;
+                  progress_total_words += in_word;
                   in_word = false;
                   break;
                 default:
@@ -506,14 +587,19 @@ wc (int fd, char const *file_x, struct fstatus
*fstatus, off_t current_pos)
           while (--bytes_read);
         }
       if (linepos > linelength)
-        linelength = linepos;
+        {
+          linelength = linepos;
+          progress_max_line_length = linepos;
+        }
       words += in_word;
+      progress_total_words += in_word;
     }

   if (count_chars < print_chars)
     chars = bytes;

-  write_counts (lines, words, chars, bytes, linelength, file_x);
+  progress_total_chars += chars;
+  write_counts_final (lines, words, chars, bytes, linelength, file_x);
   total_lines += lines;
   total_words += words;
   total_chars += chars;
@@ -665,6 +751,22 @@ main (int argc, char **argv)
         print_words = true;
         break;

+      case PROGRESS_OPTION:
+        print_progress = true;
+
+        if (optarg)
+          {
+            progress_interval_seconds = xdectoumax (optarg, 0, UINTMAX_MAX, "",
+                                                    _("invalid seconds"),
+                                                    0);
+            if (progress_interval_seconds < 1)
+              progress_interval_seconds = 1;
+          }
+        else
+          progress_interval_seconds = 1;
+
+        break;
+
       case 'L':
         print_linelength = true;
         break;
@@ -742,6 +844,14 @@ main (int argc, char **argv)
       ai = argv_iter_init_argv (files);
     }

+  if (print_progress)
+    {
+      struct sigaction action;
+      action.sa_handler = write_counts_progress;
+      sigaction (SIGALRM, &action, NULL);
+      alarm (progress_interval_seconds);
+    }
+
   if (!ai)
     xalloc_die ();

@@ -819,8 +929,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);



reply via email to

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