%% Copyright (C) 2012, SRI International.  All Rights Reserved.

%% This program is free software; you can redistribute it and/or
%% modify it under the terms of the GNU General Public License
%% as published by the Free Software Foundation; either version 2
%% of the License, or (at your option) any later version.

%% This program is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%% GNU General Public License for more details.

function [] = createGEInputFile(modelName)
    
    global subsystemSet;
    subsystemSet = java.util.HashSet;
    
    global dimensionSet;
    dimensionSet = java.util.HashSet;
    
    global dimensionDegreeMap;
    dimensionDegreeMap = java.util.Hashtable;
    
    global variableNameSet;
    variableNameSet = java.util.HashSet;
    
    global lineNameSet;
    lineNameSet = java.util.HashSet;
    
    global gotoAddressMap;
    gotoAddressMap = java.util.Hashtable;
    
    global gotoDimensionMap;
    gotoDimensionMap = java.util.Hashtable;
    
    global fromAddressMap;
    fromAddressMap = java.util.Hashtable;
    
    global fromDimensionMap;
    fromDimensionMap = java.util.Hashtable;
    
    global mdlPathName;
    
    global opFile1a;
    global opFile1b;
    global opFile1c;
    global opFile2;
    global opFile3;
    global opFile4;
    
    opFile1a = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_externalvariables_ge'))), 'w');
    opFile1b = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_internalvariables_ge'))), 'w');
    opFile1c = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_calledsubsystems_ge'))), 'w');
    opFile2 = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_dimensions_ge'))), 'w');
    opFile3 = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_constraints_ge'))), 'w');
    opFile4 = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_subsystems_ge'))), 'w');

    blks = find_system(modelName, 'SearchDepth', '1', 'type', 'Block');
    lines = find_system(modelName, 'FindAll', 'on', 'SearchDepth', '1', 'type', 'Line');
    
    printDeclaration(blks, lines, modelName);   
    subsystemSet.clear();
    collectDimensions(blks);
    subsystemSet.clear();
    printDimensions(blks, modelName);
    subsystemSet.clear();
    printTransitions(blks, modelName, modelName);     
    
    fclose(opFile1a);
    fclose(opFile1b);
    fclose(opFile1c);
    fclose(opFile2);
    fclose(opFile3);
    fclose(opFile4);
    
    checkGotoFromConsistency();
    
    opFile1a = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_externalvariables_ge'))), 'r');
    opFile1b = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_internalvariables_ge'))), 'r');
    opFile1c = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_calledsubsystems_ge'))), 'r');
    opFile2 = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_dimensions_ge'))), 'r');
    opFile3 = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_constraints_ge'))), 'r');
    opFile4 = fopen(strcat(mdlPathName, strcat('ge/', strcat(modelName, '_subsystems_ge'))), 'r');
    
    printGEInputFiles();
    
    fclose(opFile1a);
    fclose(opFile1b);
    fclose(opFile1c);
    fclose(opFile2);
    fclose(opFile3);
    fclose(opFile4);
end


function [inNames] = getInputNames(handle)
    ports = get_param(handle,'Ports');
    if (ports(1,1) > 0)
        for i = 1:ports(1,1)
            name = regexprep(char(get_param(handle, 'Name')), '\s', '');
            inNames(i) = {strcat(name,'__In',num2str(i))};
        end
    else
        inNames = {};
    end
end


function [outNames] = getOutputNames(handle)
    ports = get_param(handle,'Ports');
    if (ports(1,2) > 0)
        for i = 1:ports(1,2)
            name = regexprep(char(get_param(handle, 'Name')), '\s', '');
            outNames(i) = {strcat(name,'__Out',num2str(i))};
        end
    else
        outNames = {};
    end
end


function [numberOfRows, numberOfColumns] = getSignalDimension(dimensions, portName)
    if not(iscell(dimensions))
        dimensions = {dimensions};
    end
    dims = dimensions{1,1};
    if length(dims) == 2
        numberOfRows = dims(length(dims));
        numberOfColumns = dims(length(dims) - 1);
    elseif length(dims) == 3
        numberOfRows = dims(length(dims) - 1) ;
        numberOfColumns = dims(length(dims));
    else
        numberOfRows = dims(2);
        numberOfColumns = 1;
        fprintf('Warning : Not sure if the number of rows = %d and number of columns = %d have been correctly found for %s .. \n', numberOfRows, numberOfColumns, portName);
    end
end


function [] = printDeclaration(blks, lines, sysname)

    global subsystemSet;
    global variableNameSet;
    global lineNameSet;
    global opFile1a;
    global opFile1b;
    global opFile1c;
    global opFile4;

    for i=1:length(blks)
         handle = get_param(blks(i),'Handle');
         if iscell(handle)
             handle = handle{1,1};
         end
         name = get_param(blks(i),'Name');
         if iscell(name)
             name = name{1,1};
         end
         name = regexprep(name, '\s', '');
         parent = get_param(blks(i), 'Parent');
         if iscell(parent)
             parent = parent{1,1};
         end
         parent = regexprep(parent, '\s', '');
         parent = regexprep(parent, '/', '__');
         type = get_param(blks(i),'BlockType');
         typestr = char(type);
         
         masktype = '';
         try masktype = char(get_param(handle, 'MaskType')); catch end
         if strcmp(masktype, 'Stateflow') == 1
             % Now assuming that a Stateflow accepts only scalar inputs and
             % produces scalar output
             subsystemName = regexprep(char(get_param(handle, 'Name')), '\s', '');
             portHandles = get_param(handle,'PortHandles');
             inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
             outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
             if not(iscell(inputDimensions))
                 inputDimensions = {inputDimensions};
             end
             if not(iscell(outputDimensions))
                 outputDimensions = {outputDimensions};
             end
             fprintf(opFile1a,'%s__%s\n', sysname, subsystemName);
             for i = 1 : length(inputDimensions)
                 name1 = strcat(strcat(parent, '__'), subsystemName);
                 inPort = sprintf('%s__In%d_1_1', name1, i);
                 variableNameSet.add(inPort);
                 fprintf(opFile1a, '%s\n', inPort);
                 
             end
             for i = 1 : length(outputDimensions)
                 name1 = strcat(strcat(parent, '__'), subsystemName);
                 outPort = sprintf('%s__Out%d_1_1', name1, i);
                 variableNameSet.add(outPort);
                 fprintf(opFile1a, '%s\n', outPort);
             end
             fprintf(opFile1a, 'end\n\n\n');
         end
         
         switch typestr
             case 'SubSystem'  
                 namestr = strcat(parent, (strcat('__', name))); 
                 if not(subsystemSet.contains(namestr))
                     subsystemSet.add(namestr);
                     link_status = get_param(handle,'LinkStatus');
                     if strcmp(link_status,'none') || strcmp(link_status,'inactive')
                         subBlks = find_system(handle, 'SearchDepth', '1', 'type', 'Block');
                         subLines = find_system(handle, 'FindAll', 'on', 'SearchDepth', '1',  'type', 'Line');
                         sysPath = sprintf('%s__%s', parent, name);
                         printDeclaration(subBlks(2:length(subBlks)), subLines, sysPath);
                     end
                 end
         end
    end

    variableNameSet.clear();
    fprintf(opFile1a,'%s\n', sysname);
    fprintf(opFile1b,'%s\n', sysname);
    fprintf(opFile1c,'%s\n', sysname);
    
    fprintf(opFile4,'%s\n', sysname);

    for i=1:length(blks)
        handle = get_param(blks(i),'Handle');
        if iscell(handle)
             handle = handle{1,1};
        end
        typestr = char(get_param(blks(i),'BlockType'));
        if strcmp(typestr, 'SubSystem') == 1
            printBlockTypeInfo(handle);
        end
    end
    for i=1:length(blks)
        handle = get_param(blks(i),'Handle');
        if iscell(handle)
             handle = handle{1,1};
        end
        typestr = char(get_param(blks(i),'BlockType'));
        if strcmp(typestr, 'SubSystem') == 0
            printBlockTypeInfo(handle);
        end
    end 
    
    for i=1:length(lines)
        name  = get_param(lines(i),'Name');
        name = regexprep(name, '<', '');
        name = regexprep(name, '>', '');

        if strcmp(name, '') == 0
            name = regexprep(name, '\s', '');
            parent = get_param(handle, 'Parent');
            parent = regexprep(parent, '\s', '');
            parent = regexprep(parent, '/', '__');
            linename = strcat(strcat(parent, '__'), name);
            if lineNameSet.contains(linename) == false
                lineNameSet.add(linename);
            end
            if variableNameSet.contains(linename) == false
                variableNameSet.add(linename);
                srcblk = get_param(lines(i),'SrcBlock');
                if not(isempty(srcblk))
                    srcParent = get_param(lines(i),'Parent');
                    blkValue = strcat(srcParent,'/',srcblk);
                    handle = get_param(blkValue,'Handle');
                    portHandles = get_param(handle,'PortHandles');
                    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
                    [numrows, numcols] = getSignalDimension(outputDimensions);
                else
                    numrows = 1;
                    numcols = 1;
                end
                for i = 1 : numrows
                    for j = 1 : numcols
                        fprintf(opFile1b, '%s_%d_%d\n', linename, i, j);
                    end
                end
            end
        end
    end
    
    fprintf(opFile1a, 'end\n\n\n');
    fprintf(opFile1b, 'end\n\n\n');
    fprintf(opFile1c, 'end\n\n\n');
