(root)/
strace-6.5/
src/
print_utils.h
       1  /*
       2   * Copyright (c) 2019-2021 Eugene Syromyatnikov <evgsyr@gmail.com>.
       3   * Copyright (c) 2022-2023 The strace developers.
       4   * All rights reserved.
       5   *
       6   * SPDX-License-Identifier: LGPL-2.1-or-later
       7   */
       8  
       9  #ifndef STRACE_PRINT_UTILS_H
      10  # define STRACE_PRINT_UTILS_H
      11  
      12  # include <inttypes.h>
      13  
      14  /* Hexadecimal output utils */
      15  
      16  static const char hex_chars[16] = "0123456789abcdef";
      17  
      18  /**
      19   * Character array representing hexadecimal encoding of a character value.
      20   *
      21   * @param b_ Byte to provide representation for.
      22   */
      23  # define BYTE_HEX_CHARS(b_) \
      24  	hex_chars[((uint8_t) (b_)) >> 4], hex_chars[((uint8_t) (b_)) & 0xf]
      25  
      26  /* Character classification utils */
      27  
      28  static inline bool
      29  is_print(uint8_t c)
      30  {
      31  	return (c >= ' ') && (c < 0x7f);
      32  }
      33  
      34  /* Character printing functions */
      35  
      36  /** @param unabbrev Whether to always print \ooo instead of \[[o]o]o. */
      37  static inline char *
      38  sprint_byte_oct(char *s, uint8_t c, bool unabbrev)
      39  {
      40  	if (unabbrev) {
      41  		/* Print \ooo */
      42  		*s++ = '0' + (c >> 6);
      43  		*s++ = '0' + ((c >> 3) & 0x7);
      44  	} else {
      45  		/* Print \[[o]o]o */
      46  		if ((c >> 3) != 0) {
      47  			if ((c >> 6) != 0)
      48  				*s++ = '0' + (c >> 6);
      49  			*s++ = '0' + ((c >> 3) & 0x7);
      50  		}
      51  	}
      52  	*s++ = '0' + (c & 0x7);
      53  
      54  	return s;
      55  }
      56  
      57  static inline char *
      58  sprint_byte_hex(char *buf, uint8_t val)
      59  {
      60  	*buf++ = hex_chars[val >> 4];
      61  	*buf++ = hex_chars[val & 0xf];
      62  
      63  	return buf;
      64  }
      65  
      66  /** Maximum number of characters emitted by sprint_char */
      67  # define SPRINT_CHAR_BUFSZ 7
      68  
      69  enum sprint_char_flag_bits {
      70  	SCF_QUOTES_BIT,
      71  	SCF_NUL_BIT,
      72  	SCF_ESC_WS_BIT,
      73  };
      74  
      75  enum sprint_char_flags {
      76  	FLAG(SCF_QUOTES), /**< Whether to emit quotes */
      77  	FLAG(SCF_NUL),    /**< Whether to terminate output with \0 */
      78  	FLAG(SCF_ESC_WS), /**< Whether to print \t\n\v\f\r in symbolic form */
      79  };
      80  
      81  /** Emits a character into buf (SPRINT_CHAR_BUFSZ max), returns new position. */
      82  static inline char *
      83  sprint_char(char *buf, const unsigned char c, const enum sprint_char_flags f)
      84  {
      85  	if (f & SCF_QUOTES)
      86  		*buf++ = '\'';
      87  
      88  	if (is_print(c)) {
      89  		if (c == '\'' || c == '\\')
      90  			*buf++ = '\\';
      91  		*buf++ = c;
      92  	} else if ((f & SCF_ESC_WS) && (c >= '\t') && (c <= '\r')) {
      93  		static const char ws_chars[] = "tnvfr";
      94  
      95  		*buf++ = '\\';
      96  		*buf++ = ws_chars[c - '\t'];
      97  	} else {
      98  		*buf++ = '\\';
      99  		*buf++ = 'x';
     100  		buf = sprint_byte_hex(buf, c);
     101  	}
     102  
     103  	if (f & SCF_QUOTES)
     104  		*buf++ = '\'';
     105  	if (f & SCF_NUL)
     106  		*buf++ = '\0';
     107  
     108  	return buf;
     109  }
     110  
     111  # define print_char(c_, flags_)					\
     112  	do {							\
     113  		char buf[SPRINT_CHAR_BUFSZ];			\
     114  								\
     115  		sprint_char(buf, (c_), (flags_) | SCF_NUL);	\
     116  		tprints_string(buf);				\
     117  	} while (0)
     118  
     119  #endif /* STRACE_PRINT_UTILS_H */