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