end
    
    
 function printBlockTypeInfo(handle)

    global variableNameSet;
    global opFile1a;
    global opFile1b;
    global opFile1c;
    
    link_status = get_param(handle,'LinkStatus');
    parent = get_param(handle, 'Parent');
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');

    if strcmp(get_param(handle, 'blockType'),'SubSystem') && (strcmp(link_status,'none') || strcmp(link_status,'inactive'))
        subsystemName = regexprep(char(get_param(handle, 'Name')), '\s', '');
        fprintf(opFile1c ,'(%s__%s', parent, subsystemName);
        
        masktype = '';
        try masktype = char(get_param(handle, 'MaskType')); catch end
        
        if strcmp(masktype, 'Stateflow') == 0
            blks = find_system(handle,'SearchDepth','1', 'BlockType', 'Inport');
            for i= 1:length(blks)
                name1 = strcat(strcat(parent, '__'), subsystemName);
                name2 = regexprep(char(get_param(blks(i),'Name')), '\s', '');
                inPort = strcat(name1,'__', name2, '__Out1');
                if variableNameSet.contains(inPort) == false
                    variableNameSet.add(inPort);
                    blkhandle = get_param(blks(i), 'Handle');
                    portHandles = get_param(blkhandle,'PortHandles');
                    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
                    [numrows, numcols] = getSignalDimension(outputDimensions, inPort);
                    for i = 1 : numrows
                        for j = 1 : numcols
                            fprintf(opFile1c, ' %s_%d_%d', inPort, i, j);
                            fprintf(opFile1b, '%s_%d_%d\n', inPort, i, j);
                        end
                    end
                end
            end
            
            blks = find_system(handle,'SearchDepth','1', 'BlockType', 'Outport');
            for i= 1:length(blks)
                name1 = strcat(strcat(parent, '__'), subsystemName);
                name2 = regexprep(char(get_param(blks(i),'Name')), '\s', '');
                outPort = strcat(name1, '__', name2, '__In1');
                if variableNameSet.contains(outPort) == false
                    variableNameSet.add(outPort);
                    blkhandle = get_param(blks(i), 'Handle');
                    portHandles = get_param(blkhandle,'PortHandles');
                    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                    [numrows, numcols] = getSignalDimension(inputDimensions, outPort);
                    for i = 1 : numrows
                        for j = 1 : numcols
                            fprintf(opFile1c , ' %s_%d_%d', outPort, i, j);
                            fprintf(opFile1b, '%s_%d_%d\n', outPort, i, j);
                        end
                    end
                end
            end
        else
            % Now assuming that a Stateflow accepts only scalar inputs and
            % produces scalar output
            portHandles = get_param(handle,'PortHandles');
            inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
            outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
            if not(iscell(inputDimensions))
                inputDimensions = {inputDimensions};
            end
            if not(iscell(outputDimensions))
                outputDimensions = {outputDimensions};
            end
            for i = 1 : length(inputDimensions)
                name1 = strcat(strcat(parent, '__'), subsystemName);
                inPort = sprintf('%s__In%d_1_1', name1, i);
                variableNameSet.add(inPort);
                fprintf(opFile1c, ' %s', inPort);
                fprintf(opFile1b, '%s\n', inPort);
            end
            for i = 1 : length(outputDimensions)
                name1 = strcat(strcat(parent, '__'), subsystemName);
                outPort = sprintf('%s__Out%d_1_1', name1, i);
                variableNameSet.add(outPort);
                fprintf(opFile1c, ' %s', outPort);
                fprintf(opFile1b, '%s\n', outPort);
            end
        end
        fprintf(opFile1c ,')\n');
    else
        ports = get_param(handle,'Ports');
        typestr = char(get_param(handle,'BlockType'));
        
        inputNames = getInputNames(handle);
        portHandles = get_param(handle,'PortHandles');
        inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
        if not(iscell(inputDimensions))
            inputDimensions = {inputDimensions};
        end
        for i = 1: ports(1,1)
            if strcmp(parent, '')
                inPortKey = char(inputNames(i));
            else
                inPortKey = strcat(parent, '__', char(inputNames(i)));
            end 
            if variableNameSet.contains(inPortKey) == false
                variableNameSet.add(inPortKey);
                [numrows, numcols] = getSignalDimension(inputDimensions{i, 1}, inPortKey);
                for i = 1 : numrows
                    for j = 1 : numcols
                        if strcmp(typestr, 'Outport') == 1
                            fprintf(opFile1a, '%s_%d_%d\n', inPortKey, i, j);
                        else
                            fprintf(opFile1b,'%s_%d_%d\n', inPortKey, i, j);
                        end
                    end
                end
            end
        end
        
        outputNames = getOutputNames(handle);
        ports = get_param(handle,'Ports');
        portHandles = get_param(handle,'PortHandles');
        outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
        if not(iscell(outputDimensions))
            outputDimensions = {outputDimensions};
        end
        for i = 1: ports(1,2)
            if strcmp(parent, '')
                outPortKey = char(outputNames(i));
            else
                outPortKey = strcat(parent, '__', char(outputNames(i)));
            end
            if variableNameSet.contains(outPortKey) == false
                if strcmp(typestr, 'Mux') == 1
                    % may not always work
                    [numrows, numcols] = getSignalDimension(outputDimensions{i, 1}, outPortKey);
                    numcols = 1;
                else
                    variableNameSet.add(outPortKey);                    
                    [numrows, numcols] = getSignalDimension(outputDimensions{i, 1}, outPortKey);
                end
                for i = 1 : numrows
                    for j = 1 : numcols
                        if strcmp(typestr, 'Inport') == 1
                            fprintf(opFile1a, '%s_%d_%d\n', outPortKey, i, j);
                        else
                            fprintf(opFile1b, '%s_%d_%d\n', outPortKey, i, j);
                        end
                    end
                end
            end
        end
        
        if strcmp(typestr, 'Gain') == 1
            name = char(get_param(handle, 'Name'));
            name = regexprep(name, '\s', '');
            constantKey = strcat(parent, '__', name, '__Constant');
            if variableNameSet.contains(constantKey) == false
                variableNameSet.add(constantKey);
               
                portHandles = get_param(handle,'PortHandles');
                inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                [numrows, ~] = getSignalDimension(inputDimensions);
                outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
                [~, numcols] = getSignalDimension(outputDimensions);
                
                for i = 1 : numrows
                    for j = 1 : numcols
                        fprintf(opFile1b, '%s_%d_%d\n', constantKey, i, j);
                    end
                end
            end
        end

        if strcmp(typestr, 'Product') == 1
            multiplicationType = char(get_param(handle, 'Multiplication'));
            portHandles = get_param(handle,'PortHandles');
            inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
            outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions'); 
            if strcmp(multiplicationType, 'Matrix(*)') == 1
                ports = get_param(handle,'Ports');
                if ports(1,1) >= 2
                    name = char(get_param(handle, 'Name'));
                    name = regexprep(name, '\s', '');
                    parent = char(get_param(handle, 'Parent'));
                    parent = regexprep(parent, '\s', '');
                    parent = regexprep(parent, '/', '__');
                    indims1 = inputDimensions{1,1};
                    indims2 = inputDimensions{2,1};
                    numrows = indims1(length(indims1) - 1);
                    numcols = indims2(length(indims2));
                    for k = 3 : ports(1,1)
                        for i = 1 : numrows
                            for j = 1 : numcols
                                fprintf(opFile1b, '%s__%s__tmp%d_%d_%d\n', parent, name, k - 2, i, j);
                            end
                        end
                        indims = inputDimensions{k,1};
                        numcols = indims(length(indims));
                    end
                end
            end
        end
               
        if strcmp(typestr, 'Switch') == 1
            name = char(get_param(handle, 'Name'));
            name = regexprep(name, '\s', '');
            thresholdKey = strcat(parent, '__', name, '__Threshold');
            if variableNameSet.contains(thresholdKey) == false
                variableNameSet.add(thresholdKey);
                fprintf(opFile1b,'%s_1_1\n', thresholdKey);
            end
        end


        if strcmp(typestr, 'Integrator') == 1
            if strcmp(char(get_param(handle, 'ShowStatePort')), 'on')
                name = char(get_param(handle, 'Name'));
                name = regexprep(name, '\s', '');
                stateKey = strcat(parent, '__', name, '__Outstate');
                if variableNameSet.contains(stateKey) == false
                    variableNameSet.add(stateKey);
                    fprintf(opFile1b, '%s_1_1\n', stateKey);
                end
            end
        end 
    end
 end
 
 
function [] = collectDimensions(blks)
% Collects the dimensions used in the Simulink model to build the dimension
% structure

    global subsystemSet;
    global dimensionSet;
    
    for i=1:length(blks)
         handle = get_param(blks(i),'Handle');
         if iscell(handle)
             handle = handle{1,1};
         end
         name = get_param(blks(i),'Name');
         if iscell(name)
             name = name{1,1};
         end
         name = regexprep(name, '\s', '');
         parent = get_param(blks(i), 'Parent');
         if iscell(parent)
             parent = parent{1,1};
         end
         parent = regexprep(parent, '\s', '');
         parent = regexprep(parent, '/', '__');
         typestr = char(get_param(blks(i),'BlockType'));
         switch typestr
             case 'SubSystem'    
                 namestr = strcat(parent, (strcat('__', name))); 
                 if not(subsystemSet.contains(namestr))
                     subsystemSet.add(namestr);
                     link_status = get_param(handle,'LinkStatus');
                     if strcmp(link_status,'none') || strcmp(link_status,'inactive')
                         subBlks = find_system(handle, 'SearchDepth', '1', 'type', 'Block');
                         collectDimensions(subBlks(2:length(subBlks)));
                     end
                 end
         end
    end

    for i=1:length(blks)
        handle = get_param(blks(i),'Handle');
        if iscell(handle)
             handle = handle{1,1};
        end

        type = get_param(blks(i),'BlockType');
        typestr = char(type);
        if strcmp(typestr, 'SubSystem') == 0
            desc = get_param(handle, 'Description');
            if strcmp(desc, '') == 0
                desc = getDimensionDefinition(strcat(parent, '__', name), desc);
                desc = regexprep(desc, '\n', '');
                lines = regexp(desc, ';', 'split');
                for i = 1:length(lines) - 1
                    cells = regexp(lines{1,i}, ':', 'split');
                    str = cells{1,2};
                    str = regexprep(str, '[', '');
                    str = regexprep(str, ']', '');
                    numberOfBars = strfind(str, '|');
                    if numberOfBars > 0
                        rows = regexp(str, '|', 'split');
                    else
                        rows = {str};
                    end
                    for i = 1:length(rows)
                        columns = regexp(str, ')', 'split');
                        for j = 1:length(columns) - 1
                            dimcell = regexp(columns{1,j}, '(', 'split');
                            dims = regexp(dimcell{1,2}, ',', 'split');
                            for i = 1: length(dims)
                                dim = dims{1,i};
                                dim = deblank(dim);
                                noofspaces = length(strfind(dim, ' '));
                                components = regexp(dim, ' ', 'split');
                                if noofspaces == 3
                                    dimensionSet.add(components{1,2});
                                end
                                if noofspaces == 2
                                    dimensionSet.add(components{1,1});
                                end
                            end
                        end
                    end
                end
            end
        end
    end  
 end
    
 
 function [] = printDimensions(blks, sysname)

    global subsystemSet;
    global opFile2;
    
    for i=1:length(blks)
         handle = get_param(blks(i),'Handle');
         if iscell(handle)
             handle = handle{1,1};
         end
         name = get_param(blks(i),'Name');
         if iscell(name)
             name = name{1,1};
         end
         name = regexprep(name, '\s', '');
         parent = get_param(blks(i), 'Parent');
         if iscell(parent)
             parent = parent{1,1};
         end
         parent = regexprep(parent, '\s', '');
         parent = regexprep(parent, '/', '__');
         typestr = char(get_param(blks(i),'BlockType'));
         switch typestr
             case 'SubSystem'    
                 namestr = strcat(parent, (strcat('__', name))); 
                 if not(subsystemSet.contains(namestr))
                     subsystemSet.add(namestr);
                     link_status = get_param(handle,'LinkStatus');
                     if strcmp(link_status,'none') || strcmp(link_status,'inactive')
                         subBlks = find_system(handle, 'SearchDepth', '1', 'type', 'Block');
                         sysPath = sprintf('%s__%s', parent, name);
                         printDimensions(subBlks(2:length(subBlks)), sysPath);
                     end
                 end
         end
    end

    fprintf(opFile2,'%s\n', sysname);
    for i=1:length(blks)
        handle = get_param(blks(i),'Handle');
        if iscell(handle)
             handle = handle{1,1};
        end
        type = get_param(blks(i),'BlockType');
        typestr = char(type);
        if strcmp(typestr, 'SubSystem') == 1
            printDimensionInfo(handle);
        end
    end
    for i=1:length(blks)
        handle = get_param(blks(i),'Handle');
        if iscell(handle)
             handle = handle{1,1};
        end
        type = get_param(blks(i),'BlockType');
        typestr = char(type);
        
        if strcmp(typestr, 'SubSystem') == 0
            printDimensionInfo(handle);
        end
    end  
    fprintf(opFile2,'end\n\n\n');
