| 1 | package metadata; |
| 2 | use base 'Exporter'; |
| 3 | use strict; |
| 4 | use warnings; |
| 5 | our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features clear_packages parse_package_metadata get_multiline); |
| 6 | |
| 7 | our %package; |
| 8 | our %preconfig; |
| 9 | our %srcpackage; |
| 10 | our %category; |
| 11 | our %subdir; |
| 12 | our %features; |
| 13 | |
| 14 | sub get_multiline { |
| 15 | my $fh = shift; |
| 16 | my $prefix = shift; |
| 17 | my $str; |
| 18 | while (<$fh>) { |
| 19 | last if /^@@/; |
| 20 | $str .= (($_ and $prefix) ? $prefix . $_ : $_); |
| 21 | } |
| 22 | |
| 23 | return $str ? $str : ""; |
| 24 | } |
| 25 | |
| 26 | sub clear_packages() { |
| 27 | %subdir = (); |
| 28 | %preconfig = (); |
| 29 | %package = (); |
| 30 | %srcpackage = (); |
| 31 | %category = (); |
| 32 | %features = (); |
| 33 | } |
| 34 | |
| 35 | sub parse_package_metadata($) { |
| 36 | my $file = shift; |
| 37 | my $pkg; |
| 38 | my $feature; |
| 39 | my $makefile; |
| 40 | my $preconfig; |
| 41 | my $subdir; |
| 42 | my $src; |
| 43 | |
| 44 | open FILE, "<$file" or do { |
| 45 | warn "Cannot open '$file': $!\n"; |
| 46 | return undef; |
| 47 | }; |
| 48 | while (<FILE>) { |
| 49 | chomp; |
| 50 | /^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do { |
| 51 | $makefile = $1; |
| 52 | $subdir = $2; |
| 53 | $src = $3; |
| 54 | $subdir =~ s/^package\///; |
| 55 | $subdir{$src} = $subdir; |
| 56 | $srcpackage{$src} = []; |
| 57 | undef $pkg; |
| 58 | }; |
| 59 | next unless $src; |
| 60 | /^Package:\s*(.+?)\s*$/ and do { |
| 61 | undef $feature; |
| 62 | $pkg = {}; |
| 63 | $pkg->{src} = $src; |
| 64 | $pkg->{makefile} = $makefile; |
| 65 | $pkg->{name} = $1; |
| 66 | $pkg->{title} = ""; |
| 67 | $pkg->{default} = "m if ALL"; |
| 68 | $pkg->{depends} = []; |
| 69 | $pkg->{mdepends} = []; |
| 70 | $pkg->{builddepends} = []; |
| 71 | $pkg->{buildtypes} = []; |
| 72 | $pkg->{subdir} = $subdir; |
| 73 | $pkg->{tristate} = 1; |
| 74 | $package{$1} = $pkg; |
| 75 | push @{$srcpackage{$src}}, $pkg; |
| 76 | }; |
| 77 | /^Feature:\s*(.+?)\s*$/ and do { |
| 78 | undef $pkg; |
| 79 | $feature = {}; |
| 80 | $feature->{name} = $1; |
| 81 | $feature->{priority} = 0; |
| 82 | }; |
| 83 | $feature and do { |
| 84 | /^Target-Name:\s*(.+?)\s*$/ and do { |
| 85 | $features{$1} or $features{$1} = []; |
| 86 | push @{$features{$1}}, $feature; |
| 87 | }; |
| 88 | /^Target-Title:\s*(.+?)\s*$/ and $feature->{target_title} = $1; |
| 89 | /^Feature-Priority:\s*(\d+)\s*$/ and $feature->{priority} = $1; |
| 90 | /^Feature-Name:\s*(.+?)\s*$/ and $feature->{title} = $1; |
| 91 | /^Feature-Description:/ and $feature->{description} = get_multiline(\*FILE, "\t\t\t"); |
| 92 | next; |
| 93 | }; |
| 94 | next unless $pkg; |
| 95 | /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1; |
| 96 | /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1; |
| 97 | /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1; |
| 98 | /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1; |
| 99 | /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1; |
| 100 | /^Source: \s*(.+)\s*$/ and $pkg->{source} = $1; |
| 101 | /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1; |
| 102 | /^Provides: \s*(.+)\s*$/ and do { |
| 103 | my @vpkg = split /\s+/, $1; |
| 104 | foreach my $vpkg (@vpkg) { |
| 105 | $package{$vpkg} or $package{$vpkg} = { |
| 106 | name => $vpkg, |
| 107 | vdepends => [], |
| 108 | src => $src, |
| 109 | subdir => $subdir, |
| 110 | makefile => $makefile |
| 111 | }; |
| 112 | push @{$package{$vpkg}->{vdepends}}, $pkg->{name}; |
| 113 | } |
| 114 | }; |
| 115 | /^Menu-Depends: \s*(.+)\s*$/ and $pkg->{mdepends} = [ split /\s+/, $1 ]; |
| 116 | /^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ]; |
| 117 | /^Build-Variant: \s*([\w\-]+)\s*/ and $pkg->{variant} = $1; |
| 118 | /^Build-Only: \s*(.+)\s*$/ and $pkg->{buildonly} = 1; |
| 119 | /^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ]; |
| 120 | /^Build-Depends\/(\w+): \s*(.+)\s*$/ and $pkg->{"builddepends/$1"} = [ split /\s+/, $2 ]; |
| 121 | /^Build-Types:\s*(.+)\s*$/ and $pkg->{buildtypes} = [ split /\s+/, $1 ]; |
| 122 | /^Category: \s*(.+)\s*$/ and do { |
| 123 | $pkg->{category} = $1; |
| 124 | defined $category{$1} or $category{$1} = {}; |
| 125 | defined $category{$1}->{$src} or $category{$1}->{$src} = []; |
| 126 | push @{$category{$1}->{$src}}, $pkg; |
| 127 | }; |
| 128 | /^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline(*FILE, "\t\t "); |
| 129 | /^Type: \s*(.+)\s*$/ and do { |
| 130 | $pkg->{type} = [ split /\s+/, $1 ]; |
| 131 | undef $pkg->{tristate}; |
| 132 | foreach my $type (@{$pkg->{type}}) { |
| 133 | $type =~ /ipkg/ and $pkg->{tristate} = 1; |
| 134 | } |
| 135 | }; |
| 136 | /^Config:\s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline(*FILE, "\t"); |
| 137 | /^Prereq-Check:/ and $pkg->{prereq} = 1; |
| 138 | /^Preconfig:\s*(.+)\s*$/ and do { |
| 139 | my $pkgname = $pkg->{name}; |
| 140 | $preconfig{$pkgname} or $preconfig{$pkgname} = {}; |
| 141 | if (exists $preconfig{$pkgname}->{$1}) { |
| 142 | $preconfig = $preconfig{$pkgname}->{$1}; |
| 143 | } else { |
| 144 | $preconfig = { |
| 145 | id => $1 |
| 146 | }; |
| 147 | $preconfig{$pkgname}->{$1} = $preconfig; |
| 148 | } |
| 149 | }; |
| 150 | /^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1; |
| 151 | /^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1; |
| 152 | /^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1; |
| 153 | } |
| 154 | close FILE; |
| 155 | return 1; |
| 156 | } |
| 157 | |
| 158 | 1; |
| 159 | |