diff options
-rw-r--r-- | src/join.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/src/join.c b/src/join.c index 8e00a7a5d..16446eb58 100644 --- a/src/join.c +++ b/src/join.c @@ -54,6 +54,12 @@ char *alloca (); # define INT_MAX ((int) (UINT_MAX >> 1)) #endif +#if _LIBC || STDC_HEADERS +# define TOLOWER(c) tolower (c) +#else +# define TOLOWER(c) (ISUPPER (c) ? tolower (c) : (c)) +#endif + #include "system.h" #include "version.h" #include "long-options.h" @@ -141,6 +147,7 @@ static char tab; a character that is a short option. */ static struct option const longopts[] = { + {"ignore-case", no_argument, NULL, 'i'}, {"j", required_argument, NULL, 'j'}, {"j1", required_argument, NULL, '1'}, {"j2", required_argument, NULL, '2'}, @@ -150,6 +157,9 @@ static struct option const longopts[] = /* Used to print non-joining lines */ static struct line uni_blank; +/* If nonzero, ignore case when comparing join fields. */ +static int ignore_case; + static void usage (int status) { @@ -169,6 +179,7 @@ by whitespace. When FILE1 or FILE2 (not both) is -, read standard input.\n\ \n\ -a SIDE print unpairable lines coming from file SIDE\n\ -e EMPTY replace missing input fields with EMPTY\n\ + -i, --ignore-case ignore differences in case when comparing fields\n\ -j FIELD (Obsolescent) equivalent to `-1 FIELD -2 FIELD'\n\ -j1 FIELD (Obsolescent) equivalent to `-1 FIELD'\n\ -j2 FIELD (Obsolescent) equivalent to `-2 FIELD'\n\ @@ -191,6 +202,24 @@ separated by CHAR.\n\ exit (status); } +/* Like memcmp, but ignore differences in case. */ + +static int +memcasecmp (const void *vs1, const void *vs2, size_t n) +{ + int i; + unsigned char *s1 = (unsigned char *) vs1; + unsigned char *s2 = (unsigned char *) vs2; + for (i = 0; i < n; i++) + { + unsigned char u1 = *s1++; + unsigned char u2 = *s2++; + if (TOLOWER (u1) != TOLOWER (u2)) + return TOLOWER (u1) - TOLOWER (u2); + } + return 0; +} + static void ADD_FIELD (struct line *line, const char *field, size_t len) { @@ -373,7 +402,15 @@ keycmp (struct line *line1, struct line *line2) return len2 == 0 ? 0 : -1; if (len2 == 0) return 1; - diff = memcmp (beg1, beg2, min (len1, len2)); + + /* Use an if-statement here rather than a function variable to + avoid portability hassles of getting a non-conflicting declaration + of memcmp. */ + if (ignore_case) + diff = memcasecmp (beg1, beg2, min (len1, len2)); + else + diff = memcmp (beg1, beg2, min (len1, len2)); + if (diff) return diff; return len1 - len2; @@ -740,7 +777,7 @@ main (int argc, char **argv) nfiles = 0; print_pairables = 1; - while ((optc = getopt_long_only (argc, argv, "-a:e:1:2:o:t:v:", longopts, + while ((optc = getopt_long_only (argc, argv, "-a:e:i1:2:o:t:v:", longopts, (int *) 0)) != EOF) { long int val; @@ -768,6 +805,10 @@ main (int argc, char **argv) empty_filler = optarg; break; + case 'i': + ignore_case = 1; + break; + case '1': if (xstrtol (optarg, NULL, 10, &val, NULL) != LONGINT_OK || val <= 0 || val > INT_MAX) |