end
    
    
function printDimensionInfo(handle)
     
    global gotoAddressMap;
    global gotoDimensionMap;
    global fromAddressMap;
    global fromDimensionMap;
    global fromBlockCount;

    global opFile2;
    
    link_status = get_param(handle,'LinkStatus');
    parent = get_param(handle, 'Parent');
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    masktype = '';
    stateflowFlag = 0;
    try masktype = char(get_param(handle, 'MaskType')); catch end
    if strcmp(masktype, 'Stateflow')
        stateflowFlag = 1;
    end
   
        % Stateflow is handled separately as non-interface blocks
    if strcmp(get_param(handle, 'blockType'),'SubSystem') && ...
        (strcmp(link_status,'none') || strcmp(link_status,'inactive')) && ...
        (strcmp(masktype, 'Stateflow') == 0)    
    else
        name = char(get_param(handle, 'Name'));
        name = regexprep(name, '\s', '');
        desc = char(get_param(handle, 'Description'));
        blocktype = char(get_param(handle,'BlockType'));
        
        if strcmp(blocktype, 'Inport') == 1 || ...
           strcmp(blocktype, 'Sin') == 1 || ...
           strcmp(blocktype, 'Step') == 1 || ...
           strcmp(blocktype, 'FromWorkspace') == 1 || ...
           strcmp(blocktype, 'From') == 1 || ...
           strcmp(blocktype, 'Ground') == 1
            outputNames = getOutputNames(handle);
            if strcmp(parent, '')
                outPortKey = char(outputNames(1));
            else
                outPortKey = strcat(parent, '__', char(outputNames(1)));
            end
            if strcmp(desc, '') == 1
                fprintf('Error: No dimension provided for %s\n', outPortKey);
            else
                desc = getDimensionDefinition(outPortKey, desc);
                if (desc(length(desc)) ~= ';')
                    fprintf('Error: Semicolon is missing in the dimension definition of %s\n', outPortKey);
                else
                    portHandles = get_param(handle,'PortHandles');
                    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
                    components = regexp(desc, ';', 'split');
                    desc = components{1,1};
                    if (length(outputDimensions) == 3)
                        printDimensionDetails(desc, outPortKey, outputDimensions(length(outputDimensions) - 1), outputDimensions(length(outputDimensions)));
                    end
                    if (length(outputDimensions) == 2)
                        printDimensionDetails(desc, outPortKey, outputDimensions(length(outputDimensions)), outputDimensions(length(outputDimensions) - 1));
                    end
                end  
            end
        elseif strcmp(blocktype, 'Outport') == 1 || ...
               strcmp(blocktype, 'Scope') == 1 || ...
               strcmp(blocktype, 'Terminator') == 1 || ...
               strcmp(blocktype, 'Goto') == 1 || ...
               strcmp(blocktype, 'Display') == 1 || ...
               strcmp(blocktype, 'ToWorkspace') == 1
            inputNames = getInputNames(handle);
            if strcmp(parent, '')
                inPortKey = char(inputNames(1));
            else
                inPortKey = strcat(parent, '__', char(inputNames(1)));
            end
            if strcmp(desc, '') == 1
                fprintf('Error: No dimension provided for %s\n', inPortKey);
            else
                desc = getDimensionDefinition(inPortKey, desc);
                if (desc(length(desc)) ~= ';')
                    fprintf('Error: Semicolon is missing in the dimension definition of %s\n', inPortKey);
                else
                    portHandles = get_param(handle,'PortHandles');
                    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                    components = regexp(desc, ';', 'split');
                    desc = components{1,1};
                    if (length(inputDimensions) == 3)
                        printDimensionDetails(desc, inPortKey, inputDimensions(length(inputDimensions) - 1), inputDimensions(length(inputDimensions)));
                    end
                    if (length(inputDimensions) == 2)
                        printDimensionDetails(desc, inPortKey, inputDimensions(length(inputDimensions)), inputDimensions(length(inputDimensions) - 1));
                    end
                end
            end
        elseif strcmp(blocktype, 'Constant') == 1
            outputNames = getOutputNames(handle);
            if strcmp(parent, '')
                outPortKey = char(outputNames(1));
            else
                outPortKey = strcat(parent, '__', char(outputNames(1)));
            end
            portHandles = get_param(handle,'PortHandles');
            outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
            if (length(outputDimensions) == 3)
                numrow = outputDimensions(length(outputDimensions) - 1);
                numcol = outputDimensions(length(outputDimensions));
            end
            if (length(outputDimensions) == 2)
                numrow = outputDimensions(length(outputDimensions));
                numcol = outputDimensions(length(outputDimensions) - 1);
            end
            if strcmp(desc, '') == 1
                fprintf('Error: No dimension provided for %s\n', outPortKey);
                for i = 1:numrow
                    for j = 1:numcol
                        fprintf(opFile2, '(assert (= (is_zero (%s %d %d)) false))\n', outPortKey, i, j);
                    end
                end
            else
                desc = getDimensionDefinition(outPortKey, desc);
                if (desc(length(desc)) ~= ';')
                    fprintf('Error: Semicolon is missing in the dimension definition of %s\n', outPortKey);
                else
                    components = regexp(desc, ';', 'split');
                    desc = components{1,1};
                    printDimensionDetails(desc, outPortKey, numrow, numcol);
                end
            end
        elseif strcmp(blocktype, 'Gain') == 1
            if strcmp(parent, '')
                constantKey = strcat(name, '__Constant');
            else
                constantKey = strcat(parent, '__', name, '__Constant');
            end
            if strcmp(desc, '') == 1
                fprintf('Error: No dimension provided for %s\n', constantKey);
            else
                desc = getDimensionDefinition(constantKey, desc);
                if (desc(length(desc)) ~= ';')
                    fprintf('Error: Semicolon is missing in the dimension definition of %s\n', constantKey);
                else
                    portHandles = get_param(handle,'PortHandles');
                    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
                    components = regexp(desc, ';', 'split');
                    desc = components{1,1};
                    if (length(inputDimensions) == 3) && (length(outputDimensions) == 3)
                        printDimensionDetails(desc, constantKey, inputDimensions(length(inputDimensions)), outputDimensions(length(outputDimensions)));
                    end
                    if (length(inputDimensions) == 3) && (length(outputDimensions) == 2)
                        printDimensionDetails(desc, constantKey, inputDimensions(length(inputDimensions)), outputDimensions(length(outputDimensions) - 1));
                    end
                    if (length(inputDimensions) == 2) && (length(outputDimensions) == 3)
                        printDimensionDetails(desc, constantKey, inputDimensions(length(inputDimensions) - 1), outputDimensions(length(outputDimensions)));
                    end
                    if (length(inputDimensions) == 2) && (length(outputDimensions) == 2)
                        printDimensionDetails(desc, constantKey, inputDimensions(length(inputDimensions) - 1), outputDimensions(length(outputDimensions) - 1));
                    end
                end
            end
        elseif strcmp(blocktype, 'Switch') == 1
            if strcmp(parent, '')
                thresholdKey = strcat(name, '__Threshold');
            else
                thresholdKey = strcat(parent, '__', name, '__Threshold');
            end
            if strcmp(desc, '') == 1
                fprintf('Error: No dimension provided for %s\n', thresholdKey);
            else
                desc = getDimensionDefinition(thresholdKey, desc);
                if (desc(length(desc)) ~= ';')
                    fprintf('Error: Semicolon is missing in the dimension definition of %s\n', thresholdKey);
                else
                    components = regexp(desc, ';', 'split');
                    desc = components{1,1};
                    printDimensionDetails(desc, thresholdKey, 1, 1);
                end
            end
        else
            if strcmp(desc, '') == 1
                if strcmp(blocktype, 'Fcn') == 1 || ...
                   strcmp(blocktype, 'S-Function') == 1 || ...
                   strcmp(blocktype, 'BusSelector') == 1 || ...
                   strcmp(blocktype, 'Lookup') == 1
                    fprintf('Error: No dimension provided for %s__%s\n', parent, name);
                    % For other blocks no dimensions may be provided for inputs
                    % and outputs
                end
            else
                if strcmp(parent, '')
                    blockName = name;
                else
                    blockName = strcat(parent, '__', name);
                end
                pos1 = strfind(desc, 'begin dimension');
                if not(isempty(pos1))
                    components1 = regexp(desc, 'begin dimension', 'split');
                    pos2 = strfind(desc, 'end dimension');
                    if isempty(pos2)
                        fprintf('ERROR: "end dimension" cannot be found in the dimension definition of block %s\n', blockName);
                    else
                        components2 = regexp(components1{1,2}, 'end dimension', 'split');
                        desc = components2{1,1};
                        portHandles = get_param(handle,'PortHandles');
                        inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                        outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions'); 
                        if not(iscell(inputDimensions))
                            inputDimensions = {inputDimensions};
                        end
                        if not(iscell(outputDimensions))
                            outputDimensions = {outputDimensions};
                        end
                        semicolonpos = strfind(desc, ';');
                        inputpos = strfind(desc, 'input');
                        outputpos = strfind(desc, 'output');
                        if (length(semicolonpos) ~= length(inputpos) + length(outputpos))
                            fprintf('Error: Number of semicolons does not match with the total number of input and output dimensions for %s\n', blockName);
                        else
                            lines = regexp(desc, ';', 'split');
                            for i = 1: length(lines)-1
                                inputpos = strfind(lines{1,i}, 'input');
                                outputpos = strfind(lines{1,i}, 'output');
                                colonpos = strfind(lines{1,i}, ':');
                                if isempty(colonpos)
                                    fprintf('Error: ":" missing in the definition of dimension for %s\n', blockName);
                                elseif length(colonpos) > 1
                                    fprintf('Error: More than one ":" in the definition of dimension for %s\n', blockName);
                                else
                                    cells = regexp(lines{1,i}, ':', 'split');
                                    firstpart = cells{1,1};
                                    if not(isempty(inputpos))
                                        inputname = regexprep(firstpart, 'input', '');
                                        inputname = regexprep(inputname, '\n', '');
                                        inputname = regexprep(inputname, ' ', '');
                                        inputnumber = str2num(inputname);
                                        if isempty(inputnumber)
                                            fprintf('Error: Input number missing in the definition of dimension for %s\n', blockName);
                                        elseif (inputnumber > length(inputDimensions))
                                            fprintf('Error: Input number is greater than the number of inputs for %s\n', blockName);
                                        else
                                            if strcmp(parent, '')
                                                inPortKey = strcat(name, '__In', num2str(inputnumber));
                                            else
                                                inPortKey = strcat(parent, '__', name, '__In', num2str(inputnumber));
                                            end
                                            indims = inputDimensions{inputnumber,1};
                                            desc = regexprep(lines{1,i}, '\n','');
                                            if length(indims) == 3
                                                printDimensionDetails(desc, inPortKey, indims(length(indims) - 1), indims(length(indims)));
                                            end
                                            if length(indims) == 2
                                                printDimensionDetails(desc, inPortKey, indims(length(indims)), indims(length(indims) - 1));
                                            end
                                        end
                                    end
                                    if not(isempty(outputpos))
                                        outputname = regexprep(firstpart, 'output', '');
                                        outputname = regexprep(outputname, '\n', '');
                                        outputname = regexprep(outputname, ' ', '');
                                        outputnumber = str2num(outputname);
                                        if isempty(outputnumber)
                                            fprintf('Error: Output number missing in the definition of dimension for %s\n', blockName);
                                        elseif (outputnumber > length(outputDimensions))
                                            fprintf('Error: Output number is greater than the number of outputs for %s\n', blockName);
                                        else
                                            if strcmp(parent, '')
                                                outPortKey = strcat(name, '__Out', num2str(outputnumber));
                                            else
                                                outPortKey = strcat(parent, '__', name, '__Out', num2str(outputnumber));
                                            end
                                            outdims = outputDimensions{outputnumber,1};
                                            desc = regexprep(lines{1,i}, '\n','');
                                            if length(outdims) == 3
                                                printDimensionDetails(desc, outPortKey, outdims(length(outdims) - 1), outdims(length(outdims)));
                                            end
                                            if length(outdims) == 2
                                                printDimensionDetails(desc, outPortKey, outdims(length(outdims)), outdims(length(outdims) - 1));
                                            end
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end 
        end       
    end
    
    desc = char(get_param(handle, 'Description'));
    blocktype = char(get_param(handle,'BlockType'));
    if strcmp(blocktype, 'Goto') == 1 
        gotoTag = char(get_param(handle, 'GotoTag'));
        inputNames = getInputNames(handle);
        if strcmp(parent, '')
            gotoKey = char(inputNames(1));
        else
            gotoKey = strcat(parent, '__', char(inputNames(1)));
        end
        dim = '';
        if strcmp(desc, '') == 0
            desc = getDimensionDefinition(gotoKey, desc);
            if (desc(length(desc)) == ';')
                portHandles = get_param(handle,'PortHandles');
                inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                components = regexp(desc, ';', 'split');
                desc = components{1,1};
                if (length(inputDimensions) == 3)
                    dim = getGotoDimensionSignature(desc, gotoKey, inputDimensions(length(inputDimensions) - 1), inputDimensions(length(inputDimensions)));
                end
                if (length(inputDimensions) == 2)
                    dim = getGotoDimensionSignature(desc, gotoKey, inputDimensions(length(inputDimensions)), inputDimensions(length(inputDimensions) - 1));
                end
            end
        end
        if gotoDimensionMap.containsKey(gotoTag)
            gotoAddress = gotoAddressMap.get(gotoTag);    
            fprintf('Error: Gototag of the block %s and the block %s are the same\n', gotoAddress, gotoKey);
        end
        gotoAddressMap.put(gotoTag, gotoKey);
        if strcmp(dim, '') == 0
            gotoDimensionMap.put(gotoTag, dim);
        end
    end
    
    desc = char(get_param(handle, 'Description'));
    if strcmp(blocktype, 'From') == 1 
        gotoTag = char(get_param(handle, 'GotoTag'));
        outputNames = getOutputNames(handle);
        if strcmp(parent, '')
            fromKey = char(outputNames(1));
        else
            fromKey = strcat(parent, '__', char(outputNames(1)));
        end
        dim = '';
        if strcmp(desc, '') == 0
            desc = getDimensionDefinition(fromKey, desc);
            if (desc(length(desc)) == ';')
                portHandles = get_param(handle,'PortHandles');
                outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');                
                components = regexp(desc, ';', 'split');
                desc = components{1,1};
                if (length(outputDimensions) == 3);
                    dim = getGotoDimensionSignature(desc, fromKey, outputDimensions(length(outputDimensions) - 1), outputDimensions(length(outputDimensions)));
                end
                if (length(outputDimensions) == 2)
                    dim = getGotoDimensionSignature(desc, fromKey, outputDimensions(length(outputDimensions)), outputDimensions(length(outputDimensions) - 1));
                end
            end
        end
        fromAddressMap.put(gotoTag, fromKey);
        if strcmp(dim, '') == 0
            fromDimensionMap.put(gotoTag, dim);
        end
    end
            
