bug-coreutils
[Top][All Lists]
Advanced

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

Re: [RFC] linecut addition


From: Steven Schubiger
Subject: Re: [RFC] linecut addition
Date: Fri, 14 Sep 2007 17:32:49 +0200
User-agent: Mutt/1.5.13 (2006-08-11)

>From a conversation with Jim:

On Fri, Aug 24, 2007 at 02:27:34PM +0200, Jim Meyering wrote:
> If you end up adding a program to coreutils,
> it may make more sense to add a tiny bit of code to "head",
> to make it work the way you want, and then to arrange for that code
> to be enabled in a different incarnation of the same .c file.
> For an example of this approach, look at the vdir, ls, dir triple
> of programs.  See src/ls-ls.c, ls-vdir.c, ls-dir.c, and ls.c, and
> the trivial rules in Makefile.am.

Attached is a first (not complete) "approach" open to peer review. 

--- head.c.orig 2007-09-14 00:11:56.000000000 +0200
+++ head.c      2007-09-14 16:58:39.000000000 +0200
@@ -62,6 +62,8 @@
   multiple_files, always, never
 };
 
+static bool range_mode = false;
+
 /* The name this program was run with. */
 char *program_name;
 
@@ -91,6 +93,7 @@
    PRESUME_INPUT_PIPE_OPTION}, /* do not document */
   {"quiet", no_argument, NULL, 'q'},
   {"silent", no_argument, NULL, 'q'},
+  {"range", required_argument, NULL, 'r'},
   {"verbose", no_argument, NULL, 'v'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
@@ -803,11 +806,73 @@
 }
 
 static bool
+range_lines (const char *filename, int fd)
+{
+  char buffer[BUFSIZ];
+  int line_current, line_from, line_to;
+  int range_iter, range_from, range_to;
+  int ranges[4] = { 3,4,7,10 }; /* XXX (testing) */
+
+  size_t bytes_read = safe_read (fd, buffer, BUFSIZ);
+  size_t byte_offset = 0; 
+
+  if (bytes_read == SAFE_READ_ERROR)
+    {
+      error (0, errno, _("error reading %s"), quote (filename));
+      return false;
+    }
+  if (bytes_read == 0)
+    return true;
+
+  line_current = 1;
+  for (range_iter = 0; range_iter < 4; range_iter += 2)
+    {
+      line_from = ranges[range_iter];
+      line_to = ranges[range_iter + 1];
+
+      while (1)
+        {
+          size_t bytes_line_to_write = 0;
+          size_t byte_offset_iter;
+
+          if (byte_offset < bytes_read)
+            { 
+              byte_offset_iter = byte_offset;
+              while (buffer[byte_offset_iter++] != '\n')
+                bytes_line_to_write++;
+              bytes_line_to_write++;
+
+              if (line_current >= line_from && line_current <= line_to)
+                {
+                  if (fwrite ((buffer + byte_offset), 1, 
+                   bytes_line_to_write, stdout) < bytes_line_to_write)
+                   error (EXIT_FAILURE, errno, _("write error")); 
+                }
+
+              line_current++;
+              byte_offset = byte_offset_iter;
+            }
+          else
+            return true;
+
+          if (line_current > line_to)
+            break;
+        }
+    }
+  return true;
+}
+
+static bool
 head (const char *filename, int fd, uintmax_t n_units, bool count_lines,
       bool elide_from_end)
 {
   if (print_headers)
     write_header (filename);
+ 
+  if (range_mode)
+    {
+      return range_lines (filename, fd);
+    } 
 
   if (elide_from_end)
     {
@@ -993,7 +1058,7 @@
       argc--;
     }
 
-  while ((c = getopt_long (argc, argv, "c:n:qv0123456789", long_options, NULL))
+  while ((c = getopt_long (argc, argv, "c:n:r:qv0123456789", long_options, 
NULL))
         != -1)
     {
       switch (c)
@@ -1022,6 +1087,10 @@
          header_mode = never;
          break;
 
+        case 'r':
+          range_mode = true;
+          break;
+
        case 'v':
          header_mode = always;
          break;




reply via email to

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