# loaddsp.pl
# 01/06/2010 - store '-NEW_OUTD-' and '-NEW_INTER' uder 'PROP $conf ' key
# Now not sure now why some in 'CONFIGS' and some in 'DEFINITIONS' - looks like they could be in ONE
use strict;
use warnings;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use File::stat; # to get the file date
use Cwd;        # to set root

# ========== DEBUG =========
#require 'logfile.pl' or die "Unable to load logfile.pl ...\n";
#my $test_file = 'C:\Projects\zlib-1.2.3\projects\visualc6\zlib.dsp';
#sub prtw($) { prt(shift); }
# ========== DEBUG =========

# DEBUG FLAGS
my $dbg_ld_01 = 0;
my $dbg_ld_02 = 0;
my $dbg_ld_03 = 0;
my $dbg_ld_04 = 0;
my $dbg_ld_05 = 0;
my $dbg_ld_06 = 0;
my $dbg_ld_07 = 0;
my $dbg_ld_08 = 0;
my $dbg_ld_09 = 0;
my $dbg_ld_10 = 0; # prt( "[dbg_ld_10] Fixed=[$ffnr], src=[$src], dir=[$dsp_dir] ff=[$ff]\n" ) if ($dbg_ld_10);
my $dbg_ld_11 = 0;
my $dbg_ld_12 = 0; # prt("[dbg_ld12] Given [$itm1] + [$itm2],\nreturn [$res]\n") if ($dbg_ld_12);

sub set_dbg_show_sources3() {
   $dbg_ld_01 = 1;
   $dbg_ld_02 = 1;
   $dbg_ld_03 = 1;
}

sub set_load_debug($) {
    my ($v) = shift;
    $dbg_ld_01 = $v; $dbg_ld_02 = $v; $dbg_ld_03 = $v; $dbg_ld_04 = $v; $dbg_ld_05 = $v; $dbg_ld_06 = $v;
    $dbg_ld_07 = $v; $dbg_ld_08 = $v; $dbg_ld_09 = $v; $dbg_ld_10 = $v;  $dbg_ld_11 = $v; $dbg_ld_12 = $v;
}

sub set_load_debug_on() { set_load_debug(1); }
sub set_load_debug_off() { set_load_debug(0); }

sub ld_fix_rel_path3($) {
    my ($path) = shift;
    $path =~ s/\//\\/g; # ensure DOS only separator
    my @a = split(/\\/, $path);
    my $npath = '';
    my $max = scalar @a;
    my @na = ();
    my ($p);
    for (my $i = 0; $i < $max; $i++) {
        $p = $a[$i];
        if ($p eq '.') {
            # ignore this
        } elsif ($p eq '..') {
            if (@na) {
                pop @na;    # discard previous
            } else {
                prtw( "WARNING: ld_fix_rel_path3: Got relative .. without previous!!! path=[$path]\n" );
            }
        } else {
            push(@na,$p);  # add to new array
        }
    }

    # re-build full path
    foreach $p (@na) {
        $npath .= "\\" if length($npath);
        $npath .= $p;
    }

    return $npath;
}

### utitlity subs
sub ext_is_c_source3($) {
    my $f = shift;
    return 1 if ( ($f =~ /\.c$/i) || ($f =~ /\.cpp$/i) || ($f =~ /\.cxx$/i) || ($f =~ /\.cc$/i));
    return 0;
}

sub file_is_c_source3($) {
    my ($fil) = shift;
    my ($nm,$dir,$ext) = fileparse( $fil, qr/\.[^.]*/ );
    return ext_is_c_source3($ext);
}

sub ext_is_h_source3($) {
    my $f = shift;
    return 1 if ( ($f =~ /\.h$/i) || ($f =~ /\.hpp$/i) || ($f =~ /\.hxx$/i) );
    return 0;
}

sub file_is_h_source3($) {
    my ($fil) = shift;
    my ($nm,$dir,$ext) = fileparse( $fil, qr/\.[^.]*/ );
    return ext_is_h_source3($ext);
}

sub is_h_special3 {
    my $f = shift;
    return 1 if (($f =~ /osg/i)||($f =~ /OpenThreads/i)||($f =~ /Producer/i));
    return 0;
}

