*
*/
-#define _POSIX_SOURCE
+#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#define COLOR_SEP_CHAR '/'
-#define VERSION "0.50"
+#define VERSION "0.52"
typedef unsigned short bool;
static void print_version (void);
static void cleanup (void);
static void free_color_names (struct color_name **);
-static void process_options (unsigned int, char **, bool *, const struct color **, const char **, FILE **);
-static void process_file_option (const char *, const char **, FILE **);
+static void process_args (unsigned int, char **, bool *, const struct color **, const char **, FILE **);
+static void process_file_arg (const char *, const char **, FILE **);
static void read_print_stream (bool, const struct color **, const char *, FILE *);
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 struct color **, bool, const char * const, unsigned int);
+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);
static void *malloc_wrap (size_t);
static void free_wrap (void **);
static char *strdup_wrap (const char *);
static char *str_concat (const char *, const char *);
+static bool has_color_name (const char *, const char *);
static void vfprintf_diag (const char *, ...);
static void vfprintf_fail (const char *, ...);
static void stack_var (void ***, unsigned int *, unsigned int, void *);
{ "exclude-random", required_argument, &opt_type, OPT_EXCLUDE_RANDOM },
{ "help", no_argument, &opt_type, OPT_HELP },
{ "version", no_argument, &opt_type, OPT_VERSION },
- { 0, 0, 0, 0 },
+ { NULL, 0, NULL, 0 },
};
bool bold = false;
NULL, /* background */
};
- const char *file;
+ const char *file = NULL;
program_name = argv[0];
atexit (cleanup);
}
if (clean || clean_all)
- process_file_option (argv[optind], &file, &stream);
+ process_file_arg (argv[optind], &file, &stream);
else
- process_options (arg_cnt, &argv[optind], &bold, colors, &file, &stream);
+ process_args (arg_cnt, &argv[optind], &bold, colors, &file, &stream);
read_print_stream (bold, colors, file, stream);
RELEASE_VAR (exclude);
}
static void
-process_options (unsigned int arg_cnt, char **option_strings, bool *bold, const struct color **colors, const char **file, FILE **stream)
+process_args (unsigned int arg_cnt, char **arg_strings, bool *bold, const struct color **colors, const char **file, FILE **stream)
{
int ret;
unsigned int index;
char *color, *p, *str;
struct stat sb;
- const char *color_string = arg_cnt >= 1 ? option_strings[0] : NULL;
- const char *file_string = arg_cnt == 2 ? option_strings[1] : NULL;
+ const char *color_string = arg_cnt >= 1 ? arg_strings[0] : NULL;
+ const char *file_string = arg_cnt == 2 ? arg_strings[1] : NULL;
assert (color_string);
for (i = 0; i < tables[FOREGROUND].count; i++)
{
const struct color *entry = &tables[FOREGROUND].entries[i];
- char *p;
- if ((p = strstr (color, entry->name)) && p == color)
+ if (has_color_name (color, entry->name))
{
- color = p + strlen (entry->name);
+ color += strlen (entry->name);
matched = true;
break;
}
}
+ if (!matched && has_color_name (color, "random"))
+ {
+ color += strlen ("random");
+ matched = true;
+ }
if (matched && *color == COLOR_SEP_CHAR && *(color + 1))
color++;
else
for (index = 0, color = str; *color; index++, color = p)
{
char *ch, *sep;
+
+ p = NULL;
if ((sep = strchr (color, COLOR_SEP_CHAR)))
{
*sep = '\0';
}
else
p = color + strlen (color);
+ assert (p);
for (ch = color; *ch; ch++)
if (!isalpha (*ch))
find_color_entry (&color_name, FOREGROUND, colors);
}
- process_file_option (file_string, file, stream);
+ process_file_arg (file_string, file, stream);
}
static void
-process_file_option (const char *file_string, const char **file, FILE **stream)
+process_file_arg (const char *file_string, const char **file, FILE **stream)
{
if (file_string)
{
}
assert (*stream);
+ assert (*file);
}
#define MERGE_PRINT_LINE(part_line, line, flags, check_eof) do { \
} \
current_line = merged_line ? merged_line : (char *)line; \
if (!check_eof || *current_line != '\0') \
- print_line (colors, bold, current_line, flags); \
+ print_line (bold, colors, current_line, flags); \
free (merged_line); \
} while (false);
else if (*line != '\0')
{
if (!clean && !clean_all) /* efficiency */
- print_line (colors, bold, line, 0);
+ print_line (bold, colors, line, 0);
else if (!part_line)
part_line = xstrdup (line);
else
}
static void
-print_line (const struct color **colors, bool bold, const char *const line, unsigned int flags)
+print_line (bool bold, const struct color **colors, const char *const line, unsigned int flags)
{
/* --clean[-all] */
if (clean || clean_all)
return str;
}
+static bool
+has_color_name (const char *str, const char *name)
+{
+ char *p;
+
+ assert (strlen (str));
+ assert (strlen (name));
+
+ 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;
+}
+
#define DO_VFPRINTF(fmt) \
va_list ap; \
fprintf (stderr, "%s: ", program_name); \