diff --git a/common.cpp b/common.cpp index 2124fe678..7ec061aa2 100644 --- a/common.cpp +++ b/common.cpp @@ -1961,7 +1961,7 @@ void append_path_component(wcstring &path, const wcstring &component) } extern "C" { -__attribute__((noinline)) void debug_thread_error(void) {} +__attribute__((noinline)) void debug_thread_error(void) { while (1) sleep(9999999); } } @@ -2015,11 +2015,11 @@ void assert_is_background_thread(const char *who) } } -void assert_is_locked(void *vmutex, const char *who) +void assert_is_locked(void *vmutex, const char *who, const char *caller) { pthread_mutex_t *mutex = static_cast(vmutex); if (0 == pthread_mutex_trylock(mutex)) { - fprintf(stderr, "Warning: %s is not locked when it should be. Break on debug_thread_error to debug.\n", who); + fprintf(stderr, "Warning: %s is not locked when it should be in '%s'. Break on debug_thread_error to debug.\n", who, caller); debug_thread_error(); pthread_mutex_unlock(mutex); } diff --git a/common.h b/common.h index 27ef96fbc..c98a8956b 100644 --- a/common.h +++ b/common.h @@ -268,8 +268,8 @@ void assert_is_background_thread(const char *who); #define ASSERT_IS_BACKGROUND_THREAD() ASSERT_IS_BACKGROUND_THREAD_TRAMPOLINE(__FUNCTION__) /* Useful macro for asserting that a lock is locked. This doesn't check whether this thread locked it, which it would be nice if it did, but here it is anyways. */ -void assert_is_locked(void *mutex, const char *who); -#define ASSERT_IS_LOCKED(x) assert_is_locked((void *)(&x), #x) +void assert_is_locked(void *mutex, const char *who, const char *caller); +#define ASSERT_IS_LOCKED(x) assert_is_locked((void *)(&x), #x, __FUNCTION__) /** Converts the wide character string \c in into it's narrow diff --git a/env.h b/env.h index 16c274ed3..b8869f409 100644 --- a/env.h +++ b/env.h @@ -184,6 +184,7 @@ class env_vars { }; extern bool g_log_forks; +extern int g_fork_count; #endif diff --git a/exec.cpp b/exec.cpp index ecaaca022..227ef9e84 100644 --- a/exec.cpp +++ b/exec.cpp @@ -690,7 +690,7 @@ void exec( parser_t &parser, job_t *j ) { /* Call fork. No need to wait for threads since our use is confined and simple. */ if (g_log_forks) { - printf("Executing keepalive fork for '%ls'\n", j->command_wcstr()); + printf("fork #%d: Executing keepalive fork for '%ls'\n", g_fork_count, j->command_wcstr()); } keepalive.pid = execute_fork(false); if( keepalive.pid == 0 ) @@ -1101,7 +1101,7 @@ void exec( parser_t &parser, job_t *j ) /* We don't have to drain threads here because our child process is simple */ if (g_log_forks) { - printf("Executing fork for internal buffer for '%ls'\n", p->argv0() ? p->argv0() : L"(null)"); + printf("fork #%d: Executing fork for internal buffer for '%ls'\n", g_fork_count, p->argv0() ? p->argv0() : L"(null)"); } pid = execute_fork(false); if( pid == 0 ) @@ -1173,7 +1173,7 @@ void exec( parser_t &parser, job_t *j ) if (! skip_fork && ! j->io) { /* PCA for some reason, fish forks a lot, even for basic builtins like echo just to write out their buffers. I'm certain a lot of this is unnecessary, but I am not sure exactly when. If j->io is NULL, then it means there's no pipes or anything, so we can certainly just write out our data. Beyond that, we may be able to do the same if io_get returns 0 for STDOUT_FILENO and STDERR_FILENO. */ if (g_log_forks) { - printf("Skipping fork for internal builtin for '%ls' (io is %p, job_io is %p)\n", p->argv0(), io, j->io); + printf("fork #-: Skipping fork for internal builtin for '%ls' (io is %p, job_io is %p)\n", p->argv0(), io, j->io); } const wcstring &out = get_stdout_buffer(), &err = get_stderr_buffer(); char *outbuff = wcs2str(out.c_str()), *errbuff = wcs2str(err.c_str()); @@ -1269,7 +1269,9 @@ void exec( parser_t &parser, job_t *j ) const wchar_t *reader_current_filename(); if (g_log_forks) { - printf("forking for '%s' in '%ls'\n", actual_cmd, reader_current_filename()); + const wchar_t *file = reader_current_filename(); + const wchar_t *func = parser_t::principal_parser().is_function(); + printf("fork #%d: forking for '%s' in '%ls:%ls'\n", g_fork_count, actual_cmd, file ? file : L"", func ? func : L"?"); } pid = execute_fork(false); if( pid == 0 ) diff --git a/highlight.cpp b/highlight.cpp index a1ac40b09..848c6a33a 100644 --- a/highlight.cpp +++ b/highlight.cpp @@ -561,17 +561,38 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di { wcstring dir = tok_last( &tok ); wcstring suggested_path; + if (is_potential_path(dir, &suggested_path, true /* require directory */)) { + /* suggested_path needs to actually have dir as a prefix (perhaps with different case). Handle stuff like ./ */ bool wants_dot_slash = string_prefixes_string(L"./", dir); bool has_dot_slash = string_prefixes_string(L"./", suggested_path); - + if (wants_dot_slash && ! has_dot_slash) { suggested_path.insert(0, L"./"); } else if (! wants_dot_slash && has_dot_slash) { suggested_path.erase(0, 2); } + bool wants_tilde = string_prefixes_string(L"~", dir); + bool has_tilde = string_prefixes_string(L"~", suggested_path); + if (wants_tilde && ! has_tilde) { + // The input string has a tilde, the output string does not + // Extract the tilde part, expand it, see if the expansion prefixes the suggestion + // If so, replace it with the tilde part + size_t slash_idx = dir.find(L'/'); + const wcstring tilde_part(dir, 0, slash_idx); //note that slash_idx is npos this will return everything + + // Expand the tilde + wcstring expanded_tilde = tilde_part; + expand_tilde(expanded_tilde); + + // Replace it + if (string_prefixes_string(expanded_tilde, suggested_path)) { + suggested_path.replace(0, expanded_tilde.size(), tilde_part); + } + } + suggestion = str; suggestion.erase(tok_get_pos(&tok)); suggestion.append(suggested_path); diff --git a/parser.h b/parser.h index 016c98409..5ce832921 100644 --- a/parser.h +++ b/parser.h @@ -307,14 +307,6 @@ class parser_t { parser_t(const parser_t&); parser_t& operator=(const parser_t&); - /** - Returns the name of the currently evaluated function if we are - currently evaluating a function, null otherwise. This is tested by - moving down the block-scope-stack, checking every block if it is of - type FUNCTION_CALL. - */ - const wchar_t *is_function() const; - void parse_job_argument_list( process_t *p, job_t *j, tokenizer *tok, std::vector& ); int parse_job( process_t *p, job_t *j, tokenizer *tok ); void skipped_exec( job_t * j ); @@ -326,6 +318,14 @@ class parser_t { public: std::vector profile_items; + /** + Returns the name of the currently evaluated function if we are + currently evaluating a function, null otherwise. This is tested by + moving down the block-scope-stack, checking every block if it is of + type FUNCTION_CALL. + */ + const wchar_t *is_function() const; + /** Get the "principal" parser, whatever that is */ static parser_t &principal_parser();