#!/usr/bin/perl -w
# NAME: vcproj05.pl
# AIM: To scan a VCPROJ file, and show the results, and write (temp) DSP/DSW files.
# Since this is all about MSVC things, no attempt has been made to run it in unix.
# 19/06/2012 - Added <DisableSpecificWarnings>4996;4013;4018;4024;4047;4244</DisableSpecificWarnings>
# 10/04/2012 - Extend to MSVC10 *.vcxproj files - looking good 14/04/2012
# 19/01/2012 - Output the 'temp' DSP written
# 04/11/2011 - Warn about wild card inputs...
# 28/10/2011 - Fix like tempcopydsp.bat to COPY the DSW
# 21/10/2011 - Add an input repsponse file - $in_input_file,...
# 18/10/2011 - Reduce output if NOT verbose!
# 13/07/2011 - If a DSP destination directory given, try to FIX all DSP file source relative to this directory
# 01/12/2010 - Some updates for VC90
# 24/11/2010 - Add in VC10 support - 
# 04/08/2010 - More special fixes for various things...
# 2010/07/30 - Special fix of Simgear.cs to SimGear-cs to suit my system... see $dbg_sl_14
# 2010/05/31 - For FLTK project, include *.fl in 'C' sources
# 2010/05/01 - Fixed -dsp=. (ie a relative input) to absolute using like $sarg = File::Spec->rel2abs($tmp);   # get ABSOLUTE path of output
# 2010/04/23 - Add -ll to load log, and -fix-rel, to FIX the relative source and /I to the dsp output directory
# 2010/04/18 - Remove WARNING: DOES NOT CONTAIN(12) 'Filter'?, and use a default filter
# 2010/03/08 - Remove write tempvcx.xml from scanvc.pl, or only to perl base directory...
# 2010/03/01 - if vcproj contains IgnoreDefaultLibraryNames="MSVCRT", add /nodefaultlib:"MSVCRT" to DSP
#   Add this to the -NEW_OUT- substitution parameter - that is to the # ADD LINK32 line.
#   Can be DIFFERENT per configuration. Altered scanvc.pl to collect this, and fgdsphdrs03.pl to do substitution
# 2010/01/16 - Feeling confident of scans and dsp written - add write actual replacement!
# BUT first, begin to use File::Spec...
# 2009/11/11 - Final tidying up - seems to work fine...
# 2009/10/20 - support MULTIPLE configurations - not compatible with previous versions
# which alwasy had only 2 configurations - Debug and Release.
# 20090912 - add display of CWD, if can not find INPUT file name...
# This uses the services in scanvc.pl, to standardise the processing of a VCPROJ file
# so this is very different to vcproj03.pl, which had its own services to do the scan.
# 2009/09/22 - separarate into multiple 'temp' DSP outputs, using -NEW_PROJECT_NAME-
# but also avoid overwrtting previous out of same name...
# 2010/01/14 - add a DSP COMPARE, if one already exist, and if requested...
# 2009-06-05 also try to attempt to output what the project will create... exe,lib,dll,...
# 05/12/2008 geoff mclane http://geoffair.net/mperl
use strict;
use warnings;
use Cwd;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use File::Spec; # File::Spec->rel2abs($rel); # we are IN the SLN directory, get ABSOLUTE from RELATIVE
unshift(@INC, 'C:/GTools/perl');
require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl'! Check location and \@INC content.\n";
require 'lib_dsphdrs.pl' or die "Unable to load 'lib_dsphdrs.pl'! Check location and \@INC content.\n";
require 'lib_vcscan.pl' or die "Unable to load 'lib_vcscan.pl'! Check location and \@INC content.\n";
require 'lib_params.pl' or die "Unable to load 'lib_params.pl'! Check location and \@INC content.\n";
require 'lib_cmake.pl' or die "Unable to load 'lib_cmake.pl'! Check location and \@INC content.\n";

