From 3dacb9003cc59617874784ae41751236aff57a10 Mon Sep 17 00:00:00 2001 From: Ralph Corderoy Date: Tue, 11 Oct 2016 10:14:14 -0400 Subject: [PATCH] I've written a getline(3) from scratch based on https://manned.org/getdelim.3p and am happy for it to have whatever licence nmh needs. --- configure.ac | 3 +- sbr/getline.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 sbr/getline.c diff --git a/configure.ac b/configure.ac index c778a150..b87dd644 100644 --- a/configure.ac +++ b/configure.ac @@ -96,7 +96,8 @@ dnl CHECK HEADER FILES dnl ------------------ AC_HEADER_TIOCGWINSZ -AC_CHECK_HEADERS([fcntl.h wchar.h wctype.h sys/param.h sys/time.h sys/stream.h]) +AC_CHECK_HEADERS([fcntl.h stdbool.h wchar.h wctype.h \ + sys/param.h sys/time.h sys/stream.h]) AC_CHECK_HEADER([sys/ptem.h], AC_DEFINE(WINSIZE_IN_PTEM,1, [Define to 1 if `struct winsize' requires .]),, diff --git a/sbr/getline.c b/sbr/getline.c new file mode 100644 index 00000000..7e3e7978 --- /dev/null +++ b/sbr/getline.c @@ -0,0 +1,86 @@ +/* + * getline.c -- replacement getline() implementation + * + * This code is Copyright (c) 2016, by the authors of nmh. See the + * COPYRIGHT file in the root directory of the nmh distribution for + * complete copyright information. + */ + +#include +#include +#include +#include +#ifdef HAVE_STDBOOL_H +# include +#else /* ! HAVE_STDBOOL_H */ +# define bool int +# define true 1 +# define false 0 +#endif /* ! HAVE_STDBOOL_H */ + +/* Largest possible size of buffer that allows SSIZE_MAX to be returned + * to indicate SSIZE_MAX - 1 characters read before the '\n'. The + * additional 1 is for the terminating NUL. */ +#define MAX_AVAIL ((size_t)SSIZE_MAX + 1) + +/* Ideal increase in size of line buffer. */ +#define GROWTH 128 + +ssize_t getline(char **lineptr, size_t *n, FILE *stream) +{ + char *l; + size_t avail; + size_t used; + int c; + bool last; + + if (!lineptr || !n) { + errno = EINVAL; + return -1; + } + + l = *lineptr; + if (l) + avail = *n <= MAX_AVAIL ? *n : MAX_AVAIL; + else + avail = *n = 0; /* POSIX allows *lineptr = NULL, *n = 42. */ + used = 0; + last = false; + for (;;) { + c = getc(stream); + if (c == EOF) { + if (ferror(stream) || /* errno set by stdlib. */ + !used) /* EOF with nothing read. */ + return -1; + /* Line will be returned without a \n terminator. */ +append_nul: + c = '\0'; + last = true; + } + + if (used == avail) { + size_t want; + char *new; + + if (avail == MAX_AVAIL) { + errno = EOVERFLOW; + return -1; + } + want = avail + GROWTH; + if (want > MAX_AVAIL) + want = MAX_AVAIL; + new = realloc(l, want); + if (!new) + return -1; /* errno set by stdlib. */ + l = *lineptr = new; + avail = *n = want; + } + l[used++] = c; + + if (last) + return used - 1; /* Don't include NUL. */ + + if (c == '\n') + goto append_nul; /* Final half loop. */ + } +} -- 2.56.0