end
 


function desc = getDimensionDefinition(block, desc)
    desc = regexprep(desc, '\n','');
    desc = regexprep(desc, '\s+', ' ');
    pos1 = strfind(desc, 'begin dimension');
    if isempty(pos1)
        %fprintf('Error: "begin dimension" cannot be found in the dimension definition of block %s\n', block);
    else
        components1 = regexp(desc, 'begin dimension', 'split');
        pos2 = strfind(desc, 'end dimension');
        if isempty(pos2)
            fprintf('Error: "end dimension" cannot be found in the dimension definition of block %s\n', block);
        else
            components2 = regexp(components1{1,2}, 'end dimension', 'split');
            desc = components2{1,1};
        end
    end
end



function [] = printDimensionDetails(desc, name, dimx, dimy)

    global dimensionSet;
    global dimensionDegreeMap;
    global opFile2;
     
    dimensionDegreeMap.clear();

    cells = regexp(desc, ':', 'split');
    str = cells{1,2};
    numberOfBars = length(strfind(str, '|'));
    numberOfParenthesis = length(strfind(str, '('));
    if (dimx ~= numberOfBars + 1)
        fprintf('Error: dimension definition does not match in the number of rows for %s\n', name);
    elseif (dimx * dimy ~= numberOfParenthesis)
        fprintf('Error: dimension definition does not match in the number of columns for %s\n', name);
    else
        str = regexprep(str, '[', '');
        str = regexprep(str, ']', '');
        if numberOfBars > 0
            rows = regexp(str, '\|', 'split');
        else
            rows = {str};
        end
        for i = 1:length(rows)
            columns = regexp(rows{1,i}, ')', 'split');
            for j = 1:length(columns) - 1
                dimensionDegreeMap.clear();
                dimcell = regexp(columns{1,j}, '(', 'split');
                dims = regexp(dimcell{1,2}, ',', 'split');
                if length(dims) == 1 && strcmp(dims{1,1}, 'unknown') == 1
                    fprintf('Error: dimension definition is unknown for %s\n', name);
                elseif length(dims) == 1 && strcmp(dims{1,1}, 'zero') == 1
                    %fprintf(opFile2, '(- %s_%d_%d zero)\n', name, i, j);
                else
                for k = 1: length(dims)
                    dim = dims{1,k};
                    dim = deblank(dim);
                    noofspaces = length(strfind(dim, ' '));
                    components = regexp(dim, ' ', 'split');
                    if noofspaces == 3
                        dimensionDegreeMap.put(char(components{1,2}), char(components{1,4}));
                    end
                    if noofspaces == 2
                        dimensionDegreeMap.put(char(components{1,1}), char(components{1,3}));
                    end
                end
                fprintf(opFile2, '(- %s_%d_%d (mk-record', name, i, j);
                it = dimensionSet.iterator();
                while(it.hasNext())
                    key = it.next();
                    if dimensionDegreeMap.containsKey(key)
                        fprintf(opFile2, ' %s', dimensionDegreeMap.get(key));
                    else
                        fprintf(opFile2, ' 0');
                    end
                end
                fprintf(opFile2, '))\n');
                end
            end
        end
    end
end
 

function dim = getGotoDimensionSignature(desc, name, dimx, dimy)

    global dimensionSet;
    global dimensionDegreeMap;

    dimensionDegreeMap.clear();

    cells = regexp(desc, ':', 'split');
    str = cells{1,2};
    numberOfBars = length(strfind(str, '|'));
    numberOfParenthesis = length(strfind(str, '('));
    if (dimx ~= numberOfBars + 1)
        fprintf('Error: dimension definition does not match in the number of rows for %s\n', name);
    elseif (dimx * dimy ~= numberOfParenthesis)
        fprintf('Error: dimension definition does not match in the number of columns for %s\n', name);
    else
        str = regexprep(str, '[', '');
        str = regexprep(str, ']', '');
        if numberOfBars > 0
            rows = regexp(str, '\|', 'split');
        else
            rows = {str};
        end
        for i = 1:length(rows)
            columns = regexp(rows{1,i}, ')', 'split');
            for j = 1:length(columns) - 1
                dimensionDegreeMap.clear();
                dimcell = regexp(columns{1,j}, '(', 'split');
                dims = regexp(dimcell{1,2}, ',', 'split');
                if length(dims) == 1 && strcmp(dims{1,1}, 'unknown') == 1
                    fprintf('Error: dimension definition is unknown for %s\n', name);
                elseif length(dims) == 1 && strcmp(dims{1,1}, 'zero') == 1
                    dim = '1';
                    it = dimensionSet.iterator();
                    while(it.hasNext())
                        key = it.next();
                        dim = strcat(dim, '_0');
                    end
                else
                for k = 1: length(dims)
                    dim = dims{1,k};
                    dim = deblank(dim);
                    noofspaces = length(strfind(dim, ' '));
                    components = regexp(dim, ' ', 'split');
                    if noofspaces == 3
                        dimensionDegreeMap.put(char(components{1,2}), char(components{1,4}));
                    end
                    if noofspaces == 2
                        dimensionDegreeMap.put(char(components{1,1}), char(components{1,3}));
                    end
                end
                dim = '0';
                it = dimensionSet.iterator();
                while(it.hasNext())
                    key = it.next();
                    if dimensionDegreeMap.containsKey(key)
                        dim = strcat(dim, '_', dimensionDegreeMap.get(key));
                    else
                        dim = strcat(dim, '_', '0');
                    end
                end
                end
            end
        end
    end
end
 
 
 
 function [] = printTransitions(blks, syspath, modelName)

    global subsystemSet;
    global opFile3;
    
    for i=1:length(blks)
        handle = get_param(blks(i),'Handle');
        if iscell(handle)
            handle = handle{1,1};
        end
        name = get_param(blks(i),'Name');
        if iscell(name)
            name = name{1,1};
        end
        name = regexprep(name, '\s', '');
        parent = get_param(blks(i), 'Parent');
        if iscell(parent)
            parent = parent{1,1};
        end
        parent = regexprep(parent, '\s', '');
        type = get_param(blks(i),'BlockType');
        typestr = char(type);
        switch typestr
            case 'SubSystem'
                namestr = strcat(parent, (strcat('__', name))); 
                if not(subsystemSet.contains(namestr))
                    subsystemSet.add(namestr);
                    link_status = get_param(handle,'LinkStatus');
                    if (strcmp(link_status,'none') || strcmp(link_status,'inactive'))
                        subBlks = find_system(handle, 'SearchDepth', '1', 'type', 'Block');
                        sysPath = sprintf('%s/%s', parent, name);
                        printTransitions(subBlks(2:length(subBlks)), sysPath, modelName);
                    end
                end
        end
    end
 
    sysname = regexprep(syspath, '/', '__');
    
    fprintf(opFile3,'%s\n', sysname);
    
    for i=1:length(blks)
        handle = get_param(blks(i),'Handle');
        if iscell(handle)
            handle = handle{1,1};
        end
        printBlockInfo(handle, modelName);
    end

    printLineInfo(syspath);
    fprintf(opFile3, 'end\n\n\n');
 end
 
 
 function printLineInfo(sysPath)
 
     global lineNameSet;
     global transition;
     global opFile3;
     
     sigtrans = '';
     getGESignalTransitions(sysPath, '1');
     keys = transition.keySet();
     k = keys.iterator();
     while(k.hasNext())
         key = k.next();
         x  =  transition.get(key);
         for i = 1:x.size()
             str1 = x.get(i-1);
             str2 = key;
         
             str3 = regexp(str1, '__', 'split');    %This may be wrong
             dims = size(str3);

             numrows = 1;
             numcols = 1;
             
             if lineNameSet.contains(str2) == false
                if strfind(str2, 'Outstate')
                    str4 = regexp(str2, '__Outstate', 'split');
                else
                    flag = 0;
                    if strfind(str2, '__Out')
                        str4 = regexp(str2, '__Out\d+', 'split');
                        flag = 1;
                    else
                        str4 = {str2};
                    end
                end
                if flag == 1
                    blkValue = regexprep(str4{1,1}, '__', '/');
                else
                    blkValue = regexprep(str4{1,1}, '__In1', '');
                    blkValue = regexprep(blkValue, '__', '/');
                end
                handle = get_param(blkValue,'Handle');
                portHandles = get_param(handle,'PortHandles');
                try
                    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
                    [numrows, numcols] = getSignalDimension(outputDimensions);
                catch
                    % The block is Outport of a subsystem, does not have an
                    % Outport
                    try
                        inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                        [numrows, numcols] = getSignalDimension(inputDimensions);
                    catch
                    end
                end
             else
                 str4 = regexp(str1, '__In\d+', 'split');
                 %blkValue = regexprep(str4{1,1}, '__', '/');
                 blkValue = regexprep(str4{1,1}, '__Out1', '');
                 blkValue = regexprep(blkValue, '__', '/');
                 handle = get_param(blkValue,'Handle');
                 portHandles = get_param(handle,'PortHandles');
                 try
                     % The block is Inport of a subsystem, does not have an
                     % Inport
                     inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
                     [numrows, numcols] = getSignalDimension(inputDimensions);
                 catch
                     try
                         outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
                         [numrows, numcols] = getSignalDimension(outputDimensions);
                     catch
                     end
                 end
             end
             
             for i = 1 : numrows
                 for j = 1 : numcols
                     if dims(1,2) > 1
                         if strcmp(str3{1,2}, 'ifaction') == 0
                             sigtrans = sprintf('%s\n(- %s_%d_%d %s_%d_%d)', sigtrans, str1, i, j, str2, i, j);
                         end
                     else
                         sigtrans = sprintf('%s\n(- %s_%d_%d %s_%d_%d)', sigtrans, str1, i, j, str2, i, j);
                     end
                 end
             end
         end
     end

     fprintf(opFile3,'%s\n', sigtrans);
 end

 
