/* Copyright(c) <2009> <Martin Kopta, martin@kopta.eu> {{{1
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files(the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
****************************************************************
Controller for poga project }}}1*/
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include "./modulesmanager.h"
#include "./optionshandler.h"
#include "./container.h"
#include "./controller.h"
#include "./parser.h"
#include "./poga.h"
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::stringstream;
using std::ofstream;
/* Constructor of controller */
Controller::Controller(int argc, char** argv, const string version) {
this->argc = argc;
this->argv = argv;
this->version = version;
this->progname = string(*argv);
}
/* Destructor of controller */
Controller::~Controller() {}
/* Turn on the controller */
int Controller::run() {
int retval = 0;
PRINT_DEBUG("Controller start..");
string prefix(findPrefix(string(*(this->argv))));
/* Creates an instance of OptionsHandler to process cmdline */
OptionsHandler optionshandler(this->argc, this->argv);
retval = processCmdline(&optionshandler);
if (retval != 0) {
PRINT_DEBUG("Controller end..");
if (retval == 1) {
return 0;
} else if (retval == 2) {
return 1;
}
}
string actionName = optionshandler.getActionName();
string outputFormat = optionshandler.getOutputFormat();
string outputFilename = optionshandler.getOutputFilename();
/* Initialize actionsmanager */
PRINT_DEBUG("Init of actionsmanager.");
stringstream action_modules_path;
action_modules_path << prefix;
action_modules_path << "actions/";
ModulesManager actionsmanager(action_modules_path.str());
retval = actionsmanager.initialize();
if (retval == -1) {
PRINT_ERROR("Init of actions manager failed.");
PRINT_DEBUG("Controller end..");
return 1;
}
/* Initialize exportmanager */
PRINT_DEBUG("Init of exportmanager.");
stringstream export_modules_path;
export_modules_path << prefix;
export_modules_path << "exports/";
ModulesManager exportmanager(export_modules_path.str());
retval = exportmanager.initialize();
if (retval == -1) {
PRINT_ERROR("Init of export manager failed.");
PRINT_DEBUG("Controller end..");
return 1;
}
/* If desired action is 'help', we list availible actions */
if (actionName == "help") {
actionsmanager.listModules();
PRINT_DEBUG("Controller end..");
return 0;
}
/* If desired output format is 'help', we list availible output formats */
if (outputFormat == "help") {
exportmanager.listModules();
PRINT_DEBUG("Controller end..");
return 0;
}
/* Parse all input files into containers */
Parser parser;
vector<string> inputFilenames;
vector<Container> containers;
inputFilenames = optionshandler.getInputFilenames();
retval = parser.files2containers(inputFilenames, containers);
if (retval != 0) {
PRINT_ERROR("Parsing input files failed.");
return 1;
}
/* Now we give prepared containers to actionsmanager.
* He knows how to connect container data and algorithm module
*/
PRINT_DEBUG("Running action module: " << actionName);
actionsmanager.setContainers(containers);
retval = actionsmanager.runModule(actionName);
if (retval != 0) {
if (retval == 1) {
PRINT_ERROR("Action '" << actionName << "' not found.");
PRINT_ERROR("Use '-a help' for list of availible actions.");
return 1;
} else if (retval == 2) {
PRINT_ERROR("Fatal error happend during opening a module.");
return 1;
}
}
containers = actionsmanager.getContainers();
/* Now we check if the module worked allright */
int retvalOfModule = actionsmanager.getRetvalOfModule();
switch (retvalOfModule) {
case -1:
/* If module returns -1, it means that something in module failed
* so we stop the program */
PRINT_ERROR("Module code failed. Exiting.");
PRINT_DEBUG("Return value of module is '" << retvalOfModule << "'.");
PRINT_DEBUG("Controller end..");
return 1;
case 1:
/* If module returns 1, it means that no export is needed so we
* can end right here. */
PRINT_DEBUG("Action doesn't require an export. All done, exiting.");
PRINT_DEBUG("Controller end..");
return 0;
case 0:
/* everything is OK */
PRINT_DEBUG("Executing of action module code went fine.");
break;
default:
/* module returned unknown signal(it is probably badly programed */
PRINT_ERROR("Unexpected return code of module code! Exiting.");
PRINT_DEBUG("Return value of module is '" << retvalOfModule << "'.");
PRINT_DEBUG("Controller end..");
return 1;
}
PRINT_DEBUG("Processing data done, exporting folows.");
/* Now we have results, so we export them */
PRINT_DEBUG("Exporting as " << outputFormat);
stringstream export_output;
exportmanager.setContainers(containers);
retval = exportmanager.runModule(outputFormat, &export_output);
if (retval != 0) {
if (retval == 1) {
PRINT_ERROR("Output format '" << outputFormat << "' not found.");
PRINT_ERROR("Use '-f help' for list of output formats.");
} else if (retval == 2) {
PRINT_ERROR("Fatal error happend during opening a module.");
}
return 1;
}
/* Now we check if the module worked allright and save the result */
retvalOfModule = exportmanager.getRetvalOfModule();
switch (retvalOfModule) {
case -1:
/* If module returns -1, it means that something in module failed
* so we stop the program */
PRINT_ERROR("Module code failed. Exiting.");
PRINT_DEBUG("Return value of module is '" << retvalOfModule << "'.");
PRINT_DEBUG("Controller end..");
return 1;
case 0:
/* everything is OK */
PRINT_DEBUG("Executing of export module code went fine.");
// print/write result of export
PRINT_DEBUG("Output filename: '" << outputFilename << "'");
if (outputFilename.size() == 0) {
// print on screen
cout << export_output.str() << endl;
} else {
// write into file
ofstream fs(outputFilename.c_str());
if (fs.is_open()) {
fs << export_output.str() << endl;
fs.close();
cout <<(export_output.str().size() + 1);
cout << " bytes written into file '" << outputFilename;
cout << "'." << endl;
} else {
PRINT_ERROR("Unable to write into file '" <<
outputFilename << "' !");
PRINT_DEBUG("Controller end..");
return 1;
}
}
break;
default:
/* module returned unknown signal(it is probably badly programed */
PRINT_ERROR("Unexpected return code of module code! Exiting.");
PRINT_DEBUG("Return value of module is '" << retvalOfModule << "'.");
PRINT_DEBUG("Controller end..");
return 1;
}
/* everything done, shuting down controller */
PRINT_DEBUG("Controller end..");
return 0;
}
/****************************************************************************/
/* 0 - OK; 1 - OK, end; 2 - Err, end */
int Controller::processCmdline(OptionsHandler* optionshandler) {
if ((*optionshandler).read() == 1) {
/* Error happend while processing cmdline */
string ohmsg = (*optionshandler).getMessage();
if (!ohmsg.empty())
PRINT_ERROR(ohmsg);
if ((*optionshandler).isUsageFlag())
printUsage();
return 2;
}
if ((*optionshandler).isUsageFlag()) {
printUsage();
return 1;
} else if ((*optionshandler).isHelpFlag()) {
printHelp();
return 1;
} else if ((*optionshandler).isVersionFlag()) {
printVersion();
return 1;
}
return 0;
}
void Controller::printVersion() {
cout << "poga, " << this->version << endl;
}
void
Controller::printUsage() {
cout << "Usage: " << this->progname << " <options> <intputfiles>" << endl;
cout << "Options:" << endl;
cout << " -h, --help show help" << endl;
cout << " -u, --usage show usage" << endl;
cout << " -v, --version print version" << endl;
cout << " -o file, --output file set output file" << endl;
cout << " -a name, --action name activate desired action" << endl;
cout << " use '-a help' for list of avalible actions" << endl;
cout << " -f format, --output-format format " << endl;
cout << " set output format" << endl;
cout << " If format is not set, plain is used. For list of" << endl;
cout << " output formats use '--output-format=help'" << endl;
cout << endl;
cout << "Example: " << endl;
cout << this->progname << " -a nfa2dfa -o mydfa.dat mynfa.dat" << endl;
}
void Controller::printHelp() {
printVersion();
cout << endl;
cout << " Processing of grammars and automata" << endl
<< " Martin Kopta <martin@kopta.eu>" << endl
<< " Licensed under MIT license.(c) 2009" << endl
<< endl;
printUsage();
cout << "Report bugs to <martin@kopta.eu>." << endl;
}
string Controller::findPrefix(string arg0) {
string prefix;
unsigned int last_slash;
for (last_slash = arg0.size(); last_slash > 0; last_slash --) {
if (arg0[last_slash] == '/')
break;
}
if (last_slash == 0) {
prefix = string("/usr/lib/poga/");
} else {
prefix = arg0.substr(0, last_slash + 1);
}
PRINT_DEBUG("Using prefix '" << prefix << "'");
return(prefix);
}
/* vim: set ts=2 sw=2 expandtab fdm=marker: */
/* EOF */