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:
30 * Handles \'s and "'s specially; knows how to delete blank and comment lines.
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
);
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
) {
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;
76 uint8_t *ob
= (uint8_t *)buf
;
78 if (readpos
> outdatalen
) {
79 fprintf(stderr
, "FATAL: internal packer error!\n");
82 int left
= outdatalen
-readpos
;
84 if (left
> buflen
) left
= buflen
;
85 memcpy(ob
, outdata
+readpos
, left
);
95 static int bwrite (const void *buf
, int buflen
, void *udata
) {
98 memcpy(pkdata
+pkdataUsed
, buf
, 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");\
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
) {
131 char *p
, *e
, quoteCh
, *outp
;
132 static char buf
[32768], outbuf
[32768];
134 const char *ofn
= srcfname
;
137 if (++inclevel
> 64) {
139 fprintf(stderr
, "FATAL: too many nested includes, failed in file '%s', line %d\n", ofn
, olno
);
142 printf(": %s\n", fname
);
143 if (!(fin
= fopen(fname
, "r"))) {
145 fprintf(stderr
, "FATAL: can't open file '%s', failed in file '%s', line %d\n", fname
, ofn
, olno
);
149 if (!doCompress
) fprintf(fout
, "/* %s */\n", fname
);
155 while (fgets(buf
, sizeof(buf
), fin
)) {
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;
167 fprintf(stderr
, "FATAL: invalid '.' in file '%s', line %d\n", fname
, lineno
);
170 fn
= malloc(strlen(p
)+strlen(fname
)+64);
173 fprintf(stderr
, "FATAL: out of memory in file '%s', line %d\n", fname
, lineno
);
178 if ((t
= strrchr(fn
, '/')) != NULL
) t
[1] = '\0'; else fn
[0] = '\0';
180 processFile(fout
, fn
);
185 #ifdef MKJAMBASE_COMPACT
186 if (!strncmp(buf
, "#DONT_TOUCH", 11)) {
187 dontStrip
= !dontStrip
;
194 /* strip leading whitespace */
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 */
204 if (!doCompress
) EMIT('"');
206 for (; *p
&& *p
!= '\n' && *p
!= '\r'; ++p
) {
208 if (!quoteCh
&& !wasScreen
&& *p
== '#') break; /* comment follows; drop it */
212 if (!doCompress
) EMIT('\\');
214 if (quoteCh
!= '\x27') wasScreen
= !wasScreen
;
218 if (!doCompress
) EMIT('\\');
220 if (!wasScreen
) quoteCh
= (quoteCh
== *p
? 0 : *p
);
225 if (!wasScreen
) quoteCh
= (quoteCh
== *p
? 0 : *p
);
229 if (!dontStrip
&& *((unsigned char *)p
) <= ' ') {
230 if (wasScreen
|| !dropSpaces
|| quoteCh
) EMIT(*p
);
231 dropSpaces
= !quoteCh
;
240 /* terminate output */
243 /* strip ending whitespace */
245 while (e
>= outbuf
&& *((unsigned char *)e
) <= ' ') --e
;
247 /* drop empty line */
248 if (!outbuf
[0]) continue;
254 fprintf(fout
, "%s\\n\",\n", outbuf
);
257 fprintf(fout
, "%s", buf
);
268 int main (int argc
, char *argv
[]) {
273 fprintf(stderr
, "usage: %s jambase.c Jambase ...\n", argv
[0]);
277 if (!(fout
= fopen(argv
[1], "wb"))) {
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;
289 fprintf(fout
, "/* Generated by mkjambase from Jambase */\n");
290 fprintf(fout
, "#include \"jam.h\"\n");
292 fprintf(fout
, "char **jambase = 0;\n");
293 fprintf(fout
, "unsigned char jambasepk[] = {");
295 fprintf(fout
, "const char *jambase[] = {\n");
299 for (; argc
--; ++argv
) processFile(fout
, *argv
);
301 if (outdatalen
> 0) {
306 if (lzCompress(outdata, outdatalen, &dest, &destlen) != 0) {
307 perror("compression error!");
311 static const libha_io_t haio
= {
316 uint32_t n
= outdatalen
;
319 libha_t ha
= libha_alloc(&haio
, NULL
);
320 if (libha_pack(ha
) != 0) {
321 perror("can't pack!");
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);
330 for (int f
= 0; f
< destlen
; ++f
) {
336 fprintf(fout
, "0x%02x,", dest
[f
]);
338 if (cnt
> 0) fputc('\n', fout
);
342 //fwrite(outdata, outdatalen, 1, fout);
347 if (!doCompress
) fputc('0', fout
);
348 fprintf(fout
, "};\n");
349 if (doCompress
) fprintf(fout
, "\nJAMFA_CONST int jbpksize (void) { return sizeof(jambasepk); }\n");