changeset 21615:9ccd64201b4d

pkg: remove excessive number of private function files. pkg() makes use of many subfunctions, themselves with several subfunctions. They used to all be in a single file which became difficult to hack so it was split into one file per function (even though they all remained private). This change merges some of those functions back together so that only the functions used by pkg itself, as well as subfunctions used by more than one of those, remain as separate files. * copy_built_files.m, copy_files.m, create_pkgadddel.m, extract_pkg.m, finish_installation.m, generate_lookfor_cache.m, prepare_installation.m, verify_directory.m: merged this functions into install.m since they are only used by it. * fix_depends.m, fix_version.m: merged this functions into get_description.m since they are only used by it. * getarchprefix.m: merged into create_pkgadddel.m which then got merged into install.m. * is_architecture_dependent.m: merged into copy_built_files.m which then got merged into install.m. * load_package_dirs.m: merged into load_packages_and_dependencies.m * packinfo_copy_file.m, write_index.m: merged into copy_files.m which then then got merged into install.m. * parse_pkg_idx, print_package_description.m: merged into describe.m * shell.m: merged into configure_make.m * pkg/module.mk: update with removed files.
author Carnë Draug <carandraug@octave.org>
date Tue, 12 Apr 2016 17:46:20 +0100
parents 9bb39b754ab1
children 32cd60419b61
files scripts/pkg/module.mk scripts/pkg/private/configure_make.m scripts/pkg/private/copy_built_files.m scripts/pkg/private/copy_files.m scripts/pkg/private/create_pkgadddel.m scripts/pkg/private/describe.m scripts/pkg/private/extract_pkg.m scripts/pkg/private/finish_installation.m scripts/pkg/private/fix_depends.m scripts/pkg/private/fix_version.m scripts/pkg/private/generate_lookfor_cache.m scripts/pkg/private/get_description.m scripts/pkg/private/getarchprefix.m scripts/pkg/private/install.m scripts/pkg/private/is_architecture_dependent.m scripts/pkg/private/load_package_dirs.m scripts/pkg/private/load_packages_and_dependencies.m scripts/pkg/private/packinfo_copy_file.m scripts/pkg/private/parse_pkg_idx.m scripts/pkg/private/prepare_installation.m scripts/pkg/private/print_package_description.m scripts/pkg/private/shell.m scripts/pkg/private/verify_directory.m scripts/pkg/private/write_index.m
diffstat 24 files changed, 675 insertions(+), 1117 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/pkg/module.mk	Tue Apr 12 10:36:36 2016 -0400
+++ b/scripts/pkg/module.mk	Tue Apr 12 17:46:20 2016 +0100
@@ -5,42 +5,24 @@
 scripts_pkg_PRIVATE_FCN_FILES = \
   scripts/pkg/private/build.m \
   scripts/pkg/private/configure_make.m \
-  scripts/pkg/private/copy_built_files.m \
-  scripts/pkg/private/copy_files.m \
-  scripts/pkg/private/create_pkgadddel.m \
   scripts/pkg/private/default_prefix.m \
   scripts/pkg/private/describe.m \
   scripts/pkg/private/dirempty.m \
-  scripts/pkg/private/extract_pkg.m \
-  scripts/pkg/private/finish_installation.m \
-  scripts/pkg/private/fix_depends.m \
-  scripts/pkg/private/fix_version.m \
-  scripts/pkg/private/generate_lookfor_cache.m \
   scripts/pkg/private/get_description.m \
   scripts/pkg/private/get_forge_download.m \
   scripts/pkg/private/get_forge_pkg.m \
   scripts/pkg/private/getarch.m \
   scripts/pkg/private/getarchdir.m \
-  scripts/pkg/private/getarchprefix.m \
   scripts/pkg/private/get_unsatisfied_deps.m \
   scripts/pkg/private/install.m \
   scripts/pkg/private/installed_packages.m \
-  scripts/pkg/private/is_architecture_dependent.m \
   scripts/pkg/private/list_forge_packages.m \
-  scripts/pkg/private/load_package_dirs.m \
   scripts/pkg/private/load_packages.m \
   scripts/pkg/private/load_packages_and_dependencies.m \
-  scripts/pkg/private/packinfo_copy_file.m \
-  scripts/pkg/private/parse_pkg_idx.m \
-  scripts/pkg/private/prepare_installation.m \
-  scripts/pkg/private/print_package_description.m \
   scripts/pkg/private/rebuild.m \
   scripts/pkg/private/save_order.m \
-  scripts/pkg/private/shell.m \
   scripts/pkg/private/uninstall.m \
-  scripts/pkg/private/unload_packages.m \
-  scripts/pkg/private/verify_directory.m \
-  scripts/pkg/private/write_index.m
+  scripts/pkg/private/unload_packages.m
 
 scripts_pkg_FCN_FILES = scripts/pkg/pkg.m
 
--- a/scripts/pkg/private/configure_make.m	Tue Apr 12 10:36:36 2016 -0400
+++ b/scripts/pkg/private/configure_make.m	Tue Apr 12 17:46:20 2016 +0100
@@ -97,3 +97,40 @@
 
   endif
 endfunction
