about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-11-17 01:21:00 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-11-17 01:21:00 -0800
commit08cf048f2a8ed0fa096f2c82e147b61ffc480e2a (patch)
tree80493ca241c9172e21df76cedb98312af6de8113
parent21c277062ef151ad86e2003ad0e2bfb09f3d4c2d (diff)
downloadmu-08cf048f2a8ed0fa096f2c82e147b61ffc480e2a.tar.gz
2454
Another gotcha uncovered in the process of sorting out the previous
commit: I keep using eof() but forgetting that there are two other
states an istream can get into. Just never use eof().
-rw-r--r--001help.cc7
-rw-r--r--010vm.cc6
-rw-r--r--011load.cc26
-rw-r--r--014literal_string.cc10
-rw-r--r--030container.cc4
-rw-r--r--050scenario.cc2
-rw-r--r--054dilated_reagent.cc2
-rw-r--r--055parse_tree.cc4
-rw-r--r--058shape_shifting_container.cc2
-rw-r--r--092persist.cc2
10 files changed, 36 insertions, 29 deletions
diff --git a/001help.cc b/001help.cc
index c193cf7d..4b7c3858 100644
--- a/001help.cc
+++ b/001help.cc
@@ -113,6 +113,13 @@ template<typename T> typename T::mapped_type& get_or_insert(T& map, typename T::
 }
 //: The contract: any container that relies on get_or_insert should never call
 //: contains_key.
+//:
+//: 7. istreams are a royal pain in the arse. You have to be careful about
+//: what subclass you try to putback into. You have to watch out for the pesky
+//: failbit and badbit. Just avoid eof() and use this helper instead.
+bool has_data(istream& in) {
+  return in && !in.eof();
+}
 
 :(before "End Includes")
 #include<assert.h>
diff --git a/010vm.cc b/010vm.cc
index 016d3ad6..fcd72be2 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -236,7 +236,7 @@ reagent::reagent(string s) :original_string(s), value(0), initialized(false), ty
   istringstream in(s);
   in >> std::noskipws;
   // properties