# log file stuff
our ($LF);
my $perl_base = "C:\\GTools\\perl"; # perl directory
my $PATH_SEP = "\\";
my $temp_dir = $perl_base;
my $pgmname = $0;
if ($pgmname =~ /\w{1}:\\.*/) {
    my @tmpsp = split(/\\/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $perl_base."\\temp.$pgmname.txt";
open_log($outfile);

my $vers = "2012-07-19";    # more work on loading 1 vcproj file
#my $vers = "2012-06-19";    # try to include vcxproj files
#my $vers = "2012-04-10";    # try to include vcxproj files
#my $vers = "2011-11-04";    # minor fix
#my $vers = "2011-10-28";   # some fixes
# $vers = "2011-10-18";    # much reduced output with 'verbosity'
# $vers = "2011-07-13";

# features
my $sort_by_type = 1;
my $sort_by_name = 1;
my $load_log = 0;   # load LOG file at end
my $write_dsp = 0;

my $out_dsp_dir = $perl_base;   # this can be changed by -dsp=<new_dir>
my $g_had_dsp = 0;  # if given an OUTPUT DSP directory
# my $dbg_val = 4+2;    # 1=split defines, 2=no show defines, etc, 4=show sources;
my $dbg_val = 0;    # 1=split defines, 2=no show defines, etc, 4=show sources;
#my $dbg4write = -1; # everything ON
my $dbg4write = 0; # nothing ON
#my $dbg4write = 1; # minimal ON
#my $dbg4write = 2; # show source files ON
my $comp_2_dsps = 0;
my $out_bat_file = $perl_base."\\tempcopydsp.bat";
my $fix_rel_paths = 0;  # if given an output dsp directory, fix the releative source paths
my $debug_dsw_write = 0;   # write DSW debug silently
#my $debug_dsw_write = -1;   # add write DSW debug info
my $verbosity = 0;

sub get_write_dsp_files() { return $write_dsp; }

my @system_libs = qw(kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib 
ole32.lib oleaut32.lib uuid.lib ws2_32.lib);

sub is_system_lib($) {
    my $lib = shift;
    my $lclib = lc($lib);
    my ($tst);
    foreach $tst (@system_libs) {
        return 1 if ($lclib eq $tst);
    }
    return 0;
}

sub VERB1() { return ($verbosity >= 1); }
sub VERB2() { return ($verbosity >= 2); }
sub VERB5() { return ($verbosity >= 5); }
sub VERB9() { return ($verbosity >= 9); }

# program variables
my $in_file = '';
my $sln_path = '';
my $active_project = '';    # active project during chk_relative_paths
my $in_input_file = 0;
my @user_inputs = ();
my $act_config = 0;     # 0=Release 1=Debug
my $commdir = '';

# 20/06/2012 - output a cmake file
########################################
### SHARED RESOURCES, VALUES
### ========================
our $fix_relative_sources = 1;
our %g_user_subs = ();    # supplied by USER INPUT
our %g_user_condits = (); # conditionals supplied by the user
# Auto output does the following -
# For libaries
# Debug:  '/out:"lib\barD.lib"'
# Release:'/out:"lib\barD.lib"'
# for programs
# Debug:  '/out:"bin\fooD.exe"'
# Release:'/out:"bin\foo.exe"'
# This also 'adds' missing 'include' files
#Bit:   1: Use 'Debug\$proj_name', and 'Release\$proj_name' for intermediate and out directories
#Bit:   2: Set output to lib, or bin, and names to fooD.lib/foo.lib or barD.exe/bar.exe
#Bit:   4: Set program dependence per library output directories
#Bit:   8: Add 'msvc' to input file directory, if no target directory given
#Bit:  16: Add program library dependencies, if any, to DSW file output.
#Bit:  32: Add all necessary headers to the DSP file. That is scan the sources for #include "foo.h", etc.
#Bit:  64: Write a blank header group even there are no header files for that component.
#Bit: 128: Add defined item of HAVE_CONFIG_H to all DSP files.
#Bit: 256: Exclude projects in SUBDIRS protected by a DEFINITION macro, else include ALL.
#Bit: 512: Unconditionally add ANY libraries build, and NOT excluded to the last application
#Bit:1024: If NO users conditional, do sustitution, if at all possible, regardless of TRUE or FALSE
#Bit:2048: Add User -L dependent libraries to each application
#Bit: These can be given as an integer, or the form 2+8, etc. Note using -1 sets ALL bits on.
#Bit: Bit 32 really slows down the DSP creation, since it involves scanning every line of the sources.
my $auto_max_bit = 512;
our $auto_on_flag = -1; #Bit: ALL ON by default = ${$rparams}{'CURR_AUTO_ON_FLAG'}
sub get_curr_auto_flag() { return $auto_on_flag; }
#my ($g_in_name, $g_in_dir);
#my ($root_file, $root_folder);
#sub get_root_dir() { return $root_folder; }
our $exit_value = 0;
# But SOME Makefile.am will use specific 'paths' so the above can FAIL to find
# a file, so the following two 'try harder' options, will do a full 'root'
# directory SCAN, and search for the file of that name in the scanned files
our $try_harder = 0;
our $try_much_harder = 0;
# ==============================================================================
our $process_subdir = 0;
our $warn_on_plus = 0;
# ==============================================================================
# NOTE: Usually a Makefile.am contains SOURCE file names 'relative' to itself,
# which is usually without any path. This options ADDS the path to the
# Makefile.am, and then substracts the 'root' path, to get a SOURCE file
# relative to the 'root' configure.ac, which is what is needed if the DSP
# is to be placed in a $target_dir, and we want the file relative to that
our $add_rel_sources = 1;
our $target_dir = '';
# ==============================================================================
our $ignore_EXTRA_DIST = 0;
our $added_in_init = '';
our $supp_make_in = 0; # Support Makefile.in scanning
our $project_name = ''; # a name to override any ac scanned name of the project

###my $dsp_files_skipped = 0;

### =============================
# offsets into REF_LIB_LIST array
our $RLO_MSG = 0;
our $RLO_PRJ = 1;
our $RLO_VAL = 2;
our $RLO_NAM = 3;
our $RLO_EXC = 4;
### =============================

my $out_cmake_dir = '';
my $write_cmake = 0;
my ($rparams);  # the one and only, init per first file input
my $got_par = 0;
#    my $rex = ${$rparams}{'AM_EXCLUDED_DIRS'}; # get stored EXCLUDED directory HASH (if any!)
#    my $proj_root = ${$rparams}{'ROOT_FOLDER'};
#    my $proj_title = ${$rparams}{'PROJECT_NAME_MASTER'};
#    my $rprojsh = ${$rparams}{'REF_PROJECTS_HASH'};
#    my $rlib_lists = ${$rparams}{'REF_LIB_LISTS'};  # make list of LIBRARIES written
# optional - my $rxj = ${$rparams}{'REF_JOINED_EXCLUDED'};
my $inst_hdr_path = 'include';
my $inst_lib_path = 'lib';
my $inst_bin_path = 'bin';
sub get_inst_hdr_path() { return $inst_hdr_path; }
sub get_inst_lib_path() { return $inst_lib_path; }
sub get_inst_hdr_bin() { return $inst_bin_path; }
sub get_write_cmake_files() { return $write_cmake; }

my %by_proj_includes = ();
my %by_proj_defines = ();
my %by_proj_defused = ();

my $proj_incs = ''; # like '/I "."' for -NEW_INCS- GLOBAL
my $proj_defs = ''; # like '/D "_CRT_SECURE_NO_WARNINGS"';

sub get_project_incs($) {
    my $proj = shift;
    my $pi = '';
    $pi = $by_proj_includes{$proj} if (defined $by_proj_includes{$proj});
    return $pi;
}

sub get_project_defs($) {
    my $proj = shift;
    my $pi = '';
    $pi = $by_proj_defines{$proj} if (defined $by_proj_defines{$proj});
    $by_proj_defused{$proj} = 1;
    return $pi;
}


# FIX20110323 - changed from 'get_user_defs:' to 'get_user_incs:'
# should ALSO allow DEFINES (-D) to also be in a BY PROJECT basis
# my %by_proj_includes = ();
sub get_user_incs($$) {
    my ($not_used,$proj) = @_;
    my $pi = get_project_incs($proj);
    $pi .= ' ' if (length($pi) && length($proj_incs));
    $pi .= $proj_incs;
    prt("[v9] get_user_incs: proj=$proj, return=[$pi]\n") if (VERB9());
    return $pi;
}

sub get_user_defs($$) {
    my ($not_used,$proj) = @_;
    my $pd = get_project_defs($proj);
    $pd .= ' ' if (length($pd) && length($proj_defs));
    $pd .= $proj_defs;
    prt("[v9] get_user_defs: proj=$proj, return=[$pd]\n") if (VERB9());
    return $pd;
}

# ### DEBUG ##
my $dbg_01 = 0; # show commands
my $dbg_02 = 0; # show EACH tag 
my $dbg_03 = 0; # tag stack debug - show open and close
my $dbg_04 = 0; # if $dbg_02, also show complete 'from' item
my $dbg_05 = 0; # show each configuration PUSHED
my $dbg_06 = 0; # show additional debug for get_rt_value/set_curr_config
my $dbg_07 = 0; # show ' Property: '...
my $dbg_08 = 0; # show ' ItemDef: '...
my $dbg_09 = 0; # show full tag stack if $dbg_02
my $dbg_10 = 0; # setting a unsetting of $incommand

if (-d "C:\\MDOS") {
    $out_bat_file = "C:\\MDOS\\tempcopydsp.bat";
}

my $adj_inter = 0; # Adjust output and inter directories to "Release\\<proj>" and "Debug\\<proj>"
my $adj_out = 0; # Adjust output to "bin\\<proj>.exe" and "bin\\<proj>D.exe" for EXE and DLL
                 # projects, and "lib\\<proj>.lib" and "lib\\<proj>D.lib" for libraries.
my $adj_rt = '';  # Adjust runtime, D = /MD and /MDd, T = /MT and /MTd, accordingly.
my $del_ndl_all = 0;
my $del_dll_all = 0; # remove any DLL build if both DLL and static, or change to static if only DLL
my $del_spl_bld = 0; # remove any Special Tool Build blocks from DSP

my $debug_on = 1;   # 0 for release, but on to load default input (when using the editor say)
my $def_in_file = 'C:\Projects\notepad-plus\PowerEditor\visual.net\notepadPlus.vcproj';
my $def_out_dsp_dir = 'C:\Projects\notepad-plus';
###my $def_in_file = 'C:\GTools\ConApps\test_simp\build\test_simp.sln';
###my $def_out_dsp_dir = 'C:\GTools\ConApps\test_simp\build';

#my $def_in_file = 'C:\Projects\lpng159\build\libpng.sln';
#my $def_in_file = 'C:\Projects\lpng159\build\INSTALL.vcxproj';
#my $def_in_file = 'C:\Projects\lpng159\build\ALL_BUILD.vcxproj';
#my $def_out_dsp_dir = 'C:\Projects\lpng159\build';
#my $def_in_file = 'C:\Projects\lpng159\temp-static\png15_static.vcxproj';
#my $def_out_dsp_dir = 'C:\Projects\lpng159\temp-static';
#my $def_in_file = 'C:\Projects\lpng159\temp-shared\png15.vcxproj';
#my $def_out_dsp_dir = 'C:\Projects\lpng159\temp-shared';
#my $def_in_file = 'C:\Projects\zlib-1.2.6\temp\zlib.vcxproj';
#my $def_out_dsp_dir = 'C:\Projects\zlib-1.2.6\temp';
#my $def_in_file = 'C:\FG\10\flightgear\build\src\FDM\YASim\yasim-proptest.vcxproj';
#my $def_out_dsp_dir = 'C:\FG\10\flightgear\build';
#my $def_in_file = 'C:\Projects\curl-7.20.1\lib\libcurl.vcproj';
#my $def_out_dsp_dir = 'C:\Projects\curl-7.20.1\packages\Win32\msvc';

my @warnings = ();

#-- get current directory
my $pwd = cwd();

my @dsp_file_list = (); # simple list
my @project_list = ();  # [0]=name [1]=file
my $sln_root_dir = '';  # if given a SOLUTION FILE

# debug 
my $dbg_sl_01 = 0;
my $dbg_sl_02 = 0;
my $dbg_sl_03 = 0;
my $dbg_sl_04 = 0;   # show_hash_results3($rh) if ($dbg_sl_04);
my $dbg_sl_05 = 0;   # prt( "[dbg_s105] $pgmname: Scanning [$in]...\n" ) if ($dbg_sl_05);
my $dbg_sl_06 = 0;  # show parse_arg in detail
my $dbg_sl_07 = 0; # prt("[dbg_sl_07] Check relative vcd=[$vcd], out=[$outd]\n") if ($dbg_sl_07);
my $dbg_sl_08 = 0; # chk_relative_paths: show each config item
my $dbg_sl_09 = 0; # chk_relative_paths: show each source item, and any CHANGE
my $dbg_sl_10 = 0; # chk_relative_paths: show each other config item, and any CHANGE
my $dbg_sl_11 = 0; # chk_relative_paths: show any POST changes -NEW_POST-
my $dbg_sl_12 = 0; # debug sub get_new_post_string($$$$$) { # $v2,\$ok,$rp,$vcd,$outd);
my $dbg_sl_13 = 0;
my $dbg_sl_14 = 0;
my $dbg_sl_15 = 0; # prt( "Stored \$sln_projpath{$projname} = [0:$projfile,1:$projff,2:$relpath,3:$dspfile,4:$fdspfil]\n");
my $dbg_sl_16 = 0; # show each project, and its ID, as found

sub get_sl_debug_stg() {
    my $stg = '';
    if ($dbg_sl_01) { $stg .= "01 "; }; if ($dbg_sl_02) { $stg .= "02 "; };
    if ($dbg_sl_03) { $stg .= "03 "; }; if ($dbg_sl_04) { $stg .= "04 "; };
    if ($dbg_sl_05) { $stg .= "05 "; }; if ($dbg_sl_06) { $stg .= "06 "; };
    if ($dbg_sl_07) { $stg .= "07 "; }; if ($dbg_sl_08) { $stg .= "08 "; };
    if ($dbg_sl_09) { $stg .= "09 "; }; if ($dbg_sl_10) { $stg .= "10 "; };  if ($dbg_sl_11) { $stg .= "11 "; };
    if ($dbg_sl_12) { $stg .= "12 "; }; if ($dbg_sl_13) { $stg .= "13 "; };
    if ($dbg_sl_14) { $stg .= "14 "; };
        
    $stg .= "dbg4Write=$dbg4write " if ($dbg4write);
    $stg .= "debug_dsw_write=$debug_dsw_write " if ($debug_dsw_write);

    return $stg;
}

sub set_sl_debug_val($) {
    my ($v) = shift;
    $dbg_sl_01 = $v; $dbg_sl_02 = $v; $dbg_sl_03 = $v; $dbg_sl_04 = $v; $dbg_sl_05 = $v;
    $dbg_sl_06 = $v; $dbg_sl_07 = $v; $dbg_sl_08 = $v; $dbg_sl_09 = $v; $dbg_sl_10 = $v; $dbg_sl_11 = $v;
    $dbg_sl_12 = $v; $dbg_sl_13 = $v; $dbg_sl_14 = $v;
}

sub set_sl_debug_on() { set_sl_debug_val(1); $load_log = 1; }
sub set_sl_debug_off() { set_sl_debug_val(0); }

my $curr_app_type = '';
# APP_TYPE
# $app_console_stg  = 'Console Application'  = get_dsp_head_console
# $app_windows_stg  = 'Application'          = get_dsp_head_app
# $app_dynalib_stg  = 'Dynamic-Link Library' = get_dsp_head_dynalib
# $app_statlib_stg  = 'Static Library'       = get_dsp_head_slib

sub prtw($) {
    my ($tx) = shift;
    $tx =~ s/\n$//;
    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") if (VERB5());
    }
}

sub pgm_exit($$) {
    my ($val,$msg) = @_;
    show_warnings();
    #my $dbs = fgs_get_dbg_stg();
    my $dbs = svc_get_dbg_stg();
    if (length($dbs)) {
        prt("WARNING: Debug is ON for [$dbs], in fgscanvc03.pl\n" );
    }
    $dbs = get_sl_debug_stg();
    if (length($dbs)) {
        prt("WARNING: Debug is ON for [$dbs], in $pgmname\n" );
    } else {
        prt("Appears no DEBUG item remain on...\n") if (VERB5());
    }
    if (length($msg)) {
        $msg .= "\n" if ( !($msg =~ /\n$/) );
        prt($msg);
    }
    close_log($outfile,$load_log);
    # unlink($outfile);   # delete output file
    exit($val);
}

sub is_c_source_ext($) {
    my ($fil) = shift;
    my ($nm, $dir, $ext) = fileparse( $fil, qr/\.[^.]*/ );
    my $lce = lc($ext);
    return 1 if (($lce eq '.c') || ($lce eq '.cxx') || ($lce eq '.cpp') || ($lce eq '.cc'));
    return 1 if ($lce eq '.fl');    # 2010-05-31 - added for FLTK projects
    return 0;
}

sub is_sln_ext($) {
    my ($fil) = shift;
    my ($nm, $dir, $ext) = fileparse( $fil, qr/\.[^.]*/ );
    my $lce = lc($ext);
    if ($lce eq '.sln') {
        return 1;
    }
    return 0;
}

sub is_vcproj_ext($) {
    my ($fil) = shift;
    my ($nm, $dir, $ext) = fileparse( $fil, qr/\.[^.]*/ );
    my $lce = lc($ext);
    return 1 if ($lce eq '.vcproj');
    return 0;
}

sub is_vcxproj_ext($) {
    my $fil = shift;
    my ($nm, $dir, $ext) = fileparse( $fil, qr/\.[^.]*/ );
    my $lce = lc($ext);
    return 1 if ($lce eq '.vcxproj');   # 24/11/2010 VC10 support
    return 0;
}

# ===================================================================
#  -NEW_INCS- = [/I "." /I "..\include"], and
#  -NEW_DEFS- = [/D "NDEBUG"... ]
# Maybe could -
# (a) ensure a certain /I "somepath", exists, adding it if NOT
# (b) adjust certain /I "..\path.x64" to a different /I "..\new\path"
# (c) delete duplicates
# (d) etc
# ===================================================================
# reduce the noise...
my $prev_inc_warn = '';
my $prev_def_warn = '';
my $prev_inc_added = '';
my $prev_def_added = '';
my $prev_sdk_added = '';
my $prev_alut_added = '';
my $prev_item_dump1 = '';
my $prev_item_dump2 = '';
sub get_new_inc_hash($$$$$$) {
    my ($v,$rok,$rp,$vcd,$outd,$ky) = @_;
    my $len = length($v);
    my %hash = ();
    my %dupes = ();
    my ($i,$ch,$nc,$tag,$val,$pc,$ra,$nval,$i2,$qt);
    my ($fp,$np,$had_al,$inc_tag,$had_crt,$def_tag,$had_alu,$had_dot,$had_cfg);
    # process the line, char by char...
    $had_al = 0;
    $had_alu = 0;
    $inc_tag = '';
    $had_crt = 0;
    $def_tag = '';
    $had_dot = 0;
    $had_cfg = 0;
    $ch = '';
    for ($i = 0; $i < $len; $i++) {
        $i2 = $i + 1;
        $pc = $ch;  # keep PREVIOUS char
        $ch = substr($v,$i,1);
        $nc = ($i2 < $len) ? substr($v,$i2,1) : '';
        if ( (($ch eq '/')||($ch eq '-')) && (length($nc)) ) {
            $tag = $ch; # begin a SWITCH item
            $i++;   # bump to NEXT char
            for (; $i < $len; $i++) {
                $pc = $ch;  # keep PREVIOUS char
                $ch = substr($v,$i,1);
                $nc = ($i2 < $len) ? substr($v,$i2,1) : '';
                last if ($ch eq '"');   # found first QUOTE
                last if ($ch =~ /\s/);  # or found a SPACE
                $tag .= $ch;
            }
            if ($ch =~ /\s/) {  # if a SPACE, get to NEXT sig char
                $i++;   
                for (; $i < $len; $i++) {
                    $pc = $ch;  # keep PREVIOUS char
                    $ch = substr($v,$i,1);
                    last if ($ch eq '"');
                    last if ( !($ch =~ /\s/) );
                }
            }
            $qt = '';   # assume NO 'quote'
            $val = $ch; # start of a VALUE
            $i2 = $i + 1;
            if ($i2 < $len) {
                if ( $ch eq '"' ) {
                    $i++;   # ok, do have QUOTED text
                    $qt = $ch;  # keep 'quote'
                    $pc = $ch;  # keep PREVIOUS char
                    $ch = substr($v,$i,1);  # and get NEXT char
                    $val .= $ch;    # add to collected value
                }
            } else {
                ${$rok} = 0;
                prtw("WARNING:1:$active_project: Ran out of char! With [$v] FAILED!\n");
                return \%hash;
            }
            $i++;
            if (length($qt)) {
                # process until next 'quote' found, 2010-08-04 but NOT escaped with '\'
                for (; $i < $len; $i++) {
                    $pc = $ch;  # keep PREVIOUS char
                    $ch = substr($v,$i,1);
                    $val .= $ch;
                    last if ( ($ch eq $qt) && ($pc ne "\\") );
                }
            } else {
                # or process until a space found
                for (; $i < $len; $i++) {
                    $pc = $ch;  # keep PREVIOUS char
                    $ch = substr($v,$i,1);
                    last if ($ch =~ /\s/);
                    $val .= $ch;
                }
            }
            # we have (/|-)$tag ["]$val["]
            # ============================
            $nval = strip_quotes($val);
            if ($nval eq '.') {
                # this stays as is
                $had_dot = 1;
            } elsif ($tag =~ /^(-|\/)I$/) {
                # its a /I "path" type - need new relative item?
                prtw("WARNING:$active_project: Multiple I tags. Got [$inc_tag], NOW [$tag]! CHECK THIS\n") if (length($inc_tag) && ($tag ne $inc_tag));
                $inc_tag = $tag;
                $fp = $vcd;
                # ====================================================================
                $had_al = 1 if ($nval =~ /OpenAL/i);   # if got an OpenAL (AL/al.h) include
                $had_alu = 1 if ($nval =~ /alut/);
                $nval =~ s/SimGear\.cs/simgear-cs/i;   # SPECIAL FIX Fred vs Geoff
                $nval =~ s/3rdParty\.x64/3rdParty/i;   # SPECIAL FIX Fred vs Geoff
                $nval =~ s/install(\\|\/)msvc90(\\|\/)OpenSceneGraph/OpenSceneGraph/i;   # SPECIAL FIX Fred vs Geoff
                $nval =~ s/install(\\|\/)msvc90-64(\\|\/)OpenSceneGraph/OpenSceneGraph/i;   # SPECIAL FIX Fred vs Geoff
                $nval =~ s/install(\\|\/)msvc71(\\|\/)OpenSceneGraph/OpenSceneGraph/i;   # SPECIAL FIX Fred vs Geoff
                # ====================================================================
                $fp .= "\\" if ( !( ($fp =~ /(\\|\/)$/) || ($nval =~ /^(\\|\/)/) ) );
                $fp .= $nval;   # get the FULL (relative) path
                $fp = fix_rel_path3($fp,'get_new_inc_hash');
                $np = get_rel_dos_path($fp,$outd);
                $np =~ s/(\\|\/)$//;
                $val = add_quotes($np);
            } elsif ($tag =~ /^(-|\/)D$/) {
                prtw("WARNING:$active_project: Multiple D tags. Got [$def_tag], NOW [$tag]! CHECK THIS\n") if (length($def_tag) && ($tag ne $def_tag));
                $def_tag = $tag;
                $had_crt = 1 if ($nval =~ /_CRT_SECURE_NO_WARNINGS/);
                $had_cfg = 1 if ($nval eq 'HAVE_CONFIG_H');
                if ($nval =~ /^DEFAULT_USGS_MAPFILE/) {
                    prt("$active_project: SPECIAL FIX: Dumping tag [$tag $val]\n") if ($prev_item_dump1 ne $active_project);
                    $prev_item_dump1 = $active_project;
                    ${$rok}++;
                    next;
                }
                if ($nval =~ /^DEFAULT_PRIORITIES_FILE/) {
                    prt("$active_project: SPECIAL FIX: Dumping tag [$tag $val]\n") if ($prev_item_dump2 ne $active_project);
                    $prev_item_dump2 = $active_project;
                    ${$rok}++;
                    next;
                }
            }
            if (defined $dupes{$val}) {
                prtw("WARNING:$active_project:SPECIAL FIX: Avoided duplicate [$val]\n");
            } else {
                $hash{$tag} = [] if (!defined $hash{$tag});
                $ra = $hash{$tag};
                push(@{$ra},$val);  # store item in HASH
                $dupes{$val} = 1;
            }
            ${$rok}++;
        } elsif (($ch eq '/')||($ch eq '-')) {
            prtw("WARNING:2:$active_project: Ran out of char! With [$v] FAILED!\n");
            ${$rok} = 0;
            return \%hash;
        } else {
            if ($ch =~ /\s/) {
                # forget spaces - just continue
            } else {
                prtw("WARNING:3:$active_project: Not A SWITCH! Got [$ch]? With [$v] FAILED!\n");
                ${$rok} = 0;
                return \%hash;
            }
       }
    } # char by char for the whole string

    # =========================
    # Other SPECIAL FIX items
    # =========================
    # -NEW_INCS-
    if ( (length($inc_tag) > 0) && (defined $hash{$inc_tag}) ) {
        $ra = $hash{$inc_tag};
        if ($active_project =~ /simgear/i) {
            prt("SPECIAL FIX: for [$active_project]\n");
            if ( !$had_al ) {
                $val = '"C:\Program Files\OpenAL 1.1 SDK\include"';
                push(@{$ra},$val);  # store item in HASH
                prt("SPECIAL FIX: Added OpenAL SDK include [$val]\n") if ($active_project ne $prev_sdk_added);
                $prev_sdk_added = $active_project;
                ${$rok}++;
            }
            if ( !$had_alu) {
                $val = '"..\..\..\alut\include"';
                push(@{$ra},$val);  # store item in HASH
                prt("$active_project:SPECIAL FIX: Added alut include [$val]\n") if ($active_project ne $prev_alut_added);
                $prev_alut_added = $active_project;
                ${$rok}++;
            }
        }
        if (!$had_dot) {
            $val = '"."';
            push(@{$ra},$val);  # store item in HASH
            prt("$active_project:SPECIAL FIX: Added [/I $val]\n") if ($active_project ne $prev_inc_added);
            $prev_inc_added = $active_project;
            ${$rok}++;
        }
    } elsif ($ky eq '-NEW_INCS-') {
        prtw("WARNING:$active_project: Potential SPECIAL FIXES missed for $ky! No /I tag in [$v]???\n") if ($active_project ne $prev_inc_warn);
        $prev_inc_warn = $active_project;
    }

    # -NEW_DEFS-
    if ( (length($def_tag) > 0) && (defined $hash{$def_tag}) ) {
        $ra = $hash{$def_tag};
        if ( ! $had_crt ) { 
            $val = '"_CRT_SECURE_NO_WARNINGS"';
            push(@{$ra},$val);  # store item in HASH
            prt("$active_project:SPECIAL FIX: Added CRT [$val]\n");
            ${$rok}++;
        }
        if ( ! $had_cfg ) {
            $val = '"HAVE_CONFIG_H"';
            push(@{$ra},$val);  # store item in HASH
            prt("$active_project:SPECIAL FIX: Added CONFIG [$val]\n") if ($prev_def_added ne $active_project);
            $prev_def_added = $active_project;
            ${$rok}++;
        }
    } elsif ($ky eq '-NEW_DEFS-') {
        prtw("WARNING:$active_project: Potential SPECIAL FIXES missed for $ky! No /D tag in [$v]???\n") if ($active_project ne $prev_def_warn);
        $prev_def_warn = $active_project;
    }

    return \%hash;  # return hash{$tag} = [$val,[$val]]
}

# could have 
#   -NEW_POST- = [# Begin Special Build Tool
#SOURCE="$(InputPath)"
#PostBuild_Desc=
#PostBuild_Cmds=if not exist ..\..\..\..\lib md ..\..\..\..\lib	copy "$(TargetDir)GLUT32.LIB" ..\..\..\..\lib	copy "$(TargetDir)GLUT32.DLL" ..\..\..\..\lib	if exist ..\..\..\..\progs\demos copy "$(TargetDir)GLUT32.DLL" ..\..\..\..\progs\demos
## End Special Build Tool
# that needs ADJUSTING - wow
sub get_new_post_string($$$$$)  {   # $v2,\$ok,$rp,$vcd,$outd);
    my ($v,$rok,$rp,$vcd,$outd) = @_;
    my $len = length($v);
    my $nv = $v;
    my $chg = 0;
    my (@arr,$k,$l1,$itm,$chg1,$chg2,$i,$j,$c,$c2,@a2,@a3,$cmd,$l2,$l3,$np,$rd,$frp);
    if ($len) {
        @arr = split("\n",$v);
        $l1 = scalar @arr;
        for ($k = 0; $k < $l1; $k++) {
            $itm = $arr[$k];
            if ($itm =~ /^PostBuild_Cmds=(.+)$/) {
                $cmd = $1;
                @a2 = split("\t",$cmd);
                $l2 = scalar @a2;
                $chg2 = 0;
                for ($i = 0; $i < $l2; $i++) {
                    $c = $a2[$i];
                    if ($c =~ /\.\./) {
                        prt("[dbg_sl_12] Needs adjustment [$c]\n") if ($dbg_sl_12);
                        @a3 = split(/\s/,$c);
                        $l3 = scalar @a3;
                        $chg1 = 0;
                        for ($j = 0; $j < $l3; $j++) {
                            $c2 = $a3[$j];
                            if ($c2 =~ /\.\./) {
                                $rd = $vcd.$c2;
                                $frp = fix_rel_path3($rd,'get_new_post_string');
                                $np = get_rel_dos_path($frp,$outd);
                                $np =~ s/(\\|\/)$//;
                                prt("REL [$rd]\nnew [$frp]\n") if ($dbg_sl_12);
                                prt(" This one [$c2] to [$np]?\n") if ($dbg_sl_12);
                                if ($np ne $c2) {
                                    $a3[$j] = $np;
                                    $chg1++;
                                }
                            }
                        }
                        if ($chg1) {
                            $np = '';
                            foreach $c2 (@a3) {
                                $np .= ' ' if (length($np));
                                $np .= $c2;
                            }
                            $a2[$i] = $np;
                            $chg2++;
                        }
                    }
                }
                if ($chg2) {
                    $rd = '';
                    foreach $c (@a2) {
                        $rd .= "\t" if (length($rd));
                        $rd .= $c;
                    }
                    $arr[$k] = $rd;
                    $chg++;
                    prt("old [$cmd]\nnew [$rd]\n") if ($dbg_sl_12);
                }
            }
        }
        if ($chg) {
            $nv = '';
            foreach $itm (@arr) {
                $nv .= "\n" if (length($nv));
                $nv .= $itm;
            }
            if ($v ne $nv) {
                prt("old [$v]\nnew [$nv]\n") if ($dbg_sl_12);
                ${$rok} = 1;
            }
        }

        prt("rel=[$rp], vcd=[$vcd], od=[$outd]\n") if ($dbg_sl_12);
        #pgm_exit(1,"TEMP EXIT");
    }
    return $nv;
}

# check input libraries to link with
# $v = current value
# $rok = ref to set if changed
# $rp = get_rel_dos_path($vcd,$outd); # changing the PATH
# $vcd = directory of the vcproj file
# $outd = output directory
# can add, substrct, change list
# eg
# [ul_d.lib sg_d.lib zlibd.lib gdal_id.lib /libpath:"..\..\..\..\plib" /libpath:"..\..\..\..\3rdParty\lib"]
# needs to be changed to
# [ul_d.lib sg_d.lib zlibd.lib gdal_id.lib /libpath:"..\..\..\plib" /libpath:"..\..\..\3rdParty\lib"]

sub get_new_libs_string($$$$$)  {   # $v2,\$ok,$rp,$vcd,$outd);
    my ($v,$rok,$rp,$vcd,$outd) = @_;
    my $len = length($v);
    my $nv = $v;
    my $chg = 0;
    #prt("get_new_libs_string: from [$v]\n");
    my @arr = space_split($v);  # split on space, but honor inside inverted commas
    my ($itm,$dir,$fp,$tmp,$rdd,$nitm);
    my @narr = ();
    foreach $itm (@arr) {
        if ($itm =~ /^\/libpath:/) {
            $dir = strip_quotes(substr($itm,9));
            $fp = $vcd;
            $fp .= "\\" if ( !($fp =~ /(\/|\\)$/) );
            $fp .= $dir;
            $tmp = fix_rel_path3($fp,'get_new_libs_string');
            # my $out_dsp_dir = $perl_base;   # this can be changed by -dsp=<new_dir>
            # my $g_had_dsp = 0;  # if given an OUTPUT DSP directory
            $rdd = get_rel_dos_path($tmp,$out_dsp_dir); # changing the PATH
            $rdd =~ s/\\$//;
            $nitm = '/libpath:'.add_quotes($rdd);
            push(@narr,$nitm);
            #prt("Changed\nfrom [$itm]\nto   [$nitm]\n");
            ###pgm_exit(1,"CHECK ME");
            $chg++;
        } else {
            push(@narr,$itm);
        }
    }
    if ($chg) {
        $nv = '';
        foreach $itm (@narr) {
            $nv .= ' ' if (length($nv));
            $nv .= $itm;
        }
        ${$rok} = $chg;
    }
    return $nv;
}

sub Get_Default_Group($) {
    my ($src) = @_;
    my ($grp,$flt);
    if (is_c_source_extended($src)) {
        $grp = get_def_src_grp();
        $flt = get_def_src_filt();
    } elsif (is_h_source_extended($src)) {
        $grp = get_def_hdr_grp();
        $flt = get_def_hdr_filt();
    } elsif (is_resource_file($src)) {
        $grp = get_def_rcs_grp();
        $flt = get_def_rcs_filt();
    } else {
        $grp = "Other Files";
        $flt = '';
    }
    return $grp,$flt;
}

# ======================================================================================
# ok, need to change sources from perhaps '.\src.cxx' to '..\..\lib\src.cxx' - a big job
# and LOTS of other things...
# ======================================================================================
my $prev_src_fix = '';
sub chk_relative_paths($$$) {
    my ($rh,$outd,$vcd) = @_;
    my ($key,$val,$acnt,$i,$src,$grp,$flt,$rp);
    my ($i2,$rsb,@karr,$scnt,$msg,$ky,$v2,$rih,$ok);
    my ($k3,$v3,$v,$nv,$tmp,$tmp2);
    $rp = get_rel_dos_path($vcd,$outd); # changing the PATH
    ##my $rp2 = get_rel_dos_path($outd,$vcd); # how to get from where we were to now out directory
    # this would be used to move say 'windows\VC8\mesa\mesa.dsp' to windows\MSVC
    prt("[dbg_sl_07] Check relative vcd=[$vcd], out=[$outd]\n") if ($dbg_sl_07);
    prt("chk_relative_paths: [$rp],\n from vcd=[$vcd],\n target  =[$outd]\n");

    $key = 'PROJECT_NAME';
    if (! defined ${$rh}{$key}) {
        pgm_exit(1,"INTERNAL ERROR: HASH WITHOUT PROJECT_NAME! Can ONLY exit!");
    }
    $active_project = ${$rh}{$key};
    my @not_found = ();
    foreach $key (keys %{$rh}) {
        $val = ${$rh}{$key};
        if ( $key =~ /^CURR_/ ) {
            # ignore these CURRENT state items
        } else {
            if ($key eq 'PROJECT_SRCS') {
                $acnt = scalar @{$val};
                prt("$key - $acnt sources to fix path...\n");  # 'PROJECT_SRCS'
                for ($i = 0; $i < $acnt; $i++) {
                    $src = ${$val}[$i][0];
                    $grp = ${$val}[$i][1];
                    $flt = ${$val}[$i][2];
                    # SPECIAL FIX - Fred vs Geoff
                    if ($active_project =~ /simgear/i) {
                        ($grp,$flt) = Get_Default_Group($src);
                        ${$val}[$i][1] = $grp;
                        ${$val}[$i][2] = $flt;
                        prt("SPECIAL FIX for [$active_project] [$src] [$grp] [$flt]\n") if ($prev_src_fix ne $active_project);
                        $prev_src_fix = $active_project;
                    }
                    $src =~ s/^\.(\\|\/)//;
                    #$nv = $rp.$src;
                    $tmp = $vcd.$src;
                    $tmp2 = fix_rel_path3($tmp,'chk_relative_paths');
                    if (-f $tmp2) {
                        $ok = 'ok';
                    } else {
                        $ok = 'NF';
                        push(@not_found,$tmp2);
                    }
                    my ($fnm,$fdir) = fileparse($tmp2);
                    $nv = get_rel_dos_path($fdir,$outd);
                    # 2010/05/06 - why ??? $nv =~ s/(\\|\/)$//;
                    $nv .= "\\" if (length($nv) && !($nv =~ /(\\|\/)$/));
                    $nv .= $fnm;    # add back the file name
                    if ($nv eq $src) {
                        prt("Source [$src] not changed. [$grp] [$flt]\n") if ($dbg_sl_09 || VERB1());
                    } else {
                        prt("Was [$src] GOT CHANGE...\n") if ($dbg_sl_09 || VERB5());;
                        prt("int [$tmp2]\n") if ($dbg_sl_09 || VERB9());;
                        prt("New [$nv] [$grp] [$flt] $ok\n") if ($dbg_sl_09 || VERB1());
                        ${$val}[$i][0] = $nv;
                    }
                }
            } elsif ($key eq 'PROJECT_CFGS') {
                # my $rcfgs = ${$rh}{'PROJECT_CFGS'};
                #                   0       1      2      3
                # push(@{$rcfgs}, [ $pname, $var1, $conf, $dsp_sub_sub ]);
                #  -NEW_INCS- = [/I "." /I "..\include"]
                $acnt = scalar @{$val};
                prt("$key - $acnt configs...\n");
                for ($i = 0; $i < $acnt; $i++) {
                    $i2 = $i + 1;
                    $src = ${$val}[$i][0];
                    $grp = ${$val}[$i][1];
                    $flt = ${$val}[$i][2];
                    $rsb = ${$val}[$i][3];
                    @karr = keys(%{$rsb});
                    $scnt = scalar @karr;
                    $msg = sprintf("%3d:",$i2);
                    # prt( "$msg: [$src] [$grp] [$flt] = $scnt\n" );
                    prt( "$msg: [$src] [$flt] = $scnt config items\n" );
                    foreach $ky (@karr) {
                        $v2 = ${$rsb}{$ky};
                        ###prt("Doing [$ky], value [$v2]\n");
                        $nv = '';
                        if (($ky eq '-NEW_INCS-')||($ky eq '-NEW_DEFS-')) {
                            # also need to fix things like '/I "..\include"', but NOT '/I "."'
                            $ok = 0;
                            $rih = get_new_inc_hash($v2,\$ok,$rp,$vcd,$outd,$ky);
                            if ($ok) {
                                prt(" = $ky = [") if ($dbg_sl_10);
                                $nv = '';
                                foreach $k3 (keys %{$rih}) {
                                    $v3 = ${$rih}{$k3};
                                    foreach $v (@{$v3}) {
                                        $nv .= ' ' if (length($nv));
                                        $nv .= "$k3 $v";
                                    }
                                }
                                if ($nv eq $v2) {
                                    prt(" [$nv] NO CHANGE\n") if ($dbg_sl_10);
                                } else {
                                    prt("\nnew [$nv], \nwas [$v2]\n") if ($dbg_sl_10);
                                    ${$rsb}{$ky} = $nv;
                                    #${$val}[$i][3] = $rsb;
                                }
                            } else {
                                prt( "  $ky = [$v2] FAILED REF\n" );
                            }
                        } elsif ($ky eq '-NEW_POST-') {
                            # could have 
                            #   -NEW_POST- = [# Begin Special Build Tool
                            #SOURCE="$(InputPath)"
                            #PostBuild_Desc=
                            #PostBuild_Cmds=if not exist ..\..\..\..\lib md ..\..\..\..\lib	copy "$(TargetDir)GLUT32.LIB" ..\..\..\..\lib	copy "$(TargetDir)GLUT32.DLL" ..\..\..\..\lib	if exist ..\..\..\..\progs\demos copy "$(TargetDir)GLUT32.DLL" ..\..\..\..\progs\demos
                            ## End Special Build Tool
                            # that needs ADJUSTING - wow
                            $ok = 0;
                            $nv = get_new_post_string($v2,\$ok,$rp,$vcd,$outd);
                            if ($ok) {
                                prt( "  $ky CHANGED ok\nwas [$v2]\nnew [$nv]\n") if ($dbg_sl_11);
                                ${$rsb}{$ky} = $nv;
                            } else {
                                prt( "  $ky = [$v2] NO CHANGES\n" ) if ($dbg_sl_11);
                            }
                        } elsif ($ky eq '-NEW_OUTD-') {
                            $nv = strip_quotes($v2);
                            $nv =~ s/^\.\.\\//;
                            $nv .= "\\" if (!($nv =~ /(\\|\/)$/));
                            $nv .= $active_project;
                            $nv = add_quotes($nv);
                            prt( "  $ky CHANGED ok\nwas [$v2]\nnew [$nv]\n") if ($dbg_sl_11);
                            ${$rsb}{$ky} = $nv;
                        } elsif ($ky eq '-NEW_INTER-') {
                            $nv = strip_quotes($v2);
                            $nv =~ s/^\.\.\\//;
                            $nv .= "\\" if (!($nv =~ /(\\|\/)$/));
                            $nv .= $active_project;
                            $nv = add_quotes($nv);
                            prt( "  $ky CHANGED ok\nwas [$v2]\nnew [$nv]\n") if ($dbg_sl_11);
                            ${$rsb}{$ky} = $nv;
                        } elsif ($ky eq '-NEW_LIBS-') {
                            $nv = strip_quotes($v2);
                            $ok = 0;
                            $nv = get_new_libs_string($v2,\$ok,$rp,$vcd,$outd);
                            if ($ok) {
                                prt( "  $ky CHANGED ok\nwas [$v2]\nnew [$nv]\n") if ($dbg_sl_11);
                                ${$rsb}{$ky} = $nv;
                            } else {
                                prt( "  $ky = [$v2] NO CHANGES\n" ) if ($dbg_sl_11);
                            }
                        } else {
                            prt( "  $ky = [$v2] NOT CHANGED\n" ) if ($dbg_sl_08);
                        }
                        ###prt( "NEXT KEY after $ky [$v2] [$nv]\n");
                    }
                }
            } else {
                # dealt with 'PROJECT_SRCS' and 'PROJECT_CFGS' above
                # What about PROJECT_NAME, PROJECT_CCNT, PROJECT_FDIR, PROJECT_FILE
                # PROJECT_TYPE, PROJECT_DSPF, PROJECT_VERS, PROJECT_APTP, PROJECT_FLAG, PROJECT_MSCV?
                $tmp = '';
                if ($key eq 'PROJECT_NAME') {
                    # $tmp = "Like change name from [$val]?";
                } elsif ($key eq 'PROJECT_CCNT') {
                    # $tmp = "Like config count [$val]?";
                } elsif ($key eq 'PROJECT_FDIR') {
                    # $tmp = "Like FDIR [$val]?";
                } elsif ($key eq 'PROJECT_FILE') {
                    # $tmp = "Like FILE [$val]?";
                } elsif ($key eq 'PROJECT_TYPE') {
                    $tmp = "Like TYPE [$val]?";
                } elsif ($key eq 'PROJECT_DSPF') {
                    $tmp = "Like DSP FILE [$val]?";
                } elsif ($key eq 'PROJECT_VERS') {
                    # $tmp = "Like VERS [$val]?";
                } elsif ($key eq 'PROJECT_APTP') {
                    $tmp = "Like APTP [$val]?";
                } elsif ($key eq 'PROJECT_FLAG') {
                    # $tmp = "Like FLAG [$val]?";
                } elsif ($key eq 'PROJECT_MSCV') {
                    # $tmp = "Like FLAG [$val]?";
                } elsif ($key eq 'PROJECT_AM_FILE') {
                } elsif ($key eq 'PROJECT_ROOT') {
                } else {
                    $tmp = "Like UNCASED [$val]?";
                    pgm_exit(1,"CHECKME:chk_relative_paths: key [$key] UNCASED, with val [$val]");
                }
                prt("$key ... any items to change? $tmp\n") if (length($tmp) && $dbg_sl_10);
            }
        }
    }
    if (@not_found && VERB1()) {
        $tmp = scalar @not_found;
        prtw("WARNING: Project $active_project has $tmp MISSING sources!\n");
        foreach $src (@not_found) {
            prt("$src\n");
        }
    }
    # pgm_exit(1,"Temp stop to check");
}

# ensure -NEW_LIBS- hash ref does NOT contain LIBS already in default
sub fix_lib_list($) {
    my ($rh) = @_;
    my $key = 'PROJECT_CFGS';
    my $chgd = 0;
    my $def = get_def_lib_list();
    my @a2 = split(/\s/,$def);
    if (defined ${$rh}{$key}) {
        my $val = ${$rh}{$key};
        my $k2 = '-NEW_LIBS-';
        my $acnt = scalar @{$val};
        for (my $i = 0; $i < $acnt; $i++) {
            my $rsb = ${$val}[$i][3];   # get -NEW_LIBS- hash ref
            if (defined ${$rsb}{$k2}) {
                my $v2 = ${$rsb}{$k2};
                prt("[dbg_sl_13]  [$v2],\nwith default [$def]\n") if ($dbg_sl_13);
                my @a1 = split(/\s/,$v2);
                my $chg = 0;
                my @arr = ();
                my ($lib, $lib2,$fnd,$lclib);
                foreach $lib (@a1) {
                    $lclib = lc($lib);
                    if ($lib =~ /^\/libpath:/i) {  # no change in these
                        push(@arr,$lib);
                    } else {
                        $fnd = 0;   # else check if already in DEFAULTS
                        foreach $lib2 (@a2) {
                            if ($lclib eq lc($lib2)) {
                                $fnd = 1;
                                last;
                            }
                        }
                        if ($fnd) {
                            $chg++; # dump this DUPLICATE
                        } else {
                            push(@arr,$lib);    # else keep this
                        }
                    }
                }
                if ($chg) {
                    $lib = join(" ",@arr);
                    ${$rsb}{$k2} = $lib;
                    prt(" Set NEW [$lib]\n") if ($dbg_sl_13);
                    $chgd++;
                }
            }
        }   # for each configuration
        if ($chgd) {
           # pgm_exit(1,"TEMP EXIT");
        }
    }
}

# dbg_show_entering_files();
# dbg_show_source_files();
# dbg_show_output_files(); # { $dbg_v21 = 1; $dbg_v24 = 1; }
# 2009/10/29 - make it work for TWO different forms of VC HASH
# 13/07/2011 - if ($out_dsp_dir ne $perl_base), then try to also ADJUST sources
sub process_vcproj_file($$) {
    my ($in, $outd) = @_;
    my ($key,$pnam,$out,$cnt,$dsp);
    my ($prjf,$nm,$dir,$ext,$dspf,$tmp2);
    my ($msg);
    my ($rdspf,$fprjf,$fdspf,$dprjf,$type);
    prt( "[dbg_sl_05] $pgmname: Scanning [$in]...\n" ) if ($dbg_sl_05);
    my ($vc_name,$vc_dir) = fileparse($in);
    $vc_dir = $pwd."\\" if ($vc_dir =~ /^\.(\\|\/)$/);
    my $rh = process_VCPROJ3($in);

    # FIX20120718 - some 'fixes' if NOT already defined
    ${$rh}{'PROJECT_ROOT'} = $vc_dir if (!defined ${$rh}{'PROJECT_ROOT'});
    ${$rh}{'PROJECT_AM_FILE'} = $in if (!defined ${$rh}{'PROJECT_AM_FILE'});

    # check for application type over-ride...
    if (length($curr_app_type)) {
        $key = 'APP_TYPE';
        $key = 'PROJECT_APTP' if (!defined ${$rh}{$key});
        if (defined ${$rh}{$key}) {
            $tmp2 = ${$rh}{$key};
            ${$rh}{$key} = $curr_app_type;
            if ($tmp2 ne $curr_app_type) {
                prt("Overrode $key with [$curr_app_type], from [$tmp2]\n");
            }
        }
    }

    $type = "NOT DEFINED";
    $key = 'APP_TYPE';
    $key = 'PROJECT_APTP' if (!defined ${$rh}{$key});
    if (defined ${$rh}{$key}) {
        $type = ${$rh}{$key};
    }

    # 2010-01-15 - get appropriate DSP file name (real = to replace existing, if any)
    $key = 'PROJECT_FILE';
    $fprjf = '';
    $rdspf = '';
    $fdspf = '';
    if (defined ${$rh}{$key}) {
        $fprjf = ${$rh}{$key};
        ($nm,$dprjf,$ext) = fileparse($fprjf, qr/\.[^.]*/);
        $fdspf = $dprjf.$nm.".dsp";   # this may/should be ABSOLUTE
    } else {
        pgm_exit(1,"ERROR: key [$key] NOT IN hash! AND IT MUST BE!! Aborting!!!\n");
    }

    # FIX20120718 - If NO project name, then use the input project file name as default
    if (!defined ${$rh}{'-NEW_PROJECT_NAME-'} && !defined ${$rh}{'PROJECT_NAME'}) {
        ${$rh}{'PROJECT_NAME'} = $nm;
        prt("No project name, so using project file name [$nm]!\n");
    }
    $pnam = "NO PROJECT NAME";
    $key = '-NEW_PROJECT_NAME-';
    $key = 'PROJECT_NAME' if (!defined ${$rh}{$key});
    if (defined ${$rh}{$key}) {
        $pnam = ${$rh}{$key};    # get the PROJECT NAME
    }

    # show_hash_results3($rh) if ($dbg_sl_04);  # this would be BEFORE any changes made in chk_relative_paths...
    $key = '-NEW_PROJECT_NAME-';
    $key = 'PROJECT_NAME' if (!defined ${$rh}{$key});
    if (defined ${$rh}{$key}) {
        $pnam = ${$rh}{$key};    # get the PROJECT NAME
        $dsp = $pnam.".dsp";     # make a DSP file name
        ${$rh}{'PROJECT_DSPF'} = $dsp;
        $outd .= "\\" if ( !($outd =~ /[\\\/]$/) ); # ensure out directory ends '\'
        $out = $outd;           # using OUT directory
        $out .= "temp.".$dsp;   # form a TEMPORARY DSP file name

        fix_lib_list($rh);
        # crude game to ensure TEMP DSP name for this project is UNIQUE
        $cnt = 0;
        while ( is_in_array($out, @dsp_file_list) ) {
            $cnt++; # already have a DSP of that name, so
            $out = $outd;   # get OUT directory again, and
            $out .= "temp.".$pnam.$cnt.".dsp";   # add a COUNT to name
        }

        if ($fix_rel_paths) {
            # ======================================================================================
            # ok, need to change sources from perhaps '.\src.cxx' to '..\..\lib\src.cxx' - a big job
            # and LOTS of other things...
            # UGH - calling this HERE, is BEFORE the %results hash is built
            chk_relative_paths($rh,$outd,$vc_dir);  # was $perl_base; # this can be changed by -dsp=<new_dir>
            # ======================================================================================
        } else {
            prt("No relative path change: vcd=[$vc_dir] out=[$outd]\n") if (VERB9());
        }

        # 2011-10-18 - Make other ADSJUTMENTS to DSP HASH
        adjust_inter_out_dirs($rh) if ($adj_inter);
        adjust_runtime_to($rh,$adj_rt) if (length($adj_rt));
        adjust_output_name($rh) if ($adj_out);
        # remove like -NEW_LIBS- = [wsock32.lib comctl32.lib /libpath:"..\lib" /nodefaultlib:"libcmtd"]
        $tmp2 = ''; # clear $tmp2
        delete_nodefaultlib_all($rh,\$tmp2) if ($del_ndl_all);
        if (length($tmp2) && VERB5()) {
            prt("[v5] Removed /nodefaultlib [$tmp2]\n");
        }

        show_hash_results3($rh) if ($dbg_sl_04);

        # *** WRITE DSP FILE - FIRST TO A 'TEMP' FILE, to do a compare, if needed ***
        # ===========================================================================
        if ($write_dsp > 0) {
            prt("Doing write_hash_to_DSP3 $out (debug=$dbg4write)\n") if (VERB9());
            if ( write_hash_to_DSP3( $out, $rh, $dbg4write ) ) {
                push(@dsp_file_list,$out);  # store name
                #     project_list    0     1     2
                #push(@project_list, [ $tmp, $dsp, $out ]);
                push(@project_list, [ $pnam, $fdspf, $out ]);
                $key = 'PROJECT_FILE';
                if (defined ${$rh}{$key}) {
                    $prjf = ${$rh}{$key};
                    prt( "For '$prjf' written '$out'\n" ) if (VERB5());

                    # Uses cmp2dsps[?].pl, external to here...
                    if ($comp_2_dsps) {
                        ($nm,$dir,$ext) = fileparse($prjf, qr/\.[^.]*/);
                        $dspf = $dir.$nm.".dsp";
                        if (( -f $dspf)&&( -f $out)) {
                            $msg = "cmp2dsps $dspf $out";
                            $msg .= " -l" if ($load_log);
                            prt("Doing $msg...\n");
                            system("$msg");
                        } else {
                            $msg = "No compare done! ";
                            if ( !(-f $dspf) ) {
                                $msg .= "Missing [$dspf]?";
                            }
                            if ( !(-f $out) ) {
                                $msg .= "Missing [$out]??";
                            }
                            prtw("WARNING: $msg\n");
                        }
                    }
                    # =======================================
                }
            } else {
                prtw("WARNING: No DSP written for [$pnam] project.\n" );
            }
        } else {
            prt("Project: $pnam: No DSP written - Use -dsp[:dsp_dir] to enable!\n");
        }
    } else {
        show_hash_results3($rh) if ($dbg_sl_04);
        prtw("WARNING: NO PROJECT NAME! = NO DSP WRITTEN!\n");
    }

    if (do_hash_cmake_test($rh)) {
        prtw("WARNING: PROJECT $pnam $type FAILED CMAKE HASH TEST!\n");
    } else {
        my $rcph = get_cmake_proj_hash_ref();
        push(@{$rcph},$rh);
    }

    return $rh;
}

sub fix_rel_path2($$) {
    my ($root,$rel) = @_;
    my $cd = cwd();
    my ($fp,$msg,$tmp);
    if (chdir($root)) {
        $fp = File::Spec->rel2abs($rel);    # we are IN the SLN directory, get ABSOLUTE from RELATIVE
        chdir($cd); # and get us back to where we were...
        $msg = "1:File::Spec:";
    } else {
        $fp = fix_rel_path3($root.$rel,'fix_rel_path2'); # else use internal service
        $msg = "2:fix_rel_path3:"
    }
    if (-f $fp) {
        $msg .= " ok";
    } else {
        $msg .= " NOT FOUND";
        if ($fp =~ /\\SimGear\.cs\\/) {
            $tmp = $fp;
            $tmp =~ s/\\SimGear\.cs\\/\\SimGear-cs\\/;
            if (-f $tmp) {
                $fp = $tmp;
                $msg = "ok $msg";
            }
        }
        if ($msg =~ /^1/) {
            $tmp = fix_rel_path3($root.$rel,'fix_rel_path2'); # else use internal service
            if (-f $tmp) {
                $fp = $tmp;
                $msg .= ", but OK with fix_rel_path3!!!";
            } else {
                $msg .= ", NOR from fix_rel_path3 [$tmp]"
            }
        }
    }
    prt("From: [$root] [$rel], got [$fp] $msg\n") if ($dbg_sl_14);
    return $fp; # hopefully, return ABSOLUTE path
}

# Read and store contents of SOLUTION (.sln) file
# 22/04/2008 - Extract DEPENDENCIES from solution file, and add to DSW output
# 24/11/2010 - Support for VC10 XML files
sub process_SLN_file2($) {
	my ($sln_fil_in) = 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);
    my ($nmdeps, $depid, $pn, $fnd, $list);
    my ($msg,$text,$dspfile,$fdspfil,$name);
    my $fil = File::Spec->rel2abs($sln_fil_in);
	open IF, "<$fil" or mydie( "ERROR: Unable to open [$fil]... $! ...\n" );
	my @lines = <IF>;
	close IF;
	$cnt = scalar @lines;
	($name,$sln_path) = fileparse($fil); # get the NAME, and SOLUTION PATH (should be ABSOLUTE, NOT relative)
    my %hash = ();
    my %sln_projects = ();
    my %sln_projpath = ();
    my %sln_depends = ();
    my %sln_projids = ();
    my %missed_vcprojs = ();
	prt( "\nProcessing $cnt lines ... n=[$name] p=[$sln_path] ...\n" ) if (VERB1());
	$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}") = "ALL_BUILD", "ALL_BUILD.vcxproj", "{4BB0374F-3B6E-4EC8-9BE0-4BE8947B80E3}"
			#Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "abyss", "abyss.vcproj", "{8B384B8A-2B72-4DC4-8DF1-E3EF32F18850}"
            #Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fgadmin", "fgadmin\fgadmin.vcxproj", "{7004E589-7EA0-4AFD-B432-3D5E00B55049}"
            #	ProjectSection(ProjectDependencies) = postProject
            #		{22540CD3-D3CA-4C86-A773-80AEEE3ACDED} = {22540CD3-D3CA-4C86-A773-80AEEE3ACDED}
            #	EndProjectSection
            #EndProject
			###prt( "Got project [$line] ...\n" );
			$inproj = 1;
			@arr = split( '=', $line );
			$cnt = scalar @arr;
			if ($cnt == 2) {
				$par = $arr[1]; # get 2nd part, like say '"abyss", "abyss.vcproj", "{8B384B8A-2B72-4DC4-8DF1-E3EF32F18850}"'
				@arr = split(',', $par);
				$cnt = scalar @arr;
				if ($cnt == 3) {
					$projname = strip_quotes(trim_all($arr[0])); # project NAME
					$projfile = strip_quotes(trim_all($arr[1])); # vcproj FILE
					$projid   = strip_quotes(trim_all($arr[2])); # project ID
					$projff   = fix_rel_path2($sln_path,$projfile); # return ABSOLUTE
					# if ((length($projname)) && (is_vcproj_ext($projfile)) && (-f $projff)) {
                    # 01/12/2010 - Remove need for the file to EXIST
					#if ((length($projname)) && (is_vcproj_ext($projfile)) ) {
					if ((length($projname)) && (is_vcproj_ext($projfile) || is_vcxproj_ext($projfile)) ) {
                        if (-f $projff) {
                            # and file
                        } else {
                            $missed_vcprojs{$projname} = $projff;
                        }
						$gotproj = 1;
						($tnm,$tpth,$text) = fileparse($projff,qr/\.[^.]*/);
                        $fdspfil = $tpth.$tnm.".dsp";   # this is a DSP EQUIVALENT to the vcproj location
                        # BUT, we may have been given a DIFFERENT DSP output dir through
                        # -dsp=<dir> ($out_dsp_dir) and $g_had_dsp, and maybe '-fix-rel' ($fix_rel_paths)
                        if ($g_had_dsp) {
                            $fdspfil = $out_dsp_dir;
                            $fdspfil .= "\\" if ( !($fdspfil =~ /(\\|\/)$/) );
                            $fdspfil .= $tnm.".dsp";
                        }
						$relpath = get_rel_dos_path($tpth, $sln_path);
						($tnm,$tpth,$text) = fileparse($projfile,qr/\.[^.]*/);
                        $dspfile = $tpth.$tnm.".dsp";
						prt( "Got PROJECT name=$projname, file=[$projfile], ff=[$projff], rel=[$relpath].\n" ) if ($dbg_sl_01);
						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/'
                            #                           0         1       2        3        4
							$sln_projpath{$projname} = [$projfile,$projff,$relpath,$dspfile,$fdspfil]; # relative project file, like '..\alut\path\alut.vcproj'
							prt( "Stored \$sln_projpath{$projname} = [0:$projfile,1:$projff,2:$relpath,3:$dspfile,4:$fdspfil]\n") if ($dbg_sl_15);
							$sln_projids{$projname}  = $projid;
							$sln_depends{$projname}  = '';	# start dependencies, if any
                            if ($dbg_sl_16) {
                                my $msg = $projname;
                                $msg .= ' ' while (length($msg) < 24);
                                $msg .= $projid;
                                prt("$msg\n");
                            }
						}
                        ### pgm_exit(1,"TEMP EXIT");
					} else {
						$msg = "WARNING: ";
						if (!length($projname)) {
							$msg .= "Failed to get a project name! ";
						} elsif ( !is_vcproj_ext($projfile) && !is_vcxproj_ext($projfile)) {
							$msg .= "Name [$projfile] NOT a VCPROJ nor VCXPROJ name! ";
						} else {
							$msg .= "Unable to locate file [$projff]! ";
						}
						$msg .= " Line is (trimmed)\n$tline";
                        prtw("$msg\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
			# =====================================================================
			prtw("WARNING: line [$line] ...\n") if (!$gotproj);
			# =====================================================================
		} 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( "$pgmname: Proj $projname, dependant on $arr[0] ...\n" ) if ($dbg_sl_02);
								##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();
    # Have STORED
    # $sln_projects{$projname} = $projff;
	# $sln_projpath{$projname} = $relpath; # can be BLANK, or say 'BvMath/'
    #                           0         1       2        3        4
	#$sln_projpath{$projname} = [$projfile,$projff,$relpath,$dspfile,$fdspfil]; # relative project file, like '..\alut\path\alut.vcproj'
	#prt( "Stored \$sln_projpath{$projname} = [0:$projfile,1:$projff,2:$relpath,3:$dspfile,4:$fdspfil]\n") if ($dbg_sl_15);
	# $sln_projids{$projname}  = $projid;
	# $sln_depends{$projname}  = '';	# start dependencies, if any
	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) {
                # find project MATCHING that ID, in full list of IDs
                $fnd = 0;
                $list = '';
				foreach $pn (keys %sln_projids) {
					if ($pn ne $projname) {
						$projid = $sln_projids{$pn};
                        $list .= "|$projid";
						if ($depid eq $projid) {
							$nmdeps .= '|' if (length($nmdeps));
							$nmdeps .= $pn;
                            $fnd = 1;
							last;
						}
					}
				}
                if (!$fnd) {
                    prtw("Warning: Failed to FIND [$depid], in list \n[$list]\n!");
                }
			}
			@arr = split( /\|/, $nmdeps );
			prt( "$pgmname: proj $projname, depends on $nmdeps ...\n" ) if ($dbg_sl_03);
			if ($cnt != scalar @arr) {	# YEEK - Does NOT match - OH WELL
				prtw( "WARNING: proj [$projname] with depends [$projdeps] Failed to get SAME count $cnt - got ".scalar @arr." on split [$nmdeps]\n" );
                pgm_exit(1,"");
			}
			$sln_depends{$projname} = $nmdeps;
		}
	}
    # ====================================================================
    $hash{'SOLUTION'} = $fil;   # keep the SOLUTION files also
    $hash{'PROJECTS'} = { %sln_projects };
    $hash{'PROJPATH'} = { %sln_projpath };  # array refs [$projfile,$projff,$relpath]
    $hash{'DEPENDS'}  = { %sln_depends  };
    $hash{'PROJIDS'}  = { %sln_projids };
    $hash{'MISSED_FILES'} = { %missed_vcprojs }; # not found on DISK
    return \%hash;
}

