2013年9月7日土曜日

開発環境

プログラミング言語C 第2版 ANSI規格準拠 (B.W. カーニハン D.M. リッチー (著)、 石田 晴久 (翻訳)、共立出版)の第8章(UNIXシステム・インタフェース)、8.4(ランダム・アクセス - Lseek)、8.5(例 - Fopen と Getc の実現)、演習8-2を解いてみる。

その他参考書籍

演習 8-2.

コード

sample.c

int main(int argc, char *argv[])
{
    
    return 0;
}

#define NULL 0
#define EOF (-1)
#define BUFSIZ 1024
#define OPEN_MAX 20

/* ビットフィールドは処理系に依存する */
struct flags {
    unsigned int is_read : 1;
    unsigned int is_write : 1;
    unsigned int is_unbuf : 1;
    unsigned int is_eof : 1;
    unsigned int is_err : 1;
};

typedef struct _iobuf {
    int cnt;
    char *ptr;
    char *base;
    int fd;
    struct flags flag;
} FILE;

FILE _iob[OPEN_MAX];

#include <unistd.h>
#include <fcntl.h>

#define PERMS 0666

FILE *fopen(char *name, char *mode)
{
    int fd;
    FILE *fp;
    
    if (*mode != 'r' && *mode != 'w' && *mode != 'a') {
        return NULL;
    }
    for (fp = _iob; fp < _iob + OPEN_MAX; fp++) {
        if (fp->flag.is_read == 0 && fp->flag.is_write == 0) {
            break;
        }
    }
    if (fp >= _iob + OPEN_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;
    fp->base = NULL;
    if (*mode == 'r') {
        fp->flag.is_read = 1;
    } else {
        fp->flag.is_write = 1;
    }
    return fp;
}

#include <stdlib.h>

int _fillbuf(FILE *fp)
{
    int bufsize;
    
    if ((fp->flag.is_read == 0) || (fp->flag.is_eof == 0) ||
                                   (fp->flag.is_err == 0)) {
        return EOF;
    }
    bufsize = (fp->flag.is_unbuf == 1) ? 1 : BUFSIZ;
    if (fp->base == NULL) {
        if ((fp->base = (char *) malloc(bufsize)) == NULL) {
            return EOF;
        }
    }
    fp->ptr = fp->base;
    fp->cnt = read(fp->fd, fp->ptr, bufsize);
    if (--fp->cnt < 0) {
        if (fp->cnt == -1) {
            fp->flag.is_eof = 1;
        } else {
            fp->flag.is_err = 1;
        }
        fp->cnt = 0;
        return EOF;
    }
    return (unsigned char) *fp->ptr++;
}

0 コメント:

コメントを投稿