-  while (!in.eof()) {
+  while (has_data(in)) {
     istringstream row(slurp_until(in, '/'));
     row >> std::noskipws;
     string key = slurp_until(row, ':');
@@ -261,7 +261,7 @@ reagent::reagent(string s) :original_string(s), value(0), initialized(false), ty
 
 string_tree* parse_property_list(istream& in) {
   skip_whitespace(in);
-  if (in.eof()) return NULL;
+  if (!has_data(in)) return NULL;
   string_tree* result = new string_tree(slurp_until(in, ':'));
   result->right = parse_property_list(in);
   return result;
@@ -539,7 +539,7 @@ void dump(const string_tree* x, ostream& out) {
 }
 
 void skip_whitespace(istream& in) {
-  while (!in.eof() && isspace(in.peek()) && in.peek() != '\n') {
+  while (in && isspace(in.peek()) && in.peek() != '\n') {
     in.get();
   }
 }
diff --git a/011load.cc b/011load.cc
index b318e88a..578e2b46 100644
--- a/011load.cc
+++ b/011load.cc
@@ -19,9 +19,9 @@ vector<recipe_ordinal> load(string form) {
 vector<recipe_ordinal> load(istream& in) {
   in >> std::noskipws;
   vector<recipe_ordinal> result;
-  while (!in.eof()) {
+  while (has_data(in)) {
     skip_whitespace_and_comments(in);
-    if (in.eof()) break;
+    if (!has_data(in)) break;
     string command = next_word(in);
     // Command Handlers
     if (command == "recipe") {
@@ -82,25 +82,25 @@ void slurp_body(istream& in, recipe& result) {
 
 bool next_instruction(istream& in, instruction* curr) {
   curr->clear();
-  if (in.eof()) {
+  if (!has_data(in)) {
     raise_error << "0: unbalanced '[' for recipe\n" << end();
     return false;
   }
   skip_whitespace(in);
-  if (in.eof()) {
+  if (!has_data(in)) {
     raise_error << "1: unbalanced '[' for recipe\n" << end();
     return false;
   }
   skip_whitespace_and_comments(in);
-  if (in.eof()) {
+  if (!has_data(in)) {
     raise_error << "2: unbalanced '[' for recipe\n" << end();
     return false;
   }
 
   vector<string> words;
-  while (in.peek() != '\n' && !in.eof()) {
+  while (has_data(in) && in.peek() != '\n') {
     skip_whitespace(in);
-    if (in.eof()) {
+    if (!has_data(in)) {
       raise_error << "3: unbalanced '[' for recipe\n" << end();
       return false;
     }
@@ -117,7 +117,7 @@ bool next_instruction(istream& in, instruction* curr) {
     curr->is_label = true;
     curr->label = words.at(0);
     trace(9993, "parse") << "label: " << curr->label << end();
-    if (in.eof()) {
+    if (!has_data(in)) {
       raise_error << "7: unbalanced '[' for recipe\n" << end();
       return false;
     }
@@ -151,7 +151,7 @@ bool next_instruction(istream& in, instruction* curr) {
   for (vector<reagent>::iterator p = curr->products.begin(); p != curr->products.end(); ++p) {
     trace(9993, "parse") << "  product: " << p->to_string() << end();
   }
-  if (in.eof()) {
+  if (!has_data(in)) {
     raise_error << "9: unbalanced '[' for recipe\n" << end();
     return false;
   }
@@ -176,7 +176,7 @@ string Ignore(",");  // meaningless except within [] strings
 :(code)
 void slurp_word(istream& in, ostream& out) {
   char c;
-  if (!in.eof() && Terminators.find(in.peek()) != string::npos) {
+  if (has_data(in) && Terminators.find(in.peek()) != string::npos) {
     in >> c;
     out << c;
     return;
@@ -198,7 +198,7 @@ void skip_ignored_characters(istream& in) {
 
 void skip_whitespace_and_comments(istream& in) {
   while (true) {
-    if (in.eof()) break;
+    if (!has_data(in)) break;
     if (isspace(in.peek())) in.get();
     else if (in.peek() == ',') in.get();
     else if (in.peek() == '#') skip_comment(in);
@@ -207,9 +207,9 @@ void skip_whitespace_and_comments(istream& in) {
 }
 
 void skip_comment(istream& in) {
-  if (!in.eof() && in.peek() == '#') {
+  if (has_data(in) && in.peek() == '#') {
     in.get();
-    while (!in.eof() && in.peek() != '\n') in.get();
+    while (has_data(in) && in.peek() != '\n') in.get();
   }
 }
 
diff --git a/014literal_string.cc b/014literal_string.cc
index 1e7f7b0b..34655aa9 100644
--- a/014literal_string.cc
+++ b/014literal_string.cc
@@ -32,7 +32,7 @@ if (in.peek() == '[') {
 :(code)
 string slurp_quoted(istream& in) {
   ostringstream out;
-  assert(!in.eof());  assert(in.peek() == '[');  out << static_cast<char>(in.get());  // slurp the '['
+  assert(has_data(in));  assert(in.peek() == '[');  out << static_cast<char>(in.get());  // slurp the '['
   if (is_code_string(in, out))
     slurp_quoted_comment_aware(in, out);
   else
@@ -43,7 +43,7 @@ string slurp_quoted(istream& in) {
 // A string is a code string if it contains a newline before any non-whitespace
 // todo: support comments before the newline. But that gets messy.
 bool is_code_string(istream& in, ostream& out) {
-  while (!in.eof()) {
+  while (has_data(in)) {
     char c = in.get();
     if (!isspace(c)) {
       in.putback(c);
@@ -61,7 +61,7 @@ bool is_code_string(istream& in, ostream& out) {
 // strings.
 void slurp_quoted_comment_oblivious(istream& in, ostream& out) {
   int brace_depth = 1;
-  while (!in.eof()) {
+  while (has_data(in)) {
     char c = in.get();
     if (c == '\\') {
       out << static_cast<char>(in.get());
@@ -72,7 +72,7 @@ void slurp_quoted_comment_oblivious(istream& in, ostream& out) {
     if (c == ']') --brace_depth;
     if (brace_depth == 0) break;
   }
-  if (in.eof() && brace_depth > 0) {
+  if (!has_data(in) && brace_depth > 0) {
     raise_error << "unbalanced '['\n" << end();
     out.clear();
   }
@@ -88,7 +88,7 @@ void slurp_quoted_comment_aware(istream& in, ostream& out) {
     }
     if (c == '#') {
       out << c;
-      while (!in.eof() && in.peek() != '\n') out << static_cast<char>(in.get());
+      while (has_data(in) && in.peek() != '\n') out << static_cast<char>(in.get());
       continue;
     }
     if (c == '[') {
diff --git a/030container.cc b/030container.cc
index 25303f39..9be42f23 100644
--- a/030container.cc
+++ b/030container.cc
@@ -415,7 +415,7 @@ void insert_container(const string& command, kind_of_type kind, istream& in) {
   recently_added_types.push_back(get(Type_ordinal, name));
   info.name = name;
   info.kind = kind;
-  while (!in.eof()) {
+  while (has_data(in)) {
     skip_whitespace_and_comments(in);
     string element = next_word(in);
     if (element == "]") break;
@@ -424,7 +424,7 @@ void insert_container(const string& command, kind_of_type kind, istream& in) {
     info.element_names.push_back(slurp_until(inner, ':'));
     trace(9993, "parse") << "  element name: " << info.element_names.back() << end();
     type_tree* new_type = NULL;
-    for (type_tree** curr_type = &new_type; !inner.eof(); curr_type = &(*curr_type)->right) {
+    for (type_tree** curr_type = &new_type; has_data(inner); curr_type = &(*curr_type)->right) {
       string type_name = slurp_until(inner, ':');
       // End insert_container Special Uses(type_name)
       if (!contains_key(Type_ordinal, type_name)
diff --git a/050scenario.cc b/050scenario.cc
index 0a1c0f90..71dfa72d 100644
--- a/050scenario.cc
+++ b/050scenario.cc
@@ -270,7 +270,7 @@ void check_memory(const string& s) {
   set<long long int> locations_checked;
   while (true) {
     skip_whitespace_and_comments(in);
-    if (in.eof()) break;
+    if (!has_data(in)) break;
     string lhs = next_word(in);
     if (!is_integer(lhs)) {
       check_type(lhs, in);
diff --git a/054dilated_reagent.cc b/054dilated_reagent.cc
index f1d3b267..ac40f049 100644
--- a/054dilated_reagent.cc
+++ b/054dilated_reagent.cc
@@ -80,7 +80,7 @@ if (s.at(0) == '{') {
   istringstream in(s);
   in >> std::noskipws;
   in.get();  // skip '{'
-  while (!in.eof()) {
+  while (has_data(in)) {
     string key = slurp_key(in);
     if (key.empty()) continue;
     if (key == "}") continue;
diff --git a/055parse_tree.cc b/055parse_tree.cc
index 8f93c1c7..ef9cf4e1 100644
--- a/055parse_tree.cc
+++ b/055parse_tree.cc
@@ -29,7 +29,7 @@ string_tree* parse_string_tree(const string& s) {
 
 string_tree* parse_string_tree(istream& in) {
   skip_whitespace(in);
-  if (in.eof()) return NULL;
+  if (!has_data(in)) return NULL;
   if (in.peek() == ')') {
     in.get();
     return NULL;
@@ -42,7 +42,7 @@ string_tree* parse_string_tree(istream& in) {
   string_tree* result = NULL;
   string_tree** curr = &result;
   while (in.peek() != ')') {
-    assert(!in.eof());
+    assert(has_data(in));
     *curr = new string_tree("");
     skip_whitespace(in);
     skip_ignored_characters(in);
diff --git a/058shape_shifting_container.cc b/058shape_shifting_container.cc
index 02042ac2..c7bc38ac 100644
--- a/058shape_shifting_container.cc
+++ b/058shape_shifting_container.cc
@@ -49,7 +49,7 @@ void read_type_ingredients(string& name) {
     put(Type_ordinal, name, Next_type_ordinal++);
   type_info& info = get_or_insert(Type, get(Type_ordinal, name));
   long long int next_type_ordinal = START_TYPE_INGREDIENTS;
-  while (!in.eof()) {
+  while (has_data(in)) {
     string curr = slurp_until(in, ':');
     if (info.type_ingredient_names.find(curr) != info.type_ingredient_names.end()) {
       raise_error << "can't repeat type ingredient names in a single container definition\n" << end();
diff --git a/092persist.cc b/092persist.cc
index 774ce08f..e0201cd0 100644
--- a/092persist.cc
+++ b/092persist.cc
@@ -57,7 +57,7 @@ string slurp(const string& filename) {
   if (!fin) return result.str();  // don't bother checking errno
   const int N = 1024;
   char buf[N];
-  while (!fin.eof()) {
+  while (has_data(fin)) {
     bzero(buf, N);
     fin.read(buf, N-1);  // leave at least one null
     result << buf;