function printBlockInfo(handle, modelName)

     global opFile3;
     
     type = char(get_param(handle, 'BlockType'));
     
     name = char(get_param(handle, 'Name'));
     name = regexprep(name, '\s', '');
     parent = char(get_param(handle, 'Parent'));
     parent = regexprep(parent, '\s', '');
     parent = regexprep(parent, '/', '__');
     

     switch type
         
         % Sources and Sinks
         case {'Constant'}
         case {'Inport', 'Sin', 'Step', 'FromWorkspace', 'From', 'Ground'}
         case {'Outport', 'Scope', 'Terminator', 'Goto', 'Display', 'ToWorkspace'}
             
         % User-Defined Functions
         case {'Fcn', 'S-Function'}
             
         % Ports & Subsystems
         case {'SubSystem', 'If', 'EnablePort', 'TriggerPort', 'ActionPort'}
             
         % Signal Routing    
         case {'BusSelector'}
             
         % Lookup Tables
         case {'Lookup'}
             
         % Math Operations
         case {'Abs'}   % same as Memory
             printMemory(handle, opFile3);
         case {'UnaryMinus'}    % same as Memory
             printMemory(handle, opFile3);
         case {'Sum'}
             printSum(handle, opFile3);
         case {'Product'}
             printProduct(handle, opFile3);
         case {'Gain'}
             printGain(handle, opFile3);
         case {'DotProduct'}
             printDotProduct(handle, opFile3);
         case {'MinMax'}
             printMinMax(handle, opFile3);
         case {'Trigonometry'}
             printTrigonometry(handle, opFile3);
         case {'Concatenate'}
             printConcatenate(handle, opFile3);
         case {'Reshape'}
             printReshape(handle, opFile3);
         case {'Signum'}    % same as Relay
             printRelay(handle, opFile3);

             
         % Logic and Bit Operations
         case {'Logic'}
             printLogicalOperator(handle, opFile3);
         case {'RelationalOperator'}
             printRelationalOperator(handle, opFile3);
         case {'CombinatorialLogic'}
             printCombinatorialLogic(handle, opFile3);
             
         % Signal Routing    
         case {'Switch'}
             printSwitch(handle, opFile3);
         case {'MultiPortSwitch'}
             printMultiPortSwitch(handle, opFile3);
         case {'Mux'}
             printMux(handle, opFile3);
         case {'Demux'}
             printDemux(handle, opFile3);
         case {'Selector'}
             printSelector(handle, opFile3);
         case {'Merge'}     % same as Sum
             printSum(handle, opFile3);
             
         % Signal Attributes
         case {'InitialCondition'}  
             printMemory(handle, opFile3);
             
         % Discrete    
         case {'Memory'} 
             printMemory(handle, opFile3);
         case {'UnitDelay'}     %same as Memory
             printMemory(handle, opFile3);
         case {'DiscreteIntegrator'}    % same as Integrator
             printIntegrator(handle, opFile3);    
             
         % Continuous    
         case {'Integrator'} 
             printIntegrator(handle, opFile3);
             
         % Discontinuous
         case {'Saturate'}
             printSaturate(handle, opFile3);
         case {'Relay'}       
             printRelay(handle, opFile3);
         case {'HitCross'}  % same as Relay
             printRelay(handle, opFile3);   
             
         % Ports & Subsystems
         case {'Reference'}
             printReference(handle, modelName, opFile3);
         otherwise
             fprintf('The block %s_%s of type %s is not supported..\n', parent, name, type);
     end
 end
 

function [] = printSum(handle, opfile)
    
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');

    inNames = getInputNames(handle);
    outNames = getOutputNames(handle);
    
    portHandles = get_param(handle, 'PortHandles');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
    [numrows, numcols] = getSignalDimension(outputDimensions);
    
    for i = 1 : numrows
        for j = 1 : numcols
            fprintf(opfile,'(- %s__%s_%d_%d %s__%s_%d_%d)\n', parent, char(outNames(1)), i, j, parent, char(inNames(1)), i, j);
        end
    end
    ports = get_param(handle,'Ports');
    for k = 2:ports(1,1)
        for i = 1 : numrows
            for j = 1 : numcols
                fprintf(opfile, '(- %s__%s_%d_%d %s__%s_%d_%d)\n', parent, char(inNames(1)), i, j, parent, char(inNames(k)), i, j);
            end
        end
    end
end


function [] = printProduct(handle, opfile) 
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    inNames = getInputNames(handle);
    outNames = getOutputNames(handle);
    
    inputs = get_param(handle,'Inputs');
    x = (length(inNames));
    
    if strcmp(inputs, num2str(x))
        signs = '';
        for i = 1 : (x(1,1))
            signs = strcat(signs,'*');
        end
    else
        signs = inputs;
    end
    
    portHandles = get_param(handle,'PortHandles');
    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions'); 
    multiplicationType = char(get_param(handle, 'Multiplication'));
    
    if strcmp(multiplicationType, 'Element-wise(.*)') == 1
        % We assume that all inputs have the same dimension
                   
        ports = get_param(handle,'Ports');
        if ports(1,1) == 1
            fprintf('Not Supported: Element-wise product of single input in %s__%s\n', parent, regexprep(char(outNames(1)), '__Out1', ''));
        end
        
        indims = inputDimensions{1,1};
        if length(indims) == 2
            numberOfRows = indims(length(indims));
            numberOfColumns = indims(length(indims) - 1);
        elseif length(indims) == 3
            numberOfRows = indims(length(indims) - 1) ;
            numberOfColumns = indims(length(indims));
        else
            fprintf('Error : Number of rows and columns cannot be found.. \n');
        end
        
        for k = 1 : numberOfRows
            for l = 1 : numberOfColumns
                fprintf(opfile,'(- %s__%s_%d_%d ', parent, char(outNames(1)), k, l);
                j = 1;
                
                for i = 1:ports(1,1)
                    if signs(i) == '*'
                        if i < ports(1,1)
                            fprintf(opfile, ' (+ %s__%s_%d_%d', parent, char(inNames(j)), k, l); j = j+1;
                        else
                            fprintf(opfile,' %s__%s_%d_%d', parent, char(inNames(j)), k, l); j = j+1;
                        end
                    elseif signs(i) == '/'
                        if i < ports(1,1)
                            fprintf(opfile,' (+ (inverse %s__%s_%d_%d)', parent, char(inNames(j)), k, l); j = j+1;
                        else
                            fprintf(opfile,' (inverse %s__%s_%d_%d)', parent, char(inNames(j)), k, l); j = j+1;
                        end
                    end
                end
                for i = 1:ports(1,1) - 1
                    fprintf(opfile, ')');
                end;
                fprintf(opfile, ')\n');
            end
        end
        
    end
    
    if strcmp(multiplicationType, 'Matrix(*)') == 1
        ports = get_param(handle,'Ports');
        if ports(1,1) == 1
            if length(signs) ~= 1
                fprintf('Error: Length of Inputs is wrong in %s__%s\n', parent, regexprep(char(outNames(1)), '__Out1', ''));
            end
            if signs(1) == '*'
                fprintf(opfile,'(- %s__%s %s__%s)\n', parent, char(outNames(1)), parent, char(inNames(1)));
            end
            if signs(1) == '/'
                numberOfRows = inputDimensions(length(inputDimensions) - 1) ;
                numberOfColumns = inputDimensions(length(inputDimensions));
                if numberOfRows ~= numberOfColumns
                    fprintf('Error: The input of %s__%s is not a square matrix\n', parent, regexprep(char(outNames(1)), '__Out1', ''));
                end
                for k = 1 : numberOfRows
                    for l = 1 : numberOfColumns
                        fprintf(opfile, '(- %s__%s_%d_%d (inverse %s__%s_%d_%d))\n', parent, char(outNames(1)), k, l, parent, char(inNames(1)), l, k);
                        if(l > 1)
                            fprintf(opfile, '(- %s__%s_%d_%d %s__%s_%d_1)\n', parent, char(inNames(1)), k, l, parent, char(inNames(1)), k);
                        end
                    end
                end
            end
        end
        
        if ports(1,1) >= 2
            
            %for i = 3 : ports(1,1)
            %    fprintf(opfile, '(define %s__%s__tmp%d:: (-> int int dim))\n', parent, name, i - 2);
            %end
            
            errorflag = 0;
            for i = 1:ports(1,1)
                if signs(i) == '/'
                    fprintf('Not Supported: Matrix inversion during matrix multiplication in %s__%s\n', parent, regexprep(char(outNames(1)), '__Out1', ''));
                    errorflag = 1;
                end
            end
            if errorflag == 0
                for i = 2 : ports(1,1)
                    if i == 2
                        % the first multiplication 
                        indims1 = inputDimensions{1,1};
                        indims2 = inputDimensions{2,1};    
                        errorflag = 0;
                        if indims1(length(indims1)) ~= indims2(length(indims2) - 1)
                            fprintf('Error: Dimension mismatch for input 1 and input 2 of %s__%s\n', parent, regexprep(char(outNames(1)), '__Out1', ''));
                            errorflag = 1;
                        end
                        if errorflag == 0
                            for k = 1 : indims1(length(indims1) - 1)
                                for l = 1 : indims2(length(indims2))
                                    if (i < ports(1,1))
%                                         fprintf(opfile, '(- %s__%s__tmp1_%d_%d', parent, name, k, l);
%                                         for m = 1 : indims1(length(indims1)) - 1
%                                            fprintf(opfile, ' (ite (not (is_zero (+ %s__%s_%d_%d %s__%s_%d_%d))) (+ %s__%s_%d_%d %s__%s_%d_%d)\n', ...
%                                                parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l, parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l);  
%                                         end
%                                         fprintf(opfile, ' (+ %s__%s_%d_%d %s__%s_%d_%d)', ...
%                                                parent, char(inNames(1)), k, m + 1, parent, char(inNames(2)), m + 1, l);
%                                         for m = 1 : indims1(length(indims1)) - 1
%                                             fprintf(opfile, ')');
%                                         end
%                                         fprintf(opfile, ')\n');
                                        for m = 1 : indims1(length(indims1))
                                           fprintf(opfile, '(- %s__%s__tmp1_%d_%d', parent, name, k, l); 
                                           fprintf(opfile, ' (+ %s__%s_%d_%d %s__%s_%d_%d))\n', parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l);  
                                        end
                                    else
%                                         fprintf(opfile, '(- %s__%s_%d_%d', parent, char(outNames(1)), k, l);
%                                         for m = 1 : indims1(length(indims1)) - 1
%                                            fprintf(opfile, ' (ite (not (is_zero (+ %s__%s_%d_%d %s__%s_%d_%d))) (+ %s__%s_%d_%d %s__%s_%d_%d)\n', ...
%                                                parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l, parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l);  
%                                         end
%                                         fprintf(opfile, ' (+ %s__%s_%d_%d %s__%s_%d_%d)', ...
%                                                parent, char(inNames(1)), k, m + 1, parent, char(inNames(2)), m + 1, l);
%                                         for m = 1 : indims1(length(indims1)) - 1
%                                             fprintf(opfile, ')');
%                                         end
%                                         fprintf(opfile, ')\n');
                                        for m = 1 : indims1(length(indims1))
                                           fprintf(opfile, '(- %s__%s_%d_%d', parent, char(outNames(1)), k, l); 
                                           fprintf(opfile, ' (+ %s__%s_%d_%d %s__%s_%d_%d))\n', parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l);  
                                        end
                                    end
                                    for m = 1 : indims1(length(indims1))
                                        for n = m + 1 : indims1(length(indims1))
