<commit_before>
#include "src/CmdLineOptions.h"
#include "src/MicroCore.h"
#include "src/page.h"

#include "ext/crow/crow.h"
#include "ext/member_checker.h"

#include <fstream>

using boost::filesystem::path;

using namespace std;

// needed for log system of momero
namespace epee {
    unsigned int g_test_dbg_lock_sleep = 0;
}

int main(int ac, const char* av[]) {

    // get command line options
    xmreg::CmdLineOptions opts {ac, av};

    auto help_opt = opts.get_option<bool>("help");

    // if help was chosen, display help text and finish
    if (*help_opt)
    {
        return EXIT_SUCCESS;
    }

    auto port_opt           = opts.get_option<string>("port");
    auto bc_path_opt        = opts.get_option<string>("bc-path");
    auto custom_db_path_opt = opts.get_option<string>("custom-db-path");
    auto deamon_url_opt     = opts.get_option<string>("deamon-url");

    //cast port number in string to uint16
    uint16_t app_port = boost::lexical_cast<uint16_t>(*port_opt);

    // get blockchain path
    path blockchain_path;

    if (!xmreg::get_blockchain_path(bc_path_opt, blockchain_path))
    {
        cerr << "Error getting blockchain path." << endl;
        return EXIT_FAILURE;
    }

     // enable basic monero log output
    xmreg::enable_monero_log();

    // create instance of our MicroCore
    // and make pointer to the Blockchain
    xmreg::MicroCore mcore;
    cryptonote::Blockchain* core_storage;

    // initialize mcore and core_storage
    if (!xmreg::init_blockchain(blockchain_path.string(),
                               mcore, core_storage))
    {
        cerr << "Error accessing blockchain." << endl;
        return EXIT_FAILURE;
    }

    // check if we have path to lmdb2 (i.e., custom db)
    // and if it exists

    string custom_db_path_str;

    if (custom_db_path_opt)
    {
        if (boost::filesystem::exists(boost::filesystem::path(*custom_db_path_opt)))
        {
            custom_db_path_str = *custom_db_path_opt;
        }
        else
        {
            cerr << "Custom db path: " << *custom_db_path_opt
                 << "does not exist" << endl;

            return EXIT_FAILURE;
        }
    }
    else
    {
        // if not given assume it is located in ~./bitmonero/lmdb2 folder
        custom_db_path_str = blockchain_path.parent_path().string()
                             + string("/lmdb2");
    }

    custom_db_path_str = xmreg::remove_trailing_path_separator(custom_db_path_str);

    // create instance of page class which
    // contains logic for the website
    xmreg::page xmrblocks(&mcore, core_storage,
                          *deamon_url_opt, custom_db_path_str);

    // crow instance
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")
    ([&](const crow::request& req) {

        //for (const auto& m : req.headers)
        //    cout << m.first << ": " << m.second << endl;

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.index2());
    });

    CROW_ROUTE(app, "/page/<uint>")
    ([&](size_t page_no) {
        return xmrblocks.index2(page_no);
    });

    CROW_ROUTE(app, "/block/<uint>")
    ([&](const crow::request& req, size_t block_height) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_height));
    });

    CROW_ROUTE(app, "/block/<string>")
    ([&](const crow::request& req, string block_hash) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_hash));
    });

    CROW_ROUTE(app, "/tx/<string>")
    ([&](const crow::request& req, string tx_hash) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_tx(tx_hash));
    });

    CROW_ROUTE(app, "/tx/<string>/<uint>")
    ([&](string tx_hash, uint with_ring_signatures) {
        return xmrblocks.show_tx(tx_hash, with_ring_signatures);
    });

    CROW_ROUTE(app, "/myoutputs").methods("GET"_method)
    ([&](const crow::request& req) {

        string tx_hash     = string(req.url_params.get("tx_hash"));
        string xmr_address = string(req.url_params.get("xmr_address"));
        string viewkey     = string(req.url_params.get("viewkey"));

        return xmrblocks.show_my_outputs(tx_hash, xmr_address, viewkey);
    });

    CROW_ROUTE(app, "/search").methods("GET"_method)
    ([&](const crow::request& req) {
        return xmrblocks.search(string(req.url_params.get("value")));
    });

    CROW_ROUTE(app, "/robots.txt")
    ([&]() {
        string text = "User-agent: *\n"
                      "Disallow: ";
        return text;
    });

    CROW_ROUTE(app, "/autorefresh")
    ([&]() {
        uint64_t page_no {0};
        bool refresh_page {true};
        return xmrblocks.index2(page_no, refresh_page);
    });

    // run the crow http server
    app.port(app_port).multithreaded().run();

    return EXIT_SUCCESS;
}
<commit_msg>tmp show headers<commit_after>
#include "src/CmdLineOptions.h"
#include "src/MicroCore.h"
#include "src/page.h"

#include "ext/crow/crow.h"
#include "ext/member_checker.h"

#include <fstream>

using boost::filesystem::path;

using namespace std;

// needed for log system of momero
namespace epee {
    unsigned int g_test_dbg_lock_sleep = 0;
}

int main(int ac, const char* av[]) {

    // get command line options
    xmreg::CmdLineOptions opts {ac, av};

    auto help_opt = opts.get_option<bool>("help");

    // if help was chosen, display help text and finish
    if (*help_opt)
    {
        return EXIT_SUCCESS;
    }

    auto port_opt           = opts.get_option<string>("port");
    auto bc_path_opt        = opts.get_option<string>("bc-path");
    auto custom_db_path_opt = opts.get_option<string>("custom-db-path");
    auto deamon_url_opt     = opts.get_option<string>("deamon-url");

    //cast port number in string to uint16
    uint16_t app_port = boost::lexical_cast<uint16_t>(*port_opt);

    // get blockchain path
    path blockchain_path;

    if (!xmreg::get_blockchain_path(bc_path_opt, blockchain_path))
    {
        cerr << "Error getting blockchain path." << endl;
        return EXIT_FAILURE;
    }

     // enable basic monero log output
    xmreg::enable_monero_log();

    // create instance of our MicroCore
    // and make pointer to the Blockchain
    xmreg::MicroCore mcore;
    cryptonote::Blockchain* core_storage;

    // initialize mcore and core_storage
    if (!xmreg::init_blockchain(blockchain_path.string(),
                               mcore, core_storage))
    {
        cerr << "Error accessing blockchain." << endl;
        return EXIT_FAILURE;
    }

    // check if we have path to lmdb2 (i.e., custom db)
    // and if it exists

    string custom_db_path_str;

    if (custom_db_path_opt)
    {
        if (boost::filesystem::exists(boost::filesystem::path(*custom_db_path_opt)))
        {
            custom_db_path_str = *custom_db_path_opt;
        }
        else
        {
            cerr << "Custom db path: " << *custom_db_path_opt
                 << "does not exist" << endl;

            return EXIT_FAILURE;
        }
    }
    else
    {
        // if not given assume it is located in ~./bitmonero/lmdb2 folder
        custom_db_path_str = blockchain_path.parent_path().string()
                             + string("/lmdb2");
    }

    custom_db_path_str = xmreg::remove_trailing_path_separator(custom_db_path_str);

    // create instance of page class which
    // contains logic for the website
    xmreg::page xmrblocks(&mcore, core_storage,
                          *deamon_url_opt, custom_db_path_str);

    // crow instance
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")
    ([&](const crow::request& req) {

        //for (const auto& m : req.headers)
        //    cout << m.first << ": " << m.second << endl;

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.index2());
    });

    CROW_ROUTE(app, "/page/<uint>")
    ([&](size_t page_no) {
        return xmrblocks.index2(page_no);
    });

    CROW_ROUTE(app, "/block/<uint>")
    ([&](const crow::request& req, size_t block_height) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_height));
    });

    CROW_ROUTE(app, "/block/<string>")
    ([&](const crow::request& req, string block_hash) {

        for (const auto& m : req.headers)
            cout << m.first << ": " << m.second << endl;

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_hash));
    });

    CROW_ROUTE(app, "/tx/<string>")
    ([&](const crow::request& req, string tx_hash) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_tx(tx_hash));
    });

    CROW_ROUTE(app, "/tx/<string>/<uint>")
    ([&](string tx_hash, uint with_ring_signatures) {
        return xmrblocks.show_tx(tx_hash, with_ring_signatures);
    });

    CROW_ROUTE(app, "/myoutputs").methods("GET"_method)
    ([&](const crow::request& req) {

        string tx_hash     = string(req.url_params.get("tx_hash"));
        string xmr_address = string(req.url_params.get("xmr_address"));
        string viewkey     = string(req.url_params.get("viewkey"));

        return xmrblocks.show_my_outputs(tx_hash, xmr_address, viewkey);
    });

    CROW_ROUTE(app, "/search").methods("GET"_method)
    ([&](const crow::request& req) {
        return xmrblocks.search(string(req.url_params.get("value")));
    });

    CROW_ROUTE(app, "/robots.txt")
    ([&]() {
        string text = "User-agent: *\n"
                      "Disallow: ";
        return text;
    });

    CROW_ROUTE(app, "/autorefresh")
    ([&]() {
        uint64_t page_no {0};
        bool refresh_page {true};
        return xmrblocks.index2(page_no, refresh_page);
    });

    // run the crow http server
    app.port(app_port).multithreaded().run();

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/**
 * SUBLEQ Assembly: main.cpp
 *
 *  Created on: Apr 9, 2014
 *      Author:       Pimenta
 *      Collaborator: Alexandre Dantas
 *
 * This program reads a SUBLEQ Assembly file and outputs
 * a well-formed object file.
 * It's supposed to be fed to the Linker.
 */

#include <cstdint>
#include <cstdio>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <iostream>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

/// Buffer that contains the entire contents
/// of the input file, with normalized line endings.
static stringstream f;

/// Global buffer that always contains the current
/// token being read by `readToken`
static string buf;

/// Set of all exported symbols.
/// They're used together with other object files
/// on the linker.
static set<string> exported;