sub remove_base_path($$) {
    my ($ln, $bs) = @_;
    my $len1 = length($ln);
    my $len2 = length($bs);
    if ($len1 < $len2) {
        return $ln;
    }
    my ($i,$c1,$c2);
    for ($i = 0; $i < $len2; $i++) {
        $c1 = lc(substr($ln,$i,1));
        $c2 = lc(substr($bs,$i,1));
        if ($c1 ne $c2) {
            return $ln;
        }
    }
    return substr($ln,$len2);
}

sub return_common_dir($$) {
    my ($d1,$d2) = @_;
    my ($ll,$k,$com);
    $com = '';
    $ll = length($d1);
    $ll = length($d2) if (length($d2) < $ll);   # get SHORTEST
    for ($k = 0; $k < $ll; $k++) {  # process for SHORTEST length
        last if (lc(substr($d1,$k,1)) ne lc(substr($d2,$k,1))); # end on first NOT SAME
        $com .= substr($d1,$k,1);   # else add to common
    }
    return $com;
}

sub get_common_dir($) {
    my ($rffh) = @_;
    my $cdir = '';
    my @keys = keys %{$rffh};
    my $kcnt = scalar @keys;
    my ($ky1,$ky2,$k,$com);
    for ($k = 0; ($k+1) < $kcnt; $k++) {
        $ky1 = $keys[$k];
        $ky2 = $keys[$k+1];
        $com = return_common_dir($ky1,$ky2);
        if (length($com) == 0) {
            return "";  # no COMMON
        }
        if (length($cdir)) {
            $com = return_common_dir($com,$cdir);
            if (length($com) == 0) {
                return "";  # no COMMON
            }
        }
        $cdir = $com;    # update the COMMON
    }
    return $cdir;
}

