X-Git-Url: https://pd.if.org/git/?p=pdclib;a=blobdiff_plain;f=functions%2Fstdio%2Ffgets.c;h=8752892bedc1a26103fe375089a5fff82b4b111b;hp=556e426f9cd4bbafe63151def1dcd83018042353;hb=da0f3f353d417fed71f358a48d5d5394145e460d;hpb=0a5395faab237ba9008352b0f4bee9659bbd3d5f diff --git a/functions/stdio/fgets.c b/functions/stdio/fgets.c index 556e426..8752892 100644 --- a/functions/stdio/fgets.c +++ b/functions/stdio/fgets.c @@ -1,300 +1,84 @@ -// ---------------------------------------------------------------------------- -// $Id$ -// ---------------------------------------------------------------------------- -// Public Domain C Library - http://pdclib.sourceforge.net -// This code is Public Domain. Use, modify, and redistribute at will. -// ---------------------------------------------------------------------------- - -char * fgets( char * restrict s, int n, FILE * restrict stream ) { /* TODO */ }; - -/* PDPC code - unreviewed -/* - -In fgets, we have the following possibilites... - -1. we found a genuine '\n' that terminated the search. -2. we hit the '\n' at the endbuf. -3. we hit the '\n' sentinel. +/* fgets( char *, int, FILE * ) + This file is part of the Public Domain C Library (PDCLib). + Permission is granted to use, modify, and / or redistribute at will. */ -#ifndef __MVS__ -char *fgets(char *s, int n, FILE *stream) -{ - char *p; - register char *t; - register char *u = s; - int c; - int processed; -#ifdef __OS2__ - ULONG actualRead; - APIRET rc; -#endif -#ifdef __MSDOS__ - size_t actualRead; - int errind; -#endif - if (stream->quickText) - { - p = stream->upto + n - 1; - t = stream->upto; - if (p < stream->endbuf) - { - c = *p; - *p = '\n'; -#ifdef __OS2__ - if (n < 8) - { -#endif - while ((*u++ = *t++) != '\n') ; /* tight inner loop */ -#ifdef __OS2__ - } - else - { - register unsigned int *i1; - register unsigned int *i2; - register unsigned int z; +#include - i1 = (unsigned int *)t; - i2 = (unsigned int *)u; - while (1) - { - z = *i1; - if ((z & 0xffU) == '\n') break; - z >>= 8; - if ((z & 0xffU) == '\n') break; - z >>= 8; - if ((z & 0xffU) == '\n') break; - z >>= 8; - if ((z & 0xffU) == '\n') break; - *i2++ = *i1++; - } - t = (char *)i1; - u = (char *)i2; - while ((*u++ = *t++) != '\n') ; - } -#endif - *p = (char)c; - if (t <= p) - { - if (*(t - 2) == '\r') /* t is protected, u isn't */ - { - *(u - 2) = '\n'; - *(u - 1) = '\0'; - } - else - { - *u = '\0'; - } - stream->upto = t; - return (s); - } - else - { - processed = (int)(t - stream->upto) - 1; - stream->upto = t - 1; - u--; - } - } - else - { - while ((*u++ = *t++) != '\n') ; /* tight inner loop */ - if (t <= stream->endbuf) - { - if (*(t - 2) == '\r') /* t is protected, u isn't */ - { - *(u - 2) = '\n'; - *(u - 1) = '\0'; - } - else - { - *u = '\0'; - } - stream->upto = t; - return (s); - } - else - { - processed = (int)(t - stream->upto) - 1; - stream->upto = t - 1; - u--; - } - } - } - else - { - processed = 0; - } +#ifndef REGTEST +#include "_PDCLIB_io.h" - if (n < 1) +char * _PDCLIB_fgets_unlocked( char * _PDCLIB_restrict s, int size, FILE * _PDCLIB_restrict stream ) +{ + if ( size == 0 ) { - return (NULL); + return NULL; } - if (n < 2) + if ( size == 1 ) { - *u = '\0'; - return (s); + *s = '\0'; + return s; } - if (stream->ungetCh != -1) + if ( _PDCLIB_prepread( stream ) == EOF ) { - processed++; - *u++ = (char)stream->ungetCh; - stream->ungetCh = -1; + return NULL; } - while (1) - { - t = stream->upto; - p = stream->upto + (n - processed) - 1; - if (p < stream->endbuf) - { - c = *p; - *p = '\n'; - } - if (stream->noNl) - { - while (((*u++ = *t) != '\n') && (*t++ != '\r')) ; - if (*(u - 1) == '\n') - { - t++; - } - else - { - u--; - while ((*u++ = *t++) != '\n') ; - } - } - else - { - while ((*u++ = *t++) != '\n') ; /* tight inner loop */ - } - if (p < stream->endbuf) - { - *p = (char)c; - } - if (((t <= p) && (p < stream->endbuf)) - || ((t <= stream->endbuf) && (p >= stream->endbuf))) - { - if (stream->textMode) - { - if (stream->noNl) - { - if ((*(t - 1) == '\r') || (*(t - 1) == '\n')) - { - *(u - 1) = '\0'; - } - else - { - *u = '\0'; - } - } - else if (*(t - 2) == '\r') /* t is protected, u isn't */ - { - *(u - 2) = '\n'; - *(u - 1) = '\0'; - } - else - { - *u = '\0'; - } - } - stream->upto = t; - if (stream->textMode) - { - stream->quickText = 1; - } - return (s); - } - else if (((t > p) && (p < stream->endbuf)) - || ((t > stream->endbuf) && (p >= stream->endbuf))) - { - int leave = 1; + char * dest = s; + + dest += _PDCLIB_getchars( dest, size - 1, '\n', stream ); + + *dest = '\0'; + return ( dest == s ) ? NULL : s; +} + +char * fgets( char * _PDCLIB_restrict s, int size, + FILE * _PDCLIB_restrict stream ) +{ + _PDCLIB_flockfile( stream ); + char* r = _PDCLIB_fgets_unlocked( s, size, stream ); + _PDCLIB_funlockfile( stream ); + return r; +} - if (stream->textMode) - { - if (t > stream->endbuf) - { - if ((t - stream->upto) > 1) - { - if (*(t - 2) == '\r') /* t is protected, u isn't */ - { - processed -= 1; /* preparation for add */ - } - } - leave = 0; - } - else - { - if ((*(t - 2) == '\r') && (*(t - 1) == '\n')) - { - *(u - 2) = '\n'; - *(u - 1) = '\0'; - } - else - { - t--; - *(u - 1) = '\0'; - } - } - } - else if (t > stream->endbuf) - { - leave = 0; - } - else - { - *u = '\0'; - } - if (leave) - { - stream->upto = t; - if (stream->textMode) - { - stream->quickText = 1; - } - return (s); - } - } - processed += (int)(t - stream->upto) - 1; - u--; - stream->bufStartR += (stream->endbuf - stream->fbuf); -#ifdef __OS2__ - rc = DosRead(stream->hfile, stream->fbuf, stream->szfbuf, &actualRead); - if (rc != 0) - { - actualRead = 0; - stream->errorInd = 1; - errno = rc; - } -#endif -#ifdef __MSDOS__ - actualRead = __read(stream->hfile, - stream->fbuf, - stream->szfbuf, - &errind); - if (errind) - { - errno = actualRead; - actualRead = 0; - stream->errorInd = 1; - } #endif - stream->endbuf = stream->fbuf + actualRead; - *stream->endbuf = '\n'; - if (actualRead == 0) - { - *u = '\0'; - if ((u - s) <= 1) - { - stream->eofInd = 1; - return (NULL); - } - else - { - return (s); - } - } - stream->upto = stream->fbuf; - } + +#ifdef TEST +#include "_PDCLIB_test.h" +#include + +int main( void ) +{ + FILE * fh; + char buffer[10]; + char const * fgets_test = "foo\nbar\0baz\nweenie"; + TESTCASE( ( fh = fopen( testfile, "wb+" ) ) != NULL ); + TESTCASE( fwrite( fgets_test, 1, 18, fh ) == 18 ); + rewind( fh ); + TESTCASE( fgets( buffer, 10, fh ) == buffer ); + TESTCASE( strcmp( buffer, "foo\n" ) == 0 ); + TESTCASE( fgets( buffer, 10, fh ) == buffer ); + TESTCASE( memcmp( buffer, "bar\0baz\n", 8 ) == 0 ); + TESTCASE( fgets( buffer, 10, fh ) == buffer ); + TESTCASE( strcmp( buffer, "weenie" ) == 0 ); + TESTCASE( feof( fh ) ); + TESTCASE( fseek( fh, -1, SEEK_END ) == 0 ); + TESTCASE( fgets( buffer, 1, fh ) == buffer ); + TESTCASE( strcmp( buffer, "" ) == 0 ); + TESTCASE( fgets( buffer, 0, fh ) == NULL ); + TESTCASE( ! feof( fh ) ); + TESTCASE( fgets( buffer, 1, fh ) == buffer ); + TESTCASE( strcmp( buffer, "" ) == 0 ); + TESTCASE( ! feof( fh ) ); + TESTCASE( fgets( buffer, 2, fh ) == buffer ); + TESTCASE( strcmp( buffer, "e" ) == 0 ); + TESTCASE( fseek( fh, 0, SEEK_END ) == 0 ); + TESTCASE( fgets( buffer, 2, fh ) == NULL ); + TESTCASE( feof( fh ) ); + TESTCASE( fclose( fh ) == 0 ); + TESTCASE( remove( testfile ) == 0 ); + return TEST_RESULTS; } + #endif -*/ +