]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/uniq.c
delete old NOTICE file
[plan9front.git] / sys / src / cmd / uniq.c
1 /*
2  * Deal with duplicated lines in a file
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <bio.h>
7 #include <ctype.h>
8
9 int     fields  = 0;
10 int     letters = 0;
11 int     linec   = 0;
12 char    mode;
13 int     uniq;
14 char    *b1, *b2;
15 Biobuf  fin;
16 Biobuf  fout;
17
18 int     gline(char *buf);
19 void    pline(char *buf);
20 int     equal(char *b1, char *b2);
21 char*   skip(char *s);
22
23 void
24 main(int argc, char *argv[])
25 {
26         int f;
27
28         argv0 = argv[0];
29         b1 = malloc(Bsize);
30         b2 = malloc(Bsize);
31         f = 0;
32         while(argc > 1) {
33                 if(*argv[1] == '-') {
34                         if(isdigit(argv[1][1]))
35                                 fields = atoi(&argv[1][1]);
36                         else
37                                 mode = argv[1][1];
38                         argc--;
39                         argv++;
40                         continue;
41                 }
42                 if(*argv[1] == '+') {
43                         letters = atoi(&argv[1][1]);
44                         argc--;
45                         argv++;
46                         continue;
47                 }
48                 f = open(argv[1], 0);
49                 if(f < 0)
50                         sysfatal("cannot open %s", argv[1]);
51                 break;
52         }
53         if(argc > 2)
54                 sysfatal("unexpected argument %s", argv[2]);
55         Binit(&fin, f, OREAD);
56         Binit(&fout, 1, OWRITE);
57
58         if(gline(b1))
59                 exits(0);
60         for(;;) {
61                 linec++;
62                 if(gline(b2)) {
63                         pline(b1);
64                         exits(0);
65                 }
66                 if(!equal(b1, b2)) {
67                         pline(b1);
68                         linec = 0;
69                         do {
70                                 linec++;
71                                 if(gline(b1)) {
72                                         pline(b2);
73                                         exits(0);
74                                 }
75                         } while(equal(b2, b1));
76                         pline(b2);
77                         linec = 0;
78                 }
79         }
80 }
81
82 int
83 gline(char *buf)
84 {
85         int len;
86         char *p;
87
88         p = Brdline(&fin, '\n');
89         if(p == 0)
90                 return 1;
91         len = Blinelen(&fin);
92         if(len > Bsize)
93                 sysfatal("line too long");
94         memmove(buf, p, len);
95         buf[len-1] = 0;
96         return 0;
97 }
98
99 void
100 pline(char *buf)
101 {
102         switch(mode) {
103
104         case 'u':
105                 if(uniq) {
106                         uniq = 0;
107                         return;
108                 }
109                 break;
110
111         case 'd':
112                 if(uniq)
113                         break;
114                 return;
115
116         case 'c':
117                 Bprint(&fout, "%4d ", linec);
118         }
119         uniq = 0;
120         Bprint(&fout, "%s\n", buf);
121 }
122
123 int
124 equal(char *b1, char *b2)
125 {
126         char c;
127
128         if(fields || letters) {
129                 b1 = skip(b1);
130                 b2 = skip(b2);
131         }
132         for(;;) {
133                 c = *b1++;
134                 if(c != *b2++) {
135                         if(c == 0 && mode == 's')
136                                 return 1;
137                         return 0;
138                 }
139                 if(c == 0) {
140                         uniq++;
141                         return 1;
142                 }
143         }
144 }
145
146 char*
147 skip(char *s)
148 {
149         int nf, nl;
150
151         nf = nl = 0;
152         while(nf++ < fields) {
153                 while(*s == ' ' || *s == '\t')
154                         s++;
155                 while(!(*s == ' ' || *s == '\t' || *s == 0) ) 
156                         s++;
157         }
158         while(nl++ < letters && *s != 0) 
159                         s++;
160         return s;
161 }