Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site masscomp.UUCP Path: utzoo!watmath!clyde!bonnie!masscomp!trb From: trb@masscomp.UUCP Newsgroups: net.sources Subject: tac.c a program to print lines in reverse order in linear time Message-ID: <419@masscomp.UUCP> Date: Fri, 21-Sep-84 12:12:26 EDT Article-I.D.: masscomp.419 Posted: Fri Sep 21 12:12:26 1984 Date-Received: Sat, 22-Sep-84 07:31:25 EDT Organization: MASSCOMP, Westford, MA Lines: 126 This program was first posted to net.sources in Oct 1982. What comes around goes around, I always say, so here it is, tac.c. Tac does not read stdin. Why? Think about it. I think research!rob modified this to do squashing of multiple blank lines and printing of control characters as ^X, but he wouldn't let me give it out. Andy Tannenbaum Masscomp Inc Westford MA (617) 692-6200 x274 <<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>><<>> # include # include # include /* tac.c (backwards cat) */ main(argc, argv) int argc; char **argv; { register char *p, *q; register int i; struct stat st; off_t off, lseek(); char buffer[ 1 + BUFSIZ + BUFSIZ + 1 ]; char *buf; char *readerr = "Read error at offset %lu of %s\n"; int fd, any; void output(), utcopyn(); if (argc < 2) { (void) fprintf(stderr, "Usage: tac file ...\n"); exit(1); } buf = buffer; *buf++ = '\n'; any = 0; while (--argc) { if (stat(p = *++argv, &st) == -1) { (void) fprintf(stderr , "Bad status for %s\n", p); any++; continue; } if ((off = st.st_size) == 0) continue; if ((fd = open(p, 0)) == -1) { (void) fprintf(stderr, "Can't open %s\n", p); any++; continue; } if ((i = off % BUFSIZ ) == 0) i = BUFSIZ; off -= i; (void) lseek(fd, off, 0); if (read(fd, buf, i) != i) { (void) fprintf(stderr, readerr, off, p); (void) close(fd); any++; continue; } p = q = buf + i; if (*--p == '\n') q = p; for (;;) { while (*--p != '\n'); if (p < buf) { if (off == 0) { output(p, q); (void) close(fd); break; } (void) lseek(fd, off -= BUFSIZ, 0); if ((i = q - buf) > BUFSIZ) { (void) fprintf(stderr, "Line too long\n"); any++; i = BUFSIZ; } utcopyn(p = buf + BUFSIZ, buf, i); q = p + i; if (read(fd, buf, BUFSIZ) != BUFSIZ) { (void) fprintf(stderr, readerr, off, *argv); any++; (void) close(fd); break; } continue; } output(p, q); q = p; } } exit(any); } static void output(p, q) register char *p,*q; { register FILE *iop; for (iop = stdout, p++; p < q; (void) putc(*p++, iop)); (void) putc('\n', iop); } static void utcopyn(tp, fp, n) register char *tp, *fp; register int n; { while (--n >= 0) *tp++ = *fp++; return; } /* end of tac.c */