From 9582431bd520e7cbe1d109eda3d82b27cd723cbc Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Wed, 28 Dec 2016 14:02:50 +0100
Subject: [PATCH] bug fix: end preprocessing with error when more than 32
 nested parenthesis are encountered. closes #1201

---
 preprocessor/DynamicModel.cc |  7 +++++++
 preprocessor/ModelTree.cc    | 22 ++++++++++++++++++++++
 preprocessor/ModelTree.hh    |  3 ++-
 preprocessor/StaticModel.cc  |  7 +++++++
 4 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc
index 5f97154d47..68c4d4e09c 100644
--- a/preprocessor/DynamicModel.cc
+++ b/preprocessor/DynamicModel.cc
@@ -2343,6 +2343,13 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll, bool julia
 
   if (output_type == oMatlabDynamicModel)
     {
+      // Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201
+      testNestedParenthesis(model_output);
+      testNestedParenthesis(model_local_vars_output);
+      testNestedParenthesis(jacobian_output);
+      testNestedParenthesis(hessian_output);
+      testNestedParenthesis(third_derivatives_output);
+
       DynamicOutput << "%" << endl
                     << "% Model equations" << endl
                     << "%" << endl
diff --git a/preprocessor/ModelTree.cc b/preprocessor/ModelTree.cc
index b7fabb537d..7eb3cf96c5 100644
--- a/preprocessor/ModelTree.cc
+++ b/preprocessor/ModelTree.cc
@@ -1292,6 +1292,28 @@ ModelTree::writeTemporaryTerms(const temporary_terms_t &tt, const temporary_term
       }
 }
 
+void
+ModelTree::testNestedParenthesis(const ostringstream &output) const
+{
+  string str = output.str();
+  int open = 0;
+  for (string::iterator it = str.begin(); it != str.end(); it++)
+    {
+      if (*it == '(')
+        open++;
+      else if (*it == ')')
+        open--;
+      if (open > 32)
+        {
+          cout << "Error: A .m file created by Dynare will have more than 32 nested parenthesis. Matlab cannot support this. "
+               << "Please use the use_dll option of the model block to circumnavigate this problem." << endl
+               << "       If you have not yet set up a compiler on your system, see the Matlab documentation for doing so." << endl
+               << "       For Windows, see: https://www.mathworks.com/help/matlab/matlab_external/install-mingw-support-package.html" << endl;
+          exit(EXIT_FAILURE);
+        }
+    }
+}
+
 void
 ModelTree::compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, map_idx_t map_idx, bool dynamic, bool steady_dynamic) const
 {
diff --git a/preprocessor/ModelTree.hh b/preprocessor/ModelTree.hh
index ee4e73cf64..edb9f084b4 100644
--- a/preprocessor/ModelTree.hh
+++ b/preprocessor/ModelTree.hh
@@ -190,7 +190,8 @@ protected:
   void compileTemporaryTerms(ostream &code_file, unsigned int &instruction_number, const temporary_terms_t &tt, map_idx_t map_idx, bool dynamic, bool steady_dynamic) const;
   //! Adds informations for simulation in a binary file
   void Write_Inf_To_Bin_File(const string &basename, int &u_count_int, bool &file_open, bool is_two_boundaries, int block_mfs) const;
-
+  //! Checks for the number of nested parenthesis, issues error if > 32. Issue #1201
+  void testNestedParenthesis(const ostringstream &output) const;
   //! Writes model local variables
   /*! No temporary term is used in the output, so that local parameters declarations can be safely put before temporary terms declaration in the output files */
   void writeModelLocalVariables(ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const;
diff --git a/preprocessor/StaticModel.cc b/preprocessor/StaticModel.cc
index b54f6277c8..ae59b626c0 100644
--- a/preprocessor/StaticModel.cc
+++ b/preprocessor/StaticModel.cc
@@ -1398,6 +1398,13 @@ StaticModel::writeStaticModel(ostream &StaticOutput, bool use_dll, bool julia) c
 
   if (output_type == oMatlabStaticModel)
     {
+      // Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201
+      testNestedParenthesis(model_output);
+      testNestedParenthesis(model_local_vars_output);
+      testNestedParenthesis(jacobian_output);
+      testNestedParenthesis(hessian_output);
+      testNestedParenthesis(third_derivatives_output);
+
       StaticOutput << "residual = zeros( " << equations.size() << ", 1);" << endl << endl
                    << "%" << endl
                    << "% Model equations" << endl
-- 
GitLab