Hi Ken,
> > I think that buf may only be len long on occasion when the NUL is
> > added.
>
> So could we get a Ralph-ified version? I think the necessary
> configure glue should be straightforward, but someone else will have
> to test it. I'd be glad to commit it, though.
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. I've assumed POSIX, e.g. stdbool.h, SSIZE_MAX, etc.,
so it may need some conditional preprocessor bits for portability to
older systems.
It's quite a fun problem because it's a bit of a "loop and a half" where
you don't want more input, but need to produce a bit more output. One
can spend ages re-arranging the deckchairs, but I finally went with the
attached.
--
Cheers, Ralph.
https://plus.google.com/+RalphCorderoy
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
#include <errno.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. */
}
}
_______________________________________________
Nmh-workers mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/nmh-workers