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 {
};
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 {
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
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.
*/
#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;
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) {
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];
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
+#include <ctype.h>
+#include <limit.h>
#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
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;
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;
int num_spans, max_spans;
};
+enum { SPAN_ORIG, SPAN_ADD };
+
#endif /* VIMPL_H_ */
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, ...)
{
*/
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;
+}
+
#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 };
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;
return 0;
}
memset(nb, 0, sizeof *nb);
+ nb->vi = vi;
if(path) {
if(vi_buf_read(nb, path) == -1) {
}
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;
+}