📄 pvalidatefcnspec.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 + -