[v3,0/7] Fix some libm static issues
[platform/upstream/glibc.git] / libio / tst-widetext.c
1 /* Test program for the wide character stream functions handling larger
2    amounts of text.
3    Copyright (C) 2000-2024 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <https://www.gnu.org/licenses/>.  */
19
20 #include <assert.h>
21 #include <iconv.h>
22 #include <locale.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <wchar.h>
28
29 /* Approximate size of the file (must be larger).  */
30 #define SIZE 210000
31
32
33 static int
34 do_test (void)
35 {
36   char name[] = "/tmp/widetext.out.XXXXXX";
37   char mbbuf[SIZE];
38   char mb2buf[SIZE];
39   wchar_t wcbuf[SIZE];
40   wchar_t wc2buf[SIZE];
41   size_t mbsize;
42   size_t wcsize;
43   int fd;
44   FILE *fp;
45   size_t n;
46   int res;
47   int status = 0;
48   wchar_t *wcp;
49
50   setlocale (LC_ALL, "de_DE.UTF-8");
51   printf ("locale used: %s\n\n", setlocale (LC_ALL, NULL));
52
53   /* Read the file into memory.  */
54   mbsize = fread (mbbuf, 1, SIZE, stdin);
55   if (mbsize == 0)
56     {
57       printf ("%u: cannot read input file from standard input: %m\n",
58               __LINE__);
59       exit (1);
60     }
61
62    printf ("INFO: input file has %zd bytes\n", mbsize);
63
64   /* First convert the text to wide characters.  We use iconv here.  */
65   {
66     iconv_t cd;
67     char *inbuf = mbbuf;
68     size_t inleft = mbsize;
69     char *outbuf = (char *) wcbuf;
70     size_t outleft = sizeof (wcbuf);
71     size_t nonr;
72
73     cd = iconv_open ("WCHAR_T", "UTF-8");
74     if (cd == (iconv_t) -1)
75       {
76         printf ("%u: cannot get iconv descriptor for conversion to UCS4\n",
77                 __LINE__);
78         exit (1);
79       }
80
81     /* We must need only one call and there must be no losses.  */
82     nonr = iconv (cd, &inbuf, &inleft, &outbuf, &outleft);
83     if (nonr != 0 && nonr != (size_t) -1)
84       {
85         printf ("%u: iconv performed %zd nonreversible conversions\n",
86                 __LINE__, nonr);
87         exit (1);
88       }
89
90     if  (nonr == (size_t) -1)
91       {
92         printf ("\
93 %u: iconv returned with %zd and errno = %m (inleft: %zd, outleft: %zd)\n",
94                 __LINE__, nonr, inleft, outleft);
95         exit (1);
96       }
97
98     if (inleft != 0)
99       {
100         printf ("%u: iconv didn't convert all input\n", __LINE__);
101         exit (1);
102       }
103
104     iconv_close (cd);
105
106     if ((sizeof (wcbuf) - outleft) % sizeof (wchar_t) != 0)
107       {
108         printf ("%u: iconv converted not complete wchar_t\n", __LINE__);
109         exit (1);
110       }
111
112     wcsize = (sizeof (wcbuf) - outleft) / sizeof (wchar_t);
113     assert (wcsize + 1 <= SIZE);
114   }
115
116   /* Now that we finished the preparations, run the first test.  We
117      are writing the wide char data out and read it back in.  We write
118      and read single characters.  */
119
120   fd = mkstemp (name);
121   if (fd == -1)
122     {
123       printf ("%u: cannot open temporary file: %m\n", __LINE__);
124       exit (1);
125     }
126
127   unlink (name);
128
129   fp = fdopen (dup (fd), "w");
130   if (fp == NULL)
131     {
132       printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
133       exit (1);
134     }
135
136   for (n = 0; n < wcsize; ++n)
137     {
138       if (fputwc (wcbuf[n], fp) == WEOF)
139         {
140           printf ("%u: fputwc failed: %m\n", __LINE__);
141           exit (1);
142         }
143     }
144
145   res = fclose (fp);
146   if (res != 0)
147     {
148       printf ("%u: fclose after single-character writing failed (%d): %m\n",
149               __LINE__, res);
150       exit (1);
151     }
152
153   lseek (fd, SEEK_SET, 0);
154   fp = fdopen (dup (fd), "r");
155   if (fp == NULL)
156     {
157       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
158       exit (1);
159     }
160
161   for (n = 0; n < wcsize; ++n)
162     {
163       wint_t wch = fgetwc (fp);
164       if (wch == WEOF)
165         {
166           printf ("%u: fgetwc failed (idx %zd): %m\n", __LINE__, n);
167           exit (1);
168         }
169       wc2buf[n] = wch;
170     }
171
172   /* There should be nothing else.  */
173   if (fgetwc (fp) != WEOF)
174     {
175       printf ("%u: too many characters available with fgetwc\n", __LINE__);
176       status = 1;
177     }
178   else if (wmemcmp (wcbuf, wc2buf, wcsize) != 0)
179     {
180       printf ("%u: buffer read with fgetwc differs\n", __LINE__);
181       status = 1;
182     }
183
184   res = fclose (fp);
185   if (res != 0)
186     {
187       printf ("%u: fclose after single-character reading failed (%d): %m\n",
188               __LINE__, res);
189       exit (1);
190     }
191
192   /* Just make sure there are no two errors which hide each other, read the
193      file using the `char' functions.  */
194
195   lseek (fd, SEEK_SET, 0);
196   fp = fdopen (fd, "r");
197   if (fp == NULL)
198     {
199       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
200       exit (1);
201     }
202
203   if (fread (mb2buf, 1, mbsize, fp) != mbsize)
204     {
205       printf ("%u: cannot read all of the temp file\n", __LINE__);
206       status = 1;
207     }
208   else
209     {
210       /* Make sure there is nothing left.  */
211       if (fgetc (fp) != EOF)
212         {
213           printf ("%u: more input available\n", __LINE__);
214           status = 1;
215         }
216
217       if (memcmp (mb2buf, mbbuf, mbsize) != 0)
218         {
219           printf ("%u: buffer written with fputwc differs\n", __LINE__);
220           status = 1;
221         }
222     }
223
224   res = fclose (fp);
225   if (res != 0)
226     {
227       printf ("%u: fclose after single-character reading failed (%d): %m\n",
228               __LINE__, res);
229       exit (1);
230     }
231
232   /* Now to reading and writing line-wise.  */
233
234   fd = mkstemp (strcpy (name, "/tmp/widetext.out.XXXXXX"));
235   if (fd == -1)
236     {
237       printf ("%u: cannot open temporary file: %m\n", __LINE__);
238       exit (1);
239     }
240
241   unlink (name);
242
243   fp = fdopen (dup (fd), "w");
244   if (fp == NULL)
245     {
246       printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
247       exit (1);
248     }
249
250   for (wcp = wcbuf; wcp < &wcbuf[wcsize]; )
251     {
252       wchar_t *wendp = wcschr (wcp, L'\n');
253
254       if (wendp != NULL)
255         {
256           /* Temporarily NUL terminate the line.  */
257           wchar_t save = wendp[1];
258           wendp[1] = L'\0';
259
260           fputws (wcp, fp);
261
262           wendp[1] = save;
263           wcp = &wendp[1];
264         }
265       else
266         {
267           fputws (wcp, fp);
268           wcp = wcschr (wcp, L'\0');
269           assert (wcp == &wcbuf[wcsize]);
270         }
271     }
272
273   res = fclose (fp);
274   if (res != 0)
275     {
276       printf ("%u: fclose after line-wise writing failed (%d): %m\n",
277               __LINE__, res);
278       exit (1);
279     }
280
281   lseek (fd, SEEK_SET, 0);
282   fp = fdopen (dup (fd), "r");
283   if (fp == NULL)
284     {
285       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
286       exit (1);
287     }
288
289   for (wcp = wc2buf; wcp < &wc2buf[wcsize]; )
290     {
291       if (fgetws (wcp, &wc2buf[wcsize] - wcp + 1, fp) == NULL)
292         {
293           printf ("%u: short read using fgetws (only %td of %zd)\n",
294                   __LINE__, wcp - wc2buf, wcsize);
295           status = 1;
296           break;
297         }
298       wcp = wcschr (wcp, L'\0');
299     }
300
301   if (wcp > &wc2buf[wcsize])
302     {
303       printf ("%u: fgetws read too much\n", __LINE__);
304       status = 1;
305     }
306   else if (fgetwc (fp) != WEOF)
307     {
308       /* There should be nothing else.  */
309       printf ("%u: too many characters available with fgetws\n", __LINE__);
310       status = 1;
311     }
312
313   if (wcp >= &wc2buf[wcsize] && wmemcmp (wcbuf, wc2buf, wcsize) != 0)
314     {
315       printf ("%u: buffer read with fgetws differs\n", __LINE__);
316       status = 1;
317     }
318
319   res = fclose (fp);
320   if (res != 0)
321     {
322       printf ("%u: fclose after single-character reading failed (%d): %m\n",
323               __LINE__, res);
324       exit (1);
325     }
326
327   /* Just make sure there are no two errors which hide each other, read the
328      file using the `char' functions.  */
329
330   lseek (fd, SEEK_SET, 0);
331   fp = fdopen (fd, "r");
332   if (fp == NULL)
333     {
334       printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
335       exit (1);
336     }
337
338   if (fread (mb2buf, 1, mbsize, fp) != mbsize)
339     {
340       printf ("%u: cannot read all of the temp file\n", __LINE__);
341       status = 1;
342     }
343   else
344     {
345       /* Make sure there is nothing left.  */
346       if (fgetc (fp) != EOF)
347         {
348           printf ("%u: more input available\n", __LINE__);
349           status = 1;
350         }
351
352       if (memcmp (mb2buf, mbbuf, mbsize) != 0)
353         {
354           printf ("%u: buffer written with fputws differs\n", __LINE__);
355           status = 1;
356         }
357     }
358
359   res = fclose (fp);
360   if (res != 0)
361     {
362       printf ("%u: fclose after single-character reading failed (%d): %m\n",
363               __LINE__, res);
364       exit (1);
365     }
366
367   return status;
368 }
369
370 #define TEST_FUNCTION do_test ()
371 #include "../test-skeleton.c"