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