diff options
-rwxr-xr-x | Makefile | 4 | ||||
-rw-r--r-- | cd-tool.cpp | 612 |
2 files changed, 306 insertions, 310 deletions
@@ -2,7 +2,7 @@ CPPFLAGS=-Wall -g -O3 -mcpu=i686 -Iincludes `sdl-config --cflags` -DHAVE_ZLIB `baltisot-config --cflags` `lua-config --include` -DCHATTING LDFLAGS=-lz `sdl-config --libs` `baltisot-config --libs` -lefence -CDTOOL_LDFLAGS=`baltisot-config --libs` +CDTOOL_LDFLAGS=`baltisot-config --libs` -lreadline CXX=g++ #SUBDIRS = psxdev lib Xenogears VP MegamanX5 @@ -24,7 +24,7 @@ yazedc: yazedc-main.o lib/lib.a Makefile ${CXX} yazedc-main.o lib/lib.a -DYAZEDC_MAIN -o yazedc ${LDFLAGS} cd-tool: includes/cdutils.h includes/yazedc.h cd-tool.o lib/lib.a psxdev/psxdev.a Makefile - ${CXX} cd-tool.o lib/lib.a psxdev/psxdev.a -o cd-tool ${CDTOOL_LDFLAGS} + ${CXX} cd-tool.o lib/lib.a psxdev/psxdev.a -o cd-tool ${CDTOOL_LDFLAGS} dte-tool: includes/dte.h dtemain.o lib/lib.a Makefile ${CXX} dtemain.o lib/lib.a -o dte-tool ${LDFLAGS} diff --git a/cd-tool.cpp b/cd-tool.cpp index 888cf9a..6f19d79 100644 --- a/cd-tool.cpp +++ b/cd-tool.cpp @@ -17,15 +17,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: cd-tool.cpp,v 1.22 2004-02-29 17:44:42 pixel Exp $ */ +/* $Id: cd-tool.cpp,v 1.23 2004-04-27 17:53:04 pixel Exp $ */ #include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <string.h> +#include <readline/readline.h> +#include <readline/history.h> #include "Input.h" #include "Output.h" #include "Buffer.h" @@ -39,85 +35,202 @@ #include "luacd.h" #include "luapsx.h" +bool interactive = false; +cdutils * cdutil = 0; +isobuilder * build = 0; + static int myprint(lua_State * _L) { Lua * L = Lua::find(_L); String t = L->tostring(); - Base::printm(M_INFO, "From LUA: " + t + "\n"); + Base::printm(M_STATUS, "From LUA: " + t + "\n"); return 0; } +class Luacdtool : public LuaObject { + public: + static void pushstatics(Lua *) throw (GeneralException); +}; + +typedef void cdtool; + +enum cdtool_functions_t { + CDTOOL_PRINT = 0, + CDTOOL_QUIT, + CDTOOL_EXIT, + CDTOOL_INFOS, + CDTOOL_PATH, + CDTOOL_PRINTDIR, +}; + +struct lua_functypes_t cdtool_functions[] = { + { CDTOOL_PRINT, "print", 1, 1, { LUA_STRING } }, + { CDTOOL_QUIT, "quit", 0, 0, { } }, + { CDTOOL_EXIT, "exit", 0, 0, { } }, + { CDTOOL_INFOS, "infos", 0, 1, { LUA_OBJECT } }, + { CDTOOL_PATH, "path", 0, 1, { LUA_OBJECT } }, + { CDTOOL_PRINTDIR, "printdir", 1, 2, { LUA_STRING, LUA_OBJECT } }, + { -1, 0, 0, 0, 0 } +}; + +class sLua_cdtool : public Base { + public: + DECLARE_FUNCTION(cdtool, CDTOOL_PRINT); + DECLARE_FUNCTION(cdtool, CDTOOL_QUIT); + DECLARE_FUNCTION(cdtool, CDTOOL_EXIT); + DECLARE_FUNCTION(cdtool, CDTOOL_INFOS); + DECLARE_FUNCTION(cdtool, CDTOOL_PATH); + DECLARE_FUNCTION(cdtool, CDTOOL_PRINTDIR); + private: + static int cdtool_proceed_statics(Lua * L, int n, int caller); +}; + +void Luacdtool::pushstatics(Lua * L) throw (GeneralException ) { + CHECK_FUNCTIONS(cdtool); + + PUSH_FUNCTION(cdtool, CDTOOL_PRINT); + PUSH_FUNCTION(cdtool, CDTOOL_QUIT); + PUSH_FUNCTION(cdtool, CDTOOL_EXIT); + PUSH_FUNCTION(cdtool, CDTOOL_INFOS); + PUSH_FUNCTION(cdtool, CDTOOL_PATH); + PUSH_FUNCTION(cdtool, CDTOOL_PRINTDIR); +} + +int sLua_cdtool::cdtool_proceed_statics(Lua * L, int n, int caller) { + int r = 0; + String p; + cdutils * cd = cdutil; + + switch (caller) { + case CDTOOL_PRINT: + p = L->tostring(1); + printm(M_BARE, p + "\n"); + break; + case CDTOOL_QUIT: + case CDTOOL_EXIT: + interactive = false; + break; + case CDTOOL_INFOS: + if (n) + cd = (cdutils *) LuaObject::getme(L, 1); + if (cd) + cd->show_iso_infos(); + else + L->error("Cdutils object void"); + break; + case CDTOOL_PATH: + if (n) + cd = (cdutils *) LuaObject::getme(L, 1); + if (cd) + cd->show_pt_infos(); + else + L->error("Cdutils object void"); + break; + case CDTOOL_PRINTDIR: + p = L->tostring(1); + if (n == 2) + cd = (cdutils *) LuaObject::getme(L, 2); + if (cd) { + char * f; + cdutils::DirEntry dir = cd->find_path(f = p.strdup()); + free(f); + if (!dir.R) + L->error("Path `" + p + "' not found"); + if (!(dir.Flags & 2)) + L->error("Path `" + p + "' points to a file"); + cd->show_head_entry(); + cd->show_dir(&dir); + } else + L->error("Cdutils object void"); + break; + } + + return r; +} + int lga = 0; struct option long_options[] = { - {"help", 0, NULL, 'h'}, - {"ppf", 1, NULL, 'p'}, - {"mode", 1, NULL, 'm'}, - {"force", 0, NULL, 'f'}, - {"verbose", 0, NULL, 'v'}, - {"debug", 0, NULL, 'g'}, - {"archive", 1, NULL, 'a'}, - {0, 0, NULL, 0 } + {"help", 0, NULL, 'h'}, + {"verbose", 0, NULL, 'v'}, + {"file", 1, NULL, 'f'}, + {"output", 1, NULL, 'o'}, + {"archive", 1, NULL, 'a'}, + {"compile", 1, NULL, 'c'}, + {"debug", 0, NULL, 'd'}, + {"interactive", 0, NULL, 'i'}, + {"line", 0, NULL, 'l'}, + {"exec", 1, NULL, 'e'}, + {"probe", 0, NULL, 'p'}, + {0, 0, NULL, 0 } }; CODE_BEGINS -public: -Appli() : cdutil(0), iso_r(0), iso_w(0), file(0) {} -virtual ~Appli() { - delete cdutil; - delete iso_r; - delete iso_w; - delete file; -} -private: - -cdutils * cdutil; -Handle * iso_r, * iso_w, * file; -Lua * startlua(void) { +/* That's the basic lua starter for non interactive mode */ +Lua * start_basic_lua(void) { Lua * L = new Lua(); + L->open_base(); L->open_math(); L->open_string(); L->open_table(); + LuaInput::pushconstruct(L); LuaOutput::pushconstruct(L); LuaBuffer::pushconstruct(L); + CD_PUSHSTATICS(L); + Luapsx::pushstatics(L); + L->push("print"); L->push(myprint); - L->settable(LUA_GLOBALSINDEX); + L->setvar(); + + return L; +} + +/* That's the extended stuff for interactive mode */ +Lua * start_full_lua(void) { + Lua * L = start_basic_lua(); + + Luacdtool::pushstatics(L); + return L; } -void showhelp(void) { +void showhelp(bool longhelp = false) { printm(M_BARE, "Usage:\n" -"%s [-m <mode>] [-p <ppf file>] [-f] <isofile> <command> [command args]\n" -"Where mode can be 1 for MODE 1, 2 for MODE 2, 3 for MODE 2 FORM 1,\n" -"4 for MODE 2 FORM 2, 5 for Raw, and 6 for autodetect (default)\n" +"%s [options] [lua-script1] [lua-script2] ...\n" +"\n" +"Options:\n" +" -v for verbose mode.\n" +" -f <iso> to load an initial iso file (object cdutil).\n" +" -o <iso> to start creating an output iso (object iso).\n" +" -a <paq> to load an additionnal archive file.\n" +" -c <out> to dump the compiled byte code to file.\n" +" -d to enable debug mode (ie, do not strip)\n" +" -i to start interactive mode.\n" +" -l to turn off the no exec on end line.\n" +" -e <cmd> to execute this single command in LUA.\n" +" -h for this help page.\n" +, argv[0]); + + if (longhelp) + printm(M_BARE, +"\n" +"Verbose mode can be somewhat a floody thing.\n" +"Options -i/-e and -c are mutually exclusive.\n" +"Options -i and -e are NOT mutually exclusive. For example:\n" "\n" -"Command can be one of:\n" -" infos - dumps a bunch of infos about the iso.\n" -" path - dumps the path table.\n" -" printdir <path> - show the directoy listing of <path>\n" -" extract-file <file> <path> - extract the file <path> to <file>\n" -" extract <file> <addr> <size> - extract some sectors to <file>\n" -" insert-file <file> <path> - insert the file to <path>\n" -" insert <file> <addr> - insert some sectors at <addr>\n" -#if 0 -" copy <isofile> - copy to another iso\n" -#endif -" lua <luascript> - interpret single LUA script\n" -" luapatch <luapatch> <file> - create a new iso file using the LUA script\n" -" luacomp <luascript> <file> - compile a LUA script\n" +" $ %s -i -e \"main()\" somescript.lua\n" "\n" -"Additional options:\n" -" -v for verbose mode.\n" -" -g for LUA compiling debug mode (ie, no stripping)\n" -" -a to load an additionnal archive file\n" -" -h for this help page\n" +"This will first load the script 'somescript.lua', then execute main, and\n" +"afterward, start the interactive mode.\n" +"\n" +"If a script contains inlined code, it will be run right after loading.\n" , argv[0]); } @@ -138,297 +251,180 @@ void probe(void) { } virtual int startup() throw (GeneralException) { - int type = GUESS, c, size, force = 0, sector; - char * ppf = 0, * iso_name = 0, * arg1 = 0, * arg2 = 0, * f; - bool debug = false; + char c; + + bool auto_exec = false, strip = true, todo = false, runit; + char * file = 0, * output = 0, * compile = 0, * exec = 0, * line_read = 0; + char prompt[10]; + Lua * L = 0; + Output * build_iso = 0; + Buffer command; + String line, endline; + int pos; - verbosity = M_WARNING; + verbosity = M_STATUS; - while ((c = getopt_long(argc, argv, "Hhm:p:fvga:", long_options, NULL)) != EOF) { + /* Let's start parsing options */ + + while ((c = getopt_long(argc, argv, "Hhvf:o:a:c:dile:pm:", long_options, NULL)) != EOF) { switch (c) { case 'h': case 'H': case '?': showhelp(); throw Exit(0); - case 'm': - type = atoi(optarg); - break; - case 'p': - ppf = strdup(optarg); + case 'v': + verbosity = M_INFO; break; case 'f': - force = 1; + file = strdup(optarg); + break; + case 'o': + output = strdup(optarg); break; - case 'v': - verbosity = M_INFO; - break; - case 'g': - debug = true; - break; case 'a': new Archive(optarg); break; + case 'c': + compile = strdup(optarg); + break; + case 'd': + strip = false; + break; + case 'i': + interactive = true; + todo = true; + break; + case 'l': + auto_exec = true; + break; + case 'e': + exec = strdup(optarg); + todo = true; + break; + case 'p': + probe(); + throw Exit(0); + default: + showhelp(); + throw Exit(-1); } } - if (argc == optind) { + if (interactive) + L = start_full_lua(); + else + L = start_basic_lua(); + + /* Loading all the scripts */ + while (optind < argc) { + todo = true; + L->load(&Input(argv[optind++]), compile); + } + + /* Doh... */ + if (!todo) { showhelp(); - printm(M_ERROR, "Need an iso filename to work on.\n"); - exit(-1); + throw Exit(0); } - iso_name = argv[optind++]; - - if (!strcmp(iso_name, "probe")) { - probe(); - exit(-1); + /* Compilation process will exit from itself right after */ + if (compile) { + L->dump(&Output(compile), strip); + throw Exit(0); } - if (argc == optind) { - showhelp(); - printm(M_ERROR, "Need a command to execute.\n"); - exit(-1); + /* The basic input (and eventually output) iso file */ + if (file) { + cdutil = new cdutils(cdabstract::open_cd(file)); + if (!cdutil->get_iso_infos()) + throw Exit(-1); + Luacdutils lcdutil(cdutil); + L->push("cdutil"); + lcdutil.push(L); + L->setvar(); } - iso_r = cdabstract::open_cd(iso_name); + /* The generated iso file */ + if (output) { + build_iso = new Output(output); + build = new isobuilder(build_iso); + Luaisobuilder lbuild(build); + L->push("iso"); + lbuild.push(L); + L->setvar(); + } - cdutil = new cdutils(iso_r); + /* One shot command */ + if (exec) { + command << exec; + L->load(&command); + } - if (!cdutil->get_iso_infos()) - exit(-1); - if (!strcmp(argv[optind], "infos")) { - cdutil->show_iso_infos(); - } else if (!strcmp(argv[optind], "path")) { - cdutil->show_pt_infos(); - } else if (!strcmp(argv[optind], "printdir")) { - cdutils::DirEntry dir; - optind++; - if ((argc - 1) != optind) { - showhelp(); - printm(M_ERROR, "printdir needs one argument.\n"); - throw Exit(-1); - } - arg1 = argv[optind]; - dir = cdutil->find_path(f = strdup(arg1)); - free(f); - if (!dir.R) { - printm(M_ERROR, "Path %s was not found on iso.\n", arg1); - throw Exit(-1); - } - if (!(dir.Flags & 2)) { - printm(M_ERROR, "Path %s is a file and not a directory.\n", arg1); - throw Exit(-1); - } - cdutil->show_head_entry(); - cdutil->show_dir(&dir); - } else if (!strcmp(argv[optind], "extract-file")) { - cdutils::DirEntry * dir; - Byte * buffer; + /* Interactive mode loop */ + strcpy(prompt, "> "); + rl_bind_key('\t', rl_insert); + while (interactive) { + /* Basic usage of readline */ + if (line_read) + free(line_read); - optind++; - if ((argc - 2) != optind) { - showhelp(); - printm(M_ERROR, "extract-file needs two arguments.\n"); - throw Exit(-1); - } - arg1 = argv[optind++]; - arg2 = argv[optind++]; - file = new Output(arg1); - dir = cdutil->find_path(&buffer, arg2); - if (!dir) { - printm(M_ERROR, "Path %s was not found on iso.\n", arg2); - throw Exit(-1); - } - printm(M_STATUS, "Reading path %s to file %s.\n", arg2, arg1); -#if 0 - cdutil->read_file(file, dir->Size, type, dir->Sector); -#else - cdfile * f = new cdfile(cdutil, dir, type); - printm(M_STATUS, f->GetName()); - copy(f, file); - delete f; -#endif - free(buffer); - } else if (!strcmp(argv[optind], "extract")) { - optind++; - if ((argc - 3) != optind) { - showhelp(); - printm(M_ERROR, "extract needs three arguments.\n"); - throw Exit(-1); - } - arg1 = argv[optind++]; - size = atoi(argv[optind++]); - sector = atoi(argv[optind++]); - file = new Output(arg1); - printm(M_STATUS, "Reading %i bytes from sector %i to file %s.\n", size, sector, arg1); - cdutil->read_file(file, size, type, sector); - } else if (!strcmp(argv[optind], "insert-file")) { - cdutils::DirEntry dir, * d; - unsigned char * buffer; - int old_type; + line_read = readline(prompt); - if (ppf) { - if (cdutil->open_ppf(ppf, "Created by CD-Tool") < 0) { - printm(M_ERROR, "Failed to open file %s for writing.\n", ppf); - } - } else { - iso_w = new Output(iso_name, 0, 0); - cdutil->set_iso_w(iso_w); - } + if (line_read && *line_read) + add_history(line_read); - optind++; - if ((argc - 2) != optind) { - showhelp(); - printm(M_ERROR, "insert-file needs two arguments.\n"); - throw Exit(-1); - } - arg1 = argv[optind++]; - arg2 = argv[optind++]; - file = new Input(arg1); - dir = cdutil->find_path(f = strdup(arg2)); - free(f); - if (!dir.R) { - printm(M_ERROR, "Path %s was not found on iso.\n", arg2); - throw Exit(-1); - } + line = line_read; + line = line.trim(); + endline = ""; - old_type = cdutil->guess_type(dir.Sector); + /* Splitting the line between ;; */ + while (line.strlen()) { + runit = false; - if (type == GUESS) { - type = old_type; - } - if (((dir.Size / sec_sizes[old_type]) + ((dir.Size % sec_sizes[old_type]) ? 1 : 0)) < - (((size_t) file->GetSize() / sec_sizes[type]) + (((size_t) file->GetSize() % sec_sizes[type]) ? 1 : 0))) { - if (force) { - printm(M_WARNING, "New file too big: %i vs %i in " + sec_modes[type] + ".\n", dir.Size, file->GetSize()); + if ((pos = line.strstr(";;")) >= 0) { + endline = line.extract(pos + 2); + line = line.extract(0, pos); + runit = true; } else { - printm(M_ERROR, "New file too big: %i vs %i in " + sec_modes[type] + ".\n", dir.Size, file->GetSize()); - throw Exit(-1); + endline = ""; } - } - printm(M_STATUS, "Writing file %s at path %s (sector %i).\n", arg1, arg2, dir.Sector); - cdutil->write_file(file, -1, type, dir.Sector); - printm(M_STATUS, "Updating directory entry.\n"); - dir = cdutil->find_parent(f = strdup(arg2)); - free(f); - if ((f = strrchr(arg2, '/'))) { - f++; - } else { - f = arg2; - } - d = cdutil->find_dir_entry(&buffer, &dir, f); - d->Size = file->GetSize(); - // cdutil->write_datas(buffer, GUESS, dir.Sector, dir.Size); - free(buffer); - } else if (!strcmp(argv[optind], "insert")) { - if (ppf) { - if (cdutil->open_ppf(ppf, "Created by CD-Tool") < 0) { - printm(M_ERROR, "Failed to open file %s for writing.\n", ppf); - throw Exit(-1); + + if (line[line.strlen() - 1] == '\\') { + line[line.strlen() - 1] = ' '; + } else if (auto_exec) { + runit = true; } - } else { - iso_w = new Output(iso_name, 0, 0); - cdutil->set_iso_w(iso_w); - } + + command << line; - optind++; - if ((argc - 2) != optind) { - showhelp(); - printm(M_ERROR, "insert needs two arguments.\n"); - throw Exit(-1); - } - arg1 = argv[optind++]; - sector = atoi(argv[optind++]); - file = new Input(arg1); - printm(M_STATUS, "Writing file %s at sector %i.\n", arg1, sector); - cdutil->write_file(file, -1, type, sector); - } else if (!strcmp(argv[optind], "copy")) { - optind++; - if ((argc - 1) != optind) { - showhelp(); - printm(M_ERROR, "copy needs one argument.\n"); - throw Exit(-1); - } - arg1 = argv[optind]; - Output * o = new Output(arg1); - isobuilder * b = new isobuilder(o); - isobuilder::DirTree * root = b->setbasics(isobuilder::createpvd(cdutil)); - iso_r->seek(0); - b->foreword(iso_r); - b->copydir(root, cdutil, cdutil->rootDir); - - Buffer * buf = new Buffer(true); - (*buf) << "Touched!\n"; - b->createfile(root, buf, "TOUCHED.TXT")->setbasicsxa(); - b->close(); - - delete o; o = 0; - delete b; b = 0; - delete buf; buf = 0; - } else if (!strcmp(argv[optind], "lua")) { - optind++; - if ((argc - 1) != optind) { - showhelp(); - printm(M_ERROR, "lua needs one argument.\n"); - throw Exit(-1); - } - arg1 = argv[optind]; - Lua * L = startlua(); - Luacdutils lcdutil(cdutil); - L->push("cdutil"); - lcdutil.push(L); - L->settable(LUA_GLOBALSINDEX); - L->load(&Input(arg1)); - delete L; - } else if (!strcmp(argv[optind], "luapatch")) { - optind++; - if ((argc - 2) != optind) { - showhelp(); - printm(M_ERROR, "luapatch needs two arguments.\n"); - throw Exit(-1); - } - arg1 = argv[optind++]; - arg2 = argv[optind]; - Output * o = new Output(arg2); - isobuilder * b; - if (type == GUESS) - b = new isobuilder(o); - else - b = new isobuilder(o, type); - Lua * L = startlua(); - Luacdutils lcdutil(cdutil); - L->push("cdutil"); - lcdutil.push(L); - L->setvar(); - Luaisobuilder liso(b); - L->push("iso"); - liso.push(L); - L->setvar(); - L->load(&Input(arg1)); - delete L; - delete b; - delete o; - } else if (!strcmp(argv[optind], "luacomp")) { - optind++; - if ((argc - 2) != optind) { - showhelp(); - printm(M_ERROR, "luacomp needs two arguments.\n"); - throw Exit(-1); - } - arg1 = argv[optind++]; - arg2 = argv[optind]; - Output * o = new Output(arg2); - Lua * L = new Lua(); - L->load(&Input(arg1), false); - L->dump(o, !debug); - delete L; - delete o; - } else { - showhelp(); - printm(M_ERROR, "Command %s unknow.\n", argv[optind]); - throw Exit(-1); + if (runit) { + try { + L->load(&command); + } + catch (GeneralException e) { + /* If there was an error, ignore it, and free the stack */ + while(L->gettop()) + L->pop(); + } + strcpy(prompt, "> "); + } else { + strcpy(prompt, "- "); + } + line = endline.trim(); + }; + } + + /* Finishing off the work, cleaning out the dust */ + if (output) { + delete build_iso; + delete build; } + + if (file) { + delete cdutil; + } + return 0; } CODE_ENDS |