/* * 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.23 2004-04-27 17:53:04 pixel Exp $ */ #include #include #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" 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_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'}, {"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 /* 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(); 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(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" " -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 no exec on end line.\n" " -e 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" " $ %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 = 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_STATUS; /* 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 'v': verbosity = M_INFO; break; case 'f': file = strdup(optarg); 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 = true; 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 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) { 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(); } /* 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 (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