|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Case Larsen.
7: *
8: * Redistribution and use in source and binary forms are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: char copyright[] =
25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
26: All rights reserved.\n";
27: #endif /* not lint */
28:
29: #ifndef lint
30: static char sccsid[] = "@(#)uniq.c 5.2 (Berkeley) 6/1/90";
31: #endif /* not lint */
32:
33: #include <stdio.h>
34: #include <ctype.h>
35:
36: int cflag, dflag, uflag;
37: int numchars, numfields, repeats;
38:
39: #define MAXLINELEN (2048 + 1)
40:
41: main (argc,argv)
42: int argc;
43: char **argv;
44: {
45: extern int optind;
46: FILE *ifp, *ofp, *file();
47: int ch;
48: register char *t1, *t2;
49: char *prevline, *thisline, *malloc(), *skip();
50:
51: while ((ch = getopt(argc, argv, "-cdu123456789")) != EOF)
52: switch (ch) {
53: case '-':
54: --optind;
55: goto done;
56: case 'c':
57: cflag = 1;
58: break;
59: case 'd':
60: dflag = 1;
61: break;
62: case 'u':
63: uflag = 1;
64: break;
65: /*
66: * since -n is a valid option that could be picked up by
67: * getopt, but is better handled by the +n and -n code, we
68: * break out.
69: */
70: case '1': case '2': case '3': case '4':
71: case '5': case '6': case '7': case '8': case '9':
72: --optind;
73: goto done;
74: case '?':
75: default:
76: usage();
77: }
78:
79: done: argc -= optind;
80: argv +=optind;
81:
82: /* if no flags are set, default is -d -u */
83: if (cflag) {
84: if (dflag || uflag)
85: usage();
86: } else if (!dflag && !uflag)
87: dflag = uflag = 1;
88:
89: /* because of the +, getopt is messed up */
90: for (; **argv == '+' || **argv == '-'; ++argv, --argc)
91: switch (**argv) {
92: case '+':
93: if ((numchars = atoi(*argv + 1)) < 0)
94: goto negerr;
95: break;
96: case '-':
97: if ((numfields = atoi(*argv + 1)) < 0) {
98: negerr: (void)fprintf(stderr,
99: "uniq: negative field/char skip value.\n");
100: usage();
101: }
102: break;
103: }
104:
105: switch(argc) {
106: case 0:
107: ifp = stdin;
108: ofp = stdout;
109: break;
110: case 1:
111: ifp = file(argv[0], "r");
112: ofp = stdout;
113: break;
114: case 2:
115: ifp = file(argv[0], "r");
116: ofp = file(argv[1], "w");
117: break;
118: default:
119: usage();
120: }
121:
122: prevline = malloc(MAXLINELEN);
123: thisline = malloc(MAXLINELEN);
124: (void)fgets(prevline, MAXLINELEN, ifp);
125:
126: while (fgets(thisline, MAXLINELEN, ifp)) {
127: /* if requested get the chosen fields + character offsets */
128: if (numfields || numchars) {
129: t1 = skip(thisline);
130: t2 = skip(prevline);
131: } else {
132: t1 = thisline;
133: t2 = prevline;
134: }
135:
136: /* if different, print; set previous to new value */
137: if (strcmp(t1, t2)) {
138: show(ofp, prevline);
139: t1 = prevline;
140: prevline = thisline;
141: thisline = t1;
142: repeats = 0;
143: }
144: else
145: ++repeats;
146: }
147: show(ofp, prevline);
148: exit(0);
149: }
150:
151: /*
152: * show --
153: * output a line depending on the flags and number of repetitions
154: * of the line.
155: */
156: show(ofp, str)
157: FILE *ofp;
158: char *str;
159: {
160: if (cflag)
161: (void)fprintf(ofp, "%4d %s", repeats + 1, str);
162: if (dflag && repeats || uflag && !repeats)
163: (void)fprintf(ofp, "%s", str);
164: }
165:
166: char *
167: skip(str)
168: register char *str;
169: {
170: register int infield, nchars, nfields;
171:
172: for (nfields = numfields, infield = 0; nfields && *str; ++str)
173: if (isspace(*str)) {
174: if (infield) {
175: infield = 0;
176: --nfields;
177: }
178: } else if (!infield)
179: infield = 1;
180: for (nchars = numchars; nchars-- && *str; ++str);
181: return(str);
182: }
183:
184: FILE *
185: file(name, mode)
186: char *name, *mode;
187: {
188: FILE *fp;
189:
190: if (!(fp = fopen(name, mode))) {
191: (void)fprintf(stderr, "uniq: can't open %s.\n", name);
192: exit(1);
193: }
194: return(fp);
195: }
196:
197: usage()
198: {
199: (void)fprintf(stderr,
200: "usage: uniq [-c | -du] [- #fields] [+ #chars] [input [output]]\n");
201: exit(1);
202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.