<commit_before>#include <cstdio>
#include <fstream>
#include <string>
#include <map>
#include <memory>

#include <SDL.h>

#include <Console.h>
#include <Cart.h>
#include <Controller.h>
#include <APU.h>
#include <SoundQueue.h>

const unsigned int WINDOW_WIDTH = 256*2;
const unsigned int WINDOW_HEIGHT = 240*2;
const unsigned int GAME_FPS = 60;
const unsigned int TICKS_PER_FRAME = 1000 / GAME_FPS;

SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *frameTexture = NULL;

std::unique_ptr<SoundQueue> soundQueue;

Console console;

std::map<SDL_Keycode,Controller::Button> controllerKeyBinds;

bool initVideo() {
    // init SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        printf("SDL_Init() failed: %s\n", SDL_GetError());
        return false;
    }

    // set texture scaling to nearest pixel sampling (sharp pixels)
    if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0")) {
        printf("SDL_SetHint() failed\n");
        return false;
    }

    // create window
    window = SDL_CreateWindow(
        "ScootNES",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        SDL_WINDOW_SHOWN);
    if (window == NULL) {
        printf("SDL_CreateWindow() failed: %s\n", SDL_GetError());
        return false;
    }

    // create renderer for window
    renderer = SDL_CreateRenderer(
        window,
        -1,
        SDL_RENDERER_ACCELERATED); // | SDL_RENDERER_PRESENTVSYNC);
    if (renderer == NULL) {
        printf("SDL_CreateRederer() failed: %s\n", SDL_GetError());
        return false;
    }

    // set colour used for drawing operations e.g. SDL_RenderClear
    SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);

    // create texture that we'll display and update each frame
    frameTexture = SDL_CreateTexture(
        renderer,
        SDL_GetWindowPixelFormat(window),
        SDL_TEXTUREACCESS_STREAMING,
        256,
        240);
    if (frameTexture == NULL) {
        printf("SDL_CreateTexture() failed: %s\n", SDL_GetError());
        return false;
    }
    return true;
}

bool initSound() {
    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
	printf("SDL_Init() failed: %s\n", SDL_GetError());
        return false;
    }

    soundQueue = std::unique_ptr<SoundQueue>(new SoundQueue);
    if (!soundQueue || soundQueue->init(44100)) {
	printf("Sound queue init failed: %s\n", SDL_GetError());
        return false;
    }
    return true;
}

void freeAndQuitSDL() {
    SDL_DestroyTexture(frameTexture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    window = NULL;
    renderer = NULL;
    frameTexture = NULL;
    SDL_Quit();
}

void addControllerKeyBinds() {
    controllerKeyBinds[SDLK_UP]      = Controller::BUTTON_UP;
    controllerKeyBinds[SDLK_DOWN]    = Controller::BUTTON_DOWN;
    controllerKeyBinds[SDLK_LEFT]    = Controller::BUTTON_LEFT;
    controllerKeyBinds[SDLK_RIGHT]   = Controller::BUTTON_RIGHT;
    controllerKeyBinds[SDLK_z]       = Controller::BUTTON_A;
    controllerKeyBinds[SDLK_x]       = Controller::BUTTON_B;
    controllerKeyBinds[SDLK_SPACE]   = Controller::BUTTON_SELECT;
    controllerKeyBinds[SDLK_RETURN]  = Controller::BUTTON_START;
}

int main(int argc, char *args[]) {
    if (argc < 2) {
	printf("Rom path not provided\n");
	return 1;
    }
    if (!initVideo()) {
        printf("initVideo() failed\n");
        return 1;
    }
    if (!initSound()) {
        printf("initSound() failed\n");
        return 1;
    }

    std::string romFileName(args[1]);

    if (!console.loadINesFile(romFileName)) {
        printf("failed to read file\n");
        return 1;
    }

    console.boot();

    addControllerKeyBinds();

    // main loop
    bool isQuitting = false;
    bool isPaused = false;
    SDL_Event event;
    while (!isQuitting) {
        // track time elapsed during frame/loop
        unsigned int frameTimer = SDL_GetTicks();

        // handle events
        while (SDL_PollEvent(&event) != 0) {
            if (event.type == SDL_QUIT) {
                isQuitting = true;
            }
            else if (event.type == SDL_KEYDOWN) {
		SDL_Keycode sym = event.key.keysym.sym;
		if (controllerKeyBinds.count(sym) > 0) {
		    console.controller1.press(controllerKeyBinds[sym]);
		}
                else if (sym == SDLK_ESCAPE) {
                    isQuitting = true;
                }
                else if (sym == SDLK_p) {
                    isPaused ^= 1;
                }
            }
            else if (event.type == SDL_KEYUP) {
                SDL_Keycode sym = event.key.keysym.sym;
                if (controllerKeyBinds.count(sym) > 0) {
		    console.controller1.release(controllerKeyBinds[sym]);
		}
            }
        }

        // clear screen to black
        SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(renderer);

        // spin cpu for 1 frame
        if (!isPaused) {
            console.runForOneFrame();
        }

        // apply frame buffer data to texture
        SDL_UpdateTexture(frameTexture, NULL, console.getFrameBuffer(), 256 * sizeof(uint32_t));

        // render the texture
        SDL_RenderCopy(renderer, frameTexture, NULL, NULL);

        // finally present render target to the window
        SDL_RenderPresent(renderer);

	// retrieve buffered sound samples
	APU::sample_t soundBuf[2048];
	long soundBufLength = console.apu.readSamples(soundBuf, 2048);

	// play samples in the buffer
	soundQueue->write(soundBuf, soundBufLength);

        // delay frame to enforce framerate
        frameTimer = SDL_GetTicks() - frameTimer;
        if (frameTimer < TICKS_PER_FRAME) {
            SDL_Delay(TICKS_PER_FRAME - frameTimer);
        }
    }

    // cleanup
    freeAndQuitSDL();

    return 0;
}
<commit_msg>Use exceptions when initializing video and audio<commit_after>#include <cstdio>
#include <fstream>
#include <string>
#include <map>
#include <memory>
#include <exception>
#include <stdexcept>

#include <SDL.h>

#include <Console.h>
#include <Cart.h>
#include <Controller.h>
#include <APU.h>
#include <SoundQueue.h>

const unsigned int WINDOW_WIDTH = 256*2;
const unsigned int WINDOW_HEIGHT = 240*2;
const unsigned int GAME_FPS = 60;
const unsigned int TICKS_PER_FRAME = 1000 / GAME_FPS;

SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Texture *frameTexture = NULL;

std::unique_ptr<SoundQueue> soundQueue;

Console console;

std::map<SDL_Keycode,Controller::Button> controllerKeyBinds;

void initSDL() {
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
	throw std::runtime_error(std::string("SDL_Init() failed: ") + SDL_GetError());
    }
}

void setTextureScaling() {
    // nearest pixel sampling (i.e. sharp pixels, no aliasing)
    if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0")) {
	throw std::runtime_error(std::string("SDL_SetHint() failed: ") + SDL_GetError());
    }
}

void createWindow() {
    window = SDL_CreateWindow(
        "ScootNES",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        SDL_WINDOW_SHOWN);
    if (window == NULL) {
	throw std::runtime_error(std::string("SDL_CreateWindow() failed: ") + SDL_GetError());
    }
}

void createRendererForWindow() {
    renderer = SDL_CreateRenderer(
        window,
        -1,
        SDL_RENDERER_ACCELERATED); // | SDL_RENDERER_PRESENTVSYNC);
    if (renderer == NULL) {
	throw std::runtime_error(std::string("SDL_CreateRenderer() failed: ") + SDL_GetError());
    }
}

void setRendererDrawColor() {
    // set colour used for drawing operations e.g. SDL_RenderClear
    SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
}

void createTextureForRenderer() {
    // create texture that we'll display and update each frame
    frameTexture = SDL_CreateTexture(
        renderer,
        SDL_GetWindowPixelFormat(window),
        SDL_TEXTUREACCESS_STREAMING,
        256,
        240);
    if (frameTexture == NULL) {
	throw std::runtime_error(std::string("SDL_CreateTexture() failed: ") + SDL_GetError());
    }
}

void initVideo() {
    initSDL();
    createWindow();
    createRendererForWindow();
    setRendererDrawColor();
    createTextureForRenderer();
    setTextureScaling();
}

void initSDLAudio() {
    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
	throw std::runtime_error(std::string("SDL_Init() failed: ") + SDL_GetError());
    }
}

void initSoundQueue() {
    soundQueue = std::unique_ptr<SoundQueue>(new SoundQueue);
    if (!soundQueue || soundQueue->init(44100)) {
	throw std::runtime_error(std::string("Sound queue init failed: ") + SDL_GetError());
    }
}

bool initSound() {
    initSDLAudio();
    initSoundQueue();
}

void freeAndQuitSDL() {
    SDL_DestroyTexture(frameTexture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    window = NULL;
    renderer = NULL;
    frameTexture = NULL;
    SDL_Quit();
}

void addControllerKeyBinds() {
    controllerKeyBinds[SDLK_UP]      = Controller::BUTTON_UP;
    controllerKeyBinds[SDLK_DOWN]    = Controller::BUTTON_DOWN;
    controllerKeyBinds[SDLK_LEFT]    = Controller::BUTTON_LEFT;
    controllerKeyBinds[SDLK_RIGHT]   = Controller::BUTTON_RIGHT;
    controllerKeyBinds[SDLK_z]       = Controller::BUTTON_A;
    controllerKeyBinds[SDLK_x]       = Controller::BUTTON_B;
    controllerKeyBinds[SDLK_SPACE]   = Controller::BUTTON_SELECT;
    controllerKeyBinds[SDLK_RETURN]  = Controller::BUTTON_START;
}

int main(int argc, char *args[]) {
    if (argc < 2) {
	printf("Rom path not provided\n");
	return 1;
    }

    try {
	initVideo();
	initSound();
    } catch (std::exception const& e) {
	printf(e.what());
	SDL_Quit();
	return 1;
    }

    std::string romFileName(args[1]);

    if (!console.loadINesFile(romFileName)) {
        printf("failed to read file\n");
        return 1;
    }

    console.boot();

    addControllerKeyBinds();

    // main loop
    bool isQuitting = false;
    bool isPaused = false;
    SDL_Event event;
    while (!isQuitting) {
        // track time elapsed during frame/loop
        unsigned int frameTimer = SDL_GetTicks();

        // handle events
        while (SDL_PollEvent(&event) != 0) {
            if (event.type == SDL_QUIT) {
                isQuitting = true;
            }
            else if (event.type == SDL_KEYDOWN) {
		SDL_Keycode sym = event.key.keysym.sym;
		if (controllerKeyBinds.count(sym) > 0) {
		    console.controller1.press(controllerKeyBinds[sym]);
		}
                else if (sym == SDLK_ESCAPE) {
                    isQuitting = true;
                }
                else if (sym == SDLK_p) {
                    isPaused ^= 1;
                }
            }
            else if (event.type == SDL_KEYUP) {
                SDL_Keycode sym = event.key.keysym.sym;
                if (controllerKeyBinds.count(sym) > 0) {
		    console.controller1.release(controllerKeyBinds[sym]);
		}
            }
        }

        // clear screen to black
        SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
        SDL_RenderClear(renderer);

        // spin cpu for 1 frame
        if (!isPaused) {
            console.runForOneFrame();
        }

        // apply frame buffer data to texture
        SDL_UpdateTexture(frameTexture, NULL, console.getFrameBuffer(), 256 * sizeof(uint32_t));

        // render the texture
        SDL_RenderCopy(renderer, frameTexture, NULL, NULL);

        // finally present render target to the window
        SDL_RenderPresent(renderer);

	// retrieve buffered sound samples
	APU::sample_t soundBuf[2048];
	long soundBufLength = console.apu.readSamples(soundBuf, 2048);

	// play samples in the buffer
	soundQueue->write(soundBuf, soundBufLength);

        // delay frame to enforce framerate
        frameTimer = SDL_GetTicks() - frameTimer;
        if (frameTimer < TICKS_PER_FRAME) {
            SDL_Delay(TICKS_PER_FRAME - frameTimer);
        }
    }

    // cleanup
    freeAndQuitSDL();

    return 0;
}
<|endoftext|>


<commit_before>#include "stdafx.h"

int main( int argc, char** argv )
{
	return 0;
}
<commit_msg>Fox unused parameters in main().<commit_after>#include "stdafx.h"

int main( int /*argc*/, char** /*argv*/ )
{
	return 0;
}
<|endoftext|>


<commit_before>//#include <exception>
#include <iostream>
#include <unistd.h>
#include <ctime>
//#include <cstdlib>

#include <cstring>
#include <sys/socket.h>
#include <netdb.h>

//#include <fastcgi.h>
#include <fcgio.h>

int getSocket(int port);
void diff(timespec start, timespec end);

int main(int argc, char** argv){
  timespec init, end;
  std::cout << "[INFO] Starting  Server on port 1234" << std::endl;
  int serverSocket = getSocket(9999);

  std::cout << "Got socket number " << serverSocket << std::endl;

  std::streambuf * cin_streambuf  = std::cin.rdbuf();
  std::streambuf * cout_streambuf = std::cout.rdbuf();
  std::streambuf * cerr_streambuf = std::cerr.rdbuf();

  FCGX_Request request;
  FCGX_Init();
  FCGX_InitRequest(&request, serverSocket, 0);

  int status = FCGX_Accept_r(&request);
  std::cout << "Accept status is " << status << std::endl;
  while(status == 0) {
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &init);
    std::cout << "Have a request" << std::endl;

    fcgi_streambuf cin_fcgi_streambuf(request.in);
    fcgi_streambuf cout_fcgi_streambuf(request.out);
    fcgi_streambuf cerr_fcgi_streambuf(request.err);

    std::cin.rdbuf(&cin_fcgi_streambuf);
    std::cout.rdbuf(&cout_fcgi_streambuf);
    std::cerr.rdbuf(&cerr_fcgi_streambuf);

    std::cout << "Centent-type: text/html\r\n\r\n";
    std::cout << "Hi there" << std::endl;
    FCGX_Finish_r(&request);

    std::cin.rdbuf(cin_streambuf);
    std::cout.rdbuf(cout_streambuf);
    std::cerr.rdbuf(cerr_streambuf);

    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
    diff(init, end);
    status = FCGX_Accept_r(&request);
  }
}

