diff --git a/src/macro/Directives.cc b/src/macro/Directives.cc
index 0e84b715436e55381b9666e0947a16c914eeedf8..daa781e8f09f80c2b77e4bbcd3b1e889221a22f8 100644
--- a/src/macro/Directives.cc
+++ b/src/macro/Directives.cc
@@ -120,7 +120,7 @@ Echo::interpret(ostream &output, bool no_line_macro)
     {
       error(StackTrace("@#echo", e.what(), location));
     }
-  printLineInfo(output, no_line_macro);
+  printEndLineInfo(output, no_line_macro);
 }
 
 void
@@ -141,6 +141,16 @@ Error::interpret(ostream &output, bool no_line_macro)
     }
 }
 
+void
+EchoMacroVars::interpret(ostream &output, bool no_line_macro)
+{
+  if (save)
+    env.print(output, location.begin.line, true);
+  else
+    env.print(cout);
+  printEndLineInfo(output, no_line_macro);
+}
+
 void
 For::interpret(ostream &output, bool no_line_macro)
 {
diff --git a/src/macro/Directives.hh b/src/macro/Directives.hh
index f8220c9b55867cf9170ea21329a87fcd5cf0a981..314f33622cfbe02de7efd54cc5539b28429b55b0 100644
--- a/src/macro/Directives.hh
+++ b/src/macro/Directives.hh
@@ -137,9 +137,13 @@ namespace macro
 
   class EchoMacroVars : public Directive
   {
+  private:
+    bool save;
   public:
-    EchoMacroVars(Environment &env_arg, const Tokenizer::location location_arg) : Directive(env_arg, move(location_arg)) { }
-    inline void interpret(ostream &output, bool no_line_macro) override { env.print(); }
+    EchoMacroVars(bool save_arg,
+                  Environment &env_arg, const Tokenizer::location location_arg) :
+      Directive(env_arg, move(location_arg)), save{save_arg} { }
+    void interpret(ostream &output, bool no_line_macro) override;
   };
 
 
diff --git a/src/macro/Environment.cc b/src/macro/Environment.cc
index be12f98807ea561ea4acd189eb302988f005da22..03206a2bf6dda8975e81811d9d2c9f60ab281e47 100644
--- a/src/macro/Environment.cc
+++ b/src/macro/Environment.cc
@@ -101,32 +101,42 @@ Environment::isFunctionDefined(const string &name) const noexcept
 }
 
 void
-Environment::print() const
+Environment::print(ostream &output, int line, bool save) const
 {
-  if (!variables.empty())
+  if (!save && !variables.empty())
+    output << "Macro Variables:" << endl;
+
+  for (auto & it : variables)
     {
-      cout << "Macro Variables:" << endl;
-      for (auto & it : variables)
-        {
-          cout << "  " << it.first << " = ";
-          getVariable(it.first)->eval()->print(cout);
-          cout << endl;
-        }
+      output << (save ? "options_.macrovars_line_" + to_string(line) + "." : "  " );
+      output << it.first << " = ";
+      getVariable(it.first)->eval()->print(output, true);
+      if (save)
+        output << ";";
+      output << endl;
     }
 
-  if (!functions.empty())
+  if (!save && !functions.empty())
+    output << "Macro Functions:" << endl;
+
+  for (auto & it : functions)
     {
-      cout << "Macro Functions:" << endl;
-      for (auto & it : functions)
+      output << (save ? "options_.macrovars_line_" + to_string(line) + ".function." : "  " );
+      if (save)
         {
-          cout << "  ";
-          get<0>(it.second)->print(cout);
-          cout << " = ";
-          get<1>(it.second)->print(cout);
-          cout << endl;
+          get<0>(it.second)->printName(output);
+          output << " = '";
         }
+
+      get<0>(it.second)->print(output);
+      output << " = ";
+      get<1>(it.second)->print(output);
+
+      if (save)
+        output << "';";
+      output << endl;
     }
 
   if (parent)
-    parent->print();
+    parent->print(output, line, save);
 }
diff --git a/src/macro/Environment.hh b/src/macro/Environment.hh
index 52e8ae4837bc45e52ee796de38ca97aa38ecebc2..78e34c8c3e44d7b1c556dd3fee8613954cd16dfa 100644
--- a/src/macro/Environment.hh
+++ b/src/macro/Environment.hh
@@ -46,7 +46,7 @@ namespace macro
     bool isVariableDefined(const string &name) const noexcept;
     bool isFunctionDefined(const string &name) const noexcept;
     inline bool isSymbolDefined(const string &name) const noexcept { return isVariableDefined(name) || isFunctionDefined(name); }
