#!/usr/bin/perl -w
# NAME: amsrcs04.pl
# AIM: To scan a GNU configure.ac, or configure.in input file, for output Makefiles, then
# successifly scan the Maekfile.am (or .in) files, and create a DSP file foreach LIBRARY,
# or PROGRAMS found in this make file san, then finally a DSW file.
# =======================================================================================
# NOTE: This is NOT really a follow on from amsrcs03.pl ;=((
# This is a COMPLETE rewrite using lib_acscan.pl, and lib_amscan.pl
# =======================================================================================
# History: Growing upwards...
# 28/09/2010 Conditionals in the Makefile.am are stored, BUT when it comes to choosing the
#   correct sustitution, was just the FIRST TRUE always CHOSEN.
#   Added the option like -
#   --cond item[:1|0] (-c) = Define a conditional to be applied during parsing.
#   Revert to previous, if no conditional defined by user, but write a temp/missed_cond_list.txt
#   for items NOT defined.
# 23/09/2010:19/09/2010 - Lots of updates, changes, additions
# 08/09/2010 geoff mclane http://geoffair.net/mperl
use strict;
use warnings;
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
use Cwd;
my $perl_sdir = 'C:\GTools\perl';
unshift(@INC, $perl_sdir);
require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl'! Check location and \@INC content.\n";
require 'lib_acscan.pl' or die "Unable to load 'lib_acscan.pl'! Check location and \@INC content.\n";
require 'lib_amscan.pl' or die "Unable to load 'lib_amscan.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_srcscan.pl' or die "Unable to load 'lib_srcscan.pl'! Check location and \@INC content.\n";

