aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 21:52:58 +0000
commit931bffbda3668ddc609fc1da8f9eb576b170aa52 (patch)
treed8c1843a95da5ea0bb4acc09f7e37843d9995c86 /src/nvim/os
parent142d9041391780ac15b89886a54015fdc5c73995 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-userreg.tar.gz
rneovim-userreg.tar.bz2
rneovim-userreg.zip
Merge remote-tracking branch 'upstream/master' into userreguserreg
Diffstat (limited to 'src/nvim/os')
-rw-r--r--src/nvim/os/dl.c5
-rw-r--r--src/nvim/os/dl.h7
-rw-r--r--src/nvim/os/env.c81
-rw-r--r--src/nvim/os/fileio.c21
-rw-r--r--src/nvim/os/fileio.h4
-rw-r--r--src/nvim/os/fs.c245
-rw-r--r--src/nvim/os/fs.h13
-rw-r--r--src/nvim/os/fs_defs.h5
-rw-r--r--src/nvim/os/input.c46
-rw-r--r--src/nvim/os/input.h11
-rw-r--r--src/nvim/os/lang.c337
-rw-r--r--src/nvim/os/lang.h8
-rw-r--r--src/nvim/os/mem.c3
-rw-r--r--src/nvim/os/nvim.manifest5
-rw-r--r--src/nvim/os/os.h31
-rw-r--r--src/nvim/os/os_defs.h44
-rw-r--r--src/nvim/os/os_win_console.c8
-rw-r--r--src/nvim/os/os_win_console.h5
-rw-r--r--src/nvim/os/process.c33
-rw-r--r--src/nvim/os/process.h11
-rw-r--r--src/nvim/os/pty_conpty_win.c11
-rw-r--r--src/nvim/os/pty_conpty_win.h11
-rw-r--r--src/nvim/os/pty_process.h4
-rw-r--r--src/nvim/os/pty_process_unix.c39
-rw-r--r--src/nvim/os/pty_process_unix.h6
-rw-r--r--src/nvim/os/pty_process_win.c16
-rw-r--r--src/nvim/os/pty_process_win.h6
-rw-r--r--src/nvim/os/shell.c92
-rw-r--r--src/nvim/os/shell.h8
-rw-r--r--src/nvim/os/signal.c18
-rw-r--r--src/nvim/os/signal.h4
-rw-r--r--src/nvim/os/stdpaths.c70
-rw-r--r--src/nvim/os/stdpaths_defs.h5
-rw-r--r--src/nvim/os/time.c71
-rw-r--r--src/nvim/os/time.h11
-rw-r--r--src/nvim/os/time_defs.h4
-rw-r--r--src/nvim/os/tty.c3
-rw-r--r--src/nvim/os/tty.h6
-rw-r--r--src/nvim/os/unix_defs.h16
-rw-r--r--src/nvim/os/users.c24
-rw-r--r--src/nvim/os/win_defs.h6
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