about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/003trace.cc24
-rw-r--r--subx/003trace.test.cc5
-rw-r--r--subx/038---literal_strings.cc17
-rw-r--r--subx/Readme.md5
4 files changed, 39 insertions, 12 deletions
diff --git a/subx/003trace.cc b/subx/003trace.cc
index 9717fb80..e1dadaf6 100644
--- a/subx/003trace.cc
+++ b/subx/003trace.cc
@@ -129,6 +129,21 @@ struct trace_line {
   }
 };
 
+string unescape_newline(string& s) {
+  std::stringstream ss;
+  for(char c : s) {
+    if(c == '\n')
+      ss << "\\n";
+    else
+      ss << c;
+  }
+  return ss.str();
+}
+
+void dump_trace_line(ostream& s, trace_line &t) {
+  s << std::setw(4) << t.depth << ' ' << t.label << ": " << unescape_newline(t.contents) << '\n';
+}
+
 //: Starting a new trace line.
 :(before "End trace_stream Methods")
 ostream& stream(string label) {
@@ -164,7 +179,7 @@ void trace_stream::newline() {
     // maybe incrementally dump trace
     trace_line& t = past_lines.back();
     if (should_incrementally_print_trace()) {
-      cerr       << std::setw(4) << t.depth << ' ' << t.label << ": " << t.contents << '\n';
+      dump_trace_line(cerr, t);
     }
     // End trace Commit
   }
@@ -301,7 +316,8 @@ bool check_trace_contents(string FUNCTION, string FILE, int LINE, string expecte
   split_label_contents(expected_lines.at(curr_expected_line), &label, &contents);
   for (vector<trace_line>::iterator p = Trace_stream->past_lines.begin();  p != Trace_stream->past_lines.end();  ++p) {
     if (label != p->label) continue;
-    if (contents != trim(p->contents)) continue;
+    string t = trim(p->contents);
+    if (contents != unescape_newline(t)) continue;
     ++curr_expected_line;
     while (curr_expected_line < SIZE(expected_lines) && expected_lines.at(curr_expected_line).empty())
       ++curr_expected_line;
@@ -429,7 +445,7 @@ else if (is_equal(*arg, "--trace")) {
 }
 :(before "End trace Commit")
 if (Trace_file) {
-  Trace_file << std::setw(4) << t.depth << ' ' << t.label << ": " << t.contents << '\n';
+  dump_trace_line(Trace_file, t);
 }
 :(before "End One-time Setup")
 atexit(cleanup_main);
@@ -446,7 +462,7 @@ string readable_contents(string label) {
   label = trim(label);
   for (vector<trace_line>::iterator p = past_lines.begin();  p != past_lines.end();  ++p)
     if (label.empty() || label == p->label)
-      output << std::setw(4) << p->depth << ' ' << p->label << ": " << p->contents << '\n';
+      dump_trace_line(output, *p);
   return output.str();
 }
 
diff --git a/subx/003trace.test.cc b/subx/003trace.test.cc
index addc1f44..bec1b789 100644
--- a/subx/003trace.test.cc
+++ b/subx/003trace.test.cc
@@ -64,6 +64,11 @@ void test_trace_count_ignores_trailing_whitespace() {
   CHECK_EQ(trace_count("test layer 1", "foo"), 1);
 }
 
+void test_trace_unescapes_newlines() {
+  trace("test layer 1") << "f\no\no\n" << end();
+  CHECK_TRACE_CONTENTS("test layer 1: f\\no\\no");
+}
+
 // pending: DUMP tests
 // pending: readable_contents() adds newline if necessary.
 // pending: raise also prints to stderr.
diff --git a/subx/038---literal_strings.cc b/subx/038---literal_strings.cc
index b7cb0aa4..19ed2690 100644
--- a/subx/038---literal_strings.cc
+++ b/subx/038---literal_strings.cc
@@ -77,11 +77,11 @@ void add_global_to_data_segment(const string& name, const word& value, segment&
 
 void test_instruction_with_string_literal() {
   parse_instruction_character_by_character(
-      "a \"abc  def\" z\n"  // two spaces inside string
+      "a \"abc  def\\nwee\" z\n"  // two spaces inside string
   );
   CHECK_TRACE_CONTENTS(
       "parse2: word: a\n"
-      "parse2: word: \"abc  def\"\n"
+      "parse2: word: \"abc  def\\nwee\"\n"
       "parse2: word: z\n"
   );
   // no other words
@@ -123,7 +123,18 @@ void parse_instruction_character_by_character(const string& line_data, vector<li
       d << c;
       while (has_data(in)) {
         in >> c;
-        d << c;
+        if(c == '\\') {
+          in >> c;
+          if(c == 'n') d << '\n';
+          else if(c == 't') d << '\t';
+          else if(c == '"') d << '"';
+          else {
+            raise << "parse_instruction_character_by_character: unknown escape sequence '\\" << c << "'\n" << end();
+            return;
+          }
+        } else {
+          d << c;
+        }
         if (c == '"') break;
       }
       result.words.back().data = d.str();
diff --git a/subx/Readme.md b/subx/Readme.md
index f842adfd..cc5d7b07 100644
--- a/subx/Readme.md
+++ b/subx/Readme.md
@@ -651,11 +651,6 @@ from a slice:
 * `skip-chars-matching-in-slice`: curr, end, delimiter byte -> new-curr (in `EAX`)
 * `skip-chars-not-matching-in-slice`:  curr, end, delimiter byte -> new-curr (in `EAX`)
 
-## Known issues
-
-* String literals support no escape sequences. In particular, no way to
-  represent newlines.
-
 ## Resources
 
 * [Single-page cheatsheet for the x86 ISA](https://net.cs.uni-bonn.de/fileadmin/user_upload/plohmann/x86_opcode_structure_and_instruction_overview.pdf)