Move to kernel style SPDX license identifiers
[babeltrace.git] / src / common / common.c
index c8890cd2cab5748690d8951fb4fea9aab3ce795d..048e3d27ce4001ca6a6c443239106b7d6764095c 100644 (file)
@@ -1,25 +1,9 @@
 /*
- * Babeltrace common functions
+ * SPDX-License-Identifier: MIT
  *
  * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
  *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Babeltrace common functions
  */
 
 #define BT_LOG_OUTPUT_LEVEL log_level
@@ -63,6 +47,13 @@ static const char *bt_common_color_code_fg_blue = "";
 static const char *bt_common_color_code_fg_magenta = "";
 static const char *bt_common_color_code_fg_cyan = "";
 static const char *bt_common_color_code_fg_light_gray = "";
+static const char *bt_common_color_code_fg_bright_red = "";
+static const char *bt_common_color_code_fg_bright_green = "";
+static const char *bt_common_color_code_fg_bright_yellow = "";
+static const char *bt_common_color_code_fg_bright_blue = "";
+static const char *bt_common_color_code_fg_bright_magenta = "";
+static const char *bt_common_color_code_fg_bright_cyan = "";
+static const char *bt_common_color_code_fg_bright_light_gray = "";
 static const char *bt_common_color_code_bg_default = "";
 static const char *bt_common_color_code_bg_red = "";
 static const char *bt_common_color_code_bg_green = "";
@@ -72,9 +63,106 @@ static const char *bt_common_color_code_bg_magenta = "";
 static const char *bt_common_color_code_bg_cyan = "";
 static const char *bt_common_color_code_bg_light_gray = "";
 
