#!/usr/bin/perl -w
# NAME: test00.pl
# AIM: Used to develop lib_cmakeread.pl
# 02/05/2012 - Looking quite smooth ;=))
use strict;
use warnings;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use Cwd;
my $os = $^O;
my $perl_dir = '/home/geoff/bin';
my $PATH_SEP = '/';
my $temp_dir = '/tmp';
if ($os =~ /win/i) {
    $perl_dir = 'C:\GTools\perl';
    $temp_dir = $perl_dir;
    $PATH_SEP = "\\";
}
unshift(@INC, $perl_dir);
require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n";
require 'lib_cmakeread.pl' or die "Unable to load 'lib_cmakeread.pl' Check paths in \@INC...\n";
# log file stuff
our ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
    my @tmpsp = split(/(\\|\/)/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt";
open_log($outfile);

# user variables
my $VERS = "0.0.1 2012-04-28";
my $load_log = 0;   # 1=notepad(np), 2=editplus(ep)
my $load_cmake_inst = 1;
my $test_curr_file = 0;

my $tmp_cmake = $temp_dir.$PATH_SEP."temp.cmake.txt";
my $dump_cmake_file = 0;    # DUMP cleaned lines to a debug file dump_cmake()
my $load_dump_file = 1;     # load text in editor after writin file

# options for dump output
# -------------------------
my $add_line_nums = 1;
my $add_if_depth = 1;
my $add_uctag = 1;
my $add_skipped_lines = 0;
my $add_foreach_depth = 1;
my $add_macro_depth = 1;
my $add_tag_action = 0;     # duplicate the file line '$tag($act'\)'
# -------------------------

my $set_rh_debug = 0;       # set ALL debug flags ON
my $set_if_debug = 0;
my $set_set_debug = 0;
my $set_list_debug = 0;
my $set_list_debug2 = 0;
my $add_foreach_debug = 0;  # DEBUG FOREACH - but problem found
my $set_per_line_debug = 0;

my $show_set_items = 0;
my $show_list_items = 0;
my $write_directive_list = 0;
my $show_macro_items = 0;
my $show_function_items = 0;
my $show_if_items = 0;

# specific lines
my $test_cmake_line1 = 0;
my $test_cmake_line2 = 0;
my $test_cmake_line3 = 0;
my $test_cmake_line4 = 0;

my $debug_level_load = 0;
my $debug_level_proc = 0x100 | 0x200 | 0x400;

my $input_file = '';
my @in_files = ();
my $def_file1 = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\AddFileDependencies.cmake';
my $def_file2 = 'C:\FGCVS\flightgear\source\CMakeLists.txt';
my $def_file3 = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindHDF5.cmake';
my $def_file4 = 'C:\FGCVS\flightgear\source\CMakeModules\FlightGearComponent.cmake';
my $def_file5 = 'C:\FGCVS\flightgear\source\CMakeModules\FindSimGear.cmake';
my $def_file6 = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindBoost.cmake';
my $def_file7 = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeDetermineCXXCompiler.cmake';
my $def_file8 = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CMakeVerifyManifest.cmake';
#my $in_file = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindCUDA\run_nvcc.cmake';
#my $in_file = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\CPack.cmake';
#my $in_file = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindCUDA\run_nvcc.cmake';
#my $in_file = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindFLTK.cmake';
#my $in_file = 'C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-cl.cmake';
my @test_files = ( "$def_file1", "$def_file2", "$def_file3" );

if ($test_curr_file) {
    $input_file = $def_file3;
    #push(@in_files,$def_file4);
    #push(@in_files,$def_file5);
    #push(@in_files,$def_file2);
}

my $chk_line1 = 'STRING(REGEX REPLACE "\\\\\\\\" "/" FLTK_DIR_SEARCH1 "$ENV{PATH}")';
my $chk_line2 = 'string(REPLACE "\\"" "\\\\\\"" arg ${arg})';
my $chk_line3 = 'string(REPLACE "\\\\\\\\\\\\\\\\\\"" "\\"\\\\\"" "\\"\\\\\\\\\\\\\"" arg ${arg})';
my $chk_line4 = 'string(REPLACE "\\"\\\\\\\\\\\\\\"" "\\"" arg ${arg})';

###my $in_file = '';
my $verbosity = 0;
my $debug_on = 0;
my $def_file = 'def_file';
my $out_xml = '';

### program variables
my @warnings = ();
my $cwd = cwd();
my ($ref_hash);

sub get_curr_ref_hash() { return $ref_hash; }

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

sub show_warnings($) {
    my ($val) = @_;
    if (@warnings) {
        my %dupes = ();
        my $cnt = scalar @warnings;
        prt( "\nShowing, up to $cnt WARNINGS...\n" );
        $cnt = 0;
        foreach my $itm (@warnings) {
            if (!defined $dupes{$itm}) {
                $dupes{$itm} = 1;
                prt("$itm\n");
                $cnt++;
            }
        }
        prt("Shown $cnt WARNINGS...\n");
    } else {
        prt( "\nNo warnings issued.\n\n" ) if (VERB9());
    }
}

sub close_dump() {
    my $rh = get_curr_ref_hash();
    if (!defined ${$rh}{'CURR_DUMP_HANDLE'}) {
        return;
    }
    my $fh = ${$rh}{'CURR_DUMP_HANDLE'};
    my $df = ${$rh}{'CURR_DUMP_NAME'};
    print $fh "# End of DUMP $df\n";
    close $fh;
    prt("Written DUMP to [$df]\n");
    system($df) if ($load_dump_file);
}

# if ($dump_cmake_file) - dump cleaned lines to a debug file
sub dump_cmake($) {
    my $rh = shift;
    my ($fh);
    if (!defined ${$rh}{'CURR_DUMP_HANDLE'}) {
        if ( !open($fh,">$tmp_cmake") ) {
            pgm_exit(1,"ERROR: Unable to OPEN dump [$tmp_cmake]\n");
        }
        ${$rh}{'CURR_DUMP_HANDLE'} = $fh;
        ${$rh}{'CURR_DUMP_NAME'} = $tmp_cmake;
    }
    $fh = ${$rh}{'CURR_DUMP_HANDLE'};
    my $rclines = ${$rh}{"CLEAN_LINES"};
    my $cnt = scalar @{$rclines};
    my $bfile = ${$rh}{'BASE_FILE'};
    my ($rcln,$line,$clnn,$tag,$tdep);
    $line = "Contents of [$bfile] $cnt lines";
   	print $fh "$line\n";
    $rcln = ${$rclines}[-1];
    my $lnn = ${$rcln}[3];
    my $frm = sprintf("%d",length($lnn));
    $frm = '%'.$frm.'d';
    my $idep = 0;
    my $ind = '';
    my $isif = 0;
    my $pdep = 0;
    my $plnn = 1;
    my $endln = 0;
    my $fedep = 0;
    my $isfe = 0;
    my $pfedep = 0;
    my $comm = '';
    my $cind = "\t";
    my $mcdep = 0;
    my $pmcdep = 0;
    my $ismac = 0;
    my $act = '';
    my $msg = '';
    foreach $rcln (@{$rclines}) {
        #                  0     1      2       3      4
        #push(@{$rclines},[$line,$ucdir,$action,$bgnln,$endln]);
        $line = ${$rcln}[0];
        $tag = ${$rcln}[1];
        $act = ${$rcln}[2];
        $lnn = ${$rcln}[3];
        $endln = ${$rcln}[4];
        $ind = '';
        $isif = 0;
        if ($add_uctag) {
            $comm = " # $tag $lnn:$endln";
        }
        if ($add_if_depth) {
            if ($tag eq 'IF') {
                $pdep = $idep;
                $idep++;
                $isif = 1;
            } elsif ($tag eq 'ENDIF') {
                $idep-- if ($idep > 0);
                $pdep = $idep;
                $isif = 1;
            } elsif ($tag eq 'ELSE') {
                $isif = 2;
            } elsif ($tag eq 'ELSEIF') {
                $isif = 3;
            }
            #if ($isif) {
            #    $ind = ' ' x $pdep;
            #} else {
            #    $ind = ' ' x $idep;
            #}
        }
        $isfe = 0;
        if ($add_foreach_depth) {
            if ($tag eq 'FOREACH') {
                $isfe = 1;
                $pfedep = $fedep;
                $fedep++;
            } elsif ($tag eq 'ENDFOREACH') {
                $isfe = 1;
                $fedep-- if ($fedep);
                $pfedep = $fedep;
            }
        }
        # $add_macro_depth
        $ismac = 0;
        if ($add_macro_depth) {
            if ($tag eq 'MACRO') {
                $ismac = 1;
                $pmcdep = $mcdep;
                $mcdep++;
            } elsif ($tag eq 'ENDMACRO') {
                $ismac = 1;
                $mcdep-- if ($mcdep);
                $pmcdep = $mcdep;
            }
        }

        if ($add_if_depth || $add_foreach_depth || $add_macro_depth) {
            $tdep = 0;
            if ($isif) {
                $tdep += $pdep;
            } else {
                $tdep += $idep;
            }
            if ($isfe) {
                $tdep += $pfedep;
            } else {
                $tdep += $fedep;
            }
            if ($ismac) {
                $tdep += $pmcdep;
            } else {
                $tdep += $mcdep;
            }
            $ind = $cind x $tdep;
        }

        # collect the INFORMATION
        $msg = '';
        if ($add_skipped_lines) {
            while ($plnn < $lnn) {
                if ($add_line_nums) {
                    $clnn = sprintf($frm,$plnn);
                    $msg .= "$clnn: # skipped\n";
                } else {
                    $msg .= "# skipped\n";
                }
                $plnn++;
            }
        }
        if ($add_line_nums) {
            $clnn = sprintf($frm,$lnn);
            $msg .= "$clnn: $ind$line$comm\n";
            if ($add_tag_action) {
                $msg .= "$clnn: $ind$tag$act\n";
            }
        } else {
            $msg .= "$ind$line$comm\n";
            if ($add_tag_action) {
                $msg .= "$ind$tag$act\n";
            }
        }

        if ($add_skipped_lines) {
            while ($lnn < $endln) {
                $lnn++;
                if ($add_line_nums) {
                    $clnn = sprintf($frm,$lnn);
                    $msg .= "$clnn:\n";
                } else {
                    $msg .= "\n";
                }
            }
        }
        # output of the INFORMATION
        # ============================================
        print $fh $msg;
        # ============================================
        $plnn = $lnn + 1;   # update line number
    }
    $line = "# eof";
   	print $fh "$line\n";
}


sub pgm_exit($$) {
    my ($val,$msg) = @_;
    if (length($msg)) {
        $msg .= "\n" if (!($msg =~ /\n$/));
        prt($msg);
    }
    show_warnings($val);
    close_dump();
    close_log($outfile,$load_log);
    exit($val);
}


sub prtw($) {
   my ($tx) = shift;
   $tx =~ s/\n$//;
   prt("$tx\n");
   push(@warnings,$tx);
}

# =================================================
# enventual LIBRARY functions
# =================================================

sub local_cmake_fix_directory($) {
    my $rd = shift;
    if (!(${$rd} =~ /(\\|\/)$/)) {
        ${$rd} .= $PATH_SEP;
    }
}

sub get_cmake_install_paths_ra() {
    my $envstg = $ENV{"PATH"};
    my ($path,$up,@arr,$ver,$tmp,$cnt);
    my @paths = ();
    #prt("ENV(PATH) = $envstg\n");
    @arr = split(";",$envstg);
    $cnt = scalar @arr;
    #prt("Got $cnt paths to test...\n");
    foreach $path (@arr) {
        #prt("Testing [$path]\n");
        next if (length($path) == 0);
        if ($path =~ /CMake/i) {
            $path =~ s/(\\|\/)bin$//i;
            $ver = '';
            if (-d $path) {
                #$up = path_d2u($path);
                $up = path_u2d($path);
                prt("Adding path [$up]\n");
                @arr = split(/(\/|\\)+/,$up);
                foreach $tmp (@arr) {
                    if ($tmp =~ /cmake/i) {
                        $ver = $tmp;
                        last;
                    }
                }
                push(@paths,[$up,$ver]);
            } else {
                prtw("WARNING: Not a valid DIRECTORY! [$path]\n");
            }
        } else {
            # prt("Not 'CMake' related!\n");
        }
    }
    return \@paths;
}

sub scan_cmake_path($$);
sub scan_cmake_path($$) {
    my ($path,$rh) = @_;
    # my @installed_files = ();
    # ${$rh}{'CMAKE_INSTALLED_FILES'} = \@installed_files;
    my $rif = ${$rh}{'CMAKE_INSTALLED_FILES'};
    my @dirs = ();
    if (opendir(DIR,$path)) {
        my @files = readdir(DIR);
        closedir(DIR);
        my ($file,$ff);
        cmake_fix_directory(\$path);
        foreach $file (@files) {
            next if (($file eq '.')||($file eq '..'));
            $ff = $path.$file;
            if (-l $ff) {
                # ignore links
            } elsif (-d $ff) {
                push(@dirs,$ff);
            } elsif (-f $ff) {
                if ($file =~ /\.cmake$/i) {
                    #prt("adding file [$ff]\n");
                    push(@{$rif},$ff);
                }
            } else {
                prtw("WARNING: Unable to find file [$ff]!\n");
            }
        }
        foreach $path (@dirs) {
            scan_cmake_path($path,$rh);
        }
    } else {
        prtw("WARNING: Unable to open directory [$path]!\n");
    }
}

my $common_cmake_directory = '';
sub get_cmake_common_directory($) {
    my $fil1 = shift;
    my $fil2 = $common_cmake_directory;
    my $len1 = length($fil1);
    my $len2 = length($fil2);
    if ($len2) {
        my $comm = '';
        my ($i,$ch1,$ch2);
        for ($i = 0; (($i < $len1) && ($i < $len2)); $i++) {
            $ch1 = substr($fil1,$i,1);
            $ch2 = substr($fil2,$i,1);
            last if ($ch1 ne $ch2);
            $comm .= $ch1;
        }
        $common_cmake_directory = $comm;
    } else {
        $common_cmake_directory = $fil1 if ($len1);
    }
}

sub scan_cmake_install_paths($) {
    my $rh = shift;
    if (!defined ${$rh}{'CMAKE_INSTALLED_FILES'}) {
        pgm_exit(1,"ERROR: Ref has passed does not define 'CMAKE_INSTALLED_FILES'!\n");
    }
    my ($i,$path,$ver);
    my $rval = 0;
    my $rp = get_cmake_install_paths_ra();
    my $cnt = scalar @{$rp};
    if ($cnt) {
        for ($i = 0; $i < $cnt; $i++) {
            $path = ${$rp}[$i][0];
            scan_cmake_path($path,$rh);
        }
        my $rif = ${$rh}{'CMAKE_INSTALLED_FILES'};
        foreach $path (@{$rif}) {
            get_cmake_common_directory($path);
        }
        ${$rh}{'CMAKE_INSTALLED_PATH'} = $common_cmake_directory;
    } else {
        prtw("WARNING: Found NO Cmake install paths!\n");
        $rval = 1;
    }
    return $rval;
}


# =================================================

sub is_loaded_macro($$) {
    my ($tag,$rh) = @_;
    my $dbg_flag = get_cmake_dbg_flag($rh);
    my $iret = 0;
    my $rmh = ${$rh}{'CMAKE_MACROS'};
    # if (defined ${$rma}{$mac}) {
    #                  0     1
    # ${$rma}{$mac} = [$args,$macro];
    my $min = 0;
    my $max = 32;
    my ($mac,$len,$rma,$args,$macro);
    my @arr = sort keys(%{$rmh});
    my $cnt = scalar @arr;
    # prt("\nDisplay of $cnt MACROS collected...\n");
    foreach $mac (@arr) {
        $rma = ${$rmh}{$mac};
        $args = ${$rma}[0];
        $macro = ${$rma}[1];
        #prt("$mac $args [$macro}\n");
        if (uc($mac) eq $tag) {
            $iret = 1;
            last;
        }
    }
    if ($iret) {
        prt("[d100] Running MACRO [$mac $args $macro] not yet coded.\n") if (($dbg_flag & 0x100) && ${$rh}{'show_macro_dbg'});
    }
    return $iret;
}

sub clean_cmake_action($) {
    my $act = shift;
    $act =~ s/^\(//;
    $act =~ s/\)$//;
    #$act = trim_all($act);
    return $act;
}

sub process_cmake_script($) {
    my $rh = shift;
    if (!defined ${$rh}{'BASE_FILE'}) {
        pgm_exit(1,"ERROR: Ref hash does NOT define 'BASE_FILE'!\n");
    }
    my $bfile = ${$rh}{'BASE_FILE'};
    if (!defined ${$rh}{"CLEAN_LINES"}) {
        prtw("WARNING: No 'CLEAN_LINES' in ref hash. No [$bfile] processing!\n");
        return 1;
    }
    my $rclines = ${$rh}{"CLEAN_LINES"};
    my $csrc   = ${$rh}{'CURR_LINE_SOURCE'};
    my $cnt = scalar @{$rclines};
    my $dbg_flag = 0;
    if (defined ${$rh}{'CURR_DBG_FLAG'}) {
        $dbg_flag = ${$rh}{'CURR_DBG_FLAG'};
    } else {
        ${$rh}{'CURR_DBG_FLAG'} = $debug_level_proc;
    }
    my $src = $bfile;
    if ($csrc eq $bfile) {
        my $rflh = ${$rh}{'CMAKE_FILES_LOADED'};    # = \%cmake_files_loaded;
        if (defined ${$rflh}{$bfile}) {
            # already loaded - silently forget it
            return;
        }
    } else {
        # prt("\n") if ($dbg_flag & 0x100);;
        $src = $csrc;
    }
    prt("[d100] Processing $cnt lines, from [$src]...\n") if (($dbg_flag & 0x100) && ${$rh}{'show_process_dbg'});
    #                   0     1    2       3    4
    # push(@{$rclines},[$line,$tag,$action,$bln,$eln]);
    my ($i,$line,$tag,$action,$func,$bln,$eln,$act,@arr,$tmp);
    ${$rh}{"ACT_LCNT"} = $cnt;  # lines to process

    for ($i = 0; $i < $cnt; $i++) {
        $line = ${$rclines}[$i][0];
        next if ($line =~ /^\@/);   # skip these for now '@something@
        $tag = ${$rclines}[$i][1];
        $action = ${$rclines}[$i][2];
        $bln = ${$rclines}[$i][3];
        $eln = ${$rclines}[$i][4];
        $act = clean_cmake_action($action);
        @arr = space_split($act);
        ${$rh}{"ACT_TAG"} = $tag;
        ${$rh}{"ACT_ACT"} = $act;
        ${$rh}{"ACT_RA"}  = \@arr;
        ${$rh}{"ACT_LNN"} = $bln;
        ${$rh}{"ACT_LNN"} .= ":$eln" if ($bln != $eln);
        ${$rh}{"ACT_LINE"} = $line;
        ${$rh}{"ACT_CNT"} = scalar @arr;
        ${$rh}{'ACT_I'} = $i; # current line position
        prt("[d80] $bln:$eln: $line\n") if (${$rh}{'per_line_dbg'});
        if (is_loaded_macro($tag,$rh)) {
        } elsif (is_a_known_directive($tag)) {
            $tmp = join(" ",@arr);
            #if ($tag eq 'LIST') {
            #    prt("[d200] Processing DIRECTIVE [$tag] $i of $cnt ($action) ($tmp) $bln:$eln [$src]\n") if ($dbg_flag & 0x200);
            #}
            $func = get_directive_function($tag);
            $func->($rh);
            $i = ${$rh}{'ACT_I'}; # potentially updated line position
            ###prt("[d400] Done DIRECTIVE [$tag] $i of $cnt\n") if ($dbg_flag & 0x400);
        } else {
            prtw("WARNING: [$tag] is NOT a known directive, nor loaded MACRO act [$action] [$bfile]$bln:$eln\n");
        }

    }

}

sub process_cmake_file($) {
    my $rh = shift;
    my $dbg_flag = get_cmake_dbg_flag($rh);
    my $ff = ${$rh}{'BASE_FILE'};  # $test_file;
    my $rflh = ${$rh}{'CMAKE_FILES_LOADED'};    # = \%cmake_files_loaded;
    if (defined ${$rflh}{$ff}) {
        # already loaded - silently forget it
        return;
    }
    if (load_cmake_script_file($rh)) {
        prtw("WARNING: process_cmake_file: Failed to load [$ff]\n");
    } else {
        my $rclines = ${$rh}{"CLEAN_LINES"};
        my $rcnt = ${$rh}{"ACT_LCNT"};
        my $cnt = scalar @{$rclines};
        ### prt("process_cmake_file: [$ff] ok, $cnt of $rcnt lines\n") if (${$rh}{'show_process_dbg'});
        if ($cnt) {
            dump_cmake($rh) if ($dump_cmake_file);
            ${$rh}{'CURR_DBG_FLAG'} = $debug_level_proc;
            process_cmake_script($rh);
        }
        ### prt("process_cmake_file: done [$ff]\n") if (${$rh}{'show_process_dbg'});
    }
}

sub process_in_file($$) {
    my ($ff,$rh) = @_;
    ${$rh}{'BASE_FILE'} = $ff;  # $test_file;
    ${$rh}{'CURR_LINE_SOURCE'} = $ff;   # set FILE source
    ${$rh}{'CURR_DBG_FLAG'} = -1 if (!defined ${$rh}{'CURR_DBG_FLAG'});
    process_cmake_file($rh);
}

sub process_test_file($$) {
    my ($ff,$rh) = @_;
    ${$rh}{'BASE_FILE'} = $ff;
    ${$rh}{'CURR_LINE_SOURCE'} = $ff;   # set FILE source
    ${$rh}{'CURR_DBG_FLAG'} = -1 if (!defined ${$rh}{'CURR_DBG_FLAG'});
    process_cmake_file($rh);
}


sub test_load_installed_cmake($) {
    my $rh = shift;
    my @a = ();
    my %new_directives = ();
    my $svdebug = 0;
    $svdebug = ${$rh}{'CURR_DBG_FLAG'} if (defined ${$rh}{'CURR_DBG_FLAG'});
    # set the DEBUG for the INSTALL LOAD
    my $dbg_flag = -1;
    $dbg_flag &= ~(0x8000);
    $dbg_flag = 0;
    $dbg_flag |= 0x100;
    ${$rh}{'CMAKE_INSTALLED_FILES'} = \@a;
    ${$rh}{'CMAKE_DIRECTIVES_FOUND'} = \%new_directives;
    ${$rh}{'CURR_DBG_FLAG'} = $dbg_flag;
    scan_cmake_install_paths($rh);
    my $rif = ${$rh}{'CMAKE_INSTALLED_FILES'};
    my $cnt = scalar @{$rif};
    prt("Got $cnt files to load...\n");
    my ($ff);
    my ($dir,$i,$ch);
    foreach $ff (@{$rif}) {
        process_in_file($ff,$rh);
    }
    my @arr = sort keys(%new_directives);
    $cnt = scalar @arr;
    my $rmh = ${$rh}{'CMAKE_MACROS'};
    my $mcnt = scalar keys(%{$rmh});
    my $rfh = ${$rh}{'CMAKE_FUNCTIONS'};
    my $fcnt = scalar keys(%{$rfh});

    prt("Done loading $cnt files... $cnt dirs, $mcnt macs, $fcnt funcs\n");
    if ($cnt) {
        prt("# Found $cnt NEW directives...\n");
#        prt("my \%new_cmake_directives = (\n");
#        $ch = ',';
#        for ($i = 0; $i < $cnt; $i++) {
#            $dir = $arr[$i];
#            prt("  '$dir' => \\\&hand$ch\n");
#            $ch = '' if (($i + 1) == $cnt);
#        }
#        prt(");\n");
#        prt("# Listed $cnt directives...\n");
    }
    $dir = ${$rh}{'CMAKE_INSTALLED_PATH'};
    prt("Common cmake 'install' directory [$dir]\n");
    ${$rh}{'CURR_DBG_FLAG'} = $svdebug;
}

sub do_cmake_subdirectories($) {
    my $rh = shift;
    my $dbg_flag = get_cmake_dbg_flag($rh);
    # ADD_SUBDIRECTORY
    # my @subdirs = ();
    # ${$rh}{'CMAKE_SUBDIRS'} = \@subdirs;
    #my %subs_done = ();
    # ${$rh}{'CMAKE_SUBSDONE'} = \%subs_done;
    my $rsh = ${$rh}{'CMAKE_SUBDIRS'};
    my $rsd = ${$rh}{'CMAKE_SUBSDONE'};
    my $max  = scalar keys(%{$rsh});
    my $done = scalar keys(%{$rsd});
    my ($i,$sd,$todo,$rsa,$key,$ff);
    while ($max != $done) {
        $todo = $max - $done;
        prt("[d100] ADD_SUBDIRECTORIES: Now loading $todo files from subdirectories added...\n")
            if (($dbg_flag & 0x100) && ${$rh}{'show_addsub_dbg'});
        #for ($i = 0; $i < $max; $i++) {
        foreach $key (keys %{$rsh}) {
            $rsa = ${$rsh}{$key};
            # push(@{$rsubs},[$item1,$ff]);
            #$sd = ${$rsa}[$i][0];
            #$ff = ${$rsa}[$i][1];
            $sd = ${$rsa}[0];
            $ff = ${$rsa}[1];
            if (!defined ${$rsd}{$ff}) {
                ${$rsd}{$ff} = 1;
                ###process_in_file($ff,$rh);
                process_test_file($ff,$rh);
            }
        }
        $max  = scalar keys(%{$rsh});
        $done = scalar keys(%{$rsd});
    }
}


sub test_lines($) {
    my $rh = shift;
    #my $chk_line1 = 'STRING(REGEX REPLACE "\\\\" "/" FLTK_DIR_SEARCH1 "$ENV{PATH}")';
    #my $chk_line2 = 'string(REPLACE "\"" "\\\"" arg ${arg})';
    my @arr = ();
    ${$rh}{'BASE_FILE'} = "TEST LINES";
    ${$rh}{'CURR_DBG_FLAG'} = -1;
    ${$rh}{"BASE_LINES"} = \@arr;
    if ($test_cmake_line1) {
        @arr = ();
        push(@arr,$chk_line1);
        ${$rh}{'BASE_FILE'} = "TEST LINE 1";
        process_cmake_raw_lines($rh);
    }
    if ($test_cmake_line2) {
        @arr = ();
        push(@arr,$chk_line2);
        ${$rh}{'BASE_FILE'} = "TEST LINE 2";
        process_cmake_raw_lines($rh);
    }
    if ($test_cmake_line3) {
        @arr = ();
        push(@arr,$chk_line3);
        ${$rh}{'BASE_FILE'} = "TEST LINE 3";
        process_cmake_raw_lines($rh);
    }
    if ($test_cmake_line4) {
        @arr = ();
        push(@arr,$chk_line4);
        ${$rh}{'BASE_FILE'} = "TEST LINE 4";
        process_cmake_raw_lines($rh);
    }
}

# $rih = ${$rh}{'CMAKE_SETMACROS'};
sub list_set_items($) {
    my $rh = shift;
    my $rih = ${$rh}{'CMAKE_SETMACROS'};
    my @arr = keys(%{$rih});
    my $cnt = scalar @arr;
    my ($set,$rsi,$val,$min,$len,$max);
    $min = 0;
    $max = 32;
    foreach $set (@arr) {
        $len = length($set);
        $min = $len if ($len > $min);
        last if ($min > $max);
    }
    $min = $max if ($min > $max);
    prt("\nDisplay of $cnt SET items, and their value...\n");
    foreach $set (sort @arr) {
        $rsi = ${$rih}{$set};
        $val = join(" ",@{$rsi});
        $set .= ' ' while (length($set) < $min);
        prt("$set = [$val]\n");
    }
    prt("Done display of $cnt SET items, and their value...\n");
}

# $rli = ${$rh}{'CMAKE_LISTS'};
sub list_list_items($) {
    my $rh = shift;
    my $rih = ${$rh}{'CMAKE_LISTS'};
    my @arr = keys(%{$rih});
    my $cnt = scalar @arr;
    my ($set,$rsi,$val,$min,$len,$max);
    $min = 0;
    $max = 32;
    foreach $set (@arr) {
        $len = length($set);
        $min = $len if ($len > $min);
        last if ($min > $max);
    }
    prt("\nDisplay of $cnt LIST items, and their value...\n");
    foreach $set (sort @arr) {
        $rsi = ${$rih}{$set};
        $val = join(" ",@{$rsi});
        $set .= ' ' while (length($set) < $min);
        prt("$set = [$val]\n");
    }
    prt("Done display of $cnt LIST items, and their value...\n");
}

sub get_body() {
    my $txt = <<EOF;
    my \$rh = shift;
    my \$dbg_flag = get_cmake_dbg_flag(\$rh);
    my \$bfile = \${\$rh}{'BASE_FILE'};
    my \$lnn = \${\$rh}{"ACT_LNN"};
    my \$tag = \${\$rh}{"ACT_TAG"};
    my \$act = \${\$rh}{"ACT_ACT"};
    my \$ra  = \${\$rh}{"ACT_RA"};
    my \$cnt = \${\$rh}{"ACT_CNT"};    # = scalar \@arr;
EOF
    return $txt;
}

sub list_directives($) {
    my $rh = shift;
    my ($dir,$tmp,$line,$msg,@arr,$cnt);
    my $rdirh = ${$rh}{'CMAKE_DIRECTIVES_FOUND'};   # = \%directives;
    @arr = keys(%{$rdirh});
    $cnt = scalar @arr;
    if ($cnt == 0) {
        return;
    }
    my $outdirs = $temp_dir.$PATH_SEP."temp.directives.txt";
    my $loadfil = 'C:\GTools\perl\lib_cmakeread.pl';
    my %subs_found = ();
    my $body = get_body();
    my $min = 32;
    if (open INF, "<$loadfil") {
        my @lines = <INF>;
        close INF;
        foreach $line (@lines) {
            if ($line =~ /^sub\s+fn_(\w+)\W/) {
                $tmp = $1;
                $subs_found{$tmp} = 1;
            }
        }
    }
    @arr = keys(%subs_found);
    $cnt = scalar @arr;
    prt("Found $cnt existing directive subs...\n");

    $msg = '';
    @arr = keys(%{$rdirh});
    $cnt = scalar @arr;
    prt("Collected $cnt directives...\n");
    foreach $dir (sort @arr) {
        if (!defined $subs_found{$dir}) {
            $msg .= "sub fn_$dir {\n$body\n}\n";
        }
    }
    $msg .="\nmy \%directive_hash = (";
    foreach $dir (sort @arr) {
        $line = " '$dir' ";
        $line .= " " while (length($line) < $min);
        $tmp = "fn_$dir";
        $msg .= "\n $line=> \\\&$tmp,";
    }
    $msg =~ s/,$//g;
    $msg .= "\n);\n";
    write2file($msg,$outdirs);
    prt("Written directives hash to [$outdirs]\n");
}

sub list_macro_items($) { # if ($show_macro_items);
    my $rh = shift;
    my $rmh = ${$rh}{'CMAKE_MACROS'};
    # if (defined ${$rma}{$mac}) {
    #                  0     1
    # ${$rma}{$mac} = [$args,$macro];
    my $min = 0;
    my $max = 32;
    my ($mac,$len,$rma,$args,$macro);
    my @arr = sort keys(%{$rmh});
    my $cnt = scalar @arr;
    prt("\nDisplay of $cnt MACROS collected...\n");
    foreach $mac (@arr) {
        $rma = ${$rmh}{$mac};
        $args = ${$rma}[0];
        $macro = ${$rma}[1];
        prt("$mac $args [$macro}\n");
    }
    prt("\nDone display of $cnt MACROS collected...\n");
}
sub list_function_items($) { # if ($show_function_items);
    my $rh = shift;
}


sub do_test($$$) {
    my ($act,$exp,$rh) = @_;
    my ($res);
    $res = cmake_if_parsing($act,$rh,0);
    if ($res == $exp) {
        prt("Result of if($act) [$res] ok\n");
    } else {
        prtw("WARNING: Result of if($act) [$res] exp [$exp] FAILED!\n");
    }
}

sub check_file_for_q_object($) {
    my $file = shift;
    if (!open INF, "<$file") {
        return 1;   # can NOT open so assume YES
    }
    my @lines = <INF>;
    close INF;
    my ($line);
    foreach $line (@lines) {
        return 1 if ($line =~ /\bQ_OBJECT\b/);
    }
    return 0;
}


sub do_if_test($) {
    my ($rh) = shift;
    my $file = 'C:\Projects\fgx\src/xobjects/xsettings.h';
    my $res = check_file_for_q_object($file);
    prt("$res\n");
}

sub do_if_test2($) {
    my ($rh) = shift;
    ${$rh}{'BASE_FILE'} = "test";
    my ($act);
    

    $act = '(WIN32)';
    do_test($act,1,$rh);

    $act = 'UNIX';
    do_test($act,0,$rh);

    $act = 'NOT (UNIX OR APPLE)';
    do_test($act,1,$rh);

    # IF(WIN32 OR APPLE) (=3) [C:\FGCVS\cmake\Source\CMakeLists.txt]362
    $act = 'WIN32 OR APPLE';
    do_test($act,1,$rh);

    # YACC_EXECUTABLE MATCHES "bison"
    my $rdh = ${$rh}{'CMAKE_DEFINES'};
    ${$rdh}{'YACC_EXECUTABLE'} = "bison";
    $act = "YACC_EXECUTABLE MATCHES \"bison\"";
    do_test($act,1,$rh);

    $act = "NOT YACC_EXECUTABLE MATCHES \"bison\"";
    do_test($act,0,$rh);

    $act = "NOT YACC_EXECUTABLE MATCHES \"intel\"";
    do_test($act,1,$rh);

    $act = '"${compilerVersion}" LESS 1300';
    do_test($act,1,$rh);

    
    ${$rdh}{'compilerVersion'} = 1600;
    $act = '"${compilerVersion}" LESS 1300';
    do_test($act,0,$rh);

    $act = '"${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$"';
    ${$rdh}{'CMAKE_BACKWARDS_COMPATIBILITY'} = "1.5";
    do_test($act,1,$rh);

    $act = '${MSVC_VERSION} EQUAL 1300';
    do_test($act,0,$rh);

    $act = '"${CMAKE_CXX_COMPILER_ID}" MATCHES GNU OR "${CMAKE_CXX_COMPILER_ID}" MATCHES Intel';
    do_test($act,1,$rh);

    $act = '"$ENV{CFLAGS} $ENV{CXXFLAGS} $ENV{LDFLAGS}" MATCHES "-([no]32|64)"';
    $ENV{'LDFLAGS'} = "-64";
    do_test($act,1,$rh);

    #return;

    $act = '"${CMAKE_TEST_GENERATOR}" MATCHES "WMake" OR "${CMAKE_TEST_GENERATOR}" MATCHES "Borland"';
    ${$rdh}{'CMAKE_TEST_GENERATOR'} = "Borland";
    do_test($act,1,$rh);

    # IF("${_help}" MATCHES "--path" AND "${_help}" MATCHES "--nonet") (=7) [C:\FGCVS\cmake\Utilities\CMakeLists.txt]144
    # IF("${_help}" MATCHES "GNU ld .* 2\\.1[1-6]") (=3) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Windows-GNU.cmake]56

    $act = '"1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" "1.34" "1.33.1" "1.33.0" "1.33.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99"';
    ${$rdh}{'_Boost_FIND_VERSION_SHORT'} = "1.33";
    do_test($act,1,$rh);

    # IF("1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" \
    # "1.43" "1.42.0" "1.42" "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" \
    # "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" "1.34" "1.33.1" "1.33.0" \
    # "1.33.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") (=39) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindBoost.cmake]465
    # IF(NOT "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" \
    # "1.43" "1.42.0" "1.42" "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" \
    # "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" "1.34" "1.33.1" "1.33.0" \
    # "1.33" VERSION_LESS "${Boost_FIND_VERSION}") (=40) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindBoost.cmake]462

    # IF(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) (=5) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindBoost.cmake]772
    # IF(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.4) (=5) [C:\FGCVS\cmake\Source\QtDialog\CMakeLists.txt]74
    # IF(${CMAKE_VERSION} VERSION_GREATER 2.8.4) (=7) [C:\FGCVS\flightgear\source\CMakeLists.txt]13
    # IF(Boost_FIND_VERSION_PATCH AND Boost_SUBMINOR_VERSION LESS "${Boost_FIND_VERSION_PATCH}") (=5) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindBoost.cmake]1056

}


do_if_test(get_cmake_ref_hash());
pgm_exit(0,"");


#########################################
### MAIN ###
parse_args(@ARGV);
$ref_hash = get_cmake_ref_hash();
${$ref_hash}{'CURR_DBG_FLAG'} = $debug_level_load;
set_rh_debug_flags($ref_hash,1) if ($set_rh_debug);
set_foreach_debug_flags($ref_hash,1) if ($add_foreach_debug);
${$ref_hash}{'show_if_diags'} = 1 if ($set_if_debug);
${$ref_hash}{'show_list_dbg'} = 1 if ($set_list_debug);
${$ref_hash}{'show_list_dbg2'} = 1 if ($set_list_debug2);
${$ref_hash}{'warn_list_no_code'} = 1 if ($set_list_debug2);
${$ref_hash}{'show_set_dbg'} = 1 if ($set_set_debug);
${$ref_hash}{'per_line_dbg'} = 1 if ($set_per_line_debug);

if ($load_cmake_inst) {
    test_load_installed_cmake($ref_hash);
}
if ($test_curr_file) {
    foreach my $f (@in_files) {
        $input_file = '' if ($f eq $input_file);
        process_test_file($f,$ref_hash);
        do_cmake_subdirectories($ref_hash);
    }
    process_test_file($input_file,$ref_hash) if (length($input_file));
    do_cmake_subdirectories($ref_hash);
}
if ($test_cmake_line1 || $test_cmake_line2 || $test_cmake_line3 || $test_cmake_line4) {
    test_lines($ref_hash);
}

list_macro_items($ref_hash) if ($show_macro_items);
list_function_items($ref_hash) if ($show_function_items);
list_set_items($ref_hash) if ($show_set_items);
list_list_items($ref_hash) if ($show_list_items);
list_directives($ref_hash) if ($write_directive_list);


pgm_exit(0,"");
########################################
sub give_help {
    prt("$pgmname: version $VERS\n");
    prt("Usage: $pgmname [options] in-file\n");
    prt("Options:\n");
    prt(" --help  (-h or -?) = This help, and exit 0.\n");
    prt(" --verb[n]     (-v) = Bump [or set] verbosity. def=$verbosity\n");
    prt(" --load        (-l) = Load LOG at end. ($outfile)\n");
    prt(" --out <file>  (-o) = Write output to this file.\n");
}

sub need_arg {
    my ($arg,@av) = @_;
    pgm_exit(1,"ERROR: [$arg] must have a following argument!\n") if (!@av);
}

sub parse_args {
    my (@av) = @_;
    my ($arg,$sarg);
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /^-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /^-/);
            if (($sarg =~ /^h/i)||($sarg eq '?')) {
                give_help();
                pgm_exit(0,"Help exit(0)");
            } elsif ($sarg =~ /^v/) {
                if ($sarg =~ /^v.*(\d+)$/) {
                    $verbosity = $1;
                } else {
                    while ($sarg =~ /^v/) {
                        $verbosity++;
                        $sarg = substr($sarg,1);
                    }
                }
                prt("Verbosity = $verbosity\n") if (VERB1());
            } elsif ($sarg =~ /^l/) {
                $load_log = 1;
                prt("Set to load log at end.\n") if (VERB1());
            } elsif ($sarg =~ /^o/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $out_xml = $sarg;
                prt("Set out file to [$out_xml].\n") if (VERB1());
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            push(@in_files,$arg);
            if ((! -f $arg) && (! -d $arg)) {
                pgm_exit(1,"ERROR: Unable to find in file or folder [$arg]! Check name, location...\n");
            }
            prt("Added [$arg] to input files...\n") if (VERB1());
        }
        shift @av;
    }

    if (!@in_files && !$load_cmake_inst && !length($input_file)) {
        pgm_exit(1,"ERROR: No input files or directories found in command!\n");
    }
}

