fixed 'install' target
[k8jam.git] / src / mkjambase.c
blob6b787e1092bf4678f16d8bfe54aeddd0053c382b
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 <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
29 //#define MKJAMBASE_COMPACT
32 static void fatal (const char *msg) {
33 fprintf(stdout, "FATAL: %s\n", msg);
34 exit(1);
38 #define EMIT(ch) do { \
39 if (outp-outbuf >= sizeof(outbuf)) fatal("output line too big\n");\
40 *(outp++) = (ch); \
41 } while (0)
44 static inline void normSlashes (char *s) {
45 for (; *s; ++s) if (*s == '\\') *s = '/';
49 static int doDotC = 0, wasScreen, dontStrip = 0, dropSpaces;
51 static int lineno = 0;
52 static int inclevel = 0;
53 static const char *srcfname = "<cli>";
55 static void processFile (FILE *fout, const char *fname) {
56 FILE *fin;
57 char *p, *e, quoteCh, *outp;
58 static char buf[32768], outbuf[32768];
59 int olno = lineno;
60 const char *ofn = srcfname;
62 srcfname = fname;
63 lineno = 0;
65 if (++inclevel > 64) {
66 fclose(fout);
67 fprintf(stderr, "FATAL: too many nested includes, failed in file '%s', line %d\n", ofn, olno);
68 exit(1);
71 printf(": %s\n", fname);
72 if (!(fin = fopen(fname, "r"))) {
73 fclose(fout);
74 fprintf(stderr, "FATAL: can't open file '%s', failed in file '%s', line %d\n", fname, ofn, olno);
75 exit(1);
77 if (doDotC) fprintf(fout, "/* %s */\n", fname); else fprintf(fout, "### %s ###\n", fname);
79 while (fgets(buf, sizeof(buf), fin)) {
80 ++lineno;
82 if (buf[0] == '.') {
83 /* include */
84 char *fn, *t;
86 p = buf+1;
87 while (*p && *((unsigned char *)p) <= ' ') ++p;
88 if ((t = strchr(p, '#')) != NULL) *t = '\0';
89 for (t = p+strlen(p); t > p; --t) if (!isspace(t[-1])) break;
90 *t = '\0';
91 if (!p[0]) {
92 fclose(fout);
93 fprintf(stderr, "FATAL: invalid '.' in file '%s', line %d\n", fname, lineno);
94 exit(1);
96 fn = malloc(strlen(p)+strlen(fname)+64);
97 if (!fn) {
98 fclose(fout);
99 fprintf(stderr, "FATAL: out of memory in file '%s', line %d\n", fname, lineno);
100 exit(1);
102 strcpy(fn, fname);
103 normSlashes(fn);
104 if ((t = strrchr(fn, '/')) != NULL) t[1] = '\0'; else fn[0] = '\0';
105 strcat(fn, p);
106 processFile(fout, fn);
107 free(fn);
108 continue;
111 if (doDotC) {
112 #ifdef MKJAMBASE_COMPACT
113 if (!strncmp(buf, "#DONT_TOUCH", 11)) {
114 dontStrip = !dontStrip;
115 continue;
117 #else
118 dontStrip = 1;
119 #endif
120 p = buf;
121 /* strip leading whitespace */
122 if (!dontStrip) {
123 while (*p && *((unsigned char *)p) <= ' ') ++p;
124 /* drop comments and empty lines */
125 if (*p == '#' || !*p) continue;
127 /* copy; drop comments if # is not in quotes */
128 outp = outbuf; quoteCh = 0; wasScreen = 0;
129 EMIT('"');
130 dropSpaces = 0;
131 for (; *p && *p != '\n' && *p != '\r'; p++) {
132 if (!dontStrip) {
133 if (!quoteCh && !wasScreen && *p == '#') break; /* comment follows; drop it */
135 switch (*p) {
136 case '\\':
137 EMIT('\\'); EMIT('\\');
138 wasScreen = !wasScreen;
139 dropSpaces = 0;
140 break;
141 case '"':
142 EMIT('\\'); EMIT('"');
143 if (!wasScreen) quoteCh = (quoteCh==*p)?0:*p;
144 dropSpaces = 0;
145 break;
146 case '\x27': /* ' */
147 EMIT('\x27');
148 if (!wasScreen) quoteCh = (quoteCh==*p)?0:*p;
149 dropSpaces = 0;
150 break;
151 default:
152 if (!dontStrip && *((unsigned char *)p) <= ' ') {
153 if (wasScreen || !dropSpaces || quoteCh) EMIT(*p);
154 dropSpaces = !quoteCh;
155 } else {
156 EMIT(*p);
157 dropSpaces = 0;
159 wasScreen = 0;
160 break;
163 /* terminate output */
164 *outp = '\0';
165 if (!dontStrip) {
166 /* strip ending whitespace */
167 e = outp-1;
168 while (e >= outbuf && *((unsigned char *)e) <= ' ') --e;
169 *(++e) = '\0';
170 /* drop empty line */
171 if (!outbuf[0]) continue;
173 fprintf(fout, "%s\\n\",\n", outbuf);
174 } else {
175 fprintf(fout, "%s", buf);
178 fclose(fin);
179 --inclevel;
180 srcfname = ofn;
181 lineno = olno;
185 int main (int argc, char *argv[]) {
186 FILE *fout;
187 char *p;
189 if (argc < 3) {
190 fprintf(stderr, "usage: %s jambase.c Jambase ...\n", argv[0]);
191 return 1;
194 if (!(fout = fopen(argv[1], "w"))) {
195 perror(argv[1]);
196 return 1;
199 /* if the file ends in .c generate a C source file */
200 if ((p = strrchr(argv[1], '.')) && !strcmp(p, ".c")) ++doDotC;
202 /* now process the files */
203 argc -= 2, argv += 2;
205 if (doDotC) {
206 fprintf(fout, "/* Generated by mkjambase from Jambase */\n");
207 fprintf(fout, "const char *jambase[] = {\n");
210 for (; argc--; ++argv) processFile(fout, *argv);
212 if (doDotC) fprintf(fout, "0};\n");
213 fclose(fout);
215 return 0;