function extract_help_examples(dirpaths)
// given a vector of strings giving help chapter paths, or nothinf for
// the default scilab help chapter paths,
// this function build in SCI/tests/Examples the files required for
// testing the examples given in all xml help files available in the
// given paths.
logfile=mopen('extract_help_examples.log','w')
lsave=lines();lines(0)
if argn(2)<1 then
dirpaths=%helps(:,1)';
end
for d=dirpaths
helppaths=listfiles(pathconvert(d+'/*.xml',%f,%t))';
mfprintf(logfile,'\nExtracting examples from '+d+'\n');
mprintf('\n-- Extracting examples from '+d+'\n');
count=0
for h=helppaths
mprintf(h+"\n")
build_example_test(h,logfile)
end
mfprintf(logfile,'\n')
mprintf('\n')
end
lines(lsave(2))
mclose(logfile)
endfunction
function build_example_test(xml_path,logfile)
// given the path of an xml help file
// this function build in SCI/tests/Examples the files required for
// testing the examples given in the xml help file
name=basename(xml_path)
if argn(2)<2 then logfile=mopen(name+'.log','w'),end
T=extract_help_example(xml_path); //look for examples
if T<>[] then //an example is given
t=gettesttype(T) //check if it includes interactive or garphic functions
gen_test_files(T,name,t);
end
endfunction
function t=gettesttype(T)
interactive=['%io(1)','mscanf','dialog','tk','message','getcolor', ...
'xset()','xclick','xgetmouse', 'locate','edit', ...
'x_choices','x_matrix','show_graph','addmenu','delmenu',..
'uicontrol','uimenu','showprofile','scipad','emacs','setbpt',..
'eventhandler','dragrect','rubber','getfile','demoplay','getvalue',...
'portrait','plotprofile','getfont','getmark','getlinestyle']
graphics=['plot','pie','bar','mesh','barh','xrect','xstring','xarc','xfarc','xpoly','xfpoly','xarrow', ...
'xset(', 'xget(','contour','bode','black','nyquist','evans', ...
'param3d','champ(','surf','gcf(','gca(', 'gce(', 'champ1', 'drawaxis',..
'xgraduate','glue','polar','mapsound']
//deff('foo',T)
//T=primitives('foo')
if grep(T,interactive)<>[] then
t='i'
elseif grep(T,graphics)<>[] then
t='g'
else
t=''
end
endfunction
function T=extract_help_example(h)
//extract the example out of an xml help file
if name=='man' then T=[],return,end
T=mgetl(h);
[row,which]=grep(T,['','']);
if row<>[] then
if size(row,'*')==1 then row=[row row],end
T=T(row(1):row(2));
T(1)=stripblanks(strsubst(T(1),'',''));
T($)=stripblanks(strsubst(T($),'',''));
if length(T(1))==0 then T(1)=[];end
if length(T($))==0 then T($)=[];end
if T<>[] then
T(1)=stripblanks(strsubst(T(1),'',''));
if length(T(1))==0 then T(1)=[];end
if length(T($))==0 then T($)=[];end
end
else
T=[]
end
endfunction
function gen_test_files(instructions,name,t)
//set output directory
select t
case 'i' then
test_path='SCI/tests/interactive_tests/'
case 'g'
test_path='SCI/tests/graphical_tests/'
else
test_path='SCI/tests/automatic_tests/'
end
//set file names
tst=pathconvert(test_path+name+'.tst',%f,%f)
ref=pathconvert(test_path+name+'_data.ref',%f,%f)
dia=strsubst(tst,'.tst','.dia')
interactive=t=='i'
info=fileinfo(tst)//to check if the .tst file exists
generate_dataref=%f;generate_tst=%f;
if info==[] //no .tst file exists
mfprintf(logfile,'\n New Example '+name+' the reference is built. Check\n')
generate_tst=%t
if ~interactive then
generate_dataref=%t
T=instrument_instruction('cmp',instructions,ref);
end
else
// a tst file exists, check for validity
//compare it with instructions
T=instrument_instruction('cmp',instructions,ref);
if newest(tst,xml_path)==1 then
if fileinfo(ref)==[]&(~interactive) then
mfprintf(logfile,'\n Example in '+name+'_data.ref no more exist, It is regenerated\n')
generate_dataref=%t
end
else
T1=mgetl(tst);
if or(T1<>T) then
mfprintf(logfile,'\n Example in '+name+' help file has changed, the reference is updated. Check\n')
generate_tst=%t
generate_dataref=%t
elseif fileinfo(ref)==[]&(~interactive) then
mfprintf(logfile,'\n Example in '+name+'_data.ref no more exist, It is regenerated\n')
generate_dataref=%t
end
end
end
if generate_dataref&(~interactive) then
//build the reference data
Tb=instrument_instruction('build',instructions,ref);
build_reference_data(Tb)
[x,ierr]=fileinfo(ref)
if x(1)==0 then mfprintf(logfile,'generated file: '+name+'_data.ref is Empty '),end
end
if generate_tst then
// write down the test script
mputl(T,tst),
//remove the .dia file
if fileinfo(dia)<>[] then unix('rm -f '+pathconvert(dia,%f,%t)); end
dia=dia+'.ref'
//remove the .dia.ref file
if fileinfo(dia)<>[] then unix('rm -f '+pathconvert(dia,%f,%t)); end
end
endfunction
function build_reference_data(instructions)
mputl(instructions,TMPDIR+'/temp.tst')
// Execute the temporary file to generate the data reference file
if execstr('exec(TMPDIR+''/temp.tst'',-1)','errcatch')<>0 then
mclose(%U)
end
endfunction
function instructions=instrument_instruction(job,instructions,refpath)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Executes the given instructions saving all the intermediate
// results into a Scilab binary file.
// This function must mirror the run_with_ref one.
if argn(2)<>3 then error(42),end
// Form a function with the given instructions
mputl(['function %test()';instructions;'xdel(winsid());';'endfunction'],TMPDIR+'/test.sci')
// Compile and load it
//use exec instead of getf to handle inline functions definition
exec(TMPDIR+'/test.sci',-1);
// Get the pseudo-code image
l1=macr2lst(%test)
// Adapt the pseudo-code to add build or run tools
if job=='build' then
l=add_ref_code(list(l1(5:$)));
else //run
l=add_cmp_code(list(l1(5:$)));
end
l=list(l(1:$-2));
// Generate the Scilab instructions from the modified pseudo-code
txt=pseudocode2text(l)
// Add opening and closing instructions
instructions=[]
if job<>'build' then instructions='getf SCI/util/testexamples.sci',end
instructions=[instructions;'reinit_for_test()'];
if job=='build' then
instructions=[instructions;'%U=mopen('''+refpath+''',''wb'');']
else
instructions=[instructions;'%U=mopen('''+refpath+''',''rb'');']
end
instructions=[instructions; txt;'mclose(%U);'];
endfunction
function p=primitives(mac_name,p)
//search for the primitives called by a given macro, the second arg is
//for recursive calls only
funcprot(0)
global scanned_macros
if argn(2)==1 then p=[],scanned_macros=[];end
ierr=execstr('vars=macrovar('+mac_name+')','errcatch')
if ierr<>0 then return,end
called=vars(4);nc=size(called,1)
if nc==0 then p=[],return,end
to_get=[]
for k=1:nc
if find(called(k)==scanned_macros)<>[] then
to_get=[to_get,%f];
else
to_get=[to_get,%t];
end
end
called=called(to_get)
nc=size(called,'*')
for k=1:nc
clear w
execstr('w='+called(k))
if type(w)==130 then
if grep(p,called(k))==[] then p=[p called(k)],end
else
scanned_macros=[scanned_macros called(k)]
p=primitives(called(k),p)
end
end
endfunction
function txt=pseudocode2text(p)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Generate Scilab instructions corresponding to the pseudo-code
//make ins2sci known
prot=funcprot();funcprot(0);fun2string=fun2string;funcprot(prot);
//initialize variables for it
lcount=1;level=[0,0];
quote=''''
dquote='""'
CR='\@'
opstable()
txt=ins2sci(mmodlst(p),1)
endfunction
function ln=add_ref_code(l)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Given a pseudo-code this function add code after each affectation
//operation (29) to save lhs variables into a binary file
ln=list()// initialize result pseudo-code image
for k=1:size(l) //loop on pseudo-codes
lk=l(k);
if type(lk)==10 then //regular pseudo-code
if lk(1)=='29' then //affectation operation
if and(lk(2)<>['52' '43' '99']) then lk(2)='52',end
if or(lk(2)==['52' '99']) then
//display required build reference
lk(2)='43' //disable display
if lk(3)=="ans" then
if and(l(k-1)==['5','25','1','1'])&l(k-2)(1)=='2' then
vv=l(k-2)(2)
lk(3)=l(k-2)(2)
if exists(vv)==1 then
execstr('var='+vv)
if exists(vv)==1&or(type(var)==[11 13 130]) then
//name is a function, syntax is equivalent to ans=name()
lk(3)="%ans";
end
end
elseif and(l(k-1)==['20','deff','2','1']) then
ln($+1)=lk
continue
else
lk(3)="%ans";
end
end
ln($+1)=lk
for i=3:2:size(lk,'*')
ln($+1)="15" //newline
name=lk(i);ref=name+"_ref"
// add instruction: save_ref('''+name+''');
//
ln($+1)=["3",name];
ln($+1)=["2","save_ref","-2","1"];
ln($+1)=["5","25","2","1"];
ln($+1)=["29","43","ans","0"];
end
ln($+1)="15";
else
ln($+1)=lk
end
elseif lk(1)=='2'&or(lk(2)==['xbasc','xdel','clf']) then
//change some function names to allow overloading
lk(2)=lk(2)+'_build'
ln($+1)=lk
else //other operations, just copy them
ln($+1)=lk
end
elseif type(lk)==15 then //control structure starts
lt=lk(1)
//call the add_ref_code function recursively for imbedded instructions
if or(lt(1)==['if','while']) then
lnk=list(lk(1),lk(2))
for i=3:size(lk), lnk($+1)=add_ref_code(lk(i));end
ln($+1)=lnk
elseif lt(1)=='for' then
ln($+1)=list(lk(1),lk(2),add_ref_code(lk(3)))
elseif lt(1)=='select' then
lnk=list(lk(1),lk(2))
for i=3:2:size(lk)-1 //the "case" sequence
lnk($+1)=lk(i)
lnk($+1)=add_ref_code(lk(i+1));
end
//the else
if i+2==size(lk) then lnk($+1)=add_ref_code(lk(i+2));end
ln($+1)=lnk
end
end
end
endfunction
function ln=add_cmp_code(l)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Given a pseudo-code this function add code after each affectation
//operation (29) to compare lhs variables with references given in a binary file
// This function must mirror the add_ref_code one
ln=list() // initialize result pseudo-code image
for k=1:size(l) //loop on pseudo-codes
lk=l(k);
if type(lk)==10 then //regular pseudo-code
if lk(1)=='29' then //affectation operation
if and(lk(2)<>['52' '43' '99']) then lk(2)='52',end
if or(lk(2)==['52' '99']) then
//display required compare result with reference
lk(2)='43'// disable display
if lk(3)=="ans" then
if and(l(k-1)==['5','25','1','1'])&l(k-2)(1)=='2' then
vv=l(k-2)(2)
lk(3)=l(k-2)(2)
if exists(vv)==1 then
execstr('var='+vv)
if exists(vv)==1&or(type(var)==[11 13 130]) then
//name is a function, syntax is equivalent to ans=name()
lk(3)="%ans";
end
end
elseif and(l(k-1)==['20','deff','2','1']) then
ln($+1)=lk
continue
else
lk(3)="%ans";
end
end
ln($+1)=lk
for i=3:2:size(lk,'*')
ln($+1)="15"//newline
name=lk(i);ref=name+"_ref";
// add instruction: if load_ref('''+name+''') then pause;end
ln($+1)=list("if",list(["3",name],["2","load_ref","-2","1"],["5","25","2","1"]),..
list("12"),list())
end
ln($+1)="15"
else
ln($+1)=lk
end
elseif lk(1)=='2'&or(lk(2)==['xbasc','xdel','clf']) then
//change some function names to allow overloading
lk(2)=lk(2)+'_run'
ln($+1)=lk
else //other operations, just copy them
ln($+1)=lk
end
elseif type(lk)==15 then //control structure starts
lt=lk(1)
//call the add_ref_code function recursively for imbedded instructions
if or(lt(1)==['if','while']) then
lnk=list(lk(1),lk(2))
for i=3:size(lk), lnk($+1)=add_cmp_code(lk(i));end
ln($+1)=lnk
elseif lt(1)=='for' then
ln($+1)=list(lk(1),lk(2),add_cmp_code(lk(3)))
elseif lt(1)=='select' then
lnk=list(lk(1),lk(2))
for i=3:2:size(lk)-1 //the "case" sequence
lnk($+1)=lk(i)
lnk($+1)=add_cmp_code(lk(i+1));
end
//the else
if i+2==size(lk) then lnk($+1)=add_cmp_code(lk(i+2));end
ln($+1)=lnk
end
end
end
endfunction
function r=xbasc_build(w)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Save the graphic windows to be cleared in a Scilab binary file.
// This function must mirror the xbasc_run one.
r=%f
if winsid()==[] then return,end
cur=xget('window')
//
if argn(2)==1 then
ids_ref=[]
for k=1:size(w,'*')
xset('window',w(k))
if get('figure_style')=='new' then ids_ref=[ids_ref,w(k)],end
end
save(%U,ids_ref)
for k=ids_ref
%wins_ref=ghdl2tree(scf(k));save(%U,%wins_ref);
end
xbasc(w)
else
if get('figure_style')=='old' then return,end
ids_ref=xget('window');
save(%U,ids_ref)
%wins_ref=ghdl2tree(gcf());
save(%U,%wins_ref)
xbasc()
end
if or(winsid()==cur) then xset('window',cur),end
endfunction
function r=xbasc_run(w)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Compare the graphic windows to be cleared with the reference givenin a Scilab binary file.
// This function must mirror the xbasc_build one.
r=%f
if winsid()==[] then return,end
cur=xget('window')
//
if argn(2)==1 then
ids_=[]
for k=1:size(w,'*')
xset('window',w(k))
if get('figure_style')=='new' then ids_=[ids_,w(k)],end
end
load(%U,'ids_ref')
if or(ids_ref<>ids_) then r=%t,return,end
for k=ids_ref
%wins_=ghdl2tree(scf(k));
load(%U,'%wins_ref');
if %CMP(%wins_, %wins_ref) then r=%t,return,end
end
xbasc(w)
else
if get('figure_style')=='old' then return,end
ids_=xget('window');
load(%U,'ids_ref')
if or(ids_ref<>ids_) then r=%t,return,end
%wins_=ghdl2tree(gcf());
load(%U,'%wins_ref');
if %CMP(%wins_, %wins_ref) then r=%t,return,end
xbasc()
end
if or(winsid()==cur) then xset('window',cur),end
endfunction
function r=clf_build(w,opt)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Save the graphic windows to be cleared in a Scilab binary file.
// This function must mirror the clf_run one.
r=%f
if winsid()==[] then return,end
cur=xget('window')
rhs=argn(2)
if rhs==1&type(w)==10 then opt=w;rhs=0,end
if winsid()==[] then return,end
//
if rhs>=1 then
ids_ref=[]
if type(w)==9 then
H=w;w=[]
for h=H,w=[w,h.figure_id],end
end
for k=1:size(w,'*')
xset('window',w(k))
if get('figure_style')=='new' then ids_ref=[ids_ref,w(k)],end
end
save(%U,ids_ref)
for k=ids_ref,%wins_ref=ghdl2tree(scf(k));save(%U,%wins_ref);end
if rhs==1 then clf(w),else clf(w,opt),end
else
if get('figure_style')=='old' then return,end
ids_ref=xget('window');
save(%U,ids_ref)
%wins_ref=ghdl2tree(gcf());
save(%U,%wins_ref)
clf()
end
if or(winsid()==cur) then xset('window',cur),end
endfunction
function r=clf_run(w,opt)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Compare the graphic windows to be cleared with the reference givenin a Scilab binary file.
// This function must mirror the clf_build one.
r=%f
if winsid()==[] then return,end
cur=xget('window')
rhs=argn(2)
if rhs==1&type(w)==10 then opt=w;rhs=0,end
if winsid()==[] then return,end
//
if rhs==1 then
ids_=[]
if type(w)==9 then
H=w;w=[]
for h=H,w=[w,h.figure_id],end
end
for k=1:size(w,'*')
xset('window',w(k))
if get('figure_style')=='new' then ids_=[ids_,w(k)],end
end
load(%U,'ids_ref')
if or(ids_ref<>ids_) then r=%t,return,end
for k=ids_ref
%wins_=ghdl2tree(scf(k));
load(%U,'%wins_ref');
if %CMP(%wins_, %wins_ref) then r=%t,return,end
end
if rhs==1 then clf(w),else clf(w,opt),end
else
if get('figure_style')=='old' then return,end
ids_=xget('window')
load(%U,'ids_ref')
if or(ids_ref<>ids_) then r=%t,return,end
%wins_=ghdl2tree(gcf());
load(%U,'%wins_ref');
if %CMP(%wins_,%wins_ref) then r=%t,return,end
clf()
end
if or(winsid()==cur) then xset('window',cur),end
endfunction
function r=xdel_build(w)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Save the graphic windows to be cleared in a Scilab binary file.
// This function must mirror the xdel_run one.
r=%f
if winsid()==[] then return,end
cur=xget('window')
//
if argn(2)>=1 then
ids_ref=[]
for k=1:size(w,'*')
xset('window',w(k))
if get('figure_style')=='new' then ids_ref=[ids_ref,w(k)],end
end
save(%U,ids_ref)
for k=ids_ref,%wins_ref=ghdl2tree(scf(k));save(%U,%wins_ref);end
xdel(w);
else
if get('figure_style')=='old' then return,end
ids_ref=xget('window');
save(%U,ids_ref)
%wins_ref=ghdl2tree(gcf());
save(%U,%wins_ref)
xdel()
end
if or(winsid()==cur) then xset('window',cur),end
endfunction
function r=xdel_run(w,opt)
//Author : Serge Steer, april 2005, Copyright INRIA
//
//Compare the graphic windows to be cleared with the reference givenin a Scilab binary file.
// This function must mirror the xdel_build one.
r=%f
if winsid()==[] then return,end
cur=xget('window')
//
if argn(2)==1 then
ids_=[]
for k=1:size(w,'*')
xset('window',w(k))
if get('figure_style')=='new' then ids_=[ids_,w(k)],end
end
load(%U,'ids_ref')
if or(ids_ref<>ids_) then r=%t,return,end
for k=ids_ref
%wins_=ghdl2tree(scf(k));
load(%U,'%wins_ref');
if %CMP(%wins_, %wins_ref) then r=%t,return,end
end
xdel(w)
else
if get('figure_style')=='old' then return,end
ids_=xget('window')
load(%U,'ids_ref')
if or(ids_ref<>ids_) then r=%t,return,end
%wins_=ghdl2tree(gcf());
load(%U,'%wins_ref');
if %CMP(%wins_,%wins_ref) then r=%t,return,end
xdel()
end
if or(winsid()==cur) then xset('window',cur),end
endfunction
function save_ref(name)
if exists(name)==0 then return,end
v=evstr(name)
if type(v) == 9 then v = ghdl2tree(v);end,
if type(v) == 128 then v = 128;end,// lu handle
execstr(name+'_ref=v;save(%U,'+name+'_ref'+')')
endfunction
function r=load_ref(name)
if exists(name)==0 then r=%f;return,end
v=evstr(name)
if type(v) == 9 then v = ghdl2tree(v);end,
execstr(name+'_ref=v;load(%U,'+name+'_ref'+');r=%CMP(v,'+name+'_ref);')
endfunction
function reinit_for_test()
//reinitialize some Scilab state to be able to reproduce the same tests
sdf();sda()
xdel(winsid())
grand('setgen','clcg4');grand('setall',11111111,22222222,33333333,44444444);
grand('setgen','kiss');grand('setsd',362436069,521288629,123456789,380116160);
grand('setgen','clcg2');grand('setsd',1234567890,123456789);
grand('setgen','urand');grand('setsd',0);
grand('setgen','fsultra');grand('setsd',1234567,7654321);
grand('setgen','mt');grand('setsd',5489);
rand('seed',0);
clearglobal()
format('v',10)
endfunction