source: trunk/minix/commands/simple/comm.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 3.9 KB
Line 
1/* comm - select lines from two sorted files Author: Martin C. Atkins */
2
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.
12 */
13
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>
21
22#define BUFFER_SIZE (512)
23#define LINMAX (600)
24
25struct 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];
33
34char lines[2][LINMAX];
35
36int colflgs[3] = {1, 2, 3}; /* number of tabs + 1: 0 => no column */
37
38static char *umsg = "Usage: comm [-[123]] file1 file2\n";
39
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));
49
50int main(argc, argv)
51int argc;
52char *argv[];
53{
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();
67 }
68 argc--;
69 argv++;
70 }
71 if (argc != 3) usage();
72 eopen(argv[1], &files[0]);
73 eopen(argv[2], &files[1]);
74 comm();
75 return(0);
76}
77
78void usage()
79{
80
81 std_err(umsg);
82 exit(1);
83}
84
85void error(s, f)
86char *s, *f;
87{
88 std_err("comm: ");
89 std_err(s);
90 if (f) std_err(f);
91 std_err("\n");
92 exit(1);
93}
94
95void eopen(fn, file)
96char *fn;
97struct file *file;
98{
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);
106}
107
108
109int getbuf(file)
110struct file *file;
111{
112/* Get a buffer-full from the file. Return true if no characters
113 * were obtained because we are at end of file.
114 */
115 int n;
116
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;
123 }
124 file->next = &file->buf[0];
125 file->endp = &file->buf[n];
126 return(0);
127}
128
129
130int readline(fno)
131int fno;
132{
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/
136 */
137 register struct file *file = &files[fno];
138 char *buf = lines[fno];
139
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);
146 }
147 *buf = '\0';
148 return(1);
149}
150
151void comm()
152{
153 register int res;
154
155 if (!readline(0)) {
156 cpycol(1);
157 return;
158 }
159 if (!readline(1)) {
160 putcol(0, lines[0]);
161 cpycol(0);
162 return;
163 }
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;
172 }
173 } else {
174 putcol(2, lines[0]); /* files[1]lin == f2lin */
175 if (!readline(0)) {
176 cpycol(1);
177 return;
178 }
179 if (!readline(1)) {
180 putcol(0, lines[0]);
181 cpycol(0);
182 return;
183 }
184 }
185 }
186
187 /* NOTREACHED */
188}
189
190void putcol(col, buf)
191int col;
192char *buf;
193{
194 int cnt;
195
196 if (colflgs[col] == 0) return;
197 for (cnt = 0; cnt < colflgs[col] - 1; cnt++) printf("\t");
198 printf("%s", buf);
199}
200
201void cpycol(col)
202int col;
203{
204 if (colflgs[col]) while (readline(col))
205 putcol(col, lines[col]);
206}
Note: See TracBrowser for help on using the repository browser.