%                                             fprintf(opfile, '(- (+ %s__%s_%d_%d %s__%s_%d_%d)) \n    (if (and (not (is_zero (+ %s__%s_%d_%d %s__%s_%d_%d))) (not (is_zero (+ %s__%s_%d_%d %s__%s_%d_%d))) ) \n        (+ %s__%s_%d_%d %s__%s_%d_%d) (+ %s__%s_%d_%d %s__%s_%d_%d)))\n', ...
%                                             parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l, parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l, parent, char(inNames(1)), k, n, parent, char(inNames(2)), n, l, parent, char(inNames(1)), k, n, parent, char(inNames(2)), n, l, parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l);      
                                            fprintf(opfile, '(- (+ %s__%s_%d_%d %s__%s_%d_%d) (+ %s__%s_%d_%d %s__%s_%d_%d))\n', ...
                                            parent, char(inNames(1)), k, m, parent, char(inNames(2)), m, l, parent, char(inNames(1)), k, n, parent, char(inNames(2)), n, l);      
                                        end
                                    end
                                end
                            end
                        end
                    elseif i == ports(1,1)
                        % the last multiplication
                        indims1 = inputDimensions{1,1};
                        indims2 = inputDimensions{i - 1,1};
                        indims3 = inputDimensions{i,1};    
                        errorflag = 0;
                        if indims2(length(indims2)) ~= indims3(length(indims3) - 1)
                            fprintf('Error: Dimension mismatch for input %d and input %d of %s__%s\n', ports(1,1) - 1, ports(1,1), parent, regexprep(char(outNames(1)), '__Out1', ''));
                            errorflag = 1;
                        end
                        if errorflag == 0
                            for k = 1 : indims1(length(indims1) - 1)
                                for l = indims3(length(indims3))
%                                     fprintf(opfile, '(- %s__%s_%d_%d', parent, char(outNames(1)), k, l);
%                                     for m = 1 : indims1(length(indims1)) - 1
%                                         fprintf(opfile, ' (ite (not (is_zero (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))) (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d)\n', ...
%                                             parent, name, ports(1,1) - 2, k, m, parent, char(inNames(i)), m, l, parent, name, ports(1,1) - 2, k, m, parent, char(inNames(i)), m, l);
%                                     end
%                                     fprintf(opfile, ' (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d)', ...
%                                         parent, name, ports(1,1) - 2, k, m + 1, parent, char(inNames(i)), m + 1, l);
%                                     for m = 1 : indims1(length(indims1)) - 1
%                                         fprintf(opfile, ')');
%                                     end
%                                     fprintf(opfile, ')\n');
                                    for m = 1 : indims1(length(indims1))
                                        fprintf(opfile, '(- %s__%s_%d_%d', parent, char(outNames(1)), k, l);
                                        fprintf(opfile, ' (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))\n', parent, name, ports(1,1) - 2, k, m, parent, char(inNames(i)), m, l);
                                    end
                                    for m = 1 : indims2(length(indims2))
                                        for n = m + 1 : indims2(length(indims2))
%                                             fprintf(opfile, '(- (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d) \n    (if (and (not (is_zero (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))) (not (is_zero (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))) ) \n        (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d) (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d)))\n', ...
%                                                 parent, name, ports(1,1) - 2, k, m, parent, char(inNames(i)), m, l, parent, name, ports(1,1) - 2, k, m, parent, char(inNames(i)), m, l, parent, name, ports(1,1) - 2, k, n, parent, char(inNames(i)), n, l, parent, name, ports(1,1) - 2, k, n, parent, char(inNames(i)), n, l, parent, name, ports(1,1) - 2, k, m, parent, char(inNames(i)), m, l);   
                                            fprintf(opfile, '(- (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d) (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))\n', ...
                                                parent, name, ports(1,1) - 2, k, m, parent, char(inNames(i)), m, l, parent, name, ports(1,1) - 2, k, n, parent, char(inNames(i)), n, l);   
                                        
                                        end
                                    end
                                end
                            end
                        end
                    else
                        % intermediate multiplications
                        indims1 = inputDimensions{1,1};
                        indims2 = inputDimensions{i - 1,1};
                        indims3 = inputDimensions{i,1};    
                        errorflag = 0;
                        if indims2(length(indims2)) ~= indims3(length(indims3) - 1)
                            fprintf('Error: Dimension mismatch for input %d and input %d of %s__%s\n', ports(1,1) - 1, ports(1,1), parent, regexprep(char(outNames(1)), '__Out1', ''));
                            errorflag = 1;
                        end
                        if errorflag == 0
                            for k = 1 : indims1(length(indims1) - 1)
                                for l = indims3(length(indims3))
%                                     fprintf(opfile, '(- %s__%s__tmp%d_%d_%d', parent, name, i - 1, k, l);
%                                     for m = 1 : indims1(length(indims1)) - 1
%                                         fprintf(opfile, ' (ite (not (is_zero (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))) (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d)\n', ...
%                                             parent, name, i - 2, k, m, parent, char(inNames(i)), m, l, parent, name, i - 2, k, m, parent, char(inNames(i)), m, l);
%                                     end
%                                     fprintf(opfile, ' (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d)', ...
%                                         parent, name, i - 2, k, m + 1, parent, char(inNames(i)), m + 1, l);
%                                     for m = 1 : indims1(length(indims1)) - 1
%                                         fprintf(opfile, ')');
%                                     end
                                    for m = 1 : indims1(length(indims1))
                                        fprintf(opfile, '(- %s__%s__tmp%d_%d_%d', parent, name, i - 1, k, l);
                                        fprintf(opfile, '(+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))\n', parent, name, i - 2, k, m, parent, char(inNames(i)), m, l);
                                    end
                                    for m = 1 : indims2(length(indims2))
                                        for n = m + 1 : indims2(length(indims2))
%                                             fprintf(opfile, '(- (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d) \n    (if (and (not (is_zero (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))) (not (is_zero (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))) ) \n        (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d) (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d)))\n', ...
%                                             parent, name, i - 2, k, m, parent, char(inNames(i)), m, l, parent, name, i - 2, k, m, parent, char(inNames(i)), m, l, parent, name, i - 2, k, n, parent, char(inNames(i)), n, l, parent, name, i - 2, k, n, parent, char(inNames(i)), n, l, parent, name, i - 2, k, m, parent, char(inNames(i)), m, l);   
                                            fprintf(opfile, '(- (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d) (+ %s__%s__tmp%d_%d_%d %s__%s_%d_%d))\n', ...
                                            parent, name, i - 2, k, m, parent, char(inNames(i)), m, l, parent, name, i - 2, k, n, parent, char(inNames(i)), n, l);   
                                        end
                                    end

                                end
                            end
                        end    
                    end
                end
            end
        end
    end
end



function [] = printGain(handle, opfile)

    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    portIn = sprintf('%s__%s%s', parent, name, '__In1');
    portOut = sprintf('%s__%s%s', parent, name,'__Out1');
    portConstant = sprintf('%s__%s%s', parent, name,'__Constant');
    portHandles = get_param(handle,'PortHandles');
    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions'); 
    
    indims = inputDimensions;
    if length(indims) == 2
        numberOfInputRows = indims(length(indims));
        numberOfInputColumns = indims(length(indims) - 1);
    elseif length(indims) == 3
        numberOfInputRows = indims(length(indims) - 1) ;
        numberOfInputColumns = indims(length(indims));
    else
        fprintf('Error : Number of rows and columns cannot be found for %s\n', portIn);
    end
    
    outdims = outputDimensions;
    if length(outdims) == 2
        numberOfOutputRows = outdims(length(outdims));
        numberOfOutputColumns = outdims(length(outdims) - 1);
    elseif length(outdims) == 3
        numberOfOutputRows = outdims(length(outdims) - 1) ;
        numberOfOutputColumns = outdims(length(outdims));
    else
        fprintf('Error : Number of rows and columns cannot be found for %s\n', portOut);
    end
    
    errorflag = 0;
    if numberOfInputRows ~= numberOfOutputRows
        fprintf('Error: Dimension mismatch for input and output of %s\n', regexprep(portOut, '__Out1', ''));
        errorflag = 1;
    end
    if errorflag == 0
        for k = 1 : numberOfOutputRows
            for l = 1: numberOfOutputColumns
                fprintf(opfile, '(- %s_%d_%d (+ %s_%d_%d %s_%d_%d))\n', ...
                    portOut, k, l, portIn, k, 1, portConstant, 1, l);
                for m = 2 : numberOfInputColumns
                    fprintf(opfile, '(- (+ %s_%d_%d %s_%d_%d) (+ %s_%d_%d %s_%d_%d))\n', ...
                        portIn, k, 1, portConstant, k, l, portIn, k, m, portConstant, m, l);
                end
            end
        end
    end
end



function [] = printDotProduct(handle, opfile)
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');

    inNames = getInputNames(handle);
    portOut = sprintf('%s__%s%s', parent, name,'__Out1');

    fprintf(opfile, '(- %s_1_1 (+ %s__%s_1_1 %s__%s_1_1))\n', portOut, parent, char(inNames(1)), parent, char(inNames(2)));
    %fprintf(opfile, '(- %s__%s_1_1 (if (and (not (is_zero %s__%s_1_1)) (not (is_zero %s__%s_1_1))) %s__%s_1_1 %s__%s_1_1))\n', parent, char(inNames(1)), parent, char(inNames(1)), parent, char(inNames(2)), parent, char(inNames(2)), parent, char(inNames(1)));
    fprintf(opfile, '(- %s__%s_1_1  %s__%s_1_1)\n', parent, char(inNames(1)), parent, char(inNames(2)));
end



function [] = printMinMax(handle, opfile)
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');

    inNames = getInputNames(handle);
    portOut = sprintf('%s__%s%s', parent, name,'__Out1');
        
    ports = get_param(handle,'Ports');
    for i = 1:ports(1,1)
        %fprintf(opfile,'(- %s_1_1 (if (not (is_zero %s__%s_1_1)) %s__%s_1_1 %s_1_1))\n', portOut, parent, char(inNames(i)), parent, char(inNames(i)), portOut);
        fprintf(opfile,'(- %s_1_1 %s__%s_1_1)\n', portOut, parent, char(inNames(i)));
    end

    for i = 1 : ports(1,1)
        for j = (i + 1) : ports(1,1)
            %fprintf(opfile,'(- %s__%s_1_1 (if (and (not (is_zero %s__%s_1_1)) (not (is_zero %s__%s_1_1))) %s__%s_1_1 %s__%s_1_1))\n', parent, char(inNames(i)), parent, char(inNames(i)), parent, char(inNames(i)), parent, char(inNames(j)), parent, char(inNames(j)), parent, char(inNames(i)));
            fprintf(opfile,'(- %s__%s_1_1 %s__%s_1_1)\n', parent, char(inNames(i)), parent, char(inNames(j)));
        end
    end
end


function [] = printTrigonometry(handle, opfile) 

    global dimensionSet;

    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn = sprintf('%s__%s%s', parent, name, '__In1');
    portOut = sprintf('%s__%s%s', parent, name,'__Out1');
    
    fprintf(opfile, '(- %s_1_1 (mk-record', portIn);
    it = dimensionSet.iterator();
    while(it.hasNext())
        key = it.next();
        if strcmp(key, 'angle') == 1
            fprintf(opfile, ' 1');
        else
            fprintf(opfile, ' 0');
        end
    end
    fprintf(opfile, '))\n');

    fprintf(opfile, '(- %s_1_1 (mk-record', portOut);
    it = dimensionSet.iterator();
    while(it.hasNext())
        key = it.next();
        fprintf(opfile, ' 0');
    end
    fprintf(opfile, '))\n');
end


