diff options
| author | Man, Jianting (Meco) <[email protected]> | 2022-06-19 09:56:24 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-06-19 21:56:24 +0800 |
| commit | 8bee7a0c232f5df03e620b41cfc03347c1acfbf1 (patch) | |
| tree | a37469cd64ce669afabc05b243c77bc0b5b19feb /components/libc/compilers/common/cstdio.c | |
| parent | 8fa16f968a2e952fc8be84dc69724aa90ffa9b37 (diff) | |
[libc] implement extension standard C functions (#6044)
* implement extension standard C functions
Diffstat (limited to 'components/libc/compilers/common/cstdio.c')
| -rw-r--r-- | components/libc/compilers/common/cstdio.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/components/libc/compilers/common/cstdio.c b/components/libc/compilers/common/cstdio.c new file mode 100644 index 0000000000..3dffe55aa7 --- /dev/null +++ b/components/libc/compilers/common/cstdio.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2014-05-22 ivanrad implement getline + */ + +#include "posix/stdio.h" +#include <stdlib.h> +#include <limits.h> +#include <sys/errno.h> + +ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream) +{ + char *cur_pos, *new_lineptr; + size_t new_lineptr_len; + int c; + + if (lineptr == NULL || n == NULL || stream == NULL) + { + errno = EINVAL; + return -1; + } + + if (*lineptr == NULL) + { + *n = 128; /* init len */ + if ((*lineptr = (char *)malloc(*n)) == NULL) + { + errno = ENOMEM; + return -1; + } + } + + cur_pos = *lineptr; + for (;;) + { + c = getc(stream); + + if (ferror(stream) || (c == EOF && cur_pos == *lineptr)) + return -1; + + if (c == EOF) + break; + + if ((*lineptr + *n - cur_pos) < 2) + { + if (LONG_MAX / 2 < *n) + { +#ifdef EOVERFLOW + errno = EOVERFLOW; +#else + errno = ERANGE; /* no EOVERFLOW defined */ +#endif + return -1; + } + new_lineptr_len = *n * 2; + + if ((new_lineptr = (char *)realloc(*lineptr, new_lineptr_len)) == NULL) + { + errno = ENOMEM; + return -1; + } + cur_pos = new_lineptr + (cur_pos - *lineptr); + *lineptr = new_lineptr; + *n = new_lineptr_len; + } + + *cur_pos++ = (char)c; + + if (c == delim) + break; + } + + *cur_pos = '\0'; + return (ssize_t)(cur_pos - *lineptr); +} + +ssize_t getline(char **lineptr, size_t *n, FILE *stream) +{ + return getdelim(lineptr, n, '\n', stream); +} |
