<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>

#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/log.h"
#include <string.h>
#include <unistd.h>

static void run_frontend(std::string filename, std::string command, RTLIL::Design *design, std::string *backend_command)
{
	if (command == "auto") {
		if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
			command = "verilog";
		else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
			command = "ilang";
		else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".ys")
			command = "script";
		else if (filename == "-")
			command = "script";
		else
			log_error("Can't guess frontend for input file `%s' (missing -f option)!\n", filename.c_str());
	}

	if (command == "script") {
		log("\n-- Executing script file `%s' --\n", filename.c_str());
		FILE *f = stdin;
		if (filename != "-")
			f = fopen(filename.c_str(), "r");
		if (f == NULL)
			log_error("Can't open script file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
		char buffer[4096];
		while (fgets(buffer, 4096, f) != NULL) {
			Pass::call(design, buffer);
			design->check();
		}
		if (filename != "-")
			fclose(f);
		if (backend_command != NULL && *backend_command == "auto")
			*backend_command = "";
		return;
	}

	if (filename == "-") {
		log("\n-- Parsing stdin using frontend `%s' --\n", command.c_str());
	} else {
		log("\n-- Parsing `%s' using frontend `%s' --\n", filename.c_str(), command.c_str());
	}

	Frontend::frontend_call(design, NULL, filename, command);
	design->check();
}

static void run_pass(std::string command, RTLIL::Design *design)
{
	log("\n-- Running pass `%s' --\n", command.c_str());

	Pass::call(design, command);
	design->check();
}

static void run_backend(std::string filename, std::string command, RTLIL::Design *design)
{
	if (command == "auto") {
		if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
			command = "verilog";
		else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
			command = "ilang";
		else if (filename == "-")
			command = "ilang";
		else
			log_error("Can't guess frontend for input file `%s' (missing -f option)!\n", filename.c_str());
	}

	if (filename == "-") {
		log("\n-- Writing to stdout using backend `%s' --\n", command.c_str());
	} else {
		log("\n-- Writing to `%s' using backend `%s' --\n", filename.c_str(), command.c_str());
	}

	Backend::backend_call(design, NULL, filename, command);
	design->check();
}

static char *readline_cmd_generator(const char *text, int state)
{
	static std::map<std::string, Pass*>::iterator it;
	static int len;

	if (!state) {
		it = REGISTER_INTERN::pass_register.begin();
		len = strlen(text);
	}

	for (; it != REGISTER_INTERN::pass_register.end(); it++) {
		if (it->first.substr(0, len) == text)
			return strdup((it++)->first.c_str());
	}
	return NULL;
}

static char **readline_completion(const char *text, int start, int)
{
	if (start == 0)
		return rl_completion_matches(text, readline_cmd_generator);
	return NULL;
}

static const char *create_prompt(RTLIL::Design *design)
{
	static char buffer[100];
	std::string str = "\nyosys";
	if (!design->selected_active_module.empty())
		str += stringf(" [%s]", design->selected_active_module.c_str());
	if (!design->selection_stack.back().full_selection) {
		if (design->selected_active_module.empty())
			str += "*";
		else if (design->selection_stack.back().selected_modules.size() != 1 || design->selection_stack.back().selected_members.size() != 0 ||
				design->selection_stack.back().selected_modules.count(design->selected_active_module) == 0)
			str += "*";
	}
	snprintf(buffer, 100, "%s> ", str.c_str());
	return buffer;
}

static void shell(RTLIL::Design *design)
{
	log_cmd_error_throw = true;

	rl_readline_name = "yosys";
	rl_attempted_completion_function = readline_completion;

	char *command = NULL;
	while ((command = readline(create_prompt(design))) != NULL)
	{
		if (command[strspn(command, " \t\r\n")] == 0)
			continue;
		add_history(command);

		try {
			assert(design->selection_stack.size() == 1);
			Pass::call(design, command);
		} catch (int) {
			while (design->selection_stack.size() > 1)
				design->selection_stack.pop_back();
			log_reset_stack();
		}
	}

	log_cmd_error_throw = false;
}

