github.com/cloudwego/dynamicgo@v0.2.6-0.20240519101509-707f41b6b834/native/test/xprintf.h (about)

     1  /**
     2   * Copyright 2023 CloudWeGo Authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #include <sys/types.h>
    18  #include "../native.h"
    19  
    20  #ifndef XPRINTF_H
    21  #define XPRINTF_H
    22  
    23  
    24  #if (defined (__APPLE__) || defined(__MACH__)) && (defined(__x86_64__) || defined(_M_X64))
    25  static void __attribute__((naked)) write_syscall(const char *s, size_t n)
    26  {
    27      asm volatile(
    28          "movq %rsi, %rdx"
    29          "\n"
    30          "movq %rdi, %rsi"
    31          "\n"
    32          "movq $1, %rdi"
    33          "\n"
    34          "movq $0x02000004, %rax"
    35          "\n"
    36          "syscall"
    37          "\n"
    38          "retq"
    39          "\n");
    40  }
    41  #elif defined (__linux__) && (defined(__x86_64__) || defined(_M_X64))
    42  static void __attribute__((naked)) write_syscall(const char *s, size_t n)
    43  {
    44      asm volatile (
    45          "movq %rsi, %rdx"
    46          "\n"
    47          "movq %rdi, %rsi"
    48          "\n"
    49          "movl $1, %edi"
    50          "\n"
    51          "movl $1, %eax"
    52          "\n"
    53          "syscall"
    54          "\n"
    55          "retq"
    56      );
    57  }       
    58  #else
    59  #error syscall conv unsupported
    60  #endif
    61  
    62  
    63  static void printch(const char ch)
    64  {
    65      write_syscall(&ch, 1);
    66  }
    67  
    68  static void printstr(const char *s)
    69  {
    70      size_t n = 0;
    71      const char *p = s;
    72      while (*p++)
    73          n++;
    74      write_syscall(s, n);
    75  }
    76  
    77  static void printint(int64_t v)
    78  {
    79      char neg = 0;
    80      char buf[32] = {};
    81      char *p = &buf[31];
    82      if (v == 0)
    83      {
    84          printch('0');
    85          return;
    86      }
    87      if (v < 0)
    88      {
    89          v = -v;
    90          neg = 1;
    91      }
    92      while (v)
    93      {
    94          *--p = (v % 10) + '0';
    95          v /= 10;
    96      }
    97      if (neg)
    98      {
    99          *--p = '-';
   100      }
   101      printstr(p);
   102  }
   103  
   104  static const char tab[] = "0123456789abcdef";
   105  
   106  static void printhex(uintptr_t v)
   107  {
   108      if (v == 0)
   109      {
   110          printch('0');
   111          return;
   112      }
   113      char buf[32] = {};
   114      char *p = &buf[31];
   115  
   116      while (v)
   117      {
   118          *--p = tab[v & 0x0f];
   119          v >>= 4;
   120      }
   121      printstr(p);
   122  }
   123  
   124  #define MAX_BUF_LEN 100
   125  
   126  static void printbytes(GoSlice *s)
   127  {
   128      printch('[');
   129      int i = 0;
   130      if (s->len > MAX_BUF_LEN)
   131      {
   132          i = s->len - MAX_BUF_LEN;
   133      }
   134      for (; i < s->len; i++)
   135      {
   136          printch(tab[((s->buf[i]) & 0xf0) >> 4]);
   137          printch(tab[(s->buf[i]) & 0x0f]);
   138          if (i != s->len - 1)
   139              printch(',');
   140      }
   141      printch(']');
   142  }
   143  
   144  static void printints(GoSlice *s)
   145  {
   146      printch('[');
   147      int i = 0;
   148      for (; i < s->len; i++)
   149      {
   150          printhex(((uintptr_t *)(s->buf))[i]);
   151          if (i != s->len - 1)
   152              printch(',');
   153      }
   154      printch(']');
   155  }
   156  
   157  static void printgostr(GoString *s)
   158  {
   159      printch('"');
   160      if (s->len < MAX_BUF_LEN)
   161      {
   162          write_syscall(s->buf, s->len);
   163      }
   164      else
   165      {
   166          write_syscall(&s->buf[s->len - MAX_BUF_LEN], MAX_BUF_LEN);
   167      }
   168      printch('"');
   169  }
   170  
   171  void xprintf(const char *fmt, ...)
   172  {
   173  #ifdef DEBUG
   174      __builtin_va_list va;
   175      char buf[256] = {};
   176      char *p = buf;
   177      __builtin_va_start(va, fmt);
   178      for (;;)
   179      {
   180          if (*fmt == 0)
   181          {
   182              break;
   183          }
   184          if (*fmt != '%')
   185          {
   186              *p++ = *fmt++;
   187              continue;
   188          }
   189          *p = 0;
   190          p = buf;
   191          fmt++;
   192          printstr(buf);
   193          switch (*fmt++)
   194          {
   195          case '%':
   196          {
   197              printch('%');
   198              break;
   199          }
   200          case 's':
   201          {
   202              printgostr(__builtin_va_arg(va, GoString *));
   203              break;
   204          }
   205          case 'd':
   206          {
   207              printint(__builtin_va_arg(va, int64_t));
   208              break;
   209          }
   210          case 'f':
   211          {
   212              printint(__builtin_va_arg(va, double));
   213              break;
   214          }
   215          case 'c':
   216          {
   217              printch(__builtin_va_arg(va, const char));
   218              break;
   219          }
   220          case 'x':
   221          {
   222              printhex(__builtin_va_arg(va, uintptr_t));
   223              break;
   224          }
   225          case 'l':
   226          {
   227              printbytes(__builtin_va_arg(va, GoSlice *));
   228              break;
   229          }
   230          case 'n':
   231          {
   232              printints(__builtin_va_arg(va, GoSlice *));
   233              break;
   234          }
   235          }
   236      }
   237      __builtin_va_end(va);
   238      if (p != buf)
   239      {
   240          *p = 0;
   241          printstr(buf);
   242      }
   243  #endif
   244  }
   245  
   246  #endif // SCANNING_H