int getSocket(int port) {
  int status  = 0;
  int socketNumber = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  std::cout << "Socket number " << socketNumber << std::endl;

  struct sockaddr_in server;
  memset(&server, 0 , sizeof(server));
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = htonl(INADDR_ANY);
  server.sin_port = htons(port);

  status = bind(socketNumber, (struct sockaddr *) & server, sizeof(server));

  std::cout << "Bind status " << status << std::endl;

  listen(socketNumber, 32);
  return socketNumber;
}

void diff(timespec start, timespec end)
{
  timespec temp;
  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }
  std::cout << temp.tv_sec << ":" << temp.tv_nsec/1000000.0f << std::endl;
}

<commit_msg>/media/ -> Displayes all the fastcgi env variables received.<commit_after>//#include <exception>
#include <iostream>
#include <unistd.h>
#include <ctime>
//#include <cstdlib>

#include <cstring>
#include <sys/socket.h>
#include <netdb.h>

//#include <fastcgi.h>
#include <fcgio.h>

int getSocket(int port);
void diff(timespec start, timespec end);

int main(int argc, char** argv){
  timespec init, end;
  std::cout << "[INFO] Starting  Server on port 1234" << std::endl;
  int serverSocket = getSocket(9999);

  std::cout << "Got socket number " << serverSocket << std::endl;

  std::streambuf * cin_streambuf  = std::cin.rdbuf();
  std::streambuf * cout_streambuf = std::cout.rdbuf();
  std::streambuf * cerr_streambuf = std::cerr.rdbuf();

  FCGX_Request request;
  FCGX_Init();
  FCGX_InitRequest(&request, serverSocket, 0);

  int status = FCGX_Accept_r(&request);
  std::cout << "Accept status is " << status << std::endl;
  while(status == 0) {
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &init);
    std::cout << "Have a request" << std::endl;

    fcgi_streambuf cin_fcgi_streambuf(request.in);
    fcgi_streambuf cout_fcgi_streambuf(request.out);
    fcgi_streambuf cerr_fcgi_streambuf(request.err);

    std::cin.rdbuf(&cin_fcgi_streambuf);
    std::cout.rdbuf(&cout_fcgi_streambuf);
    std::cerr.rdbuf(&cerr_fcgi_streambuf);

    std::cout << "Centent-type: text/html\r\n\r\n";
    std::cout << "Hi there
" << std::endl;

    char **env = request.envp;
    while (*(++env))
      std::cout << *env << "
" << std::endl;

    std::cout << "" << std::endl;
    FCGX_Finish_r(&request);

    std::cin.rdbuf(cin_streambuf);
    std::cout.rdbuf(cout_streambuf);
    std::cerr.rdbuf(cerr_streambuf);

    clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
    diff(init, end);
    status = FCGX_Accept_r(&request);
  }
}

int getSocket(int port) {
  int status  = 0;
  int socketNumber = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  std::cout << "Socket number " << socketNumber << std::endl;

  struct sockaddr_in server;
  memset(&server, 0 , sizeof(server));
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = htonl(INADDR_ANY);
  server.sin_port = htons(port);

  status = bind(socketNumber, (struct sockaddr *) & server, sizeof(server));

  std::cout << "Bind status " << status << std::endl;

  listen(socketNumber, 32);
  return socketNumber;
}

void diff(timespec start, timespec end)
{
  timespec temp;
  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }
  std::cout << temp.tv_sec << ":" << temp.tv_nsec/1000000.0f << std::endl;
}

<|endoftext|>


<commit_before>#include <ArkeIndustries.CPPUtilities/Common.h>

#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <chrono>
#include <vector>

using namespace std;

class bf_interpreter {
	struct instruction {
		enum class opcode {
			add_to_dp,
			add_to_cell,
			output,
			input,
			branch_if_zero,
			branch_if_nonzero,
			store,
			add_cells
		};

		opcode op;
		sword data1;
		sword data2;
	};

	unique_ptr<uint8[]> memory;
	unique_ptr<uint8[]> raw_program;
	vector<instruction> program;
	word raw_size;
	word ip;
	word dp;

	word find_run(word start_index);
	word find_matched(word start_index);

	public:
		bf_interpreter(string filename);

		void parse();
		void print(string filename);
		void run();
};

bf_interpreter::bf_interpreter(string filename) {
	ifstream file(filename, ios::ate | ios::binary);

	this->raw_size = static_cast<word>(file.tellg());
	this->ip = 0;
	this->dp = 0;

	this->raw_program = make_unique<uint8[]>(this->raw_size);
	this->memory = make_unique<uint8[]>(65536);

	file.seekg(ios::beg);
	file.read(reinterpret_cast<char*>(this->raw_program.get()), this->raw_size);
	file.close();
}

void bf_interpreter::print(string filename) {
	ofstream file(filename);

	for (auto& i : this->program) {
		switch (i.op) {
			case instruction::opcode::add_to_dp: file << "ADD_DP\t" << i.data1; break;
			case instruction::opcode::add_to_cell: file << "ADD_CL\t" << i.data1; break;
			case instruction::opcode::add_cells: file << "ADD\t" << i.data1 << "\t" << i.data2; break;
			case instruction::opcode::output: file << "OUT\t"; break;
			case instruction::opcode::input: file << "IN\t"; break;
			case instruction::opcode::store: file << "STORE\t" << i.data1; break;
			case instruction::opcode::branch_if_zero: file << "BZ\t" << i.data1; break;
			case instruction::opcode::branch_if_nonzero: file << "BNZ\t" << i.data1; break;
		}

		file << endl;
	}
}

word bf_interpreter::find_run(word start_index) {
	auto character = this->raw_program[start_index];
	word count = 0;

	while (start_index < this->raw_size && this->raw_program[start_index++] == character)
		count++;

	return count;
}

word bf_interpreter::find_matched(word start_index) {
	word needed = 1;
	sword direction = this->program[start_index].op == instruction::opcode::branch_if_zero ? 1 : -1;

	while (needed) {
		start_index += direction;

		if (this->program[start_index].op == instruction::opcode::branch_if_zero)
			needed += direction;
		else if (this->program[start_index].op == instruction::opcode::branch_if_nonzero)
			needed -= direction;
	}

	return start_index;
}

void bf_interpreter::parse() {
	for (word i = 0; i < this->raw_size; i++) {
		instruction instr;

		instr.data1 = 0;
		instr.data2 = 0;

		switch (this->raw_program[i]) {
			case '>':
				instr.op = instruction::opcode::add_to_dp;
				instr.data1 = this->find_run(i);

				i += instr.data1 - 1;

				break;

			case '<':
				instr.op = instruction::opcode::add_to_dp;
				instr.data1 = -1 * this->find_run(i);

				i -= instr.data1 + 1;

				break;

			case '+':
				instr.op = instruction::opcode::add_to_cell;
				instr.data1 = this->find_run(i);

				i += instr.data1 - 1;

				break;

			case '-':
				instr.op = instruction::opcode::add_to_cell;
				instr.data1 = -1 * this->find_run(i);

				i -= instr.data1 + 1;

				break;

			case '.':
				instr.op = instruction::opcode::output;

				break;

			case ',':
				instr.op = instruction::opcode::input;

				break;

			case '[':
				instr.op = instruction::opcode::branch_if_zero;

				break;

			case ']':
				instr.op = instruction::opcode::branch_if_nonzero;

				break;

			default:
				continue;
		}

		this->program.push_back(instr);
	}

	for (word i = 0; i < this->program.size(); i++) {
		switch (this->program[i].op) {
			case instruction::opcode::branch_if_zero:
				if (i + 2 < this->program.size() && this->program[i + 1].op == instruction::opcode::add_to_cell && this->program[i + 1].data1 % 2 == 0 && this->program[i + 2].op == instruction::opcode::branch_if_nonzero) {
					this->program[i].op = instruction::opcode::store;
					this->program[i].data1 = 0;
					this->program.erase(this->program.begin() + i + 1, this->program.begin() + i + 3);

					continue;
				}
				else if (i + 5 < this->program.size() && this->program[i + 1].op == instruction::opcode::add_to_cell && this->program[i + 1].data1 == -1 && this->program[i + 5].op == instruction::opcode::branch_if_nonzero) {
					if (this->program[i + 2].op != instruction::opcode::add_to_dp || this->program[i + 4].op != instruction::opcode::add_to_dp || this->program[i + 3].op != instruction::opcode::add_to_cell)
						continue;
					if (this->program[i + 2].data1 < 0 && this->program[i + 4].data1 < 0)
						continue;
					if (this->program[i + 2].data1 >= 0 && this->program[i + 4].data1 >= 0)
						continue;

					this->program[i].op = instruction::opcode::add_cells;
					this->program[i].data1 = this->program[i + 2].data1;
					this->program[i].data2 = this->program[i + 3].data1;

					this->program[i + 1].op = instruction::opcode::store;
					this->program[i + 1].data1 = 0;

					this->program.erase(this->program.begin() + i + 2, this->program.begin() + i + 6);
				}

				break;
		}
	}

	for (word i = 0; i < this->program.size(); i++) {
		switch (this->program[i].op) {
			case instruction::opcode::branch_if_zero:
			case instruction::opcode::branch_if_nonzero:
				this->program[i].data1 = this->find_matched(i) + 1;

				break;
		}
	}
}

