#!perl -w
# 05/10/2008 - Part of a series of Perl scripts to compare and show changes
# in the build files of FlightGear and SimGear
# 05/10/2008 - specialised SCAN of VCPROJ file

# DEBUG
my $dbg_v01 = 0;    # show each line - prt( "$lnnum:$xln:".scalar @tag_stack.": $tag [$line]
my $dbg_v02 = 0;    # show prt( "$lnnum:$xln: tag=$tag, Name=$pname
my $dbg_v03 = 0;    # show sources - prt( "$lnnum:$xln: [$adddefs] $tmp source
my $dbg_v04 = 0;    # show prt( "$lnnum:$xln: processing inconfig '$conf' '$pname' [$line]
my $dbg_v05 = 0;    # show prt("$lnnum:$xln: Set APPTYPE:$conf: from $apptype, to $ppdefs - CHECK!
my $dbg_v06 = 0;    # show prt("$lnnum:$xln: Got APPTYPE:$conf: NO CHANGE [$apptype] equals SubSystem ($adddeps) [".$v8_subsystems{$adddeps}."] ...
my $dbg_v07 = 0;    # show prt( "$lnnum:$xln: Entering Configurations [$line] and EXIT
my $dbg_v08 = 0;    # show prt( "$lnnum:$xln: Entering Configuration [$conf]... [$line] and EXIT
my $dbg_v09 = 0;    # show prt( "$lnnum:$xln: Entering Files [$line] and EXIT
my $dbg_v10 = 0;    # show prt( "$lnnum:$xln: 'VCCLCompilerTool' [$line]
my $dbg_v11 = 0;    # show prt( "$lnnum:$xln: ENTER Filter name=[$fname] list=[$flist]
my $dbg_v12 = 0;    # show prt( "$lnnum:$xln: Entering FileConfiguration [$line]
my $dbg_v13 = 0;    # show prt( "ADVICE:$lnnum:$xln: 'VCCLCompilerTool' DOES NOT CONTAIN(1) '$seek' [$line]
my $dbg_v14 = 0;    # show prt( "$lnnum:$xln: last = $last_src [".$$src_ref[-1][0]."] $fconf $seek = $adddefs
my $dbg_v15 = 0;    # show prt( "$lnnum:$xln: got POST event [$ppdefs]
my $dbg_v16 = 0;    # for AdditionalDependencies and 'AdditionalLibraryDirectories'
#  show prtw( "WARNING:$lnnum:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(4) & (6) '$seek' [$line]
my $dbg_v17 = 0;    # show prtw( "WARNING: $lnnum:$xln: DOES NOT CONTAIN(12) '$seek'? [$line]\n"
my $dbg_v18 = 0;    # show prtw( "WARNING:$lnnum:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(7) '$seek' [$line]
my $dbg_v19 = 0;    # show prt( "$lnnum:$xln: Changed(1) $seek from [".$dsp_current_sub{$var1}."] to [$adddeps]
my $dbg_v20 = 0;    # show prt( "$lnnum:$xln: Changed(2) $seek from [".$dsp_current_sub{$var2}."] to [$adddeps]

sub dbg_show_entering_files { $dbg_v09 = 1; }
sub dbg_show_source_files { $dbg_v03 = 1; }

sub show_hash_results {
    my ($dbg, $rh) = @_;
    my ($key, $val, @arr, $itm, $icnt, $i, $msg, $len, $src, $grp, $nm, $dir, $ext);
    my ($iia, $wmsg);
    my @srcs = ();
    my @fsrcs = ();
    foreach $key (sort keys(%{$rh}) ) {
        $val = $$rh{$key};
        $len = length($val);
        if (($key eq 'C_SOURCES')||($key eq 'H_SOURCES')) {
            $icnt = scalar @{$val};
            $msg = "$key count $icnt sources ...";
            prt( "$msg ($icnt)\n" );
            $msg = '';
            # push(@vc_c_sources,[$adddefs, $fname, $flist]);
            for ($i = 0; $i < $icnt; $i++) {
                $src = $$val[$i][0];
                ($nm,$dir,$ext) = fileparse( $src, qr/\.[^.]*/ );
                $nm = lc($nm);
                $iia = is_in_array($nm,@srcs); 
                if ($iia) {
                    if (is_c_source($src)) {
                        $wmsg = "WARNING: Duplicate [$src]! ";
                        $wmsg .= "SEE [".$fsrcs[$iia-1]."]";
                        prtw( "$wmsg\n" );
                    }
                } else {
                    push(@srcs,$nm);
                    push(@fsrcs,$src);
                }
                $grp = $$val[$i][1];
                $msg .= "\n" if length($msg);
                $msg .= $src;
                $msg .= " [$grp]";
                ###$msg .= ' '.$$val[$i][2];
            }
            if ($dbg & 4) {
                prt( "$msg\n" );
            }
        } else {
            @arr = space_split($val);
            $icnt = scalar @arr;
            $msg = "$key = [";
            if ($len < 70) {
                $msg .= "$val]";
            } else {
                $msg .= "$val]";
            }
            $msg .= " $icnt items...";
            prt( "$msg\n" );
            $msg = '';
            if ($dbg & 1) {
                for ($i = 0; $i < $icnt; $i++) {
                    $itm = $arr[$i];
                    if ($itm =~ /^\//) {
                        # /I or /D
                    } else {
                        # other ...
                    }
                }
            }
        }
    }
}

