using new string modifiers in Jambase
[k8jam.git] / src / mkjambase.c
blob968ad93d3dee4bb00f442603ff076aee21c2493c
1 /*
2 * Copyright 1993, 1995 Christopher Seiwald.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
7 /*
8 * mkjambase.c - turn Jambase into a big C structure
10 * Usage: mkjambase jambase.c Jambase ...
12 * Results look like this:
14 * char *jambase[] = {
15 * "...\n",
16 * ...
17 * 0 };
19 * Handles \'s and "'s specially; knows how to delete blank and comment lines.
21 * 11/04/02 (seiwald) - const-ing for string literals
23 #include <ctype.h>
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
30 #include "lzpack.c"
32 //#define MKJAMBASE_COMPACT
35 ////////////////////////////////////////////////////////////////////////////////
36 static void fatal (const char *msg) {
37 fprintf(stdout, "FATAL: %s\n", msg);
38 exit(1);
42 static char outdata[1024*1024];
43 static int outdatalen = 0;
46 static void outStr (const char *str) {
47 memmove(outdata+outdatalen, str, strlen(str));
48 outdatalen += strlen(str);
52 #define EMIT(ch) do { \
53 if (outp-outbuf >= sizeof(outbuf)) fatal("output line too big\n");\
54 *(outp++) = (ch); \
55 } while (0)
58 static inline void normSlashes (char *s) {
59 for (; *s; ++s) if (*s == '\\') *s = '/';
63 static int doDotC = 0, wasScreen, dontStrip = 0, dropSpaces, doCompress = 1;
65 static int lineno = 0;
66 static int inclevel = 0;
67 static const char *srcfname = "<cli>";
69 static void processFile (FILE *fout, const char *fname) {
70 FILE *fin;
71 char *p, *e, quoteCh, *outp;
72 static char buf[32768], outbuf[32768];
73 int olno = lineno;
74 const char *ofn = srcfname;
76 srcfname = fname;
77 lineno = 0;
79 if (++inclevel > 64) {
80 fclose(fout);
81 fprintf(stderr, "FATAL: too many nested includes, failed in file '%s', line %d\n", ofn, olno);
82 exit(1);
85 printf(": %s\n", fname);
86 if (!(fin = fopen(fname, "r"))) {
87 fclose(fout);
88 fprintf(stderr, "FATAL: can't open file '%s', failed in file '%s', line %d\n", fname, ofn, olno);
89 exit(1);
91 if (doDotC) {
92 if (!doCompress) fprintf(fout, "/* %s */\n", fname);
93 } else {
94 outStr("### ");
95 outStr(fname);
96 outStr(" ###\n");
99 while (fgets(buf, sizeof(buf), fin)) {
100 ++lineno;
102 if (buf[0] == '.') {
103 /* include */
104 char *fn, *t;
106 p = buf+1;
107 while (*p && *((unsigned char *)p) <= ' ') ++p;
108 if ((t = strchr(p, '#')) != NULL) *t = '\0';
109 for (t = p+strlen(p); t > p; --t) if (!isspace(t[-1])) break;
110 *t = '\0';
111 if (!p[0]) {
112 fclose(fout);
113 fprintf(stderr, "FATAL: invalid '.' in file '%s', line %d\n", fname, lineno);
114 exit(1);
116 fn = malloc(strlen(p)+strlen(fname)+64);
117 if (!fn) {
118 fclose(fout);
119 fprintf(stderr, "FATAL: out of memory in file '%s', line %d\n", fname, lineno);
120 exit(1);
122 strcpy(fn, fname);
123 normSlashes(fn);
124 if ((t = strrchr(fn, '/')) != NULL) t[1] = '\0'; else fn[0] = '\0';
125 strcat(fn, p);
126 processFile(fout, fn);
127 free(fn);
128 continue;
131 if (doDotC) {
132 #ifdef MKJAMBASE_COMPACT
133 if (!strncmp(buf, "#DONT_TOUCH", 11)) {
134 dontStrip = !dontStrip;
135 continue;
137 #else
138 dontStrip = 1;
139 #endif
140 p = buf;
141 /* strip leading whitespace */
142 if (!dontStrip) {
143 while (*p && *((unsigned char *)p) <= ' ') ++p;
144 /* drop comments and empty lines */
145 if (*p == '#' || !*p) continue;
147 /* copy; drop comments if # is not in quotes */
148 outp = outbuf; quoteCh = 0; wasScreen = 0;
149 if (!doCompress) EMIT('"');
150 dropSpaces = 0;
151 for (; *p && *p != '\n' && *p != '\r'; p++) {
152 if (!dontStrip) {
153 if (!quoteCh && !wasScreen && *p == '#') break; /* comment follows; drop it */
155 switch (*p) {
156 case '\\':
157 if (!doCompress) EMIT('\\');
158 EMIT('\\');
159 wasScreen = !wasScreen;
160 dropSpaces = 0;
161 break;
162 case '"':
163 if (!doCompress) EMIT('\\');
164 EMIT('"');
165 if (!wasScreen) quoteCh = (quoteCh==*p)?0:*p;
166 dropSpaces = 0;
167 break;
168 case '\x27': /* ' */
169 EMIT('\x27');
170 if (!wasScreen) quoteCh = (quoteCh==*p)?0:*p;
171 dropSpaces = 0;
172 break;
173 default:
174 if (!dontStrip && *((unsigned char *)p) <= ' ') {
175 if (wasScreen || !dropSpaces || quoteCh) EMIT(*p);
176 dropSpaces = !quoteCh;
177 } else {
178 EMIT(*p);
179 dropSpaces = 0;
181 wasScreen = 0;
182 break;
185 /* terminate output */
186 *outp = '\0';
187 if (!dontStrip) {
188 /* strip ending whitespace */
189 e = outp-1;
190 while (e >= outbuf && *((unsigned char *)e) <= ' ') --e;
191 *(++e) = '\0';
192 /* drop empty line */
193 if (!outbuf[0]) continue;
195 if (doCompress) {
196 outStr(outbuf);
197 outStr("\n");
198 } else {
199 fprintf(fout, "%s\\n\",\n", outbuf);
201 } else {
202 fprintf(fout, "%s", buf);
203 //outStr(buf);
206 fclose(fin);
207 --inclevel;
208 srcfname = ofn;
209 lineno = olno;
213 int main (int argc, char *argv[]) {
214 FILE *fout;
215 char *p;
217 if (argc < 3) {
218 fprintf(stderr, "usage: %s jambase.c Jambase ...\n", argv[0]);
219 return 1;
222 if (!(fout = fopen(argv[1], "wb"))) {
223 perror(argv[1]);
224 return 1;
227 /* if the file ends in .c generate a C source file */
228 if ((p = strrchr(argv[1], '.')) && !strcmp(p, ".c")) ++doDotC;
230 /* now process the files */
231 argc -= 2, argv += 2;
233 if (doDotC) {
234 fprintf(fout, "/* Generated by mkjambase from Jambase */\n");
235 fprintf(fout, "#include \"jam.h\"\n");
236 if (doCompress) {
237 fprintf(fout, "char **jambase = 0;\n");
238 fprintf(fout, "unsigned char jambasepk[] = {");
239 } else {
240 fprintf(fout, "const char *jambase[] = {\n");
244 for (; argc--; ++argv) processFile(fout, *argv);
246 if (outdatalen > 0) {
247 if (doCompress) {
248 unsigned char *dest;
249 size_t destlen;
250 int cnt = 0;
252 if (lzCompress(outdata, outdatalen, &dest, &destlen) != 0) {
253 perror("compression error!");
254 return 1;
256 printf("%d bytes packed to %u bytes (%u%%)\n", outdatalen, (unsigned int)destlen, (unsigned int)(100*destlen/outdatalen));
257 //fwrite(dest, destlen, 1, fout);
258 for (int f = 0; f < destlen; ++f) {
259 if (cnt <= 0) {
260 fputc('\n', fout);
261 cnt = 16;
263 --cnt;
264 fprintf(fout, "0x%02x,", dest[f]);
266 if (cnt > 0) fputc('\n', fout);
267 } else {
268 perror("wtf?!");
269 return 1;
270 //fwrite(outdata, outdatalen, 1, fout);
274 if (doDotC) {
275 if (!doCompress) fputc('0', fout);
276 fprintf(fout, "};\n");
277 if (doCompress) fprintf(fout, "\nJAMFA_CONST int jbpksize (void) { return sizeof(jambasepk); }\n");
280 fclose(fout);
281 return 0;