diff --git a/library/stdio_gets.c b/library/stdio_gets.c index c470a90..f1bb135 100644 --- a/library/stdio_gets.c +++ b/library/stdio_gets.c @@ -1,10 +1,8 @@ /* - * $Id: stdio_gets.c,v 1.6 2006-01-08 12:04:24 obarthel Exp $ - * * :ts=4 * * Portable ISO 'C' (1994) runtime library for the Amiga computer - * Copyright (c) 2002-2015 by Olaf Barthel + * Copyright (c) 2002-2019 by Olaf Barthel * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +44,8 @@ char * gets(char *s) { + FILE * stream = stdin; + struct iob * file = (struct iob *)stream; char * result = s; int c; @@ -53,16 +53,16 @@ gets(char *s) SHOWPOINTER(s); - assert( s != NULL && stdin != NULL ); + assert( s != NULL ); if(__check_abort_enabled) __check_abort(); - flockfile(stdin); + flockfile(stream); #if defined(CHECK_FOR_NULL_POINTERS) { - if(s == NULL || stdin == NULL) + if(s == NULL) { SHOWMSG("invalid parameters"); @@ -77,21 +77,55 @@ gets(char *s) /* Take care of the checks and data structure changes that * need to be handled only once for this stream. */ - if(__fgetc_check(stdin) < 0) + if(__fgetc_check(stream) < 0) { result = NULL; goto out; } /* So that we can tell error and 'end of file' conditions apart. */ - clearerr(stdin); + clearerr(stream); while(TRUE) { - c = __getc(stdin); + /* If there is data in the buffer, try to copy it directly + into the string buffer. If there is a line feed in the + buffer, too, try to conclude the read operation. */ + if(file->iob_BufferPosition < file->iob_BufferReadBytes) + { + size_t num_bytes_in_buffer = file->iob_BufferReadBytes - file->iob_BufferPosition; + const unsigned char * buffer = &file->iob_Buffer[file->iob_BufferPosition]; + const unsigned char * lf; + + /* Try to find a line feed character which could conclude + the read operation if the remaining buffer data, including + the line feed character, fit into the string buffer. */ + lf = (unsigned char *)memchr(buffer, '\n', num_bytes_in_buffer); + if(lf != NULL) + { + size_t num_characters_in_line = lf + 1 - buffer; + + /* Copy the remainder of the read buffer into the + string buffer, including the terminating line + feed character. */ + memmove(s, buffer, num_characters_in_line); + + file->iob_BufferPosition += num_characters_in_line; + + /* And that concludes the line read operation. */ + break; + } + + memmove(s, buffer, num_bytes_in_buffer); + s += num_bytes_in_buffer; + + file->iob_BufferPosition += num_bytes_in_buffer; + } + + c = __getc(stream); if(c == EOF) { - if(ferror(stdin)) + if(ferror(stream)) { /* Just to be on the safe side. */ (*s) = '\0'; @@ -120,7 +154,7 @@ gets(char *s) out: - funlockfile(stdin); + funlockfile(stream); RETURN(result); return(result);