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, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * mkjambase.c - turn Jambase into a big C structure
20 * Usage: mkjambase jambase.c Jambase ...
22 * Results look like this:
29 * Handles \'s and "'s specially; knows how to delete blank and comment lines.
38 #include "libhapack.h"
39 #include "libhapack.c"
41 //#define MKJAMBASE_COMPACT
44 ////////////////////////////////////////////////////////////////////////////////
45 static void fatal (const char *msg
) {
46 fprintf(stdout
, "FATAL: %s\n", msg
);
51 static char outdata
[1024*1024];
52 static int outdatalen
= 0;
55 ////////////////////////////////////////////////////////////////////////////////
56 static uint8_t *pkdata
= NULL
;
57 static size_t pkdataSize
= 0;
58 static size_t pkdataUsed
= 0;
61 static void growPkData (int morebytes
) {
63 if (pkdataUsed
+morebytes
> pkdataSize
) {
64 pkdataSize
= (pkdataUsed
+morebytes
)+32768;
65 pkdata
= realloc(pkdata
, pkdataSize
);
66 if (pkdata
== NULL
) abort();
72 static int bread (void *buf
, int buflen
, void *udata
) {
73 static int readpos
= 0;
75 uint8_t *ob
= (uint8_t *)buf
;
77 if (readpos
> outdatalen
) {
78 fprintf(stderr
, "FATAL: internal packer error!\n");
81 int left
= outdatalen
-readpos
;
83 if (left
> buflen
) left
= buflen
;
84 memcpy(ob
, outdata
+readpos
, left
);
94 static int bwrite (const void *buf
, int buflen
, void *udata
) {
97 memcpy(pkdata
+pkdataUsed
, buf
, buflen
);
104 ////////////////////////////////////////////////////////////////////////////////
105 static void outStr (const char *str
) {
106 memmove(outdata
+outdatalen
, str
, strlen(str
));
107 outdatalen
+= strlen(str
);
111 #define EMIT(ch) do { \
112 if (outp-outbuf >= sizeof(outbuf)) fatal("output line too big\n");\
117 static inline void normSlashes (char *s
) {
118 for (; *s
; ++s
) if (*s
== '\\') *s
= '/';
122 static int doDotC
= 0, wasScreen
, dontStrip
= 0, dropSpaces
, doCompress
= 1;
124 static int lineno
= 0;
125 static int inclevel
= 0;
126 static const char *srcfname
= "<cli>";
128 static void processFile (FILE *fout
, const char *fname
) {
130 char *p
, *e
, quoteCh
, *outp
;
131 static char buf
[32768], outbuf
[32768];
133 const char *ofn
= srcfname
;
136 if (++inclevel
> 64) {
138 fprintf(stderr
, "FATAL: too many nested includes, failed in file '%s', line %d\n", ofn
, olno
);
141 printf(": %s\n", fname
);
142 if (!(fin
= fopen(fname
, "r"))) {
144 fprintf(stderr
, "FATAL: can't open file '%s', failed in file '%s', line %d\n", fname
, ofn
, olno
);
148 if (!doCompress
) fprintf(fout
, "/* %s */\n", fname
);
154 while (fgets(buf
, sizeof(buf
), fin
)) {
160 while (*p
&& *((unsigned char *)p
) <= ' ') ++p
;
161 if ((t
= strchr(p
, '#')) != NULL
) *t
= '\0';
162 for (t
= p
+strlen(p
); t
> p
; --t
) if (!isspace(t
[-1])) break;
166 fprintf(stderr
, "FATAL: invalid '.' in file '%s', line %d\n", fname
, lineno
);
169 fn
= malloc(strlen(p
)+strlen(fname
)+64);
172 fprintf(stderr
, "FATAL: out of memory in file '%s', line %d\n", fname
, lineno
);
177 if ((t
= strrchr(fn
, '/')) != NULL
) t
[1] = '\0'; else fn
[0] = '\0';
179 processFile(fout
, fn
);
184 #ifdef MKJAMBASE_COMPACT
185 if (!strncmp(buf
, "#DONT_TOUCH", 11)) {
186 dontStrip
= !dontStrip
;
193 /* strip leading whitespace */
195 while (*p
&& *((unsigned char *)p
) <= ' ') ++p
;
196 /* drop comments and empty lines */
197 if (*p
== '#' || !*p
) continue;
199 /* copy; drop comments if # is not in quotes */
203 if (!doCompress
) EMIT('"');
205 for (; *p
&& *p
!= '\n' && *p
!= '\r'; ++p
) {
207 if (!quoteCh
&& !wasScreen
&& *p
== '#') break; /* comment follows; drop it */
211 if (!doCompress
) EMIT('\\');
213 if (quoteCh
!= '\x27') wasScreen
= !wasScreen
;
217 if (!doCompress
) EMIT('\\');
219 if (!wasScreen
) quoteCh
= (quoteCh
== *p
? 0 : *p
);
224 if (!wasScreen
) quoteCh
= (quoteCh
== *p
? 0 : *p
);
228 if (!dontStrip
&& *((unsigned char *)p
) <= ' ') {
229 if (wasScreen
|| !dropSpaces
|| quoteCh
) EMIT(*p
);
230 dropSpaces
= !quoteCh
;
239 /* terminate output */
242 /* strip ending whitespace */
244 while (e
>= outbuf
&& *((unsigned char *)e
) <= ' ') --e
;
246 /* drop empty line */
247 if (!outbuf
[0]) continue;
253 fprintf(fout
, "%s\\n\",\n", outbuf
);
256 fprintf(fout
, "%s", buf
);
267 int main (int argc
, char *argv
[]) {
272 fprintf(stderr
, "usage: %s jambase.c Jambase ...\n", argv
[0]);
276 if (!(fout
= fopen(argv
[1], "wb"))) {
281 /* if the file ends in .c generate a C source file */
282 if ((p
= strrchr(argv
[1], '.')) && !strcmp(p
, ".c")) ++doDotC
;
284 /* now process the files */
285 argc
-= 2, argv
+= 2;
288 fprintf(fout
, "/* Generated by mkjambase from Jambase */\n");
289 fprintf(fout
, "#include \"jam.h\"\n");
291 fprintf(fout
, "char **jambase = 0;\n");
292 fprintf(fout
, "unsigned char jambasepk[] = {");
294 fprintf(fout
, "const char *jambase[] = {\n");
298 for (; argc
--; ++argv
) processFile(fout
, *argv
);
300 if (outdatalen
> 0) {
305 if (lzCompress(outdata, outdatalen, &dest, &destlen) != 0) {
306 perror("compression error!");
310 static const libha_io_t haio
= {
315 uint32_t n
= outdatalen
;
318 libha_t ha
= libha_alloc(&haio
, NULL
);
319 if (libha_pack(ha
) != 0) {
320 perror("can't pack!");
324 unsigned char *dest
= pkdata
;
325 size_t destlen
= pkdataUsed
;
326 printf("%d bytes packed to %u bytes (%u%%)\n", outdatalen
, (unsigned int)destlen
, (unsigned int)(100*destlen
/outdatalen
));
327 //fwrite(dest, destlen, 1, fout);
329 for (int f
= 0; f
< destlen
; ++f
) {
335 fprintf(fout
, "0x%02x,", dest
[f
]);
337 if (cnt
> 0) fputc('\n', fout
);
341 //fwrite(outdata, outdatalen, 1, fout);
346 if (!doCompress
) fputc('0', fout
);
347 fprintf(fout
, "};\n");
348 if (doCompress
) fprintf(fout
, "\nJAMFA_CONST int jbpksize (void) { return sizeof(jambasepk); }\n");