about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/001help.cc15
-rw-r--r--subx/003trace.cc45
2 files changed, 49 insertions, 11 deletions
diff --git a/subx/001help.cc b/subx/001help.cc
index 636205ad..65e291c5 100644
--- a/subx/001help.cc
+++ b/subx/001help.cc
@@ -9,6 +9,19 @@ if (argc <= 1 || is_equal(argv[1], "--help")) {
   return 0;
 }
 
+//: Support for option parsing.
+//: Options always begin with '--' and are always the first arguments. An
+//: option will never follow a non-option.
+char** arg = &argv[1];
+while (argc > 1 && starts_with(*arg, "--")) {
+  if (false)
+    ;  // no-op branch just so any further additions can consistently always start with 'else'
+  // End Commandline Options(*arg)
+  else
+    cerr << "skipping unknown option " << *arg << '\n';
+  --argc;  ++argv;  ++arg;
+}
+
 if (is_equal(argv[1], "help")) {
   if (argc == 2) {
     cerr << "help on what?\n";
@@ -63,6 +76,8 @@ void init_help() {
     "    subx translate <input 'source' file> <output ELF binary>\n"
     "- Run a SubX binary using SubX itself (for better error messages):\n"
     "    subx run <ELF binary>\n"
+    "Add '--trace' to any of these commands to also emit a trace, for debugging purposes.\n"
+    "However, options starting with '--' must always come before any other arguments.\n"
     "\n"
     "To start learning how to write SubX programs, run:\n"
     "  subx help\n"
diff --git a/subx/003trace.cc b/subx/003trace.cc
index 994b5eca..f5969de6 100644
--- a/subx/003trace.cc
+++ b/subx/003trace.cc
@@ -77,14 +77,36 @@ struct trace_line {
 };
 
 :(before "End Globals")
-bool Hide_errors = false;
-bool Dump_trace = false;
-string Dump_label = "";
+bool Hide_errors = false;  // if set, don't print even error trace lines to screen
+bool Dump_trace = false;  // if set, print trace lines to screen
+string Dump_label = "";  // if set, print trace lines matching a single label to screen
 :(before "End Reset")
 Hide_errors = false;
 Dump_trace = false;
 Dump_label = "";
 
+//: Support for tracing an entire run.
+//: Traces can have a lot of overhead, so only turn them on when asked.
+:(before "End Commandline Options(*arg)")
+else if (is_equal(*arg, "--trace")) {
+  Save_trace = true;
+}
+:(before "End Commandline Parsing")
+if (Save_trace) {
+  cerr << "initializing trace\n";
+  Trace_stream = new trace_stream;
+}
+:(code)
+void cleanup_main() {
+  if (!Trace_stream) return;
+  if (Save_trace)
+    Trace_stream->save();
+  delete Trace_stream;
+  Trace_stream = NULL;
+}
+:(before "End One-time Setup")
+atexit(cleanup_main);
+
 :(before "End Types")
 // Pre-define some global constants that trace_stream needs to know about.
 // Since they're in the Types section, they'll be included in any cleaved
@@ -116,6 +138,13 @@ struct trace_stream {
     return *curr_stream;
   }
 
+  void save() {
+    cerr << "saving trace to 'last_run'\n";
+    ofstream fout("last_run");
+    fout << readable_contents("");
+    fout.close();
+  }
+
   // be sure to call this before messing with curr_stream or curr_label
   void newline();
   // useful for debugging
@@ -189,7 +218,7 @@ ostream& operator<<(ostream& os, end /*unused*/) {
 }
 
 :(before "End Globals")
-bool Save_trace = false;
+bool Save_trace = false;  // if set, write out trace to disk
 
 // Trace_stream is a resource, lease_tracer uses RAII to manage it.
 :(before "End Types")
@@ -200,12 +229,7 @@ struct lease_tracer {
 :(code)
 lease_tracer::lease_tracer() { Trace_stream = new trace_stream; }
 lease_tracer::~lease_tracer() {
-  if (!Trace_stream) return;  // in case tests close Trace_stream
-  if (Save_trace) {
-    ofstream fout("last_trace");
-    fout << Trace_stream->readable_contents("");
-    fout.close();
-  }
+  if (Save_trace) Trace_stream->save();
   delete Trace_stream, Trace_stream = NULL;
 }
 :(before "End Includes")
@@ -371,7 +395,6 @@ using std::vector;
 using std::list;
 #include <set>
 using std::set;
-#include <algorithm>
 
 #include <sstream>
 using std::istringstream;