summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1999-07-04 10:28:08 +0000
committerJim Meyering <jim@meyering.net>1999-07-04 10:28:08 +0000
commit115372366e5c36d3afe9c07f8d1dd430de821716 (patch)
treecd5552d7ad74be593c12db80db3e9c9c32e40cda
parentd67adf2b8c9466e91dda5f59ae0cdcbe502977a8 (diff)
downloadcoreutils-115372366e5c36d3afe9c07f8d1dd430de821716.tar.xz
Add support for LC_COLLATE locale.
Include hard-locale.h, linebuffer.h, memcoll.h. (struct line): New member `buf', replacing `beg' and `lim'. All uses changed. (hard_LC_COLLATE): New var. (main): Initialize it. (get_line): Use readline to read the line, instead of doing it by hand. That way, we get a buffer that we can pass to memcoll. (keycmp): Use memcoll to compare lines if hard_LC_COLLATE is nonzero.
-rw-r--r--src/join.c88
1 files changed, 47 insertions, 41 deletions
diff --git a/src/join.c b/src/join.c
index d71fe8bf0..f34aeba6f 100644
--- a/src/join.c
+++ b/src/join.c
@@ -26,6 +26,8 @@
#include "system.h"
#include "error.h"
+#include "hard-locale.h"
+#include "linebuffer.h"
#include "memcasecmp.h"
#include "xstrtol.h"
@@ -63,11 +65,10 @@ struct field
size_t len; /* The length of the field. */
};
-/* A line read from an input file. Newlines are not stored. */
+/* A line read from an input file. */
struct line
{
- unsigned char *beg; /* First character in line. */
- unsigned char *lim; /* Character after last character in line. */
+ struct linebuffer buf; /* The line itself. */
int nfields; /* Number of elements in `fields'. */
int nfields_allocated; /* Number of elements in `fields'. */
struct field *fields;
@@ -85,6 +86,11 @@ struct seq
/* The name this program was run with. */
char *program_name;
+#ifdef ENABLE_NLS
+/* Nonzero if the LC_COLLATE locale is hard. */
+static int hard_LC_COLLATE;
+#endif
+
/* If nonzero, print unpairable lines in file 1 or 2. */
static int print_unpairables_1, print_unpairables_2;
@@ -191,11 +197,12 @@ static void
xfields (struct line *line)
{
int i;
+ unsigned char *ptr0 = (unsigned char *) line->buf.buffer;
unsigned char *ptr;
unsigned char *lim;
- ptr = line->beg;
- lim = line->lim;
+ ptr = ptr0;
+ lim = ptr0 + line->buf.length - 1;
if (!tab)
{
@@ -230,7 +237,7 @@ xfields (struct line *line)
}
}
- if (ptr > line->beg && ((!tab && ISBLANK (ptr[-1])) || ptr[-1] == tab))
+ if (ptr != ptr0 && ((!tab && ISBLANK (ptr[-1])) || ptr[-1] == tab))
{
/* Add one more (empty) field because the last character of the
line was a delimiter. */
@@ -244,33 +251,15 @@ xfields (struct line *line)
static int
get_line (FILE *fp, struct line *line)
{
- static int linesize = 80;
- int c, i;
- unsigned char *ptr;
-
- if (feof (fp))
- return 0;
-
- ptr = xmalloc (linesize);
-
- for (i = 0; (c = getc (fp)) != EOF && c != '\n'; ++i)
- {
- if (i == linesize)
- {
- linesize *= 2;
- ptr = xrealloc (ptr, linesize);
- }
- ptr[i] = c;
- }
+ initbuffer (&line->buf);
- if (c == EOF && i == 0)
+ if (! readline (&line->buf, fp))
{
- free (ptr);
+ free (line->buf.buffer);
+ line->buf.buffer = NULL;
return 0;
}
- line->beg = ptr;
- line->lim = line->beg + i;
line->nfields_allocated = 0;
line->nfields = 0;
line->fields = NULL;
@@ -282,8 +271,8 @@ static void
freeline (struct line *line)
{
free ((char *) line->fields);
- free (line->beg);
- line->beg = NULL;
+ free (line->buf.buffer);
+ line->buf.buffer = NULL;
}
static void
@@ -319,7 +308,7 @@ delseq (struct seq *seq)
{
int i;
for (i = 0; i < seq->count; i++)
- if (seq->lines[i].beg)
+ if (seq->lines[i].buf.buffer)
freeline (&seq->lines[i]);
free ((char *) seq->lines);
}
@@ -367,9 +356,19 @@ keycmp (struct line *line1, struct line *line2)
avoid portability hassles of getting a non-conflicting declaration
of memcmp. */
if (ignore_case)
- diff = memcasecmp (beg1, beg2, min (len1, len2));
+ {
+ /* FIXME: ignore_case does not work with NLS (in particular,
+ with multibyte chars). */
+ diff = memcasecmp (beg1, beg2, min (len1, len2));
+ }
else
- diff = memcmp (beg1, beg2, min (len1, len2));
+ {
+#ifdef ENABLE_NLS
+ if (hard_LC_COLLATE)
+ return memcoll ((char *) beg1, len1, (char *) beg2, len2);
+#endif
+ diff = memcmp (beg1, beg2, min (len1, len2));
+ }
if (diff)
return diff;
@@ -708,17 +707,20 @@ void
make_blank (struct line *blank, int count)
{
int i;
+ char *buffer;
+ struct field *fields;
blank->nfields = count;
- blank->beg = xmalloc (blank->nfields + 1);
- blank->fields = (struct field *) xmalloc (sizeof (struct field) * count);
- for (i = 0; i < blank->nfields; i++)
+ blank->buf.size = blank->buf.length = count + 1;
+ blank->buf.buffer = buffer = xmalloc (blank->buf.size);
+ blank->fields = fields =
+ (struct field *) xmalloc (sizeof (struct field) * count);
+ for (i = 0; i < count; i++)
{
- blank->beg[i] = '\t';
- blank->fields[i].beg = &blank->beg[i];
- blank->fields[i].len = 0;
+ buffer[i] = '\t';
+ fields[i].beg = &buffer[i];
+ fields[i].len = 0;
}
- blank->beg[i] = '\0';
- blank->lim = &blank->beg[i];
+ buffer[i] = '\n';
}
int
@@ -733,6 +735,10 @@ main (int argc, char **argv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
+#ifdef ENABLE_NLS
+ hard_LC_COLLATE = hard_locale (LC_COLLATE);
+#endif
+
/* Initialize this before parsing options. In parsing options,
it may be increased. */
uni_blank.nfields = 1;