tac.c a program to print lines in reverse order in linear time

trb at masscomp.UUCP trb at masscomp.UUCP
Sat Sep 22 02:12:26 AEST 1984


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	<stdio.h>
#	include	<sys/types.h>
#	include	<sys/stat.h>

/* 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 */



More information about the Comp.sources.unix mailing list