void bf_interpreter::run() {
	while (this->ip < this->program.size()) {
		auto instr = this->program[this->ip++];

		switch (instr.op) {
			case instruction::opcode::add_to_dp: this->dp += instr.data1; break;
			case instruction::opcode::add_to_cell: this->memory[this->dp] += static_cast<uint8>(instr.data1); break;
			case instruction::opcode::output: cout << this->memory[this->dp]; break;
			case instruction::opcode::input: cin >> this->memory[this->dp]; break;
			case instruction::opcode::store: this->memory[this->dp] = static_cast<uint8>(instr.data1); break;

			case instruction::opcode::add_cells:
				this->memory[this->dp + instr.data1] += static_cast<uint8>(instr.data2 * this->memory[this->dp]);

				break;

			case instruction::opcode::branch_if_zero:
				if (this->memory[this->dp] == 0)
					this->ip = instr.data1;

				break;

			case instruction::opcode::branch_if_nonzero:
				if (this->memory[this->dp] != 0)
					this->ip = instr.data1;

				break;
		}
	}
}

int main() {
	bf_interpreter bf("Mandlebrot.txt");
	bf.parse();
	bf.print("Output.txt");

	auto start = chrono::system_clock::now();
	bf.run();
	auto end = chrono::system_clock::now();

	cout << endl << endl << "Total Time: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << endl;

	system("pause");

	return 0;
}
<commit_msg>Removed dependency on util.<commit_after>#include <iostream>
#include <fstream>
#include <memory>
#include <string>
#include <chrono>
#include <vector>
#include <cstdint>

using namespace std;

class bf_interpreter {
	struct instruction {
		enum class opcode {
			add_to_dp,
			add_to_cell,
			output,
			input,
			branch_if_zero,
			branch_if_nonzero,
			store,
			add_cells
		};

		opcode op;
		int data1;
		int data2;
	};

	unique_ptr<uint8_t[]> memory;
	unique_ptr<uint8_t[]> raw_program;
	vector<instruction> program;
	size_t raw_size;
	size_t ip;
	size_t dp;

	size_t find_run(size_t start_index);
	size_t find_matched(size_t start_index);

	public:
		bf_interpreter(string filename);

		void parse();
		void print(string filename);
		void run();
};

bf_interpreter::bf_interpreter(string filename) {
	ifstream file(filename, ios::ate | ios::binary);

	this->raw_size = static_cast<size_t>(file.tellg());
	this->ip = 0;
	this->dp = 0;

	this->raw_program = make_unique<uint8_t[]>(this->raw_size);
	this->memory = make_unique<uint8_t[]>(65536);

	file.seekg(ios::beg);
	file.read(reinterpret_cast<char*>(this->raw_program.get()), this->raw_size);
	file.close();
}

void bf_interpreter::print(string filename) {
	ofstream file(filename);

	for (auto& i : this->program) {
		switch (i.op) {
			case instruction::opcode::add_to_dp: file << "ADD_DP\t" << i.data1; break;
			case instruction::opcode::add_to_cell: file << "ADD_CL\t" << i.data1; break;
			case instruction::opcode::add_cells: file << "ADD\t" << i.data1 << "\t" << i.data2; break;
			case instruction::opcode::output: file << "OUT\t"; break;
			case instruction::opcode::input: file << "IN\t"; break;
			case instruction::opcode::store: file << "STORE\t" << i.data1; break;
			case instruction::opcode::branch_if_zero: file << "BZ\t" << i.data1; break;
			case instruction::opcode::branch_if_nonzero: file << "BNZ\t" << i.data1; break;
		}

		file << endl;
	}
}

size_t bf_interpreter::find_run(size_t start_index) {
	auto character = this->raw_program[start_index];
	size_t count = 0;

	while (start_index < this->raw_size && this->raw_program[start_index++] == character)
		count++;

	return count;
}

size_t bf_interpreter::find_matched(size_t start_index) {
	size_t needed = 1;
	auto direction = this->program[start_index].op == instruction::opcode::branch_if_zero ? 1 : -1;

	while (needed) {
		start_index += direction;

		if (this->program[start_index].op == instruction::opcode::branch_if_zero)
			needed += direction;
		else if (this->program[start_index].op == instruction::opcode::branch_if_nonzero)
			needed -= direction;
	}

	return start_index;
}

void bf_interpreter::parse() {
	for (size_t i = 0; i < this->raw_size; i++) {
		instruction instr;

		instr.data1 = 0;
		instr.data2 = 0;

		switch (this->raw_program[i]) {
			case '>':
				instr.op = instruction::opcode::add_to_dp;
				instr.data1 = this->find_run(i);

				i += instr.data1 - 1;

				break;

			case '<':
				instr.op = instruction::opcode::add_to_dp;
				instr.data1 = -1 * this->find_run(i);

				i -= instr.data1 + 1;

				break;

			case '+':
				instr.op = instruction::opcode::add_to_cell;
				instr.data1 = this->find_run(i);

				i += instr.data1 - 1;

				break;

			case '-':
				instr.op = instruction::opcode::add_to_cell;
				instr.data1 = -1 * this->find_run(i);

				i -= instr.data1 + 1;

				break;

			case '.':
				instr.op = instruction::opcode::output;

				break;

			case ',':
				instr.op = instruction::opcode::input;

				break;

			case '[':
				instr.op = instruction::opcode::branch_if_zero;

				break;

			case ']':
				instr.op = instruction::opcode::branch_if_nonzero;

				break;

			default:
				continue;
		}

		this->program.push_back(instr);
	}

	for (size_t i = 0; i < this->program.size(); i++) {
		switch (this->program[i].op) {
			case instruction::opcode::branch_if_zero:
				if (i + 2 < this->program.size() && this->program[i + 1].op == instruction::opcode::add_to_cell && this->program[i + 1].data1 % 2 == 0 && this->program[i + 2].op == instruction::opcode::branch_if_nonzero) {
					this->program[i].op = instruction::opcode::store;
					this->program[i].data1 = 0;
					this->program.erase(this->program.begin() + i + 1, this->program.begin() + i + 3);

					continue;
				}
				else if (i + 5 < this->program.size() && this->program[i + 1].op == instruction::opcode::add_to_cell && this->program[i + 1].data1 == -1 && this->program[i + 5].op == instruction::opcode::branch_if_nonzero) {
					if (this->program[i + 2].op != instruction::opcode::add_to_dp || this->program[i + 4].op != instruction::opcode::add_to_dp || this->program[i + 3].op != instruction::opcode::add_to_cell)
						continue;
					if (this->program[i + 2].data1 < 0 && this->program[i + 4].data1 < 0)
						continue;
					if (this->program[i + 2].data1 >= 0 && this->program[i + 4].data1 >= 0)
						continue;

					this->program[i].op = instruction::opcode::add_cells;
					this->program[i].data1 = this->program[i + 2].data1;
					this->program[i].data2 = this->program[i + 3].data1;

					this->program[i + 1].op = instruction::opcode::store;
					this->program[i + 1].data1 = 0;

					this->program.erase(this->program.begin() + i + 2, this->program.begin() + i + 6);
				}

				break;
		}
	}

	for (size_t i = 0; i < this->program.size(); i++) {
		switch (this->program[i].op) {
			case instruction::opcode::branch_if_zero:
			case instruction::opcode::branch_if_nonzero:
				this->program[i].data1 = this->find_matched(i) + 1;

				break;
		}
	}
}

void bf_interpreter::run() {
	while (this->ip < this->program.size()) {
		auto instr = this->program[this->ip++];

		switch (instr.op) {
			case instruction::opcode::add_to_dp: this->dp += instr.data1; break;
			case instruction::opcode::add_to_cell: this->memory[this->dp] += static_cast<uint8_t>(instr.data1); break;
			case instruction::opcode::output: cout << this->memory[this->dp]; break;
			case instruction::opcode::input: cin >> this->memory[this->dp]; break;
			case instruction::opcode::store: this->memory[this->dp] = static_cast<uint8_t>(instr.data1); break;

			case instruction::opcode::add_cells:
				this->memory[this->dp + instr.data1] += static_cast<uint8_t>(instr.data2 * this->memory[this->dp]);

				break;

			case instruction::opcode::branch_if_zero:
				if (this->memory[this->dp] == 0)
					this->ip = instr.data1;

				break;

			case instruction::opcode::branch_if_nonzero:
				if (this->memory[this->dp] != 0)
					this->ip = instr.data1;

				break;
		}
	}
}

int main() {
	bf_interpreter bf("Hello World.txt");
	bf.parse();
	bf.print("Output.txt");

	auto start = chrono::system_clock::now();
	bf.run();
	auto end = chrono::system_clock::now();

	cout << endl << endl << "Total Time: " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << endl;

	system("pause");

	return 0;
}
<|endoftext|>


<commit_before>#include "twsDL.h"
#include "utilities/debug.h"

#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
	QCoreApplication app( argc, argv );

	if( argc > 3 ) {
		fprintf( stderr, "Usage: %s [configuration file] [worktodo file]\n", argv[0] );
		return 2;
	}
	QString workfile;
	if( argc == 3 ) {
		workfile = argv[2];
	}
	Test::TwsDL twsDL( argc == 2 ? argv[1] : "twsDL.cfg", workfile );
	QObject::connect( &twsDL, SIGNAL(finished()), &app, SLOT(quit()) );
	twsDL.start();
	int ret = app.exec();
	Q_ASSERT( ret == 0 );

	Test::TwsDL::State state = twsDL.currentState();
	Q_ASSERT( (state == Test::TwsDL::QUIT_READY) ||
		(state == Test::TwsDL::QUIT_ERROR) );
	if( state == Test::TwsDL::QUIT_READY ) {
		return 0;
	} else {
		qDebug() << "Finished with errors.";
		return 1;
	}
}
<commit_msg>twsDL, followup "reading workFile"<commit_after>#include "twsDL.h"
#include "utilities/debug.h"

#include <QtCore/QCoreApplication>
#include <stdio.h>

int main(int argc, char *argv[])
{
	QCoreApplication app( argc, argv );

	if( argc > 3 ) {
		fprintf( stderr, "Usage: %s [configuration file] [worktodo file]\n", argv[0] );
		return 2;
	}
	QString workfile;
	if( argc == 3 ) {
		workfile = argv[2];
	}
	Test::TwsDL twsDL( argc >= 2 ? argv[1] : "twsDL.cfg", workfile );
	QObject::connect( &twsDL, SIGNAL(finished()), &app, SLOT(quit()) );
	twsDL.start();
	int ret = app.exec();
	Q_ASSERT( ret == 0 );

	Test::TwsDL::State state = twsDL.currentState();
	Q_ASSERT( (state == Test::TwsDL::QUIT_READY) ||
		(state == Test::TwsDL::QUIT_ERROR) );
	if( state == Test::TwsDL::QUIT_READY ) {
		return 0;
	} else {
		qDebug() << "Finished with errors.";
		return 1;
	}
}
<|endoftext|>


<commit_before>#include <SDL2/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <cstdlib>

struct Window {
    const char * name = (const char *) "Game Of Life On fieldace";
    SDL_Window * window = nullptr;
    SDL_Renderer * render = nullptr;
    SDL_GLContext context;
    SDL_Event event;
    bool quit_flag = false;
    // bool button_left_set = false;
    // bool button_right_set = false;
    // bool game_step = false;
    // bool help_flag = false;
    int width = 640;
    int height = 640;
    // int counter = 0;
    // int mouse_x, mouse_y;
} gw;

GLUquadricObj * sphere;

void golos_panic( void ) {
    SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Error", SDL_GetError(), nullptr );
    exit( EXIT_FAILURE );
}

void golos_init( void ) {
    // init SDL subsystems
    if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS ) ) {
        golos_panic();
    }
    // init double buffer
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    // color configuration
    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 6 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
    // create SDL window
    gw.window =  SDL_CreateWindow( gw.name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        gw.width, gw.height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL );
    if ( gw.window == nullptr ) {
        golos_panic();
    }
    // init OpenGL context
    gw.context = SDL_GL_CreateContext( gw.window );
    // init OpenGL params
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    glClearDepth( 1.0 );
    glDepthFunc( GL_LESS );
    glEnable( GL_DEPTH_TEST );
    glShadeModel( GL_SMOOTH );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 45.0f, (float) gw.width / (float) gw.height, 0.1f, 100.0f );
    glMatrixMode( GL_MODELVIEW );
    // init sphere
    sphere = gluNewQuadric();
}

