diff options
Diffstat (limited to 'src/spawn.c')
-rw-r--r-- | src/spawn.c | 96 |
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 |