sub process_VCPROJ {
    my ($fil) = shift;
    $act_vcproj = $fil;
    my (@lines, $xlncnt, $lncnt, $lnnum, $xln, $line, $tag);
    my (@attribs, %atthash, %lnmap);
    my ($pname, $adddeps, $adddefs, $ppdefs);
    my ($var1, $var2, $var3, $seek, $tmp);
    my %dsp_current_sub = get_default_sub(); # copy the DEFAULTS
    if (open INF, "<$fil") {
        %lnmap = ();
        @lines = <INF>;
        close INF;
        $xlncnt = scalar @lines;
        @lines = fg_xml_to_lines(\%lnmap, @lines);
        $lncnt = scalar @lines;
        $lnnum = 0;
        prt( "\nProcessing file [$fil], $lncnt lines ($xlncnt) ...\n" );
        my $invcproj = 0;
        my @tag_stack = ();
        my $inconfigs = 0;
        my $inconfig = 0;
        my $apptype = '';
        my $dnaptype = 0;
        my $conf = '';
        my $infiles = 0;
        my $infile = 0;
        my $fname = '';
        my $flist = '';
        my $infilt = 0;
        my $projname = '';
        my $fconf = ''; # FileConfiguration
        my $infconf = 0; # in FileConfiguration
        my @vc_c_sources = ();
        my @vc_h_sources = ();
        my $src_ref = \@vc_c_sources;
        my $last_src = '';
        foreach $line (@lines) {
            $lnnum++;
            $xln = $lnmap{$lnnum};
            @attribs = space_split($line);
            %atthash = array_2_hash_on_equals(@attribs);
            $tag = $attribs[0];
            $pname = '';
            if (defined $atthash{'Name'}) {
                $pname = strip_quotes(trim_all($atthash{'Name'}));
                prt( "$lnnum:$xln: tag=$tag, Name=$pname\n" ) if ($dbg_v02);
            }
            if ($invcproj) {
                if ($tag =~ /<\/VisualStudioProject/) {
                    $invcproj = 0;
                    ##pop @tag_stack;
                } else {
                    # in VCPROJ file
                    if ($line =~ /\/>$/) {
                        # begin and end tag line
                    } elsif ($line =~ /^<\//) {
                        if (! @tag_stack) {
                            prtw( "Close WITHOUT stacked tag! [$line]\n" );
                        } else {
                            pop @tag_stack;
                        }
                    } else {
                        push(@tag_stack,$tag);
                    }
                    if ($inconfigs) {
                        if ($tag =~ /<\/Configurations/) {
                            $inconfigs = 0;
                            prt( "$lnnum:$xln: Exit Configurations [$line]\n" ) if ($dbg_v07);
                        } else {
                            # in configurations section
                            if ($inconfig) {
                                # in a specific config
                                if ($line =~ /^<\/Configuration/) {
                                    $inconfig = 0;
                                    prt( "$lnnum:$xln: Exit Configuration [$conf]... [$line] ...\n" ) if ($dbg_v08);
                                } else {
                                    # processing a Configuration in Configurations
                                    prt( "$lnnum:$xln: processing inconfig '$conf' '$pname' [$line]\n" ) if ($dbg_v04);
                                    if ($line =~ /<Tool\s+/ ) {
                                        if ($pname eq 'VCCLCompilerTool') {
                                            if ($conf =~ /Debug/i) {
                                                $var1 = '-NEW_INCS_DBG-';
                                                $var2 = '-NEW_DEFS_DBG-';
                                                $var3 = '-NEW_RT_DBG-';
                                            } else {
                                                $var1 = '-NEW_INCS_REL-';
                                                $var2 = '-NEW_DEFS_REL-';
                                                $var3 = '-NEW_RT_REL-';
                                                if (!($conf =~ /Release/i)) {
                                                    prtw( "WARNING:$lnnum:$xln: pname=[$conf] NOT Debug or Release - def to REL!\n" );
                                                }
                                            }
                                            prt( "$lnnum:$xln: 'VCCLCompilerTool' [$line]\n" ) if ($dbg_v10);                                            # <Tool
                                            # Name="VCCLCompilerTool"
                                            # Optimization="0"
                                            # AdditionalIncludeDirectories="../lib,../lib/curl_transport,...
                                            # PreprocessorDefinitions="_DEBUG;WIN32;_LIB;ABYSS_WIN32;CURL_STATICLIB" 
                                            # MinimalRebuild="true" 
                                            # BasicRuntimeChecks="3" 
                                            # RuntimeLibrary="1" 
                                            # PrecompiledHeaderFile=".\Debug\xmlrpccpp/xmlrpccpp.pch" 
                                            # AssemblerListingLocation=".\Debug\xmlrpccpp/" 
                                            # ObjectFile=".\Debug\xmlrpccpp/" 
                                            # ProgramDataBaseFileName=".\Debug\xmlrpccpp/" 
                                            # WarningLevel="3" 
                                            # SuppressStartupBanner="true" 
                                            # DebugInformationFormat="4" />]
                                            # WATCHOUT FOR 
                                            # AdditionalIncludeDirectories="..\..;&quot;..\..\..\zlib-1.2.3&quot;"

                                            $seek = 'AdditionalIncludeDirectories'; # -NEW_INCS_[DBG|REL]-
                                            if ( defined $atthash{$seek} ) {
                                                $ppdefs = strip_quotes(trim_all($atthash{$seek}));
                                                $ppdefs =~ s/&quot;/"/g;
                                                $dsp_current_sub{$var1} = get_includes_string($ppdefs);
                                            } else {
                                                $dsp_current_sub{$var1} = '';
                                                prt( "ADVICE:$lnnum:$xln: 'VCCLCompilerTool' DOES NOT CONTAIN(1) '$seek' [$line]\n" ) if ($dbg_v13);
                                            }

                                            $seek = 'PreprocessorDefinitions';
                                            if ( defined $atthash{$seek} ) {
                                                $ppdefs = strip_quotes(trim_all($atthash{$seek}));
                                                $dsp_current_sub{$var2} = get_defines_string($ppdefs);
                                            } else {
                                                prtw( "WARNING:$lnnum:$xln: 'VCCLCompilerTool' DOES NOT CONTAIN(2) '$seek' [$line]\n" );
                                            }

                                            $seek = 'RuntimeLibrary';
                                            if ( defined $atthash{$seek} ) {
                                                $ppdefs = strip_quotes(trim_all($atthash{$seek}));
                                                $dsp_current_sub{$var3} = fg_get_runtime_val_2_lts($ppdefs);
                                            } else {
                                                prtw( "WARNING:$lnnum:$xln: 'VCCLCompilerTool' DOES NOT CONTAIN(3) '$seek' [$line]\n" );
                                            }
                                        } elsif ($pname eq 'VCLinkerTool') {
                                            if ($conf =~ /Debug/i) {
                                                $var1 = '-NEW_LIBS_DBG-';
                                                $var2 = '-NEW_OUT_DBG-';

                                            } else {
                                                $var1 = '-NEW_LIBS_REL-';
                                                $var2 = '-NEW_OUT_REL-';
                                            }
                                            # <Tool
                                            #  Name="VCLinkerTool"
                                            #  LinkLibraryDependencies="false"
                                            #  AdditionalDependencies="wsock32.lib SimGear.lib sg_d.lib ... "
                                            #  OutputFile="..\bin\FlightGearD.exe"
                                            #  LinkIncremental="0"
                                            #  SuppressStartupBanner="true"
                                            #  AdditionalLibraryDirectories="..\SimGear\$(IntDir); ..\PLIB, ..."
                                            #  IgnoreDefaultLibraryNames=""
                                            #  GenerateDebugInformation="true"
                                            #  ProgramDatabaseFile=".\Debug/FlightGear.pdb"
                                            #  SubSystem="1"
                                            #  RandomizedBaseAddress="1"
                                            #  DataExecutionPrevention="0"
                                            #  TargetMachine="1" />
                                            $seek = 'AdditionalDependencies';
                                            if (defined $atthash{$seek} ) {
                                                $adddeps = strip_quotes(trim_all($atthash{$seek}));
                                                $dsp_current_sub{$var1} = $adddeps;
                                            } else {
                                                prtw( "WARNING:$lnnum:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(4) '$seek' [$line]\n" ) if ($dbg_v16);
                                            }

                                            $seek = 'OutputFile';
                                            if (defined $atthash{$seek} ) {
                                                $adddeps = strip_quotes(trim_all($atthash{$seek}));
                                                $dsp_current_sub{$var2} = '/out:'.$adddeps;
                                            } else {
                                                prtw( "WARNING:$lnnum:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(5) '$seek' [$line]\n" );
                                            }

                                            $seek = 'AdditionalLibraryDirectories';
                                            if (defined $atthash{$seek} ) {
                                                $adddeps = strip_quotes(trim_all($atthash{$seek}));
                                                $dsp_current_sub{$var1} .= ' '.get_libpaths_string($adddeps);
                                            } else {
                                                prtw( "WARNING:$lnnum:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(6) '$seek' [$line]\n" )  if ($dbg_v16);
                                            }

                                            $seek = 'SubSystem';
                                            if (defined $atthash{$seek} ) {
                                                $adddeps = strip_quotes(trim_all($atthash{$seek}));
                                                $apptype = adjust_app_type_per_subsystem( $apptype, $adddeps, $dbg_v05 );
                                            } else {
                                                prtw( "WARNING:$lnnum:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(7) '$seek' [$line]\n" ) if ($dbg_v18);
                                            }

                                        } elsif ($pname eq 'VCPostBuildEventTool') {
                                            if ($conf =~ /Debug/i) {
                                                $var1 = '-NEW_POST_DBG-';
                                            } else {
                                                $var1 = '-NEW_POST_REL-';
                                                if (!($conf =~ /Release/i)) {
                                                    prtw( "WARNING:$lnnum:$xln: pname=[$conf] NOT Debug or Release - def to REL!\n" );
                                                }
                                            }
                                            # <Tool
                                            #  Name="VCPostBuildEventTool"
                                            #  Description="Copy Library to plib directory"
                                            #  CommandLine="copy debug\*.lib ..\..\*.*&#x0D;&#x0A;copy ul.h ..\..\ul.h&#x0D;&#x0A;copy ulRTTI.h ..\..\ulRTTI.h&#x0D;&#x0A;"
                                            #  />
                                            # this will be output to the DSP, under the paticular, config, something like
                                            # # Begin Special Build Tool
                                            # SOURCE="$(InputPath)"
                                            # PostBuild_Desc=Copy to bin
                                            # PostBuild_Cmds=copy Release\*exe bin\.	copy test.h bin\.
                                            # # End Special Build Tool
                                            if (( defined $atthash{'Description'} ) || ( defined $atthash{'CommandLine'} ) ) {
                                                $ppdefs = ""; # to 'PostBuild_Desc=';
                                                if ( defined $atthash{'Description'} ) {
                                                    $ppdefs .= add_quotes(strip_quotes(trim_all($atthash{'Description'})));
                                                }
                                                $adddeps = ""; # to ' PostBuild_Cmds=';
                                                if ( defined $atthash{'CommandLine'} ) {
                                                    $adddeps = strip_quotes(trim_ends($atthash{'CommandLine'}));
                                                    $adddeps =~ s/&quot;/"/g;   # put back the quotes, if any
                                                    $adddeps =~ s/&#x0D;&#x0A;/\t/g;    # new line to TAB for VC6
                                                    $adddeps =~ s/\t$//;    # clear any END tab
                                                }
                                                prt( "$lnnum:$xln: got POST event [$ppdefs]\n" ) if ($dbg_v15);
                                                $tmp = "# Begin Special Build Tool\n";
                                                $tmp .= "SOURCE=\"\$(InputPath)\"\n";
                                                $tmp .= "PostBuild_Desc=$ppdefs\n";
                                                # sometimes need a little 'massaging' of the command ...
                                                $tmp .= "PostBuild_Cmds=".massage_command($adddeps)."\n";
                                                $tmp .= "# End Special Build Tool\n";
                                                $dsp_current_sub{$var1} = $tmp;
                                            }
                                        }
                                    }
                                }
                            } elsif ($line =~ /^<Configuration\s+/) {
                                $conf = $pname;
                                prt( "$lnnum:$xln: Entering Configuration [$conf]... [$line] ...\n" ) if ($dbg_v08);
                                # 28/09/2008 - note, has quotes added
                                # "-NEW_OUTD_DBG-" $out_dir
                                # "-NEW_OUTD_REL-" $out_dir
                                # "-NEW_INTER_DBG-" $int_dir
                                # "-NEW_INTER_REL-" $int_dir
                                if ($conf =~ /Debug/i) {
                                    $var1 = "-NEW_OUTD_DBG-";
                                    $var2 = "-NEW_INTER_DBG-";
                                } else {
                                    $var1 = "-NEW_OUTD_REL-";
                                    $var2 = "-NEW_INTER_REL-";
                                    if (!($conf =~ /Release/i)) {
                                        prtw( "WARNING:$lnnum:$xln: pname=[$conf] NOT Debug or Release - def to REL!\n" );
                                    }
                                }
                                #  // This is an internal type to Visual Studio, it seems that:
                                #  // 4 == static library
                                #  // 2 == dll
                                #  // 1 == executable
                                #  // 10 == utility
                                $seek = 'ConfigurationType';
                                if (defined $atthash{$seek}) {
                                    $adddeps = strip_quotes(trim_all($atthash{$seek}));
                                    $apptype = get_app_conf_type($adddeps);
                                    $dnaptype = 1;  # signal, we have an APP TYPE - VERY IMPORTANT
                                } else {
                                    prtw( "WARNING:$lnnum:$xln: DOES NOT CONTAIN(8) '$seek' [$line]\n" );
                                }
                                $seek = 'OutputDirectory';
                                if (defined $atthash{$seek}) {
                                    $adddeps = add_quotes(strip_dotrel(strip_quotes(trim_all($atthash{$seek}))));
                                    if ($dsp_current_sub{$var1} ne $adddeps) {
                                        prt( "$lnnum:$xln: Changed(1) $seek from [".$dsp_current_sub{$var1}."] to [$adddeps]\n" ) if ($dbg_v19);
                                    }
                                    $dsp_current_sub{$var1} = $adddeps;
                                } else {
                                    prtw( "WARNING:$lnnum:$xln: DOES NOT CONTAIN(9) '$seek' [$line]\n" );
                                }
                                $seek = 'IntermediateDirectory';
                                if (defined $atthash{$seek}) {
                                    $adddeps = add_quotes(strip_dotrel(strip_quotes(trim_all($atthash{$seek}))));
                                    if ($dsp_current_sub{$var2} ne $adddeps) {
                                        prt( "$lnnum:$xln: Changed(2) $seek from [".$dsp_current_sub{$var2}."] to [$adddeps]\n" ) if ($dbg_v20);
                                    }
                                    $dsp_current_sub{$var2} = $adddeps;
                                } else {
                                    prtw( "WARNING:$lnnum:$xln: DOES NOT CONTAIN(10) '$seek' [$line]\n" );
                                }
                                $inconfig = 1;
                            }
                        }
                    } elsif ($infiles) {
                        if ($tag =~ /\/Files/) {
                            prt( "$lnnum:$xln: Exit Files [$line]\n" ) if ($dbg_v09);
                            $infiles = 0;
                        } else {
                            # processing the <Files> section
                            # ##############################
                            if ($infilt) {
                                if ($line =~ /^<\/Filter/) {
                                    $infilt = 0;
                                    prt( "$lnnum:$xln: EXIT Filter name=[$fname] list=[$flist]\n" ) if ($dbg_v11);
                                } else {
                                    if ($infile) {
                                        if ($line =~ /^<\/File/) {
                                            $infile = 0;
                                        } else {
                                            # processing a <Files><Filter...><File ... may have
                                            # In <Files ...>
                                            # WATCH FOR THIS
                                            # <File RelativePath="..\..\scripts\pngw32.def">
                                            # <FileConfiguration Name="LIB Release|Win32" ExcludedFromBuild="true">
                                            # <Tool Name="VCCustomBuildTool" />
                                            # </FileConfiguration>
                                            # <FileConfiguration Name="LIB Debug|Win32" ExcludedFromBuild="true">
                                            # <Tool Name="VCCustomBuildTool" />
                                            # </FileConfiguration>
                                            # </File>
                                            # <FileConfiguration Name="Release|Win32" >
                                            # <Tool Name="VCCLCompilerTool" AdditionalIncludeDirectories="" PreprocessorDefinitions="" />
                                            # </FileConfiguration>
                                            # <FileConfiguration Name="Debug|Win32" >
                                            # <Tool Name="VCCLCompilerTool" AdditionalIncludeDirectories="" PreprocessorDefinitions="" />
                                            # </FileConfiguration>
                                            if ($tag =~ /<FileConfiguration/) {
                                                $infconf = 1;
                                                $fconf = $pname;
                                                $seek = 'ExcludedFromBuild';
                                                $adddefs = '';
                                                if (defined $atthash{$seek} ) {
                                                    $adddefs = strip_quotes(trim_all($atthash{$seek}));
                                                    if (length($adddefs) && ($adddefs =~ /true/)) {
                                                        $$src_ref[-1][3] = 1;
                                                        prt( "$lnnum:$xln: last = $last_src [".$$src_ref[-1][0]."] $fconf $seek = $adddefs\n" ) if ($dbg_v14);
                                                    }
                                                }
                                                prt( "$lnnum:$xln: Entering FileConfiguration [$line]\n") if ($dbg_v12);
                                            }
                                        }
                                    } elsif ($line =~ /^<File\s+/) {
                                        $seek = 'RelativePath';
                                        if (defined $atthash{$seek}) {
                                            $last_src = strip_dotrel(strip_quotes(trim_all($atthash{$seek})));
                                            if (is_c_source_extended($last_src)) {
                                                #push(@vc_c_sources,[$last_src, $fname, $flist, 0]);
                                                $var1 = (length($fname) ? $fname : get_def_src_grp());
                                                $var2 = (length($flist) ? $flist : get_def_src_filt());
                                                push(@vc_c_sources,[$last_src, $var1, $var2, 0]);
                                                $src_ref = \@vc_c_sources;
                                                $tmp = 'C';
                                            } else {
                                                #push(@vc_h_sources,[$last_src, $fname, $flist, 0]);
                                                $var1 = (length($fname) ? $fname : get_def_hdr_grp());
                                                $var2 = (length($flist) ? $flist : get_def_hdr_filt());
                                                push(@vc_h_sources,[$last_src, $var1, $var2, 0]);
                                                $src_ref = \@vc_h_sources;
                                                $tmp = 'H';
                                            }
                                            prt( "$lnnum:$xln: [$last_src] $tmp source\n" ) if ($dbg_v03);
                                        } else {
                                            prtw( "WARNING: $lnnum:$xln: DOES NOT CONTAIN(11) '$seek'? [$line]\n" );
                                        }
                                        $infile = 1;
                                    }
                                }
                            } elsif ($line =~ /^<Filter\s+/) {
                                $fname = $pname;
                                $seek = 'Filter';
                                if (defined $atthash{$seek} ) {
                                    $flist = strip_quotes(trim_all($atthash{$seek}));
                                } else {
                                    # example: alut.vcproj
                                    # <Filter Name="ALUT Header">
                                    # <File RelativePath="..\..\..\include\AL\alut.h">
                                    # </File></Filter>
                                    prtw( "WARNING: $lnnum:$xln: DOES NOT CONTAIN(12) '$seek'? [$line]\n" ) if ($dbg_v17);
                                }
                                prt( "$lnnum:$xln: ENTER Filter name=[$fname] list=[$flist]\n" ) if ($dbg_v11);
                                $infilt = 1;
                            } else {
                                # some VCPROJ files have NO <Filter ...><File...>...</File></Filter>
                                if ($infile) {
                                    if ($line =~ /^<\/File/) {
                                        $infile = 0;
                                    } else {
                                        # processing a <Files><File ... may have
                                        # In <Files ...>
                                        # WATCH FOR THIS
                                        # <File RelativePath="..\..\scripts\pngw32.def">
                                        # <FileConfiguration Name="LIB Release|Win32" ExcludedFromBuild="true">
                                        # <Tool Name="VCCustomBuildTool" />
                                        # </FileConfiguration>
                                        # <FileConfiguration Name="LIB Debug|Win32" ExcludedFromBuild="true">
                                        # <Tool Name="VCCustomBuildTool" />
                                        # </FileConfiguration>
                                        # </File>
                                        # <FileConfiguration Name="Release|Win32" >
                                        # <Tool Name="VCCLCompilerTool" AdditionalIncludeDirectories="" PreprocessorDefinitions="" />
                                        # </FileConfiguration>
                                        # <FileConfiguration Name="Debug|Win32" >
                                        # <Tool Name="VCCLCompilerTool" AdditionalIncludeDirectories="" PreprocessorDefinitions="" />
                                        # </FileConfiguration>
                                        if ($tag =~ /<FileConfiguration/) {
                                            $infconf = 1;
                                            $fconf = $pname;
                                            $seek = 'ExcludedFromBuild';
                                            $adddefs = '';
                                            if (defined $atthash{$seek} ) {
                                                $adddefs = strip_quotes(trim_all($atthash{$seek}));
                                                if (length($adddefs) && ($adddefs =~ /true/)) {
                                                    $$src_ref[-1][3] = 1;
                                                    prt( "$lnnum:$xln: last = $last_src [".$$src_ref[-1][0]."] $fconf $seek = $adddefs\n" ) if ($dbg_v14);
                                                }
                                            }
                                            prt( "$lnnum:$xln: Entering FileConfiguration [$line]\n") if ($dbg_v12);
                                        }
                                    }
                                } elsif ($line =~ /^<File\s+/) {
                                    $seek = 'RelativePath';
                                    if (defined $atthash{$seek}) {
                                        $last_src = strip_dotrel(strip_quotes(trim_all($atthash{$seek})));
                                        if (is_c_source_extended($last_src)) {
                                            #push(@vc_c_sources,[$last_src, $fname, $flist, 0]);
                                            $var1 = (length($fname) ? $fname : get_def_src_grp());
                                            $var2 = (length($flist) ? $flist : get_def_src_filt());
                                            push(@vc_c_sources,[$last_src, $var1, $var2, 0]);
                                            $src_ref = \@vc_c_sources;
                                            $tmp = 'C';
                                        } else {
                                            #push(@vc_h_sources,[$last_src, $fname, $flist, 0]);
                                            $var1 = (length($fname) ? $fname : get_def_hdr_grp());
                                            $var2 = (length($flist) ? $flist : get_def_hdr_filt());
                                            push(@vc_h_sources,[$last_src, $var1, $var2, 0]);
                                            $src_ref = \@vc_h_sources;
                                            $tmp = 'H';
                                        }
                                        prt( "$lnnum:$xln: [$last_src] $tmp source\n" ) if ($dbg_v03);
                                    } else {
                                        prtw( "WARNING: $lnnum:$xln: DOES NOT CONTAIN(13) '$seek'? [$line]\n" );
                                    }
                                    $infile = 1;
                                }
                            }
                        }
                    } else {
                        if ($tag =~ /<Configurations/) {
                            $inconfigs = 1;
                            prt( "$lnnum:$xln: Entering Configurations [$line]\n" ) if ($dbg_v08);
                        } elsif ($tag =~ /<Files/) {
                            prt( "$lnnum:$xln: Entering Files [$line]\n" ) if ($dbg_v09);
                            $infiles = 1;
                        }
                    }
                }
                ###if ($infconf && (($tag =~ /<\/FileConfiguration/)||($line eq '</FileConfiguration>'))) {
                if ($infconf && ($tag =~ /<\/FileConfiguration/)) {
                    $infconf = 0;
                    prt( "$lnnum:$xln: Exit FileConfiguration [$line]\n" ) if ($dbg_v12);
                }
            } else {
                if ($tag =~ /<VisualStudioProject/) {
                    $invcproj = 1;
                    ##push(@tag_stack, $tag);
                    # <VisualStudioProject
                    #  ProjectType="Visual C++" 
                    #  Version="9.00" 
                    #  Name="FlightGear"
                    #  ProjectGUID="{5C747AB8-6441-46B3-95D2-9D948C80EC77}"
                    #  TargetFrameworkVersion="131072" >
                    $seek = 'Name';
                    if (!defined $atthash{$seek} ) {
                        mydie( "ERROR: 'VisualStudioProject' DOES NOT CONTAIN(14) a porject NAME! NO GO!! ABORTING!!!\n" );
                    }
                    $projname = $pname;
                    $adddeps = '';
                    $adddefs = '';
                    $seek = 'ProjectType';
                    if (defined $atthash{$seek}) {
                        $adddefs = strip_dotrel(strip_quotes(trim_all($atthash{$seek})));
                    }
                    $seek = 'Version';
                    if (defined $atthash{$seek}) {
                        $adddeps = strip_dotrel(strip_quotes(trim_all($atthash{$seek})));
                    }
                    prt( "$lnnum:$xln: Project [$projname], using [$adddefs], version [$adddeps] ...\n" );
                }
            }
            prt( "$lnnum:$xln:".scalar @tag_stack.": $tag [$line]\n" ) if ($dbg_v01);
        }
        prtw( "WARNING: tag_stack NOT empty! ".$tag_stack[0]."\n") if (@tag_stack);
        $dsp_current_sub{'C_SOURCES'} = [@vc_c_sources];
        $dsp_current_sub{'H_SOURCES'} = [@vc_h_sources];
        $dsp_current_sub{'APP_TYPE'} = $apptype;
        $dsp_current_sub{'-NEW_PROJECT_NAME-'} = $projname;
    } else {
        mydie( "ERROR: Unable to open $fil ... $! ... check name, location ...\n" );
    }
    return %dsp_current_sub;
}

