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