FreeCalypso > hg > ffs-editor
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); +}