stdio fgets and stuff that actually kinda work correctly

This commit is contained in:
K. Lange 2018-05-04 17:53:31 +09:00
parent 5cf95b4fc0
commit a3b1b253d7
5 changed files with 164 additions and 131 deletions

View File

@ -37,82 +37,10 @@ void parse_url(char * d, struct uri * r) {
}
}
static char read_buf[1024];
static size_t available = 0;
static size_t offset = 0;
static size_t read_from = 0;
static char * read_line(FILE * f, char * out, ssize_t len) {
while (len > 0) {
if (available == 0) {
if (offset == 1024) {
offset = 0;
}
size_t r = read(fileno(f), &read_buf[offset], 1024 - offset);
read_from = offset;
available = r;
offset += available;
}
#if 0
fprintf(stderr, "Available: %d\n", available);
fprintf(stderr, "Remaining length: %d\n", len);
fprintf(stderr, "Read from: %d\n", read_from);
fprintf(stderr, "Offset: %d\n", offset);
#endif
if (available == 0) {
return out;
}
while (read_from < offset && len > 0) {
*out = read_buf[read_from];
len--;
read_from++;
available--;
if (*out == '\n') {
return out;
}
out++;
}
}
return out;
}
static size_t read_bytes(FILE * f, char * out, ssize_t len) {
size_t r_out = 0;
while (len > 0) {
if (available == 0) {
if (offset == 1024) {
offset = 0;
}
size_t r = read(fileno(f), &read_buf[offset], 1024 - offset);
read_from = offset;
available = r;
offset += available;
}
if (available == 0) {
return r_out;
}
while (read_from < offset && len > 0) {
*out = read_buf[read_from];
len--;
read_from++;
available--;
out++;
r_out += 1;
}
}
return r_out;
}
void read_http_line(char * buf, FILE * f) {
memset(buf, 0x00, 256);
read_line(f, buf, 255);
fgets(buf, 255, f);
char * _r = strchr(buf, '\r');
if (_r) {
*_r = '\0';
@ -223,7 +151,7 @@ int main(int argc, char * argv[]) {
while (bytes_to_read > 0) {
char buf[1024];
size_t r = read_bytes(f, buf, bytes_to_read < 1024 ? bytes_to_read : 1024);
size_t r = fread(buf, 1, bytes_to_read < 1024 ? bytes_to_read : 1024, f);
fwrite(buf, 1, r, stdout);
bytes_to_read -= r;
}

View File

@ -266,48 +266,6 @@ static void volume_lower(void) {
redraw();
}
static char read_buf[1024];
static size_t available = 0;
static size_t offset = 0;
static size_t read_from = 0;
static char * read_line(FILE * f, char * out, ssize_t len) {
while (len > 0) {
if (available == 0) {
if (offset == 1024) {
offset = 0;
}
size_t r = read(fileno(f), &read_buf[offset], 1024 - offset);
read_from = offset;
available = r;
offset += available;
}
#if 0
fprintf(stderr, "Available: %d\n", available);
fprintf(stderr, "Remaining length: %d\n", len);
fprintf(stderr, "Read from: %d\n", read_from);
fprintf(stderr, "Offset: %d\n", offset);
#endif
if (available == 0) {
*out = '\0';
return out;
}
while (read_from < offset && len > 0) {
*out = read_buf[read_from];
len--;
read_from++;
available--;
if (*out == '\n') {
return out;
}
out++;
}
}
return out;
}
static void update_network_status(void) {
FILE * net = fopen("/proc/netif","r");
@ -315,7 +273,7 @@ static void update_network_status(void) {
do {
memset(line, 0, 256);
read_line(net, line, 256);
fgets(line, 256, net);
if (!*line) break;
if (strstr(line,"no network") != NULL) {
network_status = 0;

View File

@ -3,9 +3,9 @@
#include <stddef.h>
#include <va_list.h>
typedef struct _FILE {
int fd;
} FILE;
typedef struct _FILE FILE;
#define BUFSIZ 1024
extern FILE * stdin;
extern FILE * stdout;
@ -44,3 +44,5 @@ extern void rewind(FILE *stream);
extern void setbuf(FILE * stream, char * buf);
extern void perror(const char *s);
extern int ungetc(int c, FILE * stream);

View File

@ -55,6 +55,9 @@ extern void _fini();
char ** environ;
int _environ_size = 0;
extern void __stdio_init_buffers(void);
void _exit(int val){
_fini();
syscall_exit(val);
@ -62,6 +65,8 @@ void _exit(int val){
__builtin_unreachable();
}
char * _argv_0 = NULL;
void pre_main(int (*main)(int,char**), int argc, char * argv[]) {
unsigned int x = 0;
unsigned int nulls = 0;
@ -78,6 +83,8 @@ void pre_main(int (*main)(int,char**), int argc, char * argv[]) {
break;
}
}
_argv_0 = argv[0];
__stdio_init_buffers();
_init();
_exit(main(argc, argv));
}

View File

@ -1,25 +1,124 @@
#include <stdio.h>
#include <syscall.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <_xlog.h>
struct _FILE {
int fd;
char * read_buf;
int available;
int offset;
int read_from;
int ungetc;
};
FILE _stdin = {
.fd = 0,
.read_buf = NULL,
.available = 0,
.offset = 0,
.read_from = 0,
.ungetc = -1,
};
FILE _stdout = {
.fd = 1,
.read_buf = NULL,
.available = 0,
.offset = 0,
.read_from = 0,
.ungetc = -1,
};
FILE _stderr = {
.fd = 2,
.read_buf = NULL,
.available = 0,
.offset = 0,
.read_from = 0,
.ungetc = -1,
};
FILE * stdin = &_stdin;
FILE * stdout = &_stdout;
FILE * stderr = &_stderr;
void __stdio_init_buffers(void) {
_stdin.read_buf = malloc(BUFSIZ);
//_stdout.read_buf = malloc(BUFSIZ);
//_stderr.read_buf = malloc(BUFSIZ);
}
#if 0
static char * stream_id(FILE * stream) {
static char out[] = "stream\0\0\0\0\0\0";
if (stream == &_stdin) return "stdin";
if (stream == &_stdout) return "stdout";
if (stream == &_stderr) return "stderr";
sprintf(out, "stream %d", fileno(stream));
return out;
}
#endif
extern char * _argv_0;
static size_t read_bytes(FILE * f, char * out, size_t len) {
size_t r_out = 0;
//fprintf(stderr, "%s: Read %d bytes from %s\n", _argv_0, len, stream_id(f));
//fprintf(stderr, "%s: off[%d] avail[%d] read[%d]\n", _argv_0, f->offset, f->available, f->read_from);
while (len > 0) {
if (f->ungetc >= 0) {
*out = f->ungetc;
len--;
out++;
r_out++;
f->ungetc = -1;
continue;
}
if (f->available == 0) {
if (f->offset == BUFSIZ) {
f->offset = 0;
}
ssize_t r = read(fileno(f), &f->read_buf[f->offset], BUFSIZ - f->offset);
if (r < 0) {
//fprintf(stderr, "error condition\n");
return r_out;
} else {
f->read_from = f->offset;
f->available = r;
f->offset += f->available;
}
}
if (f->available == 0) {
/* EOF condition */
//fprintf(stderr, "%s: no bytes available, returning read value of %d\n", _argv_0, r_out);
return r_out;
}
//fprintf(stderr, "%s: reading until %d reaches %d or %d reaches 0\n", _argv_0, f->read_from, f->offset, len);
while (f->read_from < f->offset && len > 0) {
*out = f->read_buf[f->read_from];
len--;
f->read_from++;
f->available--;
out++;
r_out += 1;
}
}
//fprintf(stderr, "%s: read completed, returning read value of %d\n", _argv_0, r_out);
return r_out;
}
FILE * fopen(const char *path, const char *mode) {
const char * x = mode;
@ -54,22 +153,52 @@ FILE * fopen(const char *path, const char *mode) {
FILE * out = malloc(sizeof(FILE));
out->fd = fd;
out->read_buf = malloc(BUFSIZ);
out->available = 0;
out->read_from = 0;
out->offset = 0;
out->ungetc = -1;
return out;
}
int ungetc(int c, FILE * stream) {
if (stream->ungetc > 0)
return EOF;
return (stream->ungetc = c);
}
FILE * fdopen(int fd, const char *mode){
FILE * out = malloc(sizeof(FILE));
out->fd = fd;
out->read_buf = malloc(BUFSIZ);
out->available = 0;
out->read_from = 0;
out->offset = 0;
out->ungetc = -1;
return out;
}
int fclose(FILE * stream) {
return syscall_close(stream->fd);
int out = syscall_close(stream->fd);
free(stream->read_buf);
if (stream == &_stdin || stream == &_stdout || stream == &_stderr) {
return out;
} else {
free(stream);
return out;
}
}
int fseek(FILE * stream, long offset, int whence) {
//fprintf(stderr, "%s: seek called, resetting\n", _argv_0);
stream->offset = 0;
stream->read_from = 0;
stream->available = 0;
stream->ungetc = -1;
int resp = syscall_lseek(stream->fd,offset,whence);
if (resp < 0) {
return -1;
@ -78,14 +207,18 @@ int fseek(FILE * stream, long offset, int whence) {
}
long ftell(FILE * stream) {
//fprintf(stderr, "%s: tell called, resetting\n", _argv_0);
stream->offset = 0;
stream->read_from = 0;
stream->available = 0;
stream->ungetc = -1;
return syscall_lseek(stream->fd, 0, SEEK_CUR);
}
size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream) {
char * tracking = (char*)ptr;
for (size_t i = 0; i < nmemb; ++i) {
int r = syscall_read(stream->fd, tracking, size);
int r = read_bytes(stream, tracking, size);
if (r < 0) {
return -1;
}
@ -145,19 +278,16 @@ int fgetc(FILE * stream) {
return buf[0];
}
int putchar(int c) {
return fputc(c, stdout);
}
void rewind(FILE *stream) {
fseek(stream, 0, SEEK_SET);
}
char *fgets(char *s, int size, FILE *stream) {
int c;
char * out = s;
while ((c = fgetc(stream)) > 0) {
*s++ = c;
size--;
if (size == 0) {
return out;
}
*s = '\0';
if (c == '\n') {
return out;
}
@ -172,6 +302,14 @@ char *fgets(char *s, int size, FILE *stream) {
return NULL;
}
int putchar(int c) {
return fputc(c, stdout);
}
void rewind(FILE *stream) {
fseek(stream, 0, SEEK_SET);
}
void setbuf(FILE * stream, char * buf) {
// ...
}