x86-64: Fix the dtv field load for x32 [BZ #31184]
[glibc.git] / libio / tst-widetext.c
blobf35f680e11d596fc76615b45da4a0f109238bde9
1 /* Test program for the wide character stream functions handling larger
2 amounts of text.
3 Copyright (C) 2000-2023 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
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.
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.
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/>. */
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>
29 /* Approximate size of the file (must be larger). */
30 #define SIZE 210000
33 static int
34 do_test (void)
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;
50 setlocale (LC_ALL, "de_DE.UTF-8");
51 printf ("locale used: %s\n\n", setlocale (LC_ALL, NULL));
53 /* Read the file into memory. */
54 mbsize = fread (mbbuf, 1, SIZE, stdin);
55 if (mbsize == 0)
57 printf ("%u: cannot read input file from standard input: %m\n",
58 __LINE__);
59 exit (1);
62 printf ("INFO: input file has %zd bytes\n", mbsize);
64 /* First convert the text to wide characters. We use iconv here. */
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;
73 cd = iconv_open ("WCHAR_T", "UTF-8");
74 if (cd == (iconv_t) -1)
76 printf ("%u: cannot get iconv descriptor for conversion to UCS4\n",
77 __LINE__);
78 exit (1);
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)
85 printf ("%u: iconv performed %zd nonreversible conversions\n",
86 __LINE__, nonr);
87 exit (1);
90 if (nonr == (size_t) -1)
92 printf ("\
93 %u: iconv returned with %zd and errno = %m (inleft: %zd, outleft: %zd)\n",
94 __LINE__, nonr, inleft, outleft);
95 exit (1);
98 if (inleft != 0)
100 printf ("%u: iconv didn't convert all input\n", __LINE__);
101 exit (1);
104 iconv_close (cd);
106 if ((sizeof (wcbuf) - outleft) % sizeof (wchar_t) != 0)
108 printf ("%u: iconv converted not complete wchar_t\n", __LINE__);
109 exit (1);
112 wcsize = (sizeof (wcbuf) - outleft) / sizeof (wchar_t);
113 assert (wcsize + 1 <= SIZE);
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. */
120 fd = mkstemp (name);
121 if (fd == -1)
123 printf ("%u: cannot open temporary file: %m\n", __LINE__);
124 exit (1);
127 unlink (name);
129 fp = fdopen (dup (fd), "w");
130 if (fp == NULL)
132 printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
133 exit (1);
136 for (n = 0; n < wcsize; ++n)
138 if (fputwc (wcbuf[n], fp) == WEOF)
140 printf ("%u: fputwc failed: %m\n", __LINE__);
141 exit (1);
145 res = fclose (fp);
146 if (res != 0)
148 printf ("%u: fclose after single-character writing failed (%d): %m\n",
149 __LINE__, res);
150 exit (1);
153 lseek (fd, SEEK_SET, 0);
154 fp = fdopen (dup (fd), "r");
155 if (fp == NULL)
157 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
158 exit (1);
161 for (n = 0; n < wcsize; ++n)
163 wint_t wch = fgetwc (fp);
164 if (wch == WEOF)
166 printf ("%u: fgetwc failed (idx %zd): %m\n", __LINE__, n);
167 exit (1);
169 wc2buf[n] = wch;
172 /* There should be nothing else. */
173 if (fgetwc (fp) != WEOF)
175 printf ("%u: too many characters available with fgetwc\n", __LINE__);
176 status = 1;
178 else if (wmemcmp (wcbuf, wc2buf, wcsize) != 0)
180 printf ("%u: buffer read with fgetwc differs\n", __LINE__);
181 status = 1;
184 res = fclose (fp);
185 if (res != 0)
187 printf ("%u: fclose after single-character reading failed (%d): %m\n",
188 __LINE__, res);
189 exit (1);
192 /* Just make sure there are no two errors which hide each other, read the
193 file using the `char' functions. */
195 lseek (fd, SEEK_SET, 0);
196 fp = fdopen (fd, "r");
197 if (fp == NULL)
199 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
200 exit (1);
203 if (fread (mb2buf, 1, mbsize, fp) != mbsize)
205 printf ("%u: cannot read all of the temp file\n", __LINE__);
206 status = 1;
208 else
210 /* Make sure there is nothing left. */
211 if (fgetc (fp) != EOF)
213 printf ("%u: more input available\n", __LINE__);
214 status = 1;
217 if (memcmp (mb2buf, mbbuf, mbsize) != 0)
219 printf ("%u: buffer written with fputwc differs\n", __LINE__);
220 status = 1;
224 res = fclose (fp);
225 if (res != 0)
227 printf ("%u: fclose after single-character reading failed (%d): %m\n",
228 __LINE__, res);
229 exit (1);
232 /* Now to reading and writing line-wise. */
234 fd = mkstemp (strcpy (name, "/tmp/widetext.out.XXXXXX"));
235 if (fd == -1)
237 printf ("%u: cannot open temporary file: %m\n", __LINE__);
238 exit (1);
241 unlink (name);
243 fp = fdopen (dup (fd), "w");
244 if (fp == NULL)
246 printf ("%u: fdopen of temp file for writing failed: %m\n", __LINE__);
247 exit (1);
250 for (wcp = wcbuf; wcp < &wcbuf[wcsize]; )
252 wchar_t *wendp = wcschr (wcp, L'\n');
254 if (wendp != NULL)
256 /* Temporarily NUL terminate the line. */
257 wchar_t save = wendp[1];
258 wendp[1] = L'\0';
260 fputws (wcp, fp);
262 wendp[1] = save;
263 wcp = &wendp[1];
265 else
267 fputws (wcp, fp);
268 wcp = wcschr (wcp, L'\0');
269 assert (wcp == &wcbuf[wcsize]);
273 res = fclose (fp);
274 if (res != 0)
276 printf ("%u: fclose after line-wise writing failed (%d): %m\n",
277 __LINE__, res);
278 exit (1);
281 lseek (fd, SEEK_SET, 0);
282 fp = fdopen (dup (fd), "r");
283 if (fp == NULL)
285 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
286 exit (1);
289 for (wcp = wc2buf; wcp < &wc2buf[wcsize]; )
291 if (fgetws (wcp, &wc2buf[wcsize] - wcp + 1, fp) == NULL)
293 printf ("%u: short read using fgetws (only %td of %zd)\n",
294 __LINE__, wcp - wc2buf, wcsize);
295 status = 1;
296 break;
298 wcp = wcschr (wcp, L'\0');
301 if (wcp > &wc2buf[wcsize])
303 printf ("%u: fgetws read too much\n", __LINE__);
304 status = 1;
306 else if (fgetwc (fp) != WEOF)
308 /* There should be nothing else. */
309 printf ("%u: too many characters available with fgetws\n", __LINE__);
310 status = 1;
313 if (wcp >= &wc2buf[wcsize] && wmemcmp (wcbuf, wc2buf, wcsize) != 0)
315 printf ("%u: buffer read with fgetws differs\n", __LINE__);
316 status = 1;
319 res = fclose (fp);
320 if (res != 0)
322 printf ("%u: fclose after single-character reading failed (%d): %m\n",
323 __LINE__, res);
324 exit (1);
327 /* Just make sure there are no two errors which hide each other, read the
328 file using the `char' functions. */
330 lseek (fd, SEEK_SET, 0);
331 fp = fdopen (fd, "r");
332 if (fp == NULL)
334 printf ("%u: fdopen of temp file for reading failed: %m\n", __LINE__);
335 exit (1);
338 if (fread (mb2buf, 1, mbsize, fp) != mbsize)
340 printf ("%u: cannot read all of the temp file\n", __LINE__);
341 status = 1;
343 else
345 /* Make sure there is nothing left. */
346 if (fgetc (fp) != EOF)
348 printf ("%u: more input available\n", __LINE__);
349 status = 1;
352 if (memcmp (mb2buf, mbbuf, mbsize) != 0)
354 printf ("%u: buffer written with fputws differs\n", __LINE__);
355 status = 1;
359 res = fclose (fp);
360 if (res != 0)
362 printf ("%u: fclose after single-character reading failed (%d): %m\n",
363 __LINE__, res);
364 exit (1);
367 return status;
370 #define TEST_FUNCTION do_test ()
371 #include "../test-skeleton.c"