sbase

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

commit 2d9d224a1b69231edabfa014f738ed2c73dd6eb3
parent ada69106b7c458f620d99f2e9e69d26a64b1ba95
Author: Jakob Kramer <jakob.kramer@gmx.de>
Date:   Sun,  1 Feb 2015 21:00:37 +0100

sort: add support for delimiter strings

Instead of just single characters.  This also fixes
some bugs in columns().  Example bug:

	$ printf "a b\nc b x\n" | sort -k 2,2 -k 1,1

Diffstat:
Msort.c | 51+++++++++++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 24 deletions(-)

diff --git a/sort.c b/sort.c @@ -33,10 +33,11 @@ static struct kdlist *tail = NULL; static void addkeydef(char *, int); static void check(FILE *); static int linecmp(const char **, const char **); -static char *skipblank(char *); static int parse_flags(char **, int *, int); static int parse_keydef(struct keydef *, char *, int); -static char *nextcol(char *); +static char *skipblank(char *); +static char *skipnonblank(char *); +static char *skipcolumn(char *, char *, int); static char *columns(char *, const struct keydef *); static int Cflag = 0, cflag = 0, uflag = 0; @@ -173,24 +174,30 @@ parse_keydef(struct keydef *kd, char *s, int flags) static char * skipblank(char *s) { - while (*s && isblank(*s)) + while (isblank(*s)) s++; + return s; +} +static char * +skipnonblank(char *s) +{ + while (*s && *s != '\n' && !isblank(*s)) + s++; return s; } static char * -nextcol(char *s) +skipcolumn(char *s, char *eol, int next_col) { - if (!fieldsep) { - s = skipblank(s); - while (*s && !isblank(*s)) - s++; - } else { - if (!strchr(s, *fieldsep)) - s = strchr(s, '\0'); + if (fieldsep) { + if ((s = strstr(s, fieldsep))) + s += next_col ? strlen(fieldsep) : 0; else - s = strchr(s, *fieldsep) + 1; + s = eol; + } else { + s = skipblank(s); + s = skipnonblank(s); } return s; } @@ -198,30 +205,28 @@ nextcol(char *s) static char * columns(char *line, const struct keydef *kd) { - char *start, *end; + char *start, *end, *eol = strchr(line, '\n'); int i; for (i = 1, start = line; i < kd->start_column; i++) - start = nextcol(start); + start = skipcolumn(start, eol, 1); if (kd->flags & MOD_STARTB) start = skipblank(start); - start += MIN(kd->start_char, nextcol(start) - start) - 1; + start = MIN(eol, start + kd->start_char - 1); if (kd->end_column) { for (i = 1, end = line; i < kd->end_column; i++) - end = nextcol(end); + end = skipcolumn(end, eol, 1); if (kd->flags & MOD_ENDB) end = skipblank(end); if (kd->end_char) - end += MIN(kd->end_char, nextcol(end) - end); + end = MIN(eol, end + kd->end_char); else - end = nextcol(end); + end = skipcolumn(end, eol, 0); } else { - if (!(end = strchr(line, '\n'))) - end = strchr(line, '\0'); + end = eol; } - - return enstrndup(2, start, end - start); + return enstrndup(2, start, start > end ? 0 : end - start); } static void @@ -270,8 +275,6 @@ main(int argc, char *argv[]) break; case 't': fieldsep = EARGF(usage()); - if (strlen(fieldsep) != 1) - usage(); break; case 'u': uflag = 1;