re-establish kernel assert()s.
[minix.git] / commands / simple / uniq.c
blobe12ce4d1665fa38f9e64477362295e98cd38c680
1 /* uniq - compact repeated lines Author: John Woods */
2 /* Uniq [-udc] [-n] [+n] [infile [outfile]]
4 * Written 02/08/86 by John Woods, placed into public domain. Enjoy.
6 */
8 /* If the symbol WRITE_ERROR is defined, uniq will exit(1) if it gets a
9 * write error on the output. This is not (of course) how V7 uniq does it,
10 * so undefine the symbol if you want to lose your output to a full disk
13 #define WRITE_ERROR 1
14 #include <ctype.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <stdio.h>
20 char buffer[BUFSIZ];
21 int uflag = 1; /* default is union of -d and -u outputs */
22 int dflag = 1; /* flags are mutually exclusive */
23 int cflag = 0;
24 int fields = 0;
25 int chars = 0;
27 _PROTOTYPE(int main, (int argc, char **argv));
28 _PROTOTYPE(FILE *xfopen, (char *fn, char *mode));
29 _PROTOTYPE(char *skip, (char *s));
30 _PROTOTYPE(int equal, (char *s1, char *s2));
31 _PROTOTYPE(void show, (char *line, int count));
32 _PROTOTYPE(int uniq, (void));
33 _PROTOTYPE(void usage, (void));
34 _PROTOTYPE(int getline, (char *buf, int count));
36 FILE *xfopen(fn, mode)
37 char *fn, *mode;
39 FILE *p;
41 if ((p = fopen(fn, mode)) == NULL) {
42 perror("uniq");
43 fflush(stdout);
44 exit(1);
46 return(p);
49 int main(argc, argv)
50 int argc;
51 char *argv[];
53 char *p;
54 int inf = -1, outf;
56 setbuf(stdout, buffer);
57 for (--argc, ++argv; argc > 0 && (**argv == '-' || **argv == '+');
58 --argc, ++argv) {
59 if (**argv == '+')
60 chars = atoi(*argv + 1);
61 else if (isdigit(argv[0][1]))
62 fields = atoi(*argv + 1);
63 else if (argv[0][1] == '\0')
64 inf = 0; /* - is stdin */
65 else
66 for (p = *argv + 1; *p; p++) {
67 switch (*p) {
68 case 'd':
69 dflag = 1;
70 uflag = 0;
71 break;
72 case 'u':
73 uflag = 1;
74 dflag = 0;
75 break;
76 case 'c': cflag = 1; break;
77 default: usage();
82 /* Input file */
83 if (argc == 0)
84 inf = 0;
85 else if (inf == -1) { /* if - was not given */
86 fclose(stdin);
87 xfopen(*argv++, "r");
88 argc--;
90 if (argc == 0)
91 outf = 1;
92 else {
93 fclose(stdout);
94 xfopen(*argv++, "w");
95 argc--;
98 uniq();
99 fflush(stdout);
100 return(0);
103 char *skip(s)
104 char *s;
106 int n;
108 /* Skip fields */
109 for (n = fields; n > 0; --n) {
110 /* Skip blanks */
111 while (*s && (*s == ' ' || *s == '\t')) s++;
112 if (!*s) return s;
113 while (*s && (*s != ' ' && *s != '\t')) s++;
114 if (!*s) return s;
117 /* Skip characters */
118 for (n = chars; n > 0; --n) {
119 if (!*s) return s;
120 s++;
122 return s;
125 int equal(s1, s2)
126 char *s1, *s2;
128 return !strcmp(skip(s1), skip(s2));
131 void show(line, count)
132 char *line;
133 int count;
135 if (cflag)
136 printf("%4d %s", count, line);
137 else {
138 if ((uflag && count == 1) || (dflag && count != 1))
139 printf("%s", line);
143 /* The meat of the whole affair */
144 char *nowline, *prevline, buf1[1024], buf2[1024];
146 int uniq()
148 char *p;
149 int seen;
151 /* Setup */
152 prevline = buf1;
153 if (getline(prevline, 1024) < 0) return(0);
154 seen = 1;
155 nowline = buf2;
157 /* Get nowline and compare if not equal, dump prevline and swap
158 * pointers else continue, bumping seen count */
159 while (getline(nowline, 1024) > 0) {
160 if (!equal(prevline, nowline)) {
161 show(prevline, seen);
162 seen = 1;
163 p = nowline;
164 nowline = prevline;
165 prevline = p;
166 } else
167 seen += 1;
169 show(prevline, seen);
170 return 0;
173 void usage()
175 fprintf(stderr, "Usage: uniq [-udc] [+n] [-n] [input [output]]\n");
178 int getline(buf, count)
179 char *buf;
180 int count;
182 int c;
183 int ct = 0;
185 while (ct++ < count) {
186 c = getc(stdin);
187 if (c < 0) return(-1);
188 *buf++ = c;
189 if (c == '\n') {
190 *buf++ = 0;
191 return(ct);
194 return(ct);