+/*
+ * A color codes structure always filled with the proper color codes for the
+ * terminal.
+ */
+static struct bt_common_color_codes color_codes;
+
+/*
+ * A color codes structure always filled with empty strings, for when we want no
+ * colors.
+ */
+static struct bt_common_color_codes no_color_codes = {
+       "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "", "", "", "", "", "",
+       "", "", "", "", "",
+};
+
 static
 void __attribute__((constructor)) bt_common_color_ctor(void)
 {
+       const char *term_env_var;
+       const char *bright_means_bold_env_var;
+       bool bright_means_bold = true;
+       const char *code_fg_bright_red;
+       const char *code_fg_bright_green;
+       const char *code_fg_bright_yellow;
+       const char *code_fg_bright_blue;
+       const char *code_fg_bright_magenta;
+       const char *code_fg_bright_cyan;
+       const char *code_fg_bright_light_gray;
+
+       /*
+        * Check whether or not the terminal supports having
+        * bold foreground colors which do _not_ become bright
+        * colors, that is, the lines
+        *
+        *     $ echo -e "\033[31mTHIS\n\033[1mTHAT\033[0m"
+        *
+        * have the _same_ color, but `THAT` uses a bold font.
+        *
+        * This is the case of the kitty terminal emulator.
+        *
+        * It's also possible with GNOME Terminal since 3.27.2
+        * and xfce4-terminal since 0.8.7 (and GNOME VTE since
+        * 0.51.2), but it's user-configurable. Since we don't
+        * have this configuration value here, assume it's not
+        * the case to support old versions of GNOME Terminal.
+        *
+        * Any user can set the
+        * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` environment
+        * variable to `0` to use the bright foreground color
+        * codes instead of making the normal foreground color
+        * codes bold.
+        *
+        * Summary:
+        *
+        * With kitty or when
+        * `BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD` is `0`:
+        *     Output bright colors using dedicated SGR codes
+        *     90 to 97.
+        *
+        * Otherwise:
+        *     Output bright colors with bold + SGR codes 30 to
+        *     37.
+        */
+       term_env_var = getenv("TERM");
+
+       if (term_env_var && strcmp(term_env_var, "xterm-kitty") == 0) {
+               /*
+                * The kitty terminal emulator supports
+                * non-bright bold foreground colors.
+                */
+               bright_means_bold = false;
+       }
+
+       bright_means_bold_env_var =
+               getenv("BABELTRACE_TERM_COLOR_BRIGHT_MEANS_BOLD");
+
+       if (bright_means_bold_env_var) {
+               bright_means_bold =
+                       !(strcmp(bright_means_bold_env_var, "0") == 0);
+       }
+
+       if (bright_means_bold) {
+               code_fg_bright_red = BT_COMMON_COLOR_FG_BOLD_RED;
+               code_fg_bright_green = BT_COMMON_COLOR_FG_BOLD_GREEN;
+               code_fg_bright_yellow = BT_COMMON_COLOR_FG_BOLD_YELLOW;
+               code_fg_bright_blue = BT_COMMON_COLOR_FG_BOLD_BLUE;
+               code_fg_bright_magenta = BT_COMMON_COLOR_FG_BOLD_MAGENTA;
+               code_fg_bright_cyan = BT_COMMON_COLOR_FG_BOLD_CYAN;
+               code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BOLD_LIGHT_GRAY;
+       } else {
+               code_fg_bright_red = BT_COMMON_COLOR_FG_BRIGHT_RED;
+               code_fg_bright_green = BT_COMMON_COLOR_FG_BRIGHT_GREEN;
+               code_fg_bright_yellow = BT_COMMON_COLOR_FG_BRIGHT_YELLOW;
+               code_fg_bright_blue = BT_COMMON_COLOR_FG_BRIGHT_BLUE;
+               code_fg_bright_magenta = BT_COMMON_COLOR_FG_BRIGHT_MAGENTA;
+               code_fg_bright_cyan = BT_COMMON_COLOR_FG_BRIGHT_CYAN;
+               code_fg_bright_light_gray = BT_COMMON_COLOR_FG_BRIGHT_LIGHT_GRAY;
+       }
+
        if (bt_common_colors_supported()) {
                bt_common_color_code_reset = BT_COMMON_COLOR_RESET;
                bt_common_color_code_bold = BT_COMMON_COLOR_BOLD;
@@ -86,6 +174,15 @@ void __attribute__((constructor)) bt_common_color_ctor(void)
                bt_common_color_code_fg_magenta = BT_COMMON_COLOR_FG_MAGENTA;
                bt_common_color_code_fg_cyan = BT_COMMON_COLOR_FG_CYAN;
                bt_common_color_code_fg_light_gray = BT_COMMON_COLOR_FG_LIGHT_GRAY;
+
+               bt_common_color_code_fg_bright_red = code_fg_bright_red;
+               bt_common_color_code_fg_bright_green = code_fg_bright_green;
+               bt_common_color_code_fg_bright_yellow = code_fg_bright_yellow;
+               bt_common_color_code_fg_bright_blue = code_fg_bright_blue;
+               bt_common_color_code_fg_bright_magenta = code_fg_bright_magenta;
+               bt_common_color_code_fg_bright_cyan = code_fg_bright_cyan;
+               bt_common_color_code_fg_bright_light_gray = code_fg_bright_light_gray;
+
                bt_common_color_code_bg_default = BT_COMMON_COLOR_BG_DEFAULT;
                bt_common_color_code_bg_red = BT_COMMON_COLOR_BG_RED;
                bt_common_color_code_bg_green = BT_COMMON_COLOR_BG_GREEN;
@@ -95,6 +192,32 @@ void __attribute__((constructor)) bt_common_color_ctor(void)
                bt_common_color_code_bg_cyan = BT_COMMON_COLOR_BG_CYAN;
                bt_common_color_code_bg_light_gray = BT_COMMON_COLOR_BG_LIGHT_GRAY;
        }
+
+       color_codes.reset = BT_COMMON_COLOR_RESET;
+       color_codes.bold = BT_COMMON_COLOR_BOLD;
+       color_codes.fg_default = BT_COMMON_COLOR_FG_DEFAULT;
+       color_codes.fg_red = BT_COMMON_COLOR_FG_RED;
+       color_codes.fg_green = BT_COMMON_COLOR_FG_GREEN;
+       color_codes.fg_yellow = BT_COMMON_COLOR_FG_YELLOW;
+       color_codes.fg_blue = BT_COMMON_COLOR_FG_BLUE;
+       color_codes.fg_magenta = BT_COMMON_COLOR_FG_MAGENTA;
+       color_codes.fg_cyan = BT_COMMON_COLOR_FG_CYAN;
+       color_codes.fg_light_gray = BT_COMMON_COLOR_FG_LIGHT_GRAY;
+       color_codes.fg_bright_red = code_fg_bright_red;
+       color_codes.fg_bright_green = code_fg_bright_green;
+       color_codes.fg_bright_yellow = code_fg_bright_yellow;
+       color_codes.fg_bright_blue = code_fg_bright_blue;
+       color_codes.fg_bright_magenta = code_fg_bright_magenta;
+       color_codes.fg_bright_cyan = code_fg_bright_cyan;
+       color_codes.fg_bright_light_gray = code_fg_bright_light_gray;
+       color_codes.bg_default = BT_COMMON_COLOR_BG_DEFAULT;
+       color_codes.bg_red = BT_COMMON_COLOR_BG_RED;
+       color_codes.bg_green = BT_COMMON_COLOR_BG_GREEN;
+       color_codes.bg_yellow = BT_COMMON_COLOR_BG_YELLOW;
+       color_codes.bg_blue = BT_COMMON_COLOR_BG_BLUE;
+       color_codes.bg_magenta = BT_COMMON_COLOR_BG_MAGENTA;
+       color_codes.bg_cyan = BT_COMMON_COLOR_BG_CYAN;
+       color_codes.bg_light_gray = BT_COMMON_COLOR_BG_LIGHT_GRAY;
 }
 
 BT_HIDDEN