/// All current symbols declared on this file.
/// Maps from a label to it's address in memory.
static map<string, uword_t> symbols;

/// Contains all symbols not found on this file.
///
/// It has labels supposed to be found on other
/// Assembly files.
/// They'll get resolved with the external symbols.
static map<string, set<uword_t>> references;

/// Relative addresses found on this file.
///
/// When you "call" a symbol on this file, it's address
/// is relative to the start of this file.
///
/// When the Linker joins several object files, it will
/// use the values on this set to relocate them all.
///
static set<uword_t> relatives;

/// Current size of the memory.
/// While parsing: points the current memory address
///                being read.
/// At the end:    has the entire size of the memory
///                read.
static uword_t mem_size = 0;

/// Raw memory.
/// It contains the assembled memory that will get
/// written at the end of the object file.
static uword_t* mem = new uword_t[MEM_WORDS];

static int currentLine = 1, lastTokenLine = 1, currentTokenLine = 1;

/// Reads a string from `is` to the end-of-line, saving it on `t`.
///
/// @note It doesn't save the end-of-line character on `t`.
///
/// This is a "safe" implementation of `std::getline`.
/// It is "safe" in the sense that it does work with all possible
/// line endings ("\r", "\n" and "\r\n").
///
/// Taken straight from StackOverflow. Source:
/// http://stackoverflow.com/a/6089413
///
std::istream& safeGetline(std::istream& is, std::string& t)
{
  t.clear();

  // The characters in the stream are read one-by-one using a
  // std::streambuf. That is faster than reading them one-by-one
  // using the std::istream.
  //
  // Code that uses streambuf this way must be guarded by a sentry
  // object.
  // The sentry object performs various tasks, such as thread
  // synchronization and updating the stream state.

  std::istream::sentry se(is, true);

  std::streambuf* sb = is.rdbuf();

  while (true) {
    int c = sb->sbumpc();

    switch (c) {

    case '\n':
      return is;

    case '\r':
      if (sb->sgetc() == '\n')
        sb->sbumpc();

      return is;

    case EOF:
      // Also handle the case when the last line has no line ending
      if (t.empty())
        is.setstate(std::ios::eofbit);

      return is;

    default:
      t += (char)c;
    }
  }
}

/// Reads a token (separated by whitespaces) from the file,
/// char by char, putting on `buf`
inline static void readToken() {
  buf = "";
  lastTokenLine = currentTokenLine;

  // Will read all chars until:
  //
  // - Finding a whitespace (or tab)
  // - Finding a comment
  // - Finding an end-of-line
  // - File somehow ends
  //
  while (true)
  {
    char c = f.get();

    if (!f.good())
      break;

    // comment found
    if (c == '/') {

      // token was read
      if (buf.size()) {
        currentTokenLine = currentLine;
        return;
      }

      // ignoring entire comment
      do {
        c = f.get();
      } while (c != '\r' && c != '\n' && f.good());

      // checking for CR or CRLF line endings
      if (c == '\r') {
        c = f.get();

        if (f.good() && c != '\n')
          f.unget();
      }

      currentLine++;
      continue;
    }

    // line break found
    if (c == '\r' || c == '\n') {

      // checking for CR or CRLF line endings
      if (c == '\r') {
        c = f.get();

        if (f.good() && c != '\n')
          f.unget();
      }

      // token was read
      if (buf.size()) {
        currentTokenLine = currentLine++;
        return;
      }

      currentLine++;
      continue;
    }

    // white space found
    if (c == ' ' || c == '\t') {

      // token was read
      if (buf.size()) {
        currentTokenLine = currentLine;
        return;
      }
      continue;
    }

    // this character was none of the above
    // simply appending it
    buf += c;
  }

  currentTokenLine = currentLine;
}

/// Returns text on `buf` as data.
///
/// Converts textual data to words.
/// For example, converts "0x1" to 1.
inline static uword_t parseData() {
  uword_t data = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // for hex notation
    sscanf(buf.c_str(), "%i", &data);
  }
  else { // for decimal notation
    stringstream ss;
    ss << buf;
    ss >> data;
  }
  return data;
}

/// Parses a single field contained on `buf`.
///
/// So for `SUBLEQ A B C` we call this function three times,
/// once for each field A, B and C.
///
/// Returns the address being "called" by the field.
///
/// For example, if we have:
///
///     .data
///         one: 1
///     .text
///       loop:
///         one one loop
///
/// For `one` on `loop:` it returns 0, since it's the
/// address of the thing being "called" by the instruction.
///
inline static uword_t parseField() {
  uword_t field = 0;
  // hex notation means absolute address
  if (buf[0] == '0' && buf[1] == 'x') {
    sscanf(buf.c_str(), "%i", &field);
  }
  // symbol means an address that needs to be relocated later
  else {
    relatives.emplace(mem_size);

    // looking for array offset
    if (buf.find("+") != buf.npos) {
      string offset = buf.substr(buf.find("+") + 1, buf.size());
      buf = buf.substr(0, buf.find("+"));
      stringstream ss;
      ss << offset;
      ss >> field;
    }

    auto sym = symbols.find(buf);
    // symbol not found. leave a reference
    if (sym == symbols.end()) {
      references[buf].emplace(mem_size);
    }
    // symbol found. the field is the address of the symbol
    else {
      field = sym->second;
    }
  }
  return field;
}

int main(int argc, char* argv[]) {
  if (argc != 3) {
    fprintf(stderr, "Usage mode: subleq-asm <assembly_file> <object_file>\n");
    return 0;
  }

  // Making sure both files exist
  fstream input_file(argv[1]);
  fstream output_file(argv[2], fstream::out | fstream::binary);

  if (!input_file) {
    cout << "Input file '" << argv[1] << "' doesn't exist" << endl;
    return EXIT_FAILURE;
  }
  if (!output_file) {
    cout << "Output file '" << argv[2] << "' doesn't exist" << endl;
    return EXIT_FAILURE;
  }

  // Read the whole file and store on a buffer.
  //
  // This way we won't need to worry about specific
  // line-endings, since it will look like it only
  // has '\n'.
  while (true) {
    string str;
    safeGetline(input_file, str);
    f << (str + '\n');

    if (!input_file)
      break;
  }
  input_file.close();

  readToken(); // reading ".export"

  // reading export section
  for (readToken(); buf != ".data"; readToken()) {
    exported.insert(buf);
  }

  // reading data section
  for (readToken(); buf != ".text";) {
    symbols[buf.substr(0, buf.size() - 1)] = mem_size;
    readToken();
    if (buf == ".array") { // uninitialized array
      readToken();
      mem_size += parseData();
      readToken(); // next symbol
    }
    else if (buf == ".iarray") { // initialized array
      for (readToken(); currentTokenLine == lastTokenLine; readToken()) {
        mem[mem_size++] = parseData();
      }
    }
    else if (buf == ".ptr") { // pointer
      readToken();
      mem[mem_size] = parseField();
      mem_size++;
      readToken(); // next symbol
    }
    else { // initialized word
      mem[mem_size++] = parseData();
      readToken(); // next symbol
    }
  }

  // reading text section
  int field = 0;
  for (readToken(); buf.size();) {
    // field 2 omitted
    if (field == 2 && currentTokenLine != lastTokenLine) {
      relatives.emplace(mem_size);
      mem[mem_size] = mem_size + 1;
      mem_size++;
      field = (field + 1)%3;
    }
    // symbol found
    else if (buf[buf.size() - 1] == ':') {
      symbols[buf.substr(0, buf.size() - 1)] = mem_size;
      if (buf == "start:")
        exported.emplace("start");
      readToken();
    }
    // field 0, 1, or field 2 specified
    else {
      mem[mem_size] = parseField();
      mem_size++;
      field = (field + 1)%3;
      readToken();
    }
  }

  // Now we go through each symbol (label), resolving references.
  //
  // If it's not on this file (`symbols` map), we assume it's
  // found on other file (`references` map).
  //
  for (auto map_it = references.begin(); map_it != references.end(); ++map_it) {

    // Which symbol was referenced
    string symbol_name = map_it->first;

    // All addresses where the symbol above was referenced
    set<uword_t> symbol_called = map_it->second;

    // Is this symbol declared on this file?
    // If not then leave it be at `references`
    auto sym = symbols.find(symbol_name);

    if (sym == symbols.end())
      continue;

    // If it's on this file, we replace it's address on every
    // memory location that called it
    uword_t symbol_address = sym->second;

    for (auto it = symbol_called.begin(); it != symbol_called.end(); ++it)
      mem[*it] += symbol_address;

    // And remove it from the external reference map
    references.erase(map_it);
  }

  // Now, outputting the binary stuff
  {
    uword_t tmp;

    // write number of exported symbols
    tmp = exported.size();
    output_file.write((const char*)&tmp, sizeof(uword_t));

    // write exported symbols
    for (auto& exp : exported) {
      // string
      output_file.write(exp.c_str(), exp.size() + 1);

      // address
      tmp = symbols[exp];
      output_file.write((const char*)&tmp, sizeof(uword_t));
    }

    // write number of symbols of pending references
    tmp = references.size();
    output_file.write((const char*)&tmp, sizeof(uword_t));

    // write symbols of pending references
    for (auto& sym : references) {
      // string
      output_file.write(sym.first.c_str(), sym.first.size() + 1);

      // write number of references to current symbol
      tmp = sym.second.size();
      output_file.write((const char*)&tmp, sizeof(uword_t));

      // write references to current symbol
      for (auto ref : sym.second) {
        tmp = ref;
        output_file.write((const char*)&tmp, sizeof(uword_t));
      }
    }

    // write number of relative addresses
    tmp = relatives.size();
    output_file.write((const char*)&tmp, sizeof(uword_t));

    // write relative addresses
    for (auto addr : relatives) {
      tmp = addr;
      output_file.write((const char*)&tmp, sizeof(uword_t));
    }

    // write assembled code size
    output_file.write((const char*)&mem_size, sizeof(uword_t));

    // write assembled code
    output_file.write((const char*)mem, sizeof(uword_t)*mem_size);
  }

  output_file.close();

  delete[] mem;

  return 0;
}
<commit_msg>No need to worry about different line endings anymore<commit_after>/**
 * SUBLEQ Assembly: main.cpp
 *
 *  Created on: Apr 9, 2014
 *      Author:       Pimenta
 *      Collaborator: Alexandre Dantas
 *
 * This program reads a SUBLEQ Assembly file and outputs
 * a well-formed object file.
 * It's supposed to be fed to the Linker.
 */

