summaryrefslogtreecommitdiff
path: root/src/dged
diff options
context:
space:
mode:
Diffstat (limited to 'src/dged')
-rw-r--r--src/dged/binding.c7
-rw-r--r--src/dged/binding.h14
-rw-r--r--src/dged/buffer.c56
-rw-r--r--src/dged/buffer.h14
-rw-r--r--src/dged/buffer_view.c5
-rw-r--r--src/dged/command.c2
-rw-r--r--src/dged/display.c60
-rw-r--r--src/dged/display.h2
-rw-r--r--src/dged/hash.c20
-rw-r--r--src/dged/hash.h14
-rw-r--r--src/dged/hashmap.h8
-rw-r--r--src/dged/json.c234
-rw-r--r--src/dged/json.h54
-rw-r--r--src/dged/lang.c34
-rw-r--r--src/dged/lsp.c163
-rw-r--r--src/dged/lsp.h75
-rw-r--r--src/dged/minibuffer.c24
-rw-r--r--src/dged/minibuffer.h20
-rw-r--r--src/dged/path.c68
-rw-r--r--src/dged/path.h69
-rw-r--r--src/dged/process-posix.c126
-rw-r--r--src/dged/process.h35
-rw-r--r--src/dged/reactor-epoll.c12
-rw-r--r--src/dged/reactor-kqueue.c2
-rw-r--r--src/dged/reactor.h2
-rw-r--r--src/dged/settings.c22
-rw-r--r--src/dged/settings.h6
-rw-r--r--src/dged/syntax.c27
-rw-r--r--src/dged/syntax.h2
-rw-r--r--src/dged/text.h4
-rw-r--r--src/dged/timers.c8
-rw-r--r--src/dged/timers.h8
-rw-r--r--src/dged/undo.c30
-rw-r--r--src/dged/undo.h6
-rw-r--r--src/dged/utf8.c3
-rw-r--r--src/dged/vec.h3
-rw-r--r--src/dged/window.c18
-rw-r--r--src/dged/window.h16
38 files changed, 997 insertions, 276 deletions
diff --git a/src/dged/binding.c b/src/dged/binding.c
index 5111548..636e694 100644
--- a/src/dged/binding.c
+++ b/src/dged/binding.c
@@ -50,21 +50,22 @@ struct lookup_result lookup_key(struct keymap *keymaps, uint32_t nkeymaps,
return (struct lookup_result){
.found = true,
.type = BindingType_Command,
- .command = lookup_command_by_hash(commands, binding->command),
+ .data.command =
+ lookup_command_by_hash(commands, binding->data.command),
};
}
case BindingType_Keymap: {
return (struct lookup_result){
.found = true,
.type = BindingType_Keymap,
- .keymap = binding->keymap,
+ .data.keymap = binding->data.keymap,
};
}
case BindingType_DirectCommand:
return (struct lookup_result){
.found = true,
.type = BindingType_Command,
- .command = binding->direct_command,
+ .data.command = binding->data.direct_command,
};
}
}
diff --git a/src/dged/binding.h b/src/dged/binding.h
index 79f8c47..93de02d 100644
--- a/src/dged/binding.h
+++ b/src/dged/binding.h
@@ -37,19 +37,19 @@ enum binding_type {
#define BINDING_INNER(mod_, c_, command_) \
(struct binding) { \
.key = {.mod = mod_, .key = c_}, .type = BindingType_Command, \
- .command = hash_name(command_) \
+ .data.command = hash_name(command_) \
}
#define ANONYMOUS_BINDING_INNER(mod_, c_, command_) \
(struct binding) { \
.key = {.mod = mod_, .key = c_}, .type = BindingType_DirectCommand, \
- .direct_command = command_ \
+ .data.direct_command = command_ \
}
#define PREFIX_INNER(mod_, c_, keymap_) \
(struct binding) { \
.key = {.mod = mod_, .key = c_}, .type = BindingType_Keymap, \
- .keymap = keymap_ \
+ .data.keymap = keymap_ \
}
/**
@@ -89,14 +89,14 @@ struct binding {
/** Type of this binding, see @ref binding_type */
uint8_t type;
- union {
+ union binding_data {
/** A hash of a command name */
uint32_t command;
/** A command */
struct command *direct_command;
/** A keymap */
struct keymap *keymap;
- };
+ } data;
};
/**
@@ -109,12 +109,12 @@ struct lookup_result {
/** Type of binding in the result */
uint8_t type;
- union {
+ union lookup_data {
/** A command */
struct command *command;
/** A keymap */
struct keymap *keymap;
- };
+ } data;
};
struct commands;
diff --git a/src/dged/buffer.c b/src/dged/buffer.c
index 1062a47..c537fb3 100644
--- a/src/dged/buffer.c
+++ b/src/dged/buffer.c
@@ -31,7 +31,7 @@ static struct kill_ring {
uint32_t curr_idx;
uint32_t paste_idx;
} g_kill_ring = {.curr_idx = 0,
- .buffer = {0},
+ .buffer = {{0}},
.last_paste = {0},
.paste_idx = 0,
.paste_up_to_date = false};
@@ -58,7 +58,7 @@ static struct kill_ring {
\
static void remove_##name##_hook(vec_type *hooks, uint32_t id, \
remove_hook_cb callback) { \
- uint64_t found_at = -1; \
+ uint64_t found_at = (uint64_t)-1; \
VEC_FOR_EACH_INDEXED(hooks, struct name##_hook *h, idx) { \
if (h->id == id) { \
if (callback != NULL) { \
@@ -68,11 +68,12 @@ static struct kill_ring {
break; \
} \
} \
- if (found_at != -1) { \
+ if (found_at != (uint64_t)-1) { \
if (found_at < VEC_SIZE(hooks) - 1) { \
VEC_SWAP(hooks, found_at, VEC_SIZE(hooks) - 1); \
} \
VEC_POP(hooks, struct name##_hook removed); \
+ (void)removed; \
} \
}
@@ -84,13 +85,13 @@ typedef VEC(struct reload_hook) reload_hook_vec;
typedef VEC(struct delete_hook) delete_hook_vec;
typedef VEC(struct render_hook) render_hook_vec;
-DECLARE_HOOK(create, create_hook_cb, create_hook_vec);
-DECLARE_HOOK(destroy, destroy_hook_cb, destroy_hook_vec);
-DECLARE_HOOK(insert, insert_hook_cb, insert_hook_vec);
-DECLARE_HOOK(update, update_hook_cb, update_hook_vec);
-DECLARE_HOOK(reload, reload_hook_cb, reload_hook_vec);
-DECLARE_HOOK(render, render_hook_cb, render_hook_vec);
-DECLARE_HOOK(delete, delete_hook_cb, delete_hook_vec);
+DECLARE_HOOK(create, create_hook_cb, create_hook_vec)
+DECLARE_HOOK(destroy, destroy_hook_cb, destroy_hook_vec)
+DECLARE_HOOK(insert, insert_hook_cb, insert_hook_vec)
+DECLARE_HOOK(update, update_hook_cb, update_hook_vec)
+DECLARE_HOOK(reload, reload_hook_cb, reload_hook_vec)
+DECLARE_HOOK(render, render_hook_cb, render_hook_vec)
+DECLARE_HOOK(delete, delete_hook_cb, delete_hook_vec)
static create_hook_vec g_create_hooks;
uint32_t g_create_hook_id;
@@ -136,19 +137,19 @@ void buffer_remove_destroy_hook(struct buffer *buffer, uint32_t hook_id,
remove_destroy_hook(&buffer->hooks->destroy_hooks, hook_id, callback);
}
-void buffer_static_init() {
+void buffer_static_init(void) {
VEC_INIT(&g_create_hooks, 8);
settings_set_default(
"editor.tab-width",
- (struct setting_value){.type = Setting_Number, .number_value = 4});
+ (struct setting_value){.type = Setting_Number, .data.number_value = 4});
settings_set_default(
"editor.show-whitespace",
- (struct setting_value){.type = Setting_Bool, .bool_value = true});
+ (struct setting_value){.type = Setting_Bool, .data.bool_value = true});
}
-void buffer_static_teardown() {
+void buffer_static_teardown(void) {
VEC_DESTROY(&g_create_hooks);
for (uint32_t i = 0; i < KILL_RING_SZ; ++i) {
if (g_kill_ring.buffer[i].allocated) {
@@ -165,7 +166,7 @@ static uint32_t get_tab_width(struct buffer *buffer) {
uint32_t tab_width = 4;
if (tw != NULL && tw->value.type == Setting_Number) {
- tab_width = tw->value.number_value;
+ tab_width = tw->value.data.number_value;
}
return tab_width;
}
@@ -178,7 +179,7 @@ static bool use_tabs(struct buffer *buffer) {
bool use_tabs = false;
if (ut != NULL && ut->value.type == Setting_Bool) {
- use_tabs = ut->value.bool_value;
+ use_tabs = ut->value.data.bool_value;
}
return use_tabs;
@@ -664,14 +665,14 @@ struct location buffer_previous_word(struct buffer *buffer,
struct location buffer_previous_line(struct buffer *buffer,
struct location dot) {
- if (dot.line == 0) {
+ (void)buffer;
+
+ if (dot.line <= 0) {
+ dot.line = 0;
return dot;
}
--dot.line;
- uint32_t nchars = buffer_line_length(buffer, dot.line);
- uint32_t new_col = dot.col > nchars ? nchars : dot.col;
-
return dot;
}
@@ -842,7 +843,7 @@ struct location buffer_undo(struct buffer *buffer, struct location dot) {
switch (rec->type) {
case Undo_Boundary: {
- struct undo_boundary *b = &rec->boundary;
+ struct undo_boundary *b = &rec->data.boundary;
if (b->save_point) {
buffer->modified = false;
}
@@ -850,7 +851,7 @@ struct location buffer_undo(struct buffer *buffer, struct location dot) {
}
case Undo_Add: {
- struct undo_add *add = &rec->add;
+ struct undo_add *add = &rec->data.add;
pos = buffer_delete(buffer,
(struct region){
@@ -864,7 +865,7 @@ struct location buffer_undo(struct buffer *buffer, struct location dot) {
}
case Undo_Delete: {
- struct undo_delete *del = &rec->delete;
+ struct undo_delete *del = &rec->data.delete;
pos = buffer_add(buffer,
(struct location){
.line = del->pos.row,
@@ -934,7 +935,7 @@ void buffer_find(struct buffer *buffer, const char *pattern,
struct location buffer_copy(struct buffer *buffer, struct region region) {
if (region_has_size(region)) {
- struct text_chunk *curr = copy_region(buffer, region);
+ copy_region(buffer, region);
}
return region.begin;
@@ -1024,7 +1025,6 @@ struct location buffer_paste_older(struct buffer *buffer, struct location at) {
if (g_kill_ring.paste_up_to_date) {
// remove previous paste
- struct text_chunk *curr = &g_kill_ring.buffer[g_kill_ring.curr_idx];
buffer_delete(buffer, region_new(g_kill_ring.last_paste, at));
// paste older
@@ -1124,7 +1124,7 @@ static void apply_properties(struct command_list *cmds,
switch (prop->type) {
case TextProperty_Colors: {
- struct text_property_colors *colors = &prop->colors;
+ struct text_property_colors *colors = &prop->data.colors;
if (colors->set_bg) {
command_list_set_index_color_bg(cmds, colors->bg);
}
@@ -1221,7 +1221,7 @@ void render_line(struct text_chunk *line, void *userdata) {
}
}
-void buffer_update(struct buffer *buffer, struct buffer_update_params *params) {
+void buffer_update(struct buffer *buffer) {
VEC_FOR_EACH(&buffer->hooks->update_hooks, struct update_hook * h) {
h->callback(buffer, h->userdata);
}
@@ -1244,7 +1244,7 @@ void buffer_render(struct buffer *buffer, struct buffer_render_params *params) {
.origin = params->origin,
.width = params->width,
.height = params->height,
- .show_ws = (show_ws != NULL ? show_ws->value.bool_value : true) &&
+ .show_ws = (show_ws != NULL ? show_ws->value.data.bool_value : true) &&
!buffer->force_show_ws_off,
.buffer = buffer,
};
diff --git a/src/dged/buffer.h b/src/dged/buffer.h
index c9fe2ca..0e45b98 100644
--- a/src/dged/buffer.h
+++ b/src/dged/buffer.h
@@ -65,8 +65,8 @@ struct buffer {
bool force_show_ws_off;
};
-void buffer_static_init();
-void buffer_static_teardown();
+void buffer_static_init(void);
+void buffer_static_teardown(void);
/**
* Create a new buffer.
@@ -690,11 +690,6 @@ uint32_t buffer_add_create_hook(create_hook_cb callback, void *userdata);
void buffer_remove_create_hook(uint32_t hook_id, remove_hook_cb callback);
/**
- * Parameters for updating a buffer.
- */
-struct buffer_update_params {};
-
-/**
* Parameters for rendering a buffer.
*/
struct buffer_render_params {
@@ -716,11 +711,8 @@ struct buffer_render_params {
* Update a buffer.
*
* @param [in] buffer The buffer to update.
- * @param [inout] params The parameters for the update. The @ref commands field
- * in @p params will be modified with the rendering commands needed for this
- * buffer.
*/
-void buffer_update(struct buffer *buffer, struct buffer_update_params *params);
+void buffer_update(struct buffer *buffer);
/**
* Render a buffer.
diff --git a/src/dged/buffer_view.c b/src/dged/buffer_view.c
index f3dd2b9..0c587a6 100644
--- a/src/dged/buffer_view.c
+++ b/src/dged/buffer_view.c
@@ -386,8 +386,7 @@ void buffer_view_update(struct buffer_view *view,
struct timer *buffer_update_timer =
timer_start("update-windows.buffer-update");
- struct buffer_update_params update_params = {};
- buffer_update(view->buffer, &update_params);
+ buffer_update(view->buffer);
timer_stop(buffer_update_timer);
uint32_t height = params->height;
@@ -446,7 +445,7 @@ void buffer_view_update(struct buffer_view *view,
buffer_add_text_property(view->buffer, reg.begin, reg.end,
(struct text_property){
.type = TextProperty_Colors,
- .colors =
+ .data.colors =
(struct text_property_colors){
.set_bg = true,
.bg = 5,
diff --git a/src/dged/command.c b/src/dged/command.c
index 2775286..5f2551f 100644
--- a/src/dged/command.c
+++ b/src/dged/command.c
@@ -79,7 +79,7 @@ void command_ctx_push_arg(struct command_ctx *ctx, const char *argv) {
}
void command_ctx_free(struct command_ctx *ctx) {
- for (uint32_t i = 0; i < ctx->saved_argc; ++i) {
+ for (uint32_t i = 0; i < (uint32_t)ctx->saved_argc; ++i) {
free((char *)ctx->saved_argv[i]);
}
diff --git a/src/dged/display.c b/src/dged/display.c
index ea3f459..0c3c47c 100644
--- a/src/dged/display.c
+++ b/src/dged/display.c
@@ -35,13 +35,13 @@ enum render_cmd_type {
struct render_command {
enum render_cmd_type type;
- union {
+ union render_cmd_data {
struct draw_text_cmd *draw_txt;
struct push_fmt_cmd *push_fmt;
struct repeat_cmd *repeat;
struct show_ws_cmd *show_ws;
struct draw_list_cmd *draw_list;
- };
+ } data;
};
struct draw_text_cmd {
@@ -87,13 +87,13 @@ struct command_list {
struct command_list *next_list;
};
-struct winsize getsize() {
+struct winsize getsize(void) {
struct winsize ws;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
return ws;
}
-struct display *display_create() {
+struct display *display_create(void) {
struct winsize ws = getsize();
@@ -182,6 +182,8 @@ void put_ansiparm(int n) {
}
void display_move_cursor(struct display *display, uint32_t row, uint32_t col) {
+ (void)display;
+
putc(ESC, stdout);
putc('[', stdout);
put_ansiparm(row + 1);
@@ -192,7 +194,6 @@ void display_move_cursor(struct display *display, uint32_t row, uint32_t col) {
void display_clear(struct display *display) {
display_move_cursor(display, 0, 0);
- uint8_t bytes[] = {ESC, '[', 'J'};
putc(ESC, stdout);
putc('[', stdout);
putc('J', stdout);
@@ -239,21 +240,21 @@ struct render_command *add_command(struct command_list *list,
cmd->type = tp;
switch (tp) {
case RenderCommand_DrawText:
- cmd->draw_txt = l->allocator(sizeof(struct draw_text_cmd));
+ cmd->data.draw_txt = l->allocator(sizeof(struct draw_text_cmd));
break;
case RenderCommand_Repeat:
- cmd->repeat = l->allocator(sizeof(struct repeat_cmd));
+ cmd->data.repeat = l->allocator(sizeof(struct repeat_cmd));
break;
case RenderCommand_PushFormat:
- cmd->push_fmt = l->allocator(sizeof(struct push_fmt_cmd));
+ cmd->data.push_fmt = l->allocator(sizeof(struct push_fmt_cmd));
break;
case RenderCommand_SetShowWhitespace:
- cmd->show_ws = l->allocator(sizeof(struct show_ws_cmd));
+ cmd->data.show_ws = l->allocator(sizeof(struct show_ws_cmd));
break;
case RenderCommand_ClearFormat:
break;
case RenderCommand_DrawList:
- cmd->draw_list = l->allocator(sizeof(struct draw_list_cmd));
+ cmd->data.draw_list = l->allocator(sizeof(struct draw_list_cmd));
break;
default:
assert(false);
@@ -266,7 +267,7 @@ struct render_command *add_command(struct command_list *list,
void command_list_draw_text(struct command_list *list, uint32_t col,
uint32_t row, uint8_t *data, uint32_t len) {
struct draw_text_cmd *cmd =
- add_command(list, RenderCommand_DrawText)->draw_txt;
+ add_command(list, RenderCommand_DrawText)->data.draw_txt;
cmd->data = data;
cmd->col = col;
cmd->row = row;
@@ -283,7 +284,7 @@ void command_list_draw_text_copy(struct command_list *list, uint32_t col,
void command_list_draw_repeated(struct command_list *list, uint32_t col,
uint32_t row, uint32_t c, uint32_t nrepeat) {
- struct repeat_cmd *cmd = add_command(list, RenderCommand_Repeat)->repeat;
+ struct repeat_cmd *cmd = add_command(list, RenderCommand_Repeat)->data.repeat;
cmd->col = col;
cmd->row = row;
cmd->c = c;
@@ -293,14 +294,14 @@ void command_list_draw_repeated(struct command_list *list, uint32_t col,
void command_list_draw_command_list(struct command_list *list,
struct command_list *to_draw) {
struct draw_list_cmd *cmd =
- add_command(list, RenderCommand_DrawList)->draw_list;
+ add_command(list, RenderCommand_DrawList)->data.draw_list;
cmd->list = to_draw;
}
void command_list_set_index_color_fg(struct command_list *list,
uint8_t color_idx) {
struct push_fmt_cmd *cmd =
- add_command(list, RenderCommand_PushFormat)->push_fmt;
+ add_command(list, RenderCommand_PushFormat)->data.push_fmt;
if (color_idx < 8) {
cmd->len = snprintf((char *)cmd->fmt, 64, "%d", 30 + color_idx);
@@ -314,14 +315,14 @@ void command_list_set_index_color_fg(struct command_list *list,
void command_list_set_color_fg(struct command_list *list, uint8_t red,
uint8_t green, uint8_t blue) {
struct push_fmt_cmd *cmd =
- add_command(list, RenderCommand_PushFormat)->push_fmt;
+ add_command(list, RenderCommand_PushFormat)->data.push_fmt;
cmd->len = snprintf((char *)cmd->fmt, 64, "38;2;%d;%d;%d", red, green, blue);
}
void command_list_set_index_color_bg(struct command_list *list,
uint8_t color_idx) {
struct push_fmt_cmd *cmd =
- add_command(list, RenderCommand_PushFormat)->push_fmt;
+ add_command(list, RenderCommand_PushFormat)->data.push_fmt;
if (color_idx < 8) {
cmd->len = snprintf((char *)cmd->fmt, 64, "%d", 40 + color_idx);
} else if (color_idx < 16) {
@@ -334,13 +335,13 @@ void command_list_set_index_color_bg(struct command_list *list,
void command_list_set_color_bg(struct command_list *list, uint8_t red,
uint8_t green, uint8_t blue) {
struct push_fmt_cmd *cmd =
- add_command(list, RenderCommand_PushFormat)->push_fmt;
+ add_command(list, RenderCommand_PushFormat)->data.push_fmt;
cmd->len = snprintf((char *)cmd->fmt, 64, "48;2;%d;%d;%d", red, green, blue);
}
void command_list_set_inverted_colors(struct command_list *list) {
struct push_fmt_cmd *cmd =
- add_command(list, RenderCommand_PushFormat)->push_fmt;
+ add_command(list, RenderCommand_PushFormat)->data.push_fmt;
cmd->fmt[0] = '7';
cmd->len = 1;
}
@@ -350,7 +351,7 @@ void command_list_reset_color(struct command_list *list) {
}
void command_list_set_show_whitespace(struct command_list *list, bool show) {
- add_command(list, RenderCommand_SetShowWhitespace)->show_ws->show = show;
+ add_command(list, RenderCommand_SetShowWhitespace)->data.show_ws->show = show;
}
void display_render(struct display *display,
@@ -374,7 +375,7 @@ void display_render(struct display *display,
struct render_command *cmd = &cl->cmds[cmdi];
switch (cmd->type) {
case RenderCommand_DrawText: {
- struct draw_text_cmd *txt_cmd = cmd->draw_txt;
+ struct draw_text_cmd *txt_cmd = cmd->data.draw_txt;
display_move_cursor(display, txt_cmd->row + cl->yoffset,
txt_cmd->col + cl->xoffset);
apply_fmt(fmt_stack, fmt_stack_len);
@@ -384,7 +385,7 @@ void display_render(struct display *display,
}
case RenderCommand_Repeat: {
- struct repeat_cmd *repeat_cmd = cmd->repeat;
+ struct repeat_cmd *repeat_cmd = cmd->data.repeat;
display_move_cursor(display, repeat_cmd->row + cl->yoffset,
repeat_cmd->col + cl->xoffset);
apply_fmt(fmt_stack, fmt_stack_len);
@@ -401,7 +402,7 @@ void display_render(struct display *display,
}
case RenderCommand_PushFormat: {
- struct push_fmt_cmd *fmt_cmd = cmd->push_fmt;
+ struct push_fmt_cmd *fmt_cmd = cmd->data.push_fmt;
fmt_stack[fmt_stack_len] = ';';
++fmt_stack_len;
@@ -416,11 +417,11 @@ void display_render(struct display *display,
break;
case RenderCommand_SetShowWhitespace:
- show_whitespace_state = cmd->show_ws->show;
+ show_whitespace_state = cmd->data.show_ws->show;
break;
case RenderCommand_DrawList:
- display_render(display, cmd->draw_list->list);
+ display_render(display, cmd->data.draw_list->list);
break;
}
}
@@ -430,7 +431,7 @@ void display_render(struct display *display,
timer_stop(render_timer);
}
-void hide_cursor() {
+void hide_cursor(void) {
putc(ESC, stdout);
putc('[', stdout);
putc('?', stdout);
@@ -439,7 +440,7 @@ void hide_cursor() {
putc('l', stdout);
}
-void show_cursor() {
+void show_cursor(void) {
putc(ESC, stdout);
putc('[', stdout);
putc('?', stdout);
@@ -448,8 +449,13 @@ void show_cursor() {
putc('h', stdout);
}
-void display_begin_render(struct display *display) { hide_cursor(); }
+void display_begin_render(struct display *display) {
+ (void)display;
+ hide_cursor();
+}
void display_end_render(struct display *display) {
+ (void)display;
+
show_cursor();
fflush(stdout);
}
diff --git a/src/dged/display.h b/src/dged/display.h
index f9c7ef8..950ab3c 100644
--- a/src/dged/display.h
+++ b/src/dged/display.h
@@ -13,7 +13,7 @@ struct command_list;
* The only implementation of this is currently a termios one.
* @returns A pointer to the display.
*/
-struct display *display_create();
+struct display *display_create(void);
/**
* Resize the display
diff --git a/src/dged/hash.c b/src/dged/hash.c
new file mode 100644
index 0000000..fce61af
--- /dev/null
+++ b/src/dged/hash.c
@@ -0,0 +1,20 @@
+#include "hash.h"
+
+uint32_t hash_name(const char *s) {
+ unsigned long hash = 5381;
+ int c;
+
+ while ((c = *s++))
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+
+ return hash;
+}
+
+uint32_t hash_name_s8(struct s8 s) {
+ unsigned long hash = 5381;
+
+ for (uint64_t i = 0; i < s.l; ++i)
+ hash = ((hash << 5) + hash) + s.s[i]; /* hash * 33 + c */
+
+ return hash;
+}
diff --git a/src/dged/hash.h b/src/dged/hash.h
index 0fd689b..60b6d6a 100644
--- a/src/dged/hash.h
+++ b/src/dged/hash.h
@@ -1,11 +1,11 @@
+#ifndef _HASH_H
+#define _HASH_H
+
#include <stdint.h>
-static uint32_t hash_name(const char *s) {
- unsigned long hash = 5381;
- int c;
+#include "s8.h"
- while ((c = *s++))
- hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+uint32_t hash_name(const char *s);
+uint32_t hash_name_s8(struct s8 s);
- return hash;
-}
+#endif
diff --git a/src/dged/hashmap.h b/src/dged/hashmap.h
index 405c193..b8475c7 100644
--- a/src/dged/hashmap.h
+++ b/src/dged/hashmap.h
@@ -66,16 +66,16 @@
} \
var = res != NULL ? &(res->value) : NULL;
-#define HASHMAP_CONTAINS_KEY(map, key) \
- uint32_t needle = (map)->hash_fn(key); \
+#define HASHMAP_CONTAINS_KEY(map, type, k, var) \
+ uint32_t needle = (map)->hash_fn(k); \
bool exists = false; \
- VEC_FOR_EACH((map)->entries, struct pair *pair) { \
+ VEC_FOR_EACH(&(map)->entries, type *pair) { \
if (needle == pair->key) { \
exists = true; \
break; \
} \
} \
- exists
+ var = exists;
#define HASHMAP_FOR_EACH(map, var) VEC_FOR_EACH_INDEXED(&(map)->entries, var, i)
diff --git a/src/dged/json.c b/src/dged/json.c
new file mode 100644
index 0000000..24d5c15
--- /dev/null
+++ b/src/dged/json.c
@@ -0,0 +1,234 @@
+#include "json.h"
+
+#include "hash.h"
+#include "hashmap.h"
+#include "utf8.h"
+#include "vec.h"
+
+#include <stddef.h>
+#include <stdio.h>
+
+HASHMAP_ENTRY_TYPE(json_object_member, struct json_value);
+
+struct json_object {
+ HASHMAP(struct json_object_member) members;
+};
+
+struct json_array {
+ VEC(struct json_value) values;
+};
+
+static void setarray(struct json_value *val) {
+ val->type = Json_Array;
+ val->value.array = calloc(1, sizeof(struct json_array));
+ VEC_INIT(&val->value.array->values, 10);
+}
+
+static void setobject(struct json_value *val) {
+ val->type = Json_Object;
+ val->value.object = calloc(1, sizeof(struct json_object));
+ HASHMAP_INIT(&val->value.object->members, 10, hash_name);
+}
+
+static void setstring(struct json_value *val, uint8_t *current) {
+ val->type = Json_String;
+ val->value.string.s = current;
+ val->value.string.l = 0;
+}
+
+static bool is_number(uint8_t byte) { return byte >= '0' && byte <= '9'; }
+
+enum object_parse_state {
+ ObjectParseState_Key,
+ ObjectParseState_Value,
+};
+
+struct json_result json_parse(uint8_t *buf, uint64_t size) {
+ struct json_result res = {
+ .ok = true,
+ .result.document.type = Json_Null,
+ };
+
+ struct json_value *parent = NULL;
+ struct json_value *current = &res.result.document;
+ struct json_value tmp_key = {0};
+ struct json_value tmp_val = {0};
+ uint32_t line = 1, col = 0;
+
+ enum object_parse_state obj_parse_state = ObjectParseState_Key;
+ for (uint64_t bufi = 0; bufi < size; ++bufi) {
+ uint8_t byte = buf[bufi];
+
+ // handle appends to the current scope
+ if (current->type == Json_Array) {
+ VEC_PUSH(&current->value.array->values, tmp_val);
+ parent = current;
+
+ // start looking for next value
+ tmp_val.type = Json_Null;
+ current = &tmp_val;
+ } else if (current->type == Json_Object &&
+ obj_parse_state == ObjectParseState_Key) {
+ // key is in tmp_key, start looking for value
+ obj_parse_state = ObjectParseState_Value;
+ parent = current;
+
+ tmp_val.type = Json_Null;
+ current = &tmp_val;
+ } else if (current->type == Json_Object &&
+ obj_parse_state == ObjectParseState_Value) {
+ // value is in tmp_val
+ // TODO: remove this alloc, should not be needed
+ char *k = s8tocstr(tmp_key.value.string);
+ uint32_t hash = 0;
+ HASHMAP_INSERT(&current->value.object->members, struct json_object_member,
+ k, tmp_val, hash);
+ (void)hash;
+ free(k);
+
+ // start looking for next key
+ obj_parse_state = ObjectParseState_Key;
+ parent = current;
+
+ tmp_key.type = Json_Null;
+ current = &tmp_key;
+ }
+
+ switch (byte) {
+ case '[':
+ setarray(current);
+ parent = current;
+
+ tmp_val.type = Json_Null;
+ current = &tmp_val;
+ break;
+ case ']':
+ current = parent;
+ break;
+ case '{':
+ setobject(current);
+ obj_parse_state = ObjectParseState_Key;
+ parent = current;
+
+ tmp_key.type = Json_Null;
+ current = &tmp_key;
+ break;
+ case '}':
+ current = parent;
+ break;
+ case '"':
+ if (current->type == Json_String) {
+ // finish off the string
+ current->value.string.l = (buf + bufi) - current->value.string.s;
+ current = parent;
+ } else {
+ setstring(current, buf + bufi + 1 /* skip " */);
+ }
+ break;
+ case '\n':
+ ++line;
+ col = 0;
+ break;
+ default:
+ if (current->type == Json_String) {
+ // append to string
+ } else if (current->type == Json_Number &&
+ !(is_number(byte) || byte == '-' || byte == '.')) {
+ // end of number
+ current->value.string.l = (buf + bufi) - current->value.string.s;
+ char *nmbr = s8tocstr(current->value.string);
+ current->value.number = atof(nmbr);
+ free(nmbr);
+
+ current = parent;
+
+ } else if (current->type == Json_Null &&
+ (is_number(byte) || byte == '-' || byte == '.')) {
+ // borrow string storage in the value for storing number
+ // as a string
+ setstring(current, buf + bufi);
+ current->type = Json_Number;
+ } else if (byte == 't') {
+ current->type = Json_Bool;
+ current->value.boolean = true;
+
+ current = parent;
+ } else if (byte == 'f') {
+ current->type = Json_Bool;
+ current->value.boolean = false;
+
+ current = parent;
+ } else if (byte == 'n') {
+ current->type = Json_Null;
+
+ current = parent;
+ }
+ break;
+ }
+
+ // TODO: not entirely correct
+ ++col;
+ }
+ return res;
+}
+
+void json_destroy(struct json_value *value) {
+ switch (value->type) {
+ case Json_Array:
+ struct json_array *arr = value->value.array;
+ VEC_FOR_EACH(&arr->values, struct json_value * val) { json_destroy(val); }
+ VEC_DESTROY(&arr->values);
+ break;
+ case Json_Object:
+ struct json_object *obj = value->value.object;
+ HASHMAP_FOR_EACH(&obj->members, struct json_object_member * memb) {
+ json_destroy(&memb->value);
+ }
+
+ HASHMAP_DESTROY(&obj->members);
+ case Json_Null:
+ case Json_Number:
+ case Json_String:
+ case Json_Bool:
+ break;
+ }
+}
+
+uint64_t json_array_len(struct json_array *arr) {
+ return VEC_SIZE(&arr->values);
+}
+
+struct json_value *json_array_get(struct json_array *arr, uint64_t idx) {
+ struct json_value *ret = NULL;
+
+ if (idx <= VEC_SIZE(&arr->values)) {
+ ret = &VEC_ENTRIES(&arr->values)[idx];
+ }
+
+ return ret;
+}
+
+uint64_t json_len(struct json_object *obj) {
+ return HASHMAP_SIZE(&obj->members);
+}
+
+bool json_contains(struct json_object *obj, struct s8 key) {
+ // TODO: get rid of alloc
+ char *k = s8tocstr(key);
+ HASHMAP_CONTAINS_KEY(&obj->members, struct json_object_member, k, bool res);
+
+ free(k);
+
+ return res;
+}
+
+struct json_value *json_get(struct json_object *obj, struct s8 key) {
+ // TODO: get rid of alloc
+ char *k = s8tocstr(key);
+ HASHMAP_GET(&obj->members, struct json_object_member, k,
+ struct json_value * result);
+
+ free(k);
+
+ return result;
+}
diff --git a/src/dged/json.h b/src/dged/json.h
new file mode 100644
index 0000000..c0428b9
--- /dev/null
+++ b/src/dged/json.h
@@ -0,0 +1,54 @@
+#ifndef _JSON_H
+#define _JSON_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "s8.h"
+
+enum json_type {
+ Json_Array,
+ Json_Object,
+ Json_Null,
+ Json_Number,
+ Json_String,
+ Json_Bool,
+};
+
+struct json_value {
+ enum json_type type;
+ union {
+ struct s8 string;
+ struct json_object *object;
+ struct json_array *array;
+ double number;
+ bool boolean;
+ } value;
+};
+
+struct json_result {
+ bool ok;
+ union {
+ const char *error;
+ struct json_value document;
+ } result;
+};
+
+struct json_writer;
+
+struct json_result json_parse(uint8_t *buf, uint64_t size);
+void json_destroy(struct json_value *value);
+
+uint64_t json_len(struct json_object *obj);
+bool json_contains(struct json_object *obj, struct s8 key);
+struct json_value *json_get(struct json_object *obj, struct s8 key);
+
+uint64_t json_array_len(struct json_array *arr);
+void json_array_foreach(struct json_array *arr,
+ void (*cb)(uint64_t, struct json_value));
+struct json_value *json_array_get(struct json_array *arr, uint64_t idx);
+
+struct json_writer *json_writer_create();
+struct s8 json_writer_done(struct json_writer *writer);
+
+#endif
diff --git a/src/dged/lang.c b/src/dged/lang.c
index 070b96e..92b4fbd 100644
--- a/src/dged/lang.c
+++ b/src/dged/lang.c
@@ -19,17 +19,19 @@ void define_lang(const char *name, const char *id, const char *pattern,
_lang_setting_set_default(
id, "name",
(struct setting_value){.type = Setting_String,
- .string_value = (char *)name});
+ .data.string_value = (char *)name});
_lang_setting_set_default(
id, "pattern",
(struct setting_value){.type = Setting_String,
- .string_value = (char *)pattern});
- _lang_setting_set_default(id, "tab-width",
- (struct setting_value){.type = Setting_Number,
- .number_value = tab_width});
+ .data.string_value = (char *)pattern});
+ _lang_setting_set_default(
+ id, "tab-width",
+ (struct setting_value){.type = Setting_Number,
+ .data.number_value = tab_width});
_lang_setting_set_default(
id, "use-tabs",
- (struct setting_value){.type = Setting_Bool, .bool_value = use_tabs});
+ (struct setting_value){.type = Setting_Bool,
+ .data.bool_value = use_tabs});
}
static struct language g_fundamental = {
@@ -65,7 +67,8 @@ bool lang_is_fundamental(const struct language *lang) {
static struct language lang_from_settings(const char *id) {
struct setting *name = _lang_setting(id, "name");
- const char *name_value = name != NULL ? name->value.string_value : "Unknown";
+ const char *name_value =
+ name != NULL ? name->value.data.string_value : "Unknown";
return (struct language){
.id = strdup(id),
@@ -73,21 +76,6 @@ static struct language lang_from_settings(const char *id) {
};
}
-static void next_ext(const char *curr, const char **nxt, const char **end) {
- if (curr == NULL) {
- *nxt = *end = NULL;
- return;
- }
-
- *nxt = curr;
- *end = curr + strlen(curr);
-
- const char *spc = strchr(curr, ' ');
- if (spc != NULL) {
- *end = spc;
- }
-}
-
void lang_settings(struct language *lang, struct setting **settings[],
uint32_t *nsettings) {
const char *key = setting_join_key("languages", lang->id);
@@ -159,7 +147,7 @@ struct language lang_from_filename(const char *filename) {
struct setting *setting = settings[i];
char *setting_name = strrchr(setting->path, '.');
if (setting_name != NULL && strncmp(setting_name + 1, "pattern", 5) == 0) {
- const char *val = setting->value.string_value;
+ const char *val = setting->value.data.string_value;
regex_t regex;
if (regcomp(&regex, val, REG_EXTENDED) == 0 &&
regexec(&regex, filename, 0, NULL, 0) == 0) {
diff --git a/src/dged/lsp.c b/src/dged/lsp.c
new file mode 100644
index 0000000..3c699f4
--- /dev/null
+++ b/src/dged/lsp.c
@@ -0,0 +1,163 @@
+#include "lsp.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "buffer.h"
+#include "process.h"
+#include "reactor.h"
+
+struct lsp {
+ const char *name;
+ char *const *command;
+ struct process *process;
+ struct reactor *reactor;
+ struct buffer *stderr_buffer;
+ struct lsp_client client_impl;
+ uint32_t stdin_event;
+ uint32_t stdout_event;
+ uint32_t stderr_event;
+};
+
+struct lsp *lsp_create(char *const command[], struct reactor *reactor,
+ struct buffer *stderr_buffer,
+ struct lsp_client client_impl, const char *name) {
+ // check length of command
+ if (command == NULL) {
+ return NULL;
+ }
+
+ uint32_t command_len = 0;
+ while (command[command_len] != NULL) {
+ ++command_len;
+ }
+
+ if (command_len == 0) {
+ return NULL;
+ }
+
+ struct lsp *lsp = calloc(1, sizeof(struct lsp));
+
+ char **cmd = calloc(command_len + 1, sizeof(const char *));
+ memcpy(cmd, command, sizeof(const char *) * command_len);
+ cmd[command_len] = NULL;
+ lsp->command = cmd;
+
+ if (name != NULL) {
+ lsp->name = strdup(name);
+ } else {
+#ifdef __unix__
+ const char *lslash = strrchr(lsp->command[0], '/');
+#elif defined(_WIN32) || defined(WIN32)
+ const char *lslash = strrchr(lsp->command[0], '\\');
+#endif
+ if (lslash == NULL) {
+ lsp->name = strdup(lsp->command[0]);
+ } else {
+ lsp->name = strdup(lslash + 1);
+ }
+ }
+ lsp->stderr_buffer = stderr_buffer;
+ lsp->client_impl = client_impl;
+ lsp->reactor = reactor;
+ lsp->stdin_event = -1;
+ lsp->stdout_event = -1;
+ lsp->stderr_event = -1;
+
+ return lsp;
+}
+
+void lsp_destroy(struct lsp *lsp) {
+ free((void *)lsp->name);
+ if (lsp->process != NULL) {
+ free(lsp->process);
+ }
+ if (lsp->command != NULL) {
+ char *command = lsp->command[0];
+ while (command != NULL) {
+ free(command);
+ ++command;
+ }
+
+ free((void *)lsp->command);
+ }
+ free(lsp);
+}
+
+uint32_t lsp_update(struct lsp *lsp, struct lsp_response **responses,
+ uint32_t responses_capacity) {
+
+ (void)responses;
+ (void)responses_capacity;
+
+ if (!lsp_server_running(lsp)) {
+ return -1;
+ }
+
+ // read stderr
+ if (lsp->stderr_event != (uint32_t)-1) {
+ uint8_t buf[1024];
+ if (reactor_poll_event(lsp->reactor, lsp->stderr_event)) {
+ ssize_t nb = 0;
+ while ((nb = read(lsp->process->stderr, buf, 1024)) > 0) {
+ buffer_set_readonly(lsp->stderr_buffer, false);
+ buffer_add(lsp->stderr_buffer, buffer_end(lsp->stderr_buffer), buf, nb);
+ buffer_set_readonly(lsp->stderr_buffer, true);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int lsp_start_server(struct lsp *lsp) {
+ struct process p;
+ struct process_create_result res = process_create(lsp->command, &p);
+
+ if (!res.ok) {
+ // TODO: losing error message here
+ return -1;
+ }
+
+ lsp->process = calloc(1, sizeof(struct process));
+ memcpy(lsp->process, &p, sizeof(struct process));
+ lsp->stderr_event = reactor_register_interest(
+ lsp->reactor, lsp->process->stderr, ReadInterest);
+
+ return 0;
+}
+
+int lsp_restart_server(struct lsp *lsp) {
+ if (lsp_server_running(lsp)) {
+ lsp_stop_server(lsp);
+ }
+
+ return lsp_start_server(lsp);
+}
+
+void lsp_stop_server(struct lsp *lsp) {
+ process_kill(lsp->process);
+ process_destroy(lsp->process);
+ free(lsp->process);
+ lsp->process = NULL;
+}
+
+bool lsp_server_running(const struct lsp *lsp) {
+ if (lsp->process == NULL) {
+ return false;
+ }
+
+ return process_running(lsp->process);
+}
+
+uint64_t lsp_server_pid(const struct lsp *lsp) {
+ if (!lsp_server_running(lsp)) {
+ return -1;
+ }
+
+ return lsp->process->id;
+}
+
+const char *lsp_server_name(const struct lsp *lsp) { return lsp->name; }
diff --git a/src/dged/lsp.h b/src/dged/lsp.h
new file mode 100644
index 0000000..3fd6285
--- /dev/null
+++ b/src/dged/lsp.h
@@ -0,0 +1,75 @@
+#ifndef _LSP_H
+#define _LSP_H
+
+#include "location.h"
+#include "s8.h"
+
+struct buffer;
+struct lsp;
+struct reactor;
+
+typedef uint32_t request_id;
+
+struct lsp_response {
+ request_id id;
+ bool ok;
+ union payload_data {
+ void *result;
+ struct s8 error;
+ } payload;
+};
+
+struct lsp_notification {
+ int something;
+};
+
+struct lsp_client {
+ void (*log_message)(int type, struct s8 msg);
+};
+
+struct hover {
+ struct s8 contents;
+
+ bool has_range;
+ struct region *range;
+};
+
+struct text_doc_item {
+ struct s8 uri;
+ struct s8 language_id;
+ uint32_t version;
+ struct s8 text;
+};
+
+struct text_doc_position {
+ struct s8 uri;
+ struct location pos;
+};
+
+struct initialize_params {
+ struct s8 client_name;
+ struct s8 client_version;
+};
+
+// lifecycle functions
+struct lsp *lsp_create(char *const command[], struct reactor *reactor,
+ struct buffer *stderr_buffer,
+ struct lsp_client client_impl, const char *name);
+uint32_t lsp_update(struct lsp *lsp, struct lsp_response **responses,
+ uint32_t responses_capacity);
+void lsp_destroy(struct lsp *lsp);
+
+// process control functions
+int lsp_start_server(struct lsp *lsp);
+int lsp_restart_server(struct lsp *lsp);
+void lsp_stop_server(struct lsp *lsp);
+bool lsp_server_running(const struct lsp *lsp);
+uint64_t lsp_server_pid(const struct lsp *lsp);
+const char *lsp_server_name(const struct lsp *lsp);
+
+// protocol functions
+void lsp_initialize(struct lsp *lsp, struct initialize_params);
+void lsp_did_open_document(struct lsp *lsp, struct text_doc_item document);
+request_id lsp_hover(struct lsp *lsp, struct text_doc_position);
+
+#endif
diff --git a/src/dged/minibuffer.c b/src/dged/minibuffer.c
index d31850b..c16a9bf 100644
--- a/src/dged/minibuffer.c
+++ b/src/dged/minibuffer.c
@@ -39,7 +39,7 @@ uint32_t minibuffer_draw_prompt(struct command_list *commands) {
static void minibuffer_abort_prompt_internal(bool clear);
-int32_t minibuffer_execute() {
+int32_t minibuffer_execute(void) {
if (g_minibuffer.prompt_active) {
struct command_ctx *c = &g_minibuffer.prompt_command_ctx;
@@ -50,7 +50,7 @@ int32_t minibuffer_execute() {
// propagate any saved arguments
char *argv[64];
- for (uint32_t i = 0; i < c->saved_argc; ++i) {
+ for (uint32_t i = 0; i < (uint32_t)c->saved_argc; ++i) {
argv[i] = (char *)c->saved_argv[i];
}
argv[c->saved_argc] = l;
@@ -79,6 +79,8 @@ int32_t minibuffer_execute() {
}
void update(struct buffer *buffer, void *userdata) {
+ (void)buffer;
+
struct timespec current;
struct minibuffer *mb = (struct minibuffer *)userdata;
clock_gettime(CLOCK_MONOTONIC, &current);
@@ -143,15 +145,15 @@ void message(const char *fmt, ...) {
nbytes > 2048 ? 2048 : nbytes);
}
-void minibuffer_destroy() {
+void minibuffer_destroy(void) {
command_ctx_free(&g_minibuffer.prompt_command_ctx);
}
-struct text_chunk minibuffer_content() {
+struct text_chunk minibuffer_content(void) {
return buffer_line(g_minibuffer.buffer, 0);
}
-struct buffer *minibuffer_buffer() {
+struct buffer *minibuffer_buffer(void) {
return g_minibuffer.buffer;
}
@@ -245,22 +247,22 @@ static void minibuffer_abort_prompt_internal(bool clear) {
g_minibuffer.prompt_active = false;
}
-void minibuffer_abort_prompt() { minibuffer_abort_prompt_internal(true); }
+void minibuffer_abort_prompt(void) { minibuffer_abort_prompt_internal(true); }
-bool minibuffer_empty() { return !minibuffer_displaying(); }
+bool minibuffer_empty(void) { return !minibuffer_displaying(); }
-bool minibuffer_displaying() {
+bool minibuffer_displaying(void) {
return g_minibuffer.buffer != NULL && !buffer_is_empty(g_minibuffer.buffer);
}
-void minibuffer_clear() {
+void minibuffer_clear(void) {
g_minibuffer.expires.tv_sec = 0;
g_minibuffer.expires.tv_nsec = 0;
buffer_clear(g_minibuffer.buffer);
}
-bool minibuffer_focused() { return g_minibuffer.prompt_active; }
+bool minibuffer_focused(void) { return g_minibuffer.prompt_active; }
-struct window *minibuffer_target_window() {
+struct window *minibuffer_target_window(void) {
return g_minibuffer.prev_window;
}
diff --git a/src/dged/minibuffer.h b/src/dged/minibuffer.h
index 6ac69c1..0b98904 100644
--- a/src/dged/minibuffer.h
+++ b/src/dged/minibuffer.h
@@ -24,11 +24,11 @@ void minibuffer_init(struct buffer *buffer, struct buffers *buffers);
*
* Note that this does not release the buffer used.
*/
-void minibuffer_destroy();
+void minibuffer_destroy(void);
-struct text_chunk minibuffer_content();
+struct text_chunk minibuffer_content(void);
-struct buffer *minibuffer_buffer();
+struct buffer *minibuffer_buffer(void);
void message(const char *fmt, ...);
@@ -74,14 +74,14 @@ uint32_t minibuffer_draw_prompt(struct command_list *commands);
*
* @returns zero on success, non-zero to indicate failure
*/
-int32_t minibuffer_execute();
+int32_t minibuffer_execute(void);
/**
* Abort the current minibuffer prompt.
*
* This returns focus to the previously focused window.
*/
-void minibuffer_abort_prompt();
+void minibuffer_abort_prompt(void);
/**
* Minibuffer prompt args
@@ -94,22 +94,22 @@ struct minibuffer_prompt_args {
/**
* Clear the current text in the minibuffer.
*/
-void minibuffer_clear();
+void minibuffer_clear(void);
-bool minibuffer_empty();
+bool minibuffer_empty(void);
/**
* Is the minibuffer currently displaying something?
*
* @returns True if the minibuffer is displaying anything, false otherwise.
*/
-bool minibuffer_displaying();
+bool minibuffer_displaying(void);
/**
* Is the minibuffer currently focused?
*
* @returns True if the minibuffer is currently focused, receiving user input.
*/
-bool minibuffer_focused();
+bool minibuffer_focused(void);
-struct window *minibuffer_target_window();
+struct window *minibuffer_target_window(void);
diff --git a/src/dged/path.c b/src/dged/path.c
new file mode 100644
index 0000000..735ef0c
--- /dev/null
+++ b/src/dged/path.c
@@ -0,0 +1,68 @@
+#include "path.h"
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *expanduser(const char *path) {
+ // replace tilde
+ char *res = NULL;
+ char *tilde_pos = strchr(path, '~');
+ if (tilde_pos != NULL) {
+ char *home = getenv("HOME");
+ if (home != NULL) {
+ // allocate a new string based with the new len
+ size_t home_len = strlen(home);
+ size_t path_len = strlen(path);
+ size_t total_len = path_len + home_len;
+ res = malloc(total_len);
+ size_t initial_len = tilde_pos - path;
+ strncpy(res, path, initial_len);
+
+ strncpy(res + initial_len, home, home_len + 1);
+
+ size_t rest_len = path_len - initial_len - 1;
+ strncpy(res + initial_len + home_len, path + initial_len + 1, rest_len);
+ res[total_len - 1] = '\0';
+ }
+ }
+
+ return res != NULL ? res : strdup(path);
+}
+
+char *to_abspath(const char *path) {
+ char *exp = expanduser(path);
+ char *p = realpath(path, NULL);
+ if (p != NULL) {
+ free(exp);
+ return p;
+ } else {
+ return exp;
+ }
+}
+
+const char *join_path_with_delim(const char *p1, const char *p2,
+ const char delim) {
+ size_t len1 = strlen(p1);
+ size_t len2 = strlen(p2);
+
+ char *path = malloc(len1 + len2 + 2);
+ uint32_t idx = 0;
+ memcpy(&path[idx], p1, len1);
+ idx += len1;
+ path[idx++] = delim;
+ memcpy(&path[idx], p2, len2);
+ idx += len2;
+ path[idx++] = '\0';
+
+ return path;
+}
+
+const char *join_path(const char *p1, const char *p2) {
+#ifdef __unix__
+ return join_path_with_delim(p1, p2, '/');
+#elif defined(_WIN32) || defined(WIN32)
+ return join_path_with_delim(p1, p2, '\\');
+#endif
+}
diff --git a/src/dged/path.h b/src/dged/path.h
index 8ea9977..6168e42 100644
--- a/src/dged/path.h
+++ b/src/dged/path.h
@@ -1,65 +1,10 @@
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
+#ifndef _PATH_H
+#define _PATH_H
-static char *expanduser(const char *path) {
- // replace tilde
- char *res = NULL;
- char *tilde_pos = strchr(path, '~');
- if (tilde_pos != NULL) {
- char *home = getenv("HOME");
- if (home != NULL) {
- // allocate a new string based with the new len
- size_t home_len = strlen(home);
- size_t path_len = strlen(path);
- size_t total_len = path_len + home_len;
- res = malloc(total_len);
- size_t initial_len = tilde_pos - path;
- strncpy(res, path, initial_len);
+char *expanduser(const char *path);
+char *to_abspath(const char *path);
+const char *join_path_with_delim(const char *p1, const char *p2,
+ const char delim);
+const char *join_path(const char *p1, const char *p2);
- strncpy(res + initial_len, home, home_len);
-
- size_t rest_len = path_len - initial_len - 1;
- strncpy(res + initial_len + home_len, path + initial_len + 1, rest_len);
- res[total_len - 1] = '\0';
- }
- }
-
- return res != NULL ? res : strdup(path);
-}
-
-static char *to_abspath(const char *path) {
- char *exp = expanduser(path);
- char *p = realpath(path, NULL);
- if (p != NULL) {
- free(exp);
- return p;
- } else {
- return exp;
- }
-}
-
-static const char *join_path_with_delim(const char *p1, const char *p2,
- const char delim) {
- size_t len1 = strlen(p1);
- size_t len2 = strlen(p2);
-
- char *path = malloc(len1 + len2 + 2);
- uint32_t idx = 0;
- memcpy(&path[idx], p1, len1);
- idx += len1;
- path[idx++] = '/';
- memcpy(&path[idx], p2, len2);
- idx += len2;
- path[idx++] = '\0';
-
- return path;
-}
-
-static const char *join_path(const char *p1, const char *p2) {
-#ifdef __unix__
- return join_path_with_delim(p1, p2, '/');
-#elif defined(_WIN32) || defined(WIN32)
- return join_path_with_delim(p1, p2, '\\');
#endif
-}
diff --git a/src/dged/process-posix.c b/src/dged/process-posix.c
new file mode 100644
index 0000000..94ceb5f
--- /dev/null
+++ b/src/dged/process-posix.c
@@ -0,0 +1,126 @@
+#include "process.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+static int create_pipe(int *read_end, int *write_end, bool read_nonblock,
+ bool write_nonblock) {
+ int pipes[2] = {0};
+ if (pipe(pipes) < 0) {
+ return -1;
+ }
+
+ if (write_nonblock) {
+ int flags = fcntl(pipes[1], F_GETFL, 0);
+ if (flags < 0) {
+ return -1;
+ }
+
+ flags |= O_NONBLOCK;
+ if (fcntl(pipes[1], F_SETFL, flags) < 0) {
+ return -1;
+ }
+ }
+
+ if (read_nonblock) {
+ int flags = fcntl(pipes[0], F_GETFL, 0);
+ if (flags < 0) {
+ return -1;
+ }
+
+ flags |= O_NONBLOCK;
+ if (fcntl(pipes[0], F_SETFL, flags) < 0) {
+ return -1;
+ }
+ }
+
+ *read_end = pipes[0];
+ *write_end = pipes[1];
+
+ return 0;
+}
+
+struct process_create_result process_create(char *const command[],
+ struct process *result) {
+
+ int stdin_read, stdin_write;
+ if (create_pipe(&stdin_read, &stdin_write, false, true) < 0) {
+ return (struct process_create_result){
+ .ok = false,
+ .error_message = strerror(errno),
+ };
+ }
+
+ int stdout_read, stdout_write;
+ if (create_pipe(&stdout_read, &stdout_write, true, false) < 0) {
+ return (struct process_create_result){
+ .ok = false,
+ .error_message = strerror(errno),
+ };
+ }
+
+ int stderr_read, stderr_write;
+ if (create_pipe(&stderr_read, &stderr_write, true, false) < 0) {
+ return (struct process_create_result){
+ .ok = false,
+ .error_message = strerror(errno),
+ };
+ }
+
+ pid_t pid = fork();
+ if (pid == -1) {
+ return (struct process_create_result){
+ .ok = false,
+ .error_message = strerror(errno),
+ };
+ } else if (pid == 0) {
+ close(stdin_write);
+ close(stdout_read);
+ close(stderr_read);
+
+ if (dup2(stdin_read, STDIN_FILENO) < 0) {
+ exit(16);
+ }
+
+ if (dup2(stdout_write, STDOUT_FILENO) < 0) {
+ exit(16);
+ }
+
+ if (dup2(stderr_write, STDERR_FILENO) < 0) {
+ exit(16);
+ }
+
+ if (execvp(command[0], command) < 0) {
+ exit(16);
+ }
+ } else {
+ close(stdin_read);
+ close(stdout_write);
+ close(stderr_write);
+
+ result->stdin = stdin_write;
+ result->stdout = stdout_read;
+ result->stderr = stderr_read;
+ result->id = (fd_t)pid;
+ result->impl = NULL;
+ }
+
+ return (struct process_create_result){
+ .ok = true,
+ };
+}
+
+void process_destroy(struct process *p) { (void)p; }
+
+bool process_running(const struct process *p) {
+ return waitpid(p->id, NULL, WNOHANG) == 0;
+}
+
+bool process_kill(const struct process *p) { return kill(p->id, SIGTERM) == 0; }
diff --git a/src/dged/process.h b/src/dged/process.h
new file mode 100644
index 0000000..cefec8c
--- /dev/null
+++ b/src/dged/process.h
@@ -0,0 +1,35 @@
+#ifndef _PROCESS_H
+#define _PROCESS_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef _WIN32
+typedef HANDLE fd_t;
+#else
+typedef int fd_t;
+#endif
+
+struct platform_process;
+struct process {
+ uint64_t id;
+ fd_t stdin;
+ fd_t stdout;
+ fd_t stderr;
+ struct platform_process *impl;
+};
+
+struct process_create_result {
+ bool ok;
+ const char *error_message;
+};
+
+struct process_create_result process_create(char *const command[],
+ struct process *result);
+
+void process_destroy(struct process *p);
+
+bool process_running(const struct process *p);
+bool process_kill(const struct process *p);
+
+#endif
diff --git a/src/dged/reactor-epoll.c b/src/dged/reactor-epoll.c
index 4c83b49..beee7ec 100644
--- a/src/dged/reactor-epoll.c
+++ b/src/dged/reactor-epoll.c
@@ -22,15 +22,15 @@ struct events {
uint32_t nevents;
};
-struct reactor *reactor_create() {
+struct reactor *reactor_create(void) {
int epollfd = epoll_create1(0);
if (epollfd == -1) {
- perror("epoll_create1");
+ return NULL;
}
int inotifyfd = inotify_init1(IN_NONBLOCK);
if (inotifyfd == -1) {
- perror("inotify_init1");
+ return NULL;
}
struct reactor *r = (struct reactor *)calloc(1, sizeof(struct reactor));
@@ -55,7 +55,6 @@ uint32_t reactor_register_interest(struct reactor *reactor, int fd,
ev.events |= (interest & WriteInterest) != 0 ? EPOLLOUT : 0;
ev.data.fd = fd;
if (epoll_ctl(reactor->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
- perror("epoll_ctl");
return -1;
}
@@ -71,7 +70,7 @@ bool reactor_poll_event(struct reactor *reactor, uint32_t ev_id) {
for (uint32_t ei = 0; ei < events->nevents; ++ei) {
struct epoll_event *ev = &events->events[ei];
- if (ev->data.fd == ev_id) {
+ if ((uint32_t)ev->data.fd == ev_id) {
return true;
}
}
@@ -118,7 +117,8 @@ void reactor_update(struct reactor *reactor) {
int nfds = epoll_wait(reactor->epoll_fd, events->events, 10, -1);
if (nfds == -1) {
- // TODO: log failure
+ events->nevents = 0;
+ message("failed update epoll reactor: %s", strerror(errno));
}
events->nevents = nfds;
diff --git a/src/dged/reactor-kqueue.c b/src/dged/reactor-kqueue.c
index 58ab7af..f30cb9a 100644
--- a/src/dged/reactor-kqueue.c
+++ b/src/dged/reactor-kqueue.c
@@ -16,7 +16,7 @@ struct reactor {
uint32_t nevents;
};
-struct reactor *reactor_create() {
+struct reactor *reactor_create(void) {
int queue = kqueue();
if (queue < 0) {
return NULL;
diff --git a/src/dged/reactor.h b/src/dged/reactor.h
index 39a94a9..82ff3fe 100644
--- a/src/dged/reactor.h
+++ b/src/dged/reactor.h
@@ -18,7 +18,7 @@ struct file_event {
struct reactor;
-struct reactor *reactor_create();
+struct reactor *reactor_create(void);
void reactor_destroy(struct reactor *reactor);
void reactor_update(struct reactor *reactor);
bool reactor_poll_event(struct reactor *reactor, uint32_t ev_id);
diff --git a/src/dged/settings.c b/src/dged/settings.c
index e63862f..68256e8 100644
--- a/src/dged/settings.c
+++ b/src/dged/settings.c
@@ -20,11 +20,11 @@ void settings_init(uint32_t initial_capacity) {
HASHMAP_INIT(&g_settings.settings, initial_capacity, hash_name);
}
-void settings_destroy() {
+void settings_destroy(void) {
HASHMAP_FOR_EACH(&g_settings.settings, struct setting_entry * entry) {
struct setting *setting = &entry->value;
if (setting->value.type == Setting_String) {
- free(setting->value.string_value);
+ free(setting->value.data.string_value);
}
}
@@ -33,8 +33,9 @@ void settings_destroy() {
void setting_set_value(struct setting *setting, struct setting_value val) {
if (setting->value.type == val.type) {
- if (setting->value.type == Setting_String && val.string_value != NULL) {
- setting->value.string_value = strdup(val.string_value);
+ if (setting->value.type == Setting_String &&
+ val.data.string_value != NULL) {
+ setting->value.data.string_value = strdup(val.data.string_value);
} else {
setting->value = val;
}
@@ -99,13 +100,13 @@ void settings_set_default(const char *path, struct setting_value value) {
void setting_to_string(struct setting *setting, char *buf, size_t n) {
switch (setting->value.type) {
case Setting_Bool:
- snprintf(buf, n, "%s", setting->value.bool_value ? "true" : "false");
+ snprintf(buf, n, "%s", setting->value.data.bool_value ? "true" : "false");
break;
case Setting_Number:
- snprintf(buf, n, "%" PRId64, setting->value.number_value);
+ snprintf(buf, n, "%" PRId64, setting->value.data.number_value);
break;
case Setting_String:
- snprintf(buf, n, "%s", setting->value.string_value);
+ snprintf(buf, n, "%s", setting->value.data.string_value);
break;
}
}
@@ -113,7 +114,6 @@ void setting_to_string(struct setting *setting, char *buf, size_t n) {
static int32_t parse_toml(struct parser *state, char **errmsgs[]) {
char *curtbl = NULL;
char *curkey = NULL;
- uint32_t errcnt = 0;
VEC(char *) errs;
VEC_INIT(&errs, 16);
@@ -160,20 +160,20 @@ static int32_t parse_toml(struct parser *state, char **errmsgs[]) {
case Token_IntValue:
i = *((int64_t *)t.data);
settings_set(curkey, (struct setting_value){.type = Setting_Number,
- .number_value = i});
+ .data.number_value = i});
break;
case Token_BoolValue:
b = *((bool *)t.data);
settings_set(curkey, (struct setting_value){.type = Setting_Bool,
- .bool_value = b});
+ .data.bool_value = b});
break;
case Token_StringValue:
v = calloc(t.len + 1, 1);
strncpy(v, (char *)t.data, t.len);
settings_set(curkey, (struct setting_value){.type = Setting_String,
- .string_value = v});
+ .data.string_value = v});
free(v);
break;
diff --git a/src/dged/settings.h b/src/dged/settings.h
index b88e483..fb79c75 100644
--- a/src/dged/settings.h
+++ b/src/dged/settings.h
@@ -26,7 +26,7 @@ struct setting_value {
/** Type of setting. */
enum setting_type type;
- union {
+ union setting_data {
/** String setting. */
char *string_value;
@@ -35,7 +35,7 @@ struct setting_value {
/** Boolean setting value. */
bool bool_value;
- };
+ } data;
};
/**
@@ -73,7 +73,7 @@ void settings_init(uint32_t initial_capacity);
/**
* Destroy the global collection of settings.
*/
-void settings_destroy();
+void settings_destroy(void);
/**
* Retrieve a single setting by path.
diff --git a/src/dged/syntax.c b/src/dged/syntax.c
index 569dc70..67ab3a2 100644
--- a/src/dged/syntax.c
+++ b/src/dged/syntax.c
@@ -48,6 +48,8 @@ struct highlight {
};
static void delete_parser(struct buffer *buffer, void *userdata) {
+ (void)buffer;
+
struct highlight *highlight = (struct highlight *)userdata;
if (highlight->query != NULL) {
@@ -72,6 +74,7 @@ static void delete_parser(struct buffer *buffer, void *userdata) {
static const char *read_text(void *payload, uint32_t byte_offset,
TSPoint position, uint32_t *bytes_read) {
+ (void)byte_offset;
struct text *text = (struct text *)payload;
@@ -97,7 +100,7 @@ static const char *read_text(void *payload, uint32_t byte_offset,
static const char *grammar_name_from_buffer(struct buffer *buffer) {
struct setting *s = lang_setting(&buffer->lang, "grammar");
if (s != NULL && s->value.type == Setting_String) {
- return s->value.string_value;
+ return s->value.data.string_value;
}
return buffer->lang.name;
@@ -124,6 +127,10 @@ static const char *lang_folder(struct buffer *buffer, const char *path) {
static bool eval_eq(struct s8 capname, uint32_t argc, struct s8 argv[],
struct s8 value, void *data) {
+ (void)capname;
+ (void)argc;
+ (void)argv;
+
const struct s8 *cmp_to = (const struct s8 *)data;
if (data == NULL) {
return false;
@@ -143,6 +150,10 @@ static void cleanup_eq(void *data) {
static bool eval_match(struct s8 capname, uint32_t argc, struct s8 argv[],
struct s8 value, void *data) {
+ (void)capname;
+ (void)argc;
+ (void)argv;
+
regex_t *regex = (regex_t *)data;
if (regex == NULL) {
return false;
@@ -325,6 +336,8 @@ static void update_parser(struct buffer *buffer, void *userdata,
struct location origin, uint32_t width,
uint32_t height) {
+ (void)width;
+
struct highlight *h = (struct highlight *)userdata;
if (h->query == NULL) {
@@ -411,7 +424,7 @@ static void update_parser(struct buffer *buffer, void *userdata,
end.column > 0 ? end.column - 1 : 0,
(struct text_property){
.type = TextProperty_Colors,
- .colors =
+ .data.colors =
(struct text_property_colors){
.set_fg = true,
.fg = color,
@@ -509,8 +522,9 @@ static void text_inserted(struct buffer *buffer, struct edit_location inserted,
}
static void create_parser(struct buffer *buffer, void *userdata) {
+ (void)userdata;
- TSLanguage *(*langsym)() = NULL;
+ TSLanguage *(*langsym)(void) = NULL;
const char *lang_root = NULL, *langname = NULL;
void *h = NULL;
@@ -601,7 +615,7 @@ void syntax_init(uint32_t grammar_path_len, const char *grammar_path[]) {
lang_setting_set_default(
&l, "grammar",
(struct setting_value){.type = Setting_String,
- .string_value = "gitcommit"});
+ .data.string_value = "gitcommit"});
lang_destroy(&l);
}
@@ -609,14 +623,15 @@ void syntax_init(uint32_t grammar_path_len, const char *grammar_path[]) {
if (!lang_is_fundamental(&l)) {
lang_setting_set_default(
&l, "grammar",
- (struct setting_value){.type = Setting_String, .string_value = "cpp"});
+ (struct setting_value){.type = Setting_String,
+ .data.string_value = "cpp"});
lang_destroy(&l);
}
buffer_add_create_hook(create_parser, NULL);
}
-void syntax_teardown() {
+void syntax_teardown(void) {
for (uint32_t i = 0; i < treesitter_path_len; ++i) {
free((void *)treesitter_path[i]);
}
diff --git a/src/dged/syntax.h b/src/dged/syntax.h
index 488406b..015f5be 100644
--- a/src/dged/syntax.h
+++ b/src/dged/syntax.h
@@ -4,6 +4,6 @@
#include <stdint.h>
void syntax_init(uint32_t grammar_path_len, const char *grammar_path[]);
-void syntax_teardown();
+void syntax_teardown(void);
#endif
diff --git a/src/dged/text.h b/src/dged/text.h
index 28bd325..505c86a 100644
--- a/src/dged/text.h
+++ b/src/dged/text.h
@@ -66,10 +66,10 @@ struct text_property_colors {
struct text_property {
enum text_property_type type;
- union {
+ union property_data {
struct text_property_colors colors;
void *userdata;
- };
+ } data;
};
void text_add_property(struct text *text, uint32_t start_line,
diff --git a/src/dged/timers.c b/src/dged/timers.c
index 798c003..2fd5fc9 100644
--- a/src/dged/timers.c
+++ b/src/dged/timers.c
@@ -23,21 +23,21 @@ static struct timers {
HASHMAP(struct timer_entry) timers;
} g_timers;
-void timers_init() {
+void timers_init(void) {
HASHMAP_INIT(&g_timers.timers, 32, hash_name);
g_timers.frame_index = 0;
}
-void timers_destroy() { HASHMAP_DESTROY(&g_timers.timers); }
+void timers_destroy(void) { HASHMAP_DESTROY(&g_timers.timers); }
-void timers_start_frame() {
+void timers_start_frame(void) {
HASHMAP_FOR_EACH(&g_timers.timers, struct timer_entry * entry) {
struct timer *timer = &entry->value;
timer->samples[g_timers.frame_index] = 0;
}
}
-void timers_end_frame() {
+void timers_end_frame(void) {
g_timers.frame_index = (g_timers.frame_index + 1) % NUM_FRAME_SAMPLES;
}
diff --git a/src/dged/timers.h b/src/dged/timers.h
index ae79a8b..03ec742 100644
--- a/src/dged/timers.h
+++ b/src/dged/timers.h
@@ -5,8 +5,8 @@
struct timer;
-void timers_init();
-void timers_start_frame();
+void timers_init(void);
+void timers_start_frame(void);
struct timer *timer_start(const char *name);
uint64_t timer_stop(struct timer *timer);
@@ -19,7 +19,7 @@ const char *timer_name(const struct timer *timer);
typedef void (*timer_callback)(const struct timer *timer, void *userdata);
void timers_for_each(timer_callback callback, void *userdata);
-void timers_end_frame();
-void timers_destroy();
+void timers_end_frame(void);
+void timers_destroy(void);
#endif
diff --git a/src/dged/undo.c b/src/dged/undo.c
index 8f00f0f..ad167c3 100644
--- a/src/dged/undo.c
+++ b/src/dged/undo.c
@@ -18,9 +18,9 @@ void undo_clear(struct undo_stack *undo) {
void undo_destroy(struct undo_stack *undo) {
VEC_FOR_EACH(&undo->records, struct undo_record * rec) {
- if (rec->type == Undo_Delete && rec->delete.data != NULL &&
- rec->delete.nbytes > 0) {
- free(rec->delete.data);
+ if (rec->type == Undo_Delete && rec->data.delete.data != NULL &&
+ rec->data.delete.nbytes > 0) {
+ free(rec->data.delete.data);
}
}
@@ -35,15 +35,15 @@ uint32_t undo_push_boundary(struct undo_stack *undo,
// we can only have one save point
if (boundary.save_point) {
VEC_FOR_EACH(&undo->records, struct undo_record * rec) {
- if (rec->type == Undo_Boundary && rec->boundary.save_point) {
- rec->boundary.save_point = false;
+ if (rec->type == Undo_Boundary && rec->data.boundary.save_point) {
+ rec->data.boundary.save_point = false;
}
}
}
VEC_APPEND(&undo->records, struct undo_record * rec);
rec->type = Undo_Boundary;
- rec->boundary = boundary;
+ rec->data.boundary = boundary;
if (!undo->undo_in_progress) {
undo->top = VEC_SIZE(&undo->records) - 1;
@@ -61,12 +61,12 @@ uint32_t undo_push_add(struct undo_stack *undo, struct undo_add add) {
// "compress"
if (!VEC_EMPTY(&undo->records) &&
VEC_BACK(&undo->records)->type == Undo_Add &&
- pos_equal(&VEC_BACK(&undo->records)->add.end, &add.begin)) {
- VEC_BACK(&undo->records)->add.end = add.end;
+ pos_equal(&VEC_BACK(&undo->records)->data.add.end, &add.begin)) {
+ VEC_BACK(&undo->records)->data.add.end = add.end;
} else {
VEC_APPEND(&undo->records, struct undo_record * rec);
rec->type = Undo_Add;
- rec->add = add;
+ rec->data.add = add;
}
if (!undo->undo_in_progress) {
@@ -79,7 +79,7 @@ uint32_t undo_push_add(struct undo_stack *undo, struct undo_add add) {
uint32_t undo_push_delete(struct undo_stack *undo, struct undo_delete delete) {
VEC_APPEND(&undo->records, struct undo_record * rec);
rec->type = Undo_Delete;
- rec->delete = delete;
+ rec->data.delete = delete;
if (!undo->undo_in_progress) {
undo->top = VEC_SIZE(&undo->records) - 1;
@@ -150,15 +150,15 @@ size_t rec_to_str(struct undo_record *rec, char *buffer, size_t n) {
switch (rec->type) {
case Undo_Add:
return snprintf(buffer, n, "add { begin: (%d, %d) end: (%d, %d)}",
- rec->add.begin.row, rec->add.begin.col, rec->add.end.row,
- rec->add.end.col);
+ rec->data.add.begin.row, rec->data.add.begin.col,
+ rec->data.add.end.row, rec->data.add.end.col);
case Undo_Delete:
return snprintf(buffer, n, "delete { pos: (%d, %d), ptr: 0x%p, nbytes: %d}",
- rec->delete.pos.row, rec->delete.pos.col, rec->delete.data,
- rec->delete.nbytes);
+ rec->data.delete.pos.row, rec->data.delete.pos.col,
+ (void *)rec->data.delete.data, rec->data.delete.nbytes);
default:
return snprintf(buffer, n, "boundary { save_point: %s }",
- rec->boundary.save_point ? "yes" : "no");
+ rec->data.boundary.save_point ? "yes" : "no");
}
}
diff --git a/src/dged/undo.h b/src/dged/undo.h
index 1ce3a8a..2f308f9 100644
--- a/src/dged/undo.h
+++ b/src/dged/undo.h
@@ -31,14 +31,14 @@ struct undo_delete {
struct undo_record {
enum undo_record_type type;
- union {
+ union undo_record_data {
struct undo_boundary boundary;
struct undo_add add;
struct undo_delete delete;
- };
+ } data;
};
-#define INVALID_TOP -1
+#define INVALID_TOP (uint32_t) - 1
struct undo_stack {
VEC(struct undo_record) records;
diff --git a/src/dged/utf8.c b/src/dged/utf8.c
index ede4fb1..01dcdbd 100644
--- a/src/dged/utf8.c
+++ b/src/dged/utf8.c
@@ -112,7 +112,6 @@ uint32_t utf8_nchars(uint8_t *bytes, uint32_t nbytes) {
uint32_t utf8_nbytes(uint8_t *bytes, uint32_t nbytes, uint32_t nchars) {
uint32_t bi = 0;
uint32_t chars = 0;
- uint32_t expected = 0;
while (chars < nchars && bi < nbytes) {
struct codepoint codepoint = next_utf8_codepoint(bytes + bi, nbytes - bi);
@@ -127,7 +126,7 @@ uint32_t utf8_nbytes(uint8_t *bytes, uint32_t nbytes, uint32_t nchars) {
uint32_t unicode_visual_char_width(const struct codepoint *codepoint) {
if (codepoint->nbytes > 0) {
// TODO: use unicode classification instead
- size_t w = wcwidth(codepoint->codepoint);
+ int w = wcwidth(codepoint->codepoint);
return w >= 0 ? w : 2;
} else {
return 0;
diff --git a/src/dged/vec.h b/src/dged/vec.h
index 929c8d5..1289a08 100644
--- a/src/dged/vec.h
+++ b/src/dged/vec.h
@@ -48,8 +48,7 @@
}
#define VEC_SWAP(vec, idx1, idx2) \
- if (idx1 < (vec)->nentries && idx2 < (vec)->nentries && idx1 >= 0 && \
- idx2 >= 0) { \
+ if (idx1 < (vec)->nentries && idx2 < (vec)->nentries) { \
*((vec)->temp) = (vec)->entries[idx1]; \
(vec)->entries[idx1] = (vec)->entries[idx2]; \
(vec)->entries[idx2] = *((vec)->temp); \
diff --git a/src/dged/window.c b/src/dged/window.c
index 20cb22f..702f97a 100644
--- a/src/dged/window.c
+++ b/src/dged/window.c
@@ -124,25 +124,25 @@ static void window_tree_clear_sub(struct window_node *root_node) {
BINTREE_FREE_NODES(root_node, window_node);
}
-static void window_tree_clear() {
+static void window_tree_clear(void) {
window_tree_clear_sub(BINTREE_ROOT(&g_windows.windows));
}
-void windows_destroy() { window_tree_clear(); }
+void windows_destroy(void) { window_tree_clear(); }
-struct window *root_window() {
+struct window *root_window(void) {
return &BINTREE_VALUE(BINTREE_ROOT(&g_windows.windows));
}
-struct window *minibuffer_window() {
+struct window *minibuffer_window(void) {
return &g_minibuffer_window;
}
-struct window *popup_window() {
+struct window *popup_window(void) {
return &g_popup_window;
}
-bool popup_window_visible() { return g_popup_visible; }
+bool popup_window_visible(void) { return g_popup_visible; }
static void window_tree_resize(struct window_node *root, uint32_t height,
uint32_t width) {
@@ -412,7 +412,7 @@ struct window *window_find_by_buffer(struct buffer *b) {
return NULL;
}
-struct window *windows_get_active() {
+struct window *windows_get_active(void) {
return g_windows.active;
}
@@ -630,7 +630,7 @@ void window_split(struct window *window, struct window **new_window_a,
: window_vsplit(window, new_window_a, new_window_b);
}
-struct window *windows_focus_next() {
+struct window *windows_focus_next(void) {
struct window *active = windows_get_active();
struct window_node *n = find_window(active);
BINTREE_NEXT(n);
@@ -693,4 +693,4 @@ void windows_show_popup(uint32_t row, uint32_t col, uint32_t width,
g_popup_visible = true;
}
-void windows_close_popup() { g_popup_visible = false; }
+void windows_close_popup(void) { g_popup_visible = false; }
diff --git a/src/dged/window.h b/src/dged/window.h
index e1b1d25..7738e16 100644
--- a/src/dged/window.h
+++ b/src/dged/window.h
@@ -25,20 +25,20 @@ void windows_init(uint32_t height, uint32_t width,
struct buffer *initial_buffer, struct buffer *minibuffer,
struct buffers *buffers);
-void windows_destroy();
+void windows_destroy(void);
void windows_resize(uint32_t height, uint32_t width);
void windows_update(void *(*frame_alloc)(size_t), float frame_time);
void windows_render(struct display *display);
-struct window *root_window();
-struct window *minibuffer_window();
-struct window *popup_window();
-bool popup_window_visible();
+struct window *root_window(void);
+struct window *minibuffer_window(void);
+struct window *popup_window(void);
+bool popup_window_visible(void);
void windows_set_active(struct window *window);
struct window *windows_focus(uint32_t id);
-struct window *windows_get_active();
-struct window *windows_focus_next();
+struct window *windows_get_active(void);
+struct window *windows_focus_next(void);
struct window *window_find_by_buffer(struct buffer *b);
void window_set_buffer(struct window *window, struct buffer *buffer);
@@ -63,6 +63,6 @@ void window_vsplit(struct window *window, struct window **new_window_a,
void windows_show_popup(uint32_t row, uint32_t col, uint32_t width,
uint32_t height);
-void windows_close_popup();
+void windows_close_popup(void);
#endif