From 18c95e4bf2cc64af53eccec1ca948de89cb9309e Mon Sep 17 00:00:00 2001
From: Timo Heister
Date: Mon, 19 Jan 2015 08:07:28 -0500
Subject: [PATCH] fix ParameterHandler::leave_subsection and parsing
- leave_subsection() had a bool return value for success that doesn't
make sense because an Assert() would never allow false to be returned.
Remove this.
- read_input() would not complain about unbalanced 'subsection'/'end' in
the input. Instead, the ParameterHandler would just stay in that
subsection and so weird error messages about undefined entries would
show up later.
- One could argue that read_input() should always start and end with an
empty subsection path, but we didn't enforce this in the past and it
might be useful to read separate files not into the "top level".
---
doc/news/changes.h | 13 +++
include/deal.II/base/parameter_handler.h | 5 +-
source/base/parameter_handler.cc | 43 ++++++--
tests/bits/parameter_handler_19.cc | 109 +++++++++++++++++++
tests/bits/parameter_handler_19.debug.output | 35 ++++++
5 files changed, 191 insertions(+), 14 deletions(-)
create mode 100644 tests/bits/parameter_handler_19.cc
create mode 100644 tests/bits/parameter_handler_19.debug.output
diff --git a/doc/news/changes.h b/doc/news/changes.h
index 348d5817a4..9b0d93dd25 100644
--- a/doc/news/changes.h
+++ b/doc/news/changes.h
@@ -38,6 +38,13 @@ inconvenience this causes.
+ - Changed: ParameterHandler::leave_subsection() no longer returns a bool
+ indicating if there was a subsection to leave. This never worked in the
+ first place, because an exception was thrown.
+
+ (Timo Heister, 2015/01/19)
+
+
- Changed: Make.global_options was completely redesigned. It still
contains Makefile sourcable information, but they now closely mimic the
declarative style of deal.IIConfig.cmake. Thus, projects that still use
@@ -239,6 +246,12 @@ inconvenience this causes.
Specific improvements
+ - Fixed: ParameterHandler::read_input() now checks that
+ 'subsection'/'end' are balanced in the input.
+
+ (Timo Heister, 2015/01/19)
+
+
- Fixed: In 3d, when you set the
colorize
flag of
GridGenerator::hyper_shell(), the faces of the domain were colored but
the edges were not. This was an oversight because to refine correctly,
diff --git a/include/deal.II/base/parameter_handler.h b/include/deal.II/base/parameter_handler.h
index 1f3639c17a..68ed0b91b2 100644
--- a/include/deal.II/base/parameter_handler.h
+++ b/include/deal.II/base/parameter_handler.h
@@ -1653,10 +1653,9 @@ public:
void enter_subsection (const std::string &subsection);
/**
- * Leave present subsection. Return false if there is no subsection
- * to leave; true otherwise.
+ * Leave present subsection.
*/
- bool leave_subsection ();
+ void leave_subsection ();
/**
* Return value of entry entry_string. If the entry was changed,
diff --git a/source/base/parameter_handler.cc b/source/base/parameter_handler.cc
index fb42ac87a0..03f3f35adb 100644
--- a/source/base/parameter_handler.cc
+++ b/source/base/parameter_handler.cc
@@ -1317,6 +1317,9 @@ bool ParameterHandler::read_input (std::istream &input,
{
AssertThrow (input, ExcIO());
+ // store subsections we are currently in
+ std::vector saved_path = subsection_path;
+
std::string line;
int lineno=0;
bool status = true;
@@ -1327,6 +1330,27 @@ bool ParameterHandler::read_input (std::istream &input,
status &= scan_line (line, filename, lineno);
}
+ if (status && (saved_path != subsection_path))
+ {
+ std::cerr << "Unbalanced 'subsection'/'end' in file <" << filename
+ << ">." << std::endl;
+ if (saved_path.size()>0)
+ {
+ std::cerr << "Path before loading input:" << std::endl;
+ for (unsigned int i=0; i 0)
+ subsection_path.pop_back ();
}
@@ -2434,7 +2451,11 @@ ParameterHandler::scan_line (std::string line,
return false;
}
else
- return leave_subsection ();
+ {
+ leave_subsection ();
+ return true;
+ }
+
}
// regular entry
diff --git a/tests/bits/parameter_handler_19.cc b/tests/bits/parameter_handler_19.cc
new file mode 100644
index 0000000000..ff66fa74df
--- /dev/null
+++ b/tests/bits/parameter_handler_19.cc
@@ -0,0 +1,109 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2002 - 2014 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE at
+// the top level of the deal.II distribution.
+//
+// ---------------------------------------------------------------------
+
+
+
+// ParameterHandler does not complain if you parse input that doesn't close
+// all subsections.
+
+
+#include "../tests.h"
+#include
+#include
+#include
+
+void check ()
+{
+
+ ParameterHandler prm;
+ prm.declare_entry ("dim", "3",Patterns::Integer());
+ prm.enter_subsection("test");
+ prm.declare_entry ("x", "1",Patterns::Integer());
+ prm.leave_subsection();
+ prm.enter_subsection("test2");
+ prm.declare_entry ("y", "1",Patterns::Integer());
+ prm.leave_subsection();
+
+
+ deallog << "* no subsection to leave: " << std::endl;
+ try
+ {
+ prm.leave_subsection();
+ }
+ catch (std::exception &e)
+ {
+ deallog << "Exception " << e.what() << std::endl;
+ }
+
+
+
+ deallog << std::endl << "* read_input with missing 'end':" << std::endl;
+
+ std::string s = "set dim=2\nsubsection test\n\n"; // note: missing "end"
+ bool success = prm.read_input_from_string (s.c_str());
+ deallog << "success? " << success << " (should fail)" << std::endl;
+
+ // make sure read_input resets the current path:
+ try
+ {
+ prm.leave_subsection();
+ deallog << "error, why could we leave a subsection?" << std::endl;
+ }
+ catch (std::exception &e)
+ {
+ deallog << "Exception " << e.what() << std::endl;
+ }
+
+
+
+ deallog << std::endl << "* Check non empty path before read_input()" << std::endl;
+
+ {
+ prm.enter_subsection("test");
+ std::string s = "set x=5\n";
+ bool success = prm.read_input_from_string (s.c_str());
+ deallog << "success? "
+ << success
+ << " (should work), x correct? "
+ << (prm.get_integer("x")==5) << std::endl;
+ prm.leave_subsection();
+ }
+
+
+ deallog << std::endl << "* Check read_input() catches messing with path:" << std::endl;
+ {
+ prm.enter_subsection("test");
+ std::string s = "end\nsubsection test2\nset y=7\n";
+ bool success = prm.read_input_from_string (s.c_str());
+ deallog << "success = " << success << " -- (should fail)" << std::endl;
+ prm.leave_subsection();
+ }
+
+}
+
+
+int main ()
+{
+ deal_II_exceptions::disable_abort_on_exception();
+
+ std::ofstream logfile("output");
+ deallog.attach(logfile);
+ deallog.depth_console(0);
+ deallog.threshold_double(1.e-10);
+
+ check ();
+
+ return 0;
+}
diff --git a/tests/bits/parameter_handler_19.debug.output b/tests/bits/parameter_handler_19.debug.output
new file mode 100644
index 0000000000..c80e0cd0f4
--- /dev/null
+++ b/tests/bits/parameter_handler_19.debug.output
@@ -0,0 +1,35 @@
+
+DEAL::* no subsection to leave:
+DEAL::Exception
+--------------------------------------------------------
+An error occurred in file in function
+ void dealii::ParameterHandler::leave_subsection()
+The violated condition was:
+ subsection_path.size() != 0
+The name and call sequence of the exception was:
+ ExcAlreadyAtTopLevel()
+Additional Information:
+(none)
+--------------------------------------------------------
+
+DEAL::
+DEAL::* read_input with missing 'end':
+DEAL::success? 0 (should fail)
+DEAL::Exception
+--------------------------------------------------------
+An error occurred in file in function
+ void dealii::ParameterHandler::leave_subsection()
+The violated condition was:
+ subsection_path.size() != 0
+The name and call sequence of the exception was:
+ ExcAlreadyAtTopLevel()
+Additional Information:
+(none)
+--------------------------------------------------------
+
+DEAL::
+DEAL::* Check non empty path before read_input()
+DEAL::success? 1 (should work), x correct? 1
+DEAL::
+DEAL::* Check read_input() catches messing with path:
+DEAL::success = 0 -- (should fail)
--
2.39.5