#!/usr/bin/perl -w
# NAME: createdsp.pl
# AIM: Given a set of source files, generate a simple DSP file, using the first source
# name as the project name, unless given other parameters...
# 25/08/2010 - Review and update
# 09/08/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_dir = 'C:\GTools\perl';
unshift(@INC, $perl_dir);
require 'fgutils02.pl' or die "Unable to load fgutils02.pl ...\n";
require 'fgdsphdrs03.pl' or die "Unable to load fgdsphdrs03.pl ...\n";
require 'scanvc.pl' or die "Unable to load scanvc.pl ...\n";
require 'chkmain.pl' or die "Unable to load chkmain.pl ...\n";
# log file stuff
my ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
    my @tmpsp = split(/(\\|\/)/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $perl_dir."\\temp.$pgmname.txt";
open_log($outfile);

# user variables
my $load_log = 0;
my $verbose = 0;

my $in_file = '';
my $proj_name = '';
my $proj_type = ''; # 'CA' => $app_console_stg, 'WA' => $app_windows_stg, 'DLL' => $app_dynalib_stg, 'SL' => $app_statlib_stg
my $dsp_out = $perl_dir."\\tempcdsp.dsp";
my $proj_targ = ''; # target directory for DSP file
my $copy_bat = $perl_dir."\\tempcb.bat";
if (-d 'C:\MDOS') {
    $copy_bat = 'C:\MDOS\tempcb.bat';
}

my $proj_libs = '';
my $proj_libD = '';
my $proj_libR = '';

my $proj_rt = 'D';
my $proj_incs = '';
my $proj_defs = '';

# NOTE: This is for BOTH '/out:"bin\foo.exe"' AND '/libpath:"lib"' COMBINED
my $proj_outR = '';
my $proj_outD = '';

my $outdefault = 0;

my $proj_interR = '';
my $proj_interD = '';

my $src_dir = '';

### program variables
my @inp_sources = ();
my @warnings = ();
my $cwd = cwd();
my $os = $^O;

### DEBUG
my $debug_on = 0;
my $def_source = 'C:\Projects\shapelib-1.2.10\contrib\shpinfo.c';
my $dbg_out = 0;
my $dbg_write = 0;  # 8; # for substitutions

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

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


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

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

sub check_proj_name() {
    if (length($proj_name) == 0) {
        my $file = $inp_sources[0];
        my ($dir,$ext);
        ($proj_name,$dir,$ext) = fileparse($file, qr/\.[^.]*/ );
        prt("Set project name to [$proj_name], from first input file [$file]\n");
    }
}

sub check_out_dir() {
    if (length($proj_targ) == 0) {
        my $file = $inp_sources[0];
        my ($dir,$ext);
        ($proj_name,$dir,$ext) = fileparse($file, qr/\.[^.]*/ );
        $dir .= 'msvc';
        $proj_targ = $dir;
        prt("Set DSP output to [$proj_targ]\n");
    }
}


sub check_proj_type() {
    if (length($proj_type) == 0) {
        my ($file,$fnd,$cnt,@arr);
        my ($res, $res1, $res2);
        $cnt = scalar @inp_sources;
        $fnd = 0;
        foreach $file (@inp_sources) {
            if (-f $file) {
                $fnd++;
                $res1 = chk_main($file,\@arr);
                $res2 = chkmain2($dbg_out,$file);
                if (($res1 && !$res2)||(!$res1 && $res2)) {
                    pgm_exit(1,"ERROR: Got different results 'chk_main', 'chkmain2'! CHECK IT OUT!\n");
                }
                if ($res1) {
                    if ($res) {
                        prtw("WARNING: Two files have a MAIN!\n");
                    }
                }
                $res += $res1;
            }
        }
        if ($fnd != $cnt) {
            pgm_exit(1,"ERROR: Unable to find some source files! Unable to set default type!\n");
        }
        if ($res) {
            $proj_type = 'CA';
            prt("Found $res 'main', so assume is console application. ($proj_type)\n");
        } else {
            $proj_type = 'SL';
            prt("Found NO 'main', in $cnt sources, so assume is static library. ($proj_type)\n");
        }
    }
}

# set DSP /out="bin\foo.exe", if NONE given, and $outdefault set
sub check_out_name() {
    if ($outdefault) {
        my ($ext,$val,$msg,$out);
        $msg = '';
        $ext = '.exe';  # default to EXE
        $out = 'bin';   # output to 'bin' directory
        if ($proj_type eq 'SL') {
            $out = 'lib';   # change to 'lib' directory,
            $ext = '.lib';  # and '.lib' extension
        }
        # NOTE: This is for BOTH '/out:"bin\foo.exe"' AND '/libpath:"lib"' COMBINED
        if ((length($proj_outR) == 0) || !($proj_outR =~ /\/out:/)) {
            $val = "/out:\"$out\\$proj_name".$ext."\"";
            $proj_outR .= " " if (length($proj_outR));
            $proj_outR .= $val;
            $msg .= "Set default: $val\n";
        }
        if ((length($proj_outD) == 0) || !($proj_outD =~ /\/out:/)) {
            $val = "/out:\"$out\\$proj_name".'d'.$ext."\"";
            $proj_outD .= " " if (length($proj_outD));
            $proj_outD .= $val;
            $msg .= "Set default: $val\n";
        }

        # object output and intermediate directory
        if (length($proj_interR) == 0) {
            $val = "\"Release\\$proj_name\"";
            $proj_interR = $val;
            $msg .= "Set intermediate: $val\n";
        }
        if (length($proj_interD) == 0) {
            $val = "\"Debug\\$proj_name\"";
            $proj_interD = $val;
            $msg .= "Set intermediate: $val\n";
        }

        if (VERB()) {
            if (length($msg)) {
                prt("Due to [outdefault] set, settings...\n$msg");
            }
        }
    }
}

# [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 $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
}

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;
}

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;
        }
    } else {
        if (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;
}

sub get_user_out($$) {
    my ($flag,$line) = @_;
    if ( ($flag == 1) && ( length($proj_outR) ) ) {
        return $proj_outR;
    }
    if (($flag == 2)&&(length($proj_outD))) {
        return $proj_outD;
    }
    return $line;
}

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


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

    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("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");
    }

    my @sources = ();
    foreach $line (@inp_sources) {
        $ok = 0;
        ($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("for [$line],\n to [$proj_targ], got\n") if (VERB5());
        prt("Rel [$sfil]\n") if (VERB2());
        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: 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( "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("$i2: [$conf] [$confname] ($flag)\n") if (VERB5());
            foreach $key (keys %{$rh2}) {
                $line = ${$rh2}{$key};
                $var1 = $line;  # start the SAME
                $msg = '';
                if ($key eq '-NEW_OUTD-') {
                    $var1 = get_user_inter($flag,$line); # -NEW_OUTD- = ["Release"]
                } elsif ($key eq '-NEW_POST-') {
                    # -NEW_POST- = []
                } elsif ($key eq '-NEW_INTER-') {
                    $var1 = get_user_inter($flag,$line); # -NEW_INTER- = ["Release"]
                } elsif ($key eq '-NEW_INCS-') {
                    $var1 = get_user_incs($flag,$line); # -NEW_INCS- = []
                } elsif ($key eq '-NEW_LIBS-') {
                    $var1 = get_user_libs($flag,$line); # -NEW_LIBS- = [Winmm.lib ws2_32.lib]
                } elsif ($key eq '-NEW_OUT-') {
                    $var1 = get_user_out($flag,$line); # -NEW_OUT- = []
                } 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("$key = [$line] $msg\n") if (VERB9());
            }
        }
    } else {
        pgm_exit(1,"INTERNAL ERROR: Hash does NOT have key [$key]!\n");
    }
    # if ( !get_project_name($rh, \$name) || (length(trim_all($name)) == 0))
    # if ( !get_project_type($rh, \$type) ) {
    #my $isdllapp = (is_dll_project($hr) | is_app_project($hr));
    #my $conf1 = '';
    #my $rconfarr = get_configs_array3($hr, \$conf1, $name);
    # my $func = \&get_configs_array3; # ($$$);
    # my $rconfarr = $func->($hr, \$conf1, $name);
    #$cnt = scalar @{$rconfarr};
    #prt( "Got $cnt CONFIGS...Default = [$conf1]\n" );
    #for ($i = 0; $i < $cnt; $i++) {
    #    $conf = ${$rconfarr}[$i][0];    # This is the FULL string 'name - Win32 Debug'
    #    $rh2 = ${$rconfarr}[$i][2];
    #    if ($conf =~ /Release/i) {
    #        $flag = 1;
    #    } elsif ($conf =~ /Debug/i) {
    #        $flag = 2;
    #    } elsif ($conf =~ /DLL/) {
    #        $flag = 1; # 2010/05/05 - assume RELEASE when a DLL type
    #    } else {
    #        pgm_exit(1,"ERROR: Can NOT place config [$conf] into a category!\n");
    #    }
    #    foreach $key (keys %{$rh2}) {
    #        $line = ${$rh2}{$key};
    #        prt("$key = [$line]\n");
    #    }
    #}
    #pgm_exit(1,"TEMP");

    if (write_hash_to_DSP3( $fil, $hr, $dbg_write )) {
        prt("Written DSP to [$fil]\n");
        $msg  = "\@echo Copy [$fil],\n";
        $msg .= "\@echo to   [$tdsp]?\n";
        $msg .= "\@if NOT EXIST $tdsp goto CHK1\n";
        $msg .= "\@echo NOTE: THIS WILL OVERWRITE THE EXISTING FILE!!!\n";
        $msg .= ":CHK1\n";
        $msg .= "\@echo *** CONTINUE? *** Ctrl+C to abort.\n";
        $msg .= "\@pause\n";
        $msg .= "\@if NOT EXIST $tdsp goto CHK2\n";
        $msg .= "\@echo Exisitng file will be OVERWRITTEN! Are you SURE?\n";
        $msg .= "\@pause\n";
        $msg .= ":CHK2\n";
        $msg .= "copy $fil $tdsp\n";
        $msg .= "\@echo Done...\n";
        write2file($msg,$copy_bat);
        prt("Update can be via the [$copy_bat] file.\n");
    } else {
        prt("WARNING: FAILED TO WRITE DSP FILE!\n");
    }
}


