libm: allow long double wrappers for all architectures
[uclibc-ng.git] / libc / stdio / getdelim.c
blob987e32a199a8d8251e062c5aa1731e6a14b90dae
1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
8 #include <features.h>
10 #ifdef __USE_GNU
11 #include "_stdio.h"
15 /* Note: There is a defect in this function. (size_t vs ssize_t). */
17 /* glibc function --
18 * Return -1 if error or EOF prior to any chars read.
19 * Return number of chars read (including possible delimiter but not
20 * the terminating nul) otherwise.
22 * NOTE: If we need to allocate a buffer, we do so prior to attempting
23 * a reading. So space may be allocated even if initially at EOF.
26 #define GETDELIM_GROWBY 64
28 ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n,
29 int delimiter, register FILE *__restrict stream)
31 register char *buf;
32 ssize_t pos = -1;
33 int c;
34 __STDIO_AUTO_THREADLOCK_VAR;
36 if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */
37 __set_errno(EINVAL); /* though I think we should assert here */
38 } else {
39 __STDIO_AUTO_THREADLOCK(stream);
41 if (!(buf = *lineptr)) { /* If passed NULL for buffer, */
42 *n = 0; /* ignore value passed and treat size as 0. */
45 /* Within the loop, pos is actually the current buffer index + 2,
46 * because we want to make sure we have enough space to store
47 * an additional char plus a nul terminator.
49 pos = 1;
51 do {
52 if (pos >= *n) {
53 if (!(buf = realloc(buf, *n + GETDELIM_GROWBY))) {
54 pos = -1;
55 break;
57 *n += GETDELIM_GROWBY;
58 *lineptr = buf;
61 if ((c = __GETC_UNLOCKED(stream)) != EOF) {
62 buf[++pos - 2] = c;
63 if (c != delimiter) {
64 continue;
68 /* We're done, so correct pos back to being the current index. */
69 if ((pos -= 2) >= 0) {
70 buf[++pos] = 0;
72 break;
74 } while (1);
76 __STDIO_AUTO_THREADUNLOCK(stream);
79 return pos;
81 libc_hidden_def(getdelim)
82 #endif