Reorder functions in sort(1)
I kind of missed that the sorting was still not properly done. parse_flags() and addkeydef() are independent of everything else, so they can be put at the bottom. Sorting the other functions reveals the true hierarchy much better.master
parent
61ee561728
commit
1622089a21
242
sort.c
242
sort.c
|
@ -26,137 +26,20 @@ enum {
|
|||
|
||||
static TAILQ_HEAD(kdhead, keydef) kdhead = TAILQ_HEAD_INITIALIZER(kdhead);
|
||||
|
||||
static int parse_flags(char **, int *, int);
|
||||
static void addkeydef(char *, int);
|
||||
static int linecmp(const char **, const char **);
|
||||
static void check(FILE *);
|
||||
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 char *col1, *col2;
|
||||
static size_t col1siz, col2siz;
|
||||
|
||||
static int
|
||||
parse_flags(char **s, int *flags, int bflag)
|
||||
{
|
||||
while (isalpha((int)**s)) {
|
||||
switch (*((*s)++)) {
|
||||
case 'b':
|
||||
*flags |= bflag;
|
||||
break;
|
||||
case 'n':
|
||||
*flags |= MOD_N;
|
||||
break;
|
||||
case 'r':
|
||||
*flags |= MOD_R;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
addkeydef(char *kdstr, int flags)
|
||||
{
|
||||
struct keydef *kd;
|
||||
|
||||
kd = enmalloc(2, sizeof(*kd));
|
||||
|
||||
/* parse key definition kdstr with format
|
||||
* start_column[.start_char][flags][,end_column[.end_char][flags]]
|
||||
*/
|
||||
kd->start_column = 1;
|
||||
kd->start_char = 1;
|
||||
kd->end_column = 0; /* 0 means end of line */
|
||||
kd->end_char = 0; /* 0 means end of column */
|
||||
kd->flags = flags;
|
||||
|
||||
if ((kd->start_column = strtol(kdstr, &kdstr, 10)) < 1)
|
||||
enprintf(2, "invalid start column in key definition\n");
|
||||
|
||||
if (*kdstr == '.') {
|
||||
if ((kd->start_char = strtol(kdstr + 1, &kdstr, 10)) < 1)
|
||||
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");
|
||||
|
||||
if (*kdstr == ',') {
|
||||
if ((kd->end_column = strtol(kdstr + 1, &kdstr, 10)) < 0)
|
||||
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");
|
||||
}
|
||||
if (parse_flags(&kdstr, &kd->flags, MOD_ENDB) < 0)
|
||||
enprintf(2, "invalid end flags in key definition\n");
|
||||
}
|
||||
|
||||
if (*kdstr != '\0')
|
||||
enprintf(2, "invalid key definition\n");
|
||||
|
||||
TAILQ_INSERT_TAIL(&kdhead, kd, entry);
|
||||
}
|
||||
|
||||
static int
|
||||
linecmp(const char **a, const char **b)
|
||||
{
|
||||
int res = 0;
|
||||
long double x, y;
|
||||
struct keydef *kd;
|
||||
|
||||
TAILQ_FOREACH(kd, &kdhead, entry) {
|
||||
columns((char *)*a, kd, &col1, &col1siz);
|
||||
columns((char *)*b, kd, &col2, &col2siz);
|
||||
|
||||
/* if -u is given, don't use default key definition
|
||||
* unless it is the only one */
|
||||
if (uflag && kd == TAILQ_LAST(&kdhead, kdhead) &&
|
||||
TAILQ_LAST(&kdhead, kdhead) != TAILQ_FIRST(&kdhead)) {
|
||||
res = 0;
|
||||
} else if (kd->flags & MOD_N) {
|
||||
x = strtold(col1, NULL);
|
||||
y = strtold(col2, NULL);
|
||||
res = (x < y) ? (-1) : (x > y);
|
||||
} else {
|
||||
res = strcmp(col1, col2);
|
||||
}
|
||||
|
||||
if (kd->flags & MOD_R)
|
||||
res = -res;
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
check(FILE *fp)
|
||||
{
|
||||
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 (!Cflag)
|
||||
weprintf("disorder: %s", cur.buf);
|
||||
exit(1);
|
||||
}
|
||||
tmp = cur;
|
||||
cur = prev;
|
||||
prev = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
skipblank(char *s)
|
||||
{
|
||||
|
@ -223,6 +106,123 @@ columns(char *line, const struct keydef *kd, char **col, size_t *colsiz)
|
|||
return len;
|
||||
}
|
||||
|
||||
static int
|
||||
linecmp(const char **a, const char **b)
|
||||
{
|
||||
int res = 0;
|
||||
long double x, y;
|
||||
struct keydef *kd;
|
||||
|
||||
TAILQ_FOREACH(kd, &kdhead, entry) {
|
||||
columns((char *)*a, kd, &col1, &col1siz);
|
||||
columns((char *)*b, kd, &col2, &col2siz);
|
||||
|
||||
/* if -u is given, don't use default key definition
|
||||
* unless it is the only one */
|
||||
if (uflag && kd == TAILQ_LAST(&kdhead, kdhead) &&
|
||||
TAILQ_LAST(&kdhead, kdhead) != TAILQ_FIRST(&kdhead)) {
|
||||
res = 0;
|
||||
} else if (kd->flags & MOD_N) {
|
||||
x = strtold(col1, NULL);
|
||||
y = strtold(col2, NULL);
|
||||
res = (x < y) ? (-1) : (x > y);
|
||||
} else {
|
||||
res = strcmp(col1, col2);
|
||||
}
|
||||
|
||||
if (kd->flags & MOD_R)
|
||||
res = -res;
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
check(FILE *fp)
|
||||
{
|
||||
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 (!Cflag)
|
||||
weprintf("disorder: %s", cur.buf);
|
||||
exit(1);
|
||||
}
|
||||
tmp = cur;
|
||||
cur = prev;
|
||||
prev = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
parse_flags(char **s, int *flags, int bflag)
|
||||
{
|
||||
while (isalpha((int)**s)) {
|
||||
switch (*((*s)++)) {
|
||||
case 'b':
|
||||
*flags |= bflag;
|
||||
break;
|
||||
case 'n':
|
||||
*flags |= MOD_N;
|
||||
break;
|
||||
case 'r':
|
||||
*flags |= MOD_R;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
addkeydef(char *kdstr, int flags)
|
||||
{
|
||||
struct keydef *kd;
|
||||
|
||||
kd = enmalloc(2, sizeof(*kd));
|
||||
|
||||
/* parse key definition kdstr with format
|
||||
* start_column[.start_char][flags][,end_column[.end_char][flags]]
|
||||
*/
|
||||
kd->start_column = 1;
|
||||
kd->start_char = 1;
|
||||
kd->end_column = 0; /* 0 means end of line */
|
||||
kd->end_char = 0; /* 0 means end of column */
|
||||
kd->flags = flags;
|
||||
|
||||
if ((kd->start_column = strtol(kdstr, &kdstr, 10)) < 1)
|
||||
enprintf(2, "invalid start column in key definition\n");
|
||||
|
||||
if (*kdstr == '.') {
|
||||
if ((kd->start_char = strtol(kdstr + 1, &kdstr, 10)) < 1)
|
||||
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");
|
||||
|
||||
if (*kdstr == ',') {
|
||||
if ((kd->end_column = strtol(kdstr + 1, &kdstr, 10)) < 0)
|
||||
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");
|
||||
}
|
||||
if (parse_flags(&kdstr, &kd->flags, MOD_ENDB) < 0)
|
||||
enprintf(2, "invalid end flags in key definition\n");
|
||||
}
|
||||
|
||||
if (*kdstr != '\0')
|
||||
enprintf(2, "invalid key definition\n");
|
||||
|
||||
TAILQ_INSERT_TAIL(&kdhead, kd, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue