summaryrefslogtreecommitdiffstats
path: root/parse.c
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 /parse.c
parentea92e8e4b24ea749e73bc6e9bc17371b07c723a3 (diff)
downloadbfs-cad5dc5cc50a43203971939fd2806bfbf9a5dac9.tar.xz
Allow flags like -L before ',' or ')' as pathnames.
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c51
1 files changed, 34 insertions, 17 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;