function [] = printConcatenate(handle, opfile)
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    ports = get_param(handle,'Ports');
    for i = 1 : ports(1,1)
        portIn(i) = {sprintf('%s__%s__In%d', parent, name, i)};
    end
    portOut = sprintf('%s__%s__Out1', parent, name);
  
    ports = get_param(handle,'Ports');
    if strcmp(char(get_param(handle, 'Mode')), 'Vector')
        for i = 1: ports(1,1)
            fprintf(opfile, '(- %s_%d_1  %s_1_1)\n', portOut, i, char(portIn(i)));
        end
    else
        portHandles = get_param(handle,'PortHandles');
        inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
        outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');      

        if strcmp(char(get_param(handle, 'ConcatenateDimension')), '1')            
            m = 1;
            n = 1;
            if iscell(inputDimensions)
                for j = 1 : length(inputDimensions)
                    indims = inputDimensions{j,1};
                    if length(indims) == 2
                        numberOfRows = indims(length(indims));
                        numberOfColumns = indims(length(indims) - 1);
                    elseif length(indims) == 3
                        numberOfRows = indims(length(indims) - 1) ;
                        numberOfColumns = indims(length(indims));
                    else
                        fprintf('Error: Number of rows and columns cannot be found.. \n');
                    end
                    
                    for k = 1 : numberOfRows
                        for l = 1 : numberOfColumns
                            fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, m, n, char(portIn(j)), k, l);
                            n = n + 1;
                        end
                        m = m + 1;
                        if outputDimensions(length(outputDimensions)) ~= n - 1
                            fprintf('Error: Output dimension mismatch in number of columns for block %s\n', regexprep(portOut, '__Out1', ''));
                        end
                        n = 1;
                    end
                end
                if outputDimensions(length(outputDimensions) - 1) ~= m -1
                    fprintf('Error: Output dimension mismatch in number of rows for block %s\n', regexprep(portOut, '__Out1', ''));
                end
            else
                % only one input, dummy concatenation
                for k = 1 : inputDimensions(length(inputDimensions) - 1)
                    for l = 1 : inputDimensions(length(inputDimensions))
                        fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, m, n, char(portIn(1)), k, l);
                        n = n + 1;
                    end
                    if outputDimensions(length(outputDimensions)) ~= n - 1
                        fprintf('Error: Output dimension mismatch in number of columns for block %s\n', regexprep(portOut, '__Out1', ''));
                    end
                    m = m + 1;
                    n = 1;
                end
                if outputDimensions(length(outputDimensions) - 1) ~= m -1
                    fprintf('Error: Output dimension mismatch in number of rows for block %s\n', regexprep(portOut, '__Out1', ''));
                end
            end
        else
            m = 1;
            startn = 1;
            if iscell(inputDimensions)
                for j = 1 : length(inputDimensions)
                    n = startn;
                    indims = inputDimensions{j,1};
                    if length(indims) == 2
                        numberOfRows = indims(length(indims));
                        numberOfColumns = indims(length(indims) - 1);
                    elseif length(indims) == 3
                        numberOfRows = indims(length(indims) - 1) ;
                        numberOfColumns = indims(length(indims));
                    else
                        fprintf('Error : Number of rows and columns cannot be found.. \n');
                    end
                        
                    for k = 1 : numberOfRows
                        for l = 1 : numberOfColumns
                            fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, m, n, char(portIn(j)), k, l);
                            n = n + 1;
                        end
                        m = m + 1;
                        n = startn;
                    end
                    
                    if outputDimensions(length(outputDimensions) - 1) ~= m - 1
                        fprintf('Output dimension mismatch in number of rows for block %s\n', regexprep(portOut, '__Out1', ''));
                    end
                    m = 1;
                    startn = startn + numberOfColumns; 
                end
                if outputDimensions(length(outputDimensions)) ~= startn -1
                    fprintf('Error: Output dimension mismatch in number of columns for block %s\n', regexprep(portOut, '__Out1', ''));
                end
            else
                % only one input, dummy concatenation
                n = 1;
                for k = 1 : inputDimensions(length(inputDimensions) - 1)
                    for l = 1 : inputDimensions(length(inputDimensions))
                        fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, m, n, char(portIn(1)), k, l);
                        n = n + 1;
                    end
                    m = m + 1;
                    if outputDimensions(length(outputDimensions)) ~= n - 1
                        fprintf('Error: Output dimension mismatch in number of columns for block %s\n', regexprep(portOut, '__Out1', ''));
                    end
                    n = 1;
                end
                if outputDimensions(length(outputDimensions) - 1) ~= m - 1
                    fprintf('Error: Output dimension mismatch in number of rows for block %s\n', regexprep(portOut, '__Out1', ''));
                end
            end 
        end
    end
end     



function [] = printReshape(handle, opfile)
    % Currently supports only transpose type of reshape
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn = sprintf('%s__%s__In1', parent, name);
    portOut = sprintf('%s__%s__Out1', parent, name);
    
    portHandles = get_param(handle,'PortHandles');
    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
        
    switch char(get_param(handle, 'OutputDimensionality'))
        case 'Customize'
            str = regexp(char(get_param(handle, 'OutputDimensions')), '[', 'split');
            str = regexp(str{1,2}, ',', 'split');
            outdimx = str2num(str{1,1});
            str = regexp(str{1,2}, ']', 'split');
            outdimy = str2num(str{1,1});
            if inputDimensions(length(inputDimensions) - 1) * inputDimensions(length(inputDimensions)) ~= outdimx * outdimy
                fprintf('Error: Output dimensions do not match with input dimensions.. \n');
            end
            m =1;
            n = 1;
            for k = 1 : inputDimensions(length(inputDimensions) - 1)
                for l = 1 : inputDimensions(length(inputDimensions))
                    fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, m, n, portIn, k, l);
                    n = n + 1;
                    if outdimy == n - 1
                        n = 1;
                        m = m + 1;
                    end
                end
            end
        otherwise
            fprintf('Reshape block with output dimensionality %s is not spported\n', char(get_param(handle, 'OutputDimensionality')));
    end
end


function [] = printLogicalOperator(handle, opfile)
% 
%     global dimensionSet;
%         
%     name = char(get_param(handle, 'Name'));
%     name = regexprep(name, '\s', '');
%     parent = char(get_param(handle, 'Parent'));
%     parent = regexprep(parent, '\s', '');
%     parent = regexprep(parent, '/', '__');    
%     
%     portOut = sprintf('%s__%s__Out1', parent, name);
%     fprintf(opfile, '(- %s_1_1 (mk-record', portOut);
%     it = dimensionSet.iterator();
%     while(it.hasNext())
%         key = it.next();
%         fprintf(opfile, ' 0');
%     end
%     fprintf(opfile, '))\n');
end


function [] = printRelationalOperator(handle, opfile)

%    global dimensionSet;
        
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');

    inNames = getInputNames(handle);
    portOut = sprintf('%s__%s__Out1', parent, name);
    ports = get_param(handle,'Ports');
    for i = 1 : ports(1,1)
        for j = i + 1 : ports(1,1)
            %fprintf(opfile,'(- %s__%s_1_1 (if (and (not (is_zero %s__%s_1_1)) (not (is_zero %s__%s_1_1))) %s__%s_1_1 %s__%s_1_1))\n', parent, char(inNames(i)), parent, char(inNames(i)), parent, char(inNames(j)), parent, char(inNames(j)), parent, char(inNames(i)));
            fprintf(opfile, '(- %s__%s_1_1 %s__%s_1_1)\n', parent, char(inNames(i)), parent, char(inNames(j)));
        end
    end
    
%     portOut = sprintf('%s__%s__Out1', parent, name);
%     fprintf(opfile, '(- %s_1_1 (mk-record', portOut);
%     it = dimensionSet.iterator();
%     while(it.hasNext())
%         key = it.next();
%         fprintf(opfile, ' 0');
%     end
%     fprintf(opfile, '))\n');
end


function [] = printCombinatorialLogic(handle, opfile)

%     global dimensionSet;
%     
%     name = char(get_param(handle, 'Name'));
%     name = regexprep(name, '\s', '');
%     parent = char(get_param(handle, 'Parent'));
%     parent = regexprep(parent, '\s', '');
%     parent = regexprep(parent, '/', '__');
%     
%     portIn = sprintf('%s__%s__In1', parent, name);
%     portOut = sprintf('%s__%s__Out1', parent, name);
%     
%     portHandles = get_param(handle,'PortHandles');
%     inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
%     
%     for i = 1:inputDimensions(1,2)
%         fprintf(opfile, '(- %s_%d_1 (mk-record', portIn, i);
%         it = dimensionSet.iterator();
%         while(it.hasNext())
%             key = it.next();
%             fprintf(opfile, ' 0');
%         end
%         fprintf(opfile, '))\n');
%     end
%     
%     fprintf(opfile, '(- %s_1_1 (mk-record ', portOut, portOut);
%     it = dimensionSet.iterator();
%     while(it.hasNext())
%         key = it.next();
%         fprintf(opfile, ' 0');
%     end
%     fprintf(opfile, '))\n');
end

     

function [] = printSwitch(handle, opfile)
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn1 = sprintf('%s__%s__In1', parent, name);
    portIn2 = sprintf('%s__%s__In2', parent, name);
    portIn3 = sprintf('%s__%s__In3', parent, name);
    portOut = sprintf('%s__%s__Out1', parent, name);
    
    portHandles = get_param(handle,'PortHandles');
    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
    
    indims = inputDimensions{1,1};    
    if length(indims) == 2
        numberOfRows = indims(length(indims));
        numberOfColumns = indims(length(indims) - 1);
    elseif length(indims) == 3
        numberOfRows = indims(length(indims) - 1) ;
        numberOfColumns = indims(length(indims));
    else
        fprintf('Error : Number of rows and columns cannot be found.. \n');
    end
    
    for i = 1:numberOfRows
        for j = 1:numberOfColumns            
            %fprintf(opfile,'(- %s_%d_%d (ite (and (not (is_zero %s_%d_%d)) (not (is_zero %s_%d_%d))) %s_%d_%d %s_%d_%d))\n', ...
            %    portIn1, i, j, portIn1, i, j, portIn3, i, j, portIn3, i, j, portIn1, i, j);
            fprintf(opfile,'(- %s_%d_%d %s_%d_%d)\n', portIn1, i, j, portIn3, i, j);
        end
    end
% Need to be taken care later    
%    fprintf(opfile, '(- %s %s__%s__Threshold)\n', portIn2, parent, name);

    for i = 1:numberOfRows
        for j = 1:numberOfColumns           
%             fprintf(opfile,'(- %s_%d_%d (ite (not (is_zero %s_%d_%d)) %s_%d_%d %s_%d_%d))\n', ...
%                 portOut, i, j, portIn1, i, j, portIn1, i, j, portOut, i, j);
%             fprintf(opfile,'(- %s_%d_%d (ite (not (is_zero %s_%d_%d)) %s_%d_%d %s_%d_%d))\n', ...
%                 portOut, i, j, portIn3, i, j, portIn3, i, j, portOut, i, j);
%             fprintf(opfile,'(- %s_%d_%d (ite (and (is_zero %s_%d_%d) (is_zero %s_%d_%d)) zero', portOut, i, j, portIn1, i, j, portIn3, i, j);
%             fprintf(opfile, '%s_%d_%d))\n', portOut, i, j);
            fprintf(opfile,'(- %s_%d_%d %s_%d_%d)\n', portOut, i, j, portIn1, i, j);
            fprintf(opfile,'(- %s_%d_%d %s_%d_%d)\n', portOut, i, j, portIn3, i, j);
        end
    end
end


function [] = printRelay(handle, opfile)

%     global dimensionSet;
%     
%     name = char(get_param(handle, 'Name'));
%     name = regexprep(name, '\s', '');
%     parent = char(get_param(handle, 'Parent'));
%     parent = regexprep(parent, '\s', '');
%     parent = regexprep(parent, '/', '__');
%     
%     portOut = sprintf('%s__%s__Out1', parent, name);
%     fprintf(opfile, '(- %s_1_1 (mk-record', portOut);
%     it = dimensionSet.iterator();
%     while(it.hasNext())
%         key = it.next();
%         fprintf(opfile, ' 0');
%     end
%     fprintf(opfile, '))\n');
end


