added "jammod" command and "genman" module
[k8jam.git] / src / mkjambase.c
bloba90b46f7f1eac24580042024a8761b8f9c362eb0
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 "libhapack.h"
40 #include "libhapack.c"
42 //#define MKJAMBASE_COMPACT
45 ////////////////////////////////////////////////////////////////////////////////
46 static void fatal (const char *msg) {
47 fprintf(stdout, "FATAL: %s\n", msg);
48 exit(1);
52 static char outdata[1024*1024];
53 static int outdatalen = 0;
56 ////////////////////////////////////////////////////////////////////////////////
57 static uint8_t *pkdata = NULL;
58 static size_t pkdataSize = 0;
59 static size_t pkdataUsed = 0;
62 static void growPkData (int morebytes) {
63 if (morebytes > 0) {
64 if (pkdataUsed+morebytes > pkdataSize) {
65 pkdataSize = (pkdataUsed+morebytes)+32768;
66 pkdata = realloc(pkdata, pkdataSize);
67 if (pkdata == NULL) abort();
73 static int bread (void *buf, int buflen, void *udata) {
74 static int readpos = 0;
75 int res = 0;
76 uint8_t *ob = (uint8_t *)buf;
77 while (buflen > 0) {
78 if (readpos > outdatalen) {
79 fprintf(stderr, "FATAL: internal packer error!\n");
80 abort();
82 int left = outdatalen-readpos;
83 if (left == 0) break;
84 if (left > buflen) left = buflen;
85 memcpy(ob, outdata+readpos, left);
86 res += left;
87 ob += left;
88 readpos += left;
89 buflen -= left;
91 return res;
95 static int bwrite (const void *buf, int buflen, void *udata) {
96 if (buflen > 0) {
97 growPkData(buflen);
98 memcpy(pkdata+pkdataUsed, buf, buflen);
99 pkdataUsed += buflen;
101 return buflen;
105 ////////////////////////////////////////////////////////////////////////////////
106 static void outStr (const char *str) {
107 memmove(outdata+outdatalen, str, strlen(str));
108 outdatalen += strlen(str);
112 #define EMIT(ch) do { \
113 if (outp-outbuf >= sizeof(outbuf)) fatal("output line too big\n");\
114 *(outp++) = (ch); \
115 } while (0)
118 static inline void normSlashes (char *s) {
119 for (; *s; ++s) if (*s == '\\') *s = '/';
123 static int doDotC = 0, wasScreen, dontStrip = 0, dropSpaces, doCompress = 1;
125 static int lineno = 0;
126 static int inclevel = 0;
127 static const char *srcfname = "<cli>";
129 static void processFile (FILE *fout, const char *fname) {
130 FILE *fin;
131 char *p, *e, quoteCh, *outp;
132 static char buf[32768], outbuf[32768];
133 int olno = lineno;
134 const char *ofn = srcfname;
135 srcfname = fname;
136 lineno = 0;
137 if (++inclevel > 64) {
138 fclose(fout);
139 fprintf(stderr, "FATAL: too many nested includes, failed in file '%s', line %d\n", ofn, olno);
140 exit(1);
142 printf(": %s\n", fname);
143 if (!(fin = fopen(fname, "r"))) {
144 fclose(fout);
145 fprintf(stderr, "FATAL: can't open file '%s', failed in file '%s', line %d\n", fname, ofn, olno);
146 exit(1);
148 if (doDotC) {
149 if (!doCompress) fprintf(fout, "/* %s */\n", fname);
150 } else {
151 outStr("### ");
152 outStr(fname);
153 outStr(" ###\n");
155 while (fgets(buf, sizeof(buf), fin)) {
156 ++lineno;
157 if (buf[0] == '.') {
158 /* include */
159 char *fn, *t;
160 p = buf+1;
161 while (*p && *((unsigned char *)p) <= ' ') ++p;
162 if ((t = strchr(p, '#')) != NULL) *t = '\0';
163 for (t = p+strlen(p); t > p; --t) if (!isspace(t[-1])) break;
164 *t = '\0';
165 if (!p[0]) {
166 fclose(fout);
167 fprintf(stderr, "FATAL: invalid '.' in file '%s', line %d\n", fname, lineno);
168 exit(1);
170 fn = malloc(strlen(p)+strlen(fname)+64);
171 if (!fn) {
172 fclose(fout);
173 fprintf(stderr, "FATAL: out of memory in file '%s', line %d\n", fname, lineno);
174 exit(1);
176 strcpy(fn, fname);
177 normSlashes(fn);
178 if ((t = strrchr(fn, '/')) != NULL) t[1] = '\0'; else fn[0] = '\0';
179 strcat(fn, p);
180 processFile(fout, fn);
181 free(fn);
182 continue;
184 if (doDotC) {
185 #ifdef MKJAMBASE_COMPACT
186 if (!strncmp(buf, "#DONT_TOUCH", 11)) {
187 dontStrip = !dontStrip;
188 continue;
190 #else
191 dontStrip = 1;
192 #endif
193 p = buf;
194 /* strip leading whitespace */
195 if (!dontStrip) {
196 while (*p && *((unsigned char *)p) <= ' ') ++p;
197 /* drop comments and empty lines */
198 if (*p == '#' || !*p) continue;
200 /* copy; drop comments if # is not in quotes */
201 outp = outbuf;
202 quoteCh = 0;
203 wasScreen = 0;
204 if (!doCompress) EMIT('"');
205 dropSpaces = 0;
206 for (; *p && *p != '\n' && *p != '\r'; ++p) {
207 if (!dontStrip) {
208 if (!quoteCh && !wasScreen && *p == '#') break; /* comment follows; drop it */
210 switch (*p) {
211 case '\\':
212 if (!doCompress) EMIT('\\');
213 EMIT('\\');
214 if (quoteCh != '\x27') wasScreen = !wasScreen;
215 dropSpaces = 0;
216 break;
217 case '"':
218 if (!doCompress) EMIT('\\');
219 EMIT('"');
220 if (!wasScreen) quoteCh = (quoteCh == *p ? 0 : *p);
221 dropSpaces = 0;
222 break;
223 case '\x27': /* ' */
224 EMIT('\x27');
225 if (!wasScreen) quoteCh = (quoteCh == *p ? 0 : *p);
226 dropSpaces = 0;
227 break;
228 default:
229 if (!dontStrip && *((unsigned char *)p) <= ' ') {
230 if (wasScreen || !dropSpaces || quoteCh) EMIT(*p);
231 dropSpaces = !quoteCh;
232 } else {
233 EMIT(*p);
234 dropSpaces = 0;
236 wasScreen = 0;
237 break;
240 /* terminate output */
241 *outp = '\0';
242 if (!dontStrip) {
243 /* strip ending whitespace */
244 e = outp-1;
245 while (e >= outbuf && *((unsigned char *)e) <= ' ') --e;
246 *(++e) = '\0';
247 /* drop empty line */
248 if (!outbuf[0]) continue;
250 if (doCompress) {
251 outStr(outbuf);
252 outStr("\n");
253 } else {
254 fprintf(fout, "%s\\n\",\n", outbuf);
256 } else {
257 fprintf(fout, "%s", buf);
258 //outStr(buf);
261 fclose(fin);
262 --inclevel;
263 srcfname = ofn;
264 lineno = olno;
268 int main (int argc, char *argv[]) {
269 FILE *fout;
270 char *p;
272 if (argc < 3) {
273 fprintf(stderr, "usage: %s jambase.c Jambase ...\n", argv[0]);
274 return 1;
277 if (!(fout = fopen(argv[1], "wb"))) {
278 perror(argv[1]);
279 return 1;
282 /* if the file ends in .c generate a C source file */
283 if ((p = strrchr(argv[1], '.')) && !strcmp(p, ".c")) ++doDotC;
285 /* now process the files */
286 argc -= 2, argv += 2;
288 if (doDotC) {
289 fprintf(fout, "/* Generated by mkjambase from Jambase */\n");
290 fprintf(fout, "#include \"jam.h\"\n");
291 if (doCompress) {
292 fprintf(fout, "char **jambase = 0;\n");
293 fprintf(fout, "unsigned char jambasepk[] = {");
294 } else {
295 fprintf(fout, "const char *jambase[] = {\n");
299 for (; argc--; ++argv) processFile(fout, *argv);
301 if (outdatalen > 0) {
302 if (doCompress) {
304 unsigned char *dest;
305 size_t destlen;
306 if (lzCompress(outdata, outdatalen, &dest, &destlen) != 0) {
307 perror("compression error!");
308 return 1;
311 static const libha_io_t haio = {
312 .bread = bread,
313 .bwrite = bwrite,
316 uint32_t n = outdatalen;
317 bwrite(&n, 4, NULL);
319 libha_t ha = libha_alloc(&haio, NULL);
320 if (libha_pack(ha) != 0) {
321 perror("can't pack!");
322 return 1;
324 libha_free(ha);
325 unsigned char *dest = pkdata;
326 size_t destlen = pkdataUsed;
327 printf("%d bytes packed to %u bytes (%u%%)\n", outdatalen, (unsigned int)destlen, (unsigned int)(100*destlen/outdatalen));
328 //fwrite(dest, destlen, 1, fout);
329 int cnt = 0;
330 for (int f = 0; f < destlen; ++f) {
331 if (cnt <= 0) {
332 fputc('\n', fout);
333 cnt = 16;
335 --cnt;
336 fprintf(fout, "0x%02x,", dest[f]);
338 if (cnt > 0) fputc('\n', fout);
339 } else {
340 perror("wtf?!");
341 return 1;
342 //fwrite(outdata, outdatalen, 1, fout);
346 if (doDotC) {
347 if (!doCompress) fputc('0', fout);
348 fprintf(fout, "};\n");
349 if (doCompress) fprintf(fout, "\nJAMFA_CONST int jbpksize (void) { return sizeof(jambasepk); }\n");
352 fclose(fout);
353 return 0;