#include "gbos.h" /* uniq [-c] [file]: collapse runs of identical ADJACENT lines (like uniq(1) - * it does not sort). -c prefixes each line with how many times it repeated. */ #define MAXLINE 80 static unsigned char lines_eq(const char *a, unsigned char la, const char *b, unsigned char lb) { unsigned char i; if (la != lb) return 0; for (i = 0; i < la; i++) if (a[i] != b[i]) return 0; return 1; } void main(void) { char *argv[4]; char cur[MAXLINE], prev[MAXLINE]; unsigned char argc = argv_parse(argv, 4); unsigned char cnt = hasflag(argv, argc, 'c'); unsigned char clen = 0, plen = 0, have = 0, fd = NOFD, i; unsigned int reps = 0; char *fname = 0; int ch; for (i = 0; i < argc; i++) if (argv[i][0] != '-') { fname = argv[i]; break; } if (fname) { fd = open(fname, O_READ); if (fd == EISDIR) { puts("uniq: is a directory"); nl(); sexit(2); } if (fd == NOFD) { puts("uniq: no such file"); nl(); sexit(2); } } for (;;) { if (fd == NOFD) { char c = readc(); ch = (c == EOF) ? -1 : c; } else ch = fgetc(fd); if (ch == '\r') continue; if (ch >= 0 && ch != '\n') { if (clen < MAXLINE) cur[clen++] = (char)ch; continue; } /* EOF with nothing buffered: stop. Falling through would compare an empty "line" against the last run and flush a phantom blank one - which showed up as a stray "1" in uniq -c. */ if (ch < 0 && clen == 0) break; if (have && lines_eq(cur, clen, prev, plen)) reps++; else { if (have) { /* flush the run that just ended */ if (cnt) { putu(reps); putc(' '); } writes(prev, plen); nl(); } for (i = 0; i < clen; i++) prev[i] = cur[i]; plen = clen; have = 1; reps = 1; } clen = 0; if (ch < 0) break; } if (have) { if (cnt) { putu(reps); putc(' '); } writes(prev, plen); nl(); } if (fd != NOFD) close(fd); }