Code covered by the BSD License  

Highlights from
C-style MATLAB preprocessor

from C-style MATLAB preprocessor by Misha Koshelev
Simple, only supports ifdef/endif/else with define/undef, simple syntax for &&/||.

[varargout]=mpp(fn,varargin)
function [varargout]=mpp(fn,varargin)
% Simple MATLAB C-like preprocessor
%
% See mpptest.m1 for simple example. Run with:
% mpp('mpptest',param)
%
% Misha Koshelev
% February 16th, 2009
% Montague Laboratory

    % definitions and temporary folder - persistent for recursion
    persistent defs;
    persistent temp;    
    recursed=~isempty(temp);
    if ~recursed
        temp=tempname;
        mkdir(temp);
    end

    % special functions
    if strcmpi(fn,'defs')
        % pre-specify definitions
        temp=[];
        defs=varargin{1};
        return;
    elseif strcmpi(fn,'clear')
        % clear everything
        temp=[];
        defs=struct();
        return;
    end

    % check for file existence
    if ~exist([fn,'.m1'],'file')
        fprintf('File %s does not exist.\n',[fn,'.m1']);
        cleanup;
        return;
    end
    
    % clear function cache
    clear(fn);
    
    fi=fopen([fn,'.m1'],'r');
    fo=fopen([temp,filesep,fn,'.m'],'w');
    
    % how far into loops are we?
    loop=0;
    
    % are we writing? 0 if we are, otherwise at what loop level we stopped
    writing=0;    

    while 1
        l=fgets(fi);
        if ~ischar(l)
            break;
        end
        
        lt=strtrim(l);
        if isempty(lt)||lt(1)~='#'
            if ~writing
                recurse=regexpi(l,'mpp\(.*\)','match');
                if ~isempty(recurse)
                    recurse=recurse{1};
                    if length(regexp(recurse,'\('))~=1||length(regexp(recurse,'\)'))~=1
                        fprintf('Statement not supported:\n%s\n',l);
                        cleanup;
                        return;
                    end
                    % pull out function name
                    fnr=regexprep(recurse,'mpp\(''(.*)''.*','$1','ignorecase');
                    defss=defs;
                    mpp(fnr);             
                    defs=defss;
                    % modify line
                    l=regexprep(l,'mpp\(''(.*)'',(.*)\)','$1($2)','ignorecase');
                end
                fwrite(fo,l);                    
            else
                % preserve line no's
                fprintf(fo,'\n');
            end
        else
            [sm,sl]=regexp(lt(2:end),'[^\w]','match','split');
            len=length(sl);            
            if strcmpi(sl{1},'define')
                % Syntax:
                % #define a
                % or
                % #define a b
                % (currently no difference)
                if ~writing
                    if length(sl)>2
                        defs.(sl{2})=sl{3};
                    else
                        defs.(sl{2})=[];
                    end
                end
            elseif strcmpi(sl{1},'undef')
                % Syntax:
                % #undef a
                if ~writing
                    if isfield(defs,sl{2})
                        defs=rmfield(defs,sl{2});
                    end
                end
            elseif strcmpi(sl{1},'ifdef')
                % Syntax:
                % #ifdef a
                % if a defined, do ...
                % or
                % #ifdef a||b
                % if a or b defined, do ...
                % or
                % #ifdef a&&b
                % if a and b both defined, do ...
                loop=loop+1;
                if len==2
                    if ~writing&&~isfield(defs,sl{2})
                        writing=loop;
                    end
                elseif len==4
                    if sm{2}=='&'&&sm{3}=='&'
                        if ~writing&&(~isfield(defs,sl{2})||~isfield(defs,sl{4}))
                            writing=loop;
                        end
                    elseif sm{2}=='|'&&sm{3}=='|'
                        if ~writing&&(~isfield(defs,sl{2})&&~isfield(defs,sl{4}))
                            writing=loop;
                        end                        
                    else
                        fprintf('Unknown preprocessor directive:\n');
                        fwrite(1,l);
                        cleanup;
                        return;                        
                    end
                end
            elseif strcmpi(sl{1},'ifndef')
                % Syntax:
                % #ifndef a
                % if a not defined, do ...
                % or
                % #ifndef a||b
                % if a or b not defined, do ...
                % or
                % #ifndef a&&b
                % if a and b both not defined, do ...
                loop=loop+1;
                if len==2
                    if ~writing&&isfield(defs,sl{2})
                        writing=loop;
                    end
                elseif len==4
                    if sm{2}=='&'&&sm{3}=='&'
                        if ~writing&&(isfield(defs,sl{2})||isfield(defs,sl{4}))
                            writing=loop;
                        end
                    elseif sm{2}=='|'&&sm{3}=='|'
                        if ~writing&&(isfield(defs,sl{2})&&isfield(defs,sl{4}))
                            writing=loop;
                        end                        
                    else
                        fprintf('Unknown preprocessor directive:\n');
                        fwrite(1,l);
                        cleanup;
                        return;                        
                    end
                end
            elseif strcmpi(sl{1},'endif')
                % Syntax:
                % #endif
                % Must close all #ifdef and #ifndef functions
                loop=loop-1;
                if writing>loop
                    writing=0;
                end
            elseif strcmpi(sl{1},'else')
                % Syntax:
                % #else
                % must follow an #ifdef or #ifndef
                if writing==loop
                    writing=0;
                elseif ~writing
                    writing=loop;
                end
            else
                fprintf('Unknown preprocessor directive:\n');
                fwrite(1,l);
                cleanup;
                return;
            end
            fprintf(fo,'\n');
        end
    end
        
    fclose(fo);
    fclose(fi);

    temps=temp;
    cleanup;
    if ~recursed
        fprintf('m file path: %s\n',temps);
        ps=path;addpath(temps);
        varargout={feval(str2func(fn),varargin{:})};    
        path(ps);
        rmdir(temps,'s');
    end
   
    function cleanup
    % Clean up persistent variables before exiting
    %
        if ~recursed
            defs=struct();
            temp=[];
        end
    end
end

Contact us at files@mathworks.com