xref: /freebsd/tools/build/cross-build/fgetwln_fallback.c (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
1*7ec1ec4fSAlex Richardson /*
2*7ec1ec4fSAlex Richardson  * Copyright 2012 Guillem Jover <guillem@hadrons.org>
3*7ec1ec4fSAlex Richardson  *
4*7ec1ec4fSAlex Richardson  * Redistribution and use in source and binary forms, with or without
5*7ec1ec4fSAlex Richardson  * modification, are permitted provided that the following conditions
6*7ec1ec4fSAlex Richardson  * are met:
7*7ec1ec4fSAlex Richardson  * 1. Redistributions of source code must retain the above copyright
8*7ec1ec4fSAlex Richardson  *    notice, this list of conditions and the following disclaimer.
9*7ec1ec4fSAlex Richardson  * 2. Redistributions in binary form must reproduce the above copyright
10*7ec1ec4fSAlex Richardson  *    notice, this list of conditions and the following disclaimer in the
11*7ec1ec4fSAlex Richardson  *    documentation and/or other materials provided with the distribution.
12*7ec1ec4fSAlex Richardson  * 3. The name of the author may not be used to endorse or promote products
13*7ec1ec4fSAlex Richardson  *    derived from this software without specific prior written permission.
14*7ec1ec4fSAlex Richardson  *
15*7ec1ec4fSAlex Richardson  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16*7ec1ec4fSAlex Richardson  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17*7ec1ec4fSAlex Richardson  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
18*7ec1ec4fSAlex Richardson  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19*7ec1ec4fSAlex Richardson  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20*7ec1ec4fSAlex Richardson  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21*7ec1ec4fSAlex Richardson  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22*7ec1ec4fSAlex Richardson  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23*7ec1ec4fSAlex Richardson  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24*7ec1ec4fSAlex Richardson  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*7ec1ec4fSAlex Richardson  */
26*7ec1ec4fSAlex Richardson 
27*7ec1ec4fSAlex Richardson #include <sys/cdefs.h>
28*7ec1ec4fSAlex Richardson 
29*7ec1ec4fSAlex Richardson #include <stdlib.h>
30*7ec1ec4fSAlex Richardson #include <stdio.h>
31*7ec1ec4fSAlex Richardson #include <wchar.h>
32*7ec1ec4fSAlex Richardson 
33*7ec1ec4fSAlex Richardson #include "local-link.h"
34*7ec1ec4fSAlex Richardson 
35*7ec1ec4fSAlex Richardson struct filewbuf {
36*7ec1ec4fSAlex Richardson 	FILE *fp;
37*7ec1ec4fSAlex Richardson 	wchar_t *wbuf;
38*7ec1ec4fSAlex Richardson 	size_t len;
39*7ec1ec4fSAlex Richardson };
40*7ec1ec4fSAlex Richardson 
41*7ec1ec4fSAlex Richardson #define FILEWBUF_INIT_LEN	128
42*7ec1ec4fSAlex Richardson #define FILEWBUF_POOL_ITEMS	32
43*7ec1ec4fSAlex Richardson 
44*7ec1ec4fSAlex Richardson static struct filewbuf fb_pool[FILEWBUF_POOL_ITEMS];
45*7ec1ec4fSAlex Richardson static int fb_pool_cur;
46*7ec1ec4fSAlex Richardson 
47*7ec1ec4fSAlex Richardson wchar_t *
fgetwln(FILE * stream,size_t * lenp)48*7ec1ec4fSAlex Richardson fgetwln(FILE *stream, size_t *lenp)
49*7ec1ec4fSAlex Richardson {
50*7ec1ec4fSAlex Richardson 	struct filewbuf *fb;
51*7ec1ec4fSAlex Richardson 	wint_t wc;
52*7ec1ec4fSAlex Richardson 	size_t wused = 0;
53*7ec1ec4fSAlex Richardson 
54*7ec1ec4fSAlex Richardson 	/* Try to diminish the possibility of several fgetwln() calls being
55*7ec1ec4fSAlex Richardson 	 * used on different streams, by using a pool of buffers per file. */
56*7ec1ec4fSAlex Richardson 	fb = &fb_pool[fb_pool_cur];
57*7ec1ec4fSAlex Richardson 	if (fb->fp != stream && fb->fp != NULL) {
58*7ec1ec4fSAlex Richardson 		fb_pool_cur++;
59*7ec1ec4fSAlex Richardson 		fb_pool_cur %= FILEWBUF_POOL_ITEMS;
60*7ec1ec4fSAlex Richardson 		fb = &fb_pool[fb_pool_cur];
61*7ec1ec4fSAlex Richardson 	}
62*7ec1ec4fSAlex Richardson 	fb->fp = stream;
63*7ec1ec4fSAlex Richardson 
64*7ec1ec4fSAlex Richardson 	while ((wc = fgetwc(stream)) != WEOF) {
65*7ec1ec4fSAlex Richardson 		if (!fb->len || wused >= fb->len) {
66*7ec1ec4fSAlex Richardson 			wchar_t *wp;
67*7ec1ec4fSAlex Richardson 
68*7ec1ec4fSAlex Richardson 			if (fb->len)
69*7ec1ec4fSAlex Richardson 				fb->len *= 2;
70*7ec1ec4fSAlex Richardson 			else
71*7ec1ec4fSAlex Richardson 				fb->len = FILEWBUF_INIT_LEN;
72*7ec1ec4fSAlex Richardson 
73*7ec1ec4fSAlex Richardson 			wp = reallocarray(fb->wbuf, fb->len, sizeof(wchar_t));
74*7ec1ec4fSAlex Richardson 			if (wp == NULL) {
75*7ec1ec4fSAlex Richardson 				wused = 0;
76*7ec1ec4fSAlex Richardson 				break;
77*7ec1ec4fSAlex Richardson 			}
78*7ec1ec4fSAlex Richardson 			fb->wbuf = wp;
79*7ec1ec4fSAlex Richardson 		}
80*7ec1ec4fSAlex Richardson 
81*7ec1ec4fSAlex Richardson 		fb->wbuf[wused++] = wc;
82*7ec1ec4fSAlex Richardson 
83*7ec1ec4fSAlex Richardson 		if (wc == L'\n')
84*7ec1ec4fSAlex Richardson 			break;
85*7ec1ec4fSAlex Richardson 	}
86*7ec1ec4fSAlex Richardson 
87*7ec1ec4fSAlex Richardson 	*lenp = wused;
88*7ec1ec4fSAlex Richardson 	return wused ? fb->wbuf : NULL;
89*7ec1ec4fSAlex Richardson }
90*7ec1ec4fSAlex Richardson 
91*7ec1ec4fSAlex Richardson libbsd_link_warning(fgetwln,
92*7ec1ec4fSAlex Richardson                     "This function cannot be safely ported, use fgetwc(3) "
93*7ec1ec4fSAlex Richardson                     "instead, as it is supported by C99 and POSIX.1-2001.")
94