From 9f0326a07930f909b44433f5d0e3b556d0b16a51 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sun, 17 Nov 2019 22:34:23 +0200 Subject: [PATCH] span table --- libvisor/include/visor.h | 26 ++++--- libvisor/src/vilibc.c | 140 ++++++++++++++++++++++++++++++++++++ libvisor/src/vilibc.h | 25 ++++++- libvisor/src/vimpl.h | 7 +- libvisor/src/viprintf.c | 61 +++++++++++++++- libvisor/src/visor.c | 178 +++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 420 insertions(+), 17 deletions(-) diff --git a/libvisor/include/visor.h b/libvisor/include/visor.h index 4c8d1f1..2846218 100644 --- a/libvisor/include/visor.h +++ b/libvisor/include/visor.h @@ -20,12 +20,14 @@ along with this program. If not, see . typedef long vi_addr; typedef long vi_motion; +typedef void vi_file; struct visor; struct vi_buffer; struct vi_span { - vi_addr beg, end; + vi_addr beg; + unsigned long size; }; enum vi_motdir { @@ -67,14 +69,14 @@ struct vi_alloc { }; struct vi_fileops { - void *(*open)(const char *path); - long (*size)(void *file); - void (*close)(void *file); - void *(*map)(void *file); - 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); + vi_file *(*open)(const char *path); + long (*size)(vi_file *file); + void (*close)(vi_file *file); + void *(*map)(vi_file *file); + void (*unmap)(vi_file *file); + long (*read)(vi_file *file, void *buf, long count); + long (*write)(vi_file *file, void *buf, long count); + long (*seek)(vi_file *file, long offs, int whence); }; struct vi_ttyops { @@ -100,6 +102,7 @@ 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); +void vi_set_ttyops(struct visor *vi, struct vi_ttyops *tty); /* vi_new_buf creates a new buffer and inserts it in the buffer list. If the * path pointer is null, the new buffer will be empty, otherwise it's as if it @@ -110,12 +113,15 @@ int vi_delete_buf(struct visor *vi, struct vi_buffer *vb); int vi_num_buf(struct visor *vi); struct vi_buffer *vi_getcur_buf(struct visor *vi); -int vi_setcur_buf(struct visor *vi, struct vi_buffer *vb); +void vi_setcur_buf(struct visor *vi, struct vi_buffer *vb); struct vi_buffer *vi_next_buf(struct visor *vi); struct vi_buffer *vi_prev_buf(struct visor *vi); +/* reset a buffer to the newly created state, freeing all resources */ +void vi_buf_reset(struct vi_buffer *vb); + /* Read a file into the buffer. * Returns 0 on success, -1 on failure. */ diff --git a/libvisor/src/vilibc.c b/libvisor/src/vilibc.c index 6c021b0..79081ef 100644 --- a/libvisor/src/vilibc.c +++ b/libvisor/src/vilibc.c @@ -3,6 +3,72 @@ #ifndef HAVE_LIBC +int atoi(const char *str) +{ + return strtol(str, 0, 10); +} + +long atol(const char *str) +{ + return strtol(str, 0, 10); +} + +long strtol(const char *str, char **endp, int base) +{ + long acc = 0; + int sign = 1; + int valid = 0; + const char *start = str; + + while(isspace(*str)) str++; + + if(base == 0) { + if(str[0] == '0') { + if(str[1] == 'x' || str[1] == 'X') { + base = 16; + } else { + base = 8; + } + } else { + base = 10; + } + } + + if(*str == '+') { + str++; + } else if(*str == '-') { + sign = -1; + str++; + } + + while(*str) { + long val = 0x7fffffff; + char c = tolower(*str); + + if(isdigit(c)) { + val = *str - '0'; + } else if(c >= 'a' && c <= 'f') { + val = 10 + c - 'a'; + } else { + break; + } + if(val >= base) { + break; + } + valid = 1; + + acc = acc * base + val; + str++; + } + + if(endp) { + *endp = (char*)(valid ? str : start); + } + + return sign > 0 ? acc : -acc; +} + + void *memset(void *s, int c, unsigned long n) { char *p = s; @@ -50,6 +116,17 @@ unsigned long strlen(const char *s) return len; } +char *strchr(const char *s, int c) +{ + while(*s) { + if(*s == c) { + return (char*)s; + } + s++; + } + return 0; +} + int strcmp(const char *s1, const char *s2) { while(*s1 && *s1 == *s2) { @@ -59,6 +136,69 @@ int strcmp(const char *s1, const char *s2) return *s1 - *s2; } +char *strcpy(char *dest, const char *src) +{ + char *dptr = dest; + while((*dptr++ = *src++)); + return dest; +} + + +int isalnum(int c) +{ + return isalpha(c) || isdigit(c); +} + +int isalpha(int c) +{ + return isupper(c) || islower(c); +} + +int isblank(int c) +{ + return c == ' ' || c == '\t'; +} + +int isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +int isupper(int c) +{ + return c >= 'A' && c <= 'Z'; +} + +int islower(int c) +{ + return c >= 'a' && c <= 'z'; +} + +int isgraph(int c) +{ + return c > ' ' && c <= '~'; +} + +int isprint(int c) +{ + return isgraph(c) || c == ' '; +} + +int isspace(int c) +{ + return isblank(c) || c == '\f' || c == '\n' || c == '\r' || c == '\v'; +} + +int toupper(int c) +{ + return islower(c) ? (c + ('A' - 'a')) : c; +} + +int tolower(int c) +{ + return isupper(c) ? (c - ('A' - 'a')) : c; +} + #endif /* !def HAVE_LIBC */ static char errstr_buf[256]; diff --git a/libvisor/src/vilibc.h b/libvisor/src/vilibc.h index 881c6ed..e955585 100644 --- a/libvisor/src/vilibc.h +++ b/libvisor/src/vilibc.h @@ -11,19 +11,27 @@ #include #include #include +#include +#include #else +int atoi(const char *str); +long atol(const char *str); +long strtol(const char *str, char **endp, int base); + 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); +char *strchr(const char *s, int c); int strcmp(const char *s1, const char *s2); +char *strcpy(char *dest, const char *src); #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) +#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 @@ -33,6 +41,19 @@ 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); +int isalnum(int c); +int isalpha(int c); +#define isascii(c) ((c) < 128) +int isblank(int c); +int isdigit(int c); +int isupper(int c); +int islower(int c); +int isprint(int c); +int isspace(int c); + +int toupper(int c); +int tolower(int c); + #endif /* !HAVE_LIBC */ struct visor; diff --git a/libvisor/src/vimpl.h b/libvisor/src/vimpl.h index b2d978f..af9b6c4 100644 --- a/libvisor/src/vimpl.h +++ b/libvisor/src/vimpl.h @@ -19,8 +19,11 @@ struct vi_buffer { vi_addr cursor, view_start; int view_xscroll; + vi_file *fp; + int file_mapped; + char *orig; - long orig_size; + unsigned long orig_size; char *add; int add_size, add_max; @@ -28,4 +31,6 @@ struct vi_buffer { int num_spans, max_spans; }; +enum { SPAN_ORIG, SPAN_ADD }; + #endif /* VIMPL_H_ */ diff --git a/libvisor/src/viprintf.c b/libvisor/src/viprintf.c index 5f2b312..315a7e1 100644 --- a/libvisor/src/viprintf.c +++ b/libvisor/src/viprintf.c @@ -6,6 +6,8 @@ enum { 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); +static void utoa(unsigned int val, char *buf, int base); +static void itoa(int val, char *buf, int base); int sprintf(char *buf, const char *fmt, ...) { @@ -239,11 +241,66 @@ static int intern_printf(int out, char *buf, unsigned long sz, const char *fmt, */ static void bwrite(int out, char *buf, unsigned long buf_sz, char *str, int sz) { - int i; - if(out == OUT_BUF) { if(buf_sz && buf_sz <= sz) sz = buf_sz; buf[sz] = 0; memcpy(buf, str, sz); } } + +static void utoa(unsigned int val, char *buf, int base) +{ + static char rbuf[16]; + char *ptr = rbuf; + + if(val == 0) { + *ptr++ = '0'; + } + + while(val) { + unsigned int digit = val % base; + *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a'); + val /= base; + } + + ptr--; + + while(ptr >= rbuf) { + *buf++ = *ptr--; + } + *buf = 0; +} + +static void itoa(int val, char *buf, int base) +{ + static char rbuf[16]; + char *ptr = rbuf; + int neg = 0; + + if(val < 0) { + neg = 1; + val = -val; + } + + if(val == 0) { + *ptr++ = '0'; + } + + while(val) { + int digit = val % base; + *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a'); + val /= base; + } + + if(neg) { + *ptr++ = '-'; + } + + ptr--; + + while(ptr >= rbuf) { + *buf++ = *ptr--; + } + *buf = 0; +} + diff --git a/libvisor/src/visor.c b/libvisor/src/visor.c index af79b4a..fc336d8 100644 --- a/libvisor/src/visor.c +++ b/libvisor/src/visor.c @@ -2,8 +2,18 @@ #include "visor.h" #include "vimpl.h" -#define vi_malloc(s) vi->mm.malloc(s) -#define vi_free(p) vi->mm.free(p) +#define vi_malloc vi->mm.malloc +#define vi_free vi->mm.free +#define vi_realloc vi->mm.realloc + +#define vi_open vi->fop.open +#define vi_size vi->fop.size +#define vi_close vi->fop.close +#define vi_map vi->fop.map +#define vi_unmap vi->fop.unmap +#define vi_read vi->fop.read +#define vi_write vi->fop.write +#define vi_seek vi->fop.seek #ifdef HAVE_LIBC static const struct vi_alloc stdalloc = { malloc, free, realloc }; @@ -41,6 +51,11 @@ void vi_set_fileops(struct visor *vi, struct vi_fileops *fop) vi->fop = *fop; } +void vi_set_ttyops(struct visor *vi, struct vi_ttyops *tty) +{ + vi->tty = *tty; +} + struct vi_buffer *vi_new_buf(struct visor *vi, const char *path) { struct vi_buffer *nb; @@ -50,6 +65,7 @@ struct vi_buffer *vi_new_buf(struct visor *vi, const char *path) return 0; } memset(nb, 0, sizeof *nb); + nb->vi = vi; if(path) { if(vi_buf_read(nb, path) == -1) { @@ -70,3 +86,161 @@ struct vi_buffer *vi_new_buf(struct visor *vi, const char *path) } return nb; } + +static int remove_buf(struct visor *vi, struct vi_buffer *vb) +{ + if(!vi->buflist) { + vi_error(vi, "failed to remove a buffer which doesn't exist\n"); + return -1; + } + + if(vb->next == vb) { + if(vi->buflist != vb) { + vi_error(vi, "failed to remove buffer, buffer list inconsistency\n"); + return -1; + } + vi->buflist = 0; + return 0; + } + + if(vi->buflist == vb) { + vi->buflist = vb->next; + } + vb->prev->next = vb->next; + vb->next->prev = vb->prev; + vb->next = vb->prev = vb; + return 0; +} + +int vi_delete_buf(struct visor *vi, struct vi_buffer *vb) +{ + if(remove_buf(vi, vb) == -1) { + return -1; + } + + vi_free(vb->path); + vi_free(vb->orig); + vi_free(vb->add); + vi_free(vb->spans); + return 0; +} + +int vi_num_buf(struct visor *vi) +{ + int count; + struct vi_buffer *vb; + + if(!vi->buflist) return 0; + + count = 1; + vb = vi->buflist->next; + while(vb != vi->buflist) { + count++; + vb = vb->next; + } + return count; +} + +struct vi_buffer *vi_getcur_buf(struct visor *vi) +{ + return vi->buflist; +} + +void vi_setcur_buf(struct visor *vi, struct vi_buffer *vb) +{ + vi->buflist = vb; +} + +struct vi_buffer *vi_next_buf(struct visor *vi) +{ + return vi->buflist ? vi->buflist->next : 0; +} + +struct vi_buffer *vi_prev_buf(struct visor *vi) +{ + return vi->buflist ? vi->buflist->prev : 0; +} + +static int add_span(struct vi_buffer *vb, int src, vi_addr start, unsigned long size) +{ + struct visor *vi = vb->vi; + struct vi_span *sp; + + if(vb->num_spans >= vb->max_spans) { + int newmax = vb->max_spans > 0 ? (vb->max_spans << 1) : 16; + struct vi_span *tmp = vi_realloc(vb->spans, newmax * sizeof *tmp); + if(!tmp) return -1; + vb->spans = tmp; + vb->max_spans = newmax; + } + + sp = vb->spans + vb->num_spans++; + sp->beg = start; + sp->size = size; + return 0; +} + +void vi_buf_reset(struct vi_buffer *vb) +{ + struct visor *vi = vb->vi; + struct vi_buffer *prev, *next; + + vi_free(vb->path); + + if(vb->fp) { + if(vb->file_mapped) vi_unmap(vb->fp); + vi_close(vb->fp); + } + vi_free(vb->orig); + vi_free(vb->add); + vi_free(vb->spans); + + prev = vb->prev; + next = vb->next; + memset(vb, 0, sizeof *vb); + vb->prev = prev; + vb->next = next; +} + +int vi_buf_read(struct vi_buffer *vb, const char *path) +{ + struct visor *vi = vb->vi; + vi_file *fp; + unsigned long fsz; + int plen; + + vi_buf_reset(vb); + + if(!(fp = vi_open(path))) { + return -1; + } + plen = strlen(path); + if(!(vb->path = vi_malloc(plen + 1))) { + vi_error(vi, "failed to allocate path name buffer\n"); + vi_buf_reset(vb); + return -1; + } + memcpy(vb->path, path, plen + 1); + + vb->num_spans = 0; + + if((fsz = vi_size(fp))) { + /* existing file, map it into memory, or failing that read it */ + if(!vi->fop.map || !(vb->orig = vi_map(fp))) { + if(!(vb->orig = vi_malloc(fsz))) { + vi_buf_reset(vb); + return -1; + } + } else { + vb->file_mapped = 1; + } + + if(add_span(vb, SPAN_ORIG, 0, fsz) == -1) { + vi_error(vi, "failed to allocate span\n"); + vi_buf_reset(vb); + return -1; + } + } + vb->orig_size = fsz; + return 0; +} -- 1.7.10.4