fgsln2dsw.pl to HTML.

index -|- end

Generated: Tue Feb 2 17:54:36 2010 from fgsln2dsw.pl 2008/10/26 146.8 KB.

#!perl -w
# NAME: fgsln2dsw.pl
# AIM: Read a MSVC7/8/9/?? solution, and vcproj files, and create
# or maybe update an (depreciated, as too hard)
# equivalent DSW/DSP files ...
# 26/10/2008 - more tidying, and writing dsplist.txt file
# 25/09/2008 - massive improvements for parsing PREVIOUS solutions files
# most changes extracted from fgslnlist.pl ...
# 19/05/2008 - Add 'Static Library' DSP header ... still missing 'Dynamic Library'
# 22/04/2008 - Extract DEPENDENCIES from solution file, and add to DSW output
# 14/02/2008 - attempt to get RELATIVE folders correct, both in DSW (and DSP)
# 17/12/2007 - geoff mclane - http://geoffair.net/mperl
use strict;
use warnings;
use File::Basename;
use Cwd;
require 'fgutils.pl' or die "Unable to load fgutils.pl ...\n";
require 'fgdsphdrs.pl' or die "Unable to load fgdsphdrs.pl ...\n";
# log file stuff
my ($LF);
my $pgname = $0;    # get perl module name
if ($pgname =~ /\w{1}:\\.*/) {
   my @tmpsp = split(/\\/,$pgname);
   $pgname= $tmpsp[-1];
}
my $outfile = "temp.$pgname.txt";
open_log($outfile);
my $inpsln = '';
my $dswfile = '';
my $dspfile = '';
my $dbg1     = 1;
my $defin = 'fgfs\fgfs.sln';
# Options
my $write_real_files = 0;   # set to 0 to generate TEMPORARY DSP/DSW files
my $use_std_groups = 0;     # substitute the groups - not good choice!
my $add_blank_groups = 0;   # force output of BLANK standard groups - not good choice
# compare options
my $comp_to_existing = 0;   # open, parse, cand compare with existing DSP, if any
my $chk4dups = 0;   # do a DUPLICATE check
my $tryharder = 0;   # needs more work to put this ON
my $keeporder = 1;   # if a PREVIOUS DSW file, then try to retain the ORDER in it
# add options
my $add_projs_to_depends = 1;   # also add ALL projects to dependency file
my $addfiles2cfg = 1;   # add list of SOURCE files to CFG outputs
my @extra_projects = ();
#my @proj_files = ();
my $pcnt = 0;
##                  [0]   [1]   [2]       [3]       [4] [5]  [6]        [7]
##                  relnm full  group      filter   cmp done project    grp
##   push(@v8_srcs, [$src, $ff, $filtname, $filttype, 0,  0,  $projname, shr] );
use constant {
    V8_SRC => 0,
    V8_FUL => 1,
    V8_GRP => 2,
    V8_FIL => 3,
    V8_CMP => 4,
    V8_DON => 5,
    V8_PRJ => 6,
    V8_SHR => 7,
    V8_EXC => 8
};
my @all_sources = (); # multidimensional array with lot of information
my @v8_srcs = ();   # multidimensional array with lot of information
my %v8_link = ();   # PREPROCESSOR compiler definitions, by configuration
my %v8_aptype = (); # application type, by configuration - see like fg = ConfigurationType="1"
my %v8_depend = (); # ADDITIONAL LINK dependencies, by configuration
# new 21/09/2008 
my %v8_runtim = (); # RUNTIME /MT or /MD, by configuration
my %v8_includ = ();
my %v8_filter = (); # In <Files>, like <Filter Name="Assembler Files (Unsupported)"
# Filter="asm;obj;c;cpp;cxx;h;hpp;hxx">
# $key = Name, $val = Filter, for whole solution 
# Filter="asm;obj;c;cpp;cxx;h;hpp;hxx">
# $key = Name, $val = Filter, for whole solution 
my %v8_apptypes = ();    # SOLUTION: full set of app type in solution, key = project name
my %v8_libdep = (); # ADDITIONAL LIB DIRS, by configuration
# new 22/09/2008
my %v8_config = ();  #  by configuration, OutputDirectory=".\Release", IntermediateDirectory="Release",
# and zlib = ConfigurationType="4", alut = ConfigurationType="2", fg = ConfigurationType="1"
#  // This is an internal type to Visual Studio, it seems that:
#  // 4 == static library
#  // 2 == dll
#  // 1 == executable
#  // 10 == utility
my %v8_linkout = (); # Name="VCLinkerTool" OutputFile=".\Release\FlightGear.exe", by configuration
my $app_console = 'Console Application';
my $app_windows = 'Application';
my $app_dynalib = 'Dynamic-Link Library';
my $app_statlib = 'Static Library';
my $app_utility  = 'Utility';
# per <Configuration ... ConfigurationType="4" ...
my %v8_conftypes = (
    1  => $app_windows,
    2  => $app_dynalib,
    4  => $app_statlib,
    10 => $app_utility );
# and if 1 ($app_windows), then per SubSystem
# <Tool Name="VCLinkerTool" ... SubSystem="2"
# SubSystem="1" = :console or "2" = :window
my %v8_subsystems = (
    1 => $app_console,
    2 => $app_windows );
# and if that FAILS, then try to decode PreprocessorDefintiions
# maybe _WINDOWS => 'Application'
# but then Alu.vcproj only has -
# PreprocessorDefinitions="NDEBUG;WIN32;AL_BUILD_LIBRARY"
# so this is NOT sure ...
my %v8_defines = (
    '_CONSOLE' => $app_console,
    '_USRDLL'  => $app_dynalib,
    '_LIB'     => $app_statlib );
