--- /dev/null
+#!/usr/bin/perl
+#
+# USAGE: specparser.pl file.spec
+#
+# Output:
+# stdout:
+# list of:
+# <md5><space><url>\n
+# for given specfile.
+# stderr:
+# diagnostics
+# exit status:
+# 0 - normal
+# 2 - cannot open spec file
+#
+
+%macro = ();
+
+# expand macros in string
+sub expand($)
+{
+ my $v = shift;
+ my $cnt = 20;
+
+ while ($cnt-- > 0 && $v =~ /\%\{([^\{]+)\}/) {
+ my $value;
+ if (defined $macro{$1}) {
+ $value = $macro{$1};
+ } else {
+ $value = "\@undef:$1\@";
+ }
+ $v =~ s/\%\{([^\{]+)\}/$value/;
+ last if (length $v > 1000);
+ }
+ return $v;
+}
+
+# define given macro
+sub define($$)
+{
+ my ($n, $v) = @_;
+ $macro{$n} = expand($v);
+}
+
+# sets hash of macros defined with %define or %global
+# also define %{name}, %{version} and %{source_N}
+sub parse_defines($)
+{
+ open(F, "< $_[0]") or die;
+ while (<F>) {
+ chomp;
+ if (/^\s*\%(define|global)\s+([^\s]+)\s+([^\s].*)$/) {
+ define($2, $3);
+ } elsif (/^Version\s*:\s*(.*)/i) {
+ define("version", $1);
+ } elsif (/^Name\s*:\s*(.*)/i) {
+ define("name", $1);
+ } elsif (/^Source(\d+)\s*:\s*(.*)/i) {
+ define("source_$1", $2);
+ }
+ }
+ close(F);
+}
+
+sub print_md5($)
+{
+ open(F, "< $_[0]") or die;
+ while (<F>) {
+ chomp;
+ if (/^\s*#\s*source(\d+)-md5\s*:\s*([a-f0-9]{32})/i) {
+ if (defined $macro{"source_$1"}) {
+ my $s = $macro{"source_$1"};
+ my $md5 = $2;
+ if ($s =~ / / || $s =~ /^\%\{/ || $s =~ /\@undef/) {
+ print STDERR "$_[0]: source url $s is ill-formatted\n";
+ } else {
+ print "$md5 $s\n";
+ }
+ } else {
+ print STDERR "$_[0]: source $1 not defined\n";
+ }
+ }
+ }
+ close(F);
+}
+
+$spec = shift;
+
+parse_defines($spec);
+print_md5($spec);
+
+exit(0);