X-Git-Url: http://git.refcnt.org/?a=blobdiff_plain;f=colorize.c;h=63237a5240d4cf7a4e44942b9503a7db9357d5c9;hb=359c07a2780a0c59eeac74ffd9a5d089cda6e41b;hp=cfc9159cac4242436a684c3b865ae0d9004d8cba;hpb=2132b9543b9b82bb5cea8f54fa41feeaed2c7ba0;p=colorize.git diff --git a/colorize.c b/colorize.c index cfc9159..63237a5 100644 --- a/colorize.c +++ b/colorize.c @@ -73,7 +73,7 @@ #define LF 0x01 #define CR 0x02 -#define SKIP_LINE_ENDINGS(flags) (((flags) & CR) && ((flags) & LF) ? 2 : 1) +#define SKIP_LINE_ENDINGS(flags) ((flags) == (CR|LF) ? 2 : 1) #define VALID_FILE_TYPE(mode) (S_ISREG (mode) || S_ISLNK (mode) || S_ISFIFO (mode)) @@ -99,12 +99,12 @@ #define ABORT_TRACE() \ fprintf (stderr, "Aborting in source file %s, line %u\n", __FILE__, __LINE__); \ - abort (); \ + abort (); #define CHECK_COLORS_RANDOM(color1, color2) \ streq (color_names[color1]->name, "random") \ && (streq (color_names[color2]->name, "none") \ - || streq (color_names[color2]->name, "default")) \ + || streq (color_names[color2]->name, "default")) #define ALLOC_COMPLETE_PART_LINE 8 @@ -116,11 +116,15 @@ # define COLOR_SEP_CHAR '/' #endif -#define DEBUG_FILE "debug.txt" +#if DEBUG +# define DEBUG_FILE "debug.txt" +#endif -#define MAX_ATTRIBUTE_CHARS (5 * 2) +#define MAX_ATTRIBUTE_CHARS (6 * 2) -#define VERSION "0.61" +#define PROGRAM_NAME "colorize" + +#define VERSION "0.63" typedef enum { false, true } bool; @@ -164,7 +168,7 @@ struct bytes_size { char unit; }; -enum fmts { +enum { FMT_GENERIC, FMT_STRING, FMT_QUOTE, @@ -188,7 +192,7 @@ static const char *formats[] = { enum { GENERIC, FOREGROUND = 0, BACKGROUND }; static const struct { - struct color const *entries; + const struct color *entries; unsigned int count; const char *desc; } tables[] = { @@ -201,18 +205,20 @@ enum { OPT_CLEAN, OPT_CLEAN_ALL, OPT_EXCLUDE_RANDOM, + OPT_OMIT_COLOR_EMPTY, OPT_HELP, OPT_VERSION }; static int opt_type; static const struct option long_opts[] = { - { "attr", required_argument, &opt_type, OPT_ATTR }, - { "clean", no_argument, &opt_type, OPT_CLEAN }, - { "clean-all", no_argument, &opt_type, OPT_CLEAN_ALL }, - { "exclude-random", required_argument, &opt_type, OPT_EXCLUDE_RANDOM }, - { "help", no_argument, &opt_type, OPT_HELP }, - { "version", no_argument, &opt_type, OPT_VERSION }, - { NULL, 0, NULL, 0 }, + { "attr", required_argument, &opt_type, OPT_ATTR }, + { "clean", no_argument, &opt_type, OPT_CLEAN }, + { "clean-all", no_argument, &opt_type, OPT_CLEAN_ALL }, + { "exclude-random", required_argument, &opt_type, OPT_EXCLUDE_RANDOM }, + { "omit-color-empty", no_argument, &opt_type, OPT_OMIT_COLOR_EMPTY }, + { "help", no_argument, &opt_type, OPT_HELP }, + { "version", no_argument, &opt_type, OPT_VERSION }, + { NULL, 0, NULL, 0 }, }; enum attr_type { @@ -238,6 +244,7 @@ static void **vars_list; static bool clean; static bool clean_all; +static bool omit_color_empty; static char attr[MAX_ATTRIBUTE_CHARS + 1]; static char *exclude; @@ -263,7 +270,7 @@ static bool get_next_char (char *, const char **, FILE *, bool *); static void save_char (char, char **, size_t *, size_t *); static void find_color_entries (struct color_name **, const struct color **); static void find_color_entry (const struct color_name *, unsigned int, const struct color **); -static void print_line (const char *, const struct color **, const char * const, unsigned int); +static void print_line (const char *, const struct color **, const char * const, unsigned int, bool); static void print_clean (const char *); static bool is_esc (const char *); static const char *get_end_of_esc (const char *); @@ -363,11 +370,11 @@ main (int argc, char **argv) #define PRINT_HELP_EXIT() \ print_help (); \ - exit (EXIT_SUCCESS); \ + exit (EXIT_SUCCESS); #define PRINT_VERSION_EXIT() \ print_version (); \ - exit (EXIT_SUCCESS); \ + exit (EXIT_SUCCESS); extern char *optarg; @@ -409,6 +416,9 @@ process_opts (int argc, char **argv) vfprintf_fail (formats[FMT_GENERIC], "--exclude-random switch must be provided a plain color"); break; } + case OPT_OMIT_COLOR_EMPTY: + omit_color_empty = true; + break; case OPT_HELP: PRINT_HELP_EXIT (); case OPT_VERSION: @@ -474,6 +484,7 @@ process_opt_attr (const char *p) strncpy (attr_invalid, s, p - s); attr_invalid[p - s] = '\0'; vfprintf_fail ("--attr switch attribute '%s' is not valid", attr_invalid); + RELEASE_VAR (attr_invalid); /* never reached */ } } if (*p) @@ -503,13 +514,16 @@ print_hint (void) static void print_help (void) { - struct short_opt { + struct opt_data { const char *name; const char *short_opt; + const char *arg; }; - const struct short_opt short_opts[] = { - { "help", "h" }, - { "version", "V" }, + const struct opt_data opts_data[] = { + { "attr", NULL, "=ATTR1,ATTR2,..." }, + { "exclude-random", NULL, "=COLOR" }, + { "help", "h", NULL }, + { "version", "V", NULL }, }; const struct option *opt = long_opts; unsigned int i; @@ -535,16 +549,21 @@ print_help (void) printf ("\n\tOptions\n"); for (; opt->name; opt++) { - const char *short_opt = NULL; + const struct opt_data *opt_data = NULL; unsigned int i; - for (i = 0; i < sizeof (short_opts) / sizeof (struct short_opt); i++) - if (streq (opt->name, short_opts[i].name)) + for (i = 0; i < sizeof (opts_data) / sizeof (struct opt_data); i++) + if (streq (opt->name, opts_data[i].name)) { - short_opt = short_opts[i].short_opt; + opt_data = &opts_data[i]; break; } - if (short_opt) - printf ("\t\t-%s, --%s\n", short_opt, opt->name); + if (opt_data) + { + if (opt_data->short_opt) + printf ("\t\t-%s, --%s\n", opt_data->short_opt, opt->name); + else + printf ("\t\t --%s%s\n", opt->name, opt_data->arg); + } else printf ("\t\t --%s\n", opt->name); } @@ -586,7 +605,7 @@ print_version (void) #endif version_prefix = version ? "" : "v"; version_string = version ? version : VERSION; - printf ("colorize %s%s (compiled at %s, %s)\n", version_prefix, version_string, __DATE__, __TIME__); + printf ("%s %s%s (compiled at %s, %s)\n", PROGRAM_NAME, version_prefix, version_string, __DATE__, __TIME__); printf ("Compiler flags: %s\n", c_flags); printf ("Linker flags: %s\n", ld_flags); @@ -701,6 +720,7 @@ process_args (unsigned int arg_cnt, char **arg_strings, char *attr, const struct color_name.name = color_name.orig = "default"; find_color_entry (&color_name, FOREGROUND, colors); + assert (colors[FOREGROUND]->code != NULL); } process_file_arg (file_string, file, stream); @@ -874,6 +894,7 @@ read_print_stream (const char *attr, const struct color **colors, const char *fi line = buf; while ((eol = strpbrk (line, "\n\r"))) { + const bool has_text = (eol > line); const char *p; flags &= ~(CR|LF); if (*eol == '\r') @@ -884,17 +905,18 @@ read_print_stream (const char *attr, const struct color **colors, const char *fi } else if (*eol == '\n') flags |= LF; - else + else /* never reached */ vfprintf_fail (formats[FMT_FILE], file, "unrecognized line ending"); p = eol + SKIP_LINE_ENDINGS (flags); *eol = '\0'; - print_line (attr, colors, line, flags); + print_line (attr, colors, line, flags, + omit_color_empty ? has_text : true); line = p; } if (feof (stream)) { if (*line != '\0') - print_line (attr, colors, line, 0); + print_line (attr, colors, line, 0, true); } else if (*line != '\0') { @@ -902,7 +924,7 @@ read_print_stream (const char *attr, const struct color **colors, const char *fi if ((clean || clean_all) && (p = strrchr (line, '\033'))) merge_print_line (line, p, stream); else - print_line (attr, colors, line, 0); + print_line (attr, colors, line, 0, true); } } } @@ -1109,12 +1131,13 @@ find_color_entry (const struct color_name *color_name, unsigned int index, const } static void -print_line (const char *attr, const struct color **colors, const char *const line, unsigned int flags) +print_line (const char *attr, const struct color **colors, const char *const line, unsigned int flags, bool emit_colors) { /* --clean[-all] */ if (clean || clean_all) print_clean (line); - else + /* skip for --omit-color-empty? */ + else if (emit_colors) { /* Foreground color code is guaranteed to be set when background color code is present. */ if (colors[BACKGROUND] && colors[BACKGROUND]->code) @@ -1436,16 +1459,16 @@ has_color_name (const char *str, const char *name) { char *p; - assert (strlen (str)); - assert (strlen (name)); + assert (strlen (str) > 0); + assert (strlen (name) > 0); if (!(*str == *name || *str == toupper (*name))) return false; else if (*(name + 1) != '\0' && !((p = strstr (str + 1, name + 1)) && p == str + 1)) return false; - - return true; + else + return true; } static FILE * @@ -1467,7 +1490,7 @@ open_file (const char *file, const char *mode) va_start (ap, fmt); \ vfprintf (stderr, fmt, ap); \ va_end (ap); \ - fprintf (stderr, "\n"); \ + fprintf (stderr, "\n"); static void vfprintf_diag (const char *fmt, ...)