:(before "int main")
:(before "End Tracing")
bool Hide_warnings = false;
:(before "End Setup")
Hide_warnings = false;
:(before "End Types")
struct trace_line {
int depth;
string label;
string contents;
trace_line(string l, string c) :depth(0), label(l), contents(c) {}
trace_line(int d, string l, string c) :depth(d), label(l), contents(c) {}
};
:(before "End Tracing")
struct trace_stream {
vector<trace_line> past_lines;
ostringstream* curr_stream;
string curr_layer;
int curr_depth;
string dump_layer;
trace_stream() :curr_stream(NULL), curr_depth(0) {}
~trace_stream() { if (curr_stream) delete curr_stream; }
ostringstream& stream(string layer) {
return stream(0, layer);
}
ostringstream& stream(int depth, string layer) {
newline();
curr_stream = new ostringstream;
curr_layer = layer;
curr_depth = depth;
return *curr_stream;
}
void newline() {
if (!curr_stream) return;
string curr_contents = curr_stream->str();
past_lines.push_back(trace_line(curr_depth, trim(curr_layer), curr_contents));
if (curr_layer == dump_layer || curr_layer == "dump" || dump_layer == "all" ||
(!Hide_warnings && curr_layer == "warn"))
cerr << curr_layer << ": " << curr_contents << '\n';
delete curr_stream;
curr_stream = NULL;
curr_layer.clear();
curr_depth = 0;
}
string readable_contents(string layer) {
newline();
ostringstream output;
layer = trim(layer);
for (vector<trace_line>::iterator p = past_lines.begin(); p != past_lines.end(); ++p)
if (layer.empty() || layer == p->label) {
if (p->depth)
output << std::setw(4) << p->depth << ' ';
output << p->label << ": " << p->contents << '\n';
}
return output.str();
}
};
^L
trace_stream* Trace_stream = NULL;
#define trace(...) !Trace_stream ? cerr : Trace_stream->stream(__VA_ARGS__)
#define raise ((!Trace_stream || !Hide_warnings) ? (tb_shutdown(),cerr) : Trace_stream->stream("warn"))
#define xlog if (false) log
#define log cerr
:(before "End Types")
struct die {};
:(before "End Tracing")
ostream& operator<<(ostream& os, unused die) {
if (Hide_warnings) return os;
tb_shutdown();
os << "dying";
if (Trace_stream) Trace_stream->newline();
exit(1);
}
#define CLEAR_TRACE delete Trace_stream, Trace_stream = new trace_stream;
#define DUMP(layer) if (Trace_stream) cerr << Trace_stream->readable_contents(layer);
static string Trace_dir = ".traces/";
string Trace_file;
struct lease_tracer {
lease_tracer() { Trace_stream = new trace_stream; }
~lease_tracer() {
if (!Trace_file.empty()) {
ofstream fout((Trace_dir+Trace_file).c_str());
fout << Trace_stream->readable_contents("");
fout.close();
}
delete Trace_stream, Trace_stream = NULL, Trace_file = "";
}
};
#define START_TRACING_UNTIL_END_OF_SCOPE lease_tracer leased_tracer;
:(before "End Test Setup")
START_TRACING_UNTIL_END_OF_SCOPE
#define CHECK_TRACE_CONTENTS(...) check_trace_contents(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
:(before "End Tracing")
bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expected) {
vector<string> expected_lines = split(expected, "^D");
long long int curr_expected_line = 0;
while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty())
++curr_expected_line;
if (curr_expected_line == SIZE(expected_lines)) return true;
Trace_stream->newline();
string layer, contents;
split_layer_contents(expected_lines.at(curr_expected_line), &layer, &contents);
for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
if (layer != p->label)
continue;
if (contents != trim(p->contents))
continue;
++curr_expected_line;
while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty())
++curr_expected_line;
if (curr_expected_line == SIZE(expected_lines)) return true;
split_layer_contents(expected_lines.at(curr_expected_line), &layer, &contents);
}
++Num_failures;
cerr << "\nF - " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << contents << "] in trace:\n";
DUMP(layer);
Passed = false;
return false;
}
void split_layer_contents(const string& s, string* layer, string* contents) {
static const string delim(": ");
size_t pos = s.find(delim);
if (pos == string::npos) {
*layer = "";
*contents = trim(s);
}
else {
*layer = trim(s.substr(0, pos));
*contents = trim(s.substr(pos+SIZE(delim)));
}
}
^L
int trace_count(string layer) {
return trace_count(layer, "");
}
int trace_count(string layer, string line) {
Trace_stream->newline();
long result = 0;
for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) {
if (layer == p->label) {
if (line == "" || line == trim(p->contents))
++result;
}
}
return result;
}
#define CHECK_TRACE_WARNS() CHECK(trace_count("warn") > 0)
#define CHECK_TRACE_DOESNT_WARN() \
if (trace_count("warn") > 0) { \
++Num_failures; \
cerr << "\nF - " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): unexpected warnings\n"; \
DUMP("warn"); \
Passed = false; \
return; \
}
bool trace_doesnt_contain(string layer, string line) {
return trace_count(layer, line) == 0;
}
bool trace_doesnt_contain(string expected) {
vector<string> tmp = split(expected, ": ");
return trace_doesnt_contain(tmp.at(0), tmp.at(1));
}
#define CHECK_TRACE_DOESNT_CONTAIN(...) CHECK(trace_doesnt_contain(__VA_ARGS__))
^L
vector<string> split(string s, string delim) {
vector<string> result;
size_t begin=0, end=s.find(delim);
while (true) {
if (end == string::npos) {
result.push_back(string(s, begin, string::npos));
break;
}
result.push_back(string(s, begin, end-begin));
begin = SIZE(end+delim);
end = s.find(delim, begin);
}
return result;
}
string trim(const string& s) {
string::const_iterator first = s.begin();
while (first != s.end() && isspace(*first))
++first;
if (first == s.end()) return "";
string::const_iterator last = --s.end();
while (last != s.begin() && isspace(*last))
--last;
++last;
return string(first, last);
}
:(before "End Includes")
#include<vector>
using std::vector;
#include<list>
using std::list;
#include<map>
using std::map;
#include<set>
using std::set;
#include<algorithm>
#include<iostream>
using std::istream;
using std::ostream;
using std::cin;
using std::cout;
using std::cerr;
#include<iomanip>
#include<sstream>
using std::istringstream;
using std::ostringstream;
#include<fstream>
using std::ifstream;
using std::ofstream;
#include"termbox/termbox.h"
#define unused __attribute__((unused))
:(before "End Globals")
const int Scheduling_depth = 100;
const int Initial_callstack_depth = 101;
const int Max_callstack_depth = 9998;
:(before "End Globals")
int Callstack_depth = 0;
:(before "End Setup")
Callstack_depth = 0;
:(before "End Globals")
const int Primitive_recipe_depth = 9999;