ref: 7d02e382d314d5bdde7978ccb7a64ea9201d03db
dir: /softcore/makesoftcore.c/
/* ** 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++) { /* if you don't do this little stuff, you get ugly sign-extended 0xFFFFFF6b crap. */ fprintf(f, "0x%02x, ", (unsigned)*(unsigned char*)data++); 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(¤tTimeT); currentTime = localtime(¤tTimeT); 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, (char*)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, &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); return 0; }