From 9272fe36e2e36789342337d81914008826499941 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 18 Jun 2019 11:08:42 +0000 Subject: [PATCH 1/2] Add a cmdq_continue function rather than twiddling the flag directly. --- cfg.c | 2 +- cmd-display-panes.c | 2 +- cmd-if-shell.c | 2 +- cmd-load-buffer.c | 2 +- cmd-queue.c | 7 +++++++ cmd-run-shell.c | 2 +- cmd-wait-for.c | 8 ++++---- menu.c | 2 +- tmux.h | 1 + window.c | 2 +- 10 files changed, 19 insertions(+), 11 deletions(-) diff --git a/cfg.c b/cfg.c index c79150de..286ed460 100644 --- a/cfg.c +++ b/cfg.c @@ -53,7 +53,7 @@ cfg_done(__unused struct cmdq_item *item, __unused void *data) cfg_show_causes(RB_MIN(sessions, &sessions)); if (cfg_item != NULL) - cfg_item->flags &= ~CMDQ_WAITING; + cmdq_continue(cfg_item); status_prompt_load_history(); diff --git a/cmd-display-panes.c b/cmd-display-panes.c index aeeb6936..aa665f08 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -188,7 +188,7 @@ cmd_display_panes_free(struct client *c) struct cmd_display_panes_data *cdata = c->overlay_data; if (cdata->item != NULL) - cdata->item->flags &= ~CMDQ_WAITING; + cmdq_continue(cdata->item); free(cdata->command); free(cdata); } diff --git a/cmd-if-shell.c b/cmd-if-shell.c index f795575a..a992602c 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -196,7 +196,7 @@ cmd_if_shell_callback(struct job *job) out: if (cdata->item != NULL) - cdata->item->flags &= ~CMDQ_WAITING; + cmdq_continue(cdata->item); } static void diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index 3e669093..cdf44bf7 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -176,7 +176,7 @@ cmd_load_buffer_callback(struct client *c, int closed, void *data) free(cause); } out: - cdata->item->flags &= ~CMDQ_WAITING; + cmdq_continue(cdata->item); free(cdata->bufname); free(cdata); diff --git a/cmd-queue.c b/cmd-queue.c index 1ee43508..ef68d5d5 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -156,6 +156,13 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, free(name); } +/* Continue processing command queue. */ +void +cmdq_continue(struct cmdq_item *item) +{ + item->flags &= ~CMDQ_WAITING; +} + /* Remove an item. */ static void cmdq_remove(struct cmdq_item *item) diff --git a/cmd-run-shell.c b/cmd-run-shell.c index c9a478c7..2f45f492 100644 --- a/cmd-run-shell.c +++ b/cmd-run-shell.c @@ -155,7 +155,7 @@ cmd_run_shell_callback(struct job *job) free(msg); if (cdata->item != NULL) - cdata->item->flags &= ~CMDQ_WAITING; + cmdq_continue(cdata->item); } static void diff --git a/cmd-wait-for.c b/cmd-wait-for.c index 33600eda..4f438a7f 100644 --- a/cmd-wait-for.c +++ b/cmd-wait-for.c @@ -153,7 +153,7 @@ cmd_wait_for_signal(__unused struct cmdq_item *item, const char *name, log_debug("signal wait channel %s, with waiters", wc->name); TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) { - wi->item->flags &= ~CMDQ_WAITING; + cmdq_continue(wi->item); TAILQ_REMOVE(&wc->waiters, wi, entry); free(wi); @@ -229,7 +229,7 @@ cmd_wait_for_unlock(struct cmdq_item *item, const char *name, } if ((wi = TAILQ_FIRST(&wc->lockers)) != NULL) { - wi->item->flags &= ~CMDQ_WAITING; + cmdq_continue(wi->item); TAILQ_REMOVE(&wc->lockers, wi, entry); free(wi); } else { @@ -248,13 +248,13 @@ cmd_wait_for_flush(void) RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) { TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) { - wi->item->flags &= ~CMDQ_WAITING; + cmdq_continue(wi->item); TAILQ_REMOVE(&wc->waiters, wi, entry); free(wi); } wc->woken = 1; TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) { - wi->item->flags &= ~CMDQ_WAITING; + cmdq_continue(wi->item); TAILQ_REMOVE(&wc->lockers, wi, entry); free(wi); } diff --git a/menu.c b/menu.c index fd35399b..cc21c796 100644 --- a/menu.c +++ b/menu.c @@ -161,7 +161,7 @@ menu_free_cb(struct client *c) struct menu_data *md = c->overlay_data; if (md->item != NULL) - md->item->flags &= ~CMDQ_WAITING; + cmdq_continue(md->item); if (md->cb != NULL) md->cb(md->menu, UINT_MAX, KEYC_NONE, md->data); diff --git a/tmux.h b/tmux.h index 3324acba..cc5e55c0 100644 --- a/tmux.h +++ b/tmux.h @@ -2037,6 +2037,7 @@ void cmdq_insert_after(struct cmdq_item *, struct cmdq_item *); void cmdq_append(struct client *, struct cmdq_item *); void cmdq_insert_hook(struct session *, struct cmdq_item *, struct cmd_find_state *, const char *, ...); +void cmdq_continue(struct cmdq_item *); void printflike(3, 4) cmdq_format(struct cmdq_item *, const char *, const char *, ...); u_int cmdq_next(struct client *); diff --git a/window.c b/window.c index e89cf96c..e7941c70 100644 --- a/window.c +++ b/window.c @@ -1512,7 +1512,7 @@ window_pane_input_callback(struct client *c, int closed, void *data) c->stdin_callback = NULL; server_client_unref(c); - cdata->item->flags &= ~CMDQ_WAITING; + cmdq_continue(cdata->item); free(cdata); return; From 250fdd08bea74f47fc9a8962d5688db353896921 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 18 Jun 2019 11:17:40 +0000 Subject: [PATCH 2/2] Handle comments more correctly inside {}, from Avi Halachmi. --- cmd-parse.y | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/cmd-parse.y b/cmd-parse.y index 1dbc27a7..6d2b970c 100644 --- a/cmd-parse.y +++ b/cmd-parse.y @@ -1338,8 +1338,8 @@ static int yylex_token_brace(char **buf, size_t *len) { struct cmd_parse_state *ps = &parse_state; - int ch, nesting = 1, escape = 0, quote = '\0'; - int lines = 0; + int ch, lines = 0, nesting = 1, escape = 0; + int quote = '\0', token = 0; /* * Extract a string up to the matching unquoted '}', including newlines @@ -1349,6 +1349,10 @@ yylex_token_brace(char **buf, size_t *len) * depth, we scan the input as if it was a tmux config file, and ignore * braces which would be considered quoted, escaped, or in a comment. * + * We update the token state after every character because '#' begins a + * comment only when it begins a token. For simplicity, we treat an + * unquoted directive format as comment. + * * The result is verbatim copy of the input excluding the final brace. */ @@ -1368,6 +1372,8 @@ yylex_token_brace(char **buf, size_t *len) ch == '\n' || ch == '\\')) { escape = 0; + if (ch != '\n') + token = 1; continue; } @@ -1383,7 +1389,7 @@ yylex_token_brace(char **buf, size_t *len) /* A newline always resets to unquoted. */ if (ch == '\n') { - quote = 0; + quote = token = 0; continue; } @@ -1394,33 +1400,47 @@ yylex_token_brace(char **buf, size_t *len) */ if (ch == quote && quote != '#') quote = 0; - } else { + token = 1; /* token continues regardless */ + } else { /* Not inside quotes or comment. */ switch (ch) { case '"': case '\'': case '#': - /* Beginning of quote or comment. */ - quote = ch; + /* Beginning of quote or maybe comment. */ + if (ch != '#' || !token) + quote = ch; + token = 1; + break; + case ' ': + case '\t': + case ';': + /* Delimiter - token resets. */ + token = 0; break; case '{': nesting++; + token = 0; /* new commands set - token resets */ break; case '}': nesting--; + token = 1; /* same as after quotes */ if (nesting == 0) { (*len)--; /* remove closing } */ ps->input->line += lines; return (1); } break; + default: + token = 1; + break; } } } /* - * Update line count after error as reporting the opening line - * is more useful than EOF. + * Update line count after error as reporting the opening line is more + * useful than EOF. */ yyerror("unterminated brace string"); ps->input->line += lines;