# sub mycmp_decend {
sub mysort2 {
   return 1 if (${$a}[2] lt ${$b}[2]);
   return -1 if (${$a}[2] gt ${$b}[2]);
   return 0;
}
sub mysort0 {
   return -1 if (lc(${$a}[0]) lt lc(${$b}[0]));
   return 1 if (lc(${$a}[0]) gt lc(${$b}[0]));
   return 0;
}


sub sort_ref_results_by_type($) {
    my ($rr) = @_;
    my @arr = sort mysort2 @{$rr};
    return \@arr;
}
sub sort_ref_results_by_name($) {
    my ($rr) = @_;
    my @arr = sort mysort0 @{$rr};
    return \@arr;
}


sub show_sln_results($) {
    my ($rsh) = @_;
    my ($cnt,$min1,$min2,$min3,$cnt2);
    my ($val,$val2,$val3,$len);
    my ($k,$i,$dspf,$j);
    my ($tdsp,$vcpf);
    $k = 'RESULTS';
    if (! defined ${$rsh}{$k}) {
        prtw("WARNING: Soluion hash reference does NOT contain [$k]!\n");
        return 1;
    }
    # push(@results, [$k, $nm, $captyp, $ff]); # stored in 'RESULTS'
    #                 0   1    2        3       4       5  6
    # push(@results, [$k, $nm, $captyp, $relpf, $fdspf, 0, 0]); # stored in 'RESULTS'
    my $results = ${$rsh}{$k};

    $k = 'PROJECT_LIST';
    if (! defined ${$rsh}{$k}) {
        prtw("WARNING: Soluion hash reference does NOT contain [$k]!\n");
        return 1;
    }
    my $plist = ${$rsh}{$k};
    $k = 'PROJECT_FILE';
    if (! defined ${$rsh}{$k}) {
        prtw("WARNING: Soluion hash reference does NOT contain [$k]!\n");
        return 1;
    }
    my $in = ${$rsh}{$k};

    $cnt = scalar @{$results};
    if ($cnt == 0) {
        prt("\nNo projects found!\n");
        return;
    }
    # get lengths, for neat output
    $min1 = 0;
    $min2 = 0;
    $min3 = 0;
    #                       0     1     2     4     
    # push(@project_list, [ $tmp, $dsp, $out, $fdspf]);
    $cnt2 = scalar @{$plist};
    #                 0      1      2      3       4       5  6
    # push(@results, [$name, $file, $type, $relpf, $fdspf, 0, 0]); # stored in 'RESULTS'
    if ($sort_by_name) {
        $results = sort_ref_results_by_name($results);
    }
    if ($sort_by_type) {
        $results = sort_ref_results_by_type($results);
    }
    my %types = ();
    for ($i = 0; $i < $cnt; $i++) {
        $val = ${$results}[$i][0];
        $val2 = ${$results}[$i][1];
        $val3 = ${$results}[$i][2];
        $len = length($val);
        $min1 = $len if ($len > $min1);
        $len = length($val2);
        $min2 = $len if ($len > $min2);
        $len = length($val3);
        $min3 = $len if ($len > $min3);
        if (defined $types{$val3}) {
            $types{$val3}++;
        } else {
            $types{$val3} = 1;
        }
    }
    prt("\nSolution file [$in], has $cnt projects...($cnt2)\n");
    if (VERB1()) {
        if ($cnt) {
            # about to output something like
            # testcon testcon.vcproj Console Application  testcon.dsp (C:\GTools\perl\temp.testcon.dsp)
            # Setup a HEADING line
            $val = "Name";
            $val2 = "File";
            $val3 = "Type";
            $val .= ' ' while (length($val) < $min1);
            $val2 .= ' ' while (length($val2) < $min2);
            $val3 .= ' ' while (length($val3) < $min3);
            prt("$val $val2 $val3"); # set HEADINGS
            prt(" DSP File") if (VERB5());
            prt("\n");
        }
        for ($i = 0; $i < $cnt; $i++) {
            $val = ${$results}[$i][0]; # extract the project NAME
            $dspf = 'UNKNOWN';
            $tdsp = $dspf;
            for ($j = 0; $j < $cnt2; $j++) {
                if (${$plist}[$j][0] eq $val) {
                    $dspf = ${$plist}[$j][1];
                    $tdsp = ${$plist}[$j][2];
                    last;
                }
            }
            $val2 = ${$results}[$i][1];
            $val3 = ${$results}[$i][2];
            #                  0         1       2        3        4     5  6
            # push(@results, [$projfile,$projff,$relpath,$dspfile,$fdsp, 0, 0]); # relative project file, like '..\alut\path\alut.dsp'
            $vcpf = ${$results}[$i][3]; # destination, relative DSP file, for DSW write
            if ($tdsp ne $dspf) {
                $dspf = "$dspf ($tdsp)";
            }
            $val .= ' ' while (length($val) < $min1);
            $val2 .= ' ' while (length($val2) < $min2);
            $val3 .= ' ' while (length($val3) < $min3);
            #prt("$val $val2 $val3 $dspf\n");
            # tgvpf tgvpf.vcproj Console Application .\tgvpf.dsp (C:\FG\28\terragear-cs\projects\msvc\temp.tgvpf.dsp) [tgvpf\tgvpf.dsp]
            prt("$val $val2 $val3");
            prt(" $dspf [$vcpf]") if (VERB5());
            prt("\n");
        }
    }
    prt("Counts per type: ");
    foreach $val (keys %types) {
        if (length($val) == 0) {
            prt("<NoType> = $types{$val} ");
        } else {
            prt("$val = $types{$val} ");
        }
    }
    prt("\n");
    prt( "$pgmname: Done $cnt vcproj processing...\n" ) if (VERB1());
}

# If an $out directory given, try to adjust all SOURCE relative to this folder
sub sln_file_processing($$$) {
    my ($flg,$in,$out) = @_;
    my ($k,$rsh,$val,$ff,$key,$captyp,$nm,$dir,$cnt,$i,$min1,$min2,$val2,$len);
    my ($refhash,$min,$cnt2,$dspf,$j,$val3,$min3,$ok);
    my ($ext,$k2,$relpf,$fdspf);
    my @results = ();
    ($nm,$sln_root_dir) = fileparse($in);
    $rsh = process_SLN_file2($in);
    if (VERB9()) {
        prt( "$pgmname: KEYS in SLN hash = " );
        foreach $k (keys %{$rsh}) { prt( "$k " ); }
        prt("\n");
    }
    # =====================================
    $k = 'PROJECTS';
    $k2 = 'PROJPATH';
    if ((defined ${$rsh}{$k})&&(defined ${$rsh}{$k2})) {
        # $sln_projects{$projname} = $projff;
        $val = ${$rsh}{$k};     # extract projects HASH
        $val2 = ${$rsh}{$k2};   # extract project paths HASH
        $min = 0;
        $cnt = 0;
        $min1 = 0;
        my %ffhash = ();
        foreach $k (keys %{$val}) {
            $ff = ${$val}{$k};
            $len = length($k);
            $min = $len if ($len > $min);
            if (is_vcproj_ext($ff) || is_vcxproj_ext($ff)) {
                $ffhash{$ff} = 1;
                $cnt++;
            } else {
                $ffhash{$ff} = 0;
            }
            $len = length($ff);
            $min1 = $len if ($len > $min1);
        }
        $commdir = get_common_dir( \%ffhash );
        if (length($commdir)) {
            prt("All $cnt vcproj files in a COMMON PATH: [$commdir]\n");
            if (length($commdir) < $min1) {
                $min1 -= length($commdir);
            }
        }
        prt("SLN path=[$sln_root_dir]\n") if ($commdir ne $sln_root_dir);
        if (VERB1()) {
            foreach $k (keys %{$val}) {
                $ff = ${$val}{$k};
                #                             0         1       2        3
                # $sln_projpath{$projname} = [$projfile,$projff,$relpath,$dspfile]; # relative project file, like '..\alut\path\alut.dsp'
                # and later
                # push(@results, [$k, $nm, $captyp, $relpf, $fdspf]); # stored in 'RESULTS'
                $val3 = ${$val2}{$k};
                $relpf = ${$val3}[3];   # relative DSP file, for DSW write
                $ok = (( -f $ff ) ? "ok" : "NOT FOUND!");
                ($nm, $dir, $ext) = fileparse( $ff, qr/\.[^.]*/ );
                $dspf = $dir.$nm.".dsp";
                $ok .= "2" if (-f $dspf);
                $ff = remove_base_path($ff,$commdir) if (length($commdir));
                $k .= ' ' while (length($k) < $min);
                $ff .= ' ' while (length($ff) < $min1);
                prt("$k - $ff ($ok) $relpf\n" );    # this DSP rel.path may need to be changed later, if -dsp=<path>
            }
            prt( "\nNow to process EACH of the $cnt projects...\n" );
        }
        # --------------------------------------------------
        foreach $k (keys %{$val}) {
            $ff = ${$val}{$k};
            # prt("$k - $ff\n" );
            ($nm, $dir) = fileparse($ff);
            # if (is_vcproj_ext($ff))
            # 01/12/2010 - add an existance check
            #if (is_vcproj_ext($ff) && (-f $ff)) {
            # 14/04/2012 - add check for vcxproj
            if (-f $ff) {
                if (is_vcproj_ext($ff)) {
                    $refhash = process_vcproj_file($ff, $out);
                } elsif (is_vcxproj_ext($ff)) {
                    $refhash = process_vcxproj_file($ff, $out);
                }
                $key = 'APP_TYPE';
                if ( ! defined ${$refhash}{$key}) {
                    $key = 'PROJECT_APTP';
                }
                if (defined ${$refhash}{$key}) {
                    $captyp = ${$refhash}{$key};
                } else {
                    $captyp = "Unknown - key=[$key] NOT SET"; 
                }
                #                             0         1       2        3     4
                # $sln_projpath{$projname} = [$projfile,$projff,$relpath,$rdsp,$fdsp]; # relative project file, like '..\alut\path\alut.dsp'
                $val3 = ${$val2}{$k};
                $relpf = ${$val3}[3];   # relative DSP file, for DSW consumption (see write_proj_DSW3)
                $fdspf = ${$val3}[4];
                if ($fix_rel_paths && $g_had_dsp) {
                    my ($tn,$td) = fileparse($relpf);
                    $relpf = ".\\$tn";
                }
                #               0   1    2        3       4       5  6
                push(@results, [$k, $nm, $captyp, $relpf, $fdspf, 0, 0]); # stored in 'RESULTS'
            }
        }
    } else {
        pgm_exit(1,"ERROR: key [$k] NOT found in hash!\n");
    }

    $k = 'RESULTS';
    ${$rsh}{$k} = [@results];
    $k = 'PROJECT_LIST';
    ${$rsh}{$k} = [@project_list];  # keep project list, including output DSP file, if written
    $k = 'PROJECT_FILE';
    ${$rsh}{$k} = $in;
    return $rsh;
}

# ==============================================
# 10/04/2012 - begin to process files with a BOM
# LOAD without a BOM
my $strip_bom = 1;
my $curr_file_bom = '';

my @BOM_list = (
    [ "UTF-8",       3, [0xEF,0xBB,0xBF     ] ], # 239 187 191   
    [ "UTF-16 (BE)", 2, [0xFE,0xFF          ] ], # 254 255 
    [ "UTF-16 (LE)", 2, [0xFF,0xFE          ] ], # 255 254
    [ "UTF-32 (BE)", 4, [0x00,0x00,0xFE,0xFF] ], # 0 0 254 255
    [ "UTF-32 (LE)", 4, [0xFF,0xFE,0x00,0x00] ], # 255 254 0 0
    [ "UTF-7a"     , 4, [0x2B,0x2F,0x76,0x38] ], # 2B 2F 76 39  2B 2F 76 2B  2B 2F 76 2F
    [ "UTF-7b"     , 4, [0x2B,0x2F,0x76,0x39] ], # 2B 2F 76 39  2B 2F 76 2B  2B 2F 76 2F
    [ "UTF-7c"     , 4, [0x2B,0x2F,0x76,0x2B] ], # 2B 2F 76 39  2B 2F 76 2B  2B 2F 76 2F
    [ "UTF-7d"     , 4, [0x2B,0x2F,0x76,0x2F] ], # 2B 2F 76 39  2B 2F 76 2B  2B 2F 76 2F
    [ "UTF-1"      , 3, [0xF7,0x64,0x4C     ] ], # 247 100 76 
    [ "UTF-EBCDIC" , 4, [0xDD,0x73,0x66,0x73] ], # 221 115 102 115
    [ "SCSU"       , 3, [0x0E,0xFE,0xFF     ] ], # 14 254 255
    [ "BOCU-1"     , 3, [0xFB,0xEE,0x28     ] ], # 251 238 40
    [ "GB-18030"   , 4, [0x84,0x31,0x95,0x33] ]  # 132 49 149 51
);

sub line_has_bom($$) {
    my ($line,$rname) = @_;
    my $max = scalar @BOM_list;
    my $len = length($line);
    my ($i,$j,$name,$cnt,$ra,$ch,$val);
    for ($i = 0; $i < $max; $i++) {
        $name = $BOM_list[$i][0]; # name
        $cnt  = $BOM_list[$i][1]; # length
        $ra   = $BOM_list[$i][2]; # ref array of values
        if ($len > $cnt) {  # make sure line length GT BOM
            for ($j = 0; $j < $cnt; $j++) {
                $ch = substr($line,$j,1);   # extract CHAR
                $val = ord($ch);            # get VALUE
                last if ($val != ${$ra}[$j]); # compare
            }
            if ($j == $cnt) {   # if ALL values found
                ${$rname} = $name;  # give back 'name'
                return $cnt;    # and return count
            }
        }
    }
    return 0;   # no BOM found
}

sub remove_utf_bom($$) {
    my ($ff,$ra) = @_;
    my $line = ${$ra}[0];  # get first line
    my $name = '';
    my $len = line_has_bom($line,\$name);
    if ($len) {
        $curr_file_bom = substr($line,0,$len);
        $line = substr($line,$len); # truncate line
        ${$ra}[0] = $line;  # and return minus BOM
        my ($nm,$dr) = fileparse($ff); # just show name
        prt("[v9] NOTE: File [$nm] is $name encoding. BOM($len) removed.\n") if (VERB9());
    }
}

sub load_file_lines($$) {
    my ($ff,$ra) = @_;
    my $lncnt = 0;
    $curr_file_bom = '';
    if (open INF, "<$ff") {
        @{$ra} = <INF>;
        close INF;
        $lncnt = scalar @{$ra};
        remove_utf_bom($ff,$ra) if ($strip_bom);
    } else {
        prtw("WARNING: Unable to open [$ff]!\n");
    }
    return $lncnt;
}

sub get_xml_ref_array($$) {
    my ($ff,$rla) = @_;
    my $max = scalar @{$rla};
    my ($i,$line,$len,$ch,$inquote,$qc,$tag,$txt,$intag,$lnn,$dnline);
    $inquote = 0;
    $intag = 0;
    my @xlines = ();
    $lnn = 0;
    $tag = '';
    $txt = '';
    $dnline = 0;
    foreach $line (@{$rla}) {
        chomp $line;    # = trim_all($line);
        $len = length($line);
        $lnn++;
        $dnline = 0;
        for ($i = 0; $i < $len; $i++) {
            $ch = substr($line,$i,1);
            if ($inquote) {
                if ($intag) {
                    $tag .= $ch;
                } else {
                    $txt .= $ch;
                }
                if ($ch eq $qc) {
                    $inquote = 0;
                }
            } else {
                if ($intag) {
                    $tag .= $ch;
                    if ($ch eq '>') {
                        $intag = 0;
                        push(@xlines,[$lnn,$txt,$tag,$dnline]);
                        $txt = '';  # clear text
                        $tag = '';  # and tag
                        $dnline++;
                    } elsif (($ch eq '"') || ($ch eq "'")) {
                        $qc = $ch;
                        $inquote = 1;
                    }
                } else {
                    if ($ch eq '<') {
                        $tag = $ch;
                        $intag = 1;
                    } else {
                        $txt .= $ch;
                        if (($ch eq '"') || ($ch eq "'")) {
                            $qc = $ch;
                            $inquote = 1;
                        }
                    }
                }
            }
        }
        if ($inquote) {
            prtw("WARNING:$lnn: Going to next line while in quotes [$qc]!\n");
            $inquote = 0;
        }
        if (!$intag && (length($txt) || !$dnline)) {
            push(@xlines,[$lnn,$txt,$tag,$dnline]);
            $txt = '';  # clear any text
        }
    }
    return \@xlines;
}

