]> git.pld-linux.org Git - projects/distfiles.git/blame - specparser.pl
- allow repeated md5s
[projects/distfiles.git] / specparser.pl
CommitLineData
0db58532 1#!/usr/bin/perl
b396edfa 2# $Id$
0db58532
MM
3#
4# USAGE: specparser.pl file.spec
5#
6# Output:
7# stdout:
8# list of:
9# <md5><space><url>\n
10# for given specfile.
1b5ce8c2 11# except for lines prefixed with: ERROR:
0db58532
MM
12# exit status:
13# 0 - normal
14# 2 - cannot open spec file
15#
8079fcc5 16use strict;
17use warnings;
18
19my %no_source;
20my $spec;
21my $base_spec;
22my @spec;
23my @sources;
0db58532 24
0dd6294b
MM
25sub next_spec($)
26{
8079fcc5 27 $spec = shift;
28 @spec = ();
29 $base_spec = $spec;
30 $base_spec =~ s|.*/||;
0dd6294b 31}
0db58532 32
0dd6294b 33sub error($)
0db58532 34{
8079fcc5 35 print_once( "ERROR: $base_spec: $_[0]" );
0dd6294b
MM
36}
37
38sub warning($)
39{
8079fcc5 40 print "ERROR: $base_spec: $_[0]\n";
0dd6294b 41}
51a652ef 42
0dd6294b
MM
43sub trim_spaces($)
44{
8079fcc5 45 my $v = shift;
46
47 $v =~ s/\s+$//;
48 $v =~ s/^\s+//;
49
50 return $v;
0dd6294b
MM
51}
52
53# expand macros in string
8079fcc5 54sub expand($$) # {{{
0dd6294b 55{
8079fcc5 56 my $v = trim_spaces(shift);
57 my $macrotree = shift;
58 my $cnt = 20;
59
60 while ($v =~ /\%\{([^\}]+)\}/) {
61 my $value;
62 if (defined $macrotree->{$1}) {
63 $value = $macrotree->{$1};
64 } else {
65 error("undefined macro $1");
66 $value = "UNDEFINED";
67 return undef;
68 }
69 $v =~ s/\%\{([^\}]+)\}/$value/;
70
71 return $v if (length $v > 1000 or $cnt-- <= 0)
72 }
0db58532 73
8079fcc5 74 while ($v =~ s/\%\(\s*echo\s+([^\|]+?)\s*\|\s*tr\s*(-d|)\s+([^\)]+?)\s*\)/\@\@tr-me\@\@/) {
75 my ($what, $d_opt, $how) = ($1, $2, $3);
76 my ($from, $to) = ($how, "");
77 ($from, $to) = ($1, $2)
78 if $how =~ /^([^\s]+)\s+([^\s]+)$/;
79 if ($d_opt and $to ne "") {
80 error("tr -d with second string)");
81 } elsif (($from . $to) =~ /^[a-zA-Z0-9\+_\-\.]+$/) {
82 if ($d_opt) {
83 eval "\$what =~ tr/$from//d;";
84 } else {
85 eval "\$what =~ tr/$from/$to/;";
86 }
87 } else {
88 error("illegal characters in tr string(s) '$from' '$to'");
89 }
90 $v =~ s/\@\@tr-me\@\@/$what/;
91
92 return $v if (length $v > 1000 or $cnt-- <= 0)
93 }
94
95 error("unexpanded macros in $v")
96 if ($v =~ /\%[^0-9]/);
97
98 return $v;
99} # }}}
100
101sub preparse_spec($) # {{{
0db58532 102{
8079fcc5 103 @spec = ("");
104
105 open(F, "< $_[0]") or die;
106 while (<F>) {
107 chomp;
108 if (/^\s*(\%(description|package|prep|install|pre|post|files)|BuildRoot|URL)/) {
109 last;
110 } elsif (/^\s*(\%if.*|\%else|\%endif|\%define\s+.*|Version.*|Name.*)\s*$/) {
111 $_ = $1;
112 if ($spec[$#spec] =~ /\%if/) {
113 if (/\%else/) {
114 next; # don't include empty %if-%else
115 } elsif (/\%endif/) {
116 # remove empty %if-%endif
117 pop @spec;
118 next;
119 }
120 }
121 push @spec, $_;
122 } elsif (/^NoSource\s*:\s*(\d+)\s*$/i) {
123 $no_source{$1} = 1;
124 }
125 }
126 close(F);
127
128 shift @spec;
129} # }}}
130
131
132my $total = 0;
133
134sub cont($$);
135sub cont($$) # {{{
136{
137 my ($spec, $macros) = @_;
138 local $_;
139 while ($_ = shift @{$spec}) {
140 if (0 <= index $_, '%if') { # if, ifarch, ifos
141
142 # split spec parsing
143 my @speccopy = @{$spec};
144 my %macroscopy = %{$macros};
145 cont(\@speccopy, \%macroscopy);
0db58532 146
8079fcc5 147 my $level = 0;
148 while ($_ = shift @{$spec}) {
149 if ($level <= 0 and ($_ eq '%else' or $_ eq '%endif')) {
150 last;
151 } elsif (0 <= index $_, '%if') {
152 $level++;
153 } elsif ($_ eq '%endif') {
154 $level--;
155 }
156 }
157
158 # continue parsing
159
160 } elsif ($_ eq '%else') {
161
162 # %else happens only when %if was interpreted
163 # so skip until %endif
164
165 my $level = 0;
166 while ($_ = shift @{$spec}) {
167 if ($level <= 0 and $_ eq '%endif') {
168 last;
169 } elsif (0 <= index $_, '%if') {
170 $level++;
171 } elsif ($_ eq '%endif') {
172 $level--;
173 }
174 }
175
176 } elsif (/^\s*\%(define|global)\s+([^\s]+)\s+([^\s].*?)\s*$/) {
177 $macros->{$2} = $3;
178
179 } elsif (/^Version\s*:\s*(.*?)\s*$/i) {
180 $macros->{"version"} = $1;
181 } elsif (/^Name\s*:\s*(.*?)\s*$/i) {
182 $macros->{"name"} = $1;
183 } elsif (!/\%endif/) {
184 warn "unrecognised line: $_\n";
185 }
186 }
187
188 # the end, yuppie !
189 foreach my $s (@sources) {
190 my $src = expand( $s->[2], $macros );
191 if (defined $src) {
192 our %tried;
193 unless (exists $tried{$src}) {
194 print_source( $s->[0], $s->[1], $src );
195 $tried{$src} = 1;
196 }
197 }
198 }
199
200 if (++$total > 10000) {
201 error("maximum number of bcond posibilities exceeded");
202 exit 0;
203 }
204} # }}}
205
206sub print_once($)
0db58532 207{
8079fcc5 208 our %printed;
209 my $l = shift;
210 unless (exists $printed{$l}) {
211 print $l . "\n";
212 $printed{$l} = 1;
213 }
0db58532
MM
214}
215
8079fcc5 216sub print_source($$$) # {{{
0db58532 217{
8079fcc5 218 my ($no, $md5, $s) = @_;
219
0dd6294b 220 if ($s =~ /^([a-z0-9A-Z:\=\?\@\+\~\.\-\/_]|\%[0-9])+$/) {
8079fcc5 221 if ($s =~ /^(ftp|http|https):\/\//) {
222 if ($s =~ /\/$/) {
223 error("source $no ($s) is directory");
224 } else {
225 if ($s =~ /:\/\/distfiles\.pld-linux\.org\/src/) {
226 $s =~ s|.*/||;
227 print_once( "$md5 no-url-copy://$s" );
228 } else {
229 print_once( "$md5 $s" );
230 }
231 }
232 } else {
233 $s =~ s|.*/||;
234 print_once( "$md5 no-url://$s");
235 }
7882011d 236 } else {
8079fcc5 237 error("source $no url $s is ill-formatted");
0db58532 238 }
8079fcc5 239} # }}}
240
241sub add_md5_to_print($) # {{{
242{
243 open(F, "< $_[0]") or die;
244 my $sourceno = undef;
245 my $source = undef;
246 while (<F>) {
247 chomp;
248 if (/^Source(\d+)\s*:\s*(.*)/i) {
249 $sourceno = $1;
250 $source = $2;
251 } elsif (/^\s*#\s*source(\d+)-md5\s*:\s*([a-f0-9]{32})/i) {
252 my $no = $1;
253 my $md5 = $2;
254 if (defined $no_source{$no}) {
255 error("both NoSource: $no and md5 given");
256 } if (defined $sourceno) {
257 if ($sourceno == $no) {
258 push @sources, [$no, $md5, $source];
259 } else {
260 error("found md5 for source $no, but last defined source is $sourceno (# SourceN-md5: has to be placed just after SourceN:)");
261 }
262 } else {
263 error("source $no not defined (# SourceN-md5: has to be placed just after SourceN:)");
264 }
265
266 $sourceno = undef;
267 $source = undef;
268 }
269 }
270 close(F);
271} # }}}
0db58532 272
0dd6294b 273next_spec(shift);
8079fcc5 274preparse_spec($spec);
275add_md5_to_print($spec);
276cont( \@spec, { "nil" => "" } );
0db58532
MM
277
278exit(0);
8079fcc5 279
280# vim: ts=4:sw=4:fdm=marker
This page took 0.071137 seconds and 4 git commands to generate.