option.c: fixed warnings
[k8jam.git] / src / mkjambase.c
blobe06cdb449a549d229a5b3427ed2d6726355a10a0
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, 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:
24 * char *jambase[] = {
25 * "...\n",
26 * ...
27 * 0 };
29 * Handles \'s and "'s specially; knows how to delete blank and comment lines.
31 #include <ctype.h>
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
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);
47 exit(1);
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) {
62 if (morebytes > 0) {
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;
74 int res = 0;
75 uint8_t *ob = (uint8_t *)buf;
76 while (buflen > 0) {
77 if (readpos > outdatalen) {
78 fprintf(stderr, "FATAL: internal packer error!\n");
79 abort();
81 int left = outdatalen-readpos;
82 if (left == 0) break;
83 if (left > buflen) left = buflen;
84 memcpy(ob, outdata+readpos, left);
85 res += left;
86 ob += left;
87 readpos += left;
88 buflen -= left;
90 return res;
94 static int bwrite (const void *buf, int buflen, void *udata) {
95 if (buflen > 0) {
96 growPkData(buflen);
97 memcpy(pkdata+pkdataUsed, buf, buflen);
98 pkdataUsed += buflen;
100 return 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");\
113 *(outp++) = (ch); \
114 } while (0)
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) {
129 FILE *fin;
130 char *p, *e, quoteCh, *outp;
131 static char buf[32768], outbuf[32768];
132 int olno = lineno;
133 const char *ofn = srcfname;
134 srcfname = fname;
135 lineno = 0;
136 if (++inclevel > 64) {
137 fclose(fout);
138 fprintf(stderr, "FATAL: too many nested includes, failed in file '%s', line %d\n", ofn, olno);
139 exit(1);
141 printf(": %s\n", fname);
142 if (!(fin = fopen(fname, "r"))) {
143 fclose(fout);
144 fprintf(stderr, "FATAL: can't open file '%s', failed in file '%s', line %d\n", fname, ofn, olno);
145 exit(1);
147 if (doDotC) {
148 if (!doCompress) fprintf(fout, "/* %s */\n", fname);
149 } else {
150 outStr("### ");
151 outStr(fname);
152 outStr(" ###\n");
154 while (fgets(buf, sizeof(buf), fin)) {
155 ++lineno;
156 if (buf[0] == '.') {
157 /* include */
158 char *fn, *t;
159 p = buf+1;
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;
163 *t = '\0';
164 if (!p[0]) {
165 fclose(fout);
166 fprintf(stderr, "FATAL: invalid '.' in file '%s', line %d\n", fname, lineno);
167 exit(1);
169 fn = malloc(strlen(p)+strlen(fname)+64);
170 if (!fn) {
171 fclose(fout);
172 fprintf(stderr, "FATAL: out of memory in file '%s', line %d\n", fname, lineno);
173 exit(1);
175 strcpy(fn, fname);
176 normSlashes(fn);
177 if ((t = strrchr(fn, '/')) != NULL) t[1] = '\0'; else fn[0] = '\0';
178 strcat(fn, p);
179 processFile(fout, fn);
180 free(fn);
181 continue;
183 if (doDotC) {
184 #ifdef MKJAMBASE_COMPACT
185 if (!strncmp(buf, "#DONT_TOUCH", 11)) {
186 dontStrip = !dontStrip;
187 continue;
189 #else
190 dontStrip = 1;
191 #endif
192 p = buf;
193 /* strip leading whitespace */
194 if (!dontStrip) {
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 */
200 outp = outbuf;
201 quoteCh = 0;
202 wasScreen = 0;
203 if (!doCompress) EMIT('"');
204 dropSpaces = 0;
205 for (; *p && *p != '\n' && *p != '\r'; ++p) {
206 if (!dontStrip) {
207 if (!quoteCh && !wasScreen && *p == '#') break; /* comment follows; drop it */
209 switch (*p) {
210 case '\\':
211 if (!doCompress) EMIT('\\');
212 EMIT('\\');
213 if (quoteCh != '\x27') wasScreen = !wasScreen;
214 dropSpaces = 0;
215 break;
216 case '"':
217 if (!doCompress) EMIT('\\');
218 EMIT('"');
219 if (!wasScreen) quoteCh = (quoteCh == *p ? 0 : *p);
220 dropSpaces = 0;
221 break;
222 case '\x27': /* ' */
223 EMIT('\x27');
224 if (!wasScreen) quoteCh = (quoteCh == *p ? 0 : *p);
225 dropSpaces = 0;
226 break;
227 default:
228 if (!dontStrip && *((unsigned char *)p) <= ' ') {
229 if (wasScreen || !dropSpaces || quoteCh) EMIT(*p);
230 dropSpaces = !quoteCh;
231 } else {
232 EMIT(*p);
233 dropSpaces = 0;
235 wasScreen = 0;
236 break;
239 /* terminate output */
240 *outp = '\0';
241 if (!dontStrip) {
242 /* strip ending whitespace */
243 e = outp-1;
244 while (e >= outbuf && *((unsigned char *)e) <= ' ') --e;
245 *(++e) = '\0';
246 /* drop empty line */
247 if (!outbuf[0]) continue;
249 if (doCompress) {
250 outStr(outbuf);
251 outStr("\n");
252 } else {
253 fprintf(fout, "%s\\n\",\n", outbuf);
255 } else {
256 fprintf(fout, "%s", buf);
257 //outStr(buf);
260 fclose(fin);
261 --inclevel;
262 srcfname = ofn;
263 lineno = olno;
267 int main (int argc, char *argv[]) {
268 FILE *fout;
269 char *p;
271 if (argc < 3) {
272 fprintf(stderr, "usage: %s jambase.c Jambase ...\n", argv[0]);
273 return 1;
276 if (!(fout = fopen(argv[1], "wb"))) {
277 perror(argv[1]);
278 return 1;
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;
287 if (doDotC) {
288 fprintf(fout, "/* Generated by mkjambase from Jambase */\n");
289 fprintf(fout, "#include \"jam.h\"\n");
290 if (doCompress) {
291 fprintf(fout, "char **jambase = 0;\n");
292 fprintf(fout, "unsigned char jambasepk[] = {");
293 } else {
294 fprintf(fout, "const char *jambase[] = {\n");
298 for (; argc--; ++argv) processFile(fout, *argv);
300 if (outdatalen > 0) {
301 if (doCompress) {
303 unsigned char *dest;
304 size_t destlen;
305 if (lzCompress(outdata, outdatalen, &dest, &destlen) != 0) {
306 perror("compression error!");
307 return 1;
310 static const libha_io_t haio = {
311 .bread = bread,
312 .bwrite = bwrite,
315 uint32_t n = outdatalen;
316 bwrite(&n, 4, NULL);
318 libha_t ha = libha_alloc(&haio, NULL);
319 if (libha_pack(ha) != 0) {
320 perror("can't pack!");
321 return 1;
323 libha_free(ha);
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);
328 int cnt = 0;
329 for (int f = 0; f < destlen; ++f) {
330 if (cnt <= 0) {
331 fputc('\n', fout);
332 cnt = 16;
334 --cnt;
335 fprintf(fout, "0x%02x,", dest[f]);
337 if (cnt > 0) fputc('\n', fout);
338 } else {
339 perror("wtf?!");
340 return 1;
341 //fwrite(outdata, outdatalen, 1, fout);
345 if (doDotC) {
346 if (!doCompress) fputc('0', fout);
347 fprintf(fout, "};\n");
348 if (doCompress) fprintf(fout, "\nJAMFA_CONST int jbpksize (void) { return sizeof(jambasepk); }\n");
351 fclose(fout);
352 return 0;