cembed.c (2280B)
1 #include <errno.h> 2 #include <rcx/all.h> 3 #include <stdio.h> 4 #include <string.h> 5 6 #define USAGE "usage: %s [-h|--help] NAME PATH\n" 7 8 usize 9 format_char(char *buf, uchar curr, uchar next) { 10 // Escape specials. 11 switch (curr) { 12 case '\a': strcpy(buf, "\\a"); return 2; 13 case '\b': strcpy(buf, "\\b"); return 2; 14 case '\t': strcpy(buf, "\\t"); return 2; 15 case '\n': strcpy(buf, "\\n"); return 2; 16 case '\v': strcpy(buf, "\\v"); return 2; 17 case '\f': strcpy(buf, "\\f"); return 2; 18 case '\r': strcpy(buf, "\\r"); return 2; 19 case '"': strcpy(buf, "\\\""); return 2; 20 case '?': strcpy(buf, "\\?"); return 2; 21 case '\\': strcpy(buf, "\\\\"); return 2; 22 } 23 24 // Keep non-special printable ASCII as-is. 25 if (' ' <= curr && curr <= '~') { 26 buf[0] = curr; 27 buf[1] = '\0'; 28 return 1; 29 } 30 31 // Octal-encode rest. We can't hex-encode, because C hex encoding is 32 // variable length. 33 char octal[4] = { 34 "01234567"[(curr >> 6) & 0x3], 35 "01234567"[(curr >> 3) & 0x7], 36 "01234567"[(curr >> 0) & 0x7], 37 '\0', 38 }; 39 buf[0] = '\\'; 40 // We want the encoding to be as small as possible, but if the next 41 // character is an octal digit, than we must pad to 3 digits. 42 if (('0' <= next && next <= '7') || curr >= 64) { 43 strcpy(&buf[1], &octal[0]); 44 return 4; 45 } else if (curr >= 8) { 46 strcpy(&buf[1], &octal[1]); 47 return 3; 48 } else { 49 strcpy(&buf[1], &octal[2]); 50 return 2; 51 } 52 } 53 54 int 55 main(int argc, char **argv) { 56 // TODO: Replace this with a proper option parsing from RCX (does not 57 // exist at the time of writing). 58 for (usize i = 1; i < argc; i++) { 59 if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { 60 printf(USAGE, argv[0]); 61 return 0; 62 } 63 } 64 65 if (argc != 3) { 66 fprintf(stderr, USAGE, argv[0]); 67 return 1; 68 } 69 70 char *name = argv[1]; 71 char *path = argv[2]; 72 73 usize size; 74 char *data = r_vmem_open(&size, 0, path, 0, "r"); 75 if (!data) { 76 fprintf(stderr, "r_vmem_open: %s\n", strerror(errno)); 77 return 1; 78 } 79 80 printf("char %s[] =\n\t\"", name); 81 usize line_len = 0; 82 for (usize i = 0; i < size; i++) { 83 if (line_len >= 72) { 84 printf("\"\n\t\""); 85 line_len = 0; 86 } 87 88 char buf[5]; 89 uchar curr = data[i]; 90 uchar next = i + 1 < size ? data[i + 1] : '\0'; 91 line_len += format_char(buf, curr, next); 92 93 fputs(buf, stdout); 94 } 95 printf("\";\n"); 96 97 return 0; 98 }