add log_set_cyclic_category_colors()

This is an easy way to ensure that categories generally have differing colors.

For a long time I've wanted to make sure each osmo-* program logs categories in
different colors, but I never really end up doing it: I don't really enjoy
setting logging category colors manually. Maybe we will use this instead?

The function sets library categories and user categories independently, because
if we did both in the same sequence, a new libosmocore category would change
the colors of all user defined logging, or the other way around.

Change-Id: I66592f1dcb8babfec490a5970a736d42c8f42e4f
diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h
index 755564d..5657d7a 100644
--- a/include/osmocom/core/logging.h
+++ b/include/osmocom/core/logging.h
@@ -175,6 +175,28 @@
 #define OSMO_LOGCOLOR_BRIGHTWHITE "\033[1;37m"
 #define OSMO_LOGCOLOR_END "\033[0;m"
 
+/*! Color constants that can be used in log_info_cat.color.
+ * This list is useful to set distinct logging category colors in a loop.
+ */
+static const char * const osmo_logcolors[] = {
+	OSMO_LOGCOLOR_RED,
+	OSMO_LOGCOLOR_GREEN,
+	OSMO_LOGCOLOR_YELLOW,
+	OSMO_LOGCOLOR_BLUE,
+	OSMO_LOGCOLOR_PURPLE,
+	OSMO_LOGCOLOR_CYAN,
+	OSMO_LOGCOLOR_DARKRED,
+	OSMO_LOGCOLOR_DARKGREEN,
+	OSMO_LOGCOLOR_DARKYELLOW,
+	OSMO_LOGCOLOR_DARKBLUE,
+	OSMO_LOGCOLOR_DARKPURPLE,
+	OSMO_LOGCOLOR_DARKCYAN,
+	OSMO_LOGCOLOR_DARKGREY,
+	OSMO_LOGCOLOR_GREY,
+	OSMO_LOGCOLOR_BRIGHTWHITE,
+	OSMO_LOGCOLOR_NORMAL,
+};
+
 /*! Configuration of single log category / sub-system */
 struct log_category {
 	uint8_t loglevel;	/*!< configured log-level */
@@ -410,6 +432,7 @@
 void log_set_all_filter(struct log_target *target, int);
 
 void log_set_use_color(struct log_target *target, int);
+void log_set_cyclic_category_colors();
 void log_set_print_extended_timestamp(struct log_target *target, int);
 void log_set_print_timestamp(struct log_target *target, int);
 void log_set_print_tid(struct log_target *target, int);
diff --git a/src/core/logging.c b/src/core/logging.c
index 938c65f..a2ef39c 100644
--- a/src/core/logging.c
+++ b/src/core/logging.c
@@ -842,6 +842,26 @@
 	target->use_color = use_color;
 }
 
+/*! Cycle through all logging categories, setting each to a different color.
+ * osmo_init_logging2() or log_init() *must* have been called before this.
+ */
+void log_set_cyclic_category_colors()
+{
+	int i;
+	struct log_info_cat *cat;
+	OSMO_ASSERT(osmo_log_info);
+	/* even though log_info->cat is defined const, we know that osmo_log_info was allocated during log_init(). */
+	cat = (struct log_info_cat*)osmo_log_info->cat;
+
+	for (i = 0; i < osmo_log_info->num_cat_user; i++) {
+		cat[i].color = osmo_logcolors[i % ARRAY_SIZE(osmo_logcolors)];
+	}
+	/* make sure the library defined categories get the same colors in each program */
+	for (i = osmo_log_info->num_cat_user; i < osmo_log_info->num_cat; i++) {
+		cat[i].color = osmo_logcolors[(i - osmo_log_info->num_cat_user) % ARRAY_SIZE(osmo_logcolors)];
+	}
+}
+
 /*! Enable or disable printing of timestamps while logging
  *  \param[in] target Log target to be affected
  *  \param[in] print_timestamp Enable (1) or disable (0) timestamps
diff --git a/tests/logging/logging_vty_test.c b/tests/logging/logging_vty_test.c
index 15f7fc2..4356939 100644
--- a/tests/logging/logging_vty_test.c
+++ b/tests/logging/logging_vty_test.c
@@ -87,31 +87,26 @@
 	[DAA] = {
 		.name = "DAA",
 		.description = "Antropomorphic Armadillos (AA)",
-		.color = "\033[1;31m",
 		.enabled = 1, .loglevel = LOGL_DEBUG,
 	},
 	[DBB] = {
 		.name = "DBB",
 		.description = "Bidirectional Breadspread (BB)",
-		.color = "\033[1;32m",
 		.enabled = 1, .loglevel = LOGL_INFO,
 	},
 	[DCCC] = {
 		.name = "DCCC",
 		.description = "Chaos Communication Congress (CCC)",
-		.color = "\033[1;33m",
 		.enabled = 1, .loglevel = LOGL_NOTICE,
 	},
 	[DDDDD] = {
 		.name = "DDDDD",
 		.description = "Dehydrated Dribbling Duck Dunkers (DDDD)",
-		.color = "\033[1;34m",
 		.enabled = 1, .loglevel = LOGL_ERROR,
 	},
 	[DEEE] = {
 		.name = "DEEE",
 		.description = "Exhaustive Entropy Extraction (EEE)",
-		.color = "\033[1;35m",
 		.enabled = 1, .loglevel = LOGL_FATAL,
 	},
 };
@@ -238,6 +233,7 @@
 
 	osmo_init_logging2(root_ctx, &log_info);
 	log_enable_multithread();
+	log_set_cyclic_category_colors();
 
 	vty_commands_init();