diff --git a/ComputingTasks.cc b/ComputingTasks.cc
index 2daf075dc1891d21cce3837fc530bb16fc28aeaa..740b061b1eaa192a661e6afc8eeaeb080f59fee0 100644
--- a/ComputingTasks.cc
+++ b/ComputingTasks.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2017 Dynare Team
+ * Copyright (C) 2003-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -852,15 +852,15 @@ RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool
     output << "options_.k_order_solver = 1;" << endl;
 
   options_list.writeOutput(output);
-  output << "var_list_ = char(";
+  output << "var_list_ = {";
   for (vector<string>::const_iterator it = ramsey_policy_list.begin();
        it != ramsey_policy_list.end(); ++it)
     {
       if (it != ramsey_policy_list.begin())
-        output << ",";
+        output << ";";
       output << "'" << *it << "'";
     }
-  output << ");" << endl
+  output << "};" << endl
          << "ramsey_policy(var_list_);" << endl;
 }
 
diff --git a/DynamicModel.cc b/DynamicModel.cc
index 19072ce71dab3aef3fbeca6c6bfdc6b8d93309aa..054482adc0a247ee91002af316c8c028a9c4a23b 100644
--- a/DynamicModel.cc
+++ b/DynamicModel.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2017 Dynare Team
+ * Copyright (C) 2003-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -1773,21 +1773,38 @@ DynamicModel::reform(const string name1) const
 }
 
 void
-DynamicModel::getNonZeroHessianEquations(map<int, string> &eqs) const
+DynamicModel::printNonZeroHessianEquations(ostream &output) const
+{
+  if (nonzero_hessian_eqs.size() !=  1)
+    output << "[";
+  for (map<int, string>::const_iterator it = nonzero_hessian_eqs.begin();
+       it != nonzero_hessian_eqs.end(); it++)
+    {
+      if (it != nonzero_hessian_eqs.begin())
+        output << " ";
+      output << it->first;
+    }
+  if (nonzero_hessian_eqs.size() != 1)
+    output << "]";
+}
+
+void
+DynamicModel::setNonZeroHessianEquations(map<int, string> &eqs)
 {
   for (second_derivatives_t::const_iterator it = second_derivatives.begin();
        it != second_derivatives.end(); it++)
-    if (eqs.find(it->first.first) == eqs.end())
+    if (nonzero_hessian_eqs.find(it->first.first) == nonzero_hessian_eqs.end())
       {
-        eqs[it->first.first] = "";
+        nonzero_hessian_eqs[it->first.first] = "";
         for (size_t i = 0; i < equation_tags.size(); i++)
           if (equation_tags[i].first == it->first.first)
             if (equation_tags[i].second.first == "name")
               {
-                eqs[it->first.first] = equation_tags[i].second.second;
+                nonzero_hessian_eqs[it->first.first] = equation_tags[i].second.second;
                 break;
               }
       }
+  eqs = nonzero_hessian_eqs;
 }
 
 void
diff --git a/DynamicModel.hh b/DynamicModel.hh
index c9eaec7fff9fc3e0e6d935db2e9b33428dbba6d1..edd506d25fe71f539de65cf2f1bf2849eb86971a 100644
--- a/DynamicModel.hh
+++ b/DynamicModel.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2017 Dynare Team
+ * Copyright (C) 2003-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -80,6 +80,9 @@ private:
   map<pair<int, int>, set<int> > xref_exo;
   map<pair<int, int>, set<int> > xref_exo_det;
 
+  //! Nonzero equations in the Hessian
+  map<int, string> nonzero_hessian_eqs;
+
   //! Number of columns of dynamic jacobian
   /*! Set by computeDerivID()s and computeDynJacobianCols() */
   int dynJacobianColsNbr;
@@ -271,11 +274,11 @@ public:
   void writeJsonXrefs(ostream &output) const;
   void writeJsonXrefsHelper(ostream &output, const map<pair<int, int>, set<int> > &xrefs) const;
 
-  //! Return true if the hessian is equal to zero
-  inline bool checkHessianZero() const;
+  //! Print equations that have non-zero second derivatives
+  void printNonZeroHessianEquations(ostream &output) const;
 
