#!/usr/bin/perl -w
##
## RPM: Extract `Source*: ...` filenames from a SPEC file
## Copyright (c) 2007-2019 SATOH Fumiyasu @ OSS Technology Corp., Japan
##                         <https://www.osstech.co.jp/>
##
## License: GNU General Public License version 2 or later
##

use strict;
#use warnings;

## Nested macro pattern
## See also: http://www.din.or.jp/~ohzaki/regex.htm#GetNestedParen
my $macro_re;
$macro_re = qr/%\{[^{}]*(?:(??{$macro_re})[^{}]*)*\}/;

## External command macro pattern
my $macro_command_re = qr/%\((?:(?!%\().)*\)/;

my %v = ();
my @s = ();

sub pwarn
{
  print STDERR "$0: WARNING: $_[0]\n";
}

sub value
{
  my $name = shift;
  my $value = $v{$name};

  unless (defined($value)) {
    #pwarn "Undefined value: \%$name";
    $value = "### Undefined value: $name ###";
  }

  return subst($value);
}

sub subst
{
  my $str = shift;

  ## Expand %{macro}
  $str =~ s/($macro_re)/subst_nested($1)/ge;
  ## Expand %(macro)
  $str =~ s/($macro_command_re)/subst_shell($1)/ge;
  ## Expand %macro
  $str =~ s/%([a-z_]\w*)/subst(value($1))/ge;

  return $str;
}

sub subst_nested
{
  my $str = shift;

  return $str if $str =~ /^%\{(\w+)\s.*\}$/;

  my ($negative, $if_defined, $name, $value) = $str =~ /^%\{(!)?(\?)?(\w+)(?::(.*))?\}$/;

  if ($if_defined) {
    return '' if (!defined($v{$name}) xor $negative);
  }
  return subst($value) if (defined($value));
  return value($name);
}

sub subst_shell
{
  my $str = shift;

  my ($shell_cmd) = $str =~ /^%\((.*)\)$/;

  my $value = eval {
    local $SIG{__WARN__} = sub {};
    `exec </dev/null; $shell_cmd`;
  };
  if (defined($value)) {
    chomp($value);
  }
  else {
    #pwarn "Command substitution failed: $shell_cmd";
    $value = "### Command substitution failed: $shell_cmd ###";
  }

  return $value;
}

while (<>) {
  chomp;

  ## FIXME
  s/\\\\/\\/g;

  if (/^%(prep|changelog)\s*$/) {
    last;
  }
  elsif (/^source\d*:\s*(.*)$/i) {
    push(@s, $1);
  }
  elsif (/^\s*%(?:define|global)\s+(\w+)\s+(.*?)\s*$/) {
    $v{$1} = $2;
  }
  elsif (/^(\w+):\s+(.*)$/) {
    $v{lc($1)} = $2;
  }
}

for my $s (@s) {
  $s = subst($s);

  if ($s =~/^https:\/\/github\.com\/.*/){
    print "$s\n";
  } else {
    $s =~ s#.*/##;
    print "$s\n";
  }
}

exit(0);
