MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add debugging capabilities to cprintf

+221 -4
+17 -4
include/cli/cprintf.h
··· 6 6 #include <stdbool.h> 7 7 8 8 extern bool io_no_color; 9 + extern bool cprintf_debug; 10 + extern bool cprintf_debug_hex; 11 + 9 12 typedef struct program_t program_t; 13 + program_t *cprintf_compile(const char *fmt); 10 14 11 - program_t *cprintf_compile(const char *fmt); 15 + void cprintf_hexdump(program_t *prog, FILE *out); 16 + void cprintf_disasm(program_t *prog, FILE *out); 17 + 12 18 int cprintf_exec(program_t *prog, FILE *stream, ...); 13 19 int csprintf_inner(program_t *prog, char *buf, size_t size, ...); 14 20 21 + #define _CPRINTF_INIT(prog, fmt) \ 22 + if (!prog) { \ 23 + prog = cprintf_compile(fmt); \ 24 + if (cprintf_debug) cprintf_disasm(prog, stderr); \ 25 + if (cprintf_debug_hex) cprintf_hexdump(prog, stderr); \ 26 + } 27 + 15 28 #define cprintf(fmt, ...) ({ \ 16 29 static program_t *_cp_prog_ = NULL; \ 17 - if (!_cp_prog_) _cp_prog_ = cprintf_compile(fmt); \ 30 + _CPRINTF_INIT(_cp_prog_, fmt); \ 18 31 cprintf_exec(_cp_prog_, stdout, ##__VA_ARGS__); \ 19 32 }) 20 33 21 34 #define cfprintf(stream, fmt, ...) ({ \ 22 35 static program_t *_cp_prog_ = NULL; \ 23 - if (!_cp_prog_) _cp_prog_ = cprintf_compile(fmt); \ 36 + _CPRINTF_INIT(_cp_prog_, fmt); \ 24 37 cprintf_exec(_cp_prog_, stream, ##__VA_ARGS__); \ 25 38 }) 26 39 27 40 #define csprintf(buf, size, fmt, ...) ({ \ 28 41 static program_t *_cp_prog_ = NULL; \ 29 - if (!_cp_prog_) _cp_prog_ = cprintf_compile(fmt); \ 42 + _CPRINTF_INIT(_cp_prog_, fmt); \ 30 43 csprintf_inner(_cp_prog_, buf, size, ##__VA_ARGS__); \ 31 44 }) 32 45
+193
src/cli/cprintf.c
··· 34 34 #include <stdint.h> 35 35 #include <wchar.h> 36 36 37 + bool cprintf_debug = false; 38 + bool cprintf_debug_hex = false; 39 + 37 40 typedef enum { 38 41 OP_NOP = 0, 39 42 OP_EMIT_LIT, ··· 817 820 free(o.data); 818 821 819 822 return (int)o.len; 823 + } 824 + 825 + static const char *op_names[OP_MAX] = { 826 + [OP_NOP] = "NOP", 827 + [OP_EMIT_LIT] = "EMIT_LIT", 828 + [OP_EMIT_FMT] = "EMIT_FMT", 829 + [OP_SET_FG] = "SET_FG", 830 + [OP_SET_BG] = "SET_BG", 831 + [OP_SET_FG_RGB] = "SET_FG_RGB", 832 + [OP_SET_BG_RGB] = "SET_BG_RGB", 833 + [OP_SET_BOLD] = "SET_BOLD", 834 + [OP_SET_DIM] = "SET_DIM", 835 + [OP_SET_UL] = "SET_UL", 836 + [OP_STYLE_PUSH] = "STYLE_PUSH", 837 + [OP_STYLE_FLUSH] = "STYLE_FLUSH", 838 + [OP_STYLE_RESET] = "STYLE_RESET", 839 + [OP_STYLE_RESET_ALL] = "STYLE_RESET_ALL", 840 + [OP_PAD_BEGIN] = "PAD_BEGIN", 841 + [OP_RPAD_BEGIN] = "RPAD_BEGIN", 842 + [OP_PAD_END] = "PAD_END", 843 + [OP_EMIT_SPACES] = "EMIT_SPACES", 844 + [OP_HALT] = "HALT", 845 + }; 846 + 847 + static const char *color_name(uint32_t col) { 848 + switch (col) { 849 + case COL_BLACK: return "black"; 850 + case COL_RED: return "red"; 851 + case COL_GREEN: return "green"; 852 + case COL_YELLOW: return "yellow"; 853 + case COL_BLUE: return "blue"; 854 + case COL_MAGENTA: return "magenta"; 855 + case COL_CYAN: return "cyan"; 856 + case COL_WHITE: return "white"; 857 + case COL_GRAY: return "gray"; 858 + case COL_BRIGHT_RED: return "bright_red"; 859 + case COL_BRIGHT_GREEN: return "bright_green"; 860 + case COL_BRIGHT_YELLOW: return "bright_yellow"; 861 + case COL_BRIGHT_BLUE: return "bright_blue"; 862 + case COL_BRIGHT_MAGENTA: return "bright_magenta"; 863 + case COL_BRIGHT_CYAN: return "bright_cyan"; 864 + case COL_BRIGHT_WHITE: return "bright_white"; 865 + default: return "?"; 866 + }} 867 + 868 + static const char *arg_class_name(arg_class_t cls) { 869 + switch (cls) { 870 + case ARG_NONE: return "none"; 871 + case ARG_INT: return "int"; 872 + case ARG_LONG: return "long"; 873 + case ARG_LLONG: return "llong"; 874 + case ARG_SIZE: return "size_t"; 875 + case ARG_DOUBLE: return "double"; 876 + case ARG_CSTR: return "char*"; 877 + case ARG_PTR: return "void*"; 878 + case ARG_WINT: return "wint_t"; 879 + case ARG_WSTR: return "wchar_t*"; 880 + default: return "?"; 881 + }} 882 + 883 + static void fprint_escaped(FILE *out, const char *s, int max_chars) { 884 + for (int c = 0; *s && (max_chars < 0 || c < max_chars); s++, c++) { 885 + if (*s == '\n') fprintf(out, "\\n"); 886 + else if (*s == '\t') fprintf(out, "\\t"); 887 + else if (*s == '"') fprintf(out, "\\\""); 888 + else if (*s < 0x20) fprintf(out, "\\x%02x", (unsigned char)*s); 889 + else fputc(*s, out); 890 + } 891 + if (max_chars >= 0 && *s) fprintf(out, "..."); 892 + } 893 + 894 + static void fprint_quoted(FILE *out, const char *s, int max_chars) { 895 + fputc('"', out); 896 + fprint_escaped(out, s, max_chars); 897 + fputc('"', out); 898 + } 899 + 900 + static void fprint_operand(FILE *out, program_t *prog, instruction_t *ins, bool compact) { 901 + switch (ins->op) { 902 + case OP_EMIT_LIT: { 903 + const char *s = prog->literals + ins->operand; 904 + fprint_quoted(out, s, compact ? 24 : -1); 905 + break; 906 + } 907 + 908 + case OP_EMIT_FMT: { 909 + uint32_t lit_off = ins->operand & 0x0FFFFFFF; 910 + arg_class_t cls = (arg_class_t)(ins->operand >> 28); 911 + const char *s = prog->literals + lit_off; 912 + fprint_quoted(out, s, compact ? 24 : -1); 913 + fprintf(out, " (%s)", arg_class_name(cls)); 914 + break; 915 + } 916 + 917 + case OP_SET_FG: 918 + case OP_SET_BG: 919 + if (compact) fprintf(out, "%s", color_name(ins->operand)); 920 + else fprintf(out, "%s (ANSI %u)", color_name(ins->operand), ins->operand); 921 + break; 922 + 923 + case OP_SET_FG_RGB: 924 + case OP_SET_BG_RGB: 925 + fprintf(out, "#%02x%02x%02x", 926 + UNPACK_R(ins->operand), UNPACK_G(ins->operand), UNPACK_B(ins->operand)); 927 + break; 928 + 929 + case OP_SET_BOLD: 930 + case OP_SET_DIM: 931 + case OP_SET_UL: 932 + fprintf(out, "%s", ins->operand ? "ON" : "OFF"); 933 + break; 934 + 935 + case OP_PAD_BEGIN: 936 + case OP_RPAD_BEGIN: 937 + fprintf(out, "width=%u", ins->operand); 938 + break; 939 + 940 + case OP_EMIT_SPACES: 941 + fprintf(out, "%u", ins->operand); 942 + break; 943 + 944 + case OP_NOP: 945 + case OP_STYLE_PUSH: 946 + case OP_STYLE_FLUSH: 947 + case OP_STYLE_RESET: 948 + case OP_STYLE_RESET_ALL: 949 + case OP_PAD_END: 950 + case OP_HALT: 951 + break; 952 + 953 + default: 954 + if (compact) { 955 + if (ins->operand) fprintf(out, "0x%x", ins->operand); 956 + } else fprintf(out, "0x%08x", ins->operand); 957 + break; 958 + } 959 + } 960 + 961 + void cprintf_disasm(program_t *prog, FILE *out) { 962 + fprintf(out, "; cprintf bytecode โ€” %zu instructions, %zu bytes literal pool\n", prog->code_len, prog->lit_len); 963 + fprintf(out, "; %-4s %-16s %s\n", "addr", "opcode", "operand"); 964 + fprintf(out, "; ---- ---------------- -------\n"); 965 + 966 + for (size_t i = 0; i < prog->code_len; i++) { 967 + instruction_t *ins = &prog->code[i]; 968 + const char *name = (ins->op < OP_MAX) ? op_names[ins->op] : "???"; 969 + 970 + fprintf(out, " %04zu %-16s ", i, name); 971 + fprint_operand(out, prog, ins, false); 972 + fputc('\n', out); 973 + } 974 + } 975 + 976 + void cprintf_hexdump(program_t *prog, FILE *out) { 977 + fprintf(out, "; cprintf hex dump โ€” %zu instructions, %zu bytes literal pool\n", prog->code_len, prog->lit_len); 978 + fprintf(out, "; %-4s %-26s %s\n", "addr", "bytes", "decoded"); 979 + fprintf(out, "; ---- ------------------------- --------\n"); 980 + 981 + for (size_t i = 0; i < prog->code_len; i++) { 982 + instruction_t *ins = &prog->code[i]; 983 + const uint8_t *raw = (const uint8_t *)ins; 984 + const char *name = (ins->op < OP_MAX) ? op_names[ins->op] : "???"; 985 + 986 + fprintf(out, " %04zu ", i); 987 + for (size_t b = 0; b < sizeof(instruction_t); b++) fprintf(out, "%02x ", raw[b]); 988 + 989 + fprintf(out, " ; %s ", name); 990 + fprint_operand(out, prog, ins, true); 991 + fputc('\n', out); 992 + } 993 + 994 + if (prog->lit_len > 0) { 995 + fprintf(out, "\n; literal pool (%zu bytes):\n", prog->lit_len); 996 + const uint8_t *lit = (const uint8_t *)prog->literals; 997 + for (size_t off = 0; off < prog->lit_len; off += 16) { 998 + fprintf(out, " %04zx ", off); 999 + 1000 + size_t end = off + 16; 1001 + if (end > prog->lit_len) end = prog->lit_len; 1002 + for (size_t b = off; b < off + 16; b++) { 1003 + if (b < end) fprintf(out, "%02x ", lit[b]); 1004 + else fprintf(out, " "); 1005 + if (b == off + 7) fputc(' ', out); 1006 + } 1007 + 1008 + fprintf(out, " |"); 1009 + for (size_t b = off; b < end; b++) fputc((lit[b] >= 0x20 && lit[b] < 0x7f) ? lit[b] : '.', out); 1010 + fprintf(out, "|\n"); 1011 + } 1012 + } 820 1013 }
+11
src/main.c
··· 80 80 {NULL, NULL, NULL, NULL} 81 81 }; 82 82 83 + static void parse_ant_debug(const char *flag) { 84 + if (strncmp(flag, "dump-cprintf=", 13) == 0) { 85 + const char *mode = flag + 13; 86 + if (strcmp(mode, "bytecode") == 0 || strcmp(mode, "all") == 0) cprintf_debug = true; 87 + if (strcmp(mode, "hex") == 0 || strcmp(mode, "all") == 0) cprintf_debug_hex = true; 88 + } 89 + 90 + else fprintf(stderr, "warning: unknown ANT_DEBUG flag: %s\n", flag); 91 + } 92 + 83 93 static const subcommand_t *find_subcommand(const char *name) { 84 94 for (const subcommand_t *cmd = subcommands; cmd->name; cmd++) { 85 95 if (strcmp(name, cmd->name) == 0) return cmd; ··· 248 258 for (int i = 0; i < argc; i++) { 249 259 if (strcmp(argv[i], "--verbose") == 0) pkg_verbose = true; 250 260 else if (strcmp(argv[i], "--no-color") == 0) io_no_color = true; 261 + else if (strncmp(argv[i], "--ANT_DEBUG:", 12) == 0) parse_ant_debug(argv[i] + 12); 251 262 else filtered_argv[filtered_argc++] = argv[i]; 252 263 } 253 264