sub xml_array_to_lines {
    my ($rlm, @lns) = @_;
    my $intag = 0;
    my $text = '';
    my @nlines = ();
    my ($fln, $ln, $ch, $pch, $nch, $len, $i, $i2, $tag, $xml, $dnx);
    my ($lnnm, $lnb, $nlnm);
	my ($ppch, $rem, $incomm);
    $pch = '';
    $nch = '';
    $tag = '';
    $xml = '';
	$ppch = '';
    $dnx = 0;
    $lnnm = 0;
    $nlnm = 0;
    $lnb = 0;
	$incomm = 0;
	$text = '';
    foreach $fln (@lns) {
        chomp $fln;
        $ln = trim_all($fln);
        $len = length($ln);
        $lnnm++;    # count another xml line
        for ($i = 0; $i < $len; $i++) {
            $i2 = $i + 1;
            $ch = substr($ln,$i,1);
            $nch = (($i2 < $len) ? substr($ln,$i2,1) : ' ');
            if ($intag) {
                # on close of tag
                $tag .= $ch;
                if ($ch eq '>') {
                    # end of XML tag
					if (( ! $incomm) || ( $incomm && ($pch eq '-') && ($ppch eq '-') )) {
						$nlnm++;
						push(@nlines,$tag);
						### prt( "push(\@xlnmap, [ $nlnm, $lnb, $lnnm ]); # each NEW line has BEGIN and END\n" );
						$$rlm{$nlnm} = "$lnb-$lnnm";    # each NEW line has BEGIN and END
						$tag = '';
						$intag = 0;
						$xml = '';
						$incomm = 0;
					}
                }
            } else {
                if ($ch eq '<') {
					if (length($text)) {
						$nlnm++;
						push(@nlines,$text);
						### prt( "push(\@xlnmap, [ $nlnm, $lnb, $lnnm ]); # each NEW line has BEGIN and END\n" );
						$$rlm{$nlnm} = "$lnb-$lnnm";    # each NEW line has BEGIN and END
						$text = '';
					}
					if ($nch eq '!') {
						# potential start of comment <!-- until -->
						$rem = $len - $i;
						if (($rem > 4) && (substr($ln,$i,4) eq '<!--')) {
							$incomm = 1;
						}
					}
                    $tag = $ch; # start a tag line
                    $intag = 1; # signal in a tag
                    $xml = '';
                    $dnx = 0;
                    $lnb = $lnnm;    # set the BEGIN xml line
                } else {
					$text .= $ch;
				}
            }
			$ppch = $pch;
            $pch = $ch;
        }
        # done a line - this is like a SPACE
        if ($intag && length($tag)) {
            $tag .= ' ' if !($tag =~ /\s$/);
        }
    }
    if (length($tag)) {
        prtw("WARNING: xml re-lining error! Left pending tag [$tag]\nin $act_vcproj file ...\n");
    }
    return @nlines;
}