-  //! Return equations that have non-zero second derivatives
-  void getNonZeroHessianEquations(map<int, string> &eqs) const;
+  //! Set the equations that have non-zero second derivatives
+  void setNonZeroHessianEquations(map<int, string> &eqs);
 
   //! Set indices for var expectation in dynamic model file
   void setVarExpectationIndices(map<string, pair<SymbolList, int> > var_model_info);
@@ -569,12 +572,6 @@ public:
   bool isChecksumMatching(const string &basename) const;
 };
 
-inline bool
-DynamicModel::checkHessianZero() const
-{
-  return second_derivatives.empty();
-}
-
 //! Classes to re-order derivatives for various sparse storage formats
 class derivative
 {
diff --git a/DynareBison.yy b/DynareBison.yy
index 821e97f2b0eee440fbfe71f9dd7a0f90356107ac..f492d6753c2abbd1bbf370a949aac3e6083ac495 100644
--- a/DynareBison.yy
+++ b/DynareBison.yy
@@ -2789,6 +2789,7 @@ dynare_sensitivity_option : o_gsa_identification
                           | o_ar
                           | o_kalman_algo
                           | o_lik_init
+                          | o_diffuse_filter
                           | o_analytic_derivation
                           | o_analytic_derivation_mode
                           ;
@@ -3360,16 +3361,16 @@ o_psd_fig_name : FIG_NAME EQUAL filename { driver.option_str("plot_shock_decomp.
 o_psd_type : TYPE EQUAL QOQ
              { driver.option_str("plot_shock_decomp.type", "qoq"); }
            | TYPE EQUAL YOY
-             { driver.option_str("plot_shock_decomp.type", "qoq"); }
+             { driver.option_str("plot_shock_decomp.type", "yoy"); }
            | TYPE EQUAL AOA
-             { driver.option_str("plot_shock_decomp.type", "qoq"); }
+             { driver.option_str("plot_shock_decomp.type", "aoa"); }
            ;
 o_icd_type : TYPE EQUAL QOQ
              { driver.option_str("initial_condition_decomp.type", "qoq"); }
            | TYPE EQUAL YOY
-             { driver.option_str("initial_condition_decomp.type", "qoq"); }
+             { driver.option_str("initial_condition_decomp.type", "yoy"); }
            | TYPE EQUAL AOA
-             { driver.option_str("initial_condition_decomp.type", "qoq"); }
+             { driver.option_str("initial_condition_decomp.type", "aoa"); }
            ;
 o_icd_plot_init_date : PLOT_INIT_DATE EQUAL date_expr { driver.option_date("initial_condition_decomp.plot_init_date", $3); } ;
 o_icd_plot_end_date : PLOT_END_DATE EQUAL date_expr { driver.option_date("initial_condition_decomp.plot_end_date", $3); } ;
diff --git a/DynareMain.cc b/DynareMain.cc
index eb2891a6e30235df2d17a4e08e2714511a84033c..16183842c4dffd9254209fde69c7ee57b2e292e7 100644
--- a/DynareMain.cc
+++ b/DynareMain.cc
@@ -50,12 +50,12 @@ void main2(stringstream &in, string &basename, bool debug, bool clear_all, bool
            );
 
 void main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
-           bool no_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output);
+           bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output);
 
 void
 usage()
 {
-  cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [notmpterms] [nolog] [warn_uninit]"
+  cerr << "Dynare usage: dynare mod_file [debug] [noclearall] [onlyclearglobals] [savemacro[=macro_file]] [onlymacro] [nolinemacro] [noemptylinemacro] [notmpterms] [nolog] [warn_uninit]"
        << " [console] [nograph] [nointeractive] [parallel[=cluster_name]] [conffile=parallel_config_path_and_filename] [parallel_slave_open_mode] [parallel_test]"
        << " [-D<variable>[=<value>]] [-I/path] [nostrict] [stochastic] [fast] [minimal_workspace] [compute_xrefs] [output=dynamic|first|second|third] [language=C|C++|julia]"
        << " [params_derivs_order=0|1|2]"
@@ -91,6 +91,7 @@ main(int argc, char **argv)
   bool no_tmp_terms = false;
   bool only_macro = false;
   bool no_line_macro = false;
+  bool no_empty_line_macro = false;
   bool no_log = false;
   bool no_warn = false;
   int params_derivs_order = 2;
@@ -162,6 +163,8 @@ main(int argc, char **argv)
         }
       else if (!strcmp(argv[arg], "nolinemacro"))
         no_line_macro = true;
+      else if (!strcmp(argv[arg], "noemptylinemacro"))
+        no_empty_line_macro = true;
       else if (!strcmp(argv[arg], "notmpterms"))
         no_tmp_terms = true;
       else if (!strcmp(argv[arg], "nolog"))
@@ -389,7 +392,8 @@ main(int argc, char **argv)
 
   // Do macro processing
   stringstream macro_output;
-  main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, defines, path, macro_output);
+  main1(modfile, basename, modfiletxt, debug, save_macro, save_macro_file, no_line_macro, no_empty_line_macro,
+        defines, path, macro_output);
 
   if (only_macro)
     return EXIT_SUCCESS;
