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