sub fg_xml_to_lines {
    my ($rlm, @lns) = @_;
    my $intag = 0;
    my $text = '';
    my @nlines = ();
    my ($fln, $ln, $ch, $pch, $nch, $len, $i, $i2, $tag, $xml, $dnx);
    my ($lnnm, $lnb, $nlnm);
    $pch = '';
    $nch = '';
    $tag = '';
    $xml = '';
    $dnx = 0;
    $lnnm = 0;
    $nlnm = 0;
    $lnb = 0;
    foreach $fln (@lns) {
        chomp $fln;
        $ln = trim_all($fln);
        $len = length($ln);
        $lnnm++;    # count another xml line
        for ($i = 0; $i < $len; $i++) {
            $i2 = $i + 1;
            $ch = substr($ln,$i,1);
            $nch = (($i2 < $len) ? substr($ln,$i2,1) : ' ');
            if ($intag) {
                # on first SPACE
                $tag .= $ch;
                if ($ch eq '>') {
                    # end of XML tag
                    $nlnm++;
                    push(@nlines,$tag);
                    ### prt( "push(\@xlnmap, [ $nlnm, $lnb, $lnnm ]); # each NEW line has BEGIN and END\n" );
                    $$rlm{$nlnm} = "$lnb-$lnnm";    # each NEW line has BEGIN and END
                    $tag = '';
                    $intag = 0;
                    $xml = '';
                }
            } else {
                if ($ch eq '<') {
                    $tag = $ch; # start a tag line
                    $intag = 1; # signal in a tag
                    $xml = '';
                    $dnx = 0;
                    $lnb = $lnnm;    # set the BEGIN xml line
                }
            }
            $pch = $ch;
        }
        # done a line - this is like a SPACE
        if ($intag && length($tag)) {
            $tag .= ' ' if !($tag =~ /\s$/);
        }
    }
    if (length($tag)) {
        prtw("WARNING: xml re-lining error! Left pending tag [$tag]\nin $act_vcproj file ...\n");
    }
    return @nlines;
}

sub get_string_with_sep {
    my ($sep, $txt) = @_;
    my @av = split(/[,;]/, $txt);
    my $ref = '';
    foreach my $tx (@av) {
        $tx = substr($tx,1) if ($tx =~ /^\s/);
        if (length($tx)) {
            $ref .= ' ' if length($ref);
            # remove any existing quotes, but add quotes for sure
            $ref .= $sep.add_quotes(strip_quotes($tx));
        }
    }
    return $ref;
}

sub get_includes_string {
    my ($txt) = shift;
    return get_string_with_sep('/I ', $txt);
}
sub get_defines_string {
    my ($txt) = shift;
    return get_string_with_sep('/D ', $txt);
}

sub get_libpaths_string {
    my ($txt) = shift;
    return get_string_with_sep('/libpath:', $txt);
}


1;
# eof fgscanvc.pl
