aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Kurtis Rader <krader@skepticism.us>2016-05-03 15:18:24 -0700
committerGravatar Kurtis Rader <krader@skepticism.us>2016-05-03 16:09:45 -0700
commit5c8763be0e68bbdec3fdd1edb5754f4c421098e1 (patch)
tree8b9a5068fa2f87d0a97c61df1336cd083c6b1504 /src
parentee44879d4d6ae28968885823db5f0ce13e5a6dec (diff)
restyle remaining modules to match project style
For this change I decided to bundle the remaining modules that need to be resytyled because only two were large enough to warrant doing on their own. Reduces lint errors from 225 to 162 (-28%). Line count from 3073 to 2465 (-20%). Another step in resolving issue #2902.
Diffstat (limited to 'src')
-rw-r--r--src/util.cpp80
-rw-r--r--src/util.h92
-rw-r--r--src/wcstringutil.cpp23
-rw-r--r--src/wcstringutil.h31
-rw-r--r--src/wgetopt.cpp640
-rw-r--r--src/wgetopt.h297
-rw-r--r--src/wildcard.cpp1303
-rw-r--r--src/wildcard.h115
-rw-r--r--src/wutil.cpp406
-rw-r--r--src/wutil.h141
10 files changed, 1260 insertions, 1868 deletions
diff --git a/src/util.cpp b/src/util.cpp
index 9d084af6..316bac68 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,39 +1,32 @@
-/** \file util.c
- Generic utilities library.
-
- Contains datastructures such as automatically growing array lists, priority queues, etc.
-*/
+// Generic utilities library.
+//
+// Contains data structures such as automatically growing array lists, priority queues, etc.
+#include <errno.h>
#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
#include <wchar.h>
#include <wctype.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <sys/time.h>
+#include "common.h"
#include "fallback.h" // IWYU pragma: keep
#include "util.h"
-#include "common.h"
#include "wutil.h" // IWYU pragma: keep
-int wcsfilecmp(const wchar_t *a, const wchar_t *b)
-{
+int wcsfilecmp(const wchar_t *a, const wchar_t *b) {
CHECK(a, 0);
CHECK(b, 0);
- if (*a==0)
- {
- if (*b==0)
- return 0;
+ if (*a == 0) {
+ if (*b == 0) return 0;
return -1;
}
- if (*b==0)
- {
+ if (*b == 0) {
return 1;
}
- long secondary_diff=0;
- if (iswdigit(*a) && iswdigit(*b))
- {
+ long secondary_diff = 0;
+ if (iswdigit(*a) && iswdigit(*b)) {
wchar_t *aend, *bend;
long al;
long bl;
@@ -43,53 +36,40 @@ int wcsfilecmp(const wchar_t *a, const wchar_t *b)
al = wcstol(a, &aend, 10);
bl = wcstol(b, &bend, 10);
- if (errno)
- {
- /*
- Huuuuuuuuge numbers - fall back to regular string comparison
- */
+ if (errno) {
+ // Huge numbers - fall back to regular string comparison.
return wcscmp(a, b);
}
diff = al - bl;
- if (diff)
- return diff > 0 ? 2 : -2;
+ if (diff) return diff > 0 ? 2 : -2;
- secondary_diff = (aend-a) - (bend-b);
+ secondary_diff = (aend - a) - (bend - b);
- a=aend-1;
- b=bend-1;
- }
- else
- {
+ a = aend - 1;
+ b = bend - 1;
+ } else {
int diff = towlower(*a) - towlower(*b);
- if (diff != 0)
- return (diff>0)?2:-2;
+ if (diff != 0) return (diff > 0) ? 2 : -2;
- secondary_diff = *a-*b;
+ secondary_diff = *a - *b;
}
- int res = wcsfilecmp(a+1, b+1);
+ int res = wcsfilecmp(a + 1, b + 1);
- if (abs(res) < 2)
- {
- /*
- No primary difference in rest of string.
- Use secondary difference on this element if found.
- */
- if (secondary_diff)
- {
- return secondary_diff > 0 ? 1 :-1;
+ if (abs(res) < 2) {
+ // No primary difference in rest of string. Use secondary difference on this element if
+ // found.
+ if (secondary_diff) {
+ return secondary_diff > 0 ? 1 : -1;
}
}
return res;
}
-long long get_time()
-{
+long long get_time() {
struct timeval time_struct;
gettimeofday(&time_struct, 0);
- return 1000000ll*time_struct.tv_sec+time_struct.tv_usec;
+ return 1000000ll * time_struct.tv_sec + time_struct.tv_usec;
}
-
diff --git a/src/util.h b/src/util.h
index d073ef83..9d2e4bbb 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,67 +1,49 @@
-/** \file util.h
- Generic utilities library.
-*/
-
+// Generic utilities library.
#ifndef FISH_UTIL_H
#define FISH_UTIL_H
-/**
- Returns the larger of two ints
-*/
-template<typename T>
-inline T maxi(T a, T b)
-{
- return a>b?a:b;
+/// Returns the larger of two ints.
+template <typename T>
+inline T maxi(T a, T b) {
+ return a > b ? a : b;
}
-/**
- Returns the smaller of two ints
- */
-template<typename T>
-inline T mini(T a, T b)
-{
- return a<b?a:b;
+/// Returns the smaller of two ints.
+template <typename T>
+inline T mini(T a, T b) {
+ return a < b ? a : b;
}
-/**
- Compares two wide character strings with an (arguably) intuitive
- ordering.
-
- This function tries to order strings in a way which is intuitive to
- humans with regards to sorting strings containing numbers.
-
- Most sorting functions would sort the strings 'file1.txt'
- 'file5.txt' and 'file12.txt' as:
-
- file1.txt
- file12.txt
- file5.txt
-
- This function regards any sequence of digits as a single entity
- when performing comparisons, so the output is instead:
-
- file1.txt
- file5.txt
- file12.txt
-
- Which most people would find more intuitive.
-
- This won't return the optimum results for numbers in bases higher
- than ten, such as hexadecimal, but at least a stable sort order
- will result.
-
- This function performs a two-tiered sort, where difference in case
- and in number of leading zeroes in numbers only have effect if no
- other differences between strings are found. This way, a 'file1'
- and 'File1' will not be considered identical, and hence their
- internal sort order is not arbitrary, but the names 'file1',
- 'File2' and 'file3' will still be sorted in the order given above.
-*/
+/// Compares two wide character strings with an (arguably) intuitive ordering. This function tries
+/// to order strings in a way which is intuitive to humans with regards to sorting strings
+/// containing numbers.
+///
+/// Most sorting functions would sort the strings 'file1.txt' 'file5.txt' and 'file12.txt' as:
+///
+/// file1.txt
+/// file12.txt
+/// file5.txt
+///
+/// This function regards any sequence of digits as a single entity when performing comparisons, so
+/// the output is instead:
+///
+/// file1.txt
+/// file5.txt
+/// file12.txt
+///
+/// Which most people would find more intuitive.
+///
+/// This won't return the optimum results for numbers in bases higher than ten, such as hexadecimal,
+/// but at least a stable sort order will result.
+///
+/// This function performs a two-tiered sort, where difference in case and in number of leading
+/// zeroes in numbers only have effect if no other differences between strings are found. This way,
+/// a 'file1' and 'File1' will not be considered identical, and hence their internal sort order is
+/// not arbitrary, but the names 'file1', 'File2' and 'file3' will still be sorted in the order
+/// given above.
int wcsfilecmp(const wchar_t *a, const wchar_t *b);
-/**
- Get the current time in microseconds since Jan 1, 1970
-*/
+/// Get the current time in microseconds since Jan 1, 1970.
long long get_time();
#endif
diff --git a/src/wcstringutil.cpp b/src/wcstringutil.cpp
index b752409b..3983eb53 100644
--- a/src/wcstringutil.cpp
+++ b/src/wcstringutil.cpp
@@ -1,24 +1,18 @@
-/** \file wcstringutil.cpp
-
-Helper functions for working with wcstring
-*/
-#include "common.h"
+// Helper functions for working with wcstring.
#include "wcstringutil.h"
+#include "common.h"
typedef wcstring::size_type size_type;
-wcstring_range wcstring_tok(wcstring& str, const wcstring &needle, wcstring_range last)
-{
+wcstring_range wcstring_tok(wcstring& str, const wcstring& needle, wcstring_range last) {
size_type pos = last.second == wcstring::npos ? wcstring::npos : last.first;
if (pos != wcstring::npos && last.second != wcstring::npos) pos += last.second;
if (pos != wcstring::npos && pos != 0) ++pos;
- if (pos == wcstring::npos || pos >= str.size())
- {
+ if (pos == wcstring::npos || pos >= str.size()) {
return std::make_pair(wcstring::npos, wcstring::npos);
}
- if (needle.empty())
- {
+ if (needle.empty()) {
return std::make_pair(pos, wcstring::npos);
}
@@ -26,12 +20,9 @@ wcstring_range wcstring_tok(wcstring& str, const wcstring &needle, wcstring_rang
if (pos == wcstring::npos) return std::make_pair(wcstring::npos, wcstring::npos);
size_type next_pos = str.find_first_of(needle, pos);
- if (next_pos == wcstring::npos)
- {
+ if (next_pos == wcstring::npos) {
return std::make_pair(pos, wcstring::npos);
- }
- else
- {
+ } else {
str[next_pos] = L'\0';
return std::make_pair(pos, next_pos - pos);
}
diff --git a/src/wcstringutil.h b/src/wcstringutil.h
index d2feec07..ea4489e7 100644
--- a/src/wcstringutil.h
+++ b/src/wcstringutil.h
@@ -1,7 +1,4 @@
-/** \file wcstringutil.h
-
-Helper functions for working with wcstring
-*/
+// Helper functions for working with wcstring.
#ifndef FISH_WCSTRINGUTIL_H
#define FISH_WCSTRINGUTIL_H
@@ -10,21 +7,19 @@ Helper functions for working with wcstring
#include "common.h"
-/**
- typedef that represents a range in a wcstring.
- The first element is the location, the second is the count.
-*/
+/// Typedef that represents a range in a wcstring. The first element is the location, the second is
+/// the count.
typedef std::pair<wcstring::size_type, wcstring::size_type> wcstring_range;
-/**
- wcstring equivalent of wcstok(). Supports NUL.
- For convenience and wcstok() compatibility, the first character of each
- token separator is replaced with NUL.
- Returns a pair of (pos, count).
- Returns (npos, npos) when it's done.
- Returns (pos, npos) when the token is already known to be the final token.
- Note that the final token may not necessarily return (pos, npos).
-*/
-wcstring_range wcstring_tok(wcstring& str, const wcstring &needle, wcstring_range last = wcstring_range(0,0));
+/// wcstring equivalent of wcstok(). Supports NUL. For convenience and wcstok() compatibility, the
+/// first character of each token separator is replaced with NUL.
+///
+/// Returns a pair of (pos, count).
+/// Returns (npos, npos) when it's done.
+/// Returns (pos, npos) when the token is already known to be the final token.
+///
+/// Note that the final token may not necessarily return (pos, npos).
+wcstring_range wcstring_tok(wcstring& str, const wcstring& needle,
+ wcstring_range last = wcstring_range(0, 0));
#endif
diff --git a/src/wgetopt.cpp b/src/wgetopt.cpp
index 02476718..d85b5e74 100644
--- a/src/wgetopt.cpp
+++ b/src/wgetopt.cpp
@@ -1,85 +1,68 @@
-/** \file wgetopt.c
- A version of the getopt library for use with wide character strings.
-
- This is simply the gnu getopt library, but converted for use with
- wchar_t instead of char. This is not usually useful since the argv
- array is always defined to be of type char**, but in fish, all
- internal commands use wide characters and hence this library is
- useful.
-
- If you want to use this version of getopt in your program,
- download the fish sourcecode, available at <a
- href='http://fishshell.com'>the fish homepage</a>. Extract
- the sourcode, copy wgetopt.c and wgetopt.h into your program
- directory, include wgetopt.h in your program, and use all the
- regular getopt functions, prefixing every function, global
- variable and structure with a 'w', and use only wide character
- strings. There are no other functional changes in this version of
- getopt besides using wide character strings.
-
- For examples of how to use wgetopt, see the fish builtin
- functions, many of which are defined in builtin.c.
-
-*/
-
-
-/* Getopt for GNU.
- NOTE: getopt is now part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
- before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
- Free Software Foundation, Inc.
-
- This file is part of the GNU C Library. Its master source is NOT part of
- the C library, however. The master source lives in /gd/gnu/lib.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If
- not, write to the Free Software Foundation, Inc., 675 Mass Ave,
- Cambridge, MA 02139, USA. */
-
+// A version of the getopt library for use with wide character strings.
+//
+// This is simply the gnu getopt library, but converted for use with wchar_t instead of char. This
+// is not usually useful since the argv array is always defined to be of type char**, but in fish,
+// all internal commands use wide characters and hence this library is useful.
+//
+// If you want to use this version of getopt in your program, download the fish sourcecode,
+// available at <a href='http://fishshell.com'>the fish homepage</a>. Extract the sourcode, copy
+// wgetopt.c and wgetopt.h into your program directory, include wgetopt.h in your program, and use
+// all the regular getopt functions, prefixing every function, global variable and structure with a
+// 'w', and use only wide character strings. There are no other functional changes in this version
+// of getopt besides using wide character strings.
+//
+// For examples of how to use wgetopt, see the fish builtin functions, many of which are defined in
+// builtin.c.
+
+// Getopt for GNU.
+//
+// NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space
+// clean" means, talk to roland@gnu.ai.mit.edu before changing it!
+//
+// Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU C Library. Its master source is NOT part of the C library, however.
+// The master source lives in /gd/gnu/lib.
+//
+// The GNU C Library is free software; you can redistribute it and/or modify it under the terms of
+// the GNU Library General Public License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+// the GNU Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public License along with the GNU C
+// Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass
+// Ave, Cambridge, MA 02139, USA.
#include "config.h"
#include <stdio.h>
#include <wchar.h>
-/* This needs to come after some library #include
- to get __GNU_LIBRARY__ defined. */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
- contain conflicting prototypes for getopt. */
+// This needs to come after some library #include to get __GNU_LIBRARY__ defined.
+#ifdef __GNU_LIBRARY__
+// Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting
+// prototypes for getopt.
#include <stdlib.h>
-#endif /* GNU C library. */
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
- but it behaves differently for the user, since it allows the user
- to intersperse the options with the other arguments.
-
- As `getopt' works, it permutes the elements of ARGV so that,
- when it is done, all the options precede everything else. Thus
- all application programs are extended to handle flexible argument order.
-
- GNU application programs can use a third alternative mode in which
- they can distinguish the relative order of options and other arguments. */
-
+#endif // GNU C library.
+
+// This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves
+// differently for the user, since it allows the user to intersperse the options with the other
+// arguments.
+//
+// As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options
+// precede everything else. Thus all application programs are extended to handle flexible argument
+// order.
+//
+// GNU application programs can use a third alternative mode in which they can distinguish the
+// relative order of options and other arguments.
#include "common.h"
+#include "fallback.h" // IWYU pragma: keep
#include "wgetopt.h"
#include "wutil.h" // IWYU pragma: keep
-#include "fallback.h" // IWYU pragma: keep
-/**
- Use translation functions if available
-*/
+// Use translation functions if available.
#ifdef _
#undef _
#endif
@@ -94,229 +77,178 @@
#define _(wstr) wstr
#endif
-#ifdef __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
- because there are many ways it can cause trouble.
- On some systems, it contains special magic macros that don't work
- in GCC. */
-#include <string.h> // IWYU pragma: keep
-#define my_index wcschr
+#ifdef __GNU_LIBRARY__
+// We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can
+// cause trouble. On some systems, it contains special magic macros that don't work in GCC.
+#include <string.h> // IWYU pragma: keep
+#define my_index wcschr
#else
-/* Avoid depending on library functions or files
- whose names are inconsistent. */
+// Avoid depending on library functions or files whose names are inconsistent.
char *getenv();
-static wchar_t *
-my_index(const wchar_t *str, int chr)
-{
- while (*str)
- {
- if (*str == chr)
- return (wchar_t *) str;
+static wchar_t *my_index(const wchar_t *str, int chr) {
+ while (*str) {
+ if (*str == chr) return (wchar_t *)str;
str++;
}
return 0;
}
-/* If using GCC, we can safely declare strlen this way.
- If not using GCC, it is ok not to declare it. */
+// If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare
+// it.
#ifdef __GNUC__
-/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
- That was relevant to code that was here before. */
-#if !defined (__STDC__) || !__STDC__
-/* gcc with -traditional declares the built-in strlen to return int,
- and has done so at least since version 2.4.5. -- rms. */
+// Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that
+// was here before.
+#if !defined(__STDC__) || !__STDC__
+// gcc with -traditional declares the built-in strlen to return int, and has done so at least since
+// version 2.4.5. -- rms.
extern int wcslen(const wchar_t *);
-#endif /* not __STDC__ */
-#endif /* __GNUC__ */
-
-#endif /* not __GNU_LIBRARY__ */
-
-
-/* Exchange two adjacent subsequences of ARGV.
- One subsequence is elements [first_nonopt,last_nonopt)
- which contains all the non-options that have been skipped so far.
- The other is elements [last_nonopt,woptind), which contains all
- the options processed since those non-options were skipped.
-
- `first_nonopt' and `last_nonopt' are relocated so that they describe
- the new indices of the non-options in ARGV after they are moved. */
-
-void wgetopter_t::exchange(wchar_t **argv)
-{
+#endif // not __STDC__
+#endif // __GNUC__
+
+#endif // not __GNU_LIBRARY__
+
+// Exchange two adjacent subsequences of ARGV. One subsequence is elements
+// [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The
+// other is elements [last_nonopt,woptind), which contains all the options processed since those
+// non-options were skipped.
+//
+// `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the
+// non-options in ARGV after they are moved.
+void wgetopter_t::exchange(wchar_t **argv) {
int bottom = first_nonopt;
int middle = last_nonopt;
int top = woptind;
wchar_t *tem;
- /* Exchange the shorter segment with the far end of the longer segment.
- That puts the shorter segment into the right place.
- It leaves the longer segment in the right place overall,
- but it consists of two parts that need to be swapped next. */
+ // Exchange the shorter segment with the far end of the longer segment. That puts the shorter
+ // segment into the right place. It leaves the longer segment in the right place overall, but it
+ // consists of two parts that need to be swapped next.
- while (top > middle && middle > bottom)
- {
- if (top - middle > middle - bottom)
- {
- /* Bottom segment is the short one. */
+ while (top > middle && middle > bottom) {
+ if (top - middle > middle - bottom) {
+ // Bottom segment is the short one.
int len = middle - bottom;
int i;
- /* Swap it with the top part of the top segment. */
- for (i = 0; i < len; i++)
- {
+ // Swap it with the top part of the top segment.
+ for (i = 0; i < len; i++) {
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
- /* Exclude the moved bottom segment from further swapping. */
+ // Exclude the moved bottom segment from further swapping.
top -= len;
- }
- else
- {
- /* Top segment is the short one. */
+ } else {
+ // Top segment is the short one.
int len = top - middle;
int i;
- /* Swap it with the bottom part of the bottom segment. */
- for (i = 0; i < len; i++)
- {
+ // Swap it with the bottom part of the bottom segment.
+ for (i = 0; i < len; i++) {
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
- /* Exclude the moved top segment from further swapping. */
+ // Exclude the moved top segment from further swapping.
bottom += len;
}
}
- /* Update records for the slots the non-options now occupy. */
-
+ // Update records for the slots the non-options now occupy.
first_nonopt += (woptind - last_nonopt);
last_nonopt = woptind;
}
-/* Initialize the internal data when the first call is made. */
-
-const wchar_t * wgetopter_t::_wgetopt_initialize(const wchar_t *optstring)
-{
- /* Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
-
+// Initialize the internal data when the first call is made.
+const wchar_t *wgetopter_t::_wgetopt_initialize(const wchar_t *optstring) {
+ // Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the
+ // sequence of previously skipped non-option ARGV-elements is empty.
first_nonopt = last_nonopt = woptind = 1;
-
nextchar = NULL;
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
+ // Determine how to handle the ordering of options and nonoptions.
+ if (optstring[0] == '-') {
ordering = RETURN_IN_ORDER;
++optstring;
- }
- else if (optstring[0] == '+')
- {
+ } else if (optstring[0] == '+') {
ordering = REQUIRE_ORDER;
++optstring;
- }
- else
+ } else
ordering = PERMUTE;
return optstring;
}
-/* Scan elements of ARGV (whose length is ARGC) for option characters
- given in OPTSTRING.
-
- If an element of ARGV starts with '-', and is not exactly "-" or "--",
- then it is an option element. The characters of this element
- (aside from the initial '-') are option characters. If `getopt'
- is called repeatedly, it returns successively each of the option characters
- from each of the option elements.
-
- If `getopt' finds another option character, it returns that character,
- updating `woptind' and `nextchar' so that the next call to `getopt' can
- resume the scan with the following option character or ARGV-element.
-
- If there are no more option characters, `getopt' returns `EOF'.
- Then `woptind' is the index in ARGV of the first ARGV-element
- that is not an option. (The ARGV-elements have been permuted
- so that those that are not options now come last.)
-
- OPTSTRING is a string containing the legitimate option characters.
- If an option character is seen that is not listed in OPTSTRING,
- return '?' after printing an error message. If you set `wopterr' to
- zero, the error message is suppressed but we still return '?'.
-
- If a char in OPTSTRING is followed by a colon, that means it wants an arg,
- so the following text in the same ARGV-element, or the text of the following
- ARGV-element, is returned in `optarg'. Two colons mean an option that
- wants an optional arg; if there is text in the current ARGV-element,
- it is returned in `w.woptarg', otherwise `w.woptarg' is set to zero.
-
- If OPTSTRING starts with `-' or `+', it requests different methods of
- handling the non-option ARGV-elements.
- See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
- Long-named options begin with `--' instead of `-'.
- Their names may be abbreviated as long as the abbreviation is unique
- or is an exact match for some defined option. If they have an
- argument, it follows the option name in the same ARGV-element, separated
- from the option name by a `=', or else the in next ARGV-element.
- When `getopt' finds a long-named option, it returns 0 if that option's
- `flag' field is nonzero, the value of the option's `val' field
- if the `flag' field is zero.
-
- LONGOPTS is a vector of `struct option' terminated by an
- element containing a name which is zero.
-
- LONGIND returns the index in LONGOPT of the long-named option found.
- It is only valid when a long-named option has been found by the most
- recent call.
-
- If LONG_ONLY is nonzero, '-' as well as '--' can introduce
- long-named options. */
-
-int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *optstring, const struct woption *longopts, int *longind, int long_only)
-{
+// Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING.
+//
+// If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option
+// element. The characters of this element (aside from the initial '-') are option characters. If
+// `getopt' is called repeatedly, it returns successively each of the option characters from each of
+// the option elements.
+//
+// If `getopt' finds another option character, it returns that character, updating `woptind' and
+// `nextchar' so that the next call to `getopt' can resume the scan with the following option
+// character or ARGV-element.
+//
+// If there are no more option characters, `getopt' returns `EOF'. Then `woptind' is the index in
+// ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so
+// that those that are not options now come last.)
+//
+// OPTSTRING is a string containing the legitimate option characters. If an option character is seen
+// that is not listed in OPTSTRING, return '?' after printing an error message. If you set
+// `wopterr' to zero, the error message is suppressed but we still return '?'.
+//
+// If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text
+// in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'.
+// Two colons mean an option that wants an optional arg; if there is text in the current
+// ARGV-element, it is returned in `w.woptarg', otherwise `w.woptarg' is set to zero.
+//
+// If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option
+// ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+//
+// Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the
+// abbreviation is unique or is an exact match for some defined option. If they have an argument,
+// it follows the option name in the same ARGV-element, separated from the option name by a `=', or
+// else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that
+// option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is
+// zero.
+//
+// LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero.
+//
+// LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a
+// long-named option has been found by the most recent call.
+//
+// If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options.
+int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *optstring,
+ const struct woption *longopts, int *longind, int long_only) {
woptarg = NULL;
- if (woptind == 0)
- optstring = _wgetopt_initialize(optstring);
-
- if (nextchar == NULL || *nextchar == '\0')
- {
- /* Advance to the next ARGV-element. */
-
- if (ordering == PERMUTE)
- {
- /* If we have just processed some options following some non-options,
- exchange them so that the options come first. */
+ if (woptind == 0) optstring = _wgetopt_initialize(optstring);
+ if (nextchar == NULL || *nextchar == '\0') {
+ // Advance to the next ARGV-element.
+ if (ordering == PERMUTE) {
+ // If we have just processed some options following some non-options, exchange them so
+ // that the options come first.
if (first_nonopt != last_nonopt && last_nonopt != woptind)
exchange(argv);
else if (last_nonopt != woptind)
first_nonopt = woptind;
- /* Skip any additional non-options
- and extend the range of non-options previously skipped. */
-
- while (woptind < argc
- && (argv[woptind][0] != '-' || argv[woptind][1] == '\0'))
+ // Skip any additional non-options and extend the range of non-options previously
+ // skipped.
+ while (woptind < argc && (argv[woptind][0] != '-' || argv[woptind][1] == '\0'))
woptind++;
last_nonopt = woptind;
}
- /* The special ARGV-element `--' means premature end of options.
- Skip it like a null option,
- then exchange with previous non-options as if it were an option,
- then skip everything else like a non-option. */
-
- if (woptind != argc && !wcscmp(argv[woptind], L"--"))
- {
+ // The special ARGV-element `--' means premature end of options. Skip it like a null option,
+ // then exchange with previous non-options as if it were an option, then skip everything
+ // else like a non-option.
+ if (woptind != argc && !wcscmp(argv[woptind], L"--")) {
woptind++;
if (first_nonopt != last_nonopt && last_nonopt != woptind)
@@ -328,241 +260,187 @@ int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *opts
woptind = argc;
}
- /* If we have done all the ARGV-elements, stop the scan
- and back over any non-options that we skipped and permuted. */
+ // If we have done all the ARGV-elements, stop the scan and back over any non-options that
+ // we skipped and permuted.
- if (woptind == argc)
- {
- /* Set the next-arg-index to point at the non-options
- that we previously skipped, so the caller will digest them. */
- if (first_nonopt != last_nonopt)
- woptind = first_nonopt;
+ if (woptind == argc) {
+ // Set the next-arg-index to point at the non-options that we previously skipped, so the
+ // caller will digest them.
+ if (first_nonopt != last_nonopt) woptind = first_nonopt;
return EOF;
}
- /* If we have come to a non-option and did not permute it,
- either stop the scan or describe it to the caller and pass it by. */
-
- if ((argv[woptind][0] != '-' || argv[woptind][1] == '\0'))
- {
- if (ordering == REQUIRE_ORDER)
- return EOF;
+ // If we have come to a non-option and did not permute it, either stop the scan or describe
+ // it to the caller and pass it by.
+ if ((argv[woptind][0] != '-' || argv[woptind][1] == '\0')) {
+ if (ordering == REQUIRE_ORDER) return EOF;
woptarg = argv[woptind++];
return 1;
}
- /* We have found another option-ARGV-element.
- Skip the initial punctuation. */
-
- nextchar = (argv[woptind] + 1
- + (longopts != NULL && argv[woptind][1] == '-'));
+ // We have found another option-ARGV-element. Skip the initial punctuation.
+ nextchar = (argv[woptind] + 1 + (longopts != NULL && argv[woptind][1] == '-'));
}
- /* Decode the current option-ARGV-element. */
-
- /* Check whether the ARGV-element is a long option.
-
- If long_only and the ARGV-element has the form "-f", where f is
- a valid short option, don't consider it an abbreviated form of
- a long option that starts with f. Otherwise there would be no
- way to give the -f short option.
-
- On the other hand, if there's a long option "fubar" and
- the ARGV-element is "-fu", do consider that an abbreviation of
- the long option, just like "--fu", and not "-f" with arg "u".
-
- This distinction seems to be the most useful approach. */
-
- if (longopts != NULL
- && (argv[woptind][1] == '-'
- || (long_only && (argv[woptind][2] || !my_index(optstring, argv[woptind][1])))))
- {
+ // Decode the current option-ARGV-element.
+
+ // Check whether the ARGV-element is a long option.
+ //
+ // If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't
+ // consider it an abbreviated form of a long option that starts with f. Otherwise there would
+ // be no way to give the -f short option.
+ //
+ // On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do
+ // consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg
+ // "u".
+ //
+ // This distinction seems to be the most useful approach.
+ if (longopts != NULL &&
+ (argv[woptind][1] == '-' ||
+ (long_only && (argv[woptind][2] || !my_index(optstring, argv[woptind][1]))))) {
wchar_t *nameend;
const struct woption *p;
const struct woption *pfound = NULL;
int exact = 0;
int ambig = 0;
- int indfound = 0; /* set to zero by Anton */
+ int indfound = 0; // set to zero by Anton
int option_index;
- for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
- /* Do nothing. */ ;
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */;
- /* Test all long options for either exact match
- or abbreviated matches. */
+ // Test all long options for either exact match or abbreviated matches.
for (p = longopts, option_index = 0; p->name; p++, option_index++)
- if (!wcsncmp(p->name, nextchar, nameend - nextchar))
- {
- if ((unsigned int)(nameend - nextchar) == (unsigned int)wcslen(p->name))
- {
- /* Exact match found. */
+ if (!wcsncmp(p->name, nextchar, nameend - nextchar)) {
+ if ((unsigned int)(nameend - nextchar) == (unsigned int)wcslen(p->name)) {
+ // Exact match found.
pfound = p;
indfound = option_index;
exact = 1;
break;
- }
- else if (pfound == NULL)
- {
- /* First nonexact match found. */
+ } else if (pfound == NULL) {
+ // First nonexact match found.
pfound = p;
indfound = option_index;
- }
- else
- /* Second or later nonexact match found. */
+ } else
+ // Second or later nonexact match found.
ambig = 1;
}
- if (ambig && !exact)
- {
+ if (ambig && !exact) {
if (wopterr)
- fwprintf(stderr, _(L"%ls: Option '%ls' is ambiguous\n"),
- argv[0], argv[woptind]);
+ fwprintf(stderr, _(L"%ls: Option '%ls' is ambiguous\n"), argv[0], argv[woptind]);
nextchar += wcslen(nextchar);
woptind++;
return '?';
}
- if (pfound != NULL)
- {
+ if (pfound != NULL) {
option_index = indfound;
woptind++;
- if (*nameend)
- {
- /* Don't test has_arg with >, because some C compilers don't
- allow it to be used on enums. */
+ if (*nameend) {
+ // Don't test has_arg with >, because some C compilers don't allow it to be used on
+ // enums.
if (pfound->has_arg)
woptarg = nameend + 1;
- else
- {
- if (wopterr)
- {
- if (argv[woptind - 1][1] == '-')
- /* --option */
- fwprintf(stderr,
- _(L"%ls: Option '--%ls' doesn't allow an argument\n"),
+ else {
+ if (wopterr) {
+ if (argv[woptind - 1][1] == '-') // --option
+ fwprintf(stderr, _(L"%ls: Option '--%ls' doesn't allow an argument\n"),
argv[0], pfound->name);
else
- /* +option or -option */
- fwprintf(stderr,
- _(L"%ls: Option '%lc%ls' doesn't allow an argument\n"),
+ // +option or -option
+ fwprintf(stderr, _(L"%ls: Option '%lc%ls' doesn't allow an argument\n"),
argv[0], argv[woptind - 1][0], pfound->name);
}
nextchar += wcslen(nextchar);
return '?';
}
- }
- else if (pfound->has_arg == 1)
- {
+ } else if (pfound->has_arg == 1) {
if (woptind < argc)
woptarg = argv[woptind++];
- else
- {
+ else {
if (wopterr)
- fwprintf(stderr, _(L"%ls: Option '%ls' requires an argument\n"),
- argv[0], argv[woptind - 1]);
+ fwprintf(stderr, _(L"%ls: Option '%ls' requires an argument\n"), argv[0],
+ argv[woptind - 1]);
nextchar += wcslen(nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += wcslen(nextchar);
- if (longind != NULL)
- *longind = option_index;
- if (pfound->flag)
- {
+ if (longind != NULL) *longind = option_index;
+ if (pfound->flag) {
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
- /* Can't find it as a long option. If this is not getopt_long_only,
- or the option starts with '--' or is not a valid short
- option, then it's an error.
- Otherwise interpret it as a short option. */
- if (!long_only || argv[woptind][1] == '-'
- || my_index(optstring, *nextchar) == NULL)
- {
- if (wopterr)
- {
- if (argv[woptind][1] == '-')
- /* --option */
- fwprintf(stderr, _(L"%ls: Unrecognized option '--%ls'\n"),
- argv[0], nextchar);
+ // Can't find it as a long option. If this is not getopt_long_only, or the option starts
+ // with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a
+ // short option.
+ if (!long_only || argv[woptind][1] == '-' || my_index(optstring, *nextchar) == NULL) {
+ if (wopterr) {
+ if (argv[woptind][1] == '-') // --option
+ fwprintf(stderr, _(L"%ls: Unrecognized option '--%ls'\n"), argv[0], nextchar);
else
- /* +option or -option */
- fwprintf(stderr, _(L"%ls: Unrecognized option '%lc%ls'\n"),
- argv[0], argv[woptind][0], nextchar);
+ // +option or -option
+ fwprintf(stderr, _(L"%ls: Unrecognized option '%lc%ls'\n"), argv[0],
+ argv[woptind][0], nextchar);
}
- nextchar = (wchar_t *) L"";
+ nextchar = (wchar_t *)L"";
woptind++;
return '?';
}
}
- /* Look at and handle the next short option-character. */
-
+ // Look at and handle the next short option-character.
{
wchar_t c = *nextchar++;
- wchar_t *temp = const_cast<wchar_t*>(my_index(optstring, c));
+ wchar_t *temp = const_cast<wchar_t *>(my_index(optstring, c));
- /* Increment `woptind' when we start to process its last character. */
- if (*nextchar == '\0')
- ++woptind;
+ // Increment `woptind' when we start to process its last character.
+ if (*nextchar == '\0') ++woptind;
- if (temp == NULL || c == ':')
- {
- if (wopterr)
- {
+ if (temp == NULL || c == ':') {
+ if (wopterr) {
fwprintf(stderr, _(L"%ls: Invalid option -- %lc\n"), argv[0], (wint_t)c);
}
woptopt = c;
- if (*nextchar != '\0')
- woptind++;
+ if (*nextchar != '\0') woptind++;
return '?';
}
- if (temp[1] == ':')
- {
- if (temp[2] == ':')
- {
- /* This is an option that accepts an argument optionally. */
- if (*nextchar != '\0')
- {
+ if (temp[1] == ':') {
+ if (temp[2] == ':') {
+ // This is an option that accepts an argument optionally.
+ if (*nextchar != '\0') {
woptarg = nextchar;
woptind++;
- }
- else
+ } else
woptarg = NULL;
nextchar = NULL;
- }
- else
- {
- /* This is an option that requires an argument. */
- if (*nextchar != '\0')
- {
+ } else {
+ // This is an option that requires an argument.
+ if (*nextchar != '\0') {
woptarg = nextchar;
- /* If we end this ARGV-element by taking the rest as an arg,
- we must advance to the next element now. */
+ // If we end this ARGV-element by taking the rest as an arg, we must advance to
+ // the next element now.
woptind++;
- }
- else if (woptind == argc)
- {
- if (wopterr)
- {
- /* 1003.2 specifies the format of this message. */
- fwprintf(stderr, _(L"%ls: Option requires an argument -- %lc\n"),
- argv[0], (wint_t)c);
+ } else if (woptind == argc) {
+ if (wopterr) {
+ // 1003.2 specifies the format of this message.
+ fwprintf(stderr, _(L"%ls: Option requires an argument -- %lc\n"), argv[0],
+ (wint_t)c);
}
woptopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
- }
- else
- /* We already incremented `woptind' once;
- increment it again when taking next ARGV-elt as argument. */
+ } else
+ // We already incremented `woptind' once; increment it again when taking next
+ // ARGV-elt as argument.
woptarg = argv[woptind++];
nextchar = NULL;
}
@@ -571,12 +449,12 @@ int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *opts
}
}
-int wgetopter_t::wgetopt_long(int argc, wchar_t **argv, const wchar_t *options, const struct woption *long_options, int *opt_index)
-{
+int wgetopter_t::wgetopt_long(int argc, wchar_t **argv, const wchar_t *options,
+ const struct woption *long_options, int *opt_index) {
return _wgetopt_internal(argc, argv, options, long_options, opt_index, 0);
}
-int wgetopter_t::wgetopt_long_only(int argc, wchar_t **argv, const wchar_t *options, const struct woption *long_options, int *opt_index)
-{
+int wgetopter_t::wgetopt_long_only(int argc, wchar_t **argv, const wchar_t *options,
+ const struct woption *long_options, int *opt_index) {
return _wgetopt_internal(argc, argv, options, long_options, opt_index, 1);
}
diff --git a/src/wgetopt.h b/src/wgetopt.h
index d20529bb..95e1462d 100644
--- a/src/wgetopt.h
+++ b/src/wgetopt.h
@@ -1,27 +1,18 @@
-/** \file wgetopt.h
- A version of the getopt library for use with wide character strings.
-
- This is simply the gnu getopt library, but converted for use with
- wchar_t instead of char. This is not usually useful since the argv
- array is always defined to be of type char**, but in fish, all
- internal commands use wide characters and hence this library is
- useful.
-
- If you want to use this version of getopt in your program,
- download the fish sourcecode, available at <a
- href='http://fishshell.com'>the fish homepage</a>. Extract
- the sourcode, copy wgetopt.c and wgetopt.h into your program
- directory, include wgetopt.h in your program, and use all the
- regular getopt functions, prefixing every function, global
- variable and structure with a 'w', and use only wide character
- strings. There are no other functional changes in this version of
- getopt besides using wide character strings.
-
- For examples of how to use wgetopt, see the fish builtin
- functions, many of which are defined in builtin.c.
-
-*/
-
+// A version of the getopt library for use with wide character strings.
+//
+// This is simply the gnu getopt library, but converted for use with wchar_t instead of char. This
+// is not usually useful since the argv array is always defined to be of type char**, but in fish,
+// all internal commands use wide characters and hence this library is useful.
+//
+// If you want to use this version of getopt in your program, download the fish sourcecode,
+// available at <a href='http://fishshell.com'>the fish homepage</a>. Extract the sourcode, copy
+// wgetopt.c and wgetopt.h into your program directory, include wgetopt.h in your program, and use
+// all the regular getopt functions, prefixing every function, global variable and structure with a
+// 'w', and use only wide character strings. There are no other functional changes in this version
+// of getopt besides using wide character strings.
+//
+// For examples of how to use wgetopt, see the fish builtin functions, many of which are defined in
+// builtin.c.
/* Declarations for getopt.
Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
@@ -49,169 +40,131 @@ Cambridge, MA 02139, USA. */
#include <stddef.h>
-class wgetopter_t
-{
-private:
+class wgetopter_t {
+ private:
void exchange(wchar_t **argv);
- const wchar_t * _wgetopt_initialize(const wchar_t *optstring);
- int _wgetopt_internal(int argc, wchar_t **argv, const wchar_t *optstring, const struct woption *longopts, int *longind, int long_only);
-
-public:
- /* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
+ const wchar_t *_wgetopt_initialize(const wchar_t *optstring);
+ int _wgetopt_internal(int argc, wchar_t **argv, const wchar_t *optstring,
+ const struct woption *longopts, int *longind, int long_only);
+
+ public:
+ // For communication from `getopt' to the caller. When `getopt' finds an option that takes an
+ // argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each
+ // non-option ARGV-element is returned here.
wchar_t *woptarg;
-
- /* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns EOF, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `woptind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
- /* XXX 1003.2 says this must be 1 before any call. */
+
+ // Index in ARGV of the next element to be scanned. This is used for communication to and from
+ // the caller and for communication between successive calls to `getopt'.
+ //
+ // On entry to `getopt', zero means this is the first call; initialize.
+ //
+ // When `getopt' returns EOF, this is the index of the first of the non-option elements that the
+ // caller should itself scan.
+ //
+ // Otherwise, `woptind' communicates from one call to the next how much of ARGV has been scanned
+ // so far.
+
+ // XXX 1003.2 says this must be 1 before any call.
int woptind;
-
-
- /* The next char to be scanned in the option-element
- in which the last option character we returned was found.
- This allows us to pick up the scan where we left off.
-
- If this is zero, or a null string, it means resume the scan
- by advancing to the next ARGV-element. */
-
+
+ // The next char to be scanned in the option-element in which the last option character we
+ // returned was found. This allows us to pick up the scan where we left off.
+ //
+ // If this is zero, or a null string, it means resume the scan by advancing to the next
+ // ARGV-element.
wchar_t *nextchar;
-
- /* Callers store zero here to inhibit the error message
- for unrecognized options. */
-
+
+ // Callers store zero here to inhibit the error message for unrecognized options.
int wopterr;
-
- /* Set to an option character which was unrecognized.
- This must be initialized on some systems to avoid linking in the
- system's own getopt implementation. */
-
+
+ // Set to an option character which was unrecognized. This must be initialized on some systems
+ // to avoid linking in the system's own getopt implementation.
int woptopt;
-
- /* Describe how to deal with options that follow non-option ARGV-elements.
-
- If the caller did not specify anything,
- the default is PERMUTE.
-
- REQUIRE_ORDER means don't recognize them as options;
- stop option processing when the first non-option is seen.
- This is what Unix does.
- This mode of operation is selected by using `+' as the first
- character of the list of option characters.
-
- PERMUTE is the default. We permute the contents of ARGV as we scan,
- so that eventually all the non-options are at the end. This allows options
- to be given in any order, even with programs that were not written to
- expect this.
-
- RETURN_IN_ORDER is an option available to programs that were written
- to expect options and other ARGV-elements in any order and that care about
- the ordering of the two. We describe each non-option ARGV-element
- as if it were the argument of an option with character code 1.
- Using `-' as the first character of the list of option characters
- selects this mode of operation.
-
- The special argument `--' forces an end of option-scanning regardless
- of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return EOF with `woptind' != ARGC. */
-
- enum
- {
- REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
- } ordering;
-
- /* Handle permutation of arguments. */
-
- /* Describe the part of ARGV that contains non-options that have
- been skipped. `first_nonopt' is the index in ARGV of the first of them;
- `last_nonopt' is the index after the last of them. */
-
+
+ // Describe how to deal with options that follow non-option ARGV-elements.
+ //
+ // If the caller did not specify anything, the default is PERMUTE.
+ //
+ // REQUIRE_ORDER means don't recognize them as options; stop option processing when the first
+ // non-option is seen. This is what Unix does. This mode of operation is selected by using `+'
+ // as the first character of the list of option characters.
+ //
+ // PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all
+ // the non-options are at the end. This allows options to be given in any order, even with
+ // programs that were not written to expect this.
+ //
+ // RETURN_IN_ORDER is an option available to programs that were written to expect options and
+ // other ARGV-elements in any order and that care about the ordering of the two. We describe
+ // each non-option ARGV-element as if it were the argument of an option with character code 1.
+ // Using `-' as the first character of the list of option characters selects this mode of
+ // operation.
+ //
+ // The special argument `--' forces an end of option-scanning regardless of the value of
+ // `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with
+ // `woptind' != ARGC.
+ enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering;
+
+ // Handle permutation of arguments.
+
+ // Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt'
+ // is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them.
int first_nonopt;
int last_nonopt;
-
-
- wgetopter_t() : woptarg(NULL), woptind(0), nextchar(0), wopterr(0), woptopt('?'), ordering(), first_nonopt(0), last_nonopt(0)
- {
- }
-
- int wgetopt_long(int argc, wchar_t **argv, const wchar_t *options, const struct woption *long_options, int *opt_index);
- int wgetopt_long_only(int argc, wchar_t **argv, const wchar_t *options, const struct woption *long_options, int *opt_index);
+
+ wgetopter_t()
+ : woptarg(NULL),
+ woptind(0),
+ nextchar(0),
+ wopterr(0),
+ woptopt('?'),
+ ordering(),
+ first_nonopt(0),
+ last_nonopt(0) {}
+
+ int wgetopt_long(int argc, wchar_t **argv, const wchar_t *options,
+ const struct woption *long_options, int *opt_index);
+ int wgetopt_long_only(int argc, wchar_t **argv, const wchar_t *options,
+ const struct woption *long_options, int *opt_index);
};
-/** Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct woption
-{
- /**
- long name for switch
- */
+/// Describe the long-named options requested by the application. The LONG_OPTIONS argument to
+/// getopt_long or getopt_long_only is a vector of `struct option' terminated by an element
+/// containing a name which is zero.
+///
+/// The field `has_arg' is:
+/// no_argument (or 0) if the option does not take an argument,
+/// required_argument (or 1) if the option requires an argument,
+/// optional_argument (or 2) if the option takes an optional argument.
+///
+/// If the field `flag' is not NULL, it points to a variable that is set to the value given in the
+/// field `val' when the option is found, but left unchanged if the option is not found.
+///
+/// To have a long-named option do something other than set an `int' to a compiled-in constant, such
+/// as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a
+/// nonzero value (the equivalent single-letter option character, if there is one). For long
+/// options that have a zero `flag' field, `getopt' returns the contents of the `val' field.
+struct woption {
+ /// Long name for switch.
const wchar_t *name;
- /**
- Must be one of no_argument, required_argument and
- optional_argument.
-
- has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int.
- */
+ /// Must be one of no_argument, required_argument and optional_argument.
+ ///
+ /// has_arg can't be an enum because some compilers complain about type mismatches in all the
+ /// code that assumes it is an int.
int has_arg;
-
- /**
- If non-null, the flag whose value should be set if this switch is encountered
- */
+ /// If non-null, the flag whose value should be set if this switch is encountered.
int *flag;
-
- /**
- If \c flag is non-null, this is the value that flag will be set
- to. Otherwise, this is the return-value of the function call.
- */
+ /// If \c flag is non-null, this is the value that flag will be set to. Otherwise, this is the
+ /// return-value of the function call.
int val;
};
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-/**
- Specifies that a switch does not accept an argument
-*/
-#define no_argument 0
-/**
- Specifies that a switch requires an argument
-*/
-#define required_argument 1
-/**
- Specifies that a switch accepts an optional argument
-*/
-#define optional_argument 2
+// Names for the values of the `has_arg' field of `struct option'.
+
+/// Specifies that a switch does not accept an argument.
+#define no_argument 0
+/// Specifies that a switch requires an argument.
+#define required_argument 1
+/// Specifies that a switch accepts an optional argument.
+#define optional_argument 2
#endif /* FISH_WGETOPT_H */
diff --git a/src/wildcard.cpp b/src/wildcard.cpp
index 471453f6..1a09d63e 100644
--- a/src/wildcard.cpp
+++ b/src/wildcard.cpp
@@ -1,113 +1,74 @@
-/** \file wildcard.c
-
-Fish needs it's own globbing implementation to support
-tab-expansion of globbed parameters. Also provides recursive
-wildcards using **.
-*/
-#include <wchar.h>
-#include <unistd.h>
-#include <sys/stat.h>
+// Fish needs it's own globbing implementation to support tab-expansion of globbed parameters. Also
+// provides recursive wildcards using **.
+#include <assert.h>
#include <dirent.h>
#include <errno.h>
-#include <set>
-#include <assert.h>
-#include <string>
-#include <utility>
#include <stdbool.h>
+#include <sys/stat.h>
#include <sys/types.h>
+#include <unistd.h>
+#include <wchar.h>
#include <memory>
+#include <set>
+#include <string>
+#include <utility>
-#include "fallback.h" // IWYU pragma: keep
-#include "wutil.h" // IWYU pragma: keep
#include "common.h"
-#include "wildcard.h"
#include "complete.h"
-#include "reader.h"
#include "expand.h"
+#include "fallback.h" // IWYU pragma: keep
+#include "reader.h"
+#include "wildcard.h"
+#include "wutil.h" // IWYU pragma: keep
-/**
- Description for generic executable
-*/
-#define COMPLETE_EXEC_DESC _( L"Executable" )
-/**
- Description for link to executable
-*/
-#define COMPLETE_EXEC_LINK_DESC _( L"Executable link" )
-
-/**
- Description for regular file
-*/
-#define COMPLETE_FILE_DESC _( L"File" )
-/**
- Description for character device
-*/
-#define COMPLETE_CHAR_DESC _( L"Character device" )
-/**
- Description for block device
-*/
-#define COMPLETE_BLOCK_DESC _( L"Block device" )
-/**
- Description for fifo buffer
-*/
-#define COMPLETE_FIFO_DESC _( L"Fifo" )
-/**
- Description for symlink
-*/
-#define COMPLETE_SYMLINK_DESC _( L"Symbolic link" )
-/**
- Description for symlink
-*/
-#define COMPLETE_DIRECTORY_SYMLINK_DESC _( L"Symbolic link to directory" )
-/**
- Description for Rotten symlink
-*/
-#define COMPLETE_ROTTEN_SYMLINK_DESC _( L"Rotten symbolic link" )
-/**
- Description for symlink loop
-*/
-#define COMPLETE_LOOP_SYMLINK_DESC _( L"Symbolic link loop" )
-/**
- Description for socket files
-*/
-#define COMPLETE_SOCKET_DESC _( L"Socket" )
-/**
- Description for directories
-*/
-#define COMPLETE_DIRECTORY_DESC _( L"Directory" )
-
-/* Finds an internal (ANY_STRING, etc.) style wildcard, or wcstring::npos */
-static size_t wildcard_find(const wchar_t *wc)
-{
- for (size_t i=0; wc[i] != L'\0'; i++)
- {
- if (wc[i] == ANY_CHAR || wc[i] == ANY_STRING || wc[i] == ANY_STRING_RECURSIVE)
- {
+/// Description for generic executable.
+#define COMPLETE_EXEC_DESC _(L"Executable")
+/// Description for link to executable.
+#define COMPLETE_EXEC_LINK_DESC _(L"Executable link")
+/// Description for regular file.
+#define COMPLETE_FILE_DESC _(L"File")
+/// Description for character device.
+#define COMPLETE_CHAR_DESC _(L"Character device")
+/// Description for block device.
+#define COMPLETE_BLOCK_DESC _(L"Block device")
+/// Description for fifo buffer.
+#define COMPLETE_FIFO_DESC _(L"Fifo")
+/// Description for symlink.
+#define COMPLETE_SYMLINK_DESC _(L"Symbolic link")
+/// Description for symlink.
+#define COMPLETE_DIRECTORY_SYMLINK_DESC _(L"Symbolic link to directory")
+/// Description for Rotten symlink.
+#define COMPLETE_ROTTEN_SYMLINK_DESC _(L"Rotten symbolic link")
+/// Description for symlink loop.
+#define COMPLETE_LOOP_SYMLINK_DESC _(L"Symbolic link loop")
+/// Description for socket files.
+#define COMPLETE_SOCKET_DESC _(L"Socket")
+/// Description for directories.
+#define COMPLETE_DIRECTORY_DESC _(L"Directory")
+
+/// Finds an internal (ANY_STRING, etc.) style wildcard, or wcstring::npos.
+static size_t wildcard_find(const wchar_t *wc) {
+ for (size_t i = 0; wc[i] != L'\0'; i++) {
+ if (wc[i] == ANY_CHAR || wc[i] == ANY_STRING || wc[i] == ANY_STRING_RECURSIVE) {
return i;
}
}
return wcstring::npos;
}
-// Implementation of wildcard_has. Needs to take the length to handle embedded nulls (#1631)
-static bool wildcard_has_impl(const wchar_t *str, size_t len, bool internal)
-{
+/// Implementation of wildcard_has. Needs to take the length to handle embedded nulls (issue #1631).
+static bool wildcard_has_impl(const wchar_t *str, size_t len, bool internal) {
assert(str != NULL);
const wchar_t *end = str + len;
- if (internal)
- {
- for (; str < end; str++)
- {
+ if (internal) {
+ for (; str < end; str++) {
if ((*str == ANY_CHAR) || (*str == ANY_STRING) || (*str == ANY_STRING_RECURSIVE))
return true;
}
- }
- else
- {
- wchar_t prev=0;
- for (; str < end; str++)
- {
- if (((*str == L'*') || (*str == L'?')) && (prev != L'\\'))
- return true;
+ } else {
+ wchar_t prev = 0;
+ for (; str < end; str++) {
+ if (((*str == L'*') || (*str == L'?')) && (prev != L'\\')) return true;
prev = *str;
}
}
@@ -115,141 +76,107 @@ static bool wildcard_has_impl(const wchar_t *str, size_t len, bool internal)
return false;
}
-bool wildcard_has(const wchar_t *str, bool internal)
-{
+bool wildcard_has(const wchar_t *str, bool internal) {
assert(str != NULL);
return wildcard_has_impl(str, wcslen(str), internal);
}
-bool wildcard_has(const wcstring &str, bool internal)
-{
+bool wildcard_has(const wcstring &str, bool internal) {
return wildcard_has_impl(str.data(), str.size(), internal);
}
-
-/**
- Check whether the string str matches the wildcard string wc.
-
- \param str String to be matched.
- \param wc The wildcard.
- \param is_first Whether files beginning with dots should not be matched against wildcards.
-*/
-static enum fuzzy_match_type_t wildcard_match_internal(const wchar_t *str, const wchar_t *wc, bool leading_dots_fail_to_match, bool is_first)
-{
- if (*str == 0 && *wc==0)
- {
- /* We're done */
- return fuzzy_match_exact;
- }
-
- /* Hackish fix for #270 . Prevent wildcards from matching . or .., but we must still allow literal matches. */
- if (leading_dots_fail_to_match && is_first && contains(str, L".", L".."))
- {
- /* The string is '.' or '..'. Return true if the wildcard exactly matches. */
+/// Check whether the string str matches the wildcard string wc.
+///
+/// \param str String to be matched.
+/// \param wc The wildcard.
+/// \param is_first Whether files beginning with dots should not be matched against wildcards.
+static enum fuzzy_match_type_t wildcard_match_internal(const wchar_t *str, const wchar_t *wc,
+ bool leading_dots_fail_to_match,
+ bool is_first) {
+ if (*str == 0 && *wc == 0) {
+ return fuzzy_match_exact; // we're done
+ }
+
+ // Hackish fix for issue #270. Prevent wildcards from matching . or .., but we must still allow
+ // literal matches.
+ if (leading_dots_fail_to_match && is_first && contains(str, L".", L"..")) {
+ // The string is '.' or '..'. Return true if the wildcard exactly matches.
return wcscmp(str, wc) ? fuzzy_match_none : fuzzy_match_exact;
}
-
- if (*wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE)
- {
- /* Ignore hidden file */
- if (leading_dots_fail_to_match && is_first && *str == L'.')
- {
+
+ if (*wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE) {
+ // Ignore hidden file
+ if (leading_dots_fail_to_match && is_first && *str == L'.') {
return fuzzy_match_none;
}
-
- /* Common case of * at the end. In that case we can early out since we know it will match. */
- if (wc[1] == L'\0')
- {
+
+ // Common case of * at the end. In that case we can early out since we know it will match.
+ if (wc[1] == L'\0') {
return fuzzy_match_exact;
}
- /* Try all submatches */
- do
- {
- enum fuzzy_match_type_t subresult = wildcard_match_internal(str, wc+1, leading_dots_fail_to_match, false);
- if (subresult != fuzzy_match_none)
- {
+ // Try all submatches.
+ do {
+ enum fuzzy_match_type_t subresult =
+ wildcard_match_internal(str, wc + 1, leading_dots_fail_to_match, false);
+ if (subresult != fuzzy_match_none) {
return subresult;
}
} while (*str++ != 0);
return fuzzy_match_none;
- }
- else if (*str == 0)
- {
- /*
- End of string, but not end of wildcard, and the next wildcard
- element is not a '*', so this is not a match.
- */
+ } else if (*str == 0) {
+ // End of string, but not end of wildcard, and the next wildcard element is not a '*', so
+ // this is not a match.
return fuzzy_match_none;
- }
- else if (*wc == ANY_CHAR)
- {
- if (is_first && *str == L'.')
- {
+ } else if (*wc == ANY_CHAR) {
+ if (is_first && *str == L'.') {
return fuzzy_match_none;
}
- return wildcard_match_internal(str+1, wc+1, leading_dots_fail_to_match, false);
- }
- else if (*wc == *str)
- {
- return wildcard_match_internal(str+1, wc+1, leading_dots_fail_to_match, false);
+ return wildcard_match_internal(str + 1, wc + 1, leading_dots_fail_to_match, false);
+ } else if (*wc == *str) {
+ return wildcard_match_internal(str + 1, wc + 1, leading_dots_fail_to_match, false);
}
return fuzzy_match_none;
}
-
-/* This does something horrible refactored from an even more horrible function */
-static wcstring resolve_description(wcstring *completion, const wchar_t *explicit_desc, wcstring(*desc_func)(const wcstring &))
-{
+// This does something horrible refactored from an even more horrible function.
+static wcstring resolve_description(wcstring *completion, const wchar_t *explicit_desc,
+ wcstring (*desc_func)(const wcstring &)) {
size_t complete_sep_loc = completion->find(PROG_COMPLETE_SEP);
- if (complete_sep_loc != wcstring::npos)
- {
- /* This completion has an embedded description, do not use the generic description */
+ if (complete_sep_loc != wcstring::npos) {
+ // This completion has an embedded description, do not use the generic description.
const wcstring description = completion->substr(complete_sep_loc + 1);
completion->resize(complete_sep_loc);
return description;
- }
- else
- {
+ } else {
const wcstring func_result = (desc_func ? desc_func(*completion) : wcstring());
- if (! func_result.empty())
- {
+ if (!func_result.empty()) {
return func_result;
- }
- else
- {
+ } else {
return explicit_desc ? explicit_desc : L"";
}
}
}
-/* A transient parameter pack needed by wildcard_complete. */
-struct wc_complete_pack_t
-{
- const wcstring &orig; // the original string, transient
- const wchar_t *desc; // literal description
- wcstring(*desc_func)(const wcstring &); // function for generating descriptions
+// A transient parameter pack needed by wildcard_complete.
+struct wc_complete_pack_t {
+ const wcstring &orig; // the original string, transient
+ const wchar_t *desc; // literal description
+ wcstring (*desc_func)(const wcstring &); // function for generating descriptions
expand_flags_t expand_flags;
- wc_complete_pack_t(const wcstring &str, const wchar_t *des, wcstring(*df)(const wcstring &), expand_flags_t fl) :
- orig(str),
- desc(des),
- desc_func(df),
- expand_flags(fl)
- {}
+ wc_complete_pack_t(const wcstring &str, const wchar_t *des, wcstring (*df)(const wcstring &),
+ expand_flags_t fl)
+ : orig(str), desc(des), desc_func(df), expand_flags(fl) {}
};
-/* Weirdly specific and non-reusable helper function that makes its one call site much clearer */
-static bool has_prefix_match(const std::vector<completion_t> *comps, size_t first)
-{
- if (comps != NULL)
- {
+// Weirdly specific and non-reusable helper function that makes its one call site much clearer.
+static bool has_prefix_match(const std::vector<completion_t> *comps, size_t first) {
+ if (comps != NULL) {
const size_t after_count = comps->size();
- for (size_t j = first; j < after_count; j++)
- {
- if (comps->at(j).match.type <= fuzzy_match_prefix)
- {
+ for (size_t j = first; j < after_count; j++) {
+ if (comps->at(j).match.type <= fuzzy_match_prefix) {
return true;
}
}
@@ -257,136 +184,116 @@ static bool has_prefix_match(const std::vector<completion_t> *comps, size_t firs
return false;
}
-/**
- Matches the string against the wildcard, and if the wildcard is a
- possible completion of the string, the remainder of the string is
- inserted into the out vector.
-
- We ignore ANY_STRING_RECURSIVE here. The consequence is that you cannot
- tab complete ** wildcards. This is historic behavior.
- */
-static bool wildcard_complete_internal(const wchar_t *str,
- const wchar_t *wc,
- const wc_complete_pack_t &params,
- complete_flags_t flags,
- std::vector<completion_t> *out,
- bool is_first_call = false)
-{
+/// Matches the string against the wildcard, and if the wildcard is a possible completion of the
+/// string, the remainder of the string is inserted into the out vector.
+///
+/// We ignore ANY_STRING_RECURSIVE here. The consequence is that you cannot tab complete **
+/// wildcards. This is historic behavior.
+static bool wildcard_complete_internal(const wchar_t *str, const wchar_t *wc,
+ const wc_complete_pack_t &params, complete_flags_t flags,
+ std::vector<completion_t> *out, bool is_first_call = false) {
assert(str != NULL);
assert(wc != NULL);
-
- /* Maybe early out for hidden files. We require that the wildcard match these exactly (i.e. a dot); ANY_STRING not allowed */
- if (is_first_call && str[0] == L'.' && wc[0] != L'.')
- {
+
+ // Maybe early out for hidden files. We require that the wildcard match these exactly (i.e. a
+ // dot); ANY_STRING not allowed.
+ if (is_first_call && str[0] == L'.' && wc[0] != L'.') {
return false;
}
-
- /* Locate the next wildcard character position, e.g. ANY_CHAR or ANY_STRING */
+
+ // Locate the next wildcard character position, e.g. ANY_CHAR or ANY_STRING.
const size_t next_wc_char_pos = wildcard_find(wc);
-
- /* Maybe we have no more wildcards at all. This includes the empty string. */
- if (next_wc_char_pos == wcstring::npos)
- {
+
+ // Maybe we have no more wildcards at all. This includes the empty string.
+ if (next_wc_char_pos == wcstring::npos) {
string_fuzzy_match_t match = string_fuzzy_match_string(wc, str);
-
- /* If we're allowing fuzzy match, any match is OK. Otherwise we require a prefix match. */
+
+ // If we're allowing fuzzy match, any match is OK. Otherwise we require a prefix match.
bool match_acceptable;
- if (params.expand_flags & EXPAND_FUZZY_MATCH)
- {
+ if (params.expand_flags & EXPAND_FUZZY_MATCH) {
match_acceptable = match.type != fuzzy_match_none;
- }
- else
- {
+ } else {
match_acceptable = match_type_shares_prefix(match.type);
}
-
- if (match_acceptable && out != NULL)
- {
- /* Wildcard complete */
- bool full_replacement = match_type_requires_full_replacement(match.type) || (flags & COMPLETE_REPLACES_TOKEN);
-
- /* If we are not replacing the token, be careful to only store the part of the string after the wildcard */
+
+ if (match_acceptable && out != NULL) {
+ // Wildcard complete.
+ bool full_replacement = match_type_requires_full_replacement(match.type) ||
+ (flags & COMPLETE_REPLACES_TOKEN);
+
+ // If we are not replacing the token, be careful to only store the part of the string
+ // after the wildcard.
assert(!full_replacement || wcslen(wc) <= wcslen(str));
wcstring out_completion = full_replacement ? params.orig : str + wcslen(wc);
wcstring out_desc = resolve_description(&out_completion, params.desc, params.desc_func);
-
- /* Note: out_completion may be empty if the completion really is empty, e.g. tab-completing 'foo' when a file 'foo' exists. */
+
+ // Note: out_completion may be empty if the completion really is empty, e.g.
+ // tab-completing 'foo' when a file 'foo' exists.
complete_flags_t local_flags = flags | (full_replacement ? COMPLETE_REPLACES_TOKEN : 0);
append_completion(out, out_completion, out_desc, local_flags, match);
}
return match_acceptable;
- }
- else if (next_wc_char_pos > 0)
- {
- /* Here we have a non-wildcard prefix. Note that we don't do fuzzy matching for stuff before a wildcard, so just do case comparison and then recurse. */
- if (wcsncmp(str, wc, next_wc_char_pos) == 0)
- {
- // Normal match
- return wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params, flags, out);
- }
- else if (wcsncasecmp(str, wc, next_wc_char_pos) == 0)
- {
- // Case insensitive match
- return wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params, flags | COMPLETE_REPLACES_TOKEN, out);
- }
- else
- {
- // No match
+ } else if (next_wc_char_pos > 0) {
+ // Here we have a non-wildcard prefix. Note that we don't do fuzzy matching for stuff before
+ // a wildcard, so just do case comparison and then recurse.
+ if (wcsncmp(str, wc, next_wc_char_pos) == 0) {
+ // Normal match.
+ return wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params,
+ flags, out);
+ } else if (wcsncasecmp(str, wc, next_wc_char_pos) == 0) {
+ // Case insensitive match.
+ return wildcard_complete_internal(str + next_wc_char_pos, wc + next_wc_char_pos, params,
+ flags | COMPLETE_REPLACES_TOKEN, out);
+ } else {
+ // No match.
return false;
}
assert(0 && "Unreachable code reached");
- }
- else
- {
- /* Our first character is a wildcard. */
+ } else {
+ // Our first character is a wildcard.
assert(next_wc_char_pos == 0);
- switch (wc[0])
- {
- case ANY_CHAR:
- {
- if (str[0] == L'\0')
- {
+ switch (wc[0]) {
+ case ANY_CHAR: {
+ if (str[0] == L'\0') {
return false;
- }
- else
- {
+ } else {
return wildcard_complete_internal(str + 1, wc + 1, params, flags, out);
}
break;
}
-
- case ANY_STRING:
- {
- /* Hackish. If this is the last character of the wildcard, then just complete with the empty string. This fixes cases like "f*<tab>" -> "f*o" */
- if (wc[1] == L'\0')
- {
+
+ case ANY_STRING: {
+ // Hackish. If this is the last character of the wildcard, then just complete with
+ // the empty string. This fixes cases like "f*<tab>" -> "f*o".
+ if (wc[1] == L'\0') {
return wildcard_complete_internal(L"", L"", params, flags, out);
}
-
- /* Try all submatches. #929: if the recursive call gives us a prefix match, just stop. This is sloppy - what we really want to do is say, once we've seen a match of a particular type, ignore all matches of that type further down the string, such that the wildcard produces the "minimal match.". */
+
+ // Try all submatches. Issue #929: if the recursive call gives us a prefix match,
+ // just stop. This is sloppy - what we really want to do is say, once we've seen a
+ // match of a particular type, ignore all matches of that type further down the
+ // string, such that the wildcard produces the "minimal match.".
bool has_match = false;
- for (size_t i=0; str[i] != L'\0'; i++)
- {
+ for (size_t i = 0; str[i] != L'\0'; i++) {
const size_t before_count = out ? out->size() : 0;
- if (wildcard_complete_internal(str + i, wc + 1, params, flags, out))
- {
- /* We found a match */
+ if (wildcard_complete_internal(str + i, wc + 1, params, flags, out)) {
+ // We found a match.
has_match = true;
-
- /* If out is NULL, we don't care about the actual matches. If out is not NULL but we have a prefix match, stop there. */
- if (out == NULL || has_prefix_match(out, before_count))
- {
+
+ // If out is NULL, we don't care about the actual matches. If out is not
+ // NULL but we have a prefix match, stop there.
+ if (out == NULL || has_prefix_match(out, before_count)) {
break;
}
}
}
return has_match;
}
-
+
case ANY_STRING_RECURSIVE:
- /* We don't even try with this one */
+ // We don't even try with this one.
return false;
-
+
default:
assert(0 && "Unreachable code reached");
return false;
@@ -395,160 +302,99 @@ static bool wildcard_complete_internal(const wchar_t *str,
assert(0 && "Unreachable code reached");
}
-bool wildcard_complete(const wcstring &str,
- const wchar_t *wc,
- const wchar_t *desc,
- wcstring(*desc_func)(const wcstring &),
- std::vector<completion_t> *out,
- expand_flags_t expand_flags,
- complete_flags_t flags)
-{
- // Note out may be NULL
+bool wildcard_complete(const wcstring &str, const wchar_t *wc, const wchar_t *desc,
+ wcstring (*desc_func)(const wcstring &), std::vector<completion_t> *out,
+ expand_flags_t expand_flags, complete_flags_t flags) {
+ // Note out may be NULL.
assert(wc != NULL);
wc_complete_pack_t params(str, desc, desc_func, expand_flags);
return wildcard_complete_internal(str.c_str(), wc, params, flags, out, true /* first call */);
}
-
-bool wildcard_match(const wcstring &str, const wcstring &wc, bool leading_dots_fail_to_match)
-{
- enum fuzzy_match_type_t match = wildcard_match_internal(str.c_str(), wc.c_str(), leading_dots_fail_to_match, true /* first */);
+bool wildcard_match(const wcstring &str, const wcstring &wc, bool leading_dots_fail_to_match) {
+ enum fuzzy_match_type_t match = wildcard_match_internal(
+ str.c_str(), wc.c_str(), leading_dots_fail_to_match, true /* first */);
return match != fuzzy_match_none;
}
-/**
- Obtain a description string for the file specified by the filename.
-
- The returned value is a string constant and should not be free'd.
-
- \param filename The file for which to find a description string
- \param lstat_res The result of calling lstat on the file
- \param lbuf The struct buf output of calling lstat on the file
- \param stat_res The result of calling stat on the file
- \param buf The struct buf output of calling stat on the file
- \param err The errno value after a failed stat call on the file.
- */
-
-static wcstring file_get_desc(const wcstring &filename,
- int lstat_res,
- const struct stat &lbuf,
- int stat_res,
- const struct stat &buf,
- int err)
-{
-
- if (!lstat_res)
- {
- if (S_ISLNK(lbuf.st_mode))
- {
- if (!stat_res)
- {
- if (S_ISDIR(buf.st_mode))
- {
+/// Obtain a description string for the file specified by the filename.
+///
+/// The returned value is a string constant and should not be free'd.
+///
+/// \param filename The file for which to find a description string
+/// \param lstat_res The result of calling lstat on the file
+/// \param lbuf The struct buf output of calling lstat on the file
+/// \param stat_res The result of calling stat on the file
+/// \param buf The struct buf output of calling stat on the file
+/// \param err The errno value after a failed stat call on the file.
+static wcstring file_get_desc(const wcstring &filename, int lstat_res, const struct stat &lbuf,
+ int stat_res, const struct stat &buf, int err) {
+ if (!lstat_res) {
+ if (S_ISLNK(lbuf.st_mode)) {
+ if (!stat_res) {
+ if (S_ISDIR(buf.st_mode)) {
return COMPLETE_DIRECTORY_SYMLINK_DESC;
- }
- else
- {
-
- if (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
- {
-
- if (waccess(filename, X_OK) == 0)
- {
- /*
- Weird group permissions and other such
- issues make it non-trivial to find out
- if we can actually execute a file using
- the result from stat. It is much safer
- to use the access function, since it
- tells us exactly what we want to know.
- */
+ } else {
+ if (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) {
+ if (waccess(filename, X_OK) == 0) {
+ // Weird group permissions and other such issues make it non-trivial to
+ // find out if we can actually execute a file using the result from
+ // stat. It is much safer to use the access function, since it tells us
+ // exactly what we want to know.
return COMPLETE_EXEC_LINK_DESC;
}
}
}
-
+
return COMPLETE_SYMLINK_DESC;
-
- }
- else
- {
- switch (err)
- {
- case ENOENT:
- {
+
+ } else {
+ switch (err) {
+ case ENOENT: {
return COMPLETE_ROTTEN_SYMLINK_DESC;
}
-
- case ELOOP:
- {
+ case ELOOP: {
return COMPLETE_LOOP_SYMLINK_DESC;
}
}
- /*
- On unknown errors we do nothing. The file will be
- given the default 'File' description or one based on the suffix.
- */
+ // On unknown errors we do nothing. The file will be given the default 'File'
+ // description or one based on the suffix.
}
-
- }
- else if (S_ISCHR(buf.st_mode))
- {
+
+ } else if (S_ISCHR(buf.st_mode)) {
return COMPLETE_CHAR_DESC;
- }
- else if (S_ISBLK(buf.st_mode))
- {
+ } else if (S_ISBLK(buf.st_mode)) {
return COMPLETE_BLOCK_DESC;
- }
- else if (S_ISFIFO(buf.st_mode))
- {
+ } else if (S_ISFIFO(buf.st_mode)) {
return COMPLETE_FIFO_DESC;
- }
- else if (S_ISSOCK(buf.st_mode))
- {
+ } else if (S_ISSOCK(buf.st_mode)) {
return COMPLETE_SOCKET_DESC;
- }
- else if (S_ISDIR(buf.st_mode))
- {
+ } else if (S_ISDIR(buf.st_mode)) {
return COMPLETE_DIRECTORY_DESC;
- }
- else
- {
- if (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXGRP))
- {
-
- if (waccess(filename, X_OK) == 0)
- {
- /*
- Weird group permissions and other such issues
- make it non-trivial to find out if we can
- actually execute a file using the result from
- stat. It is much safer to use the access
- function, since it tells us exactly what we want
- to know.
- */
+ } else {
+ if (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXGRP)) {
+ if (waccess(filename, X_OK) == 0) {
+ // Weird group permissions and other such issues make it non-trivial to find out
+ // if we can actually execute a file using the result from stat. It is much
+ // safer to use the access function, since it tells us exactly what we want to
+ // know.
return COMPLETE_EXEC_DESC;
}
}
}
}
-
- return COMPLETE_FILE_DESC ;
+
+ return COMPLETE_FILE_DESC;
}
-/** Test if the given file is an executable (if EXECUTABLES_ONLY) or directory (if DIRECTORIES_ONLY).
- If it matches, call wildcard_complete() with some description that we make up.
- Note that the filename came from a readdir() call, so we know it exists.
- */
-static bool wildcard_test_flags_then_complete(const wcstring &filepath,
- const wcstring &filename,
- const wchar_t *wc,
- expand_flags_t expand_flags,
- std::vector<completion_t> *out)
-{
- /* Check if it will match before stat() */
- if (! wildcard_complete(filename, wc, NULL, NULL, NULL, expand_flags, 0))
- {
+/// Test if the given file is an executable (if EXECUTABLES_ONLY) or directory (if
+/// DIRECTORIES_ONLY). If it matches, call wildcard_complete() with some description that we make
+/// up. Note that the filename came from a readdir() call, so we know it exists.
+static bool wildcard_test_flags_then_complete(const wcstring &filepath, const wcstring &filename,
+ const wchar_t *wc, expand_flags_t expand_flags,
+ std::vector<completion_t> *out) {
+ // Check if it will match before stat().
+ if (!wildcard_complete(filename, wc, NULL, NULL, NULL, expand_flags, 0)) {
return false;
}
@@ -556,199 +402,160 @@ static bool wildcard_test_flags_then_complete(const wcstring &filepath,
int stat_res = -1;
int stat_errno = 0;
int lstat_res = lwstat(filepath, &lstat_buf);
- if (lstat_res < 0)
- {
- /* lstat failed */
- }
- else
- {
- if (S_ISLNK(lstat_buf.st_mode))
- {
+ if (lstat_res < 0) {
+ // lstat failed.
+ } else {
+ if (S_ISLNK(lstat_buf.st_mode)) {
stat_res = wstat(filepath, &stat_buf);
-
- if (stat_res < 0)
- {
- /*
- In order to differentiate between e.g. rotten symlinks
- and symlink loops, we also need to know the error status of wstat.
- */
+
+ if (stat_res < 0) {
+ // In order to differentiate between e.g. rotten symlinks and symlink loops, we also
+ // need to know the error status of wstat.
stat_errno = errno;
}
- }
- else
- {
+ } else {
stat_buf = lstat_buf;
stat_res = lstat_res;
}
}
-
+
const long long file_size = stat_res == 0 ? stat_buf.st_size : 0;
const bool is_directory = stat_res == 0 && S_ISDIR(stat_buf.st_mode);
const bool is_executable = stat_res == 0 && S_ISREG(stat_buf.st_mode);
-
- if (expand_flags & DIRECTORIES_ONLY)
- {
- if (!is_directory)
- {
+
+ if (expand_flags & DIRECTORIES_ONLY) {
+ if (!is_directory) {
return false;
}
}
- if (expand_flags & EXECUTABLES_ONLY)
- {
- if (!is_executable || waccess(filepath, X_OK) != 0)
- {
+ if (expand_flags & EXECUTABLES_ONLY) {
+ if (!is_executable || waccess(filepath, X_OK) != 0) {
return false;
}
}
-
- /* Compute the description */
+
+ // Compute the description.
wcstring desc;
- if (!(expand_flags & EXPAND_NO_DESCRIPTIONS))
- {
+ if (!(expand_flags & EXPAND_NO_DESCRIPTIONS)) {
desc = file_get_desc(filepath, lstat_res, lstat_buf, stat_res, stat_buf, stat_errno);
-
- if (file_size >= 0)
- {
- if (!desc.empty())
- desc.append(L", ");
+
+ if (file_size >= 0) {
+ if (!desc.empty()) desc.append(L", ");
desc.append(format_size(file_size));
}
}
-
- /* Append a / if this is a directory. Note this requirement may be the only reason we have to call stat() in some cases. */
- if (is_directory)
- {
- return wildcard_complete(filename + L'/', wc, desc.c_str(), NULL, out, expand_flags, COMPLETE_NO_SPACE);
- }
- else
- {
+
+ // Append a / if this is a directory. Note this requirement may be the only reason we have to
+ // call stat() in some cases.
+ if (is_directory) {
+ return wildcard_complete(filename + L'/', wc, desc.c_str(), NULL, out, expand_flags,
+ COMPLETE_NO_SPACE);
+ } else {
return wildcard_complete(filename, wc, desc.c_str(), NULL, out, expand_flags, 0);
}
}
-class wildcard_expander_t
-{
- /* Prefix, i.e. effective working directory */
+class wildcard_expander_t {
+ // Prefix, i.e. effective working directory.
const wcstring prefix;
-
- /* The original base we are expanding */
+ // The original base we are expanding.
const wcstring original_base;
-
- /* Original wildcard we are expanding. */
- const wchar_t * const original_wildcard;
-
- /* the set of items we have resolved, used to efficiently avoid duplication */
+ // Original wildcard we are expanding.
+ const wchar_t *const original_wildcard;
+ // The set of items we have resolved, used to efficiently avoid duplication.
std::set<wcstring> completion_set;
-
- /* the set of file IDs we have visited, used to avoid symlink loops */
+ // The set of file IDs we have visited, used to avoid symlink loops.
std::set<file_id_t> visited_files;
-
- /* flags controlling expansion */
+ // Flags controlling expansion.
const expand_flags_t flags;
-
- /* resolved items get inserted into here. This is transient of course. */
+ // Resolved items get inserted into here. This is transient of course.
std::vector<completion_t> *resolved_completions;
-
- /* whether we have been interrupted */
+ // Whether we have been interrupted.
bool did_interrupt;
-
- /* whether we have successfully added any completions */
+ // Whether we have successfully added any completions.
bool did_add;
-
- /* We are a trailing slash - expand at the end */
+
+ /// We are a trailing slash - expand at the end.
void expand_trailing_slash(const wcstring &base_dir);
-
- /* Given a directory base_dir, which is opened as base_dir_fp, expand an intermediate segment of the wildcard.
- Treat ANY_STRING_RECURSIVE as ANY_STRING.
- wc_segment is the wildcard segment for this directory
- wc_remainder is the wildcard for subdirectories
- */
- void expand_intermediate_segment(const wcstring &base_dir, DIR *base_dir_fp, const wcstring &wc_segment, const wchar_t *wc_remainder);
-
- /* Given a directory base_dir, which is opened as base_dir_fp, expand an intermediate literal segment.
- Use a fuzzy matching algorithm.
- */
- void expand_literal_intermediate_segment_with_fuzz(const wcstring &base_dir, DIR *base_dir_fp, const wcstring &wc_segment, const wchar_t *wc_remainder);
-
- /* Given a directory base_dir, which is opened as base_dir_fp, expand the last segment of the wildcard.
- Treat ANY_STRING_RECURSIVE as ANY_STRING.
- wc is the wildcard segment to use for matching
- wc_remainder is the wildcard for subdirectories
- */
+
+ /// Given a directory base_dir, which is opened as base_dir_fp, expand an intermediate segment
+ /// of the wildcard. Treat ANY_STRING_RECURSIVE as ANY_STRING. wc_segment is the wildcard
+ /// segment for this directory wc_remainder is the wildcard for subdirectories
+ void expand_intermediate_segment(const wcstring &base_dir, DIR *base_dir_fp,
+ const wcstring &wc_segment, const wchar_t *wc_remainder);
+
+ /// Given a directory base_dir, which is opened as base_dir_fp, expand an intermediate literal
+ /// segment. Use a fuzzy matching algorithm.
+ void expand_literal_intermediate_segment_with_fuzz(const wcstring &base_dir, DIR *base_dir_fp,
+ const wcstring &wc_segment,
+ const wchar_t *wc_remainder);
+
+ /// Given a directory base_dir, which is opened as base_dir_fp, expand the last segment of the
+ /// wildcard. Treat ANY_STRING_RECURSIVE as ANY_STRING. wc is the wildcard segment to use for
+ /// matching wc_remainder is the wildcard for subdirectories.
void expand_last_segment(const wcstring &base_dir, DIR *base_dir_fp, const wcstring &wc);
-
- /* Indicate whether we should cancel wildcard expansion. This latches 'interrupt' */
- bool interrupted()
- {
- if (! did_interrupt)
- {
- did_interrupt = (is_main_thread() ? reader_interrupted() : reader_thread_job_is_stale());
+
+ /// Indicate whether we should cancel wildcard expansion. This latches 'interrupt'.
+ bool interrupted() {
+ if (!did_interrupt) {
+ did_interrupt =
+ (is_main_thread() ? reader_interrupted() : reader_thread_job_is_stale());
}
return did_interrupt;
}
-
- void add_expansion_result(const wcstring &result)
- {
- /* This function is only for the non-completions case */
- assert(! (this->flags & EXPAND_FOR_COMPLETIONS));
- if (this->completion_set.insert(result).second)
- {
+
+ void add_expansion_result(const wcstring &result) {
+ // This function is only for the non-completions case.
+ assert(!(this->flags & EXPAND_FOR_COMPLETIONS));
+ if (this->completion_set.insert(result).second) {
append_completion(this->resolved_completions, result);
this->did_add = true;
}
}
-
- /* Given a start point as an absolute path, for any directory that has exactly one non-hidden entity in it which is itself a directory, return that. The result is a relative path. For example, if start_point is '/usr' we may return 'local/bin/'.
-
- The result does not have a leading slash, but does have a trailing slash if non-empty. */
- wcstring descend_unique_hierarchy(const wcstring &start_point)
- {
- assert(! start_point.empty() && start_point.at(0) == L'/');
-
+
+ // Given a start point as an absolute path, for any directory that has exactly one non-hidden
+ // entity in it which is itself a directory, return that. The result is a relative path. For
+ // example, if start_point is '/usr' we may return 'local/bin/'.
+ //
+ // The result does not have a leading slash, but does have a trailing slash if non-empty.
+ wcstring descend_unique_hierarchy(const wcstring &start_point) {
+ assert(!start_point.empty() && start_point.at(0) == L'/');
+
wcstring unique_hierarchy;
wcstring abs_unique_hierarchy = start_point;
-
+
bool stop_descent = false;
DIR *dir;
- while (!stop_descent && (dir = wopendir(abs_unique_hierarchy)))
- {
- /* We keep track of the single unique_entry entry. If we get more than one, it's not unique and we stop the descent. */
+ while (!stop_descent && (dir = wopendir(abs_unique_hierarchy))) {
+ // We keep track of the single unique_entry entry. If we get more than one, it's not
+ // unique and we stop the descent.
wcstring unique_entry;
-
+
bool child_is_dir;
wcstring child_entry;
- while (wreaddir_resolving(dir, abs_unique_hierarchy, child_entry, &child_is_dir))
- {
- if (child_entry.empty() || child_entry.at(0) == L'.')
- {
- /* Either hidden, or . and .. entries. Skip them. */
- continue;
- }
- else if (child_is_dir && unique_entry.empty())
- {
- /* First candidate */
- unique_entry = child_entry;
- }
- else
- {
- /* We either have two or more candidates, or the child is not a directory. We're done. */
+ while (wreaddir_resolving(dir, abs_unique_hierarchy, child_entry, &child_is_dir)) {
+ if (child_entry.empty() || child_entry.at(0) == L'.') {
+ continue; // either hidden, or . and .. entries -- skip them
+ } else if (child_is_dir && unique_entry.empty()) {
+ unique_entry = child_entry; // first candidate
+ } else {
+ // We either have two or more candidates, or the child is not a directory. We're
+ // done.
stop_descent = true;
break;
}
}
-
- /* We stop if we got two or more entries; also stop if we got zero. */
- if (unique_entry.empty())
- {
+
+ // We stop if we got two or more entries; also stop if we got zero.
+ if (unique_entry.empty()) {
stop_descent = true;
}
-
- if (! stop_descent)
- {
- /* We have an entry in the unique hierarchy! */
+
+ if (!stop_descent) {
+ // We have an entry in the unique hierarchy!
append_path_component(unique_hierarchy, unique_entry);
unique_hierarchy.push_back(L'/');
-
+
append_path_component(abs_unique_hierarchy, unique_entry);
abs_unique_hierarchy.push_back(L'/');
}
@@ -757,121 +564,104 @@ class wildcard_expander_t
return unique_hierarchy;
}
-
- void try_add_completion_result(const wcstring &filepath, const wcstring &filename, const wcstring &wildcard)
- {
- /* This function is only for the completions case */
+ void try_add_completion_result(const wcstring &filepath, const wcstring &filename,
+ const wcstring &wildcard) {
+ // This function is only for the completions case.
assert(this->flags & EXPAND_FOR_COMPLETIONS);
-
+
wcstring abs_path = this->prefix;
append_path_component(abs_path, filepath);
-
+
size_t before = this->resolved_completions->size();
- if (wildcard_test_flags_then_complete(abs_path, filename, wildcard.c_str(), this->flags, this->resolved_completions))
- {
- /* Hack. We added this completion result based on the last component of the wildcard.
- Prepend all prior components of the wildcard to each completion that replaces its token. */
+ if (wildcard_test_flags_then_complete(abs_path, filename, wildcard.c_str(), this->flags,
+ this->resolved_completions)) {
+ // Hack. We added this completion result based on the last component of the wildcard.
+ // Prepend all prior components of the wildcard to each completion that replaces its
+ // token.
size_t wc_len = wildcard.size();
size_t orig_wc_len = wcslen(this->original_wildcard);
assert(wc_len <= orig_wc_len);
const wcstring wc_base(this->original_wildcard, orig_wc_len - wc_len);
-
+
size_t after = this->resolved_completions->size();
- for (size_t i=before; i < after; i++)
- {
+ for (size_t i = before; i < after; i++) {
completion_t &c = this->resolved_completions->at(i);
c.prepend_token_prefix(wc_base);
c.prepend_token_prefix(this->original_base);
}
-
- /* Hack. Implement EXPAND_SPECIAL_FOR_CD by descending the deepest unique hierarchy we can, and then appending any components to each new result. */
- if (flags & EXPAND_SPECIAL_FOR_CD)
- {
+
+ // Hack. Implement EXPAND_SPECIAL_FOR_CD by descending the deepest unique hierarchy we
+ // can, and then appending any components to each new result.
+ if (flags & EXPAND_SPECIAL_FOR_CD) {
wcstring unique_hierarchy = this->descend_unique_hierarchy(abs_path);
- if (! unique_hierarchy.empty())
- {
- for (size_t i=before; i < after; i++)
- {
+ if (!unique_hierarchy.empty()) {
+ for (size_t i = before; i < after; i++) {
completion_t &c = this->resolved_completions->at(i);
c.completion.append(unique_hierarchy);
}
}
}
-
+
this->did_add = true;
}
}
-
- /* Helper to resolve using our prefix */
- DIR *open_dir(const wcstring &base_dir) const
- {
+
+ // Helper to resolve using our prefix.
+ DIR *open_dir(const wcstring &base_dir) const {
wcstring path = this->prefix;
append_path_component(path, base_dir);
return wopendir(path);
}
-
-public:
-
- wildcard_expander_t(const wcstring &pref, const wcstring &orig_base, const wchar_t *orig_wc, expand_flags_t f, std::vector<completion_t> *r) :
- prefix(pref),
- original_base(orig_base),
- original_wildcard(orig_wc),
- flags(f),
- resolved_completions(r),
- did_interrupt(false),
- did_add(false)
- {
+
+ public:
+ wildcard_expander_t(const wcstring &pref, const wcstring &orig_base, const wchar_t *orig_wc,
+ expand_flags_t f, std::vector<completion_t> *r)
+ : prefix(pref),
+ original_base(orig_base),
+ original_wildcard(orig_wc),
+ flags(f),
+ resolved_completions(r),
+ did_interrupt(false),
+ did_add(false) {
assert(resolved_completions != NULL);
-
- /* Insert initial completions into our set to avoid duplicates */
- for (std::vector<completion_t>::const_iterator iter = resolved_completions->begin(); iter != resolved_completions->end(); ++iter)
- {
+
+ // Insert initial completions into our set to avoid duplicates.
+ for (std::vector<completion_t>::const_iterator iter = resolved_completions->begin();
+ iter != resolved_completions->end(); ++iter) {
this->completion_set.insert(iter->completion);
}
}
-
- /* Do wildcard expansion. This is recursive. */
+
+ // Do wildcard expansion. This is recursive.
void expand(const wcstring &base_dir, const wchar_t *wc);
-
- int status_code() const
- {
- if (this->did_interrupt)
- {
+
+ int status_code() const {
+ if (this->did_interrupt) {
return -1;
- }
- else
- {
+ } else {
return this->did_add ? 1 : 0;
}
}
};
-void wildcard_expander_t::expand_trailing_slash(const wcstring &base_dir)
-{
- if (interrupted())
- {
+void wildcard_expander_t::expand_trailing_slash(const wcstring &base_dir) {
+ if (interrupted()) {
return;
}
-
- if (! (flags & EXPAND_FOR_COMPLETIONS))
- {
- /* Trailing slash and not accepting incomplete, e.g. `echo /tmp/`. Insert this file if it exists. */
- if (waccess(base_dir, F_OK) == 0)
- {
+
+ if (!(flags & EXPAND_FOR_COMPLETIONS)) {
+ // Trailing slash and not accepting incomplete, e.g. `echo /tmp/`. Insert this file if it
+ // exists.
+ if (waccess(base_dir, F_OK) == 0) {
this->add_expansion_result(base_dir);
}
- }
- else
- {
- /* Trailing slashes and accepting incomplete, e.g. `echo /tmp/<tab>`. Everything is added. */
+ } else {
+ // Trailing slashes and accepting incomplete, e.g. `echo /tmp/<tab>`. Everything is added.
DIR *dir = open_dir(base_dir);
- if (dir)
- {
+ if (dir) {
wcstring next;
- while (wreaddir(dir, next) && ! interrupted())
- {
- if (! next.empty() && next.at(0) != L'.')
- {
+ while (wreaddir(dir, next) && !interrupted()) {
+ if (!next.empty() && next.at(0) != L'.') {
this->try_add_completion_result(base_dir + next, next, L"");
}
}
@@ -880,239 +670,212 @@ void wildcard_expander_t::expand_trailing_slash(const wcstring &base_dir)
}
}
-void wildcard_expander_t::expand_intermediate_segment(const wcstring &base_dir, DIR *base_dir_fp, const wcstring &wc_segment, const wchar_t *wc_remainder)
-{
+void wildcard_expander_t::expand_intermediate_segment(const wcstring &base_dir, DIR *base_dir_fp,
+ const wcstring &wc_segment,
+ const wchar_t *wc_remainder) {
wcstring name_str;
- while (!interrupted() && wreaddir_for_dirs(base_dir_fp, &name_str))
- {
- /* Note that it's critical we ignore leading dots here, else we may descend into . and .. */
- if (! wildcard_match(name_str, wc_segment, true))
- {
- /* Doesn't match the wildcard for this segment, skip it */
+ while (!interrupted() && wreaddir_for_dirs(base_dir_fp, &name_str)) {
+ // Note that it's critical we ignore leading dots here, else we may descend into . and ..
+ if (!wildcard_match(name_str, wc_segment, true)) {
+ // Doesn't match the wildcard for this segment, skip it.
continue;
}
-
+
wcstring full_path = base_dir + name_str;
struct stat buf;
- if (0 != wstat(full_path, &buf) || !S_ISDIR(buf.st_mode))
- {
- /* We either can't stat it, or we did but it's not a directory */
+ if (0 != wstat(full_path, &buf) || !S_ISDIR(buf.st_mode)) {
+ // We either can't stat it, or we did but it's not a directory.
continue;
}
const file_id_t file_id = file_id_t::file_id_from_stat(&buf);
- if (!this->visited_files.insert(file_id).second)
- {
- /* Symlink loop! This directory was already visited, so skip it */
+ if (!this->visited_files.insert(file_id).second) {
+ // Symlink loop! This directory was already visited, so skip it.
continue;
}
- /* We made it through. Perform normal wildcard expansion on this new directory, starting at our tail_wc, which includes the ANY_STRING_RECURSIVE guy. */
+ // We made it through. Perform normal wildcard expansion on this new directory, starting at
+ // our tail_wc, which includes the ANY_STRING_RECURSIVE guy.
full_path.push_back(L'/');
this->expand(full_path, wc_remainder);
- /* Now remove the visited file. This is for #2414: only directories "beneath" us should be considered visited. */
+ // Now remove the visited file. This is for #2414: only directories "beneath" us should be
+ // considered visited.
this->visited_files.erase(file_id);
}
}
-
-void wildcard_expander_t::expand_literal_intermediate_segment_with_fuzz(const wcstring &base_dir, DIR *base_dir_fp, const wcstring &wc_segment, const wchar_t *wc_remainder)
-{
- // This only works with tab completions
- // Ordinary wildcard expansion should never go fuzzy
+
+void wildcard_expander_t::expand_literal_intermediate_segment_with_fuzz(
+ const wcstring &base_dir, DIR *base_dir_fp, const wcstring &wc_segment,
+ const wchar_t *wc_remainder) {
+ // This only works with tab completions. Ordinary wildcard expansion should never go fuzzy.
wcstring name_str;
- while (!interrupted() && wreaddir_for_dirs(base_dir_fp, &name_str))
- {
- /* Don't bother with . and .. */
- if (contains(name_str, L".", L".."))
- {
+ while (!interrupted() && wreaddir_for_dirs(base_dir_fp, &name_str)) {
+ // Don't bother with . and ..
+ if (contains(name_str, L".", L"..")) {
continue;
}
-
- // Skip cases that don't match or match exactly
- // The match-exactly case was handled directly in expand()
+
+ // Skip cases that don't match or match exactly. The match-exactly case was handled directly
+ // in expand().
const string_fuzzy_match_t match = string_fuzzy_match_string(wc_segment, name_str);
- if (match.type == fuzzy_match_none || match.type == fuzzy_match_exact)
- {
+ if (match.type == fuzzy_match_none || match.type == fuzzy_match_exact) {
continue;
}
-
+
wcstring new_full_path = base_dir + name_str;
new_full_path.push_back(L'/');
struct stat buf;
- if (0 != wstat(new_full_path, &buf) || !S_ISDIR(buf.st_mode))
- {
+ if (0 != wstat(new_full_path, &buf) || !S_ISDIR(buf.st_mode)) {
/* We either can't stat it, or we did but it's not a directory */
continue;
}
-
- // Ok, this directory matches. Recurse to it.
- // Then perform serious surgery on each result!
- // Each result was computed with a prefix of original_wildcard
- // We need to replace our segment of that with our name_str
- // We also have to mark the completion as replacing and fuzzy
+
+ // Ok, this directory matches. Recurse to it. Then perform serious surgery on each result!
+ // Each result was computed with a prefix of original_wildcard. We need to replace our
+ // segment of that with our name_str. We also have to mark the completion as replacing and
+ // fuzzy.
const size_t before = this->resolved_completions->size();
-
+
this->expand(new_full_path, wc_remainder);
const size_t after = this->resolved_completions->size();
-
+
assert(before <= after);
- for (size_t i=before; i < after; i++)
- {
+ for (size_t i = before; i < after; i++) {
completion_t *c = &this->resolved_completions->at(i);
- // Mark the completion as replacing
- if (!(c->flags & COMPLETE_REPLACES_TOKEN))
- {
+ // Mark the completion as replacing.
+ if (!(c->flags & COMPLETE_REPLACES_TOKEN)) {
c->flags |= COMPLETE_REPLACES_TOKEN;
c->prepend_token_prefix(this->original_wildcard);
c->prepend_token_prefix(this->original_base);
}
- // Ok, it's now replacing and is prefixed with the segment base, plus our original wildcard
- // Replace our segment with name_str
- // Our segment starts at the length of the original wildcard, minus what we have left to process, minus the length of our segment
- // This logic is way too picky. Need to clean this up.
- // One possibility is to send the "resolved wildcard" along with the actual wildcard
+ // Ok, it's now replacing and is prefixed with the segment base, plus our original
+ // wildcard. Replace our segment with name_str. Our segment starts at the length of the
+ // original wildcard, minus what we have left to process, minus the length of our
+ // segment. This logic is way too picky. Need to clean this up. One possibility is to
+ // send the "resolved wildcard" along with the actual wildcard.
const size_t original_wildcard_len = wcslen(this->original_wildcard);
const size_t wc_remainder_len = wcslen(wc_remainder);
const size_t segment_len = wc_segment.length();
assert(c->completion.length() >= original_wildcard_len);
- const size_t segment_start = original_wildcard_len + this->original_base.size() - wc_remainder_len - wc_segment.length() - 1; // -1 for the slash after our segment
+ const size_t segment_start = original_wildcard_len + this->original_base.size() -
+ wc_remainder_len - wc_segment.length() -
+ 1; // -1 for the slash after our segment
assert(segment_start < original_wildcard_len);
assert(c->completion.substr(segment_start, segment_len) == wc_segment);
c->completion.replace(segment_start, segment_len, name_str);
-
- // And every match must be made at least as fuzzy as ours
- if (match.compare(c->match) > 0)
- {
- // Our match is fuzzier
+
+ // And every match must be made at least as fuzzy as ours.
+ if (match.compare(c->match) > 0) {
+ // Our match is fuzzier.
c->match = match;
}
}
}
}
-void wildcard_expander_t::expand_last_segment(const wcstring &base_dir, DIR *base_dir_fp, const wcstring &wc)
-{
+void wildcard_expander_t::expand_last_segment(const wcstring &base_dir, DIR *base_dir_fp,
+ const wcstring &wc) {
wcstring name_str;
- while (wreaddir(base_dir_fp, name_str))
- {
- if (flags & EXPAND_FOR_COMPLETIONS)
- {
+ while (wreaddir(base_dir_fp, name_str)) {
+ if (flags & EXPAND_FOR_COMPLETIONS) {
this->try_add_completion_result(base_dir + name_str, name_str, wc);
- }
- else
- {
- // Normal wildcard expansion, not for completions
- if (wildcard_match(name_str, wc, true /* skip files with leading dots */))
- {
+ } else {
+ // Normal wildcard expansion, not for completions.
+ if (wildcard_match(name_str, wc, true /* skip files with leading dots */)) {
this->add_expansion_result(base_dir + name_str);
}
}
}
}
-/**
- The real implementation of wildcard expansion is in this
- function. Other functions are just wrappers around this one.
-
- This function traverses the relevant directory tree looking for
- matches, and recurses when needed to handle wildcrards spanning
- multiple components and recursive wildcards.
-
- Because this function calls itself recursively with substrings,
- it's important that the parameters be raw pointers instead of wcstring,
- which would be too expensive to construct for all substrings.
-
- Args:
- base_dir: the "working directory" against which the wildcard is to be resolved
- wc: the wildcard string itself, e.g. foo*bar/baz (where * is acutally ANY_CHAR)
-*/
-void wildcard_expander_t::expand(const wcstring &base_dir, const wchar_t *wc)
-{
+/// The real implementation of wildcard expansion is in this function. Other functions are just
+/// wrappers around this one.
+///
+/// This function traverses the relevant directory tree looking for matches, and recurses when
+/// needed to handle wildcrards spanning multiple components and recursive wildcards.
+///
+/// Because this function calls itself recursively with substrings, it's important that the
+/// parameters be raw pointers instead of wcstring, which would be too expensive to construct for
+/// all substrings.
+///
+/// Args:
+/// base_dir: the "working directory" against which the wildcard is to be resolved
+/// wc: the wildcard string itself, e.g. foo*bar/baz (where * is acutally ANY_CHAR)
+void wildcard_expander_t::expand(const wcstring &base_dir, const wchar_t *wc) {
assert(wc != NULL);
-
- if (interrupted())
- {
+
+ if (interrupted()) {
return;
}
-
- /* Get the current segment and compute interesting properties about it. */
+
+ // Get the current segment and compute interesting properties about it.
const size_t wc_len = wcslen(wc);
- const wchar_t * const next_slash = wcschr(wc, L'/');
+ const wchar_t *const next_slash = wcschr(wc, L'/');
const bool is_last_segment = (next_slash == NULL);
const size_t wc_segment_len = next_slash ? next_slash - wc : wc_len;
const wcstring wc_segment = wcstring(wc, wc_segment_len);
- const bool segment_has_wildcards = wildcard_has(wc_segment, true /* internal, i.e. look for ANY_CHAR instead of ? */);
-
- if (wc_segment.empty())
- {
- /* Handle empty segment */
- assert(! segment_has_wildcards);
- if (is_last_segment)
- {
+ const bool segment_has_wildcards =
+ wildcard_has(wc_segment, true /* internal, i.e. look for ANY_CHAR instead of ? */);
+
+ if (wc_segment.empty()) {
+ // Handle empty segment.
+ assert(!segment_has_wildcards);
+ if (is_last_segment) {
this->expand_trailing_slash(base_dir);
- }
- else
- {
- /* Multiple adjacent slashes in the wildcard. Just skip them. */
+ } else {
+ // Multiple adjacent slashes in the wildcard. Just skip them.
this->expand(base_dir, next_slash + 1);
}
- }
- else if (! segment_has_wildcards && ! is_last_segment)
- {
- /* Literal intermediate match. Note that we may not be able to actually read the directory (#2099) */
+ } else if (!segment_has_wildcards && !is_last_segment) {
+ // Literal intermediate match. Note that we may not be able to actually read the directory
+ // (issue #2099).
assert(next_slash != NULL);
const wchar_t *wc_remainder = next_slash;
- while (*wc_remainder == L'/')
- {
+ while (*wc_remainder == L'/') {
wc_remainder++;
}
-
- /* This just trumps everything */
+
+ // This just trumps everything.
size_t before = this->resolved_completions->size();
this->expand(base_dir + wc_segment + L'/', wc_remainder);
-
- /* Maybe try a fuzzy match (#94) if nothing was found with the literal match. Respect EXPAND_NO_DIRECTORY_ABBREVIATIONS (#2413). */
- bool allow_fuzzy = (this->flags & (EXPAND_FUZZY_MATCH | EXPAND_NO_FUZZY_DIRECTORIES)) == EXPAND_FUZZY_MATCH;
- if (allow_fuzzy && this->resolved_completions->size() == before)
- {
+
+ // Maybe try a fuzzy match (#94) if nothing was found with the literal match. Respect
+ // EXPAND_NO_DIRECTORY_ABBREVIATIONS (issue #2413).
+ bool allow_fuzzy = (this->flags & (EXPAND_FUZZY_MATCH | EXPAND_NO_FUZZY_DIRECTORIES)) ==
+ EXPAND_FUZZY_MATCH;
+ if (allow_fuzzy && this->resolved_completions->size() == before) {
assert(this->flags & EXPAND_FOR_COMPLETIONS);
DIR *base_dir_fd = open_dir(base_dir);
- if (base_dir_fd != NULL)
- {
- this->expand_literal_intermediate_segment_with_fuzz(base_dir, base_dir_fd, wc_segment, wc_remainder);
+ if (base_dir_fd != NULL) {
+ this->expand_literal_intermediate_segment_with_fuzz(base_dir, base_dir_fd,
+ wc_segment, wc_remainder);
closedir(base_dir_fd);
}
}
- }
- else
- {
- assert(! wc_segment.empty() && (segment_has_wildcards || is_last_segment));
+ } else {
+ assert(!wc_segment.empty() && (segment_has_wildcards || is_last_segment));
DIR *dir = open_dir(base_dir);
- if (dir)
- {
- if (is_last_segment)
- {
- /* Last wildcard segment, nonempty wildcard */
+ if (dir) {
+ if (is_last_segment) {
+ // Last wildcard segment, nonempty wildcard.
this->expand_last_segment(base_dir, dir, wc_segment);
- }
- else
- {
- /* Not the last segment, nonempty wildcard */
+ } else {
+ // Not the last segment, nonempty wildcard.
assert(next_slash != NULL);
const wchar_t *wc_remainder = next_slash;
- while (*wc_remainder == L'/')
- {
+ while (*wc_remainder == L'/') {
wc_remainder++;
}
this->expand_intermediate_segment(base_dir, dir, wc_segment, wc_remainder);
}
-
- /* Recursive wildcards require special handling */
+
+ // Recursive wildcards require special handling.
size_t asr_idx = wc_segment.find(ANY_STRING_RECURSIVE);
- if (asr_idx != wcstring::npos)
- {
- /* Construct a "head + any" wildcard for matching stuff in this directory, and an "any + tail" wildcard for matching stuff in subdirectories. Note that the ANY_STRING_RECURSIVE character is present in both the head and the tail. */
+ if (asr_idx != wcstring::npos) {
+ // Construct a "head + any" wildcard for matching stuff in this directory, and an
+ // "any + tail" wildcard for matching stuff in subdirectories. Note that the
+ // ANY_STRING_RECURSIVE character is present in both the head and the tail.
const wcstring head_any(wc_segment, 0, asr_idx + 1);
const wchar_t *any_tail = wc + asr_idx;
assert(head_any.at(head_any.size() - 1) == ANY_STRING_RECURSIVE);
@@ -1126,41 +889,45 @@ void wildcard_expander_t::expand(const wcstring &base_dir, const wchar_t *wc)
}
}
-
-int wildcard_expand_string(const wcstring &wc, const wcstring &working_directory, expand_flags_t flags, std::vector<completion_t> *output)
-{
+int wildcard_expand_string(const wcstring &wc, const wcstring &working_directory,
+ expand_flags_t flags, std::vector<completion_t> *output) {
assert(output != NULL);
- /* Fuzzy matching only if we're doing completions */
+ // Fuzzy matching only if we're doing completions.
assert((flags & (EXPAND_FUZZY_MATCH | EXPAND_FOR_COMPLETIONS)) != EXPAND_FUZZY_MATCH);
-
- /* EXPAND_SPECIAL_FOR_CD requires DIRECTORIES_ONLY and EXPAND_FOR_COMPLETIONS and EXPAND_NO_DESCRIPTIONS */
+
+ // EXPAND_SPECIAL_FOR_CD requires DIRECTORIES_ONLY and EXPAND_FOR_COMPLETIONS and
+ // EXPAND_NO_DESCRIPTIONS.
assert(!(flags & EXPAND_SPECIAL_FOR_CD) ||
- ((flags & DIRECTORIES_ONLY) && (flags & EXPAND_FOR_COMPLETIONS) && (flags & EXPAND_NO_DESCRIPTIONS)));
-
- /* Hackish fix for 1631. We are about to call c_str(), which will produce a string truncated at any embedded nulls. We could fix this by passing around the size, etc. However embedded nulls are never allowed in a filename, so we just check for them and return 0 (no matches) if there is an embedded null. */
- if (wc.find(L'\0') != wcstring::npos)
- {
+ ((flags & DIRECTORIES_ONLY) && (flags & EXPAND_FOR_COMPLETIONS) &&
+ (flags & EXPAND_NO_DESCRIPTIONS)));
+
+ // Hackish fix for issue #1631. We are about to call c_str(), which will produce a string
+ // truncated at any embedded nulls. We could fix this by passing around the size, etc. However
+ // embedded nulls are never allowed in a filename, so we just check for them and return 0 (no
+ // matches) if there is an embedded null.
+ if (wc.find(L'\0') != wcstring::npos) {
return 0;
}
-
- /* Compute the prefix and base dir. The prefix is what we prepend for filesystem operations (i.e. the working directory), the base_dir is the part of the wildcard consumed thus far, which we also have to append. The difference is that the base_dir is returned as part of the expansion, and the prefix is not.
-
- Check for a leading slash. If we find one, we have an absolute path: the prefix is empty, the base dir is /, and the wildcard is the remainder. If we don't find one, the prefix is the working directory, there's base dir is empty.
- */
+
+ // Compute the prefix and base dir. The prefix is what we prepend for filesystem operations
+ // (i.e. the working directory), the base_dir is the part of the wildcard consumed thus far,
+ // which we also have to append. The difference is that the base_dir is returned as part of the
+ // expansion, and the prefix is not.
+ //
+ // Check for a leading slash. If we find one, we have an absolute path: the prefix is empty, the
+ // base dir is /, and the wildcard is the remainder. If we don't find one, the prefix is the
+ // working directory, there's base dir is empty.
wcstring prefix, base_dir, effective_wc;
- if (string_prefixes_string(L"/", wc))
- {
+ if (string_prefixes_string(L"/", wc)) {
prefix = L"";
base_dir = L"/";
effective_wc = wc.substr(1);
- }
- else
- {
+ } else {
prefix = working_directory;
base_dir = L"";
effective_wc = wc;
}
-
+
wildcard_expander_t expander(prefix, base_dir, effective_wc.c_str(), flags, output);
expander.expand(base_dir, wc.c_str());
return expander.status_code();
diff --git a/src/wildcard.h b/src/wildcard.h
index 05e185f4..1ed7cc89 100644
--- a/src/wildcard.h
+++ b/src/wildcard.h
@@ -1,84 +1,69 @@
-/** \file wildcard.h
-
- My own globbing implementation. Needed to implement this instead
- of using libs globbing to support tab-expansion of globbed
- paramaters.
-
-*/
+// My own globbing implementation. Needed to implement this instead of using libs globbing to
+// support tab-expansion of globbed paramaters.
#ifndef FISH_WILDCARD_H
#define FISH_WILDCARD_H
-#include <vector>
#include <stdbool.h>
+#include <vector>
#include "common.h"
-#include "expand.h"
#include "complete.h"
+#include "expand.h"
-// Enumeration of all wildcard types
-enum
-{
- // Character representing any character except '/' (slash).
+// Enumeration of all wildcard types.
+enum {
+ /// Character representing any character except '/' (slash).
ANY_CHAR = WILDCARD_RESERVED_BASE,
- // Character representing any character string not containing '/' (slash).
+ /// Character representing any character string not containing '/' (slash).
ANY_STRING,
- // Character representing any character string.
+ /// Character representing any character string.
ANY_STRING_RECURSIVE,
- // This is a special psuedo-char that is not used other than to mark the
- // end of the the special characters so we can sanity check the enum range.
+ /// This is a special psuedo-char that is not used other than to mark the
+ /// end of the the special characters so we can sanity check the enum range.
ANY_SENTINAL
};
-/**
- Expand the wildcard by matching against the filesystem.
-
- New strings are allocated using malloc and should be freed by the caller.
-
- wildcard_expand works by dividing the wildcard into segments at
- each directory boundary. Each segment is processed separatly. All
- except the last segment are handled by matching the wildcard
- segment against all subdirectories of matching directories, and
- recursively calling wildcard_expand for matches. On the last
- segment, matching is made to any file, and all matches are
- inserted to the list.
-
- If wildcard_expand encounters any errors (such as insufficient
- priviliges) during matching, no error messages will be printed and
- wildcard_expand will continue the matching process.
-
- \param wc The wildcard string
- \param working_directory The working directory
- \param flags flags for the search. Can be any combination of EXPAND_FOR_COMPLETIONS and EXECUTABLES_ONLY
- \param out The list in which to put the output
-
- \return 1 if matches where found, 0 otherwise. Return -1 on abort (I.e. ^C was pressed).
-
-*/
-int wildcard_expand_string(const wcstring &wc, const wcstring &working_directory, expand_flags_t flags, std::vector<completion_t> *out);
-
-/**
- Test whether the given wildcard matches the string. Does not perform any I/O.
-
- \param str The string to test
- \param wc The wildcard to test against
- \param leading_dots_fail_to_match if set, strings with leading dots are assumed to be hidden files and are not matched
- \return true if the wildcard matched
-*/
-bool wildcard_match(const wcstring &str, const wcstring &wc, bool leading_dots_fail_to_match = false);
-
-/** Check if the specified string contains wildcards */
+/// Expand the wildcard by matching against the filesystem.
+///
+/// New strings are allocated using malloc and should be freed by the caller.
+///
+/// wildcard_expand works by dividing the wildcard into segments at each directory boundary. Each
+/// segment is processed separatly. All except the last segment are handled by matching the wildcard
+/// segment against all subdirectories of matching directories, and recursively calling
+/// wildcard_expand for matches. On the last segment, matching is made to any file, and all matches
+/// are inserted to the list.
+///
+/// If wildcard_expand encounters any errors (such as insufficient priviliges) during matching, no
+/// error messages will be printed and wildcard_expand will continue the matching process.
+///
+/// \param wc The wildcard string
+/// \param working_directory The working directory
+/// \param flags flags for the search. Can be any combination of EXPAND_FOR_COMPLETIONS and
+/// EXECUTABLES_ONLY
+/// \param out The list in which to put the output
+///
+/// \return 1 if matches where found, 0 otherwise. Return -1 on abort (I.e. ^C was pressed).
+int wildcard_expand_string(const wcstring &wc, const wcstring &working_directory,
+ expand_flags_t flags, std::vector<completion_t> *out);
+
+/// Test whether the given wildcard matches the string. Does not perform any I/O.
+///
+/// \param str The string to test
+/// \param wc The wildcard to test against
+/// \param leading_dots_fail_to_match if set, strings with leading dots are assumed to be hidden
+/// files and are not matched
+///
+/// \return true if the wildcard matched
+bool wildcard_match(const wcstring &str, const wcstring &wc,
+ bool leading_dots_fail_to_match = false);
+
+/// Check if the specified string contains wildcards.
bool wildcard_has(const wcstring &, bool internal);
bool wildcard_has(const wchar_t *, bool internal);
-/**
- Test wildcard completion
-*/
-bool wildcard_complete(const wcstring &str,
- const wchar_t *wc,
- const wchar_t *desc,
- wcstring(*desc_func)(const wcstring &),
- std::vector<completion_t> *out,
- expand_flags_t expand_flags,
- complete_flags_t flags);
+/// Test wildcard completion.
+bool wildcard_complete(const wcstring &str, const wchar_t *wc, const wchar_t *desc,
+ wcstring (*desc_func)(const wcstring &), std::vector<completion_t> *out,
+ expand_flags_t expand_flags, complete_flags_t flags);
#endif
diff --git a/src/wutil.cpp b/src/wutil.cpp
index 1cee8320..c8b9e3f4 100644
--- a/src/wutil.cpp
+++ b/src/wutil.cpp
@@ -1,30 +1,27 @@
-/** \file wutil.c
- Wide character equivalents of various standard unix
- functions.
-*/
+// Wide character equivalents of various standard unix functions.
#include "config.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <assert.h>
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
-#include <wchar.h>
-#include <string.h>
-#include <dirent.h>
-#include <limits.h>
#include <libgen.h>
+#include <limits.h>
#include <pthread.h>
-#include <assert.h>
-#include <string>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wchar.h>
#include <map>
#include <memory>
+#include <string>
#include "common.h"
#include "fallback.h" // IWYU pragma: keep
-#include "wutil.h" // IWYU pragma: keep
+#include "wutil.h" // IWYU pragma: keep
typedef std::string cstring;
@@ -34,65 +31,53 @@ const file_id_t kInvalidFileID = {(dev_t)-1LL, (ino_t)-1LL, (uint64_t)-1LL, -1,
#ifdef MAXPATHLEN
#define PATH_MAX MAXPATHLEN
#else
-/**
- Fallback length of MAXPATHLEN. Just a hopefully sane value...
-*/
+/// Fallback length of MAXPATHLEN. Hopefully a sane value.
#define PATH_MAX 4096
#endif
#endif
-/* Lock to protect wgettext */
+/// Lock to protect wgettext.
static pthread_mutex_t wgettext_lock;
-/* Map used as cache by wgettext. */
+/// Map used as cache by wgettext.
typedef std::map<wcstring, wcstring> wgettext_map_t;
static wgettext_map_t wgettext_map;
-bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name, bool *out_is_dir)
-{
+bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name,
+ bool *out_is_dir) {
struct dirent *d = readdir(dir);
if (!d) return false;
out_name = str2wcstring(d->d_name);
- if (out_is_dir)
- {
- /* The caller cares if this is a directory, so check */
+ if (out_is_dir) {
+ // The caller cares if this is a directory, so check.
bool is_dir = false;
-
- /* We may be able to skip stat, if the readdir can tell us the file type directly */
+
+ // We may be able to skip stat, if the readdir can tell us the file type directly.
bool check_with_stat = true;
#ifdef HAVE_STRUCT_DIRENT_D_TYPE
- if (d->d_type == DT_DIR)
- {
- /* Known directory */
+ if (d->d_type == DT_DIR) {
+ // Known directory.
is_dir = true;
check_with_stat = false;
- }
- else if (d->d_type == DT_LNK || d->d_type == DT_UNKNOWN)
- {
- /* We want to treat symlinks to directories as directories. Use stat to resolve it. */
+ } else if (d->d_type == DT_LNK || d->d_type == DT_UNKNOWN) {
+ // We want to treat symlinks to directories as directories. Use stat to resolve it.
check_with_stat = true;
- }
- else
- {
- /* Regular file */
+ } else {
+ // Regular file.
is_dir = false;
check_with_stat = false;
}
-#endif // HAVE_STRUCT_DIRENT_D_TYPE
- if (check_with_stat)
- {
- /* We couldn't determine the file type from the dirent; check by stat'ing it */
+#endif // HAVE_STRUCT_DIRENT_D_TYPE
+ if (check_with_stat) {
+ // We couldn't determine the file type from the dirent; check by stat'ing it.
cstring fullpath = wcs2string(dir_path);
fullpath.push_back('/');
fullpath.append(d->d_name);
struct stat buf;
- if (stat(fullpath.c_str(), &buf) != 0)
- {
+ if (stat(fullpath.c_str(), &buf) != 0) {
is_dir = false;
- }
- else
- {
+ } else {
is_dir = !!(S_ISDIR(buf.st_mode));
}
}
@@ -101,8 +86,7 @@ bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &ou
return true;
}
-bool wreaddir(DIR *dir, std::wstring &out_name)
-{
+bool wreaddir(DIR *dir, std::wstring &out_name) {
struct dirent *d = readdir(dir);
if (!d) return false;
@@ -110,53 +94,45 @@ bool wreaddir(DIR *dir, std::wstring &out_name)
return true;
}
-bool wreaddir_for_dirs(DIR *dir, wcstring *out_name)
-{
+bool wreaddir_for_dirs(DIR *dir, wcstring *out_name) {
struct dirent *result = NULL;
- while (result == NULL)
- {
+ while (result == NULL) {
struct dirent *d = readdir(dir);
if (!d) break;
-
+
#if HAVE_STRUCT_DIRENT_D_TYPE
- switch (d->d_type)
- {
- // These may be directories
+ switch (d->d_type) {
case DT_DIR:
case DT_LNK:
- case DT_UNKNOWN:
+ case DT_UNKNOWN: {
+ // These may be directories.
result = d;
break;
-
- // Nothing else can
- default:
+ }
+ default: {
+ // Nothing else can.
break;
+ }
}
#else
- /* We can't determine if it's a directory or not, so just return it */
+ // We can't determine if it's a directory or not, so just return it.
result = d;
#endif
}
- if (result && out_name)
- {
+ if (result && out_name) {
*out_name = str2wcstring(result->d_name);
}
return result != NULL;
}
-
-const wcstring wgetcwd()
-{
+const wcstring wgetcwd() {
wcstring retval;
char *res = getcwd(NULL, 0);
- if (res)
- {
+ if (res) {
retval = str2wcstring(res);
free(res);
- }
- else
- {
+ } else {
debug(0, _(L"getcwd() failed with errno %d/%s"), errno, strerror(errno));
retval = wcstring();
}
@@ -164,176 +140,147 @@ const wcstring wgetcwd()
return retval;
}
-int wchdir(const wcstring &dir)
-{
+int wchdir(const wcstring &dir) {
cstring tmp = wcs2string(dir);
return chdir(tmp.c_str());
}
-FILE *wfopen(const wcstring &path, const char *mode)
-{
+FILE *wfopen(const wcstring &path, const char *mode) {
int permissions = 0, options = 0;
size_t idx = 0;
- switch (mode[idx++])
- {
- case 'r':
+ switch (mode[idx++]) {
+ case 'r': {
permissions = O_RDONLY;
break;
- case 'w':
+ }
+ case 'w': {
permissions = O_WRONLY;
options = O_CREAT | O_TRUNC;
break;
- case 'a':
+ }
+ case 'a': {
permissions = O_WRONLY;
options = O_CREAT | O_APPEND;
break;
- default:
+ }
+ default: {
errno = EINVAL;
return NULL;
break;
+ }
}
- /* Skip binary */
- if (mode[idx] == 'b')
- idx++;
+ // Skip binary.
+ if (mode[idx] == 'b') idx++;
- /* Consider append option */
- if (mode[idx] == '+')
- permissions = O_RDWR;
+ // Consider append option.
+ if (mode[idx] == '+') permissions = O_RDWR;
int fd = wopen_cloexec(path, permissions | options, 0666);
- if (fd < 0)
- return NULL;
+ if (fd < 0) return NULL;
FILE *result = fdopen(fd, mode);
- if (result == NULL)
- close(fd);
+ if (result == NULL) close(fd);
return result;
}
-bool set_cloexec(int fd)
-{
+bool set_cloexec(int fd) {
int flags = fcntl(fd, F_GETFD, 0);
- if (flags < 0)
- {
+ if (flags < 0) {
return false;
- }
- else if (flags & FD_CLOEXEC)
- {
+ } else if (flags & FD_CLOEXEC) {
return true;
- }
- else
- {
+ } else {
return fcntl(fd, F_SETFD, flags | FD_CLOEXEC) >= 0;
}
}
-static int wopen_internal(const wcstring &pathname, int flags, mode_t mode, bool cloexec)
-{
+static int wopen_internal(const wcstring &pathname, int flags, mode_t mode, bool cloexec) {
ASSERT_IS_NOT_FORKED_CHILD();
cstring tmp = wcs2string(pathname);
- /* Prefer to use O_CLOEXEC. It has to both be defined and nonzero. */
+// Prefer to use O_CLOEXEC. It has to both be defined and nonzero.
#ifdef O_CLOEXEC
- if (cloexec && (O_CLOEXEC != 0))
- {
+ if (cloexec && (O_CLOEXEC != 0)) {
flags |= O_CLOEXEC;
cloexec = false;
}
#endif
int fd = ::open(tmp.c_str(), flags, mode);
- if (cloexec && fd >= 0 && ! set_cloexec(fd))
- {
+ if (cloexec && fd >= 0 && !set_cloexec(fd)) {
close(fd);
fd = -1;
}
return fd;
-
}
-int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode)
-{
+int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode) {
return wopen_internal(pathname, flags, mode, true);
}
-DIR *wopendir(const wcstring &name)
-{
+DIR *wopendir(const wcstring &name) {
const cstring tmp = wcs2string(name);
return opendir(tmp.c_str());
}
-int wstat(const wcstring &file_name, struct stat *buf)
-{
+int wstat(const wcstring &file_name, struct stat *buf) {
const cstring tmp = wcs2string(file_name);
return stat(tmp.c_str(), buf);
}
-int lwstat(const wcstring &file_name, struct stat *buf)
-{
+int lwstat(const wcstring &file_name, struct stat *buf) {
const cstring tmp = wcs2string(file_name);
return lstat(tmp.c_str(), buf);
}
-int waccess(const wcstring &file_name, int mode)
-{
+int waccess(const wcstring &file_name, int mode) {
const cstring tmp = wcs2string(file_name);
return access(tmp.c_str(), mode);
}
-int wunlink(const wcstring &file_name)
-{
+int wunlink(const wcstring &file_name) {
const cstring tmp = wcs2string(file_name);
return unlink(tmp.c_str());
}
-void wperror(const wchar_t *s)
-{
+void wperror(const wchar_t *s) {
int e = errno;
- if (s[0] != L'\0')
- {
+ if (s[0] != L'\0') {
fwprintf(stderr, L"%ls: ", s);
}
fwprintf(stderr, L"%s\n", strerror(e));
}
-int make_fd_nonblocking(int fd)
-{
+int make_fd_nonblocking(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
int err = 0;
- if (!(flags & O_NONBLOCK))
- {
+ if (!(flags & O_NONBLOCK)) {
err = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
return err == -1 ? errno : 0;
}
-int make_fd_blocking(int fd)
-{
+int make_fd_blocking(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
int err = 0;
- if (flags & O_NONBLOCK)
- {
+ if (flags & O_NONBLOCK) {
err = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
}
return err == -1 ? errno : 0;
}
-static inline void safe_append(char *buffer, const char *s, size_t buffsize)
-{
+static inline void safe_append(char *buffer, const char *s, size_t buffsize) {
strncat(buffer, s, buffsize - strlen(buffer) - 1);
}
-// In general, strerror is not async-safe, and therefore we cannot use it directly
-// So instead we have to grub through sys_nerr and sys_errlist directly
-// On GNU toolchain, this will produce a deprecation warning from the linker (!!),
-// which appears impossible to suppress!
-const char *safe_strerror(int err)
-{
+// In general, strerror is not async-safe, and therefore we cannot use it directly. So instead we
+// have to grub through sys_nerr and sys_errlist directly On GNU toolchain, this will produce a
+// deprecation warning from the linker (!!), which appears impossible to suppress!
+const char *safe_strerror(int err) {
#if defined(__UCLIBC__)
- // uClibc does not have sys_errlist, however, its strerror is believed to be async-safe
- // See #808
+ // uClibc does not have sys_errlist, however, its strerror is believed to be async-safe.
+ // See issue #808.
return strerror(err);
#elif defined(HAVE__SYS__ERRS) || defined(HAVE_SYS_ERRLIST)
#ifdef HAVE_SYS_ERRLIST
- if (err >= 0 && err < sys_nerr && sys_errlist[err] != NULL)
- {
+ if (err >= 0 && err < sys_nerr && sys_errlist[err] != NULL) {
return sys_errlist[err];
}
#elif defined(HAVE__SYS__ERRS)
@@ -342,15 +289,15 @@ const char *safe_strerror(int err)
extern int _sys_num_err;
if (err >= 0 && err < _sys_num_err) {
- return &_sys_errs[_sys_index[err]];
+ return &_sys_errs[_sys_index[err]];
}
-#endif // either HAVE__SYS__ERRS or HAVE_SYS_ERRLIST
+#endif // either HAVE__SYS__ERRS or HAVE_SYS_ERRLIST
else
-#endif // defined(HAVE__SYS__ERRS) || defined(HAVE_SYS_ERRLIST)
+#endif // defined(HAVE__SYS__ERRS) || defined(HAVE_SYS_ERRLIST)
{
int saved_err = errno;
- /* Use a shared buffer for this case */
+ // Use a shared buffer for this case.
static char buff[384];
char errnum_buff[64];
format_long_safe(errnum_buff, err);
@@ -365,16 +312,14 @@ const char *safe_strerror(int err)
}
}
-void safe_perror(const char *message)
-{
- // Note we cannot use strerror, because on Linux it uses gettext, which is not safe
+void safe_perror(const char *message) {
+ // Note we cannot use strerror, because on Linux it uses gettext, which is not safe.
int err = errno;
char buff[384];
buff[0] = '\0';
- if (message)
- {
+ if (message) {
safe_append(buff, message, sizeof buff);
safe_append(buff, ": ", sizeof buff);
}
@@ -387,23 +332,18 @@ void safe_perror(const char *message)
#ifdef HAVE_REALPATH_NULL
-wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
-{
+wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
cstring narrow_path = wcs2string(pathname);
char *narrow_res = realpath(narrow_path.c_str(), NULL);
- if (!narrow_res)
- return NULL;
+ if (!narrow_res) return NULL;
wchar_t *res;
wcstring wide_res = str2wcstring(narrow_res);
- if (resolved_path)
- {
+ if (resolved_path) {
wcslcpy(resolved_path, wide_res.c_str(), PATH_MAX);
res = resolved_path;
- }
- else
- {
+ } else {
res = wcsdup(wide_res.c_str());
}
@@ -414,24 +354,19 @@ wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
#else
-wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
-{
+wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
cstring tmp = wcs2string(pathname);
char narrow_buff[PATH_MAX];
char *narrow_res = realpath(tmp.c_str(), narrow_buff);
wchar_t *res;
- if (!narrow_res)
- return 0;
+ if (!narrow_res) return 0;
const wcstring wide_res = str2wcstring(narrow_res);
- if (resolved_path)
- {
+ if (resolved_path) {
wcslcpy(resolved_path, wide_res.c_str(), PATH_MAX);
res = resolved_path;
- }
- else
- {
+ } else {
res = wcsdup(wide_res.c_str());
}
return res;
@@ -439,9 +374,7 @@ wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
#endif
-
-wcstring wdirname(const wcstring &path)
-{
+wcstring wdirname(const wcstring &path) {
char *tmp = wcs2str(path.c_str());
char *narrow_res = dirname(tmp);
wcstring result = format_string(L"%s", narrow_res);
@@ -449,8 +382,7 @@ wcstring wdirname(const wcstring &path)
return result;
}
-wcstring wbasename(const wcstring &path)
-{
+wcstring wbasename(const wcstring &path) {
char *tmp = wcs2str(path.c_str());
char *narrow_res = basename(tmp);
wcstring result = format_string(L"%s", narrow_res);
@@ -458,29 +390,24 @@ wcstring wbasename(const wcstring &path)
return result;
}
-/* Really init wgettext */
-static void wgettext_really_init()
-{
+// Really init wgettext.
+static void wgettext_really_init() {
pthread_mutex_init(&wgettext_lock, NULL);
fish_bindtextdomain(PACKAGE_NAME, LOCALEDIR);
fish_textdomain(PACKAGE_NAME);
}
-/**
- For wgettext: Internal init function. Automatically called when a translation is first requested.
-*/
-static void wgettext_init_if_necessary()
-{
+/// For wgettext: Internal init function. Automatically called when a translation is first
+/// requested.
+static void wgettext_init_if_necessary() {
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, wgettext_really_init);
}
-const wchar_t *wgettext(const wchar_t *in)
-{
- if (!in)
- return in;
+const wchar_t *wgettext(const wchar_t *in) {
+ if (!in) return in;
- // preserve errno across this since this is often used in printing error messages
+ // Preserve errno across this since this is often used in printing error messages.
int err = errno;
wgettext_init_if_necessary();
@@ -489,59 +416,51 @@ const wchar_t *wgettext(const wchar_t *in)
scoped_lock lock(wgettext_lock);
wcstring &val = wgettext_map[key];
- if (val.empty())
- {
+ if (val.empty()) {
cstring mbs_in = wcs2string(key);
char *out = fish_gettext(mbs_in.c_str());
val = format_string(L"%s", out);
}
errno = err;
- // The returned string is stored in the map
- // TODO: If we want to shrink the map, this would be a problem
+ // The returned string is stored in the map.
+ // TODO: If we want to shrink the map, this would be a problem.
return val.c_str();
}
-int wmkdir(const wcstring &name, int mode)
-{
+int wmkdir(const wcstring &name, int mode) {
cstring name_narrow = wcs2string(name);
return mkdir(name_narrow.c_str(), mode);
}
-int wrename(const wcstring &old, const wcstring &newv)
-{
+int wrename(const wcstring &old, const wcstring &newv) {
cstring old_narrow = wcs2string(old);
- cstring new_narrow =wcs2string(newv);
+ cstring new_narrow = wcs2string(newv);
return rename(old_narrow.c_str(), new_narrow.c_str());
}
-int fish_wcstoi(const wchar_t *str, wchar_t ** endptr, int base)
-{
+int fish_wcstoi(const wchar_t *str, wchar_t **endptr, int base) {
long ret = wcstol(str, endptr, base);
- if (ret > INT_MAX)
- {
+ if (ret > INT_MAX) {
ret = INT_MAX;
errno = ERANGE;
- }
- else if (ret < INT_MIN)
- {
+ } else if (ret < INT_MIN) {
ret = INT_MIN;
errno = ERANGE;
}
return (int)ret;
}
-file_id_t file_id_t::file_id_from_stat(const struct stat *buf)
-{
+file_id_t file_id_t::file_id_from_stat(const struct stat *buf) {
assert(buf != NULL);
-
+
file_id_t result = {};
result.device = buf->st_dev;
result.inode = buf->st_ino;
result.size = buf->st_size;
result.change_seconds = buf->st_ctime;
result.mod_seconds = buf->st_mtime;
-
+
#if STAT_HAVE_NSEC
result.change_nanoseconds = buf->st_ctime_nsec;
result.mod_nanoseconds = buf->st_mtime_nsec;
@@ -555,74 +474,53 @@ file_id_t file_id_t::file_id_from_stat(const struct stat *buf)
result.change_nanoseconds = 0;
result.mod_nanoseconds = 0;
#endif
-
+
return result;
}
-
-file_id_t file_id_for_fd(int fd)
-{
+file_id_t file_id_for_fd(int fd) {
file_id_t result = kInvalidFileID;
struct stat buf = {};
- if (0 == fstat(fd, &buf))
- {
+ if (0 == fstat(fd, &buf)) {
result = file_id_t::file_id_from_stat(&buf);
}
return result;
}
-file_id_t file_id_for_path(const wcstring &path)
-{
+file_id_t file_id_for_path(const wcstring &path) {
file_id_t result = kInvalidFileID;
struct stat buf = {};
- if (0 == wstat(path, &buf))
- {
+ if (0 == wstat(path, &buf)) {
result = file_id_t::file_id_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->compare_file_id(rhs) == 0; }
-bool file_id_t::operator!=(const file_id_t &rhs) const
-{
- return ! (*this == rhs);
-}
+bool file_id_t::operator!=(const file_id_t &rhs) const { return !(*this == rhs); }
-template<typename T>
-int compare(T a, T b)
-{
- if (a < b)
- {
+template <typename T>
+int compare(T a, T b) {
+ if (a < b) {
return -1;
- }
- else if (a > b)
- {
+ } else if (a > b) {
return 1;
}
return 0;
}
-int file_id_t::compare_file_id(const file_id_t &rhs) const
-{
- /* Compare each field, stopping when we get to a non-equal field */
+int file_id_t::compare_file_id(const file_id_t &rhs) const {
+ // Compare each field, stopping when we get to a non-equal field.
int ret = 0;
- if (! ret) ret = compare(device, rhs.device);
- if (! ret) ret = compare(inode, rhs.inode);
- if (! ret) ret = compare(size, rhs.size);
- if (! ret) ret = compare(change_seconds, rhs.change_seconds);
- if (! ret) ret = compare(change_nanoseconds, rhs.change_nanoseconds);
- if (! ret) ret = compare(mod_seconds, rhs.mod_seconds);
- if (! ret) ret = compare(mod_nanoseconds, rhs.mod_nanoseconds);
+ if (!ret) ret = compare(device, rhs.device);
+ if (!ret) ret = compare(inode, rhs.inode);
+ if (!ret) ret = compare(size, rhs.size);
+ if (!ret) ret = compare(change_seconds, rhs.change_seconds);
+ if (!ret) ret = compare(change_nanoseconds, rhs.change_nanoseconds);
+ if (!ret) ret = compare(mod_seconds, rhs.mod_seconds);
+ if (!ret) ret = compare(mod_nanoseconds, rhs.mod_nanoseconds);
return ret;
}
-
-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->compare_file_id(rhs) < 0; }
diff --git a/src/wutil.h b/src/wutil.h
index a4fee900..9fc61096 100644
--- a/src/wutil.h
+++ b/src/wutil.h
@@ -1,141 +1,105 @@
-/** \file wutil.h
-
- Prototypes for wide character equivalents of various standard unix
- functions.
-*/
+// Prototypes for wide character equivalents of various standard unix functions.
#ifndef FISH_WUTIL_H
#define FISH_WUTIL_H
-#include <stdio.h>
#include <dirent.h>
+#include <stdbool.h>
+#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <string>
-#include <stdbool.h>
#include "common.h"
-/**
- Wide character version of fopen(). This sets CLO_EXEC.
-*/
+/// Wide character version of fopen(). This sets CLO_EXEC.
FILE *wfopen(const wcstring &path, const char *mode);
-/** Sets CLO_EXEC on a given fd */
+/// Sets CLO_EXEC on a given fd.
bool set_cloexec(int fd);
-/** Wide character version of open() that also sets the close-on-exec flag (atomically when possible). */
+/// Wide character version of open() that also sets the close-on-exec flag (atomically when
+/// possible).
int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode = 0);
-/** Mark an fd as nonblocking; returns errno or 0 on success */
+/// Mark an fd as nonblocking; returns errno or 0 on success.
int make_fd_nonblocking(int fd);
-/** Mark an fd as blocking; returns errno or 0 on success */
+/// Mark an fd as blocking; returns errno or 0 on success.
int make_fd_blocking(int fd);
-/** Wide character version of opendir(). Note that opendir() is guaranteed to set close-on-exec by POSIX (hooray). */
+/// Wide character version of opendir(). Note that opendir() is guaranteed to set close-on-exec by
+/// POSIX (hooray).
DIR *wopendir(const wcstring &name);
-/**
- Wide character version of stat().
-*/
+/// Wide character version of stat().
int wstat(const wcstring &file_name, struct stat *buf);
-/**
- Wide character version of lstat().
-*/
+/// Wide character version of lstat().
int lwstat(const wcstring &file_name, struct stat *buf);
-/**
- Wide character version of access().
-*/
+/// Wide character version of access().
int waccess(const wcstring &pathname, int mode);
-/**
- Wide character version of unlink().
-*/
+/// Wide character version of unlink().
int wunlink(const wcstring &pathname);
-/**
- Wide character version of perror().
-*/
+/// Wide character version of perror().
void wperror(const wchar_t *s);
-/**
- Async-safe version of perror().
-*/
+/// Async-safe version of perror().
void safe_perror(const char *message);
-/**
- Async-safe version of strerror().
-*/
+/// Async-safe version of strerror().
const char *safe_strerror(int err);
-// Wide character version of getcwd().
+/// Wide character version of getcwd().
const wcstring wgetcwd();
-/**
- Wide character version of chdir()
-*/
+/// Wide character version of chdir().
int wchdir(const wcstring &dir);
-/**
- Wide character version of realpath function. Just like the GNU
- version of realpath, wrealpath will accept 0 as the value for the
- second argument, in which case the result will be allocated using
- malloc, and must be free'd by the user.
-*/
+/// Wide character version of realpath function. Just like the GNU version of realpath, wrealpath
+/// will accept 0 as the value for the second argument, in which case the result will be allocated
+/// using malloc, and must be free'd by the user.
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path);
-/**
- Wide character version of readdir()
-*/
+/// Wide character version of readdir().
bool wreaddir(DIR *dir, std::wstring &out_name);
-bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name, bool *out_is_dir);
-
-/**
- Like wreaddir, but skip items that are known to not be directories.
- If this requires a stat (i.e. the file is a symlink), then return it.
- Note that this does not guarantee that everything returned is a directory,
- it's just an optimization for cases where we would check for directories anyways.
-*/
+bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name,
+ bool *out_is_dir);
+
+/// Like wreaddir, but skip items that are known to not be directories. If this requires a stat
+/// (i.e. the file is a symlink), then return it. Note that this does not guarantee that everything
+/// returned is a directory, it's just an optimization for cases where we would check for
+/// directories anyways.
bool wreaddir_for_dirs(DIR *dir, wcstring *out_name);
-/**
- Wide character version of dirname()
-*/
+/// Wide character version of dirname().
std::wstring wdirname(const std::wstring &path);
-/**
- Wide character version of basename()
-*/
+/// Wide character version of basename().
std::wstring wbasename(const std::wstring &path);
-/**
- Wide character wrapper around the gettext function. For historic
- reasons, unlike the real gettext function, wgettext takes care of
- setting the correct domain, etc. using the textdomain and
- bindtextdomain functions. This should probably be moved out of
- wgettext, so that wgettext will be nothing more than a wrapper
- around gettext, like all other functions in this file.
-*/
+/// Wide character wrapper around the gettext function. For historic reasons, unlike the real
+/// gettext function, wgettext takes care of setting the correct domain, etc. using the textdomain
+/// and bindtextdomain functions. This should probably be moved out of wgettext, so that wgettext
+/// will be nothing more than a wrapper around gettext, like all other functions in this file.
const wchar_t *wgettext(const wchar_t *in);
-/**
- Wide character version of mkdir
-*/
+/// Wide character version of mkdir.
int wmkdir(const wcstring &dir, int mode);
-/**
- Wide character version of rename
-*/
+/// Wide character version of rename.
int wrename(const wcstring &oldName, const wcstring &newName);
-/** Like wcstol(), but fails on a value outside the range of an int */
-int fish_wcstoi(const wchar_t *str, wchar_t ** endptr, int base);
+/// Like wcstol(), but fails on a value outside the range of an int.
+int fish_wcstoi(const wchar_t *str, wchar_t **endptr, int base);
-/** Class for representing a file's inode. We use this to detect and avoid symlink loops, among other things. While an inode / dev pair is sufficient to distinguish co-existing files, Linux seems to aggressively re-use inodes, so it cannot determine if a file has been deleted (ABA problem). Therefore we include richer information. */
-struct file_id_t
-{
+/// Class for representing a file's inode. We use this to detect and avoid symlink loops, among
+/// other things. While an inode / dev pair is sufficient to distinguish co-existing files, Linux
+/// seems to aggressively re-use inodes, so it cannot determine if a file has been deleted (ABA
+/// problem). Therefore we include richer information.
+struct file_id_t {
dev_t device;
ino_t inode;
uint64_t size;
@@ -143,16 +107,16 @@ struct file_id_t
long change_nanoseconds;
time_t mod_seconds;
long mod_nanoseconds;
-
+
bool operator==(const file_id_t &rhs) const;
bool operator!=(const file_id_t &rhs) const;
-
- // Used to permit these as keys in std::map
+
+ // Used to permit these as keys in std::map.
bool operator<(const file_id_t &rhs) const;
-
+
static file_id_t file_id_from_stat(const struct stat *buf);
-
- private:
+
+ private:
int compare_file_id(const file_id_t &rhs) const;
};
@@ -161,5 +125,4 @@ file_id_t file_id_for_path(const wcstring &path);
extern const file_id_t kInvalidFileID;
-
#endif