Fix etags reading of compressed files
[emacs.git] / test / indent / octave.m
bloba7041462f7f3309f2fd1843d088073448af8e3db
1 ## -*- mode: octave; coding: utf-8 -*-
2 0;                              # Don't make this a function file
3 function res = tcomp (fn)
4   %% res = tcomp (fn)
5   %%     imports components and rearranges them.
7   if nargin ~= 1
8     print_usage()
9   end
11   data = dlmread(fn, 3, 0);
13   x = data(:,2:end);
14   y = 'hello';
15   z = y';
17   ## Bug#14399.
18   vec = [...
19           one;...
20           two;...
21           three];
23   cnty = repmat(x(:,1)(:), 10, 1);
24   x = ...
25   12
27   pop = x(:,1:10)(:);
28     ## Here and below, we test if the indentation aligns with a previous
29     ## fixindented line.  This is important so as to make it easier for the
30     ## user to override some indentation somewhere, and also because it
31     ## reflects the fact that the indentation decision is taken with a minimum
32     ## amount of work (i.e. in the present case, without having to walk back
33     ## until the `function' line).
34     bir = x(:,11:20)(:);        # fixindent
35     dth = x(:,21:30)(:);
36     imig = x(:,31:40)(:);
37     dmig = x(:,41:50)(:);
38     gq = x(:,51:60)(:);
40     yrs = repmat(2000:2009, 39, 1)(:);
42     res = [yrs, cnty, pop, bir, dth, imig, dmig, gq];
44 endfunction
46 ## Copyright (C) 2005, 2006, 2007, 2008, 2009 Søren Hauberg
48 ## This file is part of Octave.
50 ## Octave is free software; you can redistribute it and/or modify it
51 ## under the terms of the GNU General Public License as published by
52 ## the Free Software Foundation; either version 3 of the License, or (at
53 ## your option) any later version.
55 ## Octave is distributed in the hope that it will be useful, but
56 ## WITHOUT ANY WARRANTY; without even the implied warranty of
57 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
58 ## General Public License for more details.
60 ## You should have received a copy of the GNU General Public License
61 ## along with Octave; see the file COPYING.  If not, see
62 ## <http://www.gnu.org/licenses/>.
64 ## -*- texinfo -*-
65 ## @deftypefn  {Command} pkg @var{command} @var{pkg_name}
66 ## @deftypefnx {Command} pkg @var{command} @var{option} @var{pkg_name}
67 ## This command interacts with the package manager.  Different actions will
68 ## be taken depending on the value of @var{command}.
70 ## @table @samp
71 ## @item install
72 ## Install named packages.  For example,
73 ## @example
74 ## pkg install image-1.0.0.tar.gz
75 ## @end example
76 ## @noindent
77 ## installs the package found in the file @file{image-1.0.0.tar.gz}.
79 ## The @var{option} variable can contain options that affect the manner
80 ## in which a package is installed.  These options can be one or more of
82 ## @table @code
83 ## @item -nodeps
84 ## The package manager will disable the dependency checking.  That way it
85 ## is possible to install a package even if it depends on another package
86 ## that's not installed on the system.  @strong{Use this option with care.}
88 ## @item -noauto
89 ## The package manager will not automatically load the installed package
90 ## when starting Octave, even if the package requests that it is.
92 ## @item -auto
93 ## The package manager will automatically load the installed package when
94 ## starting Octave, even if the package requests that it isn't.
96 ## @item -local
97 ## A local installation is forced, even if the user has system privileges.
99 ## @item -global
100 ## A global installation is forced, even if the user doesn't normally have
101 ## system privileges
103 ## @item -verbose
104 ## The package manager will print the output of all of the commands that are
105 ## performed.
106 ## @end table
108 ## @item uninstall
109 ## Uninstall named packages.  For example,
110 ## @example
111 ## pkg uninstall image
112 ## @end example
113 ## @noindent
114 ## removes the @code{image} package from the system.  If another installed
115 ## package depends on the @code{image} package an error will be issued.
116 ## The package can be uninstalled anyway by using the @code{-nodeps} option.
117 ## @item load
118 ## Add named packages to the path.  After loading a package it is
119 ## possible to use the functions provided by the package.  For example,
120 ## @example
121 ## pkg load image
122 ## @end example
123 ## @noindent
124 ## adds the @code{image} package to the path.  It is possible to load all
125 ## installed packages at once with the command
126 ## @example
127 ## pkg load all
128 ## @end example
129 ## @item unload
130 ## Removes named packages from the path.  After unloading a package it is
131 ## no longer possible to use the functions provided by the package.
132 ## This command behaves like the @code{load} command.
133 ## @item list
134 ## Show a list of the currently installed packages.  By requesting one or two
135 ## output argument it is possible to get a list of the currently installed
136 ## packages.  For example,
137 ## @example
138 ## installed_packages = pkg list;
139 ## @end example
140 ## @noindent
141 ## returns a cell array containing a structure for each installed package.
142 ## The command
143 ## @example
144 ## [@var{user_packages}, @var{system_packages}] = pkg list
145 ## @end example
146 ## @noindent
147 ## splits the list of installed packages into those who are installed by
148 ## the current user, and those installed by the system administrator.
149 ## @item describe
150 ## Show a short description of the named installed packages, with the option
151 ## '-verbose' also list functions provided by the package, e.g.:
152 ## @example
153 ##  pkg describe -verbose all
154 ## @end example
155 ## @noindent
156 ## will describe all installed packages and the functions they provide.
157 ## If one output is requested a cell of structure containing the
158 ## description and list of functions of each package is returned as
159 ## output rather than printed on screen:
160 ## @example
161 ##  desc = pkg ("describe", "secs1d", "image")
162 ## @end example
163 ## @noindent
164 ## If any of the requested packages is not installed, pkg returns an
165 ## error, unless a second output is requested:
166 ## @example
167 ##  [ desc, flag] = pkg ("describe", "secs1d", "image")
168 ## @end example
169 ## @noindent
170 ## @var{flag} will take one of the values "Not installed", "Loaded" or
171 ## "Not loaded" for each of the named packages.
172 ## @item prefix
173 ## Set the installation prefix directory.  For example,
174 ## @example
175 ## pkg prefix ~/my_octave_packages
176 ## @end example
177 ## @noindent
178 ## sets the installation prefix to @file{~/my_octave_packages}.
179 ## Packages will be installed in this directory.
181 ## It is possible to get the current installation prefix by requesting an
182 ## output argument.  For example,
183 ## @example
184 ## p = pkg prefix
185 ## @end example
187 ## The location in which to install the architecture dependent files can be
188 ## independent specified with an addition argument.  For example
190 ## @example
191 ## pkg prefix ~/my_octave_packages ~/my_arch_dep_pkgs
192 ## @end example
193 ## @item local_list
194 ## Set the file in which to look for information on the locally
195 ## installed packages.  Locally installed packages are those that are
196 ## typically available only to the current user.  For example
197 ## @example
198 ## pkg local_list ~/.octave_packages
199 ## @end example
200 ## It is possible to get the current value of local_list with the following
201 ## @example
202 ## pkg local_list
203 ## @end example
204 ## @item global_list
205 ## Set the file in which to look for, for information on the globally
206 ## installed packages.  Globally installed packages are those that are
207 ## typically available to all users.  For example
208 ## @example
209 ## pkg global_list /usr/share/octave/octave_packages
210 ## @end example
211 ## It is possible to get the current value of global_list with the following
212 ## @example
213 ## pkg global_list
214 ## @end example
215 ## @item rebuild
216 ## Rebuilds the package database from the installed directories.  This can
217 ## be used in cases where for some reason the package database is corrupted.
218 ## It can also take the @code{-auto} and @code{-noauto} options to allow the
219 ## autoloading state of a package to be changed.  For example
221 ## @example
222 ## pkg rebuild -noauto image
223 ## @end example
225 ## will remove the autoloading status of the image package.
226 ## @item build
227 ## Builds a binary form of a package or packages.  The binary file produced
228 ## will itself be an Octave package that can be installed normally with
229 ## @code{pkg}.  The form of the command to build a binary package is
231 ## @example
232 ## pkg build builddir image-1.0.0.tar.gz @dots{}
233 ## @end example
235 ## @noindent
236 ## where @code{builddir} is the name of a directory where the temporary
237 ## installation will be produced and the binary packages will be found.
238 ## The options @code{-verbose} and @code{-nodeps} are respected, while
239 ## the other options are ignored.
240 ## @end table
241 ## @end deftypefn
243 function [local_packages, global_packages] = pkg (varargin)
244   ## Installation prefix (FIXME: what should these be on windows?)
245   persistent user_prefix = false;
246   persistent prefix = -1;
247   persistent archprefix = -1;
248   persistent local_list = tilde_expand (fullfile ("~", ".octave_packages"));
249   persistent global_list = fullfile (OCTAVE_HOME (), "share", "octave",
250                                      "octave_packages");
251   mlock ();
253   global_install = issuperuser ();
255   if (prefix == -1)
256     if (global_install)
257       prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
258       archprefix = fullfile (octave_config_info ("libexecdir"),
259                              "octave", "packages");
260     else
261       prefix = fullfile ("~", "octave");
262       archprefix = prefix;
263     endif
264     prefix = tilde_expand (prefix);
265     archprefix = tilde_expand (archprefix);
266   endif
268   available_actions = {"list", "install", "uninstall", "load", ...
269                        "unload", "prefix", "local_list", ...
270                        "global_list", "rebuild", "build","describe"};
271   ## Handle input
272   if (length (varargin) == 0 || ! iscellstr (varargin))
273     print_usage ();
274   endif
275   files = {};
276   deps = true;
277   auto = 0;
278   action = "none";
279   verbose = false;
280   for i = 1:length (varargin)
281     switch (varargin{i})
282       case "-nodeps"
283         deps = false;
284       case "-noauto"
285         auto = -1;
286       case "-auto"
287         auto = 1;
288       case "-verbose"
289         verbose = true;
290       case "-local"
291         global_install = false;
292         if (! user_prefix)
293           prefix = tilde_expand (fullfile ("~", "octave"));
294           archprefix = prefix;
295         endif
296       case "-global"
297         global_install = true;
298         if (! user_prefix)
299           prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
300           archprefix = fullfile (octave_config_info ("libexecdir"),
301                                  "octave", "packages");
302         endif
303       case available_actions
304         if (strcmp (action, "none"))
305           action = varargin{i};
306         else
307           error ("more than one action specified");
308         endif
309       otherwise
310         files{end+1} = varargin{i};
311     endswitch
312   endfor
314   ## Take action
315   switch (action)
316     case "list"
317       if (nargout == 0)
318         installed_packages (local_list, global_list);
319       elseif (nargout == 1)
320         local_packages = installed_packages (local_list, global_list);
321       elseif (nargout == 2)
322         [local_packages, global_packages] = installed_packages (local_list,
323                                                                 global_list);
324       else
325         error ("too many output arguments requested");
326       endif
328     case "install"
329       if (length (files) == 0)
330         error ("you must specify at least one filename when calling 'pkg install'");
331       endif
332       install (files, deps, auto, prefix, archprefix, verbose, local_list,
333                global_list, global_install);
335     case "uninstall"
336       if (length (files) == 0)
337         error ("you must specify at least one package when calling 'pkg uninstall'");
338       endif
339       uninstall (files, deps, verbose, local_list,
340                  global_list, global_install);
342     case "load"
343       if (length (files) == 0)
344         error ("you must specify at least one package, 'all' or 'auto' when calling 'pkg load'");
345       endif
346       load_packages (files, deps, local_list, global_list);
348     case "unload"
349       if (length (files) == 0)
350         error ("you must specify at least one package or 'all' when calling 'pkg unload'");
351       endif
352       unload_packages (files, deps, local_list, global_list);
354     case "prefix"
355       if (length (files) == 0 && nargout == 0)
356         printf ("Installation prefix:             %s\n", prefix);
357         printf ("Architecture dependent prefix:   %s\n", archprefix);
358       elseif (length (files) == 0 && nargout >= 1)
359         local_packages = prefix;
360         global_packages = archprefix;
361       elseif (length (files) >= 1 && nargout <= 2 && ischar (files{1}))
362         prefix = files{1};
363         prefix = absolute_pathname (prefix);
364         local_packages = prefix;
365         user_prefix = true;
366         if (length (files) >= 2 && ischar (files{2}))
367           archprefix = files{2};
368           try
369             archprefix = absolute_pathname (archprefix);
370           catch
371             mkdir (archprefix);
372             warning ("creating the directory %s\n", archprefix);
373             archprefix = absolute_pathname (archprefix);
374           end_try_catch
375           global_packages = archprefix;
376         endif
377       else
378         error ("you must specify a prefix directory, or request an output argument");
379       endif
381     case "local_list"
382       if (length (files) == 0 && nargout == 0)
383         disp (local_list);
384       elseif (length (files) == 0 && nargout == 1)
385         local_packages = local_list;
386       elseif (length (files) == 1 && nargout == 0 && ischar (files{1}))
387         try
388           local_list = absolute_pathname (files{1});
389         catch
390           ## Force file to be created
391           fclose (fopen (files{1}, "wt"));
392           local_list = absolute_pathname (files{1});
393         end_try_catch
394       else
395         error ("you must specify a local_list file, or request an output argument");
396       endif
398     case "global_list"
399       if (length (files) == 0 && nargout == 0)
400         disp(global_list);
401       elseif (length (files) == 0 && nargout == 1)
402         local_packages = global_list;
403       elseif (length (files) == 1 && nargout == 0 && ischar (files{1}))
404         try
405           global_list = absolute_pathname (files{1});
406         catch
407           ## Force file to be created
408           fclose (fopen (files{1}, "wt"));
409           global_list = absolute_pathname (files{1});
410         end_try_catch
411       else
412         error ("you must specify a global_list file, or request an output argument");
413       endif
415     case "rebuild"
416       if (global_install)
417         global_packages = rebuild (prefix, archprefix, global_list, files,
418                                    auto, verbose);
419         global_packages = save_order (global_packages);
420         save (global_list, "global_packages");
421         if (nargout > 0)
422           local_packages = global_packages;
423         endif
424       else
425         local_packages = rebuild (prefix, archprefix, local_list, files, auto,
426                                   verbose);
427         local_packages = save_order (local_packages);
428         save (local_list, "local_packages");
429         if (nargout == 0)
430           clear ("local_packages");
431         endif
432       endif
434     case "build"
435       if (length (files) < 2)
436         error ("you must specify at least the build directory and one filename\nwhen calling 'pkg build'");
437       endif
438       build (files, deps, auto, verbose);
440     case "describe"
441       if (length (files) == 0)
442         error ("you must specify at least one package or 'all' when calling 'pkg describe'");
443       endif
444       ## FIXME: the name of the output variables is inconsistent
445       ##            with their content
446       switch (nargout)
447         case 0
448           describe (files, verbose, local_list, global_list);
449         case 1
450           pkg_desc_list = describe (files, verbose, local_list, ...
451                                     global_list);
452           local_packages = pkg_desc_list;
453         case 2
454           [pkg_desc_list, flag] = describe (files, verbose, local_list, ...
455                                             global_list);
456           local_packages  = pkg_desc_list;
457           global_packages = flag;
458         otherwise
459           error ("you can request at most two outputs when calling 'pkg describe'");
460       endswitch
462     otherwise
463       error ("you must specify a valid action for 'pkg'. See 'help pkg' for details");
464   endswitch
465 endfunction
467 function descriptions = rebuild (prefix, archprefix, list, files, auto, verbose)
468   if (isempty (files))
469     [dirlist, err, msg] = readdir (prefix);
470     if (err)
471       error ("couldn't read directory %s: %s", prefix, msg);
472     endif
473     ## the two first entries of dirlist are "." and ".."
474     dirlist([1,2]) = [];
475   else
476     old_descriptions = installed_packages (list, list);
477     wd = pwd ();
478     unwind_protect
479       cd (prefix);
480       dirlist = glob (cellfun(@(x) cstrcat(x, '-*'), files, 'UniformOutput', 0));
481     unwind_protect_cleanup
482       cd (wd);
483     end_unwind_protect
484   endif
485   descriptions = {};
486   for k = 1:length (dirlist)
487     descfile = fullfile (prefix, dirlist{k}, "packinfo", "DESCRIPTION");
488     if (verbose)
489       printf ("recreating package description from %s\n", dirlist{k});
490     endif
491     if (exist (descfile, "file"))
492       desc = get_description (descfile);
493       desc.dir = fullfile (prefix, dirlist{k});
494       desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-",
495                                                        desc.version));
496       if (auto != 0)
497         if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file"))
498           unlink (fullfile (desc.dir, "packinfo", ".autoload"));
499         endif
500         if (auto < 0)
501           desc.autoload = 0;
502         elseif (auto > 0)
503           desc.autoload = 1;
504           fclose (fopen (fullfile (desc.dir, "packinfo", ".autoload"), "wt"));
505         endif
506       else
507         if (exist (fullfile (desc.dir, "packinfo", ".autoload"), "file"))
508           desc.autoload = 1;
509         else
510           desc.autoload = 0;
511         endif
512       endif
513       descriptions{end + 1} = desc;
514     elseif (verbose)
515       warning ("directory %s is not a valid package", dirlist{k});
516     endif
517   endfor
519   if (! isempty (files))
520     ## We are rebuilding for a particular package(s) so we should take
521     ## care to keep the other untouched packages in the descriptions
522     descriptions = {descriptions{:}, old_descriptions{:}};
524     dup = [];
525     for i = 1:length (descriptions)
526       if (find (dup, i))
527         continue;
528       endif
529       for j = (i+1):length (descriptions)
530         if (find (dup, j))
531           continue;
532         endif
533         if (strcmp (descriptions{i}.name, descriptions{j}.name))
534           dup = [dup, j];
535         endif
536       endfor
537     endfor
538     if (! isempty (dup))
539       descriptions (dup) = [];
540     endif
541   endif
542 endfunction
544 function build (files, handle_deps, autoload, verbose)
545   if (length (files) < 1)
546     error ("insufficient number of files");
547   endif
548   builddir = files{1};
549   if (! exist (builddir, "dir"))
550     warning ("creating build directory %s", builddir);
551     [status, msg] = mkdir (builddir);
552     if (status != 1)
553       error ("could not create installation directory: %s", msg);
554     endif
555   endif
556   builddir = absolute_pathname (builddir);
557   installdir = fullfile (builddir, "install");
558   if (! exist (installdir, "dir"))
559     [status, msg] = mkdir (installdir);
560     if (status != 1)
561       error ("could not create installation directory: %s", msg);
562     endif
563   endif
564   files(1) = [];
565   buildlist = fullfile (builddir, "octave_packages");
566   install (files, handle_deps, autoload, installdir, installdir, verbose,
567            buildlist, "", false);
568   unwind_protect
569     repackage (builddir, buildlist);
570   unwind_protect_cleanup
571     unload_packages ({"all"}, handle_deps, buildlist, "");
572     if (exist (installdir, "dir"))
573       rm_rf (installdir);
574     endif
575     if (exist (buildlist, "file"))
576       unlink (buildlist);
577     endif
578   end_unwind_protect
579 endfunction
581 function install (files, handle_deps, autoload, prefix, archprefix, verbose,
582                   local_list, global_list, global_install)
584   ## Check that the directory in prefix exist. If it doesn't: create it!
585   if (! exist (prefix, "dir"))
586     warning ("creating installation directory %s", prefix);
587     [status, msg] = mkdir (prefix);
588     if (status != 1)
589       error ("could not create installation directory: %s", msg);
590     endif
591   endif
593   ## Get the list of installed packages.
594   [local_packages, global_packages] = installed_packages (local_list,
595                                                           global_list);
597   installed_pkgs_lst = {local_packages{:}, global_packages{:}};
599   if (global_install)
600     packages = global_packages;
601   else
602     packages = local_packages;
603   endif
605   ## Uncompress the packages and read the DESCRIPTION files.
606   tmpdirs = packdirs = descriptions = {};
607   try
608     ## Warn about non existent files.
609     for i = 1:length (files)
610       if (isempty (glob(files{i})))
611         warning ("file %s does not exist", files{i});
612       endif
613     endfor
615     ## Unpack the package files and read the DESCRIPTION files.
616     files = glob (files);
617     packages_to_uninstall = [];
618     for i = 1:length (files)
619       tgz = files{i};
621       if (exist (tgz, "file"))
622         ## Create a temporary directory.
623         tmpdir = tmpnam ();
624         tmpdirs{end+1} = tmpdir;
625         if (verbose)
626           printf ("mkdir (%s)\n", tmpdir);
627         endif
628         [status, msg] = mkdir (tmpdir);
629         if (status != 1)
630           error ("couldn't create temporary directory: %s", msg);
631         endif
633         ## Uncompress the package.
634         if (verbose)
635           printf ("untar (%s, %s)\n", tgz, tmpdir);
636         endif
637         untar (tgz, tmpdir);
639         ## Get the name of the directories produced by tar.
640         [dirlist, err, msg] = readdir (tmpdir);
641         if (err)
642           error ("couldn't read directory produced by tar: %s", msg);
643         endif
645         if (length (dirlist) > 3)
646           error ("bundles of packages are not allowed")
647         endif
648       endif
650       ## The filename pointed to an uncompressed package to begin with.
651       if (exist (tgz, "dir"))
652         dirlist = {".", "..", tgz};
653       endif
655       if (exist (tgz, "file") || exist (tgz, "dir"))
656         ## The two first entries of dirlist are "." and "..".
657         if (exist (tgz, "file"))
658           packdir = fullfile (tmpdir, dirlist{3});
659         else
660           packdir = fullfile (pwd(), dirlist{3});
661         endif
662         packdirs{end+1} = packdir;
664         ## Make sure the package contains necessary files.
665         verify_directory (packdir);
667         ## Read the DESCRIPTION file.
668         filename = fullfile (packdir, "DESCRIPTION");
669         desc = get_description (filename);
671         ## Verify that package name corresponds with filename.
672         [dummy, nm] = fileparts (tgz);
673         if ((length (nm) >= length (desc.name))
674             && ! strcmp (desc.name, nm(1:length(desc.name))))
675           error ("package name '%s' doesn't correspond to its filename '%s'",
676                  desc.name, nm);
677         endif
679         ## Set default installation directory.
680         desc.dir = fullfile (prefix, cstrcat (desc.name, "-", desc.version));
682         ## Set default architecture dependent installation directory.
683         desc.archprefix = fullfile (archprefix, cstrcat (desc.name, "-",
684                                                          desc.version));
686         ## Save desc.
687         descriptions{end+1} = desc;
689         ## Are any of the new packages already installed?
690         ## If so we'll remove the old version.
691         for j = 1:length (packages)
692           if (strcmp (packages{j}.name, desc.name))
693             packages_to_uninstall(end+1) = j;
694           endif
695         endfor
696       endif
697     endfor
698   catch
699     ## Something went wrong, delete tmpdirs.
700     for i = 1:length (tmpdirs)
701       rm_rf (tmpdirs{i});
702     endfor
703     rethrow (lasterror ());
704   end_try_catch
706   ## Check dependencies.
707   if (handle_deps)
708     ok = true;
709     error_text = "";
710     for i = 1:length (descriptions)
711       desc = descriptions{i};
712       idx2 = complement (i, 1:length(descriptions));
713       if (global_install)
714         ## Global installation is not allowed to have dependencies on locally
715         ## installed packages.
716         idx1 = complement (packages_to_uninstall,
717                            1:length(global_packages));
718         pseudo_installed_packages = {global_packages{idx1}, ...
719                                      descriptions{idx2}};
720       else
721         idx1 = complement (packages_to_uninstall,
722                            1:length(local_packages));
723         pseudo_installed_packages = {local_packages{idx1}, ...
724                                      global_packages{:}, ...
725                                      descriptions{idx2}};
726       endif
727       bad_deps = get_unsatisfied_deps (desc, pseudo_installed_packages);
728       ## Are there any unsatisfied dependencies?
729       if (! isempty (bad_deps))
730         ok = false;
731         for i = 1:length (bad_deps)
732           dep = bad_deps{i};
733           error_text = cstrcat (error_text, " ", desc.name, " needs ",
734                                 dep.package, " ", dep.operator, " ",
735                                 dep.version, "\n");
736         endfor
737       endif
738     endfor
740     ## Did we find any unsatisfied dependencies?
741     if (! ok)
742       error ("the following dependencies where unsatisfied:\n  %s", error_text);
743     endif
744   endif
746   ## Prepare each package for installation.
747   try
748     for i = 1:length (descriptions)
749       desc = descriptions{i};
750       pdir = packdirs{i};
751       prepare_installation (desc, pdir);
752       configure_make (desc, pdir, verbose);
753     endfor
754   catch
755     ## Something went wrong, delete tmpdirs.
756     for i = 1:length (tmpdirs)
757       rm_rf (tmpdirs{i});
758     endfor
759     rethrow (lasterror ());
760   end_try_catch
762   ## Uninstall the packages that will be replaced.
763   try
764     for i = packages_to_uninstall
765       if (global_install)
766         uninstall ({global_packages{i}.name}, false, verbose, local_list,
767                    global_list, global_install);
768       else
769         uninstall ({local_packages{i}.name}, false, verbose, local_list,
770                    global_list, global_install);
771       endif
772     endfor
773   catch
774     ## Something went wrong, delete tmpdirs.
775     for i = 1:length (tmpdirs)
776       rm_rf (tmpdirs{i});
777     endfor
778     rethrow (lasterror ());
779   end_try_catch
781   ## Install each package.
782   try
783     for i = 1:length (descriptions)
784       desc = descriptions{i};
785       pdir = packdirs{i};
786       copy_files (desc, pdir, global_install);
787       create_pkgadddel (desc, pdir, "PKG_ADD", global_install);
788       create_pkgadddel (desc, pdir, "PKG_DEL", global_install);
789       finish_installation (desc, pdir, global_install);
790       generate_lookfor_cache (desc);
791     endfor
792   catch
793     ## Something went wrong, delete tmpdirs.
794     for i = 1:length (tmpdirs)
795       rm_rf (tmpdirs{i});
796     endfor
797     for i = 1:length (descriptions)
798       rm_rf (descriptions{i}.dir);
799       rm_rf (getarchdir (descriptions{i}));
800     endfor
801     rethrow (lasterror ());
802   end_try_catch
804   ## Check if the installed directory is empty. If it is remove it
805   ## from the list.
806   for i = length (descriptions):-1:1
807     if (dirempty (descriptions{i}.dir, {"packinfo", "doc"}) &&
808         dirempty (getarchdir (descriptions{i})))
809       warning ("package %s is empty\n", descriptions{i}.name);
810       rm_rf (descriptions{i}.dir);
811       rm_rf (getarchdir (descriptions{i}));
812       descriptions(i) = [];
813     endif
814   endfor
816   ## If the package requested that it is autoloaded, or the installer
817   ## requested that it is, then mark the package as autoloaded.
818   for i = length (descriptions):-1:1
819     if (autoload > 0 || (autoload == 0 && isautoload (descriptions(i))))
820       fclose (fopen (fullfile (descriptions{i}.dir, "packinfo",
821                                ".autoload"), "wt"));
822       descriptions{i}.autoload = 1;
823     endif
824   endfor
826   ## Add the packages to the package list.
827   try
828     if (global_install)
829       idx = complement (packages_to_uninstall, 1:length(global_packages));
830       global_packages = save_order ({global_packages{idx}, descriptions{:}});
831       save (global_list, "global_packages");
832       installed_pkgs_lst = {local_packages{:}, global_packages{:}};
833     else
834       idx = complement (packages_to_uninstall, 1:length(local_packages));
835       local_packages = save_order ({local_packages{idx}, descriptions{:}});
836       save (local_list, "local_packages");
837       installed_pkgs_lst = {local_packages{:}, global_packages{:}};
838     endif
839   catch
840     ## Something went wrong, delete tmpdirs.
841     for i = 1:length (tmpdirs)
842       rm_rf (tmpdirs{i});
843     endfor
844     for i = 1:length (descriptions)
845       rm_rf (descriptions{i}.dir);
846     endfor
847     if (global_install)
848       printf ("error: couldn't append to %s\n", global_list);
849     else
850       printf ("error: couldn't append to %s\n", local_list);
851     endif
852     rethrow (lasterror ());
853   end_try_catch
855   ## All is well, let's clean up.
856   for i = 1:length (tmpdirs)
857     [status, msg] = rm_rf (tmpdirs{i});
858     if (status != 1)
859       warning ("couldn't clean up after my self: %s\n", msg);
860     endif
861   endfor
863   ## Add the newly installed packages to the path, so the user
864   ## can begin using them. Only load them if they are marked autoload.
865   if (length (descriptions) > 0)
866     idx = [];
867     for i = 1:length (descriptions)
868       if (isautoload (descriptions(i)))
869         nm = descriptions{i}.name;
870         for j = 1:length (installed_pkgs_lst)
871           if (strcmp (nm, installed_pkgs_lst{j}.name))
872             idx (end + 1) = j;
873             break;
874           endif
875         endfor
876       endif
877     endfor
878     load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst,
879                                     global_install);
880   endif
881 endfunction
883 function uninstall (pkgnames, handle_deps, verbose, local_list,
884                     global_list, global_install)
885   ## Get the list of installed packages.
886   [local_packages, global_packages] = installed_packages(local_list,
887                                                          global_list);
888   if (global_install)
889     installed_pkgs_lst = {local_packages{:}, global_packages{:}};
890   else
891     installed_pkgs_lst = local_packages;
892   endif
894   num_packages = length (installed_pkgs_lst);
895   delete_idx = [];
896   for i = 1:num_packages
897     cur_name = installed_pkgs_lst{i}.name;
898     if (any (strcmp (cur_name, pkgnames)))
899       delete_idx(end+1) = i;
900     endif
901   endfor
903   ## Are all the packages that should be uninstalled already installed?
904   if (length (delete_idx) != length (pkgnames))
905     if (global_install)
906       ## Try again for a locally installed package.
907       installed_pkgs_lst = local_packages;
909       num_packages = length (installed_pkgs_lst);
910       delete_idx = [];
911       for i = 1:num_packages
912         cur_name = installed_pkgs_lst{i}.name;
913         if (any (strcmp (cur_name, pkgnames)))
914           delete_idx(end+1) = i;
915         endif
916       endfor
917       if (length (delete_idx) != length (pkgnames))
918         ## FIXME: We should have a better error message.
919         warning ("some of the packages you want to uninstall are not installed");
920       endif
921     else
922       ## FIXME: We should have a better error message.
923       warning ("some of the packages you want to uninstall are not installed");
924     endif
925   endif
927   ## Compute the packages that will remain installed.
928   idx = complement (delete_idx, 1:num_packages);
929   remaining_packages = {installed_pkgs_lst{idx}};
931   ## Check dependencies.
932   if (handle_deps)
933     error_text = "";
934     for i = 1:length (remaining_packages)
935       desc = remaining_packages{i};
936       bad_deps = get_unsatisfied_deps (desc, remaining_packages);
938       ## Will the uninstallation break any dependencies?
939       if (! isempty (bad_deps))
940         for i = 1:length (bad_deps)
941           dep = bad_deps{i};
942           error_text = cstrcat (error_text, " ", desc.name, " needs ",
943                                 dep.package, " ", dep.operator, " ",
944                                 dep.version, "\n");
945         endfor
946       endif
947     endfor
949     if (! isempty (error_text))
950       error ("the following dependencies where unsatisfied:\n  %s", error_text);
951     endif
952   endif
954   ## Delete the directories containing the packages.
955   for i = delete_idx
956     desc = installed_pkgs_lst{i};
957     ## If an 'on_uninstall.m' exist, call it!
958     if (exist (fullfile (desc.dir, "packinfo", "on_uninstall.m"), "file"))
959       wd = pwd ();
960       cd (fullfile (desc.dir, "packinfo"));
961       on_uninstall (desc);
962       cd (wd);
963     endif
964     ## Do the actual deletion.
965     if (desc.loaded)
966       rmpath (desc.dir);
967       if (exist (getarchdir (desc)))
968         rmpath (getarchdir (desc));
969       endif
970     endif
971     if (exist (desc.dir, "dir"))
972       [status, msg] = rm_rf (desc.dir);
973       if (status != 1)
974         error ("couldn't delete directory %s: %s", desc.dir, msg);
975       endif
976       [status, msg] = rm_rf (getarchdir (desc));
977       if (status != 1)
978         error ("couldn't delete directory %s: %s", getarchdir (desc), msg);
979       endif
980       if (dirempty (desc.archprefix))
981         rm_rf (desc.archprefix);
982       endif
983     else
984       warning ("directory %s previously lost", desc.dir);
985     endif
986   endfor
988   ## Write a new ~/.octave_packages.
989   if (global_install)
990     if (length (remaining_packages) == 0)
991       unlink (global_list);
992     else
993       global_packages = save_order (remaining_packages);
994       save (global_list, "global_packages");
995     endif
996   else
997     if (length (remaining_packages) == 0)
998       unlink (local_list);
999     else
1000       local_packages = save_order (remaining_packages);
1001       save (local_list, "local_packages");
1002     endif
1003   endif
1005 endfunction
1007 function [pkg_desc_list, flag] = describe (pkgnames, verbose,
1008                                            local_list, global_list)
1010   ## Get the list of installed packages.
1011   installed_pkgs_lst = installed_packages(local_list, global_list);
1012   num_packages = length (installed_pkgs_lst);
1015   describe_all = false;
1016   if (any (strcmp ("all", pkgnames)))
1017     describe_all = true;
1018     flag(1:num_packages) = {"Not Loaded"};
1019     num_pkgnames = num_packages;
1020   else
1021     num_pkgnames = length (pkgnames);
1022     flag(1:num_pkgnames) = {"Not installed"};
1023   endif
1025   for i = 1:num_packages
1026     curr_name = installed_pkgs_lst{i}.name;
1027     if (describe_all)
1028       name_pos = i;
1029     else
1030       name_pos = find(strcmp (curr_name, pkgnames));
1031     endif
1033     if (! isempty (name_pos))
1034       if (installed_pkgs_lst{i}.loaded)
1035         flag{name_pos} = "Loaded";
1036       else
1037         flag{name_pos} = "Not loaded";
1038       endif
1040       pkg_desc_list{name_pos}.name = installed_pkgs_lst{i}.name;
1041       pkg_desc_list{name_pos}.version = installed_pkgs_lst{i}.version;
1042       pkg_desc_list{name_pos}.description = installed_pkgs_lst{i}.description;
1043       pkg_desc_list{name_pos}.provides = parse_pkg_idx (installed_pkgs_lst{i}.dir);
1045     endif
1046   endfor
1048   non_inst = find (strcmp (flag, "Not installed"));
1049   if (! isempty (non_inst))
1050     if (nargout < 2)
1051       non_inst_str = sprintf (" %s ", pkgnames{non_inst});
1052       error ("some packages are not installed: %s", non_inst_str);
1053     else
1054       pkg_desc_list{non_inst} = struct ("name", {}, "description",
1055                                         {}, "provides", {});
1056     endif
1057   endif
1059   if (nargout == 0)
1060     for i = 1:num_pkgnames
1061       print_package_description (pkg_desc_list{i}.name,
1062                                  pkg_desc_list{i}.version,
1063                                  pkg_desc_list{i}.provides,
1064                                  pkg_desc_list{i}.description,
1065                                  flag{i}, verbose);
1066     endfor
1067   endif
1069 endfunction
1071 ## AUXILIARY FUNCTIONS
1073 ## Read an INDEX file.
1074 function [pkg_idx_struct] = parse_pkg_idx (packdir)
1076   index_file = fullfile (packdir, "packinfo", "INDEX");
1078   if (! exist (index_file, "file"))
1079     error ("could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files", packdir);
1080   endif
1083   [fid, msg] = fopen (index_file, "r");
1084   if (fid == -1)
1085     error ("the INDEX file %s could not be read: %s",
1086            index_file, msg);
1087   endif
1089   cat_num = 1;
1090   pkg_idx_struct{1}.category = "Uncategorized";
1091   pkg_idx_struct{1}.functions = {};
1093   line = fgetl (fid);
1094   while (isempty (strfind (line, ">>")) && ! feof (fid))
1095     line = fgetl (fid);
1096   endwhile
1098   while (! feof (fid) || line != -1)
1099     if (! any (! isspace (line)) || line(1) == "#" || any (line == "="))
1100       ## Comments,  blank lines or comments about unimplemented
1101       ## functions: do nothing
1102       ## FIXME: probably comments and pointers to external functions
1103       ## could be treated better when printing to screen?
1104     elseif (! isempty (strfind (line, ">>")))
1105       ## Skip package name and description as they are in DESCRIPTION
1106       ## already.
1107     elseif (! isspace (line(1)))
1108       ## Category.
1109       if (! isempty (pkg_idx_struct{cat_num}.functions))
1110         pkg_idx_struct{++cat_num}.functions = {};
1111       endif
1112       pkg_idx_struct{cat_num}.category = deblank (line);
1113     else
1114       ## Function names.
1115       while (any (! isspace (line)))
1116         [fun_name, line] = strtok (line);
1117         pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name);
1118       endwhile
1119     endif
1120     line = fgetl (fid);
1121   endwhile
1122   fclose (fid);
1123 endfunction
1125 function print_package_description (pkg_name, pkg_ver, pkg_idx_struct,
1126                                     pkg_desc, status, verbose)
1128   printf ("---\nPackage name:\n\t%s\n", pkg_name);
1129   printf ("Version:\n\t%s\n", pkg_ver);
1130   printf ("Short description:\n\t%s\n", pkg_desc);
1131   printf ("Status:\n\t%s\n", status);
1132   if (verbose)
1133     printf ("---\nProvides:\n");
1134     for i = 1:length(pkg_idx_struct)
1135       if (! isempty (pkg_idx_struct{i}.functions))
1136         printf ("%s\n", pkg_idx_struct{i}.category);
1137         for j = 1:length(pkg_idx_struct{i}.functions)
1138           printf ("\t%s\n", pkg_idx_struct{i}.functions{j});
1139         endfor
1140       endif
1141     endfor
1142   endif
1144 endfunction
1147 function pth = absolute_pathname (pth)
1148   [status, msg, msgid] = fileattrib (pth);
1149   if (status != 1)
1150     error ("could not find the file or path %s", pth);
1151   else
1152     pth = msg.Name;
1153   endif
1154 endfunction
1156 function repackage (builddir, buildlist)
1157   packages = installed_packages (buildlist, buildlist);
1159   wd = pwd();
1160   for i = 1 : length(packages)
1161     pack = packages{i};
1162     unwind_protect
1163       cd (builddir);
1164       mkdir (pack.name);
1165       mkdir (fullfile (pack.name, "inst"));
1166       copyfile (fullfile (pack.dir, "*"), fullfile (pack.name, "inst"));
1167       movefile (fullfile (pack.name, "inst","packinfo", "*"), pack.name);
1168       if (exist (fullfile (pack.name, "inst","packinfo", ".autoload"), "file"))
1169         unlink (fullfile (pack.name, "inst","packinfo", ".autoload"));
1170       endif
1171       rmdir (fullfile (pack.name, "inst", "packinfo"));
1172       if (exist (fullfile (pack.name, "inst", "doc"), "dir"))
1173         movefile (fullfile (pack.name, "inst", "doc"), pack.name);
1174       endif
1175       if (exist (fullfile (pack.name, "inst", "bin"), "dir"))
1176         movefile (fullfile (pack.name, "inst", "bin"), pack.name);
1177       endif
1178       archdir = fullfile (pack.archprefix, cstrcat (pack.name, "-",
1179                                                     pack.version), getarch ());
1180       if (exist (archdir, "dir"))
1181         if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file"))
1182           unlink (fullfile (pack.name, "inst", "PKG_ADD"));
1183         endif
1184         if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file"))
1185           unlink (fullfile (pack.name, "inst", "PKG_DEL"));
1186         endif
1187         if (exist (fullfile (archdir, "PKG_ADD"), "file"))
1188           movefile (fullfile (archdir, "PKG_ADD"),
1189                     fullfile (pack.name, "PKG_ADD"));
1190         endif
1191         if (exist (fullfile (archdir, "PKG_DEL"), "file"))
1192           movefile (fullfile (archdir, "PKG_DEL"),
1193                     fullfile (pack.name, "PKG_DEL"));
1194         endif
1195       else
1196         if (exist (fullfile (pack.name, "inst", "PKG_ADD"), "file"))
1197           movefile (fullfile (pack.name, "inst", "PKG_ADD"),
1198                     fullfile (pack.name, "PKG_ADD"));
1199         endif
1200         if (exist (fullfile (pack.name, "inst", "PKG_DEL"), "file"))
1201           movefile (fullfile (pack.name, "inst", "PKG_DEL"),
1202                     fullfile (pack.name, "PKG_DEL"));
1203         endif
1204       endif
1205       tfile = cstrcat (pack.name, "-", pack.version, ".tar");
1206       tar (tfile, pack.name);
1207       try
1208         gzip (tfile);
1209         unlink (tfile);
1210       catch
1211         warning ("failed to compress %s", tfile);
1212       end_try_catch
1213     unwind_protect_cleanup
1214       if (exist (pack.name, "dir"))
1215         rm_rf (pack.name);
1216       endif
1217       cd (wd);
1218     end_unwind_protect
1219   endfor
1220 endfunction
1222 function auto = isautoload (desc)
1223   auto = false;
1224   if (isfield (desc{1}, "autoload"))
1225     a = desc{1}.autoload;
1226     if ((isnumeric (a) && a > 0)
1227         || (ischar (a) && (strcmpi (a, "true")
1228                            || strcmpi (a, "on")
1229                            || strcmpi (a, "yes")
1230                            || strcmpi (a, "1"))))
1231       auto = true;
1232     endif
1233   endif
1234 endfunction
1236 function prepare_installation (desc, packdir)
1237   ## Is there a pre_install to call?
1238   if (exist (fullfile (packdir, "pre_install.m"), "file"))
1239     wd = pwd ();
1240     try
1241       cd (packdir);
1242       pre_install (desc);
1243       cd (wd);
1244     catch
1245       cd (wd);
1246       rethrow (lasterror ());
1247     end_try_catch
1248   endif
1250   ## If the directory "inst" doesn't exist, we create it.
1251   inst_dir = fullfile (packdir, "inst");
1252   if (! exist (inst_dir, "dir"))
1253     [status, msg] = mkdir (inst_dir);
1254     if (status != 1)
1255       rm_rf (desc.dir);
1256       error ("the 'inst' directory did not exist and could not be created: %s",
1257              msg);
1258     endif
1259   endif
1260 endfunction
1262 function configure_make (desc, packdir, verbose)
1263   ## Perform ./configure, make, make install in "src".
1264   if (exist (fullfile (packdir, "src"), "dir"))
1265     src = fullfile (packdir, "src");
1266     ## Configure.
1267     if (exist (fullfile (src, "configure"), "file"))
1268       flags = "";
1269       if (isempty (getenv ("CC")))
1270         flags = cstrcat (flags, " CC=\"", octave_config_info ("CC"), "\"");
1271       endif
1272       if (isempty (getenv ("CXX")))
1273         flags = cstrcat (flags, " CXX=\"", octave_config_info ("CXX"), "\"");
1274       endif
1275       if (isempty (getenv ("AR")))
1276         flags = cstrcat (flags, " AR=\"", octave_config_info ("AR"), "\"");
1277       endif
1278       if (isempty (getenv ("RANLIB")))
1279         flags = cstrcat (flags, " RANLIB=\"", octave_config_info ("RANLIB"), "\"");
1280       endif
1281       [status, output] = shell (strcat ("cd '", src, "'; ./configure --prefix=\"",
1282                                         desc.dir, "\"", flags));
1283       if (status != 0)
1284         rm_rf (desc.dir);
1285         error ("the configure script returned the following error: %s", output);
1286       elseif (verbose)
1287         printf("%s", output);
1288       endif
1290     endif
1292     ## Make.
1293     if (exist (fullfile (src, "Makefile"), "file"))
1294       [status, output] = shell (cstrcat ("export INSTALLDIR=\"", desc.dir,
1295                                          "\"; make -C '", src, "'"));
1296       if (status != 0)
1297         rm_rf (desc.dir);
1298         error ("'make' returned the following error: %s", output);
1299       elseif (verbose)
1300         printf("%s", output);
1301       endif
1302     endif
1304     ## Copy files to "inst" and "inst/arch" (this is instead of 'make
1305     ## install').
1306     files = fullfile (src, "FILES");
1307     instdir = fullfile (packdir, "inst");
1308     archdir = fullfile (packdir, "inst", getarch ());
1310     ## Get file names.
1311     if (exist (files, "file"))
1312       [fid, msg] = fopen (files, "r");
1313       if (fid < 0)
1314         error ("couldn't open %s: %s", files, msg);
1315       endif
1316       filenames = char (fread (fid))';
1317       fclose (fid);
1318       if (filenames(end) == "\n")
1319         filenames(end) = [];
1320       endif
1321       filenames = split_by (filenames, "\n");
1322       delete_idx =  [];
1323       for i = 1:length (filenames)
1324         if (! all (isspace (filenames{i})))
1325           filenames{i} = fullfile (src, filenames{i});
1326         else
1327           delete_idx(end+1) = i;
1328         endif
1329       endfor
1330       filenames(delete_idx) = [];
1331     else
1332       m = dir (fullfile (src, "*.m"));
1333       oct = dir (fullfile (src, "*.oct"));
1334       mex = dir (fullfile (src, "*.mex"));
1336       filenames = cellfun (@(x) fullfile (src, x),
1337                            {m.name, oct.name, mex.name},
1338                            "UniformOutput", false);
1339     endif
1341     ## Split into architecture dependent and independent files.
1342     if (isempty (filenames))
1343       idx = [];
1344     else
1345       idx = cellfun (@is_architecture_dependent, filenames);
1346     endif
1347     archdependent = filenames (idx);
1348     archindependent = filenames (!idx);
1350     ## Copy the files.
1351     if (! all (isspace ([filenames{:}])))
1352         if (! exist (instdir, "dir")) # fixindent
1353           mkdir (instdir);
1354         endif
1355         if (! all (isspace ([archindependent{:}])))
1356           if (verbose)
1357             printf ("copyfile");
1358             printf (" %s", archindependent{:});
1359             printf ("%s\n", instdir);
1360           endif
1361           [status, output] = copyfile (archindependent, instdir);
1362           if (status != 1)
1363             rm_rf (desc.dir);
1364             error ("Couldn't copy files from 'src' to 'inst': %s", output);
1365           endif
1366         endif
1367         if (! all (isspace ([archdependent{:}])))
1368           if (verbose)
1369             printf ("copyfile");
1370             printf (" %s", archdependent{:});
1371             printf (" %s\n", archdir);
1372           endif
1373           if (! exist (archdir, "dir"))
1374             mkdir (archdir);
1375           endif
1376           [status, output] = copyfile (archdependent, archdir);
1377           if (status != 1)
1378             rm_rf (desc.dir);
1379             error ("Couldn't copy files from 'src' to 'inst': %s", output);
1380           endif
1381         endif
1382     endif
1383   endif
1384 endfunction
1386 function pkg = extract_pkg (nm, pat)
1387   fid = fopen (nm, "rt");
1388   pkg = "";
1389   if (fid >= 0)
1390     while (! feof (fid))
1391       ln = fgetl (fid);
1392       if (ln > 0)
1393         t = regexp (ln, pat, "tokens");
1394         if (! isempty (t))
1395           pkg = cstrcat (pkg, "\n", t{1}{1});
1396         endif
1397       endif
1398     endwhile
1399     if (! isempty (pkg))
1400       pkg = cstrcat (pkg, "\n");
1401     endif
1402     fclose (fid);
1403   endif
1404 endfunction
1406 function create_pkgadddel (desc, packdir, nm, global_install)
1407   instpkg = fullfile (desc.dir, nm);
1408   instfid = fopen (instpkg, "wt");
1409   ## If it is exists, most of the  PKG_* file should go into the
1410   ## architecture dependent directory so that the autoload/mfilename
1411   ## commands work as expected. The only part that doesn't is the
1412   ## part in the main directory.
1413   archdir = fullfile (getarchprefix (desc), cstrcat (desc.name, "-",
1414                                                      desc.version), getarch ());
1415   if (exist (getarchdir (desc, global_install), "dir"))
1416     archpkg = fullfile (getarchdir (desc, global_install), nm);
1417     archfid = fopen (archpkg, "at");
1418   else
1419     archpkg = instpkg;
1420     archfid = instfid;
1421   endif
1423   if (archfid >= 0 && instfid >= 0)
1424     ## Search all dot-m files for PKG commands.
1425     lst = dir (fullfile (packdir, "inst", "*.m"));
1426     for i = 1:length (lst)
1427       nam = fullfile (packdir, "inst", lst(i).name);
1428       fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$']));
1429     endfor
1431     ## Search all C++ source files for PKG commands.
1432     lst = dir (fullfile (packdir, "src", "*.cc"));
1433     for i = 1:length (lst)
1434       nam = fullfile (packdir, "src", lst(i).name);
1435       fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$']));
1436       fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$']));
1437     endfor
1439     ## Add developer included PKG commands.
1440     packdirnm = fullfile (packdir, nm);
1441     if (exist (packdirnm, "file"))
1442       fid = fopen (packdirnm, "rt");
1443       if (fid >= 0)
1444         while (! feof (fid))
1445           ln = fgets (fid);
1446           if (ln > 0)
1447             fwrite (archfid, ln);
1448           endif
1449         endwhile
1450         fclose (fid);
1451       endif
1452     endif
1454     ## If the files is empty remove it.
1455     fclose (instfid);
1456     t = dir (instpkg);
1457     if (t.bytes <= 0)
1458       unlink (instpkg);
1459     endif
1461     if (instfid != archfid)
1462       fclose (archfid);
1463       t = dir (archpkg);
1464       if (t.bytes <= 0)
1465         unlink (archpkg);
1466       endif
1467     endif
1468   endif
1469 endfunction
1471 function copy_files (desc, packdir, global_install)
1472   ## Create the installation directory.
1473   if (! exist (desc.dir, "dir"))
1474     [status, output] = mkdir (desc.dir);
1475     if (status != 1)
1476       error ("couldn't create installation directory %s : %s",
1477              desc.dir, output);
1478     endif
1479   endif
1481   octfiledir = getarchdir (desc);
1483   ## Copy the files from "inst" to installdir.
1484   instdir = fullfile (packdir, "inst");
1485   if (! dirempty (instdir))
1486     [status, output] = copyfile (fullfile (instdir, "*"), desc.dir);
1487     if (status != 1)
1488       rm_rf (desc.dir);
1489       error ("couldn't copy files to the installation directory");
1490     endif
1491     if (exist (fullfile (desc.dir, getarch ()), "dir") &&
1492         ! strcmp (fullfile (desc.dir, getarch ()), octfiledir))
1493       if (! exist (octfiledir, "dir"))
1494         ## Can be required to create upto three levels of dirs.
1495         octm1 = fileparts (octfiledir);
1496         if (! exist (octm1, "dir"))
1497           octm2 = fileparts (octm1);
1498           if (! exist (octm2, "dir"))
1499             octm3 = fileparts (octm2);
1500             if (! exist (octm3, "dir"))
1501               [status, output] = mkdir (octm3);
1502               if (status != 1)
1503                 rm_rf (desc.dir);
1504                 error ("couldn't create installation directory %s : %s",
1505                        octm3, output);
1506               endif
1507             endif
1508             [status, output] = mkdir (octm2);
1509             if (status != 1)
1510               rm_rf (desc.dir);
1511               error ("couldn't create installation directory %s : %s",
1512                      octm2, output);
1513             endif
1514           endif
1515           [status, output] = mkdir (octm1);
1516           if (status != 1)
1517             rm_rf (desc.dir);
1518             error ("couldn't create installation directory %s : %s",
1519                    octm1, output);
1520           endif
1521         endif
1522         [status, output] = mkdir (octfiledir);
1523         if (status != 1)
1524           rm_rf (desc.dir);
1525           error ("couldn't create installation directory %s : %s",
1526                  octfiledir, output);
1527         endif
1528       endif
1529       [status, output] = movefile (fullfile (desc.dir, getarch (), "*"),
1530                                    octfiledir);
1531       rm_rf (fullfile (desc.dir, getarch ()));
1533       if (status != 1)
1534         rm_rf (desc.dir);
1535         rm_rf (octfiledir);
1536         error ("couldn't copy files to the installation directory");
1537       endif
1538     endif
1540   endif
1542   ## Create the "packinfo" directory.
1543   packinfo = fullfile (desc.dir, "packinfo");
1544   [status, msg] = mkdir (packinfo);
1545   if (status != 1)
1546     rm_rf (desc.dir);
1547     rm_rf (octfiledir);
1548     error ("couldn't create packinfo directory: %s", msg);
1549   endif
1551   ## Copy DESCRIPTION.
1552   [status, output] = copyfile (fullfile (packdir, "DESCRIPTION"), packinfo);
1553   if (status != 1)
1554     rm_rf (desc.dir);
1555     rm_rf (octfiledir);
1556     error ("couldn't copy DESCRIPTION: %s", output);
1557   endif
1559   ## Copy COPYING.
1560   [status, output] = copyfile (fullfile (packdir, "COPYING"), packinfo);
1561   if (status != 1)
1562     rm_rf (desc.dir);
1563     rm_rf (octfiledir);
1564     error ("couldn't copy COPYING: %s", output);
1565   endif
1567   ## If the file ChangeLog exists, copy it.
1568   changelog_file = fullfile (packdir, "ChangeLog");
1569   if (exist (changelog_file, "file"))
1570     [status, output] = copyfile (changelog_file, packinfo);
1571     if (status != 1)
1572       rm_rf (desc.dir);
1573       rm_rf (octfiledir);
1574       error ("couldn't copy ChangeLog file: %s", output);
1575     endif
1576   endif
1578   ## Is there an INDEX file to copy or should we generate one?
1579   index_file = fullfile (packdir, "INDEX");
1580   if (exist(index_file, "file"))
1581     [status, output] = copyfile (index_file, packinfo);
1582     if (status != 1)
1583       rm_rf (desc.dir);
1584       rm_rf (octfiledir);
1585       error ("couldn't copy INDEX file: %s", output);
1586     endif
1587   else
1588     try
1589       write_index (desc, fullfile (packdir, "inst"),
1590                    fullfile (packinfo, "INDEX"), global_install);
1591     catch
1592       rm_rf (desc.dir);
1593       rm_rf (octfiledir);
1594       rethrow (lasterror ());
1595     end_try_catch
1596   endif
1598   ## Is there an 'on_uninstall.m' to install?
1599   fon_uninstall = fullfile (packdir, "on_uninstall.m");
1600   if (exist (fon_uninstall, "file"))
1601     [status, output] = copyfile (fon_uninstall, packinfo);
1602     if (status != 1)
1603       rm_rf (desc.dir);
1604       rm_rf (octfiledir);
1605       error ("couldn't copy on_uninstall.m: %s", output);
1606     endif
1607   endif
1609   ## Is there a doc/ directory that needs to be installed?
1610   docdir = fullfile (packdir, "doc");
1611   if (exist (docdir, "dir") && ! dirempty (docdir))
1612     [status, output] = copyfile (docdir, desc.dir);
1613   endif
1615   ## Is there a bin/ directory that needs to be installed?
1616   ## FIXME: Need to treat architecture dependent files in bin/
1617   bindir = fullfile (packdir, "bin");
1618   if (exist (bindir, "dir") && ! dirempty (bindir))
1619     [status, output] = copyfile (bindir, desc.dir);
1620   endif
1621 endfunction
1623 function finish_installation (desc, packdir, global_install)
1624   ## Is there a post-install to call?
1625   if (exist (fullfile (packdir, "post_install.m"), "file"))
1626     wd = pwd ();
1627     try
1628       cd (packdir);
1629       post_install (desc);
1630       cd (wd);
1631     catch
1632       cd (wd);
1633       rm_rf (desc.dir);
1634       rm_rf (getarchdir (desc), global_install);
1635       rethrow (lasterror ());
1636     end_try_catch
1637   endif
1638 endfunction
1640 function generate_lookfor_cache (desc)
1641   dirs = split_by (genpath (desc.dir), pathsep ());
1642   for i = 1 : length (dirs)
1643     gen_doc_cache (fullfile (dirs{i}, "doc-cache"), dirs{i});
1644   endfor
1645 endfunction
1647 ## Make sure the package contains the essential files.
1648 function verify_directory (dir)
1649   needed_files = {"COPYING", "DESCRIPTION"};
1650   for f = needed_files
1651     if (! exist (fullfile (dir, f{1}), "file"))
1652       error ("package is missing file: %s", f{1});
1653     endif
1654   endfor
1655 endfunction
1657 ## Parse the DESCRIPTION file.
1658 function desc = get_description (filename)
1659   [fid, msg] = fopen (filename, "r");
1660   if (fid == -1)
1661     error ("the DESCRIPTION file %s could not be read: %s", filename, msg);
1662   endif
1664   desc = struct ();
1666   line = fgetl (fid);
1667   while (line != -1)
1668     if (line(1) == "#")
1669       ## Comments, do nothing.
1670     elseif (isspace(line(1)))
1671       ## Continuation lines
1672       if (exist ("keyword", "var") && isfield (desc, keyword))
1673         desc.(keyword) = cstrcat (desc.(keyword), " ", rstrip(line));
1674       endif
1675     else
1676       ## Keyword/value pair
1677       colon = find (line == ":");
1678       if (length (colon) == 0)
1679         disp ("skipping line");
1680       else
1681         colon = colon(1);
1682         keyword = tolower (strip (line(1:colon-1)));
1683         value = strip (line (colon+1:end));
1684         if (length (value) == 0)
1685           fclose (fid);
1686           error ("the keyword %s has an empty value", desc.keywords{end});
1687         endif
1688         desc.(keyword) = value;
1689       endif
1690     endif
1691     line = fgetl (fid);
1692   endwhile
1693   fclose (fid);
1695   ## Make sure all is okay.
1696   needed_fields = {"name", "version", "date", "title", ...
1697                    "author", "maintainer", "description"};
1698   for f = needed_fields
1699     if (! isfield (desc, f{1}))
1700       error ("description is missing needed field %s", f{1});
1701     endif
1702   endfor
1703   desc.version = fix_version (desc.version);
1704   if (isfield (desc, "depends"))
1705     desc.depends = fix_depends (desc.depends);
1706   else
1707     desc.depends = "";
1708   endif
1709   desc.name = tolower (desc.name);
1710 endfunction
1712 ## Make sure the version string v is a valid x.y.z version string
1713 ## Examples: "0.1" => "0.1.0", "monkey" => error(...).
1714 function out = fix_version (v)
1715   dots = find (v == ".");
1716   if (length (dots) == 1)
1717     major = str2num (v(1:dots-1));
1718     minor = str2num (v(dots+1:end));
1719     if (length (major) != 0 && length (minor) != 0)
1720       out = sprintf ("%d.%d.0", major, minor);
1721       return;
1722     endif
1723   elseif (length (dots) == 2)
1724     major = str2num (v(1:dots(1)-1));
1725     minor = str2num (v(dots(1)+1:dots(2)-1));
1726     rev = str2num (v(dots(2)+1:end));
1727     if (length (major) != 0 && length (minor) != 0 && length (rev) != 0)
1728       out = sprintf ("%d.%d.%d", major, minor, rev);
1729       return;
1730     endif
1731   endif
1732   error ("bad version string: %s", v);
1733 endfunction
1735 ## Make sure the depends field is of the right format.
1736 ## This function returns a cell of structures with the following fields:
1737 ##   package, version, operator
1738 function deps_cell = fix_depends (depends)
1739   deps = split_by (tolower (depends), ",");
1740   deps_cell = cell (1, length (deps));
1742   ## For each dependency.
1743   for i = 1:length (deps)
1744     dep = deps{i};
1745     lpar = find (dep == "(");
1746     rpar = find (dep == ")");
1747     ## Does the dependency specify a version
1748     ## Example: package(>= version).
1749     if (length (lpar) == 1 && length (rpar) == 1)
1750       package = tolower (strip (dep(1:lpar-1)));
1751       sub = dep(lpar(1)+1:rpar(1)-1);
1752       parts = strsplit (sub, " ", true);
1753       if (length (parts) != 2)
1754         error ("incorrect syntax for dependency `%s' in the DESCRIPTION file\n",
1755                dep);
1756       endif
1757       operator = parts{1};
1758       if (! any (strcmp (operator, {">", ">=", "<=", "<", "=="})))
1759         error ("unsupported operator: %s", operator);
1760       endif
1761       version  = fix_version (parts{2});
1763       ## If no version is specified for the dependency
1764       ## we say that the version should be greater than
1765       ## or equal to "0.0.0".
1766     else
1767       package = tolower (strip (dep));
1768       operator = ">=";
1769       version  = "0.0.0";
1770     endif
1771     deps_cell{i} = struct ("package", package, "operator", operator,
1772                            "version", version);
1773   endfor
1774 endfunction
1776 ## Strip the text of spaces from the right
1777 ## Example: "  hello world  " => "  hello world"
1778 ## FIXME -- is this the same as deblank?
1779 function text = rstrip (text)
1780   chars = find (! isspace (text));
1781   if (length (chars) > 0)
1782     ## FIXME: shouldn't it be text = text(1:chars(end));
1783     text = text (chars(1):end);
1784   else
1785     text = "";
1786   endif
1787 endfunction
1789 ## Strip the text of spaces from the left and the right.
1790 ## Example: "  hello world  " => "hello world"
1791 function text = strip (text)
1792   chars = find (! isspace (text));
1793   if (length (chars) > 0)
1794     text = text(chars(1):chars(end));
1795   else
1796     text = "";
1797   endif
1798 endfunction
1800 ## Split the text into a cell array of strings by sep.
1801 ## Example: "A, B" => {"A", "B"} (with sep = ",")
1802 function out = split_by (text, sep)
1803   out = strtrim (strsplit (text, sep));
1804 endfunction
1806 ## Create an INDEX file for a package that doesn't provide one.
1807 ##   'desc'  describes the package.
1808 ##   'dir'   is the 'inst' directory in temporary directory.
1809 ##   'index_file' is the name (including path) of resulting INDEX file.
1810 function write_index (desc, dir, index_file, global_install)
1811   ## Get names of functions in dir
1812   [files, err, msg] = readdir (dir);
1813   if (err)
1814     error ("couldn't read directory %s: %s", dir, msg);
1815   endif
1817   ## Check for architecture dependent files.
1818   tmpdir = getarchdir (desc);
1819   if (exist (tmpdir, "dir"))
1820     [files2, err, msg] = readdir (tmpdir);
1821     if (err)
1822       error ("couldn't read directory %s: %s", tmpdir, msg);
1823     endif
1824     files = [files; files2];
1825   endif
1827   functions = {};
1828   for i = 1:length (files)
1829     file = files{i};
1830     lf = length (file);
1831     if (lf > 2 && strcmp (file(end-1:end), ".m"))
1832       functions{end+1} = file(1:end-2);
1833     elseif (lf > 4 && strcmp (file(end-3:end), ".oct"))
1834       functions{end+1} = file(1:end-4);
1835     endif
1836   endfor
1838   ## Does desc have a categories field?
1839   if (! isfield (desc, "categories"))
1840     error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given");
1841   endif
1842   categories = split_by (desc.categories, ",");
1843   if (length (categories) < 1)
1844     error ("the Category field is empty");
1845   endif
1847   ## Write INDEX.
1848   fid = fopen (index_file, "w");
1849   if (fid == -1)
1850     error ("couldn't open %s for writing.", index_file);
1851   endif
1852   fprintf (fid, "%s >> %s\n", desc.name, desc.title);
1853   fprintf (fid, "%s\n", categories{1});
1854   fprintf (fid, "  %s\n", functions{:});
1855   fclose (fid);
1856 endfunction
1858 function bad_deps = get_unsatisfied_deps (desc, installed_pkgs_lst)
1859   bad_deps = {};
1861   ## For each dependency.
1862   for i = 1:length (desc.depends)
1863     dep = desc.depends{i};
1865     ## Is the current dependency Octave?
1866     if (strcmp (dep.package, "octave"))
1867       if (! compare_versions (OCTAVE_VERSION, dep.version, dep.operator))
1868         bad_deps{end+1} = dep;
1869       endif
1870       ## Is the current dependency not Octave?
1871     else
1872       ok = false;
1873       for i = 1:length (installed_pkgs_lst)
1874         cur_name = installed_pkgs_lst{i}.name;
1875         cur_version = installed_pkgs_lst{i}.version;
1876         if (strcmp (dep.package, cur_name)
1877             && compare_versions (cur_version, dep.version, dep.operator))
1878           ok = true;
1879           break;
1880         endif
1881       endfor
1882       if (! ok)
1883         bad_deps{end+1} = dep;
1884       endif
1885     endif
1886   endfor
1887 endfunction
1889 function [out1, out2] = installed_packages (local_list, global_list)
1890   ## Get the list of installed packages.
1891   try
1892     local_packages = load (local_list).local_packages;
1893   catch
1894     local_packages = {};
1895   end_try_catch
1896   try
1897     global_packages = load (global_list).global_packages;
1898   catch
1899     global_packages = {};
1900   end_try_catch
1901   installed_pkgs_lst = {local_packages{:}, global_packages{:}};
1903   ## Eliminate duplicates in the installed package list.
1904   ## Locally installed packages take precedence.
1905   dup = [];
1906   for i = 1:length (installed_pkgs_lst)
1907     if (find (dup, i))
1908       continue;
1909     endif
1910     for j = (i+1):length (installed_pkgs_lst)
1911       if (find (dup, j))
1912         continue;
1913       endif
1914       if (strcmp (installed_pkgs_lst{i}.name, installed_pkgs_lst{j}.name))
1915         dup = [dup, j];
1916       endif
1917     endfor
1918   endfor
1919   if (! isempty(dup))
1920     installed_pkgs_lst(dup) = [];
1921   endif
1923   ## Now check if the package is loaded.
1924   tmppath = strrep (path(), "\\", "/");
1925   for i = 1:length (installed_pkgs_lst)
1926     if (findstr (tmppath, strrep (installed_pkgs_lst{i}.dir, "\\", "/")))
1927       installed_pkgs_lst{i}.loaded = true;
1928     else
1929       installed_pkgs_lst{i}.loaded = false;
1930     endif
1931   endfor
1932   for i = 1:length (local_packages)
1933     if (findstr (tmppath, strrep (local_packages{i}.dir, "\\", "/")))
1934       local_packages{i}.loaded = true;
1935     else
1936       local_packages{i}.loaded = false;
1937     endif
1938   endfor
1939   for i = 1:length (global_packages)
1940     if (findstr (tmppath, strrep (global_packages{i}.dir, "\\", "/")))
1941       global_packages{i}.loaded = true;
1942     else
1943       global_packages{i}.loaded = false;
1944     endif
1945   endfor
1947   ## Should we return something?
1948   if (nargout == 2)
1949     out1 = local_packages;
1950     out2 = global_packages;
1951     return;
1952   elseif (nargout == 1)
1953     out1 = installed_pkgs_lst;
1954     return;
1955   endif
1957   ## We shouldn't return something, so we'll print something.
1958   num_packages = length (installed_pkgs_lst);
1959   if (num_packages == 0)
1960     printf ("no packages installed.\n");
1961     return;
1962   endif
1964   ## Compute the maximal lengths of name, version, and dir.
1965   h1 = "Package Name";
1966   h2 = "Version";
1967   h3 = "Installation directory";
1968   max_name_length = length (h1);
1969   max_version_length = length (h2);
1970   names = cell (num_packages, 1);
1971   for i = 1:num_packages
1972     max_name_length = max (max_name_length,
1973                            length (installed_pkgs_lst{i}.name));
1974     max_version_length = max (max_version_length,
1975                               length (installed_pkgs_lst{i}.version));
1976     names{i} = installed_pkgs_lst{i}.name;
1977   endfor
1978   max_dir_length = terminal_size()(2) - max_name_length - ...
1979                    max_version_length - 7;
1980   if (max_dir_length < 20)
1981     max_dir_length = Inf;
1982   endif
1984   h1 = postpad (h1, max_name_length + 1, " ");
1985   h2 = postpad (h2, max_version_length, " ");
1987   ## Print a header.
1988   header = sprintf("%s | %s | %s\n", h1, h2, h3);
1989   printf (header);
1990   tmp = sprintf (repmat ("-", 1, length(header)-1));
1991   tmp(length(h1)+2) = "+";
1992   tmp(length(h1)+length(h2)+5) = "+";
1993   printf ("%s\n", tmp);
1995   ## Print the packages.
1996   format = sprintf ("%%%ds %%1s| %%%ds | %%s\n", max_name_length,
1997                     max_version_length);
1998   [dummy, idx] = sort (names);
1999   for i = 1:num_packages
2000     cur_name = installed_pkgs_lst{idx(i)}.name;
2001     cur_version = installed_pkgs_lst{idx(i)}.version;
2002     cur_dir = installed_pkgs_lst{idx(i)}.dir;
2003     if (length (cur_dir) > max_dir_length)
2004       first_char = length (cur_dir) - max_dir_length + 4;
2005       first_filesep = strfind (cur_dir(first_char:end), filesep());
2006       if (! isempty (first_filesep))
2007         cur_dir = cstrcat ("...",
2008                            cur_dir((first_char + first_filesep(1) - 1):end));
2009       else
2010         cur_dir = cstrcat ("...", cur_dir(first_char:end));
2011       endif
2012     endif
2013     if (installed_pkgs_lst{idx(i)}.loaded)
2014       cur_loaded = "*";
2015     else
2016       cur_loaded = " ";
2017     endif
2018     printf (format, cur_name, cur_loaded, cur_version, cur_dir);
2019   endfor
2020 endfunction
2022 function load_packages (files, handle_deps, local_list, global_list)
2023   installed_pkgs_lst = installed_packages (local_list, global_list);
2024   num_packages = length (installed_pkgs_lst);
2026   ## Read package names and installdirs into a more convenient format.
2027   pnames = pdirs = cell (1, num_packages);
2028   for i = 1:num_packages
2029     pnames{i} = installed_pkgs_lst{i}.name;
2030     pdirs{i} = installed_pkgs_lst{i}.dir;
2031   endfor
2033   ## Load all.
2034   if (length (files) == 1 && strcmp (files{1}, "all"))
2035     idx = [1:length(installed_pkgs_lst)];
2036     ## Load auto.
2037   elseif (length (files) == 1 && strcmp (files{1}, "auto"))
2038     idx = [];
2039     for i = 1:length (installed_pkgs_lst)
2040       if (exist (fullfile (pdirs{i}, "packinfo", ".autoload"), "file"))
2041         idx (end + 1) = i;
2042       endif
2043     endfor
2044     ## Load package_name1 ...
2045   else
2046     idx = [];
2047     for i = 1:length (files)
2048       idx2 = find (strcmp (pnames, files{i}));
2049       if (! any (idx2))
2050         error ("package %s is not installed", files{i});
2051       endif
2052       idx (end + 1) = idx2;
2053     endfor
2054   endif
2056   ## Load the packages, but take care of the ordering of dependencies.
2057   load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst, true);
2058 endfunction
2060 function unload_packages (files, handle_deps, local_list, global_list)
2061   installed_pkgs_lst = installed_packages (local_list, global_list);
2062   num_packages = length (installed_pkgs_lst);
2064   ## Read package names and installdirs into a more convenient format.
2065   pnames = pdirs = cell (1, num_packages);
2066   for i = 1:num_packages
2067     pnames{i} = installed_pkgs_lst{i}.name;
2068     pdirs{i} = installed_pkgs_lst{i}.dir;
2069     pdeps{i} = installed_pkgs_lst{i}.depends;
2070   endfor
2072   ## Get the current octave path.
2073   p = split_by (path(), pathsep ());
2075   if (length (files) == 1 && strcmp (files{1}, "all"))
2076     ## Unload all.
2077     dirs = pdirs;
2078     desc = installed_pkgs_lst;
2079   else
2080     ## Unload package_name1 ...
2081     dirs = {};
2082     desc = {};
2083     for i = 1:length (files)
2084       idx = strcmp (pnames, files{i});
2085       if (! any (idx))
2086         error ("package %s is not installed", files{i});
2087       endif
2088       dirs{end+1} = pdirs{idx};
2089       desc{end+1} = installed_pkgs_lst{idx};
2090     endfor
2091   endif
2093   ## Check for architecture dependent directories.
2094   archdirs = {};
2095   for i = 1:length (dirs)
2096     tmpdir = getarchdir (desc{i});
2097     if (exist (tmpdir, "dir"))
2098       archdirs{end+1} = dirs{i};
2099       archdirs{end+1} = tmpdir;
2100     else
2101       archdirs{end+1} = dirs{i};
2102     endif
2103   endfor
2105   ## Unload the packages.
2106   for i = 1:length (archdirs)
2107     d = archdirs{i};
2108     idx = strcmp (p, d);
2109     if (any (idx))
2110       rmpath (d);
2111       ## FIXME: We should also check if we need to remove items from
2112       ## EXEC_PATH.
2113     endif
2114   endfor
2115 endfunction
2117 function [status_out, msg_out] = rm_rf (dir)
2118   if (exist (dir))
2119     crr = confirm_recursive_rmdir ();
2120     unwind_protect
2121       confirm_recursive_rmdir (false);
2122       [status, msg] = rmdir (dir, "s");
2123     unwind_protect_cleanup
2124       confirm_recursive_rmdir (crr);
2125     end_unwind_protect
2126   else
2127     status = 1;
2128     msg = "";
2129   endif
2130   if (nargout > 0)
2131     status_out = status;
2132   endif
2133   if (nargout > 1)
2134     msg_out = msg;
2135   endif
2136 endfunction
2138 function emp = dirempty (nm, ign)
2139   if (exist (nm, "dir"))
2140     if (nargin < 2)
2141       ign = {".", ".."};
2142     else
2143       ign = [{".", ".."}, ign];
2144     endif
2145     l = dir (nm);
2146     for i = 1:length (l)
2147       found = false;
2148       for j = 1:length (ign)
2149         if (strcmp (l(i).name, ign{j}))
2150           found = true;
2151           break;
2152         endif
2153       endfor
2154       if (! found)
2155         emp = false;
2156         return
2157       endif
2158     endfor
2159     emp = true;
2160   else
2161     emp = true;
2162   endif
2163 endfunction
2165 function arch = getarch ()
2166   persistent _arch = cstrcat (octave_config_info("canonical_host_type"), ...
2167                               "-", octave_config_info("api_version"));
2168   arch = _arch;
2169 endfunction
2171 function archprefix = getarchprefix (desc, global_install)
2172   if ((nargin == 2 && global_install) || (nargin < 2 && issuperuser ()))
2173     archprefix = fullfile (octave_config_info ("libexecdir"), "octave",
2174                            "packages", cstrcat(desc.name, "-", desc.version));
2175   else
2176     archprefix = desc.dir;
2177   endif
2178 endfunction
2180 function archdir = getarchdir (desc)
2181   archdir = fullfile (desc.archprefix, getarch());
2182 endfunction
2184 function s = issuperuser ()
2185   if ((ispc () && ! isunix ()) || (geteuid() == 0))
2186     s = true;
2187   else
2188     s = false;
2189   endif
2190 endfunction
2192 function [status, output] = shell (cmd)
2193   persistent have_sh;
2195   cmd = strrep (cmd, "\\", "/");
2196   if (ispc () && ! isunix ())
2197     if (isempty(have_sh))
2198       if (system("sh.exe -c \"exit\""))
2199         have_sh = false;
2200       else
2201         have_sh = true;
2202       endif
2203     endif
2204     if (have_sh)
2205       [status, output] = system (cstrcat ("sh.exe -c \"", cmd, "\""));
2206     else
2207       error ("Can not find the command shell")
2208     endif
2209   else
2210     [status, output] = system (cmd);
2211   endif
2212 endfunction
2214 function newdesc = save_order (desc)
2215   newdesc = {};
2216   for i = 1 : length(desc)
2217     deps = desc{i}.depends;
2218     if (isempty (deps) || (length (deps) == 1 &&
2219                            strcmp(deps{1}.package, "octave")))
2220       newdesc {end + 1} = desc{i};
2221     else
2222       tmpdesc = {};
2223       for k = 1 : length (deps)
2224         for j = 1 : length (desc)
2225           if (strcmp (desc{j}.name, deps{k}.package))
2226             tmpdesc{end+1} = desc{j};
2227             break;
2228           endif
2229         endfor
2230       endfor
2231       if (! isempty (tmpdesc))
2232         newdesc = {newdesc{:}, save_order(tmpdesc){:}, desc{i}};
2233       else
2234         newdesc{end+1} = desc{i};
2235       endif
2236     endif
2237   endfor
2238   ## Eliminate the duplicates.
2239   idx = [];
2240   for i = 1 : length (newdesc)
2241     for j = (i + 1) : length (newdesc)
2242       if (strcmp (newdesc{i}.name, newdesc{j}.name))
2243         idx (end + 1) = j;
2244       endif
2245     endfor
2246   endfor
2247   newdesc(idx) = [];
2248 endfunction
2250 function load_packages_and_dependencies (idx, handle_deps, installed_pkgs_lst,
2251                                          global_install)
2252   idx = load_package_dirs (idx, [], handle_deps, installed_pkgs_lst);
2253   dirs = {};
2254   execpath = EXEC_PATH ();
2255   for i = idx;
2256     ndir = installed_pkgs_lst{i}.dir;
2257     dirs{end+1} = ndir;
2258     if (exist (fullfile (dirs{end}, "bin"), "dir"))
2259       execpath = cstrcat (fullfile (dirs{end}, "bin"), ":", execpath);
2260     endif
2261     tmpdir = getarchdir (installed_pkgs_lst{i});
2262     if (exist (tmpdir, "dir"))
2263       dirs{end + 1} = tmpdir;
2264       if (exist (fullfile (dirs{end}, "bin"), "dir"))
2265         execpath = cstrcat (fullfile (dirs{end}, "bin"), ":", execpath);
2266       endif
2267     endif
2268   endfor
2270   ## Load the packages.
2271   if (length (dirs) > 0)
2272     addpath (dirs{:});
2273   endif
2275   ## Add the binaries to exec_path.
2276   if (! strcmp (EXEC_PATH, execpath))
2277     EXEC_PATH (execpath);
2278   endif
2279 endfunction
2281 function idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst)
2282   for i = lidx
2283     if (isfield (installed_pkgs_lst{i}, "loaded") &&
2284         installed_pkgs_lst{i}.loaded)
2285       continue;
2286     else
2287       if (handle_deps)
2288         deps = installed_pkgs_lst{i}.depends;
2289         if ((length (deps) > 1) || (length (deps) == 1 &&
2290                                     ! strcmp(deps{1}.package, "octave")))
2291           tmplidx = [];
2292           for k = 1 : length (deps)
2293             for j = 1 : length (installed_pkgs_lst)
2294               if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package))
2295                 tmplidx (end + 1) = j;
2296                 break;
2297               endif
2298             endfor
2299           endfor
2300           idx = load_package_dirs (tmplidx, idx, handle_deps,
2301                                    installed_pkgs_lst);
2302         endif
2303       endif
2304       if (isempty (find(idx == i)))
2305         idx (end + 1) = i;
2306       endif
2307     endif
2308   endfor
2309 endfunction
2311 function dep = is_architecture_dependent (nm)
2312   persistent archdepsuffix = {".oct",".mex",".a",".lib",".so",".so.*",".dll","dylib"};
2314   dep = false;
2315   for i = 1 : length (archdepsuffix)
2316     ext = archdepsuffix{i};
2317     if (ext(end) == "*")
2318       isglob = true;
2319       ext(end) = [];
2320     else
2321       isglob = false;           # I am a test
2322                                 #%% me too
2323 ### I shall align to column 0
2324     endif
2325     pos = findstr (nm, ext);
2326     if (pos)
2327       if (! isglob && (length(nm) - pos(end) != length(ext) - 1))
2328         continue;
2329       endif
2330       dep = true;
2331       break;
2332     endif
2333   endfor
2334 endfunction
2336 %!assert(norm(logm([1 -1;0 1]) - [0 -1; 0 0]) < 1e-5);
2337 %!assert(norm(expm(logm([-1 2 ; 4 -1])) - [-1 2 ; 4 -1]) < 1e-5);
2338 %!assert(logm([1 -1 -1;0 1 -1; 0 0 1]), [0 -1 -1.5; 0 0 -1; 0 0 0], 1e-5);
2339 %!assert (logm (expm ([0 1i; -1i 0])), [0 1i; -1i 0], 10 * eps)
2341 %% Test input validation
2342 %!error logm ();
2343 %!error logm (1, 2, 3);
2344 %!error <logm: A must be a square matrix> logm([1 0;0 1; 2 2]);
2346 %!assert (logm (10), log (10))
2347 %!assert (full (logm (eye (3))), logm (full (eye (3))))
2348 %!assert (full (logm (10*eye (3))), logm (full (10*eye (3))), 8*eps)