struct ShellPass : public Pass {
	ShellPass() : Pass("shell", "enter interactive command mode") { }
	virtual void help() {
		log("\n");
		log("    shell\n");
		log("\n");
		log("This command enters the interactive command mode. This can be useful\n");
		log("in a script to interrupt the script at a certain point and allow for\n");
		log("interactive inspection or manual synthesis of the design at this point.\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string>, RTLIL::Design *design) {
		shell(design);
	}
} ShellPass;

int main(int argc, char **argv)
{
	std::string frontend_command = "auto";
	std::string backend_command = "auto";
	std::vector<std::string> passes_commands;
	std::string output_filename = "-";
	std::string scriptfile = "";
	bool got_output_filename = false;

	Pass::init_register();

	RTLIL::Design *design = new RTLIL::Design;
	design->selection_stack.push_back(RTLIL::Selection());
	log_push();

	int opt;
	while ((opt = getopt(argc, argv, "f:b:o:p:l:qts:")) != -1)
	{
		switch (opt)
		{
		case 'f':
			frontend_command = optarg;
			break;
		case 'b':
			backend_command = optarg;
			break;
		case 'p':
			passes_commands.push_back(optarg);
			break;
		case 'o':
			output_filename = optarg;
			got_output_filename = true;
			break;
		case 'l':
			log_files.push_back(fopen(optarg, "wt"));
			if (log_files.back() == NULL) {
				fprintf(stderr, "Can't open log file `%s' for writing!\n", optarg);
				exit(1);
			}
			break;
		case 'q':
			log_errfile = stderr;
			break;
		case 't':
			log_time = true;
			break;
		case 's':
			scriptfile = optarg;
			break;
		default:
			fprintf(stderr, "\n");
			fprintf(stderr, "Usage: %s [-q] [-t] [-l logfile] [-o <outfile>] [-f <frontend>] [-s <scriptfile>]\n", argv[0]);
			fprintf(stderr, "       %*s[-p <pass> [-p ..]] [-b <backend>] [<infile> [..]]\n", int(strlen(argv[0])+1), "");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -q\n");
			fprintf(stderr, "        quiet operation. only write error messages to console\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -t\n");
			fprintf(stderr, "        annotate all log messages with a time stamp\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -l logfile\n");
			fprintf(stderr, "        write log messages to the specified file\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -o outfile\n");
			fprintf(stderr, "        write the design to the specified file on exit\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -b backend\n");
			fprintf(stderr, "        use this backend for the output file specified on the command line\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -f backend\n");
			fprintf(stderr, "        use the specified front for the input files on the command line\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -s scriptfile\n");
			fprintf(stderr, "        execute the commands in the script file\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -p command\n");
			fprintf(stderr, "        execute the commands\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "For more complex synthesis jobs it is recommended to use the read_* and write_*\n");
			fprintf(stderr, "commands in a script file instead of specifying input and output files on the\n");
			fprintf(stderr, "command line.\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "When no commands, script files and input files are specified on the command\n");
			fprintf(stderr, "line, yosys automatically enters the interactive command mode. Use the 'help'\n");
			fprintf(stderr, "command to get information on the individual commands.\n");
			fprintf(stderr, "\n");
			exit(1);
		}
	}

	if (log_errfile == NULL)
		log_files.push_back(stderr);

	log("\n");
	log(" /-----------------------------------------------------------------------------\\\n");
	log(" |                                                                             |\n");
	log(" |  yosys -- Yosys Open SYnthesis Suite                                        |\n");
	log(" |                                                                             |\n");
	log(" |  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>                   |\n");
	log(" |                                                                             |\n");
	log(" |  Permission to use, copy, modify, and/or distribute this software for any   |\n");
	log(" |  purpose with or without fee is hereby granted, provided that the above     |\n");
	log(" |  copyright notice and this permission notice appear in all copies.          |\n");
	log(" |                                                                             |\n");
	log(" |  THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES   |\n");
	log(" |  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF           |\n");
	log(" |  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR    |\n");
	log(" |  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES     |\n");
	log(" |  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN      |\n");
	log(" |  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF    |\n");
	log(" |  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.             |\n");
	log(" |                                                                             |\n");
	log(" \\-----------------------------------------------------------------------------/\n");
	log("\n");

	if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) {
		if (!got_output_filename)
			backend_command = "";
		shell(design);
	}

	while (optind < argc)
		run_frontend(argv[optind++], frontend_command, design, output_filename == "-" ? &backend_command : NULL);

	if (!scriptfile.empty())
		run_frontend(scriptfile, "script", design, output_filename == "-" ? &backend_command : NULL);

	for (auto it = passes_commands.begin(); it != passes_commands.end(); it++)
		run_pass(*it, design);

	if (!backend_command.empty())
		run_backend(output_filename, backend_command, design);

	delete design;

	log("\nREADY.\n");
	log_pop();

	for (auto f : log_files)
		if (f != stderr)
			fclose(f);
	log_errfile = NULL;
	log_files.clear();

	Pass::done_register();

	return 0;
}

<commit_msg>Improved help message for "shell" command<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>

#include "kernel/rtlil.h"
#include "kernel/register.h"
#include "kernel/log.h"
#include <string.h>
#include <unistd.h>

static void run_frontend(std::string filename, std::string command, RTLIL::Design *design, std::string *backend_command)
{
	if (command == "auto") {
		if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
			command = "verilog";
		else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
			command = "ilang";
		else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".ys")
			command = "script";
		else if (filename == "-")
			command = "script";
		else
			log_error("Can't guess frontend for input file `%s' (missing -f option)!\n", filename.c_str());
	}

	if (command == "script") {
		log("\n-- Executing script file `%s' --\n", filename.c_str());
		FILE *f = stdin;
		if (filename != "-")
			f = fopen(filename.c_str(), "r");
		if (f == NULL)
			log_error("Can't open script file `%s' for reading: %s\n", filename.c_str(), strerror(errno));
		char buffer[4096];
		while (fgets(buffer, 4096, f) != NULL) {
			Pass::call(design, buffer);
			design->check();
		}
		if (filename != "-")
			fclose(f);
		if (backend_command != NULL && *backend_command == "auto")
			*backend_command = "";
		return;
	}

	if (filename == "-") {
		log("\n-- Parsing stdin using frontend `%s' --\n", command.c_str());
	} else {
		log("\n-- Parsing `%s' using frontend `%s' --\n", filename.c_str(), command.c_str());
	}

	Frontend::frontend_call(design, NULL, filename, command);
	design->check();
}

static void run_pass(std::string command, RTLIL::Design *design)
{
	log("\n-- Running pass `%s' --\n", command.c_str());

	Pass::call(design, command);
	design->check();
}

static void run_backend(std::string filename, std::string command, RTLIL::Design *design)
{
	if (command == "auto") {
		if (filename.size() > 2 && filename.substr(filename.size()-2) == ".v")
			command = "verilog";
		else if (filename.size() > 3 && filename.substr(filename.size()-3) == ".il")
			command = "ilang";
		else if (filename == "-")
			command = "ilang";
		else
			log_error("Can't guess frontend for input file `%s' (missing -f option)!\n", filename.c_str());
	}

	if (filename == "-") {
		log("\n-- Writing to stdout using backend `%s' --\n", command.c_str());
	} else {
		log("\n-- Writing to `%s' using backend `%s' --\n", filename.c_str(), command.c_str());
	}

	Backend::backend_call(design, NULL, filename, command);
	design->check();
}

static char *readline_cmd_generator(const char *text, int state)
{
	static std::map<std::string, Pass*>::iterator it;
	static int len;

	if (!state) {
		it = REGISTER_INTERN::pass_register.begin();
		len = strlen(text);
	}

	for (; it != REGISTER_INTERN::pass_register.end(); it++) {
		if (it->first.substr(0, len) == text)
			return strdup((it++)->first.c_str());
	}
	return NULL;
}

static char **readline_completion(const char *text, int start, int)
{
	if (start == 0)
		return rl_completion_matches(text, readline_cmd_generator);
	return NULL;
}

static const char *create_prompt(RTLIL::Design *design)
{
	static char buffer[100];
	std::string str = "\nyosys";
	if (!design->selected_active_module.empty())
		str += stringf(" [%s]", design->selected_active_module.c_str());
	if (!design->selection_stack.back().full_selection) {
		if (design->selected_active_module.empty())
			str += "*";
		else if (design->selection_stack.back().selected_modules.size() != 1 || design->selection_stack.back().selected_members.size() != 0 ||
				design->selection_stack.back().selected_modules.count(design->selected_active_module) == 0)
			str += "*";
	}
	snprintf(buffer, 100, "%s> ", str.c_str());
	return buffer;
}

static void shell(RTLIL::Design *design)
{
	static bool recursion_detect = false;

	if (recursion_detect) {
		log("Already in interactive shell.\n");
		return;
	}

	recursion_detect = true;
	log_cmd_error_throw = true;

	rl_readline_name = "yosys";
	rl_attempted_completion_function = readline_completion;

	char *command = NULL;
	while ((command = readline(create_prompt(design))) != NULL)
	{
		if (command[strspn(command, " \t\r\n")] == 0)
			continue;
		add_history(command);

		try {
			assert(design->selection_stack.size() == 1);
			Pass::call(design, command);
		} catch (int) {
			while (design->selection_stack.size() > 1)
				design->selection_stack.pop_back();
			log_reset_stack();
		}
	}

	recursion_detect = false;
	log_cmd_error_throw = false;
}

struct ShellPass : public Pass {
	ShellPass() : Pass("shell", "enter interactive command mode") { }
	virtual void help() {
		log("\n");
		log("    shell\n");
		log("\n");
		log("This command enters the interactive command mode. This can be useful\n");
		log("in a script to interrupt the script at a certain point and allow for\n");
		log("interactive inspection or manual synthesis of the design at this point.\n");
		log("\n");
		log("The command prompt of the interactive shell indicates the current\n");
		log("selection (see 'help select'):\n");
		log("\n");
		log("    yosys>\n");
		log("        the entire design is selected\n");
		log("\n");
		log("    yosys*>\n");
		log("        only part of the design is selected\n");
		log("\n");
		log("    yosys [modname]>\n");
		log("        the entire module 'modname' is selected using 'select -module modname'\n");
		log("\n");
		log("    yosys [modname]*>\n");
		log("        only part of current module 'modname' is selected\n");
		log("\n");
		log("When in interavtive shell, some errors (e.g. invalid command arguments)\n");
		log("do not terminate yosys but return to the command prompt.\n");
		log("\n");
		log("This command is the default action if nothing else has been specified\n");
		log("on the command line.\n");
		log("\n");
	}
	virtual void execute(std::vector<std::string>, RTLIL::Design *design) {
		shell(design);
	}
} ShellPass;

int main(int argc, char **argv)
{
	std::string frontend_command = "auto";
	std::string backend_command = "auto";
	std::vector<std::string> passes_commands;
	std::string output_filename = "-";
	std::string scriptfile = "";
	bool got_output_filename = false;

	Pass::init_register();

	RTLIL::Design *design = new RTLIL::Design;
	design->selection_stack.push_back(RTLIL::Selection());
	log_push();

	int opt;
	while ((opt = getopt(argc, argv, "f:b:o:p:l:qts:")) != -1)
	{
		switch (opt)
		{
		case 'f':
			frontend_command = optarg;
			break;
		case 'b':
			backend_command = optarg;
			break;
		case 'p':
			passes_commands.push_back(optarg);
			break;
		case 'o':
			output_filename = optarg;
			got_output_filename = true;
			break;
		case 'l':
			log_files.push_back(fopen(optarg, "wt"));
			if (log_files.back() == NULL) {
				fprintf(stderr, "Can't open log file `%s' for writing!\n", optarg);
				exit(1);
			}
			break;
		case 'q':
			log_errfile = stderr;
			break;
		case 't':
			log_time = true;
			break;
		case 's':
			scriptfile = optarg;
			break;
		default:
			fprintf(stderr, "\n");
			fprintf(stderr, "Usage: %s [-q] [-t] [-l logfile] [-o <outfile>] [-f <frontend>] [-s <scriptfile>]\n", argv[0]);
			fprintf(stderr, "       %*s[-p <pass> [-p ..]] [-b <backend>] [<infile> [..]]\n", int(strlen(argv[0])+1), "");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -q\n");
			fprintf(stderr, "        quiet operation. only write error messages to console\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -t\n");
			fprintf(stderr, "        annotate all log messages with a time stamp\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -l logfile\n");
			fprintf(stderr, "        write log messages to the specified file\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -o outfile\n");
			fprintf(stderr, "        write the design to the specified file on exit\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -b backend\n");
			fprintf(stderr, "        use this backend for the output file specified on the command line\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -f backend\n");
			fprintf(stderr, "        use the specified front for the input files on the command line\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -s scriptfile\n");
			fprintf(stderr, "        execute the commands in the script file\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "    -p command\n");
			fprintf(stderr, "        execute the commands\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "For more complex synthesis jobs it is recommended to use the read_* and write_*\n");
			fprintf(stderr, "commands in a script file instead of specifying input and output files on the\n");
			fprintf(stderr, "command line.\n");
			fprintf(stderr, "\n");
			fprintf(stderr, "When no commands, script files and input files are specified on the command\n");
			fprintf(stderr, "line, yosys automatically enters the interactive command mode. Use the 'help'\n");
			fprintf(stderr, "command to get information on the individual commands.\n");
			fprintf(stderr, "\n");
			exit(1);
		}
	}

	if (log_errfile == NULL)
		log_files.push_back(stderr);

	log("\n");
	log(" /-----------------------------------------------------------------------------\\\n");
	log(" |                                                                             |\n");
	log(" |  yosys -- Yosys Open SYnthesis Suite                                        |\n");
	log(" |                                                                             |\n");
	log(" |  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>                   |\n");
	log(" |                                                                             |\n");
	log(" |  Permission to use, copy, modify, and/or distribute this software for any   |\n");
	log(" |  purpose with or without fee is hereby granted, provided that the above     |\n");
	log(" |  copyright notice and this permission notice appear in all copies.          |\n");
	log(" |                                                                             |\n");
	log(" |  THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES   |\n");
	log(" |  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF           |\n");
	log(" |  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR    |\n");
	log(" |  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES     |\n");
	log(" |  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN      |\n");
	log(" |  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF    |\n");
	log(" |  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.             |\n");
	log(" |                                                                             |\n");
	log(" \\-----------------------------------------------------------------------------/\n");
	log("\n");

	if (optind == argc && passes_commands.size() == 0 && scriptfile.empty()) {
		if (!got_output_filename)
			backend_command = "";
		shell(design);
	}

	while (optind < argc)
		run_frontend(argv[optind++], frontend_command, design, output_filename == "-" ? &backend_command : NULL);

	if (!scriptfile.empty())
		run_frontend(scriptfile, "script", design, output_filename == "-" ? &backend_command : NULL);

	for (auto it = passes_commands.begin(); it != passes_commands.end(); it++)
		run_pass(*it, design);

	if (!backend_command.empty())
		run_backend(output_filename, backend_command, design);

	delete design;

	log("\nREADY.\n");
	log_pop();

	for (auto f : log_files)
		if (f != stderr)
			fclose(f);
	log_errfile = NULL;
	log_files.clear();

	Pass::done_register();

	return 0;
}

<|endoftext|>


<commit_before>#include "client_ws.hpp"
#include "server_ws.hpp"

#include <cassert>

using namespace std;

typedef SimpleWeb::SocketServer<SimpleWeb::WS> WsServer;
typedef SimpleWeb::SocketClient<SimpleWeb::WS> WsClient;

int main() {
  WsServer server;
  server.config.port = 8080;
  server.config.thread_pool_size = 4;

  auto &echo = server.endpoint["^/echo/?$"];

  atomic<int> server_callback_count(0);

  echo.on_message = [&server, &server_callback_count](shared_ptr<WsServer::Connection> connection, shared_ptr<WsServer::Message> message) {
    auto message_str = message->string();
    assert(message_str == "Hello");

    ++server_callback_count;
    auto send_stream = make_shared<WsServer::SendStream>();
    *send_stream << message_str;
    server.send(connection, send_stream, [](const SimpleWeb::error_code &ec) {
      if(ec) {
        cerr << ec.message() << endl;
        assert(false);
      }
    });
  };

  echo.on_open = [&server_callback_count](shared_ptr<WsServer::Connection> /*connection*/) {
    ++server_callback_count;
  };

  echo.on_close = [&server_callback_count](shared_ptr<WsServer::Connection> /*connection*/, int /*status*/, const string & /*reason*/) {
    ++server_callback_count;
  };

  echo.on_error = [](shared_ptr<WsServer::Connection> /*connection*/, const SimpleWeb::error_code &ec) {
    cerr << ec.message() << endl;
    assert(false);
  };

  auto &echo_thrice = server.endpoint["^/echo_thrice/?$"];
  echo_thrice.on_message = [&server](shared_ptr<WsServer::Connection> connection, shared_ptr<WsServer::Message> message) {
    auto message_str = message->string();

    auto send_stream1 = make_shared<WsServer::SendStream>();
    *send_stream1 << message_str;
    server.send(connection, send_stream1, [&server, connection, message_str](const SimpleWeb::error_code &ec) {
      if(!ec) {
        auto send_stream3 = make_shared<WsServer::SendStream>();
        *send_stream3 << message_str;
        server.send(connection, send_stream3); //Sent after send_stream1 is sent, and most likely after send_stream2
      }
    });
    //Do not reuse send_stream1 here as it most likely is not sent yet
    auto send_stream2 = make_shared<WsServer::SendStream>();
    *send_stream2 << message_str;
    server.send(connection, send_stream2); //Most likely queued, and sent after send_stream1
  };

  thread server_thread([&server]() {
    server.start();
  });

  this_thread::sleep_for(chrono::seconds(1));

  for(size_t i = 0; i < 400; ++i) {
    WsClient client("localhost:8080/echo");

    atomic<int> client_callback_count(0);

    client.on_message = [&client, &client_callback_count](shared_ptr<WsClient::Message> message) {
      assert(message->string() == "Hello");

      ++client_callback_count;

      client.send_close(1000);
    };

    client.on_open = [&client, &client_callback_count]() {
      ++client_callback_count;

      auto send_stream = make_shared<WsClient::SendStream>();
      *send_stream << "Hello";
      client.send(send_stream);
    };

    client.on_close = [&client_callback_count](int /*status*/, const string & /*reason*/) {
      ++client_callback_count;
    };

    client.on_error = [](const SimpleWeb::error_code &ec) {
      cerr << ec.message() << endl;
      assert(false);
    };

    thread client_thread([&client]() {
      client.start();
    });

    while(client_callback_count < 3)
      this_thread::sleep_for(chrono::milliseconds(10));

    client.stop();
    client_thread.join();

    assert(client_callback_count == 3);
  }
  assert(server_callback_count == 1200);

  for(size_t i = 0; i < 400; ++i) {
    WsClient client("localhost:8080/echo_thrice");

    atomic<int> client_callback_count(0);

    client.on_message = [&client, &client_callback_count](shared_ptr<WsClient::Message> message) {
      assert(message->string() == "Hello");

      ++client_callback_count;

      if(client_callback_count == 4)
        client.send_close(1000);
    };

    client.on_open = [&client, &client_callback_count]() {
      ++client_callback_count;

      auto send_stream = make_shared<WsClient::SendStream>();
      *send_stream << "Hello";
      client.send(send_stream);
    };

    client.on_close = [&client_callback_count](int /*status*/, const string & /*reason*/) {
      ++client_callback_count;
    };

    client.on_error = [](const SimpleWeb::error_code &ec) {
      cerr << ec.message() << endl;
      assert(false);
    };

    thread client_thread([&client]() {
      client.start();
    });

    while(client_callback_count < 5)
      this_thread::sleep_for(chrono::milliseconds(10));

    client.stop();
    client_thread.join();

    assert(client_callback_count == 5);
  }

  {
    WsClient client("localhost:8080/echo");

    server_callback_count = 0;
    atomic<int> client_callback_count(0);

    client.on_message = [&client, &client_callback_count](shared_ptr<WsClient::Message> message) {
      assert(message->string() == "Hello");

      ++client_callback_count;

      if(client_callback_count == 201)
        client.send_close(1000);
    };

    client.on_open = [&client, &client_callback_count]() {
      ++client_callback_count;

      for(size_t i = 0; i < 200; ++i) {
        auto send_stream = make_shared<WsClient::SendStream>();
        *send_stream << "Hello";
        client.send(send_stream);
      }
    };

    client.on_close = [&client_callback_count](int /*status*/, const string & /*reason*/) {
      ++client_callback_count;
    };

    client.on_error = [](const SimpleWeb::error_code &ec) {
      cerr << ec.message() << endl;
      assert(false);
    };

    thread client_thread([&client]() {
      client.start();
    });

    while(client_callback_count < 202)
      this_thread::sleep_for(chrono::milliseconds(10));

    client.stop();
    client_thread.join();

    assert(client_callback_count == 202);
    assert(server_callback_count == 202);
  }

  server.stop();
  server_thread.join();

  return 0;
}
<commit_msg>Further improvements to io_test<commit_after>#include "client_ws.hpp"
#include "server_ws.hpp"

#include <cassert>

using namespace std;

typedef SimpleWeb::SocketServer<SimpleWeb::WS> WsServer;
typedef SimpleWeb::SocketClient<SimpleWeb::WS> WsClient;

int main() {
  WsServer server;
  server.config.port = 8080;
  server.config.thread_pool_size = 4;

  auto &echo = server.endpoint["^/echo/?$"];

  atomic<int> server_callback_count(0);

  echo.on_message = [&server, &server_callback_count](shared_ptr<WsServer::Connection> connection, shared_ptr<WsServer::Message> message) {
    auto message_str = message->string();
    assert(message_str == "Hello");

    ++server_callback_count;
    auto send_stream = make_shared<WsServer::SendStream>();
    *send_stream << message_str;
    server.send(connection, send_stream, [](const SimpleWeb::error_code &ec) {
      if(ec) {
        cerr << ec.message() << endl;
        assert(false);
      }
    });
  };

  echo.on_open = [&server_callback_count](shared_ptr<WsServer::Connection> /*connection*/) {
    ++server_callback_count;
  };

  echo.on_close = [&server_callback_count](shared_ptr<WsServer::Connection> /*connection*/, int /*status*/, const string & /*reason*/) {
    ++server_callback_count;
  };

  echo.on_error = [](shared_ptr<WsServer::Connection> /*connection*/, const SimpleWeb::error_code &ec) {
    cerr << ec.message() << endl;
    assert(false);
  };

  auto &echo_thrice = server.endpoint["^/echo_thrice/?$"];
  echo_thrice.on_message = [&server](shared_ptr<WsServer::Connection> connection, shared_ptr<WsServer::Message> message) {
    auto message_str = message->string();

    auto send_stream1 = make_shared<WsServer::SendStream>();
    *send_stream1 << message_str;
    server.send(connection, send_stream1, [&server, connection, message_str](const SimpleWeb::error_code &ec) {
      if(!ec) {
        auto send_stream3 = make_shared<WsServer::SendStream>();
        *send_stream3 << message_str;
        server.send(connection, send_stream3); //Sent after send_stream1 is sent, and most likely after send_stream2
      }
    });
    //Do not reuse send_stream1 here as it most likely is not sent yet
    auto send_stream2 = make_shared<WsServer::SendStream>();
    *send_stream2 << message_str;
    server.send(connection, send_stream2); //Most likely queued, and sent after send_stream1
  };

  thread server_thread([&server]() {
    server.start();
  });

  this_thread::sleep_for(chrono::seconds(1));

  for(size_t i = 0; i < 400; ++i) {
    WsClient client("localhost:8080/echo");

    atomic<int> client_callback_count(0);
    atomic<bool> closed(false);

    client.on_message = [&](shared_ptr<WsClient::Message> message) {
      assert(message->string() == "Hello");

      ++client_callback_count;

      assert(!closed);

      client.send_close(1000);
    };

    client.on_open = [&]() {
      ++client_callback_count;

      assert(!closed);

      auto send_stream = make_shared<WsClient::SendStream>();
      *send_stream << "Hello";
      client.send(send_stream);
    };

    client.on_close = [&](int /*status*/, const string & /*reason*/) {
      ++client_callback_count;
      assert(!closed);
      closed = true;
    };

    client.on_error = [](const SimpleWeb::error_code &ec) {
      cerr << ec.message() << endl;
      assert(false);
    };

    thread client_thread([&client]() {
      client.start();
    });

    while(!closed)
      this_thread::sleep_for(chrono::milliseconds(5));

    client.stop();
    client_thread.join();

    assert(client_callback_count == 3);
  }
  assert(server_callback_count == 1200);

  for(size_t i = 0; i < 400; ++i) {
    WsClient client("localhost:8080/echo_thrice");

    atomic<int> client_callback_count(0);
    atomic<bool> closed(false);

    client.on_message = [&](shared_ptr<WsClient::Message> message) {
      assert(message->string() == "Hello");

      ++client_callback_count;

      assert(!closed);

      if(client_callback_count == 4)
        client.send_close(1000);
    };

    client.on_open = [&]() {
      ++client_callback_count;

      assert(!closed);

      auto send_stream = make_shared<WsClient::SendStream>();
      *send_stream << "Hello";
      client.send(send_stream);
    };

    client.on_close = [&](int /*status*/, const string & /*reason*/) {
      ++client_callback_count;
      assert(!closed);
      closed = true;
    };

    client.on_error = [](const SimpleWeb::error_code &ec) {
      cerr << ec.message() << endl;
      assert(false);
    };

    thread client_thread([&client]() {
      client.start();
    });

    while(!closed)
      this_thread::sleep_for(chrono::milliseconds(5));

    client.stop();
    client_thread.join();

    assert(client_callback_count == 5);
  }

  {
    WsClient client("localhost:8080/echo");

    server_callback_count = 0;
    atomic<int> client_callback_count(0);
    atomic<bool> closed(false);

    client.on_message = [&](shared_ptr<WsClient::Message> message) {
      assert(message->string() == "Hello");

      ++client_callback_count;

      assert(!closed);

      if(client_callback_count == 201)
        client.send_close(1000);
    };

    client.on_open = [&]() {
      ++client_callback_count;

      assert(!closed);

      for(size_t i = 0; i < 200; ++i) {
        auto send_stream = make_shared<WsClient::SendStream>();
        *send_stream << "Hello";
        client.send(send_stream);
      }
    };

    client.on_close = [&](int /*status*/, const string & /*reason*/) {
      ++client_callback_count;
      assert(!closed);
      closed = true;
    };

    client.on_error = [](const SimpleWeb::error_code &ec) {
      cerr << ec.message() << endl;
      assert(false);
    };

    thread client_thread([&client]() {
      client.start();
    });

    while(!closed)
      this_thread::sleep_for(chrono::milliseconds(5));

    client.stop();
    client_thread.join();

    assert(client_callback_count == 202);
    assert(server_callback_count == 202);
  }

  server.stop();
  server_thread.join();

  return 0;
}
<|endoftext|>


<commit_before>#include <log-declarations.h>

void log_change_settings_locally()
{
}

void log_without_init()
{
  //TODO pseudo code
  // NO log_init!
  //some logging
  log_debug("log message 1");

  log_change_settings_locally();
  //some logging to check that settings reset back
}

void log_with_init()
{
  //TODO pseudo code
  // log_init (current init for a while)
  const char *log_file = "logtest.log" ;
  log_init("logtest", log_file, true, true) ;

  log_without_init();
}

int main(void)
{
  log_debug("======= start of logtest =======");

  log_with_init();
  log_without_init();

  log_debug("======= end of logtest =======");
  return 0 ;
}
<commit_msg>[LOGTEST] real tests are added (can't be compiled due to bug in logger)<commit_after>#include <log-declarations.h>

void log_change_settings_locally()
{
  //TODO implement
}

void test_empty_log_macro()
{
  log_info("===== empty macro testing =====");
  log_debug();
  log_info();
  log_warning();
  log_error();
  log_critical();
  log_info("===============================");
}

#define test_log_macro_with_fmt(fmt, ...) \
do {                                                  \
  log_info("====== fmt macro testing =====");         \
  log_debug(fmt, ## __VA_ARGS__);                     \
  log_info(fmt, ## __VA_ARGS__);                      \
  log_warning(fmt, ## __VA_ARGS__);                   \
  log_error(fmt, ## __VA_ARGS__);                     \
  log_critical(fmt, ## __VA_ARGS__);                  \
  log_info("===============================");        \
} while(0)                                            \

void log_without_init(bool print_start_end_log = true)
{
  //TODO pseudo code
  // NO log_init!
  //some logging
  if(print_start_end_log)
  {
    log_info("============== no init =============");
  }

  test_empty_log_macro();
  test_log_macro_with_fmt("string only");
  test_log_macro_with_fmt("\"x = %d\" == \"x = 5\"", 5);

  const char * format = "\"fmt\" is in \"const char * format\""
  test_log_macro_with_fmt(format);

  log_change_settings_locally();

  if(print_start_end_log)
  {
    log_info("=========== no init done ===========");
  }
}

void log_with_init()
{
  //TODO pseudo code
  // log_init (current init for a while)
  log_info("=========== with init ===========");
  const char *log_file = "logtest.log" ;
  log_init("logtest", log_file, true, true) ;

  log_without_init(false);
  log_info("========== with init done ==========");
}

int main(void)
{
  log_info("============= start of logtest =============");

  log_with_init();
  log_without_init();

  log_info("============= end of logtest ==============");
  return 0 ;
}
<|endoftext|>


<commit_before>#include "config.h"
#include "libs/mpq_libmpq04.h"
#include "libs/dbcfile.h"
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include "libs/blp/MemImage.h"
#include "util.h"
#include <unordered_map>

using namespace std;

struct F2 {
	float x, y;
};

struct WorldMapOverlay {
	int zone;
	int area;
	const char* name;
	int w;
	int h;
	int left;
	int top;
};

struct WorldMapArea {
	int id;
	int map;	// key to Map
	int area;	// key to AreaTable
	const char* name;
	vector<WorldMapOverlay> overlays;
};
// key: WorldMapArea::id == WorldMapOverlay::zone
typedef unordered_map<int, WorldMapArea> WmaMap;

static void extractWorldMap(const WorldMapArea&);
static void applyOverlay(MemImage& combine, const WorldMapArea& a,
	const WorldMapOverlay& o);

int main() {
	printf("Opening locale.mpq...\n");
	MPQArchive locale(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/locale-"WOW_LOCALE".MPQ");
	MPQArchive patch(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/patch-"WOW_LOCALE".MPQ");
	MPQArchive patch2(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/patch-"WOW_LOCALE"-2.MPQ");
	MPQArchive patch3(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/patch-"WOW_LOCALE"-3.MPQ");

	printf("Opening WorldMapContinent.dbc...\n");
	DBCFile wmc("DBFilesClient\\WorldMapContinent.dbc");
	bool res = wmc.open();
	if(!res) {
		printf("DBC open fail, dumping mpq...\n");
		vector<string> files;
		locale.GetFileListTo(files);
		printf("%"PRIuPTR" files:\n", files.size());
		for(size_t i=0; i<files.size(); i++) {
			printf("%s\n", files[i].c_str());
		}
		return 1;
	}
	printf("Extracting %"PRIuPTR" continents...\n", wmc.getRecordCount());
	for(DBCFile::Iterator itr = wmc.begin(); itr != wmc.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		int cid = r.getInt(0);
		int mid = r.getInt(1);
		float x1 = r.getFloat(9);
		float y1 = r.getFloat(10);
		float x2 = r.getFloat(11);
		float y2 = r.getFloat(12);
		printf("%i, %i, %gx%g, %gx%g\n", cid, mid, x1, y1, x2, y2);
	}

	mkdir("output");

	WmaMap wmaMap;

	printf("Opening WorldMapArea.dbc...\n");
	DBCFile wma("DBFilesClient\\WorldMapArea.dbc");
	res = wma.open();
	if(!res)
		return 1;
	printf("Extracting %"PRIuPTR" map areas...\n", wma.getRecordCount());
	FILE* out = fopen("output/WorldMapArea.txt", "w");
	for(DBCFile::Iterator itr = wma.begin(); itr != wma.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		WorldMapArea a;
		a.id = r.getInt(0);
		a.map = r.getInt(1);
		a.area = r.getInt(2);
		a.name = r.getString(3);
		F2 fa = { r.getFloat(6), r.getFloat(4) };
		F2 fb = { r.getFloat(7), r.getFloat(5) };
		int vmap = r.getInt(8);
		int dmap = r.getInt(9);
#if 1
		fprintf(out, "%i, %i, %i, '%s', %.0fx%.0f, %.0fx%.0f, %i, %i\n",
			a.id, a.map, a.area, a.name, fa.x, fa.y, fb.x, fb.y, vmap, dmap);
#endif
		if(a.id != 0) {	//top-level zone (Azeroth, Kalimdor, Outland, Northrend)
			assert(wmaMap.find(a.id) == wmaMap.end());
			wmaMap[a.id] = a;
		}
	}
#if 0
	MPQFile testBlp("interface\\worldmap\\azeroth\\azeroth12.blp");
	printf("size: %"PRIuPTR"\n", testBlp.getSize());
	MemImage img;
	img.LoadFromBLP((const BYTE*)testBlp.getBuffer(), (DWORD)testBlp.getSize());
	img.SaveToPNG("output/azeroth12.png");
#endif

	// looks like we may also need AreaTable.dbc.
	// not for now.
#if 0
	printf("Opening AreaTable.dbc...\n");
	DBCFile at("DBFilesClient\\AreaTable.dbc");
	res = at.open();
	if(!res)
		return 1;
	printf("Extracting %"PRIuPTR" AreaTable entries...\n", at.getRecordCount());
	out = fopen("output/AreaTable.txt", "w");
	for(DBCFile::Iterator itr = at.begin(); itr != at.end(); ++itr) {
		//const DBCFile::Record& r(*itr);
	}
#endif

	// now for the overlays.
	printf("Opening WorldMapOverlay.dbc...\n");
	DBCFile wmo("DBFilesClient\\WorldMapOverlay.dbc");
	res = wmo.open();
	if(!res)
		return 1;
	printf("Extracting %"PRIuPTR" map overlays...\n", wmo.getRecordCount());
	out = fopen("output/WorldMapOverlay.txt", "w");
	for(DBCFile::Iterator itr = wmo.begin(); itr != wmo.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		WorldMapOverlay o;
		o.zone = r.getInt(1);
		o.area = r.getInt(2);
		o.name = r.getString(8);
		// If we don't have a name, we don't have a texture.
		if(o.name[0] == 0)
			continue;
		o.w = r.getInt(9);
		o.h = r.getInt(10);
		o.left = r.getInt(11);
		o.top = r.getInt(12);
		int bbtop = r.getInt(13);
		int bbleft = r.getInt(14);
		int bbb = r.getInt(15);
		int bbright = r.getInt(16);
		fprintf(out, "%i, %i, '%s', %ix%i, %ix%i, [%ix%i,%ix%i]\n",
			o.zone, o.area, o.name, o.w, o.h, o.left, o.top, bbleft, bbtop, bbright, bbb);
		assert(wmaMap.find(o.zone) != wmaMap.end());
		wmaMap[o.zone].overlays.push_back(o);

		// w,h is the size of the combined texture, in pixels.
		// left,top is the coordinates on the area map where this texture should be drawn.
		// texture may be split in 1, 2(2x1), 4(2x2) or 6(3x2) parts.
		// sanity-check that the combined texture is rectangular and that all parts fit.
		// also check that it's as at least big as w,h says.
		// only copy the w,h part.
		// we'll ignore the bounding box for now; I think it's for mouse pointers.
	}

	for(WmaMap::const_iterator itr = wmaMap.begin(); itr != wmaMap.end(); ++itr) {
		extractWorldMap(itr->second);
	}

	return 0;
}

static void checkOverlayDimension(const char* name, int actual, int expected) {
	if(actual < expected) {
		int diff = expected - actual;
		if(diff <= 2) {
			printf("Warning: overlay %s is %i < %i (diff %i)\n", name, actual, expected, diff);
		} else {
			printf("Error: overlay %s is %i < %i (diff %i)\n", name, actual, expected, diff);
			assert(false);
		}
	}
}

static void applyOverlay(MemImage& combine, const WorldMapArea& a,
	const WorldMapOverlay& o)
{
	printf("Loading BLPs for %s/%s...\n", a.name, o.name);
	MemImage src[12];
	int srcCount=0;
	// Gotta calculate how many rows and columns there ought to be,
	// since that info doesn't appear to be stored anywhere.
	// There may be surplus texture pieces; these should be discarded.
	int columns=0, rows=0;
	int totalWidth=0, totalHeight=0;
	for(srcCount=0; srcCount<12; srcCount++) {
		MemImage& img(src[srcCount]);
		char buf[256];
		bool res;
		sprintf(buf, "interface\\worldmap\\%s\\%s%i.blp", a.name, o.name, srcCount+1);
		MPQFile blp(buf);
		if(blp.getSize() <= 32) {	// I guess that any valid texture is at least this big.
			break;
		}
		res = img.LoadFromBLP((const BYTE*)blp.getBuffer(), (DWORD)blp.getSize());
		assert(res);
		//res = img.RemoveAlpha();
		assert(res);
		printf("%s: %ix%i\n", buf, img.GetWidth(), img.GetHeight());
#if 0
		sprintf(buf, "output/%s_%s%i.png", a.name, o.name, srcCount+1);
		img.SaveToPNG(buf);
#endif
		if(totalWidth < o.w) {
			totalWidth += img.GetWidth();
			columns++;
			assert(columns <= 4);
		}
		if((totalWidth >= o.w) && ((srcCount % columns) == 0 || rows == 0)) {
			totalHeight += img.GetHeight();
			rows++;
			assert(columns * rows <= 12);
		}
		// if we have all we need, stop now.
		if(totalHeight >= o.h && (srcCount+1) == (columns * rows))
			break;
	}
	checkOverlayDimension("width", totalWidth, o.w);
	checkOverlayDimension("height", totalHeight, o.h);
	// check that all parts of each row has the same height.
	// check that all parts of each column has the same width.
	for(int y=0; y<rows; y++) {
		DWORD h = src[y*columns].GetHeight();
		for(int x=0; x<columns; x++) {
			assert(h == src[y*columns+x].GetHeight());
		}
	}
	for(int x=0; x<columns; x++) {
		DWORD w = src[x].GetWidth();
		for(int y=0; y<rows; y++) {
			assert(w == src[y*columns+x].GetWidth());
		}
	}
	// draw
	int py=o.top;
	for(int y=0; y<rows; y++) {
		int px=o.left;
		for(int x=0; x<columns; x++) {
			int i = y*columns+x;
			MemImage& img(src[i]);
			// some images are blank. don't draw those.
			if(img.IsBlank()) {
				printf("Blank part: %s%i.blp\n", o.name, i);
			} else {
				DWORD w = MIN(combine.GetWidth() - px, img.GetWidth());
				DWORD h = MIN(combine.GetHeight() - py, img.GetHeight());
				combine.DrawImage(img, px, py, w, h);
			}
			px += img.GetWidth();
		}
		py += src[y*columns].GetHeight();
	}
}

// Records of WMA where 'at' == 0 are continents.
// The world map images are found in interface/worldmap.
// They are numbered 1 to 12 and ordered in a 4x3 grid,
// left-to-right, top-to-bottom. Tiles are 256x256 pixels,
// making the full image 1024x768 pixels.
// I suspect the client would bilinear-scale these textures for higher resolutions.

// Now: extract them!

static const unsigned int TILE_WIDTH = 256;
static const unsigned int TILE_HEIGHT = 256;

static void extractWorldMap(const WorldMapArea& a) {
	// check if we're done already.
	char outputFileName[256];
	sprintf(outputFileName, "output/%s.jpeg", a.name);
	if(fileExists(outputFileName)) {
		printf("%s already exists, skipping...\n", outputFileName);
		return;
	}

	// load BLPs.
	MemImage src[12];
	bool hasAlpha = false, isPalettized;
	for(int i=0; i<12; i++) {
		MemImage& img(src[i]);
		char buf[256];
		sprintf(buf, "interface\\worldmap\\%s\\%s%i.blp", a.name, a.name, i+1);
		MPQFile testBlp(buf);
		if(testBlp.getSize() <= 256) {	//sanity
			printf("Warning: cannot extract %s\n", buf);
			return;
		}
		bool res = img.LoadFromBLP((const BYTE*)testBlp.getBuffer(),
			(DWORD)testBlp.getSize());
		assert(res);
		assert(img.GetWidth() == TILE_WIDTH);
		assert(img.GetWidth() == TILE_HEIGHT);
		if(!hasAlpha) {
			res = img.RemoveAlpha();
			assert(res);
		}
		if(i == 0) {
			//hasAlpha = img.HasAlpha();
			isPalettized = img.IsPalettized();
		} else {
			assert(hasAlpha == img.HasAlpha());
			assert(isPalettized == img.IsPalettized());
		}
		//printf("%s%i.blp: alpha: %i. palette: %i\n",
			//name, i+1, img.HasAlpha(), img.IsPalettized());
	}
	printf("BLPs loaded.\n");

	// Gattai!!
	MemImage combine;
	combine.Init(4*TILE_WIDTH, 3*TILE_HEIGHT, hasAlpha, isPalettized);
	for(int y=0; y<3; y++) {
		for(int x=0; x<4; x++) {
			int i=y*4+x;
			MemImage& img(src[i]);
			combine.Blit(img, x*TILE_WIDTH, y*TILE_HEIGHT);
		}
	}

	for(size_t i=0; i<a.overlays.size(); i++) {
		applyOverlay(combine, a, a.overlays[i]);
	}

	// save as png.
	combine.SaveToJPEG(outputFileName);
}
<commit_msg>Output Ruby files instead of text files.<commit_after>#include "config.h"
#include "libs/mpq_libmpq04.h"
#include "libs/dbcfile.h"
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include "libs/blp/MemImage.h"
#include "util.h"
#include <unordered_map>

using namespace std;

struct F2 {
	float x, y;
};

struct WorldMapOverlay {
	int zone;
	int area;
	const char* name;
	int w;
	int h;
	int left;
	int top;
};

struct WorldMapArea {
	int id;
	int map;	// key to Map
	int area;	// key to AreaTable
	const char* name;
	vector<WorldMapOverlay> overlays;
};
// key: WorldMapArea::id == WorldMapOverlay::zone
typedef unordered_map<int, WorldMapArea> WmaMap;

static void extractWorldMap(const WorldMapArea&);
static void applyOverlay(MemImage& combine, const WorldMapArea& a,
	const WorldMapOverlay& o);

int main() {
	printf("Opening locale.mpq...\n");
	MPQArchive locale(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/locale-"WOW_LOCALE".MPQ");
	MPQArchive patch(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/patch-"WOW_LOCALE".MPQ");
	MPQArchive patch2(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/patch-"WOW_LOCALE"-2.MPQ");
	MPQArchive patch3(WOW_INSTALL_DIR"Data/"WOW_LOCALE"/patch-"WOW_LOCALE"-3.MPQ");

	printf("Opening WorldMapContinent.dbc...\n");
	DBCFile wmc("DBFilesClient\\WorldMapContinent.dbc");
	bool res = wmc.open();
	if(!res) {
		printf("DBC open fail, dumping mpq...\n");
		vector<string> files;
		locale.GetFileListTo(files);
		printf("%"PRIuPTR" files:\n", files.size());
		for(size_t i=0; i<files.size(); i++) {
			printf("%s\n", files[i].c_str());
		}
		return 1;
	}
	printf("Extracting %"PRIuPTR" continents...\n", wmc.getRecordCount());
	for(DBCFile::Iterator itr = wmc.begin(); itr != wmc.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		int cid = r.getInt(0);
		int mid = r.getInt(1);
		float x1 = r.getFloat(9);
		float y1 = r.getFloat(10);
		float x2 = r.getFloat(11);
		float y2 = r.getFloat(12);
		printf("%i, %i, %gx%g, %gx%g\n", cid, mid, x1, y1, x2, y2);
	}

	mkdir("output");

	WmaMap wmaMap;

	printf("Opening WorldMapArea.dbc...\n");
	DBCFile wma("DBFilesClient\\WorldMapArea.dbc");
	res = wma.open();
	if(!res)
		return 1;
	printf("Extracting %"PRIuPTR" map areas...\n", wma.getRecordCount());
	FILE* out = fopen("output/WorldMapArea.rb", "w");
	fprintf(out, "WORLD_MAP_AREA = {\n");
	for(DBCFile::Iterator itr = wma.begin(); itr != wma.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		WorldMapArea a;
		a.id = r.getInt(0);
		a.map = r.getInt(1);
		a.area = r.getInt(2);
		a.name = r.getString(3);
		F2 fa = { r.getFloat(6), r.getFloat(4) };
		F2 fb = { r.getFloat(7), r.getFloat(5) };
#if 1
		if(a.area != 0) {
			fprintf(out, "\t%i => { :map => %i, :name => \"%s\", :a => {:x => %.0f, :y => %.0f},"
				" :b => {:x => %.0f, :y => %.0f} },\n",
				a.area, a.map, a.name, fa.x, fa.y, fb.x, fb.y);
		}
#endif
		if(a.id != 0) {	//top-level zone (Azeroth, Kalimdor, Outland, Northrend)
			assert(wmaMap.find(a.id) == wmaMap.end());
			wmaMap[a.id] = a;
		}
	}
	fprintf(out, "}\n");
#if 0
	MPQFile testBlp("interface\\worldmap\\azeroth\\azeroth12.blp");
	printf("size: %"PRIuPTR"\n", testBlp.getSize());
	MemImage img;
	img.LoadFromBLP((const BYTE*)testBlp.getBuffer(), (DWORD)testBlp.getSize());
	img.SaveToPNG("output/azeroth12.png");
#endif

	// looks like we may also need AreaTable.dbc.
#if 1
	printf("Opening AreaTable.dbc...\n");
	DBCFile at("DBFilesClient\\AreaTable.dbc");
	res = at.open();
	if(!res)
		return 1;
	printf("Extracting %"PRIuPTR" AreaTable entries...\n", at.getRecordCount());
	out = fopen("output/AreaTable.rb", "w");
	fprintf(out, "AREA_TABLE = {\n");
	for(DBCFile::Iterator itr = at.begin(); itr != at.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		int id = r.getInt(0);
		int map = r.getInt(1);
		int parentId = r.getInt(2);
		int playerLevel = r.getInt(10);
		const char* name = r.getString(11);
		fprintf(out, "\t%i => { :map => %i, :parent => %i, :level => %i, :name => \"%s\" },\n",
			id, map, parentId, playerLevel, name);
	}
	fprintf(out, "}\n");
#endif

	// now for the overlays.
	printf("Opening WorldMapOverlay.dbc...\n");
	DBCFile wmo("DBFilesClient\\WorldMapOverlay.dbc");
	res = wmo.open();
	if(!res)
		return 1;
	printf("Extracting %"PRIuPTR" map overlays...\n", wmo.getRecordCount());
	out = fopen("output/WorldMapOverlay.txt", "w");
	for(DBCFile::Iterator itr = wmo.begin(); itr != wmo.end(); ++itr) {
		const DBCFile::Record& r(*itr);
		WorldMapOverlay o;
		o.zone = r.getInt(1);
		o.area = r.getInt(2);
		o.name = r.getString(8);
		// If we don't have a name, we don't have a texture.
		if(o.name[0] == 0)
			continue;
		o.w = r.getInt(9);
		o.h = r.getInt(10);
		o.left = r.getInt(11);
		o.top = r.getInt(12);
		int bbtop = r.getInt(13);
		int bbleft = r.getInt(14);
		int bbb = r.getInt(15);
		int bbright = r.getInt(16);
		fprintf(out, "%i, %i, '%s', %ix%i, %ix%i, [%ix%i,%ix%i]\n",
			o.zone, o.area, o.name, o.w, o.h, o.left, o.top, bbleft, bbtop, bbright, bbb);
		assert(wmaMap.find(o.zone) != wmaMap.end());
		wmaMap[o.zone].overlays.push_back(o);

		// w,h is the size of the combined texture, in pixels.
		// left,top is the coordinates on the area map where this texture should be drawn.
		// texture may be split in 1, 2(2x1), 4(2x2) or 6(3x2) parts.
		// sanity-check that the combined texture is rectangular and that all parts fit.
		// also check that it's as at least big as w,h says.
		// only copy the w,h part.
		// we'll ignore the bounding box for now; I think it's for mouse pointers.
	}

	for(WmaMap::const_iterator itr = wmaMap.begin(); itr != wmaMap.end(); ++itr) {
		extractWorldMap(itr->second);
	}

	return 0;
}

static void checkOverlayDimension(const char* name, int actual, int expected) {
	if(actual < expected) {
		int diff = expected - actual;
		if(diff <= 2) {
			printf("Warning: overlay %s is %i < %i (diff %i)\n", name, actual, expected, diff);
		} else {
			printf("Error: overlay %s is %i < %i (diff %i)\n", name, actual, expected, diff);
			assert(false);
		}
	}
}

static void applyOverlay(MemImage& combine, const WorldMapArea& a,
	const WorldMapOverlay& o)
{
	printf("Loading BLPs for %s/%s...\n", a.name, o.name);
	MemImage src[12];
	int srcCount=0;
	// Gotta calculate how many rows and columns there ought to be,
	// since that info doesn't appear to be stored anywhere.
	// There may be surplus texture pieces; these should be discarded.
	int columns=0, rows=0;
	int totalWidth=0, totalHeight=0;
	for(srcCount=0; srcCount<12; srcCount++) {
		MemImage& img(src[srcCount]);
		char buf[256];
		bool res;
		sprintf(buf, "interface\\worldmap\\%s\\%s%i.blp", a.name, o.name, srcCount+1);
		MPQFile blp(buf);
		if(blp.getSize() <= 32) {	// I guess that any valid texture is at least this big.
			break;
		}
		res = img.LoadFromBLP((const BYTE*)blp.getBuffer(), (DWORD)blp.getSize());
		assert(res);
		//res = img.RemoveAlpha();
		assert(res);
		printf("%s: %ix%i\n", buf, img.GetWidth(), img.GetHeight());
#if 0
		sprintf(buf, "output/%s_%s%i.jpeg", a.name, o.name, srcCount+1);
		img.SaveToJPEG(buf);
#endif
		if(totalWidth < o.w) {
			totalWidth += img.GetWidth();
			columns++;
			assert(columns <= 4);
		}
		if((totalWidth >= o.w) && ((srcCount % columns) == 0 || rows == 0)) {
			totalHeight += img.GetHeight();
			rows++;
			assert(columns * rows <= 12);
		}
		// if we have all we need, stop now.
		if(totalHeight >= o.h && (srcCount+1) == (columns * rows))
			break;
	}
	checkOverlayDimension("width", totalWidth, o.w);
	checkOverlayDimension("height", totalHeight, o.h);
	// check that all parts of each row has the same height.
	// check that all parts of each column has the same width.
	for(int y=0; y<rows; y++) {
		DWORD h = src[y*columns].GetHeight();
		for(int x=0; x<columns; x++) {
			assert(h == src[y*columns+x].GetHeight());
		}
	}
	for(int x=0; x<columns; x++) {
		DWORD w = src[x].GetWidth();
		for(int y=0; y<rows; y++) {
			assert(w == src[y*columns+x].GetWidth());
		}
	}
	// draw
	int py=o.top;
	for(int y=0; y<rows; y++) {
		int px=o.left;
		for(int x=0; x<columns; x++) {
			int i = y*columns+x;
			MemImage& img(src[i]);
			// some images are blank. don't draw those.
			if(img.IsBlank()) {
				printf("Blank part: %s%i.blp\n", o.name, i);
			} else {
				DWORD w = MIN(combine.GetWidth() - px, img.GetWidth());
				DWORD h = MIN(combine.GetHeight() - py, img.GetHeight());
				combine.DrawImage(img, px, py, w, h);
			}
			px += img.GetWidth();
		}
		py += src[y*columns].GetHeight();
	}
}

// Records of WMA where 'at' == 0 are continents.
// The world map images are found in interface/worldmap.
// They are numbered 1 to 12 and ordered in a 4x3 grid,
// left-to-right, top-to-bottom. Tiles are 256x256 pixels,
// making the full image 1024x768 pixels.
// I suspect the client would bilinear-scale these textures for higher resolutions.

// Now: extract them!

static const unsigned int TILE_WIDTH = 256;
static const unsigned int TILE_HEIGHT = 256;

static void extractWorldMap(const WorldMapArea& a) {
	// check if we're done already.
	char outputFileName[256];
	sprintf(outputFileName, "output/%s.jpeg", a.name);
	if(fileExists(outputFileName)) {
		printf("%s already exists, skipping...\n", outputFileName);
		return;
	}

	// load BLPs.
	MemImage src[12];
	bool hasAlpha = false, isPalettized;
	for(int i=0; i<12; i++) {
		MemImage& img(src[i]);
		char buf[256];
		sprintf(buf, "interface\\worldmap\\%s\\%s%i.blp", a.name, a.name, i+1);
		MPQFile testBlp(buf);
		if(testBlp.getSize() <= 256) {	//sanity
			printf("Warning: cannot extract %s\n", buf);
			return;
		}
		bool res = img.LoadFromBLP((const BYTE*)testBlp.getBuffer(),
			(DWORD)testBlp.getSize());
		assert(res);
		assert(img.GetWidth() == TILE_WIDTH);
		assert(img.GetWidth() == TILE_HEIGHT);
		if(!hasAlpha) {
			res = img.RemoveAlpha();
			assert(res);
		}
		if(i == 0) {
			//hasAlpha = img.HasAlpha();
			isPalettized = img.IsPalettized();
		} else {
			assert(hasAlpha == img.HasAlpha());
			assert(isPalettized == img.IsPalettized());
		}
		//printf("%s%i.blp: alpha: %i. palette: %i\n",
			//name, i+1, img.HasAlpha(), img.IsPalettized());
	}
	printf("BLPs loaded.\n");

	// Gattai!!
	MemImage combine;
	combine.Init(4*TILE_WIDTH, 3*TILE_HEIGHT, hasAlpha, isPalettized);
	for(int y=0; y<3; y++) {
		for(int x=0; x<4; x++) {
			int i=y*4+x;
			MemImage& img(src[i]);
			combine.Blit(img, x*TILE_WIDTH, y*TILE_HEIGHT);
		}
	}

	for(size_t i=0; i<a.overlays.size(); i++) {
		applyOverlay(combine, a, a.overlays[i]);
	}

	// save as JPEG.
	// Effective area: 1002 x 668 pixels.
	combine.SaveToJPEG(outputFileName);
}
<|endoftext|>


<commit_before>// neuralplex is distributed under BSD license reproduced below.
//
// Copyright (c) 2015 Gregory "f3z0" Ray, f3z0@fezo.com
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//  * Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//  * Neither the name of the psutil authors nor the names of its contributors
//    may be used to endorse or promote products derived from this software without
//    specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <unistd.h>
#include <sys/time.h>
#include "neural_net_constants.h"
#include "neural_net.h"
#include <mysql.h>
#include "rapidjson/filestream.h"
#include "rapidjson/prettywriter.h"

float TanhScaled(float x){
  return 1.7159*tanh(0.66666667*x);
}

float TanhScaledPrime(float x) {
  return 0.66666667/1.7159*(1.7159+tanh(x))*(1.7159-tanh(x));
}

float Sigmoid(float x) {
  return 1/(1+pow(exp(1.0), -x));
}

float SigmoidPrime(float x) {
  return Sigmoid(x) * (1.0-Sigmoid(x));
}

int main () {
  MYSQL *conn;
  MYSQL_RES *res_good;
  MYSQL_RES *res_bad;
  MYSQL_RES *res_all;
  MYSQL_ROW row;
  unsigned int n_field_max_length = 50;
  unsigned int n_hidden = 150;
  unsigned int n_output = 1;
  unsigned int n_positive_training_rows = 300;
  unsigned int n_negative_training_rows = 300;
  std::string good_user_query = ("SELECT * FROM (SELECT LCASE(email), LCASE(city), dateOfBirth, LCASE(billingAddress), phone, LCASE(firstName), LCASE(lastName), LCASE(zipcode), \
                                                billingAddress \
                                                from (SELECT sum(amount) as total, email, city, dateOfBirth, billingAddress, phone, firstName, lastName, zipcode FROM transaction_receipts JOIN User ON User.id = userId JOIN UserInformation ON information_fk = UserInformation.id WHERE productId = 'Slotser Deposit' AND (transaction_receipts.currency = 'GBP' OR transaction_receipts.currency = 'EUR') AND User.status = 'ENABLED' AND userType = 'USER' AND CHAR_LENGTH(billingAddress) > 10 GROUP BY userId) b where total >= 25.0) DerivedA \
                                        ORDER BY RAND() \
                                        LIMIT " + std::to_string(n_positive_training_rows));
  std::string bad_user_query = "SELECT \
                                                LCASE(email), \
                                                LCASE(city), \
                                                LCASE(billingAddress), \
                                                phone, \
                                                LCASE(firstName), \
                                                LCASE(lastName), \
                                                LCASE(zipcode), \
                                                billingAddress \
                                                from User \
                                                JOIN UserInformation ON information_fk = UserInformation.id \
                                                AND status = \"CLOSED\" \
                                                AND userType = \"USER\" \
                                                AND dateOfBirth IS NOT NULL \
                                                ORDER BY RAND() \
                                                LIMIT " + std::to_string(n_negative_training_rows);
  std::string all_user_query = "SELECT \
                                              LCASE(email), \
                                              LCASE(city), \
                                              LCASE(billingAddress), \
                                              phone, \
                                              LCASE(firstName), \
                                              LCASE(lastName), \
                                              LCASE(zipcode), \
                                                billingAddress, \
                                              User.id, \
                                              status \
                                              FROM User \
                                              JOIN UserInformation ON information_fk = UserInformation.id \
                                              WHERE  (status = \"ENABLED\" \
                                              OR status = \"CLOSED\") \
                                              AND userType = \"USER\" \
                                              AND dateOfBirth IS NOT NULL;";
  char const *server = "127.0.0.1";
  char const *user = "un";
  char const *password = "ps" ;
  char const *database = "db";
  conn = mysql_init(NULL);
  if (!mysql_real_connect(conn, server,
       user, password, database, 3307, NULL, 0)) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  if (mysql_query(conn, good_user_query.c_str())) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  res_good = mysql_store_result(conn);
  if (mysql_query(conn, bad_user_query.c_str())) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  res_bad = mysql_store_result(conn);
  unsigned int n_fields = mysql_field_count(conn);
  unsigned int n_good_rows = mysql_num_rows(res_good);
  unsigned int n_bad_rows = mysql_num_rows(res_bad);
  unsigned int batch_size = n_good_rows+n_bad_rows;
  float training_data_arr[n_good_rows+n_bad_rows][n_fields*n_field_max_length+1];
  unsigned int k = 0;
  while ((row = mysql_fetch_row(res_good)) != NULL) {
    for (unsigned int j = 0; j < n_fields; j++) {
      for (unsigned int i = 0; i < n_field_max_length; i++) {
        float c = 0;
        if (row[j] && i < strlen(row[j])) c = (float)row[j][i];
        training_data_arr[k][j*n_field_max_length+i] = c;
      }
    }
    training_data_arr[k][n_field_max_length*n_fields] = 1.0f;
   // training_data_arr[k][n_field_max_length*n_fields+1] = -1.0f;
    k++;
  }
  while ((row = mysql_fetch_row(res_bad)) != NULL) {
    for (unsigned int j = 0; j < n_fields; j++) {
      for (unsigned int i = 0; i < n_field_max_length; i++) {
        //std::cout << "FF: char: " << row[j][i]  << std::endl;
        int c = 0;
        if (row[j] && i < strlen(row[j])) c = (int)row[j][i];
        training_data_arr[k][j*n_field_max_length+i] = c;
        //std::cout << "FF: char: " << row[j][i] << " int: " << (int)row[j][i] << " float1: " << (float)(int)row[j][i] << " float2: " << training_data_arr[k][j*n_field_max_length+i] << std::endl;
      }
    }
    training_data_arr[k][n_field_max_length*n_fields] = 0.0f;
  //  training_data_arr[k][n_field_max_length*n_fields+1] = 1.0f;
    k++;
  }
  mysql_free_result(res_good);
  mysql_free_result(res_bad);
  if (mysql_query(conn, all_user_query.c_str())) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  res_all = mysql_store_result(conn);
  unsigned int n_all_rows = mysql_num_rows(res_all);
  std::vector<std::string> user_ids;
  std::vector<std::string> emails;
  std::vector<std::string> statuses;

  std::vector < std::vector<float> > test_data_arr;
  //test_data_arr = (float*) malloc(n_all_rows * n_fields * n_field_max_length * sizeof(float));

  for (unsigned int i = 0; i < n_all_rows; i++) {
    std::vector<float> poo;
    for (unsigned int j = 0; j < (n_fields*n_field_max_length); j++) {
      poo.push_back(0.0f);
    }
    test_data_arr.push_back(poo);
  }
  k = 0;

  while ((row = mysql_fetch_row(res_all)) != NULL) {
    for (unsigned int j = 0; j < n_fields; j++) {
      for (unsigned int i = 0; i < n_field_max_length; i++) {
        float c = 0;

        if (row[j] && i < strlen(row[j])) c = (float)(int)row[j][i];
        test_data_arr[k][j*n_field_max_length+i] = c;
     // std::cout << "strlen(row[j]): " << strlen(row[j]) << " i: " << i <<  "FF: char: " << c << " int: " << (int)row[j][i] << " float1: " << (float)(int)row[j][i] << " float2: " << test_data_arr[k][j*n_field_max_length+i] << std::endl;
      }
    }
    user_ids.push_back(row[n_fields]);
    emails.push_back(row[0]);
    statuses.push_back(row[n_fields+1]);
    k++;
  }

  mysql_free_result(res_all);
  //std::random_shuffle(training_data_arr[0], training_data_arr[batch_size-1]);
  //for (int i = 0; i < batch_size; i++) { for (int j = 0; j < n_fields*n_field_max_length+1; j++) { std::cout << training_data_arr[i][j] << ","; }; std::cout << std::endl;  }
  unsigned int n_input = n_fields*n_field_max_length;
  bool did_converge = false;
  long long elapsed_time  = 0;
  struct timeval start, end;
  gettimeofday(&start, NULL);
  std::cout << std::endl << "STARTING: " << std::endl;
  neuralplex::NeuralNet *neural_net = new neuralplex::NeuralNet(n_input, n_hidden, n_output, Sigmoid, SigmoidPrime);
  float global_error = neural_net->Train(*training_data_arr, batch_size, neuralplex::kLearningAlgorithmsResilientProp);
  if (global_error <= neuralplex::kNeuralLearningThreshold) {
    did_converge = true;
    gettimeofday(&end, NULL);
    elapsed_time +=   (end.tv_sec * (unsigned int)1e6 +   end.tv_usec) - (start.tv_sec * (unsigned int)1e6 + start.tv_usec);
  }
  if (did_converge) {
    std::cout << std::endl << "STATS: " << std::endl << (neural_net->epoch()) << " training intervals (epoch) to convergence." << std::endl;
    std::cout << (elapsed_time/1000) << "ms time to converge." << std::endl << std::endl;
    std::cout << "GENERATED NETWORK:" << std::endl;
    std::cout << neural_net->ToJSON() << std::endl << std::endl;
    std::cout << std::endl << "TEST RESULTS:" << std::endl;
    for(int i = 0; i < n_all_rows; i++) {
      float results[n_output];
      /*for(int j = 0; j < n_output; j++) {
        results[i] = 0.0f;
      }*/
      neural_net->Compute(&test_data_arr[i][0], &results[0]);
      std::cout << user_ids[i] << ",\"" <<  statuses[i] << "\",\"" <<  emails[i] << "\",";
      for(int j = 0; j < n_output; j++) {
        std::cout  << results[j] << ",";
      }
      std::cout  << std::endl;
    }
  }
  mysql_close(conn);
  return 0;
}
<commit_msg>renaming sample initialization variable!<commit_after>// neuralplex is distributed under BSD license reproduced below.
//
// Copyright (c) 2015 Gregory "f3z0" Ray, f3z0@fezo.com
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//  * Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//  * Neither the name of the psutil authors nor the names of its contributors
//    may be used to endorse or promote products derived from this software without
//    specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <unistd.h>
#include <sys/time.h>
#include "neural_net_constants.h"
#include "neural_net.h"
#include <mysql.h>
#include "rapidjson/filestream.h"
#include "rapidjson/prettywriter.h"

float TanhScaled(float x){
  return 1.7159*tanh(0.66666667*x);
}

float TanhScaledPrime(float x) {
  return 0.66666667/1.7159*(1.7159+tanh(x))*(1.7159-tanh(x));
}

float Sigmoid(float x) {
  return 1/(1+pow(exp(1.0), -x));
}

float SigmoidPrime(float x) {
  return Sigmoid(x) * (1.0-Sigmoid(x));
}

int main () {
  MYSQL *conn;
  MYSQL_RES *res_good;
  MYSQL_RES *res_bad;
  MYSQL_RES *res_all;
  MYSQL_ROW row;
  unsigned int n_field_max_length = 50;
  unsigned int n_hidden = 150;
  unsigned int n_output = 1;
  unsigned int n_positive_training_rows = 300;
  unsigned int n_negative_training_rows = 300;
  std::string good_user_query = ("SELECT * FROM (SELECT LCASE(email), LCASE(city), dateOfBirth, LCASE(billingAddress), phone, LCASE(firstName), LCASE(lastName), LCASE(zipcode), \
                                                billingAddress \
                                                from (SELECT sum(amount) as total, email, city, dateOfBirth, billingAddress, phone, firstName, lastName, zipcode FROM transaction_receipts JOIN User ON User.id = userId JOIN UserInformation ON information_fk = UserInformation.id WHERE productId = 'Slotser Deposit' AND (transaction_receipts.currency = 'GBP' OR transaction_receipts.currency = 'EUR') AND User.status = 'ENABLED' AND userType = 'USER' AND CHAR_LENGTH(billingAddress) > 10 GROUP BY userId) b where total >= 25.0) DerivedA \
                                        ORDER BY RAND() \
                                        LIMIT " + std::to_string(n_positive_training_rows));
  std::string bad_user_query = "SELECT \
                                                LCASE(email), \
                                                LCASE(city), \
                                                LCASE(billingAddress), \
                                                phone, \
                                                LCASE(firstName), \
                                                LCASE(lastName), \
                                                LCASE(zipcode), \
                                                billingAddress \
                                                from User \
                                                JOIN UserInformation ON information_fk = UserInformation.id \
                                                AND status = \"CLOSED\" \
                                                AND userType = \"USER\" \
                                                AND dateOfBirth IS NOT NULL \
                                                ORDER BY RAND() \
                                                LIMIT " + std::to_string(n_negative_training_rows);
  std::string all_user_query = "SELECT \
                                              LCASE(email), \
                                              LCASE(city), \
                                              LCASE(billingAddress), \
                                              phone, \
                                              LCASE(firstName), \
                                              LCASE(lastName), \
                                              LCASE(zipcode), \
                                                billingAddress, \
                                              User.id, \
                                              status \
                                              FROM User \
                                              JOIN UserInformation ON information_fk = UserInformation.id \
                                              WHERE  (status = \"ENABLED\" \
                                              OR status = \"CLOSED\") \
                                              AND userType = \"USER\" \
                                              AND dateOfBirth IS NOT NULL;";
  char const *server = "127.0.0.1";
  char const *user = "un";
  char const *password = "ps" ;
  char const *database = "db";
  conn = mysql_init(NULL);
  if (!mysql_real_connect(conn, server,
       user, password, database, 3307, NULL, 0)) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  if (mysql_query(conn, good_user_query.c_str())) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  res_good = mysql_store_result(conn);
  if (mysql_query(conn, bad_user_query.c_str())) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  res_bad = mysql_store_result(conn);
  unsigned int n_fields = mysql_field_count(conn);
  unsigned int n_good_rows = mysql_num_rows(res_good);
  unsigned int n_bad_rows = mysql_num_rows(res_bad);
  unsigned int batch_size = n_good_rows+n_bad_rows;
  float training_data_arr[n_good_rows+n_bad_rows][n_fields*n_field_max_length+1];
  unsigned int k = 0;
  while ((row = mysql_fetch_row(res_good)) != NULL) {
    for (unsigned int j = 0; j < n_fields; j++) {
      for (unsigned int i = 0; i < n_field_max_length; i++) {
        float c = 0;
        if (row[j] && i < strlen(row[j])) c = (float)row[j][i];
        training_data_arr[k][j*n_field_max_length+i] = c;
      }
    }
    training_data_arr[k][n_field_max_length*n_fields] = 1.0f;
   // training_data_arr[k][n_field_max_length*n_fields+1] = -1.0f;
    k++;
  }
  while ((row = mysql_fetch_row(res_bad)) != NULL) {
    for (unsigned int j = 0; j < n_fields; j++) {
      for (unsigned int i = 0; i < n_field_max_length; i++) {
        //std::cout << "FF: char: " << row[j][i]  << std::endl;
        int c = 0;
        if (row[j] && i < strlen(row[j])) c = (int)row[j][i];
        training_data_arr[k][j*n_field_max_length+i] = c;
        //std::cout << "FF: char: " << row[j][i] << " int: " << (int)row[j][i] << " float1: " << (float)(int)row[j][i] << " float2: " << training_data_arr[k][j*n_field_max_length+i] << std::endl;
      }
    }
    training_data_arr[k][n_field_max_length*n_fields] = 0.0f;
  //  training_data_arr[k][n_field_max_length*n_fields+1] = 1.0f;
    k++;
  }
  mysql_free_result(res_good);
  mysql_free_result(res_bad);
  if (mysql_query(conn, all_user_query.c_str())) {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(1);
  }
  res_all = mysql_store_result(conn);
  unsigned int n_all_rows = mysql_num_rows(res_all);
  std::vector<std::string> user_ids;
  std::vector<std::string> emails;
  std::vector<std::string> statuses;

  std::vector < std::vector<float> > test_data_arr;
  //test_data_arr = (float*) malloc(n_all_rows * n_fields * n_field_max_length * sizeof(float));

  for (unsigned int i = 0; i < n_all_rows; i++) {
    std::vector<float> init_data;
    for (unsigned int j = 0; j < (n_fields*n_field_max_length); j++) {
      init_data.push_back(0.0f);
    }
    test_data_arr.push_back(init_data);
  }
  k = 0;

  while ((row = mysql_fetch_row(res_all)) != NULL) {
    for (unsigned int j = 0; j < n_fields; j++) {
      for (unsigned int i = 0; i < n_field_max_length; i++) {
        float c = 0;

        if (row[j] && i < strlen(row[j])) c = (float)(int)row[j][i];
        test_data_arr[k][j*n_field_max_length+i] = c;
     // std::cout << "strlen(row[j]): " << strlen(row[j]) << " i: " << i <<  "FF: char: " << c << " int: " << (int)row[j][i] << " float1: " << (float)(int)row[j][i] << " float2: " << test_data_arr[k][j*n_field_max_length+i] << std::endl;
      }
    }
    user_ids.push_back(row[n_fields]);
    emails.push_back(row[0]);
    statuses.push_back(row[n_fields+1]);
    k++;
  }

  mysql_free_result(res_all);
  //std::random_shuffle(training_data_arr[0], training_data_arr[batch_size-1]);
  //for (int i = 0; i < batch_size; i++) { for (int j = 0; j < n_fields*n_field_max_length+1; j++) { std::cout << training_data_arr[i][j] << ","; }; std::cout << std::endl;  }
  unsigned int n_input = n_fields*n_field_max_length;
  bool did_converge = false;
  long long elapsed_time  = 0;
  struct timeval start, end;
  gettimeofday(&start, NULL);
  std::cout << std::endl << "STARTING: " << std::endl;
  neuralplex::NeuralNet *neural_net = new neuralplex::NeuralNet(n_input, n_hidden, n_output, Sigmoid, SigmoidPrime);
  float global_error = neural_net->Train(*training_data_arr, batch_size, neuralplex::kLearningAlgorithmsResilientProp);
  if (global_error <= neuralplex::kNeuralLearningThreshold) {
    did_converge = true;
    gettimeofday(&end, NULL);
    elapsed_time +=   (end.tv_sec * (unsigned int)1e6 +   end.tv_usec) - (start.tv_sec * (unsigned int)1e6 + start.tv_usec);
  }
  if (did_converge) {
    std::cout << std::endl << "STATS: " << std::endl << (neural_net->epoch()) << " training intervals (epoch) to convergence." << std::endl;
    std::cout << (elapsed_time/1000) << "ms time to converge." << std::endl << std::endl;
    std::cout << "GENERATED NETWORK:" << std::endl;
    std::cout << neural_net->ToJSON() << std::endl << std::endl;
    std::cout << std::endl << "TEST RESULTS:" << std::endl;
    for(int i = 0; i < n_all_rows; i++) {
      float results[n_output];
      /*for(int j = 0; j < n_output; j++) {
        results[i] = 0.0f;
      }*/
      neural_net->Compute(&test_data_arr[i][0], &results[0]);
      std::cout << user_ids[i] << ",\"" <<  statuses[i] << "\",\"" <<  emails[i] << "\",";
      for(int j = 0; j < n_output; j++) {
        std::cout  << results[j] << ",";
      }
      std::cout  << std::endl;
    }
  }
  mysql_close(conn);
  return 0;
}
<|endoftext|>


<commit_before>/*
* (C) 2014,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "tests.h"
#include <iostream>
#include <fstream>
#include <botan/auto_rng.h>
#include <botan/fs.h>

#if defined(BOTAN_HAS_SYSTEM_RNG)
  #include <botan/system_rng.h>
#endif

Botan::RandomNumberGenerator& test_rng()
   {
#if defined(BOTAN_HAS_SYSTEM_RNG)
   return Botan::system_rng();
#else
   static Botan::AutoSeeded_RNG rng;
   return rng;
#endif
   }

size_t run_tests_in_dir(const std::string& dir, std::function<size_t (const std::string&)> fn)
   {
   size_t fails = 0;

   for(auto vec: Botan::list_all_readable_files_in_or_under(dir))
      fails += fn(vec);
   return fails;
   }

size_t run_tests(const std::vector<test_fn>& tests)
   {
   size_t fails = 0;

   for(auto& test : tests)
      {
      try
         {
         fails += test();
         }
      catch(std::exception& e)
         {
         std::cout << "Exception escaped test: " << e.what() << std::endl;
         ++fails;
         }
      catch(...)
         {
         std::cout << "Exception escaped test" << std::endl;
         ++fails;
         }
      }

   // Summary for test suite
   test_report("Tests", 0, fails);

   return fails;
   }

void test_report(const std::string& name, size_t ran, size_t failed)
   {
   std::cout << name;

   if(ran > 0)
      std::cout << " " << ran << " tests";

   if(failed)
      std::cout << " " << failed << " FAILs" << std::endl;
   else
      std::cout << " all ok" << std::endl;
   }

size_t run_tests_bb(std::istream& src,
                    const std::string& name_key,
                    const std::string& output_key,
                    bool clear_between_cb,
                    std::function<size_t (std::map<std::string, std::string>)> cb)
   {
   if(!src.good())
      {
      std::cout << "Could not open input file for " << name_key << std::endl;
      return 1;
      }

   std::map<std::string, std::string> vars;
   size_t test_fails = 0, algo_fail = 0;
   size_t test_count = 0, algo_count = 0;

   std::string fixed_name;

   while(src.good())
      {
      std::string line;
      std::getline(src, line);

      if(line == "")
         continue;

      if(line[0] == '#')
         continue;

      if(line[0] == '[' && line[line.size()-1] == ']')
         {
         if(fixed_name != "")
            test_report(fixed_name, algo_count, algo_fail);

         test_count += algo_count;
         test_fails += algo_fail;
         algo_count = 0;
         algo_fail = 0;
         fixed_name = line.substr(1, line.size() - 2);
         vars[name_key] = fixed_name;
         continue;
         }

      const std::string key = line.substr(0, line.find_first_of(' '));
      const std::string val = line.substr(line.find_last_of(' ') + 1, std::string::npos);

      vars[key] = val;

      if(key == name_key)
         fixed_name.clear();

      if(key == output_key)
         {
         //std::cout << vars[name_key] << " " << algo_count << std::endl;
         ++algo_count;
         try
            {
            const size_t fails = cb(vars);

            if(fails)
               {
               std::cout << vars[name_key] << " test " << algo_count << ": " << fails << " failure" << std::endl;
               algo_fail += fails;
               }
            }
         catch(std::exception& e)
            {
            std::cout << vars[name_key] << " test " << algo_count << " failed: " << e.what() << std::endl;
            ++algo_fail;
            }

         if(clear_between_cb)
            {
            vars.clear();
            vars[name_key] = fixed_name;
            }
         }
      }

   test_count += algo_count;
   test_fails += algo_fail;

   if(fixed_name != "" && (algo_count > 0 || algo_fail > 0))
      test_report(fixed_name, algo_count, algo_fail);
   else
      test_report(name_key, test_count, test_fails);

   return test_fails;
   }

size_t run_tests(const std::string& filename,
                 const std::string& name_key,
                 const std::string& output_key,
                 bool clear_between_cb,
                 std::function<std::string (std::map<std::string, std::string>)> cb)
   {
   std::ifstream vec(filename);

   if(!vec)
      {
      std::cout << "Failure opening " << filename << std::endl;
      return 1;
      }

   return run_tests(vec, name_key, output_key, clear_between_cb, cb);
   }

size_t run_tests(std::istream& src,
                 const std::string& name_key,
                 const std::string& output_key,
                 bool clear_between_cb,
                 std::function<std::string (std::map<std::string, std::string>)> cb)
   {
   return run_tests_bb(src, name_key, output_key, clear_between_cb,
                [name_key,output_key,cb](std::map<std::string, std::string> vars)
                {
                const std::string got = cb(vars);
                if(got != vars[output_key])
                   {
                   std::cout << name_key << ' ' << vars[name_key] << " got " << got
                             << " expected " << vars[output_key] << std::endl;
                   return 1;
                   }
                return 0;
                });
   }

namespace {

int help(char* argv0)
   {
   std::cout << "Usage: " << argv0 << " [suite]" << std::endl;
   std::cout << "Suites: all (default), block, hash, bigint, rsa, ecdsa, ..." << std::endl;
   return 1;
   }

}

int main(int argc, char* argv[])
   {
   if(argc != 1 && argc != 2)
      return help(argv[0]);

   std::string target = "all";

   if(argc == 2)
      target = argv[1];

   if(target == "-h" || target == "--help" || target == "help")
      return help(argv[0]);

   std::vector<test_fn> tests;

#define DEF_TEST(test) do { if(target == "all" || target == #test) \
      tests.push_back(test_ ## test);                              \
   } while(0)

   DEF_TEST(block);
   DEF_TEST(modes);
   DEF_TEST(aead);
   DEF_TEST(ocb);

   DEF_TEST(stream);
   DEF_TEST(hash);
   DEF_TEST(mac);
   DEF_TEST(pbkdf);
   DEF_TEST(kdf);
   DEF_TEST(keywrap);
   DEF_TEST(transform);
   DEF_TEST(rngs);
   DEF_TEST(passhash9);
   DEF_TEST(bcrypt);
   DEF_TEST(cryptobox);
   DEF_TEST(tss);
   DEF_TEST(rfc6979);
   DEF_TEST(srp6);

   DEF_TEST(bigint);

   DEF_TEST(rsa);
   DEF_TEST(rw);
   DEF_TEST(dsa);
   DEF_TEST(nr);
   DEF_TEST(dh);
   DEF_TEST(dlies);
   DEF_TEST(elgamal);
   DEF_TEST(ecc_pointmul);
   DEF_TEST(ecdsa);
   DEF_TEST(gost_3410);
   DEF_TEST(curve25519);
   DEF_TEST(mceliece);

   DEF_TEST(ecc_unit);
   DEF_TEST(ecdsa_unit);
   DEF_TEST(ecdh_unit);
   DEF_TEST(pk_keygen);
   DEF_TEST(cvc);
   DEF_TEST(x509);
   DEF_TEST(nist_x509);
   DEF_TEST(tls);
   DEF_TEST(compression);

   if(tests.empty())
      {
      std::cout << "No tests selected by target '" << target << "'" << std::endl;
      return 1;
      }

   return run_tests(tests);
   }
<commit_msg>Add seperator above test summary<commit_after>/*
* (C) 2014,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "tests.h"
#include <iostream>
#include <fstream>
#include <botan/auto_rng.h>
#include <botan/fs.h>

#if defined(BOTAN_HAS_SYSTEM_RNG)
  #include <botan/system_rng.h>
#endif

Botan::RandomNumberGenerator& test_rng()
   {
#if defined(BOTAN_HAS_SYSTEM_RNG)
   return Botan::system_rng();
#else
   static Botan::AutoSeeded_RNG rng;
   return rng;
#endif
   }

size_t run_tests_in_dir(const std::string& dir, std::function<size_t (const std::string&)> fn)
   {
   size_t fails = 0;

   for(auto vec: Botan::list_all_readable_files_in_or_under(dir))
      fails += fn(vec);
   return fails;
   }

size_t run_tests(const std::vector<test_fn>& tests)
   {
   size_t fails = 0;

   for(auto& test : tests)
      {
      try
         {
         fails += test();
         }
      catch(std::exception& e)
         {
         std::cout << "Exception escaped test: " << e.what() << std::endl;
         ++fails;
         }
      catch(...)
         {
         std::cout << "Exception escaped test" << std::endl;
         ++fails;
         }
      }

   // Summary for test suite
   std::cout << "===============" << std::endl;
   test_report("Tests", 0, fails);

   return fails;
   }

void test_report(const std::string& name, size_t ran, size_t failed)
   {
   std::cout << name;

   if(ran > 0)
      std::cout << " " << ran << " tests";

   if(failed)
      std::cout << " " << failed << " FAILs" << std::endl;
   else
      std::cout << " all ok" << std::endl;
   }

size_t run_tests_bb(std::istream& src,
                    const std::string& name_key,
                    const std::string& output_key,
                    bool clear_between_cb,
                    std::function<size_t (std::map<std::string, std::string>)> cb)
   {
   if(!src.good())
      {
      std::cout << "Could not open input file for " << name_key << std::endl;
      return 1;
      }

   std::map<std::string, std::string> vars;
   size_t test_fails = 0, algo_fail = 0;
   size_t test_count = 0, algo_count = 0;

   std::string fixed_name;

   while(src.good())
      {
      std::string line;
      std::getline(src, line);

      if(line == "")
         continue;

      if(line[0] == '#')
         continue;

      if(line[0] == '[' && line[line.size()-1] == ']')
         {
         if(fixed_name != "")
            test_report(fixed_name, algo_count, algo_fail);

         test_count += algo_count;
         test_fails += algo_fail;
         algo_count = 0;
         algo_fail = 0;
         fixed_name = line.substr(1, line.size() - 2);
         vars[name_key] = fixed_name;
         continue;
         }

      const std::string key = line.substr(0, line.find_first_of(' '));
      const std::string val = line.substr(line.find_last_of(' ') + 1, std::string::npos);

      vars[key] = val;

      if(key == name_key)
         fixed_name.clear();

      if(key == output_key)
         {
         //std::cout << vars[name_key] << " " << algo_count << std::endl;
         ++algo_count;
         try
            {
            const size_t fails = cb(vars);

            if(fails)
               {
               std::cout << vars[name_key] << " test " << algo_count << ": " << fails << " failure" << std::endl;
               algo_fail += fails;
               }
            }
         catch(std::exception& e)
            {
            std::cout << vars[name_key] << " test " << algo_count << " failed: " << e.what() << std::endl;
            ++algo_fail;
            }

         if(clear_between_cb)
            {
            vars.clear();
            vars[name_key] = fixed_name;
            }
         }
      }

   test_count += algo_count;
   test_fails += algo_fail;

   if(fixed_name != "" && (algo_count > 0 || algo_fail > 0))
      test_report(fixed_name, algo_count, algo_fail);
   else
      test_report(name_key, test_count, test_fails);

   return test_fails;
   }

size_t run_tests(const std::string& filename,
                 const std::string& name_key,
                 const std::string& output_key,
                 bool clear_between_cb,
                 std::function<std::string (std::map<std::string, std::string>)> cb)
   {
   std::ifstream vec(filename);

   if(!vec)
      {
      std::cout << "Failure opening " << filename << std::endl;
      return 1;
      }

   return run_tests(vec, name_key, output_key, clear_between_cb, cb);
   }

size_t run_tests(std::istream& src,
                 const std::string& name_key,
                 const std::string& output_key,
                 bool clear_between_cb,
                 std::function<std::string (std::map<std::string, std::string>)> cb)
   {
   return run_tests_bb(src, name_key, output_key, clear_between_cb,
                [name_key,output_key,cb](std::map<std::string, std::string> vars)
                {
                const std::string got = cb(vars);
                if(got != vars[output_key])
                   {
                   std::cout << name_key << ' ' << vars[name_key] << " got " << got
                             << " expected " << vars[output_key] << std::endl;
                   return 1;
                   }
                return 0;
                });
   }

namespace {

int help(char* argv0)
   {
   std::cout << "Usage: " << argv0 << " [suite]" << std::endl;
   std::cout << "Suites: all (default), block, hash, bigint, rsa, ecdsa, ..." << std::endl;
   return 1;
   }

}

int main(int argc, char* argv[])
   {
   if(argc != 1 && argc != 2)
      return help(argv[0]);

   std::string target = "all";

   if(argc == 2)
      target = argv[1];

   if(target == "-h" || target == "--help" || target == "help")
      return help(argv[0]);

   std::vector<test_fn> tests;

#define DEF_TEST(test) do { if(target == "all" || target == #test) \
      tests.push_back(test_ ## test);                              \
   } while(0)

   DEF_TEST(block);
   DEF_TEST(modes);
   DEF_TEST(aead);
   DEF_TEST(ocb);

   DEF_TEST(stream);
   DEF_TEST(hash);
   DEF_TEST(mac);
   DEF_TEST(pbkdf);
   DEF_TEST(kdf);
   DEF_TEST(keywrap);
   DEF_TEST(transform);
   DEF_TEST(rngs);
   DEF_TEST(passhash9);
   DEF_TEST(bcrypt);
   DEF_TEST(cryptobox);
   DEF_TEST(tss);
   DEF_TEST(rfc6979);
   DEF_TEST(srp6);

   DEF_TEST(bigint);

   DEF_TEST(rsa);
   DEF_TEST(rw);
   DEF_TEST(dsa);
   DEF_TEST(nr);
   DEF_TEST(dh);
   DEF_TEST(dlies);
   DEF_TEST(elgamal);
   DEF_TEST(ecc_pointmul);
   DEF_TEST(ecdsa);
   DEF_TEST(gost_3410);
   DEF_TEST(curve25519);
   DEF_TEST(mceliece);

   DEF_TEST(ecc_unit);
   DEF_TEST(ecdsa_unit);
   DEF_TEST(ecdh_unit);
   DEF_TEST(pk_keygen);
   DEF_TEST(cvc);
   DEF_TEST(x509);
   DEF_TEST(nist_x509);
   DEF_TEST(tls);
   DEF_TEST(compression);

   if(tests.empty())
      {
      std::cout << "No tests selected by target '" << target << "'" << std::endl;
      return 1;
      }

   return run_tests(tests);
   }
<|endoftext|>


<commit_before>#include <UnitTest/stdafx.h>
#include <UnitTest/UnitTest.h>
#include <core/utility/file.h>

namespace filetest
{
	TEST_CLASS(filetest)
	{
	public:
		// Without this, clang gets weird
		static const bool dummy_var = true;

		TEST_CLASS_INITIALIZE(initialize) { unittest::init(); }

		TEST_METHOD(Test_GetSystemDirectory)
		{
			// This test is likely not portable
			unittest::AreEqualEx(L"C:\\WINDOWS\\system32", file::GetSystemDirectory());
		}

		TEST_METHOD(Test_ShortenPath)
		{
			unittest::AreEqualEx(
				L"C:\\thisIsAFakePath\\thisIsAnotherFakePath",
				file::ShortenPath(L"C:\\thisIsAFakePath\\thisIsAnotherFakePath"));
			// This test is likely not portable
			unittest::AreEqualEx(L"C:\\PROGRA~1\\COMMON~1\\", file::ShortenPath(L"C:\\Program Files\\Common Files"));
			// This test is likely not portable
			unittest::AreEqualEx(
				L"C:\\PROGRA~2\\COMMON~1\\", file::ShortenPath(L"C:\\Program Files (x86)\\Common Files"));
		}

		TEST_METHOD(Test_BuildFileNameAndPath)
		{
			unittest::AreEqualEx(
				L"c:\\testpath\\subject.xml", file::BuildFileNameAndPath(L".xml", L"subject", L"c:\\testpath\\", NULL));
		}

		TEST_METHOD(Test_GetModuleFileName)
		{
			unittest::AreEqualEx(
				L"C:\\WINDOWS\\SYSTEM32\\ntdll.dll", file::GetModuleFileName(::GetModuleHandle(L"ntdll.dll")));
		}

		TEST_METHOD(Test_GetFileVersionInfo)
		{
			auto fi1 = file::GetFileVersionInfo(::GetModuleHandle(NULL));
			unittest::AreEqualEx(L"Microsoft Corporation", fi1[L"CompanyName"]);
			unittest::AreEqualEx(L"© Microsoft Corporation. All rights reserved.", fi1[L"LegalCopyright"]);

			auto fi2 = file::GetFileVersionInfo(::GetModuleHandle(L"ntdll.dll"));
			unittest::AreEqualEx(L"Microsoft Corporation", fi2[L"CompanyName"]);
			unittest::AreEqualEx(L"NT Layer DLL", fi2[L"FileDescription"]);
			unittest::AreEqualEx(L"Microsoft® Windows® Operating System", fi2[L"ProductName"]);
		}
	};
} // namespace filetest<commit_msg>fix build<commit_after>#include <UnitTest/stdafx.h>
#include <UnitTest/UnitTest.h>
#include <core/utility/file.h>

namespace filetest
{
	TEST_CLASS(filetest)
	{
	public:
		// Without this, clang gets weird
		static const bool dummy_var = true;

		TEST_CLASS_INITIALIZE(initialize) { unittest::init(); }

		TEST_METHOD(Test_GetSystemDirectory)
		{
			// This test is likely not portable
			unittest::AreEqualEx(L"C:\\WINDOWS\\system32", file::GetSystemDirectory());
		}

		TEST_METHOD(Test_ShortenPath)
		{
			unittest::AreEqualEx(
				L"C:\\thisIsAFakePath\\thisIsAnotherFakePath",
				file::ShortenPath(L"C:\\thisIsAFakePath\\thisIsAnotherFakePath"));
			// This test is likely not portable
			unittest::AreEqualEx(L"C:\\PROGRA~1\\COMMON~1\\", file::ShortenPath(L"C:\\Program Files\\Common Files"));
			// This test is likely not portable
			unittest::AreEqualEx(
				L"C:\\PROGRA~2\\COMMON~1\\", file::ShortenPath(L"C:\\Program Files (x86)\\Common Files"));
		}

		TEST_METHOD(Test_BuildFileNameAndPath)
		{
			unittest::AreEqualEx(
				L"c:\\testpath\\subject.xml", file::BuildFileNameAndPath(L".xml", L"subject", L"c:\\testpath\\", NULL));
		}

		TEST_METHOD(Test_GetModuleFileName)
		{
			unittest::AreEqualEx(
				L"C:\\WINDOWS\\SYSTEM32\\ntdll.dll", file::GetModuleFileName(::GetModuleHandleW(L"ntdll.dll")));
		}

		TEST_METHOD(Test_GetFileVersionInfo)
		{
			auto fi1 = file::GetFileVersionInfo(::GetModuleHandleW(NULL));
			unittest::AreEqualEx(L"Microsoft Corporation", fi1[L"CompanyName"]);
			unittest::AreEqualEx(L"© Microsoft Corporation. All rights reserved.", fi1[L"LegalCopyright"]);

			auto fi2 = file::GetFileVersionInfo(::GetModuleHandleW(L"ntdll.dll"));
			unittest::AreEqualEx(L"Microsoft Corporation", fi2[L"CompanyName"]);
			unittest::AreEqualEx(L"NT Layer DLL", fi2[L"FileDescription"]);
			unittest::AreEqualEx(L"Microsoft® Windows® Operating System", fi2[L"ProductName"]);
		}
	};
} // namespace filetest<|endoftext|>