FreeCalypso > hg > fc-magnetite
view src/cs/layer1/tools/abc.pl @ 30:4993332e514b
atp.lib done
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 29 Sep 2016 15:29:16 +0000 |
parents | 945cf7f506b2 |
children |
line wrap: on
line source
#!/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); }