fgetwln.c revision 1.8
11.8Schristos/* $NetBSD: fgetwln.c,v 1.8 2016/08/27 13:15:48 christos Exp $ */ 21.1Schristos 31.1Schristos/*- 41.1Schristos * Copyright (c) 2002-2004 Tim J. Robbins. 51.1Schristos * All rights reserved. 61.1Schristos * 71.1Schristos * Redistribution and use in source and binary forms, with or without 81.1Schristos * modification, are permitted provided that the following conditions 91.1Schristos * are met: 101.1Schristos * 1. Redistributions of source code must retain the above copyright 111.1Schristos * notice, this list of conditions and the following disclaimer. 121.1Schristos * 2. Redistributions in binary form must reproduce the above copyright 131.1Schristos * notice, this list of conditions and the following disclaimer in the 141.1Schristos * documentation and/or other materials provided with the distribution. 151.1Schristos * 161.1Schristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 171.1Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 181.1Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191.1Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 201.1Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 211.1Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 221.1Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 231.1Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 241.1Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251.1Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261.1Schristos * SUCH DAMAGE. 271.1Schristos */ 281.1Schristos 291.1Schristos#include <sys/cdefs.h> 301.1Schristos#if defined(LIBC_SCCS) && !defined(lint) 311.1Schristos#if 0 321.1Schristos__FBSDID("$FreeBSD: src/lib/libc/stdio/fgetwln.c,v 1.2 2004/08/06 17:00:09 tjr Exp $"); 331.1Schristos#else 341.8Schristos__RCSID("$NetBSD: fgetwln.c,v 1.8 2016/08/27 13:15:48 christos Exp $"); 351.1Schristos#endif 361.1Schristos#endif /* LIBC_SCCS and not lint */ 371.1Schristos 381.1Schristos#include "namespace.h" 391.3Sroy#include <assert.h> 401.3Sroy#include <errno.h> 411.3Sroy#include <limits.h> 421.1Schristos#include <stdio.h> 431.3Sroy#include <stdlib.h> 441.1Schristos#include <wchar.h> 451.1Schristos#include "reentrant.h" 461.1Schristos#include "local.h" 471.1Schristos 481.1Schristos#ifdef __weak_alias 491.1Schristos__weak_alias(fgetwln,_fgetwln) 501.1Schristos#endif 511.1Schristos 521.3Sroy/* 531.3Sroy * Expand the line buffer. Return -1 on error. 541.3Sroy#ifdef notdef 551.3Sroy * The `new size' does not account for a terminating '\0', 561.3Sroy * so we add 1 here. 571.3Sroy#endif 581.3Sroy */ 591.3Sroystatic int 601.3Sroy__slbexpand(FILE *fp, size_t newsize) 611.3Sroy{ 621.3Sroy void *p; 631.3Sroy 641.3Sroy#ifdef notdef 651.3Sroy ++newsize; 661.3Sroy#endif 671.3Sroy _DIAGASSERT(fp != NULL); 681.3Sroy 691.4Sjoerg if (_EXT(fp)->_fgetstr_len >= newsize) 701.5Schristos return 0; 711.4Sjoerg if ((p = realloc(_EXT(fp)->_fgetstr_buf, newsize)) == NULL) 721.5Schristos return -1; 731.4Sjoerg _EXT(fp)->_fgetstr_buf = p; 741.4Sjoerg _EXT(fp)->_fgetstr_len = newsize; 751.5Schristos return 0; 761.3Sroy} 771.3Sroy 781.1Schristoswchar_t * 791.1Schristosfgetwln(FILE * __restrict fp, size_t *lenp) 801.1Schristos{ 811.1Schristos wint_t wc; 821.1Schristos size_t len; 831.1Schristos 841.1Schristos FLOCKFILE(fp); 851.1Schristos _SET_ORIENTATION(fp, 1); 861.1Schristos 871.1Schristos len = 0; 881.1Schristos while ((wc = __fgetwc_unlock(fp)) != WEOF) { 891.1Schristos#define GROW 512 901.4Sjoerg if (len * sizeof(wchar_t) >= _EXT(fp)->_fgetstr_len && 911.8Schristos __slbexpand(fp, (len + GROW) * sizeof(wchar_t))) { 921.8Schristos fp->_flags |= __SERR; 931.1Schristos goto error; 941.8Schristos } 951.4Sjoerg *((wchar_t *)(void *)_EXT(fp)->_fgetstr_buf + len++) = wc; 961.1Schristos if (wc == L'\n') 971.1Schristos break; 981.1Schristos } 991.8Schristos 1001.8Schristos /* 1011.8Schristos * The following test assumes that fgetwc() fails when 1021.8Schristos * feof() is already set, and that fgetwc() will never 1031.8Schristos * set feof() in the same call where it also sets ferror() 1041.8Schristos * or returns non-WEOF. 1051.8Schristos * Testing ferror() would not be better because fgetwc() 1061.8Schristos * may succeed even when ferror() is already set. 1071.8Schristos */ 1081.8Schristos 1091.8Schristos if (len == 0 || (wc == WEOF && !__sfeof(fp))) 1101.1Schristos goto error; 1111.1Schristos 1121.1Schristos FUNLOCKFILE(fp); 1131.1Schristos *lenp = len; 1141.5Schristos return (wchar_t *)(void *)_EXT(fp)->_fgetstr_buf; 1151.1Schristos 1161.1Schristoserror: 1171.1Schristos FUNLOCKFILE(fp); 1181.1Schristos *lenp = 0; 1191.5Schristos return NULL; 1201.1Schristos} 121