forget difference between big and small commands - obsolete with vm.
[minix.git] / commands / simple / comm.c
blob5fecf33222291bedb94c691ed57516b12883dbac
1 /* comm - select lines from two sorted files Author: Martin C. Atkins */
3 /*
4 * This program was written by:
5 * Martin C. Atkins,
6 * University of York,
7 * Heslington,
8 * York. Y01 5DD
9 * England
10 * and is released into the public domain, on the condition
11 * that this comment is always included without alteration.
14 #include <sys/types.h>
15 #include <fcntl.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <minix/minlib.h>
20 #include <stdio.h>
22 #define BUFFER_SIZE (512)
23 #define LINMAX (600)
25 struct file {
26 char *name; /* the file's name */
27 int fd; /* the file descripter */
28 char buf[BUFFER_SIZE]; /* buffer storage */
29 char *next; /* the next character to read */
30 char *endp; /* the first invalid character */
31 int seeneof; /* an end of file has been seen */
32 } files[2];
34 char lines[2][LINMAX];
36 int colflgs[3] = {1, 2, 3}; /* number of tabs + 1: 0 => no column */
38 static char *umsg = "Usage: comm [-[123]] file1 file2\n";
40 _PROTOTYPE(int main, (int argc, char **argv));
41 _PROTOTYPE(void usage, (void));
42 _PROTOTYPE(void error, (char *s, char *f));
43 _PROTOTYPE(void eopen, (char *fn, struct file *file));
44 _PROTOTYPE(int getbuf, (struct file *file));
45 _PROTOTYPE(int readline, (int fno));
46 _PROTOTYPE(void comm, (void));
47 _PROTOTYPE(void putcol, (int col, char *buf));
48 _PROTOTYPE(void cpycol, (int col));
50 int main(argc, argv)
51 int argc;
52 char *argv[];
54 int cnt;
55 if (argc > 1 && argv[1][0] == '-' && argv[1][1] != '\0') {
56 char *ap;
57 for (ap = &argv[1][1]; *ap; ap++) switch (*ap) {
58 case '1':
59 case '2':
60 case '3':
61 cnt = *ap - '1';
62 if (colflgs[cnt] == 0) break;
63 colflgs[cnt] = 0;
64 for (cnt++; cnt < 3; cnt++) colflgs[cnt]--;
65 break;
66 default: usage();
68 argc--;
69 argv++;
71 if (argc != 3) usage();
72 eopen(argv[1], &files[0]);
73 eopen(argv[2], &files[1]);
74 comm();
75 return(0);
78 void usage()
81 std_err(umsg);
82 exit(1);
85 void error(s, f)
86 char *s, *f;
88 std_err("comm: ");
89 std_err(s);
90 if (f) std_err(f);
91 std_err("\n");
92 exit(1);
95 void eopen(fn, file)
96 char *fn;
97 struct file *file;
99 file->name = fn;
100 file->next = file->endp = &file->buf[0];
101 file->seeneof = 0;
102 if (fn[0] == '-' && fn[1] == '\0')
103 file->fd = 0;
104 else if ((file->fd = open(fn, O_RDONLY)) < 0)
105 error("can't open ", fn);
109 int getbuf(file)
110 struct file *file;
112 /* Get a buffer-full from the file. Return true if no characters
113 * were obtained because we are at end of file.
115 int n;
117 if (file->seeneof) return(1);
118 if ((n = read(file->fd, &file->buf[0], BUFFER_SIZE)) < 0)
119 error("read error on ", file->name);
120 if (n == 0) {
121 file->seeneof++;
122 return 1;
124 file->next = &file->buf[0];
125 file->endp = &file->buf[n];
126 return(0);
130 int readline(fno)
131 int fno;
133 /* Read up to the next '\n' character to buf.
134 * Return a complete line, even if end of file occurs within a line.
135 * Return false at end of file/
137 register struct file *file = &files[fno];
138 char *buf = lines[fno];
140 if (file->next == file->endp && getbuf(file)) return(0);
141 while ((*buf++ = *file->next++) != '\n')
142 if (file->next == file->endp && getbuf(file)) {
143 *buf++ = '\n';
144 *buf = '\0';
145 return(1);
147 *buf = '\0';
148 return(1);
151 void comm()
153 register int res;
155 if (!readline(0)) {
156 cpycol(1);
157 return;
159 if (!readline(1)) {
160 putcol(0, lines[0]);
161 cpycol(0);
162 return;
164 for (;;) {
165 if ((res = strcmp(lines[0], lines[1])) != 0) {
166 res = res > 0;
167 putcol(res, lines[res]);
168 if (!readline(res)) {
169 putcol(!res, lines[!res]);
170 cpycol(!res);
171 return;
173 } else {
174 putcol(2, lines[0]); /* files[1]lin == f2lin */
175 if (!readline(0)) {
176 cpycol(1);
177 return;
179 if (!readline(1)) {
180 putcol(0, lines[0]);
181 cpycol(0);
182 return;
187 /* NOTREACHED */
190 void putcol(col, buf)
191 int col;
192 char *buf;
194 int cnt;
196 if (colflgs[col] == 0) return;
197 for (cnt = 0; cnt < colflgs[col] - 1; cnt++) printf("\t");
198 printf("%s", buf);
201 void cpycol(col)
202 int col;
204 if (colflgs[col]) while (readline(col))
205 putcol(col, lines[col]);