diff src/cs/layer1/tools/abc.pl @ 0:92470e5d0b9e

src: partial import from FC Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 15 May 2020 01:28:16 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/layer1/tools/abc.pl	Fri May 15 01:28:16 2020 +0000
@@ -0,0 +1,492 @@
+#!/usr/bin/perl -w
+
+# This perl script is the core of a generic configuration system as
+# described in TIDKs bugzilla Bug #3 The configuration system depends
+# on a *.cfg file. This script will generate appropriate configuration
+# include files (i.e. *.h files) from the *.cfg file.
+
+# NOTE! If you think you need to edit this script, you are probably
+# wrong or I forgot something, so please email me (mmj@ti.com)
+
+# Known bugs/limitations:
+# The comment character '#' cannot be embedded within quoted strings
+
+# Notes:
+
+# A target section in the master config file can include another
+# section with a line "&SECTION". SECTION can be any section,
+# including the special sub-sections which are just like a normal
+# section but with the name prefixed by '&'. Only special thing about
+# the sub-sections is that they cannot be built and they are not shown
+# in the list printed by the -l option.
+
+# TODO:
+
+# Should we delete the configuration file for which there is no
+# corresponding lines in the master config file, e.g. if there is no
+# DSP_ lines, should we delete the dsp.cfg file?  Or should it be an
+# option (-od) Should we give a warning?
+
+# Perhaps we should check for duplicate config lines. This is
+# especially useful with the include feature, as this feature increase
+# the risk of duplicate lines. As it is now, the lines are just copied
+# into the corresponding config/*.cfg file so the compiler will
+# complain
+
+
+###############################################################################
+# Customization
+###############################################################################
+
+# none!
+
+###############################################################################
+# Globals
+###############################################################################
+
+# Full list of valid configuration prefixes
+@Prefixes = ();
+
+# Target(s) from the global cfg file to build
+@Targets = ();
+
+# Default options (overridden by command line arguments)
+$verbose = 1;     # verbosity level
+$nomake  = 0;     # don't invoke make at end of script
+$dryrun  = 0;     # don't make actual config changes.
+$listtargets = 0; # List all configs from master config
+$printconfig = 0;
+$printenv = 0;    # Print out all ENV variables that are set.
+$ConfigDir = "config"; # directory to put output config files
+$makedb = 0;      # Print out the make database to stdout (gnumake option -p)
+$MakeParams = "";
+$MakeFile = "";
+$MasterConfigFile = "";
+
+$warnings = 0;
+
+$make_name = "gmake";
+
+my %sections;
+my $line = 0;
+my $current_section = "";
+my %expanded;
+my %env_var;
+my %cfg_file;
+
+####################################################################
+# Main 
+####################################################################
+
+GetOpts();
+
+# Find the configuration file to use
+@ConfigFiles = glob("*.cfg");
+$#ConfigFiles < 0 && die "No configuration file found\n";
+
+# Check if MasterConfigFile was already set with the -f<cfg file> option
+if ($MasterConfigFile eq "") {
+    $#ConfigFiles > 0 && die "Multiple config-files found! (@ConfigFiles)\n";
+    $MasterConfigFile = $ConfigFiles[0];
+}
+
+# Find name of make file, using the basename of the master config-file
+if ($MakeFile eq "") {
+    @tmp = $MasterConfigFile =~ /(\w+)/;
+    $MakeFile = $tmp[0] . ".mak";
+}
+
+ReadMasterConfig($MasterConfigFile);
+
+if ($listtargets) { ListTargets(); }
+if ($printconfig) { PrintConfig(); }
+
+foreach $build (@Targets) {
+
+# >>>> Start Adding SB : 17/03/03
+# Add an environment variable for master.mak
+    $RFname 	= "DELIVERY_BASENAME" ;
+    $RFvalue	= $build ;
+    if ( defined( $ENV{"$RFname"} ) )
+    {
+	print STDERR "  Warning : environement vartiable $RFname already set to $ENV{\"$RFname\"} updated to $RFvalue\n" ;
+    }
+    $ENV{"$RFname"} = $RFvalue ;  # set environment variable
+# >>>> Stop Adding SB : 17/03/03
+
+    verb(2,"ExpandMasterConfig for $build\n");
+    %expanded = ();
+    ExpandMasterConfig($build);
+
+    verb(1, "Building target: $build\n");
+    Process($build);
+    if ($nomake == 0) {
+	@args = ( "$make_name", "$MakeParams", "-f", "$MakeFile" );
+	if ($makedb == 1) {
+ 	    push (@args,"-p");
+	}
+	verb(1, "Invoking make: @args \n\n");
+	system("@args");
+    }
+}
+
+
+####################################################################
+# Admin procedures
+####################################################################
+
+sub GetOpts {
+    foreach (@ARGV) {
+	if (/^-n/) { $dryrun++; }
+	if (/^-c/) { $nomake++; }
+	if (/^-p/) { $printconfig++; }
+	if (/^-d/) { $makedb++; }
+	if (/^-l/) { $listtargets++; }
+	if (/^-e/) { $printenv++; }
+	if (/^-f(\w+\.?\w*)/) { $MasterConfigFile = $1; }
+	if (/^-m(\w+\.?\w*)/) { $MakeFile = $1; }
+	if (/^-x([^\s]+)/) { 
+	    $MakeParams = $1;
+	    $MakeParams =~ tr/,/ /;
+	}
+	if (/^-o(\w+\.?\w*)/) { $ConfigDir = $1; }
+	if (/^-h|--help/) { Usage(); }
+	if (/^-v/) { $verbose++; }
+	if (/^-q/) { $verbose = -1; }
+	if (/^[^\-](\w+)/) {
+	    push (@Targets,uc($_));  # push uppercased string
+	}
+    }
+    if ($#Targets < 0) { $Targets[0] = "DEFAULT"; }
+}
+
+sub PrintConfig {
+    foreach (@Targets) {
+	unless (/\&/) { 
+            !defined($sections{$_}) && die "Target section $_ not found\n";
+            print "Target [$_]:\n";
+	    %expanded = ();
+	    ExpandSection ("$_",0,1);
+	    print "\n\n";
+	}
+    }
+    exit(0);
+}
+
+sub ListTargets {
+    print "Targets:\n";
+    foreach (sort keys %sections) {
+	unless (/\&/) { print "  [$_]\n"; }
+    }
+    exit(0);
+}
+
+sub Usage
+{
+    print <<USAGE_END;
+abc.pl v1.10. Automatic Building, Configuration and Dependencies System.
+              Copyright TI 2001.
+
+Usage: [perl] abc.pl [OPTION]... [TARGETS]...
+
+OPTIONS:
+ -h       Display this help and exit
+ -c       Only do configuration step. Do not invoke gnumake.
+ -n       Dry run. Print what is going to be done without doing it.
+ -l       List all configurations in master config file, then exit
+ -f<name> Specify which master configuration file to use.
+          Note that there must be no spaces between "-f" and the file name.
+	  Default is to use the *.cfg file from the current directory.
+ -m<name> Specify which make file use.
+          Note that there must be no spaces between "-m" and the file name.
+	  Default is to use the makefile <file>.mak file from the current
+          directory, where <file> corresponds to the basename of the
+          config file.
+ -o<name> Specify output directory name (where to put *.cfg files).
+          Default is 'config'.
+          Note that there must be no spaces between "-o" and the dir name.
+ -p       Print out contents of the specified target(s)
+ -d       Print make database (corresponds to gnumake -p)
+ -e       Print out all ENVironment variables that are set
+ -v       Be verbose (repeat several times to be more verbose)
+ -q       Be quiet
+
+ TARGETS  Name(s) of the target(s) to build.
+
+Report bugs and suggestions to mmj\@ti.com or skl\@ti.com
+USAGE_END
+# -t       Touch. Invoke make with additional parameter: -t
+    exit(0);
+}
+
+
+####################################################################
+## Core procedures
+####################################################################
+
+# Expand all section inclusions in each target
+sub ExpandMasterConfig
+{
+    my ($default_section) = @_;
+    if (defined($sections{$default_section})){
+	#print default section only
+	ExpandSection ($default_section);
+    } else {
+	#error in $default_section
+	verb (1,"Section [$default_section] is not defined in $MasterConfigFile \n");
+	exit 1;
+    }
+}
+
+ 
+sub ExpandSection
+{
+    my ($section,$level,$show);
+    my $j;
+    my $var;
+    my @values;
+    my $indent;
+    my $egal_column = 40;
+
+    ($section,$level,$show) = @_;
+
+    verb (2,"Expanding [$section]\n");
+    if (!$level){$level = 1};
+
+    $indent = "  "x$level."+- ";
+    if ($level > 9){
+	die "Including somewhat deep! Did you make a loop?\n";
+    }
+    @values = split(' ',$sections{"$_[0]"});
+    foreach $j (@values){
+	if($j =~ /^&/){
+	    if ($show){
+		print "$indent$j\n";}
+	}else{
+	    $j =~ /([^=]*)=(.*)/;
+	    $var = $1;
+	    $value = $2;
+	    $value =~ s/\#.*$//;
+	    $env_var = '';
+	    if ($var =~ /^\$/){
+		$var =~ s/^\$//;
+		$env_var = '$';
+	    }
+	    if ( exists $expanded{$var} ) {
+		print STDERR "Warning : in [$section], $env_var{$var}$var = $expanded{$var} is overwritten by $env_var$var = $value\n";
+	    }
+	    $env_var{$var} = $env_var;
+	    $expanded{$var} = $value;
+	    if ($show){
+		$line = $indent.$var;
+		$points = "."x(40-length($line)-1);
+		print "$line$points = $value\n";
+	    }
+	}
+	if ($j =~ /^&(\w*)/){
+	    ExpandSection ($1,++$level,$show);
+	    $level--;
+	}
+    }
+}
+
+
+sub ReadMasterConfig
+{
+    my ($filename)=(@_);
+
+    verb(1, "Reading master config file: $filename\n");
+    [-e $filename] || die "File $filename not found\n";
+    
+#Gather informations from master.cfg
+    open (MASTER_CFG,"$filename") || die "Can't open $filename\n";
+    while (<MASTER_CFG>){
+	
+	while (/[\r\n]$/){s/[\r\n]$//}
+	
+	#line counter
+	$line++;
+	
+	#ignore line comment
+	if (/^\s*\#/) {
+	    verb(5, "Skip: comment line \n");
+	    next};
+	
+	#ignore blank lines
+	if (/^$/) {
+	    verb(5, "Skip: empty line\n");
+	    next};
+	
+	#identify new section
+	if (/\[(\w*)\]/){
+	    $current_section = uc($1);
+	    verb(4, "Reading section: $current_section\n");
+	    if (defined($sections{"$current_section"})){
+		print STDERR "Warning [$line]: Section $current_section is already defined\n";
+		die;
+	    } else {
+		$sections{"$current_section"}="";
+	    }
+	    next;
+	}
+	
+	#add section lines
+	if ($current_section eq ""){
+	    die "Error [$line]: $filename must starts by a [section] definition\n";
+	}
+	
+	s/ //g;
+	verb(5, "Read: $_\n");
+	$sections{"$current_section"} .= " $_";
+	if (/^\$?([^_]+)_\w+\s*=\s*.*/){
+	    $Prefixes{$1}=1;
+	}
+    }
+    
+    close (MASTER_CFG);
+    verb(4, "Successfully read configuration sections\n");
+    verb(3, "\n");
+}
+
+
+sub ReadConfigFile
+{
+    my ($cfg)=(@_);
+    my (@list);
+    my ($prefix);
+
+    %cfg_file = ();
+
+    $filename = $cfg;
+    $filename =~ s@$cfg@$ConfigDir/\L$cfg\E.cfg@;
+
+    # If the file  does not exist, just return empty list
+    if (-e $filename) {
+	verb(2, "Reading current config file: $filename\n");
+    }
+    else {
+	verb(2, "Config file $filename non-existing\n");
+	return;
+    }
+
+    $protect = "";
+    open (FH, "<$filename") || die "Can't open $filename\n";
+    while (<FH>)
+    {
+	chomp;
+	if (m/\#ifndef\s*(\w+)/){
+	    $protect = $1;
+	}
+	# here we add the $cfg prefix to each line
+	if (m/\#define\s*([^ ]+)\s*(.*)/) {
+	    $var = $1;
+	    $val = $2;
+	    if ($var =~ /$protect/i){
+		verb(6,"Ignore $protect define\n");
+		next;
+	    }
+	    verb(5, "Read: $var=$val\n");
+	    $cfg_file{"${cfg}_$var"}=$val;
+	}
+    }
+    close (FH) || die "Can't close $filename\n";
+}
+
+
+sub Process
+{
+    if (-e $ConfigDir) {
+        -d $ConfigDir || die "'$ConfigDir' is a file, should be a directory!\n";
+    }
+    else {
+        verb(4, "Config-dir $ConfigDir not found - creating it...\n");
+        @args = ("mkdir", "$ConfigDir");
+        system("@args");
+    }
+
+    foreach $cfg (keys (%Prefixes)){
+	$update = 0;
+	ReadConfigFile($cfg);
+	verb (2,"File read\n");
+	foreach $i (keys(%expanded)){
+	    if ($i =~ /^${cfg}_/){
+		if (defined($cfg_file{$i})) {
+		    if ($cfg_file{$i} ne $expanded{$i}){
+			$update = 1;
+		    }
+		    delete $cfg_file{$i};
+		    
+		} else {
+		    $update = 1;
+		}
+	    }
+	}
+	if (keys(%cfg_file) > 0){
+	    verb (2,"Some variables are deleted.\n");
+	    $update = 1;
+	}
+	#update ENV vars and cfg files
+	if ($update && !$dryrun) {
+	    open (FH, ">$filename") || die "Can't open $filename\n";
+	    print FH "#ifndef __$cfg\_CFG__\n";
+	    print FH "#define __$cfg\_CFG__\n";
+	}
+	foreach $i (sort (keys(%expanded))){
+	    if ($i =~ /^${cfg}_/){
+		$var = $i;
+		$var =~ s/^${cfg}_//;
+		if ($update && !$dryrun){
+		    print FH "#define $var $expanded{$i}\n";
+		}
+		if ($env_var{$i}){
+		    if (exists $ENV{$var}){
+			verb(1,"Warning environnement varaible is already set to $ENV{$i} in the system and is overwritten by $expanded{$i}\n");}
+		    $ENV{$var}=$expanded{$i};
+		    verb (2,"Setting $var environnement variable to $ENV{$var}\n");
+		}
+	    }
+	}
+	if ($update && !$dryrun) {
+	    print FH "#endif /* __$cfg\_CFG__ \*/ \n";
+	    close (FH) || die "Can't close $filename\n";
+	}   
+	if ($update){
+	    verb(2, "Updating $filename.\n");
+	} else {
+	    verb (2,"$cfg file leaved untouched.\n");
+	}
+    }
+}
+
+
+
+
+# Print trace message (without indentation if $level < 0)
+sub verb
+{
+    my ($level, $str) = @_;
+    my ($indent) = 0;
+    if ($level < 0) {
+	$level = -$level;
+    }
+    else {
+	$indent = ($level || 1) - 1;
+    }
+    if ($verbose >= $level) {
+	print "  " x $indent . $str;
+    }
+}
+
+sub warning
+{
+    my ($str) = @_;
+    print STDERR "WARNING: $str";
+    $warnings++;
+}
+
+sub error
+{
+    my ($str) = @_;
+    print STDERR "ERROR: $str";
+    exit(1);
+}