Upgrade grep version 2.9 to 2.12 on the vendor branch
[dragonfly.git] / contrib / grep / lib / wcscoll-impl.h
1 /* Compare two wide strings using the current locale.
2    Copyright (C) 2011-2012 Free Software Foundation, Inc.
3    Written by Bruno Haible <bruno@clisp.org>, 2011.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 int
19 wcscoll (const wchar_t *s1, const wchar_t *s2)
20 {
21   char mbbuf1[1024];
22   char mbbuf2[1024];
23   char *mbs1;
24   char *mbs2;
25
26   {
27     int saved_errno = errno;
28
29     /* Convert s1 to a multibyte string, trying to avoid malloc().  */
30     {
31       size_t ret;
32
33       ret = wcstombs (mbbuf1, s1, sizeof (mbbuf1));
34       if (ret == (size_t)-1)
35         goto failed1;
36       if (ret < sizeof (mbbuf1))
37         mbs1 = mbbuf1;
38       else
39         {
40           size_t need = wcstombs (NULL, s1, 0);
41           if (need == (size_t)-1)
42             goto failed1;
43           mbs1 = (char *) malloc (need + 1);
44           if (mbs1 == NULL)
45             goto out_of_memory1;
46           ret = wcstombs (mbs1, s1, need + 1);
47           if (ret != need)
48             abort ();
49         }
50     }
51
52     /* Convert s2 to a multibyte string, trying to avoid malloc().  */
53     {
54       size_t ret;
55
56       ret = wcstombs (mbbuf2, s2, sizeof (mbbuf2));
57       if (ret == (size_t)-1)
58         goto failed2;
59       if (ret < sizeof (mbbuf2))
60         mbs2 = mbbuf2;
61       else
62         {
63           size_t need = wcstombs (NULL, s2, 0);
64           if (need == (size_t)-1)
65             goto failed2;
66           mbs2 = (char *) malloc (need + 1);
67           if (mbs2 == NULL)
68             goto out_of_memory2;
69           ret = wcstombs (mbs2, s2, need + 1);
70           if (ret != need)
71             abort ();
72         }
73     }
74
75     /* No error so far.  */
76     errno = saved_errno;
77   }
78
79   /* Compare the two multibyte strings.  */
80   {
81     int result = strcoll (mbs1, mbs2);
82
83     if (mbs1 != mbbuf1)
84       {
85         int saved_errno = errno;
86         free (mbs1);
87         errno = saved_errno;
88       }
89     if (mbs2 != mbbuf2)
90       {
91         int saved_errno = errno;
92         free (mbs2);
93         errno = saved_errno;
94       }
95     return result;
96   }
97
98  out_of_memory2:
99   if (mbs1 != mbbuf1)
100     free (mbs1);
101  out_of_memory1:
102   errno = ENOMEM;
103   return 0;
104
105  failed2:
106   if (mbs1 != mbbuf1)
107     free (mbs1);
108  failed1:
109   errno = EILSEQ;
110   return 0;
111 }