*** textutils/src/join.c 2001-12-02 20:51:39.000000000 +0100 --- textutils-i18n/src/join.c 2001-12-11 00:09:40.000000000 +0100 *************** *** 29,38 **** #include "error.h" #include "hard-locale.h" #include "linebuffer.h" ! #include "memcasecmp.h" #include "memcoll.h" #include "xstrtol.h" /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "join" --- 29,42 ---- #include "error.h" #include "hard-locale.h" #include "linebuffer.h" ! #include "memcasecoll.h" #include "memcoll.h" #include "xstrtol.h" + #if HAVE_MBRTOWC + # include "mbchar.h" + #endif + /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "join" *************** *** 88,94 **** /* 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 --- 92,98 ---- /* The name this program was run with. */ char *program_name; ! #if HAVE_SETLOCALE /* Nonzero if the LC_COLLATE locale is hard. */ static int hard_LC_COLLATE; #endif *************** *** 111,120 **** /* Last element in `outlist', where a new element can be added. */ static struct outlist *outlist_end = &outlist_head; ! /* Tab character separating fields; if this is NUL fields are separated ! by any nonempty string of white space, otherwise by exactly one ! tab character. */ ! static unsigned char tab; /* When using getopt_long_only, no long option can start with a character that is a short option. */ --- 115,127 ---- /* Last element in `outlist', where a new element can be added. */ static struct outlist *outlist_end = &outlist_head; ! /* Tab character separating fields; if this is NULL fields are separated ! by any nonempty string of white space, otherwise by exactly one copy ! of this tab character. */ ! static char* tab; ! #if HAVE_MBRTOWC ! static mbchar_t tabmb; ! #endif /* When using getopt_long_only, no long option can start with a character that is a short option. */ *************** *** 184,189 **** --- 191,242 ---- exit (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } + /* Set tab and tabmb according to the command line argument. */ + #if HAVE_MBRTOWC + #include "mbiter_multi.h" + static inline void + set_tab_multi (const char *arg) + { + MBI_ITERATOR iter; + + MBI_INIT (iter, arg, strlen (arg)); + if (MBI_AVAIL (iter)) + { + size_t len = MB_LEN (MBI_CUR (iter)); + + tab = (char *) xmalloc (len + 1); + memcpy (tab, MBI_CUR_PTR (iter), len); + tab[len] = '\0'; + mb_copy (&tabmb, &MBI_CUR (iter)); + MBI_ADVANCE (iter); + if (MBI_AVAIL (iter)) + error (EXIT_FAILURE, 0, + _("the separator must be a single character: %s"), arg); + } + } + #include "mbiter_undef.h" + #endif + static void + set_tab (const char *arg) + { + #if HAVE_MBRTOWC + if (MB_CUR_MAX > 1) + set_tab_multi (arg); + else + #endif + { + if (*arg != '\0') + { + tab = (char *) xmalloc (2); + tab[0] = *arg; + tab[1] = '\0'; + if (arg[1] != '\0') + error (EXIT_FAILURE, 0, + _("the separator must be a single character: %s"), arg); + } + } + } + static void ADD_FIELD (struct line *line, const unsigned char *field, size_t len) { *************** *** 201,256 **** /* Fill in the `fields' structure in LINE. */ ! static void ! xfields (struct line *line) ! { ! int i; ! unsigned char *ptr0 = (unsigned char *) line->buf.buffer; ! unsigned char *ptr; ! unsigned char *lim; ! ! ptr = ptr0; ! lim = ptr0 + line->buf.length - 1; ! if (!tab) ! { ! /* Skip leading blanks before the first field. */ ! while (ptr < lim && ISBLANK (*ptr)) ! ++ptr; ! } ! for (i = 0; ptr < lim; ++i) ! { ! if (tab) { ! unsigned char *beg; ! ! beg = ptr; ! while (ptr < lim && *ptr != tab) ! ++ptr; ! ADD_FIELD (line, beg, ptr - beg); ! if (ptr < lim) ! ++ptr; ! } else ! { ! unsigned char *beg; ! ! beg = ptr; ! while (ptr < lim && !ISBLANK (*ptr)) ! ++ptr; ! ADD_FIELD (line, beg, ptr - beg); ! while (ptr < lim && ISBLANK (*ptr)) ! ++ptr; ! } ! } ! ! 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. */ ! ADD_FIELD (line, NULL, 0); ! } } /* Read a line from FP into LINE and split it into fields. --- 254,282 ---- /* Fill in the `fields' structure in LINE. */ ! #if HAVE_MBRTOWC ! #define FUNC xfields_multi ! #define IS_TAB(mbc) MB_EQUAL (mbc, tabmb) ! #include "mbiter_multi.h" ! #include "join_fields.h" ! #include "mbiter_undef.h" ! #endif ! #define FUNC xfields_8bit ! #define IS_TAB(mbc) ((mbc) == tab[0]) ! #include "mbiter_8bit.h" ! #include "join_fields.h" ! #include "mbiter_undef.h" ! static void ! xfields (struct line *line) { ! #if HAVE_MBRTOWC ! if (MB_CUR_MAX > 1) ! return xfields_multi (line); else ! #endif ! return xfields_8bit (line); } /* Read a line from FP into LINE and split it into fields. *************** *** 365,377 **** of memcmp. */ if (ignore_case) { ! /* FIXME: ignore_case does not work with NLS (in particular, ! with multibyte chars). */ ! diff = memcasecmp (beg1, beg2, min (len1, len2)); } else { ! #ifdef ENABLE_NLS if (hard_LC_COLLATE) return memcoll ((char *) beg1, len1, (char *) beg2, len2); #endif --- 391,405 ---- of memcmp. */ if (ignore_case) { ! #if HAVE_SETLOCALE ! return memcasecoll (beg1, len1, beg2, len2, hard_LC_COLLATE); ! #else ! return memcasecoll (beg1, len1, beg2, len2, 0); ! #endif } else { ! #if HAVE_SETLOCALE if (hard_LC_COLLATE) return memcoll ((char *) beg1, len1, (char *) beg2, len2); #endif *************** *** 444,450 **** o = o->next; if (o == NULL) break; ! putchar (tab ? tab : ' '); } putchar ('\n'); } --- 472,478 ---- o = o->next; if (o == NULL) break; ! fputs (tab ? tab : " ", stdout); } putchar ('\n'); } *************** *** 462,484 **** prfield (join_field_1, line1); for (i = 0; i < join_field_1 && i < line1->nfields; ++i) { ! putchar (tab ? tab : ' '); prfield (i, line1); } for (i = join_field_1 + 1; i < line1->nfields; ++i) { ! putchar (tab ? tab : ' '); prfield (i, line1); } for (i = 0; i < join_field_2 && i < line2->nfields; ++i) { ! putchar (tab ? tab : ' '); prfield (i, line2); } for (i = join_field_2 + 1; i < line2->nfields; ++i) { ! putchar (tab ? tab : ' '); prfield (i, line2); } putchar ('\n'); --- 490,512 ---- prfield (join_field_1, line1); for (i = 0; i < join_field_1 && i < line1->nfields; ++i) { ! fputs (tab ? tab : " ", stdout); prfield (i, line1); } for (i = join_field_1 + 1; i < line1->nfields; ++i) { ! fputs (tab ? tab : " ", stdout); prfield (i, line1); } for (i = 0; i < join_field_2 && i < line2->nfields; ++i) { ! fputs (tab ? tab : " ", stdout); prfield (i, line2); } for (i = join_field_2 + 1; i < line2->nfields; ++i) { ! fputs (tab ? tab : " ", stdout); prfield (i, line2); } putchar ('\n'); *************** *** 746,752 **** atexit (close_stdout); ! #ifdef ENABLE_NLS hard_LC_COLLATE = hard_locale (LC_COLLATE); #endif --- 774,780 ---- atexit (close_stdout); ! #if HAVE_SETLOCALE hard_LC_COLLATE = hard_locale (LC_COLLATE); #endif *************** *** 820,826 **** break; case 't': ! tab = *optarg; break; case 1: /* Non-option argument. */ --- 848,854 ---- break; case 't': ! set_tab (optarg); break; case 1: /* Non-option argument. */ *** /dev/null 2009-04-14 12:31:40.000000000 +0200 --- textutils-i18n/src/join_fields.h 2001-12-11 00:09:40.000000000 +0100 *************** *** 0 **** --- 1,90 ---- + /* Split a line into fields. + Copyright (C) 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + static inline void + FUNC (struct line *line) + { + MBI_ITERATOR iter; + + MBI_INIT (iter, line->buf.buffer, line->buf.length - 1); + + if (tab) + { + /* In this case, a leading tab means that the first field is empty. + A trailing tab means that the last field is empty. */ + if (MBI_AVAIL (iter)) + for (;;) + { + const char *beg = MBI_CUR_PTR (iter); + + /* Skip a field. */ + while (MBI_AVAIL (iter) && !IS_TAB (MBI_CUR (iter))) + MBI_ADVANCE (iter); + + ADD_FIELD (line, beg, MBI_CUR_PTR (iter) - beg); + + if (!MBI_AVAIL (iter)) + break; + + /* Skip a tab. */ + MBI_ADVANCE (iter); + + if (!MBI_AVAIL (iter)) + { + /* Add one more (empty) field because the last character of + the line was a delimiter. */ + ADD_FIELD (line, NULL, 0); + break; + } + } + } + else + { + /* In this case, leading blanks are ignored. + But trailing blanks mean that the last field is empty. */ + for (;;) + { + const char *beg; + + if (!MBI_AVAIL (iter)) + break; + + /* Skip blanks. */ + while (MBI_AVAIL (iter) && MB_ISBLANK (MBI_CUR (iter))) + MBI_ADVANCE (iter); + + if (!MBI_AVAIL (iter)) + { + /* Add one more (empty) field because the last character of + the line was a delimiter. */ + ADD_FIELD (line, NULL, 0); + break; + } + + beg = MBI_CUR_PTR (iter); + + /* Skip a field. */ + while (MBI_AVAIL (iter) && !MB_ISBLANK (MBI_CUR (iter))) + MBI_ADVANCE (iter); + + ADD_FIELD (line, beg, MBI_CUR_PTR (iter) - beg); + } + } + } + + #undef FUNC + #undef IS_TAB