+sub confstr($) {
+ my $conf = shift;
+ $conf =~ tr#/\.\-/#___#;
+ return $conf;
+}
+
+sub parse_package_metadata_usergroup($$$$$) {
+ my $makefile = shift;
+ my $typename = shift;
+ my $names = shift;
+ my $ids = shift;
+ my $spec = shift;
+ my $name;
+ my $id;
+
+ # the regex for name is taken from is_valid_name() of package shadow
+ if ($spec =~ /^([a-z_][a-z0-9_-]*\$?)$/) {
+ $name = $spec;
+ $id = -1;
+ } elsif ($spec =~ /^([a-z_][a-z0-9_-]*\$?)=(\d+)$/) {
+ $name = $1;
+ $id = $2;
+ } else {
+ warn "$makefile: invalid $typename spec $spec\n";
+ return 0;
+ }
+
+ if ($id =~ /^[1-9]\d*$/) {
+ if ($id >= 65536) {
+ warn "$makefile: $typename $name id $id >= 65536";
+ return 0;
+ }
+ if (not exists $ids->{$id}) {
+ $ids->{$id} = {
+ name => $name,
+ makefile => $makefile,
+ };
+ } elsif ($ids->{$id}{name} ne $name) {
+ warn "$makefile: $typename $name id $id is already taken by $ids->{$id}{makefile}\n";
+ return 0;
+ }
+ } elsif ($id != -1) {
+ warn "$makefile: $typename $name has invalid id $id\n";
+ return 0;
+ }
+
+ if (not exists $names->{$name}) {
+ $names->{$name} = {
+ id => $id,
+ makefile => $makefile,
+ };
+ } elsif ($names->{$name}{id} != $id) {
+ warn "$makefile: id of $typename $name collides with that defined defined in $names->{$name}{makefile}\n";
+ return 0;
+ }
+ return 1;
+}
+
+sub parse_target_metadata($) {
+ my $file = shift;
+ my ($target, @target, $profile);
+ my %target;
+ my $makefile;
+
+ open FILE, "<$file" or do {
+ warn "Can't open file '$file': $!\n";
+ return;
+ };
+ while (<FILE>) {
+ chomp;
+ /^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and $makefile = $1;
+ /^Target:\s*(.+)\s*$/ and do {
+ my $name = $1;
+ $target = {
+ id => $name,
+ board => $name,
+ makefile => $makefile,
+ boardconf => confstr($name),
+ conf => confstr($name),
+ profiles => [],
+ features => [],
+ depends => [],
+ subtargets => []
+ };
+ push @target, $target;
+ $target{$name} = $target;
+ if ($name =~ /([^\/]+)\/([^\/]+)/) {
+ push @{$target{$1}->{subtargets}}, $2;
+ $target->{board} = $1;
+ $target->{boardconf} = confstr($1);
+ $target->{subtarget} = 1;
+ $target->{parent} = $target{$1};
+ }
+ };
+ /^Target-Name:\s*(.+)\s*$/ and $target->{name} = $1;
+ /^Target-Arch:\s*(.+)\s*$/ and $target->{arch} = $1;
+ /^Target-Arch-Packages:\s*(.+)\s*$/ and $target->{arch_packages} = $1;
+ /^Target-Features:\s*(.+)\s*$/ and $target->{features} = [ split(/\s+/, $1) ];
+ /^Target-Depends:\s*(.+)\s*$/ and $target->{depends} = [ split(/\s+/, $1) ];
+ /^Target-Description:/ and $target->{desc} = get_multiline(*FILE);
+ /^Target-Optimization:\s*(.+)\s*$/ and $target->{cflags} = $1;
+ /^CPU-Type:\s*(.+)\s*$/ and $target->{cputype} = $1;
+ /^Linux-Version:\s*(.+)\s*$/ and $target->{version} = $1;
+ /^Linux-Release:\s*(.+)\s*$/ and $target->{release} = $1;
+ /^Linux-Kernel-Arch:\s*(.+)\s*$/ and $target->{karch} = $1;
+ /^Default-Subtarget:\s*(.+)\s*$/ and $target->{def_subtarget} = $1;
+ /^Default-Packages:\s*(.+)\s*$/ and $target->{packages} = [ split(/\s+/, $1) ];
+ /^Target-Profile:\s*(.+)\s*$/ and do {
+ $profile = {
+ id => $1,
+ name => $1,
+ priority => 999,
+ packages => []
+ };
+ $1 =~ /^DEVICE_/ and $target->{has_devices} = 1;
+ push @{$target->{profiles}}, $profile;
+ };
+ /^Target-Profile-Name:\s*(.+)\s*$/ and $profile->{name} = $1;
+ /^Target-Profile-Priority:\s*(\d+)\s*$/ and do {
+ $profile->{priority} = $1;
+ $target->{sort} = 1;
+ };
+ /^Target-Profile-Packages:\s*(.*)\s*$/ and $profile->{packages} = [ split(/\s+/, $1) ];
+ /^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline(*FILE);
+ }
+ close FILE;
+ foreach my $target (@target) {
+ if (@{$target->{subtargets}} > 0) {
+ $target->{profiles} = [];
+ next;
+ }
+ @{$target->{profiles}} > 0 or $target->{profiles} = [
+ {
+ id => 'Default',
+ name => 'Default',
+ packages => []
+ }
+ ];
+
+ $target->{sort} and @{$target->{profiles}} = sort {
+ $a->{priority} <=> $b->{priority} or
+ $a->{name} cmp $b->{name};
+ } @{$target->{profiles}};
+ }
+ return @target;
+}
+