-    void print() const;
+    void print(ostream &output, int line = -1, bool save = false) const;
     inline size_t size() const noexcept { return variables.size() + functions.size(); }
     inline const Environment *getGlobalEnv() const noexcept { return parent == nullptr ? this : parent->getGlobalEnv(); }
   };
diff --git a/src/macro/Expressions.cc b/src/macro/Expressions.cc
index 9ad085facd5ed8915007168bededb0d4290721a6..c0cc4c4386499b53c6cb806428623d01fd57a8f0 100644
--- a/src/macro/Expressions.cc
+++ b/src/macro/Expressions.cc
@@ -1094,35 +1094,43 @@ Comprehension::to_string() const noexcept
 }
 
 void
-Array::print(ostream &output) const noexcept
+String::print(ostream &output, bool matlab_output) const noexcept
 {
-  output << "[";
+  output << (matlab_output ? "'" : R"(")");
+  output << value;
+  output << (matlab_output ? "'" : R"(")");
+}
+
+void
+Array::print(ostream &output, bool matlab_output) const noexcept
+{
+output << (matlab_output ? "{" : "[");
   for (auto it = arr.begin(); it != arr.end(); it++)
     {
       if (it != arr.begin())
         output << ", ";
-      (*it)->print(output);
+      (*it)->print(output, matlab_output);
     }
-  output << "]";
+  output << (matlab_output ? "}" : "]");
 }
 
 void
-Tuple::print(ostream &output) const noexcept
+Tuple::print(ostream &output, bool matlab_output) const noexcept
 {
-  output << "(";
+  output << (matlab_output ? "{" : "(");
   for (auto it = tup.begin(); it != tup.end(); it++)
     {
       if (it != tup.begin())
         output << ", ";
-      (*it)->print(output);
+      (*it)->print(output, matlab_output);
     }
-  output << ")";
+  output << (matlab_output ? "}" : ")");
 }
 
 void
-Function::print(ostream &output) const noexcept
+Function::printArgs(ostream &output) const noexcept
 {
-  output << name << "(";
+  output << "(";
   for (auto it = args.begin(); it != args.end(); it++)
     {
       if (it != args.begin())
@@ -1133,7 +1141,7 @@ Function::print(ostream &output) const noexcept
 }
 
 void
-UnaryOp::print(ostream &output) const noexcept
+UnaryOp::print(ostream &output, bool matlab_output) const noexcept
 {
   switch (op_code)
     {
@@ -1220,7 +1228,7 @@ UnaryOp::print(ostream &output) const noexcept
       break;
     }
 
-  arg->print(output);
+  arg->print(output, matlab_output);
 
   if (op_code != codes::UnaryOp::logical_not
       && op_code != codes::UnaryOp::unary_plus
@@ -1229,7 +1237,7 @@ UnaryOp::print(ostream &output) const noexcept
 }
 
 void
-BinaryOp::print(ostream &output) const noexcept
+BinaryOp::print(ostream &output, bool matlab_output) const noexcept
 {
   if (op_code == codes::BinaryOp::set_union
       || op_code == codes::BinaryOp::set_intersection
@@ -1257,14 +1265,14 @@ BinaryOp::print(ostream &output) const noexcept
         default:
           break;
         }
-      arg1->print(output);
+      arg1->print(output, matlab_output);
       output << ", ";
-      arg2->print(output);
+      arg2->print(output, matlab_output);
       output << ")";
       return;
     }
 
-  arg1->print(output);
+  arg1->print(output, matlab_output);
   switch(op_code)
     {
     case codes::BinaryOp::plus:
@@ -1317,11 +1325,11 @@ BinaryOp::print(ostream &output) const noexcept
       cerr << "macro::BinaryOp::print: Should not arrive here" << endl;
       exit(EXIT_FAILURE);
     }
-  arg2->print(output);
+  arg2->print(output, matlab_output);
 }
 
 void
-TrinaryOp::print(ostream &output) const noexcept
+TrinaryOp::print(ostream &output, bool matlab_output) const noexcept
 {
   switch(op_code)
     {
@@ -1332,23 +1340,23 @@ TrinaryOp::print(ostream &output) const noexcept
       output << "normcdf(";
       break;
     }
-  arg1->print(output);
+  arg1->print(output, matlab_output);
   output << ", ";
-  arg2->print(output);
+  arg2->print(output, matlab_output);
   output << ", ";
-  arg3->print(output);
+  arg3->print(output, matlab_output);
   output << ")";
 }
 
 void
-Comprehension::print(ostream &output) const noexcept
+Comprehension::print(ostream &output, bool matlab_output) const noexcept
 {
   output << "[";
-  c_vars->print(output);
+  c_vars->print(output, matlab_output);
   output << " in ";
-  c_set->print(output);
+  c_set->print(output, matlab_output);
   output << " when ";
-  c_when->print(output);
+  c_when->print(output, matlab_output);
   output << "]";
 }
 
diff --git a/src/macro/Expressions.hh b/src/macro/Expressions.hh
index 82e8539e4d9aeb1b280edec472149c59235ce97e..e3fcc2211c2d7fd3630852f9a73fac3ebc2d0d8d 100644
--- a/src/macro/Expressions.hh
+++ b/src/macro/Expressions.hh
@@ -114,7 +114,7 @@ namespace macro
     Expression(Environment &env_arg, const Tokenizer::location location_arg) :
       Node(env_arg, move(location_arg)) { }
     virtual string to_string() const noexcept = 0;
-    virtual void print(ostream &output) const noexcept = 0;
+    virtual void print(ostream &output, bool matlab_output = false) const noexcept = 0;
     virtual BaseTypePtr eval() = 0;
   };
 
