comparison extern/bcc/bcc.c @ 0:f1de39079243

misc: initial import
author David Demelier <markand@malikania.fr>
date Mon, 07 Jun 2021 09:41:37 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f1de39079243
1 /*
2 * bcc.c -- binary to C/C++ arrays converter
3 *
4 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdnoreturn.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 static const char *charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
28 static char findentchar = '\t';
29 static int findent = 1, fconst, fnull, fstatic;
30
31 noreturn static void
32 usage(void)
33 {
34 fprintf(stderr, "usage: bcc [-0cs] [-I tab-indent] [-i space-indent] input variable\n");
35 exit(1);
36 }
37
38 noreturn static void
39 die(const char *fmt, ...)
40 {
41 va_list ap;
42
43 va_start(ap, fmt);
44 fputs("abort: ", stderr);
45 vfprintf(stderr, fmt, ap);
46 va_end(ap);
47 exit(1);
48 }
49
50 static char *
51 mangle(char *variable)
52 {
53 char *p;
54 size_t pos;
55
56 /* Remove extension. */
57 if ((p = strrchr(variable, '.')))
58 *p = '\0';
59
60 /* Remove disallowed characters. */
61 while ((pos = strspn(variable, charset)) != strlen(variable))
62 variable[pos] = '_';
63
64 return variable;
65 }
66
67 static void
68 indent(void)
69 {
70 for (int i = 0; i < findent; ++i)
71 putchar(findentchar);
72 }
73
74 static void
75 put(int ch)
76 {
77 printf("0x%02hhx", (unsigned char)ch);
78 }
79
80 static void
81 process(const char *input, const char *variable)
82 {
83 FILE *fp;
84 int ch, col = 0;
85
86 if (strcmp(input, "-") == 0)
87 fp = stdin;
88 else if (!(fp = fopen(input, "rb")))
89 die("%s: %s\n", input, strerror(errno));
90
91 if (fstatic)
92 printf("static ");
93 if (fconst)
94 printf("const ");
95
96 printf("unsigned char %s[] = {\n", variable);
97
98 for (ch = fgetc(fp); ch != EOF; ) {
99 if (col == 0)
100 indent();
101
102 put(ch);
103
104 if ((ch = fgetc(fp)) != EOF || fnull)
105 printf(",%s", col < 3 ? " " : "");
106
107 if (++col == 4) {
108 col = 0;
109 putchar('\n');
110 }
111
112 /* Add final '\0' if required. */
113 if (ch == EOF && fnull) {
114 if (col++ == 0)
115 indent();
116
117 put(0);
118 }
119 }
120
121 if (col != 0)
122 printf("\n");
123
124 puts("};");
125 fclose(fp);
126 }
127
128 int
129 main(int argc, char **argv)
130 {
131 int ch;
132
133 while ((ch = getopt(argc, argv, "0cI:i:s")) != -1) {
134 switch (ch) {
135 case '0':
136 fnull = 1;
137 break;
138 case 'c':
139 fconst = 1;
140 break;
141 case 'I':
142 findentchar = '\t';
143 findent = atoi(optarg);
144 break;
145 case 'i':
146 findentchar = ' ';
147 findent = atoi(optarg);
148 break;
149 case 's':
150 fstatic = 1;
151 break;
152 default:
153 break;
154 }
155 }
156
157 argc -= optind;
158 argv += optind;
159
160 if (argc < 2)
161 usage();
162
163 process(argv[0], mangle(argv[1]));
164 }