# scanvc.pl # 07/07/2010 - Add ability to set debug items - svc_set_dbg_item(val) # 2010.05/31 - Minor fix to '$cf_dn_no_s' - or in, not '&', and add 'scanvc' to WARNINGS... # 2010/05/06 - fix bug [dbg_v32] 015:048-059: VCCLCompilerTool:CompileAs: set [-NEW_RT-] from [/MDd] to [/MDd /] # 2010/05/05 - minor fix for item like '"2">', which should be fixed upstream... # 2010/05/01 - added 'strict' and 'warnings', and fixed lots of things # 2010/04/23 - handle different xml lining - added sub get_clean_seek_item($) to ensure trailing '>' also removed # 2010/03/08 - Remove write tempvcx.xml from scanvc.pl, or only to perl base directory... # 2010/03/01 - if vcproj contains IgnoreDefaultLibraryNames="MSVCRT", add /nodefaultlib:"MSVCRT" to DSP # Add this to the -NEW_OUT- substitution parameter - that is to the # ADD LINK32 line. # Can be DIFFERENT per configuration. # 2010/01/14 = Can be 'Description=""Copy Library to plib directory""' Note double QUOTES as '"', AND '"', OR WORSE!!! # 2009/10/25 - move out of fgscanvc03.pl # Subroutine name list - generated by chkperl.pl, on 20091029 # svc_get_dbg_stg(), get_default_ref_hash($), get_item_from_hash($$), get_per_file_hash($), get_last_src_offset($), # get_current_xline_stg($), get_project_configs($), svc_get_project_name_stg($), get_project_srcs_ref($), add_vs_project_items($$$$), # extract_curr_items($$$$$$$$$), svc_add_props_to_hash($$$$), add_vs_config_item($), show_hash_results3($), massage_command3($), # get_line_hash_missed($$$), get_ct_line_hash_missed($$), process_vc_conf_tool_tag($), process_vc_file_tool_tag($), # get_cfgs_array_order($$), add_any_per_file_items3($), get_xln_stg($$), process_VC_lines($$$), svc_xml_to_lines($$), # process_VCPROJ3 # === End sub name list === use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; # 2010/05/01 - additions my %compileas = ( 0 => "", 1 => "TC", 2 => "TP" ); my $write_temp_xml = 0; # only really needed for DEBUG, and should be to perl base directory if done... my $sc_last_intdir = ''; # CURR_FLAG values my $cf_apptype = 0x00000001; # signal, we have an APP TYPE - VERY IMPORTANT my $cf_apptyp2 = 0x00000002; # APP TYPE my $cf_dn_lt_t = 0x80000000; # if (!$dn_lt_noo) my $cf_dn_no_s = 0x40000000; # DOES NOT CONTAIN(7) 'SubSystem' NOR 'ImportLibrary' only ONCE my $flist_done_once = 0; # only once for prtw( "WARNING:$xln DOES NOT CONTAIN(12) '$seek'? [$line] [$fil]\n" ); my $g_sc_inconfigs = 0; my $g_sc_infiles = 0; my $g_sc_infconf = 0; my $g_sc_act_vcproj = ''; my ($g_sc_act_name,$g_sc_act_path); # = fileparse($g_sc_act_vcproj); # DEBUG my $dbg_v01 = 0; # prt( "[dbg_v01] $xln Bgn VisualStudioProject name=[$val1], type=[$val3], vers=[$val2]\n" ) if ($dbg_v01); my $dbg_v02 = 0; # prt( "[dbg_v02] $xln Bgn Configurations ($tag)\n" ) if ($dbg_v02); my $dbg_v03 = 0; # prt( "[dbg_v03] seek=PreprocessorDefinitions = [$ppdefs] [$fil]\n" ) if ($dbg_v03); my $dbg_v04 = 0; # prt( "[dbg_v04] $xln 'VCCLCompilerTool' DOES NOT CONTAIN(2) 'PreprocessorDefinitions' [$line]\n" ) if ($dbg_v04); my $dbg_v05 = 0; # prt( "[dbg_v05] $xln 'VCCLCompilerTool' DOES NOT CONTAIN(3) 'RuntimeLibrary' [$line]\n" ) if ($dbg_v05); my $dbg_v06 = 0; # prt( "[dbg_v06] $xln Bgn ConfigurationName=[$confname] conf=[$conf] [$line] ...($tag)\n" ) if ($dbg_v06); my $dbg_v07 = 0; # prt( "[dbg_v07] $xln Bgn Filter name=[$fname] list=[$flist] ($tag)\n" ) if ($dbg_v07); my $dbg_v08 = 0; # prt( "[dbg_v08] $xln Bgn File [$last_src] ($tag)\n" ) if ($dbg_v08); my $dbg_v09 = 0; # prt( "[dbg_v09] $xln Bgn FileConfiguration [$last_src] ($tag)\n" ) if ($dbg_v09); my $dbg_v10 = 0; # prt( "[dbg_v10] $xln Last = $last_src=[".${$src_ref}[-1][0]."] $fconf ExcludedFromBuild = $adddefs\n" ) if ($dbg_v10); my $dbg_v11 = 0; # prt( "[dbg_v11] $xln NO keys in per file hash...\n") if ($dbg_v11); my $dbg_v12 = 0; # prt( "[dbg_v12] $xln Bgn Files ($tag)\n" ) if ($dbg_v12); my $dbg_v13 = 0; # prt( "[dbg_v13] $xln 'VCCLCompilerTool' DOES NOT CONTAIN(1) 'AdditionalIncludeDirectories' [$line]\n" ) if ($dbg_v13); my $dbg_v15 = 0; # prt( "[dbg_v15] $xln got POST event [$ppdefs]\n" ) if ($dbg_v15); my $dbg_v16 = 0; # prtw( "WARNING:$xln 'VCCLinkerTool' DOES NOT CONTAIN(4) '$seek' [$line] [$fil]\n" ) if ($dbg_v16); my $dbg_v20 = 0; # prt( "[dbg_v20] $xln Changed(2) [IntermediateDirectory] from [".${$dsp_sub_sub}{$var2}."] to [".add_quotes($adddeps)."]\n" ) if ($dbg_v20); my $dbg_v22 = 0; # prt( "[dbg_v22] $xln seek=AdditionalDependencies: Set [$var1] to [$adddeps]\n" ) if ($dbg_v22); my $dbg_v23 = 0; # prt( "[dbg_v23] $xln seek=AdditionalLibraryDirectories: Set [$var1] to [$tmp] from [$adddeps]\n" ) if ($dbg_v23); my $dbg_v24 = 0; # prt( "[dbg_v24] $xln seek=OutputFile: Set [$var2] to [$newval]\n" ) if ($dbg_v24); my $dbg_v25 = 0; # prt( "[dbg_v25] " ); prt( "$xln VCCLCompilerTool:AdditionalIncludeDirectories: RESET [$var1] to [$newval] from [$curval]\n" ); my $dbg_v26 = 0; # prt( "[dbg_v26] Processing prop file(s) [$fils] cnt=$cnt\n" ) if ($dbg_v26); and MORE my $dbg_v27 = 0; # prt( "[dbg_v27] $xln got CUSTOM event [$pname] [$fconf] [$adddefs]\n" ) if ($dbg_v27); my $dbg_v28 = 0; # prt( "[dbg_v28] CUSTOM event [$tmp]\n" ) if ($dbg_v28); my $dbg_v29 = 0; # prt( "[dbg_v29] $xln Added CUSTOM build for source [$key]\n" ) if ($dbg_v29); my $dbg_v30 = 0; # prt( "[dbg_v30] CUSTOM build [$tmp]\n" ) if ($dbg_v30); my $dbg_v31 = 0; # prt( "[dbg_v31] " ); prt( "$xln conf=[$confname]:VCCLCompilerTool: [$line]\n seeks=[$doneseeks]\n missed=[$missed] ($lhlen)\n" ); my $dbg_v32 = 0; # prt( "[dbg_v32] $xln VCCLCompilerTool:CompileAs: set [$var3] to ".${$dsp_sub_sub}{$var3}."\n" ) if ($dbg_v32); my $dbg_v33 = 0; # prt( "[dbg_v33] $xln Changed(1) [OutputDirectory] from [".${$dsp_sub_sub}{$var1}."] to [".add_quotes($adddeps)."]\n" ) if ($dbg_v33); my $dbg_v34 = 0; # prt( "[dbg_v34] $xln file: 'VCCLCompilerTool' [$line] IGNORED CHECK ($lhlen)\n" ) if ($dbg_v34); AND 'VCResourceCompilerTool' my $dbg_v35 = 0; # prt( "[dbg_v35] $xln Project [$projname], APP_TYPE CONFIRMED per 'ImportLibrary' set to [$dnapptype]...\n" ) if ($dbg_v35); my $dbg_v36 = 0; # prt("[dbg_v36] Got description: [$ppdefs]\n") if ($dbg_v36); and more... 2010/01/14 my $dbg_v37 = 0; # prt("[dbg_v37] Done process_VC_lines...\n") if ($dbg_v37); my $dbg_v38 = 0; # prt( "[dbg_v38] Processing project [$projname]...\n" ) if ($dbg_v38); my $dbg_v39 = 0; # prt( "[dbg_v39] $xln seek=IgnoreDefaultLibraryNames: Set [$var1] to [$tmp] from [$adddeps] prev [$curval]\n" ) if ($dbg_v39); my $dbg_v40 = 0; # prt("[dbg_v40] STORE:$tmp: In rcfgs (ra)[$confname], [$var1], [$conf], & \$dsp_sub_sub ] )\n") if ($dbg_v40); # ONLY STORE OF 'PROJECT_CFGS' # forward sub svc_xml_to_lines($$); sub svc_get_dbg_stg() { my $dbs = ''; if ($dbg_v01) { $dbs .= "v01 "; } if ($dbg_v02) { $dbs .= "v02 "; } if ($dbg_v03) { $dbs .= "v03 "; } if ($dbg_v04) { $dbs .= "v04 "; } if ($dbg_v05) { $dbs .= "v05 "; } if ($dbg_v06) { $dbs .= "v06 "; } if ($dbg_v07) { $dbs .= "v07 "; } if ($dbg_v08) { $dbs .= "v08 "; } if ($dbg_v09) { $dbs .= "v09 "; } if ($dbg_v10) { $dbs .= "v10 "; } if ($dbg_v11) { $dbs .= "v11 "; } if ($dbg_v12) { $dbs .= "v12 "; } if ($dbg_v13) { $dbs .= "v13 "; } if ($dbg_v15) { $dbs .= "v15 "; } if ($dbg_v16) { $dbs .= "v16 "; } if ($dbg_v20) { $dbs .= "v20 "; } if ($dbg_v22) { $dbs .= "v22 "; } if ($dbg_v23) { $dbs .= "v23 "; } if ($dbg_v24) { $dbs .= "v24 "; } if ($dbg_v25) { $dbs .= "v25 "; } if ($dbg_v26) { $dbs .= "v26 "; } if ($dbg_v27) { $dbs .= "v27 "; } if ($dbg_v28) { $dbs .= "v28 "; } if ($dbg_v29) { $dbs .= "v29 "; } if ($dbg_v30) { $dbs .= "v30 "; } if ($dbg_v31) { $dbs .= "v31 "; } if ($dbg_v32) { $dbs .= "v32 "; } if ($dbg_v33) { $dbs .= "v33 "; } if ($dbg_v34) { $dbs .= "v34 "; } if ($dbg_v35) { $dbs .= "v35 "; } if ($dbg_v36) { $dbs .= "v36 "; } if ($dbg_v37) { $dbs .= "v37 "; } if ($dbg_v38) { $dbs .= "v38 "; } if ($dbg_v39) { $dbs .= "v39 "; } if ($dbg_v40) { $dbs .= "v40 "; } return $dbs; } sub svc_set_dbg_val($) { my ($v) = shift; $dbg_v01 = $v; $dbg_v02 = $v; $dbg_v03 = $v; $dbg_v04 = $v; $dbg_v05 = $v; $dbg_v06 = $v; $dbg_v07 = $v; $dbg_v08 = $v; $dbg_v09 = $v; $dbg_v10 = $v; $dbg_v11 = $v; $dbg_v12 = $v; $dbg_v13 = $v; $dbg_v15 = $v; $dbg_v20 = $v; $dbg_v22 = $v; $dbg_v23 = $v; $dbg_v24 = $v; $dbg_v25 = $v; $dbg_v26 = $v; $dbg_v27 = $v; $dbg_v28 = $v; $dbg_v29 = $v; $dbg_v30 = $v; $dbg_v31 = $v; $dbg_v32 = $v; $dbg_v33 = $v; $dbg_v34 = $v; $dbg_v35 = $v; $dbg_v36 = $v; $dbg_v37 = $v; $dbg_v38 = $v; $dbg_v39 = $v; $dbg_v40 = $v; } sub svc_set_dbg_on() { svc_set_dbg_val(1); } sub svc_set_dbg_off() { svc_set_dbg_val(0); } sub svc_set_dbg_item($$) { my ($val,$of) = @_; if ($val == 40) { $dbg_v40 = 1; return 0; } my $var = '$dbg_v'.$val; prt("Setting var [$var] to [$of]\n"); my $v = eval $var; if (defined $v) { my $stg = "$var"." = $of;"; eval $stg; return 0; } return 1; } sub get_default_ref_hash($) { my ($fil) = @_; my %hash = (); my $rh = \%hash; my ($nam,$dir,$ext) = fileparse($fil,qr/\.[^.]*/); $dir = cwd() if ($dir =~ /^\.(\\|\/)$/); $dir .= "\\" if (!($dir =~ /(\\|\/)$/)); $dir =~ s/\//\\/g; ${$rh}{'PROJECT_VERS'} = 1; # version of the HASH ${$rh}{'PROJECT_FILE'} = $nam.$ext; # 2010/05/07 - was $fil ${$rh}{'PROJECT_FDIR'} = $dir; ${$rh}{'PROJECT_DSPF'} = $nam.".dsp"; ${$rh}{'PROJECT_FLAG'} = 0; ${$rh}{'PROJECT_APTP'} = ''; ${$rh}{'PROJECT_CCNT'} = 0; # count of configurations ${$rh}{'PROJECT_CFGS'} = [ ]; ${$rh}{'PROJECT_SRCS'} = [ ]; ${$rh}{'CURR_FLAG'} = 0; ${$rh}{'CURR_LOFF'} = 0; # last/current source OFFSET ${$rh}{'CURR_LINE'} = ''; return $rh; } my %ignore_in_ct_lh = ( 'AssemblerListingLocation' => 1, 'EnableFunctionLevelLinking' => 2, 'InlineFunctionExpansion' => 3, 'ObjectFile' => 4, 'Optimization' => 5, 'PrecompiledHeaderFile' => 6, 'ProgramDataBaseFileName' => 7, 'RuntimeTypeInfo' => 8, 'StringPooling' => 9, 'SuppressStartupBanner' => 10, 'WarningLevel' => 11, ' 12, 'Name' => 13, '/>' => 14, 'BasicRuntimeChecks' => 14, 'DebugInformationFormat' => 15, 'MinimalRebuild' => 16 ); sub get_item_from_hash($$) { my ($rh,$key) = @_; my ($item); if (defined ${$rh}{$key}) { $item = ${$rh}{$key}; } else { prtw("ERROR:scanvc: Key [$key] NOT present in HASH!\n"); pgm_exit(1,"ENSURE key [$key] ADDED TO HASH!\n"); } return $item; } sub get_per_file_hash($) { my ($rh) = shift; return get_item_from_hash($rh,'CURR_PFHR'); } sub get_last_src_offset($) { my ($rh) = shift; return get_item_from_hash($rh,'CURR_LOFF'); # last/current source OFFSET } sub get_current_xline_stg($) { my ($rh) = shift; return get_item_from_hash($rh,'CURR_LINE'); # = $xln } sub get_project_configs($) { my ($rh) = shift; return get_item_from_hash($rh,'PROJECT_CFGS'); } sub svc_get_project_name_stg($) { my ($rh) = shift; return get_item_from_hash($rh,'PROJECT_NAME'); } sub get_project_srcs_ref($) { my ($rh) = shift; return get_item_from_hash($rh,'PROJECT_SRCS'); } sub add_vs_project_items($$$$) { my ($rh, $rah, $xln, $fil) = @_; my ($seek,$val1,$val2,$val3); $seek = 'Name'; if (!defined ${$rah}{$seek} ) { mydie( "ERROR: 'VisualStudioProject' DOES NOT CONTAIN(14) a project NAME! NO GO!! ABORTING!!! [$fil]\n" ); } $val1 = strip_quotes(${$rah}{$seek}); # get the (all important) PROJECT NAME $val2 = ''; $val3 = ''; $seek = 'ProjectType'; if (defined ${$rah}{$seek}) { $val3 = strip_dotrel(strip_quotes(trim_all(${$rah}{$seek}))); } $seek = 'Version'; if (defined ${$rah}{$seek}) { $val2 = strip_dotrel(strip_quotes(trim_all(${$rah}{$seek}))); } ${$rh}{'PROJECT_NAME'} = $val1; # SET the PROJECT NAME! ${$rh}{'PROJECT_MSCV'} = $val2; ${$rh}{'PROJECT_TYPE'} = $val3; prt( "[dbg_v01] $xln Bgn VisualStudioProject name=[$val1], type=[$val3], vers=[$val2]\n" ) if ($dbg_v01); } # extract_curr_items($rh,\$xln,\$rah,\$tag,\$pname,\$fil,\$projname,\$line,\$flag); sub extract_curr_items($$$$$$$$$) { my ($rh,$rxln,$rrah,$rtag,$rpnm,$rfil,$rnam,$rlin,$rflg) = @_; ${$rxln} = ${$rh}{'CURR_LINE'}; ${$rrah} = ${$rh}{'CURR_HASH'}; ${$rtag} = ${$rh}{'CURR_TAG'}; ${$rpnm} = ${$rh}{'CURR_NAME'}; ${$rlin} = ${$rh}{'CURR_TEXT'}; ${$rfil} = ${$rh}{'PROJECT_FILE'}; ${$rnam} = ${$rh}{'PROJECT_NAME'}; ${$rflg} = ${$rh}{'CURR_FLAG'}; } # Specifically interested in addeding # $seek = 'OutputDirectory'; # $seek = 'IntermediateDirectory'; # %comspec% /k ""C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"" x86 # $(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops sub svc_add_props_to_hash($$$$) { # ( $adddeps, \%atthash ); my ($fil,$fils,$rh,$props) = @_; my (@arr,$cnt,$i,$nm,$dir,$itm,$ff,%lnmap,$xlncnt,@lines,$lncnt,$lnnum); my ($line,$xln,@attribs,$ratthash,$key,$val); my ($val2, $tkey, $tag, $idir); my @parr = split(";",$props); ($nm,$dir) = fileparse($fil); $dir = strip_dotrel($dir); @arr = split(/[;,]/,$fils); # can be MORE THAN ONE property sheet $cnt = scalar @arr; prt( "[dbg_v26] Processing prop file(s) [$fils] cnt=$cnt\n" ) if ($dbg_v26); for ($i = 0; $i < $cnt; $i++) { $itm = strip_dotrel(trim_all(strip_quotes(trim_all($arr[$i])))); if ($itm =~ /^\$\(VCInstallDir\)/i) { $idir = ''; if ( get_vs_install_dir(\$idir) && length($idir) ) { $itm =~ s/^\$\(VCInstallDir\)//i; $dir = $idir."\\VC"; prt( "[dbg_v26] Setting dir to [$dir], for item [$itm]\n" ) if ($dbg_v26); } else { prtw("WARNING:scanvc: Failed to get VCINSTALLDIR!\n"); } } # =========================================================================== $ff = $dir; $ff .= "\\" if ( length($dir) && !(($dir =~ /(\\|\/)$/)||($itm =~ /^(\\|\/)/)) ); $ff .= $itm; ###prt( "Finding [$ff], from [$dir]/[$itm]...\n" ); # =========================================================================== if (-f $ff) { prt( "[dbg_v26] Loading inherited props [$ff]..\n" ) if ($dbg_v26); if (open INF, "<$ff") { %lnmap = (); @lines = ; close INF; $xlncnt = scalar @lines; @lines = svc_xml_to_lines(\%lnmap, \@lines); $lncnt = scalar @lines; $lnnum = 0; prt( "[dbg_v26] Processing file [$ff], $lncnt lines ($xlncnt) ...\n" ) if ($dbg_v26); foreach $line (@lines) { $lnnum++; $xln = $lnmap{$lnnum}; $ratthash = line_2_hash_on_equals($line,$lnnum); $tag = $attribs[0]; foreach $key (sort keys %{$ratthash}) { $val = ${$ratthash}{$key}; $tkey = substr($key,16); if (length($val) && is_in_array($tkey,@parr)) { if (defined ${$rh}{$tkey}) { $val2 = ${$rh}{$tkey}; prtw( "WARNING:scanvc: key=[$tkey], value=[$val2] REPLACED with [$val] [$fil]\n" ); } else { prt( "[dbg_v26] Added key=[$tkey], value=[$val]\n" ) if ($dbg_v26); ${$rh}{$tkey} = $val; } } } } } else { prtw( "WARNING:scanvc: FAILED to OPEN inherited props [$ff] [$fil]\n" ); } } else { prtw( "WARNING:scanvc: FAILED to FIND inherited props [$itm] [$ff]! in [$fil]\n" ); } } } sub add_vs_config_item($) { my ($rh) = @_; my ($xln,$rah,$tag,$pname,$fil,$projname,$line,$flag); my ($tmp); # 2010/05/05 extract_curr_items($rh,\$xln,\$rah,\$tag,\$pname,\$fil,\$projname,\$line,\$flag); my $conf = $pname; # like ReleaseSSE|WIN32 my @arr = split(/\|/,$pname); # split it my $confname = $arr[0]; # get just 'ReleaseSSE' ${$rh}{'CURR_CONF'} = $confname; ${$rh}{'CURR_CON1'} = $conf; my $dnapptype = ${$rh}{'PROJECT_APTP'}; # 28/09/2008 - note, has quotes added # "-NEW_OUTD-" $out_dir # "-NEW_INTER-" $int_dir my $var1 = "-NEW_OUTD-"; my $var2 = "-NEW_INTER-"; my ($dsp_sub_sub, $seek, $adddeps, $apptype); if ($conf =~ /Debug/i) { $dsp_sub_sub = get_default_sub3(1); } else { $dsp_sub_sub = get_default_sub3(0); # 2010/05/05 - assume 'DLL' means RELEASE without WARNING if (!(($conf =~ /Release/i)||($conf =~ /DLL/))) { prtw( "WARNING:scanvc:$xln: pname=[$conf] NOT Debug or Release - def to REL! [$fil]\n" ); } } my $rcfgs = get_project_configs($rh); # 'PROJECT_CFGS' $tmp = ${$rh}{'PROJECT_CCNT'}; $tmp++; prt("[dbg_v40] STORE:$tmp: In rcfgs (ra)[$confname], [$var1], [$conf], & \$dsp_sub_sub ] )\n") if ($dbg_v40); # ONLY STORE OF 'PROJECT_CFGS' push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); # ONLY STORE OF 'PROJECT_CFGS' ${$rh}{'PROJECT_CCNT'}++; # count of stored 'PROJECT_CFGS ${$rh}{'CURR_DSUB'} = $dsp_sub_sub; #push(@configs,[ $pname, $var1, $conf ]); # // This is an internal type to Visual Studio, it seems that: # // 4 == static library # // 2 == dll # // 1 == executable - note, subsytem decides if this remains 'Application' or becomes 'Console Application' # // 10 == utility $seek = 'ConfigurationType'; if (defined ${$rah}{$seek}) { $tmp = trim_all(${$rah}{$seek}); $tmp =~ s/>$//; # remove any trailing $adddeps = strip_quotes(trim_all($tmp)); $apptype = get_app_conf_type($adddeps); $flag |= $cf_apptype; # signal, we have an APP TYPE - VERY IMPORTANT if (length($dnapptype)) { if ($flag & $cf_apptyp2) { $apptype = $dnapptype; } if ($dnapptype ne $apptype) { prt( "$xln Project [$projname], APP_TYPE RESET per 'ConfigurationType' [$apptype] from [$dnapptype]...\n" ); $dnapptype = $apptype; } } else { prt( "$xln Project [$projname], APP_TYPE per 'ConfigurationType' [$apptype]...\n" ); $dnapptype = $apptype; } ${$rh}{'PROJECT_APTP'} = $dnapptype; ${$rh}{'CURR_FLAG'} = $flag; } else { prtw( "WARNING:scanvc:$xln: DOES NOT CONTAIN(8) 'ConfigurationType' [$line] [$fil]\n" ); } # 2009/10/15 - handle better 'InheritedPropertySheets=".\vc9_lame_config.vsprops;.\arch_nasm.vsprops"' # and this PROPS (vsprops) MAY contain the following items $seek = 'InheritedPropertySheets'; if (defined ${$rah}{$seek}) { $adddeps = strip_quotes(trim_all(${$rah}{$seek})); svc_add_props_to_hash( $fil, $adddeps, $rah, "OutputDirectory;IntermediateDirectory" ); } $seek = 'OutputDirectory'; if (defined ${$rah}{$seek}) { # 20090808 - improved to handle # EG: 9:18-24: Changed(1) OutputDirectory from ["Debug"] # to ["$(SolutionDir)$(ConfigurationName)"] #$adddeps = add_quotes(strip_dotrel(strip_quotes(trim_all($atthash{$seek})))); $adddeps = strip_dotrel(strip_quotes(trim_all(${$rah}{$seek}))); $adddeps =~ s/\$\(SolutionDir\)//; $adddeps =~ s/\$\(ConfigurationName\)/$confname/; if ( ${$dsp_sub_sub}{$var1} ne add_quotes($adddeps)) { prt( "[dbg_v33] $xln Changed(1) [OutputDirectory] from [".${$dsp_sub_sub}{$var1}."] to [".add_quotes($adddeps)."]\n" ) if ($dbg_v33); } ${$dsp_sub_sub}{$var1} = add_quotes($adddeps); } else { prtw( "WARNING:scanvc:xln: DOES NOT CONTAIN(9) '$seek' [$line] [$fil]\n" ); } $seek = 'IntermediateDirectory'; if (defined ${$rah}{$seek}) { # 20090808 - improved to handle # 9:18-24: Changed(2) IntermediateDirectory from ["Debug"] # to ["$(ConfigurationName)"] # $adddeps = add_quotes(strip_dotrel(strip_quotes(trim_all($atthash{$seek})))); $adddeps = strip_dotrel(strip_quotes(trim_all(${$rah}{$seek}))); $adddeps =~ s/\$\(SolutionDir\)//; $adddeps =~ s/\$\(ConfigurationName\)/$confname/; if (${$dsp_sub_sub}{$var2} ne add_quotes($adddeps)) { prt( "[dbg_v20] $xln Changed(2) [IntermediateDirectory] from [".${$dsp_sub_sub}{$var2}."] to [".add_quotes($adddeps)."]\n" ) if ($dbg_v20); } $sc_last_intdir = $adddeps; ${$dsp_sub_sub}{$var2} = add_quotes($sc_last_intdir); } else { prtw( "WARNING:scanvc:$xln DOES NOT CONTAIN(10) '$seek' [$line] [$fil]\n" ); } prt( "[dbg_v06] $xln Bgn ConfigurationName=[$confname] conf=[$conf] [$line] ...($tag)\n" ) if ($dbg_v06); } # my %prj_key_info = ( # 'PROJECT_CFGS' => ' Configurations found', # 'PROJECT_NAME' => ' Name of project:', # 'PROJECT_CCNT' => ' Count of configs', # 'PROJECT_FILE' => ' Input File', # 'PROJECT_SRCS' => ' Array of sources', # 'PROJECT_TYPE' => ' MSVS type', # 'PROJECT_VERS' => ' HASH Version', # 'PROJECT_MSCV' => ' MSVC Version', # 'PROJECT_APTP' => ' Application Type', # 'PROJECT_FLAG' => ' Project flag' # ); sub get_prj_key_info_ref() { my %prj_key_info = ( 'PROJECT_CFGS' => ' Configs found: ', 'PROJECT_NAME' => ' Name of project: ', 'PROJECT_CCNT' => ' Count of configs: ', 'PROJECT_FILE' => ' Input File: ', 'PROJECT_FDIR' => ' Input Directory: ', 'PROJECT_DSPF' => ' Output File: ', 'PROJECT_SRCS' => ' Array of sources: ', 'PROJECT_TYPE' => ' MSVS type: ', 'PROJECT_VERS' => ' HASH Version: ', 'PROJECT_MSCV' => ' MSVC Version: ', 'PROJECT_APTP' => ' Application Type: ', 'PROJECT_FLAG' => ' Project flag: ' ); return \%prj_key_info; } #sub show_new_hash_ref($) { sub show_hash_results3($) { my ($nhr) = @_; my @arr = keys( %{$nhr} ); my $cnt = scalar @arr; prt( "Show of NEW hash reference, with up to $cnt keys...\n" ); my ($key,$val,$inf,$acnt,$src); my ($grp,$flt,$min1,$min2,$len); my ($i,$i2,$msg,$rsb,$scnt,@karr); my ($ky,$v2,$sdir,$ff,$ok); $key = 'PROJECT_FDIR'; $sdir = ${$nhr}{$key}; $cnt = 0; my $rpki = get_prj_key_info_ref(); foreach $key (@arr) { $val = ${$nhr}{$key}; if ( $key =~ /^CURR_/ ) { # ignore these CURRENT state items } else { $cnt++; if (defined ${$rpki}{$key}) { $inf = ${$rpki}{$key}; if (($inf =~ /^/)||($inf =~ /^/)) { prt( "$key $inf =[$val]\n" ); } else { $acnt = scalar @{$val}; prt( "$key $inf =(ARRAY of count $acnt)\n" ); if ($key eq 'PROJECT_SRCS') { $min1 = 0; $min2 = 0; for ($i = 0; $i < $acnt; $i++) { $src = ${$val}[$i][0]; $grp = ${$val}[$i][1]; $flt = ${$val}[$i][2]; $len = length($src); $min1 = $len if ($len > $min1); $len = length($grp); $min2 = $len if ($len > $min2); } for ($i = 0; $i < $acnt; $i++) { $i2 = $i + 1; $src = ${$val}[$i][0]; $grp = ${$val}[$i][1]; $flt = ${$val}[$i][2]; $ff = fix_rel_path3($sdir.$src,'show_hash_results3'); # in fgutils02.pl $ok = (-f $ff) ? 'ok' : 'NF'; $src .= ' ' while(length($src) < $min1); $grp .= ' ' while(length($grp) < $min2); $msg = sprintf("%3d:",$i2); prt( "$msg $src $grp $flt $ok\n" ); } } elsif ($key eq 'PROJECT_CFGS') { # my $rcfgs = ${$rh}{'PROJECT_CFGS'}; # 0 1 2 3 # push(@{$rcfgs}, [ $pname, $var1, $conf, $dsp_sub_sub ]); for ($i = 0; $i < $acnt; $i++) { $i2 = $i + 1; $src = ${$val}[$i][0]; $grp = ${$val}[$i][1]; $flt = ${$val}[$i][2]; $rsb = ${$val}[$i][3]; @karr = keys(%{$rsb}); $scnt = scalar @karr; $msg = sprintf("%3d:",$i2); prt( "$msg $src $grp $flt $scnt\n" ); foreach $ky (@karr) { $v2 = ${$rsb}{$ky}; prt( " $ky = [$v2]\n" ); } } } } } else { prtw( "WARNING:scanvc: [$key] NOT IN INFO LIST, so do not know type! see sub get_prj_key_info_ref() & \%prj_key_info\n" ); } } } prt("Done show of $cnt keys...\n"); } # seems MSVC8, and maybe others, when converting the MSVC6 DSP # to a VCPROJ file can NOT tollerate a command # ending in a '\' character, without quotes around it # ######################################################### sub massage_command3($) { my ($txt) = shift; if ($txt =~ /\\$/) { my ($len, $ch, $bgn, $end); # need to back up to previous space, # and add quotes around the last command $len = length($txt); while ($len) { $len--; $ch = substr($txt,$len,1); if ($ch eq ' ') { last; } } if ($len) { $len++; $bgn = substr($txt,0,$len); $end = substr($txt,$len); $txt = $bgn.add_quotes($end); } } return $txt; } sub get_line_hash_missed($$$) { my ($rah,$dnsks,$ign) = @_; my @arr1 = split(/\|/,$dnsks); my @arr2 = sort(keys(%{$rah})); my $missed = ''; my ($kitm,$ditm,,$fnd); foreach $kitm (@arr2) { # process the keys if ( !defined ${$ign}{$kitm} ) { $fnd = 0; foreach $ditm (@arr1) { if ($kitm eq $ditm) { $fnd = 1; last; } } if (!$fnd) { $missed .= '|' if (length($missed)); $missed .= $kitm; } } } #prtw( "WARNING:scanvc: MISSED [$missed]!\n" ) if (length($missed)); return $missed; } sub get_ct_line_hash_missed($$) { my ($rah,$dnsks) = @_; return get_line_hash_missed($rah,$dnsks,\%ignore_in_ct_lh); } sub get_nodeflib_string($) { my ($add) = @_; my $rstg = ''; if (length($add)) { $rstg = "/nodefaultlib:\"$add\""; } return $rstg; } sub process_vc_conf_tool_tag($) { my ($rh) = @_; my ($xln,$rah,$tag,$pname,$fil,$projname,$line,$flag); extract_curr_items($rh,\$xln,\$rah,\$tag,\$pname,\$fil,\$projname,\$line,\$flag); my ($var1,$var2,$var3,$seek); my ($ppdefs,$curval,$newval); my ($adddeps,$doneseeks,$missed); my ($tmp); # 2010/05/01 my $last_src = ${$rh}{'CURR_LSRC'}; my $last_nm = ${$rh}{'CURR_LNME'}; my $last_dir = ${$rh}{'CURR_LDIR'}; my $last_ext = ${$rh}{'CURR_LEXT'}; my $confname = ${$rh}{'CURR_CONF'}; my $dsp_sub_sub = ${$rh}{'CURR_DSUB'}; my $dnapptype = ${$rh}{'PROJECT_APTP'}; my $lhlen = scalar keys(%{$rah}); # get item count in line hash my ($apptype,$outfile); $doneseeks = ''; $outfile = ''; if ($pname eq 'VCCLCompilerTool') { $var1 = '-NEW_INCS-'; $var2 = '-NEW_DEFS-'; $var3 = '-NEW_RT-'; # '] # WATCHOUT FOR # AdditionalIncludeDirectories="..\..;"..\..\..\zlib-1.2.3"" $seek = 'AdditionalIncludeDirectories'; # -NEW_INCS_[DBG|REL]- $doneseeks = $seek; if ( defined ${$rah}{$seek} ) { $ppdefs = strip_quotes(trim_all(${$rah}{$seek})); $ppdefs =~ s/&/&/g; # 20081205 - added $ppdefs =~ s/"/"/g; $curval = ''; if (defined ${$dsp_sub_sub}{$var1}) { $curval = ${$dsp_sub_sub}{$var1}; } $newval = get_includes_string($ppdefs); if ($curval ne $newval) { ${$dsp_sub_sub}{$var1} = $newval; if ($dbg_v25) { prt( "[dbg_v25] " ); if (length($curval)) { prt( "$xln VCCLCompilerTool:AdditionalIncludeDirectories: RESET [$var1] to [$newval] from [$curval]\n" ); } else { prt( "$xln VCCLCompilerTool:AdditionalIncludeDirectories: set [$var1] to [$newval]\n" ); } } } } else { ${$dsp_sub_sub}{$var1} = ''; prt( "[dbg_v13] $xln 'VCCLCompilerTool' DOES NOT CONTAIN(1) 'AdditionalIncludeDirectories' [$line]\n" ) if ($dbg_v13); } $seek = 'PreprocessorDefinitions'; $doneseeks .= "|$seek"; if ( defined ${$rah}{$seek} ) { $ppdefs = strip_quotes(trim_all(${$rah}{$seek})); prt( "[dbg_v03] seek=PreprocessorDefinitions = [$ppdefs] [$fil]\n" ) if ($dbg_v03); $curval = ''; if (defined ${$dsp_sub_sub}{$var1}) { $curval = ${$dsp_sub_sub}{$var1}; } $newval = get_defines_string($ppdefs); # lib function - fgutils02.pl ${$dsp_sub_sub}{$var2} = $newval; } else { # 2009/09/22 - downgraded from WARNING, to a simple ADVICE # prtw( "WARNING:$lnnum:$xln 'VCCLCompilerTool' DOES NOT CONTAIN(2) '$seek' [$line]\n" ); prt( "[dbg_v04] $xln 'VCCLCompilerTool' DOES NOT CONTAIN(2) 'PreprocessorDefinitions' [$line]\n" ) if ($dbg_v04); } $seek = 'RuntimeLibrary'; $doneseeks .= "|$seek"; if ( defined ${$rah}{$seek} ) { $ppdefs = strip_quotes(trim_all(${$rah}{$seek})); ${$dsp_sub_sub}{$var3} = fg_get_runtime_val_2_lts($ppdefs); } else { # 2009/09/22 - downgraded from WARNING, to a simple ADVICE # prtw( "WARNING:$lnnum:$xln 'VCCLCompilerTool' DOES NOT CONTAIN(3) '$seek' [$line]\n" ); prt( "[dbg_v05] $xln 'VCCLCompilerTool' DOES NOT CONTAIN(3) 'RuntimeLibrary' [$line]\n" ) if ($dbg_v05); } $seek = 'CompileAs'; $doneseeks .= "|$seek"; if ( defined ${$rah}{$seek} ) { $ppdefs = strip_quotes(trim_all(${$rah}{$seek})); $adddeps = ${$dsp_sub_sub}{$var3}; if (defined $compileas{$ppdefs} ) { $tmp = $compileas{$ppdefs}; if (length($tmp)) { $adddeps .= " " if length($adddeps); $adddeps .= "/$tmp"; } $curval = ''; if (defined ${$dsp_sub_sub}{$var3}) { $curval = ${$dsp_sub_sub}{$var3}; } $newval = $adddeps; if ($curval ne $newval) { ${$dsp_sub_sub}{$var3} = $newval; prt( "[dbg_v32] $xln VCCLCompilerTool:CompileAs: set [$var3] from [$curval] to [".${$dsp_sub_sub}{$var3}."]\n" ) if ($dbg_v32); } else { prt( "[dbg_v32] $xln VCCLCompilerTool:CompileAs: NO CHANGE [$var3] as [$curval]\n" ) if ($dbg_v32); } } else { prtw( "WARNING:scanvc:$xln: VCCLCompilerTool:$seek: [$var3] NOT BEING SET! [$ppdefs] NOT IN 'compileas' hash [$fil]\n" ); } } $missed = get_ct_line_hash_missed($rah,$doneseeks); if ($dbg_v31) { prt( "[dbg_v31] " ); if (length($missed)) { prt( "$xln conf=[$confname]:VCCLCompilerTool: [$line]\n seeks=[$doneseeks]\n missed=[$missed] ($lhlen)\n" ); } else { prt( "$xln conf=[$confname]:VCCLCompilerTool: [$line] ($lhlen)\n" ); # if ($dbg_v10); } } } elsif ($pname eq 'VCCustomBuildTool') { if (length($pname) && ($lhlen < 4)) { # this is ONLY - so IGNORE } else { prtw( "WARNING:scanvc: MISSED CUSTOM BUILD: Check this conf=[$confname] TAG=$tag -\n [$line]\n" ); } } elsif ($pname eq 'VCLinkerTool') { $var1 = '-NEW_LIBS-'; $var2 = '-NEW_OUT-'; # $seek = 'AdditionalDependencies'; if (defined ${$rah}{$seek} ) { $adddeps = strip_quotes(trim_all(${$rah}{$seek})); $adddeps =~ s/&/&/g; # 20081205 - added $adddeps =~ s/"/"/g; # 20081205 - added $newval = $adddeps; $curval = ''; if (defined ${$dsp_sub_sub}{$var1}) { $curval = ${$dsp_sub_sub}{$var1}; } if ($newval ne $curval) { ${$dsp_sub_sub}{$var1} = $adddeps; prt( "[dbg_v22] $xln seek=AdditionalDependencies: Set [$var1] to [$adddeps]\n" ) if ($dbg_v22); } } else { prtw( "WARNING:scanvc:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(4) '$seek' [$line] [$fil]\n" ) if ($dbg_v16); } $seek = 'OutputFile'; if (defined ${$rah}{$seek} ) { $adddeps = strip_quotes(trim_all(${$rah}{$seek})); # 20090808 - handle substitution # EG: 39:138-149: seek=OutputFile: Set [-NEW_OUT_REL-] # to [.\$(ProjectName).exe] $adddeps =~ s/\$\(ProjectName\)/$projname/; $curval = ''; if (defined ${$dsp_sub_sub}{$var2}) { $curval = ${$dsp_sub_sub}{$var2}; } $newval = '/out:'.$adddeps; if ($curval ne $newval) { ${$dsp_sub_sub}{$var2} = $newval; prt( "[dbg_v24] $xln seek=OutputFile: Set [$var2] to [$newval]\n" ) if ($dbg_v24); } $outfile = $adddeps; } else { # 20090912 - downgraded to a NOTE only, and ONLY once per file if ( !($flag & $cf_dn_lt_t) ) { # $dn_lt_noo # prtw( "WARNING:$lnnum:$xln 'VCCLinkerTool' DOES NOT CONTAIN(5) '$seek' [$line]\n" ) if ($dbg_v21); prt( "NOTE:scanvc:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(5) 'OutputFile' [$line]\n" ); # if ($dbg_v21); $flag |= $cf_dn_lt_t; # $dn_lt_noo = 1; ${$rh}{'CURR_FLAG'} |= $cf_dn_lt_t; } } $seek = 'AdditionalLibraryDirectories'; if (defined ${$rah}{$seek} ) { # must deal with a crazy string like this - # AdditionalLibraryDirectories= # "&quot,..\fltk-1.1.7\lib&quot,..\SimGear.plib\Debug, # ..\zlib-1.2.3&quot,..\plib, # ..\pthreads-w32-2-7-0-release&quot,..\gettext\lib" # after quotes removed, and the first substitution # ",..\fltk-1.1.7\lib",..\SimGear.plib\Debug, # ..\zlib-1.2.3",..\plib, # ..\pthreads-w32-2-7-0-release",..\gettext\lib # after next pair of subs # ",..\fltk-1.1.7\lib",..\SimGear.plib\Debug, # ..\zlib-1.2.3",..\plib, # ..\pthreads-w32-2-7-0-release",..\gettext\lib # then removing the auotes # ,..\fltk-1.1.7\lib,..\SimGear.plib\Debug, # ..\zlib-1.2.3,..\plib, # ..\pthreads-w32-2-7-0-release,..\gettext\lib $adddeps = strip_quotes(trim_all(${$rah}{$seek})); $adddeps =~ s/&/&/g; # 20081205 - added $adddeps =~ s/"/"/g; # 20081205 - added $adddeps =~ s/"/"/g; # 20081205 - added $adddeps =~ s/"//g; # 20081205 - added $adddeps =~ s/^,//; # 20081205 - added $tmp = get_libpaths_string($adddeps); $curval = ''; if (defined ${$dsp_sub_sub}{$var1}) { $curval = ${$dsp_sub_sub}{$var1}; } ${$dsp_sub_sub}{$var1} .= ' '.$tmp; prt( "[dbg_v23] $xln seek=AdditionalLibraryDirectories: Set [$var1] to [$tmp] from [$adddeps]\n" ) if ($dbg_v23); } else { # This is very likely to be TRUE in DLL project especially, since they are DYNAMIC, # and do not link with any other libriaries at compile time prt( "[dbg_v23] $xln 'VCCLinkerTool' DOES NOT CONTAIN(6) 'AdditionalLibraryDirectories' [$line] [$fil]\n" ) if ($dbg_v23); } $seek = 'IgnoreDefaultLibraryNames'; if (defined ${$rah}{$seek}) { # $var1 = '-NEW_LIBS-'; # this would also be an indication that this was a 'exe' type project # Note, it may be a BLANK $adddeps = trim_all(strip_quotes(trim_all(${$rah}{$seek}))); if (length($adddeps)) { $tmp = get_nodeflib_string($adddeps); $curval = ''; if (defined ${$dsp_sub_sub}{$var1}) { $curval = ${$dsp_sub_sub}{$var1}; ${$dsp_sub_sub}{$var1} .= ' '; } ${$dsp_sub_sub}{$var1} .= $tmp; prt( "[dbg_v39] $xln seek=IgnoreDefaultLibraryNames: Set [$var1] to [$tmp] from [$adddeps] prev [$curval]\n" ) if ($dbg_v39); } } $seek = 'SubSystem'; if (defined ${$rah}{$seek} ) { $adddeps = strip_quotes(trim_all(${$rah}{$seek})); $apptype = adjust_app_type_per_subsystem( $dnapptype, $adddeps, $dbg_v05 ); $flag |= $cf_apptyp2; # signal, we have an APP TYPE - VERY IMPORTANT # subsystem determines different between 'Application' and 'Console Application' if (length($dnapptype)) { if ($dnapptype ne $apptype) { prt( "$xln Project [$projname], APP_TYPE RESET per 'SubSystem' [$apptype] from [$dnapptype]...\n" ); $dnapptype = $apptype; } } else { prt( "$xln Project [$projname], APP_TYPE per 'SubSystem' [$apptype]...\n" ); $dnapptype = $apptype; } ${$rh}{'PROJECT_APTP'} = $dnapptype; ${$rh}{'CURR_FLAG'} |= $flag; } else { # it seems DLL vcproj do NOT have a 'SubSystem' # ] # from [c:\FG\32\alut\admin\VisualStudioDotNET\alut\alut.vcproj] $seek = 'ImportLibrary'; # seems this IMPORT LIBRARY entry would be a good DLL indication! if (defined ${$rah}{$seek}) { $apptype = ''; if (get_app_type_4_short('DLL', \$apptype) && length($apptype)) { $flag |= $cf_apptyp2; # signal, we have an APP TYPE - VERY IMPORTANT # should be DLL if (length($dnapptype)) { if ($dnapptype ne $apptype) { prt( "$xln Project [$projname], APP_TYPE RESET per 'ImportLibrary' [$apptype] from [$dnapptype]...\n" ); $dnapptype = $apptype; } else { prt( "[dbg_v35] $xln Project [$projname], APP_TYPE CONFIRMED per 'ImportLibrary' set to [$dnapptype]...\n" ) if ($dbg_v35); } } else { prt( "$xln Project [$projname], APP_TYPE per 'ImportLibrary' [$apptype]...\n" ); $dnapptype = $apptype; } ${$rh}{'PROJECT_APTP'} = $dnapptype; ${$rh}{'CURR_FLAG'} |= $flag; } else { prtw( "WARNING:scanvc:$xln: FAILED TO GET 'DLL' application type string!\n" ); # if ($dbg_v18); pgm_exit(1,"INTERNAL FAILURE"); } } else { # ANOTHER STRONG indication of a DLL would be the presence of a DEF (definition) file $seek = 'ModuleDefinitionFile'; if (defined ${$rah}{$seek}) { $apptype = ''; if (get_app_type_4_short('DLL', \$apptype) && length($apptype)) { $flag |= $cf_apptyp2; # signal, we have an APP TYPE - VERY IMPORTANT # should be DLL if (length($dnapptype)) { if ($dnapptype ne $apptype) { prt( "$xln Project [$projname], APP_TYPE RESET per 'ModuleDefinitionFile' [$apptype] from [$dnapptype]...\n" ); $dnapptype = $apptype; } else { prt( "[dbg_v35] $xln Project [$projname], APP_TYPE CONFIRMED per 'ModuleDefinitionFile' set to [$dnapptype]...\n" ) if ($dbg_v35); } } else { prt( "$xln Project [$projname], APP_TYPE per 'ModuleDefinitionFile' [$apptype]...\n" ); $dnapptype = $apptype; } ${$rh}{'PROJECT_APTP'} = $dnapptype; ${$rh}{'CURR_FLAG'} |= $flag; } else { prtw( "WARNING:scanv:$xln: FAILED TO GET 'DLL' application type string!\n" ); # if ($dbg_v18); pgm_exit(1,"INTERNAL FAILURE"); } } else { # FINALLY ANOTHER STRONG indication of a DLL would be that OutputFile ends in ".dll" $seek = 'OutputFile'; if ( length($outfile) && ($outfile =~ /\.dll$/i)) { $apptype = ''; if (get_app_type_4_short('DLL', \$apptype) && length($apptype)) { $flag |= $cf_apptyp2; # signal, we have an APP TYPE - VERY IMPORTANT if (length($dnapptype)) { if ($dnapptype ne $apptype) { prt( "$xln Project [$projname], APP_TYPE RESET per 'OutputFile' [$apptype] from [$dnapptype]...\n" ); $dnapptype = $apptype; } else { prt( "[dbg_v35] $xln Project [$projname], APP_TYPE CONFIRMED per 'OutputFile' set to [$dnapptype]...\n" ) if ($dbg_v35); } } else { prt( "$xln Project [$projname], APP_TYPE per 'OutputFile' [$apptype]...\n" ); $dnapptype = $apptype; } ${$rh}{'PROJECT_APTP'} = $dnapptype; ${$rh}{'CURR_FLAG'} |= $flag; } else { prtw( "WARNING:scanv:$xln: FAILED TO GET 'DLL' application type string!\n" ); # if ($dbg_v18); pgm_exit(1,"INTERNAL FAILURE"); } } else { if (!($flag & $cf_dn_no_s)) { prtw( "WARNING:scanvc:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(7) 'SubSystem' NOR 'ModuleDefinitionFile' NOR 'OutputFile' [$line] [$fil]\n" ); # if ($dbg_v18); $flag |= $cf_dn_no_s; ${$rh}{'CURR_FLAG'} |= $flag; } } } } } } elsif ($pname eq 'VCLibrarianTool' ) { # $var2 = '-NEW_OUT-'; $seek = 'OutputFile'; if (defined ${$rah}{$seek} ) { $adddeps = strip_quotes(trim_all(${$rah}{$seek})); $curval = ''; if (defined ${$dsp_sub_sub}{$var2}) { $curval = ${$dsp_sub_sub}{$var2}; } $newval = '/out:'.$adddeps; if ($curval ne $newval) { ${$dsp_sub_sub}{$var2} = $newval; prt( "[dbg_v24] $xln seek=OutputFile: Set [$var2] to [$newval]\n" ) if ($dbg_v24); } } else { # 20090914 - set as 15, downgraded to a NOTE only, and ONLY once per file # it seems this will DEFAULT TO '$(OutDir)\$(ProjectName).lib'!!! if ( !($flag & $cf_dn_lt_t) ) { # $dn_lt_noo # prtw( "WARNING:$lnnum:$xln 'VCCLinkerTool' DOES NOT CONTAIN(5) '$seek' [$line]\n" ) if ($dbg_v21); prt( "NOTE:scanvc:$xln: 'VCCLinkerTool' DOES NOT CONTAIN(15) '$seek' [$line]\n" ); # if ($dbg_v21); $flag |= $cf_dn_lt_t; # $dn_lt_noo = 1; ${$rh}{'CURR_FLAG'} |= $cf_dn_lt_t; } } } elsif ($pname eq 'VCPostBuildEventTool') { $var1 = '-NEW_POST-'; #if ( !(($confname =~ /Debug/i)||($confname =~ /Release/i)) ) { # prtw( "WARNING:$xln pname=[$confname] NOT Debug or Release - def to REL! [$fil]\n" ); #} # # this will be output to the DSP, under the paticular, config, something like # # Begin Special Build Tool # SOURCE="$(InputPath)" # PostBuild_Desc=Copy to bin # PostBuild_Cmds=copy Release\*exe bin\. copy test.h bin\. # # End Special Build Tool # 2010/01/14 = Can be 'Description=""Copy Library to plib directory""' Note double QUOTES as '"', AND '"' # or even '"&quot;Copy Library to plib directory&quot;"' if (( defined ${$rah}{'Description'} ) || ( defined ${$rah}{'CommandLine'} ) ) { $ppdefs = ""; # to 'PostBuild_Desc='; if ( defined ${$rah}{'Description'} ) { #$ppdefs .= add_quotes(strip_quotes(trim_all(${$rah}{'Description'}))); $ppdefs = strip_quotes(trim_all(${$rah}{'Description'})); prt("[dbg_v36] Got description: [$ppdefs]\n") if ($dbg_v36); $ppdefs =~ s/"/"/g; $ppdefs = strip_quotes($ppdefs); $ppdefs =~ s/&/&/g; # could strip it ALL with added, but not for now... #$ppdefs =~ s/"/"/g; #$ppdefs = strip_quotes($ppdefs); $ppdefs = add_quotes($ppdefs); prt("[dbg_v36] Massaged to: [$ppdefs]\n") if ($dbg_v36); } $adddeps = ""; # to ' PostBuild_Cmds='; if ( defined ${$rah}{'CommandLine'} ) { $adddeps = strip_quotes(trim_ends(${$rah}{'CommandLine'})); $adddeps =~ s/"/"/g; # put back the quotes, if any $adddeps =~ s/ /\t/g; # new line to TAB for VC6 $adddeps =~ s/\t$//; # clear any END tab } prt( "[dbg_v15] $xln got POST event [$ppdefs]\n" ) if ($dbg_v15); $tmp = "# Begin Special Build Tool\n"; $tmp .= "SOURCE=\"\$(InputPath)\"\n"; $tmp .= "PostBuild_Desc=$ppdefs\n"; # sometimes need a little 'massaging' of the command ... $tmp .= "PostBuild_Cmds=".massage_command3($adddeps)."\n"; $tmp .= "# End Special Build Tool\n"; ${$dsp_sub_sub}{$var1} = $tmp; } } elsif ($pname eq 'VCMIDLTool') { # perhaps to be done *TBD* } elsif ($pname eq 'VCResourceCompilerTool') { # perhaps to be done *TBD* } elsif ($pname eq 'VCBscMakeTool') { # perhaps to be done *TBD* } else { if (length($pname) && ($lhlen < 4)) { # this is ONLY - so IGNORE } else { prtw( "WARNING:scanvc:$xln: conf=[$confname] Tag=[$tag] [$pname] NOT HANDLED! [$line] ($lhlen)\n" ); } } } sub process_vc_file_tool_tag($$) { my ($rh,$fconf) = @_; my ($xln,$rah,$tag,$pname,$fil,$projname,$line,$flag); extract_curr_items($rh,\$xln,\$rah,\$tag,\$pname,\$fil,\$projname,\$line,\$flag); my ($seek); my ($ppdefs,$curval,$newval); my ($adddeps); my ($adddefs,$tmp); # 2010/05/01 my $last_src = ${$rh}{'CURR_LSRC'}; my $last_nm = ${$rh}{'CURR_LNME'}; my $last_dir = ${$rh}{'CURR_LDIR'}; my $last_ext = ${$rh}{'CURR_LEXT'}; my $dsp_sub_sub = ${$rh}{'CURR_DSUB'}; my $lhlen = scalar keys(%{$rah}); # get item count in line hash if ($pname eq 'VCCLCompilerTool') { prt( "[dbg_v34] $xln file: 'VCCLCompilerTool' [$line] IGNORED CHECK ($lhlen)\n" ) if ($dbg_v34); } elsif ($pname eq 'VCCustomBuildTool') { my ($nm,$dir); my $pfhr = get_per_file_hash($rh); # 'CURR_PFHR' if (( defined ${$rah}{'Description'} ) || ( defined ${$rah}{'CommandLine'} ) ) { $ppdefs = ""; # to 'PostBuild_Desc='; $seek = 'Description'; if ( defined ${$rah}{$seek} ) { $ppdefs .= strip_quotes(trim_all(${$rah}{$seek})); } $seek = 'CommandLine'; $adddeps = ""; # to ' PostBuild_Cmds='; if ( defined ${$rah}{$seek} ) { $adddeps = strip_quotes(trim_ends(${$rah}{$seek})); $adddeps =~ s/"/"/g; # put back the quotes, if any $adddeps =~ s/ /\t/g; # new line to TAB for VC6 $adddeps =~ s/\t$//; # clear any END tab } $adddefs = '$(IntDir)'; $seek = 'Outputs'; if ( defined ${$rah}{$seek} ) { $adddefs = strip_quotes(trim_all(${$rah}{$seek})); } # this seems to be something like - # $(IntDir)\asm\$(InputName).obj, but for the DSP file the '\$(InputName).obj' seems ASSUMED, # and the $(IndDir) is replaced with an actual DIRECTORY, so... if ($adddefs =~ /\.obj$/i) { ($nm,$dir) = fileparse( $adddefs ); $dir =~ s/(\\|\/)$//; $adddefs = $dir; } if ($adddefs =~ /\$\(IntDir\)/) { if (defined ${$dsp_sub_sub}{'-NEW_INTER-'}) { $dir = strip_quotes(${$dsp_sub_sub}{'-NEW_INTER-'}); $dir =~ s/(\\|\/)$//; $adddefs =~ s/\$\(IntDir\)/$dir/; } } $tmp = "# Begin Custom Build - $ppdefs\n"; $tmp .= "IntDir=$adddefs\n"; $tmp .= "Inputpath=$last_src\n"; $tmp .= "InputName=$last_nm\n\n"; $tmp .= "\"\$(IntDir)\\\$(InputName).obj\" : \$(SOURCE) \"\$(INTDIR)\" \"\$(OUTDIR)\"\n"; $tmp .= "\t".massage_command3($adddeps)."\n\n"; $tmp .= "# End Custom Build\n"; prt( "[dbg_v27] $xln got CUSTOM event [$pname] [$fconf] [$adddefs]\n" ) if ($dbg_v27); prt( "[dbg_v28] CUSTOM event [$tmp]\n" ) if ($dbg_v28); if (defined ${$pfhr}{$fconf}) { prtw("WARNING:scanvc: Already have [$fconf] in per_file_hash!\n"); } ${$pfhr}{$fconf} = $tmp; # store it for later } else { $tmp = scalar keys(%{$rah}); if (length($pname) && ($tmp < 4)) { # ignore is just , but empty otherwise } else { prtw( "WARNING:scanvc: Deal with TAG=$tag - [$line] NO Decription or Command line! ($tmp)\n file=[$fil]\n" ); } } } elsif ($pname eq 'VCResourceCompilerTool') { prt( "[dbg_v34] $xln file: 'VCResourceCompilerTool' [$line] IGNORED CHECK (line=$lhlen)\n" ) if ($dbg_v34); } else { prtw( "WARNING:scanvc:$xln: [$pname] NOT HANDLED! (line=$lhlen)\n" ); } } sub get_cfgs_array_order($$) { my ($rcfgs,$rkarr) = @_; my $cnt = scalar @{$rcfgs}; my ($i, $cfg, $test, @arr); @arr = (); push(@arr,-99); push(@arr,-99); return 0 if ($cnt < 2); $test = 0; # 2010/05/05 - add init of var for ($i = 0; $i < $cnt; $i++) { $cfg = ${$rcfgs}[$i][0]; if ($cfg eq 'Release') { $test |= 1; $arr[0] = $i; } elsif ($cfg eq 'Debug') { $test |= 2; $arr[1] = $i; } else { push(@arr,$i); } } if ($test == 3) { # found both 'Release' and 'Debug' # then enforce the ORDER 'Release, Debug, Others @{$rkarr} = @arr; # copy the index array return 1; } return 0; } #add_any_per_file_items( $rdsp_current_sub, \%per_file_hash, $src_ref, # \@configs, $last_fpos, $projname ); sub add_any_per_file_items3($) { my ($rh) = @_; my $pfhr = get_per_file_hash($rh); # 'CURR_PFHR' my $xln = get_current_xline_stg($rh); my @karr = keys(%{$pfhr}); my $kcnt = scalar @karr; my $modstg = $xln."scanvc:add_any_per_file_items3:"; my ($cfg); # 2010/05/01 if ($kcnt) { my ($rcfgs,$ccnt,$key,$i,$fnd,$tmp,$pname); $rcfgs = get_project_configs($rh); # 'PROJECT_CFGS' $pname = svc_get_project_name_stg($rh); # 'PROJECT_NAME' # push(@{$rcfgs}, [ $confname, $var1, $conf, $dsp_sub_sub ]); $ccnt = scalar @{$rcfgs}; $fnd = 0; foreach $key (@karr) { for ($i = 0; $i < $ccnt; $i++) { if (${$rcfgs}[$i][2] eq $key) { $fnd++; last; } } } if ($fnd == $kcnt) { $tmp = ''; @karr = (); # clear this array if ( get_cfgs_array_order($rcfgs,\@karr) && (scalar @karr == $kcnt) ) { $fnd = 0; foreach $i (@karr) { $key = ${$rcfgs}[$i][2]; $cfg = ${$rcfgs}[$i][0]; if ($fnd == 0) { $tmp .= "\n!IF "; # Release } else { $tmp .= "!ELSEIF "; # Debug, and others } $tmp .= "\"\$(CFG)\" == \"$pname - Win32 $cfg\"\n\n"; if (defined ${$pfhr}{$key}) { $tmp .= ${$pfhr}{$key}; } $tmp .= "\n"; $fnd++; } } else { for ($i = 0; $i < $ccnt; $i++) { $key = ${$rcfgs}[$i][2]; $cfg = ${$rcfgs}[$i][0]; if ($i == 0) { $tmp .= "\n!IF "; } else { $tmp .= "!ELSEIF "; } $tmp .= "\"\$(CFG)\" == \"$pname - Win32 $cfg\"\n\n"; if (defined ${$pfhr}{$key}) { $tmp .= ${$pfhr}{$key}; } $tmp .= "\n"; } } $tmp .= "!ENDIF \n\n"; my $srcs = get_project_srcs_ref($rh); # 'PROJECT_SRCS' my $coff = get_last_src_offset($rh); # 'CURR_LOFF' # last/current source OFFSET # 0 1 2 3 4 # push(@{$src_ref}, [ $last_src, $fname, $flist, 0, '' ]); # and PUSH onto SOURCE stack $key = ${$srcs}[$coff][0]; ${$srcs}[$coff][4] = $tmp; prt( "[dbg_v29] $xln Added CUSTOM build for source [$key]\n" ) if ($dbg_v29); prt( "[dbg_v30] CUSTOM build [$tmp]\n" ) if ($dbg_v30); } else { prtw("WARNING:scanvc: $kcnt keys NOT handled in per file hash! Only found $fnd!!\n"); } } else { prt("[dbg_v11] $xln NO keys in per file hash...\n") if ($dbg_v11); } } sub get_xln_stg($$) { my ($lnn,$npair) = @_; # "$lnnum:".${$rlm}{$lnnum}; my @a = split('-',$npair); my $xln = sprintf("%03d:%03d-%03d:", $lnn, $a[0], $a[1]); return $xln; } sub get_clean_seek_item($) { my ($txt) = shift; $txt =~ s/>$//; # 2010-04-23 - ensure any trailing '>' is removed $txt = strip_quotes(trim_all($txt)); return $txt; } # sub pre_process_VCPROJ($$$) { sub process_VC_lines($$$) { my ($fil, $rlines, $rlm) = @_; my ($line, @attribs, %atthash); my ($tag, $pname); my $invcproj = 0; my $projname = ''; my $adddeps = ''; my $adddefs = ''; my $do_pre_pro = 1; my $lnnum = 0; my $xln = ''; my $rh = get_default_ref_hash($fil); my $infile = 0; my $infilter = 0; my $inconfig = 0; my $fname = ''; my $flist = ''; my $fconf = ''; my ($tmp); my $last_src = ''; my ($last_nm,$last_dir,$last_ext,$src_ref); my $confname = ''; my $conf = ''; $g_sc_infiles = 0; $g_sc_inconfigs = 0; $g_sc_infconf = 0; my %p_f_h = (); my $pfhr = \%p_f_h; my ($seek,$var1); # 2010/05/01 if ($do_pre_pro) { $fname = ''; $flist = ''; foreach $line (@{$rlines}) { $lnnum++; $xln = get_xln_stg($lnnum,${$rlm}{$lnnum}); # "$lnnum:".${$rlm}{$lnnum}; @attribs = space_split($line); %atthash = array_2_hash_on_equals(@attribs); $tag = $attribs[0]; #$pname = (defined $atthash{'Name'}) ? strip_quotes(trim_all($atthash{'Name'})) : ''; $pname = (defined $atthash{'Name'}) ? get_clean_seek_item($atthash{'Name'}) : ''; ${$rh}{'CURR_LINE'} = $xln; ${$rh}{'CURR_TEXT'} = $line; ${$rh}{'CURR_HASH'} = \%atthash; ${$rh}{'CURR_TAG'} = $tag; ${$rh}{'CURR_NAME'} = $pname; ${$rh}{'CURR_PFHR'} = $pfhr; if ($invcproj) { if ($tag =~ /<\/VisualStudioProject/) { $invcproj = 0; $tmp = ${$rh}{'PROJECT_NAME'}; $adddefs = ${$rh}{'PROJECT_TYPE'}; $adddeps = ${$rh}{'PROJECT_VERS'}; prt( "[dbg_v01] $xln End VisualStudioProject name=[$tmp], type=[$adddefs], vers=[$adddeps]\n" ) if ($dbg_v01); } else { # ===================================================================== # *** IN THE PROJECT *** if ($g_sc_inconfigs) { if ($tag =~ /<\/Configurations/) { $g_sc_inconfigs = 0; prt( "[dbg_v02] $xln End Configurations ($tag)\n" ) if ($dbg_v02); } else { # ================================================================== # *** IN CONFIGURATIONS *** if ($inconfig) { if ($tag =~ /^<\/Configuration>/) { prt( "[dbg_v06] $xln End ConfigurationName=[$confname] conf=[$conf] [$line] ...($tag)\n" ) if ($dbg_v06); $inconfig = 0; } else { if ($tag =~ /^ # # if (!$flist_done_once) { prtw( "WARNING:scanvc:$xln: DOES NOT CONTAIN(12) '$seek'? [$line] [$fil]\n" ); # if ($dbg_v17); $flist_done_once++; } } # prt( "$lnnum:$xln ENTER Filter name=[$fname] list=[$flist]\n" ) if ($dbg_v11); prt( "[dbg_v07] $xln Bgn Filter name=[$fname] list=[$flist] ($tag)\n" ) if ($dbg_v07); $infilter = 1; } elsif ($tag =~ /^<\/Filter/) { $infilter = 0; prt( "[dbg_v07] $xln End Filter ($tag)\n" ) if ($dbg_v07); $fname = ''; $flist = ''; } elsif ($tag =~ /^$//; $last_src = strip_dotrel(strip_quotes(trim_all($var1))); # # this is the RELATIVE PATH - relative to the vcproj file being scanned # Now would be a good time to ADJUST this PATH, for any NEW location # of the final DSP file!!! BUT, this is done back in vcproj05.pl # in the sub chk_relative_paths()... # ========================= ($last_nm,$last_dir,$last_ext) = fileparse( $last_src, qr/\.[^.]*/ ); # ========================= $src_ref = get_project_srcs_ref($rh); # 'PROJECT_SRCS' ${$rh}{'CURR_LOFF'} = scalar @{$src_ref}; # get current source OFFSET # *** STORING SOURCE *** push(@{$src_ref}, [ $last_src, $fname, $flist, 0, '' ]); # and PUSH onto SOURCE stack ${$rh}{'CURR_LSRC'} = $last_src; ${$rh}{'CURR_LNME'} = $last_nm; ${$rh}{'CURR_LDIR'} = $last_dir; ${$rh}{'CURR_LEXT'} = $last_ext; } else { prtw( "ERROR:scanvc:$xln: NO ITEM(1) '$seek'? [$line] [$fil]\n" ); pgm_exit(1, "NO FILE NAME FOUND!\n" ); } $infile = 1; prt( "[dbg_v08] $xln Bgn File [$last_src] ($tag)\n" ) if ($dbg_v08); } elsif ($tag =~ /^<\/File>/) { prt( "[dbg_v08] $xln End File ($tag)\n" ) if ($dbg_v08); #add_any_per_file_items( $rdsp_current_sub, \%per_file_hash, $src_ref, # \@configs, $last_fpos, $projname ); add_any_per_file_items3($rh); # %p_f_h = (); %{$pfhr} = (); $infile = 0; } elsif ($tag =~ /^') { # end of XML tag $nlnm++; push(@nlines,$tag); ### prt( "push(\@xlnmap, [ $nlnm, $lnb, $lnnm ]); # each NEW line has BEGIN and END\n" ); $$rlm{$nlnm} = "$lnb-$lnnm"; # each NEW line has BEGIN and END $nxtxt .= "$lnb-$lnnm: [$tag]\n"; $tag = ''; $intag = 0; $xml = ''; } } else { if ($ch eq '<') { $tag = $ch; # start a tag line $intag = 1; # signal in a tag $xml = ''; $dnx = 0; $lnb = $lnnm; # set the BEGIN xml line } } $pch = $ch; } # done a line - this is like a SPACE if ($intag && length($tag)) { $tag .= ' ' if !($tag =~ /\s$/); } } if (length($tag)) { prtw("WARNING:scanvc: xml re-lining error! Left pending tag [$tag]\nin $g_sc_act_vcproj file ...\n"); } $dnx = scalar @nlines; if ($dnx < 5) { prt("ERROR: Input file [$g_sc_act_vcproj] only has $dnx lines!\n"); pgm_exit(1, "INPUT TOO SMALL!!!\n"); } if ($write_temp_xml) { my $tmpxml = "C:\\GTools\\perl\\tempvcx.xml"; if (! -f $tmpxml) { write2file($nxtxt,$tmpxml); prt( "Written relined XML to '$tmpxml'\n" ); } } return @nlines; } sub process_VCPROJ3 { my ($fil) = shift; $g_sc_act_vcproj = $fil; ($g_sc_act_name,$g_sc_act_path) = fileparse($fil); $g_sc_act_path = cwd() if ($g_sc_act_path =~ /^\.(\\|\/)$/); $g_sc_act_path .= "\\" if (!($g_sc_act_path =~ /(\\|\/)$/)); my ($new_ref); if (open INF, "<$fil") { my %lnmap = (); my @lines = ; close INF; my $xlncnt = scalar @lines; @lines = svc_xml_to_lines(\%lnmap, \@lines); my $lncnt = scalar @lines; prt( "\nProcessing file [$fil], $lncnt lines ($xlncnt) ...\n" ); $new_ref = process_VC_lines( $fil, \@lines, \%lnmap ); } else { mydie( "ERROR: Unable to open $fil ... $! ... check name, location ...\n" ); } return $new_ref; } 1; # scanvc.pl