From ef2f334e88fcd5daffc4c72dfc51794927c75920 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Thu, 17 Jul 2003 16:23:52 +0000 Subject: [PATCH] New module 'getnline'. --- ChangeLog | 6 +++ MODULES.html.sh | 1 + lib/ChangeLog | 10 +++++ lib/getline.c | 95 ++--------------------------------------- lib/getndelim2.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/getnline.c | 37 ++++++++++++++++ lib/getnline.h | 49 +++++++++++++++++++++ m4/ChangeLog | 4 ++ m4/getnline.m4 | 15 +++++++ modules/getline | 2 + modules/getnline | 26 ++++++++++++ 11 files changed, 281 insertions(+), 91 deletions(-) create mode 100644 lib/getndelim2.c create mode 100644 lib/getnline.c create mode 100644 lib/getnline.h create mode 100644 m4/getnline.m4 create mode 100644 modules/getnline diff --git a/ChangeLog b/ChangeLog index 691b5ca5d..f51440e74 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2003-07-17 Bruno Haible + * modules/getnline: New file. + * modules/getline: Add lib/getndelim2.c to source file list. + * MODULES.html.sh (func_all_modules): Add getnline. + +2003-07-17 Bruno Haible + * configure.in: Remove file. * Makefile.in: Remove file. diff --git a/MODULES.html.sh b/MODULES.html.sh index ac653ff55..9d6eef392 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -1579,6 +1579,7 @@ func_all_modules () func_begin_table func_module diacrit func_module getline + func_module getnline func_module linebuffer func_module obstack func_module hash-pjw diff --git a/lib/ChangeLog b/lib/ChangeLog index 5f395ece2..2af31c927 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,13 @@ +2003-07-17 Bruno Haible + + * getnline.h: New file. + * getnline.c: New file. + * getndelim2.c: New file, extracted from getline.c. + (getndelim2): Renamed from getdelim2, with added nmax argument. + * getline.c: Include getndelim2.c. + (getdelim2): Moved out to getndelim2.c. + (getline, getdelim): Update. + 2003-07-15 * vasnprintf.c: update from gettext. diff --git a/lib/getline.c b/lib/getline.c index f4edecc8a..ccc3b4a39 100644 --- a/lib/getline.c +++ b/lib/getline.c @@ -23,6 +23,7 @@ # include #endif +/* Specification. */ #include "getline.h" /* The `getdelim' function is only declared if the following symbol @@ -44,105 +45,17 @@ getline (char **lineptr, size_t *n, FILE *stream) #else /* ! have getdelim */ -# if STDC_HEADERS -# include -# else -char *malloc (), *realloc (); -# endif - -#include "unlocked-io.h" - -/* Always add at least this many bytes when extending the buffer. */ -#define MIN_CHUNK 64 - -/* Read up to (and including) a delimiter DELIM1 from STREAM into *LINEPTR - + OFFSET (and NUL-terminate it). If DELIM2 is non-zero, then read up - and including the first occurrence of DELIM1 or DELIM2. *LINEPTR is - a pointer returned from malloc (or NULL), pointing to *N characters of - space. It is realloc'd as necessary. Return the number of characters - read (not including the NUL terminator), or -1 on error or EOF. */ - -static int -getdelim2 (char **lineptr, size_t *n, FILE *stream, int delim1, int delim2, - size_t offset) -{ - size_t nchars_avail; /* Allocated but unused chars in *LINEPTR. */ - char *read_pos; /* Where we're reading into *LINEPTR. */ - int ret; - - if (!lineptr || !n || !stream) - return -1; - - if (!*lineptr) - { - *n = MIN_CHUNK; - *lineptr = malloc (*n); - if (!*lineptr) - return -1; - } - - if (*n < offset) - return -1; - - nchars_avail = *n - offset; - read_pos = *lineptr + offset; - - for (;;) - { - register int c = getc (stream); - - /* We always want at least one char left in the buffer, since we - always (unless we get an error while reading the first char) - NUL-terminate the line buffer. */ - - if (nchars_avail < 2) - { - if (*n > MIN_CHUNK) - *n *= 2; - else - *n += MIN_CHUNK; - - nchars_avail = *n + *lineptr - read_pos; - *lineptr = realloc (*lineptr, *n); - if (!*lineptr) - return -1; - read_pos = *n - nchars_avail + *lineptr; - } - - if (c == EOF || ferror (stream)) - { - /* Return partial line, if any. */ - if (read_pos == *lineptr) - return -1; - else - break; - } - - *read_pos++ = c; - nchars_avail--; - - if (c == delim1 || (delim2 && c == delim2)) - /* Return the line. */ - break; - } - - /* Done - NUL terminate and return the number of chars read. */ - *read_pos = '\0'; - - ret = read_pos - (*lineptr + offset); - return ret; -} - +#include "getndelim2.c" int getline (char **lineptr, size_t *n, FILE *stream) { - return getdelim2 (lineptr, n, stream, '\n', 0, 0); + return getndelim2 (lineptr, n, (size_t)(-1), stream, '\n', 0, 0); } int getdelim (char **lineptr, size_t *n, int delimiter, FILE *stream) { - return getdelim2 (lineptr, n, stream, delimiter, 0, 0); + return getndelim2 (lineptr, n, (size_t)(-1), stream, delimiter, 0, 0); } #endif diff --git a/lib/getndelim2.c b/lib/getndelim2.c new file mode 100644 index 000000000..bceb70fbe --- /dev/null +++ b/lib/getndelim2.c @@ -0,0 +1,127 @@ +/* getndelim2 - Core of getline, getdelim, getnline, getndelim. + + Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003 Free Software + Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if STDC_HEADERS +# include +#else +char *malloc (), *realloc (); +#endif + +#include "unlocked-io.h" + +/* Always add at least this many bytes when extending the buffer. */ +#define MIN_CHUNK 64 + +/* Read up to (and including) a delimiter DELIM1 from STREAM into *LINEPTR + + OFFSET (and NUL-terminate it). If DELIM2 is non-zero, then read up + and including the first occurrence of DELIM1 or DELIM2. *LINEPTR is + a pointer returned from malloc (or NULL), pointing to *LINESIZE bytes of + space. It is realloc'd as necessary. Reallocation is limited to + NMAX bytes; if the line is longer than that, the extra bytes are read but + thrown away. + Return the number of bytes read and stored at *LINEPTR + OFFSET (not + including the NUL terminator), or -1 on error or EOF. */ + +static int +getndelim2 (char **lineptr, size_t *linesize, size_t nmax, + FILE *stream, int delim1, int delim2, size_t offset) +{ + size_t nbytes_avail; /* Allocated but unused chars in *LINEPTR. */ + char *read_pos; /* Where we're reading into *LINEPTR. */ + + if (!lineptr || !linesize || !nmax || !stream) + return -1; + + if (!*lineptr) + { + size_t newlinesize = MIN_CHUNK; + + if (newlinesize > nmax) + newlinesize = nmax; + + *linesize = newlinesize; + *lineptr = malloc (*linesize); + if (!*lineptr) + return -1; + } + + if (*linesize < offset) + return -1; + + nbytes_avail = *linesize - offset; + read_pos = *lineptr + offset; + + if (nbytes_avail == 0 && *linesize >= nmax) + return -1; + + for (;;) + { + /* Here always *lineptr + *linesize == read_pos + nbytes_avail. */ + + register int c = getc (stream); + + /* We always want at least one char left in the buffer, since we + always (unless we get an error while reading the first char) + NUL-terminate the line buffer. */ + + if (nbytes_avail < 2 && *linesize < nmax) + { + size_t newlinesize = + (*linesize > MIN_CHUNK ? 2 * *linesize : *linesize + MIN_CHUNK); + + if (newlinesize > nmax) + newlinesize = nmax; + + if (newlinesize > *linesize) + { + *linesize = newlinesize; + nbytes_avail = *linesize + *lineptr - read_pos; + *lineptr = realloc (*lineptr, *linesize); + if (!*lineptr) + return -1; + read_pos = *linesize - nbytes_avail + *lineptr; + } + } + + if (c == EOF || ferror (stream)) + { + /* Return partial line, if any. */ + if (read_pos == *lineptr) + return -1; + else + break; + } + + if (nbytes_avail >= 2) + { + *read_pos++ = c; + nbytes_avail--; + } + + if (c == delim1 || (delim2 && c == delim2)) + /* Return the line. */ + break; + } + + /* Done - NUL terminate and return the number of chars read. + At this point we know that nbytes_avail >= 1. */ + *read_pos = '\0'; + + return read_pos - (*lineptr + offset); +} diff --git a/lib/getnline.c b/lib/getnline.c new file mode 100644 index 000000000..311bb1d7b --- /dev/null +++ b/lib/getnline.c @@ -0,0 +1,37 @@ +/* getnline - Read a line from a stream, with bounded memory allocation. + + Copyright (C) 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +/* Specification. */ +#include "getnline.h" + +ssize_t +getnline (char **lineptr, size_t *linesize, size_t nmax, FILE *stream) +{ + return getndelim2 (lineptr, linesize, (size_t)(-1), stream, '\n', 0, 0); +} + +ssize_t +getndelim (char **lineptr, size_t *linesize, size_t nmax, + int delimiter, FILE *stream) +{ + return getndelim2 (lineptr, linesize, (size_t)(-1), stream, delimiter, 0, 0); +} diff --git a/lib/getnline.h b/lib/getnline.h new file mode 100644 index 000000000..e455300ab --- /dev/null +++ b/lib/getnline.h @@ -0,0 +1,49 @@ +/* getnline - Read a line from a stream, with bounded memory allocation. + + Copyright (C) 2003 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GETNLINE_H +#define GETNLINE_H 1 + +#include +#include + +/* Get ssize_t. */ +#include + +/* Read a line, up to the next newline, from STREAM, and store it in *LINEPTR. + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. Reallocation is limited to + NMAX bytes; if the line is longer than that, the extra bytes are read but + thrown away. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +extern ssize_t getnline (char **lineptr, size_t *linesize, size_t nmax, + FILE *stream); + +/* Read a line, up to the next occurrence of DELIMITER, from STREAM, and store + it in *LINEPTR. + *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE + bytes of space. It is realloc'd as necessary. Reallocation is limited to + NMAX bytes; if the line is longer than that, the extra bytes are read but + thrown away. + Return the number of bytes read and stored at *LINEPTR (not including the + NUL terminator), or -1 on error or EOF. */ +extern ssize_t getndelim (char **lineptr, size_t *linesize, size_t nmax, + int delimiter, FILE *stream); + +#endif /* GETNLINE_H */ diff --git a/m4/ChangeLog b/m4/ChangeLog index e409b2acb..ea545ecbc 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,7 @@ +2003-07-17 Bruno Haible + + * getnline.m4: New file. + 2003-07-14 Simon Josefsson * mempcpy.m4: New file. diff --git a/m4/getnline.m4 b/m4/getnline.m4 new file mode 100644 index 000000000..c83ab36c4 --- /dev/null +++ b/m4/getnline.m4 @@ -0,0 +1,15 @@ +# getnline.m4 serial 1 +dnl Copyright (C) 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +AC_DEFUN([gl_GETNLINE], +[ + dnl Prerequisites of lib/getnline.h. + AC_REQUIRE([gt_TYPE_SSIZE_T]) + dnl Prerequisites of lib/getnline.c. + AC_REQUIRE([AC_HEADER_STDC]) +]) diff --git a/modules/getline b/modules/getline index e584a466d..e7f6f56fe 100644 --- a/modules/getline +++ b/modules/getline @@ -4,6 +4,7 @@ Read a line from a stream. Files: lib/getline.h lib/getline.c +lib/getndelim2.c m4/getline.m4 Depends-on: @@ -14,6 +15,7 @@ AM_FUNC_GETLINE Makefile.am: lib_SOURCES += getline.h +EXTRA_DIST += getndelim2.c Include: "getline.h" diff --git a/modules/getnline b/modules/getnline new file mode 100644 index 000000000..e57895483 --- /dev/null +++ b/modules/getnline @@ -0,0 +1,26 @@ +Description: +Read a line from a stream, with bounded memory allocation. + +Files: +lib/getnline.h +lib/getnline.c +lib/getndelim2.c +m4/getnline.m4 +m4/ssize_t.m4 + +Depends-on: +unlocked-io + +configure.ac: +gl_GETNLINE + +Makefile.am: +lib_SOURCES += getnline.h +EXTRA_DIST += getndelim2.c + +Include: +"getnline.h" + +Maintainer: +all + -- 2.11.0