void golos_event( void ) {
    SDL_PollEvent( &( gw.event ) );
    switch ( gw.event.type ) {
        case SDL_QUIT:
            gw.quit_flag = true;
            break;
        default:
            break;
    }
}

void golos_loop( void ) {
    // input code
}

void golos_render( void ) {
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glColor3f( 0.0f, 1.0f, 0.0f );
    glLoadIdentity();
    glTranslatef( 0.0f, 0.0f, -4.0f );
    glRotatef( -45.0f, 1.0f, 0.0f, 0.0f );
    glPolygonMode( GL_BACK, GL_POINT );
    glPolygonMode( GL_FRONT, GL_LINE );
    glColor3f( 0.0f, 1.0f, 0.0f );
    gluSphere( sphere, 1.0f, 16, 16 );
    glFlush();
    SDL_GL_SwapWindow( gw.window );
}

void golos_destroy( void ) {
    gluDeleteQuadric( sphere );
    SDL_DestroyWindow( gw.window );
    SDL_Quit();
}

int main( int argc, char ** argv ) {
    float current = 0.0f, last = 0.0f;

    golos_init();
    while ( !gw.quit_flag ) {
        current = (float) SDL_GetTicks();
        if ( current > last + 1000.0f / 60.0f ) {
            golos_event();
            golos_loop();
            golos_render();
            last = current;
        }
    }
    golos_destroy();
    return EXIT_SUCCESS;
}<commit_msg>[add] camera rotation<commit_after>#include <SDL2/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <cstdlib>

float camera[] = {3,0,0}; // положение камеры в сферических координатах
float dtheta = 0.012;
float dphi = 0.01;

struct Window {
    const char * name = (const char *) "Game Of Life On sphere";
    SDL_Window * window = nullptr;
    SDL_Renderer * render = nullptr;
    SDL_GLContext context;
    SDL_Event event;
    bool quit_flag = false;
    // bool button_left_set = false;
    // bool button_right_set = false;
    // bool game_step = false;
    // bool help_flag = false;
    int width = 640;
    int height = 640;
    // int counter = 0;
    // int mouse_x, mouse_y;
} gw;

GLUquadricObj * sphere;

void golos_panic( void ) {
    SDL_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "Error", SDL_GetError(), nullptr );
    exit( EXIT_FAILURE );
}

void golos_init( void ) {
    // init SDL subsystems
    if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_EVENTS ) ) {
        golos_panic();
    }
    // init double buffer
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    // color configuration
    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 6 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
    // create SDL window
    gw.window =  SDL_CreateWindow( gw.name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        gw.width, gw.height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL );
    if ( gw.window == nullptr ) {
        golos_panic();
    }
    // init OpenGL context
    gw.context = SDL_GL_CreateContext( gw.window );
    // init OpenGL params
    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    glClearDepth( 1.0 );
    glDepthFunc( GL_LESS );
    glEnable( GL_DEPTH_TEST );
    glShadeModel( GL_SMOOTH );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 45.0f, (float) gw.width / (float) gw.height, 0.1f, 100.0f );
    glMatrixMode( GL_MODELVIEW );
    // init sphere
    sphere = gluNewQuadric();
}

void golos_event( void ) {
    SDL_PollEvent( &( gw.event ) );
    switch ( gw.event.type ) {
        case SDL_QUIT:
            gw.quit_flag = true;
            break;
        default:
            break;
    }
}

void golos_loop( void ) {
    // input code
}

void golos_render( void ) {
    float rect_camera[3]; // положение камеры в прямоугольных координатах
	rect_camera[0] = camera[0] * sin(camera[1]) * cos(camera[2]);
	rect_camera[1] = camera[0] * sin(camera[1]) * sin(camera[2]);
	rect_camera[2] = camera[0] * cos(camera[1]);
	camera[1] += dtheta;
	camera[2] += dphi;

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glColor3f( 0.0f, 1.0f, 0.0f );
    glLoadIdentity();
	gluLookAt(rect_camera[0], rect_camera[1], rect_camera[2], 0,  0, 0, 0, 1, 0);
    glTranslatef( 0.0f, 0.0f, 0.0f );
    glRotatef( -45.0f, 1.0f, 0.0f, 0.0f );
    glPolygonMode( GL_BACK, GL_POINT );
    glPolygonMode( GL_FRONT, GL_LINE );
    glColor3f( 0.0f, 1.0f, 0.0f );
    gluQuadricTexture(sphere, true);
    gluQuadricNormals(sphere, GLU_SMOOTH);
    gluSphere( sphere, 1.0f, 16, 16 );
    glFlush();
    SDL_GL_SwapWindow( gw.window );
}

void golos_destroy( void ) {
    gluDeleteQuadric( sphere );
    SDL_DestroyWindow( gw.window );
    SDL_Quit();
}

