drop unused functions and configure checks

Remove the following C++ functions/methods, which have no callers:

common.cpp:
- read_loop
- narrow_string_safe
- escape_string_for_double_quotes
- read_unquoted_escape
- format_size
- format_size_safe
- valid_func_name
- get_executable_path

env.cpp:
- env_stack_t::set_empty
- env_stack_t::set_argv

fallback.cpp:
- fish_mkstemp_cloexec
- flock

proc_util.cpp:
- parse_util_slice_length
- parse_util_argument_is_help

path.cpp:
- path_get_path
- path_as_implicit_cd
- path_apply_working_directory
- path_emit_config_directory_messages
- path_get_data_remoteness
- path_get_config_remoteness
- path_is_valid
- paths_are_same_file

wcstringutil.cpp:
- split_string_tok

wutil.cpp:
- wgetcwd
- wunlink
- wrealpath
- wrename
- file_id_for_path
- fish_wcstoull

Also drop unused configure checks/defines:
- HAVE_FLOCK
This commit is contained in:
David Adam
2023-11-20 15:21:58 +08:00
parent f773697bc1
commit f2f41c6eec
18 changed files with 0 additions and 917 deletions

View File

@@ -572,14 +572,6 @@ ssize_t write_loop(int fd, const char *buff, size_t count) {
return static_cast<ssize_t>(out_cum);
}
ssize_t read_loop(int fd, void *buff, size_t count) {
ssize_t result;
do {
result = read(fd, buff, count);
} while (result < 0 && (errno == EAGAIN || errno == EINTR));
return result;
}
/// Hack to not print error messages in the tests. Do not call this from functions in this module
/// like `debug()`. It is only intended to suppress diagnostic noise from testing things like the
/// fish parser where we expect a lot of diagnostic messages due to testing error conditions.
@@ -645,20 +637,6 @@ void format_ullong_safe(wchar_t buff[64], unsigned long long val) {
return format_safe_impl(buff, 64, val);
}
void narrow_string_safe(char buff[64], const wchar_t *s) {
size_t idx = 0;
for (size_t widx = 0; s[widx] != L'\0'; widx++) {
wchar_t c = s[widx];
if (c <= 127) {
buff[idx++] = char(c);
if (idx + 1 == 64) {
break;
}
}
}
buff[idx] = '\0';
}
/// Escape a string in a fashion suitable for using as a URL. Store the result in out_str.
static void escape_string_url(const wcstring &in, wcstring &out) {
auto result = escape_string_url(in.c_str(), in.size());
@@ -675,22 +653,6 @@ static void escape_string_var(const wcstring &in, wcstring &out) {
}
}
wcstring escape_string_for_double_quotes(wcstring in) {
// We need to escape backslashes, double quotes, and dollars only.
wcstring result = std::move(in);
size_t idx = result.size();
while (idx--) {
switch (result[idx]) {
case L'\\':
case L'$':
case L'"':
result.insert(idx, 1, L'\\');
break;
}
}
return result;
}
/// Escape a string in a fashion suitable for using in fish script. Store the result in out_str.
static void escape_string_script(const wchar_t *orig_in, size_t in_len, wcstring &out,
escape_flags_t flags) {
@@ -785,228 +747,6 @@ wcstring escape_string(const wcstring &in, escape_flags_t flags, escape_string_s
return result;
}
/// Given a null terminated string starting with a backslash, read the escape as if it is unquoted,
/// appending to result. Return the number of characters consumed, or none on error.
maybe_t<size_t> read_unquoted_escape(const wchar_t *input, wcstring *result, bool allow_incomplete,
bool unescape_special) {
assert(input[0] == L'\\' && "Not an escape");
// Here's the character we'll ultimately append, or none. Note that L'\0' is a
// valid thing to append.
maybe_t<wchar_t> result_char_or_none = none();
bool errored = false;
size_t in_pos = 1; // in_pos always tracks the next character to read (and therefore the number
// of characters read so far)
// For multibyte \X sequences.
std::string byte_buff;
while (true) {
const wchar_t c = input[in_pos++];
switch (c) {
// A null character after a backslash is an error.
case L'\0': {
// Adjust in_pos to only include the backslash.
assert(in_pos > 0);
in_pos--;
// It's an error, unless we're allowing incomplete escapes.
if (!allow_incomplete) errored = true;
break;
}
// Numeric escape sequences. No prefix means octal escape, otherwise hexadecimal.
case L'0':
case L'1':
case L'2':
case L'3':
case L'4':
case L'5':
case L'6':
case L'7':
case L'u':
case L'U':
case L'x':
case L'X': {
long long res = 0;
size_t chars = 2;
int base = 16;
bool byte_literal = false;
wchar_t max_val = ASCII_MAX;
switch (c) {
case L'u': {
chars = 4;
max_val = UCS2_MAX;
break;
}
case L'U': {
chars = 8;
max_val = WCHAR_MAX;
// Don't exceed the largest Unicode code point - see #1107.
if (0x10FFFF < max_val) max_val = static_cast<wchar_t>(0x10FFFF);
break;
}
case L'x':
case L'X': {
byte_literal = true;
max_val = BYTE_MAX;
break;
}
default: {
base = 8;
chars = 3;
// Note that in_pos currently is just after the first post-backslash
// character; we want to start our escape from there.
assert(in_pos > 0);
in_pos--;
break;
}
}
for (size_t i = 0; i < chars; i++) {
long d = convert_digit(input[in_pos], base);
if (d < 0) {
// If we have no digit, this is a tokenizer error.
if (i == 0) errored = true;
break;
}
res = (res * base) + d;
in_pos++;
}
if (!errored && res <= max_val) {
if (byte_literal) {
// Multibyte encodings necessitate that we keep adjacent byte escapes.
// - `\Xc3\Xb6` is "ö", but only together.
// (this assumes a valid codepoint can't consist of multiple bytes
// that are valid on their own, which is true for UTF-8)
byte_buff.push_back(static_cast<char>(res));
result_char_or_none = none();
if (input[in_pos] == L'\\' &&
(input[in_pos + 1] == L'X' || input[in_pos + 1] == L'x')) {
in_pos++;
continue;
}
} else {
result_char_or_none = static_cast<wchar_t>(res);
}
} else {
errored = true;
}
break;
}
// \a means bell (alert).
case L'a': {
result_char_or_none = L'\a';
break;
}
// \b means backspace.
case L'b': {
result_char_or_none = L'\b';
break;
}
// \cX means control sequence X.
case L'c': {
const wchar_t sequence_char = input[in_pos++];
if (sequence_char >= L'a' && sequence_char <= (L'a' + 32)) {
result_char_or_none = sequence_char - L'a' + 1;
} else if (sequence_char >= L'A' && sequence_char <= (L'A' + 32)) {
result_char_or_none = sequence_char - L'A' + 1;
} else {
errored = true;
}
break;
}
// \x1B means escape.
case L'e': {
result_char_or_none = L'\x1B';
break;
}
// \f means form feed.
case L'f': {
result_char_or_none = L'\f';
break;
}
// \n means newline.
case L'n': {
result_char_or_none = L'\n';
break;
}
// \r means carriage return.
case L'r': {
result_char_or_none = L'\r';
break;
}
// \t means tab.
case L't': {
result_char_or_none = L'\t';
break;
}
// \v means vertical tab.
case L'v': {
result_char_or_none = L'\v';
break;
}
// If a backslash is followed by an actual newline, swallow them both.
case L'\n': {
result_char_or_none = none();
break;
}
default: {
if (unescape_special) result->push_back(INTERNAL_SEPARATOR);
result_char_or_none = c;
break;
}
}
if (errored) return none();
if (!byte_buff.empty()) {
result->append(str2wcstring(byte_buff));
}
break;
}
if (result_char_or_none.has_value()) {
result->push_back(*result_char_or_none);
}
return in_pos;
}
wcstring format_size(long long sz) {
wcstring result;
const wchar_t *sz_name[] = {L"kB", L"MB", L"GB", L"TB", L"PB", L"EB", L"ZB", L"YB", nullptr};
if (sz < 0) {
result.append(L"unknown");
} else if (sz < 1) {
result.append(_(L"empty"));
} else if (sz < 1024) {
result.append(format_string(L"%lldB", sz));
} else {
int i;
for (i = 0; sz_name[i]; i++) {
if (sz < (1024 * 1024) || !sz_name[i + 1]) {
long isz = (static_cast<long>(sz)) / 1024;
if (isz > 9)
result.append(format_string(L"%ld%ls", isz, sz_name[i]));
else
result.append(
format_string(L"%.1f%ls", static_cast<double>(sz) / 1024, sz_name[i]));
break;
}
sz /= 1024;
}
}
return result;
}
/// Crappy function to extract the most significant digit of an unsigned long long value.
static char extract_most_significant_digit(unsigned long long *xp) {
unsigned long long place_value = 1;
@@ -1019,53 +759,6 @@ static char extract_most_significant_digit(unsigned long long *xp) {
return x + '0';
}
static void append_ull(char *buff, unsigned long long val, size_t *inout_idx, size_t max_len) {
size_t idx = *inout_idx;
while (val > 0 && idx < max_len) buff[idx++] = extract_most_significant_digit(&val);
*inout_idx = idx;
}
static void append_str(char *buff, const char *str, size_t *inout_idx, size_t max_len) {
size_t idx = *inout_idx;
while (*str && idx < max_len) buff[idx++] = *str++;
*inout_idx = idx;
}
void format_size_safe(char buff[128], unsigned long long sz) {
const size_t buff_size = 128;
const size_t max_len = buff_size - 1; // need to leave room for a null terminator
std::memset(buff, 0, buff_size);
size_t idx = 0;
const char *const sz_name[] = {"kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB", nullptr};
if (sz < 1) {
strcpy(buff, "empty");
} else if (sz < 1024) {
append_ull(buff, sz, &idx, max_len);
append_str(buff, "B", &idx, max_len);
} else {
for (size_t i = 0; sz_name[i]; i++) {
if (sz < (1024 * 1024) || !sz_name[i + 1]) {
unsigned long long isz = sz / 1024;
if (isz > 9) {
append_ull(buff, isz, &idx, max_len);
} else {
append_ull(buff, isz, &idx, max_len);
// Maybe append a single fraction digit.
unsigned long long remainder = sz % 1024;
if (remainder > 0) {
char tmp[3] = {'.', extract_most_significant_digit(&remainder), 0};
append_str(buff, tmp, &idx, max_len);
}
}
append_str(buff, sz_name[i], &idx, max_len);
break;
}
sz /= 1024;
}
}
}
double timef() {
struct timeval tv;
assert_with_errno(gettimeofday(&tv, nullptr) != -1);
@@ -1148,75 +841,6 @@ bool valid_var_name(const wchar_t *str) {
return true;
}
/// Test if the string is a valid function name.
bool valid_func_name(const wcstring &str) {
if (str.empty()) return false;
if (str.at(0) == L'-') return false;
// A function name needs to be a valid path, so no / and no NULL.
if (str.find_first_of(L'/') != wcstring::npos) return false;
if (str.find_first_of(L'\0') != wcstring::npos) return false;
return true;
}
/// Return the path to the current executable. This needs to be realpath'd.
std::string get_executable_path(const char *argv0) {
char buff[PATH_MAX];
#ifdef __APPLE__
// On OS X use it's proprietary API to get the path to the executable.
// This is basically grabbing exec_path after argc, argv, envp, ...: for us
// https://opensource.apple.com/source/adv_cmds/adv_cmds-163/ps/print.c
uint32_t buffSize = sizeof buff;
if (_NSGetExecutablePath(buff, &buffSize) == 0) return std::string(buff);
#elif defined(__BSD__) && defined(KERN_PROC_PATHNAME)
// BSDs do not have /proc by default, (although it can be mounted as procfs via the Linux
// compatibility layer). We can use sysctl instead: per sysctl(3), passing in a process ID of -1
// returns the value for the current process.
size_t buff_size = sizeof buff;
#if defined(__NetBSD__)
int name[] = {CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_PATHNAME};
#else
int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
#endif
int result = sysctl(name, sizeof(name) / sizeof(int), buff, &buff_size, nullptr, 0);
if (result != 0) {
wperror(L"sysctl KERN_PROC_PATHNAME");
} else {
return std::string(buff);
}
#else
// On other unixes, fall back to the Linux-ish /proc/ directory
ssize_t len;
len = readlink("/proc/self/exe", buff, sizeof buff - 1); // Linux
if (len == -1) {
len = readlink("/proc/curproc/file", buff, sizeof buff - 1); // other BSDs
if (len == -1) {
len = readlink("/proc/self/path/a.out", buff, sizeof buff - 1); // Solaris
}
}
if (len > 0) {
buff[len] = '\0';
// When /proc/self/exe points to a file that was deleted (or overwritten on update!)
// then linux adds a " (deleted)" suffix.
// If that's not a valid path, let's remove that awkward suffix.
std::string buffstr{buff};
if (access(buff, F_OK)) {
auto dellen = const_strlen(" (deleted)");
if (buffstr.size() > dellen &&
buffstr.compare(buffstr.size() - dellen, dellen, " (deleted)") == 0) {
buffstr = buffstr.substr(0, buffstr.size() - dellen);
}
}
return buffstr;
}
#endif
// Just return argv0, which probably won't work (i.e. it's not an absolute path or a path
// relative to the working directory, but instead something the caller found via $PATH). We'll
// eventually fall back to the compile time paths.
return std::string(argv0 ? argv0 : "");
}
/// Return a path to a directory where we can store temporary files.
std::string get_path_to_tmp_dir() {
char *env_tmpdir = getenv("TMPDIR");

View File

@@ -321,21 +321,12 @@ bool should_suppress_stderr_for_tests();
#define likely(x) __builtin_expect(bool(x), 1)
#define unlikely(x) __builtin_expect(bool(x), 0)
/// Format the specified size (in bytes, kilobytes, etc.) into the specified stringbuffer.
wcstring format_size(long long sz);
/// Version of format_size that does not allocate memory.
void format_size_safe(char buff[128], unsigned long long sz);
/// Writes out a long safely.
void format_long_safe(char buff[64], long val);
void format_long_safe(wchar_t buff[64], long val);
void format_llong_safe(wchar_t buff[64], long long val);
void format_ullong_safe(wchar_t buff[64], unsigned long long val);
/// "Narrows" a wide character string. This just grabs any ASCII characters and truncates.
void narrow_string_safe(char buff[64], const wchar_t *s);
/// Stored in blocks to reference the file which created the block.
using filename_ref_t = std::shared_ptr<wcstring>;
@@ -475,10 +466,6 @@ long read_blocked(int fd, void *buf, size_t count);
/// error.
ssize_t write_loop(int fd, const char *buff, size_t count);
/// Loop a read request while failure is non-critical. Return -1 and set errno in case of critical
/// error.
ssize_t read_loop(int fd, void *buff, size_t count);
/// Replace special characters with backslash escape sequences. Newline is replaced with \n, etc.
///
/// \param in The string to be escaped
@@ -489,19 +476,10 @@ wcstring escape_string(const wchar_t *in, escape_flags_t flags = 0,
wcstring escape_string(const wcstring &in, escape_flags_t flags = 0,
escape_string_style_t style = STRING_STYLE_SCRIPT);
/// Escape a string so that it may be inserted into a double-quoted string.
/// This permits ownership transfer.
wcstring escape_string_for_double_quotes(wcstring in);
/// Expand backslashed escapes and substitute them with their unescaped counterparts. Also
/// optionally change the wildcards, the tilde character and a few more into constants which are
/// defined in a private use area of Unicode. This assumes wchar_t is a unicode character set.
/// Given a null terminated string starting with a backslash, read the escape as if it is unquoted,
/// appending to result. Return the number of characters consumed, or none() on error.
maybe_t<size_t> read_unquoted_escape(const wchar_t *input, wcstring *result, bool allow_incomplete,
bool unescape_special);
/// Return the number of seconds from the UNIX epoch, with subsecond precision. This function uses
/// the gettimeofday function and will have the same precision as that function.
using timepoint_t = double;
@@ -552,7 +530,6 @@ std::string get_path_to_tmp_dir();
bool valid_var_name_char(wchar_t chr);
bool valid_var_name(const wcstring &str);
bool valid_var_name(const wchar_t *str);
bool valid_func_name(const wcstring &str);
// Return values (`$status` values for fish scripts) for various situations.
enum {
@@ -610,9 +587,6 @@ struct hash<const wcstring> {
} // namespace std
#endif
/// Get the absolute path to the fish executable itself
std::string get_executable_path(const char *argv0);
/// A RAII wrapper for resources that don't recur, so we don't have to create a separate RAII
/// wrapper for each function. Avoids needing to call "return cleanup()" or similar / everywhere.
struct cleanup_t {

View File

@@ -177,10 +177,6 @@ int env_stack_t::set_one(const wcstring &key, env_mode_flags_t mode, wcstring va
return set(key, mode, std::move(vals));
}
int env_stack_t::set_empty(const wcstring &key, env_mode_flags_t mode) {
return set(key, mode, {});
}
int env_stack_t::remove(const wcstring &key, int mode) {
return static_cast<int>(impl_->remove(key, mode));
}
@@ -203,8 +199,6 @@ std::shared_ptr<environment_t> env_stack_t::snapshot() const {
return std::static_pointer_cast<environment_t>(res);
}
void env_stack_t::set_argv(std::vector<wcstring> argv) { set(L"argv", ENV_LOCAL, std::move(argv)); }
wcstring env_stack_t::get_pwd_slash() const {
std::unique_ptr<wcstring> res = impl_->get_pwd_slash();
return std::move(*res);

View File

@@ -221,8 +221,6 @@ class env_stack_t final : public environment_t {
int set_one(const wcstring &key, env_mode_flags_t mode, wcstring val);
/// Sets the variable with the specified name to no values.
int set_empty(const wcstring &key, env_mode_flags_t mode);
/// Update the PWD variable based on the result of getcwd.
void set_pwd_from_getcwd();
@@ -248,9 +246,6 @@ class env_stack_t final : public environment_t {
/// you want to read from another thread.
std::shared_ptr<environment_t> snapshot() const;
/// Sets up argv as the given list of strings.
void set_argv(std::vector<wcstring> argv);
/// Slightly optimized implementation.
wcstring get_pwd_slash() const override;

View File

@@ -5,8 +5,6 @@
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
// We need the sys/file.h for the flock() declaration on Linux but not OS X.
#include <sys/file.h> // IWYU pragma: keep
// We need the ioctl.h header so we can check if SIOCGIFHWADDR is defined by it so we know if we're
// on a Linux system.
#include <netinet/in.h> // IWYU pragma: keep

View File

@@ -43,20 +43,6 @@ char *tparm_solaris_kludge(char *str, long p1, long p2, long p3, long p4, long p
}
#endif
int fish_mkstemp_cloexec(char *name_template) {
#if HAVE_MKOSTEMP
// null check because mkostemp may be a weak symbol
if (&mkostemp != nullptr) {
return mkostemp(name_template, O_CLOEXEC);
}
#endif
int result_fd = mkstemp(name_template);
if (result_fd != -1) {
fcntl(result_fd, F_SETFD, FD_CLOEXEC);
}
return result_fd;
}
/// Fallback implementations of wcsncasecmp and wcscasecmp. On systems where these are not needed
/// (e.g. building on Linux) these should end up just being stripped, as they are static functions
/// that are not referenced in this file.
@@ -193,72 +179,3 @@ int fish_wcswidth(const wchar_t *str, size_t n) {
}
return result;
}
#ifndef HAVE_FLOCK
/* $NetBSD: flock.c,v 1.6 2008/04/28 20:24:12 martin Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Todd Vierling.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Emulate flock() with fcntl().
*/
int flock(int fd, int op) {
int rc = 0;
struct flock fl = {0};
switch (op & (LOCK_EX | LOCK_SH | LOCK_UN)) {
case LOCK_EX:
fl.l_type = F_WRLCK;
break;
case LOCK_SH:
fl.l_type = F_RDLCK;
break;
case LOCK_UN:
fl.l_type = F_UNLCK;
break;
default:
errno = EINVAL;
return -1;
}
fl.l_whence = SEEK_SET;
rc = fcntl(fd, op & LOCK_NB ? F_SETLK : F_SETLKW, &fl);
if (rc && (errno == EAGAIN)) errno = EWOULDBLOCK;
return rc;
}
#endif // HAVE_FLOCK

View File

@@ -23,11 +23,6 @@ extern int32_t FISH_EMOJI_WIDTH;
int fish_wcwidth(wchar_t wc);
int fish_wcswidth(const wchar_t *str, size_t n);
// Replacement for mkostemp(str, O_CLOEXEC)
// This uses mkostemp if available,
// otherwise it uses mkstemp followed by fcntl
int fish_mkstemp_cloexec(char *);
/// thread_local support.
#if HAVE_CX11_THREAD_LOCAL
#define FISH_THREAD_LOCAL thread_local
@@ -115,16 +110,4 @@ char *fish_textdomain(const char *domainname);
int killpg(int pgr, int sig);
#endif
#ifndef HAVE_FLOCK
/// Fallback implementation of flock in terms of fcntl.
/// Danger! The semantics of flock and fcntl locking are very different.
/// Use with caution.
int flock(int fd, int op);
#define LOCK_SH 1 // Shared lock.
#define LOCK_EX 2 // Exclusive lock.
#define LOCK_UN 8 // Unlock.
#define LOCK_NB 4 // Don't block when locking.
#endif
#endif // FISH_FALLBACK_H

View File

@@ -204,48 +204,6 @@ static int parse_util_locate_cmdsub(const wchar_t *in, const wchar_t **begin, co
return 1;
}
long parse_util_slice_length(const wchar_t *in) {
assert(in && "null parameter");
const wchar_t openc = L'[';
const wchar_t closec = L']';
bool escaped = false;
// Check for initial opening [
if (*in != openc) return 0;
int bracket_count = 1;
assert(in && "null parameter");
for (const wchar_t *pos = in + 1; *pos; pos++) {
if (!escaped) {
if (*pos == L'\'' || *pos == L'"') {
const wchar_t *q_end = quote_end(pos, *pos);
if (q_end && *q_end) {
pos = q_end;
} else {
break;
}
} else {
if (*pos == openc) {
bracket_count++;
} else if (*pos == closec) {
bracket_count--;
if (bracket_count == 0) {
// pos points at the closing ], so add 1.
return pos - in + 1;
}
}
}
}
if (*pos == '\\') {
escaped = !escaped;
} else {
escaped = false;
}
}
assert(bracket_count > 0 && "Should have unclosed brackets");
return -1;
}
int parse_util_locate_cmdsubst_range(const wcstring &str, size_t *inout_cursor_offset,
wcstring *out_contents, size_t *out_start, size_t *out_end,
bool accept_incomplete, bool *inout_is_quoted,
@@ -612,8 +570,6 @@ static bool append_syntax_error(parse_error_list_t *errors, size_t source_locati
return true;
}
bool parse_util_argument_is_help(const wcstring &s) { return s == L"-h" || s == L"--help"; }
// \return a pointer to the first argument node of an argument_or_redirection_list_t, or nullptr if
// there are no arguments.
static const ast::argument_t *get_first_arg(const ast::argument_or_redirection_list_t &list) {

View File

@@ -18,11 +18,6 @@
struct Tok;
using tok_t = Tok;
/// Handles slices: the square brackets in an expression like $foo[5..4]
/// \return the length of the slice starting at \p in, or 0 if there is no slice, or -1 on error.
/// This never accepts incomplete slices.
long parse_util_slice_length(const wchar_t *in);
/// Alternative API. Iterate over command substitutions.
///
/// \param str the string to search for subshells
@@ -101,9 +96,6 @@ size_t parse_util_get_offset(const wcstring &str, int line, long line_offset);
/// transformation.
wcstring parse_util_unescape_wildcards(const wcstring &str);
/// Checks if the specified string is a help option.
bool parse_util_argument_is_help(const wcstring &s);
/// Calculates information on the parameter at the specified index.
///
/// \param cmd The command to be analyzed

View File

@@ -83,15 +83,6 @@ static get_path_result_t path_get_path_core(const wcstring &cmd,
return best;
}
maybe_t<wcstring> path_get_path(const wcstring &cmd, const environment_t &vars) {
auto result = path_try_get_path(cmd, vars);
if (result.err != 0) {
return none();
}
wcstring path = std::move(result.path);
return path;
}
get_path_result_t path_try_get_path(const wcstring &cmd, const environment_t &vars) {
auto pathvar = vars.get(L"PATH");
return path_get_path_core(cmd, pathvar ? pathvar->as_list() : kDefaultPath);
@@ -196,81 +187,6 @@ maybe_t<wcstring> path_get_cdpath(const wcstring &dir, const wcstring &wd,
return none();
}
maybe_t<wcstring> path_as_implicit_cd(const wcstring &path, const wcstring &wd,
// todo!("should be environment_t")
const env_stack_t &vars) {
wcstring exp_path = path;
expand_tilde(exp_path, vars);
if (string_prefixes_string(L"/", exp_path) || string_prefixes_string(L"./", exp_path) ||
string_prefixes_string(L"../", exp_path) || string_suffixes_string(L"/", exp_path) ||
exp_path == L"..") {
// These paths can be implicit cd, so see if you cd to the path. Note that a single period
// cannot (that's used for sourcing files anyways).
return path_get_cdpath(exp_path, wd, vars);
}
return none();
}
// If the given path looks like it's relative to the working directory, then prepend that working
// directory. This operates on unescaped paths only (so a ~ means a literal ~).
wcstring path_apply_working_directory(const wcstring &path, const wcstring &working_directory) {
if (path.empty() || working_directory.empty()) return path;
// We're going to make sure that if we want to prepend the wd, that the string has no leading
// "/".
bool prepend_wd = path.at(0) != L'/' && path.at(0) != HOME_DIRECTORY;
if (!prepend_wd) {
// No need to prepend the wd, so just return the path we were given.
return path;
}
// Remove up to one "./".
wcstring path_component = path;
if (string_prefixes_string(L"./", path_component)) {
path_component.erase(0, 2);
}
// Removing leading /s.
while (string_prefixes_string(L"/", path_component)) {
path_component.erase(0, 1);
}
// Construct and return a new path.
wcstring new_path = working_directory;
append_path_component(new_path, path_component);
return new_path;
}
/// We separate this from path_create() for two reasons. First it's only caused if there is a
/// problem, and thus is not central to the behavior of that function. Second, we only want to issue
/// the message once. If the current shell starts a new fish shell (e.g., by running `fish -c` from
/// a function) we don't want that subshell to issue the same warnings.
static void maybe_issue_path_warning(const wcstring &which_dir, const wcstring &custom_error_msg,
bool using_xdg, const wcstring &xdg_var, const wcstring &path,
int saved_errno, env_stack_t &vars) {
wcstring warning_var_name = L"_FISH_WARNED_" + which_dir;
if (vars.get(warning_var_name, ENV_GLOBAL | ENV_EXPORT)) {
return;
}
vars.set_one(warning_var_name, ENV_GLOBAL | ENV_EXPORT, L"1");
FLOG(error, custom_error_msg.c_str());
if (path.empty()) {
FLOGF(warning_path, _(L"Unable to locate the %ls directory."), which_dir.c_str());
FLOGF(warning_path,
_(L"Please set the %ls or HOME environment variable before starting fish."),
xdg_var.c_str());
} else {
const wchar_t *env_var = using_xdg ? xdg_var.c_str() : L"HOME";
FLOGF(warning_path, _(L"Unable to locate %ls directory derived from $%ls: '%ls'."),
which_dir.c_str(), env_var, path.c_str());
FLOGF(warning_path, _(L"The error was '%s'."), std::strerror(saved_errno));
FLOGF(warning_path, _(L"Please set $%ls to a directory where you have write access."),
env_var);
}
ignore_result(write(STDERR_FILENO, "\n", 1));
}
/// Make sure the specified directory exists. If needed, try to create it and any currently not
/// existing parent directories, like mkdir -p,.
///
@@ -350,27 +266,6 @@ static const base_directory_t &get_config_directory() {
return s_dir;
}
void path_emit_config_directory_messages(env_stack_t &vars) {
const auto &data = get_data_directory();
if (!data.success()) {
maybe_issue_path_warning(L"data", _(L"can not save history"), data.used_xdg,
L"XDG_DATA_HOME", data.path, data.err, vars);
}
if (data.remoteness == dir_remoteness_t::remote) {
FLOG(path, "data path appears to be on a network volume");
}
const auto &config = get_config_directory();
if (!config.success()) {
maybe_issue_path_warning(L"config", _(L"can not save universal variables or functions"),
config.used_xdg, L"XDG_CONFIG_HOME", config.path, config.err,
vars);
}
if (config.remoteness == dir_remoteness_t::remote) {
FLOG(path, "config path appears to be on a network volume");
}
}
bool path_get_config(wcstring &path) {
const auto &dir = get_config_directory();
path = dir.success() ? dir.path : L"";
@@ -383,10 +278,6 @@ bool path_get_data(wcstring &path) {
return dir.success();
}
dir_remoteness_t path_get_data_remoteness() { return get_data_directory().remoteness; }
dir_remoteness_t path_get_config_remoteness() { return get_config_directory().remoteness; }
bool paths_are_equivalent(const wcstring &p1, const wcstring &p2) {
if (p1 == p2) return true;
@@ -417,38 +308,6 @@ bool paths_are_equivalent(const wcstring &p1, const wcstring &p2) {
return idx1 == len1 && idx2 == len2;
}
bool path_is_valid(const wcstring &path, const wcstring &working_directory) {
bool path_is_valid;
// Some special paths are always valid.
if (path.empty()) {
path_is_valid = false;
} else if (path == L"." || path == L"./") {
path_is_valid = true;
} else if (path == L".." || path == L"../") {
path_is_valid = (!working_directory.empty() && working_directory != L"/");
} else if (path.at(0) != '/') {
// Prepend the working directory. Note that we know path is not empty here.
wcstring tmp = working_directory;
tmp.append(path);
path_is_valid = (0 == waccess(tmp, F_OK));
} else {
// Simple check.
path_is_valid = (0 == waccess(path, F_OK));
}
return path_is_valid;
}
bool paths_are_same_file(const wcstring &path1, const wcstring &path2) {
if (paths_are_equivalent(path1, path2)) return true;
struct stat s1, s2;
if (wstat(path1, &s1) == 0 && wstat(path2, &s2) == 0) {
return s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev;
}
return false;
}
void append_path_component(wcstring &path, const wcstring &component) {
if (path.empty() || component.empty()) {
path.append(component);

View File

@@ -35,21 +35,6 @@ enum class dir_remoteness_t {
remote, // directory is known remote
};
/// \return the remoteness of the fish data directory.
/// This will be remote for filesystems like NFS, SMB, etc.
dir_remoteness_t path_get_data_remoteness();
/// Like path_get_data_remoteness but for the config directory.
dir_remoteness_t path_get_config_remoteness();
/// Emit any errors if config directories are missing.
/// Use the given environment stack to ensure this only occurs once.
void path_emit_config_directory_messages(env_stack_t &vars);
/// Finds the path of an executable named \p cmd, by looking in $PATH taken from \p vars.
/// \returns the path if found, none if not.
maybe_t<wcstring> path_get_path(const wcstring &cmd, const environment_t &vars);
/// Finds the path of an executable named \p cmd, by looking in $PATH taken from \p vars.
/// On success, err will be 0 and the path is returned.
/// On failure, we return the "best path" with err set appropriately.
@@ -81,24 +66,10 @@ maybe_t<wcstring> path_get_cdpath(const wcstring &dir, const wcstring &wd,
std::vector<wcstring> path_apply_cdpath(const wcstring &dir, const wcstring &wd,
const env_stack_t &env_vars);
/// Returns the path resolved as an implicit cd command, or none() if none. This requires it to
/// start with one of the allowed prefixes (., .., ~) and resolve to a directory.
maybe_t<wcstring> path_as_implicit_cd(const wcstring &path, const wcstring &wd,
const env_stack_t &vars);
/// Check if two paths are equivalent, which means to ignore runs of multiple slashes (or trailing
/// slashes).
bool paths_are_equivalent(const wcstring &p1, const wcstring &p2);
bool path_is_valid(const wcstring &path, const wcstring &working_directory);
/// Returns whether the two paths refer to the same file.
bool paths_are_same_file(const wcstring &path1, const wcstring &path2);
/// If the given path looks like it's relative to the working directory, then prepend that working
/// directory. This operates on unescaped paths only (so a ~ means a literal ~).
wcstring path_apply_working_directory(const wcstring &path, const wcstring &working_directory);
/// Appends a path component, with a / if necessary.
void append_path_component(wcstring &path, const wcstring &component);

View File

@@ -259,34 +259,6 @@ std::vector<wcstring> split_string(const wcstring &val, wchar_t sep) {
return out;
}
std::vector<wcstring> split_string_tok(const wcstring &val, const wcstring &seps,
size_t max_results) {
std::vector<wcstring> out;
size_t end = val.size();
size_t pos = 0;
while (pos < end && out.size() + 1 < max_results) {
// Skip leading seps.
pos = val.find_first_not_of(seps, pos);
if (pos == wcstring::npos) break;
// Find next sep.
size_t next_sep = val.find_first_of(seps, pos);
if (next_sep == wcstring::npos) {
next_sep = end;
}
out.emplace_back(val, pos, next_sep - pos);
// Note we skip exactly one sep here. This is because on the last iteration we retain all
// but the first leading separators. This is historical.
pos = next_sep + 1;
}
if (pos < end && max_results > 0) {
assert(out.size() + 1 == max_results && "Should have split the max");
out.emplace_back(val, pos);
}
assert(out.size() <= max_results && "Got too many results");
return out;
}
static wcstring join_strings_impl(const std::vector<wcstring> &vals, const wchar_t *sep,
size_t seplen) {
if (vals.empty()) return wcstring{};

View File

@@ -130,16 +130,6 @@ inline maybe_t<string_fuzzy_match_t> string_fuzzy_match_string(const wcstring &s
/// Split a string by a separator character.
std::vector<wcstring> split_string(const wcstring &val, wchar_t sep);
/// Split a string by runs of any of the separator characters provided in \p seps.
/// Note the delimiters are the characters in \p seps, not \p seps itself.
/// \p seps may contain the NUL character.
/// Do not output more than \p max_results results. If we are to output exactly that much,
/// the last output is the the remainder of the input, including leading delimiters,
/// except for the first. This is historical behavior.
/// Example: split_string_tok(" a b c ", " ", 3) -> {"a", "b", " c "}
std::vector<wcstring> split_string_tok(const wcstring &val, const wcstring &seps,
size_t max_results = std::numeric_limits<size_t>::max());
/// Join a list of strings by a separator character or string.
wcstring join_strings(const std::vector<wcstring> &vals, wchar_t sep);
wcstring join_strings(const std::vector<wcstring> &vals, const wchar_t *sep);

View File

@@ -45,17 +45,6 @@ wcstring_list_ffi_t::~wcstring_list_ffi_t() = default;
/// Map used as cache by wgettext.
static owning_lock<std::unordered_map<wcstring, wcstring>> wgettext_map;
wcstring wgetcwd() {
char cwd[PATH_MAX];
char *res = getcwd(cwd, sizeof(cwd));
if (res) {
return str2wcstring(res);
}
FLOGF(error, _(L"getcwd() failed with errno %d/%s"), errno, std::strerror(errno));
return wcstring();
}
DIR *wopendir(const wcstring &name) {
const cstring tmp = wcs2zstring(name);
return opendir(tmp.c_str());
@@ -261,11 +250,6 @@ int waccess(const wcstring &file_name, int mode) {
return access(tmp.c_str(), mode);
}
int wunlink(const wcstring &file_name) {
const cstring tmp = wcs2zstring(file_name);
return unlink(tmp.c_str());
}
void wperror(wcharz_t s) {
int e = errno;
if (s.str[0] != L'\0') {
@@ -294,59 +278,6 @@ int make_fd_blocking(int fd) {
return err == -1 ? errno : 0;
}
/// Wide character realpath. The last path component does not need to be valid. If an error occurs,
/// wrealpath() returns none() and errno is likely set.
maybe_t<wcstring> wrealpath(const wcstring &pathname) {
if (pathname.empty()) return none();
cstring real_path;
cstring narrow_path = wcs2zstring(pathname);
// Strip trailing slashes. This is treats "/a//" as equivalent to "/a" if /a is a non-directory.
while (narrow_path.size() > 1 && narrow_path.at(narrow_path.size() - 1) == '/') {
narrow_path.erase(narrow_path.size() - 1, 1);
}
char tmpbuf[PATH_MAX];
char *narrow_res = realpath(narrow_path.c_str(), tmpbuf);
if (narrow_res) {
real_path.append(narrow_res);
} else {
// Check if everything up to the last path component is valid.
size_t pathsep_idx = narrow_path.rfind('/');
if (pathsep_idx == 0) {
// If the only pathsep is the first character then it's an absolute path with a
// single path component and thus doesn't need conversion.
real_path = narrow_path;
} else {
// Only call realpath() on the portion up to the last component.
errno = 0;
if (pathsep_idx == cstring::npos) {
// If there is no "/", this is a file in $PWD, so give the realpath to that.
narrow_res = realpath(".", tmpbuf);
} else {
errno = 0;
// Only call realpath() on the portion up to the last component.
narrow_res = realpath(narrow_path.substr(0, pathsep_idx).c_str(), tmpbuf);
}
if (!narrow_res) return none();
pathsep_idx++;
real_path.append(narrow_res);
// This test is to deal with cases such as /../../x => //x.
if (real_path.size() > 1) real_path.append("/");
real_path.append(narrow_path.substr(pathsep_idx, cstring::npos));
}
}
return str2wcstring(real_path);
}
wcstring normalize_path(const wcstring &path, bool allow_leading_double_slashes) {
// Count the leading slashes.
const wchar_t sep = L'/';
@@ -514,12 +445,6 @@ int wmkdir(const wcstring &name, int mode) {
return mkdir(name_narrow.c_str(), mode);
}
int wrename(const wcstring &old, const wcstring &newv) {
cstring old_narrow = wcs2zstring(old);
cstring new_narrow = wcs2zstring(newv);
return rename(old_narrow.c_str(), new_narrow.c_str());
}
ssize_t wwrite_to_fd(const wchar_t *input, size_t input_len, int fd) {
// Accumulate data in a local buffer.
char accum[512];
@@ -740,24 +665,6 @@ file_id_t file_id_for_fd(int fd) {
file_id_t file_id_for_fd(const autoclose_fd_t &fd) { return file_id_for_fd(fd.fd()); }
file_id_t file_id_for_path(const wcstring &path) {
file_id_t result = kInvalidFileID;
struct stat buf = {};
if (0 == wstat(path, &buf)) {
result = file_id_t::from_stat(buf);
}
return result;
}
file_id_t file_id_for_path(const std::string &path) {
file_id_t result = kInvalidFileID;
struct stat buf = {};
if (0 == stat(path.c_str(), &buf)) {
result = file_id_t::from_stat(buf);
}
return result;
}
bool file_id_t::operator==(const file_id_t &rhs) const { return this->compare_file_id(rhs) == 0; }
bool file_id_t::operator!=(const file_id_t &rhs) const { return !(*this == rhs); }

View File

@@ -89,19 +89,9 @@ int lwstat(const wcstring &file_name, struct stat *buf);
/// Wide character version of access().
int waccess(const wcstring &file_name, int mode);
/// Wide character version of unlink().
int wunlink(const wcstring &file_name);
/// Wide character version of perror().
void wperror(wcharz_t s);
/// Wide character version of getcwd().
wcstring wgetcwd();
/// Wide character version of realpath function.
/// \returns the canonicalized path, or none if the path is invalid.
maybe_t<wcstring> wrealpath(const wcstring &pathname);
/// Given an input path, "normalize" it:
/// 1. Collapse multiple /s into a single /, except maybe at the beginning.
/// 2. .. goes up a level.
@@ -130,9 +120,6 @@ const wchar_t *wgettext_ptr(const wchar_t *in);
/// Wide character version of mkdir.
int wmkdir(const wcstring &name, int mode);
/// Wide character version of rename.
int wrename(const wcstring &oldName, const wcstring &newv);
/// Write a wide string to a file descriptor. This avoids doing any additional allocation.
/// This does NOT retry on EINTR or EAGAIN, it simply returns.
/// \return -1 on error in which case errno will have been set. In this event, the number of bytes
@@ -317,8 +304,6 @@ struct hash<file_id_t> {
file_id_t file_id_for_fd(int fd);
file_id_t file_id_for_fd(const autoclose_fd_t &fd);
file_id_t file_id_for_path(const wcstring &path);
file_id_t file_id_for_path(const std::string &path);
extern const file_id_t kInvalidFileID;