207 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* comm - select lines from two sorted files	Author: Martin C. Atkins */
 | 
						|
 | 
						|
/*
 | 
						|
 *	This program was written by:
 | 
						|
 *		Martin C. Atkins,
 | 
						|
 *		University of York,
 | 
						|
 *		Heslington,
 | 
						|
 *		York. Y01 5DD
 | 
						|
 *		England
 | 
						|
 *	and is released into the public domain, on the condition
 | 
						|
 *	that this comment is always included without alteration.
 | 
						|
 */
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <minix/minlib.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#define BUFFER_SIZE (512)
 | 
						|
#define LINMAX (600)
 | 
						|
 | 
						|
struct file {
 | 
						|
  char *name;			/* the file's name */
 | 
						|
  int fd;			/* the file descripter */
 | 
						|
  char buf[BUFFER_SIZE];		/* buffer storage */
 | 
						|
  char *next;			/* the next character to read */
 | 
						|
  char *endp;			/* the first invalid character */
 | 
						|
  int seeneof;			/* an end of file has been seen */
 | 
						|
} files[2];
 | 
						|
 | 
						|
char lines[2][LINMAX];
 | 
						|
 | 
						|
int colflgs[3] = {1, 2, 3};	/* number of tabs + 1: 0 => no column */
 | 
						|
 | 
						|
static char *umsg = "Usage: comm [-[123]] file1 file2\n";
 | 
						|
 | 
						|
_PROTOTYPE(int main, (int argc, char **argv));
 | 
						|
_PROTOTYPE(void usage, (void));
 | 
						|
_PROTOTYPE(void error, (char *s, char *f));
 | 
						|
_PROTOTYPE(void eopen, (char *fn, struct file *file));
 | 
						|
_PROTOTYPE(int getbuf, (struct file *file));
 | 
						|
_PROTOTYPE(int readline, (int fno));
 | 
						|
_PROTOTYPE(void comm, (void));
 | 
						|
_PROTOTYPE(void putcol, (int col, char *buf));
 | 
						|
_PROTOTYPE(void cpycol, (int col));
 | 
						|
 | 
						|
int main(argc, argv)
 | 
						|
int argc;
 | 
						|
char *argv[];
 | 
						|
{
 | 
						|
  int cnt;
 | 
						|
  if (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
 | 
						|
	char *ap;
 | 
						|
	for (ap = &argv[1][1]; *ap; ap++) switch (*ap) {
 | 
						|
		    case '1':
 | 
						|
		    case '2':
 | 
						|
		    case '3':
 | 
						|
			cnt = *ap - '1';
 | 
						|
			if (colflgs[cnt] == 0) break;
 | 
						|
			colflgs[cnt] = 0;
 | 
						|
			for (cnt++; cnt < 3; cnt++) colflgs[cnt]--;
 | 
						|
			break;
 | 
						|
		    default:	usage();
 | 
						|
		}
 | 
						|
	argc--;
 | 
						|
	argv++;
 | 
						|
  }
 | 
						|
  if (argc != 3) usage();
 | 
						|
  eopen(argv[1], &files[0]);
 | 
						|
  eopen(argv[2], &files[1]);
 | 
						|
  comm();
 | 
						|
  return(0);
 | 
						|
}
 | 
						|
 | 
						|
void usage()
 | 
						|
{
 | 
						|
 | 
						|
  std_err(umsg);
 | 
						|
  exit(1);
 | 
						|
}
 | 
						|
 | 
						|
void error(s, f)
 | 
						|
char *s, *f;
 | 
						|
{
 | 
						|
  std_err("comm: ");
 | 
						|
  std_err(s);
 | 
						|
  if (f) std_err(f);
 | 
						|
  std_err("\n");
 | 
						|
  exit(1);
 | 
						|
}
 | 
						|
 | 
						|
void eopen(fn, file)
 | 
						|
char *fn;
 | 
						|
