uniq.c (1581B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <unistd.h> 6 7 #include "text.h" 8 #include "util.h" 9 10 static void uniqline(char *); 11 static void uniq(FILE *, const char *); 12 static void uniqfinish(void); 13 14 static const char *countfmt = ""; 15 static int dflag = 0; 16 static int uflag = 0; 17 18 static char *prevline = NULL; 19 static long prevlinecount = 0; 20 21 static void 22 usage(void) 23 { 24 eprintf("usage: %s [-cdiu] [input]]\n", argv0); 25 } 26 27 int 28 main(int argc, char *argv[]) 29 { 30 FILE *fp; 31 32 ARGBEGIN { 33 case 'i': 34 eprintf("not implemented\n"); 35 case 'c': 36 countfmt = "%7ld "; 37 break; 38 case 'd': 39 dflag = 1; 40 break; 41 case 'u': 42 uflag = 1; 43 break; 44 default: 45 usage(); 46 } ARGEND; 47 48 if (argc == 0) { 49 uniq(stdin, "<stdin>"); 50 } else if (argc == 1) { 51 if (!(fp = fopen(argv[0], "r"))) 52 eprintf("fopen %s:", argv[0]); 53 uniq(fp, argv[0]); 54 fclose(fp); 55 } else 56 usage(); 57 uniqfinish(); 58 59 return 0; 60 } 61 62 static void 63 uniqline(char *l) 64 { 65 int linesequel = (!l || !prevline) 66 ? l == prevline 67 : !strcmp(l, prevline); 68 69 if (linesequel) { 70 ++prevlinecount; 71 return; 72 } 73 74 if (prevline) { 75 if ((prevlinecount == 1 && !dflag) || 76 (prevlinecount != 1 && !uflag)) { 77 printf(countfmt, prevlinecount); 78 fputs(prevline, stdout); 79 } 80 free(prevline); 81 prevline = NULL; 82 } 83 84 if (l) 85 prevline = estrdup(l); 86 prevlinecount = 1; 87 } 88 89 static void 90 uniq(FILE *fp, const char *str) 91 { 92 char *buf = NULL; 93 size_t size = 0; 94 95 while (getline(&buf, &size, fp) != -1) 96 uniqline(buf); 97 } 98 99 static void 100 uniqfinish(void) 101 { 102 uniqline(NULL); 103 }