summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2017-03-16 23:01:00 -0400
committerTavian Barnes <tavianator@tavianator.com>2017-03-16 23:02:33 -0400
commitc85f569daf3e0e99c9e8941d0234711afdb58cd7 (patch)
tree347db11ddb49f1f256d7d0f3f24dc15059318e8c
parenta7c51baacf0867b1089f683b05811744f01a70af (diff)
downloadbfs-c85f569daf3e0e99c9e8941d0234711afdb58cd7.tar.xz
Give struct expr a CFILE* instead of just a FILE*
This unifies the behaviour of -print and -fprint /dev/stdout.
-rw-r--r--bfs.h3
-rw-r--r--color.c52
-rw-r--r--color.h14
-rw-r--r--eval.c50
-rw-r--r--parse.c29
5 files changed, 90 insertions, 58 deletions
diff --git a/bfs.h b/bfs.h
index 61ee2ce..e3f4263 100644
--- a/bfs.h
+++ b/bfs.h
@@ -245,7 +245,7 @@ struct expr {
ino_t ino;
/** File to output to. */
- FILE *file;
+ CFILE *cfile;
/** Optional -exec flags. */
enum exec_flags exec_flags;
@@ -322,7 +322,6 @@ bool eval_fls(const struct expr *expr, struct eval_state *state);
bool eval_fprint(const struct expr *expr, struct eval_state *state);
bool eval_fprint0(const struct expr *expr, struct eval_state *state);
bool eval_fprintf(const struct expr *expr, struct eval_state *state);
-bool eval_print(const struct expr *expr, struct eval_state *state);
bool eval_prune(const struct expr *expr, struct eval_state *state);
bool eval_quit(const struct expr *expr, struct eval_state *state);
diff --git a/color.c b/color.c
index b8acc32..18a975f 100644
--- a/color.c
+++ b/color.c
@@ -213,22 +213,56 @@ void free_colors(struct colors *colors) {
}
}
+CFILE *cfopen(const char *path, const struct colors *colors) {
+ CFILE *cfile = malloc(sizeof(*cfile));
+ if (!cfile) {
+ return NULL;
+ }
+
+ cfile->close = false;
+ cfile->file = fopen(path, "wb");
+ if (!cfile->file) {
+ cfclose(cfile);
+ return NULL;
+ }
+ cfile->close = true;
+
+ if (isatty(fileno(cfile->file))) {
+ cfile->colors = colors;
+ } else {
+ cfile->colors = NULL;
+ }
+
+ return cfile;
+}
+
CFILE *cfdup(FILE *file, const struct colors *colors) {
CFILE *cfile = malloc(sizeof(*cfile));
- if (cfile) {
- cfile->file = file;
- if (isatty(fileno(file))) {
- cfile->colors = colors;
- } else {
- cfile->colors = NULL;
- }
+ if (!cfile) {
+ return NULL;
+ }
+
+ cfile->close = false;
+ cfile->file = file;
+
+ if (isatty(fileno(file))) {
+ cfile->colors = colors;
+ } else {
+ cfile->colors = NULL;
}
+
return cfile;
}
int cfclose(CFILE *cfile) {
- free(cfile);
- return 0;
+ int ret = 0;
+ if (cfile) {
+ if (cfile->close) {
+ ret = fclose(cfile->file);
+ }
+ free(cfile);
+ }
+ return ret;
}
static const char *file_color(const struct colors *colors, const char *filename, const struct BFTW *ftwbuf) {
diff --git a/color.h b/color.h
index c3b3e41..6ba6fb0 100644
--- a/color.h
+++ b/color.h
@@ -13,6 +13,7 @@
#define BFS_COLOR_H
#include "bftw.h"
+#include <stdbool.h>
#include <stdio.h>
/**
@@ -45,9 +46,22 @@ typedef struct CFILE {
FILE *file;
/** The color table to use, if any. */
const struct colors *colors;
+ /** Whether to close the underlying stream. */
+ bool close;
} CFILE;
/**
+ * Open a file for colored output.
+ *
+ * @param path
+ * The path to the file to open.
+ * @param colors
+ * The color table to use if file is a TTY.
+ * @return A colored file stream.
+ */
+CFILE *cfopen(const char *path, const struct colors *colors);
+
+/**
* Make a colored copy of an open file.
*
* @param file
diff --git a/eval.c b/eval.c
index 3cf8965..1a8bc02 100644
--- a/eval.c
+++ b/eval.c
@@ -11,6 +11,7 @@
#include "bfs.h"
#include "bftw.h"
+#include "color.h"
#include "dstring.h"
#include "util.h"
#include <assert.h>
@@ -687,7 +688,8 @@ bool eval_perm(const struct expr *expr, struct eval_state *state) {
* -f?ls action.
*/
bool eval_fls(const struct expr *expr, struct eval_state *state) {
- FILE *file = expr->file;
+ CFILE *cfile = expr->cfile;
+ FILE *file = cfile->file;
const struct BFTW *ftwbuf = state->ftwbuf;
const struct stat *statbuf = fill_statbuf(state);
if (!statbuf) {
@@ -753,14 +755,8 @@ bool eval_fls(const struct expr *expr, struct eval_state *state) {
goto error;
}
- if (file == stdout) {
- if (cfprintf(state->cmdline->cout, " %P", ftwbuf) < 0) {
- goto error;
- }
- } else {
- if (fprintf(file, " %s", ftwbuf->path) < 0) {
- goto error;
- }
+ if (cfprintf(cfile, " %P", ftwbuf) < 0) {
+ goto error;
}
if (ftwbuf->typeflag == BFTW_LNK) {
@@ -788,20 +784,18 @@ error:
}
/**
- * -fprint action.
+ * -f?print action.
*/
bool eval_fprint(const struct expr *expr, struct eval_state *state) {
- const char *path = state->ftwbuf->path;
- if (fputs(path, expr->file) == EOF) {
- goto error;
+ CFILE *cfile = expr->cfile;
+ if (cfile->colors) {
+ fill_statbuf(state);
}
- if (fputc('\n', expr->file) == EOF) {
- goto error;
+
+ if (cfprintf(cfile, "%P\n", state->ftwbuf) < 0) {
+ eval_error(state);
}
- return true;
-error:
- eval_error(state);
return true;
}
@@ -811,7 +805,7 @@ error:
bool eval_fprint0(const struct expr *expr, struct eval_state *state) {
const char *path = state->ftwbuf->path;
size_t length = strlen(path) + 1;
- if (fwrite(path, 1, length, expr->file) != length) {
+ if (fwrite(path, 1, length, expr->cfile->file) != length) {
eval_error(state);
}
return true;
@@ -827,7 +821,7 @@ bool eval_fprintf(const struct expr *expr, struct eval_state *state) {
}
}
- if (bfs_printf(expr->file, expr->printf, state->ftwbuf) != 0) {
+ if (bfs_printf(expr->cfile->file, expr->printf, state->ftwbuf) != 0) {
eval_error(state);
}
@@ -836,22 +830,6 @@ done:
}
/**
- * -print action.
- */
-bool eval_print(const struct expr *expr, struct eval_state *state) {
- CFILE *cout = state->cmdline->cout;
- if (cout->colors) {
- fill_statbuf(state);
- }
-
- if (cfprintf(cout, "%P\n", state->ftwbuf) < 0) {
- eval_error(state);
- }
-
- return true;
-}
-
-/**
* -prune action.
*/
bool eval_prune(const struct expr *expr, struct eval_state *state) {
diff --git a/parse.c b/parse.c
index af1bc1f..5cc286c 100644
--- a/parse.c
+++ b/parse.c
@@ -69,9 +69,9 @@ static struct expr expr_false = {
*/
static void free_expr(struct expr *expr) {
if (expr && expr != &expr_true && expr != &expr_false) {
- if (expr->file && expr->file != stdout && expr->file != stderr) {
- if (fclose(expr->file) != 0) {
- perror("fclose()");
+ if (expr->cfile && expr->cfile->close) {
+ if (cfclose(expr->cfile) != 0) {
+ perror("cfclose()");
}
}
@@ -110,7 +110,7 @@ static struct expr *new_expr(eval_fn *eval, bool pure, size_t argc, char **argv)
expr->elapsed.tv_nsec = 0;
expr->argc = argc;
expr->argv = argv;
- expr->file = NULL;
+ expr->cfile = NULL;
expr->regex = NULL;
expr->printf = NULL;
return expr;
@@ -938,8 +938,8 @@ static struct expr *parse_f(struct parser_state *state, int arg1, int arg2) {
* Open a file for an expression.
*/
static int expr_open(struct parser_state *state, struct expr *expr, const char *path) {
- expr->file = fopen(path, "wb");
- if (!expr->file) {
+ expr->cfile = cfopen(path, state->cmdline->colors);
+ if (!expr->cfile) {
cfprintf(state->cmdline->cerr, "%{er}error: '%s': %s%{rs}\n", path, strerror(errno));
return -1;
}
@@ -1143,7 +1143,7 @@ static struct expr *parse_links(struct parser_state *state, int arg1, int arg2)
static struct expr *parse_ls(struct parser_state *state, int arg1, int arg2) {
struct expr *expr = parse_nullary_action(state, eval_fls);
if (expr) {
- expr->file = stdout;
+ expr->cfile = state->cmdline->cout;
expr->reftime = state->now;
}
return expr;
@@ -1555,7 +1555,13 @@ fail:
* Parse -print.
*/
static struct expr *parse_print(struct parser_state *state, int arg1, int arg2) {
- return parse_nullary_action(state, eval_print);
+ struct expr *expr = parse_nullary_action(state, eval_fprint);
+ if (!expr) {
+ return NULL;
+ }
+
+ expr->cfile = state->cmdline->cout;
+ return expr;
}
/**
@@ -1564,7 +1570,7 @@ static struct expr *parse_print(struct parser_state *state, int arg1, int arg2)
static struct expr *parse_print0(struct parser_state *state, int arg1, int arg2) {
struct expr *expr = parse_nullary_action(state, eval_fprint0);
if (expr) {
- expr->file = stdout;
+ expr->cfile = state->cmdline->cout;
}
return expr;
}
@@ -1578,7 +1584,7 @@ static struct expr *parse_printf(struct parser_state *state, int arg1, int arg2)
return NULL;
}
- expr->file = stdout;
+ expr->cfile = state->cmdline->cout;
expr->printf = parse_bfs_printf(expr->sdata, state->cmdline->cerr);
if (!expr->printf) {
@@ -2495,10 +2501,11 @@ static struct expr *parse_whole_expr(struct parser_state *state) {
}
if (state->implicit_print) {
- struct expr *print = new_expr(eval_print, false, 1, &fake_print_arg);
+ struct expr *print = new_expr(eval_fprint, false, 1, &fake_print_arg);
if (!print) {
goto fail;
}
+ print->cfile = state->cmdline->cout;
expr = new_and_expr(state, expr, print, &fake_and_arg);
if (!expr) {