-###########################################################
-### SMB Build System ###
-### - config.mk parsing functions ###
-### ###
-### Copyright (C) Stefan (metze) Metzmacher 2004 ###
-### Released under the GNU GPL ###
-###########################################################
+# Samba Build System
+# - config.mk parsing functions
+#
+# Copyright (C) Stefan (metze) Metzmacher 2004
+# Copyright (C) Jelmer Vernooij 2005
+# Released under the GNU GPL
+#
-package config_mk;
+package smb_build::config_mk;
use smb_build::input;
+use File::Basename;
use strict;
-my %attribute_types = (
- "NOPROTO" => "bool",
- "REQUIRED_SUBSYSTEMS" => "list",
- "OUTPUT_TYPE" => "string",
- "INIT_OBJ_FILES" => "list",
- "ADD_OBJ_FILES" => "list",
- "OBJ_FILES" => "list",
- "SUBSYSTEM" => "string",
- "CFLAGS" => "list",
- "CPPFLAGS" => "list",
- "LDFLAGS" => "list",
- "INSTALLDIR" => "string",
- "LIBS" => "list",
- "INIT_FUNCTION" => "string",
- "MAJOR_VERSION" => "string",
- "MINOR_VERSION" => "string",
- "RELEASE_VERSION" => "string",
- "ENABLE" => "bool",
- "CMD" => "string",
- "MANPAGE" => "string"
-);
+my $section_types = {
+ "EXT_LIB" => {
+ "LIBS" => "list",
+ "CFLAGS" => "list",
+ "CPPFLAGS" => "list",
+ "LDFLAGS" => "list",
+ },
+ "SUBSYSTEM" => {
+ "OBJ_FILES" => "list",
+
+ "REQUIRED_SUBSYSTEMS" => "list",
+
+ "ENABLE" => "bool",
+ "NOPROTO" => "bool",
+
+ "MANPAGE" => "string",
+
+ "PUBLIC_PROTO_HEADER" => "string",
+ "PRIVATE_PROTO_HEADER" => "string",
+
+ "PUBLIC_HEADERS" => "list",
+ },
+ "MODULE" => {
+ "SUBSYSTEM" => "string",
+
+ "INIT_FUNCTION" => "string",
+ "OBJ_FILES" => "list",
+
+ "REQUIRED_SUBSYSTEMS" => "list",
+
+ "ENABLE" => "bool",
+ "NOPROTO" => "bool",
+
+ "OUTPUT_TYPE" => "string",
+
+ "MANPAGE" => "string",
+ "PRIVATE_PROTO_HEADER" => "string"
+ },
+ "BINARY" => {
+ "OBJ_FILES" => "list",
+
+ "REQUIRED_SUBSYSTEMS" => "list",
+
+ "ENABLE" => "bool",
+ "NOPROTO" => "bool",
+
+ "MANPAGE" => "string",
+ "INSTALLDIR" => "string",
+ "PRIVATE_PROTO_HEADER" => "string",
+ "PUBLIC_HEADERS" => "string"
+ },
+ "LIBRARY" => {
+ "MAJOR_VERSION" => "string",
+ "MINOR_VERSION" => "string",
+ "RELEASE_VERSION" => "string",
+
+ "INIT_FUNCTION_TYPE" => "string",
+
+ "OBJ_FILES" => "list",
+
+ "DESCRIPTION" => "string",
+
+ "REQUIRED_SUBSYSTEMS" => "list",
+
+ "ENABLE" => "bool",
+ "NOPROTO" => "bool",
+
+ "MANPAGE" => "string",
+
+ "PUBLIC_HEADERS" => "list",
+
+ "PUBLIC_PROTO_HEADER" => "string",
+ "PRIVATE_PROTO_HEADER" => "string"
+ }
+};
+
+use vars qw(@parsed_files);
+
+@parsed_files = ();
###########################################################
# The parsing function which parses the file
#
# $filename - the path of the config.mk file
# which should be parsed
-#
-# $result - the resulting structure
-#
-# $result->{ERROR_CODE} - the error_code, '0' means success
-# $result->{ERROR_STR} - the error string
-#
-# $result->{$key}{KEY} - the key == the variable which was parsed
-# $result->{$key}{VAL} - the value of the variable
-sub _parse_config_mk($)
+sub run_config_mk($$$)
{
- my $filename = shift;
+ sub run_config_mk($$$);
+ my ($input, $srcdir, $filename) = @_;
my $result;
my $linenum = -1;
- my $waiting = 0;
+ my $infragment = 0;
my $section = "GLOBAL";
- my $key;
-
- $result->{ERROR_CODE} = -1;
+ my $makefile = "";
- open(CONFIG_MK, "< $filename") || die ("Can't open $filename\n");
+ push (@parsed_files, $srcdir."/".$filename);
+
+ open(CONFIG_MK, $srcdir."/".$filename) or die("Can't open `$srcdir/$filename'\n");
+ my @lines = <CONFIG_MK>;
+ close(CONFIG_MK);
- while (<CONFIG_MK>) {
- my $line = $_;
- my $val;
+ my $line = "";
+ my $prev = "";
+ foreach (@lines) {
$linenum++;
- #
- # lines beginnig with '#' are ignored
- #
- if ($line =~ /^\#.*$/) {
+ # lines beginning with '#' are ignored
+ next if (/^\#.*$/);
+
+ if (/^(.*)\\$/) {
+ $prev .= $1;
next;
+ } else {
+ $line = "$prev$_";
+ $prev = "";
}
- #
- #
- #
- if (($waiting == 0) && ($line =~ /^\[([a-zA-Z0-9_:]+)\][\t ]*$/)) {
+ if ($line =~ /^\[([a-zA-Z0-9_:]+)\][\t ]*$/)
+ {
$section = $1;
+ $infragment = 0;
next;
}
-
- #
- # 1.) lines with an alphanumeric character indicate
- # a new variable,
- # 2.) followed by zero or more whitespaces or tabs
- # 3.) then one '=' character
- # 4.) followed by the value of the variable
- # 5.) a newline ('\n') can be escaped by a '\' before the newline
- # and the next line needs to start with a tab ('\t')
- #
- if (($waiting == 0) && ($line =~ /^([a-zA-Z0-9_]+)[\t ]*=(.*)$/)) {
- $key = $1;
- $val = $2;
-
- #
- # when we have a '\' before the newline
- # then skip it and wait for the next line.
- #
- if ($val =~ /(.*)(\\)$/) {
- $val = $1;
- $waiting = 1;
- } else {
- $waiting = 0;
- }
- $result->{$section}{$key}{KEY} = $key;
- $result->{$section}{$key}{VAL} = $val;
+ # include
+ if ($line =~ /^include (.*)$/) {
+ $makefile .= run_config_mk($input, $srcdir, dirname($filename)."/$1");
next;
}
- #
- # when we are waiting for a value to continue then
- # check if it has a leading tab.
- #
- if (($waiting == 1) && ($line =~ /^\t(.*)$/)) {
- $val = $1;
-
- #
- # when we have a '\' before the newline
- # then skip it and wait for the next line.
- #
- if ($val =~ /(.*)( \\)$/) {
- $val = $1;
- $waiting = 1;
- } else {
- $waiting = 0;
- }
-
- $result->{$section}{$key}{VAL} .= " ";
- $result->{$section}{$key}{VAL} .= $val;
+ # empty line
+ if ($line =~ /^[ \t]*$/) {
+ $section = "GLOBAL";
+ if ($infragment) { $makefile.="\n"; }
next;
}
- #
- # catch empty lines they're ignored
- # and we're no longer waiting for the value to continue
- #
- if ($line =~ /^$/) {
- $waiting = 0;
+ # global stuff is considered part of the makefile
+ if ($section eq "GLOBAL") {
+ if (!$infragment) { $makefile.="\n"; }
+ $makefile .= $line;
+ $infragment = 1;
next;
}
- close(CONFIG_MK);
-
- $result->{ERROR_STR} = "Bad line while parsing $filename\n$filename:$linenum: $line";
+
+ # Assignment
+ if ($line =~ /^([a-zA-Z0-9_]+)[\t ]*=(.*)$/) {
+ $result->{$section}{$1}{VAL} = $2;
+ $result->{$section}{$1}{KEY} = $1;
+
+ next;
+ }
- return $result;
+ die("$srcdir."/".$filename:$linenum: Bad line while parsing $srcdir."/".$filename");
}
- close(CONFIG_MK);
-
- $result->{ERROR_CODE} = 0;
-
- return $result;
-}
-
-sub import_file($$)
-{
- my ($input, $filename) = @_;
-
- my $result = _parse_config_mk($filename);
-
- die ($result->{ERROR_STR}) unless $result->{ERROR_CODE} == 0;
-
foreach my $section (keys %{$result}) {
- next if ($section eq "ERROR_CODE");
my ($type, $name) = split(/::/, $section, 2);
-
+
+ my $sectype = $section_types->{$type};
+ if (not defined($sectype)) {
+ die($srcdir."/".$filename.":[".$section."] unknown section type \"".$type."\"!");
+ }
+
$input->{$name}{NAME} = $name;
$input->{$name}{TYPE} = $type;
+ $input->{$name}{BASEDIR} = dirname($filename);
foreach my $key (values %{$result->{$section}}) {
$key->{VAL} = smb_build::input::strtrim($key->{VAL});
- my $vartype = $attribute_types{$key->{KEY}};
+ my $vartype = $sectype->{$key->{KEY}};
if (not defined($vartype)) {
- die("Unknown attribute $key->{KEY}");
+ die($srcdir."/".$filename.":[".$section."]: unknown attribute type \"$key->{KEY}\"!");
}
if ($vartype eq "string") {
$input->{$name}{$key->{KEY}} = $key->{VAL};
$input->{$name}{$key->{KEY}} = [smb_build::input::str2array($key->{VAL})];
} elsif ($vartype eq "bool") {
if (($key->{VAL} ne "YES") and ($key->{VAL} ne "NO")) {
- die("Invalid value for bool attribute $key->{KEY}: $key->{VAL}");
+ die("Invalid value for bool attribute $key->{KEY}: $key->{VAL} in section $section");
}
$input->{$name}{$key->{KEY}} = $key->{VAL};
}
}
}
-}
-
-sub import_files($$)
-{
- my ($input, $config_list) = @_;
-
- open(IN, $config_list) or die("Can't open $config_list: $!");
- my @mkfiles = grep{!/^#/} <IN>;
- close(IN);
- $| = 1;
-
- foreach (@mkfiles) {
- s/\n//g;
- import_file($input, $_);
- }
+ return $makefile;
}
+
1;