⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pvalidatefcnspec.m

📁 利用Stateflow 进行嵌入式代码开发很好用
💻 M
字号:
function pValidateFcnSpec(iStruct)
%PVALIDATEFCNSPEC Validate the function specification.
%

%   Copyright 2005 The MathWorks, Inc.
%   $File: $
%   $Revision: $
%   $Date:  $

% Parse the Function Spec to extract lhs, rhs, ...
infoStart = pGetFcnSpecInfo(iStruct.StartFcnSpec);
infoOutput = pGetFcnSpecInfo(iStruct.OutputFcnSpec);
infoTerm = pGetFcnSpecInfo(iStruct.TerminateFcnSpec);

% Validate each Function Spec
iValidateFcnSpecType(iStruct.StartFcnSpec, 'Start', infoStart)
iValidateFcnSpecType(iStruct.OutputFcnSpec, 'Output', infoOutput)
iValidateFcnSpecType(iStruct.TerminateFcnSpec, 'Terminate', infoTerm)

% Need to validate each IO info accross all Function Spec !!!
% The previous validation function ensures that input/output/parameter have:
%  - unique name
%  - a number starting from 1 monotically
%  - a valid data type
%  - a valid dimension
%
% Now, we have to ensure that for the same input/output/parameter, there
% is no different specification concerning the data type and the dimension.
allStartIOinfo = [infoStart.lhsIOinfo; infoStart.rhsIOinfo];
allOutputIOinfo = [infoOutput.lhsIOinfo; infoOutput.rhsIOinfo];
allTerminateIOinfo = [infoTerm.lhsIOinfo; infoTerm.rhsIOinfo];
allIOInfo = [allStartIOinfo; allOutputIOinfo; allTerminateIOinfo];

err = iValidateIOInfoAccrossFcnSpec(allIOInfo, 'u');
if ~isempty(err)
    error('LegacyCode:badFcnSpecification',...
        'Input port specifications: %s',err);
end

err = iValidateIOInfoAccrossFcnSpec(allIOInfo, 'y');
if ~isempty(err)
    error('LegacyCode:badFcnSpecification',...
        'Output port specifications: %s',err);
end

err = iValidateIOInfoAccrossFcnSpec(allIOInfo, 'p');
if ~isempty(err)
    error('LegacyCode:badFcnSpecification',...
        'Parameter specifications: %s',err);
end


%--------------------------------------------------------------------------
function iValidateFcnSpecType(fcnSpec, type, info)

% Validate IO information
allIOinfo = [info.lhsIOinfo; info.rhsIOinfo];
err = iValidateIOInfo(allIOinfo, 'u');
if ~isempty(err)
    error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
        'Bad input port argument in expression: ''%s''. %s', fcnSpec, err);
end

err = iValidateIOInfo(allIOinfo, 'y');
if ~isempty(err)
    error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
        'Bad output port argument in expression: ''%s''. %s', fcnSpec, err);
end

err = iValidateIOInfo(allIOinfo, 'p');
if ~isempty(err)
    error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
        'Bad parameter argument in expression: ''%s''. %s', fcnSpec, err);
end

% Verify lhs
info.lhsExprRem = regexprep(info.lhsExprRem, '\s*','');
if ~isempty(info.lhsExpr) && (~isempty(info.lhsExprRem) || size(info.lhsIOinfo, 1) > 1)
    error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
        'Bad assignment in expression: ''%s''.', fcnSpec);
end

if (isempty(info.lhsExpr)&& ~isempty(info.eqExpr)) || (~isempty(info.lhsExpr)&& isempty(info.eqExpr))
    error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
        'Bad assignment in expression: ''%s''.', fcnSpec);
end

% Validate rhs
info.rhsExprRem = regexprep(info.rhsExprRem, 'void', '', 'ignorecase');
[s, e, t] = regexpi(info.rhsExprRem, [',\s*(\w*\s*)*|(\w*\s*)*\s*,']);
for ii=1:length(t)
    if ~isempty(t{ii}) && t{ii}(1,1) <= t{ii}(1,2) % test for ML 14 
        badArg = info.rhsExprRem(t{ii}(1,1):t{ii}(1,2));
        error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
            'Argument ''%s'' not recognized in expression: ''%s''.', badArg, fcnSpec);        
    end
end

info.rhsExprRem = regexprep(info.rhsExprRem, '\s*\w*\s*\(\s*(,\s*)*\)', '', 'ignorecase');
if ~isempty(info.rhsExprRem)
    error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
        'Token (or expression) ''%s'' not recognized in expression: ''%s''.', info.rhsExprRem, fcnSpec);            
end