function [] = printMultiPortSwitch(handle, opfile )
    
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    inNames = getInputNames(handle);
    outNames = getOutputNames(handle);
    
    portHandles = get_param(handle, 'PortHandles');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
    [numrows, numcols] = getSignalDimension(outputDimensions);
    
    for i = 1 : numrows
        for j = 1 : numcols
            fprintf(opfile, '(- %s__%s_%d_%d %s__%s_%d_%d)\n', parent, char(outNames(1)), i, j, parent, char(inNames(2)), i, j);
        end
    end

    ports = get_param(handle,'Ports');
    for k = 3:ports(1,1)
        for i = 1 : numrows
            for j = 1 : numcols
                fprintf(opfile, '(- %s__%s_%d_%d %s__%s_%d_%d)\n', parent, char(inNames(2)), i, j, parent, char(inNames(k)), i, j);
            end
        end
    end;
end


function [] = printMux(handle, opfile)
    
    % We assume that the inputs are scalars and the output is a column
    % vector
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    inNames = getInputNames(handle);
    portOut = sprintf('%s__%s%s', parent, name, '__Out1');
    ports = get_param(handle,'Ports');
    
    portHandles = get_param(handle, 'PortHandles');
    inputDimensions = get_param(portHandles.Inport,'CompiledPortDimensions');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
    [numrowsout, numcolsout] = getSignalDimension(outputDimensions, portOut);
    numcolsout = 1;
    outcount = 1;
    for k = 1:ports(1,1)
        indims = inputDimensions{k,1};
        [numrowsin, numcolsin] = getSignalDimension(inputDimensions, char(inNames(k)));
        for i = 1 : numrowsin
            for j = 1 : numcolsin
                portIn = sprintf('%s__%s_%d_%d', parent, char(inNames(k)), i, j);
                fprintf(opfile, '(- %s_%d_1 %s)\n', portOut, outcount, portIn);
                outcount = outcount + 1;
            end
        end
    end
end


function [] = printDemux(handle, opfile)
    
    % We assume that the input is a column vector and the outputs are
    % scalars
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn = sprintf('%s__%s%s', parent, name, '__In1');
    outNames = getOutputNames(handle);
    ports = get_param(handle,'Ports');
    for i = 1:ports(1,2)
        portOut = sprintf('%s__%s', parent, char(outNames(i)));
        fprintf(opfile, '(- %s_1_1 %s_%d_1)\n', portOut, portIn, i);
    end
end


function [] = printSelector(handle, opfile)
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn = sprintf('%s__%s__In1', parent, name);
    portOut = sprintf('%s__%s__Out1', parent, name);
    
    portHandles = get_param(handle,'PortHandles');
    indices = regexp(char(get_param(handle, 'Indices')), ',', 'split');

    if strfind(indices{1,1}, ':')
        rowindices = regexprep(indices{1,1}, '[', '');
        rowindices = regexprep(rowindices, ']', '');
        rowindices = regexp(rowindices, ':', 'split');
        if strcmp(char(get_param(handle, 'IndexMode')), 'Zero-based') == 1
            rowstart = str2num(rowindices{1,1}) + 1;
            rowend = str2num(rowindices{1,2}) + 1;
        end
        if strcmp(char(get_param(handle, 'IndexMode')), 'One-based') == 1
            rowstart = str2num(rowindices{1,1});
            rowend = str2num(rowindices{1,2});
        end
    else
        if strcmp(char(get_param(handle, 'IndexMode')), 'Zero-based') == 1
            rowstart = str2num(indices{1,1}) + 1;
            rowend = str2num(indices{1,1}) + 1;
        end
        if strcmp(char(get_param(handle, 'IndexMode')), 'One-based') == 1
            rowstart = str2num(indices{1,1});
            rowend = str2num(indices{1,1});
        end
    end
    if strfind(indices{1,2}, ':')
        columnindices = regexprep(indices{1,2}, '[', '');
        columnindices = regexprep(columnindices, ']', '');
        columnindices = regexp(columnindices, ':', 'split');
        columnindices{1,1};
        columnindices{1,2};
        if strcmp(char(get_param(handle, 'IndexMode')), 'Zero-based') == 1
            columnstart = str2num(columnindices{1,1}) + 1;
            columnend = str2num(columnindices{1,2}) + 1;
        end
        if strcmp(char(get_param(handle, 'IndexMode')), 'One-based') == 1
            columnstart = str2num(columnindices{1,1});
            columnend = str2num(columnindices{1,2});
        end
    else
        if strcmp(char(get_param(handle, 'IndexMode')), 'Zero-based') == 1
            columnstart = str2num(indices{1,2}) + 1;
            columnend = str2num(indices{1,2}) + 1;
        end
        if strcmp(char(get_param(handle, 'IndexMode')), 'One-based') == 1
            columnstart = str2num(indices{1,2});
            columnend = str2num(indices{1,2});
        end
    end
    
    
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
    
    if outputDimensions(length(outputDimensions) - 1) ~= rowend - rowstart + 1
        fprintf('Output dimension mismatch in number of rowss for block %s\n', regexprep(portOut, '__Out1', ''));
    end
    if outputDimensions(length(outputDimensions)) ~= columnend - columnstart + 1
        fprintf('Output dimension mismatch in number of columns for block %s\n', regexprep(portOut, '__Out1', ''));
    end
    
    m = rowstart;
    n = columnstart;
    for k = 1 : outputDimensions(length(outputDimensions) - 1)
        for l = 1 : outputDimensions(length(outputDimensions))
            fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, k, l, portIn, m, n);
            n = n + 1;
            if columnend == n - 1
                n = columnstart;
                m = m + 1;
            end
        end
    end  
end


function [] = printMemory(handle, opfile)  
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn = sprintf('%s__%s%s', parent, name, '__In1');
    portOut = sprintf('%s__%s%s', parent, name,'__Out1');
    
    portHandles = get_param(handle, 'PortHandles');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
    [numrows, numcols] = getSignalDimension(outputDimensions);
    
    for i = 1 : numrows
        for j = 1 : numcols
            fprintf(opfile,'(- %s_%d_%d %s_%d_%d)\n', portOut, i, j, portIn, i, j);
        end
    end
end


function [] = printIntegrator(handle, opfile) 

    global dimensionSet;
     
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn = sprintf('%s__%s%s', parent, name, '__In1');
    portInit = sprintf('%s__%s%s', parent, name, '__In2');
    portOut = sprintf('%s__%s%s', parent, name,'__Out1');
    it = dimensionSet.iterator();
    count = 0;
    while(it.hasNext())
        key = it.next();
        if strcmp(key, 'time') == 1
            break;
        else
            count = count + 1;
        end
    end
    fprintf(opfile,'(- %s_1_1 (increment %s_1_1 %d 1))\n', portOut, portIn, count);
    if strcmp(char(get_param(handle, 'InitialConditionSource')), 'external')
        fprintf(opfile, '(- %s_1_1 %s_1_1)\n', portOut, portInit);
    end
end


function [] = printSaturate(handle, opfile)
    
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    portIn1 = sprintf('%s__%s%s', parent, name, '__In1');
    portOut = sprintf('%s__%s%s', parent, name,'__Out1');
    
    portHandles = get_param(handle, 'PortHandles');
    outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
    [numrows, numcols] = getSignalDimension(outputDimensions);
    
    
    for i = 1 : numrows
        for j = 1 : numcols
            fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, i, j, portIn1, i, j);
        end
    end
end


function [] = printReference(handle, opfile)
     
    name = char(get_param(handle, 'Name'));
    name = regexprep(name, '\s', '');
    parent = char(get_param(handle, 'Parent'));
    parent = regexprep(parent, '\s', '');
    parent = regexprep(parent, '/', '__');
    
    switch char(get_param(handle, 'SourceType'))
        case 'Cross Product'
            portIn1 = sprintf('%s__%s%s', parent, name, '__In1');
            portIn2 = sprintf('%s__%s%s', parent, name, '__In2');
            portOut = sprintf('%s__%s%s', parent, name,'__Out1');


             portHandles = get_param(handle, 'PortHandles');
            outputDimensions = get_param(portHandles.Outport,'CompiledPortDimensions');
            [numrows, numcols] = getSignalDimension(outputDimensions);
            
            for i = 1 : numrows
                for j = 1 : numcols
                    fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portOut, portIn1);
                    fprintf(opfile, '(- %s_%d_%d %s_%d_%d)\n', portIn1, portIn1);
                end
            end
        otherwise
            printf('Reference block %s is not supported', char(get_param(handle, 'SourceType')));
    end
end


function [] = checkGotoFromConsistency()
    global gotoAddressMap;
    global gotoDimensionMap;
    global fromAddressMap;
    global fromDimensionMap;

    fromKeySet = fromDimensionMap.keySet();
    k1 = fromKeySet.iterator();
    while(k1.hasNext())
        fromKey = k1.next();
        gotoAddress = gotoAddressMap.get(fromKey);
        gotodim = gotoDimensionMap.get(fromKey);
        fromAddress = fromAddressMap.get(fromKey);
        fromdim = fromDimensionMap.get(fromKey);
        
        str1 = regexp(gotodim, '_', 'split');
        str2 = regexp(fromdim, '_', 'split');
        
        if str1{1,1} ~= '1' && str2{1,1} ~= '1' && strcmp(fromdim, gotodim) == 0 
            fprintf('DimensionError: The dimension of the From Block %s does not match with the dimension of the corresponding Goto block %s\n', fromAddress, gotoAddress);
        end
    end
end
    


function [] = printGEInputFiles()

    global mdlPathName;
    global dimensionSet;
    global opFile;
    global opFile1a;
    global opFile1b;
    global opFile1c;
    global opFile2;
    global opFile3;
    global opFile4;
    
    sysname = fgets(opFile4);
    while sysname ~= -1
        %filename = strcat(mdlPathName, strcat('ge/', strcat(sysname, '_ge')));
        filename = strcat(mdlPathName, strcat('ge/', sysname));
        opFile = fopen(filename, 'w');

        fprintf(opFile, ';; (define-type dim (record');
        it = dimensionSet.iterator();
        while(it.hasNext())
            key = it.next();
            fprintf(opFile, ' %s::int', key);            
        end
        fprintf(opFile, '))\n\n');
        
        fprintf(opFile, '(define-block\n  %s\n\n', sysname);
        
        fprintf(opFile, '  (\n');
        line = fgets(opFile1a);  
        while(strcmp(line, sysname) == 0)
            line = fgets(opFile1a);
        end;
        line = fgets(opFile1a);
        while(strncmp(line, 'end', 3) == 0)
            fprintf(opFile, '    %s', line);
            line = fgets(opFile1a);
        end
        fprintf(opFile, '  )\n\n');
        
        fprintf(opFile, '  (\n');
        line = fgets(opFile1b);  
        while(strcmp(line, sysname) == 0)
            line = fgets(opFile1b);
        end;
        line = fgets(opFile1b);
        while(strncmp(line, 'end', 3) == 0)
            fprintf(opFile, '    %s', line);
            line = fgets(opFile1b);
        end
        fprintf(opFile, '  )\n\n');
        
        fprintf(opFile, '  (\n');
        line = fgets(opFile1c);  
        while(strcmp(line, sysname) == 0)
            line = fgets(opFile1c);
        end;
        line = fgets(opFile1c);
        while(strncmp(line, 'end', 3) == 0)
            fprintf(opFile, '    %s', line);
            line = fgets(opFile1c);
        end
        fprintf(opFile, '  )\n\n');
        
        fprintf(opFile, '  (\n');
        line = fgets(opFile2);
        while(strcmp(line, sysname) == 0)
            line = fgets(opFile2);
        end;
        line = fgets(opFile2);
        while(strncmp(line, 'end', 3) == 0)
            fprintf(opFile, '    %s', line);
            line = fgets(opFile2);
        end
        fprintf(opFile, '\n');
        
        line = fgets(opFile3);
        while(strcmp(line, sysname) == 0)
            line = fgets(opFile3);
        end;
        line = fgets(opFile3);
        while(strncmp(line, 'end', 3) == 0)
            fprintf(opFile, '    %s', line);
            line = fgets(opFile3);
        end
        fprintf(opFile, '  )\n)');
        
        fclose(opFile);
        
        sysname = fgets(opFile4);
    end
end