my $my_version = "version 0.4.8 2010-09-28";
# log file stuff
my ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
    my @tmpsp = split(/(\\|\/)/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $perl_sdir."\\temp.$pgmname.txt";
open_log($outfile);
my $perl_temp_dir = $perl_sdir."\\temp";

# user variables
my $load_log = 0;
my $conf_file = $perl_temp_dir."\\temp.$pgmname.conf";
my $no_conf_write = 0;
my $amlistfile = $perl_temp_dir."\\amlist.txt";
my $write_am_list = 1;
my $verbosity = 0;
my $temp_copy_bat = $perl_temp_dir."\\tempcopy.bat";
my $miss_mac_file = $perl_temp_dir."\\missed_mscro_list.txt";
my $missing_list_file = $perl_temp_dir."\\missed_defined_list.txt";
my $missed_source_list = $perl_temp_dir."\\missed_source_list.txt";
my $missed_cond_list = $perl_temp_dir."\\missed_cond_list.txt";
my $show_per_file = 1;

# ==========================================================
# test projects
my $debug_on = 0;   # run with DEFAULT, if no other input...
my $def_file = 'C:\Projects\libxml2\configure.in';
my $def_targ = '';
#my $def_file = 'C:\Projects\giflib\configure.ac';
#my $def_file = 'C:\Projects\pcre\configure.ac';
#my $def_targ = 'C:\Projects\giflib\msvc';
#my $def_targ = '';
#my $def_file = 'C:\Projects\libsigc\libsigc++-2.2.8\configure.ac';
#my $def_targ = 'C:\Projects\libsigc\libsigc++-2.2.8\msvc';
#my $def_name = 'pcre';
my $def_name = '';
# ============================================================
my %g_default_condits = ( # default conditionals
    "USE_GLUT" => "TRUE",
    "ENABLE_JPEG_SERVER" => "FALSE",
    "ENABLE_SP_FDM" => "TRUE"
);

########################################
### 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: 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 = 128;
our $auto_on_flag = -1; #Bit: ALL ON by default = ${$rparams}{'CURR_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 = 1;
our $try_much_harder = 1;
# ==============================================================================
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 = ''; # ***TBD*** a name to override any ac scanned name of the project
### ========================

my $proj_incs = '/I "."';

my $proj_rt = 'D';  # ie use /MD and /MDd
my $proj_defs = '/D "_CRT_SECURE_NO_WARNINGS"';

# NOTE: For user includes, usually also NEED 'libpath'
# like $proj_libD .= " /libpath:\"Debug\" foo.lib";
# like $proj_libR .= " /libpath:\"Release\" foo.lib";
# OR
# like $proj_lib .= " /libpath:\"lib\";
# like $proj_libD .= " fooD.lib";
# like $proj_libR .= " foo.lib";
# sub in line ADD LINK32 kernel32.lib ... -NEW_LIBS- /nologo ...
my $proj_libs = 'Winmm.lib ws2_32.lib';
my $proj_libD = '';
my $proj_libR = '';

# NOTE: This is for say '/out:"bin\foo.exe"' or '/out:"lib\bar.lib"'
my $proj_outputR = '';
my $proj_outputD = '';

# object output, and the default for other things if NOT specifically stated
my $proj_interR = '"Release"';
my $proj_interD = '"Debug"';

### program variables
my @warnings = ();
my $cwd = cwd();
my $os = $^O;
my $conf_string = '';
my $only_dry_run = 0;
my $in_file = '';
my $curr_command = '';

#########################################
### DEBUG STUFF ###
# Debug items SHARED with LIBRARY - note use of 'our' - to adjust this list
# must also adjust the lib_acscan.pl library!!!
our $dbg_lac01 = 0; # prt( "[01] scan_..._file: Reading $file\n" ) if $dbg_lac01; and more
our $dbg_lac02 = 0; # show EACH line prt( "[02] $lnn: $cline... for each read line.
our $dbg_lac03 = 0; # prt( "[03] Variable [$key] = [$nval]\n" )
our $dbg_lac04 = 0; # prt( "[04] Split to $vlen components ...\n" )
our $dbg_lac05 = 0; # prt( "[05] Substitute [$key] = [$nval]\n" ) if ($v1 ne $v2))
our $dbg_lac06 = 0; # prt( "[06] $.: Should JOIN lines? - [$cline]\n" ) and more...
our $dbg_lac07 = 0; # prt( "[07] $.: Got AC_INIT = [$1]\n" ) and AC_DEFIN... etc
our $dbg_lac08 = 0; # prt( "[08] Got ac_output_line = $. [$rawline]\n" ) plus accumulation
our $dbg_lac09 = 0; # prt( "[01|09] Adding $input [$ff] to mk_inp_list ...\n" )
our $dbg_lac10 = 0; # prt( "[01|10] Adding $input [$ff] to other_input_files ...\n" )
our $dbg_lac11 = 0; # prt( "[11] Storing configure_cond key $1 ... value=2\n" ), and more
our $dbg_lac12 = 0; # prt( "[12] $.: 1=[$1] = 2=[$2] NOT USED [$cline]\n" )
our $dbg_lac13 = 0; # prt("[13] $lnn: Failed on MACRO [$blk], in file [$file]\n")
our $dbg_lac14 = 0; # show each MACRO split in FULL
our $dbg_lac15 = 0; # Show each AC MACRO accumulation...
our $dbg_lac16 = 0; # Show back slash accumulation...
our $dbg_lac17 = 0; # show all substitutions
our $dbg_lac18 = 0; # show setting or replacing each macro with value
our $dbg_lac19 = 0; # unused at present
our $dbg_lac20 = 0; # prt("[20] Directory SEARCH for [$test], found $fcnt...
my $dbg_lac_check = 20;

#########################################
# DEBUG for lib_amscan.pl
our $dbg_s01 = 0; # show each file line, in form "[01] $i2: [$line]"
our $dbg_s02 = 0; # show extraction from hash, like "Listing $acnt keys in hash ..."
our $dbg_s03 = 0; # show "Find sources for $val LIBRARY keys ...\n" and MORE
our $dbg_s04 = 0; # show prt( "LIBRARY [$ky] has SOURCES [$val]
our $dbg_s05 = 0; # show prt( "$am ". ((-f $am) ? "ok" : "no find!")
our $dbg_s06 = 0; # show prt( "Opened cond_stack with [".$cond_stack[$#cond_stack]."] $fil
our $dbg_s07 = 0; # add new line before 'Processing $cnt lines..., as does 08 also...
our $dbg_s08 = 0; # show prt( "Processing $cnt lines from $fil ...
our $dbg_s09 = 0; # show prt( "Got $cnt subdirectories [$slist] ...
our $dbg_s10 = 0; # show prtw("WARNING:1: No substitution for [$ms] found in hash ...
our $dbg_s11 = 0; # show target: gathering of lines...
our $dbg_s12 = 0; # show setting key=value in hash, during am file scan
our $dbg_s13 = 0; # show initial substitution, during am file scan
our $dbg_s14 = 0; # similar to about, but only show NO sub FOUND
our $dbg_s15 = 0; # List each source, for each project...
our $dbg_s16 = 0; # Like [02] list ALL keys showing dispostion
our $dbg_s17 = 0; # Out CHECK ME - SHOULD THIS ITEMS BE INCLUDED for a prog,lib,src key, now skipped!
our $dbg_s18 = 0; # show change due to adding relative directory
our $dbg_s19 = 0; # show finds found by directory searching...
our $dbg_s20 = 0; # output list of sources and header from dir scan, NOT included in a project
our $dbg_s21 = 0; # prt("\n[21] Seeking 'all' or 'default' in $cnt keys...\n"), and MORE...
our $dbg_s22 = 0; # show '[22]CHANGED:1: key [gatomic_c] cond [FALSE] Was [gatomic-gcc.c], now [gatomic.c] FALSE, plus
my $am_check_tot = 22;

sub VERB1() { return ($verbosity > 0); }
sub VERB2() { return ($verbosity > 1); }
sub VERB5() { return ($verbosity > 4); }
sub VERB9() { return ($verbosity > 8); }

my $project_dbg_write = 0;

sub set_all_dbg_on() {
    ac_set_all_dbg_on();
    am_set_all_dbg_on();
}
sub set_all_dbg_off() {
    ac_set_all_dbg_off();
    am_set_all_dbg_off();
}

sub set_max_debug_on() {
    $verbosity = 10;
    $project_dbg_write = -1;
    set_all_dbg_on();
    #ac_set_dbg_extra();
    prt("[debug_on] Have set MAXIMUM debug output...\n");
}

sub wait_key() {
    prt("Any key to continue...\n");
    my $char = <>;
}

# ***TBD*** this is NOW not called - see show_missing_subs2() instead
# but perhaps this is better, in that it als adds those added automatically
# but this is a 'conflict' between g_user_sub, and common_sub to be resolved
sub show_missing_subs($) {
    my ($rsnf) = @_;
    if ($dbg_s13 || $dbg_s14) {
        my @arr = keys %{$rsnf};
        my ($cnt,$txt,$key,$fil,$val,%hash,$msg);
        $txt = '';
        if (@arr) {
            $cnt = scalar @arr;
            prt("[13|14] There are at least $cnt missing substitutions.\n");
            $txt = "# [13|14] There are at least $cnt missing substitutions.\n";
            if ($show_per_file) {
                %hash = ();
                foreach $key (@arr) {
                    $fil = ${$rsnf}{$key};
                    push(@{$hash{$fil}},$key);
                }
                foreach $fil (keys %hash) {
                    $val = $hash{$fil};
                    $cnt = scalar @{$val};
                    $txt .= "\n# Missing $cnt from file [$fil]\n";
                    prt("Missing $cnt [");
                    $msg = '';
                    foreach $key (sort @{$val}) {
                        $txt .= "-m $key \"\"\n";
                        $msg .= ', ' if (length($msg));
                        $msg .= $key;
                    }
                    prt("$msg] from file [$fil]\n");
                }
            } else {
                foreach $key (sort @arr) {
                    $fil = ${$rsnf}{$key};
                    prt("Missing [$key], in [$fil]\n");
                    $txt .= "-m $key \"\"\n";
                }
            }
        } else {
            prt("[13|14] There are NO missing substitutions.\n");
        }
        @arr = split(/\s/,$added_in_init);
        $cnt = scalar @arr;
        if ($cnt) {
            prt("But note ADDED $cnt items, during init...");
            if (length($miss_mac_file) && (length($txt))) {
                $txt .= "\n# Note the following set of $cnt items were added during init...\n";
                %hash = ();
                init_common_subs2(\%hash,0);
                $cnt = 0;
                foreach $key (@arr) {
                    if (defined $hash{$key}) {
                        $val = $hash{$key};
                        if ( (length($val) == 0) || ($val =~ /^\s+$/) ) {
                            $val = '""';
                        }
                        $txt .= "-m $key $val\n";
                        $cnt++;
                    }
                }
                prt(" also now added to response file...");
            }
            prt("\n");
        }
        if (length($miss_mac_file) && (length($txt))) {
            write2file($txt,$miss_mac_file);
            prt("Written list for use as '-r $miss_mac_file' response file, after correction.\n");
        }
    }
}

# =============================================
sub show_warnings($) {
    my $val = shift;
   if (@warnings) {
      prt( "\nGot ".scalar @warnings." WARNINGS...\n" );
      foreach my $itm (@warnings) {
         prt("$itm\n");
      }
      prt("\n");
   } else {
      prt("No warnings issued.\n");
   }
}

sub show_missing_conds() {
    my $rparams = get_ref_params();
    my $rmc = ${$rparams}{'REF_MISSED_CONDITIONS'};
    my $cnt = scalar keys(%{$rmc});
    if ($cnt) {
        if (VERB1()) {
            prt("[v1] List of $cnt missing conditionals...\n");
        } else {
            prt("Would list $cnt missing conditionals... if verbose >= 1\n");
        }
        my ($key,$val,$msg,@arr,$num,%dupes);
        $msg = "# List of $cnt missing conditionals...\n";
        $msg .= "# If used ONLY in TRUE or FALSE, then parameter should be correct.\n";
        $msg .= "# but if used TRUE and FALSE, then must select 0 or 1 only.\n";
        $cnt = 0;
        foreach $key (sort keys %{$rmc}) {
            $cnt++;
            $val = ${$rmc}{$key};
            @arr = split(/\|/,$val);
            %dupes = ();
            foreach $num (@arr) {
                $dupes{$num} = 1;
            }
            @arr = sort keys(%dupes);
            $val = '';
            foreach $num (@arr) {
                $val .= '|' if (length($val));
                $val .= $num;
            }
            $num = '0|1';
            if (scalar @arr == 1) {
                if ($val eq 'FALSE') {
                    $num = 0;
                } elsif ($val eq 'TRUE') {
                    $num = 1;
                } else {
                    $num .= '?';
                }
            } else {
                $msg .= "# TO BE SELECTED\n";
            }
            $msg .= "-c $key:$num\n";
            prt(" $cnt: $key $num ($val)\n") if (VERB1());
        }
        if (length($missed_cond_list)) {
            write2file($msg,$missed_cond_list);
            prt("Written list of $cnt missing conditionals to [$missed_cond_list]\n");
        }
    } else {
        prt("No missing conditionals listed.\n");
    }
}


sub show_missing_subs2($) {
    my ($val) = shift;
    my $rparams = get_ref_params();
    my $rsnf = ${$rparams}{'CURR_SUBS_NOT_FOUND'};
    my @arr = keys %{$rsnf};
    my $cnt = scalar @arr;
    my $msg = '';
    #if ($dbg_lac13) {
    my ($key,$fil);
    if ($cnt) {
        $cnt = scalar @arr;
        prt("There are at least $cnt missing substitutions. ");
        if ($dbg_lac13) {
            prt("\n");
        } else {
            prt("Use '-d 113' to view list...\n");
        }
        foreach $key (sort @arr) {
            $fil = ${$rsnf}{$key};
            prt("Missing [$key], in [$fil]\n") if ($dbg_lac13);
            $msg .= "-m $key \"\"\n";
        }
        if (length($missing_list_file)) {
            write2file($msg,$missing_list_file);
            prt("List written to file [$missing_list_file] for review...\n");
        }
    } else {
        prt("[13] There are NO missing substitutions.\n") if ($val == 0);
    }
    #@arr = split $added_in_init;
    #$cnt = scalar @arr;
    #prt("But note added $cnt, [$added_in_init] in init...\n") if (length($added_in_init));
    #} elsif ($cnt && ($val == 0)) {
    #    prt("There are at least $cnt missing substitutions. Use '-d 13' to view.\n");
    #}
    if (defined ${$rparams}{'TOTAL_LINE_COUNT'} && defined ${$rparams}{'CURR_BEGIN_TIME'}) {
        $cnt = ${$rparams}{'TOTAL_LINE_COUNT'};
        $key = time();
        $fil = $key - ${$rparams}{'CURR_BEGIN_TIME'};
        prt("Scanned a total of ".get_nn($cnt)." lines of source, in ".secs_HHMMSS($fil)." secs...\n");
    }
}

sub pgm_exit($$) {
    my ($val,$msg) = @_;

    show_missing_conds() if ($val == 0);

    show_missing_subs2($val) if ($val != 2);

    if (length($conf_string) && ($val == 0) && !$no_conf_write) {
        write2file($conf_string,$conf_file);
        prt("Written configuration to [$conf_file]\n");
    }

    show_warnings($val) if ($val != 2);

    if (length($msg)) {
        prt("Current CMD: [$curr_command]\n") if (length($curr_command));
        prt("\a\n") if ($msg =~ /^ERROR/);
        $msg =~ s/\n$//;
        $msg .= " time:".localtime(time())."\n";
        prt("$msg\n");
    } else {
        prt("Current CMD: [$curr_command] time [".localtime(time())."]\n");
    }
    close_log($outfile,$load_log);
    exit($val);
}


my %warnings_done = ();
my $last_warning = '';
sub prtw($) {
   my ($tx) = shift;
   $tx =~ s/\n$//;
   # avoid REPETATIVE warnings
   prt("$tx\n") if ($tx ne $last_warning);
   $last_warning = $tx;
   if (!defined $warnings_done{$tx}) {
       $warnings_done{$tx} = 1;
       push(@warnings,$tx);
   }
}


sub write_to_am_list($$) {
    my ($ff,$ok) = @_;
    if (length($amlistfile) && $write_am_list) {
        my $dff = path_u2d($ff);
        my ($nm,$dir) = fileparse($ff);
        my $typ = 3;
        if ($ok) {
            my $lcid = lc(path_u2d(get_root_dir()));  # g_in_dir
            my $lcfd = lc($dir);
            if ($lcid eq $lcfd) {
                $typ = 1;
            } else {
                $typ = 2;
            }
        }
        if (-f $amlistfile) {
            if (open INF, "<$amlistfile") {
                my @lines = <INF>;
                close INF;
                my ($line,@arr,$cnt,$fff);
                my $lcinf = lc($dff);
                foreach $line (@lines) {
                    chomp $line;
                    @arr = split(/\s/,$line);
                    $cnt = scalar @arr;
                    if ($cnt == 2) {
                        $fff = lc($arr[1]);
                        if ($fff eq $lcinf) {
                            return;
                        }
                    }
                }
            }
            append2file("$typ $dff\n",$amlistfile);
        } else {
            write2file("$typ $dff\n",$amlistfile);
        }
    }
}

sub process_ac_file($) {
    my ($rparams) = @_;
    my $inf = ${$rparams}{'CURR_FILE'};
    return if (! -f $inf);
    #($g_in_name, $g_in_dir) = fileparse($inf);
    prt("Scanning [$inf] file...\n");
    scan_configure_ac_file($rparams,0);
    # ======================================================
    show_ac_hash($rparams);
    return $rparams;
}

#====================================================
# do NOT know WHY I have 2 subs that do the SAME thing
# sub sub_root_folder  AND sub_root_dir($)

sub 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 sub_root_folder {
    my ($fil) = shift;
    my $rd = get_root_dir();
    return sub_common_folder($fil,$rd);
}

sub begins_with {
    my ($rt, $pt) = @_;
    my $ln = length($rt);
    my ($i);
    if (length($pt) >= $ln) {
        for ($i = 0; $i < $ln; $i++) {
            return 0 if (substr($rt,$i,1) ne substr($pt,$i,1));
        }
        return 1; # does indeed begin with...
    }
    return 0;
}

sub sub_first_from_second_if($$) {
    my ($d1,$d2) = @_;
    if (being_with($d1,$d2)) {
        $d2 = substr($d2, length($d1));
    }
    return $d2;
}

# VARIOUS FIXES FOR THE FILE NAME
# 1. ensure ALL DOS format
# 2. remove any simple dot relative, like '.\' from beginning
# 3. if given a FULL PATH name, remove C:\FG\20\FlightGear
# 4. if a relative name, remove FligthGear
# 5. if any removal, ensure any beginning '\' is removed
sub sub_root_dir($) {
    my ($ff) = shift;   # = $a_dir.$src
    $ff = path_u2d($ff);
    my $rd = get_root_dir();
    if (begins_with($rd, $ff)) {
        $ff = substr($ff, length($rd));
    }
    return $ff;
}


sub process_one_am_file($);
sub process_one_am_file($) {
    my ($rparams) = @_;
    my $fil = ${$rparams}{'AM_FILE'};
    $fil = fix_rel_path3($fil,'process_one_am_file');
    my $sfil = sub_root_folder($fil);

    ###return if (defined ${$ramsdone}{$fil});
    ###my %h;
    ###${$ramsdone}{$fil} = \%h;
    my $ramh = am_process_AM_file($rparams,0);

    my $ramsdone = ${$rparams}{'REF_AMS_DONE'};
    ${$ramsdone}{$fil} = $ramh;

    my ($p_tit,$p_dir,$p_ext) = fileparse( $fil, qr/\.[^.]*/ );
    my $do_subs = ${$rparams}{'PROCESS_SUBDIR'};
    if ($do_subs && (defined ${$ramh}{'SUBDIRS'})) {
        my $slist = ${$ramh}{'SUBDIRS'};
        my @ar = split(/\s/,$slist);
        my $cnt = scalar @ar;
        prt( "[09] Got $cnt subdirectories [$slist] ...from [$sfil]\n" ) if ($dbg_s09);
        foreach my $dir (@ar) {
            my $am = $p_dir.$dir.'\Makefile.am';
            $am = path_u2d($am);
            $am =~ s/\\\\/\\/g while ($am =~ /\\\\/);
            my $sam = sub_root_folder($am);
            if (-f $am) {
                prt( "[05] Processing AM file [$am], from [$fil] ...\n" ) if ($dbg_s05);
                ${$rparams}{'AM_FILE'} = $am;   # DOS form ensured
                process_one_am_file($rparams);
                ${$rparams}{'AM_FILE'} = $fil;
            } else {
                prtw( "[05] WARNING: AM [$am] NOT FOUND! in [$dir], from [$fil]!\n" ) if ($dbg_s05);
            }
        }
    } 
    return $ramh;
}

sub process_an_am_file($) {
    my ($rparams) = @_;

    my $rh = process_one_am_file($rparams);  # iteratively process the Makefile.am files
    #list_to_arrays($fil,\%g_programs,\%g_libraries,\%g_ams_done);
    #list_to_arrays($rparams);
    ##write_temp_dsp($dsp_outfile);
}

# [dbg_v40] STORE:1: In rcfgs (ra)[Release], [-NEW_OUTD-], [Release|Win32], & $dsp_sub_sub ] )
# [dbg_v40] STORE:2: In rcfgs (ra)[Debug], [-NEW_OUTD-], [Debug|Win32], & $dsp_sub_sub ] )
sub set_default_configs_2($) {
    my ($rh) = @_;
    #my $var1 = "-NEW_OUTD-";
    my $var1 = "";
    my $rcfgs = get_project_configs($rh);   # 'PROJECT_CFGS'
    my ($dsp_sub_sub,$confname,$conf);
    $dsp_sub_sub = get_default_sub3(0);
    $confname = 'Release';
    $conf = 'Release|WIN32';
    push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS'
    ${$rh}{'PROJECT_CCNT'}++;   # count of stored 'PROJECT_CFGS
    $dsp_sub_sub = get_default_sub3(1);
    $confname = 'Debug';
    $conf = 'Debug|WIN32';
    push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS'
    ${$rh}{'PROJECT_CCNT'}++;   # count of stored 'PROJECT_CFGS
}

# ###########################################################
# get DSP replacement values
# ==========================
sub get_user_rt($$) {
    my ($flag,$line) = @_;
    my $urt = '';
    if ($proj_rt eq 'D') {
        if ($flag == 1) {
            $urt = '/MD';
        } else {
            $urt = '/MDd';
        }
    } else {
        if ($flag == 1) {
            $urt = '/MT';
        } else {
            $urt = '/MTd';
        }
    }
    return $urt;
}

# NOTE: Bit 1 == Release, else Debug
sub get_user_libs($$) {
    my ($flag,$line) = @_;
    my $var1 = $proj_libs;
    if ($flag & 1) {
        if (length($proj_libR)) {
            $var1 .= " " if (length($var1));
            $var1 .= $proj_libR;
        }
    } elsif (length($proj_libD)) {
        $var1 .= " " if (length($var1));
        $var1 .= $proj_libD;
    }
    return $var1;
}

sub get_user_incs($$) {
    my ($flag,$line) = @_;
    return $proj_incs;
}

sub get_user_defs($$) {
    my ($flag,$line) = @_;
    return $proj_defs;
}

# 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"'
# our $auto_on_flag = BITS = ${$rparams}{'CURR_AUTO_ON_FLAG'}
sub get_user_output($$) {
    my ($flag,$line) = @_;
    if ($flag & 1) {
        if (length($proj_outputR)) {
            $line = $proj_outputR;
        }
    } elsif (length($proj_outputD)) {
        $line = $proj_outputD;
    }
    return $line;
}

sub get_user_inter($$) {
    my ($flag,$line) = @_;
    if ( $flag & 1 ) {
        if (length($proj_interR)) {
            $line = $proj_interR;
        }
    } elsif (length($proj_interD)) {
        $line = $proj_interD;
    }
    return $line;
}

# setting defines and include
sub add_defined_item($) {
    my $txt = shift;
    $txt = '/D "'.$txt.'"';
    $proj_defs .= ' ' if (length($proj_defs));
    $proj_defs .= $txt;
    $proj_defs = eliminate_dupes($proj_defs);
    prt("Added [$txt] to compiler defines.\n");
}

sub add_include_item($) {
    my $txt = shift;
    $txt = '/I "'.$txt.'"';
    $proj_incs .= ' ' if (length($proj_incs));
    $proj_incs .= $txt;
    $proj_incs = eliminate_dupes($proj_incs);
    prt("Added [$txt] to compiler includes.\n");
}

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

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


sub valid_rp_hash($) {
    my $rp = shift;
    my @arr = qw(PROJECT_NAME PROJECT_TYPE PROJECT_TARGET PROJECT_DBG_WRITE PROJECT_FIX_REL);
    my ($key);
    foreach $key (@arr) {
        if (!defined ${$rp}{$key}) {
            prt("ERROR: $key NOT defined in project hash\n");
            return 0;
        }
    }
    return 1;
}

sub fix_dir_string($) {
    my ($rdir) = @_;
    if (! ( ${$rdir} =~ /(\\|\/)$/) ) {
        ${$rdir} .= "\\";
    }
}

sub is_same_file($$) {
    my ($f1,$f2) = @_;
    my $len = length($f1);
    return 0 if ($len != length($f2));
    my ($i,$c1,$c2);
    for ($i = 0; $i < $len; $i++) {
        $c1 = lc(substr($f1,$i,1));
        $c2 = lc(substr($f2,$i,1));
        return 0 if ($c1 ne $c2);
    }
    return 1;
}

my @missed_dir_cmp = ();
sub mark_in_dir_scan($$) {
    my ($rparams,$relfile) = @_;
    return if (! ${$rparams}{'CURR_DONE_SCAN'} );
    #my $dir = ${$rparams}{'CURR_FILE_DIR'};
    my $dir = ${$rparams}{'TARGET_DIR'};
    fix_dir_string(\$dir);
    my $ff = $dir.$relfile;
    $ff = path_u2d($ff);
    $ff = fix_rel_path($ff);
    my $rda = ${$rparams}{'CURR_DIR_SCAN'};
    my $cnt = scalar @{$rda};
    my ($i,$file);
    ### prt("Mark in dir scan [$relfile] [$ff] of $cnt files...\n");
    for ($i = 0; $i < $cnt; $i++) {
        $file = ${$rda}[$i][1];  # get FULL FILE
        if (is_same_file($ff,$file)) {
            #              0     1   2 3
            #push(@{$rda},[$file,$ff,0,0]);
            ${$rda}[$i][2] = 1;
            last;
        }
    }

    if ($i >= $cnt) {
        push(@missed_dir_cmp,$ff);
        ### prt("Missed in dir scan [$relfile] [$ff] in $i files...\n");
    }
}

sub create_proj_dsp($$$$) {
    my ($fil,$odir,$rparams,$rp) = @_;

    if (!valid_rp_hash($rp)) {
        prtw("WARNING: INTERNAL ERROR: 'project' HAS NOT valid! Check script!\n");
        return;
    }
    my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'};
    my $proj_name = ${$rp}{'PROJECT_NAME'};
    my $proj_type = ${$rp}{'PROJECT_TYPE'};
    my $rinp_srcs = ${$rp}{'PROJECT_SOURCES'};
    my $proj_targ = ${$rp}{'PROJECT_TARGET'};
    my $dbg_write = ${$rp}{'PROJECT_DBG_WRITE'};
    #my $temp_copy_bat  = ${$rp}{'PROJECT_COPY_BAT'};
    my $fix_rel   = ${$rp}{'PROJECT_FIX_REL'};

    my ($nm,$dr,$ex) = fileparse($fil, qr/\.[^.]*/ );

    my $hr = get_default_ref_hash($fil);    # this it the VERSION 1

    my ($line,$key,$group,$filter,$ok,$rdir,$cfil,$cdir,$sfil,$tdsp,$msg);
    my ($name,$type,$i,$conf,$rh2,$flag,$cnt,$i2);
    my ($confname,$var1,$rcfgs);

    $name = $proj_name;

    $tdsp = $odir;
    $tdsp .= "\\" if (!($tdsp =~ /(\\|\/)$/));
    $tdsp .= $proj_name.".dsp";
    
    $key = 'PROJECT_NAME';
    ${$hr}{$key} = $proj_name;
    #$key = 'PROJECT_TYPE';
    $key = 'PROJECT_APTP';
    if ( get_app_type_4_short($proj_type, \$type) ) {
        ${$hr}{$key} = $type;
        prt("[v2] Set project type to [$type], from [$proj_type]\n") if (VERB2());
    } else {
        pgm_exit(1,"ERROR: Unable to get project type from [$proj_type]! Only 'CA', 'SL', 'DLL', 'WA'!\n");
    }

    ${$rp}{'PROJECT_DSP'}     = $tdsp;
    ${$rp}{'PROJECT_DSP_TMP'} = $fil;

    my @sources = ();
    foreach $line (@{$rinp_srcs}) {
        $ok = 0;
        if ($fix_rel) {
            ($cfil,$cdir) = fileparse($line);
            # $rdir = get_relative_path($cdir,$odir);
            $rdir = get_rel_dos_path($cdir,$odir);
            $sfil = $rdir.$cfil;
            #prt("From [$line], to [$proj_targ], got rel [$sfil]\n");
            prt("[v5] for [$line],\n     to [$proj_targ], got\n") if (VERB5());
        } else {
            $sfil = $line;
        }
        prt("[v2] Relative source [$sfil]\n") if (VERB2());
        mark_in_dir_scan($rparams,$line);
        if (is_c_source_extended($line)) {
            # if (($line =~ /\.cxx$/i) || ($line =~ /\.c$/i) || ($line =~ /\.cpp$/i) || ($line =~ /\.cc$/i))
            $filter = get_def_src_filt();
            $group = get_def_src_grp();
            $ok = 1;
        } elsif (is_h_source_extended($line)) {
            # elsif ( ($line =~ /\.hxx$/i) || ($line =~ /\.h$/i) || ($line =~ /\.hpp$/i) )
            $filter = get_def_hdr_filt();
            $group = get_def_hdr_grp();
            $ok = 1;
        } elsif (is_resource_file($line)) {
            $filter = get_def_rcs_filt();
            $group = get_def_rcs_grp();
            $ok = 1;
        }

        if ($ok) {
            #push(@sources, [ $line, $group, $filter, 0, '' ]);
            push(@sources, [ $sfil, $group, $filter, 0, '' ]);
        } else {
            prtw("WARNING: CHECK Discarded [$line]\n");
		}
	}
    if (@sources) {
        $key = 'PROJECT_SRCS';
        ${$hr}{$key} = [@sources];
    } else {
        pgm_exit(1,"ERROR: Project: [$proj_name] No sources!!!\n");
    }

    set_default_configs_2($hr);     # set Release and Debug

    $key = 'PROJECT_CFGS';
    if (defined ${$hr}{$key}) {
        $rcfgs = ${$hr}{$key};
        $cnt = scalar @{$rcfgs};
        prt( "[v5] Got $cnt CONFIGS...\n" ) if (VERB5());
        for ($i = 0; $i < $cnt; $i++) {
            $i2 = $i + 1;
            #                   0          1          2           3
            #                   Debug      -NEW_OUTD- Debug|WIN32
            # push(@{$rcfgs}, [ $confname, $var1,     $conf,      $dsp_sub_sub ]);
            $confname = ${$rcfgs}[$i][0];
            #$var1     = ${$rcfgs}[$i][1]; # has no meaning!!!
            $conf     = ${$rcfgs}[$i][2];
            $rh2      = ${$rcfgs}[$i][3];
            if (($conf =~ /Release/i)||($confname =~ /Release/i)) {
                $flag = 1;
            } elsif (($conf =~ /Debug/i)||($confname =~ /Debug/i)) {
                $flag = 2;
            } else {
                pgm_exit(1,"ERROR: Can NOT set config type as 'Release' or 'Debug'! Got [$conf] [$confname]\n");
            }

            prt("[v5] $i2: [$conf] [$confname] ($flag)\n") if (VERB5());
            foreach $key (keys %{$rh2}) {
                $line = ${$rh2}{$key};
                $var1 = $line;  # start the SAME
                $msg = '';
                if ($key eq '-NEW_OUT-') {  # of form '/out:"bin\foo.exe"'
                    $var1 = ${$rp}{'PROJECT_USER_OUTS'}->($flag,$line);;
                } elsif (($key eq '-NEW_OUTD-') || ($key eq '-NEW_INTER-')) {
                    # Intermediate or Output DIRECTORY
                    $var1 = get_user_inter($flag,$line);
                    if ($auto_on & 1) {
                        if ($proj_name =~ /[\w\.-]+/) {
                            if ($var1 eq '"Debug"') {
                                $var1 = "\"Debug\\$proj_name\"";
                            } elsif ($var1 eq '"Release"') {
                                $var1 = "\"Release\\$proj_name\"";
                            }
                        } else {
                            prtw("WARNING: auto_on_flag=$auto_on, but prog name [$proj_name] NOT just [an,.,-]??? CHECK ME\n");
                        }
                    }
                } elsif ($key eq '-NEW_POST-') {
                    # -NEW_POST- = []
                } elsif ($key eq '-NEW_INCS-') {
                    $var1 = get_user_incs($flag,$line); # -NEW_INCS- = []
                } elsif ($key eq '-NEW_LIBS-') {
                    $var1 = '';
                    if (($proj_type ne 'SL') && ($proj_type ne 'DLL')) {
                        # $var1 = get_user_libs($flag,$line); # -NEW_LIBS- = [Winmm.lib ws2_32.lib]
                        # $var1 = ${$rparams}{'CURR_USER_LIBS'}->($flag,$line);
                        $var1 = ${$rp}{'PROJECT_USER_LIBS'}->($flag,$line); # = ${$rparams}{'CURR_USER_LIBS'};  # normal fetch for 'libraries'
                    }
                } elsif ($key eq '-NEW_DEFS-') {
                    $var1 = get_user_defs($flag,$line); # -NEW_DEFS- = [/D "_CRT_SECURE_NO_WARNINGS"]
                } elsif ($key eq '-NEW_RT-') {
                    $var1 = get_user_rt($flag,$line); # -NEW_RT- = [/MT]
                } else {
                    prtw("WARNING: Key [$key] NOT in if table!?!?\n");
                }
                if ($line ne $var1) {
                    $msg = "changed to [$var1]";
                    ${$rh2}{$key} = $var1;
                }
                prt("[v9] $key = [$line] $msg\n") if (VERB9());
            }
        }
    } else {
        pgm_exit(1,"INTERNAL ERROR: Hash does NOT have key [$key]!\n");
    }

    if ($only_dry_run) {
        prt("Write of DSP to [$fil] AVOIDED, due to DRY RUN ON!\n") if ($dbg_write);
        return;
    }

    # prt("Writing DSP...\n");
    if ( write_hash_to_DSP3( $fil, $hr, $dbg_write ) ) {
        prt("Written DSP to [$fil]\n") if ($dbg_write);
    } else {
        prt("WARNING: FAILED TO WRITE DSP FILE!\n");
    }
}

# ================================================================
# ***TBD*** could preprocess the sources, and add 'missed' headers
# ================================================================
sub write_project_DSP_DSW_files($) {
    my ($rparams) = @_;
    my $rph = ${$rparams}{'REF_PROJECTS_HASH'};
    my $cnt = scalar keys(%{$rph});
    my ($key,$rp,$val,$val2,$dsp,$msg,$n,$d);
    $key = 'PROJECT_NAME';  # should have been set by AC_INIT(...) MACRO
    my $proj_name = 'tempprojname';
    if (defined ${$rparams}{$key}) {
        $proj_name = ${$rparams}{$key};
    }
    my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'};
    prt("\nCreating DSP files for $cnt projects [$proj_name]...\n");
    if (VERB9()) {
        foreach $key (keys %{$rph}) {
            $rp = ${$rph}{$key};
            $val = ${$rp}{'PROJECT_NAME'};
            $val2 = '<FAILED>';    my $proj_type = ${$rp}{'PROJECT_TYPE'};
            get_app_type_4_short(${$rp}{'PROJECT_TYPE'}, \$val2);
            $dsp = ${$rp}{'PROJECT_USER_OUTS'}->(1,"");
            prt("[v9] key [$key] name [$val] [$val2] [$dsp]\n");
        }
    }
    #my @project_list = ();
    foreach $key (keys %{$rph}) {
        $rp = ${$rph}{$key};
        $val = ${$rp}{'PROJECT_NAME'};
        $val2 = $perl_temp_dir."\\temp.$val.dsp";
        prt("\nCreate DSP for project [$val]...\n") if ($project_dbg_write);

        ${$rp}{'PROJECT_TARGET'} = $target_dir;
        ${$rp}{'PROJECT_DBG_WRITE'} = $project_dbg_write;
        #${$rp}{'PROJECT_COPY_BAT'} = $temp_copy_bat;
        ${$rp}{'PROJECT_FIX_REL'} = 0;  # source array already FIXED, relative to $target_dir
        create_proj_dsp($val2,$target_dir,$rparams,$rp);
        $dsp = ${$rp}{'PROJECT_DSP'};
        #                     name  dsp  tempdsp
        #     project_list    0     1     2
        #push(@project_list,[ $tmp, $dsp, $out ]);
        #push(@project_list, [ $val, $dsp, $val2 ]);
    }

    $rph = ${$rparams}{'REF_PROJECTS_HASH'};
    my $dswreal = "$proj_name.dsw";
    my $dswfull = $target_dir.$dswreal;
    my $dswtemp = $perl_temp_dir."\\temp.$dswreal";
    my $cbtemp = $temp_copy_bat; # = $perl_temp_dir."\\tempcopy.bat";
    $cnt = scalar keys(%{$rph});
    if ($cnt) {
        if ($only_dry_run) {
            prt("\nSummary of $cnt project DSP files that would be written, if NOT DRY RUN!\n");
        } elsif (VERB1()) {
            prt("\n[v1] Summary of $cnt project DSP files written...\n");
        }
    } else {
        prt("\nEEK! It looks like NO project DSP files written!\n");
    }

    my $dswtxt = get_dsw_head();
    my $cbtxt = "\@echo Copy of $cnt DSP, plus the DSW to target directory\n";
    $cbtxt .= "\@echo Target is [$target_dir]\n";
    $cbtxt .= "\@if EXIST $target_dir".". goto GOTTARG\n";
    $cbtxt .= "\@echo ERROR: Appears TARGET directory does NOT EXIST!\n";
    $cbtxt .= "\@goto END\n";
    $cbtxt .= ":GOTTARG\n";
    $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" (\n";
    $cbtxt .= "\@echo Due to TEMPNP, will unconditionally OVERWRITE existing files, if any.\n";
    $cbtxt .= ") else (\n";
    $cbtxt .= "\@echo Setting TEMPNP=yes in the environment will skip more pauses, if file exists.\n";
    $cbtxt .= ")\n";
    $cbtxt .= "\@echo *** CONTINUE? ***\n";
    $cbtxt .= "\@pause\n";
    my $lab = '';
    $cnt = 0;
    foreach $key (keys %{$rph}) {
        my $rp = ${$rph}{$key};
        my $nm = ${$rp}{'PROJECT_NAME'};
        my $dsp = "$nm.dsp";
        $val = ${$rp}{'PROJECT_DSP'};
        ($n,$d) = fileparse($val);
        $val2 = ${$rp}{'PROJECT_DSP_TMP'};
        $val = '"'.$val.'"' if ($val =~ /[\s\+]+/);
        $val2 = '"'.$val2.'"' if ($val2 =~ /[\s\+]+/);
        $cnt++;
        $lab = "DOCOPY$cnt";
        $cbtxt .= "\@if NOT EXIST $val goto $lab\n";
        $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" goto $lab\n";
        $cbtxt .= "\@echo Warning: File [$val] ALREADY EXISTS! *** OVERWRITE? ***\n";
        $cbtxt .= "\@pause\n";
        $cbtxt .= ":$lab\n";
        $cbtxt .= "\@echo Copying $n...\n";
        $cbtxt .= "\@copy $val2 $val >nul\n";
        $dswtxt .= get_proj_begin( $nm, $dsp );
        # INSERT PROJECT DEPENDENCIES ***
        $msg = 'NO depends';
        if (defined ${$rp}{'PROJECT_DEPENDS'}) {
            if ($auto_on & 16) {
                my $rpda = ${$rp}{'PROJECT_DEPENDS'};
                $msg = 'with deps [';
                foreach $nm (@{$rpda}) {
                    $dswtxt .= "    Begin Project Dependency\n";
                    $dswtxt .= "    Project_Dep_Name $nm\n";
                    $dswtxt .= "    End Project Dependency\n";
                    $msg .= " $nm";
                }
                $msg .= ']';
            } else {
                $msg .= "add depend NOT enabled (16)";
            }
        }
        $dswtxt .= get_proj_end();
        prt("Project [$key], for [".sub_root_dir(strip_quotes($val))."]\n written [$val2] $msg\n") if (VERB1());
    }
    if ($cnt) {
        $dswtxt .= get_dsw_tail();
        $cnt++;
        $lab = "DOCOPY$cnt";
        $val = $dswfull;
        ($n,$d) = fileparse($val);
        $val2 = $dswtemp;
        $val = '"'.$val.'"' if ($val =~ /[\s\+]+/);
        $val2 = '"'.$val2.'"' if ($val2 =~ /[\s\+]+/);
        prt("For project [$proj_name] DSW [".sub_root_dir(strip_quotes($val))."]\n") if (VERB1());
        $cbtxt .= "\@if NOT EXIST $val goto $lab\n";
        $cbtxt .= "\@if \"\%TEMPNP\%x\" == \"yesx\" goto $lab\n";
        $cbtxt .= "\@echo Warning: File [$val] ALREADY EXISTS! *** OVERWRITE? ***\n";
        $cbtxt .= "\@pause\n";
        $cbtxt .= ":$lab\n";
        $cbtxt .= "\@echo Copying $n...\n";
        $cbtxt .= "\@copy $val2 $val >nul\n";
        $cbtxt .= "\@echo All $cnt copied, done...\n";
        $cbtxt .= "\@echo Change to [$target_dir], and run MSVC... Good luck ;=))\n";

        $cbtxt .= ":END\n";
        if ($only_dry_run) {
            prt(" would write [$dswtemp]...if NOT DRY RUN\n") if (VERB1());
        } else {
            rename_2_old_bak_plus($dswtemp);
            write2file($dswtxt,$dswtemp);
            prt(" written [$dswtemp]...\n") if (VERB1());
            write2file($cbtxt,$cbtemp);
            prt("Written BATCH file [$cbtemp], to COPY the $cnt 'temp' DSW/DSP files\n to TARGET [$target_dir]... ");
            if (-d $target_dir) {
                prt("ok\n");
            } else {
                prt("WARNING: DOES NOT EXIST!\n");
            }
        }
    } else {
        prt("No project DSP files written, nor a DSW! Sorry...\n");
    }
}


sub process_am_list($) {
    my ($rparams) = @_;
    my ($key,$val,$cnt,$ky2,$val2,$len,$min,$ff,$ok);
    my $inf = ${$rparams}{'CURR_FILE'};
    my $rh =  ${$rparams}{'CURR_HASH'};
    my $supp_make_in = ${$rparams}{'SUPP_MAKE_IN'};
    my ($in_name, $in_dir) = fileparse($inf);
    $key = 'A_MAKE_INPUT_LIST';
    if (defined ${$rh}{$key}) {
        $val = ${$rh}{$key};
        $cnt = scalar @{$val};
        prt("\nprocess_am_list: $key with $cnt items in array...\n");
        # try to get the ROOT AM FILE
        foreach $ky2 (@{$val}) {
            $ff = $in_dir.$ky2.".am";
            if (-f $ff) {
                if (!($ky2 =~ /(\\|\/)/)) {
                    ${$rparams}{'ROOT_AM_FILE'} = $ff;
                    last;
                }
            } elsif ($supp_make_in) {
                $ff = $in_dir.$ky2.".in";
                if (-f $ff) {
                    if (!($ky2 =~ /(\\|\/)/)) {
                        ${$rparams}{'ROOT_AM_FILE'} = $ff;
                        last;
                    }
                }
            }
        }
        foreach $ky2 (@{$val}) {
            $ff = path_u2d($in_dir.$ky2.".am");
            if (-f $ff) {
                $ok = ".am ok";
                ${$rparams}{'AM_FILE'} = $ff;
            } elsif ($supp_make_in) {
                $ff = path_u2d($in_dir.$ky2.".in");
                if (-f $ff) {
                    $ok = ".in ok";
                    ${$rparams}{'AM_FILE'} = $ff;
                } else {
                    $ok = "'am' or 'in' NOT FOUND [$ff]";
                }
            } else {
                $ok = "'am' NOT FOUND [$ff]";
            }
            if ($ok =~ /ok/) {
                process_an_am_file($rparams);
            } else {
                prtw("WARNING: Missing AM File: [$ky2] $ok\n");
            }
        }
    }
    if (defined ${$rparams}{'ROOT_AM_FILE'}) {
       ${$rparams}{'AM_FILE'} = ${$rparams}{'ROOT_AM_FILE'};
    }
}

sub get_perl_temp_dir() {
    if (! -d $perl_temp_dir) {
        mkdir $perl_temp_dir;
        if (! -d $perl_temp_dir) {
            pgm_exit(1,"ERROR: Unable to create directory [$perl_temp_dir]\nMaybe there is already a file of that name, or...\n");
        }
    }
}

sub do_sanity_check() {
    pgm_exit(1,"ERROR: Problem with lib_acscan DEBUG!\n") if (ac_get_dbg_range() != $dbg_lac_check);
    pgm_exit(1,"ERROR: Problem with lib_amscan DEBUG!\n") if (am_get_dbg_range() != $am_check_tot );
    get_perl_temp_dir();
}

sub module_intialisation($) {
    my ($fil) = @_;
    #my $auto_on = ${$rparams}{'CURR_AUTO_ON_FLAG'};
    set_blank_header_group() if ($auto_on_flag & 64);
    # my $proj_defs = '/D "_CRT_SECURE_NO_WARNINGS"';
    add_defined_item('HAVE_CONFIG_H') if ($auto_on_flag & 128);
    my $rparams = init_common_subs($fil);
    ${$rparams}{'CURR_MISSED_SOURCES'} = $missed_source_list;
    return $rparams;
}

#########################################
### MAIN ###
# check the DEBUG stuff is ok
do_sanity_check();

parse_args(@ARGV);

my $rph = module_intialisation($in_file); # establish $root_folder, and init %g_common_subs

process_ac_file($rph);  # mainly to get substitutions, and get the Makefile AM file output list

process_am_list($rph);  # process EACH Makefile.AM individually

am_list_to_arrays($rph);    # move the AM information into 'project' HASHES

write_project_DSP_DSW_files($rph); # write the 'project' HASHES to DSP, and finally a DSW

am_out_dir_scan_info($rph);

pgm_exit($exit_value,"Normal exit(0)");

########################################
### COMMAND LINE PARSING ###

sub show_dbg_ranges() {
    my ($max,$tmp);
    $max = ac_get_dbg_range();
    prt(" --dbg <num>    (-d) = Set DEBUG flag of this value.\n");
    prt("   For AC lib_acscan, numbers in range 101 to 1$max\n");
    $max = am_get_dbg_range();
    prt("   For AM lib_amscan, numbers in range 201 to 2$max\n");
    $tmp = ac_get_dbg_stg();
    prt("   Presently $tmp are ON in lib_acscan.\n") if (length($tmp));
    $tmp = am_get_dbg_stg();
    prt("   Presently $tmp are ON in lib_amscan.\n") if (length($tmp));
    prt("   Additional text setting are 'all', 'none', 'extra', and 'help'.\n");
}


sub give_help {
    my ($tmp);
    prt("$pgmname: $my_version\n");
    prt("Usage: $pgmname [options] in-file\n");
    prt("Options:\n");
    prt(" --help   (-h or -?) = This help, and exit 0.\n");
    prt(" --auto on|off  (-a) = Automate certain preferred outputs. Use '-a help' for more.\n");
    prt(" --cond item    (-c) = Define a conditional item. Can add [:1|0]. Default is 1 (TRUE).\n");
    show_dbg_ranges();
    prt(" --DEF <FGFS>   (-D) = Add a defined macro, like '/D \"FGFS\"', to the DSP compile.\n");
    prt(" --INC <path>   (-I) = Add an include macro, like '/I \"path\"', to the DSP compile.\n");
    prt(" --LIB <set>    (-L) = Add a dependant libraries, to programs being built.\n");
    prt(" --load-log     (-l) = Load log file at end. (def=".($load_log ? "On" : "Off").")\n");
    prt(" --mac item val (-m) = Store a MACRO, item=value, for substitution. (use '-d 13' to list missing).\n");
    prt(" --name <name>  (-n) = Overrride any name in the AC_INIT/AM_INIT_AUTOMAKE.\n");
    prt(" --previous     (-p) = Load previous commands from [$conf_file]\n") if (-f $conf_file);
    prt(" --resp <file>  (-r) = Commands from a reponse/input file.\n");
#    prt(" --ROOT <dir>   (-R) = Set the project ROOT directory.\n");
    prt(" --supp_in      (-s) = Suupport Makefile.in, if NO Makefile.am. (def=$supp_make_in)\n");
    prt(" --targ <dir>   (-t) = Establish a target directory for the DSW/DSP files.\n");
    prt(" --verbosity    (-v) = Bump verbosity of this module. Default [$verbosity] to 9 (-vvvvvvvvv)\n");
    prt(" --wr_dbg <num> (-w) = Add debug during the DSP write output. Bit values. -1 for all.\n");
    prt("Purpose:\n");
    prt(" Scan the input file as a configure.ac file, then scan the Makefile.am entries indicated by the\n");
    prt("  AC_OUTPUT macro, and output MSVC DSW/DSP build files for the contents found.\n");
    prt("NOTES:\n");
    prt(" Auto output does the following, and more: For libaries: D:'/out:\"lib\\barD.lib\"'; R:\n");
    prt("  '/out:\"lib\\barD.lib\"'. For programs: D:'/out:\"bin\\fooD.exe\"'; R:'/out:\"bin\\foo.exe\"'\n");
    prt("  Use '-a help' for fuller list of this 'auto' feature BIT effects.\n");
    prt(" The LIB <set> consists of <name:path:[D|R|B]>. The 'path' can be blank, absolute, or relative\n");
    prt("  to the 'target' directory of the program DSP. D=Debug, R=Release, B=Both\n");
    prt(" Do NOT add the /D or /I to the macro defined or included. This will be added internally,\n");
    prt("  and note the upper case for -D, -I and -L.\n");
    prt(" Setting a macro is 3 entries, like '-m item value', thus if set a blank is required, use\n");
    prt("  '-m item \"\"'. Macros substitutions found missing are written to the file\n");
    prt("  [$miss_mac_file] for review, and then using as a '-r <file>' response input file.\n");
    prt(" The debug switch is strictly for that. It adds no functionality, just a noisier output,\n");
    prt("  and thus allow a DEBUG view of what the script 'saw', and 'did' to potentially\n");
    prt("  'fix' the script.\n");
    prt(" Unless there are two commands using the same letter, normally case, and after the first\n");
    prt("  letter are ignored.\n");
}

sub show_dbg_help() {
    my $file = $0;
    my ($line,$max,$tmp,$cnt,$tmp2);
    show_dbg_ranges();
    if (open INF, "<$file") {
        my @lines = <INF>;
        close INF;
        prt(" Detailed list, with some 'notes' indicating what each does.\n");
        $cnt = 0;
        my @ac_dbg = ();
        my @am_dbg = ();
        foreach $line (@lines) {
            $line = trim_all($line);
            if ($line =~ /^our\s+\$dbg_lac(\d+)\s*=\s*\d+\s*;\s*#(.+)$/) {
                $tmp = $1;
                $tmp2 = $2;
                push(@ac_dbg,"1$tmp: $tmp2");
                $cnt++;
            } elsif ($line =~ /^our\s+\$dbg_s(\d+)\s*=\s*\d+\s*;\s*#(.+)$/) {
                $tmp = $1;
                $tmp2 = $2;
                push(@am_dbg,"2$tmp: $tmp2");
                $cnt++;
            }
        }
        if ($cnt) {
            if (@ac_dbg) {
                $cnt = scalar @ac_dbg;
                prt("For DEBUG of AC file scan... $cnt\n");
                foreach $tmp (@ac_dbg) {
                    prt(" $tmp\n");
                }
            } else {
                prt("PROBLEM: NO lib_acscan ADDITIONAL debug HELP!\n");
            }
            if (@am_dbg) {
                $cnt = scalar @am_dbg;
                prt("For DEBUG of AM file scans... $cnt\n");
                foreach $tmp (@am_dbg) {
                    prt(" $tmp\n");
                }
            } else {
                prt("PROBLEM: NO lib_amscan ADDITIONAL debug HELP!\n");
            }
            prt("NOTE: Adding DEBUG output only serves to DEBUG what the script 'saw', and 'did'!\n");
        } else {
            prt("\nPROBLEM: Found no \$dbg?? vars in file [$file], so NO DEBUG ADDITIONAL HELP!\n");
        }
    } else {
        prt("ERROR: Unable to open file [$file], so NO ADDITIONAL DEBUG HELP!\n");
    }
}

sub local_strip_both_quotes($) {
    my $txt = shift;
    if ($txt =~ /^'(.+)'$/) {
        return $1;
    }
    if ($txt =~ /^"(.+)"$/) {
        return $1;
    }
    return '' if ($txt eq '""');
    return '' if ($txt eq "''");
    #prt("Stripping [$txt] FAILED\n");
    return $txt;
}

my $in_input_file = 0;
sub load_input_file($$) {
    my ($arg,$file) = @_;
    if (open INF, "<$file") {
        my @lines = <INF>;
        close INF;
        my @carr = ();
        my ($line,@arr,$tmp);
        foreach $line (@lines) {
            $line = trim_all($line);
            next if (length($line) == 0);
            next if ($line =~ /^#/);
            @arr = split(/\s/,$line);
            foreach $tmp (@arr) {
                $tmp = local_strip_both_quotes($tmp);
                push(@carr,$tmp);
            }
        }
        $in_input_file++;
        parse_args(@carr);
        $in_input_file--;
    } else {
        pgm_exit(1,"ERROR: Unable to 'open' file [$file]!\n")
    }
}

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

sub add_2_commands($) {
    my ($ra) = @_;  # = \@av
    my ($itm);
    foreach $itm (@{$ra}) {
        $curr_command .= ' ' if (length($curr_command));
        $curr_command .= $itm;
    }
}

sub show_auto_help() {
    my $file = $0;
    my ($line,$max,$tmp,$cnt,$tmp2);
    my $auto_on = $auto_on_flag;
    if (open INF, "<$file") {
        my @lines = <INF>;
        close INF;
        prt("Bit list, with some 'notes', indicating what each BIT does.\n");
        $cnt = 0;
        foreach $line (@lines) {
            chomp $line;
            if ($line =~ /\#Bit:/) {
                prt("$line\n");
                $cnt++;
            }
        }
        prt("ERROR: Not able to find auto on flag lines!\n") if ($cnt == 0);
    } else {
        prt("Unable to open file [$file], no auto help NOT available!\n");
    }
    $tmp = 1;
    $tmp2 = '';
    while ($tmp) {
        if ($auto_on & $tmp) {
            $tmp2 .= ' ' if (length($tmp2));
            $tmp2 .= "$tmp";
        }
        $tmp = $tmp << 1;
        last if ($tmp > $auto_max_bit);
    }
    prt("Current auto on = $auto_on. Bits: [$tmp2]\n");

    pgm_exit(0,"End AUTO help ($cnt)\n");
}

sub set_auto_flag($$) {
    my ($arg,$sarg) = @_;
    my $ok = -1;
    my $num = 0;
    if ($sarg =~ /^\d+\+\d+/) {
        my @arr = split(/\+/,$sarg);
        $num = 0;
        foreach (@arr) {
            $num += $_;
        }
        $sarg = $num;
    }
    if ($sarg =~ /^-(\d+)$/) {
        $num = $1;
        $num *= -1;
        $ok = 1;
    } elsif ($sarg =~ /^(\d+)$/) {
        $num = $1;
        if ($num > 0) {
            $ok = 1;
        } else {
            $ok = 0;
        }
    } else {
        if ($sarg =~ /^on$/i) {
            $ok = 1;
            $num = -1;
        } elsif ($sarg =~ /^off$/i) {
            $ok = 0;
            $num = 0;
        } elsif ($sarg =~ /^help$/i) {
            show_auto_help();
        } else {
            pgm_exit(1,"ERROR: Unknown command '$arg $sarg'! Can only be 'on', 'off', or integer. (or -1 for all)\n");
        }
    }
    if ($ok == 1) {
        $ok = 'ON';
        $auto_on_flag = $num;
    } else {
        $auto_on_flag = $num;
        $ok = 'OFF';
    }
    prt("Set auto on flag $ok ($auto_on_flag)\n");
}

# like $proj_lib .= " /libpath:\"lib\";
# like $proj_libD .= " fooD.lib";
# like $proj_libR .= " foo.lib";
# sub in line ADD LINK32 kernel32.lib ... -NEW_LIBS- /nologo ...
#my $proj_libs = 'Winmm.lib ws2_32.lib';
#my $proj_libD = '';
#my $proj_libR = '';
sub add_user_libs($$) {
    my ($arg,$libs) = @_;
    my @arr = split(":",$libs);
    my $cnt = scalar @arr;
    my ($lib,$path,$dest,$rtarg,$stg,$typ);
    if ($cnt == 3) {
        $lib = strip_quotes($arr[0]);
        $path = strip_quotes($arr[1]);
        $dest = $arr[2];
        if ($dest eq 'D') {
            $rtarg = \$proj_libD;
            $typ = 'Debug';
        } elsif ($dest eq 'R') {
            $rtarg = \$proj_libR;
            $typ = 'Release';
        } elsif ($dest eq 'B') {
            $rtarg = \$proj_libs;
            $typ = 'Both';
        } else {
            pgm_exit(1,"ERROR: For '$arg $libs', the 3rd item MUST be 'D', 'R', or 'B', NOT '$dest'!\n");
        }
        if ($lib =~ /\s/) {
            $stg = "\"$lib\"";
        } else {
            $stg = "$lib";
        }
        if (length($path)) {
            $stg .= " /libpath:\"$path\"";
        }
        if (length(${$rtarg})) {
            ${$rtarg} .= ' ';
        }
        ${$rtarg} .= $stg;
        prt("Added '$stg' to $typ program library dependence.\n");
    } else {
        pgm_exit(1,"ERROR: For '$arg $libs', the 'set' did NOT split into 3 items!\n".
            " The LIB <set> consists of <name:path:[D|R|B]>. The 'path' can be blank, absolute, or relative\n".
            "  to the 'target' directory of the program DSP. D=Debug, R=Release, B=Both\n");
    }
}

sub set_cond_item($$) {
    my ($arg,$sarg) = @_;
    my @arr = split(":",$sarg);
    my $item = $arr[0];
    my $val = 'TRUE';
    my ($tmp);
    if (scalar @arr > 1) {
        $tmp = $arr[1];
        if ( ($tmp =~ /^\d+$/) && (($tmp == 1)||($tmp == 0)) ) {
            $val = 'FALSE' if ($tmp == 0);
        } else {
            pgm_exit(2,"ERROR: Argument can only be $item + :1 or :0, not [$tmp]\n");
        }
    }
    if (defined $g_user_condits{$item}) {
        prt("Resetting conditional [$item] to [$val]\n");
    } else {
        prt("Setting conditional [$item] to [$val]\n");
    }
    $g_user_condits{$item} = $val; # stored as ${$rparams}{'REF_DEF_CONDITIONS'}
}


sub parse_args {
    my (@av) = @_;
    my ($arg,$sarg,$tmp,$rngac,$rngam);
    add_2_commands(\@av);
    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();
                $conf_string = "";
                pgm_exit(0,"Help exit(0)");
            } elsif ($sarg =~ /^a/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                set_auto_flag($arg,$sarg);
            } elsif ($sarg =~ /^c/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                set_cond_item($arg,$sarg);
            } elsif ($sarg =~ /^D/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                add_defined_item($sarg);
                $conf_string .= "$arg $sarg\n";
            } elsif ($sarg =~ /^d/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $conf_string .= "$arg $sarg\n";
                if ($sarg =~ /^(\d+)$/) {
                    $tmp = $1;
                    $rngac = ac_get_dbg_range();
                    $rngam = am_get_dbg_range();
                    if (($tmp > 200) && (($tmp - 200) <= $rngam)) {
                        if (am_set_dbg_var($tmp - 200)) {
                            prt("Set AM lib Debug $tmp ON!\n");
                        } else {
                            pgm_exit(1,"ERROR: FAILED to set AM lib Debug $tmp ON!\n");
                        }
                    } elsif (($tmp > 100) && (($tmp - 100) <= $rngac)) {
                        if (ac_set_dbg_var($tmp - 100)) {
                            prt("Set AC lib Debug $tmp ON!\n");
                        } else {
                            pgm_exit(1,"ERROR: FAILED to set AC lib Debug $tmp ON!\n");
                        }
                    } else {
                        $rngac += 100;
                        $rngam += 200;
                        pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Is numerical, but not range 101 to $rngac, nor 202 to $rngam!\n");
                    }
                } else {
                    if ($sarg =~ /^help$/i) {
                        show_dbg_help();
                        $conf_string = "";
                        pgm_exit(0,"DEBUG Help exit(0)\n");
                    } elsif ($sarg =~ /^all$/i) {
                        prt("Setting ALL debug ON!\n");
                        set_all_dbg_on();
                    } elsif ($sarg =~ /^none$/i) {
                        prt("Setting ALL debug OFF!\n");
                        set_all_dbg_off();
                    } elsif ($sarg =~ /^dry-run$/i) {
                        prt("Setting DRY RUN ONLY!\n");
                        $only_dry_run = 1;
                    } elsif ($sarg =~ /^extra$/i) {
                        prt("Setting ALL debug ON, plus EXTRA!\n");
                        set_max_debug_on();
                    } else {
                        pgm_exit(1,"ERROR: Invalid argument [$arg $sarg]! Not numerical, nor 'all', 'none', or 'help' !\n");
                    }
                }
            } elsif ($sarg =~ /^I/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                add_include_item($sarg);
                $conf_string .= "$arg $sarg\n";
            } elsif ($sarg =~ /^l/) {
                $conf_string .= "$arg\n";
                $load_log = 1;
            } elsif ($sarg =~ /^L/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                add_user_libs($arg,$sarg);
                $conf_string .= "$arg $sarg\n";
            } elsif ($sarg =~ /^m/i) {
                # store a macro
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                need_arg(@av);
                shift @av;
                $tmp = $av[0];
                $g_user_subs{$sarg} = $tmp; # supplied by USER INPUT
                prt("Set MACRO [$sarg] = [$tmp] in common subs...\n");
                $tmp = '""' if ((length($tmp) == 0)||($tmp =~ /^\s+$/));
                $conf_string .= "$arg $sarg $tmp\n";
            } elsif ($sarg =~ /^n/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $project_name = $sarg;
                prt("Set default over-all project name to [$project_name]\n");
            } elsif ($sarg =~ /^p/i) {
                if (-f $conf_file) {
                    prt("Loading previous commands from [$conf_file]\n");
                    load_input_file($arg,$conf_file);
                    $no_conf_write = 1;
                } else {
                    pgm_exit(1,"ERROR: No previous config file [$conf_file] to load!\n");
                }
            } elsif ($sarg =~ /^r/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                prt("Loading from response file [$sarg]...\n");
                load_input_file($arg,$sarg);
            } elsif ($sarg =~ /^s/) {
                $supp_make_in = 1;
                prt("Added support for Makefile.in.\n");
            } elsif ($sarg =~ /^t/i) {  # target directory for DSP file(s)
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $target_dir = File::Spec->rel2abs($sarg);
                $fix_relative_sources = 1;
                prt("Set to TARGET folder to [$target_dir].\n");
            } elsif ($sarg =~ /^v/i) {
                while ($sarg =~ /^v/i) {
                    $verbosity++;
                    $sarg = substr($sarg,1);
                }
                prt("Set verbosity to [$verbosity]\n");
            } elsif ($sarg =~ /^w/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $project_dbg_write = $sarg;
                prt("Set write debug to $project_dbg_write\n");
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            $in_file = File::Spec->rel2abs($arg);
            if (-f $in_file) {
                $conf_string .= "$in_file\n";
                prt("Set input to [$in_file]\n");
            } else {
                pgm_exit(1,"ERROR: Unable to locate file [$in_file]! Check name, location...\n");
            }
        }
        shift @av;
    }

    if (!$in_input_file) {
        if ((length($in_file) ==  0) && $debug_on) {
            my @carr = ();
            push(@carr,"-d"); push(@carr,"extra");
            #push(@carr,"-d"); push(@carr,"dry-run");

            push(@carr,"$def_file");
            # for libxm2
            push(@carr,"-s"); # $supp_make_in = 1; # Support Makefile.in scanning
            push(@carr,"-I"); push(@carr,"..\\include");
            push(@carr,"-D"); push(@carr,"LIBXML_STATIC");
            push(@carr,"-m"); push(@carr,'THREAD_W32'); push(@carr,'Win32');
            push(@carr,"-d"); push(@carr,113);

            # for libgif
            #push(@carr,"-I"); push(@carr,"..\\lib");
            #push(@carr,"-I"); push(@carr,"..\\windows");

            # for sigc++
            # $g_user_subs{'SIGCXX_API_VERSION'} = 2; # supplied by USER INPUT

            # for pcre
            #push(@carr,"-s"); # $supp_make_in = 1; # Support Makefile.in scanning
            #push(@carr,"-D"); push(@carr,"PCRE_STATIC");

            #push(@carr,"-l\n"); # $load_log = 1;
            if ((length($target_dir) ==  0) && length($def_targ)) {
                push(@carr,"-t"); push(@carr,"$def_targ"); # $target_dir = $def_targ;
            }
            if (length($def_name) && (length($project_name) == 0)) {
                push(@carr,"-n"); push(@carr,$def_name);
            }
            $in_input_file++;
            parse_args(@carr);
            $in_input_file--;
        }

        if (length($in_file) ==  0) {
            pgm_exit(2,"ERROR: No 'configure.ac' input file found in command!\n");
        }
        if (! -f $in_file) {
            pgm_exit(2,"ERROR: Can NOT find file [$in_file]! Check name, location!\n");
        }
    }
    #wait_key();

}

