% % matlab2octave project converter % % converts your OWN matlab code to octave matching with the guidlines on % wiki.octave.org. % % Be sure to remember: % NEVER USE SOURCE CODE FROM MATLAB. NOR CODE WHICH IS DERIVED FROM IT OR JUST MODIFIED. % Always use 100% your own code. % % - Do not add an additional copyright to your m-file it will be added automatically % - Put the name and path to the m-file including your function in mFileInUsingMatlabStyle. % - The output octave file is stored in mfileOutUsingOctaveGuidlines. % - Place your help text in your mfile directly under your function header. % Start with each help text line with '%' or '#'. Like you would do it normally. % % partially implemented guidlines on wiki.octave.org: % - % % License: GPL3 % ----------------------- some global variables -------------------------------- global d6 % ----------------------- fill in this parameters ------------------------------ % file settings mFileInUsingMatlabStyle='D:\Projekte1\OctaveSupport\extractBefore_matlab.m'; %'U:\60_Toolbox\Octave\extractBefore.m'; mfileOutUsingOctaveGuidlines='D:\Projekte1\OctaveSupport\extractBefore_octave.m'; seealso='extractAfter'; % string with functions which are related, e.g. seealso='mean, meanabs, meansq, sumsqr, sumabs' % other settings endlineInEsc='\r\n'; endlineIn=sprintf(endlineInEsc); % endline of Matlab function endlineOutEsc='\n'; endlineOut=sprintf(endlineOutEsc); % endline of Octave commandIndent=' '; % ------------------ define some local functions ------------------------------- function u=ChangeToEmptyIfPositionIsInComment(s) global d6 if isempty(s), u=s; return; end if isscalar(s) disp('XX'); i=s; while i>=1 if d6(i)=='#' u=[]; return; elseif ( d6(i)==char(10) || d6(i)==char(13) || i==1 ) u=s; return; end i=i-1; end end u=s; end function isfunction(functionname) try e=exist(functionname,'class'); catch e=(e>0)|ishandle(e); end e=e|exist(functionname,'builtin')|exist(functionname,'file'); end % ------------------------------- main ------------------------------------ % read mfileIn if ~exist(mFileInUsingMatlabStyle,'file') error('input file does not exist'); end f=fopen(mFileInUsingMatlabStyle,'r'); d=fread(f,'char=>char')'; fclose(f); clear f; % input file is in d if isempty(d) error('file is empty'); end t=''; % output file is in t % do some primary reformattings... % asymmetric operators: , % single sign operators: +-*/\^&|<>= % double sign operators: '.*','./','.\','.^','==','>=','<=','&&','||' % ignored operators: ! @ ... d=regexprep(d,'[ ]+,',','); % change space+, d=regexprep(d,',[ ]*',', '); % change ,+space d=strrep(d,'~','!'); % change NOT d=regexprep(d,'(?m)(^[ ]*)%%','$1##'); % change COMMENT section at the beginning of a line d=regexprep(d,'(?m)(^[ ]*)%','$1##'); % change COMMENT at the beginning of a line d=regexprep(d,'([ ]+)%','$1##'); % change COMMENT at end of a line % insert correct spacing around operators operators1={'\+','\-','\*','\/','\\','\^','\&','\|','\=','<','>','\.\*','\.\/','\.\\','\.\^','\=\=','>\=','<\=','\&\&','\|\|','!\='}; operators2={'+','-','*','/','\','^','&','|','=','<','>','.*','./','.\','.^','==','>=','<=','&&','||','!='}; for i=1:length(operators2) d=regexprep(d,['([A-Za-z0-9\(\[\{\}\]\)])[ ]*',operators1{i},'[ ]*([A-Za-z0-9\(\[\{\}\]\)])'],['$1 ',operators2{i},' $2']); end % check line length of max 79 characters and give warning i=diff(strfind(d,endlineIn)); if i>79+length(endlineIn), warning('Some lines are longer than 79 characters. Please try to shorten the line width.'); end % ============= start with the copyright ================= year=str2num(datestr(now,'YYYY')); year=[num2str(year),'-',num2str(year+9)]; copyrightNotice=([... '########################################################################',endlineOut,... '##',endlineOut,... '## Copyright (C) ',year,' The Octave Project Developers',endlineOut,... '## See for copyright notices.',endlineOut,... '##',endlineOut,... '## This file is part of Octave.',endlineOut,... '##',endlineOut,... '## This program is free software: you can redistribute it and/or modify',endlineOut,... '## it under the terms of the GNU General Public License as published by',endlineOut,... '## the Free Software Foundation, either version 3 of the License, or',endlineOut,... '## any later version.',endlineOut,... '##',endlineOut,... '## This program is distributed in the hope that it will be useful,',endlineOut,... '## but WITHOUT ANY WARRANTY; without even the implied warranty of',endlineOut,... '## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the',endlineOut,... '## GNU General Public License for more details.',endlineOut,... '##',endlineOut,... '## You should have received a copy of the GNU General Public License',endlineOut,... '## along with Octave; see the file COPYING. If not, see',endlineOut,... '## .',endlineOut,... '##',endlineOut,... '########################################################################',endlineOut,... endlineOut]); t=[t,copyrightNotice]; % ============= modify help text ============== % generate start of the output help text helptext=['## -*- texinfo -*-',endlineOut]; % function definitions - preparations d1=d(1:min(strfind(d,endlineIn))-1); % function definition d1=regexprep(d1,'[ ]+',' '); d1=regexprep(d1,'\[[ ]+','\['); d1=regexprep(d1,'[ ]+\]','\]'); d1=regexprep(d1,'[ ]*,[ ]*',','); if ~strcmp(d1(1:8),'function') error('matlab input should be a function. The function header must be defined in the first line.'); end % function definitions - output parameters i=strfind(d1,'='); outputParametersPresent=~isempty(i); if outputParametersPresent d0=strtrim(d1(1:min(i)-1)); % output parameters d2=strtrim(d1(min(i)+1:end)); % function name and variables d3=strtrim(d2(1:min(strfind(d2,'('))-1)); % function name multipleOutputParametersPresent=~isempty(strfind(d0,'[')); if multipleOutputParametersPresent dx=regexp(d0,'(?<=\[)(.*?)(?=\])','match'); % remove braces [ ] outputParameters=dx; dx=regexp([',',dx{1},','],'(?<=[ ,]+)(.+?)(?=[ ,]+)','match'); % remove seperators dx=cellfun(@(x) ['@var{',strtrim(x),'}, '],dx, 'UniformOutput',false); % add var syntax dx=cell2mat(dx);dx=['@deftypefnx {} {[',dx(2:end-2),'] =} ',d3,' (@dots{})']; else dx=strtrim(d0(10:end)); % get the output variable, cut "function" outputParameters={dx}; dx=['@deftypefnx {} {@var{',dx,'} =} ',d3,' (@dots{})']; end else d3=strtrim(d1(10:min(strfind(d1,'('))-1)); outputParameters={''}; dx=['@deftypefnx {} {} ',d3,' (@dots{})']; end mainFunctionName=d3; % function definitions - input parameters d4=regexp(d1,'(?<=\()(.*?)(?=\))','match'); if ~isempty(d4), d4=d4{1}; else d4=''; end % input variables inputParametersPresent=~isempty(d4); if inputParametersPresent dy=regexp([',',d4,','],'(?<=[ ,]+)(.+?)(?=[ ,]+)','match'); inputParameters=dy; dy=cellfun(@(x) ['@var{',strtrim(x),'}, '],dy, 'UniformOutput',false); % add var syntax dy=cell2mat(dy);dy=['@deftypefn {} {} ',d3,' (',dy(2:end-2),')']; else dy=['@deftypefn {} {} ',d3,' ()']; inputParameters={''}; dx=strrep(dx,[d3,' (@dots{})'],[d3,' ()']); end helptext=[helptext,'## ',dy,endlineOut]; helptext=[helptext,'## ',dx,endlineOut]; helptext=[helptext,'##',endlineOut]; % modify existing help text - extract help text i=strfind(d,endlineIn); i=i+length(endlineIn); i=i(1:end-1); % i is the position of the first character of each line j=[min(find(d(i)=='#')) min(find(d(i)~='#'))]; i=i(j); % look for block of comments after the function definition d5=d(i(1):i(2)-length(endlineIn)); % extract help text d6=d(i(2):end); % rest of the programm d5=strrep(d5,'matlab','@sc{matlab}'); d5=strrep(d5,'Matlab','@sc{Matlab}'); d5=strrep(d5,'MATLAB','@sc{MATLAB}'); % matlab => @sc{matlab} d5=regexprep(d5,'([A-Za-z0-9\(\[\{\}\]\)])[ ]*\.[ ]*([A-Za-z0-9\(\[\{\}\]\)])','$1. $2'); %xx. xx two space convention for i=1:length(inputParameters), d5=regexprep(d5,['([ \r\n;,:!\/\\\*\-\+\|\&\=\(\[\{\}\]\)])',inputParameters{i},'([ \r\n;,:!\/\\\*\-\+\|\&\=\(\[\{\}\]\)])'],['$1@var{',inputParameters{i},'}$2']); end % mark variables in help text for i=1:length(outputParameters), d5=regexprep(d5,['([ \r\n;,:!\/\\\*\-\+\|\&\=\(\[\{\}\]\)])',outputParameters{i},'([ \r\n;,:!\/\\\*\-\+\|\&\=\(\[\{\}\]\)])'],['$1@var{',outputParameters{i},'}$2']); end % mark variables in help text % give some comments about text style if neccessary :) if ~isempty(strfind(upper(d5),'CAUSE')) warning('see https://wiki.octave.org/Help_text_style_guide to simplify the help text.'); end if ~isempty(strfind(upper(d5),'WILL BE')) warning('use active voice in the present tense. See https://wiki.octave.org/Help_text_style_guide to simplify the help text.'); end if (length(strfind(d5,'## '))./length(strfind(d5,endlineIn)))>0.3 warning('Many indents in help text detected. Think about removing the indents for readability.'); end % if there is an example at the end of the help in the matlab file than mark it i=regexp(d5,'##([A-Za-z0-9!|&7%*+\- ]*?)[Ee]xampl[es:]+?'); if ~isempty(i), d5=[d5(1:i-1),'## @example',endlineOut,'## @group',endlineOut,d5(i:end),endlineOut,'## @end group',endlineOut,'## @end example',endlineOut]; end helptextEnd=['## @seealso{',seealso,'}',endlineOut,'## @end deftypefn',endlineOut]; helptext=[helptext,d5,helptextEnd]; t=[t,helptext]; % get octave function list and add a space after each funtion p=regexp(char(median(double(char(regexp(path,'(?<=;)(.*?);','match'))))),'^(.*?)ctave-(.*?)\\','match'); p=p{1}; %get installation path [temp,q]=system(['dir /S /B "',p,'*.m"']); q=regexp(q,'(?<=\\)([@!+\-*\(\)\[\]\{\}=&%\$\"\!A-Za-z0-9\.,:;ß_<>]*?)(?=\.m[\r\n]+)','match'); % get all m files u=urlread('https://octave.sourceforge.io/list_functions.php?sort=alphabetic'); % get all functions from octave sourceforge u=regexp(u,'(?<=">)([ @!+\-*\(\)\[\]\{\}=&%\$\"\!A-Za-z0-9\.,:;_]*?)(?=)','match'); % get all functions from html page u=regexprep(u,'[ ]\((.*?)\)',''); u=strrep(u,'.m',''); % remove some artefacts: () and .m q=unique([q,u]); % sort and remove double entries for i=1:length(q), d6=strrep(d6,[q{i},'('],[q{i},' (']); end % add a space after each funtion % add function header to function body d6 d6=[d1,endlineOut,d6]; % change the source code a little bit % if...end => if...endif ... specialOpenings={'try','classdef','enumeration','events','for','function','if','methods','parfor','properties','switch','while'}; specialEndings={'end_try_catch','endclassdef','endenumeration','endevents','endfor','endfunction','endif','endmethods','endparfor','endproperties','endswitch','endwhile','end'}; tagList=[]; for i=1:length(specialOpenings),s=regexp(d6,['(?m)(?<=^[ ^#]*)',specialOpenings{i},'[ \n\r]'])'; s=ChangeToEmptyIfPositionIsInComment(s); s=[s,ones(size(s))*i,ones(size(s))]; tagList=[tagList;s]; end % opening directly at the bebinning of the line for i=1:length(specialOpenings),s=regexp(d6,['(?<=[;,^#][ ])',specialOpenings{i},'[ \n\r]'])'; s=ChangeToEmptyIfPositionIsInComment(s); s=[s,ones(size(s))*i,ones(size(s))]; tagList=[tagList;s]; end % if a comment is written in front of the opening for i=1:length(specialEndings), s=regexp(d6,['(?m)(?<=^[ ^#]*)',specialEndings{i},'[ \n\r]'])'; s=ChangeToEmptyIfPositionIsInComment(s); s=[s,ones(size(s))*i,-ones(size(s))]; tagList=[tagList;s]; end % ending at the beginning of a line for i=1:length(specialEndings), s=regexp(d6,['(?m)(?<=[ ]+)',specialEndings{i},'[ \n\r]'])'; s=ChangeToEmptyIfPositionIsInComment(s); s=[s,ones(size(s))*i,-ones(size(s))]; tagList=[tagList;s]; end % ending at the end of the line [a,b]=unique(prod(tagList,2)); tagList=tagList(b,:); tagList=sortrows(tagList,1); % remove double entries in tagList tagList(tagList(:,2)==13,2)=0; % set normal end to 0 n=size(tagList,1); tagList=[tagList,tagList(:,2)]; % extend taglist for corrected endings stack=[]; for i=1:n if tagList(i,3)==1 stack=[stack,tagList(i,2)]; elseif tagList(i,3)==-1, if stack(end)==tagList(i,2) stack=stack(1:end-1); elseif tagList(i,2)==0 tagList(i,4)=stack(end); stack=stack(1:end-1); else disp('problem in programm structure.'); end end %disp(stack); end if ~isempty(stack) disp('problem in programm structure.'); end % additional structure changes % if (a==b) command; end => multiline notation % if a==b, command; end => multiline notation specialCommands={'try','for','if','parfor','switch','while'}; for i=1:length(specialCommands) %to do .... %d6=regexprep(d6,['([ ]+)(',specialCommands{i},'[ ]+)(.*?)\,([ A-Za-z]+)(.*?)(end)([ A-Za-z]+)',endlineInEsc],['$1$2$3',endlineInEsc,commandIndent,'$1$4$5',endlineInEsc,'$1$6$7']); % free standing if %d6=regexprep(d6,['(?m)(^[ ]*)(',specialCommands{i},'[ ]+)(.*?),([ A-Za-z]+)(.*?)(end)([ A-Za-z]+)'],['$1$2$3',endlineInEsc,commandIndent,'$1$4$5',endlineInEsc,'$1$6$7']); % if at the beginning end % finalize output t=[t,endlineOut,d6,endlineOut]; t=char(t); % --------------------------- save octave file -------------------------------------- fid=fopen(mfileOutUsingOctaveGuidlines,'w'); fwrite(fid,t'); fclose(fid); disp('ok');