@@ -193,7 +193,7 @@ namespace macro
       value{value_arg} { }
     inline codes::BaseType getType() const noexcept override { return codes::BaseType::Bool; }
     inline string to_string() const noexcept override { return value ? "true" : "false"; }
-    inline void print(ostream &output) const noexcept override { output << to_string(); }
+    inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << to_string(); }
   public:
     operator bool() const { return value; }
     BoolPtr is_equal(const BaseTypePtr &btp) const override;
@@ -225,7 +225,7 @@ namespace macro
       strs << setprecision(15) << value;
       return strs.str();
     }
-    inline void print(ostream &output) const noexcept override { output << to_string(); }
+    inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << to_string(); }
   public:
     operator double() const { return value; }
     BaseTypePtr plus(const BaseTypePtr &bt) const override;
@@ -287,7 +287,7 @@ namespace macro
       value{move(value_arg)} { }
     inline codes::BaseType getType() const noexcept override { return codes::BaseType::String; }
     inline string to_string() const noexcept override { return value; }
-    inline void print(ostream &output) const noexcept override { output << R"(")" << value << R"(")"; }
+    void print(ostream &output, bool matlab_output = false) const noexcept override;
   public:
     operator string() const { return value; }
     BaseTypePtr plus(const BaseTypePtr &bt) const override;
@@ -311,7 +311,7 @@ namespace macro
       tup{move(tup_arg)} { }
     inline codes::BaseType getType() const noexcept override { return codes::BaseType::Tuple; }
     string to_string() const noexcept override;
-    void print(ostream &output) const noexcept override;
+    void print(ostream &output, bool matlab_output = false) const noexcept override;
     BaseTypePtr eval() override;
   public:
     inline size_t size() const { return tup.size(); }
@@ -344,7 +344,7 @@ namespace macro
       range1{move(range1_arg)}, increment{move(increment_arg)}, range2{move(range2_arg)} { }
     inline codes::BaseType getType() const noexcept override { return codes::BaseType::Array; }
     string to_string() const noexcept override;
-    void print(ostream &output) const noexcept override;
+    void print(ostream &output, bool matlab_output = false) const noexcept override;
     BaseTypePtr eval() override;
   private:
     BaseTypePtr evalArray();
@@ -382,7 +382,7 @@ namespace macro
         indices = make_shared<Array>(vector<ExpressionPtr>{indices_arg}, env);
     }
     inline string to_string() const noexcept override { return name; }
-    inline void print(ostream &output) const noexcept override { output << name; }
+    inline void print(ostream &output, bool matlab_output = false) const noexcept override { output << name; }
     BaseTypePtr eval() override;
   public:
     inline string getName() const noexcept { return name; }
@@ -401,9 +401,11 @@ namespace macro
              Environment &env_arg, const Tokenizer::location location_arg) :
       Expression(env_arg, move(location_arg)), name{move(name_arg)}, args{move(args_arg)} { }
     string to_string() const noexcept override;
-    void print(ostream &output) const noexcept override;
+    inline void print(ostream &output, bool matlab_output = false) const noexcept override { printName(output); printArgs(output); }
     BaseTypePtr eval() override;
   public:
+    inline void printName(ostream &output) const noexcept { output << name; }
+    void printArgs(ostream &output) const noexcept;
     inline string getName() const { return name; }
     inline vector<ExpressionPtr> getArgs() const { return args; }
   };
