Further improvements to parsing of arguments on the MATLAB command-line

Under GNU/Linux and macOS, double-quote arguments before passing them to the
shell. In particular, this allows passing single-quotes within those arguments.

We therefore have to escape the four characters that are interpreted within
double-quoted strings in POSIX shells: \, ", $ and `

On Windows, also systematically escape the backslashes.

Also move display of arguments before escaping, so that it remains readable.

Ref. #1696
time-shift
Sébastien Villemot 2020-02-10 16:36:52 +01:00
parent ae3f150c99
commit ae59f4dcb2
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
2 changed files with 23 additions and 22 deletions

View File

@ -334,9 +334,10 @@ by the ``dynare`` command.
Defines a macro-variable from the command line (the same effect as Defines a macro-variable from the command line (the same effect as
using the Macro directive ``@#define`` in a model file, see using the Macro directive ``@#define`` in a model file, see
:ref:`macro-proc-lang`). Note that when passing a MACRO_EXPRESSION that :ref:`macro-proc-lang`). Note that when passing a MACRO_EXPRESSION that
contains a space, you must surround the entire ``-D`` flag with single contains a space (or, under Octave, a double quote), you must surround
quotes, as in the following example. Also note that an expression the entire ``-D`` flag with single quotes, as in the following example.
passed on the command line can reference variables defined before it. Also note that an expression passed on the command line can reference
variables defined before it.
*Example* *Example*

View File

@ -210,34 +210,34 @@ else
end end
end end
command = ['"' dynareroot 'preprocessor' arch_ext filesep 'dynare_m" ' fname] ;
command = [ command ' mexext=' mexext ' "matlabroot=' matlabroot '"'];
if ~isempty(varargin)
if ispc
varargincopy = varargin;
for i = 1:length(varargincopy)
if varargincopy{i}(end) == '\'
varargincopy{i} = [varargincopy{i} '\'];
end
end
varargincopy = strrep(varargincopy, '"', '\"');
dynare_varargin = ['"' strjoin(varargincopy, '" "') '"'];
else
dynare_varargin = ['''' strjoin(varargin, ''' ''') ''''];
end
command = [command ' ' dynare_varargin];
end
if preprocessoroutput if preprocessoroutput
fprintf(['Starting Dynare (version ' dynare_version() ').\n']); fprintf(['Starting Dynare (version ' dynare_version() ').\n']);
fprintf('Calling Dynare with arguments: '); fprintf('Calling Dynare with arguments: ');
if isempty(varargin) if isempty(varargin)
disp('none') disp('none')
else else
disp(dynare_varargin); disp(strjoin(varargin, ' '));
end end
end end
command = ['"' dynareroot 'preprocessor' arch_ext filesep 'dynare_m" ' fname] ;
command = [ command ' mexext=' mexext ' "matlabroot=' matlabroot '"'];
% Properly quote arguments before passing them to the shell
if ~isempty(varargin)
varargincopy = varargin;
% Escape backslashes and double-quotes
varargincopy = strrep(varargincopy, '\', '\\');
varargincopy = strrep(varargincopy, '"', '\"');
if ~ispc
% On GNU/Linux and macOS, also escape dollars and backquotes
varargincopy = strrep(varargincopy, '$', '\$');
varargincopy = strrep(varargincopy, '`', '\`');
end
% Finally, enclose arguments within double quotes
dynare_varargin = ['"' strjoin(varargincopy, '" "') '"'];
command = [command ' ' dynare_varargin];
end
% Under Windows, make sure the MEX file is unloaded (in the use_dll case), % Under Windows, make sure the MEX file is unloaded (in the use_dll case),
% otherwise the preprocessor can't recompile it % otherwise the preprocessor can't recompile it
if isoctave if isoctave