X-Git-Url: http://git.refcnt.org/?a=blobdiff_plain;f=colorize.c;h=8eccfc91f1a0535bcb73f725b620fa4b03e2058e;hb=bd0f827c8a51859dff207be5822edff97700df04;hp=ab4e786232ec84a0c12ac0d625fe358565a47512;hpb=20334d6175dace7f23ee9f6cffc47790fef86dc7;p=colorize.git diff --git a/colorize.c b/colorize.c index ab4e786..8eccfc9 100644 --- a/colorize.c +++ b/colorize.c @@ -2,7 +2,7 @@ * colorize - Read text from standard input stream or file and print * it colorized through use of ANSI escape sequences * - * Copyright (c) 2011-2013 Steven Schubiger + * Copyright (c) 2011-2014 Steven Schubiger * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,8 @@ * */ -#define _POSIX_C_SOURCE 200809L +#define _BSD_SOURCE +#define _XOPEN_SOURCE 700 #include #include #include @@ -68,6 +69,8 @@ #define SKIP_LINE_ENDINGS(flags) (((flags) & CR) && ((flags) & LF) ? 2 : 1) +#define VALID_FILE_TYPE(mode) (S_ISREG (mode) || S_ISLNK (mode) || S_ISFIFO (mode)) + #define STACK_VAR(ptr) do { \ stack_var (&vars_list, &stacked_vars, stacked_vars, ptr); \ } while (false) @@ -76,14 +79,17 @@ release_var (vars_list, stacked_vars, (void **)&ptr); \ } while (false) -#define MEM_ALLOC_FAIL_DEBUG(file, line) do { \ +#if DEBUG +# define MEM_ALLOC_FAIL_DEBUG(file, line) do { \ fprintf (stderr, "Memory allocation failure in source file %s, line %u\n", file, line); \ exit (2); \ } while (false) -#define MEM_ALLOC_FAIL() do { \ +#else +# define MEM_ALLOC_FAIL() do { \ fprintf (stderr, "%s: memory allocation failure\n", program_name); \ exit (2); \ } while (false) +#endif #define ABORT_TRACE() \ fprintf (stderr, "Aborting in source file %s, line %u\n", __FILE__, __LINE__); \ @@ -96,11 +102,9 @@ #define COLOR_SEP_CHAR '/' -#define VERSION "0.52" - -typedef unsigned short bool; +#define VERSION "0.53" -enum { false, true }; +typedef enum { false, true } bool; struct color_name { char *name; @@ -141,17 +145,23 @@ static const struct color bg_colors[] = { enum fmts { FMT_GENERIC, + FMT_STRING, + FMT_QUOTE, FMT_COLOR, FMT_RANDOM, FMT_ERROR, - FMT_FILE + FMT_FILE, + FMT_TYPE }; static const char *formats[] = { "%s", /* generic */ + "%s '%s'", /* string */ + "%s `%s' %s", /* quote */ "%s color '%s' %s", /* color */ "%s color '%s' %s '%s'", /* random */ "less than %u bytes %s", /* error */ "%s: %s", /* file */ + "%s: %s: %s", /* type */ }; enum { FOREGROUND, BACKGROUND }; @@ -177,6 +187,7 @@ static char *exclude = NULL; static const char *program_name; +static void print_hint (void); static void print_help (void); static void print_version (void); static void cleanup (void); @@ -189,15 +200,19 @@ static void find_color_entry (const struct color_name *, unsigned int, const str static void print_line (bool, const struct color **, const char * const, unsigned int); static void print_clean (const char *); static void print_free_offsets (const char *, char ***, unsigned int); +#if !DEBUG static void *malloc_wrap (size_t); static void *calloc_wrap (size_t, size_t); static void *realloc_wrap (void *, size_t); +#else static void *malloc_wrap_debug (size_t, const char *, unsigned int); static void *calloc_wrap_debug (size_t, size_t, const char *, unsigned int); static void *realloc_wrap_debug (void *, size_t, const char *, unsigned int); +#endif static void free_wrap (void **); static char *strdup_wrap (const char *); static char *str_concat (const char *, const char *); +static char *get_file_type (mode_t); static bool has_color_name (const char *, const char *); static void vfprintf_diag (const char *, ...); static void vfprintf_fail (const char *, ...); @@ -212,6 +227,8 @@ static void release_var (void **, unsigned int, void **); extern char *optarg; extern int optind; +static int opt_type = 0; + int main (int argc, char **argv) { @@ -225,7 +242,7 @@ main (int argc, char **argv) OPT_VERSION }; - int opt, opt_type = 0; + int opt; struct option long_opts[] = { { "clean", no_argument, &opt_type, OPT_CLEAN }, { "clean-all", no_argument, &opt_type, OPT_CLEAN_ALL }, @@ -296,7 +313,7 @@ main (int argc, char **argv) case 'v': SET_OPT_TYPE (OPT_VERSION); case '?': - print_help (); + print_hint (); exit (EXIT_FAILURE); default: /* never reached */ ABORT_TRACE (); @@ -323,8 +340,8 @@ main (int argc, char **argv) { if (arg_cnt == 0 || arg_cnt > 2) { - vfprintf_diag ("%u arguments provided, expected 1-2 arguments or option", arg_cnt); - print_help (); + vfprintf_diag ("%u arguments provided, expected 1-2 arguments or clean option", arg_cnt); + print_hint (); exit (EXIT_FAILURE); } } @@ -340,6 +357,12 @@ main (int argc, char **argv) exit (EXIT_SUCCESS); } +static void +print_hint (void) +{ + fprintf (stderr, "Type `%s --help' for help screen.\n", program_name); +} + static void print_help (void) { @@ -444,7 +467,7 @@ process_args (unsigned int arg_cnt, char **arg_strings, bool *bold, const struct vfprintf_fail (formats[FMT_GENERIC], "hyphen must be preceeded by color string"); } - ret = stat (color_string, &sb); + ret = lstat (color_string, &sb); /* Ensure that we don't fail if there's a file with one or more color names in its path. */ @@ -453,6 +476,7 @@ process_args (unsigned int arg_cnt, char **arg_strings, bool *bold, const struct bool have_file; unsigned int c; const char *color = color_string; + const mode_t mode = sb.st_mode; for (c = 1; c <= 2 && *color; c++) { @@ -484,20 +508,25 @@ process_args (unsigned int arg_cnt, char **arg_strings, bool *bold, const struct if (have_file) { if (file_string) - vfprintf_fail (formats[FMT_GENERIC], "file cannot be used as color string"); + vfprintf_fail (formats[FMT_QUOTE], get_file_type (mode), color_string, "cannot be used as color string"); else - vfprintf_fail (formats[FMT_GENERIC], "file must be preceeded by color string"); + { + if (VALID_FILE_TYPE (mode)) + vfprintf_fail (formats[FMT_QUOTE], get_file_type (mode), color_string, "must be preceeded by color string"); + else + vfprintf_fail (formats[FMT_QUOTE], get_file_type (mode), color_string, "is not a valid file type"); + } } } if ((p = strchr (color_string, COLOR_SEP_CHAR))) { if (p == color_string) - vfprintf_fail (formats[FMT_GENERIC], "foreground color missing"); + vfprintf_fail (formats[FMT_STRING], "foreground color missing in string", color_string); else if (p == color_string + strlen (color_string) - 1) - vfprintf_fail (formats[FMT_GENERIC], "background color missing"); + vfprintf_fail (formats[FMT_STRING], "background color missing in string", color_string); else if (strchr (++p, COLOR_SEP_CHAR)) - vfprintf_fail (formats[FMT_GENERIC], "one color pair allowed only"); + vfprintf_fail (formats[FMT_STRING], "one color pair allowed only for string", color_string); } str = xstrdup (color_string); @@ -599,13 +628,13 @@ process_file_arg (const char *file_string, const char **file, FILE **stream) int errno, ret; errno = 0; - ret = stat (file, &sb); + ret = lstat (file, &sb); if (ret == -1) vfprintf_fail (formats[FMT_FILE], file, strerror (errno)); - if (!(S_ISREG (sb.st_mode) || S_ISLNK (sb.st_mode) || S_ISFIFO (sb.st_mode))) - vfprintf_fail (formats[FMT_FILE], file, "unrecognized file type"); + if (!VALID_FILE_TYPE (sb.st_mode)) + vfprintf_fail (formats[FMT_TYPE], file, "unrecognized type", get_file_type (sb.st_mode)); errno = 0; @@ -918,6 +947,7 @@ print_free_offsets (const char *line, char ***offsets, unsigned int count) free_null (offsets); } +#if !DEBUG static void * malloc_wrap (size_t size) { @@ -944,7 +974,7 @@ realloc_wrap (void *ptr, size_t size) MEM_ALLOC_FAIL (); return p; } - +#else static void * malloc_wrap_debug (size_t size, const char *file, unsigned int line) { @@ -971,6 +1001,7 @@ realloc_wrap_debug (void *ptr, size_t size, const char *file, unsigned int line) MEM_ALLOC_FAIL_DEBUG (file, line); return p; } +#endif static void free_wrap (void **ptr) @@ -1004,6 +1035,27 @@ str_concat (const char *str1, const char *str2) return str; } +static char * +get_file_type (mode_t mode) +{ + if (S_ISREG (mode)) + return "file"; + else if (S_ISDIR (mode)) + return "directory"; + else if (S_ISCHR (mode)) + return "character device"; + else if (S_ISBLK (mode)) + return "block device"; + else if (S_ISFIFO (mode)) + return "named pipe"; + else if (S_ISLNK (mode)) + return "symbolic link"; + else if (S_ISSOCK (mode)) + return "socket"; + else + return "file"; +} + static bool has_color_name (const char *str, const char *name) {