+
+## Executes a shell command. In the end it calls system() but in case of
+## windows will first check if sh.exe works.
+##
+## If VERBOSE is true, it will prints the output to STDOUT in real time and
+## the second output argument will be an empty string. Otherwise, it will
+## contain the output of the execeuted command.
+function [status, output] = shell (cmd, verbose)
+  persistent have_sh;
+
+  cmd = strrep (cmd, "\\", "/");
+  if (ispc () && ! isunix ())
+    if (isempty (have_sh))
+      if (system ('sh.exe -c "exit"'))
+        have_sh = false;
+      else
+        have_sh = true;
+      endif
+    endif
+    if (have_sh)
+      cmd = ['sh.exe -c "' cmd '"'];
+    else
+      error ("pkg: unable to find the command shell.");
+    endif
+  endif
+  ## if verbose, we want to display the output in real time. To do this, we
+  ## must call system with 1 output argument. But then the variable `output'
+  ## won't exist. So we initialize it empty. If an error does occur, and we
+  ## are verbose we will return an empty string but it's all fine since
+  ## the error message has already been displayed.
+  output = "";
+  if (verbose)
+    [status] = system (cmd);
+  else
+    [status, output] = system (cmd);
+  endif
+endfunction
--- a/scripts/pkg/private/copy_built_files.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} copy_built_files (@var{desc}, @var{packdir}, @var{verbose})
-## Undocumented internal function.
-## @end deftypefn
-
-function copy_built_files (desc, packdir, verbose)
-
-  src = fullfile (packdir, "src");
-  if (! exist (src, "dir"))
-    return
-  endif
-
-  ## Copy files to "inst" and "inst/arch" (this is instead of 'make install').
-  files = fullfile (src, "FILES");
-  instdir = fullfile (packdir, "inst");
-  archdir = fullfile (packdir, "inst", getarch ());
-
-  ## Get filenames.
-  if (exist (files, "file"))
-    [fid, msg] = fopen (files, "r");
-    if (fid < 0)
-      error ("couldn't open %s: %s", files, msg);
-    endif
-    filenames = char (fread (fid))';
-    fclose (fid);
-    if (filenames(end) == "\n")
-      filenames(end) = [];
-    endif
-    filenames = strtrim (ostrsplit (filenames, "\n"));
-    delete_idx = [];
-    for i = 1:length (filenames)
-      if (! all (isspace (filenames{i})))
-        filenames{i} = fullfile (src, filenames{i});
-      else
-        delete_idx(end+1) = i;
-      endif
-    endfor
-    filenames(delete_idx) = [];
-  else
-    m = dir (fullfile (src, "*.m"));
-    oct = dir (fullfile (src, "*.oct"));
-    mex = dir (fullfile (src, "*.mex"));
-
-    filenames = cellfun (@(x) fullfile (src, x),
-                         {m.name, oct.name, mex.name},
-                         "uniformoutput", false);
-  endif
-
-  ## Split into architecture dependent and independent files.
-  if (isempty (filenames))
-    idx = [];
-  else
-    idx = cellfun ("is_architecture_dependent", filenames);
-  endif
-  archdependent = filenames(idx);
-  archindependent = filenames(! idx);
-
-  ## Copy the files.
-  if (! all (isspace ([filenames{:}])))
-      if (! exist (instdir, "dir"))
-        mkdir (instdir);
-      endif
-      if (! all (isspace ([archindependent{:}])))
-        if (verbose)
-          printf ("copyfile");
-          printf (" %s", archindependent{:});
-          printf ("%s\n", instdir);
-        endif
-        [status, output] = copyfile (archindependent, instdir);
-        if (status != 1)
-          rmdir (desc.dir, "s");
-          error ("Couldn't copy files from 'src' to 'inst': %s", output);
-        endif
-      endif
-      if (! all (isspace ([archdependent{:}])))
-        if (verbose)
-          printf ("copyfile");
-          printf (" %s", archdependent{:});
-          printf (" %s\n", archdir);
-        endif
-        if (! exist (archdir, "dir"))
-          mkdir (archdir);
-        endif
-        [status, output] = copyfile (archdependent, archdir);
-        if (status != 1)
-          rmdir (desc.dir, "s");
-          error ("Couldn't copy files from 'src' to 'inst': %s", output);
-        endif
-      endif
-  endif
-endfunction
--- a/scripts/pkg/private/copy_files.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} copy_files (@var{desc}, @var{packdir}, @var{global_install})
-## Undocumented internal function.
-## @end deftypefn
-
-function copy_files (desc, packdir, global_install)
-  ## Create the installation directory.
-  if (! exist (desc.dir, "dir"))
-    [status, output] = mkdir (desc.dir);
-    if (status != 1)
-      error ("couldn't create installation directory %s : %s",
-      desc.dir, output);
-    endif
-  endif
-
-  octfiledir = getarchdir (desc);
-
-  ## Copy the files from "inst" to installdir.
-  instdir = fullfile (packdir, "inst");
-  if (! dirempty (instdir))
-    [status, output] = copyfile (fullfile (instdir, "*"), desc.dir);
-    if (status != 1)
-      rmdir (desc.dir, "s");
-      error ("couldn't copy files to the installation directory");
-    endif
-    if (exist (fullfile (desc.dir, getarch ()), "dir")
-        && ! strcmp (fullfile (desc.dir, getarch ()), octfiledir))
-      if (! exist (octfiledir, "dir"))
-        ## Can be required to create upto three levels of dirs.
-        octm1 = fileparts (octfiledir);
-        if (! exist (octm1, "dir"))
-          octm2 = fileparts (octm1);
-          if (! exist (octm2, "dir"))
-            octm3 = fileparts (octm2);
-            if (! exist (octm3, "dir"))
-              [status, output] = mkdir (octm3);
-              if (status != 1)
-                rmdir (desc.dir, "s");
-                error ("couldn't create installation directory %s : %s",
-                       octm3, output);
-              endif
-            endif
-            [status, output] = mkdir (octm2);
-            if (status != 1)
-              rmdir (desc.dir, "s");
-              error ("couldn't create installation directory %s : %s",
-                     octm2, output);
-            endif
-          endif
-          [status, output] = mkdir (octm1);
-          if (status != 1)
-            rmdir (desc.dir, "s");
-            error ("couldn't create installation directory %s : %s",
-                   octm1, output);
-          endif
-        endif
-        [status, output] = mkdir (octfiledir);
-        if (status != 1)
-          rmdir (desc.dir, "s");
-          error ("couldn't create installation directory %s : %s",
-          octfiledir, output);
-        endif
-      endif
-      [status, output] = movefile (fullfile (desc.dir, getarch (), "*"),
-                                   octfiledir);
-      rmdir (fullfile (desc.dir, getarch ()), "s");
-
-      if (status != 1)
-        rmdir (desc.dir, "s");
-        rmdir (octfiledir, "s");
-        error ("couldn't copy files to the installation directory");
-      endif
-    endif
-
-  endif
-
-  ## Create the "packinfo" directory.
-  packinfo = fullfile (desc.dir, "packinfo");
-  [status, msg] = mkdir (packinfo);
-  if (status != 1)
-    rmdir (desc.dir, "s");
-    rmdir (octfiledir, "s");
-    error ("couldn't create packinfo directory: %s", msg);
-  endif
-
-  packinfo_copy_file ("DESCRIPTION", "required", packdir, packinfo, desc, octfiledir);
-  packinfo_copy_file ("COPYING", "required", packdir, packinfo, desc, octfiledir);
-  packinfo_copy_file ("CITATION", "optional", packdir, packinfo, desc, octfiledir);
-  packinfo_copy_file ("NEWS", "optional", packdir, packinfo, desc, octfiledir);
-  packinfo_copy_file ("ONEWS", "optional", packdir, packinfo, desc, octfiledir);
-  packinfo_copy_file ("ChangeLog", "optional", packdir, packinfo, desc, octfiledir);
-
-  ## Is there an INDEX file to copy or should we generate one?
-  index_file = fullfile (packdir, "INDEX");
-  if (exist (index_file, "file"))
-    packinfo_copy_file ("INDEX", "required", packdir, packinfo, desc, octfiledir);
-  else
-    try
-      write_index (desc, fullfile (packdir, "inst"),
-                   fullfile (packinfo, "INDEX"), global_install);
-    catch
-      rmdir (desc.dir, "s");
-      rmdir (octfiledir, "s");
-      rethrow (lasterror ());
-    end_try_catch
-  endif
-
-  ## Is there an 'on_uninstall.m' to install?
-  packinfo_copy_file ("on_uninstall.m", "optional", packdir, packinfo, desc, octfiledir);
-
-  ## Is there a doc/ directory that needs to be installed?
-  docdir = fullfile (packdir, "doc");
-  if (exist (docdir, "dir") && ! dirempty (docdir))
-    [status, output] = copyfile (docdir, desc.dir);
-  endif
-
-  ## Is there a bin/ directory that needs to be installed?
-  ## FIXME: Need to treat architecture dependent files in bin/
-  bindir = fullfile (packdir, "bin");
-  if (exist (bindir, "dir") && ! dirempty (bindir))
-    [status, output] = copyfile (bindir, desc.dir);
-  endif
-endfunction
-
--- a/scripts/pkg/private/create_pkgadddel.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} create_pkgadddel (@var{desc}, @var{packdir}, @var{nm}, @var{global_install})
-## Undocumented internal function.
-## @end deftypefn
-
-function create_pkgadddel (desc, packdir, nm, global_install)
-  instpkg = fullfile (desc.dir, nm);
-  instfid = fopen (instpkg, "at"); # append to support PKG_ADD at inst/
-  ## If it is exists, most of the PKG_* file should go into the
-  ## architecture dependent directory so that the autoload/mfilename
-  ## commands work as expected. The only part that doesn't is the
-  ## part in the main directory.
-  archdir = fullfile (getarchprefix (desc, global_install),
-                      [desc.name "-" desc.version], getarch ());
-  if (exist (getarchdir (desc, global_install), "dir"))
-    archpkg = fullfile (getarchdir (desc, global_install), nm);
-    archfid = fopen (archpkg, "at");
-  else
-    archpkg = instpkg;
-    archfid = instfid;
-  endif
-
-  if (archfid >= 0 && instfid >= 0)
-    ## Search all dot-m files for PKG commands.
-    lst = dir (fullfile (packdir, "inst", "*.m"));
-    for i = 1:length (lst)
-      nam = fullfile (packdir, "inst", lst(i).name);
-      fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$']));
-    endfor
-
-    ## Search all C++ source files for PKG commands.
-    lst = dir (fullfile (packdir, "src", "*.cc"));
-    for i = 1:length (lst)
-      nam = fullfile (packdir, "src", lst(i).name);
-      fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$']));
-      fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$']));
-    endfor
-
-    ## Add developer included PKG commands.
-    packdirnm = fullfile (packdir, nm);
-    if (exist (packdirnm, "file"))
-      fid = fopen (packdirnm, "rt");
-      if (fid >= 0)
-        while (! feof (fid))
-          ln = fgets (fid);
-          if (ln > 0)
-            fwrite (archfid, ln);
-          endif
-        endwhile
-        fclose (fid);
-      endif
-    endif
-
-    ## If the files is empty remove it.
-    fclose (instfid);
-    t = dir (instpkg);
-    if (t.bytes <= 0)
-      unlink (instpkg);
-    endif
-
-    if (instfid != archfid)
-      fclose (archfid);
-      t = dir (archpkg);
-      if (t.bytes <= 0)
-        unlink (archpkg);
-      endif
-    endif
-  endif
-endfunction
-
--- a/scripts/pkg/private/describe.m	Tue Apr 12 10:36:36 2016 -0400
+++ b/scripts/pkg/private/describe.m	Tue Apr 12 17:46:20 2016 +0100
@@ -82,6 +82,77 @@
                                  flag{i}, verbose);
     endfor
   endif
