Created
July 28, 2011 13:35
-
-
Save Alexis-D/1111559 to your computer and use it in GitHub Desktop.
stdio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Alexis Daboville - 2011 | |
*/ | |
#include <fcntl.h> | |
#include <stdarg.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#include <sys/stat.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include "stdio.h" | |
#define MAX_FILE 1024 | |
/* | |
* Pas de gestion des erreurs | |
* Alloué un buffer en écriture dans _flsbuf si nécessaire. | |
*/ | |
struct _iobuf _IOB[MAX_FILE] = { | |
{ 0, NULL, NULL, 0, _IOREAD, 0 }, | |
{ 0, NULL, NULL, 0, _IOWRT | _IOLBF, 1 }, | |
{ 0, NULL, NULL, 0, _IOWRT | _IONBF, 2 } | |
}; | |
/* | |
* Remplit le buffer de p, et alloue le buffer si ça n'a pas été fait. | |
*/ | |
int _filbuf(FILE *p) { | |
//si on a pas de buffer, on en alloue un | |
if(!p->_base) { | |
if(!p->_bufsiz) { | |
p->_bufsiz = BUFSIZ; | |
} | |
p->_base = malloc(p->_bufsiz); | |
} | |
//on lit les carctères, et on place _ptr au début du buffer | |
p->_cnt = read(p->_file, p->_base, p->_bufsiz); | |
p->_ptr = p->_base; | |
if(p->_cnt) { | |
--p->_cnt; | |
return *p->_ptr++; | |
} | |
return EOF; | |
} | |
/* | |
* Flush le buffer de p, et affiche c. | |
*/ | |
int _flsbuf(int c, FILE *p) { | |
//si on est pas bufferisé, on écrit le carctère (e.g. stderr) | |
if(p->_flag & _IONBF) { | |
write(p->_file, &c, 1); | |
return c; | |
} | |
//si on a pas de buffer, on en alloue un | |
if(!p->_base) { | |
if(!p->_bufsiz) { | |
p->_bufsiz = BUFSIZ; | |
} | |
p->_ptr = p->_base = malloc(p->_bufsiz); | |
p->_cnt = 0; | |
//on ajoute le caractère au buffer | |
return putc(c, p); | |
} | |
//si on est line buffered et que le buffer n'est pas plein | |
//on le vide | |
if(p->_flag & _IOLBF && -p->_cnt < p->_bufsiz) { | |
write(p->_file, p->_base, -p->_cnt); | |
p->_ptr = p->_base; | |
p->_cnt = 0; | |
} | |
else { | |
//s'il reste de la place dans le buffer on le vide (+1 pour le denier char) | |
if(p->_cnt >= 0) { | |
write(p->_file, p->_base, p->_ptr - p->_base + 1); | |
p->_ptr = p->_base; | |
p->_cnt = p->_bufsiz; | |
} | |
//le buffer est plein : on le vide, et on mets c dedans | |
else { | |
write(p->_file, p->_base, p->_ptr - p->_base); | |
p->_ptr = p->_base; | |
p->_cnt = p->_flag & _IOLBF ? 0 : p->_bufsiz; | |
putc(c, p); | |
} | |
} | |
return c; | |
} | |
/* | |
* Force le flush du buffer de stream. | |
*/ | |
int fflush(FILE *stream) { | |
return stream->_cnt == 0 ? 0 :_flsbuf((int) *--stream->_ptr, stream); | |
} | |
/* | |
* Ouvre le fichier à l'adresse path selon le mode mode, man 3 fopen | |
* pour voir les modes disponibles. | |
*/ | |
/* | |
* Comment gérer r+, w+, a. avec un seul buffer ? | |
*/ | |
FILE *fopen(const char *path, const char *mode) { | |
int fd; | |
if(strcmp(mode, "r") == 0) { | |
fd = open(path, O_RDONLY); | |
_IOB[fd]._flag = _IOREAD; | |
_IOB[fd]._cnt = 0; | |
} | |
else if(strcmp(mode, "w") == 0) { | |
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, | |
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | |
_IOB[fd]._flag = _IOWRT | _IOFBF; | |
} | |
else if(strcmp(mode, "a") == 0) { | |
fd = open(path, O_WRONLY | O_CREAT | O_APPEND, | |
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | |
_IOB[fd]._flag = _IOWRT | _IOFBF; | |
} | |
_IOB[fd]._bufsiz = 0; | |
_IOB[fd]._ptr = _IOB[fd]._base = NULL; | |
_IOB[fd]._file = fd; | |
return &_IOB[fd]; | |
} | |
/* | |
* Ferme le fichier stream, et désalloue le buffer s'il | |
* y en a un. | |
*/ | |
int fclose(FILE *stream) { | |
fflush(stream); | |
if(stream->_base) { | |
free(stream->_base); | |
} | |
return close(stream->_file); | |
} | |
/* | |
* man 3 setbuf | |
*/ | |
void setbuf(FILE *stream, char *buf) { | |
setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ); | |
} | |
/* | |
* man 3 setvbuf | |
*/ | |
int setvbuf(FILE *stream, char *buf, int mode, int size) { | |
stream->_ptr = stream->_base = buf; | |
stream->_bufsiz = size; | |
stream->_flag &= (~_IOLBF | ~_IOFBF | ~_IONBF); | |
stream->_flag |= mode; | |
if(~stream->_flag & _IOLBF && stream->_flag & _IOWRT) { | |
stream->_cnt = size; | |
} | |
else { | |
stream->_cnt = 0; | |
} | |
return 0; | |
} | |
int _fprintf(FILE *stream, const char *format, va_list ap) { | |
int a, i = 0, c, count = 0, base, j, mod; | |
bool modifier = false, hexa = false; | |
char *b, buff[8 * sizeof (int)]; | |
while(c = (int) format[i]) { | |
if(modifier) { | |
++count; | |
modifier = false; | |
switch(c) { | |
case '%': | |
putc(c, stream); | |
break; | |
case 'c': | |
a = va_arg(ap, int); | |
putc(a, stream); | |
break; | |
case 's': | |
b = va_arg(ap, char*); | |
--count; | |
while(*b) { | |
putc(*b, stream); | |
++b; | |
++count; | |
} | |
break; | |
case 'x': | |
hexa = true; | |
case 'd': | |
a = va_arg(ap, int); | |
base = hexa ? 16 : 10; | |
j = sizeof(buff); | |
b = buff; | |
b[--j] = 0; | |
if(a < 0) { | |
putc('-', stream); | |
} | |
do { | |
--j; | |
mod = a % base; | |
a /= base; | |
b[j] = mod + (mod < 10 ? '0' : 'a' - 10); | |
} while(a != 0); | |
b = buff + j; | |
while(*b) { | |
putc(*b, stream); | |
++b; | |
} | |
hexa = false; | |
break; | |
default: | |
return -1; | |
} | |
} | |
else if(format[i] == '%') { | |
modifier = true; | |
} | |
else { | |
++count; | |
putc(c, stream); | |
} | |
++i; | |
} | |
return count; | |
} | |
int fprintf(FILE *stream, const char *format, ...) { | |
va_list ap; | |
int c; | |
va_start(ap, format); | |
c = _fprintf(stream, format, ap); | |
va_end(ap); | |
return c; | |
} | |
int printf(const char *format, ...) { | |
va_list ap; | |
int c; | |
va_start(ap, format); | |
c = _fprintf(stdout, format, ap); | |
va_end(ap); | |
return c; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*** | |
* | |
* Re-ecriture des fonctions de base de stdio | |
* | |
* Author: Erick Gallesio [[email protected]] | |
* Creation date: 27-Oct-1992 09:28 | |
* Last file update: 6-Mar-2011 22:21 (eg) | |
* | |
*/ | |
/**** Ce qui suit est le fichier standard stdio.h de Sun OS 4.x | |
(legerement modifie) ****/ | |
# ifndef FILE | |
#define BUFSIZ 1024 | |
#define _SBFSIZ 8 | |
extern struct _iobuf { | |
int _cnt; | |
unsigned char* _ptr; | |
unsigned char* _base; | |
int _bufsiz; | |
short _flag; | |
char _file; | |
} _IOB[]; | |
#define _IOFBF 0 | |
#define _IOREAD 01 | |
#define _IOWRT 02 | |
#define _IONBF 04 | |
#define _IOMYBUF 010 | |
#define _IOEOF 020 | |
#define _IOERR 040 | |
#define _IOSTRG 0100 | |
#define _IOLBF 0200 | |
#define _IORW 0400 | |
#define NULL ((void*) 0) | |
#define FILE struct _iobuf | |
#define EOF (-1) | |
#define stdin (&_IOB[0]) | |
#define stdout (&_IOB[1]) | |
#define stderr (&_IOB[2]) | |
#ifdef lint /* so that lint likes (void)putc(a,b) */ | |
extern int putc(); | |
extern int getc(); | |
#else | |
#define getc(p) (--(p)->_cnt>=0? ((int)*(p)->_ptr++):_filbuf(p)) | |
#define putc(x, p) (--(p)->_cnt >= 0 ?\ | |
(int)(*(p)->_ptr++ = (unsigned char)(x)) :\ | |
(((p)->_flag & _IOLBF) && -(p)->_cnt < (p)->_bufsiz ?\ | |
((*(p)->_ptr = (unsigned char)(x)) != '\n' ?\ | |
(int)(*(p)->_ptr++) :\ | |
_flsbuf(*(unsigned char *)(p)->_ptr, p)) :\ | |
_flsbuf((unsigned char)(x), p))) | |
#endif | |
#define getchar() getc(stdin) | |
#define putchar(x) putc((x),stdout) | |
#define feof(p) (((p)->_flag&_IOEOF)!=0) | |
#define ferror(p) (((p)->_flag&_IOERR)!=0) | |
#define fileno(p) ((p)->_file) | |
#define clearerr(p) (void) ((p)->_flag &= ~(_IOERR|_IOEOF)) | |
FILE *fopen(const char *path, const char *mode); | |
FILE *fdopen(int fd, const char *mode); | |
FILE *freopen(const char *path, const char *mode, FILE *stream); | |
int fclose(FILE *fp); | |
FILE *popen(const char *command, const char *type); | |
int pclose(FILE *stream); | |
FILE *tmpfile(void); | |
int fgetc(FILE *stream); | |
char *fgets(char *s, int size, FILE *stream); | |
char *gets(char *s); | |
int fputc(int c, FILE *stream); | |
int fputs(const char *s, FILE *stream); | |
int puts(const char *s); | |
int printf(const char *format, ...); | |
int fprintf(FILE *stream, const char *format, ...); | |
int sprintf(char *str, const char *format, ...); | |
void setbuf(FILE *stream, char *buf); | |
int setvbuf(FILE *stream, char *buf, int mode, int size); | |
# endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment