Describe the bug
The script convert_code.m fails to run on Octave (Linux environment) due to several compatibility issues with MATLAB-specific syntax and file reading functions. The errors range from reserved keyword conflicts (do) to out of bound errors when parsing the .mod file using importdata, which behaves differently in Octave for non-numeric files.
To Reproduce
Steps to reproduce the behavior:
- Run the MMB toolbox using Octave on a Linux machine.
- Attempt to load a model that triggers the convert_code function (Dynare version adaptation).
- The execution crashes inside convert_code.m.
- See errors:
- parse error: 'do' is a keyword
- operator +: nonconformant arguments (string concatenation)
- index out of bound (caused by importdata)
Expected behavior
The function should correctly read the .mod file, parse it as a cell array of strings, perform the necessary replacements for Dynare compatibility, and save the file without crashing, regardless of whether it is running on MATLAB or Octave.
Desktop (please complete the following information):
- OS: Linux (e.g., Ubuntu/Debian)
- Software: GNU Octave
- Version: 8.4.0
Additional context
I have implemented a set of fixes that make the script robust for Octave while maintaining MATLAB compatibility.
List of changes:
-
Reserved Keyword Conflict: Renamed the variable do to keep_going (line ~36). do is a reserved keyword in Octave (used for do-until loops) and cannot be used as a variable name.
-
String Concatenation: Replaced string addition using + with bracket concatenation [...] (lines 32, 53). Example: changed name+".mod" to [name, '.mod'] for better compatibility.
-
Cell Conversion: Replaced string() with cellstr() (line 33) to ensure the data is treated as a cell array of character vectors.
-
File Reading (Major Fix): Replaced importdata() with fileread() + strsplit().
- Reason: importdata in Octave often misinterprets raw code files as matrices, causing dimension mismatches (out of bound errors). Reading the file as a raw string and splitting by newline \n is safer and faster.
-
Output Formatting: Corrected fprintf syntax at the end of the file. Changed code(k) to code{k} to correctly access the cell content during writing.
-
Optimization: Vectorized the replacement loop using strrep directly on the cell array, removing the need for the nested while/find loop.
Proposed Solution Code:
function check = convert_code(name)
%%
% Input: name of models
% Output: check = 0, mod file could not be changed
% = 1, all mod files successfully changed
% This file converts mod file to dynare version >4.6
% Copy file
% Read mod file
% Look for sequence to change
% Replace it
% Save mod file
oldpath=pwd;
%%
check=0;
cd(name);
%% Sequences which replace code
sequence_change = {}; %sequence to search
lines_change={}; %lines to add
%Loading policy rule coefficients
sequence_change{end+1} = "M_.param_names(i,:)";
lines_change{end+1}= "M_.param_names{i}";
% copy paste original code
%copyfile(name+".mod",name+"_orig.mod");
% Read the mod file as a cell with element being one line of code
% --- FIX FOR OCTAVE/LINUX START ---
if exist([name, '.mod'], 'file')
raw_text = fileread([name, '.mod']); % Read all the file as an only string
code = strsplit(raw_text, {'\n', '\r'}, 'CollapseDelimiters', false); % Cut by line breaks
code = code(:); % Ensure that it is a column vector.
else
error(['The file ' name '.mod cannot be found.']);
end
% --- FIX FOR OCTAVE/LINUX END ---
% Look for the sequences where to change code
% Look for the sequences where to change code
for j = 1:size(sequence_change, 2)
% Vectorized replacement: applies the change to all lines at once.
% This replaces the manual 'while' loop and index searching.
code = strrep(code, sequence_change{1,j}, lines_change{1,j});
end
% Set check to 1 to indicate the conversion process ran
check = 1;
% create a mod file with the converted code
filename = [name, '.mod'];
fid = fopen(filename,'wt');
for k = 1:length(code)
fprintf(fid, '%s \n', code{k});
end
fclose(fid);
cd(oldpath)
convert_code.txt
Describe the bug
The script convert_code.m fails to run on Octave (Linux environment) due to several compatibility issues with MATLAB-specific syntax and file reading functions. The errors range from reserved keyword conflicts (do) to out of bound errors when parsing the .mod file using importdata, which behaves differently in Octave for non-numeric files.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The function should correctly read the .mod file, parse it as a cell array of strings, perform the necessary replacements for Dynare compatibility, and save the file without crashing, regardless of whether it is running on MATLAB or Octave.
Desktop (please complete the following information):
Additional context
I have implemented a set of fixes that make the script robust for Octave while maintaining MATLAB compatibility.
List of changes:
Reserved Keyword Conflict: Renamed the variable do to keep_going (line ~36). do is a reserved keyword in Octave (used for do-until loops) and cannot be used as a variable name.
String Concatenation: Replaced string addition using + with bracket concatenation [...] (lines 32, 53). Example: changed name+".mod" to [name, '.mod'] for better compatibility.
Cell Conversion: Replaced string() with cellstr() (line 33) to ensure the data is treated as a cell array of character vectors.
File Reading (Major Fix): Replaced importdata() with fileread() + strsplit().
Output Formatting: Corrected fprintf syntax at the end of the file. Changed code(k) to code{k} to correctly access the cell content during writing.
Optimization: Vectorized the replacement loop using strrep directly on the cell array, removing the need for the nested while/find loop.
Proposed Solution Code:
function check = convert_code(name)
%%
% Input: name of models
% Output: check = 0, mod file could not be changed
% = 1, all mod files successfully changed
% This file converts mod file to dynare version >4.6
% Copy file
% Read mod file
% Look for sequence to change
% Replace it
% Save mod file
oldpath=pwd;
%%
check=0;
cd(name);
%% Sequences which replace code
sequence_change = {}; %sequence to search
lines_change={}; %lines to add
%Loading policy rule coefficients
sequence_change{end+1} = "M_.param_names(i,:)";
lines_change{end+1}= "M_.param_names{i}";
% copy paste original code
%copyfile(name+".mod",name+"_orig.mod");
% Read the mod file as a cell with element being one line of code
% --- FIX FOR OCTAVE/LINUX START ---
if exist([name, '.mod'], 'file')
raw_text = fileread([name, '.mod']); % Read all the file as an only string
code = strsplit(raw_text, {'\n', '\r'}, 'CollapseDelimiters', false); % Cut by line breaks
code = code(:); % Ensure that it is a column vector.
else
error(['The file ' name '.mod cannot be found.']);
end
% --- FIX FOR OCTAVE/LINUX END ---
% Look for the sequences where to change code
% Look for the sequences where to change code
for j = 1:size(sequence_change, 2)
% Vectorized replacement: applies the change to all lines at once.
% This replaces the manual 'while' loop and index searching.
code = strrep(code, sequence_change{1,j}, lines_change{1,j});
end
% Set check to 1 to indicate the conversion process ran
check = 1;
% create a mod file with the converted code
filename = [name, '.mod'];
fid = fopen(filename,'wt');
for k = 1:length(code)
fprintf(fid, '%s \n', code{k});
end
fclose(fid);
cd(oldpath)
convert_code.txt