diff --git a/DynareMain1.cc b/DynareMain1.cc
index fe87ba83b4cf0c60aae726883dbc991b7af6e759..c801fd86d8c9b840675e34e863bb49175b681c3a 100644
--- a/DynareMain1.cc
+++ b/DynareMain1.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Dynare Team
+ * Copyright (C) 2015-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -22,14 +22,18 @@
 
 #include "macro/MacroDriver.hh"
 
+bool compareNewline (int i, int j) {
+  return i == '\n' && j == '\n';
+}
+
 void
 main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool save_macro, string &save_macro_file,
-      bool no_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output)
+      bool no_line_macro, bool no_empty_line_macro, map<string, string> &defines, vector<string> &path, stringstream &macro_output)
 {
   // Do macro processing
   MacroDriver m;
 
-  m.parse(modfile, modfiletxt, macro_output, debug, no_line_macro, defines, path);
+  m.parse(modfile, basename, modfiletxt, macro_output, debug, no_line_macro, defines, path);
   if (save_macro)
     {
       if (save_macro_file.empty())
@@ -40,7 +44,11 @@ main1(string &modfile, string &basename, string &modfiletxt, bool debug, bool sa
           cerr << "Cannot open " << save_macro_file << " for macro output" << endl;
           exit(EXIT_FAILURE);
         }
-      macro_output_file << macro_output.str();
+
+      string str (macro_output.str());
+      if (no_empty_line_macro)
+        str.erase(unique(str.begin(), str.end(), compareNewline), str.end());
+      macro_output_file << str;
       macro_output_file.close();
     }
 }