struct file *file;
 | 
						|
{
 | 
						|
  file->name = fn;
 | 
						|
  file->next = file->endp = &file->buf[0];
 | 
						|
  file->seeneof = 0;
 | 
						|
  if (fn[0] == '-' && fn[1] == '\0')
 | 
						|
	file->fd = 0;
 | 
						|
  else if ((file->fd = open(fn, O_RDONLY)) < 0)
 | 
						|
	error("can't open ", fn);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int getbuf(file)
 | 
						|
struct file *file;
 | 
						|
{
 | 
						|
/* Get a buffer-full from the file.  Return true if no characters
 | 
						|
 * were obtained because we are at end of file.
 | 
						|
 */
 | 
						|
  int n;
 | 
						|
 | 
						|
  if (file->seeneof) return(1);
 | 
						|
  if ((n = read(file->fd, &file->buf[0], BUFFER_SIZE)) < 0)
 | 
						|
	error("read error on ", file->name);
 | 
						|
  if (n == 0) {
 | 
						|
	file->seeneof++;
 | 
						|
	return 1;
 | 
						|
  }
 | 
						|
  file->next = &file->buf[0];
 | 
						|
  file->endp = &file->buf[n];
 | 
						|
  return(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int readline(fno)
 | 
						|
int fno;
 | 
						|
{
 | 
						|
/* Read up to the next '\n' character to buf.
 | 
						|
 * Return a complete line, even if end of file occurs within a line.
 | 
						|
 * Return false at end of file/
 | 
						|
 */
 | 
						|
  register struct file *file = &files[fno];
 | 
						|
  char *buf = lines[fno];
 | 
						|
 | 
						|
  if (file->next == file->endp && getbuf(file)) return(0);
 | 
						|
  while ((*buf++ = *file->next++) != '\n')
 | 
						|
	if (file->next == file->endp && getbuf(file)) {
 | 
						|
		*buf++ = '\n';
 | 
						|
		*buf = '\0';
 | 
						|
		return(1);
 | 
						|
	}
 | 
						|
  *buf = '\0';
 | 
						|
  return(1);
 | 
						|
}
 | 
						|
 | 
						|
void comm()
 | 
						|
{
 | 
						|
  register int res;
 | 
						|
 | 
						|
  if (!readline(0)) {
 | 
						|
	cpycol(1);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  if (!readline(1)) {
 | 
						|
	putcol(0, lines[0]);
 | 
						|
	cpycol(0);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  for (;;) {
 | 
						|
	if ((res = strcmp(lines[0], lines[1])) != 0) {
 | 
						|
		res = res > 0;
 | 
						|
		putcol(res, lines[res]);
 | 
						|
		if (!readline(res)) {
 | 
						|
			putcol(!res, lines[!res]);
 | 
						|
			cpycol(!res);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		putcol(2, lines[0]);	/* files[1]lin == f2lin */
 | 
						|
		if (!readline(0)) {
 | 
						|
			cpycol(1);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
		if (!readline(1)) {
 | 
						|
			putcol(0, lines[0]);
 | 
						|
			cpycol(0);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
	}
 | 
						|
  }
 | 
						|
 | 
						|
  /* NOTREACHED */
 | 
						|
}
 | 
						|
 | 
						|
void putcol(col, buf)
 | 
						|
int col;
 | 
						|
char *buf;
 | 
						|
{
 | 
						|
  int cnt;
 | 
						|
 | 
						|
  if (colflgs[col] == 0) return;
 | 
						|
  for (cnt = 0; cnt < colflgs[col] - 1; cnt++) printf("\t");
 | 
						|
  printf("%s", buf);
 | 
						|
}
 | 
						|
 | 
						|
void cpycol(col)
 | 
						|
int col;
 | 
						|
{
 | 
						|
  if (colflgs[col]) while (readline(col))
 | 
						|
		putcol(col, lines[col]);
 | 
						|
}
 |