switch type
    case 'Output'
        if ~isempty(info.lhsIOinfo)
            if info.lhsIOinfo{1, 1} ~= 'y' || info.lhsIOinfo{1, 5}==1 % bad naeme or access by a pointer
                error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
                    ['Bad assignment in expression: ''%s''.'...
                        ' The return from the function must be assigned ',...
                        'to an output port value.'], fcnSpec);                
            end
        end
        
    case {'Start', 'Terminate'}
        if ~isempty(allIOinfo)
            idx1 = find(strcmp(allIOinfo(:,1), 'u'));
            idx2 = find(strcmp(allIOinfo(:,1), 'y'));
            if ~isempty(idx1) || ~isempty(idx2)
                error(sprintf('LegacyCode:bad%sFcnSpecification',type),...
                    ['During ''%s'' method, the legacy code cannot ',...
                        'acces input/output value or address.'], type);                                
            end
        end
        
    otherwise
        
end


%--------------------------------------------------------------------------
function err = iValidateIOInfo(ioInfo, token)
% Internal function

% Initialize output error
err = '';

% If no information then return
if isempty(ioInfo)
    return
end

% If token not found then return
idx = find(strcmp(ioInfo(:,1), token));
if isempty(idx)
    return
end

% Extract only info concerning token
ioInfo = ioInfo(idx,:);

% Validate input/output/parameter number are unique
portNum = cell2mat(ioInfo(:,2));
[num, idx1, idx2] = unique(portNum);
if length(idx1)~=length(idx2)
    err = 'Function argument names must be unique.';
    return
end

% Validate supported DataTypes
dataType = pGetCDataTypes;
idx = find(cellfun('isempty', ioInfo(:,3)));
if ~isempty(idx)
    err = sprintf('Data types must by specified ''%s''.', ioInfo{idx(1),6});
end
badDataType = setdiff(ioInfo(:,3), dataType);
if ~isempty(badDataType)
    err = sprintf('Non-supported data type ''%s''.', badDataType{1});
    return
end

% Validate input/output/parameter dimension
nDimAllowed = 0;
if strcmp(lower(token), 'p')
    nDimAllowed = 1;
end

dynSizeAllowed = 1;
if strcmp(lower(token), 'y')
    dynSizeAllowed = 0;
end

for ii=1:size(ioInfo, 1)
    
    dim = ioInfo{ii,4};
    if length(dim) > 1 && nDimAllowed == 0
        err = ['The number of dimensions for an input or an output must be <2 ',...
                '(',ioInfo{ii,6},').'];
        return
    end
    
    idx = find(dim==-1);
    if ~isempty(idx) 
        if dynSizeAllowed==0
            err = ['An ouput cannot be dynamically sized :',...
                '(',ioInfo{ii,6},').'];
        end
        if ~all(dim==-1)
            err = ['When specifying dynamically sized, all dimensions must be dynamically sized: ',...
                '(',ioInfo{ii,6},').'];
        end        
    end
    
    idx = find(dim(find(dim ~= -1)) <= 0);
    if ~isempty(idx)
        err = ['The dimension specifications must be empty (for dynamically sized) or > 0 :',...
                '(',ioInfo{ii,6},').'];
        return
    end    
end


%--------------------------------------------------------------------------
function err = iValidateIOInfoAccrossFcnSpec(ioInfo, token)
% Internal function

% Initialize output error
err = '';

% If no information then return
if isempty(ioInfo)
    return
end

% If token not found then return
idx = find(strcmp(ioInfo(:,1), token));
if isempty(idx)
    return
end

% Extract only info concerning token
ioInfo = ioInfo(idx,:);

% Validate all input/output/parameter number
portNum = cell2mat(ioInfo(:,2));

num = unique(portNum);
d = diff(num);
if isempty(d)
    d = 1;
end
if num(1)~=1 || max(d) > 1
    err = 'argument number must start at 1 and monotically increased.';
    return
end

% Search for non-unique number and verify data type and dimension
isTested = zeros(1,length(portNum));
for ii = 1:length(portNum)
    isTested(ii) = 1;
    refVar = ioInfo(ii, :);
    idx = find(portNum(ii+1:end)==portNum(ii)) + ii;
    for jj=1:length(idx)
        if isTested(idx(jj))
            continue
        end
        isTested(idx(jj)) = 1;
        tstVar = ioInfo(idx(jj), :);
        if ~strcmp(tstVar{1,3}, refVar{1,3}) || ... % test for same data type
                ~isempty(setdiff(tstVar{1,4}, refVar{1,4})) ... % test for same dimension
                
            err = 'the dimension and data type specifications must be the same accross all function specifications.';
            return
        end
    end
end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -