-
Notifications
You must be signed in to change notification settings - Fork 138
/
yacc.pm
146 lines (119 loc) · 4.43 KB
/
yacc.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# Copyright (C) 2001-2007, Parrot Foundation.
=head1 NAME
config/auto/yacc.pm - parser generator
=head1 DESCRIPTION
Determines whether C<yacc> is installed and if it's actually C<bison> of at
least the user-specified minimum version, defaulting to 2.1.
=cut
package inter::yacc;
use strict;
use warnings;
use base qw(Parrot::Configure::Step);
use Parrot::Configure::Utils qw( :inter capture_output check_progs );
sub _init {
my $self = shift;
my %data;
$data{description} = q{Is yacc installed};
$data{result} = q{};
return \%data;
}
my @yacc_defaults =
defined( $ENV{TEST_YACC} )
? $ENV{TEST_YACC}
: ( 'bison -v -y', 'yacc', 'byacc' );
my $default_required = '2.1';
sub runstep {
my ( $self, $conf ) = @_;
my $util = 'yacc';
my $prompt = "Do you have a parser generator, like bison or yacc?";
my $verbose = $conf->options->get('verbose');
# undef means we don't have bison... default to not having bison
$conf->data->set( bison_version => undef );
unless ( $conf->options->get('maintainer') ) {
$conf->data->set( $util => 'echo' );
$self->set_result('skipped');
return 1;
}
# precedence of sources for the program:
# default -> probe -> environment -> option -> ask
my $prog = $conf->options->get($util);
unless ($prog) {
$prog = $ENV{ uc($util) };
}
# never override the user. If a non-existent program is specified then
# the user is responsible for the consequences.
if ( defined $prog ) {
$conf->data->set( $util => $prog );
$self->set_result('user defined');
return 1;
}
else {
$prog = check_progs( [@yacc_defaults], $verbose );
if ( !$prog ) {
$self->set_result('no yacc program was found');
return;
}
else {
if ( $conf->options->get('ask') ) {
$prog = prompt( $prompt, $prog ? $prog : $conf->data->get($util) );
}
my ( $stdout, $stderr, $ret ) = capture_output( $prog, '--version' );
# don't override the user even if the program they provided
# appears to be broken
if ( $ret == -1 and !$conf->options->get('ask') ) {
# fall back to default
$self->set_result('yacc program does not exist or does not understand --version');
return;
}
elsif ( $stdout =~ /Bison .*? (\d+) \. (\d+) (\w)?/x ) {
# if '--version' returns a string assume that this is bison.
# if this is bison pretending to be yacc
# '--version' doesn't work
# someday we might need to check $3 also.
my ( $prog_major, $prog_minor, $prog_patch ) = ( $1, $2, $3 );
my $prog_version = "$1.$2";
$prog_version .= $3 if $3;
# is there a version requirement?
my $req = $conf->options->get('bison_required');
unless ( defined $req ) {
$req = $default_required;
}
if ($req) {
my ( $rmajor, $rminor ) = ( $req =~ / ^ (\d+) \. (\d+) (\w)? $ /x );
if ( !defined $rmajor ) {
$self->set_result("could not understand bison version requirement");
return;
}
elsif (
$prog_major < $rmajor
or ( $prog_major == $rmajor
and $prog_minor < $rminor )
)
{
$self->set_result( "found bison version $prog_version"
. " but at least $rmajor.$rminor is required" );
return;
}
else {
1; # lack an explicit 'else' here
}
}
$conf->data->set( bison_version => $prog_version );
$self->set_result("bison $prog_version");
$conf->data->set( $util => $prog );
return 1;
}
else {
$self->set_result('yacc program does not exist or does not understand --version');
return;
}
}
}
}
1;
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4: