sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

commit cb427d553af31c30c1c1ca0c1490374fee1b6cdb
parent e23d20e1d401bd65bab93c0cfefaf2b88d4e56e8
Author: Michael Forney <mforney@mforney.org>
Date:   Sun, 23 Nov 2014 19:35:56 +0000

sort: Implement -c and -C flags

Diffstat:
Msort.1 | 11+++++++++++
Msort.c | 57+++++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/sort.1 b/sort.1 @@ -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 @@ -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 *); @@ -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 @@ -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; @@ -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); + } } } @@ -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;