sub set_group_and_filter($$$) {
    my ($src,$rgrp,$rflt) = @_;
    # use default group and filter - MAYBE

}

sub split_rsc_items3($) {
    my ($itm) = @_;
    # made up of /l ["]...["], and /d ["]...["]
    my @arr = split(/\s/,$itm);
    my $ac = scalar @arr;
    my ($par,$ra);
    my %hash = ();
    for (my $i = 0; $i < $ac; $i++) {
        my $tx = trim_all($arr[$i]);
        if ($tx =~ /\/l/) {
            if (($i + 1) < $ac) {
                $i++;
                $par = trim_all($arr[$i]);
                if (defined $hash{'l'}) {
                    $ra = $hash{'l'};
                    push(@{$ra},$par);
                    $hash{'l'} = $ra;
                } else {
                    $hash{'l'} = [ $par ];
                }
            } else {
                pgm_exit(1,"ERROR: Nothing following [$tx]\n");
            }
        } elsif ($tx =~ /\/d/) {
            if (($i + 1) < $ac) {
                $i++;
                $par = trim_all($arr[$i]);
                if (defined $hash{'d'}) {
                    $ra = $hash{'d'};
                    push(@{$ra},$par);
                    $hash{'d'} = $ra;
                } else {
                    $hash{'d'} = [ $par ];
                }
            } else {
                pgm_exit(1,"ERROR: Nothing following [$tx]\n");
            }

        } else {
            pgm_exit(1,"ERROR: Uncased [$tx]\n");
        }
    }

    return \%hash;
}

sub combine_rsc_items3($$) {
    my ($itm1,$itm2) = @_;  # ( ${$rconf}{$key}, $item );
    my $rh1 = split_rsc_items3($itm1);
    my $rh2 = split_rsc_items3($itm2);
    my $res = '';
    my ($k,%h1,$ra1,$ra2);
    if (defined ${$rh1}{'l'}) {
        $ra1 = ${$rh1}{'l'};
        if (defined ${$rh2}{'l'}) {
            $ra2 = ${$rh2}{'l'};
            # combine two arrays
            %h1 = ();
            foreach $k (@{$ra1}) {
                $h1{$k} = 1;
            }
            foreach $k (@{$ra2}) {
                $h1{$k} = 1;
            }
            foreach $k (keys %h1) {
                $res .= ' ' if (length($res));
                $res .= "/l $k";
            }
        } else {
            foreach $k (@{$ra1}) {
                $res .= ' ' if (length($res));
                $res .= "/l $k";
            }
        }
    }
    if (defined ${$rh1}{'d'}) {
        $ra1 = ${$rh1}{'d'};
        if (defined ${$rh2}{'d'}) {
            $ra2 = ${$rh2}{'d'};
            # combine two arrays
            %h1 = ();
            foreach $k (@{$ra1}) {
                $h1{$k} = 1;
            }
            foreach $k (@{$ra2}) {
                $h1{$k} = 1;
            }
            foreach $k (keys %h1) {
                $res .= ' ' if (length($res));
                $res .= "/d $k";
            }
        } else {
            foreach $k (@{$ra1}) {
                $res .= ' ' if (length($res));
                $res .= "/d $k";
            }
        }
    }
    prt("[dbg_ld12] Given [$itm1] + [$itm2],\nreturn [$res]\n") if ($dbg_ld_12);
    return $res;
    #return "$itm1 | $itm2";
}