-
 endfunction
 
+
+## Read an INDEX file.
+function pkg_idx_struct = parse_pkg_idx (packdir)
+
+  index_file = fullfile (packdir, "packinfo", "INDEX");
+
+  if (! exist (index_file, "file"))
+    error ("could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files", packdir);
+  endif
+
+
+  [fid, msg] = fopen (index_file, "r");
+  if (fid == -1)
+    error ("the INDEX file %s could not be read: %s",
+           index_file, msg);
+  endif
+
+  cat_num = 1;
+  pkg_idx_struct{1}.category = "Uncategorized";
+  pkg_idx_struct{1}.functions = {};
+
+  line = fgetl (fid);
+  while (isempty (strfind (line, ">>")) && ! feof (fid))
+    line = fgetl (fid);
+  endwhile
+
+  while (! feof (fid) || line != -1)
+    if (! any (! isspace (line)) || line(1) == "#" || any (line == "="))
+      ## Comments,  blank lines or comments about unimplemented
+      ## functions: do nothing
+      ## FIXME: probably comments and pointers to external functions
+      ## could be treated better when printing to screen?
+    elseif (! isempty (strfind (line, ">>")))
+      ## Skip package name and description as they are in DESCRIPTION
+      ## already.
+    elseif (! isspace (line(1)))
+      ## Category.
+      if (! isempty (pkg_idx_struct{cat_num}.functions))
+        pkg_idx_struct{++cat_num}.functions = {};
+      endif
+      pkg_idx_struct{cat_num}.category = deblank (line);
+    else
+      ## Function names.
+      while (any (! isspace (line)))
+        [fun_name, line] = strtok (line);
+        pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name);
+      endwhile
+    endif
+    line = fgetl (fid);
+  endwhile
+  fclose (fid);
+endfunction
+
+
+function print_package_description (pkg_name, pkg_ver, pkg_idx_struct,
+                                    pkg_desc, status, verbose)
+  printf ("---\nPackage name:\n\t%s\n", pkg_name);
+  printf ("Version:\n\t%s\n", pkg_ver);
+  printf ("Short description:\n\t%s\n", pkg_desc);
+  printf ("Status:\n\t%s\n", status);
+  if (verbose)
+    printf ("---\nProvides:\n");
+    for i = 1:length (pkg_idx_struct)
+      if (! isempty (pkg_idx_struct{i}.functions))
+        printf ("%s\n", pkg_idx_struct{i}.category);
+        for j = 1:length (pkg_idx_struct{i}.functions)
+          printf ("\t%s\n", pkg_idx_struct{i}.functions{j});
+        endfor
+      endif
+    endfor
+  endif
+endfunction
--- a/scripts/pkg/private/extract_pkg.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{pkg} =} extract_pkg (@var{nm}, @var{pat})
-## Undocumented internal function.
-## @end deftypefn
-
-function pkg = extract_pkg (nm, pat)
-  fid = fopen (nm, "rt");
-  pkg = "";
-  if (fid >= 0)
-    while (! feof (fid))
-      ln = fgetl (fid);
-      if (ln > 0)
-        t = regexp (ln, pat, "tokens");
-        if (! isempty (t))
-          pkg = [pkg "\n" t{1}{1}];
-        endif
-      endif
-    endwhile
-    if (! isempty (pkg))
-      pkg = [pkg "\n"];
-    endif
-    fclose (fid);
-  endif
-endfunction
-
--- a/scripts/pkg/private/finish_installation.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} finish_installation (@var{desc}, @var{packdir}, @var{global_install})
-## Undocumented internal function.
-## @end deftypefn
-
-function finish_installation (desc, packdir, global_install)
-  ## Is there a post-install to call?
-  if (exist (fullfile (packdir, "post_install.m"), "file"))
-    wd = pwd ();
-    try
-      cd (packdir);
-      post_install (desc);
-      cd (wd);
-    catch
-      cd (wd);
-      rmdir (desc.dir, "s");
-      rmdir (getarchdir (desc), "s");
-      rethrow (lasterror ());
-    end_try_catch
-  endif
-endfunction
-
--- a/scripts/pkg/private/fix_depends.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{deps_cell} =} fix_depends (@var{depends})
-## Undocumented internal function.
-## @end deftypefn
-
-## Make sure the depends field is of the right format.
-## This function returns a cell of structures with the following fields:
-##   package, version, operator
-function deps_cell = fix_depends (depends)
-  deps = strtrim (ostrsplit (tolower (depends), ","));
-  deps_cell = cell (1, length (deps));
-  dep_pat = ...
-  '\s*(?<name>[-\w]+)\s*(\(\s*(?<op>[<>=]+)\s*(?<ver>\d+\.\d+(\.\d+)*)\s*\))*\s*';
-
-  ## For each dependency.
-  for i = 1:length (deps)
-    dep = deps{i};
-    [start, nm] = regexp (dep, dep_pat, 'start', 'names');
-    ## Is the dependency specified
-    ## in the correct format?
-    if (! isempty (start))
-      package = tolower (strtrim (nm.name));
-      ## Does the dependency specify a version
-      ## Example: package(>= version).
-      if (! isempty (nm.ver))
-        operator = nm.op;
-        if (! any (strcmp (operator, {">", ">=", "<=", "<", "=="})))
-          error ("unsupported operator: %s", operator);
-        endif
-        version = fix_version (nm.ver);
-        ## If no version is specified for the dependency
-        ## we say that the version should be greater than
-        ## or equal to "0.0.0".
-      else
-        package = tolower (strtrim (dep));
-        operator = ">=";
-        version = "0.0.0";
-      endif
-      deps_cell{i} = struct ("package", package,
-                             "operator", operator,
-                             "version", version);
-    else
-      error ("incorrect syntax for dependency '%s' in the DESCRIPTION file\n",
-             dep);
-    endif
-  endfor
-endfunction
-
--- a/scripts/pkg/private/fix_version.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{out} =} fix_version (@var{v})
-## Undocumented internal function.
-## @end deftypefn
-
-## Make sure the version string v is a valid x.y.z version string
-## Examples: "0.1" => "0.1.0", "monkey" => error(...).
-function out = fix_version (v)
-
-  if (regexp (v, '^\d+(\.\d+){1,2}$') == 1)
-    parts = ostrsplit (v, '.', true);
-    if (numel (parts) == 2)
-      out = [v ".0"];
-    else
-      out = v;
-    endif
-  else
-    error ("bad version string: %s", v);
-  endif
-
-endfunction
-
--- a/scripts/pkg/private/generate_lookfor_cache.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} generate_lookfor_cache (@var{desc})
-## Undocumented internal function.
-## @end deftypefn
-
-function generate_lookfor_cache (desc)
-  dirs = strtrim (ostrsplit (genpath (desc.dir), pathsep ()));
-  for i = 1 : length (dirs)
-    doc_cache_create (fullfile (dirs{i}, "doc-cache"), dirs{i});
-  endfor
-endfunction
-
--- a/scripts/pkg/private/get_description.m	Tue Apr 12 10:36:36 2016 -0400
+++ b/scripts/pkg/private/get_description.m	Tue Apr 12 17:46:20 2016 +0100
@@ -78,3 +78,62 @@
   desc.name = tolower (desc.name);
 endfunction
 
