Source

lrc / src / compiler / lrc.cxx

Full commit
//      lrc.cxx
//
//      Copyright 2011, 2012 Andreas Tscharner <andy@vis.ethz.ch>
//
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU Lesser General Public License as
//      published by the Free Software Foundation; either version 3 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 Lesser General Public
//      License along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.


/*! \file lrc.cxx
 *
 * This is the main file for the compiler. It calls the appropiate parser
 * and then the collector which creates the .rdf file
 *
 * \author Andreas Tscharner
 * \date 2012-05-06
 */


#include <iostream>
#include <cstring>
#include <unistd.h>
#include "include/CompressDecompress.hxx"
#include "include/EncryptDecrypt.hxx"
#include "../lrcExceptions.hxx"
#include "../Utils.hxx"
#include "InFileParser.hxx"
#include "Collector.hxx"
#include "ParserFactory.hxx"

#ifdef HAVE_CONFIG_H
#include "../lrc_config.h"
#else
#define VERSION "<undefined>"          //!< Define for version number if generated header file is missing
#endif

#ifdef __DEBUG__
#include <cstdio>
#endif


//! Show the usage of the compiler
void usage(int argc, char **argv)
{
	std::cout << "lrc - Linux Resource Compiler\n";
	std::cout << "A resource compiler for Linux (Version " << VERSION << ")\n\n";
	std::cout << "Usage:\n" << argv[0] << " [-d] [-o <rdfFile>] [-c <compression type>] [-e <encryption type> -p <password>] <RCFile>|<RIFFile>\n";
	std::cout << "\t-h\t\t\tShow this help screen\n";
	std::cout << "\t-d\t\t\tDeny overwriting (optional)\n";
	std::cout << "\t-o <rdfFile>\t\tDefine final resource data file (optional)\n";
	std::cout << "\t-c <compression type>\tDefine compression type for the whole file\n";
	std::cout << "\t-e <encryption type>\tDefine encryption type for the whole file\n";
	std::cout << "\t-p <password>\t\tPassword when encryption is used (ignored otherwise)\n";
	std::cout << "\t<RCFile>\t\tInput file in RC format\n";
	std::cout << "\t<RCFile>\t\tInput file in RIF format (XML format)\n";
}


//! Main program
int main(int argc, char **argv)
{
	InFileParser *inputFileParser;
	Collector *inputDataCollector;
	int errVal, optRet;
	inFilePosition errPos;
	char *errMsg;
	char *inputFile = nullptr;
	char *rdfFile = nullptr;
	char *compressType = nullptr;
	char *encryptType = nullptr;
	char *pwdStr = nullptr;
	unsigned char *password = nullptr;
	bool allowOverwrite = true;
	lrc::CompressionType complCompress = lrc::NoneCompression;
	lrc::EncryptionType complEncrypt = lrc::NoneEncryption;


	if (argc < 2) {
		usage(argc, argv);
		return -1;
	};

	while ((optRet = getopt(argc, argv, "dho:c:e:p:")) != -1) {
		switch (optRet) {
			case 'o' :
				rdfFile = new char[strlen(optarg)+1];
				memset(rdfFile, 0, (strlen(optarg)+1));
				strncpy(rdfFile, optarg, (strlen(optarg)));
				break;

			case 'c' :
				compressType = new char[strlen(optarg)+1];
				memset(compressType, 0, (strlen(optarg)+1));
				strncpy(compressType, optarg, (strlen(optarg)));
				break;

			case 'e' :
				encryptType = new char[strlen(optarg)+1];
				memset(encryptType, 0, (strlen(optarg)+1));
				strncpy(encryptType, optarg, (strlen(optarg)));
				break;

			case 'p' :
				pwdStr = new char[strlen(optarg)+1];
				memset(pwdStr, 0, (strlen(optarg)+1));
				strncpy(pwdStr, optarg, (strlen(optarg)));
				break;

			case 'd' :
				allowOverwrite = false;
				break;

			case 'h' :
				usage(argc, argv);
				return 0;
		};
	};

	if (compressType) {
		if (strlen(compressType) == 0) {
			std::cout << "A compression type must be defined with option -c\n";
			return -1;
		};
		complCompress = InFileParser::eval_compression_type(compressType);
	};

	if (encryptType) {
		if (strlen(encryptType) == 0) {
			std::cout << "An encryption type must be defined with option -e\n";
			return -1;
		};
		if (!pwdStr) {
			std::cout << "A password must be provided if encryption is desired\n";
			return -1;
		};
		complEncrypt = InFileParser::eval_encryption_type(encryptType);
		try {
			password = InFileParser::get_password(pwdStr);
		} catch (lrcFileNotFoundException const &fnfEx) {
			std::cout << "Password file provided in password string not found (" << fnfEx.what() << ")\n";
			return -1;
		};
	} else {
		if (pwdStr) {
			delete[] pwdStr;
		};
	};

	inputFile = new char[strlen(argv[optind])+1];
	strncpy(inputFile, argv[optind], (strlen(argv[optind])));

	if (!rdfFile) {
		rdfFile = replace_extension(inputFile, (char *)".rdf");
	};
	DEBUG_PRINT(("Input file: %s; rdfFile: %s\n", inputFile, rdfFile))

	try {
		inputFileParser = ParserFactory::create_input_parser(inputFile);
	} catch (lrcFileNotFoundException const &fnfEx) {
		std::cout << fnfEx.what() << "\n";
		return -1;
	} catch (std::exception const &stdEx) {
		std::cout << "Unexpected exception: " << stdEx.what() << "\n";
		return -1;
	};

	try {
		inputDataCollector = new Collector(inputFile, rdfFile, allowOverwrite);
	} catch (lrcFileExistsException const &exFile) {
		std::cout << exFile.what() << "\n";
		return -1;
	} catch (std::exception const &stdEx) {
		std::cout << "Unexpected exception: " << stdEx.what() << "\n";
		return -1;
	};

	if (inputFileParser->parse()) {
		inputFileParser->get_internal_error(errPos, &errMsg);
		std::cout << errMsg;
		delete[] errMsg;
		return -1;
	};

	errVal = inputDataCollector->collect(inputFileParser->get_resource_entries(), complCompress, complEncrypt, password);
	if (errVal < 0) {
		std::cout << "Compiler exited with code " << errVal << "\n";
		return -1;
	};

	if (password) {
		delete[] password;
	};

	delete inputDataCollector;
	delete inputFileParser;

	delete[] rdfFile;
	delete[] inputFile;

	return 0;
}