sub write_xml_lines($$) {
    my ($ff,$rxml) = @_;
    my ($name,$dir) = fileparse($ff);
    my $tmp_out = $temp_dir.$PATH_SEP."temp.$name.xml";
    my $cnt = scalar @{$rxml};
    if ($cnt == 0) {
        prt("Array for [$ff] is BLANK!\n");
        return;
    }
    my ($i,$rt,$msg,$lnn,$plnn,$txt,$tag);
    $msg = $curr_file_bom;
    $rt = ${$rxml}[0];
    $plnn = ${$rt}[0];
    $txt = '';
    $tag = '';
    for ($i = 0; $i < $cnt; $i++) {
        $rt = ${$rxml}[$i];
        #                0    1    2    3
        #  push(@xlines,[$lnn,$txt,$tag,$dnline]);
        $lnn = ${$rt}[0];
        $txt = ${$rt}[1];
        $tag = ${$rt}[2];
        if ($lnn != $plnn) {
            $msg .= "\n";
            $plnn = $lnn;
        }
        $msg .= $txt;
        $msg .= $tag;
    }
    $msg .= "\n";
    write2file($msg,$tmp_out);
    prt("Array written to [$tmp_out], for [$ff]\n");
}

sub get_tag_hash($$) {
    my ($itag,$r2t) = @_;
    my $tag = $itag;
    my %h = ();
    my $len = length($tag);
    if ($len) {
        if (($tag =~ /^</) && ($tag =~ />$/)) {
            $tag = substr($tag,1,$len-2);
            my @attribs = space_split($tag);
            $tag = $attribs[0];
            ${$r2t} = $tag;
            my @arr = ();
            my $len = scalar @attribs;
            my ($i,$key,$val);
            for ($i = 1; $i < $len; $i++) {
                push(@arr,$attribs[$i]);
            }
            %h = array_2_hash_on_equals(@arr);
        } else {
            prtw("WARNING: Tag NOT complete [$tag]\n");
        }
    }
    return \%h;
}

sub show_tag_hash($$$$) {
    my ($tag,$rh,$itag,$ra) = @_;
    my ($key,$val);
    my $rth = ${$rh}{'CURR_RTH'};
    my $lnn = ${$rh}{'CURR_LNN'};
    my $txt = trim_all(${$rh}{'CURR_TXT'});
    my $cnt = scalar @{$ra};
    #my $tag = ${$rh}{'CURR_TAG'};
    #if (VERB9()) {
    if ($dbg_02) {
        prt("[02]$lnn: ");
        prt("Txt [$txt] ") if (length($txt));
        prt("Tag [$tag] ");
        foreach $key (keys %{$rth}) {
            $val = ${$rth}{$key};
            prt(" $key=$val");
        }
        prt(" from [$itag]") if ($dbg_04);
        $txt = $cnt ? ${$ra}[-1] : "Empty";
        prt(" nts [$txt]$cnt");
        prt("\n");
    }
    if ($dbg_09) {
        prt("[09]$lnn:$cnt:");
        $cnt = 0;
        foreach $txt (@{$ra}) {
            $cnt++;
            prt(" $cnt");
            prt("[$txt]");
        }
        prt("\n");
    }
}

sub set_curr_config($$) {
    my ($rh,$conf) = @_;
    prt("Setting CONFIG for [$conf]\n") if ($dbg_06);
    my $lnn = ${$rh}{'CURR_LNN'};
    my $rcfgs = get_project_configs($rh);   # 'PROJECT_CFGS'
    #          short   'Release' full 'Release|Win32'
    # push(@{$rcfgs}, [ $confname, "", $conf, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS'
    my ($cfg,$tconf,$fnd,$dsp_sub_sub);
    $fnd = 0;
    foreach $cfg (@{$rcfgs}) {
        $tconf = ${$cfg}[2];
        if ($conf eq $tconf) {
            $fnd = 1;
            $dsp_sub_sub = ${$cfg}[3];
            prtw("$lnn: WARNING: Not a VALID \$dsp_sub_sub!\n") if (is_valid_dsp_sub_sub($dsp_sub_sub));
            ${$rh}{'CURR_DSUB'} = $dsp_sub_sub;
            ${$rh}{'CURR_CFG'} = $conf; # like 'Release|Win32' etc
            last;
        }
    }
    if (!$fnd) {
        prt("$lnn: WARNING: Unable to locate CONFIG for [$conf]\n");
    }
}

sub get_rt_value($$) {
    my ($rh,$test) = @_;
    if (!defined ${$rh}{'CURR_RTH'}) {
        pgm_exit(1,"ERROR: get_rt_value: passed ref.hash does NOT contain 'CURR'RTH'!\n");
    }
    my $rt = ${$rh}{'CURR_RTH'};
    my $lnn = ${$rh}{'CURR_LNN'};
    my $fil = ${$rh}{'PROJECT_FDIR'}.${$rh}{'PROJECT_FILE'}; # = $nam.$ext;  # 2010/05/07 - was $fil
    my $val = '';
    if (defined ${$rt}{$test}) {
        $val = strip_quotes(${$rt}{$test});
        # special for 'Condition' # <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
        # and     <ProjectReference Condition="exists('db.vcxproj')" Include="db.vcxproj">
        if ($test eq 'Condition') {
            if ($val =~ /^\s*exists\('(.+)'\)/) {
                # TODO **TBD** mayeb load the 'Include file
            } else {
                prt("$lnn: Getting RT VALUE for 'Condition'\n") if ($dbg_06);
                my @arr = split(/==/,$val);
                if (scalar @arr == 2) {
                    my $tmp = strip_single_quotes($arr[1]);
                    $act_config = get_act_config_type($tmp);      # test /Release/i and /Debug/i and others
                    $val = "CONFIG=$tmp";
                    set_curr_config($rh,$tmp);
                } else {
                    prtw("$lnn: WARNING: Condition did NOT split into 2 on '=='! [$val]! CHECK ME!\n file [$fil]\n");
                }
            }
        }
    }
    return $val;
}

sub merge_library_list($) {
    my ($rh) = shift;
    my $rlibs = ${$rh}{'CURR_LIBS'}; # = \%liblist;
    my $rdirs = ${$rh}{'CURR_LDIRS'}; # = \%dirs;
    my $var1 = '-NEW_LIBS-';
    my $dsp_sub_sub = ${$rh}{'CURR_DSUB'};
    my $conf = ${$rh}{'CURR_CFG'};
    my $lnn = ${$rh}{'CURR_LNN'};
    my @arrd = keys(%{$rdirs});
    my $dlist = '';
    if (@arrd) {
        $dlist = join(" ",@arrd);
        $dlist = get_libpaths_string($dlist);
    }
    my @arr1 = keys(%{$rlibs});
    my @arr2 = ();
    my ($clist,$lib);
    if (defined ${$dsp_sub_sub}{$var1}) {
        $clist = ${$dsp_sub_sub}{$var1};
        @arr2 = split(/\s+/,$clist);
    }
    if (@arr1) {
        foreach $lib (@arr1) {
            next if (length($lib) == 0);
            push(@arr2,$lib) if (!is_in_array_nc($lib,\@arr2));
        }
    }
    $clist = join(" ",@arr2);
    if (length($dlist)) {
        $clist .= " " if (length($clist));
        $clist .= $dlist;
    }
    ${$dsp_sub_sub}{$var1} = $clist;
    prt("[v5] $lnn:SET: -NEW_LIBS-: cfg [$conf] = [$clist]\n") if (VERB5());
}

# $seek = 'AdditionalIncludeDirectories'; # -NEW_INCS_[DBG|REL]-
# sub get_default_sub3(0=rel,1=debug) {
# ItemDef: ClCompile: AdditionalIncludeDirectories = [C:/FG/10/3rdparty/include;C:/Projects/lpng159/temp;C:/Projects/lpng159;%(AdditionalIncludeDirectories)], cond idg [CONFIG=Debug|Win32] op []
sub merge_inc_directories($$) {
    my ($rh,$txt) = @_;
    return if (length($txt) == 0);
    my $var1 = '-NEW_INCS-';
    my $dsp_sub_sub = ${$rh}{'CURR_DSUB'};
    my $conf = ${$rh}{'CURR_CFG'};
    my $lnn = ${$rh}{'CURR_LNN'};
    my @arr = split(/;+/,$txt);
    # my $istg =  get_includes_string($txt);
    my $istg = '';
    my ($inc);
    foreach $inc (@arr) {
        next if ($inc =~ /^%/);
        $istg .= ' ' if (length($istg));
        $istg .= '/I "'.$inc.'"';
    }
    my $ilist = '';
    if (defined ${$dsp_sub_sub}{$var1}) {
        $ilist = ${$dsp_sub_sub}{$var1};
        prtw("$lnn: WARNING: Need MERGE of old [$ilist], with [$istg]\n") if (length($ilist) && length($istg));
    }
    ${$dsp_sub_sub}{$var1} = $istg;
    prt("[v5] $lnn:SET: -NEW_INCS-: cfg [$conf] = [$istg]\n") if (VERB5());
}

sub split_defines_dlist($) {
    my $txt = shift;
    my @arr = split(/\/D\s+/,$txt);
    my $max = scalar @arr;
    my ($i,$def);
    for ($i = 0; $i < $max; $i++) {
        $def = $arr[$i];
        $def = strip_quotes($def);
        $arr[$i] = $def;
    }
    return @arr;
}

# 94: ItemDef: ClCompile: PreprocessorDefinitions = [WIN32;_WINDOWS;_DEBUG;PNG_CONFIGURE_LIBPNG;_CRT_SECURE_NO_DEPRECATE;CMAKE_INTDIR="Debug";PNG_BUILD_DLL;%(PreprocessorDefinitions)], cond idg [CONFIG=Debug|Win32] op [] -NEW_DEFS-
sub set_preprocessor_defines($$) {
    my ($rh,$txt) = @_;
    return if (length($txt) == 0);
    my $var1 = '-NEW_DEFS-';
    my $dsp_sub_sub = ${$rh}{'CURR_DSUB'};
    my $conf = ${$rh}{'CURR_CFG'};
    my $lnn = ${$rh}{'CURR_LNN'};
    my @arr2 = ();
    if (defined ${$dsp_sub_sub}{$var1}) {
        @arr2 = split_defines_dlist(${$dsp_sub_sub}{$var1});
    }
    my @arr1 = split(/;+/,$txt);
    my ($def);
    foreach $def (@arr1) {
        next if ($def =~ /^%/);
        next if (length($def) == 0);
        $def = strip_quotes($def);
        next if (length($def) == 0);
        $def =~ s/"/&quot;/g;
        push(@arr2,$def) if (!is_in_array($def,@arr2));
    }
    my $list = '';
    foreach $def (@arr2) {
        next if (length($def) == 0);
        $def = strip_quotes($def);
        next if (length($def) == 0);
        $list .= ' ' if (length($list));
        $list .= "/I \"$def\"";
    }
    ${$dsp_sub_sub}{$var1} = $list;
    prt("[v5] $lnn:SET: -NEW_DEFS-: cfg [$conf] to [$list]\n") if (VERB5());
}

# 92: ItemDef: ClCompile: RuntimeLibrary = [MultiThreadedDebugDLL], cond idg [CONFIG=Debug|Win32] op [] -NEW_RT-
sub set_runtime_library($$) {
    my ($rh,$txt) = @_;
    return if (length($txt) == 0);
    my $var1 = '-NEW_RT-';
    my $dsp_sub_sub = ${$rh}{'CURR_DSUB'};
    my $conf = ${$rh}{'CURR_CFG'};
    my $lnn = ${$rh}{'CURR_LNN'};
    my $rt = '';
    my $crt = '';
    my $msg = '';
    if ($txt eq 'MultiThreadedDebugDLL') {
        $rt = "/MDd";
    } elsif ($txt eq 'MultiThreadedDLL') {
        $rt = "/MD";
    } elsif ($txt eq 'MultiThreaded') {
        $rt = "/MT";
    } elsif ($txt eq 'MultiThreadedDebug') {
        $rt = "/MTd";
    }
    if (length($rt)) {
        if (defined ${$dsp_sub_sub}{$var1}) {
            $crt = ${$dsp_sub_sub}{$var1};
            if ($crt eq $rt) {
                $msg .= 'same as before';
            } else {
                $msg .= "changed from [$crt]";
            }
        }
        ${$dsp_sub_sub}{$var1} = $rt;
        prt("[v5] $lnn:SET: -NEW_RT-: cfg [$conf], to [$rt] $msg\n") if (VERB5());
    } else {
        prtw("$lnn: WARNING: TODO: Set RUNTIME for cfg [$conf] for [$txt] FIX ME\n");
    }
}

# from CMake source
#    std::string configType = "<ConfigurationType>";
#    switch(this->Target->GetType())
#      {
#      case cmTarget::SHARED_LIBRARY:
#      case cmTarget::MODULE_LIBRARY:
#        configType += "DynamicLibrary";
#        break;
#      case cmTarget::OBJECT_LIBRARY:
#      case cmTarget::STATIC_LIBRARY:
#        configType += "StaticLibrary";
#        break;
#      case cmTarget::EXECUTABLE:
#        configType += "Application";
#        break;
#      case cmTarget::UTILITY:
#        configType += "Utility";
#        break;
#      }
#    configType += "</ConfigurationType>\n";
# PROJECT_APTP - application TYPE
# $app_console_stg  = 'Console Application'  = get_dsp_head_console
# $app_windows_stg  = 'Application'          = get_dsp_head_app
# $app_dynalib_stg  = 'Dynamic-Link Library' = get_dsp_head_dynalib
# $app_statlib_stg  = 'Static Library'       = get_dsp_head_slib
# $app_utility_stg  = 'Utility'              = *TBD*
my %configs_shown = ();
sub set_configuration_type($$) {
    my ($rh,$txt) = @_;
    return if (length($txt) == 0);
    my $lnn = ${$rh}{'CURR_LNN'};
    pgm_exit(1,"ERROR: in set_configuration_type() \${\$rh}{'CURR_CFG'} NOT DEFINED!\n") if (!defined ${$rh}{'CURR_CFG'});
    my $conf = ${$rh}{'CURR_CFG'};
    my $app = '';
    if ($txt eq 'DynamicLibrary') {
        $app = 'Dynamic-Link Library';
    } elsif ($txt eq 'StaticLibrary') {
        $app = 'Static Library';
    } elsif ($txt eq 'Application') {
        $app = 'Application';
    } elsif ($txt eq 'Utility') {
        $app = 'Utility'; # $app_utility_stg  = 'Utility' = *TBD*
    }
    if (length($app)) {
        ${$rh}{'PROJECT_APTP'} = $app;
        if (VERB9() || !defined $configs_shown{$conf}) {
            prt("$lnn:SET: project type [$app] for cfg [$conf]\n");
            if (!defined $configs_shown{$conf}) {
                $configs_shown{$conf} = [];
            }
            my $ra = $configs_shown{$conf};
            push(@{$ra},$app);
        }
    } else {
        prtw("$lnn: WARNING: Uncased ConfigurationType: [$txt]! FIX ME!\n");
    }
}

