Introduction
Introduction Statistics Contact Development Disclaimer Help
tChange assert to dump contents of buffer before abort - ledit - Text editor (W…
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log
Files
Refs
README
LICENSE
---
commit b8557a969d0da663fe3175d19269cb2f37eb9e72
parent 7501cea8774e0b58705da53357947723f213cbf5
Author: lumidify <[email protected]>
Date: Thu, 9 Dec 2021 23:13:50 +0100
Change assert to dump contents of buffer before abort
Diffstat:
M Makefile | 2 ++
A assert.c | 31 +++++++++++++++++++++++++++++…
A assert.h | 8 ++++++++
M buffer.c | 54 ++++++++++++++++++++++-------…
M buffer.h | 18 ++++++++++++++++--
M cache.c | 6 +++---
M cleanup.h | 1 +
M keys_basic.c | 1 -
M keys_command.c | 2 +-
M ledit.c | 43 +++++++++++++++++++++++++++++…
M memory.c | 14 +++++++-------
M undo.c | 4 ++--
M view.c | 30 +++++++++++++++---------------
M window.c | 8 ++++----
14 files changed, 170 insertions(+), 52 deletions(-)
---
diff --git a/Makefile b/Makefile
t@@ -10,6 +10,7 @@ BIN = ${NAME}
MAN1 = ${BIN:=.1}
OBJ = \
+ assert.o \
buffer.o \
view.o \
cache.o \
t@@ -27,6 +28,7 @@ OBJ = \
pango-compat.o
HDR = \
+ assert.h \
buffer.h \
view.h \
cache.h \
diff --git a/assert.c b/assert.c
t@@ -0,0 +1,31 @@
+/* FIXME: sort out the stupid includes */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <pango/pangoxft.h>
+#include <X11/extensions/Xdbe.h>
+
+#include "pango-compat.h"
+#include "memory.h"
+#include "common.h"
+#include "txtbuf.h"
+#include "undo.h"
+#include "cache.h"
+#include "theme.h"
+#include "window.h"
+#include "buffer.h"
+#include "cleanup.h"
+
+void
+ledit_assert_impl(const char *file, int line, const char *func, const char *fa…
+{
+ (void)fprintf(stderr,
+ "assertion \"%s\" failed: file \"%s\", line %d, function \"%s\"\n",
+ failedexpr, file, line, func);
+ ledit_emergencydump();
+ abort();
+ /* NOTREACHED */
+}
diff --git a/assert.h b/assert.h
t@@ -0,0 +1,8 @@
+#ifndef _LEDIT_ASSERT_H_
+#define _LEDIT_ASSERT_H_
+
+/* based on the assert found in OpenBSD */
+void ledit_assert_impl(const char *file, int line, const char *func, const cha…
+#define ledit_assert(e) ((e) ? (void)0 : ledit_assert_impl(__FILE__, __LINE__,…
+
+#endif
diff --git a/buffer.c b/buffer.c
t@@ -6,9 +6,9 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
-#include <assert.h>
#include <limits.h>
#include <stdlib.h>
+#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
t@@ -25,6 +25,7 @@
#include "theme.h"
#include "window.h"
#include "buffer.h"
+#include "assert.h"
/*
* Important notes:
t@@ -388,13 +389,9 @@ errorclose:
return 1;
}
-/* FIXME: allow to write only certain lines */
int
-buffer_write_to_file(ledit_buffer *buffer, char *filename, char **errstr) {
- FILE *file;
+buffer_write_to_file(ledit_buffer *buffer, FILE *file, char **errstr) {
ledit_line *ll;
- file = fopen(filename, "w");
- if (!file) goto error;
clearerr(file);
for (size_t i = 0; i < buffer->lines_num; i++) {
ll = buffer_get_line(buffer, i);
t@@ -414,6 +411,32 @@ errorclose:
return 1;
}
+int
+buffer_write_to_fd(ledit_buffer *buffer, int fd, char **errstr) {
+ FILE *file = fdopen(fd, "w");
+ if (!file) goto error;
+ return buffer_write_to_file(buffer, file, errstr);
+error:
+ if (*errstr)
+ *errstr = strerror(errno);
+ /* catching errors on the close wouldn't
+ really make much sense anymore */
+ close(fd);
+ return 1;
+}
+
+/* FIXME: allow to write only certain lines */
+int
+buffer_write_to_filename(ledit_buffer *buffer, char *filename, char **errstr) {
+ FILE *file = fopen(filename, "w");
+ if (!file) goto error;
+ return buffer_write_to_file(buffer, file, errstr);
+error:
+ if (*errstr)
+ *errstr = strerror(errno);
+ return 1;
+}
+
void
buffer_destroy(ledit_buffer *buffer) {
ledit_line *l;
t@@ -439,8 +462,9 @@ buffer_normalize_line(ledit_line *line) {
);
line->gap = line->len;
}
- /* FIXME: check if enough space, just to be sure */
- assert(line->len < line->cap);
+ /* this should never happen because the functions always
+ make sure to allocate one more for the '\0' */
+ ledit_assert(line->len < line->cap);
line->text[line->len] = '\0';
}
t@@ -455,7 +479,7 @@ buffer_insert_text_from_line_base(
size_t dst_line, size_t dst_index,
size_t src_line, size_t src_index, size_t src_len,
txtbuf *text_ret) {
- assert(dst_line != src_line);
+ ledit_assert(dst_line != src_line);
ledit_line *ll = buffer_get_line(buffer, src_line);
if (text_ret != NULL) {
txtbuf_grow(text_ret, src_len);
t@@ -684,9 +708,9 @@ buffer_append_line_base(ledit_buffer *buffer, size_t line_…
static void
buffer_delete_line_entries_base(ledit_buffer *buffer, size_t index1, size_t in…
ledit_line *l;
- assert (index2 >= index1);
+ ledit_assert(index2 >= index1);
/* it isn't allowed to delete all lines */
- assert(index2 - index1 != buffer->lines_num);
+ ledit_assert(index2 - index1 != buffer->lines_num);
for (size_t i = index1; i <= index2; i++) {
l = buffer_get_line(buffer, i);
free(l->text);
t@@ -700,7 +724,7 @@ buffer_delete_line_entries_base(ledit_buffer *buffer, size…
ledit_line *
buffer_get_line(ledit_buffer *buffer, size_t index) {
- assert(index < buffer->lines_num);
+ ledit_assert(index < buffer->lines_num);
return index < buffer->lines_gap ?
&buffer->lines[index] :
&buffer->lines[index + buffer->lines_cap - buffer->lines_num];
t@@ -729,7 +753,7 @@ buffer_recalc_all_lines(ledit_buffer *buffer) {
size_t
buffer_textlen(ledit_buffer *buffer, size_t line1, size_t byte1, size_t line2,…
- assert(line1 < line2 || (line1 == line2 && byte1 <= byte2));
+ ledit_assert(line1 < line2 || (line1 == line2 && byte1 <= byte2));
size_t len = 0;
ledit_line *ll = buffer_get_line(buffer, line1);
if (line1 == line2) {
t@@ -753,7 +777,7 @@ buffer_textlen(ledit_buffer *buffer, size_t line1, size_t …
backend is added, it would be good to optimize this, though. */
void
buffer_copy_text(ledit_buffer *buffer, char *dst, int line1, int byte1, int li…
- assert(line1 < line2 || (line1 == line2 && byte1 <= byte2));
+ ledit_assert(line1 < line2 || (line1 == line2 && byte1 <= byte2));
ledit_line *ll1 = buffer_get_line(buffer, line1);
ledit_line *ll2 = buffer_get_line(buffer, line2);
buffer_normalize_line(ll1);
t@@ -787,7 +811,7 @@ buffer_copy_text_to_txtbuf(
txtbuf *buf,
size_t line1, size_t byte1,
size_t line2, size_t byte2) {
- assert(line1 < line2 || (line1 == line2 && byte1 <= byte2));
+ ledit_assert(line1 < line2 || (line1 == line2 && byte1 <= byte2));
size_t len = buffer_textlen(buffer, line1, byte1, line2, byte2);
txtbuf_grow(buf, len + 1);
buffer_copy_text(buffer, buf->text, line1, byte1, line2, byte2);
diff --git a/buffer.h b/buffer.h
t@@ -95,12 +95,26 @@ void buffer_recalc_all_views_from_line(ledit_buffer *buffe…
int buffer_load_file(ledit_buffer *buffer, char *filename, size_t line, char *…
/*
- * Write the buffer to a file.
+ * Write the buffer to a FILE pointer.
* Returns 0 on success and 1 on error. In case of an error, *errstr is filled
* with an error message which must be copied as soon as possible because it m…
* be overwritten by subsequent function calls.
+ * In all cases, 'file' is closed.
*/
-int buffer_write_to_file(ledit_buffer *buffer, char *filename, char **errstr);
+int buffer_write_to_file(ledit_buffer *buffer, FILE *file, char **errstr);
+
+/*
+ * Write the buffer to a filename.
+ * Behaves the same as 'buffer_write_to_file'.
+ */
+int buffer_write_to_filename(ledit_buffer *buffer, char *filename, char **errs…
+
+/*
+ * Write the buffer to a file descriptor.
+ * Behaves the same as 'buffer_write_to_file', but if the
+ * file descriptor cannot be fdopen'd, it is closed before returning.
+ */
+int buffer_write_to_fd(ledit_buffer *buffer, int fd, char **errstr);
/*
* Destroy a buffer.
diff --git a/cache.c b/cache.c
t@@ -1,5 +1,4 @@
#include <stdio.h>
-#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#include <X11/Xlib.h>
t@@ -10,6 +9,7 @@
#include "common.h"
#include "memory.h"
#include "cache.h"
+#include "assert.h"
ledit_cache *
cache_create(Display *dpy) {
t@@ -84,13 +84,13 @@ cache_destroy(ledit_cache *cache) {
cache_pixmap *
cache_get_pixmap(ledit_cache *cache, size_t index) {
- assert(index < cache->num_pixmaps);
+ ledit_assert(index < cache->num_pixmaps);
return &cache->pixmaps[index];
}
cache_layout *
cache_get_layout(ledit_cache *cache, size_t index) {
- assert(index < cache->num_layouts);
+ ledit_assert(index < cache->num_layouts);
return &cache->layouts[index];
}
diff --git a/cleanup.h b/cleanup.h
t@@ -1,3 +1,4 @@
/* This is here so it can be called from other places
even though the function definition is in ledit.c */
void ledit_cleanup(void);
+void ledit_emergencydump(void);
diff --git a/keys_basic.c b/keys_basic.c
t@@ -11,7 +11,6 @@
them reliably yet */
#include <stdio.h>
#include <stdlib.h>
-#include <assert.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
diff --git a/keys_command.c b/keys_command.c
t@@ -118,7 +118,7 @@ handle_write(ledit_view *view, char *cmd, size_t l1, size_…
/* FIXME: Implement properly; handle error */
char *errstr;
if (view->buffer->filename)
- buffer_write_to_file(view->buffer, view->buffer->filename, &er…
+ buffer_write_to_filename(view->buffer, view->buffer->filename,…
return 0;
}
diff --git a/ledit.c b/ledit.c
t@@ -1,4 +1,4 @@
-/* FIXME: Add special assert that dumps currently edited file to backup on err…
+/* FIXME: clean up asserts a bit; clean up includes */
/* FIXME: On large files, expose event takes a long time for some reason
-> but somehow only sometimes... */
/* FIXME: generally optimize redrawing */
t@@ -18,7 +18,6 @@
#include <time.h>
#include <stdio.h>
#include <errno.h>
-#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
t@@ -255,6 +254,46 @@ setup(int argc, char *argv[]) {
}
void
+ledit_emergencydump(void) {
+ if (!buffer)
+ return;
+ /* FIXME: maybe write assertion message to file? */
+ char *orig = buffer->filename ? buffer->filename : "ledit";
+ char *suffix = "-emergency-dump-XXXXXXXXXX";
+ size_t len1, len2;
+ len1 = strlen(orig);
+ len2 = strlen(suffix);
+ /* This doesn't use ledit_strcat so a memory allocation
+ failure doesn't interfere with the abort in the assertion
+ that calls this function. */
+ char *template = malloc(len1 + len2 + 1);
+ if (!template)
+ return;
+ strcpy(template, orig);
+ strcpy(template + len1, suffix);
+ int fd = mkstemp(template);
+ if (fd == -1) {
+ fprintf(
+ stderr,
+ "Unable to open file for emergency dump: %s\n",
+ strerror(errno)
+ );
+ }
+ char *errstr;
+ if (buffer_write_to_fd(buffer, fd, &errstr)) {
+ fprintf(
+ stderr,
+ "Unable to perform emergency dump: %s\n",
+ errstr
+ );
+ /* FIXME: maybe just leave the file in case at
+ least part of it was written? */
+ unlink(template);
+ }
+ free(template);
+}
+
+void
ledit_cleanup(void) {
/* FIXME: check for other things to clean up */
search_cleanup();
diff --git a/memory.c b/memory.c
t@@ -2,9 +2,9 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "cleanup.h"
+#include "assert.h"
static void
fatal_err(const char *msg) {
t@@ -65,7 +65,7 @@ ledit_realloc(void *ptr, size_t size) {
the actual strcat. Aborts program on error */
char *
ledit_strcat(const char *str1, const char *str2) {
- int len1, len2;
+ size_t len1, len2;
char *ret;
len1 = strlen(str1);
t@@ -103,9 +103,9 @@ move_gap(
void *array, size_t elem_size, size_t index,
size_t gap, size_t cap, size_t len,
size_t *new_gap_ret) {
- assert(array != NULL);
- assert(index <= len);
- assert(len <= cap);
+ ledit_assert(array != NULL);
+ ledit_assert(index <= len);
+ ledit_assert(len <= cap);
char *carray = (char *)array; /* cast to char * for pointer arithmetic…
/* since the array has size cap * elem_size, it is assumed that no ove…
if (index > gap) {
t@@ -139,8 +139,8 @@ resize_and_move_gap(
size_t old_gap, size_t old_cap, size_t len,
size_t min_size, size_t index,
size_t *new_gap_ret, size_t *new_cap_ret) {
- assert(index <= len);
- assert(len <= old_cap);
+ ledit_assert(index <= len);
+ ledit_assert(len <= old_cap);
size_t gap_size = old_cap - len;
size_t new_cap = old_cap;
/* FIXME: read up on what the best values are here */
diff --git a/undo.c b/undo.c
t@@ -1,5 +1,4 @@
#include <string.h>
-#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
t@@ -12,6 +11,7 @@
#include "txtbuf.h"
#include "cache.h"
#include "undo.h"
+#include "assert.h"
/* FIXME: more sanity checks in case text is
inserted/deleted without adding to undo stack */
t@@ -66,7 +66,7 @@ undo_stack_destroy(undo_stack *undo) {
/* FIXME: resize text buffers when they aren't needed anymore */
static undo_elem *
push_undo_elem(undo_stack *undo) {
- assert(undo->cur >= -1);
+ ledit_assert(undo->cur >= -1);
undo->cur++;
undo->len = undo->cur + 1;
if (undo->len > undo->cap) {
diff --git a/view.c b/view.c
t@@ -4,7 +4,6 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
-#include <assert.h>
#include <limits.h>
#include <stdlib.h>
t@@ -23,6 +22,7 @@
#include "theme.h"
#include "window.h"
#include "buffer.h"
+#include "assert.h"
/* Basic attributes set for all text. */
static PangoAttrList *basic_attrs = NULL;
t@@ -162,7 +162,7 @@ view_unlock(ledit_view *view) {
ledit_view_line *
view_get_line(ledit_view *view, size_t index) {
- assert(index < view->lines_num);
+ ledit_assert(index < view->lines_num);
return index < view->lines_gap ?
&view->lines[index] :
&view->lines[index + view->lines_cap - view->lines_num];
t@@ -386,7 +386,7 @@ void
render_line(ledit_view *view, size_t line_index) {
/* FIXME: check for <= 0 on size */
ledit_view_line *ll = view_get_line(view, line_index);
- assert(!ll->h_dirty); /* FIXME */
+ ledit_assert(!ll->h_dirty); /* FIXME */
PangoLayout *layout = get_pango_layout(view, line_index);
if (!ll->cache_pixmap_valid) {
cache_assign_pixmap_index(
t@@ -884,9 +884,9 @@ void
view_get_pos_softline_bounds(
ledit_view *view, size_t line, size_t pos,
size_t *start_byte_ret, size_t *end_byte_ret) {
- assert(line < view->lines_num);
+ ledit_assert(line < view->lines_num);
ledit_line *ll = buffer_get_line(view->buffer, line);
- assert(pos <= ll->len);
+ ledit_assert(pos <= ll->len);
PangoLayout *layout = get_pango_layout(view, line);
int x, sli;
if (pos > INT_MAX)
t@@ -901,10 +901,10 @@ void
view_get_softline_bounds(
ledit_view *view, size_t line, int softline,
size_t *start_byte_ret, size_t *end_byte_ret) {
- assert(line < view->lines_num);
+ ledit_assert(line < view->lines_num);
ledit_view_line *vl = view_get_line(view, line);
PangoLayout *layout = get_pango_layout(view, line);
- assert(softline < vl->softlines);
+ ledit_assert(softline < vl->softlines);
PangoLayoutLine *pl = pango_layout_get_line_readonly(layout, softline);
*start_byte_ret = (size_t)pl->start_index;
*end_byte_ret = (size_t)(pl->start_index + pl->length);
t@@ -912,7 +912,7 @@ view_get_softline_bounds(
int
view_get_softline_count(ledit_view *view, size_t line) {
- assert(line < view->lines_num);
+ ledit_assert(line < view->lines_num);
ledit_view_line *vl = view_get_line(view, line);
if (vl->text_dirty)
set_pango_text_and_highlight(view, line);
t@@ -921,9 +921,9 @@ view_get_softline_count(ledit_view *view, size_t line) {
int
view_pos_to_softline(ledit_view *view, size_t line, size_t pos) {
- assert(line < view->lines_num);
+ ledit_assert(line < view->lines_num);
ledit_line *ll = buffer_get_line(view->buffer, line);
- assert(pos <= ll->len);
+ ledit_assert(pos <= ll->len);
PangoLayout *layout = get_pango_layout(view, line);
int x, sli;
if (pos > INT_MAX)
t@@ -934,9 +934,9 @@ view_pos_to_softline(ledit_view *view, size_t line, size_t…
void
view_get_cursor_pixel_pos(ledit_view *view, size_t line, size_t pos, int *x_re…
- assert(line < view->lines_num);
+ ledit_assert(line < view->lines_num);
ledit_line *ll = buffer_get_line(view->buffer, line);
- assert(pos <= ll->len);
+ ledit_assert(pos <= ll->len);
PangoLayout *layout = get_pango_layout(view, line);
PangoRectangle strong, weak;
if (pos > INT_MAX)
t@@ -1196,8 +1196,8 @@ view_delete_range_base(
size_t cur_byte = byte_index1;
view_sort_selection(&line_index1, &byte_index1, &line_index2, &byte_in…
size_t new_line = 0, new_byte = 0;
- assert(line_index1 < view->lines_num);
- assert(line_index2 < view->lines_num);
+ ledit_assert(line_index1 < view->lines_num);
+ ledit_assert(line_index2 < view->lines_num);
ledit_range cur_range = {0, 0, 0, 0};
/* FIXME: could this be simplified by just calculating the range and t…
the non-line-based version? */
t@@ -1295,7 +1295,7 @@ view_delete_range_base(
rgl1, rgb1, rgl2, rgb2, text_ret
);
} else {
- assert(pl2->start_index + pl2->length >= pl1->…
+ ledit_assert(pl2->start_index + pl2->length >=…
rgl1 = rgl2 = line_index1;
rgb1 = (size_t)pl1->start_index;
rgb2 = (size_t)(pl2->start_index + pl2->length…
diff --git a/window.c b/window.c
t@@ -2,7 +2,6 @@
#include <time.h>
#include <math.h>
#include <stdio.h>
-#include <assert.h>
#include <stdlib.h>
#include <X11/Xlib.h>
t@@ -21,6 +20,7 @@
#include "util.h"
#include "macros.h"
#include "config.h"
+#include "assert.h"
/* FIXME: Everything to do with the bottom bar is extremely hacky */
struct bottom_bar {
t@@ -103,8 +103,8 @@ recalc_text_size(ledit_window *window) {
/* FIXME: allow lines longer than window width to be displayed properly */
void
window_insert_bottom_bar_text(ledit_window *window, char *text, int len) {
- assert(len >= -1);
- assert(window->bb->line_cur_pos <= window->bb->line_len);
+ ledit_assert(len >= -1);
+ ledit_assert(window->bb->line_cur_pos <= window->bb->line_len);
if (len == -1)
len = strlen(text);
t@@ -136,7 +136,7 @@ window_insert_bottom_bar_text(ledit_window *window, char *…
void
window_move_bottom_bar_cursor(ledit_window *window, int movement) {
- assert(window->bb->line_cur_pos <= window->bb->line_len);
+ ledit_assert(window->bb->line_cur_pos <= window->bb->line_len);
int trailing = 0;
int new_index = window->bb->line_cur_pos;
pango_layout_move_cursor_visually(
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.