#########################################
### MAIN ###
parse_args(0,@ARGV);
check_proj_name();  # set $proj_name, if null, using the first source file
check_proj_type();  # set project type to 'CA', if null, and if 'main' found, else 'SL'
check_out_dir();    # set output target directory, if none given
check_out_name();   # set DSP /out="foo.exe", if NONE given, and $outdefault set
create_proj_dsp($dsp_out,$proj_targ);
pgm_exit(0,"Normal exit(0)");
########################################
sub give_help {
    prt("$pgmname: version 0.2.1 2010-08-25. (see amsrcs04.pl for fuller implementation.)\n");
    prt("Usage: $pgmname [options] source [source...]\n");
    prt("Options:\n");
    prt(" --help -h -?    = This help, and exit(0)\n");
    prt(" -\@<inpfile>     = Read input parameters from a file.\n");
    prt(" -name=<name>    = Set the project name.\n");
    prt(" -targ=<dir>     = Set a target directory for the DSP file.\n");
    prt(" -type=<CA>      = Set project type. Only 'CA', 'SL', 'DLL', 'WA'\n");
    prt(" -def=<FGFS>     = Add a define macro, /D \"FGFS\" to the compile.\n");
    prt(" -inc=<path>     = Add an include macro, /I \"path\" to the compile.\n");
    prt(" -int(d|r)=<dir> = Set output and intermediate directory, for objects, etc.\n");
    prt(" -lib=<lib>      = Add a library to the compile, both Debug and Release.\n");
    prt(" -libd=<lib>     = Add a library to the compile, for Debug only.\n");
    prt(" -libr=<lib>     = Add a library to the compile, for Release only.\n");
    prt(" -libp=<path>    = Add a library path, ie /libpath:\"path\" to BOTH Debug and Release.\n");
    prt(" -outd=<fd.exe>  = Add an /out:\"fd.exe\" to Debug.\n");
    prt(" -outr=<f.exe>   = Add an /out:\"f.exe\" to Release.\n");
    prt(" -outdefault     = Set output per project name, and type, adding 'd' for debug\n");
    prt(" -rt=<D|T>       = Set RUNTIME D=/MD & /MDd T=/MT & /MTd (default).\n");
    prt(" -src=<fil[;fil> = Semicolon delimited source file input, instead of 'bare' names.\n");
    prt(" -srcdir=<dir>   = Common source directory to be applied to each subsequent source.\n");
    prt(" -v[num]         = Bump or set verbosity. Default=$verbose\n");
    prt(" -l              = Load log file at end.\n");
    prt("PURPOSE: Generate a DSP project file to compile this/these given sources,\n");
    prt("         which can be 'C/C++' sources, headers and/or resource files.\n");
    prt("NOTES:\n");
    prt("  1: The -\@<inpfile> is a text file with line delimited parameters. Lines beginning with a '#'\n");
    prt("     are treated as comments, and skipped, as are blank lines.\n");
    prt("  2: In general the sources given are assumed to one level up. That is given the command -\n");
    prt("     > $pgmname -type=CA foo.c foo.h\n");
    prt("     the destination of the DSP file will be assumed to be one level down, say in .\\msvc\\foo.dsp\n");
    prt("     and the sources will be listed as 'SOURCE=..\\foo.c'. This is a feature by design.\n");
    prt("  3: Dependant library paths given are assumed for BOTH Debug and Release, the idea being\n");
    prt("     that such dependant libraries will be of the form 'bar.lib', and 'bard.lib' both residing in\n");
    prt("     the SAME -libp<path>. This may means you need to adjust to library names, and location.\n");

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

sub get_adjusted_srcs {
    my ($tmp) = shift;
    $src_dir .= "\\" if (!($src_dir =~ /(\\|\/)$/));
    my @ar2 = split(';',$tmp);
    my $nsrcs = '';
    foreach $tmp (@ar2) {
        $nsrcs .= ';' if (length($nsrcs));
        $nsrcs .= $src_dir.$tmp;
    }
    return $nsrcs;
}

sub load_arg_file {
    my ($fil) = shift;
    if (! open INF, "<$fil") {
        pgm_exit(1,"ERROR: Unable to open file [$fil]!\n");
    }
    my @lines = <INF>;
    close INF;
    my ($line,@arr,$lncnt,$i,$tmp);
    @arr = ();
    $lncnt = scalar @lines;
    for ($i = 0; $i < $lncnt; $i++) {
        $line = $lines[$i];
        $line = trim_all($line);
        next if (length($line) == 0);
        next if ($line =~ /^#/);
        while ($line =~ /\\$/) {
            # got continuation of this line
            $i++;
            $tmp = trim_all($lines[$i]);
            next if ($tmp =~ /^#/);
            last if (length($tmp) == 0);
            $line =~ s/\\$//;
            $line = trim_all($line);
            $line .= $tmp;  #add this to the line
        }
        if ($line =~ /^srcdir=(.+)$/) {
            # we have a SOURCE directory, to be applied to each source
            $src_dir = $1;
            prt("Set source directory to [$src_dir].\n") if ($verbose);
            next;   # do NOT add this, since already dealt with...
        }
        if ( ($line =~ /^src=/) && length($src_dir) ) {
            # need to adjust the source, per $src_dir
            $tmp = substr($line,4); # get source list
            $line = 'src='.get_adjusted_srcs($tmp);
        }
        push(@arr,$line);
    }
    if (@arr) {
        parse_args(1,@arr);
    }
}

sub pre_process_verbosity {
    my (@av) = @_;
    my ($arg,$sarg,$tmp);
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /-/);
            if ($sarg =~ /^v/i) {
                if ($sarg =~ /^v(\d+)$/) {
                    $tmp = $1;
                    $verbose = $tmp;
                } else {
                    while ($sarg =~ /^v/i) {
                        $verbose++;
                        $sarg = substr($sarg,1);
                    }
                }
                prt("Set verbosity level to [$verbose]\n") if ($verbose);
                if (VERB9()) {
                    $dbg_out = -1;
                    $dbg_write = -1;  # 8; # for substitutions
                    $load_log = 1;
                    prt("VERB=$verbose: Also set verbosity level to maximum for write, and load log.\n");

                }
            }
        }
        shift @av;
    }
}

