--- /dev/null
+src-svn packages https://svn.openwrt.org/openwrt/packages
+src-svn xwrt http://svn.berlios.de/svnroot/repos/xwrt/trunk/package
include $(TOPDIR)/include/verbose.mk
TMP_DIR:=$(TOPDIR)/tmp
-all: tmp/.$(SCAN_TARGET)
+all: $(TMP_DIR)/.$(SCAN_TARGET)
include $(TOPDIR)/include/host.mk
SCAN_TARGET ?= packageinfo
SCAN_NAME ?= package
SCAN_DIR ?= package
-TARGET_STAMP:=tmp/info/.files-$(SCAN_TARGET).stamp
-FILELIST:=tmp/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE)
+TARGET_STAMP:=$(TMP_DIR)/info/.files-$(SCAN_TARGET).stamp
+FILELIST:=$(TMP_DIR)/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE)
ifeq ($(IS_TTY),1)
define progress
endif
define PackageDir
- tmp/.$(SCAN_TARGET): tmp/info/.$(SCAN_TARGET)-$(1)
- tmp/info/.$(SCAN_TARGET)-$(1): $(SCAN_DIR)/$(2)/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$(1)/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$(1)/$(DEP))))
+ $(TMP_DIR)/.$(SCAN_TARGET): $(TMP_DIR)/info/.$(SCAN_TARGET)-$(1)
+ $(TMP_DIR)/info/.$(SCAN_TARGET)-$(1): $(SCAN_DIR)/$(2)/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$(1)/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$(1)/$(DEP))))
{ \
$$(call progress,Collecting $(SCAN_NAME) info: $(SCAN_DIR)/$(2)) \
echo Source-Makefile: $(SCAN_DIR)/$(2)/Makefile; \
endef
$(FILELIST):
- rm -f tmp/info/.files-$(SCAN_TARGET)-*
+ rm -f $(TMP_DIR)/info/.files-$(SCAN_TARGET)-*
$(call FIND_L, $(SCAN_DIR)) $(SCAN_EXTRA) -mindepth 1 $(if $(SCAN_DEPTH),-maxdepth $(SCAN_DEPTH)) -name Makefile | xargs grep -HE 'call (Build/DefaultTargets|Build(Package|Target)|.+Package)' | sed -e 's#^$(SCAN_DIR)/##' -e 's#/Makefile:.*##' | uniq > $@
-tmp/info/.files-$(SCAN_TARGET).mk: $(FILELIST)
+$(TMP_DIR)/info/.files-$(SCAN_TARGET).mk: $(FILELIST)
( \
cat $< | awk '{print "$(SCAN_DIR)/" $$0 "/Makefile" }' | xargs grep -HE '^ *SCAN_DEPS *= *' | awk -F: '{ gsub(/^.*DEPS *= */, "", $$2); print "DEPS_" $$1 "=" $$2 }'; \
awk -v deps="$$DEPS" '{ \
true; \
) > $@
--include tmp/info/.files-$(SCAN_TARGET).mk
+-include $(TMP_DIR)/info/.files-$(SCAN_TARGET).mk
$(TARGET_STAMP):
( \
} \
)
-tmp/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP)
+$(TMP_DIR)/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP)
$(call progress,Collecting $(SCAN_NAME) info: merging...)
- cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "tmp/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@
+ cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "$(TMP_DIR)/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@
$(call progress,Collecting $(SCAN_NAME) info: done)
echo
SCAN_COOKIE?=$(shell echo $$$$)
export SCAN_COOKIE
+prepare-mk: FORCE ;
+
prepare-tmpinfo: FORCE
mkdir -p tmp/info
+$(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="$(TOPDIR)/include/package*.mk" SCAN_DEPTH=4 SCAN_EXTRA=""
+$(NO_TRACE_MAKE) -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="profiles/*.mk $(TOPDIR)/include/kernel*.mk" SCAN_DEPTH=2 SCAN_EXTRA="" SCAN_MAKEOPTS="TARGET_BUILD=1"
for type in package target; do \
f=tmp/.$${type}info; t=tmp/.config-$${type}.in; \
- [ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config < "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \
+ [ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \
done
- ./scripts/metadata.pl package_mk < tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
+ ./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
touch $(TOPDIR)/tmp/.build
.config: ./scripts/config/conf prepare-tmpinfo
$< -D .config Config.in
oldconfig: scripts/config/conf prepare-tmpinfo FORCE
- $< -o Config.in
+ $< -$(if $(CONFDEFAULT),$(CONFDEFAULT),o) Config.in
menuconfig: scripts/config/mconf prepare-tmpinfo FORCE
if [ \! -f .config -a -e $(HOME)/.openwrt/defconfig ]; then \
}
case ask_all:
case ask_new:
- conf_read(NULL);
- break;
case set_no:
case set_mod:
case set_yes:
case set_random:
- name = getenv("KCONFIG_ALLCONFIG");
- if (name && !stat(name, &tmpstat)) {
- conf_read_simple(name);
- break;
- }
- switch (input_mode) {
- case set_no: name = "allno.config"; break;
- case set_mod: name = "allmod.config"; break;
- case set_yes: name = "allyes.config"; break;
- case set_random: name = "allrandom.config"; break;
- default: break;
- }
- if (!stat(name, &tmpstat))
- conf_read_simple(name);
- else if (!stat("all.config", &tmpstat))
- conf_read_simple("all.config");
+ conf_read(NULL);
break;
default:
break;
--- /dev/null
+#!/usr/bin/perl
+use Getopt::Std;
+use FindBin;
+use Cwd;
+use lib "$FindBin::Bin";
+use metadata;
+use warnings;
+use strict;
+
+chdir "$FindBin::Bin/..";
+$ENV{TOPDIR}=getcwd();
+
+my @feeds;
+my %build_packages;
+my %installed;
+
+sub parse_config() {
+ my $line = 0;
+ my %name;
+
+ open FEEDS, "feeds.conf";
+ while (<FEEDS>) {
+ chomp;
+ s/#.+$//;
+ next unless /\S/;
+ my @line = split /\s+/, $_, 3;
+ $line++;
+
+ my $valid = 1;
+ $line[0] =~ /^src-\w+$/ or $valid = 0;
+ $line[1] =~ /^\w+$/ or $valid = 0;
+ $line[2] =~ /\s/ and $valid = 0;
+ $valid or die "Syntax error in feeds.list, line: $line\n";
+
+ $name{$line[1]} and die "Duplicate feed name '$line[1]', line: $line\n";
+ $name{$line[1]} = 1;
+
+ push @feeds, [@line];
+ }
+ close FEEDS;
+}
+
+sub update_svn($$) {
+ my $name = shift;
+ my $src = shift;
+
+ system("svn co $src ./feeds/$name") == 0 or return 1;
+ -d "./feeds/$name.tmp" or mkdir "./feeds/$name.tmp" or return 1;
+ -d "./feeds/$name.tmp/info" or mkdir "./feeds/$name.tmp/info" or return 1;
+
+ system("make -s prepare-mk TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\"");
+ system("make -s -f include/scan.mk IS_TTY=1 SCAN_TARGET=\"packageinfo\" SCAN_DIR=\"feeds/$name\" SCAN_NAME=\"package\" SCAN_DEPS=\"$ENV{TOPDIR}/include/package*.mk\" SCAN_DEPTH=4 SCAN_EXTRA=\"\" TMP_DIR=\"$ENV{TOPDIR}/feeds/$name.tmp\"");
+ system("ln -sf $name.tmp/.packageinfo ./feeds/$name.index");
+
+ return 0;
+}
+
+sub get_feed($) {
+ my $feed = shift;
+
+ clear_packages();
+ parse_package_metadata("./feeds/$feed.index") or return;
+ return { %package };
+}
+
+sub get_installed() {
+ system("make -s prepare-tmpinfo");
+ clear_packages();
+ parse_package_metadata("./tmp/.packageinfo");
+ %installed = %package;
+}
+
+sub search_feed {
+ my $feed = shift;
+ my @substr = @_;
+ my $display;
+
+ return unless @substr > 0;
+ get_feed($feed);
+ foreach my $name (sort { lc($a) cmp lc($b) } keys %package) {
+ my $pkg = $package{$name};
+ my $substr;
+ my $pkgmatch = 1;
+
+ foreach my $substr (@substr) {
+ my $match;
+ foreach my $key (qw(name title description)) {
+ $substr and $pkg->{$key} =~ m/$substr/i and $match = 1;
+ }
+ $match or undef $pkgmatch;
+ };
+ $pkgmatch and do {
+ $display or do {
+ print "Search results in feed '$feed':\n";
+ $display = 1;
+ };
+ printf "\%-25s\t\%s\n", $pkg->{name}, $pkg->{title};
+ };
+ }
+ return 0;
+}
+
+
+sub search {
+ my %opts;
+
+ getopt('r:', \%opts);
+ foreach my $feed (@feeds) {
+ search_feed($feed->[1], @ARGV) if (!defined($opts{r}) or $opts{r} eq $feed->[1]);
+ }
+}
+
+sub install_svn() {
+ my $feed = shift;
+ my $pkg = shift;
+ my $path = $pkg->{makefile};
+ $path =~ s/\/Makefile$//;
+
+ -d "./package/feeds" or mkdir "./package/feeds";
+ -d "./package/feeds/$feed->[1]" or mkdir "./package/feeds/$feed->[1]";
+ system("ln -sf ../../../$path ./package/feeds/$feed->[1]/");
+
+ return 0;
+}
+
+my %install_method = (
+ 'src-svn' => \&install_svn
+);
+
+my %feed;
+
+sub lookup_package($$) {
+ my $feed = shift;
+ my $package = shift;
+
+ foreach my $feed ($feed, @feeds) {
+ next unless $feed->[1];
+ next unless $feed{$feed->[1]};
+ $feed{$feed->[1]}->{$package} and return $feed;
+ }
+ return;
+}
+
+sub install_package {
+ my $feed = shift;
+ my $name = shift;
+ my $ret = 0;
+
+ $feed = lookup_package($feed, $name);
+ $feed or do {
+ $installed{$name} and return 0;
+ warn "WARNING: Package '$name' is not available.\n";
+ return 1;
+ };
+
+ my $pkg = $feed{$feed->[1]}->{$name} or return 1;
+ my $src = $pkg->{src};
+ my $type = $feed->[0];
+ $src or $src = $name;
+
+ # previously installed packages set the runtime package
+ # newly installed packages set the source package
+ $installed{$src} and return 0;
+
+ # install all dependencies
+ foreach my $dep (@{$pkg->{depends}}) {
+ next if $dep =~ /@/;
+ $dep =~ s/^\+//;
+ install_package($feed, $dep) == 0 or $ret = 1;
+ }
+
+ # check previously installed packages
+ $installed{$name} and return 0;
+ $installed{$src} = 1;
+ warn "Installing package '$src'\n";
+
+ $install_method{$type} or do {
+ warn "Unknown installation method: '$type'\n";
+ return 1;
+ };
+
+ &{$install_method{$type}}($feed, $pkg) == 0 or do {
+ warn "failed.\n";
+ return 1;
+ };
+
+ return $ret;
+}
+
+sub refresh_config {
+ my $default = shift;
+ $default or $default = "o";
+
+ # workaround for timestamp check
+ system("rm -f tmp/.packageinfo");
+
+ # refresh the config
+ system("make oldconfig CONFDEFAULT=\"$default\" Config.in >/dev/null 2>/dev/null");
+}
+
+sub install {
+ my $name;
+ my %opts;
+ my $feed;
+ my $ret = 0;
+
+ getopt('p:d:', \%opts);
+ get_installed();
+
+ foreach my $f (@feeds) {
+ # index all feeds
+ $feed{$f->[1]} = get_feed($f->[1]);
+
+ # look up the preferred feed
+ $opts{p} and $f->[1] eq $opts{p} and $feed = $f;
+ }
+
+ while ($name = shift @ARGV) {
+ install_package($feed, $name) == 0 or $ret = 1;
+ }
+
+ # workaround for timestamp check
+
+ # set the defaults
+ if ($opts{d} and $opts{d} =~ /^[ymn]$/) {
+ refresh_config($opts{d});
+ }
+
+ return $ret;
+}
+
+sub uninstall {
+ my $name;
+ my $uninstall;
+
+ if ($ARGV[0] eq '-a') {
+ system("rm -rf ./package/feeds");
+ $uninstall = 1;
+ } else {
+ get_installed();
+ while ($name = shift @ARGV) {
+ my $pkg = $installed{$name};
+ $pkg or do {
+ warn "WARNING: $name not installed\n";
+ next;
+ };
+ $pkg->{src} and $name = $pkg->{src};
+ warn "Uninstalling package '$name'\n";
+ system("rm -f ./package/feeds/*/$name");
+ $uninstall = 1;
+ }
+ }
+ $uninstall and refresh_config();
+ return 0;
+}
+
+sub usage() {
+ print <<EOF;
+Usage: $0 <command> [options]
+
+Commands:
+ install [options] <package>: Install a package
+ Options:
+ -p <feedname>: Prefer this feed when installing packages
+ -d <y|m|n>: Set default for newly installed packages
+
+ search [options] <substring>: Search for a package
+ Options:
+ -r <feedname>: Only search in this feed
+
+ uninstall -a|<package>: Uninstall a package
+ -a uninstalls all packages
+
+ update: Update packages and lists of feeds in feeds.list
+ clean: Remove downloaded/generated files
+
+EOF
+ exit(1);
+}
+
+my %update_method = (
+ 'src-svn' => \&update_svn
+);
+
+my %commands = (
+ 'update' => sub {
+ -d "feeds" or do {
+ mkdir "feeds" or die "Unable to create the feeds directory";
+ };
+ $ENV{SCAN_COOKIE} = $$;
+ $ENV{KBUILD_VERBOSE} = 99;
+ foreach my $feed (@feeds) {
+ my ($type, $name, $src) = @$feed;
+ $update_method{$type} or do {
+ warn "Unknown type '$type' in feed $name\n";
+ next;
+ };
+ warn "Updating feed '$name'...\n";
+ &{$update_method{$type}}($name, $src) == 0 or do {
+ warn "failed.\n";
+ return 1;
+ };
+ }
+ return 0;
+ },
+ 'install' => \&install,
+ 'search' => \&search,
+ 'uninstall' => \&uninstall,
+ 'clean' => sub {
+ system("rm -rf feeds");
+ }
+);
+
+my $arg = shift @ARGV;
+$arg or usage();
+parse_config;
+foreach my $cmd (keys %commands) {
+ $arg eq $cmd and do {
+ exit(&{$commands{$cmd}}());
+ };
+}
+usage();
#!/usr/bin/perl
+use FindBin;
+use lib "$FindBin::Bin";
use strict;
-my %preconfig;
-my %package;
-my %srcpackage;
-my %category;
-my %subdir;
-my %board;
-
-sub get_multiline {
- my $prefix = shift;
- my $str;
- while (<>) {
- last if /^@@/;
- s/^\s*//g;
- $str .= (($_ and $prefix) ? $prefix . $_ : $_);
- }
+use metadata;
- return $str;
-}
+my %board;
sub confstr($) {
my $conf = shift;
}
sub parse_target_metadata() {
- my ($target, @target, $profile);
- while (<>) {
+ my $file = shift @ARGV;
+ my ($target, @target, $profile);
+ open FILE, "<$file" or do {
+ warn "Can't open file '$file': $!\n";
+ return;
+ };
+ while (<FILE>) {
chomp;
/^Target:\s*(.+)\s*$/ and do {
$target = {
/^Target-Path:\s*(.+)\s*$/ and $target->{path} = $1;
/^Target-Arch:\s*(.+)\s*$/ and $target->{arch} = $1;
/^Target-Features:\s*(.+)\s*$/ and $target->{features} = [ split(/\s+/, $1) ];
- /^Target-Description:/ and $target->{desc} = get_multiline();
+ /^Target-Description:/ and $target->{desc} = get_multiline(*FILE);
/^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;
};
/^Target-Profile-Name:\s*(.+)\s*$/ and $profile->{name} = $1;
/^Target-Profile-Packages:\s*(.*)\s*$/ and $profile->{packages} = [ split(/\s+/, $1) ];
- /^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline();
- /^Target-Profile-Config:/ and $profile->{config} = get_multiline("\t");
+ /^Target-Profile-Description:\s*(.*)\s*/ and $profile->{desc} = get_multiline(*FILE);
+ /^Target-Profile-Config:/ and $profile->{config} = get_multiline(*FILE, "\t");
/^Target-Profile-Kconfig:/ and $profile->{kconfig} = 1;
}
+ close FILE;
foreach my $target (@target) {
@{$target->{profiles}} > 0 or $target->{profiles} = [
{
return @target;
}
-sub parse_package_metadata() {
- my $pkg;
- my $makefile;
- my $preconfig;
- my $subdir;
- my $src;
- while (<>) {
- chomp;
- /^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do {
- $makefile = $1;
- $subdir = $2;
- $src = $3;
- $subdir =~ s/^package\///;
- $subdir{$src} = $subdir;
- $srcpackage{$src} = [];
- undef $pkg;
- };
- /^Package:\s*(.+?)\s*$/ and do {
- $pkg = {};
- $pkg->{src} = $src;
- $pkg->{makefile} = $makefile;
- $pkg->{name} = $1;
- $pkg->{default} = "m if ALL";
- $pkg->{depends} = [];
- $pkg->{builddepends} = [];
- $pkg->{subdir} = $subdir;
- $package{$1} = $pkg;
- push @{$srcpackage{$src}}, $pkg;
- };
- /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
- /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
- /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
- /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
- /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
- /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
- /^Provides: \s*(.+)\s*$/ and do {
- my @vpkg = split /\s+/, $1;
- foreach my $vpkg (@vpkg) {
- $package{$vpkg} or $package{$vpkg} = { vdepends => [] };
- push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
- }
- };
- /^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ];
- /^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ];
- /^Category: \s*(.+)\s*$/ and do {
- $pkg->{category} = $1;
- defined $category{$1} or $category{$1} = {};
- defined $category{$1}->{$src} or $category{$1}->{$src} = [];
- push @{$category{$1}->{$src}}, $pkg;
- };
- /^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline("\t\t ");
- /^Config: \s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline();
- /^Prereq-Check:/ and $pkg->{prereq} = 1;
- /^Preconfig:\s*(.+)\s*$/ and do {
- my $pkgname = $pkg->{name};
- $preconfig{$pkgname} or $preconfig{$pkgname} = {};
- if (exists $preconfig{$pkgname}->{$1}) {
- $preconfig = $preconfig{$pkgname}->{$1};
- } else {
- $preconfig = {
- id => $1
- };
- $preconfig{$pkgname}->{$1} = $preconfig;
- }
- };
- /^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1;
- /^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1;
- /^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1;
- }
- return %category;
-}
-
sub gen_kconfig_overrides() {
my %config;
my %kconfig;
print "endchoice\n";
}
-
-sub find_package_dep($$) {
+my %dep_check;
+sub __find_package_dep($$) {
my $pkg = shift;
my $name = shift;
my $deps = ($pkg->{vdepends} or $pkg->{depends});
return 0 unless defined $deps;
foreach my $dep (@{$deps}) {
+ next if $dep_check{$dep};
+ $dep_check{$dep} = 1;
return 1 if $dep eq $name;
- return 1 if ($package{$dep} and (find_package_dep($package{$dep},$name) == 1));
+ return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1));
}
return 0;
}
+# wrapper to avoid infinite recursion
+sub find_package_dep($$) {
+ my $pkg = shift;
+ my $name = shift;
+
+ %dep_check = ();
+ return __find_package_dep($pkg, $name);
+}
+
sub package_depends($$) {
my $a = shift;
my $b = shift;
}
sub gen_package_config() {
- parse_package_metadata();
+ parse_package_metadata($ARGV[0]) or exit 1;
print "menuconfig UCI_PRECONFIG\n\tbool \"Image configuration\"\n";
foreach my $preconfig (keys %preconfig) {
foreach my $cfg (keys %{$preconfig{$preconfig}}) {
my %dep;
my $line;
- parse_package_metadata();
+ parse_package_metadata($ARGV[0]) or exit 1;
foreach my $name (sort {uc($a) cmp uc($b)} keys %package) {
my $config;
my $pkg = $package{$name};
--- /dev/null
+package metadata;
+use base 'Exporter';
+use strict;
+use warnings;
+our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig clear_packages parse_package_metadata get_multiline);
+
+our %package;
+our %preconfig;
+our %srcpackage;
+our %category;
+our %subdir;
+
+sub get_multiline {
+ my $fh = shift;
+ my $prefix = shift;
+ my $str;
+ while (<$fh>) {
+ last if /^@@/;
+ s/^\s*//g;
+ $str .= (($_ and $prefix) ? $prefix . $_ : $_);
+ }
+
+ return $str ? $str : "";
+}
+
+sub clear_packages() {
+ %subdir = ();
+ %preconfig = ();
+ %package = ();
+ %srcpackage = ();
+ %category = ();
+}
+
+sub parse_package_metadata($) {
+ my $file = shift;
+ my $pkg;
+ my $makefile;
+ my $preconfig;
+ my $subdir;
+ my $src;
+
+ open FILE, "<$file" or do {
+ warn "Cannot open '$file': $!\n";
+ return undef;
+ };
+ while (<FILE>) {
+ chomp;
+ /^Source-Makefile: \s*((.+\/)([^\/]+)\/Makefile)\s*$/ and do {
+ $makefile = $1;
+ $subdir = $2;
+ $src = $3;
+ $subdir =~ s/^package\///;
+ $subdir{$src} = $subdir;
+ $srcpackage{$src} = [];
+ undef $pkg;
+ };
+ /^Package:\s*(.+?)\s*$/ and do {
+ $pkg = {};
+ $pkg->{src} = $src;
+ $pkg->{makefile} = $makefile;
+ $pkg->{name} = $1;
+ $pkg->{default} = "m if ALL";
+ $pkg->{depends} = [];
+ $pkg->{builddepends} = [];
+ $pkg->{subdir} = $subdir;
+ $package{$1} = $pkg;
+ push @{$srcpackage{$src}}, $pkg;
+ };
+ /^Version: \s*(.+)\s*$/ and $pkg->{version} = $1;
+ /^Title: \s*(.+)\s*$/ and $pkg->{title} = $1;
+ /^Menu: \s*(.+)\s*$/ and $pkg->{menu} = $1;
+ /^Submenu: \s*(.+)\s*$/ and $pkg->{submenu} = $1;
+ /^Submenu-Depends: \s*(.+)\s*$/ and $pkg->{submenudep} = $1;
+ /^Default: \s*(.+)\s*$/ and $pkg->{default} = $1;
+ /^Provides: \s*(.+)\s*$/ and do {
+ my @vpkg = split /\s+/, $1;
+ foreach my $vpkg (@vpkg) {
+ $package{$vpkg} or $package{$vpkg} = { vdepends => [] };
+ push @{$package{$vpkg}->{vdepends}}, $pkg->{name};
+ }
+ };
+ /^Depends: \s*(.+)\s*$/ and $pkg->{depends} = [ split /\s+/, $1 ];
+ /^Build-Depends: \s*(.+)\s*$/ and $pkg->{builddepends} = [ split /\s+/, $1 ];
+ /^Category: \s*(.+)\s*$/ and do {
+ $pkg->{category} = $1;
+ defined $category{$1} or $category{$1} = {};
+ defined $category{$1}->{$src} or $category{$1}->{$src} = [];
+ push @{$category{$1}->{$src}}, $pkg;
+ };
+ /^Description: \s*(.*)\s*$/ and $pkg->{description} = "\t\t $1\n". get_multiline(*FILE, "\t\t ");
+ /^Config: \s*(.*)\s*$/ and $pkg->{config} = "$1\n".get_multiline(*FILE);
+ /^Prereq-Check:/ and $pkg->{prereq} = 1;
+ /^Preconfig:\s*(.+)\s*$/ and do {
+ my $pkgname = $pkg->{name};
+ $preconfig{$pkgname} or $preconfig{$pkgname} = {};
+ if (exists $preconfig{$pkgname}->{$1}) {
+ $preconfig = $preconfig{$pkgname}->{$1};
+ } else {
+ $preconfig = {
+ id => $1
+ };
+ $preconfig{$pkgname}->{$1} = $preconfig;
+ }
+ };
+ /^Preconfig-Type:\s*(.*?)\s*$/ and $preconfig->{type} = $1;
+ /^Preconfig-Label:\s*(.*?)\s*$/ and $preconfig->{label} = $1;
+ /^Preconfig-Default:\s*(.*?)\s*$/ and $preconfig->{default} = $1;
+ }
+ close FILE;
+ return %category;
+}
+
+1;