my $typelse = $app_windows;
my @special_typing = qw( libpng zlib visualc6 );   # make these STATIC LIBRARIES
my %dsp_appheader = (
    $app_console => \&get_dsp_head_console,  # = 'Console Application';
    $app_windows => \&get_dsp_head_app,      # = 'Application';
    $app_dynalib => \&get_dsp_head_dynalib,  # = 'Dynamic-Link Library';
    $app_statlib => \&get_dsp_head_slib      # = 'Static Library';
);
use constant {
    TT_UNK => 0,
    TT_BGN => 1,
    TT_END => 2,
    TT_BE  => 3,
    TT_DEC => 4
};
# failed for some reason
#my %tt_strings = (
#    TT_UNK => 'Unknown',
#    TT_BGN => 'Begin',
#    TT_END => 'End',
#    TT_BE  => 'BE',
#    TT_DEC => 'Decl'
#);
my $TYP_OPEN = 1;
my $TYP_CLOSE = 2;
my $TYP_OPENCLOSE = 3;
my $TYP_VERSION = 4;
my $v8_cfgexp = '<Configuration\\s+.*Name=\\"(\\S+)\\"\\s';
my $v8_toolexp = '<Tool\\s+.?\\s*Name=\\"(\\S+)\\"\\s';
my $v8_prepexp = '\\s+PreprocessorDefinitions=\\"(\\S+)\\"';
use constant {
    GRP_UNK => 0,
    GRP_SRC => 1,
    GRP_HDR => 2,    # also include extensionless files, maybe ...
    GRP_RCS => 3,
    GRP_SPL => 4    # special items
};
my $def_src_g = "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90";
my $def_hdr_g = "h;hpp;hxx;hm;inl;fi;fd";
my $def_rcs_g = "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe";
my $def_spl_g = "txt;vc5;h-msvc8;asm";
my $def_src_nm = "Source Files";    # Begin Group "Source Files"
my $def_hdr_nm = "Header Files";   # Begin Group "Header Files"
my $def_rcs_nm = "Resource Files";   # Begin Group "Resource Files"
my $def_spl_nm = "Special Files";
my $def_unknown = "Unknown";
my @dsp_base_defs_rel = qw( WIN32 NDEBUG _WINDOWS _MBCS );
my @dsp_base_defs_dbg = qw( WIN32 _DEBUG _WINDOWS _MBCS );
my @dsp_base_libs_rel = qw( kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib );
my @dsp_base_libs_dbg = qw( kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib 
advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib );
my @dsw_file = ();   # contents of the DSW file, if ONE EXISTS
my @dsp_files = (); # [relfile, fullpath, and project NAME]
my @v6_srcs = ();  # relnm full group filter
my %v6_defs = ();
my %v6_conf = ();
# 20/09/2008 new items
# key = projname|$conf|$rtim, eg FlightGear|Debug|Win32|MDd
# value = string 'defines=[ list of defines ] $libraries=[ list of libraries ]
my %v6_refall = (); # instead of a scalar list, try to add a COPY of an array
my %v6_all = ();    # OLD - NOW NOT USED projects
my @xml_tag_map = ();
my @xml_lines = ();
my @xml_line_map = ();  # multi - [ new_line, begin_line, end_line ]
my $xml_last_line = 0;
my $act_file = '';  # last file source from project
my $act_disp = '';  # can be 'MISSED', 'EXCLUDED', or 'ok'
use constant {
    RT_NAM => 0,
    RT_LTS => 1,
    RT_STG => 2,
    RT_VAL => 3,
    RT_RES => 4
};
my $def_runtime_lts = "MD";
my $def_runtime_stg = "Multithreaded DLL";
my $def_runtime_val = 2;
#    0                  1     2                         3  4
my @runtimes_array = (
    ["RuntimeLibrary", "MT",  "Multithreaded",           0, 0],
    ["RuntimeLibrary", "MTd", "Multithreaded Debug",     1, 0],
    ["RuntimeLibrary", $def_runtime_lts, $def_runtime_stg, $def_runtime_val, 0],
    ["RuntimeLibrary", "MDd", "Multithreaded DLL Debug", 3, 0],
    ["RuntimeLibrary", "ML",  "Single Thread",           4, 0],
    ["RuntimeLibrary", "MLd", "Single Thread Debug",     5, 0]
);
# 23/09/2008 from fgsln2dsw.pl - get SOLUTION dependencies
my %sln_projects = ();   # projects FOUND in SLN file - key=name, data=vcproj file
my %sln_projpath = ();   # and the RELATIVE path of the project, IF ANY ...
my %sln_projids  = ();   # special ID used in SLN file
my %sln_depends  = ();   # dependencies, key by projname, with '|' list of values
# 27/09/2008
my %v8_postbuild = (); # Name="VCPostBuildEventTool", with
# 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;"
# the &#x0D;&#x0A; is replaced with a TAB (\t) in the DSP file
##############################################################
# common 'reserved' words for config files
# for neatness only, make them all equal length
my $prjname   = 'projname';
my $ap_type   = 'app_type';
my $runtime   = 'runtime_';
my $platform  = 'platform';
my $linkout   = 'link_out';
my $includes  = 'inc_path';
my $libraries = 'add_libs';
my $libpath   = 'lib_path';
my $defines   = 'defines_';
my $outputs   = 'outputs_';
my $out_dir   = 'out__dir';
my $int_dir   = 'interout';
my $depends   = 'depends_';
my $filter    = 'filter__';
my $srcfiles  = 'src_file';
my $excfiles  = 'exc_file';
# 27/09/2008
my $postevt   = 'postbld_';
my $postdesc  = 'postdesc';
my $postcmds  = 'postcmds';
##############################################################
my $vcproj_cnt = 0;
my %dsw_projects = ();
my %dsw_projpath = ();
my $compres = 0;
my @dsp_written = ();
my @dsp_list = ();
my $tot_vclines = 0;
my $excl_mark = "EXCLUDED";
# default items for Application (windows and console)
my $def_runtime_rel = '/MT';
my $def_runtime_dbg = '/MTd';
my $def_defines_dbg = '/D "_CRT_SECURE_NO_WARNINGS"';
my $def_defines_rel = '/D "_CRT_SECURE_NO_WARNINGS"';
my $def_libs_rel = 'comctl32.lib Msimg32.lib Winmm.lib';
my $def_libs_dbg = 'comctl32.lib Msimg32.lib Winmm.lib';
my $def_include_dirs_dbg = '';
my $def_include_dirs_rel = '';
my $def_post_dbg = '';
my $def_post_rel = '';
my $def_output_dbg = 'Debug';    # "-NEW_OUTD_DBG-"
my $def_output_rel = 'Release';    # "-NEW_OUTD_REL-"
my $def_inter_dbg  = 'Debug';    # "-NEW_INTER_DBG-"
my $def_inter_rel  = 'Release';    # "-NEW_INTER_REL-"
my $def_out_dbg = '';
my $def_out_rel = '';
my $dsp_runtime_rel = '';
my $dsp_runtime_dbg = '';
my $dsp_defines_dbg = '';
my $dsp_defines_rel = '';
my $dsp_libs_rel = '';
my $dsp_libs_dbg = '';
my $dsp_includes_dbg = '';
my $dsp_includes_rel = '';
my $dsp_post_dbg = '';  # $msg =~ s/-NEW_POST_DBG-/$dsp_post_dbg/gm;
my $dsp_post_rel = '';  # $msg =~ s/-NEW_POST_REL-/$dsp_post_rel/gm;
# 28/09/2008
my $dsp_output_dbg = '';    # "-NEW_OUTD_DBG-"
my $dsp_output_rel = '';    # "-NEW_OUTD_REL-"
my $dsp_inter_dbg  = '';    # "-NEW_INTER_DBG-"
my $dsp_inter_rel  = '';    # "-NEW_INTER_REL-"
# 29/09/2008
my $dsp_out_dbg = '';   # "-NEW_OUT_DBG-"
my $dsp_out_rel = '';   # "-NEW_OUT_REL-"
# 27/09/2008 - substitutions
my $act_key = '';
my $use_sub_hash = 1;
my %dsp_substitions = (
    "-NEW_PROJECT_NAME-" => \$act_key,
    "-NEW_RT_REL-"       => \$dsp_runtime_rel,
    "-NEW_RT_DBG-"       => \$dsp_runtime_dbg,
    "-NEW_DEFS_REL-"     => \$dsp_defines_rel,
    "-NEW_DEFS_DBG-"     => \$dsp_defines_dbg,
    "-NEW_LIBS_DBG-"     => \$dsp_libs_dbg,
    "-NEW_LIBS_REL-"     => \$dsp_libs_rel,
    "-NEW_POST_DBG-"     => \$dsp_post_dbg,
    "-NEW_POST_REL-"     => \$dsp_post_rel,
    "-NEW_INCS_DBG-"     => \$dsp_includes_dbg,
    "-NEW_INCS_REL-"     => \$dsp_includes_rel,
    "-NEW_OUTD_DBG-"     => \$dsp_output_dbg,
    "-NEW_OUTD_REL-"     => \$dsp_output_rel,
    "-NEW_INTER_DBG-"    => \$dsp_inter_dbg,
    "-NEW_INTER_REL-"    => \$dsp_inter_rel,
    "-NEW_OUT_DBG-"      => \$dsp_out_dbg,
    "-NEW_OUT_REL-"      => \$dsp_out_rel
);
# DEBUG SWITCHES
# ##############
my $dbg_srcv = 0;
my $dbg_srcc = 0;
my $dbg_sln = 0;    # show prt( "$cnt: Project=[".$arr[0]."] Path=[".$arr[1]."] ...
my $dbg11 = 0;
my $dbg_src1  = 0;
my $dbg_src2  = 0;
my $dbg_src3  = 0;
my $dbg_src4 = 0;
my $dbg_src5 = 0;
my $dbg_src6 = 0;   # show prt( "Got configuration $conf
my $dbg_src7 = 0;   # show prt( "Got Tool name $tname and prt( "Is linker tool ...[$fline]
my $dbg_src8  = 0;  # show prt( "Setting DEFS: $conf [$ppdefs] $apptype ($ctype)
my $dbg_src9 = 0;
my $dbg_src10 = 0;
my $dbg_src11 = 0;  # show prt( "Project=$projname, v=$version GUID=$ProjectGUID
my $dbg_src12 = 0;  # show prt( "Setting LINKS: $conf [$adddeps] - 
my $dbg_src12a = 0;
my $dbg_src12b = 0; # show prt( "Set LNKDIRS:$conf: [$adddeps] - also see $dbg_d15
my $dbg_src13 = 0;
my $dbg_src14 = 0;
my $dbg_src15 = 0;
my $dbg_src16 = 0;  # show prt( "SRC: [$ffnr] $itm
my $dgb_src17 = 0;  # show prt( "Got RUNTIME value [$ppdefs] ... config=$conf ($ctype) $itm (= $def)
my $dbg_src18 = 0;
my $dbg_x01 = 0;    # to do write2file( join("\n",@nlines), 'tempxml.txt'); and more
my $dbg_x02 = 0;    # show warning if from @special_type list
my $dbg_x03 = 0;    # show prt( "v6_all: Adding [$mask] with $libraries=[$cdefs] ...
my $dbg_x04 = 0;    # show each with 'Name' - prt( "tag=$xmltag, Name=$pname
my $dgb_x05 = 0;    # show massive debug information in sub exclude_from_build{...}
my $dbg_x06 = 0;    # show prt( "$lnnum: Enter Files ... ($fline), AND exit
my $dbg_x07 = 0;    # show prtw("WARNING: Got 'AdditionalIncludeDirectories' = $ppdefs, ... if (($act_disp ne 'EXCLUDED')
my $dbg_x08 = 0;    # show prt( "dbg_x08: Showing _ALL_ for tag=[$xmltag], line=[$fline]
my $dbg_x09 = 0;    # show prt( "$msg\n" ) if ($dbg_x09);    # done ONE application
my $dbg_x10 = 0;    # show prt( "Got equal split of [$key] = [$val]
my $dbg_x11 = 0;    # show prt( "VCLibrarianTool:$conf Suggests STATIC LIBRARY - out=$ppdefs - and that is what we have in v8_aptype...
my $dbg_x12 = 0;    # show prt( "VCPROJ Project: $projname, as $apptype, version=$version ... AND MORE
my $dbg_x13 = 0;    # show prt( "Defined Debug = $dsp_defines_dbg, Release = $dsp_defines_rel... AND MORE
my $dbg_x14 = 0;    # show prt("Set INCLUDES:$conf: to [$ppdefs]
my $dbg_x15 = 0;    # show prt( "Set APPTYPE:$conf: v8_aptype[$apptype] (ln=$lnnum)... AND MORE see $dgbx_08 also
my $dbg_x16 = 0;    # show prt("Got APPTYPE:$conf: NO CHANGE [$apptype] equals SubSystem ($adddeps) [".$v8_subsystems{$adddeps}."] ...
my $dbg_x17 = 0;    # show prt( "\nLoading [$in] file in directory [$in_fd] ...
my $dbg_x18 = 0;    # show prt( "Begin List - first solution name, then VCPROJ files ...
my $dbg_x19 = 0;    # show prt( "Writing $cnt potential dependencies to $outfil ... AND MORE
my $dbg_x20 = 0;    # show prt( "Set 'VCLibrarianTool' v8_linkout[$conf] to [$ppdefs] $act_vcproj
my $dbg_x21 = 0;    # show prt( "For mask [$mask], set linkout $linkout = [$lout] ...
my $dbg_x22 = 0;    # show prt( "For mask [$mask], set libpath $libpath = [$libdirs] - see $dbg_src12b & $dbg_d15
my $dbg_sl1 = 0;   # show projects found in SOLUTION (SLN) file - "Got PROJECT name=$projname, file=$projff
my $dbg_s12 = 0;   # show "Proj $projname, dependant on $arr[0] ...
my $dbg_s13 = 0;   # show "proj $projname, depends on $nmdeps ...
my $dbg_sl4 = 0;    # show prt( "key=$key, fil=$fil, rp=$rp, slndr=$slndr, vcdr=$vcdr ...
my $dbg_dsp = 0;    # show prt( "Project NAME = $prjname ...
my $dbg_ds1 = 0;    # show prt("SOURCE=[$src]
my $dbg_ds2 = 0;    # show prt("HEADER=[$src]
my $dbg_ds3 = 0;   # show prt("OTHER=[$src] ($line)
my $dbg_ds4 = 0;   # show CPP and LINK config items - %v6_conf
my $dbg_ds5 = 0;   # show Defined items - %v6_defs
my $dbg_ds6 = 0;   # show !IF, !ELSEIF switching
my $dbg_ds7 = 0;   # show %v6_conf listing
my $dbg_ds8 = 0;   # show VC6 Filter and Group Name
my $dbg_ds9 = 0;   # show EACH VC6 source pushed
my $big_dbg = 0;   # show EACH COMPARE, and results
my $dbg_d10 = 0;    # show substitutions for DSP generation - see also $dbg_d12
my $dbg_d11 = 0;    # show "DSP app type = ... plus more
my $dbg_d11a = 0;   # show prt( "For [$key], got $rcnt reference keys!
my $dbg_d12 = 0;    # show prt( "CHECK OUT THE REPLACEMENTS! ... a series of outputs see $dbg_d10
my $dbg_d13 = 0;    # show $dmsg = "Link OUPUT: $linkout]=[$cont]";
my $dbg_d14 = 0;    # show $dmsg = "Object OUPUT: $outputs]=[$cont]";
my $dbg_d15 = 0;    # show $dmsg = "Link LIBPATH: $libpath=[$cont]";
my $dbg_dsw1 = 0;   # show EACH LINE from the file
my $dbg_dsw2 = 0;   # show $msg = "Project: name=$pnm, file=$pfil ff=$ff ...";
my $dbg_dsw3 = 0;   # show prt( "Processing $lncnt lines from file ...
my $dbg12    = 0;   # show debug output for sub is_same_DOS_file ...
# ##############
my $tmpdsw = 'tempdsp2.dsw';
my @warnings = ();   # output any WARNINGS at the END
my $sln_path = '';   # this is DIRECTORY of SOLUTION
my $act_vcproj = '';   # active VCPROJ file
#########################################################################
# PROGRAM COMMENCES
### commence process ###
parse_args( @ARGV );
my ($sln_nm,$sln_dr,$sln_ex) = fileparse($inpsln, qr/\.[^.]*/ );
if ( -f $inpsln) {
    Process_SLN_in($inpsln);
} else {
   prtw( "ERROR: Can NOT locate $inpsln file ...\n" );
}
show_v6_refall();
write_out_depends($sln_nm);
show_warnings();
close_log($outfile,1);
exit(0);
######################
#  main processing section
sub Process_SLN_in {    # $inpsln
   my $slnfil = shift;
   my ($slnnm,$slndr) = fileparse($slnfil);
    my ($ffrdsp);
   $dswfile = $slndr . basename($slnnm,  ".".get_suffix($slnnm));
   $dswfile .= ".dsw";
   prt( "Processing [$slnfil] file ...\n" );
   process_SLN( $slnfil );
   $pcnt = scalar keys(%sln_projects);
   process_DSW( $dswfile );    # and if there is an EXISTING DSW, then process it ...
   prt( "Got $pcnt vcproj files to process ...\n" );
   if ($pcnt) {
      my ($key, $fil, $rp, $realdsp, $tmpdsp);
        my ($vcnm,$vcdr,$vcex);
      foreach $key (keys %sln_projects) {
         $fil = $sln_projects{$key};
         $rp  = $sln_projpath{$key};
         ($vcnm,$vcdr,$vcex) = fileparse($fil, qr/\.[^.]*/ );
            prt( "key=$key, fil=$fil, rp=$rp, slndr=$slndr, vcdr=$vcdr ...\n" ) if ($dbg_sl4);
         $rp =~ s/\\$//;   # remove any TRAILING '\' char
            $realdsp = $key.".dsp";  # real DSP file name
            # but ONLY write a temp version until very sure
         $tmpdsp = "temp.".$realdsp;
            ### $ffrdsp = $basepath . $key . ".dsp";
            $ffrdsp = $slndr . $key . ".dsp";
         if (length($rp)) {
                $tmpdsp = $rp;
                $tmpdsp .= "\\" if !($rp =~ /(\\|\/)$/);
                $ffrdsp = $slndr . $tmpdsp . $key . ".dsp";
                $tmpdsp .= $realdsp;
                $realdsp = $tmpdsp; # a relative DSP file
            $rp =~ s/\\/#/g;    # SUBSTITUTE path separator for '#' character
            $tmpdsp = "temp.$rp.$key.dsp";  # TEMP DSP file
         }
            $ffrdsp = fix_rel_path($ffrdsp);
            # we have the REAL and TEMP name of the DSP file to write
            # get the potentially MODIDFIED relative PATH back
         $rp  = $sln_projpath{$key};
         $rp =~ s/\\$//;   # remove any TRAILING '\' char
         $dspfile = $vcdr .$vcnm.".dsp";
         fg_clear_proj_files();
         $vcproj_cnt++;
         prt( "\n$vcproj_cnt: Processing:[$fil] VCPROJ file ... \n" );
         $act_vcproj = $fil;
         get_xml_sources( $fil );   # load the VCPROJ file
            push(@all_sources,@v8_srcs);    # keep the information gathered
              # whether compared or not, keep the DSW entry
            $dsw_projects{$key} = "$key.dsp";
            $dsw_projpath{$key} = $rp;
            if ($comp_to_existing) {
                process_DSP( $key, $dspfile );   # and any EXISTING DSP file
                my $compcnt = compare_proj_with_dsp( $key, $rp ); # also WRITES new DSP file
                $compres += $compcnt;
            }
         generate_DSP( $key, $tmpdsp, $realdsp, $ffrdsp ); # out DSP, ALWAYS instead of if ($compcnt); # output a DSP file
      }
        ###$tmpdsw = $dswfile if ($write_real_files);
      write_DSW_file( $slnnm, $tmpdsw, $dswfile ); # ALWAYS OUT file - not only if ($compres); 
   }
}
# DEAL WITH DSW OUTPUT
sub add_proj_begin {
   my ($fh, $prj, $fil) = @_;
   print $fh <<EOF;
###############################################################################
Project: "$prj"=".\\$fil" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
EOF
}
sub add_proj_depends {
   my ($fh, $prj) = @_;
   my ($pdeps, @arr, $dpn);
   if (defined $sln_depends{$prj}) {
      $pdeps = $sln_depends{$prj};
      if (length($pdeps)) {
         @arr = split( /\|/, $pdeps );
         foreach $dpn (@arr) {
            print $fh "    Begin Project Dependency\n";
            print $fh "    Project_Dep_Name $dpn\n";
            print $fh "    End Project Dependency\n";
         }
      }
   } else {
      prtw( "WARNING: Project $prj NOT defined in sln_depends!!!\n" );
   }
}
sub add_proj_end {
   my ($fh) = shift;
   print $fh <<EOF;
}}}
EOF
}
sub in_list {
   my ($itm, @lst) = @_;
   foreach my $ti (@lst) {
      if ($itm eq $ti) {
         return 1;
      }
   }
   return 0;
}
# output a DSW file
# if $keeporder, and there is a previous DSW, then try to output in SAME order
sub write_DSW_file {
   my ($key,$dfile,$rfile) = @_;
   my ($msg, $prj, $DSW);
   my ($pdeps, @arr, $dpn, $i);
   my ($fil, $rp);
   my @prjlist = sort keys(%dsw_projects);
   my $prjcnt = scalar @prjlist;
   my $dspcnt = scalar @dsp_files;   # list collected from previous DSW, if any
   my @donelist = ();
    if ($prjcnt == 0) {
        prtw( "WARNING: NO PROJECTS IN \%dsw_projects!!!\n".
            "SO NO DSW FILE CREATED! Why is hash blank???\n" );
        return;
    }
    $dfile = $rfile if ($write_real_files);
    rename_2_old_bak($dfile);
   if (open $DSW, ">$dfile") {
      $msg = get_dsw_head();
      print $DSW $msg;
      if ($keeporder && $dspcnt) {
         prt( "Output in ORDER of previous DSW file ...\n" );
         for ($i = 0; $i < $dspcnt; $i++) {
            #                   0      1    2
            # push(@dsp_files, [$pfil, $ff, $pnm]); # [file, fullpath, and project NAME]
            $prj = $dsp_files[$i][2];
            if (defined $dsw_projects{$prj}) {
               $fil = $dsw_projects{$prj};
               $rp  = $dsw_projpath{$prj};
               $fil = $rp."\\".$fil if (length($rp));
               add_proj_begin( $DSW, $prj, $fil );
               # add any DEPENDENCIES NOW
               add_proj_depends( $DSW, $prj );
               add_proj_end( $DSW );
               push(@donelist, $prj);
            } else {
               prt( "Warning: $prj now discarded ...\n" );
            }
         }
      } elsif ($keeporder) {
         prt( "No ORDER possible, since no previous DSW file ...\n" );
      }
      # $dsw_projects{$key} = "$key.dsp";
      #foreach $prj (sort keys(%dsw_projects)) {
      # foreach $prj (@prjlist)
      for ($i = 0; $i < $prjcnt; $i++) {
         $prj = $prjlist[$i];
         if (!in_list($prj, @donelist)) {
            $fil = $dsw_projects{$prj};
            $rp  = $dsw_projpath{$prj};
            $fil = $rp."\\".$fil if (length($rp));
            add_proj_begin( $DSW, $prj, $fil );
            # add any DEPENDENCIES NOW
            add_proj_depends( $DSW, $prj );
            add_proj_end( $DSW );
         }
      }
      $msg = get_dsw_tail();
      print $DSW $msg;
      close $DSW;
      # diagnostic OUTPUT
      prt( "\nWritten [$dfile] file ...\n" );
      prt( "For DSP list :-\n" );
      foreach $msg (@dsp_written) {
         prt( "$msg\n" );
      }
   } else {
      prtw("ERROR: Unable to WRITE $dfile ...\n" );
   }   
    write_dsp_list_file( $rfile, "dsplist.txt" );
}
sub write_dsp_list_file {
    my ($df, $fil) = @_;
    if (@dsp_list) {
        my ($OF, $msg);
        rename_2_old_bak($fil);
        if (open $OF, ">$fil") {
            print $OF "$df\n";
            foreach $msg (@dsp_list) {
                print $OF "$msg\n";
            }
            close $OF;
        } else {
            prtw( "WARNING: Failed to create file [$fil] ... $! ...\n" );
        }
    } else {
        prtw( "WARNING: No items in \@dsp_list array ...\n" );
    }
}
sub compare_proj_with_dsp {
   my ($key, $rp) = @_;   # key is PROJECT name, and any relative path
   my ($i1, $i2, $fnd, $matched);
   ##   push(@cv8_srcs, [$src, $ff, $filtname, $filttype, $flag, $projname] );
   my ($src1, $ff1, $fnm1, $typ1, $flg1);
   my ($src2, $ff2, $fnm2, $typ2, $flg2);
   my ($nm1, $pth1, $suf1);
   my ($nm2, $pth2, $suf2);
   my ($added, $subed);
   my ($miss1, $miss2, $msg);
   my ($dup1, $dup2);
    my ($tmpsrc);
   # compare @v8_srcs, with @v6_srcs
   my $v8_tot = scalar @v8_srcs;
   my $v6_tot = scalar @v6_srcs;
   prt( "\nCompare of sources " );
   prt( "MSVC 8 total = $v8_tot, with " ); 
   prt( "MSVC 6 total = $v6_tot\n" );
   $fnd = 0;
   $matched = 0;
   # clear the compare flag
   for ($i1 = 0; $i1 < $v8_tot; $i1++) {
      $v8_srcs[$i1][4] = 0;
   }
   # clear compare flags
   for ($i2 = 0; $i2 < $v6_tot; $i2++) {
      $v6_srcs[$i2][4] = 0;
   }
   if ($chk4dups) {
      prt( "Check $v8_tot VC8 for DUPLICATES ...\n" );
      $dup1 = 0;
      for ($i1 = 0; $i1 < $v8_tot; $i1++) {
         if( $v8_srcs[$i1][4] ) {
            next;
         }
         $ff1  = $v8_srcs[$i1][1];
         for ($i2 = 0; $i2 < $v8_tot; $i2++) {
            if ($i1 != $i2) {
               if( $v8_srcs[$i2][4] ) {
                  next;
               }
               $ff2  = $v8_srcs[$i2][1];
               if (is_same_DOS_file($ff1,$ff2)) {
                  $v8_srcs[$i2][4] = -1;   # MARK IT DUPLICATE
                  prt( "Found VC8 duplicate [$ff2]\n" );
                  $dup1++;
               }
            }   
         }
      }
      prt( "Found $dup1 of $v8_tot VC8 DUPLICATES ...\n" );
      prt( "Check $v6_tot VC6 for DUPLICATES ...\n" );
      $dup2 = 0;
      for ($i2 = 0; $i2 < $v6_tot; $i2++) {
         if ($v6_srcs[$i2][4]) {
            next;
         }
         $ff1  = $v6_srcs[$i2][1];
         for ($i1 = 0; $i1 < $v6_tot; $i1++) {
            if ($i1 != $i2) {
               if ($v6_srcs[$i1][4]) {
                  next;
               }
               $ff2  = $v6_srcs[$i1][1];
               if (is_same_DOS_file($ff1,$ff2)) {
                  $v6_srcs[$i1][4] = -1;   # MARK IT DUPLICATE
                  prt( "Found VC6 duplicate [$ff2]\n" );
                  $dup2++;
               }
            }
         }
      }
      prt( "Found $dup2 of $v6_tot VC6 DUPLICATES ...\n" );
   }
   for ($i1 = 0; $i1 < $v8_tot; $i1++) {
      $src1 = $v8_srcs[$i1][0];
      $ff1  = $v8_srcs[$i1][1];
      $fnm1 = $v8_srcs[$i1][2];
      $typ1 = $v8_srcs[$i1][3];
      $flg1 = $v8_srcs[$i1][4];
      if ($chk4dups && $flg1) {
         next;
      }
      ($nm1,$pth1,$suf1) = fileparse( $src1 );
      $msg = "$i1 $nm1 ($ff1) - "; 
      $fnd = 0;
      for ($i2 = 0; $i2 < $v6_tot; $i2++) {
         $src2 = $v6_srcs[$i2][0];
         $ff2  = $v6_srcs[$i2][1];
         $fnm2 = $v6_srcs[$i2][2];
         $typ2 = $v6_srcs[$i2][3];
         $flg2 = $v6_srcs[$i2][4];
         if ($chk4dups && $flg2) {
            next;
         }
         ($nm2,$pth2,$suf2) = fileparse( $src2 );
         if (is_same_DOS_file($ff1,$ff2)) {
            $v6_srcs[$i2][4] = ($i1 + 1);   # put offset + 1 to VC8
            $v8_srcs[$i1][4] = ($i2 + 1);   # put offset + 1 to VC6
            $fnd = 1;
            last;
         }
      }
      if ($fnd) {
         $msg .= "ok";
         $matched++;
      } else {
         $msg .= "NO MATCH";
      }
      prt( "$msg\n" ) if ($big_dbg);
   }
   $added = $v8_tot - $matched;
   $subed = $v6_tot - $matched;
   $miss1 = 0;
   $miss2 = 0;
   for ($i1 = 0; $i1 < $v8_tot; $i1++) {
      if ($v8_srcs[$i1][4] == 0) {
         $miss1++;
      }
   }
   for ($i2 = 0; $i2 < $v6_tot; $i2++) {
      if ($v6_srcs[$i2][4] == 0) {
         $miss2++;
      }
   }
    # show RESULTS of COMPARE of EXISTING and about to be CREATED DSP file
   prt( "Matched $matched of $v8_tot, with $matched of $v6_tot ...\n" );
   if (($added == 0) && ($subed == 0)) {
      prt( "DSP appears EQUIVALENT to VCPROJ file - perhaps no DSP modification needed.\n" );
   } else {
      if ($v6_tot > 0) {
         prt( "DSP needs to be MODIFIED ... add = $added, subed = $subed\n" );
      } else {
         prt( "DSP will be CREATED ... with $added sources ...\n" );
      }
   }
   if ($miss1) {
      prt( "There are $miss1 files in VCPROJ, NOT in DSP\n" );
      for ($i1 = 0; $i1 < $v8_tot; $i1++) {
         if ($v8_srcs[$i1][4] == 0) {
            $src1 = $v8_srcs[$i1][0];
            $ff1  = $v8_srcs[$i1][1];
            $msg = "$src1 ($ff1) ";
            if (-f $ff1) {
               $msg .= "ok";
            } else {
                  $msg .= "NOT FOUND";
            }
            prt( "$msg\n" );
         }
      }
   }
   if ($miss2) {
      prt( "There are $miss2 files in DSP, NOT in VCPROJ\n" );
      for ($i2 = 0; $i2 < $v6_tot; $i2++) {
         if ($v6_srcs[$i2][4] == 0) {
            $src2 = $v6_srcs[$i2][0];
            $ff2  = $v6_srcs[$i2][1];
            $msg = "$src2 ($ff2) ";
            if (-f $ff2) {
               $msg .= "ok";
            } else {
               $msg .= "NOT FOUND";
            }
            prt( "$msg\n" );
         }
      }
   }
   prt("\n");
   return ($added + $subed);   # return CHANGE counter
}
sub is_same_DOS_file {
   my ($f1, $f2) = @_;
   prt( "Comparing [$f1] with [$f2] " ) if ($dbg12);
   my $len = length($f1);
   if ($len != length($f2)) {
      prt( "Len $len != ".length($f2)."\n" ) if ($dbg12);
      return 0;   # not the SAME
   }
   $f1 =~ s/\//\\/g;
   $f2 =~ s/\//\\/g;
   my $lcf1 = lc($f1);
   my $lcf2 = lc($f2);
   my $i = 0;
   while ($i < $len) {
      if (substr($lcf1,$i,1) ne substr($lcf2,$i,1)) {
         prt( "Diff at $i\n" ) if ($dbg12);
         return 0;
      }
      $i++;
   }
   prt( "SAME\n\n" ) if ($dbg12);
   return 1;
}
sub process_DSW {
   my ($fil) = shift;
   my ($pnm, $pfil, $ff, $line, $lncnt);
   my ($msg);
   prt( "\nProcess DSW file $fil ... " );
   if ( -f $fil ) {
      my ($p_name,$p_dir) = fileparse($fil);
      prt( "already exists ... $p_name in [$p_dir] ...\n" );
      # Project: "mirror"=.\mirror.dsp - Package Owner=<4>
      open IF, "<$fil" or mydie( "ERROR: Unable to open FILE! ... $! ...\n" );
      @dsw_file = <IF>;   # slurp it in, and keep it
      close IF;   # close file
      $lncnt = scalar @dsw_file;
      prt( "Processing $lncnt lines from file ...\n" )if ($dbg_dsw3);
      foreach $line (@dsw_file) {
            chomp $line;
         prt( "$line\n" ) if ($dbg_dsw1);
         #####if ($line =~ /Project:\s+\"(\w+)\"=([\.\w\\]+)+\s*/) {
         if ($line =~ /^Project:\s+"([\w\.]+)"="*([\w\.\\-]+)"*\s+/) {
            $pnm = $1;
            $pfil = $2;
            $ff = $p_dir.$pfil;
            $msg = "Project: name=$pnm, file=$pfil ff=$ff ...";
            if ( -f $ff) {
               $msg .= "ok";
               push(@dsp_files, [$pfil, $ff, $pnm]); # [file, fullpath, and project NAME]
               prt( "$msg\n" ) if ($dbg_dsw2);
            } else {
               $msg .= "FAILED! CHECK ME!!";
               prtw( "WARNING: $msg\n" );
            }
         } elsif ($line =~ /Project:/i) {
                prtw( "WARNING: MISSED PROJECT [$line]\n" );
            }
      }
      if (@dsp_files) {
         prt( "Got ".scalar @dsp_files." projects from $fil ...\n" );
      } else {
         prtw( "Warning: No projects found in $fil!!!\n" );
      }
   } else {
      prt( "*** DOES NOT EXIST ***\n" );
   }
}
sub process_DSP {
   my ($proj, $fil) = @_;
   my ($line, $prjname, $grpname, $filter, $ff, $src, $chr, $tmp, $conf, $ffnr);
   my ($itm1, $itm2, $key, $targtype);
   my $scnt = 0;
   my @dsp_lines = ();
   prt( "\nProcess DSP file $fil ... " );
   if ( -f $fil ) {
      prt( "already exists ...\n" );
      my ($name,$dir,$suffix) = fileparse($fil);
      if ( open IF, "<$fil" ) {
         @dsp_lines = <IF>;
         close IF;
         prt( "Got ".scalar @dsp_lines." lines to process ...\n" );
         my $ins = 0;
         foreach $line (@dsp_lines) {
            $line = trim_all($line);
            $chr = substr($line, 0, 1);   # get FIRST char of LINE
            if( $chr eq '#' ) {
               # line begins with SHARP
               if ($line =~ /\s+Microsoft Developer Studio Project File - Name=\"([\.\w\s]+)+/) {
                  $prjname = $1;
                  prt( "Project NAME = $prjname ...\n" ) if ($dbg_dsp);
               } elsif ($line =~ /\s+Microsoft Developer Studio Generated Build File, Format Version ([\d\.]+)/) {
                  prt( "MSVC Version $1 ...\n" ) if ($dbg_dsp);
               } elsif ($line =~ /\s*TARGTYPE\s+\"(.+)\"\s+/) { # Win32 (x86) Console Application" 0x0103
                  $targtype = $1;
                  prt( "TARGTYPE: $targtype, name=$prjname ($proj)\n" );
               } elsif ($line =~ /Begin Group \"([\s\w]+)+/ ) {
                  $grpname = $1;
                  prt( "Begin group ... $grpname\n" ) if ($dbg_dsp);
               } elsif ($line =~ /PROP\s+Default_Filter\s+\"([\w;]+)+\"/ ) {
                  $filter = $1;
                  prt( "Begin Filter group $grpname, filter $filter\n" ) if ($dbg_ds8);
               } elsif ($line =~ /Begin Source File/) {
                  $ins = 1;
                  prt( "Begin source ... $ins ...\n" ) if ($dbg_dsp);
               } elsif ($line =~ /End Source File/) {
                  $ins = 0;
                  prt( "End source ... $ins ...\n" ) if ($dbg_dsp);
               } elsif ( $line =~ /ADD BASE CPP (.+)/ )  {
                  # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
                  $key = 'CPP '.$conf;
                  prt( "ADD BASE $key [$1]\n" ) if ($dbg_ds4);
                  $v6_conf{$key} = $1;
               } elsif ( $line =~ /ADD CPP (.+)/ )  {
                  # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
                  $key = 'CPP '.$conf;
                  prt( "ADD $key [$1]\n" ) if ($dbg_ds4);
                  $v6_conf{$key} = $1;
               } elsif ( $line =~ /ADD BASE LINK32 (.+)/ )  {
                  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
                  $key = 'LINK '.$conf;
                  prt( "ADD BASE $key [$1]\n" ) if ($dbg_ds4);
                  $v6_conf{$key} = $1;
               } elsif ( $line =~ /ADD LINK32 (.+)/ )  {
                  $key = 'LINK '.$conf;
                  # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
                  prt( "ADD $key [$1]\n" ) if ($dbg_ds4);
                  $v6_conf{$key} = $1;
               }
            } elsif ( $chr eq '!' ) {
               if ($line =~ /^!IF\s+(.+)/i ) {
                  prt( "Entering IF $1 ...\n" ) if ($dbg_ds6);
                  if ($line =~ /!IF\s+(.+) == (.+)/i) {
                     $itm1 = $1;
                     $itm2 = $2;
                     $itm1 =~ s/\"//g;
                     $itm2 =~ s/\"//g;
                     prt( "Got [$itm1] [$itm2]...\n" ) if ($dbg_ds6);
                     if ($itm1 =~ /^\$\((.+)\)/ ) {
                        if (defined $v6_defs{$1}) {
                           if ($v6_defs{$1} eq $itm2) {
                              $tmp = "TRUE";
                           } else {
                              $tmp = "FALSE";
                           }
                           if( $1 eq 'CFG' ) {
                              $conf = $itm2;
                           }
                           prt( "and [$1] defined as \"$v6_defs{$1}\" ... $tmp $conf\n" ) if ($dbg_ds6);
                        } else {
                           prt( "NOT DEFINED [$1] ...\n" );
                        }
                     }
                  } else {
                     prt( "FAILED IF == [$line]\n" );
                  }
               } elsif ( $line =~ /^!ELSE\s+/i ) {
                  prt( "Entering ELSE ...\n" ) if ($dbg_ds6);
               } elsif ( $line =~ /^!ELSEIF\s+(.+)/i ) {
                  prt( "Entering ELSEIF $1 ...\n" ) if ($dbg_ds6);
                  if ($line =~ /!ELSEIF\s+(.+) == (.+)/i) {
                     $itm1 = $1;
                     $itm2 = $2;
                     $itm1 =~ s/\"//g;
                     $itm2 =~ s/\"//g;
                     prt( "Got [$itm1] [$itm2]...\n" ) if ($dbg_ds6);
                     if ($itm1 =~ /^\$\((.+)\)/ ) {
                        if (defined $v6_defs{$1}) {
                           if ($v6_defs{$1} eq $itm2) {
                              $tmp = "TRUE";
                           } else {
                              $tmp = "FALSE";
                           }
                           if( $1 eq 'CFG' ) {
                              $conf = $itm2;
                           }
                           prt( "and [$1] defined as \"$v6_defs{$1}\" ... $tmp $conf\n" ) if ($dbg_ds6);
                        } else {
                           prt( "NOT DEFINED [$1] ...\n" );
                        }
                     }
                  } else {
                     prt( "FAILED ELSEIF == [$line]\n" );
                  }
               } elsif ( $line =~ /^!ENDIF\s*/i ) {
                  prt( "Out ENDIF ...\n" ) if ($dbg_ds6);
               }
            } else {
               if ($line =~ /SOURCE=([\.\\\w-]+)+/ ) {
                  $src = $1;
                  $ff = $dir.$src;
                  $ffnr = fix_rel_path($ff);
                  if ($ins) {
                     prt( "SOURCE = $src ($ff)... $ins \n" ) if ($dbg_dsp);
                  } else {
                     prt( "source = $src ($ff) OUTSIDE 'in source' ... $ins\n" );
                  }
                  if (is_c_source($src)) {
                     prt("SOURCE=[$src]\n") if ($dbg_ds1);
                  } elsif (is_h_source($src)) {
                     prt("HEADER=[$src]\n") if ($dbg_ds2);
                  } elsif (is_h_special($src)) {
                     prt("HEADER=[$src]\n") if ($dbg_ds2);
                  } else {
                     prt("OTHER=[$src] ($line)\n") if ($dbg_ds3);
                  }
                  #                0     1      2          3          4  5  6
                  #push(@v6_srcs, [$src, $ffnr, $filtname, $filttype, 0, 0, $projname] );
                  push(@v6_srcs, [$src, $ffnr, $grpname, $filter, 0, 0, $proj] );
                  $scnt++;
                  prt( "$scnt v6_srcs: $src, $ffnr, $grpname, $filter, 0, 0, $proj\n" ) if ($dbg_ds9);
               } elsif ( $line =~ /(.*)=(.*)/ ) {
                  $itm1 = $1;
                  $itm2 = $2;
                  $v6_defs{$itm1} = $itm2;
                  prt( "Defined [$itm1] = [$itm2] ...\n" ) if ($dbg_ds5);
               }
            }
         }
         prt( "End DSP - got $scnt source files ...\n" );
         if ($dbg_ds7) {
            foreach $key (keys %v6_conf) {
               prt( "Config $key = [$v6_conf{$key}]\n" );
            }
         }
      } else {
         prtw( "ERROR: FAILED TO OPEN $fil FILE!\n" );
      }
   } else {
      prt( "*** DOES NOT EXIST ***\n" );
   }
}
#################################################
##### VCPROJ XML PARSING #####
#################################################
sub get_xml_tag {
   my ($lin) = shift;
   my $len = length($lin);
   my $tag = '';
   my $pch = '';
   for (my $t = 0; $t < $len; $t++) {
      my $ch = substr($lin,$t,1);
      if ($ch eq '<') {
         prtw( "WARNING: Second TAG in line! ($lin)\n" ) if (length($tag));
         $tag = '';
         $t++;
         for ( ; $t < $len; $t++) {
            $ch = substr($lin,$t,1);
            if ($ch =~ /\s/) {
               # end of tag
               $t++;
               for ( ; $t < $len; $t++) {
                  $ch = substr($lin,$t,1);
                  if ($ch eq '>') {
                     $tag .= $pch if ($pch eq '/');
                     prtw( "WARNING: Premature CLOSE! ($lin)(1)\n" ) if (($t +1) < $len);
                     last;   # end of TAG
                  }
                  $pch = $ch;   # keep last
               }
               last;
            } elsif ($ch eq '>') {
               prtw( "WARNING: Premature CLOSE! ($lin)(2)\n" ) if (($t +1) < $len);
               last;
            }
            $tag .= $ch;
         }
      }
   }
   return $tag;
}
sub tag_typ_2_stg {
   my ($typ) = shift;
   if ($typ == $TYP_OPEN) {
      return "OPEN";
   } elsif ($typ == $TYP_CLOSE) {
      return "CLOSE";
   } elsif ($typ == $TYP_OPENCLOSE) {
      return "OPENCLOSE";
   } elsif ($typ == $TYP_VERSION) {
      return "VERSION";
   }
   return "UNKNOWN";
}
sub get_tag_typ {
   my ($xt) = shift;
   my $typ = $TYP_OPEN;
   if ($xt =~ /^\//) {
      $typ = $TYP_CLOSE;
   } elsif ($xt =~ /\/$/) {
      $typ = $TYP_OPENCLOSE;
   } elsif ($xt eq '?xml') {
      $typ = $TYP_VERSION;
   }
   ###prt( "For [$xt] returning [$typ] ...\n" );
   return $typ;
}
# get application type
# one of Console Application, Application, static library, dynamic library
# get application type
# one of Console Application, Application, static library, dynamic library
sub fg_get_app_type {
   my ($defs, $ln) = @_;
   my ($def, $key);
   my @arr = split(';',$defs);
   foreach $def (@arr) {
      foreach $key (keys %v8_defines) {
         if ($def eq $key) {
            return $v8_defines{$key};
         }
      }
   }
   # ok, nothing found - TRY HARDER
   foreach $def (@arr) {
      if ($def =~ /BUILD_LIBRARY/) {
         return $v8_defines{'_LIB'};
      } elsif ($def =~ /STATIC/) {
         return $v8_defines{'_LIB'};
      }
   }
   # UGH - still NOT FOUND - provide overrides for
   foreach $def (@special_typing) {
      if ($act_vcproj =~ /$def/) {
            if ($dbg_x02) {
                prtw( "WARNING: String [$defs] no clue to TYPE!!!\n".
                    "Typed from special_typing list!\n".
                    "$ln: $act_vcproj - return static library ??? CHECK ME\n" );
            }
         return $v8_defines{'_LIB'};
      }
   }
   prtw( "WARNING: String [$defs] does not give clue to TYPE!!!\n$ln: $act_vcproj - return def $typelse ??? CHECK ME\n" );
   return $typelse;
}
sub get_app_type {
   my ($defs) = shift;
   my ($def, $key);
   my @arr = split(';',$defs);
   foreach $def (@arr) {
      foreach $key (keys %v8_defines) {
         if ($def eq $key) {
            return $v8_defines{$key};
         }
      }
   }
   # ok, nothing found - TRY HARDER
   foreach $def (@arr) {
      if ($def =~ /BUILD_LIBRARY/) {
         return $v8_defines{'_LIB'};
      } elsif ($def =~ /STATIC/) {
         return $v8_defines{'_LIB'};
      }
   }
   # UGH - still NOT FOUND - provide overrides for
   foreach $def (@special_typing) {
      if ($act_vcproj =~ /$def/) {
         return $v8_defines{'_LIB'};
      }
   }
   prtw( "Warning: String [$defs] does not give clue to TYPE!!!\n$act_vcproj - return def $typelse ??? CHECK ME\n" );
   return $typelse;
}
# @arr = split_conf( $dsp_defines_dbg );
sub split_conf {
   my ($cc) = shift;
   my $ln = length($cc);
   my @ar = ();
   my $itm = '';
   for (my $p = 0; $p < $ln; $p++) {
      my $ch = substr($cc,$p,1);
      if ($ch eq '"') {
         $p++;
         $itm = '';
         for (; $p < $ln; $p++) {
            $ch = substr($cc,$p,1);
            if ($ch eq '"') {
               last;
            }
            $itm .= $ch;
         }
         push(@ar,$itm) if length($itm);
      }
   }
   return @ar;
}
sub is_in_skip_conf_rel {
   my ($itm) = shift;
   foreach my $tst (@dsp_base_defs_rel) {
      if ($itm eq $tst) {
         return 1;
      }
   }
   return 0;
}
sub is_in_skip_conf_dbg {
   my ($itm) = shift;
   foreach my $tst (@dsp_base_defs_dbg) {
      if ($itm eq $tst) {
         return 1;
      }
   }
   return 0;
}
sub is_in_skip_lib_rel {
   my ($itm) = shift;
   foreach my $tst (@dsp_base_libs_rel) {
      if ($itm =~ /$tst/i) {
         return 1;
      }
   }
   return 0;
}
sub is_in_skip_lib_dbg {
   my ($itm) = shift;
   foreach my $tst (@dsp_base_libs_dbg) {
      if ($itm =~ /$tst/i) {
         return 1;
      }
   }
   return 0;
}
sub set_runtime_dbg { $dsp_runtime_dbg = shift; }
sub set_runtime_rel { $dsp_runtime_rel = shift; }
# new 21/09/2008
sub set_includes {
    my ($txt, $ref) = @_;
    my @av = split(/[,;]/, $txt);
    foreach my $tx (@av) {
        if (length($tx)) {
            $$ref .= ' ' if length($$ref);
            # remove any existing quotes, but add quotes for sure
            $$ref .= '/I '.add_quotes(strip_quotes($tx));
        }
    }
}
sub set_includes_dbg {
    my ($txt) = shift;
    set_includes( $txt, \$dsp_includes_dbg );
}
sub set_includes_rel {
    my ($txt) = shift;
    set_includes( $txt, \$dsp_includes_rel );
}
sub get_group_type {
    my ($src) = shift;
    my ($n,$d,$s) = fileparse($src, qr/\.[^.]*/ );
    my (@arr, $ext, $ex);
    $ex = substr($s,1) if ($s =~ /^\./);
    $ex = lc($ex);
    if (length($ex) == 0) {
        return GRP_HDR; # default to header is NO EXT
    }
    @arr = split(';', $def_src_g);
    foreach $ext (@arr) {
        if ($ext eq $ex) {
            return GRP_SRC;
        }
    }
    @arr = split(';', $def_hdr_g);
    foreach $ext (@arr) {
        if ($ext eq $ex) {
            return GRP_HDR;
        }
    }
    @arr = split(';', $def_rcs_g);
    foreach $ext (@arr) {
        if ($ext eq $ex) {
            return GRP_RCS;
        }
    }
    @arr = split(';', $def_spl_g);
    foreach $ext (@arr) {
        if ($ext eq $ex) {
            return GRP_SPL;
        }
    }
    prt( "CHECK EXTENSION: What group [$src], with ext [$s] or [$ex] ...\n" );
    return GRP_UNK; # not found, so UNKNOWN
}
sub get_def_group_name {
    my ($grp) = shift;
    if ($grp == GRP_SRC) {
        return $def_src_nm;
    }
    if ($grp == GRP_HDR) {
        return $def_hdr_nm;
    }
    if ($grp == GRP_RCS) {
        return $def_rcs_nm;
    }
    if ($grp == GRP_SPL) {
        return $def_spl_nm;
    }
    return $def_unknown." Group";
}
sub get_def_group_filter {
    my ($grp) = shift;
    if ($grp == GRP_SRC) {
        return $def_src_g;
    }
    if ($grp == GRP_HDR) {
        return $def_hdr_g;
    }
    if ($grp == GRP_RCS) {
        return $def_rcs_g;
    }
    if ($grp == GRP_SPL) {
        return $def_spl_g;
    }
    return $def_unknown." Filter";
}
sub get_tt_string {
    my ($val) = shift;
    if ($val == TT_UNK) {
        return "Unknown";
    } elsif ($val == TT_BGN) {
        return 'Begin';
    } elsif ($val == TT_END) {
        return 'End';
    } elsif ($val == TT_BE) {
        return 'BE';
    } elsif ($val == TT_DEC) {
        return 'Decl';
    }
    return "MISSED IT";
}
# search forward in the XML line array
# assumed to be already arranged in neat XML lines
# and if 'ExcludedFromBuild' found in FileConfiguration
sub exclude_from_build {
    my ($j) = shift;
    my $max = scalar @xml_lines;
    for ( ; $j < $max; $j++) {
        my $ln = trim_all( $xml_lines[$j] );
      my $xt = get_xml_tag($ln);
        prt( "DEBUG:$j: line=[$ln], tag=[$xt]\n" ) if ($dgb_x05);
        my %ah = array_2_hash_on_equals(space_split($ln));
        if (($xt eq 'File') && ( defined $ah{'RelativePath'} ) ) {
            # good START
            $j++;   # got to NEXT line, and go until </File>
            $ln = trim_all( $xml_lines[$j] );
          $xt = get_xml_tag($ln);
            if ($ln =~ /<\/File>/) {
                prt( "DEBUG:$j:LAST: line=[$ln], tag=[$xt]\n" ) if ($dgb_x05);
                last;
            }
            %ah = array_2_hash_on_equals(space_split($ln));
            if ($ln =~ /<FileConfiguration/) {
                my $cfg = "unknown";
                if (defined $ah{'Name'}) {
                    $cfg = $ah{'Name'};
                }
                if (defined $ah{'ExcludedFromBuild'}) {
                    my $res = strip_quotes(trim_all($ah{'ExcludedFromBuild'}));
                    if ($res eq 'true') {
                        prt( "DEBUG:$j:true: cfg=$cfg, line=[$ln], tag=[$xt]\n" ) if ($dgb_x05);
                        return 1;
                    } else {
                        prt( "DEBUG:$j:false: cfg=$cfg, line=[$ln], tag=[$xt]\n" ) if ($dgb_x05);
                        return 0;
                    }
                }
            }
            prt( "DEBUG:$j: line=[$ln], tag=[$xt]\n" ) if ($dgb_x05);
        } else {
            last;
            prtw( "WARNING: Failed to get <File RelativePath>\n" );
            mydie( "FIX ME FIRST!\n" );
        }
    }
    return 0;
}
sub reline_xml {
    my (@lns) = @_;
    my $intag = 0;
    my $text = '';
    my @nlines = ();
    my @tagmap = ();
    my ($ln, $ch, $pch, $nch, $len, $i, $i2, $tag, $xml, $dnx);
    $pch = '';
    $nch = '';
    $tag = '';
    $xml = '';
    $dnx = 0;
    foreach $ln (@lns) {
        chomp $ln;
        $ln = trim_all($ln);
        $len = length($ln);
        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
                if ( !$dnx && (($ch eq ' ')||($ch eq "\t")||($ch =~ /\s/)) ) {
                    $dnx = 1;
                    $xml = substr($tag,1);
                    if ($xml =~ /^\?/) {
                        push(@tagmap, [$xml, TT_DEC, 1]);
                    } elsif ($xml =~ /^\//) {
                        $xml = substr($xml,1);
                        push(@tagmap, [$xml, TT_END, 1]);
                    } else {
                        push(@tagmap, [$xml, TT_BGN, 1]);
                    }
                }
                $tag .= $ch;
                if ($ch eq '>') {
                    # end of XML tag
                    if (!$dnx) {
                        $xml = substr($tag,1,length($tag)-2);
                        if ($xml =~ /^\?/) {
                            push(@tagmap, [$xml, TT_DEC, 2]);
                        } elsif ($xml =~ /^\//) {
                            $xml = substr($xml,1);
                            push(@tagmap, [$xml, TT_END, 2]);
                        } elsif ($pch eq '/') {
                            push(@tagmap, [$xml, TT_BE, 2]);
                        } else {
                            push(@tagmap, [$xml, TT_BGN, 2]);
                        }
                    } else {
                        if ($pch eq '/') {
                            $tagmap[-1][1] = TT_BE;
                        }
                    }
                    push(@nlines,$tag);
                    $tag = '';
                    $intag = 0;
                    $xml = '';
                }
            } else {
                if ($ch eq '<') {
                    $tag = $ch;
                    $intag = 1;
                    $xml = '';
                    $dnx = 0;
                }
            }
            $pch = $ch;
        }
        # done a line - this is like a SPACE
        if ($intag && length($tag)) {
            if ( !$dnx ) {
                $dnx = 1;
                $xml = substr($tag,1);
                if ($xml =~ /^\?/) {
                    push(@tagmap, [$xml, TT_DEC, 3]);
                } elsif ($xml =~ /^\//) {
                    $xml = substr($xml,1);
                    push(@tagmap, [$xml, TT_END, 3]);
                } else {
                    push(@tagmap, [$xml, TT_BGN, 3]);
                }
            }
            $tag .= ' ' if !($tag =~ /\s$/);
        }
    }
    if (length($tag)) {
        prtw("WARNING: xml re-lining error! Left pending tag [$tag]\nin $act_vcproj file ...\n");
    }
    # store global tag map, and lines
    @xml_tag_map = @tagmap;
    @xml_lines = @nlines;
    if ($dbg_x01) {
        $ln = 0;
        $tag = '';
        foreach $xml (@nlines) {
            $ln++;
            $tag .= "$ln: $xml\n";
        }
        write2file( $tag, 'tempxml.txt');
        #write2file( join("\n",@nlines), 'tempxml.txt');
        $len = scalar @tagmap;
        $ln = '';
        for ($i = 0; $i < $len; $i++) {
            $tag = $tagmap[$i][0];
            $ch = $tagmap[$i][1];
            $nch = $tagmap[$i][2];
            $pch = get_tt_string($ch);
            $ln .= "$tag $pch ($ch) [$nch]\n";
        }
        write2file( $ln, 'tempxml2.txt' );
    }
    return @nlines;
}
sub fg_reline_xml {
    my (@lns) = @_;
    my $intag = 0;
    my $text = '';
    my @nlines = ();
    my @tagmap = ();
    my @xlnmap = ();
    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
                if ( !$dnx && (($ch eq ' ')||($ch eq "\t")||($ch =~ /\s/)) ) {
                    $dnx = 1;
                    $xml = substr($tag,1);
                    if ($xml =~ /^\?/) {
                        push(@tagmap, [$xml, TT_DEC, 1]);
                    } elsif ($xml =~ /^\//) {
                        $xml = substr($xml,1);
                        push(@tagmap, [$xml, TT_END, 1]);
                    } else {
                        push(@tagmap, [$xml, TT_BGN, 1]);
                    }
                }
                $tag .= $ch;
                if ($ch eq '>') {
                    # end of XML tag
                    if (!$dnx) {
                        $xml = substr($tag,1,length($tag)-2);
                        if ($xml =~ /^\?/) {
                            push(@tagmap, [$xml, TT_DEC, 2]);
                        } elsif ($xml =~ /^\//) {
                            $xml = substr($xml,1);
                            push(@tagmap, [$xml, TT_END, 2]);
                        } elsif ($pch eq '/') {
                            push(@tagmap, [$xml, TT_BE, 2]);
                        } else {
                            push(@tagmap, [$xml, TT_BGN, 2]);
                        }
                    } else {
                        if ($pch eq '/') {
                            $tagmap[-1][1] = TT_BE;
                        }
                    }
                    $nlnm++;
                    push(@nlines,$tag);
                    ### prt( "push(\@xlnmap, [ $nlnm, $lnb, $lnnm ]); # each NEW line has BEGIN and END\n" );
                    push(@xlnmap, [ $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)) {
            if ( !$dnx ) {
                $dnx = 1;
                $xml = substr($tag,1);
                if ($xml =~ /^\?/) {
                    push(@tagmap, [$xml, TT_DEC, 3]);
                } elsif ($xml =~ /^\//) {
                    $xml = substr($xml,1);
                    push(@tagmap, [$xml, TT_END, 3]);
                } else {
                    push(@tagmap, [$xml, TT_BGN, 3]);
                }
            }
            $tag .= ' ' if !($tag =~ /\s$/);
        }
    }
    if (length($tag)) {
        prtw("WARNING: xml re-lining error! Left pending tag [$tag]\nin $act_vcproj file ...\n");
    }
    # store global tag map, lines, and a line map
    @xml_tag_map = @tagmap;
    @xml_lines = @nlines;
    @xml_line_map = @xlnmap;
    $xml_last_line = 0;
    if ($dbg_x01) {
        $ln = 0;
        $tag = '';
        foreach $xml (@nlines) {
            $ln++;
            $tag .= "$ln: $xml\n";
        }
        write2file( $tag, 'tempxml.txt');
        #write2file( join("\n",@nlines), 'tempxml.txt');
        $len = scalar @tagmap;
        $ln = '';
        for ($i = 0; $i < $len; $i++) {
            $tag = $tagmap[$i][0];
            $ch = $tagmap[$i][1];
            $nch = $tagmap[$i][2];
            $pch = get_tt_string($ch);
            $ln .= "$tag $pch ($ch) [$nch]\n";
        }
        write2file( $ln, 'tempxml2.txt' );
    }
    return @nlines;
}
### $v8_filter{$filtname} = merge_filters($v8_filter{$filtname}, $filttype); 
sub merge_filters {
    my ($f1, $f2) = @_;
    my @a1 = split(";",$f1);
    my @a2 = split(";",$f2);
    my $nf = '';
    foreach my $f (@a2) {
        # if new is not in old
        if (! is_in_array($f, @a1) ) {
            $nf .= ';' if length($nf);
            $nf .= $f;
        }
    }
    $f1 .= ';' if length($nf);
    $f1 .= $nf;
}
sub get_mapped_lines {
    my ($nln) = shift;
    my $max = scalar @xml_line_map;
    my $n = $xml_last_line;
    my $nn;
    for (; $n < $max; $n++) {
        $nn = $xml_line_map[$n][0]; # extract new line number
        if ($nln == $nn) {
            $xml_last_line = $n;
            my $res = "$nln:".$xml_line_map[$n][1].":".$xml_line_map[$n][2];
            ### prt( "Found [$nln] == [$nn] - return $res\n" );
            return $res;
        } elsif ($nn > $nln) {
            $xml_last_line = $n;
            my $res = "$nln:".$xml_line_map[$n][1].":".$xml_line_map[$n][2];
            ### prt( "Found [$nln] > [$nn] - return $res\n" );
            return $res;
        }
    }
    return "$nln:?:?";
}
# RUNTIME conversions
# #################################################
sub fg_get_runtime_val_2_lts {
   my ($rtn) = shift;
    my $len = scalar @runtimes_array;
    for (my $i = 0; $i < $len; $i++) {
        my $itm = $runtimes_array[$i][RT_VAL];  # [3];
        if ($itm == $rtn) {
            return "/" . $runtimes_array[$i][RT_LTS];   # [1];
        }
    }
    prtw( "WARNING: $rtn not found in runtimes_array! Using default '/$def_runtime_lts'!!\n" );
   return "/$def_runtime_lts";
}
# 24/09/2008 - convert letters to human string
sub fg_get_runtime_lts_2_stg {
   my ($rtn) = shift;
    my $len = scalar @runtimes_array;
    $rtn =~ s/^\///;    # remove any leading '/' ...
    for (my $i = 0; $i < $len; $i++) {
        my $itm = $runtimes_array[$i][RT_LTS];  # [1];
        if ($itm eq $rtn) {
            return $runtimes_array[$i][RT_STG]; # [2];
        }
    }
    prtw( "WARNING: [$rtn] not found in runtimes_array! Using default '$def_runtime_stg'!!\n" );
   return $def_runtime_stg;
}
sub fg_get_runtime_stg_2_val {
   my ($rtn) = shift;
    my $len = scalar @runtimes_array;
    for (my $i = 0; $i < $len; $i++) {
        my $itm = $runtimes_array[$i][RT_STG];
        if ($itm eq $rtn) {
            return $runtimes_array[$i][RT_VAL];
        }
    }
    prtw( "WARNING: [$rtn] not found in runtimes_array! Using default $def_runtime_val\n" );
   return $def_runtime_val;
}
sub fg_get_runtime_stg_2_lts {
   my ($rtn) = shift;
    my $len = scalar @runtimes_array;
    for (my $i = 0; $i < $len; $i++) {
        my $itm = $runtimes_array[$i][RT_STG];
        if ($itm eq $rtn) {
            return '/'.$runtimes_array[$i][RT_LTS];
        }
    }
    prtw( "WARNING: [$rtn] not found in runtimes_array! Using default /$def_runtime_lts\n" );
   return "/$def_runtime_lts";
}
# #################################################
# get_xml_source
# process the XML project file (*.vcproj) and
# extract the SOURCE file list,
# but do lots MORE than that ...
sub get_xml_sources {
   my ($in) = shift;
   my ($in_name,$in_fd,$in_suffix) = fileparse($in);
   my ($src, $ff, $pline);
   my $stf = '<File\\s+RelativePath=\\"([\\.\\\\\\w-]+)+\\"+(.)+';
   #my $filt = '^<Filter\\s+Name=\\"([\\w\\s]+)\\"\\s+Filter=\\"([\\w;]+)\\"';
   my @lines = ();
   my $line = '';
   my $filtname = '';
   my $filttype = '';
   my $conf = '';
   my $tname = '';
   my $version = 'Unknown';
   my $projname = '';
   my $srccount = 0;
   my @xmltags = ();
   my $xmltag = '';
   my $tagtyp = 0;
   my $lnnum = 0;
   my $nlnnum = 0;
   my $bgn = 0;
   my $end = 0;
   my $ll = 0;
   my $ch = '';
   my $bgnend = '';
   my $inconfigs = 0;
   my $ppdefs = '';
   my $apptype = '';   # one of the various types
   my $adddeps = '';
   my @attribs = ();
   my %atthash = ();
   my $ctype = 0;
   my $def = '';
   my ($func, $itm, $ffnr, $shr, $tmpsrc);
    my $dnaptype = 0;
    my $gottoolname = 0;
    my ($funcinc, $pname, $ProjectGUID, $ckey);
    my ($i, $j, $msg, $tmpdbg);
    my $infiles = 0;    # in the <Files> section of the XML
    my $cfgcount = 0;   # each file will have multiple 'configurations', and some things are global
    ### SET ACTIVE PROJECT FILE ###
    $act_vcproj = $in;
   prt( "\nLoading [$in] file in directory [$in_fd] ...\n" ) if ($dbg_x17);
   open FH, "<$in" or mydie( "ERROR: Can not open [$in] ... aborting ...\n" );
   @lines = <FH>; # slurp the whole file
   close( FH );
   my $fline = '';
    my $lncnt = scalar @lines;
   prt( "Processing VCPROJ $lncnt lines in $in ...\n" );
    $tot_vclines += $lncnt;
   my $hadver = 0;
    my $hadlibtool = 0;
    @lines = fg_reline_xml(@lines);
    $lncnt = scalar @lines;
    if ($lncnt != scalar @xml_tag_map) {
        prtw( "WARNING: xml lines $lncnt NOT SAME AS xml_tag_map ".scalar @xml_tag_map." CHECK THIS!\n" );
    }
   ###foreach $line (@lines) {
    for ($i = 0; $i < $lncnt; $i++) {
        $line = $lines[$i];
        $nlnnum++;  # bump the array line number
      $lnnum = get_mapped_lines($nlnnum);
      $line = trim_all($line);
      $ll = length($line);
      if ($ll) {
         if (length($fline)) {
            $fline .= ' '.$line;
         } else {
            $ch = substr($line,0,1);
            $fline .= $line;
            if ($ch eq '<') {
               $bgn = $lnnum;  # set the BEGIN line number
            }
         }
      } else {
         next;   # skip BLANK lines
      }
        # only get interested when the XML closes ...
      if ($fline =~ />/) {
         $bgnend = "$bgn-$lnnum";
         $bgn = -1;
         $xmltag = get_xml_tag($fline);
         $tagtyp = get_tag_typ($xmltag);
         prt( "$bgnend: $xmltag ".tag_typ_2_stg($tagtyp). " ($tagtyp)\n" ) if ($dbg_src9);
         @attribs = space_split($fline);
         %atthash = array_2_hash_on_equals(@attribs);
            if ($dbg_x08) {
                $ll = 0;
                prt( "dbg_x08: Showing _ALL_ for tag=[$xmltag], line=[$fline]\n" );
                foreach $ppdefs (sort @attribs) {
                    $ll++;
                    prt( "dbg_x08:ats:$ll: [$ppdefs]\n" );
                }
                $ctype = 0;
                foreach $ppdefs (sort keys %atthash) {
                    $ctype++;
                    prt( "dbg_x08:key:$ctype: [$ppdefs] = [".$atthash{$ppdefs}."]\n" );
                }
                if ($ll != $ctype) {
                    mydir( "DEAD IN THE WATER! Array size $ll not same as hash $ctype!!!\n" );
                }
            }
            $pname = '';
            if (defined $atthash{'Name'}) {
                $pname = strip_quotes(trim_all($atthash{'Name'}));
                prt( "tag=$xmltag, Name=$pname (ln=$lnnum)\n" ) if ($dbg_x04);
            }
         if ((defined $atthash{'<VisualStudioProject'}) || ($fline =~ /<VisualStudioProject\s+/)) {
                $version = '';
                $ProjectGUID = '';
                if (defined $atthash{'Version'}) {
                    $version = strip_quotes(trim_all($atthash{'Version'}));
                    $hadver = 1;
            }
                if (defined $atthash{'ProjectGUID'}) {
                    $ProjectGUID = strip_quotes(trim_all($atthash{'ProjectGUID'}));
                }
            $projname = $pname;
            ##prt( "$fline\n" );
            prt( "Project=$projname, v=$version GUID=$ProjectGUID\n" ) if ($dbg_src11);
                mydie( "BIG PROBLEM! project name is blank!!\n" ) if (length($projname) == 0);
         } elsif ($fline =~ /$stf/) {
            # <File RelativePath="src\FDM\SP\ACMS.cxx" >
            $src = $1;
                $act_file = $src;
            $ff = $in_fd . $src;
            $ffnr = fix_rel_path($ff);
            $itm = "MISSING";
                if (exclude_from_build($i)) {
                    $itm = $excl_mark; # "EXCLUDED";
                } elsif (-f $ffnr) {
               $itm = "ok";
               prt( "SRC: [$ffnr] $itm\n" ) if ($dbg_src16);
            } else {
                    if (is_c_source($src) || $dbg_src16) {
                    prt( "SRC: [$ffnr] $itm [$src][$ff] CHECKME!\n" );   # always SHOW MISSING if ($dbg_src16);
                    }
            }
                $act_disp = $itm;   # can be 'MISSED', 'EXCLUDED', or 'ok'
                if (is_c_source($src)) {
               prt("SOURCE=[$src]\n") if ($dbg_src1);
            } elsif (is_h_source($src)) {
               prt("HEADER=[$src]\n") if ($dbg_src2);
            } elsif (is_h_special($src)) {
               prt("HEADER=[$src]\n") if ($dbg_src2);
            } else {
               prt("OTHER=[$src]\n") if ($dbg_src3);
            }
            $srccount++;
                $shr = get_group_type($src);
            prt( "$srccount v8_srcs: $src, $ffnr, $filtname, $filttype, 0, 0, $projname);\n" ) if ($dbg11);
            #                0    1      2          3          4  5  6          7     8
            push(@v8_srcs, [$src, $ffnr, $filtname, $filttype, 0, 0, $projname, $shr, $itm] );
         } elsif ((defined $atthash{'<Filter'})||($fline =~ /<Filter\s+/)) {
            # <Filter Name="Source Files" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
            $filtname = ''; # = NO FILTER NAME, like Source Files
            $filttype = ''; # = NOR FILTER TYPE, like cpp;c;cxx;rc;def;r;odl;idl;hpj;bat
                if (defined $atthash{'Name'} ) {
                    $filtname = strip_quotes(trim_all($atthash{'Name'}));
                } elsif ($fline =~ /\s+Name=\"([\w\s]+)\"[\s>]+/) {
               $filtname = $1; # = Source Files
            }
                if (defined $atthash{'Filter'} ) {
                    $filttype = strip_quotes(trim_all($atthash{'Filter'}));
                } elsif ($fline =~ /\s+Filter=\"([\w;,]+)\"[\s>]+/) {
               $filttype = $1; # = cpp;c;cxx;rc;def;r;odl;idl;hpj;bat
            }
                if ( length($filtname) && length($filttype) ) {
                    if ( defined $v8_filter{$filtname} ) {
                        $v8_filter{$filtname} = merge_filters($v8_filter{$filtname}, $filttype); 
                    } else {
                        $v8_filter{$filtname} = $filttype;
                    }
                }
            prt("FILTNAME=[$filtname] [$filttype]\n") if ($dbg_src4);
         ###} elsif ($fline =~ /$v8_cfgexp/ ) {
            } elsif ($fline =~ /<Configuration\s+(.+)$/) {
            ##if ($fline =~ /<Configuration\s+.*Name=\"(\S+)\"\s/ )
                # <Configuration
                #  Name="LIB Release|Win32"
                #  OutputDirectory=".\Win32_LIB_Release"
                #  IntermediateDirectory=".\Win32_LIB_Release"
                #  ConfigurationType="4"
                #  InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
                #  UseOfMFC="0"
                #  ATLMinimizesCRunTimeLibraryUsage="false">
            #@attribs = space_split($fline);
            #%atthash = array_2_hash_on_equals(@attribs);
                if (length($pname)) {
                    $conf = $pname;
                } elsif (defined $atthash{'Name'} ) {
                    $adddeps = strip_quotes(trim_all($atthash{'Name'}));
                    $conf = $adddeps;
                } else {
                    mydie("ERROR: No 'Name' found in [$fline] - def to [$conf] CHECK THIS! In $act_vcproj!\n");
                }
                $ctype = 0;
                $def = '<UNKNOWN-CHECK-ME>';
                # the name can be 'Name="LIB Release|Win32"', as in libpng ...
                ###if ($conf =~ /^Debug\|/) { this is TOO restrictive, try
                # -NEW_INCS_[REL|DBG]-
                if ($conf =~ /Debug/i) {
                    $ctype = 1;
                    $def = $dsp_runtime_dbg;
                    $func = \&set_runtime_dbg;
                    $funcinc = \&set_includes_dbg;  # { $dsp_includes_dbg = shift; }
                } elsif ($conf =~ /Release/i) {
                    ###} elsif ($conf =~ /^Release\|/) { too restrictive
                    $ctype = 2;
                    $def = $dsp_runtime_rel;
                    $func = \&set_runtime_rel;
                    $funcinc = \&set_includes_rel;  # { $dsp_includes_rel = shift; }
                } else {
                    prtw( "WARNING: CHECK ME CONF: Not Debug or Release ... WHAT IS IT? [$conf] ASSUME RELEASE,\n".
                        "line=[$fline] ... \n".
                        "(ln=$lnnum) $act_vcproj!\n" );
                    $ctype = 2;
                    $def = $dsp_runtime_rel;
                    $func = \&set_runtime_rel;
                    $funcinc = \&set_includes_rel;  # { $dsp_includes_rel = shift; }
                }
                # my %v8_config = ();  #  by configuration, OutputDirectory=".\Release", IntermediateDirectory="Release",
                # and zlib = ConfigurationType="4", alut = ConfigurationType="2", fg = ConfigurationType="1"
                #  // This is an internal type to Visual Studio, it seems that:
                #  // 4 == static library
                #  // 2 == dll
                #  // 1 == executable
                #  // 10 == utility
                if (defined $atthash{'ConfigurationType'}) {
                    $adddeps = strip_quotes(trim_all($atthash{'ConfigurationType'}));
                    if (defined $v8_conftypes{$adddeps}) {
                        $apptype = $v8_conftypes{$adddeps};
                        $dnaptype = 1;  # signal, no need to try to parse defines
                    }
                }
                # 28/09/2008 - note, has quotes added
                # $dsp_output_dbg = $def_output_dbg;    # "-NEW_OUTD_DBG-" $out_dir
                # $dsp_output_rel = $def_output_rel;    # "-NEW_OUTD_REL-" $out_dir
                # $dsp_inter_dbg  = $def_inter_dbg;    # "-NEW_INTER_DBG-" $int_dir
                # $dsp_inter_rel  = $def_inter_rel;    # "-NEW_INTER_REL-" $int_dir
                $adddeps = '';
                if (defined $atthash{'OutputDirectory'}) {
                    $adddeps .= "$out_dir=".add_quotes(strip_dotrel(strip_quotes(trim_all($atthash{'OutputDirectory'}))));
                }
                if (defined $atthash{'IntermediateDirectory'}) {
                    $adddeps .= ' ' if length($adddeps);
                    $adddeps .= "$int_dir=".add_quotes(strip_dotrel(strip_quotes(trim_all($atthash{'IntermediateDirectory'}))));
                }
                if (defined $v8_config{$conf}) {
                    if (length($adddeps)) {
                        if ($v8_config{$conf} ne $adddeps) {
                            prtw("WARNING: conf $conf ALREADY in v8_config as ".$v8_config{$conf}."! Adding $adddeps!! (ln=$lnnum)\n" );
                        }
                    }
                } else {
                    $v8_config{$conf} = $adddeps;
                }
                $cfgcount++;
            prt( "Got configuration [$conf] [$projname] [$apptype] (ln=$lnnum, cnt=$cfgcount)\n" ) if ($dbg_src6);
         } elsif ($fline =~ /<Tool\s+(.*)$/ ) {
            #} elsif ($fline =~ /$v8_toolexp/ ) {
            $pline = $1;
            #@attribs = space_split($fline);
            #%atthash = array_2_hash_on_equals(@attribs);
                $gottoolname = 0;
                if (length($pname)) {
                    $tname = $pname;
                    $gottoolname = 1;
                } elsif (defined $atthash{'Name'}) {
                    $tname = strip_quotes(trim_all($atthash{'Name'}));
                    $gottoolname = 1;
                }
            #prt( "Got Tool $pline\n" ) if ($dbg_src7);
            if ($gottoolname || ($pline =~ /\s*Name=\"*(\w+)\"*/)) {
                    if (!$gottoolname) {
                   $tname = $1;
                    }
               prt( "Got Tool name $tname ...\n" ) if ($dbg_src7);
               if ($tname eq 'VCCLCompilerTool') {
                  # <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" />]
                  prt( "Is compiler tool ...[$fline] ... $conf ($ctype)\n" ) if ($dbg_src14);
                  ## @attribs = space_split($fline);
                  ## %atthash = array_2_hash_on_equals(@attribs);
                        # set the PREPROCESSOR defines
                        ###########################################################
                        $ppdefs = "";   # maybe NONE
                        if ( defined $atthash{'PreprocessorDefinitions'} ) {
                            $ppdefs = strip_quotes(trim_all($atthash{'PreprocessorDefinitions'}));
                            if ($inconfigs) {
                                # try to GUESS application type from this string - UGH
                                $adddeps = fg_get_app_type($ppdefs, $lnnum);
                                if (! $dnaptype || (length($apptype) == 0)) {
                                    prt( "Set APPTYPE:$conf: [$apptype] to [$adddeps] (ln=$lnnum)\n" ) if ($dbg_src8);
                                    $apptype = $adddeps;
                                }
                                prt( "Set DEFINES:$conf: [$ppdefs] $apptype ($ctype) (ln=$lnnum)\n" ) if ($dbg_src8);
                                ###$v8_link{$conf} = $ppdefs;
                                if (defined $v8_aptype{$conf}) {
                                    if ($v8_aptype{$conf} ne $apptype) {
                                        prtw( "WARNING: ALREADY HAVE [$conf] in v8_aptype, with [".$v8_aptype{$conf}."] which is NOT [$apptype]!!! (ln=$lnnum) $act_vcproj\n" );
                                    }
                                } else {
                                    prt( "Set APPTYPE:$conf: v8_aptype[$apptype] (ln=$lnnum)\n" ) if ($dbg_x15);
                                    $v8_aptype{$conf} = $apptype;
                                }
                                if (defined $v8_apptypes{$projname}) {
                                    if ($v8_apptypes{$projname} ne $apptype) {
                                        if ($cfgcount < 2) {
                                            # unexpected ...
                                            prtw( "WARNING: ALREADY HAVE [$projname]  in v8_apptypes with [".$v8_apptypes{$projname}."] which is NOT [$apptype]!!! (ln=$lnnum) $act_vcproj\n" );
                                            # but is expected if running 2nd or subsequent configurations
                                            # so no warning ...
                                        }
                                    }
                                } else {
                                    prt( "Set APPTYPE: in v8_apptypes[$projname] to [$apptype] (ln=$lnnum)\n" ) if ($dbg_src8);
                                    $v8_apptypes{$projname} = $apptype;
                                }
                                $v8_link{$conf} = $ppdefs;  # set it PREPROCESSOR DEFINES ...
                            } elsif (length($ppdefs)) {
                                prtw( "WARNING: Got DEFS: $conf [$1] OUTSIDE Configurations! (ln=$lnnum) $act_vcproj\n" ); # if ($dbg_src10);
                            }
                        } else {
                            if ($inconfigs) {
                                prtw( "WARNING: Got NO 'PreprocessorDefinitions' for $conf - $act_vcproj!\n" );
                            }
                        }
                        ############################################################
                  if ( defined $atthash{'RuntimeLibrary'} ) {
                            if ($inconfigs) {
                                $ppdefs = strip_quotes(trim_all($atthash{'RuntimeLibrary'}));
                                ###$itm = get_runtime_stg($ppdefs);
                                $itm = fg_get_runtime_val_2_lts($ppdefs);
                                if (($ctype == 1)||($ctype == 2)) {
                                    if ($itm eq $def) {
                                        prt( "Got RUNTIME:$conf: value [$ppdefs] ($ctype) $itm (= $def)\n" ) if ($dgb_src17);
                                    } else {
                                        $func->($itm);
                                        prt( "Set RUNTIME:$conf: value [$ppdefs] ($ctype) $itm (was $def)\n" ) if ($dgb_src17);
                                    }
                                } else {
                                    prtw( "WARNING:CHECKME:$conf: RUNTIME value [$ppdefs] ($ctype) $itm ($def) in $act_vcproj\n" );
                                }
                                if (defined $v8_runtim{$conf}) {
                                    if ($v8_runtim{$conf} ne $itm) {
                                        prtw( "WARNING: AREADY HAVE RUNTIME $conf of ".$v8_runtim{$conf}." versus $itm!! $act_vcproj\n" );
                                    }
                                } else {
                                    $v8_runtim{$conf} = $itm; # RUNTIME /MT or /MD, by configuration
                                }
                            } else {
                                prtw( "WARNING: Unhandled 'RuntimeLibrary' for $conf, $act_vcproj\n$lnnum: $fline\n$lnnum: $pline!\n" );
                            }
                  } else {
                            if ($inconfigs) {
                                prtw( "WARNING: Did NOT find 'RuntimeLibrary' for $conf in configs, $act_vcproj\n$lnnum: $fline\n$lnnum: $pline!\n" );
                            }
                        }
                        ##################################################################
                        ### set AdditionalIncludeDirectories - VERY IMPORTANT
                        ### push(@allarr, "$includes=[$cincs]"); -NEW_INCS_[DBG|REL]-
                        $ppdefs = '';
                  if ( defined $atthash{'AdditionalIncludeDirectories'} ) {
                            $ppdefs = strip_quotes(trim_all($atthash{'AdditionalIncludeDirectories'}));
                            $ppdefs =~ s/&quot;/"/g;
                            if ($inconfigs) {
                                $funcinc->($ppdefs);
                                prt("Set INCLUDES:$conf: to [$ppdefs]\n" ) if ($dbg_x14);
                                $v8_includ{$conf} = $ppdefs;
                            } else {
                                if (length($ppdefs)) {
                                    if (($act_disp ne 'EXCLUDED')||($dbg_x07)) {
                                        prtw("WARNING: Got 'AdditionalIncludeDirectories' = $ppdefs, outside configs unhandled!\n".
                                            "$conf $act_file $act_disp $act_vcproj [$fline]!!\n" );
                                    }
                                }
                            }
                        } else {
                            if ($inconfigs) {
                                $v8_includ{$conf} = $ppdefs;    # set NONE
                            }
                        }
                        ##################################################################
                  prt( "Done VCCLCompilerTool atthash for $conf ...\n" )  if ($dbg_src15);
               } elsif ($tname eq 'VCLinkerTool') {
                        # this SUGGESTS an application or DLL, per ??? value
                        # SubSystem="1" - :console or "2" :window
                  # <Tool
                  # Name="VCLinkerTool"
                  # AdditionalDependencies="comctl32.lib Msimg32.lib Winmm.lib"
                  # LinkIncremental="1"
                  # GenerateDebugInformation="true"
                  # SubSystem="2"
                  # OptimizeReferences="2"
                  # EnableCOMDATFolding="2"
                  # TargetMachine="1"
                  # />
                  prt( "Is linker tool ...[$fline]\n" ) if ($dbg_src7);
                  ## @attribs = space_split($fline);
                  ## %atthash = array_2_hash_on_equals(@attribs);
                  if ($dbg_src12a) {   # DEBUG ONLY
                     prt( "Split of attribs [$fline] ...\n" );
                     foreach $adddeps (@attribs) {
                        prt( " $adddeps\n" );
                     }
                     prt( "Show of HASH ...\n" );
                     foreach $adddeps (keys %atthash) {
                        prt( " $adddeps = ".$atthash{$adddeps}."\n" );
                     }
                  }
                        ##################################################################
                        $adddeps = '';
                  if (defined $atthash{'AdditionalDependencies'} ) {
                     $adddeps = strip_quotes(trim_all($atthash{'AdditionalDependencies'}));
                     prt( "Set LINKLIB:$conf: [$adddeps]\n" ) if ($dbg_src12);
                  }
                  $v8_depend{$conf} = $adddeps;
                        ##################################################################
                        $adddeps = '';  # see also $dbg_d15
                        if (defined $atthash{'AdditionalLibraryDirectories'}) {
                     $adddeps = strip_quotes(trim_all($atthash{'AdditionalLibraryDirectories'}));
                     prt( "Set LNKDIRS:$conf: [$adddeps]\n" ) if ($dbg_src12b);
                        } else {
                     prt( "Set LNKDIRS:$conf: [<NULL>]\n" ) if ($dbg_src12b);
                        }
                  $v8_libdep{$conf} = $adddeps;
                        ##################################################################
                        # my %v8_linkout = (); # Name="VCLinkerTool" OutputFile=".\Release\FlightGear.exe", by configuration
                        # $dsp_out_[dbg|rel} = $def_out_[dbg|rel] = "-NEW_OUT_[DBG|REL]"
                        # = $outputs = $v8_linkout{$conf} = push(@allarr, "$linkout=[$lout]");
                        $adddeps = '';
                        if (defined $atthash{'OutputFile'}) {
                     $adddeps = strip_quotes(trim_all($atthash{'OutputFile'}));
                        }
                        $v8_linkout{$conf} = $adddeps;
                        ##################################################################
                        $adddeps = '';
                        if (defined $atthash{'SubSystem'}) {
                     $adddeps = strip_quotes(trim_all($atthash{'SubSystem'}));
                            # this should decide the $apptype
                            # $v8_aptype{$conf} = $apptype;
                            # $v8_apptypes{$projname} = $apptype;
                            if (defined $v8_subsystems{$adddeps}) {
                                $ppdefs = $v8_subsystems{$adddeps};
                                if ($apptype eq $ppdefs) {
                                    prt("Got APPTYPE:$conf: NO CHANGE [$apptype] equals SubSystem ($adddeps) [".$v8_subsystems{$adddeps}."] ...(ln=$lnnum)\n" ) if ($dbg_x16);
                                } else {
                                    if ($apptype eq $app_dynalib) {
                                        if ($ppdefs eq $app_windows) {
                                            # these are NOT incompatible, so NO CHANGE
                                            prt("Got APPTYPE:$conf: NO CHANGE [$apptype] EQUIVALENT to $ppdefs ($adddeps) ...(ln=$lnnum)\n" ) if ($dbg_x16);
                                        } else {
                                            prtw("WARNING: NO CHANGE :$conf: but [$apptype] NOT EQUIVALENT to $ppdefs ($adddeps) ...(ln=$lnnum)\n" );
                                        }
                                    } else {
                                        prt("Set APPTYPE:$conf: from $apptype, to $ppdefs - CHECK! (ln=$lnnum)\n" ) if ($dbg_x15);
                                        $apptype = $ppdefs;
                                    }
                                    if (! defined $v8_aptype{$conf}) {
                                        prtw("HEY! $conf NOT already set in v8_aptype - CHECK ORDER OF DECODE! (ln=$lnnum) $act_vcproj\n" );
                                    }
                                    $v8_aptype{$conf} = $apptype;
                                    if (! defined $v8_apptypes{$projname}) {
                                        prtw("HEY! $projname NOT already set in v8_apptypes - CHECK ORDER OF DECODE! (ln=$lnnum) $act_vcproj\n" );
                                    } else {
                                        prt( "Set APPTYPE: in v8_apptypes[$projname] to [$apptype] (ln=$lnnum)\n" ) if ($dbg_x15);
                                    }
                                    $v8_apptypes{$projname} = $apptype;
                                }
                            } else {
                                prtw( "WARNING: Got SubSystem='$adddeps', NOT in v8_subsystems! CHECK IT OUT!!! (ln=$lnnum) $act_vcproj: $fline\n" );
                                ### $tmpdbg = $dbg_x10;
                                ### $dbg_x10 = 1;
                                ### @attribs = space_split($fline);
                                ### %atthash = array_2_hash_on_equals(@attribs);
                                ### $adddeps = $atthash{'SubSystem'};
                                ### prt( "2nd run got $adddeps ...\n");
                                ### $dbg_x10 = $tmpdbg;
                            }
                        }
                        ##################################################################
                    } elsif ($tname eq 'VCLibrarianTool') {
                        # <Tool
                        #  Name="VCLibrarianTool"
                        #  OutputFile="Win32_LIB_Debug\libpngd.lib"
                        #  SuppressStartupBanner="true" />
                        $hadlibtool = 1;
                        $ppdefs = '';
                  if ( defined $atthash{'OutputFile'} ) {
                     $ppdefs = strip_quotes(trim_all($atthash{'OutputFile'}));
                        }
                        $v8_linkout{$conf} = $ppdefs;
                        prt( "Set 'VCLibrarianTool' v8_linkout[$conf] to [$ppdefs] $act_vcproj\n" ) if ($dbg_x20);
                        ######################################################################
                        $adddeps = '';
                        if (defined $v8_aptype{$conf}) {
                            $adddeps = $v8_aptype{$conf};
                        }
                        if ($adddeps ne $app_statlib) {
                            prtw( "VCLibrarianTool:$conf: This suggests a STATIC LIBRARY ...out=$ppdefs\n".
                                "but v8_aptype[$conf] HAS [".$v8_aptype{$conf}."] CHECK FOR CHANGE!! (ln=$lnnum) $act_vcproj\n" );
                        } else {
                            prt( "VCLibrarianTool:$conf Suggests STATIC LIBRARY - out=$ppdefs".
                                " - and that is what we have in v8_aptype...\n" ) if ($dbg_x11);
                        }
                        if (! defined $v8_depend{$conf} ) {
                      $v8_depend{$conf} = "";
                        }
                        if (! defined $v8_libdep{$conf} ) {
                      $v8_libdep{$conf} = "";
                        }
                    } elsif ($tname eq 'VCPostBuildEventTool') {
                        # <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
                        $ppdefs = '';
                        if (( defined $atthash{'Description'} ) || ( defined $atthash{'CommandLine'} ) ) {
                            $ppdefs = "$postdesc="; # to 'PostBuild_Desc=';
                            if ( defined $atthash{'Description'} ) {
                                $ppdefs .= add_quotes(strip_quotes(trim_all($atthash{'Description'})));
                            }
                            $ppdefs .= " $postcmds="; # to ' PostBuild_Cmds=';
                            if ( defined $atthash{'CommandLine'} ) {
                                $adddeps = strip_quotes(trim_all($atthash{'CommandLine'}));
                                $adddeps =~ s/&#x0D;&#x0A;/\t/g;
                                $adddeps =~ s/\t$//;
                                $ppdefs .= add_quotes($adddeps);
                            }
                        }
                        $v8_postbuild{$conf} = $ppdefs; # later, added under $postevt
               }
            } else {
               prtw( "WARNING: FAILED Name [$fline] in $act_vcproj!\n" );
            }
         } elsif ($fline =~ /<\/Filter>/) {
            $filtname = ''; # = NO FILTER NAME, like Source Files
            $filttype = ''; # = NOR FILTER TYPE, like cpp;c;cxx;rc;def;r;odl;idl;hpj;bat
         } elsif ($fline =~ /<Platforms/) {
            # 8-8: LINE=[<Platforms>]
         } elsif ($fline =~ /<Platform/) {
            # 9-11: LINE=[<Platform Name="Win32" />]
         } elsif ($fline =~ /<ToolFiles/) {
            # 13-13: LINE=[<ToolFiles>]
         } elsif ($fline =~ /<Configurations>/) {
            # 15-15: LINE=[<Configurations>]
            $inconfigs = 1;
            prt( "$lnnum: Enter Configurations ... ($fline)\n" ) if ($dbg_src10);
         } elsif ($fline =~ /<\/Configurations>/) {
            # LINE=[</Configurations>]
            $inconfigs = 0;
            prt( "$lnnum: Exit Configurations ... ($fline)\n" ) if ($dbg_src10);
            } elsif ($fline =~ /<\/Configuration>/) {
                $dnaptype = 0;
         } elsif ($fline =~ /<References/) {
            # 167-167: LINE=[<References>]
         } elsif ($fline =~ /<Files/) {
            # 169-169: LINE=[<Files>]
                $infiles = 1;
            prt( "$lnnum: Enter Files ... ($fline)\n" ) if ($dbg_x06);
         } elsif ($fline =~ /<\/Files/) {
            # 169-169: LINE=[<Files>]
                $infiles = 0;
            prt( "$lnnum: Exit Files ... ($fline)\n" ) if ($dbg_x06);
                $act_file = '';
                $act_disp = '';
         } elsif ($fline =~ /<FileConfiguration/) {
            # 177-179: LINE=[<FileConfiguration Name="Debug|Win32" >]
         } elsif ($fline =~ /<Globals/) {
            # 591-591: LINE=[<Globals>]
         } else {
            if ($tagtyp == $TYP_VERSION) {
               prt("$bgnend: LINE=[$fline]\n") if ($dbg_srcv);
            } elsif ($tagtyp == $TYP_CLOSE) {
               prt("$bgnend: LINE=[$fline]\n") if ($dbg_srcc);
            } else {
               prt("$bgnend: LINE=[$fline]\n") if ($dbg_src5);
            }
         }
         if ($tagtyp == $TYP_OPEN) {
            push(@xmltags,$xmltag);
         } elsif ($tagtyp == $TYP_CLOSE) {
            if (@xmltags) {
               my $tmptag = pop @xmltags;
               $xmltag = substr($xmltag,1);
               if ($tmptag ne $xmltag) {
                  prtw( "WARNING: Closing TAG [$xmltag] not last [$tmptag]! $bgnend\n" );
               }
               if ($xmltag eq 'Configurations') {
                  $inconfigs = 0;
                  prt( "$lnnum: Exit Configurations ... ($fline)\n" ) if ($dbg_src10);
               }
            } else {
               prtw( "WARNING: CLOSE TAG NOT OPEN! [$fline]\n" );
            }
         }
         $fline = '';
      }
   }
   ###prt( "Project: $projname, as $apptype\n" ); # eg 'Project: gshhs, as Console Application'
   my (@att2, @disc, @arr, $mask, $cdefs, $rtime, $cincs, $libdirs, @allarr);
    # COLLECT the information obtained
    # collect andd add to %v6_all under key $mask
    # The $mask is "$projname|$conf|$rtime"
    # $projname from XML line =~ /<VisualStudioProject\s+/ Name=
    # $conf is the key to each of the hashes
    # $rtime from $v8_runtim{$conf}
    # %v8_depend - gives $libraries=[$cdefs]
    # %v8_link - gives $defines=[$cdefs] (poorly names hash!)
    # %v8_includ - gives $includes=[$cincs]
    # %v8_libdep - gives $libpath=[$libdirs]
   foreach $conf (keys %v8_depend) {
      $ctype = 0;
      if ($conf =~ /Debug/i) {
         $ctype = 1;
         $func = \&is_in_skip_lib_dbg;
      } elsif ($conf =~ /Release/i) {
         $ctype = 2;
         $func = \&is_in_skip_lib_rel;
      } else {
         $func = \&is_in_skip_lib_rel;
            $ctype = 2;
            prtw( "WARNING: NOT Debug or Release - WHAT IS IT? [$conf]! Using Release\n" );
      }
        if (defined $v8_aptype{$conf}) {
            $apptype = $v8_aptype{$conf};
        } else {
            $apptype = $typelse;
            prtw( "WARNING: No application type in v8_aptype for $conf! Using default $apptype!!\n" );
        }
        if (defined $v8_runtim{$conf}) {
            $rtime = $v8_runtim{$conf};
        } else {
            if ($ctype == 1) {
                $rtime = $def_runtime_dbg;
            } else {
                $rtime = $def_runtime_rel;
            }
            prtw( "WARNING: No RUNTIME in v8_runtim for $conf! Using default $rtime!!\n" );
        }
        $rtime =~ s/^\///;
        $mask = "$projname|$conf|$rtime";  # start with project name and configuration
        # my %v6_all = ();    # all projects in this solution
        # key = projname|$conf eg FlightGear|Debug|Win32
        # value = string '$defines=[ list of defines ] $libraries=[ list of libraries ]
      $ppdefs = $v8_depend{$conf};
      @attribs = split(/ /,$ppdefs);
      @att2 = ();
      @disc = ();
      foreach $itm (@attribs) {
         if ( ! $func->($itm) ) {
            push(@att2,$itm);
         } else {
            push(@disc,$itm);
         }
      }
      prt( "\nLINK:Config: $conf=$ppdefs ... ".scalar @attribs." items\n" ) if ($dbg_src18);
      prt( "Reduced to ".scalar @att2." items ...Discarding [ @disc ], as already there...\n" ) if ($dbg_src18);
      if ($ctype == 1) {   # ($conf =~ /Debug/i)
         $def = $dsp_libs_dbg;
         @arr = split(/ /,$dsp_libs_dbg);
         @disc = ();
         prt( "Debug VERSION ... $conf ... [ @arr ]\n" ) if ($dbg_src18);
         foreach $itm (@att2) {
            if (is_in_array( $itm, @arr )) {
               push(@disc,$itm);
            } else {
               $dsp_libs_dbg .= ' '.$itm;
            }
         }
         prt( "Changed $def (\$dsp_libs_dbg) ...\n") if ($dbg_src18);
         prt( "To      $dsp_libs_dbg, discarding [ @disc ], as already there ...\n" ) if ($dbg_src18);
            $cdefs = $dsp_libs_dbg;
      } elsif ($ctype == 2) {   # $conf =~ /Release/)
         $def = $dsp_libs_rel;
         @arr = split(/ /, $dsp_libs_rel );
         prt( "Release VERSION ... $conf ... @arr\n" ) if ($dbg_src18);
         foreach $itm (@att2) {
            if (is_in_array( $itm, @arr )) {
               push(@disc,$itm);
            } else {
               $dsp_libs_rel .= ' '.$itm;
            }
         }
         prt( "Changed $def (\$dsp_libs_rel) ...\n" ) if ($dbg_src18);
         prt( "To      $dsp_libs_rel, discarding [ @disc ], as already there ...\n" ) if ($dbg_src18);
            $cdefs = $dsp_libs_rel;
      } else {
         prtw( "WARNING: CHECKME: VERSION NOT DEBUG OR RELEASE??? ... $conf ...\n" );
      }
        if ($ctype > 0) {
            if (defined $v6_all{$mask}) {
                prtw( "WARNING: $mask ALREADY IN v6_all!!! value=".$v6_all{$mask}."\n" );
            } else {
                $v6_all{$mask} = "$libraries=[$cdefs] ";
                prt( "v6_all: Adding [$mask] with $libraries=[$cdefs] ...\n" ) if ($dbg_x03);
            }
        }
        # add to v6_refall, as scalar for now
        $v6_refall{$mask} = "$libraries=[$cdefs]";
   }
   foreach $conf (keys %v8_link) {
      $ctype = 0;
      if ($conf =~ /Debug/i) {
         $ctype = 1;
         $func = \&is_in_skip_conf_dbg;
      } elsif ($conf =~ /Release/i) {
         $ctype = 2;
         $func = \&is_in_skip_conf_rel;
      } else {
            # default to RELEASE
         $func = \&is_in_skip_conf_rel;
            $ctype = 2;
         prtw( "WARNING: CHECKME: VERSION NOT DEBUG NOR RELEASE??? ... Got [$conf]! ASSUME RELEASE\n" );
      }
        if (defined $v8_aptype{$conf}) {
            $apptype = $v8_aptype{$conf};
        } else {
            $apptype = $typelse;
            prtw( "WARNING:$projname: No APPTYPE in v8_aptype for $conf! Using default [$apptype]!! $act_vcproj\n" );
        }
        if (defined $v8_runtim{$conf}) {
            $rtime = $v8_runtim{$conf};
        } else {
            if ($ctype == 1) {
                $rtime = $def_runtime_dbg;
            } else {
                $rtime = $def_runtime_rel;
            }
            prtw( "WARNING:$projname: No RUNTIME in v8_runtim for $conf! Using default [$rtime]!! $act_vcproj\n" );
        }
        # push(@allarr, "$includes=[$cincs]");
        if (defined $v8_includ{$conf}) {
            $cincs = $v8_includ{$conf};
        } else {
            if ($ctype == 1) {
                $cincs = $def_include_dirs_dbg;
            } else {
                $cincs = $def_include_dirs_rel;
            }
            prtw( "WARNING:$projname: No INCLUDES in v8_includ for $conf! Using default [$cincs]!! $act_vcproj\n" );
        }
        # could massage these $cincs, to REMOVE the MEANINGLESS (in windows) '.\', or do it later
        $rtime =~ s/^\///;
        $mask = "$projname|$conf|$rtime";  # start with project name and configuration
      $ppdefs = $v8_link{$conf};
      @attribs = split(/;/,$ppdefs);
      @att2 = ();
      @disc = ();
      foreach $itm (@attribs) {
         if ( ! $func->($itm) ) {
            push(@att2,$itm);
         } else {
            push(@disc,$itm);
         }
      }
      @arr = ();
      prt( "\nDEFS:Config: $conf=$ppdefs ... ".scalar @attribs." items\n" ) if ($dbg_src18);
      prt( "Reduced to ".scalar @att2." items ...Discarding [ @disc ], as already there...\n" ) if ($dbg_src18);
      if ($ctype == 1) {   # ($conf =~ /Debug/i)
         $def = $dsp_defines_dbg;
         @arr = split_conf( $dsp_defines_dbg );
         @disc = ();
         prt( "Debug VERSION ... $conf ... @arr\n" ) if ($dbg_src18);
         foreach $itm (@att2) {
            if (is_in_array( $itm, @arr )) {
               push(@disc,$itm);
            } else {
               $dsp_defines_dbg .= ' /D "'.$itm.'"';
            }
         }
         prt( "Changed $def (\$dsp_defines_dbg) ...\n" ) if ($dbg_src18);
         prt( "To      $dsp_defines_dbg, discarding [ @disc ], as already there ...\n" ) if ($dbg_src18);
            $cdefs = $dsp_defines_dbg;
      } elsif ($ctype == 2) {   # $conf =~ /Release/i)
         $def = $dsp_defines_rel;
         @arr = split_conf( $dsp_defines_rel );
         prt( "Release VERSION ... $conf ... @arr\n" ) if ($dbg_src18);
         foreach $itm (@att2) {
            if (is_in_array( $itm, @arr )) {
               push(@disc,$itm);
            } else {
               $dsp_defines_rel .= ' /D "'.$itm.'"';
            }
         }
         prt( "Changed $def (\$dsp_defines_rel) ...\n") if ($dbg_src18);
         prt( "To      $dsp_defines_rel, discarding [ @disc ], as already there ...\n" ) if ($dbg_src18);
            $cdefs = $dsp_defines_rel;
      }
        # vcproj = AdditionalLibraryDirectories
        $libdirs = '';
        if (defined $v8_libdep{$conf} ) {
            $libdirs = $v8_libdep{$conf};
        } else {
            prtw( "WARNING:$mask: v8_libdep does not contain conf $conf ...\n" );
        }
        # my %v8_config = ();  #  by configuration, OutputDirectory=".\Release", IntermediateDirectory="Release",
        # 28/09/2008 - note, has quotes added push(@allarr, "$outputs=[$outs]");
        # $dsp_output_dbg = $def_output_dbg;    # "-NEW_OUTD_DBG-" $out_dir
        # $dsp_output_rel = $def_output_rel;    # "-NEW_OUTD_REL-" $out_dir
        # $dsp_inter_dbg  = $def_inter_dbg;    # "-NEW_INTER_DBG-" $int_dir
        # $dsp_inter_rel  = $def_inter_rel;    # "-NEW_INTER_REL-" $int_dir
        my $outs = '';
        if (defined $v8_config{$conf}) {
            $outs = $v8_config{$conf};
            ###prtw( "SHOW OUTS = [$outs]\n" );
        }
        # $dsp_out_[dbg|rel} = $def_out_[dbg|rel] = "-NEW_OUT_[DBG|REL]"
        # = $outputs = $v8_linkout{$conf} = push(@allarr, "$linkout=[$lout]");
        my $lout = '';
        if (defined $v8_linkout{$conf}) {
            $lout = strip_dotrel($v8_linkout{$conf});
        }
        $msg = "$defines=[$cdefs] $includes=[$cincs] $libpath=[$libdirs] $outputs=[$outs] $linkout=[$lout]";
        if ($ctype > 0) {
            if (! defined $v6_all{$mask}) {
                prtw( "WARNING: $mask NOT already defined!!!\n" );
                $v6_all{$mask} = $msg;
            } else {
                $v6_all{$mask} .= $msg;
            }
        }
        my $post = '';
        if (defined $v8_postbuild{$conf}) {
            $post = $v8_postbuild{$conf};
        }
        @allarr = ();   # clear the array
        push(@allarr, $v6_refall{$mask});
        push(@allarr, "$defines=[$cdefs]");
        push(@allarr, "$includes=[$cincs]");
        push(@allarr, "$libpath=[$libdirs]");
        push(@allarr, "$outputs=[$outs]");
        push(@allarr, "$linkout=[$lout]");
        push(@allarr, "$postevt=[$post]");
        prt( "For mask [$mask], set linkout $linkout = [$lout] ...\n" ) if ($dbg_x21);
        prt( "For mask [$mask], set libpath $libpath = [$libdirs] ...\n" ) if ($dbg_x22);
        $v6_refall{$mask} = [@allarr];  # COPY the ARRAY to the HASH
   }
   my $new_srcs = scalar @v8_srcs;
   prt( "VCPROJ Project: $projname, as $apptype, version=$version\n" ) if ($dbg_x12); # eg 'Project: gshhs, as Console Application'
   prt( "Got new $new_srcs C/C++ files, header files, and others \n" ) if ($dbg_x12);
   prt( "Defined Debug = $dsp_defines_dbg, Release = $dsp_defines_rel\n" ) if ($dbg_x13);
   prt( "Library Debug = $dsp_libs_dbg, Release = $dsp_libs_rel\n" ) if ($dbg_x13);
}
sub fg_clear_proj_files {
   @v8_srcs = ();       # start with NONE
   %v8_link = ();       # PREPROCESSOR compiler definitions, by configuration
   %v8_depend = ();   # linker addtional dependencies, by configuration
    %v8_aptype = ();    # application type - console, static library, DLL, ...
   @v6_srcs = ();  # relnm full group filter
   %v6_defs = ();
   %v6_conf = ();
   # establish DEFAULT items for DSP generation
   # these can be altered by the XML decode
   $dsp_runtime_rel = $def_runtime_rel;
   $dsp_runtime_dbg = $def_runtime_dbg;
   $dsp_defines_dbg = $def_defines_dbg;
   $dsp_defines_rel = $def_defines_rel;
   $dsp_libs_rel = $def_libs_rel;
   $dsp_libs_dbg = $def_libs_dbg;
    # new items
    %v8_runtim = ();    # RUNTIME /MT /MD ...
    %v8_includ = ();    # INCLUDE DIRECTORIES for compiler
    ###%v8_filter = ();    # NO single list for whole solution - <Files><Filter Name="Source Files" ...
    %v8_libdep = (); # ADDITIONAL LIB DIRS, by configuration
    # new 22/09/2008
    %v8_config = ();  #  by configuration, OutputDirectory=".\Release", IntermediateDirectory="Release",
    # and zlib = ConfigurationType="4", alut = ConfigurationType="2", fg = ConfigurationType="1"
    %v8_linkout = (); # Name="VCLinkerTool" OutputFile=".\Release\FlightGear.exe", by configuration
    %v8_postbuild = (); # Name="VCPostBuildEventTool", with
    # 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;"
    # the &#x0D;&#x0A; is replaced with a TAB (\t) in the DSP file
    @xml_tag_map = ();  # clear the xml_tag_map
    @xml_lines = ();    # neat xml lines from VCPRJ file
    $dsp_includes_dbg = $def_include_dirs_dbg;
    $dsp_includes_rel = $def_include_dirs_rel;
    $dsp_post_dbg = $def_post_dbg;
    $dsp_post_rel = $def_post_rel;
    # 28/09/2008
    $dsp_output_dbg = $def_output_dbg;    # "-NEW_OUTD_DBG-"
    $dsp_output_rel = $def_output_rel;    # "-NEW_OUTD_REL-"
    $dsp_inter_dbg  = $def_inter_dbg;    # "-NEW_INTER_DBG-"
    $dsp_inter_rel  = $def_inter_rel;    # "-NEW_INTER_REL-"
}
#################################################
sub is_vcproj {
   my $fil = shift;
   if ($fil =~ /\.vcproj$/i) {
      return 1;
   }
   return 0;
}
sub resolve_depends {
   my ($projname, $projdeps, @arr, $cnt);
   my ($depid, $pn, $projid);
   my ($nmdeps, $fnd);
   foreach $projname (keys %sln_projects) {
      $projdeps = $sln_depends{$projname};
      if (length($projdeps)) {
         # there is LENGTH, convert giant CID to simple project names
         @arr = split( /\|/, $projdeps );   # split em up
         $cnt = scalar @arr;   # get count of split
         #prt( "Proj $projname, depends on $cnt = $projdeps ...\n" );
         $nmdeps = '';   # build simple NAME set
         foreach $depid (@arr) {
            foreach $pn (keys %sln_projids) {
               if ($pn ne $projname) {
                  $projid = $sln_projids{$pn};
                  if ($depid eq $projid) {
                     $nmdeps .= '|' if (length($nmdeps));
                     $nmdeps .= $pn;
                     last;
                  }
               }
            }
         }
         @arr = split( /\|/, $nmdeps );
         prt( "proj $projname, depends on $nmdeps ...\n" ) if ($dbg_s13);
         if ($cnt != scalar @arr) {   # YEEK - Does NOT match - OH WELL
            prtw( "WARNING: Failed to get SAME count $cnt - got ".scalar @arr."!\n" );
         }
         $sln_depends{$projname} = $nmdeps;
      }
   }
}
# Read and store contents of SOLUTION (.sln) file
# 22/04/2008 - Extract DEPENDENCIES from solution file, and add to DSW output
sub process_SLN {
   my ($fil) = shift;
   my ($cnt, $line, $vers, @arr, $mver, $par, $ff, $itmnum);
   my ($projname, $projfile, $projff, $gotproj, $relpath);
   my ($tnm,$tpth);
   my ($inproj, $tline, $projid, $inpdeps, $projdeps);
   open IF, "<$fil" or mydie( "ERROR: Unable to open $fil ... $! ...\n" );
   my @lines = <IF>;
   close IF;
   $cnt = scalar @lines;
   my ($name,$sln_path) = fileparse($fil);
   prt( "\nProcessing $cnt lines ... n=[$name] p=[$sln_path] ...\n" );
   $projname = '';
   $projfile = '';
   $projff = '';
   $gotproj = 0;
   $inproj = 0;
   $inpdeps = 0;
   foreach $line (@lines) {
      $tline = trim_all($line);
      if ($line =~ /.+Format\s+Version\s+(\d+\.\d+)$/i) {
         $vers = $1;   # get n.nn version
         @arr = split(/\./,$vers);
         $mver = $arr[0];
         prt( "Is MSVC Version $mver ...\n" );
      } elsif ($line =~ /^Project\s*\(/) {
         # seek like 
         #Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "abyss", "abyss.vcproj", "{8B384B8A-2B72-4DC4-8DF1-E3EF32F18850}"
         ###prt( "Got project [$line] ...\n" );
         $inproj = 1;
         @arr = split( '=', $line );
         $cnt = scalar @arr;
         if ($cnt == 2) {
            $par = $arr[1];
            @arr = split(',', $par);
            $cnt = scalar @arr;
            if ($cnt == 3) {
               $projname = strip_quotes(trim_all($arr[0]));
               $projfile = strip_quotes(trim_all($arr[1]));
               $projid   = strip_quotes(trim_all($arr[2]));
               $projff = fix_rel_path($sln_path.$projfile);
               if ((length($projname)) && (is_vcproj($projfile)) && (-f $projff)) {
                  $gotproj = 1;
                  ($tnm,$tpth) = fileparse($projff);
                  $relpath = get_rel_dos_path($tpth, $sln_path);
                  prt( "Got PROJECT name=$projname, file=$projff, rel=[$relpath].\n" ) if ($dbg_sl1);
                  ###push(@proj_files, $projff);
                  if (defined $sln_projects{$projname}) {
                     mydie( "A PROBLEM: Already GOT this project name $projname!!!\n" );
                  } else {
                     $sln_projects{$projname} = $projff;
                     $sln_projpath{$projname} = $relpath; # can be BLANK, or say 'BvMath/'
                     $sln_projids{$projname}  = $projid;
                     $sln_depends{$projname}  = '';   # start dependencies, if any
                  }
               } else {
                  prt( "WARNING: " );
                  if (!length($projname)) {
                     prt( "Failed to get a project name!" );
                  } elsif ( !is_vcproj($projfile) ) {
                     prt( "Name [$projfile] NOT a VCPROJ name!" );
                  } else {
                     prt( "Unable to locate file [$projff]!" );
                  }
                  prt( " Line is (trimmed)\n$tline\n" );
               }
            } else {
               prtw( "Warning: Part 2 of Project line did NOT split into 3 on comma!???\n" );
            }
         } else {
            prtw( "Warning: Project line did NOT split in 2 on equal sign!???\n" );
         }
         # to switch on $tryharder requires additional work on parsing this line
         # =====================================================================
         if (!$gotproj && $tryharder) {
            @arr = split( /\"/, $line );
            $itmnum = 0;
            foreach $par (@arr) {
               $itmnum++;
               ###prt( "$itmnum [$par]\n" );
               if (is_vcproj($par)) {
                  $ff = $sln_path.$par;
                  prt( "Got PROJECT file [$par] " );
                  if ( -f $ff) {
                     prt( "ok" );
                     ###push(@proj_files, $ff);
                     my ($nm,$pt,$ex) = fileparse( $ff, qr/\.[^.]*/ );
                     $projname = $nm;
                     if (defined $sln_projects{$projname}) {
                        mydie( "A PROBLEM: Already GOT this project name $projname!!!\n" );
                     } else {
                        ($tnm,$tpth) = fileparse($ff);
                        $relpath = get_rel_dos_path($tpth, $sln_path);
                        $sln_projects{$projname} = $ff;
                        $sln_projpath{$projname} = $relpath; # can be BLANK, or say 'BvMath/'
                        # WARNING: TO BE DONE !!!
                        $sln_projids{$projname}  = $projid;
                        $sln_depends{$projname}  = '';   # start dependencies, if any
                     }
                  } else {
                     prt( "FAILED" );
                  }
                  prt("\n");
               }
            }
         }
         # =====================================================================
      } elsif ($inproj) {
         # in the Project section - look for END of section, and DEPENDENCIES
         # ProjectSection(ProjectDependencies)
         if ($tline eq 'EndProject') {
         ###if ($line =~ /^EndProject\s*/)
            $inproj = 0;
         } else {
            if ($inpdeps) {
               if ($tline eq 'EndProjectSection' ) {
                  $inpdeps = 0;
               } else {
                  # collect dependencies
                  @arr = split( '=', $line );
                  $cnt = scalar @arr;
                  if ($cnt == 2) {
                     $arr[0] = trim_all($arr[0]);
                     $arr[1] = trim_all($arr[1]);
                     if ($arr[0] eq $arr[1]) {
                        $projdeps = $sln_depends{$projname};   # extract dependencies, if any
                        $projdeps .= '|' if (length($projdeps));
                        $projdeps .= $arr[0];
                        prt( "Proj $projname, dependant on $arr[0] ...\n" ) if ($dbg_s12);
                        ##prt( "Proj $projname, dependant on $projdeps ...\n" );
                        $sln_depends{$projname} = $projdeps;
                     } else {
                        prtw( "Warning: Found different IDS '$arr[0]' NE '$arr[1]'!!! \n" );
                     }
                  } else {
                     prtw( "Warning: Project DEPENDENCY line did NOT split in 2 on equal sign!???\n" );
                     prtw( "line=$line" );
                  }
               }
            } elsif ($line =~ /ProjectSection\s*\(\s*ProjectDependencies\s*\)/) {
               $inpdeps = 1;
            }
         }
      }
   }
   ###prt( "Done $fil ... got ".scalar @proj_files." project files ...\n" );
   prt( "Done $fil ... got ".scalar keys(%sln_projects)." project files ...\n" );
   # resolve dependencies, if possible - warn if NOT ...
   resolve_depends();
}
### utitlity subs
sub get_suffix {
   my ($f) = shift;
   my @arr = split(/\./,$f);
   return $arr[-1];
}
sub is_rc_file {
    my ($f) = shift;
    my $s = get_suffix($f);
    if (lc($s) eq 'rc') {
        return 1;
    } elsif ($s =~ /^rc/i) {
        return 2;
    }
    return 0;
}
sub parse_args {
   my (@av) = @_;
   while (@av) {
      my $arg = shift @av;
      if ( length($inpsln) ) {
         prtw( "ERROR: Already have input file $inpsln ...\n" );
         mydie( "Only input is a single file ...\n" );
      }
      $inpsln = $arg;
   }
   if ( !length($inpsln) ) {
      if ($dbg1) {
         $inpsln = $defin;
      } else {
         prtw( "ERROR: Solution file not found!\n" );
         mydie( "Useage: solution_file ...\n" );
      }
   }
}
#########################################################
# # Begin Group "Source Files"
# 
# # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# # Begin Source File
# 
# SOURCE=.\mirror.cpp
# # End Source File
# ...
# # End Group
sub is_in_array_nc {
   my ($itm, @arr) = @_;
   foreach my $val (@arr) {
      if ($val =~ /$itm/i) {
         return 1;
      }
   }
   return 0;
}
sub out_src {
   my ($sc,$of) = @_;
   print $of "# Begin Source File\n";
   print $of "\n";
   print $of "SOURCE=$sc\n";
   print $of "# End Source File\n";
}
sub fg_out_src {
   my ($sc,$of,$ex) = @_;
   print $of "# Begin Source File\n";
   print $of "\n";
   print $of "SOURCE=$sc\n";
    print $of "# PROP Exclude_From_Build 1\n" if ($ex eq $excl_mark);
   print $of "# End Source File\n";
}
sub get_header {
    my ($apt) = shift;
    my $hdr = '';
    if (defined $dsp_appheader{$apt}) {
        my $func = $dsp_appheader{$apt};
        $hdr = $func->();
    } else {
        prtw( "WARNING: [$apt] NOT found in dsp_appheader! FOUND ONLY ...\n" );
        foreach $hdr (keys %dsp_appheader) {
            prt( "[$hdr] " );
        }
        prt("\n");
        mydie( "Aborting in disgust ;=))\n" );
    }
    return $hdr;
}
sub v8_aptype_consistent {
    my ($val, @keys, $ky, $cnt, $i, $apt);
    @keys = keys(%v8_aptype);
    $cnt = scalar @keys;
    $ky = $keys[0];
    $apt = $v8_aptype{$ky};
    for ($i = 1; $i < $cnt; $i++) {
        $ky = $keys[$i];
        $val = $v8_aptype{$ky};
        if ($val ne $apt) {
            prtw("WARNING: For $ky, application type [$val] NOT SAME as [$apt]!\n".
                "Aborting generation of this DSP file!!!\n" );
            return "";
        }
    }
    return $apt;
}
sub get_refs_for_pname {
    my ($pn) = shift;
    my @refs = ();
    my ($key, $val, $cond, $pform, $rtim);
    my ($gnum, @groups);
    ($gnum, @groups) = get_refall_groups();
    my $kcnt = scalar @groups;
    for (my $k = 0; $k < $kcnt; $k++) {
        if ($pn eq $groups[$k][1]) {
            $gnum  = $groups[$k][0];
            $key   = $groups[$k][2];
            $cond  = $groups[$k][3];
            $pform = $groups[$k][4];
            $rtim  = $groups[$k][5];
            $val   = $v6_refall{$key};
            push(@refs, [$val, $cond, $pform, $rtim]);
        }
    }
    return @refs;
}
sub generate_DSP {
   my ($key, $tof, $reald, $ffrdsp) = @_;
   my ($DSP, $cnt, $i, $src, $fnm, $ftyp, $rpt, $apt, $dmsg);
   my ($got_src, $got_hdr, $got_rc, $src_cnt, $non_cnt, $shr);
    my ($def_grp);
    my ($got_other, $msg, $tmp, $dspmsg);
    my (@groups, $gnum, $kcnt, $rcnt);
   my @fltnms = ();
    my @refs = ();    
   $got_src = 0;
   $got_hdr = 0;
   $got_rc = 0;
    $got_other = 0;
   $src_cnt = 0;
   $non_cnt = 0;
    $act_key = $key;
    $tof = $ffrdsp if ($write_real_files);
   $dspmsg = "Generate DSP file [$tof], for $key ...\n";
    $dspmsg .= "Real rel=[$reald] ... absolute=[$ffrdsp] ";
    if (-f $ffrdsp) {
        $dspmsg .= "REPLACE";
    } else {
        $dspmsg .= "NEW";
    }
    prt("$dspmsg\n");
    # it can be ONE OF
    # 'Console Application', 'Dynamic-Link Library', 'Static Library', or 'Application'
    $apt = 'Application';
    $dmsg = "DSP app type = ";
    $apt = v8_aptype_consistent();
    if (length($apt) == 0) {
        return;
    }
    $dmsg .= $apt;
    $msg = get_header($apt);
    if ( !($msg =~ /^# Microsoft Developer Studio Project File/) ) {
        ptrw( "WARNING: $dmsg - FAILED TO GET DSP HEADER???\n".
            "No $tof generated!\n");
        return;
    }
    $kcnt = scalar keys(%v6_refall);
    ($gnum, @groups) = get_refall_groups();
    @refs = get_refs_for_pname( $key );
    $rcnt = scalar @refs;
    prt( "$dmsg\n" ) if ($dbg_d11 || $dbg_d10);
    prt( "For [$key], got $rcnt reference keys!\n" ) if ($dbg_d11 || $dbg_d11a);
    my ($val, $cond, $pform, $rtim, @arr, %hash, $ky, $cont, %h2, $sep);
    my ($ref1, $ref2, @ar2, $j);
    $sep = "\t=\t";
    # clear current post events, outputs, etc ... that are setup here
    $dsp_post_rel = $def_post_rel;  # $msg =~ s/-NEW_POST_REL-/$dsp_post_rel/gm;
    $dsp_post_dbg = $def_post_dbg;  # $msg =~ s/-NEW_POST_DBG-/$dsp_post_dbg/gm;
    $dsp_output_dbg = $def_output_dbg;    # "-NEW_OUTD_DBG-" $out_dir
    $dsp_output_rel = $def_output_rel;    # "-NEW_OUTD_REL-" $out_dir
    $dsp_inter_dbg  = $def_inter_dbg;    # "-NEW_INTER_DBG-" $int_dir
    $dsp_inter_rel  = $def_inter_rel;    # "-NEW_INTER_REL-" $int_dir
    $dsp_out_dbg = $def_out_dbg;    # "-NEW_OUT_DBG-"
    $dsp_out_rel = $def_out_rel;    # "-NEW_OUT_REL-"
    if ($dbg_d11a) {
        for ($i = 0; $i < $rcnt; $i++) {
            $val   = $refs[$i][0];
            $cond  = $refs[$i][1];
            $pform = $refs[$i][2];
            $rtim  = $refs[$i][3];
            prt( "$i: $key|$pform|$cond|$rtim\n" );
        }
    }
    # my %v8_linkout = (); # Name="VCLinkerTool" OutputFile=".\Release\FlightGear.exe", by configuration
    # $dsp_out_[dbg|rel} = $def_out_[dbg|rel] = "-NEW_OUT_[DBG|REL]"
    # = $outputs = $v8_linkout{$conf} = push(@allarr, "$linkout=[$lout]");
    for ($i = 0; $i < $rcnt; $i++) {
        $val   = $refs[$i][0];
        $cond  = $refs[$i][1];
        $pform = $refs[$i][2];
        $rtim  = $refs[$i][3];
        prt( "$key|$pform|$cond|$rtim\n" ) if ($dbg_d11 || $dbg_d11a);
        @arr = array_ref_2_array($val);
        %hash = array_2_hash_on_equals(@arr);
        foreach $ky (keys %hash) {
            $cont = $hash{$ky};
            $cont =~ s/^\[//;
            $cont =~ s/\]$//;
            prt( "$ky=[$cont]\n" ) if ($dbg_d11);
            if ($ky eq $postevt) {
                if (length($cont)) {
                    # PostBuild_Desc=Copy to bin
                    # PostBuild_Cmds=copy Release\*exe bin\.   copy test.h bin\.
                    %h2 = array_2_hash_on_equals(space_split($cont));
                    $dmsg = '';
                    $dmsg .= "# Begin Special Build Tool\n";
                    $dmsg .= "SOURCE=\"\$(InputPath)\"\n";
                    $dmsg .= "PostBuild_Desc=";
                    if (defined $h2{$postdesc}) {
                       $dmsg .= strip_quotes($h2{$postdesc});
                    }
                    $dmsg .= "\n";
                    $dmsg .= "PostBuild_Cmds=";
                    if (defined $h2{$postcmds}) {
                        $tmp = strip_quotes($h2{$postcmds});
                        $tmp = massage_command($tmp);
                        $dmsg .= $tmp;
                    }
                    $dmsg .= "\n";
                    $dmsg .= "# End Special Build Tool\n";
                    $dmsg =~ s/&quot;/"/g;
                    if ($cond =~ /Debug/i) {
                        $dsp_post_dbg = $dmsg;  # $msg =~ s/-NEW_POST_DBG-/$dsp_post_dbg/gm;
                    } else {
                        $dsp_post_rel = $dmsg;  # $msg =~ s/-NEW_POST_REL-/$dsp_post_rel/gm;
                    }
                }
            } elsif ($ky eq $outputs) {
                # my %v8_config = ();  #  by configuration, OutputDirectory=".\Release", IntermediateDirectory="Release",
                # 28/09/2008 - note, has quotes added push(@allarr, "$outputs=[$outs]");
                # $dsp_output_dbg = $def_output_dbg;    # "-NEW_OUTD_DBG-" $out_dir
                # $dsp_output_rel = $def_output_rel;    # "-NEW_OUTD_REL-" $out_dir
                # $dsp_inter_dbg  = $def_inter_dbg;    # "-NEW_INTER_DBG-" $int_dir
                # $dsp_inter_rel  = $def_inter_rel;    # "-NEW_INTER_REL-" $int_dir
                if (length($cont)) {
                    %h2 = array_2_hash_on_equals(space_split($cont));
                    $dmsg = "Object OUPUT: $outputs]=[$cont]";
                    $ref1 = \$dsp_output_rel;
                    $ref2 = \$dsp_inter_rel;
                    if ($cond =~ /Debug/i) {
                        $ref1 = \$dsp_output_dbg;
                        $ref2 = \$dsp_inter_dbg;
                        $dmsg .= ' (DEBUG)';
                    }
                    if (defined $h2{$out_dir}) {
                        $$ref1 = $h2{$out_dir};
                        $dmsg .= ' ['.$$ref1.']';
                    }
                    if (defined $h2{$int_dir}) {
                        $$ref2 = $h2{$int_dir};
                        $dmsg .= ' ['.$$ref2.']';
                    }
                    prt( "$dmsg\n" ) if ($dbg_d14);
                }
            } elsif ($ky eq $linkout) {
                # my %v8_linkout = (); # Name="VCLinkerTool" OutputFile=".\Release\FlightGear.exe", by configuration
                # $dsp_out_[dbg|rel} = $def_out_[dbg|rel] = "-NEW_OUT_[DBG|REL]"
                # $v8_linkout{$conf} = push(@allarr, "$linkout=[$lout]");
                if (length($cont)) {
                    $dmsg = "Link OUPUT: $linkout=[$cont]";
                    $ref1 = \$dsp_out_rel;
                    if ($cond =~ /Debug/i) {
                        $ref1 = \$dsp_out_dbg;
                        $dmsg .= ' (DEBUG)';
                    }
                    $$ref1 .= ' ' if length($$ref1);
                    $$ref1 .= '/out:'.add_quotes($cont);
                    $dmsg .= ' '.$$ref1;
                    prt( "$dmsg\n" ) if ($dbg_d13);;
                }
            } elsif ($ky eq $libpath) {
                if (length($cont)) {
                    # AdditionalLibraryDirectories
                    # add like  /libpath:"testdll___Win32_Release" /libpath:"libs"
                    $dmsg = "Link LIBPATH: $cond libpaths=[$cont]";
                    $ref1 = \$dsp_out_rel;
                    if ($cond =~ /Debug/i) {
                        $ref1 = \$dsp_out_dbg;
                        $dmsg .= ' (DEBUG)';
                    }
                    @ar2 = split(/[;,]/,$cont);
                    $cnt = scalar @ar2;
                    for ($j = 0; $j < $cnt; $j++) {
                        $tmp = '/libpath:'.add_quotes(strip_quotes(trim_all($ar2[$j])));
                        $$ref1 .= ' ' if length($$ref1);
                        $$ref1 .= $tmp;
                        $dmsg .= ' '.$tmp;
                    }
                    prt( "$dmsg\n" ) if ($dbg_d15);
                } else {
                    prt( "Link LIBPATH: $cond libpaths=[<NULL>]\n" ) if ($dbg_d15);
                }
            }
        }   # foreach $key in the HASH
    }   # for EACH reference, per $i
    if ($dbg_d12 || $dbg_d10) {
        foreach $ky (keys %dsp_substitions) {
            $val = $dsp_substitions{$ky};
            $cont = $$val;
            prt( "s/$ky/[$cont]/gm\n" );
        }
        prt( "CHECK OUT THE REPLACEMENTS!\n" );
        ###close_log($outfile,1);
        ###exit(0);
    }
    rename_2_old_bak($tof);
   if (open $DSP, ">$tof") {
      push(@dsp_written, $dspmsg);
        push(@dsp_list, $ffrdsp);
      # perform SUBSTITUTIONS
        foreach $ky (keys %dsp_substitions) {
            $val = $dsp_substitions{$ky};
            $cont = $$val;
            $msg =~ s/$ky/$cont/gm;
        }
      print $DSP $msg;
      #                 0     1    2          3          4  5  6
      # push(@v8_srcs, [$src, $ff, $filtname, $filttype, 0, 0, $projname, 7] );
      $cnt = scalar @v8_srcs;
      for ($i = 0; $i < $cnt; $i++) {
         $v8_srcs[$i][V8_DON] = 0;   # [5] clear the DONE FLAG
            if ($use_std_groups) {  # subsequent thought that this is BAD IDEA!!!
                $src = $v8_srcs[$i][0];         # source file
                $fnm = $v8_srcs[$i][V8_GRP];    # [2] # GROUP NAME 'Source Files', etc ...
                $ftyp = $v8_srcs[$i][3];        # group filter, if any
                $shr = $v8_srcs[$i][V8_SHR];    # [7] get GROUP by extension
                $def_grp = get_def_group_name($shr);
                if ($def_grp =~ /^$def_unknown/) {
                    prt( "CHECK UNKNOWN: $shr for $src WHAT IS THIS???\n" );
                } else {
                    if (length($fnm) ) {
                        if ($fnm ne $def_grp) {
                            if (!is_rc_file($src)) {
                                prt( "CHECK CHANGE: Change from '$fnm' to '$def_grp' for $src ... [$ftyp] \n" );
                            }
                            $v8_srcs[$i][V8_GRP] = $def_grp;
                        }
                    } else {
                        $v8_srcs[$i][V8_GRP] = $def_grp;
                    }
                }
            }
      }
      $rpt = 1;   # set to BEGIN LOOP
      while ($rpt) {
         $rpt = 0;   # assume NO MORE
         for ($i = 0; $i < $cnt; $i++) {
            if ($v8_srcs[$i][V8_DON] == 0) {    # [5]
               $src = $v8_srcs[$i][0];
               $fnm = $v8_srcs[$i][V8_GRP];   # [2] GROUP NAME 'Source Files', etc ...
               $ftyp = $v8_srcs[$i][3];
               if ( length($fnm) && !is_in_array($fnm,@fltnms) ) {
                  if ($fnm =~ /Source/i) {
                     prt( "Outing GROUP $fnm ...\n" ) if (!$got_src);
                     $got_src = 1;
                  } elsif ($fnm =~ /Header/i) {
                     prt( "Outing GROUP $fnm ...\n" ) if (!$got_hdr);
                     $got_hdr = 1;
                  } elsif ($fnm =~ /Resource/i) {
                     prt( "Outing GROUP $fnm ...\n" ) if (!$got_rc);
                     $got_rc = 1;
                  } else {
                     prt( "Outing GROUP $fnm ...\n" ) if (!$got_other);
                     $got_other = 1;
                        }
                  push(@fltnms,$fnm);   # add it to the DONE GROUP
                  $v8_srcs[$i][V8_DON] = 1; # [5] SET AS DONE
                  print $DSP '# Begin Group "'.$fnm."\"\n";
                  print $DSP "\n";
                  if (length$ftyp) {
                     print $DSP '# PROP Default_Filter "'.$ftyp."\"\n";
                  }
                  fg_out_src($src,$DSP,$v8_srcs[$i][V8_EXC]);
                  $src_cnt++;
                  $i++;   # move to NEXT
                  for (; $i < $cnt; $i++) {
                     $src = $v8_srcs[$i][0];
                     if ($v8_srcs[$i][V8_DON] == 0) {
                        if ($fnm eq $v8_srcs[$i][2]) {
                           fg_out_src($src,$DSP,$v8_srcs[$i][V8_EXC]);
                           $src_cnt++;
                           $v8_srcs[$i][V8_DON] = 1; # SET AS DONE
                        }
                     }
                  }
                  print $DSP "# End Group\n";
                  $rpt = 1;   # try for some more
               }
            }
         }
      }
      # add any GROUPS not already DONE
        if ($add_blank_groups) {    # NOT A GOOD IDEA!!!
            if (!$got_src) {
                $fnm = "Source Files";
                $ftyp = $def_src_g; # = "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90"
                prt( "Outing GROUP $fnm ... BLANK\n" );
                print $DSP '# Begin Group "'.$fnm."\"\n";
                print $DSP "\n";
                print $DSP '# PROP Default_Filter "'.$ftyp."\"\n";
                print $DSP "# End Group\n";
            }
            if (!$got_hdr) {
                $fnm = "Header Files";
                $ftyp = $def_hdr_g; # = "h;hpp;hxx;hm;inl;fi;fd"
                prt( "Outing GROUP $fnm ... BLANK\n" );
                print $DSP '# Begin Group "'.$fnm."\"\n";
                print $DSP "\n";
                print $DSP '# PROP Default_Filter "'.$ftyp."\"\n";
                print $DSP "# End Group\n";
            }
            if (!$got_rc) {
                $fnm = "Resource Files";
                prt( "Outing GROUP $fnm ... BLANK\n" );
                $ftyp = $def_rcs_g; # = "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
                print $DSP '# Begin Group "'.$fnm."\"\n";
                print $DSP "\n";
                print $DSP '# PROP Default_Filter "'.$ftyp."\"\n";
                print $DSP "# End Group\n";
            }
        }
      ###################################
      # any NOT in a GROUP
      for ($i = 0; $i < $cnt; $i++) {
         if ($v8_srcs[$i][V8_DON] == 0) {
            $non_cnt++
         }
      }
      prt( "Outing any NOT IN GROUP, count $non_cnt ... $act_vcproj\n" ) if ($non_cnt);
      for ($i = 0; $i < $cnt; $i++) {
         if ($v8_srcs[$i][V8_DON] == 0) {
            $src = $v8_srcs[$i][0];
            out_src($src,$DSP,$v8_srcs[$i][V8_EXC]);
            $src_cnt++;
         }
      }
      $msg = get_dsp_tail();
      print $DSP $msg;
      close $DSP;
      prt( "Written temp [$tof] DSP file, with $src_cnt sources - (real=$reald)\n" );
   } else {
      prtw( "WARNING: Failed to create [$tof] ... $! ...\n" );
   }
}
sub fg_get_runtime_stg {
   my ($rtn) = shift;
    my $len = scalar @runtimes_array;
    for (my $i = 0; $i < $len; $i++) {
        my $itm = $runtimes_array[$i][3];
        if ($itm == $rtn) {
            return "/" . $runtimes_array[$i][1];
        }
    }
    prtw( "WARNING: $rtn not found in runtimes_array! Using default '/MT'!! $act_vcproj\n" );
   return "/MT";
}
sub get_runtime_stg {
   my ($rtn) = shift;
   if ($rtn == 0) {
      return "/MT";
   } elsif ($rtn == 1) {
      return "/MTd";
   } elsif ($rtn == 2) {
      return "/MD";
   } elsif ($rtn == 3) {
      return "/MDd";
   }
   return "/MT";
}
sub array_ref_2_array {
    my ($ref) = shift;
    my @narr = ();
    foreach (@{$ref}) {
        push(@narr,$_);
    }
    return @narr;
}
# $defines=[/D "_CRT_SECURE_NO_WARNINGS" /D "_CRT_SECURE_NO_DEPRECATE"]
sub split_defines {
    my ($txt) = shift;
    my @darr = ();
    my $len = length($txt);
    my ($i, $ch, $inq, $tag);
    $inq = 0;
    $tag = '';
    for ($i = 0; $i < $len; $i++) {
        $ch = substr($txt,$i,1);
        if ($inq) {
            if ($ch eq '"') {
                push(@darr, $tag) if length($tag);
                $tag = '';
                $inq = 0;
            }
        } else {
            if ($ch eq '"') {
                $tag = '';
                $inq = 1;
            }
        }
    }
    return @darr;
}
sub prtf {
    my ($of, $txt) = @_;
    print $of $txt;
}
##                  [0]SRC [1]FUL [2]GRP    [3]FIL      [4]CMP [5]DON [6]PRJ     [7]SHR [8]EXC
##                  relnm  full   group      filter     cmp    done   project    grp    exclude
##   @all_sources   [$src,  $ff,   $filtname, $filttype, 0,     0,     $projname, shr,   excl] );
sub out_group_files {
    my ($OF, $pname, $max, $sep, $f, $grp, $filt, $scnt, $xcnt) = @_;
    my ($prj, $src, $grp2, $filt2);
    for (; $f < $max; $f++) {
        if ($all_sources[$f][V8_DON] == 0) {
            $prj = $all_sources[$f][V8_PRJ];
            $filt2 = $all_sources[$f][V8_FIL];
            $grp2  = $all_sources[$f][V8_GRP];
            if ( ($pname eq $prj) && ($grp eq $grp2) ) {
                $src = strip_dotrel($all_sources[$f][V8_SRC]);
                if ($all_sources[$f][V8_EXC] eq $excl_mark) {
                    prtf( $OF, $excfiles.$sep.$src."\n");
                    $$xcnt++;
                } else {
                    prtf( $OF, $srcfiles.$sep.$src."\n");
                    $$scnt++;
                }
                $all_sources[$f][V8_DON] = 1;
            }
        }
    }
}
sub add_source_files {
    my ($OF, $pname, $max, $sep) = @_;
    my $scnt = 0;
    my $xcnt = 0;
    my ($f, $prj, $filt, $grp);
    for ($f = 0; $f < $max; $f++) {
        if ($all_sources[$f][V8_DON] == 0) {
            $prj = $all_sources[$f][V8_PRJ];
            if ($pname eq $prj) {
                $filt = $all_sources[$f][V8_FIL];
                $grp  = $all_sources[$f][V8_GRP];
                # my $filter    = '_filter_';
                prtf( $OF, $filter.$sep.$grp.'='.$filt."\n");
                out_group_files($OF, $pname, $max, $sep, $f, $grp, $filt, \$scnt, \$xcnt);
                prtf( $OF, "\n");
            }
        }
    }
    prtf( $OF, "# Listed $scnt sources");
    if ($xcnt) {
        prtf( $OF, ", $xcnt excluded");
    }
    prtf( $OF, "\n\n");
}
sub get_refall_groups {
    my @groups = ();
    my (@keys, $kcnt, $gnum);
    my ($k, $key, @ar, $pname, $cond, $pform, $rtim);
    my ($j, $ky, $pname2, $cond2);
    @keys = sort keys(%v6_refall);
    $kcnt = scalar @keys;
    $gnum = 0;
    for ($k = 0; $k < $kcnt; $k++) {
        $key = $keys[$k];
        @ar = split(/\|/,$key);
        $pname = $ar[0];
        $cond  = $ar[1];
        $pform = $ar[2];
        $rtim  = $ar[3];
        #              0      1       2     3      4       5
        push(@groups, [$gnum, $pname, $key, $cond, $pform, $rtim]);
        for ($j = $k + 1; $j < $kcnt; $j++) {
            $ky = $keys[$j];
            @ar = split(/\|/,$ky);
            $pname2 = $ar[0];
            $cond2  = $ar[1];
            if ($pname eq $pname2) {
                $k++;
                #              0      1       2    3       4       5
                push(@groups, [$gnum, $pname, $ky, $cond2, $ar[2], $ar[3]]);
            } else {
                last;
            }
        }
        $gnum++;
    }
    return $gnum,@groups;
}
sub show_v6_refall {
    my ($key, $val, @ar, $pname);
    my ($atype, $msg, $mxky);
    my (@arr, %hash, $ky, $tmp);
    my ($cond, @keys, @groups, $kcnt, $k, $gnum, $j);
    my ($pname2, $cond2, $rcnt);
    my (@refs, $cont, $scnt, $xcnt);
    my ($outfil, $rtim, $pform);
    my (%h2);
    my $sep = "\t=\t";
    my $fcnt = 0;
    my $flist = '';
    my $max = scalar @all_sources; # multidimensional array with lot of information
    my ($f);
    $mxky = 32;
    $tmp = "\t";
    prt( "\nNow the LIST from v6_refall... " );
    $kcnt = scalar keys(%v6_refall);
    prt( "Grouping $kcnt keys... " );
    ($gnum, @groups) = get_refall_groups();
    prt( "into $gnum groups... " );
    if ($addfiles2cfg && $max) {
        for ($f = 0; $f < $max; $f++) {
           $all_sources[$f][V8_DON] = 0;
        }
        prt( "cleared done ..." );
    }
    prt( "\n" );
    if ($kcnt != scalar @groups) {
        prtw( "WARNING: failed to divide into correct groups! $kcnt versus ".scalar @groups."! FIX CODE!!\n");
        return;
    }
    for ($k = 0; $k < $kcnt; $k++) {
        $gnum  = $groups[$k][0];
        $pname = $groups[$k][1];
        $key   = $groups[$k][2];
        $cond  = $groups[$k][3];
        $pform = $groups[$k][4];
        $rtim  = $groups[$k][5];
        $val = $v6_refall{$key};
        if (defined $v8_apptypes{$pname}) {
            $atype = $v8_apptypes{$pname};
        } else {
            $atype = "UNKNOWN APPLICATION TYPE - CHECK ME Did not find $pname in v8_apptypes!!!";
            prtw( "$atype\n" );
            next;
        }
        $msg = '';
        # name of application or library
        # my $prjname   = 'projname';
        $msg .= $prjname.$sep.$pname."\n";
        # type = ConsoleApplication|StaticLibrary|DLL|Application
        # my $ap_type   = 'app_type';
        $msg .= $ap_type.$sep.$atype."\n";
        @refs = (); # clear last references
        # collect all with this $gnum
        #            0     1      2       3
        push(@refs, [$val, $cond, $pform, $rtim]);
        for ($j = $k + 1; $j < $kcnt; $j++) {
            if( $gnum == $groups[$j][0] ) {
                $ky    = $groups[$j][2];
                $cond2 = $groups[$j][3];
                $pform = $groups[$j][4];
                $rtim  = $groups[$j][5];
                $val = $v6_refall{$ky};
                #             0     1       2       3
                push(@refs, [ $val, $cond2, $pform, $rtim ]);
                $k++;   # skip this used one
            } else {
                last;
            }
        }
        $msg .= "\n";
        # have a set of refs
        $rcnt = scalar @refs;
        # $defines=[/D "_CRT_SECURE_NO_WARNINGS" /D "_CRT_SECURE_NO_DEPRECATE"]
        # outputs=[".\Win32_LIB_Debug" ".\Win32_LIB_Debug"]
       # $linkout=[Win32_LIB_Debug\zlibd.lib]
        # $includes=[...]
        # $libraries=[comctl32.lib Msimg32.lib Winmm.lib]
        # $libpath=[...]
        for ($j = 0; $j < $rcnt; $j++) {
            $val   = $refs[$j][0];
            $cond  = $refs[$j][1];
            $pform = $refs[$j][2];
            $rtim  = $refs[$j][3];
            if ($j == 0) {
                $msg .= "if $cond\n\n";
            } elsif (($j + 1) < $rcnt) {
                $msg .= "\nelse if $cond\n\n";
            } else {
                $msg .= "\nelse\n\n";
            }
            $msg .= $platform.$sep.$pform."\n"; # add PLATFORM
            $msg .= $runtime.$sep.fg_get_runtime_lts_2_stg($rtim)."\n";   # add RUNTIME
            @arr = array_ref_2_array($val);
            %hash = array_2_hash_on_equals(@arr);
            foreach $ky (keys %hash) {
                $cont = $hash{$ky};
                $cont =~ s/^\[//;
                $cont =~ s/\]$//;
                if ($ky eq $defines) {
                    # defines=[/D "_CRT_SECURE_NO_WARNINGS" /D "_CRT_SECURE_NO_DEPRECATE"]
                    @arr = split_defines($cont);
                    foreach (@arr) {
                        $msg .= $defines.$sep.$_."\n";
                    }
                } elsif ($ky eq $outputs) {
                    ### $msg .= "# $outputs = $cont\n";
                    # outputs=[$out_dir=".\Release" $int_out=".\Release"]
                    # prtw( "SHOW OUTS: [$cont]\n" );
                    %h2 = array_2_hash_on_equals(space_split($cont));
                    foreach (keys (%h2)) {
                        $msg .= $_ .$sep.strip_quotes($h2{$_})."\n";
                    }
                } elsif ($ky eq $linkout) {
                    # $linkout=[.\Release\FlightGear.exe]
                    $msg .= $linkout.$sep.$cont."\n";
                } elsif ($ky eq $includes) {
                    # includes=[.,..,.\SimGear,..\zlib-1.2.3,C:\Program Files\OpenAL 1.1 SDK\include,..\openal\alut\include,..\OpenAL\include\AL,..\OpenSceneGraph\include,
                    # ..\OpenThreads\include,..\pthreads;..\alut\include]
                    $cont =~ s/&quot;/"/g;
                    foreach (split(/[;,]/,$cont)) {
                        $msg .= $includes.$sep.strip_dotrel($_)."\n";
                    }
                } elsif ($ky eq $libraries) {
                    # libraries=[comctl32.lib Msimg32.lib Winmm.lib openal32.lib]
                    foreach (split(/\s/,$cont)) {
                        $msg .= $libraries.$sep.$_."\n";
                    }
                } elsif ($ky eq $libpath) {
                    # lib_path=[..\SimGear\$(IntDir); ..\PLIB,..\zlib-1.2.3\projects\visualc6\Win32_LIB_Debug
                    foreach (split(/[,;]/,$cont)) {
                        # hmmmm, like the above, sometimes there is a SPACE beginning
                        # should I remove it? for now NO!
                        $msg .= $libpath.$sep.$_."\n";
                    }
                } elsif ($ky eq $postevt) {
                    if (length($cont)) {
                        # PostBuild_Desc=Copy to bin
                        # PostBuild_Cmds=copy Release\*exe bin\.   copy test.h bin\.
                        %h2 = array_2_hash_on_equals(space_split($cont));
                        foreach (keys (%h2)) {
                            $msg .= $_ .$sep.strip_quotes($h2{$_})."\n";
                        }
                        # for the DSP file
                        # $msg .= "# Begin Special Build Tool\n";
                        # $msg .= "SOURCE=\"\$(InputPath)\"\n";
                        # $msg .= "PostBuild_Desc=";
                        # if (defined $h2{$postdesc}) {
                        #    $msg .= strip_quotes($h2{$postdesc});
                        # }
                        # $msg .= "\n";
                        # $msg .= "PostBuild_Cmds=";
                        # if (defined $h2{$postcmds}) {
                        #    $msg .= strip_quotes($h2{$postcmds});
                        #}
                        # $msg .= "\n";
                        # $msg .= "# End Special Build Tool\n";
                    }
                } else {
                    if (length($cont)) {
                        $cont =~ s/\t/\n/g;
                        prtw("WARNING: [$cond] Unhandle key [$ky], with value\n".
                            "[$cont]!!!\n" );
                    }
                }
                ###$msg .= "$ky=".$hash{$ky} . "\n";
            }
        }
        $msg .= "\nendif\n";
        prt( "$msg\n" ) if ($dbg_x09);    # done ONE application
        # generate a configuration file
        #########################################
        $outfil = "temp.$pname.cfg.txt";
        my ($OF);
        rename_2_old_bak($outfile);
        if (open $OF, ">$outfil") {
            $fcnt++;
            $flist .= '|' if length($flist);
            $flist .= $pname;
            $cont = "# configuration for $pname - generated by $pgname\n# on ".scalar localtime(time())."\n";
            prtf( $OF, $cont);
            prtf( $OF, "\n");
            prtf( $OF, $msg);
            prtf( $OF, "\n");
            # write out the source files, per filter to cfg files
            if ($addfiles2cfg && $max) {
                add_source_files( $OF, $pname, $max, $sep );
            }
            prtf( $OF, "# eof - $outfil\n" );
            close $OF;
        } else {
            prtw( "WARNING: Unable to create $outfil! ... $! ...\n" );
        }
        ##########################################
    }
    if ($addfiles2cfg && $max) {
        for ($f = 0; $f < $max; $f++) {
           if ($all_sources[$f][V8_DON] == 0) {
               prtw( "WARNING: Source MISSED [".$all_sources[$f][V8_PRJ]."] [".
                   strip_dotrel($all_sources[$f][V8_SRC])."] WHY????\n" );
           }
        }
    }
    prt("Written $fcnt configuration files ... one each for -\n$flist\n");
}
sub add_proj_2_depends {
    my ($OF, $sln) = @_;    # if ($add_projs_to_depends);
    my ($key, $val, @ar, $pname);
    my ($atype, $msg, $mxky);
    my (@arr, %hash, $ky, $tmp);
    my ($cond, @keys, @groups, $kcnt, $k, $gnum, $j);
    my ($pname2, $cond2, $rcnt);
    my (@refs, $cont, $scnt, $xcnt);
    my ($outfil, $rtim, $pform);
    my (%h2);
    my $sep = "\t=\t";
    my $fcnt = 0;
    my $flist = '';
    my $max = scalar @all_sources; # multidimensional array with lot of information
    my ($f);
    $mxky = 32;
    $tmp = "\t";
    prt( "Now the LIST from v6_refall... " );
    $kcnt = scalar keys(%v6_refall);
    prt( "Grouping $kcnt keys... " );
    ($gnum, @groups) = get_refall_groups();
    prt( "into $gnum groups... " );
    if ($addfiles2cfg && $max) {
        for ($f = 0; $f < $max; $f++) {
           $all_sources[$f][V8_DON] = 0;
        }
        prt( "cleared done ..." );
    }
    prt( "\n" );
    if ($kcnt != scalar @groups) {
        prtw( "WARNING: failed to divide into correct groups! $kcnt versus ".scalar @groups."! FIX CODE!!\n");
        return;
    }
    for ($k = 0; $k < $kcnt; $k++) {
        $gnum  = $groups[$k][0];
        $pname = $groups[$k][1];
        $key   = $groups[$k][2];
        $cond  = $groups[$k][3];
        $pform = $groups[$k][4];
        $rtim  = $groups[$k][5];
        $val = $v6_refall{$key};
        if (defined $v8_apptypes{$pname}) {
            $atype = $v8_apptypes{$pname};
        } else {
            $atype = "UNKNOWN APPLICATION TYPE - CHECK ME Did not find $pname in v8_apptypes!!!";
            prtw( "$atype\n" );
            next;
        }
        $msg = '';
        # name of application or library
        # my $prjname   = 'projname';
        $msg .= $prjname.$sep.$pname."\n";
        # type = ConsoleApplication|StaticLibrary|DLL|Application
        # my $ap_type   = 'app_type';
        $msg .= $ap_type.$sep.$atype."\n";
        @refs = (); # clear last references
        # collect all with this $gnum
        #            0     1      2       3
        push(@refs, [$val, $cond, $pform, $rtim]);
        for ($j = $k + 1; $j < $kcnt; $j++) {
            if( $gnum == $groups[$j][0] ) {
                $ky    = $groups[$j][2];
                $cond2 = $groups[$j][3];
                $pform = $groups[$j][4];
                $rtim  = $groups[$j][5];
                $val = $v6_refall{$ky};
                #             0     1       2       3
                push(@refs, [ $val, $cond2, $pform, $rtim ]);
                $k++;   # skip this used one
            } else {
                last;
            }
        }
        $msg .= "\n";
        # have a set of refs
        $rcnt = scalar @refs;
        # $defines=[/D "_CRT_SECURE_NO_WARNINGS" /D "_CRT_SECURE_NO_DEPRECATE"]
        # outputs=[".\Win32_LIB_Debug" ".\Win32_LIB_Debug"]
       # $linkout=[Win32_LIB_Debug\zlibd.lib]
        # $includes=[...]
        # $libraries=[comctl32.lib Msimg32.lib Winmm.lib]
        # $libpath=[...]
        for ($j = 0; $j < $rcnt; $j++) {
            $val   = $refs[$j][0];
            $cond  = $refs[$j][1];
            $pform = $refs[$j][2];
            $rtim  = $refs[$j][3];
            if ($j == 0) {
                $msg .= "if $cond\n\n";
            } elsif (($j + 1) < $rcnt) {
                $msg .= "\nelse if $cond\n\n";
            } else {
                $msg .= "\nelse\n\n";
            }
            $msg .= $platform.$sep.$pform."\n"; # add PLATFORM
            $msg .= $runtime.$sep.fg_get_runtime_lts_2_stg($rtim)."\n";   # add RUNTIME
            @arr = array_ref_2_array($val);
            %hash = array_2_hash_on_equals(@arr);
            foreach $ky (keys %hash) {
                $cont = $hash{$ky};
                $cont =~ s/^\[//;
                $cont =~ s/\]$//;
                if ($ky eq $defines) {
                    # defines=[/D "_CRT_SECURE_NO_WARNINGS" /D "_CRT_SECURE_NO_DEPRECATE"]
                    @arr = split_defines($cont);
                    foreach (@arr) {
                        $msg .= $defines.$sep.$_."\n";
                    }
                } elsif ($ky eq $outputs) {
                    ### $msg .= "# $outputs = $cont\n";
                    # outputs=[$out_dir=".\Release" $int_out=".\Release"]
                    # prtw( "SHOW OUTS: [$cont]\n" );
                    %h2 = array_2_hash_on_equals(space_split($cont));
                    foreach (keys (%h2)) {
                        $msg .= $_ .$sep.strip_quotes($h2{$_})."\n";
                    }
                } elsif ($ky eq $linkout) {
                    # $linkout=[.\Release\FlightGear.exe]
                    $msg .= $linkout.$sep.$cont."\n";
                } elsif ($ky eq $includes) {
                    # includes=[.,..,.\SimGear,..\zlib-1.2.3,C:\Program Files\OpenAL 1.1 SDK\include,..\openal\alut\include,..\OpenAL\include\AL,..\OpenSceneGraph\include,
                    # ..\OpenThreads\include,..\pthreads;..\alut\include]
                    $cont =~ s/&quot;/"/g;
                    foreach (split(/[;,]/,$cont)) {
                        $msg .= $includes.$sep.strip_dotrel($_)."\n";
                    }
                } elsif ($ky eq $libraries) {
                    # libraries=[comctl32.lib Msimg32.lib Winmm.lib openal32.lib]
                    foreach (split(/\s/,$cont)) {
                        $msg .= $libraries.$sep.$_."\n";
                    }
                } elsif ($ky eq $libpath) {
                    # lib_path=[..\SimGear\$(IntDir); ..\PLIB,..\zlib-1.2.3\projects\visualc6\Win32_LIB_Debug
                    foreach (split(/[,;]/,$cont)) {
                        # hmmmm, like the above, sometimes there is a SPACE beginning
                        # should I remove it? for now NO!
                        $msg .= $libpath.$sep.$_."\n";
                    }
                } elsif ($ky eq $postevt) {
                    if (length($cont)) {
                        # PostBuild_Desc=Copy to bin
                        # PostBuild_Cmds=copy Release\*exe bin\.   copy test.h bin\.
                        %h2 = array_2_hash_on_equals(space_split($cont));
                        foreach (keys (%h2)) {
                            $msg .= $_ .$sep.strip_quotes($h2{$_})."\n";
                        }
                    }
                } else {
                    if (length($cont)) {
                        $cont =~ s/\t/\n/g;
                        prtw("WARNING: [$cond] Unhandle key [$ky], with value\n".
                            "[$cont]!!!\n" );
                    }
                }
                ###$msg .= "$ky=".$hash{$ky} . "\n";
            }
        }
        $msg .= "\nendif\n";
        prt( "$msg\n" ) if ($dbg_x09);    # done ONE application
        # write to dependencies file
        #########################################
        $fcnt++;
        $flist .= '|' if length($flist);
        $flist .= $pname;
        $cont = "[configuration-$pname]\n";
        prtf( $OF, $cont);
        prtf( $OF, "\n");
        prtf( $OF, $msg);
        prtf( $OF, "\n");
        # write out the source files, per filter to cfg files
        if ($addfiles2cfg && $max) {
            add_source_files( $OF, $pname, $max, $sep );
        }
        prtf( $OF, "[eos-$pname]\n\n" );
        ##########################################
    }
    if ($addfiles2cfg && $max) {
        for ($f = 0; $f < $max; $f++) {
           if ($all_sources[$f][V8_DON] == 0) {
               prtw( "WARNING: Source MISSED [".$all_sources[$f][V8_PRJ]."] [".
                   strip_dotrel($all_sources[$f][V8_SRC])."] WHY????\n" );
           }
        }
    }
    prt("Written $fcnt configuration blocks\n");
}
# my %sln_depends  = ();   # dependencies, key by projname, with '|' list of values
sub write_out_depends {
    my ($sln) = shift;
    my $outfil = 'temp.'.$sln.'.cfg.txt';
    my $msg = '';
    my $cnt = scalar keys(%sln_depends);
    my ($key, $val, $OF);
    prt( "Writing $cnt potential dependencies to $outfil ...\n" ) if ($dbg_x19);
    $cnt = 0;
    rename_2_old_bak($outfil);
    if (open $OF, ">$outfil") {
        $msg = "# configuration for $sln - generated by $pgname\n# on ".scalar localtime(time())."\n";
        $msg .= "# list of inter-project dependencies, if any ...\n";
        print $OF $msg;
        print $OF "\n";
        print $OF "[dependencies-$sln]\n\n";
        foreach $key (keys %sln_depends) {
            $val = $sln_depends{$key};
            if (length($val)) {
                $msg = $depends."\t=\t"."$key=$val\n";
                print $OF $msg;
                prt($msg) if ($dbg_x19);
                $cnt++;
            }
        }
        print $OF "\n";
        add_proj_2_depends($OF, $sln) if ($add_projs_to_depends);
        print $OF "# eof - $outfil\n";
        close $OF;
        prt( "Written $cnt dependencies to $outfil ...\n" );
    } else {
        prtw( "WARNING: Unable to create $outfil! ... $! ...\n" );
    }
}
sub set_modest_debug {
    $dbg_sln = 1;    # show prt( "$cnt: Project=[".$arr[0]."] Path=[".$arr[1]."] ...
    $dbg_src6 = 1;   # show prt( "Got configuration $conf
    $dbg_src8  = 1;  # show prt( "Setting DEFS: $conf [$ppdefs] $apptype ($ctype)
    $dbg_src11 = 1;  # show prt( "Project=$projname, v=$version GUID=$ProjectGUID
    $dbg_src12 = 1;  # show prt( "Setting LINKS: $conf [$adddeps]
    $dgb_src17 = 1;  # show prt( "Got RUNTIME value [$ppdefs] ... config=$conf ($ctype) $itm (= $def)
    $dbg_x12 = 1;    # show prt( "VCPROJ Project: $projname, as $apptype, version=$version ... AND MORE
    #$dbg_x13 = 1;    # show prt( "Defined Debug = $dsp_defines_dbg, Release = $dsp_defines_rel... AND MORE
    $dbg_x14 = 1;    # show prt("Set INCLUDES:$conf: to [$ppdefs]
    $dbg_x15 = 1;    # show prt( "Set APPTYPE:$conf: v8_aptype[$apptype] (ln=$lnnum)... AND MORE see $dgbx_08 also
    #$dbg_x16 = 1;    # show prt("Got APPTYPE:$conf: NO CHANGE [$apptype] equals SubSystem ($adddeps) [".$v8_subsystems{$adddeps}."] ...
    $dbg_x17 = 1;    # show    prt( "\nLoading [$in] file in directory [$in_fd] ...
}
sub prtw {
    my ($tx) = shift;
    if ($tx =~ /\n$/) {
        prt($tx);
        $tx =~ s/\n$//;
    } else {
        prt("$tx\n");
    }
    push(@warnings,$tx);
}
sub show_warnings {
    if (@warnings) {
        prt( "\nGot ".scalar @warnings." WARNINGS ...\n" );
        foreach my $line (@warnings) {
            prt("$line\n" );
        }
        prt("\n");
    } else {
        prt("\nNo warnings issued.\n\n");
    }
}
# eof - fgsln2dsw.pl

index -|- top

checked by tidy  Valid HTML 4.01 Transitional