+
+## Make sure the version string v is a valid x.y.z version string
+## Examples: "0.1" => "0.1.0", "monkey" => error(...).
+function out = fix_version (v)
+  if (regexp (v, '^\d+(\.\d+){1,2}$') == 1)
+    parts = ostrsplit (v, '.', true);
+    if (numel (parts) == 2)
+      out = [v ".0"];
+    else
+      out = v;
+    endif
+  else
+    error ("bad version string: %s", v);
+  endif
+endfunction
+
+
+## Make sure the depends field is of the right format.
+## This function returns a cell of structures with the following fields:
+##   package, version, operator
+function deps_cell = fix_depends (depends)
+  deps = strtrim (ostrsplit (tolower (depends), ","));
+  deps_cell = cell (1, length (deps));
+  dep_pat = ...
+  '\s*(?<name>[-\w]+)\s*(\(\s*(?<op>[<>=]+)\s*(?<ver>\d+\.\d+(\.\d+)*)\s*\))*\s*';
+
+  ## For each dependency.
+  for i = 1:length (deps)
+    dep = deps{i};
+    [start, nm] = regexp (dep, dep_pat, 'start', 'names');
+    ## Is the dependency specified
+    ## in the correct format?
+    if (! isempty (start))
+      package = tolower (strtrim (nm.name));
+      ## Does the dependency specify a version
+      ## Example: package(>= version).
+      if (! isempty (nm.ver))
+        operator = nm.op;
+        if (! any (strcmp (operator, {">", ">=", "<=", "<", "=="})))
+          error ("unsupported operator: %s", operator);
+        endif
+        version = fix_version (nm.ver);
+        ## If no version is specified for the dependency
+        ## we say that the version should be greater than
+        ## or equal to "0.0.0".
+      else
+        package = tolower (strtrim (dep));
+        operator = ">=";
+        version = "0.0.0";
+      endif
+      deps_cell{i} = struct ("package", package,
+                             "operator", operator,
+                             "version", version);
+    else
+      error ("incorrect syntax for dependency '%s' in the DESCRIPTION file\n",
+             dep);
+    endif
+  endfor
+endfunction
--- a/scripts/pkg/private/getarchprefix.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {[@var{archprefix} =} getarchprefix (@var{desc}, @var{global_install})
-## Undocumented internal function.
-## @end deftypefn
-
-function archprefix = getarchprefix (desc, global_install)
-  if (global_install)
-    [~, archprefix] = default_prefix (global_install, desc);
-  else
-    archprefix = desc.dir;
-  endif
-endfunction
-
--- a/scripts/pkg/private/install.m	Tue Apr 12 10:36:36 2016 -0400
+++ b/scripts/pkg/private/install.m	Tue Apr 12 17:46:20 2016 +0100
@@ -341,6 +341,478 @@
     printf ("For information about changes from previous versions of the %s package, run 'news %s'.\n",
             desc.name, desc.name);
   endif
+endfunction
 
+
+function pkg = extract_pkg (nm, pat)
+  fid = fopen (nm, "rt");
+  pkg = "";
+  if (fid >= 0)
+    while (! feof (fid))
+      ln = fgetl (fid);
+      if (ln > 0)
+        t = regexp (ln, pat, "tokens");
+        if (! isempty (t))
+          pkg = [pkg "\n" t{1}{1}];
+        endif
+      endif
+    endwhile
+    if (! isempty (pkg))
+      pkg = [pkg "\n"];
+    endif
+    fclose (fid);
+  endif
+endfunction
+
+
+## Make sure the package contains the essential files.
+function verify_directory (dir)
+  needed_files = {"COPYING", "DESCRIPTION"};
+  for f = needed_files
+    if (! exist (fullfile (dir, f{1}), "file"))
+      error ("package is missing file: %s", f{1});
+    endif
+  endfor
+endfunction
+
+
+function prepare_installation (desc, packdir)
+  ## Is there a pre_install to call?
+  if (exist (fullfile (packdir, "pre_install.m"), "file"))
+    wd = pwd ();
+    try
+      cd (packdir);
+      pre_install (desc);
+      cd (wd);
+    catch
+      cd (wd);
+      rethrow (lasterror ());
+    end_try_catch
+  endif
+
+  ## If the directory "inst" doesn't exist, we create it.
+  inst_dir = fullfile (packdir, "inst");
+  if (! exist (inst_dir, "dir"))
+    [status, msg] = mkdir (inst_dir);
+    if (status != 1)
+      rmdir (desc.dir, "s");
+      error ("the 'inst' directory did not exist and could not be created: %s",
+             msg);
+    endif
+  endif
+endfunction
+
+
+function copy_built_files (desc, packdir, verbose)
+  src = fullfile (packdir, "src");
+  if (! exist (src, "dir"))
+    return
+  endif
+
+  ## Copy files to "inst" and "inst/arch" (this is instead of 'make install').
+  files = fullfile (src, "FILES");
+  instdir = fullfile (packdir, "inst");
+  archdir = fullfile (packdir, "inst", getarch ());
+
+  ## Get filenames.
+  if (exist (files, "file"))
+    [fid, msg] = fopen (files, "r");
+    if (fid < 0)
+      error ("couldn't open %s: %s", files, msg);
+    endif
+    filenames = char (fread (fid))';
+    fclose (fid);
+    if (filenames(end) == "\n")
+      filenames(end) = [];
+    endif
+    filenames = strtrim (ostrsplit (filenames, "\n"));
+    delete_idx = [];
+    for i = 1:length (filenames)
+      if (! all (isspace (filenames{i})))
+        filenames{i} = fullfile (src, filenames{i});
+      else
+        delete_idx(end+1) = i;
+      endif
+    endfor
+    filenames(delete_idx) = [];
+  else
+    m = dir (fullfile (src, "*.m"));
+    oct = dir (fullfile (src, "*.oct"));
+    mex = dir (fullfile (src, "*.mex"));
+
+    filenames = cellfun (@(x) fullfile (src, x),
+                         {m.name, oct.name, mex.name},
+                         "uniformoutput", false);
+  endif
+
+  ## Split into architecture dependent and independent files.
+  if (isempty (filenames))
+    idx = [];
+  else
+    idx = cellfun ("is_architecture_dependent", filenames);
+  endif
+  archdependent = filenames(idx);
+  archindependent = filenames(! idx);
+
+  ## Copy the files.
+  if (! all (isspace ([filenames{:}])))
+      if (! exist (instdir, "dir"))
+        mkdir (instdir);
+      endif
+      if (! all (isspace ([archindependent{:}])))
+        if (verbose)
+          printf ("copyfile");
+          printf (" %s", archindependent{:});
+          printf ("%s\n", instdir);
+        endif
+        [status, output] = copyfile (archindependent, instdir);
+        if (status != 1)
+          rmdir (desc.dir, "s");
+          error ("Couldn't copy files from 'src' to 'inst': %s", output);
+        endif
+      endif
+      if (! all (isspace ([archdependent{:}])))
+        if (verbose)
+          printf ("copyfile");
+          printf (" %s", archdependent{:});
+          printf (" %s\n", archdir);
+        endif
+        if (! exist (archdir, "dir"))
+          mkdir (archdir);
+        endif
+        [status, output] = copyfile (archdependent, archdir);
+        if (status != 1)
+          rmdir (desc.dir, "s");
+          error ("Couldn't copy files from 'src' to 'inst': %s", output);
+        endif
+      endif
+  endif
+endfunction
+
+
+function dep = is_architecture_dependent (nm)
+  persistent archdepsuffix = {".oct",".mex",".a",".lib",".so",".so.*",".dll","dylib"};
+
+  dep = false;
+  for i = 1 : length (archdepsuffix)
+    ext = archdepsuffix{i};
+    if (ext(end) == "*")
+      isglob = true;
+      ext(end) = [];
+    else
+      isglob = false;
+    endif
+    pos = strfind (nm, ext);
+    if (pos)
+      if (! isglob && (length (nm) - pos(end) != length (ext) - 1))
+        continue;
+      endif
+      dep = true;
+      break;
+    endif
+  endfor
 endfunction
 
+
+function copy_files (desc, packdir, global_install)
+  ## Create the installation directory.
+  if (! exist (desc.dir, "dir"))
+    [status, output] = mkdir (desc.dir);
+    if (status != 1)
+      error ("couldn't create installation directory %s : %s",
+      desc.dir, output);
+    endif
+  endif
+
+  octfiledir = getarchdir (desc);
+
+  ## Copy the files from "inst" to installdir.
+  instdir = fullfile (packdir, "inst");
+  if (! dirempty (instdir))
+    [status, output] = copyfile (fullfile (instdir, "*"), desc.dir);
+    if (status != 1)
+      rmdir (desc.dir, "s");
+      error ("couldn't copy files to the installation directory");
+    endif
+    if (exist (fullfile (desc.dir, getarch ()), "dir")
+        && ! strcmp (fullfile (desc.dir, getarch ()), octfiledir))
+      if (! exist (octfiledir, "dir"))
+        ## Can be required to create upto three levels of dirs.
+        octm1 = fileparts (octfiledir);
+        if (! exist (octm1, "dir"))
+          octm2 = fileparts (octm1);
+          if (! exist (octm2, "dir"))
+            octm3 = fileparts (octm2);
+            if (! exist (octm3, "dir"))
+              [status, output] = mkdir (octm3);
+              if (status != 1)
+                rmdir (desc.dir, "s");
+                error ("couldn't create installation directory %s : %s",
+                       octm3, output);
+              endif
+            endif
+            [status, output] = mkdir (octm2);
+            if (status != 1)
+              rmdir (desc.dir, "s");
+              error ("couldn't create installation directory %s : %s",
+                     octm2, output);
+            endif
+          endif
+          [status, output] = mkdir (octm1);
+          if (status != 1)
+            rmdir (desc.dir, "s");
+            error ("couldn't create installation directory %s : %s",
+                   octm1, output);
+          endif
+        endif
+        [status, output] = mkdir (octfiledir);
+        if (status != 1)
+          rmdir (desc.dir, "s");
+          error ("couldn't create installation directory %s : %s",
+          octfiledir, output);
+        endif
+      endif
+      [status, output] = movefile (fullfile (desc.dir, getarch (), "*"),
+                                   octfiledir);
+      rmdir (fullfile (desc.dir, getarch ()), "s");
+
+      if (status != 1)
+        rmdir (desc.dir, "s");
+        rmdir (octfiledir, "s");
+        error ("couldn't copy files to the installation directory");
+      endif
+    endif
+
+  endif
+
+  ## Create the "packinfo" directory.
+  packinfo = fullfile (desc.dir, "packinfo");
+  [status, msg] = mkdir (packinfo);
+  if (status != 1)
+    rmdir (desc.dir, "s");
+    rmdir (octfiledir, "s");
+    error ("couldn't create packinfo directory: %s", msg);
+  endif
+
+  packinfo_copy_file ("DESCRIPTION", "required", packdir, packinfo, desc, octfiledir);
+  packinfo_copy_file ("COPYING", "required", packdir, packinfo, desc, octfiledir);
+  packinfo_copy_file ("CITATION", "optional", packdir, packinfo, desc, octfiledir);
+  packinfo_copy_file ("NEWS", "optional", packdir, packinfo, desc, octfiledir);
+  packinfo_copy_file ("ONEWS", "optional", packdir, packinfo, desc, octfiledir);
+  packinfo_copy_file ("ChangeLog", "optional", packdir, packinfo, desc, octfiledir);
+
+  ## Is there an INDEX file to copy or should we generate one?
+  index_file = fullfile (packdir, "INDEX");
+  if (exist (index_file, "file"))
+    packinfo_copy_file ("INDEX", "required", packdir, packinfo, desc, octfiledir);
+  else
+    try
+      write_index (desc, fullfile (packdir, "inst"),
+                   fullfile (packinfo, "INDEX"), global_install);
+    catch
+      rmdir (desc.dir, "s");
+      rmdir (octfiledir, "s");
+      rethrow (lasterror ());
+    end_try_catch
+  endif
+
+  ## Is there an 'on_uninstall.m' to install?
+  packinfo_copy_file ("on_uninstall.m", "optional", packdir, packinfo, desc, octfiledir);
+
+  ## Is there a doc/ directory that needs to be installed?
+  docdir = fullfile (packdir, "doc");
+  if (exist (docdir, "dir") && ! dirempty (docdir))
+    [status, output] = copyfile (docdir, desc.dir);
+  endif
+
+  ## Is there a bin/ directory that needs to be installed?
+  ## FIXME: Need to treat architecture dependent files in bin/
+  bindir = fullfile (packdir, "bin");
+  if (exist (bindir, "dir") && ! dirempty (bindir))
+    [status, output] = copyfile (bindir, desc.dir);
+  endif
+endfunction
+
+
+function packinfo_copy_file (filename, requirement, packdir, packinfo, desc, octfiledir)
+  filepath = fullfile (packdir, filename);
+  if (! exist (filepath, "file") && strcmpi (requirement, "optional"))
+    ## do nothing, it's still OK
+  else
+    [status, output] = copyfile (filepath, packinfo);
+    if (status != 1)
+      rmdir (desc.dir, "s");
+      rmdir (octfiledir, "s");
+      error ("Couldn't copy %s file: %s", filename, output);
+    endif
+  endif
+endfunction
+
+
+## Create an INDEX file for a package that doesn't provide one.
+##   'desc'  describes the package.
+##   'dir'   is the 'inst' directory in temporary directory.
+##   'index_file' is the name (including path) of resulting INDEX file.
+function write_index (desc, dir, index_file, global_install)
+  ## Get names of functions in dir
+  [files, err, msg] = readdir (dir);
+  if (err)
+    error ("couldn't read directory %s: %s", dir, msg);
+  endif
+
+  ## Get classes in dir
+  class_idx = find (strncmp (files, '@', 1));
+  for k = 1:length (class_idx)
+    class_name = files {class_idx(k)};
+    class_dir = fullfile (dir, class_name);
+    if (exist (class_dir, "dir"))
+      [files2, err, msg] = readdir (class_dir);
+      if (err)
+        error ("couldn't read directory %s: %s", class_dir, msg);
+      endif
+      files2 = strcat (class_name, filesep (), files2);
+      files = [files; files2];
+    endif
+  endfor
+
+  ## Check for architecture dependent files.
+  tmpdir = getarchdir (desc);
+  if (exist (tmpdir, "dir"))
+    [files2, err, msg] = readdir (tmpdir);
+    if (err)
+      error ("couldn't read directory %s: %s", tmpdir, msg);
+    endif
+    files = [files; files2];
+  endif
+
+  functions = {};
+  for i = 1:length (files)
+    file = files{i};
+    lf = length (file);
+    if (lf > 2 && strcmp (file(end-1:end), ".m"))
+      functions{end+1} = file(1:end-2);
+    elseif (lf > 4 && strcmp (file(end-3:end), ".oct"))
+      functions{end+1} = file(1:end-4);
+    endif
+  endfor
+
+  ## Does desc have a categories field?
+  if (! isfield (desc, "categories"))
+    error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given");
+  endif
+  categories = strtrim (strsplit (desc.categories, ","));
+  if (length (categories) < 1)
+    error ("the Category field is empty");
+  endif
+
+  ## Write INDEX.
+  fid = fopen (index_file, "w");
+  if (fid == -1)
+    error ("couldn't open %s for writing", index_file);
+  endif
+  fprintf (fid, "%s >> %s\n", desc.name, desc.title);
+  fprintf (fid, "%s\n", categories{1});
+  fprintf (fid, "  %s\n", functions{:});
+  fclose (fid);
+endfunction
+
+
+function create_pkgadddel (desc, packdir, nm, global_install)
+  instpkg = fullfile (desc.dir, nm);
+  instfid = fopen (instpkg, "at"); # append to support PKG_ADD at inst/
+  ## If it is exists, most of the PKG_* file should go into the
+  ## architecture dependent directory so that the autoload/mfilename
+  ## commands work as expected. The only part that doesn't is the
+  ## part in the main directory.
+  archdir = fullfile (getarchprefix (desc, global_install),
+                      [desc.name "-" desc.version], getarch ());
+  if (exist (getarchdir (desc, global_install), "dir"))
+    archpkg = fullfile (getarchdir (desc, global_install), nm);
+    archfid = fopen (archpkg, "at");
+  else
+    archpkg = instpkg;
+    archfid = instfid;
+  endif
+
+  if (archfid >= 0 && instfid >= 0)
+    ## Search all dot-m files for PKG commands.
+    lst = dir (fullfile (packdir, "inst", "*.m"));
+    for i = 1:length (lst)
+      nam = fullfile (packdir, "inst", lst(i).name);
+      fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$']));
+    endfor
+
+    ## Search all C++ source files for PKG commands.
+    lst = dir (fullfile (packdir, "src", "*.cc"));
+    for i = 1:length (lst)
+      nam = fullfile (packdir, "src", lst(i).name);
+      fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$']));
+      fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$']));
+    endfor
+
+    ## Add developer included PKG commands.
+    packdirnm = fullfile (packdir, nm);
+    if (exist (packdirnm, "file"))
+      fid = fopen (packdirnm, "rt");
+      if (fid >= 0)
+        while (! feof (fid))
+          ln = fgets (fid);
+          if (ln > 0)
+            fwrite (archfid, ln);
+          endif
+        endwhile
+        fclose (fid);
+      endif
+    endif
+
+    ## If the files is empty remove it.
+    fclose (instfid);
+    t = dir (instpkg);
+    if (t.bytes <= 0)
+      unlink (instpkg);
+    endif
+
+    if (instfid != archfid)
+      fclose (archfid);
+      t = dir (archpkg);
+      if (t.bytes <= 0)
+        unlink (archpkg);
+      endif
+    endif
+  endif
+endfunction
+
+
+function archprefix = getarchprefix (desc, global_install)
+  if (global_install)
+    [~, archprefix] = default_prefix (global_install, desc);
+  else
+    archprefix = desc.dir;
+  endif
+endfunction
+
+
+function finish_installation (desc, packdir, global_install)
+  ## Is there a post-install to call?
+  if (exist (fullfile (packdir, "post_install.m"), "file"))
+    wd = pwd ();
+    try
+      cd (packdir);
+      post_install (desc);
+      cd (wd);
+    catch
+      cd (wd);
+      rmdir (desc.dir, "s");
+      rmdir (getarchdir (desc), "s");
+      rethrow (lasterror ());
+    end_try_catch
+  endif
+endfunction
+
+
+function generate_lookfor_cache (desc)
+  dirs = strtrim (ostrsplit (genpath (desc.dir), pathsep ()));
+  for i = 1 : length (dirs)
+    doc_cache_create (fullfile (dirs{i}, "doc-cache"), dirs{i});
+  endfor
+endfunction
--- a/scripts/pkg/private/is_architecture_dependent.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{dep} =} is_architecture_dependent (@var{nm})
-## Undocumented internal function.
-## @end deftypefn
-
-function dep = is_architecture_dependent (nm)
-  persistent archdepsuffix = {".oct",".mex",".a",".lib",".so",".so.*",".dll","dylib"};
-
-  dep = false;
-  for i = 1 : length (archdepsuffix)
-    ext = archdepsuffix{i};
-    if (ext(end) == "*")
-      isglob = true;
-      ext(end) = [];
-    else
-      isglob = false;
-    endif
-    pos = strfind (nm, ext);
-    if (pos)
-      if (! isglob && (length (nm) - pos(end) != length (ext) - 1))
-        continue;
-      endif
-      dep = true;
-      break;
-    endif
-  endfor
-endfunction
-
--- a/scripts/pkg/private/load_package_dirs.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{idx} =} load_package_dirs (@var{lidx}, @var{idx}, @var{handle_deps}, @var{installed_pkgs_lst})
-## Undocumented internal function.
-## @end deftypefn
-
-function idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst)
-  for i = lidx
-    if (isfield (installed_pkgs_lst{i}, "loaded")
-        && installed_pkgs_lst{i}.loaded)
-      continue;
-    else
-      ## Insert this package at the front before recursing over dependencies.
-      if (! any (idx == i))
-        idx = [i, idx];
-      endif
-
-      if (handle_deps)
-        deps = installed_pkgs_lst{i}.depends;
-        if ((length (deps) > 1)
-            || (length (deps) == 1 && ! strcmp (deps{1}.package, "octave")))
-          tmplidx = [];
-          for k = 1 : length (deps)
-            for j = 1 : length (installed_pkgs_lst)
-              if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package))
-                if (! any (idx == j))
-                  tmplidx(end + 1) = j;
-                  break;
-                endif
-              endif
-            endfor
-          endfor
-          idx = load_package_dirs (tmplidx, idx, handle_deps,
-                                 installed_pkgs_lst);
-        endif
-      endif
-    endif
-  endfor
-endfunction
-
--- a/scripts/pkg/private/load_packages_and_dependencies.m	Tue Apr 12 10:36:36 2016 -0400
+++ b/scripts/pkg/private/load_packages_and_dependencies.m	Tue Apr 12 17:46:20 2016 +0100
@@ -53,3 +53,37 @@
   endif
 endfunction
 
