| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: uniq.c,v 1.18 2012/08/26 14:14:16 wiz Exp $ */ | | 1 | /* $NetBSD: uniq.c,v 1.19 2016/10/14 19:43:59 abhinav Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1989, 1993 | | 4 | * Copyright (c) 1989, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Case Larsen. | | 8 | * Case Larsen. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -32,54 +32,55 @@ | | | @@ -32,54 +32,55 @@ |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | #ifndef lint | | 36 | #ifndef lint |
37 | __COPYRIGHT("@(#) Copyright (c) 1989, 1993\ | | 37 | __COPYRIGHT("@(#) Copyright (c) 1989, 1993\ |
38 | The Regents of the University of California. All rights reserved."); | | 38 | The Regents of the University of California. All rights reserved."); |
39 | #endif /* not lint */ | | 39 | #endif /* not lint */ |
40 | | | 40 | |
41 | #ifndef lint | | 41 | #ifndef lint |
42 | #if 0 | | 42 | #if 0 |
43 | static char sccsid[] = "@(#)uniq.c 8.3 (Berkeley) 5/4/95"; | | 43 | static char sccsid[] = "@(#)uniq.c 8.3 (Berkeley) 5/4/95"; |
44 | #endif | | 44 | #endif |
45 | __RCSID("$NetBSD: uniq.c,v 1.18 2012/08/26 14:14:16 wiz Exp $"); | | 45 | __RCSID("$NetBSD: uniq.c,v 1.19 2016/10/14 19:43:59 abhinav Exp $"); |
46 | #endif /* not lint */ | | 46 | #endif /* not lint */ |
47 | | | 47 | |
48 | #include <err.h> | | 48 | #include <err.h> |
49 | #include <errno.h> | | 49 | #include <errno.h> |
50 | #include <stdio.h> | | 50 | #include <stdio.h> |
51 | #include <ctype.h> | | 51 | #include <ctype.h> |
52 | #include <stdlib.h> | | 52 | #include <stdlib.h> |
53 | #include <string.h> | | 53 | #include <string.h> |
54 | #include <unistd.h> | | 54 | #include <unistd.h> |
55 | | | 55 | |
56 | static int cflag, dflag, uflag; | | 56 | static int cflag, dflag, uflag; |
57 | static int numchars, numfields, repeats; | | 57 | static int numchars, numfields, repeats; |
58 | | | 58 | |
59 | static FILE *file(const char *, const char *); | | 59 | static FILE *file(const char *, const char *); |
60 | static void show(FILE *, const char *); | | 60 | static void show(FILE *, const char *); |
61 | static const char *skip(const char *); | | 61 | static const char *skip(const char *, size_t *); |
62 | static void obsolete(char *[]); | | 62 | static void obsolete(char *[]); |
63 | static void usage(void) __dead; | | 63 | static void usage(void) __dead; |
64 | | | 64 | |
65 | int | | 65 | int |
66 | main (int argc, char *argv[]) | | 66 | main (int argc, char *argv[]) |
67 | { | | 67 | { |
68 | const char *t1, *t2; | | 68 | const char *t1, *t2; |
69 | FILE *ifp, *ofp; | | 69 | FILE *ifp, *ofp; |
70 | int ch; | | 70 | int ch; |
71 | char *prevline, *thisline, *p; | | 71 | char *prevline, *thisline, *p; |
72 | size_t prevlinesize, thislinesize, psize; | | 72 | size_t prevlinesize, thislinesize, psize; |
| | | 73 | size_t prevlinecompsize, thislinecompsize; |
73 | | | 74 | |
74 | setprogname(argv[0]); | | 75 | setprogname(argv[0]); |
75 | ifp = ofp = NULL; | | 76 | ifp = ofp = NULL; |
76 | obsolete(argv); | | 77 | obsolete(argv); |
77 | while ((ch = getopt(argc, argv, "-cdf:s:u")) != -1) | | 78 | while ((ch = getopt(argc, argv, "-cdf:s:u")) != -1) |
78 | switch (ch) { | | 79 | switch (ch) { |
79 | case '-': | | 80 | case '-': |
80 | --optind; | | 81 | --optind; |
81 | goto done; | | 82 | goto done; |
82 | case 'c': | | 83 | case 'c': |
83 | cflag = 1; | | 84 | cflag = 1; |
84 | break; | | 85 | break; |
85 | case 'd': | | 86 | case 'd': |
| @@ -134,38 +135,40 @@ done: argc -= optind; | | | @@ -134,38 +135,40 @@ done: argc -= optind; |
134 | | | 135 | |
135 | thislinesize = psize; | | 136 | thislinesize = psize; |
136 | if ((thisline = malloc(thislinesize + 1)) == NULL) | | 137 | if ((thisline = malloc(thislinesize + 1)) == NULL) |
137 | err(1, "malloc"); | | 138 | err(1, "malloc"); |
138 | | | 139 | |
139 | while ((p = fgetln(ifp, &psize)) != NULL) { | | 140 | while ((p = fgetln(ifp, &psize)) != NULL) { |
140 | if (psize > thislinesize) { | | 141 | if (psize > thislinesize) { |
141 | if ((thisline = realloc(thisline, psize + 1)) == NULL) | | 142 | if ((thisline = realloc(thisline, psize + 1)) == NULL) |
142 | err(1, "realloc"); | | 143 | err(1, "realloc"); |
143 | thislinesize = psize; | | 144 | thislinesize = psize; |
144 | } | | 145 | } |
145 | (void)memcpy(thisline, p, psize); | | 146 | (void)memcpy(thisline, p, psize); |
146 | thisline[psize] = '\0'; | | 147 | thisline[psize] = '\0'; |
| | | 148 | thislinecompsize = thislinesize; |
| | | 149 | prevlinecompsize = prevlinesize; |
147 | | | 150 | |
148 | /* If requested get the chosen fields + character offsets. */ | | 151 | /* If requested get the chosen fields + character offsets. */ |
149 | if (numfields || numchars) { | | 152 | if (numfields || numchars) { |
150 | t1 = skip(thisline); | | 153 | t1 = skip(thisline, &thislinecompsize); |
151 | t2 = skip(prevline); | | 154 | t2 = skip(prevline, &prevlinecompsize); |
152 | } else { | | 155 | } else { |
153 | t1 = thisline; | | 156 | t1 = thisline; |
154 | t2 = prevline; | | 157 | t2 = prevline; |
155 | } | | 158 | } |
156 | | | 159 | |
157 | /* If different, print; set previous to new value. */ | | 160 | /* If different, print; set previous to new value. */ |
158 | if (strcmp(t1, t2)) { | | 161 | if (thislinecompsize != prevlinecompsize || strcmp(t1, t2)) { |
159 | char *t; | | 162 | char *t; |
160 | size_t ts; | | 163 | size_t ts; |
161 | | | 164 | |
162 | show(ofp, prevline); | | 165 | show(ofp, prevline); |
163 | t = prevline; | | 166 | t = prevline; |
164 | prevline = thisline; | | 167 | prevline = thisline; |
165 | thisline = t; | | 168 | thisline = t; |
166 | ts = prevlinesize; | | 169 | ts = prevlinesize; |
167 | prevlinesize = thislinesize; | | 170 | prevlinesize = thislinesize; |
168 | thislinesize = ts; | | 171 | thislinesize = ts; |
169 | repeats = 0; | | 172 | repeats = 0; |
170 | } else | | 173 | } else |
171 | ++repeats; | | 174 | ++repeats; |
| @@ -185,40 +188,42 @@ static void | | | @@ -185,40 +188,42 @@ static void |
185 | show(FILE *ofp, const char *str) | | 188 | show(FILE *ofp, const char *str) |
186 | { | | 189 | { |
187 | | | 190 | |
188 | if ((dflag && repeats == 0) || (uflag && repeats > 0)) | | 191 | if ((dflag && repeats == 0) || (uflag && repeats > 0)) |
189 | return; | | 192 | return; |
190 | if (cflag) { | | 193 | if (cflag) { |
191 | (void)fprintf(ofp, "%4d %s", repeats + 1, str); | | 194 | (void)fprintf(ofp, "%4d %s", repeats + 1, str); |
192 | } else { | | 195 | } else { |
193 | (void)fprintf(ofp, "%s", str); | | 196 | (void)fprintf(ofp, "%s", str); |
194 | } | | 197 | } |
195 | } | | 198 | } |
196 | | | 199 | |
197 | static const char * | | 200 | static const char * |
198 | skip(const char *str) | | 201 | skip(const char *str, size_t *linesize) |
199 | { | | 202 | { |
200 | int infield, nchars, nfields; | | 203 | int infield, nchars, nfields; |
| | | 204 | size_t ls = *linesize; |
201 | | | 205 | |
202 | for (nfields = numfields, infield = 0; nfields && *str; ++str) | | 206 | for (nfields = numfields, infield = 0; nfields && *str; ++str, --ls) |
203 | if (isspace((unsigned char)*str)) { | | 207 | if (isspace((unsigned char)*str)) { |
204 | if (infield) { | | 208 | if (infield) { |
205 | infield = 0; | | 209 | infield = 0; |
206 | --nfields; | | 210 | --nfields; |
207 | } | | 211 | } |
208 | } else if (!infield) | | 212 | } else if (!infield) |
209 | infield = 1; | | 213 | infield = 1; |
210 | for (nchars = numchars; nchars-- && *str; ++str) | | 214 | for (nchars = numchars; nchars-- && *str; ++str, --ls) |
211 | continue; | | 215 | continue; |
| | | 216 | *linesize = ls; |
212 | return str; | | 217 | return str; |
213 | } | | 218 | } |
214 | | | 219 | |
215 | static FILE * | | 220 | static FILE * |
216 | file(const char *name, const char *mode) | | 221 | file(const char *name, const char *mode) |
217 | { | | 222 | { |
218 | FILE *fp; | | 223 | FILE *fp; |
219 | | | 224 | |
220 | if ((fp = fopen(name, mode)) == NULL) | | 225 | if ((fp = fopen(name, mode)) == NULL) |
221 | err(1, "%s", name); | | 226 | err(1, "%s", name); |
222 | return(fp); | | 227 | return(fp); |
223 | } | | 228 | } |
224 | | | 229 | |