The R Project SVN R

Rev

Rev 34111 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 34111 Rev 34311
1
#! @PERL@
1
#! @PERL@
2
#-*- perl -*-
2
#-*- perl -*-
3
 
3
 
4
## Copyright (C) 2000-2005 R Development Core Team
4
## Copyright (C) 2000-2005 R Development Core Team
5
##
5
##
6
## This program is free software; you can redistribute it and/or modify
6
## This program is free software; you can redistribute it and/or modify
7
## it under the terms of the GNU General Public License as published by
7
## it under the terms of the GNU General Public License as published by
8
## the Free Software Foundation; either version 2, or (at your option)
8
## the Free Software Foundation; either version 2, or (at your option)
9
## any later version.
9
## any later version.
10
##
10
##
11
## This program is distributed in the hope that it will be useful, but
11
## This program is distributed in the hope that it will be useful, but
12
## WITHOUT ANY WARRANTY; without even the implied warranty of
12
## WITHOUT ANY WARRANTY; without even the implied warranty of
13
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
13
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
14
## General Public License for more details.
14
## General Public License for more details.
15
##
15
##
16
## A copy of the GNU General Public License is available via WWW at
16
## A copy of the GNU General Public License is available via WWW at
17
## http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
17
## http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
18
## writing to the Free Software Foundation, Inc., 59 Temple Place,
18
## writing to the Free Software Foundation, Inc., 59 Temple Place,
19
## Suite 330, Boston, MA  02111-1307  USA.
19
## Suite 330, Boston, MA  02111-1307  USA.
20
 
20
 
21
## Send any bug reports to r-bugs@r-project.org
21
## Send any bug reports to r-bugs@r-project.org
22
 
22
 
23
use Cwd;
23
use Cwd;
24
use File::Basename;
24
use File::Basename;
25
use File::Copy;
25
use File::Copy;
26
use File::Find;
26
use File::Find;
27
use File::Path;
27
use File::Path;
28
use Getopt::Long;
28
use Getopt::Long;
29
use IO::File;
29
use IO::File;
30
use R::Dcf;
30
use R::Dcf;
31
use R::Logfile;
31
use R::Logfile;
32
use R::Rdtools;
32
use R::Rdtools;
33
use R::Utils;
33
use R::Utils;
34
use R::Vars;
34
use R::Vars;
35
use Text::Wrap;
35
use Text::Wrap;
36
 
36
 
37
## Don't buffer output.
37
## Don't buffer output.
38
$| = 1;
38
$| = 1;
39
 
39
 
40
my $revision = ' $Revision: 1.193 $ ';
40
my $revision = ' $Revision: 1.193 $ ';
41
my $version;
41
my $version;
42
my $name;
42
my $name;
43
$revision =~ / ([\d\.]*) /;
43
$revision =~ / ([\d\.]*) /;
44
$version = $1;
44
$version = $1;
45
($name = $0) =~ s|.*/||;
45
($name = $0) =~ s|.*/||;
46
 
46
 
47
### Options
47
### Options
48
my $opt_clean = 1;
48
my $opt_clean = 1;
49
my $opt_examples = 1;
49
my $opt_examples = 1;
50
my $opt_tests = 1;
50
my $opt_tests = 1;
51
my $opt_latex = 1;
51
my $opt_latex = 1;
52
my $opt_use_gct = 0;
52
my $opt_use_gct = 0;
53
my $opt_codoc = 1;
53
my $opt_codoc = 1;
54
my $opt_install = 1;
54
my $opt_install = 1;
55
my $opt_vignettes = 1;
55
my $opt_vignettes = 1;
56
my $opt_use_valgrind = 0;
56
my $opt_use_valgrind = 0;
57
my $opt_rcfile = "";		# Only set this if $ENV{"HOME"} is set.
57
my $opt_rcfile = "";		# Only set this if $ENV{"HOME"} is set.
58
$opt_rcfile = &file_path($ENV{"HOME"}, ".R", "check.conf")
58
$opt_rcfile = &file_path($ENV{"HOME"}, ".R", "check.conf")
59
    if defined($ENV{"HOME"});
59
    if defined($ENV{"HOME"});
60
 
60
 
61
my $WINDOWS = ($R::Vars::OSTYPE eq "windows");
61
my $WINDOWS = ($R::Vars::OSTYPE eq "windows");
62
 
62
 
63
R::Vars::error("R_HOME", "R_EXE");
63
R::Vars::error("R_HOME", "R_EXE");
64
 
64
 
65
my @known_options = ("help|h", "version|v", "outdir|o:s", "library|l:s",
65
my @known_options = ("help|h", "version|v", "outdir|o:s", "library|l:s",
66
		    "no-clean", "no-examples", "no-tests", "no-latex",
66
		    "no-clean", "no-examples", "no-tests", "no-latex",
67
		    "use-gct" => \$opt_use_gct, "no-codoc",
67
		    "use-gct" => \$opt_use_gct, "no-codoc",
68
		    "install=s" => \$opt_install, "no-install",
68
		    "install=s" => \$opt_install, "no-install",
69
		     "no-vignettes", "use-valgrind" => \$opt_use_valgrind,
69
		     "no-vignettes", "use-valgrind" => \$opt_use_valgrind,
70
		     "rcfile=s" => \$opt_rcfile);
70
		     "rcfile=s" => \$opt_rcfile);
71
GetOptions(@known_options) or usage();
71
GetOptions(@known_options) or usage();
72
 
72
 
73
R_version("R add-on package checker", $version) if $opt_version;
73
R_version("R add-on package checker", $version) if $opt_version;
74
usage() if $opt_help;
74
usage() if $opt_help;
75
 
75
 
76
$opt_clean = 0 if $opt_no_clean;
76
$opt_clean = 0 if $opt_no_clean;
77
$opt_examples = 0 if $opt_no_examples;
77
$opt_examples = 0 if $opt_no_examples;
78
$opt_tests = 0 if $opt_no_tests;
78
$opt_tests = 0 if $opt_no_tests;
79
$opt_latex = 0 if $opt_no_latex;
79
$opt_latex = 0 if $opt_no_latex;
80
$opt_codoc = 0 if $opt_no_codoc;
80
$opt_codoc = 0 if $opt_no_codoc;
81
$opt_install = 0 if $opt_no_install;
81
$opt_install = 0 if $opt_no_install;
82
$opt_vignettes = 0 if $opt_no_vignettes;
82
$opt_vignettes = 0 if $opt_no_vignettes;
83
 
83
 
84
if($opt_install eq "fake") {
84
if($opt_install eq "fake") {
85
    ## If we fake installation, then we cannot *run* any code.
85
    ## If we fake installation, then we cannot *run* any code.
86
    $opt_examples = $opt_tests = $opt_vignettes = 0;
86
    $opt_examples = $opt_tests = $opt_vignettes = 0;
87
}
87
}
88
$opt_install = 0 if($opt_install eq "no");
88
$opt_install = 0 if($opt_install eq "no");
89
 
89
 
90
my $opt_ff_calls = 1;
90
my $opt_ff_calls = 1;
91
## The neverending story ...
91
## The neverending story ...
92
## For the time being, allow to turn this off by setting the environment
92
## For the time being, allow to turn this off by setting the environment
93
## variable _R_CHECK_FF_CALLS_ to a Perl 'null' value.
93
## variable _R_CHECK_FF_CALLS_ to a Perl 'null' value.
94
if(defined($ENV{"_R_CHECK_FF_CALLS_"})) {
94
if(defined($ENV{"_R_CHECK_FF_CALLS_"})) {
95
    $opt_ff_calls = $ENV{"_R_CHECK_FF_CALLS_"};
95
    $opt_ff_calls = $ENV{"_R_CHECK_FF_CALLS_"};
96
}
96
}
97
 
97
 
98
## Use system default unless explicitly specified otherwise.
98
## Use system default unless explicitly specified otherwise.
99
$ENV{"R_DEFAULT_PACKAGES"} = "";
99
$ENV{"R_DEFAULT_PACKAGES"} = "";
100
 
100
 
101
### Configurable variables
101
### Configurable variables
102
my $R_check_use_install_log =
102
my $R_check_use_install_log =
103
    &R_getenv("_R_CHECK_USE_INSTALL_LOG_", "FALSE");
103
    &R_getenv("_R_CHECK_USE_INSTALL_LOG_", "FALSE");
104
my $R_check_subdirs_nocase =
104
my $R_check_subdirs_nocase =
105
    &R_getenv("_R_CHECK_SUBDIRS_NOCASE_", "FALSE");
105
    &R_getenv("_R_CHECK_SUBDIRS_NOCASE_", "FALSE");
106
my $R_check_all_non_ISO_C =
106
my $R_check_all_non_ISO_C =
107
    &R_getenv("_R_CHECK_ALL_NON_ISO_C_", "FALSE");
107
    &R_getenv("_R_CHECK_ALL_NON_ISO_C_", "FALSE");
108
my $R_check_weave_vignettes =
108
my $R_check_weave_vignettes =
109
    &R_getenv("_R_CHECK_WEAVE_VIGNETTES_", "TRUE");
109
    &R_getenv("_R_CHECK_WEAVE_VIGNETTES_", "TRUE");
110
 
110
 
111
## Maybe move basic configuration (and documentation) to
111
## Maybe move basic configuration (and documentation) to
112
##   &file_path($R::Vars::R_HOME, "etc", "check.conf")
112
##   &file_path($R::Vars::R_HOME, "etc", "check.conf")
113
## eventually ...
113
## eventually ...
114
for my $file ($opt_rcfile) {
114
for my $file ($opt_rcfile) {
115
    if(-r $file) {
115
    if(-r $file) {
116
	open(FILE, "< $file")
116
	open(FILE, "< $file")
117
	    or die "Error: cannot open file '$file' for reading\n";
117
	    or die "Error: cannot open file '$file' for reading\n";
118
	my @lines = <FILE>;
118
	my @lines = <FILE>;
119
	close(FILE);
119
	close(FILE);
120
	eval("@lines");
120
	eval("@lines");
121
	die "Error: failed to eval config file '$file'\n$@\n" if ($@);
121
	die "Error: failed to eval config file '$file'\n$@\n" if ($@);
122
	## <NOTE>
122
	## <NOTE>
123
	## We prefer the above to the usual recommendation
123
	## We prefer the above to the usual recommendation
124
	## 	unless ($return = do($file)) {
124
	## 	unless ($return = do($file)) {
125
	## 	    warn "couldn't parse $file: $@" if $@;
125
	## 	    warn "couldn't parse $file: $@" if $@;
126
	## 	    warn "couldn't do $file: $!"    unless defined $return;
126
	## 	    warn "couldn't do $file: $!"    unless defined $return;
127
	## 	    warn "couldn't run $file"       unless $return;
127
	## 	    warn "couldn't run $file"       unless $return;
128
	##  }
128
	##  }
129
	## as do(FILE) cannot see lexicals in the enclosing scope.
129
	## as do(FILE) cannot see lexicals in the enclosing scope.
130
	## </NOTE>
130
	## </NOTE>
131
    }
131
    }
132
}
132
}
133
 
133
 
134
$R_check_use_install_log =
134
$R_check_use_install_log =
135
    &config_val_to_logical($R_check_use_install_log);
135
    &config_val_to_logical($R_check_use_install_log);
136
$R_check_subdirs_nocase =
136
$R_check_subdirs_nocase =
137
    &config_val_to_logical($R_check_subdirs_nocase);
137
    &config_val_to_logical($R_check_subdirs_nocase);
138
$R_check_all_non_ISO_C =
138
$R_check_all_non_ISO_C =
139
    &config_val_to_logical($R_check_all_non_ISO_C);
139
    &config_val_to_logical($R_check_all_non_ISO_C);
140
$R_check_weave_vignettes =
140
$R_check_weave_vignettes =
141
    &config_val_to_logical($R_check_weave_vignettes);
141
    &config_val_to_logical($R_check_weave_vignettes);
142
 
142
 
143
my $startdir = R_cwd();
143
my $startdir = R_cwd();
144
$opt_outdir = $startdir unless $opt_outdir;
144
$opt_outdir = $startdir unless $opt_outdir;
145
chdir($opt_outdir)
145
chdir($opt_outdir)
146
    or die "Error: cannot change to directory '$opt_outdir'\n";
146
    or die "Error: cannot change to directory '$opt_outdir'\n";
147
my $outdir = R_cwd();
147
my $outdir = R_cwd();
148
chdir($startdir);
148
chdir($startdir);
149
 
149
 
150
my $R_LIBS = $ENV{'R_LIBS'};
150
my $R_LIBS = $ENV{'R_LIBS'};
151
my $library;
151
my $library;
152
if($opt_library) {
152
if($opt_library) {
153
    chdir($opt_library)
153
    chdir($opt_library)
154
	or die "Error: cannot change to directory '$opt_library'\n";
154
	or die "Error: cannot change to directory '$opt_library'\n";
155
    $library = R_cwd();
155
    $library = R_cwd();
156
    $ENV{'R_LIBS'} = env_path($library, $R_LIBS);
156
    $ENV{'R_LIBS'} = env_path($library, $R_LIBS);
157
 
157
 
158
    chdir($startdir);
158
    chdir($startdir);
159
}
159
}
160
 
160
 
161
my $tar = R_getenv("TAR", "tar");
161
my $tar = R_getenv("TAR", "tar");
162
my $gzip = R_getenv("R_GZIPCMD", "gzip");
162
my $gzip = R_getenv("R_GZIPCMD", "gzip");
163
 
163
 
164
my $R_opts = "--vanilla";
164
my $R_opts = "--vanilla";
165
 
165
 
166
if($opt_latex) {
166
if($opt_latex) {
167
    my $log = new R::Logfile();
167
    my $log = new R::Logfile();
168
    $log->checking("for working latex");
168
    $log->checking("for working latex");
169
    open(TEXFILE,
169
    open(TEXFILE,
170
	 "> " . &file_path(${R::Vars::TMPDIR}, "Rtextest$$.tex"))
170
	 "> " . &file_path(${R::Vars::TMPDIR}, "Rtextest$$.tex"))
171
      or die "Error: cannot open file 'Rtextest$$.tex' for writing\n";
171
      or die "Error: cannot open file 'Rtextest$$.tex' for writing\n";
172
    print TEXFILE "\\documentclass\{article\}\\begin\{document\}" .
172
    print TEXFILE "\\documentclass\{article\}\\begin\{document\}" .
173
	"test\\end\{document\}\n";
173
	"test\\end\{document\}\n";
174
    close(TEXFILE);
174
    close(TEXFILE);
175
    chdir($R::Vars::TMPDIR);
175
    chdir($R::Vars::TMPDIR);
176
    if(R_system("${R::Vars::LATEX} Rtextest$$ > Rtextest$$.out")) {
176
    if(R_system("${R::Vars::LATEX} Rtextest$$ > Rtextest$$.out")) {
177
	$log->result("NO");
177
	$log->result("NO");
178
	$HAVE_LATEX = 0;
178
	$HAVE_LATEX = 0;
179
    } else {
179
    } else {
180
	$log->result("OK");
180
	$log->result("OK");
181
	$HAVE_LATEX = 1;
181
	$HAVE_LATEX = 1;
182
    }
182
    }
183
    unlink(<Rtextest$$.*>);
183
    unlink(<Rtextest$$.*>);
184
    chdir($startdir);
184
    chdir($startdir);
185
    $log->close();
185
    $log->close();
186
}
186
}
187
 
187
 