+
+function idx = load_package_dirs (lidx, idx, handle_deps, installed_pkgs_lst)
+  for i = lidx
+    if (isfield (installed_pkgs_lst{i}, "loaded")
+        && installed_pkgs_lst{i}.loaded)
+      continue;
+    else
+      ## Insert this package at the front before recursing over dependencies.
+      if (! any (idx == i))
+        idx = [i, idx];
+      endif
+
+      if (handle_deps)
+        deps = installed_pkgs_lst{i}.depends;
+        if ((length (deps) > 1)
+            || (length (deps) == 1 && ! strcmp (deps{1}.package, "octave")))
+          tmplidx = [];
+          for k = 1 : length (deps)
+            for j = 1 : length (installed_pkgs_lst)
+              if (strcmp (installed_pkgs_lst{j}.name, deps{k}.package))
+                if (! any (idx == j))
+                  tmplidx(end + 1) = j;
+                  break;
+                endif
+              endif
+            endfor
+          endfor
+          idx = load_package_dirs (tmplidx, idx, handle_deps,
+                                 installed_pkgs_lst);
+        endif
+      endif
+    endif
+  endfor
+endfunction
--- a/scripts/pkg/private/packinfo_copy_file.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} packinfo_copy_file (@var{filename}, @var{requirement}, @var{packdir}, @var{packinfo}, @var{desc}, @var{octfiledir})
-## Undocumented internal function.
-## @end deftypefn
-
-function packinfo_copy_file (filename, requirement, packdir, packinfo, desc, octfiledir)
-  filepath = fullfile (packdir, filename);
-  if (! exist (filepath, "file") && strcmpi (requirement, "optional"))
-    ## do nothing, it's still OK
-  else
-    [status, output] = copyfile (filepath, packinfo);
-    if (status != 1)
-      rmdir (desc.dir, "s");
-      rmdir (octfiledir, "s");
-      error ("Couldn't copy %s file: %s", filename, output);
-    endif
-  endif
-endfunction
-
--- a/scripts/pkg/private/parse_pkg_idx.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {@var{pkg_idx_struct} =} parse_pkg_idx (@var{packdir})
-## Undocumented internal function.
-## @end deftypefn
-
-
-## Read an INDEX file.
-function pkg_idx_struct = parse_pkg_idx (packdir)
-
-  index_file = fullfile (packdir, "packinfo", "INDEX");
-
-  if (! exist (index_file, "file"))
-    error ("could not find any INDEX file in directory %s, try 'pkg rebuild all' to generate missing INDEX files", packdir);
-  endif
-
-
-  [fid, msg] = fopen (index_file, "r");
-  if (fid == -1)
-    error ("the INDEX file %s could not be read: %s",
-           index_file, msg);
-  endif
-
-  cat_num = 1;
-  pkg_idx_struct{1}.category = "Uncategorized";
-  pkg_idx_struct{1}.functions = {};
-
-  line = fgetl (fid);
-  while (isempty (strfind (line, ">>")) && ! feof (fid))
-    line = fgetl (fid);
-  endwhile
-
-  while (! feof (fid) || line != -1)
-    if (! any (! isspace (line)) || line(1) == "#" || any (line == "="))
-      ## Comments,  blank lines or comments about unimplemented
-      ## functions: do nothing
-      ## FIXME: probably comments and pointers to external functions
-      ## could be treated better when printing to screen?
-    elseif (! isempty (strfind (line, ">>")))
-      ## Skip package name and description as they are in DESCRIPTION
-      ## already.
-    elseif (! isspace (line(1)))
-      ## Category.
-      if (! isempty (pkg_idx_struct{cat_num}.functions))
-        pkg_idx_struct{++cat_num}.functions = {};
-      endif
-      pkg_idx_struct{cat_num}.category = deblank (line);
-    else
-      ## Function names.
-      while (any (! isspace (line)))
-        [fun_name, line] = strtok (line);
-        pkg_idx_struct{cat_num}.functions{end+1} = deblank (fun_name);
-      endwhile
-    endif
-    line = fgetl (fid);
-  endwhile
-  fclose (fid);
-endfunction
-
--- a/scripts/pkg/private/prepare_installation.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} prepare_installation (@var{desc}, @var{packdir})
-## Undocumented internal function.
-## @end deftypefn
-
-function prepare_installation (desc, packdir)
-  ## Is there a pre_install to call?
-  if (exist (fullfile (packdir, "pre_install.m"), "file"))
-    wd = pwd ();
-    try
-      cd (packdir);
-      pre_install (desc);
-      cd (wd);
-    catch
-      cd (wd);
-      rethrow (lasterror ());
-    end_try_catch
-  endif
-
-  ## If the directory "inst" doesn't exist, we create it.
-  inst_dir = fullfile (packdir, "inst");
-  if (! exist (inst_dir, "dir"))
-    [status, msg] = mkdir (inst_dir);
-    if (status != 1)
-      rmdir (desc.dir, "s");
-      error ("the 'inst' directory did not exist and could not be created: %s",
-             msg);
-    endif
-  endif
-endfunction
-
--- a/scripts/pkg/private/print_package_description.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} print_package_description (@var{pkg_name}, @var{pkg_ver}, @var{pkg_idx_struct}, @var{pkg_desc}, @var{status}, @var{verbose})
-## Undocumented internal function.
-## @end deftypefn
-
-function print_package_description (pkg_name, pkg_ver, pkg_idx_struct,
-                                    pkg_desc, status, verbose)
-
-  printf ("---\nPackage name:\n\t%s\n", pkg_name);
-  printf ("Version:\n\t%s\n", pkg_ver);
-  printf ("Short description:\n\t%s\n", pkg_desc);
-  printf ("Status:\n\t%s\n", status);
-  if (verbose)
-    printf ("---\nProvides:\n");
-    for i = 1:length (pkg_idx_struct)
-      if (! isempty (pkg_idx_struct{i}.functions))
-        printf ("%s\n", pkg_idx_struct{i}.category);
-        for j = 1:length (pkg_idx_struct{i}.functions)
-          printf ("\t%s\n", pkg_idx_struct{i}.functions{j});
-        endfor
-      endif
-    endfor
-  endif
-
-endfunction
-
-
--- a/scripts/pkg/private/shell.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## Executes a shell command. In the end it calls system() but in case of
-## windows will first check if sh.exe works.
-##
-## If VERBOSE is true, it will prints the output to STDOUT in real time and
-## the second output argument will be an empty string. Otherwise, it will
-## contain the output of the execeuted command.
-
-function [status, output] = shell (cmd, verbose)
-  persistent have_sh;
-
-  cmd = strrep (cmd, "\\", "/");
-  if (ispc () && ! isunix ())
-    if (isempty (have_sh))
-      if (system ('sh.exe -c "exit"'))
-        have_sh = false;
-      else
-        have_sh = true;
-      endif
-    endif
-    if (have_sh)
-      cmd = ['sh.exe -c "' cmd '"'];
-    else
-      error ("pkg: unable to find the command shell.");
-    endif
-  endif
-  ## if verbose, we want to display the output in real time. To do this, we
-  ## must call system with 1 output argument. But then the variable `output'
-  ## won't exist. So we initialize it empty. If an error does occur, and we
-  ## are verbose we will return an empty string but it's all fine since
-  ## the error message has already been displayed.
-  output = "";
-  if (verbose)
-    [status] = system (cmd);
-  else
-    [status, output] = system (cmd);
-  endif
-endfunction
-
--- a/scripts/pkg/private/verify_directory.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} verify_directory (@var{dir})
-## Undocumented internal function.
-## @end deftypefn
-
-## Make sure the package contains the essential files.
-function verify_directory (dir)
-  needed_files = {"COPYING", "DESCRIPTION"};
-  for f = needed_files
-    if (! exist (fullfile (dir, f{1}), "file"))
-      error ("package is missing file: %s", f{1});
-    endif
-  endfor
-endfunction
-
--- a/scripts/pkg/private/write_index.m	Tue Apr 12 10:36:36 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-## Copyright (C) 2005-2015 Søren Hauberg
-## Copyright (C) 2010 VZLU Prague, a.s.
-##
-## This file is part of Octave.
-##
-## Octave is free software; you can redistribute it and/or modify it
-## under the terms of the GNU General Public License as published by
-## the Free Software Foundation; either version 3 of the License, or (at
-## your option) any later version.
-##
-## Octave is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with Octave; see the file COPYING.  If not, see
-## <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {} {} write_index (@var{desc}, @var{dir}, @var{index_file}, @var{global_install})
-## Undocumented internal function.
-## @end deftypefn
-
-## Create an INDEX file for a package that doesn't provide one.
-##   'desc'  describes the package.
-##   'dir'   is the 'inst' directory in temporary directory.
-##   'index_file' is the name (including path) of resulting INDEX file.
-
-function write_index (desc, dir, index_file, global_install)
-  ## Get names of functions in dir
-  [files, err, msg] = readdir (dir);
-  if (err)
-    error ("couldn't read directory %s: %s", dir, msg);
-  endif
-
-  ## Get classes in dir
-  class_idx = find (strncmp (files, '@', 1));
-  for k = 1:length (class_idx)
-    class_name = files {class_idx(k)};
-    class_dir = fullfile (dir, class_name);
-    if (exist (class_dir, "dir"))
-      [files2, err, msg] = readdir (class_dir);
-      if (err)
-        error ("couldn't read directory %s: %s", class_dir, msg);
-      endif
-      files2 = strcat (class_name, filesep (), files2);
-      files = [files; files2];
-    endif
-  endfor
-
-  ## Check for architecture dependent files.
-  tmpdir = getarchdir (desc);
-  if (exist (tmpdir, "dir"))
-    [files2, err, msg] = readdir (tmpdir);
-    if (err)
-      error ("couldn't read directory %s: %s", tmpdir, msg);
-    endif
-    files = [files; files2];
-  endif
-
-  functions = {};
-  for i = 1:length (files)
-    file = files{i};
-    lf = length (file);
-    if (lf > 2 && strcmp (file(end-1:end), ".m"))
-      functions{end+1} = file(1:end-2);
-    elseif (lf > 4 && strcmp (file(end-3:end), ".oct"))
-      functions{end+1} = file(1:end-4);
-    endif
-  endfor
-
-  ## Does desc have a categories field?
-  if (! isfield (desc, "categories"))
-    error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given");
-  endif
-  categories = strtrim (strsplit (desc.categories, ","));
-  if (length (categories) < 1)
-    error ("the Category field is empty");
-  endif
-
-  ## Write INDEX.
-  fid = fopen (index_file, "w");
-  if (fid == -1)
-    error ("couldn't open %s for writing", index_file);
-  endif
-  fprintf (fid, "%s >> %s\n", desc.name, desc.title);
-  fprintf (fid, "%s\n", categories{1});
-  fprintf (fid, "  %s\n", functions{:});
-  fclose (fid);
-endfunction
-