2 * Ficl softcore generator.
3 * Generates both uncompressed and Lempel-Ziv compressed versions.
4 * Strips blank lines, strips full-line comments, collapses whitespace.
5 * Chops, blends, dices, makes julienne fries.
7 * Contributed by Larry Hastings, larry@hastings.org
17 #define SOFTCORE_OUT "softcore.c"
21 lz4_compress(void *s_start
, void *d_start
, size_t s_len
, size_t d_len
, int n
);
24 fprintDataAsHex(FILE *f
, unsigned char *data
, int length
)
29 for (i
= 0; (i
< 8) && length
; i
++) {
32 * if you don't do this little stuff, you get ugly
33 * sign-extended 0xFFFFFF6b crap.
35 sprintf(buf
, "%08x", (unsigned int)*data
++);
36 fprintf(f
, "0x%s, ", buf
+ 6);
44 fprintDataAsQuotedString(FILE *f
, char *data
)
46 int lineIsBlank
= 1; /* true */
51 fprintf(f
, "\\n\"\n");
52 lineIsBlank
= 1; /* true */
57 lineIsBlank
= 0; /* false */
62 else if (*data
== '\\')
74 main(int argc
, char *argv
[])
76 char *uncompressed
= (char *)malloc(128 * 1024);
77 unsigned char *compressed
= malloc(128 * 1024);
78 char *trace
= uncompressed
;
80 size_t compressedSize
= 128 * 1024;
81 size_t uncompressedSize
;
85 struct tm
*currentTime
;
89 currentTime
= localtime(¤tTimeT
);
90 strftime(cleverTime
, sizeof (cleverTime
),
91 "%Y/%m/%d %H:%M:%S", currentTime
);
95 for (i
= 1; i
< argc
; i
++) {
98 * This ensures there's always whitespace space between files.
99 * It *also* ensures that src[-1] is always safe in comment
100 * detection code below. (Any leading whitespace will be
101 * thrown away in a later pass.)
106 f
= fopen(argv
[i
], "rb");
107 fseek(f
, 0, SEEK_END
);
109 fseek(f
, 0, SEEK_SET
);
110 fread(trace
, 1, size
, f
);
116 #define IS_EOL(x) ((*x == '\n') || (*x == '\r'))
117 #define IS_EOL_COMMENT(x) \
118 (((x[0] == '\\') && isspace(x[1])) || \
119 ((x[0] == '/') && (x[1] == '/') && isspace(x[2])))
120 #define IS_BLOCK_COMMENT(x) \
121 ((x[0] == '(') && isspace(x[1]) && isspace(x[-1]))
123 src
= dst
= uncompressed
;
125 /* ignore leading whitespace, or entirely blank lines */
126 while (isspace(*src
))
128 /* if the line is commented out */
129 if (IS_EOL_COMMENT(src
)) {
130 /* throw away this entire line */
131 while (*src
&& !IS_EOL(src
))
136 * This is where we'd throw away mid-line comments, but
137 * that's simply unsafe. Things like
141 * get broken that way.
144 while (*src
&& !IS_EOL(src
)) {
148 /* strip trailing whitespace */
150 while (isspace(*dst
))
154 /* and end the line */
161 * now make a second pass to collapse all contiguous whitespace
164 src
= dst
= uncompressed
;
170 while (isspace(*src
))
176 f
= fopen(SOFTCORE_OUT
, "wt");
178 printf("couldn't open " SOFTCORE_OUT
179 " for writing! giving up.\n");
186 "** both uncompressed and LZ4 compressed versions.\n"
191 "#include \"ficl.h\"\n"
195 uncompressedSize
= dst
- uncompressed
;
196 compressedSize
= lz4_compress(uncompressed
, compressed
,
197 uncompressedSize
, compressedSize
, 0);
199 fprintf(f
, "static size_t ficlSoftcoreUncompressedSize = %d; "
200 "/* not including trailing null */\n", uncompressedSize
);
202 fprintf(f
, "#if !FICL_WANT_LZ4_SOFTCORE\n");
204 fprintf(f
, "static char ficlSoftcoreUncompressed[] =\n");
205 fprintDataAsQuotedString(f
, uncompressed
);
208 fprintf(f
, "#else /* !FICL_WANT_LZ4_SOFTCORE */\n");
210 fprintf(f
, "extern int lz4_decompress(void *, void *, size_t, "
211 "size_t, int);\n\n");
212 fprintf(f
, "static unsigned char ficlSoftcoreCompressed[%d] = "
213 "{\n", compressedSize
);
214 fprintDataAsHex(f
, compressed
, compressedSize
);
215 fprintf(f
, "\t};\n");
217 fprintf(f
, "#endif /* !FICL_WANT_LZ4_SOFTCORE */\n");
221 "void ficlSystemCompileSoftCore(ficlSystem *system)\n"
223 " ficlVm *vm = system->vmList;\n"
224 " int returnValue;\n"
225 " ficlCell oldSourceID = vm->sourceId;\n"
227 "#if FICL_WANT_LZ4_SOFTCORE\n"
228 " char *ficlSoftcoreUncompressed = malloc(ficlSoftcoreUncompressedSize+1);\n"
229 " returnValue = lz4_decompress(ficlSoftcoreCompressed, "
230 "ficlSoftcoreUncompressed, sizeof(ficlSoftcoreCompressed), "
231 "ficlSoftcoreUncompressedSize+1, 0);\n"
232 " FICL_VM_ASSERT(vm, returnValue == 0);\n"
233 "#endif /* FICL_WANT_LZ4_SOFTCORE */\n"
234 " vm->sourceId.i = -1;\n"
235 " FICL_STRING_SET_POINTER(s, (char *)(ficlSoftcoreUncompressed));\n"
236 " FICL_STRING_SET_LENGTH(s, ficlSoftcoreUncompressedSize);\n"
237 " returnValue = ficlVmExecuteString(vm, s);\n"
238 " vm->sourceId = oldSourceID;\n"
239 "#if FICL_WANT_LZ4_SOFTCORE\n"
240 " free(ficlSoftcoreUncompressed);\n"
241 "#endif /* FICL_WANT_LZ4_SOFTCORE */\n"
242 " FICL_VM_ASSERT(vm, returnValue != FICL_VM_STATUS_ERROR_EXIT);\n"
245 "/* end-of-file */\n");