diff --git a/ModFile.cc b/ModFile.cc
index f83604258fa9e119ec128b9a1a51c6890455e0f5..1de813fcde3c47fc60359e16bfad9dd21930651c 100644
--- a/ModFile.cc
+++ b/ModFile.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2017 Dynare Team
+ * Copyright (C) 2006-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -615,15 +615,14 @@ ModFile::computingPass(bool no_tmp_terms, FileOutputType output, int params_deri
       else // No computing task requested, compute derivatives up to 2nd order by default
         dynamic_model.computingPass(true, true, false, none, global_eval_context, no_tmp_terms, block, use_dll, byte_code, nopreprocessoroutput);
 
-      if ((linear && !mod_file_struct.ramsey_model_present && !dynamic_model.checkHessianZero())
-          || (linear && mod_file_struct.ramsey_model_present && !orig_ramsey_dynamic_model.checkHessianZero()))
-        {
-          map<int, string> eqs;
-          if (mod_file_struct.ramsey_model_present)
-            orig_ramsey_dynamic_model.getNonZeroHessianEquations(eqs);
-          else
-            dynamic_model.getNonZeroHessianEquations(eqs);
+      map<int, string> eqs;
+      if (mod_file_struct.ramsey_model_present)
+        orig_ramsey_dynamic_model.setNonZeroHessianEquations(eqs);
+      else
+        dynamic_model.setNonZeroHessianEquations(eqs);
 
+      if (linear && !eqs.empty())
+        {
           cerr << "ERROR: If the model is declared linear the second derivatives must be equal to zero." << endl
                << "       The following equations had non-zero second derivatives:" << endl;
           for (map<int, string >::const_iterator it = eqs.begin(); it != eqs.end(); it++)
@@ -770,7 +769,13 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo
       mOutputFile << "};" << endl;
     }
 
-  mOutputFile << "M_.hessian_eq_zero = " << dynamic_model.checkHessianZero() << ";" << endl;
+  mOutputFile << "M_.nonzero_hessian_eqs = ";
+  if (mod_file_struct.ramsey_model_present)
+    orig_ramsey_dynamic_model.printNonZeroHessianEquations(mOutputFile);
+  else
+    dynamic_model.printNonZeroHessianEquations(mOutputFile);
+  mOutputFile << ";" << endl
+              << "M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs);" << endl;
 
   config_file.writeCluster(mOutputFile);
 
diff --git a/ModelTree.cc b/ModelTree.cc
index cb3523a627c1c7070b6cccced67a765aa47d1108..aea4f6b70b824b38563e37f82ebcfc74b267613a 100644
--- a/ModelTree.cc
+++ b/ModelTree.cc
@@ -1453,35 +1453,31 @@ ModelTree::writeJsonModelLocalVariables(ostream &output, deriv_node_temp_terms_t
   for (size_t i = 0; i < equations.size(); i++)
     equations[i]->collectVariables(eModelLocalVariable, used_local_vars);
 
-  output << "\"external_functions_model_local_variables\": [";
-  for (set<int>::const_iterator it = used_local_vars.begin();
-       it != used_local_vars.end(); ++it)
-    {
-      vector<string> efout;
-      expr_t value = local_variables_table.find(*it)->second;
-      value->writeJsonExternalFunctionOutput(efout, tt, tef_terms);
-      for (vector<string>::const_iterator it1 = efout.begin(); it1 != efout.end(); it1++)
-        {
-          if (it1 != efout.begin())
-            output << ", ";
-          output << *it1;
-        }
-    }
-  output << "]"
-         << ", \"model_local_variables\": [";
+  output << "\"model_local_variables\": [";
   bool printed = false;
   for (vector<int>::const_iterator it = local_variables_vector.begin();
        it != local_variables_vector.end(); it++)
     if (used_local_vars.find(*it) != used_local_vars.end())
       {
-        int id = *it;
-        expr_t value = local_variables_table.find(id)->second;
-
         if (printed)
           output << ", ";
         else
           printed = true;
 
+        int id = *it;
+        vector<string> efout;
+        expr_t value = local_variables_table.find(id)->second;
+        value->writeJsonExternalFunctionOutput(efout, tt, tef_terms);
+        for (vector<string>::const_iterator it1 = efout.begin(); it1 != efout.end(); it1++)
+          {
+            if (it1 != efout.begin())
+              output << ", ";
+            output << *it1;
+          }
+
+        if (!efout.empty())
+          output << ", ";
+
         /* We append underscores to avoid name clashes with "g1" or "oo_" (see
            also VariableNode::writeOutput) */
         output << "{\"variable\": \"" << symbol_table.getName(id) << "__\""
diff --git a/ParsingDriver.cc b/ParsingDriver.cc
index 5d2639f009c403732fd024944f4b6f55cb2d7706..b9e2a9b10ba2cc76b3bb178d367490dfd7492679 100644
--- a/ParsingDriver.cc
+++ b/ParsingDriver.cc
@@ -2580,8 +2580,7 @@ ParsingDriver::add_divide(expr_t arg1, expr_t arg2)
     }
   catch (DataTree::DivisionByZeroException)
     {
-      cerr << "...division by zero error encountred when reading model from .mod file" << endl;
-      exit(EXIT_FAILURE);
+      error("Division by zero error encountered when reading model from .mod file");
     }
 }
 
diff --git a/SymbolList.cc b/SymbolList.cc
index 6e5251f1a2cee0e59bc0512c32246c107ee15efe..d6a16562c78c8e8caf10d44656380e81ce26298b 100644
--- a/SymbolList.cc
+++ b/SymbolList.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2017 Dynare Team
+ * Copyright (C) 2003-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -28,35 +28,15 @@ SymbolList::addSymbol(const string &symbol)
 void
 SymbolList::writeOutput(const string &varname, ostream &output) const
 {
-  output << varname << " = ";
-  write(output);
-  output << ";" << endl;
-}
-
-void
-SymbolList::write(ostream &output) const
-{
-  output << " char(";
+  output << varname << " = {";
   for (vector<string>::const_iterator it = symbols.begin();
        it != symbols.end(); ++it)
     {
       if (it != symbols.begin())
-        output << ",";
+        output << ";";
       output << "'" << *it << "'";
     }
-  output << ")";
-}
-
-int
-SymbolList::getSize() const
-{
-  return symbols.size();
-}
-
-vector<string>
-SymbolList::getSymbols() const
-{
-  return symbols;
+  output << "};" << endl;
 }
 
 void
@@ -78,3 +58,15 @@ SymbolList::clear()
 {
   symbols.clear();
 }
+
+int
+SymbolList::getSize() const
+{
+  return symbols.size();
+}
+
+vector<string>
+SymbolList::getSymbols() const
+{
+  return symbols;
+}
diff --git a/SymbolTable.cc b/SymbolTable.cc
index f1409587cd79f531875eb49b8178c66b255ee012..dde3d141bc047ed7d1202920b61538721ab0cd92 100644
--- a/SymbolTable.cc
+++ b/SymbolTable.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2017 Dynare Team
+ * Copyright (C) 2003-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -219,14 +219,13 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
 
   if (exo_nbr() > 0)
     {
-      output << "M_.exo_names = '" << getName(exo_ids[0]) << "';" << endl;
-      output << "M_.exo_names_tex = '" << getTeXName(exo_ids[0]) << "';" << endl;
-      output << "M_.exo_names_long = '" << getLongName(exo_ids[0]) << "';" << endl;
-      for (int id = 1; id < exo_nbr(); id++)
-        output << "M_.exo_names = char(M_.exo_names, '" << getName(exo_ids[id]) << "');" << endl
-               << "M_.exo_names_tex = char(M_.exo_names_tex, '" << getTeXName(exo_ids[id]) << "');" << endl
-               << "M_.exo_names_long = char(M_.exo_names_long, '" << getLongName(exo_ids[id]) << "');" << endl;
-
+      output << "M_.exo_names = cell(" << exo_nbr() << ",1);" << endl;
+      output << "M_.exo_names_tex = cell(" << exo_nbr() << ",1);" << endl;
+      output << "M_.exo_names_long = cell(" << exo_nbr() << ",1);" << endl;
+      for (int id = 0; id < exo_nbr(); id++)
+        output << "M_.exo_names(" << id+1 << ") = {'" << getName(exo_ids[id]) << "'};" << endl
+               << "M_.exo_names_tex(" << id+1 << ") = {'" << getTeXName(exo_ids[id]) << "'};" << endl
+               << "M_.exo_names_long(" << id+1 << ") = {'" << getLongName(exo_ids[id]) << "'};" << endl;
       map<string, map<int, string> > partitions = getPartitionsForType(eExogenous);
       for (map<string, map<int, string> >::const_iterator it = partitions.begin();
            it != partitions.end(); it++)
@@ -248,14 +247,13 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
 
   if (exo_det_nbr() > 0)
     {
-      output << "M_.exo_det_names = '" << getName(exo_det_ids[0]) << "';" << endl;
-      output << "M_.exo_det_names_tex = '" << getTeXName(exo_det_ids[0]) << "';" << endl;
-      output << "M_.exo_det_names_long = '" << getLongName(exo_det_ids[0]) << "';" << endl;
-      for (int id = 1; id < exo_det_nbr(); id++)
-        output << "M_.exo_det_names = char(M_.exo_det_names, '" << getName(exo_det_ids[id]) << "');" << endl
-               << "M_.exo_det_names_tex = char(M_.exo_det_names_tex, '" << getTeXName(exo_det_ids[id]) << "');" << endl
-               << "M_.exo_det_names_long = char(M_.exo_det_names_long, '" << getLongName(exo_det_ids[id]) << "');" << endl;
-
+      output << "M_.exo_det_names = cell(" << exo_det_nbr() << ",1);" << endl;
+      output << "M_.exo_det_names_tex = cell(" << exo_det_nbr() << ",1);" << endl;
+      output << "M_.exo_det_names_long = cell(" << exo_det_nbr() << ",1);" << endl;
+      for (int id = 0; id < exo_det_nbr(); id++)
+        output << "M_.exo_det_names(" << id+1 << ") = {'" << getName(exo_det_ids[id]) << "'};" << endl
+               << "M_.exo_det_names_tex(" << id+1 << ") = {'" << getTeXName(exo_det_ids[id]) << "'};" << endl
+               << "M_.exo_det_names_long(" << id+1 << ") = {'" << getLongName(exo_det_ids[id]) << "'};" << endl;
       output << "M_.exo_det_partitions = struct();" << endl;
       map<string, map<int, string> > partitions = getPartitionsForType(eExogenousDet);
       for (map<string, map<int, string> >::const_iterator it = partitions.begin();
@@ -278,14 +276,13 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
 
   if (endo_nbr() > 0)
     {
-      output << "M_.endo_names = '" << getName(endo_ids[0]) << "';" << endl;
-      output << "M_.endo_names_tex = '" << getTeXName(endo_ids[0]) << "';" << endl;
-      output << "M_.endo_names_long = '" << getLongName(endo_ids[0]) << "';" << endl;
-      for (int id = 1; id < endo_nbr(); id++)
-        output << "M_.endo_names = char(M_.endo_names, '" << getName(endo_ids[id]) << "');" << endl
-               << "M_.endo_names_tex = char(M_.endo_names_tex, '" << getTeXName(endo_ids[id]) << "');" << endl
-               << "M_.endo_names_long = char(M_.endo_names_long, '" << getLongName(endo_ids[id]) << "');" << endl;
-
+      output << "M_.endo_names = cell(" << endo_nbr() << ",1);" << endl;
+      output << "M_.endo_names_tex = cell(" << endo_nbr() << ",1);" << endl;
+      output << "M_.endo_names_long = cell(" << endo_nbr() << ",1);" << endl;
+      for (int id = 0; id < endo_nbr(); id++)
+        output << "M_.endo_names(" << id+1 << ") = {'" << getName(endo_ids[id]) << "'};" << endl
+               << "M_.endo_names_tex(" << id+1 << ") = {'" << getTeXName(endo_ids[id]) << "'};" << endl
+               << "M_.endo_names_long(" << id+1 << ") = {'" << getLongName(endo_ids[id]) << "'};" << endl;
       output << "M_.endo_partitions = struct();" << endl;
       map<string, map<int, string> > partitions = getPartitionsForType(eEndogenous);
       for (map<string, map<int, string> >::const_iterator it = partitions.begin();
@@ -308,19 +305,17 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
 
   if (param_nbr() > 0)
     {
-      output << "M_.param_names = '" << getName(param_ids[0]) << "';" << endl;
-      output << "M_.param_names_tex = '" << getTeXName(param_ids[0]) << "';" << endl;
-      output << "M_.param_names_long = '" << getLongName(param_ids[0]) << "';" << endl;
-      for (int id = 1; id < param_nbr(); id++)
+      output << "M_.param_names = cell(" << param_nbr() << ",1);" << endl;
+      output << "M_.param_names_tex = cell(" << param_nbr() << ",1);" << endl;
+      output << "M_.param_names_long = cell(" << param_nbr() << ",1);" << endl;
+      for (int id = 0; id < param_nbr(); id++)
         {
-          output << "M_.param_names = char(M_.param_names, '" << getName(param_ids[id]) << "');" << endl
-                 << "M_.param_names_tex = char(M_.param_names_tex, '" << getTeXName(param_ids[id]) << "');" << endl
-                 << "M_.param_names_long = char(M_.param_names_long, '" << getLongName(param_ids[id]) << "');" << endl;
-
+          output << "M_.param_names(" << id+1 << ") = {'" << getName(param_ids[id]) << "'};" << endl
+                 << "M_.param_names_tex(" << id+1 << ") = {'" << getTeXName(param_ids[id]) << "'};" << endl
+                 << "M_.param_names_long(" << id+1 << ") = {'" << getLongName(param_ids[id]) << "'};" << endl;
           if (getName(param_ids[id]) == "dsge_prior_weight")
             output << "options_.dsge_var = 1;" << endl;
         }
-
       output << "M_.param_partitions = struct();" << endl;
       map<string, map<int, string> > partitions = getPartitionsForType(eParameter);
       for (map<string, map<int, string> >::const_iterator it = partitions.begin();
@@ -394,7 +389,7 @@ SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
   if (observedVariablesNbr() > 0)
     {
       int ic = 1;
-      output << "options_.varobs = cell(1);" << endl;
+      output << "options_.varobs = cell(" << observedVariablesNbr() << ", 1);" << endl;
       for (vector<int>::const_iterator it = varobs.begin();
            it != varobs.end(); it++, ic++)
         output << "options_.varobs(" << ic << ")  = {'" << getName(*it) << "'};" << endl;
diff --git a/macro/MacroBison.yy b/macro/MacroBison.yy
index 27c0e4b28c11dc61735eee686730545d698b054e..a2523356c9b7c482b6f5a10ed9422a28e10efc4f 100644
--- a/macro/MacroBison.yy
+++ b/macro/MacroBison.yy
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2016 Dynare Team
+ * Copyright (C) 2008-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -74,7 +74,7 @@ class MacroDriver;
 }
 
 %token DEFINE LINE FOR IN IF ELSE ENDIF ECHO_DIR ERROR IFDEF IFNDEF
-%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH
+%token LPAREN RPAREN LBRACKET RBRACKET EQUAL EOL LENGTH ECHOMACROVARS SAVE
 
 %token <int_val> INTEGER
 %token <string_val> NAME STRING
@@ -121,6 +121,10 @@ statement : expr
             { TYPERR_CATCH(driver.error(@$, $2), @$); }
           | LINE STRING INTEGER
             /* Ignore @#line declarations */
+          | ECHOMACROVARS
+            { driver.printvars(@$, true); }
+          | ECHOMACROVARS LPAREN SAVE RPAREN
+            { out << driver.printvars(@$, false); }
           ;
 
 expr : INTEGER
diff --git a/macro/MacroDriver.cc b/macro/MacroDriver.cc
index 4d2399ec0ba91f9a300ecd708c45839305dc54d4..bd15152b366c5830305a6035d95308bb256940ae 100644
--- a/macro/MacroDriver.cc
+++ b/macro/MacroDriver.cc
@@ -37,10 +37,13 @@ MacroDriver::~MacroDriver()
 }
 
 void
-MacroDriver::parse(const string &f, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro,
-                   map<string, string> defines, vector<string> path)
+MacroDriver::parse(const string &f, const string &fb, const string &modfiletxt,
+                   ostream &out, bool debug, bool no_line_macro_arg, map<string, string> defines,
+                   vector<string> path)
 {
   file = f;
+  basename = fb;
+  no_line_macro = no_line_macro_arg;
 
   /*
     Copy the file into a stringstream, and add an extra end-of-line. This is a
@@ -205,3 +208,27 @@ MacroDriver::error(const Macro::parser::location_type &l, const MacroValue *valu
 
   error(l, sval->value);
 }
+
+string
+MacroDriver::printvars(const Macro::parser::location_type &l, const bool tostdout) const
+{
+  if (tostdout)
+    {
+      cout << "Macroprocessor: Printing macro variable values from " << file
+           << " at line " << l.begin.line << endl;
+      for (map<string, const MacroValue *>::const_iterator it = env.begin();
+           it != env.end(); it++)
+        cout << "    " << it->first << " = " << it->second->print() << endl;
+      cout << endl;
+      return "";
+    }
+
+  stringstream intomfile;
+  if (!no_line_macro)
+    intomfile << "@#line \"" << file << "\" " << l.begin.line << endl;
+
+  for (map<string, const MacroValue *>::const_iterator it = env.begin();
+       it != env.end(); it++)
+    intomfile<< "options_.macrovars_line_" << l.begin.line << "." << it->first << " = " << it->second->print() << ";" << endl;
+  return intomfile.str();
+}
diff --git a/macro/MacroDriver.hh b/macro/MacroDriver.hh
index c76947de228faadaac514920e6796e93a4069b33..53b1271d8193131a04c9ff261d0dde463ce2a171 100644
--- a/macro/MacroDriver.hh
+++ b/macro/MacroDriver.hh
@@ -182,12 +182,18 @@ public:
 
   //! Starts parsing a file, returns output in out
   /*! \param no_line_macro should we omit the @#line statements ? */
-  void parse(const string &f, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro,
+  void parse(const string &f, const string &fb, const string &modfiletxt, ostream &out, bool debug, bool no_line_macro_arg,
              map<string, string> defines, vector<string> path);
 
   //! Name of main file being parsed
   string file;
 
+  //! Basename of main file being parsed
+  string basename;
+
+  //! Whether or not to print @#line
+  bool no_line_macro;
+
   //! Reference to the lexer
   class MacroFlex *lexer;
 
@@ -197,6 +203,9 @@ public:
   //! Error handler
   void error(const Macro::parser::location_type &l, const string &m) const;
 
+  //! Print variables
+  string printvars(const Macro::parser::location_type &l, const bool save) const;
+
   //! Set a variable
   void set_variable(const string &name, const MacroValue *value);
 
diff --git a/macro/MacroFlex.ll b/macro/MacroFlex.ll
index 9c9bc66f79bc73b4f9df8d7d439ceb13a1dfa29c..5125ffa73906f12668b492ffd99f9b3915f41a72 100644
--- a/macro/MacroFlex.ll
+++ b/macro/MacroFlex.ll
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2016 Dynare Team
+ * Copyright (C) 2008-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -236,6 +236,9 @@ CONT \\\\
 <STMT>line                  { return token::LINE; }
 <STMT>define                { return token::DEFINE; }
 
+<STMT>echomacrovars         { return token::ECHOMACROVARS; }
+<STMT>save                  { return token::SAVE; }
+
 <STMT>for                   { reading_for_statement = true; return token::FOR; }
 <STMT>endfor                { driver.error(*yylloc, "@#endfor is not matched by a @#for statement"); }
 
diff --git a/macro/MacroValue.cc b/macro/MacroValue.cc
index b20beb5db8d00392f2a8192a17fd2f76c7b48af7..db8c8ac293979ecf87a9fdf16c3a4c8d680106d0 100644
--- a/macro/MacroValue.cc
+++ b/macro/MacroValue.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2014 Dynare Team
+ * Copyright (C) 2008-2017 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -280,6 +280,12 @@ IntMV::toString() const
   return ss.str();
 }
 
+string
+IntMV::print() const
+{
+  return toString();
+}
+
 const MacroValue *
 IntMV::toArray() const
 {
@@ -398,6 +404,12 @@ StringMV::toString() const
   return value;
 }
 
+string
+StringMV::print() const
+{
+  return "'" + value + "'";
+}
+
 const MacroValue *
 StringMV::toArray() const
 {
diff --git a/macro/MacroValue.hh b/macro/MacroValue.hh
index 1097841d9831f9e0c37b5c5e116c6bce691dfbe9..ced2918958ae30939f4514d81fe1666f401e05b1 100644
--- a/macro/MacroValue.hh
+++ b/macro/MacroValue.hh
@@ -23,6 +23,7 @@
 #include <string>
 #include <vector>
 #include <sstream>
+#include <boost/lexical_cast.hpp>
 
 using namespace std;
 
@@ -91,6 +92,8 @@ public:
   virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
   //! Converts value to string
   virtual string toString() const = 0;
+  //! Converts value to be printed
+  virtual string print() const = 0;
   //! Converts value to array form
   virtual const MacroValue *toArray() const = 0;
   //! Gets length
@@ -147,6 +150,7 @@ public:
   //! Computes logical negation
   virtual const MacroValue *operator!() const throw (TypeError);
   virtual string toString() const;
+  virtual string print() const;
   //! Converts value to array form
   /*! Returns an integer array containing a single value */
   virtual const MacroValue *toArray() const;
@@ -187,6 +191,7 @@ public:
   virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
   //! Returns underlying string value
   virtual string toString() const;
+  virtual string print() const;
   //! Converts value to array form
   /*! Returns a string array containing a single value */
   virtual const MacroValue *toArray() const;
@@ -226,6 +231,7 @@ public:
   virtual const MacroValue *operator[](const MacroValue &mv) const throw (TypeError, OutOfBoundsError);
   //! Returns a string containing the concatenation of string representations of elements
   virtual string toString() const;
+  virtual string print() const;
   //! Returns itself
   virtual const MacroValue *toArray() const;
   //! Gets length
@@ -335,6 +341,43 @@ ArrayMV<T>::toString() const
   return ss.str();
 }
 
+template<typename T>
+string
+ArrayMV<T>::print() const
+{
+  bool printStrArr = false;
+  try
+    {
+      typename vector<T>::const_iterator it = values.begin();
+      boost::lexical_cast<int>(*it);
+    }
+  catch (boost::bad_lexical_cast &)
+    {
+      printStrArr= true;
+    }
+  ostringstream ss;
+  if (printStrArr)
+    ss << "{";
+  else
+    ss << "[";
+  for (typename vector<T>::const_iterator it = values.begin();
+       it != values.end(); it++)
+    {
+      if (it != values.begin())
+        ss << ", ";
+
+      if (printStrArr)
+        ss << "'" << *it << "'";
+      else
+        ss << *it;
+    }
+  if (printStrArr)
+    ss << "}";
+  else
+    ss << "]";
+  return ss.str();
+}
+
 template<typename T>
 const MacroValue *
 ArrayMV<T>::toArray() const