view src/cs/layer1/tools/abc.pl @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 4e78acac3d88
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);
}