# =============================================================================================
# TO BE DONE - ***TBD*** Other items thought of, but not yet implemented
#
# - Adding headers - ok this is good, but most headers get attached to the LIBRARIES,
#   since they are processed FIRST. There should be a better scheme for this. But can not
#   immediately see how to handle it yet.
#   And in one instance in Glib-1.24.2 I saw one header added twice - I though I had BLOCK this!
#   AND, since I now know all the headers included by a file, the script SHOULD make sure
#   the additional include directories is updated to find this/these headers.
#
# - noinst_PROGRAMS, check_PROGRAMS versus bin_PROGRAMS
#   Maybe the DSP for no-install prograsm could be still written, BUT not included in
#   the main DSW file. Maybe a 2nd DSW file could be written for these 'check' and 'no-install'
#   programs.
#
# - There are times when combining some static libraries could be good, but care should be taken with
#   this, because this separation is important in most cases. Maybe
#   --join a:b:c d  (-j) = Join projects named 'a', 'b', and 'c', and make a project 'd'
#
# - config.h - When it is noted that the source uses a 'config.h', maybe generate a common file
#   in the target directory, and make sure it is added to the most important library/programs, if pos.
#
# - missing source - certain Makefile.am will have a $host switch to INCLUDE say MAC or Windows
#   sources in say a library, but these will not always get picked up and put in the library.
#   Conversely, sometimes say MAC items will get picked up when they should not. Need a way to
#   (a) Force the INCLUSION of certain source to a project, and
#   (b) Force the EXCLUSION of certain sources from a project.
#   These sources are presently only written to the $missed_source_list file,
#   but this seems now well handled, at least partially, by the new --cond item:[0|1] option
#
#   Be able to ADD use dependencies to the DSW file, especially for additional libraries that
#   may NOT be in a LDADD entries - like they are only for WIN32
#   Maybe --PROJ <dep) (-P) = Project dependence added to DSW file.
#
#   An idea to force ALL libraries to be compiled first would be to add a 'dummy' application,
#   and add dependence of each library to it...
#
# =============================================================================================
# eof - amsrcs04.pl