int main( int argc, char ** argv ) {
    float current = 0.0f, last = 0.0f;

    golos_init();
    while ( !gw.quit_flag ) {
        current = (float) SDL_GetTicks();
        if ( current > last + 1000.0f / 60.0f ) {
            golos_event();
            golos_loop();
            golos_render();
            last = current;
        }
    }
    golos_destroy();
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <iostream>

using namespace std;

int main() {
	return 0;
}
<commit_msg>began on the main part of the shell<commit_after>#include <iostream>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
using namespace std;

int main() {
        string userinput = "";
	while(userinput != "exit") {
		getline(cin, userinput);
	}
	return 0;
}
<|endoftext|>


<commit_before>#include <memory>
#include <iostream>
#include <string>
#include <sstream>
#include <functional>
#include <nan.h>
#include <v8.h>
#include <uv.h>

#include "log.h"
#include "queue.h"
#include "callbacks.h"
#include "worker/thread.h"

using namespace v8;
using std::unique_ptr;
using std::string;
using std::ostringstream;
using std::endl;

static void handle_events_helper(uv_async_t *handle);

class Main {
public:
  Main() : worker_thread{out, in, &event_handler}
  {
    int err;
    err = uv_async_init(uv_default_loop(), &event_handler, handle_events_helper);
    if (err) return;

    worker_thread.run();
  }

  void use_main_log_file(string &&main_log_file)
  {
    Logger::to_file(main_log_file.c_str());
  }

  void handle_events()
  {
    LOGGER << "Handling events." << endl;
  }

private:
  Queue in;
  Queue out;
  uv_async_t event_handler;

  WorkerThread worker_thread;
};

static Main instance;

static void handle_events_helper(uv_async_t *handle)
{
  instance.handle_events();
}

static bool get_string_option(Local<Object>& options, const char *key_name, string &out)
{
  Nan::HandleScope scope;
  const Local<String> key = Nan::New<String>(key_name).ToLocalChecked();

  Nan::MaybeLocal<Value> as_maybe_value = Nan::Get(options, key);
  if (as_maybe_value.IsEmpty()) {
    return true;
  }
  Local<Value> as_value = as_maybe_value.ToLocalChecked();
  if (as_value->IsUndefined()) {
    return true;
  }

  if (!as_value->IsString()) {
    ostringstream message;
    message << "configure() option " << key_name << " must be a String";
    Nan::ThrowError(message.str().c_str());
    return false;
  }

  Nan::Utf8String as_string(as_value);

  if (*as_string == nullptr) {
    ostringstream message;
    message << "configure() option " << key_name << " must be a valid UTF-8 String";
    Nan::ThrowError(message.str().c_str());
    return false;
  }

  out.assign(*as_string, as_string.length());
  return true;
}

void configure(const Nan::FunctionCallbackInfo<Value> &info)
{
  string main_log_file;
  string worker_log_file;

  Nan::MaybeLocal<Object> maybe_options = Nan::To<Object>(info[0]);
  if (maybe_options.IsEmpty()) {
    Nan::ThrowError("configure() requires an option object");
    return;
  }

  Local<Object> options = maybe_options.ToLocalChecked();
  if (!get_string_option(options, "mainLogFile", main_log_file)) return;
  if (!get_string_option(options, "workerLogFile", worker_log_file)) return;

  Nan::Callback *callback = new Nan::Callback(info[1].As<Function>());

  if (!main_log_file.empty()) {
    instance.use_main_log_file(move(main_log_file));
  }

  callback->Call(0, 0);
  delete callback;
}

void watch(const Nan::FunctionCallbackInfo<Value> &info)
{
  if (info.Length() != 2) {
    return Nan::ThrowError("watch() requires two arguments");
  }
}

void unwatch(const Nan::FunctionCallbackInfo<Value> &info)
{
  if (info.Length() != 2) {
    return Nan::ThrowError("watch() requires two arguments");
  }
}

void initialize(Local<Object> exports)
{
  exports->Set(
    Nan::New<String>("configure").ToLocalChecked(),
    Nan::GetFunction(Nan::New<FunctionTemplate>(configure)).ToLocalChecked()
  );
  exports->Set(
    Nan::New<String>("watch").ToLocalChecked(),
    Nan::GetFunction(Nan::New<FunctionTemplate>(watch)).ToLocalChecked()
  );
  exports->Set(
    Nan::New<String>("unwatch").ToLocalChecked(),
    Nan::GetFunction(Nan::New<FunctionTemplate>(unwatch)).ToLocalChecked()
  );
}

NODE_MODULE(sfw, initialize);
<commit_msg>Invoke a callback on configuration ack (and Command acks in general)<commit_after>#include <memory>
#include <iostream>
#include <string>
#include <sstream>
#include <functional>
#include <utility>
#include <unordered_map>
#include <vector>
#include <nan.h>
#include <v8.h>
#include <uv.h>

#include "log.h"
#include "queue.h"
#include "worker/worker_thread.h"

using v8::Local;
using v8::Value;
using v8::Object;
using v8::String;
using v8::Function;
using v8::FunctionTemplate;
using std::unique_ptr;
using std::string;
using std::ostringstream;
using std::endl;
using std::unordered_map;
using std::vector;
using std::move;
using std::make_pair;

static void handle_events_helper(uv_async_t *handle);

class Main {
public:
  Main() : worker_thread{&event_handler}
  {
    int err;

    next_command_id = 0;

    err = uv_async_init(uv_default_loop(), &event_handler, handle_events_helper);
    if (err) return;

    worker_thread.run();
  }

  void use_main_log_file(string &&main_log_file)
  {
    Logger::to_file(main_log_file.c_str());
  }

  void use_worker_log_file(string &&worker_log_file, unique_ptr<Nan::Callback> callback)
  {
    CommandID command_id = next_command_id;

    CommandPayload command_payload(next_command_id, COMMAND_LOG_FILE, move(worker_log_file));
    Message log_file_message(move(command_payload));

    pending_callbacks.emplace(command_id, move(callback));

    next_command_id++;

    LOGGER << "Sending command " << log_file_message << " to worker thread." << endl;
    worker_thread.send(move(log_file_message));
  }

  void handle_events()
  {
    Nan::HandleScope scope;

    LOGGER << "Handling messages from the worker thread." << endl;

    unique_ptr<vector<Message>> accepted = worker_thread.receive_all();
    if (!accepted) {
      LOGGER << "No messages waiting." << endl;
      return;
    }

    LOGGER << accepted->size() << " messages to process." << endl;

    for (auto it = accepted->begin(); it != accepted->end(); ++it) {
      const AckPayload *ack_message = it->as_ack();
      if (ack_message) {
        auto maybe_callback = pending_callbacks.find(ack_message->get_key());
        if (maybe_callback == pending_callbacks.end()) {
          LOGGER << "Ignoring unexpected ack " << *it << endl;
          continue;
        }

        unique_ptr<Nan::Callback> callback = move(maybe_callback->second);
        pending_callbacks.erase(maybe_callback);

        callback->Call(0, nullptr);
        continue;
      }

      const FileSystemPayload *filesystem_message = it->as_filesystem();
      if (filesystem_message) {
        LOGGER << "Received filesystem event message " << *it << endl;
        continue;
      }

      LOGGER << "Received unexpected message " << *it << endl;
    }
  }

private:
  uv_async_t event_handler;

  WorkerThread worker_thread;

  CommandID next_command_id;
  unordered_map<CommandID, unique_ptr<Nan::Callback>> pending_callbacks;
};

static Main instance;

static void handle_events_helper(uv_async_t *handle)
{
  instance.handle_events();
}

static bool get_string_option(Local<Object>& options, const char *key_name, string &out)
{
  Nan::HandleScope scope;
  const Local<String> key = Nan::New<String>(key_name).ToLocalChecked();

  Nan::MaybeLocal<Value> as_maybe_value = Nan::Get(options, key);
  if (as_maybe_value.IsEmpty()) {
    return true;
  }
  Local<Value> as_value = as_maybe_value.ToLocalChecked();
  if (as_value->IsUndefined()) {
    return true;
  }

  if (!as_value->IsString()) {
    ostringstream message;
    message << "configure() option " << key_name << " must be a String";
    Nan::ThrowError(message.str().c_str());
    return false;
  }

  Nan::Utf8String as_string(as_value);

  if (*as_string == nullptr) {
    ostringstream message;
    message << "configure() option " << key_name << " must be a valid UTF-8 String";
    Nan::ThrowError(message.str().c_str());
    return false;
  }

  out.assign(*as_string, as_string.length());
  return true;
}

void configure(const Nan::FunctionCallbackInfo<Value> &info)
{
  string main_log_file;
  string worker_log_file;
  bool async = false;

  Nan::MaybeLocal<Object> maybe_options = Nan::To<Object>(info[0]);
  if (maybe_options.IsEmpty()) {
    Nan::ThrowError("configure() requires an option object");
    return;
  }

  Local<Object> options = maybe_options.ToLocalChecked();
  if (!get_string_option(options, "mainLogFile", main_log_file)) return;
  if (!get_string_option(options, "workerLogFile", worker_log_file)) return;

  unique_ptr<Nan::Callback> callback(new Nan::Callback(info[1].As<Function>()));

  if (!main_log_file.empty()) {
    instance.use_main_log_file(move(main_log_file));
  }

  if (!worker_log_file.empty()) {
    instance.use_worker_log_file(move(worker_log_file), move(callback));
    async = true;
  }

  if (!async) {
    callback->Call(0, 0);
  }
}

void watch(const Nan::FunctionCallbackInfo<Value> &info)
{
  if (info.Length() != 2) {
    return Nan::ThrowError("watch() requires two arguments");
  }
}

void unwatch(const Nan::FunctionCallbackInfo<Value> &info)
{
  if (info.Length() != 2) {
    return Nan::ThrowError("watch() requires two arguments");
  }
}

void initialize(Local<Object> exports)
{
  exports->Set(
    Nan::New<String>("configure").ToLocalChecked(),
    Nan::GetFunction(Nan::New<FunctionTemplate>(configure)).ToLocalChecked()
  );
  exports->Set(
    Nan::New<String>("watch").ToLocalChecked(),
    Nan::GetFunction(Nan::New<FunctionTemplate>(watch)).ToLocalChecked()
  );
  exports->Set(
    Nan::New<String>("unwatch").ToLocalChecked(),
    Nan::GetFunction(Nan::New<FunctionTemplate>(unwatch)).ToLocalChecked()
  );
}

NODE_MODULE(sfw, initialize);
<|endoftext|>


<commit_before>/*****************************************************************************************
 *                                                                                *
 * MIT License                                                                           *
 *                                                                                *
 * Copyright (c) 2017 Maxime Pinard                                                      *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy          *
 * of this software and associated documentation files (the "Software"), to deal         *
 * in the Software without restriction, including without limitation the rights          *
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell             *
 * copies of the Software, and to permit persons to whom the Software is                 *
 * furnished to do so, subject to the following conditions:                              *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all        *
 * copies or substantial portions of the Software.                                       *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR            *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,              *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE           *
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                *
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,         *
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE         *
 * SOFTWARE.                                                                             *
 *                                                                                *
 *****************************************************************************************/

#include <ext_headers.hpp>

EXT_HEADERS_OPEN
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/Window/Event.hpp>

#include <imgui.h>
#include <imgui-SFML.h>

#include <iostream>
#include <cstring>
EXT_HEADERS_CLOSE

#include <imgui_easy_theming.hpp>
#include <ulltostr.hpp>
#include <clamp.hpp>

#define COUNT_OF(X) (sizeof(X)/sizeof(*(X)))

static const int minBase = 2;
static const int maxBase = 36;

struct TextFilters
{
	static int filterBase(ImGuiTextEditCallbackData* data)
	{
		if((data->EventChar >= '0' && data->EventChar < '0' + *(static_cast<int*>(data->UserData)))
		   || (data->EventChar >= 'A' && data->EventChar < 'A' + *(static_cast<int*>(data->UserData)) - 10))
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}
};

struct BaseBlock
{
	int base;
	char txt[128];

	explicit BaseBlock(int base_ = 10, const char* txt_ = "0")
	  : base(base_), txt()
	{
		std::strncpy(txt, txt_, 128);
	}
};

struct ThemeHolder
{
	const char name[12];
	const ImGuiColorTheme& colorTheme;
	bool enabled;
};

static void setupStyle();

void setupStyle()
{
	ImGuiStyle& style = ImGui::GetStyle();
	style.WindowRounding = 0.0f;
	style.ScrollbarRounding = 0.0f;
	ImGuiEasyTheming(ImGuiColorTheme::ArcDark);
}

int main()
{
	bool inputCustomBases = false;
	bool outputDefaultBases = true;
	bool outputCustomBases = false;

	int baseNb = 0;
	bool valUpd = false;
	bool baseUpd = false;
	bool tooBig = false;

	unsigned long long int value = 0;

	BaseBlock input{10};

	BaseBlock defaultBasesOut[]{
	  BaseBlock{10},
	  BaseBlock{16},
	  BaseBlock{8},
	  BaseBlock{2}
	};
	const char* defaultBasesOutDisplayTxt[]{
	  "DEC",
	  "HEX",
	  "OCT",
	  "BIN"
	};
	std::vector<BaseBlock> extraBasesOut{};

	std::vector<ThemeHolder> themeHolders{
	  ThemeHolder{"Arc Dark", ImGuiColorTheme::ArcDark, true},
	  ThemeHolder{"Flat UI", ImGuiColorTheme::FlatUI, false},
	  ThemeHolder{"Mint-Y-Dark", ImGuiColorTheme::MintYDark, false},
	};

	sf::Clock deltaClock;

	ImGui::GetIO().IniFilename = nullptr; // disable .ini saving
	setupStyle();

	sf::RenderWindow window(sf::VideoMode(300, 480), "Base converter");
	window.setVerticalSyncEnabled(true);
	ImGui::SFML::Init(window);

	errno = 0;
	ImGui::SetNextWindowPos(ImVec2(0, 0));

	while(window.isOpen())
	{
		sf::Event event{};
		while(window.pollEvent(event))
		{
			ImGui::SFML::ProcessEvent(event);

			if(event.type == sf::Event::Closed)
			{
				window.close();
			}
		}

		ImGui::SFML::Update(window, deltaClock.restart());
		ImGui::SetNextWindowSize(ImVec2{
		  static_cast<float>(window.getSize().x),
		  static_cast<float>(window.getSize().y)
		});
		ImGui::Begin("Main", nullptr,
		             ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
		             ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar);

		if(ImGui::BeginMenuBar())
		{
			if(ImGui::BeginMenu("Options"))
			{
				if(ImGui::BeginMenu("Color theme", true))
				{
					for(ThemeHolder& themeHolder : themeHolders)
					{
						if(ImGui::MenuItem(themeHolder.name, nullptr, themeHolder.enabled))
						{
							ImGuiEasyTheming(themeHolder.colorTheme);
							for(ThemeHolder& themeHolderBis : themeHolders)
							{
								themeHolderBis.enabled = false;
							}
							themeHolder.enabled = true;
						}
					}
					ImGui::EndMenu();
				}
				if(ImGui::MenuItem("Quit"))
				{
					ImGui::SFML::Shutdown();
					return EXIT_SUCCESS;
				}
				ImGui::EndMenu();
			}
			ImGui::EndMenuBar();
		}

		ImGui::PushItemWidth(-1);

		if(ImGui::CollapsingHeader("Input", ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen |
		                                    ImGuiTreeNodeFlags_Leaf))
		{
			if(inputCustomBases)
			{
				ImGui::PushItemWidth(-40);
				valUpd |= ImGui::InputText("Value##IN", input.txt, sizeof(input.txt),
				                           ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank |
				                           ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CallbackCharFilter,
				                           TextFilters::filterBase, &input.base);
				baseUpd |= ImGui::DragInt("Base", &input.base, 1, minBase, maxBase, "%.0f");
				input.base = clamp(input.base, minBase, maxBase);
				ImGui::PopItemWidth();
			}
			else
			{
				ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 50);
				valUpd |= ImGui::InputText("##IN", input.txt, sizeof(input.txt),
				                           ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank |
				                           ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CallbackCharFilter,
				                           TextFilters::filterBase, &input.base);
				ImGui::PopItemWidth();
				ImGui::PushItemWidth(50);
				ImGui::SameLine();
				if(ImGui::Combo("##base", &baseNb, defaultBasesOutDisplayTxt, COUNT_OF(defaultBasesOutDisplayTxt)))
				{
					input.base = defaultBasesOut[baseNb].base;
					baseUpd = true;
				}
				ImGui::PopItemWidth();
			}
		}

		if(valUpd)
		{
			errno = 0;
			value = std::strtoull(input.txt, nullptr, input.base);
			tooBig = errno != 0;

			if(tooBig)
			{
				for(BaseBlock& baseBlock : defaultBasesOut)
				{
					baseBlock.txt[0] = '\0';
				}
				for(BaseBlock& baseBlock : extraBasesOut)
				{
					baseBlock.txt[0] = '\0';
				}
			}
			else
			{
				for(BaseBlock& baseBlock : defaultBasesOut)
				{
					if(!ulltostr(value, baseBlock.base, baseBlock.txt, sizeof(baseBlock.txt)))
					{
						baseBlock.txt[0] = '\0';
					}
				}
				for(BaseBlock& baseBlock : extraBasesOut)
				{
					if(!ulltostr(value, baseBlock.base, baseBlock.txt, sizeof(baseBlock.txt)))
					{
						baseBlock.txt[0] = '\0';
					}
				}
			}
			valUpd = false;
		}

		if(baseUpd)
		{
			if(!ulltostr(value, input.base, input.txt, sizeof(input.txt)))
			{
				input.txt[0] = '0';
				input.txt[1] = '\0';
				valUpd = true;
			}
			baseUpd = false;
		}

		if(tooBig)
		{
			ImGui::TextColored(ImColor(255, 0, 0), "Value is too large");
		}

		if(outputDefaultBases)
		{
			const char* defaultOutputTxt = outputCustomBases ? "Default output" : "Output";
			if(ImGui::CollapsingHeader(defaultOutputTxt,
			                           ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen |
			                           ImGuiTreeNodeFlags_Leaf))
			{
				ImGui::PushItemWidth(-30);
				for(size_t i = 0; i < COUNT_OF(defaultBasesOut); ++i)
				{
					ImGui::InputText(defaultBasesOutDisplayTxt[i], defaultBasesOut[i].txt,
					                 sizeof(defaultBasesOut[i].txt),
					                 ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_ReadOnly);
				}
				ImGui::PopItemWidth();
			}
		}

		if(outputCustomBases)
		{
			const char* customOutputTxt = outputDefaultBases ? "Custom output" : "Output";
			if(ImGui::CollapsingHeader(customOutputTxt,
			                           ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen |
			                           ImGuiTreeNodeFlags_Leaf))
			{
				for(BaseBlock& baseBlock : extraBasesOut)
				{
					ImGui::PushItemWidth(-40);
					ImGui::PushID(&baseBlock);
					ImGui::InputText("Value", baseBlock.txt, sizeof(baseBlock.txt),
					                 ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_ReadOnly);
					if(ImGui::DragInt("Base", &baseBlock.base, 1, minBase, maxBase, "%.0f"))
					{
						baseBlock.base = clamp(baseBlock.base, minBase, maxBase);
						if(!ulltostr(value, baseBlock.base, baseBlock.txt, sizeof(baseBlock.txt)))
						{
							baseBlock.txt[0] = '\0';
						}
					}
					ImGui::PopID();
					ImGui::PopItemWidth();
					ImGui::Separator();
				}
				if(ImGui::Button("Add", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 20)))
				{
					extraBasesOut.emplace_back(defaultBasesOut[0].base, defaultBasesOut[0].txt);
				}
				ImGui::SameLine();
				if(ImGui::Button("Remove", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 20)))
				{
					if(!extraBasesOut.empty())
					{
						extraBasesOut.pop_back();
					}
				}
			}
		}

		if(ImGui::CollapsingHeader("Config", ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen))
		{
			ImGui::Checkbox("Input custom bases", &inputCustomBases);
			ImGui::Checkbox("Output default bases", &outputDefaultBases);
			ImGui::Checkbox("Output custom base", &outputCustomBases);
		}

		ImGui::PopItemWidth();

		ImGui::End();
		window.clear();
		ImGui::Render();
		window.display();
	}

	ImGui::SFML::Shutdown();
	return EXIT_SUCCESS;
}
<commit_msg>Added missing 's'<commit_after>/*****************************************************************************************
 *                                                                                *
 * MIT License                                                                           *
 *                                                                                *
 * Copyright (c) 2017 Maxime Pinard                                                      *
 *                                                                                *
 * Permission is hereby granted, free of charge, to any person obtaining a copy          *
 * of this software and associated documentation files (the "Software"), to deal         *
 * in the Software without restriction, including without limitation the rights          *
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell             *
 * copies of the Software, and to permit persons to whom the Software is                 *
 * furnished to do so, subject to the following conditions:                              *
 *                                                                                *
 * The above copyright notice and this permission notice shall be included in all        *
 * copies or substantial portions of the Software.                                       *
 *                                                                                *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR            *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,              *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE           *
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER                *
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,         *
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE         *
 * SOFTWARE.                                                                             *
 *                                                                                *
 *****************************************************************************************/

