Annotation of src/usr.bin/uniq/uniq.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: uniq.c,v 1.7 1995/08/31 22:03:48 jtc Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1989, 1993
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * This code is derived from software contributed to Berkeley by
! 8: * Case Larsen.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed by the University of
! 21: * California, Berkeley and its contributors.
! 22: * 4. Neither the name of the University nor the names of its contributors
! 23: * may be used to endorse or promote products derived from this software
! 24: * without specific prior written permission.
! 25: *
! 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 36: * SUCH DAMAGE.
! 37: */
! 38:
! 39: #ifndef lint
! 40: static char copyright[] =
! 41: "@(#) Copyright (c) 1989, 1993\n\
! 42: The Regents of the University of California. All rights reserved.\n";
! 43: #endif /* not lint */
! 44:
! 45: #ifndef lint
! 46: #if 0
! 47: static char sccsid[] = "@(#)uniq.c 8.3 (Berkeley) 5/4/95";
! 48: #endif
! 49: static char rcsid[] = "$NetBSD: uniq.c,v 1.7 1995/08/31 22:03:48 jtc Exp $";
! 50: #endif /* not lint */
! 51:
! 52: #include <errno.h>
! 53: #include <stdio.h>
! 54: #include <ctype.h>
! 55: #include <stdlib.h>
! 56: #include <string.h>
! 57: #include <unistd.h>
! 58:
! 59: #define MAXLINELEN (8 * 1024)
! 60:
! 61: int cflag, dflag, uflag;
! 62: int numchars, numfields, repeats;
! 63:
! 64: void err __P((const char *, ...));
! 65: FILE *file __P((char *, char *));
! 66: void show __P((FILE *, char *));
! 67: char *skip __P((char *));
! 68: void obsolete __P((char *[]));
! 69: void usage __P((void));
! 70:
! 71: int
! 72: main (argc, argv)
! 73: int argc;
! 74: char *argv[];
! 75: {
! 76: register char *t1, *t2;
! 77: FILE *ifp, *ofp;
! 78: int ch;
! 79: char *prevline, *thisline, *p;
! 80:
! 81: obsolete(argv);
! 82: while ((ch = getopt(argc, argv, "-cdf:s:u")) != EOF)
! 83: switch (ch) {
! 84: case '-':
! 85: --optind;
! 86: goto done;
! 87: case 'c':
! 88: cflag = 1;
! 89: break;
! 90: case 'd':
! 91: dflag = 1;
! 92: break;
! 93: case 'f':
! 94: numfields = strtol(optarg, &p, 10);
! 95: if (numfields < 0 || *p)
! 96: err("illegal field skip value: %s", optarg);
! 97: break;
! 98: case 's':
! 99: numchars = strtol(optarg, &p, 10);
! 100: if (numchars < 0 || *p)
! 101: err("illegal character skip value: %s", optarg);
! 102: break;
! 103: case 'u':
! 104: uflag = 1;
! 105: break;
! 106: case '?':
! 107: default:
! 108: usage();
! 109: }
! 110:
! 111: done: argc -= optind;
! 112: argv +=optind;
! 113:
! 114: /* If no flags are set, default is -d -u. */
! 115: if (cflag) {
! 116: if (dflag || uflag)
! 117: usage();
! 118: } else if (!dflag && !uflag)
! 119: dflag = uflag = 1;
! 120:
! 121: switch(argc) {
! 122: case 0:
! 123: ifp = stdin;
! 124: ofp = stdout;
! 125: break;
! 126: case 1:
! 127: ifp = file(argv[0], "r");
! 128: ofp = stdout;
! 129: break;
! 130: case 2:
! 131: ifp = file(argv[0], "r");
! 132: ofp = file(argv[1], "w");
! 133: break;
! 134: default:
! 135: usage();
! 136: }
! 137:
! 138: prevline = malloc(MAXLINELEN);
! 139: thisline = malloc(MAXLINELEN);
! 140: if (prevline == NULL || thisline == NULL)
! 141: err("%s", strerror(errno));
! 142:
! 143: if (fgets(prevline, MAXLINELEN, ifp) == NULL)
! 144: exit(0);
! 145:
! 146: while (fgets(thisline, MAXLINELEN, ifp)) {
! 147: /* If requested get the chosen fields + character offsets. */
! 148: if (numfields || numchars) {
! 149: t1 = skip(thisline);
! 150: t2 = skip(prevline);
! 151: } else {
! 152: t1 = thisline;
! 153: t2 = prevline;
! 154: }
! 155:
! 156: /* If different, print; set previous to new value. */
! 157: if (strcmp(t1, t2)) {
! 158: show(ofp, prevline);
! 159: t1 = prevline;
! 160: prevline = thisline;
! 161: thisline = t1;
! 162: repeats = 0;
! 163: } else
! 164: ++repeats;
! 165: }
! 166: show(ofp, prevline);
! 167: exit(0);
! 168: }
! 169:
! 170: /*
! 171: * show --
! 172: * Output a line depending on the flags and number of repetitions
! 173: * of the line.
! 174: */
! 175: void
! 176: show(ofp, str)
! 177: FILE *ofp;
! 178: char *str;
! 179: {
! 180:
! 181: if (cflag && *str)
! 182: (void)fprintf(ofp, "%4d %s", repeats + 1, str);
! 183: if (dflag && repeats || uflag && !repeats)
! 184: (void)fprintf(ofp, "%s", str);
! 185: }
! 186:
! 187: char *
! 188: skip(str)
! 189: register char *str;
! 190: {
! 191: register int infield, nchars, nfields;
! 192:
! 193: for (nfields = numfields, infield = 0; nfields && *str; ++str)
! 194: if (isspace(*str)) {
! 195: if (infield) {
! 196: infield = 0;
! 197: --nfields;
! 198: }
! 199: } else if (!infield)
! 200: infield = 1;
! 201: for (nchars = numchars; nchars-- && *str; ++str);
! 202: return(str);
! 203: }
! 204:
! 205: FILE *
! 206: file(name, mode)
! 207: char *name, *mode;
! 208: {
! 209: FILE *fp;
! 210:
! 211: if ((fp = fopen(name, mode)) == NULL)
! 212: err("%s: %s", name, strerror(errno));
! 213: return(fp);
! 214: }
! 215:
! 216: void
! 217: obsolete(argv)
! 218: char *argv[];
! 219: {
! 220: int len;
! 221: char *ap, *p, *start;
! 222:
! 223: while (ap = *++argv) {
! 224: /* Return if "--" or not an option of any form. */
! 225: if (ap[0] != '-') {
! 226: if (ap[0] != '+')
! 227: return;
! 228: } else if (ap[1] == '-')
! 229: return;
! 230: if (!isdigit(ap[1]))
! 231: continue;
! 232: /*
! 233: * Digit signifies an old-style option. Malloc space for dash,
! 234: * new option and argument.
! 235: */
! 236: len = strlen(ap);
! 237: if ((start = p = malloc(len + 3)) == NULL)
! 238: err("%s", strerror(errno));
! 239: *p++ = '-';
! 240: *p++ = ap[0] == '+' ? 's' : 'f';
! 241: (void)strcpy(p, ap + 1);
! 242: *argv = start;
! 243: }
! 244: }
! 245:
! 246: void
! 247: usage()
! 248: {
! 249: (void)fprintf(stderr,
! 250: "usage: uniq [-c | -du] [-f fields] [-s chars] [input [output]]\n");
! 251: exit(1);
! 252: }
! 253:
! 254: #if __STDC__
! 255: #include <stdarg.h>
! 256: #else
! 257: #include <varargs.h>
! 258: #endif
! 259:
! 260: void
! 261: #if __STDC__
! 262: err(const char *fmt, ...)
! 263: #else
! 264: err(fmt, va_alist)
! 265: char *fmt;
! 266: va_dcl
! 267: #endif
! 268: {
! 269: va_list ap;
! 270: #if __STDC__
! 271: va_start(ap, fmt);
! 272: #else
! 273: va_start(ap);
! 274: #endif
! 275: (void)fprintf(stderr, "uniq: ");
! 276: (void)vfprintf(stderr, fmt, ap);
! 277: va_end(ap);
! 278: (void)fprintf(stderr, "\n");
! 279: exit(1);
! 280: /* NOTREACHED */
! 281: }