From 2a4a51fafc1c12003a12a6b78249bf0b6eec31ba Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 13 Feb 2012 01:07:02 +0100 Subject: [PATCH] Added getline(3), getdelim(3), sortix_gets(3) and gets(3). gets(3) exists and is an alias for sortix_gets(3) if _SORTIX_SOURCE. sortix_gets(3) returns a pointer to a safe newly read and allocated line. --- libmaxsi/include/features.h | 9 +++++++ libmaxsi/include/stdio.h | 15 ++++++++--- libmaxsi/stdio.c | 54 ++++++++++++++++++++++++++++++++++--- 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/libmaxsi/include/features.h b/libmaxsi/include/features.h index c98a0c34..2e5f25a5 100644 --- a/libmaxsi/include/features.h +++ b/libmaxsi/include/features.h @@ -45,6 +45,15 @@ #define _SORTIX_SOURCE 1 #endif +/* Whether to override some "standard" functions with Sortix alternatives. */ +#if !defined(__SORTIX_STDLIB_REDIRECTS) + #if defined(_SORTIX_SOURCE) + #define __SORTIX_STDLIB_REDIRECTS 1 + #else + #define __SORTIX_STDLIB_REDIRECTS 0 + #endif +#endif + #define restrict /* TODO: Improve these declarations, perhaps like they are in glibc. */ diff --git a/libmaxsi/include/stdio.h b/libmaxsi/include/stdio.h index cd783b89..7680ec5e 100644 --- a/libmaxsi/include/stdio.h +++ b/libmaxsi/include/stdio.h @@ -94,13 +94,18 @@ extern off_t ftello(FILE* stream); extern size_t fwrite(const void* restrict ptr, size_t size, size_t nitems, FILE* restrict stream); extern int getc(FILE* stream); extern int getchar(void); +extern ssize_t getdelim(char** restrict lineptr, size_t* restrict n, int delimiter, FILE* restrict stream); +extern ssize_t getline(char** restrict lineptr, size_t* restrict n, FILE* restrict stream); extern void perror(const char* s); extern int printf(const char* restrict format, ...); extern int putc(int c, FILE* stream); extern int putchar(int c); +extern int puts(const char* str); extern int remove(const char* path); extern void rewind(FILE* stream); extern int snprintf(char* restrict s, size_t n, const char* restrict format, ...); +extern char* sortix_gets(void); +extern int sortix_puts(const char* str); extern int sprintf(char* restrict s, const char* restrict format, ...); extern int vfprintf(FILE* restrict stream, const char* restrict format, va_list ap); extern int vprintf(const char* restrict format, va_list ap); @@ -127,7 +132,6 @@ extern int getc_unlocked(FILE* stream); extern int pclose(FILE* steam); extern int putchar_unlocked(int c); extern int putc_unlocked(int c, FILE* steam); -extern int puts(const char* s); extern int rename(const char* oldname, const char* newname); extern int renameat(int oldfd, const char* oldname, int newfd, const char* newname); extern int scanf(const char* restrict format, ...); @@ -138,14 +142,11 @@ extern int vdprintf(int fildes, const char* restrict format, va_list ap); extern int vfscanf(FILE* restrict stream, const char* restrict format, va_list arg); extern int vscanf(const char* restrict format, va_list arg); extern int vsscanf(const char* restrict s, const char* restrict format, va_list arg); -extern ssize_t getdelim(char** restrict lineptr, size_t* restrict n, int delimiter, FILE* restrict stream); -extern ssize_t getline(char** restrict lineptr, size_t* restrict n, FILE* restrict stream); extern void flockfile(FILE* file); extern void funlockfile(FILE* file); extern void setbuf(FILE* restrict stream, char* restrict buf); #if __POSIX_OBSOLETE <= 200801 -extern char* gets(char* s); extern char* tmpnam(char* s); extern char* tempnam(const char* dir, const char* pfx); #endif @@ -158,6 +159,12 @@ FILE* fnewfile(void); int fcloseall(void); #endif +#if __SORTIX_STDLIB_REDIRECTS +inline char* gets(void) { return sortix_gets(); } +#else +/* traditional gets(3) is no longer POSIX, hence removed. */ +#endif + __END_DECLS #endif diff --git a/libmaxsi/stdio.c b/libmaxsi/stdio.c index d3beb827..7ac37ef6 100644 --- a/libmaxsi/stdio.c +++ b/libmaxsi/stdio.c @@ -22,8 +22,11 @@ ******************************************************************************/ +#define __SORTIX_STDLIB_REDIRECTS 0 #include +#include #include +#include #include "fdio.h" FILE* stdin; @@ -48,9 +51,54 @@ int putchar(int c) return fputc(c, stdout); } -/* This function is quite stupid because of its trailing newline that fputs(3) - does not have - but it's still better than gets(3). I'd have left it out if - various programs didn't need it. */ +ssize_t getdelim(char** lineptr, size_t* n, int delim, FILE* fp) +{ + if ( !lineptr || (*lineptr && !n) || !fp ) { errno = EINVAL; return -1; } + const size_t DEFAULT_BUFSIZE = 32UL; + int malloced = !*lineptr; + if ( malloced ) { *lineptr = (char*) malloc(DEFAULT_BUFSIZE); } + if ( !*lineptr ) { return -1; } + size_t bufsize = malloced ? DEFAULT_BUFSIZE : *n; + if ( n ) { *n = bufsize; } + ssize_t written = 0; + int c; + do + { + if ( (c = getc(fp)) == EOF ) { goto cleanup; } + if ( bufsize <= (size_t) written + 1UL ) + { + size_t newbufsize = 2UL * bufsize; + char* newbuf = (char*) realloc(*lineptr, newbufsize); + if ( !newbuf ) { goto cleanup; } + bufsize = newbufsize; + if ( n ) { *n = bufsize; } + *lineptr = newbuf; + } + (*lineptr)[written++] = c; + } while ( c != delim ); + (*lineptr)[written] = 0; + return written; + +cleanup: + free(malloced ? *lineptr : NULL); + return -1; +} + +ssize_t getline(char** lineptr, size_t* n, FILE* fp) +{ + return getdelim(lineptr, n, '\n', fp); +} + +char* sortix_gets(void) +{ + char* buf = NULL; + size_t n; + if ( getline(&buf, &n, stdin) < 0 ) { return NULL; } + size_t linelen = strlen(buf); + if ( linelen && buf[linelen-1] == '\n' ) { buf[linelen-1] = 0; } + return buf; +} + int puts(const char* str) { return printf("%s\n", str) < 0 ? EOF : 1;