@@ -388,6 +511,48 @@ const char *bt_common_color_fg_light_gray(void)
        return bt_common_color_code_fg_light_gray;
 }
 
+BT_HIDDEN
+const char *bt_common_color_fg_bright_red(void)
+{
+       return bt_common_color_code_fg_bright_red;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_green(void)
+{
+       return bt_common_color_code_fg_bright_green;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_yellow(void)
+{
+       return bt_common_color_code_fg_bright_yellow;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_blue(void)
+{
+       return bt_common_color_code_fg_bright_blue;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_magenta(void)
+{
+       return bt_common_color_code_fg_bright_magenta;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_cyan(void)
+{
+       return bt_common_color_code_fg_bright_cyan;
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_bright_light_gray(void)
+{
+       return bt_common_color_code_fg_bright_light_gray;
+}
+
 BT_HIDDEN
 const char *bt_common_color_bg_default(void)
 {
@@ -436,6 +601,25 @@ const char *bt_common_color_bg_light_gray(void)
        return bt_common_color_code_bg_light_gray;
 }
 
+BT_HIDDEN
+void bt_common_color_get_codes(struct bt_common_color_codes *codes,
+               enum bt_common_color_when use_colors)
+{
+       if (use_colors == BT_COMMON_COLOR_WHEN_ALWAYS) {
+               *codes = color_codes;
+       } else if (use_colors == BT_COMMON_COLOR_WHEN_NEVER) {
+               *codes = no_color_codes;
+       } else {
+               BT_ASSERT(use_colors == BT_COMMON_COLOR_WHEN_AUTO);
+
+               if (bt_common_colors_supported()) {
+                       *codes = color_codes;
+               } else {
+                       *codes = no_color_codes;
+               }
+       }
+}
+
 BT_HIDDEN
 GString *bt_common_string_until(const char *input, const char *escapable_chars,
                const char *end_chars, size_t *end_pos)
@@ -580,10 +764,10 @@ bool bt_common_string_is_printable(const char *input)
 {
        const char *ch;
        bool printable = true;
-       BT_ASSERT(input);
+       BT_ASSERT_DBG(input);
 
        for (ch = input; *ch != '\0'; ch++) {
-               if (!isprint(*ch) && *ch != '\n' && *ch != '\r' &&
+               if (!isprint((unsigned char) *ch) && *ch != '\n' && *ch != '\r' &&
                                *ch != '\t' && *ch != '\v') {
                        printable = false;
                        goto end;
@@ -1256,7 +1440,7 @@ size_t bt_common_get_page_size(int log_level)
        if (page_size < 0) {
                BT_LOGF("Cannot get system's page size: ret=%d",
                        page_size);
-               abort();
+               bt_common_abort();
        }
 
        return page_size;
@@ -1271,7 +1455,7 @@ size_t bt_common_get_page_size(int log_level)
                strncpy(_tmp_fmt, *out_fmt_ch, _tmp_fmt_size);          \
                _tmp_fmt[_tmp_fmt_size] = '\0';                         \
                _count = snprintf(*buf_ch, _size, _tmp_fmt, __VA_ARGS__); \
-               BT_ASSERT(_count >= 0);                                 \
+               BT_ASSERT_DBG(_count >= 0);                                     \
                *buf_ch += MIN(_count, _size);                          \
        } while (0)
 
@@ -1413,13 +1597,11 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
 
                switch (length_mod) {
                case LENGTH_MOD_NONE:
-                       BUF_STD_APPEND_SINGLE_ARG(int);
-                       break;
                case LENGTH_MOD_LOW_L:
-                       BUF_STD_APPEND_SINGLE_ARG(wint_t);
+                       BUF_STD_APPEND_SINGLE_ARG(int);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        }
@@ -1434,7 +1616,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(wchar_t *);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'd':
@@ -1457,7 +1639,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(size_t);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'o':
@@ -1482,7 +1664,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(size_t);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'f':
@@ -1501,7 +1683,7 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                        BUF_STD_APPEND_SINGLE_ARG(long double);
                        break;
                default:
-                       abort();
+                       bt_common_abort();
                }
                break;
        case 'p':
@@ -1510,11 +1692,11 @@ static inline void handle_conversion_specifier_std(char *buf, char **buf_ch,
                if (length_mod == LENGTH_MOD_NONE) {
                        BUF_STD_APPEND_SINGLE_ARG(void *);
                } else {
-                       abort();
+                       bt_common_abort();
                }
                break;
        default:
-               abort();
+               bt_common_abort();
        }
 
 update_rw_fmt:
@@ -1530,13 +1712,13 @@ void bt_common_custom_vsnprintf(char *buf, size_t buf_size,
        const char *fmt_ch = fmt;
        char *buf_ch = buf;
 
-       BT_ASSERT(buf);
-       BT_ASSERT(fmt);
+       BT_ASSERT_DBG(buf);
+       BT_ASSERT_DBG(fmt);
 
        while (*fmt_ch != '\0') {
                switch (*fmt_ch) {
                case '%':
-                       BT_ASSERT(fmt_ch[1] != '\0');
+                       BT_ASSERT_DBG(fmt_ch[1] != '\0');
 
                        if (fmt_ch[1] == intro) {
                                handle_specifier(priv_data, &buf_ch,
@@ -1588,12 +1770,12 @@ void bt_common_sep_digits(char *str, unsigned int digits_per_group, char sep)
        uint64_t sep_count;
        uint64_t new_len;
 
-       BT_ASSERT(digits_per_group > 0);
-       BT_ASSERT(sep != '\0');
+       BT_ASSERT_DBG(digits_per_group > 0);
+       BT_ASSERT_DBG(sep != '\0');
 
        /* Compute new length of `str` */
        orig_len = strlen(str);
-       BT_ASSERT(orig_len > 0);
+       BT_ASSERT_DBG(orig_len > 0);
        sep_count = (orig_len - 1) / digits_per_group;
        new_len = strlen(str) + sep_count;
 
@@ -1693,10 +1875,10 @@ GString *bt_common_fold(const char *str, unsigned int total_length,
        gchar * const *line;
        unsigned int i;
 
-       BT_ASSERT(str);
-       BT_ASSERT(indent < total_length);
-       BT_ASSERT(tmp_line);
-       BT_ASSERT(folded);
+       BT_ASSERT_DBG(str);
+       BT_ASSERT_DBG(indent < total_length);
+       BT_ASSERT_DBG(tmp_line);
+       BT_ASSERT_DBG(folded);
 
        if (strlen(str) == 0) {
                /* Empty input string: empty output string */
@@ -1705,7 +1887,7 @@ GString *bt_common_fold(const char *str, unsigned int total_length,
 
        /* Split lines */
        lines = g_strsplit(str, "\n", 0);
-       BT_ASSERT(lines);
+       BT_ASSERT_DBG(lines);
 
        /* For each source line */
        for (line = lines; *line; line++) {
@@ -1722,7 +1904,7 @@ GString *bt_common_fold(const char *str, unsigned int total_length,
 
                /* Split words */
                line_words = g_strsplit(*line, " ", 0);
-               BT_ASSERT(line_words);
+               BT_ASSERT_DBG(line_words);
 
                /*
                 * Indent for first line (we know there's at least one
@@ -1790,7 +1972,7 @@ end:
                g_strfreev(lines);
        }
 
-       BT_ASSERT(!line_words);
+       BT_ASSERT_DBG(!line_words);
 
        if (tmp_line) {
                g_string_free(tmp_line, TRUE);
@@ -1903,3 +2085,24 @@ end:
        g_free(buf);
        return ret;
 }
+
+BT_HIDDEN
+void bt_common_abort(void)
+{
+       static const char * const exec_on_abort_env_name =
+               "BABELTRACE_EXEC_ON_ABORT";
+       const char *env_exec_on_abort;
+
+       env_exec_on_abort = getenv(exec_on_abort_env_name);
+       if (env_exec_on_abort) {
+               if (bt_common_is_setuid_setgid()) {
+                       goto do_abort;
+               }
+
+               (void) g_spawn_command_line_sync(env_exec_on_abort,
+                           NULL, NULL, NULL, NULL);
+       }
+
+do_abort:
+       abort();
+}
This page took 0.028507 seconds and 4 git commands to generate.