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