/* * PSX-Tools Bundle Pack * Copyright (C) 2002-2003 Nicolas "Pixel" Noble * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: cd-tool.cpp,v 1.27 2004-05-02 00:41:38 pixel Exp $ */ #define VERSION "0.5" #include #include "Input.h" #include "Output.h" #include "Buffer.h" #include "BLua.h" #include "cdreader.h" #include "cdutils.h" #include "generic.h" #include "Main.h" #include "cdabstract.h" #include "isobuilder.h" #include "luacd.h" #include "luapsx.h" #include #include bool interactive = false; cdutils * cdutil = 0; isobuilder * build = 0; static int myprint(lua_State * _L) { Lua * L = Lua::find(_L); String t = "From LUA: " + L->tostring() + "\n"; char * tc = t.strdup(); Base::printm(M_STATUS, "%s", tc); free(tc); return 0; } class Luabasecdtool : public LuaObject { public: static void pushstatics(Lua *) throw (GeneralException); }; typedef void basecdtool; enum basecdtool_t { BASECDTOOL_LOAD = 0, }; struct lua_functypes_t basecdtool_functions[] = { { BASECDTOOL_LOAD, "load", 0, 1, { LUA_ANY } }, { -1, 0, 0, 0, 0 } }; class sLua_basecdtool : public Base { public: DECLARE_FUNCTION(basecdtool, BASECDTOOL_LOAD); private: static int basecdtool_proceed_statics(Lua * L, int n, int caller); }; void Luabasecdtool::pushstatics(Lua * L) throw (GeneralException ) { CHECK_FUNCTIONS(basecdtool); PUSH_FUNCTION(basecdtool, BASECDTOOL_LOAD); } int sLua_basecdtool::basecdtool_proceed_statics(Lua * L, int n, int caller) { int r = 0; switch (caller) { case BASECDTOOL_LOAD: if (!n) { L->load(&Input("cd-tool.lua")); } else { if (L->isstring(1)) { L->load(&Input(L->tostring(1))); } else { Handle * t = (Handle *) LuaObject::getme(L, 1); L->load(t); } } } return r; } class Luacdtool : public LuaObject { public: static void pushstatics(Lua *) throw (GeneralException); }; typedef void cdtool; enum cdtool_functions_t { CDTOOL_PRINT = 0, CDTOOL_PRINTN, CDTOOL_QUIT, CDTOOL_EXIT, CDTOOL_INFOS, CDTOOL_PATH, CDTOOL_PRINTDIR, }; struct lua_functypes_t cdtool_functions[] = { { CDTOOL_PRINT, "print", 0, 1, { LUA_ANY } }, { CDTOOL_PRINTN, "printn", 1, 1, { LUA_ANY } }, { CDTOOL_QUIT, "quit", 0, 0, 0 }, { CDTOOL_EXIT, "exit", 0, 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_PRINTN); 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_PRINTN); 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; char * tc; String eol = ""; switch (caller) { case CDTOOL_PRINT: eol = "\n"; case CDTOOL_PRINTN: if (n) p = L->tostring(1) + eol; else p = eol; tc = p.strdup(); printm(M_BARE, "%s", tc); free(tc); 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'}, {"verbose", 0, NULL, 'v'}, {"file", 1, NULL, 'f'}, {"write", 0, NULL, 'w'}, {"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 /* 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->setvar(); Luabasecdtool::pushstatics(L); 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 showbanner() { printm(M_BARE, "CD-Tool version " VERSION " (c) 2003-2004 Nicolas \"Pixel\" Noble\n" "This is free software with ABSOLUTELY NO WARRANTY.\n" "\n"); } void showhelp(bool longhelp = false) { printm(M_BARE, "Usage:\n" "%s [options] [lua-script1] [lua-script2] ...\n" "\n" "Options:\n" " -v for verbose mode.\n" " -f to load an initial iso file (object cdutil).\n" " -w to open the previous iso file in write mode.\n" " -o to start creating an output iso (object iso).\n" " -a to load an additionnal archive file.\n" " -c 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 exec on end line.\n" " -e to execute this single command in LUA.\n" " -h for a 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" " $ %s -i -e \"main()\" somescript.lua\n" "\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]); } void probe(void) { std::vector p; if (!cdabstract::canprobe()) { printm(M_ERROR, "Can't probe on this platform.\n"); exit(-1); } p = cdabstract::probe(); printm(M_BARE, "Alvaible devices:\n"); for (std::vector::iterator i = p.begin(); i != p.end(); i++) { printm(M_BARE, *i + "\n"); } } virtual int startup() throw (GeneralException) { char c; bool auto_exec = true, strip = true, todo = false, runit, write = false; char * file = 0, * output = 0, * compile = 0, * exec = 0, * line_read = 0; char prompt[10]; Lua * L = 0; Handle * read_iso = 0; Output * build_iso = 0, * write_iso = 0; Buffer command; String line, endline; int pos; verbosity = M_STATUS; showbanner(); /* Let's start parsing options */ while ((c = getopt_long(argc, argv, "Hhvf:wo:a:c:dile:pm:", long_options, NULL)) != EOF) { switch (c) { case 'h': case 'H': case '?': showhelp(true); throw Exit(0); case 'v': verbosity = M_INFO; break; case 'f': file = strdup(optarg); break; case 'w': write = true; break; case 'o': output = strdup(optarg); 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 = false; break; case 'e': exec = strdup(optarg); todo = true; break; case 'p': probe(); throw Exit(0); default: showhelp(); throw Exit(-1); } } if (interactive) L = start_full_lua(); else L = start_basic_lua(); /* Loading cd-tool.lua (only when not compiling) */ if (!compile) L->load(&Input("cd-tool.lua")); /* Loading all the scripts */ while (optind < argc) { todo = true; L->load(&Input(argv[optind++]), !compile); } /* Doh... */ if (!todo) { showhelp(); throw Exit(0); } /* Compilation process will exit from itself right after */ if (compile) { L->dump(&Output(compile), strip); throw Exit(0); } /* The basic input (and eventually output) iso file */ if (file) { /* The write mode can't apply on a CD of course... */ if (write) { read_iso = new Input(file); write_iso = new Output(file, 0, 0); } else { read_iso = cdabstract::open_cd(file); } cdutil = new cdutils(read_iso, write_iso); if (!cdutil->get_iso_infos()) throw Exit(-1); Luacdutils lcdutil(cdutil); L->push("cdutil"); lcdutil.push(L); L->setvar(); } /* 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(); } /* One shot command */ if (exec) { command << exec; L->load(&command); } /* Interactive mode loop */ strcpy(prompt, "> "); rl_bind_key('\t', rl_insert); while (interactive) { /* Basic usage of readline */ if (line_read) free(line_read); line_read = readline(prompt); if (line_read && *line_read) add_history(line_read); line = line_read; line = line.trim(); endline = ""; /* Splitting the line between ;; */ while (line.strlen()) { runit = false; if ((pos = line.strstr(";;")) >= 0) { endline = line.extract(pos + 2); line = line.extract(0, pos); runit = true; } else { endline = ""; } if (line[line.strlen() - 1] == '\\') { line[line.strlen() - 1] = ' '; } else if (auto_exec) { runit = true; } command << line; if (runit) { try { L->load(&command); } catch (LuaException 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