// Copyright (c) CNES 2008 // // This software is part of CelestLab, a CNES toolbox for Scilab // // This software is governed by the CeCILL license under French law and // abiding by the rules of distribution of free software. You can use, // modify and/ or redistribute the software under the terms of the CeCILL // license as circulated by CEA, CNRS and INRIA at the following URL // 'http://www.cecill.info'. //----------------------------------------------------------- // Returns the list of all the functions found in fpaths. // fpaths: paths of files containing scilab functions (1xN) // // listfuncs is a list of structures with the following fields: // - ndeb: first line of function in file // - nfin: last line of function in file // - txt = (string) function lines (Px1) // - ind_exec: indices of executable lines (not comments nor blank lines) // - name: (string) function name // - fpath: (string) path of file where the function is defined // - fname: (string) basename of fpath (=function name) // - depth: 0 for main level, 1: subfunction, 2:subsubfunction... // // ok = %f is some functions are defined more than once. //----------------------------------------------------------- function [listfuncs, ok] = CL__extractFunctions(fpaths) //----------------------------------------------------------- // Function name (if defined by "function"). // ligne: line where "function" has been detected //----------------------------------------------------------- function [nom] = function_name(ligne) ind = strindex(ligne, "="); if (ind <> []) i1 = ind(1) + 1; else i1 = strindex(ligne, "function") + length("function"); end ind = strindex(ligne, "("); if (ind <> []) i2 = ind(1) - 1; else i2 = length(ligne) - 1; end nom = stripblanks(part(ligne, i1:i2), %t); endfunction //----------------------------------------------------------- // Function name (if defined by "deff"). // ligne: line where "deff" has been detected //----------------------------------------------------------- function [nom] = function_name_deff(ligne) quotes = ["""", "''"]; nom = "?"; I = strindex(ligne, quotes); if (length(I) < 2); return; end nom = function_name(part(ligne,I(1)+1:I(2)-1)); endfunction //----------------------------------------------------------- // Returns the list of all the functions found in one file. // fpath: path of the file (1x1) // listfuncs is a list of structures (see above for fields). //----------------------------------------------------------- function [listfuncs] = extract_funcs(fpath) listfuncs = list(); // replace comments to save memory space txt = stripblanks(mgetl(fpath), %t); I = find(part(txt,1:2) == "//"); txt(I) = ""; // replace tabs by " " txt = strsubst(txt, ascii(9), " "); // warning if deff found if (find(part(txt,1:4) == "deff") <> []) // CL__warning("''deff'' found in file: " + fpath); end while (1) // Index of lines starting with "function" nl_func = find(part(txt+" ",1:9) == "function "); // Index of lines starting with "endfunction" nl_endf = find(part(txt+" ",1:12) == "endfunction "); // This error should not happen if (size(nl_func,2) <> size(nl_endf,2)) CL__warning("Anomaly in file: " + fpath + " => skip"); return; end if (size(nl_func,2) == 0) break; end // deff: analysed in limited cases only nl_deff = find(part(txt,1:5) == "deff(" & grep(txt, "..") == []); // deff not analysed! nl_deff = []; // K: // K(1,:): line numbers // K(2,:): 1 if function, -1 if endfunction // K(3,:): 1 if function defined by "deff" K = [ [nl_func, nl_endf, nl_deff, nl_deff]; .. [ones(nl_func), -1*ones(nl_endf), 1*ones(nl_deff), -1*ones(nl_deff)]; .. [zeros(nl_func), zeros(nl_endf), ones(nl_deff), ones(nl_deff)] ]; [X,I] = gsort(K(1,:), "c", "i"); K = K(:,I); // K(2,:): gives level of function (from 1) K(2,:) = cumsum(K(2,:)); // I: index of function to consider (most deeply nestled) [m,I] = max(K(2,:)); I = I(1); // in case not unique // function decl => should not be in last line if (I == size(K,2)) CL__warning("Anomaly in file ''" + fpath + "'' -> skip"); return; end n1 = K(1,I); // function n2 = K(1,I+1); // endfunction lignes = txt(n1:n2); ind_exec = find(lignes <> "" & part(lignes,1:2) <> "//"); depth = K(2,I) - 1; // 0 => main level if (K(3,I) == 1) name = function_name_deff(lignes(1)); else name = function_name(lignes(1)); end func = struct(); func.ndeb = n1; // 1st line in file func.nfin = n2; // last line in file func.txt = lignes; func.ind_exec = ind_exec; func.name = name; func.fpath = fpath; func.fname = basename(fpath); func.depth = depth; listfuncs($+1) = func; // text not removed to keep line numbers correct txt(n1:n2) = ""; end endfunction //----------------------------------------------------------- // Returns: // - names of functions defined more than once (1xN) // - list of corresponding indices in listfuncs (dim = N) //----------------------------------------------------------- function [names, list_ind] = multiple_defined(listfuncs) nb = length(listfuncs); tabnames = emptystr(1, nb); for k = 1:nb tabnames(k) = listfuncs(k).name; end [names] = gsort(tabnames, "lc", "i"); I = find(names(2:$) == names(1:$-1)); names = unique(names(I)); list_ind = list(); for (k = 1:size(names,"*")) I = find(names(k) == tabnames); list_ind(k) = I; end endfunction // ========================================================== // MAIN // ========================================================== listfuncs = list(); ok = %t; for (fpath = fpaths) l = extract_funcs(fpath); listfuncs = lstcat(listfuncs, l); end // check that each function name is unique. [names, list_ind] = multiple_defined(listfuncs); for k = 1 : size(names,"*") mprintf("Function %s is defined more than once in file(s):\n", names(k)); ind = list_ind(k); for (i = 1 : length(ind)) mprintf("-> %s\n", listfuncs(ind(i)).fpath); end end if (size(names,"*") > 0) ok = %f; end endfunction