From d3a9db3aff54ea485f409eaaef3d8f56ad77f0dc Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 5 Oct 2020 11:00:05 -0700 Subject: 6958 --- html/003trace.cc.html | 566 +++++++++++++++++++++++++------------------------- 1 file changed, 283 insertions(+), 283 deletions(-) (limited to 'html/003trace.cc.html') diff --git a/html/003trace.cc.html b/html/003trace.cc.html index 6a9800d3..7c259d19 100644 --- a/html/003trace.cc.html +++ b/html/003trace.cc.html @@ -15,14 +15,14 @@ body { font-size:12pt; font-family: monospace; color: #000000; background-color: a { color:inherit; } * { font-size:12pt; font-size: 1em; } .cSpecial { color: #008000; } +.PreProc { color: #c000c0; } .LineNr { } -.Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } +.SpecialChar { color: #d70000; } .Comment { color: #005faf; } .Delimiter { color: #c000c0; } -.Special { color: #d70000; } .Identifier { color: #af5f00; } .Constant { color: #008787; } -.PreProc { color: #c000c0; } +.Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .SalientComment { color: #0000af; } --> @@ -130,7 +130,7 @@ if ('onhashchange' in window) { 69 //:: == Core data structures 70 71 :(before "End Globals") - 72 trace_stream* Trace_stream = NULL; + 72 trace_stream* Trace_stream = NULL; 73 74 :(before "End Types") 75 struct trace_stream { @@ -154,7 +154,7 @@ if ('onhashchange' in window) { 93 :(before "End Includes") 94 // No brackets around the expansion so that it prints nothing if Trace_stream 95 // isn't initialized. - 96 #define trace(...) !Trace_stream ? cerr : Trace_stream->stream(__VA_ARGS__) + 96 #define trace(...) !Trace_stream ? cerr : Trace_stream->stream(__VA_ARGS__) 97 98 :(before "End trace_stream Fields") 99 // accumulator for current trace_line @@ -167,11 +167,11 @@ if ('onhashchange' in window) { 106 107 //: Some constants. 108 :(before "struct trace_stream") // include constants in all cleaved compilation units -109 const int Max_depth = 9999; +109 const int Max_depth = 9999; 110 :(before "End trace_stream Constructor") 111 curr_stream = NULL; -112 curr_depth = Max_depth; -113 collect_depth = Max_depth; +112 curr_depth = Max_depth; +113 collect_depth = Max_depth; 114 115 :(before "struct trace_stream") 116 struct trace_line { @@ -192,7 +192,7 @@ if ('onhashchange' in window) { 131 132 string unescape_newline(string& s) { 133 std::stringstream ss; -134 for (int i = 0; i < SIZE(s); ++i) { +134 for (int i = 0; i < SIZE(s); ++i) { 135 if (s.at(i) == '\n') 136 ss << "\\n"; 137 else @@ -208,7 +208,7 @@ if ('onhashchange' in window) { 147 //: Starting a new trace line. 148 :(before "End trace_stream Methods") 149 ostream& stream(string label) { -150 return stream(Max_depth, label); +150 return stream(Max_depth, label); 151 } 152 153 ostream& stream(int depth, string label) { @@ -225,7 +225,7 @@ if ('onhashchange' in window) { 164 struct end {}; 165 :(code) 166 ostream& operator<<(ostream& os, end /*unused*/) { -167 if (Trace_stream) Trace_stream->newline(); +167 if (Trace_stream) Trace_stream->newline(); 168 return os; 169 } 170 @@ -234,7 +234,7 @@ if ('onhashchange' in window) { 173 struct die {}; 174 :(code) 175 ostream& operator<<(ostream& /*unused*/, die /*unused*/) { -176 if (Trace_stream) Trace_stream->newline(); +176 if (Trace_stream) Trace_stream->newline(); 177 exit(1); 178 } 179 @@ -246,285 +246,285 @@ if ('onhashchange' in window) { 185 string curr_contents = curr_stream->str(); 186 if (!curr_contents.empty()) { 187 past_lines.push_back(trace_line(curr_contents, trim(curr_label), curr_depth)); // preserve indent in contents -188 // maybe incrementally dump trace +188 // maybe print this line to stderr 189 trace_line& t = past_lines.back(); -190 if (should_incrementally_print_trace()) { +190 if (should_incrementally_print_trace()) { 191 dump_trace_line(cerr, t); 192 } -193 // Hack: on 'bootstrap --trace --dump', emit only to stderr, not 'last_run'. -194 if (Dump_trace) past_lines.pop_back(); // economize on memory -195 // End trace Commit -196 } -197 -198 // clean up -199 delete curr_stream; -200 curr_stream = NULL; -201 curr_label.clear(); -202 curr_depth = Max_depth; -203 } +193 // End trace Commit +194 } +195 +196 // clean up +197 delete curr_stream; +198 curr_stream = NULL; +199 curr_label.clear(); +200 curr_depth = Max_depth; +201 } +202 +203 //:: == Initializing the trace in tests 204 -205 //:: == Initializing the trace in tests -206 -207 :(before "End Includes") -208 #define START_TRACING_UNTIL_END_OF_SCOPE lease_tracer leased_tracer; -209 :(before "End Test Setup") -210 START_TRACING_UNTIL_END_OF_SCOPE -211 -212 //: Trace_stream is a resource, lease_tracer uses RAII to manage it. -213 :(before "End Types") -214 struct lease_tracer { -215 lease_tracer(); -216 ~lease_tracer(); -217 }; -218 :(code) -219 lease_tracer::lease_tracer() { Trace_stream = new trace_stream; } -220 lease_tracer::~lease_tracer() { -221 delete Trace_stream; -222 Trace_stream = NULL; -223 } +205 :(before "End Includes") +206 #define START_TRACING_UNTIL_END_OF_SCOPE lease_tracer leased_tracer; +207 :(before "End Test Setup") +208 START_TRACING_UNTIL_END_OF_SCOPE +209 +210 //: Trace_stream is a resource, lease_tracer uses RAII to manage it. +211 :(before "End Types") +212 struct lease_tracer { +213 lease_tracer(); +214 ~lease_tracer(); +215 }; +216 :(code) +217 lease_tracer::lease_tracer() { Trace_stream = new trace_stream; } +218 lease_tracer::~lease_tracer() { +219 delete Trace_stream; +220 Trace_stream = NULL; +221 } +222 +223 //:: == Errors and warnings using traces 224 -225 //:: == Errors and warnings using traces -226 -227 :(before "End Includes") -228 #define raise (!Trace_stream ? (++Trace_errors,cerr) /*do print*/ : Trace_stream->stream(Error_depth, "error")) -229 #define warn (!Trace_stream ? (++Trace_errors,cerr) /*do print*/ : Trace_stream->stream(Warn_depth, "warn")) -230 -231 //: Print errors and warnings to the screen by default. -232 :(before "struct trace_stream") // include constants in all cleaved compilation units -233 const int Error_depth = 0; -234 const int Warn_depth = 1; -235 :(before "End Globals") -236 int Hide_errors = false; // if set, don't print errors or warnings to screen -237 int Hide_warnings = false; // if set, don't print warnings to screen -238 :(before "End Reset") -239 Hide_errors = false; -240 Hide_warnings = false; -241 //: Never dump warnings in tests -242 :(before "End Test Setup") -243 Hide_warnings = true; -244 :(code) -245 bool trace_stream::should_incrementally_print_trace() { -246 if (!Hide_errors && curr_depth == Error_depth) return true; -247 if (!Hide_warnings && !Hide_errors && curr_depth == Warn_depth) return true; -248 // End Incremental Trace Print Conditions -249 return false; -250 } -251 :(before "End trace_stream Methods") -252 bool should_incrementally_print_trace(); -253 -254 :(before "End Globals") -255 int Trace_errors = 0; // used only when Trace_stream is NULL -256 -257 // Fail tests that displayed (unexpected) errors. -258 // Expected errors should always be hidden and silently checked for. -259 :(before "End Test Teardown") -260 if (Passed && !Hide_errors && trace_contains_errors()) { -261 Passed = false; -262 } -263 :(code) -264 bool trace_contains_errors() { -265 return Trace_errors > 0 || trace_count("error") > 0; -266 } -267 -268 :(before "End Includes") -269 // If we aren't yet sure how to deal with some corner case, use assert_for_now -270 // to indicate that it isn't an inviolable invariant. -271 #define assert_for_now assert -272 #define raise_for_now raise -273 -274 //:: == Other assertions on traces -275 //: Primitives: -276 //: - CHECK_TRACE_CONTENTS(lines) -277 //: Assert that the trace contains the given lines (separated by newlines) -278 //: in order. There can be other intervening lines between them. -279 //: - CHECK_TRACE_DOESNT_CONTAIN(line) -280 //: - CHECK_TRACE_DOESNT_CONTAIN(label, contents) -281 //: Assert that the trace doesn't contain the given (single) line. -282 //: - CHECK_TRACE_COUNT(label, count) -283 //: Assert that the trace contains exactly 'count' lines with the given -284 //: 'label'. -285 //: - CHECK_TRACE_CONTAINS_ERRORS() -286 //: - CHECK_TRACE_DOESNT_CONTAIN_ERRORS() -287 //: - trace_count_prefix(label, prefix) -288 //: Count the number of trace lines with the given 'label' that start with -289 //: the given 'prefix'. -290 -291 :(before "End Includes") -292 #define CHECK_TRACE_CONTENTS(...) check_trace_contents(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) +225 :(before "End Includes") +226 #define raise (!Trace_stream ? (++Trace_errors,cerr) /*do print*/ : Trace_stream->stream(Error_depth, "error")) +227 #define warn (!Trace_stream ? (++Trace_errors,cerr) /*do print*/ : Trace_stream->stream(Warn_depth, "warn")) +228 +229 //: Print errors and warnings to the screen by default. +230 :(before "struct trace_stream") // include constants in all cleaved compilation units +231 const int Error_depth = 0; +232 const int Warn_depth = 1; +233 :(before "End Globals") +234 int Hide_errors = false; // if set, don't print errors or warnings to screen +235 int Hide_warnings = false; // if set, don't print warnings to screen +236 :(before "End Reset") +237 Hide_errors = false; +238 Hide_warnings = false; +239 //: Never dump warnings in tests +240 :(before "End Test Setup") +241 Hide_warnings = true; +242 :(code) +243 bool trace_stream::should_incrementally_print_trace() { +244 if (!Hide_errors && curr_depth == Error_depth) return true; +245 if (!Hide_warnings && !Hide_errors && curr_depth == Warn_depth) return true; +246 // End Incremental Trace Print Conditions +247 return false; +248 } +249 :(before "End trace_stream Methods") +250 bool should_incrementally_print_trace(); +251 +252 :(before "End Globals") +253 int Trace_errors = 0; // used only when Trace_stream is NULL +254 +255 // Fail tests that displayed (unexpected) errors. +256 // Expected errors should always be hidden and silently checked for. +257 :(before "End Test Teardown") +258 if (Passed && !Hide_errors && trace_contains_errors()) { +259 Passed = false; +260 } +261 :(code) +262 bool trace_contains_errors() { +263 return Trace_errors > 0 || trace_count("error") > 0; +264 } +265 +266 :(before "End Includes") +267 // If we aren't yet sure how to deal with some corner case, use assert_for_now +268 // to indicate that it isn't an inviolable invariant. +269 #define assert_for_now assert +270 #define raise_for_now raise +271 +272 //:: == Other assertions on traces +273 //: Primitives: +274 //: - CHECK_TRACE_CONTENTS(lines) +275 //: Assert that the trace contains the given lines (separated by newlines) +276 //: in order. There can be other intervening lines between them. +277 //: - CHECK_TRACE_DOESNT_CONTAIN(line) +278 //: - CHECK_TRACE_DOESNT_CONTAIN(label, contents) +279 //: Assert that the trace doesn't contain the given (single) line. +280 //: - CHECK_TRACE_COUNT(label, count) +281 //: Assert that the trace contains exactly 'count' lines with the given +282 //: 'label'. +283 //: - CHECK_TRACE_CONTAINS_ERRORS() +284 //: - CHECK_TRACE_DOESNT_CONTAIN_ERRORS() +285 //: - trace_count_prefix(label, prefix) +286 //: Count the number of trace lines with the given 'label' that start with +287 //: the given 'prefix'. +288 +289 :(before "End Includes") +290 #define CHECK_TRACE_CONTENTS(...) check_trace_contents(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) +291 +292 #define CHECK_TRACE_DOESNT_CONTAIN(...) CHECK(trace_doesnt_contain(__VA_ARGS__)) 293 -294 #define CHECK_TRACE_DOESNT_CONTAIN(...) CHECK(trace_doesnt_contain(__VA_ARGS__)) -295 -296 #define CHECK_TRACE_COUNT(label, count) \ -297 if (Passed && trace_count(label) != (count)) { \ -298 cerr << "\nF - " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): trace_count of " << label << " should be " << count << '\n'; \ -299 cerr << " got " << trace_count(label) << '\n'; /* multiple eval */ \ -300 DUMP(label); \ -301 Passed = false; \ -302 return; /* Currently we stop at the very first failure. */ \ -303 } -304 -305 #define CHECK_TRACE_CONTAINS_ERRORS() CHECK(trace_contains_errors()) -306 #define CHECK_TRACE_DOESNT_CONTAIN_ERRORS() \ -307 if (Passed && trace_contains_errors()) { \ -308 cerr << "\nF - " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): unexpected errors\n"; \ -309 DUMP("error"); \ -310 Passed = false; \ -311 return; \ -312 } -313 -314 // Allow tests to ignore trace lines generated during setup. -315 #define CLEAR_TRACE delete Trace_stream, Trace_stream = new trace_stream -316 -317 :(code) -318 bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expected) { -319 if (!Passed) return false; -320 if (!Trace_stream) return false; -321 vector<string> expected_lines = split(expected, "\n"); -322 int curr_expected_line = 0; -323 while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty()) -324 ++curr_expected_line; -325 if (curr_expected_line == SIZE(expected_lines)) return true; -326 string label, contents; -327 split_label_contents(expected_lines.at(curr_expected_line), &label, &contents); -328 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { -329 if (label != p->label) continue; -330 string t = trim(p->contents); -331 if (contents != unescape_newline(t)) continue; -332 ++curr_expected_line; -333 while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty()) -334 ++curr_expected_line; -335 if (curr_expected_line == SIZE(expected_lines)) return true; -336 split_label_contents(expected_lines.at(curr_expected_line), &label, &contents); -337 } -338 -339 if (line_exists_anywhere(label, contents)) { -340 cerr << "\nF - " << FUNCTION << "(" << FILE << ":" << LINE << "): line [" << label << ": " << contents << "] out of order in trace:\n"; -341 DUMP(""); -342 } -343 else { -344 cerr << "\nF - " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << contents << "] in trace:\n"; -345 DUMP(label); -346 } -347 Passed = false; -348 return false; -349 } -350 -351 bool trace_doesnt_contain(string expected) { -352 vector<string> tmp = split_first(expected, ": "); -353 if (SIZE(tmp) == 1) { -354 raise << expected << ": missing label or contents in trace line\n" << end(); -355 assert(false); -356 } -357 return trace_count(tmp.at(0), tmp.at(1)) == 0; -358 } -359 -360 int trace_count(string label) { -361 return trace_count(label, ""); -362 } -363 -364 int trace_count(string label, string line) { -365 if (!Trace_stream) return 0; -366 long result = 0; -367 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { -368 if (label == p->label) { -369 if (line == "" || trim(line) == trim(p->contents)) -370 ++result; -371 } -372 } -373 return result; -374 } -375 -376 int trace_count_prefix(string label, string prefix) { -377 if (!Trace_stream) return 0; -378 long result = 0; -379 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { -380 if (label == p->label) { -381 if (starts_with(trim(p->contents), trim(prefix))) -382 ++result; -383 } -384 } -385 return result; -386 } -387 -388 void split_label_contents(const string& s, string* label, string* contents) { -389 static const string delim(": "); -390 size_t pos = s.find(delim); -391 if (pos == string::npos) { -392 *label = ""; -393 *contents = trim(s); -394 } -395 else { -396 *label = trim(s.substr(0, pos)); -397 *contents = trim(s.substr(pos+SIZE(delim))); -398 } -399 } -400 -401 bool line_exists_anywhere(const string& label, const string& contents) { -402 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { -403 if (label != p->label) continue; -404 if (contents == trim(p->contents)) return true; -405 } -406 return false; -407 } -408 -409 vector<string> split(string s, string delim) { -410 vector<string> result; -411 size_t begin=0, end=s.find(delim); -412 while (true) { -413 if (end == string::npos) { -414 result.push_back(string(s, begin, string::npos)); -415 break; -416 } -417 result.push_back(string(s, begin, end-begin)); -418 begin = end+SIZE(delim); -419 end = s.find(delim, begin); -420 } -421 return result; -422 } -423 -424 vector<string> split_first(string s, string delim) { -425 vector<string> result; -426 size_t end=s.find(delim); -427 result.push_back(string(s, 0, end)); -428 if (end != string::npos) -429 result.push_back(string(s, end+SIZE(delim), string::npos)); -430 return result; -431 } +294 #define CHECK_TRACE_COUNT(label, count) \ +295 if (Passed && trace_count(label) != (count)) { \ +296 cerr << "\nF - " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): trace_count of " << label << " should be " << count << '\n'; \ +297 cerr << " got " << trace_count(label) << '\n'; /* multiple eval */ \ +298 DUMP(label); \ +299 Passed = false; \ +300 return; /* Currently we stop at the very first failure. */ \ +301 } +302 +303 #define CHECK_TRACE_CONTAINS_ERRORS() CHECK(trace_contains_errors()) +304 #define CHECK_TRACE_DOESNT_CONTAIN_ERRORS() \ +305 if (Passed && trace_contains_errors()) { \ +306 cerr << "\nF - " << __FUNCTION__ << "(" << __FILE__ << ":" << __LINE__ << "): unexpected errors\n"; \ +307 DUMP("error"); \ +308 Passed = false; \ +309 return; \ +310 } +311 +312 // Allow tests to ignore trace lines generated during setup. +313 #define CLEAR_TRACE delete Trace_stream, Trace_stream = new trace_stream +314 +315 :(code) +316 bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expected) { +317 if (!Passed) return false; +318 if (!Trace_stream) return false; +319 vector<string> expected_lines = split(expected, "\n"); +320 int curr_expected_line = 0; +321 while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty()) +322 ++curr_expected_line; +323 if (curr_expected_line == SIZE(expected_lines)) return true; +324 string label, contents; +325 split_label_contents(expected_lines.at(curr_expected_line), &label, &contents); +326 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { +327 if (label != p->label) continue; +328 string t = trim(p->contents); +329 if (contents != unescape_newline(t)) continue; +330 ++curr_expected_line; +331 while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty()) +332 ++curr_expected_line; +333 if (curr_expected_line == SIZE(expected_lines)) return true; +334 split_label_contents(expected_lines.at(curr_expected_line), &label, &contents); +335 } +336 +337 if (line_exists_anywhere(label, contents)) { +338 cerr << "\nF - " << FUNCTION << "(" << FILE << ":" << LINE << "): line [" << label << ": " << contents << "] out of order in trace:\n"; +339 DUMP(""); +340 } +341 else { +342 cerr << "\nF - " << FUNCTION << "(" << FILE << ":" << LINE << "): missing [" << contents << "] in trace:\n"; +343 DUMP(label); +344 } +345 Passed = false; +346 return false; +347 } +348 +349 bool trace_doesnt_contain(string expected) { +350 vector<string> tmp = split_first(expected, ": "); +351 if (SIZE(tmp) == 1) { +352 raise << expected << ": missing label or contents in trace line\n" << end(); +353 assert(false); +354 } +355 return trace_count(tmp.at(0), tmp.at(1)) == 0; +356 } +357 +358 int trace_count(string label) { +359 return trace_count(label, ""); +360 } +361 +362 int trace_count(string label, string line) { +363 if (!Trace_stream) return 0; +364 long result = 0; +365 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { +366 if (label == p->label) { +367 if (line == "" || trim(line) == trim(p->contents)) +368 ++result; +369 } +370 } +371 return result; +372 } +373 +374 int trace_count_prefix(string label, string prefix) { +375 if (!Trace_stream) return 0; +376 long result = 0; +377 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { +378 if (label == p->label) { +379 if (starts_with(trim(p->contents), trim(prefix))) +380 ++result; +381 } +382 } +383 return result; +384 } +385 +386 void split_label_contents(const string& s, string* label, string* contents) { +387 static const string delim(": "); +388 size_t pos = s.find(delim); +389 if (pos == string::npos) { +390 *label = ""; +391 *contents = trim(s); +392 } +393 else { +394 *label = trim(s.substr(0, pos)); +395 *contents = trim(s.substr(pos+SIZE(delim))); +396 } +397 } +398 +399 bool line_exists_anywhere(const string& label, const string& contents) { +400 for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin(); p != Trace_stream->past_lines.end(); ++p) { +401 if (label != p->label) continue; +402 if (contents == trim(p->contents)) return true; +403 } +404 return false; +405 } +406 +407 vector<string> split(string s, string delim) { +408 vector<string> result; +409 size_t begin=0, end=s.find(delim); +410 while (true) { +411 if (end == string::npos) { +412 result.push_back(string(s, begin, string::npos)); +413 break; +414 } +415 result.push_back(string(s, begin, end-begin)); +416 begin = end+SIZE(delim); +417 end = s.find(delim, begin); +418 } +419 return result; +420 } +421 +422 vector<string> split_first(string s, string delim) { +423 vector<string> result; +424 size_t end=s.find(delim); +425 result.push_back(string(s, 0, end)); +426 if (end != string::npos) +427 result.push_back(string(s, end+SIZE(delim), string::npos)); +428 return result; +429 } +430 +431 //:: == Helpers for debugging using traces 432 -433 //:: == Helpers for debugging using traces -434 -435 :(before "End Includes") -436 // To debug why a test is failing, dump its trace using '?'. -437 #define DUMP(label) if (Trace_stream) cerr << Trace_stream->readable_contents(label); -438 -439 // To add temporary prints to the trace, use 'dbg'. -440 // `git log` should never show any calls to 'dbg'. -441 #define dbg trace(0, "a") -442 -443 //: Dump the entire trace to file where it can be browsed offline. -444 //: Dump the trace as it happens; that way you get something even if the -445 //: program crashes. -446 -447 :(before "End Globals") -448 ofstream Trace_file; -449 :(before "End Commandline Options(*arg)") -450 else if (is_equal(*arg, "--trace")) { -451 cerr << "saving trace to 'last_run'\n"; -452 Trace_file.open("last_run"); -453 // Add a dummy line up top; otherwise the `browse_trace` tool currently has -454 // no way to expand any lines above an error. -455 Trace_file << " 0 dummy: start\n"; -456 // End --trace Settings -457 } -458 :(before "End trace Commit") -459 if (Trace_file) { -460 dump_trace_line(Trace_file, t); +433 :(before "End Includes") +434 // To debug why a test is failing, dump its trace using '?'. +435 #define DUMP(label) if (Trace_stream) cerr << Trace_stream->readable_contents(label); +436 +437 // To add temporary prints to the trace, use 'dbg'. +438 // `git log` should never show any calls to 'dbg'. +439 #define dbg trace(0, "a") +440 +441 //: Dump the entire trace to file where it can be browsed offline. +442 //: Dump the trace as it happens; that way you get something even if the +443 //: program crashes. +444 +445 :(before "End Globals") +446 ofstream Trace_file; +447 :(before "End Commandline Options(*arg)") +448 else if (is_equal(*arg, "--trace")) { +449 cerr << "saving trace to 'last_run'\n"; +450 Trace_file.open("last_run"); +451 // Add a dummy line up top; otherwise the `browse_trace` tool currently has +452 // no way to expand any lines above an error. +453 Trace_file << " 0 dummy: start\n"; +454 // End --trace Settings +455 } +456 :(before "End trace Commit") +457 if (Trace_file.is_open()) { +458 dump_trace_line(Trace_file, t); +459 Trace_file.flush(); +460 past_lines.pop_back(); // economize on memory 461 } 462 :(before "End One-time Setup") 463 atexit(cleanup_main); 464 :(code) 465 void cleanup_main() { -466 if (Trace_file) Trace_file.close(); +466 if (Trace_file.is_open()) Trace_file.close(); 467 // End cleanup_main 468 } 469 @@ -543,13 +543,13 @@ if ('onhashchange' in window) { 482 //: Particularly useful when juggling multiple trace streams, like when 483 //: debugging sandboxes. 484 :(before "End Globals") -485 bool Dump_trace = false; +485 bool Dump_trace = false; 486 :(before "End Commandline Options(*arg)") -487 else if (is_equal(*arg, "--dump")) { -488 Dump_trace = true; +487 else if (is_equal(*arg, "--dump")) { +488 Dump_trace = true; 489 } 490 :(before "End Incremental Trace Print Conditions") -491 if (Dump_trace) return true; +491 if (Dump_trace) return true; 492 493 //: Miscellaneous helpers. 494 -- cgit 1.4.1-2-gfad0