The R Project SVN R

Rev

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

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