-/*
- * Copyright © 2024 Nick Bowler
- *
- * getline-like function which removes trailing newline (if any), and
- * returns nonzero if and only if a line was successfully read.
- *
- * 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 3 of the License, 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, see <https://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <errno.h>
-
-#ifdef CDECL_TEST_H_
-/*
- * Use the minimum initial alloc size in the test programs to ensure we at
- * least are exercising the realloc path on a reasonably regular basis.
- */
-# define CDECL99_GETLINE_INITIAL_ALLOC 1
-#else
-# define CDECL99_GETLINE_INITIAL_ALLOC 75
-#endif
-
-static inline int do_getline(char **linebuf, size_t *n)
-{
- extern void print_error(const char *fmt, ...);
- const char *errmsg;
-
-#if HAVE_GETLINE
- ssize_t rc;
-
- if ((rc = getline(linebuf, n, stdin)) < 0) {
- if (ferror(stdin))
- goto input_error;
- return 0;
- }
-
- if (rc-- && (*linebuf)[rc] == '\n')
- (*linebuf)[rc] = '\0';
- return 1;
-#else
- char *work = *linebuf;
- size_t pos = 0;
- size_t sz;
-
- if (!work) {
- sz = CDECL99_GETLINE_INITIAL_ALLOC;
- goto initial_alloc;
- }
-
- for (sz = *n;;) {
- if (!fgets(&work[pos], sz - pos, stdin)) {
- if (ferror(stdin))
- goto input_error;
-
- return !!pos;
- }
-
- pos += strlen(&work[pos]);
- if (work[pos-1] == '\n') {
- work[pos-1] = '\0';
- return 1;
- }
-
- if (sz > INT_MAX/2 || sz > ((size_t)-1)/4)
- break;
-
- sz = ((sz*4) + 2) / 3;
-initial_alloc:
- work = realloc(work, sz);
- if (!work)
- break;
- *linebuf = work;
- *n = sz;
- }
-
- errmsg = _("failed to allocate memory");
-#endif
- if (0) input_error: errmsg = strerror(errno);
- print_error("%s", errmsg);
- return 0;
-}
-