The R Project SVN R

Rev

Details | Last modification | View Log | RSS feed

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