@@ -420,7 +422,7 @@ namespace macro
             Environment &env_arg, const Tokenizer::location location_arg) :
       Expression(env_arg, move(location_arg)), op_code{move(op_code_arg)}, arg{move(arg_arg)} { }
     string to_string() const noexcept override;
-    void print(ostream &output) const noexcept override;
+    void print(ostream &output, bool matlab_output = false) const noexcept override;
     BaseTypePtr eval() override;
   };
 
@@ -438,7 +440,7 @@ namespace macro
       arg1{move(arg1_arg)}, arg2{move(arg2_arg)} { }
   public:
     string to_string() const noexcept override;
-    void print(ostream &output) const noexcept override;
+    void print(ostream &output, bool matlab_output = false) const noexcept override;
     BaseTypePtr eval() override;
   };
 
@@ -455,7 +457,7 @@ namespace macro
       Expression(env_arg, move(location_arg)), op_code{move(op_code_arg)},
       arg1{move(arg1_arg)}, arg2{move(arg2_arg)}, arg3{move(arg3_arg)} { }
     string to_string() const noexcept override;
-    void print(ostream &output) const noexcept override;
+    void print(ostream &output, bool matlab_output = false) const noexcept override;
     BaseTypePtr eval() override;
   };
 
@@ -472,7 +474,7 @@ namespace macro
       Expression(env_arg, move(location_arg)),
       c_vars{move(c_vars_arg)}, c_set{move(c_set_arg)}, c_when{move(c_when_arg)} { }
     string to_string() const noexcept override;
-    void print(ostream &output) const noexcept override;
+    void print(ostream &output, bool matlab_output = false) const noexcept override;
     BaseTypePtr eval() override;
   };
 }
diff --git a/src/macro/Parser.yy b/src/macro/Parser.yy
index 7045479557cbde8dba34a09e146e9b825c5f0068..e1d7f6d7f67370227325a138d8372753b76ffa33 100644
--- a/src/macro/Parser.yy
+++ b/src/macro/Parser.yy
@@ -64,7 +64,7 @@ using namespace macro;
 %token FOR ENDFOR IF IFDEF IFNDEF ELSE ENDIF TRUE FALSE
 %token INCLUDE INCLUDEPATH DEFINE EQUAL D_ECHO ERROR
 %token COMMA LPAREN RPAREN LBRACKET RBRACKET WHEN
-%token BEGIN_EVAL END_EVAL ECHOMACROVARS
+%token BEGIN_EVAL END_EVAL ECHOMACROVARS SAVE
 
 %token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN
 %token SQRT CBRT SIGN MAX MIN FLOOR CEIL TRUNC SUM MOD
@@ -137,7 +137,9 @@ directive_one_line : INCLUDE expr
                    | ERROR expr
                      { $$ = make_shared<Error>($2, driver.env, @$); }
                    | ECHOMACROVARS
-                     { $$ = make_shared<EchoMacroVars>(driver.env, @$); }
+                     { $$ = make_shared<EchoMacroVars>(false, driver.env, @$); }
+                   | ECHOMACROVARS LPAREN SAVE RPAREN
+                     { $$ = make_shared<EchoMacroVars>(true, driver.env, @$); }
                    ;
 
 directive_multiline : for
diff --git a/src/macro/Tokenizer.ll b/src/macro/Tokenizer.ll
index 938b9b674fe96b80cd2c878ebe412926f458e794..a1268a4a56faeadde1ce7b3caf052264275943e4 100644
--- a/src/macro/Tokenizer.ll
+++ b/src/macro/Tokenizer.ll
@@ -81,7 +81,7 @@ CONT \\\\{SPC}*
 <directive>endif           { BEGIN(end_line); return token::ENDIF; }
 <directive>for             { BEGIN(expr); return token::FOR; }
 <directive>endfor          { BEGIN(end_line); return token::ENDFOR; }
-<directive>echomacrovars   { BEGIN(end_line); return token::ECHOMACROVARS; }
+<directive>echomacrovars   { BEGIN(expr); return token::ECHOMACROVARS; }
 
 <expr,eval>\+              { return token::PLUS; }
 <expr,eval>-               { return token::MINUS; }
@@ -112,6 +112,7 @@ CONT \\\\{SPC}*
 <expr,eval>\]              { return token::RBRACKET; }
 <expr,eval>in              { return token::IN; }
 <expr,eval>when            { return token::WHEN; }
+<expr,eval>save            { return token::SAVE; }
 
 <expr,eval>true            { return token::TRUE; }
 <expr,eval>false           { return token::FALSE; }