summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-06-09 18:37:58 -0400
committerTavian Barnes <tavianator@tavianator.com>2016-06-09 18:37:58 -0400
commitcad5dc5cc50a43203971939fd2806bfbf9a5dac9 (patch)
treee42db8dbef9c6896945473668534c709f7165b5f
parentea92e8e4b24ea749e73bc6e9bc17371b07c723a3 (diff)
downloadbfs-cad5dc5cc50a43203971939fd2806bfbf9a5dac9.tar.xz
Allow flags like -L before ',' or ')' as pathnames.
-rw-r--r--parse.c51
-rwxr-xr-xtests.sh17
2 files changed, 50 insertions, 18 deletions
diff --git a/parse.c b/parse.c
index 4101c36..e9e1b52 100644
--- a/parse.c
+++ b/parse.c
@@ -193,8 +193,8 @@ struct parser_state {
bool implicit_print;
/** Whether warnings are enabled (see -warn, -nowarn). */
bool warn;
- /** Whether any non-path arguments have been encountered. */
- bool non_path_seen;
+ /** Whether the expression has started. */
+ bool expr_started;
/** Whether any non-option arguments have been encountered. */
bool non_option_seen;
/** Whether an information option like -help or -version was passed. */
@@ -208,6 +208,8 @@ struct parser_state {
* Possible token types.
*/
enum token_type {
+ /** A flag. */
+ T_FLAG,
/** A root path. */
T_PATH,
/** An option. */
@@ -281,8 +283,8 @@ static struct expr *parse_expr(struct parser_state *state);
* Advance by a single token.
*/
static char **parser_advance(struct parser_state *state, enum token_type type, size_t argc) {
- if (type != T_PATH) {
- state->non_path_seen = true;
+ if (type != T_FLAG && type != T_PATH) {
+ state->expr_started = true;
if (type != T_OPTION) {
state->non_option_seen = true;
@@ -309,7 +311,7 @@ static const char *skip_paths(struct parser_state *state) {
return arg;
}
- if (state->non_path_seen) {
+ if (state->expr_started) {
// By POSIX, these can be paths. We only treat them as
// such at the beginning of the command line
if (strcmp(arg, ")") == 0 || strcmp(arg, ",") == 0) {
@@ -409,6 +411,28 @@ static const char *parse_icmp(const struct parser_state *state, const char *str,
}
/**
+ * Parse a single flag.
+ */
+static struct expr *parse_flag(struct parser_state *state, size_t argc) {
+ parser_advance(state, T_FLAG, argc);
+ return &expr_true;
+}
+
+/**
+ * Parse a flag that doesn't take a value.
+ */
+static struct expr *parse_nullary_flag(struct parser_state *state) {
+ return parse_flag(state, 1);
+}
+
+/**
+ * Parse a flag that takes a single value.
+ */
+static struct expr *parse_unary_flag(struct parser_state *state) {
+ return parse_flag(state, 2);
+}
+
+/**
* Parse a single option.
*/
static struct expr *parse_option(struct parser_state *state, size_t argc) {
@@ -455,13 +479,6 @@ static struct expr *parse_nullary_positional_option(struct parser_state *state)
}
/**
- * Parse a positional option that takes a value.
- */
-static struct expr *parse_unary_positional_option(struct parser_state *state) {
- return parse_positional_option(state, 2);
-}
-
-/**
* Parse a single test.
*/
static struct expr *parse_test(struct parser_state *state, eval_fn *eval, size_t argc) {
@@ -585,7 +602,7 @@ static struct expr *parse_debug(struct parser_state *state) {
"warning: Unrecognized debug flag '%s'.\n\n", flag);
}
- return parse_unary_positional_option(state);
+ return parse_unary_flag(state);
}
/**
@@ -596,7 +613,7 @@ static struct expr *parse_optlevel(struct parser_state *state) {
return NULL;
}
- return parse_nullary_positional_option(state);
+ return parse_nullary_flag(state);
}
/**
@@ -1181,7 +1198,7 @@ static struct expr *parse_literal(struct parser_state *state) {
case 'P':
if (strcmp(arg, "-P") == 0) {
cmdline->flags &= ~(BFTW_FOLLOW | BFTW_DETECT_CYCLES);
- return parse_nullary_positional_option(state);
+ return parse_nullary_flag(state);
}
break;
@@ -1189,14 +1206,14 @@ static struct expr *parse_literal(struct parser_state *state) {
if (strcmp(arg, "-H") == 0) {
cmdline->flags &= ~(BFTW_FOLLOW_NONROOT | BFTW_DETECT_CYCLES);
cmdline->flags |= BFTW_FOLLOW_ROOT;
- return parse_nullary_positional_option(state);
+ return parse_nullary_flag(state);
}
break;
case 'L':
if (strcmp(arg, "-L") == 0) {
cmdline->flags |= BFTW_FOLLOW | BFTW_DETECT_CYCLES;
- return parse_nullary_positional_option(state);
+ return parse_nullary_flag(state);
}
break;
diff --git a/tests.sh b/tests.sh
index ead81f6..5fd4a9b 100755
--- a/tests.sh
+++ b/tests.sh
@@ -344,6 +344,21 @@ function test_0061() {
}
function test_0062() {
+ cd "$weirdnames"
+ find_diff -L '-' '(-' '!-' ',' ')' './(' './!' \( \! -print , -print \)
+}
+
+function test_0063() {
+ cd "$weirdnames"
+ find_diff -L ',' -true
+}
+
+function test_0064() {
+ cd "$weirdnames"
+ find_diff -follow ',' -true
+}
+
+function test_0065() {
find "$basic" -fprint "$out/out.find"
"$BFS" "$basic" -fprint "$out/out.bfs"
@@ -352,7 +367,7 @@ function test_0062() {
diff -u "$out/out.find" "$out/out.bfs"
}
-for i in {1..62}; do
+for i in {1..65}; do
test="test_$(printf '%04d' $i)"
("$test" "$dir")
status=$?