* Bug 16565: edit(user_defined_func) corrupted the original code
[scilab.git] / scilab / modules / scinotes / macros / edit.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) ????-2008 - INRIA
3 // Copyright (C) 2008 - INRIA - Allan CORNET
4 // Copyright (C) 2010 - DIGITEO - Allan CORNET
5 // Copyright (C) 2012 - 2016 - Scilab Enterprises
6 // Copyright (C) 2018 - 2020 - Samuel GOUGEON
7 //
8 // This file is hereby licensed under the terms of the GNU GPL v2.0,
9 // pursuant to article 5.3.4 of the CeCILL v.2.1.
10 // This file was originally licensed under the terms of the CeCILL v2.1,
11 // and continues to be available under such terms.
12 // For more information, see the COPYING file which you should have received
13 // along with this program.
14
15 function edit(macroname, linenumber)
16     // macroname : character string giving a macroname
17     // linenumber : line number (as decimal number or literal one)
18
19     [lhs,rhs] = argn(0);
20     if (rhs > 2) then
21         msg = _("%s: Wrong number of input argument(s): At least %d expected.\n")
22         error(msprintf(msg, "edit", 1));
23     end
24
25     if (rhs >= 1 & type(macroname) ~= 10) then
26         msg = _("%s: Wrong type for input argument #%d: String expected.\n")
27         error(msprintf(msg, "edit", 1));
28     end
29
30     if rhs == 2 then
31         if and(type(linenumber)~=[1 10]) | (type(linenumber)==10 & isnan(strtod(linenumber(1)))) then
32             msg = _("%s: Wrong type for input argument #%d: Number expected.\n")
33             error(msprintf(msg, "edit", 2));
34         end
35         linenumber = strtod(linenumber(1))
36     end
37
38     found = %f;
39     tmp = %f;
40     // tmpdir will have trailing / or \
41     tmpdir= pathconvert(TMPDIR);
42
43     if rhs >= 1 then // macroname or filename is given
44         if regexp(macroname, "/^([a-zA-Z%_#!$?][0-9a-zA-Z_#!$?]*)$/") == [] then
45             // File
46             fname = macroname;
47             found = %t;
48         else
49             if isdef(macroname)
50                 execstr("object = "+macroname)
51                 if type(object)==13
52                     // macroname may be an alias. Example: sinus = sind
53                     // We need to get the original macro name to edit it:
54                     tree = macr2tree(object);
55                     tmp = tree.name
56                     if tmp ~= macroname then
57                         msg = _("edit: ""%s"" is an alias of ""%s"" => editing %s()\n      Please reset %s=%s if %s() is recompiled.\n")
58                         warning(msprintf(msg, macroname, tmp, tmp, macroname, tmp, tmp))
59                         macroname = tmp
60                     end
61
62                     libr = whereis(macroname);
63                     if type(libr($))==10 & libr($)=="script"
64                         // the user-defined macro may overwrite a macro in library
65                         path = whereis_in_libs(macroname)
66                         if path ~= []
67                             // priority = from library:
68                             fname = pathconvert(path) + macroname + ".sci"
69                         else
70                             // txt = tree2code(tree, %t);
71                             // http://bugzilla.scilab.org/16565 : no actual workaround
72                             // http://bugzilla.scilab.org/16576 : workaround
73                             // http://bugzilla.scilab.org/16595 : no workaround
74                             [o,i,txt] = string(object)
75                             if size(o,"*")==1
76                                 o = o + " = "
77                             elseif size(o,"*") > 1
78                                 o = "[" + strcat(o,", ") + "] = "
79                             else
80                                 o = ""
81                             end
82                             if txt(1)==" ", txt(1)=[], end
83                             if txt($)==" ", txt($)=[], end
84                             if i<>[], i = strcat(i, ", "), else i = "", end
85                             txt = ["function " + o + macroname + "(" + i + ")"
86                                   "    " + txt
87                                   "endfunction"
88                                   ];
89                             fname = tmpdir + macroname + ".sci";
90                             mputl(txt, fname);
91                         end
92                         found = %t
93                     else // libr is either a module name or a library name
94                         libr = libr($)
95                         err = execstr("tmp="+libr, "errcatch")
96                         if ~err & type(tmp)==14
97                             [macrolist, path] = libraryinfo(libr);
98                             fname = pathconvert(path) + macroname + ".sci"
99                             found = %t
100                         else // either a module name or any variable name:
101                             // If macroname is a user-defined function,
102                             // whereis() would have reported it as "script".
103                             // => it's a macro in a library, but with a
104                             // macroname equal to a built-in name
105                             // => we must retrieve the library without whereis()
106                             path = whereis_in_libs(macroname)
107                             if path ~= []
108                                 fname = pathconvert(path) + macroname + ".sci"
109                                 found = %t
110                             end
111                         end
112                     end
113                 end
114
115                 if ~found & funptr(macroname)<>0 then
116                     error(msprintf(gettext("%s: %s() is an uneditable hard coded function.\n"), "edit", macroname));
117                 end
118             end
119         end
120     end
121
122     if ~found
123         if ~isdef("macroname","l")
124             macroname = "untitled"
125         end
126         fname = tmpdir + macroname + ".sci";
127         txt = ["function [] = " + macroname + "()"; "endfunction"];
128         mputl(txt, fname);
129     end
130
131     // call the editor with the filename
132     if (rhs == 2) then
133         editor(fname, linenumber, macroname);
134     else
135         editor(fname);
136     end
137
138 endfunction
139
140 // ----------------------------------------------------------------------------
141
142 function path = whereis_in_libs(macroname)
143     path = []
144     for l = librarieslist()'
145         [m, p] = libraryinfo(l)
146         if or(m==macroname)
147             path = p
148             break
149         end
150     end
151 endfunction