Fixing ke

Back in February of 2020, I started writing my own text editor ke. It seemed to work on my mac, but would always crash on Linux. While I never figured out what the bug was, I kept using it on Darwin.

Well, Wally and I got to talking Thursday, pining for the good old days (Dissolved Girl, some vim and terminal windows and man pages and C code and IRC and MDCR and ...). Well, after the absolute dumpster fire work has been, I got a hair up my ass to throw on some Massive Attack (the trip-hop playlist in general) and fix it.

The patch (eliding a function move)?

diff --git a/main.c b/main.c
 index 67acb57..ba0b6e5 100644
 --- a/main.c
 +++ b/main.c
 @@ -152,7 +152,70 @@ struct editor_t {
     int              dirtyex;
     char             msg[80];
     time_t           msgtm;
 -} editor;
 +} editor = {
 +   .cols = 0,
 +   .rows = 0,
 +   .curx = 0,
 +   .cury = 0,
 +   .mode = 0,
 +   .nrows = 0,
 +   .rowoffs = 0,
 +   .coloffs = 0,
 +   .row = NULL,
 +   .filename = NULL,
 +   .dirty = 0,
 +   .dirtyex = 0,
 +};
 +
 +
 +/*
 + * reset_editor presumes that editor has been initialized.
 + */
 +void
 +reset_editor(void)
 +{
 +   for (int i = 0; i < editor.nrows; i++) {
 +           erow_free(&editor.row[i]);
 +   }
 +   free(editor.row);
 +
 +   if (editor.filename != NULL) {
 +           free(editor.filename);
 +           editor.filename = NULL;
 +   }
 +
 +   init_editor();
 +}


  void
 @@ -503,6 +566,8 @@ open_file(const char *filename)
     editor.filename = strdup(filename);
     assert(editor.filename != NULL);

 +   reset_editor();
 +
     editor.dirty = 0;
     if ((fp = fopen(filename, "r")) == NULL) {
             if (errno == ENOENT) {
 @@ -1408,35 +1473,6 @@ loop(void)
  }


  int
  main(int argc, char *argv[])
  {

Two main things here:

  1. On initialization (and program start) the editor should be initialized. The struct value setting is probably unnecessary given =init_editor=, but sanity checks never killed anyone.
  2. On loading a file, make sure to clear out all the data appropriately.

This fixed the main double-free killer; I found this by using ASan. It also pointed out some other areas I was leaking memory and I cleaned all that up.

I also got =forward-word=, =backward-word=, =kill-word=, and =kill-backward-word= (or, =find_next_word=, =find_prev_word=, =delete_next_word=, and =delete_prev_word=) working.

Next up: yanking.

I ended up putting both cert (the tool from the previous post) and =ke= on Homebrew:

brew tap kisom/homebrew-tap
brew install cert ke

Should make it easier to keep them up to date on the work machine.


Tags: ,