Re: [hackers] [sbase][PATCH] Add tac(1)

2016-12-27 Thread Mattias Andrée
On Tue, 27 Dec 2016 16:07:01 +0100
Laslo Hunhold  wrote:

> On Tue, 27 Dec 2016 16:05:19 +0100
> Mattias Andrée  wrote:
> 
> Hey Mattias,
>  
> > I actually use tac(1) a lot, but I can't think of
> > anything I have used it for right now. However, it can
> > be used for reversing the output after sort(1), however
> > POSIX specifies -r for sort(1p) which does this, but
> > chances are your common user is not aware of this.  
> 
> but sort(1) requires sorted input, whereas tac(1) can
> operate on any input.

You sort(1) sorts the input. And yes, tac(1) is more
flexible, but that was the only use case I could think
of off the top of my head. But now I remember that I
have used it a number of times to reverse the output
of find(1) to get directories listed after the files
without the directories.

> 
> > I can't see the rationale for adding this behaviour to
> > tail(1). If it is added to tail, the flag would do two
> > things instead of one thing: reversing the output, and
> > output the entire file. It would make more sense to add
> > it to cat(1), perhaps you men to write “cat”. I would
> > think that this is a good idea, but since tac(1)
> > already exists and -r for cat(1) doesn't, I think it is
> > better to go with tac(1), but I'm flexible.  
> 
> What do the others think?
> 
> Cheers
> 
> Laslo
> 



pgpa7gSNsKEh0.pgp
Description: OpenPGP digital signature


Re: [hackers] [sbase][PATCH] Add tac(1)

2016-12-27 Thread Mattias Andrée
On Tue, 27 Dec 2016 11:29:58 +0100
Laslo Hunhold  wrote:

> On Sat, 26 Mar 2016 12:08:28 +0100
> Mattias Andrée  wrote:
> 
> Hey Mattias,
> 
> > Signed-off-by: Mattias Andrée 
> > ---
> >  Makefile   |  1 +
> >  README |  1 +
> >  libutil/getlines.c |  3 ++-
> >  tac.1  | 20 
> >  tac.c  | 69
> > + +
> > text.h |  3 ++-  
> 
> wouldn't it be better to add the r-flag to tail(1)? I
> personally don't see tac(1) at all in the wild, but prove
> me wrong in case I'm missing something.

I actually use tac(1) a lot, but I can't think of anything
I have used it for right now. However, it can be used for
reversing the output after sort(1), however POSIX specifies
-r for sort(1p) which does this, but chances are your common
user is not aware of this.

I can't see the rationale for adding this behaviour to tail(1).
If it is added to tail, the flag would do two things instead
of one thing: reversing the output, and output the entire file.
It would make more sense to add it to cat(1), perhaps you
men to write “cat”. I would think that this is a good idea,
but since tac(1) already exists and -r for cat(1) doesn't, I
think it is better to go with tac(1), but I'm flexible.

> 
> Cheers
> 
> Laslo
> 



pgpPapyJswiXV.pgp
Description: OpenPGP digital signature


Re: [hackers] [sbase][PATCH] Add tac(1)

2016-12-27 Thread Laslo Hunhold
On Sat, 26 Mar 2016 12:08:28 +0100
Mattias Andrée  wrote:

Hey Mattias,

> Signed-off-by: Mattias Andrée 
> ---
>  Makefile   |  1 +
>  README |  1 +
>  libutil/getlines.c |  3 ++-
>  tac.1  | 20 
>  tac.c  | 69 +
> + text.h |  3 ++-

wouldn't it be better to add the r-flag to tail(1)? I personally don't
see tac(1) at all in the wild, but prove me wrong in case I'm missing
something.

Cheers

Laslo

-- 
Laslo Hunhold 



[hackers] [sbase][PATCH] Add tac(1)

2016-03-26 Thread Mattias Andrée
Signed-off-by: Mattias Andrée 
---
 Makefile   |  1 +
 README |  1 +
 libutil/getlines.c |  3 ++-
 tac.1  | 20 
 tac.c  | 69 ++
 text.h |  3 ++-
 6 files changed, 95 insertions(+), 2 deletions(-)
 create mode 100644 tac.1
 create mode 100644 tac.c