sub process_DSP3($$$$) {
    my ($fil,$proj,$root,$dbg) = @_;
    my ($line, $prjname, $grpname, $filter, $ff, $src, $chr, $tmp, $conf, $ffnr);
    my ($itm1, $itm2, $key, $targtype, $i);
    my ($ok,$lnn);
    my $scnt = 0;
    my @dsp_lines = ();
    my %src_list = (); # 20090828 - avoid adding simple DUPLICATES
    my $inanif = 0; # in an !IF block
    my $ins = 0;    # in a source block
    my $inproj = 0; # in project portion of file
    my $intarget = 0;
    my $ingroup = 0;
    my $incustom = 0;
    my $sline = '';
    my $inspecial = 0;
    my ($gotbase,$gotadd,$gotsub);  # line has BASE ADD SUB
    my %prop_nh = ();
    my %add_nh = ();
    my @tmparr = ();
    my ($item);
    my %v6_defs3 = ();
    my %v6_conf3 = ();
    my @v6_srcs3 = ();
    my $rdefs = \%v6_defs3;
    my $rconf = \%v6_conf3;
    my $rsrcs = \@v6_srcs3;
    my %hash = ();
    prt( "Process DSP file $fil...\n" ) if ($dbg & 1);
    if ( -f $fil ) {
        my $sb = stat($fil);
        prt( " dated ".scalar localtime($sb->mtime).", size ".$sb->size." bytes.\n" ) if ($dbg & 2);
        $hash{'FILE_NAME'} = $fil;
        $hash{'FILE_TIME'} = $sb->mtime;
        $hash{'FILE_SIZE'} = $sb->size;
        my ($name,$dsp_dir) = fileparse($fil);
        $dsp_dir = trim_all($dsp_dir);
        $dsp_dir = $root if ((length($dsp_dir) == 0)||($dsp_dir =~ /\.(\\|\/)$/));
        $dsp_dir .= "\\" if !($dsp_dir =~ /(\\|\/)$/);    # 20090827 - ensure ends with '\'
        if ( open IF, "<$fil" ) {
            @dsp_lines = <IF>;
            close IF;
            my $lncnt = scalar @dsp_lines;
            prt( "Got $lncnt lines, from file [$fil], to process ...\n" ) if ($dbg & 4);
            for ($i = 0; $i < $lncnt; $i++) {
                $lnn = $i + 1;
                $line = $dsp_lines[$i];
                $line = trim_all($line);
                next if (length($line) == 0);
                $chr = substr($line, 0, 1);    # get FIRST char of LINE
                if( $chr eq '#' ) {
                    $gotbase = ($line =~ /\s+BASE\s+/) ? 1 : 0;
                    $gotadd  = ($line =~ /\s+ADD\s+/) ? 1 : 0;
                    $gotsub  = ($line =~ /\s+SUBTRACT\s+/) ? 1 : 0;
                    # line begins with SHARP
                    $sline = trim_all(substr($line,1));
                   # [# Microsoft Developer Studio Project File - Name="" - Package Owner=<4>]
                    # if ($line =~ /\s+Microsoft Developer Studio Project File - Name=\"([\.\w\s]+)+/) {
                    if ($line =~ /\s+Microsoft Developer Studio Project File - Name="([\.\w\s]+)*" - Package/) {
                        $prjname = $1;
                        $prjname = '<no project name>' if (length($prjname) == 0);
                        # $v6_defs{'PROJECT_NAME'} = $prjname;
                        ${$rdefs}{'PROJECT_NAME'} = $prjname;
                        prt( "rdefs:PROJECT_NAME: [$prjname]\n" ); # if ($dbg_ld_01);
                    } elsif ($line =~ /\s+Microsoft Developer Studio Generated Build File, Format Version ([\d\.]+)/) {
                        prt( "dbg_dsp: MSVC Version $1 ...\n" ) if ($dbg_ld_01);
                    #} elsif ($line =~ /\s*TARGTYPE\s+\"(.+)\"\s+/) { # Win32 (x86) Console Application" 0x0103
                    } elsif ($line =~ /\s*TARGTYPE\s+"(.+)"\s+/) { # Win32 (x86) Console Application" 0x0103
                        $targtype = $1;
                        prt( "rdefs:PROJECT_TYPE: TARGTYPE: [$targtype]\n"); # name=[$prjname]\n"); # ($proj)\n" );
                        #$v6_defs{'PROJECT_TYPE'} = $targtype;
                        ${$rdefs}{'PROJECT_TYPE'} = $targtype;
                    } elsif ($sline =~ /^PROP\s+/) {
                        $sline =~ s/^PROP\s+//;
                        $sline =~ s/^BASE\s+//;
                        if ($line =~ /PROP\s+Default_Filter\s+\"([\w;]+)+\"/ ) {
                            $filter = $1;
                            prt( "dbg_ds8: Begin Filter group $grpname, filter $filter\n" ) if ($dbg_ld_08);
                        } elsif ($sline =~ /^Use_MFC/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^Scc_ProjName/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^AllowPerConfigDependencies/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^Output_Dir\s+"(.+)"\s*$/) {
                            $item = $1;
                            $key = "PROP $conf -NEW_OUTD-";
                            prt("rdefs:$key: [$item]\n") if ($dbg_ld_11);
                            ${$rdefs}{$key} = $item;
                        } elsif ($sline =~ /^Scc_LocalPath/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^Intermediate_Dir\s+"(.+)"\s*$/) {
                            $item = $1;
                            $key = "PROP $conf -NEW_INTER-";
                            prt("rdefs:$key: [$item]\n") if ($dbg_ld_11);
                            ${$rdefs}{$key} = $item;
                        } elsif ($sline =~ /^Use_Debug_Libraries/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^Ignore_Export_Lib/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^Exclude_From_Build/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^Target_Dir/) {
                            # *TBD* if needed
                        } else {
                            prtw( "WARNING: PROP NOT HANDLED! [$sline] [$line]\n" );
                            @tmparr = split(/\s/,$sline);
                            $item = $tmparr[0];
                            $prop_nh{$item} = 1;
                        }
                    } elsif ( $sline =~ /^ADD\s+/ ) {
                        $sline =~ s/^ADD\s+//;
                        $sline =~ s/^BASE\s+//;
                        if ( $line =~ /ADD BASE CPP (.+)/ )  {
                            $item = $1;
                            # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c
                            $key = 'CPP '.$conf;
                            prt( "rdefs:dbg04: ADD BASE key=[$key] [$item]\n" ) if ($dbg_ld_04);
                            #$v6_conf{$key} = $item;
                            #${$rconf}{$key} = $item;
                            ${$rdefs}{$key} = $item;
                        } elsif ( $line =~ /ADD CPP (.+)/ )  {
                            $item = $1;
                            # ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
                            $key = 'CPP '.$conf;
                            prt( "rdefs:dbg04: ADD key=[$key] [$item]\n" ) if ($dbg_ld_04);
                            #$v6_conf{$key} = $item;
                            ${$rdefs}{$key} = $item;
                        } elsif ( $line =~ /ADD BASE LINK32 (.+)/ )  {
                            $item = $1;
                            # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
                            $key = 'LINK '.$conf;
                            prt( "rconf:dbg04: ADD BASE key=[$key] [$item]\n" ) if ($dbg_ld_04);
                            #$v6_conf{$key} = $item;
                            ${$rconf}{$key} = $item;
                        } elsif ( $line =~ /ADD LINK32 (.+)/ )  {
                            $item = $1;
                            $key = 'LINK '.$conf;
                            # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
                            prt( "rconf:dbg04: ADD key=[$key] [$item]\n" ) if ($dbg_ld_04);
                            #$v6_conf{$key} = $item;
                            ${$rconf}{$key} = $item;
                        } elsif ( $line =~ /ADD BASE LIB32 (.+)/ )  {
                            $item = $1;
                            $key = 'LIB '.$conf;
                            prt( "rconf:dbg04: ADD BASE key=[$key] [$item]\n" ) if ($dbg_ld_04);
                            #$v6_conf{$key} = $item;
                            ${$rconf}{$key} = $item;
                        } elsif ( $line =~ /ADD LIB32 (.+)/ )  {
                            $item = $1;
                            $key = 'LIB '.$conf;
                            prt( "rconf:dbg04: ADD key=[$key] [$item]\n" ) if ($dbg_ld_04);
                            #$v6_conf{$key} = $item;
                            ${$rconf}{$key} = $item;
                        } elsif ($sline =~ /^RSC\s+(.+)$/) {
                            # 2010-01-19 IS NEEDED - like
                            # c:\FG\32\zips\temp\pthread.dsp
                            # # ADD BASE RSC /l 0x809 /d "NDEBUG"
                            # # ADD RSC /l 0x809 /d "NDEBUG" /d "PTW32_RC_MSC"
                            # OR LIKE - c:\FG\32\lpng\projects\visualc6\libpng.dsp
                            # # ADD RSC /l 0x409 /i "..\.." /d "_DEBUG" /d PNG_DEBUG=1
                            # # ADD RSC /l 0x409 /i "..\.." /d "NDEBUG" /d PNG_LIBPNG_SPECIALBUILD=""""Use MMX instructions""""
                            # # ADD RSC /l 0x409 /i "..\.." /d "NDEBUG" /dPNG_LIBPNG_DLLFNAME_POSTFIX=""""VB"""" /dPNG_LIBPNG_SPECIALBUILD=""""__stdcall calling convention used for exported functions""""
                            $item = $1;
                            $key = 'RSC '.$conf;
                            if (defined ${$rconf}{$key}) {
                                if ($gotbase) {
                                    ${$rconf}{$key} = $item;
                                } elsif ($gotsub) {
                                    prtw("WARNING: SUBTRACT NOT HANDLED YET!\n");
                                } else {
                                    ${$rconf}{$key} = combine_rsc_items3( ${$rconf}{$key}, $item );
                                }
                            } else {
                                ${$rconf}{$key} = $item;
                            }
                        } elsif ($sline =~ /^BSC32/) {
                            # *TBD* if needed
                        } elsif ($sline =~ /^MTL/) {
                            # *TBD* if needed
                        } else {
                            prtw( "WARNING:$lnn: ADD NOT HANDLED! [$sline] [$line]\n" );
                            @tmparr = split(/\s/,$sline);
                            $item = $tmparr[0];
                            $add_nh{$item} = 1;
                        }
                    } elsif ( $sline =~ /\*\*\s+DO\s+NOT\s+EDIT\s+\*\*/) {
                        # ignore this line
                    } elsif ( $sline =~ /^Name\s+(.+)$/) {
                        # Name "testcon - Win32 ReleaseSSE"]
                    } elsif ( $sline =~ /^SUBTRACT\s+/ ) {
                        # ignore for now
                    } elsif ( $line =~ /Begin\s+Project/ ) {
                        $inproj = 1;
                    } elsif ( $line =~ /End\s+Project/ ) {
                        $inproj = 0;
                    } elsif ( $line =~ /Begin\sTarget/ ) {
                        $intarget = 1;
                    } elsif ( $line =~ /End\sTarget/ ) {
                        $intarget = 0;
                    } elsif ($line =~ /Begin Group \"([\s\w]+)+/ ) {
                        $grpname = $1;
                        prt( "dbg_dsp: Begin group ... $grpname\n" ) if ($dbg_ld_02);
                        $ingroup = 1;
                    } elsif ($line =~ /End\s+Group/) {
                        $ingroup = 0;
                    } elsif ($line =~ /Begin\s+Source\s+File/) {
                        $ins = 1;
                        prt( "dbg_dsp: Begin source ... $ins ...\n" ) if ($dbg_ld_02);
                    } elsif ($line =~ /End\s+Source\s+File/) {
                        $ins = 0;
                        prt( "dbg_dsp: End source ... $ins ...\n" ) if ($dbg_ld_02);
                    } elsif ($line =~ /Begin\s+Custom\s+Build/) {
                        $incustom = 1;
                    } elsif ($line =~ /End\s+Custom\s+Build/) {
                        $incustom = 0;
                    } elsif ($line =~ /Begin\s+Special\s+Build\s+Tool/) {
                        $inspecial = 1;
                    } elsif ($line =~ /End\s+Special\s+Build\s+Tool/) {
                        $inspecial = 0;
                    } else {
                        prtw( "WARNING:$lnn: Line beginning with SHARP(#) NOT HANDLED [$line]\n" );
                    }
                } elsif ( $chr eq '!' ) {
                    # line beginning with '!' char
                    $sline = substr($line,1);
                    if ($line =~ /^!IF\s+(.+)/i ) {
                        prt( "dbg_ds6: Entering IF $1 ...\n" ) if ($dbg_ld_06);
                        prtw( "WARNING: !IF found BUT aready in an !IF block!\n" ) if ( $inanif );
                        $inanif = 1;
                        if ($line =~ /!IF\s+(.+) == (.+)/i) {
                            $itm1 = $1;
                            $itm2 = $2;
                            $itm1 =~ s/\"//g;
                            $itm2 =~ s/\"//g;
                            prt( "dbg_ds6: Got [$itm1] [$itm2]...\n" ) if ($dbg_ld_06);
                            if ($itm1 =~ /^\$\((.+)\)/ ) {
                                #if (defined $v6_defs{$1}) {
                                #    if ($v6_defs{$1} eq $itm2) {
                                $item = $1;
                                if (defined ${$rdefs}{$item}) {
                                    if (${$rdefs}{$item} eq $itm2) {
                                        $tmp = "TRUE";
                                    } else {
                                        $tmp = "FALSE";
                                    }
                                    if( $item eq 'CFG' ) {
                                        $conf = $itm2;
                                    }
                                    #prt( "dbg_ds6: and [$item] defined as \"$v6_defs{$item}\" ... $tmp $conf\n" ) if ($dbg_ld_06);
                                    prt( "dbg_ds6: and [$item] defined as \"${$rdefs}{$item}\" ... $tmp $conf\n" ) if ($dbg_ld_06);
                                } else {
                                    prt( "NOT DEFINED [$item] ...\n" );
                                }
                            }
                        } else {
                            prt( "FAILED IF == [$line]\n" );
                        }
                    } elsif ( $line =~ /^!ELSE\s+/i ) {
                        prt( "dbg_ds6: Entering ELSE ...\n" ) if ($dbg_ld_06);
                        prtw( "WARNING: !ELSE found NOT in an !IF block!\n" ) if ( ! $inanif );
                    } elsif ( $line =~ /^!ELSEIF\s+(.+)/i ) {
                        prt( "dbg_ds6: Entering ELSEIF $1 ...\n" ) if ($dbg_ld_06);
                        prtw( "WARNING: !ELSEIF found NOT in an !IF block!\n" ) if ( ! $inanif );
                        if ($line =~ /!ELSEIF\s+(.+) == (.+)/i) {
                            $itm1 = $1;
                            $itm2 = $2;
                            $itm1 =~ s/\"//g;
                            $itm2 =~ s/\"//g;
                            prt( "dbg_ds6: Got [$itm1] [$itm2]...\n" ) if ($dbg_ld_06);
                            if ($itm1 =~ /^\$\((.+)\)/ ) {
                                $item = $1;
                                #if (defined $v6_defs{$item}) {
                                #    if ($v6_defs{$item} eq $itm2) {
                                if (defined ${$rdefs}{$item}) {
                                    if (${$rdefs}{$item} eq $itm2) {
                                        $tmp = "TRUE";
                                    } else {
                                        $tmp = "FALSE";
                                    }
                                    if( $item eq 'CFG' ) {
                                        $conf = $itm2;
                                    }
                                    #prt( "dbg_ds6: and [$item] defined as \"$v6_defs{$item}\" ... $tmp $conf\n" ) if ($dbg_ld_06);
                                    prt( "dbg_ds6: and [$item] defined as \"${$rdefs}{$item}\" ... $tmp $conf\n" ) if ($dbg_ld_06);
                                } else {
                                    prt( "NOT DEFINED [$item] ...\n" );
                                }
                            }
                        } else {
                            prt( "FAILED ELSEIF == [$line]\n" );
                        }
                    } elsif ( $line =~ /^!ENDIF\s*/i ) {
                        prt( "dbg_ds6: Out ENDIF ...\n" ) if ($dbg_ld_06);
                        prtw( "WARNING: !ENDIF found NOT in an !IF block!\n" ) if ( ! $inanif );
                        $inanif = 0;    # end the !IF
                    } elsif ( $line =~ /^!MESSAGE/) {
                        # ignore MESSAGE lines for now...
                    } else {
                        prtw( "WARNING: Line beginning with ! NOT HANDLED [$line]\n" );
                    }
                } else {
                    #if ($line =~ /SOURCE=([\.\\\w-]+)+/ ) {
                    #    $src = $1;
                    if ($line =~ /^SOURCE=/ ) {
                        $src = substr($line,7);
                        $ff = $dsp_dir.$src;
                        $ffnr = ld_fix_rel_path3($ff);
                        $ok = 'NF';
                        $ok = 'ok' if (-f $ff);
                        prt( "[dbg_ld_10] Fixed=[$ffnr], src=[$src], dir=[$dsp_dir] ff=[$ff]\n" ) if ($dbg_ld_10);
                        if ($ins) { # had 'Begin Source File', and before 'End Source File' in DSP
                            prt( "dbg_ld_01:SOURCE=[$src] ($ffnr)... $ok\n" ) if ($dbg_ld_01);
                            if (file_is_c_source3($src)) {
                                prt("dbg_ds1: SOURCE=[$src]\n") if ($dbg_ld_02);
                            } elsif (file_is_h_source3($src)) {
                                prt("dbg_ds2: HEADER=[$src]\n") if ($dbg_ld_02);
                            } elsif (is_h_special3($src)) {
                                prt("dbg_ds2: HEADER=[$src]\n") if ($dbg_ld_02);
                            } else {
                                prt("dbg_ds3: OTHER=[$src]\n") if ($dbg_ld_03);
                            }
                            if (defined $src_list{$src}) {
                                prtw( "WARNING: Avoiding DUPLICATED SOURCE [$src]\n" );   # 20090828 - do NOT add duplicates
                            } else {
                                $src_list{$src} = 1;
                                #                0     1      2          3      4  5  6
                                #push(@v8_srcs,[$src, $ffnr, $filtname, $filttype, 0, 0, $projname] );
                                #push(@v6_srcs, [$src, $ffnr, $grpname, $filter, 0, 0, $proj] );
                                if ($ingroup) {
                                    push(@{$rsrcs}, [$src, $ffnr, $grpname, $filter, 0, 0, $proj] );
                                } else {
                                    # no group name, and thus probable no filter name
                                    my $tmpgrp = "";
                                    my $tmpflt = "";
                                    set_group_and_filter($src,\$tmpgrp,\$tmpflt);
                                    push(@{$rsrcs}, [$src, $ffnr, $tmpgrp, $tmpflt, 0, 0, $proj] );
                                }
                                $scnt++;
                                prt( "dbg_ds9: $scnt v6_srcs: $src, $ffnr, $grpname, $filter, 0, 0, $proj\n" ) if ($dbg_ld_09);
                            }
                        } else {
                            # another place where 'SOURCE=<path>' is in 
                            # # Begin Special Build Tool, where $inspecial = 1;
                            if ( !$inspecial ) {
                                prtw("WARNING: SOURCE=$src ($ff) OUTSIDE 'in source' or 'special' CHECKME!!\n" );
                            }
                        }
                    } elsif ( $line =~ /(.*)=(.*)/ ) {
                        $itm1 = $1;
                        $itm2 = $2;
                        #$v6_defs{$itm1} = $itm2;
                        ${$rdefs}{$itm1} = $itm2;
                        prt( "rdefs:dbg05: Defined [$itm1] = [$itm2] ...\n" ) if ($dbg_ld_05);
                    } else {
                        if ($incustom) {
                            # just a custom build line
                        } else {
                            prtw( "WARNING: Skipped line [$line]\n" );
                        }
                    }
                }
            }
            prt( "End DSP - got $scnt source files ...\n" ) if ($dbg & 8);
            if ($dbg_ld_07) {
                #foreach $key (keys %v6_conf) { prt( "Config $key = [$v6_conf{$key}]\n" ); }
                foreach $key (keys %{$rconf}) { prt( "CONFIGS [$key] = [".${$rconf}{$key}."]\n" ); }
            }
            @tmparr = keys(%prop_nh);
            if (@tmparr) {
                prt( "PROPs NOT HANDLED...\n" );
                foreach $key (@tmparr) {
                    prt( "elsif (\$sline =~ /^$key/) {\n" );
                }
            }
            @tmparr = keys(%add_nh);
            if (@tmparr) {
                prt( "ADDs NOT HANDLED...\n" );
                foreach $key (@tmparr) {
                    prt( "elsif (\$sline =~ /^$key/) {\n" );
                }
            }
            $hash{'DEFINITIONS'} = { %{$rdefs} };
            $hash{'CONFIGS'}     = { %{$rconf} };
            $hash{'SOURCES'}     = [ @{$rsrcs} ];
        } else {
            prt( "ERROR: FAILED TO OPEN $fil FILE!\n" );
            pgm_exit(1,"NO FILE $fil OPENNED!");
        }
    } else {
        prt( "*** DOES NOT EXIST *** [$fil]\n" );
        pgm_exit(1,"NO FILE $fil FOUND!");
    }
    return \%hash;
}

# ========== DEBUG =========
#my ($file_name,$file_dir) = fileparse($test_file);
#set_dbg_show_sources3();
#my $rh = process_DSP3($test_file,$file_name,$file_dir);
# ========== DEBUG =========
1;

# eof - loadsp.pl