aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/spawn.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/spawn.c')
-rw-r--r--src/spawn.c96
1 files changed, 50 insertions, 46 deletions
diff --git a/src/spawn.c b/src/spawn.c
index a30e6b2..e6d620c 100644
--- a/src/spawn.c
+++ b/src/spawn.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2023 Robin Haberkorn
+ * Copyright (C) 2012-2024 Robin Haberkorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -76,8 +76,8 @@ static struct {
GSource *stdin_src, *stdout_src;
gboolean interrupted;
- teco_int_t from, to;
- teco_int_t start;
+ gssize from, to;
+ gsize start;
gboolean text_added;
teco_eol_writer_t stdin_writer;
@@ -121,7 +121,7 @@ teco_parse_shell_command_line(const gchar *cmdline, GError **error)
teco_qreg_t *reg = teco_qreg_table_find(&teco_qreg_table_globals, "$COMSPEC", 8);
g_assert(reg != NULL);
teco_string_t comspec;
- if (!reg->vtable->get_string(reg, &comspec.data, &comspec.len, error))
+ if (!reg->vtable->get_string(reg, &comspec.data, &comspec.len, NULL, error))
return NULL;
argv = g_new(gchar *, 5);
@@ -140,7 +140,7 @@ teco_parse_shell_command_line(const gchar *cmdline, GError **error)
teco_qreg_t *reg = teco_qreg_table_find(&teco_qreg_table_globals, "$SHELL", 6);
g_assert(reg != NULL);
teco_string_t shell;
- if (!reg->vtable->get_string(reg, &shell.data, &shell.len, error))
+ if (!reg->vtable->get_string(reg, &shell.data, &shell.len, NULL, error))
return NULL;
argv = g_new(gchar *, 4);
@@ -164,6 +164,13 @@ teco_state_execute_initial(teco_machine_main_t *ctx, GError **error)
if (ctx->mode > TECO_MODE_NORMAL)
return TRUE;
+ /*
+ * Command-lines and file names are always assumed to be UTF-8,
+ * unless we set TECO_ED_DEFAULT_ANSI.
+ */
+ teco_machine_stringbuilding_set_codepage(&ctx->expectstring.machine,
+ teco_default_codepage());
+
if (!teco_expressions_eval(FALSE, error))
return FALSE;
@@ -202,15 +209,17 @@ teco_state_execute_initial(teco_machine_main_t *ctx, GError **error)
break;
}
- default:
+ default: {
/* pipe and replace character range */
- if (!teco_expressions_pop_num_calc(&teco_spawn_ctx.to, 0, error) ||
- !teco_expressions_pop_num_calc(&teco_spawn_ctx.from, 0, error))
+ teco_int_t from, to;
+ if (!teco_expressions_pop_num_calc(&to, 0, error) ||
+ !teco_expressions_pop_num_calc(&from, 0, error))
return FALSE;
+ teco_spawn_ctx.from = teco_interface_glyphs2bytes(from);
+ teco_spawn_ctx.to = teco_interface_glyphs2bytes(to);
rc = teco_bool(teco_spawn_ctx.from <= teco_spawn_ctx.to &&
- teco_validate_pos(teco_spawn_ctx.from) &&
- teco_validate_pos(teco_spawn_ctx.to));
- break;
+ teco_spawn_ctx.from >= 0 && teco_spawn_ctx.to >= 0);
+ }
}
if (teco_is_failure(rc)) {
@@ -257,12 +266,11 @@ teco_state_execute_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr
g_autoptr(GIOChannel) stdin_chan = NULL, stdout_chan = NULL;
g_auto(GStrv) argv = NULL, envp = NULL;
- if (teco_string_contains(str, '\0')) {
+ if (!str->len || teco_string_contains(str, '\0')) {
g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED,
- "Command line must not contain null-bytes");
+ "Command line must not be empty or contain null-bytes");
goto gerror;
}
- g_assert(str->data != NULL);
argv = teco_parse_shell_command_line(str->data, error);
if (!argv)
@@ -410,17 +418,17 @@ cleanup:
}
/* in cmdline.c */
-gboolean teco_state_execute_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gchar key, GError **error);
+gboolean teco_state_execute_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error);
/*$ EC pipe filter
- * EC[command]$ -- Execute operating system command and filter buffer contents
- * linesEC[command]$
- * -EC[command]$
- * from,toEC[command]$
- * :EC[command]$ -> Success|Failure
- * lines:EC[command]$ -> Success|Failure
- * -:EC[command]$ -> Success|Failure
- * from,to:EC[command]$ -> Success|Failure
+ * ECcommand$ -- Execute operating system command and filter buffer contents
+ * linesECcommand$
+ * -ECcommand$
+ * from,toECcommand$
+ * :ECcommand$ -> Success|Failure
+ * lines:ECcommand$ -> Success|Failure
+ * -:ECcommand$ -> Success|Failure
+ * from,to:ECcommand$ -> Success|Failure
*
* The EC command allows you to interface with the operating
* system shell and external programs.
@@ -546,14 +554,14 @@ teco_state_egcommand_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg,
}
/*$ EG EGq
- * EGq[command]$ -- Set Q-Register to output of operating system command
- * linesEGq[command]$
- * -EGq[command]$
- * from,toEGq[command]$
- * :EGq[command]$ -> Success|Failure
- * lines:EGq[command]$ -> Success|Failure
- * -:EGq[command]$ -> Success|Failure
- * from,to:EGq[command]$ -> Success|Failure
+ * EGq command$ -- Set Q-Register to output of operating system command
+ * linesEGq command$
+ * -EGq command$
+ * from,toEGq command$
+ * :EGq command$ -> Success|Failure
+ * lines:EGq command$ -> Success|Failure
+ * -:EGq command$ -> Success|Failure
+ * from,to:EGq command$ -> Success|Failure
*
* Runs an operating system <command> and set Q-Register
* <q> to the data read from its standard output stream.
@@ -635,7 +643,7 @@ teco_spawn_stdin_watch_cb(GIOChannel *chan, GIOCondition condition, gpointer dat
gssize bytes_written = teco_eol_writer_convert(&teco_spawn_ctx.stdin_writer, buffer,
convert_len, &teco_spawn_ctx.error);
if (bytes_written < 0) {
- /* GError ocurred */
+ /* GError occurred */
g_main_loop_quit(teco_spawn_ctx.mainloop);
return G_SOURCE_REMOVE;
}
@@ -667,6 +675,8 @@ teco_spawn_stdout_watch_cb(GIOChannel *chan, GIOCondition condition, gpointer da
/* source has already been dispatched */
return G_SOURCE_REMOVE;
+ teco_qreg_t *qreg = teco_spawn_ctx.register_argument;
+
for (;;) {
teco_string_t buffer;
@@ -685,20 +695,16 @@ teco_spawn_stdout_watch_cb(GIOChannel *chan, GIOCondition condition, gpointer da
if (!buffer.len)
return G_SOURCE_CONTINUE;
- if (teco_spawn_ctx.register_argument) {
+ if (qreg) {
if (teco_spawn_ctx.text_added) {
- if (!teco_spawn_ctx.register_argument->vtable->undo_append_string(teco_spawn_ctx.register_argument,
- &teco_spawn_ctx.error) ||
- !teco_spawn_ctx.register_argument->vtable->append_string(teco_spawn_ctx.register_argument,
- buffer.data, buffer.len,
- &teco_spawn_ctx.error))
+ if (!qreg->vtable->undo_append_string(qreg, &teco_spawn_ctx.error) ||
+ !qreg->vtable->append_string(qreg, buffer.data, buffer.len,
+ &teco_spawn_ctx.error))
goto error;
} else {
- if (!teco_spawn_ctx.register_argument->vtable->undo_set_string(teco_spawn_ctx.register_argument,
- &teco_spawn_ctx.error) ||
- !teco_spawn_ctx.register_argument->vtable->set_string(teco_spawn_ctx.register_argument,
- buffer.data, buffer.len,
- &teco_spawn_ctx.error))
+ if (!qreg->vtable->undo_set_string(qreg, &teco_spawn_ctx.error) ||
+ !qreg->vtable->set_string(qreg, buffer.data, buffer.len,
+ teco_default_codepage(), &teco_spawn_ctx.error))
goto error;
}
} else {
@@ -789,8 +795,7 @@ teco_spawn_idle_cb(gpointer user_data)
return G_SOURCE_CONTINUE;
}
-#ifndef NDEBUG
-static void __attribute__((destructor))
+static void TECO_DEBUG_CLEANUP
teco_spawn_cleanup(void)
{
g_source_unref(teco_spawn_ctx.idle_src);
@@ -801,4 +806,3 @@ teco_spawn_cleanup(void)
if (teco_spawn_ctx.error)
g_error_free(teco_spawn_ctx.error);
}
-#endif