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;
}