#include <ext_headers.hpp>

EXT_HEADERS_OPEN
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/Window/Event.hpp>

#include <imgui.h>
#include <imgui-SFML.h>

#include <iostream>
#include <cstring>
EXT_HEADERS_CLOSE

#include <imgui_easy_theming.hpp>
#include <ulltostr.hpp>
#include <clamp.hpp>

#define COUNT_OF(X) (sizeof(X)/sizeof(*(X)))

static const int minBase = 2;
static const int maxBase = 36;

struct TextFilters
{
	static int filterBase(ImGuiTextEditCallbackData* data)
	{
		if((data->EventChar >= '0' && data->EventChar < '0' + *(static_cast<int*>(data->UserData)))
		   || (data->EventChar >= 'A' && data->EventChar < 'A' + *(static_cast<int*>(data->UserData)) - 10))
		{
			return 0;
		}
		else
		{
			return 1;
		}
	}
};

struct BaseBlock
{
	int base;
	char txt[128];

	explicit BaseBlock(int base_ = 10, const char* txt_ = "0")
	  : base(base_), txt()
	{
		std::strncpy(txt, txt_, 128);
	}
};

struct ThemeHolder
{
	const char name[12];
	const ImGuiColorTheme& colorTheme;
	bool enabled;
};

static void setupStyle();

void setupStyle()
{
	ImGuiStyle& style = ImGui::GetStyle();
	style.WindowRounding = 0.0f;
	style.ScrollbarRounding = 0.0f;
	ImGuiEasyTheming(ImGuiColorTheme::ArcDark);
}

int main()
{
	bool inputCustomBases = false;
	bool outputDefaultBases = true;
	bool outputCustomBases = false;

	int baseNb = 0;
	bool valUpd = false;
	bool baseUpd = false;
	bool tooBig = false;

	unsigned long long int value = 0;

	BaseBlock input{10};

	BaseBlock defaultBasesOut[]{
	  BaseBlock{10},
	  BaseBlock{16},
	  BaseBlock{8},
	  BaseBlock{2}
	};
	const char* defaultBasesOutDisplayTxt[]{
	  "DEC",
	  "HEX",
	  "OCT",
	  "BIN"
	};
	std::vector<BaseBlock> extraBasesOut{};

	std::vector<ThemeHolder> themeHolders{
	  ThemeHolder{"Arc Dark", ImGuiColorTheme::ArcDark, true},
	  ThemeHolder{"Flat UI", ImGuiColorTheme::FlatUI, false},
	  ThemeHolder{"Mint-Y-Dark", ImGuiColorTheme::MintYDark, false},
	};

	sf::Clock deltaClock;

	ImGui::GetIO().IniFilename = nullptr; // disable .ini saving
	setupStyle();

	sf::RenderWindow window(sf::VideoMode(300, 480), "Base converter");
	window.setVerticalSyncEnabled(true);
	ImGui::SFML::Init(window);

	errno = 0;
	ImGui::SetNextWindowPos(ImVec2(0, 0));

	while(window.isOpen())
	{
		sf::Event event{};
		while(window.pollEvent(event))
		{
			ImGui::SFML::ProcessEvent(event);

			if(event.type == sf::Event::Closed)
			{
				window.close();
			}
		}

		ImGui::SFML::Update(window, deltaClock.restart());
		ImGui::SetNextWindowSize(ImVec2{
		  static_cast<float>(window.getSize().x),
		  static_cast<float>(window.getSize().y)
		});
		ImGui::Begin("Main", nullptr,
		             ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
		             ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar);

		if(ImGui::BeginMenuBar())
		{
			if(ImGui::BeginMenu("Options"))
			{
				if(ImGui::BeginMenu("Color theme", true))
				{
					for(ThemeHolder& themeHolder : themeHolders)
					{
						if(ImGui::MenuItem(themeHolder.name, nullptr, themeHolder.enabled))
						{
							ImGuiEasyTheming(themeHolder.colorTheme);
							for(ThemeHolder& themeHolderBis : themeHolders)
							{
								themeHolderBis.enabled = false;
							}
							themeHolder.enabled = true;
						}
					}
					ImGui::EndMenu();
				}
				if(ImGui::MenuItem("Quit"))
				{
					ImGui::SFML::Shutdown();
					return EXIT_SUCCESS;
				}
				ImGui::EndMenu();
			}
			ImGui::EndMenuBar();
		}

		ImGui::PushItemWidth(-1);

		if(ImGui::CollapsingHeader("Input", ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen |
		                                    ImGuiTreeNodeFlags_Leaf))
		{
			if(inputCustomBases)
			{
				ImGui::PushItemWidth(-40);
				valUpd |= ImGui::InputText("Value##IN", input.txt, sizeof(input.txt),
				                           ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank |
				                           ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CallbackCharFilter,
				                           TextFilters::filterBase, &input.base);
				baseUpd |= ImGui::DragInt("Base", &input.base, 1, minBase, maxBase, "%.0f");
				input.base = clamp(input.base, minBase, maxBase);
				ImGui::PopItemWidth();
			}
			else
			{
				ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 50);
				valUpd |= ImGui::InputText("##IN", input.txt, sizeof(input.txt),
				                           ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank |
				                           ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_CallbackCharFilter,
				                           TextFilters::filterBase, &input.base);
				ImGui::PopItemWidth();
				ImGui::PushItemWidth(50);
				ImGui::SameLine();
				if(ImGui::Combo("##base", &baseNb, defaultBasesOutDisplayTxt, COUNT_OF(defaultBasesOutDisplayTxt)))
				{
					input.base = defaultBasesOut[baseNb].base;
					baseUpd = true;
				}
				ImGui::PopItemWidth();
			}
		}

		if(valUpd)
		{
			errno = 0;
			value = std::strtoull(input.txt, nullptr, input.base);
			tooBig = errno != 0;

			if(tooBig)
			{
				for(BaseBlock& baseBlock : defaultBasesOut)
				{
					baseBlock.txt[0] = '\0';
				}
				for(BaseBlock& baseBlock : extraBasesOut)
				{
					baseBlock.txt[0] = '\0';
				}
			}
			else
			{
				for(BaseBlock& baseBlock : defaultBasesOut)
				{
					if(!ulltostr(value, baseBlock.base, baseBlock.txt, sizeof(baseBlock.txt)))
					{
						baseBlock.txt[0] = '\0';
					}
				}
				for(BaseBlock& baseBlock : extraBasesOut)
				{
					if(!ulltostr(value, baseBlock.base, baseBlock.txt, sizeof(baseBlock.txt)))
					{
						baseBlock.txt[0] = '\0';
					}
				}
			}
			valUpd = false;
		}

		if(baseUpd)
		{
			if(!ulltostr(value, input.base, input.txt, sizeof(input.txt)))
			{
				input.txt[0] = '0';
				input.txt[1] = '\0';
				valUpd = true;
			}
			baseUpd = false;
		}

		if(tooBig)
		{
			ImGui::TextColored(ImColor(255, 0, 0), "Value is too large");
		}

		if(outputDefaultBases)
		{
			const char* defaultOutputTxt = outputCustomBases ? "Default output" : "Output";
			if(ImGui::CollapsingHeader(defaultOutputTxt,
			                           ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen |
			                           ImGuiTreeNodeFlags_Leaf))
			{
				ImGui::PushItemWidth(-30);
				for(size_t i = 0; i < COUNT_OF(defaultBasesOut); ++i)
				{
					ImGui::InputText(defaultBasesOutDisplayTxt[i], defaultBasesOut[i].txt,
					                 sizeof(defaultBasesOut[i].txt),
					                 ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_ReadOnly);
				}
				ImGui::PopItemWidth();
			}
		}

		if(outputCustomBases)
		{
			const char* customOutputTxt = outputDefaultBases ? "Custom output" : "Output";
			if(ImGui::CollapsingHeader(customOutputTxt,
			                           ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen |
			                           ImGuiTreeNodeFlags_Leaf))
			{
				for(BaseBlock& baseBlock : extraBasesOut)
				{
					ImGui::PushItemWidth(-40);
					ImGui::PushID(&baseBlock);
					ImGui::InputText("Value", baseBlock.txt, sizeof(baseBlock.txt),
					                 ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_ReadOnly);
					if(ImGui::DragInt("Base", &baseBlock.base, 1, minBase, maxBase, "%.0f"))
					{
						baseBlock.base = clamp(baseBlock.base, minBase, maxBase);
						if(!ulltostr(value, baseBlock.base, baseBlock.txt, sizeof(baseBlock.txt)))
						{
							baseBlock.txt[0] = '\0';
						}
					}
					ImGui::PopID();
					ImGui::PopItemWidth();
					ImGui::Separator();
				}
				if(ImGui::Button("Add", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 20)))
				{
					extraBasesOut.emplace_back(defaultBasesOut[0].base, defaultBasesOut[0].txt);
				}
				ImGui::SameLine();
				if(ImGui::Button("Remove", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 20)))
				{
					if(!extraBasesOut.empty())
					{
						extraBasesOut.pop_back();
					}
				}
			}
		}

		if(ImGui::CollapsingHeader("Config", ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_DefaultOpen))
		{
			ImGui::Checkbox("Input custom bases", &inputCustomBases);
			ImGui::Checkbox("Output default bases", &outputDefaultBases);
			ImGui::Checkbox("Output custom bases", &outputCustomBases);
		}

		ImGui::PopItemWidth();

		ImGui::End();
		window.clear();
		ImGui::Render();
		window.display();
	}

	ImGui::SFML::Shutdown();
	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2014, Richard Martin
