cembed

convert files to C char arrays
git clone git://git.rr3.xyz/cembed
Log | Files | Refs | README | LICENSE

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 }