--- sort.1 | 11 +++++++++++ sort.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/sort.1 b/sort.1 index 12fb95d..71c8154 100644 --- a/sort.1 +++ b/sort.1 _AT_@ -15,9 +15,20 @@ writes the sorted concatenation of the given files to stdout. If no file is given, sort reads from stdin. .SH OPTIONS .TP +.B \-C +check that the concatenation of the given files is sorted rather than sorting +them. In this mode, no output is printed to stdout, and the exit status +indicates the result of the check. +.TP .B \-b skip leading whitespace of columns when sorting. .TP +.B \-c +the same as +.B \-C +except that when disorder is detected, a message is printed to stderr +indicating the location of the disorder. +.TP .BI \-k \ key specifies a key definition of the form .BR S [. s ][ f ][, E [. e ][ f ]] diff --git a/sort.c b/sort.c index 2a89870..c4cd81f 100644 --- a/sort.c +++ b/sort.c _AT_@ -32,6 +32,7 @@ static struct kdlist *head = NULL; static struct kdlist *tail = NULL; static void addkeydef(char *, int); +static void check(FILE *); static void freelist(void); static int linecmp(const char **, const char **); static char *skipblank(char *); _AT_@ -40,13 +41,13 @@ static int parse_keydef(struct keydef *, char *, int); static char *nextcol(char *); static char *columns(char *, const struct keydef *); -static int uflag = 0; +static int Cflag = 0, cflag = 0, uflag = 0; static char *fieldsep = NULL; static void usage(void) { - enprintf(2, "usage: %s [-bnru] [-t delim] [-k def]... [file...]\n", argv0); + enprintf(2, "usage: %s [-Cbcnru] [-t delim] [-k def]... [file...]\n", argv0); } int _AT_@ -58,9 +59,15 @@ main(int argc, char *argv[]) int global_flags = 0; ARGBEGIN { + case 'C': + Cflag = 1; + break; case 'b': global_flags |= MOD_STARTB | MOD_ENDB; break; + case 'c': + cflag = 1; + break; case 'k': addkeydef(EARGF(usage()), global_flags); break; _AT_@ -87,22 +94,33 @@ main(int argc, char *argv[]) addkeydef("1", global_flags & MOD_R); if (argc == 0) { - getlines(stdin, &linebuf); + if (Cflag || cflag) { + check(stdin); + } else { + getlines(stdin, &linebuf); + } } else for (; argc > 0; argc--, argv++) { if (!(fp = fopen(argv[0], "r"))) { enprintf(2, "fopen %s:", argv[0]); continue; } - getlines(fp, &linebuf); + if (Cflag || cflag) { + check(fp); + } else { + getlines(fp, &linebuf); + } fclose(fp); } - qsort(linebuf.lines, linebuf.nlines, sizeof *linebuf.lines, - (int (*)(const void *, const void *))linecmp); - for (i = 0; i < linebuf.nlines; i++) { - if (!uflag || i == 0 || linecmp((const char **)&linebuf.lines[i], - (const char **)&linebuf.lines[i-1])) { - fputs(linebuf.lines[i], stdout); + if (!Cflag && !cflag) { + qsort(linebuf.lines, linebuf.nlines, sizeof *linebuf.lines, + (int (*)(const void *, const void *))linecmp); + + for (i = 0; i < linebuf.nlines; i++) { + if (!uflag || i == 0 || linecmp((const char **)&linebuf.lines[i], + (const char **)&linebuf.lines[i-1])) { + fputs(linebuf.lines[i], stdout); + } } } _AT_@ -129,6 +147,25 @@ addkeydef(char *def, int flags) } static void +check(FILE *fp) +{ + static struct { char *buf; size_t size; } prev, cur, tmp; + + if (!prev.buf) + getline(&prev.buf, &prev.size, fp); + while (getline(&cur.buf, &cur.size, fp) != -1) { + if (uflag > linecmp((const char **) &cur.buf, (const char **) &prev.buf)) { + if (!Cflag) + weprintf("disorder: %s", cur.buf); + exit(1); + } + tmp = cur; + cur = prev; + prev = tmp; + } +} + +static void freelist(void) { struct kdlist *node; -- 2.1.3.1.g339ec9cReceived on Sun Nov 23 2014 - 20:35:56 CET
This archive was generated by hypermail 2.3.0 : Sun Nov 23 2014 - 20:48:08 CET