All rights reserved.

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 Richard Martin 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 RICHARD MARTIN 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 "BookReader.hpp"
#include "MainWindow.hpp"

#include <gtkmm/application.h>
#include <gtkmm/window.h>

using namespace Glib;
using namespace Gtk;

HeaderBar * header_bar;

int main(int argc, char* argv[])
{
	/*Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");

	Gtk::Window window;
	window.set_title("Drawing text example");

	window.set_default_size(600,900);

	BookReader area;
	window.add(area);
	area.show();

	return app->run(window); */

	RefPtr<Application> app = Application::create(argc, argv, "org.rmarti.dnd");

	MainWindow window;

	// Shows the window and returns when it is closed.
	return app->run(window);
}<commit_msg>Clean the cruft out of main<commit_after>/*
Copyright (c) 2014, Richard Martin
All rights reserved.

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 Richard Martin 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 RICHARD MARTIN 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 "BookReader.hpp"
#include "MainWindow.hpp"

#include <gtkmm/application.h>
#include <gtkmm/window.h>

using namespace Glib;
using namespace Gtk;

HeaderBar * header_bar;

int main(int argc, char* argv[])
{

	RefPtr<Application> app = Application::create(argc, argv, "org.rmarti.dnd");

	MainWindow window;

	return app->run(window);
}<|endoftext|>


<commit_before>/*
 * Author: doe300
 *
 * See the file "LICENSE" for the full license governing this code.
 */

#include "./optimization/Optimizer.h"
#include "Compiler.h"
#include "Precompiler.h"
#include "Profiler.h"
#include "concepts.h"
#include "config.h"
#include "log.h"
#include "tools.h"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <unistd.h>
#include <unordered_map>

using namespace std;
using namespace vc4c;

extern void disassemble(const std::string& input, const std::string& output, const OutputMode outputMode);

static void printHelp()
{
    vc4c::Configuration defaultConfig;
    std::cout << "Usage: vc4c [flags] [options] -o <destination> <sources>" << std::endl;
    std::cout << "flags:" << std::endl;
    std::cout << "\t-h, --help\t\tPrints this help message and exits" << std::endl;
    std::cout << "\t-v, --version\t\tPrints version and build info and exists" << std::endl;
    std::cout << "\t--verbose\t\tEnables verbose debug logging" << std::endl;
    std::cout << "\t--quiet\t\t\tQuiet verbose debug logging" << std::endl;
    std::cout << "\t-l, --log <file>\tWrite log output to the given file, defaults to stdout ('-')" << std::endl;
    std::cout << "\t--hex\t\t\tGenerate hex output (e.g. included in source-code)" << std::endl;
    std::cout << "\t--bin\t\t\tGenerate binary output (as used by VC4CL run-time)" << std::endl;
    std::cout << "\t--asm\t\t\tGenerate assembler output (for analysis only)" << std::endl;

    std::cout << "optimizations:" << std::endl;
    std::cout << "\t-O0,-O1,-O2,-O3\t\t\tSwitches to the specific optimization level, defaults to -O2" << std::endl;
    for(const auto& pass : vc4c::optimizations::Optimizer::ALL_PASSES)
    {
        std::cout << "\t--f" << std::left << std::setw(28) << pass.parameterName << pass.description << std::endl;
        // TODO print which optimization level includes optimization
        std::cout << "\t--fno-" << std::left << std::setw(25) << pass.parameterName << "Disables the above optimization"
                  << std::endl;
    }

    std::cout << "optimization parameters:" << std::endl;
    std::cout << "\t--fcombine-load-threshold=" << defaultConfig.additionalOptions.combineLoadThreshold
              << "\tThe maximum distance between two literal loads to combine" << std::endl;
    std::cout << "\t--faccumulator-threshold=" << defaultConfig.additionalOptions.accumulatorThreshold
              << "\tThe maximum live-range of a local still considered to be mapped to an accumulator" << std::endl;
    std::cout << "\t--freplace-nop-threshold=" << defaultConfig.additionalOptions.replaceNopThreshold
              << "\tThe number of instructions to search for a replacement for NOPs" << std::endl;
    std::cout << "\t--fregister-resolver-rounds=" << defaultConfig.additionalOptions.registerResolverMaxRounds
              << "\tThe maximum number of rows for the register allocator" << std::endl;
    std::cout << "\t--fmove-constants-depth=" << defaultConfig.additionalOptions.moveConstantsDepth
              << "\tThe maximum depth of nested loops to move constants out of" << std::endl;
    std::cout << "\t--foptimization-iterations=" << defaultConfig.additionalOptions.maxOptimizationIterations
              << "\tThe maximum number of iterations to repeat the optimizations in" << std::endl;

    std::cout << "options:" << std::endl;
    std::cout << "\t--kernel-info\t\tWrite the kernel-info meta-data (as required by VC4CL run-time, default)"
              << std::endl;
    std::cout << "\t--no-kernel-info\tDont write the kernel-info meta-data" << std::endl;
    std::cout << "\t--spirv\t\t\tExplicitely use the SPIR-V front-end" << std::endl;
    std::cout << "\t--llvm\t\t\tExplicitely use the LLVM-IR front-end" << std::endl;
    std::cout << "\t--disassemble\t\tDisassembles the binary input to either hex or assembler output" << std::endl;
    std::cout << "\tany other option is passed to the pre-compiler" << std::endl;
}

#ifndef LLVM_LIBRARY_VERSION
#define LLVM_LIBRARY_VERSION 0
#endif
#ifndef VC4C_VERSION
#define VC4C_VERSION ""
#endif

static std::string toVersionString(unsigned version)
{
    std::stringstream s;
    s << (version / 10.0f);
    return s.str();
}

static void printInfo()
{
    std::cout << "Running VC4C in version: " << VC4C_VERSION << std::endl;
    std::cout << "Build configuration:" << std::endl;
    static const std::vector<std::string> infoString = {
#ifdef DEBUG_MODE
        "debug mode",
#endif
#ifdef MULTI_THREADED
        "multi-threaded optimization",
#endif
#ifdef USE_CLANG_OPENCL
        "clang 3.9+ OpenCL features",
#endif
#if defined SPIRV_CLANG_PATH
        "SPIRV-LLVM clang in " SPIRV_CLANG_PATH,
#if defined SPIRV_LLVM_SPIRV_PATH and defined SPIRV_FRONTEND
        "SPIR-V front-end",
#endif
#elif defined CLANG_PATH
        "clang in " CLANG_PATH,
#endif
#ifdef USE_LLVM_LIBRARY
        std::string("LLVM library front-end with libLLVM ") + toVersionString(LLVM_LIBRARY_VERSION),
#endif
#ifdef VC4CL_STDLIB_HEADER
        "VC4CL standard-library in " VC4CL_STDLIB_HEADER,
#endif
#ifdef SPIRV_FRONTEND
        "SPIR-V linker",
#endif
#ifdef VERIFIER_HEADER
        "vc4asm verification"
#endif
    };

    std::cout << vc4c::to_string<std::string>(infoString, "; ") << std::endl;
}

static auto availableOptimizations = vc4c::optimizations::Optimizer::getPasses(OptimizationLevel::FULL);

/*
 *
 */