sub process_rxml_vcxproj($$$) {
    my ($inff,$rxml,$outd) = @_;
    my ($vcname,$vcdir,$vcext) = fileparse($inff, qr/\.[^.]*/);
    my $tmp_out = $temp_dir.$PATH_SEP."temp.$vcname.xml";
    my $cnt = scalar @{$rxml};
    if ($cnt == 0) {
        prt("Array for [$inff] is BLANK!\n");
        return;
    }
    my ($i,$rth,$rtx,$msg,$lnn,$plnn,$txt,$tag,$inproj,$incommand,$command,$initemgroup,$inpropgroup,$impgroup);
    my ($idefgroup,$rtag,$label,$val,$ptag,$show,$opcond,$pgcond,$tvers);
    my ($tver,$dtargs); # attribs of <Project DefaultTargets="..." ToolVersion=".." ...>
    my ($ltag,$otag,$nxtstag,$tagtype,$attcnt,$idconf,$lnnbcmd,$tmp,$idopntag);
    my ($itemlabel,$pglabel,$inprojcfg,$incustom,$inmessage,$inprojref,$prjcfg);
    my ($dsp_sub_sub,$confname,$var1,$platform,$cdsub,$pcfginc,$relpath,$conf,$innone);
    my (@arr);
    my ($inprepro,$inrescomp,$RootNamespace);
    # '-fix-rel' ($fix_rel_paths)
    my $fixrel = $fix_rel_paths;
    if (! -d $outd) {
        $fixrel = 0;    # not valid destination for DSP file
    }
    $msg = $curr_file_bom;
    $tmp = ${$rxml}[0];
    $plnn = ${$tmp}[0]; # get first line value
    $txt = '';
    $tag = '';
    $ptag = '';
    $rtag = '';
    $idopntag = '';
    $itemlabel = '';
    $pglabel = '';
    $nxtstag = '';
    $inproj = 0;
    $incommand = 0;
    $command = '';
    $initemgroup = 0;
    $inpropgroup = 0;
    $idefgroup = 0;
    $impgroup = 0;
    $inprojcfg = 0;
    $incustom = 0;
    $inmessage = 0;
    $inprojref = 0;
    $inprepro = 0;
    $inrescomp = 0;
    $innone = 0;
    $prjcfg = '';
    $pcfginc = '';
    $RootNamespace = '';
    $tvers = 'UNKNOWN';
    $val = '*\$val NOT SET*';
    my @sources = ();
    my @tag_stack = ();
    my $rh = get_default_ref_hash($inff); # get the DEFAULT reference HASH - lib_vcscan.pl
    my $rcfgs = get_project_configs($rh);   # 'PROJECT_CFGS'
    #                      just name like 'Release'  full name 'Debug|Win32'
    # prt("[v40] STORE:$tmp: In rcfgs (ra)[$confname], [$var1], [$conf], & \$dsp_sub_sub ] )\n") if ($dbg_v40); # ONLY STORE OF 'PROJECT_CFGS'
    # push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS'
    # ${$rh}{'PROJECT_CCNT'}++;   # count of stored 'PROJECT_CFGS
    # ${$rh}{'CURR_DSUB'} = $dsp_sub_sub;
    ${$rh}{'CURR_DCFG'} = 0;    # no configuration done yet
    ${$rh}{'PROJECT_NAME'} = $vcname;   # always have a NAME, even if it is the project file name
    for ($i = 0; $i < $cnt; $i++) {
        $rtx = ${$rxml}[$i];
        #                0    1    2    3
        #  push(@xlines,[$lnn,$txt,$tag,$dnline]);
        $lnn = ${$rtx}[0];
        $txt = ${$rtx}[1];
        $tag = ${$rtx}[2];
        ${$rh}{'CURR_LNN'} = $lnn;
        ${$rh}{'CURR_TXT'} = $txt;
        ${$rh}{'CURR_TAG'} = $tag;
        if ($lnn != $plnn) {
            $msg .= "\n";
        }
        $msg .= $txt;
        $msg .= $tag;
        if ($inproj) {
            # SETUP
            # ==============================
            #if ($incommand && ($initemgroup || $idefgroup)) {
            if ($incommand) {
                # STAY to complete the command!!!
                $command .= "\n" if ($lnn != $plnn);
                $command .= $txt;
                if ($tag =~ /<\/Command>$/) {
                    $ptag = $rtag;
                    $rth = get_tag_hash($tag,\$rtag);
                    ${$rh}{'CURR_RTH'} = $rth;
                    show_tag_hash($rtag,$rh,$tag,\@tag_stack);
                    $otag = substr($rtag,1);
                    if (@tag_stack) {
                        $ltag = pop @tag_stack;
                        $nxtstag = ((@tag_stack) ? $tag_stack[-1] : "EMPTY STACK");
                        prt("[09] POPPED [$ltag] from tag_stack. nxt [$nxtstag] incommand\n") if ($dbg_09);
                        if ($otag ne $ltag) {
                            prtw("WARNING: $lnn: Got close [$otag], but last on stack is [$ltag]! nxt [$nxtstag]\n file [$inff]\n");
                        }
                    } else {
                        $nxtstag = "EMPTY STACK";
                        prtw("WARNING: $lnn: Got close [$otag], but NONE ON STACK!\n file [$inff]\n");
                    }
                    prt("$lnn: CLOSE tag $otag [$tag] next [$nxtstag]\n") if ($dbg_03);
                    if (VERB9()) {
                        prt("$command\n") if ($dbg_01);
                        $tmp = length($command);
                        prt("$lnn:[v9]: End command bgn=$lnnbcmd, len=$tmp\n");
                    }
                    if ($initemgroup) {
                        prt("[10] $lnn:fall through to UNSET incommnd\n") if ($dbg_10);
                    } else {
                        $command = '';
                        $incommand = 0;   # this done LATER
                        prt("\n[10] $lnn: CLEARED incommnd\n\n") if ($dbg_10);
                    }
                } else {
                    next;
                }
            } else {
                $ptag = $rtag;
                $rth = get_tag_hash($tag,\$rtag);
                ${$rh}{'CURR_RTH'} = $rth;
                show_tag_hash($rtag,$rh,$tag,\@tag_stack);
                $attcnt = scalar keys(%{$rth});  # get attribute COUNT for tag - note for <... /> the '/' is counted
                if (defined ${$rth}{'/'}) {
                    prt("$lnn: COMP tag $rtag [$tag]\n") if ($dbg_03);
                    $tagtype = 0;   # a compete TAG <foo />
                } elsif ($rtag =~ /^\//) {
                    $tagtype = 1;   # a close TAG </foo>
                    $otag = substr($rtag,1);
                    if (@tag_stack) {
                        $ltag = pop @tag_stack;
                        $nxtstag = ((@tag_stack) ? $tag_stack[-1] : "EMPTY STACK");
                        prt("[09] POPPED [$ltag] from tag_stack. nxt [$nxtstag]\n") if ($dbg_09);
                        if ($otag ne $ltag) {
                            prtw("WARNING: $lnn: Got close [$otag], but last on stack is [$ltag]!\n file [$inff]\n");
                        }
                    } else {
                        prtw("WARNING: $lnn: Got close [$otag], but NONE ON STACK!\n file [$inff]\n");
                    }
                    prt("$lnn: CLOSE tag $otag [$tag] next [$nxtstag]\n") if ($dbg_03);
                } elsif ($rtag =~ /\/$/) {
                    # self-closing tag - like <Message/> - do NOT add to stack
                    $tagtype = 0;    # a compete TAG <foo/>
                } else {
                    $opcond = get_rt_value($rh,'Condition');
                    $tagtype = 2;   # an open tag <foo ...>
                    $nxtstag = ((@tag_stack) ? $tag_stack[-1] : "EMPTY STACK");
                    prt("$lnn: OPEN tag $rtag [$tag] prev [$nxtstag]\n") if ($dbg_03);
                    push(@tag_stack,$rtag);
                    prt("[09] ADDED  [$rtag] to tag_statck prev [$nxtstag] itmg=$initemgroup idefg=$idefgroup pgrp=$inpropgroup impgrp=$impgroup\n") if ($dbg_09);
                }
            }
            # ======================================================================
            # after SETUP
            # =======================================================================
            # 1 = ItemGroup
            if ($initemgroup) {
                if ($incommand) {
                    # $command .= "\n" if ($lnn != $plnn);
                    # $command .= $txt;
                    if ($tag =~ /<\/Command>$/) {
                        #if (VERB9()) {
                        #    prt("$command\n") if ($dbg_01);
                        #    prt("$lnn:[v9]: End command\n");
                        #}
                        $command = '';
                        $incommand = 0;
                        prt("\n[10] $lnn: CLEARED incommnd initemgroup\n\n") if ($dbg_10);
                    }
                } else {
                    if ($tag =~ /^<\/ItemGroup>/) {
                        prt("$lnn:[v9]: End ItemGroup\n") if (VERB9());
                        $initemgroup = 0;
                        ${$rh}{'CURR_DCFG'} = 1;
                        if ($itemlabel eq "ProjectConfigurations") {    # no configuration done yet
                            ${$rh}{'CURR_DCFG'} = 1;
                            if (VERB9()) {
                                prt("$lnn: ProjectConfigurations: ");
                                prt("Got ".${$rh}{'PROJECT_CCNT'}." configs.");   # count of stored 'PROJECT_CFGS
                                $rcfgs = get_project_configs($rh);   # 'PROJECT_CFGS'
                                #          short   'Release' full 'Release|Win32'
                                # push(@{$rcfgs}, [ $confname, "", $val, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS'
                                foreach $tmp (@{$rcfgs}) {
                                    prt(" ".${$tmp}[2]);
                                }
                                prt("\n");
                            }
                        }


                    } elsif ($tag =~ /^<Command\W/) {
                        # <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
                        # "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/FG/10/flightgear -BC:/FG/10/flightgear/build --check-stamp-file C:\FG\10\flightgear\build\src\FDM\YASim\CMakeFiles\generate.stamp
                        # if %errorlevel% neq 0 goto :cmEnd
                        $incommand = 1;
                        prt("\n[10] $lnn:initemgroup: SETTING incommnd\n\n") if ($dbg_10);
                        prt("$lnn:[v9]: ItemGroup\n") if (VERB9());
                        $lnnbcmd = $lnn;
                        $command = '';
                    } elsif ($inprojcfg || ($itemlabel eq 'ProjectConfigurations')) {
                        #  <ItemGroup Label="ProjectConfigurations">
                        #    <ProjectConfiguration Include="Debug|Win32">
                        #      <Configuration>Debug</Configuration>
                        #      <Platform>Win32</Platform>
                        #    </ProjectConfiguration>
                        #    <ProjectConfiguration Include="Release|Win32">
                        #      <Configuration>Release</Configuration>
                        #      <Platform>Win32</Platform>
                        #    </ProjectConfiguration>
                        #  </ItemGroup>
                        if ($rtag eq 'ProjectConfiguration') {
                            # <ProjectConfiguration Include="Debug|Win32">
                            $pcfginc = get_rt_value($rh,'Include');
                            $inprojcfg = 1;
                            ${$rh}{'CURR_CONF'} = '';
                            ${$rh}{'CURR_CON1'} = '';
                        } elsif ($rtag eq '/ProjectConfiguration') {
                            $confname = ${$rh}{'CURR_CONF'};    # Configuration
                            $platform = ${$rh}{'CURR_CON1'};    # Platform
                            if ( length($platform) && length($confname) ) {
                                $val = $confname.'|'.$platform;  # join Configuration|Platform
                                $tmp = get_act_config_type($confname);    # test /Release/i and /Debug/i and others
                                $dsp_sub_sub = get_default_sub3($tmp);
                                $rcfgs = get_project_configs($rh);   # 'PROJECT_CFGS'
                                #         short   'Release' full 'Release|Win32'
                                push(@{$rcfgs}, [ $confname, "", $val, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS'
                                ${$rh}{'PROJECT_CCNT'}++;   # count of stored 'PROJECT_CFGS
                                ${$rh}{'CURR_DSUB'} = $dsp_sub_sub;
                                prtw("WARNING: ProjectCOnfiguration Include=$pcfginc NOT EQUAL merge [$val]!\n") if ($pcfginc ne $val);
                                if (VERB5() || $dbg_05) {
                                    prt("$lnn: [v5] STORED:$tmp:".${$rh}{'PROJECT_CCNT'}.": ");
                                    prt("[[$confname], [], [$val], \$dsp_sub_sub ] cmp [$pcfginc]\n");
                                }
                            } else {
                                prtw("WARNING: $lnn: CONFIG NOT CREATED! WHY? [$tag]\n");
                            }
                            $inprojcfg = 0;
                        } elsif (($rtag eq 'Configuration')||($rtag eq 'Platform')) {
                            # entering...
                        } elsif ($rtag eq '/Configuration') {
                            ${$rh}{'CURR_CONF'} = $txt;
                        } elsif ($rtag eq '/Platform') {
                            ${$rh}{'CURR_CON1'} = $txt;
                        } else {
                            prtw("WARNING: $lnn:ItemGroup: tag text $val = $txt NOT HANDLED! FIX ME\n");
                        }
                    } elsif (($tag =~ /^<ClCompile\W/) || ($tag =~ /^<ClInclude\W/) || ($tag =~ /^<ResourceCompile\W/)) {
                        # <ClCompile Include="C:\Projects\zlib-1.2.6\zutil.c" />
                        # <ClInclude Include="C:\Projects\zlib-1.2.6\temp\zconf.h" />
                        # <ResourceCompile Include="C:\Projects\zlib-1.2.6\win32\zlib1.rc" />
                        $val = get_rt_value($rh,'Include');
                        if (length($val)) {
                            ####$last_src = strip_dotrel(strip_quotes(trim_all($var1)));
                            my ($last_src,$last_nm,$last_dir,$last_ext,$fname,$flist,$src_ref,$ok,$ff);
                            $last_src = $val;
                            if ($val =~ /^\w{1}:/) {
                                $ff = $val;
                            } else {
                                $ff = $vcdir;
                                $ff .= $PATH_SEP if (!($ff =~ /(\\|\/)$/));
                                $ff .= $val;
                            }
                            $ff = path_u2d($ff);
                            $ff = fix_rel_path($ff);
                            $ok = 'NF';
                            $ok = 'ok' if (-f $ff);
                            # Prior to MSVC10 this was a RELATIVE PATH - like
                            # <File RelativePath="..\..\..\include\AL\alut.h">
                            # this is the RELATIVE PATH - relative to the vcproj file being scanned
                            # Now would be a good time to ADJUST this PATH, for any NEW location
                            # of the final DSP file!!! BUT, this is done back in vcproj05.pl
                            # in the sub chk_relative_paths()...
                            # BUT in MSVC10 this 'can' be an absolute path, like 
                            # C:\FG\10\flightgear\src\FDM\YASim\Wing.cpp
                            # =========================
                            if ($fixrel) {
                                my $cd = cwd();
                                # prt("Last source [$last_src]\n");
                                if ( ( -d $outd ) && chdir($outd) ) {
                                    $last_src = File::Spec->rel2abs($last_src);    # we are IN the SLN directory, get ABSOLUTE from RELATIVE
                                    chdir($cd); # and get us back to where we were...
                                }
                            }
                            ($last_nm,$last_dir,$last_ext) = fileparse( $last_src, qr/\.[^.]*/ );
                            # =========================
                            if ($fixrel) {
                                $relpath = get_relative_path4($last_dir,$outd);
                                $last_src = $relpath.$last_nm.$last_ext;
                            }
                            $fname = '<none>';
                            $flist = '<none>';
                            $src_ref = get_project_srcs_ref($rh); # 'PROJECT_SRCS'
                            ${$rh}{'CURR_LOFF'} = scalar @{$src_ref};   # get current source OFFSET
                            # *** STORING SOURCE ***
                            push(@{$src_ref}, [ $last_src, $fname, $flist, 0, '' ]); # and PUSH onto SOURCE stack
                            ${$rh}{'CURR_LSRC'} = $last_src;
                            ${$rh}{'CURR_LNME'} = $last_nm;
                            ${$rh}{'CURR_LDIR'} = $last_dir;
                            ${$rh}{'CURR_LEXT'} = $last_ext;
                            prt("$lnn: SOURCE: [$last_src] [$val] $ok\n");
                            push(@sources,[$last_src,$val]);
                        } else {
                            prtw("WARNING: $lnn: No Include [$tag] CHECKME\n");
                        }
                    } else {
                        $show = 0;
                        if ($rtag eq 'CustomBuild') {
                            $incustom = 1;
                        } elsif ($rtag eq '/CustomBuild') {
                            $incustom = 0;
                        } elsif ($rtag eq 'Message') {
                            $inmessage = 1;
                        } elsif ($rtag eq '/Message') {
                            $inmessage = 0;
                        } elsif ($rtag eq 'ProjectReference') {
                            $inprojref = 1;
                        } elsif ($rtag eq '/ProjectReference') {
                            $inprojref = 0;
                        } elsif ($rtag eq 'PreprocessorDefinitions') {
                            $inprepro = 1;
                        } elsif ($rtag eq '/PreprocessorDefinitions') {
                            $inprepro = 0;
                        } elsif ($rtag eq 'ResourceCompile') {
                            $inrescomp = 1;
                        } elsif ($rtag eq '/ResourceCompile') {
                            $inrescomp = 0;
                        } elsif (($rtag eq 'None') && ($tagtype == 0)) {
                            $innone++;
                        } else {
                            if ($incustom || $inmessage || $inprojref || $inprepro || $inrescomp) {
                                if ($rtag =~ /^\//) {
                                    $val = substr($rtag,1);
                                    prt("$lnn:[v9] ItemGroup: tag text $val = $txt\n") if (VERB9());
                                    if ($incustom) {
                                        # already collecting the command
                                    } elsif ($inmessage) {
                                        # nothing special here
                                    } elsif ($inprojref) {
                                        # nothing special here
                                    } elsif ($inprepro) {
                                        # like NDEBUG;$(NoInherit));%(PreprocessorDefinitions)
                                        # or   _DEBUG;$(NoInherit));%(PreprocessorDefinitions)
                                    } elsif ($inrescomp) {
                                        # compiling a rc file
                                    } else {
                                        prgm_exit(1,"ERROR: $lnn: ItemGroup type NOT HANDLED! [$tag]\n");
                                    }
                                }
                            } else {
                                prtw("WARNING: $lnn: ItemGroup: NOT in conf [$rtag] [$txt] FIX ME!\n file [$inff]\n");
                            }
                        }
                    }
                }
            # 2 - PropertyGroup
            } elsif ($inpropgroup) {
                if ($tag =~ /^<\/PropertyGroup>/) {
                    prt("$lnn:[v9]: End PropertyGroup\n") if (VERB9());
                    $inpropgroup = 0;
                } else {
                    #    <PropertyGroup>
                    #      <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
                    #      <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\FG\10\flightgear\build\src\FDM\YASim\Debug\</OutDir>
                    #      <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">yasim-proptest.dir\Debug\</IntDir>
                    #      <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">yasim-proptest</TargetName>
                    #      <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
                    #      <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
                    #      <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
                    #      <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\FG\10\flightgear\build\src\FDM\YASim\Release\</OutDir>
                    #      <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">yasim-proptest.dir\Release\</IntDir>
                    #      <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">yasim-proptest</TargetName>
                    #      <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
                    #      <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
                    #      <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
                    #    </PropertyGroup>
                    #  <PropertyGroup Label="Globals">
                    #    <ProjectGUID>{DADB5FFC-3724-4318-BC6E-1DE2291A71F2}</ProjectGUID>
                    #    <Keyword>Win32Proj</Keyword>
                    #    <Platform>Win32</Platform>
                    #    <ProjectName>yasim-proptest</ProjectName>
                    #  </PropertyGroup>
                    $show = 0;
                    if ($rtag =~ /^\//) {
                        # on CLOSING tag, get TEXT
                        if ($pglabel eq 'Globals') {
                            if (($rtag eq '/ProjectGUID')||($rtag eq '/ProjectGuid')) {
                                $show = 1;
                            } elsif ($rtag eq '/Keyword') {
                                $show = 1;
                            } elsif ($rtag eq '/Platform') {
                                $show = 1;
                            } elsif ($rtag eq '/ProjectName') {
                                ${$rh}{'PROJECT_NAME'} = $txt;
                                $show = 1;
                            } elsif ($rtag eq '/RootNamespace') {
                                $show = 1;
                                $RootNamespace = $txt;
                            }
                        } else {
                            if ($rtag eq '/_ProjectFileVersion') {
                                $show = 1;
                            } elsif ($rtag eq '/OutDir') {
                                # -NEW_OUTD-
                                ${$rh}{'CURR_ODIR'} = $txt;
                                $dsp_sub_sub = ${$rh}{'CURR_DSUB'};
                                if (defined ${$dsp_sub_sub}{'-NEW_OUTD-'}) {
                                    ${$dsp_sub_sub}{'-NEW_OUTD-'} = add_quotes($txt) if (length($txt));
                                } else {
                                    prtw("WARNING: current \$dsp_sub_sub does not have '-NEW_OUTD-'!\n");
                                }
                                $show = 1;
                            } elsif ($rtag eq '/IntDir') {
                                # -NEW_INTER-
                                $dsp_sub_sub = ${$rh}{'CURR_DSUB'};
                                if (defined ${$dsp_sub_sub}{'-NEW_INTER-'}) {
                                    ${$dsp_sub_sub}{'-NEW_INTER-'} = add_quotes($txt) if (length($txt));
                                } else {
                                    prtw("WARNING: current \$dsp_sub_sub does not have '-NEW_INTER-'!\n");
                                }
                                $show = 1;
                            } elsif ($rtag eq '/TargetName') {
                                ${$rh}{'CURR_TNAME'} = $txt;
                                $show = 1;
                            } elsif ($rtag eq '/TargetExt') {
                                # adds a BIG clue to the project TYPE
                                # dll = DLL
                                # lib = LIB (static)
                                # exe = console or windows type
                                ${$rh}{'CURR_TEXT'} = $txt;
                                $show = 1;
                            } elsif ($rtag eq '/LinkIncremental') {
                                $show = 1;
                            } elsif ($rtag eq '/GenerateManifest') {
                                $show = 1;
                            } elsif ($rtag eq '/CharacterSet') {
                                $show = 1;
                            } elsif ($rtag eq '/ConfigurationType') {
                                set_configuration_type($rh,$txt);
                                $show = 1;
                            } elsif ($rtag eq '/UseOfMfc') {
                                $show = 1;
                            } elsif ($rtag eq '/WholeProgramOptimization') {
                                $show = 1;
                            }
                        }
                        if ($show) {
                            $val = substr($rtag,1);
                            prt("[v9] $lnn: Property: $pglabel: $val = [$txt], cond pg [$pgcond] oc [$opcond]\n") if (VERB9() || $dbg_07);
                        } elsif ($rtag =~ /^\//) {
                            prtw("WARNING: $lnn: $pglabel: Unmanaged PropertyGroup [$rtag] [$txt]\n file [$inff]\n");
                        }
                        if (defined ${$rh}{'CURR_ODIR'} && defined ${$rh}{'CURR_TNAME'} && defined ${$rh}{'CURR_TEXT'}) {
                            if (length(${$rh}{'CURR_ODIR'}) && length(${$rh}{'CURR_TNAME'}) && length(${$rh}{'CURR_TEXT'}) ) {
                                $tmp = ${$rh}{'CURR_ODIR'};
                                $tmp .= $PATH_SEP if (!($tmp =~ /(\\|\/)$/));
                                $tmp .= ${$rh}{'CURR_TNAME'};
                                $tmp .= ${$rh}{'CURR_TEXT'};
                                $conf = ${$rh}{'CURR_CFG'};
                                $dsp_sub_sub = ${$rh}{'CURR_DSUB'};
                                ${$dsp_sub_sub}{'-NEW_OUT-'} = $tmp;
                                prt("[v5] SET: -NEW_OUT-: cfg [$conf] with [$tmp]\n") if (VERB5());
                            }
                        }
                    }
                }
            } elsif ($idefgroup) {
                if ($tag =~ /<\/ItemDefinitionGroup>/) {
                    $idefgroup = 0;
                    prt("$lnn:[v9]: End   ItemDefinitionGroup\n") if (VERB9());
                    $idopntag = ''; # clear the OPEN tag group
                } elsif ($tag =~ /^<Command\W/) {
                    $incommand = 1;
                    prt("\n[10] $lnn:idefgroup: SETTING incommnd\n\n") if ($dbg_10);
                    prt("$lnn:[v9]: Start command ItemDefinitionGroup [$tag] nxt [$nxtstag]\n") if (VERB9());
                    $lnnbcmd = $lnn;
                    $command = '';
                } else {
                    #  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
                    #    <ClCompile>
                    #      <AdditionalOptions> /Zm1000 %(AdditionalOptions)</AdditionalOptions>
                    #      <AdditionalIncludeDirectories>C:/FG/10/3rdparty/include;C:/FG/10/Boost-1.49;C:/FG/10/3rdparty/3rdParty/include;C:/FG/10/flightgear/src;C:/FG/10/flightgear/build/src;C:/FG/10/flightgear/build/src/Include;C:/FG/10/flightgear;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
                    #      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
                    #      <CompileAs>CompileAsCpp</CompileAs>
                    #      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
                    #      <ExceptionHandling>Sync</ExceptionHandling>
                    #      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
                    #      <Optimization>Disabled</Optimization>
                    #      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
                    #      <RuntimeTypeInfo>true</RuntimeTypeInfo>
                    #      <WarningLevel>Level3</WarningLevel>
                    #      <PreprocessorDefinitions>WIN32;_WINDOWS;NOMINMAX;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;__CRT_NONSTDC_NO_WARNINGS;_REENTRANT;_DEBUG;HAVE_CONFIG_H;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
                    #      <AssemblerListingLocation>Debug</AssemblerListingLocation>
                    #      <ObjectFileName>$(IntDir)</ObjectFileName>
                    #      <ProgramDataBaseFileName>C:/FG/10/flightgear/build/src/FDM/YASim/Debug/yasim-proptest.pdb</ProgramDataBaseFileName>
                    #    </ClCompile>
                    #    <ResourceCompile>
                    #      <PreprocessorDefinitions>WIN32;_WINDOWS;NOMINMAX;_USE_MATH_DEFINES;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;__CRT_NONSTDC_NO_WARNINGS;_REENTRANT;_DEBUG;HAVE_CONFIG_H;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
                    #      <AdditionalIncludeDirectories>C:/FG/10/3rdparty/include;C:/FG/10/Boost-1.49;C:/FG/10/3rdparty/3rdParty/include;C:/FG/10/flightgear/src;C:/FG/10/flightgear/build/src;C:/FG/10/flightgear/build/src/Include;C:/FG/10/flightgear;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
                    #    </ResourceCompile>
                    #    <Midl>
                    #      <AdditionalIncludeDirectories>C:/FG/10/3rdparty/include;C:/FG/10/Boost-1.49;C:/FG/10/3rdparty/3rdParty/include;C:/FG/10/flightgear/src;C:/FG/10/flightgear/build/src;C:/FG/10/flightgear/build/src/Include;C:/FG/10/flightgear;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
                    #      <OutputDirectory>$(IntDir)</OutputDirectory>
                    #      <HeaderFileName>%(Filename).h</HeaderFileName>
                    #      <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
                    #      <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
                    #      <ProxyFileName>%(Filename)_p.c</ProxyFileName>
                    #    </Midl>
                    #    <Link>
                    #      <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
                    #      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;C:\FG\10\3rdparty\lib\sgenvironmentd.lib;C:\FG\10\3rdparty\lib\sgnasald.lib;C:\FG\10\3rdparty\lib\sgtsyncd.lib;C:\FG\10\3rdparty\lib\sgbucketd.lib;C:\FG\10\3rdparty\lib\sgrouted.lib;C:\FG\10\3rdparty\lib\sgiod.lib;C:\FG\10\3rdparty\lib\sgseriald.lib;C:\FG\10\3rdparty\lib\sgmathd.lib;C:\FG\10\3rdparty\lib\sgpropsd.lib;C:\FG\10\3rdparty\lib\sgstructured.lib;C:\FG\10\3rdparty\lib\sgtimingd.lib;C:\FG\10\3rdparty\lib\sgxmld.lib;C:\FG\10\3rdparty\lib\sgmiscd.lib;C:\FG\10\3rdparty\lib\sgthreadsd.lib;C:\FG\10\3rdparty\lib\sgdebugd.lib;C:\FG\10\3rdparty\lib\sgmagvard.lib;C:\FG\10\3rdparty\lib\zlib1.lib;winmm.lib;ws2_32.lib</AdditionalDependencies>
                    #      <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
                    #      <ForceFileOutput>MultiplyDefinedSymbolOnly</ForceFileOutput>
                    #      <GenerateDebugInformation>true</GenerateDebugInformation>
                    #      <ImportLibrary>C:/FG/10/flightgear/build/src/FDM/YASim/Debug/yasim-proptest.lib</ImportLibrary>
                    #      <LinkIncremental>true</LinkIncremental>
                    #      <ProgramDataBaseFileName>C:/FG/10/flightgear/build/src/FDM/YASim/Debug/yasim-proptest.pdb</ProgramDataBaseFileName>
                    #      <StackReserveSize>10000000</StackReserveSize>
                    #      <SubSystem>Console</SubSystem>
                    #      <Version></Version>
                    #    </Link>
                    #    <ProjectReference>
                    #      <LinkLibraryDependencies>false</LinkLibraryDependencies>
                    #    </ProjectReference>
                    #    <PostBuildEvent>
                    #      <Message></Message>
                    #      <Command>setlocal
                    #"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
                    #if %errorlevel% neq 0 goto :cmEnd
                    #:cmEnd
                    #endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone
                    #:cmErrorLevel
                    #exit /b %1
                    #:cmDone
                    #if %errorlevel% neq 0 goto :VCEnd</Command>
                    #    </PostBuildEvent>
                    #  </ItemDefinitionGroup>
                    if ($tagtype == 1) {   # a close TAG </foo>
                        $show = 0;
                        if ($nxtstag eq 'ClCompile') {
                            if ($rtag eq '/AdditionalOptions') {
                                $show = 1;
                            } elsif ($rtag eq '/AdditionalIncludeDirectories') {
                                # $seek = 'AdditionalIncludeDirectories'; # -NEW_INCS_[DBG|REL]-
                                # sub get_default_sub3(0=rel,1=debug) {
                                merge_inc_directories($rh,$txt);
                                $show = 1;
                            } elsif ($rtag eq '/BasicRuntimeChecks') {
                                $show = 1;
                            } elsif ($rtag eq '/CompileAs') {
                                $show = 1;
                            } elsif ($rtag eq '/DebugInformationFormat') {
                                $show = 1;
                            } elsif ($rtag eq '/ExceptionHandling') {
                                $show = 1;
                            } elsif ($rtag eq '/InlineFunctionExpansion') {
                                $show = 1;
                            } elsif ($rtag eq '/Optimization') {
                                $show = 1;
                            } elsif ($rtag eq '/RuntimeLibrary') {
                                # 92: ItemDef: ClCompile: RuntimeLibrary = [MultiThreadedDebugDLL], cond idg [CONFIG=Debug|Win32] op [] -NEW_RT-
                                set_runtime_library($rh,$txt);
                                $show = 1;
                            } elsif ($rtag eq '/RuntimeTypeInfo') {
                                $show = 1;
                            } elsif ($rtag eq '/WarningLevel') {
                                $show = 1;
                            } elsif ($rtag eq '/PreprocessorDefinitions') {
                                # 94: ItemDef: ClCompile: PreprocessorDefinitions = [WIN32;_WINDOWS;_DEBUG;PNG_CONFIGURE_LIBPNG;_CRT_SECURE_NO_DEPRECATE;CMAKE_INTDIR="Debug";PNG_BUILD_DLL;%(PreprocessorDefinitions)], cond idg [CONFIG=Debug|Win32] op [] -NEW_DEFS-
                                set_preprocessor_defines($rh,$txt);
                                $show = 1;
                            } elsif ($rtag eq '/AssemblerListingLocation') {
                                $show = 1;
                            } elsif ($rtag eq '/ObjectFileName') {
                                $show = 1;
                            } elsif ($rtag eq '/ProgramDataBaseFileName') {
                                $show = 1;
                            } elsif ($rtag eq '/FunctionLevelLinking') {
                                # <FunctionLevelLinking>false</FunctionLevelLinking>
                                $show = 1;
                            } elsif ($rtag eq '/SuppressStartupBanner') {
                                $show = 1;
                            } elsif ($rtag eq '/MinimalRebuild') {
                                $show = 1;
                            } elsif ($rtag eq '/PrecompiledHeaderOutputFile') {
                                $show = 1;
                            } elsif ($rtag eq '/PrecompiledHeader') {
                                $show = 1;
                            } elsif ($rtag eq '/StringPooling') {
                                $show = 1;
                            } elsif ($rtag eq '/DisableSpecificWarnings') {
                                # like <DisableSpecificWarnings>4996;4013;4018;4024;4047;4244</DisableSpecificWarnings>
                                $show = 1;
                            } else {
                                prtw("WARNING: $lnn: Uncased 'ClCompile' [$tag] FIX ME!\n");
                            }
                        } elsif ($nxtstag eq 'ResourceCompile') {
                            if ($rtag eq '/PreprocessorDefinitions') {
                                # <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
                                $show = 1;
                            } elsif ($rtag eq '/AdditionalIncludeDirectories') {
                                $show = 1;
                            } elsif ($rtag eq '/Culture') {
                                # <Culture>0x0809</Culture>
                                $show = 1;
                            } else {
                                prtw("WARNING: $lnn: Uncased 'ResourceCompile' [$tag] FIX ME!\n");
                            }
                        } elsif ($nxtstag eq 'Midl') {
                            if ($rtag eq '/AdditionalIncludeDirectories') {
                                $show = 1;
                            } elsif ($rtag eq '/OutputDirectory') {
                                $show = 1;
                            } elsif ($rtag eq '/HeaderFileName') {
                                $show = 1;
                            } elsif ($rtag eq '/TypeLibraryName') {
                                $show = 1;
                            } elsif ($rtag eq '/InterfaceIdentifierFileName') {
                                $show = 1;
                            } elsif ($rtag eq '/ProxyFileName') {
                                $show = 1;
                            } else {
                                prtw("WARNING: $lnn: Uncased 'Midl' [$tag] FIX ME!\n");
                            }
                        } elsif ($nxtstag eq 'Link') {
                            if ($rtag eq '/AdditionalOptions') {
                                $show = 1;
                            } elsif ($rtag eq '/AdditionalDependencies') {
                                # like elsif ($pname eq 'VCLinkerTool')
                                $var1 = '-NEW_LIBS-';
                                # get the list, and add need libraries
                                #       <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;C:\FG\10\3rdparty\lib\sgenvironmentd.lib;C:\FG\10\3rdparty\lib\sgnasald.lib;C:\FG\10\3rdparty\lib\sgtsyncd.lib;C:\FG\10\3rdparty\lib\sgbucketd.lib;C:\FG\10\3rdparty\lib\sgrouted.lib;C:\FG\10\3rdparty\lib\sgiod.lib;C:\FG\10\3rdparty\lib\sgseriald.lib;C:\FG\10\3rdparty\lib\sgmathd.lib;C:\FG\10\3rdparty\lib\sgpropsd.lib;C:\FG\10\3rdparty\lib\sgstructured.lib;C:\FG\10\3rdparty\lib\sgtimingd.lib;C:\FG\10\3rdparty\lib\sgxmld.lib;C:\FG\10\3rdparty\lib\sgmiscd.lib;C:\FG\10\3rdparty\lib\sgthreadsd.lib;C:\FG\10\3rdparty\lib\sgdebugd.lib;C:\FG\10\3rdparty\lib\sgmagvard.lib;C:\FG\10\3rdparty\lib\zlib1.lib;winmm.lib;ws2_32.lib</AdditionalDependencies>
                                @arr = split(";",$txt);
                                my %liblist = ();
                                my %dirs = ();
                                foreach $tmp (@arr) {
                                    if ($tmp =~ /\.lib$/i) {
                                        my ($n,$d) = fileparse($tmp);
                                        $d = '' if ($d =~ /^\.(\\|\/)$/);
                                        if (is_system_lib($n)) {
                                            # we know about these
                                        } else {
                                            $liblist{$n} = 1;
                                            $dirs{$d} = 1 if (length($d));
                                        }
                                    } elsif ($tmp eq '%(AdditionalDependencies)') {
                                        # ignore this
                                    } else {
                                        prtw("WARNING: $lnn: AdditionalDependencies: This is NOT .lib WHAT is IT? [$tmp]\n");
                                    }
                                }
                                @arr = sort keys(%liblist);
                                $tmp = scalar @arr;
                                $val = (@arr) ? join(" ",@arr) : '';
                                if (@arr && VERB5()) {
                                    prt("[v5] $lnn: LIBRARIES: AdditionalDependencies: Got $tmp additional libraries [$val]\n");
                                }
                                @arr = keys %dirs;
                                $tmp =scalar @arr;
                                if (@arr && VERB5()) {
                                    prt("[v5] $lnn: LIBDIRS: AdditionalDependencies: In $tmp dirs [".join(" ",@arr)."]\n");
                                }
                                ${$rh}{'CURR_LIBS'} = \%liblist;
                                ${$rh}{'CURR_LDIRS'} = \%dirs;
                                merge_library_list($rh);
                                $show = 1;
                            } elsif ($rtag eq '/AdditionalLibraryDirectories') {
                                $show = 1;
                            } elsif ($rtag eq '/ForceFileOutput') {
                                $show = 1;
                            } elsif ($rtag eq '/GenerateDebugInformation') {
                                $show = 1;
                            } elsif ($rtag eq '/ImportLibrary') {
                                $show = 1;
                            } elsif ($rtag eq '/LinkIncremental') {
                                $show = 1;
                            } elsif ($rtag eq '/ProgramDataBaseFileName') {
                                $show = 1;
                            } elsif ($rtag eq '/StackReserveSize') {
                                $show = 1;
                            } elsif ($rtag eq '/SubSystem') {
                                if ($txt =~ /Console/i) {
                                    if (defined ${$rh}{'PROJECT_APTP'}) {
                                        $val = ${$rh}{'PROJECT_APTP'};
                                        if ($val eq 'Application') {
                                            ${$rh}{'PROJECT_APTP'} = 'Console Application';
                                            prt("$lnn: SubSystem: Console: Changes App Type to 'Console Application'\n");
                                        }
                                    } else {
                                        ${$rh}{'PROJECT_APTP'} = 'Console Application';
                                    }
                                } elsif ($txt =~ /Windows/i) {
                                    if (defined ${$rh}{'PROJECT_APTP'}) {
                                        $val = ${$rh}{'PROJECT_APTP'};
                                        if ($val ne 'Application') {
                                            ${$rh}{'PROJECT_APTP'} = 'Application';
                                            prt("$lnn: SubSystem: Windows: Changes App Type from [$val] to 'Application'\n");
                                        }
                                    } else {
                                        ${$rh}{'PROJECT_APTP'} = 'Application';
                                    }
                                } else {
                                    prtw("WARNING: $lnn: 'SubSystem' NOT 'Console'! IS [$txt]! FIX ME\n");
                                }
                                $show = 1;
                            } elsif ($rtag eq '/Version') {
                                $show = 1;
                            } elsif ($rtag eq '/SuppressStartupBanner') {
                                $show = 1;
                            } elsif ($rtag eq '/OutputFile') {
                                $show = 1;
                            } elsif ($rtag eq '/ModuleDefinitionFile') {
                                $show = 1;
                            } elsif ($rtag eq '/TargetMachine') {
                                $show = 1;
                            } elsif ($rtag eq '/OptimizeReferences') {
                                $show = 1;
                            } elsif ($rtag eq '/EnableCOMDATFolding') {
                                $show = 1;
                            } else {
                                prtw("WARNING: $lnn: Uncased 'Link' [$tag] [$txt] FIX ME!\n");
                            }
                        } elsif ($nxtstag eq 'ProjectReference') {
                            if ($rtag eq '/LinkLibraryDependencies') {
                                $show = 1;
                            } else {
                                prtw("WARNING: $lnn: Uncased 'ProjectReference' [$tag] FIX ME!\n");
                            }
                        } elsif ($nxtstag eq 'ItemDefinitionGroup') {
                            # close of group
                        } elsif ($nxtstag eq 'PostBuildEvent') {
                            # close a postbuildevent
                        } elsif ($nxtstag eq 'Bscmake') {
                            #    <Bscmake
                            #      <SuppressStartupBanner>true</SuppressStartupBanner>
                            #      <OutputFile>.\Debug\test_static\test_static.bsc</OutputFile>
                            #    </Bscmake>
                        } elsif ($nxtstag eq 'Lib') {
                            #    <Lib>
                            #      <SuppressStartupBanner>true</SuppressStartupBanner>
                            #      <OutputFile>.\Debug\test_static\test_static.lib</OutputFile>
                            #    </Lib>
                        } elsif ($nxtstag eq 'Message') {
                            # ???
                        } elsif ($nxtstag eq 'CustomBuildStep') {
                            # ???
                        } else {
                            prtw("WARNING: $lnn: ItemDefinitionGroup: Uncased Next [$nxtstag] curr tag [$tag] FIX ME!\n file [$inff]\n");
                        }
                        if ($show) {
                            $val = substr($rtag,1);
                            prt("[v9] $lnn: ItemDef: nxt $nxtstag: $val = [$txt], cond idg [$idconf] op [$opcond]\n") if (VERB9() || $dbg_08);
                        #} elsif ($rtag =~ /^\//) {
                        #    prtw("WARNING: $lnn: Unmanaged PropertyGroup [$rtag] [$txt]\n");
                        }
                    } elsif ($tagtype == 2) {
                        if (($nxtstag ne 'ItemDefinitionGroup') && ($nxtstag ne $idopntag)) {
                            #      <Message></Message>
                            #if ($ntag eq 'Command') { # like =~ /^<Command\W/) {
                            #if ($tag =~ /^<Command\W/) {
                            #    $incommand = 1;
                            #    prt("\n[10] $lnn:ideefgroup: SETTING incommnd\n\n") if ($dbg_10);
                            #    prt("$lnn:[v9]: Start command ItemDefinitionGroup [$tag] nxt [$nxtstag]\n") if (VERB9());
                            #    $lnnbcmd = $lnn;
                            #    $command = '';
                            #} else {
                                $idopntag = $nxtstag;
                                prt("$lnn:[v9]: ItemDefintionGroup: Open tag [$tag] nxt [$nxtstag]\n") if (VERB9());
                            #}
                        }
                    }
                }
            } elsif ($impgroup) {
                if ($tag =~ /<\/ImportGroup>/) {
                    prt("$lnn:[v9]: End  ImportGroup\n") if (VERB9());
                    $impgroup = 0;
                }
            } elsif (length($tag)) {
                if ($tag =~ /^<Command\W/) {
                    # <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
                    # "C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -HC:/FG/10/flightgear -BC:/FG/10/flightgear/build --check-stamp-file C:\FG\10\flightgear\build\src\FDM\YASim\CMakeFiles\generate.stamp
                    # if %errorlevel% neq 0 goto :cmEnd
                    $incommand = 1;
                    prt("\n[10] $lnn:outsied ItemGroup: SETTING incommnd\n\n") if ($dbg_10);
                    #prt("$lnn:[v9]: Start command\n") if (VERB9());
                    prtw("WARNING: $lnn: Start command OUTSIDE ItemGroup!\n"); # should NOT happen
                    $command = '';
                } elsif ($tag =~ /^<ItemGroup\W/) {
                    # <ItemGroup Label="ProjectConfigurations">
                    $itemlabel = get_rt_value($rh,'Label');
                    prt("$lnn:[v9]: Start ItemGroup $itemlabel\n") if (VERB9());
                    $initemgroup = 1;
                } elsif ($tag =~ /^<PropertyGroup\W/) {
                    if ($tag =~ /\/>$/) {
                        prt("$lnn:[v9]: Comp PropertyGroup\n") if (VERB9());
                    } else {
                        # <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
                        #  <PropertyGroup Label="Globals">
                        $pgcond = get_rt_value($rh,'Condition');
                        $pglabel = get_rt_value($rh,'Label');
                        prt("$lnn:[v9]: Start PropertyGroup [$pgcond] [$pglabel]\n") if (VERB9());
                        $inpropgroup = 1;
                        ${$rh}{'CURR_ODIR'} = '';
                        ${$rh}{'CURR_TNAME'} = '';
                        ${$rh}{'CURR_TEXT'} = '';
                    }
                } elsif ($tag =~ /^<ItemDefinitionGroup\W/) {
                    $val = get_rt_value($rh,'Condition');
                    $idconf = $val;
                    prt("$lnn:[v9]: Start ItemDefinitionGroup $val\n") if (VERB9());
                    $idefgroup = 1;
                } elsif ($tag =~ /^<ImportGroup\W/) {
                    prt("$lnn:[v9]: Start ImportGroup\n") if (VERB9());
                    $impgroup = 1;
                } elsif ($tag =~ /^<\/Project>$/) {
                    $inproj = 0;
                    prt("$lnn:[v9]: End project\n") if (VERB9());
                } elsif (($tag =~ /^<Import\W/) && ($tag =~ /\/>$/)) {
                    #  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
                } else {
                    prtw("WARNING:$lnn: Tag not handled: [$tag]\n");
                }
            }
        } else {
            # <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
            if ($tag =~ /^<Project\W/) {
                $rth = get_tag_hash($tag,\$rtag);
                ${$rh}{'CURR_RTH'} = $rth;
                $tver = get_rt_value($rh,'ToolsVersion');
                $dtargs = get_rt_value($rh,'DefaultTargets');
                $inproj = 1;
                prt("$lnn:[v9]: Start project DefaultTargets [$dtargs] ToolsVersion [$tver] \n") if (VERB9());
                push(@tag_stack,$rtag);
                prt("[09] ADDED  [$rtag] to tag_statck\n") if ($dbg_09);
            }
        }
        $plnn = $lnn;
    }
    $msg .= "\n";
    if (@tag_stack) {
        $val = scalar @tag_stack;
        prtw("WARNING: Ended lines with $val [".join(" ",@tag_stack)."] still on TAG STACK!\n");
    }
    return $rh;
}

sub my_sub_common_folder {
    my ($fil,$root) = @_;
    my $lfil = lc(path_u2d($fil));
    my $lrot = lc(path_u2d($root));
    my $len1 = length($lfil);
    my $len2 = length($lrot);
    my ($i);
    for ($i = 0; (($i < $len1)&&($i < $len2)); $i++) {
        if (substr($lfil,$i,1) ne substr($lrot,$i,1)) {
            last;
        }
    }
    return substr($fil,$i);
}


sub process_vcxproj_file($$) {
    my ($ff, $outd) = @_;
    my ($name,$dir) = fileparse($ff);
    my @lines = ();
    my $lncnt = load_file_lines($ff,\@lines);
    my $snf = my_sub_common_folder($ff,$commdir);
    prt("\nLoaded $lncnt lines, from [$snf]\n");
    #prt("\nLoaded $lncnt lines, from $ff\n");
    my $rxml = get_xml_ref_array($ff,\@lines);
    # write_xml_lines($ff,$rxml); # JUST FOR DEBUG - should be EXACTLY the same!!!
    my $rh = process_rxml_vcxproj($ff,$rxml,$outd);
    # like  adjust_output_name($rh) if ($adj_out); here add a POST event
    # TODO add_post_copy($rh) if ($adj_out);
    ${$rh}{'PROJECT_ROOT'} = $dir;
    ${$rh}{'PROJECT_AM_FILE'} = $name;
    show_hash_results3($rh) if (VERB5());
    my $app = '';
    if (defined ${$rh}{'PROJECT_APTP'}) {
        $app = ${$rh}{'PROJECT_APTP'};
    }
    if (length($app) == 0) {
        prt("No DSP written due no app type found!\n");
        return $rh;
    }
    if ($app eq 'Utility') {
        prt("No DSP written for a 'Utility' type app!\n");
        return $rh;
    }
    my $out = $perl_base."\\temp.$name.dsp";
    if ($write_dsp) {
        prt("Doing write_hash_to_DSP3 $out (debug=$dbg4write)\n") if (VERB9());
        # set_only_win32_conf(0);
        if ( write_hash_to_DSP3( $out, $rh, $dbg4write ) ) {
            prt("Written [$out]\n");
        } else {
            prt("FAILED to write any DSP files!\n");
        }
    } else {
        prt("No DSP written. Use -dsp[:fil] to enable.\n");
    }
    my $key = '-NEW_PROJECT_NAME-';
    my $proj_name = "NO PROJECT NAME!";
    $key = 'PROJECT_NAME' if (!defined ${$rh}{$key});
    if (defined ${$rh}{$key}) {
        $proj_name = ${$rh}{$key};    # get the PROJECT NAME
    }
    if (do_hash_cmake_test($rh)) {
        prtw("WARNING: PROJECT $proj_name $app FAILED CMAKE HASH TEST!\n");
    } else {
        my $rcph = get_cmake_proj_hash_ref(); # = return \@g_cmake_proj_hashes; 
        push(@{$rcph},$rh);
        prt("For $proj_name $app stored ref hash.\n");
    }

    return $rh;
}

sub write_cmake_output() {
    if (get_write_cmake_files()) {
        if (!defined ${$rparams}{'AM_EXCLUDED_DIRS'}) {
            my %excluded = ();
            my $rex = \%excluded;
            ${$rparams}{'AM_EXCLUDED_DIRS'} = $rex;
        }
        #my $rparams = get_ref_params();
        # need to set
        #    my $rex = ${$rparams}{'AM_EXCLUDED_DIRS'}; # get stored EXCLUDED directory HASH (if any!)
        #    my $proj_root = ${$rparams}{'ROOT_FOLDER'};
        #    my $proj_title = ${$rparams}{'PROJECT_NAME_MASTER'};
        #    my $rprojsh = ${$rparams}{'REF_PROJECTS_HASH'};
        #    my $rlib_lists = ${$rparams}{'REF_LIB_LISTS'};  # make list of LIBRARIES written
        if (write_project_cmake_files($rparams)) {
            prt("Write CMAKE FAILED!\n");
        }
    } else {
        prt("Write CMAKE is disabled! Use -cmake:dir to enable.\n");
    }
}


# ==========================================================
# MAIN
############################################################
my $args_ref = parse_args(@ARGV);
foreach $in_file (@{$args_ref}) {
    prt("[v9] Processing file [$in_file]...\n") if (VERB9());
    if (is_vcxproj_ext($in_file)) {
        process_vcxproj_file($in_file, $out_dsp_dir);
    } elsif (is_vcproj_ext($in_file)) {
        process_vcproj_file($in_file, $out_dsp_dir);
    } elsif (is_sln_ext($in_file)) {
        my $rsh = sln_file_processing(0, $in_file, $out_dsp_dir);
        show_sln_results($rsh);
        if (@project_list) {
            my $out_dsw = $out_dsp_dir."\\temp.$pgmname.DSW";
            # write_proj_DSW3( $out_dsp_dir."\\temp.$pgmname.DSW", \@project_list);
            # DEBUG: 
            # $dbg & 128 = get_configs_array3()
            # prt("[dbg & 1] write_proj_DSW3: 'temp'     DSP file [$odsp]\n") if ($g_write_dbg & 1);
            # prt("[dbg & 2] write_proj_DSW3: 'absolute' DSP file [$fdsp]\n") if ($g_write_dbg & 2);
            # $debug_dsw_write = 3;
            prt("\nDoing write_proj_DSW3 to [$out_dsw]. Debug=[3]\n");
            write_proj_DSW3( $out_dsw, $rsh, $out_bat_file, 3);
        }
    } else {
        prtw( "WARNING: Unprocessed file extension! [$in_file]!\n" );
    }
}

write_cmake_output();

pgm_exit(0,"");

##########################################################

sub chk_arg {
    my ($arg, @av) = @_;
    fatal( "Invalid $arg - needs value ... -? for help ... aborting!\n" ) if !(@av);
}

sub need_arg {
	my ($a, @b) = @_;
	if (!@b) {
		prt( "Error: $a argument requires additional item! Try -?\n" );
        pgm_exit(1,"COMMAND ERROR");
	}
}

sub load_arg_file($$);

sub load_arg_file($$) {
    my ($fil,$lev) = @_;
    if (! open INF, "<$fil") {
        pgm_exit(1,"ERROR: Unable to open file [$fil]!\n");
    }
    my @lines = <INF>;
    close INF;
    my ($line,@arr,$lncnt,$i,$tmp,$sarg);
    @arr = ();
    $lncnt = scalar @lines;
    for ($i = 0; $i < $lncnt; $i++) {
        $line = $lines[$i];
        $line = trim_all($line);
        next if (length($line) == 0);
        if ($line =~ /^\s*\#\s*include\s+"(.+)"/) {
            $sarg = $1;
            if (-f $sarg) {
                prt("Loading #include [$sarg]...\n") if (VERB1());
                load_arg_file($sarg,$lev+1);
            } else {
                pgm_exit(1,"ERROR: INCLUDE file #include \"$sarg\" NOT FOUND\n");
            }
            next;
        }
        next if ($line =~ /^#/);
        while ($line =~ /\\$/) {
            # got continuation of this line
            $i++;
            $tmp = trim_all($lines[$i]);
            next if ($tmp =~ /^#/);
            last if (length($tmp) == 0);
            $line =~ s/\\$//;
            $line = trim_all($line);
            $line .= $tmp;  #add this to the line
        }
        # store argument from file
        if ($line =~ /\s/) {
            my @a = space_split($line);
            foreach $tmp (@a) {
                push(@arr,$tmp);
            }
        } else {
            push(@arr,$line);
        }
    }
    if (@arr) {
        $in_input_file++;
        parse_args(@arr);
        $in_input_file--;
    }
}
sub has_wild_cards($) {
    my $fil = shift;
    return 1 if ($fil =~ /(\?|\*)/);
    return 0;
}

sub set_cmake_options($) {
    my $sarg = shift;
    $write_cmake = 1;
    my @arr = split(":",$sarg);
    my $cnt = scalar @arr;
    my ($i,$opt,@arr2,$msg);
    $msg = '';
    for ($i = 1; $i < $cnt; $i++) {
        $opt = $arr[$i];
        $msg = "Option: " if (length($msg) == 0);
        if (($opt eq '?')||($opt =~ /help/i)) {
            show_cmake_help();
            pgm_exit(0,"Cmake HELP exit(0)\n");
        } elsif ($opt =~ /^it;.+/) {
            $opt =~ s/^it;//;
            $inst_hdr_path = $opt;
            $msg .= "Inst. hdrs to [$opt] ";
        } elsif ($opt =~ /^lt;.+/) {
            $opt =~ s/^lt;//;
            $inst_lib_path = $opt;
            $msg .= "Inst. libs to [$opt] ";
        } elsif ($opt =~ /^bt;.+/) {
            $opt =~ s/^bt;//;
            $inst_bin_path = $opt;
            $msg .= "Inst. bins to [$opt] ";
        } elsif ($opt =~ /^out;.+/) {
            $opt =~ s/^out;//;
            $out_cmake_dir = File::Spec->rel2abs($opt);
    		#	$sarg = File::Spec->rel2abs($tmp);   # get ABSOLUTE path of input
            #    prt( "Setting to output cmake to abs=[$sarg]\n" ) if (VERB1());
            #    $out_cmake_dir = $sarg;
            if (-d $out_cmake_dir) {
                $msg .= "Root dir to [$out_cmake_dir] ";
            } else {
                pgm_exit(1,"ERROR: Root dir [$out_cmake_dir] DOES NOT EXIST!\n");
            }
        } else {
            pgm_exit(1,"ERROR: Unknown cmake option [$opt] (1)\n");
        }
    }
    prt("Set to write CMake files $msg.\n");
}

sub parse_args { # @ARGV
    my (@av) = @_;
    my $dn = scalar @av;
    my ($arg,$tmp,$i,$sarg,$val,@arr);
    if ($dbg_sl_06) {
        prt( "[dbg01] parsing $dn arguments... " );
        for ($i = 0; $i < $dn; $i++) {
            prt( "[".$av[$i]."]" );
        }
        prt("\n");
    }
    $dn = 0;
    my $had_frp = 0;
    $got_par = 0;
	while (@av) {
        $dn++;
		$arg = $av[0];
        prt( "[dbg01] $dn: $arg\n" ) if ($dbg_sl_06);
		if (substr($arg,0,1) eq '-') {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /^-/);
			if (($sarg eq '?')||($sarg eq 'h')||($sarg eq '-help')) {
				give_help();
                pgm_exit(0,"HELP_EXIT");
            } elsif ($sarg =~ /^\@/) {
                $sarg = substr($sarg,1);
                load_arg_file($sarg,0);
            } elsif ($sarg =~ /^adj-inter$/) {
                $adj_inter = 1;
                prt("Set to adjust output and inter dirs to \"Release\\<proj>\" and \"Debug\\<proj>\"\n") if (VERB1());
            } elsif ($sarg =~ /^adj-out$/) {
                $adj_out = 1;
                prt("Set to adjust output to \"bin\\<proj>[D].exe\" EXE and DLL and \"lib\\...\" libs.\n") if (VERB1());
            } elsif ($sarg =~ /^adj-rt$/) {
                need_arg(@av);
                shift @av;
                $dn++;
                $sarg = $av[0];
                if (($sarg eq 'D')||($sarg eq 'T')) {
                    $adj_rt = $sarg;
                    if ($sarg eq 'D') {
                        $tmp = "D = /MD and /MDd";
                    } else {
                        $tmp = "T = /MT and /MTd";
                    }
                    prt("Set to adjust RUNTIME to $tmp, accordingly.\n") if (VERB1());
                } else {
                    pgm_exit(1,"ERROR: Argument $arg can ONLY be follwed by 'D' or 'T'! NOT [$sarg].\n");
                }
            } elsif ($sarg =~ /^del-ndl-all$/) {
                $del_ndl_all = 1;
                prt( "Set to delete /nodefaultlib:\"*...*\"...\n" ) if (VERB1());
            } elsif ($sarg =~ /^del-dll-all$/) {
                $del_dll_all = 1;
                prt("Set to remove any DLL build if both DLL and static, or change to static is only DLL\n") if (VERB1());
            } elsif ($sarg =~ /^del-spl-bld$/) {
                $del_spl_bld = 1;
                prt("Remove any Special Tool Build blocks from DSP\n") if (VERB1());
            } elsif ($sarg =~ /^in=(.+)$/) {
    			$in_file = $1;
                if (has_wild_cards($in_file)) {
                    @arr = glob($in_file);
                    prt("Potential inputs: ".join(" ",@arr)."\n") if (@arr);
                    prt("ERROR: At present do not support wild card inputs like [$arg]\n");
                    pgm_exit(1,"but do support multiple file inputs...\n");
                }
                if (-f $in_file) {
                   $rparams = init_common_subs($in_file) if (!$got_par); # note: sets ROOT_FOLDER - where a CMakeLists.txt could be written
                   prt( "Set in file to [$in_file] ...\n" ) if (VERB1());
                   push(@user_inputs,$in_file);
                   $got_par = 1;
                } else {
                    prt( "Current Work Directory = [$pwd]\n" );
                    mydie( "ERROR: Can NOT locate IN FILE [$in_file]! check name, location! aborting...\n" );
                }
            } elsif ($arg eq '-l') {
                $load_log = 1;
                prt( "Set in load log at end...\n" ) if (VERB1());
            } elsif ($arg eq '-in') {
                need_arg(@av);
                shift @av;
                $dn++;
                $arg = $av[0];
                prt("[dbg01] $dn: $arg\n") if ($dbg_sl_06);
                if (has_wild_cards($arg)) {
                    @arr = glob($arg);
                    prt("Potential inputs: ".join(" ",@arr)."\n") if (@arr);
                    prt("ERROR: At present do not support wild card inputs like [$arg]\n");
                    pgm_exit(1,"but do support multiple file inputs...\n");
                }
    			#$in_file = $arg;
    			$in_file = File::Spec->rel2abs($arg);   # get ABSOLUTE path of input
                if (-f $in_file) {
                   $rparams = init_common_subs($in_file) if (!$got_par); # note: sets ROOT_FOLDER - where a CMakeLists.txt could be written
                   prt( "Set in file to [$in_file] ...\n" ) if (VERB1());
                   push(@user_inputs,$in_file);
                   $got_par = 1;
                } else {
                    prt( "Current Work Directory = [$pwd]\n" );
                    pgm_exit(1,"ERROR: Can NOT locate IN FILE [$in_file]! check name, location! aborting...\n" );
                }
            } elsif ($arg eq '-cmp') {
                $comp_2_dsps = 1;
                prt("Set compare NEW and any OLD DSP file.\n") if (VERB1());
            } elsif ($arg eq '-debug') {
                set_sl_debug_on();
                svc_set_dbg_on();
                $dbg4write = -1;    # all write DEBUG on
            } elsif ($arg =~ /^-cmake/) {
                $sarg = substr($arg,1);
                set_cmake_options($sarg);
                $dn++;
            #} elsif ($sarg =~ /^cmake:(.+)$/) {
            #    $tmp = $1;
    		#	$sarg = File::Spec->rel2abs($tmp);   # get ABSOLUTE path of input
            #    prt( "Setting to output cmake to abs=[$sarg]\n" ) if (VERB1());
            #    $out_cmake_dir = $sarg;
            #    $write_cmake = 1;
            } elsif ($arg eq '-dsp') {
                $dn++;
                prt("[dbg01] $dn: $arg\n") if ($dbg_sl_06);
                $write_dsp = 1;
                $g_had_dsp = 1;
                prt( "Setting to output a DSP to [$out_dsp_dir]\n" ) if (VERB1());
            } elsif ($sarg =~ /^dsp:(.+)$/) {
                $tmp = $1;
    			$sarg = File::Spec->rel2abs($tmp);   # get ABSOLUTE path of input
                prt( "Setting output file to abs=[$sarg] ($tmp), from [$out_dsp_dir]...\n" ) if (VERB1());
                #$out_dsp_dir = $tmp;
                $out_dsp_dir = $sarg;
                $write_dsp = 1;
                $g_had_dsp = 1;
            } elsif ($arg =~ /^-type=(CA|WA|DLL|SL)$/) {
                $tmp = $1;
                if ( get_app_type_4_short($tmp,\$curr_app_type)  && length($curr_app_type) ) {
        			prt( "Set proj type override to [$curr_app_type] ($tmp)...\n" ) if (VERB1());
                } else {
    				mydie( "ERROR: Unknown option [$arg] ... try -? ... aborting!\n" );
                }
            } elsif (($arg eq '-fix-rel')||($arg eq '-fix_rel')) {
                $fix_rel_paths = 1;
                prt("Set to fix relative paths of sources.\n") if (VERB1());
                $had_frp = 1;
            } elsif ($sarg =~ /^svc-dbg=(\d+)/) {
                $val = $1;
                prt("[dbg01] $dn: $arg\n") if ($dbg_sl_06);
                if (svc_set_dbg_item($val,1)) {
                   pgm_exit(1,"ERROR: Unable to set lib_vcscan.pl dbg_v$val... aborting!\n" );
                }
            } elsif ($sarg =~ /^svc-dbg$/) {
                need_arg(@av);
                shift @av;
                $dn++;
                $sarg = $av[0];
                prt("[dbg01] $dn: $arg $sarg\n") if ($dbg_sl_06 || VERB9());
                if ( !($sarg =~ /^\d+$/) || ( svc_set_dbg_item($sarg,1) ) ) {
                   pgm_exit(1,"ERROR: [$arg] [$sarg] Unable to set lib_vcscan.pl dbg_v$sarg... aborting!\n" );
                }
            } elsif ($sarg =~ /^show-hash$/) {
                $dbg_sl_04 = 1; # Show DSP hash results (for debug).
                prt("Set to show DSP hash results (for debug).\n") if (VERB1());
            } elsif ($sarg eq 'type') {
                need_arg(@av);
                shift @av;
                $dn++;
                $arg = $av[0];
                prt("[dbg01] $dn: $arg\n") if ($dbg_sl_06 || VERB9());
                if ($arg =~ /^(CA|WA|DLL|SL)$/) {
                    $tmp = $1;
                    if ( get_app_type_4_short($tmp,\$curr_app_type) && length($curr_app_type) ) {
                        prt( "Set proj type override to [$curr_app_type] ($tmp)...\n" ) if (VERB1());
                    } else {
                        pgm_exit(1,"ERROR: Unknown option [-type $arg] ... try -? ... aborting!\n" );
                    }
                } else {
    				pgm_exit(1,"ERROR: Unknown option [$arg]! Expected one {CA|WA|DLL|SL]!! try -? ... aborting!\n" );
                }
            } elsif ($sarg =~ /^v/) {
                if ($sarg =~ /^v(\d+)$/) {
                    $verbosity = $1;
                } else {
                    while ($sarg =~ /^v/) {
                        $verbosity++;
                        $sarg = substr($sarg,1);
                    }
                }
                $dbg4write = -1 if (VERB9());  # all write DEBUG on
                prt("Set verbosity to [$verbosity]\n") if (VERB1());
            } elsif ($arg eq '-ll') {
                $load_log = 1;
                prt("Set to load log at end.\n") if (VERB1());
            } else {
				pgm_exit(1,"ERROR: Unknown option [$arg] ... try -? ... aborting!\n" );
			}
		} else {
			# bare item - assume an INPUT file
			#$in_file = $arg;
            if (has_wild_cards($arg)) {
                @arr = glob($arg);
                prt("Potential inputs: ".join(" ",@arr)."\n") if (@arr);
                prt("ERROR: At present do not support wild card inputs like [$arg]\n");
                pgm_exit(1,"but do support multiple file inputs...\n");
            }
			$in_file = File::Spec->rel2abs($arg);   # get ABSOLUTE path of input
            if (-f $in_file) {
               $rparams = init_common_subs($in_file) if (!$got_par); # note: sets ROOT_FOLDER - where a CMakeLists.txt could be written
               prt( "Set in file to [$in_file] ...\n" ) if (VERB1());
               push(@user_inputs,$in_file);
               $got_par = 1;
            } else {
                prt( "Current Work Directory = [$pwd]\n" );
                pgm_exit(1,"ERROR: Can NOT locate IN FILE [$in_file]! check name, location! aborting...\n" );
            }
		}
		shift @av;
	}

    if ($in_input_file) {
        return;
    }

    if ($had_frp && !$g_had_dsp) {
        pgm_exit(1,"ERROR: Option conflict! Had -fix_rel, but no -dsp=<dir> for output.\n");
    }

    $dn = scalar @user_inputs;
    if (!$dn && $debug_on && length($def_in_file) && (-f $def_in_file) && length($def_out_dsp_dir) && (-d $def_out_dsp_dir)) {
        $in_file = $def_in_file;
        push(@user_inputs,$in_file);
        $out_dsp_dir = $def_out_dsp_dir;
        $fix_rel_paths = 1;
        #$load_log = 1;
        #$verbosity = 9;
        #$dbg4write = -1;
        prt("DEBUG ON: Set input to [$in_file], and out [$out_dsp_dir]\n");
        $rparams = init_common_subs($in_file) if (!$got_par); # note: sets ROOT_FOLDER - where a CMakeLists.txt could be written
        $got_par = 1;
        $write_cmake = 1;
    }
    $dn = scalar @user_inputs;
    if ($dn) {
        prt("Got $dn items to process...\n");
    } else {
        # no file(s), and not $debug_on
		give_help();
        pgm_exit(1,"ERROR: No input file found!\n");
    }
    if (length($out_dsp_dir) == 0) {
        pgm_exit(1,"ERROR: No DSP out directory givent! Aborting...");
    } elsif (! -d $out_dsp_dir) {
        pgm_exit(1,"ERROR: DSP out directory [$out_dsp_dir] does NOT exist! Aborting...");
    }
    if ($write_cmake) {
        #my $out_cmake_dir = '';

    }

    return \@user_inputs;
}

# -cmp            - If an existing DSP file, compare NEW and OLD.
#  -cmake[:dir]    - Write cmake file to this root directory. Default to in file directory if none given.

sub give_help {
    my $help = <<EOF;
$pgmname [OPTIONS] input_file
$pgmname Version: $vers

OPTIONS:
 -? or -h        - This brief help.
 -\@rep_file     - Commands from an input (repsonse) file.
 -adj-inter      - Adjust output and inter directories to "Release\\<proj>" and "Debug\\<proj>"
 -adj-out        - Adjust output to "bin\\<proj>.exe" and "bin\\<proj>D.exe" for EXE and DLL
                   projects, and "lib\\<proj>.lib" and "lib\\<proj>D.lib" for libraries.
 -adj-rt <D|T>   - Adjust runtime, D = /MD and /MDd, T = /MT and /MTd, accordingly.
 -del-ndl-all    - To delete /nodefaultlib:\"*...*\", if found
 -del-dll-all    - Remove any DLL build if both DLL and static, or change to static is only DLL
 -del-spl-bld    - Remove any Special Tool Build blocks from DSP
 -dsp[:dsp_dir]  - Write DSP file(s) to this directory. (def=$out_dsp_dir).
 -in=in_file     - Alternative to set input file.
 -ll             - Load LOG at end.
 -fix-rel        - Fix relative paths, if an output directory, relative to source, given.
 -svc-dbg=<num>  - Set this debug item in the lib_vcscan.pl module.
 -show-hash      - Show DSP hash results (for debug \$dbg_v04).
 -type=TYPE      - Override project type. TYPES = [CA|WA|DLL|SL] only.
                   CA=Console App, WA=Windows App, DLL=Dynamic-Link, Lib SL=Static Library.
 -v[n]           - Bump (or set) verbosity. Def=$verbosity

The 'input file' can be either a single 'vcproj' file, of a 'sln' file.
If a solution file (*.sln) is given, then all the project files if contains (*.vcproj) will
first be extracted, and then processed one-by-one.
EOF
    prt( $help );
    prt(" -cmake[:op[:op...]]  = Output CMake CMakeLists.txt file, to -o <dir>, with bat to copy to source.\n");
    show_cmake_help();
}

sub show_cmake_help {
    prt(" Can be followed by a list of colon spearated special cmake options.\n");
    prt(" it;targ   = Set special 'install' headers option, like it;include/plib for PLIB.\n");
    prt(" lt;targ   = Set special 'install' libraries option, like lt;sbin for a system utility.\n");
    prt(" bt;targ   = Set special 'install' binary option, perhaps like bt;bin/tg.\n");
    prt(" out;targ  = Set target root output directory.\n");
    prt(" Other otions to follow as they ar identified.\n");
   
}

# eof - vcproj05.pl
