📄 bffparse.m
字号:
fname(ldimmatcht{1}(1, 1):ldimmatcht{1}(1, 1)));
fname = regexprep(fname, '\(.*\)', '');
end
% update known variables
if isfield(bffspec.Variables, fname)
bffspec.Variables.(fname) = max( ...
bffspec.Variables.(fname), ldim);
else
bffspec.Variables.(fname) = ldim;
end
% put loop struct into Loops
bffspec.Loops.(fname)(ldim) = lstruct;
% loops (end)
elseif strcmp(rstrtype, 'eloop')
% check if name matches last pushed name
if isempty(looplist) || ...
~strcmp(rstruct.varname, looplist{end})
error( ...
'BVQXtools:BadBFFSpec', ...
'Invalid LOOP (end) detected in rule %d.', ...
slc ...
);
end
% pop loop from looplist
looplist(end) = [];
% loops (exit)
elseif strcmp(rstrtype, 'xloop')
% check if name matches any current loops
if ...
isempty(looplist) || ...
~any(strcmp(rstruct.varname, looplist))
error( ...
'BVQXtools:BadBFFSpec', ...
'Invalid XLOOP token: ''%s''.', ...
rstruct.varname ...
);
end
% don't do anything else !!! (see at bloop)
% skip N rules
elseif strcmp(rstrtype, 'skipn')
% dim MUST be a simple number
if ~all(rstruct.dim > 47 & rstruct.dim < 58)
error( ...
'BVQXtools:BadBFFSpec', ...
'SKIPN requires a simple numeric dim.' ...
);
end
end
end
% put actrules at the end of ListOfFields
bffspec.ListOfFields(end + 1:end + length(actrules)) = actrules;
% list of magic tokens
case {'magic'}
% find "EndMagic" line
endline = llc + 1;
for slc = (lc + 2):llc
if ~isempty(regexpi(bfflines{slc}, '^endmagic'))
endline = slc - 1;
break;
end
end
blc = lc;
lc = endline + 1;
% invalid Magic
if lc > llc
error( ...
'BVQXtools:BadBFFSpec', ...
'Unclosed Magic block in specification.' ...
);
end
% list/table field separator
listsep = bffval;
% get rule headers
rhead = splittocell(bfflines{blc}, listsep, 0);
% build header struct
hstruct = struct;
for hfc = 1:length(rhead)
hfield = makelabel(rhead{hfc});
hstruct.(hfield) = hfc;
rhead{hfc} = hfield;
end
blc = blc + 1;
% bail out if invalid header given
if ~isfield(hstruct, 'name') || ...
~isfield(hstruct, 'range') || ...
~isfield(hstruct, 'type') || ...
~isfield(hstruct, 'magic')
error( ...
'BVQXtools:BadBFFSpec', ...
'Magic with bad headers.' ...
);
end
% get list of header field names (in their order)
hfields = fieldnames(hstruct);
nfields = length(hfields);
% build empty field list struct
fmagic = cell2struct(cell(0, 0, nfields), hfields, 3);
% check global fieldlist struct
tfields = fieldnames(bffspec.Magic);
% no rules yet -> OK
if isempty(tfields)
bffspec.Magic = fmagic;
% otherwise compare header fields
else
% assume no mismatch
headermismatch = false;
% check number of fields
if length(tfields) ~= length(hfields)
tfields = {};
headermismatch = true;
end
% only if still content in tfields, check names
for tfc = 1:length(tfields)
if ~strcmp(tfields{tfc}, hfields{tfc})
headermismatch = true;
break;
end
end
% if mismatch give warning and continue with next block
if headermismatch
warning( ...
'BVQXtools:BadBFFSpec', ...
'Magic blocks must match in their headers.' ...
);
continue;
end
end
% build list of magics to consider
actmagic = fmagic;
for slc = blc:endline
% split to fields
rcont = splittocell(bfflines{slc}, listsep, 0);
% reject too short arrays
if length(rcont) < length(rhead)
continue;
end
% deal into struct
rstruct = hstruct;
for hfc = 1:length(hfields)
hfield = hfields{hfc};
rstruct.(hfield) = deblank(rcont{hstruct.(hfield)});
end
% deal with empty lines
if isempty(rstruct.name) || ...
isempty(rstruct.range) || ...
isempty(rstruct.type) || ...
isempty(rstruct.magic)
continue;
end
% put non-empty type/varname rules into actrules
actmagic(end + 1) = rstruct;
end
% parse magics (using for; if any magic fails, error out!)
for slc = 1:length(actmagic)
% get rstruct from actrules
rstruct = actmagic(slc);
% check syntax of fields, name
if ~strcmp(rstruct.name, makelabel(rstruct.name))
error( ...
'BVQXtools:BadBFFSpec', ...
'Invalid Magic.name token: ''%s''.', ...
rstruct.name ...
);
end
% ..., type
rstrtype = lower(rstruct.type);
if ~any(strcmp(rstrtype, ...
{'hex', 'regexp', 'regexpi', 'strfind'}))
error( ...
'BVQXtools:BadBFFSpec', ...
'Invalid Magic.type token: ''%s''.', ...
rstruct.type ...
);
end
% ..., range
try
rrange = eval(['[' rstruct.range ']']);
if numel(rrange) ~= 2
error('INVALIDRANGE');
end
catch
error( ...
'BVQXtools:BadBFFSpec', ...
'Invalid Magic.range specification: ''%s''.', ...
rstruct.range ...
);
end
actmagic(slc).range = rrange;
% ..., magic -> parse hex codes
if strcmp(rstrtype, 'hex')
% split at comma, semicolon or spaces
rhexcodes = splittocell(rstruct.magic, ',; ', 1, 1);
% and convert
rhexvals = [];
for rhc = 1:length(rhexcodes)
rhexvals(end+1) = hex2dec(rhexcodes{rhc});
end
% put back into array
actmagic(slc).magic = rhexvals(:)';
% allow hexadecimal content in other fields
else
% pack %C{xx} and 0x{xx} into hex vars
[hexpackt{1:3}] = regexpi( ...
rstruct.magic, ...
'(\%c\{|0x\{)([0-9a-f][0-9a-f])(\})', 'once');
while ~isempty(hexpackt{3})
hexpackt = hexpackt{3};
rstruct.magic = strrep(rstruct.magic, ...
rstruct.magic(hexpackt(1, 1):hexpackt(3, 2)), ...
char(hex2dec( ...
rstruct.magic(hexpackt(2, 1):hexpackt(2, 2)))));
[hexpackt{1:3}] = regexpi( ...
rstruct.magic, ...
'(\%c\{|0x\{)([0-9a-f][0-9a-f])(\})', 'once');
end
% put back into actmagic
actmagic(slc).magic = rstruct.magic;
end
end
% put actrules at the end of ListOfFields
bffspec.Magic(end + 1:end + length(actmagic)) = actmagic;
% create new file snippet
case {'newfilecode'}
% find "EndNewFileCode"
endline = llc + 1;
for slc = lc:llc
if ~isempty(regexpi(bfflines{slc}, '^endnewfilecode'))
endline = slc - 1;
break;
end
end
% check endline
if endline > llc
error( ...
'BVQXtools:BadBFFSpec', ...
'Unclosed NewFileCode section in BFF spec.' ...
);
end
% generate and check code snippet
codesnip = gluetostring(bfflines(lc:endline), char(10), 1);
tcodesnip = codesnip;
tcodesnip(tcodesnip == '@') = [];
try
eval(['if 1==0,' tcodesnip ';end']);
catch
error( ...
'BVQXtools:BadBFFSpec', ...
'Syntax error detected in NewFileCode: ''%s''.', ...
lasterr ...
);
end
% store code
bffspec.NewFileCode = codesnip;
% critical transio object size
case {'transiosize'}
try
tiosize = splittocell(bffval, ';, ', 1, 1);
if ~isempty(tiosize)
bffspec.TransIOSize = str2double(tiosize{1});
end
if length(bffspec.TransIOSize) ~= 1 || ...
isnan(bffspec.TransIOSize) || ...
bffspec.TransIOSize < 4096
bffspec.TransIOSize = default_tiosize;
else
bffspec.TransIOSize = fix(bffspec.TransIOSize);
end
catch
bffspec.TransIOSize = default_tiosize;
end
% unrecognized token, just go on
otherwise
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -