Commit a97ce513e031b29a47965b740be14fb9a84277fc

Guillem Jover 2012-11-23T21:19:45

Add new fgetwln() function Man page taken from FreeBSD.

diff --git a/include/bsd/wchar.h b/include/bsd/wchar.h
index 9b16f53..a7e25bf 100644
--- a/include/bsd/wchar.h
+++ b/include/bsd/wchar.h
@@ -38,6 +38,8 @@
 #include <sys/types.h>
 
 __BEGIN_DECLS
+wchar_t *fgetwln(FILE *stream, size_t *len);
+
 size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size);
 size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t size);
 __END_DECLS
diff --git a/man/Makefile.am b/man/Makefile.am
index 6881f12..eb9c133 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -24,6 +24,7 @@ dist_man_MANS = \
 	dehumanize_number.3 \
 	expand_number.3 \
 	fgetln.3 \
+	fgetwln.3 \
 	flopen.3 \
 	fmtcheck.3 \
 	fparseln.3 \
diff --git a/man/fgetwln.3 b/man/fgetwln.3
new file mode 100644
index 0000000..0372d21
--- /dev/null
+++ b/man/fgetwln.3
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)fgetln.3	8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd July 16, 2004
+.Dt FGETWLN 3
+.Os
+.Sh NAME
+.Nm fgetwln
+.Nd get a line of wide characters from a stream
+.Sh LIBRARY
+.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
+.Lb libbsd
+.Sh SYNOPSIS
+.In stdio.h
+.In bsd/wchar.h
+.Ft wchar_t *
+.Fn fgetwln "FILE * restrict stream" "size_t * restrict len"
+.Sh DESCRIPTION
+The
+.Fn fgetwln
+function
+returns a pointer to the next line from the stream referenced by
+.Fa stream .
+This line is
+.Em not
+a standard wide character string as it does not end with a terminating
+null wide character.
+The length of the line, including the final newline,
+is stored in the memory location to which
+.Fa len
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
+.Sh RETURN VALUES
+Upon successful completion a pointer is returned;
+this pointer becomes invalid after the next
+.Tn I/O
+operation on
+.Fa stream
+(whether successful or not)
+or as soon as the stream is closed.
+Otherwise,
+.Dv NULL
+is returned.
+The
+.Fn fgetwln
+function
+does not distinguish between end-of-file and error; the routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used
+to determine which occurred.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv NULL
+until the condition is
+cleared with
+.Xr clearerr 3 .
+.Pp
+The text to which the returned pointer points may be modified,
+provided that no changes are made beyond the returned size.
+These changes are lost as soon as the pointer becomes invalid.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa stream
+is not a stream open for reading.
+.El
+.Pp
+The
+.Fn fgetwln
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr mbrtowc 3 ,
+.Xr realloc 3 ,
+or
+.Xr read 2 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgetln 3 ,
+.Xr fgetws 3 ,
+.Xr fopen 3
diff --git a/src/Makefile.am b/src/Makefile.am
index 2146438..95ebbb9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,7 @@ libbsd_la_SOURCES = \
 	err.c \
 	expand_number.c \
 	fgetln.c \
+	fgetwln.c \
 	flopen.c \
 	fmtcheck.c \
 	fparseln.c \
diff --git a/src/fgetwln.c b/src/fgetwln.c
new file mode 100644
index 0000000..2473932
--- /dev/null
+++ b/src/fgetwln.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2012 Guillem Jover <guillem@hadrons.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+
+struct filewbuf {
+	FILE *fp;
+	wchar_t *wbuf;
+	size_t len;
+};
+
+#define FILEWBUF_INIT_LEN	128
+#define FILEWBUF_POOL_ITEMS	32
+
+static struct filewbuf fb_pool[FILEWBUF_POOL_ITEMS];
+static int fb_pool_cur;
+
+wchar_t *
+fgetwln(FILE *stream, size_t *lenp)
+{
+	struct filewbuf *fb;
+	wint_t wc;
+	size_t wused = 0;
+
+	/* Try to diminish the possibility of several fgetwln() calls being
+	 * used on different streams, by using a pool of buffers per file. */
+	fb = &fb_pool[fb_pool_cur];
+	if (fb->fp != stream && fb->fp != NULL) {
+		fb_pool_cur++;
+		fb_pool_cur %= FILEWBUF_POOL_ITEMS;
+		fb = &fb_pool[fb_pool_cur];
+	}
+	fb->fp = stream;
+
+	while ((wc = fgetwc(stream)) != WEOF) {
+		if (!fb->len || wused > fb->len) {
+			wchar_t *wp;
+
+			if (fb->len)
+				fb->len *= 2;
+			else
+				fb->len = FILEWBUF_INIT_LEN;
+
+			wp = realloc(fb->wbuf, fb->len * sizeof(wchar_t));
+			if (wp == NULL) {
+				wused = 0;
+				break;
+			}
+			fb->wbuf = wp;
+		}
+
+		fb->wbuf[wused++] = wc;
+
+		if (wc == L'\n')
+			break;
+	}
+
+	*lenp = wused;
+	return wused ? fb->wbuf : NULL;
+}
diff --git a/src/libbsd.map b/src/libbsd.map
index 488267c..e900ee3 100644
--- a/src/libbsd.map
+++ b/src/libbsd.map
@@ -96,6 +96,7 @@ LIBBSD_0.4 {
 } LIBBSD_0.3;
 
 LIBBSD_0.5 {
+    fgetwln;
     fparseln;
 
     strnstr;