admin (DEVEL): distfiles/specparser.pl - brute-force macros expans...

sparky sparky at pld-linux.org
Mon Mar 12 23:24:22 CET 2007


Author: sparky                       Date: Mon Mar 12 22:24:22 2007 GMT
Module: admin                         Tag: DEVEL
---- Log message:
- brute-force macros expansion: finds all possibilities;
  useful for kernel.spec at LINUX_2_6_20, but it may be distfiles killer in
  case of opera.spec (918 possibilities)

---- Files affected:
admin/distfiles:
   specparser.pl (1.13.2.1 -> 1.13.2.2) 

---- Diffs:

================================================================
Index: admin/distfiles/specparser.pl
diff -u admin/distfiles/specparser.pl:1.13.2.1 admin/distfiles/specparser.pl:1.13.2.2
--- admin/distfiles/specparser.pl:1.13.2.1	Mon Mar 12 23:21:33 2007
+++ admin/distfiles/specparser.pl	Mon Mar 12 23:24:17 2007
@@ -25,7 +25,7 @@
 	$spec = shift;
 	$base_spec = $spec;
 	$base_spec =~ s|.*/||;
-	%macro = ( "nil" => "" );
+	%macro = ( "nil" => [""] );
 	#$err_cnt = 0;
 }
 
@@ -50,25 +50,11 @@
 	return $v;
 }
 
-# expand macros in string
-sub expand($)
+sub expand_tr($)
 {
-	my $v = trim_spaces(shift);
-	my $cnt = 20;
-
-	while ($v =~ /\%\{([^\}]+)\}/) {
-		my $value;
-		if (defined $macro{$1}) {
-			$value = $macro{$1};
-		} else {
-			error("undefined macro $1");
-			$value = "UNDEFINED";
-		}
-		$v =~ s/\%\{([^\}]+)\}/$value/;
-
-		return $v if (length $v > 1000 or $cnt-- <= 0)
-	}
+	my $v = shift;
 
+	my $cnt = 20;
 	while ($v =~ s/\%\(\s*echo\s+([^\|]+?)\s*\|\s*tr\s*(-d|)\s+([^\)]+?)\s*\)/\@\@tr-me\@\@/) {
 		my ($what, $d_opt, $how) = ($1, $2, $3);
 		my ($from, $to) = ($how, "");
@@ -90,17 +76,60 @@
 		return $v if (length $v > 1000 or $cnt-- <= 0)
 	}
 
-	error("unexpanded macros in $v")
-		if ($v =~ /\%[^0-9]/);
-	
 	return $v;
 }
 
+# recursive expansion
+sub expand_r($$);
+sub expand_r($$)
+{
+	my ($to_expand, $level) = @_;
+	return $to_expand if $level < 0;
+	$level--;
+
+	if ($to_expand =~ /\%\{([^\}]+)\}/) {
+		my $key = quotemeta $1;
+		my $values;
+		if (defined $macro{$1}) {
+			$values = $macro{$1};
+		} else {
+			error("undefined macro $1");
+			$values = ["UNDEFINED"];
+		}
+		my @vs;
+		foreach my $value (@{$values}) {
+			(my $vs = $to_expand) =~ s/\%\{($key)\}/$value/;
+			push @vs, expand_r($vs, $level);
+		}
+
+		return @vs;
+	} else {
+		return $to_expand;
+	}
+}
+
+# expand macros in string
+sub expand($)
+{
+	my $v = trim_spaces(shift);
+	my $done = [];
+
+	foreach my $e ( expand_r($v, 20) ) {
+		$e = expand_tr($e);
+		push @{$done}, $e;
+		error("unexpanded macros in $e")
+			if ($e =~ /\%[^0-9]/);
+	}
+
+	return $done;
+}
+
 # define given macro
 sub define($$)
 {
 	my ($n, $v) = @_;
-	$macro{$n} = trim_spaces($v);
+	$macro{$n} = [] unless exists $macro{$n};
+	push @{$macro{$n}}, trim_spaces($v);
 }
 
 # sets hash of macros defined with %define or %global
@@ -116,8 +145,6 @@
 			define("version", $1);
 		} elsif (/^Name\s*:\s*(.*)/i) {
 			define("name", $1);
-		#} elsif (/^Source(\d+)\s*:\s*(.*)/i) {
-		#	define("source_$1", expand($2));
 		} elsif (/^Patch(\d+)\s*:\s*(.*)/i) {
 			define("patch_$1", expand($2));
 		} elsif (/^NoSource\s*:\s*(\d+)\s*$/i) {
@@ -127,6 +154,16 @@
 	close(F);
 }
 
+my %printed;
+sub print_once($)
+{
+	my $l = shift;
+	unless (exists $printed{$l}) {
+		print $l . "\n";
+		$printed{$l} = 1;
+	}
+}
+
 sub print_source($$$) {
 	my ($no, $md5, $s) = @_;
 	if ($s =~ /^([a-z0-9A-Z:\=\?\@\+\~\.\-\/_]|\%[0-9])+$/) {
@@ -136,14 +173,14 @@
 			} else {
 				if ($s =~ /:\/\/distfiles\.pld-linux\.org\/src/) {
 					$s =~ s|.*/||;
-					print "$md5 no-url-copy://$s\n";
+					print_once( "$md5 no-url-copy://$s" );
 				} else {
-								print "$md5 $s\n";
-							}
+					print_once( "$md5 $s" );
+				}
 			}
 		} else {
 			$s =~ s|.*/||;
-			print "$md5 no-url://$s\n";
+			print_once( "$md5 no-url://$s");
 		}
 	} else {
 		error("source $no url $s is ill-formatted");
@@ -167,7 +204,9 @@
 			if (defined $macro{"no_source_$no"}) {
 				error("both NoSource: $no and md5 given");
 			} elsif (defined $sourceno and ($sourceno == $no)) {
-				print_source($no, $md5, $source);
+				foreach my $s (@{$source}) {
+					print_source($no, $md5, $s);
+				}
 			} elsif (defined $sourceno) {
 				error("found md5 for source $no, but last defined source is $sourceno");
 			} else {
================================================================

---- CVS-web:
    http://cvs.pld-linux.org/admin/distfiles/specparser.pl?r1=1.13.2.1&r2=1.13.2.2&f=u



More information about the pld-cvs-commit mailing list