#include <cstdint>
#include <cstdio>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <iostream>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

/// Buffer that contains the entire contents
/// of the input file, with normalized line endings.
static stringstream f;

/// Global buffer that always contains the current
/// token being read by `readToken`
static string buf;

/// Set of all exported symbols.
/// They're used together with other object files
/// on the linker.
static set<string> exported;

/// All current symbols declared on this file.
/// Maps from a label to it's address in memory.
static map<string, uword_t> symbols;

/// Contains all symbols not found on this file.
///
/// It has labels supposed to be found on other
/// Assembly files.
/// They'll get resolved with the external symbols.
static map<string, set<uword_t>> references;

/// Relative addresses found on this file.
///
/// When you "call" a symbol on this file, it's address
/// is relative to the start of this file.
///
/// When the Linker joins several object files, it will
/// use the values on this set to relocate them all.
///
static set<uword_t> relatives;

/// Current size of the memory.
/// While parsing: points the current memory address
///                being read.
/// At the end:    has the entire size of the memory
///                read.
static uword_t mem_size = 0;

/// Raw memory.
/// It contains the assembled memory that will get
/// written at the end of the object file.
static uword_t* mem = new uword_t[MEM_WORDS];

static int currentLine = 1, lastTokenLine = 1, currentTokenLine = 1;

/// Reads a string from `is` to the end-of-line, saving it on `t`.
///
/// @note It doesn't save the end-of-line character on `t`.
///
/// This is a "safe" implementation of `std::getline`.
/// It is "safe" in the sense that it does work with all possible
/// line endings ("\r", "\n" and "\r\n").
///
/// Taken straight from StackOverflow. Source:
/// http://stackoverflow.com/a/6089413
///
std::istream& safeGetline(std::istream& is, std::string& t)
{
  t.clear();

  // The characters in the stream are read one-by-one using a
  // std::streambuf. That is faster than reading them one-by-one
  // using the std::istream.
  //
  // Code that uses streambuf this way must be guarded by a sentry
  // object.
  // The sentry object performs various tasks, such as thread
  // synchronization and updating the stream state.

  std::istream::sentry se(is, true);

  std::streambuf* sb = is.rdbuf();

  while (true) {
    int c = sb->sbumpc();

    switch (c) {

    case '\n':
      return is;

    case '\r':
      if (sb->sgetc() == '\n')
        sb->sbumpc();

      return is;

    case EOF:
      // Also handle the case when the last line has no line ending
      if (t.empty())
        is.setstate(std::ios::eofbit);

      return is;

    default:
      t += (char)c;
    }
  }
}

/// Reads a token (separated by whitespaces) from the file,
/// char by char, putting on `buf`
inline static void readToken() {
  buf = "";
  lastTokenLine = currentTokenLine;

  // Will read all chars until:
  //
  // - Finding a whitespace (or tab)
  // - Finding a comment
  // - Finding an end-of-line
  // - File somehow ends
  //
  while (true)
  {
    char c = f.get();

    if (!f.good())
      break;

    // comment found
    if (c == '/') {

      // token was read
      if (buf.size()) {
        currentTokenLine = currentLine;
        return;
      }

      // ignoring entire comment
      do {
        c = f.get();
      } while (c != '\n' && f.good());

      currentLine++;
      continue;
    }

    // line break found
    if (c == '\n') {

      // token was read
      if (buf.size()) {
        currentTokenLine = currentLine++;
        return;
      }

      currentLine++;
      continue;
    }

    // white space found
    if (c == ' ' || c == '\t') {

      // token was read
      if (buf.size()) {
        currentTokenLine = currentLine;
        return;
      }
      continue;
    }

    // this character was none of the above
    // simply appending it
    buf += c;
  }

  currentTokenLine = currentLine;
}

/// Returns text on `buf` as data.
///
/// Converts textual data to words.
/// For example, converts "0x1" to 1.
inline static uword_t parseData() {
  uword_t data = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // for hex notation
    sscanf(buf.c_str(), "%i", &data);
  }
  else { // for decimal notation
    stringstream ss;
    ss << buf;
    ss >> data;
  }
  return data;
}

/// Parses a single field contained on `buf`.
///
/// So for `SUBLEQ A B C` we call this function three times,
/// once for each field A, B and C.
///
/// Returns the address being "called" by the field.
///
/// For example, if we have:
///
///     .data
///         one: 1
///     .text
///       loop:
///         one one loop
///
/// For `one` on `loop:` it returns 0, since it's the
/// address of the thing being "called" by the instruction.
///
inline static uword_t parseField() {
  uword_t field = 0;
  // hex notation means absolute address
  if (buf[0] == '0' && buf[1] == 'x') {
    sscanf(buf.c_str(), "%i", &field);
  }
  // symbol means an address that needs to be relocated later
  else {
    relatives.emplace(mem_size);

    // looking for array offset
    if (buf.find("+") != buf.npos) {
      string offset = buf.substr(buf.find("+") + 1, buf.size());
      buf = buf.substr(0, buf.find("+"));
      stringstream ss;
      ss << offset;
      ss >> field;
    }

    auto sym = symbols.find(buf);
    // symbol not found. leave a reference
    if (sym == symbols.end()) {
      references[buf].emplace(mem_size);
    }
    // symbol found. the field is the address of the symbol
    else {
      field = sym->second;
    }
  }
  return field;
}

int main(int argc, char* argv[]) {
  if (argc != 3) {
    fprintf(stderr, "Usage mode: subleq-asm <assembly_file> <object_file>\n");
    return 0;
  }

  // Making sure both files exist
  fstream input_file(argv[1]);
  fstream output_file(argv[2], fstream::out | fstream::binary);

  if (!input_file) {
    cout << "Input file '" << argv[1] << "' doesn't exist" << endl;
    return EXIT_FAILURE;
  }
  if (!output_file) {
    cout << "Output file '" << argv[2] << "' doesn't exist" << endl;
    return EXIT_FAILURE;
  }

  // Read the whole file and store on a buffer.
  //
  // This way we won't need to worry about specific
  // line-endings, since it will look like it only
  // has '\n'.
  while (true) {
    string str;
    safeGetline(input_file, str);
    f << (str + '\n');

    if (!input_file)
      break;
  }
  input_file.close();

  readToken(); // reading ".export"

  // reading export section
  for (readToken(); buf != ".data"; readToken()) {
    exported.insert(buf);
  }

  // reading data section
  for (readToken(); buf != ".text";) {
    symbols[buf.substr(0, buf.size() - 1)] = mem_size;
    readToken();
    if (buf == ".array") { // uninitialized array
      readToken();
      mem_size += parseData();
      readToken(); // next symbol
    }
    else if (buf == ".iarray") { // initialized array
      for (readToken(); currentTokenLine == lastTokenLine; readToken()) {
        mem[mem_size++] = parseData();
      }
    }
    else if (buf == ".ptr") { // pointer
      readToken();
      mem[mem_size] = parseField();
      mem_size++;
      readToken(); // next symbol
    }
    else { // initialized word
      mem[mem_size++] = parseData();
      readToken(); // next symbol
    }
  }

  // reading text section
  int field = 0;
  for (readToken(); buf.size();) {
    // field 2 omitted
    if (field == 2 && currentTokenLine != lastTokenLine) {
      relatives.emplace(mem_size);
      mem[mem_size] = mem_size + 1;
      mem_size++;
      field = (field + 1)%3;
    }
    // symbol found
    else if (buf[buf.size() - 1] == ':') {
      symbols[buf.substr(0, buf.size() - 1)] = mem_size;
      if (buf == "start:")
        exported.emplace("start");
      readToken();
    }
    // field 0, 1, or field 2 specified
    else {
      mem[mem_size] = parseField();
      mem_size++;
      field = (field + 1)%3;
      readToken();
    }
  }

  // Now we go through each symbol (label), resolving references.
  //
  // If it's not on this file (`symbols` map), we assume it's
  // found on other file (`references` map).
  //
  for (auto map_it = references.begin(); map_it != references.end(); ++map_it) {

    // Which symbol was referenced
    string symbol_name = map_it->first;

    // All addresses where the symbol above was referenced
    set<uword_t> symbol_called = map_it->second;

    // Is this symbol declared on this file?
    // If not then leave it be at `references`
    auto sym = symbols.find(symbol_name);

    if (sym == symbols.end())
      continue;

    // If it's on this file, we replace it's address on every
    // memory location that called it
    uword_t symbol_address = sym->second;

    for (auto it = symbol_called.begin(); it != symbol_called.end(); ++it)
      mem[*it] += symbol_address;

    // And remove it from the external reference map
    references.erase(map_it);
  }

  // Now, outputting the binary stuff
  {
    uword_t tmp;

    // write number of exported symbols
    tmp = exported.size();
    output_file.write((const char*)&tmp, sizeof(uword_t));

    // write exported symbols
    for (auto& exp : exported) {
      // string
      output_file.write(exp.c_str(), exp.size() + 1);

      // address
      tmp = symbols[exp];
      output_file.write((const char*)&tmp, sizeof(uword_t));
    }

    // write number of symbols of pending references
    tmp = references.size();
    output_file.write((const char*)&tmp, sizeof(uword_t));

    // write symbols of pending references
    for (auto& sym : references) {
      // string
      output_file.write(sym.first.c_str(), sym.first.size() + 1);

      // write number of references to current symbol
      tmp = sym.second.size();
      output_file.write((const char*)&tmp, sizeof(uword_t));

      // write references to current symbol
      for (auto ref : sym.second) {
        tmp = ref;
        output_file.write((const char*)&tmp, sizeof(uword_t));
      }
    }

    // write number of relative addresses
    tmp = relatives.size();
    output_file.write((const char*)&tmp, sizeof(uword_t));

    // write relative addresses
    for (auto addr : relatives) {
      tmp = addr;
      output_file.write((const char*)&tmp, sizeof(uword_t));
    }

    // write assembled code size
    output_file.write((const char*)&mem_size, sizeof(uword_t));

    // write assembled code
    output_file.write((const char*)mem, sizeof(uword_t)*mem_size);
  }

  output_file.close();

  delete[] mem;

  return 0;
}
<|endoftext|>


