#include #include #include #include #include "8-02_syscalls.h" /* The C Programming Language: 2nd Edition * * Exercise 8-2: Rewrite `fopen` and `_fillbuf` with fields instead of explicit * bit operations. Compare code size and execution speed. * * Notes: Fields, in this case, are struct fields. I implemented them as 1-bit * integers to simulate bit fields via struct. * * The resulting binary of this file (plus the custom header) runs through this * source file in about 0.001s. However, the binary is 1KB larger. */ #define PERMS 0666 int getc(FILE *); int my__fillbuf(my_FILE *fp) { int bufsize; if (fp->flags._READ == 0) { return EOF; } bufsize = (fp->flags._UNBUF != 0) ? 1 : BUFSIZ; if (fp->base == NULL) { if ((fp->base = (char *) calloc(bufsize, sizeof (char))) == NULL) { return EOF; } } fp->ptr = fp->base; fp->cnt = read(fp->fd, fp->ptr, bufsize); if (--fp->cnt < 0) { if (fp->cnt == -1) { fp->flags._EOF = 1; } else { fp->flags._ERR = 1; } fp->cnt = 0; return EOF; } return (unsigned char) *fp->ptr++; } my_FILE * my_fopen(char *name, char *mode) { int fd; my_FILE *fp; if (*mode != 'r' && *mode != 'w' && *mode != 'a') { return NULL; } for (fp = _iob; fp < _iob + FOPEN_MAX; fp++) { if (fp->flags._READ == 0 && fp->flags._WRITE == 0) { break; } } if (fp >= _iob + FOPEN_MAX) { return NULL; } if (*mode == 'w') { fd = creat(name, PERMS); } else if (*mode == 'a') { if ((fd = open(name, O_WRONLY, 0)) == -1) { fd = creat(name, PERMS); } lseek(fd, 0L, 2); } else { fd = open(name, O_RDONLY, 0); } if (fd == -1) { return NULL; } fp->fd = fd; fp->cnt = 0; if (*mode == 'r') { fp->flags._READ = 1; } else { fp->flags._WRITE = 1; } return fp; } int main() { my_FILE *fp = my_fopen("8-02_fopen-and-fillbuf.c", "r"); if (fp != NULL) { puts("We could read the file.\n"); /* pro tip: don't declare this as 'unsigned' or you'll create an * endless loop thanks to EOF typically being negative. Don't waste * half an hour on a newbie mistake like I did. :) */ char c; while ((c = my_getc(fp)) != EOF) { putchar(c); } } else { puts("Could not open file for reading."); } return 0; }