int main(int argc, char** argv)
{
    std::unique_ptr<std::wofstream> fileLog;
    std::reference_wrapper<std::wostream> logStream = std::wcout;
    bool colorLog = true;
#if DEBUG_MODE
    LogLevel minLevel = LogLevel::DEBUG;
#else
    LogLevel minLevel = LogLevel::WARNING;
#endif

    Configuration config;
    std::vector<std::string> inputFiles;
    std::string outputFile;
    std::string options;
    bool runDisassembler = false;

    int i = 1;
    for(; i < argc; ++i)
    {
        // treat an argument, which first character isnt "-", as an input file
        if(argv[i][0] != '-')
        {
            inputFiles.emplace_back(argv[i]);
        }

        // flags
        else if(strcmp("--help", argv[i]) == 0 || strcmp("-h", argv[i]) == 0)
        {
            printHelp();
            return 0;
        }
        else if(strcmp("--version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0)
        {
            printInfo();
            return 0;
        }
        else if(strcmp("--quiet", argv[i]) == 0)
            minLevel = LogLevel::WARNING;
        else if(strcmp("--verbose", argv[i]) == 0)
            minLevel = LogLevel::DEBUG;
        else if(strcmp("--log", argv[i]) == 0 || strcmp("-l", argv[i]) == 0)
        {
            if(strcmp("-", argv[i + 1]) == 0)
            {
                colorLog = true;
                logStream = std::wcout;
            }
            else
            {
                colorLog = false;
                fileLog.reset(new std::wofstream(argv[i + 1]));
                logStream = *fileLog;
            }
            ++i;
        }
        else if(strcmp("--disassemble", argv[i]) == 0)
            runDisassembler = true;
        else if(strcmp("-o", argv[i]) == 0)
        {
            outputFile = argv[i + 1];
            // any further parameter is an input-file
            i += 2;
            break;
        }
        else if(!vc4c::tools::parseConfigurationParameter(config, argv[i]) || strstr(argv[i], "-cl") == argv[i])
            // pass every not understood option to the pre-compiler, as well as every OpenCL compiler option
            options.append(argv[i]).append(" ");
    }

    if(&logStream.get() == &std::wcout && outputFile == "-")
    {
        std::cerr << "Cannot write both log and data to stdout, aborting" << std::endl;
        return 6;
    }
    setLogger(logStream, colorLog, minLevel);

    if(inputFiles.empty())
    {
        std::cerr << "No input file(s) specified, aborting!" << std::endl;
        return 2;
    }
    if(outputFile.empty())
    {
        // special case: if input files is just one, we specify the implicit output file.
        std::string postfix;
        if(inputFiles.size() == 1)
        {
            switch(config.outputMode)
            {
            case OutputMode::BINARY:
                postfix = ".bin";
                break;
            case OutputMode::HEX:
                postfix = ".hex";
                break;
            case OutputMode::ASSEMBLER:
                postfix = ".s";
                break;
            }
            outputFile = inputFiles[0] + postfix;
        }
        else
        {
            std::cerr << "No output file specified, aborting!" << std::endl;
            return 3;
        }
    }

    if(runDisassembler)
    {
        if(inputFiles.size() != 1)
        {
            std::cerr << "For disassembling, a single input file must be specified, aborting!" << std::endl;
            return 4;
        }
        logging::debug() << "Disassembling '" << inputFiles[0] << "' into '" << outputFile << "'..." << logging::endl;
        disassemble(inputFiles[0], outputFile, config.outputMode);
        return 0;
    }

    logging::debug() << "Compiling '" << to_string<std::string>(inputFiles, "', '") << "' into '" << outputFile
                     << "' with optimization level " << static_cast<unsigned>(config.optimizationLevel)
                     << " and options '" << options << "' ..." << logging::endl;

    Optional<std::string> inputFile;
    std::unique_ptr<std::istream> input;
    // link if necessary
    if(inputFiles.size() > 1)
    {
        std::vector<std::unique_ptr<std::istream>> fileStreams;
        std::unordered_map<std::istream*, Optional<std::string>> inputs;
        for(const std::string& file : inputFiles)
        {
            auto ifs = new std::ifstream(file);
            if(!ifs->is_open())
                throw CompilationError(CompilationStep::PRECOMPILATION, "cannot find file", file);
            fileStreams.emplace_back(ifs);
            inputs.emplace(fileStreams.back().get(), Optional<std::string>(file));
        }
        input.reset(new std::stringstream());
        SourceType linkedType = Precompiler::linkSourceCode(inputs, *reinterpret_cast<std::ostream*>(input.get()));
        if(!isSupportedByFrontend(linkedType, config.frontend))
        {
            std::cerr << "Selected front-end does not support the input-format generated by the linker, aborting! "
                      << std::endl;
            return 5;
        }
    }
    else
    {
        const auto& file = inputFiles[0];
        auto ifs = new std::ifstream(file);
        if(!ifs->is_open())
            throw CompilationError(CompilationStep::PRECOMPILATION, "cannot find file", file);
        input.reset(ifs);
        inputFile = inputFiles[0];
    }

    std::ofstream output(outputFile == "-" ? "/dev/stdout" : outputFile,
        std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
    PROFILE_START(Compiler);
    Compiler::compile(*input, output, config, options, inputFile);
    PROFILE_END(Compiler);

    PROFILE_RESULTS();
    return 0;
}
<commit_msg>Fix: add guard when there is no argument<commit_after>/*
 * Author: doe300
 *
 * See the file "LICENSE" for the full license governing this code.
 */

#include "./optimization/Optimizer.h"
#include "Compiler.h"
#include "Precompiler.h"
#include "Profiler.h"
#include "concepts.h"
#include "config.h"
#include "log.h"
#include "tools.h"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <unistd.h>
#include <unordered_map>

using namespace std;
using namespace vc4c;

extern void disassemble(const std::string& input, const std::string& output, const OutputMode outputMode);

static void printHelp()
{
    vc4c::Configuration defaultConfig;
    std::cout << "Usage: vc4c [flags] [options] -o <destination> <sources>" << std::endl;
    std::cout << "flags:" << std::endl;
    std::cout << "\t-h, --help\t\tPrints this help message and exits" << std::endl;
    std::cout << "\t-v, --version\t\tPrints version and build info and exists" << std::endl;
    std::cout << "\t--verbose\t\tEnables verbose debug logging" << std::endl;
    std::cout << "\t--quiet\t\t\tQuiet verbose debug logging" << std::endl;
    std::cout << "\t-l, --log <file>\tWrite log output to the given file, defaults to stdout ('-')" << std::endl;
    std::cout << "\t--hex\t\t\tGenerate hex output (e.g. included in source-code)" << std::endl;
    std::cout << "\t--bin\t\t\tGenerate binary output (as used by VC4CL run-time)" << std::endl;
    std::cout << "\t--asm\t\t\tGenerate assembler output (for analysis only)" << std::endl;

    std::cout << "optimizations:" << std::endl;
    std::cout << "\t-O0,-O1,-O2,-O3\t\t\tSwitches to the specific optimization level, defaults to -O2" << std::endl;
    for(const auto& pass : vc4c::optimizations::Optimizer::ALL_PASSES)
    {
        std::cout << "\t--f" << std::left << std::setw(28) << pass.parameterName << pass.description << std::endl;
        // TODO print which optimization level includes optimization
        std::cout << "\t--fno-" << std::left << std::setw(25) << pass.parameterName << "Disables the above optimization"
                  << std::endl;
    }

    std::cout << "optimization parameters:" << std::endl;
    std::cout << "\t--fcombine-load-threshold=" << defaultConfig.additionalOptions.combineLoadThreshold
              << "\tThe maximum distance between two literal loads to combine" << std::endl;
    std::cout << "\t--faccumulator-threshold=" << defaultConfig.additionalOptions.accumulatorThreshold
              << "\tThe maximum live-range of a local still considered to be mapped to an accumulator" << std::endl;
    std::cout << "\t--freplace-nop-threshold=" << defaultConfig.additionalOptions.replaceNopThreshold
              << "\tThe number of instructions to search for a replacement for NOPs" << std::endl;
    std::cout << "\t--fregister-resolver-rounds=" << defaultConfig.additionalOptions.registerResolverMaxRounds
              << "\tThe maximum number of rows for the register allocator" << std::endl;
    std::cout << "\t--fmove-constants-depth=" << defaultConfig.additionalOptions.moveConstantsDepth
              << "\tThe maximum depth of nested loops to move constants out of" << std::endl;
    std::cout << "\t--foptimization-iterations=" << defaultConfig.additionalOptions.maxOptimizationIterations
              << "\tThe maximum number of iterations to repeat the optimizations in" << std::endl;

    std::cout << "options:" << std::endl;
    std::cout << "\t--kernel-info\t\tWrite the kernel-info meta-data (as required by VC4CL run-time, default)"
              << std::endl;
    std::cout << "\t--no-kernel-info\tDont write the kernel-info meta-data" << std::endl;
    std::cout << "\t--spirv\t\t\tExplicitely use the SPIR-V front-end" << std::endl;
    std::cout << "\t--llvm\t\t\tExplicitely use the LLVM-IR front-end" << std::endl;
    std::cout << "\t--disassemble\t\tDisassembles the binary input to either hex or assembler output" << std::endl;
    std::cout << "\tany other option is passed to the pre-compiler" << std::endl;
}

#ifndef LLVM_LIBRARY_VERSION
#define LLVM_LIBRARY_VERSION 0
#endif
#ifndef VC4C_VERSION
#define VC4C_VERSION ""
#endif

static std::string toVersionString(unsigned version)
{
    std::stringstream s;
    s << (version / 10.0f);
    return s.str();
}

static void printInfo()
{
    std::cout << "Running VC4C in version: " << VC4C_VERSION << std::endl;
    std::cout << "Build configuration:" << std::endl;
    static const std::vector<std::string> infoString = {
#ifdef DEBUG_MODE
        "debug mode",
#endif
#ifdef MULTI_THREADED
        "multi-threaded optimization",
#endif
#ifdef USE_CLANG_OPENCL
        "clang 3.9+ OpenCL features",
#endif
#if defined SPIRV_CLANG_PATH
        "SPIRV-LLVM clang in " SPIRV_CLANG_PATH,
#if defined SPIRV_LLVM_SPIRV_PATH and defined SPIRV_FRONTEND
        "SPIR-V front-end",
#endif
#elif defined CLANG_PATH
        "clang in " CLANG_PATH,
#endif
#ifdef USE_LLVM_LIBRARY
        std::string("LLVM library front-end with libLLVM ") + toVersionString(LLVM_LIBRARY_VERSION),
#endif
#ifdef VC4CL_STDLIB_HEADER
        "VC4CL standard-library in " VC4CL_STDLIB_HEADER,
#endif
#ifdef SPIRV_FRONTEND
        "SPIR-V linker",
#endif
#ifdef VERIFIER_HEADER
        "vc4asm verification"
#endif
    };

    std::cout << vc4c::to_string<std::string>(infoString, "; ") << std::endl;
}

static auto availableOptimizations = vc4c::optimizations::Optimizer::getPasses(OptimizationLevel::FULL);

/*
 *
 */
int main(int argc, char** argv)
{
    std::unique_ptr<std::wofstream> fileLog;
    std::reference_wrapper<std::wostream> logStream = std::wcout;
    bool colorLog = true;
#if DEBUG_MODE
    LogLevel minLevel = LogLevel::DEBUG;
#else
    LogLevel minLevel = LogLevel::WARNING;
#endif

    Configuration config;
    std::vector<std::string> inputFiles;
    std::string outputFile;
    std::string options;
    bool runDisassembler = false;

    if (argc == 1)
    {
        printHelp();
        return 0;
    }

    int i = 1;
    for(; i < argc; ++i)
    {
        // treat an argument, which first character isnt "-", as an input file
        if(argv[i][0] != '-')
        {
            inputFiles.emplace_back(argv[i]);
        }

        // flags
        else if(strcmp("--help", argv[i]) == 0 || strcmp("-h", argv[i]) == 0)
        {
            printHelp();
            return 0;
        }
        else if(strcmp("--version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0)
        {
            printInfo();
            return 0;
        }
        else if(strcmp("--quiet", argv[i]) == 0)
            minLevel = LogLevel::WARNING;
        else if(strcmp("--verbose", argv[i]) == 0)
            minLevel = LogLevel::DEBUG;
        else if(strcmp("--log", argv[i]) == 0 || strcmp("-l", argv[i]) == 0)
        {
            if(strcmp("-", argv[i + 1]) == 0)
            {
                colorLog = true;
                logStream = std::wcout;
            }
            else
            {
                colorLog = false;
                fileLog.reset(new std::wofstream(argv[i + 1]));
                logStream = *fileLog;
            }
            ++i;
        }
        else if(strcmp("--disassemble", argv[i]) == 0)
            runDisassembler = true;
        else if(strcmp("-o", argv[i]) == 0)
        {
            outputFile = argv[i + 1];
            // any further parameter is an input-file
            i += 2;
            break;
        }
        else if(!vc4c::tools::parseConfigurationParameter(config, argv[i]) || strstr(argv[i], "-cl") == argv[i])
            // pass every not understood option to the pre-compiler, as well as every OpenCL compiler option
            options.append(argv[i]).append(" ");
    }

    if(&logStream.get() == &std::wcout && outputFile == "-")
    {
        std::cerr << "Cannot write both log and data to stdout, aborting" << std::endl;
        return 6;
    }
    setLogger(logStream, colorLog, minLevel);

    if(inputFiles.empty())
    {
        std::cerr << "No input file(s) specified, aborting!" << std::endl;
        return 2;
    }
    if(outputFile.empty())
    {
        // special case: if input files is just one, we specify the implicit output file.
        std::string postfix;
        if(inputFiles.size() == 1)
        {
            switch(config.outputMode)
            {
            case OutputMode::BINARY:
                postfix = ".bin";
                break;
            case OutputMode::HEX:
                postfix = ".hex";
                break;
            case OutputMode::ASSEMBLER:
                postfix = ".s";
                break;
            }
            outputFile = inputFiles[0] + postfix;
        }
        else
        {
            std::cerr << "No output file specified, aborting!" << std::endl;
            return 3;
        }
    }

    if(runDisassembler)
    {
        if(inputFiles.size() != 1)
        {
            std::cerr << "For disassembling, a single input file must be specified, aborting!" << std::endl;
            return 4;
        }
        logging::debug() << "Disassembling '" << inputFiles[0] << "' into '" << outputFile << "'..." << logging::endl;
        disassemble(inputFiles[0], outputFile, config.outputMode);
        return 0;
    }

    logging::debug() << "Compiling '" << to_string<std::string>(inputFiles, "', '") << "' into '" << outputFile
                     << "' with optimization level " << static_cast<unsigned>(config.optimizationLevel)
                     << " and options '" << options << "' ..." << logging::endl;

    Optional<std::string> inputFile;
    std::unique_ptr<std::istream> input;
    // link if necessary
    if(inputFiles.size() > 1)
    {
        std::vector<std::unique_ptr<std::istream>> fileStreams;
        std::unordered_map<std::istream*, Optional<std::string>> inputs;
        for(const std::string& file : inputFiles)
        {
            auto ifs = new std::ifstream(file);
            if(!ifs->is_open())
                throw CompilationError(CompilationStep::PRECOMPILATION, "cannot find file", file);
            fileStreams.emplace_back(ifs);
            inputs.emplace(fileStreams.back().get(), Optional<std::string>(file));
        }
        input.reset(new std::stringstream());
        SourceType linkedType = Precompiler::linkSourceCode(inputs, *reinterpret_cast<std::ostream*>(input.get()));
        if(!isSupportedByFrontend(linkedType, config.frontend))
        {
            std::cerr << "Selected front-end does not support the input-format generated by the linker, aborting! "
                      << std::endl;
            return 5;
        }
    }
    else
    {
        const auto& file = inputFiles[0];
        auto ifs = new std::ifstream(file);
        if(!ifs->is_open())
            throw CompilationError(CompilationStep::PRECOMPILATION, "cannot find file", file);
        input.reset(ifs);
        inputFile = inputFiles[0];
    }

    std::ofstream output(outputFile == "-" ? "/dev/stdout" : outputFile,
        std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
    PROFILE_START(Compiler);
    Compiler::compile(*input, output, config, options, inputFile);
    PROFILE_END(Compiler);

    PROFILE_RESULTS();
    return 0;
}
<|endoftext|>