From c85f569daf3e0e99c9e8941d0234711afdb58cd7 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 16 Mar 2017 23:01:00 -0400 Subject: Give struct expr a CFILE* instead of just a FILE* This unifies the behaviour of -print and -fprint /dev/stdout. --- bfs.h | 3 +-- color.c | 52 +++++++++++++++++++++++++++++++++++++++++++--------- color.h | 14 ++++++++++++++ eval.c | 50 ++++++++++++++------------------------------------ parse.c | 29 ++++++++++++++++++----------- 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 #include /** @@ -45,8 +46,21 @@ 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. * 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 @@ -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); } @@ -835,22 +829,6 @@ done: return true; } -/** - * -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. */ 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) { -- cgit v1.2.3