<commit_before>#include <math.h>
#include <stdio.h>

struct Vec3
{
    typedef const Vec3& InParam;

    Vec3() noexcept {}

    Vec3(const float x, const float y, const float z) noexcept
        : x(x)
        , y(y)
        , z(z)
    {
    }

    float x, y, z;
};

Vec3& operator+=(Vec3& left, Vec3::InParam right) noexcept {
    left.x += right.x;
    left.y += right.y;
    left.z += right.z;
    return left;
}

Vec3 operator+(Vec3::InParam left, Vec3::InParam right) noexcept {
    return Vec3{
        left.x + right.x,
        left.y + right.y,
        left.z + right.z
    };
}

Vec3 operator-(Vec3::InParam left, Vec3::InParam right) noexcept {
    return Vec3{
        left.x - right.x,
        left.y - right.y,
        left.z - right.z
    };
}

Vec3 operator*(Vec3::InParam v, const float scale) noexcept {
    return Vec3{
        v.x * scale,
        v.y * scale,
        v.z * scale
    };
}

Vec3& operator*=(Vec3& v, const float scale) noexcept {
    v.x *= scale;
    v.y *= scale;
    v.z *= scale;
    return v;
}

float dot(Vec3::InParam left, Vec3::InParam right) noexcept {
    return left.x*right.x + left.y*right.y + left.z*right.z;
}

float length_squared(const float x, const float y, const float z) noexcept {
    return x*x + y*y + z*z;
}

float length_squared(Vec3::InParam in) noexcept {
    return length_squared(in.x, in.y, in.z);
}

float length(const float x, const float y) noexcept {
    // sqrt may raise std::domain_error if the input is negative but that's not
    // possible here as we're summing two squares
    return sqrt(x*x + y*y);
}

float length(const float x, const float y, const float z) noexcept {
    // sqrt may raise std::domain_error if the input is negative but that's not
    // possible here as we're summing three squares
    return sqrt(x*x + y*y + z*z);
}

float length(Vec3::InParam in) noexcept {
    return length(in.x, in.y, in.z);
}

Vec3 normalised(Vec3::InParam in) noexcept {
    const float scale = 1.0f / length(in);
    return in * scale;
}

Vec3 lerp(Vec3::InParam from, Vec3::InParam to, const float t) noexcept {
    return (from * (1.0f - t)) + (to * t);
}

Vec3 reflected(Vec3::InParam vector, Vec3::InParam normal) noexcept {
    // To reflect the supplied vector along the axis of the normal, add as much
    // of the normal to the vector as would make it perpendicular to the
    // normal, then add the same amount again.
    //
    // This will reverse the vector's magnitude with respect to the normal,
    // whilst keeping the magnitude of the vector the same.
    //
    const float magnitude_of_normal_shared_with_vector = dot(vector, normal);
    const float normal_scale = -2.0f * magnitude_of_normal_shared_with_vector;
    return vector + normal * normal_scale;
}

Vec3 sample_sky(const Vec3::InParam direction) noexcept {
    const Vec3 up{0.0f, 1.0f, 0.0f};

    const float red = 32.0f;
    const float green = 128.0f;
    const float blue = 180.0f + 64.0f * dot(direction, up);

    return Vec3{red, green, blue};
}

