summaryrefslogtreecommitdiff
path: root/softcore/makesoftcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'softcore/makesoftcore.c')
-rw-r--r--softcore/makesoftcore.c244
1 files changed, 244 insertions, 0 deletions
diff --git a/softcore/makesoftcore.c b/softcore/makesoftcore.c
new file mode 100644
index 000000000000..090e2cddd10c
--- /dev/null
+++ b/softcore/makesoftcore.c
@@ -0,0 +1,244 @@
+/*
+** Ficl softcore generator.
+** Generates both uncompressed and Lempel-Ziv compressed versions.
+** Strips blank lines, strips full-line comments, collapses whitespace.
+** Chops, blends, dices, makes julienne fries.
+**
+** Contributed by Larry Hastings, larry@hastings.org
+**/
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "ficl.h"
+
+
+#ifndef SOFTCORE_OUT
+#define SOFTCORE_OUT "../softcore.c"
+#endif
+
+void fprintDataAsHex(FILE *f, char *data, int length)
+ {
+ int i;
+ while (length)
+ {
+ fprintf(f, "\t");
+ for (i = 0; (i < 8) && length; i++)
+ {
+ char buf[16];
+ /* if you don't do this little stuff, you get ugly sign-extended 0xFFFFFF6b crap. */
+ sprintf(buf, "%08x", (unsigned int)*data++);
+ fprintf(f, "0x%s, ", buf + 6);
+ length--;
+ }
+ fprintf(f, "\n");
+ }
+ }
+
+void fprintDataAsQuotedString(FILE *f, char *data)
+ {
+ int i;
+ int lineIsBlank = 1; /* true */
+
+ while (*data)
+ {
+ if (*data == '\n')
+ {
+ if (!lineIsBlank)
+ fprintf(f, "\\n\"\n");
+ lineIsBlank = 1; /* true */
+ }
+ else
+ {
+ if (lineIsBlank)
+ {
+ fputc('\t', f);
+ fputc('"', f);
+ lineIsBlank = 0; /* false */
+ }
+
+ if (*data == '"')
+ fprintf(f, "\\\"");
+ else if (*data == '\\')
+ fprintf(f, "\\\\");
+ else
+ fputc(*data, f);
+ }
+ data++;
+ }
+ if (!lineIsBlank)
+ fprintf(f, "\"");
+ }
+
+int main(int argc, char *argv[])
+ {
+ char *uncompressed = (char *)malloc(128 * 1024);
+ unsigned char *compressed;
+ char *trace = uncompressed;
+ int i;
+ size_t compressedSize;
+ size_t uncompressedSize;
+ char *src, *dst;
+ FILE *f;
+ time_t currentTimeT;
+ struct tm *currentTime;
+ char cleverTime[32];
+
+ time(&currentTimeT);
+ currentTime = localtime(&currentTimeT);
+ strftime(cleverTime, sizeof(cleverTime), "%Y/%m/%d %H:%M:%S", currentTime);
+
+ *trace++ = ' ';
+
+ for (i = 1; i < argc; i++)
+ {
+ int size;
+ /*
+ ** This ensures there's always whitespace space between files. It *also*
+ ** ensures that src[-1] is always safe in comment detection code below.
+ ** (Any leading whitespace will be thrown away in a later pass.)
+ ** --lch
+ */
+ *trace++ = ' ';
+
+ f = fopen(argv[i], "rb");
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ fread(trace, 1, size, f);
+ fclose(f);
+ trace += size;
+ }
+ *trace = 0;
+
+#define IS_EOL(x) ((*x == '\n') || (*x == '\r'))
+#define IS_EOL_COMMENT(x) (((x[0] == '\\') && isspace(x[1])) || ((x[0] == '/') && (x[1] == '/') && isspace(x[2])))
+#define IS_BLOCK_COMMENT(x) ((x[0] == '(') && isspace(x[1]) && isspace(x[-1]))
+
+ src = dst = uncompressed;
+ while (*src)
+ {
+ /* ignore leading whitespace, or entirely blank lines */
+ while (isspace(*src))
+ src++;
+ /* if the line is commented out */
+ if (IS_EOL_COMMENT(src))
+ {
+ /* throw away this entire line */
+ while (*src && !IS_EOL(src))
+ src++;
+ continue;
+ }
+ /*
+ ** This is where we'd throw away mid-line comments, but
+ ** that's simply unsafe. Things like
+ ** start-prefixes
+ ** : \ postpone \ ;
+ ** : ( postpone ( ;
+ ** get broken that way.
+ ** --lch
+ */
+ while (*src && !IS_EOL(src))
+ {
+ *dst++ = *src++;
+ }
+
+ /* strip trailing whitespace */
+ dst--;
+ while (isspace(*dst))
+ dst--;
+ dst++;
+
+ /* and end the line */
+ *dst++ = '\n';
+ }
+
+ *dst = 0;
+
+ /* now make a second pass to collapse all contiguous whitespace to a single space. */
+ src = dst = uncompressed;
+ while (*src)
+ {
+ *dst++ = *src;
+ if (!isspace(*src))
+ src++;
+ else
+ {
+ while (isspace(*src))
+ src++;
+ }
+ }
+ *dst = 0;
+
+ f = fopen(SOFTCORE_OUT, "wt");
+ if (f == NULL)
+ {
+ printf("couldn't open " SOFTCORE_OUT " for writing! giving up.\n");
+ exit(-1);
+ }
+
+ fprintf(f,
+"/*\n"
+"** Ficl softcore\n"
+"** both uncompressed and Lempel-Ziv compressed versions.\n"
+"**\n"
+"** Generated %s\n"
+"**/\n"
+"\n"
+"#include \"ficl.h\"\n"
+"\n"
+"\n",
+ cleverTime);
+
+ uncompressedSize = dst - uncompressed;
+ ficlLzCompress(uncompressed, uncompressedSize, &compressed, &compressedSize);
+
+ fprintf(f, "static size_t ficlSoftcoreUncompressedSize = %d; /* not including trailing null */\n", uncompressedSize);
+ fprintf(f, "\n");
+ fprintf(f, "#if !FICL_WANT_LZ_SOFTCORE\n");
+ fprintf(f, "\n");
+ fprintf(f, "static char ficlSoftcoreUncompressed[] =\n");
+ fprintDataAsQuotedString(f, uncompressed);
+ fprintf(f, ";\n");
+ fprintf(f, "\n");
+ fprintf(f, "#else /* !FICL_WANT_LZ_SOFTCORE */\n");
+ fprintf(f, "\n");
+ fprintf(f, "static unsigned char ficlSoftcoreCompressed[%d] = {\n", compressedSize);
+ fprintDataAsHex(f, compressed, compressedSize);
+ fprintf(f, "\t};\n");
+ fprintf(f, "\n");
+ fprintf(f, "#endif /* !FICL_WANT_LZ_SOFTCORE */\n");
+ fprintf(f,
+"\n"
+"\n"
+"void ficlSystemCompileSoftCore(ficlSystem *system)\n"
+"{\n"
+" ficlVm *vm = system->vmList;\n"
+" int returnValue;\n"
+" ficlCell oldSourceID = vm->sourceId;\n"
+" ficlString s;\n"
+"#if FICL_WANT_LZ_SOFTCORE\n"
+" char *ficlSoftcoreUncompressed = NULL;\n"
+" size_t gotUncompressedSize = 0;\n"
+" returnValue = ficlLzUncompress(ficlSoftcoreCompressed, (unsigned char **)&ficlSoftcoreUncompressed, &gotUncompressedSize);\n"
+" FICL_VM_ASSERT(vm, returnValue == 0);\n"
+" FICL_VM_ASSERT(vm, gotUncompressedSize == ficlSoftcoreUncompressedSize);\n"
+"#endif /* FICL_WANT_LZ_SOFTCORE */\n"
+" vm->sourceId.i = -1;\n"
+" FICL_STRING_SET_POINTER(s, (char *)(ficlSoftcoreUncompressed));\n"
+" FICL_STRING_SET_LENGTH(s, ficlSoftcoreUncompressedSize);\n"
+" returnValue = ficlVmExecuteString(vm, s);\n"
+" vm->sourceId = oldSourceID;\n"
+"#if FICL_WANT_LZ_SOFTCORE\n"
+" free(ficlSoftcoreUncompressed);\n"
+"#endif /* FICL_WANT_LZ_SOFTCORE */\n"
+" FICL_VM_ASSERT(vm, returnValue != FICL_VM_STATUS_ERROR_EXIT);\n"
+" return;\n"
+"}\n"
+"\n"
+"/* end-of-file */\n"
+ );
+ free(uncompressed);
+ free(compressed);
+ }