scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit 1411e9231618c55fd39a970af79f3e99a593f7ba
parent 03edfe03f5a09e129c84537ce44d030e974dd00c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat,  9 Dec 2017 14:41:24 +0100

[lib/c] Add fopen(), fclose() and freopen()

This is a preliminar work in these functions and they are not
very well tested (you know, it means that I didn't execute them :P)

Diffstat:
Mlib/c/include/stdio.h | 3++-
Mlib/c/src/Makefile | 2+-
Alib/c/src/_fpopen.c | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/c/src/fclose.c | 31+++++++++++++++++++++++++++++++
Alib/c/src/fopen.c | 20++++++++++++++++++++
Alib/c/src/freopen.c | 12++++++++++++
6 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/lib/c/include/stdio.h b/lib/c/include/stdio.h @@ -27,6 +27,7 @@ #define _IOFBF (1 << 7) #define _IOLBF (1 << 8) #define _IONBF (1 << 9) +#define _IOALLOC (1 <<10) typedef struct { int fd; /* file descriptor */ @@ -35,7 +36,7 @@ typedef struct { unsigned char *wp; /* write pointer */ unsigned char *lp; /* write pointer used when line-buffering */ size_t len; /* actual length of buffer */ - unsigned char flags; + unsigned short flags; unsigned char unbuf[1]; /* tiny buffer for unbuffered io */ } FILE; diff --git a/lib/c/src/Makefile b/lib/c/src/Makefile @@ -10,7 +10,7 @@ OBJ = bsearch.o qsort.o \ fputs.o puts.o fread.o fwrite.o \ getc.o putc.o __putc.o __getc.o \ rewind.o fseek.o ferror.o feof.o clearerr.o \ - stdio.o \ + fclose.o fopen.c freopen.c _fpopen.o stdio.o \ realloc.o calloc.o malloc.o \ assert.o strcpy.o strcmp.o strlen.o strchr.o \ strrchr.o strcat.o strncmp.o strncpy.o strncat.o strcoll.o \ diff --git a/lib/c/src/_fpopen.c b/lib/c/src/_fpopen.c @@ -0,0 +1,70 @@ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include "syscall.h" +#undef fopen + +FILE * +_fpopen(const char * restrict fname, + const char * restrict mode, + FILE * restrict fp) +{ + int i, flags, fd, rw, bin; + + flags = rw = bin = 0; + + if (mode[0] == '\0) + goto einval; + if (mode[i = 1] == '+') + i++, rw = 1; + if (mode[i] == 'b') + i++, bin = 1; + if (mode[i] != '\0') + goto einval; + + switch (mode[0]) { + case 'a': + flags |= O_APPEND | O_CREAT; + goto wrflags; + case 'w': + flags |= O_TRUNC | O_CREAT; + wrflags: + flags |= (rw) ? O_RDWR : O_WRONLY; + break; + case 'r': + flags = (rw) ? O_RDWR : O_RDONLY; + break; + default: + einval: + errno = EINVAL; + return NULL; + } + + if ((fd = _open(name, flags)) < 0) + return NULL; + + if (fp->buf == NULL) { + if ((fp->buf = malloc(BUFSIZ)) == NULL) { + close(fd); + errno = ENOMEM; + return NULL; + } + fp->flags |= _IOALLOC; + } + fp->fd = fd; + + if (!bin) + fp->flags |= _IOTEXT; + + if (flags & O_RDWR) + fp->flags |= _IORW; + else if (flags & O_RDONLY) + fp->flags |= _IOREAD; + else + fp->flags |= _IOWRITE; + + fp->lp = fp->rp = fp->wp = NULL; + + return fp; +} diff --git a/lib/c/src/fclose.c b/lib/c/src/fclose.c @@ -0,0 +1,31 @@ + +#include <stdio.h> +#undef fclose + +int +fclose(FILE *fp) +{ + int r = EOF; + + if ((fp->flags & _IOSTRG) == 0 && + fp->flags & (_IOWRITE | _IOREAD | _IOWR)) { + r = 0; + if (fflush(fp) == EOF) + r = EOF; + if (close(fp->fd) < 0) + r = EOF; + } + + if (fp->flags & _IOALLOC) { + free(fp->buf); + fp->buf = NULL; + } + + fp->flags &= ~(_IOWRITE | _IOREAD | _IOWR | + _IOERR | _IOEOF | + _IOALLOC | + _IOTXT | + _IOSTRG); + + return r; +} diff --git a/lib/c/src/fopen.c b/lib/c/src/fopen.c @@ -0,0 +1,20 @@ + +#include <errno.h> +#include <stdio.h> +#undef fopen + +FILE * +fopen(const char * restrict name, const char * restrict mode) +{ + FILE *fp; + + for (fp = __iob; fp < &__iob[FILE_MAX]; ++fp) { + if (fp->flags & (_IOREAD | _IOWRITE | _IORW) == 0) + break; + } + if (fp == &__iob[FILE_MAX]) { + errno = ENOMEM; + return NULL; + } + return _fpopen(name, mode, fp); +} diff --git a/lib/c/src/freopen.c b/lib/c/src/freopen.c @@ -0,0 +1,12 @@ + +#include <stdio.h> +#undef freopen + +FILE * +freopen(const char * restrict name, const char * restrict mode, + FILE * restrict fp) +{ + if (fclose(fp) == EOF) + return NULL; + return _fpopen(name, mode, fp); +}