aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2016-07-16 23:39:51 +0200
committerAlex Auvolat <alex@adnab.me>2016-07-16 23:39:51 +0200
commit6466208ec051e58b824cc3c839b6b086ae910fe6 (patch)
tree434741997865ec6f0c4c3badb4fcfde557a7af35 /src
parentbb2dd23f315bafa7b0b64845c2fe25d7a0893b10 (diff)
downloadkogata-6466208ec051e58b824cc3c839b6b086ae910fe6.tar.gz
kogata-6466208ec051e58b824cc3c839b6b086ae910fe6.zip
Progress on stdio impementation
Diffstat (limited to 'src')
-rw-r--r--src/common/include/kogata/printf.h2
-rw-r--r--src/common/libc/printf.c210
-rw-r--r--src/common/libc/string.c3
-rw-r--r--src/lib/include/stdio.h16
-rw-r--r--src/lib/libc/stdio.c215
-rw-r--r--src/lib/lua/luaconf.h2
6 files changed, 309 insertions, 139 deletions
diff --git a/src/common/include/kogata/printf.h b/src/common/include/kogata/printf.h
index b4e1c1b..121af78 100644
--- a/src/common/include/kogata/printf.h
+++ b/src/common/include/kogata/printf.h
@@ -7,4 +7,6 @@
int snprintf(char* s, size_t n, const char* format, ...);
int vsnprintf(char* s, size_t n, const char* format, va_list arg);
+int vcprintf(int (*putc_fun)(int c, void* p), void* p, const char* format, va_list arg);
+
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/common/libc/printf.c b/src/common/libc/printf.c
index 0498b2d..fbebafe 100644
--- a/src/common/libc/printf.c
+++ b/src/common/libc/printf.c
@@ -1,6 +1,7 @@
#include <stdarg.h>
#include <stdbool.h>
+#include <kogata/debug.h>
#include <kogata/printf.h>
int snprintf(char * buff, size_t len, const char *format, ...) {
@@ -13,20 +14,48 @@ int snprintf(char * buff, size_t len, const char *format, ...) {
return len;
}
-int vsnprintf(char *buff, size_t len, const char* format, va_list ap){
- size_t i, result;
+struct vsnprintf_s {
+ char* buff;
+ size_t len;
+ size_t i;
+};
+int vsnprintf_putc_fun(int c, void* p) {
+ struct vsnprintf_s *s = (struct vsnprintf_s*)p;
+ if (s->i < s->len - 1) {
+ s->buff[s->i] = c;
+ s->i++;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+int vsnprintf(char *buff, size_t len, const char* format, va_list arg){
if (!buff || !format)
return -1;
-#define PUTCHAR(thechar) \
- do { \
- if (result < len-1) \
- *buff++ = (thechar); \
- result++; \
- } while (0)
+ struct vsnprintf_s s;
+ s.buff = buff;
+ s.len = len;
+ s.i = 0;
+
+ size_t ret = vcprintf(vsnprintf_putc_fun, &s, format, arg);
+ ASSERT(ret == s.i);
+
+ buff[s.i] = 0;
+ return s.i;
+}
+
+int vcprintf(int (*putc_fun)(int c, void* p), void* p, const char* format, va_list ap) {
+ if (!format) return -1;
+
+ int ret = 0;
+#define PUTCHAR(thechar) { int _tmp = putc_fun(thechar, p);\
+ if (_tmp == 1) ret++; \
+ else if (_tmp == 0) return ret; \
+ else if (_tmp < 0) return _tmp; }
- result = 0;
+ size_t i;
for(i = 0; format[i] != '\0' ; i++) {
if (format[i] == '%') {
i++;
@@ -34,111 +63,98 @@ int vsnprintf(char *buff, size_t len, const char* format, va_list ap){
int l = 0;
bool spec = true;
while (spec) {
- switch(format[i]) {
- case 'l': {
- l++;
- i++;
- break;
- }
- case 'u': {
- u = 1;
- i++;
- break;
- }
- default:
- spec = false;
+ if (format[i] == 'l') {
+ l++;
+ i++;
+ } else if (format[i] == 'u') {
+ u = 1;
+ i++;
+ } else {
+ spec = false;
}
}
- switch(format[i]) {
- case '%':
+ if (format[i] == '%') {
PUTCHAR('%');
- break;
- case 'i':;
- case 'd': {
- if (u) {
- // TODO
- } else {
- long long int integer;
- if (l == 0) integer = va_arg(ap, int);
- if (l == 1) integer = va_arg(ap, long int);
- if (l == 2) integer = va_arg(ap, long long int);
-
- int cpt2 = 0;
- char buff_int[32];
-
- if (integer<0)
- PUTCHAR('-');
-
- do {
- int m10 = integer%10;
- m10 = (m10 < 0)? -m10:m10;
- buff_int[cpt2++] = (char)('0'+ m10);
- integer = integer/10;
- } while(integer != 0);
-
- for(cpt2 = cpt2 - 1; cpt2 >= 0; cpt2--)
- PUTCHAR(buff_int[cpt2]);
+ } else if (format[i] == 'i' || format[i] == 'd') {
+ if (u) {
+ // TODO
+ } else {
+ long long int integer;
+ if (l == 0) integer = va_arg(ap, int);
+ if (l == 1) integer = va_arg(ap, long int);
+ if (l == 2) integer = va_arg(ap, long long int);
+
+ int cpt2 = 0;
+ char buff_int[32];
+
+ if (integer<0) {
+ PUTCHAR('-');
}
- break;
+
+ do {
+ int m10 = integer%10;
+ m10 = (m10 < 0)? -m10:m10;
+ buff_int[cpt2++] = (char)('0'+ m10);
+ integer = integer/10;
+ } while(integer != 0);
+
+ for(cpt2 = cpt2 - 1; cpt2 >= 0; cpt2--)
+ PUTCHAR(buff_int[cpt2]);
}
- case 'c': {
+ } else if (format[i] == 'c') {
int value = va_arg(ap,int);
PUTCHAR((char)value);
break;
+ } else if (format[i] == 's') {
+ char *string = va_arg(ap,char *);
+ if (!string)
+ string = "(null)";
+ for(; *string != '\0' ; string++)
+ PUTCHAR(*string);
+ } else if (format[i] == 'x') {
+ unsigned int hexa = va_arg(ap,int);
+ int had_nonzero = 0;
+ for(int j = 0; j < 8; j++) {
+ unsigned int nb = (unsigned int)(hexa << (j*4));
+ nb = (nb >> 28) & 0xf;
+ // Skip the leading zeros
+ if (nb == 0) {
+ if (had_nonzero) {
+ PUTCHAR('0');
+ }
+ } else {
+ had_nonzero = 1;
+ if (nb < 10) {
+ PUTCHAR('0'+nb);
+ } else {
+ PUTCHAR('a'+(nb-10));
+ }
+ }
}
- case 's': {
- char *string = va_arg(ap,char *);
- if (!string)
- string = "(null)";
- for(; *string != '\0' ; string++)
- PUTCHAR(*string);
- break;
- }
- case 'x': {
- unsigned int hexa = va_arg(ap,int);
- int had_nonzero = 0;
- for(int j = 0; j < 8; j++) {
- unsigned int nb = (unsigned int)(hexa << (j*4));
- nb = (nb >> 28) & 0xf;
- // Skip the leading zeros
- if (nb == 0) {
- if (had_nonzero)
- PUTCHAR('0');
- } else {
- had_nonzero = 1;
- if (nb < 10)
- PUTCHAR('0'+nb);
- else
- PUTCHAR('a'+(nb-10));
- }
- }
- if (!had_nonzero)
- PUTCHAR('0');
- break;
+ if (!had_nonzero) {
+ PUTCHAR('0');
}
- case 'p': {
- unsigned int hexa = va_arg(ap,int);
- for (int j = 0; j < 8; j++) {
- unsigned int nb = (unsigned int)(hexa << (j*4));
- nb = (nb >> 28) & 0xf;
- if (nb < 10)
- PUTCHAR('0'+nb);
- else
- PUTCHAR('a'+(nb-10));
- }
- break;
+ } else if (format[i] == 'p') {
+ unsigned int hexa = va_arg(ap,int);
+ for (int j = 0; j < 8; j++) {
+ unsigned int nb = (unsigned int)(hexa << (j*4));
+ nb = (nb >> 28) & 0xf;
+ if (nb < 10) {
+ PUTCHAR('0'+nb);
+ } else {
+ PUTCHAR('a'+(nb-10));
+ }
}
- default:
- PUTCHAR('%');
- PUTCHAR(format[i]);
+ } else {
+ PUTCHAR('%');
+ PUTCHAR(format[i]);
}
} else {
PUTCHAR(format[i]);
}
}
- *buff = '\0';
- return result;
+ return ret;
}
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/common/libc/string.c b/src/common/libc/string.c
index 4b99dda..b2c6bb8 100644
--- a/src/common/libc/string.c
+++ b/src/common/libc/string.c
@@ -176,8 +176,9 @@ size_t strspn(const char *s, const char *accept) {
}
const char *strstr(const char *haystack, const char *needle) {
+ int n = strlen(needle);
for (const char* p = haystack; *p != 0; p++) {
- if (!strcmp(p, needle)) return p;
+ if (!strncmp(p, needle, n)) return p;
}
return NULL;
}
diff --git a/src/lib/include/stdio.h b/src/lib/include/stdio.h
index a67553c..5bb3b71 100644
--- a/src/lib/include/stdio.h
+++ b/src/lib/include/stdio.h
@@ -10,13 +10,22 @@
void setup_libc_stdio();
+#define BUFSIZ 256
+
-//TODO below
struct file_t {
fd_t fd;
stat_t st;
- int mode;
- int flags;
+ int file_mode;
+
+ size_t pos;
+
+ int buf_mode;
+ char *out_buf;
+ size_t out_buf_size, out_buf_used;
+ bool out_buf_owned;
+
+ int ungetc_char;
};
typedef struct file_t FILE;
@@ -52,7 +61,6 @@ int fclose(FILE* f);
extern FILE *stdin, *stdout, *stderr;
-#define BUFSIZ 1024
void setbuf(FILE *stream, char *buf);
void setbuffer(FILE *stream, char *buf, size_t size);
void setlinebuf(FILE *stream);
diff --git a/src/lib/libc/stdio.c b/src/lib/libc/stdio.c
index c849683..f825c1b 100644
--- a/src/lib/libc/stdio.c
+++ b/src/lib/libc/stdio.c
@@ -1,5 +1,6 @@
#include <string.h>
#include <stdio.h>
+#include <stdlib.h>
#include <proto/launch.h>
@@ -12,28 +13,69 @@ FILE *stderr = 0;
FILE libc_tty_stdio, libc_stdin, libc_stdout, libc_stderr;
+void initialize_out_buffer(FILE* f, int buf_mode) {
+ if (buf_mode == 0) {
+ f->buf_mode = 0;
+ f->out_buf = 0;
+ f->out_buf_size = f->out_buf_used = 0;
+ f->out_buf_owned = false;
+ } else {
+ f->buf_mode = buf_mode;
+ f->out_buf = malloc(BUFSIZ);
+ f->out_buf_size = BUFSIZ;
+ f->out_buf_used = 0;
+ f->out_buf_owned = true;
+ }
+}
+
void setup_libc_stdio() {
if (sc_stat_open(STD_FD_TTY_STDIO, &libc_tty_stdio.st)) {
libc_tty_stdio.fd = STD_FD_TTY_STDIO;
+ libc_tty_stdio.file_mode = (libc_tty_stdio.st.access & (FM_READ | FM_WRITE));
+ libc_tty_stdio.pos = 0;
+
+ initialize_out_buffer(&libc_tty_stdio, _IOLBF);
+
sc_fctl(libc_tty_stdio.fd, FC_SET_BLOCKING, 0);
- // TODO: initialize libc_tty_stdio as a TTY
+ libc_tty_stdio.file_mode |= FM_BLOCKING;
+ libc_tty_stdio.ungetc_char = EOF;
+
stdin = &libc_tty_stdio;
stdout = &libc_tty_stdio;
stderr = &libc_tty_stdio;
}
if (sc_stat_open(STD_FD_STDIN, &libc_stdin.st)) {
libc_stdin.fd = STD_FD_STDIN;
- // TODO: initialize
+ ASSERT(libc_stdin.st.access & FM_READ);
+ libc_stdin.file_mode = FM_READ;
+ libc_stdin.pos = 0;
+
+ initialize_out_buffer(&libc_stdin, 0);
+
+ sc_fctl(libc_stdin.fd, FC_SET_BLOCKING, 0);
+ libc_stdin.file_mode |= FM_BLOCKING;
+ libc_stdin.ungetc_char = EOF;
+
stdin = &libc_stdin;
}
if (sc_stat_open(STD_FD_STDOUT, &libc_stdout.st)) {
libc_stdout.fd = STD_FD_STDOUT;
- // TODO: initialize
+ ASSERT(libc_stdout.st.access & FM_WRITE);
+ libc_stdout.file_mode = FM_WRITE;
+ libc_stdout.pos = 0;
+
+ initialize_out_buffer(&libc_stdout, _IOLBF);
+
stdout = &libc_stdout;
}
if (sc_stat_open(STD_FD_STDERR, &libc_stderr.st)) {
libc_stderr.fd = STD_FD_STDERR;
- // TODO: initialize
+ ASSERT(libc_stderr.st.access & FM_WRITE);
+ libc_stderr.file_mode = FM_WRITE;
+ libc_stderr.pos = 0;
+
+ initialize_out_buffer(&libc_stderr, _IONBF);
+
stderr = &libc_stderr;
}
}
@@ -85,11 +127,16 @@ int fclose(FILE* f) {
// ---------------
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ ASSERT(size == 1); //TODO all cases
+
if (stream == NULL || stream->fd == 0) return 0;
// TODO buffering
- // TODO position
- return sc_read(stream->fd, 0, size * nmemb, ptr);
+ size_t ret = sc_read(stream->fd, stream->pos, size * nmemb, ptr);
+ if (!(stream->st.type & (FT_CHARDEV | FT_CHANNEL | FT_DIR))) {
+ stream->pos += ret;
+ }
+ return ret;
}
int fgetc(FILE *stream) {
@@ -108,8 +155,14 @@ char *fgets(char *s, int size, FILE *stream) {
if (c == EOF) {
break;
} else if (c == '\b') {
- if (l > 0) l--;
- // TODO if terminal write back space or something
+ if (l > 0) {
+ l--;
+ } else {
+ //HACK
+ if (stream == &libc_tty_stdio) {
+ putc(' ', stream);
+ }
+ }
} else {
s[l] = c;
l++;
@@ -132,26 +185,122 @@ int ungetc(int c, FILE *stream) {
// OUTPUT FUNCTIONS
// ----------------
+// buffering
+
+void setbuf(FILE *stream, char *buf) {
+ setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
+void setbuffer(FILE *stream, char *buf, size_t size) {
+ setvbuf(stream, buf, buf ? _IOFBF : _IONBF, size);
+}
+void setlinebuf(FILE *stream) {
+ setvbuf(stream, NULL, _IOLBF, 0);
+}
+int setvbuf(FILE *stream, char *buf, int mode, size_t size) {
+ if (stream == NULL || stream->fd == 0
+ || !(stream->file_mode & FM_WRITE)) return EOF;
+
+ if (fflush(stream) == EOF) return EOF;
+
+ if (stream->out_buf_owned) free(stream->out_buf);
+ if (buf == NULL) {
+ stream->out_buf = malloc(size);
+
+ // if we cannot allocate a buffer, set file to read-only mode
+ if (stream->out_buf == NULL) {
+ stream->file_mode &= ~FM_WRITE;
+ stream->buf_mode = 0;
+ return EOF;
+ }
+
+ stream->out_buf_owned = true;
+ } else {
+ stream->out_buf = buf;
+ stream->out_buf_owned = false;
+ }
+
+ stream->buf_mode = mode;
+
+ return 0;
+}
+
+int fflush(FILE* stream) {
+ if (stream == NULL || stream->fd == 0
+ || !(stream->file_mode & FM_WRITE)) return EOF;
+
+ if (stream->buf_mode != 0 && stream->out_buf_used > 0) {
+ size_t ret = sc_write(stream->fd, stream->pos, stream->out_buf_used, stream->out_buf);
+ stream->out_buf_used = 0;
+
+ if (ret != stream->out_buf_used) {
+ return EOF;
+ }
+ if (!(stream->st.type & (FT_CHARDEV | FT_CHANNEL | FT_DIR))) {
+ stream->pos += ret;
+ }
+ }
+ return 0;
+}
+
+int buffered_putc(int c, FILE* stream) {
+ ASSERT(stream->buf_mode != 0 && stream->out_buf_used < stream->out_buf_size);
+ stream->out_buf[stream->out_buf_used++] = c;
+ if (stream->out_buf_used == stream->out_buf_size ||
+ (stream->buf_mode == _IOLBF && c == '\n')) {
+ fflush(stream);
+ }
+ return c;
+}
+
+
+// real output functions
+
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
- if (stream == NULL || stream->fd == 0) return 0;
+ if (stream == NULL || stream->fd == 0
+ || !(stream->file_mode & FM_WRITE)) return 0;
- // TODO buffering
- // TODO position
- return sc_write(stream->fd, 0, size * nmemb, ptr);
+ fflush(stream);
+
+ size_t ret = sc_write(stream->fd, stream->pos, size * nmemb, ptr);
+ if (!(stream->st.type & (FT_CHARDEV | FT_CHANNEL | FT_DIR))) {
+ stream->pos += ret;
+ }
+ return ret / size;
}
int fputc(int c, FILE *stream) {
- unsigned char x = c;
- return fwrite(&x, 1, 1, stream);
+ if (stream == NULL || stream->fd == 0
+ || !(stream->file_mode & FM_WRITE)) return EOF;
+
+ buffered_putc(c, stream);
+ if (stream->buf_mode == _IONBF) {
+ if (fflush(stream) == EOF) return EOF;
+ }
+ return c;
}
int fputs(const char *s, FILE *stream) {
- return fwrite(s, strlen(s), 1, stream);
+ if (stream == NULL || stream->fd == 0
+ || !(stream->file_mode & FM_WRITE)) return EOF;
+
+ int i = 0;
+ while (s[i]) {
+ buffered_putc(s[i], stream);
+ i++;
+ }
+ if (stream->buf_mode == _IONBF) {
+ if (fflush(stream) == EOF) return EOF;
+ }
+ return i;
}
int putc(int c, FILE *stream) {
+ // just an alias
return fputc(c, stream);
}
int fprintf(FILE *stream, const char *fmt, ...) {
+ if (stream == NULL || stream->fd == 0
+ || !(stream->file_mode & FM_WRITE)) return -1;
+
va_list ap;
va_start(ap, fmt);
@@ -160,34 +309,28 @@ int fprintf(FILE *stream, const char *fmt, ...) {
return ret;
}
-int vfprintf(FILE *stream, const char *format, va_list ap) {
- char buf[1024];
- vsnprintf(buf, 1024, format, ap);
- return fputs(buf, stream);
+int vfprintf_putc_fun(int c, void* p) {
+ FILE *stream = (FILE*)p;
+ if (buffered_putc(c, stream) == EOF)
+ return -1;
+ else
+ return 1;
}
+int vfprintf(FILE *stream, const char *format, va_list ap) {
+ if (stream == NULL || stream->fd == 0
+ || !(stream->file_mode & FM_WRITE)) return -1;
-// buffering
+ int ret = vcprintf(vfprintf_putc_fun, stream, format, ap);
-void setbuf(FILE *stream, char *buf) {
- setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
-}
-void setbuffer(FILE *stream, char *buf, size_t size) {
- // TODO
-}
-void setlinebuf(FILE *stream) {
- setvbuf(stream, NULL, _IOLBF, 0);
-}
-int setvbuf(FILE *stream, char *buf, int mode, size_t size) {
- // TODO
- return 0;
-}
+ if (stream->buf_mode == _IONBF) {
+ if (fflush(stream) == EOF) return -1;
+ }
-int fflush(FILE* f) {
- // TODO
- return 0;
+ return ret;
}
+
// ---------------------
// COMPLICATED FUNCTIONS
// ---------------------
diff --git a/src/lib/lua/luaconf.h b/src/lib/lua/luaconf.h
index c6592fb..22418f3 100644
--- a/src/lib/lua/luaconf.h
+++ b/src/lib/lua/luaconf.h
@@ -178,7 +178,7 @@
LUA_ROOT"?.lua;" LUA_ROOT"?/init.lua;" \
"./?.lua;" "./?/init.lua"
#define LUA_CPATH_DEFAULT \
- LUA_ROOT"?.so;" LUA_ROOT"loadall.so;" "./?.so"
+ LUA_ROOT"?.so;" "./?.so"
/*