Changeset bd5414e in mainline


Ignore:
Timestamp:
2015-09-21T21:05:26Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c70703a
Parents:
bea710f
Message:

Proper ungetc() in libc.

Location:
uspace/lib
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/io/io.c

    rbea710f rbd5414e  
    6464        .buf_head = NULL,
    6565        .buf_tail = NULL,
    66         .buf_state = _bs_empty
     66        .buf_state = _bs_empty,
    6767};
    6868
     
    466466                return 0;
    467467
     468        bytes_left = size * nmemb;
     469        total_read = 0;
     470        dp = (uint8_t *) dest;
     471
     472        /* Bytes from ungetc() buffer */
     473        while (stream->ungetc_chars > 0 && bytes_left > 0) {
     474                *dp++ = stream->ungetc_buf[--stream->ungetc_chars];
     475                ++total_read;
     476        }
     477
    468478        /* If not buffered stream, read in directly. */
    469479        if (stream->btype == _IONBF) {
    470                 now = _fread(dest, size, nmemb, stream);
    471                 return now;
     480                total_read += _fread(dest, 1, bytes_left, stream);
     481                return total_read / size;
    472482        }
    473483
     
    481491                        return 0; /* Errno set by _fallocbuf(). */
    482492        }
    483 
    484         bytes_left = size * nmemb;
    485         total_read = 0;
    486         dp = (uint8_t *) dest;
    487493
    488494        while ((!stream->error) && (!stream->eof) && (bytes_left > 0)) {
     
    674680}
    675681
     682int ungetc(int c, FILE *stream)
     683{
     684        if (c == EOF)
     685                return EOF;
     686
     687        if (stream->ungetc_chars >= UNGETC_MAX)
     688                return EOF;
     689
     690        stream->ungetc_buf[stream->ungetc_chars++] =
     691            (uint8_t)c;
     692
     693        stream->eof = false;
     694        return (uint8_t)c;
     695}
     696
    676697int fseek(FILE *stream, off64_t offset, int whence)
    677698{
     
    679700
    680701        _fflushbuf(stream);
     702        stream->ungetc_chars = 0;
    681703
    682704        rc = lseek(stream->fd, offset, whence);
     
    693715{
    694716        _fflushbuf(stream);
    695         return lseek(stream->fd, 0, SEEK_CUR);
     717        return lseek(stream->fd, 0, SEEK_CUR) - stream->ungetc_chars;
    696718}
    697719
  • uspace/lib/c/generic/private/stdio.h

    rbea710f rbd5414e  
    3939#include <stdio.h>
    4040#include <async.h>
     41
     42/** Maximum characters that can be pushed back by ungetc() */
     43#define UNGETC_MAX 1
    4144
    4245struct _IO_FILE {
     
    8285        /** Points to end of occupied space when in read mode. */
    8386        uint8_t *buf_tail;
     87
     88        /** Pushed back characters */
     89        uint8_t ungetc_buf[UNGETC_MAX];
     90
     91        /** Number of pushed back characters */
     92        int ungetc_chars;
    8493};
    8594
  • uspace/lib/c/include/stdio.h

    rbea710f rbd5414e  
    109109extern int puts(const char *);
    110110
     111extern int ungetc(int, FILE *);
     112
    111113/* Formatted string output functions */
    112114extern int fprintf(FILE *, const char*, ...)
  • uspace/lib/posix/source/stdio.c

    rbea710f rbd5414e  
    118118int posix_ungetc(int c, FILE *stream)
    119119{
    120         uint8_t b = (uint8_t) c;
    121 
    122         bool can_unget =
    123             /* Provided character is legal. */
    124             c != EOF &&
    125             /* Stream is consistent. */
    126             !stream->error &&
    127             /* Stream is buffered. */
    128             stream->btype != _IONBF &&
    129             /* Last operation on the stream was a read operation. */
    130             stream->buf_state == _bs_read &&
    131             /* Stream buffer is already allocated (i.e. there was already carried
    132              * out either write or read operation on the stream). This is probably
    133              * redundant check but let's be safe. */
    134             stream->buf != NULL &&
    135             /* There is still space in the stream to retreat. POSIX demands the
    136              * possibility to unget at least 1 character. It should be always
    137              * possible, assuming the last operation on the stream read at least 1
    138              * character, because the buffer is refilled in the lazily manner. */
    139             stream->buf_tail > stream->buf;
    140 
    141         if (can_unget) {
    142                 --stream->buf_tail;
    143                 stream->buf_tail[0] = b;
    144                 stream->eof = false;
    145                 return (int) b;
    146         } else {
    147                 return EOF;
    148         }
     120        return ungetc(c, stream);
    149121}
    150122
Note: See TracChangeset for help on using the changeset viewer.