diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 21:52:58 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-11-29 21:52:58 +0000 |
commit | 931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch) | |
tree | d8c1843a95da5ea0bb4acc09f7e37843d9995c86 /src/nvim/os | |
parent | 142d9041391780ac15b89886a54015fdc5c73995 (diff) | |
parent | 4a8bf24ac690004aedf5540fa440e788459e5e34 (diff) | |
download | rneovim-userreg.tar.gz rneovim-userreg.tar.bz2 rneovim-userreg.zip |
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'src/nvim/os')
41 files changed, 836 insertions, 518 deletions
diff --git a/src/nvim/os/dl.c b/src/nvim/os/dl.c index 519cef7876..1a8d847f79 100644 --- a/src/nvim/os/dl.c +++ b/src/nvim/os/dl.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - /// Functions for using external native libraries #include <stdbool.h> @@ -75,7 +72,7 @@ bool os_libcall(const char *libname, const char *funcname, const char *argv, int // assume that ptr values of NULL, 1 or -1 are illegal *str_out = (res && (intptr_t)res != 1 && (intptr_t)res != -1) - ? xstrdup(res) : NULL; + ? xstrdup(res) : NULL; } else { str_int_fn sfn = (str_int_fn)fn; int_int_fn ifn = (int_int_fn)fn; diff --git a/src/nvim/os/dl.h b/src/nvim/os/dl.h index 302e4e6678..0787c7fe46 100644 --- a/src/nvim/os/dl.h +++ b/src/nvim/os/dl.h @@ -1,10 +1,5 @@ -#ifndef NVIM_OS_DL_H -#define NVIM_OS_DL_H - -#include <stdbool.h> -#include <stdint.h> +#pragma once #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/dl.h.generated.h" #endif -#endif // NVIM_OS_DL_H diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 0611de14aa..8620c79069 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // Environment inspection #include <assert.h> @@ -12,29 +9,33 @@ #include <uv.h> #include "auto/config.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" #include "nvim/eval.h" -#include "nvim/ex_cmds_defs.h" +#include "nvim/func_attr.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/log.h" -#include "nvim/macros.h" -#include "nvim/map.h" +#include "nvim/macros_defs.h" +#include "nvim/map_defs.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/option_defs.h" +#include "nvim/option_vars.h" +#include "nvim/os/fs.h" #include "nvim/os/os.h" #include "nvim/path.h" #include "nvim/strings.h" -#include "nvim/types.h" #include "nvim/version.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #ifdef MSWIN -# include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +# include "nvim/mbyte.h" +#endif + +#ifdef BACKSLASH_IN_FILENAME +# include "nvim/fileio.h" #endif #ifdef HAVE__NSGETENVIRON @@ -48,22 +49,6 @@ // Because `uv_os_getenv` requires allocating, we must manage a map to maintain // the behavior of `os_getenv`. static PMap(cstr_t) envmap = MAP_INIT; -static uv_mutex_t mutex; - -void env_init(void) -{ - uv_mutex_init(&mutex); -} - -void os_env_var_lock(void) -{ - uv_mutex_lock(&mutex); -} - -void os_env_var_unlock(void) -{ - uv_mutex_unlock(&mutex); -} /// Like getenv(), but returns NULL if the variable is empty. /// @see os_env_exists @@ -75,9 +60,8 @@ const char *os_getenv(const char *name) if (name[0] == '\0') { return NULL; } - uv_mutex_lock(&mutex); int r = 0; - if (pmap_has(cstr_t)(&envmap, name) + if (map_has(cstr_t, &envmap, name) && !!(e = (char *)pmap_get(cstr_t)(&envmap, name))) { if (e[0] != '\0') { // Found non-empty cached env var. @@ -101,8 +85,6 @@ const char *os_getenv(const char *name) } pmap_put(cstr_t)(&envmap, xstrdup(name), e); end: - // Must do this before ELOG, log.c may call os_setenv. - uv_mutex_unlock(&mutex); if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) { ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r)); } @@ -154,7 +136,6 @@ int os_setenv(const char *name, const char *value, int overwrite) return 0; } #endif - uv_mutex_lock(&mutex); int r; #ifdef MSWIN // libintl uses getenv() for LC_ALL/LANG/etc., so we must use _putenv_s(). @@ -169,8 +150,6 @@ int os_setenv(const char *name, const char *value, int overwrite) // Destroy the old map item. Do this AFTER uv_os_setenv(), because `value` // could be a previous os_getenv() result. pmap_del2(&envmap, name); - // Must do this before ELOG, log.c may call os_setenv. - uv_mutex_unlock(&mutex); if (r != 0) { ELOG("uv_os_setenv(%s) failed: %d %s", name, r, uv_err_name(r)); } @@ -184,11 +163,8 @@ int os_unsetenv(const char *name) if (name[0] == '\0') { return -1; } - uv_mutex_lock(&mutex); pmap_del2(&envmap, name); int r = uv_os_unsetenv(name); - // Must do this before ELOG, log.c may call os_setenv. - uv_mutex_unlock(&mutex); if (r != 0) { ELOG("uv_os_unsetenv(%s) failed: %d %s", name, r, uv_err_name(r)); } @@ -315,12 +291,11 @@ char *os_getenvname_at_index(size_t index) // Some Windows env vars start with =, so skip over that to find the // separator between name/value - const char * const end = strchr(utf8_str + (utf8_str[0] == '=' ? 1 : 0), - '='); + const char *const end = strchr(utf8_str + (utf8_str[0] == '=' ? 1 : 0), '='); assert(end != NULL); ptrdiff_t len = end - utf8_str; assert(len > 0); - name = xstrndup(utf8_str, (size_t)len); + name = xmemdupz(utf8_str, (size_t)len); xfree(utf8_str); break; } @@ -351,7 +326,7 @@ char *os_getenvname_at_index(size_t index) assert(end != NULL); ptrdiff_t len = end - str; assert(len > 0); - return xstrndup(str, (size_t)len); + return xmemdupz(str, (size_t)len); #endif } @@ -490,7 +465,7 @@ void init_homedir(void) // links. Don't do it when we can't return. if (os_dirname(os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) { if (!os_chdir(var) && os_dirname(IObuff, IOSIZE) == OK) { - var = (char *)IObuff; + var = IObuff; } if (os_chdir(os_buf) != 0) { emsg(_(e_prev_dir)); @@ -515,10 +490,8 @@ static char *os_homedir(void) { homedir_buf[0] = NUL; size_t homedir_size = MAXPATHL; - uv_mutex_lock(&mutex); // http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_homedir int ret_value = uv_os_homedir(homedir_buf, &homedir_size); - uv_mutex_unlock(&mutex); if (ret_value == 0 && homedir_size < MAXPATHL) { return homedir_buf; } @@ -599,7 +572,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es if (src[0] == '`' && src[1] == '=') { var = src; src += 2; - (void)skip_expr(&src); + (void)skip_expr(&src, NULL); if (*src == '`') { src++; } @@ -841,7 +814,7 @@ const void *vim_env_iter(const char delim, const char *const val, const void *co const char **const dir, size_t *const len) FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT { - const char *varval = (const char *)iter; + const char *varval = iter; if (varval == NULL) { varval = val; } @@ -872,7 +845,7 @@ const void *vim_env_iter_rev(const char delim, const char *const val, const void const char **const dir, size_t *const len) FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT { - const char *varend = (const char *)iter; + const char *varend = iter; if (varend == NULL) { varend = val + strlen(val) - 1; } @@ -956,10 +929,8 @@ char *vim_getenv(const char *name) // Find runtime path relative to the nvim binary: ../share/nvim/runtime if (vim_path == NULL) { vim_get_prefix_from_exepath(exe_name); - if (append_path(exe_name, - "share" _PATHSEPSTR "nvim" _PATHSEPSTR "runtime" _PATHSEPSTR, - MAXPATHL) == OK) { - vim_path = exe_name; // -V507 + if (append_path(exe_name, "share/nvim/runtime/", MAXPATHL) == OK) { + vim_path = exe_name; } } @@ -985,7 +956,7 @@ char *vim_getenv(const char *name) // check that the result is a directory name assert(vim_path_end >= vim_path); - vim_path = xstrndup(vim_path, (size_t)(vim_path_end - vim_path)); + vim_path = xmemdupz(vim_path, (size_t)(vim_path_end - vim_path)); if (!os_isdir(vim_path)) { xfree(vim_path); @@ -1056,7 +1027,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si } if (buf != NULL && buf->b_help) { - const size_t dlen = xstrlcpy(dst, path_tail((char *)src), dstlen); + const size_t dlen = xstrlcpy(dst, path_tail(src), dstlen); return MIN(dlen, dstlen - 1); } @@ -1094,7 +1065,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si } if (!one) { - src = skipwhite((char *)src); + src = skipwhite(src); } char *dst_p = dst; while (*src && dstlen > 0) { @@ -1107,7 +1078,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si // er's home directory)). char *p = homedir; size_t len = dirlen; - for (;;) { + while (true) { if (len && path_fnamencmp(src, p, len) == 0 && (vim_ispathsep(src[len]) diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index 5af39555c9..79d6ac08e7 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - /// @file fileio.c /// /// Buffered reading/writing to a file. Unlike fileio.c this is not dealing with @@ -18,14 +15,22 @@ #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/log.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/os/fileio.h" -#include "nvim/os/os.h" +#include "nvim/os/fs.h" #include "nvim/os/os_defs.h" #include "nvim/rbuffer.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" + +#ifdef MSWIN +# include "nvim/os/os_win_console.h" +#endif + +#ifdef HAVE_SYS_UIO_H +# include <sys/uio.h> +#endif #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fileio.c.generated.h" @@ -49,7 +54,6 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname, const int f { int os_open_flags = 0; TriState wr = kNone; - // -V:FLAG:501 #define FLAG(flags, flag, fcntl_flags, wrval, cond) \ do { \ if (flags & flag) { \ @@ -278,9 +282,10 @@ static char writebuf[kRWBufferSize]; /// /// @param[in,out] rv RBuffer instance used. /// @param[in,out] fp File to work with. -static void file_rb_write_full_cb(RBuffer *const rv, FileDescriptor *const fp) +static void file_rb_write_full_cb(RBuffer *const rv, void *const fp_in) FUNC_ATTR_NONNULL_ALL { + FileDescriptor *const fp = fp_in; assert(fp->wr); assert(rv->data == (void *)fp); if (rbuffer_size(rv) == 0) { diff --git a/src/nvim/os/fileio.h b/src/nvim/os/fileio.h index 5e47bbf921..72e7984c8a 100644 --- a/src/nvim/os/fileio.h +++ b/src/nvim/os/fileio.h @@ -1,5 +1,4 @@ -#ifndef NVIM_OS_FILEIO_H -#define NVIM_OS_FILEIO_H +#pragma once #include <stdbool.h> #include <stddef.h> @@ -75,4 +74,3 @@ enum { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fileio.h.generated.h" #endif -#endif // NVIM_OS_FILEIO_H diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index 302faa8140..8f939c3b40 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // fs.c -- filesystem access #include <assert.h> #include <errno.h> @@ -12,79 +9,75 @@ #include <stdlib.h> #include <string.h> #include <sys/stat.h> +#include <sys/types.h> +#include <uv.h> + +#ifdef MSWIN +# include <shlobj.h> +#endif #include "auto/config.h" -#include "nvim/gettext.h" -#include "nvim/globals.h" -#include "nvim/log.h" -#include "nvim/macros.h" -#include "nvim/option_defs.h" -#include "nvim/os/fs_defs.h" -#include "nvim/types.h" -#include "nvim/vim.h" +#include "nvim/func_attr.h" +#include "nvim/os/fs.h" -#ifdef HAVE_SYS_UIO_H -# include <sys/uio.h> +#if defined(HAVE_ACL) +# ifdef HAVE_SYS_ACL_H +# include <sys/acl.h> +# endif +# ifdef HAVE_SYS_ACCESS_H +# include <sys/access.h> +# endif #endif -#include <uv.h> +#ifdef HAVE_XATTR +# include <sys/xattr.h> +#endif -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" +#include "nvim/gettext.h" +#include "nvim/globals.h" +#include "nvim/log.h" +#include "nvim/macros_defs.h" #include "nvim/memory.h" #include "nvim/message.h" +#include "nvim/option_vars.h" #include "nvim/os/os.h" #include "nvim/path.h" +#include "nvim/types_defs.h" +#include "nvim/vim_defs.h" -struct iovec; +#ifdef HAVE_SYS_UIO_H +# include <sys/uio.h> +#endif #ifdef MSWIN -# include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +# include "nvim/mbyte.h" +# include "nvim/option.h" +# include "nvim/strings.h" #endif #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fs.c.generated.h" #endif +#ifdef HAVE_XATTR +static const char e_xattr_erange[] + = N_("E1506: Buffer too small to copy xattr value or key"); +static const char e_xattr_e2big[] + = N_("E1508: Size of the extended attribute value is larger than the maximum size allowed"); +static const char e_xattr_other[] + = N_("E1509: Error occurred when reading or writing extended attribute"); +#endif + #define RUN_UV_FS_FUNC(ret, func, ...) \ do { \ - bool did_try_to_free = false; \ -uv_call_start: {} \ uv_fs_t req; \ - fs_loop_lock(); \ - ret = func(&fs_loop, &req, __VA_ARGS__); \ + ret = func(NULL, &req, __VA_ARGS__); \ uv_fs_req_cleanup(&req); \ - fs_loop_unlock(); \ - if (ret == UV_ENOMEM && !did_try_to_free) { \ - try_to_free_memory(); \ - did_try_to_free = true; \ - goto uv_call_start; \ - } \ } while (0) // Many fs functions from libuv return that value on success. static const int kLibuvSuccess = 0; -static uv_loop_t fs_loop; -static uv_mutex_t fs_loop_mutex; - -// Initialize the fs module -void fs_init(void) -{ - uv_loop_init(&fs_loop); - uv_mutex_init_recursive(&fs_loop_mutex); -} - -/// TODO(bfredl): some of these operations should -/// be possible to do the private libuv loop of the -/// thread, instead of contending the global fs loop -void fs_loop_lock(void) -{ - uv_mutex_lock(&fs_loop_mutex); -} - -void fs_loop_unlock(void) -{ - uv_mutex_unlock(&fs_loop_mutex); -} /// Changes the current directory to `path`. /// @@ -94,7 +87,7 @@ int os_chdir(const char *path) { if (p_verbose >= 5) { verbose_enter(); - smsg("chdir(%s)", path); + smsg(0, "chdir(%s)", path); verbose_leave(); } return uv_chdir(path); @@ -123,12 +116,9 @@ bool os_isrealdir(const char *name) FUNC_ATTR_NONNULL_ALL { uv_fs_t request; - fs_loop_lock(); - if (uv_fs_lstat(&fs_loop, &request, name, NULL) != kLibuvSuccess) { - fs_loop_unlock(); + if (uv_fs_lstat(NULL, &request, name, NULL) != kLibuvSuccess) { return false; } - fs_loop_unlock(); if (S_ISLNK(request.statbuf.st_mode)) { return false; } @@ -146,11 +136,7 @@ bool os_isdir(const char *name) return false; } - if (!S_ISDIR(mode)) { - return false; - } - - return true; + return S_ISDIR(mode); } /// Check what `name` is: @@ -377,7 +363,7 @@ static bool is_executable_in_path(const char *name, char **abspath) // is an executable file. char *p = path; bool rv = false; - for (;;) { + while (true) { char *e = xstrchrnul(p, ENV_SEPCHAR); // Combine the $PATH segment with `name`. @@ -571,7 +557,6 @@ ptrdiff_t os_read(const int fd, bool *const ret_eof, char *const ret_buf, const return 0; } size_t read_bytes = 0; - bool did_try_to_free = false; while (read_bytes != size) { assert(size >= read_bytes); const ptrdiff_t cur_read_bytes = read(fd, ret_buf + read_bytes, @@ -586,10 +571,6 @@ ptrdiff_t os_read(const int fd, bool *const ret_eof, char *const ret_buf, const break; } else if (error == UV_EINTR || error == UV_EAGAIN) { continue; - } else if (error == UV_ENOMEM && !did_try_to_free) { - try_to_free_memory(); - did_try_to_free = true; - continue; } else { return (ptrdiff_t)error; } @@ -623,7 +604,6 @@ ptrdiff_t os_readv(const int fd, bool *const ret_eof, struct iovec *iov, size_t { *ret_eof = false; size_t read_bytes = 0; - bool did_try_to_free = false; size_t toread = 0; for (size_t i = 0; i < iov_size; i++) { // Overflow, trying to read too much data @@ -655,10 +635,6 @@ ptrdiff_t os_readv(const int fd, bool *const ret_eof, struct iovec *iov, size_t break; } else if (error == UV_EINTR || error == UV_EAGAIN) { continue; - } else if (error == UV_ENOMEM && !did_try_to_free) { - try_to_free_memory(); - did_try_to_free = true; - continue; } else { return (ptrdiff_t)error; } @@ -747,9 +723,7 @@ static int os_stat(const char *name, uv_stat_t *statbuf) return UV_EINVAL; } uv_fs_t request; - fs_loop_lock(); - int result = uv_fs_stat(&fs_loop, &request, name, NULL); - fs_loop_unlock(); + int result = uv_fs_stat(NULL, &request, name, NULL); if (result == kLibuvSuccess) { *statbuf = request.statbuf; } @@ -781,13 +755,84 @@ int os_setperm(const char *const name, int perm) return (r == kLibuvSuccess ? OK : FAIL); } -#if defined(HAVE_ACL) -# ifdef HAVE_SYS_ACL_H -# include <sys/acl.h> -# endif -# ifdef HAVE_SYS_ACCESS_H -# include <sys/access.h> -# endif +#ifdef HAVE_XATTR +/// Copy extended attributes from_file to to_file +void os_copy_xattr(const char *from_file, const char *to_file) +{ + if (from_file == NULL) { + return; + } + + // get the length of the extended attributes + ssize_t size = listxattr((char *)from_file, NULL, 0); + // not supported or no attributes to copy + if (errno == ENOTSUP || size <= 0) { + return; + } + char *xattr_buf = xmalloc((size_t)size); + size = listxattr(from_file, xattr_buf, (size_t)size); + ssize_t tsize = size; + + errno = 0; + + ssize_t max_vallen = 0; + char *val = NULL; + const char *errmsg = NULL; + + for (int round = 0; round < 2; round++) { + char *key = xattr_buf; + if (round == 1) { + size = tsize; + } + + while (size > 0) { + ssize_t vallen = getxattr(from_file, key, val, round ? (size_t)max_vallen : 0); + // only set the attribute in the second round + if (vallen >= 0 && round + && setxattr(to_file, key, val, (size_t)vallen, 0) == 0) { + // + } else if (errno) { + switch (errno) { + case E2BIG: + errmsg = e_xattr_e2big; + goto error_exit; + case ENOTSUP: + case EACCES: + case EPERM: + break; + case ERANGE: + errmsg = e_xattr_erange; + goto error_exit; + default: + errmsg = e_xattr_other; + goto error_exit; + } + } + + if (round == 0 && vallen > max_vallen) { + max_vallen = vallen; + } + + // add one for terminating null + ssize_t keylen = (ssize_t)strlen(key) + 1; + size -= keylen; + key += keylen; + } + if (round) { + break; + } + + val = xmalloc((size_t)max_vallen + 1); + } +error_exit: + xfree(xattr_buf); + xfree(val); + + if (errmsg != NULL) { + emsg(_(errmsg)); + } +} +#endif // Return a pointer to the ACL of file "fname" in allocated memory. // Return NULL if the ACL is not available for whatever reason. @@ -811,7 +856,6 @@ void os_free_acl(vim_acl_T aclent) return; } } -#endif #ifdef UNIX /// Checks if the current user owns a file. @@ -942,10 +986,13 @@ int os_mkdir(const char *path, int32_t mode) /// the name of the directory which os_mkdir_recurse /// failed to create. I.e. it will contain dir or any /// of the higher level directories. +/// @param[out] created Set to the full name of the first created directory. +/// It will be NULL until that happens. /// /// @return `0` for success, libuv error code for failure. -int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_dir) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_dir, + char **const created) + FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT { // Get end of directory name in "dir". // We're done when it's "/" or "c:/". @@ -980,6 +1027,8 @@ int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_di if ((ret = os_mkdir(curdir, mode)) != 0) { *failed_dir = curdir; return ret; + } else if (created != NULL && *created == NULL) { + *created = FullName_save(curdir, false); } } xfree(curdir); @@ -1007,7 +1056,7 @@ int os_file_mkdir(char *fname, int32_t mode) *tail = NUL; int r; char *failed_dir; - if (((r = os_mkdir_recurse(fname, mode, &failed_dir)) < 0)) { + if (((r = os_mkdir_recurse(fname, mode, &failed_dir, NULL)) < 0)) { semsg(_(e_mkdir), failed_dir, os_strerror(r)); xfree(failed_dir); } @@ -1019,18 +1068,16 @@ int os_file_mkdir(char *fname, int32_t mode) /// Create a unique temporary directory. /// -/// @param[in] template Template of the path to the directory with XXXXXX -/// which would be replaced by random chars. +/// @param[in] templ Template of the path to the directory with XXXXXX +/// which would be replaced by random chars. /// @param[out] path Path to created directory for success, undefined for /// failure. /// @return `0` for success, non-zero for failure. -int os_mkdtemp(const char *template, char *path) +int os_mkdtemp(const char *templ, char *path) FUNC_ATTR_NONNULL_ALL { uv_fs_t request; - fs_loop_lock(); - int result = uv_fs_mkdtemp(&fs_loop, &request, template, NULL); - fs_loop_unlock(); + int result = uv_fs_mkdtemp(NULL, &request, templ, NULL); if (result == kLibuvSuccess) { xstrlcpy(path, request.path, TEMP_FILE_PATH_MAXLEN); } @@ -1057,9 +1104,7 @@ int os_rmdir(const char *path) bool os_scandir(Directory *dir, const char *path) FUNC_ATTR_NONNULL_ALL { - fs_loop_lock(); - int r = uv_fs_scandir(&fs_loop, &dir->request, path, 0, NULL); - fs_loop_unlock(); + int r = uv_fs_scandir(NULL, &dir->request, path, 0, NULL); if (r < 0) { os_closedir(dir); } @@ -1120,9 +1165,7 @@ bool os_fileinfo_link(const char *path, FileInfo *file_info) return false; } uv_fs_t request; - fs_loop_lock(); - bool ok = uv_fs_lstat(&fs_loop, &request, path, NULL) == kLibuvSuccess; - fs_loop_unlock(); + bool ok = uv_fs_lstat(NULL, &request, path, NULL) == kLibuvSuccess; if (ok) { file_info->stat = request.statbuf; } @@ -1140,8 +1183,7 @@ bool os_fileinfo_fd(int file_descriptor, FileInfo *file_info) { uv_fs_t request; CLEAR_POINTER(file_info); - fs_loop_lock(); - bool ok = uv_fs_fstat(&fs_loop, + bool ok = uv_fs_fstat(NULL, &request, file_descriptor, NULL) == kLibuvSuccess; @@ -1149,7 +1191,6 @@ bool os_fileinfo_fd(int file_descriptor, FileInfo *file_info) file_info->stat = request.statbuf; } uv_fs_req_cleanup(&request); - fs_loop_unlock(); return ok; } @@ -1266,8 +1307,7 @@ char *os_realpath(const char *name, char *buf) FUNC_ATTR_NONNULL_ARG(1) { uv_fs_t request; - fs_loop_lock(); - int result = uv_fs_realpath(&fs_loop, &request, name, NULL); + int result = uv_fs_realpath(NULL, &request, name, NULL); if (result == kLibuvSuccess) { if (buf == NULL) { buf = xmallocz(MAXPATHL); @@ -1275,13 +1315,10 @@ char *os_realpath(const char *name, char *buf) xstrlcpy(buf, request.ptr, MAXPATHL + 1); } uv_fs_req_cleanup(&request); - fs_loop_unlock(); return result == kLibuvSuccess ? buf : NULL; } #ifdef MSWIN -# include <shlobj.h> - /// When "fname" is the name of a shortcut (*.lnk) resolve the file it points /// to and return that name in allocated memory. /// Otherwise NULL is returned. diff --git a/src/nvim/os/fs.h b/src/nvim/os/fs.h index 75c24b8db2..56dd657f70 100644 --- a/src/nvim/os/fs.h +++ b/src/nvim/os/fs.h @@ -1,10 +1,13 @@ -#ifndef NVIM_OS_FS_H -#define NVIM_OS_FS_H +#pragma once -#include "nvim/os/fs_defs.h" -#include "nvim/types.h" +#include <stddef.h> // IWYU pragma: keep +#include <stdint.h> // IWYU pragma: keep +#include <stdio.h> // IWYU pragma: keep +#include <uv.h> // IWYU pragma: keep + +#include "nvim/os/fs_defs.h" // IWYU pragma: export +#include "nvim/types_defs.h" // IWYU pragma: keep #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/fs.h.generated.h" #endif -#endif // NVIM_OS_FS_H diff --git a/src/nvim/os/fs_defs.h b/src/nvim/os/fs_defs.h index f4929b12b1..e5355ddefd 100644 --- a/src/nvim/os/fs_defs.h +++ b/src/nvim/os/fs_defs.h @@ -1,5 +1,4 @@ -#ifndef NVIM_OS_FS_DEFS_H -#define NVIM_OS_FS_DEFS_H +#pragma once #include <uv.h> @@ -26,5 +25,3 @@ typedef struct { #define NODE_WRITABLE 1 // something we can write to (character // device, fifo, socket, ..) #define NODE_OTHER 2 // non-writable thing (e.g., block device) - -#endif // NVIM_OS_FS_DEFS_H diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 759b3cf83c..f3bd1c7ed9 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <assert.h> #include <stdbool.h> #include <stdint.h> @@ -9,28 +6,28 @@ #include <uv.h> #include "nvim/api/private/defs.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" -#include "nvim/buffer_defs.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/event/rstream.h" #include "nvim/event/stream.h" +#include "nvim/func_attr.h" #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/keycodes.h" #include "nvim/log.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/main.h" #include "nvim/msgpack_rpc/channel.h" -#include "nvim/option_defs.h" +#include "nvim/option_vars.h" #include "nvim/os/input.h" +#include "nvim/os/os_defs.h" #include "nvim/os/time.h" #include "nvim/profile.h" #include "nvim/rbuffer.h" #include "nvim/state.h" -#include "nvim/vim.h" #define READ_BUFFER_SIZE 0xfff #define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4) @@ -242,8 +239,8 @@ bool os_isatty(int fd) size_t input_enqueue(String keys) { - char *ptr = keys.data; - char *end = ptr + keys.size; + const char *ptr = keys.data; + const char *end = ptr + keys.size; while (rbuffer_space(input_buffer) >= 19 && ptr < end) { // A "<x>" form occupies at least 1 characters, and produces up @@ -253,9 +250,8 @@ size_t input_enqueue(String keys) // K_SPECIAL(0x80). uint8_t buf[19] = { 0 }; // Do not simplify the keys here. Simplification will be done later. - unsigned int new_size - = trans_special((const char **)&ptr, (size_t)(end - ptr), (char *)buf, FSK_KEYCODE, true, - NULL); + unsigned new_size + = trans_special(&ptr, (size_t)(end - ptr), (char *)buf, FSK_KEYCODE, true, NULL); if (new_size) { new_size = handle_mouse_event(&ptr, buf, new_size); @@ -264,7 +260,7 @@ size_t input_enqueue(String keys) } if (*ptr == '<') { - char *old_ptr = ptr; + const char *old_ptr = ptr; // Invalid or incomplete key sequence, skip until the next '>' or *end. do { ptr++; @@ -346,7 +342,7 @@ static uint8_t check_multiclick(int code, int grid, int row, int col) // Mouse event handling code(Extract row/col if available and detect multiple // clicks) -static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, unsigned int bufsize) +static unsigned handle_mouse_event(const char **ptr, uint8_t *buf, unsigned bufsize) { int mouse_code = 0; int type = 0; @@ -441,7 +437,7 @@ bool input_blocking(void) // This is a replacement for the old `WaitForChar` function in os_unix.c static InbufPollResult inbuf_poll(int ms, MultiQueue *events) { - if (input_ready(events)) { + if (os_input_ready(events)) { return kInputAvail; } @@ -457,24 +453,19 @@ static InbufPollResult inbuf_poll(int ms, MultiQueue *events) DLOG("blocking... events_enabled=%d events_pending=%d", events != NULL, events && !multiqueue_empty(events)); LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, ms, - input_ready(events) || input_eof); + os_input_ready(events) || input_eof); blocking = false; if (do_profiling == PROF_YES && ms) { prof_inchar_exit(); } - if (input_ready(events)) { + if (os_input_ready(events)) { return kInputAvail; } return input_eof ? kInputEof : kInputNone; } -void input_done(void) -{ - input_eof = true; -} - bool input_available(void) { return rbuffer_size(input_buffer) != 0; @@ -483,7 +474,7 @@ bool input_available(void) static void input_read_cb(Stream *stream, RBuffer *buf, size_t c, void *data, bool at_eof) { if (at_eof) { - input_done(); + input_eof = true; } assert(rbuffer_space(input_buffer) >= rbuffer_size(buf)); @@ -535,8 +526,8 @@ static int push_event_key(uint8_t *buf, int maxlen) return buf_idx; } -// Check if there's pending input -static bool input_ready(MultiQueue *events) +/// Check if there's pending input already in typebuf or `events` +bool os_input_ready(MultiQueue *events) { return (typebuf_was_filled // API call filled typeahead || rbuffer_size(input_buffer) // Input buffer filled @@ -550,8 +541,7 @@ static void read_error_exit(void) if (silent_mode) { // Normal way to exit for "nvim -es". getout(0); } - STRCPY(IObuff, _("Vim: Error reading input, exiting...\n")); - preserve_exit(); + preserve_exit(_("Vim: Error reading input, exiting...\n")); } static bool pending_events(MultiQueue *events) diff --git a/src/nvim/os/input.h b/src/nvim/os/input.h index 6f25efdc7b..4b104b0b50 100644 --- a/src/nvim/os/input.h +++ b/src/nvim/os/input.h @@ -1,15 +1,14 @@ -#ifndef NVIM_OS_INPUT_H -#define NVIM_OS_INPUT_H +#pragma once #include <stdbool.h> -#include <stdint.h> +#include <stdint.h> // IWYU pragma: keep -#include "nvim/api/private/defs.h" +#include "nvim/api/private/defs.h" // IWYU pragma: keep #include "nvim/event/multiqueue.h" +#include "nvim/macros_defs.h" -EXTERN bool used_stdin INIT(= false); +EXTERN bool used_stdin INIT( = false); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/input.h.generated.h" #endif -#endif // NVIM_OS_INPUT_H diff --git a/src/nvim/os/lang.c b/src/nvim/os/lang.c index 57c82bba86..17d179a56a 100644 --- a/src/nvim/os/lang.c +++ b/src/nvim/os/lang.c @@ -1,22 +1,341 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #ifdef __APPLE__ # define Boolean CFBoolean // Avoid conflict with API's Boolean # define FileInfo CSFileInfo // Avoid conflict with API's Fileinfo # include <CoreServices/CoreServices.h> + # undef Boolean # undef FileInfo +#endif -# include "auto/config.h" -# ifdef HAVE_LOCALE_H -# include <locale.h> -# endif -# include "nvim/os/os.h" +#include <locale.h> +#include <stdbool.h> +#include <stdio.h> +#include "auto/config.h" +#include "nvim/ascii_defs.h" +#include "nvim/buffer.h" +#include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" +#include "nvim/eval.h" +#include "nvim/ex_cmds_defs.h" +#include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/macros_defs.h" +#include "nvim/memory.h" +#include "nvim/message.h" +#include "nvim/option.h" +#include "nvim/os/lang.h" +#include "nvim/os/os.h" +#include "nvim/os/shell.h" +#include "nvim/path.h" +#include "nvim/profile.h" +#include "nvim/vim_defs.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "os/lang.c.generated.h" #endif -#include "nvim/os/lang.h" +static char *get_locale_val(int what) +{ + // Obtain the locale value from the libraries. + char *loc = setlocale(what, NULL); + + return loc; +} + +/// @return true when "lang" starts with a valid language name. +/// Rejects NULL, empty string, "C", "C.UTF-8" and others. +static bool is_valid_mess_lang(const char *lang) +{ + return lang != NULL && ASCII_ISALPHA(lang[0]) && ASCII_ISALPHA(lang[1]); +} + +/// Obtain the current messages language. Used to set the default for +/// 'helplang'. May return NULL or an empty string. +char *get_mess_lang(void) +{ + char *p; + +#if defined(LC_MESSAGES) + p = get_locale_val(LC_MESSAGES); +#else + // This is necessary for Win32, where LC_MESSAGES is not defined and $LANG + // may be set to the LCID number. LC_COLLATE is the best guess, LC_TIME + // and LC_MONETARY may be set differently for a Japanese working in the + // US. + p = get_locale_val(LC_COLLATE); +#endif + return is_valid_mess_lang(p) ? p : NULL; +} + +/// Get the language used for messages from the environment. +/// +/// This uses LC_MESSAGES when available, which it is for most systems we build for +/// except for windows. Then fallback to get the value from the environment +/// ourselves, and use LC_CTYPE as a last resort. +static char *get_mess_env(void) +{ +#ifdef LC_MESSAGES + return get_locale_val(LC_MESSAGES); +#else + char *p = (char *)os_getenv("LC_ALL"); + if (p == NULL) { + p = (char *)os_getenv("LC_MESSAGES"); + if (p == NULL) { + p = (char *)os_getenv("LANG"); + if (p != NULL && ascii_isdigit(*p)) { + p = NULL; // ignore something like "1043" + } + if (p == NULL) { + p = get_locale_val(LC_CTYPE); + } + } + } + return p; +#endif +} + +/// Set the "v:lang" variable according to the current locale setting. +/// Also do "v:lc_time"and "v:ctype". +void set_lang_var(void) +{ + const char *loc; + + loc = get_locale_val(LC_CTYPE); + set_vim_var_string(VV_CTYPE, loc, -1); + + loc = get_mess_env(); + set_vim_var_string(VV_LANG, loc, -1); + + loc = get_locale_val(LC_TIME); + set_vim_var_string(VV_LC_TIME, loc, -1); + + loc = get_locale_val(LC_COLLATE); + set_vim_var_string(VV_COLLATE, loc, -1); +} + +/// Setup to use the current locale (for ctype() and many other things). +void init_locale(void) +{ + setlocale(LC_ALL, ""); + +#ifdef LC_NUMERIC + // Make sure strtod() uses a decimal point, not a comma. + setlocale(LC_NUMERIC, "C"); +#endif + + char localepath[MAXPATHL] = { 0 }; + snprintf(localepath, sizeof(localepath), "%s", get_vim_var_str(VV_PROGPATH)); + char *tail = path_tail_with_sep(localepath); + *tail = NUL; + tail = path_tail(localepath); + xstrlcpy(tail, "share/locale", + sizeof(localepath) - (size_t)(tail - localepath)); + bindtextdomain(PROJECT_NAME, localepath); + textdomain(PROJECT_NAME); + TIME_MSG("locale set"); +} + +/// ":language": Set the language (locale). +/// +/// @param eap +void ex_language(exarg_T *eap) +{ + char *loc; + char *p; + char *name; + int what = LC_ALL; + char *whatstr = ""; +#ifdef LC_MESSAGES +# define VIM_LC_MESSAGES LC_MESSAGES +#else +# define VIM_LC_MESSAGES 6789 +#endif + + name = eap->arg; + + // Check for "messages {name}", "ctype {name}" or "time {name}" argument. + // Allow abbreviation, but require at least 3 characters to avoid + // confusion with a two letter language name "me" or "ct". + p = skiptowhite(eap->arg); + if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) { + if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) { + what = VIM_LC_MESSAGES; + name = skipwhite(p); + whatstr = "messages "; + } else if (STRNICMP(eap->arg, "ctype", p - eap->arg) == 0) { + what = LC_CTYPE; + name = skipwhite(p); + whatstr = "ctype "; + } else if (STRNICMP(eap->arg, "time", p - eap->arg) == 0) { + what = LC_TIME; + name = skipwhite(p); + whatstr = "time "; + } else if (STRNICMP(eap->arg, "collate", p - eap->arg) == 0) { + what = LC_COLLATE; + name = skipwhite(p); + whatstr = "collate "; + } + } + + if (*name == NUL) { + if (what == VIM_LC_MESSAGES) { + p = get_mess_env(); + } else { + p = setlocale(what, NULL); + } + if (p == NULL || *p == NUL) { + p = "Unknown"; + } + smsg(0, _("Current %slanguage: \"%s\""), whatstr, p); + } else { +#ifndef LC_MESSAGES + if (what == VIM_LC_MESSAGES) { + loc = ""; + } else { +#endif + loc = setlocale(what, name); +#ifdef LC_NUMERIC + // Make sure strtod() uses a decimal point, not a comma. + setlocale(LC_NUMERIC, "C"); +#endif +#ifndef LC_MESSAGES + } +#endif + if (loc == NULL) { + semsg(_("E197: Cannot set language to \"%s\""), name); + } else { +#ifdef HAVE_NL_MSG_CAT_CNTR + // Need to do this for GNU gettext, otherwise cached translations + // will be used again. + extern int _nl_msg_cat_cntr; // NOLINT(bugprone-reserved-identifier) + + _nl_msg_cat_cntr++; +#endif + // Reset $LC_ALL, otherwise it would overrule everything. + os_setenv("LC_ALL", "", 1); + + if (what != LC_TIME && what != LC_COLLATE) { + // Tell gettext() what to translate to. It apparently doesn't + // use the currently effective locale. + if (what == LC_ALL) { + os_setenv("LANG", name, 1); + + // Clear $LANGUAGE because GNU gettext uses it. + os_setenv("LANGUAGE", "", 1); + } + if (what != LC_CTYPE) { + os_setenv("LC_MESSAGES", name, 1); + set_helplang_default(name); + } + } + + // Set v:lang, v:lc_time, v:collate and v:ctype to the final result. + set_lang_var(); + maketitle(); + } + } +} + +static char **locales = NULL; // Array of all available locales + +#ifndef MSWIN +static bool did_init_locales = false; + +/// @return an array of strings for all available locales + NULL for the +/// last element or, +/// NULL in case of error. +static char **find_locales(void) +{ + garray_T locales_ga; + char *loc; + char *saveptr = NULL; + + // Find all available locales by running command "locale -a". If this + // doesn't work we won't have completion. + char *locale_a = get_cmd_output("locale -a", NULL, kShellOptSilent, NULL); + if (locale_a == NULL) { + return NULL; + } + ga_init(&locales_ga, sizeof(char *), 20); + + // Transform locale_a string where each locale is separated by "\n" + // into an array of locale strings. + loc = os_strtok(locale_a, "\n", &saveptr); + + while (loc != NULL) { + loc = xstrdup(loc); + GA_APPEND(char *, &locales_ga, loc); + loc = os_strtok(NULL, "\n", &saveptr); + } + xfree(locale_a); + // Guarantee that .ga_data is NULL terminated + ga_grow(&locales_ga, 1); + ((char **)locales_ga.ga_data)[locales_ga.ga_len] = NULL; + return locales_ga.ga_data; +} +#endif + +/// Lazy initialization of all available locales. +static void init_locales(void) +{ +#ifndef MSWIN + if (did_init_locales) { + return; + } + + did_init_locales = true; + locales = find_locales(); +#endif +} + +#if defined(EXITFREE) +void free_locales(void) +{ + if (locales == NULL) { + return; + } + + for (int i = 0; locales[i] != NULL; i++) { + xfree(locales[i]); + } + XFREE_CLEAR(locales); +} +#endif + +/// Function given to ExpandGeneric() to obtain the possible arguments of the +/// ":language" command. +char *get_lang_arg(expand_T *xp, int idx) +{ + if (idx == 0) { + return "messages"; + } + if (idx == 1) { + return "ctype"; + } + if (idx == 2) { + return "time"; + } + if (idx == 3) { + return "collate"; + } + + init_locales(); + if (locales == NULL) { + return NULL; + } + return locales[idx - 4]; +} + +/// Function given to ExpandGeneric() to obtain the available locales. +char *get_locales(expand_T *xp, int idx) +{ + init_locales(); + if (locales == NULL) { + return NULL; + } + return locales[idx]; +} void lang_init(void) { diff --git a/src/nvim/os/lang.h b/src/nvim/os/lang.h index f60e064f57..4e7bf82195 100644 --- a/src/nvim/os/lang.h +++ b/src/nvim/os/lang.h @@ -1,7 +1,9 @@ -#ifndef NVIM_OS_LANG_H -#define NVIM_OS_LANG_H +#pragma once + +#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep +#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep +#include "nvim/types_defs.h" // IWYU pragma: keep #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/lang.h.generated.h" #endif -#endif // NVIM_OS_LANG_H diff --git a/src/nvim/os/mem.c b/src/nvim/os/mem.c index 0b7e8065ef..3e6264c691 100644 --- a/src/nvim/os/mem.c +++ b/src/nvim/os/mem.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - /// Functions for accessing system memory information. #include <stdint.h> diff --git a/src/nvim/os/nvim.manifest b/src/nvim/os/nvim.manifest index 8878822a5d..571b7f4580 100644 --- a/src/nvim/os/nvim.manifest +++ b/src/nvim/os/nvim.manifest @@ -17,4 +17,9 @@ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> </application> </compatibility> + <asmv3:application> + <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings"> + <activeCodePage>UTF-8</activeCodePage> + </asmv3:windowsSettings> + </asmv3:application> </assembly> diff --git a/src/nvim/os/os.h b/src/nvim/os/os.h index a7496130cc..302d84d066 100644 --- a/src/nvim/os/os.h +++ b/src/nvim/os/os.h @@ -1,22 +1,33 @@ -#ifndef NVIM_OS_OS_H -#define NVIM_OS_OS_H +#pragma once -#include <stdbool.h> -#include <uv.h> +#include <stddef.h> // IWYU pragma: keep +#include <stdint.h> // IWYU pragma: keep +#include <uv.h> // IWYU pragma: keep -#include "nvim/os/fs_defs.h" -#include "nvim/os/stdpaths_defs.h" -#include "nvim/vim.h" +#include "nvim/buffer_defs.h" // IWYU pragma: keep +#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep +#include "nvim/garray_defs.h" // IWYU pragma: keep +#include "nvim/os/os_defs.h" // IWYU pragma: export +#include "nvim/os/stdpaths_defs.h" // IWYU pragma: keep + +#define HAVE_PATHDEF + +// Some file names are stored in pathdef.c, which is generated from the +// Makefile to make their value depend on the Makefile. +#ifdef HAVE_PATHDEF +extern char *default_vim_dir; +extern char *default_vimruntime_dir; +extern char *default_lib_dir; +#endif #ifdef INCLUDE_GENERATED_DECLARATIONS +// IWYU pragma: begin_exports # include "os/env.h.generated.h" -# include "os/fs.h.generated.h" # include "os/mem.h.generated.h" # include "os/stdpaths.h.generated.h" # include "os/users.h.generated.h" +// IWYU pragma: end_exports #endif #define ENV_LOGFILE "NVIM_LOG_FILE" #define ENV_NVIM "NVIM" - -#endif // NVIM_OS_OS_H diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index a30e16eeba..12de55a227 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -1,5 +1,4 @@ -#ifndef NVIM_OS_OS_DEFS_H -#define NVIM_OS_OS_DEFS_H +#pragma once #include <ctype.h> #include <stdio.h> @@ -7,12 +6,26 @@ #include <sys/stat.h> #include <sys/types.h> +#include "auto/config.h" + +// Note: Some systems need both string.h and strings.h (Savage). +#include <string.h> +#ifdef HAVE_STRINGS_H +# include <strings.h> // IWYU pragma: export +#endif + #ifdef MSWIN # include "nvim/os/win_defs.h" #else # include "nvim/os/unix_defs.h" #endif +#ifdef BACKSLASH_IN_FILENAME +# define BACKSLASH_IN_FILENAME_BOOL true +#else +# define BACKSLASH_IN_FILENAME_BOOL false +#endif + #if !defined(NAME_MAX) && defined(_XOPEN_NAME_MAX) # define NAME_MAX _XOPEN_NAME_MAX #endif @@ -30,12 +43,7 @@ // Command-processing buffer. Use large buffers for all platforms. #define CMDBUFFSIZE 1024 -// Note: Some systems need both string.h and strings.h (Savage). However, -// some systems can't handle both, only use string.h in that case. -#include <string.h> -#if defined(HAVE_STRINGS_H) && !defined(NO_STRINGS_WITH_STRING_H) -# include <strings.h> -#endif +#define ROOT_UID 0 /// Converts libuv error (negative int) to error description string. #define os_strerror uv_strerror @@ -52,52 +60,56 @@ // stat macros #ifndef S_ISDIR # ifdef S_IFDIR -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# define S_ISDIR(m) (((m)& S_IFMT) == S_IFDIR) # else # define S_ISDIR(m) 0 # endif #endif #ifndef S_ISREG # ifdef S_IFREG -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# define S_ISREG(m) (((m)& S_IFMT) == S_IFREG) # else # define S_ISREG(m) 0 # endif #endif #ifndef S_ISBLK # ifdef S_IFBLK -# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) +# define S_ISBLK(m) (((m)& S_IFMT) == S_IFBLK) # else # define S_ISBLK(m) 0 # endif #endif #ifndef S_ISSOCK # ifdef S_IFSOCK -# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +# define S_ISSOCK(m) (((m)& S_IFMT) == S_IFSOCK) # else # define S_ISSOCK(m) 0 # endif #endif #ifndef S_ISFIFO # ifdef S_IFIFO -# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) +# define S_ISFIFO(m) (((m)& S_IFMT) == S_IFIFO) # else # define S_ISFIFO(m) 0 # endif #endif #ifndef S_ISCHR # ifdef S_IFCHR -# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# define S_ISCHR(m) (((m)& S_IFMT) == S_IFCHR) # else # define S_ISCHR(m) 0 # endif #endif #ifndef S_ISLNK # ifdef S_IFLNK -# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +# define S_ISLNK(m) (((m)& S_IFMT) == S_IFLNK) # else # define S_ISLNK(m) 0 # endif #endif -#endif // NVIM_OS_OS_DEFS_H +// BSD is supposed to cover FreeBSD and similar systems. +#if (defined(BSD) || defined(__FreeBSD_kernel__)) \ + && (defined(S_ISCHR) || defined(S_IFCHR)) +# define OPEN_CHR_FILES +#endif diff --git a/src/nvim/os/os_win_console.c b/src/nvim/os/os_win_console.c index 006e27d28f..816e81e997 100644 --- a/src/nvim/os/os_win_console.c +++ b/src/nvim/os/os_win_console.c @@ -1,10 +1,10 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +#include <string.h> +#include "nvim/globals.h" +#include "nvim/os/fs.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/os_win_console.h" -#include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/os_win_console.c.generated.h" @@ -83,7 +83,7 @@ void os_icon_init(void) const char *vimruntime = os_getenv("VIMRUNTIME"); if (vimruntime != NULL) { - snprintf(NameBuff, MAXPATHL, "%s" _PATHSEPSTR "neovim.ico", vimruntime); + snprintf(NameBuff, MAXPATHL, "%s/neovim.ico", vimruntime); if (!os_path_exists(NameBuff)) { WLOG("neovim.ico not found: %s", NameBuff); } else { diff --git a/src/nvim/os/os_win_console.h b/src/nvim/os/os_win_console.h index 7b5800afa8..098267312a 100644 --- a/src/nvim/os/os_win_console.h +++ b/src/nvim/os/os_win_console.h @@ -1,5 +1,4 @@ -#ifndef NVIM_OS_OS_WIN_CONSOLE_H -#define NVIM_OS_OS_WIN_CONSOLE_H +#pragma once #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/os_win_console.h.generated.h" @@ -8,5 +7,3 @@ #ifndef ENABLE_VIRTUAL_TERMINAL_INPUT # define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200 #endif - -#endif // NVIM_OS_OS_WIN_CONSOLE_H diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c index f4d95e141b..d9ec3a7a8a 100644 --- a/src/nvim/os/process.c +++ b/src/nvim/os/process.c @@ -1,29 +1,21 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - /// OS process functions /// /// psutil is a good reference for cross-platform syscall voodoo: /// https://github.com/giampaolo/psutil/tree/master/psutil/arch +// IWYU pragma: no_include <sys/param.h> + #include <assert.h> #include <signal.h> #include <stdbool.h> #include <stddef.h> -#include <stdio.h> #include <uv.h> -#include "nvim/log.h" -#include "nvim/memory.h" -#include "nvim/os/process.h" - #ifdef MSWIN # include <tlhelp32.h> - -# include "nvim/api/private/helpers.h" #endif -#if defined(__FreeBSD__) // XXX: OpenBSD ? +#if defined(__FreeBSD__) # include <string.h> # include <sys/types.h> # include <sys/user.h> @@ -34,8 +26,21 @@ #endif #if defined(__APPLE__) || defined(BSD) -# include <pwd.h> # include <sys/sysctl.h> + +# include "nvim/macros_defs.h" +#endif + +#if defined(__linux__) +# include <stdio.h> +#endif + +#include "nvim/log.h" +#include "nvim/memory.h" +#include "nvim/os/process.h" + +#ifdef MSWIN +# include "nvim/api/private/helpers.h" #endif #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -72,7 +77,7 @@ static bool os_proc_tree_kill_rec(HANDLE process, int sig) } theend: - return (bool)TerminateProcess(process, (unsigned int)sig); + return (bool)TerminateProcess(process, (unsigned)sig); } /// Kills process `pid` and its descendants recursively. bool os_proc_tree_kill(int pid, int sig) @@ -254,7 +259,7 @@ Dictionary os_proc_info(int pid) if (pe.th32ProcessID == (DWORD)pid) { PUT(pinfo, "pid", INTEGER_OBJ(pid)); PUT(pinfo, "ppid", INTEGER_OBJ((int)pe.th32ParentProcessID)); - PUT(pinfo, "name", STRING_OBJ(cstr_to_string(pe.szExeFile))); + PUT(pinfo, "name", CSTR_TO_OBJ(pe.szExeFile)); } return pinfo; diff --git a/src/nvim/os/process.h b/src/nvim/os/process.h index faa4762cf1..3b116b4bad 100644 --- a/src/nvim/os/process.h +++ b/src/nvim/os/process.h @@ -1,12 +1,11 @@ -#ifndef NVIM_OS_PROCESS_H -#define NVIM_OS_PROCESS_H +#pragma once -#include <stddef.h> +#include <stddef.h> // IWYU pragma: keep -#include "nvim/api/private/defs.h" +#ifdef MSWIN +# include "nvim/api/private/defs.h" // IWYU pragma: keep +#endif #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/process.h.generated.h" #endif - -#endif // NVIM_OS_PROCESS_H diff --git a/src/nvim/os/pty_conpty_win.c b/src/nvim/os/pty_conpty_win.c index 43c89f8865..53169c0ef8 100644 --- a/src/nvim/os/pty_conpty_win.c +++ b/src/nvim/os/pty_conpty_win.c @@ -1,11 +1,8 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <uv.h> #include "nvim/os/os.h" #include "nvim/os/pty_conpty_win.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #ifndef EXTENDED_STARTUPINFO_PRESENT # define EXTENDED_STARTUPINFO_PRESENT 0x00080000 @@ -14,9 +11,9 @@ # define PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE 0x00020016 #endif -HRESULT (WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON *); -HRESULT (WINAPI *pResizePseudoConsole)(HPCON, COORD); -void (WINAPI *pClosePseudoConsole)(HPCON); +HRESULT(WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON *); +HRESULT(WINAPI *pResizePseudoConsole)(HPCON, COORD); +void(WINAPI *pClosePseudoConsole)(HPCON); bool os_has_conpty_working(void) { diff --git a/src/nvim/os/pty_conpty_win.h b/src/nvim/os/pty_conpty_win.h index 0c25a5970e..aa04cd1e84 100644 --- a/src/nvim/os/pty_conpty_win.h +++ b/src/nvim/os/pty_conpty_win.h @@ -1,5 +1,4 @@ -#ifndef NVIM_OS_PTY_CONPTY_WIN_H -#define NVIM_OS_PTY_CONPTY_WIN_H +#pragma once #include "klib/kvec.h" #include "nvim/os/input.h" @@ -8,10 +7,10 @@ # define HPCON VOID * #endif -extern HRESULT (WINAPI *pCreatePseudoConsole) // NOLINT(whitespace/parens) +extern HRESULT(WINAPI *pCreatePseudoConsole) // NOLINT(whitespace/parens) (COORD, HANDLE, HANDLE, DWORD, HPCON *); -extern HRESULT (WINAPI *pResizePseudoConsole)(HPCON, COORD); -extern void (WINAPI *pClosePseudoConsole)(HPCON); +extern HRESULT(WINAPI *pResizePseudoConsole)(HPCON, COORD); +extern void(WINAPI *pClosePseudoConsole)(HPCON); typedef struct conpty { HPCON pty; @@ -21,5 +20,3 @@ typedef struct conpty { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/pty_conpty_win.h.generated.h" #endif - -#endif // NVIM_OS_PTY_CONPTY_WIN_H diff --git a/src/nvim/os/pty_process.h b/src/nvim/os/pty_process.h index 07d346be22..2c7a5f66bd 100644 --- a/src/nvim/os/pty_process.h +++ b/src/nvim/os/pty_process.h @@ -1,9 +1,7 @@ -#ifndef NVIM_OS_PTY_PROCESS_H -#define NVIM_OS_PTY_PROCESS_H +#pragma once #ifdef MSWIN # include "nvim/os/pty_process_win.h" #else # include "nvim/os/pty_process_unix.h" #endif -#endif // NVIM_OS_PTY_PROCESS_H diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index 2413f0339b..f801646967 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // Some of the code came from pangoterm and libuv #include <assert.h> @@ -11,6 +8,7 @@ #include <string.h> #include <sys/ioctl.h> #include <sys/wait.h> +#include <uv.h> // forkpty is not in POSIX, so headers are platform-specific #if defined(__FreeBSD__) || defined(__DragonFly__) @@ -31,16 +29,15 @@ # include <crt_externs.h> #endif -#include <uv.h> - #include "auto/config.h" #include "klib/klist.h" #include "nvim/eval/typval.h" #include "nvim/event/loop.h" #include "nvim/event/process.h" #include "nvim/event/stream.h" +#include "nvim/func_attr.h" #include "nvim/log.h" -#include "nvim/os/os.h" +#include "nvim/os/fs.h" #include "nvim/os/os_defs.h" #include "nvim/os/pty_process.h" #include "nvim/os/pty_process_unix.h" @@ -286,7 +283,7 @@ static void init_child(PtyProcess *ptyproc) return; } - char *prog = ptyproc->process.argv[0]; + const char *prog = process_get_exepath(proc); assert(proc->env); environ = tv_dict_to_env(proc->env); @@ -336,21 +333,21 @@ static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL termios->c_lflag |= ECHOKE; #endif - termios->c_cc[VINTR] = 0x1f & 'C'; - termios->c_cc[VQUIT] = 0x1f & '\\'; - termios->c_cc[VERASE] = 0x7f; - termios->c_cc[VKILL] = 0x1f & 'U'; - termios->c_cc[VEOF] = 0x1f & 'D'; - termios->c_cc[VEOL] = _POSIX_VDISABLE; - termios->c_cc[VEOL2] = _POSIX_VDISABLE; - termios->c_cc[VSTART] = 0x1f & 'Q'; - termios->c_cc[VSTOP] = 0x1f & 'S'; - termios->c_cc[VSUSP] = 0x1f & 'Z'; + termios->c_cc[VINTR] = 0x1f & 'C'; + termios->c_cc[VQUIT] = 0x1f & '\\'; + termios->c_cc[VERASE] = 0x7f; + termios->c_cc[VKILL] = 0x1f & 'U'; + termios->c_cc[VEOF] = 0x1f & 'D'; + termios->c_cc[VEOL] = _POSIX_VDISABLE; + termios->c_cc[VEOL2] = _POSIX_VDISABLE; + termios->c_cc[VSTART] = 0x1f & 'Q'; + termios->c_cc[VSTOP] = 0x1f & 'S'; + termios->c_cc[VSUSP] = 0x1f & 'Z'; termios->c_cc[VREPRINT] = 0x1f & 'R'; - termios->c_cc[VWERASE] = 0x1f & 'W'; - termios->c_cc[VLNEXT] = 0x1f & 'V'; - termios->c_cc[VMIN] = 1; - termios->c_cc[VTIME] = 0; + termios->c_cc[VWERASE] = 0x1f & 'W'; + termios->c_cc[VLNEXT] = 0x1f & 'V'; + termios->c_cc[VMIN] = 1; + termios->c_cc[VTIME] = 0; } static int set_duplicating_descriptor(int fd, uv_pipe_t *pipe) diff --git a/src/nvim/os/pty_process_unix.h b/src/nvim/os/pty_process_unix.h index 0cc68cf3e9..92cc582832 100644 --- a/src/nvim/os/pty_process_unix.h +++ b/src/nvim/os/pty_process_unix.h @@ -1,5 +1,5 @@ -#ifndef NVIM_OS_PTY_PROCESS_UNIX_H -#define NVIM_OS_PTY_PROCESS_UNIX_H +#pragma once +// IWYU pragma: private, include "nvim/os/pty_process.h" #include <stdint.h> #include <sys/ioctl.h> @@ -27,5 +27,3 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/pty_process_unix.h.generated.h" #endif - -#endif // NVIM_OS_PTY_PROCESS_UNIX_H diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c index 6233a90638..ca2dce36ea 100644 --- a/src/nvim/os/pty_process_win.c +++ b/src/nvim/os/pty_process_win.c @@ -1,12 +1,10 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <assert.h> #include <stdbool.h> #include <stdlib.h> -#include "nvim/ascii.h" -#include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8 +#include "nvim/ascii_defs.h" +#include "nvim/eval/typval.h" +#include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/os/os.h" #include "nvim/os/pty_conpty_win.h" @@ -172,11 +170,13 @@ void pty_process_close(PtyProcess *ptyproc) void pty_process_close_master(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL -{} +{ +} void pty_process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL -{} +{ +} static void pty_process_connect_cb(uv_connect_t *req, int status) FUNC_ATTR_NONNULL_ALL @@ -253,9 +253,9 @@ static int build_cmd_line(char **argv, wchar_t **cmd_line, bool is_cmdexe) QUEUE_FOREACH(q, &args_q, { ArgNode *arg_node = QUEUE_DATA(q, ArgNode, node); xstrlcat(utf8_cmd_line, arg_node->arg, utf8_cmd_line_len); + QUEUE_REMOVE(q); xfree(arg_node->arg); xfree(arg_node); - QUEUE_REMOVE(q); if (!QUEUE_EMPTY(&args_q)) { xstrlcat(utf8_cmd_line, " ", utf8_cmd_line_len); } diff --git a/src/nvim/os/pty_process_win.h b/src/nvim/os/pty_process_win.h index ed7d765ac7..26cf387e54 100644 --- a/src/nvim/os/pty_process_win.h +++ b/src/nvim/os/pty_process_win.h @@ -1,5 +1,5 @@ -#ifndef NVIM_OS_PTY_PROCESS_WIN_H -#define NVIM_OS_PTY_PROCESS_WIN_H +#pragma once +// IWYU pragma: private, include "nvim/os/pty_process.h" #include <uv.h> @@ -37,5 +37,3 @@ static inline PtyProcess pty_process_init(Loop *loop, void *data) #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/pty_process_win.h.generated.h" #endif - -#endif // NVIM_OS_PTY_PROCESS_WIN_H diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index f1e2c5440f..191be784e8 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <assert.h> #include <stdbool.h> #include <stdint.h> @@ -10,8 +7,7 @@ #include "auto/config.h" #include "klib/kvec.h" -#include "nvim/ascii.h" -#include "nvim/buffer_defs.h" +#include "nvim/ascii_defs.h" #include "nvim/charset.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" @@ -24,29 +20,30 @@ #include "nvim/event/wstream.h" #include "nvim/ex_cmds.h" #include "nvim/fileio.h" +#include "nvim/func_attr.h" #include "nvim/gettext.h" #include "nvim/globals.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/main.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/option_defs.h" +#include "nvim/option_vars.h" #include "nvim/os/fs.h" -#include "nvim/os/os_defs.h" #include "nvim/os/shell.h" #include "nvim/os/signal.h" #include "nvim/os/time.h" #include "nvim/path.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/profile.h" #include "nvim/rbuffer.h" +#include "nvim/state_defs.h" #include "nvim/strings.h" #include "nvim/tag.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #define DYNAMIC_BUFFER_INIT { NULL, 0, 0 } #define NS_1_SECOND 1000000000U // 1 second, in nanoseconds @@ -134,6 +131,8 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in #define STYLE_VIMGLOB 2 // use "vimglob", for Posix sh #define STYLE_PRINT 3 // use "print -N", for zsh #define STYLE_BT 4 // `cmd` expansion, execute the pattern directly +#define STYLE_GLOBSTAR 5 // use extended shell glob for bash (this uses extended + // globbing functionality with globstar, needs bash > 4) int shell_style = STYLE_ECHO; int check_spaces; static bool did_find_nul = false; @@ -141,10 +140,13 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in // vimglob() function to define for Posix shell static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >"; + // vimglob() function with globstar setting enabled, only for bash >= 4.X + static char *sh_globstar_opt = + "[[ ${BASH_VERSINFO[0]} -ge 4 ]] && shopt -s globstar; "; bool is_fish_shell = #if defined(UNIX) - strncmp((char *)invocation_path_tail(p_sh, NULL), "fish", 4) == 0; + strncmp(invocation_path_tail(p_sh, NULL), "fish", 4) == 0; #else false; #endif @@ -190,6 +192,8 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in // If we use *zsh, "print -N" will work better than "glob". // STYLE_VIMGLOB: NL separated // If we use *sh*, we define "vimglob()". + // STYLE_GLOBSTAR: NL separated + // If we use *bash*, we define "vimglob() and enable globstar option". // STYLE_ECHO: space separated. // A shell we don't know, stay safe and use "echo". if (num_pat == 1 && *pat[0] == '`' @@ -203,9 +207,12 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in shell_style = STYLE_PRINT; } } - if (shell_style == STYLE_ECHO - && strstr(path_tail(p_sh), "sh") != NULL) { - shell_style = STYLE_VIMGLOB; + if (shell_style == STYLE_ECHO) { + if (strstr(path_tail(p_sh), "bash") != NULL) { + shell_style = STYLE_GLOBSTAR; + } else if (strstr(path_tail(p_sh), "sh") != NULL) { + shell_style = STYLE_VIMGLOB; + } } // Compute the length of the command. We need 2 extra bytes: for the @@ -214,6 +221,8 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in len = strlen(tempname) + 29; if (shell_style == STYLE_VIMGLOB) { len += strlen(sh_vimglob_func); + } else if (shell_style == STYLE_GLOBSTAR) { + len += strlen(sh_vimglob_func) + strlen(sh_globstar_opt); } for (i = 0; i < num_pat; i++) { @@ -281,6 +290,9 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in STRCAT(command, "print -N >"); } else if (shell_style == STYLE_VIMGLOB) { STRCAT(command, sh_vimglob_func); + } else if (shell_style == STYLE_GLOBSTAR) { + STRCAT(command, sh_globstar_opt); + STRCAT(command, sh_vimglob_func); } else { STRCAT(command, "echo >"); } @@ -352,7 +364,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in // When running in the background, give it some time to create the temp // file, but don't wait for it to finish. if (ampersand) { - os_delay(10L, true); + os_delay(10, true); } xfree(command); @@ -364,7 +376,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in if (!(flags & EW_SILENT)) { msg_putchar('\n'); // clear bottom line quickly cmdline_row = Rows - 1; // continue on last line - msg(_(e_wildexpand)); + msg(_(e_wildexpand), 0); msg_start(); // don't overwrite this message } @@ -381,13 +393,13 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in if (fd == NULL) { // Something went wrong, perhaps a file name with a special char. if (!(flags & EW_SILENT)) { - msg(_(e_wildexpand)); + msg(_(e_wildexpand), 0); msg_start(); // don't overwrite this message } xfree(tempname); goto notfound; } - int fseek_res = fseek(fd, 0L, SEEK_END); + int fseek_res = fseek(fd, 0, SEEK_END); if (fseek_res < 0) { xfree(tempname); fclose(fd); @@ -399,11 +411,11 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in fclose(fd); return FAIL; } -#if SIZEOF_LONG_LONG > SIZEOF_SIZE_T - assert(templen <= (long long)SIZE_MAX); // NOLINT(runtime/int) +#if 8 > SIZEOF_SIZE_T + assert(templen <= SIZE_MAX); // NOLINT(runtime/int) #endif len = (size_t)templen; - fseek(fd, 0L, SEEK_SET); + fseek(fd, 0, SEEK_SET); buffer = xmalloc(len + 1); // fread() doesn't terminate buffer with NUL; // appropriate termination (not always NUL) is done below. @@ -430,7 +442,9 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in p = skipwhite(p); // skip to next entry } // file names are separated with NL - } else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB) { + } else if (shell_style == STYLE_BT + || shell_style == STYLE_VIMGLOB + || shell_style == STYLE_GLOBSTAR) { buffer[len] = NUL; // make sure the buffer ends in NUL p = buffer; for (i = 0; *p != NUL; i++) { // count number of entries @@ -496,7 +510,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in (*file)[i] = p; // Space or NL separates if (shell_style == STYLE_ECHO || shell_style == STYLE_BT - || shell_style == STYLE_VIMGLOB) { + || shell_style == STYLE_VIMGLOB || shell_style == STYLE_GLOBSTAR) { while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n' && *p != NUL) { p++; @@ -715,7 +729,7 @@ int call_shell(char *cmd, ShellOpts opts, char *extra_shell_arg) if (p_verbose > 3) { verbose_enter(); - smsg(_("Executing command: \"%s\""), cmd == NULL ? p_sh : cmd); + smsg(0, _("Executing command: \"%s\""), cmd == NULL ? p_sh : cmd); msg_putchar('\n'); verbose_leave(); } @@ -786,9 +800,9 @@ char *get_cmd_output(char *cmd, char *infile, ShellOpts flags, size_t *ret_len) goto done; } - fseek(fd, 0L, SEEK_END); + fseek(fd, 0, SEEK_END); size_t len = (size_t)ftell(fd); // get size of temp file - fseek(fd, 0L, SEEK_SET); + fseek(fd, 0, SEEK_SET); buffer = xmalloc(len + 1); size_t i = fread(buffer, 1, len, fd); @@ -876,9 +890,9 @@ static int do_os_system(char **argv, const char *input, size_t len, char **outpu // Failed, probably 'shell' is not executable. if (!silent) { msg_puts(_("\nshell failed to start: ")); - msg_outtrans((char *)os_strerror(status)); + msg_outtrans(os_strerror(status), 0); msg_puts(": "); - msg_outtrans(prog); + msg_outtrans(prog, 0); msg_putchar('\n'); } multiqueue_free(events); @@ -1006,9 +1020,9 @@ static void system_data_cb(Stream *stream, RBuffer *buf, size_t count, void *dat /// Returns the previous decision if size=0. static bool out_data_decide_throttle(size_t size) { - static uint64_t started = 0; // Start time of the current throttle. - static size_t received = 0; // Bytes observed since last throttle. - static size_t visit = 0; // "Pulse" count of the current throttle. + static uint64_t started = 0; // Start time of the current throttle. + static size_t received = 0; // Bytes observed since last throttle. + static size_t visit = 0; // "Pulse" count of the current throttle. static char pulse_msg[] = { ' ', ' ', ' ', '\0' }; if (!size) { @@ -1026,7 +1040,7 @@ static bool out_data_decide_throttle(size_t size) started = os_hrtime(); } else { uint64_t since = os_hrtime() - started; - if (since < (visit * 0.1L * NS_1_SECOND)) { + if (since < (visit * (NS_1_SECOND / 10))) { return true; } if (since > (3 * NS_1_SECOND)) { @@ -1088,7 +1102,7 @@ static void out_data_ring(char *output, size_t size) last_skipped_len = MAX_CHUNK_SIZE; } else if (size > 0) { // Length of the old data that can be kept. - size_t keep_len = MIN(last_skipped_len, MAX_CHUNK_SIZE - size); + size_t keep_len = MIN(last_skipped_len, MAX_CHUNK_SIZE - size); size_t keep_start = last_skipped_len - keep_len; // Shift the kept part of the old data to the start. if (keep_start) { @@ -1127,7 +1141,7 @@ static void out_data_append_to_screen(char *output, size_t *count, bool eof) goto end; } - (void)msg_outtrans_len_attr(p, i, 0); + (void)msg_outtrans_len(p, i, 0); p += i; } } @@ -1180,7 +1194,7 @@ static size_t tokenize(const char *const str, char **const argv) } argc++; - p = (const char *)skipwhite((p + len)); + p = skipwhite((p + len)); } return argc; @@ -1221,12 +1235,12 @@ static size_t word_length(const char *str) /// before we finish writing. static void read_input(DynamicBuffer *buf) { - size_t written = 0, l = 0, len = 0; + size_t written = 0, len = 0; linenr_T lnum = curbuf->b_op_start.lnum; char *lp = ml_get(lnum); - for (;;) { - l = strlen(lp + written); + while (true) { + size_t l = strlen(lp + written); if (l == 0) { len = 0; } else if (lp[written] == NL) { diff --git a/src/nvim/os/shell.h b/src/nvim/os/shell.h index 48503f2601..82c83543af 100644 --- a/src/nvim/os/shell.h +++ b/src/nvim/os/shell.h @@ -1,9 +1,6 @@ -#ifndef NVIM_OS_SHELL_H -#define NVIM_OS_SHELL_H +#pragma once -#include <stdio.h> - -#include "nvim/types.h" +#include <stddef.h> // IWYU pragma: keep // Flags for os_call_shell() second argument typedef enum { @@ -19,4 +16,3 @@ typedef enum { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/shell.h.generated.h" #endif -#endif // NVIM_OS_SHELL_H diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index b8daaabba2..c920cb655e 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -1,23 +1,24 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <assert.h> #include <stdbool.h> #include <stdio.h> + #ifndef MSWIN -# include <signal.h> // for sigset_t +# include <signal.h> #endif #include "nvim/autocmd.h" -#include "nvim/buffer_defs.h" #include "nvim/eval.h" #include "nvim/event/signal.h" +#include "nvim/func_attr.h" #include "nvim/globals.h" #include "nvim/log.h" #include "nvim/main.h" -#include "nvim/memline.h" #include "nvim/os/signal.h" +#ifdef SIGPWR +# include "nvim/memline.h" +#endif + static SignalWatcher spipe, shup, squit, sterm, susr1, swinch; #ifdef SIGPWR static SignalWatcher spwr; @@ -172,11 +173,10 @@ static void deadly_signal(int signum) ILOG("got signal %d (%s)", signum, signal_name(signum)); - snprintf(IObuff, sizeof(IObuff), "Vim: Caught deadly signal '%s'\r\n", - signal_name(signum)); + snprintf(IObuff, IOSIZE, "Vim: Caught deadly signal '%s'\r\n", signal_name(signum)); // Preserve files and exit. - preserve_exit(); + preserve_exit(IObuff); } static void on_signal(SignalWatcher *handle, int signum, void *data) diff --git a/src/nvim/os/signal.h b/src/nvim/os/signal.h index 5d8cc6f661..83a0a9c91b 100644 --- a/src/nvim/os/signal.h +++ b/src/nvim/os/signal.h @@ -1,7 +1,5 @@ -#ifndef NVIM_OS_SIGNAL_H -#define NVIM_OS_SIGNAL_H +#pragma once #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/signal.h.generated.h" #endif -#endif // NVIM_OS_SIGNAL_H diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index 6b07b6ef70..7691aa5122 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -1,11 +1,11 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - +#include <assert.h> #include <stdbool.h> #include <string.h> -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/fileio.h" +#include "nvim/func_attr.h" +#include "nvim/globals.h" #include "nvim/memory.h" #include "nvim/os/os.h" #include "nvim/os/stdpaths_defs.h" @@ -57,6 +57,39 @@ static const char *const xdg_defaults[] = { #endif }; +/// Get the value of $NVIM_APPNAME or "nvim" if not set. +/// +/// @return $NVIM_APPNAME value +const char *get_appname(void) +{ + const char *env_val = os_getenv("NVIM_APPNAME"); + if (env_val == NULL || *env_val == '\0') { + env_val = "nvim"; + } + return env_val; +} + +/// Ensure that APPNAME is valid. Must be a name or relative path. +bool appname_is_valid(void) +{ + const char *appname = get_appname(); + if (path_is_absolute(appname) + // TODO(justinmk): on Windows, path_is_absolute says "/" is NOT absolute. Should it? + || strequal(appname, "/") + || strequal(appname, "\\") + || strequal(appname, ".") + || strequal(appname, "..") +#ifdef BACKSLASH_IN_FILENAME + || strstr(appname, "\\..") != NULL + || strstr(appname, "..\\") != NULL +#endif + || strstr(appname, "/..") != NULL + || strstr(appname, "../") != NULL) { + return false; + } + return true; +} + /// Return XDG variable value /// /// @param[in] idx XDG variable to use. @@ -92,7 +125,7 @@ char *stdpaths_get_xdg_var(const XDGVarType idx) ret = "/tmp/"; } size_t len = strlen(ret); - ret = xstrndup(ret, len >= 2 ? len - 1 : 0); // Trim trailing slash. + ret = xmemdupz(ret, len >= 2 ? len - 1 : 0); // Trim trailing slash. } return ret; @@ -100,25 +133,28 @@ char *stdpaths_get_xdg_var(const XDGVarType idx) /// Return Nvim-specific XDG directory subpath. /// -/// Windows: Uses "…/nvim-data" for kXDGDataHome to avoid storing +/// Windows: Uses "…/$NVIM_APPNAME-data" for kXDGDataHome to avoid storing /// configuration and data files in the same path. #4403 /// /// @param[in] idx XDG directory to use. /// -/// @return [allocated] "{xdg_directory}/nvim" +/// @return [allocated] "{xdg_directory}/$NVIM_APPNAME" char *get_xdg_home(const XDGVarType idx) FUNC_ATTR_WARN_UNUSED_RESULT { char *dir = stdpaths_get_xdg_var(idx); + const char *appname = get_appname(); + size_t appname_len = strlen(appname); + assert(appname_len < (IOSIZE - sizeof("-data"))); + if (dir) { + xstrlcpy(IObuff, appname, appname_len + 1); #if defined(MSWIN) - dir = concat_fnames_realloc(dir, - ((idx == kXDGDataHome - || idx == kXDGStateHome) ? "nvim-data" : "nvim"), - true); -#else - dir = concat_fnames_realloc(dir, "nvim", true); + if (idx == kXDGDataHome || idx == kXDGStateHome) { + xstrlcat(IObuff, "-data", IOSIZE); + } #endif + dir = concat_fnames_realloc(dir, IObuff, true); #ifdef BACKSLASH_IN_FILENAME slash_adjust(dir); @@ -131,7 +167,7 @@ char *get_xdg_home(const XDGVarType idx) /// /// @param[in] fname New component of the path. /// -/// @return [allocated] `$XDG_CACHE_HOME/nvim/{fname}` +/// @return [allocated] `$XDG_CACHE_HOME/$NVIM_APPNAME/{fname}` char *stdpaths_user_cache_subpath(const char *fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { @@ -142,7 +178,7 @@ char *stdpaths_user_cache_subpath(const char *fname) /// /// @param[in] fname New component of the path. /// -/// @return [allocated] `$XDG_CONFIG_HOME/nvim/{fname}` +/// @return [allocated] `$XDG_CONFIG_HOME/$NVIM_APPNAME/{fname}` char *stdpaths_user_conf_subpath(const char *fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { @@ -153,7 +189,7 @@ char *stdpaths_user_conf_subpath(const char *fname) /// /// @param[in] fname New component of the path. /// -/// @return [allocated] `$XDG_DATA_HOME/nvim/{fname}` +/// @return [allocated] `$XDG_DATA_HOME/$NVIM_APPNAME/{fname}` char *stdpaths_user_data_subpath(const char *fname) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { @@ -166,7 +202,7 @@ char *stdpaths_user_data_subpath(const char *fname) /// @param[in] trailing_pathseps Amount of trailing path separators to add. /// @param[in] escape_commas If true, all commas will be escaped. /// -/// @return [allocated] `$XDG_STATE_HOME/nvim/{fname}`. +/// @return [allocated] `$XDG_STATE_HOME/$NVIM_APPNAME/{fname}`. char *stdpaths_user_state_subpath(const char *fname, const size_t trailing_pathseps, const bool escape_commas) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET diff --git a/src/nvim/os/stdpaths_defs.h b/src/nvim/os/stdpaths_defs.h index f94c511fe7..985688390d 100644 --- a/src/nvim/os/stdpaths_defs.h +++ b/src/nvim/os/stdpaths_defs.h @@ -1,5 +1,4 @@ -#ifndef NVIM_OS_STDPATHS_DEFS_H -#define NVIM_OS_STDPATHS_DEFS_H +#pragma once /// List of possible XDG variables typedef enum { @@ -12,5 +11,3 @@ typedef enum { kXDGConfigDirs, ///< XDG_CONFIG_DIRS kXDGDataDirs, ///< XDG_DATA_DIRS } XDGVarType; - -#endif // NVIM_OS_STDPATHS_DEFS_H diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index 873302a27d..49b43af6c0 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -1,10 +1,6 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include <inttypes.h> #include <limits.h> #include <stdbool.h> -#include <stdlib.h> #include <string.h> #include <time.h> @@ -12,32 +8,20 @@ #include "auto/config.h" #include "nvim/event/loop.h" +#include "nvim/func_attr.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/log.h" -#include "nvim/macros.h" #include "nvim/main.h" #include "nvim/memory.h" #include "nvim/os/input.h" #include "nvim/os/os.h" #include "nvim/os/time.h" -struct tm; - -static uv_mutex_t delay_mutex; -static uv_cond_t delay_cond; - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/time.c.generated.h" // IWYU pragma: export #endif -/// Initializes the time module -void time_init(void) -{ - uv_mutex_init(&delay_mutex); - uv_cond_init(&delay_cond); -} - /// Gets a high-resolution (nanosecond), monotonically-increasing time relative /// to an arbitrary time in the past. /// @@ -73,55 +57,28 @@ uint64_t os_now(void) void os_delay(uint64_t ms, bool ignoreinput) { DLOG("%" PRIu64 " ms", ms); - if (ignoreinput) { - if (ms > INT_MAX) { - ms = INT_MAX; - } - LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)ms, got_int); - } else { - os_microdelay(ms * 1000U, ignoreinput); + if (ms > INT_MAX) { + ms = INT_MAX; } + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)ms, + ignoreinput ? got_int : os_input_ready(NULL)); } -/// Sleeps for `us` microseconds. +/// Sleeps for `ms` milliseconds without checking for events or interrupts. +/// +/// This blocks even "fast" events which is quite disruptive. This should only +/// be used in debug code. Prefer os_delay() and decide if the delay should be +/// interrupted by input or only a CTRL-C. /// /// @see uv_sleep() (libuv v1.34.0) /// /// @param us Number of microseconds to sleep. -/// @param ignoreinput If true, ignore all input (including SIGINT/CTRL-C). -/// If false, waiting is aborted on any input. -void os_microdelay(uint64_t us, bool ignoreinput) +void os_sleep(uint64_t ms) { - uint64_t elapsed = 0U; - uint64_t base = uv_hrtime(); - // Convert microseconds to nanoseconds, or UINT64_MAX on overflow. - const uint64_t ns = (us < UINT64_MAX / 1000U) ? us * 1000U : UINT64_MAX; - - uv_mutex_lock(&delay_mutex); - - while (elapsed < ns) { - // If ignoring input, we simply wait the full delay. - // Else we check for input in ~100ms intervals. - const uint64_t ns_delta = ignoreinput - ? ns - elapsed - : MIN(ns - elapsed, 100000000U); // 100ms - - const int rv = uv_cond_timedwait(&delay_cond, &delay_mutex, ns_delta); - if (0 != rv && UV_ETIMEDOUT != rv) { - abort(); - break; - } // Else: Timeout proceeded normally. - - if (!ignoreinput && os_char_avail()) { - break; - } - - const uint64_t now = uv_hrtime(); - elapsed += now - base; - base = now; + if (ms > UINT_MAX) { + ms = UINT_MAX; } - - uv_mutex_unlock(&delay_mutex); + uv_sleep((unsigned)ms); } // Cache of the current timezone name as retrieved from TZ, or an empty string diff --git a/src/nvim/os/time.h b/src/nvim/os/time.h index 1b6c667dbb..2748ba6953 100644 --- a/src/nvim/os/time.h +++ b/src/nvim/os/time.h @@ -1,13 +1,10 @@ -#ifndef NVIM_OS_TIME_H -#define NVIM_OS_TIME_H +#pragma once -#include <stdbool.h> -#include <stdint.h> -#include <time.h> +#include <stddef.h> // IWYU pragma: keep +#include <time.h> // IWYU pragma: keep -typedef uint64_t Timestamp; +#include "nvim/os/time_defs.h" // IWYU pragma: export #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/time.h.generated.h" #endif -#endif // NVIM_OS_TIME_H diff --git a/src/nvim/os/time_defs.h b/src/nvim/os/time_defs.h new file mode 100644 index 0000000000..9b71a6764d --- /dev/null +++ b/src/nvim/os/time_defs.h @@ -0,0 +1,4 @@ +#pragma once + +#include <stdint.h> +typedef uint64_t Timestamp; diff --git a/src/nvim/os/tty.c b/src/nvim/os/tty.c index b5124bd83a..e683b9383f 100644 --- a/src/nvim/os/tty.c +++ b/src/nvim/os/tty.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // // Terminal/console utils // diff --git a/src/nvim/os/tty.h b/src/nvim/os/tty.h index d771e63768..a24d875c05 100644 --- a/src/nvim/os/tty.h +++ b/src/nvim/os/tty.h @@ -1,7 +1,5 @@ -#ifndef NVIM_OS_TTY_H -#define NVIM_OS_TTY_H +#pragma once #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "os/tty.h.generated.h" +# include "os/tty.h.generated.h" // IWYU pragma: export #endif -#endif // NVIM_OS_TTY_H diff --git a/src/nvim/os/unix_defs.h b/src/nvim/os/unix_defs.h index 8d002fc5e9..d2bec7b361 100644 --- a/src/nvim/os/unix_defs.h +++ b/src/nvim/os/unix_defs.h @@ -1,14 +1,18 @@ -#ifndef NVIM_OS_UNIX_DEFS_H -#define NVIM_OS_UNIX_DEFS_H +#pragma once +// IWYU pragma: private, include "nvim/os/os_defs.h" +// IWYU pragma: begin_exports +#include <arpa/inet.h> +#include <netdb.h> +#include <netinet/in.h> +#include <pthread.h> #include <sys/param.h> +#include <sys/socket.h> #include <unistd.h> #if defined(HAVE_TERMIOS_H) # include <termios.h> #endif - -// POSIX.1-2008 says that NAME_MAX should be in here -#include <limits.h> +// IWYU pragma: end_exports #define TEMP_DIR_NAMES { "$TMPDIR", "/tmp", ".", "~" } #define TEMP_FILE_PATH_MAXLEN 256 @@ -21,5 +25,3 @@ // Character that separates entries in $PATH. #define ENV_SEPCHAR ':' #define ENV_SEPSTR ":" - -#endif // NVIM_OS_UNIX_DEFS_H diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c index ef2986246b..ae0994a73f 100644 --- a/src/nvim/os/users.c +++ b/src/nvim/os/users.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // users.c -- operating system user information #include <stdbool.h> @@ -9,17 +6,20 @@ #include <uv.h> #include "auto/config.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/garray.h" #include "nvim/memory.h" #include "nvim/os/os.h" -#include "nvim/types.h" -#include "nvim/vim.h" -#ifdef HAVE_PWD_H +#include "nvim/vim_defs.h" +#ifdef HAVE_PWD_FUNCS # include <pwd.h> #endif #ifdef MSWIN # include <lm.h> + +# include "nvim/mbyte.h" +# include "nvim/message.h" #endif // All user names (for ~user completion as done by shell). @@ -30,7 +30,7 @@ static garray_T ga_users = GA_EMPTY_INIT_VALUE; static void add_user(garray_T *users, char *user, bool need_copy) { char *user_copy = (user != NULL && need_copy) - ? xstrdup(user) : user; + ? xstrdup(user) : user; if (user_copy == NULL || *user_copy == NUL) { if (need_copy) { @@ -50,7 +50,7 @@ int os_get_usernames(garray_T *users) } ga_init(users, sizeof(char *), 20); -#if defined(HAVE_GETPWENT) && defined(HAVE_PWD_H) +#ifdef HAVE_PWD_FUNCS { struct passwd *pw; @@ -81,7 +81,7 @@ int os_get_usernames(garray_T *users) } } #endif -#if defined(HAVE_GETPWNAM) +#ifdef HAVE_PWD_FUNCS { const char *user_env = os_getenv("USER"); @@ -141,7 +141,7 @@ int os_get_username(char *s, size_t len) /// @return OK if a username was found, else FAIL. int os_get_uname(uv_uid_t uid, char *s, size_t len) { -#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID) +#ifdef HAVE_PWD_FUNCS struct passwd *pw; if ((pw = getpwuid(uid)) != NULL // NOLINT(runtime/threadsafe_fn) @@ -159,7 +159,7 @@ int os_get_uname(uv_uid_t uid, char *s, size_t len) /// Caller must free() the returned string. char *os_get_userdir(const char *name) { -#if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) +#ifdef HAVE_PWD_FUNCS if (name == NULL || *name == NUL) { return NULL; } diff --git a/src/nvim/os/win_defs.h b/src/nvim/os/win_defs.h index 4f8a242a51..852059f78b 100644 --- a/src/nvim/os/win_defs.h +++ b/src/nvim/os/win_defs.h @@ -1,5 +1,5 @@ -#ifndef NVIM_OS_WIN_DEFS_H -#define NVIM_OS_WIN_DEFS_H +#pragma once +// IWYU pragma: private, include "nvim/os/os_defs.h" #ifndef MSWIN # error Header must be included only when compiling for Windows. @@ -86,5 +86,3 @@ typedef int mode_t; #ifndef STDERR_FILENO # define STDERR_FILENO 2 #endif - -#endif // NVIM_OS_WIN_DEFS_H |