Vec3 sample_ground(
        const Vec3::InParam position,
        const Vec3::InParam direction,
        const Vec3::InParam sphere_point_on_ground,
        const float sphere_magnitude_squared) noexcept
{
    const float inverse_square_scale = 0.1f;
    const int x = fabs(position.x * inverse_square_scale);
    const int y = fabs(position.z * inverse_square_scale);

    const Vec3 world_down {0.0f, -1.0f, 0.0f};
    const float dot_down {dot(direction, world_down)};

    Vec3 colour;

    if ((x%2) ^ (y%2)) {
        const Vec3 green {32.0f, 128.0f, 32.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    } else {
        const Vec3 green {64.0f, 128.0f, 64.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    }

    const Vec3 to_sphere_on_ground = sphere_point_on_ground - position;
    if (length_squared(to_sphere_on_ground) < sphere_magnitude_squared) {
        colour *= 0.5f;
    }

    return colour;
}

Vec3 sample_sphere(
        const Vec3::InParam position,
        const Vec3::InParam normal,
        const Vec3::InParam direction) noexcept
{
    const Vec3 world_up {0.0f, 1.0f, 0.0f};
    const float dot_up {dot(normal, world_up)};

    const Vec3 half {0.5f, 0.5f, 0.5f};
    const Vec3 color {(normal * 0.5f + half) * 255.0f};
    const Vec3 half_color {color * 0.5f};
    return lerp(half_color, color, dot_up);
}

Vec3 sample(Vec3 position, Vec3 direction) noexcept {

    Vec3 colour {0.0f, 0.0f, 0.0f};
    float colour_blend = 1.0f;

    // check for collision against sphere
    const Vec3 sphere_point {0.0f, 15.0f, 40.0f};
    const Vec3 sphere_point_on_ground {0.0f, 0.0f, 40.0f};
    const float sphere_magnitude = 11.0f;
    const float sphere_magnitude_squared = sphere_magnitude * sphere_magnitude;
    const Vec3 to_sphere {sphere_point - position};
    const float closest_to_sphere {dot(direction, to_sphere)};
    const Vec3 point_nearest_sphere {position + direction * closest_to_sphere};
    const float length_to_sphere {length(sphere_point - point_nearest_sphere)};
    // TODO: use squared magnitude
    if (length_to_sphere < sphere_magnitude) {
        // calc intersection point
        const float adjacent_length = sqrt(
            sphere_magnitude * sphere_magnitude
            - length_to_sphere * length_to_sphere);
        const Vec3 intersection {
            point_nearest_sphere - (direction * adjacent_length)};

        // sample the sphere
        const Vec3 normal {normalised(intersection - sphere_point)};
        position = intersection;
        direction = reflected(direction, normal);
        colour = lerp(
            colour,
            sample_sphere(intersection, normal, direction),
            colour_blend);
        colour_blend = 0.5f;
    }

    // check for collision against ground
    const Vec3 ground_inverse_normal(0.0f, -1.0f, 0.0f);
    if (dot(ground_inverse_normal, direction) > 0.0f) {
        // hit the ground, figure out where
        const Vec3 ground_point(0.0f, 0.0f, 0.0f);
        const Vec3 to_ground {ground_point - position};
        const float distance_to_ground {dot(to_ground, ground_inverse_normal)};
        const float dot_to_ground {dot(direction, ground_inverse_normal)};
        const float distance {distance_to_ground / dot_to_ground};
        const Vec3 ground_intersection {position + direction * distance};
        colour = lerp(
            colour,
            sample_ground(
                ground_intersection,
                direction,
                sphere_point_on_ground,
                sphere_magnitude_squared),
            colour_blend);
    } else {
        colour = lerp(
            colour,
            // TODO: remove position parameter
            sample_sky(direction),
            colour_blend);
    }

    return colour;
}

void draw_scene(const int image_width, const int image_height) noexcept {
    const Vec3 camera_forward{0.0f, 0.0f, 1.0f};
    const Vec3 camera_right{1.0f, 0.0f, 0.0f};
    const Vec3 camera_up{0.0f, 1.0f, 0.0f};
    const Vec3 camera_pos{0.0f, 10.0f, 0.0f};

    const int half_image_width = image_width / 2;
    const int half_image_height = image_height / 2;

    for (int y=image_height-1; y>=0; --y) {
        for (int x=0; x<image_width; ++x) {
            const Vec3 pixel_offset = Vec3{
                float(x-half_image_width),
                float(y-half_image_height),
                0.0f};

            const Vec3 pixel_direction = normalised(
                camera_forward*image_height + pixel_offset);

            const Vec3 colour = sample(camera_pos, pixel_direction);

            printf("%c%c%c", int(colour.x), int(colour.y), int(colour.z));
        }
    }
}

int main() {
    printf("P6 512 512 255 ");
    draw_scene(512, 512);
}

// Copyright 2014 Angelos Evripiotis
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
<commit_msg>Bump copyright date<commit_after>#include <math.h>
#include <stdio.h>

struct Vec3
{
    typedef const Vec3& InParam;

    Vec3() noexcept {}

    Vec3(const float x, const float y, const float z) noexcept
        : x(x)
        , y(y)
        , z(z)
    {
    }

    float x, y, z;
};

Vec3& operator+=(Vec3& left, Vec3::InParam right) noexcept {
    left.x += right.x;
    left.y += right.y;
    left.z += right.z;
    return left;
}

Vec3 operator+(Vec3::InParam left, Vec3::InParam right) noexcept {
    return Vec3{
        left.x + right.x,
        left.y + right.y,
        left.z + right.z
    };
}

Vec3 operator-(Vec3::InParam left, Vec3::InParam right) noexcept {
    return Vec3{
        left.x - right.x,
        left.y - right.y,
        left.z - right.z
    };
}

Vec3 operator*(Vec3::InParam v, const float scale) noexcept {
    return Vec3{
        v.x * scale,
        v.y * scale,
        v.z * scale
    };
}

Vec3& operator*=(Vec3& v, const float scale) noexcept {
    v.x *= scale;
    v.y *= scale;
    v.z *= scale;
    return v;
}

float dot(Vec3::InParam left, Vec3::InParam right) noexcept {
    return left.x*right.x + left.y*right.y + left.z*right.z;
}

float length_squared(const float x, const float y, const float z) noexcept {
    return x*x + y*y + z*z;
}

float length_squared(Vec3::InParam in) noexcept {
    return length_squared(in.x, in.y, in.z);
}

float length(const float x, const float y) noexcept {
    // sqrt may raise std::domain_error if the input is negative but that's not
    // possible here as we're summing two squares
    return sqrt(x*x + y*y);
}

float length(const float x, const float y, const float z) noexcept {
    // sqrt may raise std::domain_error if the input is negative but that's not
    // possible here as we're summing three squares
    return sqrt(x*x + y*y + z*z);
}

float length(Vec3::InParam in) noexcept {
    return length(in.x, in.y, in.z);
}

Vec3 normalised(Vec3::InParam in) noexcept {
    const float scale = 1.0f / length(in);
    return in * scale;
}

Vec3 lerp(Vec3::InParam from, Vec3::InParam to, const float t) noexcept {
    return (from * (1.0f - t)) + (to * t);
}

Vec3 reflected(Vec3::InParam vector, Vec3::InParam normal) noexcept {
    // To reflect the supplied vector along the axis of the normal, add as much
    // of the normal to the vector as would make it perpendicular to the
    // normal, then add the same amount again.
    //
    // This will reverse the vector's magnitude with respect to the normal,
    // whilst keeping the magnitude of the vector the same.
    //
    const float magnitude_of_normal_shared_with_vector = dot(vector, normal);
    const float normal_scale = -2.0f * magnitude_of_normal_shared_with_vector;
    return vector + normal * normal_scale;
}

Vec3 sample_sky(const Vec3::InParam direction) noexcept {
    const Vec3 up{0.0f, 1.0f, 0.0f};

    const float red = 32.0f;
    const float green = 128.0f;
    const float blue = 180.0f + 64.0f * dot(direction, up);

    return Vec3{red, green, blue};
}

Vec3 sample_ground(
        const Vec3::InParam position,
        const Vec3::InParam direction,
        const Vec3::InParam sphere_point_on_ground,
        const float sphere_magnitude_squared) noexcept
{
    const float inverse_square_scale = 0.1f;
    const int x = fabs(position.x * inverse_square_scale);
    const int y = fabs(position.z * inverse_square_scale);

    const Vec3 world_down {0.0f, -1.0f, 0.0f};
    const float dot_down {dot(direction, world_down)};

    Vec3 colour;

    if ((x%2) ^ (y%2)) {
        const Vec3 green {32.0f, 128.0f, 32.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    } else {
        const Vec3 green {64.0f, 128.0f, 64.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    }

    const Vec3 to_sphere_on_ground = sphere_point_on_ground - position;
    if (length_squared(to_sphere_on_ground) < sphere_magnitude_squared) {
        colour *= 0.5f;
    }

    return colour;
}

Vec3 sample_sphere(
        const Vec3::InParam position,
        const Vec3::InParam normal,
        const Vec3::InParam direction) noexcept
{
    const Vec3 world_up {0.0f, 1.0f, 0.0f};
    const float dot_up {dot(normal, world_up)};

    const Vec3 half {0.5f, 0.5f, 0.5f};
    const Vec3 color {(normal * 0.5f + half) * 255.0f};
    const Vec3 half_color {color * 0.5f};
    return lerp(half_color, color, dot_up);
}

Vec3 sample(Vec3 position, Vec3 direction) noexcept {

    Vec3 colour {0.0f, 0.0f, 0.0f};
    float colour_blend = 1.0f;

    // check for collision against sphere
    const Vec3 sphere_point {0.0f, 15.0f, 40.0f};
    const Vec3 sphere_point_on_ground {0.0f, 0.0f, 40.0f};
    const float sphere_magnitude = 11.0f;
    const float sphere_magnitude_squared = sphere_magnitude * sphere_magnitude;
    const Vec3 to_sphere {sphere_point - position};
    const float closest_to_sphere {dot(direction, to_sphere)};
    const Vec3 point_nearest_sphere {position + direction * closest_to_sphere};
    const float length_to_sphere {length(sphere_point - point_nearest_sphere)};
    // TODO: use squared magnitude
    if (length_to_sphere < sphere_magnitude) {
        // calc intersection point
        const float adjacent_length = sqrt(
            sphere_magnitude * sphere_magnitude
            - length_to_sphere * length_to_sphere);
        const Vec3 intersection {
            point_nearest_sphere - (direction * adjacent_length)};

        // sample the sphere
        const Vec3 normal {normalised(intersection - sphere_point)};
        position = intersection;
        direction = reflected(direction, normal);
        colour = lerp(
            colour,
            sample_sphere(intersection, normal, direction),
            colour_blend);
        colour_blend = 0.5f;
    }

    // check for collision against ground
    const Vec3 ground_inverse_normal(0.0f, -1.0f, 0.0f);
    if (dot(ground_inverse_normal, direction) > 0.0f) {
        // hit the ground, figure out where
        const Vec3 ground_point(0.0f, 0.0f, 0.0f);
        const Vec3 to_ground {ground_point - position};
        const float distance_to_ground {dot(to_ground, ground_inverse_normal)};
        const float dot_to_ground {dot(direction, ground_inverse_normal)};
        const float distance {distance_to_ground / dot_to_ground};
        const Vec3 ground_intersection {position + direction * distance};
        colour = lerp(
            colour,
            sample_ground(
                ground_intersection,
                direction,
                sphere_point_on_ground,
                sphere_magnitude_squared),
            colour_blend);
    } else {
        colour = lerp(
            colour,
            // TODO: remove position parameter
            sample_sky(direction),
            colour_blend);
    }

    return colour;
}

void draw_scene(const int image_width, const int image_height) noexcept {
    const Vec3 camera_forward{0.0f, 0.0f, 1.0f};
    const Vec3 camera_right{1.0f, 0.0f, 0.0f};
    const Vec3 camera_up{0.0f, 1.0f, 0.0f};
    const Vec3 camera_pos{0.0f, 10.0f, 0.0f};

    const int half_image_width = image_width / 2;
    const int half_image_height = image_height / 2;

    for (int y=image_height-1; y>=0; --y) {
        for (int x=0; x<image_width; ++x) {
            const Vec3 pixel_offset = Vec3{
                float(x-half_image_width),
                float(y-half_image_height),
                0.0f};

            const Vec3 pixel_direction = normalised(
                camera_forward*image_height + pixel_offset);

            const Vec3 colour = sample(camera_pos, pixel_direction);

            printf("%c%c%c", int(colour.x), int(colour.y), int(colour.z));
        }
    }
}

int main() {
    printf("P6 512 512 255 ");
    draw_scene(512, 512);
}

// Copyright 2014-2019 Angelos Evripiotis
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
<|endoftext|>


<commit_before>7fd895c2-4b02-11e5-a89c-28cfe9171a43<commit_msg>I'm done<commit_after>7fe4923d-4b02-11e5-b631-28cfe9171a43<|endoftext|>


<commit_before>d6d67df0-4b02-11e5-916f-28cfe9171a43<commit_msg>No longer crashes if X<commit_after>d6e65599-4b02-11e5-97c6-28cfe9171a43<|endoftext|>


<commit_before>/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "config.h"

#include "build/buildjson.hpp"
#include "conf.hpp"
#include "dbus/dbusconfiguration.hpp"
#include "interfaces.hpp"
#include "pid/builder.hpp"
#include "pid/buildjson.hpp"
#include "pid/pidloop.hpp"
#include "pid/tuning.hpp"
#include "pid/zone.hpp"
#include "sensors/builder.hpp"
#include "sensors/buildjson.hpp"
#include "sensors/manager.hpp"
#include "util.hpp"

#include <CLI/CLI.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/bus.hpp>

#include <chrono>
#include <filesystem>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>

namespace pid_control
{

/* The configuration converted sensor list. */
std::map<std::string, conf::SensorConfig> sensorConfig = {};
/* The configuration converted PID list. */
std::map<int64_t, conf::PIDConf> zoneConfig = {};
/* The configuration converted Zone configuration. */
std::map<int64_t, conf::ZoneConfig> zoneDetailsConfig = {};

} // namespace pid_control

/** the swampd daemon will check for the existence of this file. */
constexpr auto jsonConfigurationPath = "/usr/share/swampd/config.json";
std::string configPath = "";

/* async io context for operation */
boost::asio::io_context io;

/* buses for system control */
static sdbusplus::asio::connection modeControlBus(io);
static sdbusplus::asio::connection
    hostBus(io, sdbusplus::bus::new_system().release());
static sdbusplus::asio::connection
    passiveBus(io, sdbusplus::bus::new_system().release());

namespace pid_control
{

void restartControlLoops()
{
    static SensorManager mgmr;
    static std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> zones;
    static std::vector<std::shared_ptr<boost::asio::steady_timer>> timers;
    static bool isCanceling = false;

    for (const auto timer : timers)
    {
        timer->cancel();
    }
    isCanceling = true;
    timers.clear();

    if (zones.size() > 0 && zones.begin()->second.use_count() > 1)
    {
        throw std::runtime_error("wait for count back to 1");
    }
    zones.clear();
    isCanceling = false;

    const std::string& path =
        (configPath.length() > 0) ? configPath : jsonConfigurationPath;

    if (std::filesystem::exists(path))
    {
        /*
         * When building the sensors, if any of the dbus passive ones aren't on
         * the bus, it'll fail immediately.
         */
        try
        {
            auto jsonData = parseValidateJson(path);
            sensorConfig = buildSensorsFromJson(jsonData);
            std::tie(zoneConfig, zoneDetailsConfig) =
                buildPIDsFromJson(jsonData);
        }
        catch (const std::exception& e)
        {
            std::cerr << "Failed during building: " << e.what() << "\n";
            exit(EXIT_FAILURE); /* fatal error. */
        }
    }
    else
    {
        static boost::asio::steady_timer reloadTimer(io);
        if (!dbus_configuration::init(modeControlBus, reloadTimer, sensorConfig,
                                      zoneConfig, zoneDetailsConfig))
        {
            return; // configuration not ready
        }
    }

    mgmr = buildSensors(sensorConfig, passiveBus, hostBus);
    zones = buildZones(zoneConfig, zoneDetailsConfig, mgmr, modeControlBus);

    if (0 == zones.size())
    {
        std::cerr << "No zones defined, exiting.\n";
        std::exit(EXIT_FAILURE);
    }

    for (const auto& i : zones)
    {
        std::shared_ptr<boost::asio::steady_timer> timer = timers.emplace_back(
            std::make_shared<boost::asio::steady_timer>(io));
        std::cerr << "pushing zone " << i.first << "\n";
        pidControlLoop(i.second, timer, &isCanceling);
    }
}

void tryRestartControlLoops(bool first)
{
    static int count = 0;
    static const auto delayTime = std::chrono::seconds(10);
    static boost::asio::steady_timer timer(io);
    // try to start a control loop while the loop has been scheduled.
    if (first && count != 0)
    {
        std::cerr
            << "ControlLoops has been scheduled, refresh the loop count\n";
        count = 1;
        return;
    }

    auto restartLbd = [](const boost::system::error_code& error) {
        if (error == boost::asio::error::operation_aborted)
        {
            return;
        }

        // for the last loop, don't elminate the failure of restartControlLoops.
        if (count >= 5)
        {
            restartControlLoops();
            // reset count after succesful restartControlLoops()
            count = 0;
            return;
        }

        // retry when restartControlLoops() has some failure.
        try
        {
            restartControlLoops();
            // reset count after succesful restartControlLoops()
            count = 0;
        }
        catch (const std::exception& e)
        {
            std::cerr << count
                      << " Failed during restartControlLoops, try again: "
                      << e.what() << "\n";
            tryRestartControlLoops(false);
        }
    };
    count++;
    // first time of trying to restart the control loop without a delay
    if (first)
    {
        boost::asio::post(io,
                          std::bind(restartLbd, boost::system::error_code()));
    }
    // re-try control loop, set up a delay.
    else
    {
        timer.expires_after(delayTime);
        timer.async_wait(restartLbd);
    }

    return;
}

} // namespace pid_control

int main(int argc, char* argv[])
{
    loggingPath = "";
    loggingEnabled = false;
    tuningEnabled = false;

    CLI::App app{"OpenBMC Fan Control Daemon"};

    app.add_option("-c,--conf", configPath,
                   "Optional parameter to specify configuration at run-time")
        ->check(CLI::ExistingFile);
    app.add_option("-l,--log", loggingPath,
                   "Optional parameter to specify logging folder")
        ->check(CLI::ExistingDirectory);
    app.add_flag("-t,--tuning", tuningEnabled, "Enable or disable tuning");

    CLI11_PARSE(app, argc, argv);

    static constexpr auto loggingEnablePath = "/etc/thermal.d/logging";
    static constexpr auto tuningEnablePath = "/etc/thermal.d/tuning";

    // If this file exists, enable logging at runtime
    std::ifstream fsLogging(loggingEnablePath);
    if (fsLogging)
    {
        // Unless file contents are a valid directory path, use system default
        std::getline(fsLogging, loggingPath);
        if (!(std::filesystem::exists(loggingPath)))
        {
            loggingPath = std::filesystem::temp_directory_path();
        }
        fsLogging.close();

        loggingEnabled = true;
        std::cerr << "Logging enabled: " << loggingPath << "\n";
    }

    // If this file exists, enable tuning at runtime
    if (std::filesystem::exists(tuningEnablePath))
    {
        tuningEnabled = true;
        std::cerr << "Tuning enabled\n";
    }

    static constexpr auto modeRoot = "/xyz/openbmc_project/settings/fanctrl";
    // Create a manager for the ModeBus because we own it.
    sdbusplus::server::manager::manager(
        static_cast<sdbusplus::bus::bus&>(modeControlBus), modeRoot);
    hostBus.request_name("xyz.openbmc_project.Hwmon.external");
    modeControlBus.request_name("xyz.openbmc_project.State.FanCtrl");

    /*
     * All sensors are managed by one manager, but each zone has a pointer to
     * it.
     */

    pid_control::tryRestartControlLoops();

    io.run();
    return 0;
}
<commit_msg>Add object manager<commit_after>/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "config.h"

#include "build/buildjson.hpp"
#include "conf.hpp"
#include "dbus/dbusconfiguration.hpp"
#include "interfaces.hpp"
#include "pid/builder.hpp"
#include "pid/buildjson.hpp"
#include "pid/pidloop.hpp"
#include "pid/tuning.hpp"
#include "pid/zone.hpp"
#include "sensors/builder.hpp"
#include "sensors/buildjson.hpp"
#include "sensors/manager.hpp"
#include "util.hpp"

#include <CLI/CLI.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/manager.hpp>

#include <chrono>
#include <filesystem>
#include <iostream>
#include <list>
#include <map>
#include <memory>
#include <thread>
#include <unordered_map>
#include <utility>
#include <vector>

namespace pid_control
{

/* The configuration converted sensor list. */
std::map<std::string, conf::SensorConfig> sensorConfig = {};
/* The configuration converted PID list. */
std::map<int64_t, conf::PIDConf> zoneConfig = {};
/* The configuration converted Zone configuration. */
std::map<int64_t, conf::ZoneConfig> zoneDetailsConfig = {};

} // namespace pid_control

/** the swampd daemon will check for the existence of this file. */
constexpr auto jsonConfigurationPath = "/usr/share/swampd/config.json";
std::string configPath = "";

/* async io context for operation */
boost::asio::io_context io;

/* buses for system control */
static sdbusplus::asio::connection modeControlBus(io);
static sdbusplus::asio::connection
    hostBus(io, sdbusplus::bus::new_system().release());
static sdbusplus::asio::connection
    passiveBus(io, sdbusplus::bus::new_system().release());

namespace pid_control
{

void restartControlLoops()
{
    static SensorManager mgmr;
    static std::unordered_map<int64_t, std::shared_ptr<ZoneInterface>> zones;
    static std::vector<std::shared_ptr<boost::asio::steady_timer>> timers;
    static bool isCanceling = false;

    for (const auto timer : timers)
    {
        timer->cancel();
    }
    isCanceling = true;
    timers.clear();

    if (zones.size() > 0 && zones.begin()->second.use_count() > 1)
    {
        throw std::runtime_error("wait for count back to 1");
    }
    zones.clear();
    isCanceling = false;

    const std::string& path =
        (configPath.length() > 0) ? configPath : jsonConfigurationPath;

    if (std::filesystem::exists(path))
    {
        /*
         * When building the sensors, if any of the dbus passive ones aren't on
         * the bus, it'll fail immediately.
         */
        try
        {
            auto jsonData = parseValidateJson(path);
            sensorConfig = buildSensorsFromJson(jsonData);
            std::tie(zoneConfig, zoneDetailsConfig) =
                buildPIDsFromJson(jsonData);
        }
        catch (const std::exception& e)
        {
            std::cerr << "Failed during building: " << e.what() << "\n";
            exit(EXIT_FAILURE); /* fatal error. */
        }
    }
    else
    {
        static boost::asio::steady_timer reloadTimer(io);
        if (!dbus_configuration::init(modeControlBus, reloadTimer, sensorConfig,
                                      zoneConfig, zoneDetailsConfig))
        {
            return; // configuration not ready
        }
    }

    mgmr = buildSensors(sensorConfig, passiveBus, hostBus);
    zones = buildZones(zoneConfig, zoneDetailsConfig, mgmr, modeControlBus);

    if (0 == zones.size())
    {
        std::cerr << "No zones defined, exiting.\n";
        std::exit(EXIT_FAILURE);
    }

    for (const auto& i : zones)
    {
        std::shared_ptr<boost::asio::steady_timer> timer = timers.emplace_back(
            std::make_shared<boost::asio::steady_timer>(io));
        std::cerr << "pushing zone " << i.first << "\n";
        pidControlLoop(i.second, timer, &isCanceling);
    }
}

void tryRestartControlLoops(bool first)
{
    static int count = 0;
    static const auto delayTime = std::chrono::seconds(10);
    static boost::asio::steady_timer timer(io);
    // try to start a control loop while the loop has been scheduled.
    if (first && count != 0)
    {
        std::cerr
            << "ControlLoops has been scheduled, refresh the loop count\n";
        count = 1;
        return;
    }

    auto restartLbd = [](const boost::system::error_code& error) {
        if (error == boost::asio::error::operation_aborted)
        {
            return;
        }

        // for the last loop, don't elminate the failure of restartControlLoops.
        if (count >= 5)
        {
            restartControlLoops();
            // reset count after succesful restartControlLoops()
            count = 0;
            return;
        }

        // retry when restartControlLoops() has some failure.
        try
        {
            restartControlLoops();
            // reset count after succesful restartControlLoops()
            count = 0;
        }
        catch (const std::exception& e)
        {
            std::cerr << count
                      << " Failed during restartControlLoops, try again: "
                      << e.what() << "\n";
            tryRestartControlLoops(false);
        }
    };
    count++;
    // first time of trying to restart the control loop without a delay
    if (first)
    {
        boost::asio::post(io,
                          std::bind(restartLbd, boost::system::error_code()));
    }
    // re-try control loop, set up a delay.
    else
    {
        timer.expires_after(delayTime);
        timer.async_wait(restartLbd);
    }

    return;
}

} // namespace pid_control

int main(int argc, char* argv[])
{
    loggingPath = "";
    loggingEnabled = false;
    tuningEnabled = false;

    CLI::App app{"OpenBMC Fan Control Daemon"};

    app.add_option("-c,--conf", configPath,
                   "Optional parameter to specify configuration at run-time")
        ->check(CLI::ExistingFile);
    app.add_option("-l,--log", loggingPath,
                   "Optional parameter to specify logging folder")
        ->check(CLI::ExistingDirectory);
    app.add_flag("-t,--tuning", tuningEnabled, "Enable or disable tuning");

    CLI11_PARSE(app, argc, argv);

    static constexpr auto loggingEnablePath = "/etc/thermal.d/logging";
    static constexpr auto tuningEnablePath = "/etc/thermal.d/tuning";

    // If this file exists, enable logging at runtime
    std::ifstream fsLogging(loggingEnablePath);
    if (fsLogging)
    {
        // Unless file contents are a valid directory path, use system default
        std::getline(fsLogging, loggingPath);
        if (!(std::filesystem::exists(loggingPath)))
        {
            loggingPath = std::filesystem::temp_directory_path();
        }
        fsLogging.close();

        loggingEnabled = true;
        std::cerr << "Logging enabled: " << loggingPath << "\n";
    }

    // If this file exists, enable tuning at runtime
    if (std::filesystem::exists(tuningEnablePath))
    {
        tuningEnabled = true;
        std::cerr << "Tuning enabled\n";
    }

    static constexpr auto modeRoot = "/xyz/openbmc_project/settings/fanctrl";
    // Create a manager for the ModeBus because we own it.
    sdbusplus::server::manager::manager(
        static_cast<sdbusplus::bus::bus&>(modeControlBus), modeRoot);
    hostBus.request_name("xyz.openbmc_project.Hwmon.external");
    modeControlBus.request_name("xyz.openbmc_project.State.FanCtrl");
    sdbusplus::server::manager::manager objManager(modeControlBus, modeRoot);

    /*
     * All sensors are managed by one manager, but each zone has a pointer to
     * it.
     */

    pid_control::tryRestartControlLoops();

    io.run();
    return 0;
}
<|endoftext|>


<commit_before>// $Id$
// Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

void pmd_digits(Int_t mode = 0)
{
  Bool_t drawBackPolygons = kFALSE;

  gStyle->SetPalette(1, 0);

  TString spl;

  TString sddl;
  TString bsddl="DDL";

  AliRunLoader* rl =  AliEveEventManager::AssertRunLoader();
  rl->LoadDigits("PMD");
  TTree* pmdt = rl->GetTreeD("PMD", false);

  //  cout << pmdt->GetEntries() << endl;

  gEve->DisableRedraw();

  TEveElementList* l = new TEveElementList("PMD");
  // l->SetTitle("tooltip");
  // l->SetMainColor(3);
  gEve->AddElement(l);

  TEveRGBAPalette* pal = new TEveRGBAPalette(20, 1000);
  pal->SetLimits(0, 1024);

  Int_t NSM         = 0;
  Int_t istartDDL   = 0;
  Int_t iendDDL     = 0;
  Int_t modnumber   = 0;
  Int_t istartPlane = 0;
  Int_t iendPlane   = 0;
  Float_t zpos      = 0;

  switch(mode)
    {
    case 0:
      istartPlane = 0;
      iendPlane   = 1;
      printf("--- Visualization is set for PREshower Plane ---\n");
      break;

    case 1:
      istartPlane = 1;
      iendPlane   = 2;
      printf("--- Visualization is set for CPV Plane ---\n");
      break;

    case 2:
      istartPlane = 0;
      iendPlane   = 2;
      printf("--- Visualization is set for both Planes ---\n");
      break;

    default:
      printf("--- Not set for any Plane ---\n");
    }

  for (Int_t ipl = istartPlane; ipl < iendPlane; ipl++)
    {

      if (ipl == 0)
	{
	  spl       = "PRE";
	  istartDDL = 0;
	  iendDDL   = 4;
	  zpos      = 365.;
	}
      if (ipl == 1)
	{
	  spl       = "CPV";
	  istartDDL = 4;
	  iendDDL   = 6;
	  zpos      = 360.;
	}

      TEveElementList* lplane = new TEveElementList(spl.Data());
      //  l->SetMainColor(3);
      gEve->AddElement(lplane, l);

      for (Int_t iddl = istartDDL; iddl < iendDDL; iddl++)
	{
	  sddl = bsddl;
	  sddl += iddl;
	  TEveElementList* lddl = new TEveElementList(sddl.Data());
	  //  l->SetMainColor(3);
	  gEve->AddElement(lddl, lplane);

	  modnumber = iddl*6;

	  if (iddl < 4)
	    {
	      NSM = 6;
	    }
	  else if (iddl >=4 && iddl < 6)
	    {
	      NSM = 12;
	    }

	  for (Int_t ism = 0; ism < NSM; ism++)
	    {

	      AliEvePMDModule *lmodule = new AliEvePMDModule();
	      lmodule->SetPosition(0.,0.,zpos);
	      lmodule->DisplayDigitsData(modnumber, pmdt);
              lmodule->SetPalette(pal);
              if (drawBackPolygons)
              {
                TEveFrameBox* b = lmodule->GetFrame();
                b->SetFrameWidth(1.5);
                b->SetFrameColor(1);
                b->SetBackColor (kTeal - 9);
                b->SetFrameFill (kFALSE);
                b->SetDrawBack  (kTRUE);
              }
	      gEve->AddElement(lmodule, lddl);
	      modnumber++;
	      if (iddl == 4 && modnumber == 30) modnumber = 42;
	    }

	}

    }

  gEve->EnableRedraw();
}

// ---------------------------------------------------------------------- //
<commit_msg>Put back Color_t cast for TEveFrameBox::SetBackColor() which I forgot to sanitize in ROOT.<commit_after>// $Id$
// Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

void pmd_digits(Int_t mode = 0)
{
  Bool_t drawBackPolygons = kFALSE;

  gStyle->SetPalette(1, 0);

  TString spl;

  TString sddl;
  TString bsddl="DDL";

  AliRunLoader* rl =  AliEveEventManager::AssertRunLoader();
  rl->LoadDigits("PMD");
  TTree* pmdt = rl->GetTreeD("PMD", false);

  //  cout << pmdt->GetEntries() << endl;

  gEve->DisableRedraw();

  TEveElementList* l = new TEveElementList("PMD");
  // l->SetTitle("tooltip");
  // l->SetMainColor(3);
  gEve->AddElement(l);

  TEveRGBAPalette* pal = new TEveRGBAPalette(20, 1000);
  pal->SetLimits(0, 1024);

  Int_t NSM         = 0;
  Int_t istartDDL   = 0;
  Int_t iendDDL     = 0;
  Int_t modnumber   = 0;
  Int_t istartPlane = 0;
  Int_t iendPlane   = 0;
  Float_t zpos      = 0;

  switch(mode)
    {
    case 0:
      istartPlane = 0;
      iendPlane   = 1;
      printf("--- Visualization is set for PREshower Plane ---\n");
      break;

    case 1:
      istartPlane = 1;
      iendPlane   = 2;
      printf("--- Visualization is set for CPV Plane ---\n");
      break;

    case 2:
      istartPlane = 0;
      iendPlane   = 2;
      printf("--- Visualization is set for both Planes ---\n");
      break;

    default:
      printf("--- Not set for any Plane ---\n");
    }

  for (Int_t ipl = istartPlane; ipl < iendPlane; ipl++)
    {

      if (ipl == 0)
	{
	  spl       = "PRE";
	  istartDDL = 0;
	  iendDDL   = 4;
	  zpos      = 365.;
	}
      if (ipl == 1)
	{
	  spl       = "CPV";
	  istartDDL = 4;
	  iendDDL   = 6;
	  zpos      = 360.;
	}

      TEveElementList* lplane = new TEveElementList(spl.Data());
      //  l->SetMainColor(3);
      gEve->AddElement(lplane, l);

      for (Int_t iddl = istartDDL; iddl < iendDDL; iddl++)
	{
	  sddl = bsddl;
	  sddl += iddl;
	  TEveElementList* lddl = new TEveElementList(sddl.Data());
	  //  l->SetMainColor(3);
	  gEve->AddElement(lddl, lplane);

	  modnumber = iddl*6;

	  if (iddl < 4)
	    {
	      NSM = 6;
	    }
	  else if (iddl >=4 && iddl < 6)
	    {
	      NSM = 12;
	    }

	  for (Int_t ism = 0; ism < NSM; ism++)
	    {

	      AliEvePMDModule *lmodule = new AliEvePMDModule();
	      lmodule->SetPosition(0.,0.,zpos);
	      lmodule->DisplayDigitsData(modnumber, pmdt);
              lmodule->SetPalette(pal);
              if (drawBackPolygons)
              {
                TEveFrameBox* b = lmodule->GetFrame();
                b->SetFrameWidth(1.5);
                b->SetFrameColor(1);
                b->SetBackColor ((Color_t) (kTeal - 9));
                b->SetFrameFill (kFALSE);
                b->SetDrawBack  (kTRUE);
              }
	      gEve->AddElement(lmodule, lddl);
	      modnumber++;
	      if (iddl == 4 && modnumber == 30) modnumber = 42;
	    }

	}

    }

  gEve->EnableRedraw();
}

// ---------------------------------------------------------------------- //
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}
<commit_msg>Changed application style to "Fusion"<commit_after>#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setStyle("fusion");
    MainWindow w;
    w.show();
    return a.exec();
}
<|endoftext|>


<commit_before>44892428-2748-11e6-a830-e0f84713e7b8<commit_msg>Does anyone even read these anymore???<commit_after>44bdd4cc-2748-11e6-8c45-e0f84713e7b8<|endoftext|>


<commit_before>//
// Urho3D Engine
// Copyright (c) 2008-2012 Lasse rni
//
// 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 "Precompiled.h"
#include "Context.h"
#include "Log.h"
#include "Technique.h"
#include "Profiler.h"
#include "ResourceCache.h"
#include "ShaderVariation.h"
#include "StringUtils.h"
#include "XMLFile.h"

#include "DebugNew.h"

static const String passNames[] =
{
    "base",
    "litbase",
    "light",
    "prealpha",
    "postalpha",
    "prepass",
    "material",
    "deferred",
    "shadow",
    ""
};

static const String blendModeNames[] =
{
    "replace",
    "add",
    "multiply",
    "alpha",
    "addalpha",
    "premulalpha",
    "invdestalpha",
    ""
};

static const String CompareModeNames[] =
{
    "always",
    "equal",
    "notequal",
    "less",
    "lessequal",
    "greater",
    "greaterequal",
    ""
};

Pass::Pass(PassType type) :
    type_(type),
    blendMode_(BLEND_REPLACE),
    depthTestMode_(CMP_LESSEQUAL),
    depthWrite_(true),
    alphaMask_(false)
{
}

Pass::~Pass()
{
}

void Pass::SetBlendMode(BlendMode mode)
{
    blendMode_ = mode;
}

void Pass::SetDepthTestMode(CompareMode mode)
{
    depthTestMode_ = mode;
}

void Pass::SetDepthWrite(bool enable)
{
    depthWrite_ = enable;
}

void Pass::SetAlphaMask(bool enable)
{
    alphaMask_ = enable;
}

void Pass::SetVertexShader(const String& name)
{
    vertexShaderName_ = name;
    ReleaseShaders();
}

void Pass::SetPixelShader(const String& name)
{
    pixelShaderName_ = name;
    ReleaseShaders();
}

void Pass::ReleaseShaders()
{
    vertexShaders_.Clear();
    pixelShaders_.Clear();
}

OBJECTTYPESTATIC(Technique);

Technique::Technique(Context* context) :
    Resource(context),
    isSM3_(false),
    shadersLoadedFrameNumber_(0)
{
}

Technique::~Technique()
{
}

void Technique::RegisterObject(Context* context)
{
    context->RegisterFactory<Technique>();
}

bool Technique::Load(Deserializer& source)
{
    PROFILE(LoadTechnique);

    SharedPtr<XMLFile> xml(new XMLFile(context_));
    if (!xml->Load(source))
        return false;

    XMLElement rootElem = xml->GetRoot();
    if (rootElem.HasAttribute("sm3"))
        isSM3_ = rootElem.GetBool("sm3");

    XMLElement passElem = rootElem.GetChild("pass");
    while (passElem)
    {
        PassType type = MAX_PASSES;
        if (passElem.HasAttribute("name"))
        {
            String name = passElem.GetAttributeLower("name");
            type = (PassType)GetStringListIndex(name, passNames, MAX_PASSES);
            if (type == MAX_PASSES)
                LOGERROR("Unknown pass " + name);
        }
        else
            LOGERROR("Missing pass name");

        if (type != MAX_PASSES)
        {
            Pass* newPass = CreatePass(type);

            if (passElem.HasAttribute("vs"))
                newPass->SetVertexShader(passElem.GetAttribute("vs"));

            if (passElem.HasAttribute("ps"))
                newPass->SetPixelShader(passElem.GetAttribute("ps"));

            if (passElem.HasAttribute("blend"))
            {
                String blend = passElem.GetAttributeLower("blend");
                newPass->SetBlendMode((BlendMode)GetStringListIndex(blend, blendModeNames, BLEND_REPLACE));
            }

            if (passElem.HasAttribute("depthtest"))
            {
                String depthTest = passElem.GetAttributeLower("depthtest");
                if (depthTest == "false")
                    newPass->SetDepthTestMode(CMP_ALWAYS);
                else
                    newPass->SetDepthTestMode((CompareMode)GetStringListIndex(depthTest, CompareModeNames, CMP_LESS));
            }

            if (passElem.HasAttribute("depthwrite"))
                newPass->SetDepthWrite(passElem.GetBool("depthwrite"));

            if (passElem.HasAttribute("alphamask"))
                newPass->SetAlphaMask(passElem.GetBool("alphamask"));
        }

        passElem = passElem.GetNext("pass");
    }

    // Calculate memory use
    unsigned memoryUse = sizeof(Technique);
    for (unsigned i = 0; i < MAX_PASSES; ++i)
    {
        if (passes_[i])
            memoryUse += sizeof(Pass);
    }

    SetMemoryUse(memoryUse);
    return true;
}

void Technique::SetIsSM3(bool enable)
{
    isSM3_ = enable;
}

void Technique::ReleaseShaders()
{
    for (unsigned i = 0; i < MAX_PASSES; ++i)
    {
        if (passes_[i])
            passes_[i]->ReleaseShaders();
    }
}

Pass* Technique::CreatePass(PassType pass)
{
    if (!passes_[pass])
        passes_[pass] = new Pass(pass);

    return passes_[pass];
}

void Technique::RemovePass(PassType pass)
{
    passes_[pass].Reset();
}

void Technique::MarkShadersLoaded(unsigned frameNumber)
{
    shadersLoadedFrameNumber_ = frameNumber;
}

const String& Technique::GetPassName(PassType pass)
{
    return passNames[pass];
}
<commit_msg>Fixed erroneous capitalization.<commit_after>//
// Urho3D Engine
// Copyright (c) 2008-2012 Lasse rni
//
// 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 "Precompiled.h"
#include "Context.h"
#include "Log.h"
#include "Technique.h"
#include "Profiler.h"
#include "ResourceCache.h"
#include "ShaderVariation.h"
#include "StringUtils.h"
#include "XMLFile.h"

#include "DebugNew.h"

static const String passNames[] =
{
    "base",
    "litbase",
    "light",
    "prealpha",
    "postalpha",
    "prepass",
    "material",
    "deferred",
    "shadow",
    ""
};

static const String blendModeNames[] =
{
    "replace",
    "add",
    "multiply",
    "alpha",
    "addalpha",
    "premulalpha",
    "invdestalpha",
    ""
};

static const String compareModeNames[] =
{
    "always",
    "equal",
    "notequal",
    "less",
    "lessequal",
    "greater",
    "greaterequal",
    ""
};

Pass::Pass(PassType type) :
    type_(type),
    blendMode_(BLEND_REPLACE),
    depthTestMode_(CMP_LESSEQUAL),
    depthWrite_(true),
    alphaMask_(false)
{
}

Pass::~Pass()
{
}

void Pass::SetBlendMode(BlendMode mode)
{
    blendMode_ = mode;
}

void Pass::SetDepthTestMode(CompareMode mode)
{
    depthTestMode_ = mode;
}

void Pass::SetDepthWrite(bool enable)
{
    depthWrite_ = enable;
}

void Pass::SetAlphaMask(bool enable)
{
    alphaMask_ = enable;
}

void Pass::SetVertexShader(const String& name)
{
    vertexShaderName_ = name;
    ReleaseShaders();
}

void Pass::SetPixelShader(const String& name)
{
    pixelShaderName_ = name;
    ReleaseShaders();
}

void Pass::ReleaseShaders()
{
    vertexShaders_.Clear();
    pixelShaders_.Clear();
}

OBJECTTYPESTATIC(Technique);

Technique::Technique(Context* context) :
    Resource(context),
    isSM3_(false),
    shadersLoadedFrameNumber_(0)
{
}

Technique::~Technique()
{
}

void Technique::RegisterObject(Context* context)
{
    context->RegisterFactory<Technique>();
}

bool Technique::Load(Deserializer& source)
{
    PROFILE(LoadTechnique);

    SharedPtr<XMLFile> xml(new XMLFile(context_));
    if (!xml->Load(source))
        return false;

    XMLElement rootElem = xml->GetRoot();
    if (rootElem.HasAttribute("sm3"))
        isSM3_ = rootElem.GetBool("sm3");

    XMLElement passElem = rootElem.GetChild("pass");
    while (passElem)
    {
        PassType type = MAX_PASSES;
        if (passElem.HasAttribute("name"))
        {
            String name = passElem.GetAttributeLower("name");
            type = (PassType)GetStringListIndex(name, passNames, MAX_PASSES);
            if (type == MAX_PASSES)
                LOGERROR("Unknown pass " + name);
        }
        else
            LOGERROR("Missing pass name");

        if (type != MAX_PASSES)
        {
            Pass* newPass = CreatePass(type);

            if (passElem.HasAttribute("vs"))
                newPass->SetVertexShader(passElem.GetAttribute("vs"));

            if (passElem.HasAttribute("ps"))
                newPass->SetPixelShader(passElem.GetAttribute("ps"));

            if (passElem.HasAttribute("blend"))
            {
                String blend = passElem.GetAttributeLower("blend");
                newPass->SetBlendMode((BlendMode)GetStringListIndex(blend, blendModeNames, BLEND_REPLACE));
            }

            if (passElem.HasAttribute("depthtest"))
            {
                String depthTest = passElem.GetAttributeLower("depthtest");
                if (depthTest == "false")
                    newPass->SetDepthTestMode(CMP_ALWAYS);
                else
                    newPass->SetDepthTestMode((CompareMode)GetStringListIndex(depthTest, compareModeNames, CMP_LESS));
            }

            if (passElem.HasAttribute("depthwrite"))
                newPass->SetDepthWrite(passElem.GetBool("depthwrite"));

            if (passElem.HasAttribute("alphamask"))
                newPass->SetAlphaMask(passElem.GetBool("alphamask"));
        }

        passElem = passElem.GetNext("pass");
    }

    // Calculate memory use
    unsigned memoryUse = sizeof(Technique);
    for (unsigned i = 0; i < MAX_PASSES; ++i)
    {
        if (passes_[i])
            memoryUse += sizeof(Pass);
    }

    SetMemoryUse(memoryUse);
    return true;
}

void Technique::SetIsSM3(bool enable)
{
    isSM3_ = enable;
}

void Technique::ReleaseShaders()
{
    for (unsigned i = 0; i < MAX_PASSES; ++i)
    {
        if (passes_[i])
            passes_[i]->ReleaseShaders();
    }
}

Pass* Technique::CreatePass(PassType pass)
{
    if (!passes_[pass])
        passes_[pass] = new Pass(pass);

    return passes_[pass];
}

void Technique::RemovePass(PassType pass)
{
    passes_[pass].Reset();
}

void Technique::MarkShadersLoaded(unsigned frameNumber)
{
    shadersLoadedFrameNumber_ = frameNumber;
}

const String& Technique::GetPassName(PassType pass)
{
    return passNames[pass];
}
<|endoftext|>


<commit_before><commit_msg>make sure screencap's data stream matches what adb expects<commit_after><|endoftext|>