diff --git a/Makefile b/Makefile
index 6b2bfdf..fc52e62 100644
--- a/Makefile
+++ b/Makefile
@@ -155,6 +155,7 @@ BIN =\
sponge\
strings\
sync\
+   tac\
tail\
tar\
tee\
diff --git a/README b/README
index d60d8fc..9c3bc09 100644
--- a/README
+++ b/README
@@ -84,6 +84,7 @@ The following tools are implemented:
 0=*|x sponge  .
 0#*|o strings .
 0=*|x sync.
+0=* x tac .
 0=*|o tail.
 0=*|x tar .
 0=*|o tee .
diff --git a/libutil/getlines.c b/libutil/getlines.c
index b912769..96fec53 100644
--- a/libutil/getlines.c
+++ b/libutil/getlines.c
@@ -23,7 +23,8 @@ getlines(FILE *fp, struct linebuf *b)
b->lines[b->nlines - 1].len = linelen;
}
free(line);
-   if (b->lines && b->nlines && linelen && b->lines[b->nlines - 
1].data[linelen - 1] != '\n') {
+   b->nolf = b->lines && b->nlines && linelen && b->lines[b->nlines - 
1].data[linelen - 1] != '\n';
+   if (b->nolf) {
b->lines[b->nlines - 1].data = erealloc(b->lines[b->nlines - 
1].data, linelen + 2);
b->lines[b->nlines - 1].data[linelen] = '\n';
b->lines[b->nlines - 1].data[linelen + 1] = '\0';
diff --git a/tac.1 b/tac.1
new file mode 100644
index 000..13ae1ad
--- /dev/null
+++ b/tac.1
@@ -0,0 +1,20 @@
+.Dd 2016-03-26
+.Dt TAC 1
+.Os sbase
+.Sh NAME
+.Nm tac
+.Nd concatenate files, but reverse the order of their lines
+.Sh SYNOPSIS
+.Nm
+.Op Ar file ...
+.Sh DESCRIPTION
+.Nm
+reads each
+.Ar file
+and prints the their lines in reverse order.
+The files themself are however printed in order.
+If no
+.Ar file
+is given
+.Nm
+reads from stdin.
diff --git a/tac.c b/tac.c
new file mode 100644
index 000..a3cd22b
--- /dev/null
+++ b/tac.c
@@ -0,0 +1,69 @@
+/* See LICENSE file for copyright and license details. */
+#include 
+#include 
+#include 
+#include 
+
+#include "text.h"
+#include "util.h"
+
+static void
+usage(void)
+{
+   eprintf("usage: %s [file ...]\n", argv0);
+}
+
+static void
+tac(FILE *fp)
+{
+   struct linebuf buf = EMPTY_LINEBUF;
+   struct line line;
+   getlines(fp, );
+   while (buf.nlines--) {
+   line = buf.lines[buf.nlines];
+   if (buf.nolf) {
+   /* If the last line is not LF-terminated, the
+* first output line should not be either. */
+   buf.nolf = 0;
+   line.len--;
+   line.data[line.len] = '\0';
+   }
+   fwrite(line.data, 1, line.len, stdout);
+   free(line.data);
+   }
+   free(buf.lines);
+}
+
+int
+main(int argc, char *argv[])
+{
+   FILE *fp;
+   int ret = 0;
+
+   ARGBEGIN {
+   default:
+   usage();
+   } ARGEND
+
+   if (!argc) {
+   tac(stdin);
+   } else {
+   for (; *argv; argc--, argv++) {
+   if (!strcmp(*argv, "-")) {
+   *argv = "";
+   fp = stdin;
+   } else if (!(fp = fopen(*argv, "r"))) {
+   weprintf("fopen %s:", *argv);
+   ret = 1;
+   continue;
+   }
+   tac(fp);
+   if (fp != stdin && fshut(fp, *argv))
+   ret = 1;
+   }
+   }
+
+   ret |= fshut(stdin, "") | fshut(stdout, "");
+
+   return ret;
+}
diff --git a/text.h b/text.h
index bceda52..7e3088d 100644
--- a/text.h
+++ b/text.h
@@ -9,8 +9,9 @@ struct linebuf {
struct line *lines;
size_t nlines;
size_t capacity;
+   int nolf;
 };
-#define EMPTY_LINEBUF {NULL, 0, 0,}
+#define EMPTY_LINEBUF {NULL, 0, 0, 0}
 void getlines(FILE *, struct linebuf *);
 
 void concat(FILE *, const char *, FILE *, const char *);
-- 
2.7.3