mirror of
https://github.com/g012/l65.git
synced 2024-12-29 16:29:15 +00:00
ce2737c353
Added lpeg's re.lua lib. Added dkjson.lua. Added parser for TIATracker .ttt files.
201 lines
6.5 KiB
C
201 lines
6.5 KiB
C
#define LUA_IMPLEMENTATION
|
|
#include "lua.h"
|
|
|
|
#define PROGNAME "embed" /* default program name */
|
|
#define OUTPUT "scripts.h" /* default output file */
|
|
|
|
static int dumping = 1; /* dump bytecodes? */
|
|
static int stripping = 0; /* strip debug information? */
|
|
static char Output[] = { OUTPUT }; /* default output file name */
|
|
static const char* output = Output; /* actual output file name */
|
|
static const char* progname = PROGNAME; /* actual program name */
|
|
|
|
static void fatal(const char* message)
|
|
{
|
|
fprintf(stderr, "%s: %s\n", progname, message);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
static void cannot(const char* what)
|
|
{
|
|
fprintf(stderr, "%s: cannot %s %s: %s\n", progname, what, output, strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
static void usage(const char* message)
|
|
{
|
|
if (*message == '-')
|
|
fprintf(stderr, "%s: unrecognized option '%s'\n", progname, message);
|
|
else
|
|
fprintf(stderr, "%s: %s\n", progname, message);
|
|
fprintf(stderr,
|
|
"usage: %s [options] [filenames]\n"
|
|
"Available options are:\n"
|
|
" -o name output to file 'name' (default is \"%s\")\n"
|
|
, progname, Output);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
#define IS(s) (strcmp(argv[i],s)==0)
|
|
|
|
static int doargs(int argc, char* argv[])
|
|
{
|
|
int i;
|
|
if (argv[0] != NULL && *argv[0] != 0) progname = argv[0];
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (*argv[i] != '-') /* end of options; keep it */
|
|
break;
|
|
else if (IS("--")) /* end of options; skip it */
|
|
{
|
|
++i;
|
|
break;
|
|
}
|
|
else if (IS("-")) /* end of options; use stdin */
|
|
break;
|
|
else if (IS("-o")) /* output file */
|
|
{
|
|
output = argv[++i];
|
|
if (output == NULL || *output == 0 || (*output == '-' && output[1] != 0))
|
|
usage("'-o' needs argument");
|
|
if (IS("-")) output = NULL;
|
|
}
|
|
else /* unknown option */
|
|
usage(argv[i]);
|
|
}
|
|
return i;
|
|
}
|
|
|
|
#define FUNCTION "(function()end)();"
|
|
|
|
static size_t w_o;
|
|
static int writer(lua_State* L, const void* p, size_t size, void* f)
|
|
{
|
|
for (size_t i = 0; i < size; ++i)
|
|
{
|
|
if ((i+w_o) % 32 == 0) fprintf(f, "\n");
|
|
fprintf(f, "0x%02X, ", (int)(((unsigned char*)p)[i]));
|
|
}
|
|
w_o += size;
|
|
return 0;
|
|
}
|
|
|
|
// use custom version so that filename is not used for debug info
|
|
LUALIB_API int luaL_loadfilex2 (lua_State *L, const char *filename,
|
|
const char *mode, const char *chunkname) {
|
|
luai_LoadF lf;
|
|
int status, readstatus;
|
|
int c;
|
|
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
|
|
if (filename == NULL) {
|
|
lua_pushliteral(L, "=stdin");
|
|
lf.f = stdin;
|
|
}
|
|
else {
|
|
lua_pushfstring(L, "@%s", filename);
|
|
lf.f = fopen(filename, "r");
|
|
if (lf.f == NULL) return luai_errfile(L, "open", fnameindex);
|
|
}
|
|
if (luai_skipcomment(&lf, &c)) /* read initial portion */
|
|
lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
|
|
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
|
|
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
|
|
if (lf.f == NULL) return luai_errfile(L, "reopen", fnameindex);
|
|
luai_skipcomment(&lf, &c); /* re-read initial portion */
|
|
}
|
|
if (c != EOF)
|
|
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
|
|
lua_pop(L, 1);
|
|
lua_pushstring(L, chunkname);
|
|
status = lua_load(L, luai_getF, &lf, lua_tostring(L, -1), mode);
|
|
readstatus = ferror(lf.f);
|
|
if (filename) fclose(lf.f); /* close file (even in case of errors) */
|
|
if (readstatus) {
|
|
lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
|
|
return luai_errfile(L, "read", fnameindex);
|
|
}
|
|
lua_remove(L, fnameindex);
|
|
return status;
|
|
}
|
|
|
|
static int pmain(lua_State* L)
|
|
{
|
|
int argc = (int)lua_tointeger(L, 1);
|
|
char** argv = (char**)lua_touserdata(L, 2);
|
|
int i;
|
|
if (!lua_checkstack(L, argc)) fatal("too many input files");
|
|
FILE* f = (output == NULL) ? stdout : fopen(output, "wb");
|
|
if (f == NULL) cannot("open");
|
|
for (i = 0; i < argc; i++)
|
|
{
|
|
int compile = 0;
|
|
const char* filename = IS("-") ? NULL : argv[i];
|
|
if (!filename) fatal("invalid input file");
|
|
char *ufname = strdup(filename);
|
|
int fnix = 0; for (int i = 0; ufname[i]; ++i) { if (ufname[i] == '/' || ufname[i] == '\\') fnix = i + 1; if (ufname[i] == '.') ufname[i] = '_'; }
|
|
char *name = malloc(1024);
|
|
sprintf(name, "script_%s", ufname + fnix);
|
|
free(ufname);
|
|
int fnl = (int)strlen(filename);
|
|
compile = fnl > 4 && !strcmp(".lua", filename + fnl - 4);
|
|
if (compile)
|
|
{
|
|
// do no use luaL_loadfile so that the filename is not used for error printing
|
|
char *p = strdup(filename), *n = p;
|
|
for (p = p + strlen(p); p != n && *p != '/' && *p != '\\'; --p) ;
|
|
if (p != n) ++p;
|
|
char *chunkname = malloc(strlen(p) + 16);
|
|
strcpy(chunkname, "=(");
|
|
strcat(chunkname, p);
|
|
strcat(chunkname, ")");
|
|
free(n);
|
|
if (luaL_loadfilex2(L, filename, 0, chunkname) != LUA_OK) fatal(lua_tostring(L, -1));
|
|
free(chunkname);
|
|
fprintf(f, "static const char %s[] = {", name);
|
|
w_o = 0;
|
|
lua_dump(L, writer, f, 0);
|
|
lua_pop(L, 1);
|
|
fprintf(f, "\n};\n");
|
|
}
|
|
else
|
|
{
|
|
FILE* l = fopen(filename, "rb"); if (!l) cannot("open");
|
|
fseek(l, 0, SEEK_END);
|
|
int size = (int)ftell(l);
|
|
rewind(l);
|
|
unsigned char *buffer = malloc(size);
|
|
if (size != (int)fread(buffer, 1, size, l)) fatal("failed reading input file");
|
|
fclose(l);
|
|
fprintf(f, "static const char %s[] = {", name);
|
|
for (int i = 0; i < size; ++i)
|
|
{
|
|
if (i % 32 == 0) fprintf(f, "\n");
|
|
fprintf(f, "0x%02X, ", (int)buffer[i]);
|
|
}
|
|
fprintf(f, "\n};\n");
|
|
free(buffer);
|
|
}
|
|
free(name);
|
|
}
|
|
if (ferror(f)) cannot("write");
|
|
if (fclose(f)) cannot("close");
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
lua_State* L;
|
|
int i = doargs(argc, argv);
|
|
argc -= i; argv += i;
|
|
if (argc <= 0) usage("no input files given");
|
|
L = luaL_newstate();
|
|
if (L == NULL) fatal("cannot create state: not enough memory");
|
|
lua_pushcfunction(L, &pmain);
|
|
lua_pushinteger(L, argc);
|
|
lua_pushlightuserdata(L, argv);
|
|
if (lua_pcall(L, 2, 0, 0) != LUA_OK) fatal(lua_tostring(L, -1));
|
|
lua_close(L);
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|