sub parse_args {
    my ($src,@av) = @_;
    my ($arg,$sarg,$tmp,$rtmp,@arr);
    pre_process_verbosity(@av);
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /-/);
            if (($sarg =~ /^h$/i)||($sarg =~ /^help$/i)||($sarg eq '?')) {
                prt("Showing HELP [$arg]...\n");
                give_help();
                pgm_exit(0,"Help exit(0)");
            } elsif ($sarg =~ /^\@(.+)$/) {
                $sarg = $1;
                prt("Loading arguments from file [$sarg]...\n") if ($verbose);
                load_arg_file($sarg);
            } elsif ($sarg =~ /^v/i) {
                # already done
            } elsif ($sarg =~ /^name=/i) {
                $sarg = substr($sarg,5);
                $proj_name = $sarg;
                prt("Set project name to [$proj_name], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^name$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $proj_name = $sarg;
                prt("Set project name to [$proj_name], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^n=/i) {
                $sarg = substr($sarg,5);
                $proj_name = $sarg;
                prt("Set project name to [$proj_name], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^n$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $proj_name = $sarg;
                prt("Set project name to [$proj_name], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^rt=/i) {
                $sarg = substr($sarg,3);
                $proj_rt = $sarg;
                prt("Set project RUNTIME to [$proj_rt], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^rt$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $proj_rt = $sarg;
                prt("Set project RUNTIME to [$proj_rt], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^out(d|r)=/i) {
                $tmp = $1;
                $sarg = substr($sarg,5);
                if ($tmp =~ /^d$/i) {
                    $rtmp = \$proj_outD;
                } elsif ($tmp =~ /^r$/i) {
                    $rtmp = \$proj_outR;
                } else {
                    pgm_exit(1,"INTERNAL ERROR: Did NOT get 'd' or 'r'! Got [$tmp]\n");
                }
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/out:\"$sarg\"";
                prt("Set project output to [${$rtmp}] ($tmp)\n") if ($verbose);
            } elsif ($sarg =~ /^out(d|r)$/i) {
                $tmp = $1;
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                if ($tmp =~ /^d$/i) {
                    $rtmp = \$proj_outD;
                } elsif ($tmp =~ /^r$/i) {
                    $rtmp = \$proj_outR;
                } else {
                    pgm_exit(1,"INTERNAL ERROR: Did NOT get 'd' or 'r'! Got [$tmp]\n");
                }
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/out:\"$sarg\"";
                prt("Set project output to [${$rtmp}] ($tmp)\n") if ($verbose);
            } elsif ($sarg =~ /^int(d|r)=/i) {
                $tmp = $1;
                $sarg = substr($sarg,5);
                if ($tmp =~ /^d$/i) {
                    $rtmp = \$proj_interD;
                } elsif ($tmp =~ /^r$/i) {
                    $rtmp = \$proj_interR;
                } else {
                    pgm_exit(1,"INTERNAL ERROR: Did NOT get 'd' or 'r'! Got [$tmp]\n");
                }
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/out:\"$sarg\"";
                prt("Set project inter output to [${$rtmp}] ($tmp)\n") if ($verbose);
            } elsif ($sarg =~ /^int(d|r)$/i) {
                $tmp = $1;
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                if ($tmp =~ /^d$/i) {
                    $rtmp = \$proj_interD;
                } elsif ($tmp =~ /^r$/i) {
                    $rtmp = \$proj_interR;
                } else {
                    pgm_exit(1,"INTERNAL ERROR: Did NOT get 'd' or 'r'! Got [$tmp]\n");
                }
                ${$rtmp} = $sarg;
                prt("Set project inter output to [${$rtmp}] ($tmp)\n") if ($verbose);
            } elsif ($sarg =~ /^lib(d|r)=/i) {
                $tmp = $1;
                $sarg = substr($sarg,5);
                if ($tmp =~ /^d$/i) {
                    $rtmp = \$proj_libD;
                } elsif ($tmp =~ /^r$/i) {
                    $rtmp = \$proj_libR;
                } else {
                    pgm_exit(1,"INTERNAL ERROR: Did NOT get 'd' or 'r'! Got [$tmp]\n");
                }
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= $sarg;
                prt("Add project library depend [${$rtmp}] ($tmp)\n") if ($verbose);
            } elsif ($sarg =~ /^lib(d|r)$/i) {
                $tmp = $1;
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                if ($tmp =~ /^d$/i) {
                    $rtmp = \$proj_libD;
                } elsif ($tmp =~ /^r$/i) {
                    $rtmp = \$proj_libR;
                } else {
                    pgm_exit(1,"INTERNAL ERROR: Did NOT get 'd' or 'r'! Got [$tmp]\n");
                }
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= $sarg;
                prt("Add project library depend [${$rtmp}] ($tmp)\n") if ($verbose);
            } elsif ($sarg =~ /^lib=/i) {
                $sarg = substr($sarg,4);
                $rtmp = \$proj_libs;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= $sarg;
                prt("Add project library depend [$sarg] both Debug and Release\n") if ($verbose);
            } elsif ($sarg =~ /^lib$/i) {
                $tmp = $1;
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $rtmp = \$proj_libs;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= $sarg;
                prt("Add project library depend [$sarg] both Debug and Release\n") if ($verbose);
            } elsif ($sarg =~ /^l$/) {
                $load_log = 1;
                prt("Set to load log file at end.\n") if ($verbose);
            } elsif ($sarg =~ /^inc=/i) {
                $sarg = substr($sarg,4);
                $rtmp = \$proj_incs;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/I \"$sarg\"";
                prt("Add project include path [$sarg], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^inc$/i) {
                $tmp = $1;
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $rtmp = \$proj_incs;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/I \"$sarg\"";
                prt("Add project include path [$sarg], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^def=/i) {
                $sarg = substr($sarg,4);
                $rtmp = \$proj_defs;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/D \"$sarg\"";
                prt("Add project defines [$sarg], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^def$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $rtmp = \$proj_defs;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/D \"$sarg\"";
                prt("Add project defines path [$sarg], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^libp=/i) {
                $sarg = substr($sarg,5);
                $rtmp = \$proj_outD;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/libpath:\"$sarg\"";
                $rtmp = \$proj_outR;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/libpath:\"$sarg\"";
                prt("Add project libpath [$sarg], to both Debug and Release\n") if ($verbose);
            } elsif ($sarg =~ /^libp$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $rtmp = \$proj_outD;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/libpath:\"$sarg\"";
                $rtmp = \$proj_outR;
                ${$rtmp} .= " " if (length(${$rtmp}));
                ${$rtmp} .= "/libpath:\"$sarg\"";
                prt("Add project libpath [$sarg], to both Debug and Release\n") if ($verbose);
            } elsif ($sarg =~ /^src=/i) {
                $sarg = substr($sarg,4);
                $sarg = get_adjusted_srcs($sarg) if (length($src_dir));
                @arr = split(';',$sarg);
                foreach $tmp (@arr) {
                    $in_file = File::Spec->rel2abs($tmp);
                    push(@inp_sources,$in_file);
                }
                $tmp = scalar @inp_sources;
                prt("Bump inputs to $tmp files. [".join(" ",@arr)."]\n") if ($verbose);
            } elsif ($sarg =~ /^src$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $sarg = get_adjusted_srcs($sarg) if (length($src_dir));
                @arr = split(';',$sarg);
                foreach $tmp (@arr) {
                    $in_file = File::Spec->rel2abs($tmp);
                    push(@inp_sources,$in_file);
                }
                $tmp = scalar @inp_sources;
                prt("Bump inputs to $tmp files. [".join(" ",@arr)."]\n") if ($verbose);
            } elsif ($sarg =~ /^srcdir$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $src_dir = $sarg;
                prt("Set source directory to [$src_dir].\n") if ($verbose);
            } elsif ($sarg =~ /^srcdir=/i) {
                $sarg = substr($sarg,7);
                $src_dir = $sarg;
                prt("Set source directory to [$src_dir].\n") if ($verbose);
            } elsif ($sarg =~ /^targ=/i) {
                $sarg = substr($sarg,5);
                $proj_targ = File::Spec->rel2abs($sarg);
                prt("Set DSP to [$proj_targ], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^targ$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $proj_targ = File::Spec->rel2abs($sarg);
                prt("Set DSP to [$proj_targ], from arg [$arg]\n") if ($verbose);
            } elsif ($sarg =~ /^type=/i) {
                $sarg = substr($sarg,5);
                $proj_type = $sarg;
                if ( get_app_type_4_short($proj_type, \$tmp) ) {
                    prt("Set project type to [$proj_type] ($tmp), from arg [$arg]\n") if ($verbose);
                } else {
                    pgm_exit(1,"ERROR: Unable to get project type from [$proj_type]! Only 'CA', 'SL', 'DLL', 'WA'!\n");
                }
            } elsif ($sarg =~ /^type$/i) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                $proj_type = $sarg;
                if ( get_app_type_4_short($proj_type, \$tmp) ) {
                    prt("Set project type to [$proj_type] ($tmp), from arg [$arg]\n") if ($verbose);
                } else {
                    pgm_exit(1,"ERROR: Unable to get project type from [$proj_type]! Only 'CA', 'SL', 'DLL', 'WA'!\n");
                }
            } elsif ($sarg =~ /^outdefault$/) {
                $outdefault = 1;
                prt("Default out set [$outdefault] to use name and type for link output\n") if ($verbose);
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            $in_file = File::Spec->rel2abs($arg);
            push(@inp_sources,$in_file);
            $tmp = scalar @inp_sources;
            prt("Added input [$in_file]($tmp), from arg [$arg]\n") if ($verbose);
        }
        shift @av;
    }

    # check what we got
    if ($src == 0) {
        if ((length($in_file) == 0) && $debug_on) {
            $in_file = $def_source;
            prt("[debug_on] Add input [$in_file]\n");
            push(@inp_sources,$in_file);
            $proj_libR = 'shapelib.lib';
            $proj_libD = 'shapelibd.lib';
            $proj_incs = '/I "..\.."';
            $proj_outD = '/out:"bin\shpinfod.exe" /libpath:"lib"';
            $proj_outR = '/out:"bin\shpinfo.exe" /libpath:"lib"';
        }

        if (length($in_file) == 0) {
            pgm_exit(1,"ERROR: No source file name found in command! Use -? for HELP.\n");
        }
    }
}

# eof - createdsp.pl
