welcome GPLv3! yes, k8jam is GPL'ed now, along with Jambase. because i can.
[k8jam.git] / src / mkjambase.c
blobef73b3f65e311111b518e4a4d855e0b0b9bea9c8
1 /*
2 * Copyright 1993, 1995 Christopher Seiwald.
3 * This file is part of Jam - see jam.c for Copyright information.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * mkjambase.c - turn Jambase into a big C structure
21 * Usage: mkjambase jambase.c Jambase ...
23 * Results look like this:
25 * char *jambase[] = {
26 * "...\n",
27 * ...
28 * 0 };
30 * Handles \'s and "'s specially; knows how to delete blank and comment lines.
32 #include <ctype.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
39 #include "lzpack.c"
41 //#define MKJAMBASE_COMPACT
44 ////////////////////////////////////////////////////////////////////////////////
45 static void fatal (const char *msg) {
46 fprintf(stdout, "FATAL: %s\n", msg);
47 exit(1);
51 static char outdata[1024*1024];
52 static int outdatalen = 0;
55 static void outStr (const char *str) {
56 memmove(outdata+outdatalen, str, strlen(str));
57 outdatalen += strlen(str);
61 #define EMIT(ch) do { \
62 if (outp-outbuf >= sizeof(outbuf)) fatal("output line too big\n");\
63 *(outp++) = (ch); \
64 } while (0)
67 static inline void normSlashes (char *s) {
68 for (; *s; ++s) if (*s == '\\') *s = '/';
72 static int doDotC = 0, wasScreen, dontStrip = 0, dropSpaces, doCompress = 1;
74 static int lineno = 0;
75 static int inclevel = 0;
76 static const char *srcfname = "<cli>";
78 static void processFile (FILE *fout, const char *fname) {
79 FILE *fin;
80 char *p, *e, quoteCh, *outp;
81 static char buf[32768], outbuf[32768];
82 int olno = lineno;
83 const char *ofn = srcfname;
85 srcfname = fname;
86 lineno = 0;
88 if (++inclevel > 64) {
89 fclose(fout);
90 fprintf(stderr, "FATAL: too many nested includes, failed in file '%s', line %d\n", ofn, olno);
91 exit(1);
94 printf(": %s\n", fname);
95 if (!(fin = fopen(fname, "r"))) {
96 fclose(fout);
97 fprintf(stderr, "FATAL: can't open file '%s', failed in file '%s', line %d\n", fname, ofn, olno);
98 exit(1);
100 if (doDotC) {
101 if (!doCompress) fprintf(fout, "/* %s */\n", fname);
102 } else {
103 outStr("### ");
104 outStr(fname);
105 outStr(" ###\n");
108 while (fgets(buf, sizeof(buf), fin)) {
109 ++lineno;
111 if (buf[0] == '.') {
112 /* include */
113 char *fn, *t;
115 p = buf+1;
116 while (*p && *((unsigned char *)p) <= ' ') ++p;
117 if ((t = strchr(p, '#')) != NULL) *t = '\0';
118 for (t = p+strlen(p); t > p; --t) if (!isspace(t[-1])) break;
119 *t = '\0';
120 if (!p[0]) {
121 fclose(fout);
122 fprintf(stderr, "FATAL: invalid '.' in file '%s', line %d\n", fname, lineno);
123 exit(1);
125 fn = malloc(strlen(p)+strlen(fname)+64);
126 if (!fn) {
127 fclose(fout);
128 fprintf(stderr, "FATAL: out of memory in file '%s', line %d\n", fname, lineno);
129 exit(1);
131 strcpy(fn, fname);
132 normSlashes(fn);
133 if ((t = strrchr(fn, '/')) != NULL) t[1] = '\0'; else fn[0] = '\0';
134 strcat(fn, p);
135 processFile(fout, fn);
136 free(fn);
137 continue;
140 if (doDotC) {
141 #ifdef MKJAMBASE_COMPACT
142 if (!strncmp(buf, "#DONT_TOUCH", 11)) {
143 dontStrip = !dontStrip;
144 continue;
146 #else
147 dontStrip = 1;
148 #endif
149 p = buf;
150 /* strip leading whitespace */
151 if (!dontStrip) {
152 while (*p && *((unsigned char *)p) <= ' ') ++p;
153 /* drop comments and empty lines */
154 if (*p == '#' || !*p) continue;
156 /* copy; drop comments if # is not in quotes */
157 outp = outbuf; quoteCh = 0; wasScreen = 0;
158 if (!doCompress) EMIT('"');
159 dropSpaces = 0;
160 for (; *p && *p != '\n' && *p != '\r'; p++) {
161 if (!dontStrip) {
162 if (!quoteCh && !wasScreen && *p == '#') break; /* comment follows; drop it */
164 switch (*p) {
165 case '\\':
166 if (!doCompress) EMIT('\\');
167 EMIT('\\');
168 wasScreen = !wasScreen;
169 dropSpaces = 0;
170 break;
171 case '"':
172 if (!doCompress) EMIT('\\');
173 EMIT('"');
174 if (!wasScreen) quoteCh = (quoteCh==*p)?0:*p;
175 dropSpaces = 0;
176 break;
177 case '\x27': /* ' */
178 EMIT('\x27');
179 if (!wasScreen) quoteCh = (quoteCh==*p)?0:*p;
180 dropSpaces = 0;
181 break;
182 default:
183 if (!dontStrip && *((unsigned char *)p) <= ' ') {
184 if (wasScreen || !dropSpaces || quoteCh) EMIT(*p);
185 dropSpaces = !quoteCh;
186 } else {
187 EMIT(*p);
188 dropSpaces = 0;
190 wasScreen = 0;
191 break;
194 /* terminate output */
195 *outp = '\0';
196 if (!dontStrip) {
197 /* strip ending whitespace */
198 e = outp-1;
199 while (e >= outbuf && *((unsigned char *)e) <= ' ') --e;
200 *(++e) = '\0';
201 /* drop empty line */
202 if (!outbuf[0]) continue;
204 if (doCompress) {
205 outStr(outbuf);
206 outStr("\n");
207 } else {
208 fprintf(fout, "%s\\n\",\n", outbuf);
210 } else {
211 fprintf(fout, "%s", buf);
212 //outStr(buf);
215 fclose(fin);
216 --inclevel;
217 srcfname = ofn;
218 lineno = olno;
222 int main (int argc, char *argv[]) {
223 FILE *fout;
224 char *p;
226 if (argc < 3) {
227 fprintf(stderr, "usage: %s jambase.c Jambase ...\n", argv[0]);
228 return 1;
231 if (!(fout = fopen(argv[1], "wb"))) {
232 perror(argv[1]);
233 return 1;
236 /* if the file ends in .c generate a C source file */
237 if ((p = strrchr(argv[1], '.')) && !strcmp(p, ".c")) ++doDotC;
239 /* now process the files */
240 argc -= 2, argv += 2;
242 if (doDotC) {
243 fprintf(fout, "/* Generated by mkjambase from Jambase */\n");
244 fprintf(fout, "#include \"jam.h\"\n");
245 if (doCompress) {
246 fprintf(fout, "char **jambase = 0;\n");
247 fprintf(fout, "unsigned char jambasepk[] = {");
248 } else {
249 fprintf(fout, "const char *jambase[] = {\n");
253 for (; argc--; ++argv) processFile(fout, *argv);
255 if (outdatalen > 0) {
256 if (doCompress) {
257 unsigned char *dest;
258 size_t destlen;
259 int cnt = 0;
261 if (lzCompress(outdata, outdatalen, &dest, &destlen) != 0) {
262 perror("compression error!");
263 return 1;
265 printf("%d bytes packed to %u bytes (%u%%)\n", outdatalen, (unsigned int)destlen, (unsigned int)(100*destlen/outdatalen));
266 //fwrite(dest, destlen, 1, fout);
267 for (int f = 0; f < destlen; ++f) {
268 if (cnt <= 0) {
269 fputc('\n', fout);
270 cnt = 16;
272 --cnt;
273 fprintf(fout, "0x%02x,", dest[f]);
275 if (cnt > 0) fputc('\n', fout);
276 } else {
277 perror("wtf?!");
278 return 1;
279 //fwrite(outdata, outdatalen, 1, fout);
283 if (doDotC) {
284 if (!doCompress) fputc('0', fout);
285 fprintf(fout, "};\n");
286 if (doCompress) fprintf(fout, "\nJAMFA_CONST int jbpksize (void) { return sizeof(jambasepk); }\n");
289 fclose(fout);
290 return 0;