# =====================================================


sub cmake_if_parsing_NEARLY_OK($$$) {
    my ($act,$rh,$lev) = @_;
    my $rdh = ${$rh}{'CMAKE_DEFINES'};
    my $rta = cmake_token_split($act);
    my $acnt = scalar @{$rta};
    my %cmake_opers = (
    'AND' => 1,
    'OR'  => 2,
    'EQUAL' => 3,
    'LESS'  => 4,
    'GREATER' => 5,
    'MATCHES'  => 6,
    'STREQUAL' => 7,
    'STRLESS' => 8,
    'STRGREATER' => 9 );

    my $res = 0;
    my ($tok,$val,$tmp,$str1,$str2,$cnt,$i,$msg,$tmp1,$tmp2,$tmps1,$tmps2,$i2);
    $msg = ($lev ? 'sub if' : "\nPARSE IF");
    $msg .= " ( $act ) split $acnt array";
    prt("$msg\n");
    my @braces = ();
    my @resarr = ();
    my $oper = '';
    my $isstr = 0;
    my @vals = ();
    my @svals = ();
    my @ops = ();
    my $fop = 0;
    $str1 = '';
    $str2 = '';
    $cnt = 0;
    my $nact = '';
    my $hadq = 0;
    for ($i = 0; $i < $acnt; $i++) {
        $i2 = $i + 1;
        $tmp = ${$rta}[$i];
        $tok = strip_quotes($tmp);
        $hadq = ($tmp eq $tok) ? 0 : 1;
        $msg = "$cnt:$i2:$acnt: Token [$tmp] [$tok] ";
        if ($tok eq '(') {
            $tmps1 = '';
            push(@braces,$i);
            $i++;
            for (; $i < $acnt; $i++) {
                $tmp = ${$rta}[$i];
                $tok = strip_quotes($tmp);
                if ($tok eq ')') {
                    pop @braces if (@braces);
                    last if (!@braces);
                } elsif ($tok eq '(') {
                    push(@braces,$i);
                }
                $tmps1 .= ' ' if (length($tmps1));
                $tmps1 .= $tmp;
            }
            $val = cmake_if_parsing($tmps1,$rh,($lev+1)); 
            $msg .= "parse [$tmps1] = [$val]";
            $vals[$cnt] = $val;
            if ($val =~ /^\d+$/) {
                $svals[$cnt] = ($val == 0) ? "" : "$val";
            } else {
                $svals[$cnt] = $val;
            }
            if (@ops && ($ops[-1] eq 'NOT')) {
                pop @ops;
                $val = ($val ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $cnt++;
        } elsif ($tok =~ /\$\{(\w+)\}/) {
            # a macro token
            $tmp = $1;
            if (defined ${$rdh}{$tmp}) {
                $val = ${$rdh}{$tmp};
                $msg .= "def [$tmp] = [$val] ";
                $vals[$cnt] = ${$rdh}{$tmp};
                $svals[$cnt] = "${$rdh}{$tmp}";
            } elsif (cmake_macro_sub(\$tok,$rh)) {
                $msg .= "mac = [$tok]";
                $val = $tok;
                $vals[$cnt] = $tok;
                $svals[$cnt] = "$tok";
            } else {
                $msg .= "nods set 0";
                $val = 0;
                $vals[$cnt] = 0;
                $svals[$cnt] = "";
            }
            if (@ops && ($ops[-1] eq 'NOT')) {
                pop @ops;
                $val = ($val ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $cnt++;
        } elsif ($tok =~ /\$ENV\{(\w+)\}/) {
            # an enviroment token (or more)
            my $nta = cmake_token_split($tok);
            $val = '';
            $tmp2 = scalar @{$nta};
            foreach $tok (@{$nta}) {
                if ($tok =~ /\$ENV\{(\w+)\}/) {
                    $tmp = $1;
                    if (exists $ENV{$tmp}) {
                        $tmp1 = $ENV{$tmp};
                        $msg .= "env [$tmp] = [$tmp1] ";
                    } else {
                        $tmp1 = '';
                        $msg .= "noenv [$tmp] so [$tmp1] ";
                    }
                    $tok =~ s/\$ENV\{$tmp\}/$tmp1/;
                    if (length($tok)) {
                        $val .= ' ' if (length($val));
                        $val .= $tok;
                    }
                } else {
                    $val .= ' ' if (length($val));
                    $val .= $tok;
                }
            }
            $msg .= "fin [$val] " if ($tmp2 > 1);
            $vals[$cnt] = $val;
            if ($val =~ /^\d+$/) {
                $svals[$cnt] = ($val == 0) ? "" : "$val";
            } else {
                $svals[$cnt] = $val;
            }
            if (@ops && ($ops[-1] eq 'NOT')) {
                pop @ops;
                $val = ($val ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $cnt++;
        # elsif (($txt =~ /^AND$/i)||($txt =~ /^OR$/i)||($txt =~ /^NOT$/i)||($txt =~ /^STREQUAL$/i)) {
        } elsif ($tok eq 'NOT') {
            if ($i == 0) {
                $msg .= "store 1st op $tok";
                $fop = 1;   # negates the result
            } else {
                $oper = $tok;
                push(@ops,$tok);
                $msg .= "push op $tok";
            }
        } elsif (defined $cmake_opers{$tok}) {
            $oper = $tok;
            push(@ops,$tok);
            $msg .= "push op $tok";
            $isstr = $cmake_opers{$tok};
        } elsif ($tok =~ /^\d+$/) {
            $val = $tok;
            $vals[$cnt] = $val;
            $msg .= "digit $tok";
            $svals[$cnt] = ($val == 0) ? "" : "$val";
            if (@ops && ($ops[-1] eq 'NOT')) {
                pop @ops;
                $val = ($val ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $cnt++;
        } elsif ($tok =~ /^\w+$/) {
            # also a macro?
            $tmp = "\${$tok}";
            $tmp1 = $tmp;
            if (defined ${$rdh}{$tok}) {
                $val = ${$rdh}{$tok};
                $msg .= "Def = [$val]";
            } elsif (cmake_macro_sub(\$tmp,$rh)) {
                $val = $tmp;
                $msg .= "Mac [$tmp1] = $val";
            } else {
                $val = $tok;
                $msg .= "NF [$tmp1] set $val";
            }
            $vals[$cnt] = $val;
            if ($val =~ /^\d+$/) {
                $svals[$cnt] = ($val == 0) ? "" : "$val";
            } else {
                $svals[$cnt] = $val;
            }
            if (@ops && ($ops[-1] eq 'NOT')) {
                pop @ops;
                $val = ($val ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $cnt++;
        } else {
            # what is this
            if (length($tok)) {
                $msg .= 'asm str ';
                $vals[$cnt] = $tok;
                $svals[$cnt] = $tok;
                $cnt++;
            } else {
                $msg .= "UNK set 0";
                $val = 0;
                $vals[$cnt] = 0;
                $svals[$cnt] = '';
                if (@ops && ($ops[-1] eq 'NOT')) {
                    pop @ops;
                    $val = ($val ? 0 : 1);
                    $vals[$cnt] = $val;
                    $msg .= "NOT = $val";
                }
            }
            $cnt++;
        }
        prt("$msg\n");
        if ($cnt == 2) {
            $i++;
            last;
        }
    }
    $msg = "Result:$lev: ";
    if ($cnt > 1) {
        $tmp1 = $vals[0];
        $tmp2 = $vals[1];
        $tmps1 = $svals[0];
        $tmps2 = $svals[1];
        $msg .= "2 values [$tmp1] [$tmp2] ";
        if (@ops) {
            $oper = pop @ops;
            if ($oper eq 'AND') {
                $res = ($tmp1 && $tmp2) ? 1 : 0;
                $msg .= "AND ";
            } elsif ($oper eq 'OR') {
                $res = ($tmp1 || $tmp2) ? 1 : 0;
                $msg .= "OR ";
            } elsif ($oper eq 'EQUAL') {
                $msg .= "$oper ";
                if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                    # both are digits, so
                    $res = ($tmp1 == $tmp2) ? 1 : 0;
                    $msg .= "= ";
                } else {
                    $res = ($tmps1 eq $tmps2) ? 1 : 0;
                    $msg .= "eq ";
                }
            } elsif ($oper eq 'LESS') {
                $msg .= "$oper ";
                if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                    # both are digits, so
                    $res = ($tmp1 < $tmp2) ? 1 : 0;
                    $msg .= "< ";
                } else {
                    $res = ($tmps1 eq $tmps2) ? 1 : 0;
                    $msg .= "lt ";
                }
                #$res = ($tmp1 < $tmp2) ? 1 : 0;
                #$msg .= "$oper ";
            } elsif ($oper eq 'GREATER') {
                $msg .= "$oper ";
                if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                    # both are digits, so
                    $res = ($tmp1 > $tmp2) ? 1 : 0;
                    $msg .= "> ";
                } else {
                    $res = ($tmps1 eq $tmps2) ? 1 : 0;
                    $msg .= "gt ";
                }
                ##$res = ($tmp1 > $tmp2) ? 1 : 0;
                ##$msg .= "$oper ";
            } elsif ($oper eq 'STREQUAL') {
                $res = ($tmps1 eq $tmps2) ? 1 : 0;
                $msg .= "STREQUAL ";
            } elsif ($oper eq 'MATCHES') {
                $msg .= "MATCHING $tmps1 with $tmps2 ";
                if ($tmp1 =~ /$tmp2/) {
                    $res = 1;
                    $msg .= "t2 in t1 ";
                #} elsif ($tmp2 =~ /$tmp1/) {
                #    $res = 1;
                #    $msg .= "1 is in 2 ";
                #} elsif ($tmp1 eq $tmp2) {
                #    $res = 1;
                #    $msg .= "simp 'eq' ";
                } else {
                    $msg .= "NO MATCH ";
                }
            }
        } else {
            $msg .= "NO OPS - some problem ";
            $res = 0;
        }
    } else {
        $tmp1 = $vals[0];
        $tmp2 = $svals[0];
        $msg .= "Single [$tmp1] ";
        if ($tmp1 =~ /^\d+$/) {
            $res = $tmp1;
        } else {
            if (length($tmp2)) {
                $res = 1;
            }
        }
    }
    if ($i < $acnt) {
        $tmps1 = "$res";
        $tmp1 = 0;
        for (; $i < $acnt; $i++) {
            $tmp = ${$rta}[$i];
            $tmps1 .= " $tmp";  # add the token
            if (($tmp1 == 0) && (defined $cmake_opers{$tmp})) {
                $tmps1 .= " ("; # start brackets
                $tmp1 = 1;
            }
        }
        $tmps1 .= " )" if ($tmp1);
        $res = cmake_if_parsing($tmps1,$rh,($lev+1));
        prt("sub parsed [$tmps1] with res [$res]\n");
    }
    if ($fop) {
        $res = ($res ? 0 : 1);
        $msg .= "NOT"
    }
    prt("$msg return $res\n");
    return $res;
}


sub cmake_if_parsing($$$);

#   if(<constant>)
# True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. False if the constant 
# is 0, OFF, NO, FALSE, N, IGNORE, "", or ends in the suffix '-NOTFOUND'. Named boolean constants 
# are case-insensitive. If the argument is not one of these constants, it is treated as a variable:
my %cmake_boolean_constants = (
   '1'  => 1,
   'ON' => 1,
   'YES' => 1,
   'TRUE' => 1,
   'Y'  => 1,
   # or a non-zero number are all TRUE(1).
   '0'  => 0,
   'OFF' => 0,
   'NO'  => 0,
   'FALSE' => 0,
   'N'   => 0,
   'IGNORE' => 0 );
   # plus "", or ends in the suffix '-NOTFOUND' are all FALSE(0)

my %cmake_operators = (
    'AND' => 1,
    'OR'  => 2,
    'EQUAL' => 3,
    'LESS'  => 4,
    'GREATER' => 5,
    'MATCHES'  => 6,
    'STREQUAL' => 7,
    'STRLESS' => 8,
    'STRGREATER' => 9 );

#   if(<variable|string> MATCHES regex)
#True if the given string or variable's value matches the given regular expression.
#   if(<variable|string> LESS <variable|string>)
#   if(<variable|string> GREATER <variable|string>)  
#   if(<variable|string> EQUAL <variable|string>)
#True if the given string or variable's value is a valid number and the inequality or equality is true.
#   if(<variable|string> STRLESS <variable|string>)
#   if(<variable|string> STRGREATER <variable|string>)
#   if(<variable|string> STREQUAL <variable|string>)
#True if the given string or variable's value is lexicographically less (or greater, or equal) 
#than the string or variable on the right.

my %cmake_special_opers = (
    'COMMAND' => 20,    # if(COMMAND command-name) True if the given name is a command, macro or function that can be invoked.
    'POLICY'  => 21,    # if(POLICY policy-id) True if the given name is an existing policy (of the form CMP<NNNN>).
    'TARGET'  => 22,    # if(TARGET target-name) True if the given name is an existing target, built or imported.
    'EXIST'   => 23,    # if(EXISTS file-name) or if(EXISTS directory-name) True if the named file or directory exists. Behavior is well-defined only for full paths.
    'IS_NEWER_THAN' => 24, # if(file1 IS_NEWER_THAN file2) True if file1 is newer than file2 or if one of the two files doesn't exist.
    'IS_DIRECTORY' => 25, # if(IS_DIRECTORY directory-name) True if the given name is a directory. (only for full paths).
    'IS_SYMLINK' => 26, # if(IS_SYMLINK file-name) True if the given name is a symbolic link.
    'IS_ABSOLUTE' => 27, # if(IS_ABSOLUTE path) True if the given path is an absolute path.
    'VERSION_LESS' => 30, #   if(<variable|string> VERSION_LESS <variable|string>)
    'VERSION_EQUAL' => 31, #   if(<variable|string> VERSION_EQUAL <variable|string>)
    'VERSION_GREATER' => 32); #   if(<variable|string> VERSION_GREATER <variable|string>)
#Component-wise integer version number comparison (version format is major[.minor[.patch[.tweak]]]).
# IF("${CMAKE_MINIMUM_REQUIRED_VERSION}" VERSION_LESS "2.8.3.20101214") (=3) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\CYGWIN.cmake]1
# IF("${CMake_VERSION_TWEAK}" VERSION_LESS 20000000) (=3) [C:\FGCVS\cmake\CMakeLists.txt]426
# IF("${Ruby_FIND_VERSION_SHORT_NODOT}" VERSION_LESS "19") (=3) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\FindRuby.cmake]56
# IF("${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5") (=3) [C:\Program Files (x86)\CMake 2.8\share\cmake-2.8\Modules\Platform\Darwin.cmake]190

sub local_cmake_version_comp($$$$) {
    my ($oper,$ver1,$ver2,$rh) = @_;
    return 1 if ($ver1 eq $ver2);
    return 0;
}

sub cmake_if_parsing_VERY_GOOD($$$) {
    my ($act,$rh,$lev) = @_;
    my $rdh = ${$rh}{'CMAKE_DEFINES'};
    my $rta = cmake_token_split($act);
    my $acnt = scalar @{$rta};
    my $rcmso = \%cmake_special_opers;
    my $rcmop = \%cmake_operators;
    my $rcmbool = \%cmake_boolean_constants;
    my ($tok,$val,$tmp,$str1,$str2,$cnt,$i,$msg,$tmp1,$tmp2,$tmps1,$tmps2,$i2,$rop,$fval,$rtok,$tcnt,$nta);
    $msg = ($lev ? 'sub if' : "\nPARSE IF");
    $msg .= " [ $act ] split $acnt array";
    prt("$msg\n");
    ###my @braces = ();
    my @resarr = ();
    my $oper = '';
    my $isstr = 0;
    my @vals = ();
    my @svals = ();
    my @opersm = ();
    my $fop = 0;
    $str1 = '';
    $str2 = '';
    $cnt = 0;
    my $nact = '';
    my $hadq = 0;
    my $pcnt = 0;
    for ($i = 0; $i < $acnt; $i++) {
        $i2 = $i + 1;
        $pcnt = $cnt;
        $rtok = ${$rta}[$i];
        $tok = strip_quotes($rtok);
        $hadq = ($rtok eq $tok) ? 0 : 1;
        $msg = "$cnt:$i2:$acnt: Token [$rtok]$hadq ";
        if ($rtok eq '(') {
            $tmps1 = '';
            $i++;
            my @br = ();
            push(@br,$i);
            for (; $i < $acnt; $i++) {
                $tmp = ${$rta}[$i];
                ### $tmp = strip_quotes($tmp);
                if ($tmp eq ')') {
                    pop @br if (@br);
                    last if (!@br);
                } elsif ($tmp eq '(') {
                    push(@br,$i);
                }
                $tmps1 .= ' ' if (length($tmps1));
                $tmps1 .= $tmp;
            }
            $val = cmake_if_parsing($tmps1,$rh,($lev+1)); 
            $msg .= "br.parsed [$tmps1] = [$val]";
            if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                pop @opersm;
                $val = ($val ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $vals[$cnt] = $val;
            if ($val =~ /^\d+$/) {
                $svals[$cnt] = ($val == 0) ? "" : "$val";
            } else {
                $svals[$cnt] = $val;
            }
            $cnt++;
        } elsif ($rtok eq 'NOT') {
            if ($i == 0) {
                $msg .= "store 1st op $rtok";
                $fop = 1;   # negates the result
            } else {
                $oper = $rtok;
                push(@opersm,[$rtok,0]);
                $msg .= "push op $rtok";
            }
        } elsif (defined ${$rcmop}{$rtok}) {
            $isstr = ${$rcmop}{$rtok};
            $oper = $rtok;
            push(@opersm,[$rtok,$isstr]);
            $msg .= "push op $rtok";
        } elsif (defined ${$rcmso}{$rtok}) {
            $isstr = ${$rcmop}{$rtok};
            $oper = $rtok;
            push(@opersm,[$rtok,$isstr]);
            $msg .= "push spl op $rtok";
        } elsif (defined ${$rcmbool}{$rtok}) {
            $val = ${$rcmbool}{$rtok};
            $msg .= "bool val [$val] ";
            if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                pop @opersm;
                $val = ($val ? 0 : 1);
                $msg .= "NOT = $val";
            }
            $vals[$cnt] = $val;
            $svals[$cnt] = ($val == 0) ? "" : "$val";
            $cnt++;
        } elsif (@opersm && ($opersm[-1][0] eq 'MATCHES')) {
            $vals[$cnt] = $tok;
            ###$svals[$cnt] = ($tok == 0) ? "" : "$tok";
            $svals[$cnt] = "$tok";
            $cnt++;
        } else {
            if ($cnt && !@opersm) {
                # hmmm next token, but no OPERATION YET - back up and accumulate
                $cnt--;
                $fval = $vals[$cnt];
            } else {
                $fval = ''; # accumulate value
            }
            if ($rtok eq $tok) {
                $nta = cmake_token_split($rtok);
            } else {
                if (($tok =~ /\$\{\w+\}/) || ($tok =~ /\$ENV\{(\w+)\}/)) {
                    $nta = cmake_token_split($tok); # use de-cloaked version
                } else {
                    $nta = cmake_token_split($rtok); # use raw version
                }
            }
            $tmp2 = scalar @{$nta};
            $tcnt = 0;
            foreach $rtok (@{$nta}) {
                $tcnt++;
                $tok = strip_quotes($rtok);
                if ($tok =~ /\$\{(\w+)\}/) {
                    # a macro token
                    $tmp = $1;
                    $tmps2 = $tok;
                    if (defined ${$rdh}{$tmp}) {
                        $tmps2 = ${$rdh}{$tmp};
                        $tok =~ s/\$\{$tmp\}/$tmps2/;
                        $val = $tok;
                        $msg .= "$i2:$tcnt: def [$rtok] [$tmp] = [$tmps2] = [$val] ";
                    } elsif (cmake_macro_sub(\$tmps2,$rh)) {
                        $tok =~ s/\$\{$tmp\}/$tmps2/;
                        $val = $tok;
                        $msg .= "$i2:$tcnt: mac [$rtok] [$tmp] = [$tmps2] = [$val] ";
                    } else {
                        $msg .= "$i2:$tcnt: nods set 0";
                        $val = 0;
                    }
                } elsif ($tok =~ /\$ENV\{(\w+)\}/) {
                    # an enviroment token (or more)
                    $tmp = $1;
                    if (exists $ENV{$tmp}) {
                        $tmps2 = $ENV{$tmp};
                        $tok =~ s/\$ENV\{$tmp\}/$tmps2/;
                        $val = $tok;
                        $msg .= "$i2:$tcnt: env [$rtok] [$tmp] = [$tmps2] = [$val] ";
                    } else {
                        $tmps2 = '';
                        $tok =~ s/\$ENV\{$tmp\}/$tmps2/;
                        $val = $tok;
                        $msg .= "$i2:$tcnt: no-env [$rtok] [$tmp] so [$val] ";
                    }
                } elsif ($tok =~ /^\d+$/) {
                    $val = $tok;
                    $msg .= "$i2:$tcnt: digit $tok";
                } elsif ($tok =~ /^\w+$/) {
                    # also a macro?
                    $tmp = "\${$tok}";
                    $tmp1 = $tmp;
                    if (defined ${$rdh}{$tok}) {
                        $val = ${$rdh}{$tok};
                        $msg .= "$i2:$tcnt: Def = [$val]";
                    } elsif (cmake_macro_sub(\$tmp,$rh)) {
                        $val = $tmp;
                        $msg .= "$i2:$tcnt: Mac [$tmp1] = $val";
                    } else {
                        $val = $tok;
                        $msg .= "$i2:$tcnt: NF [$tmp1] set $val";
                    }
                } else {
                    # what is this
                    if (length($tok)) {
                        $msg .= "$i2:$tcnt: asm str ";
                        $val = $tok;
                    } else {
                        $msg .= "$i2:$tcnt: UNK set 0";
                        $val = 0;
                    }
                }
                # accumulate into final value, if anything to accumulate
                if (length($val)) {
                    if ($val =~ /^\d+$/) {
                        #if ($val > 0) {
                            $fval .= ' ' if (length($fval));
                            $fval .= $val;
                        #}
                    } else {
                        $fval .= ' ' if (length($fval));
                        $fval .= $val;
                    }
                }
            }
            $msg .= "fin [$fval] " if ($tmp2 > 1);
            $vals[$cnt] = $fval;
            if ($fval =~ /^\d+$/) {
                $svals[$cnt] = ($fval == 0) ? "" : "$fval";
            } else {
                $svals[$cnt] = $fval;
            }
            if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                pop @opersm;
                $val = ($fval ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $cnt++;
        }
        prt("$msg\n");
        if ($cnt == 2) {
            $i++;
            last;
        }
    }
    $msg = "Result:$lev: ";
    my $res = 0;
    if ($cnt > 1) {
        $tmp1 = $vals[0];
        $tmp2 = $vals[1];
        $tmps1 = $svals[0];
        $tmps2 = $svals[1];
        $msg .= "2 values [$tmp1] [$tmp2] ";
        if (@opersm) {
            # $oper = pop @ops;
            $rop = pop @opersm;
            $oper = ${$rop}[0];
            if (defined ${$rcmop}{$oper}) {
                # standard operators
                $isstr = ${$rcmop}{$tok};
                #   'AND' => 1, 'OR'  => 2, 'EQUAL' => 3, 'LESS'  => 4, 'GREATER' => 5, 'MATCHES'  => 6,
                # 'STREQUAL' => 7, 'STRLESS' => 8, 'STRGREATER' => 9 );
                if ($oper eq 'AND') {
                    $res = ($tmp1 && $tmp2) ? 1 : 0;
                    $msg .= "AND ";
                } elsif ($oper eq 'OR') {
                    $res = ($tmp1 || $tmp2) ? 1 : 0;
                    $msg .= "OR ";
                } elsif ($oper eq 'EQUAL') {
                    $msg .= "$oper ";
                    if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                        # both are digits, so
                        $res = ($tmp1 == $tmp2) ? 1 : 0;
                        $msg .= "= ";
                    } else {
                        $res = ($tmps1 eq $tmps2) ? 1 : 0;
                        $msg .= "eq ";
                    }
                } elsif ($oper eq 'LESS') {
                    $msg .= "$oper ";
                    if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                        # both are digits, so
                        $res = ($tmp1 < $tmp2) ? 1 : 0;
                        $msg .= "< ";
                    } else {
                        $res = ($tmps1 eq $tmps2) ? 1 : 0;
                        $msg .= "lt ";
                    }
                } elsif ($oper eq 'GREATER') {
                    $msg .= "$oper ";
                    if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                        # both are digits, so
                        $res = ($tmp1 > $tmp2) ? 1 : 0;
                        $msg .= "> ";
                    } else {
                        $res = ($tmps1 eq $tmps2) ? 1 : 0;
                        $msg .= "gt ";
                    }
                } elsif ($oper eq 'MATCHES') {
                    $msg .= "MATCHING $tmps1 =~ /$tmps2/ ";
                    if ($tmp1 =~ /$tmp2/) {
                        $res = 1;
                        $msg .= "t2 in t1 ";
                    } else {
                        $msg .= "NO MATCH ";
                    }
                } elsif ($oper eq 'STREQUAL') {
                    $res = ($tmps1 eq $tmps2) ? 1 : 0;
                    $msg .= "STREQUAL ";
                } elsif ($oper eq 'STRLESS') {
                    $res = ($tmps1 lt $tmps2) ? 1 : 0;
                    $msg .= "STRLESS ";
                } elsif ($oper eq 'STRGREATER') {
                    $res = ($tmps1 gt $tmps2) ? 1 : 0;
                    $msg .= "STRGREATER ";
                } else {
                    prtw("IF Operation NOT CODED! [$oper]\n");
                    $msg .= "$oper NOT CODED! ";
                }
            } elsif (defined ${$rcmso}{$oper}) {
                if ($oper eq 'VERSION_EQUAL') {
                    my $rvers = cmake_space_split($tmps1);  # maybe more than one given
                    my $rvcnt = scalar @{$rvers};
                    foreach $tmp (@{$rvers}) {
                        if (local_cmake_version_comp($oper,$tmp,$tmps2,$rh)) {
                            # got version equal
                            $res = 1;
                            $msg .= "fnd [$tmps2] in $rvcnt ";
                            last;
                        }
                    }
                    if (!$res) {
                        $msg .= "NO fnd [$tmps2] in $rvcnt ";
                    }
                } else {
                    prtw("IF SPECIAL Operation NOT CODED! [$oper]\n");
                    $msg .= "SPL $oper NOT CODED! ";
                }
            } else {
                prtw("IF SPECIAL Operation  NOT LISTED! [$oper]\n");
                $msg .= "$oper NOT LISTED! ";
            }
        } else {
            $msg .= "NO OPS - some problem ";
            $res = 0;
        }
    } else {
        $tmp1 = $vals[0];
        $tmp2 = $svals[0];
        $msg .= "Single [$tmp1] ";
        if ($tmp1 =~ /^\d+$/) {
            $res = $tmp1;
        } else {
            if (length($tmp2)) {
                $res = 1;
            }
        }
    }
    if ($i < $acnt) {
        $tmps1 = "$res";
        $tmp1 = 0;
        for (; $i < $acnt; $i++) {
            $tmp = ${$rta}[$i];
            $tmps1 .= " $tmp";  # add the token
            if (($tmp1 == 0) && (defined ${$rcmop}{$tmp})) {
                $tmps1 .= " ("; # start brackets
                $tmp1 = 1;
            }
        }
        $tmps1 .= " )" if ($tmp1);
        $res = cmake_if_parsing($tmps1,$rh,($lev+1));
        prt("sub parsed [$tmps1] with res [$res]\n");
    }
    if ($fop) {
        $res = ($res ? 0 : 1);
        $msg .= "NOT"
    }
    prt("$msg return $res\n");
    return $res;
}

sub cmake_if_parsing_QUITE_OK($$$) {
    my ($act,$rh,$lev) = @_;
    my $rdh = ${$rh}{'CMAKE_DEFINES'};
    my $rta = cmake_token_split($act);
    my $acnt = scalar @{$rta};
    my $rcmso = \%cmake_special_opers;
    my $rcmop = \%cmake_operators;
    my $rcmbool = \%cmake_boolean_constants;
    my ($tok,$val,$tmp,$str1,$str2,$cnt,$i,$msg,$tmp1,$tmp2,$tmps1,$tmps2,$i2,$rop);
    $msg = ($lev ? 'sub if' : "\nPARSE IF");
    $msg .= " [ $act ] split $acnt array";
    prt("$msg\n");
    ###my @braces = ();
    my @resarr = ();
    my $oper = '';
    my $isstr = 0;
    my @vals = ();
    my @svals = ();
    my @opersm = ();
    my $fop = 0;
    $str1 = '';
    $str2 = '';
    $cnt = 0;
    my $nact = '';
    my $hadq = 0;
    my $pcnt = 0;
    for ($i = 0; $i < $acnt; $i++) {
        $i2 = $i + 1;
        $pcnt = $cnt;
        $tmp = ${$rta}[$i];
        $tok = strip_quotes($tmp);
        $hadq = ($tmp eq $tok) ? 0 : 1;
        $msg = "$cnt:$i2:$acnt: Token [$tmp]$hadq ";
        if ($tok eq '(') {
            $tmps1 = '';
            $i++;
            my @br = ();
            push(@br,$i);
            for (; $i < $acnt; $i++) {
                $tmp = ${$rta}[$i];
                ### $tmp = strip_quotes($tmp);
                if ($tmp eq ')') {
                    pop @br if (@br);
                    last if (!@br);
                } elsif ($tmp eq '(') {
                    push(@br,$i);
                }
                $tmps1 .= ' ' if (length($tmps1));
                $tmps1 .= $tmp;
            }
            $val = cmake_if_parsing($tmps1,$rh,($lev+1)); 
            $msg .= "br.parsed [$tmps1] = [$val]";
            if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                pop @opersm;
                $val = ($val ? 0 : 1);
                $vals[$cnt] = $val;
                $msg .= "NOT = $val";
            }
            $vals[$cnt] = $val;
            if ($val =~ /^\d+$/) {
                $svals[$cnt] = ($val == 0) ? "" : "$val";
            } else {
                $svals[$cnt] = $val;
            }
            $cnt++;
        } elsif ($tok eq 'NOT') {
            if ($i == 0) {
                $msg .= "store 1st op $tok";
                $fop = 1;   # negates the result
            } else {
                $oper = $tok;
                push(@opersm,[$tok,0]);
                $msg .= "push op $tok";
            }
        } elsif (defined ${$rcmop}{$tok}) {
            $isstr = ${$rcmop}{$tok};
            $oper = $tok;
            push(@opersm,[$tok,$isstr]);
            $msg .= "push op $tok";
        } elsif (defined ${$rcmso}{$tok}) {
            $isstr = ${$rcmop}{$tok};
            $oper = $tok;
            push(@opersm,[$tok,$isstr]);
            $msg .= "push spl op $tok";
        } elsif (defined ${$rcmbool}{$tok}) {
            $val = ${$rcmbool}{$tok};
            $msg .= "bool val [$val] ";
            if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                pop @opersm;
                $val = ($val ? 0 : 1);
                $msg .= "NOT = $val";
            }
            $vals[$cnt] = $val;
            $svals[$cnt] = ($val == 0) ? "" : "$val";
            $cnt++;
        } else {
            if ($tok =~ /\$\{(\w+)\}/) {
                # a macro token
                $tmp = $1;
                if (defined ${$rdh}{$tmp}) {
                    $val = ${$rdh}{$tmp};
                    $msg .= "def [$tmp] = [$val] ";
                    $vals[$cnt] = ${$rdh}{$tmp};
                    $svals[$cnt] = "${$rdh}{$tmp}";
                } elsif (cmake_macro_sub(\$tok,$rh)) {
                    $msg .= "mac = [$tok]";
                    $val = $tok;
                    $vals[$cnt] = $tok;
                    $svals[$cnt] = "$tok";
                } else {
                    $msg .= "nods set 0";
                    $val = 0;
                    $vals[$cnt] = 0;
                    $svals[$cnt] = "";
                }
                if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                    pop @opersm;
                    $val = ($val ? 0 : 1);
                    $vals[$cnt] = $val;
                    $msg .= "NOT = $val";
                }
                $cnt++;
            } elsif ($tok =~ /\$ENV\{(\w+)\}/) {
                # an enviroment token (or more)
                my $nta = cmake_token_split($tok);
                $val = '';
                $tmp2 = scalar @{$nta};
                foreach $tok (@{$nta}) {
                    if ($tok =~ /\$ENV\{(\w+)\}/) {
                        $tmp = $1;
                        if (exists $ENV{$tmp}) {
                            $tmp1 = $ENV{$tmp};
                            $msg .= "env [$tmp] = [$tmp1] ";
                        } else {
                            $tmp1 = '';
                            $msg .= "noenv [$tmp] so [$tmp1] ";
                        }
                        $tok =~ s/\$ENV\{$tmp\}/$tmp1/;
                        if (length($tok)) {
                            $val .= ' ' if (length($val));
                            $val .= $tok;
                        }
                    } else {
                        $val .= ' ' if (length($val));
                        $val .= $tok;
                    }
                }
                $msg .= "fin [$val] " if ($tmp2 > 1);
                $vals[$cnt] = $val;
                if ($val =~ /^\d+$/) {
                    $svals[$cnt] = ($val == 0) ? "" : "$val";
                } else {
                    $svals[$cnt] = $val;
                }
                if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                    pop @opersm;
                    $val = ($val ? 0 : 1);
                    $vals[$cnt] = $val;
                    $msg .= "NOT = $val";
                }
                $cnt++;
            } elsif ($tok =~ /^\d+$/) {
                $val = $tok;
                $vals[$cnt] = $val;
                $msg .= "digit $tok";
                $svals[$cnt] = ($val == 0) ? "" : "$val";
                if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                    pop @opersm;
                    $val = ($val ? 0 : 1);
                    $vals[$cnt] = $val;
                    $msg .= "NOT = $val";
                }
                $cnt++;
            } elsif ($tok =~ /^\w+$/) {
                # also a macro?
                $tmp = "\${$tok}";
                $tmp1 = $tmp;
                if (defined ${$rdh}{$tok}) {
                    $val = ${$rdh}{$tok};
                    $msg .= "Def = [$val]";
                } elsif (cmake_macro_sub(\$tmp,$rh)) {
                    $val = $tmp;
                    $msg .= "Mac [$tmp1] = $val";
                } else {
                    $val = $tok;
                    $msg .= "NF [$tmp1] set $val";
                }
                $vals[$cnt] = $val;
                if ($val =~ /^\d+$/) {
                    $svals[$cnt] = ($val == 0) ? "" : "$val";
                } else {
                    $svals[$cnt] = $val;
                }
                if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                    pop @opersm;
                    $val = ($val ? 0 : 1);
                    $vals[$cnt] = $val;
                    $msg .= "NOT = $val";
                }
                $cnt++;
            } else {
                # what is this
                if (length($tok)) {
                    $msg .= 'asm str ';
                    $vals[$cnt] = $tok;
                    $svals[$cnt] = $tok;
                    $cnt++;
                } else {
                    $msg .= "UNK set 0";
                    $val = 0;
                    $vals[$cnt] = 0;
                    $svals[$cnt] = '';
                    if (@opersm && ($opersm[-1][0] eq 'NOT')) {
                        pop @opersm;
                        $val = ($val ? 0 : 1);
                        $vals[$cnt] = $val;
                        $msg .= "NOT = $val";
                    }
                }
                $cnt++;
            }
        }
        prt("$msg\n");
        if ($cnt == 2) {
            $i++;
            last;
        }
    }
    $msg = "Result:$lev: ";
    my $res = 0;
    if ($cnt > 1) {
        $tmp1 = $vals[0];
        $tmp2 = $vals[1];
        $tmps1 = $svals[0];
        $tmps2 = $svals[1];
        $msg .= "2 values [$tmp1] [$tmp2] ";
        if (@opersm) {
            # $oper = pop @ops;
            $rop = pop @opersm;
            $oper = ${$rop}[0];
            if (defined ${$rcmop}{$oper}) {
                # standard operators
                $isstr = ${$rcmop}{$tok};
                #   'AND' => 1, 'OR'  => 2, 'EQUAL' => 3, 'LESS'  => 4, 'GREATER' => 5, 'MATCHES'  => 6,
                # 'STREQUAL' => 7, 'STRLESS' => 8, 'STRGREATER' => 9 );
                if ($oper eq 'AND') {
                    $res = ($tmp1 && $tmp2) ? 1 : 0;
                    $msg .= "AND ";
                } elsif ($oper eq 'OR') {
                    $res = ($tmp1 || $tmp2) ? 1 : 0;
                    $msg .= "OR ";
                } elsif ($oper eq 'EQUAL') {
                    $msg .= "$oper ";
                    if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                        # both are digits, so
                        $res = ($tmp1 == $tmp2) ? 1 : 0;
                        $msg .= "= ";
                    } else {
                        $res = ($tmps1 eq $tmps2) ? 1 : 0;
                        $msg .= "eq ";
                    }
                } elsif ($oper eq 'LESS') {
                    $msg .= "$oper ";
                    if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                        # both are digits, so
                        $res = ($tmp1 < $tmp2) ? 1 : 0;
                        $msg .= "< ";
                    } else {
                        $res = ($tmps1 eq $tmps2) ? 1 : 0;
                        $msg .= "lt ";
                    }
                    #$res = ($tmp1 < $tmp2) ? 1 : 0;
                    #$msg .= "$oper ";
                } elsif ($oper eq 'GREATER') {
                    $msg .= "$oper ";
                    if (($tmp1 =~ /^\d+$/) && ($tmp2 =~ /^\d+$/)) {
                        # both are digits, so
                        $res = ($tmp1 > $tmp2) ? 1 : 0;
                        $msg .= "> ";
                    } else {
                        $res = ($tmps1 eq $tmps2) ? 1 : 0;
                        $msg .= "gt ";
                    }
                    ##$res = ($tmp1 > $tmp2) ? 1 : 0;
                    ##$msg .= "$oper ";
                } elsif ($oper eq 'MATCHES') {
                    $msg .= "MATCHING $tmps1 with $tmps2 ";
                    if ($tmp1 =~ /$tmp2/) {
                        $res = 1;
                        $msg .= "t2 in t1 ";
                    #} elsif ($tmp2 =~ /$tmp1/) {
                    #    $res = 1;
                    #    $msg .= "1 is in 2 ";
                    #} elsif ($tmp1 eq $tmp2) {
                    #    $res = 1;
                    #    $msg .= "simp 'eq' ";
                    } else {
                        $msg .= "NO MATCH ";
                    }
                } elsif ($oper eq 'STREQUAL') {
                    $res = ($tmps1 eq $tmps2) ? 1 : 0;
                    $msg .= "STREQUAL ";
                } elsif ($oper eq 'STRLESS') {
                    $res = ($tmps1 lt $tmps2) ? 1 : 0;
                    $msg .= "STRLESS ";
                } elsif ($oper eq 'STRGREATER') {
                    $res = ($tmps1 gt $tmps2) ? 1 : 0;
                    $msg .= "STRGREATER ";
                } else {
                    prtw("IF Operation NOT CODED! [$oper]\n");
                    $msg .= "$oper NOT CODED! ";
                }
            } elsif (defined ${$rcmso}{$oper}) {
                prtw("IF SPECIAL Operation NOT CODED! [$oper]\n");
                $msg .= "SPL $oper NOT CODED! ";
            } else {
                prtw("IF SPECIAL Operation  NOT LISTED! [$oper]\n");
                $msg .= "$oper NOT LISTED! ";
            }
        } else {
            $msg .= "NO OPS - some problem ";
            $res = 0;
        }
    } else {
        $tmp1 = $vals[0];
        $tmp2 = $svals[0];
        $msg .= "Single [$tmp1] ";
        if ($tmp1 =~ /^\d+$/) {
            $res = $tmp1;
        } else {
            if (length($tmp2)) {
                $res = 1;
            }
        }
    }
    if ($i < $acnt) {
        $tmps1 = "$res";
        $tmp1 = 0;
        for (; $i < $acnt; $i++) {
            $tmp = ${$rta}[$i];
            $tmps1 .= " $tmp";  # add the token
            if (($tmp1 == 0) && (defined ${$rcmop}{$tmp})) {
                $tmps1 .= " ("; # start brackets
                $tmp1 = 1;
            }
        }
        $tmps1 .= " )" if ($tmp1);
        $res = cmake_if_parsing($tmps1,$rh,($lev+1));
        prt("sub parsed [$tmps1] with res [$res]\n");
    }
    if ($fop) {
        $res = ($res ? 0 : 1);
        $msg .= "NOT"
    }
    prt("$msg return $res\n");
    return $res;
}



# eof - test00.pl