188
## This is the main loop over all packages to be checked.
188
## This is the main loop over all packages to be checked.
189
(scalar(@ARGV) > 0) or die "Error: no packages were specified\n";
189
(scalar(@ARGV) > 0) or die "Error: no packages were specified\n";
190
foreach my $pkg (@ARGV) {
190
foreach my $pkg (@ARGV) {
191
    ## $pkg should be the path to the package (bundle) root source
191
    ## $pkg should be the path to the package (bundle) root source
192
    ## directory, either absolute or relative to $startdir.
192
    ## directory, either absolute or relative to $startdir.
193
    ## As from 2.1.0 it can also be a tarball
193
    ## As from 2.1.0 it can also be a tarball
194
 
194
 
195
    ## $pkgdir is the corresponding absolute path.
195
    ## $pkgdir is the corresponding absolute path.
196
    ## $pkgname is the name of the package (bundle).
196
    ## $pkgname is the name of the package (bundle).
197
    chdir($startdir);
197
    chdir($startdir);
198
    $pkg =~ s+/$++;  # strip any trailing '/'
198
    $pkg =~ s+/$++;  # strip any trailing '/'
199
    my $pkgname = basename($pkg);
199
    my $pkgname = basename($pkg);
200
 
200
 
201
    ## is this a tar archive?
201
    ## is this a tar archive?
202
    my $istar = 0;
202
    my $istar = 0;
203
    if($pkgname =~ /\.tar\.gz$/ || $pkgname =~ /\.tgz$/) {
203
    if($pkgname =~ /\.tar\.gz$/ || $pkgname =~ /\.tgz$/) {
204
	$pkgname =~ s/\.tar\.gz$//;
204
	$pkgname =~ s/\.tar\.gz$//;
205
	$pkgname =~ s/\.tgz$//;
205
	$pkgname =~ s/\.tgz$//;
206
	$pkgname =~ s/_[0-9\.-]*$//;
206
	$pkgname =~ s/_[0-9\.-]*$//;
207
	$istar = 1;
207
	$istar = 1;
208
    }
208
    }
209
 
209
 
210
    my $pkgoutdir = &file_path($outdir, "$pkgname.Rcheck");
210
    my $pkgoutdir = &file_path($outdir, "$pkgname.Rcheck");
211
    rmtree($pkgoutdir) if ($opt_clean && (-d $pkgoutdir)) ;
211
    rmtree($pkgoutdir) if ($opt_clean && (-d $pkgoutdir)) ;
212
    if(!(-d $pkgoutdir)) {
212
    if(!(-d $pkgoutdir)) {
213
	mkdir($pkgoutdir, 0755)
213
	mkdir($pkgoutdir, 0755)
214
	  or die("Error: cannot create directory '$pkgoutdir'\n");
214
	  or die("Error: cannot create directory '$pkgoutdir'\n");
215
    }
215
    }
216
 
216
 
217
    if($istar) {
217
    if($istar) {
218
	my $dir = &file_path("$pkgoutdir", "00_pkg_src");
218
	my $dir = &file_path("$pkgoutdir", "00_pkg_src");
219
	mkdir($dir, 0755)
219
	mkdir($dir, 0755)
220
	  or die("Error: cannot create directory '$dir'\n");
220
	  or die("Error: cannot create directory '$dir'\n");
221
	if($WINDOWS) {
221
	if($WINDOWS) {
222
	    ## workaround for paths in Cygwin tar
222
	    ## workaround for paths in Cygwin tar
223
	    $pkg =~ s+^([A-Za-x]):+/cygdrive/\1+;
223
	    $pkg =~ s+^([A-Za-x]):+/cygdrive/\1+;
224
	}
224
	}
225
	if(R_system("$gzip -dc '$pkg' | $tar -xf - -C $dir")) {
225
	if(R_system("$gzip -dc '$pkg' | $tar -xf - -C $dir")) {
226
	    die "Error: cannot untar $pkg\n";}
226
	    die "Error: cannot untar $pkg\n";}
227
	$pkg = &file_path($dir, $pkgname);
227
	$pkg = &file_path($dir, $pkgname);
228
    }
228
    }
229
 
229
 
230
    $pkg =~ s/\/$//;
230
    $pkg =~ s/\/$//;
231
    (-d $pkg) or die "Error: package dir '$pkg' does not exist\n";
231
    (-d $pkg) or die "Error: package dir '$pkg' does not exist\n";
232
    chdir($pkg)
232
    chdir($pkg)
233
	or die "Error: cannot change to directory '$pkg'\n";
233
	or die "Error: cannot change to directory '$pkg'\n";
234
    my $pkgdir = R_cwd();
234
    my $pkgdir = R_cwd();
235
    ## my $pkgname = basename($pkgdir);
235
    ## my $pkgname = basename($pkgdir);
236
    chdir($startdir);
236
    chdir($startdir);
237
 
237
 
238
    $log = new R::Logfile(&file_path($pkgoutdir, "00check.log"));
238
    $log = new R::Logfile(&file_path($pkgoutdir, "00check.log"));
239
    $log->message("using log directory '$pkgoutdir'");
239
    $log->message("using log directory '$pkgoutdir'");
240
    my @out = R_runR("cat(R.version.string, '\n', sep='')", 
240
    my @out = R_runR("cat(R.version.string, '\n', sep='')", 
241
		     "--slave --vanilla");
241
		     "--slave --vanilla");
242
    $log->message("using @out");
242
    $log->message("using @out");
243
 
243
 
244
    if(!$opt_library) {
244
    if(!$opt_library) {
245
	$library = $pkgoutdir;
245
	$library = $pkgoutdir;
246
	$ENV{'R_LIBS'} = env_path($library, $R_LIBS);
246
	$ENV{'R_LIBS'} = env_path($library, $R_LIBS);
247
    }
247
    }
248
    if($WINDOWS) { ## need to avoid spaces in $library
248
    if($WINDOWS) { ## need to avoid spaces in $library
249
	$library = Win32::GetShortPathName($library) if $library =~ / /;
249
	$library = Win32::GetShortPathName($library) if $library =~ / /;
250
    }
250
    }
251
 
251
 
252
    my $description;
252
    my $description;
253
    my $is_base_pkg = 0;
253
    my $is_base_pkg = 0;
254
    my $is_bundle = 0;
254
    my $is_bundle = 0;
255
    my $package_or_bundle = "package";
255
    my $package_or_bundle = "package";
256
    my $package_or_bundle_name;
256
    my $package_or_bundle_name;
257
    ## Package sources from the R distribution are special.  They have a
257
    ## Package sources from the R distribution are special.  They have a
258
    ## 'DESCRIPTION.in' file (instead of 'DESCRIPTION'), with Version
258
    ## 'DESCRIPTION.in' file (instead of 'DESCRIPTION'), with Version
259
    ## field containing '@VERSION@' for substitution by configure.  We
259
    ## field containing '@VERSION@' for substitution by configure.  We
260
    ## test for such packages by looking for 'DESCRIPTION.in' with
260
    ## test for such packages by looking for 'DESCRIPTION.in' with
261
    ## Priority 'base', and skip the installation test for such
261
    ## Priority 'base', and skip the installation test for such
262
    ## packages.
262
    ## packages.
263
    if(-r &file_path($pkgdir, "DESCRIPTION.in")) {
263
    if(-r &file_path($pkgdir, "DESCRIPTION.in")) {
264
	$description =
264
	$description =
265
	  new R::Dcf(&file_path($pkgdir, "DESCRIPTION.in"));
265
	  new R::Dcf(&file_path($pkgdir, "DESCRIPTION.in"));
266
	if($description->{"Priority"} eq "base") {
266
	if($description->{"Priority"} eq "base") {
267
	    $log->message("looks like '${pkgname}' is a base package");
267
	    $log->message("looks like '${pkgname}' is a base package");
268
	    $log->message("skipping installation test");
268
	    $log->message("skipping installation test");
269
	    $is_base_pkg = 1;
269
	    $is_base_pkg = 1;
270
	}
270
	}
271
    }
271
    }
272
 
272
 
273
    if(!$is_base_pkg) {
273
    if(!$is_base_pkg) {
274
	$log->checking(join("",
274
	$log->checking(join("",
275
			    ("for file '",
275
			    ("for file '",
276
			     &file_path($pkgname, "DESCRIPTION"),
276
			     &file_path($pkgname, "DESCRIPTION"),
277
			     "'")));
277
			     "'")));
278
	if(-r &file_path($pkgdir, "DESCRIPTION")) {
278
	if(-r &file_path($pkgdir, "DESCRIPTION")) {
279
	    $description =
279
	    $description =
280
	      new R::Dcf(&file_path($pkgdir, "DESCRIPTION"));
280
	      new R::Dcf(&file_path($pkgdir, "DESCRIPTION"));
281
	    $log->result("OK");
281
	    $log->result("OK");
282
	}
282
	}
283
	else {
283
	else {
284
	    $log->result("NO");
284
	    $log->result("NO");
285
	    exit(1);
285
	    exit(1);
286
	}
286
	}
287
	if($description->{"Type"}) { # standard packages do not have this
287
	if($description->{"Type"}) { # standard packages do not have this
288
	    $log->checking("extension type");
288
	    $log->checking("extension type");
289
	    $log->result($description->{"Type"});
289
	    $log->result($description->{"Type"});
290
	    if($description->{"Type"} ne "Package") {
290
	    if($description->{"Type"} ne "Package") {
291
		$log->print("Only Type = Package extensions can be checked.\n");
291
		$log->print("Only Type = Package extensions can be checked.\n");
292
		exit(0);
292
		exit(0);
293
	    }
293
	    }
294
	}
294
	}
295
 
295
 
296
	if($description->{"Bundle"}) {
296
	if($description->{"Bundle"}) {
297
	    $is_bundle = 1;
297
	    $is_bundle = 1;
298
	    $log->message("looks like '${pkgname}' is a package bundle");
298
	    $log->message("looks like '${pkgname}' is a package bundle");
299
	    $package_or_bundle = "bundle";
299
	    $package_or_bundle = "bundle";
300
	    $package_or_bundle_name = $description->{"Bundle"};
300
	    $package_or_bundle_name = $description->{"Bundle"};
301
	}
301
	}
302
	else {
302
	else {
303
	    $package_or_bundle_name = $description->{"Package"};
303
	    $package_or_bundle_name = $description->{"Package"};
304
	}
304
	}
305
	$log->message("this is $package_or_bundle " .
305
	$log->message("this is $package_or_bundle " .
306
		      "'$package_or_bundle_name' " .
306
		      "'$package_or_bundle_name' " .
307
		      "version '$description->{\"Version\"}'");
307
		      "version '$description->{\"Version\"}'");
308
	## <NOTE>
308
	## <NOTE>
309
	## This check should be adequate, but would not catch a manually
309
	## This check should be adequate, but would not catch a manually
310
	## installed package, nor one installed prior to 1.4.0.
310
	## installed package, nor one installed prior to 1.4.0.
311
	## </NOTE>
311
	## </NOTE>
312
	$log->checking("if this is a source $package_or_bundle");
312
	$log->checking("if this is a source $package_or_bundle");
313
	if(defined($description->{"Built"})) {
313
	if(defined($description->{"Built"})) {
314
	    $log->error();
314
	    $log->error();
315
	    $log->print("Only *source* packages can be checked.\n");
315
	    $log->print("Only *source* packages can be checked.\n");
316
	    exit(1);
316
	    exit(1);
317
	}
317
	}
318
	elsif($opt_install !~ /^check/) {
318
	elsif($opt_install !~ /^check/) {
319
	    ## Check for package/bundle 'src' subdirectories with object
319
	    ## Check for package/bundle 'src' subdirectories with object
320
	    ## files (but not if installation was already performed).
320
	    ## files (but not if installation was already performed).
321
	    my $any;
321
	    my $any;
322
	    my $pat = "(a|o|[ls][ao]|sl|obj)"; # Object file extensions.
322
	    my $pat = "(a|o|[ls][ao]|sl|obj)"; # Object file extensions.
323
	    my @dirs;
323
	    my @dirs;
324
	    if($in_bundle) {
324
	    if($in_bundle) {
325
		foreach my $ppkg (split(/\s+/,
325
		foreach my $ppkg (split(/\s+/,
326
					description->{"Contains"})) {
326
					description->{"Contains"})) {
327
		    push(@dirs, &file_path($ppkg, "src"));
327
		    push(@dirs, &file_path($ppkg, "src"));
328
		}
328
		}
329
	    }
329
	    }
330
	    else {
330
	    else {
331
		@dirs = ("src");
331
		@dirs = ("src");
332
	    }
332
	    }
333
	    foreach my $dir (@dirs) {
333
	    foreach my $dir (@dirs) {
334
		if((-d &file_path($pkgdir, $dir))
334
		if((-d &file_path($pkgdir, $dir))
335
		   && &list_files_with_exts(&file_path($pkgdir, $dir),
335
		   && &list_files_with_exts(&file_path($pkgdir, $dir),
336
					    $pat)) {
336
					    $pat)) {
337
		    $log->warning() unless $any;
337
		    $log->warning() unless $any;
338
		    $any++;
338
		    $any++;
339
		    $dir = &file_path($pkgname, $dir);
339
		    $dir = &file_path($pkgname, $dir);
340
		    $log->print("Subdirectory '$dir' " .
340
		    $log->print("Subdirectory '$dir' " .
341
				"contains object files.\n");
341
				"contains object files.\n");
342
		}
342
		}
343
	    }
343
	    }
344
	    $log->result("OK") unless $any;	    
344
	    $log->result("OK") unless $any;	    
345
	}
345
	}
346
	else {
346
	else {
347
	    $log->result("OK");
347
	    $log->result("OK");
348
	}
348
	}
349
	    
349
	    
350
	## Option '--no-install' turns off installation and the tests
350
	## Option '--no-install' turns off installation and the tests
351
	## which require the package to be installed.  When testing
351
	## which require the package to be installed.  When testing
352
	## recommended packages bundled with R we can skip installation,
352
	## recommended packages bundled with R we can skip installation,
353
	## and do so if '--install=skip' was given.  If command line
353
	## and do so if '--install=skip' was given.  If command line
354
	## option '--install' is of the form 'check:FILE', it is assumed
354
	## option '--install' is of the form 'check:FILE', it is assumed
355
	## that installation was already performed with stdout/stderr to
355
	## that installation was already performed with stdout/stderr to
356
	## FILE, the contents of which need to be checked (without
356
	## FILE, the contents of which need to be checked (without
357
	## repeating the installation).
357
	## repeating the installation).
358
	## <NOTE>
358
	## <NOTE>
359
	## In this case, one also needs to specify *where* the package
359
	## In this case, one also needs to specify *where* the package
360
	## was installed to using command line option '--library'.
360
	## was installed to using command line option '--library'.
361
	## Perhaps we should check for that, although '--install=check'
361
	## Perhaps we should check for that, although '--install=check'
362
	## is really only meant for repository maintainers.
362
	## is really only meant for repository maintainers.
363
	## </NOTE>
363
	## </NOTE>
364
	if($opt_install) {
364
	if($opt_install) {
365
	    if($opt_install eq "skip") {
365
	    if($opt_install eq "skip") {
366
		$log->message("skipping installation test");
366
		$log->message("skipping installation test");
367
	    }
367
	    }
368
	    else {
368
	    else {
369
		my $use_install_log =
369
		my $use_install_log =
370
		    (($opt_install =~ /^check/) ||
370
		    (($opt_install =~ /^check/) ||
371
		     $R_check_use_install_log ||
371
		     $R_check_use_install_log ||
372
		     !(-t STDIN && -t STDOUT));
372
		     !(-t STDIN && -t STDOUT));
373
		my $INSTALL_opts = "";
373
		my $INSTALL_opts = "";
374
		$INSTALL_opts = "--fake" if($opt_install eq "fake");
374
		$INSTALL_opts = "--fake" if($opt_install eq "fake");
375
		my $cmd;
375
		my $cmd;
376
		if($WINDOWS) {
376
		if($WINDOWS) {
377
		    $cmd = join(" ",
377
		    $cmd = join(" ",
378
				("Rcmd.exe INSTALL -l",
378
				("Rcmd.exe INSTALL -l",
379
				 &shell_quote_file_path($library),
379
				 &shell_quote_file_path($library),
380
				 "$INSTALL_opts",
380
				 "$INSTALL_opts",
381
				 &shell_quote_file_path($pkgdir)));
381
				 &shell_quote_file_path($pkgdir)));
382
		} else {
382
		} else {
383
		    $cmd = join(" ",
383
		    $cmd = join(" ",
384
				(&shell_quote_file_path(${R::Vars::R_EXE}),
384
				(&shell_quote_file_path(${R::Vars::R_EXE}),
385
				 "CMD INSTALL -l",
385
				 "CMD INSTALL -l",
386
				 &shell_quote_file_path($library),
386
				 &shell_quote_file_path($library),
387
				 "$INSTALL_opts",
387
				 "$INSTALL_opts",
388
				 &shell_quote_file_path($pkgdir)));
388
				 &shell_quote_file_path($pkgdir)));
389
		}
389
		}
390
		if(!$use_install_log) {
390
		if(!$use_install_log) {
391
		    ## Case A: No redirection of stdout/stderr from
391
		    ## Case A: No redirection of stdout/stderr from
392
		    ## installation.
392
		    ## installation.
393
		    print("\n");
393
		    print("\n");
394
		    if(R_system($cmd)) {
394
		    if(R_system($cmd)) {
395
			$log->error();
395
			$log->error();
396
			$log->print("Installation failed.\n");
396
			$log->print("Installation failed.\n");
397
			exit(1);
397
			exit(1);
398
		    }
398
		    }
399
		    print("\n");
399
		    print("\n");
400
		}
400
		}
401
		else {
401
		else {
402
		    ## Case B. All output from installation redirected,
402
		    ## Case B. All output from installation redirected,
403
		    ## or already available in the log file.
403
		    ## or already available in the log file.
404
		    $log->checking("whether $package_or_bundle " .
404
		    $log->checking("whether $package_or_bundle " .
405
				   "'$package_or_bundle_name' " .
405
				   "'$package_or_bundle_name' " .
406
				   "can be installed");
406
				   "can be installed");
407
		    my $out = &file_path($pkgoutdir, "00install.out");
407
		    my $out = &file_path($pkgoutdir, "00install.out");
408
		    my $install_error;
408
		    my $install_error;
409
		    my @lines;
409
		    my @lines;
410
		    if($opt_install =~ /^check/) {
410
		    if($opt_install =~ /^check/) {
411
			copy(substr($opt_install, 6), $out);
411
			copy(substr($opt_install, 6), $out);
412
			$opt_install = "check";
412
			$opt_install = "check";
413
			@lines = &read_lines($out);
413
			@lines = &read_lines($out);
414
			$install_error =
414
			$install_error =
415
			    ($lines[$#lines] !~ /^\* DONE/);
415
			    ($lines[$#lines] !~ /^\* DONE/);
416
		    }
416
		    }
417
		    else {
417
		    else {
418
			$cmd .= " >" .
418
			$cmd .= " >" .
419
			    &shell_quote_file_path($out) .
419
			    &shell_quote_file_path($out) .
420
			    " 2>&1";
420
			    " 2>&1";
421
			$install_error = &R_system($cmd);
421
			$install_error = &R_system($cmd);
422
		    }
422
		    }
423
		    if($install_error) {
423
		    if($install_error) {
424
			$log->error();
424
			$log->error();
425
			$log->print("Installation failed.\n");
425
			$log->print("Installation failed.\n");
426
			$log->print("See '$out' for details.\n");
426
			$log->print("See '$out' for details.\n");
427
			exit(1);
427
			exit(1);
428
		    }
428
		    }
429
		    ## There could still be some important warnings that
429
		    ## There could still be some important warnings that
430
		    ## we'd like to report.  For the time being, start
430
		    ## we'd like to report.  For the time being, start
431
		    ## with compiler warnings about non ISO C code (Or
431
		    ## with compiler warnings about non ISO C code (Or
432
		    ## at least, what looks like it.)  In theory, we
432
		    ## at least, what looks like it.)  In theory, we
433
		    ## should only do this when using GCC ...
433
		    ## should only do this when using GCC ...
434
		    @lines = &read_lines($out)
434
		    @lines = &read_lines($out)
435
			unless($opt_install eq "check");
435
			unless($opt_install eq "check");
436
		    my $warn_re =
436
		    my $warn_re =
437
			"(" . join("|", ("^WARNING:",
437
			"(" . join("|", ("^WARNING:",
438
					 "^Warning:",
438
					 "^Warning:",
439
					 ": warning: .*ISO C",
439
					 ": warning: .*ISO C",
440
					 "missing link\\(s\\):")) . ")";
440
					 "missing link\\(s\\):")) . ")";
441
		    @lines = grep(/$warn_re/, @lines);
441
		    @lines = grep(/$warn_re/, @lines);
442
		    ## Ignore install time readLines() warnings about
442
		    ## Ignore install time readLines() warnings about
443
		    ## files with incomplete final lines.  Most of these
443
		    ## files with incomplete final lines.  Most of these
444
		    ## come from .install_package_indices(), and should be
444
		    ## come from .install_package_indices(), and should be
445
		    ## safe to ignore ...
445
		    ## safe to ignore ...
446
		    $warn_re = "Warning: incomplete final line " .
446
		    $warn_re = "Warning: incomplete final line " .
447
			"found by readLines";
447
			"found by readLines";
448
		    @lines = grep(!/$warn_re/, @lines);
448
		    @lines = grep(!/$warn_re/, @lines);
449
		    ## Package writers cannot really do anything about
449
		    ## Package writers cannot really do anything about
450
		    ## non ISO C code in *system* headers.  Also, GCC
450
		    ## non ISO C code in *system* headers.  Also, GCC
451
		    ## 3.4 or better warns about function pointers
451
		    ## 3.4 or better warns about function pointers
452
		    ## casts which are "needed" for dlsym(), but it
452
		    ## casts which are "needed" for dlsym(), but it
453
		    ## seems that all systems which have dlsym() also
453
		    ## seems that all systems which have dlsym() also
454
		    ## support the cast.  Hence, try to ignore these by
454
		    ## support the cast.  Hence, try to ignore these by
455
		    ## default, but make it possible to get all ISO C
455
		    ## default, but make it possible to get all ISO C
456
		    ## warnings via an environment variable.
456
		    ## warnings via an environment variable.
457
		    if(!$R_check_all_non_ISO_C) {
457
		    if(!$R_check_all_non_ISO_C) {
458
			@lines = grep(!/^ *\/.*: warning: .*ISO C/,
458
			@lines = grep(!/^ *\/.*: warning: .*ISO C/,
459
				      @lines);
459
				      @lines);
460
			$warn_re = "warning: *ISO C forbids.*" .
460
			$warn_re = "warning: *ISO C forbids.*" .
461
			    "function pointer";
461
			    "function pointer";
462
			@lines = grep(!/$warn_re/, @lines);
462
			@lines = grep(!/$warn_re/, @lines);
463
		    }
463
		    }
464
		    if(scalar(@lines) > 0) {
464
		    if(scalar(@lines) > 0) {
465
			$log->warning();
465
			$log->warning();
466
			$log->print("Found the following " .
466
			$log->print("Found the following " .
467
				    "significant warnings:\n");
467
				    "significant warnings:\n");
468
			$log->print("  " . join("\n  ", @lines) . "\n");
468
			$log->print("  " . join("\n  ", @lines) . "\n");
469
		    }
469
		    }
470
		    else {
470
		    else {
471
			$log->result("OK");
471
			$log->result("OK");
472
		    }
472
		    }
473
		}
473
		}
474
	    }
474
	    }
475
	}
475
	}
476
 
476
 
477
    }
477
    }
478
 
478
 
479
    if($is_bundle) {
479
    if($is_bundle) {
480
	my @bundlepkgs = split(/\s+/, $description->{"Contains"});
480
	my @bundlepkgs = split(/\s+/, $description->{"Contains"});
481
	foreach my $ppkg (@bundlepkgs) {
481
	foreach my $ppkg (@bundlepkgs) {
482
	    $log->message("checking '$ppkg' in bundle '$pkgname'");
482
	    $log->message("checking '$ppkg' in bundle '$pkgname'");
483
	    $log->setstars("**");
483
	    $log->setstars("**");
484
	    chdir($startdir);
484
	    chdir($startdir);
485
	    check_pkg(&file_path($pkgdir, $ppkg), $pkgoutdir, $startdir,
485
	    check_pkg(&file_path($pkgdir, $ppkg), $pkgoutdir, $startdir,
486
		      $library, $is_bundle, $description, $log,
486
		      $library, $is_bundle, $description, $log,
487
		      $is_base_pkg);
487
		      $is_base_pkg);
488
	    $log->setstars("*");
488
	    $log->setstars("*");
489
	}
489
	}
490
    }
490
    }
491
    else {
491
    else {
492
	chdir($startdir);
492
	chdir($startdir);
493
	check_pkg($pkgdir, $pkgoutdir, $startdir, $library,
493
	check_pkg($pkgdir, $pkgoutdir, $startdir, $library,
494
		  $is_bundle, $description, $log, $is_base_pkg);
494
		  $is_bundle, $description, $log, $is_base_pkg);
495
    }
495
    }
496
 
496
 
497
    if($log->{"warnings"}) {
497
    if($log->{"warnings"}) {
498
	print("\n") ;
498
	print("\n") ;
499
	$log->summary();
499
	$log->summary();
500
    }
500
    }
501
    $log->close();
501
    $log->close();
502
    print("\n");
502
    print("\n");
503
}
503
}
504
 
504
 
505

505

506
sub check_pkg {
506
sub check_pkg {
507
 
507
 
508
    my ($pkg, $pkgoutdir, $startdir, $library,
508
    my ($pkg, $pkgoutdir, $startdir, $library,
509
	$in_bundle, $description, $log, $is_base_pkg) = @_;
509
	$in_bundle, $description, $log, $is_base_pkg) = @_;
510
    my ($pkgdir, $pkgname);
510
    my ($pkgdir, $pkgname);
511
 
511
 
512
    ## $pkg is the argument we received from the main loop.
512
    ## $pkg is the argument we received from the main loop.
513
    ## $pkgdir is the corresponding absolute path,
513
    ## $pkgdir is the corresponding absolute path,
514
    ## $pkgname the name of the package.
514
    ## $pkgname the name of the package.
515
    ## Note that we need to do repeat the checking from the main loop in
515
    ## Note that we need to do repeat the checking from the main loop in
516
    ## the case of package bundles (and we could check for this).
516
    ## the case of package bundles (and we could check for this).
517
 
517
 
518
    $log->checking("package directory");
518
    $log->checking("package directory");
519
    chdir($startdir);
519
    chdir($startdir);
520
    $pkg =~ s/\/$//;
520
    $pkg =~ s/\/$//;
521
    if(-d $pkg) {
521
    if(-d $pkg) {
522
	chdir($pkg)
522
	chdir($pkg)
523
	  or die "Error: cannot change to directory '$pkg'\n";
523
	  or die "Error: cannot change to directory '$pkg'\n";
524
	$pkgdir = R_cwd();
524
	$pkgdir = R_cwd();
525
	$pkgname = basename($pkgdir);
525
	$pkgname = basename($pkgdir);
526
    }
526
    }
527
    else {
527
    else {
528
	$log->error();
528
	$log->error();
529
	$log->print("Package directory '$pkg' does not exist.\n");
529
	$log->print("Package directory '$pkg' does not exist.\n");
530
	exit(1);
530
	exit(1);
531
    }
531
    }
532
    $log->result("OK");
532
    $log->result("OK");
533
 
533
 
534
    chdir($pkgdir);
534
    chdir($pkgdir);
535
 
535
 
536
    ## Build list of exclude patterns.
536
    ## Build list of exclude patterns.
537
 
537
 
538
    my @exclude_patterns = R::Utils::get_exclude_patterns();
538
    my @exclude_patterns = R::Utils::get_exclude_patterns();
539
    my $exclude_file = ".Rbuildignore";
539
    my $exclude_file = ".Rbuildignore";
540
    ## This is a bit tricky for bundles where the build ignore pattern
540
    ## This is a bit tricky for bundles where the build ignore pattern
541
    ## file is in the top-level bundle dir.
541
    ## file is in the top-level bundle dir.
542
    $exclude_file = &file_path(dirname($pkgdir), $exclude_file);
542
    $exclude_file = &file_path(dirname($pkgdir), $exclude_file);
543
    if(-f $exclude_file) {
543
    if(-f $exclude_file) {
544
	open(RBUILDIGNORE, "< $exclude_file");
544
	open(RBUILDIGNORE, "< $exclude_file");
545
	while(<RBUILDIGNORE>) {
545
	while(<RBUILDIGNORE>) {
546
	    chop;	    
546
	    chop;	    
547
	    push(@exclude_patterns, $_) if $_;
547
	    push(@exclude_patterns, $_) if $_;
548
	}
548
	}
549
	close(RBUILDIGNORE);
549
	close(RBUILDIGNORE);
550
    }
550
    }
551
 
551
 
552
    ## Check for portable file names.
552
    ## Check for portable file names.
553
 
553
 
554
    ## Ensure that the names of the files in the package are valid for
554
    ## Ensure that the names of the files in the package are valid for
555
    ## at least the supported OS types.  Under Unix, we definitely
555
    ## at least the supported OS types.  Under Unix, we definitely
556
    ## cannot have '/'; under Windows, the control characters as well as
556
    ## cannot have '/'; under Windows, the control characters as well as
557
    ##   " * : < > ? \ |
557
    ##   " * : < > ? \ |
558
    ## (i.e., ASCII characters 1 to 31 and 34, 36, 58, 60, 62, 63, 92,
558
    ## (i.e., ASCII characters 1 to 31 and 34, 36, 58, 60, 62, 63, 92,
559
    ## and 124) are or can be invalid.  (In addition, one cannot have
559
    ## and 124) are or can be invalid.  (In addition, one cannot have
560
    ## one-character file names consisting of just ' ', '.', or '~'.)
560
    ## one-character file names consisting of just ' ', '.', or '~'.)
561
    ## Based on information by Uwe Ligges, Duncan Murdoch, and Brian
561
    ## Based on information by Uwe Ligges, Duncan Murdoch, and Brian
562
    ## Ripley.
562
    ## Ripley.
563
 
563
 
564
    ## Furthermore, Uwe Ligges says that Windows still does not allow
564
    ## Furthermore, Uwe Ligges says that Windows still does not allow
565
    ## the following DOS device names (by themselves or with possible
565
    ## the following DOS device names (by themselves or with possible
566
    ## extensions):
566
    ## extensions):
567
    ##
567
    ##
568
    ## Name    Function
568
    ## Name    Function
569
    ## ----    --------
569
    ## ----    --------
570
    ## CON     Keyboard and display
570
    ## CON     Keyboard and display
571
    ## PRN     System list device, usually a parallel port
571
    ## PRN     System list device, usually a parallel port
572
    ## AUX     Auxiliary device, usually a serial port
572
    ## AUX     Auxiliary device, usually a serial port
573
    ## CLOCK$  System real-time clock
573
    ## CLOCK$  System real-time clock
574
    ## NUL     Bit-bucket device
574
    ## NUL     Bit-bucket device
575
    ## COM1    First serial communications port
575
    ## COM1    First serial communications port
576
    ## COM2    Second serial communications port
576
    ## COM2    Second serial communications port
577
    ## COM3    Third serial communications port
577
    ## COM3    Third serial communications port
578
    ## COM4    Fourth serial communications port
578
    ## COM4    Fourth serial communications port
579
    ## LPT1    First parallel printer port
579
    ## LPT1    First parallel printer port
580
    ## LPT2    Second parallel printer port
580
    ## LPT2    Second parallel printer port
581
    ## LPT3    Third parallel printer port
581
    ## LPT3    Third parallel printer port
582
 
582
 
583
    $log->checking("for portable file names");
583
    $log->checking("for portable file names");
584
    my @bad_files = ();
584
    my @bad_files = ();
585
    sub find_wrong_names {
585
    sub find_wrong_names {
586
	my $file_path = $File::Find::name;
586
	my $file_path = $File::Find::name;
587
	$file_path =~ s/^\.[^\/]*\///;
587
	$file_path =~ s/^\.[^\/]*\///;
588
	foreach my $p (@exclude_patterns) {
588
	foreach my $p (@exclude_patterns) {
589
	    if($WINDOWS) {
589
	    if($WINDOWS) {
590
		## Argh: Windows is case-honoring but not
590
		## Argh: Windows is case-honoring but not
591
		## case-insensitive ...
591
		## case-insensitive ...
592
		return 0 if($file_path =~ /$p/i);
592
		return 0 if($file_path =~ /$p/i);
593
	    }
593
	    }
594
	    else {
594
	    else {
595
		return 0 if($file_path =~ /$p/);
595
		return 0 if($file_path =~ /$p/);
596
	    }
596
	    }
597
	}
597
	}
598
	my $file_name = basename($file_path);
598
	my $file_name = basename($file_path);
599
	if(grep(/[[:cntrl:]\"\*\/\:\<\>\?\\\|]/, $file_name)) {
599
	if(grep(/[[:cntrl:]\"\*\/\:\<\>\?\\\|]/, $file_name)) {
600
	    push(@bad_files, $file_path);
600
	    push(@bad_files, $file_path);
601
	}
601
	}
602
	else {
602
	else {
603
	    $file_name =~ tr/A-Z/a-z/;
603
	    $file_name =~ tr/A-Z/a-z/;
604
	    $file_name =~ s/\..*//;
604
	    $file_name =~ s/\..*//;
605
	    push(@bad_files, $file_path)
605
	    push(@bad_files, $file_path)
606
	      if(grep(/^(con|prn|aux|clock\$|nul|lpt[1-3]|com[1-4])$/,
606
	      if(grep(/^(con|prn|aux|clock\$|nul|lpt[1-3]|com[1-4])$/,
607
		     $file_name));
607
		     $file_name));
608
	}
608
	}
609
    }
609
    }
610
    if($in_bundle) {
610
    if($in_bundle) {
611
	chdir(dirname($pkgdir)); # more portable than '..'?
611
	chdir(dirname($pkgdir)); # more portable than '..'?
612
	find(\&find_wrong_names, $pkgname);
612
	find(\&find_wrong_names, $pkgname);
613
	chdir($pkgname);
613
	chdir($pkgname);
614
    }
614
    }
615
    else {
615
    else {
616
	find(\&find_wrong_names, ".");
616
	find(\&find_wrong_names, ".");
617
    }
617
    }
618
    if(scalar(@bad_files) > 0) {
618
    if(scalar(@bad_files) > 0) {
619
	$log->error();
619
	$log->error();
620
	$log->print("Found the following file(s) with " .
620
	$log->print("Found the following file(s) with " .
621
		    "non-portable file names:\n");
621
		    "non-portable file names:\n");
622
	$log->print("  " . join("\n  ", @bad_files) . "\n");
622
	$log->print("  " . join("\n  ", @bad_files) . "\n");
623
	$log->print(wrap("", "",
623
	$log->print(wrap("", "",
624
			 ("These are not valid file names",
624
			 ("These are not valid file names",
625
			  "on all R platforms.\n",
625
			  "on all R platforms.\n",
626
			  "Please rename the files and try again.\n",
626
			  "Please rename the files and try again.\n",
627
			  "See section 'Package structure'",
627
			  "See section 'Package structure'",
628
			  "in manual 'Writing R Extensions'.\n")));
628
			  "in manual 'Writing R Extensions'.\n")));
629
	exit(1);
629
	exit(1);
630
    }
630
    }
631
 
631
 
632
    ## next check for name clashes on case-insensitive file systems
632
    ## next check for name clashes on case-insensitive file systems
633
    ## (that is on Windows).
633
    ## (that is on Windows).
634
    %seen = (); 
634
    %seen = (); 
635
    my @duplicated = ();
635
    my @duplicated = ();
636
    sub check_case_names {
636
    sub check_case_names {
637
	my $file_path = lc($File::Find::name);
637
	my $file_path = lc($File::Find::name);
638
	if($seen{$file_path}) {push(@duplicated, $file_path);}
638
	if($seen{$file_path}) {push(@duplicated, $file_path);}
639
	$seen{$file_path}  = 1;
639
	$seen{$file_path}  = 1;
640
    }
640
    }
641
    if($in_bundle) {
641
    if($in_bundle) {
642
	chdir(dirname($pkgdir)); # more portable than '..'?
642
	chdir(dirname($pkgdir)); # more portable than '..'?
643
	find(\&check_case_names, $pkgname);
643
	find(\&check_case_names, $pkgname);
644
	chdir($pkgname);
644
	chdir($pkgname);
645
    }
645
    }
646
    else {
646
    else {
647
	find(\&check_case_names, ".");
647
	find(\&check_case_names, ".");
648
    }
648
    }
649
    if(scalar(@duplicated) > 0) {
649
    if(scalar(@duplicated) > 0) {
650
	$log->error();
650
	$log->error();
651
	$log->print("Found the following file(s) with " .
651
	$log->print("Found the following file(s) with " .
652
		    "duplicate lower-cased file names:\n");
652
		    "duplicate lower-cased file names:\n");
653
	$log->print("  " . join("\n  ", @duplicated) . "\n");
653
	$log->print("  " . join("\n  ", @duplicated) . "\n");
654
	$log->print(wrap("", "",
654
	$log->print(wrap("", "",
655
			 ("File names must not differ just by case",
655
			 ("File names must not differ just by case",
656
			  "to be usable on all R platforms.\n",
656
			  "to be usable on all R platforms.\n",
657
			  "Please rename the files and try again.\n",
657
			  "Please rename the files and try again.\n",
658
			  "See section 'Package structure'",
658
			  "See section 'Package structure'",
659
			  "in manual 'Writing R Extensions'.\n")));
659
			  "in manual 'Writing R Extensions'.\n")));
660
	exit(1);
660
	exit(1);
661
    }
661
    }
662
 
662
 
663
    $log->result("OK");
663
    $log->result("OK");
664
 
664
 
665
    ## Check for sufficient file permissions (Unix only).
665
    ## Check for sufficient file permissions (Unix only).
666
 
666
 
667
    ## This used to be much more 'aggressive', requiring that dirs and
667
    ## This used to be much more 'aggressive', requiring that dirs and
668
    ## files have mode >= 00755 and 00644, respectively (with an error
668
    ## files have mode >= 00755 and 00644, respectively (with an error
669
    ## if not), and that files know to be 'text' have mode 00644 (with a
669
    ## if not), and that files know to be 'text' have mode 00644 (with a
670
    ## warning if not).  We now only require that dirs and files have
670
    ## warning if not).  We now only require that dirs and files have
671
    ## mode >= 00700 and 00400, respectively, and try to fix
671
    ## mode >= 00700 and 00400, respectively, and try to fix
672
    ## insufficient permission in the INSTALL code (Unix only).
672
    ## insufficient permission in the INSTALL code (Unix only).
673
    ##
673
    ##
674
    ## In addition, we check whether files 'configure' and 'cleanup'
674
    ## In addition, we check whether files 'configure' and 'cleanup'
675
    ## exists in the top-level directory but are not executable, which
675
    ## exists in the top-level directory but are not executable, which
676
    ## is most likely not what was intended.
676
    ## is most likely not what was intended.
677
 
677
 
678
    if($R::Vars::OSTYPE eq "unix") {
678
    if($R::Vars::OSTYPE eq "unix") {
679
	$log->checking("for sufficient/correct file permissions");
679
	$log->checking("for sufficient/correct file permissions");
680
	my @bad_files = ();
680
	my @bad_files = ();
681
 
681
 
682
	## Phase A.  Directories at least 700, files at least 400.
682
	## Phase A.  Directories at least 700, files at least 400.
683
	sub find_wrong_perms_A {
683
	sub find_wrong_perms_A {
684
	    my $filename = $File::Find::name;
684
	    my $filename = $File::Find::name;
685
	    $filename =~ s/^\.[^\/]*\///;
685
	    $filename =~ s/^\.[^\/]*\///;
686
	    foreach my $p (@exclude_patterns) {
686
	    foreach my $p (@exclude_patterns) {
687
		## Unix only, so no special casing for Windows.
687
		## Unix only, so no special casing for Windows.
688
		return 0 if($filename =~ /$p/);
688
		return 0 if($filename =~ /$p/);
689
	    }
689
	    }
690
	    if(-d $_ && (((stat $_)[2] & 00700) < oct("700"))) {
690
	    if(-d $_ && (((stat $_)[2] & 00700) < oct("700"))) {
691
		push(@bad_files, $filename);
691
		push(@bad_files, $filename);
692
	    }
692
	    }
693
	    if(-f $_ && (((stat $_)[2] & 00400) < oct("400"))) {
693
	    if(-f $_ && (((stat $_)[2] & 00400) < oct("400"))) {
694
		push(@bad_files, $filename);
694
		push(@bad_files, $filename);
695
	    }
695
	    }
696
	}
696
	}
697
	if($in_bundle) {
697
	if($in_bundle) {
698
	    chdir(dirname($pkgdir)); # more portable than '..'?
698
	    chdir(dirname($pkgdir)); # more portable than '..'?
699
	    find(\&find_wrong_perms_A, $pkgname);
699
	    find(\&find_wrong_perms_A, $pkgname);
700
	    chdir($pkgname);
700
	    chdir($pkgname);
701
	}
701
	}
702
	else {
702
	else {
703
	    find(\&find_wrong_perms_A, ".");
703
	    find(\&find_wrong_perms_A, ".");
704
	}
704
	}
705
        if(scalar(@bad_files) > 0) {
705
        if(scalar(@bad_files) > 0) {
706
	    $log->error();
706
	    $log->error();
707
	    $log->print("Found the following files with " .
707
	    $log->print("Found the following files with " .
708
			"insufficient permissions:\n");
708
			"insufficient permissions:\n");
709
	    $log->print("  " . join("\n  ", @bad_files) . "\n");
709
	    $log->print("  " . join("\n  ", @bad_files) . "\n");
710
	    $log->print(wrap("", "",
710
	    $log->print(wrap("", "",
711
			     ("Permissions should be at least 700",
711
			     ("Permissions should be at least 700",
712
			      "for directories and 400 for files.\n",
712
			      "for directories and 400 for files.\n",
713
			      "Please fix permissions",
713
			      "Please fix permissions",
714
			      "and try again.\n")));
714
			      "and try again.\n")));
715
	    exit(1);
715
	    exit(1);
716
	}
716
	}
717
 
717
 
718
	## Phase B.  Top-level scripts 'configure' and 'cleanup' should
718
	## Phase B.  Top-level scripts 'configure' and 'cleanup' should
719
	## really be mode at least 500, or they will not be necessarily
719
	## really be mode at least 500, or they will not be necessarily
720
	## be used (or should we rather change *that*?)
720
	## be used (or should we rather change *that*?)
721
	@bad_files = ();
721
	@bad_files = ();
722
	foreach my $filename ("configure", "cleanup") {
722
	foreach my $filename ("configure", "cleanup") {
723
	    ## This is a bit silly ...
723
	    ## This is a bit silly ...
724
	    my $ignore = 0;
724
	    my $ignore = 0;
725
	    foreach my $p (@exclude_patterns) {
725
	    foreach my $p (@exclude_patterns) {
726
		if($filename =~ /$p/) {
726
		if($filename =~ /$p/) {
727
		    $ignore = 1;
727
		    $ignore = 1;
728
		    last;
728
		    last;
729
		}
729
		}
730
	    }
730
	    }
731
	    if(!$ignore
731
	    if(!$ignore
732
	       && (-f $filename)
732
	       && (-f $filename)
733
	       && (((stat $filename)[2] & 00500) < oct("500"))) {
733
	       && (((stat $filename)[2] & 00500) < oct("500"))) {
734
		push(@bad_files, $filename);
734
		push(@bad_files, $filename);
735
	    }
735
	    }
736
	}
736
	}
737
	if(scalar(@bad_files) > 0) {
737
	if(scalar(@bad_files) > 0) {
738
	    $log->warning();
738
	    $log->warning();
739
	    $log->print(wrap("", "",
739
	    $log->print(wrap("", "",
740
			     "The following files should most likely",
740
			     "The following files should most likely",
741
			     "be executable (for the owner):\n"));
741
			     "be executable (for the owner):\n"));
742
	    $log->print("  " . join("\n  ", @bad_files) . "\n");
742
	    $log->print("  " . join("\n  ", @bad_files) . "\n");
743
	    $log->print(wrap("", "",
743
	    $log->print(wrap("", "",
744
			     "Please fix permissions.\n"));
744
			     "Please fix permissions.\n"));
745
	}
745
	}
746
	else {
746
	else {
747
	    $log->result("OK");
747
	    $log->result("OK");
748
	}
748
	}
749
    }
749
    }
750
 
750
 
751
    ## Check DESCRIPTION meta-information.
751
    ## Check DESCRIPTION meta-information.
752
 
752
 
753
    ## If we just installed the package (via R CMD INSTALL), we already
753
    ## If we just installed the package (via R CMD INSTALL), we already
754
    ## validated most of the package DESCRIPTION metadata.  Otherwise,
754
    ## validated most of the package DESCRIPTION metadata.  Otherwise,
755
    ## let us be defensive about this ...
755
    ## let us be defensive about this ...
756
 
756
 
757
    my $full =
757
    my $full =
758
	!$opt_install || ($opt_install eq "skip") || $is_base_pkg;
758
	!$opt_install || ($opt_install eq "skip") || $is_base_pkg;
759
    &R::Utils::check_package_description($pkgdir, $pkgname, $log,
759
    &R::Utils::check_package_description($pkgdir, $pkgname, $log,
760
					 $in_bundle, $is_base_pkg,
760
					 $in_bundle, $is_base_pkg,
761
					 $full);
761
					 $full);
762
    
762
    
763
    ## Check package dependencies.
763
    ## Check package dependencies.
764
 
764
 
765
    ## Try figuring out whether the package dependencies can be resolved
765
    ## Try figuring out whether the package dependencies can be resolved
766
    ## at run time.  Ideally, the installation mechanism would do this,
766
    ## at run time.  Ideally, the installation mechanism would do this,
767
    ## and we also do not check versions ... also see whether vignette
767
    ## and we also do not check versions ... also see whether vignette
768
    ## and namespace package dependencies are recorded in DESCRIPTION.
768
    ## and namespace package dependencies are recorded in DESCRIPTION.
769
 
769
 
770
    ## <NOTE>
770
    ## <NOTE>
771
    ## When checking uninstalled base or bundle packages, there is no
771
    ## When checking uninstalled base or bundle packages, there is no
772
    ## DESCRIPTION file in the package source directory.  Hence, for
772
    ## DESCRIPTION file in the package source directory.  Hence, for
773
    ## simplicity, we only run this check on "installed" packages.  We
773
    ## simplicity, we only run this check on "installed" packages.  We
774
    ## could work around this, but checking uninstalled packages is a
774
    ## could work around this, but checking uninstalled packages is a
775
    ## bad thing anyway.
775
    ## bad thing anyway.
776
    ##
776
    ##
777
    ## Also, if --install=skip, bundles never get DESCRIPTION files
777
    ## Also, if --install=skip, bundles never get DESCRIPTION files
778
    ## made in the source dir which is what we are checking here.
778
    ## made in the source dir which is what we are checking here.
779
    ## </NOTE>
779
    ## </NOTE>
780
    if($opt_install) {
780
    if($opt_install) {
781
	$log->checking("package dependencies");
781
	$log->checking("package dependencies");
782
	## Everything listed in Depends or Suggests or Imports
782
	## Everything listed in Depends or Suggests or Imports
783
	## should be available for successfully running R CMD check.
783
	## should be available for successfully running R CMD check.
784
	## \VignetteDepends{} entries not "required" by the package code
784
	## \VignetteDepends{} entries not "required" by the package code
785
	## must be in Suggests.  Note also that some of us think that a
785
	## must be in Suggests.  Note also that some of us think that a
786
	## package vignette must require its own package, which OTOH is
786
	## package vignette must require its own package, which OTOH is
787
	## not required in the package DESCRIPTION file.
787
	## not required in the package DESCRIPTION file.
788
	## Namespace imports must really be in Depends.
788
	## Namespace imports must really be in Depends.
789
	my $Rcmd = "tools:::.check_package_depends(\"${pkgname}\")\n";
789
	my $Rcmd = "tools:::.check_package_depends(\"${pkgname}\")\n";
790
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
790
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
791
			 "R_DEFAULT_PACKAGES=NULL");
791
			 "R_DEFAULT_PACKAGES=NULL");
792
	@out = grep(!/^\>/, @out);
792
	@out = grep(!/^\>/, @out);
793
	if(scalar(@out) > 0) {
793
	if(scalar(@out) > 0) {
794
	    ## <FIXME>
794
	    ## <FIXME>
795
	    ## These should really all be errors ...
795
	    ## These should really all be errors ...
796
	    ## Change this for 2.1 at least, once stubs are fully gone.
796
	    ## Change this for 2.1 at least, once stubs are fully gone.
797
	    if(grep(/^Packages required but not available:/, @out)) {
797
	    if(grep(/^Packages required but not available:/, @out)) {
798
		$log->error();
798
		$log->error();
799
		$log->print(join("\n", @out) . "\n");
799
		$log->print(join("\n", @out) . "\n");
800
		$log->print(wrap("", "", @msg_DESCRIPTION));
800
		$log->print(wrap("", "", @msg_DESCRIPTION));
801
		exit(1);
801
		exit(1);
802
	    }
802
	    }
803
	    else {
803
	    else {
804
		$log->warning();
804
		$log->warning();
805
		$log->print(join("\n", @out) . "\n");
805
		$log->print(join("\n", @out) . "\n");
806
		$log->print(wrap("", "", @msg_DESCRIPTION));
806
		$log->print(wrap("", "", @msg_DESCRIPTION));
807
	    }
807
	    }
808
	    ## </FIXME>
808
	    ## </FIXME>
809
	}
809
	}
810
	else {
810
	else {
811
	    $log->result("OK");
811
	    $log->result("OK");
812
	}
812
	}
813
    }
813
    }
814
 
814
 
815
    ## Check index information.
815
    ## Check index information.
816
 
816
 
817
    $log->checking("index information");
817
    $log->checking("index information");
818
    my @msg_index = ("See the information on INDEX files and package",
818
    my @msg_index = ("See the information on INDEX files and package",
819
		     "subdirectories in section 'Creating R packages'",
819
		     "subdirectories in section 'Creating R packages'",
820
		     "of the 'Writing R Extensions' manual.\n");
820
		     "of the 'Writing R Extensions' manual.\n");
821
    my $any = 0;
821
    my $any = 0;
822
    if(-z "INDEX") {
822
    if(-z "INDEX") {
823
	## If there is an empty INDEX file, we get no information about
823
	## If there is an empty INDEX file, we get no information about
824
	## the package contents ...
824
	## the package contents ...
825
	$any++;
825
	$any++;
826
	$log->warning();
826
	$log->warning();
827
	$log->print("Empty file 'INDEX'.\n");
827
	$log->print("Empty file 'INDEX'.\n");
828
    }
828
    }
829
    if((-d "demo")
829
    if((-d "demo")
830
       && &list_files_with_type("demo", "demo")) {
830
       && &list_files_with_type("demo", "demo")) {
831
	my $index = &file_path("demo", "00Index");
831
	my $index = &file_path("demo", "00Index");
832
	if(!(-s $index)) {
832
	if(!(-s $index)) {
833
	    $log->warning() unless($any);
833
	    $log->warning() unless($any);
834
	    $any++;
834
	    $any++;
835
	    $log->print("Empty or missing file '$index'.\n");
835
	    $log->print("Empty or missing file '$index'.\n");
836
	}
836
	}
837
	else {
837
	else {
838
	    my $dir = "demo";
838
	    my $dir = "demo";
839
	    my $Rcmd = "options(warn=1)\ntools:::.check_demo_index(\"$dir\")\n";
839
	    my $Rcmd = "options(warn=1)\ntools:::.check_demo_index(\"$dir\")\n";
840
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
840
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
841
			     "R_DEFAULT_PACKAGES=NULL");
841
			     "R_DEFAULT_PACKAGES=NULL");
842
	    @out = grep(!/^\>/, @out);
842
	    @out = grep(!/^\>/, @out);
843
	    if(scalar(@out) > 0) {
843
	    if(scalar(@out) > 0) {
844
		$log->warning() unless($any);
844
		$log->warning() unless($any);
845
		$any++;
845
		$any++;
846
		$log->print(join("\n", @out) . "\n");
846
		$log->print(join("\n", @out) . "\n");
847
	    }
847
	    }
848
	}
848
	}
849
    }
849
    }
850
    if((-d &file_path("inst", "doc"))
850
    if((-d &file_path("inst", "doc"))
851
       && &list_files_with_type(&file_path("inst", "doc"),
851
       && &list_files_with_type(&file_path("inst", "doc"),
852
				"vignette")) {
852
				"vignette")) {
853
	my $dir = &file_path("inst", "doc");
853
	my $dir = &file_path("inst", "doc");
854
	my $Rcmd = "options(warn=1)\ntools:::.check_vignette_index(\"$dir\")\n";
854
	my $Rcmd = "options(warn=1)\ntools:::.check_vignette_index(\"$dir\")\n";
855
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
855
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
856
			 "R_DEFAULT_PACKAGES=NULL");
856
			 "R_DEFAULT_PACKAGES=NULL");
857
	@out = grep(!/^\>/, @out);
857
	@out = grep(!/^\>/, @out);
858
	if(scalar(@out) > 0) {
858
	if(scalar(@out) > 0) {
859
	    $log->warning() unless($any);
859
	    $log->warning() unless($any);
860
	    $any++;
860
	    $any++;
861
	    $log->print(join("\n", @out) . "\n");
861
	    $log->print(join("\n", @out) . "\n");
862
	}
862
	}
863
    }
863
    }
864
    if($any) {
864
    if($any) {
865
	$log->print(wrap("", "", @msg_index));
865
	$log->print(wrap("", "", @msg_index));
866
    }
866
    }
867
    else {
867
    else {
868
	$log->result("OK");
868
	$log->result("OK");
869
    }
869
    }
870
 
870
 
871
    ## Check package subdirectories.
871
    ## Check package subdirectories.
872
 
872
 
873
    $log->checking("package subdirectories");
873
    $log->checking("package subdirectories");
874
    my $any;
874
    my $any;
875
    if($R_check_subdirs_nocase) {
875
    if($R_check_subdirs_nocase) {
876
	## Argh.  We often get submissions where 'R' comes out as 'r',
876
	## Argh.  We often get submissions where 'R' comes out as 'r',
877
	## or 'man' comes out as 'MAN'.  Maybe we should warn about this
877
	## or 'man' comes out as 'MAN'.  Maybe we should warn about this
878
	## unconditionally ...
878
	## unconditionally ...
879
	if((-d "r")) {
879
	if((-d "r")) {
880
	    $log->warning() unless $any;
880
	    $log->warning() unless $any;
881
	    $any++;
881
	    $any++;
882
	    $log->print("Found subdirectory 'r'.\n");
882
	    $log->print("Found subdirectory 'r'.\n");
883
	    $log->print("Most likely, this should be 'R'.\n")
883
	    $log->print("Most likely, this should be 'R'.\n")
884
	}
884
	}
885
	if((-d "MAN")) {
885
	if((-d "MAN")) {
886
	    $log->warning() unless $any;
886
	    $log->warning() unless $any;
887
	    $any++;
887
	    $any++;
888
	    $log->print("Found subdirectory 'MAN'.\n");
888
	    $log->print("Found subdirectory 'MAN'.\n");
889
	    $log->print("Most likely, this should be 'man'.\n")
889
	    $log->print("Most likely, this should be 'man'.\n")
890
	}
890
	}
891
    }
891
    }
892
    if((-d "data") || (-d "demo") || (-d "src") || (-d "inst")) {
892
    if((-d "data") || (-d "demo") || (-d "src") || (-d "inst")) {
893
	## Subdirectory 'data' without data sets?
893
	## Subdirectory 'data' without data sets?
894
	if((-d "data") && !&list_files_with_type("data", "data")) {
894
	if((-d "data") && !&list_files_with_type("data", "data")) {
895
	    $log->warning() unless $any;
895
	    $log->warning() unless $any;
896
	    $any++;
896
	    $any++;
897
	    $log->print("Subdirectory 'data' contains no data sets.\n");
897
	    $log->print("Subdirectory 'data' contains no data sets.\n");
898
	}
898
	}
899
	## Subdirectory 'demo' without demos?
899
	## Subdirectory 'demo' without demos?
900
	if((-d "demo") && !&list_files_with_type("demo", "demo")) {
900
	if((-d "demo") && !&list_files_with_type("demo", "demo")) {
901
	    $log->warning() unless $any;
901
	    $log->warning() unless $any;
902
	    $any++;
902
	    $any++;
903
	    $log->print("Subdirectory 'demo' contains no demos.\n");
903
	    $log->print("Subdirectory 'demo' contains no demos.\n");
904
	}
904
	}
905
	## Subdirectory 'src' without sources?
905
	## Subdirectory 'src' without sources?
906
	## <NOTE>
906
	## <NOTE>
907
	## If there is a Makefile (or a Makefile.win), we cannot assume
907
	## If there is a Makefile (or a Makefile.win), we cannot assume
908
	## that source files have the predefined extensions.
908
	## that source files have the predefined extensions.
909
	## </NOTE>
909
	## </NOTE>
910
	if((-d "src")
910
	if((-d "src")
911
	   && !(&list_files_with_exts("src", "([Ccf]|cc|cpp)")
911
	   && !(&list_files_with_exts("src", "([Ccf]|cc|cpp)")
912
		|| (-f &file_path("src", "Makefile"))
912
		|| (-f &file_path("src", "Makefile"))
913
		|| (-f &file_path("src", "Makefile.win")))) {
913
		|| (-f &file_path("src", "Makefile.win")))) {
914
	    $log->warning() unless $any;
914
	    $log->warning() unless $any;
915
	    $any++;
915
	    $any++;
916
	    $log->print("Subdirectory 'src' contains no source files.\n");
916
	    $log->print("Subdirectory 'src' contains no source files.\n");
917
	}
917
	}
918
	## Do subdirectories of 'inst' interfere with R package system
918
	## Do subdirectories of 'inst' interfere with R package system
919
	## subdirectories?
919
	## subdirectories?
920
	if((-d "inst")) {
920
	if((-d "inst")) {
921
	    my @R_system_subdirs =
921
	    my @R_system_subdirs =
922
		("Meta", "R", "data", "demo", "exec", "libs",
922
		("Meta", "R", "data", "demo", "exec", "libs",
923
		 "man", "help", "html", "latex", "R-ex");
923
		 "man", "help", "html", "latex", "R-ex");
924
	    my @bad_dirs = ();
924
	    my @bad_dirs = ();
925
	    foreach my $dir (@R_system_subdirs) {
925
	    foreach my $dir (@R_system_subdirs) {
926
		push(@bad_dirs, $dir)
926
		push(@bad_dirs, $dir)
927
		  if((-d &file_path("inst", $dir))
927
		  if((-d &file_path("inst", $dir))
928
		     && &list_files(file_path("inst", $dir)));
928
		     && &list_files(file_path("inst", $dir)));
929
	    }
929
	    }
930
	    if(scalar(@bad_dirs) > 0) {
930
	    if(scalar(@bad_dirs) > 0) {
931
		$log->warning() unless $any;
931
		$log->warning() unless $any;
932
		$any++;
932
		$any++;
933
		$log->print(wrap("", "",
933
		$log->print(wrap("", "",
934
				 ("Found the following non-empty",
934
				 ("Found the following non-empty",
935
				  "subdirectories of 'inst' also",
935
				  "subdirectories of 'inst' also",
936
				  "used by R:\n")));
936
				  "used by R:\n")));
937
		$log->print("  " . join(" ", @bad_dirs) . "\n");
937
		$log->print("  " . join(" ", @bad_dirs) . "\n");
938
		$log->print(wrap("", "",
938
		$log->print(wrap("", "",
939
				 ("It is recommended not to interfere",
939
				 ("It is recommended not to interfere",
940
				  "with package subdirectories",
940
				  "with package subdirectories",
941
				  "used by R.\n")));
941
				  "used by R.\n")));
942
	    }
942
	    }
943
	}
943
	}
944
    }
944
    }
945
    $log->result("OK") unless $any;
945
    $log->result("OK") unless $any;
946
 
946
 
947
    ## Check R code for syntax errors.
947
    ## Check R code for syntax errors.
948
 
948
 
949
    if(!$is_base_pkg && (-d "R")) {
949
    if(!$is_base_pkg && (-d "R")) {
950
	$log->checking("R files for syntax errors");
950
	$log->checking("R files for syntax errors");
951
	## <NOTE>
951
	## <NOTE>
952
	## We could/should really check *all* OS specific subdirs here.
952
	## We could/should really check *all* OS specific subdirs here.
953
	my @R_files = &list_files_with_type("R", "code");
953
	my @R_files = &list_files_with_type("R", "code");
954
	## </NOTE>
954
	## </NOTE>
955
	my $Rcmd = "RFiles <- c(\"";
955
	my $Rcmd = "RFiles <- c(\"";
956
	$Rcmd .= join("\",\n\"", @R_files) . "\")\n";
956
	$Rcmd .= join("\",\n\"", @R_files) . "\")\n";
957
	$Rcmd .= "for(f in RFiles)\n";
957
	$Rcmd .= "for(f in RFiles)\n";
958
	$Rcmd .= "if(inherits(try(parse(f)), \"try-error\")) stop(f)\n";
958
	$Rcmd .= "if(inherits(try(parse(f)), \"try-error\")) stop(f)\n";
959
        my @out = R_runR($Rcmd, "${R_opts} --quiet");
959
        my @out = R_runR($Rcmd, "${R_opts} --quiet");
960
	@out = grep(/^Error:/, @out);
960
	@out = grep(/^Error:/, @out);
961
	if(scalar(@out) > 0) {
961
	if(scalar(@out) > 0) {
962
	    my $Rfile = $out[0];
962
	    my $Rfile = $out[0];
963
	    $Rfile =~ s/^Error: *//;
963
	    $Rfile =~ s/^Error: *//;
964
	    $log->error();
964
	    $log->error();
965
	    $log->print("Syntax error in file " . $Rfile . "\n");
965
	    $log->print("Syntax error in file " . $Rfile . "\n");
966
	    exit(1);
966
	    exit(1);
967
	}
967
	}
968
	else {
968
	else {
969
	    $log->result("OK");
969
	    $log->result("OK");
970
	}
970
	}
971
    }
971
    }
972
 
972
 
973
    ## Check usage of library.dynam (if any).
973
    ## Check usage of library.dynam (if any).
974
 
974
 
975
    if(!$is_base_pkg && (-d "R")) {
975
    if(!$is_base_pkg && (-d "R")) {
976
	$log->checking("R files for library.dynam");
976
	$log->checking("R files for library.dynam");
977
	my @R_files;
977
	my @R_files;
978
	if($opt_install) {
978
	if($opt_install) {
979
	    ## Only need to check the installed file (if installed).
979
	    ## Only need to check the installed file (if installed).
980
	    @R_files = (&file_path($library, $pkgname, "R", $pkgname));
980
	    @R_files = (&file_path($library, $pkgname, "R", $pkgname));
981
	}
981
	}
982
	else {
982
	else {
983
	    ## Otherwise (if the package was not installed), we need to
983
	    ## Otherwise (if the package was not installed), we need to
984
	    ## check all R code files.
984
	    ## check all R code files.
985
	    ## <NOTE>
985
	    ## <NOTE>
986
	    ## We could/should really check all OS specific subdirs here.
986
	    ## We could/should really check all OS specific subdirs here.
987
	    @R_files = &list_files_with_type("R", "code");
987
	    @R_files = &list_files_with_type("R", "code");
988
	    ## </NOTE>
988
	    ## </NOTE>
989
	}
989
	}
990
	my $any = 0;
990
	my $any = 0;
991
	my $ext;
991
	my $ext;
992
	foreach my $file (@R_files) {
992
	foreach my $file (@R_files) {
993
	    last if $any;
993
	    last if $any;
994
	    open(FILE, "< $file")
994
	    open(FILE, "< $file")
995
	      or die "Error: cannot open file '$file' for reading\n";
995
	      or die "Error: cannot open file '$file' for reading\n";
996
	    while(<FILE>) {
996
	    while(<FILE>) {
997
		if(/library.dynam\(\"(.*?)\"/o) {
997
		if(/library.dynam\(\"(.*?)\"/o) {
998
		    my $arg = $1;
998
		    my $arg = $1;
999
		    if($arg =~ /\.(so|sl|dll)$/) {
999
		    if($arg =~ /\.(so|sl|dll)$/) {
1000
			$ext = $1;
1000
			$ext = $1;
1001
			$any++;
1001
			$any++;
1002
			last;
1002
			last;
1003
		    }
1003
		    }
1004
		}
1004
		}
1005
	    }
1005
	    }
1006
	    close(FILE);
1006
	    close(FILE);
1007
	}
1007
	}
1008
	if($any == 0) {
1008
	if($any == 0) {
1009
	    $log->result("OK");
1009
	    $log->result("OK");
1010
	}
1010
	}
1011
	else {
1011
	else {
1012
	    $log->error();
1012
	    $log->error();
1013
	    $log->print("library.dynam() used with extension '.$ext'.\n");
1013
	    $log->print("library.dynam() used with extension '.$ext'.\n");
1014
	    $log->print(wrap("", "",
1014
	    $log->print(wrap("", "",
1015
			     ("The system-specific extension for",
1015
			     ("The system-specific extension for",
1016
			      "shared libraries should not be added.\n",
1016
			      "shared libraries should not be added.\n",
1017
			      "See ?library.dynam\n")));
1017
			      "See ?library.dynam\n")));
1018
	    exit(1);
1018
	    exit(1);
1019
	}
1019
	}
1020
    }
1020
    }
1021
 
1021
 
1022
    ## Check whether methods have all arguments of the corresponding
1022
    ## Check whether methods have all arguments of the corresponding
1023
    ## generic.
1023
    ## generic.
1024
 
1024
 
1025
    if(-d "R") {
1025
    if(-d "R") {
1026
	$log->checking("S3 generic/method consistency");
1026
	$log->checking("S3 generic/method consistency");
1027
 
1027
 
1028
	my @msg_S3_methods =
1028
	my @msg_S3_methods =
1029
	  ("See section 'Generic functions and methods'",
1029
	  ("See section 'Generic functions and methods'",
1030
	   "of the 'Writing R Extensions' manual.\n");
1030
	   "of the 'Writing R Extensions' manual.\n");
1031
 
1031
 
1032
	my $Rcmd = "options(warn=1)\n";
1032
	my $Rcmd = "options(warn=1)\n";
1033
	$Rcmd .= "options(expressions=1000)\n";
1033
	$Rcmd .= "options(expressions=1000)\n";
1034
	if($opt_install) {
1034
	if($opt_install) {
1035
	    $Rcmd .= "tools::checkS3methods(package = \"${pkgname}\")\n";
1035
	    $Rcmd .= "tools::checkS3methods(package = \"${pkgname}\")\n";
1036
	}
1036
	}
1037
        else {
1037
        else {
1038
	    $Rcmd .= "tools::checkS3methods(dir = \"${pkgdir}\")\n";
1038
	    $Rcmd .= "tools::checkS3methods(dir = \"${pkgdir}\")\n";
1039
	}
1039
	}
1040
 
1040
 
1041
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1041
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1042
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1042
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1043
	@out = grep(!/^\>/, @out);
1043
	@out = grep(!/^\>/, @out);
1044
	if(scalar(@out) > 0) {
1044
	if(scalar(@out) > 0) {
1045
	    $log->warning();
1045
	    $log->warning();
1046
	    $log->print(join("\n", @out) . "\n");
1046
	    $log->print(join("\n", @out) . "\n");
1047
	    $log->print(wrap("", "", @msg_S3_methods));
1047
	    $log->print(wrap("", "", @msg_S3_methods));
1048
	}
1048
	}
1049
	else {
1049
	else {
1050
	    $log->result("OK");
1050
	    $log->result("OK");
1051
	}
1051
	}
1052
    }
1052
    }
1053
 
1053
 
1054
    ## Check whether replacement functions have their final argument
1054
    ## Check whether replacement functions have their final argument
1055
    ## named 'value'.
1055
    ## named 'value'.
1056
 
1056
 
1057
    if(-d "R") {
1057
    if(-d "R") {
1058
	$log->checking("replacement functions");
1058
	$log->checking("replacement functions");
1059
 
1059
 
1060
	my @msg_replace_funs =
1060
	my @msg_replace_funs =
1061
	  ("In R, the argument of a replacement function",
1061
	  ("In R, the argument of a replacement function",
1062
	   "which corresponds to the right hand side",
1062
	   "which corresponds to the right hand side",
1063
	   "must be named 'value'.\n");
1063
	   "must be named 'value'.\n");
1064
 
1064
 
1065
	my $Rcmd = "options(warn=1)\n";
1065
	my $Rcmd = "options(warn=1)\n";
1066
	if($opt_install) {
1066
	if($opt_install) {
1067
	    $Rcmd .= "tools::checkReplaceFuns(package = \"${pkgname}\")\n";
1067
	    $Rcmd .= "tools::checkReplaceFuns(package = \"${pkgname}\")\n";
1068
	}
1068
	}
1069
	else {
1069
	else {
1070
	    $Rcmd .= "tools::checkReplaceFuns(dir = \"${pkgdir}\")\n";
1070
	    $Rcmd .= "tools::checkReplaceFuns(dir = \"${pkgdir}\")\n";
1071
	}
1071
	}
1072
 
1072
 
1073
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1073
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1074
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1074
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1075
        @out = grep(!/^\>/, @out);
1075
        @out = grep(!/^\>/, @out);
1076
	if(scalar(@out) > 0) {
1076
	if(scalar(@out) > 0) {
1077
	    ## <NOTE>
1077
	    ## <NOTE>
1078
	    ## We really want to stop if we find offending replacement
1078
	    ## We really want to stop if we find offending replacement
1079
	    ## functions.  But we cannot use error() because output may
1079
	    ## functions.  But we cannot use error() because output may
1080
	    ## contain warnings ...
1080
	    ## contain warnings ...
1081
	    $log->warning();
1081
	    $log->warning();
1082
	    ## </NOTE>
1082
	    ## </NOTE>
1083
	    $log->print(join("\n", @out) . "\n");
1083
	    $log->print(join("\n", @out) . "\n");
1084
	    $log->print(wrap("", "", @msg_replace_funs));
1084
	    $log->print(wrap("", "", @msg_replace_funs));
1085
	}
1085
	}
1086
	else {
1086
	else {
1087
	    $log->result("OK");
1087
	    $log->result("OK");
1088
	}
1088
	}
1089
    }
1089
    }
1090
 
1090
 
1091
    ## Check foreign function calls.
1091
    ## Check foreign function calls.
1092
 
1092
 
1093
    if($opt_ff_calls && (-d "R")) {
1093
    if($opt_ff_calls && (-d "R")) {
1094
	$log->checking("foreign function calls");
1094
	$log->checking("foreign function calls");
1095
 
1095
 
1096
	my @msg_ff_calls =
1096
	my @msg_ff_calls =
1097
	  ("See section 'System and foreign language interfaces'",
1097
	  ("See section 'System and foreign language interfaces'",
1098
	   "of the 'Writing R Extensions' manual.\n");
1098
	   "of the 'Writing R Extensions' manual.\n");
1099
 
1099
 
1100
	my $Rcmd = "options(warn=1)\n";
1100
	my $Rcmd = "options(warn=1)\n";
1101
	if($opt_install) {
1101
	if($opt_install) {
1102
	    $Rcmd .= "tools::checkFF(package = \"${pkgname}\")\n";
1102
	    $Rcmd .= "tools::checkFF(package = \"${pkgname}\")\n";
1103
	}
1103
	}
1104
        else {
1104
        else {
1105
	    $Rcmd .= "tools::checkFF(dir = \"${pkgdir}\")\n";
1105
	    $Rcmd .= "tools::checkFF(dir = \"${pkgdir}\")\n";
1106
	}
1106
	}
1107
 
1107
 
1108
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1108
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1109
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1109
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1110
	@out = grep(!/^\>/, @out);
1110
	@out = grep(!/^\>/, @out);
1111
	if(scalar(@out) > 0) {
1111
	if(scalar(@out) > 0) {
1112
	    $log->warning();
1112
	    $log->warning();
1113
	    $log->print(join("\n", @out) . "\n");
1113
	    $log->print(join("\n", @out) . "\n");
1114
	    $log->print(wrap("", "", @msg_ff_calls));
1114
	    $log->print(wrap("", "", @msg_ff_calls));
1115
	}
1115
	}
1116
	else {
1116
	else {
1117
	    $log->result("OK");
1117
	    $log->result("OK");
1118
	}
1118
	}
1119
    }
1119
    }
1120
 
1120
 
1121
    ## Check R documentation files.
1121
    ## Check R documentation files.
1122
 
1122
 
1123
    my @msg_writing_Rd
1123
    my @msg_writing_Rd
1124
      = ("See chapter 'Writing R documentation files'",
1124
      = ("See chapter 'Writing R documentation files'",
1125
	 "in manual 'Writing R Extensions'.\n");
1125
	 "in manual 'Writing R Extensions'.\n");
1126
 
1126
 
1127
    if(-d "man") {
1127
    if(-d "man") {
1128
	$log->checking("Rd files");
1128
	$log->checking("Rd files");
1129
 
1129
 
1130
	my $Rcmd = "options(warn=1)\ntools:::check_Rd_files_in_man_dir(\"man\")\n";
1130
	my $Rcmd = "options(warn=1)\ntools:::check_Rd_files_in_man_dir(\"man\")\n";
1131
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
1131
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
1132
			 "R_DEFAULT_PACKAGES=NULL");
1132
			 "R_DEFAULT_PACKAGES=NULL");
1133
	@out = grep(!/^\>/, @out);
1133
	@out = grep(!/^\>/, @out);
1134
	if(scalar(@out) > 0) {
1134
	if(scalar(@out) > 0) {
1135
	    ## Output may indicate warnings or errors ...
1135
	    ## Output may indicate warnings or errors ...
1136
	    if(grep(/^Rd files with (syntax errors|missing or empty)/,
1136
	    if(grep(/^Rd files with (syntax errors|missing or empty)/,
1137
		    @out)) {
1137
		    @out)) {
1138
		$log->error();
1138
		$log->error();
1139
		$log->print(join("\n", @out) . "\n");
1139
		$log->print(join("\n", @out) . "\n");
1140
		$log->print(wrap("", "", @msg_writing_Rd));
1140
		$log->print(wrap("", "", @msg_writing_Rd));
1141
		exit(1);
1141
		exit(1);
1142
	    }
1142
	    }
1143
	    else {
1143
	    else {
1144
		$log->warning();
1144
		$log->warning();
1145
		$log->print(join("\n", @out) . "\n");
1145
		$log->print(join("\n", @out) . "\n");
1146
		$log->print(wrap("", "", @msg_writing_Rd));
1146
		$log->print(wrap("", "", @msg_writing_Rd));
1147
	    }
1147
	    }
1148
	}
1148
	}
1149
	else {
1149
	else {
1150
	    $log->result("OK");
1150
	    $log->result("OK");
1151
	}
1151
	}
1152
    }
1152
    }
1153
 
1153
 
1154
    ## Check for missing documentation entries.
1154
    ## Check for missing documentation entries.
1155
 
1155
 
1156
    if(((-d "R") || (-d "data"))) {
1156
    if(((-d "R") || (-d "data"))) {
1157
	$log->checking("for missing documentation entries");
1157
	$log->checking("for missing documentation entries");
1158
 
1158
 
1159
	my $Rcmd= "options(warn=1)\n";
1159
	my $Rcmd= "options(warn=1)\n";
1160
	if($opt_install) {
1160
	if($opt_install) {
1161
	    $Rcmd .= "tools::undoc(package = \"${pkgname}\")\n";
1161
	    $Rcmd .= "tools::undoc(package = \"${pkgname}\")\n";
1162
	}
1162
	}
1163
	else {
1163
	else {
1164
	    $Rcmd .= "tools::undoc(dir = \"${pkgdir}\")\n";
1164
	    $Rcmd .= "tools::undoc(dir = \"${pkgdir}\")\n";
1165
	}
1165
	}
1166
 
1166
 
1167
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1167
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1168
                         "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1168
                         "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1169
	my @err = grep(/^Error/, @out);
1169
	my @err = grep(/^Error/, @out);
1170
	@out = grep(!/^\>/, @out);
1170
	@out = grep(!/^\>/, @out);
1171
	if(scalar(@err) > 0) {
1171
	if(scalar(@err) > 0) {
1172
	    $log->error();
1172
	    $log->error();
1173
	    $log->print(join("\n", @err) . "\n");
1173
	    $log->print(join("\n", @err) . "\n");
1174
	    exit(1);
1174
	    exit(1);
1175
	}
1175
	}
1176
	elsif(scalar(@out) > 0) {
1176
	elsif(scalar(@out) > 0) {
1177
	    $log->warning();
1177
	    $log->warning();
1178
	    $log->print(join("\n", @out) . "\n");
1178
	    $log->print(join("\n", @out) . "\n");
1179
	    my $details;
1179
	    my $details;
1180
	    $details = " (including S4 classes and methods)"
1180
	    $details = " (including S4 classes and methods)"
1181
	      if(grep(/^Undocumented S4/, @out));
1181
	      if(grep(/^Undocumented S4/, @out));
1182
	    $log->print(wrap("", "",
1182
	    $log->print(wrap("", "",
1183
			     ("All user-level objects",
1183
			     ("All user-level objects",
1184
			      "in a package${details} should",
1184
			      "in a package${details} should",
1185
			      "have documentation entries.\n")));
1185
			      "have documentation entries.\n")));
1186
	    $log->print(wrap("", "", @msg_writing_Rd));
1186
	    $log->print(wrap("", "", @msg_writing_Rd));
1187
	}
1187
	}
1188
	else {
1188
	else {
1189
	    $log->result("OK");
1189
	    $log->result("OK");
1190
	}
1190
	}
1191
    }
1191
    }
1192
 
1192
 
1193
    ## Check for code/documentation mismatches.
1193
    ## Check for code/documentation mismatches.
1194
 
1194
 
1195
    if($opt_codoc && (-d "man")) {
1195
    if($opt_codoc && (-d "man")) {
1196
	$log->checking("for code/documentation mismatches");
1196
	$log->checking("for code/documentation mismatches");
1197
 
1197
 
1198
	my $any = 0;
1198
	my $any = 0;
1199
 
1199
 
1200
	## Check for code/documentation mismatches in functions.
1200
	## Check for code/documentation mismatches in functions.
1201
	if(-d "R") {
1201
	if(-d "R") {
1202
	    my $Rcmd = "options(warn=1)\n";
1202
	    my $Rcmd = "options(warn=1)\n";
1203
	    if($opt_install) {
1203
	    if($opt_install) {
1204
		$Rcmd .= "tools::codoc(package = \"${pkgname}\")\n";
1204
		$Rcmd .= "tools::codoc(package = \"${pkgname}\")\n";
1205
	    }
1205
	    }
1206
	    else {
1206
	    else {
1207
		$Rcmd .= "tools::codoc(dir = \"${pkgdir}\")\n";
1207
		$Rcmd .= "tools::codoc(dir = \"${pkgdir}\")\n";
1208
	    }
1208
	    }
1209
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
1209
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
1210
			     "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1210
			     "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1211
 
1211
 
1212
	    @out = grep(!/^\>/, @out);
1212
	    @out = grep(!/^\>/, @out);
1213
	    if(scalar(@out) > 0) {
1213
	    if(scalar(@out) > 0) {
1214
		$any++;
1214
		$any++;
1215
		$log->warning();
1215
		$log->warning();
1216
		$log->print(join("\n", @out) . "\n");
1216
		$log->print(join("\n", @out) . "\n");
1217
	    }
1217
	    }
1218
	}
1218
	}
1219
 
1219
 
1220
	## Check for code/documentation mismatches in data sets.
1220
	## Check for code/documentation mismatches in data sets.
1221
	if($opt_install) {
1221
	if($opt_install) {
1222
	    my $Rcmd = "options(warn=1)\ntools::codocData(package = \"${pkgname}\")\n";
1222
	    my $Rcmd = "options(warn=1)\ntools::codocData(package = \"${pkgname}\")\n";
1223
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
1223
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
1224
			     "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1224
			     "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1225
	    @out = grep(!/^\>/, @out);
1225
	    @out = grep(!/^\>/, @out);
1226
	    if(scalar(@out) > 0) {
1226
	    if(scalar(@out) > 0) {
1227
		$log->warning() unless($any);
1227
		$log->warning() unless($any);
1228
		$any++;
1228
		$any++;
1229
		$log->print(join("\n", @out) . "\n");
1229
		$log->print(join("\n", @out) . "\n");
1230
	    }
1230
	    }
1231
	}
1231
	}
1232
 
1232
 
1233
	## Check for code/documentation mismatches in S4 classes.
1233
	## Check for code/documentation mismatches in S4 classes.
1234
	if($opt_install && (-d "R")) {
1234
	if($opt_install && (-d "R")) {
1235
	    my $Rcmd = "options(warn=1)\ntools::codocClasses(package = \"${pkgname}\")\n";
1235
	    my $Rcmd = "options(warn=1)\ntools::codocClasses(package = \"${pkgname}\")\n";
1236
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
1236
	    my @out = R_runR($Rcmd, "${R_opts} --quiet",
1237
			     "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1237
			     "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1238
	    @out = grep(!/^\>/, @out);
1238
	    @out = grep(!/^\>/, @out);
1239
	    if(scalar(@out) > 0) {
1239
	    if(scalar(@out) > 0) {
1240
		$log->warning() unless($any);
1240
		$log->warning() unless($any);
1241
		$any++;
1241
		$any++;
1242
		$log->print(join("\n", @out) . "\n");
1242
		$log->print(join("\n", @out) . "\n");
1243
	    }
1243
	    }
1244
	}
1244
	}
1245
 
1245
 
1246
	$log->result("OK") unless($any);
1246
	$log->result("OK") unless($any);
1247
 
1247
 
1248
    }
1248
    }
1249
 
1249
 
1250
    ## Check Rd files, for consistency of \usage with \arguments (are
1250
    ## Check Rd files, for consistency of \usage with \arguments (are
1251
    ## all arguments shown in \usage documented in \arguments?) and
1251
    ## all arguments shown in \usage documented in \arguments?) and
1252
    ## aliases (do all functions shown in \usage have an alias?)
1252
    ## aliases (do all functions shown in \usage have an alias?)
1253
 
1253
 
1254
    if(-d "man") {
1254
    if(-d "man") {
1255
	$log->checking("Rd \\usage sections");
1255
	$log->checking("Rd \\usage sections");
1256
 
1256
 
1257
	my @msg_doc_files =
1257
	my @msg_doc_files =
1258
	  ("Functions with \\usage entries",
1258
	  ("Functions with \\usage entries",
1259
	   "need to have the appropriate \\alias entries,",
1259
	   "need to have the appropriate \\alias entries,",
1260
	   "and all their arguments documented.\n");
1260
	   "and all their arguments documented.\n",
-
 
1261
	   "The \\usage entries must correspond to syntactically",
-
 
1262
	   "valid R code.\n");
1261
 
1263
 
1262
	my $Rcmd = "options(warn=1)\n";
1264
	my $Rcmd = "options(warn=1)\n";
1263
	if($opt_install) {
1265
	if($opt_install) {
1264
	    $Rcmd .= "tools::checkDocFiles(package = \"${pkgname}\")\n";
1266
	    $Rcmd .= "tools::checkDocFiles(package = \"${pkgname}\")\n";
1265
	}
1267
	}
1266
	else {
1268
	else {
1267
	    $Rcmd .= "tools::checkDocFiles(dir = \"${pkgdir}\")\n";
1269
	    $Rcmd .= "tools::checkDocFiles(dir = \"${pkgdir}\")\n";
1268
	}
1270
	}
1269
 
1271
 
1270
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1272
        my @out = R_runR($Rcmd, "${R_opts} --quiet",
1271
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1273
			 "R_DEFAULT_PACKAGES='utils,grDevices,graphics,stats'");
1272
	@out = grep(!/^\>/, @out);
1274
	@out = grep(!/^\>/, @out);
1273
	if(scalar(@out) > 0) {
1275
	if(scalar(@out) > 0) {
1274
	    $log->warning();
1276
	    $log->warning();
1275
	    $log->print(join("\n", @out) . "\n");
1277
	    $log->print(join("\n", @out) . "\n");
1276
	    $log->print(wrap("", "", @msg_doc_files));
1278
	    $log->print(wrap("", "", @msg_doc_files));
1277
	    $log->print(wrap("", "", @msg_writing_Rd));
1279
	    $log->print(wrap("", "", @msg_writing_Rd));
1278
	}
1280
	}
1279
	else {
1281
	else {
1280
	    $log->result("OK");
1282
	    $log->result("OK");
1281
	}
1283
	}
1282
    }
1284
    }
1283
 
1285
 
1284
    ## Check C/C++/Fortran sources/headers for CRLF line endings.
1286
    ## Check C/C++/Fortran sources/headers for CRLF line endings.
1285
 
1287
 
1286
    ## <FIXME>
1288
    ## <FIXME>
1287
    ## Does ISO C really require LF line endings?  (Reference?)
1289
    ## Does ISO C really require LF line endings?  (Reference?)
1288
    ## We definitely know that some versions of Solaris cc and f77
1290
    ## We definitely know that some versions of Solaris cc and f77
1289
    ## will not accept CRLF or CR line endings.
1291
    ## will not accept CRLF or CR line endings.
1290
    ## Note that we currently only check the CRLF part.
1292
    ## Note that we currently only check the CRLF part.
1291
    ## </FIXME>
1293
    ## </FIXME>
1292
 
1294
 
1293
    if(!$is_base_pkg && (-d "src")) {
1295
    if(!$is_base_pkg && (-d "src")) {
1294
	$log->checking("for CRLF line endings in C/C++/Fortran sources/headers");
1296
	$log->checking("for CRLF line endings in C/C++/Fortran sources/headers");
1295
	my @src_files = &list_files_with_exts("src", "(c|h|f|cc|cpp)");
1297
	my @src_files = &list_files_with_exts("src", "(c|h|f|cc|cpp)");
1296
	my @bad_files = ();
1298
	my @bad_files = ();
1297
	foreach my $file (@src_files) {
1299
	foreach my $file (@src_files) {
1298
	    open(FILE, "< $file")
1300
	    open(FILE, "< $file")
1299
	      or die "Error: cannot open '$file' for reading\n";
1301
	      or die "Error: cannot open '$file' for reading\n";
1300
            binmode(FILE);	# for Windows
1302
            binmode(FILE);	# for Windows
1301
	    while(<FILE>) {
1303
	    while(<FILE>) {
1302
		chop;
1304
		chop;
1303
		if($_ =~ /\r$/) {
1305
		if($_ =~ /\r$/) {
1304
		    push(@bad_files, $file);
1306
		    push(@bad_files, $file);
1305
		    last;
1307
		    last;
1306
		}
1308
		}
1307
	    }
1309
	    }
1308
	    close(FILE);
1310
	    close(FILE);
1309
	}
1311
	}
1310
	if(scalar(@bad_files) > 0) {
1312
	if(scalar(@bad_files) > 0) {
1311
	    $log->warning();
1313
	    $log->warning();
1312
	    $log->print("Found the following sources/headers with " .
1314
	    $log->print("Found the following sources/headers with " .
1313
			"CRLF line endings:\n");
1315
			"CRLF line endings:\n");
1314
	    $log->print("  " . join("\n  ", @bad_files) . "\n");
1316
	    $log->print("  " . join("\n  ", @bad_files) . "\n");
1315
	    $log->print("Some Unix compilers require LF line endings.\n");
1317
	    $log->print("Some Unix compilers require LF line endings.\n");
1316
	}
1318
	}
1317
	else {
1319
	else {
1318
	    $log->result("OK");
1320
	    $log->result("OK");
1319
	}
1321
	}
1320
    }
1322
    }
1321
 
1323
 
1322
    ## Check src/Makevars[.in] for portable compilation flags.
1324
    ## Check src/Makevars[.in] for portable compilation flags.
1323
 
1325
 
1324
    if((-f &file_path("src", "Makevars.in"))
1326
    if((-f &file_path("src", "Makevars.in"))
1325
       || (-f &file_path("src", "Makevars"))) {
1327
       || (-f &file_path("src", "Makevars"))) {
1326
	$log->checking("for portable compilation flags in Makevars");
1328
	$log->checking("for portable compilation flags in Makevars");
1327
	my $Rcmd = "tools:::.check_make_vars(\"src\")\n";
1329
	my $Rcmd = "tools:::.check_make_vars(\"src\")\n";
1328
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
1330
	my @out = R_runR($Rcmd, "${R_opts} --quiet",
1329
			 "R_DEFAULT_PACKAGES=NULL");
1331
			 "R_DEFAULT_PACKAGES=NULL");
1330
	@out = grep(!/^\>/, @out);
1332
	@out = grep(!/^\>/, @out);
1331
	if(scalar(@out) > 0) {
1333
	if(scalar(@out) > 0) {
1332
	    $log->warning();
1334
	    $log->warning();
1333
	    $log->print(join("\n", @out) . "\n");
1335
	    $log->print(join("\n", @out) . "\n");
1334
	}
1336
	}
1335
	else {
1337
	else {
1336
	    $log->result("OK");
1338
	    $log->result("OK");
1337
	}
1339
	}
1338
    }
1340
    }
1339
    
1341
    
1340
 
1342
 
1341
    chdir($pkgoutdir);
1343
    chdir($pkgoutdir);
1342
 
1344
 
1343
    ## Run the examples.
1345
    ## Run the examples.
1344
    ## This setting applies to vignettes below too.
1346
    ## This setting applies to vignettes below too.
1345
    ${R_opts} = ${R_opts}." -d valgrind" if $opt_use_valgrind;
1347
    ${R_opts} = ${R_opts}." -d valgrind" if $opt_use_valgrind;
1346
 
1348
 
1347
    if($opt_examples && (-d &file_path($library, $pkgname, "R-ex"))) {
1349
    if($opt_examples && (-d &file_path($library, $pkgname, "R-ex"))) {
1348
	$log->creating("${pkgname}-Ex.R");
1350
	$log->creating("${pkgname}-Ex.R");
1349
	my $Rexdir = &file_path($library, $pkgname, "R-ex");
1351
	my $Rexdir = &file_path($library, $pkgname, "R-ex");
1350
        ## $Rexdir might contain spaces (not on Windows)
1352
        ## $Rexdir might contain spaces (not on Windows)
1351
        my $is_zipped = 0;
1353
        my $is_zipped = 0;
1352
	my $cmd;
1354
	my $cmd;
1353
 
1355
 
1354
        if(-e &file_path($Rexdir, "Rex.zip")) {
1356
        if(-e &file_path($Rexdir, "Rex.zip")) {
1355
            $is_zipped = 1;
1357
            $is_zipped = 1;
1356
	    my $UNZIP = &R_getenv("R_UNZIPCMD", "unzip");
1358
	    my $UNZIP = &R_getenv("R_UNZIPCMD", "unzip");
1357
            my $Rexfile = &file_path($Rexdir, "Rex.zip");
1359
            my $Rexfile = &file_path($Rexdir, "Rex.zip");
1358
	    $cmd = join(" ",
1360
	    $cmd = join(" ",
1359
			("$UNZIP", "-q",
1361
			("$UNZIP", "-q",
1360
			 &shell_quote_file_path($Rexfile),
1362
			 &shell_quote_file_path($Rexfile),
1361
			 "-d",
1363
			 "-d",
1362
			 &shell_quote_file_path($Rexdir)));
1364
			 &shell_quote_file_path($Rexdir)));
1363
	    if(R_system($cmd)) {
1365
	    if(R_system($cmd)) {
1364
		$log->error();
1366
		$log->error();
1365
		$log->print("Cannot extract examples from ZIP archive.\n");
1367
		$log->print("Cannot extract examples from ZIP archive.\n");
1366
		exit(1);
1368
		exit(1);
1367
	    }
1369
	    }
1368
        }
1370
        }
1369
        if($WINDOWS) {
1371
        if($WINDOWS) {
1370
            ## avoid Rcmd as line may be too long after expansion.
1372
            ## avoid Rcmd as line may be too long after expansion.
1371
            ## We've forced R_HOME and Rexdir to have no spaces already.
1373
            ## We've forced R_HOME and Rexdir to have no spaces already.
1372
            $cmd = "perl ${R::Vars::R_HOME}/bin/massage-Examples ".
1374
            $cmd = "perl ${R::Vars::R_HOME}/bin/massage-Examples ".
1373
  		     "${pkgname} ${Rexdir} ".
1375
  		     "${pkgname} ${Rexdir} ".
1374
  		     "> ${pkgname}-Ex.R";
1376
  		     "> ${pkgname}-Ex.R";
1375
        } else {
1377
        } else {
1376
	    $cmd =
1378
	    $cmd =
1377
		join(" ",
1379
		join(" ",
1378
		     (&shell_quote_file_path(${R::Vars::R_EXE}),
1380
		     (&shell_quote_file_path(${R::Vars::R_EXE}),
1379
		      "CMD perl",
1381
		      "CMD perl",
1380
		      &shell_quote_file_path(&file_path(${R::Vars::R_SHARE_DIR},
1382
		      &shell_quote_file_path(&file_path(${R::Vars::R_SHARE_DIR},
1381
							"perl",
1383
							"perl",
1382
							"massage-Examples.pl")),
1384
							"massage-Examples.pl")),
1383
		      "${pkgname}",
1385
		      "${pkgname}",
1384
		      &shell_quote_file_path(${Rexdir}),
1386
		      &shell_quote_file_path(${Rexdir}),
1385
		      "> ${pkgname}-Ex.R"));
1387
		      "> ${pkgname}-Ex.R"));
1386
        }
1388
        }
1387
 
1389
 
1388
 	if(R_system($cmd)) {
1390
 	if(R_system($cmd)) {
1389
  	    $log->error();
1391
  	    $log->error();
1390
	    $log->print("Running massage-Examples to create " .
1392
	    $log->print("Running massage-Examples to create " .
1391
			"${pkgname}-Ex.R failed.\n");
1393
			"${pkgname}-Ex.R failed.\n");
1392
  	    exit(1);
1394
  	    exit(1);
1393
        }
1395
        }
1394
        if($is_zipped) {
1396
        if($is_zipped) {
1395
            unlink(&list_files_with_exts($Rexdir, "R"));
1397
            unlink(&list_files_with_exts($Rexdir, "R"));
1396
        }
1398
        }
1397
 
1399
 
1398
	$log->result("OK");
1400
	$log->result("OK");
1399
	$log->checking("examples");
1401
	$log->checking("examples");
1400
 
1402
 
1401
	if($opt_use_gct) {
1403
	if($opt_use_gct) {
1402
            $cmd = join(" ",
1404
            $cmd = join(" ",
1403
			("(echo 'gctorture(TRUE)';",
1405
			("(echo 'gctorture(TRUE)';",
1404
			 "cat ${pkgname}-Ex.R) |",
1406
			 "cat ${pkgname}-Ex.R) |",
1405
			 &shell_quote_file_path(${R::Vars::R_EXE}),
1407
			 &shell_quote_file_path(${R::Vars::R_EXE}),
1406
			 "${R_opts}",
1408
			 "${R_opts}",
1407
			 "> ${pkgname}-Ex.Rout 2>&1"));
1409
			 "> ${pkgname}-Ex.Rout 2>&1"));
1408
	} else {
1410
	} else {
1409
	    $cmd = join(" ",
1411
	    $cmd = join(" ",
1410
			(&shell_quote_file_path(${R::Vars::R_EXE}),
1412
			(&shell_quote_file_path(${R::Vars::R_EXE}),
1411
			 "${R_opts}",
1413
			 "${R_opts}",
1412
			 "< ${pkgname}-Ex.R",
1414
			 "< ${pkgname}-Ex.R",
1413
			 "> ${pkgname}-Ex.Rout 2>&1"));
1415
			 "> ${pkgname}-Ex.Rout 2>&1"));
1414
	}
1416
	}
1415
	if(R_system($cmd)) {
1417
	if(R_system($cmd)) {
1416
	    $log->error();
1418
	    $log->error();
1417
	    $log->print("Running examples in ${pkgname}-Ex.R failed.\n");
1419
	    $log->print("Running examples in ${pkgname}-Ex.R failed.\n");
1418
	    ## Try to spot the offending example right away.
1420
	    ## Try to spot the offending example right away.
1419
	    my $txt = join("\n", &read_lines("${pkgname}-Ex.Rout"));
1421
	    my $txt = join("\n", &read_lines("${pkgname}-Ex.Rout"));
1420
	    ## Look for the header section anchored by a subsequent call
1422
	    ## Look for the header section anchored by a subsequent call
1421
	    ## to flush(): needs to be kept in sync with the code in
1423
	    ## to flush(): needs to be kept in sync with the code in
1422
	    ## massage-Examples.pl.  Should perhaps also be more
1424
	    ## massage-Examples.pl.  Should perhaps also be more
1423
	    ## defensive about the prompt ...
1425
	    ## defensive about the prompt ...
1424
	    my @chunks = split(/(> \#\#\# \* [^\n]+\n> \n> flush)/, $txt);
1426
	    my @chunks = split(/(> \#\#\# \* [^\n]+\n> \n> flush)/, $txt);
1425
	    if(scalar(@chunks) > 2) {
1427
	    if(scalar(@chunks) > 2) {
1426
		$log->print("The error most likely occurred in:\n\n");
1428
		$log->print("The error most likely occurred in:\n\n");
1427
		$log->print($chunks[$#chunks - 1]);
1429
		$log->print($chunks[$#chunks - 1]);
1428
		$log->print($chunks[$#chunks] . "\n");
1430
		$log->print($chunks[$#chunks] . "\n");
1429
	    }
1431
	    }
1430
	    exit(1);
1432
	    exit(1);
1431
	}
1433
	}
1432
	## Look at the output from running the examples.  For the time
1434
	## Look at the output from running the examples.  For the time
1433
	## being, report warnings about use of deprecated functions, as
1435
	## being, report warnings about use of deprecated functions, as
1434
	## the next release will make them defunct and hence using them
1436
	## the next release will make them defunct and hence using them
1435
	## an error.  Also warn about loading defunct base package stubs, 
1437
	## an error.  Also warn about loading defunct base package stubs, 
1436
	## as load special-casing for these will be removed eventually.
1438
	## as load special-casing for these will be removed eventually.
1437
	my @lines = &read_lines("${pkgname}-Ex.Rout");
1439
	my @lines = &read_lines("${pkgname}-Ex.Rout");
1438
	my $any;
1440
	my $any;
1439
	my @bad_lines;
1441
	my @bad_lines;
1440
	@bad_lines = grep(/^Warning: .*is deprecated.$/, @lines);
1442
	@bad_lines = grep(/^Warning: .*is deprecated.$/, @lines);
1441
	if(scalar(@bad_lines) > 0) {
1443
	if(scalar(@bad_lines) > 0) {
1442
	    $log->warning();
1444
	    $log->warning();
1443
	    $any++;
1445
	    $any++;
1444
	    $log->print("Found the following significant warnings:\n");
1446
	    $log->print("Found the following significant warnings:\n");
1445
	    $log->print("  " . join("\n  ", @bad_lines) . "\n");
1447
	    $log->print("  " . join("\n  ", @bad_lines) . "\n");
1446
	    $log->print(wrap("", "",
1448
	    $log->print(wrap("", "",
1447
			     ("Deprecated functions may be defunct as",
1449
			     ("Deprecated functions may be defunct as",
1448
			      "soon as of the next release of R.\n",
1450
			      "soon as of the next release of R.\n",
1449
			      "See ?Deprecated.\n")));
1451
			      "See ?Deprecated.\n")));
1450
	}
1452
	}
1451
	@bad_lines = grep(/^Warning: package '.*' has been merged into/,
1453
	@bad_lines = grep(/^Warning: package '.*' has been merged into/,
1452
			  @lines);
1454
			  @lines);
1453
	## Could make this more precise by looking for an exact match
1455
	## Could make this more precise by looking for an exact match
1454
	## for one of the defunct stubs, but we currently do not get
1456
	## for one of the defunct stubs, but we currently do not get
1455
	## R_PKGS_STUBS from 'share/make/vars.mk'.
1457
	## R_PKGS_STUBS from 'share/make/vars.mk'.
1456
	if(scalar(@bad_lines) > 0) {
1458
	if(scalar(@bad_lines) > 0) {
1457
	    if($any) {
1459
	    if($any) {
1458
		$log->print("\nAdditional significant warnings:\n");
1460
		$log->print("\nAdditional significant warnings:\n");
1459
	    }
1461
	    }
1460
	    else {
1462
	    else {
1461
		$log->warning();
1463
		$log->warning();
1462
		$any++;
1464
		$any++;
1463
		$log->print("Found the following significant " .
1465
		$log->print("Found the following significant " .
1464
			    "warnings:\n");
1466
			    "warnings:\n");
1465
	    }
1467
	    }
1466
	    $log->print("  " . join("\n  ", @bad_lines) . "\n");
1468
	    $log->print("  " . join("\n  ", @bad_lines) . "\n");
1467
	    $log->print(wrap("", "",
1469
	    $log->print(wrap("", "",
1468
			     ("Support for loading defunct former base",
1470
			     ("Support for loading defunct former base",
1469
			      "packages may be removed as soon as of",
1471
			      "packages may be removed as soon as of",
1470
			      "the next release of R.\n")));
1472
			      "the next release of R.\n")));
1471
	}
1473
	}
1472
	$log->result("OK") unless($any);
1474
	$log->result("OK") unless($any);
1473
    }
1475
    }
1474
 
1476
 
1475
    ## Run the package-specific tests.
1477
    ## Run the package-specific tests.
1476
 
1478
 
1477
    if($opt_install && $opt_tests && (-d &file_path($pkgdir, "tests"))) {
1479
    if($opt_install && $opt_tests && (-d &file_path($pkgdir, "tests"))) {
1478
        $log->checking("tests");
1480
        $log->checking("tests");
1479
        my $testsrcdir = &file_path($pkgdir, "tests");
1481
        my $testsrcdir = &file_path($pkgdir, "tests");
1480
        my $testdir = &file_path($pkgoutdir, "tests");
1482
        my $testdir = &file_path($pkgoutdir, "tests");
1481
        if(!(-d $testdir)) {
1483
        if(!(-d $testdir)) {
1482
            mkdir($testdir, 0755)
1484
            mkdir($testdir, 0755)
1483
	      or die "Error: cannot create directory '$testdir'\n";
1485
	      or die "Error: cannot create directory '$testdir'\n";
1484
        }
1486
        }
1485
        chdir($testdir);
1487
        chdir($testdir);
1486
	foreach my $file (&list_files($testsrcdir)) {
1488
	foreach my $file (&list_files($testsrcdir)) {
1487
	    copy($file, basename($file));
1489
	    copy($file, basename($file));
1488
	}
1490
	}
1489
        my $makefiles = "-f " .
1491
        my $makefiles = "-f " .
1490
	    &shell_quote_file_path(&file_path(${R::Vars::R_SHARE_DIR},
1492
	    &shell_quote_file_path(&file_path(${R::Vars::R_SHARE_DIR},
1491
					      "make", "tests.mk"));
1493
					      "make", "tests.mk"));
1492
        if($WINDOWS) {
1494
        if($WINDOWS) {
1493
            $makefiles = "-f ${R::Vars::R_SHARE_DIR}/make/wintests.mk";}
1495
            $makefiles = "-f ${R::Vars::R_SHARE_DIR}/make/wintests.mk";}
1494
        my $makevars = "";
1496
        my $makevars = "";
1495
        if($WINDOWS && (-r "$testsrcdir/Makefile.win")) {
1497
        if($WINDOWS && (-r "$testsrcdir/Makefile.win")) {
1496
            $makefiles .= " -f $testsrcdir/Makefile.win";
1498
            $makefiles .= " -f $testsrcdir/Makefile.win";
1497
        }
1499
        }
1498
        elsif(-r &file_path($testsrcdir, "Makefile")) {
1500
        elsif(-r &file_path($testsrcdir, "Makefile")) {
1499
            $makefiles .= " -f " . &file_path($testsrcdir, "Makefile");
1501
            $makefiles .= " -f " . &file_path($testsrcdir, "Makefile");
1500
        }
1502
        }
1501
        if($WINDOWS && (-r "$testsrcdir/Makevars.win")) {
1503
        if($WINDOWS && (-r "$testsrcdir/Makevars.win")) {
1502
            $makevars = " -f $testsrcdir/Makevars.win";
1504
            $makevars = " -f $testsrcdir/Makevars.win";
1503
        }
1505
        }
1504
        elsif(-r &file_path($testsrcdir, "Makevars")) {
1506
        elsif(-r &file_path($testsrcdir, "Makevars")) {
1505
            $makevars = " -f " . &file_path($testsrcdir, "Makevars");
1507
            $makevars = " -f " . &file_path($testsrcdir, "Makevars");
1506
        }
1508
        }
1507
        else {
1509
        else {
1508
            open(MAKEVARS, "> Makevars");
1510
            open(MAKEVARS, "> Makevars");
1509
            print MAKEVARS "makevars = -f Makevars\n";
1511
            print MAKEVARS "makevars = -f Makevars\n";
1510
            print MAKEVARS "srcdir = $testsrcdir\n";
1512
            print MAKEVARS "srcdir = $testsrcdir\n";
1511
            ## at least windows does not pass env correctly to make
1513
            ## at least windows does not pass env correctly to make
1512
            print MAKEVARS "R_LIBS = $ENV{'R_LIBS'}\n";
1514
            print MAKEVARS "R_LIBS = $ENV{'R_LIBS'}\n";
1513
            print MAKEVARS "VPATH = \$(srcdir)\n\n";
1515
            print MAKEVARS "VPATH = \$(srcdir)\n\n";
1514
            print MAKEVARS "test-src-1 =";
1516
            print MAKEVARS "test-src-1 =";
1515
	    foreach my $file (&list_files_with_exts($testdir, "R")) {
1517
	    foreach my $file (&list_files_with_exts($testdir, "R")) {
1516
                print MAKEVARS "\\\n " . basename($file);
1518
                print MAKEVARS "\\\n " . basename($file);
1517
            }
1519
            }
1518
            print MAKEVARS "\n";
1520
            print MAKEVARS "\n";
1519
            print MAKEVARS "test-src-auto =";
1521
            print MAKEVARS "test-src-auto =";
1520
	    foreach my $file (&list_files_with_exts($testdir, "Rin")) {
1522
	    foreach my $file (&list_files_with_exts($testdir, "Rin")) {
1521
                $file =~ s/Rin$/R/;
1523
                $file =~ s/Rin$/R/;
1522
                print MAKEVARS "\\\n " . basename($file);
1524
                print MAKEVARS "\\\n " . basename($file);
1523
            }
1525
            }
1524
            print MAKEVARS "\n";
1526
            print MAKEVARS "\n";
1525
	    print MAKEVARS "USE_GCT = $opt_use_gct\n";
1527
	    print MAKEVARS "USE_GCT = $opt_use_gct\n";
1526
	    print MAKEVARS "R_OPTS = -d valgrind\n" if $opt_use_valgrind;
1528
	    print MAKEVARS "R_OPTS = -d valgrind\n" if $opt_use_valgrind;
1527
            close(MAKEVARS);
1529
            close(MAKEVARS);
1528
            $makevars = " -f Makevars";
1530
            $makevars = " -f Makevars";
1529
        }
1531
        }
1530
        print "\n";
1532
        print "\n";
1531
        if(R_system("${R::Vars::MAKE} $makefiles $makevars")) {
1533
        if(R_system("${R::Vars::MAKE} $makefiles $makevars")) {
1532
            $log->error();
1534
            $log->error();
1533
            exit(1);
1535
            exit(1);
1534
        }
1536
        }
1535
        chdir($pkgoutdir);
1537
        chdir($pkgoutdir);
1536
        $log->result("OK");
1538
        $log->result("OK");
1537
    }
1539
    }
1538
 
1540
 
1539
    ## Check package vignettes.
1541
    ## Check package vignettes.
1540
 
1542
 
1541
    chdir($pkgoutdir);
1543
    chdir($pkgoutdir);
1542
 
1544
 
1543
    my $vignette_dir = &file_path($pkgdir, "inst", "doc");
1545
    my $vignette_dir = &file_path($pkgdir, "inst", "doc");
1544
    if((-d $vignette_dir)
1546
    if((-d $vignette_dir)
1545
       && &list_files_with_type($vignette_dir, "vignette")) {
1547
       && &list_files_with_type($vignette_dir, "vignette")) {
1546
	$log->checking(join(" ",
1548
	$log->checking(join(" ",
1547
			    ("package vignettes in",
1549
			    ("package vignettes in",
1548
			     &sQuote(&file_path("inst", "doc")))));
1550
			     &sQuote(&file_path("inst", "doc")))));
1549
	my $any = 0;
1551
	my $any = 0;
1550
 
1552
 
1551
	## Do PDFs exist for all package vignettes?
1553
	## Do PDFs exist for all package vignettes?
1552
	my @vignette_files =
1554
	my @vignette_files =
1553
	  &list_files_with_type($vignette_dir, "vignette");
1555
	  &list_files_with_type($vignette_dir, "vignette");
1554
	my @bad_vignettes = ();
1556
	my @bad_vignettes = ();
1555
	foreach my $file (@vignette_files) {
1557
	foreach my $file (@vignette_files) {
1556
	    my $pdf_file = $file;
1558
	    my $pdf_file = $file;
1557
	    $pdf_file =~ s/\.[[:alpha:]]+$/.pdf/;
1559
	    $pdf_file =~ s/\.[[:alpha:]]+$/.pdf/;
1558
	    push(@bad_vignettes, $file) unless(-f $pdf_file);
1560
	    push(@bad_vignettes, $file) unless(-f $pdf_file);
1559
	}
1561
	}
1560
        ## A base package may not have PDFs to avoid blowing out the
1562
        ## A base package may not have PDFs to avoid blowing out the
1561
	## distribution size.  *Note* that it is assumed that base
1563
	## distribution size.  *Note* that it is assumed that base
1562
	## packages can be woven (i.e., that they only contain
1564
	## packages can be woven (i.e., that they only contain
1563
	## "standard" LaTeX).
1565
	## "standard" LaTeX).
1564
	if(!$is_base_pkg && scalar(@bad_vignettes) > 0) {
1566
	if(!$is_base_pkg && scalar(@bad_vignettes) > 0) {
1565
	    $log->warning();
1567
	    $log->warning();
1566
	    $any++;
1568
	    $any++;
1567
	    $log->print("Package vignettes without corresponding PDF:\n");
1569
	    $log->print("Package vignettes without corresponding PDF:\n");
1568
	    $log->print("  " . join("\n  ", @bad_vignettes) . "\n");
1570
	    $log->print("  " . join("\n  ", @bad_vignettes) . "\n");
1569
	}
1571
	}
1570
 
1572
 
1571
	## Can we run the code in the vignettes?
1573
	## Can we run the code in the vignettes?
1572
	if($opt_install && $opt_vignettes) {
1574
	if($opt_install && $opt_vignettes) {
1573
	    ## Should checking the vignettes assume the system default
1575
	    ## Should checking the vignettes assume the system default
1574
	    ## packages, or just base?
1576
	    ## packages, or just base?
1575
	    my $Rcmd = "options(warn=1)\nlibrary(tools)\n";
1577
	    my $Rcmd = "options(warn=1)\nlibrary(tools)\n";
1576
            ## A base package does not get installed during check.
1578
            ## A base package does not get installed during check.
1577
	    if(!$is_base_pkg && $opt_install) {
1579
	    if(!$is_base_pkg && $opt_install) {
1578
		$Rcmd .= "checkVignettes(package = \"${pkgname}\", " .
1580
		$Rcmd .= "checkVignettes(package = \"${pkgname}\", " .
1579
		         "lib.loc = \"${library}\", " .
1581
		         "lib.loc = \"${library}\", " .
1580
		         "workdir = \"src\"";
1582
		         "workdir = \"src\"";
1581
	    }
1583
	    }
1582
	    else {
1584
	    else {
1583
		$Rcmd .= "checkVignettes(dir = \"${pkgdir}\"";
1585
		$Rcmd .= "checkVignettes(dir = \"${pkgdir}\"";
1584
	    }
1586
	    }
1585
	    $Rcmd .= ", weave = FALSE" if(!$R_check_weave_vignettes);
1587
	    $Rcmd .= ", weave = FALSE" if(!$R_check_weave_vignettes);
1586
	    $Rcmd .= ")\n";
1588
	    $Rcmd .= ")\n";
1587
	    my @out = R_runR($Rcmd, "${R_opts} --quiet");
1589
	    my @out = R_runR($Rcmd, "${R_opts} --quiet");
1588
	    ## Vignette could redefine the prompt, e.g. to 'R>' ...
1590
	    ## Vignette could redefine the prompt, e.g. to 'R>' ...
1589
	    @out = grep(!/^[[:alnum:]]*\>/, @out);	    
1591
	    @out = grep(!/^[[:alnum:]]*\>/, @out);	    
1590
	    ## Or to "empty".  As empty lines in the output will most
1592
	    ## Or to "empty".  As empty lines in the output will most
1591
	    ## likely not indicate a problem ...
1593
	    ## likely not indicate a problem ...
1592
	    @out = grep(!/^[[:space:]]*$/, @out);
1594
	    @out = grep(!/^[[:space:]]*$/, @out);
1593
	    if(scalar(@out) > 0) {
1595
	    if(scalar(@out) > 0) {
1594
		$log->warning() unless($any);
1596
		$log->warning() unless($any);
1595
		$any++;
1597
		$any++;
1596
		$log->print(join("\n", @out) . "\n");
1598
		$log->print(join("\n", @out) . "\n");
1597
	    }
1599
	    }
1598
	}
1600
	}
1599
 
1601
 
1600
	$log->result("OK") unless($any);
1602
	$log->result("OK") unless($any);
1601
    }
1603
    }
1602
 
1604
 
1603
    ## Run LaTeX on the manual.
1605
    ## Run LaTeX on the manual.
1604
 
1606
 
1605
    if($opt_latex) {
1607
    if($opt_latex) {
1606
        my $latex_dir = &file_path($library, $pkgname, "latex");
1608
        my $latex_dir = &file_path($library, $pkgname, "latex");
1607
	if(-d $latex_dir) {
1609
	if(-d $latex_dir) {
1608
	    $ENV{'TEXINPUTS'} =
1610
	    $ENV{'TEXINPUTS'} =
1609
	      env_path(&file_path($R::Vars::R_SHARE_DIR, "texmf"),
1611
	      env_path(&file_path($R::Vars::R_SHARE_DIR, "texmf"),
1610
		       $ENV{'TEXINPUTS'});
1612
		       $ENV{'TEXINPUTS'});
1611
            my $is_zipped = 0;
1613
            my $is_zipped = 0;
1612
            # latex files might have been zipped
1614
            # latex files might have been zipped
1613
            if(-f &file_path($latex_dir, "Rhelp.zip")) {
1615
            if(-f &file_path($latex_dir, "Rhelp.zip")) {
1614
                $is_zipped = 1;
1616
                $is_zipped = 1;
1615
		my $UNZIP = &R_getenv("R_UNZIPCMD", "unzip");
1617
		my $UNZIP = &R_getenv("R_UNZIPCMD", "unzip");
1616
		my $latex_file = &file_path($latex_dir, "Rhelp.zip");
1618
		my $latex_file = &file_path($latex_dir, "Rhelp.zip");
1617
		$cmd = join(" ",
1619
		$cmd = join(" ",
1618
			    ("$UNZIP", "-q",
1620
			    ("$UNZIP", "-q",
1619
			     &shell_quote_file_path($latex_file),
1621
			     &shell_quote_file_path($latex_file),
1620
			     "-d",
1622
			     "-d",
1621
			     &shell_quote_file_path($latex_dir)));
1623
			     &shell_quote_file_path($latex_dir)));
1622
                if(R_system($cmd)) {
1624
                if(R_system($cmd)) {
1623
		    $log->error();
1625
		    $log->error();
1624
		    $log->print("Unzipping latex files failed.\n");
1626
		    $log->print("Unzipping latex files failed.\n");
1625
		    exit(1);
1627
		    exit(1);
1626
                }
1628
                }
1627
            }
1629
            }
1628
	    $log->creating("${pkgname}-manual.tex");
1630
	    $log->creating("${pkgname}-manual.tex");
1629
	    open(MANUAL, "> ${pkgname}-manual.tex")
1631
	    open(MANUAL, "> ${pkgname}-manual.tex")
1630
	      or die("Error: cannot open file '${pkgname}-manual.tex'" .
1632
	      or die("Error: cannot open file '${pkgname}-manual.tex'" .
1631
		     "for writing\n");
1633
		     "for writing\n");
1632
	    print MANUAL "\\documentclass\{article\}\n" .
1634
	    print MANUAL "\\documentclass\{article\}\n" .
1633
	      "\\usepackage[ae,hyper]\{Rd\}\n\\begin\{document\}\n";
1635
	      "\\usepackage[ae,hyper]\{Rd\}\n\\begin\{document\}\n";
1634
	    my @tex_files = &list_files_with_exts($latex_dir, "tex");
1636
	    my @tex_files = &list_files_with_exts($latex_dir, "tex");
1635
	    foreach my $file (@tex_files) {
1637
	    foreach my $file (@tex_files) {
1636
		open(FILE, "< $file")
1638
		open(FILE, "< $file")
1637
		  or die("Error: cannot open file '$file' for reading\n");
1639
		  or die("Error: cannot open file '$file' for reading\n");
1638
		while(<FILE>) {
1640
		while(<FILE>) {
1639
		    print MANUAL $_;
1641
		    print MANUAL $_;
1640
		}
1642
		}
1641
		close(FILE);
1643
		close(FILE);
1642
	    }
1644
	    }
1643
	    print MANUAL "\\end\{document\}\n";
1645
	    print MANUAL "\\end\{document\}\n";
1644
	    close(MANUAL);
1646
	    close(MANUAL);
1645
            if($is_zipped) {
1647
            if($is_zipped) {
1646
		unlink(&list_files_with_exts($latex_dir, "tex"));
1648
		unlink(&list_files_with_exts($latex_dir, "tex"));
1647
            }
1649
            }
1648
	    $log->result("OK");
1650
	    $log->result("OK");
1649
	    if($HAVE_LATEX) {
1651
	    if($HAVE_LATEX) {
1650
		$log->checking("${pkgname}-manual.tex");
1652
		$log->checking("${pkgname}-manual.tex");
1651
		## <NOTE>
1653
		## <NOTE>
1652
		## We use \nonstopmode{} so that LaTeX really gives an
1654
		## We use \nonstopmode{} so that LaTeX really gives an
1653
	        ## error (and returns) if something is wrong, and all
1655
	        ## error (and returns) if something is wrong, and all
1654
	        ## info goes to ${pkgname}-manual.log.
1656
	        ## info goes to ${pkgname}-manual.log.
1655
		## We also suppress all output from running LaTeX.
1657
		## We also suppress all output from running LaTeX.
1656
                ## We could also write stdout to a tempfile and replay
1658
                ## We could also write stdout to a tempfile and replay
1657
                ## this in case of problems.  But does this really help?
1659
                ## this in case of problems.  But does this really help?
1658
		my $cmd = "${R::Vars::LATEX}";
1660
		my $cmd = "${R::Vars::LATEX}";
1659
		$cmd .= " '\\nonstopmode{}\\input{${pkgname}-manual.tex}'";
1661
		$cmd .= " '\\nonstopmode{}\\input{${pkgname}-manual.tex}'";
1660
		$cmd .= " >/dev/null 2>&1";
1662
		$cmd .= " >/dev/null 2>&1";
1661
		## </NOTE>
1663
		## </NOTE>
1662
		if(R_system($cmd)) {
1664
		if(R_system($cmd)) {
1663
		    $log->error();
1665
		    $log->error();
1664
		    $log->print("LaTeX errors when creating DVI version.\n");
1666
		    $log->print("LaTeX errors when creating DVI version.\n");
1665
		    $log->print("This typically indicates Rd problems.\n");
1667
		    $log->print("This typically indicates Rd problems.\n");
1666
		    exit(1);
1668
		    exit(1);
1667
		}
1669
		}
1668
		$log->result("OK");
1670
		$log->result("OK");
1669
	    }
1671
	    }
1670
	}
1672
	}
1671
	else {
1673
	else {
1672
	    if($HAVE_LATEX) {
1674
	    if($HAVE_LATEX) {
1673
		$log->checking("DVI version of manual");
1675
		$log->checking("DVI version of manual");
1674
		my $cmd;
1676
		my $cmd;
1675
		if($WINDOWS) {
1677
		if($WINDOWS) {
1676
		    $cmd = join(" ",
1678
		    $cmd = join(" ",
1677
				("Rcmd.exe Rd2dvi --batch --no-preview",
1679
				("Rcmd.exe Rd2dvi --batch --no-preview",
1678
				 "-o ${pkgname}-manual.dvi >/dev/null 2>&1",
1680
				 "-o ${pkgname}-manual.dvi >/dev/null 2>&1",
1679
				 "$pkgdir"));
1681
				 "$pkgdir"));
1680
		} else {
1682
		} else {
1681
		    $cmd = join(" ",
1683
		    $cmd = join(" ",
1682
				(&shell_quote_file_path("${R::Vars::R_EXE}"),
1684
				(&shell_quote_file_path("${R::Vars::R_EXE}"),
1683
				 "CMD Rd2dvi --batch --no-preview",
1685
				 "CMD Rd2dvi --batch --no-preview",
1684
				 "-o ${pkgname}-manual.dvi >/dev/null 2>&1",
1686
				 "-o ${pkgname}-manual.dvi >/dev/null 2>&1",
1685
				 "$pkgdir"));
1687
				 "$pkgdir"));
1686
		}
1688
		}
1687
		if(R_system($cmd)) {
1689
		if(R_system($cmd)) {
1688
		    $log->error();
1690
		    $log->error();
1689
		    $log->print("LaTeX errors when creating DVI version.\n");
1691
		    $log->print("LaTeX errors when creating DVI version.\n");
1690
		    $log->print("This typically indicates Rd problems.\n");
1692
		    $log->print("This typically indicates Rd problems.\n");
1691
		    exit(1);
1693
		    exit(1);
1692
		}
1694
		}
1693
		$log->result("OK");
1695
		$log->result("OK");
1694
	    }
1696
	    }
1695
	}
1697
	}
1696
    }
1698
    }
1697
}
1699
}
1698
 
1700
 
1699

1701

1700
sub usage {
1702
sub usage {
1701
    print STDERR <<END;
1703
    print STDERR <<END;
1702
Usage: R CMD $name [options] pkgs
1704
Usage: R CMD $name [options] pkgs
1703
 
1705
 
1704
Check R packages from package sources, which can be directories or 
1706
Check R packages from package sources, which can be directories or 
1705
gzipped package 'tar' archives with extension '.tar.gz' or '.tgz'.
1707
gzipped package 'tar' archives with extension '.tar.gz' or '.tgz'.
1706
 
1708
 
1707
A variety of diagnostic checks on directory structure, index and
1709
A variety of diagnostic checks on directory structure, index and
1708
control files are performed.  The package is installed into the log
1710
control files are performed.  The package is installed into the log
1709
directory (which includes the translation of all Rd files into several
1711
directory (which includes the translation of all Rd files into several
1710
formats), and the Rd files are tested by LaTeX (if available).  All
1712
formats), and the Rd files are tested by LaTeX (if available).  All
1711
examples and tests provided by the package are tested to see if they
1713
examples and tests provided by the package are tested to see if they
1712
run successfully.
1714
run successfully.
1713
 
1715
 
1714
Options:
1716
Options:
1715
  -h, --help            print short help message and exit
1717
  -h, --help            print short help message and exit
1716
  -v, --version         print 'check' version info and exit
1718
  -v, --version         print 'check' version info and exit
1717
  -l, --library=LIB     library directory used for test installation
1719
  -l, --library=LIB     library directory used for test installation
1718
                        of packages (default is outdir)
1720
                        of packages (default is outdir)
1719
  -o, --outdir=DIR      directory used for logfiles, R output, etc.
1721
  -o, --outdir=DIR      directory used for logfiles, R output, etc.
1720
                        (default is 'pkg.Rcheck' in current directory,
1722
                        (default is 'pkg.Rcheck' in current directory,
1721
			where 'pkg' is the name of the package checked)
1723
			where 'pkg' is the name of the package checked)
1722
      --no-clean        do not clean outdir before using it
1724
      --no-clean        do not clean outdir before using it
1723
      --no-codoc        do not check for code/documentation mismatches
1725
      --no-codoc        do not check for code/documentation mismatches
1724
      --no-examples     do not run the examples in the Rd files
1726
      --no-examples     do not run the examples in the Rd files
1725
      --no-install      skip installation and associated tests
1727
      --no-install      skip installation and associated tests
1726
      --no-tests        do not run code in tests subdirectory
1728
      --no-tests        do not run code in tests subdirectory
1727
      --no-vignettes    do not check vignettes in Sweave format
1729
      --no-vignettes    do not check vignettes in Sweave format
1728
      --no-latex        do not run LaTeX on help files
1730
      --no-latex        do not run LaTeX on help files
1729
      --use-gct         use 'gctorture(TRUE)' when running examples/tests
1731
      --use-gct         use 'gctorture(TRUE)' when running examples/tests
1730
      --use-valgrind    use 'valgrind' when running examples/tests/vignettes
1732
      --use-valgrind    use 'valgrind' when running examples/tests/vignettes
1731
      --rcfile=FILE     read configuration values from FILE
1733
      --rcfile=FILE     read configuration values from FILE
1732
      
1734
      
1733
By default, all test sections are turned on.
1735
By default, all test sections are turned on.
1734
 
1736
 
1735
Email bug reports to <r-bugs\@r-project.org>.
1737
Email bug reports to <r-bugs\@r-project.org>.
1736
END
1738
END
1737
    exit 0;
1739
    exit 0;
1738
}
1740
}