1########################################################################
2##
3## Copyright (C) 2005-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn {} {} install (@var{files}, @var{handle_deps}, @var{prefix}, @var{archprefix}, @var{verbose}, @var{local_list}, @var{global_list}, @var{global_install})
28## Undocumented internal function.
29## @end deftypefn
30
31function install (files, handle_deps, prefix, archprefix, verbose,
32                  local_list, global_list, global_install)
33
34  ## Check that the directory in prefix exist.  If it doesn't: create it!
35  if (! isfolder (prefix))
36    warning ("creating installation directory %s", prefix);
37    [status, msg] = mkdir (prefix);
38    if (status != 1)
39      error ("could not create installation directory: %s", msg);
40    endif
41  endif
42
43  ## Get the list of installed packages.
44  [local_packages, global_packages] = installed_packages (local_list,
45                                                          global_list);
46
47  installed_pkgs_lst = {local_packages{:}, global_packages{:}};
48
49  if (global_install)
50    packages = global_packages;
51  else
52    packages = local_packages;
53  endif
54
55  ## Uncompress the packages and read the DESCRIPTION files.
56  tmpdirs = packdirs = descriptions = {};
57  try
58    ## Warn about non existent files.
59    for i = 1:length (files)
60      if (isempty (glob (files{i})))
61        warning ("file %s does not exist", files{i});
62      endif
63    endfor
64
65    ## Unpack the package files and read the DESCRIPTION files.
66    files = glob (files);
67    packages_to_uninstall = [];
68    for i = 1:length (files)
69      tgz = files{i};
70
71      if (exist (tgz, "file"))
72        ## Create a temporary directory.
73        tmpdir = tempname ();
74        tmpdirs{end+1} = tmpdir;
75        if (verbose)
76          printf ("mkdir (%s)\n", tmpdir);
77        endif
78        [status, msg] = mkdir (tmpdir);
79        if (status != 1)
80          error ("couldn't create temporary directory: %s", msg);
81        endif
82
83        ## Uncompress the package.
84        [~, ~, ext] = fileparts (tgz);
85        if (strcmpi (ext, ".zip"))
86          func_uncompress = @unzip;
87        else
88          func_uncompress = @untar;
89        endif
90        if (verbose)
91          printf ("%s (%s, %s)\n", func2str (func_uncompress), tgz, tmpdir);
92        endif
93        func_uncompress (tgz, tmpdir);
94
95        ## Get the name of the directories produced by tar.
96        [dirlist, err, msg] = readdir (tmpdir);
97        if (err)
98          error ("couldn't read directory produced by tar: %s", msg);
99        endif
100
101        if (length (dirlist) > 3)
102          error ("bundles of packages are not allowed");
103        endif
104      endif
105
106      ## The filename pointed to an uncompressed package to begin with.
107      if (isfolder (tgz))
108        dirlist = {".", "..", tgz};
109      endif
110
111      if (exist (tgz, "file") || isfolder (tgz))
112        ## The two first entries of dirlist are "." and "..".
113        if (exist (tgz, "file"))
114          packdir = fullfile (tmpdir, dirlist{3});
115        else
116          packdir = fullfile (pwd (), dirlist{3});
117        endif
118        packdirs{end+1} = packdir;
119
120        ## Make sure the package contains necessary files.
121        verify_directory (packdir);
122
123        ## Read the DESCRIPTION file.
124        filename = fullfile (packdir, "DESCRIPTION");
125        desc = get_description (filename);
126
127        ## Set default installation directory.
128        desc.dir = fullfile (prefix, [desc.name "-" desc.version]);
129
130        ## Set default architectire dependent installation directory.
131        desc.archprefix = fullfile (archprefix, [desc.name "-" desc.version]);
132
133        ## Save desc.
134        descriptions{end+1} = desc;
135
136        ## Are any of the new packages already installed?
137        ## If so we'll remove the old version.
138        for j = 1:length (packages)
139          if (strcmp (packages{j}.name, desc.name))
140            packages_to_uninstall(end+1) = j;
141          endif
142        endfor
143      endif
144    endfor
145  catch
146    ## Something went wrong, delete tmpdirs.
147    for i = 1:length (tmpdirs)
148      rmdir (tmpdirs{i}, "s");
149    endfor
150    rethrow (lasterror ());
151  end_try_catch
152
153  ## Check dependencies.
154  if (handle_deps)
155    ok = true;
156    error_text = "";
157    for i = 1:length (descriptions)
158      desc = descriptions{i};
159      idx2 = setdiff (1:length (descriptions), i);
160      if (global_install)
161        ## Global installation is not allowed to have dependencies on locally
162        ## installed packages.
163        idx1 = setdiff (1:length (global_packages), packages_to_uninstall);
164        pseudo_installed_packages = {global_packages{idx1}, ...
165                                     descriptions{idx2}};
166      else
167        idx1 = setdiff (1:length (local_packages), packages_to_uninstall);
168        pseudo_installed_packages = {local_packages{idx1}, ...
169                                     global_packages{:}, ...
170                                     descriptions{idx2}};
171      endif
172      bad_deps = get_unsatisfied_deps (desc, pseudo_installed_packages);
173      ## Are there any unsatisfied dependencies?
174      if (! isempty (bad_deps))
175        ok = false;
176        for i = 1:length (bad_deps)
177          dep = bad_deps{i};
178          error_text = [error_text " " desc.name " needs " ...
179                        dep.package " " dep.operator " " dep.version "\n"];
180        endfor
181      endif
182    endfor
183
184    ## Did we find any unsatisfied dependencies?
185    if (! ok)
186      error ("the following dependencies were unsatisfied:\n  %s", error_text);
187    endif
188  endif
189
190  ## Prepare each package for installation.
191  try
192    for i = 1:length (descriptions)
193      desc = descriptions{i};
194      pdir = packdirs{i};
195      prepare_installation (desc, pdir);
196      configure_make (desc, pdir, verbose);
197      copy_built_files (desc, pdir, verbose);
198    endfor
199  catch
200    ## Something went wrong, delete tmpdirs.
201    for i = 1:length (tmpdirs)
202      rmdir (tmpdirs{i}, "s");
203    endfor
204    rethrow (lasterror ());
205  end_try_catch
206
207  ## Uninstall the packages that will be replaced.
208  try
209    for i = packages_to_uninstall
210      if (global_install)
211        uninstall ({global_packages{i}.name}, false, verbose, local_list,
212                   global_list, global_install);
213      else
214        uninstall ({local_packages{i}.name}, false, verbose, local_list,
215                   global_list, global_install);
216      endif
217    endfor
218  catch
219    ## Something went wrong, delete tmpdirs.
220    for i = 1:length (tmpdirs)
221      rmdir (tmpdirs{i}, "s");
222    endfor
223    rethrow (lasterror ());
224  end_try_catch
225
226  ## Install each package.
227  try
228    for i = 1:length (descriptions)
229      desc = descriptions{i};
230      pdir = packdirs{i};
231      copy_files (desc, pdir, global_install);
232      create_pkgadddel (desc, pdir, "PKG_ADD", global_install);
233      create_pkgadddel (desc, pdir, "PKG_DEL", global_install);
234      finish_installation (desc, pdir, global_install);
235      generate_lookfor_cache (desc);
236    endfor
237  catch
238    ## Something went wrong, delete tmpdirs.
239    for i = 1:length (tmpdirs)
240      rmdir (tmpdirs{i}, "s");
241    endfor
242    for i = 1:length (descriptions)
243      rmdir (descriptions{i}.dir, "s");
244      rmdir (getarchdir (descriptions{i}), "s");
245    endfor
246    rethrow (lasterror ());
247  end_try_catch
248
249  ## Check if the installed directory is empty.  If it is remove it
250  ## from the list.
251  for i = length (descriptions):-1:1
252    if (dirempty (descriptions{i}.dir, {"packinfo", "doc"})
253        && dirempty (getarchdir (descriptions{i})))
254      warning ("package %s is empty\n", descriptions{i}.name);
255      rmdir (descriptions{i}.dir, "s");
256      rmdir (getarchdir (descriptions{i}), "s");
257      descriptions(i) = [];
258    endif
259  endfor
260
261  ## Add the packages to the package list.
262  try
263    if (global_install)
264      idx = setdiff (1:length (global_packages), packages_to_uninstall);
265      global_packages = save_order ({global_packages{idx}, descriptions{:}});
266      if (ispc)
267        ## On Windows ensure LFN paths are saved rather than 8.3 style paths
268        global_packages = standardize_paths (global_packages);
269      endif
270      global_packages = make_rel_paths (global_packages);
271      save (global_list, "global_packages");
272      installed_pkgs_lst = {local_packages{:}, global_packages{:}};
273    else
274      idx = setdiff (1:length (local_packages), packages_to_uninstall);
275      local_packages = save_order ({local_packages{idx}, descriptions{:}});
276      if (ispc)
277        local_packages = standardize_paths (local_packages);
278      endif
279      save (local_list, "local_packages");
280      installed_pkgs_lst = {local_packages{:}, global_packages{:}};
281    endif
282  catch
283    ## Something went wrong, delete tmpdirs.
284    for i = 1:length (tmpdirs)
285      rmdir (tmpdirs{i}, "s");
286    endfor
287    for i = 1:length (descriptions)
288      rmdir (descriptions{i}.dir, "s");
289    endfor
290    if (global_install)
291      printf ("error: couldn't append to %s\n", global_list);
292    else
293      printf ("error: couldn't append to %s\n", local_list);
294    endif
295    rethrow (lasterror ());
296  end_try_catch
297
298  ## All is well, let's clean up.
299  for i = 1:length (tmpdirs)
300    [status, msg] = rmdir (tmpdirs{i}, "s");
301    if (status != 1 && isfolder (tmpdirs{i}))
302      warning ("couldn't clean up after my self: %s\n", msg);
303    endif
304  endfor
305
306  ## If there is a NEWS file, mention it.
307  ## Check if desc exists too because it's possible to get to this point
308  ## without creating it such as giving an invalid filename for the package
309  if (exist ("desc", "var")
310      && exist (fullfile (desc.dir, "packinfo", "NEWS"), "file"))
311    printf (["For information about changes from previous versions " ...
312             "of the %s package, run 'news %s'.\n"],
313            desc.name, desc.name);
314  endif
315
316endfunction
317
318
319function pkg = extract_pkg (nm, pat)
320
321  mfile_encoding = __mfile_encoding__ ();
322  if (strcmp (mfile_encoding, "system"))
323    mfile_encoding = __locale_charset__ ();
324  endif
325  fid = fopen (nm, "rt", "n", mfile_encoding);
326  pkg = "";
327  if (fid >= 0)
328    while (! feof (fid))
329      ln = __u8_validate__ (fgetl (fid));
330      if (ln > 0)
331        t = regexp (ln, pat, "tokens");
332        if (! isempty (t))
333          pkg = [pkg "\n" t{1}{1}];
334        endif
335      endif
336    endwhile
337    if (! isempty (pkg))
338      pkg = [pkg "\n"];
339    endif
340    fclose (fid);
341  endif
342
343endfunction
344
345
346## Make sure the package contains the essential files.
347function verify_directory (dir)
348
349  needed_files = {"COPYING", "DESCRIPTION"};
350  for f = needed_files
351    if (! exist (fullfile (dir, f{1}), "file"))
352      error ("package is missing file: %s", f{1});
353    endif
354  endfor
355
356endfunction
357
358
359function prepare_installation (desc, packdir)
360
361  ## Is there a pre_install to call?
362  if (exist (fullfile (packdir, "pre_install.m"), "file"))
363    wd = pwd ();
364    try
365      cd (packdir);
366      pre_install (desc);
367      cd (wd);
368    catch
369      cd (wd);
370      rethrow (lasterror ());
371    end_try_catch
372  endif
373
374  ## If the directory "inst" doesn't exist, we create it.
375  inst_dir = fullfile (packdir, "inst");
376  if (! isfolder (inst_dir))
377    [status, msg] = mkdir (inst_dir);
378    if (status != 1)
379      rmdir (desc.dir, "s");
380      error ("the 'inst' directory did not exist and could not be created: %s",
381             msg);
382    endif
383  endif
384
385endfunction
386
387
388function copy_built_files (desc, packdir, verbose)
389
390  src = fullfile (packdir, "src");
391  if (! isfolder (src))
392    return
393  endif
394
395  ## Copy files to "inst" and "inst/arch" (this is instead of 'make install').
396  files = fullfile (src, "FILES");
397  instdir = fullfile (packdir, "inst");
398  archdir = fullfile (packdir, "inst", getarch ());
399
400  ## Get filenames.
401  if (exist (files, "file"))
402    [fid, msg] = fopen (files, "r");
403    if (fid < 0)
404      error ("couldn't open %s: %s", files, msg);
405    endif
406    filenames = char (fread (fid))';
407    fclose (fid);
408    if (filenames(end) == "\n")
409      filenames(end) = [];
410    endif
411    filenames = strtrim (ostrsplit (filenames, "\n"));
412    delete_idx = [];
413    for i = 1:length (filenames)
414      if (! all (isspace (filenames{i})))
415        filenames{i} = fullfile (src, filenames{i});
416      else
417        delete_idx(end+1) = i;
418      endif
419    endfor
420    filenames(delete_idx) = [];
421  else
422    m = dir (fullfile (src, "*.m"));
423    oct = dir (fullfile (src, "*.oct"));
424    mex = dir (fullfile (src, "*.mex"));
425    tst = dir (fullfile (src, "*tst"));
426
427    filenames = cellfun (@(x) fullfile (src, x),
428                         {m.name, oct.name, mex.name, tst.name},
429                         "uniformoutput", false);
430  endif
431
432  ## Split into architecture dependent and independent files.
433  if (isempty (filenames))
434    idx = [];
435  else
436    idx = cellfun ("is_architecture_dependent", filenames);
437  endif
438  archdependent = filenames(idx);
439  archindependent = filenames(! idx);
440
441  ## Copy the files.
442  if (! all (isspace ([filenames{:}])))
443      if (! isfolder (instdir))
444        mkdir (instdir);
445      endif
446      if (! all (isspace ([archindependent{:}])))
447        if (verbose)
448          printf ("copyfile");
449          printf (" %s", archindependent{:});
450          printf ("%s\n", instdir);
451        endif
452        [status, output] = copyfile (archindependent, instdir);
453        if (status != 1)
454          rmdir (desc.dir, "s");
455          error ("Couldn't copy files from 'src' to 'inst': %s", output);
456        endif
457      endif
458      if (! all (isspace ([archdependent{:}])))
459        if (verbose)
460          printf ("copyfile");
461          printf (" %s", archdependent{:});
462          printf (" %s\n", archdir);
463        endif
464        if (! isfolder (archdir))
465          mkdir (archdir);
466        endif
467        [status, output] = copyfile (archdependent, archdir);
468        if (status != 1)
469          rmdir (desc.dir, "s");
470          error ("Couldn't copy files from 'src' to 'inst': %s", output);
471        endif
472      endif
473  endif
474
475endfunction
476
477
478function dep = is_architecture_dependent (nm)
479
480  persistent archdepsuffix = {".oct", ".mex", ".a", ".lib", ".so", ...
481                              "tst", ".so.*", ".dll", "dylib"};
482
483  dep = false;
484  for i = 1 : length (archdepsuffix)
485    ext = archdepsuffix{i};
486    if (ext(end) == "*")
487      isglob = true;
488      ext(end) = [];
489    else
490      isglob = false;
491    endif
492    pos = strfind (nm, ext);
493    if (pos)
494      if (! isglob && (length (nm) - pos(end) != length (ext) - 1))
495        continue;
496      endif
497      dep = true;
498      break;
499    endif
500  endfor
501
502endfunction
503
504
505function copy_files (desc, packdir, global_install)
506
507  ## Create the installation directory.
508  if (! isfolder (desc.dir))
509    [status, output] = mkdir (desc.dir);
510    if (status != 1)
511      error ("couldn't create installation directory %s : %s",
512      desc.dir, output);
513    endif
514  endif
515
516  octfiledir = getarchdir (desc);
517
518  ## Copy the files from "inst" to installdir.
519  instdir = fullfile (packdir, "inst");
520  if (! dirempty (instdir))
521    [status, output] = copyfile (fullfile (instdir, "*"), desc.dir);
522    if (status != 1)
523      rmdir (desc.dir, "s");
524      error ("couldn't copy files to the installation directory");
525    endif
526    if (isfolder (fullfile (desc.dir, getarch ()))
527        && ! is_same_file (fullfile (desc.dir, getarch ()), octfiledir))
528      if (! isfolder (octfiledir))
529        ## Can be required to create up to three levels of dirs.
530        octm1 = fileparts (octfiledir);
531        if (! isfolder (octm1))
532          octm2 = fileparts (octm1);
533          if (! isfolder (octm2))
534            octm3 = fileparts (octm2);
535            if (! isfolder (octm3))
536              [status, output] = mkdir (octm3);
537              if (status != 1)
538                rmdir (desc.dir, "s");
539                error ("couldn't create installation directory %s : %s",
540                       octm3, output);
541              endif
542            endif
543            [status, output] = mkdir (octm2);
544            if (status != 1)
545              rmdir (desc.dir, "s");
546              error ("couldn't create installation directory %s : %s",
547                     octm2, output);
548            endif
549          endif
550          [status, output] = mkdir (octm1);
551          if (status != 1)
552            rmdir (desc.dir, "s");
553            error ("couldn't create installation directory %s : %s",
554                   octm1, output);
555          endif
556        endif
557        [status, output] = mkdir (octfiledir);
558        if (status != 1)
559          rmdir (desc.dir, "s");
560          error ("couldn't create installation directory %s : %s",
561          octfiledir, output);
562        endif
563      endif
564      [status, output] = movefile (fullfile (desc.dir, getarch (), "*"),
565                                   octfiledir);
566      rmdir (fullfile (desc.dir, getarch ()), "s");
567
568      if (status != 1)
569        rmdir (desc.dir, "s");
570        rmdir (octfiledir, "s");
571        error ("couldn't copy files to the installation directory");
572      endif
573    endif
574
575  endif
576
577  ## Create the "packinfo" directory.
578  packinfo = fullfile (desc.dir, "packinfo");
579  [status, msg] = mkdir (packinfo);
580  if (status != 1)
581    rmdir (desc.dir, "s");
582    rmdir (octfiledir, "s");
583    error ("couldn't create packinfo directory: %s", msg);
584  endif
585
586  packinfo_copy_file ("DESCRIPTION", "required", packdir, packinfo, desc, octfiledir);
587  packinfo_copy_file ("COPYING", "required", packdir, packinfo, desc, octfiledir);
588  packinfo_copy_file ("CITATION", "optional", packdir, packinfo, desc, octfiledir);
589  packinfo_copy_file ("NEWS", "optional", packdir, packinfo, desc, octfiledir);
590  packinfo_copy_file ("ONEWS", "optional", packdir, packinfo, desc, octfiledir);
591  packinfo_copy_file ("ChangeLog", "optional", packdir, packinfo, desc, octfiledir);
592
593  ## Is there an INDEX file to copy or should we generate one?
594  index_file = fullfile (packdir, "INDEX");
595  if (exist (index_file, "file"))
596    packinfo_copy_file ("INDEX", "required", packdir, packinfo, desc, octfiledir);
597  else
598    try
599      write_index (desc, fullfile (packdir, "inst"),
600                   fullfile (packinfo, "INDEX"), global_install);
601    catch
602      rmdir (desc.dir, "s");
603      rmdir (octfiledir, "s");
604      rethrow (lasterror ());
605    end_try_catch
606  endif
607
608  ## Is there an 'on_uninstall.m' to install?
609  packinfo_copy_file ("on_uninstall.m", "optional", packdir, packinfo, desc, octfiledir);
610
611  ## Is there a doc/ directory that needs to be installed?
612  docdir = fullfile (packdir, "doc");
613  if (isfolder (docdir) && ! dirempty (docdir))
614    [status, output] = copyfile (docdir, desc.dir);
615  endif
616
617  ## Is there a bin/ directory that needs to be installed?
618  ## FIXME: Need to treat architecture dependent files in bin/
619  bindir = fullfile (packdir, "bin");
620  if (isfolder (bindir) && ! dirempty (bindir))
621    [status, output] = copyfile (bindir, desc.dir);
622  endif
623
624endfunction
625
626
627function packinfo_copy_file (filename, requirement, packdir, packinfo, desc, octfiledir)
628
629  filepath = fullfile (packdir, filename);
630  if (! exist (filepath, "file") && strcmpi (requirement, "optional"))
631    ## do nothing, it's still OK
632  else
633    [status, output] = copyfile (filepath, packinfo);
634    if (status != 1)
635      rmdir (desc.dir, "s");
636      rmdir (octfiledir, "s");
637      error ("Couldn't copy %s file: %s", filename, output);
638    endif
639  endif
640
641endfunction
642
643
644## Create an INDEX file for a package that doesn't provide one.
645##   'desc'  describes the package.
646##   'dir'   is the 'inst' directory in temporary directory.
647##   'index_file' is the name (including path) of resulting INDEX file.
648function write_index (desc, dir, index_file, global_install)
649
650  ## Get names of functions in dir
651  [files, err, msg] = readdir (dir);
652  if (err)
653    error ("couldn't read directory %s: %s", dir, msg);
654  endif
655
656  ## Get classes in dir
657  class_idx = find (strncmp (files, '@', 1));
658  for k = 1:length (class_idx)
659    class_name = files {class_idx(k)};
660    class_dir = fullfile (dir, class_name);
661    if (isfolder (class_dir))
662      [files2, err, msg] = readdir (class_dir);
663      if (err)
664        error ("couldn't read directory %s: %s", class_dir, msg);
665      endif
666      files2 = strcat (class_name, filesep (), files2);
667      files = [files; files2];
668    endif
669  endfor
670
671  ## Check for architecture dependent files.
672  tmpdir = getarchdir (desc);
673  if (isfolder (tmpdir))
674    [files2, err, msg] = readdir (tmpdir);
675    if (err)
676      error ("couldn't read directory %s: %s", tmpdir, msg);
677    endif
678    files = [files; files2];
679  endif
680
681  functions = {};
682  for i = 1:length (files)
683    file = files{i};
684    lf = length (file);
685    if (lf > 2 && strcmp (file(end-1:end), ".m"))
686      functions{end+1} = file(1:end-2);
687    elseif (lf > 4 && strcmp (file(end-3:end), ".oct"))
688      functions{end+1} = file(1:end-4);
689    endif
690  endfor
691
692  ## Does desc have a categories field?
693  if (! isfield (desc, "categories"))
694    error ("the DESCRIPTION file must have a Categories field, when no INDEX file is given");
695  endif
696  categories = strtrim (strsplit (desc.categories, ","));
697  if (length (categories) < 1)
698    error ("the Category field is empty");
699  endif
700
701  ## Write INDEX.
702  fid = fopen (index_file, "w");
703  if (fid == -1)
704    error ("couldn't open %s for writing", index_file);
705  endif
706  fprintf (fid, "%s >> %s\n", desc.name, desc.title);
707  fprintf (fid, "%s\n", categories{1});
708  fprintf (fid, "  %s\n", functions{:});
709  fclose (fid);
710
711endfunction
712
713
714function create_pkgadddel (desc, packdir, nm, global_install)
715
716  instpkg = fullfile (desc.dir, nm);
717  instfid = fopen (instpkg, "at"); # append to support PKG_ADD at inst/
718  ## If it is exists, most of the PKG_* file should go into the
719  ## architecture dependent directory so that the autoload/mfilename
720  ## commands work as expected.  The only part that doesn't is the
721  ## part in the main directory.
722  archdir = fullfile (getarchprefix (desc, global_install),
723                      [desc.name "-" desc.version], getarch ());
724  if (isfolder (getarchdir (desc, global_install)))
725    archpkg = fullfile (getarchdir (desc, global_install), nm);
726    archfid = fopen (archpkg, "at");
727  else
728    archpkg = instpkg;
729    archfid = instfid;
730  endif
731
732  if (archfid >= 0 && instfid >= 0)
733    ## Search all dot-m files for PKG commands.
734    lst = glob (fullfile (packdir, "inst", "*.m"));
735    for i = 1:length (lst)
736      nam = lst{i};
737      fwrite (instfid, extract_pkg (nam, ['^[#%][#%]* *' nm ': *(.*)$']));
738    endfor
739
740    ## Search all C++ source files for PKG commands.
741    cc_lst = glob (fullfile (packdir, "src", "*.cc"));
742    cpp_lst = glob (fullfile (packdir, "src", "*.cpp"));
743    cxx_lst = glob (fullfile (packdir, "src", "*.cxx"));
744    lst = [cc_lst; cpp_lst; cxx_lst];
745    for i = 1:length (lst)
746      nam = lst{i};
747      fwrite (archfid, extract_pkg (nam, ['^//* *' nm ': *(.*)$']));
748      fwrite (archfid, extract_pkg (nam, ['^/\** *' nm ': *(.*) *\*/$']));
749    endfor
750
751    ## Add developer included PKG commands.
752    packdirnm = fullfile (packdir, nm);
753    if (exist (packdirnm, "file"))
754      fid = fopen (packdirnm, "rt");
755      if (fid >= 0)
756        while (! feof (fid))
757          ln = fgets (fid);
758          if (ln > 0)
759            fwrite (archfid, ln);
760          endif
761        endwhile
762        fclose (fid);
763      endif
764    endif
765
766    ## If the files is empty remove it.
767    fclose (instfid);
768    t = dir (instpkg);
769    if (t.bytes <= 0)
770      unlink (instpkg);
771    endif
772
773    if (instfid != archfid)
774      fclose (archfid);
775      t = dir (archpkg);
776      if (t.bytes <= 0)
777        unlink (archpkg);
778      endif
779    endif
780  endif
781
782endfunction
783
784
785function archprefix = getarchprefix (desc, global_install)
786
787  if (global_install)
788    [~, archprefix] = default_prefix (global_install, desc);
789  else
790    archprefix = desc.dir;
791  endif
792
793endfunction
794
795
796function finish_installation (desc, packdir, global_install)
797
798  ## Is there a post-install to call?
799  if (exist (fullfile (packdir, "post_install.m"), "file"))
800    wd = pwd ();
801    try
802      cd (packdir);
803      post_install (desc);
804      cd (wd);
805    catch
806      cd (wd);
807      rmdir (desc.dir, "s");
808      rmdir (getarchdir (desc), "s");
809      rethrow (lasterror ());
810    end_try_catch
811  endif
812
813endfunction
814
815
816function generate_lookfor_cache (desc)
817
818  dirs = strtrim (ostrsplit (genpath (desc.dir), pathsep ()));
819  if (ispc)
820    dirs = cellfun (@canonicalize_file_name, dirs, "uniformoutput", false);
821  endif
822  for i = 1 : length (dirs)
823    doc_cache_create (fullfile (dirs{i}, "doc-cache"), dirs{i});
824  endfor
825
826endfunction
827