summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2015-11-29 12:00:05 -0500
committerTavian Barnes <tavianator@tavianator.com>2015-11-29 12:00:05 -0500
commitda51ac27f1849ad94753277650435ae482a0423f (patch)
treed194bda63df14c5ec6bd32601d8a7db189f6c39e
parentf81be72020a886b5eca21bc1d8a5b0d62b9954d9 (diff)
downloadbfs-da51ac27f1849ad94753277650435ae482a0423f.tar.xz
Split out parsing code.
-rw-r--r--Makefile2
-rw-r--r--bfs.h118
-rw-r--r--eval.c263
-rw-r--r--main.c27
-rw-r--r--parse.c (renamed from bfs.c)352
5 files changed, 412 insertions, 350 deletions
diff --git a/Makefile b/Makefile
index 5a8d958..d6e7870 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ ALL_LDFLAGS = $(ALL_CFLAGS) $(LDFLAGS)
all: bfs
-bfs: bfs.o bftw.o color.o
+bfs: bftw.o color.o eval.o main.o parse.o
$(CC) $(ALL_LDFLAGS) $^ -o $@
%.o: %.c
diff --git a/bfs.h b/bfs.h
new file mode 100644
index 0000000..aedd2c0
--- /dev/null
+++ b/bfs.h
@@ -0,0 +1,118 @@
+/*********************************************************************
+ * bfs *
+ * Copyright (C) 2015 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This program is free software. It comes without any warranty, to *
+ * the extent permitted by applicable law. You can redistribute it *
+ * and/or modify it under the terms of the Do What The Fuck You Want *
+ * To Public License, Version 2, as published by Sam Hocevar. See *
+ * the COPYING file or http://www.wtfpl.net/ for more details. *
+ *********************************************************************/
+
+#ifndef BFS_H
+#define BFS_H
+
+#include "color.h"
+#include <stdbool.h>
+#include <stddef.h>
+
+/**
+ * The parsed command line.
+ */
+typedef struct cmdline cmdline;
+
+/**
+ * A command line expression.
+ */
+typedef struct expression expression;
+
+/**
+ * Ephemeral state for evaluating an expression.
+ */
+typedef struct eval_state eval_state;
+
+/**
+ * Expression evaluation function.
+ *
+ * @param expr
+ * The current expression.
+ * @param state
+ * The current evaluation state.
+ * @return
+ * The result of the test.
+ */
+typedef bool eval_fn(const expression *expr, eval_state *state);
+
+struct cmdline {
+ /** The array of paths to start from. */
+ const char **roots;
+ /** The number of root paths. */
+ size_t nroots;
+
+ /** Color data. */
+ color_table *colors;
+ /** -color option. */
+ bool color;
+
+ /** -mindepth option. */
+ int mindepth;
+ /** -maxdepth option. */
+ int maxdepth;
+
+ /** bftw() flags. */
+ int flags;
+
+ /** The command line expression. */
+ expression *expr;
+};
+
+struct expression {
+ /** The left hand side of the expression. */
+ expression *lhs;
+ /** The right hand side of the expression. */
+ expression *rhs;
+ /** The function that evaluates this expression. */
+ eval_fn *eval;
+ /** Optional integer data for this expression. */
+ int idata;
+ /** Optional string data for this expression. */
+ const char *sdata;
+};
+
+/**
+ * Parse the command line.
+ */
+cmdline *parse_cmdline(int argc, char *argv[]);
+
+/**
+ * Evaluate the command line.
+ */
+int eval_cmdline(cmdline *cl);
+
+/**
+ * Free the parsed command line.
+ */
+void free_cmdline(cmdline *cl);
+
+// Predicate evaluation functions
+bool eval_access(const expression *expr, eval_state *state);
+bool eval_delete(const expression *expr, eval_state *state);
+bool eval_false(const expression *expr, eval_state *state);
+bool eval_hidden(const expression *expr, eval_state *state);
+bool eval_name(const expression *expr, eval_state *state);
+bool eval_nohidden(const expression *expr, eval_state *state);
+bool eval_path(const expression *expr, eval_state *state);
+bool eval_print(const expression *expr, eval_state *state);
+bool eval_print0(const expression *expr, eval_state *state);
+bool eval_prune(const expression *expr, eval_state *state);
+bool eval_quit(const expression *expr, eval_state *state);
+bool eval_true(const expression *expr, eval_state *state);
+bool eval_type(const expression *expr, eval_state *state);
+
+// Operator evaluation functions
+bool eval_not(const expression *expr, eval_state *state);
+bool eval_and(const expression *expr, eval_state *state);
+bool eval_or(const expression *expr, eval_state *state);
+bool eval_comma(const expression *expr, eval_state *state);
+
+#endif // BFS_H
diff --git a/eval.c b/eval.c
new file mode 100644
index 0000000..56238ea
--- /dev/null
+++ b/eval.c
@@ -0,0 +1,263 @@
+#include "bfs.h"
+#include "bftw.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+struct eval_state {
+ /** Data about the current file. */
+ struct BFTW *ftwbuf;
+ /** The parsed command line. */
+ const cmdline *cl;
+ /** The bftw() callback return value. */
+ bftw_action action;
+ /** A stat() buffer, if necessary. */
+ struct stat statbuf;
+};
+
+/**
+ * Perform a stat() call if necessary.
+ */
+static void fill_statbuf(eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+ if (ftwbuf->statbuf) {
+ return;
+ }
+
+ if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, AT_SYMLINK_NOFOLLOW) == 0) {
+ ftwbuf->statbuf = &state->statbuf;
+ } else {
+ perror("fstatat()");
+ }
+}
+
+/**
+ * -true test.
+ */
+bool eval_true(const expression *expr, eval_state *state) {
+ return true;
+}
+
+/**
+ * -false test.
+ */
+bool eval_false(const expression *expr, eval_state *state) {
+ return false;
+}
+
+/**
+ * -executable, -readable, -writable action.
+ */
+bool eval_access(const expression *expr, eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+ return faccessat(ftwbuf->at_fd, ftwbuf->at_path, expr->idata, AT_SYMLINK_NOFOLLOW) == 0;
+}
+
+/**
+ * -delete action.
+ */
+bool eval_delete(const expression *expr, eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+
+ int flag = 0;
+ if (ftwbuf->typeflag == BFTW_DIR) {
+ flag |= AT_REMOVEDIR;
+ }
+
+ if (unlinkat(ftwbuf->at_fd, ftwbuf->at_path, flag) != 0) {
+ print_error(state->cl->colors, ftwbuf->path, errno);
+ state->action = BFTW_STOP;
+ }
+
+ return true;
+}
+
+/**
+ * -prune action.
+ */
+bool eval_prune(const expression *expr, eval_state *state) {
+ state->action = BFTW_SKIP_SUBTREE;
+ return true;
+}
+
+/**
+ * -hidden test.
+ */
+bool eval_hidden(const expression *expr, eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+ return ftwbuf->nameoff > 0 && ftwbuf->path[ftwbuf->nameoff] == '.';
+}
+
+/**
+ * -nohidden action.
+ */
+bool eval_nohidden(const expression *expr, eval_state *state) {
+ if (eval_hidden(expr, state)) {
+ eval_prune(expr, state);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/**
+ * -name test.
+ */
+bool eval_name(const expression *expr, eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+ return fnmatch(expr->sdata, ftwbuf->path + ftwbuf->nameoff, 0) == 0;
+}
+
+/**
+ * -path test.
+ */
+bool eval_path(const expression *expr, eval_state *state) {
+ struct BFTW *ftwbuf = state->ftwbuf;
+ return fnmatch(expr->sdata, ftwbuf->path, 0) == 0;
+}
+
+/**
+ * -print action.
+ */
+bool eval_print(const expression *expr, eval_state *state) {
+ color_table *colors = state->cl->colors;
+ if (colors) {
+ fill_statbuf(state);
+ }
+ pretty_print(colors, state->ftwbuf);
+ return true;
+}
+
+/**
+ * -print0 action.
+ */
+bool eval_print0(const expression *expr, eval_state *state) {
+ const char *path = state->ftwbuf->path;
+ fwrite(path, 1, strlen(path) + 1, stdout);
+ return true;
+}
+
+/**
+ * -quit action.
+ */
+bool eval_quit(const expression *expr, eval_state *state) {
+ state->action = BFTW_STOP;
+ return true;
+}
+
+/**
+ * -type test.
+ */
+bool eval_type(const expression *expr, eval_state *state) {
+ return state->ftwbuf->typeflag == expr->idata;
+}
+
+/**
+ * Evaluate a negation.
+ */
+bool eval_not(const expression *expr, eval_state *state) {
+ return !expr->rhs->eval(expr, state);
+}
+
+/**
+ * Evaluate a conjunction.
+ */
+bool eval_and(const expression *expr, eval_state *state) {
+ return expr->lhs->eval(expr->lhs, state) && expr->rhs->eval(expr->rhs, state);
+}
+
+/**
+ * Evaluate a disjunction.
+ */
+bool eval_or(const expression *expr, eval_state *state) {
+ return expr->lhs->eval(expr->lhs, state) || expr->rhs->eval(expr->rhs, state);
+}
+
+/**
+ * Evaluate the comma operator.
+ */
+bool eval_comma(const expression *expr, eval_state *state) {
+ expr->lhs->eval(expr->lhs, state);
+ return expr->rhs->eval(expr->rhs, state);
+}
+
+/**
+ * Infer the number of open file descriptors we're allowed to have.
+ */
+static int infer_nopenfd() {
+ int ret = 4096;
+
+ struct rlimit rl;
+ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
+ if (rl.rlim_cur != RLIM_INFINITY) {
+ ret = rl.rlim_cur;
+ }
+ }
+
+ // Account for std{in,out,err}
+ if (ret > 3) {
+ ret -= 3;
+ }
+
+ return ret;
+}
+
+/**
+ * bftw() callback.
+ */
+static bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) {
+ const cmdline *cl = ptr;
+
+ if (ftwbuf->typeflag == BFTW_ERROR) {
+ print_error(cl->colors, ftwbuf->path, ftwbuf->error);
+ return BFTW_SKIP_SUBTREE;
+ }
+
+ eval_state state = {
+ .ftwbuf = ftwbuf,
+ .cl = cl,
+ .action = BFTW_CONTINUE,
+ };
+
+ if (ftwbuf->depth >= cl->maxdepth) {
+ state.action = BFTW_SKIP_SUBTREE;
+ }
+
+ // In -depth mode, only handle directories on the BFTW_POST visit
+ bftw_visit expected_visit = BFTW_PRE;
+ if ((cl->flags & BFTW_DEPTH)
+ && ftwbuf->typeflag == BFTW_DIR
+ && ftwbuf->depth < cl->maxdepth) {
+ expected_visit = BFTW_POST;
+ }
+
+ if (ftwbuf->visit == expected_visit
+ && ftwbuf->depth >= cl->mindepth
+ && ftwbuf->depth <= cl->maxdepth) {
+ cl->expr->eval(cl->expr, &state);
+ }
+
+ return state.action;
+}
+
+/**
+ * Evaluate the command line.
+ */
+int eval_cmdline(cmdline *cl) {
+ int ret = 0;
+ int nopenfd = infer_nopenfd();
+
+ for (size_t i = 0; i < cl->nroots; ++i) {
+ if (bftw(cl->roots[i], cmdline_callback, nopenfd, cl->flags, cl) != 0) {
+ ret = -1;
+ perror("bftw()");
+ }
+ }
+
+ return ret;
+}
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..b74219f
--- /dev/null
+++ b/main.c
@@ -0,0 +1,27 @@
+/*********************************************************************
+ * bfs *
+ * Copyright (C) 2015 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This program is free software. It comes without any warranty, to *
+ * the extent permitted by applicable law. You can redistribute it *
+ * and/or modify it under the terms of the Do What The Fuck You Want *
+ * To Public License, Version 2, as published by Sam Hocevar. See *
+ * the COPYING file or http://www.wtfpl.net/ for more details. *
+ *********************************************************************/
+
+#include "bfs.h"
+#include <stdlib.h>
+
+int main(int argc, char *argv[]) {
+ int ret = EXIT_FAILURE;
+
+ cmdline *cl = parse_cmdline(argc, argv);
+ if (cl) {
+ if (eval_cmdline(cl) == 0) {
+ ret = EXIT_SUCCESS;
+ }
+ }
+
+ free_cmdline(cl);
+ return ret;
+}
diff --git a/bfs.c b/parse.c
index d9d1f7a..348ddd8 100644
--- a/bfs.c
+++ b/parse.c
@@ -1,94 +1,11 @@
-/*********************************************************************
- * bfs *
- * Copyright (C) 2015 Tavian Barnes <tavianator@tavianator.com> *
- * *
- * This program is free software. It comes without any warranty, to *
- * the extent permitted by applicable law. You can redistribute it *
- * and/or modify it under the terms of the Do What The Fuck You Want *
- * To Public License, Version 2, as published by Sam Hocevar. See *
- * the COPYING file or http://www.wtfpl.net/ for more details. *
- *********************************************************************/
-
-#include "bftw.h"
-#include "color.h"
-#include <errno.h>
-#include <fcntl.h>
-#include <fnmatch.h>
+#include "bfs.h"
#include <limits.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
#include <unistd.h>
/**
- * A command line expression.
- */
-typedef struct expression expression;
-
-/**
- * The parsed command line.
- */
-typedef struct cmdline cmdline;
-
-/**
- * Ephemeral state for evaluating an expression.
- */
-typedef struct {
- /** Data about the current file. */
- struct BFTW *ftwbuf;
- /** The parsed command line. */
- const cmdline *cl;
- /** The bftw() callback return value. */
- bftw_action action;
- /** A stat() buffer, if necessary. */
- struct stat statbuf;
-} eval_state;
-
-/**
- * Perform a stat() call if necessary.
- */
-static void fill_statbuf(eval_state *state) {
- struct BFTW *ftwbuf = state->ftwbuf;
- if (ftwbuf->statbuf) {
- return;
- }
-
- if (fstatat(ftwbuf->at_fd, ftwbuf->at_path, &state->statbuf, AT_SYMLINK_NOFOLLOW) == 0) {
- ftwbuf->statbuf = &state->statbuf;
- } else {
- perror("fstatat()");
- }
-}
-
-/**
- * Expression evaluation function.
- *
- * @param expr
- * The current expression.
- * @param state
- * The current evaluation state.
- * @return
- * The result of the test.
- */
-typedef bool eval_fn(const expression *expr, eval_state *state);
-
-struct expression {
- /** The left hand side of the expression. */
- expression *lhs;
- /** The right hand side of the expression. */
- expression *rhs;
- /** The function that evaluates this expression. */
- eval_fn *eval;
- /** Optional integer data for this expression. */
- int idata;
- /** Optional string data for this expression. */
- const char *sdata;
-};
-
-/**
* Create a new expression.
*/
static expression *new_expression(eval_fn *eval) {
@@ -107,13 +24,6 @@ static expression *new_expression(eval_fn *eval) {
}
/**
- * -true test.
- */
-static bool eval_true(const expression *expr, eval_state *state) {
- return true;
-}
-
-/**
* Singleton true expression instance.
*/
static expression expr_true = {
@@ -125,13 +35,6 @@ static expression expr_true = {
};
/**
- * -false test.
- */
-static bool eval_false(const expression *expr, eval_state *state) {
- return false;
-}
-
-/**
* Singleton false expression instance.
*/
static expression expr_false = {
@@ -185,33 +88,10 @@ static expression *new_binary_expression(expression *lhs, expression *rhs, eval_
return expr;
}
-struct cmdline {
- /** The array of paths to start from. */
- const char **roots;
- /** The number of root paths. */
- size_t nroots;
-
- /** Color data. */
- color_table *colors;
- /** -color option. */
- bool color;
-
- /** -mindepth option. */
- int mindepth;
- /** -maxdepth option. */
- int maxdepth;
-
- /** bftw() flags. */
- int flags;
-
- /** The command line expression. */
- expression *expr;
-};
-
/**
* Free the parsed command line.
*/
-static void free_cmdline(cmdline *cl) {
+void free_cmdline(cmdline *cl) {
if (cl) {
free_expression(cl->expr);
free_colors(cl->colors);
@@ -284,113 +164,6 @@ static const char *skip_paths(parser_state *state) {
}
/**
- * -executable, -readable, -writable action.
- */
-static bool eval_access(const expression *expr, eval_state *state) {
- struct BFTW *ftwbuf = state->ftwbuf;
- return faccessat(ftwbuf->at_fd, ftwbuf->at_path, expr->idata, AT_SYMLINK_NOFOLLOW) == 0;
-}
-
-/**
- * -delete action.
- */
-static bool eval_delete(const expression *expr, eval_state *state) {
- struct BFTW *ftwbuf = state->ftwbuf;
-
- int flag = 0;
- if (ftwbuf->typeflag == BFTW_DIR) {
- flag |= AT_REMOVEDIR;
- }
-
- if (unlinkat(ftwbuf->at_fd, ftwbuf->at_path, flag) != 0) {
- print_error(state->cl->colors, ftwbuf->path, errno);
- state->action = BFTW_STOP;
- }
-
- return true;
-}
-
-/**
- * -prune action.
- */
-static bool eval_prune(const expression *expr, eval_state *state) {
- state->action = BFTW_SKIP_SUBTREE;
- return true;
-}
-
-/**
- * -hidden test.
- */
-static bool eval_hidden(const expression *expr, eval_state *state) {
- struct BFTW *ftwbuf = state->ftwbuf;
- return ftwbuf->nameoff > 0 && ftwbuf->path[ftwbuf->nameoff] == '.';
-}
-
-/**
- * -nohidden action.
- */
-static bool eval_nohidden(const expression *expr, eval_state *state) {
- if (eval_hidden(expr, state)) {
- eval_prune(expr, state);
- return false;
- } else {
- return true;
- }
-}
-
-/**
- * -name test.
- */
-static bool eval_name(const expression *expr, eval_state *state) {
- struct BFTW *ftwbuf = state->ftwbuf;
- return fnmatch(expr->sdata, ftwbuf->path + ftwbuf->nameoff, 0) == 0;
-}
-
-/**
- * -path test.
- */
-static bool eval_path(const expression *expr, eval_state *state) {
- struct BFTW *ftwbuf = state->ftwbuf;
- return fnmatch(expr->sdata, ftwbuf->path, 0) == 0;
-}
-
-/**
- * -print action.
- */
-static bool eval_print(const expression *expr, eval_state *state) {
- color_table *colors = state->cl->colors;
- if (colors) {
- fill_statbuf(state);
- }
- pretty_print(colors, state->ftwbuf);
- return true;
-}
-
-/**
- * -print0 action.
- */
-static bool eval_print0(const expression *expr, eval_state *state) {
- const char *path = state->ftwbuf->path;
- fwrite(path, 1, strlen(path) + 1, stdout);
- return true;
-}
-
-/**
- * -quit action.
- */
-static bool eval_quit(const expression *expr, eval_state *state) {
- state->action = BFTW_STOP;
- return true;
-}
-
-/**
- * -type test.
- */
-static bool eval_type(const expression *expr, eval_state *state) {
- return state->ftwbuf->typeflag == expr->idata;
-}
-
-/**
* Create a new option expression.
*/
static expression *new_option(parser_state *state, const char *option) {
@@ -620,13 +393,6 @@ static expression *parse_literal(parser_state *state) {
}
/**
- * Evaluate a negation.
- */
-static bool eval_not(const expression *expr, eval_state *state) {
- return !expr->rhs->eval(expr, state);
-}
-
-/**
* Create a "not" expression.
*/
static expression *new_not_expression(expression *rhs) {
@@ -682,13 +448,6 @@ static expression *parse_factor(parser_state *state) {
}
/**
- * Evaluate a conjunction.
- */
-static bool eval_and(const expression *expr, eval_state *state) {
- return expr->lhs->eval(expr->lhs, state) && expr->rhs->eval(expr->rhs, state);
-}
-
-/**
* Create an "and" expression.
*/
static expression *new_and_expression(expression *lhs, expression *rhs) {
@@ -743,13 +502,6 @@ static expression *parse_term(parser_state *state) {
}
/**
- * Evaluate a disjunction.
- */
-static bool eval_or(const expression *expr, eval_state *state) {
- return expr->lhs->eval(expr->lhs, state) || expr->rhs->eval(expr->rhs, state);
-}
-
-/**
* Create an "or" expression.
*/
static expression *new_or_expression(expression *lhs, expression *rhs) {
@@ -799,14 +551,6 @@ static expression *parse_clause(parser_state *state) {
}
/**
- * Evaluate the comma operator.
- */
-static bool eval_comma(const expression *expr, eval_state *state) {
- expr->lhs->eval(expr->lhs, state);
- return expr->rhs->eval(expr->rhs, state);
-}
-
-/**
* Create a "comma" expression.
*/
static expression *new_comma_expression(expression *lhs, expression *rhs) {
@@ -852,7 +596,7 @@ static expression *parse_expression(parser_state *state) {
/**
* Parse the command line.
*/
-static cmdline *parse_cmdline(int argc, char *argv[]) {
+cmdline *parse_cmdline(int argc, char *argv[]) {
cmdline *cl = malloc(sizeof(cmdline));
if (!cl) {
goto fail;
@@ -916,93 +660,3 @@ fail:
free_cmdline(cl);
return NULL;
}
-
-/**
- * Infer the number of open file descriptors we're allowed to have.
- */
-static int infer_nopenfd() {
- int ret = 4096;
-
- struct rlimit rl;
- if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
- if (rl.rlim_cur != RLIM_INFINITY) {
- ret = rl.rlim_cur;
- }
- }
-
- // Account for std{in,out,err}
- if (ret > 3) {
- ret -= 3;
- }
-
- return ret;
-}
-
-/**
- * bftw() callback.
- */
-static bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) {
- const cmdline *cl = ptr;
-
- if (ftwbuf->typeflag == BFTW_ERROR) {
- print_error(cl->colors, ftwbuf->path, ftwbuf->error);
- return BFTW_SKIP_SUBTREE;
- }
-
- eval_state state = {
- .ftwbuf = ftwbuf,
- .cl = cl,
- .action = BFTW_CONTINUE,
- };
-
- if (ftwbuf->depth >= cl->maxdepth) {
- state.action = BFTW_SKIP_SUBTREE;
- }
-
- // In -depth mode, only handle directories on the BFTW_POST visit
- bftw_visit expected_visit = BFTW_PRE;
- if ((cl->flags & BFTW_DEPTH)
- && ftwbuf->typeflag == BFTW_DIR
- && ftwbuf->depth < cl->maxdepth) {
- expected_visit = BFTW_POST;
- }
-
- if (ftwbuf->visit == expected_visit
- && ftwbuf->depth >= cl->mindepth
- && ftwbuf->depth <= cl->maxdepth) {
- cl->expr->eval(cl->expr, &state);
- }
-
- return state.action;
-}
-
-/**
- * Evaluate the command line.
- */
-static int eval_cmdline(cmdline *cl) {
- int ret = 0;
- int nopenfd = infer_nopenfd();
-
- for (size_t i = 0; i < cl->nroots; ++i) {
- if (bftw(cl->roots[i], cmdline_callback, nopenfd, cl->flags, cl) != 0) {
- ret = -1;
- perror("bftw()");
- }
- }
-
- return ret;
-}
-
-int main(int argc, char *argv[]) {
- int ret = EXIT_FAILURE;
-
- cmdline *cl = parse_cmdline(argc, argv);
- if (cl) {
- if (eval_cmdline(cl) == 0) {
- ret = EXIT_SUCCESS;
- }
- }
-
- free_cmdline(cl);
- return ret;
-}