From: John Tsiombikas Date: Sun, 17 Nov 2019 15:43:41 +0000 (+0200) Subject: started the implementation X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=visor;a=commitdiff_plain;h=4f957b16f77eb7761afd9e0b9064c7f08deb45be started the implementation --- diff --git a/libvisor/Makefile b/libvisor/Makefile index 095481e..757ab30 100644 --- a/libvisor/Makefile +++ b/libvisor/Makefile @@ -4,7 +4,7 @@ dep = $(obj:.o=.d) liba = libvisor.a -CFLAGS = -pedantic -Wall -g +CFLAGS = -pedantic -Wall -g -Iinclude $(liba): $(obj) $(AR) rcs $@ $< diff --git a/libvisor/include/visor.h b/libvisor/include/visor.h index 165e2b2..4c8d1f1 100644 --- a/libvisor/include/visor.h +++ b/libvisor/include/visor.h @@ -60,6 +60,11 @@ enum vi_motdir { #define VI_MOTION(d, n) (((long)(n) << 8) | ((long)(d))) +struct vi_alloc { + void *(*malloc)(unsigned long); + void (*free)(void*); + void *(*realloc)(void*, unsigned long); /* can be null, will use malloc/free */ +}; struct vi_fileops { void *(*open)(const char *path); @@ -69,6 +74,7 @@ struct vi_fileops { void (*unmap)(void *file); long (*read)(void *file, void *buf, long count); long (*write)(void *file, void *buf, long count); + long (*seek)(void *file, long offs, int whence); }; struct vi_ttyops { @@ -84,9 +90,14 @@ struct vi_ttyops { void (*status)(char *s, void *cls); }; - -struct visor *vi_init(void); -void vi_cleanup(struct visor *vi); +/* Create a new instance of the visor editor. + * The alloc argument can be used to provide custom memory allocation + * functions. It can be null in a hosted build, or if you set the HAVE_LIBC + * preprocessor macro, in which case the standard library allocator will be + * used. + */ +struct visor *vi_create(struct vi_alloc *mm); +void vi_destroy(struct visor *vi); void vi_set_fileops(struct visor *vi, struct vi_fileops *fop); diff --git a/libvisor/src/vilibc.c b/libvisor/src/vilibc.c new file mode 100644 index 0000000..6c021b0 --- /dev/null +++ b/libvisor/src/vilibc.c @@ -0,0 +1,77 @@ +#include "vilibc.h" +#include "vimpl.h" + +#ifndef HAVE_LIBC + +void *memset(void *s, int c, unsigned long n) +{ + char *p = s; + while(n--) *p++ = c; + return s; +} + +void *memcpy(void *dest, const void *src, unsigned long n) +{ + char *d = dest; + const char *s = src; + while(n--) *d++ = *s++; + return dest; +} + +void *memmove(void *dest, const void *src, unsigned long n) +{ + unsigned long i; + char *dptr; + const char *sptr; + + if(dest <= src) { + /* forward copy */ + dptr = dest; + sptr = src; + for(i=0; itty.status) { + vi->tty.status(errstr_buf, vi->tty_cls); + } +} diff --git a/libvisor/src/vilibc.h b/libvisor/src/vilibc.h new file mode 100644 index 0000000..881c6ed --- /dev/null +++ b/libvisor/src/vilibc.h @@ -0,0 +1,41 @@ +#ifndef VISOR_LIBC_H_ +#define VISOR_LIBC_H_ + +/* XXX let's pretend we don't have a libc to test our own code +#ifdef __STDC_HOSTED__ +#define HAVE_LIBC +#endif +*/ + +#ifdef HAVE_LIBC +#include +#include +#include +#else + +void *memset(void *s, int c, unsigned long n); +void *memcpy(void *dest, const void *src, unsigned long n); +void *memmove(void *dest, const void *src, unsigned long n); +unsigned long strlen(const char *s); +int strcmp(const char *s1, const char *s2); + +#ifdef __GNUC__ +typedef __builtin_va_list va_list; +#define va_start(v,l) __builtin_va_start(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v,l) __builtin_va_arg(v,l) +#else /* !def __GNUC__ */ +#error "stdargs implementation for this compiler missing (libvisor/src/vilibc.h)" +#endif + +int sprintf(char *buf, const char *fmt, ...); +int vsprintf(char *buf, const char *fmt, va_list ap); +int snprintf(char *buf, unsigned long sz, const char *fmt, ...); +int vsnprintf(char *buf, unsigned long sz, const char *fmt, va_list ap); + +#endif /* !HAVE_LIBC */ + +struct visor; +void vi_error(struct visor *vi, const char *fmt, ...); + +#endif /* VISOR_LIBC_H_ */ diff --git a/libvisor/src/vimpl.h b/libvisor/src/vimpl.h index 1e6d201..b2d978f 100644 --- a/libvisor/src/vimpl.h +++ b/libvisor/src/vimpl.h @@ -6,6 +6,9 @@ struct visor { struct vi_fileops fop; struct vi_buffer *buflist; /* circular linked list of buffers cur first */ + struct vi_alloc mm; + struct vi_ttyops tty; + void *tty_cls; }; struct vi_buffer { diff --git a/libvisor/src/viprintf.c b/libvisor/src/viprintf.c new file mode 100644 index 0000000..5f2b312 --- /dev/null +++ b/libvisor/src/viprintf.c @@ -0,0 +1,249 @@ +#include "vilibc.h" + +enum { + OUT_BUF +}; + +static int intern_printf(int out, char *buf, unsigned long sz, const char *fmt, va_list ap); +static void bwrite(int out, char *buf, unsigned long buf_sz, char *str, int sz); + +int sprintf(char *buf, const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = intern_printf(OUT_BUF, buf, 0, fmt, ap); + va_end(ap); + return res; +} + +int vsprintf(char *buf, const char *fmt, va_list ap) +{ + return intern_printf(OUT_BUF, buf, 0, fmt, ap); +} + +int snprintf(char *buf, unsigned long sz, const char *fmt, ...) +{ + int res; + va_list ap; + + va_start(ap, fmt); + res = intern_printf(OUT_BUF, buf, sz, fmt, ap); + va_end(ap); + return res; +} + +int vsnprintf(char *buf, unsigned long sz, const char *fmt, va_list ap) +{ + return intern_printf(OUT_BUF, buf, sz, fmt, ap); +} + +/* intern_printf provides all the functionality needed by all the printf + * variants. + * - buf: optional buffer onto which the formatted results are written. If null + * then the output goes to the terminal through putchar calls. This is used + * by the (v)sprintf variants which write to an array of char. + * - sz: optional maximum size of the output, 0 means unlimited. This is used + * by the (v)snprintf variants to avoid buffer overflows. + * The rest are obvious, format string and variable argument list. + */ +static char *convc = "dioxXucsfeEgGpn%"; + +#define IS_CONV(c) strchr(convc, c) + +#define BUF(x) ((x) ? (x) + cnum : (x)) +#define SZ(x) ((x) ? (x) - cnum : (x)) + +static int intern_printf(int out, char *buf, unsigned long sz, const char *fmt, va_list ap) +{ + char conv_buf[32]; + char *str; + int i, slen; + const char *fstart = 0; + + /* state */ + int cnum = 0; + int base = 10; + int alt = 0; + int fwidth = 0; + int padc = ' '; + int sign = 0; + int left_align = 0; + int hex_caps = 0; + int unsig = 0; + int num, unum; + + while(*fmt) { + if(*fmt == '%') { + fstart = fmt++; + continue; + } + + if(fstart) { + if(IS_CONV(*fmt)) { + switch(*fmt) { + case 'X': + hex_caps = 1; + + case 'x': + case 'p': + base = 16; + + if(alt) { + bwrite(out, BUF(buf), SZ(sz), "0x", 2); + cnum += 2; + } + + case 'u': + unsig = 1; + + if(0) { + case 'o': + base = 8; + + if(alt) { + bwrite(out, BUF(buf), SZ(sz), "0", 1); + cnum++; + } + } + + case 'd': + case 'i': + if(unsig) { + unum = va_arg(ap, unsigned int); + utoa(unum, conv_buf, base); + } else { + num = va_arg(ap, int); + itoa(num, conv_buf, base); + } + if(hex_caps) { + for(i=0; conv_buf[i]; i++) { + conv_buf[i] = toupper(conv_buf[i]); + } + } + + slen = strlen(conv_buf); + + if(left_align) { + if(!unsig && sign && num >= 0) { + bwrite(out, BUF(buf), SZ(sz), "+", 1); + cnum++; + } + bwrite(out, BUF(buf), SZ(sz), conv_buf, slen); + cnum += slen; + padc = ' '; + } + for(i=slen; i= 0) { + bwrite(out, BUF(buf), SZ(sz), "+", 1); + cnum++; + } + bwrite(out, BUF(buf), SZ(sz), conv_buf, slen); + cnum += slen; + } + break; + + case 'c': + { + char c = va_arg(ap, int); + bwrite(out, BUF(buf), SZ(sz), &c, 1); + cnum++; + } + break; + + case 's': + str = va_arg(ap, char*); + slen = strlen(str); + + if(left_align) { + bwrite(out, BUF(buf), SZ(sz), str, slen); + cnum += slen; + padc = ' '; + } + for(i=slen; imm.malloc(s) +#define vi_free(p) vi->mm.free(p) + +#ifdef HAVE_LIBC +static const struct vi_alloc stdalloc = { malloc, free, realloc }; +#endif + +struct visor *vi_create(struct vi_alloc *mm) +{ + struct visor *vi; + +#ifdef HAVE_LIBC + if(!mm) mm = &stdalloc; +#else + if(!mm) return 0; +#endif + + if(!(vi = mm->malloc(sizeof *vi))) { + return 0; + } + memset(vi, 0, sizeof *vi); + vi->mm = *mm; + + return vi; +} + +void vi_destroy(struct visor *vi) +{ + while(vi->buflist) { + vi_delete_buf(vi, vi->buflist); + } + vi_free(vi); +} + +void vi_set_fileops(struct visor *vi, struct vi_fileops *fop) +{ + vi->fop = *fop; +} + +struct vi_buffer *vi_new_buf(struct visor *vi, const char *path) +{ + struct vi_buffer *nb; + + if(!(nb = vi_malloc(sizeof *nb))) { + vi_error(vi, "failed to allocate new buffer\n"); + return 0; + } + memset(nb, 0, sizeof *nb); + + if(path) { + if(vi_buf_read(nb, path) == -1) { + vi_free(nb); + return 0; + } + } + + if(vi->buflist) { + struct vi_buffer *last = vi->buflist->prev; + nb->prev = last; + nb->next = vi->buflist; + last->next = nb; + vi->buflist->prev = nb; + } else { + nb->next = nb->prev = nb; + vi->buflist = nb; + } + return nb; +}