commit 51390a3c51189783b8a55635d1097a58c2f60352
parent 0a2562e9949df7e6f5c4f43171aaf5ccf7ba7943
Author: FRIGN <dev@frign.de>
Date: Tue, 4 Aug 2015 12:45:59 +0200
Audit sort(1) and mark it as finished
1) Remove the function prototypes. No need for them, as the
functions are ordered.
2) Add fieldseplen, so the length of the field-separator is not
calculated nearly each time skipcolumn() is called.
3) rename next_col to skip_to_next_col so the purpose is clear,
also reorder the conditional accordingly.
4) Put parentheses around certain ternary expressions.
5) BUGFIX: Don't just exit() in check(), but make it return something,
so we can cleanly fshut() everything.
6) OFF-POSIX: Posix for no apparent reason does not allow more than
one file when the -c or -C flags are given.
This can be problematic when you want to check multiple files.
With the change 5), rewriting check() to return a value, I went
off-posix after discussing this with Dimitris to just allow
arbitrary numbers of files. Obviously, this does not break scripts
and is convenient for everybody who wants to quickly check a big
amount of files.
As soon as 1 file is "unsorted", the return value is 1, as expected.
For convenience reasons, check()'s warning now includes the filename.
7) BUGFIX: Set ret to 2 instead of 1 when the fshut(fp, *argv) fails.
8) BUGFIX: Don't forget to fshut stderr at the end. This would improperly
return 1 in the following case:
$ sort -c unsorted_file 2> /dev/full
9) Other style changes, line length, empty line before return.
Diffstat:
M | README | | | 2 | +- |
M | sort.c | | | 64 | ++++++++++++++++++++++++++++++++++++---------------------------- |
2 files changed, 37 insertions(+), 29 deletions(-)
diff --git a/README b/README
@@ -69,7 +69,7 @@ The following tools are implemented:
=*|x sha256sum .
=*|x sha512sum .
=*|o sleep .
-# sort (-d, -f, -i)
+#*|o sort (-d, -f, -i)
=*|o split .
=*|x sponge .
#*|o strings .
diff --git a/sort.c b/sort.c
@@ -27,17 +27,9 @@ enum {
static TAILQ_HEAD(kdhead, keydef) kdhead = TAILQ_HEAD_INITIALIZER(kdhead);
-static char *skipblank(char *);
-static char *skipnonblank(char *);
-static char *skipcolumn(char *, char *, int);
-static size_t columns(char *, const struct keydef *, char **, size_t *);
-static int linecmp(const char **, const char **);
-static void check(FILE *);
-static int parse_flags(char **, int *, int);
-static void addkeydef(char *, int);
-
static int Cflag = 0, cflag = 0, uflag = 0;
static char *fieldsep = NULL;
+static size_t fieldseplen = 0;
static char *col1, *col2;
static size_t col1siz, col2siz;
@@ -46,6 +38,7 @@ skipblank(char *s)
{
while (*s == ' ' || *s == '\t')
s++;
+
return s;
}
@@ -54,21 +47,25 @@ skipnonblank(char *s)
{
while (*s && *s != '\n' && *s != ' ' && *s != '\t')
s++;
+
return s;
}
static char *
-skipcolumn(char *s, char *eol, int next_col)
+skipcolumn(char *s, char *eol, int skip_to_next_col)
{
if (fieldsep) {
- if ((s = strstr(s, fieldsep)))
- s += next_col ? strlen(fieldsep) : 0;
- else
+ if ((s = strstr(s, fieldsep))) {
+ if (skip_to_next_col)
+ s += fieldseplen;
+ } else {
s = eol;
+ }
} else {
s = skipblank(s);
s = skipnonblank(s);
}
+
return s;
}
@@ -107,13 +104,14 @@ columns(char *line, const struct keydef *kd, char **col, size_t *colsiz)
} else {
end = eol;
}
- len = start > end ? 0 : end - start;
+ len = (start > end) ? 0 : (end - start);
if (!*col || *colsiz < len)
*col = erealloc(*col, len + 1);
memcpy(*col, start, len);
(*col)[len] = '\0';
if (*colsiz < len)
*colsiz = len;
+
return len;
}
@@ -136,7 +134,7 @@ linecmp(const char **a, const char **b)
} else if (kd->flags & MOD_N) {
x = strtold(col1, NULL);
y = strtold(col2, NULL);
- res = (x < y) ? (-1) : (x > y);
+ res = (x < y) ? -1 : (x > y);
} else {
res = strcmp(col1, col2);
}
@@ -150,23 +148,26 @@ linecmp(const char **a, const char **b)
return res;
}
-static void
-check(FILE *fp)
+static int
+check(FILE *fp, const char *fname)
{
static struct { char *buf; size_t size; } prev, cur, tmp;
if (!prev.buf && getline(&prev.buf, &prev.size, fp) < 0)
eprintf("getline:");
while (getline(&cur.buf, &cur.size, fp) > 0) {
- if (uflag > linecmp((const char **) &cur.buf, (const char **) &prev.buf)) {
+ if (uflag > linecmp((const char **)&cur.buf,
+ (const char **)&prev.buf)) {
if (!Cflag)
- weprintf("disorder: %s", cur.buf);
- exit(1);
+ weprintf("disorder %s: %s", fname, cur.buf);
+ return 1;
}
tmp = cur;
cur = prev;
prev = tmp;
}
+
+ return 0;
}
static int
@@ -212,7 +213,8 @@ addkeydef(char *kdstr, int flags)
if (*kdstr == '.') {
if ((kd->start_char = strtol(kdstr + 1, &kdstr, 10)) < 1)
- enprintf(2, "invalid start character in key definition\n");
+ enprintf(2, "invalid start character in key "
+ "definition\n");
}
if (parse_flags(&kdstr, &kd->flags, MOD_STARTB) < 0)
enprintf(2, "invalid start flags in key definition\n");
@@ -222,7 +224,8 @@ addkeydef(char *kdstr, int flags)
enprintf(2, "invalid end column in key definition\n");
if (*kdstr == '.') {
if ((kd->end_char = strtol(kdstr + 1, &kdstr, 10)) < 0)
- enprintf(2, "invalid end character in key definition\n");
+ enprintf(2, "invalid end character in key "
+ "definition\n");
}
if (parse_flags(&kdstr, &kd->flags, MOD_ENDB) < 0)
enprintf(2, "invalid end flags in key definition\n");
@@ -281,6 +284,7 @@ main(int argc, char *argv[])
break;
case 't':
fieldsep = EARGF(usage());
+ fieldseplen = strlen(fieldsep);
break;
case 'u':
uflag = 1;
@@ -296,7 +300,8 @@ main(int argc, char *argv[])
if (!argc) {
if (Cflag || cflag) {
- check(stdin);
+ if (check(stdin, "<stdin>") && !ret)
+ ret = 1;
} else {
getlines(stdin, &linebuf);
}
@@ -309,12 +314,13 @@ main(int argc, char *argv[])
continue;
}
if (Cflag || cflag) {
- check(fp);
+ if (check(fp, *argv) && !ret)
+ ret = 1;
} else {
getlines(fp, &linebuf);
}
if (fp != stdin && fshut(fp, *argv))
- ret = 1;
+ ret = 2;
}
if (!Cflag && !cflag) {
@@ -325,14 +331,16 @@ main(int argc, char *argv[])
(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])) {
+ if (!uflag || i == 0 ||
+ linecmp((const char **)&linebuf.lines[i],
+ (const char **)&linebuf.lines[i - 1])) {
fputs(linebuf.lines[i], ofp);
}
}
}
- if (fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"))
+ if (fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>") |
+ fshut(stderr, "<stderr>"))
ret = 2;
return ret;